summaryrefslogtreecommitdiff
path: root/openbox/event.c
diff options
context:
space:
mode:
authorDana Jansens <danakj@orodu.net>2003-09-15 10:54:07 +0000
committerDana Jansens <danakj@orodu.net>2003-09-15 10:54:07 +0000
commit4ccc4c5ed7d5cffc4bf733191f7bc30fbbf069c8 (patch)
treec576a940be5853ac5ec9bde841f797d63e78061c /openbox/event.c
parent17676168255fcf5cbec9ea5dadcee546c5ab7bbb (diff)
break focus. or maybe make it better.
these changes make it work when you alt-tab off a fullscreen window, that it doesnt iconify, and that it is immediately restacked instead of waiting for a FocusIn event to arrive. The code now assumes that if the window says it can focus, that if we focus it, it is focused. add the XDone handler to ObMainLoop, which is fired upon the occurance of there being no more X events to read.
Diffstat (limited to 'openbox/event.c')
-rw-r--r--openbox/event.c154
1 files changed, 48 insertions, 106 deletions
diff --git a/openbox/event.c b/openbox/event.c
index 483050fa..68d51135 100644
--- a/openbox/event.c
+++ b/openbox/event.c
@@ -42,6 +42,7 @@ typedef struct
} ObEventData;
static void event_process(const XEvent *e, gpointer data);
+static void event_done(gpointer data);
static void event_handle_root(XEvent *e);
static void event_handle_menu(XEvent *e);
static void event_handle_dock(ObDock *s, XEvent *e);
@@ -132,7 +133,7 @@ void event_startup(gboolean reconfig)
}
}
- ob_main_loop_x_add(ob_main_loop, event_process, NULL, NULL);
+ ob_main_loop_x_add(ob_main_loop, event_process, event_done, NULL, NULL);
#ifdef USE_SM
IceAddConnectionWatch(ice_watch, NULL);
@@ -283,24 +284,32 @@ static void event_hack_mods(XEvent *e)
static gboolean event_ignore(XEvent *e, ObClient *client)
{
+ gboolean ignore = FALSE;
+ XEvent ce;
+
switch(e->type) {
case FocusIn:
+ while (XCheckTypedWindowEvent(ob_display, e->xfocus.window,
+ FocusIn, &ce))
+ {
+ if (!INVALID_FOCUSIN(&ce)) {
+ XPutBackEvent(ob_display, &ce);
+ ignore = TRUE;
+ break;
+ }
+ }
+
/* 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 (INVALID_FOCUSIN(e) ||
- client == NULL) {
+ if (ignore || INVALID_FOCUSIN(e) || client == NULL) {
#ifdef DEBUG_FOCUS
ob_debug("FocusIn on %lx mode %d detail %d IGNORED\n",
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.
- */
- e->xfocus.window = None;
return TRUE;
}
@@ -310,10 +319,20 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
#endif
break;
case FocusOut:
- if (INVALID_FOCUSOUT(e)) {
+ while (XCheckTypedWindowEvent(ob_display, e->xfocus.window,
+ FocusOut, &ce))
+ {
+ if (!INVALID_FOCUSOUT(&ce)) {
+ XPutBackEvent(ob_display, &ce);
+ ignore = TRUE;
+ break;
+ }
+ }
+
+ if (ignore || INVALID_FOCUSOUT(e)) {
#ifdef DEBUG_FOCUS
- ob_debug("FocusOut on %lx mode %d detail %d IGNORED\n",
- e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
+ ob_debug("FocusOut on %lx mode %d detail %d IGNORED\n",
+ e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
#endif
return TRUE;
}
@@ -322,84 +341,6 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
ob_debug("FocusOut on %lx mode %d detail %d\n",
e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
#endif
-
- {
- XEvent fe;
- gboolean fallback = TRUE;
-
- while (TRUE) {
- if (!XCheckTypedWindowEvent(ob_display, e->xfocus.window,
- FocusOut, &fe))
- if (!XCheckTypedEvent(ob_display, FocusIn, &fe))
- break;
- if (fe.type == FocusOut) {
-#ifdef DEBUG_FOCUS
- ob_debug("found pending FocusOut\n");
-#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
- ob_debug("found pending FocusIn\n");
-#endif
- /* is the focused window getting a FocusOut/In back to
- itself?
- */
- if (fe.xfocus.window == e->xfocus.window &&
- !event_ignore(&fe, client)) {
- /*
- if focus_client is not set, then we can't do
- this. we need the FocusIn. This happens in the
- case when the set_focus_client(NULL) in the
- focus_fallback function fires and then
- focus_fallback picks the currently focused
- window (such as on a SendToDesktop-esque action.
- */
- if (focus_client) {
-#ifdef DEBUG_FOCUS
- ob_debug("focused window got an Out/In back to "
- "itself IGNORED both\n");
-#endif
- return TRUE;
- } else {
- event_process(&fe, NULL);
-#ifdef DEBUG_FOCUS
- ob_debug("focused window got an Out/In back to "
- "itself but focus_client was null "
- "IGNORED just the Out\n");
-#endif
- return TRUE;
- }
- }
-
- {
- ObEventData d;
-
- /* 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, &d);
- if (!d.ignored) {
- ob_debug("FocusIn was OK, so don't fallback\n");
- fallback = FALSE;
- break;
- }
- }
- }
- }
- if (fallback) {
-#ifdef DEBUG_FOCUS
- ob_debug("no valid FocusIn and no FocusOut events found, "
- "falling back\n");
-#endif
- focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS);
- }
- }
break;
case EnterNotify:
case LeaveNotify:
@@ -413,7 +354,7 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
(e->xcrossing.detail == NotifyAncestor ||
e->xcrossing.detail == NotifyNonlinearVirtual ||
e->xcrossing.detail == NotifyVirtual))) {
-#ifdef DEBUG_FOCUS
+#ifdef aDEBUG_FOCUS
ob_debug("%sNotify mode %d detail %d on %lx IGNORED\n",
(e->type == EnterNotify ? "Enter" : "Leave"),
e->xcrossing.mode,
@@ -421,7 +362,7 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
#endif
return TRUE;
}
-#ifdef DEBUG_FOCUS
+#ifdef aDEBUG_FOCUS
ob_debug("%sNotify mode %d detail %d on %lx\n",
(e->type == EnterNotify ? "Enter" : "Leave"),
e->xcrossing.mode,
@@ -545,6 +486,12 @@ static void event_process(const XEvent *ec, gpointer data)
}
}
+static void event_done(gpointer data)
+{
+ if (!focus_client)
+ focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS);
+}
+
static void event_handle_root(XEvent *e)
{
Atom msgtype;
@@ -650,27 +597,22 @@ static void event_handle_client(ObClient *client, XEvent *e)
break;
case FocusIn:
#ifdef DEBUG_FOCUS
- ob_debug("FocusIn on client for %lx\n", client->window);
+ ob_debug("Focus%s on client for %lx\n", (e->type==FocusIn?"In":"Out"),
+ client->window);
#endif
- if (client != focus_client) {
+ if (client != focus_client)
focus_set_client(client);
- frame_adjust_focus(client->frame, TRUE);
- }
+ frame_adjust_focus(client->frame, e->type == FocusIn);
break;
case FocusOut:
#ifdef DEBUG_FOCUS
- ob_debug("FocusOut on client for %lx\n", client->window);
+ ob_debug("Focus%s on client for %lx\n", (e->type==FocusIn?"In":"Out"),
+ client->window);
#endif
- /* are we a fullscreen window or a transient of one? (checks layer)
- if we are then we need to be iconified since we are losing focus
- */
- if (client->layer == OB_STACKING_LAYER_FULLSCREEN && !client->iconic &&
- !client_search_focus_tree_full(client))
- /* iconify fullscreen windows when they and their transients
- aren't focused */
- client_iconify(client, TRUE, TRUE);
- frame_adjust_focus(client->frame, FALSE);
- break;
+ if (client == focus_client)
+ focus_client = NULL;
+ frame_adjust_focus(client->frame, e->type == FocusIn);
+ break;
case LeaveNotify:
con = frame_context(client, e->xcrossing.window);
switch (con) {
@@ -733,7 +675,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
case OB_FRAME_CONTEXT_FRAME:
if (client_normal(client)) {
if (config_focus_follow) {
-#ifdef DEBUG_FOCUS
+#ifdef aDEBUG_FOCUS
ob_debug("EnterNotify on %lx, focusing window\n",
client->window);
#endif