~ubuntu-branches/ubuntu/utopic/gxine/utopic-proposed

« back to all changes in this revision

Viewing changes to .pc/debian-changes/src/systray.c

  • Committer: Package Import Robot
  • Author(s): Steve Langasek
  • Date: 2014-05-07 21:34:55 UTC
  • mfrom: (2.1.17 sid)
  • Revision ID: package-import@ubuntu.com-20140507213455-qnu5diwyyj8bkaap
Tags: 0.5.907-3ubuntu1
* Merge from Debian unstable, remaining changes:
  - debian/rules, debian/control: use dh-autoreconf at build time.
  - debian/control: Add Xb-Npp-xxx, Xb-Npp-Description and Xb-Npp-File
    fields.
  - src/script_engine.c: fix a remaining memory leak issue associated with
    using JS_EncodeString(), which somehow didn't get fixed upstream
  - debian/gxineplugin.links: Add a link to xulrunner-addons/plugins
    directory.
  - mime.default: Add dvd, vcd, svcd tags.
* Dropped changes, no longer needed:
  - debian/gxine.install: no need to diverge from Debian since we no longer
    ship a wrapper
* All other changes dropped, as they have been included upstream or in
  Debian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2007 the xine-project
3
 
 *
4
 
 * This program is free software; you can redistribute it and/or modify it
5
 
 * under the terms of the GNU General Public License as published by the Free
6
 
 * Software Foundation; either version 2 of the License, or (at your option)
7
 
 * any later version.
8
 
 *
9
 
 * This program is distributed in the hope that it will be useful, but WITHOUT
10
 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
 
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12
 
 * more details.
13
 
 *
14
 
 * You should have received a copy of the GNU General Public License along
15
 
 * with this program; if not, write to the Free Software Foundation, Inc., 51
16
 
 * Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
 
 *
18
 
 * System tray icon for gxine.
19
 
 */
20
 
 
21
 
#include "globals.h"
22
 
#include "systray.h"
23
 
 
24
 
#include <stdlib.h>
25
 
 
26
 
#include "drag_drop.h"
27
 
#include "engine.h"
28
 
#include "menu.h"
29
 
#include "noskin_window.h"
30
 
#include "ui.h"
31
 
 
32
 
#include <gtk/gtk.h>
33
 
#include <gdk/gdkx.h>
34
 
#include <X11/Xlib.h>
35
 
 
36
 
static GtkWidget *tray_icon, *tray_menu;
37
 
static Window tray = None;
38
 
 
39
 
static struct {
40
 
  Atom data, manager, opcode, selection;
41
 
} atoms;
42
 
 
43
 
static GdkFilterReturn systray_filter (GdkXEvent *, GdkEvent *, gpointer);
44
 
static gboolean button_cb (GtkWidget *, GdkEventButton *, gpointer);
45
 
 
46
 
 
47
 
static void
48
 
send_opcode (glong d1, glong d2, glong d3, glong d4)
49
 
{
50
 
  GdkDisplay *display = gtk_widget_get_display (tray_icon);
51
 
  Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
52
 
 
53
 
  XClientMessageEvent xev = {
54
 
    ClientMessage, 0, True,
55
 
    xdisplay, tray, atoms.opcode,
56
 
    32, { .l = { gdk_x11_get_server_time (tray_icon->window), d1, d2, d3, d4 } }
57
 
  };
58
 
 
59
 
  gdk_error_trap_push ();
60
 
  XSendEvent (xdisplay, tray, False, NoEventMask, (XEvent *) &xev);
61
 
  XSync (xdisplay, FALSE);
62
 
  gdk_error_trap_pop ();
63
 
}
64
 
 
65
 
static inline GdkScreen *
66
 
create_tray_icon (void)
67
 
{
68
 
  tray_icon = gtk_plug_new (0);
69
 
  gtk_container_add (GTK_CONTAINER (tray_icon),
70
 
                     gtk_image_new_from_icon_name ("gxine", GTK_ICON_SIZE_LARGE_TOOLBAR));
71
 
  gtk_widget_show_all (tray_icon);
72
 
  drag_drop_setup (tray_icon, TRUE);
73
 
 
74
 
  GdkScreen *screen = gtk_widget_get_screen (tray_icon);
75
 
  Screen *xscreen = GDK_SCREEN_XSCREEN (screen);
76
 
  GdkDisplay *display = gtk_widget_get_display (tray_icon);
77
 
  Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
78
 
 
79
 
  char selection[32];
80
 
  snprintf (selection, sizeof (selection), "_NET_SYSTEM_TRAY_S%d",
81
 
            XScreenNumberOfScreen (xscreen));
82
 
  atoms.data = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_MESSAGE_DATA", False);
83
 
  atoms.manager = XInternAtom (xdisplay, "MANAGER", False);
84
 
  atoms.opcode = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_OPCODE", False);
85
 
  atoms.selection = XInternAtom (xdisplay, selection, False);
86
 
 
87
 
  return screen;
88
 
}
89
 
 
90
 
static void
91
 
systray_delete_icon (void)
92
 
{
93
 
  tray = None;
94
 
  if (!tray_icon)
95
 
    return;
96
 
 
97
 
  gtk_widget_destroy (tray_icon);
98
 
  tray_icon = NULL;
99
 
 
100
 
  GdkDisplay *display = gtk_widget_get_display (app);
101
 
  GdkWindow *window = gdk_window_lookup_for_display (display, tray);
102
 
  gdk_window_remove_filter (window, systray_filter, NULL);
103
 
 
104
 
  if (!GTK_WIDGET_MAPPED (app))
105
 
    app_show ();
106
 
 
107
 
  gtk_action_set_visible (action_items.showmain, FALSE);
108
 
  gtk_action_set_visible (action_items.hidemain, FALSE);
109
 
}
110
 
 
111
 
static void
112
 
systray_create_icon (void)
113
 
{
114
 
  if (tray_icon)
115
 
    systray_delete_icon ();
116
 
 
117
 
  GdkDisplay *display = gtk_widget_get_display (app);
118
 
  Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
119
 
 
120
 
  /* Create the tray icon */
121
 
  GdkDisplay *tray_screen = create_tray_icon ();
122
 
 
123
 
  /* Get the tray id */
124
 
  XGrabServer (xdisplay);
125
 
  tray = XGetSelectionOwner (xdisplay, atoms.selection);
126
 
  if (tray != None)
127
 
    XSelectInput (xdisplay, tray, StructureNotifyMask);
128
 
  XUngrabServer (xdisplay);
129
 
  XFlush (xdisplay);
130
 
 
131
 
  /* No tray? */
132
 
  if (tray == None)
133
 
    return;
134
 
 
135
 
  /* Dock it */
136
 
  GdkWindow *window = gdk_window_lookup_for_display (display, tray);
137
 
  gdk_window_add_filter (window, systray_filter, NULL);
138
 
  /* request dock */
139
 
  send_opcode (0, gtk_plug_get_id (GTK_PLUG (tray_icon)), 0, 0);
140
 
 
141
 
  /* Filtering & events */
142
 
  gdk_window_add_filter (gdk_screen_get_root_window (tray_screen),
143
 
                         systray_filter, NULL);
144
 
  gdk_window_set_events (tray_icon->window,
145
 
                         gdk_window_get_events (tray_icon->window) | GDK_BUTTON_PRESS_MASK);
146
 
  g_signal_connect (G_OBJECT (tray_icon), "button-press-event",
147
 
                    G_CALLBACK (button_cb), NULL);
148
 
 
149
 
  /* Handle menu items */
150
 
  gtk_action_set_visible (action_items.showmain, FALSE);
151
 
  gtk_action_set_visible (action_items.hidemain, TRUE);
152
 
}
153
 
 
154
 
static GdkFilterReturn
155
 
systray_filter (GdkXEvent *gxev, GdkEvent *ev, gpointer data)
156
 
{
157
 
  XEvent *xev = (XEvent *) gxev;
158
 
 
159
 
  switch (xev->type)
160
 
  {
161
 
  case ClientMessage:
162
 
    /* tray appeared? */
163
 
    if (xev->xclient.message_type == atoms.manager
164
 
        && xev->xclient.data.l[1] == atoms.selection)
165
 
      systray_create_icon ();
166
 
    break;
167
 
 
168
 
  case DestroyNotify:
169
 
    /* tray disappeared? */
170
 
    if (xev->xclient.window == tray)
171
 
      systray_delete_icon ();
172
 
    break;
173
 
  }
174
 
 
175
 
  return GDK_FILTER_CONTINUE;
176
 
}
177
 
 
178
 
static const char popup_menu_xml[] =
179
 
        "<ui><popup name='tray'>\n"
180
 
         "<menuitem action='PrevTrack' />\n"
181
 
         "<menuitem action='Play' />\n"
182
 
         "<menuitem action='Pause' />\n"
183
 
         "<menuitem action='FFwd' />\n"
184
 
         "<menuitem action='Stop' />\n"
185
 
         "<menuitem action='NextTrack' />\n"
186
 
         "<menuitem action='Playlist' />\n"
187
 
         "<separator />\n"
188
 
         "<menuitem action='HideMain' />\n"
189
 
         "<menuitem action='ShowMain' />\n"
190
 
         "<menuitem action='Quit' />\n"
191
 
        "</popup></ui>";
192
 
 
193
 
static gboolean
194
 
button_cb (GtkWidget *widget, GdkEventButton *ev, gpointer data)
195
 
{
196
 
  switch (ev->button)
197
 
  {
198
 
  case 1:
199
 
    gtk_menu_popup (GTK_MENU (tray_menu), NULL, NULL, NULL, NULL,
200
 
                    ev->button, ev->time);
201
 
    break;
202
 
  case 2:
203
 
    if (GTK_WIDGET_MAPPED (app))
204
 
      app_hide ();
205
 
    else
206
 
      app_show ();
207
 
    break;
208
 
  case 3:
209
 
    gtk_menu_popup (GTK_MENU (popup_menu), NULL, NULL, NULL, NULL,
210
 
                    ev->button, ev->time);
211
 
    break;
212
 
  }
213
 
 
214
 
  return TRUE;
215
 
}
216
 
 
217
 
static JSBool js_minimise (JSContext *cx, JSObject *obj, uintN argc,
218
 
                              jsval *argv, jsval *rval)
219
 
{
220
 
  int32 tray_state=-1;
221
 
 
222
 
  se_log_fncall_checkinit ("set_minimised");
223
 
  se_argc_check_max (1, "set_minimised");
224
 
 
225
 
  if (argc == 1)
226
 
  {
227
 
    se_arg_is_int_or_bool (0, "set_minimised");
228
 
    JS_ValueToInt32 (cx, argv[0], &tray_state);
229
 
  }
230
 
 
231
 
  switch (tray_state)
232
 
  {
233
 
  default: /* toggle */
234
 
    if (GTK_WIDGET_MAPPED (app))
235
 
  case 1:
236
 
      app_hide ();
237
 
    else
238
 
  case 0:
239
 
      app_show ();
240
 
  }
241
 
 
242
 
  return JS_TRUE;
243
 
}
244
 
 
245
 
void systray_init (void)
246
 
{
247
 
  static const se_f_def_t defs[] = {
248
 
    { "set_minimised", js_minimise, 0, 0,
249
 
      SE_GROUP_ENGINE, N_("[bool]"),
250
 
      N_("true to hide, false to show") },
251
 
    { NULL }
252
 
  };
253
 
  se_defuns (gse, NULL, defs);
254
 
 
255
 
  GError *error = NULL;
256
 
  gtk_ui_manager_add_ui_from_string (ui, popup_menu_xml, -1, &error);
257
 
  tray_menu = gtk_ui_manager_get_widget (ui, "/ui/tray");
258
 
 
259
 
  static const char items[][16] = {
260
 
    [Control_STOP] = "/ui/tray/Stop",
261
 
    [Control_PAUSE] = "/ui/tray/Pause",
262
 
    [Control_PLAY] = "/ui/tray/Play",
263
 
    [Control_FASTFWD] = "/ui/tray/FFwd",
264
 
   };
265
 
  for (int i = 0; i < G_N_ELEMENTS (items); ++i)
266
 
    if (items[i][0])
267
 
      ui_register_control_button (i, gtk_ui_manager_get_widget (ui, items[i]));
268
 
 
269
 
  systray_create_icon ();
270
 
}
271
 
 
272
 
gboolean systray_present (void)
273
 
{
274
 
  return tray != None;
275
 
}