]> Dogcows Code - chaz/openbox/blobdiff - openbox/event.c
some repositioning of frame elements for maximized windows.
[chaz/openbox] / openbox / event.c
index 383b260136ca6e80dfb1c94de7b21515ca2f4283..ac0e6ff2efc567ffb972f3aec0c97ca4fba1a9e8 100644 (file)
@@ -38,6 +38,7 @@
 #include "mainloop.h"
 #include "framerender.h"
 #include "focus.h"
+#include "focus_cycle.h"
 #include "moveresize.h"
 #include "group.h"
 #include "stacking.h"
@@ -97,11 +98,7 @@ static gboolean menu_hide_delay_func(gpointer data);
 /* 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;
 
@@ -775,7 +772,8 @@ static void event_handle_client(ObClient *client, XEvent *e)
         {
             /* 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;
@@ -812,6 +810,8 @@ static void event_handle_client(ObClient *client, XEvent *e)
                             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 ||
@@ -863,6 +863,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) {
+        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);
@@ -888,7 +904,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))
-                event_ignore_enters_leaving_window(client);
+                event_ignore_all_queued_enters();
 
             ob_debug_type(OB_DEBUG_FOCUS,
                           "%sNotify mode %d detail %d on %lx\n",
@@ -914,11 +930,6 @@ static void event_handle_client(ObClient *client, XEvent *e)
         break;
     case EnterNotify:
     {
-        gboolean nofocus = FALSE;
-
-        if (is_enter_focus_event_ignored(e))
-            nofocus = TRUE;
-
         con = frame_context(client, e->xcrossing.window,
                             e->xcrossing.x, e->xcrossing.y);
         switch (con) {
@@ -948,22 +959,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 */
-                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);
-            } else {
+            }
+            else {
                 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->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;
@@ -1087,7 +1099,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
             client_configure(client, x, y, w, h, FALSE, TRUE);
 
             /* ignore enter events caused by these like ob actions do */
-            event_ignore_enters_leaving_window(client);
+            event_ignore_all_queued_enters();
         }
         break;
     }
@@ -1183,7 +1195,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 */
-            event_ignore_enters_leaving_window(client);
+            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);
@@ -1271,7 +1283,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
             client_configure(client, x, y, w, h, FALSE, TRUE);
 
             /* ignore enter events caused by these like ob actions do */
-            event_ignore_enters_leaving_window(client);
+            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,
@@ -1281,8 +1293,8 @@ static void event_handle_client(ObClient *client, XEvent *e)
             } 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)
                     {
@@ -1489,8 +1501,11 @@ static gboolean event_handle_menu_keyboard(XEvent *ev)
         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 ||
@@ -1614,6 +1629,10 @@ static gboolean event_handle_menu(XEvent *ev)
         }
         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)
@@ -1720,87 +1739,48 @@ void event_halt_focus_delay()
     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)
 {
-    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))
+    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;
-        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;
-        }
+        /* 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;
     }
     return False; /* don't disrupt the queue order, just count them */
 }
 
 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;
-    lfe.c = c;
-    lfe.looking_for_enter = 0;
-    XCheckIfEvent(ob_display, &e, event_look_for_enters, (XPointer)&lfe);
-
+    XCheckIfEvent(ob_display, &e, event_look_for_enters, NULL);
 }
 
 static gboolean is_enter_focus_event_ignored(XEvent *e)
 {
-    g_assert(e->type == EnterNotify);
+    g_assert(e->type == EnterNotify &&
+             !(e->xcrossing.mode == NotifyGrab ||
+               e->xcrossing.mode == NotifyUngrab ||
+               e->xcrossing.detail == NotifyInferior));
 
-    if (ignore_enter_focus) {
-        gint i;
+    ob_debug_type(OB_DEBUG_FOCUS, "# enters ignored: %d\n",
+                  ignore_enter_focus);
 
+    if (ignore_enter_focus) {
         --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;
This page took 0.03031 seconds and 4 git commands to generate.