diff --git a/plugins/plane.c b/plugins/plane.c index 7c9a03c..2a7c7e6 100644 --- a/plugins/plane.c +++ b/plugins/plane.c @@ -364,38 +364,14 @@ static void planeHandleEvent (CompDisplay *d, XEvent *event) { + Window activeWindow = d->activeWindow; CompScreen *s; PLANE_DISPLAY (d); switch (event->type) { case ClientMessage: - if (event->xclient.message_type == d->winActiveAtom) - { - CompWindow *w; - - w = findWindowAtDisplay (d, event->xclient.window); - if (w) - { - int dx, dy; - - s = w->screen; - - /* window must be placed */ - if (!w->placed) - break; - - if (otherScreenGrabExist (s, "plane", "switcher", "cube", 0)) - break; - - defaultViewportForWindow (w, &dx, &dy); - dx -= s->x; - dy -= s->y; - - moveViewport (s, dx, dy); - } - } - else if (event->xclient.message_type == d->desktopViewportAtom) + if (event->xclient.message_type == d->desktopViewportAtom) { int dx, dy; @@ -423,6 +399,26 @@ planeHandleEvent (CompDisplay *d, UNWRAP (pd, d, handleEvent); (*d->handleEvent) (d, event); WRAP (pd, d, handleEvent, planeHandleEvent); + + if (activeWindow != d->activeWindow) + { + CompWindow *w; + + w = findWindowAtDisplay (d, d->activeWindow); + if (w && w->placed && + !otherScreenGrabExist (w->screen, "plane", "switcher", "cube", 0)) + { + int dx, dy; + + s = w->screen; + + defaultViewportForWindow (w, &dx, &dy); + dx -= s->x; + dy -= s->y; + + moveViewport (s, dx, dy); + } + } } static void diff --git a/plugins/rotate.c b/plugins/rotate.c index 05eb363..7b5ee20 100644 --- a/plugins/rotate.c +++ b/plugins/rotate.c @@ -1435,6 +1435,7 @@ rotateHandleEvent (CompDisplay *d, XEvent *event) { CompScreen *s; + Window activeWindow = d->activeWindow; ROTATE_DISPLAY (d); @@ -1483,22 +1484,14 @@ rotateHandleEvent (CompDisplay *d, } break; case ClientMessage: - if (event->xclient.message_type == d->winActiveAtom) + if (event->xclient.message_type == d->desktopViewportAtom) { - CompWindow *w; - - w = findWindowAtDisplay (d, event->xclient.window); - if (w) + s = findScreenAtDisplay (d, event->xclient.window); + if (s) { int dx; - ROTATE_SCREEN (w->screen); - - s = w->screen; - - /* window must be placed */ - if (!w->placed) - break; + ROTATE_SCREEN (s); if (otherScreenGrabExist (s, "rotate", "switcher", "cube", 0)) break; @@ -1506,8 +1499,7 @@ rotateHandleEvent (CompDisplay *d, /* reset movement */ rs->moveTo = 0.0f; - defaultViewportForWindow (w, &dx, NULL); - dx -= s->x; + dx = event->xclient.data.l[0] / s->width - s->x; if (dx) { Window win; @@ -1543,64 +1535,68 @@ rotateHandleEvent (CompDisplay *d, } } } - else if (event->xclient.message_type == d->desktopViewportAtom) + default: + break; + } + + UNWRAP (rd, d, handleEvent); + (*d->handleEvent) (d, event); + WRAP (rd, d, handleEvent, rotateHandleEvent); + + if (activeWindow != d->activeWindow) + { + CompWindow *w; + + w = findWindowAtDisplay (d, d->activeWindow); + if (w && w->placed && + !otherScreenGrabExist (w->screen, "rotate", "switcher", "cube", 0)) { - s = findScreenAtDisplay (d, event->xclient.window); - if (s) - { - int dx; + int dx; - ROTATE_SCREEN (s); + ROTATE_SCREEN (w->screen); - if (otherScreenGrabExist (s, "rotate", "switcher", "cube", 0)) - break; + s = w->screen; - /* reset movement */ - rs->moveTo = 0.0f; + /* reset movement */ + rs->moveTo = 0.0f; - dx = event->xclient.data.l[0] / s->width - s->x; - if (dx) - { - Window win; - int i, x, y; - unsigned int ui; - CompOption o[4]; + defaultViewportForWindow (w, &dx, NULL); + dx -= s->x; + if (dx) + { + Window win; + int i, x, y; + unsigned int ui; + CompOption o[4]; - XQueryPointer (d->display, s->root, - &win, &win, &x, &y, &i, &i, &ui); + XQueryPointer (d->display, s->root, + &win, &win, &x, &y, &i, &i, &ui); - if (dx > (s->hsize + 1) / 2) - dx -= s->hsize; - else if (dx < -(s->hsize + 1) / 2) - dx += s->hsize; + if (dx > (s->hsize + 1) / 2) + dx -= s->hsize; + else if (dx < -(s->hsize + 1) / 2) + dx += s->hsize; - o[0].type = CompOptionTypeInt; - o[0].name = "x"; - o[0].value.i = x; + o[0].type = CompOptionTypeInt; + o[0].name = "x"; + o[0].value.i = x; - o[1].type = CompOptionTypeInt; - o[1].name = "y"; - o[1].value.i = y; + o[1].type = CompOptionTypeInt; + o[1].name = "y"; + o[1].value.i = y; - o[2].type = CompOptionTypeInt; - o[2].name = "root"; - o[2].value.i = s->root; + o[2].type = CompOptionTypeInt; + o[2].name = "root"; + o[2].value.i = s->root; - o[3].type = CompOptionTypeInt; - o[3].name = "direction"; - o[3].value.i = dx; + o[3].type = CompOptionTypeInt; + o[3].name = "direction"; + o[3].value.i = dx; - rotate (d, NULL, 0, o, 4); - } + rotate (d, NULL, 0, o, 4); } } - default: - break; } - - UNWRAP (rd, d, handleEvent); - (*d->handleEvent) (d, event); - WRAP (rd, d, handleEvent, rotateHandleEvent); } static void diff --git a/src/window.c b/src/window.c index b3c0edd..3943101 100644 --- a/src/window.c +++ b/src/window.c @@ -4557,6 +4557,95 @@ setWindowUserTime (CompWindow *w, (time2) != 0) \ ) +static Bool +isWindowFocusAllowed (CompWindow *w, + Time timestamp) +{ + CompDisplay *d = w->screen->display; + CompScreen *s = w->screen; + CompWindow *active; + Time wUserTime, aUserTime; + CompMatch *match; + int vx, vy; + + if (w->id == d->activeWindow) + return TRUE; + + /* not in current viewport */ + defaultViewportForWindow (w, &vx, &vy); + if (vx != s->x || vy != s->y) + return FALSE; + + if (timestamp) + { + /* the caller passed a timestamp, so use that + instead of the window's user time */ + wUserTime = timestamp; + } + else + { + if (!getWindowUserTime (w, &wUserTime)) + { + /* no user time or initial timestamp */ + if (!w->initialTimestampSet) + return TRUE; + + wUserTime = w->initialTimestamp; + } + + /* window explicitly requested no focus */ + if (!wUserTime) + return FALSE; + } + + /* can't get user time for active window */ + active = findWindowAtDisplay (d, d->activeWindow); + if (!active || !getWindowUserTime (active, &aUserTime)) + return TRUE; + + match = &s->opt[COMP_SCREEN_OPTION_FOCUS_PREVENTION_MATCH].value.match; + + /* focus prevention */ + if (matchEval (match, w)) + { + if (XSERVER_TIME_IS_BEFORE (wUserTime, aUserTime)) + return FALSE; + } + + return TRUE; +} + +Bool +allowWindowFocus (CompWindow *w, + unsigned int noFocusMask, + Time timestamp) +{ + Bool retval; + + /* do not focus windows of these types */ + if (w->type & noFocusMask) + return FALSE; + + /* window doesn't take focus */ + if (!w->inputHint && !(w->protocols & CompWindowProtocolTakeFocusMask)) + return FALSE; + + retval = isWindowFocusAllowed (w, timestamp); + + if (!retval) + { + /* add demands attention state if focus was prevented */ + unsigned int state = w->state; + + state |= CompWindowStateDemandsAttentionMask; + if (state != w->state) + changeWindowState (w, state); + } + + return retval; +} + + Bool allowWindowFocus (CompWindow *w, unsigned int noFocusMask,