Add a strict option to the ToggleShowDesktop action
authorDana Jansens <danakj@orodu.net>
Sun, 8 Sep 2013 17:39:59 +0000 (13:39 -0400)
committerDana Jansens <danakj@orodu.net>
Mon, 9 Sep 2013 14:47:43 +0000 (10:47 -0400)
When the strict option is used, normal windows are not able to show themselves
while showing the desktop.

data/rc.xsd
openbox/actions/showdesktop.c
openbox/client.c
openbox/event.c
openbox/place.c
openbox/screen.c
openbox/screen.h

index 75dd660..c8f5638 100644 (file)
             <xsd:element minOccurs="0" name="here" type="ob:bool"/>
             <xsd:element minOccurs="0" name="linear" type="ob:bool"/>
             <xsd:element minOccurs="0" name="group" type="ob:bool"/>
+            <xsd:element minOccurs="0" name="strict" type="ob:bool"/>
         </xsd:all>
         <xsd:attribute name="name" type="ob:actionname" use="required"/>
     </xsd:complexType>
index 6dc77d5..3c3b2d1 100644 (file)
@@ -1,17 +1,52 @@
 #include "openbox/actions.h"
 #include "openbox/screen.h"
 
+typedef struct {
+    /* If true, windows are unable to be shown while in the showing-desktop
+       state. */
+    gboolean strict;
+} Options;
+
+static gpointer setup_func(xmlNodePtr node);
+static void free_func(gpointer o);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_showdesktop_startup(void)
 {
-    actions_register("ToggleShowDesktop", NULL, NULL, run_func);
+    actions_register("ToggleShowDesktop", setup_func, free_func, run_func);
+}
+
+static gpointer setup_func(xmlNodePtr node)
+{
+    xmlNodePtr n;
+    Options *o = g_slice_new0(Options);
+    o->strict = FALSE;
+
+    if ((n = obt_xml_find_node(node, "strict")))
+        o->strict = obt_xml_node_bool(n);
+
+    return o;
+}
+
+static void free_func(gpointer o)
+{
+    g_slice_free(Options, o);
 }
 
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
-    screen_show_desktop(!screen_showing_desktop, NULL);
+    Options *o = options;
+
+    ObScreenShowDestopMode show_mode;
+    if (screen_showing_desktop())
+        show_mode = SCREEN_SHOW_DESKTOP_NO;
+    else if (!o->strict)
+        show_mode = SCREEN_SHOW_DESKTOP_UNTIL_WINDOW;
+    else
+        show_mode = SCREEN_SHOW_DESKTOP_UNTIL_TOGGLE;
+
+    screen_show_desktop(show_mode, NULL);
 
     return FALSE;
 }
index 5e6569e..3ff278a 100644 (file)
@@ -2734,7 +2734,7 @@ gboolean client_should_show(ObClient *self)
 {
     if (self->iconic)
         return FALSE;
-    if (client_normal(self) && screen_showing_desktop)
+    if (client_normal(self) && screen_showing_desktop())
         return FALSE;
     if (self->desktop == screen_desktop || self->desktop == DESKTOP_ALL)
         return TRUE;
@@ -4080,7 +4080,7 @@ gboolean client_focus(ObClient *self)
 static void client_present(ObClient *self, gboolean here, gboolean raise,
                            gboolean unshade)
 {
-    if (client_normal(self) && screen_showing_desktop)
+    if (client_normal(self) && screen_showing_desktop())
         screen_show_desktop(FALSE, self);
     if (self->iconic)
         client_iconify(self, FALSE, here, FALSE);
index 1b3a0e4..31462a9 100644 (file)
@@ -772,7 +772,12 @@ static void event_handle_root(XEvent *e)
             if (d > 0 && d <= 1000)
                 screen_set_num_desktops(d);
         } else if (msgtype == OBT_PROP_ATOM(NET_SHOWING_DESKTOP)) {
-            screen_show_desktop(e->xclient.data.l[0] != 0, NULL);
+            ObScreenShowDestopMode show_mode;
+            if (e->xclient.data.l[0] != 0)
+                show_mode = SCREEN_SHOW_DESKTOP_UNTIL_WINDOW;
+            else
+                show_mode = SCREEN_SHOW_DESKTOP_NO;
+            screen_show_desktop(show_mode, NULL);
         } else if (msgtype == OBT_PROP_ATOM(OB_CONTROL)) {
             ob_debug("OB_CONTROL: %d", e->xclient.data.l[0]);
             if (e->xclient.data.l[0] == 1)
index 7d5c869..aaa1639 100644 (file)
@@ -406,8 +406,19 @@ static gboolean place_least_overlap(ObClient *c, Rect *head, int *x, int *y,
     GSList* potential_overlap_clients = NULL;
     gint n_client_rects = config_dock_hide ? 0 : 1;
 
-    /* if we're "showing desktop", ignore all existing windows */
-    if (!screen_showing_desktop) {
+    /* If we're "showing desktop", and going to allow this window to
+       be shown now, then ignore all existing windows */
+    gboolean ignore_windows = FALSE;
+    switch (screen_show_desktop_mode) {
+    case SCREEN_SHOW_DESKTOP_NO:
+    case SCREEN_SHOW_DESKTOP_UNTIL_WINDOW:
+        break;
+    case SCREEN_SHOW_DESKTOP_UNTIL_TOGGLE:
+        ignore_windows = TRUE;
+        break;
+    }
+
+    if (!ignore_windows) {
         GList* it;
         for (it = client_list; it != NULL; it = g_list_next(it)) {
             ObClient* maybe_client = (ObClient*)it->data;
index 9295194..ecffa48 100644 (file)
@@ -57,15 +57,15 @@ static gboolean replace_wm(void);
 static void     screen_tell_ksplash(void);
 static void     screen_fallback_focus(void);
 
-guint           screen_num_desktops;
-guint           screen_num_monitors;
-guint           screen_desktop;
-guint           screen_last_desktop;
-gboolean        screen_showing_desktop;
-ObDesktopLayout screen_desktop_layout;
-gchar         **screen_desktop_names;
-Window          screen_support_win;
-Time            screen_desktop_user_time = CurrentTime;
+guint                  screen_num_desktops;
+guint                  screen_num_monitors;
+guint                  screen_desktop;
+guint                  screen_last_desktop;
+ObScreenShowDestopMode screen_show_desktop_mode;
+ObDesktopLayout        screen_desktop_layout;
+gchar                **screen_desktop_names;
+Window                 screen_support_win;
+Time                   screen_desktop_user_time = CurrentTime;
 
 static Size     screen_physical_size;
 static guint    screen_old_desktop;
@@ -445,9 +445,9 @@ void screen_startup(gboolean reconfig)
     screen_last_desktop = screen_desktop;
 
     /* don't start in showing-desktop mode */
-    screen_showing_desktop = FALSE;
+    screen_show_desktop_mode = SCREEN_SHOW_DESKTOP_NO;
     OBT_PROP_SET32(obt_root(ob_screen),
-                   NET_SHOWING_DESKTOP, CARDINAL, screen_showing_desktop);
+                   NET_SHOWING_DESKTOP, CARDINAL, screen_showing_desktop());
 
     if (session_desktop_layout_present &&
         screen_validate_layout(&session_desktop_layout))
@@ -1218,15 +1218,33 @@ void screen_update_desktop_names(void)
                                       screen_num_desktops);
 }
 
-void screen_show_desktop(gboolean show, ObClient *show_only)
+void screen_show_desktop(ObScreenShowDestopMode show_mode, ObClient *show_only)
 {
     GList *it;
 
-    if (show == screen_showing_desktop) return; /* no change */
+    ObScreenShowDestopMode before_mode = screen_show_desktop_mode;
 
-    screen_showing_desktop = show;
+    gboolean showing_before = screen_showing_desktop();
+    screen_show_desktop_mode = show_mode;
+    gboolean showing_after = screen_showing_desktop();
 
-    if (show) {
+    if (showing_before == showing_after) {
+        /* No change. */
+        screen_show_desktop_mode = before_mode;
+        return;
+    }
+
+    if (screen_show_desktop_mode == SCREEN_SHOW_DESKTOP_UNTIL_TOGGLE &&
+        show_only != NULL)
+    {
+        /* If we're showing the desktop until the show-mode is toggled, we
+           don't allow breaking out of showing-desktop mode unless we're
+           showing all the windows again. */
+        screen_show_desktop_mode = before_mode;
+        return;
+    }
+
+    if (showing_after) {
         /* hide windows bottom to top */
         for (it = g_list_last(stacking_list); it; it = g_list_previous(it)) {
             if (WINDOW_IS_CLIENT(it->data)) {
@@ -1250,7 +1268,7 @@ void screen_show_desktop(gboolean show, ObClient *show_only)
         }
     }
 
-    if (show) {
+    if (showing_after) {
         /* focus the desktop */
         for (it = focus_order; it; it = g_list_next(it)) {
             ObClient *c = it->data;
@@ -1275,8 +1293,23 @@ void screen_show_desktop(gboolean show, ObClient *show_only)
         }
     }
 
-    show = !!show; /* make it boolean */
-    OBT_PROP_SET32(obt_root(ob_screen), NET_SHOWING_DESKTOP, CARDINAL, show);
+    OBT_PROP_SET32(obt_root(ob_screen),
+                   NET_SHOWING_DESKTOP,
+                   CARDINAL,
+                   !!showing_after);
+}
+
+gboolean screen_showing_desktop()
+{
+    switch (screen_show_desktop_mode) {
+    case SCREEN_SHOW_DESKTOP_NO:
+        return FALSE;
+    case SCREEN_SHOW_DESKTOP_UNTIL_WINDOW:
+    case SCREEN_SHOW_DESKTOP_UNTIL_TOGGLE:
+        return TRUE;
+    }
+    g_assert_not_reached();
+    return FALSE;
 }
 
 void screen_install_colormap(ObClient *client, gboolean install)
index a6a3995..673a994 100644 (file)
@@ -26,6 +26,12 @@ struct _ObClient;
 
 #define DESKTOP_ALL (0xffffffff)
 
+typedef enum {
+    SCREEN_SHOW_DESKTOP_NO,
+    SCREEN_SHOW_DESKTOP_UNTIL_WINDOW,
+    SCREEN_SHOW_DESKTOP_UNTIL_TOGGLE
+} ObScreenShowDestopMode;
+
 /*! The number of available desktops */
 extern guint screen_num_desktops;
 /*! The number of virtual "xinerama" screens/heads */
@@ -35,7 +41,7 @@ extern guint screen_desktop;
 /*! The desktop which was last visible */
 extern guint screen_last_desktop;
 /*! Are we in showing-desktop mode? */
-extern gboolean screen_showing_desktop;
+extern ObScreenShowDestopMode screen_show_desktop_mode;
 /*! The support window also used for focus and stacking */
 extern Window screen_support_win;
 /*! The last time at which the user changed desktops */
@@ -90,7 +96,11 @@ void screen_hide_desktop_popup(void);
          show is FALSE (restoring from show-desktop mode), and the rest are
          iconified.
 */
-void screen_show_desktop(gboolean show, struct _ObClient *show_only);
+void screen_show_desktop(ObScreenShowDestopMode show_mode,
+                         struct _ObClient *show_only);
+
+/*! Returns true if showing desktop mode is enabled. */
+gboolean screen_showing_desktop();
 
 /*! Updates the desktop layout from the root property if available */
 void screen_update_layout(void);