merge r6904-6915 from trunk
authorDana Jansens <danakj@orodu.net>
Sat, 26 May 2007 22:29:33 +0000 (22:29 +0000)
committerDana Jansens <danakj@orodu.net>
Sat, 26 May 2007 22:29:33 +0000 (22:29 +0000)
doc/rc-mouse-focus.xml
openbox/action.c
openbox/client.c
openbox/event.c
openbox/event.h
openbox/focus.c
openbox/focus_cycle.c
openbox/focus_cycle.h
openbox/keyboard.c
tests/focusout.c

index e5f327e131682ff54f3d7dfc311c28e979d5ab6f..af62b260a28f2d54542557265398fe8d97e2b5bb 100644 (file)
       <action name="Resize"/>
     </mousebind> 
 
-    <mousebind button="A-Middle" action="Click">
+    <mousebind button="A-Middle" action="Press">
       <action name="Focus"/>
       <action name="Lower"/>
     </mousebind>
 
     <mousebind button="Middle" action="Press">
       <action name="Focus"/>
-    </mousebind>
-    <mousebind button="Middle" action="Click">
       <action name="Lower"/>
     </mousebind>
 
 
     <mousebind button="Middle" action="Press">
       <action name="Focus"/>
-    </mousebind>
-    <mousebind button="Middle" action="Click">
       <action name="Lower"/>
     </mousebind>
 
index faf065a12fedd0bf10057a27b7f14a2a43ff0efa..39da39a5b7842ec4159545abd1f3ddf9ad7f7ef5 100644 (file)
@@ -47,17 +47,18 @@ static void client_action_end(union ActionData *data)
 {
     if (config_focus_follow)
         if (data->any.context != OB_FRAME_CONTEXT_CLIENT) {
-            if (!data->any.button && data->any.c)
+            if (!data->any.button && data->any.c) {
                 event_ignore_all_queued_enters();
-            else {
-                /* we USED to create a fake enter event here, so that when you
-                   used a Press context, and the button was still down,
-                   you could still get enter events that weren't
-                   NotifyWhileGrabbed.
-
-                   only problem with this is that then the resulting focus
-                   change events can ALSO be NotifyWhileGrabbed. And that is
-                   bad. So, don't create fake enter events anymore. */
+            } else {
+                ObClient *c;
+
+                /* usually this is sorta redundant, but with a press action
+                   that moves windows our from under the cursor, the enter
+                   event will come as a GrabNotify which is ignored, so this
+                   makes a fake enter event
+                */
+                if ((c = client_under_pointer()))
+                    event_enter_client(c);
             }
         }
 }
@@ -1215,11 +1216,9 @@ void action_execute(union ActionData *data)
     if (data->execute.path) {
         cmd = g_filename_from_utf8(data->execute.path, -1, NULL, NULL, NULL);
         if (cmd) {
-            /* If there is an interactive action going on, then cancel it
-               to release the keyboard, so that the run application
-               can grab the keyboard if it wants to. */
-            if (keyboard_interactively_grabbed())
-                keyboard_interactive_cancel();
+            /* If there is a keyboard grab going on then we need to cancel
+               it so the application can grab things */
+            event_cancel_all_key_grabs();
 
             if (!g_shell_parse_argv (cmd, NULL, &argv, &e)) {
                 g_message(_("Failed to execute '%s': %s"),
index ffbcd5cae8c7074f08d3e99ea3a762e23246558a..9c679fee9e2f9e3f56765be5f670e6c2c79ab119 100644 (file)
@@ -2540,8 +2540,7 @@ gboolean client_hide(ObClient *self)
                actions should not rely on being able to move focus during an
                interactive grab.
             */
-            if (keyboard_interactively_grabbed())
-                keyboard_interactive_cancel();
+            event_cancel_all_key_grabs();
         }
 
         frame_hide(self->frame);
@@ -2932,7 +2931,7 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
         event.xconfigure.y = self->root_pos.y;
         event.xconfigure.width = w;
         event.xconfigure.height = h;
-        event.xconfigure.border_width = 0;
+        event.xconfigure.border_width = self->border_width;
         event.xconfigure.above = self->frame->plate;
         event.xconfigure.override_redirect = FALSE;
         XSendEvent(event.xconfigure.display, event.xconfigure.window,
@@ -3526,8 +3525,7 @@ gboolean client_focus(ObClient *self)
        actions should not rely on being able to move focus during an
        interactive grab.
     */
-    if (keyboard_interactively_grabbed())
-        keyboard_interactive_cancel();
+    event_cancel_all_key_grabs();
 
     xerror_set_ignore(TRUE);
     xerror_occured = FALSE;
index cb739339e6d8b961bb9c653b1e90f3e4f17626d7..e7ef27fb3058b1ab7ca6942c3a582463cde39d32 100644 (file)
@@ -1837,6 +1837,25 @@ static gboolean is_enter_focus_event_ignored(XEvent *e)
     return FALSE;
 }
 
+void event_cancel_all_key_grabs()
+{
+    if (keyboard_interactively_grabbed())
+        keyboard_interactive_cancel();
+    else if (menu_frame_visible)
+        menu_frame_hide_all();
+    else if (grab_on_keyboard())
+        ungrab_keyboard();
+    else
+        /* If we don't have the keyboard grabbed, then ungrab it with
+           XUngrabKeyboard, so that there is not a passive grab left
+           on from the KeyPress. If the grab is left on, and focus
+           moves during that time, it will be NotifyWhileGrabbed, and
+           applications like to ignore those! */
+        if (!keyboard_interactively_grabbed())
+            XUngrabKeyboard(ob_display, CurrentTime);
+
+}
+
 gboolean event_time_after(Time t1, Time t2)
 {
     g_assert(t1 != CurrentTime);
index 542115fb6d4b1e9102dc062a8ecbbc5f61abd1fe..29f621d5d6bb6b54f582c8375fb01e7b9a9ac1ee 100644 (file)
@@ -43,6 +43,9 @@ void event_enter_client(struct _ObClient *client);
   till now. */
 void event_ignore_all_queued_enters();
 
+/*! End *all* active and passive grabs on the keyboard */
+void event_cancel_all_key_grabs();
+
 /* Halts any focus delay in progress, use this when the user is selecting a
    window for focus */
 void event_halt_focus_delay();
index fad53e92dcf67897f927076129ce3f2465f44ad6..6713d98dd7566535fe8d81cb5d4d0e0a502af652 100644 (file)
@@ -75,7 +75,8 @@ void focus_set_client(ObClient *client)
     screen_install_colormap(client, TRUE);
 
     /* in the middle of cycling..? kill it. */
-    focus_cycle_stop();
+    focus_cycle_stop(focus_client);
+    focus_cycle_stop(client);
 
     focus_client = client;
 
@@ -193,9 +194,30 @@ void focus_nothing()
                    event_curtime);
 }
 
+void focus_order_add_new(ObClient *c)
+{
+    if (c->iconic)
+        focus_order_to_top(c);
+    else {
+        g_assert(!g_list_find(focus_order, c));
+        /* if there are any iconic windows, put this above them in the order,
+           but if there are not, then put it under the currently focused one */
+        if (focus_order && ((ObClient*)focus_order->data)->iconic)
+            focus_order = g_list_insert(focus_order, c, 0);
+        else
+            focus_order = g_list_insert(focus_order, c, 1);
+    }
+
+    /* in the middle of cycling..? kill it. */
+    focus_cycle_stop(c);
+}
+
 void focus_order_remove(ObClient *c)
 {
     focus_order = g_list_remove(focus_order, c);
+
+    /* in the middle of cycling..? kill it. */
+    focus_cycle_stop(c);
 }
 
 void focus_order_to_top(ObClient *c)
index 4c0630b30abe39fc2edf0def2e5bccb12b99d195..46f5f058daff1bf5424973dec9693807ff5708e2 100644 (file)
 #include <X11/Xlib.h>
 #include <glib.h>
 
-ObClient     *focus_cycle_target = NULL;
+ObClient       *focus_cycle_target = NULL;
+static gboolean focus_cycle_iconic_windows;
+static gboolean focus_cycle_all_desktops;
+static gboolean focus_cycle_dock_windows;
+static gboolean focus_cycle_desktop_windows;
 
-static void      focus_cycle_destroy_notify (ObClient *client, gpointer data);
 static gboolean  focus_target_has_siblings  (ObClient *ft,
                                              gboolean iconic_windows,
                                              gboolean all_desktops);
@@ -49,30 +52,27 @@ static ObClient *focus_find_directional    (ObClient *c,
 void focus_cycle_startup(gboolean reconfig)
 {
     if (reconfig) return;
-
-    client_add_destroy_notify(focus_cycle_destroy_notify, NULL);
 }
 
 void focus_cycle_shutdown(gboolean reconfig)
 {
     if (reconfig) return;
-
-    client_remove_destroy_notify(focus_cycle_destroy_notify);
-}
-
-void focus_cycle_stop()
-{
-    if (focus_cycle_target)
-        focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
 }
 
-static void focus_cycle_destroy_notify(ObClient *client, gpointer data)
+void focus_cycle_stop(ObClient *ifclient)
 {
-    /* end cycling if the target disappears. CurrentTime is fine, time won't
-       be used
-    */
-    if (focus_cycle_target == client)
+    /* stop focus cycling if the given client is a valid focus target,
+       and so the cycling is being disrupted */
+    if (focus_cycle_target && ifclient &&
+        focus_cycle_target_valid(ifclient,
+                                 focus_cycle_iconic_windows,
+                                 focus_cycle_all_desktops,
+                                 focus_cycle_dock_windows,
+                                 focus_cycle_desktop_windows))
+    {
         focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
+        focus_directional_cycle(0, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
+    }
 }
 
 /*! Returns if a focus target has valid group siblings that can be cycled
@@ -185,7 +185,15 @@ void focus_cycle(gboolean forward, gboolean all_desktops,
             goto done_cycle;
         list = client_list;
     }
-    if (!focus_cycle_target) focus_cycle_target = focus_client;
+
+
+    if (focus_cycle_target == NULL) {
+        focus_cycle_iconic_windows = TRUE;
+        focus_cycle_all_desktops = all_desktops;
+        focus_cycle_dock_windows = dock_windows;
+        focus_cycle_desktop_windows = desktop_windows;
+        focus_cycle_target = focus_client;
+    }
 
     start = it = g_list_find(list, focus_cycle_target);
     if (!start) /* switched desktops or something? */
@@ -201,9 +209,11 @@ void focus_cycle(gboolean forward, gboolean all_desktops,
             if (it == NULL) it = g_list_last(list);
         }
         ft = it->data;
-        if (focus_cycle_target_valid(ft, TRUE,
-                                     all_desktops, dock_windows,
-                                     desktop_windows))
+        if (focus_cycle_target_valid(ft,
+                                     focus_cycle_iconic_windows,
+                                     focus_cycle_all_desktops,
+                                     focus_cycle_dock_windows,
+                                     focus_cycle_desktop_windows))
         {
             if (interactive) {
                 if (ft != focus_cycle_target) { /* prevents flicker */
@@ -212,9 +222,11 @@ void focus_cycle(gboolean forward, gboolean all_desktops,
                 }
                 if (dialog)
                     /* same arguments as focus_target_valid */
-                    focus_cycle_popup_show(ft, TRUE,
-                                           all_desktops, dock_windows,
-                                           desktop_windows);
+                    focus_cycle_popup_show(ft,
+                                           focus_cycle_iconic_windows,
+                                           focus_cycle_all_desktops,
+                                           focus_cycle_dock_windows,
+                                           focus_cycle_desktop_windows);
                 return;
             } else if (ft != focus_cycle_target) {
                 focus_cycle_target = ft;
@@ -355,8 +367,15 @@ void focus_directional_cycle(ObDirection dir, gboolean dock_windows,
     if (!focus_order)
         goto done_cycle;
 
+    if (focus_cycle_target == NULL) {
+        focus_cycle_iconic_windows = FALSE;
+        focus_cycle_all_desktops = FALSE;
+        focus_cycle_dock_windows = dock_windows;
+        focus_cycle_desktop_windows = desktop_windows;
+        focus_cycle_target = focus_client;
+    }
+
     if (!first) first = focus_client;
-    if (!focus_cycle_target) focus_cycle_target = focus_client;
 
     if (focus_cycle_target)
         ft = focus_find_directional(focus_cycle_target, dir, dock_windows,
@@ -365,8 +384,11 @@ void focus_directional_cycle(ObDirection dir, gboolean dock_windows,
         GList *it;
 
         for (it = focus_order; it; it = g_list_next(it))
-            if (focus_cycle_target_valid(it->data, FALSE, FALSE, dock_windows,
-                                         desktop_windows))
+            if (focus_cycle_target_valid(it->data,
+                                         focus_cycle_iconic_windows,
+                                         focus_cycle_all_desktops,
+                                         focus_cycle_dock_windows,
+                                         focus_cycle_desktop_windows))
                 ft = it->data;
     }
         
@@ -379,8 +401,10 @@ void focus_directional_cycle(ObDirection dir, gboolean dock_windows,
     if (focus_cycle_target && dialog) {
         /* same arguments as focus_target_valid */
         focus_cycle_popup_single_show(focus_cycle_target,
-                                      FALSE, FALSE, dock_windows,
-                                      desktop_windows);
+                                      focus_cycle_iconic_windows,
+                                      focus_cycle_all_desktops,
+                                      focus_cycle_dock_windows,
+                                      focus_cycle_desktop_windows);
         return;
     }
 
@@ -396,19 +420,3 @@ done_cycle:
 
     return;
 }
-
-void focus_order_add_new(ObClient *c)
-{
-    if (c->iconic)
-        focus_order_to_top(c);
-    else {
-        g_assert(!g_list_find(focus_order, c));
-        /* if there are any iconic windows, put this above them in the order,
-           but if there are not, then put it under the currently focused one */
-        if (focus_order && ((ObClient*)focus_order->data)->iconic)
-            focus_order = g_list_insert(focus_order, c, 0);
-        else
-            focus_order = g_list_insert(focus_order, c, 1);
-    }
-}
-
index 38c0e8371c95e2e8d8884ebf6cd493ecca59efe6..afdbdc799d049015d7589f582f2a89173424b5e0 100644 (file)
@@ -42,7 +42,7 @@ void focus_directional_cycle(ObDirection dir, gboolean dock_windows,
                              gboolean desktop_windows, gboolean interactive,
                              gboolean dialog, gboolean done, gboolean cancel);
 
-void focus_cycle_stop();
+void focus_cycle_stop(struct _ObClient *ifclient);
 
 gboolean  focus_cycle_target_valid(struct _ObClient *ft,
                                    gboolean iconic_windows,
index 2c60ac3d4f632e14c195eb0c1ce0380483b94263..218e251accebbdf69476e157246abfdf9dc73a09 100644 (file)
@@ -311,14 +311,6 @@ void keyboard_event(ObClient *client, const XEvent *e)
             else {
                 keyboard_reset_chains(0);
 
-                /* If we don't have the keyboard grabbed, then ungrab it with
-                   XUngrabKeyboard, so that there is not a passive grab left
-                   on from the KeyPress. If the grab is left on, and focus
-                   moves during that time, it will be NotifyWhileGrabbed, and
-                   applications like to ignore those! */
-                if (!keyboard_interactively_grabbed())
-                    XUngrabKeyboard(ob_display, e->xkey.time);
-
                 action_run_key(p->actions, client, e->xkey.state,
                                e->xkey.x_root, e->xkey.y_root,
                                e->xkey.time);
index 1f31a8aa9084ea930a9a01c792c2226ee5659546..1cc7259d09c255a266a9ab5ec9b006326077aa08 100644 (file)
@@ -47,7 +47,8 @@ int main () {
     XSetWindowBackground(display,win,WhitePixel(display,0)); 
     XSetWindowBackground(display,child,BlackPixel(display,0)); 
 
-    XSelectInput(display, win, FocusChangeMask);
+    XSelectInput(display, win,
+                 FocusChangeMask|EnterWindowMask|LeaveWindowMask);
     XMapWindow(display, win);
     XMapWindow(display, child);
 
@@ -157,8 +158,62 @@ int main () {
             printf("mode      : %s\n", mode);
             printf("detail    : %s\n", detail);
             printf("---\n");
-        }
+            break;
+        case EnterNotify:
+            switch (report.xcrossing.mode) {
+            case NotifyNormal: mode = "NotifyNormal"; break;
+            case NotifyGrab: mode = "NotifyGrab"; break;
+            case NotifyUngrab: mode = "NotifyUngrab"; break;
+            }
+
+            switch (report.xcrossing.detail) {
+            case NotifyAncestor: detail = "NotifyAncestor"; break;
+            case NotifyVirtual: detail = "NotifyVirtual"; break;
+            case NotifyInferior: detail = "NotifyInferior"; break;
+            case NotifyNonlinear: detail = "NotifyNonlinear"; break;
+            case NotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break;
+            case NotifyPointer: detail = "NotifyPointer"; break;
+            case NotifyPointerRoot: detail = "NotifyPointerRoot"; break;
+            case NotifyDetailNone: detail = "NotifyDetailNone"; break;
+            }
+            printf("enternotify\n");
+            printf("type      : %d\n", report.xcrossing.type);
+            printf("serial    : %d\n", report.xcrossing.serial);
+            printf("send_event: %d\n", report.xcrossing.send_event);
+            printf("display   : 0x%x\n", report.xcrossing.display);
+            printf("window    : 0x%x\n", report.xcrossing.window);
+            printf("mode      : %s\n", mode);
+            printf("detail    : %s\n", detail);
+            printf("---\n");
+            break;
+        case LeaveNotify:
+            switch (report.xcrossing.mode) {
+            case NotifyNormal: mode = "NotifyNormal"; break;
+            case NotifyGrab: mode = "NotifyGrab"; break;
+            case NotifyUngrab: mode = "NotifyUngrab"; break;
+            }
 
+            switch (report.xcrossing.detail) {
+            case NotifyAncestor: detail = "NotifyAncestor"; break;
+            case NotifyVirtual: detail = "NotifyVirtual"; break;
+            case NotifyInferior: detail = "NotifyInferior"; break;
+            case NotifyNonlinear: detail = "NotifyNonlinear"; break;
+            case NotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break;
+            case NotifyPointer: detail = "NotifyPointer"; break;
+            case NotifyPointerRoot: detail = "NotifyPointerRoot"; break;
+            case NotifyDetailNone: detail = "NotifyDetailNone"; break;
+            }
+            printf("leavenotify\n");
+            printf("type      : %d\n", report.xcrossing.type);
+            printf("serial    : %d\n", report.xcrossing.serial);
+            printf("send_event: %d\n", report.xcrossing.send_event);
+            printf("display   : 0x%x\n", report.xcrossing.display);
+            printf("window    : 0x%x\n", report.xcrossing.window);
+            printf("mode      : %s\n", mode);
+            printf("detail    : %s\n", detail);
+            printf("---\n");
+            break;
+        }
     }
 
     return 1;