super correct enter event ignoring that will only ignore what it has to, yay?
This commit is contained in:
parent
9451205cf1
commit
6d26502631
8 changed files with 100 additions and 31 deletions
|
@ -46,8 +46,8 @@ static void client_action_end(union ActionData *data)
|
||||||
{
|
{
|
||||||
if (config_focus_follow)
|
if (config_focus_follow)
|
||||||
if (data->any.context != OB_FRAME_CONTEXT_CLIENT) {
|
if (data->any.context != OB_FRAME_CONTEXT_CLIENT) {
|
||||||
if (!data->any.button) {
|
if (!data->any.button && data->any.c) {
|
||||||
event_ignore_queued_enters();
|
event_ignore_enters_leaving_window(data->any.c);
|
||||||
} else {
|
} else {
|
||||||
ObClient *c;
|
ObClient *c;
|
||||||
|
|
||||||
|
|
|
@ -565,7 +565,7 @@ void client_unmanage(ObClient *self)
|
||||||
|
|
||||||
/* ignore enter events from the unmap so it doesnt mess with the
|
/* ignore enter events from the unmap so it doesnt mess with the
|
||||||
focus */
|
focus */
|
||||||
event_ignore_queued_enters();
|
event_ignore_enters_leaving_window(self);
|
||||||
|
|
||||||
mouse_grab_for_client(self, FALSE);
|
mouse_grab_for_client(self, FALSE);
|
||||||
|
|
||||||
|
|
|
@ -119,19 +119,15 @@ static void client_menu_execute(ObMenuEntry *e, ObMenuFrame *f,
|
||||||
break;
|
break;
|
||||||
case CLIENT_RESTORE:
|
case CLIENT_RESTORE:
|
||||||
client_maximize(c, FALSE, 0);
|
client_maximize(c, FALSE, 0);
|
||||||
event_ignore_queued_enters();
|
|
||||||
break;
|
break;
|
||||||
case CLIENT_MAXIMIZE:
|
case CLIENT_MAXIMIZE:
|
||||||
client_maximize(c, TRUE, 0);
|
client_maximize(c, TRUE, 0);
|
||||||
event_ignore_queued_enters();
|
|
||||||
break;
|
break;
|
||||||
case CLIENT_SHADE:
|
case CLIENT_SHADE:
|
||||||
client_shade(c, !c->shaded);
|
client_shade(c, !c->shaded);
|
||||||
event_ignore_queued_enters();
|
|
||||||
break;
|
break;
|
||||||
case CLIENT_DECORATE:
|
case CLIENT_DECORATE:
|
||||||
client_set_undecorated(c, !c->undecorated);
|
client_set_undecorated(c, !c->undecorated);
|
||||||
event_ignore_queued_enters();
|
|
||||||
break;
|
break;
|
||||||
case CLIENT_MOVE:
|
case CLIENT_MOVE:
|
||||||
/* this needs to grab the keyboard so hide the menu */
|
/* this needs to grab the keyboard so hide the menu */
|
||||||
|
@ -158,6 +154,10 @@ static void client_menu_execute(ObMenuEntry *e, ObMenuFrame *f,
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* we have to ignore all queued enters because the menu has a grab, and the
|
||||||
|
so the cursor isnt considered inside the client's window */
|
||||||
|
event_ignore_all_queued_enters();
|
||||||
|
|
||||||
/* update the menu cuz stuff can have changed */
|
/* update the menu cuz stuff can have changed */
|
||||||
if (f) {
|
if (f) {
|
||||||
client_menu_update(f, NULL);
|
client_menu_update(f, NULL);
|
||||||
|
@ -217,7 +217,9 @@ static void layer_menu_execute(ObMenuEntry *e, ObMenuFrame *f,
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
event_ignore_queued_enters();
|
/* we have to ignore all queued enters because the menu has a grab, and the
|
||||||
|
so the cursor isnt considered inside the client's window */
|
||||||
|
event_ignore_all_queued_enters();
|
||||||
|
|
||||||
/* update the menu cuz stuff can have changed */
|
/* update the menu cuz stuff can have changed */
|
||||||
if (f) {
|
if (f) {
|
||||||
|
|
|
@ -85,6 +85,7 @@ static void event_handle_dockapp(ObDockApp *app, XEvent *e);
|
||||||
static void event_handle_client(ObClient *c, XEvent *e);
|
static void event_handle_client(ObClient *c, XEvent *e);
|
||||||
static void event_handle_user_time_window_clients(GSList *l, XEvent *e);
|
static void event_handle_user_time_window_clients(GSList *l, XEvent *e);
|
||||||
static void event_handle_user_input(ObClient *client, XEvent *e);
|
static void event_handle_user_input(ObClient *client, XEvent *e);
|
||||||
|
static gboolean is_enter_focus_event_ignored(XEvent *e);
|
||||||
|
|
||||||
static void focus_delay_dest(gpointer data);
|
static void focus_delay_dest(gpointer data);
|
||||||
static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2);
|
static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2);
|
||||||
|
@ -96,7 +97,11 @@ static gboolean menu_hide_delay_func(gpointer data);
|
||||||
/* The time for the current event being processed */
|
/* The time for the current event being processed */
|
||||||
Time event_curtime = CurrentTime;
|
Time event_curtime = CurrentTime;
|
||||||
|
|
||||||
|
#define NUM_IGNORE_SERIALS 20
|
||||||
|
|
||||||
static guint ignore_enter_focus = 0;
|
static guint ignore_enter_focus = 0;
|
||||||
|
/*! This is a 0 terminated list of ignored serials */
|
||||||
|
static gulong ignore_enter_serials[NUM_IGNORE_SERIALS+1] = {0};
|
||||||
static gboolean menu_can_hide;
|
static gboolean menu_can_hide;
|
||||||
static gboolean focus_left_screen = FALSE;
|
static gboolean focus_left_screen = FALSE;
|
||||||
|
|
||||||
|
@ -883,7 +888,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
|
||||||
corresponding enter events. Pretend like the animating window
|
corresponding enter events. Pretend like the animating window
|
||||||
doesn't even exist..! */
|
doesn't even exist..! */
|
||||||
if (frame_iconify_animating(client->frame))
|
if (frame_iconify_animating(client->frame))
|
||||||
event_ignore_queued_enters();
|
event_ignore_enters_leaving_window(client);
|
||||||
|
|
||||||
ob_debug_type(OB_DEBUG_FOCUS,
|
ob_debug_type(OB_DEBUG_FOCUS,
|
||||||
"%sNotify mode %d detail %d on %lx\n",
|
"%sNotify mode %d detail %d on %lx\n",
|
||||||
|
@ -911,10 +916,8 @@ static void event_handle_client(ObClient *client, XEvent *e)
|
||||||
{
|
{
|
||||||
gboolean nofocus = FALSE;
|
gboolean nofocus = FALSE;
|
||||||
|
|
||||||
if (ignore_enter_focus) {
|
if (is_enter_focus_event_ignored(e))
|
||||||
ignore_enter_focus--;
|
|
||||||
nofocus = TRUE;
|
nofocus = TRUE;
|
||||||
}
|
|
||||||
|
|
||||||
con = frame_context(client, e->xcrossing.window,
|
con = frame_context(client, e->xcrossing.window,
|
||||||
e->xcrossing.x, e->xcrossing.y);
|
e->xcrossing.x, e->xcrossing.y);
|
||||||
|
@ -1084,7 +1087,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
|
||||||
client_configure(client, x, y, w, h, FALSE, TRUE);
|
client_configure(client, x, y, w, h, FALSE, TRUE);
|
||||||
|
|
||||||
/* ignore enter events caused by these like ob actions do */
|
/* ignore enter events caused by these like ob actions do */
|
||||||
event_ignore_queued_enters();
|
event_ignore_enters_leaving_window(client);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1180,7 +1183,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
|
||||||
e->xclient.data.l[1], e->xclient.data.l[2]);
|
e->xclient.data.l[1], e->xclient.data.l[2]);
|
||||||
|
|
||||||
/* ignore enter events caused by these like ob actions do */
|
/* ignore enter events caused by these like ob actions do */
|
||||||
event_ignore_queued_enters();
|
event_ignore_enters_leaving_window(client);
|
||||||
} else if (msgtype == prop_atoms.net_close_window) {
|
} else if (msgtype == prop_atoms.net_close_window) {
|
||||||
ob_debug("net_close_window for 0x%lx\n", client->window);
|
ob_debug("net_close_window for 0x%lx\n", client->window);
|
||||||
client_close(client);
|
client_close(client);
|
||||||
|
@ -1268,7 +1271,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
|
||||||
client_configure(client, x, y, w, h, FALSE, TRUE);
|
client_configure(client, x, y, w, h, FALSE, TRUE);
|
||||||
|
|
||||||
/* ignore enter events caused by these like ob actions do */
|
/* ignore enter events caused by these like ob actions do */
|
||||||
event_ignore_queued_enters();
|
event_ignore_enters_leaving_window(client);
|
||||||
} else if (msgtype == prop_atoms.net_restack_window) {
|
} else if (msgtype == prop_atoms.net_restack_window) {
|
||||||
if (e->xclient.data.l[0] != 2) {
|
if (e->xclient.data.l[0] != 2) {
|
||||||
ob_debug_type(OB_DEBUG_APP_BUGS,
|
ob_debug_type(OB_DEBUG_APP_BUGS,
|
||||||
|
@ -1717,32 +1720,92 @@ void event_halt_focus_delay()
|
||||||
ob_main_loop_timeout_remove(ob_main_loop, focus_delay_func);
|
ob_main_loop_timeout_remove(ob_main_loop, focus_delay_func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ObLookForEnters
|
||||||
|
{
|
||||||
|
ObClient *c;
|
||||||
|
gulong looking_for_enter;
|
||||||
|
};
|
||||||
|
|
||||||
static Bool event_look_for_enters(Display *d, XEvent *e, XPointer arg)
|
static Bool event_look_for_enters(Display *d, XEvent *e, XPointer arg)
|
||||||
{
|
{
|
||||||
guint *count = (guint*)arg;
|
struct ObLookForEnters *lfe = (struct ObLookForEnters*)arg;
|
||||||
if (e->type == EnterNotify) {
|
|
||||||
ObWindow *win;
|
|
||||||
|
|
||||||
win = g_hash_table_lookup(window_map, &e->xany.window);
|
if (lfe->c != NULL && e->type == LeaveNotify) {
|
||||||
if (win && WINDOW_IS_CLIENT(win))
|
if (g_hash_table_lookup(window_map, &e->xany.window) == lfe->c)
|
||||||
++(*count);
|
/* found an event leaving this window */
|
||||||
|
lfe->looking_for_enter = e->xany.serial;
|
||||||
|
} else if (e->type == EnterNotify &&
|
||||||
|
(lfe->c == NULL || e->xany.serial == lfe->looking_for_enter))
|
||||||
|
{
|
||||||
|
ObWindow *win;
|
||||||
|
gint i;
|
||||||
|
gboolean ignored = FALSE;
|
||||||
|
|
||||||
|
/* make sure the serial isn't already being ignored */
|
||||||
|
for (i = 0; ignore_enter_serials[i] != 0 && !ignored; ++i) {
|
||||||
|
if (ignore_enter_serials[i] == e->xany.serial)
|
||||||
|
ignored = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ignored) {
|
||||||
|
/* found an enter for that leave, ignore it if it's going to
|
||||||
|
another window */
|
||||||
|
win = g_hash_table_lookup(window_map, &e->xany.window);
|
||||||
|
if (win && WINDOW_IS_CLIENT(win))
|
||||||
|
++ignore_enter_focus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add it to the ignored list if there is room */
|
||||||
|
if (i < NUM_IGNORE_SERIALS) {
|
||||||
|
ignore_enter_serials[i] = e->xany.serial;
|
||||||
|
ignore_enter_serials[i+1] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return False; /* don't disrupt the queue order, just count them */
|
return False; /* don't disrupt the queue order, just count them */
|
||||||
}
|
}
|
||||||
|
|
||||||
void event_ignore_queued_enters()
|
void event_ignore_all_queued_enters()
|
||||||
{
|
{
|
||||||
|
event_ignore_enters_leaving_window(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void event_ignore_enters_leaving_window(ObClient *c)
|
||||||
|
{
|
||||||
|
struct ObLookForEnters lfe;
|
||||||
XEvent e;
|
XEvent e;
|
||||||
|
|
||||||
XSync(ob_display, FALSE);
|
XSync(ob_display, FALSE);
|
||||||
|
|
||||||
/* count the events without disrupting them */
|
/* count the events without disrupting them */
|
||||||
ignore_enter_focus = 0;
|
ignore_enter_focus = 0;
|
||||||
XCheckIfEvent(ob_display, &e, event_look_for_enters,
|
lfe.c = c;
|
||||||
(XPointer)&ignore_enter_focus);
|
lfe.looking_for_enter = 0;
|
||||||
|
XCheckIfEvent(ob_display, &e, event_look_for_enters, (XPointer)&lfe);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean is_enter_focus_event_ignored(XEvent *e)
|
||||||
|
{
|
||||||
|
g_assert(e->type == EnterNotify);
|
||||||
|
|
||||||
|
if (ignore_enter_focus) {
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
--ignore_enter_focus;
|
||||||
|
|
||||||
|
/* remove the serial */
|
||||||
|
for (i = 0; ignore_enter_serials[i] != 0; ++i) {
|
||||||
|
if (ignore_enter_serials[i] == e->xany.serial) {
|
||||||
|
for (; ignore_enter_serials[i+1] != 0; ++i)
|
||||||
|
ignore_enter_serials[i] = ignore_enter_serials[i+1];
|
||||||
|
ignore_enter_serials[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean event_time_after(Time t1, Time t2)
|
gboolean event_time_after(Time t1, Time t2)
|
||||||
{
|
{
|
||||||
g_assert(t1 != CurrentTime);
|
g_assert(t1 != CurrentTime);
|
||||||
|
|
|
@ -39,9 +39,13 @@ void event_shutdown(gboolean reconfig);
|
||||||
follows mouse */
|
follows mouse */
|
||||||
void event_enter_client(struct _ObClient *client);
|
void event_enter_client(struct _ObClient *client);
|
||||||
|
|
||||||
/*! Request that any queued EnterNotify events not be used for distributing
|
/*! Make mouse focus not move if the mouse leaves this client from what
|
||||||
focus */
|
has just transpired. */
|
||||||
void event_ignore_queued_enters();
|
void event_ignore_enters_leaving_window(struct _ObClient *c);
|
||||||
|
|
||||||
|
/*! Make mouse focus not move at all from the stuff that has happened up
|
||||||
|
till now. */
|
||||||
|
void event_ignore_all_queued_enters();
|
||||||
|
|
||||||
/* Halts any focus delay in progress, use this when the user is selecting a
|
/* Halts any focus delay in progress, use this when the user is selecting a
|
||||||
window for focus */
|
window for focus */
|
||||||
|
|
|
@ -425,7 +425,7 @@ void focus_cycle_draw_indicator()
|
||||||
XUnmapWindow(ob_display, focus_indicator.bottom.win);
|
XUnmapWindow(ob_display, focus_indicator.bottom.win);
|
||||||
|
|
||||||
/* kill enter events cause by this unmapping */
|
/* kill enter events cause by this unmapping */
|
||||||
event_ignore_queued_enters();
|
event_ignore_all_queued_enters();
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
if (focus_cycle_target)
|
if (focus_cycle_target)
|
||||||
|
|
|
@ -269,7 +269,7 @@ void popup_hide(ObPopup *self)
|
||||||
self->mapped = FALSE;
|
self->mapped = FALSE;
|
||||||
|
|
||||||
/* kill enter events cause by this unmapping */
|
/* kill enter events cause by this unmapping */
|
||||||
event_ignore_queued_enters();
|
event_ignore_all_queued_enters();
|
||||||
} else if (self->delay_mapped) {
|
} else if (self->delay_mapped) {
|
||||||
ob_main_loop_timeout_remove(ob_main_loop, popup_show_timeout);
|
ob_main_loop_timeout_remove(ob_main_loop, popup_show_timeout);
|
||||||
self->delay_mapped = FALSE;
|
self->delay_mapped = FALSE;
|
||||||
|
|
|
@ -523,7 +523,7 @@ void screen_set_desktop(guint num, gboolean dofocus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
event_ignore_queued_enters();
|
event_ignore_all_queued_enters();
|
||||||
|
|
||||||
if (event_curtime != CurrentTime)
|
if (event_curtime != CurrentTime)
|
||||||
screen_desktop_user_time = event_curtime;
|
screen_desktop_user_time = event_curtime;
|
||||||
|
|
Loading…
Reference in a new issue