From 897643c70861373393ac9f387ddc244930e16aeb Mon Sep 17 00:00:00 2001 From: Victor Kareh Date: Thu, 7 Feb 2019 12:17:22 -0500 Subject: Convert GtkStatusIcon to real applet --- mate-volume-control/gvc-stream-status-icon.c | 221 +++++++++++---------------- 1 file changed, 93 insertions(+), 128 deletions(-) (limited to 'mate-volume-control/gvc-stream-status-icon.c') diff --git a/mate-volume-control/gvc-stream-status-icon.c b/mate-volume-control/gvc-stream-status-icon.c index 70501c9..d4c1509 100644 --- a/mate-volume-control/gvc-stream-status-icon.c +++ b/mate-volume-control/gvc-stream-status-icon.c @@ -2,6 +2,7 @@ * * Copyright (C) 2008 William Jon McCann * Copyright (C) 2014 Michal Ratajsky + * Copyright (C) 2019 Victor Kareh * * 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 @@ -25,6 +26,7 @@ #include #include +#include #define MATE_DESKTOP_USE_UNSTABLE_API #include @@ -36,12 +38,15 @@ struct _GvcStreamStatusIconPrivate { - gchar **icon_names; - GtkWidget *dock; - GtkWidget *bar; - guint current_icon; - gchar *display_name; + gchar **icon_names; + GtkImage *image; + GtkWidget *dock; + GtkWidget *bar; + guint current_icon; + gchar *display_name; MateMixerStreamControl *control; + MatePanelAppletOrient orient; + guint size; }; enum @@ -59,61 +64,52 @@ static void gvc_stream_status_icon_class_init (GvcStreamStatusIconClass *klass); static void gvc_stream_status_icon_init (GvcStreamStatusIcon *stream_status_icon); static void gvc_stream_status_icon_finalize (GObject *object); -G_DEFINE_TYPE (GvcStreamStatusIcon, gvc_stream_status_icon, GTK_TYPE_STATUS_ICON) +G_DEFINE_TYPE (GvcStreamStatusIcon, gvc_stream_status_icon, GTK_TYPE_EVENT_BOX) static gboolean popup_dock (GvcStreamStatusIcon *icon, guint time) { - GdkRectangle area; - GtkOrientation orientation; + GtkAllocation allocation; GdkDisplay *display; GdkScreen *screen; - int x; - int y; + int x, y; GdkMonitor *monitor_num; GdkRectangle monitor; GtkRequisition dock_req; - screen = gtk_status_icon_get_screen (GTK_STATUS_ICON (icon)); - - if (gtk_status_icon_get_geometry (GTK_STATUS_ICON (icon), - &screen, - &area, - &orientation) == FALSE) { - g_warning ("Unable to determine geometry of status icon"); - return FALSE; - } + screen = gtk_widget_get_screen (GTK_WIDGET (icon)); + gtk_widget_get_allocation (GTK_WIDGET (icon), &allocation); + gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (icon)), &allocation.x, &allocation.y); /* position roughly */ gtk_window_set_screen (GTK_WINDOW (icon->priv->dock), screen); - gvc_channel_bar_set_orientation (GVC_CHANNEL_BAR (icon->priv->bar), - 1 - orientation); + gvc_channel_bar_set_orientation (GVC_CHANNEL_BAR (icon->priv->bar), icon->priv->orient); - monitor_num = gdk_display_get_monitor_at_point (gdk_screen_get_display (screen), area.x, area.y); + monitor_num = gdk_display_get_monitor_at_point (gdk_screen_get_display (screen), allocation.x, allocation.y); gdk_monitor_get_geometry (monitor_num, &monitor); gtk_container_foreach (GTK_CONTAINER (icon->priv->dock), (GtkCallback) gtk_widget_show_all, NULL); gtk_widget_get_preferred_size (icon->priv->dock, &dock_req, NULL); - if (orientation == GTK_ORIENTATION_VERTICAL) { - if (area.x + area.width + dock_req.width <= monitor.x + monitor.width) - x = area.x + area.width; + if (icon->priv->orient == MATE_PANEL_APPLET_ORIENT_LEFT || icon->priv->orient == MATE_PANEL_APPLET_ORIENT_RIGHT) { + if (allocation.x + allocation.width + dock_req.width <= monitor.x + monitor.width) + x = allocation.x + allocation.width; else - x = area.x - dock_req.width; + x = allocation.x - dock_req.width; - if (area.y + dock_req.height <= monitor.y + monitor.height) - y = area.y; + if (allocation.y + dock_req.height <= monitor.y + monitor.height) + y = allocation.y; else y = monitor.y + monitor.height - dock_req.height; } else { - if (area.y + area.height + dock_req.height <= monitor.y + monitor.height) - y = area.y + area.height; + if (allocation.y + allocation.height + dock_req.height <= monitor.y + monitor.height) + y = allocation.y + allocation.height; else - y = area.y - dock_req.height; + y = allocation.y - dock_req.height; - if (area.x + dock_req.width <= monitor.x + monitor.width) - x = area.x; + if (allocation.x + dock_req.width <= monitor.x + monitor.width) + x = allocation.x; else x = monitor.x + monitor.width - dock_req.width; } @@ -154,17 +150,16 @@ popup_dock (GvcStreamStatusIcon *icon, guint time) return TRUE; } -static void -on_status_icon_activate (GtkStatusIcon *status_icon, GvcStreamStatusIcon *icon) -{ - popup_dock (icon, GDK_CURRENT_TIME); -} - static gboolean -on_status_icon_button_press (GtkStatusIcon *status_icon, +on_status_icon_button_press (GtkWidget *status_icon, GdkEventButton *event, GvcStreamStatusIcon *icon) { + if (event->button == 1) { + popup_dock (icon, GDK_CURRENT_TIME); + return TRUE; + } + /* Middle click acts as mute/unmute */ if (event->button == 2) { gboolean is_muted = mate_mixer_stream_control_get_mute (icon->priv->control); @@ -175,19 +170,20 @@ on_status_icon_button_press (GtkStatusIcon *status_icon, return FALSE; } -static void -on_menu_mute_toggled (GtkMenuItem *item, GvcStreamStatusIcon *icon) +void +gvc_stream_status_icon_set_mute (GvcStreamStatusIcon *icon, gboolean mute) { - gboolean is_muted; - - is_muted = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)); + mate_mixer_stream_control_set_mute (icon->priv->control, mute); +} - mate_mixer_stream_control_set_mute (icon->priv->control, is_muted); +gboolean +gvc_stream_status_icon_get_mute (GvcStreamStatusIcon *icon) +{ + return mate_mixer_stream_control_get_mute (icon->priv->control); } -static void -on_menu_activate_open_volume_control (GtkMenuItem *item, - GvcStreamStatusIcon *icon) +void +gvc_stream_status_icon_volume_control (GvcStreamStatusIcon *icon) { GError *error = NULL; @@ -213,64 +209,8 @@ on_menu_activate_open_volume_control (GtkMenuItem *item, } } -static void -on_status_icon_popup_menu (GtkStatusIcon *status_icon, - guint button, - guint activate_time, - GvcStreamStatusIcon *icon) -{ - GtkWidget *menu; - GtkWidget *item; - GtkWidget *image; - - menu = gtk_menu_new (); - - /*Set up theme and transparency support*/ - GtkWidget *toplevel = gtk_widget_get_toplevel (menu); - /* Fix any failures of compiz/other wm's to communicate with gtk for transparency */ - GdkScreen *screen = gtk_widget_get_screen(GTK_WIDGET(toplevel)); - GdkVisual *visual = gdk_screen_get_rgba_visual(screen); - gtk_widget_set_visual(GTK_WIDGET(toplevel), visual); - /* Set menu and it's toplevel window to follow panel theme */ - GtkStyleContext *context; - context = gtk_widget_get_style_context (GTK_WIDGET(toplevel)); - gtk_style_context_add_class(context,"gnome-panel-menu-bar"); - gtk_style_context_add_class(context,"mate-panel-menu-bar"); - - item = gtk_check_menu_item_new_with_mnemonic (_("_Mute")); - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), - mate_mixer_stream_control_get_mute (icon->priv->control)); - g_signal_connect (G_OBJECT (item), - "toggled", - G_CALLBACK (on_menu_mute_toggled), - icon); - - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - - item = gtk_image_menu_item_new_with_mnemonic (_("_Sound Preferences")); - image = gtk_image_new_from_icon_name ("multimedia-volume-control", - GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); - - g_signal_connect (G_OBJECT (item), - "activate", - G_CALLBACK (on_menu_activate_open_volume_control), - icon); - - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - - gtk_widget_show_all (menu); - gtk_menu_popup (GTK_MENU (menu), - NULL, - NULL, - gtk_status_icon_position_menu, - status_icon, - button, - activate_time); -} - static gboolean -on_status_icon_scroll_event (GtkStatusIcon *status_icon, +on_status_icon_scroll_event (GtkWidget *event_box, GdkEventScroll *event, GvcStreamStatusIcon *icon) { @@ -371,6 +311,21 @@ on_dock_scroll_event (GtkWidget *widget, return TRUE; } +static void +gvc_stream_status_icon_set_icon_from_name (GvcStreamStatusIcon *icon, + const gchar *icon_name) +{ + GtkIconTheme *icon_theme = gtk_icon_theme_get_default (); + gint icon_scale = gtk_widget_get_scale_factor (GTK_WIDGET (icon)); + + cairo_surface_t* surface = gtk_icon_theme_load_surface (icon_theme, icon_name, + icon->priv->size, + icon_scale, NULL, 0, NULL); + + gtk_image_set_from_surface (GTK_IMAGE (icon->priv->image), surface); + cairo_surface_destroy (surface); +} + static void update_icon (GvcStreamStatusIcon *icon) { @@ -386,10 +341,10 @@ update_icon (GvcStreamStatusIcon *icon) if (icon->priv->control == NULL) { /* Do not bother creating a tooltip for an unusable icon as it * has no practical use */ - gtk_status_icon_set_has_tooltip (GTK_STATUS_ICON (icon), FALSE); + gtk_widget_set_has_tooltip (GTK_WIDGET (icon), FALSE); return; } else - gtk_status_icon_set_has_tooltip (GTK_STATUS_ICON (icon), TRUE); + gtk_widget_set_has_tooltip (GTK_WIDGET (icon), TRUE); flags = mate_mixer_stream_control_get_flags (icon->priv->control); @@ -412,8 +367,7 @@ update_icon (GvcStreamStatusIcon *icon) /* Apparently status icon will reset icon even if it doesn't change */ if (icon->priv->current_icon != n) { - gtk_status_icon_set_from_icon_name (GTK_STATUS_ICON (icon), - icon->priv->icon_names[n]); + gvc_stream_status_icon_set_icon_from_name (icon, icon->priv->icon_names[n]); icon->priv->current_icon = n; } @@ -454,11 +408,27 @@ update_icon (GvcStreamStatusIcon *icon) description); } - gtk_status_icon_set_tooltip_markup (GTK_STATUS_ICON (icon), markup); + gtk_widget_set_tooltip_markup (GTK_WIDGET (icon), markup); g_free (markup); } +void +gvc_stream_status_icon_set_size (GvcStreamStatusIcon *icon, + guint size) +{ + icon->priv->size = size; + gvc_stream_status_icon_set_icon_from_name (icon, + icon->priv->icon_names[icon->priv->current_icon]); +} + +void +gvc_stream_status_icon_set_orient (GvcStreamStatusIcon *icon, + MatePanelAppletOrient orient) +{ + icon->priv->orient = orient; +} + void gvc_stream_status_icon_set_icon_names (GvcStreamStatusIcon *icon, const gchar **names) @@ -477,7 +447,7 @@ gvc_stream_status_icon_set_icon_names (GvcStreamStatusIcon *icon, /* Set the first icon as the initial one, the icon may be immediately * updated or not depending on whether a stream is available */ - gtk_status_icon_set_from_icon_name (GTK_STATUS_ICON (icon), names[0]); + gvc_stream_status_icon_set_icon_from_name (icon, names[0]); update_icon (icon); g_object_notify_by_pspec (G_OBJECT (icon), properties[PROP_ICON_NAMES]); @@ -665,7 +635,7 @@ gvc_stream_status_icon_class_init (GvcStreamStatusIconClass *klass) static void on_status_icon_visible_notify (GvcStreamStatusIcon *icon) { - if (gtk_status_icon_get_visible (GTK_STATUS_ICON (icon)) == FALSE) + if (gtk_widget_get_visible (GTK_WIDGET (icon)) == FALSE) gtk_widget_hide (icon->priv->dock); } @@ -674,8 +644,8 @@ on_icon_theme_change (GtkSettings *settings, GParamSpec *pspec, GvcStreamStatusIcon *icon) { - gtk_status_icon_set_from_icon_name (GTK_STATUS_ICON (icon), - icon->priv->icon_names[icon->priv->current_icon]); + gvc_stream_status_icon_set_icon_from_name (icon, + icon->priv->icon_names[icon->priv->current_icon]); } static void @@ -686,23 +656,18 @@ gvc_stream_status_icon_init (GvcStreamStatusIcon *icon) icon->priv = GVC_STREAM_STATUS_ICON_GET_PRIVATE (icon); - g_signal_connect (G_OBJECT (icon), - "activate", - G_CALLBACK (on_status_icon_activate), - icon); - g_signal_connect (G_OBJECT (icon), + icon->priv->image = GTK_IMAGE (gtk_image_new ()); + gtk_container_add (GTK_CONTAINER (icon), GTK_WIDGET (icon->priv->image)); + + g_signal_connect (GTK_WIDGET (icon), "button-press-event", G_CALLBACK (on_status_icon_button_press), icon); - g_signal_connect (G_OBJECT (icon), - "popup-menu", - G_CALLBACK (on_status_icon_popup_menu), - icon); - g_signal_connect (G_OBJECT (icon), + g_signal_connect (GTK_WIDGET (icon), "scroll-event", G_CALLBACK (on_status_icon_scroll_event), icon); - g_signal_connect (G_OBJECT (icon), + g_signal_connect (GTK_WIDGET (icon), "notify::visible", G_CALLBACK (on_status_icon_visible_notify), NULL); @@ -741,8 +706,8 @@ gvc_stream_status_icon_init (GvcStreamStatusIcon *icon) gvc_channel_bar_set_orientation (GVC_CHANNEL_BAR (icon->priv->bar), GTK_ORIENTATION_VERTICAL); - - /* Set volume control frame, slider and toplevel window to follow panel theme */ + + /* Set volume control frame, slider and toplevel window to follow panel theme */ GtkWidget *toplevel = gtk_widget_get_toplevel (icon->priv->dock); GtkStyleContext *context; context = gtk_widget_get_style_context (GTK_WIDGET(toplevel)); -- cgit v1.2.1