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 --- configure.ac | 2 + mate-volume-control/Makefile.am | 130 +++++++----- mate-volume-control/applet-main.c | 61 +++--- mate-volume-control/gvc-applet.c | 145 +++++++++++++- mate-volume-control/gvc-applet.h | 2 + mate-volume-control/gvc-stream-status-icon.c | 221 +++++++++------------ mate-volume-control/gvc-stream-status-icon.h | 17 +- ....mate.applets.GvcApplet.mate-panel-applet.in.in | 11 + ...g.mate.panel.applet.GvcAppletFactory.service.in | 4 + 9 files changed, 369 insertions(+), 224 deletions(-) create mode 100644 mate-volume-control/org.mate.applets.GvcApplet.mate-panel-applet.in.in create mode 100644 mate-volume-control/org.mate.panel.applet.GvcAppletFactory.service.in diff --git a/configure.ac b/configure.ac index 8c99ad2..66298df 100644 --- a/configure.ac +++ b/configure.ac @@ -38,6 +38,7 @@ GTK_REQUIRED_VERSION=3.22.0 CANBERRA_REQUIRED_VERSION=0.13 MATE_MIXER_REQUIRED_VERSION=1.10.0 MATE_DESKTOP_REQUIRED_VERSION=1.17.0 +LIBPANEL4_REQUIRED=1.17.0 dnl======================================================================= dnl Check for the volume control modules @@ -51,6 +52,7 @@ PKG_CHECK_MODULES(VOLUME_CONTROL, libxml-2.0 mate-desktop-2.0 >= $MATE_DESKTOP_REQUIRED_VERSION libmatemixer >= $MATE_MIXER_REQUIRED_VERSION + libmatepanelapplet-4.0 >= $LIBPANEL4_REQUIRED ) AC_SUBST(VOLUME_CONTROL_CFLAGS) diff --git a/mate-volume-control/Makefile.am b/mate-volume-control/Makefile.am index e830802..f67d087 100644 --- a/mate-volume-control/Makefile.am +++ b/mate-volume-control/Makefile.am @@ -1,74 +1,102 @@ NULL = -bin_PROGRAMS = \ - mate-volume-control-applet \ - mate-volume-control \ - $(NULL) +bin_PROGRAMS = mate-volume-control +libexec_PROGRAMS = mate-volume-control-applet -AM_CPPFLAGS = \ - $(WARN_CFLAGS) \ - $(VOLUME_CONTROL_CFLAGS) \ - $(DISABLE_DEPRECATED) \ - -DLOCALE_DIR=\""$(datadir)/locale"\" \ - -DICON_DATA_DIR="\"$(pkgdatadir)/icons\"" \ - -DSOUND_SET_DIR="\"$(pkgdatadir)/sounds\"" \ +AM_CPPFLAGS = \ + $(WARN_CFLAGS) \ + $(VOLUME_CONTROL_CFLAGS) \ + $(DISABLE_DEPRECATED) \ + -DMATELOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ + -DLOCALE_DIR=\""$(datadir)/locale"\" \ + -DICON_DATA_DIR="\"$(pkgdatadir)/icons\"" \ + -DSOUND_SET_DIR="\"$(pkgdatadir)/sounds\"" \ + -I$(srcdir) \ $(NULL) +APPLET_LOCATION = $(libexecdir)/mate-volume-control-applet + +appletsdir = $(datadir)/mate-panel/applets +applets_in_files = org.mate.applets.GvcApplet.mate-panel-applet.in +applets_DATA = $(applets_in_files:.mate-panel-applet.in=.mate-panel-applet) + +$(applets_in_files): $(applets_in_files).in Makefile + $(AM_V_GEN)sed \ + -e "s|\@LOCATION\@|$(APPLET_LOCATION)|" \ + $< > $@ +%.mate-panel-applet: %.mate-panel-applet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache + +servicedir = $(datadir)/dbus-1/services +service_in_files = org.mate.panel.applet.GvcAppletFactory.service.in +service_DATA = $(service_in_files:.service.in=.service) + +org.mate.panel.applet.GvcAppletFactory.service: $(service_in_files) + $(AM_V_GEN)sed \ + -e "s|\@LOCATION\@|$(APPLET_LOCATION)|" \ + $< > $@ + +EXTRA_DIST = \ + $(applets_in_files).in \ + $(service_in_files) + noinst_LTLIBRARIES = libmatevolumecontrol.la -libmatevolumecontrol_la_SOURCES = \ - gvc-channel-bar.h \ - gvc-channel-bar.c \ +libmatevolumecontrol_la_SOURCES = \ + gvc-channel-bar.h \ + gvc-channel-bar.c \ $(NULL) -mate_volume_control_applet_LDADD = \ - -lm \ - libmatevolumecontrol.la \ - $(VOLUME_CONTROL_LIBS) \ +mate_volume_control_applet_LDADD = \ + -lm \ + libmatevolumecontrol.la \ + $(VOLUME_CONTROL_LIBS) \ + $(MATEDESKTOP_LIBS) \ $(NULL) -mate_volume_control_applet_SOURCES = \ - gvc-stream-status-icon.h \ - gvc-stream-status-icon.c \ - gvc-applet.h \ - gvc-applet.c \ - applet-main.c \ +mate_volume_control_applet_SOURCES = \ + gvc-stream-status-icon.h \ + gvc-stream-status-icon.c \ + gvc-applet.h \ + gvc-applet.c \ + applet-main.c \ $(NULL) -mate_volume_control_LDADD = \ - -lm \ - libmatevolumecontrol.la \ - $(VOLUME_CONTROL_LIBS) \ +mate_volume_contro_applet_CFLAGS = $(WARN_CFLAGS) + +mate_volume_control_LDADD = \ + -lm \ + libmatevolumecontrol.la \ + $(VOLUME_CONTROL_LIBS) \ $(NULL) -mate_volume_control_SOURCES = \ - gvc-balance-bar.h \ - gvc-balance-bar.c \ - gvc-level-bar.h \ - gvc-level-bar.c \ - gvc-combo-box.h \ - gvc-combo-box.c \ - gvc-sound-theme-chooser.c \ - gvc-sound-theme-chooser.h \ - gvc-speaker-test.h \ - gvc-speaker-test.c \ - gvc-utils.c \ - gvc-utils.h \ - sound-theme-file-utils.c \ - sound-theme-file-utils.h \ - gvc-mixer-dialog.c \ - gvc-mixer-dialog.h \ - dialog-main.c \ +mate_volume_control_SOURCES = \ + gvc-balance-bar.h \ + gvc-balance-bar.c \ + gvc-level-bar.h \ + gvc-level-bar.c \ + gvc-combo-box.h \ + gvc-combo-box.c \ + gvc-sound-theme-chooser.c \ + gvc-sound-theme-chooser.h \ + gvc-speaker-test.h \ + gvc-speaker-test.c \ + gvc-utils.c \ + gvc-utils.h \ + sound-theme-file-utils.c \ + sound-theme-file-utils.h \ + gvc-mixer-dialog.c \ + gvc-mixer-dialog.h \ + dialog-main.c \ $(NULL) -BUILT_SOURCES = \ +BUILT_SOURCES = \ $(NULL) -CLEANFILES = \ - $(BUILT_SOURCES) \ +CLEANFILES = \ + $(BUILT_SOURCES) \ $(NULL) -MAINTAINERCLEANFILES = \ - *~ \ +MAINTAINERCLEANFILES = \ + *~ \ Makefile.in -include $(top_srcdir)/git.mk diff --git a/mate-volume-control/applet-main.c b/mate-volume-control/applet-main.c index 23bef45..776f823 100644 --- a/mate-volume-control/applet-main.c +++ b/mate-volume-control/applet-main.c @@ -29,60 +29,35 @@ #include #include #include +#include #include "gvc-applet.h" -static gboolean show_version = FALSE; -static gboolean debug = FALSE; - -int -main (int argc, char **argv) +static gboolean +applet_main (MatePanelApplet* applet_widget) { GError *error = NULL; GvcApplet *applet; GApplication *app = NULL; - GOptionEntry entries[] = { - { "version", 'v', 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL }, - { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, N_("Enable debug"), NULL }, - { NULL } - }; bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); - gtk_init_with_args (&argc, &argv, - _(" — MATE Volume Control Applet"), - entries, GETTEXT_PACKAGE, - &error); - - if (error != NULL) { - g_warning ("%s", error->message); - g_error_free (error); - return 1; - } - if (show_version == TRUE) { - g_print ("%s %s\n", argv[0], VERSION); - return 0; - } - if (debug == TRUE) { - g_setenv ("G_MESSAGES_DEBUG", "all", FALSE); - } - app = g_application_new (GVC_APPLET_DBUS_NAME, G_APPLICATION_FLAGS_NONE); if (!g_application_register (app, NULL, &error)) { g_warning ("%s", error->message); g_error_free (error); - return 1; + return FALSE; } if (g_application_get_is_remote (app)) { g_warning ("Applet is already running, exiting"); - return 0; + return TRUE; } if (mate_mixer_init () == FALSE) { g_warning ("libmatemixer initialization failed, exiting"); - return 1; + return FALSE; } gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), @@ -90,11 +65,29 @@ main (int argc, char **argv) applet = gvc_applet_new (); + gvc_applet_fill (applet, applet_widget); gvc_applet_start (applet); - gtk_main (); - g_object_unref (applet); g_object_unref (app); - return 0; + return TRUE; } + +/* this function, called by mate-panel, will create the applet */ +static gboolean +applet_factory (MatePanelApplet* applet, const char* iid, gpointer data) +{ + gboolean retval = FALSE; + + if (!g_strcmp0 (iid, "GvcApplet")) + retval = applet_main (applet); + + return retval; +} + +/* needed by mate-panel applet library */ +MATE_PANEL_APPLET_OUT_PROCESS_FACTORY("GvcAppletFactory", + PANEL_TYPE_APPLET, + "Volume Control applet", + applet_factory, + NULL) diff --git a/mate-volume-control/gvc-applet.c b/mate-volume-control/gvc-applet.c index bcf64a3..f39d989 100644 --- a/mate-volume-control/gvc-applet.c +++ b/mate-volume-control/gvc-applet.c @@ -2,6 +2,7 @@ * * Copyright (C) 2008 Red Hat, Inc. * 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 @@ -28,6 +29,7 @@ #include #include +#include #include "gvc-applet.h" #include "gvc-stream-status-icon.h" @@ -50,6 +52,21 @@ static const gchar *icon_names_input[] = { NULL }; +static void menu_input_mute_toggle (GtkAction *action, GvcApplet *applet); +static void menu_output_mute_toggle (GtkAction *action, GvcApplet *applet); +static void menu_activate_open_volume_control (GtkAction *action, GvcApplet *applet); +static const GtkActionEntry applet_menu_actions [] = { + { "Preferences", APPLET_ICON, N_("_Sound Preferences"), NULL, NULL, G_CALLBACK (menu_activate_open_volume_control) } +}; +/* static const GtkToggleActionEntry applet_menu_toggle_actions [] = { */ +/* { "MuteInput", "audio-input-microphone-muted", N_("Mute Input"), NULL, NULL, G_CALLBACK (menu_input_mute_toggle) }, */ +/* { "MuteOutput", "audio-volume-muted", N_("Mute Output"), NULL, NULL, G_CALLBACK (menu_output_mute_toggle) } */ +/* }; */ +static char *ui = ""; +/* static char *ui = "" */ +/* "" */ +/* ""; */ + struct _GvcAppletPrivate { GvcStreamStatusIcon *icon_input; @@ -57,6 +74,10 @@ struct _GvcAppletPrivate gboolean running; MateMixerContext *context; MateMixerStream *input; + + MatePanelApplet *applet; + GtkBox *box; + GtkActionGroup *action_group; }; static void gvc_applet_class_init (GvcAppletClass *klass); @@ -137,7 +158,7 @@ update_icon_input (GvcApplet *applet) gvc_stream_status_icon_set_control (applet->priv->icon_input, control); - gtk_status_icon_set_visible (GTK_STATUS_ICON (applet->priv->icon_input), show); + gtk_widget_set_visible (GTK_WIDGET (applet->priv->icon_input), show); } static void @@ -154,12 +175,12 @@ update_icon_output (GvcApplet *applet) if (control != NULL) { g_debug ("Output icon enabled"); - gtk_status_icon_set_visible (GTK_STATUS_ICON (applet->priv->icon_output), + gtk_widget_set_visible (GTK_WIDGET (applet->priv->icon_output), TRUE); } else { g_debug ("There is no output stream/control, output icon disabled"); - gtk_status_icon_set_visible (GTK_STATUS_ICON (applet->priv->icon_output), + gtk_widget_set_visible (GTK_WIDGET (applet->priv->icon_output), FALSE); } } @@ -330,11 +351,6 @@ gvc_applet_init (GvcApplet *applet) gvc_stream_status_icon_set_display_name (applet->priv->icon_input, _("Input")); gvc_stream_status_icon_set_display_name (applet->priv->icon_output, _("Output")); - gtk_status_icon_set_title (GTK_STATUS_ICON (applet->priv->icon_input), - _("Microphone Volume")); - gtk_status_icon_set_title (GTK_STATUS_ICON (applet->priv->icon_output), - _("Sound Output Volume")); - applet->priv->context = mate_mixer_context_new (); mate_mixer_context_set_app_name (applet->priv->context, @@ -342,7 +358,7 @@ gvc_applet_init (GvcApplet *applet) mate_mixer_context_set_app_id (applet->priv->context, GVC_APPLET_DBUS_NAME); mate_mixer_context_set_app_version (applet->priv->context, VERSION); - mate_mixer_context_set_app_icon (applet->priv->context, "multimedia-volume-control"); + mate_mixer_context_set_app_icon (applet->priv->context, APPLET_ICON); g_signal_connect (G_OBJECT (applet->priv->context), "notify::state", @@ -363,3 +379,114 @@ gvc_applet_new (void) { return g_object_new (GVC_TYPE_APPLET, NULL); } + +static void +gvc_applet_set_size(GtkWidget* widget, int size, gpointer user_data) +{ + GvcApplet *applet = user_data; + + gvc_stream_status_icon_set_size (applet->priv->icon_input, size); + gvc_stream_status_icon_set_size (applet->priv->icon_output, size); +} + +static void +gvc_applet_set_orient(GtkWidget *widget, MatePanelAppletOrient orient, gpointer user_data) +{ + GvcApplet *applet = user_data; + + gvc_stream_status_icon_set_orient (applet->priv->icon_input, orient); + gvc_stream_status_icon_set_orient (applet->priv->icon_output, orient); +} + +static void +menu_input_mute_toggle (GtkAction *action, GvcApplet *applet) +{ + gboolean mute = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gvc_stream_status_icon_set_mute (applet->priv->icon_input, mute); +} + +static void +menu_output_mute_toggle (GtkAction *action, GvcApplet *applet) +{ + gboolean mute = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gvc_stream_status_icon_set_mute (applet->priv->icon_output, mute); +} + +static void +menu_activate_open_volume_control (GtkAction *action, GvcApplet *applet) +{ + gvc_stream_status_icon_volume_control (applet->priv->icon_output); +} + +/* static void */ +/* on_popup_pre_activate (GtkActionGroup *action_group, */ +/* GtkAction *action, */ +/* gpointer user_data) */ +/* { */ +/* g_message("on_popup_pre_activate"); */ +/* GvcApplet *applet = user_data; */ +/* gboolean is_muted; */ +/* */ +/* is_muted = gvc_stream_status_icon_get_mute (applet->priv->icon_input); */ +/* action = gtk_action_group_get_action (applet->priv->action_group, "MuteInput"); */ +/* gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), is_muted); */ +/* */ +/* is_muted = gvc_stream_status_icon_get_mute (applet->priv->icon_output); */ +/* action = gtk_action_group_get_action (applet->priv->action_group, "MuteOutput"); */ +/* gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), is_muted); */ +/* } */ + +gboolean +gvc_applet_fill (GvcApplet *applet, MatePanelApplet* applet_widget) +{ + GdkEventMask event_mask; + GdkWindow *window; + + g_set_application_name (_("Volume Control Applet")); + gtk_window_set_default_icon_name (APPLET_ICON); + + mate_panel_applet_set_flags (applet_widget, MATE_PANEL_APPLET_EXPAND_MINOR); + mate_panel_applet_set_background_widget (MATE_PANEL_APPLET (applet_widget), GTK_WIDGET (applet_widget)); + + applet->priv->applet = applet_widget; + applet->priv->box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0)); + + /* Define an initial size and orientation */ + gvc_stream_status_icon_set_size (applet->priv->icon_input, mate_panel_applet_get_size (applet->priv->applet)); + gvc_stream_status_icon_set_size (applet->priv->icon_output, mate_panel_applet_get_size (applet->priv->applet)); + gvc_stream_status_icon_set_orient (applet->priv->icon_input, mate_panel_applet_get_orient (applet->priv->applet)); + gvc_stream_status_icon_set_orient (applet->priv->icon_output, mate_panel_applet_get_orient (applet->priv->applet)); + + /* we add the Gtk buttons into the applet */ + gtk_box_pack_start (applet->priv->box, GTK_WIDGET (applet->priv->icon_input), TRUE, TRUE, 2); + gtk_box_pack_start (applet->priv->box, GTK_WIDGET (applet->priv->icon_output), TRUE, TRUE, 2); + gtk_container_add (GTK_CONTAINER (applet->priv->applet), GTK_WIDGET (applet->priv->box)); + gtk_widget_show_all (GTK_WIDGET (applet->priv->applet)); + + /* Enable 'scroll-event' signal to get through */ + window = gtk_widget_get_window (GTK_WIDGET (applet->priv->icon_input)); + event_mask = gdk_window_get_events (window); + gdk_window_set_events (window, event_mask | GDK_SCROLL_MASK); + + window = gtk_widget_get_window (GTK_WIDGET (applet->priv->icon_output)); + event_mask = gdk_window_get_events (window); + gdk_window_set_events (window, event_mask | GDK_SCROLL_MASK); + + /* Update icons on size/orientation changes */ + g_object_connect (applet->priv->applet, + "signal::change_size", gvc_applet_set_size, applet, + "signal::change_orient", gvc_applet_set_orient, applet, + NULL); + + /* set up context menu */ + applet->priv->action_group = gtk_action_group_new ("Volume Control Applet Actions"); + gtk_action_group_set_translation_domain (applet->priv->action_group, GETTEXT_PACKAGE); + gtk_action_group_add_actions (applet->priv->action_group, applet_menu_actions, + G_N_ELEMENTS (applet_menu_actions), applet); + /* gtk_action_group_add_toggle_actions (applet->priv->action_group, applet_menu_toggle_actions, */ + /* G_N_ELEMENTS (applet_menu_toggle_actions), applet); */ + + mate_panel_applet_setup_menu (applet->priv->applet, ui, applet->priv->action_group); + + return TRUE; +} diff --git a/mate-volume-control/gvc-applet.h b/mate-volume-control/gvc-applet.h index 991ef6d..42e9261 100644 --- a/mate-volume-control/gvc-applet.h +++ b/mate-volume-control/gvc-applet.h @@ -28,6 +28,7 @@ G_BEGIN_DECLS #define GVC_APPLET_DBUS_NAME "org.mate.VolumeControlApplet" +#define APPLET_ICON "multimedia-volume-control" #define GVC_TYPE_APPLET (gvc_applet_get_type ()) #define GVC_APPLET(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_APPLET, GvcApplet)) @@ -55,6 +56,7 @@ GType gvc_applet_get_type (void) G_GNUC_CONST; GvcApplet * gvc_applet_new (void); void gvc_applet_start (GvcApplet *applet); +gboolean gvc_applet_fill (GvcApplet *applet, MatePanelApplet *applet_widget); G_END_DECLS 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)); diff --git a/mate-volume-control/gvc-stream-status-icon.h b/mate-volume-control/gvc-stream-status-icon.h index 7b51801..976616d 100644 --- a/mate-volume-control/gvc-stream-status-icon.h +++ b/mate-volume-control/gvc-stream-status-icon.h @@ -41,13 +41,13 @@ typedef struct _GvcStreamStatusIconPrivate GvcStreamStatusIconPrivate; struct _GvcStreamStatusIcon { - GtkStatusIcon parent; + GtkEventBox parent; GvcStreamStatusIconPrivate *priv; }; struct _GvcStreamStatusIconClass { - GtkStatusIconClass parent_class; + GtkEventBoxClass parent_class; }; GType gvc_stream_status_icon_get_type (void) G_GNUC_CONST; @@ -63,6 +63,19 @@ void gvc_stream_status_icon_set_display_name (GvcStreamStatusIc void gvc_stream_status_icon_set_control (GvcStreamStatusIcon *icon, MateMixerStreamControl *control); +void gvc_stream_status_icon_set_size (GvcStreamStatusIcon *icon, + guint size); + +void gvc_stream_status_icon_set_orient (GvcStreamStatusIcon *icon, + MatePanelAppletOrient orient); + +gboolean gvc_stream_status_icon_get_mute (GvcStreamStatusIcon *icon); + +void gvc_stream_status_icon_set_mute (GvcStreamStatusIcon *icon, + gboolean mute); + +void gvc_stream_status_icon_volume_control (GvcStreamStatusIcon *icon); + G_END_DECLS #endif /* __GVC_STREAM_STATUS_ICON_H */ diff --git a/mate-volume-control/org.mate.applets.GvcApplet.mate-panel-applet.in.in b/mate-volume-control/org.mate.applets.GvcApplet.mate-panel-applet.in.in new file mode 100644 index 0000000..ca9f5d4 --- /dev/null +++ b/mate-volume-control/org.mate.applets.GvcApplet.mate-panel-applet.in.in @@ -0,0 +1,11 @@ +[Applet Factory] +Id=GvcAppletFactory +Location=@LOCATION@ +_Name=Volume Control Factory +_Description=Volume Control Factory + +[GvcApplet] +_Name=Volume Control +_Description=Control multimedia volume +Icon=multimedia-volume-control + diff --git a/mate-volume-control/org.mate.panel.applet.GvcAppletFactory.service.in b/mate-volume-control/org.mate.panel.applet.GvcAppletFactory.service.in new file mode 100644 index 0000000..0a01e2d --- /dev/null +++ b/mate-volume-control/org.mate.panel.applet.GvcAppletFactory.service.in @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.mate.panel.applet.GvcAppletFactory +Exec=@LOCATION@ + -- cgit v1.2.1