[geary] Fix GTK+ widget style issues under GTK+ < 3.20.



commit d6466d57475d37d6f1ac8c6fbe842b28edbcbdd4
Author: Michael Gratton <mike vee net>
Date:   Thu Dec 8 22:08:39 2016 +1100

    Fix GTK+ widget style issues under GTK+ < 3.20.

 .../conversation-viewer/conversation-list-box.vala |   86 +++++++++++++++++---
 .../conversation-viewer/conversation-message.vala  |    6 ++
 ui/geary.css                                       |   42 ++++++++--
 3 files changed, 118 insertions(+), 16 deletions(-)
---
diff --git a/src/client/conversation-viewer/conversation-list-box.vala 
b/src/client/conversation-viewer/conversation-list-box.vala
index fe997ad..cf03c18 100644
--- a/src/client/conversation-viewer/conversation-list-box.vala
+++ b/src/client/conversation-viewer/conversation-list-box.vala
@@ -49,20 +49,59 @@ public class ConversationListBox : Gtk.ListBox {
 
 
         protected const string EXPANDED_CLASS = "geary-expanded";
+        private const string FIRST_CLASS = "geary-first";
         private const string LAST_CLASS = "geary-last";
-
+#if !GTK_3_20
+        // GTK < 3.20+ style workarounds. Keep this in sync
+        // with geary.css.
+        private const int CANT_USE_PADDING_WORKAROUND = 18;
+#endif
 
         // The email being displayed by this row, if any
         public Geary.Email? email { get; private set; default = null; }
 
         // Is the row showing the email's message body or just headers?
-        public bool is_expanded { get; protected set; default = false; }
+        public bool is_expanded {
+            get {
+                return this._is_expanded;
+            }
+            protected set {
+#if !GTK_3_20
+                // GTK+ < 3.20 style workaround. Keep this in sync
+                // with geary.css
+                this.margin_bottom = value ? 6 : 0;
+#endif
+                this._is_expanded = value;
+            }
+        }
+        private bool _is_expanded = false;
+
+        // Designate this row as the first visible row in the
+        // conversation listbox, or not. See Bug 764710 and
+        // ::update_first_last_row() below.
+        internal bool is_first {
+            set {
+                set_style_context_class(FIRST_CLASS, value);
+#if !GTK_3_20
+                // GTK < 3.20+ style workarounds. Keep this in sync
+                // with geary.css.
+                this.margin_top = CANT_USE_PADDING_WORKAROUND;
+#endif
+            }
+        }
 
         // Designate this row as the last visible row in the
         // conversation listbox, or not. See Bug 764710 and
-        // ::update_last_row() below.
+        // ::update_first_last_row() below.
         internal bool is_last {
-            set { set_style_context_class(LAST_CLASS, value); }
+            set {
+                set_style_context_class(LAST_CLASS, value);
+#if !GTK_3_20
+                // GTK < 3.20+ style workarounds. Keep this in sync
+                // with geary.css.
+                this.margin_bottom = CANT_USE_PADDING_WORKAROUND;
+#endif
+            }
         }
 
 
@@ -75,6 +114,13 @@ public class ConversationListBox : Gtk.ListBox {
         public ConversationRow(Geary.Email? email) {
             this.email = email;
             show();
+
+#if !GTK_3_20
+            // GTK < 3.20+ style workarounds. Keep this in sync with
+            // geary.css.
+            this.margin_start = CANT_USE_PADDING_WORKAROUND;
+            this.margin_end = CANT_USE_PADDING_WORKAROUND;
+#endif
         }
 
         // Request the row be expanded, if supported.
@@ -249,7 +295,8 @@ public class ConversationListBox : Gtk.ListBox {
     // The id of the draft referred to by the current composer.
     private Geary.EmailIdentifier? draft_id = null;
 
-    // Last visible row in the list, if any
+    // First and last visible row in the list, if any
+    private ConversationRow? first_row = null;
     private ConversationRow? last_row = null;
 
     // Cached search terms to apply to new messages
@@ -291,6 +338,10 @@ public class ConversationListBox : Gtk.ListBox {
 
         get_style_context().add_class("background");
         get_style_context().add_class("conversation-listbox");
+#if !GTK_3_20
+        // GTK < 3.20+ style workaround
+        get_style_context().remove_class("list");
+#endif
 
         set_adjustment(adjustment);
         set_selection_mode(Gtk.SelectionMode.NONE);
@@ -356,7 +407,7 @@ public class ConversationListBox : Gtk.ListBox {
             }
         }
 
-        update_last_row();
+        update_first_last_row();
         EmailRow? last_email = this.last_row as EmailRow;
 
         if (last_email != null && !this.cancellable.is_cancelled()) {
@@ -448,7 +499,7 @@ public class ConversationListBox : Gtk.ListBox {
         row.enable_should_scroll();
         row.should_scroll.connect(() => { scroll_to(row); });
         add(row);
-        update_last_row();
+        update_first_last_row();
 
         embed.composer.draft_id_changed.connect((id) => { this.draft_id = id; });
         embed.vanished.connect(() => {
@@ -684,7 +735,7 @@ public class ConversationListBox : Gtk.ListBox {
 
         if (!this.cancellable.is_cancelled()) {
             EmailRow row = add_email(full_email);
-            update_last_row();
+            update_first_last_row();
             yield row.view.start_loading(this.cancellable);
         }
     }
@@ -793,9 +844,24 @@ public class ConversationListBox : Gtk.ListBox {
     // Due to Bug 764710, we can only use the CSS :last-child selector
     // for GTK themes after 3.20.3, so for now manually maintain a
     // class on the last box so we can emulate it
-    private void update_last_row() {
+    private void update_first_last_row() {
+        ConversationRow? first = null;
         ConversationRow? last = null;
-        this.foreach((child) => { last = (ConversationRow) child; });
+        this.foreach((child) => {
+                if (first == null) {
+                    first = (ConversationRow) child;
+                }
+                last = (ConversationRow) child;
+            });
+
+        if (this.first_row != first) {
+            if (this.first_row != null) {
+                this.first_row.is_first = false;
+            }
+
+            this.first_row = first;
+            this.first_row.is_first = true;
+        }
 
         if (this.last_row != last) {
             if (this.last_row != null) {
diff --git a/src/client/conversation-viewer/conversation-message.vala 
b/src/client/conversation-viewer/conversation-message.vala
index 03f8840..d60cbf6 100644
--- a/src/client/conversation-viewer/conversation-message.vala
+++ b/src/client/conversation-viewer/conversation-message.vala
@@ -301,6 +301,12 @@ public class ConversationMessage : Gtk.Grid {
         this.contact_store = contact_store;
         this.always_load_remote_images = always_load_remote_images;
 
+#if !GTK_3_20
+        // GTK < 3.20+ style workarounds. Keep this in sync with
+        // geary.css.
+        this.summary.border_width = 12;
+#endif
+
         // Actions
 
         add_action(ACTION_COPY_EMAIL, true, VariantType.STRING)
diff --git a/ui/geary.css b/ui/geary.css
index e6777f8..c743b0d 100644
--- a/ui/geary.css
+++ b/ui/geary.css
@@ -6,6 +6,14 @@
  * (version 2.1 or later). See the COPYING file in this distribution.
  */
 
+/*
+ * Since GTK+ 3.20 introduced some significant breaking changes to CSS
+ * node names for styling GTK+ widgets, we need to duplicate selectors
+ * that either either refer to a widget by node name (e.g. "GtkLabel"
+ * vs "label"), or that referrs to any child nodes introduced by 3.20
+ * (e.g. "frame > border").
+ */
+
 .geary-folder-frame, /* GTK < 3.20 */
 .geary-folder-frame > border {
   border-left-width: 0;
@@ -24,9 +32,11 @@
   border-bottom-width: 0;
 }
 
+.geary-composer-box, /* GTK < 3.20 */
 .geary-composer-box > border {
   border-width: 0px;
 }
+.geary-composer-body, /* GTK < 3.20 */
 .geary-composer-body > border {
   border-left-width: 0;
   border-right-width: 0;
@@ -44,12 +54,14 @@
 
 /* FolderPopover */
 
+.list-row.geary-folder-popover-list-row, /* GTK < 3.20 */
 row.geary-folder-popover-list-row {
   padding: 6px;
   border-color: @borders;
   border-style: groove;
   border-bottom-width: 1px;
 }
+.list-row.geary-folder-popover-list-row > GtkLabel, /* GTK < 3.20 */
 row.geary-folder-popover-list-row > label {
   color: @theme_text_color;
 }
@@ -59,6 +71,7 @@ row.geary-folder-popover-list-row > label {
 .conversation-listbox {
   padding: 18px;
 }
+.conversation-listbox > .list-row, /* GTK < 3.20 */
 .conversation-listbox > row {
   margin: 0;
   border: 1px solid @borders;
@@ -67,71 +80,86 @@ row.geary-folder-popover-list-row > label {
   box-shadow: 0 4px 8px 1px rgba(0,0,0,0.4);
   transition: margin 0.1s;
 }
+.conversation-listbox > .list-row > GtkBox, /* GTK < 3.20 */
 .conversation-listbox > row > box {
   background: @theme_base_color;
   transition: background 0.25s;
 }
+.conversation-listbox > .list-row:hover > GtkBox, /* GTK < 3.20 */
 .conversation-listbox > row:hover > box {
   background: shade(@theme_base_color, 0.96);
 }
+.conversation-listbox > .list-row.geary-expanded, /* GTK < 3.20 */
 .conversation-listbox > row.geary-expanded {
   margin-bottom: 6px;
   border-bottom-width: 1px;
 }
+.conversation-listbox > .list-row.geary-match GtkFlowBox > *.geary-match, /* GTK < 3.20 */
 .conversation-listbox > row.geary-match flowboxchild.geary-match {
   color: @theme_selected_fg_color;
   background: @theme_selected_bg_color;
 }
+.conversation-listbox > .list-row.geary-last, /* GTK < 3.20 */
 .conversation-listbox > row.geary-last {
   margin-bottom: 0;
 }
 
 /* ConversationEmail */
 
-.geary-unread .geary-message-summary {
+.geary-unread, ConversationMessage, /* GTK < 3.20 */
+.geary-unread grid.geary-message-summary {
   border-color: @theme_selected_bg_color;
   transition: border 0.25s;
 }
 
 /* ConversationMessage */
 
-.geary-message-summary {
+ConversationMessage, /* GTK < 3.20 */
+grid.geary-message-summary {
   border-top: 4px solid transparent;
   padding: 12px;
   padding-top: 8px;
   transition: border 4s;
 }
 
+.geary-headers GtkLabel, /* GTK < 3.20 */
 .geary-headers label {
   margin: 0;
   padding: 1px;
 }
+.geary-headers GtkLabel.geary-header, /* GTK < 3.20 */
 .geary-headers label.geary-header {
   padding-right: 6px;
 }
+.geary-headers GtkFlowBox > *, /* GTK < 3.20 */
 .geary-headers flowboxchild {
   margin: 0;
   padding: 1px;
 }
+.geary-headers GtkFlowBox > * GtkLabel, /* GTK < 3.20 */
 .geary-headers flowboxchild label {
   margin: 0;
   padding: 0;
 }
 
+.geary-headers GtkLabel.geary-from, /* GTK < 3.20 */
 .geary-headers label.geary-from {
   font-weight: bold;
 }
 
-.geary-header-value flowboxchild:active {
+.geary-header-value > *:active, /* GTK < 3.20 */
+.geary-header-value > flowboxchild:active {
   background: mix(@theme_base_color, @theme_bg_color, 0.5);
 }
 
-.geary-header-value flowboxchild:hover {
+.geary-header-value > *:hover, /* GTK < 3.20 */
+.geary-header-value > flowboxchild:hover {
   background: @theme_base_color;
 }
 
-.geary-header-value flowboxchild label.dim-label {
-  margin-left: 6px;
+.geary-header-value > * GtkLabel.dim-label, /* GTK < 3.20 */
+.geary-header-value > flowboxchild label.dim-label {
+  padding-left: 6px; /* Would be margin-left, but GTK 3.14 doesn't like it */
 }
 
 .geary-submessages .geary-message {
@@ -140,6 +168,7 @@ row.geary-folder-popover-list-row > label {
 
 /* Composer */
 
+.geary-composer-embed GtkHeaderBar, /* GTK < 3.20 */
 .geary-composer-embed headerbar {
   border-top: 1px solid @borders;
   border-radius: 0px;
@@ -147,6 +176,7 @@ row.geary-folder-popover-list-row > label {
 
 /* EmptyPlaceholder */
 
+.geary-empty-placeholder > GtkImage, /* GTK < 3.20 */
 .geary-empty-placeholder > image {
   margin-bottom: 12px;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]