From bd25c5b4c173bb3541f204c60ffb9450a0d010cd Mon Sep 17 00:00:00 2001 From: Colomban Wendling Date: Fri, 20 Jan 2017 15:49:00 +0100 Subject: status-notifier: Fix elements display on GTK < 3.20 On GTK 3.20 onwards, themes are expected to use CSS names rather than widget class names, and apparently CSS names are not inherited. So, a derived widget altering its CSS name won't be styled as its parent classes. Thus, SnItem setting the CSS name "sn-item" avoids being styled as a "button". But on older GTK versions, the widget class being used makes this change ineffective. Fix that by introducing a custom derived button that doesn't draw the unwanted parts. --- .../notification_area/status-notifier/Makefile.am | 2 + .../status-notifier/sn-flat-button.c | 174 +++++++++++++++++++++ .../status-notifier/sn-flat-button.h | 60 +++++++ .../notification_area/status-notifier/sn-item.c | 2 +- .../notification_area/status-notifier/sn-item.h | 6 +- 5 files changed, 241 insertions(+), 3 deletions(-) create mode 100644 applets/notification_area/status-notifier/sn-flat-button.c create mode 100644 applets/notification_area/status-notifier/sn-flat-button.h (limited to 'applets/notification_area') diff --git a/applets/notification_area/status-notifier/Makefile.am b/applets/notification_area/status-notifier/Makefile.am index 9bbb4134..6eab62ee 100644 --- a/applets/notification_area/status-notifier/Makefile.am +++ b/applets/notification_area/status-notifier/Makefile.am @@ -22,6 +22,8 @@ libstatus_notifier_la_SOURCES = \ sn-dbus-menu.h \ sn-dbus-menu-item.c \ sn-dbus-menu-item.h \ + sn-flat-button.c \ + sn-flat-button.h \ sn-host-v0.c \ sn-host-v0.h \ sn-image-menu-item.c \ diff --git a/applets/notification_area/status-notifier/sn-flat-button.c b/applets/notification_area/status-notifier/sn-flat-button.c new file mode 100644 index 00000000..d920dadf --- /dev/null +++ b/applets/notification_area/status-notifier/sn-flat-button.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2017 Colomban Wendling + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * A GtkButton that doesn't draw anything specific but the focus, and pass + * all drawing and sizing requests to its child. + */ + +#define SN_FLAT_BUTTON_C + +#include + +#include "sn-flat-button.h" + +G_DEFINE_TYPE (SnFlatButton, + sn_flat_button, + GTK_TYPE_BUTTON) + +static gboolean +sn_flat_button_draw (GtkWidget *widget, + cairo_t *cr) +{ + GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget)); + + if (child) + gtk_container_propagate_draw (GTK_CONTAINER (widget), child, cr); + + if (gtk_widget_is_drawable (widget) && gtk_widget_has_focus (widget)) + { + GtkStyleContext *context = gtk_widget_get_style_context (widget); + gdouble x1, y1, x2, y2; + + cairo_clip_extents (cr, &x1, &y1, &x2, &y2); + gtk_render_focus (context, cr, x1, y1, x2 - x1, y2 - y1); + } + + return child != NULL; +} + +static void +sn_flat_button_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkWidget *child; + + GTK_WIDGET_CLASS (sn_flat_button_parent_class)->size_allocate (widget, + allocation); + + child = gtk_bin_get_child (GTK_BIN (widget)); + + if (child && gtk_widget_get_visible (child)) + gtk_widget_size_allocate (child, allocation); +} + +static GtkSizeRequestMode +sn_flat_button_get_request_mode (GtkWidget *widget) +{ + GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget)); + + if (child) + return gtk_widget_get_request_mode (child); + else + return GTK_WIDGET_CLASS (sn_flat_button_parent_class)->get_request_mode (widget); +} + +static void +sn_flat_button_get_preferred_height (GtkWidget *widget, + gint *min, + gint *nat) +{ + GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget)); + + if (child) + gtk_widget_get_preferred_height (child, min, nat); + else + GTK_WIDGET_CLASS (sn_flat_button_parent_class)->get_preferred_height (widget, min, nat); +} + +static void +sn_flat_button_get_preferred_width (GtkWidget *widget, + gint *min, + gint *nat) +{ + GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget)); + + if (child) + gtk_widget_get_preferred_width (child, min, nat); + else + GTK_WIDGET_CLASS (sn_flat_button_parent_class)->get_preferred_width (widget, min, nat); +} + +static void +sn_flat_button_get_preferred_height_for_width (GtkWidget *widget, + gint width, + gint *min, + gint *nat) +{ + GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget)); + + if (child) + gtk_widget_get_preferred_height_for_width (child, width, min, nat); + else + GTK_WIDGET_CLASS (sn_flat_button_parent_class)->get_preferred_height_for_width (widget, width, min, nat); +} + +static void +sn_flat_button_get_preferred_width_for_height (GtkWidget *widget, + gint height, + gint *min, + gint *nat) +{ + GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget)); + + if (child) + gtk_widget_get_preferred_width_for_height (child, height, min, nat); + else + GTK_WIDGET_CLASS (sn_flat_button_parent_class)->get_preferred_width_for_height (widget, height, min, nat); +} + +static void +sn_flat_button_get_preferred_height_and_baseline_for_width (GtkWidget *widget, + gint width, + gint *min, + gint *nat, + gint *min_baseline, + gint *nat_baseline) +{ + GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget)); + + if (child) + gtk_widget_get_preferred_height_and_baseline_for_width (child, width, min, nat, + min_baseline, nat_baseline); + else + GTK_WIDGET_CLASS (sn_flat_button_parent_class)->get_preferred_height_and_baseline_for_width (widget, width, + min, nat, + min_baseline, nat_baseline); +} + +static void +sn_flat_button_class_init (SnFlatButtonClass *klass) +{ + GtkWidgetClass *widget_class; + + widget_class = GTK_WIDGET_CLASS (klass); + + widget_class->draw = sn_flat_button_draw; + widget_class->size_allocate = sn_flat_button_size_allocate; + widget_class->get_request_mode = sn_flat_button_get_request_mode; + widget_class->get_preferred_height = sn_flat_button_get_preferred_height; + widget_class->get_preferred_height_for_width = sn_flat_button_get_preferred_height_for_width; + widget_class->get_preferred_height_and_baseline_for_width = sn_flat_button_get_preferred_height_and_baseline_for_width; + widget_class->get_preferred_width = sn_flat_button_get_preferred_width; + widget_class->get_preferred_width_for_height = sn_flat_button_get_preferred_width_for_height; +} + +static void +sn_flat_button_init (SnFlatButton *self) +{ + gtk_button_set_relief (GTK_BUTTON (self), GTK_RELIEF_NONE); +} diff --git a/applets/notification_area/status-notifier/sn-flat-button.h b/applets/notification_area/status-notifier/sn-flat-button.h new file mode 100644 index 00000000..1a93d30f --- /dev/null +++ b/applets/notification_area/status-notifier/sn-flat-button.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2017 Colomban Wendling + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SN_FLAT_BUTTON_H +#define SN_FLAT_BUTTON_H + +#include + +G_BEGIN_DECLS + +#define SN_TYPE_FLAT_BUTTON (sn_flat_button_get_type ()) +#define SN_FLAT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SN_TYPE_FLAT_BUTTON, SnFlatButton)) +#define SN_FLAT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SN_TYPE_FLAT_BUTTON, SnFlatButtonClass)) +#define SN_IS_FLAT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SN_TYPE_FLAT_BUTTON)) +#define SN_IS_FLAT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SN_TYPE_FLAT_BUTTON)) +#define SN_FLAT_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SN_TYPE_FLAT_BUTTON, SnFlatButtonClass)) + +typedef struct _SnFlatButton SnFlatButton; +typedef struct _SnFlatButtonPrivate SnFlatButtonPrivate; +typedef struct _SnFlatButtonClass SnFlatButtonClass; + +struct _SnFlatButton +{ + GtkButton parent_instance; + + SnFlatButtonPrivate *priv; +}; + +struct _SnFlatButtonClass +{ + GtkButtonClass parent_class; +}; + +GType sn_flat_button_get_type (void); +GtkWidget *sn_flat_button_new (void); + +#if 0 +#ifndef SN_COMPAT_BUTTON_NODRAW_C +/* replace GtkButton */ +# define gtk_button_get_type sn_compat_button_nodraw_get_type +#endif +#endif + +G_END_DECLS + +#endif diff --git a/applets/notification_area/status-notifier/sn-item.c b/applets/notification_area/status-notifier/sn-item.c index fc0401b6..d102a6cc 100644 --- a/applets/notification_area/status-notifier/sn-item.c +++ b/applets/notification_area/status-notifier/sn-item.c @@ -57,7 +57,7 @@ static guint signals[LAST_SIGNAL] = { 0 }; static void na_item_init (NaItemInterface *iface); -G_DEFINE_ABSTRACT_TYPE_WITH_CODE (SnItem, sn_item, GTK_TYPE_BUTTON, +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (SnItem, sn_item, SN_TYPE_FLAT_BUTTON, G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL) G_IMPLEMENT_INTERFACE (NA_TYPE_ITEM, diff --git a/applets/notification_area/status-notifier/sn-item.h b/applets/notification_area/status-notifier/sn-item.h index de7de892..3736c1d8 100644 --- a/applets/notification_area/status-notifier/sn-item.h +++ b/applets/notification_area/status-notifier/sn-item.h @@ -20,6 +20,8 @@ #include +#include "sn-flat-button.h" + G_BEGIN_DECLS #define SN_TYPE_ITEM (sn_item_get_type ()) @@ -41,14 +43,14 @@ typedef struct _SnItemClass SnItemClass; struct _SnItem { - GtkButtonClass parent_instance; + SnFlatButtonClass parent_instance; SnItemPrivate *priv; }; struct _SnItemClass { - GtkButtonClass parent_class; + SnFlatButtonClass parent_class; void (* ready) (SnItem *item); -- cgit v1.2.1