36 | 36 |
|
37 | 37 |
static guint signals[LAST_SIGNAL] = {0, };
|
38 | 38 |
|
|
39 |
enum
|
|
40 |
{
|
|
41 |
PROP_0,
|
|
42 |
PROP_MENU,
|
|
43 |
N_PROPERTIES
|
|
44 |
};
|
|
45 |
|
39 | 46 |
/**
|
40 | 47 |
* SECTION:xapp-status-icon
|
41 | 48 |
* @Short_description: Broadcasts status information over DBUS
|
|
46 | 53 |
* Gtk.StatusIcon widget.
|
47 | 54 |
*
|
48 | 55 |
* If used in an environment where no applet is handling XAppStatusIcons,
|
49 | |
* The XAppStatusIcon delegates its calls to a Gtk.StatusIcon.
|
|
56 |
* the XAppStatusIcon delegates its calls to a Gtk.StatusIcon.
|
50 | 57 |
*/
|
51 | 58 |
struct _XAppStatusIconPrivate
|
52 | 59 |
{
|
|
102 | 109 |
}
|
103 | 110 |
}
|
104 | 111 |
|
|
112 |
typedef struct {
|
|
113 |
gint x;
|
|
114 |
gint y;
|
|
115 |
gint position;
|
|
116 |
guint32 t;
|
|
117 |
} PositionData;
|
|
118 |
|
|
119 |
static void
|
|
120 |
position_menu_cb (GtkMenu *menu,
|
|
121 |
gint *x,
|
|
122 |
gint *y,
|
|
123 |
gboolean *push_in,
|
|
124 |
gpointer user_data)
|
|
125 |
{
|
|
126 |
GtkAllocation alloc;
|
|
127 |
PositionData *position_data = (PositionData *) user_data;
|
|
128 |
|
|
129 |
*x = position_data->x;
|
|
130 |
*y = position_data->y;
|
|
131 |
|
|
132 |
gtk_widget_get_allocation (GTK_WIDGET (menu), &alloc);
|
|
133 |
|
|
134 |
switch (position_data->position) {
|
|
135 |
case GTK_POS_BOTTOM:
|
|
136 |
*y = *y - alloc.height;
|
|
137 |
break;
|
|
138 |
case GTK_POS_RIGHT:
|
|
139 |
*x = *x - alloc.width;
|
|
140 |
break;
|
|
141 |
}
|
|
142 |
|
|
143 |
*push_in = TRUE;
|
|
144 |
}
|
|
145 |
|
|
146 |
static void
|
|
147 |
popup_native_icon_menu (XAppStatusIcon *self,
|
|
148 |
gint x,
|
|
149 |
gint y,
|
|
150 |
guint button,
|
|
151 |
guint _time,
|
|
152 |
gint panel_position)
|
|
153 |
{
|
|
154 |
GdkDisplay *display;
|
|
155 |
GdkDevice *pointer;
|
|
156 |
|
|
157 |
g_debug ("XAppStatusIcon: Popup menu on behalf of application");
|
|
158 |
|
|
159 |
PositionData position_data = {
|
|
160 |
x, y, panel_position, _time
|
|
161 |
};
|
|
162 |
|
|
163 |
display = gdk_display_get_default ();
|
|
164 |
pointer = gdk_device_manager_get_client_pointer (gdk_display_get_device_manager (display));
|
|
165 |
|
|
166 |
gtk_menu_popup_for_device (GTK_MENU (self->priv->menu),
|
|
167 |
pointer,
|
|
168 |
NULL,
|
|
169 |
NULL,
|
|
170 |
position_menu_cb,
|
|
171 |
&position_data,
|
|
172 |
NULL,
|
|
173 |
button,
|
|
174 |
_time);
|
|
175 |
}
|
|
176 |
|
105 | 177 |
static gboolean
|
106 | 178 |
handle_click_method (XAppStatusIconInterface *skeleton,
|
107 | 179 |
GDBusMethodInvocation *invocation,
|
|
123 | 195 |
|
124 | 196 |
g_signal_emit (icon, signals[BUTTON_PRESS], 0, x, y, button, _time, panel_position);
|
125 | 197 |
|
|
198 |
if (button == GDK_BUTTON_PRIMARY)
|
|
199 |
{
|
|
200 |
g_signal_emit (icon, signals[ACTIVATE], 0);
|
|
201 |
}
|
|
202 |
|
126 | 203 |
xapp_status_icon_interface_complete_button_press (skeleton,
|
127 | 204 |
invocation);
|
128 | 205 |
}
|
|
135 | 212 |
x, y, button, _time, panel_position_to_str (panel_position));
|
136 | 213 |
|
137 | 214 |
g_signal_emit (icon, signals[BUTTON_RELEASE], 0, x, y, button, _time, panel_position);
|
|
215 |
|
|
216 |
if (button == GDK_BUTTON_SECONDARY)
|
|
217 |
{
|
|
218 |
if (icon->priv->menu)
|
|
219 |
{
|
|
220 |
popup_native_icon_menu (icon, x, y, button, _time, panel_position);
|
|
221 |
}
|
|
222 |
else
|
|
223 |
{
|
|
224 |
g_signal_emit (icon, signals[POPUP_MENU], 0, x, y, button, _time, panel_position);
|
|
225 |
}
|
|
226 |
}
|
138 | 227 |
|
139 | 228 |
xapp_status_icon_interface_complete_button_release (skeleton,
|
140 | 229 |
invocation);
|
|
199 | 288 |
{
|
200 | 289 |
g_debug ("XAppStatusIcon: GtkStatusIcon popup menu with NO menu provided");
|
201 | 290 |
|
202 | |
/* No menu provided, do our best to pass along good position info the app or appindicator
|
203 | |
* (if they're not using patched appindicator) */
|
|
291 |
/* No menu provided, do our best to pass along good position info to the app
|
|
292 |
* or appindicator (if they're not using patched appindicator). */
|
204 | 293 |
GdkScreen *screen;
|
205 | 294 |
GdkRectangle irect;
|
206 | 295 |
GtkOrientation orientation;
|
|
609 | 698 |
}
|
610 | 699 |
|
611 | 700 |
static void
|
|
701 |
xapp_status_icon_set_property (GObject *object,
|
|
702 |
guint prop_id,
|
|
703 |
const GValue *value,
|
|
704 |
GParamSpec *pspec)
|
|
705 |
{
|
|
706 |
switch (prop_id)
|
|
707 |
{
|
|
708 |
case PROP_MENU:
|
|
709 |
xapp_status_icon_set_menu (XAPP_STATUS_ICON (object), g_value_get_object (value));
|
|
710 |
break;
|
|
711 |
default:
|
|
712 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
713 |
break;
|
|
714 |
}
|
|
715 |
}
|
|
716 |
|
|
717 |
static void
|
|
718 |
xapp_status_icon_get_property (GObject *object,
|
|
719 |
guint prop_id,
|
|
720 |
GValue *value,
|
|
721 |
GParamSpec *pspec)
|
|
722 |
{
|
|
723 |
XAppStatusIcon *icon = XAPP_STATUS_ICON (object);
|
|
724 |
|
|
725 |
switch (prop_id)
|
|
726 |
{
|
|
727 |
case PROP_MENU:
|
|
728 |
g_value_set_object (value, icon->priv->menu);
|
|
729 |
break;
|
|
730 |
default:
|
|
731 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
732 |
break;
|
|
733 |
}
|
|
734 |
}
|
|
735 |
|
|
736 |
static void
|
612 | 737 |
xapp_status_icon_init (XAppStatusIcon *self)
|
613 | 738 |
{
|
614 | 739 |
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, XAPP_TYPE_STATUS_ICON, XAppStatusIconPrivate);
|
|
693 | 818 |
|
694 | 819 |
gobject_class->dispose = xapp_status_icon_dispose;
|
695 | 820 |
gobject_class->finalize = xapp_status_icon_finalize;
|
|
821 |
gobject_class->set_property = xapp_status_icon_set_property;
|
|
822 |
gobject_class->get_property = xapp_status_icon_get_property;
|
696 | 823 |
|
697 | 824 |
g_type_class_add_private (gobject_class, sizeof (XAppStatusIconPrivate));
|
698 | 825 |
|
699 | |
/**
|
700 | |
* XAppStatusIcon::button-press-event:
|
701 | |
* @icon: The #XAppStatusIcon
|
702 | |
* @x: The absolute x position to use for menu positioning
|
703 | |
* @y: The absolute y position to use for menu positioning
|
704 | |
* @button: The button that was pressed
|
705 | |
* @time: The time supplied by the event, or 0
|
706 | |
* @panel_position: The #GtkPositionType to use for menu positioning
|
707 | |
*
|
708 | |
* Gets emitted when there is a button press received from an applet
|
709 | |
*/
|
|
826 |
/**
|
|
827 |
* XAppStatusIcon:menu:
|
|
828 |
*
|
|
829 |
* A #GtkMenu to use when requested by the remote monitor.
|
|
830 |
*
|
|
831 |
* When this property is not %NULL, it is not necessary for the application
|
|
832 |
* to connect to the #XAppStatusIcon::button-release-event signal, and the
|
|
833 |
* #XAppStatusIcon::popup-menu signal will not be emitted. All menu positioning
|
|
834 |
* will be handled internally by #XAppStatusIcon.
|
|
835 |
*
|
|
836 |
* Setting this will remove any floating reference to the menu and assume ownership.
|
|
837 |
* As a result, it is not necessary to maintain a reference to it in the parent
|
|
838 |
* application (or unref it when finished with it - if you wish to replace the menu,
|
|
839 |
* simply call this method again with a new menu.
|
|
840 |
*/
|
|
841 |
g_object_class_install_property (gobject_class, PROP_MENU,
|
|
842 |
g_param_spec_object ("menu",
|
|
843 |
"Status icon menu",
|
|
844 |
"The menu to use when the status icon is remotely requested",
|
|
845 |
GTK_TYPE_WIDGET,
|
|
846 |
G_PARAM_READWRITE));
|
|
847 |
|
|
848 |
/**
|
|
849 |
* XAppStatusIcon::button-press-event:
|
|
850 |
* @icon: The #XAppStatusIcon
|
|
851 |
* @x: The absolute x position to use for menu positioning
|
|
852 |
* @y: The absolute y position to use for menu positioning
|
|
853 |
* @button: The button that was pressed
|
|
854 |
* @time: The time supplied by the event, or 0
|
|
855 |
* @panel_position: The #GtkPositionType to use for menu positioning
|
|
856 |
*
|
|
857 |
* Gets emitted when there is a button press received from an applet
|
|
858 |
*/
|
710 | 859 |
signals[BUTTON_PRESS] =
|
711 | 860 |
g_signal_new ("button-press-event",
|
712 | 861 |
XAPP_TYPE_STATUS_ICON,
|
|
715 | 864 |
NULL, NULL, NULL,
|
716 | 865 |
G_TYPE_NONE, 5, G_TYPE_INT, G_TYPE_INT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INT);
|
717 | 866 |
|
718 | |
/**
|
719 | |
* XAppStatusIcon::button-release-event:
|
720 | |
* @icon: The #XAppStatusIcon
|
721 | |
* @x: The absolute x position to use for menu positioning
|
722 | |
* @y: The absolute y position to use for menu positioning
|
723 | |
* @button: The button that was released
|
724 | |
* @time: The time supplied by the event, or 0
|
725 | |
* @panel_position: The #GtkPositionType to use for menu positioning
|
726 | |
*
|
727 | |
* Gets emitted when there is a button release received from an applet
|
728 | |
*/
|
|
867 |
/**
|
|
868 |
* XAppStatusIcon::button-release-event:
|
|
869 |
* @icon: The #XAppStatusIcon
|
|
870 |
* @x: The absolute x position to use for menu positioning
|
|
871 |
* @y: The absolute y position to use for menu positioning
|
|
872 |
* @button: The button that was released
|
|
873 |
* @time: The time supplied by the event, or 0
|
|
874 |
* @panel_position: The #GtkPositionType to use for menu positioning
|
|
875 |
*
|
|
876 |
* Gets emitted when there is a button release received from an applet
|
|
877 |
*/
|
729 | 878 |
signals[BUTTON_RELEASE] =
|
730 | 879 |
g_signal_new ("button-release-event",
|
731 | 880 |
XAPP_TYPE_STATUS_ICON,
|
|
734 | 883 |
NULL, NULL, NULL,
|
735 | 884 |
G_TYPE_NONE, 5, G_TYPE_INT, G_TYPE_INT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INT);
|
736 | 885 |
|
737 | |
/**
|
738 | |
* XAppStatusIcon::activate:
|
739 | |
* @icon: The #XAppStatusIcon
|
740 | |
*
|
741 | |
* Gets emitted when the user activates the status icon.
|
742 | |
*/
|
|
886 |
/**
|
|
887 |
* XAppStatusIcon::activate:
|
|
888 |
* @icon: The #XAppStatusIcon
|
|
889 |
*
|
|
890 |
* Gets emitted when the user activates (left-click) the status icon.
|
|
891 |
*/
|
743 | 892 |
signals [ACTIVATE] =
|
744 | 893 |
g_signal_new ("activate",
|
745 | 894 |
XAPP_TYPE_STATUS_ICON,
|
|
749 | 898 |
G_TYPE_NONE,
|
750 | 899 |
0);
|
751 | 900 |
|
752 | |
/**
|
753 | |
* XAppStatusIcon::popup-menu:
|
754 | |
* @icon: the #XAppStatusIcon
|
755 | |
* @button: the button that was pressed, or 0 if the
|
756 | |
* signal is not emitted in response to a button press event
|
757 | |
* @activate_time: the timestamp of the event that
|
758 | |
* triggered the signal emission
|
759 | |
*
|
760 | |
* Gets emitted when the user brings up the context menu
|
761 | |
* of the status icon.
|
762 | |
*
|
763 | |
*/
|
|
901 |
/**
|
|
902 |
* XAppStatusIcon::popup-menu:
|
|
903 |
* @icon: the #XAppStatusIcon
|
|
904 |
* @x: The absolute x position to use for menu positioning
|
|
905 |
* @y: The absolute y position to use for menu positioning
|
|
906 |
* @button: The button that was released
|
|
907 |
* @time: The time supplied by the event, or 0
|
|
908 |
* @panel_position: The #GtkPositionType to use for menu positioning
|
|
909 |
*
|
|
910 |
* Gets emitted when a right-click is performed on a button-release-
|
|
911 |
* event.
|
|
912 |
*
|
|
913 |
*/
|
764 | 914 |
signals [POPUP_MENU] =
|
765 | 915 |
g_signal_new ("popup-menu",
|
766 | 916 |
XAPP_TYPE_STATUS_ICON,
|
767 | 917 |
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
|
768 | 918 |
0,
|
769 | 919 |
NULL, NULL, NULL,
|
770 | |
G_TYPE_NONE,
|
771 | |
2,
|
772 | |
G_TYPE_UINT,
|
773 | |
G_TYPE_UINT);
|
|
920 |
G_TYPE_NONE, 5, G_TYPE_INT, G_TYPE_INT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INT);
|
774 | 921 |
}
|
775 | 922 |
|
776 | 923 |
/**
|
|
778 | 925 |
* @icon: a #XAppStatusIcon
|
779 | 926 |
* @name: a name (this defaults to the name of the application, if not set)
|
780 | 927 |
*
|
781 | |
* Sets the status icon name. This is now shown to users.
|
|
928 |
* Sets the status icon name. This is not shown to users.
|
782 | 929 |
*
|
783 | 930 |
* Since: 1.6
|
784 | 931 |
*/
|
|
807 | 954 |
* @icon: a #XAppStatusIcon
|
808 | 955 |
* @icon_name: An icon name or absolute path to an icon.
|
809 | 956 |
*
|
810 | |
* Sets the icon name or icon filename to use.
|
|
957 |
* Sets the icon name or local path to use.
|
811 | 958 |
*
|
812 | 959 |
* Since: 1.6
|
813 | 960 |
*/
|
|
915 | 1062 |
/**
|
916 | 1063 |
* xapp_status_icon_set_menu:
|
917 | 1064 |
* @icon: a #XAppStatusIcon
|
918 | |
* @menu: A #GtkMenu to display when requested
|
919 | |
*
|
920 | |
* Sets a menu that will be used when requested.
|
|
1065 |
* @menu: (nullable): A #GtkMenu to display when requested
|
|
1066 |
*
|
|
1067 |
* See the #XAppStatusIcon:menu property for details
|
921 | 1068 |
*
|
922 | 1069 |
* Since: 1.6
|
923 | 1070 |
*/
|
|
928 | 1075 |
g_return_if_fail (XAPP_IS_STATUS_ICON (icon));
|
929 | 1076 |
|
930 | 1077 |
g_clear_object (&icon->priv->menu);
|
931 | |
icon->priv->menu = GTK_WIDGET (g_object_ref (menu));
|
|
1078 |
|
|
1079 |
if (menu)
|
|
1080 |
{
|
|
1081 |
icon->priv->menu = GTK_WIDGET (g_object_ref_sink (menu));
|
|
1082 |
}
|
|
1083 |
}
|
|
1084 |
|
|
1085 |
/**
|
|
1086 |
* xapp_status_icon_get_menu:
|
|
1087 |
* @icon: a #XAppStatusIcon
|
|
1088 |
*
|
|
1089 |
* Returns a pointer to a #GtkMenu that was set previously. If
|
|
1090 |
* no menu was set, this returns %NULL.
|
|
1091 |
*
|
|
1092 |
* Returns: (transfer none): the #GtkMenu or %NULL if none was set.
|
|
1093 |
|
|
1094 |
* Since: 1.6
|
|
1095 |
*/
|
|
1096 |
void
|
|
1097 |
xapp_status_icon_get_menu (XAppStatusIcon *icon,
|
|
1098 |
GtkMenu *menu)
|
|
1099 |
{
|
|
1100 |
g_return_if_fail (XAPP_IS_STATUS_ICON (icon));
|
|
1101 |
|
|
1102 |
g_clear_object (&icon->priv->menu);
|
|
1103 |
icon->priv->menu = GTK_WIDGET (g_object_ref_sink (menu));
|
932 | 1104 |
}
|
933 | 1105 |
|
934 | 1106 |
/**
|