]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
hide titlebar buttons if that won't move other buttons
[chaz/openbox] / openbox / client.c
index 3b66a836f629d17b8903fa0546e68ee639b8bcda..ded81e3893a843eb2c24e3787de80457a8d9b83e 100644 (file)
 
 typedef struct
 {
-    ObClientDestructor func;
+    ObClientCallback func;
     gpointer data;
-} Destructor;
+} ClientCallback;
 
-GList            *client_list        = NULL;
+GList            *client_list          = NULL;
 
-static GSList *client_destructors    = NULL;
+static GSList *client_destructors      = NULL;
 
 static void client_get_all(ObClient *self);
 static void client_toggle_border(ObClient *self, gboolean show);
@@ -105,20 +105,20 @@ void client_shutdown(gboolean reconfig)
 {
 }
 
-void client_add_destructor(ObClientDestructor func, gpointer data)
+void client_add_destructor(ObClientCallback func, gpointer data)
 {
-    Destructor *d = g_new(Destructor, 1);
+    ClientCallback *d = g_new(ClientCallback, 1);
     d->func = func;
     d->data = data;
     client_destructors = g_slist_prepend(client_destructors, d);
 }
 
-void client_remove_destructor(ObClientDestructor func)
+void client_remove_destructor(ObClientCallback func)
 {
     GSList *it;
 
     for (it = client_destructors; it; it = g_slist_next(it)) {
-        Destructor *d = it->data;
+        ClientCallback *d = it->data;
         if (d->func == func) {
             g_free(d);
             client_destructors = g_slist_delete_link(client_destructors, it);
@@ -533,7 +533,7 @@ void client_unmanage(ObClient *self)
         screen_update_areas();
 
     for (it = client_destructors; it; it = g_slist_next(it)) {
-        Destructor *d = it->data;
+        ClientCallback *d = it->data;
         d->func(self, d->data);
     }
 
@@ -1254,11 +1254,13 @@ static void client_update_transient_tree(ObClient *self,
     }
             
 
-    /* If the group changed then we need to remove any old group transient
-       windows from our children. But if we're transient for the group, then
+    /* If the group changed, or if we are just becoming transient for the
+       group, then we need to remove any old group transient windows
+       from our children. But if we were already transient for the group, then
        other group transients are not our children. */
-    if (oldgroup != newgroup && oldgroup != NULL &&
-        oldparent != OB_TRAN_GROUP)
+    if ((oldgroup != newgroup ||
+         (newparent == OB_TRAN_GROUP && oldparent != newparent)) &&
+        oldgroup != NULL && oldparent != OB_TRAN_GROUP)
     {
         for (it = self->transients; it; it = next) {
             next = g_slist_next(it);
@@ -1573,10 +1575,15 @@ void client_setup_decor_and_functions(ObClient *self)
         self->functions &= ~(OB_CLIENT_FUNC_ICONIFY | OB_CLIENT_FUNC_RESIZE);
         break;
 
+    case OB_CLIENT_TYPE_SPLASH:
+        /* these don't get get any decorations, and the only thing you can
+           do with them is move them */
+        self->decorations = 0;
+        self->functions = OB_CLIENT_FUNC_MOVE;
+
     case OB_CLIENT_TYPE_DESKTOP:
     case OB_CLIENT_TYPE_DOCK:
-    case OB_CLIENT_TYPE_SPLASH:
-        /* none of these windows are manipulated by the window manager */
+        /* these windows are not manipulated by the window manager */
         self->decorations = 0;
         self->functions = 0;
         break;
@@ -2361,12 +2368,29 @@ gboolean client_normal(ObClient *self) {
               self->type == OB_CLIENT_TYPE_SPLASH);
 }
 
-gboolean client_application(ObClient *self)
+gboolean client_helper(ObClient *self)
+{
+    return (self->type == OB_CLIENT_TYPE_UTILITY ||
+            self->type == OB_CLIENT_TYPE_MENU ||
+            self->type == OB_CLIENT_TYPE_TOOLBAR);
+}
+
+gboolean client_mouse_focusable(ObClient *self)
+{
+    return !(self->type == OB_CLIENT_TYPE_MENU ||
+             self->type == OB_CLIENT_TYPE_TOOLBAR ||
+             self->type == OB_CLIENT_TYPE_SPLASH ||
+             self->type == OB_CLIENT_TYPE_DOCK);
+}
+
+gboolean client_enter_focusable(ObClient *self)
 {
-    return (self->type == OB_CLIENT_TYPE_NORMAL ||
-            self->type == OB_CLIENT_TYPE_DIALOG);
+    /* you can focus desktops but it shouldn't on enter */
+    return (client_mouse_focusable(self) &&
+            self->type != OB_CLIENT_TYPE_DESKTOP);
 }
 
+
 static void client_apply_startup_state(ObClient *self, gint x, gint y)
 {
     gboolean pos = FALSE; /* has the window's position been configured? */
@@ -2771,7 +2795,9 @@ static void client_iconify_recursive(ObClient *self,
                  self->window);
 
         if (iconic) {
-            if (self->functions & OB_CLIENT_FUNC_ICONIFY) {
+            /* don't let non-normal windows iconify along with their parents
+               or whatever */
+            if (client_normal(self)) {
                 self->iconic = iconic;
 
                 /* update the focus lists.. iconic windows go to the bottom of
@@ -2814,9 +2840,11 @@ static void client_iconify_recursive(ObClient *self,
 
 void client_iconify(ObClient *self, gboolean iconic, gboolean curdesk)
 {
-    /* move up the transient chain as far as possible first */
-    self = client_search_top_normal_parent(self);
-    client_iconify_recursive(self, iconic, curdesk);
+    if (self->functions & OB_CLIENT_FUNC_ICONIFY || !iconic) {
+        /* move up the transient chain as far as possible first */
+        self = client_search_top_normal_parent(self);
+        client_iconify_recursive(self, iconic, curdesk);
+    }
 }
 
 void client_maximize(ObClient *self, gboolean max, gint dir)
@@ -2966,7 +2994,8 @@ void client_hilite(ObClient *self, gboolean hilite)
 }
 
 void client_set_desktop_recursive(ObClient *self,
-                                  guint target, gboolean donthide)
+                                  guint target,
+                                  gboolean donthide)
 {
     guint old;
     GSList *it;
@@ -2977,9 +3006,6 @@ void client_set_desktop_recursive(ObClient *self,
 
         g_assert(target < screen_num_desktops || target == DESKTOP_ALL);
 
-        /* remove from the old desktop(s) */
-        focus_order_remove(self);
-
         old = self->desktop;
         self->desktop = target;
         PROP_SET32(self->window, net_wm_desktop, cardinal, target);
@@ -2993,12 +3019,6 @@ void client_set_desktop_recursive(ObClient *self,
             client_raise(self);
         if (STRUT_EXISTS(self->strut))
             screen_update_areas();
-
-        /* add to the new desktop(s) */
-        if (config_focus_new)
-            focus_order_to_top(self);
-        else
-            focus_order_to_bottom(self);
     }
 
     /* move all transients */
@@ -3008,7 +3028,8 @@ void client_set_desktop_recursive(ObClient *self,
                 client_set_desktop_recursive(it->data, target, donthide);
 }
 
-void client_set_desktop(ObClient *self, guint target, gboolean donthide)
+void client_set_desktop(ObClient *self, guint target,
+                        gboolean donthide)
 {
     self = client_search_top_normal_parent(self);
     client_set_desktop_recursive(self, target, donthide);
@@ -3074,6 +3095,8 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
     gboolean modal = self->modal;
     gboolean iconic = self->iconic;
     gboolean demands_attention = self->demands_attention;
+    gboolean above = self->above;
+    gboolean below = self->below;
     gint i;
 
     if (!(action == prop_atoms.net_wm_state_add ||
@@ -3150,11 +3173,11 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
             } else if (state == prop_atoms.net_wm_state_fullscreen) {
                 fullscreen = TRUE;
             } else if (state == prop_atoms.net_wm_state_above) {
-                self->above = TRUE;
-                self->below = FALSE;
+                above = TRUE;
+                below = FALSE;
             } else if (state == prop_atoms.net_wm_state_below) {
-                self->above = FALSE;
-                self->below = TRUE;
+                above = FALSE;
+                below = TRUE;
             } else if (state == prop_atoms.net_wm_state_demands_attention) {
                 demands_attention = TRUE;
             } else if (state == prop_atoms.openbox_wm_state_undecorated) {
@@ -3179,9 +3202,9 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
             } else if (state == prop_atoms.net_wm_state_fullscreen) {
                 fullscreen = FALSE;
             } else if (state == prop_atoms.net_wm_state_above) {
-                self->above = FALSE;
+                above = FALSE;
             } else if (state == prop_atoms.net_wm_state_below) {
-                self->below = FALSE;
+                below = FALSE;
             } else if (state == prop_atoms.net_wm_state_demands_attention) {
                 demands_attention = FALSE;
             } else if (state == prop_atoms.openbox_wm_state_undecorated) {
@@ -3226,6 +3249,12 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
     if (demands_attention != self->demands_attention)
         client_hilite(self, demands_attention);
 
+    if (above != self->above || below != self->below) {
+        self->above = above;
+        self->below = below;
+        client_calc_layer(self);
+    }
+
     client_change_state(self); /* change the hint to reflect these changes */
 }
 
@@ -3370,29 +3399,56 @@ static void client_present(ObClient *self, gboolean here, gboolean raise)
 void client_activate(ObClient *self, gboolean here, gboolean user)
 {
     guint32 last_time = focus_client ? focus_client->user_time : CurrentTime;
+    gboolean allow = FALSE;
 
-    /* XXX do some stuff here if user is false to determine if we really want
-       to activate it or not (a parent or group member is currently
-       active)?
+    /* if the request came from the user, or if nothing is focused, then grant
+       the request.
+       if the currently focused app doesn't set a user_time, then it can't
+       benefit from any focus stealing prevention.
     */
+    if (user || !focus_client || !last_time)
+        allow = TRUE;
+    /* otherwise, if they didn't give a time stamp or if it is too old, they
+       don't get focus */
+    else
+        allow = event_curtime && event_time_after(event_curtime, last_time);
+
     ob_debug_type(OB_DEBUG_FOCUS,
                   "Want to activate window 0x%x with time %u (last time %u), "
-                  "source=%s\n",
+                  "source=%s allowing? %d\n",
                   self->window, event_curtime, last_time,
-                  (user ? "user" : "application"));
+                  (user ? "user" : "application"), allow);
 
-    if (!user && event_curtime && last_time &&
-        !event_time_after(event_curtime, last_time))
-    {
-        client_hilite(self, TRUE);
-    } else {
+    if (allow) {
         if (event_curtime != CurrentTime)
             self->user_time = event_curtime;
 
         client_present(self, here, TRUE);
+    } else
+        /* don't focus it but tell the user it wants attention */
+        client_hilite(self, TRUE);
+}
+
+static void client_bring_helper_windows_recursive(ObClient *self,
+                                                  guint desktop)
+{
+    GSList *it;
+
+    for (it = self->transients; it; it = g_slist_next(it))
+        client_bring_helper_windows_recursive(it->data, desktop);
+
+    if (client_helper(self) &&
+        self->desktop != desktop && self->desktop != DESKTOP_ALL)
+    {
+        client_set_desktop(self, desktop, FALSE);
     }
 }
 
+void client_bring_helper_windows(ObClient *self)
+{
+    client_bring_helper_windows_recursive(self, self->desktop);
+}
+
 void client_raise(ObClient *self)
 {
     action_run_string("Raise", self, CurrentTime);
@@ -3826,17 +3882,3 @@ gboolean client_has_group_siblings(ObClient *self)
 {
     return self->group && self->group->members->next;
 }
-
-gboolean client_has_application_group_siblings(ObClient *self)
-{
-    GSList *it;
-
-    if (!self->group) return FALSE;
-
-    for (it = self->group->members; it; it = g_slist_next(it)) {
-        ObClient *c = it->data;
-        if (c != self && client_application(c))
-            return TRUE;
-    }
-    return FALSE;
-}
This page took 0.028037 seconds and 4 git commands to generate.