gnome-shell-3.6.3.1/src/shell-xfixes-cursor.c

Location Tool Test ID Function Issue
shell-xfixes-cursor.c:393:5 gcc deprecated-declarations shell_xfixes_cursor_update_texture_image 'clutter_texture_get_cogl_texture' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-texture.h:78)
shell-xfixes-cursor.c:397:5 gcc deprecated-declarations shell_xfixes_cursor_update_texture_image 'clutter_texture_set_cogl_texture' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-texture.h:80)
  1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 
  5 #include "shell-xfixes-cursor.h"
  6 
  7 #include <clutter/x11/clutter-x11.h>
  8 #include <X11/extensions/Xfixes.h>
  9 
 10 /**
 11  * SECTION:shell-xfixes-cursor
 12  * @short_description: Capture/manipulate system mouse cursor.
 13  *
 14  * The #ShellXFixesCursor object uses the XFixes extension to show/hide the
 15  * the system mouse pointer, to grab its image as it changes, and emit a
 16  * notification when its image changes.
 17  */
 18 
 19 struct _ShellXFixesCursorClass
 20 {
 21   GObjectClass parent_class;
 22 };
 23 
 24 struct _ShellXFixesCursor {
 25   GObject parent;
 26 
 27   ClutterStage *stage;
 28 
 29   gboolean have_xfixes;
 30   int xfixes_event_base;
 31 
 32   gboolean is_showing;
 33 
 34   CoglHandle *cursor_sprite;
 35   int cursor_hot_x;
 36   int cursor_hot_y;
 37 };
 38 
 39 static void xfixes_cursor_show        (ShellXFixesCursor *xfixes_cursor);
 40 static void xfixes_cursor_hide        (ShellXFixesCursor *xfixes_cursor);
 41 
 42 static void xfixes_cursor_set_stage   (ShellXFixesCursor *xfixes_cursor,
 43                                        ClutterStage  *stage);
 44 
 45 static void xfixes_cursor_reset_image (ShellXFixesCursor *xfixes_cursor);
 46 
 47 enum {
 48   PROP_0,
 49   PROP_STAGE,
 50 };
 51 
 52 G_DEFINE_TYPE(ShellXFixesCursor, shell_xfixes_cursor, G_TYPE_OBJECT);
 53 
 54 enum {
 55     CURSOR_CHANGED,
 56     LAST_SIGNAL
 57 };
 58 
 59 static guint signals[LAST_SIGNAL] = { 0 };
 60 
 61 static void
 62 shell_xfixes_cursor_init (ShellXFixesCursor *xfixes_cursor)
 63 {
 64   // (JS) Best (?) that can be assumed since XFixes doesn't provide a way of
 65   // detecting if the system mouse cursor is showing or not.
 66   xfixes_cursor->is_showing = TRUE;
 67 }
 68 
 69 static void
 70 shell_xfixes_cursor_finalize (GObject  *object)
 71 {
 72   ShellXFixesCursor *xfixes_cursor = SHELL_XFIXES_CURSOR (object);
 73 
 74   // Make sure the system cursor is showing before leaving the stage.
 75   xfixes_cursor_show (xfixes_cursor);
 76   xfixes_cursor_set_stage (xfixes_cursor, NULL);
 77   if (xfixes_cursor->cursor_sprite != NULL)
 78     cogl_handle_unref (xfixes_cursor->cursor_sprite);
 79 
 80   G_OBJECT_CLASS (shell_xfixes_cursor_parent_class)->finalize (object);
 81 }
 82 
 83 static void
 84 xfixes_cursor_on_stage_destroy (ClutterActor  *actor,
 85                                 ShellXFixesCursor *xfixes_cursor)
 86 {
 87   xfixes_cursor_set_stage (xfixes_cursor, NULL);
 88 }
 89 
 90 static ClutterX11FilterReturn
 91 xfixes_cursor_event_filter (XEvent        *xev,
 92                             ClutterEvent  *cev,
 93                             gpointer       data)
 94 {
 95   ShellXFixesCursor *xfixes_cursor = data;
 96 
 97   if (xev->xany.window != clutter_x11_get_stage_window (xfixes_cursor->stage))
 98     return CLUTTER_X11_FILTER_CONTINUE;
 99 
100   if (xev->xany.type == xfixes_cursor->xfixes_event_base + XFixesCursorNotify)
101     {
102       XFixesCursorNotifyEvent *notify_event = (XFixesCursorNotifyEvent *)xev;
103       if (notify_event->subtype == XFixesDisplayCursorNotify)
104         xfixes_cursor_reset_image (xfixes_cursor);
105     }
106     return CLUTTER_X11_FILTER_CONTINUE;
107 }
108 
109 static void
110 xfixes_cursor_set_stage (ShellXFixesCursor *xfixes_cursor,
111                          ClutterStage  *stage)
112 {
113   if (xfixes_cursor->stage == stage)
114     return;
115 
116   if (xfixes_cursor->stage)
117     {
118       g_signal_handlers_disconnect_by_func (xfixes_cursor->stage,
119                                             (void *)xfixes_cursor_on_stage_destroy,
120                                             xfixes_cursor);
121 
122       clutter_x11_remove_filter (xfixes_cursor_event_filter, xfixes_cursor);
123     }
124   xfixes_cursor->stage = stage;
125   if (xfixes_cursor->stage)
126     {
127       int error_base;
128 
129       xfixes_cursor->stage = stage;
130       g_signal_connect (xfixes_cursor->stage, "destroy",
131                         G_CALLBACK (xfixes_cursor_on_stage_destroy), xfixes_cursor);
132 
133       clutter_x11_add_filter (xfixes_cursor_event_filter, xfixes_cursor);
134 
135       xfixes_cursor->have_xfixes = XFixesQueryExtension (clutter_x11_get_default_display (),
136                                                          &xfixes_cursor->xfixes_event_base,
137                                                          &error_base);
138       if (xfixes_cursor->have_xfixes)
139         XFixesSelectCursorInput (clutter_x11_get_default_display (),
140                                  clutter_x11_get_stage_window (stage),
141                                  XFixesDisplayCursorNotifyMask);
142 
143       xfixes_cursor_reset_image (xfixes_cursor);
144     }
145 }
146 
147 static void
148 xfixes_cursor_show (ShellXFixesCursor *xfixes_cursor)
149 {
150   int minor, major;
151   Display *xdisplay;
152   Window xwindow;
153 
154   if (xfixes_cursor->is_showing == TRUE)
155       return;
156 
157   if (!xfixes_cursor->have_xfixes || !xfixes_cursor->stage)
158       return;
159 
160   xdisplay = clutter_x11_get_default_display ();
161   xwindow = clutter_x11_get_stage_window (xfixes_cursor->stage);
162   XFixesQueryVersion (xdisplay, &major, &minor);
163   if (major >= 4)
164     {
165       XFixesShowCursor (xdisplay, xwindow);
166       xfixes_cursor->is_showing = TRUE;
167     }
168 }
169 
170 static void
171 xfixes_cursor_hide (ShellXFixesCursor *xfixes_cursor)
172 {
173   int minor, major;
174   Display *xdisplay;
175   Window xwindow;
176 
177   if (xfixes_cursor->is_showing == FALSE)
178       return;
179 
180   if (!xfixes_cursor->have_xfixes || !xfixes_cursor->stage)
181       return;
182 
183   xdisplay = clutter_x11_get_default_display ();
184   xwindow = clutter_x11_get_stage_window (xfixes_cursor->stage);
185   XFixesQueryVersion (xdisplay, &major, &minor);
186   if (major >= 4)
187     {
188       XFixesHideCursor (xdisplay, xwindow);
189       xfixes_cursor->is_showing = FALSE;
190     }
191 }
192 
193 static void
194 xfixes_cursor_reset_image (ShellXFixesCursor *xfixes_cursor)
195 {
196   XFixesCursorImage *cursor_image;
197   CoglHandle sprite = COGL_INVALID_HANDLE;
198   guint8 *cursor_data;
199   gboolean free_cursor_data;
200 
201   if (!xfixes_cursor->have_xfixes)
202     return;
203 
204   cursor_image = XFixesGetCursorImage (clutter_x11_get_default_display ());
205   if (!cursor_image)
206     return;
207 
208   /* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit
209    * quantities as arrays of long; we need to convert on 64 bit */
210   if (sizeof(long) == 4)
211     {
212       cursor_data = (guint8 *)cursor_image->pixels;
213       free_cursor_data = FALSE;
214     }
215   else
216     {
217       int i, j;
218       guint32 *cursor_words;
219       gulong *p;
220       guint32 *q;
221 
222       cursor_words = g_new (guint32, cursor_image->width * cursor_image->height);
223       cursor_data = (guint8 *)cursor_words;
224 
225       p = cursor_image->pixels;
226       q = cursor_words;
227       for (j = 0; j < cursor_image->height; j++)
228         for (i = 0; i < cursor_image->width; i++)
229           *(q++) = *(p++);
230 
231       free_cursor_data = TRUE;
232     }
233 
234   sprite = cogl_texture_new_from_data (cursor_image->width,
235                                        cursor_image->height,
236                                        COGL_TEXTURE_NONE,
237                                        CLUTTER_CAIRO_FORMAT_ARGB32,
238                                        COGL_PIXEL_FORMAT_ANY,
239                                        cursor_image->width * 4, /* stride */
240                                        cursor_data);
241 
242   if (free_cursor_data)
243     g_free (cursor_data);
244 
245   if (sprite != COGL_INVALID_HANDLE)
246     {
247       if (xfixes_cursor->cursor_sprite != NULL)
248         cogl_handle_unref (xfixes_cursor->cursor_sprite);
249 
250       xfixes_cursor->cursor_sprite = sprite;
251       xfixes_cursor->cursor_hot_x = cursor_image->xhot;
252       xfixes_cursor->cursor_hot_y = cursor_image->yhot;
253       g_signal_emit (xfixes_cursor, signals[CURSOR_CHANGED], 0);
254     }
255   XFree (cursor_image);
256 }
257 
258 static void
259 shell_xfixes_cursor_set_property (GObject      *object,
260                                  guint         prop_id,
261                                  const GValue *value,
262                                  GParamSpec   *pspec)
263 {
264   ShellXFixesCursor *xfixes_cursor = SHELL_XFIXES_CURSOR (object);
265 
266   switch (prop_id)
267     {
268     case PROP_STAGE:
269       xfixes_cursor_set_stage (xfixes_cursor, g_value_get_object (value));
270       break;
271     default:
272       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
273       break;
274     }
275 }
276 
277 static void
278 shell_xfixes_cursor_get_property (GObject         *object,
279                              guint            prop_id,
280                              GValue          *value,
281                              GParamSpec      *pspec)
282 {
283   ShellXFixesCursor *xfixes_cursor = SHELL_XFIXES_CURSOR (object);
284 
285   switch (prop_id)
286     {
287     case PROP_STAGE:
288       g_value_set_object (value, G_OBJECT (xfixes_cursor->stage));
289       break;
290     default:
291       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
292       break;
293     }
294 }
295 
296 static void
297 shell_xfixes_cursor_class_init (ShellXFixesCursorClass *klass)
298 {
299   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
300 
301   gobject_class->finalize = shell_xfixes_cursor_finalize;
302 
303   signals[CURSOR_CHANGED] = g_signal_new ("cursor-change",
304                                        G_TYPE_FROM_CLASS (klass),
305                                        G_SIGNAL_RUN_LAST,
306                                        0,
307                                        NULL, NULL, NULL,
308                                        G_TYPE_NONE, 0);
309 
310   gobject_class->get_property = shell_xfixes_cursor_get_property;
311   gobject_class->set_property = shell_xfixes_cursor_set_property;
312 
313   g_object_class_install_property (gobject_class,
314                                    PROP_STAGE,
315                                    g_param_spec_object ("stage",
316                                                         "Stage",
317                                                         "Stage for mouse cursor",
318                                                         CLUTTER_TYPE_STAGE,
319                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
320 }
321 
322 /**
323  * shell_xfixes_cursor_get_for_stage:
324  * @stage: (transfer none): The #ClutterStage to get the cursor for
325  *
326  * Return value: (transfer none): A #ShellXFixesCursor instance
327  */
328 ShellXFixesCursor *
329 shell_xfixes_cursor_get_for_stage (ClutterStage *stage)
330 {
331   ShellXFixesCursor *instance;
332   static GQuark xfixes_cursor_quark;
333 
334   if (G_UNLIKELY (xfixes_cursor_quark == 0))
335     xfixes_cursor_quark = g_quark_from_static_string ("gnome-shell-xfixes-cursor");
336 
337   instance = g_object_get_qdata (G_OBJECT (stage), xfixes_cursor_quark);
338 
339   if (instance == NULL)
340     {
341       instance = g_object_new (SHELL_TYPE_XFIXES_CURSOR,
342                                "stage", stage,
343                                NULL);
344       g_object_set_qdata (G_OBJECT (stage), xfixes_cursor_quark, instance);
345     }
346 
347   return instance;
348 }
349 
350 /**
351  * shell_xfixes_cursor_hide:
352  * @xfixes_cursor: the #ShellXFixesCursor
353  *
354  * Hide the system mouse cursor.
355  */
356 void
357 shell_xfixes_cursor_hide (ShellXFixesCursor *xfixes_cursor)
358 {
359   g_return_if_fail (SHELL_IS_XFIXES_CURSOR (xfixes_cursor));
360 
361   xfixes_cursor_hide (xfixes_cursor);
362 }
363 
364 /**
365  * shell_xfixes_cursor_show:
366  * @xfixes_cursor: the #ShellXFixesCursor
367  *
368  * Show the system mouse cursor to show
369  */
370 void
371 shell_xfixes_cursor_show (ShellXFixesCursor *xfixes_cursor)
372 {
373   g_return_if_fail (SHELL_IS_XFIXES_CURSOR (xfixes_cursor));
374 
375   xfixes_cursor_show (xfixes_cursor);
376 }
377 
378 /**
379  * shell_xfixes_cursor_update_texture_image:
380  * @xfixes_cursor:  the #ShellXFixesCursor
381  * @texture:        ClutterTexture to update with the current sprite image.
382  */
383 void
384 shell_xfixes_cursor_update_texture_image (ShellXFixesCursor *xfixes_cursor,
385                                           ClutterTexture *texture)
386 {
387     CoglHandle *old_sprite;
388     g_return_if_fail (SHELL_IS_XFIXES_CURSOR (xfixes_cursor));
389 
390     if (texture == NULL)
391         return;
392 
393     old_sprite = clutter_texture_get_cogl_texture (texture);
'clutter_texture_get_cogl_texture' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-texture.h:78)
(emitted by gcc)
394 if (xfixes_cursor->cursor_sprite == old_sprite) 395 return; 396 397 clutter_texture_set_cogl_texture (texture, xfixes_cursor->cursor_sprite);
'clutter_texture_set_cogl_texture' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-texture.h:80)
(emitted by gcc)
398 } 399 400 /** 401 * shell_xfixes_cursor_get_hot_x: 402 * @xfixes_cursor: the #ShellXFixesCursor 403 * 404 * Returns: the current mouse cursor's hot x-coordinate. 405 */ 406 int 407 shell_xfixes_cursor_get_hot_x (ShellXFixesCursor *xfixes_cursor) 408 { 409 g_return_val_if_fail (SHELL_IS_XFIXES_CURSOR (xfixes_cursor), 0); 410 411 return xfixes_cursor->cursor_hot_x; 412 } 413 414 /** 415 * shell_xfixes_cursor_get_hot_y: 416 * @xfixes_cursor: the #ShellXFixesCursor 417 * 418 * Returns: the current mouse cursor's hot y-coordinate. 419 */ 420 int 421 shell_xfixes_cursor_get_hot_y (ShellXFixesCursor *xfixes_cursor) 422 { 423 g_return_val_if_fail (SHELL_IS_XFIXES_CURSOR (xfixes_cursor), 0); 424 425 return xfixes_cursor->cursor_hot_y; 426 }