1 /* window object */
2 /* vim: set sw=2 et: */
3 
4 /*
5  * Copyright (C) 2001 Havoc Pennington
6  * Copyright (C) 2003 Kim Woelders
7  * Copyright (C) 2003 Red Hat, Inc.
8  * Copyright (C) 2006-2007 Vincent Untz
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public
21  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #include <config.h>
25 
26 #include <glib/gi18n-lib.h>
27 #include <string.h>
28 #include <time.h>
29 
30 #include "window.h"
31 #include "class-group.h"
32 #include "util.h"
33 #include "xutils.h"
34 #include "private.h"
35 #include "wnck-enum-types.h"
36 
37 /**
38  * SECTION:window
39  * @short_description: an object representing a window.
40  * @see_also: #WnckWorkspace, #WnckApplication, #WnckClassGroup
41  * @stability: Unstable
42  *
43  * The #WnckWindow objects are always owned by libwnck and must not be
44  * referenced or unreferenced.
45  */
46 
47 #define FALLBACK_NAME _("Untitled window")
48 #define ALL_WORKSPACES ((int) 0xFFFFFFFF)
49 
50 static GHashTable *window_hash = NULL;
51 
52 /* Keep 0-7 in sync with the numbers in the WindowState enum. Yeah I'm
53  * a loser.
54  */
55 #define COMPRESS_STATE(window)                          \
56   ( ((window)->priv->is_minimized        << 0) |        \
57     ((window)->priv->is_maximized_horz   << 1) |        \
58     ((window)->priv->is_maximized_vert   << 2) |        \
59     ((window)->priv->is_shaded           << 3) |        \
60     ((window)->priv->skip_pager          << 4) |        \
61     ((window)->priv->skip_taskbar        << 5) |        \
62     ((window)->priv->is_sticky           << 6) |        \
63     ((window)->priv->is_hidden           << 7) |        \
64     ((window)->priv->is_fullscreen       << 8) |        \
65     ((window)->priv->demands_attention   << 9) |        \
66     ((window)->priv->is_urgent           << 10)|        \
67     ((window)->priv->is_above            << 11)|        \
68     ((window)->priv->is_below            << 12))
69 
70 struct _WnckWindowPrivate
71 {
72   Window xwindow;
73   WnckScreen *screen;
74   WnckApplication *app;
75   WnckClassGroup *class_group;
76   Window group_leader;
77   Window transient_for;
78   int orig_event_mask;
79   GdkRectangle icon_geometry;
80   char *name;
81   char *icon_name;
82   char *session_id;
83   char *session_id_utf8;
84   char *role;
85   int pid;
86   int workspace;
87   gint sort_order;
88 
89   WnckWindowType wintype;
90 
91   GdkPixbuf *icon;
92   GdkPixbuf *mini_icon;
93 
94   WnckIconCache *icon_cache;
95 
96   WnckWindowActions actions;
97 
98   int x;
99   int y;
100   int width;
101   int height;
102 
103   int left_frame;
104   int right_frame;
105   int top_frame;
106   int bottom_frame;
107 
108   char *startup_id;
109 
110   char *res_class;
111   char *res_name;
112 
113   /* true if transient_for points to root window,
114    * not another app window
115    */
116   guint transient_for_root : 1;
117 
118   /* window state */
119   guint is_minimized : 1;
120   guint is_maximized_horz : 1;
121   guint is_maximized_vert : 1;
122   guint is_shaded : 1;
123   guint is_above : 1;
124   guint is_below : 1;
125   guint skip_pager : 1;
126   guint skip_taskbar : 1;
127   guint is_sticky : 1;
128   guint is_hidden : 1;
129   guint is_fullscreen : 1;
130   guint demands_attention : 1;
131   guint is_urgent : 1;
132 
133   time_t needs_attention_time;
134 
135   /* _NET_WM_STATE_HIDDEN doesn't map directly into an
136    * externally-visible state (it determines the WM_STATE
137    * interpretation)
138    */
139   guint net_wm_state_hidden : 1;
140   guint wm_state_iconic : 1;
141 
142   /* idle handler for updates */
143   guint update_handler;
144 
145   /* if you add flags, be sure to set them
146    * when we create the window so we get an initial update
147    */
148   guint need_update_name : 1;
149   guint need_update_state : 1;
150   guint need_update_wm_state : 1;
151   guint need_update_icon_name : 1;
152   guint need_update_workspace : 1;
153   guint need_update_actions : 1;
154   guint need_update_wintype : 1;
155   guint need_update_transient_for : 1;
156   guint need_update_startup_id : 1;
157   guint need_update_wmclass : 1;
158   guint need_update_wmhints : 1;
159   guint need_update_frame_extents : 1;
160   guint need_update_role : 1;
161 
162   guint need_emit_name_changed : 1;
163   guint need_emit_icon_changed : 1;
164   guint need_emit_class_changed : 1;
165   guint need_emit_role_changed : 1;
166   guint need_emit_type_changed : 1;
167 };
168 
169 G_DEFINE_TYPE_WITH_PRIVATE (WnckWindow, wnck_window, G_TYPE_OBJECT);
170 
171 enum {
172   NAME_CHANGED,
173   STATE_CHANGED,
174   WORKSPACE_CHANGED,
175   ICON_CHANGED,
176   ACTIONS_CHANGED,
177   GEOMETRY_CHANGED,
178   CLASS_CHANGED,
179   ROLE_CHANGED,
180   TYPE_CHANGED,
181   LAST_SIGNAL
182 };
183 
184 static void wnck_window_finalize    (GObject        *object);
185 
186 static void emit_name_changed      (WnckWindow      *window);
187 static void emit_state_changed     (WnckWindow      *window,
188                                     WnckWindowState  changed_mask,
189                                     WnckWindowState  new_state);
190 static void emit_workspace_changed (WnckWindow      *window);
191 static void emit_icon_changed      (WnckWindow      *window);
192 static void emit_actions_changed   (WnckWindow       *window,
193                                     WnckWindowActions changed_mask,
194                                     WnckWindowActions new_actions);
195 static void emit_geometry_changed  (WnckWindow      *window);
196 static void emit_class_changed     (WnckWindow      *window);
197 static void emit_role_changed      (WnckWindow      *window);
198 static void emit_type_changed      (WnckWindow      *window);
199 
200 static void update_name      (WnckWindow *window);
201 static void update_state     (WnckWindow *window);
202 static void update_wm_state  (WnckWindow *window);
203 static void update_icon_name (WnckWindow *window);
204 static void update_workspace (WnckWindow *window);
205 static void update_actions   (WnckWindow *window);
206 static void update_wintype   (WnckWindow *window);
207 static void update_transient_for (WnckWindow *window);
208 static void update_startup_id (WnckWindow *window);
209 static void update_wmclass   (WnckWindow *window);
210 static void update_frame_extents (WnckWindow *window);
211 static void update_role      (WnckWindow *window);
212 static void unqueue_update   (WnckWindow *window);
213 static void queue_update     (WnckWindow *window);
214 static void force_update_now (WnckWindow *window);
215 
216 static WnckWindow* find_last_transient_for (GList *windows,
217                                             Window xwindow);
218 
219 static guint signals[LAST_SIGNAL] = { 0 };
220 
221 void
_wnck_window_shutdown_all(void)222 _wnck_window_shutdown_all (void)
223 {
224   if (window_hash != NULL)
225     {
226       g_hash_table_destroy (window_hash);
227       window_hash = NULL;
228     }
229 }
230 
231 static void
wnck_window_init(WnckWindow * window)232 wnck_window_init (WnckWindow *window)
233 {
234   window->priv = wnck_window_get_instance_private (window);
235 
236   window->priv->icon_cache = _wnck_icon_cache_new ();
237   window->priv->icon_geometry.width = -1; /* invalid cached value */
238   window->priv->workspace = -1;
239   window->priv->sort_order = G_MAXINT;
240 
241   /* FIXME: should we have an invalid window type for this? */
242   window->priv->wintype = WNCK_WINDOW_NORMAL;
243 }
244 
245 static void
wnck_window_class_init(WnckWindowClass * klass)246 wnck_window_class_init (WnckWindowClass *klass)
247 {
248   GObjectClass *object_class = G_OBJECT_CLASS (klass);
249 
250   object_class->finalize = wnck_window_finalize;
251 
252   /**
253    * WnckWindow::name-changed:
254    * @window: the #WnckWindow which emitted the signal.
255    *
256    * Emitted when the name of @window changes.
257    */
258   signals[NAME_CHANGED] =
259     g_signal_new ("name_changed",
260                   G_OBJECT_CLASS_TYPE (object_class),
261                   G_SIGNAL_RUN_LAST,
262                   G_STRUCT_OFFSET (WnckWindowClass, name_changed),
263                   NULL, NULL, NULL,
264                   G_TYPE_NONE, 0);
265 
266   /**
267    * WnckWindow::state-changed:
268    * @window: the #WnckWindow which emitted the signal.
269    * @changed_mask: the bitmask containing bits set for all states of @window
270    * that have changed.
271    * @new_state: the new state of @window.
272    *
273    * Emitted when the state of @window changes. This can happen when @window is
274    * (un)minimized, (un)maximized, (un)sticked, (un)shaded, (un)made above,
275    * (un)made below, (un)set fullscreen, when it needs attention, etc. See
276    * #WnckWindowState for the complete list of states that might have changed.
277    */
278   signals[STATE_CHANGED] =
279     g_signal_new ("state_changed",
280                   G_OBJECT_CLASS_TYPE (object_class),
281                   G_SIGNAL_RUN_LAST,
282                   G_STRUCT_OFFSET (WnckWindowClass, state_changed),
283                   NULL, NULL, NULL,
284                   G_TYPE_NONE, 2,
285                   WNCK_TYPE_WINDOW_STATE, WNCK_TYPE_WINDOW_STATE);
286 
287   /**
288    * WnckWindow::workspace-changed:
289    * @window: the #WnckWindow which emitted the signal.
290    *
291    * Emitted when the current workspace of @window changes, or if @window has
292    * been pinned or unpinned.
293    */
294   signals[WORKSPACE_CHANGED] =
295     g_signal_new ("workspace_changed",
296                   G_OBJECT_CLASS_TYPE (object_class),
297                   G_SIGNAL_RUN_LAST,
298                   G_STRUCT_OFFSET (WnckWindowClass, workspace_changed),
299                   NULL, NULL, NULL,
300                   G_TYPE_NONE, 0);
301 
302   /**
303    * WnckWindow::icon-changed:
304    * @window: the #WnckWindow which emitted the signal.
305    *
306    * Emitted when the icon of @window changes.
307    */
308   signals[ICON_CHANGED] =
309     g_signal_new ("icon_changed",
310                   G_OBJECT_CLASS_TYPE (object_class),
311                   G_SIGNAL_RUN_LAST,
312                   G_STRUCT_OFFSET (WnckWindowClass, icon_changed),
313                   NULL, NULL, NULL,
314                   G_TYPE_NONE, 0);
315 
316   /**
317    * WnckWindow::actions-changed:
318    * @window: the #WnckWindow which emitted the signal.
319    * @changed_mask: the bitmask containing bits set for all actions
320    * availabilities for @window that have changed.
321    * @new_state: the new actions availabilities for @window.
322    *
323    * Emitted when the actions availabilities for @window change.
324    */
325   signals[ACTIONS_CHANGED] =
326     g_signal_new ("actions_changed",
327                   G_OBJECT_CLASS_TYPE (object_class),
328                   G_SIGNAL_RUN_LAST,
329                   G_STRUCT_OFFSET (WnckWindowClass, actions_changed),
330                   NULL, NULL, NULL,
331                   G_TYPE_NONE, 2,
332                   WNCK_TYPE_WINDOW_ACTIONS,
333                   WNCK_TYPE_WINDOW_ACTIONS);
334 
335   /**
336    * WnckWindow::geometry-changed:
337    * @window: the #WnckWindow which emitted the signal.
338    *
339    * Emitted when the geometry of @window changes.
340    */
341   signals[GEOMETRY_CHANGED] =
342     g_signal_new ("geometry_changed",
343                   G_OBJECT_CLASS_TYPE (object_class),
344                   G_SIGNAL_RUN_LAST,
345                   G_STRUCT_OFFSET (WnckWindowClass, geometry_changed),
346                   NULL, NULL, NULL,
347                   G_TYPE_NONE, 0);
348 
349   /**
350    * WnckWindow::class-changed:
351    * @window: the #WnckWindow which emitted the signal.
352    *
353    * Emitted when the class name or instance name of @window changes.
354    */
355   signals[CLASS_CHANGED] =
356     g_signal_new ("class_changed",
357                   G_OBJECT_CLASS_TYPE (object_class),
358                   G_SIGNAL_RUN_LAST,
359                   G_STRUCT_OFFSET (WnckWindowClass, class_changed),
360                   NULL, NULL, NULL,
361                   G_TYPE_NONE, 0);
362 
363   /**
364    * WnckWindow::role-changed:
365    * @window: the #WnckWindow which emitted the signal.
366    *
367    * Emitted when the role of @window changes.
368    */
369   signals[ROLE_CHANGED] =
370     g_signal_new ("role_changed",
371                   G_OBJECT_CLASS_TYPE (object_class),
372                   G_SIGNAL_RUN_LAST,
373                   G_STRUCT_OFFSET (WnckWindowClass, role_changed),
374                   NULL, NULL, NULL,
375                   G_TYPE_NONE, 0);
376 
377   /**
378    * WnckWindow::type-changed:
379    * @window: the #WnckWindow which emitted the signal.
380    *
381    * Emitted when the EWMH type hint of the window changes.
382    *
383    * Since: 3.20
384    */
385   signals[TYPE_CHANGED] =
386     g_signal_new ("type_changed",
387                   G_OBJECT_CLASS_TYPE (object_class),
388                   G_SIGNAL_RUN_LAST,
389                   G_STRUCT_OFFSET (WnckWindowClass, type_changed),
390                   NULL, NULL, NULL,
391                   G_TYPE_NONE, 0);
392 }
393 
394 static void
wnck_window_finalize(GObject * object)395 wnck_window_finalize (GObject *object)
396 {
397   WnckWindow *window;
398 
399   window = WNCK_WINDOW (object);
400 
401   _wnck_select_input (WNCK_SCREEN_XSCREEN (window->priv->screen),
402                       window->priv->xwindow,
403                       window->priv->orig_event_mask,
404                       FALSE);
405 
406   unqueue_update (window);
407 
408   if (window->priv->app)
409     g_object_unref (G_OBJECT (window->priv->app));
410   window->priv->app = NULL;
411 
412   if (window->priv->class_group)
413     g_object_unref (G_OBJECT (window->priv->class_group));
414   window->priv->class_group = NULL;
415 
416   g_free (window->priv->name);
417   window->priv->name = NULL;
418   g_free (window->priv->icon_name);
419   window->priv->icon_name = NULL;
420   g_free (window->priv->session_id);
421   window->priv->session_id = NULL;
422   g_free (window->priv->session_id_utf8);
423   window->priv->session_id_utf8 = NULL;
424 
425   if (window->priv->icon)
426     g_object_unref (G_OBJECT (window->priv->icon));
427   window->priv->icon = NULL;
428 
429   if (window->priv->mini_icon)
430     g_object_unref (G_OBJECT (window->priv->mini_icon));
431   window->priv->mini_icon = NULL;
432 
433   _wnck_icon_cache_free (window->priv->icon_cache);
434   window->priv->icon_cache = NULL;
435 
436   g_free (window->priv->startup_id);
437   window->priv->startup_id = NULL;
438   g_free (window->priv->res_class);
439   window->priv->res_class = NULL;
440   g_free (window->priv->res_name);
441   window->priv->res_name = NULL;
442 
443   window->priv->xwindow = None;
444 
445   G_OBJECT_CLASS (wnck_window_parent_class)->finalize (object);
446 }
447 
448 /**
449  * wnck_window_get:
450  * @xwindow: an X window ID.
451  *
452  * Gets a preexisting #WnckWindow for the X window @xwindow. This will not
453  * create a #WnckWindow if none exists. The function is robust against bogus
454  * window IDs.
455  *
456  * Return value: (transfer none): the #WnckWindow for @xwindow. The returned
457  * #WnckWindow is owned by libwnck and must not be referenced or unreferenced.
458  **/
459 WnckWindow*
wnck_window_get(gulong xwindow)460 wnck_window_get (gulong xwindow)
461 {
462   if (window_hash == NULL)
463     return NULL;
464   else
465     return g_hash_table_lookup (window_hash, &xwindow);
466 }
467 
468 /**
469  * wnck_window_get_screen:
470  * @window: a #WnckWindow.
471  *
472  * Gets the #WnckScreen @window is on.
473  *
474  * Return value: (transfer none): the #WnckScreen @window is on. The returned
475  * #WnckScreen is owned by libwnck and must not be referenced or unreferenced.
476  **/
477 WnckScreen*
wnck_window_get_screen(WnckWindow * window)478 wnck_window_get_screen (WnckWindow *window)
479 {
480   g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
481 
482   return window->priv->screen;
483 }
484 
485 WnckWindow*
_wnck_window_create(Window xwindow,WnckScreen * screen,gint sort_order)486 _wnck_window_create (Window      xwindow,
487                      WnckScreen *screen,
488                      gint        sort_order)
489 {
490   WnckWindow *window;
491   Screen     *xscreen;
492 
493   if (window_hash == NULL)
494     window_hash = g_hash_table_new_full (_wnck_xid_hash, _wnck_xid_equal,
495                                          NULL, g_object_unref);
496 
497   g_return_val_if_fail (g_hash_table_lookup (window_hash, &xwindow) == NULL,
498                         NULL);
499 
500   xscreen = WNCK_SCREEN_XSCREEN (screen);
501 
502   window = g_object_new (WNCK_TYPE_WINDOW, NULL);
503   window->priv->xwindow = xwindow;
504   window->priv->screen = screen;
505 
506   g_hash_table_insert (window_hash, &window->priv->xwindow, window);
507 
508   /* Hash now owns one ref, caller gets none */
509 
510   /* Note that xwindow may correspond to a WnckApplication's xwindow,
511    * that's why we select the union of the mask we want for Application
512    * and the one we want for window
513    */
514   window->priv->orig_event_mask =_wnck_select_input (xscreen,
515                                                      window->priv->xwindow,
516                                                      WNCK_APP_WINDOW_EVENT_MASK,
517                                                      TRUE);
518 
519   /* Default the group leader to the window itself; it is set in
520    * update_wmhints() if a different group leader is specified.
521    */
522   window->priv->group_leader = window->priv->xwindow;
523 
524   window->priv->session_id =
525     _wnck_get_session_id (xscreen, window->priv->xwindow);
526 
527   window->priv->pid =
528     _wnck_get_pid (xscreen, window->priv->xwindow);
529 
530   window->priv->x = 0;
531   window->priv->y = 0;
532   window->priv->width = 0;
533   window->priv->height = 0;
534   _wnck_get_window_geometry (xscreen,
535 			     xwindow,
536                              &window->priv->x,
537                              &window->priv->y,
538                              &window->priv->width,
539                              &window->priv->height);
540 
541   window->priv->sort_order = sort_order;
542 
543   window->priv->need_update_name = TRUE;
544   window->priv->need_update_state = TRUE;
545   window->priv->need_update_icon_name = TRUE;
546   window->priv->need_update_wm_state = TRUE;
547   window->priv->need_update_workspace = TRUE;
548   window->priv->need_update_actions = TRUE;
549   window->priv->need_update_wintype = TRUE;
550   window->priv->need_update_transient_for = TRUE;
551   window->priv->need_update_startup_id = TRUE;
552   window->priv->need_update_wmclass = TRUE;
553   window->priv->need_update_wmhints = TRUE;
554   window->priv->need_update_frame_extents = TRUE;
555   window->priv->need_update_role = TRUE;
556   window->priv->need_emit_name_changed = FALSE;
557   window->priv->need_emit_icon_changed = FALSE;
558   window->priv->need_emit_class_changed = FALSE;
559   window->priv->need_emit_role_changed = FALSE;
560   window->priv->need_emit_type_changed = FALSE;
561   force_update_now (window);
562 
563   return window;
564 }
565 
566 void
_wnck_window_destroy(WnckWindow * window)567 _wnck_window_destroy (WnckWindow *window)
568 {
569   Window xwindow = window->priv->xwindow;
570 
571   g_return_if_fail (WNCK_IS_WINDOW (window));
572 
573   g_return_if_fail (wnck_window_get (xwindow) == window);
574 
575   g_hash_table_remove (window_hash, &xwindow);
576 
577   /* Removing from hash also removes the only ref WnckWindow had */
578 
579   g_return_if_fail (wnck_window_get (xwindow) == NULL);
580 }
581 
582 static Display *
_wnck_window_get_display(WnckWindow * window)583 _wnck_window_get_display (WnckWindow *window)
584 {
585   return DisplayOfScreen (WNCK_SCREEN_XSCREEN (window->priv->screen));
586 }
587 
588 /**
589  * wnck_window_has_name:
590  * @window: a #WnckWindow.
591  *
592  * Checks whether or not @window has a name. wnck_window_get_name()
593  * will always return some value, even if @window has no name set;
594  * wnck_window_has_name() can be used to tell if that name is
595  * real or not.
596  *
597  * For icons titles, use wnck_window_has_icon_name() instead.
598  *
599  * Return value: %TRUE if wnck_window_get_name() returns @window<!-- -->'s
600  * name, %FALSE if it returns a fallback name.
601  *
602  * Since: 2.16
603  **/
604 gboolean
wnck_window_has_name(WnckWindow * window)605 wnck_window_has_name (WnckWindow *window)
606 {
607   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
608 
609   return window->priv->name != NULL;
610 }
611 
612 /**
613  * wnck_window_get_name:
614  * @window: a #WnckWindow.
615  *
616  * Gets the name of @window, as it should be displayed in a pager
617  * or tasklist. Always returns some value, even if @window has no name
618  * set; use wnck_window_has_name() if you need to know whether the returned
619  * name is "real" or not.
620  *
621  * For icons titles, use wnck_window_get_icon_name() instead.
622  *
623  * Return value: the name of @window, or a fallback name if no name is
624  * available.
625  **/
626 const char*
wnck_window_get_name(WnckWindow * window)627 wnck_window_get_name (WnckWindow *window)
628 {
629   g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
630 
631   if (window->priv->name)
632     return window->priv->name;
633   else
634     return FALLBACK_NAME;
635 }
636 
637 /**
638  * wnck_window_has_icon_name:
639  * @window: a #WnckWindow
640  *
641  * Checks whether or not @window has an icon name.
642  * wnck_window_get_icon_name() will always return some value, even if
643  * @window has no icon name set; wnck_window_has_icon_name() can
644  * be used to tell if that icon name is real or not.
645  *
646  * (Note that if wnck_window_has_icon_name() returns %FALSE, but
647  * wnck_window_has_name() returns %TRUE, then the name returned by
648  * wnck_window_get_icon_name() is @window<!-- -->'s name. Only when both
649  * methods return %FALSE does wnck_window_get_icon_name() return a
650  * generic fallback name.)
651  *
652  * Return value: %TRUE if wnck_window_get_icon_name() returns
653  * @window<!-- -->'s icon name, %FALSE if it returns a fallback name.
654  *
655  * Since: 2.16
656  **/
657 gboolean
wnck_window_has_icon_name(WnckWindow * window)658 wnck_window_has_icon_name (WnckWindow *window)
659 {
660   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
661 
662   return window->priv->icon_name != NULL;
663 }
664 
665 /**
666  * wnck_window_get_icon_name:
667  * @window: a #WnckWindow
668  *
669  * Gets the icon name of @window, as it should be displayed for an icon
670  * (minimized state). Always returns some value, even if @window has no icon
671  * name set; use wnck_window_has_icon_name() if you need to know whether the
672  * returned icon name is "real" or not.
673  *
674  * Contrast with wnck_window_get_name(), which returns @window<!-- -->'s
675  * title, not its icon title.
676  *
677  * Return value: the icon name of @window, or a fallback icon name if no icon
678  * name is available.
679  **/
680 const char*
wnck_window_get_icon_name(WnckWindow * window)681 wnck_window_get_icon_name (WnckWindow *window)
682 {
683   g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
684 
685   if (window->priv->icon_name)
686     return window->priv->icon_name;
687   else if (window->priv->name)
688     return window->priv->name;
689   else
690     return FALLBACK_NAME;
691 }
692 
693 char *
_wnck_window_get_name_for_display(WnckWindow * window,gboolean use_icon_name,gboolean use_state_decorations)694 _wnck_window_get_name_for_display (WnckWindow *window,
695                                    gboolean    use_icon_name,
696                                    gboolean    use_state_decorations)
697 {
698   const char *name;
699 
700   g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
701 
702   if (use_icon_name && wnck_window_has_icon_name (window))
703     name = wnck_window_get_icon_name (window);
704   else
705     name = wnck_window_get_name (window);
706 
707   if (use_state_decorations)
708     {
709       if (window->priv->is_shaded)
710         return g_strdup_printf ("=%s=", name);
711       else if (window->priv->is_minimized)
712         return g_strdup_printf ("[%s]", name);
713       else
714         return g_strdup (name);
715     }
716   else
717     return g_strdup (name);
718 }
719 
720 
721 /**
722  * wnck_window_get_application:
723  * @window: a #WnckWindow.
724  *
725  * Gets the #WnckApplication to which @window belongs.
726  *
727  * Return value: (transfer none): the #WnckApplication to which @window belongs.
728  * The returned #WnckApplication is owned by libwnck and must not be referenced
729  * or unreferenced.
730  **/
731 WnckApplication*
wnck_window_get_application(WnckWindow * window)732 wnck_window_get_application  (WnckWindow *window)
733 {
734   g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
735 
736   return window->priv->app;
737 }
738 
739 /**
740  * wnck_window_get_transient:
741  * @window: a #WnckWindow.
742  *
743  * Gets the #WnckWindow for which @window is transient.
744  *
745  * Return value: (transfer none): the #WnckWindow for which @window is
746  * transient, or %NULL if @window is not transient for any #WnckWindow.
747  * The returned #WnckWindow is owned by libwnck and must not be referenced or
748  * unreferenced.
749  *
750  * Since: 2.12
751  **/
752 WnckWindow*
wnck_window_get_transient(WnckWindow * window)753 wnck_window_get_transient (WnckWindow *window)
754 {
755   g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
756 
757   return wnck_window_get (window->priv->transient_for);
758 }
759 
760 /**
761  * wnck_window_get_group_leader:
762  * @window: a #WnckWindow.
763  *
764  * Gets the group leader of the group of windows to which @window belongs.
765  *
766  * Return value: the group leader of the group of windows to which @window
767  * belongs, or the X window ID of @window if @window does not belong to any
768  * group.
769  **/
770 gulong
wnck_window_get_group_leader(WnckWindow * window)771 wnck_window_get_group_leader (WnckWindow *window)
772 {
773   g_return_val_if_fail (WNCK_IS_WINDOW (window), None);
774 
775   return window->priv->group_leader;
776 }
777 
778 /**
779  * wnck_window_get_xid:
780  * @window: a #WnckWindow.
781  *
782  * Gets the X window ID of @window.
783  *
784  * Return value: the X window ID of @window.
785  **/
786 gulong
wnck_window_get_xid(WnckWindow * window)787 wnck_window_get_xid (WnckWindow *window)
788 {
789   g_return_val_if_fail (WNCK_IS_WINDOW (window), None);
790 
791   return window->priv->xwindow;
792 }
793 
794 /**
795  * wnck_window_get_class_group:
796  * @window: a #WnckWindow.
797  *
798  * Gets the #WnckClassGroup to which @window belongs.
799  *
800  * Return value: (transfer none): the #WnckClassGroup to which @window belongs.
801  * The returned #WnckClassGroup is owned by libwnck and must not be referenced
802  * or unreferenced.
803  *
804  * Since: 2.2
805  **/
806 WnckClassGroup *
wnck_window_get_class_group(WnckWindow * window)807 wnck_window_get_class_group (WnckWindow *window)
808 {
809   g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
810 
811   return window->priv->class_group;
812 }
813 
814 /**
815  * wnck_window_get_session_id:
816  * @window: a #WnckWindow.
817  *
818  * Gets the session ID for @window in Latin-1 encoding.
819  * NOTE: this is invalid UTF-8. You can't display this
820  * string in a GTK+ widget without converting to UTF-8.
821  * See wnck_window_get_session_id_utf8().
822  *
823  * Return value: the session ID for @window in Latin-1, or %NULL if @window has
824  * no session ID.
825  **/
826 const char*
wnck_window_get_session_id(WnckWindow * window)827 wnck_window_get_session_id (WnckWindow *window)
828 {
829   g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
830 
831   return window->priv->session_id;
832 }
833 
834 /**
835  * wnck_window_get_session_id_utf8:
836  * @window: a #WnckWindow.
837  *
838  * Gets the session ID for @window in UTF-8 encoding.
839  * The session ID should be in Latin-1 encoding, so the conversion should work,
840  * but a broken client could set a session ID that might not be convertable to
841  * UTF-8.
842  *
843  * Return value: the session ID for @window in UTF-8, or %NULL if @window has
844  * no session ID.
845  **/
846 const char*
wnck_window_get_session_id_utf8(WnckWindow * window)847 wnck_window_get_session_id_utf8 (WnckWindow *window)
848 {
849   g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
850 
851   if (window->priv->session_id_utf8 == NULL &&
852       window->priv->session_id != NULL)
853     {
854       GString *str;
855       char *p;
856 
857       str = g_string_new ("");
858 
859       p = window->priv->session_id;
860       while (*p)
861         {
862           g_string_append_unichar (str, g_utf8_get_char (p));
863           p = g_utf8_next_char (p);
864         }
865 
866       window->priv->session_id_utf8 = g_string_free (str, FALSE);
867     }
868 
869   return window->priv->session_id_utf8;
870 }
871 
872 /**
873  * wnck_window_get_role:
874  * @window: a #WnckWindow.
875  *
876  * Gets the role for @window.
877  * The role uniquely identifies a window among all windows that have the same
878  * client leader window.
879  *
880  * Return value: role for @window, or %NULL if @window has no role.
881  **/
882 const char*
wnck_window_get_role(WnckWindow * window)883 wnck_window_get_role (WnckWindow *window)
884 {
885   g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
886 
887   return window->priv->role;
888 }
889 
890 /**
891  * wnck_window_get_pid:
892  * @window: a #WnckWindow.
893  *
894  * Gets the process ID of @window.
895  *
896  * Return value: the process ID of @window, or 0 if none is available.
897  **/
898 int
wnck_window_get_pid(WnckWindow * window)899 wnck_window_get_pid (WnckWindow *window)
900 {
901   g_return_val_if_fail (WNCK_IS_WINDOW (window), 0);
902 
903   return window->priv->pid;
904 }
905 
906 /**
907  * wnck_window_get_sort_order:
908  * @window: a #WnckWindow.
909  *
910  * Gets the sort order of @window, used for ordering of @window in
911  * #WnckSelector and #WnckTasklist. The sort order is an internal state in
912  * libwnck. The initial value is defined when the window is created.
913  *
914  * Return value: the sort order of @window, or G_MAXINT if none is available.
915  *
916  * Since: 2.10
917  **/
918 gint
wnck_window_get_sort_order(WnckWindow * window)919 wnck_window_get_sort_order (WnckWindow *window)
920 {
921   g_return_val_if_fail (WNCK_IS_WINDOW (window), G_MAXINT);
922 
923   return window->priv->sort_order;
924 }
925 
926 /**
927  * wnck_window_set_sort_order:
928  * @window: a #WnckWindow.
929  * @order: new sort order for @window.
930  *
931  * Sets the sort order of @window. The sort order is used for ordering of
932  * @window in #WnckSelector and #WnckTasklist.
933  *
934  * Since: 2.20
935  **/
wnck_window_set_sort_order(WnckWindow * window,gint order)936 void        wnck_window_set_sort_order        (WnckWindow *window,
937 					       gint order)
938 {
939   g_return_if_fail (WNCK_IS_WINDOW (window));
940 
941   window->priv->sort_order = order;
942   return;
943 }
944 
945 /**
946  * wnck_window_get_window_type:
947  * @window: a #WnckWindow.
948  *
949  * Gets the semantic type of @window.
950  *
951  * Return value: the semantic type of @window.
952  **/
953 WnckWindowType
wnck_window_get_window_type(WnckWindow * window)954 wnck_window_get_window_type (WnckWindow *window)
955 {
956   /* FIXME: should we have an invalid window type for this? */
957   g_return_val_if_fail (WNCK_IS_WINDOW (window), 0);
958 
959   return window->priv->wintype;
960 }
961 
962 /**
963  * wnck_window_set_window_type:
964  * @window: a #WnckWindow.
965  * @wintype: a semantic type.
966  *
967  * Sets the semantic type of @window to @wintype.
968  *
969  * Since: 2.12
970  **/
971 void
wnck_window_set_window_type(WnckWindow * window,WnckWindowType wintype)972 wnck_window_set_window_type (WnckWindow *window, WnckWindowType wintype)
973 {
974   Atom atom;
975   Display *display;
976 
977   g_return_if_fail (WNCK_IS_WINDOW (window));
978 
979   switch (wintype) {
980   case WNCK_WINDOW_NORMAL:
981     atom = _wnck_atom_get ("_NET_WM_WINDOW_TYPE_NORMAL");
982     break;
983   case WNCK_WINDOW_DESKTOP:
984     atom = _wnck_atom_get ("_NET_WM_WINDOW_TYPE_DESKTOP");
985     break;
986   case WNCK_WINDOW_DOCK:
987     atom = _wnck_atom_get ("_NET_WM_WINDOW_TYPE_DOCK");
988     break;
989   case WNCK_WINDOW_DIALOG:
990     atom = _wnck_atom_get ("_NET_WM_WINDOW_TYPE_DIALOG");
991     break;
992   case WNCK_WINDOW_TOOLBAR:
993     atom = _wnck_atom_get ("_NET_WM_WINDOW_TYPE_TOOLBAR");
994     break;
995   case WNCK_WINDOW_MENU:
996     atom = _wnck_atom_get ("_NET_WM_WINDOW_TYPE_MENU");
997     break;
998   case WNCK_WINDOW_UTILITY:
999     atom = _wnck_atom_get ("_NET_WM_WINDOW_TYPE_UTILITY");
1000     break;
1001   case WNCK_WINDOW_SPLASHSCREEN:
1002     atom = _wnck_atom_get ("_NET_WM_WINDOW_TYPE_SPLASH");
1003     break;
1004   default:
1005     return;
1006   }
1007 
1008   display = _wnck_window_get_display (window);
1009 
1010   _wnck_error_trap_push (display);
1011 
1012   XChangeProperty (display,
1013                    window->priv->xwindow,
1014                    _wnck_atom_get ("_NET_WM_WINDOW_TYPE"),
1015 		   XA_ATOM, 32, PropModeReplace,
1016 		   (guchar *)&atom, 1);
1017 
1018   _wnck_error_trap_pop (display);
1019 
1020   emit_type_changed (window);
1021 }
1022 
1023 /**
1024  * wnck_window_is_minimized:
1025  * @window: a #WnckWindow.
1026  *
1027  * Gets whether @window is minimized. Minimization state may change anytime
1028  * a #WnckWindow::state-changed signal gets emitted.
1029  *
1030  * Return value: %TRUE if @window is minimized, %FALSE otherwise.
1031  **/
1032 gboolean
wnck_window_is_minimized(WnckWindow * window)1033 wnck_window_is_minimized (WnckWindow *window)
1034 {
1035   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
1036 
1037   return window->priv->is_minimized;
1038 }
1039 
1040 /**
1041  * wnck_window_needs_attention:
1042  * @window: a #WnckWindow.
1043  *
1044  * Gets whether @window needs attention. This state may change anytime
1045  * a #WnckWindow::state-changed signal gets emitted.
1046  *
1047  * This state depends on flags such as the demands_attention and is_urgent
1048  * hints.
1049  *
1050  * Return value: %TRUE if @window needs attention, %FALSE otherwise.
1051  *
1052  * Since: 2.12
1053  **/
1054 gboolean
wnck_window_needs_attention(WnckWindow * window)1055 wnck_window_needs_attention (WnckWindow *window)
1056 {
1057   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
1058 
1059   return window->priv->demands_attention || window->priv->is_urgent;
1060 }
1061 
1062 time_t
_wnck_window_get_needs_attention_time(WnckWindow * window)1063 _wnck_window_get_needs_attention_time (WnckWindow *window)
1064 {
1065   g_return_val_if_fail (WNCK_IS_WINDOW (window), 0);
1066 
1067   return window->priv->needs_attention_time;
1068 }
1069 
1070 /* Return whether the transient of @window needs attention */
1071 static WnckWindow *
transient_needs_attention(WnckWindow * window)1072 transient_needs_attention (WnckWindow *window)
1073 {
1074   GList *windows;
1075   WnckWindow *transient;
1076 
1077   if (!WNCK_IS_WINDOW (window))
1078     return NULL;
1079 
1080   windows = wnck_screen_get_windows_stacked (window->priv->screen);
1081 
1082   transient = window;
1083   while ((transient = find_last_transient_for (windows, transient->priv->xwindow)))
1084     {
1085       /* catch transient cycles */
1086       if (transient == window)
1087         return NULL;
1088 
1089       if (wnck_window_needs_attention (transient))
1090         return transient;
1091     }
1092 
1093   return FALSE;
1094 }
1095 
1096 time_t
_wnck_window_or_transient_get_needs_attention_time(WnckWindow * window)1097 _wnck_window_or_transient_get_needs_attention_time (WnckWindow *window)
1098 {
1099   g_return_val_if_fail (WNCK_IS_WINDOW (window), 0);
1100 
1101   if (_wnck_window_get_needs_attention_time (window) == 0)
1102     {
1103       WnckWindow *transient;
1104 
1105       transient = transient_needs_attention (window);
1106       if (transient)
1107         return _wnck_window_get_needs_attention_time (transient);
1108       else
1109         return 0;
1110     }
1111   else
1112     return _wnck_window_get_needs_attention_time (window);
1113 }
1114 
1115 /**
1116  * wnck_window_or_transient_needs_attention:
1117  * @window: a #WnckWindow.
1118  *
1119  * Gets whether @window or one of its transients needs attention. This state
1120  * may change anytime a #WnckWindow::state-changed signal gets emitted.
1121  *
1122  * Return value: %TRUE if @window or one of its transients needs attention,
1123  * %FALSE otherwise.
1124  *
1125  * Since: 2.12
1126  **/
1127 gboolean
wnck_window_or_transient_needs_attention(WnckWindow * window)1128 wnck_window_or_transient_needs_attention (WnckWindow *window)
1129 {
1130   return wnck_window_needs_attention (window) ||
1131          transient_needs_attention (window) != NULL;
1132 }
1133 
1134 /**
1135  * wnck_window_is_maximized_horizontally:
1136  * @window: a #WnckWindow.
1137  *
1138  * Gets whether @window is maximized horizontally. Horizontal maximization
1139  * state may change anytime a #WnckWindow::state-changed signal gets emitted.
1140  *
1141  * Return value: %TRUE if @window is maximized horizontally, %FALSE otherwise.
1142  **/
1143 gboolean
wnck_window_is_maximized_horizontally(WnckWindow * window)1144 wnck_window_is_maximized_horizontally (WnckWindow *window)
1145 {
1146   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
1147 
1148   return window->priv->is_maximized_horz;
1149 }
1150 
1151 /**
1152  * wnck_window_is_maximized_vertically:
1153  * @window: a #WnckWindow.
1154  *
1155  * Gets whether @window is maximized vertically. vertiVal maximization
1156  * state may change anytime a #WnckWindow::state-changed signal gets emitted.
1157  *
1158  * Return value: %TRUE if @window is maximized vertically, %FALSE otherwise.
1159  **/
1160 gboolean
wnck_window_is_maximized_vertically(WnckWindow * window)1161 wnck_window_is_maximized_vertically   (WnckWindow *window)
1162 {
1163   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
1164 
1165   return window->priv->is_maximized_vert;
1166 }
1167 
1168 const char*
_wnck_window_get_startup_id(WnckWindow * window)1169 _wnck_window_get_startup_id (WnckWindow *window)
1170 {
1171   g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
1172 
1173   if (window->priv->startup_id == NULL &&
1174       window->priv->group_leader != None)
1175     {
1176       WnckApplication *app;
1177 
1178       /* Fall back to group leader property */
1179 
1180       app = wnck_application_get (window->priv->group_leader);
1181 
1182       if (app != NULL)
1183         return wnck_application_get_startup_id (app);
1184       else
1185         return NULL;
1186     }
1187 
1188   return window->priv->startup_id;
1189 }
1190 
1191 /**
1192  * wnck_window_get_class_group_name:
1193  * @window: a #WnckWindow.
1194  *
1195  * Gets the class group name from the <ulink
1196  * url="http://tronche.com/gui/x/icccm/sec-4.html&num;WM_CLASS">WM_CLASS Property</ulink>
1197  * for @window.
1198  *
1199  * The class group name is also the identifier name of the #WnckClassGroup to
1200  * which @window belongs.
1201  *
1202  * Return value: the class group name for @window, or %NULL if @window belongs
1203  * to no class group.
1204  **/
1205 const char*
wnck_window_get_class_group_name(WnckWindow * window)1206 wnck_window_get_class_group_name (WnckWindow *window)
1207 {
1208   g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
1209 
1210   return window->priv->res_class;
1211 }
1212 
1213 /**
1214  * wnck_window_get_class_instance_name:
1215  * @window: a #WnckWindow.
1216  *
1217  * Gets the class instance name from the <ulink
1218  * url="http://tronche.com/gui/x/icccm/sec-4.html&num;WM_CLASS">WM_CLASS Property</ulink>
1219  * for @window.
1220  *
1221  * The class instance name allows to differentiate windows belonging to the
1222  * same class group, so that they can use different resources.
1223  *
1224  * Return value: the class instance name for @window, or %NULL if @window has
1225  * no class instance.
1226  **/
1227 const char*
wnck_window_get_class_instance_name(WnckWindow * window)1228 wnck_window_get_class_instance_name (WnckWindow *window)
1229 {
1230   g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
1231 
1232   return window->priv->res_name;
1233 }
1234 
1235 /**
1236  * wnck_window_is_maximized:
1237  * @window: a #WnckWindow.
1238  *
1239  * Gets whether @window is maximized. Maximization state may change
1240  * anytime a #WnckWindow::state-changed signal gets emitted.
1241  *
1242  * As for GDK, "maximized" means both vertically and horizontally. If @window
1243  * is maximized in only one direction, then @window is not considered
1244  * maximized.
1245  *
1246  * Return value: %TRUE if @window is maximized in both directions, %FALSE
1247  * otherwise.
1248  **/
1249 gboolean
wnck_window_is_maximized(WnckWindow * window)1250 wnck_window_is_maximized (WnckWindow *window)
1251 {
1252   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
1253 
1254   return
1255     window->priv->is_maximized_horz &&
1256     window->priv->is_maximized_vert;
1257 }
1258 
1259 /**
1260  * wnck_window_is_shaded:
1261  * @window: a #WnckWindow.
1262  *
1263  * Gets whether @window is shaded. Shade state may change anytime
1264  * a #WnckWindow::state-changed signal gets emitted.
1265  *
1266  * Return value: %TRUE if @window is shaded, %FALSE otherwise.
1267  **/
1268 gboolean
wnck_window_is_shaded(WnckWindow * window)1269 wnck_window_is_shaded                 (WnckWindow *window)
1270 {
1271   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
1272 
1273   return window->priv->is_shaded;
1274 }
1275 
1276 /**
1277  * wnck_window_is_above:
1278  * @window: a #WnckWindow.
1279  *
1280  * Gets whether @window is above other windows. This state may change
1281  * anytime a #WnckWindow::state-changed signal gets emitted.
1282  *
1283  * See wnck_window_make_above() for more details on this state.
1284  *
1285  * Return value: %TRUE if @window is above other windows, %FALSE otherwise.
1286  *
1287  * Since: 2.14
1288  **/
1289 gboolean
wnck_window_is_above(WnckWindow * window)1290 wnck_window_is_above                  (WnckWindow *window)
1291 {
1292   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
1293 
1294   return window->priv->is_above;
1295 }
1296 
1297 /**
1298  * wnck_window_is_below:
1299  * @window: a #WnckWindow.
1300  *
1301  * Gets whether @window is below other windows. This state may change
1302  * anytime a #WnckWindow::state-changed signal gets emitted.
1303  *
1304  * See wnck_window_make_below() for more details on this state.
1305  *
1306  * Return value: %TRUE if @window is below other windows, %FALSE otherwise.
1307  *
1308  * Since: 2.20
1309  **/
1310 gboolean
wnck_window_is_below(WnckWindow * window)1311 wnck_window_is_below                  (WnckWindow *window)
1312 {
1313   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
1314 
1315   return window->priv->is_below;
1316 }
1317 
1318 /**
1319  * wnck_window_is_skip_pager:
1320  * @window: a #WnckWindow.
1321  *
1322  * Gets whether @window is included on pagers. This state may change
1323  * anytime a #WnckWindow::state-changed signal gets emitted.
1324  *
1325  * Return value: %TRUE if @window is included on pagers, %FALSE otherwise.
1326  **/
1327 gboolean
wnck_window_is_skip_pager(WnckWindow * window)1328 wnck_window_is_skip_pager             (WnckWindow *window)
1329 {
1330   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
1331 
1332   return window->priv->skip_pager;
1333 }
1334 
1335 /**
1336  * wnck_window_set_skip_pager:
1337  * @window: a #WnckWindow.
1338  * @skip: whether @window should be included on pagers.
1339  *
1340  * Asks the window manager to make @window included or not included on pagers.
1341  **/
1342 void
wnck_window_set_skip_pager(WnckWindow * window,gboolean skip)1343 wnck_window_set_skip_pager (WnckWindow *window,
1344                             gboolean    skip)
1345 {
1346   g_return_if_fail (WNCK_IS_WINDOW (window));
1347 
1348   _wnck_change_state (window->priv->screen,
1349                       window->priv->xwindow,
1350                       skip,
1351                       _wnck_atom_get ("_NET_WM_STATE_SKIP_PAGER"),
1352                       0);
1353 }
1354 
1355 /**
1356  * wnck_window_is_skip_tasklist:
1357  * @window: a #WnckWindow.
1358  *
1359  * Gets whether @window is included on tasklists. This state may change
1360  * anytime a #WnckWindow::state-changed signal gets emitted.
1361  *
1362  * Return value: %TRUE if @window is included on tasklists, %FALSE otherwise.
1363  **/
1364 gboolean
wnck_window_is_skip_tasklist(WnckWindow * window)1365 wnck_window_is_skip_tasklist          (WnckWindow *window)
1366 {
1367   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
1368 
1369   return window->priv->skip_taskbar;
1370 }
1371 
1372 /**
1373  * wnck_window_is_fullscreen:
1374  * @window: a #WnckWindow.
1375  *
1376  * Gets whether @window is fullscreen. Fullscreen state may change
1377  * anytime a #WnckWindow::state-changed signal gets emitted.
1378  *
1379  * Return value: %TRUE if @window is fullscreen, %FALSE otherwise.
1380  *
1381  * Since: 2.8
1382  **/
1383 gboolean
wnck_window_is_fullscreen(WnckWindow * window)1384 wnck_window_is_fullscreen                 (WnckWindow *window)
1385 {
1386   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
1387 
1388   return window->priv->is_fullscreen;
1389 }
1390 
1391 /**
1392  * wnck_window_set_skip_tasklist:
1393  * @window: a #WnckWindow.
1394  * @skip: whether @window should be included on tasklists.
1395  *
1396  * Asks the window manager to make @window included or not included on
1397  * tasklists.
1398  **/
1399 void
wnck_window_set_skip_tasklist(WnckWindow * window,gboolean skip)1400 wnck_window_set_skip_tasklist (WnckWindow *window,
1401                                gboolean    skip)
1402 {
1403   g_return_if_fail (WNCK_IS_WINDOW (window));
1404 
1405   _wnck_change_state (window->priv->screen,
1406                       window->priv->xwindow,
1407                       skip,
1408                       _wnck_atom_get ("_NET_WM_STATE_SKIP_TASKBAR"),
1409                       0);
1410 }
1411 
1412 /**
1413  * wnck_window_set_fullscreen:
1414  * @window: a #WnckWindow.
1415  * @fullscreen: whether to make @window fullscreen.
1416  *
1417  * Asks the window manager to set the fullscreen state of @window according to
1418  * @fullscreen.
1419  *
1420  * Since: 2.8
1421  **/
1422 void
wnck_window_set_fullscreen(WnckWindow * window,gboolean fullscreen)1423 wnck_window_set_fullscreen (WnckWindow *window,
1424                             gboolean    fullscreen)
1425 {
1426   g_return_if_fail (WNCK_IS_WINDOW (window));
1427 
1428   _wnck_change_state (window->priv->screen,
1429                       window->priv->xwindow,
1430                       fullscreen,
1431                       _wnck_atom_get ("_NET_WM_STATE_FULLSCREEN"),
1432                       0);
1433 }
1434 
1435 /**
1436  * wnck_window_is_sticky:
1437  * @window: a #WnckWindow.
1438  *
1439  * Gets whether @window is sticky. Sticky state may change
1440  * anytime a #WnckWindow::state-changed signal gets emitted.
1441  *
1442  * Sticky here means "stuck to the glass", i.e. does not scroll with the
1443  * viewport. In GDK/GTK+ (e.g. gdk_window_stick()/gtk_window_stick()), sticky
1444  * means "stuck to the glass" and <emphasis>also</emphasis> that the window is
1445  * on all workspaces. But here it only means the viewport aspect of it.
1446  *
1447  * Return value: %TRUE if @window is "stuck to the glass", %FALSE otherwise.
1448  **/
1449 gboolean
wnck_window_is_sticky(WnckWindow * window)1450 wnck_window_is_sticky                 (WnckWindow *window)
1451 {
1452   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
1453 
1454   return window->priv->is_sticky;
1455 }
1456 
1457 /**
1458  * wnck_window_close:
1459  * @window: a #WnckWindow.
1460  * @timestamp: the X server timestamp of the user interaction event that caused
1461  * this call to occur.
1462  *
1463  * Closes @window.
1464  *
1465  * This function existed before 2.6, but the @timestamp argument was missing
1466  * in earlier versions.
1467  *
1468  * Since: 2.6
1469  **/
1470 void
wnck_window_close(WnckWindow * window,guint32 timestamp)1471 wnck_window_close (WnckWindow *window,
1472                    guint32     timestamp)
1473 {
1474   g_return_if_fail (WNCK_IS_WINDOW (window));
1475 
1476   _wnck_close (window->priv->screen, window->priv->xwindow, timestamp);
1477 }
1478 
1479 /**
1480  * wnck_window_minimize:
1481  * @window: a #WnckWindow.
1482  *
1483  * Minimizes @window.
1484  **/
1485 void
wnck_window_minimize(WnckWindow * window)1486 wnck_window_minimize                (WnckWindow *window)
1487 {
1488   g_return_if_fail (WNCK_IS_WINDOW (window));
1489 
1490   _wnck_iconify (WNCK_SCREEN_XSCREEN (window->priv->screen),
1491                  window->priv->xwindow);
1492 }
1493 
1494 /**
1495  * wnck_window_unminimize:
1496  * @window: a #WnckWindow.
1497  * @timestamp: the X server timestamp of the user interaction event that caused
1498  * this call to occur.
1499  *
1500  * Unminimizes @window by activating it or one of its transients. See
1501  * wnck_window_activate_transient() for details on how the activation is done.
1502  **/
1503 void
wnck_window_unminimize(WnckWindow * window,guint32 timestamp)1504 wnck_window_unminimize              (WnckWindow *window,
1505                                      guint32     timestamp)
1506 {
1507   g_return_if_fail (WNCK_IS_WINDOW (window));
1508 
1509   wnck_window_activate_transient (window, timestamp);
1510 }
1511 
1512 /**
1513  * wnck_window_maximize:
1514  * @window: a #WnckWindow.
1515  *
1516  * Asks the window manager to maximize @window.
1517  **/
1518 void
wnck_window_maximize(WnckWindow * window)1519 wnck_window_maximize (WnckWindow *window)
1520 {
1521   g_return_if_fail (WNCK_IS_WINDOW (window));
1522 
1523   _wnck_change_state (window->priv->screen,
1524                       window->priv->xwindow,
1525                       TRUE,
1526                       _wnck_atom_get ("_NET_WM_STATE_MAXIMIZED_VERT"),
1527                       _wnck_atom_get ("_NET_WM_STATE_MAXIMIZED_HORZ"));
1528 }
1529 
1530 /**
1531  * wnck_window_unmaximize:
1532  * @window: a #WnckWindow.
1533  *
1534  * Asks the window manager to unmaximize @window.
1535  **/
1536 void
wnck_window_unmaximize(WnckWindow * window)1537 wnck_window_unmaximize (WnckWindow *window)
1538 {
1539   g_return_if_fail (WNCK_IS_WINDOW (window));
1540 
1541   _wnck_change_state (window->priv->screen,
1542                       window->priv->xwindow,
1543                       FALSE,
1544                       _wnck_atom_get ("_NET_WM_STATE_MAXIMIZED_VERT"),
1545                       _wnck_atom_get ("_NET_WM_STATE_MAXIMIZED_HORZ"));
1546 }
1547 
1548 /**
1549  * wnck_window_maximize_horizontally:
1550  * @window: a #WnckWindow.
1551  *
1552  * Asks the window manager to maximize horizontally @window.
1553  **/
1554 void
wnck_window_maximize_horizontally(WnckWindow * window)1555 wnck_window_maximize_horizontally (WnckWindow *window)
1556 {
1557   g_return_if_fail (WNCK_IS_WINDOW (window));
1558 
1559   _wnck_change_state (window->priv->screen,
1560                       window->priv->xwindow,
1561                       TRUE,
1562                       _wnck_atom_get ("_NET_WM_STATE_MAXIMIZED_HORZ"),
1563                       0);
1564 }
1565 
1566 /**
1567  * wnck_window_unmaximize_horizontally:
1568  * @window: a #WnckWindow.
1569  *
1570  * Asks the window manager to unmaximize horizontally @window.
1571  **/
1572 void
wnck_window_unmaximize_horizontally(WnckWindow * window)1573 wnck_window_unmaximize_horizontally (WnckWindow *window)
1574 {
1575   g_return_if_fail (WNCK_IS_WINDOW (window));
1576 
1577   _wnck_change_state (window->priv->screen,
1578                       window->priv->xwindow,
1579                       FALSE,
1580                       _wnck_atom_get ("_NET_WM_STATE_MAXIMIZED_HORZ"),
1581                       0);
1582 }
1583 
1584 /**
1585  * wnck_window_maximize_vertically:
1586  * @window: a #WnckWindow.
1587  *
1588  * Asks the window manager to maximize vertically @window.
1589  **/
1590 void
wnck_window_maximize_vertically(WnckWindow * window)1591 wnck_window_maximize_vertically (WnckWindow *window)
1592 {
1593   g_return_if_fail (WNCK_IS_WINDOW (window));
1594 
1595   _wnck_change_state (window->priv->screen,
1596                       window->priv->xwindow,
1597                       TRUE,
1598                       _wnck_atom_get ("_NET_WM_STATE_MAXIMIZED_VERT"),
1599                       0);
1600 }
1601 
1602 /**
1603  * wnck_window_unmaximize_vertically:
1604  * @window: a #WnckWindow.
1605  *
1606  * Asks the window manager to unmaximize vertically @window.
1607  **/
1608 void
wnck_window_unmaximize_vertically(WnckWindow * window)1609 wnck_window_unmaximize_vertically (WnckWindow *window)
1610 {
1611   g_return_if_fail (WNCK_IS_WINDOW (window));
1612 
1613   _wnck_change_state (window->priv->screen,
1614                       window->priv->xwindow,
1615                       FALSE,
1616                       _wnck_atom_get ("_NET_WM_STATE_MAXIMIZED_VERT"),
1617                       0);
1618 }
1619 
1620 /**
1621  * wnck_window_shade:
1622  * @window: a #WnckWindow.
1623  *
1624  * Asks the window manager to shade @window.
1625  **/
1626 void
wnck_window_shade(WnckWindow * window)1627 wnck_window_shade (WnckWindow *window)
1628 {
1629   g_return_if_fail (WNCK_IS_WINDOW (window));
1630 
1631   _wnck_change_state (window->priv->screen,
1632                       window->priv->xwindow,
1633                       TRUE,
1634                       _wnck_atom_get ("_NET_WM_STATE_SHADED"),
1635                       0);
1636 }
1637 
1638 /**
1639  * wnck_window_unshade:
1640  * @window: a #WnckWindow.
1641  *
1642  * Asks the window manager to unshade @window.
1643  **/
1644 void
wnck_window_unshade(WnckWindow * window)1645 wnck_window_unshade (WnckWindow *window)
1646 {
1647   g_return_if_fail (WNCK_IS_WINDOW (window));
1648 
1649   _wnck_change_state (window->priv->screen,
1650                       window->priv->xwindow,
1651                       FALSE,
1652                       _wnck_atom_get ("_NET_WM_STATE_SHADED"),
1653                       0);
1654 }
1655 
1656 /**
1657  * wnck_window_make_above:
1658  * @window: a #WnckWindow.
1659  *
1660  * Asks the window manager to put @window on top of most windows (@window will
1661  * not be on top of focused fullscreen windows, of other windows with this
1662  * setting and of dock windows).
1663  *
1664  * Since: 2.14
1665  **/
1666 void
wnck_window_make_above(WnckWindow * window)1667 wnck_window_make_above (WnckWindow *window)
1668 {
1669   g_return_if_fail (WNCK_IS_WINDOW (window));
1670 
1671   _wnck_change_state (window->priv->screen,
1672                       window->priv->xwindow,
1673                       TRUE,
1674                       _wnck_atom_get ("_NET_WM_STATE_ABOVE"),
1675                       0);
1676 }
1677 
1678 /**
1679  * wnck_window_unmake_above:
1680  * @window: a #WnckWindow.
1681  *
1682  * Asks the window manager to not put @window on top of most windows, and to
1683  * put it again in the stack with other windows.
1684  *
1685  * Since: 2.14
1686  **/
1687 void
wnck_window_unmake_above(WnckWindow * window)1688 wnck_window_unmake_above (WnckWindow *window)
1689 {
1690   g_return_if_fail (WNCK_IS_WINDOW (window));
1691 
1692   _wnck_change_state (window->priv->screen,
1693                       window->priv->xwindow,
1694                       FALSE,
1695                       _wnck_atom_get ("_NET_WM_STATE_ABOVE"),
1696                       0);
1697 }
1698 
1699 /**
1700  * wnck_window_make_below:
1701  * @window: a #WnckWindow.
1702  *
1703  * Asks the window manager to put @window below most windows.
1704  *
1705  * Since: 2.20
1706  **/
1707 void
wnck_window_make_below(WnckWindow * window)1708 wnck_window_make_below (WnckWindow *window)
1709 {
1710   g_return_if_fail (WNCK_IS_WINDOW (window));
1711 
1712   _wnck_change_state (window->priv->screen,
1713                       window->priv->xwindow,
1714                       TRUE,
1715                       _wnck_atom_get ("_NET_WM_STATE_BELOW"),
1716                       0);
1717 }
1718 
1719 /**
1720  * wnck_window_unmake_below:
1721  * @window: a #WnckWindow.
1722  *
1723  * Asks the window manager to not put @window below most windows, and to
1724  * put it again in the stack with other windows.
1725  *
1726  * Since: 2.20
1727  **/
1728 void
wnck_window_unmake_below(WnckWindow * window)1729 wnck_window_unmake_below (WnckWindow *window)
1730 {
1731   g_return_if_fail (WNCK_IS_WINDOW (window));
1732 
1733   _wnck_change_state (window->priv->screen,
1734                       window->priv->xwindow,
1735                       FALSE,
1736                       _wnck_atom_get ("_NET_WM_STATE_BELOW"),
1737                       0);
1738 }
1739 
1740 /**
1741  * wnck_window_stick:
1742  * @window: a #WnckWindow.
1743  *
1744  * Asks the window manager to keep the @window<!-- -->'s position fixed on the
1745  * screen, even when the workspace or viewport scrolls.
1746  **/
1747 void
wnck_window_stick(WnckWindow * window)1748 wnck_window_stick (WnckWindow *window)
1749 {
1750   g_return_if_fail (WNCK_IS_WINDOW (window));
1751 
1752   _wnck_change_state (window->priv->screen,
1753                       window->priv->xwindow,
1754                       TRUE,
1755                       _wnck_atom_get ("_NET_WM_STATE_STICKY"),
1756                       0);
1757 }
1758 
1759 /**
1760  * wnck_window_unstick:
1761  * @window: a #WnckWindow.
1762  *
1763  * Asks the window manager to not have @window<!-- -->'s position fixed on the
1764  * screen when the workspace or viewport scrolls.
1765  **/
1766 void
wnck_window_unstick(WnckWindow * window)1767 wnck_window_unstick (WnckWindow *window)
1768 {
1769   g_return_if_fail (WNCK_IS_WINDOW (window));
1770 
1771   _wnck_change_state (window->priv->screen,
1772                       window->priv->xwindow,
1773                       FALSE,
1774                       _wnck_atom_get ("_NET_WM_STATE_STICKY"),
1775                       0);
1776 }
1777 
1778 /**
1779  * wnck_window_keyboard_move:
1780  * @window: a #WnckWindow.
1781  *
1782  * Asks the window manager to start moving @window via the keyboard.
1783  **/
1784 void
wnck_window_keyboard_move(WnckWindow * window)1785 wnck_window_keyboard_move (WnckWindow *window)
1786 {
1787   g_return_if_fail (WNCK_IS_WINDOW (window));
1788 
1789   _wnck_keyboard_move (window->priv->screen,
1790                        window->priv->xwindow);
1791 }
1792 
1793 /**
1794  * wnck_window_keyboard_size:
1795  * @window: a #WnckWindow.
1796  *
1797  * Asks the window manager to start resizing @window via the keyboard.
1798  **/
1799 void
wnck_window_keyboard_size(WnckWindow * window)1800 wnck_window_keyboard_size (WnckWindow *window)
1801 {
1802   g_return_if_fail (WNCK_IS_WINDOW (window));
1803 
1804   _wnck_keyboard_size (window->priv->screen,
1805                        window->priv->xwindow);
1806 }
1807 
1808 /**
1809  * wnck_window_get_workspace:
1810  * @window: a #WnckWindow.
1811  *
1812  * Gets the current workspace @window is on. If the window is pinned (on all
1813  * workspaces), or not on any workspaces, %NULL may be returned.
1814  *
1815  * Return value: (transfer none): the single current workspace @window is on, or
1816  * %NULL. The returned #WnckWorkspace is owned by libwnck and must not be
1817  * referenced or unreferenced.
1818  **/
1819 WnckWorkspace*
wnck_window_get_workspace(WnckWindow * window)1820 wnck_window_get_workspace (WnckWindow *window)
1821 {
1822   g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
1823 
1824   if (window->priv->workspace == ALL_WORKSPACES)
1825     return NULL;
1826   else
1827     return wnck_screen_get_workspace (window->priv->screen, window->priv->workspace);
1828 }
1829 
1830 /**
1831  * wnck_window_move_to_workspace:
1832  * @window: a #WnckWindow.
1833  * @space: a #WnckWorkspace.
1834  *
1835  * Asks the window manager to move @window to @space. If @window was pinned, it
1836  * will also result in @window being visible only on @space.
1837  **/
1838 void
wnck_window_move_to_workspace(WnckWindow * window,WnckWorkspace * space)1839 wnck_window_move_to_workspace (WnckWindow    *window,
1840                                WnckWorkspace *space)
1841 {
1842   g_return_if_fail (WNCK_IS_WINDOW (window));
1843   g_return_if_fail (WNCK_IS_WORKSPACE (space));
1844 
1845   _wnck_change_workspace (window->priv->screen,
1846                           window->priv->xwindow,
1847                           wnck_workspace_get_number (space));
1848 }
1849 
1850 /**
1851  * wnck_window_is_pinned:
1852  * @window: a #WnckWindow.
1853  *
1854  * Gets whether @window is on all workspace. Pinned state may change
1855  * anytime a #WnckWindow::workspace-changed signal gets emitted, but not when
1856  * a #WnckWindow::state-changed gets emitted.
1857  *
1858  * Return value: %TRUE if @window is on all workspaces, %FALSE otherwise.
1859  **/
1860 gboolean
wnck_window_is_pinned(WnckWindow * window)1861 wnck_window_is_pinned (WnckWindow *window)
1862 {
1863   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
1864 
1865   return window->priv->workspace == ALL_WORKSPACES;
1866 }
1867 
1868 /**
1869  * wnck_window_pin:
1870  * @window: a #WnckWindow.
1871  *
1872  * Asks the window manager to put @window on all workspaces.
1873  **/
1874 void
wnck_window_pin(WnckWindow * window)1875 wnck_window_pin (WnckWindow *window)
1876 {
1877   g_return_if_fail (WNCK_IS_WINDOW (window));
1878 
1879   _wnck_change_workspace (window->priv->screen,
1880                           window->priv->xwindow,
1881                           ALL_WORKSPACES);
1882 }
1883 
1884 /**
1885  * wnck_window_unpin:
1886  * @window: a #WnckWindow.
1887  *
1888  * Asks the window manager to put @window only in the currently active
1889  * workspace, if @window was previously pinned. If @window was not pinned,
1890  * does not change @window<!-- -->'s workspace. If the active workspace
1891  * is not known for some reason (it should not happen much), sets
1892  * @window<!-- -->'s workspace to the first workspace.
1893  **/
1894 void
wnck_window_unpin(WnckWindow * window)1895 wnck_window_unpin (WnckWindow *window)
1896 {
1897   WnckWorkspace *active;
1898 
1899   g_return_if_fail (WNCK_IS_WINDOW (window));
1900 
1901   if (window->priv->workspace != ALL_WORKSPACES)
1902     return;
1903 
1904   active = wnck_screen_get_active_workspace (window->priv->screen);
1905 
1906   _wnck_change_workspace (window->priv->screen,
1907                           window->priv->xwindow,
1908                           active ? wnck_workspace_get_number (active) : 0);
1909 }
1910 
1911 /**
1912  * wnck_window_activate:
1913  * @window: a #WnckWindow.
1914  * @timestamp: the X server timestamp of the user interaction event that caused
1915  * this call to occur.
1916  *
1917  * Asks the window manager to make @window the active window. The
1918  * window manager may choose to raise @window along with focusing it, and may
1919  * decide to refuse the request (to not steal the focus if there is a more
1920  * recent user activity, for example).
1921  *
1922  * This function existed before 2.10, but the @timestamp argument was missing
1923  * in earlier versions.
1924  *
1925  * Since: 2.10
1926  **/
1927 void
wnck_window_activate(WnckWindow * window,guint32 timestamp)1928 wnck_window_activate (WnckWindow *window,
1929                       guint32     timestamp)
1930 {
1931   g_return_if_fail (WNCK_IS_WINDOW (window));
1932 
1933   _wnck_activate (window->priv->screen,
1934                   window->priv->xwindow,
1935                   timestamp);
1936 }
1937 
1938 /**
1939  * wnck_window_is_active:
1940  * @window: a #WnckWindow.
1941  *
1942  * Gets whether @window is the active window on its #WnckScreen.
1943  *
1944  * Return value: %TRUE if @window is the active window on its #WnckScreen,
1945  * %FALSE otherwise.
1946  **/
1947 gboolean
wnck_window_is_active(WnckWindow * window)1948 wnck_window_is_active (WnckWindow *window)
1949 {
1950   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
1951 
1952   return window == wnck_screen_get_active_window (window->priv->screen);
1953 }
1954 
1955 /**
1956  * wnck_window_is_most_recently_activated:
1957  * @window: a #WnckWindow.
1958  *
1959  * Gets whether @window is the most recently activated window on its
1960  * #WnckScreen.
1961  *
1962  * The most recently activated window is identical to the active
1963  * window for click and sloppy focus methods (since a window is always
1964  * active in those cases) but differs slightly for mouse focus since
1965  * there often is no active window.
1966  *
1967  * Return value: %TRUE if @window was the most recently activated window on its
1968  * #WnckScreen, %FALSE otherwise.
1969  *
1970  * Since: 2.8
1971  **/
1972 gboolean
wnck_window_is_most_recently_activated(WnckWindow * window)1973 wnck_window_is_most_recently_activated (WnckWindow *window)
1974 {
1975   WnckWindow * current;
1976   WnckWindow * previous;
1977   WnckWindow * most_recently_activated_window;
1978 
1979   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
1980 
1981   current  = wnck_screen_get_active_window (window->priv->screen);
1982   previous = wnck_screen_get_previously_active_window (window->priv->screen);
1983 
1984   if (current)
1985     most_recently_activated_window = current;
1986   else
1987     most_recently_activated_window = previous;
1988 
1989   return (window == most_recently_activated_window);
1990 }
1991 
1992 static WnckWindow*
find_last_transient_for(GList * windows,Window xwindow)1993 find_last_transient_for (GList *windows,
1994                          Window xwindow)
1995 {
1996   GList *tmp;
1997   WnckWindow *retval;
1998 
1999   /* find _last_ transient for xwindow in the list */
2000 
2001   retval = NULL;
2002 
2003   tmp = windows;
2004   while (tmp != NULL)
2005     {
2006       WnckWindow *w = tmp->data;
2007 
2008       if (w->priv->transient_for == xwindow &&
2009 	  w->priv->wintype != WNCK_WINDOW_UTILITY)
2010         retval = w;
2011 
2012       tmp = tmp->next;
2013     }
2014 
2015   return retval;
2016 }
2017 
2018 /**
2019  * wnck_window_activate_transient:
2020  * @window: a #WnckWindow.
2021  * @timestamp: the X server timestamp of the user interaction event that caused
2022  * this call to occur.
2023  *
2024  * If @window has transients, activates the most likely transient
2025  * instead of the window itself. Otherwise activates @window.
2026  *
2027  * FIXME the ideal behavior of this function is probably to activate
2028  * the most recently active window among @window and its transients.
2029  * This is probably best implemented on the window manager side.
2030  *
2031  * This function existed before 2.10, but the @timestamp argument was missing
2032  * in earlier versions.
2033  *
2034  * Since: 2.10
2035  **/
2036 void
wnck_window_activate_transient(WnckWindow * window,guint32 timestamp)2037 wnck_window_activate_transient (WnckWindow *window,
2038                                 guint32     timestamp)
2039 {
2040   GList *windows;
2041   WnckWindow *transient;
2042   WnckWindow *next;
2043 
2044   g_return_if_fail (WNCK_IS_WINDOW (window));
2045 
2046   windows = wnck_screen_get_windows_stacked (window->priv->screen);
2047 
2048   transient = NULL;
2049   next = find_last_transient_for (windows, window->priv->xwindow);
2050 
2051   while (next != NULL)
2052     {
2053       if (next == window)
2054         {
2055           /* catch transient cycles */
2056           transient = NULL;
2057           break;
2058         }
2059 
2060       transient = next;
2061 
2062       next = find_last_transient_for (windows, transient->priv->xwindow);
2063     }
2064 
2065   if (transient != NULL)
2066     wnck_window_activate (transient, timestamp);
2067   else
2068     wnck_window_activate (window, timestamp);
2069 }
2070 
2071 /**
2072  * wnck_window_transient_is_most_recently_activated:
2073  * @window: a #WnckWindow.
2074  *
2075  * Gets whether one of the transients of @window is the most
2076  * recently activated window. See
2077  * wnck_window_is_most_recently_activated() for a more complete
2078  * description of what is meant by most recently activated.  This
2079  * function is needed because clicking on a #WnckTasklist once will
2080  * activate a transient instead of @window itself
2081  * (wnck_window_activate_transient), and clicking again should
2082  * minimize @window and its transients.  (Not doing this can be
2083  * especially annoying in the case of modal dialogs that don't appear
2084  * in the #WnckTasklist).
2085  *
2086  * Return value: %TRUE if one of the transients of @window is the most recently
2087  * activated window, %FALSE otherwise.
2088  *
2089  * Since: 2.12
2090  **/
2091 gboolean
wnck_window_transient_is_most_recently_activated(WnckWindow * window)2092 wnck_window_transient_is_most_recently_activated (WnckWindow *window)
2093 {
2094   GList *windows;
2095   WnckWindow *transient;
2096 
2097   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
2098 
2099   windows = wnck_screen_get_windows_stacked (window->priv->screen);
2100 
2101   transient = window;
2102   while ((transient = find_last_transient_for (windows, transient->priv->xwindow)))
2103     {
2104       /* catch transient cycles */
2105       if (transient == window)
2106         return FALSE;
2107 
2108       if (wnck_window_is_most_recently_activated (transient))
2109         return TRUE;
2110     }
2111 
2112   return FALSE;
2113 }
2114 
2115 static void
get_icons(WnckWindow * window)2116 get_icons (WnckWindow *window)
2117 {
2118   GdkPixbuf *icon;
2119   GdkPixbuf *mini_icon;
2120   gsize normal_size;
2121   gsize mini_size;
2122 
2123   icon = NULL;
2124   mini_icon = NULL;
2125   normal_size = _wnck_get_default_icon_size ();
2126   mini_size = _wnck_get_default_mini_icon_size ();
2127 
2128   if (_wnck_read_icons (window->priv->screen,
2129                         window->priv->xwindow,
2130                         window->priv->icon_cache,
2131                         &icon, normal_size, normal_size,
2132                         &mini_icon, mini_size, mini_size))
2133     {
2134       window->priv->need_emit_icon_changed = TRUE;
2135 
2136       if (window->priv->icon)
2137         g_object_unref (G_OBJECT (window->priv->icon));
2138 
2139       if (window->priv->mini_icon)
2140         g_object_unref (G_OBJECT (window->priv->mini_icon));
2141 
2142       window->priv->icon = icon;
2143       window->priv->mini_icon = mini_icon;
2144     }
2145 
2146   g_assert ((window->priv->icon && window->priv->mini_icon) ||
2147             !(window->priv->icon || window->priv->mini_icon));
2148 }
2149 
2150 void
_wnck_window_load_icons(WnckWindow * window)2151 _wnck_window_load_icons (WnckWindow *window)
2152 {
2153   g_return_if_fail (WNCK_IS_WINDOW (window));
2154 
2155   get_icons (window);
2156   if (window->priv->need_emit_icon_changed)
2157     queue_update (window); /* not done in get_icons since we call that from
2158                             * the update
2159                             */
2160 }
2161 
2162 /**
2163  * wnck_window_get_icon:
2164  * @window: a #WnckWindow.
2165  *
2166  * Gets the icon to be used for @window. If no icon was found, a fallback
2167  * icon is used. wnck_window_get_icon_is_fallback() can be used to tell if the
2168  * icon is the fallback icon.
2169  *
2170  * Return value: (transfer none): the icon for @window. The caller should
2171  * reference the returned <classname>GdkPixbuf</classname> if it needs to keep
2172  * the icon around.
2173  **/
2174 GdkPixbuf*
wnck_window_get_icon(WnckWindow * window)2175 wnck_window_get_icon (WnckWindow *window)
2176 {
2177   g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
2178 
2179   _wnck_window_load_icons (window);
2180 
2181   return window->priv->icon;
2182 }
2183 
2184 /**
2185  * wnck_window_get_mini_icon:
2186  * @window: a #WnckWindow.
2187  *
2188  * Gets the mini-icon to be used for @window. If no mini-icon was found, a
2189  * fallback mini-icon is used. wnck_window_get_icon_is_fallback() can be used
2190  * to tell if the mini-icon is the fallback mini-icon.
2191  *
2192  * Return value: (transfer none): the mini-icon for @window. The caller should
2193  * reference the returned <classname>GdkPixbuf</classname> if it needs to keep
2194  * the icon around.
2195  **/
2196 GdkPixbuf*
wnck_window_get_mini_icon(WnckWindow * window)2197 wnck_window_get_mini_icon (WnckWindow *window)
2198 {
2199   g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
2200 
2201   _wnck_window_load_icons (window);
2202 
2203   return window->priv->mini_icon;
2204 }
2205 
2206 /**
2207  * wnck_window_get_icon_is_fallback:
2208  * @window: a #WnckWindow.
2209  *
2210  * Gets whether a default fallback icon is used for @window (because none
2211  * was set on @window).
2212  *
2213  * Return value: %TRUE if the icon for @window is a fallback, %FALSE otherwise.
2214  **/
2215 gboolean
wnck_window_get_icon_is_fallback(WnckWindow * window)2216 wnck_window_get_icon_is_fallback (WnckWindow *window)
2217 {
2218   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
2219 
2220   return _wnck_icon_cache_get_is_fallback (window->priv->icon_cache);
2221 }
2222 
2223 /**
2224  * wnck_window_get_actions:
2225  * @window: a #WnckWindow.
2226  *
2227  * Gets the actions that can be done for @window.
2228  *
2229  * Return value: bitmask of actions that can be done for @window.
2230  **/
2231 WnckWindowActions
wnck_window_get_actions(WnckWindow * window)2232 wnck_window_get_actions (WnckWindow *window)
2233 {
2234   g_return_val_if_fail (WNCK_IS_WINDOW (window), 0);
2235 
2236   return window->priv->actions;
2237 }
2238 
2239 
2240 /**
2241  * wnck_window_get_state:
2242  * @window: a #WnckWindow.
2243  *
2244  * Gets the state of @window.
2245  *
2246  * Return value: bitmask of active states for @window.
2247  **/
2248 WnckWindowState
wnck_window_get_state(WnckWindow * window)2249 wnck_window_get_state (WnckWindow *window)
2250 {
2251   g_return_val_if_fail (WNCK_IS_WINDOW (window), 0);
2252 
2253   return COMPRESS_STATE (window);
2254 }
2255 
2256 /**
2257  * wnck_window_get_client_window_geometry:
2258  * @window: a #WnckWindow.
2259  * @xp: (out): return location for X coordinate in pixels of @window.
2260  * @yp: (out): return location for Y coordinate in pixels of @window.
2261  * @widthp: (out): return location for width in pixels of @window.
2262  * @heightp: (out): return location for height in pixels of @window.
2263  *
2264  * Gets the size and position of @window, as last received
2265  * in a ConfigureNotify event (i.e. this call does not round-trip
2266  * to the server, just gets the last size we were notified of).
2267  * The X and Y coordinates are relative to the root window.
2268  *
2269  * The window manager usually adds a frame around windows. If
2270  * you need to know the size of @window with the frame, use
2271  * wnck_window_get_geometry().
2272  *
2273  * Since: 2.20
2274  **/
2275 void
wnck_window_get_client_window_geometry(WnckWindow * window,int * xp,int * yp,int * widthp,int * heightp)2276 wnck_window_get_client_window_geometry (WnckWindow *window,
2277                                         int        *xp,
2278 					int        *yp,
2279 					int        *widthp,
2280 					int        *heightp)
2281 {
2282   g_return_if_fail (WNCK_IS_WINDOW (window));
2283 
2284   if (xp)
2285     *xp = window->priv->x;
2286   if (yp)
2287     *yp = window->priv->y;
2288   if (widthp)
2289     *widthp = window->priv->width;
2290   if (heightp)
2291     *heightp = window->priv->height;
2292 }
2293 
2294 /**
2295  * wnck_window_get_geometry:
2296  * @window: a #WnckWindow.
2297  * @xp: (out): return location for X coordinate in pixels of @window.
2298  * @yp: (out): return location for Y coordinate in pixels of @window.
2299  * @widthp: (out): return location for width in pixels of @window.
2300  * @heightp: (out): return location for height in pixels of @window.
2301  *
2302  * Gets the size and position of @window, including decorations. This
2303  * function uses the information last received in a ConfigureNotify
2304  * event and adjusts it according to the size of the frame that is
2305  * added by the window manager (this call does not round-trip to the
2306  * server, it just gets the last sizes that were notified). The
2307  * X and Y coordinates are relative to the root window.
2308  *
2309  * If you need to know the actual size of @window ignoring the frame
2310  * added by the window manager, use wnck_window_get_client_window_geometry().
2311  **/
2312 void
wnck_window_get_geometry(WnckWindow * window,int * xp,int * yp,int * widthp,int * heightp)2313 wnck_window_get_geometry (WnckWindow *window,
2314                           int        *xp,
2315                           int        *yp,
2316                           int        *widthp,
2317                           int        *heightp)
2318 {
2319   g_return_if_fail (WNCK_IS_WINDOW (window));
2320 
2321   if (xp)
2322     *xp = window->priv->x - window->priv->left_frame;
2323   if (yp)
2324     *yp = window->priv->y - window->priv->top_frame;
2325   if (widthp)
2326     *widthp = window->priv->width + window->priv->left_frame + window->priv->right_frame;
2327   if (heightp)
2328     *heightp = window->priv->height + window->priv->top_frame + window->priv->bottom_frame;
2329 }
2330 
2331 /**
2332  * wnck_window_set_geometry:
2333  * @window: a #WnckWindow.
2334  * @gravity: the gravity point to use as a reference for the new position.
2335  * @geometry_mask: a bitmask containing flags for what should be set.
2336  * @x: new X coordinate in pixels of @window.
2337  * @y: new Y coordinate in pixels of @window.
2338  * @width: new width in pixels of @window.
2339  * @height: new height in pixels of @window.
2340  *
2341  * Sets the size and position of @window. The X and Y coordinates should be
2342  * relative to the root window.
2343  *
2344  * Note that the new size and position apply to @window with its frame added
2345  * by the window manager. Therefore, using wnck_window_set_geometry() with
2346  * the values returned by wnck_window_get_geometry() should be a no-op, while
2347  * using wnck_window_set_geometry() with the values returned by
2348  * wnck_window_get_client_window_geometry() should reduce the size of @window
2349  * and move it.
2350  *
2351  * Since: 2.16
2352  **/
2353 void
wnck_window_set_geometry(WnckWindow * window,WnckWindowGravity gravity,WnckWindowMoveResizeMask geometry_mask,int x,int y,int width,int height)2354 wnck_window_set_geometry (WnckWindow               *window,
2355                           WnckWindowGravity         gravity,
2356                           WnckWindowMoveResizeMask  geometry_mask,
2357                           int                       x,
2358                           int                       y,
2359                           int                       width,
2360                           int                       height)
2361 {
2362   int gravity_and_flags;
2363   int source;
2364 
2365   g_return_if_fail (WNCK_IS_WINDOW (window));
2366 
2367   source = _wnck_get_client_type();
2368   gravity_and_flags = gravity;
2369   gravity_and_flags |= geometry_mask << 8;
2370   gravity_and_flags |= source << 12;
2371 
2372   x += window->priv->left_frame;
2373   y += window->priv->top_frame;
2374   width -= window->priv->left_frame + window->priv->right_frame;
2375   height -= window->priv->top_frame + window->priv->bottom_frame;
2376 
2377   _wnck_set_window_geometry (WNCK_SCREEN_XSCREEN (window->priv->screen),
2378                              window->priv->xwindow,
2379                              gravity_and_flags, x, y, width, height);
2380 }
2381 
2382 /**
2383  * wnck_window_is_visible_on_workspace:
2384  * @window: a #WnckWindow.
2385  * @workspace: a #WnckWorkspace.
2386  *
2387  * Like wnck_window_is_on_workspace(), but also checks that
2388  * the window is in a visible state (i.e. not minimized or shaded).
2389  *
2390  * Return value: %TRUE if @window appears on @workspace in normal state, %FALSE
2391  * otherwise.
2392  **/
2393 gboolean
wnck_window_is_visible_on_workspace(WnckWindow * window,WnckWorkspace * workspace)2394 wnck_window_is_visible_on_workspace (WnckWindow    *window,
2395                                      WnckWorkspace *workspace)
2396 {
2397   WnckWindowState state;
2398 
2399   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
2400   g_return_val_if_fail (WNCK_IS_WORKSPACE (workspace), FALSE);
2401 
2402   state = wnck_window_get_state (window);
2403 
2404   if (state & WNCK_WINDOW_STATE_HIDDEN)
2405     return FALSE; /* not visible */
2406 
2407   return wnck_window_is_on_workspace (window, workspace);
2408 }
2409 
2410 /**
2411  * wnck_window_set_icon_geometry:
2412  * @window: a #WnckWindow.
2413  * @x: X coordinate in pixels.
2414  * @y: Y coordinate in pixels.
2415  * @width: width in pixels.
2416  * @height: height in pixels.
2417  *
2418  * Sets the icon geometry for @window. A typical use case for this is the
2419  * destination of the minimization animation of @window.
2420  */
2421 void
wnck_window_set_icon_geometry(WnckWindow * window,int x,int y,int width,int height)2422 wnck_window_set_icon_geometry (WnckWindow *window,
2423 			       int         x,
2424 			       int         y,
2425 			       int         width,
2426 			       int         height)
2427 {
2428   g_return_if_fail (WNCK_IS_WINDOW (window));
2429 
2430   if (window->priv->icon_geometry.x == x &&
2431       window->priv->icon_geometry.y == y &&
2432       window->priv->icon_geometry.width == width &&
2433       window->priv->icon_geometry.height == height)
2434     return;
2435 
2436   window->priv->icon_geometry.x = x;
2437   window->priv->icon_geometry.y = y;
2438   window->priv->icon_geometry.width = width;
2439   window->priv->icon_geometry.height = height;
2440 
2441   _wnck_set_icon_geometry (WNCK_SCREEN_XSCREEN (window->priv->screen),
2442                            window->priv->xwindow,
2443                            x, y, width, height);
2444 }
2445 
2446 /**
2447  * wnck_window_is_on_workspace:
2448  * @window: a #WnckWindow.
2449  * @workspace: a #WnckWorkspace.
2450  *
2451  * Gets whether @window appears on @workspace.
2452  *
2453  * Return value: %TRUE if @window appears on @workspace, %FALSE otherwise.
2454  **/
2455 gboolean
wnck_window_is_on_workspace(WnckWindow * window,WnckWorkspace * workspace)2456 wnck_window_is_on_workspace (WnckWindow    *window,
2457                              WnckWorkspace *workspace)
2458 {
2459   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
2460   g_return_val_if_fail (WNCK_IS_WORKSPACE (workspace), FALSE);
2461 
2462   return wnck_window_is_pinned (window) ||
2463     wnck_window_get_workspace (window) == workspace;
2464 }
2465 
2466 /**
2467  * wnck_window_is_in_viewport:
2468  * @window: a #WnckWindow.
2469  * @workspace: a #WnckWorkspace.
2470  *
2471  * Gets %TRUE if @window appears in the current viewport of @workspace.
2472  *
2473  * Return value: %TRUE if @window appears in current viewport of @workspace,
2474  * %FALSE otherwise.
2475  *
2476  * Since: 2.4
2477  **/
2478 gboolean
wnck_window_is_in_viewport(WnckWindow * window,WnckWorkspace * workspace)2479 wnck_window_is_in_viewport (WnckWindow    *window,
2480                             WnckWorkspace *workspace)
2481 {
2482   GdkRectangle window_rect;
2483   GdkRectangle viewport_rect;
2484 
2485   g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE);
2486   g_return_val_if_fail (WNCK_IS_WORKSPACE (workspace), FALSE);
2487 
2488   if (wnck_window_is_pinned (window) )
2489     return TRUE;
2490 
2491   if (wnck_window_get_workspace (window) != workspace)
2492     return FALSE;
2493 
2494   viewport_rect.x = wnck_workspace_get_viewport_x (workspace);
2495   viewport_rect.y = wnck_workspace_get_viewport_y (workspace);
2496   viewport_rect.width = wnck_screen_get_width (window->priv->screen);
2497   viewport_rect.height = wnck_screen_get_height (window->priv->screen);
2498 
2499   window_rect.x = window->priv->x - window->priv->left_frame + viewport_rect.x;
2500   window_rect.y = window->priv->y - window->priv->top_frame + viewport_rect.y;
2501   window_rect.width = window->priv->width + window->priv->left_frame + window->priv->right_frame;
2502   window_rect.height = window->priv->height + window->priv->top_frame + window->priv->bottom_frame;
2503 
2504   return gdk_rectangle_intersect (&viewport_rect, &window_rect, &window_rect);
2505 }
2506 
2507 void
_wnck_window_set_application(WnckWindow * window,WnckApplication * app)2508 _wnck_window_set_application (WnckWindow      *window,
2509                               WnckApplication *app)
2510 {
2511   g_return_if_fail (WNCK_IS_WINDOW (window));
2512   g_return_if_fail (app == NULL || WNCK_IS_APPLICATION (app));
2513 
2514   if (app)
2515     g_object_ref (G_OBJECT (app));
2516   if (window->priv->app)
2517     g_object_unref (G_OBJECT (window->priv->app));
2518   window->priv->app = app;
2519 }
2520 
2521 void
_wnck_window_set_class_group(WnckWindow * window,WnckClassGroup * class_group)2522 _wnck_window_set_class_group (WnckWindow     *window,
2523 			      WnckClassGroup *class_group)
2524 {
2525   g_return_if_fail (WNCK_IS_WINDOW (window));
2526   g_return_if_fail (class_group == NULL || WNCK_IS_CLASS_GROUP (class_group));
2527 
2528   if (class_group)
2529     g_object_ref (G_OBJECT (class_group));
2530   if (window->priv->class_group)
2531     g_object_unref (G_OBJECT (window->priv->class_group));
2532   window->priv->class_group = class_group;
2533 }
2534 
2535 void
_wnck_window_process_property_notify(WnckWindow * window,XEvent * xevent)2536 _wnck_window_process_property_notify (WnckWindow *window,
2537                                       XEvent     *xevent)
2538 {
2539   if (xevent->xproperty.atom ==
2540       _wnck_atom_get ("_NET_WM_STATE"))
2541     {
2542       window->priv->need_update_state = TRUE;
2543       queue_update (window);
2544     }
2545   else if (xevent->xproperty.atom ==
2546       _wnck_atom_get ("WM_STATE"))
2547     {
2548       window->priv->need_update_wm_state = TRUE;
2549       queue_update (window);
2550     }
2551   else if (xevent->xproperty.atom ==
2552            XA_WM_NAME ||
2553            xevent->xproperty.atom ==
2554            _wnck_atom_get ("_NET_WM_NAME") ||
2555            xevent->xproperty.atom ==
2556            _wnck_atom_get ("_NET_WM_VISIBLE_NAME"))
2557     {
2558       window->priv->need_update_name = TRUE;
2559       queue_update (window);
2560     }
2561   else if (xevent->xproperty.atom ==
2562            XA_WM_ICON_NAME ||
2563            xevent->xproperty.atom ==
2564            _wnck_atom_get ("_NET_WM_ICON_NAME") ||
2565            xevent->xproperty.atom ==
2566            _wnck_atom_get ("_NET_WM_VISIBLE_ICON_NAME"))
2567     {
2568       window->priv->need_update_icon_name = TRUE;
2569       queue_update (window);
2570     }
2571   else if (xevent->xproperty.atom ==
2572            _wnck_atom_get ("_NET_WM_ALLOWED_ACTIONS"))
2573     {
2574       window->priv->need_update_actions = TRUE;
2575       queue_update (window);
2576     }
2577   else if (xevent->xproperty.atom ==
2578            _wnck_atom_get ("_NET_WM_DESKTOP"))
2579     {
2580       window->priv->need_update_workspace = TRUE;
2581       queue_update (window);
2582     }
2583   else if (xevent->xproperty.atom ==
2584            _wnck_atom_get ("_NET_WM_WINDOW_TYPE"))
2585     {
2586       window->priv->need_update_wintype = TRUE;
2587       queue_update (window);
2588     }
2589   else if (xevent->xproperty.atom ==
2590            _wnck_atom_get ("WM_TRANSIENT_FOR"))
2591     {
2592       window->priv->need_update_transient_for = TRUE;
2593       window->priv->need_update_wintype = TRUE;
2594       queue_update (window);
2595     }
2596   else if (xevent->xproperty.atom ==
2597            _wnck_atom_get ("_NET_STARTUP_ID"))
2598     {
2599       window->priv->need_update_startup_id = TRUE;
2600       queue_update (window);
2601     }
2602   else if (xevent->xproperty.atom == XA_WM_CLASS)
2603     {
2604       window->priv->need_update_wmclass = TRUE;
2605       queue_update (window);
2606     }
2607   else if (xevent->xproperty.atom ==
2608            _wnck_atom_get ("_NET_WM_ICON") ||
2609            xevent->xproperty.atom ==
2610            _wnck_atom_get ("KWM_WIN_ICON"))
2611     {
2612       _wnck_icon_cache_property_changed (window->priv->icon_cache,
2613                                          xevent->xproperty.atom);
2614       queue_update (window);
2615     }
2616   else if (xevent->xproperty.atom ==
2617   	   _wnck_atom_get ("WM_HINTS"))
2618     {
2619       window->priv->need_update_wmhints = TRUE;
2620       queue_update (window);
2621     }
2622   else if (xevent->xproperty.atom ==
2623            _wnck_atom_get ("_NET_FRAME_EXTENTS") ||
2624            xevent->xproperty.atom ==
2625            _wnck_atom_get ("_GTK_FRAME_EXTENTS"))
2626     {
2627       window->priv->need_update_frame_extents = TRUE;
2628       queue_update (window);
2629     }
2630   else if (xevent->xproperty.atom ==
2631            _wnck_atom_get ("WM_WINDOW_ROLE"))
2632     {
2633       window->priv->need_update_role = TRUE;
2634       queue_update (window);
2635     }
2636 }
2637 
2638 void
_wnck_window_process_configure_notify(WnckWindow * window,XEvent * xevent)2639 _wnck_window_process_configure_notify (WnckWindow *window,
2640                                        XEvent     *xevent)
2641 {
2642   if (xevent->xconfigure.send_event)
2643     {
2644       window->priv->x = xevent->xconfigure.x;
2645       window->priv->y = xevent->xconfigure.y;
2646     }
2647   else
2648     {
2649       _wnck_get_window_position (WNCK_SCREEN_XSCREEN (window->priv->screen),
2650 				 window->priv->xwindow,
2651                                  &window->priv->x,
2652                                  &window->priv->y);
2653     }
2654 
2655   window->priv->width = xevent->xconfigure.width;
2656   window->priv->height = xevent->xconfigure.height;
2657 
2658   emit_geometry_changed (window);
2659 }
2660 
2661 static void
update_wm_state(WnckWindow * window)2662 update_wm_state (WnckWindow *window)
2663 {
2664   int state;
2665 
2666   if (!window->priv->need_update_wm_state)
2667     return;
2668 
2669   window->priv->need_update_wm_state = FALSE;
2670 
2671   window->priv->wm_state_iconic = FALSE;
2672 
2673   state = _wnck_get_wm_state (WNCK_SCREEN_XSCREEN (window->priv->screen),
2674                               window->priv->xwindow);
2675 
2676   if (state == IconicState)
2677     window->priv->wm_state_iconic = TRUE;
2678 }
2679 
2680 static void
update_state(WnckWindow * window)2681 update_state (WnckWindow *window)
2682 {
2683   Atom *atoms;
2684   int n_atoms;
2685   int i;
2686   gboolean reread_net_wm_state;
2687 
2688   reread_net_wm_state = window->priv->need_update_state;
2689 
2690   window->priv->need_update_state = FALSE;
2691 
2692   /* This is a bad hack, we always add the
2693    * state based on window type in to the state,
2694    * even if no state update is pending (since the
2695    * state update just means the _NET_WM_STATE prop
2696    * changed
2697    */
2698 
2699   if (reread_net_wm_state)
2700     {
2701       gboolean demanded_attention;
2702 
2703       demanded_attention = window->priv->demands_attention;
2704 
2705       window->priv->is_maximized_horz = FALSE;
2706       window->priv->is_maximized_vert = FALSE;
2707       window->priv->is_sticky = FALSE;
2708       window->priv->is_shaded = FALSE;
2709       window->priv->is_above = FALSE;
2710       window->priv->is_below = FALSE;
2711       window->priv->skip_taskbar = FALSE;
2712       window->priv->skip_pager = FALSE;
2713       window->priv->net_wm_state_hidden = FALSE;
2714       window->priv->is_fullscreen = FALSE;
2715       window->priv->demands_attention = FALSE;
2716 
2717       atoms = NULL;
2718       n_atoms = 0;
2719       _wnck_get_atom_list (WNCK_SCREEN_XSCREEN (window->priv->screen),
2720                            window->priv->xwindow,
2721                            _wnck_atom_get ("_NET_WM_STATE"),
2722                            &atoms, &n_atoms);
2723 
2724       i = 0;
2725       while (i < n_atoms)
2726         {
2727           if (atoms[i] == _wnck_atom_get ("_NET_WM_STATE_MAXIMIZED_VERT"))
2728             window->priv->is_maximized_vert = TRUE;
2729           else if (atoms[i] == _wnck_atom_get ("_NET_WM_STATE_MAXIMIZED_HORZ"))
2730             window->priv->is_maximized_horz = TRUE;
2731           else if (atoms[i] == _wnck_atom_get ("_NET_WM_STATE_HIDDEN"))
2732             window->priv->net_wm_state_hidden = TRUE;
2733           else if (atoms[i] == _wnck_atom_get ("_NET_WM_STATE_STICKY"))
2734             window->priv->is_sticky = TRUE;
2735           else if (atoms[i] == _wnck_atom_get ("_NET_WM_STATE_SHADED"))
2736             window->priv->is_shaded = TRUE;
2737           else if (atoms[i] == _wnck_atom_get ("_NET_WM_STATE_ABOVE"))
2738             window->priv->is_above = TRUE;
2739           else if (atoms[i] == _wnck_atom_get ("_NET_WM_STATE_BELOW"))
2740             window->priv->is_below = TRUE;
2741           else if (atoms[i] == _wnck_atom_get ("_NET_WM_STATE_FULLSCREEN"))
2742             window->priv->is_fullscreen = TRUE;
2743           else if (atoms[i] == _wnck_atom_get ("_NET_WM_STATE_SKIP_TASKBAR"))
2744             window->priv->skip_taskbar = TRUE;
2745           else if (atoms[i] == _wnck_atom_get ("_NET_WM_STATE_SKIP_PAGER"))
2746             window->priv->skip_pager = TRUE;
2747           else if (atoms[i] == _wnck_atom_get ("_NET_WM_STATE_DEMANDS_ATTENTION"))
2748             window->priv->demands_attention = TRUE;
2749 
2750           ++i;
2751         }
2752 
2753       if (window->priv->demands_attention != demanded_attention)
2754         {
2755           if (window->priv->demands_attention)
2756             time (&window->priv->needs_attention_time);
2757           else if (!window->priv->is_urgent)
2758             window->priv->needs_attention_time = 0;
2759         }
2760 
2761       g_free (atoms);
2762     }
2763 
2764   switch (window->priv->wintype)
2765     {
2766     case WNCK_WINDOW_DESKTOP:
2767     case WNCK_WINDOW_DOCK:
2768     case WNCK_WINDOW_SPLASHSCREEN:
2769       window->priv->skip_taskbar = TRUE;
2770       break;
2771 
2772     case WNCK_WINDOW_TOOLBAR:
2773     case WNCK_WINDOW_MENU:
2774     case WNCK_WINDOW_UTILITY:
2775     case WNCK_WINDOW_DIALOG:
2776       /* Skip taskbar if the window is transient
2777        * for some main application window
2778        */
2779       if (wnck_window_get_transient (window) != NULL &&
2780           !window->priv->transient_for_root)
2781         window->priv->skip_taskbar = TRUE;
2782       break;
2783 
2784     case WNCK_WINDOW_NORMAL:
2785     default:
2786       break;
2787     }
2788 
2789   /* FIXME!!!!!!!!!! What in the world is this buggy duplicate of the code
2790    * immediately above this for??!?!?
2791    */
2792   switch (window->priv->wintype)
2793     {
2794     case WNCK_WINDOW_DESKTOP:
2795     case WNCK_WINDOW_DOCK:
2796     case WNCK_WINDOW_TOOLBAR:
2797     case WNCK_WINDOW_MENU:
2798     case WNCK_WINDOW_SPLASHSCREEN:
2799       window->priv->skip_pager = TRUE;
2800       break;
2801 
2802     case WNCK_WINDOW_NORMAL:
2803     case WNCK_WINDOW_DIALOG:
2804     case WNCK_WINDOW_UTILITY:
2805     default:
2806       break;
2807     }
2808 
2809   /* FIXME we need to recompute this if the window manager changes */
2810   if (wnck_screen_net_wm_supports (window->priv->screen,
2811                                    "_NET_WM_STATE_HIDDEN"))
2812     {
2813       window->priv->is_hidden = window->priv->net_wm_state_hidden;
2814 
2815       /* FIXME this is really broken; need to bring it up on
2816        * wm-spec-list. It results in showing an "Unminimize" menu
2817        * item on task list, for shaded windows.
2818        */
2819       window->priv->is_minimized = window->priv->is_hidden;
2820     }
2821   else
2822     {
2823       window->priv->is_minimized = window->priv->wm_state_iconic;
2824 
2825       window->priv->is_hidden = window->priv->is_minimized || window->priv->is_shaded;
2826     }
2827 }
2828 
2829 static void
update_name(WnckWindow * window)2830 update_name (WnckWindow *window)
2831 {
2832   char *new_name;
2833 
2834   if (!window->priv->need_update_name)
2835     return;
2836 
2837   window->priv->need_update_name = FALSE;
2838 
2839   new_name = _wnck_get_name (WNCK_SCREEN_XSCREEN (window->priv->screen),
2840                              window->priv->xwindow);
2841 
2842   if (g_strcmp0 (window->priv->name, new_name) != 0)
2843     window->priv->need_emit_name_changed = TRUE;
2844 
2845   g_free (window->priv->name);
2846   window->priv->name = new_name;
2847 }
2848 
2849 static void
update_icon_name(WnckWindow * window)2850 update_icon_name (WnckWindow *window)
2851 {
2852   char *new_name = NULL;
2853 
2854   if (!window->priv->need_update_icon_name)
2855     return;
2856 
2857   window->priv->need_update_icon_name = FALSE;
2858 
2859   new_name = _wnck_get_icon_name (WNCK_SCREEN_XSCREEN (window->priv->screen),
2860                                   window->priv->xwindow);
2861 
2862   if (g_strcmp0 (window->priv->icon_name, new_name) != 0)
2863     window->priv->need_emit_name_changed = TRUE;
2864 
2865   g_free (window->priv->icon_name);
2866   window->priv->icon_name = new_name;
2867 }
2868 
2869 static void
update_workspace(WnckWindow * window)2870 update_workspace (WnckWindow *window)
2871 {
2872   int val;
2873   int old;
2874 
2875   if (!window->priv->need_update_workspace)
2876     return;
2877 
2878   window->priv->need_update_workspace = FALSE;
2879 
2880   old = window->priv->workspace;
2881 
2882   val = ALL_WORKSPACES;
2883   _wnck_get_cardinal (WNCK_SCREEN_XSCREEN (window->priv->screen),
2884                       window->priv->xwindow,
2885                       _wnck_atom_get ("_NET_WM_DESKTOP"),
2886                       &val);
2887 
2888   window->priv->workspace = val;
2889 
2890   if (old != window->priv->workspace)
2891     emit_workspace_changed (window);
2892 }
2893 
2894 static void
update_actions(WnckWindow * window)2895 update_actions (WnckWindow *window)
2896 {
2897   Atom *atoms;
2898   int   n_atoms;
2899   int   i;
2900 
2901   if (!window->priv->need_update_actions)
2902     return;
2903 
2904   window->priv->need_update_actions = FALSE;
2905 
2906   window->priv->actions = 0;
2907 
2908   atoms = NULL;
2909   n_atoms = 0;
2910   if (!_wnck_get_atom_list (WNCK_SCREEN_XSCREEN (window->priv->screen),
2911                             window->priv->xwindow,
2912                             _wnck_atom_get ("_NET_WM_ALLOWED_ACTIONS"),
2913                             &atoms,
2914                             &n_atoms))
2915     {
2916       window->priv->actions =
2917                 WNCK_WINDOW_ACTION_MOVE                    |
2918                 WNCK_WINDOW_ACTION_RESIZE                  |
2919                 WNCK_WINDOW_ACTION_SHADE                   |
2920                 WNCK_WINDOW_ACTION_STICK                   |
2921                 WNCK_WINDOW_ACTION_MAXIMIZE_HORIZONTALLY   |
2922                 WNCK_WINDOW_ACTION_MAXIMIZE_VERTICALLY     |
2923                 WNCK_WINDOW_ACTION_CHANGE_WORKSPACE        |
2924                 WNCK_WINDOW_ACTION_CLOSE                   |
2925                 WNCK_WINDOW_ACTION_UNMAXIMIZE_HORIZONTALLY |
2926                 WNCK_WINDOW_ACTION_UNMAXIMIZE_VERTICALLY   |
2927                 WNCK_WINDOW_ACTION_UNSHADE                 |
2928                 WNCK_WINDOW_ACTION_UNSTICK                 |
2929                 WNCK_WINDOW_ACTION_MINIMIZE                |
2930                 WNCK_WINDOW_ACTION_UNMINIMIZE              |
2931                 WNCK_WINDOW_ACTION_MAXIMIZE                |
2932                 WNCK_WINDOW_ACTION_UNMAXIMIZE              |
2933                 WNCK_WINDOW_ACTION_FULLSCREEN              |
2934                 WNCK_WINDOW_ACTION_ABOVE                   |
2935                 WNCK_WINDOW_ACTION_BELOW;
2936       return;
2937     }
2938 
2939   i = 0;
2940   while (i < n_atoms)
2941     {
2942       if (atoms[i] == _wnck_atom_get ("_NET_WM_ACTION_MOVE"))
2943         window->priv->actions |= WNCK_WINDOW_ACTION_MOVE;
2944 
2945       else if (atoms[i] == _wnck_atom_get ("_NET_WM_ACTION_RESIZE"))
2946         window->priv->actions |= WNCK_WINDOW_ACTION_RESIZE;
2947 
2948       else if (atoms[i] == _wnck_atom_get ("_NET_WM_ACTION_SHADE"))
2949         window->priv->actions |= WNCK_WINDOW_ACTION_SHADE |
2950                                  WNCK_WINDOW_ACTION_UNSHADE;
2951 
2952       else if (atoms[i] == _wnck_atom_get ("_NET_WM_ACTION_STICK"))
2953         window->priv->actions |= WNCK_WINDOW_ACTION_STICK |
2954                                  WNCK_WINDOW_ACTION_UNSTICK;
2955 
2956       else if (atoms[i] == _wnck_atom_get ("_NET_WM_ACTION_MINIMIZE"))
2957 	window->priv->actions |= WNCK_WINDOW_ACTION_MINIMIZE   |
2958 	                         WNCK_WINDOW_ACTION_UNMINIMIZE;
2959 
2960       else if (atoms[i] == _wnck_atom_get ("_NET_WM_ACTION_MAXIMIZE_HORZ"))
2961         window->priv->actions |= WNCK_WINDOW_ACTION_MAXIMIZE_HORIZONTALLY |
2962                                  WNCK_WINDOW_ACTION_UNMAXIMIZE_HORIZONTALLY;
2963 
2964       else if (atoms[i] == _wnck_atom_get ("_NET_WM_ACTION_MAXIMIZE_VERT"))
2965         window->priv->actions |= WNCK_WINDOW_ACTION_MAXIMIZE_VERTICALLY |
2966                                  WNCK_WINDOW_ACTION_UNMAXIMIZE_VERTICALLY;
2967 
2968       else if (atoms[i] == _wnck_atom_get ("_NET_WM_ACTION_CHANGE_DESKTOP"))
2969         window->priv->actions |= WNCK_WINDOW_ACTION_CHANGE_WORKSPACE;
2970 
2971       else if (atoms[i] == _wnck_atom_get ("_NET_WM_ACTION_CLOSE"))
2972         window->priv->actions |= WNCK_WINDOW_ACTION_CLOSE;
2973 
2974       else if (atoms[i] == _wnck_atom_get ("_NET_WM_ACTION_FULLSCREEN"))
2975         window->priv->actions |= WNCK_WINDOW_ACTION_FULLSCREEN;
2976 
2977       else if (atoms[i] == _wnck_atom_get ("_NET_WM_ACTION_ABOVE"))
2978         window->priv->actions |= WNCK_WINDOW_ACTION_ABOVE;
2979 
2980       else if (atoms[i] == _wnck_atom_get ("_NET_WM_ACTION_BELOW"))
2981         window->priv->actions |= WNCK_WINDOW_ACTION_BELOW;
2982 
2983       else
2984         {
2985           const char *name = _wnck_atom_name (atoms [i]);
2986 
2987           if (name && g_str_has_prefix (name, "_NET_WM_"))
2988             g_warning ("Unhandled action type %s", name);
2989         }
2990 
2991       i++;
2992     }
2993 
2994   g_free (atoms);
2995 
2996   if ((window->priv->actions & WNCK_WINDOW_ACTION_MAXIMIZE_HORIZONTALLY) &&
2997       (window->priv->actions & WNCK_WINDOW_ACTION_MAXIMIZE_VERTICALLY))
2998     window->priv->actions |=
2999         WNCK_WINDOW_ACTION_MAXIMIZE   |
3000         WNCK_WINDOW_ACTION_UNMAXIMIZE;
3001 }
3002 
3003 static void
update_wintype(WnckWindow * window)3004 update_wintype (WnckWindow *window)
3005 {
3006   Atom *atoms;
3007   int n_atoms;
3008   WnckWindowType type;
3009   gboolean found_type;
3010 
3011   if (!window->priv->need_update_wintype)
3012     return;
3013 
3014   window->priv->need_update_wintype = FALSE;
3015 
3016   found_type = FALSE;
3017   type = WNCK_WINDOW_NORMAL;
3018 
3019   atoms = NULL;
3020   n_atoms = 0;
3021   if (_wnck_get_atom_list (WNCK_SCREEN_XSCREEN (window->priv->screen),
3022                            window->priv->xwindow,
3023                            _wnck_atom_get ("_NET_WM_WINDOW_TYPE"),
3024                            &atoms,
3025                            &n_atoms))
3026     {
3027       int i;
3028 
3029       i = 0;
3030       while (i < n_atoms && !found_type)
3031         {
3032           /* We break as soon as we find one we recognize,
3033            * supposed to prefer those near the front of the list
3034            */
3035           found_type = TRUE;
3036           if (atoms[i] == _wnck_atom_get ("_NET_WM_WINDOW_TYPE_DESKTOP"))
3037             type = WNCK_WINDOW_DESKTOP;
3038           else if (atoms[i] == _wnck_atom_get ("_NET_WM_WINDOW_TYPE_DOCK"))
3039             type = WNCK_WINDOW_DOCK;
3040           else if (atoms[i] == _wnck_atom_get ("_NET_WM_WINDOW_TYPE_TOOLBAR"))
3041             type = WNCK_WINDOW_TOOLBAR;
3042           else if (atoms[i] == _wnck_atom_get ("_NET_WM_WINDOW_TYPE_MENU"))
3043             type = WNCK_WINDOW_MENU;
3044           else if (atoms[i] == _wnck_atom_get ("_NET_WM_WINDOW_TYPE_DIALOG"))
3045             type = WNCK_WINDOW_DIALOG;
3046           else if (atoms[i] == _wnck_atom_get ("_NET_WM_WINDOW_TYPE_NORMAL"))
3047             type = WNCK_WINDOW_NORMAL;
3048           else if (atoms[i] == _wnck_atom_get ("_NET_WM_WINDOW_TYPE_UTILITY"))
3049             type = WNCK_WINDOW_UTILITY;
3050           else if (atoms[i] == _wnck_atom_get ("_NET_WM_WINDOW_TYPE_SPLASH"))
3051             type = WNCK_WINDOW_SPLASHSCREEN;
3052           else
3053             found_type = FALSE;
3054 
3055           ++i;
3056         }
3057 
3058       g_free (atoms);
3059     }
3060 
3061   if (!found_type)
3062     {
3063       if (window->priv->transient_for != None)
3064         {
3065           type = WNCK_WINDOW_DIALOG;
3066         }
3067       else
3068         {
3069           type = WNCK_WINDOW_NORMAL;
3070         }
3071       found_type = TRUE;
3072     }
3073 
3074   if (window->priv->wintype != type)
3075     {
3076       window->priv->need_emit_type_changed = TRUE;
3077       window->priv->wintype = type;
3078     }
3079 }
3080 
3081 static void
update_transient_for(WnckWindow * window)3082 update_transient_for (WnckWindow *window)
3083 {
3084   Window parent;
3085 
3086   if (!window->priv->need_update_transient_for)
3087     return;
3088 
3089   window->priv->need_update_transient_for = FALSE;
3090 
3091   parent = None;
3092   if (_wnck_get_window (WNCK_SCREEN_XSCREEN (window->priv->screen),
3093                         window->priv->xwindow,
3094                         _wnck_atom_get ("WM_TRANSIENT_FOR"),
3095                         &parent) &&
3096       parent != window->priv->xwindow)
3097     {
3098       window->priv->transient_for = parent;
3099 
3100       if (wnck_screen_get_for_root (window->priv->transient_for) != NULL)
3101         window->priv->transient_for_root = TRUE;
3102       else
3103         window->priv->transient_for_root = FALSE;
3104     }
3105   else
3106     {
3107       window->priv->transient_for = None;
3108       window->priv->transient_for_root = FALSE;
3109     }
3110 }
3111 
3112 static void
update_startup_id(WnckWindow * window)3113 update_startup_id (WnckWindow *window)
3114 {
3115   if (!window->priv->need_update_startup_id)
3116     return;
3117 
3118   window->priv->need_update_startup_id = FALSE;
3119 
3120   g_free (window->priv->startup_id);
3121   window->priv->startup_id =
3122     _wnck_get_utf8_property (WNCK_SCREEN_XSCREEN (window->priv->screen),
3123                              window->priv->xwindow,
3124                              _wnck_atom_get ("_NET_STARTUP_ID"));
3125 }
3126 
3127 static void
update_wmclass(WnckWindow * window)3128 update_wmclass (WnckWindow *window)
3129 {
3130   char *new_res_class = NULL;
3131   char *new_res_name = NULL;
3132 
3133   if (!window->priv->need_update_wmclass)
3134     return;
3135 
3136   window->priv->need_update_wmclass = FALSE;
3137 
3138   _wnck_get_wmclass (WNCK_SCREEN_XSCREEN (window->priv->screen),
3139                      window->priv->xwindow,
3140                      &new_res_class,
3141                      &new_res_name);
3142 
3143   if (g_strcmp0 (window->priv->res_class, new_res_class) != 0 ||
3144       g_strcmp0 (window->priv->res_name, new_res_name) != 0)
3145     {
3146       window->priv->need_emit_class_changed = TRUE;
3147 
3148       g_free (window->priv->res_class);
3149       g_free (window->priv->res_name);
3150 
3151       window->priv->res_class = new_res_class;
3152       window->priv->res_name = new_res_name;
3153     }
3154   else
3155     {
3156       g_free (new_res_class);
3157       g_free (new_res_name);
3158     }
3159 }
3160 
3161 static void
update_wmhints(WnckWindow * window)3162 update_wmhints (WnckWindow *window)
3163 {
3164   Display  *display;
3165   XWMHints *hints;
3166 
3167   if (!window->priv->need_update_wmhints)
3168     return;
3169 
3170   display = _wnck_window_get_display (window);
3171 
3172   _wnck_error_trap_push (display);
3173   hints = XGetWMHints (display, window->priv->xwindow);
3174   _wnck_error_trap_pop (display);
3175 
3176   if (hints)
3177     {
3178       if ((hints->flags & IconPixmapHint) ||
3179           (hints->flags & IconMaskHint))
3180         _wnck_icon_cache_property_changed (window->priv->icon_cache,
3181                                            _wnck_atom_get ("WM_HINTS"));
3182 
3183       if (hints->flags & WindowGroupHint)
3184           window->priv->group_leader = hints->window_group;
3185 
3186       if (hints->flags & XUrgencyHint)
3187         {
3188           window->priv->is_urgent = TRUE;
3189           time (&window->priv->needs_attention_time);
3190         }
3191       else
3192         {
3193           window->priv->is_urgent = FALSE;
3194           if (!window->priv->demands_attention)
3195             window->priv->needs_attention_time = 0;
3196         }
3197 
3198       XFree (hints);
3199     }
3200 
3201   window->priv->need_update_wmhints = FALSE;
3202 }
3203 
3204 static void
update_frame_extents(WnckWindow * window)3205 update_frame_extents (WnckWindow *window)
3206 {
3207   int left, right, top, bottom;
3208 
3209   if (!window->priv->need_update_frame_extents)
3210     return;
3211 
3212   window->priv->need_update_frame_extents = FALSE;
3213 
3214   left = right = top = bottom = 0;
3215 
3216   if (!_wnck_get_frame_extents (WNCK_SCREEN_XSCREEN (window->priv->screen),
3217                                 window->priv->xwindow,
3218                                 &left, &right, &top, &bottom))
3219     return;
3220 
3221   if (left   != window->priv->left_frame ||
3222       right  != window->priv->right_frame ||
3223       top    != window->priv->top_frame ||
3224       bottom != window->priv->bottom_frame)
3225     {
3226       window->priv->left_frame   = left;
3227       window->priv->right_frame  = right;
3228       window->priv->top_frame    = top;
3229       window->priv->bottom_frame = bottom;
3230 
3231       emit_geometry_changed (window);
3232     }
3233 }
3234 
3235 static void
update_role(WnckWindow * window)3236 update_role (WnckWindow *window)
3237 {
3238   char *new_role;
3239 
3240   if (!window->priv->need_update_role)
3241     return;
3242 
3243   window->priv->need_update_role = FALSE;
3244 
3245   new_role = _wnck_get_text_property (WNCK_SCREEN_XSCREEN (window->priv->screen),
3246                                       window->priv->xwindow,
3247                                       _wnck_atom_get ("WM_WINDOW_ROLE"));
3248 
3249   if (g_strcmp0 (window->priv->role, new_role) != 0)
3250     {
3251       window->priv->need_emit_role_changed = TRUE;
3252 
3253       g_free (window->priv->role);
3254       window->priv->role = new_role;
3255     }
3256   else
3257     {
3258       g_free (new_role);
3259     }
3260 }
3261 
3262 static void
force_update_now(WnckWindow * window)3263 force_update_now (WnckWindow *window)
3264 {
3265   WnckWindowState old_state;
3266   WnckWindowState new_state;
3267   WnckWindowActions old_actions;
3268 
3269   unqueue_update (window);
3270 
3271   /* Name must be done before all other stuff,
3272    * because we have iconsistent state across the
3273    * update_name/update_icon_name functions (no window name),
3274    * and we have to fix that before we emit any other signals
3275    */
3276 
3277   update_name (window);
3278   update_icon_name (window);
3279 
3280   if (window->priv->need_emit_name_changed)
3281     emit_name_changed (window);
3282 
3283   old_state = COMPRESS_STATE (window);
3284   old_actions = window->priv->actions;
3285 
3286   update_startup_id (window);    /* no side effects */
3287   update_wmclass (window);
3288   update_wmhints (window);
3289   update_transient_for (window); /* wintype needs this to be first */
3290   update_wintype (window);   /* emits signals */
3291   update_wm_state (window);
3292   update_state (window);     /* must come after the above, since they affect
3293                               * our calculated state
3294                               */
3295   update_workspace (window); /* emits signals */
3296   update_actions (window);
3297   update_frame_extents (window); /* emits signals */
3298   update_role (window); /* emits signals */
3299 
3300   get_icons (window);
3301 
3302   new_state = COMPRESS_STATE (window);
3303 
3304   if (old_state != new_state)
3305     emit_state_changed (window, old_state ^ new_state, new_state);
3306 
3307   if (old_actions != window->priv->actions)
3308     emit_actions_changed (window, old_actions ^ window->priv->actions,
3309                           window->priv->actions);
3310 
3311   if (window->priv->need_emit_icon_changed)
3312     emit_icon_changed (window);
3313 
3314   if (window->priv->need_emit_class_changed)
3315     emit_class_changed (window);
3316 
3317   if (window->priv->need_emit_role_changed)
3318     emit_role_changed (window);
3319 
3320   if (window->priv->need_emit_type_changed)
3321     emit_type_changed (window);
3322 }
3323 
3324 
3325 static gboolean
update_idle(gpointer data)3326 update_idle (gpointer data)
3327 {
3328   WnckWindow *window = WNCK_WINDOW (data);
3329 
3330   window->priv->update_handler = 0;
3331   force_update_now (window);
3332   return FALSE;
3333 }
3334 
3335 static void
queue_update(WnckWindow * window)3336 queue_update (WnckWindow *window)
3337 {
3338   if (window->priv->update_handler != 0)
3339     return;
3340 
3341   window->priv->update_handler = g_idle_add (update_idle, window);
3342 }
3343 
3344 static void
unqueue_update(WnckWindow * window)3345 unqueue_update (WnckWindow *window)
3346 {
3347   if (window->priv->update_handler != 0)
3348     {
3349       g_source_remove (window->priv->update_handler);
3350       window->priv->update_handler = 0;
3351     }
3352 }
3353 
3354 static void
emit_name_changed(WnckWindow * window)3355 emit_name_changed (WnckWindow *window)
3356 {
3357   window->priv->need_emit_name_changed = FALSE;
3358   g_signal_emit (G_OBJECT (window),
3359                  signals[NAME_CHANGED],
3360                  0);
3361 }
3362 
3363 static void
emit_state_changed(WnckWindow * window,WnckWindowState changed_mask,WnckWindowState new_state)3364 emit_state_changed (WnckWindow     *window,
3365                     WnckWindowState changed_mask,
3366                     WnckWindowState new_state)
3367 {
3368   g_signal_emit (G_OBJECT (window),
3369                  signals[STATE_CHANGED],
3370                  0, changed_mask, new_state);
3371 }
3372 
3373 static void
emit_workspace_changed(WnckWindow * window)3374 emit_workspace_changed (WnckWindow *window)
3375 {
3376   g_signal_emit (G_OBJECT (window),
3377                  signals[WORKSPACE_CHANGED],
3378                  0);
3379 }
3380 
3381 static void
emit_icon_changed(WnckWindow * window)3382 emit_icon_changed (WnckWindow *window)
3383 {
3384   window->priv->need_emit_icon_changed = FALSE;
3385   g_signal_emit (G_OBJECT (window),
3386                  signals[ICON_CHANGED],
3387                  0);
3388 }
3389 
3390 static void
emit_class_changed(WnckWindow * window)3391 emit_class_changed (WnckWindow *window)
3392 {
3393   window->priv->need_emit_class_changed = FALSE;
3394   g_signal_emit (G_OBJECT (window),
3395                  signals[CLASS_CHANGED],
3396                  0);
3397 }
3398 
3399 static void
emit_actions_changed(WnckWindow * window,WnckWindowActions changed_mask,WnckWindowActions new_actions)3400 emit_actions_changed   (WnckWindow       *window,
3401                         WnckWindowActions changed_mask,
3402                         WnckWindowActions new_actions)
3403 {
3404   g_signal_emit (G_OBJECT (window),
3405                  signals[ACTIONS_CHANGED],
3406                  0, changed_mask, new_actions);
3407 }
3408 
3409 static void
emit_geometry_changed(WnckWindow * window)3410 emit_geometry_changed (WnckWindow *window)
3411 {
3412   g_signal_emit (G_OBJECT (window),
3413                  signals[GEOMETRY_CHANGED],
3414                  0);
3415 }
3416 
3417 static void
emit_role_changed(WnckWindow * window)3418 emit_role_changed (WnckWindow *window)
3419 {
3420   window->priv->need_emit_role_changed = FALSE;
3421   g_signal_emit (G_OBJECT (window),
3422                  signals[ROLE_CHANGED],
3423                  0);
3424 }
3425 
3426 static void
emit_type_changed(WnckWindow * window)3427 emit_type_changed (WnckWindow *window)
3428 {
3429   window->priv->need_emit_type_changed = FALSE;
3430   g_signal_emit (G_OBJECT (window),
3431                  signals[TYPE_CHANGED],
3432                  0);
3433 }
3434