[gnome-control-center/wip/benzea/display: 7/7] display: Draw monitors using CSS



commit 5248f245bbcdcd1a5e0b442c5ba4a41cd4636804
Author: Benjamin Berg <bberg redhat com>
Date:   Wed Dec 27 01:33:13 2017 +0100

    display: Draw monitors using CSS
    
    Updates the design (removing the background) and ports the drawing to use
    CSS.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=786971

 panels/display/cc-display-arrangement.c |  143 +++++++++++++++----------------
 panels/display/cc-display-panel.c       |    8 ++
 panels/display/display-arrangement.css  |   24 +++++
 panels/display/display.gresource.xml    |    1 +
 4 files changed, 103 insertions(+), 73 deletions(-)
---
diff --git a/panels/display/cc-display-arrangement.c b/panels/display/cc-display-arrangement.c
index 7cd885f..17a1499 100644
--- a/panels/display/cc-display-arrangement.c
+++ b/panels/display/cc-display-arrangement.c
@@ -33,11 +33,11 @@ struct _CcDisplayArrangementPrivate
   cairo_matrix_t to_widget;
   cairo_matrix_t to_actual;
 
-  GnomeBG *background;
   GnomeDesktopThumbnailFactory *thumbnail_factory;
 
   gboolean          drag_active;
   CcDisplayMonitor *selected_output;
+  CcDisplayMonitor *prelit_output;
   /* Starting position of cursor inside the monitor. */
   gdouble           drag_anchor_x;
   gdouble           drag_anchor_y;
@@ -241,21 +241,9 @@ cc_display_arrangement_set_selected_output (CcDisplayArrangement *arr,
 static void
 cc_display_arrangement_init (CcDisplayArrangement *arr)
 {
-  CcDisplayArrangementPrivate *priv = CC_DISPLAY_ARRANGEMENT_GET_PRIVATE (arr);
-  GSettings *settings;
-
   /* XXX: Do we need to listen to touch events here? */
   gtk_widget_add_events (GTK_WIDGET (arr),
                         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
-
-  /* XXX: We never update the desktop background, but that is not really
-   *      a big deal. */
-  settings = g_settings_new ("org.gnome.desktop.background");
-  priv->background = gnome_bg_new ();
-  gnome_bg_load_from_preferences (priv->background, settings);
-  g_object_unref (settings);
-
-  priv->thumbnail_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL);
 }
 
 static void
@@ -295,12 +283,16 @@ cc_display_arrangement_draw (GtkWidget *widget,
 {
   CcDisplayArrangement *arr = CC_DISPLAY_ARRANGEMENT (widget);
   CcDisplayArrangementPrivate *priv = CC_DISPLAY_ARRANGEMENT_GET_PRIVATE (arr);
+  GtkStyleContext *context = gtk_widget_get_style_context (widget);
   GList *outputs, *l;
 
   g_return_val_if_fail (priv->config, FALSE);
 
   cc_display_arrangement_update_matrices (arr);
 
+  gtk_style_context_save (context);
+  gtk_style_context_add_class (context, "display-arrangement");
+
   /* Draw in reverse order so that hit detection matches visual. Also pull
    * the selected output to the back. */
   outputs = g_list_copy (cc_display_config_get_monitors (priv->config));
@@ -311,14 +303,29 @@ cc_display_arrangement_draw (GtkWidget *widget,
   for (l = outputs; l; l = l->next)
     {
       CcDisplayMonitor *output = l->data;
+      GtkStateFlags state = GTK_STATE_FLAG_NORMAL;
+      GtkBorder border, padding, margin;
       gint x1, y1, x2, y2;
-      gint w, h, top_offset = 0;
-      GdkPixbuf *background;
+      gint w, h;
       gint num;
 
       if (!cc_display_monitor_is_useful (output))
         continue;
 
+      gtk_style_context_save (context);
+      cairo_save (cr);
+
+      gtk_style_context_add_class (context, "monitor");
+
+      if (output == priv->selected_output)
+        state |= GTK_STATE_FLAG_SELECTED;
+      if (output == priv->prelit_output)
+        state |= GTK_STATE_FLAG_PRELIGHT;
+
+      gtk_style_context_set_state (context, state);
+      if (cc_display_monitor_is_primary (output) || cc_display_config_is_cloning (priv->config))
+        gtk_style_context_add_class (context, "primary");
+
       /* Set in cc-display-panel.c */
       num = cc_display_monitor_get_ui_number (output);
 
@@ -326,85 +333,72 @@ cc_display_arrangement_draw (GtkWidget *widget,
       w = x2 - x1;
       h = y2 - y1;
 
-      cairo_save (cr);
       cairo_translate (cr, x1, y1);
 
-      /* TODO: Draw the selected output differently. */
-      if (output == priv->selected_output)
-        cairo_set_source_rgb (cr, 0, 0, 0);
-      else
-        cairo_set_source_rgb (cr, 0, 0, 0);
-      cairo_rectangle (cr, 0, 0, w, h);
-      cairo_fill (cr);
-
-      background = gnome_bg_create_thumbnail (priv->background,
-                                             priv->thumbnail_factory,
-                                             gdk_screen_get_default (), w, h);
+      gtk_render_background (context, cr, 0, 0, w, h);
+      gtk_render_frame (context, cr, 0, 0, w, h);
 
-      if (background)
-        gdk_cairo_set_source_pixbuf (cr, background, 0, 0);
-      else
-        cairo_set_source_rgb (cr, 0.3, 0.3, 0.3);
+      gtk_style_context_get_border (context, state, &border);
+      gtk_style_context_get_padding (context, state, &padding);
 
-      g_clear_object (&background);
+      w -= border.left + border.right + padding.left + padding.right;
+      h -= border.top + border.bottom + padding.top + padding.bottom;
 
-      cairo_rectangle (cr, 1, 1, w - 2, h - 2);
-      cairo_fill (cr);
-
-      if (cc_display_monitor_is_primary (output) || cc_display_config_is_cloning (priv->config))
-        {
-          top_offset = TOP_BAR_HEIGHT;
-          cairo_set_source_rgb (cr, 0, 0, 0);
-          cairo_rectangle (cr, 1, 1, w -2, top_offset - 1);
-          cairo_fill (cr);
-        }
+      cairo_translate (cr, border.left + padding.left, border.top + padding.top);
 
       if (num > 0)
         {
           PangoLayout *layout;
+          PangoFontDescription *font = NULL;
           gchar *number_str;
-          gdouble r = 3, r2 = r / 2.0, _x1, _y1, _x2, _y2;
           PangoRectangle extents;
-          gdouble max_extent;
+          GdkRGBA color;
+          gdouble text_width, text_padding;
+
+          gtk_style_context_add_class (context, "monitor-label");
+          gtk_style_context_remove_class (context, "monitor");
+
+          gtk_style_context_get_border (context, state, &border);
+          gtk_style_context_get_padding (context, state, &padding);
+          gtk_style_context_get_margin (context, state, &margin);
+
+          cairo_translate (cr, margin.left, margin.top);
 
-          number_str = g_strdup_printf ("<small>%d</small>", num);
-          layout = gtk_widget_create_pango_layout (GTK_WIDGET (arr), "");
-          pango_layout_set_markup (layout, number_str, -1);
+          number_str = g_strdup_printf ("%d", num);
+          gtk_style_context_get (context, state, "font", &font, NULL);
+          layout = gtk_widget_create_pango_layout (GTK_WIDGET (arr), number_str);
+          pango_layout_set_font_description (layout, font);
           pango_layout_get_extents (layout, NULL, &extents);
           g_free (number_str);
 
-          cairo_set_source_rgba (cr, 0, 0, 0, 0.75);
-          max_extent = MAX ((extents.width - extents.x)/ PANGO_SCALE,
-                            (extents.height - extents.y) / PANGO_SCALE);
-
-          _x1 = 5;
-          _x2 = _x1 + max_extent + 1;
-          _y1 = 5 + top_offset;
-          _y2 = _y1 + max_extent + 1;
-          cairo_move_to    (cr, _x1 + r, _y1);
-          cairo_line_to    (cr, _x2 - r, _y1);
-          cairo_curve_to   (cr, _x2 - r2, _y1, _x2, _y1 + r2, _x2, _y1 + r);
-          cairo_line_to    (cr, _x2, _y2 - r);
-          cairo_curve_to   (cr, _x2, _y2 - r2, _x2 - r2, _y2, _x2 - r, _y2);
-          cairo_line_to    (cr, _x1 + r, _y2);
-          cairo_curve_to   (cr, _x1 + r2, _y2, _x1, _y2 - r2, _x1, _y2 - r);
-          cairo_line_to    (cr, _x1, _y1 + r);
-          cairo_curve_to   (cr, _x1, _y1 + r2, _x1 + r2, _y1, _x1 + r, _y1);
-          cairo_fill (cr);
-
-          cairo_set_source_rgb (cr, 1, 1, 1);
-          cairo_move_to (cr,
-                         _x1 + (max_extent / 2.0) - ((extents.width / PANGO_SCALE) / 2.0),
-                         _y1 + (max_extent / 2.0) - ((extents.height / PANGO_SCALE) / 2.0));
-          pango_cairo_show_layout (cr, layout);
-          cairo_fill (cr);
+          h = (extents.height - extents.y) / PANGO_SCALE;
+          text_width = (extents.width - extents.x) / PANGO_SCALE;
+          w = MAX (text_width, h - padding.left - padding.right);
+          text_padding = w - text_width;
+
+          w += border.left + border.right + padding.left + padding.right;
+          h += border.top + border.bottom + padding.top + padding.bottom;
+
+          gtk_render_background (context, cr, 0, 0, w, h);
+          gtk_render_frame (context, cr, 0, 0, w, h);
+
+          cairo_translate (cr, border.left + padding.left, border.top + padding.top);
+          cairo_translate (cr, extents.x + text_padding / 2, 0);
+
+          gtk_style_context_get_color (context, state, &color);
+          gdk_cairo_set_source_rgba (cr, &color);
+
+          gtk_render_layout (context, cr, 0, 0, layout);
           g_object_unref (layout);
         }
 
+      gtk_style_context_restore (context);
       cairo_restore (cr);
     }
   g_list_free (outputs);
 
+  gtk_style_context_restore (context);
+
   return TRUE;
 }
 
@@ -724,6 +718,10 @@ cc_display_arrangement_motion_notify_event (GtkWidget      *widget,
       output = cc_display_arrangement_find_monitor_at (arr, event->x, event->y);
 
       cc_display_arrangement_update_cursor (arr, output != NULL);
+      if (priv->prelit_output != output)
+        gtk_widget_queue_draw (widget);
+
+      priv->prelit_output = output;
 
       return FALSE;
     }
@@ -761,7 +759,6 @@ cc_display_arrangement_finalize (GObject *object)
   CcDisplayArrangementPrivate *priv = CC_DISPLAY_ARRANGEMENT_GET_PRIVATE (object);
 
   g_clear_object (&priv->config);
-  g_clear_object (&priv->background);
   g_clear_object (&priv->thumbnail_factory);
 }
 
diff --git a/panels/display/cc-display-panel.c b/panels/display/cc-display-panel.c
index 7916c16..0d14fc6 100644
--- a/panels/display/cc-display-panel.c
+++ b/panels/display/cc-display-panel.c
@@ -2341,6 +2341,7 @@ static void
 cc_display_panel_init (CcDisplayPanel *self)
 {
   CcDisplayPanelPrivate *priv;
+  GtkCssProvider *provider;
   GtkWidget *bin;
 
   g_resources_register (cc_display_get_resource ());
@@ -2402,4 +2403,11 @@ cc_display_panel_init (CcDisplayPanel *self)
                                             sensor_proxy_vanished_cb,
                                             self,
                                             NULL);
+
+  provider = gtk_css_provider_new ();
+  gtk_css_provider_load_from_resource (provider, 
"/org/gnome/control-center/display/display-arrangement.css");
+  gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+                                             GTK_STYLE_PROVIDER (provider),
+                                             GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+  g_object_unref (provider);
 }
diff --git a/panels/display/display-arrangement.css b/panels/display/display-arrangement.css
new file mode 100644
index 0000000..31c1585
--- /dev/null
+++ b/panels/display/display-arrangement.css
@@ -0,0 +1,24 @@
+
+.display-arrangement.monitor {
+  background: @theme_bg_color;
+  padding: 0.4em;
+}
+
+.display-arrangement.monitor.primary {
+  border-top: 0.4em solid #000000;
+}
+
+.display-arrangement.monitor:selected {
+  background: @theme_selected_bg_color;
+}
+
+.display-arrangement.monitor-label {
+  font-size: larger;
+  font-weight: bold;
+  border-radius: 0.3em;
+  padding-right: 0.2em;
+  padding-left: 0.2em;
+  color: #fff;
+  background: #000;
+}
+
diff --git a/panels/display/display.gresource.xml b/panels/display/display.gresource.xml
index 5712673..1824dc5 100644
--- a/panels/display/display.gresource.xml
+++ b/panels/display/display.gresource.xml
@@ -2,6 +2,7 @@
 <gresources>
   <gresource prefix="/org/gnome/control-center/display">
     <file preprocess="xml-stripblanks">display.ui</file>
+    <file>display-arrangement.css</file>
     <file>16x16/sunrise.png</file>
     <file>16x16/sunset.png</file>
   </gresource>


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