diff options
Diffstat (limited to 'mate-volume-control/gvc-stream-status-icon.c')
-rw-r--r-- | mate-volume-control/gvc-stream-status-icon.c | 238 |
1 files changed, 126 insertions, 112 deletions
diff --git a/mate-volume-control/gvc-stream-status-icon.c b/mate-volume-control/gvc-stream-status-icon.c index f48a370..558dd55 100644 --- a/mate-volume-control/gvc-stream-status-icon.c +++ b/mate-volume-control/gvc-stream-status-icon.c @@ -2,7 +2,6 @@ * * Copyright (C) 2008 William Jon McCann * Copyright (C) 2014 Michal Ratajsky <[email protected]> - * Copyright (C) 2019 Victor Kareh <[email protected]> * * 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 @@ -26,7 +25,6 @@ #include <gdk/gdkkeysyms.h> #include <libmatemixer/matemixer.h> -#include <mate-panel-applet.h> #define MATE_DESKTOP_USE_UNSTABLE_API #include <libmate-desktop/mate-desktop-utils.h> @@ -38,15 +36,12 @@ struct _GvcStreamStatusIconPrivate { - gchar **icon_names; - GtkImage *image; - GtkWidget *dock; - GtkWidget *bar; - guint current_icon; - gchar *display_name; + gchar **icon_names; + GtkWidget *dock; + GtkWidget *bar; + guint current_icon; + gchar *display_name; MateMixerStreamControl *control; - MatePanelAppletOrient orient; - guint size; }; enum @@ -64,52 +59,61 @@ 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_EVENT_BOX) +G_DEFINE_TYPE (GvcStreamStatusIcon, gvc_stream_status_icon, GTK_TYPE_STATUS_ICON) static gboolean popup_dock (GvcStreamStatusIcon *icon, guint time) { - GtkAllocation allocation; + GdkRectangle area; + GtkOrientation orientation; GdkDisplay *display; GdkScreen *screen; - int x, y; + int x; + int y; GdkMonitor *monitor_num; GdkRectangle monitor; GtkRequisition dock_req; - 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); + 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; + } /* position roughly */ gtk_window_set_screen (GTK_WINDOW (icon->priv->dock), screen); - gvc_channel_bar_set_orientation (GVC_CHANNEL_BAR (icon->priv->bar), icon->priv->orient); + gvc_channel_bar_set_orientation (GVC_CHANNEL_BAR (icon->priv->bar), + 1 - orientation); - monitor_num = gdk_display_get_monitor_at_point (gdk_screen_get_display (screen), allocation.x, allocation.y); + monitor_num = gdk_display_get_monitor_at_point (gdk_screen_get_display (screen), area.x, area.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 (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; + if (orientation == GTK_ORIENTATION_VERTICAL) { + if (area.x + area.width + dock_req.width <= monitor.x + monitor.width) + x = area.x + area.width; else - x = allocation.x - dock_req.width; + x = area.x - dock_req.width; - if (allocation.y + dock_req.height <= monitor.y + monitor.height) - y = allocation.y; + if (area.y + dock_req.height <= monitor.y + monitor.height) + y = area.y; else y = monitor.y + monitor.height - dock_req.height; } else { - if (allocation.y + allocation.height + dock_req.height <= monitor.y + monitor.height) - y = allocation.y + allocation.height; + if (area.y + area.height + dock_req.height <= monitor.y + monitor.height) + y = area.y + area.height; else - y = allocation.y - dock_req.height; + y = area.y - dock_req.height; - if (allocation.x + dock_req.width <= monitor.x + monitor.width) - x = allocation.x; + if (area.x + dock_req.width <= monitor.x + monitor.width) + x = area.x; else x = monitor.x + monitor.width - dock_req.width; } @@ -150,16 +154,17 @@ 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 (GtkWidget *status_icon, +on_status_icon_button_press (GtkStatusIcon *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); @@ -170,20 +175,19 @@ on_status_icon_button_press (GtkWidget *status_icon, return FALSE; } -void -gvc_stream_status_icon_set_mute (GvcStreamStatusIcon *icon, gboolean mute) +static void +on_menu_mute_toggled (GtkMenuItem *item, GvcStreamStatusIcon *icon) { - mate_mixer_stream_control_set_mute (icon->priv->control, mute); -} + gboolean is_muted; -gboolean -gvc_stream_status_icon_get_mute (GvcStreamStatusIcon *icon) -{ - return mate_mixer_stream_control_get_mute (icon->priv->control); + is_muted = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)); + + mate_mixer_stream_control_set_mute (icon->priv->control, is_muted); } -void -gvc_stream_status_icon_volume_control (GvcStreamStatusIcon *icon) +static void +on_menu_activate_open_volume_control (GtkMenuItem *item, + GvcStreamStatusIcon *icon) { GError *error = NULL; @@ -209,8 +213,64 @@ gvc_stream_status_icon_volume_control (GvcStreamStatusIcon *icon) } } +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 (GtkWidget *event_box, +on_status_icon_scroll_event (GtkStatusIcon *status_icon, GdkEventScroll *event, GvcStreamStatusIcon *icon) { @@ -312,23 +372,6 @@ on_dock_scroll_event (GtkWidget *widget, } 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, - GTK_ICON_LOOKUP_FORCE_SIZE, - NULL); - - gtk_image_set_from_surface (GTK_IMAGE (icon->priv->image), surface); - cairo_surface_destroy (surface); -} - -static void update_icon (GvcStreamStatusIcon *icon) { guint volume = 0; @@ -343,10 +386,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_widget_set_has_tooltip (GTK_WIDGET (icon), FALSE); + gtk_status_icon_set_has_tooltip (GTK_STATUS_ICON (icon), FALSE); return; } else - gtk_widget_set_has_tooltip (GTK_WIDGET (icon), TRUE); + gtk_status_icon_set_has_tooltip (GTK_STATUS_ICON (icon), TRUE); flags = mate_mixer_stream_control_get_flags (icon->priv->control); @@ -369,7 +412,8 @@ update_icon (GvcStreamStatusIcon *icon) /* Apparently status icon will reset icon even if it doesn't change */ if (icon->priv->current_icon != n) { - gvc_stream_status_icon_set_icon_from_name (icon, icon->priv->icon_names[n]); + gtk_status_icon_set_from_icon_name (GTK_STATUS_ICON (icon), + icon->priv->icon_names[n]); icon->priv->current_icon = n; } @@ -410,47 +454,12 @@ update_icon (GvcStreamStatusIcon *icon) description); } - gtk_widget_set_tooltip_markup (GTK_WIDGET (icon), markup); + gtk_status_icon_set_tooltip_markup (GTK_STATUS_ICON (icon), markup); g_free (markup); } void -gvc_stream_status_icon_set_size (GvcStreamStatusIcon *icon, - guint size) -{ - - /*Iterate through the icon sizes so they can be kept sharp*/ - if (size < 22) - size = 16; - else if (size < 24) - size = 22; - else if (size < 32) - size = 24; - else if (size < 48) - size = 32; - else - size = 48; - 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) -{ - /*Sometimes orient does not get properly defined especially on a bottom panel - *Use the applet orientation if it is valid, otherwise set a vertical slider - *Otherwise bottom panels get a horizontal slider - */ - if (orient) - icon->priv->orient = orient; - else - icon->priv->orient = MATE_PANEL_APPLET_ORIENT_DOWN; -} - -void gvc_stream_status_icon_set_icon_names (GvcStreamStatusIcon *icon, const gchar **names) { @@ -468,7 +477,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 */ - gvc_stream_status_icon_set_icon_from_name (icon, names[0]); + gtk_status_icon_set_from_icon_name (GTK_STATUS_ICON (icon), names[0]); update_icon (icon); g_object_notify_by_pspec (G_OBJECT (icon), properties[PROP_ICON_NAMES]); @@ -656,7 +665,7 @@ gvc_stream_status_icon_class_init (GvcStreamStatusIconClass *klass) static void on_status_icon_visible_notify (GvcStreamStatusIcon *icon) { - if (gtk_widget_get_visible (GTK_WIDGET (icon)) == FALSE) + if (gtk_status_icon_get_visible (GTK_STATUS_ICON (icon)) == FALSE) gtk_widget_hide (icon->priv->dock); } @@ -665,8 +674,8 @@ on_icon_theme_change (GtkSettings *settings, GParamSpec *pspec, GvcStreamStatusIcon *icon) { - gvc_stream_status_icon_set_icon_from_name (icon, - icon->priv->icon_names[icon->priv->current_icon]); + gtk_status_icon_set_from_icon_name (GTK_STATUS_ICON (icon), + icon->priv->icon_names[icon->priv->current_icon]); } static void @@ -677,18 +686,23 @@ gvc_stream_status_icon_init (GvcStreamStatusIcon *icon) icon->priv = GVC_STREAM_STATUS_ICON_GET_PRIVATE (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), + g_signal_connect (G_OBJECT (icon), + "activate", + G_CALLBACK (on_status_icon_activate), + icon); + g_signal_connect (G_OBJECT (icon), "button-press-event", G_CALLBACK (on_status_icon_button_press), icon); - g_signal_connect (GTK_WIDGET (icon), + g_signal_connect (G_OBJECT (icon), + "popup-menu", + G_CALLBACK (on_status_icon_popup_menu), + icon); + g_signal_connect (G_OBJECT (icon), "scroll-event", G_CALLBACK (on_status_icon_scroll_event), icon); - g_signal_connect (GTK_WIDGET (icon), + g_signal_connect (G_OBJECT (icon), "notify::visible", G_CALLBACK (on_status_icon_visible_notify), NULL); |