]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkcolorswatch.c
GtkIconTheme: fix regression from 0db32f0632ef4675bfcfc9ec201f7af157a48ab0
[~andy/gtk] / gtk / gtkcolorswatch.c
index 0429455124818d4c05ed5145406652ebc9f77f96..c6081d7907f1adadc9339f088297f497801fbf5b 100644 (file)
@@ -12,9 +12,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "config.h"
 #include "gtkmenu.h"
 #include "gtkmenuitem.h"
 #include "gtkmenushell.h"
+#include "gtkpressandholdprivate.h"
 #include "gtkprivate.h"
 #include "gtkintl.h"
-#include "a11y/gtkcolorswatchaccessible.h"
+#include "a11y/gtkcolorswatchaccessibleprivate.h"
 
 
 struct _GtkColorSwatchPrivate
@@ -44,6 +43,10 @@ struct _GtkColorSwatchPrivate
   guint    contains_pointer : 1;
   guint    use_alpha        : 1;
   guint    selectable       : 1;
+
+  GdkWindow *event_window;
+
+  GtkPressAndHold *press_and_hold;
 };
 
 enum
@@ -72,16 +75,14 @@ gtk_color_swatch_init (GtkColorSwatch *swatch)
                                               GtkColorSwatchPrivate);
 
   gtk_widget_set_can_focus (GTK_WIDGET (swatch), TRUE);
-  gtk_widget_set_events (GTK_WIDGET (swatch), GDK_BUTTON_PRESS_MASK
-                                              | GDK_BUTTON_RELEASE_MASK
-                                              | GDK_EXPOSURE_MASK
-                                              | GDK_ENTER_NOTIFY_MASK
-                                              | GDK_LEAVE_NOTIFY_MASK);
+  gtk_widget_set_has_window (GTK_WIDGET (swatch), FALSE);
+
   swatch->priv->use_alpha = TRUE;
   swatch->priv->selectable = TRUE;
 }
 
 #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
+#define ACTIVE_BADGE_RADIUS 10
 
 static gboolean
 swatch_draw (GtkWidget *widget,
@@ -119,7 +120,7 @@ swatch_draw (GtkWidget *widget,
         {
           cairo_save (cr);
 
-          _gtk_rounded_box_path (&background.clip_box, cr);
+          _gtk_rounded_box_path (&background.padding_box, cr);
           cairo_clip_preserve (cr);
 
           cairo_set_source_rgb (cr, 0.33, 0.33, 0.33);
@@ -158,9 +159,9 @@ swatch_draw (GtkWidget *widget,
         cairo_set_source_rgba (cr, 1., 1., 1., 0.4);
       else
         cairo_set_source_rgba (cr, 0., 0., 0., 0.4);
-      _gtk_rounded_box_shrink (&background.clip_box, 3, 3, 3, 3);
-      _gtk_rounded_box_path (&background.clip_box, cr);
-      cairo_stroke (cr);
+        _gtk_rounded_box_shrink (&background.padding_box, 3, 3, 3, 3);
+        _gtk_rounded_box_path (&background.padding_box, cr);
+        cairo_stroke (cr);
     }
 
   if (swatch->priv->icon)
@@ -176,28 +177,40 @@ swatch_draw (GtkWidget *widget,
       GIcon *gicon;
 
       gtk_style_context_add_class (context, "color-active-badge");
-      gtk_style_context_get_background_color (context, state, &bg);
-      gtk_style_context_get_border_color (context, state, &border);
-      gtk_style_context_get_border (context, state, &border_width);
-
-      cairo_new_sub_path (cr);
-      cairo_arc (cr, width / 2, height / 2, 10, 0, 2 * G_PI);
-      cairo_close_path (cr);
-      gdk_cairo_set_source_rgba (cr, &bg);
-      cairo_fill_preserve (cr);
-
-      gdk_cairo_set_source_rgba (cr, &border);
-      cairo_set_line_width (cr, border_width.left);
-      cairo_stroke (cr);
-
-      gicon = g_themed_icon_new ("object-select-symbolic");
-      /* fallback for themes that don't have object-select-symbolic */
-      g_themed_icon_append_name (G_THEMED_ICON (gicon), "gtk-apply");
-
-      icon_info = gtk_icon_theme_lookup_by_gicon (theme, gicon, 16,
-                                                  GTK_ICON_LOOKUP_GENERIC_FALLBACK
-                                                  | GTK_ICON_LOOKUP_USE_BUILTIN);
-      g_object_unref (gicon);
+      _gtk_theming_background_init_from_context (&background, context,
+                                                 (width - 2 * ACTIVE_BADGE_RADIUS) / 2, (height - 2 * ACTIVE_BADGE_RADIUS) / 2,
+                                                 2 * ACTIVE_BADGE_RADIUS, 2* ACTIVE_BADGE_RADIUS,
+                                                 GTK_JUNCTION_NONE);
+
+      if (_gtk_theming_background_has_background_image (&background))
+        {
+          _gtk_theming_background_render (&background, cr);
+        }
+      else
+        {
+          gtk_style_context_get_background_color (context, state, &bg);
+          gtk_style_context_get_border_color (context, state, &border);
+          gtk_style_context_get_border (context, state, &border_width);
+
+          cairo_new_sub_path (cr);
+          cairo_arc (cr, width / 2, height / 2, ACTIVE_BADGE_RADIUS, 0, 2 * G_PI);
+          cairo_close_path (cr);
+          gdk_cairo_set_source_rgba (cr, &bg);
+          cairo_fill_preserve (cr);
+
+          gdk_cairo_set_source_rgba (cr, &border);
+          cairo_set_line_width (cr, border_width.left);
+          cairo_stroke (cr);
+
+          gicon = g_themed_icon_new ("object-select-symbolic");
+          /* fallback for themes that don't have object-select-symbolic */
+          g_themed_icon_append_name (G_THEMED_ICON (gicon), "gtk-apply");
+
+          icon_info = gtk_icon_theme_lookup_by_gicon (theme, gicon, 16,
+                                                      GTK_ICON_LOOKUP_GENERIC_FALLBACK
+                                                      | GTK_ICON_LOOKUP_USE_BUILTIN);
+          g_object_unref (gicon);
+        }
     }
 
   if (icon_info != NULL)
@@ -215,7 +228,7 @@ swatch_draw (GtkWidget *widget,
           g_object_unref (pixbuf);
         }
 
-      gtk_icon_info_free (icon_info);
+      g_object_unref (icon_info);
     }
 
   cairo_restore (cr);
@@ -363,6 +376,8 @@ swatch_enter_notify (GtkWidget        *widget,
 {
   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
   swatch->priv->contains_pointer = TRUE;
+  gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE);
+
   return FALSE;
 }
 
@@ -372,6 +387,8 @@ swatch_leave_notify (GtkWidget        *widget,
 {
   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
   swatch->priv->contains_pointer = FALSE;
+  gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_PRELIGHT);
+
   return FALSE;
 }
 
@@ -470,59 +487,179 @@ swatch_button_press (GtkWidget      *widget,
   return FALSE;
 }
 
+static gboolean
+swatch_primary_action (GtkColorSwatch *swatch)
+{
+  GtkWidget *widget = (GtkWidget *)swatch;
+  GtkStateFlags flags;
+
+  flags = gtk_widget_get_state_flags (widget);
+  if (!swatch->priv->has_color)
+    {
+      g_signal_emit (swatch, signals[ACTIVATE], 0);
+      return TRUE;
+    }
+  else if (swatch->priv->selectable &&
+           (flags & GTK_STATE_FLAG_SELECTED) == 0)
+    {
+      gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_SELECTED, FALSE);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
 static gboolean
 swatch_button_release (GtkWidget      *widget,
                        GdkEventButton *event)
 {
   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
-  GtkStateFlags flags;
 
   if (event->button == GDK_BUTTON_PRIMARY &&
       swatch->priv->contains_pointer)
+    return swatch_primary_action (swatch);
+
+  return FALSE;
+}
+
+static void
+hold_action (GtkPressAndHold *pah,
+             gint             x,
+             gint             y,
+             GtkColorSwatch  *swatch)
+{
+  emit_customize (swatch);
+}
+
+static void
+tap_action (GtkPressAndHold *pah,
+            gint             x,
+            gint             y,
+            GtkColorSwatch  *swatch)
+{
+  swatch_primary_action (swatch);
+}
+
+static gboolean
+swatch_touch (GtkWidget     *widget,
+              GdkEventTouch *event)
+{
+  GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
+
+  if (!swatch->priv->press_and_hold)
     {
-      flags = gtk_widget_get_state_flags (widget);
-      if (!swatch->priv->has_color)
-        {
-          g_signal_emit (swatch, signals[ACTIVATE], 0);
-          return TRUE;
-        }
-      else if (swatch->priv->selectable &&
-               (flags & GTK_STATE_FLAG_SELECTED) == 0)
-        {
-          gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_SELECTED, FALSE);
-          return TRUE;
-        }
+      gint drag_threshold;
+
+      g_object_get (gtk_widget_get_settings (widget),
+                    "gtk-dnd-drag-threshold", &drag_threshold,
+                    NULL);
+
+      swatch->priv->press_and_hold = gtk_press_and_hold_new ();
+
+      g_object_set (swatch->priv->press_and_hold,
+                    "drag-threshold", drag_threshold,
+                    "hold-time", 1000,
+                    NULL);
+
+      g_signal_connect (swatch->priv->press_and_hold, "hold",
+                        G_CALLBACK (hold_action), swatch);
+      g_signal_connect (swatch->priv->press_and_hold, "tap",
+                        G_CALLBACK (tap_action), swatch);
     }
 
-  return FALSE;
+  gtk_press_and_hold_process_event (swatch->priv->press_and_hold, (GdkEvent *)event);
+
+  return TRUE;
+}
+
+static void
+swatch_map (GtkWidget *widget)
+{
+  GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
+
+  GTK_WIDGET_CLASS (gtk_color_swatch_parent_class)->map (widget);
+
+  if (swatch->priv->event_window)
+    gdk_window_show (swatch->priv->event_window);
+}
+
+static void
+swatch_unmap (GtkWidget *widget)
+{
+  GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
+
+  if (swatch->priv->event_window)
+    gdk_window_hide (swatch->priv->event_window);
+
+  GTK_WIDGET_CLASS (gtk_color_swatch_parent_class)->unmap (widget);
 }
 
 static void
 swatch_realize (GtkWidget *widget)
 {
+  GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
   GtkAllocation allocation;
   GdkWindow *window;
   GdkWindowAttr attributes;
   gint attributes_mask;
 
-  gtk_widget_set_realized (widget, TRUE);
   gtk_widget_get_allocation (widget, &allocation);
+  gtk_widget_set_realized (widget, TRUE);
 
   attributes.window_type = GDK_WINDOW_CHILD;
   attributes.x = allocation.x;
   attributes.y = allocation.y;
   attributes.width = allocation.width;
   attributes.height = allocation.height;
-  attributes.wclass = GDK_INPUT_OUTPUT;
-  attributes.visual = gtk_widget_get_visual (widget);
-  attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
+  attributes.wclass = GDK_INPUT_ONLY;
+  attributes.event_mask = gtk_widget_get_events (widget);
+  attributes.event_mask |= GDK_BUTTON_PRESS_MASK
+                           | GDK_BUTTON_RELEASE_MASK
+                           | GDK_ENTER_NOTIFY_MASK
+                           | GDK_LEAVE_NOTIFY_MASK
+                           | GDK_TOUCH_MASK;
 
-  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
+  attributes_mask = GDK_WA_X | GDK_WA_Y;
 
-  window = gdk_window_new (gtk_widget_get_parent_window (widget),
-                           &attributes, attributes_mask);
-  gdk_window_set_user_data (window, widget);
+  window = gtk_widget_get_parent_window (widget);
   gtk_widget_set_window (widget, window);
+  g_object_ref (window);
+
+  swatch->priv->event_window = 
+    gdk_window_new (window,
+                    &attributes, attributes_mask);
+  gtk_widget_register_window (widget, swatch->priv->event_window);
+}
+
+static void
+swatch_unrealize (GtkWidget *widget)
+{
+  GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
+
+  if (swatch->priv->event_window)
+    {
+      gtk_widget_unregister_window (widget, swatch->priv->event_window);
+      gdk_window_destroy (swatch->priv->event_window);
+      swatch->priv->event_window = NULL;
+    }
+
+  GTK_WIDGET_CLASS (gtk_color_swatch_parent_class)->unrealize (widget);
+}
+
+static void
+swatch_size_allocate (GtkWidget *widget,
+                      GtkAllocation *allocation)
+{
+  GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
+
+  gtk_widget_set_allocation (widget, allocation);
+
+  if (gtk_widget_get_realized (widget))
+    gdk_window_move_resize (swatch->priv->event_window,
+                            allocation->x,
+                            allocation->y,
+                            allocation->width,
+                            allocation->height);
 }
 
 static gboolean
@@ -586,6 +723,7 @@ swatch_finalize (GObject *object)
   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (object);
 
   g_free (swatch->priv->icon);
+  g_clear_object (&swatch->priv->press_and_hold);
 
   G_OBJECT_CLASS (gtk_color_swatch_parent_class)->finalize (object);
 }
@@ -613,6 +751,11 @@ gtk_color_swatch_class_init (GtkColorSwatchClass *class)
   widget_class->enter_notify_event = swatch_enter_notify;
   widget_class->leave_notify_event = swatch_leave_notify;
   widget_class->realize = swatch_realize;
+  widget_class->unrealize = swatch_unrealize;
+  widget_class->map = swatch_map;
+  widget_class->unmap = swatch_unmap;
+  widget_class->size_allocate = swatch_size_allocate;
+  widget_class->touch_event = swatch_touch;
 
   signals[ACTIVATE] =
     g_signal_new ("activate",