static void event_handle_client(Client *c, XEvent *e);
static void event_handle_menu(Menu *menu, XEvent *e);
+#define INVALID_FOCUSIN(e) ((e)->xfocus.detail == NotifyInferior || \
+ (e)->xfocus.detail > NotifyNonlinearVirtual)
+#define INVALID_FOCUSOUT(e) ((e)->xfocus.mode == NotifyGrab || \
+ (e)->xfocus.detail == NotifyInferior || \
+ (e)->xfocus.detail == NotifyAncestor || \
+ (e)->xfocus.detail > NotifyNonlinearVirtual)
+
Time event_lasttime = 0;
/*! The value of the mask for the NumLock modifier */
{
switch(e->type) {
case FocusIn:
-#ifdef DEBUG_FOCUS
- g_message("FocusIn on %lx mode %d detail %d", window,
- e->xfocus.mode, e->xfocus.detail);
-#endif
/* NotifyAncestor is not ignored in FocusIn like it is in FocusOut
because of RevertToPointerRoot. If the focus ends up reverting to
pointer root on a workspace change, then the FocusIn event that we
want will be of type NotifyAncestor. This situation does not occur
for FocusOut, so it is safely ignored there.
*/
- if (e->xfocus.detail == NotifyInferior ||
- e->xfocus.detail > NotifyNonlinearVirtual ||
+ if (INVALID_FOCUSIN(e) ||
client == NULL) {
+#ifdef DEBUG_FOCUS
+ g_message("FocusIn on %lx mode %d detail %d IGNORED", e->xfocus.window,
+ e->xfocus.mode, e->xfocus.detail);
+#endif
/* says a client was not found for the event (or a valid FocusIn
event was not found.
*/
}
#ifdef DEBUG_FOCUS
- g_message("FocusIn on %lx", window);
+ g_message("FocusIn on %lx mode %d detail %d", e->xfocus.window,
+ e->xfocus.mode, e->xfocus.detail);
#endif
break;
case FocusOut:
+ if (INVALID_FOCUSOUT(e)) {
#ifdef DEBUG_FOCUS
- g_message("FocusOut on %lx mode %d detail %d", window,
- e->xfocus.mode, e->xfocus.detail);
+ g_message("FocusOut on %lx mode %d detail %d IGNORED",
+ e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
#endif
- if (e->xfocus.mode == NotifyGrab ||
- e->xfocus.detail == NotifyInferior ||
- e->xfocus.detail == NotifyAncestor ||
- e->xfocus.detail > NotifyNonlinearVirtual) return TRUE;
-
+ return TRUE;
+ }
+
#ifdef DEBUG_FOCUS
- g_message("FocusOut on %lx", window);
+ g_message("FocusOut on %lx mode %d detail %d",
+ e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
#endif
+
/* Try process a FocusIn first, and if a legit one isn't found, then
do the fallback shiznit. */
{
- XEvent fi, fo;
- gboolean isfo = FALSE;
-
- if (XCheckTypedEvent(ob_display, FocusIn, &fi)) {
- event_process(&fi);
-
- /* when we have gotten a fi/fo pair, then see if there are any
- more fo's coming. if there are, then don't fallback just yet
- */
- if ((isfo = XCheckTypedEvent(ob_display, FocusOut, &fo)))
- XPutBackEvent(ob_display, &fo);
-
- /* secret magic way of event_process telling us that no client
- was found for the FocusIn event. ^_^ */
- if (!isfo && fi.xfocus.window == None)
- focus_fallback(Fallback_NoFocus);
- if (fi.xfocus.window == e->xfocus.window)
- return TRUE;
- } else
+ XEvent fe;
+ gboolean fallback = TRUE;
+
+ while (TRUE) {
+ if (!XCheckTypedEvent(ob_display, FocusOut, &fe))
+ if (!XCheckTypedEvent(ob_display, FocusIn, &fe))
+ break;
+ if (fe.type == FocusOut) {
+#ifdef DEBUG_FOCUS
+ g_message("found pending FocusOut");
+#endif
+ if (!INVALID_FOCUSOUT(&fe)) {
+ /* if there is a VALID FocusOut still coming, don't
+ fallback focus yet, we'll deal with it then */
+ XPutBackEvent(ob_display, &fe);
+ fallback = FALSE;
+ break;
+ }
+ } else {
+#ifdef DEBUG_FOCUS
+ g_message("found pending FocusIn");
+#endif
+ /* once all the FocusOut's have been dealt with, if there
+ is a FocusIn still left and it is valid, then use it */
+ event_process(&fe);
+ /* secret magic way of event_process telling us that no
+ client was found for the FocusIn event. ^_^ */
+ if (fe.xfocus.window != None) {
+ fallback = FALSE;
+ break;
+ }
+ }
+ }
+ if (fallback) {
+#ifdef DEBUG_FOCUS
+ g_message("no valid FocusIn and no FocusOut events found, "
+ "falling back");
+#endif
focus_fallback(Fallback_NoFocus);
+ }
}
break;
case EnterNotify:
/* NotifyVirtual occurs when ungrabbing the pointer */
if (e->xcrossing.mode == NotifyGrab ||
e->xcrossing.detail == NotifyInferior ||
- e->xcrossing.detail == NotifyVirtual)
+ (e->xcrossing.mode == NotifyUngrab &&
+ e->xcrossing.detail == NotifyVirtual)) {
+#ifdef DEBUG_FOCUS
+ g_message("%sNotify mode %d detail %d on %lx IGNORED",
+ (e->type == EnterNotify ? "Enter" : "Leave"),
+ e->xcrossing.mode,
+ e->xcrossing.detail, client?client->window:0);
+#endif
return TRUE;
+ }
+#ifdef DEBUG_FOCUS
+ g_message("%sNotify mode %d detail %d on %lx",
+ (e->type == EnterNotify ? "Enter" : "Leave"),
+ e->xcrossing.mode,
+ e->xcrossing.detail, client?client->window:0);
+#endif
break;
}
return FALSE;
e->type == ButtonPress ||
e->type == KeyPress || e->type == KeyRelease) {
moveresize_event(e);
+
return; /* no dispatch! */
+
}
/* user input (action-bound) events */
client_shade(client, FALSE);
client_focus(client);
stacking_raise(client);
- }
+ } else if (msgtype == prop_atoms.net_wm_moveresize) {
+ g_message("net_wm_moveresize for 0x%lx", client->window);
+ if ((Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_topleft ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_top ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_topright ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_right ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_right ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_bottomright ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_bottom ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_bottomleft ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_left ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_move ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_keyboard ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_move_keyboard) {
+
+ moveresize_start(client, e->xclient.data.l[0],
+ e->xclient.data.l[1], e->xclient.data.l[3],
+ e->xclient.data.l[2]);
+ }
+ } else if (msgtype == prop_atoms.net_moveresize_window) {
+ int oldg = client->gravity;
+ int tmpg, x, y, w, h;
+
+ if (e->xclient.data.l[0] & 0xff)
+ tmpg = e->xclient.data.l[0] & 0xff;
+ else
+ tmpg = oldg;
+
+ if (e->xclient.data.l[0] & 1 << 8)
+ x = e->xclient.data.l[1];
+ else
+ x = client->area.x;
+ if (e->xclient.data.l[0] & 1 << 9)
+ y = e->xclient.data.l[2];
+ else
+ y = client->area.y;
+ if (e->xclient.data.l[0] & 1 << 10)
+ w = e->xclient.data.l[3];
+ else
+ w = client->area.y;
+ if (e->xclient.data.l[0] & 1 << 11)
+ h = e->xclient.data.l[4];
+ else
+ h = client->area.y;
+ client->gravity = tmpg;
+ client_configure(client, Corner_TopLeft, x, y, w, h, TRUE, TRUE);
+ client->gravity = oldg;
+ }
break;
case PropertyNotify:
/* validate cuz we query stuff off the client here */