]> Dogcows Code - chaz/openbox/blobdiff - openbox/event.c
prevent flicker in the follow actiosn again instead of in focus fallback. focus fallb...
[chaz/openbox] / openbox / event.c
index 458e4a35ece987f62c870f08cdfd86696f19d957..6e11f82eac819dcf8fff9addb8c10e8f27c723fd 100644 (file)
@@ -38,6 +38,7 @@
 #include "mainloop.h"
 #include "framerender.h"
 #include "focus.h"
 #include "mainloop.h"
 #include "framerender.h"
 #include "focus.h"
+#include "focus_cycle.h"
 #include "moveresize.h"
 #include "group.h"
 #include "stacking.h"
 #include "moveresize.h"
 #include "group.h"
 #include "stacking.h"
@@ -85,6 +86,7 @@ static void event_handle_dockapp(ObDockApp *app, 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_input(ObClient *client, 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_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);
 
 static void focus_delay_dest(gpointer data);
 static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2);
@@ -317,6 +319,12 @@ static gboolean wanted_focusevent(XEvent *e, gboolean in_client_only)
             if (!w || !WINDOW_IS_CLIENT(w))
                 return FALSE;
         }
             if (!w || !WINDOW_IS_CLIENT(w))
                 return FALSE;
         }
+        else {
+            /* This means focus reverted to parent from the client (this
+               happens often during iconify animation) */
+            if (detail == NotifyInferior)
+                return TRUE;
+        }
 
         /* This means focus moved from the root window to a client */
         if (detail == NotifyVirtual)
 
         /* This means focus moved from the root window to a client */
         if (detail == NotifyVirtual)
@@ -478,7 +486,8 @@ static void event_process(const XEvent *ec, gpointer data)
         {
             XEvent ce;
 
         {
             XEvent ce;
 
-            ob_debug_type(OB_DEBUG_FOCUS, "Focus went to pointer root/none\n");
+            ob_debug_type(OB_DEBUG_FOCUS, "Focus went to pointer root/none or"
+                          " the frame window\n");
 
             /* If another FocusIn is in the queue then don't fallback yet. This
                fixes the fun case of:
 
             /* If another FocusIn is in the queue then don't fallback yet. This
                fixes the fun case of:
@@ -500,7 +509,7 @@ static void event_process(const XEvent *ec, gpointer data)
                 ob_debug_type(OB_DEBUG_FOCUS,
                               "  but another FocusIn is coming\n");
             } else {
                 ob_debug_type(OB_DEBUG_FOCUS,
                               "  but another FocusIn is coming\n");
             } else {
-                /* Focus has been reverted to the root window or nothing.
+                /* Focus has been reverted.
 
                    FocusOut events come after UnmapNotify, so we don't need to
                    worry about focusing an invalid window
 
                    FocusOut events come after UnmapNotify, so we don't need to
                    worry about focusing an invalid window
@@ -530,6 +539,13 @@ static void event_process(const XEvent *ec, gpointer data)
         gboolean nomove = FALSE;
         XEvent ce;
 
         gboolean nomove = FALSE;
         XEvent ce;
 
+        if (client) {
+            frame_adjust_focus(client->frame, FALSE);
+            /* focus_set_client(NULL) has already been called in this
+               section or by focus_fallback */
+            client_calc_layer(client);
+        }
+
         /* Look for the followup FocusIn */
         if (!XCheckIfEvent(ob_display, &ce, event_look_for_focusin, NULL)) {
             /* There is no FocusIn, this means focus went to a window that
         /* Look for the followup FocusIn */
         if (!XCheckIfEvent(ob_display, &ce, event_look_for_focusin, NULL)) {
             /* There is no FocusIn, this means focus went to a window that
@@ -552,12 +568,8 @@ static void event_process(const XEvent *ec, gpointer data)
             xerror_set_ignore(FALSE);
             /* nothing is focused */
             focus_set_client(NULL);
             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 {
         } else {
-            /* Focus did move, so process the FocusIn event */
+            /* Focus moved, so process the FocusIn event */
             ObEventData ed = { .ignored = FALSE };
             event_process(&ce, &ed);
             if (ed.ignored) {
             ObEventData ed = { .ignored = FALSE };
             event_process(&ce, &ed);
             if (ed.ignored) {
@@ -569,13 +581,6 @@ static void event_process(const XEvent *ec, gpointer data)
                 focus_fallback(TRUE);
             }
         }
                 focus_fallback(TRUE);
             }
         }
-
-        if (client && !nomove) {
-            frame_adjust_focus(client->frame, FALSE);
-            if (client == focus_client)
-                focus_set_client(NULL);
-            client_calc_layer(client);
-        }
     } else if (timewinclients)
         event_handle_user_time_window_clients(timewinclients, e);
     else if (client)
     } else if (timewinclients)
         event_handle_user_time_window_clients(timewinclients, e);
     else if (client)
@@ -677,7 +682,7 @@ static void event_handle_root(XEvent *e)
             }
         } else if (msgtype == prop_atoms.net_number_of_desktops) {
             guint d = e->xclient.data.l[0];
             }
         } else if (msgtype == prop_atoms.net_number_of_desktops) {
             guint d = e->xclient.data.l[0];
-            if (d > 0)
+            if (d > 0 && d <= 1000)
                 screen_set_num_desktops(d);
         } else if (msgtype == prop_atoms.net_showing_desktop) {
             screen_show_desktop(e->xclient.data.l[0] != 0, NULL);
                 screen_set_num_desktops(d);
         } else if (msgtype == prop_atoms.net_showing_desktop) {
             screen_show_desktop(e->xclient.data.l[0] != 0, NULL);
@@ -770,7 +775,8 @@ static void event_handle_client(ObClient *client, XEvent *e)
         {
             /* use where the press occured */
             con = frame_context(client, e->xbutton.window, px, py);
         {
             /* use where the press occured */
             con = frame_context(client, e->xbutton.window, px, py);
-            con = mouse_button_frame_context(con, e->xbutton.button);
+            con = mouse_button_frame_context(con, e->xbutton.button,
+                                             e->xbutton.state);
 
             if (e->type == ButtonRelease && e->xbutton.button == pb)
                 pb = 0, px = py = -1;
 
             if (e->type == ButtonRelease && e->xbutton.button == pb)
                 pb = 0, px = py = -1;
@@ -807,6 +813,8 @@ static void event_handle_client(ObClient *client, XEvent *e)
                             e->xmotion.x, e->xmotion.y);
         switch (con) {
         case OB_FRAME_CONTEXT_TITLEBAR:
                             e->xmotion.x, e->xmotion.y);
         switch (con) {
         case OB_FRAME_CONTEXT_TITLEBAR:
+        case OB_FRAME_CONTEXT_TLCORNER:
+        case OB_FRAME_CONTEXT_TRCORNER:
             /* we've left the button area inside the titlebar */
             if (client->frame->max_hover || client->frame->desk_hover ||
                 client->frame->shade_hover || client->frame->iconify_hover ||
             /* we've left the button area inside the titlebar */
             if (client->frame->max_hover || client->frame->desk_hover ||
                 client->frame->shade_hover || client->frame->iconify_hover ||
@@ -858,6 +866,22 @@ static void event_handle_client(ObClient *client, XEvent *e)
         con = frame_context(client, e->xcrossing.window,
                             e->xcrossing.x, e->xcrossing.y);
         switch (con) {
         con = frame_context(client, e->xcrossing.window,
                             e->xcrossing.x, e->xcrossing.y);
         switch (con) {
+        case OB_FRAME_CONTEXT_TITLEBAR:
+        case OB_FRAME_CONTEXT_TLCORNER:
+        case OB_FRAME_CONTEXT_TRCORNER:
+            /* we've left the button area inside the titlebar */
+            if (client->frame->max_hover || client->frame->desk_hover ||
+                client->frame->shade_hover || client->frame->iconify_hover ||
+                client->frame->close_hover)
+            {
+                client->frame->max_hover = FALSE;
+                client->frame->desk_hover = FALSE;
+                client->frame->shade_hover = FALSE;
+                client->frame->iconify_hover = FALSE;
+                client->frame->close_hover = FALSE;
+                frame_adjust_state(client->frame);
+            }
+            break;
         case OB_FRAME_CONTEXT_MAXIMIZE:
             client->frame->max_hover = FALSE;
             frame_adjust_state(client->frame);
         case OB_FRAME_CONTEXT_MAXIMIZE:
             client->frame->max_hover = FALSE;
             frame_adjust_state(client->frame);
@@ -883,7 +907,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
                corresponding enter events. Pretend like the animating window
                doesn't even exist..! */
             if (frame_iconify_animating(client->frame))
                corresponding enter events. Pretend like the animating window
                doesn't even exist..! */
             if (frame_iconify_animating(client->frame))
-                event_ignore_queued_enters();
+                event_ignore_all_queued_enters();
 
             ob_debug_type(OB_DEBUG_FOCUS,
                           "%sNotify mode %d detail %d on %lx\n",
 
             ob_debug_type(OB_DEBUG_FOCUS,
                           "%sNotify mode %d detail %d on %lx\n",
@@ -909,13 +933,6 @@ static void event_handle_client(ObClient *client, XEvent *e)
         break;
     case EnterNotify:
     {
         break;
     case EnterNotify:
     {
-        gboolean nofocus = FALSE;
-
-        if (ignore_enter_focus) {
-            ignore_enter_focus--;
-            nofocus = TRUE;
-        }
-
         con = frame_context(client, e->xcrossing.window,
                             e->xcrossing.x, e->xcrossing.y);
         switch (con) {
         con = frame_context(client, e->xcrossing.window,
                             e->xcrossing.x, e->xcrossing.y);
         switch (con) {
@@ -945,22 +962,23 @@ static void event_handle_client(ObClient *client, XEvent *e)
             if (e->xcrossing.mode == NotifyGrab ||
                 e->xcrossing.mode == NotifyUngrab ||
                 /*ignore enters when we're already in the window */
             if (e->xcrossing.mode == NotifyGrab ||
                 e->xcrossing.mode == NotifyUngrab ||
                 /*ignore enters when we're already in the window */
-                e->xcrossing.detail == NotifyInferior)
+                e->xcrossing.detail == NotifyInferior ||
+                is_enter_focus_event_ignored(e))
             {
                 ob_debug_type(OB_DEBUG_FOCUS,
                               "%sNotify mode %d detail %d on %lx IGNORED\n",
                               (e->type == EnterNotify ? "Enter" : "Leave"),
                               e->xcrossing.mode,
                               e->xcrossing.detail, client?client->window:0);
             {
                 ob_debug_type(OB_DEBUG_FOCUS,
                               "%sNotify mode %d detail %d on %lx IGNORED\n",
                               (e->type == EnterNotify ? "Enter" : "Leave"),
                               e->xcrossing.mode,
                               e->xcrossing.detail, client?client->window:0);
-            } else {
+            }
+            else {
                 ob_debug_type(OB_DEBUG_FOCUS,
                               "%sNotify mode %d detail %d on %lx, "
                 ob_debug_type(OB_DEBUG_FOCUS,
                               "%sNotify mode %d detail %d on %lx, "
-                              "focusing window: %d\n",
+                              "focusing window\n",
                               (e->type == EnterNotify ? "Enter" : "Leave"),
                               e->xcrossing.mode,
                               (e->type == EnterNotify ? "Enter" : "Leave"),
                               e->xcrossing.mode,
-                              e->xcrossing.detail, (client?client->window:0),
-                              !nofocus);
-                if (!nofocus && config_focus_follow)
+                              e->xcrossing.detail, (client?client->window:0));
+                if (config_focus_follow)
                     event_enter_client(client);
             }
             break;
                     event_enter_client(client);
             }
             break;
@@ -978,14 +996,11 @@ static void event_handle_client(ObClient *client, XEvent *e)
         */
 
         gint x, y, w, h;
         */
 
         gint x, y, w, h;
+        gboolean move = FALSE;
+        gboolean resize = FALSE;
 
 
-        /* if nothing is changed, then a configurenotify is needed */
-        gboolean config = TRUE;
-
-        x = client->area.x;
-        y = client->area.y;
-        w = client->area.width;
-        h = client->area.height;
+        /* get the current area */
+        RECT_TO_DIMS(client->area, x, y, w, h);
 
         ob_debug("ConfigureRequest desktop %d wmstate %d visibile %d\n",
                  screen_desktop, client->wmstate, client->frame->visible);
 
         ob_debug("ConfigureRequest desktop %d wmstate %d visibile %d\n",
                  screen_desktop, client->wmstate, client->frame->visible);
@@ -993,8 +1008,13 @@ static void event_handle_client(ObClient *client, XEvent *e)
         if (e->xconfigurerequest.value_mask & CWBorderWidth)
             if (client->border_width != e->xconfigurerequest.border_width) {
                 client->border_width = e->xconfigurerequest.border_width;
         if (e->xconfigurerequest.value_mask & CWBorderWidth)
             if (client->border_width != e->xconfigurerequest.border_width) {
                 client->border_width = e->xconfigurerequest.border_width;
-                /* if only the border width is changing, then it's not needed*/
-                config = FALSE;
+
+                /* if the border width is changing then that is the same
+                   as requesting a resize, but we don't actually change
+                   the client's border, so it will change their root
+                   coordiantes (since they include the border width) and
+                   we need to a notify then */
+                move = TRUE;
             }
 
 
             }
 
 
@@ -1014,20 +1034,8 @@ static void event_handle_client(ObClient *client, XEvent *e)
             stacking_restack_request(client, sibling,
                                      e->xconfigurerequest.detail, TRUE);
 
             stacking_restack_request(client, sibling,
                                      e->xconfigurerequest.detail, TRUE);
 
-            /* if a stacking change is requested then it is needed */
-            config = TRUE;
-        }
-
-        /* don't allow clients to move shaded windows (fvwm does this) */
-        if (client->shaded && (e->xconfigurerequest.value_mask & CWX ||
-                               e->xconfigurerequest.value_mask & CWY))
-        {
-            e->xconfigurerequest.value_mask &= ~CWX;
-            e->xconfigurerequest.value_mask &= ~CWY;
-
-            /* if the client tried to move and we aren't letting it then a
-               synthetic event is needed */
-            config = TRUE;
+            /* if a stacking change moves the window without resizing */
+            move = TRUE;
         }
 
         if (e->xconfigurerequest.value_mask & CWX ||
         }
 
         if (e->xconfigurerequest.value_mask & CWX ||
@@ -1035,25 +1043,48 @@ static void event_handle_client(ObClient *client, XEvent *e)
             e->xconfigurerequest.value_mask & CWWidth ||
             e->xconfigurerequest.value_mask & CWHeight)
         {
             e->xconfigurerequest.value_mask & CWWidth ||
             e->xconfigurerequest.value_mask & CWHeight)
         {
-            if (e->xconfigurerequest.value_mask & CWX)
-                x = e->xconfigurerequest.x;
-            if (e->xconfigurerequest.value_mask & CWY)
-                y = e->xconfigurerequest.y;
-            if (e->xconfigurerequest.value_mask & CWWidth)
+            if (e->xconfigurerequest.value_mask & CWX) {
+                /* don't allow clients to move shaded windows (fvwm does this)
+                 */
+                if (!client->shaded)
+                    x = e->xconfigurerequest.x;
+                move = TRUE;
+            }
+            if (e->xconfigurerequest.value_mask & CWY) {
+                /* don't allow clients to move shaded windows (fvwm does this)
+                 */
+                if (!client->shaded)
+                    y = e->xconfigurerequest.y;
+                move = TRUE;
+            }
+
+            if (e->xconfigurerequest.value_mask & CWWidth) {
                 w = e->xconfigurerequest.width;
                 w = e->xconfigurerequest.width;
-            if (e->xconfigurerequest.value_mask & CWHeight)
+                resize = TRUE;
+
+                /* if x was not given, then use gravity to figure out the new
+                   x.  the reference point should not be moved */
+                if (!(e->xconfigurerequest.value_mask & CWX))
+                    client_gravity_resize_w(client, &x, client->area.width, w);
+            }
+            if (e->xconfigurerequest.value_mask & CWHeight) {
                 h = e->xconfigurerequest.height;
                 h = e->xconfigurerequest.height;
+                resize = TRUE;
 
 
-            /* if a new position or size is requested, then a configure is
-               needed */
-            config = TRUE;
+                /* if y was not given, then use gravity to figure out the new
+                   y.  the reference point should not be moved */
+                if (!(e->xconfigurerequest.value_mask & CWY))
+                    client_gravity_resize_h(client, &y, client->area.height,h);
+            }
         }
 
         }
 
-        ob_debug("ConfigureRequest x(%d) %d y(%d) %d w(%d) %d h(%d) %d\n",
+        ob_debug("ConfigureRequest x(%d) %d y(%d) %d w(%d) %d h(%d) %d "
+                 "move %d resize %d\n",
                  e->xconfigurerequest.value_mask & CWX, x,
                  e->xconfigurerequest.value_mask & CWY, y,
                  e->xconfigurerequest.value_mask & CWWidth, w,
                  e->xconfigurerequest.value_mask & CWX, x,
                  e->xconfigurerequest.value_mask & CWY, y,
                  e->xconfigurerequest.value_mask & CWWidth, w,
-                 e->xconfigurerequest.value_mask & CWHeight, h);
+                 e->xconfigurerequest.value_mask & CWHeight, h,
+                 move, resize);
 
         /* check for broken apps moving to their root position
 
 
         /* check for broken apps moving to their root position
 
@@ -1062,7 +1093,8 @@ static void event_handle_client(ObClient *client, XEvent *e)
            desktop. eg. open amarok window on desktop 1, switch to desktop
            2, click amarok tray icon. it will move by its decoration size.
         */
            desktop. eg. open amarok window on desktop 1, switch to desktop
            2, click amarok tray icon. it will move by its decoration size.
         */
-        if (x != client->area.x &&
+        if (move && !resize &&
+            x != client->area.x &&
             x == (client->frame->area.x + client->frame->size.left -
                   (gint)client->border_width) &&
             y != client->area.y &&
             x == (client->frame->area.x + client->frame->size.left -
                   (gint)client->border_width) &&
             y != client->area.y &&
@@ -1077,14 +1109,26 @@ static void event_handle_client(ObClient *client, XEvent *e)
             /* don't move it */
             x = client->area.x;
             y = client->area.y;
             /* don't move it */
             x = client->area.x;
             y = client->area.y;
+
+            /* they still requested a move, so don't change whether a
+               notify is sent or not */
         }
 
         }
 
-        if (config) {
+        if (move || resize) {
+            gint lw,lh;
+
             client_find_onscreen(client, &x, &y, w, h, FALSE);
             client_find_onscreen(client, &x, &y, w, h, FALSE);
-            client_configure(client, x, y, w, h, FALSE, TRUE);
+            client_try_configure(client, &x, &y, &w, &h, &lw, &lh, FALSE);
+            /* if they requested something that moves the window, or if
+               the window is actually being changed then configure it and
+               send a configure notify to them */
+            if (move || !RECT_EQUAL_DIMS(client->area, x, y, w, h)) {
+                ob_debug("Doing configure\n");
+                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_all_queued_enters();
         }
         break;
     }
         }
         break;
     }
@@ -1180,7 +1224,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
                              e->xclient.data.l[1], e->xclient.data.l[2]);
 
             /* ignore enter events caused by these like ob actions do */
                              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_all_queued_enters();
         } else if (msgtype == prop_atoms.net_close_window) {
             ob_debug("net_close_window for 0x%lx\n", client->window);
             client_close(client);
         } else if (msgtype == prop_atoms.net_close_window) {
             ob_debug("net_close_window for 0x%lx\n", client->window);
             client_close(client);
@@ -1191,11 +1235,16 @@ static void event_handle_client(ObClient *client, XEvent *e)
                       (e->xclient.data.l[0] == 1 ? "application" :
                        (e->xclient.data.l[0] == 2 ? "user" : "INVALID"))));
             /* XXX make use of data.l[2] !? */
                       (e->xclient.data.l[0] == 1 ? "application" :
                        (e->xclient.data.l[0] == 2 ? "user" : "INVALID"))));
             /* XXX make use of data.l[2] !? */
-            event_curtime = e->xclient.data.l[1];
-            if (event_curtime == 0)
+            if (e->xclient.data.l[0] == 1 || e->xclient.data.l[0] == 2) {
+                event_curtime = e->xclient.data.l[1];
+                if (event_curtime == 0)
+                    ob_debug_type(OB_DEBUG_APP_BUGS,
+                                  "_NET_ACTIVE_WINDOW message for window %s is"
+                                  " missing a timestamp\n", client->title);
+            } else
                 ob_debug_type(OB_DEBUG_APP_BUGS,
                               "_NET_ACTIVE_WINDOW message for window %s is "
                 ob_debug_type(OB_DEBUG_APP_BUGS,
                               "_NET_ACTIVE_WINDOW message for window %s is "
-                              "missing a timestamp\n", client->title);
+                              "missing source indication\n");
             client_activate(client, FALSE,
                             (e->xclient.data.l[0] == 0 ||
                              e->xclient.data.l[0] == 2));
             client_activate(client, FALSE,
                             (e->xclient.data.l[0] == 0 ||
                              e->xclient.data.l[0] == 2));
@@ -1235,12 +1284,12 @@ static void event_handle_client(ObClient *client, XEvent *e)
                      prop_atoms.net_wm_moveresize_cancel)
                 moveresize_end(TRUE);
         } else if (msgtype == prop_atoms.net_moveresize_window) {
                      prop_atoms.net_wm_moveresize_cancel)
                 moveresize_end(TRUE);
         } else if (msgtype == prop_atoms.net_moveresize_window) {
-            gint grav, x, y, w, h;
+            gint ograv, x, y, w, h;
+
+            ograv = client->gravity;
 
             if (e->xclient.data.l[0] & 0xff)
 
             if (e->xclient.data.l[0] & 0xff)
-                grav = e->xclient.data.l[0] & 0xff;
-            else 
-                grav = client->gravity;
+                client->gravity = e->xclient.data.l[0] & 0xff;
 
             if (e->xclient.data.l[0] & 1 << 8)
                 x = e->xclient.data.l[1];
 
             if (e->xclient.data.l[0] & 1 << 8)
                 x = e->xclient.data.l[1];
@@ -1250,25 +1299,42 @@ static void event_handle_client(ObClient *client, XEvent *e)
                 y = e->xclient.data.l[2];
             else
                 y = client->area.y;
                 y = e->xclient.data.l[2];
             else
                 y = client->area.y;
-            if (e->xclient.data.l[0] & 1 << 10)
+
+            if (e->xclient.data.l[0] & 1 << 10) {
                 w = e->xclient.data.l[3];
                 w = e->xclient.data.l[3];
+
+                /* if x was not given, then use gravity to figure out the new
+                   x.  the reference point should not be moved */
+                if (!(e->xclient.data.l[0] & 1 << 8))
+                    client_gravity_resize_w(client, &x, client->area.width, w);
+            }
             else
                 w = client->area.width;
             else
                 w = client->area.width;
-            if (e->xclient.data.l[0] & 1 << 11)
+
+            if (e->xclient.data.l[0] & 1 << 11) {
                 h = e->xclient.data.l[4];
                 h = e->xclient.data.l[4];
+
+                /* if y was not given, then use gravity to figure out the new
+                   y.  the reference point should not be moved */
+                if (!(e->xclient.data.l[0] & 1 << 9))
+                    client_gravity_resize_h(client, &y, client->area.height,h);
+            }
             else
                 h = client->area.height;
 
             else
                 h = client->area.height;
 
-            ob_debug("MOVERESIZE x %d %d y %d %d\n",
+            ob_debug("MOVERESIZE x %d %d y %d %d (gravity %d)\n",
                      e->xclient.data.l[0] & 1 << 8, x,
                      e->xclient.data.l[0] & 1 << 8, x,
-                     e->xclient.data.l[0] & 1 << 9, y);
-            client_convert_gravity(client, grav, &x, &y, w, h);
+                     e->xclient.data.l[0] & 1 << 9, y,
+                     client->gravity);
+
             client_find_onscreen(client, &x, &y, w, h, FALSE);
 
             client_configure(client, x, y, w, h, FALSE, TRUE);
 
             client_find_onscreen(client, &x, &y, w, h, FALSE);
 
             client_configure(client, x, y, w, h, FALSE, TRUE);
 
+            client->gravity = ograv;
+
             /* 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_all_queued_enters();
         } else if (msgtype == prop_atoms.net_restack_window) {
             if (e->xclient.data.l[0] != 2) {
                 ob_debug_type(OB_DEBUG_APP_BUGS,
         } else if (msgtype == prop_atoms.net_restack_window) {
             if (e->xclient.data.l[0] != 2) {
                 ob_debug_type(OB_DEBUG_APP_BUGS,
@@ -1278,8 +1344,8 @@ static void event_handle_client(ObClient *client, XEvent *e)
             } else {
                 ObClient *sibling = NULL;
                 if (e->xclient.data.l[1]) {
             } else {
                 ObClient *sibling = NULL;
                 if (e->xclient.data.l[1]) {
-                    ObWindow *win = g_hash_table_lookup(window_map,
-                                                        &e->xclient.data.l[1]);
+                    ObWindow *win = g_hash_table_lookup
+                        (window_map, &e->xclient.data.l[1]);
                     if (WINDOW_IS_CLIENT(win) &&
                         WINDOW_AS_CLIENT(win) != client)
                     {
                     if (WINDOW_IS_CLIENT(win) &&
                         WINDOW_AS_CLIENT(win) != client)
                     {
@@ -1486,8 +1552,11 @@ static gboolean event_handle_menu_keyboard(XEvent *ev)
         ret = FALSE;
 
     else if (keycode == ob_keycode(OB_KEY_ESCAPE) && state == 0) {
         ret = FALSE;
 
     else if (keycode == ob_keycode(OB_KEY_ESCAPE) && state == 0) {
-        /* Escape closes the active menu */
-        menu_frame_hide(frame);
+        /* Escape goes to the parent menu or closes the last one */
+        if (frame->parent)
+            menu_frame_select(frame, NULL, TRUE);
+        else
+            menu_frame_hide_all();
     }
 
     else if (keycode == ob_keycode(OB_KEY_RETURN) && (state == 0 ||
     }
 
     else if (keycode == ob_keycode(OB_KEY_RETURN) && (state == 0 ||
@@ -1611,6 +1680,10 @@ static gboolean event_handle_menu(XEvent *ev)
         }
         break;
     case LeaveNotify:
         }
         break;
     case LeaveNotify:
+        /*ignore leaves when we're already in the window */
+        if (ev->xcrossing.detail == NotifyInferior)
+            break;
+
         if ((e = g_hash_table_lookup(menu_frame_map, &ev->xcrossing.window)) &&
             (f = find_active_menu()) && f->selected == e &&
             e->entry->type != OB_MENU_ENTRY_TYPE_SUBMENU)
         if ((e = g_hash_table_lookup(menu_frame_map, &ev->xcrossing.window)) &&
             (f = find_active_menu()) && f->selected == e &&
             e->entry->type != OB_MENU_ENTRY_TYPE_SUBMENU)
@@ -1717,39 +1790,51 @@ 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);
 }
 
-void event_ignore_queued_enters()
+static Bool event_look_for_enters(Display *d, XEvent *e, XPointer arg)
 {
 {
-    GSList *saved = NULL, *it;
-    XEvent *e;
-    gint i = 0;
-                
-    XSync(ob_display, FALSE);
+    if (e->type == EnterNotify &&
+        /* these types aren't used for focusing */
+        !(e->xcrossing.mode == NotifyGrab ||
+          e->xcrossing.mode == NotifyUngrab ||
+          e->xcrossing.detail == NotifyInferior))
+    {
+        ObWindow *win;
 
 
-    /* count the events */
-    while (TRUE) {
-        e = g_new(XEvent, 1);
-        if (XCheckTypedEvent(ob_display, EnterNotify, e)) {
-            ObWindow *win;
-            
-            win = g_hash_table_lookup(window_map, &e->xany.window);
-            /* check to make sure we're not ignoring the same event multiple
-               times */
-            if (win && WINDOW_IS_CLIENT(win) && i >= ignore_enter_focus)
-                ++ignore_enter_focus;
-            
-            saved = g_slist_append(saved, e);
-            ++i;
-        } else {
-            g_free(e);
-            break;
-        }
+        /* 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;
     }
     }
-    /* put the events back */
-    for (it = saved; it; it = g_slist_next(it)) {
-        XPutBackEvent(ob_display, it->data);
-        g_free(it->data);
+    return False; /* don't disrupt the queue order, just count them */
+}
+
+void event_ignore_all_queued_enters()
+{
+    XEvent e;
+
+    XSync(ob_display, FALSE);
+
+    /* count the events without disrupting them */
+    ignore_enter_focus = 0;
+    XCheckIfEvent(ob_display, &e, event_look_for_enters, NULL);
+}
+
+static gboolean is_enter_focus_event_ignored(XEvent *e)
+{
+    g_assert(e->type == EnterNotify &&
+             !(e->xcrossing.mode == NotifyGrab ||
+               e->xcrossing.mode == NotifyUngrab ||
+               e->xcrossing.detail == NotifyInferior));
+
+    ob_debug_type(OB_DEBUG_FOCUS, "# enters ignored: %d\n",
+                  ignore_enter_focus);
+
+    if (ignore_enter_focus) {
+        --ignore_enter_focus;
+        return TRUE;
     }
     }
-    g_slist_free(saved);
+    return FALSE;
 }
 
 gboolean event_time_after(Time t1, Time t2)
 }
 
 gboolean event_time_after(Time t1, Time t2)
This page took 0.040209 seconds and 4 git commands to generate.