gnome-shell-3.6.3.1/src/shell-window-tracker.c

Location Tool Test ID Function Issue
shell-window-tracker.c:791:7 gcc deprecated-declarations shell_startup_sequence_create_icon 'clutter_texture_new' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-texture.h:36): Use 'clutter_image_new' instead
  1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  2 
  3 #include "config.h"
  4 
  5 #include <string.h>
  6 #include <stdlib.h>
  7 
  8 #include <X11/Xlib.h>
  9 #include <X11/Xatom.h>
 10 #include <gdk/gdk.h>
 11 #include <gdk/gdkx.h>
 12 #include <meta/display.h>
 13 #include <meta/group.h>
 14 #include <meta/util.h>
 15 #include <meta/window.h>
 16 
 17 #define SN_API_NOT_YET_FROZEN 1
 18 #include <libsn/sn.h>
 19 
 20 #include "shell-window-tracker-private.h"
 21 #include "shell-app-private.h"
 22 #include "shell-global.h"
 23 #include "st.h"
 24 
 25 /* This file includes modified code from
 26  * desktop-data-engine/engine-dbus/hippo-application-monitor.c
 27  * in the functions collecting application usage data.
 28  * Written by Owen Taylor, originally licensed under LGPL 2.1.
 29  * Copyright Red Hat, Inc. 2006-2008
 30  */
 31 
 32 /**
 33  * SECTION:shell-window-tracker
 34  * @short_description: Associate windows with applications
 35  *
 36  * Maintains a mapping from windows to applications (.desktop file ids).
 37  * It currently implements this with some heuristics on the WM_CLASS X11
 38  * property (and some static override regexps); in the future, we want to
 39  * have it also track through startup-notification.
 40  */
 41 
 42 struct _ShellWindowTracker
 43 {
 44   GObject parent;
 45 
 46   ShellApp *focus_app;
 47 
 48   /* <MetaWindow * window, ShellApp *app> */
 49   GHashTable *window_to_app;
 50 
 51   /* <int, ShellApp *app> */
 52   GHashTable *launched_pid_to_app;
 53 };
 54 
 55 G_DEFINE_TYPE (ShellWindowTracker, shell_window_tracker, G_TYPE_OBJECT);
 56 
 57 enum {
 58   PROP_0,
 59   PROP_FOCUS_APP
 60 };
 61 
 62 enum {
 63   STARTUP_SEQUENCE_CHANGED,
 64   TRACKED_WINDOWS_CHANGED,
 65 
 66   LAST_SIGNAL
 67 };
 68 
 69 static guint signals[LAST_SIGNAL] = { 0 };
 70 
 71 static void shell_window_tracker_finalize (GObject *object);
 72 static void set_focus_app (ShellWindowTracker  *tracker,
 73                            ShellApp            *new_focus_app);
 74 static void on_focus_window_changed (MetaDisplay *display, GParamSpec *spec, ShellWindowTracker *tracker);
 75 
 76 static void track_window (ShellWindowTracker *tracker, MetaWindow *window);
 77 static void disassociate_window (ShellWindowTracker *tracker, MetaWindow *window);
 78 
 79 
 80 static void
 81 shell_window_tracker_get_property (GObject    *gobject,
 82                             guint       prop_id,
 83                             GValue     *value,
 84                             GParamSpec *pspec)
 85 {
 86   ShellWindowTracker *tracker = SHELL_WINDOW_TRACKER (gobject);
 87 
 88   switch (prop_id)
 89     {
 90     case PROP_FOCUS_APP:
 91       g_value_set_object (value, tracker->focus_app);
 92       break;
 93     default:
 94       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
 95       break;
 96     }
 97 }
 98 
 99 static void
100 shell_window_tracker_class_init (ShellWindowTrackerClass *klass)
101 {
102   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
103 
104   gobject_class->get_property = shell_window_tracker_get_property;
105   gobject_class->finalize = shell_window_tracker_finalize;
106 
107   g_object_class_install_property (gobject_class,
108                                    PROP_FOCUS_APP,
109                                    g_param_spec_object ("focus-app",
110                                                         "Focus App",
111                                                         "Focused application",
112                                                         SHELL_TYPE_APP,
113                                                         G_PARAM_READABLE));
114 
115   signals[STARTUP_SEQUENCE_CHANGED] = g_signal_new ("startup-sequence-changed",
116                                    SHELL_TYPE_WINDOW_TRACKER,
117                                    G_SIGNAL_RUN_LAST,
118                                    0,
119                                    NULL, NULL, NULL,
120                                    G_TYPE_NONE, 1, SHELL_TYPE_STARTUP_SEQUENCE);
121   signals[TRACKED_WINDOWS_CHANGED] = g_signal_new ("tracked-windows-changed",
122                                                    SHELL_TYPE_WINDOW_TRACKER,
123                                                    G_SIGNAL_RUN_LAST,
124                                                    0,
125                                                    NULL, NULL, NULL,
126                                                    G_TYPE_NONE, 0);
127 }
128 
129 /**
130  * shell_window_tracker_is_window_interesting:
131  *
132  * The ShellWindowTracker associates certain kinds of windows with
133  * applications; however, others we don't want to
134  * appear in places where we want to give a list of windows
135  * for an application, such as the alt-tab dialog.
136  *
137  * An example of a window we don't want to show is the root
138  * desktop window.  We skip all override-redirect types, and also
139  * exclude other window types like tooltip explicitly, though generally
140  * most of these should be override-redirect.
141  *
142  * Returns: %TRUE iff a window is "interesting"
143  */
144 gboolean
145 shell_window_tracker_is_window_interesting (MetaWindow *window)
146 {
147   if (meta_window_is_override_redirect (window)
148       || meta_window_is_skip_taskbar (window))
149     return FALSE;
150 
151   switch (meta_window_get_window_type (window))
152     {
153       /* Definitely ignore these. */
154       case META_WINDOW_DESKTOP:
155       case META_WINDOW_DOCK:
156       case META_WINDOW_SPLASHSCREEN:
157       /* Should have already been handled by override_redirect above,
158        * but explicitly list here so we get the "unhandled enum"
159        * warning if in the future anything is added.*/
160       case META_WINDOW_DROPDOWN_MENU:
161       case META_WINDOW_POPUP_MENU:
162       case META_WINDOW_TOOLTIP:
163       case META_WINDOW_NOTIFICATION:
164       case META_WINDOW_COMBO:
165       case META_WINDOW_DND:
166       case META_WINDOW_OVERRIDE_OTHER:
167         return FALSE;
168       case META_WINDOW_NORMAL:
169       case META_WINDOW_DIALOG:
170       case META_WINDOW_MODAL_DIALOG:
171       case META_WINDOW_MENU:
172       case META_WINDOW_TOOLBAR:
173       case META_WINDOW_UTILITY:
174         break;
175     }
176 
177   return TRUE;
178 }
179 
180 /**
181  * get_app_from_window_group:
182  * @monitor: a #ShellWindowTracker
183  * @window: a #MetaWindow
184  *
185  * Check other windows in the group for @window to see if we have
186  * an application for one of them.
187  *
188  * Return value: (transfer full): A newly-referenced #ShellApp, or %NULL
189  */
190 static ShellApp*
191 get_app_from_window_group (ShellWindowTracker  *tracker,
192                            MetaWindow          *window)
193 {
194   ShellApp *result;
195   GSList *group_windows;
196   MetaGroup *group;
197   GSList *iter;
198 
199   group = meta_window_get_group (window);
200   if (group == NULL)
201     return NULL;
202 
203   group_windows = meta_group_list_windows (group);
204 
205   result = NULL;
206   /* Try finding a window in the group of type NORMAL; if we
207    * succeed, use that as our source. */
208   for (iter = group_windows; iter; iter = iter->next)
209     {
210       MetaWindow *group_window = iter->data;
211 
212       if (meta_window_get_window_type (group_window) != META_WINDOW_NORMAL)
213         continue;
214 
215       result = g_hash_table_lookup (tracker->window_to_app, group_window);
216       if (result)
217         break;
218     }
219 
220   g_slist_free (group_windows);
221 
222   if (result)
223     g_object_ref (result);
224 
225   return result;
226 }
227 
228 /**
229  * get_app_from_window_pid:
230  * @tracker: a #ShellWindowTracker
231  * @window: a #MetaWindow
232  *
233  * Check if the pid associated with @window corresponds to an
234  * application we launched.
235  *
236  * Return value: (transfer full): A newly-referenced #ShellApp, or %NULL
237  */
238 static ShellApp *
239 get_app_from_window_pid (ShellWindowTracker  *tracker,
240                          MetaWindow          *window)
241 {
242   ShellApp *result;
243   int pid;
244 
245   if (meta_window_is_remote (window))
246     return NULL;
247 
248   pid = meta_window_get_pid (window);
249 
250   if (pid == -1)
251     return NULL;
252 
253   result = g_hash_table_lookup (tracker->launched_pid_to_app, GINT_TO_POINTER (pid));
254   if (result != NULL)
255     g_object_ref (result);
256 
257   return result;
258 }
259 
260 /**
261  * get_app_for_window:
262  *
263  * Determines the application associated with a window, using
264  * all available information such as the window's MetaGroup,
265  * and what we know about other windows.
266  *
267  * Returns: (transfer full): a #ShellApp, or NULL if none is found
268  */
269 static ShellApp *
270 get_app_for_window (ShellWindowTracker    *tracker,
271                     MetaWindow            *window)
272 {
273   ShellAppSystem *app_system;
274   ShellApp *result = NULL;
275   const char *startup_id;
276 
277   app_system = shell_app_system_get_default ();
278 
279   /* First, we check whether we already know about this window,
280    * if so, just return that.
281    */
282   if (meta_window_get_window_type (window) == META_WINDOW_NORMAL
283       || meta_window_is_remote (window))
284     {
285       result = g_hash_table_lookup (tracker->window_to_app, window);
286       if (result != NULL)
287         {
288           g_object_ref (result);
289           return result;
290         }
291     }
292 
293   if (meta_window_is_remote (window))
294     return _shell_app_new_for_window (window);
295 
296   /* Check if the app's WM_CLASS specifies an app; this is
297    * canonical if it does.
298    */
299   result = shell_app_system_lookup_wmclass (app_system,
300                                             meta_window_get_wm_class (window));
301   if (result != NULL)
302     return g_object_ref (result);
303 
304   result = get_app_from_window_pid (tracker, window);
305   if (result != NULL)
306     return result;
307 
308   /* Now we check whether we have a match through startup-notification */
309   startup_id = meta_window_get_startup_id (window);
310   if (startup_id)
311     {
312       GSList *iter, *sequences;
313 
314       sequences = shell_window_tracker_get_startup_sequences (tracker);
315       for (iter = sequences; iter; iter = iter->next)
316         {
317           ShellStartupSequence *sequence = iter->data;
318           const char *id = shell_startup_sequence_get_id (sequence);
319           if (strcmp (id, startup_id) != 0)
320             continue;
321 
322           result = shell_startup_sequence_get_app (sequence);
323           if (result)
324             {
325               result = g_object_ref (result);
326               break;
327             }
328         }
329     }
330 
331   /* If we didn't get a startup-notification match, see if we matched
332    * any other windows in the group.
333    */
334   if (result == NULL)
335     result = get_app_from_window_group (tracker, window);
336 
337   /* Our last resort - we create a fake app from the window */
338   if (result == NULL)
339     result = _shell_app_new_for_window (window);
340 
341   return result;
342 }
343 
344 const char *
345 _shell_window_tracker_get_app_context (ShellWindowTracker *tracker, ShellApp *app)
346 {
347   return "";
348 }
349 
350 static void
351 update_focus_app (ShellWindowTracker *self)
352 {
353   MetaWindow *new_focus_win;
354   ShellApp *new_focus_app;
355 
356   new_focus_win = meta_display_get_focus_window (shell_global_get_display (shell_global_get ()));
357   new_focus_app = new_focus_win ? shell_window_tracker_get_window_app (self, new_focus_win) : NULL;
358 
359   if (new_focus_app)
360     {
361       shell_app_update_window_actions (new_focus_app, new_focus_win);
362       shell_app_update_app_menu (new_focus_app, new_focus_win);
363     }
364 
365   set_focus_app (self, new_focus_app);
366 }
367 
368 static void
369 on_wm_class_changed (MetaWindow  *window,
370                      GParamSpec  *pspec,
371                      gpointer     user_data)
372 {
373   ShellWindowTracker *self = SHELL_WINDOW_TRACKER (user_data);
374 
375   /* It's simplest to just treat this as a remove + add. */
376   disassociate_window (self, window);
377   track_window (self, window);
378   /* also just recaulcuate the focused app, in case it was the focused
379      window that changed */
380   update_focus_app (self);
381 }
382 
383 static void
384 track_window (ShellWindowTracker *self,
385               MetaWindow      *window)
386 {
387   ShellApp *app;
388 
389   if (!shell_window_tracker_is_window_interesting (window))
390     return;
391 
392   app = get_app_for_window (self, window);
393   if (!app)
394     return;
395 
396   /* At this point we've stored the association from window -> application */
397   g_hash_table_insert (self->window_to_app, window, app);
398 
399   g_signal_connect (window, "notify::wm-class", G_CALLBACK (on_wm_class_changed), self);
400 
401   _shell_app_add_window (app, window);
402 
403   g_signal_emit (self, signals[TRACKED_WINDOWS_CHANGED], 0);
404 }
405 
406 static void
407 shell_window_tracker_on_window_added (MetaWorkspace   *workspace,
408                                    MetaWindow      *window,
409                                    gpointer         user_data)
410 {
411   ShellWindowTracker *self = SHELL_WINDOW_TRACKER (user_data);
412 
413   track_window (self, window);
414 }
415 
416 static void
417 disassociate_window (ShellWindowTracker   *self,
418                      MetaWindow        *window)
419 {
420   ShellApp *app;
421 
422   app = g_hash_table_lookup (self->window_to_app, window);
423   if (!app)
424     return;
425 
426   g_object_ref (app);
427 
428   g_hash_table_remove (self->window_to_app, window);
429 
430   if (shell_window_tracker_is_window_interesting (window))
431     {
432       _shell_app_remove_window (app, window);
433       g_signal_handlers_disconnect_by_func (window, G_CALLBACK(on_wm_class_changed), self);
434     }
435 
436   g_signal_emit (self, signals[TRACKED_WINDOWS_CHANGED], 0);
437 
438   g_object_unref (app);
439 }
440 
441 static void
442 shell_window_tracker_on_window_removed (MetaWorkspace   *workspace,
443                                      MetaWindow      *window,
444                                      gpointer         user_data)
445 {
446   disassociate_window (SHELL_WINDOW_TRACKER (user_data), window);
447 }
448 
449 static void
450 load_initial_windows (ShellWindowTracker *tracker)
451 {
452   GList *workspaces, *iter;
453   MetaScreen *screen = shell_global_get_screen (shell_global_get ());
454   workspaces = meta_screen_get_workspaces (screen);
455 
456   for (iter = workspaces; iter; iter = iter->next)
457     {
458       MetaWorkspace *workspace = iter->data;
459       GList *windows = meta_workspace_list_windows (workspace);
460       GList *window_iter;
461 
462       for (window_iter = windows; window_iter; window_iter = window_iter->next)
463         {
464           MetaWindow *window = window_iter->data;
465           track_window (tracker, window);
466         }
467 
468       g_list_free (windows);
469     }
470 }
471 
472 static void
473 shell_window_tracker_on_n_workspaces_changed (MetaScreen    *screen,
474                                            GParamSpec    *pspec,
475                                            gpointer       user_data)
476 {
477   ShellWindowTracker *self = SHELL_WINDOW_TRACKER (user_data);
478   GList *workspaces, *iter;
479 
480   workspaces = meta_screen_get_workspaces (screen);
481 
482   for (iter = workspaces; iter; iter = iter->next)
483     {
484       MetaWorkspace *workspace = iter->data;
485 
486       /* This pair of disconnect/connect is idempotent if we were
487        * already connected, while ensuring we get connected for
488        * new workspaces.
489        */
490       g_signal_handlers_disconnect_by_func (workspace,
491                                             shell_window_tracker_on_window_added,
492                                             self);
493       g_signal_handlers_disconnect_by_func (workspace,
494                                             shell_window_tracker_on_window_removed,
495                                             self);
496 
497       g_signal_connect (workspace, "window-added",
498                         G_CALLBACK (shell_window_tracker_on_window_added), self);
499       g_signal_connect (workspace, "window-removed",
500                         G_CALLBACK (shell_window_tracker_on_window_removed), self);
501     }
502 }
503 
504 static void
505 init_window_tracking (ShellWindowTracker *self)
506 {
507   MetaDisplay *display;
508   MetaScreen *screen = shell_global_get_screen (shell_global_get ());
509 
510   g_signal_connect (screen, "notify::n-workspaces",
511                     G_CALLBACK (shell_window_tracker_on_n_workspaces_changed), self);
512   display = meta_screen_get_display (screen);
513   g_signal_connect (display, "notify::focus-window",
514                     G_CALLBACK (on_focus_window_changed), self);
515 
516   shell_window_tracker_on_n_workspaces_changed (screen, NULL, self);
517 }
518 
519 static void
520 on_startup_sequence_changed (MetaScreen            *screen,
521                              SnStartupSequence     *sequence,
522                              ShellWindowTracker    *self)
523 {
524   ShellApp *app;
525 
526   app = shell_startup_sequence_get_app ((ShellStartupSequence*)sequence);
527   if (app)
528     _shell_app_handle_startup_sequence (app, sequence);
529 
530   g_signal_emit (G_OBJECT (self), signals[STARTUP_SEQUENCE_CHANGED], 0, sequence);
531 }
532 
533 static void
534 shell_window_tracker_init (ShellWindowTracker *self)
535 {
536   MetaScreen *screen;
537 
538   self->window_to_app = g_hash_table_new_full (g_direct_hash, g_direct_equal,
539                                                NULL, (GDestroyNotify) g_object_unref);
540 
541   self->launched_pid_to_app = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_object_unref);
542 
543   screen = shell_global_get_screen (shell_global_get ());
544 
545   g_signal_connect (G_OBJECT (screen), "startup-sequence-changed",
546                     G_CALLBACK (on_startup_sequence_changed), self);
547 
548   load_initial_windows (self);
549   init_window_tracking (self);
550 }
551 
552 static void
553 shell_window_tracker_finalize (GObject *object)
554 {
555   ShellWindowTracker *self = SHELL_WINDOW_TRACKER (object);
556 
557   g_hash_table_destroy (self->window_to_app);
558   g_hash_table_destroy (self->launched_pid_to_app);
559 
560   G_OBJECT_CLASS (shell_window_tracker_parent_class)->finalize(object);
561 }
562 
563 /**
564  * shell_window_tracker_get_window_app:
565  * @tracker: An app monitor instance
566  * @metawin: A #MetaWindow
567  *
568  * Returns: (transfer full): Application associated with window
569  */
570 ShellApp *
571 shell_window_tracker_get_window_app (ShellWindowTracker *tracker,
572                                      MetaWindow         *metawin)
573 {
574   MetaWindow *transient_for;
575   ShellApp *app;
576 
577   transient_for = meta_window_get_transient_for (metawin);
578   if (transient_for != NULL)
579     metawin = transient_for;
580 
581   app = g_hash_table_lookup (tracker->window_to_app, metawin);
582   if (app)
583     g_object_ref (app);
584 
585   return app;
586 }
587 
588 
589 /**
590  * shell_window_tracker_get_app_from_pid:
591  * @tracker: A #ShellAppSystem
592  * @pid: A Unix process identifier
593  *
594  * Look up the application corresponding to a process.
595  *
596  * Returns: (transfer none): A #ShellApp, or %NULL if none
597  */
598 ShellApp *
599 shell_window_tracker_get_app_from_pid (ShellWindowTracker *tracker,
600                                        int                 pid)
601 {
602   GSList *running = shell_app_system_get_running (shell_app_system_get_default());
603   GSList *iter;
604   ShellApp *result = NULL;
605 
606   for (iter = running; iter; iter = iter->next)
607     {
608       ShellApp *app = iter->data;
609       GSList *pids = shell_app_get_pids (app);
610       GSList *pids_iter;
611 
612       for (pids_iter = pids; pids_iter; pids_iter = pids_iter->next)
613         {
614           int app_pid = GPOINTER_TO_INT (pids_iter->data);
615           if (app_pid == pid)
616             {
617               result = app;
618               break;
619             }
620         }
621       g_slist_free (pids);
622 
623       if (result != NULL)
624         break;
625     }
626 
627   g_slist_free (running);
628 
629   return result;
630 }
631 
632 static void
633 on_child_exited (GPid      pid,
634                  gint      status,
635                  gpointer  unused_data)
636 {
637   ShellWindowTracker *tracker;
638 
639   tracker = shell_window_tracker_get_default ();
640 
641   g_hash_table_remove (tracker->launched_pid_to_app, GINT_TO_POINTER((gint)pid));
642 }
643 
644 void
645 _shell_window_tracker_add_child_process_app (ShellWindowTracker *tracker,
646                                              GPid                pid,
647                                              ShellApp           *app)
648 {
649   gpointer pid_ptr = GINT_TO_POINTER((int)pid);
650 
651   if (g_hash_table_lookup (tracker->launched_pid_to_app,
652                            &pid_ptr))
653     return;
654 
655   g_hash_table_insert (tracker->launched_pid_to_app,
656                        pid_ptr,
657                        g_object_ref (app));
658   g_child_watch_add (pid, on_child_exited, NULL);
659   /* TODO: rescan unassociated windows
660    * Unlikely in practice that the launched app gets ahead of us
661    * enough to map an X window before we get scheduled after the fork(),
662    * but adding this note for future reference.
663    */
664 }
665 
666 static void
667 set_focus_app (ShellWindowTracker  *tracker,
668                ShellApp            *new_focus_app)
669 {
670   if (new_focus_app == tracker->focus_app)
671     return;
672 
673   if (tracker->focus_app != NULL)
674     g_object_unref (tracker->focus_app);
675 
676   tracker->focus_app = new_focus_app;
677 
678   if (tracker->focus_app != NULL)
679     g_object_ref (tracker->focus_app);
680 
681   g_object_notify (G_OBJECT (tracker), "focus-app");
682 }
683 
684 static void
685 on_focus_window_changed (MetaDisplay        *display,
686                          GParamSpec         *spec,
687                          ShellWindowTracker *tracker)
688 {
689   update_focus_app (tracker);
690 }
691 
692 /**
693  * shell_window_tracker_get_startup_sequences:
694  * @tracker:
695  *
696  * Returns: (transfer none) (element-type ShellStartupSequence): Currently active startup sequences
697  */
698 GSList *
699 shell_window_tracker_get_startup_sequences (ShellWindowTracker *self)
700 {
701   ShellGlobal *global = shell_global_get ();
702   MetaScreen *screen = shell_global_get_screen (global);
703   return meta_screen_get_startup_sequences (screen);
704 }
705 
706 /* sn_startup_sequence_ref returns void, so make a
707  * wrapper which returns self */
708 static SnStartupSequence *
709 sequence_ref (SnStartupSequence *sequence)
710 {
711   sn_startup_sequence_ref (sequence);
712   return sequence;
713 }
714 
715 GType
716 shell_startup_sequence_get_type (void)
717 {
718   static GType gtype = G_TYPE_INVALID;
719   if (gtype == G_TYPE_INVALID)
720     {
721       gtype = g_boxed_type_register_static ("ShellStartupSequence",
722           (GBoxedCopyFunc)sequence_ref,
723           (GBoxedFreeFunc)sn_startup_sequence_unref);
724     }
725   return gtype;
726 }
727 
728 const char *
729 shell_startup_sequence_get_id (ShellStartupSequence *sequence)
730 {
731   return sn_startup_sequence_get_id ((SnStartupSequence*)sequence);
732 }
733 
734 /**
735  * shell_startup_sequence_get_app:
736  * @sequence: A #ShellStartupSequence
737  *
738  * Returns: (transfer none): The application being launched, or %NULL if unknown.
739  */
740 ShellApp *
741 shell_startup_sequence_get_app (ShellStartupSequence *sequence)
742 {
743   const char *appid;
744   ShellAppSystem *appsys;
745   ShellApp *app;
746 
747   appid = sn_startup_sequence_get_application_id ((SnStartupSequence*)sequence);
748   if (!appid)
749     return NULL;
750 
751   appsys = shell_app_system_get_default ();
752   app = shell_app_system_lookup_app_for_path (appsys, appid);
753   return app;
754 }
755 
756 const char *
757 shell_startup_sequence_get_name (ShellStartupSequence *sequence)
758 {
759   return sn_startup_sequence_get_name ((SnStartupSequence*)sequence);
760 }
761 
762 gboolean
763 shell_startup_sequence_get_completed (ShellStartupSequence *sequence)
764 {
765   return sn_startup_sequence_get_completed ((SnStartupSequence*)sequence);
766 }
767 
768 int
769 shell_startup_sequence_get_workspace (ShellStartupSequence *sequence)
770 {
771   return sn_startup_sequence_get_workspace ((SnStartupSequence*)sequence);
772 }
773 
774 /**
775  * shell_startup_sequence_create_icon:
776  * @sequence:
777  * @size: Size in pixels of icon
778  *
779  * Returns: (transfer none): A new #ClutterTexture containing an icon for the sequence
780  */
781 ClutterActor *
782 shell_startup_sequence_create_icon (ShellStartupSequence *sequence, guint size)
783 {
784   GIcon *themed;
785   const char *icon_name;
786   ClutterActor *texture;
787 
788   icon_name = sn_startup_sequence_get_icon_name ((SnStartupSequence*)sequence);
789   if (!icon_name)
790     {
791       texture = clutter_texture_new ();
'clutter_texture_new' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-texture.h:36): Use 'clutter_image_new' instead
(emitted by gcc)
792 clutter_actor_set_size (texture, size, size); 793 return texture; 794 } 795 796 themed = g_themed_icon_new (icon_name); 797 texture = st_texture_cache_load_gicon (st_texture_cache_get_default (), 798 NULL, themed, size); 799 g_object_unref (G_OBJECT (themed)); 800 return texture; 801 } 802 803 804 /** 805 * shell_window_tracker_get_default: 806 * 807 * Return Value: (transfer none): The global #ShellWindowTracker instance 808 */ 809 ShellWindowTracker * 810 shell_window_tracker_get_default () 811 { 812 static ShellWindowTracker *instance; 813 814 if (instance == NULL) 815 instance = g_object_new (SHELL_TYPE_WINDOW_TRACKER, NULL); 816 817 return instance; 818 }