break;
case CLIENT_RESTORE:
client_maximize(c, FALSE, 0);
- event_ignore_queued_enters();
break;
case CLIENT_MAXIMIZE:
client_maximize(c, TRUE, 0);
- event_ignore_queued_enters();
break;
case CLIENT_SHADE:
client_shade(c, !c->shaded);
- event_ignore_queued_enters();
break;
case CLIENT_DECORATE:
client_set_undecorated(c, !c->undecorated);
- event_ignore_queued_enters();
break;
case CLIENT_MOVE:
/* this needs to grab the keyboard so hide the menu */
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 */
if (f) {
client_menu_update(f, NULL);
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 */
if (f) {
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_input(ObClient *client, XEvent *e);
+static gboolean is_enter_focus_event_ignored(XEvent *e);
static void focus_delay_dest(gpointer data);
static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2);
/* The time for the current event being processed */
Time event_curtime = CurrentTime;
+#define NUM_IGNORE_SERIALS 20
+
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 focus_left_screen = FALSE;
corresponding enter events. Pretend like the animating window
doesn't even exist..! */
if (frame_iconify_animating(client->frame))
- event_ignore_queued_enters();
+ event_ignore_enters_leaving_window(client);
ob_debug_type(OB_DEBUG_FOCUS,
"%sNotify mode %d detail %d on %lx\n",
{
gboolean nofocus = FALSE;
- if (ignore_enter_focus) {
- ignore_enter_focus--;
+ if (is_enter_focus_event_ignored(e))
nofocus = TRUE;
- }
con = frame_context(client, e->xcrossing.window,
e->xcrossing.x, e->xcrossing.y);
client_configure(client, x, y, w, h, FALSE, TRUE);
/* ignore enter events caused by these like ob actions do */
- event_ignore_queued_enters();
+ event_ignore_enters_leaving_window(client);
}
break;
}
e->xclient.data.l[1], e->xclient.data.l[2]);
/* 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) {
ob_debug("net_close_window for 0x%lx\n", client->window);
client_close(client);
client_configure(client, x, y, w, h, FALSE, TRUE);
/* 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) {
if (e->xclient.data.l[0] != 2) {
ob_debug_type(OB_DEBUG_APP_BUGS,
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)
{
- guint *count = (guint*)arg;
- if (e->type == EnterNotify) {
+ struct ObLookForEnters *lfe = (struct ObLookForEnters*)arg;
+
+ if (lfe->c != NULL && e->type == LeaveNotify) {
+ if (g_hash_table_lookup(window_map, &e->xany.window) == lfe->c)
+ /* 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;
-
- win = g_hash_table_lookup(window_map, &e->xany.window);
- if (win && WINDOW_IS_CLIENT(win))
- ++(*count);
+ 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 */
}
-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;
-
+
XSync(ob_display, FALSE);
/* count the events without disrupting them */
ignore_enter_focus = 0;
- XCheckIfEvent(ob_display, &e, event_look_for_enters,
- (XPointer)&ignore_enter_focus);
+ lfe.c = c;
+ 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)