From 5c99612305a3042d7096123619a83346492eadf3 Mon Sep 17 00:00:00 2001 From: Stefano Karapetsas Date: Sat, 26 Oct 2013 14:39:39 +0200 Subject: notification_area: Add GTK3 support --- applets/notification_area/fixedtip.c | 54 ++++++++++++++++--- applets/notification_area/main.c | 4 ++ applets/notification_area/na-tray-child.c | 80 ++++++++++++++++++++++++++--- applets/notification_area/na-tray-child.h | 4 ++ applets/notification_area/na-tray-manager.c | 60 +++++++++++++++++++++- applets/notification_area/na-tray-manager.h | 3 ++ applets/notification_area/na-tray.c | 62 +++++++++++++++++++++- applets/notification_area/testtray.c | 6 +++ 8 files changed, 256 insertions(+), 17 deletions(-) diff --git a/applets/notification_area/fixedtip.c b/applets/notification_area/fixedtip.c index 220273b2..7bd61409 100644 --- a/applets/notification_area/fixedtip.c +++ b/applets/notification_area/fixedtip.c @@ -51,6 +51,35 @@ button_press_handler (GtkWidget *fixedtip, return FALSE; } +#if GTK_CHECK_VERSION (3, 0, 0) +static gboolean +na_fixed_tip_draw (GtkWidget *widget, cairo_t *cr) +{ + GtkStyleContext *context; + GtkStateFlags state; + int width, height; + + width = gtk_widget_get_allocated_width (widget); + height = gtk_widget_get_allocated_height (widget); + + state = gtk_widget_get_state_flags (widget); + context = gtk_widget_get_style_context (widget); + gtk_style_context_save (context); + gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOOLTIP); + gtk_style_context_set_state (context, state); + + cairo_save (cr); + gtk_render_background (context, cr, + 0., 0., + (gdouble)width, + (gdouble)height); + cairo_restore (cr); + + gtk_style_context_restore (context); + + return FALSE; +} +#else static gboolean expose_handler (GtkWidget *fixedtip) { @@ -66,10 +95,16 @@ expose_handler (GtkWidget *fixedtip) return FALSE; } +#endif static void na_fixed_tip_class_init (NaFixedTipClass *class) { +#if GTK_CHECK_VERSION (3, 0, 0) + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); + widget_class->draw = na_fixed_tip_draw; +#endif + fixedtip_signals[CLICKED] = g_signal_new ("clicked", G_OBJECT_CLASS_TYPE (class), @@ -106,8 +141,10 @@ na_fixed_tip_init (NaFixedTip *fixedtip) gtk_container_add (GTK_CONTAINER (fixedtip), label); fixedtip->priv->label = label; +#if !GTK_CHECK_VERSION (3, 0, 0) g_signal_connect (fixedtip, "expose_event", G_CALLBACK (expose_handler), NULL); +#endif gtk_widget_add_events (GTK_WIDGET (fixedtip), GDK_BUTTON_PRESS_MASK); @@ -135,16 +172,19 @@ na_fixed_tip_position (NaFixedTip *fixedtip) gtk_window_set_screen (GTK_WINDOW (fixedtip), screen); +#if GTK_CHECK_VERSION (3, 0, 0) + gtk_widget_get_preferred_size (GTK_WIDGET (fixedtip), &req, NULL); +#else gtk_widget_size_request (GTK_WIDGET (fixedtip), &req); +#endif gdk_window_get_origin (parent_window, &root_x, &root_y); - #if GTK_CHECK_VERSION(3, 0, 0) - parent_width = gdk_window_get_width(parent_window); - parent_height = gdk_window_get_height(parent_window); - #else - gdk_drawable_get_size(GDK_DRAWABLE(parent_window), &parent_width, &parent_height); - #endif - +#if GTK_CHECK_VERSION(3, 0, 0) + parent_width = gdk_window_get_width(parent_window); + parent_height = gdk_window_get_height(parent_window); +#else + gdk_drawable_get_size(GDK_DRAWABLE(parent_window), &parent_width, &parent_height); +#endif screen_width = gdk_screen_get_width (screen); screen_height = gdk_screen_get_height (screen); diff --git a/applets/notification_area/main.c b/applets/notification_area/main.c index f752ca02..0b63bf65 100644 --- a/applets/notification_area/main.c +++ b/applets/notification_area/main.c @@ -141,7 +141,11 @@ static const GtkActionEntry menu_actions [] = { G_CALLBACK (about_cb) } }; +#if GTK_CHECK_VERSION (3, 0, 0) +static void applet_change_background(MatePanelApplet* applet, MatePanelAppletBackgroundType type, GdkColor* color, cairo_pattern_t *pattern, AppletData* data) +#else static void applet_change_background(MatePanelApplet* applet, MatePanelAppletBackgroundType type, GdkColor* color, GdkPixmap* pixmap, AppletData* data) +#endif { na_tray_force_redraw(data->tray); } diff --git a/applets/notification_area/na-tray-child.c b/applets/notification_area/na-tray-child.c index 5160d699..93ac4bb8 100644 --- a/applets/notification_area/na-tray-child.c +++ b/applets/notification_area/na-tray-child.c @@ -54,21 +54,33 @@ na_tray_child_realize (GtkWidget *widget) * extension. */ /* Set a transparent background */ +#if GTK_CHECK_VERSION (3, 0, 0) + cairo_pattern_t *transparent = cairo_pattern_create_rgba (0, 0, 0, 0); + gdk_window_set_background_pattern (window, transparent); +#else GdkColor transparent = { 0, 0, 0, 0 }; /* only pixel=0 matters */ gdk_window_set_background (window, &transparent); +#endif gdk_window_set_composited (window, TRUE); +#if GTK_CHECK_VERSION (3, 0, 0) + cairo_pattern_destroy (transparent); +#endif child->parent_relative_bg = FALSE; - } - #if GTK_CHECK_VERSION(3, 0, 0) - else if (visual == gdk_window_get_visual(gdk_window_get_parent(window))) - #else - else if (visual == gdk_drawable_get_visual(GDK_DRAWABLE(gdk_window_get_parent(window)))) - #endif - { + } +#if GTK_CHECK_VERSION(3, 0, 0) + else if (visual == gdk_window_get_visual(gdk_window_get_parent(window))) +#else + else if (visual == gdk_drawable_get_visual(GDK_DRAWABLE(gdk_window_get_parent(window)))) +#endif + { /* Otherwise, if the visual matches the visual of the parent window, we * can use a parent-relative background and fake transparency. */ +#if GTK_CHECK_VERSION (3, 0, 0) + gdk_window_set_background_pattern (window, NULL); +#else gdk_window_set_back_pixmap (window, NULL, TRUE); +#endif child->parent_relative_bg = TRUE; } @@ -180,8 +192,13 @@ na_tray_child_size_allocate (GtkWidget *widget, * expose handler draws with real or fake transparency. */ static gboolean +#if GTK_CHECK_VERSION (3, 0, 0) +na_tray_child_draw (GtkWidget *widget, + cairo_t *cr) +#else na_tray_child_expose_event (GtkWidget *widget, GdkEventExpose *event) +#endif { NaTrayChild *child = NA_TRAY_CHILD (widget); GdkWindow *window = gtk_widget_get_window (widget); @@ -189,19 +206,50 @@ na_tray_child_expose_event (GtkWidget *widget, if (na_tray_child_has_alpha (child)) { /* Clear to transparent */ +#if !GTK_CHECK_VERSION (3, 0, 0) cairo_t *cr = gdk_cairo_create (window); +#endif cairo_set_source_rgba (cr, 0, 0, 0, 0); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); +#if GTK_CHECK_VERSION (3, 0, 0) + cairo_paint (cr); +#else gdk_cairo_region (cr, event->region); cairo_fill (cr); cairo_destroy (cr); +#endif } else if (child->parent_relative_bg) { /* Clear to parent-relative pixmap */ +#if GTK_CHECK_VERSION (3, 0, 0) + GdkWindow *window; + cairo_surface_t *target; + GdkRectangle clip_rect; + + window = gtk_widget_get_window (widget); + target = cairo_get_group_target (cr); + + gdk_cairo_get_clip_rectangle (cr, &clip_rect); + + /* Clear to parent-relative pixmap + * We need to use direct X access here because GDK doesn't know about + * the parent relative pixmap. */ + cairo_surface_flush (target); + + XClearArea (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XID (window), + clip_rect.x, clip_rect.y, + clip_rect.width, clip_rect.height, + False); + cairo_surface_mark_dirty_rectangle (target, + clip_rect.x, clip_rect.y, + clip_rect.width, clip_rect.height); +#else gdk_window_clear_area (window, event->area.x, event->area.y, event->area.width, event->area.height); +#endif } return FALSE; @@ -225,7 +273,11 @@ na_tray_child_class_init (NaTrayChildClass *klass) widget_class->style_set = na_tray_child_style_set; widget_class->realize = na_tray_child_realize; widget_class->size_allocate = na_tray_child_size_allocate; +#if GTK_CHECK_VERSION (3, 0, 0) + widget_class->draw = na_tray_child_draw; +#else widget_class->expose_event = na_tray_child_expose_event; +#endif } GtkWidget * @@ -237,8 +289,10 @@ na_tray_child_new (GdkScreen *screen, NaTrayChild *child; GdkVisual *visual; gboolean visual_has_alpha; +#if !GTK_CHECK_VERSION (3, 0, 0) GdkColormap *colormap; gboolean new_colormap; +#endif int red_prec, green_prec, blue_prec, depth; int result; @@ -264,6 +318,7 @@ na_tray_child_new (GdkScreen *screen, if (!visual) /* Icon window is on another screen? */ return NULL; +#if !GTK_CHECK_VERSION (3, 0, 0) new_colormap = FALSE; if (visual == gdk_screen_get_rgb_visual (screen)) @@ -277,11 +332,16 @@ na_tray_child_new (GdkScreen *screen, colormap = gdk_colormap_new (visual, FALSE); new_colormap = TRUE; } +#endif child = g_object_new (NA_TYPE_TRAY_CHILD, NULL); child->icon_window = icon_window; +#if GTK_CHECK_VERSION (3, 0, 0) + gtk_widget_set_visual (GTK_WIDGET (child), visual); +#else gtk_widget_set_colormap (GTK_WIDGET (child), colormap); +#endif /* We have alpha if the visual has something other than red, green, * and blue */ @@ -296,8 +356,10 @@ na_tray_child_new (GdkScreen *screen, child->composited = child->has_alpha; +#if !GTK_CHECK_VERSION (3, 0, 0) if (new_colormap) g_object_unref (colormap); +#endif return GTK_WIDGET (child); } @@ -426,7 +488,11 @@ na_tray_child_force_redraw (NaTrayChild *child) gtk_widget_get_allocation (widget, &allocation); xev.xexpose.type = Expose; +#if GTK_CHECK_VERSION (3, 0, 0) + xev.xexpose.window = GDK_WINDOW_XID (plug_window); +#else xev.xexpose.window = GDK_WINDOW_XWINDOW (plug_window); +#endif xev.xexpose.x = 0; xev.xexpose.y = 0; xev.xexpose.width = allocation.width; diff --git a/applets/notification_area/na-tray-child.h b/applets/notification_area/na-tray-child.h index 8dd7202a..9427d74b 100644 --- a/applets/notification_area/na-tray-child.h +++ b/applets/notification_area/na-tray-child.h @@ -26,6 +26,10 @@ #include #include +#if GTK_CHECK_VERSION (3, 0, 0) +#include +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/applets/notification_area/na-tray-manager.c b/applets/notification_area/na-tray-manager.c index 9a397109..1a2acc7f 100644 --- a/applets/notification_area/na-tray-manager.c +++ b/applets/notification_area/na-tray-manager.c @@ -26,7 +26,12 @@ #include "na-tray-manager.h" +#include +#if GTK_CHECK_VERSION (3, 0, 0) +#define GDK_WINDOW_XWINDOW GDK_WINDOW_XID +#else #include +#endif #include #if defined (GDK_WINDOWING_X11) #include @@ -34,7 +39,6 @@ #elif defined (GDK_WINDOWING_WIN32) #include #endif -#include #include "na-marshal.h" @@ -316,18 +320,28 @@ pending_message_free (PendingMessage *message) g_free (message); } +#if GTK_CHECK_VERSION (3, 0, 0) +static void +na_tray_manager_handle_message_data (NaTrayManager *manager, + XClientMessageEvent *xevent) +#else static GdkFilterReturn na_tray_manager_handle_client_message_message_data (GdkXEvent *xev, GdkEvent *event, gpointer data) +#endif { +#if !GTK_CHECK_VERSION (3, 0, 0) XClientMessageEvent *xevent; NaTrayManager *manager; +#endif GList *p; int len; +#if !GTK_CHECK_VERSION (3, 0, 0) xevent = (XClientMessageEvent *) xev; manager = data; +#endif /* Try to see if we can find the pending message in the list */ for (p = manager->messages; p; p = p->next) @@ -363,7 +377,9 @@ na_tray_manager_handle_client_message_message_data (GdkXEvent *xev, } } +#if !GTK_CHECK_VERSION (3, 0, 0) return GDK_FILTER_REMOVE; +#endif } static void @@ -455,6 +471,7 @@ na_tray_manager_handle_cancel_message (NaTrayManager *manager, } } +#if !GTK_CHECK_VERSION (3, 0, 0) static GdkFilterReturn na_tray_manager_handle_client_message_opcode (GdkXEvent *xev, GdkEvent *event, @@ -487,6 +504,7 @@ na_tray_manager_handle_client_message_opcode (GdkXEvent *xev, return GDK_FILTER_CONTINUE; } +#endif static GdkFilterReturn na_tray_manager_window_filter (GdkXEvent *xev, @@ -507,6 +525,31 @@ na_tray_manager_window_filter (GdkXEvent *xev, (XClientMessageEvent *) xevent); return GDK_FILTER_REMOVE; } +#if GTK_CHECK_VERSION (3, 0, 0) + /* _NET_SYSTEM_TRAY_OPCODE: SYSTEM_TRAY_BEGIN_MESSAGE */ + else if (xevent->xclient.message_type == manager->opcode_atom && + xevent->xclient.data.l[1] == SYSTEM_TRAY_BEGIN_MESSAGE) + { + na_tray_manager_handle_begin_message (manager, + (XClientMessageEvent *) event); + return GDK_FILTER_REMOVE; + } + /* _NET_SYSTEM_TRAY_OPCODE: SYSTEM_TRAY_CANCEL_MESSAGE */ + else if (xevent->xclient.message_type == manager->opcode_atom && + xevent->xclient.data.l[1] == SYSTEM_TRAY_CANCEL_MESSAGE) + { + na_tray_manager_handle_cancel_message (manager, + (XClientMessageEvent *) event); + return GDK_FILTER_REMOVE; + } + /* _NET_SYSTEM_TRAY_MESSAGE_DATA */ + else if (xevent->xclient.message_type == manager->message_data_atom) + { + na_tray_manager_handle_message_data (manager, + (XClientMessageEvent *) event); + return GDK_FILTER_REMOVE; + } +#endif } else if (xevent->type == SelectionClear) { @@ -564,9 +607,12 @@ na_tray_manager_unmanage (NaTrayManager *manager) TRUE); } +/* fixed in GTK3 */ +#if !GTK_CHECK_VERSION (3, 0, 0) //FIXME: we should also use gdk_remove_client_message_filter when it's //available // See bug #351254 +#endif gdk_window_remove_filter (window, na_tray_manager_window_filter, manager); @@ -647,10 +693,14 @@ na_tray_manager_set_visual_property (NaTrayManager *manager) * be embedded. In almost all cases, this will be the same as the visual * of the screen. */ +#if GTK_CHECK_VERSION (3, 0, 0) + xvisual = GDK_VISUAL_XVISUAL (gdk_screen_get_system_visual (manager->screen)); +#else GdkColormap *colormap; colormap = gdk_screen_get_default_colormap (manager->screen); xvisual = GDK_VISUAL_XVISUAL (gdk_colormap_get_visual (colormap)); +#endif } data[0] = XVisualIDFromVisual (xvisual); @@ -749,6 +799,12 @@ na_tray_manager_manage_screen_x11 (NaTrayManager *manager, message_data_atom = gdk_atom_intern ("_NET_SYSTEM_TRAY_MESSAGE_DATA", FALSE); +#if GTK_CHECK_VERSION (3, 0, 0) + manager->message_data_atom = gdk_x11_atom_to_xatom_for_display (display, + message_data_atom); +#endif + + /* Add a window filter */ #if 0 /* This is for when we lose the selection of _NET_SYSTEM_TRAY_Sx */ @@ -759,6 +815,7 @@ na_tray_manager_manage_screen_x11 (NaTrayManager *manager, /* This is for SYSTEM_TRAY_REQUEST_DOCK and SelectionClear */ gdk_window_add_filter (window, na_tray_manager_window_filter, manager); +#if !GTK_CHECK_VERSION (3, 0, 0) /* This is for SYSTEM_TRAY_BEGIN_MESSAGE and SYSTEM_TRAY_CANCEL_MESSAGE */ gdk_display_add_client_message_filter (display, opcode_atom, na_tray_manager_handle_client_message_opcode, @@ -767,6 +824,7 @@ na_tray_manager_manage_screen_x11 (NaTrayManager *manager, gdk_display_add_client_message_filter (display, message_data_atom, na_tray_manager_handle_client_message_message_data, manager); +#endif return TRUE; } else diff --git a/applets/notification_area/na-tray-manager.h b/applets/notification_area/na-tray-manager.h index 19d03081..e98c4848 100644 --- a/applets/notification_area/na-tray-manager.h +++ b/applets/notification_area/na-tray-manager.h @@ -52,6 +52,9 @@ struct _NaTrayManager #ifdef GDK_WINDOWING_X11 GdkAtom selection_atom; Atom opcode_atom; +#if GTK_CHECK_VERSION (3, 0, 0) + Atom message_data_atom; +#endif #endif GtkWidget *invisible; diff --git a/applets/notification_area/na-tray.c b/applets/notification_area/na-tray.c index 61f9b568..e6359581 100644 --- a/applets/notification_area/na-tray.c +++ b/applets/notification_area/na-tray.c @@ -527,7 +527,11 @@ update_size_and_orientation (NaTray *tray) * gdk_window_set_composited(). We need to paint these children ourselves. */ static void +#if GTK_CHECK_VERSION (3, 0, 0) +na_tray_draw_icon (GtkWidget *widget, +#else na_tray_expose_icon (GtkWidget *widget, +#endif gpointer data) { cairo_t *cr = data; @@ -538,18 +542,39 @@ na_tray_expose_icon (GtkWidget *widget, gtk_widget_get_allocation (widget, &allocation); +#if GTK_CHECK_VERSION (3, 0, 0) + cairo_save (cr); + gdk_cairo_set_source_window (cr, + gtk_widget_get_window (widget), + allocation.x, + allocation.y); + cairo_rectangle (cr, allocation.x, allocation.y, allocation.width, allocation.height); + cairo_clip (cr); +#else gdk_cairo_set_source_pixmap (cr, gtk_widget_get_window (widget), allocation.x, allocation.y); +#endif cairo_paint (cr); +#if GTK_CHECK_VERSION (3, 0, 0) + cairo_restore (cr); +#endif } } static void +#if GTK_CHECK_VERSION (3, 0, 0) +na_tray_draw_box (GtkWidget *box, + cairo_t *cr) +#else na_tray_expose_box (GtkWidget *box, - GdkEventExpose *event) + GdkEventExpose *event) +#endif { +#if GTK_CHECK_VERSION (3, 0, 0) + gtk_container_foreach (GTK_CONTAINER (box), na_tray_draw_icon, cr); +#else cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (box)); gdk_cairo_region (cr, event->region); @@ -558,6 +583,7 @@ na_tray_expose_box (GtkWidget *box, gtk_container_foreach (GTK_CONTAINER (box), na_tray_expose_icon, cr); cairo_destroy (cr); +#endif } static void @@ -575,8 +601,13 @@ na_tray_init (NaTray *tray) gtk_widget_show (priv->frame); priv->box = g_object_new (na_box_get_type (), NULL); +#if GTK_CHECK_VERSION (3, 0, 0) + g_signal_connect (priv->box, "draw", + G_CALLBACK (na_tray_draw_box), NULL); +#else g_signal_connect (priv->box, "expose-event", - G_CALLBACK (na_tray_expose_box), tray); + G_CALLBACK (na_tray_expose_box), tray); +#endif gtk_box_set_spacing (GTK_BOX (priv->box), ICON_SPACING); gtk_container_add (GTK_CONTAINER (priv->frame), priv->box); gtk_widget_show (priv->box); @@ -729,12 +760,34 @@ na_tray_set_property (GObject *object, } } +#if GTK_CHECK_VERSION (3, 0, 0) +static void +na_tray_get_preferred_width (GtkWidget *widget, + gint *minimal_width, + gint *natural_width) +{ + gtk_widget_get_preferred_width (gtk_bin_get_child (GTK_BIN (widget)), + minimal_width, + natural_width); +} + +static void +na_tray_get_preferred_height (GtkWidget *widget, + gint *minimal_height, + gint *natural_height) +{ + gtk_widget_get_preferred_height (gtk_bin_get_child (GTK_BIN (widget)), + minimal_height, + natural_height); +} +#else static void na_tray_size_request (GtkWidget *widget, GtkRequisition *requisition) { gtk_widget_size_request (gtk_bin_get_child (GTK_BIN (widget)), requisition); } +#endif static void na_tray_size_allocate (GtkWidget *widget, @@ -753,7 +806,12 @@ na_tray_class_init (NaTrayClass *klass) gobject_class->set_property = na_tray_set_property; gobject_class->dispose = na_tray_dispose; +#if GTK_CHECK_VERSION (3, 0, 0) + widget_class->get_preferred_width = na_tray_get_preferred_width; + widget_class->get_preferred_height = na_tray_get_preferred_height; +#else widget_class->size_request = na_tray_size_request; +#endif widget_class->size_allocate = na_tray_size_allocate; g_object_class_install_property diff --git a/applets/notification_area/testtray.c b/applets/notification_area/testtray.c index f6a9111e..9feed828 100644 --- a/applets/notification_area/testtray.c +++ b/applets/notification_area/testtray.c @@ -162,9 +162,15 @@ create_tray_on_screen (GdkScreen *screen, label = gtk_label_new_with_mnemonic ("_Orientation:"); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); +#if GTK_CHECK_VERSION (3, 0, 0) + combo = gtk_combo_box_text_new (); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "Horizontal"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "Vertical"); +#else combo = gtk_combo_box_new_text (); gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "Horizontal"); gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "Vertical"); +#endif g_signal_connect (combo, "changed", G_CALLBACK (orientation_changed_cb), data); gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, FALSE, 0); -- cgit v1.2.1