From 7b408bc3b8f5166a3c725459e0ae7fd93ec8aacb Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sun, 8 Sep 2013 13:39:59 -0400 Subject: [PATCH] Add a strict option to the ToggleShowDesktop action When the strict option is used, normal windows are not able to show themselves while showing the desktop. --- data/rc.xsd | 1 + openbox/actions/showdesktop.c | 39 +++++++++++++++++++- openbox/client.c | 4 +- openbox/event.c | 7 +++- openbox/place.c | 15 +++++++- openbox/screen.c | 69 ++++++++++++++++++++++++++--------- openbox/screen.h | 14 ++++++- 7 files changed, 122 insertions(+), 27 deletions(-) diff --git a/data/rc.xsd b/data/rc.xsd index 75dd660e..c8f5638b 100644 --- a/data/rc.xsd +++ b/data/rc.xsd @@ -176,6 +176,7 @@ + diff --git a/openbox/actions/showdesktop.c b/openbox/actions/showdesktop.c index 6dc77d5e..3c3b2d10 100644 --- a/openbox/actions/showdesktop.c +++ b/openbox/actions/showdesktop.c @@ -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; } diff --git a/openbox/client.c b/openbox/client.c index 5e6569e0..3ff278ae 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -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); diff --git a/openbox/event.c b/openbox/event.c index 1b3a0e46..31462a92 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -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) diff --git a/openbox/place.c b/openbox/place.c index 7d5c8694..aaa1639a 100644 --- a/openbox/place.c +++ b/openbox/place.c @@ -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; diff --git a/openbox/screen.c b/openbox/screen.c index 9295194e..ecffa487 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -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) diff --git a/openbox/screen.h b/openbox/screen.h index a6a3995b..673a994d 100644 --- a/openbox/screen.h +++ b/openbox/screen.h @@ -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);