static Bool scaleaddonPullWindow(CompDisplay * d, CompAction * action, CompActionState state, CompOption * option, int nOption) { CompScreen *s; Window xid; xid = getIntOptionNamed(option, nOption, "root", 0); s = findScreenAtDisplay(d, xid); if (s) { CompWindow *w; SCALE_SCREEN(s); ADDON_DISPLAY(d); if (!ss->grabIndex) return FALSE; w = findWindowAtDisplay(d, ad->highlightedWindow); if (w) { int x, y, vx, vy; defaultViewportForWindow(w, &vx, &vy); x = w->attrib.x + (s->x - vx) * s->width; y = w->attrib.y + (s->y - vy) * s->height; if (scaleaddonGetConstrainPullToScreen(s)) { XRectangle workArea; CompWindowExtents extents; getWorkareaForOutput(s, outputDeviceForWindow(w), &workArea); extents.left = x - w->input.left; extents.right = x + w->width + w->input.right; extents.top = y - w->input.top; extents.bottom = y + w->height + w->input.bottom; if (extents.left < workArea.x) x += workArea.x - extents.left; else if (extents.right > workArea.x + workArea.width) x += workArea.x + workArea.width - extents.right; if (extents.top < workArea.y) y += workArea.y - extents.top; else if (extents.bottom > workArea.y + workArea.height) y += workArea.y + workArea.height - extents.bottom; } if (x != w->attrib.x || y != w->attrib.y) { SCALE_WINDOW(w); moveWindowToViewportPosition(w, x, y, TRUE); /* Select this window when ending scale */ (*ss->selectWindow) (w); /* stop scaled window dissapearing */ sw->tx -= (s->x - vx) * s->width; sw->ty -= (s->y - vy) * s->height; if (scaleaddonGetExitAfterPull(s)) { int opt; CompAction *action2; CompOption o[1]; SCALE_DISPLAY(d); opt = SCALE_DISPLAY_OPTION_INITIATE_KEY; action2 = &sd->opt[opt].value.action; o[0].type = CompOptionTypeInt; o[0].name = "root"; o[0].value.i = s->root; if (action2->terminate) (*action2->terminate) (d, action, 0, o, 1); } else { /* provide a simple animation */ addWindowDamage(w); sw->tx -= (sw->slot->x2 - sw->slot->x1) / 20; sw->ty -= (sw->slot->y2 - sw->slot->y1) / 20; sw->scale *= 1.1f; sw->adjust = TRUE; ss->state = SCALE_STATE_OUT; addWindowDamage(w); } return TRUE; } } } return FALSE; }
/* X Event Handler */ void FWHandleEvent(CompDisplay *d, XEvent *ev){ float dx, dy; CompWindow *oldPrev, *oldNext, *w; FREEWINS_DISPLAY(d); /* Check our modifiers first */ if (ev->type == d->xkbEvent) { XkbAnyEvent *xkbEvent = (XkbAnyEvent *) ev; if (xkbEvent->xkb_type == XkbStateNotify) { XkbStateNotifyEvent *stateEvent = (XkbStateNotifyEvent *) ev; unsigned int snapMods = 0xffffffff; unsigned int invertMods = 0xffffffff; if (fwd->snapMask) snapMods = fwd->snapMask; if ((stateEvent->mods & snapMods) == snapMods) fwd->snap = TRUE; else fwd->snap = FALSE; if (fwd->invertMask) invertMods = fwd->invertMask; if ((stateEvent->mods & invertMods) == invertMods) fwd->invert = TRUE; else fwd->invert = FALSE; } } switch(ev->type){ case EnterNotify: { CompWindow *btnW; btnW = findWindowAtDisplay (d, ev->xbutton.subwindow); /* It wasn't the subwindow, try the window */ if (!btnW) btnW = findWindowAtDisplay (d, ev->xbutton.window); /* We have established the CompWindow we clicked * on. Get the real window */ if (btnW) { if (FWCanShape (btnW) && !fwd->grabWindow && !otherScreenGrabExist(btnW->screen, 0)) fwd->hoverWindow = btnW; btnW = FWGetRealWindow (btnW); } if (btnW) { if (FWCanShape (btnW) && !fwd->grabWindow && !otherScreenGrabExist(btnW->screen, 0)) fwd->hoverWindow = btnW; FWHandleEnterNotify (btnW, ev); } } break; case LeaveNotify: { CompWindow *btnW; btnW = findWindowAtDisplay (d, ev->xbutton.subwindow); /* It wasn't the subwindow, try the window */ if (!btnW) btnW = findWindowAtDisplay (d, ev->xbutton.window); /* We have established the CompWindow we clicked * on. Get the real window */ if (btnW) btnW = FWGetRealWindow (btnW); if (btnW) FWHandleLeaveNotify (btnW, ev); } break; case MotionNotify: if(fwd->grabWindow) { FREEWINS_WINDOW(fwd->grabWindow); dx = ((float)(pointerX - lastPointerX) / fwd->grabWindow->screen->width) * \ freewinsGetMouseSensitivity (fwd->grabWindow->screen); dy = ((float)(pointerY - lastPointerY) / fwd->grabWindow->screen->height) * \ freewinsGetMouseSensitivity (fwd->grabWindow->screen); if (matchEval (freewinsGetShapeWindowTypes (fwd->grabWindow->screen), fwd->grabWindow)) { if (fww->grab == grabMove || fww->grab == grabResize) { FREEWINS_SCREEN (fwd->grabWindow->screen); FWWindowInputInfo *info; CompWindow *w = fwd->grabWindow; for (info = fws->transformedWindows; info; info = info->next) { if (fwd->grabWindow->id == info->ipw) /* The window we just grabbed was actually * an IPW, get the real window instead */ w = FWGetRealWindow (fwd->grabWindow); } switch (fww->grab) { case grabMove: FWHandleIPWMoveMotionEvent (w, pointerX, pointerY); break; case grabResize: FWHandleIPWResizeMotionEvent (w, pointerX, pointerY); break; default: break; } } } if (fww->grab == grabRotate) { FWHandleRotateMotionEvent(fwd->grabWindow, dx, dy, ev->xmotion.x, ev->xmotion.y); } if (fww->grab == grabScale) { FWHandleScaleMotionEvent(fwd->grabWindow, dx * 3, dy * 3, ev->xmotion.x, ev->xmotion.y); } if(dx != 0.0 || dy != 0.0) FWDamageArea (fwd->grabWindow); } break; /* Button Press and Release */ case ButtonPress: { CompWindow *btnW; btnW = findWindowAtDisplay (d, ev->xbutton.subwindow); /* It wasn't the subwindow, try the window */ if (!btnW) btnW = findWindowAtDisplay (d, ev->xbutton.window); /* We have established the CompWindow we clicked * on. Get the real window * FIXME: Free btnW and use another CompWindow * such as realW */ if (btnW) btnW = FWGetRealWindow (btnW); if (btnW) { if (matchEval (freewinsGetShapeWindowTypes (btnW->screen), btnW)) switch (ev->xbutton.button) { case Button1: FWHandleIPWMoveInitiate (btnW); break; case Button3: FWHandleIPWResizeInitiate (btnW); break; default: break; } } fwd->click_root_x = ev->xbutton.x_root; fwd->click_root_y = ev->xbutton.y_root; } break; case ButtonRelease: { if (fwd->grabWindow) { FREEWINS_WINDOW (fwd->grabWindow); if (matchEval (freewinsGetShapeWindowTypes (fwd->grabWindow->screen), fwd->grabWindow)) if (fww->grab == grabMove || fww->grab == grabResize) { FWHandleButtonReleaseEvent (fwd->grabWindow); fwd->grabWindow = 0; } } } break; case ConfigureNotify: w = findWindowAtDisplay (d, ev->xconfigure.window); if (w) { oldPrev = w->prev; oldNext = w->next; FREEWINS_WINDOW (w); fww->winH = WIN_REAL_H (w); fww->winW = WIN_REAL_W (w); } break; case ClientMessage: if (ev->xclient.message_type == d->desktopViewportAtom) { /* Viewport change occurred, or something like that - adjust the IPW's */ CompScreen *s; CompWindow *adjW, *actualW; for (s = d->screens; s; s = s->next) for (adjW = s->windows; adjW; adjW = adjW->next) { int vX = 0, vY = 0, dX, dY; actualW = FWGetRealWindow (adjW); if (!actualW) actualW = adjW; if (actualW) { CompWindow *ipw; FREEWINS_WINDOW (actualW); if (!fww->input || fww->input->ipw) break; ipw = findWindowAtDisplay (d, fww->input->ipw); if (ipw) { dX = s->x - vX; dY = s->y - vY; defaultViewportForWindow (actualW, &vX, &vY); moveWindowToViewportPosition (ipw, ipw->attrib.x - dX * s->width, ipw->attrib.y - dY * s->height, FALSE); } } } } break; default: if (ev->type == d->shapeEvent + ShapeNotify) { XShapeEvent *se = (XShapeEvent *) ev; if (se->kind == ShapeInput) { CompWindow *w; w = findWindowAtDisplay (d, se->window); if (w) { FREEWINS_WINDOW (w); if (FWCanShape (w) && (fww->transform.scaleX != 1.0f || fww->transform.scaleY != 1.0f)) { // Reset the window back to normal fww->transform.scaleX = 1.0f; fww->transform.scaleY = 1.0f; fww->transform.angX = 0.0f; fww->transform.angY = 0.0f; fww->transform.angZ = 0.0f; /*FWShapeInput (w); - Disabled due to problems it causes*/ } } } } } UNWRAP(fwd, d, handleEvent); (*d->handleEvent)(d, ev); WRAP(fwd, d, handleEvent, FWHandleEvent); /* Now we can find out if a restacking occurred while we were handing events */ switch (ev->type) { case ConfigureNotify: if (w) /* already assigned above */ { if (w->prev != oldPrev || w->next != oldNext) { /* restacking occured, ensure ipw stacking */ FWAdjustIPWStacking (w->screen); FWAdjustIPW (w); } } break; } }