Disable "Reserve space" button if another monitor lies beyond the edge.
authorAndriy Grytsenko <andrej@rep.kiev.ua>
Thu, 13 Nov 2014 14:30:53 +0000 (16:30 +0200)
committerAndriy Grytsenko <andrej@rep.kiev.ua>
Thu, 13 Nov 2014 14:30:53 +0000 (16:30 +0200)
In this case reservation will cover it so that should be denied.
Reservation will not be applied in such cases even if set in config manually.

ChangeLog
src/configurator.c
src/panel.c
src/private.h

index 8272a52..546d543 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -9,6 +9,11 @@
     to allow pre-0.6.0 behavior).
 * Implemented monitors hotplug support.
 * Fixed popups positioning in multi-monitor environment.
+* Fixed updating panel size if appropriate monitor changed its size or
+    position.
+* Implemented disabling for "Reserve space" button if another monitor
+    lies beyond the edge so reservation will cover it. Also reservation
+    will not be applied in such cases even if set in config manually.
 
 0.7.2
 -------------------------------------------------------------------------
index b69285c..103ad68 100644 (file)
@@ -119,6 +119,26 @@ gboolean panel_edge_available(Panel* p, int edge, gint monitor)
     return TRUE;
 }
 
+static void update_strut_control_button(LXPanel *panel)
+{
+    Panel *p = panel->priv;
+    gboolean active = _panel_edge_can_strut(panel, p->edge, p->monitor, NULL);
+    gboolean old_active = !!gtk_widget_get_sensitive(p->strut_control);
+
+    if (active == old_active)
+        return;
+    gtk_widget_set_sensitive(p->strut_control, active);
+    if (active)
+        gtk_widget_set_tooltip_text(p->strut_control, NULL);
+    else
+        gtk_widget_set_tooltip_text(p->strut_control,
+                                    _("Space reservation is not available for"
+                                      " this panel because there is another"
+                                      " monitor beyond this edge and reservation"
+                                      " would cover it if enabled."));
+    _panel_set_wm_strut(panel);
+}
+
 static void set_edge(LXPanel* panel, int edge)
 {
     Panel *p = panel->priv;
@@ -128,6 +148,7 @@ static void set_edge(LXPanel* panel, int edge)
     _panel_set_panel_configuration_changed(panel);
     UPDATE_GLOBAL_STRING(p, "edge", num2str(edge_pair, edge, "none"));
     //FIXME: update monitors and strut sensitivities
+    update_strut_control_button(panel);
 }
 
 static void edge_bottom_toggle(GtkToggleButton *widget, LXPanel *p)
@@ -192,6 +213,7 @@ static void set_monitor_cb(GtkComboBox *cb, LXPanel *panel)
     _panel_set_panel_configuration_changed(panel);
     UPDATE_GLOBAL_INT(p, "monitor", p->monitor);
     //FIXME: update edge and strut sensitivities
+    update_strut_control_button(panel);
 }
 
 static void set_alignment(LXPanel* panel, int align)
@@ -449,6 +471,7 @@ set_strut(GtkToggleButton* toggle, LXPanel* panel)
 
     p->setstrut = gtk_toggle_button_get_active(toggle) ? 1 : 0;
     gtk_widget_queue_resize(GTK_WIDGET(panel));
+    _panel_set_wm_strut(panel);
     UPDATE_GLOBAL_INT(p, "setpartialstrut", p->setstrut);
 }
 
@@ -1114,8 +1137,9 @@ void panel_configure( LXPanel* panel, int sel_page )
         be accessed by other applications.
         GNOME Panel acts this way, too.
     */
-    w = (GtkWidget*)gtk_builder_get_object( builder, "reserve_space" );
+    p->strut_control = w = (GtkWidget*)gtk_builder_get_object( builder, "reserve_space" );
     update_toggle_button( w, p->setstrut );
+    update_strut_control_button(panel);
     g_signal_connect( w, "toggled",
                       G_CALLBACK(set_strut), panel );
 
index ce2f921..b90c033 100644 (file)
@@ -357,6 +357,92 @@ static void panel_normalize_configuration(Panel* p)
         p->transparent = 0;
 }
 
+gboolean _panel_edge_can_strut(LXPanel *panel, int edge, gint monitor, gulong *size)
+{
+    Panel *p;
+    GdkScreen *screen;
+    GdkRectangle rect;
+    GdkRectangle rect2;
+    gint n, i;
+    gulong s;
+
+#if GTK_CHECK_VERSION(2, 20, 0)
+    if (!gtk_widget_get_mapped(GTK_WIDGET(panel)))
+#else
+    if (!GTK_WIDGET_MAPPED(p))
+#endif
+        return FALSE;
+
+    p = panel->priv;
+    /* Handle autohide case.  EWMH recommends having the strut be the minimized size. */
+    if (p->autohide)
+        s = p->height_when_hidden;
+    else switch (edge)
+    {
+    case EDGE_LEFT:
+    case EDGE_RIGHT:
+        s = p->aw;
+        break;
+    case EDGE_TOP:
+    case EDGE_BOTTOM:
+        s = p->ah;
+        break;
+    default: /* error! */
+        return FALSE;
+    }
+
+    if (monitor < 0) /* screen span */
+    {
+        if (G_LIKELY(size))
+            *size = s;
+        return TRUE;
+    }
+
+    screen = gtk_widget_get_screen(GTK_WIDGET(panel));
+    gdk_screen_get_monitor_geometry(screen, monitor, &rect);
+    switch (edge)
+    {
+        case EDGE_LEFT:
+            rect.width = rect.x;
+            rect.x = 0;
+            s += rect.width;
+            break;
+        case EDGE_RIGHT:
+            rect.x += rect.width;
+            rect.width = gdk_screen_get_width(screen) - rect.x;
+            s += rect.width;
+            break;
+        case EDGE_TOP:
+            rect.height = rect.y;
+            rect.y = 0;
+            s += rect.height;
+            break;
+        case EDGE_BOTTOM:
+            rect.y += rect.height;
+            rect.height = gdk_screen_get_height(screen) - rect.y;
+            s += rect.height;
+            break;
+        default: ;
+    }
+    if (rect.height == 0 || rect.width == 0) ; /* on a border of monitor */
+    else
+    {
+        n = gdk_screen_get_n_monitors(screen);
+        for (i = 0; i < n; i++)
+        {
+            if (i == monitor)
+                continue;
+            gdk_screen_get_monitor_geometry(screen, i, &rect2);
+            if (gdk_rectangle_intersect(&rect, &rect2, NULL))
+                /* that monitor lies over the edge */
+                return FALSE;
+        }
+    }
+    if (G_LIKELY(size))
+        *size = s;
+    return TRUE;
+}
+
 /****************************************************
  *         panel's handlers for WM events           *
  ****************************************************/
@@ -391,25 +477,21 @@ void _panel_set_wm_strut(LXPanel *panel)
     {
         case EDGE_LEFT:
             index = 0;
-            strut_size = p->aw;
             strut_lower = p->ay;
             strut_upper = p->ay + p->ah;
             break;
         case EDGE_RIGHT:
             index = 1;
-            strut_size = p->aw;
             strut_lower = p->ay;
             strut_upper = p->ay + p->ah;
             break;
         case EDGE_TOP:
             index = 2;
-            strut_size = p->ah;
             strut_lower = p->ax;
             strut_upper = p->ax + p->aw;
             break;
         case EDGE_BOTTOM:
             index = 3;
-            strut_size = p->ah;
             strut_lower = p->ax;
             strut_upper = p->ax + p->aw;
             break;
@@ -417,14 +499,11 @@ void _panel_set_wm_strut(LXPanel *panel)
             return;
     }
 
-    /* Handle autohide case.  EWMH recommends having the strut be the minimized size. */
-    if (p->autohide)
-        strut_size = p->height_when_hidden;
-
     /* Set up strut value in property format. */
     gulong desired_strut[12];
     memset(desired_strut, 0, sizeof(desired_strut));
-    if (p->setstrut)
+    if (p->setstrut &&
+        _panel_edge_can_strut(panel, p->edge, p->monitor, &strut_size))
     {
         desired_strut[index] = strut_size;
         desired_strut[4 + index * 2] = strut_lower;
index 5a016d7..8c20275 100644 (file)
@@ -134,6 +134,7 @@ struct _Panel {
     GtkWidget* alignment_right_label;  /* Label of alignment: right control */
     GtkWidget* height_control;         /* Height control in preference dialog */
     GtkWidget* width_control;          /* Width control in preference dialog */
+    GtkWidget* strut_control;          /* Reserve space in preference dialog */
 
     guint initialized : 1;              /* Should be grouped better later, */
     guint ah_far : 1;                   /* placed here for binary compatibility */
@@ -231,6 +232,7 @@ void _panel_queue_update_background(LXPanel *p);
 
 void panel_configure(LXPanel* p, int sel_page);
 gboolean panel_edge_available(Panel* p, int edge, gint monitor);
+gboolean _panel_edge_can_strut(LXPanel *panel, int edge, gint monitor, gulong *size);
 void restart(void);
 void logout(void);
 void gtk_run(void);