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#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#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