Merge branch 'backport' into work
[mikachu/openbox.git] / openbox / client.c
index 7c23e8e..e9443d4 100644 (file)
@@ -414,6 +414,12 @@ void client_manage(Window window, ObPrompt *prompt)
                   activate ? "yes" : "no");
     if (activate) {
         gboolean raise = FALSE;
+        gboolean relative_focused = FALSE;
+
+        relative_focused = (focus_client != NULL &&
+                            client_search_focus_tree_full(self) != NULL &&
+                            client_search_focus_group_full(self) != NULL);
+
 
         /* This is focus stealing prevention */
         ob_debug_type(OB_DEBUG_FOCUS,
@@ -444,10 +450,8 @@ void client_manage(Window window, ObPrompt *prompt)
                           "Not focusing the window because its on another "
                           "desktop");
         }
-        /* If something is focused, and it's not our relative... */
-        else if (focus_client && client_search_focus_tree_full(self) == NULL &&
-                 client_search_focus_group_full(self) == NULL)
-        {
+        /* If something is focused... */
+        else if (focus_client) {
             /* If the user is working in another window right now, then don't
                steal focus */
             if (event_last_user_time && launch_time &&
@@ -461,8 +465,9 @@ void client_manage(Window window, ObPrompt *prompt)
                               "Not focusing the window because the user is "
                               "working in another window");
             }
-            /* If it's a transient (and its parents aren't focused) */
-            else if (client_has_parent(self)) {
+            /* If the new window is a transient (and its relatives aren't
+               focused) */
+            else if (client_has_parent(self) && !relative_focused) {
                 activate = FALSE;
                 ob_debug_type(OB_DEBUG_FOCUS,
                               "Not focusing the window because it is a "
@@ -488,8 +493,11 @@ void client_manage(Window window, ObPrompt *prompt)
                               "Not focusing the window because another window "
                               "would get the focus anyway");
             }
+            /* Don't move focus if the window is not visible on the current
+               desktop and none of its relatives are focused */
             else if (!(self->desktop == screen_desktop ||
-                       self->desktop == DESKTOP_ALL))
+                       self->desktop == DESKTOP_ALL) &&
+                     !relative_focused)
             {
                 activate = FALSE;
                 raise = TRUE;
@@ -562,7 +570,7 @@ void client_manage(Window window, ObPrompt *prompt)
     ob_debug("Managed window 0x%lx plate 0x%x (%s)",
              window, self->frame->window, self->class);
 
-    hooks_run(OB_HOOK_WIN_NEW, self);
+    hooks_queue(OB_HOOK_WIN_NEW, self);
 }
 
 
@@ -638,6 +646,7 @@ void client_unmanage(ObClient *self)
     if (!self->prompt)
         XChangeSaveSet(obt_display, self->window, SetModeDelete);
 
+    /* this can't be queued to run later */
     hooks_run(OB_HOOK_WIN_CLOSE, self);
 
     /* update the focus lists */
@@ -2525,7 +2534,7 @@ gboolean client_show(ObClient *self)
         */
         client_change_wm_state(self);
 
-        hooks_run(OB_HOOK_WIN_VISIBLE, self);
+        hooks_queue(OB_HOOK_WIN_VISIBLE, self);
     }
     return show;
 }
@@ -2565,7 +2574,7 @@ gboolean client_hide(ObClient *self)
         */
         client_change_wm_state(self);
 
-        hooks_run(OB_HOOK_WIN_INVISIBLE, self);
+        hooks_queue(OB_HOOK_WIN_INVISIBLE, self);
     }
     return hide;
 }
@@ -3162,7 +3171,8 @@ static void client_iconify_recursive(ObClient *self,
         /* do this after starting the animation so it doesn't flash */
         client_showhide(self);
 
-        hooks_run((iconic ? OB_HOOK_WIN_ICONIC : OB_HOOK_WIN_UNICONIC), self);
+        hooks_queue((iconic ? OB_HOOK_WIN_ICONIC : OB_HOOK_WIN_UNICONIC),
+                    self);
     }
 
     /* iconify all direct transients, and deiconify all transients
@@ -3251,7 +3261,7 @@ void client_maximize(ObClient *self, gboolean max, gint dir)
     client_setup_decor_and_functions(self, FALSE);
     client_move_resize(self, x, y, w, h);
 
-    hooks_run((max ? OB_HOOK_WIN_MAX : OB_HOOK_WIN_UNMAX), self);
+    hooks_queue((max ? OB_HOOK_WIN_MAX : OB_HOOK_WIN_UNMAX), self);
 }
 
 void client_shade(ObClient *self, gboolean shade)
@@ -3266,7 +3276,7 @@ void client_shade(ObClient *self, gboolean shade)
     /* resize the frame to just the titlebar */
     frame_adjust_area(self->frame, FALSE, TRUE, FALSE);
 
-    hooks_run((shade ? OB_HOOK_WIN_SHADE : OB_HOOK_WIN_UNSHADE), self);
+    hooks_queue((shade ? OB_HOOK_WIN_SHADE : OB_HOOK_WIN_UNSHADE), self);
 }
 
 static void client_ping_event(ObClient *self, gboolean dead)
@@ -3329,12 +3339,20 @@ void client_close(ObClient *self)
 #define OB_KILL_RESULT_NO 0
 #define OB_KILL_RESULT_YES 1
 
-static void client_kill_requested(ObPrompt *p, gint result, gpointer data)
+static gboolean client_kill_requested(ObPrompt *p, gint result, gpointer data)
 {
     ObClient *self = data;
 
     if (result == OB_KILL_RESULT_YES)
         client_kill(self);
+    return TRUE; /* call the cleanup func */
+}
+
+static void client_kill_cleanup(ObPrompt *p, gpointer data)
+{
+    ObClient *self = data;
+
+    g_assert(p == self->kill_prompt);
 
     prompt_unref(self->kill_prompt);
     self->kill_prompt = NULL;
@@ -3381,11 +3399,13 @@ static void client_prompt_kill(ObClient *self)
         answers[0].text = _("Cancel");  /* "no" */
         answers[1].text = y;            /* "yes" */
 
-        self->kill_prompt = prompt_new(m, answers,
+        self->kill_prompt = prompt_new(m, NULL, answers,
                                        sizeof(answers)/sizeof(answers[0]),
                                        OB_KILL_RESULT_NO, /* default = no */
                                        OB_KILL_RESULT_NO, /* cancel = no */
-                                       client_kill_requested, self);
+                                       client_kill_requested,
+                                       client_kill_cleanup,
+                                       self);
         g_free(m);
     }
 
@@ -3470,7 +3490,7 @@ static void client_set_desktop_recursive(ObClient *self,
             client_reconfigure(self, FALSE);
 
         if (old != self->desktop)
-            hooks_run(OB_HOOK_WIN_DESK_CHANGE, self);
+            hooks_queue(OB_HOOK_WIN_DESK_CHANGE, self);
     }
 
     /* move all transients */
@@ -3874,8 +3894,8 @@ void client_set_undecorated(ObClient *self, gboolean undecorated)
         client_setup_decor_and_functions(self, TRUE);
         client_change_state(self); /* reflect this in the state hints */
 
-        hooks_run((undecorated ?
-                   OB_HOOK_WIN_UNDECORATED : OB_HOOK_WIN_DECORATED), self);
+        hooks_queue((undecorated ?
+                     OB_HOOK_WIN_UNDECORATED : OB_HOOK_WIN_DECORATED), self);
     }
 }