+
+ if (menu_frame_visible &&
+ (e->type == EnterNotify || e->type == LeaveNotify))
+ {
+ /* crossing events for menu */
+ event_handle_menu(e);
+ } else if (e->type == FocusIn) {
+ if (e->xfocus.detail == NotifyPointerRoot ||
+ e->xfocus.detail == NotifyDetailNone ||
+ e->xfocus.detail == NotifyInferior)
+ {
+ XEvent ce;
+ ob_debug_type(OB_DEBUG_FOCUS,
+ "Focus went to pointer root/none or to our frame "
+ "window\n");
+
+ /* If another FocusIn is in the queue then don't fallback yet. This
+ fixes the fun case of:
+ window map -> send focusin
+ window unmap -> get focusout
+ window map -> send focusin
+ get first focus out -> fall back to something (new window
+ hasn't received focus yet, so something else) -> send focusin
+ which means the "something else" is the last thing to get a
+ focusin sent to it, so the new window doesn't end up with focus.
+
+ But if the other focus in is something like PointerRoot then we
+ still want to fall back.
+ */
+ if (XCheckIfEvent(ob_display, &ce, look_for_focusin_client, NULL)){
+ XPutBackEvent(ob_display, &ce);
+ ob_debug_type(OB_DEBUG_FOCUS,
+ " but another FocusIn is coming\n");
+ } else {
+ /* Focus has been reverted to the root window, nothing, or to
+ our frame window.
+
+ FocusOut events come after UnmapNotify, so we don't need to
+ worry about focusing an invalid window
+ */
+
+ /* In this case we know focus is in our screen */
+ if (e->xfocus.detail == NotifyInferior)
+ focus_left_screen = FALSE;
+
+ if (!focus_left_screen)
+ focus_fallback(TRUE);
+ }
+ } else if (client && client != focus_client) {
+ focus_left_screen = FALSE;
+ frame_adjust_focus(client->frame, TRUE);
+ focus_set_client(client);
+ client_calc_layer(client);
+ client_bring_helper_windows(client);
+ }
+ } else if (e->type == FocusOut) {
+ gboolean nomove = FALSE;
+ XEvent ce;
+
+ /* 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. */
+ Window win, root;
+ gint i;
+ guint u;
+ xerror_set_ignore(TRUE);
+ if (XGetInputFocus(ob_display, &win, &i) != 0 &&
+ XGetGeometry(ob_display, win, &root, &i,&i,&u,&u,&u,&u) != 0 &&
+ root != RootWindow(ob_display, ob_screen))
+ {
+ ob_debug_type(OB_DEBUG_FOCUS,
+ "Focus went to another screen !\n");
+ focus_left_screen = TRUE;
+ }
+ else
+ ob_debug_type(OB_DEBUG_FOCUS,
+ "Focus went to a black hole !\n");
+ xerror_set_ignore(FALSE);
+ /* nothing is focused */
+ focus_set_client(NULL);
+ } else if (ce.xany.window == e->xany.window) {
+ ob_debug_type(OB_DEBUG_FOCUS, "Focus didn't go anywhere\n");
+ /* 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) {
+ frame_adjust_focus(client->frame, FALSE);
+ /* focus_set_client has already been called for sure */
+ client_calc_layer(client);
+ }
+ } else if (timewinclients)
+ event_handle_user_time_window_clients(timewinclients, e);