/* Checks if w is a ipw and returns the real window */ static CompWindow * FWGetRealWindow (CompWindow *w) { FWWindowInputInfo *info; int count = 0; FREEWINS_SCREEN (w->screen); for (info = fws->transformedWindows; info; info = info->next) { count++; fprintf(stderr, "Counted %i transformed windows\n", count); if (w->id == info->ipw) return info->w; } return NULL; } static CompWindow * FWGetRealWindowFromID (CompDisplay *d, Window wid) { CompWindow *orig, *w; CompScreen *s; orig = findWindowAtDisplay (d, wid); for (s = d->screens; s; s = s->next) for (w = s->windows; w; w = w->next) if (wid == w->id) orig = w; if (!orig) { fprintf(stderr, "Cannot get a compWindow for this window\n"); return NULL; } return FWGetRealWindow (orig); } /* ------ Input Prevention -------------------------------------------*/ static void FWSaveInputShape (CompWindow *w, XRectangle **retRects, int *retCount, int *retOrdering) { XRectangle *rects; int count = 0, ordering; Display *dpy = w->screen->display->display; rects = XShapeGetRectangles (dpy, w->id, ShapeInput, &count, &ordering); /* check if the returned shape exactly matches the window shape - if that is true, the window currently has no set input shape */ if ((count == 1) && (rects[0].x == -w->serverBorderWidth) && (rects[0].y == -w->serverBorderWidth) && (rects[0].width == (w->serverWidth + w->serverBorderWidth)) && (rects[0].height == (w->serverHeight + w->serverBorderWidth))) { count = 0; } *retRects = rects; *retCount = count; *retOrdering = ordering; } static void FWUnshapeInput (CompWindow *w) { Display *dpy = w->screen->display->display; FREEWINS_WINDOW (w); if (fww->input->nInputRects) { XShapeCombineRectangles (dpy, w->id, ShapeInput, 0, 0, fww->input->inputRects, fww->input->nInputRects, ShapeSet, fww->input->inputRectOrdering); } else { XShapeCombineMask (dpy, w->id, ShapeInput, 0, 0, None, ShapeSet); } if (fww->input->frameNInputRects >= 0) { if (fww->input->frameInputRects) { XShapeCombineRectangles (dpy, w->frame, ShapeInput, 0, 0, fww->input->frameInputRects, fww->input->frameNInputRects, ShapeSet, fww->input->frameInputRectOrdering); } else { XShapeCombineMask (dpy, w->frame, ShapeInput, 0, 0, None, ShapeSet); } } } /* Input Shaper. This no longer adjusts the shape of the window but instead shapes it to 0 as the IPW deals with the input. Old code is available commented, but will be removed as soon as input prevention becomes stable enough */ static void FWShapeInput (CompWindow *w) { CompWindow *fw; Display *dpy = w->screen->display->display; FREEWINS_WINDOW (w); /* save old shape */ FWSaveInputShape (w, &fww->input->inputRects, &fww->input->nInputRects, &fww->input->inputRectOrdering); fw = findWindowAtDisplay (w->screen->display, w->frame); if (fw) { FWSaveInputShape(fw, &fww->input->frameInputRects, &fww->input->frameNInputRects, &fww->input->frameInputRectOrdering); } else { fww->input->frameInputRects = NULL; fww->input->frameNInputRects = -1; fww->input->frameInputRectOrdering = 0; } /* clear shape */ XShapeSelectInput (dpy, w->id, NoEventMask); XShapeCombineRectangles (dpy, w->id, ShapeInput, 0, 0, NULL, 0, ShapeSet, 0); if (w->frame) XShapeCombineRectangles (dpy, w->frame, ShapeInput, 0, 0, NULL, 0, ShapeSet, 0); XShapeSelectInput (dpy, w->id, ShapeNotify); } /* Add the input info to the list of input info */ static void FWAddWindowToList (FWWindowInputInfo *info) { CompScreen *s = info->w->screen; FWWindowInputInfo *run; FREEWINS_SCREEN (s); run = fws->transformedWindows; if (!run) fws->transformedWindows = info; else { for (; run->next; run = run->next) run->next = info; } } /* Remove the input info from the list of input info */ static void FWRemoveWindowFromList (FWWindowInputInfo *info) { CompScreen *s = info->w->screen; FWWindowInputInfo *run; FREEWINS_SCREEN (s); if (!fws->transformedWindows) return; if (fws->transformedWindows == info) fws->transformedWindows = info->next; else { for (run = fws->transformedWindows; run->next; run = run->next) { if (run->next == info) { run->next = info->next; break; } } } } /* Adjust size and location of the input prevention window */ static void FWAdjustIPW (CompWindow *w) { XWindowChanges xwc; Display *dpy = w->screen->display->display; float width, height; FREEWINS_WINDOW (w); if (!fww->input || !fww->input->ipw) return; width = fww->inputRect.x2 - fww->inputRect.x1; height = fww->inputRect.y2 - fww->inputRect.y1; fprintf(stderr, "ipw X %i Y %i W %f H %f\n", fww->inputRect.x1, fww->inputRect.y1, width, height); xwc.x = (fww->inputRect.x1); xwc.y = (fww->inputRect.y1); xwc.width = ceil(width); xwc.height = ceil(height); xwc.stack_mode = Below; xwc.sibling = w->id; XConfigureWindow (dpy, fww->input->ipw, CWSibling | CWStackMode | CWX | CWY | CWWidth | CWHeight, &xwc); XMapWindow (dpy, fww->input->ipw); } /* Create an input prevention window */ static void FWCreateIPW (CompWindow *w) { Window ipw; XSetWindowAttributes attrib; FREEWINS_WINDOW (w); if (!fww->input || fww->input->ipw) return; attrib.override_redirect = TRUE; attrib.event_mask = 0; ipw = XCreateWindow (w->screen->display->display, w->screen->root, w->serverX - w->input.left, w->serverY - w->input.top, w->serverWidth + w->input.left + w->input.right, w->serverHeight + w->input.top + w->input.bottom, 0, CopyFromParent, InputOnly, CopyFromParent, CWEventMask | CWOverrideRedirect, &attrib); fww->input->ipw = ipw; FWAdjustIPW (w); if (ipw) fprintf(stderr, "success in creating IPW with ID of %i", ipw); } /* Ensure that the input prevention window * is always on top of the transformed * window */ static void FWAdjustIPWStacking (CompScreen *s) { FWWindowInputInfo *input; FREEWINS_SCREEN (s); for (input = fws->transformedWindows; input; input = input->next) { if (!input->w->prev || input->w->prev->id != input->ipw) FWAdjustIPW (input->w); } } static void FWHandleIPWResizeInitiate (CompWindow *w) { FREEWINS_SCREEN (w->screen); FREEWINS_DISPLAY (w->screen->display); (*w->screen->activateWindow) (w); fwd->grab = grabResize; fws->rotateCursor = XCreateFontCursor (w->screen->display->display, XC_plus); if(!otherScreenGrabExist(w->screen, "freewins", "resize", 0)) if(!fws->grabIndex) { unsigned int mods = 0; mods &= CompNoMask; fws->grabIndex = pushScreenGrab(w->screen, fws->rotateCursor, "resize"); (w->screen->windowGrabNotify) (w, w->attrib.x + (w->width / 2), w->attrib.y + (w->height / 2), mods, CompWindowGrabMoveMask | CompWindowGrabButtonMask); fwd->grabWindow = w; } } static void FWHandleIPWMoveInitiate (CompWindow *w) { FREEWINS_SCREEN (w->screen); FREEWINS_DISPLAY (w->screen->display); (*w->screen->activateWindow) (w); fwd->grab = grabMove; fws->rotateCursor = XCreateFontCursor (w->screen->display->display, XC_fleur); if(!otherScreenGrabExist(w->screen, "freewins", "move", 0)) if(!fws->grabIndex) { unsigned int mods = 0; mods &= CompNoMask; fws->grabIndex = pushScreenGrab(w->screen, fws->rotateCursor, "move"); (w->screen->windowGrabNotify) (w, w->attrib.x + (w->width / 2), w->attrib.y + (w->height / 2), mods, CompWindowGrabMoveMask | CompWindowGrabButtonMask); } fwd->grabWindow = w; } static void FWHandleIPWMoveMotionEvent (CompWindow *w, unsigned int x, unsigned int y) { FREEWINS_SCREEN (w->screen); //static int oldPointerX, oldPointerY; int dx = x - lastPointerX; int dy = y - lastPointerY; if (!fws->grabIndex) return; moveWindow(w, dx, dy, TRUE, FALSE); syncWindowPosition (w); } static void FWHandleIPWResizeMotionEvent (CompWindow *w, unsigned int x, unsigned int y) { FREEWINS_WINDOW (w); int dx = (x - lastPointerX) * 10; int dy = (y - lastPointerY) * 10; fww->winH += dx; fww->winW += dy; /* In order to prevent a window redraw on resize * on every motion event we have a threshold */ if (fww->winH - 10 > w->height || fww->winW - 10 > w->width) { XWindowChanges xwc; unsigned int mask = CWX | CWY | CWWidth | CWHeight; xwc.x = w->serverX; xwc.y = w->serverX; xwc.width = fww->winW; xwc.height = fww->winH; if (xwc.width == w->serverWidth) mask &= ~CWWidth; if (xwc.height == w->serverHeight) mask &= ~CWHeight; if (w->mapNum && (mask & (CWWidth | CWHeight))) sendSyncRequest (w); configureXWindow (w, mask, &xwc); } }