eat enter events after unmanaging a window
change how focus falls back for windows being unmanaged, don't fall back immediately, instead wait for the focus out event and use it (break stuff maybe! yay)
This commit is contained in:
parent
63f1b1230c
commit
a70633d42a
2 changed files with 61 additions and 83 deletions
|
@ -77,7 +77,6 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y);
|
||||||
static void client_restore_session_state(ObClient *self);
|
static void client_restore_session_state(ObClient *self);
|
||||||
static void client_restore_session_stacking(ObClient *self);
|
static void client_restore_session_stacking(ObClient *self);
|
||||||
static ObAppSettings *client_get_settings_state(ObClient *self);
|
static ObAppSettings *client_get_settings_state(ObClient *self);
|
||||||
static void client_unfocus(ObClient *self);
|
|
||||||
|
|
||||||
void client_startup(gboolean reconfig)
|
void client_startup(gboolean reconfig)
|
||||||
{
|
{
|
||||||
|
@ -507,8 +506,8 @@ void client_unmanage(ObClient *self)
|
||||||
|
|
||||||
g_assert(self != NULL);
|
g_assert(self != NULL);
|
||||||
|
|
||||||
/* update the focus lists */
|
frame_hide(self->frame);
|
||||||
focus_order_remove(self);
|
XSync(ob_display, FALSE);
|
||||||
|
|
||||||
if (focus_client == self) {
|
if (focus_client == self) {
|
||||||
XEvent e;
|
XEvent e;
|
||||||
|
@ -516,20 +515,8 @@ void client_unmanage(ObClient *self)
|
||||||
/* focus the last focused window on the desktop, and ignore enter
|
/* focus the last focused window on the desktop, and ignore enter
|
||||||
events from the unmap so it doesnt mess with the focus */
|
events from the unmap so it doesnt mess with the focus */
|
||||||
while (XCheckTypedEvent(ob_display, EnterNotify, &e));
|
while (XCheckTypedEvent(ob_display, EnterNotify, &e));
|
||||||
/* remove these flags so we don't end up getting focused in the
|
|
||||||
fallback! */
|
|
||||||
self->can_focus = FALSE;
|
|
||||||
self->focus_notify = FALSE;
|
|
||||||
self->modal = FALSE;
|
|
||||||
client_unfocus(self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* potentially fix focusLast */
|
|
||||||
if (config_focus_last)
|
|
||||||
grab_pointer(TRUE, OB_CURSOR_NONE);
|
|
||||||
|
|
||||||
frame_hide(self->frame);
|
|
||||||
XFlush(ob_display);
|
|
||||||
|
|
||||||
keyboard_grab_for_client(self, FALSE);
|
keyboard_grab_for_client(self, FALSE);
|
||||||
mouse_grab_for_client(self, FALSE);
|
mouse_grab_for_client(self, FALSE);
|
||||||
|
@ -540,6 +527,9 @@ void client_unmanage(ObClient *self)
|
||||||
/* we dont want events no more */
|
/* we dont want events no more */
|
||||||
XSelectInput(ob_display, self->window, NoEventMask);
|
XSelectInput(ob_display, self->window, NoEventMask);
|
||||||
|
|
||||||
|
/* update the focus lists */
|
||||||
|
focus_order_remove(self);
|
||||||
|
|
||||||
client_list = g_list_remove(client_list, self);
|
client_list = g_list_remove(client_list, self);
|
||||||
stacking_remove(self);
|
stacking_remove(self);
|
||||||
g_hash_table_remove(window_map, &self->window);
|
g_hash_table_remove(window_map, &self->window);
|
||||||
|
@ -639,9 +629,6 @@ void client_unmanage(ObClient *self)
|
||||||
|
|
||||||
/* update the list hints */
|
/* update the list hints */
|
||||||
client_set_list();
|
client_set_list();
|
||||||
|
|
||||||
if (config_focus_last)
|
|
||||||
grab_pointer(FALSE, OB_CURSOR_NONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ObAppSettings *client_get_settings_state(ObClient *self)
|
static ObAppSettings *client_get_settings_state(ObClient *self)
|
||||||
|
@ -3054,19 +3041,6 @@ gboolean client_focus(ObClient *self)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used when the current client is closed or otherwise hidden, focus_last will
|
|
||||||
then prevent focus from going to the mouse pointer
|
|
||||||
*/
|
|
||||||
static void client_unfocus(ObClient *self)
|
|
||||||
{
|
|
||||||
if (focus_client == self) {
|
|
||||||
#ifdef DEBUG_FOCUS
|
|
||||||
ob_debug("client_unfocus for %lx\n", self->window);
|
|
||||||
#endif
|
|
||||||
focus_fallback(FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void client_activate(ObClient *self, gboolean here, gboolean user)
|
void client_activate(ObClient *self, gboolean here, gboolean user)
|
||||||
{
|
{
|
||||||
guint32 last_time = focus_client ? focus_client->user_time : CurrentTime;
|
guint32 last_time = focus_client ? focus_client->user_time : CurrentTime;
|
||||||
|
|
108
openbox/event.c
108
openbox/event.c
|
@ -398,12 +398,11 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
|
||||||
return keyboard_interactively_grabbed();
|
return keyboard_interactively_grabbed();
|
||||||
case FocusIn:
|
case FocusIn:
|
||||||
case FocusOut:
|
case FocusOut:
|
||||||
/* I don't think this should ever happen with our event masks, but
|
if (!wanted_focusevent(e)) {
|
||||||
if it does, we don't want it. */
|
ob_debug_type(OB_DEBUG_FOCUS, "focus event ignored\n");
|
||||||
if (client == NULL)
|
|
||||||
return TRUE;
|
|
||||||
if (!wanted_focusevent(e))
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
}
|
||||||
|
ob_debug_type(OB_DEBUG_FOCUS, "focus event used;\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -485,6 +484,58 @@ static void event_process(const XEvent *ec, gpointer data)
|
||||||
{
|
{
|
||||||
/* crossing events for menu */
|
/* crossing events for menu */
|
||||||
event_handle_menu(e);
|
event_handle_menu(e);
|
||||||
|
} else if (e->type == FocusIn) {
|
||||||
|
if (e->xfocus.detail == NotifyPointerRoot ||
|
||||||
|
e->xfocus.detail == NotifyDetailNone) {
|
||||||
|
ob_debug_type(OB_DEBUG_FOCUS, "Focus went to root\n");
|
||||||
|
/* Focus has been reverted to the root window or nothing, so fall
|
||||||
|
back to something other than the window which just had it. */
|
||||||
|
focus_fallback(FALSE);
|
||||||
|
} else if (e->xfocus.detail == NotifyInferior) {
|
||||||
|
ob_debug_type(OB_DEBUG_FOCUS, "Focus went to parent\n");
|
||||||
|
/* Focus has been reverted to parent, which is our frame window,
|
||||||
|
or the root window, so fall back to something other than the
|
||||||
|
window which had it. */
|
||||||
|
focus_fallback(FALSE);
|
||||||
|
} else if (client && client != focus_client) {
|
||||||
|
focus_set_client(client);
|
||||||
|
frame_adjust_focus(client->frame, TRUE);
|
||||||
|
client_calc_layer(client);
|
||||||
|
}
|
||||||
|
} else if (e->type == FocusOut) {
|
||||||
|
gboolean nomove = FALSE;
|
||||||
|
XEvent ce;
|
||||||
|
|
||||||
|
ob_debug_type(OB_DEBUG_FOCUS, "FocusOut Event\n");
|
||||||
|
|
||||||
|
/* Look for the followup FocusIn */
|
||||||
|
if (!XCheckIfEvent(ob_display, &ce, look_for_focusin, NULL)) {
|
||||||
|
/* There is no FocusIn, this means focus went to a window that
|
||||||
|
is not being managed, or a window on another screen. */
|
||||||
|
ob_debug_type(OB_DEBUG_FOCUS, "Focus went to a black hole !\n");
|
||||||
|
} else if (ce.xany.window == e->xany.window) {
|
||||||
|
/* If focus didn't actually move anywhere, there is nothing to do*/
|
||||||
|
nomove = TRUE;
|
||||||
|
} else {
|
||||||
|
/* Focus did move, so process the FocusIn event */
|
||||||
|
ObEventData ed = { .ignored = FALSE };
|
||||||
|
event_process(&ce, &ed);
|
||||||
|
if (ed.ignored) {
|
||||||
|
/* The FocusIn was ignored, this means it was on a window
|
||||||
|
that isn't a client. */
|
||||||
|
ob_debug_type(OB_DEBUG_FOCUS,
|
||||||
|
"Focus went to an unmanaged window 0x%x !\n",
|
||||||
|
ce.xfocus.window);
|
||||||
|
focus_fallback(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client && !nomove) {
|
||||||
|
/* This client is no longer focused, so show that */
|
||||||
|
focus_hilite = NULL;
|
||||||
|
frame_adjust_focus(client->frame, FALSE);
|
||||||
|
client_calc_layer(client);
|
||||||
|
}
|
||||||
} else if (group)
|
} else if (group)
|
||||||
event_handle_group(group, e);
|
event_handle_group(group, e);
|
||||||
else if (client)
|
else if (client)
|
||||||
|
@ -690,53 +741,6 @@ static void event_handle_client(ObClient *client, XEvent *e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FocusIn:
|
|
||||||
if (client != focus_client) {
|
|
||||||
focus_set_client(client);
|
|
||||||
frame_adjust_focus(client->frame, TRUE);
|
|
||||||
client_calc_layer(client);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FocusOut:
|
|
||||||
/* Look for the followup FocusIn */
|
|
||||||
if (!XCheckIfEvent(ob_display, &ce, look_for_focusin, NULL)) {
|
|
||||||
/* There is no FocusIn, this means focus went to a window that
|
|
||||||
is not being managed, or a window on another screen. */
|
|
||||||
ob_debug_type(OB_DEBUG_FOCUS, "Focus went to a black hole !\n");
|
|
||||||
} else if (ce.xany.window == e->xany.window) {
|
|
||||||
/* If focus didn't actually move anywhere, there is nothing to do*/
|
|
||||||
break;
|
|
||||||
} else if (ce.xfocus.detail == NotifyPointerRoot ||
|
|
||||||
ce.xfocus.detail == NotifyDetailNone) {
|
|
||||||
ob_debug_type(OB_DEBUG_FOCUS, "Focus went to root\n");
|
|
||||||
/* Focus has been reverted to the root window or nothing, so fall
|
|
||||||
back to something other than the window which just had it. */
|
|
||||||
focus_fallback(FALSE);
|
|
||||||
} else if (ce.xfocus.detail == NotifyInferior) {
|
|
||||||
ob_debug_type(OB_DEBUG_FOCUS, "Focus went to parent\n");
|
|
||||||
/* Focus has been reverted to parent, which is our frame window,
|
|
||||||
or the root window, so fall back to something other than the
|
|
||||||
window which had it. */
|
|
||||||
focus_fallback(FALSE);
|
|
||||||
} else {
|
|
||||||
/* Focus did move, so process the FocusIn event */
|
|
||||||
ObEventData ed = { .ignored = FALSE };
|
|
||||||
event_process(&ce, &ed);
|
|
||||||
if (ed.ignored) {
|
|
||||||
/* The FocusIn was ignored, this means it was on a window
|
|
||||||
that isn't a client. */
|
|
||||||
ob_debug_type(OB_DEBUG_FOCUS,
|
|
||||||
"Focus went to an unmanaged window 0x%x !\n",
|
|
||||||
ce.xfocus.window);
|
|
||||||
focus_fallback(TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This client is no longer focused, so show that */
|
|
||||||
focus_hilite = NULL;
|
|
||||||
frame_adjust_focus(client->frame, FALSE);
|
|
||||||
client_calc_layer(client);
|
|
||||||
break;
|
|
||||||
case LeaveNotify:
|
case LeaveNotify:
|
||||||
con = frame_context(client, e->xcrossing.window);
|
con = frame_context(client, e->xcrossing.window);
|
||||||
switch (con) {
|
switch (con) {
|
||||||
|
|
Loading…
Reference in a new issue