Bug Summary

File:_build/../libvnck/tasklist.c
Warning:line 4164, column 10
Although the value stored to 'pos2' is used in the enclosing expression, the value is never actually read from 'pos2'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name tasklist.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/_build -fcoverage-compilation-dir=/rootdir/_build -resource-dir /usr/lib/llvm-19/lib/clang/19 -I libvnck/libvnck-3.so.0.3.0.p -I libvnck -I ../libvnck -I . -I .. -I /usr/include/cairo -I /usr/include/libpng16 -I /usr/include/freetype2 -I /usr/include/pixman-1 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/startup-notification-1.0 -D _FILE_OFFSET_BITS=64 -D G_LOG_DOMAIN="Vnck" -D VNCK_I_KNOW_THIS_IS_UNSTABLE -D VNCK_LOCALEDIR="/usr/local/share/locale" -D VNCK_COMPILATION -D SN_API_NOT_YET_FROZEN=1 -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2025-07-25-113614-9305-1 -x c ../libvnck/tasklist.c
1/* tasklist object */
2
3/*
4 * Copyright (C) 2001 Havoc Pennington
5 * Copyright (C) 2003 Kim Woelders
6 * Copyright (C) 2003 Red Hat, Inc.
7 * Copyright (C) 2003, 2005-2007 Vincent Untz
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include <config.h>
24
25#include <math.h>
26#include <string.h>
27#include <stdio.h>
28#include <glib/gi18n-lib.h>
29#include "tasklist.h"
30#include "window.h"
31#include "class-group.h"
32#include "window-action-menu.h"
33#include "vnck-image-menu-item-private.h"
34#include "workspace.h"
35#include "xutils.h"
36#include "private.h"
37
38/**
39 * SECTION:tasklist
40 * @short_description: a tasklist widget, showing the list of windows as a list
41 * of buttons.
42 * @see_also: #VnckScreen, #VnckSelector
43 * @stability: Unstable
44 *
45 * The #VnckTasklist represents client windows on a screen as a list of buttons
46 * labelled with the window titles and icons. Pressing a button can activate or
47 * minimize the represented window, and other typical actions are available
48 * through a popup menu. Windows needing attention can also be distinguished
49 * by a fade effect on the buttons representing them, to help attract the
50 * user's attention.
51 *
52 * The behavior of the #VnckTasklist can be customized in various ways, like
53 * grouping multiple windows of the same application in one button (see
54 * vnck_tasklist_set_grouping() and vnck_tasklist_set_grouping_limit()), or
55 * showing windows from all workspaces (see
56 * vnck_tasklist_set_include_all_workspaces()). The fade effect for windows
57 * needing attention can be controlled by various style properties like
58 * #VnckTasklist:fade-max-loops and #VnckTasklist:fade-opacity.
59 *
60 * The tasklist also acts as iconification destination. If there are multiple
61 * #VnckTasklist or other applications setting the iconification destination
62 * for windows, the iconification destinations might not be consistent among
63 * windows and it is not possible to determine which #VnckTasklist (or which
64 * other application) owns this propriety.
65 */
66
67/* TODO:
68 *
69 * Add total focused time to the grouping score function
70 * Fine tune the grouping scoring function
71 * Fix "changes" to icon for groups/applications
72 * Maybe fine tune size_allocate() some more...
73 * Better vertical layout handling
74 * prefs
75 * support for right-click menu merging w/ bonobo for the applet
76 *
77 */
78
79
80#define VNCK_TYPE_TASK(vnck_task_get_type ()) (vnck_task_get_type ())
81#define VNCK_TASK(object)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((vnck_task_get_type ()))))))
(G_TYPE_CHECK_INSTANCE_CAST ((object), VNCK_TYPE_TASK, VnckTask)(((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((vnck_task_get_type ())))))
)
82#define VNCK_TASK_CLASS(klass)((((VnckTaskClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), ((vnck_task_get_type ()))))))
(G_TYPE_CHECK_CLASS_CAST ((klass), VNCK_TYPE_TASK, VnckTaskClass)(((VnckTaskClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), ((vnck_task_get_type ())))))
)
83#define VNCK_IS_TASK(object)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(object)); GType __t = ((vnck_task_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
(G_TYPE_CHECK_INSTANCE_TYPE ((object), VNCK_TYPE_TASK)((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(object)); GType __t = ((vnck_task_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))
)
84#define VNCK_IS_TASK_CLASS(klass)(((__extension__ ({ GTypeClass *__class = (GTypeClass*) ((klass
)); GType __t = ((vnck_task_get_type ())); gboolean __r; if (
!__class) __r = (0); else if (__class->g_type == __t) __r =
(!(0)); else __r = g_type_check_class_is_a (__class, __t); __r
; }))))
(G_TYPE_CHECK_CLASS_TYPE ((klass), VNCK_TYPE_TASK)((__extension__ ({ GTypeClass *__class = (GTypeClass*) ((klass
)); GType __t = ((vnck_task_get_type ())); gboolean __r; if (
!__class) __r = (0); else if (__class->g_type == __t) __r =
(!(0)); else __r = g_type_check_class_is_a (__class, __t); __r
; })))
)
85#define VNCK_TASK_GET_CLASS(obj)((((VnckTaskClass*) (((GTypeInstance*) ((obj)))->g_class))
))
(G_TYPE_INSTANCE_GET_CLASS ((obj), VNCK_TYPE_TASK, VnckTaskClass)(((VnckTaskClass*) (((GTypeInstance*) ((obj)))->g_class))))
86
87typedef struct _VnckTask VnckTask;
88typedef struct _VnckTaskClass VnckTaskClass;
89
90#define DEFAULT_GROUPING_LIMIT80 80
91
92#define MINI_ICON_SIZE_vnck_get_default_mini_icon_size () _vnck_get_default_mini_icon_size ()
93#define TASKLIST_BUTTON_PADDING4 4
94#define TASKLIST_TEXT_MAX_WIDTH25 25 /* maximum width in characters */
95
96#define N_SCREEN_CONNECTIONS5 5
97
98#define POINT_IN_RECT(xcoord, ycoord, rect)((xcoord) >= (rect).x && (xcoord) < ((rect).x +
(rect).width) && (ycoord) >= (rect).y && (
ycoord) < ((rect).y + (rect).height))
\
99 ((xcoord) >= (rect).x && \
100 (xcoord) < ((rect).x + (rect).width) && \
101 (ycoord) >= (rect).y && \
102 (ycoord) < ((rect).y + (rect).height))
103
104typedef enum
105{
106 VNCK_TASK_CLASS_GROUP,
107 VNCK_TASK_WINDOW,
108 VNCK_TASK_STARTUP_SEQUENCE
109} VnckTaskType;
110
111struct _VnckTask
112{
113 GObject parent_instance;
114
115 VnckTasklist *tasklist;
116
117 CtkWidget *button;
118 CtkWidget *image;
119 CtkWidget *label;
120
121 VnckTaskType type;
122
123 VnckClassGroup *class_group;
124 VnckWindow *window;
125#ifdef HAVE_STARTUP_NOTIFICATION1
126 SnStartupSequence *startup_sequence;
127#endif
128
129 gdouble grouping_score;
130
131 GList *windows; /* List of the VnckTask for the window,
132 if this is a class group */
133 guint state_changed_tag;
134 guint icon_changed_tag;
135 guint name_changed_tag;
136 guint class_name_changed_tag;
137 guint class_icon_changed_tag;
138
139 /* task menu */
140 CtkWidget *menu;
141 /* ops menu */
142 CtkWidget *action_menu;
143
144 guint really_toggling : 1; /* Set when tasklist really wants
145 * to change the togglebutton state
146 */
147 guint was_active : 1; /* used to fixup activation behavior */
148
149 guint button_activate;
150
151 guint32 dnd_timestamp;
152
153 time_t start_needs_attention;
154 gdouble glow_start_time;
155 gdouble glow_factor;
156
157 guint button_glow;
158
159 gint row;
160 gint col;
161
162 guint resize_idle_id;
163};
164
165struct _VnckTaskClass
166{
167 GObjectClass parent_class;
168};
169
170typedef struct _skipped_window
171{
172 VnckWindow *window;
173 gulong tag;
174} skipped_window;
175
176struct _VnckTasklistPrivate
177{
178 VnckScreen *screen;
179
180 VnckTask *active_task; /* NULL if active window not in tasklist */
181 VnckTask *active_class_group; /* NULL if active window not in tasklist */
182
183 gboolean include_all_workspaces;
184
185 /* Calculated by update_lists */
186 GList *class_groups;
187 GList *windows;
188 GList *windows_without_class_group;
189
190 /* Not handled by update_lists */
191 GList *startup_sequences;
192
193 /* windows with _NET_WM_STATE_SKIP_TASKBAR set; connected to
194 * "state_changed" signal, but excluded from tasklist.
195 */
196 GList *skipped_windows;
197
198 GHashTable *class_group_hash;
199 GHashTable *win_hash;
200
201 gint max_button_width;
202 gint max_button_height;
203
204 gboolean switch_workspace_on_unminimize;
205 gboolean middle_click_close;
206
207 VnckTasklistGroupingType grouping;
208 gint grouping_limit;
209
210 guint activate_timeout_id;
211 guint screen_connections [N_SCREEN_CONNECTIONS5];
212
213 guint idle_callback_tag;
214
215 int *size_hints;
216 int size_hints_len;
217
218 VnckLoadIconFunction icon_loader;
219 void *icon_loader_data;
220 GDestroyNotify free_icon_loader_data;
221
222#ifdef HAVE_STARTUP_NOTIFICATION1
223 SnMonitorContext *sn_context;
224 guint startup_sequence_timeout;
225#endif
226
227 CdkMonitor *monitor;
228 CdkRectangle monitor_geometry;
229 CtkReliefStyle relief;
230 CtkOrientation orientation;
231
232 guint drag_start_time;
233
234 gboolean scroll_enabled;
235};
236
237static GType vnck_task_get_type (void);
238
239G_DEFINE_TYPE (VnckTask, vnck_task, G_TYPE_OBJECT)static void vnck_task_init (VnckTask *self); static void vnck_task_class_init
(VnckTaskClass *klass); static GType vnck_task_get_type_once
(void); static gpointer vnck_task_parent_class = ((void*)0);
static gint VnckTask_private_offset; static void vnck_task_class_intern_init
(gpointer klass) { vnck_task_parent_class = g_type_class_peek_parent
(klass); if (VnckTask_private_offset != 0) g_type_class_adjust_private_offset
(klass, &VnckTask_private_offset); vnck_task_class_init (
(VnckTaskClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer vnck_task_get_instance_private (VnckTask *self
) { return (((gpointer) ((guint8*) (self) + (glong) (VnckTask_private_offset
)))); } GType vnck_task_get_type (void) { static GType static_g_define_type_id
= 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) * (&static_g_define_type_id) : ((void*)
0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= vnck_task_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType vnck_task_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("VnckTask"), sizeof
(VnckTaskClass), (GClassInitFunc)(void (*)(void)) vnck_task_class_intern_init
, sizeof (VnckTask), (GInstanceInitFunc)(void (*)(void)) vnck_task_init
, (GTypeFlags) 0); { {{};} } return g_define_type_id; }
;
240G_DEFINE_TYPE_WITH_PRIVATE (VnckTasklist, vnck_tasklist, CTK_TYPE_CONTAINER)static void vnck_tasklist_init (VnckTasklist *self); static void
vnck_tasklist_class_init (VnckTasklistClass *klass); static GType
vnck_tasklist_get_type_once (void); static gpointer vnck_tasklist_parent_class
= ((void*)0); static gint VnckTasklist_private_offset; static
void vnck_tasklist_class_intern_init (gpointer klass) { vnck_tasklist_parent_class
= g_type_class_peek_parent (klass); if (VnckTasklist_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &VnckTasklist_private_offset
); vnck_tasklist_class_init ((VnckTasklistClass*) klass); } __attribute__
((__unused__)) static inline gpointer vnck_tasklist_get_instance_private
(VnckTasklist *self) { return (((gpointer) ((guint8*) (self)
+ (glong) (VnckTasklist_private_offset)))); } GType vnck_tasklist_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= vnck_tasklist_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType vnck_tasklist_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
ctk_container_get_type ()), g_intern_static_string ("VnckTasklist"
), sizeof (VnckTasklistClass), (GClassInitFunc)(void (*)(void
)) vnck_tasklist_class_intern_init, sizeof (VnckTasklist), (GInstanceInitFunc
)(void (*)(void)) vnck_tasklist_init, (GTypeFlags) 0); { {{ VnckTasklist_private_offset
= g_type_add_instance_private (g_define_type_id, sizeof (VnckTasklistPrivate
)); };} } return g_define_type_id; }
;
241
242enum
243{
244 TASK_ENTER_NOTIFY,
245 TASK_LEAVE_NOTIFY,
246 LAST_SIGNAL
247};
248
249static void vnck_task_finalize (GObject *object);
250
251static void vnck_task_stop_glow (VnckTask *task);
252
253static VnckTask *vnck_task_new_from_window (VnckTasklist *tasklist,
254 VnckWindow *window);
255static VnckTask *vnck_task_new_from_class_group (VnckTasklist *tasklist,
256 VnckClassGroup *class_group);
257#ifdef HAVE_STARTUP_NOTIFICATION1
258static VnckTask *vnck_task_new_from_startup_sequence (VnckTasklist *tasklist,
259 SnStartupSequence *sequence);
260#endif
261static gboolean vnck_task_get_needs_attention (VnckTask *task);
262
263
264static char *vnck_task_get_text (VnckTask *task,
265 gboolean icon_text,
266 gboolean include_state);
267static GdkPixbuf *vnck_task_get_icon (VnckTask *task);
268static gint vnck_task_compare_alphabetically (gconstpointer a,
269 gconstpointer b);
270static gint vnck_task_compare (gconstpointer a,
271 gconstpointer b);
272static void vnck_task_update_visible_state (VnckTask *task);
273static void vnck_task_state_changed (VnckWindow *window,
274 VnckWindowState changed_mask,
275 VnckWindowState new_state,
276 gpointer data);
277
278static void vnck_task_drag_begin (CtkWidget *widget,
279 CdkDragContext *context,
280 VnckTask *task);
281static void vnck_task_drag_end (CtkWidget *widget,
282 CdkDragContext *context,
283 VnckTask *task);
284static void vnck_task_drag_data_get (CtkWidget *widget,
285 CdkDragContext *context,
286 CtkSelectionData *selection_data,
287 guint info,
288 guint time,
289 VnckTask *task);
290
291static void vnck_tasklist_finalize (GObject *object);
292
293static void vnck_tasklist_get_preferred_width (CtkWidget *widget,
294 int *minimum_width,
295 int *natural_width);
296static void vnck_tasklist_get_preferred_height (CtkWidget *widget,
297 int *minimum_height,
298 int *natural_height);
299static void vnck_tasklist_size_allocate (CtkWidget *widget,
300 CtkAllocation *allocation);
301static void vnck_tasklist_realize (CtkWidget *widget);
302static void vnck_tasklist_unrealize (CtkWidget *widget);
303static gboolean vnck_tasklist_scroll_event (CtkWidget *widget,
304 CdkEventScroll *event);
305static void vnck_tasklist_forall (CtkContainer *container,
306 gboolean include_internals,
307 CtkCallback callback,
308 gpointer callback_data);
309static void vnck_tasklist_remove (CtkContainer *container,
310 CtkWidget *widget);
311static void vnck_tasklist_free_tasks (VnckTasklist *tasklist);
312static void vnck_tasklist_update_lists (VnckTasklist *tasklist);
313static int vnck_tasklist_layout (CtkAllocation *allocation,
314 int max_width,
315 int max_height,
316 int n_buttons,
317 CtkOrientation orientation,
318 int *n_cols_out,
319 int *n_rows_out);
320
321static void vnck_tasklist_active_window_changed (VnckScreen *screen,
322 VnckWindow *previous_window,
323 VnckTasklist *tasklist);
324static void vnck_tasklist_active_workspace_changed (VnckScreen *screen,
325 VnckWorkspace *previous_workspace,
326 VnckTasklist *tasklist);
327static void vnck_tasklist_window_added (VnckScreen *screen,
328 VnckWindow *win,
329 VnckTasklist *tasklist);
330static void vnck_tasklist_window_removed (VnckScreen *screen,
331 VnckWindow *win,
332 VnckTasklist *tasklist);
333static void vnck_tasklist_viewports_changed (VnckScreen *screen,
334 VnckTasklist *tasklist);
335static void vnck_tasklist_connect_window (VnckTasklist *tasklist,
336 VnckWindow *window);
337static void vnck_tasklist_disconnect_window (VnckTasklist *tasklist,
338 VnckWindow *window);
339
340static void vnck_tasklist_change_active_task (VnckTasklist *tasklist,
341 VnckTask *active_task);
342static gboolean vnck_tasklist_change_active_timeout (gpointer data);
343static void vnck_tasklist_activate_task_window (VnckTask *task,
344 guint32 timestamp);
345
346static void vnck_tasklist_update_icon_geometries (VnckTasklist *tasklist,
347 GList *visible_tasks);
348static void vnck_tasklist_connect_screen (VnckTasklist *tasklist);
349static void vnck_tasklist_disconnect_screen (VnckTasklist *tasklist);
350
351#ifdef HAVE_STARTUP_NOTIFICATION1
352static void vnck_tasklist_sn_event (SnMonitorEvent *event,
353 void *user_data);
354static void vnck_tasklist_check_end_sequence (VnckTasklist *tasklist,
355 VnckWindow *window);
356#endif
357
358/*
359 * Keep track of all tasklist instances so we can decide
360 * whether to show windows from all monitors in the
361 * tasklist
362 */
363static GSList *tasklist_instances;
364
365static void
366vnck_task_init (VnckTask *task)
367{
368 task->type = VNCK_TASK_WINDOW;
369 task->resize_idle_id = 0;
370}
371
372static void
373vnck_task_class_init (VnckTaskClass *klass)
374{
375 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), (((GType) ((20) << (2))))))))
;
376
377 object_class->finalize = vnck_task_finalize;
378}
379
380static gboolean
381vnck_task_button_glow (VnckTask *task)
382{
383 gdouble now;
384 gfloat fade_opacity, loop_time;
385 gint fade_max_loops;
386 gboolean stopped;
387
388 now = g_get_real_time () / G_USEC_PER_SEC1000000;
389
390 if (task->glow_start_time <= G_MINDOUBLE2.2250738585072014e-308)
391 task->glow_start_time = now;
392
393 ctk_widget_style_get (CTK_WIDGET (task->tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->tasklist)), ((ctk_widget_get_type ()))))))
, "fade-opacity", &fade_opacity,
394 "fade-loop-time", &loop_time,
395 "fade-max-loops", &fade_max_loops,
396 NULL((void*)0));
397
398 if (task->button_glow == 0)
399 {
400 /* we're in "has stopped glowing" mode */
401 task->glow_factor = (gdouble) fade_opacity * 0.5;
402 stopped = TRUE(!(0));
403 }
404 else
405 {
406 task->glow_factor =
407 (gdouble) fade_opacity * (0.5 -
408 0.5 * cos ((now - task->glow_start_time) *
409 M_PI3.14159265358979323846 * 2.0 / (gdouble) loop_time));
410
411 if (now - task->start_needs_attention > (gdouble) loop_time * 1.0 * fade_max_loops)
412 stopped = ABS (task->glow_factor - (gdouble) fade_opacity * 0.5)(((task->glow_factor - (gdouble) fade_opacity * 0.5) < 0
) ? -(task->glow_factor - (gdouble) fade_opacity * 0.5) : (
task->glow_factor - (gdouble) fade_opacity * 0.5))
< 0.05;
413 else
414 stopped = FALSE(0);
415 }
416
417 ctk_widget_queue_draw (task->button);
418
419 if (stopped)
420 vnck_task_stop_glow (task);
421
422 return !stopped;
423}
424
425static void
426vnck_task_clear_glow_start_timeout_id (VnckTask *task)
427{
428 task->button_glow = 0;
429}
430
431static void
432vnck_task_queue_glow (VnckTask *task)
433{
434 if (task->button_glow == 0)
435 {
436 task->glow_start_time = 0.0;
437
438 /* The animation doesn't speed up or slow down based on the
439 * timeout value, but instead will just appear smoother or
440 * choppier.
441 */
442 task->button_glow =
443 g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE200,
444 50,
445 (GSourceFunc) vnck_task_button_glow, task,
446 (GDestroyNotify) vnck_task_clear_glow_start_timeout_id);
447 }
448}
449
450static void
451vnck_task_stop_glow (VnckTask *task)
452{
453 /* We stop glowing, but we might still have the task colored,
454 * so we don't reset the glow factor */
455 if (task->button_glow != 0)
456 g_source_remove (task->button_glow);
457}
458
459static void
460vnck_task_reset_glow (VnckTask *task)
461{
462 vnck_task_stop_glow (task);
463 task->glow_factor = 0.0;
464}
465
466static void
467vnck_task_finalize (GObject *object)
468{
469 VnckTask *task;
470
471 task = VNCK_TASK (object)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((vnck_task_get_type ()))))))
;
472
473 if (task->tasklist->priv->active_task == task)
474 vnck_tasklist_change_active_task (task->tasklist, NULL((void*)0));
475
476 if (task->button)
477 {
478 g_object_remove_weak_pointer (G_OBJECT (task->button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), (((GType) ((20) << (2))))))))
,
479 (void**) &task->button);
480 ctk_widget_destroy (task->button);
481 task->button = NULL((void*)0);
482 task->image = NULL((void*)0);
483 task->label = NULL((void*)0);
484 }
485
486#ifdef HAVE_STARTUP_NOTIFICATION1
487 if (task->startup_sequence)
488 {
489 sn_startup_sequence_unref (task->startup_sequence);
490 task->startup_sequence = NULL((void*)0);
491 }
492#endif
493
494 g_list_free (task->windows);
495 task->windows = NULL((void*)0);
496
497 if (task->state_changed_tag != 0)
498 {
499 g_signal_handler_disconnect (task->window,
500 task->state_changed_tag);
501 task->state_changed_tag = 0;
502 }
503
504 if (task->icon_changed_tag != 0)
505 {
506 g_signal_handler_disconnect (task->window,
507 task->icon_changed_tag);
508 task->icon_changed_tag = 0;
509 }
510
511 if (task->name_changed_tag != 0)
512 {
513 g_signal_handler_disconnect (task->window,
514 task->name_changed_tag);
515 task->name_changed_tag = 0;
516 }
517
518 if (task->class_name_changed_tag != 0)
519 {
520 g_signal_handler_disconnect (task->class_group,
521 task->class_name_changed_tag);
522 task->class_name_changed_tag = 0;
523 }
524
525 if (task->class_icon_changed_tag != 0)
526 {
527 g_signal_handler_disconnect (task->class_group,
528 task->class_icon_changed_tag);
529 task->class_icon_changed_tag = 0;
530 }
531
532 if (task->class_group)
533 {
534 g_object_unref (task->class_group);
535 task->class_group = NULL((void*)0);
536 }
537
538 if (task->window)
539 {
540 g_object_unref (task->window);
541 task->window = NULL((void*)0);
542 }
543
544 if (task->menu)
545 {
546 ctk_widget_destroy (task->menu);
547 task->menu = NULL((void*)0);
548 }
549
550 if (task->action_menu)
551 {
552 g_object_remove_weak_pointer (G_OBJECT (task->action_menu)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->action_menu)), (((GType) ((20) << (2)))))
)))
,
553 (void**) &task->action_menu);
554 ctk_widget_destroy (task->action_menu);
555 task->action_menu = NULL((void*)0);
556 }
557
558 if (task->button_activate != 0)
559 {
560 g_source_remove (task->button_activate);
561 task->button_activate = 0;
562 }
563
564 vnck_task_stop_glow (task);
565
566 if (task->resize_idle_id > 0)
567 {
568 g_source_remove (task->resize_idle_id);
569 task->resize_idle_id = 0;
570 }
571
572 G_OBJECT_CLASS (vnck_task_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((vnck_task_parent_class)), (((GType) ((20) << (2)))
)))))
->finalize (object);
573}
574
575static guint signals[LAST_SIGNAL] = { 0 };
576
577static void
578vnck_tasklist_init (VnckTasklist *tasklist)
579{
580 CtkWidget *widget;
581 AtkObject *atk_obj;
582
583 widget = CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
;
584
585 ctk_widget_set_has_window (widget, FALSE(0));
586
587 tasklist->priv = vnck_tasklist_get_instance_private (tasklist);
588
589 tasklist->priv->class_group_hash = g_hash_table_new (NULL((void*)0), NULL((void*)0));
590 tasklist->priv->win_hash = g_hash_table_new (NULL((void*)0), NULL((void*)0));
591
592 tasklist->priv->grouping = VNCK_TASKLIST_AUTO_GROUP;
593 tasklist->priv->grouping_limit = DEFAULT_GROUPING_LIMIT80;
594
595 tasklist->priv->monitor = NULL((void*)0);
596 tasklist->priv->monitor_geometry.width = -1; /* invalid value */
597 tasklist->priv->relief = CTK_RELIEF_NORMAL;
598 tasklist->priv->orientation = CTK_ORIENTATION_HORIZONTAL;
599 tasklist->priv->scroll_enabled = TRUE(!(0));
600
601 atk_obj = ctk_widget_get_accessible (widget);
602 atk_object_set_name (atk_obj, _("Window List")((char *) g_dgettext ("libvnck-3.0", "Window List")));
603 atk_object_set_description (atk_obj, _("Tool to switch between visible windows")((char *) g_dgettext ("libvnck-3.0", "Tool to switch between visible windows"
))
);
604
605#if 0
606 /* This doesn't work because, and I think this is because we have no window;
607 * therefore, we use the scroll events on task buttons instead */
608 ctk_widget_add_events (widget, CDK_SCROLL_MASK);
609#endif
610}
611
612static void
613vnck_tasklist_class_init (VnckTasklistClass *klass)
614{
615 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), (((GType) ((20) << (2))))))))
;
616 CtkWidgetClass *widget_class = CTK_WIDGET_CLASS (klass)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), ((ctk_widget_get_type ()))))))
;
617 CtkContainerClass *container_class = CTK_CONTAINER_CLASS (klass)((((CtkContainerClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), ((ctk_container_get_type ()))))))
;
618
619 object_class->finalize = vnck_tasklist_finalize;
620
621 widget_class->get_preferred_width = vnck_tasklist_get_preferred_width;
622 widget_class->get_preferred_height = vnck_tasklist_get_preferred_height;
623 widget_class->size_allocate = vnck_tasklist_size_allocate;
624 widget_class->realize = vnck_tasklist_realize;
625 widget_class->unrealize = vnck_tasklist_unrealize;
626#if 0
627 /* See comment above ctk_widget_add_events() in vnck_tasklist_init() */
628 widget_class->scroll_event = vnck_tasklist_scroll_event;
629#endif
630
631 container_class->forall = vnck_tasklist_forall;
632 container_class->remove = vnck_tasklist_remove;
633
634 /**
635 * VnckTasklist:fade-loop-time:
636 *
637 * When a window needs attention, a fade effect is drawn on the button
638 * representing the window. This property controls the time one loop of this
639 * fade effect takes, in seconds.
640 *
641 * Since: 2.16
642 */
643 ctk_widget_class_install_style_property (widget_class,
644 g_param_spec_float ("fade-loop-time",
645 "Loop time",
646 "The time one loop takes when fading, in seconds. Default: 3.0",
647 0.2, 10.0, 3.0,
648 G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
649
650 /**
651 * VnckTasklist:fade-max-loops:
652 *
653 * When a window needs attention, a fade effect is drawn on the button
654 * representing the window. This property controls the number of loops for
655 * this fade effect. 0 means the button will only fade to the final color.
656 *
657 * Since: 2.20
658 */
659 ctk_widget_class_install_style_property (widget_class,
660 g_param_spec_int ("fade-max-loops",
661 "Maximum number of loops",
662 "The number of fading loops. 0 means the button will only fade to the final color. Default: 5",
663 0, 50, 5,
664 G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
665
666 /**
667 * VnckTasklist:fade-overlay-rect:
668 *
669 * When a window needs attention, a fade effect is drawn on the button
670 * representing the window. Set this property to %TRUE to enable a
671 * compatibility mode for pixbuf engine themes that cannot react to color
672 * changes. If enabled, a rectangle with the correct color will be drawn on
673 * top of the button.
674 *
675 * Since: 2.16
676 */
677 ctk_widget_class_install_style_property (widget_class,
678 g_param_spec_boolean ("fade-overlay-rect",
679 "Overlay a rectangle, instead of modifying the background.",
680 "Compatibility mode for pixbuf engine themes that cannot react to color changes. If enabled, a rectangle with the correct color will be drawn on top of the button. Default: TRUE",
681 TRUE(!(0)),
682 G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
683
684 /**
685 * VnckTasklist:fade-opacity:
686 *
687 * When a window needs attention, a fade effect is drawn on the button
688 * representing the window. This property controls the final opacity that
689 * will be reached by the fade effect.
690 *
691 * Since: 2.16
692 */
693 ctk_widget_class_install_style_property (widget_class,
694 g_param_spec_float ("fade-opacity",
695 "Final opacity",
696 "The final opacity that will be reached. Default: 0.8",
697 0.0, 1.0, 0.8,
698 G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
699
700 ctk_widget_class_set_css_name (widget_class, "vnck-tasklist");
701
702 /**
703 * VnckTasklist::task-enter-notify:
704 * @tasklist: the #VnckTasklist which emitted the signal.
705 * @windows: the #GList with all the #VnckWindow belonging to the task.
706 *
707 * Emitted when the task is entered.
708 */
709 signals[TASK_ENTER_NOTIFY] =
710 g_signal_new ("task_enter_notify",
711 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
712 G_SIGNAL_RUN_LAST,
713 0, NULL((void*)0), NULL((void*)0), NULL((void*)0),
714 G_TYPE_NONE((GType) ((1) << (2))), 1,
715 G_TYPE_POINTER((GType) ((17) << (2))));
716
717 /**
718 * VnckTasklist::task-leave-notify:
719 * @tasklist: the #VnckTasklist which emitted the signal.
720 * @windows: the #GList with all the #VnckWindow belonging to the task.
721 *
722 * Emitted when the task is entered.
723 */
724 signals[TASK_LEAVE_NOTIFY] =
725 g_signal_new ("task_leave_notify",
726 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
727 G_SIGNAL_RUN_LAST,
728 0, NULL((void*)0), NULL((void*)0), NULL((void*)0),
729 G_TYPE_NONE((GType) ((1) << (2))), 1,
730 G_TYPE_POINTER((GType) ((17) << (2))));
731}
732
733static void
734vnck_tasklist_free_skipped_windows (VnckTasklist *tasklist)
735{
736 GList *l;
737
738 l = tasklist->priv->skipped_windows;
739
740 while (l != NULL((void*)0))
741 {
742 skipped_window *skipped = (skipped_window*) l->data;
743 g_signal_handler_disconnect (skipped->window, skipped->tag);
744 g_object_unref (skipped->window);
745 g_free (skipped);
746 l = l->next;
747 }
748
749 g_list_free (tasklist->priv->skipped_windows);
750}
751
752static void
753vnck_tasklist_finalize (GObject *object)
754{
755 VnckTasklist *tasklist;
756
757 tasklist = VNCK_TASKLIST (object)((((VnckTasklist*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((vnck_tasklist_get_type ()))))))
;
758
759 /* Tasks should have gone away due to removing their
760 * buttons in container destruction
761 */
762 g_assert (tasklist->priv->class_groups == NULL)do { if (tasklist->priv->class_groups == ((void*)0)) ; else
g_assertion_message_expr ("Vnck", "../libvnck/tasklist.c", 762
, ((const char*) (__func__)), "tasklist->priv->class_groups == NULL"
); } while (0)
;
763 g_assert (tasklist->priv->windows == NULL)do { if (tasklist->priv->windows == ((void*)0)) ; else g_assertion_message_expr
("Vnck", "../libvnck/tasklist.c", 763, ((const char*) (__func__
)), "tasklist->priv->windows == NULL"); } while (0)
;
764 g_assert (tasklist->priv->windows_without_class_group == NULL)do { if (tasklist->priv->windows_without_class_group ==
((void*)0)) ; else g_assertion_message_expr ("Vnck", "../libvnck/tasklist.c"
, 764, ((const char*) (__func__)), "tasklist->priv->windows_without_class_group == NULL"
); } while (0)
;
765 g_assert (tasklist->priv->startup_sequences == NULL)do { if (tasklist->priv->startup_sequences == ((void*)0
)) ; else g_assertion_message_expr ("Vnck", "../libvnck/tasklist.c"
, 765, ((const char*) (__func__)), "tasklist->priv->startup_sequences == NULL"
); } while (0)
;
766 /* vnck_tasklist_free_tasks (tasklist); */
767
768 if (tasklist->priv->skipped_windows)
769 {
770 vnck_tasklist_free_skipped_windows (tasklist);
771 tasklist->priv->skipped_windows = NULL((void*)0);
772 }
773
774 g_hash_table_destroy (tasklist->priv->class_group_hash);
775 tasklist->priv->class_group_hash = NULL((void*)0);
776
777 g_hash_table_destroy (tasklist->priv->win_hash);
778 tasklist->priv->win_hash = NULL((void*)0);
779
780 if (tasklist->priv->activate_timeout_id != 0)
781 {
782 g_source_remove (tasklist->priv->activate_timeout_id);
783 tasklist->priv->activate_timeout_id = 0;
784 }
785
786 if (tasklist->priv->idle_callback_tag != 0)
787 {
788 g_source_remove (tasklist->priv->idle_callback_tag);
789 tasklist->priv->idle_callback_tag = 0;
790 }
791
792 g_free (tasklist->priv->size_hints);
793 tasklist->priv->size_hints = NULL((void*)0);
794 tasklist->priv->size_hints_len = 0;
795
796 if (tasklist->priv->free_icon_loader_data != NULL((void*)0))
797 (* tasklist->priv->free_icon_loader_data) (tasklist->priv->icon_loader_data);
798 tasklist->priv->free_icon_loader_data = NULL((void*)0);
799 tasklist->priv->icon_loader_data = NULL((void*)0);
800
801 G_OBJECT_CLASS (vnck_tasklist_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((vnck_tasklist_parent_class)), (((GType) ((20) << (
2))))))))
->finalize (object);
802}
803
804/**
805 * vnck_tasklist_set_grouping:
806 * @tasklist: a #VnckTasklist.
807 * @grouping: a grouping policy.
808 *
809 * Sets the grouping policy for @tasklist to @grouping.
810 */
811void
812vnck_tasklist_set_grouping (VnckTasklist *tasklist,
813 VnckTasklistGroupingType grouping)
814{
815 g_return_if_fail (VNCK_IS_TASKLIST (tasklist))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tasklist)); GType __t = ((vnck_tasklist_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Vnck", ((const char*) (__func__
)), "VNCK_IS_TASKLIST (tasklist)"); return; } } while (0)
;
816
817 if (tasklist->priv->grouping == grouping)
818 return;
819
820 tasklist->priv->grouping = grouping;
821 ctk_widget_queue_resize (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
822}
823
824static void
825vnck_tasklist_set_relief_callback (VnckWindow *win G_GNUC_UNUSED__attribute__ ((__unused__)),
826 VnckTask *task,
827 VnckTasklist *tasklist)
828{
829 ctk_button_set_relief (CTK_BUTTON (task->button)((((CtkButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), ((ctk_button_get_type ()))))))
, tasklist->priv->relief);
830}
831
832/**
833 * vnck_tasklist_set_button_relief:
834 * @tasklist: a #VnckTasklist.
835 * @relief: a relief type.
836 *
837 * Sets the relief type of the buttons in @tasklist to @relief. The main use of
838 * this function is proper integration of #VnckTasklist in panels with
839 * non-system backgrounds.
840 *
841 * Since: 2.12
842 */
843void
844vnck_tasklist_set_button_relief (VnckTasklist *tasklist, CtkReliefStyle relief)
845{
846 GList *walk;
847
848 g_return_if_fail (VNCK_IS_TASKLIST (tasklist))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tasklist)); GType __t = ((vnck_tasklist_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Vnck", ((const char*) (__func__
)), "VNCK_IS_TASKLIST (tasklist)"); return; } } while (0)
;
849
850 if (relief == tasklist->priv->relief)
851 return;
852
853 tasklist->priv->relief = relief;
854
855 g_hash_table_foreach (tasklist->priv->win_hash,
856 (GHFunc) vnck_tasklist_set_relief_callback,
857 tasklist);
858 for (walk = tasklist->priv->class_groups; walk; walk = g_list_next (walk)((walk) ? (((GList *)(walk))->next) : ((void*)0)))
859 ctk_button_set_relief (CTK_BUTTON (VNCK_TASK (walk->data)->button)((((CtkButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((walk->data)), ((vnck_task_get_type ()))))))->button
)), ((ctk_button_get_type ()))))))
, relief);
860}
861
862/**
863 * vnck_tasklist_set_middle_click_close:
864 * @tasklist: a #VnckTasklist.
865 * @middle_click_close: whether to close windows with middle click on
866 * button.
867 *
868 * Sets @tasklist to close windows with mouse middle click on button,
869 * according to @middle_click_close.
870 *
871 * Since: 3.4.6
872 */
873void
874vnck_tasklist_set_middle_click_close (VnckTasklist *tasklist,
875 gboolean middle_click_close)
876{
877 g_return_if_fail (VNCK_IS_TASKLIST (tasklist))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tasklist)); GType __t = ((vnck_tasklist_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Vnck", ((const char*) (__func__
)), "VNCK_IS_TASKLIST (tasklist)"); return; } } while (0)
;
878
879 tasklist->priv->middle_click_close = middle_click_close;
880}
881
882/**
883 * vnck_tasklist_set_orientation:
884 * @tasklist: a #VnckTasklist.
885 * @orient: a CtkOrientation.
886 *
887 * Set the orientation of the @tasklist to match @orient.
888 * This function can be used to integrate a #VnckTasklist in vertical panels.
889 *
890 * Since: 3.4.6
891 */
892void vnck_tasklist_set_orientation (VnckTasklist *tasklist,
893 CtkOrientation orient)
894{
895 g_return_if_fail (VNCK_IS_TASKLIST (tasklist))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tasklist)); GType __t = ((vnck_tasklist_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Vnck", ((const char*) (__func__
)), "VNCK_IS_TASKLIST (tasklist)"); return; } } while (0)
;
896
897 tasklist->priv->orientation = orient;
898}
899
900/**
901 * vnck_tasklist_set_scroll_enabled:
902 * @tasklist: a #VnckTasklist.
903 * @scroll_enabled: a boolean.
904 *
905 * Sets the scroll behavior of the @tasklist. When set to %TRUE, a scroll
906 * event over the tasklist will change the current window accordingly.
907 *
908 * Since: 3.24.0
909 */
910void
911vnck_tasklist_set_scroll_enabled (VnckTasklist *tasklist,
912 gboolean scroll_enabled)
913{
914 g_return_if_fail (VNCK_IS_TASKLIST (tasklist))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tasklist)); GType __t = ((vnck_tasklist_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Vnck", ((const char*) (__func__
)), "VNCK_IS_TASKLIST (tasklist)"); return; } } while (0)
;
915
916 tasklist->priv->scroll_enabled = scroll_enabled;
917}
918
919/**
920 * vnck_tasklist_get_scroll_enabled:
921 * @tasklist: a #VnckTasklist.
922 *
923 * Gets the scroll behavior of the @tasklist.
924 *
925 * Since: 3.24.0
926 */
927gboolean
928vnck_tasklist_get_scroll_enabled (VnckTasklist *tasklist)
929{
930 g_return_val_if_fail (VNCK_IS_TASKLIST (tasklist), TRUE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tasklist)); GType __t = ((vnck_tasklist_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Vnck", ((const char*) (__func__
)), "VNCK_IS_TASKLIST (tasklist)"); return ((!(0))); } } while
(0)
;
931
932 return tasklist->priv->scroll_enabled;
933}
934
935/**
936 * vnck_tasklist_set_switch_workspace_on_unminimize:
937 * @tasklist: a #VnckTasklist.
938 * @switch_workspace_on_unminimize: whether to activate the #VnckWorkspace a
939 * #VnckWindow is on when unminimizing it.
940 *
941 * Sets @tasklist to activate or not the #VnckWorkspace a #VnckWindow is on
942 * when unminimizing it, according to @switch_workspace_on_unminimize.
943 *
944 * FIXME: does it still work?
945 */
946void
947vnck_tasklist_set_switch_workspace_on_unminimize (VnckTasklist *tasklist,
948 gboolean switch_workspace_on_unminimize)
949{
950 g_return_if_fail (VNCK_IS_TASKLIST (tasklist))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tasklist)); GType __t = ((vnck_tasklist_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Vnck", ((const char*) (__func__
)), "VNCK_IS_TASKLIST (tasklist)"); return; } } while (0)
;
951
952 tasklist->priv->switch_workspace_on_unminimize = switch_workspace_on_unminimize;
953}
954
955/**
956 * vnck_tasklist_set_include_all_workspaces:
957 * @tasklist: a #VnckTasklist.
958 * @include_all_workspaces: whether to display #VnckWindow from all
959 * #VnckWorkspace in @tasklist.
960 *
961 * Sets @tasklist to display #VnckWindow from all #VnckWorkspace or not,
962 * according to @include_all_workspaces.
963 *
964 * Note that if the active #VnckWorkspace has a viewport and if
965 * @include_all_workspaces is %FALSE, then only the #VnckWindow visible in the
966 * viewport are displayed in @tasklist. The rationale for this is that the
967 * viewport is generally used to implement workspace-like behavior. A
968 * side-effect of this is that, when using multiple #VnckWorkspace with
969 * viewport, it is not possible to show all #VnckWindow from a #VnckWorkspace
970 * (even those that are not visible in the viewport) in @tasklist without
971 * showing all #VnckWindow from all #VnckWorkspace.
972 */
973void
974vnck_tasklist_set_include_all_workspaces (VnckTasklist *tasklist,
975 gboolean include_all_workspaces)
976{
977 g_return_if_fail (VNCK_IS_TASKLIST (tasklist))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tasklist)); GType __t = ((vnck_tasklist_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Vnck", ((const char*) (__func__
)), "VNCK_IS_TASKLIST (tasklist)"); return; } } while (0)
;
978
979 include_all_workspaces = (include_all_workspaces != 0);
980
981 if (tasklist->priv->include_all_workspaces == include_all_workspaces)
982 return;
983
984 tasklist->priv->include_all_workspaces = include_all_workspaces;
985 vnck_tasklist_update_lists (tasklist);
986 ctk_widget_queue_resize (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
987}
988
989/**
990 * vnck_tasklist_set_grouping_limit:
991 * @tasklist: a #VnckTasklist.
992 * @limit: a size in pixels.
993 *
994 * Sets the maximum size of buttons in @tasklist before @tasklist tries to
995 * group #VnckWindow in the same #VnckApplication in only one button. This
996 * limit is valid only when the grouping policy of @tasklist is
997 * %VNCK_TASKLIST_AUTO_GROUP.
998 */
999void
1000vnck_tasklist_set_grouping_limit (VnckTasklist *tasklist,
1001 gint limit)
1002{
1003 g_return_if_fail (VNCK_IS_TASKLIST (tasklist))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tasklist)); GType __t = ((vnck_tasklist_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Vnck", ((const char*) (__func__
)), "VNCK_IS_TASKLIST (tasklist)"); return; } } while (0)
;
1004
1005 if (tasklist->priv->grouping_limit == limit)
1006 return;
1007
1008 tasklist->priv->grouping_limit = limit;
1009 ctk_widget_queue_resize (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
1010}
1011
1012/**
1013 * vnck_tasklist_set_icon_loader:
1014 * @tasklist: a #VnckTasklist
1015 * @load_icon_func: icon loader function
1016 * @data: data for icon loader function
1017 * @free_data_func: function to free the data
1018 *
1019 * Sets a function to be used for loading icons.
1020 *
1021 * Since: 2.2
1022 **/
1023void
1024vnck_tasklist_set_icon_loader (VnckTasklist *tasklist,
1025 VnckLoadIconFunction load_icon_func,
1026 void *data,
1027 GDestroyNotify free_data_func)
1028{
1029 g_return_if_fail (VNCK_IS_TASKLIST (tasklist))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tasklist)); GType __t = ((vnck_tasklist_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Vnck", ((const char*) (__func__
)), "VNCK_IS_TASKLIST (tasklist)"); return; } } while (0)
;
1030
1031 if (tasklist->priv->free_icon_loader_data != NULL((void*)0))
1032 (* tasklist->priv->free_icon_loader_data) (tasklist->priv->icon_loader_data);
1033
1034 tasklist->priv->icon_loader = load_icon_func;
1035 tasklist->priv->icon_loader_data = data;
1036 tasklist->priv->free_icon_loader_data = free_data_func;
1037}
1038
1039/* returns the maximal possible button width (i.e. if you
1040 * don't want to stretch the buttons to fill the alloctions
1041 * the width can be smaller) */
1042static int
1043vnck_tasklist_layout (CtkAllocation *allocation,
1044 int max_width,
1045 int max_height,
1046 int n_buttons,
1047 CtkOrientation orientation,
1048 int *n_cols_out,
1049 int *n_rows_out)
1050{
1051 int n_cols, n_rows;
1052
1053 if (n_buttons == 0)
1054 {
1055 *n_cols_out = 0;
1056 *n_rows_out = 0;
1057 return 0;
1058 }
1059
1060 if (orientation == CTK_ORIENTATION_HORIZONTAL)
1061 {
1062 /* How many rows fit in the allocation */
1063 n_rows = allocation->height / max_height;
1064
1065 /* Don't have more rows than buttons */
1066 n_rows = MIN (n_rows, n_buttons)(((n_rows) < (n_buttons)) ? (n_rows) : (n_buttons));
1067
1068 /* At least one row */
1069 n_rows = MAX (n_rows, 1)(((n_rows) > (1)) ? (n_rows) : (1));
1070
1071 /* We want to use as many cols as possible to limit the width */
1072 n_cols = (n_buttons + n_rows - 1) / n_rows;
1073
1074 /* At least one column */
1075 n_cols = MAX (n_cols, 1)(((n_cols) > (1)) ? (n_cols) : (1));
1076 }
1077 else
1078 {
1079 /* How many cols fit in the allocation */
1080 n_cols = allocation->width / max_width;
1081
1082 /* Don't have more cols than buttons */
1083 n_cols = MIN (n_cols, n_buttons)(((n_cols) < (n_buttons)) ? (n_cols) : (n_buttons));
1084
1085 /* At least one col */
1086 n_cols = MAX (n_cols, 1)(((n_cols) > (1)) ? (n_cols) : (1));
1087
1088 /* We want to use as many rows as possible to limit the height */
1089 n_rows = (n_buttons + n_cols - 1) / n_cols;
1090
1091 /* At least one row */
1092 n_rows = MAX (n_rows, 1)(((n_rows) > (1)) ? (n_rows) : (1));
1093 }
1094
1095 *n_cols_out = n_cols;
1096 *n_rows_out = n_rows;
1097
1098 return allocation->width / n_cols;
1099}
1100
1101static void
1102vnck_tasklist_score_groups (VnckTasklist *tasklist G_GNUC_UNUSED__attribute__ ((__unused__)),
1103 GList *ungrouped_class_groups)
1104{
1105 VnckTask *class_group_task;
1106 VnckTask *win_task;
1107 GList *l, *w;
1108 const char *first_name = NULL((void*)0);
1109 int n_windows;
1110 int n_same_title;
1111 double same_window_ratio;
1112
1113 l = ungrouped_class_groups;
1114 while (l != NULL((void*)0))
1115 {
1116 class_group_task = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
1117
1118 n_windows = g_list_length (class_group_task->windows);
1119
1120 n_same_title = 0;
1121 w = class_group_task->windows;
1122 while (w != NULL((void*)0))
1123 {
1124 win_task = VNCK_TASK (w->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((w->data)), ((vnck_task_get_type ()))))))
;
1125
1126 if (first_name == NULL((void*)0))
1127 {
1128 if (vnck_window_has_icon_name (win_task->window))
1129 first_name = vnck_window_get_icon_name (win_task->window);
1130 else
1131 first_name = vnck_window_get_name (win_task->window);
1132 n_same_title++;
1133 }
1134 else
1135 {
1136 const char *name;
1137
1138 if (vnck_window_has_icon_name (win_task->window))
1139 name = vnck_window_get_icon_name (win_task->window);
1140 else
1141 name = vnck_window_get_name (win_task->window);
1142
1143 if (strcmp (name, first_name) == 0)
1144 n_same_title++;
1145 }
1146
1147 w = w->next;
1148 }
1149 same_window_ratio = (double)n_same_title/(double)n_windows;
1150
1151 /* FIXME: This is fairly bogus and should be researched more.
1152 * XP groups by least used, so we probably want to add
1153 * total focused time to this expression.
1154 */
1155 class_group_task->grouping_score = -same_window_ratio * 5 + n_windows;
1156
1157 l = l->next;
1158 }
1159}
1160
1161static GList *
1162vnck_task_get_highest_scored (GList *ungrouped_class_groups,
1163 VnckTask **class_group_task_out)
1164{
1165 VnckTask *class_group_task;
1166 VnckTask *best_task = NULL((void*)0);
1167 double max_score = -1000000000.0; /* Large negative score */
1168 GList *l;
1169
1170 l = ungrouped_class_groups;
1171 while (l != NULL((void*)0))
1172 {
1173 class_group_task = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
1174
1175 if (class_group_task->grouping_score >= max_score)
1176 {
1177 max_score = class_group_task->grouping_score;
1178 best_task = class_group_task;
1179 }
1180
1181 l = l->next;
1182 }
1183
1184 *class_group_task_out = best_task;
1185
1186 return g_list_remove (ungrouped_class_groups, best_task);
1187}
1188
1189static int
1190vnck_tasklist_get_button_size (CtkWidget *widget)
1191{
1192 CtkStyleContext *style_context;
1193 CtkStateFlags state;
1194 PangoContext *context;
1195 PangoFontMetrics *metrics;
1196 PangoFontDescription *description;
1197 gint char_width;
1198 gint text_width;
1199 gint width;
1200
1201 style_context = ctk_widget_get_style_context (widget);
1202 state = ctk_style_context_get_state (style_context);
1203 ctk_style_context_get (style_context, state, CTK_STYLE_PROPERTY_FONT"font", &description, NULL((void*)0));
1204
1205 context = ctk_widget_get_pango_context (widget);
1206 metrics = pango_context_get_metrics (context, description,
1207 pango_context_get_language (context));
1208 char_width = pango_font_metrics_get_approximate_char_width (metrics);
1209 pango_font_metrics_unref (metrics);
1210 text_width = PANGO_PIXELS (TASKLIST_TEXT_MAX_WIDTH * char_width)(((int)(25 * char_width) + 512) >> 10);
1211
1212 width = text_width + 2 * TASKLIST_BUTTON_PADDING4
1213 + MINI_ICON_SIZE_vnck_get_default_mini_icon_size () + 2 * TASKLIST_BUTTON_PADDING4;
1214
1215 return width;
1216}
1217
1218static void
1219vnck_tasklist_size_request (CtkWidget *widget,
1220 CtkRequisition *requisition)
1221{
1222 VnckTasklist *tasklist;
1223 CtkRequisition child_req;
1224 CtkAllocation tasklist_allocation;
1225 CtkAllocation fake_allocation;
1226 int max_height = 1;
1227 int max_width = 1;
1228 /* int u_width, u_height; */
1229 GList *l;
1230 GArray *array;
1231 GList *ungrouped_class_groups;
1232 int n_windows;
1233 int n_startup_sequences;
1234 int n_rows;
1235 int n_cols, last_n_cols;
1236 int n_grouped_buttons;
1237 gboolean score_set;
1238 int val;
1239 VnckTask *class_group_task;
1240 int lowest_range;
1241 int grouping_limit;
1242
1243 tasklist = VNCK_TASKLIST (widget)((((VnckTasklist*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((vnck_tasklist_get_type ()))))))
;
1244
1245 /* Calculate max needed height and width of the buttons */
1246#define GET_MAX_WIDTH_HEIGHT_FROM_BUTTONS(list)l = list; while (l != ((void*)0)) { VnckTask *task = ((((VnckTask
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((l->
data)), ((vnck_task_get_type ())))))); ctk_widget_get_preferred_size
(task->button, &child_req, ((void*)0)); max_height = (
((child_req.height) > (max_height)) ? (child_req.height) :
(max_height)); max_width = (((child_req.width) > (max_width
)) ? (child_req.width) : (max_width)); l = l->next; }
\
1247 l = list; \
1248 while (l != NULL((void*)0)) \
1249 { \
1250 VnckTask *task = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
; \
1251 \
1252 ctk_widget_get_preferred_size (task->button, \
1253 &child_req, NULL((void*)0)); \
1254 \
1255 max_height = MAX (child_req.height, \(((child_req.height) > (max_height)) ? (child_req.height) :
(max_height))
1256 max_height)(((child_req.height) > (max_height)) ? (child_req.height) :
(max_height))
; \
1257 max_width = MAX (child_req.width, \(((child_req.width) > (max_width)) ? (child_req.width) : (
max_width))
1258 max_width)(((child_req.width) > (max_width)) ? (child_req.width) : (
max_width))
; \
1259 \
1260 l = l->next; \
1261 }
1262
1263 GET_MAX_WIDTH_HEIGHT_FROM_BUTTONS (tasklist->priv->windows)l = tasklist->priv->windows; while (l != ((void*)0)) { VnckTask
*task = ((((VnckTask*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((l->data)), ((vnck_task_get_type ())))))
); ctk_widget_get_preferred_size (task->button, &child_req
, ((void*)0)); max_height = (((child_req.height) > (max_height
)) ? (child_req.height) : (max_height)); max_width = (((child_req
.width) > (max_width)) ? (child_req.width) : (max_width));
l = l->next; }
1264 GET_MAX_WIDTH_HEIGHT_FROM_BUTTONS (tasklist->priv->class_groups)l = tasklist->priv->class_groups; while (l != ((void*)0
)) { VnckTask *task = ((((VnckTask*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((l->data)), ((vnck_task_get_type ())))
))); ctk_widget_get_preferred_size (task->button, &child_req
, ((void*)0)); max_height = (((child_req.height) > (max_height
)) ? (child_req.height) : (max_height)); max_width = (((child_req
.width) > (max_width)) ? (child_req.width) : (max_width));
l = l->next; }
1265 GET_MAX_WIDTH_HEIGHT_FROM_BUTTONS (tasklist->priv->startup_sequences)l = tasklist->priv->startup_sequences; while (l != ((void
*)0)) { VnckTask *task = ((((VnckTask*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((l->data)), ((vnck_task_get_type ())))
))); ctk_widget_get_preferred_size (task->button, &child_req
, ((void*)0)); max_height = (((child_req.height) > (max_height
)) ? (child_req.height) : (max_height)); max_width = (((child_req
.width) > (max_width)) ? (child_req.width) : (max_width));
l = l->next; }
1266
1267 /* Note that the fact that we nearly don't care about the width/height
1268 * requested by the buttons makes it possible to hide/show the label/image
1269 * in vnck_task_size_allocated(). If we really cared about those, this
1270 * wouldn't work since our call to ctk_widget_size_request() does not take
1271 * into account the hidden widgets.
1272 */
1273 tasklist->priv->max_button_width = vnck_tasklist_get_button_size (widget);
1274 tasklist->priv->max_button_height = max_height;
1275
1276 ctk_widget_get_allocation (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
, &tasklist_allocation);
1277
1278 fake_allocation.width = tasklist_allocation.width;
1279 fake_allocation.height = tasklist_allocation.height;
1280
1281 array = g_array_new (FALSE(0), FALSE(0), sizeof (int));
1282
1283 /* Calculate size_hints list */
1284
1285 n_windows = g_list_length (tasklist->priv->windows);
1286 n_startup_sequences = g_list_length (tasklist->priv->startup_sequences);
1287 n_grouped_buttons = 0;
1288 ungrouped_class_groups = g_list_copy (tasklist->priv->class_groups);
1289 score_set = FALSE(0);
1290
1291 grouping_limit = MIN (tasklist->priv->grouping_limit,(((tasklist->priv->grouping_limit) < (tasklist->priv
->max_button_width)) ? (tasklist->priv->grouping_limit
) : (tasklist->priv->max_button_width))
1292 tasklist->priv->max_button_width)(((tasklist->priv->grouping_limit) < (tasklist->priv
->max_button_width)) ? (tasklist->priv->grouping_limit
) : (tasklist->priv->max_button_width))
;
1293
1294 /* Try ungrouped mode */
1295 vnck_tasklist_layout (&fake_allocation,
1296 tasklist->priv->max_button_width,
1297 tasklist->priv->max_button_height,
1298 n_windows + n_startup_sequences,
1299 tasklist->priv->orientation,
1300 &n_cols, &n_rows);
1301
1302 last_n_cols = G_MAXINT2147483647;
1303 lowest_range = G_MAXINT2147483647;
1304 if (tasklist->priv->grouping != VNCK_TASKLIST_ALWAYS_GROUP)
1305 {
1306 if (tasklist->priv->orientation == CTK_ORIENTATION_HORIZONTAL)
1307 {
1308 val = n_cols * tasklist->priv->max_button_width;
1309 g_array_insert_val (array, array->len, val)g_array_insert_vals (array, array->len, &(val), 1);
1310 val = n_cols * grouping_limit;
1311 g_array_insert_val (array, array->len, val)g_array_insert_vals (array, array->len, &(val), 1);
1312
1313 last_n_cols = n_cols;
1314 lowest_range = val;
1315 }
1316 else
1317 {
1318 val = n_rows * tasklist->priv->max_button_height;
1319 g_array_insert_val (array, array->len, val)g_array_insert_vals (array, array->len, &(val), 1);
1320 val = n_rows * grouping_limit;
1321 g_array_insert_val (array, array->len, val)g_array_insert_vals (array, array->len, &(val), 1);
1322
1323 last_n_cols = n_rows;
1324 lowest_range = val;
1325 }
1326 }
1327
1328 while (ungrouped_class_groups != NULL((void*)0) &&
1329 tasklist->priv->grouping != VNCK_TASKLIST_NEVER_GROUP)
1330 {
1331 if (!score_set)
1332 {
1333 vnck_tasklist_score_groups (tasklist, ungrouped_class_groups);
1334 score_set = TRUE(!(0));
1335 }
1336
1337 ungrouped_class_groups = vnck_task_get_highest_scored (ungrouped_class_groups, &class_group_task);
1338
1339 n_grouped_buttons += g_list_length (class_group_task->windows) - 1;
1340
1341 vnck_tasklist_layout (&fake_allocation,
1342 tasklist->priv->max_button_width,
1343 tasklist->priv->max_button_height,
1344 n_startup_sequences + n_windows - n_grouped_buttons,
1345 tasklist->priv->orientation,
1346 &n_cols, &n_rows);
1347
1348 if (tasklist->priv->orientation == CTK_ORIENTATION_HORIZONTAL)
1349 {
1350 if (n_cols != last_n_cols &&
1351 (tasklist->priv->grouping == VNCK_TASKLIST_AUTO_GROUP ||
1352 ungrouped_class_groups == NULL((void*)0)))
1353 {
1354 val = n_cols * tasklist->priv->max_button_width;
1355 if (val >= lowest_range)
1356 {
1357 /* Overlaps old range */
1358 g_assert (array->len > 0)do { if (array->len > 0) ; else g_assertion_message_expr
("Vnck", "../libvnck/tasklist.c", 1358, ((const char*) (__func__
)), "array->len > 0"); } while (0)
;
1359 lowest_range = n_cols * grouping_limit;
1360 g_array_index(array, int, array->len-1)(((int*) (void *) (array)->data) [(array->len-1)]) = lowest_range;
1361 }
1362 else
1363 {
1364 /* Full new range */
1365 g_array_insert_val (array, array->len, val)g_array_insert_vals (array, array->len, &(val), 1);
1366 val = n_cols * grouping_limit;
1367 g_array_insert_val (array, array->len, val)g_array_insert_vals (array, array->len, &(val), 1);
1368 lowest_range = val;
1369 }
1370
1371 last_n_cols = n_cols;
1372 }
1373 }
1374 else
1375 {
1376 if (n_rows != last_n_cols &&
1377 (tasklist->priv->grouping == VNCK_TASKLIST_AUTO_GROUP ||
1378 ungrouped_class_groups == NULL((void*)0)))
1379 {
1380 val = n_rows * tasklist->priv->max_button_height;
1381 if (val >= lowest_range)
1382 {
1383 /* Overlaps old range */
1384 g_assert (array->len > 0)do { if (array->len > 0) ; else g_assertion_message_expr
("Vnck", "../libvnck/tasklist.c", 1384, ((const char*) (__func__
)), "array->len > 0"); } while (0)
;
1385 lowest_range = n_rows * grouping_limit;
1386 g_array_index (array, int, array->len-1)(((int*) (void *) (array)->data) [(array->len-1)]) = lowest_range;
1387 }
1388 else
1389 {
1390 /* Full new range */
1391 g_array_insert_val (array, array->len, val)g_array_insert_vals (array, array->len, &(val), 1);
1392 val = n_rows * grouping_limit;
1393 g_array_insert_val (array, array->len, val)g_array_insert_vals (array, array->len, &(val), 1);
1394 lowest_range = val;
1395 }
1396
1397 last_n_cols = n_rows;
1398 }
1399 }
1400 }
1401
1402 g_list_free (ungrouped_class_groups);
1403
1404 /* Always let you go down to a zero size: */
1405 if (array->len > 0)
1406 {
1407 g_array_index(array, int, array->len-1)(((int*) (void *) (array)->data) [(array->len-1)]) = 0;
1408 }
1409 else
1410 {
1411 val = 0;
1412 g_array_insert_val (array, 0, val)g_array_insert_vals (array, 0, &(val), 1);
1413 g_array_insert_val (array, 0, val)g_array_insert_vals (array, 0, &(val), 1);
1414 }
1415
1416 if (tasklist->priv->size_hints)
1417 g_free (tasklist->priv->size_hints);
1418
1419 tasklist->priv->size_hints_len = array->len;
1420 tasklist->priv->size_hints = (int *)g_array_free (array, FALSE(0));
1421
1422 if (tasklist->priv->orientation == CTK_ORIENTATION_HORIZONTAL)
1423 {
1424 requisition->width = tasklist->priv->size_hints[0];
1425 requisition->height = fake_allocation.height;
1426 }
1427 else
1428 {
1429 requisition->width = fake_allocation.width;
1430 requisition->height = tasklist->priv->size_hints[0];
1431 }
1432}
1433
1434static void
1435vnck_tasklist_get_preferred_width (CtkWidget *widget,
1436 int *minimum_width,
1437 int *natural_width)
1438{
1439 CtkRequisition req;
1440
1441 vnck_tasklist_size_request (widget, &req);
1442
1443 *minimum_width = *natural_width = req.width;
1444}
1445
1446static void
1447vnck_tasklist_get_preferred_height (CtkWidget *widget,
1448 int *minimum_height,
1449 int *natural_height)
1450{
1451 CtkRequisition req;
1452
1453 vnck_tasklist_size_request (widget, &req);
1454
1455 *minimum_height = *natural_height = req.height;
1456}
1457
1458
1459/**
1460 * vnck_tasklist_get_size_hint_list:
1461 * @tasklist: a #VnckTasklist.
1462 * @n_elements: return location for the number of elements in the array
1463 * returned by this function. This number should always be pair.
1464 *
1465 * Since a #VnckTasklist does not have a fixed size (#VnckWindow can be grouped
1466 * when needed, for example), the standard size request mechanism in CTK+ is
1467 * not enough to announce what sizes can be used by @tasklist. The size hints
1468 * mechanism is a solution for this. See panel_applet_set_size_hints() for more
1469 * information.
1470 *
1471 * Return value: a list of size hints that can be used to allocate an
1472 * appropriate size for @tasklist.
1473 */
1474const int *
1475vnck_tasklist_get_size_hint_list (VnckTasklist *tasklist,
1476 int *n_elements)
1477{
1478 g_return_val_if_fail (VNCK_IS_TASKLIST (tasklist), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tasklist)); GType __t = ((vnck_tasklist_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Vnck", ((const char*) (__func__
)), "VNCK_IS_TASKLIST (tasklist)"); return (((void*)0)); } } while
(0)
;
1479 g_return_val_if_fail (n_elements != NULL, NULL)do { if ((n_elements != ((void*)0))) { } else { g_return_if_fail_warning
("Vnck", ((const char*) (__func__)), "n_elements != NULL"); return
(((void*)0)); } } while (0)
;
1480
1481 *n_elements = tasklist->priv->size_hints_len;
1482 return tasklist->priv->size_hints;
1483}
1484
1485static gboolean
1486task_button_queue_resize (gpointer user_data)
1487{
1488 VnckTask *task = VNCK_TASK (user_data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((vnck_task_get_type ()))))))
;
1489
1490 ctk_widget_queue_resize (task->button);
1491 task->resize_idle_id = 0;
1492
1493 return G_SOURCE_REMOVE(0);
1494}
1495
1496static void
1497vnck_task_size_allocated (CtkWidget *widget,
1498 CtkAllocation *allocation,
1499 gpointer data)
1500{
1501 VnckTask *task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
1502 CtkStyleContext *context;
1503 CtkStateFlags state;
1504 CtkBorder padding;
1505 int min_image_width;
1506 gboolean old_image_visible;
1507 gboolean old_label_visible;
1508
1509 context = ctk_widget_get_style_context (widget);
1510 state = ctk_style_context_get_state (context);
1511 ctk_style_context_get_padding (context, state, &padding);
1512
1513 min_image_width = MINI_ICON_SIZE_vnck_get_default_mini_icon_size () +
1514 padding.left + padding.right +
1515 2 * TASKLIST_BUTTON_PADDING4;
1516 old_image_visible = ctk_widget_get_visible (task->image);
1517 old_label_visible = ctk_widget_get_visible (task->label);
1518
1519 if ((allocation->width < min_image_width + 2 * TASKLIST_BUTTON_PADDING4) &&
1520 (allocation->width >= min_image_width)) {
1521 ctk_widget_show (task->image);
1522 ctk_widget_hide (task->label);
1523 } else if (allocation->width < min_image_width) {
1524 ctk_widget_hide (task->image);
1525 ctk_widget_show (task->label);
1526 } else {
1527 ctk_widget_show (task->image);
1528 ctk_widget_show (task->label);
1529 }
1530
1531 if (old_image_visible != ctk_widget_get_visible (task->image) ||
1532 old_label_visible != ctk_widget_get_visible (task->label))
1533 {
1534 if (task->resize_idle_id == 0)
1535 task->resize_idle_id = g_idle_add (task_button_queue_resize, task);
1536 }
1537}
1538
1539static void
1540vnck_tasklist_size_allocate (CtkWidget *widget,
1541 CtkAllocation *allocation)
1542{
1543 CtkAllocation child_allocation;
1544 VnckTasklist *tasklist;
1545 VnckTask *class_group_task;
1546 int n_windows;
1547 int n_startup_sequences;
1548 GList *l;
1549 int button_width;
1550 int total_width;
1551 int n_rows;
1552 int n_cols;
1553 int n_grouped_buttons;
1554 int i;
1555 gboolean score_set;
1556 GList *ungrouped_class_groups;
1557 VnckTask *win_task;
1558 GList *visible_tasks = NULL((void*)0);
1559 GList *windows_sorted = NULL((void*)0);
1560 int grouping_limit;
1561
1562 if (allocation->width <= 1 || allocation->height <= 1)
1563 {
1564 CTK_WIDGET_CLASS (vnck_tasklist_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((vnck_tasklist_parent_class)), ((ctk_widget_get_type ()))
))))
->size_allocate (widget, allocation);
1565 return;
1566 }
1567
1568 tasklist = VNCK_TASKLIST (widget)((((VnckTasklist*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((vnck_tasklist_get_type ()))))))
;
1569
1570 n_windows = g_list_length (tasklist->priv->windows);
1571 n_startup_sequences = g_list_length (tasklist->priv->startup_sequences);
1572 n_grouped_buttons = 0;
1573 ungrouped_class_groups = g_list_copy (tasklist->priv->class_groups);
1574 score_set = FALSE(0);
1575
1576 grouping_limit = MIN (tasklist->priv->grouping_limit,(((tasklist->priv->grouping_limit) < (tasklist->priv
->max_button_width)) ? (tasklist->priv->grouping_limit
) : (tasklist->priv->max_button_width))
1577 tasklist->priv->max_button_width)(((tasklist->priv->grouping_limit) < (tasklist->priv
->max_button_width)) ? (tasklist->priv->grouping_limit
) : (tasklist->priv->max_button_width))
;
1578
1579 /* Try ungrouped mode */
1580 button_width = vnck_tasklist_layout (allocation,
1581 tasklist->priv->max_button_width,
1582 tasklist->priv->max_button_height,
1583 n_startup_sequences + n_windows,
1584 tasklist->priv->orientation,
1585 &n_cols, &n_rows);
1586 while (ungrouped_class_groups != NULL((void*)0) &&
1587 ((tasklist->priv->grouping == VNCK_TASKLIST_ALWAYS_GROUP) ||
1588 ((tasklist->priv->grouping == VNCK_TASKLIST_AUTO_GROUP) &&
1589 (button_width < grouping_limit))))
1590 {
1591 if (!score_set)
1592 {
1593 vnck_tasklist_score_groups (tasklist, ungrouped_class_groups);
1594 score_set = TRUE(!(0));
1595 }
1596
1597 ungrouped_class_groups = vnck_task_get_highest_scored (ungrouped_class_groups, &class_group_task);
1598
1599 n_grouped_buttons += g_list_length (class_group_task->windows) - 1;
1600
1601 if (g_list_length (class_group_task->windows) > 1)
1602 {
1603 visible_tasks = g_list_prepend (visible_tasks, class_group_task);
1604
1605 /* Sort */
1606 class_group_task->windows = g_list_sort (class_group_task->windows,
1607 vnck_task_compare_alphabetically);
1608
1609 /* Hide all this group's windows */
1610 l = class_group_task->windows;
1611 while (l != NULL((void*)0))
1612 {
1613 win_task = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
1614
1615 ctk_widget_set_child_visible (CTK_WIDGET (win_task->button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((win_task->button)), ((ctk_widget_get_type ()))))))
, FALSE(0));
1616
1617 l = l->next;
1618 }
1619 }
1620 else
1621 {
1622 visible_tasks = g_list_prepend (visible_tasks, class_group_task->windows->data);
1623 ctk_widget_set_child_visible (CTK_WIDGET (class_group_task->button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((class_group_task->button)), ((ctk_widget_get_type ())
)))))
, FALSE(0));
1624 }
1625
1626 button_width = vnck_tasklist_layout (allocation,
1627 tasklist->priv->max_button_width,
1628 tasklist->priv->max_button_height,
1629 n_startup_sequences + n_windows - n_grouped_buttons,
1630 tasklist->priv->orientation,
1631 &n_cols, &n_rows);
1632 }
1633
1634 /* Add all ungrouped windows to visible_tasks, and hide their class groups */
1635 l = ungrouped_class_groups;
1636 while (l != NULL((void*)0))
1637 {
1638 class_group_task = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
1639
1640 visible_tasks = g_list_concat (visible_tasks, g_list_copy (class_group_task->windows));
1641 ctk_widget_set_child_visible (CTK_WIDGET (class_group_task->button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((class_group_task->button)), ((ctk_widget_get_type ())
)))))
, FALSE(0));
1642
1643 l = l->next;
1644 }
1645
1646 /* Add all windows that are ungrouped because they don't belong to any class
1647 * group */
1648 l = tasklist->priv->windows_without_class_group;
1649 while (l != NULL((void*)0))
1650 {
1651 VnckTask *task;
1652
1653 task = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
1654 visible_tasks = g_list_append (visible_tasks, task);
1655
1656 l = l->next;
1657 }
1658
1659 /* Add all startup sequences */
1660 visible_tasks = g_list_concat (visible_tasks, g_list_copy (tasklist->priv->startup_sequences));
1661
1662 /* Sort */
1663 visible_tasks = g_list_sort (visible_tasks, vnck_task_compare);
1664
1665 /* Allocate children */
1666 l = visible_tasks;
1667 i = 0;
1668 total_width = tasklist->priv->max_button_width * n_cols;
1669 total_width = MIN (total_width, allocation->width)(((total_width) < (allocation->width)) ? (total_width) :
(allocation->width))
;
1670 /* FIXME: this is obviously wrong, but if we don't this, some space that the
1671 * panel allocated to us won't have the panel popup menu, but the tasklist
1672 * popup menu */
1673 total_width = allocation->width;
1674 while (l != NULL((void*)0))
1675 {
1676 VnckTask *task = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
1677 int row = i % n_rows;
1678 int col = i / n_rows;
1679
1680 if (ctk_widget_get_direction (widget) == CTK_TEXT_DIR_RTL)
1681 col = n_cols - col - 1;
1682
1683 child_allocation.x = total_width*col / n_cols;
1684 child_allocation.y = allocation->height*row / n_rows;
1685 child_allocation.width = total_width*(col + 1) / n_cols - child_allocation.x;
1686 child_allocation.height = allocation->height*(row + 1) / n_rows - child_allocation.y;
1687 child_allocation.x += allocation->x;
1688 child_allocation.y += allocation->y;
1689
1690 ctk_widget_size_allocate (task->button, &child_allocation);
1691 ctk_widget_set_child_visible (CTK_WIDGET (task->button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), ((ctk_widget_get_type ()))))))
, TRUE(!(0)));
1692
1693 if (task->type != VNCK_TASK_STARTUP_SEQUENCE)
1694 {
1695 GList *ll;
1696
1697 /* Build sorted windows list */
1698 if (g_list_length (task->windows) > 1)
1699 windows_sorted = g_list_concat (windows_sorted,
1700 g_list_copy (task->windows));
1701 else
1702 windows_sorted = g_list_append (windows_sorted, task);
1703 task->row = row;
1704 task->col = col;
1705 for (ll = task->windows; ll; ll = ll->next)
1706 {
1707 VNCK_TASK (ll->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ll->data)), ((vnck_task_get_type ()))))))
->row = row;
1708 VNCK_TASK (ll->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ll->data)), ((vnck_task_get_type ()))))))
->col = col;
1709 }
1710 }
1711 i++;
1712 l = l->next;
1713 }
1714
1715 /* Update icon geometries. */
1716 vnck_tasklist_update_icon_geometries (tasklist, visible_tasks);
1717
1718 g_list_free (visible_tasks);
1719 g_list_free (tasklist->priv->windows);
1720 g_list_free (ungrouped_class_groups);
1721 tasklist->priv->windows = windows_sorted;
1722
1723 CTK_WIDGET_CLASS (vnck_tasklist_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((vnck_tasklist_parent_class)), ((ctk_widget_get_type ()))
))))
->size_allocate (widget,
1724 allocation);
1725}
1726
1727static void
1728foreach_tasklist (VnckTasklist *tasklist,
1729 gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
1730{
1731 vnck_tasklist_update_lists (tasklist);
1732}
1733
1734static void
1735vnck_tasklist_realize (CtkWidget *widget)
1736{
1737 VnckTasklist *tasklist;
1738 CdkScreen *cdkscreen;
1739
1740 tasklist = VNCK_TASKLIST (widget)((((VnckTasklist*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((vnck_tasklist_get_type ()))))))
;
1741
1742 cdkscreen = ctk_widget_get_screen (widget);
1743 tasklist->priv->screen = vnck_screen_get (cdk_x11_screen_get_screen_number (cdkscreen));
1744 g_assert (tasklist->priv->screen != NULL)do { if (tasklist->priv->screen != ((void*)0)) ; else g_assertion_message_expr
("Vnck", "../libvnck/tasklist.c", 1744, ((const char*) (__func__
)), "tasklist->priv->screen != NULL"); } while (0)
;
1745
1746#ifdef HAVE_STARTUP_NOTIFICATION1
1747 tasklist->priv->sn_context =
1748 sn_monitor_context_new (_vnck_screen_get_sn_display (tasklist->priv->screen),
1749 vnck_screen_get_number (tasklist->priv->screen),
1750 vnck_tasklist_sn_event,
1751 tasklist,
1752 NULL((void*)0));
1753#endif
1754
1755 (* CTK_WIDGET_CLASS (vnck_tasklist_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((vnck_tasklist_parent_class)), ((ctk_widget_get_type ()))
))))
->realize) (widget);
1756
1757 tasklist_instances = g_slist_append (tasklist_instances, tasklist);
1758 g_slist_foreach (tasklist_instances, (GFunc) foreach_tasklist, NULL((void*)0));
1759
1760 vnck_tasklist_update_lists (tasklist);
1761
1762 vnck_tasklist_connect_screen (tasklist);
1763}
1764
1765static void
1766vnck_tasklist_unrealize (CtkWidget *widget)
1767{
1768 VnckTasklist *tasklist;
1769
1770 tasklist = VNCK_TASKLIST (widget)((((VnckTasklist*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((vnck_tasklist_get_type ()))))))
;
1771
1772 vnck_tasklist_disconnect_screen (tasklist);
1773 tasklist->priv->screen = NULL((void*)0);
1774
1775#ifdef HAVE_STARTUP_NOTIFICATION1
1776 sn_monitor_context_unref (tasklist->priv->sn_context);
1777 tasklist->priv->sn_context = NULL((void*)0);
1778#endif
1779
1780 (* CTK_WIDGET_CLASS (vnck_tasklist_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((vnck_tasklist_parent_class)), ((ctk_widget_get_type ()))
))))
->unrealize) (widget);
1781
1782 tasklist_instances = g_slist_remove (tasklist_instances, tasklist);
1783 g_slist_foreach (tasklist_instances, (GFunc) foreach_tasklist, NULL((void*)0));
1784}
1785
1786static void
1787vnck_tasklist_forall (CtkContainer *container,
1788 gboolean include_internals G_GNUC_UNUSED__attribute__ ((__unused__)),
1789 CtkCallback callback,
1790 gpointer callback_data)
1791{
1792 VnckTasklist *tasklist;
1793 GList *tmp;
1794
1795 tasklist = VNCK_TASKLIST (container)((((VnckTasklist*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((vnck_tasklist_get_type ()))))))
;
1796
1797 tmp = tasklist->priv->windows;
1798 while (tmp != NULL((void*)0))
1799 {
1800 VnckTask *task = VNCK_TASK (tmp->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tmp->data)), ((vnck_task_get_type ()))))))
;
1801 tmp = tmp->next;
1802
1803 (* callback) (task->button, callback_data);
1804 }
1805
1806 tmp = tasklist->priv->class_groups;
1807 while (tmp != NULL((void*)0))
1808 {
1809 VnckTask *task = VNCK_TASK (tmp->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tmp->data)), ((vnck_task_get_type ()))))))
;
1810 tmp = tmp->next;
1811
1812 (* callback) (task->button, callback_data);
1813 }
1814
1815 tmp = tasklist->priv->startup_sequences;
1816 while (tmp != NULL((void*)0))
1817 {
1818 VnckTask *task = VNCK_TASK (tmp->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tmp->data)), ((vnck_task_get_type ()))))))
;
1819 tmp = tmp->next;
1820
1821 (* callback) (task->button, callback_data);
1822 }
1823}
1824
1825static void
1826vnck_tasklist_remove (CtkContainer *container,
1827 CtkWidget *widget)
1828{
1829 VnckTasklist *tasklist;
1830 GList *tmp;
1831
1832 g_return_if_fail (VNCK_IS_TASKLIST (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = ((vnck_tasklist_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Vnck", ((const char*) (__func__
)), "VNCK_IS_TASKLIST (container)"); return; } } while (0)
;
1833 g_return_if_fail (widget != NULL)do { if ((widget != ((void*)0))) { } else { g_return_if_fail_warning
("Vnck", ((const char*) (__func__)), "widget != NULL"); return
; } } while (0)
;
1834
1835 tasklist = VNCK_TASKLIST (container)((((VnckTasklist*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((vnck_tasklist_get_type ()))))))
;
1836
1837 /* it's safer to handle windows_without_class_group before windows */
1838 tmp = tasklist->priv->windows_without_class_group;
1839 while (tmp != NULL((void*)0))
1840 {
1841 VnckTask *task = VNCK_TASK (tmp->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tmp->data)), ((vnck_task_get_type ()))))))
;
1842 tmp = tmp->next;
1843
1844 if (task->button == widget)
1845 {
1846 tasklist->priv->windows_without_class_group =
1847 g_list_remove (tasklist->priv->windows_without_class_group,
1848 task);
1849 g_object_unref (task);
1850 break;
1851 }
1852 }
1853
1854 tmp = tasklist->priv->windows;
1855 while (tmp != NULL((void*)0))
1856 {
1857 VnckTask *task = VNCK_TASK (tmp->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tmp->data)), ((vnck_task_get_type ()))))))
;
1858 tmp = tmp->next;
1859
1860 if (task->button == widget)
1861 {
1862 g_hash_table_remove (tasklist->priv->win_hash,
1863 task->window);
1864 tasklist->priv->windows =
1865 g_list_remove (tasklist->priv->windows,
1866 task);
1867
1868 ctk_widget_unparent (widget);
1869 g_object_unref (task);
1870 break;
1871 }
1872 }
1873
1874 tmp = tasklist->priv->class_groups;
1875 while (tmp != NULL((void*)0))
1876 {
1877 VnckTask *task = VNCK_TASK (tmp->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tmp->data)), ((vnck_task_get_type ()))))))
;
1878 tmp = tmp->next;
1879
1880 if (task->button == widget)
1881 {
1882 g_hash_table_remove (tasklist->priv->class_group_hash,
1883 task->class_group);
1884 tasklist->priv->class_groups =
1885 g_list_remove (tasklist->priv->class_groups,
1886 task);
1887
1888 ctk_widget_unparent (widget);
1889 g_object_unref (task);
1890 break;
1891 }
1892 }
1893
1894 tmp = tasklist->priv->startup_sequences;
1895 while (tmp != NULL((void*)0))
1896 {
1897 VnckTask *task = VNCK_TASK (tmp->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tmp->data)), ((vnck_task_get_type ()))))))
;
1898 tmp = tmp->next;
1899
1900 if (task->button == widget)
1901 {
1902 tasklist->priv->startup_sequences =
1903 g_list_remove (tasklist->priv->startup_sequences,
1904 task);
1905
1906 ctk_widget_unparent (widget);
1907 g_object_unref (task);
1908 break;
1909 }
1910 }
1911
1912 ctk_widget_queue_resize (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
);
1913}
1914
1915static void
1916vnck_tasklist_connect_screen (VnckTasklist *tasklist)
1917{
1918 GList *windows;
1919 guint *c;
1920 int i;
1921 VnckScreen *screen;
1922
1923 g_return_if_fail (tasklist->priv->screen != NULL)do { if ((tasklist->priv->screen != ((void*)0))) { } else
{ g_return_if_fail_warning ("Vnck", ((const char*) (__func__
)), "tasklist->priv->screen != NULL"); return; } } while
(0)
;
1924
1925 screen = tasklist->priv->screen;
1926
1927 i = 0;
1928 c = tasklist->priv->screen_connections;
1929
1930 c [i++] = g_signal_connect_object (G_OBJECT (screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), (((GType) ((20) << (2))))))))
, "active_window_changed",
1931 G_CALLBACK (vnck_tasklist_active_window_changed)((GCallback) (vnck_tasklist_active_window_changed)),
1932 tasklist, 0);
1933 c [i++] = g_signal_connect_object (G_OBJECT (screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), (((GType) ((20) << (2))))))))
, "active_workspace_changed",
1934 G_CALLBACK (vnck_tasklist_active_workspace_changed)((GCallback) (vnck_tasklist_active_workspace_changed)),
1935 tasklist, 0);
1936 c [i++] = g_signal_connect_object (G_OBJECT (screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), (((GType) ((20) << (2))))))))
, "window_opened",
1937 G_CALLBACK (vnck_tasklist_window_added)((GCallback) (vnck_tasklist_window_added)),
1938 tasklist, 0);
1939 c [i++] = g_signal_connect_object (G_OBJECT (screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), (((GType) ((20) << (2))))))))
, "window_closed",
1940 G_CALLBACK (vnck_tasklist_window_removed)((GCallback) (vnck_tasklist_window_removed)),
1941 tasklist, 0);
1942 c [i++] = g_signal_connect_object (G_OBJECT (screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((screen)), (((GType) ((20) << (2))))))))
, "viewports_changed",
1943 G_CALLBACK (vnck_tasklist_viewports_changed)((GCallback) (vnck_tasklist_viewports_changed)),
1944 tasklist, 0);
1945
1946
1947 g_assert (i == N_SCREEN_CONNECTIONS)do { if (i == 5) ; else g_assertion_message_expr ("Vnck", "../libvnck/tasklist.c"
, 1947, ((const char*) (__func__)), "i == N_SCREEN_CONNECTIONS"
); } while (0)
;
1948
1949 windows = vnck_screen_get_windows (screen);
1950 while (windows != NULL((void*)0))
1951 {
1952 vnck_tasklist_connect_window (tasklist, windows->data);
1953 windows = windows->next;
1954 }
1955}
1956
1957static void
1958vnck_tasklist_disconnect_screen (VnckTasklist *tasklist)
1959{
1960 GList *windows;
1961 int i;
1962
1963 windows = vnck_screen_get_windows (tasklist->priv->screen);
1964 while (windows != NULL((void*)0))
1965 {
1966 vnck_tasklist_disconnect_window (tasklist, windows->data);
1967 windows = windows->next;
1968 }
1969
1970 i = 0;
1971 while (i < N_SCREEN_CONNECTIONS5)
1972 {
1973 if (tasklist->priv->screen_connections [i] != 0)
1974 g_signal_handler_disconnect (G_OBJECT (tasklist->priv->screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist->priv->screen)), (((GType) ((20) <<
(2))))))))
,
1975 tasklist->priv->screen_connections [i]);
1976
1977 tasklist->priv->screen_connections [i] = 0;
1978
1979 ++i;
1980 }
1981
1982 g_assert (i == N_SCREEN_CONNECTIONS)do { if (i == 5) ; else g_assertion_message_expr ("Vnck", "../libvnck/tasklist.c"
, 1982, ((const char*) (__func__)), "i == N_SCREEN_CONNECTIONS"
); } while (0)
;
1983
1984#ifdef HAVE_STARTUP_NOTIFICATION1
1985 if (tasklist->priv->startup_sequence_timeout != 0)
1986 {
1987 g_source_remove (tasklist->priv->startup_sequence_timeout);
1988 tasklist->priv->startup_sequence_timeout = 0;
1989 }
1990#endif
1991}
1992
1993static gboolean
1994vnck_tasklist_scroll_event (CtkWidget *widget,
1995 CdkEventScroll *event)
1996{
1997 /* use the fact that tasklist->priv->windows is sorted
1998 * see vnck_tasklist_size_allocate() */
1999 VnckTasklist *tasklist;
2000 CtkTextDirection ltr;
2001 GList *window;
2002 gint row = 0;
2003 gint col = 0;
2004
2005 tasklist = VNCK_TASKLIST (widget)((((VnckTasklist*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((vnck_tasklist_get_type ()))))))
;
2006
2007 if (!tasklist->priv->scroll_enabled)
2008 return FALSE(0);
2009
2010 window = g_list_find (tasklist->priv->windows,
2011 tasklist->priv->active_task);
2012 if (window)
2013 {
2014 row = VNCK_TASK (window->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->data)), ((vnck_task_get_type ()))))))
->row;
2015 col = VNCK_TASK (window->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->data)), ((vnck_task_get_type ()))))))
->col;
2016 }
2017 else
2018 if (tasklist->priv->activate_timeout_id)
2019 /* There is no active_task yet, but there will be one after the timeout.
2020 * It occurs if we change the active task too fast. */
2021 return TRUE(!(0));
2022
2023 ltr = (ctk_widget_get_direction (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
) != CTK_TEXT_DIR_RTL);
2024
2025 switch (event->direction)
2026 {
2027 case CDK_SCROLL_UP:
2028 if (!window)
2029 window = g_list_last (tasklist->priv->windows);
2030 else
2031 window = window->prev;
2032 break;
2033
2034 case CDK_SCROLL_DOWN:
2035 if (!window)
2036 window = tasklist->priv->windows;
2037 else
2038 window = window->next;
2039 break;
2040
2041#define TASKLIST_GET_MOST_LEFT(ltr, window, tasklist) \
2042 do \
2043 { \
2044 if (ltr) \
2045 window = tasklist->priv->windows; \
2046 else \
2047 window = g_list_last (tasklist->priv->windows); \
2048 } while (0)
2049
2050#define TASKLIST_GET_MOST_RIGHT(ltr, window, tasklist) \
2051 do \
2052 { \
2053 if (ltr) \
2054 window = g_list_last (tasklist->priv->windows); \
2055 else \
2056 window = tasklist->priv->windows; \
2057 } while (0)
2058
2059 case CDK_SCROLL_LEFT:
2060 if (!window)
2061 TASKLIST_GET_MOST_RIGHT (ltr, window, tasklist);
2062 else
2063 {
2064 /* Search the first window on the previous colomn at same row */
2065 if (ltr)
2066 {
2067 while (window && (VNCK_TASK(window->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->data)), ((vnck_task_get_type ()))))))
->row != row ||
2068 VNCK_TASK(window->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->data)), ((vnck_task_get_type ()))))))
->col != col-1))
2069 window = window->prev;
2070 }
2071 else
2072 {
2073 while (window && (VNCK_TASK(window->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->data)), ((vnck_task_get_type ()))))))
->row != row ||
2074 VNCK_TASK(window->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->data)), ((vnck_task_get_type ()))))))
->col != col-1))
2075 window = window->next;
2076 }
2077 /* If no window found, select the top/bottom left one */
2078 if (!window)
2079 TASKLIST_GET_MOST_LEFT (ltr, window, tasklist);
2080 }
2081 break;
2082
2083 case CDK_SCROLL_RIGHT:
2084 if (!window)
2085 TASKLIST_GET_MOST_LEFT (ltr, window, tasklist);
2086 else
2087 {
2088 /* Search the first window on the next colomn at same row */
2089 if (ltr)
2090 {
2091 while (window && (VNCK_TASK(window->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->data)), ((vnck_task_get_type ()))))))
->row != row ||
2092 VNCK_TASK(window->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->data)), ((vnck_task_get_type ()))))))
->col != col+1))
2093 window = window->next;
2094 }
2095 else
2096 {
2097 while (window && (VNCK_TASK(window->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->data)), ((vnck_task_get_type ()))))))
->row != row ||
2098 VNCK_TASK(window->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->data)), ((vnck_task_get_type ()))))))
->col != col+1))
2099 window = window->prev;
2100 }
2101 /* If no window found, select the top/bottom right one */
2102 if (!window)
2103 TASKLIST_GET_MOST_RIGHT (ltr, window, tasklist);
2104 }
2105 break;
2106
2107 case CDK_SCROLL_SMOOTH:
2108 window = NULL((void*)0);
2109 break;
2110
2111#undef TASKLIST_GET_MOST_LEFT
2112#undef TASKLIST_GET_MOST_RIGHT
2113
2114 default:
2115 g_assert_not_reached ()do { g_assertion_message_expr ("Vnck", "../libvnck/tasklist.c"
, 2115, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2116 }
2117
2118 if (window)
2119 vnck_tasklist_activate_task_window (window->data, event->time);
2120
2121 return TRUE(!(0));
2122}
2123
2124/**
2125 * vnck_tasklist_new:
2126 *
2127 * Creates a new #VnckTasklist. The #VnckTasklist will list #VnckWindow of the
2128 * #VnckScreen it is on.
2129 *
2130 * Return value: a newly created #VnckTasklist.
2131 */
2132CtkWidget*
2133vnck_tasklist_new (void)
2134{
2135 VnckTasklist *tasklist;
2136
2137 tasklist = g_object_new (VNCK_TYPE_TASKLIST(vnck_tasklist_get_type ()), NULL((void*)0));
2138
2139 return CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
;
2140}
2141
2142static void
2143vnck_tasklist_free_tasks (VnckTasklist *tasklist)
2144{
2145 GList *l;
2146
2147 tasklist->priv->active_task = NULL((void*)0);
2148 tasklist->priv->active_class_group = NULL((void*)0);
2149
2150 if (tasklist->priv->windows)
2151 {
2152 l = tasklist->priv->windows;
2153 while (l != NULL((void*)0))
2154 {
2155 VnckTask *task = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
2156 l = l->next;
2157 /* if we just unref the task it means we lose our ref to the
2158 * task before we unparent the button, which breaks stuff.
2159 */
2160 ctk_widget_destroy (task->button);
2161 }
2162 }
2163 g_assert (tasklist->priv->windows == NULL)do { if (tasklist->priv->windows == ((void*)0)) ; else g_assertion_message_expr
("Vnck", "../libvnck/tasklist.c", 2163, ((const char*) (__func__
)), "tasklist->priv->windows == NULL"); } while (0)
;
2164 g_assert (tasklist->priv->windows_without_class_group == NULL)do { if (tasklist->priv->windows_without_class_group ==
((void*)0)) ; else g_assertion_message_expr ("Vnck", "../libvnck/tasklist.c"
, 2164, ((const char*) (__func__)), "tasklist->priv->windows_without_class_group == NULL"
); } while (0)
;
2165 g_assert (g_hash_table_size (tasklist->priv->win_hash) == 0)do { if (g_hash_table_size (tasklist->priv->win_hash) ==
0) ; else g_assertion_message_expr ("Vnck", "../libvnck/tasklist.c"
, 2165, ((const char*) (__func__)), "g_hash_table_size (tasklist->priv->win_hash) == 0"
); } while (0)
;
2166
2167 if (tasklist->priv->class_groups)
2168 {
2169 l = tasklist->priv->class_groups;
2170 while (l != NULL((void*)0))
2171 {
2172 VnckTask *task = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
2173 l = l->next;
2174 /* if we just unref the task it means we lose our ref to the
2175 * task before we unparent the button, which breaks stuff.
2176 */
2177 ctk_widget_destroy (task->button);
2178 }
2179 }
2180
2181 g_assert (tasklist->priv->class_groups == NULL)do { if (tasklist->priv->class_groups == ((void*)0)) ; else
g_assertion_message_expr ("Vnck", "../libvnck/tasklist.c", 2181
, ((const char*) (__func__)), "tasklist->priv->class_groups == NULL"
); } while (0)
;
2182 g_assert (g_hash_table_size (tasklist->priv->class_group_hash) == 0)do { if (g_hash_table_size (tasklist->priv->class_group_hash
) == 0) ; else g_assertion_message_expr ("Vnck", "../libvnck/tasklist.c"
, 2182, ((const char*) (__func__)), "g_hash_table_size (tasklist->priv->class_group_hash) == 0"
); } while (0)
;
2183
2184 if (tasklist->priv->skipped_windows)
2185 {
2186 vnck_tasklist_free_skipped_windows (tasklist);
2187 tasklist->priv->skipped_windows = NULL((void*)0);
2188 }
2189}
2190
2191
2192/*
2193 * This function determines if a window should be included in the tasklist.
2194 */
2195static gboolean
2196tasklist_include_window_impl (VnckTasklist *tasklist,
2197 VnckWindow *win,
2198 gboolean check_for_skipped_list)
2199{
2200 VnckWorkspace *active_workspace;
2201 int x, y, w, h;
2202
2203 if (!check_for_skipped_list &&
2204 vnck_window_get_state (win) & VNCK_WINDOW_STATE_SKIP_TASKLIST)
2205 return FALSE(0);
2206
2207 if (tasklist->priv->monitor != NULL((void*)0))
2208 {
2209 CdkDisplay *display;
2210 CdkMonitor *monitor;
2211
2212 vnck_window_get_geometry (win, &x, &y, &w, &h);
2213
2214 /* Don't include the window if its center point is not on the same monitor */
2215
2216 display = cdk_display_get_default ();
2217 monitor = cdk_display_get_monitor_at_point (display, x + w / 2, y + h / 2);
2218
2219 if (monitor != tasklist->priv->monitor)
2220 return FALSE(0);
2221 }
2222
2223 /* Remainder of checks aren't relevant for checking if the window should
2224 * be in the skipped list.
2225 */
2226 if (check_for_skipped_list)
2227 return TRUE(!(0));
2228
2229 if (tasklist->priv->include_all_workspaces)
2230 return TRUE(!(0));
2231
2232 if (vnck_window_is_pinned (win))
2233 return TRUE(!(0));
2234
2235 active_workspace = vnck_screen_get_active_workspace (tasklist->priv->screen);
2236 if (active_workspace == NULL((void*)0))
2237 return TRUE(!(0));
2238
2239 if (vnck_window_or_transient_needs_attention (win))
2240 return TRUE(!(0));
2241
2242 if (active_workspace != vnck_window_get_workspace (win))
2243 return FALSE(0);
2244
2245 if (!vnck_workspace_is_virtual (active_workspace))
2246 return TRUE(!(0));
2247
2248 return vnck_window_is_in_viewport (win, active_workspace);
2249}
2250
2251static gboolean
2252tasklist_include_in_skipped_list (VnckTasklist *tasklist, VnckWindow *win)
2253{
2254 return tasklist_include_window_impl (tasklist,
2255 win,
2256 TRUE(!(0)) /* check_for_skipped_list */);
2257}
2258
2259static gboolean
2260vnck_tasklist_include_window (VnckTasklist *tasklist, VnckWindow *win)
2261{
2262 return tasklist_include_window_impl (tasklist,
2263 win,
2264 FALSE(0) /* check_for_skipped_list */);
2265}
2266
2267static void
2268vnck_tasklist_update_lists (VnckTasklist *tasklist)
2269{
2270 CdkWindow *tasklist_window;
2271 GList *windows;
2272 VnckWindow *win;
2273 VnckClassGroup *class_group;
2274 GList *l;
2275 VnckTask *win_task;
2276 VnckTask *class_group_task;
2277
2278 vnck_tasklist_free_tasks (tasklist);
2279
2280 /* vnck_tasklist_update_lists() will be called on realize */
2281 if (!ctk_widget_get_realized (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
))
2282 return;
2283
2284 tasklist_window = ctk_widget_get_window (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
2285
2286 if (tasklist_window != NULL((void*)0))
2287 {
2288 /*
2289 * only show windows from this monitor if there is more than one tasklist running
2290 */
2291 if (tasklist_instances == NULL((void*)0) || tasklist_instances->next == NULL((void*)0))
2292 {
2293 tasklist->priv->monitor = NULL((void*)0);
2294 }
2295 else
2296 {
2297 CdkDisplay *display;
2298 CdkMonitor *monitor;
2299
2300 display = cdk_display_get_default ();
2301 monitor = cdk_display_get_monitor_at_window (display, tasklist_window);
2302
2303 if (monitor != tasklist->priv->monitor)
2304 {
2305 tasklist->priv->monitor = monitor;
2306 cdk_monitor_get_geometry (monitor, &tasklist->priv->monitor_geometry);
2307 }
2308 }
2309 }
2310
2311 l = windows = vnck_screen_get_windows (tasklist->priv->screen);
2312 while (l != NULL((void*)0))
2313 {
2314 win = VNCK_WINDOW (l->data)((((VnckWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_window_get_type ()))))))
;
2315
2316 if (vnck_tasklist_include_window (tasklist, win))
2317 {
2318 win_task = vnck_task_new_from_window (tasklist, win);
2319 tasklist->priv->windows = g_list_prepend (tasklist->priv->windows, win_task);
2320 g_hash_table_insert (tasklist->priv->win_hash, win, win_task);
2321
2322 ctk_widget_set_parent (win_task->button, CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
2323 ctk_widget_show (win_task->button);
2324
2325 /* Class group */
2326
2327 class_group = vnck_window_get_class_group (win);
2328 /* don't group windows if they do not belong to any class */
2329 if (strcmp (vnck_class_group_get_id (class_group), "") != 0)
2330 {
2331 class_group_task =
2332 g_hash_table_lookup (tasklist->priv->class_group_hash,
2333 class_group);
2334
2335 if (class_group_task == NULL((void*)0))
2336 {
2337 class_group_task =
2338 vnck_task_new_from_class_group (tasklist,
2339 class_group);
2340 ctk_widget_set_parent (class_group_task->button,
2341 CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
2342 ctk_widget_show (class_group_task->button);
2343
2344 tasklist->priv->class_groups =
2345 g_list_prepend (tasklist->priv->class_groups,
2346 class_group_task);
2347 g_hash_table_insert (tasklist->priv->class_group_hash,
2348 class_group, class_group_task);
2349 }
2350
2351 class_group_task->windows =
2352 g_list_prepend (class_group_task->windows,
2353 win_task);
2354 }
2355 else
2356 {
2357 g_object_ref (win_task)((__typeof__ (win_task)) (g_object_ref) (win_task));
2358 tasklist->priv->windows_without_class_group =
2359 g_list_prepend (tasklist->priv->windows_without_class_group,
2360 win_task);
2361 }
2362 }
2363 else if (tasklist_include_in_skipped_list (tasklist, win))
2364 {
2365 skipped_window *skipped = g_new0 (skipped_window, 1)((skipped_window *) g_malloc0_n ((1), sizeof (skipped_window)
))
;
2366 skipped->window = g_object_ref (win)((__typeof__ (win)) (g_object_ref) (win));
2367 skipped->tag = g_signal_connect (G_OBJECT (win),g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((win)), (((GType) ((20) << (2))))))
))), ("state_changed"), (((GCallback) (vnck_task_state_changed
))), (tasklist), ((void*)0), (GConnectFlags) 0)
2368 "state_changed",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((win)), (((GType) ((20) << (2))))))
))), ("state_changed"), (((GCallback) (vnck_task_state_changed
))), (tasklist), ((void*)0), (GConnectFlags) 0)
2369 G_CALLBACK (vnck_task_state_changed),g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((win)), (((GType) ((20) << (2))))))
))), ("state_changed"), (((GCallback) (vnck_task_state_changed
))), (tasklist), ((void*)0), (GConnectFlags) 0)
2370 tasklist)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((win)), (((GType) ((20) << (2))))))
))), ("state_changed"), (((GCallback) (vnck_task_state_changed
))), (tasklist), ((void*)0), (GConnectFlags) 0)
;
2371 tasklist->priv->skipped_windows =
2372 g_list_prepend (tasklist->priv->skipped_windows,
2373 (gpointer) skipped);
2374 }
2375
2376 l = l->next;
2377 }
2378
2379 /* Sort the class group list */
2380 l = tasklist->priv->class_groups;
2381 while (l)
2382 {
2383 class_group_task = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
2384
2385 class_group_task->windows = g_list_sort (class_group_task->windows, vnck_task_compare);
2386
2387 /* so the number of windows in the task gets reset on the
2388 * task label
2389 */
2390 vnck_task_update_visible_state (class_group_task);
2391
2392 l = l->next;
2393 }
2394
2395 /* since we cleared active_window we need to reset it */
2396 vnck_tasklist_active_window_changed (tasklist->priv->screen, NULL((void*)0), tasklist);
2397
2398 ctk_widget_queue_resize (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
2399}
2400
2401static void
2402vnck_tasklist_change_active_task (VnckTasklist *tasklist, VnckTask *active_task)
2403{
2404 if (active_task &&
2405 active_task == tasklist->priv->active_task)
2406 return;
2407
2408 g_assert (active_task == NULL ||do { if (active_task == ((void*)0) || active_task->type !=
VNCK_TASK_STARTUP_SEQUENCE) ; else g_assertion_message_expr (
"Vnck", "../libvnck/tasklist.c", 2409, ((const char*) (__func__
)), "active_task == NULL || active_task->type != VNCK_TASK_STARTUP_SEQUENCE"
); } while (0)
2409 active_task->type != VNCK_TASK_STARTUP_SEQUENCE)do { if (active_task == ((void*)0) || active_task->type !=
VNCK_TASK_STARTUP_SEQUENCE) ; else g_assertion_message_expr (
"Vnck", "../libvnck/tasklist.c", 2409, ((const char*) (__func__
)), "active_task == NULL || active_task->type != VNCK_TASK_STARTUP_SEQUENCE"
); } while (0)
;
2410
2411 if (tasklist->priv->active_task)
2412 {
2413 tasklist->priv->active_task->really_toggling = TRUE(!(0));
2414 ctk_toggle_button_set_active (CTK_TOGGLE_BUTTON (tasklist->priv->active_task->button)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist->priv->active_task->button)), ((ctk_toggle_button_get_type
()))))))
,
2415 FALSE(0));
2416 tasklist->priv->active_task->really_toggling = FALSE(0);
2417 }
2418
2419 tasklist->priv->active_task = active_task;
2420
2421 if (tasklist->priv->active_task)
2422 {
2423 tasklist->priv->active_task->really_toggling = TRUE(!(0));
2424 ctk_toggle_button_set_active (CTK_TOGGLE_BUTTON (tasklist->priv->active_task->button)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist->priv->active_task->button)), ((ctk_toggle_button_get_type
()))))))
,
2425 TRUE(!(0)));
2426 tasklist->priv->active_task->really_toggling = FALSE(0);
2427 }
2428
2429 if (active_task)
2430 {
2431 active_task = g_hash_table_lookup (tasklist->priv->class_group_hash,
2432 active_task->class_group);
2433
2434 if (active_task &&
2435 active_task == tasklist->priv->active_class_group)
2436 return;
2437
2438 if (tasklist->priv->active_class_group)
2439 {
2440 tasklist->priv->active_class_group->really_toggling = TRUE(!(0));
2441 ctk_toggle_button_set_active (CTK_TOGGLE_BUTTON (tasklist->priv->active_class_group->button)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist->priv->active_class_group->button)), (
(ctk_toggle_button_get_type ()))))))
,
2442 FALSE(0));
2443 tasklist->priv->active_class_group->really_toggling = FALSE(0);
2444 }
2445
2446 tasklist->priv->active_class_group = active_task;
2447
2448 if (tasklist->priv->active_class_group)
2449 {
2450 tasklist->priv->active_class_group->really_toggling = TRUE(!(0));
2451 ctk_toggle_button_set_active (CTK_TOGGLE_BUTTON (tasklist->priv->active_class_group->button)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist->priv->active_class_group->button)), (
(ctk_toggle_button_get_type ()))))))
,
2452 TRUE(!(0)));
2453 tasklist->priv->active_class_group->really_toggling = FALSE(0);
2454 }
2455 }
2456}
2457
2458static void
2459vnck_tasklist_update_icon_geometries (VnckTasklist *tasklist G_GNUC_UNUSED__attribute__ ((__unused__)),
2460 GList *visible_tasks)
2461{
2462 gint x, y, width, height;
2463 GList *l1;
2464
2465 for (l1 = visible_tasks; l1; l1 = l1->next) {
2466 VnckTask *task = VNCK_TASK (l1->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l1->data)), ((vnck_task_get_type ()))))))
;
2467 CtkAllocation allocation;
2468
2469 if (!ctk_widget_get_realized (task->button))
2470 continue;
2471
2472 /* Let's cheat with some internal knowledge of CtkButton: in a
2473 * CtkButton, the window is the same as the parent window. So
2474 * to know the position of the widget, we should use the
2475 * the position of the parent window and the allocation information. */
2476
2477 ctk_widget_get_allocation (task->button, &allocation);
2478
2479 cdk_window_get_origin (ctk_widget_get_parent_window (task->button),
2480 &x, &y);
2481
2482 x += allocation.x;
2483 y += allocation.y;
2484 width = allocation.width;
2485 height = allocation.height;
2486
2487 if (task->window)
2488 vnck_window_set_icon_geometry (task->window,
2489 x, y, width, height);
2490 else {
2491 GList *l2;
2492
2493 for (l2 = task->windows; l2; l2 = l2->next) {
2494 VnckTask *win_task = VNCK_TASK (l2->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l2->data)), ((vnck_task_get_type ()))))))
;
2495
2496 g_assert (win_task->window)do { if (win_task->window) ; else g_assertion_message_expr
("Vnck", "../libvnck/tasklist.c", 2496, ((const char*) (__func__
)), "win_task->window"); } while (0)
;
2497
2498 vnck_window_set_icon_geometry (win_task->window,
2499 x, y, width, height);
2500 }
2501 }
2502 }
2503}
2504
2505static void
2506vnck_tasklist_active_window_changed (VnckScreen *screen,
2507 VnckWindow *previous_window G_GNUC_UNUSED__attribute__ ((__unused__)),
2508 VnckTasklist *tasklist)
2509{
2510 VnckWindow *active_window;
2511 VnckWindow *initial_window;
2512 VnckTask *active_task = NULL((void*)0);
2513
2514 /* FIXME: check for group modal window */
2515 initial_window = active_window = vnck_screen_get_active_window (screen);
2516 active_task = g_hash_table_lookup (tasklist->priv->win_hash, active_window);
2517 while (active_window && !active_task)
2518 {
2519 active_window = vnck_window_get_transient (active_window);
2520 active_task = g_hash_table_lookup (tasklist->priv->win_hash,
2521 active_window);
2522 /* Check for transient cycles */
2523 if (active_window == initial_window)
2524 break;
2525 }
2526
2527 vnck_tasklist_change_active_task (tasklist, active_task);
2528}
2529
2530static void
2531vnck_tasklist_active_workspace_changed (VnckScreen *screen G_GNUC_UNUSED__attribute__ ((__unused__)),
2532 VnckWorkspace *previous_workspace G_GNUC_UNUSED__attribute__ ((__unused__)),
2533 VnckTasklist *tasklist)
2534{
2535 vnck_tasklist_update_lists (tasklist);
2536 ctk_widget_queue_resize (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
2537}
2538
2539static void
2540vnck_tasklist_window_changed_workspace (VnckWindow *window,
2541 VnckTasklist *tasklist)
2542{
2543 VnckWorkspace *active_ws;
2544 VnckWorkspace *window_ws;
2545 gboolean need_update;
2546 GList *l;
2547
2548 active_ws = vnck_screen_get_active_workspace (tasklist->priv->screen);
2549 window_ws = vnck_window_get_workspace (window);
2550
2551 if (!window_ws)
2552 return;
2553
2554 need_update = FALSE(0);
2555
2556 if (active_ws == window_ws)
2557 need_update = TRUE(!(0));
2558
2559 l = tasklist->priv->windows;
2560 while (!need_update && l != NULL((void*)0))
2561 {
2562 VnckTask *task = l->data;
2563
2564 if (task->type == VNCK_TASK_WINDOW &&
2565 task->window == window)
2566 need_update = TRUE(!(0));
2567
2568 l = l->next;
2569 }
2570
2571 if (need_update)
2572 {
2573 vnck_tasklist_update_lists (tasklist);
2574 ctk_widget_queue_resize (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
2575 }
2576}
2577
2578static gboolean
2579do_vnck_tasklist_update_lists (gpointer data)
2580{
2581 VnckTasklist *tasklist = VNCK_TASKLIST (data)((((VnckTasklist*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_tasklist_get_type ()))))))
;
2582
2583 tasklist->priv->idle_callback_tag = 0;
2584
2585 vnck_tasklist_update_lists (tasklist);
2586
2587 return FALSE(0);
2588}
2589
2590static void
2591vnck_tasklist_window_changed_geometry (VnckWindow *window,
2592 VnckTasklist *tasklist)
2593{
2594 CdkWindow *tasklist_window;
2595 VnckTask *win_task;
2596 gboolean show;
2597 gboolean monitor_changed;
2598 int x, y, w, h;
2599
2600 if (tasklist->priv->idle_callback_tag != 0)
2601 return;
2602
2603 tasklist_window = ctk_widget_get_window (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
2604
2605 /*
2606 * If the (parent of the) tasklist itself skips
2607 * the tasklist, we need an extra check whether
2608 * the tasklist itself possibly changed monitor.
2609 */
2610 monitor_changed = FALSE(0);
2611 if (tasklist->priv->monitor != NULL((void*)0) &&
2612 (vnck_window_get_state (window) & VNCK_WINDOW_STATE_SKIP_TASKLIST) &&
2613 tasklist_window != NULL((void*)0))
2614 {
2615 /* Do the extra check only if there is a suspect of a monitor change (= this window is off monitor) */
2616 vnck_window_get_geometry (window, &x, &y, &w, &h);
2617 if (!POINT_IN_RECT (x + w / 2, y + h / 2, tasklist->priv->monitor_geometry)((x + w / 2) >= (tasklist->priv->monitor_geometry).x
&& (x + w / 2) < ((tasklist->priv->monitor_geometry
).x + (tasklist->priv->monitor_geometry).width) &&
(y + h / 2) >= (tasklist->priv->monitor_geometry).y
&& (y + h / 2) < ((tasklist->priv->monitor_geometry
).y + (tasklist->priv->monitor_geometry).height))
)
2618 {
2619 CdkDisplay *display;
2620 CdkMonitor *monitor;
2621
2622 display = cdk_display_get_default ();
2623 monitor = cdk_display_get_monitor_at_window (display, tasklist_window);
2624
2625 monitor_changed = (monitor != tasklist->priv->monitor);
2626 }
2627 }
2628
2629 /*
2630 * We want to re-generate the task list if
2631 * the window is shown but shouldn't be or
2632 * the window isn't shown but should be or
2633 * the tasklist itself changed monitor.
2634 */
2635 win_task = g_hash_table_lookup (tasklist->priv->win_hash, window);
2636 show = vnck_tasklist_include_window (tasklist, window);
2637 if (((win_task == NULL((void*)0) && !show) || (win_task != NULL((void*)0) && show)) &&
2638 !monitor_changed)
2639 return;
2640
2641 /* Don't keep any stale references */
2642 ctk_widget_queue_draw (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
2643
2644 tasklist->priv->idle_callback_tag = g_idle_add (do_vnck_tasklist_update_lists, tasklist);
2645}
2646
2647static void
2648vnck_tasklist_connect_window (VnckTasklist *tasklist,
2649 VnckWindow *window)
2650{
2651 g_signal_connect_object (window, "workspace_changed",
2652 G_CALLBACK (vnck_tasklist_window_changed_workspace)((GCallback) (vnck_tasklist_window_changed_workspace)),
2653 tasklist, 0);
2654 g_signal_connect_object (window, "geometry_changed",
2655 G_CALLBACK (vnck_tasklist_window_changed_geometry)((GCallback) (vnck_tasklist_window_changed_geometry)),
2656 tasklist, 0);
2657}
2658
2659static void
2660vnck_tasklist_disconnect_window (VnckTasklist *tasklist,
2661 VnckWindow *window)
2662{
2663 g_signal_handlers_disconnect_by_func (window,g_signal_handlers_disconnect_matched ((window), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (vnck_tasklist_window_changed_workspace), (tasklist))
2664 vnck_tasklist_window_changed_workspace,g_signal_handlers_disconnect_matched ((window), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (vnck_tasklist_window_changed_workspace), (tasklist))
2665 tasklist)g_signal_handlers_disconnect_matched ((window), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (vnck_tasklist_window_changed_workspace), (tasklist))
;
2666 g_signal_handlers_disconnect_by_func (window,g_signal_handlers_disconnect_matched ((window), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (vnck_tasklist_window_changed_geometry), (tasklist))
2667 vnck_tasklist_window_changed_geometry,g_signal_handlers_disconnect_matched ((window), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (vnck_tasklist_window_changed_geometry), (tasklist))
2668 tasklist)g_signal_handlers_disconnect_matched ((window), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (vnck_tasklist_window_changed_geometry), (tasklist))
;
2669}
2670
2671static void
2672vnck_tasklist_window_added (VnckScreen *screen G_GNUC_UNUSED__attribute__ ((__unused__)),
2673 VnckWindow *win,
2674 VnckTasklist *tasklist)
2675{
2676#ifdef HAVE_STARTUP_NOTIFICATION1
2677 vnck_tasklist_check_end_sequence (tasklist, win);
2678#endif
2679
2680 vnck_tasklist_connect_window (tasklist, win);
2681
2682 vnck_tasklist_update_lists (tasklist);
2683 ctk_widget_queue_resize (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
2684}
2685
2686static void
2687vnck_tasklist_window_removed (VnckScreen *screen G_GNUC_UNUSED__attribute__ ((__unused__)),
2688 VnckWindow *win G_GNUC_UNUSED__attribute__ ((__unused__)),
2689 VnckTasklist *tasklist)
2690{
2691 vnck_tasklist_update_lists (tasklist);
2692 ctk_widget_queue_resize (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
2693}
2694
2695static void
2696vnck_tasklist_viewports_changed (VnckScreen *screen G_GNUC_UNUSED__attribute__ ((__unused__)),
2697 VnckTasklist *tasklist)
2698{
2699 vnck_tasklist_update_lists (tasklist);
2700 ctk_widget_queue_resize (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
2701}
2702
2703static gboolean
2704vnck_tasklist_change_active_timeout (gpointer data)
2705{
2706 VnckTasklist *tasklist = VNCK_TASKLIST (data)((((VnckTasklist*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_tasklist_get_type ()))))))
;
2707
2708 tasklist->priv->activate_timeout_id = 0;
2709
2710 vnck_tasklist_active_window_changed (tasklist->priv->screen, NULL((void*)0), tasklist);
2711
2712 return FALSE(0);
2713}
2714
2715static void
2716vnck_task_menu_activated (CtkMenuItem *menu_item G_GNUC_UNUSED__attribute__ ((__unused__)),
2717 gpointer data)
2718{
2719 VnckTask *task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
2720
2721 /* This is an "activate" callback function so ctk_get_current_event_time()
2722 * will suffice.
2723 */
2724 vnck_tasklist_activate_task_window (task, ctk_get_current_event_time ());
2725}
2726
2727static void
2728vnck_tasklist_activate_next_in_class_group (VnckTask *task,
2729 guint32 timestamp)
2730{
2731 VnckTask *activate_task;
2732 gboolean activate_next;
2733 GList *l;
2734
2735 activate_task = NULL((void*)0);
2736 activate_next = FALSE(0);
2737
2738 l = task->windows;
2739 while (l)
2740 {
2741 VnckTask *tmp;
2742
2743 tmp = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
2744
2745 if (vnck_window_is_most_recently_activated (tmp->window))
2746 activate_next = TRUE(!(0));
2747 else if (activate_next)
2748 {
2749 activate_task = tmp;
2750 break;
2751 }
2752
2753 l = l->next;
2754 }
2755
2756 /* no task in this group is active, or only the last one => activate
2757 * the first task */
2758 if (!activate_task && task->windows)
2759 activate_task = VNCK_TASK (task->windows->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->windows->data)), ((vnck_task_get_type ()))))
))
;
2760
2761 if (activate_task)
2762 {
2763 task->was_active = FALSE(0);
2764 vnck_tasklist_activate_task_window (activate_task, timestamp);
2765 }
2766}
2767
2768static void
2769vnck_tasklist_activate_task_window (VnckTask *task,
2770 guint32 timestamp)
2771{
2772 VnckTasklist *tasklist;
2773 VnckWindowState state;
2774 VnckWorkspace *active_ws;
2775 VnckWorkspace *window_ws;
2776
2777 tasklist = task->tasklist;
2778
2779 if (task->window == NULL((void*)0))
2780 return;
2781
2782 state = vnck_window_get_state (task->window);
2783
2784 active_ws = vnck_screen_get_active_workspace (tasklist->priv->screen);
2785 window_ws = vnck_window_get_workspace (task->window);
2786
2787 if (state & VNCK_WINDOW_STATE_MINIMIZED)
2788 {
2789 if (window_ws &&
2790 active_ws != window_ws &&
2791 !tasklist->priv->switch_workspace_on_unminimize)
2792 vnck_workspace_activate (window_ws, timestamp);
2793
2794 vnck_window_activate_transient (task->window, timestamp);
2795 }
2796 else
2797 {
2798 if ((task->was_active ||
2799 vnck_window_transient_is_most_recently_activated (task->window)) &&
2800 (!window_ws || active_ws == window_ws))
2801 {
2802 task->was_active = FALSE(0);
2803 vnck_window_minimize (task->window);
2804 return;
2805 }
2806 else
2807 {
2808 /* FIXME: THIS IS SICK AND WRONG AND BUGGY. See the end of
2809 * http://mail.gnome.org/archives/wm-spec-list/2005-July/msg00032.html
2810 * There should only be *one* activate call.
2811 */
2812 if (window_ws)
2813 vnck_workspace_activate (window_ws, timestamp);
2814
2815 vnck_window_activate_transient (task->window, timestamp);
2816 }
2817 }
2818
2819
2820 if (tasklist->priv->activate_timeout_id)
2821 g_source_remove (tasklist->priv->activate_timeout_id);
2822
2823 tasklist->priv->activate_timeout_id =
2824 g_timeout_add (500, &vnck_tasklist_change_active_timeout, tasklist);
2825
2826 vnck_tasklist_change_active_task (tasklist, task);
2827}
2828
2829static void
2830vnck_task_close_all (CtkMenuItem *menu_item G_GNUC_UNUSED__attribute__ ((__unused__)),
2831 gpointer data)
2832{
2833 VnckTask *task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
2834 GList *l;
2835
2836 l = task->windows;
2837 while (l)
2838 {
2839 VnckTask *child = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
2840 vnck_window_close (child->window, ctk_get_current_event_time ());
2841 l = l->next;
2842 }
2843}
2844
2845static void
2846vnck_task_unminimize_all (CtkMenuItem *menu_item G_GNUC_UNUSED__attribute__ ((__unused__)),
2847 gpointer data)
2848{
2849 VnckTask *task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
2850 GList *l;
2851
2852 l = task->windows;
2853 while (l)
2854 {
2855 VnckTask *child = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
2856 /* This is inside an activate callback, so ctk_get_current_event_time()
2857 * will work.
2858 */
2859 vnck_window_unminimize (child->window, ctk_get_current_event_time ());
2860 l = l->next;
2861 }
2862}
2863
2864static void
2865vnck_task_minimize_all (CtkMenuItem *menu_item G_GNUC_UNUSED__attribute__ ((__unused__)),
2866 gpointer data)
2867{
2868 VnckTask *task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
2869 GList *l;
2870
2871 l = task->windows;
2872 while (l)
2873 {
2874 VnckTask *child = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
2875 vnck_window_minimize (child->window);
2876 l = l->next;
2877 }
2878}
2879
2880static void
2881vnck_task_unmaximize_all (CtkMenuItem *menu_item G_GNUC_UNUSED__attribute__ ((__unused__)),
2882 gpointer data)
2883{
2884 VnckTask *task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
2885 GList *l;
2886
2887 l = task->windows;
2888 while (l)
2889 {
2890 VnckTask *child = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
2891 vnck_window_unmaximize (child->window);
2892 l = l->next;
2893 }
2894}
2895
2896static void
2897vnck_task_maximize_all (CtkMenuItem *menu_item G_GNUC_UNUSED__attribute__ ((__unused__)),
2898 gpointer data)
2899{
2900 VnckTask *task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
2901 GList *l;
2902
2903 l = task->windows;
2904 while (l)
2905 {
2906 VnckTask *child = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
2907 vnck_window_maximize (child->window);
2908 l = l->next;
2909 }
2910}
2911
2912static void
2913vnck_task_popup_menu (VnckTask *task,
2914 gboolean action_submenu)
2915{
2916 CtkWidget *menu;
2917 VnckTask *win_task;
2918 char *text;
2919 GdkPixbuf *pixbuf;
2920 CtkWidget *menu_item;
2921 GList *l, *list;
2922
2923 g_return_if_fail (task->type == VNCK_TASK_CLASS_GROUP)do { if ((task->type == VNCK_TASK_CLASS_GROUP)) { } else {
g_return_if_fail_warning ("Vnck", ((const char*) (__func__))
, "task->type == VNCK_TASK_CLASS_GROUP"); return; } } while
(0)
;
2924
2925 if (task->class_group == NULL((void*)0))
2926 return;
2927
2928 if (task->menu == NULL((void*)0))
2929 {
2930 task->menu = ctk_menu_new ();
2931 g_object_ref_sink (task->menu)((__typeof__ (task->menu)) (g_object_ref_sink) (task->menu
))
;
2932 }
2933
2934 menu = task->menu;
2935
2936 /* Remove old menu content */
2937 list = ctk_container_get_children (CTK_CONTAINER (menu)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_container_get_type ()))))))
);
2938 l = list;
2939 while (l)
2940 {
2941 CtkWidget *child = CTK_WIDGET (l->data)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((ctk_widget_get_type ()))))))
;
2942 ctk_container_remove (CTK_CONTAINER (menu)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_container_get_type ()))))))
, child);
2943 l = l->next;
2944 }
2945 g_list_free (list);
2946
2947 l = task->windows;
2948 while (l)
2949 {
2950 win_task = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
2951
2952 text = vnck_task_get_text (win_task, TRUE(!(0)), TRUE(!(0)));
2953 menu_item = vnck_image_menu_item_new_with_label (text);
2954 g_free (text);
2955
2956 if (vnck_task_get_needs_attention (win_task))
2957 _make_ctk_label_bold (CTK_LABEL (ctk_bin_get_child (CTK_BIN (menu_item)))((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_bin_get_child (((((CtkBin*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((menu_item)), ((ctk_bin_get_type ()))))))
))), ((ctk_label_get_type ()))))))
);
2958
2959 text = vnck_task_get_text (win_task, FALSE(0), FALSE(0));
2960 ctk_widget_set_tooltip_text (menu_item, text);
2961 g_free (text);
2962
2963 pixbuf = vnck_task_get_icon (win_task);
2964 if (pixbuf)
2965 {
2966 VnckImageMenuItem *item;
2967
2968 item = VNCK_IMAGE_MENU_ITEM (menu_item);
2969
2970 vnck_image_menu_item_set_image_from_icon_pixbuf (item, pixbuf);
2971 g_object_unref (pixbuf);
2972 }
2973
2974 ctk_widget_show (menu_item);
2975
2976 if (action_submenu)
2977 ctk_menu_item_set_submenu (CTK_MENU_ITEM (menu_item)((((CtkMenuItem*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu_item)), ((ctk_menu_item_get_type ()))))))
,
2978 vnck_action_menu_new (win_task->window));
2979 else
2980 {
2981 static const CtkTargetEntry targets[] = {
2982 { (gchar *) "application/x-vnck-window-id", 0, 0 }
2983 };
2984
2985 g_signal_connect_object (G_OBJECT (menu_item)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu_item)), (((GType) ((20) << (2))))))))
, "activate",
2986 G_CALLBACK (vnck_task_menu_activated)((GCallback) (vnck_task_menu_activated)),
2987 G_OBJECT (win_task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((win_task)), (((GType) ((20) << (2))))))))
,
2988 0);
2989
2990
2991 ctk_drag_source_set (menu_item, CDK_BUTTON1_MASK,
2992 targets, 1, CDK_ACTION_MOVE);
2993 g_signal_connect_object (G_OBJECT(menu_item)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu_item)), (((GType) ((20) << (2))))))))
, "drag_begin",
2994 G_CALLBACK (vnck_task_drag_begin)((GCallback) (vnck_task_drag_begin)),
2995 G_OBJECT (win_task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((win_task)), (((GType) ((20) << (2))))))))
,
2996 0);
2997 g_signal_connect_object (G_OBJECT(menu_item)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu_item)), (((GType) ((20) << (2))))))))
, "drag_end",
2998 G_CALLBACK (vnck_task_drag_end)((GCallback) (vnck_task_drag_end)),
2999 G_OBJECT (win_task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((win_task)), (((GType) ((20) << (2))))))))
,
3000 0);
3001 g_signal_connect_object (G_OBJECT(menu_item)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu_item)), (((GType) ((20) << (2))))))))
, "drag_data_get",
3002 G_CALLBACK (vnck_task_drag_data_get)((GCallback) (vnck_task_drag_data_get)),
3003 G_OBJECT (win_task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((win_task)), (((GType) ((20) << (2))))))))
,
3004 0);
3005 }
3006
3007 ctk_menu_shell_append (CTK_MENU_SHELL (menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_shell_get_type ()))))))
, menu_item);
3008
3009 l = l->next;
3010 }
3011
3012 /* In case of Right click, show Minimize All, Unminimize All, Close All*/
3013 if (action_submenu)
3014 {
3015 CtkWidget *separator;
3016
3017 separator = ctk_separator_menu_item_new ();
3018 ctk_widget_show (separator);
3019 ctk_menu_shell_append (CTK_MENU_SHELL (menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_shell_get_type ()))))))
, separator);
3020
3021 menu_item = ctk_menu_item_new_with_mnemonic (_("Mi_nimize All")((char *) g_dgettext ("libvnck-3.0", "Mi_nimize All")));
3022 ctk_widget_show (menu_item);
3023 ctk_menu_shell_append (CTK_MENU_SHELL (menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_shell_get_type ()))))))
, menu_item);
3024 g_signal_connect_object (G_OBJECT (menu_item)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu_item)), (((GType) ((20) << (2))))))))
, "activate",
3025 G_CALLBACK (vnck_task_minimize_all)((GCallback) (vnck_task_minimize_all)),
3026 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3027 0);
3028
3029 menu_item = ctk_menu_item_new_with_mnemonic (_("Un_minimize All")((char *) g_dgettext ("libvnck-3.0", "Un_minimize All")));
3030 ctk_widget_show (menu_item);
3031 ctk_menu_shell_append (CTK_MENU_SHELL (menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_shell_get_type ()))))))
, menu_item);
3032 g_signal_connect_object (G_OBJECT (menu_item)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu_item)), (((GType) ((20) << (2))))))))
, "activate",
3033 G_CALLBACK (vnck_task_unminimize_all)((GCallback) (vnck_task_unminimize_all)),
3034 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3035 0);
3036
3037 menu_item = ctk_menu_item_new_with_mnemonic (_("Ma_ximize All")((char *) g_dgettext ("libvnck-3.0", "Ma_ximize All")));
3038 ctk_widget_show (menu_item);
3039 ctk_menu_shell_append (CTK_MENU_SHELL (menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_shell_get_type ()))))))
, menu_item);
3040 g_signal_connect_object (G_OBJECT (menu_item)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu_item)), (((GType) ((20) << (2))))))))
, "activate",
3041 G_CALLBACK (vnck_task_maximize_all)((GCallback) (vnck_task_maximize_all)),
3042 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3043 0);
3044
3045 menu_item = ctk_menu_item_new_with_mnemonic (_("_Unmaximize All")((char *) g_dgettext ("libvnck-3.0", "_Unmaximize All")));
3046 ctk_widget_show (menu_item);
3047 ctk_menu_shell_append (CTK_MENU_SHELL (menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_shell_get_type ()))))))
, menu_item);
3048 g_signal_connect_object (G_OBJECT (menu_item)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu_item)), (((GType) ((20) << (2))))))))
, "activate",
3049 G_CALLBACK (vnck_task_unmaximize_all)((GCallback) (vnck_task_unmaximize_all)),
3050 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3051 0);
3052
3053 separator = ctk_separator_menu_item_new ();
3054 ctk_widget_show (separator);
3055 ctk_menu_shell_append (CTK_MENU_SHELL (menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_shell_get_type ()))))))
, separator);
3056
3057 menu_item = ctk_menu_item_new_with_mnemonic(_("_Close All")((char *) g_dgettext ("libvnck-3.0", "_Close All")));
3058 ctk_widget_show (menu_item);
3059 ctk_menu_shell_append (CTK_MENU_SHELL (menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_shell_get_type ()))))))
, menu_item);
3060 g_signal_connect_object (G_OBJECT (menu_item)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu_item)), (((GType) ((20) << (2))))))))
, "activate",
3061 G_CALLBACK (vnck_task_close_all)((GCallback) (vnck_task_close_all)),
3062 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3063 0);
3064 }
3065
3066 ctk_menu_set_screen (CTK_MENU (menu)((((CtkMenu*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_get_type ()))))))
,
3067 _vnck_screen_get_cdk_screen (task->tasklist->priv->screen));
3068
3069 ctk_widget_show (menu);
3070 ctk_menu_popup_at_widget (CTK_MENU (menu)((((CtkMenu*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_get_type ()))))))
, task->button,
3071 CDK_GRAVITY_SOUTH_WEST,
3072 CDK_GRAVITY_NORTH_WEST,
3073 NULL((void*)0));
3074}
3075
3076static void
3077vnck_task_button_toggled (CtkButton *button,
3078 VnckTask *task)
3079{
3080 /* Did we really want to change the state of the togglebutton? */
3081 if (task->really_toggling)
3082 return;
3083
3084 /* Undo the toggle */
3085 task->really_toggling = TRUE(!(0));
3086 ctk_toggle_button_set_active (CTK_TOGGLE_BUTTON (button)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_toggle_button_get_type ()))))))
,
3087 !ctk_toggle_button_get_active (CTK_TOGGLE_BUTTON (button)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_toggle_button_get_type ()))))))
));
3088 task->really_toggling = FALSE(0);
3089
3090 switch (task->type)
3091 {
3092 case VNCK_TASK_CLASS_GROUP:
3093 vnck_task_popup_menu (task, FALSE(0));
3094 break;
3095 case VNCK_TASK_WINDOW:
3096 if (task->window == NULL((void*)0))
3097 return;
3098
3099 /* This should only be called by clicking on the task button, so
3100 * ctk_get_current_event_time() should be fine here...
3101 */
3102 vnck_tasklist_activate_task_window (task, ctk_get_current_event_time ());
3103 break;
3104 case VNCK_TASK_STARTUP_SEQUENCE:
3105 break;
3106 default:
3107 break;
3108 }
3109}
3110
3111static char *
3112vnck_task_get_text (VnckTask *task,
3113 gboolean icon_text,
3114 gboolean include_state)
3115{
3116 const char *name;
3117
3118 switch (task->type)
3119 {
3120 case VNCK_TASK_CLASS_GROUP:
3121 name = vnck_class_group_get_name (task->class_group);
3122 if (name[0] != 0)
3123 return g_strdup_printf ("%s (%d)",
3124 name,
3125 g_list_length (task->windows));
3126 else
3127 return g_strdup_printf ("(%d)",
3128 g_list_length (task->windows));
3129
3130 case VNCK_TASK_WINDOW:
3131 return _vnck_window_get_name_for_display (task->window,
3132 icon_text, include_state);
3133 break;
3134
3135 case VNCK_TASK_STARTUP_SEQUENCE:
3136#ifdef HAVE_STARTUP_NOTIFICATION1
3137 name = sn_startup_sequence_get_description (task->startup_sequence);
3138 if (name == NULL((void*)0))
3139 name = sn_startup_sequence_get_name (task->startup_sequence);
3140 if (name == NULL((void*)0))
3141 name = sn_startup_sequence_get_binary_name (task->startup_sequence);
3142
3143 return g_strdup (name)g_strdup_inline (name);
3144#else
3145 return NULL((void*)0);
3146#endif
3147 break;
3148
3149 default:
3150 break;
3151 }
3152
3153 return NULL((void*)0);
3154}
3155
3156static void
3157vnck_dimm_icon (GdkPixbuf *pixbuf)
3158{
3159 int x, y, pixel_stride, row_stride;
3160 guchar *row, *pixels;
3161 int w, h;
3162
3163 g_assert (pixbuf != NULL)do { if (pixbuf != ((void*)0)) ; else g_assertion_message_expr
("Vnck", "../libvnck/tasklist.c", 3163, ((const char*) (__func__
)), "pixbuf != NULL"); } while (0)
;
3164
3165 w = gdk_pixbuf_get_width (pixbuf);
3166 h = gdk_pixbuf_get_height (pixbuf);
3167
3168 g_assert (gdk_pixbuf_get_has_alpha (pixbuf))do { if (gdk_pixbuf_get_has_alpha (pixbuf)) ; else g_assertion_message_expr
("Vnck", "../libvnck/tasklist.c", 3168, ((const char*) (__func__
)), "gdk_pixbuf_get_has_alpha (pixbuf)"); } while (0)
;
3169
3170 pixel_stride = 4;
3171
3172 row = gdk_pixbuf_get_pixels (pixbuf);
3173 row_stride = gdk_pixbuf_get_rowstride (pixbuf);
3174
3175 for (y = 0; y < h; y++)
3176 {
3177 pixels = row;
3178
3179 for (x = 0; x < w; x++)
3180 {
3181 pixels[3] /= 2;
3182
3183 pixels += pixel_stride;
3184 }
3185
3186 row += row_stride;
3187 }
3188}
3189
3190static GdkPixbuf *
3191vnck_task_scale_icon (GdkPixbuf *orig, gboolean minimized)
3192{
3193 int w, h;
3194 GdkPixbuf *pixbuf;
3195
3196 if (!orig)
3197 return NULL((void*)0);
3198
3199 w = gdk_pixbuf_get_width (orig);
3200 h = gdk_pixbuf_get_height (orig);
3201
3202 if (h != (int) MINI_ICON_SIZE_vnck_get_default_mini_icon_size () ||
3203 !gdk_pixbuf_get_has_alpha (orig))
3204 {
3205 double scale;
3206
3207 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
3208 TRUE(!(0)),
3209 8,
3210 MINI_ICON_SIZE_vnck_get_default_mini_icon_size () * w / (double) h,
3211 MINI_ICON_SIZE_vnck_get_default_mini_icon_size ());
3212
3213 scale = MINI_ICON_SIZE_vnck_get_default_mini_icon_size () / (double) gdk_pixbuf_get_height (orig);
3214
3215 gdk_pixbuf_scale (orig,
3216 pixbuf,
3217 0, 0,
3218 gdk_pixbuf_get_width (pixbuf),
3219 gdk_pixbuf_get_height (pixbuf),
3220 0, 0,
3221 scale, scale,
3222 GDK_INTERP_HYPER);
3223 }
3224 else
3225 pixbuf = orig;
3226
3227 if (minimized)
3228 {
3229 if (orig == pixbuf)
3230 pixbuf = gdk_pixbuf_copy (orig);
3231
3232 vnck_dimm_icon (pixbuf);
3233 }
3234
3235 if (orig == pixbuf)
3236 g_object_ref (pixbuf)((__typeof__ (pixbuf)) (g_object_ref) (pixbuf));
3237
3238 return pixbuf;
3239}
3240
3241
3242static GdkPixbuf *
3243vnck_task_get_icon (VnckTask *task)
3244{
3245 VnckWindowState state;
3246 GdkPixbuf *pixbuf;
3247
3248 pixbuf = NULL((void*)0);
3249
3250 switch (task->type)
3251 {
3252 case VNCK_TASK_CLASS_GROUP:
3253 pixbuf = vnck_task_scale_icon (vnck_class_group_get_mini_icon (task->class_group),
3254 FALSE(0));
3255 break;
3256
3257 case VNCK_TASK_WINDOW:
3258 state = vnck_window_get_state (task->window);
3259
3260 pixbuf = vnck_task_scale_icon (vnck_window_get_mini_icon (task->window),
3261 state & VNCK_WINDOW_STATE_MINIMIZED);
3262 break;
3263
3264 case VNCK_TASK_STARTUP_SEQUENCE:
3265#ifdef HAVE_STARTUP_NOTIFICATION1
3266 if (task->tasklist->priv->icon_loader != NULL((void*)0))
3267 {
3268 const char *icon;
3269
3270 icon = sn_startup_sequence_get_icon_name (task->startup_sequence);
3271 if (icon != NULL((void*)0))
3272 {
3273 GdkPixbuf *loaded;
3274
3275 loaded = (* task->tasklist->priv->icon_loader) (icon,
3276 MINI_ICON_SIZE_vnck_get_default_mini_icon_size (),
3277 0,
3278 task->tasklist->priv->icon_loader_data);
3279
3280 if (loaded != NULL((void*)0))
3281 {
3282 pixbuf = vnck_task_scale_icon (loaded, FALSE(0));
3283 g_object_unref (G_OBJECT (loaded)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((loaded)), (((GType) ((20) << (2))))))))
);
3284 }
3285 }
3286 }
3287
3288 if (pixbuf == NULL((void*)0))
3289 {
3290 _vnck_get_fallback_icons (NULL((void*)0), 0, 0,
3291 &pixbuf, MINI_ICON_SIZE_vnck_get_default_mini_icon_size (), MINI_ICON_SIZE_vnck_get_default_mini_icon_size ());
3292 }
3293#endif
3294 break;
3295
3296 default:
3297 break;
3298 }
3299
3300 return pixbuf;
3301}
3302
3303static gboolean
3304vnck_task_get_needs_attention (VnckTask *task)
3305{
3306 GList *l;
3307 VnckTask *win_task;
3308 gboolean needs_attention;
3309
3310 needs_attention = FALSE(0);
3311
3312 switch (task->type)
3313 {
3314 case VNCK_TASK_CLASS_GROUP:
3315 task->start_needs_attention = 0;
3316 l = task->windows;
3317 while (l)
3318 {
3319 win_task = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
3320
3321 if (vnck_window_or_transient_needs_attention (win_task->window))
3322 {
3323 needs_attention = TRUE(!(0));
3324 task->start_needs_attention = MAX (task->start_needs_attention, _vnck_window_or_transient_get_needs_attention_time (win_task->window))(((task->start_needs_attention) > (_vnck_window_or_transient_get_needs_attention_time
(win_task->window))) ? (task->start_needs_attention) :
(_vnck_window_or_transient_get_needs_attention_time (win_task
->window)))
;
3325 break;
3326 }
3327
3328 l = l->next;
3329 }
3330 break;
3331
3332 case VNCK_TASK_WINDOW:
3333 needs_attention =
3334 vnck_window_or_transient_needs_attention (task->window);
3335 task->start_needs_attention = _vnck_window_or_transient_get_needs_attention_time (task->window);
3336 break;
3337
3338 case VNCK_TASK_STARTUP_SEQUENCE:
3339 default:
3340 break;
3341 }
3342
3343 return needs_attention != FALSE(0);
3344}
3345
3346static void
3347vnck_task_update_visible_state (VnckTask *task)
3348{
3349 GdkPixbuf *pixbuf;
3350 char *text;
3351
3352 pixbuf = vnck_task_get_icon (task);
3353 ctk_image_set_from_pixbuf (CTK_IMAGE (task->image)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->image)), ((ctk_image_get_type ()))))))
,
3354 pixbuf);
3355 if (pixbuf)
3356 g_object_unref (pixbuf);
3357
3358 text = vnck_task_get_text (task, TRUE(!(0)), TRUE(!(0)));
3359 if (text != NULL((void*)0))
3360 {
3361 ctk_label_set_text (CTK_LABEL (task->label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->label)), ((ctk_label_get_type ()))))))
, text);
3362 if (vnck_task_get_needs_attention (task))
3363 {
3364 _make_ctk_label_bold ((CTK_LABEL (task->label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->label)), ((ctk_label_get_type ()))))))
));
3365 vnck_task_queue_glow (task);
3366 }
3367 else
3368 {
3369 _make_ctk_label_normal ((CTK_LABEL (task->label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->label)), ((ctk_label_get_type ()))))))
));
3370 vnck_task_reset_glow (task);
3371 }
3372 g_free (text);
3373 }
3374
3375 text = vnck_task_get_text (task, FALSE(0), FALSE(0));
3376 /* if text is NULL, this unsets the tooltip, which is probably what we'd want
3377 * to do */
3378 ctk_widget_set_tooltip_text (task->button, text);
3379 g_free (text);
3380
3381 ctk_widget_queue_resize (CTK_WIDGET (task->tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->tasklist)), ((ctk_widget_get_type ()))))))
);
3382}
3383
3384static void
3385vnck_task_state_changed (VnckWindow *window,
3386 VnckWindowState changed_mask,
3387 VnckWindowState new_state G_GNUC_UNUSED__attribute__ ((__unused__)),
3388 gpointer data)
3389{
3390 VnckTasklist *tasklist = VNCK_TASKLIST (data)((((VnckTasklist*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_tasklist_get_type ()))))))
;
3391
3392 if (changed_mask & VNCK_WINDOW_STATE_SKIP_TASKLIST)
3393 {
3394 vnck_tasklist_update_lists (tasklist);
3395 ctk_widget_queue_resize (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
3396 return;
3397 }
3398
3399 if ((changed_mask & VNCK_WINDOW_STATE_DEMANDS_ATTENTION) ||
3400 (changed_mask & VNCK_WINDOW_STATE_URGENT))
3401 {
3402 VnckWorkspace *active_workspace =
3403 vnck_screen_get_active_workspace (tasklist->priv->screen);
3404
3405 if (active_workspace &&
3406 (active_workspace != vnck_window_get_workspace (window) ||
3407 (vnck_workspace_is_virtual (active_workspace) &&
3408 !vnck_window_is_in_viewport (window, active_workspace))))
3409 {
3410 vnck_tasklist_update_lists (tasklist);
3411 ctk_widget_queue_resize (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
3412 }
3413 }
3414
3415 if ((changed_mask & VNCK_WINDOW_STATE_MINIMIZED) ||
3416 (changed_mask & VNCK_WINDOW_STATE_DEMANDS_ATTENTION) ||
3417 (changed_mask & VNCK_WINDOW_STATE_URGENT))
3418 {
3419 VnckTask *win_task = NULL((void*)0);
3420
3421 /* FIXME: Handle group modal dialogs */
3422 for (; window && !win_task; window = vnck_window_get_transient (window))
3423 win_task = g_hash_table_lookup (tasklist->priv->win_hash, window);
3424
3425 if (win_task)
3426 {
3427 VnckTask *class_group_task;
3428
3429 vnck_task_update_visible_state (win_task);
3430
3431 class_group_task =
3432 g_hash_table_lookup (tasklist->priv->class_group_hash,
3433 win_task->class_group);
3434
3435 if (class_group_task)
3436 vnck_task_update_visible_state (class_group_task);
3437 }
3438 }
3439
3440}
3441
3442static void
3443vnck_task_icon_changed (VnckWindow *window G_GNUC_UNUSED__attribute__ ((__unused__)),
3444 gpointer data)
3445{
3446 VnckTask *task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
3447
3448 if (task)
3449 vnck_task_update_visible_state (task);
3450}
3451
3452static void
3453vnck_task_name_changed (VnckWindow *window G_GNUC_UNUSED__attribute__ ((__unused__)),
3454 gpointer data)
3455{
3456 VnckTask *task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
3457
3458 if (task)
3459 vnck_task_update_visible_state (task);
3460}
3461
3462static void
3463vnck_task_class_name_changed (VnckClassGroup *class_group G_GNUC_UNUSED__attribute__ ((__unused__)),
3464 gpointer data)
3465{
3466 VnckTask *task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
3467
3468 if (task)
3469 vnck_task_update_visible_state (task);
3470}
3471
3472static void
3473vnck_task_class_icon_changed (VnckClassGroup *class_group G_GNUC_UNUSED__attribute__ ((__unused__)),
3474 gpointer data)
3475{
3476 VnckTask *task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
3477
3478 if (task)
3479 vnck_task_update_visible_state (task);
3480}
3481
3482static gboolean
3483vnck_task_motion_timeout (gpointer data)
3484{
3485 VnckWorkspace *ws;
3486 VnckTask *task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
3487
3488 task->button_activate = 0;
3489
3490 /* FIXME: THIS IS SICK AND WRONG AND BUGGY. See the end of
3491 * http://mail.gnome.org/archives/wm-spec-list/2005-July/msg00032.html
3492 * There should only be *one* activate call.
3493 */
3494 ws = vnck_window_get_workspace (task->window);
3495 if (ws && ws != vnck_screen_get_active_workspace (vnck_screen_get_default ()))
3496 {
3497 vnck_workspace_activate (ws, task->dnd_timestamp);
3498 }
3499 vnck_window_activate_transient (task->window, task->dnd_timestamp);
3500
3501 task->dnd_timestamp = 0;
3502
3503 return FALSE(0);
3504}
3505
3506static void
3507vnck_task_drag_leave (CtkWidget *widget,
3508 CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
3509 guint time G_GNUC_UNUSED__attribute__ ((__unused__)),
3510 VnckTask *task)
3511{
3512 if (task->button_activate != 0)
3513 {
3514 g_source_remove (task->button_activate);
3515 task->button_activate = 0;
3516 }
3517
3518 ctk_drag_unhighlight (widget);
3519}
3520
3521static gboolean
3522vnck_task_drag_motion (CtkWidget *widget,
3523 CdkDragContext *context,
3524 gint x G_GNUC_UNUSED__attribute__ ((__unused__)),
3525 gint y G_GNUC_UNUSED__attribute__ ((__unused__)),
3526 guint time,
3527 VnckTask *task)
3528{
3529 if (ctk_drag_dest_find_target (widget, context, NULL((void*)0)))
3530 {
3531 ctk_drag_highlight (widget);
3532 cdk_drag_status (context, cdk_drag_context_get_suggested_action (context), time);
3533 }
3534 else
3535 {
3536 task->dnd_timestamp = time;
3537
3538 if (task->button_activate == 0 && task->type == VNCK_TASK_WINDOW)
3539 {
3540 task->button_activate = g_timeout_add_seconds (VNCK_ACTIVATE_TIMEOUT1,
3541 vnck_task_motion_timeout,
3542 task);
3543 }
3544
3545 cdk_drag_status (context, 0, time);
3546 }
3547 return TRUE(!(0));
3548}
3549
3550static void
3551vnck_task_drag_begin (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
3552 CdkDragContext *context,
3553 VnckTask *task)
3554{
3555 _vnck_window_set_as_drag_icon (task->window, context,
3556 CTK_WIDGET (task->tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->tasklist)), ((ctk_widget_get_type ()))))))
);
3557
3558 task->tasklist->priv->drag_start_time = ctk_get_current_event_time ();
3559}
3560
3561static void
3562vnck_task_drag_end (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
3563 CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
3564 VnckTask *task)
3565{
3566 task->tasklist->priv->drag_start_time = 0;
3567}
3568
3569static void
3570vnck_task_drag_data_get (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
3571 CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
3572 CtkSelectionData *selection_data,
3573 guint info G_GNUC_UNUSED__attribute__ ((__unused__)),
3574 guint time G_GNUC_UNUSED__attribute__ ((__unused__)),
3575 VnckTask *task)
3576{
3577 gulong xid;
3578
3579 xid = vnck_window_get_xid (task->window);
3580 ctk_selection_data_set (selection_data,
3581 ctk_selection_data_get_target (selection_data),
3582 8, (guchar *)&xid, sizeof (gulong));
3583}
3584
3585static void
3586vnck_task_drag_data_received (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
3587 CdkDragContext *context,
3588 gint x G_GNUC_UNUSED__attribute__ ((__unused__)),
3589 gint y G_GNUC_UNUSED__attribute__ ((__unused__)),
3590 CtkSelectionData *data,
3591 guint info G_GNUC_UNUSED__attribute__ ((__unused__)),
3592 guint time,
3593 VnckTask *target_task)
3594{
3595 VnckTasklist *tasklist;
3596 GList *l, *windows;
3597 VnckWindow *window;
3598 gulong *xid;
3599 guint new_order, old_order, order;
3600 VnckWindow *found_window;
3601
3602 if ((ctk_selection_data_get_length (data) != sizeof (gulong)) ||
3603 (ctk_selection_data_get_format (data) != 8))
3604 {
3605 ctk_drag_finish (context, FALSE(0), FALSE(0), time);
3606 return;
3607 }
3608
3609 tasklist = target_task->tasklist;
3610 xid = (gulong *) ctk_selection_data_get_data (data);
3611 found_window = NULL((void*)0);
3612 new_order = 0;
3613 windows = vnck_screen_get_windows (tasklist->priv->screen);
3614
3615 for (l = windows; l; l = l->next)
3616 {
3617 window = VNCK_WINDOW (l->data)((((VnckWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_window_get_type ()))))))
;
3618 if (vnck_window_get_xid (window) == *xid)
3619 {
3620 old_order = vnck_window_get_sort_order (window);
3621 new_order = vnck_window_get_sort_order (target_task->window);
3622 if (old_order < new_order)
3623 new_order++;
3624 found_window = window;
3625 break;
3626 }
3627 }
3628
3629 if (target_task->window == found_window)
3630 {
3631 CtkSettings *settings;
3632 guint double_click_time;
3633
3634 settings = ctk_settings_get_for_screen (ctk_widget_get_screen (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
));
3635 double_click_time = 0;
3636 g_object_get (G_OBJECT (settings)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((settings)), (((GType) ((20) << (2))))))))
,
3637 "ctk-double-click-time", &double_click_time,
3638 NULL((void*)0));
3639
3640 if ((time - tasklist->priv->drag_start_time) < double_click_time)
3641 {
3642 vnck_tasklist_activate_task_window (target_task, time);
3643 ctk_drag_finish (context, TRUE(!(0)), FALSE(0), time);
3644 return;
3645 }
3646 }
3647
3648 if (found_window)
3649 {
3650 for (l = windows; l; l = l->next)
3651 {
3652 window = VNCK_WINDOW (l->data)((((VnckWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_window_get_type ()))))))
;
3653 order = vnck_window_get_sort_order (window);
3654 if (order >= new_order)
3655 vnck_window_set_sort_order (window, order + 1);
3656 }
3657 vnck_window_set_sort_order (found_window, new_order);
3658
3659 if (!tasklist->priv->include_all_workspaces &&
3660 !vnck_window_is_pinned (found_window))
3661 {
3662 VnckWorkspace *active_space;
3663 active_space = vnck_screen_get_active_workspace (tasklist->priv->screen);
3664 vnck_window_move_to_workspace (found_window, active_space);
3665 }
3666
3667 ctk_widget_queue_resize (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
3668 }
3669
3670 ctk_drag_finish (context, TRUE(!(0)), FALSE(0), time);
3671}
3672
3673static gboolean
3674vnck_task_button_press_event (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
3675 CdkEventButton *event,
3676 gpointer data)
3677{
3678 VnckTask *task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
3679
3680 switch (task->type)
3681 {
3682 case VNCK_TASK_CLASS_GROUP:
3683 if (event->button == 2)
3684 vnck_tasklist_activate_next_in_class_group (task, event->time);
3685 else
3686 vnck_task_popup_menu (task,
3687 event->button == 3);
3688 return TRUE(!(0));
3689
3690 case VNCK_TASK_WINDOW:
3691 if (event->button == 1)
3692 {
3693 /* is_most_recently_activated == is_active for click &
3694 * sloppy focus methods. We use the former here because
3695 * 'mouse' focus provides a special case. In that case, no
3696 * window will be active, but if a window was the most
3697 * recently active one (i.e. user moves mouse straight from
3698 * window to tasklist), then we should still minimize it.
3699 */
3700 if (vnck_window_is_most_recently_activated (task->window))
3701 task->was_active = TRUE(!(0));
3702 else
3703 task->was_active = FALSE(0);
3704
3705 return FALSE(0);
3706 }
3707 else if (event->button == 2)
3708 {
3709 /* middle-click close window */
3710 if (task->tasklist->priv->middle_click_close == TRUE(!(0)))
3711 {
3712 vnck_window_close (task->window, ctk_get_current_event_time ());
3713 return TRUE(!(0));
3714 }
3715 }
3716 else if (event->button == 3)
3717 {
3718 if (task->action_menu)
3719 ctk_widget_destroy (task->action_menu);
3720
3721 g_assert (task->action_menu == NULL)do { if (task->action_menu == ((void*)0)) ; else g_assertion_message_expr
("Vnck", "../libvnck/tasklist.c", 3721, ((const char*) (__func__
)), "task->action_menu == NULL"); } while (0)
;
3722
3723 task->action_menu = vnck_action_menu_new (task->window);
3724
3725 g_object_add_weak_pointer (G_OBJECT (task->action_menu)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->action_menu)), (((GType) ((20) << (2)))))
)))
,
3726 (void**) &task->action_menu);
3727
3728 ctk_menu_set_screen (CTK_MENU (task->action_menu)((((CtkMenu*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->action_menu)), ((ctk_menu_get_type ()))))))
,
3729 _vnck_screen_get_cdk_screen (task->tasklist->priv->screen));
3730
3731 ctk_widget_show (task->action_menu);
3732 ctk_menu_popup_at_widget (CTK_MENU (task->action_menu)((((CtkMenu*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->action_menu)), ((ctk_menu_get_type ()))))))
, task->button,
3733 CDK_GRAVITY_SOUTH_WEST,
3734 CDK_GRAVITY_NORTH_WEST,
3735 (CdkEvent *) event);
3736
3737 g_signal_connect (task->action_menu, "selection-done",g_signal_connect_data ((task->action_menu), ("selection-done"
), (((GCallback) (ctk_widget_destroy))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
3738 G_CALLBACK (ctk_widget_destroy), NULL)g_signal_connect_data ((task->action_menu), ("selection-done"
), (((GCallback) (ctk_widget_destroy))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
;
3739
3740 return TRUE(!(0));
3741 }
3742 break;
3743
3744 case VNCK_TASK_STARTUP_SEQUENCE:
3745 default:
3746 break;
3747 }
3748
3749 return FALSE(0);
3750}
3751
3752static GList*
3753vnck_task_extract_windows (VnckTask *task)
3754{
3755 GList *windows = NULL((void*)0);
3756 GList *l;
3757
3758 /* Add the ungrouped window in the task */
3759 if (task->window != NULL((void*)0))
3760 {
3761 windows = g_list_prepend (windows, task->window);
3762 }
3763
3764 /* Add any grouped windows available in the task */
3765 for (l = task->windows; l != NULL((void*)0); l = l->next)
3766 {
3767 VnckTask *t = VNCK_TASK (l->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((vnck_task_get_type ()))))))
;
3768 windows = g_list_prepend (windows, t->window);
3769 }
3770
3771 return g_list_reverse (windows);
3772}
3773
3774static gboolean
3775vnck_task_enter_notify_event (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
3776 CdkEvent *event G_GNUC_UNUSED__attribute__ ((__unused__)),
3777 gpointer data)
3778{
3779 VnckTask *task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
3780 GList *windows = vnck_task_extract_windows (task);
3781
3782 g_signal_emit (G_OBJECT (task->tasklist)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->tasklist)), (((GType) ((20) << (2))))))))
,
3783 signals[TASK_ENTER_NOTIFY],
3784 0, windows);
3785
3786 g_list_free (windows);
3787
3788 return FALSE(0);
3789}
3790
3791static gboolean
3792vnck_task_leave_notify_event (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
3793 CdkEvent *event G_GNUC_UNUSED__attribute__ ((__unused__)),
3794 gpointer data)
3795{
3796 VnckTask *task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
3797 GList *windows = vnck_task_extract_windows (task);
3798
3799 g_signal_emit (G_OBJECT (task->tasklist)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->tasklist)), (((GType) ((20) << (2))))))))
,
3800 signals[TASK_LEAVE_NOTIFY],
3801 0, windows);
3802
3803 g_list_free (windows);
3804
3805 return FALSE(0);
3806}
3807
3808static gboolean
3809vnck_task_scroll_event (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
3810 CdkEvent *event,
3811 gpointer data)
3812{
3813 VnckTask *task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
3814
3815 return vnck_tasklist_scroll_event (CTK_WIDGET (task->tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->tasklist)), ((ctk_widget_get_type ()))))))
, (CdkEventScroll *) event);
3816}
3817
3818static gboolean
3819vnck_task_draw (CtkWidget *widget,
3820 cairo_t *cr,
3821 gpointer data);
3822
3823static void
3824vnck_task_create_widgets (VnckTask *task, CtkReliefStyle relief)
3825{
3826 CtkWidget *hbox;
3827 GdkPixbuf *pixbuf;
3828 char *text;
3829 static const CtkTargetEntry targets[] = {
3830 { (gchar *) "application/x-vnck-window-id", 0, 0 }
3831 };
3832
3833 if (task->type == VNCK_TASK_STARTUP_SEQUENCE)
3834 task->button = ctk_button_new ();
3835 else
3836 task->button = ctk_toggle_button_new ();
3837
3838 ctk_button_set_relief (CTK_BUTTON (task->button)((((CtkButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), ((ctk_button_get_type ()))))))
, relief);
3839
3840 task->button_activate = 0;
3841 g_object_add_weak_pointer (G_OBJECT (task->button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), (((GType) ((20) << (2))))))))
,
3842 (void**) &task->button);
3843
3844 ctk_widget_set_name (task->button,
3845 "tasklist-button");
3846
3847 if (task->type == VNCK_TASK_WINDOW)
3848 {
3849 ctk_drag_source_set (CTK_WIDGET (task->button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), ((ctk_widget_get_type ()))))))
,
3850 CDK_BUTTON1_MASK,
3851 targets, 1,
3852 CDK_ACTION_MOVE);
3853 ctk_drag_dest_set (CTK_WIDGET (task->button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), ((ctk_widget_get_type ()))))))
, CTK_DEST_DEFAULT_DROP,
3854 targets, 1, CDK_ACTION_MOVE);
3855 }
3856 else
3857 ctk_drag_dest_set (CTK_WIDGET (task->button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), ((ctk_widget_get_type ()))))))
, 0,
3858 NULL((void*)0), 0, CDK_ACTION_DEFAULT);
3859
3860 hbox = ctk_box_new (CTK_ORIENTATION_HORIZONTAL, 0);
3861
3862 pixbuf = vnck_task_get_icon (task);
3863 if (pixbuf)
3864 {
3865 task->image = ctk_image_new_from_pixbuf (pixbuf);
3866 g_object_unref (pixbuf);
3867 }
3868 else
3869 task->image = ctk_image_new ();
3870
3871 ctk_widget_show (task->image);
3872
3873 text = vnck_task_get_text (task, TRUE(!(0)), TRUE(!(0)));
3874 task->label = ctk_label_new (text);
3875 ctk_label_set_xalign (CTK_LABEL (task->label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->label)), ((ctk_label_get_type ()))))))
, 0.0);
3876 ctk_label_set_ellipsize (CTK_LABEL (task->label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->label)), ((ctk_label_get_type ()))))))
,
3877 PANGO_ELLIPSIZE_END);
3878
3879 if (vnck_task_get_needs_attention (task))
3880 {
3881 _make_ctk_label_bold ((CTK_LABEL (task->label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->label)), ((ctk_label_get_type ()))))))
));
3882 vnck_task_queue_glow (task);
3883 }
3884
3885 ctk_widget_show (task->label);
3886
3887 ctk_box_pack_start (CTK_BOX (hbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((hbox)), ((ctk_box_get_type ()))))))
, task->image, FALSE(0), FALSE(0),
3888 TASKLIST_BUTTON_PADDING4);
3889 ctk_box_pack_start (CTK_BOX (hbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((hbox)), ((ctk_box_get_type ()))))))
, task->label, TRUE(!(0)), TRUE(!(0)),
3890 TASKLIST_BUTTON_PADDING4);
3891
3892 ctk_container_add (CTK_CONTAINER (task->button)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), ((ctk_container_get_type ()))))))
, hbox);
3893 ctk_widget_show (hbox);
3894 g_free (text);
3895
3896 text = vnck_task_get_text (task, FALSE(0), FALSE(0));
3897 ctk_widget_set_tooltip_text (task->button, text);
3898 g_free (text);
3899
3900 /* Set up signals */
3901 if (CTK_IS_TOGGLE_BUTTON (task->button)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(task->button)); GType __t = ((ctk_toggle_button_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
3902 g_signal_connect_object (G_OBJECT (task->button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), (((GType) ((20) << (2))))))))
, "toggled",
3903 G_CALLBACK (vnck_task_button_toggled)((GCallback) (vnck_task_button_toggled)),
3904 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3905 0);
3906
3907 g_signal_connect_object (G_OBJECT (task->button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), (((GType) ((20) << (2))))))))
, "size_allocate",
3908 G_CALLBACK (vnck_task_size_allocated)((GCallback) (vnck_task_size_allocated)),
3909 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3910 0);
3911
3912 g_signal_connect_object (G_OBJECT (task->button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), (((GType) ((20) << (2))))))))
, "button_press_event",
3913 G_CALLBACK (vnck_task_button_press_event)((GCallback) (vnck_task_button_press_event)),
3914 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3915 0);
3916
3917 g_signal_connect_object (G_OBJECT (task->button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), (((GType) ((20) << (2))))))))
, "enter_notify_event",
3918 G_CALLBACK (vnck_task_enter_notify_event)((GCallback) (vnck_task_enter_notify_event)),
3919 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3920 0);
3921
3922 g_signal_connect_object (G_OBJECT (task->button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), (((GType) ((20) << (2))))))))
, "leave_notify_event",
3923 G_CALLBACK (vnck_task_leave_notify_event)((GCallback) (vnck_task_leave_notify_event)),
3924 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3925 0);
3926
3927 ctk_widget_add_events (task->button, CDK_SCROLL_MASK);
3928 g_signal_connect_object (G_OBJECT (task->button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), (((GType) ((20) << (2))))))))
, "scroll_event",
3929 G_CALLBACK (vnck_task_scroll_event)((GCallback) (vnck_task_scroll_event)),
3930 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3931 0);
3932
3933 g_signal_connect_object (G_OBJECT(task->button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), (((GType) ((20) << (2))))))))
, "drag_motion",
3934 G_CALLBACK (vnck_task_drag_motion)((GCallback) (vnck_task_drag_motion)),
3935 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3936 0);
3937
3938 if (task->type == VNCK_TASK_WINDOW)
3939 {
3940 g_signal_connect_object (G_OBJECT (task->button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), (((GType) ((20) << (2))))))))
, "drag_data_received",
3941 G_CALLBACK (vnck_task_drag_data_received)((GCallback) (vnck_task_drag_data_received)),
3942 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3943 0);
3944
3945 }
3946
3947 g_signal_connect_object (G_OBJECT(task->button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), (((GType) ((20) << (2))))))))
, "drag_leave",
3948 G_CALLBACK (vnck_task_drag_leave)((GCallback) (vnck_task_drag_leave)),
3949 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3950 0);
3951
3952 if (task->type == VNCK_TASK_WINDOW) {
3953 g_signal_connect_object (G_OBJECT(task->button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), (((GType) ((20) << (2))))))))
, "drag_data_get",
3954 G_CALLBACK (vnck_task_drag_data_get)((GCallback) (vnck_task_drag_data_get)),
3955 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3956 0);
3957
3958 g_signal_connect_object (G_OBJECT(task->button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), (((GType) ((20) << (2))))))))
, "drag_begin",
3959 G_CALLBACK (vnck_task_drag_begin)((GCallback) (vnck_task_drag_begin)),
3960 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3961 0);
3962
3963 g_signal_connect_object (G_OBJECT(task->button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), (((GType) ((20) << (2))))))))
, "drag_end",
3964 G_CALLBACK (vnck_task_drag_end)((GCallback) (vnck_task_drag_end)),
3965 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3966 0);
3967 }
3968
3969 switch (task->type)
3970 {
3971 case VNCK_TASK_CLASS_GROUP:
3972 task->class_name_changed_tag = g_signal_connect (G_OBJECT (task->class_group), "name_changed",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((task->class_group)), (((GType) ((20) <<
(2))))))))), ("name_changed"), (((GCallback) (vnck_task_class_name_changed
))), (task), ((void*)0), (GConnectFlags) 0)
3973 G_CALLBACK (vnck_task_class_name_changed), task)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((task->class_group)), (((GType) ((20) <<
(2))))))))), ("name_changed"), (((GCallback) (vnck_task_class_name_changed
))), (task), ((void*)0), (GConnectFlags) 0)
;
3974 task->class_icon_changed_tag = g_signal_connect (G_OBJECT (task->class_group), "icon_changed",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((task->class_group)), (((GType) ((20) <<
(2))))))))), ("icon_changed"), (((GCallback) (vnck_task_class_icon_changed
))), (task), ((void*)0), (GConnectFlags) 0)
3975 G_CALLBACK (vnck_task_class_icon_changed), task)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((task->class_group)), (((GType) ((20) <<
(2))))))))), ("icon_changed"), (((GCallback) (vnck_task_class_icon_changed
))), (task), ((void*)0), (GConnectFlags) 0)
;
3976 break;
3977
3978 case VNCK_TASK_WINDOW:
3979 task->state_changed_tag = g_signal_connect (G_OBJECT (task->window), "state_changed",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((task->window)), (((GType) ((20) <<
(2))))))))), ("state_changed"), (((GCallback) (vnck_task_state_changed
))), (task->tasklist), ((void*)0), (GConnectFlags) 0)
3980 G_CALLBACK (vnck_task_state_changed), task->tasklist)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((task->window)), (((GType) ((20) <<
(2))))))))), ("state_changed"), (((GCallback) (vnck_task_state_changed
))), (task->tasklist), ((void*)0), (GConnectFlags) 0)
;
3981 task->icon_changed_tag = g_signal_connect (G_OBJECT (task->window), "icon_changed",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((task->window)), (((GType) ((20) <<
(2))))))))), ("icon_changed"), (((GCallback) (vnck_task_icon_changed
))), (task), ((void*)0), (GConnectFlags) 0)
3982 G_CALLBACK (vnck_task_icon_changed), task)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((task->window)), (((GType) ((20) <<
(2))))))))), ("icon_changed"), (((GCallback) (vnck_task_icon_changed
))), (task), ((void*)0), (GConnectFlags) 0)
;
3983 task->name_changed_tag = g_signal_connect (G_OBJECT (task->window), "name_changed",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((task->window)), (((GType) ((20) <<
(2))))))))), ("name_changed"), (((GCallback) (vnck_task_name_changed
))), (task), ((void*)0), (GConnectFlags) 0)
3984 G_CALLBACK (vnck_task_name_changed), task)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((task->window)), (((GType) ((20) <<
(2))))))))), ("name_changed"), (((GCallback) (vnck_task_name_changed
))), (task), ((void*)0), (GConnectFlags) 0)
;
3985 break;
3986
3987 case VNCK_TASK_STARTUP_SEQUENCE:
3988 break;
3989
3990 default:
3991 g_assert_not_reached ()do { g_assertion_message_expr ("Vnck", "../libvnck/tasklist.c"
, 3991, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3992 }
3993
3994 g_signal_connect_object (task->button, "draw",
3995 G_CALLBACK (vnck_task_draw)((GCallback) (vnck_task_draw)),
3996 G_OBJECT (task)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task)), (((GType) ((20) << (2))))))))
,
3997 G_CONNECT_AFTER);
3998}
3999
4000#define ARROW_SPACE4 4
4001#define ARROW_SIZE12 12
4002#define INDICATOR_SIZE7 7
4003
4004static gboolean
4005vnck_task_draw (CtkWidget *widget,
4006 cairo_t *cr,
4007 gpointer data)
4008{
4009 int x, y;
4010 VnckTask *task;
4011 CtkStyleContext *context;
4012 CtkStateFlags state;
4013 CtkBorder padding;
4014 CtkWidget *tasklist_widget;
4015 gint width, height;
4016 gboolean overlay_rect;
4017 gint arrow_width;
4018 gint arrow_height;
4019 CdkRGBA color;
4020
4021 task = VNCK_TASK (data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((vnck_task_get_type ()))))))
;
4022
4023 switch (task->type)
4024 {
4025 case VNCK_TASK_CLASS_GROUP:
4026 context = ctk_widget_get_style_context (widget);
4027
4028 state = ctk_style_context_get_state (context);
4029 ctk_style_context_get_padding (context, state, &padding);
4030
4031 state = (task->tasklist->priv->active_class_group == task) ?
4032 CTK_STATE_FLAG_ACTIVE : CTK_STATE_FLAG_NORMAL;
4033
4034 ctk_style_context_save (context);
4035 ctk_style_context_set_state (context, state);
4036 ctk_style_context_get_color (context, state, &color);
4037 ctk_style_context_restore (context);
4038
4039 x = ctk_widget_get_allocated_width (widget) -
4040 (ctk_container_get_border_width (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
) + padding.right + ARROW_SIZE12);
4041 y = ctk_widget_get_allocated_height (widget) / 2;
4042
4043 arrow_width = INDICATOR_SIZE7 + ((INDICATOR_SIZE7 % 2) - 1);
4044 arrow_height = arrow_width / 2 + 1;
4045 x += (ARROW_SIZE12 - arrow_width) / 2;
4046 y -= (2 * arrow_height + ARROW_SPACE4) / 2;
4047
4048 cairo_save (cr);
4049 cdk_cairo_set_source_rgba (cr, &color);
4050
4051 /* Up arrow */
4052 cairo_move_to (cr, x, y + arrow_height);
4053 cairo_line_to (cr, x + arrow_width / 2., y);
4054 cairo_line_to (cr, x + arrow_width, y + arrow_height);
4055 cairo_close_path (cr);
4056 cairo_fill (cr);
4057
4058 /* Down arrow */
4059 y += arrow_height + ARROW_SPACE4;
4060 cairo_move_to (cr, x, y);
4061 cairo_line_to (cr, x + arrow_width, y);
4062 cairo_line_to (cr, x + arrow_width / 2., y + arrow_height);
4063 cairo_close_path (cr);
4064 cairo_fill (cr);
4065
4066 cairo_restore (cr);
4067
4068 break;
4069
4070 case VNCK_TASK_WINDOW:
4071 case VNCK_TASK_STARTUP_SEQUENCE:
4072 default:
4073 break;
4074 }
4075
4076 if (task->glow_factor == 0.0)
4077 return FALSE(0);
4078
4079 /* push a translucent overlay to paint to, so we can blend later */
4080 cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
4081
4082 width = ctk_widget_get_allocated_width (task->button);
4083 height = ctk_widget_get_allocated_height (task->button);
4084
4085 tasklist_widget = CTK_WIDGET (task->tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->tasklist)), ((ctk_widget_get_type ()))))))
;
4086
4087 context = ctk_widget_get_style_context (task->button);
4088
4089 /* first draw the button */
4090 ctk_widget_style_get (tasklist_widget, "fade-overlay-rect", &overlay_rect, NULL((void*)0));
4091 if (overlay_rect)
4092 {
4093 ctk_style_context_save (context);
4094 ctk_style_context_set_state (context, CTK_STATE_FLAG_SELECTED);
4095
4096 /* Draw a rectangle with selected background color */
4097 ctk_render_background (context, cr, 0, 0, width, height);
4098
4099 ctk_style_context_restore (context);
4100 }
4101 else
4102 {
4103 ctk_style_context_save (context);
4104 ctk_style_context_set_state (context, CTK_STATE_FLAG_SELECTED);
4105 ctk_style_context_add_class (context, CTK_STYLE_CLASS_BUTTON"button");
4106
4107 cairo_save (cr);
4108 ctk_render_background (context, cr, 0, 0, width, height);
4109 ctk_render_frame (context, cr, 0, 0, width, height);
4110 cairo_restore (cr);
4111
4112 ctk_style_context_restore (context);
4113 }
4114
4115 /* then the contents */
4116 ctk_container_propagate_draw (CTK_CONTAINER (task->button)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), ((ctk_container_get_type ()))))))
,
4117 ctk_bin_get_child (CTK_BIN (task->button)((((CtkBin*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((task->button)), ((ctk_bin_get_type ()))))))
),
4118 cr);
4119 /* finally blend it */
4120 cairo_pop_group_to_source (cr);
4121 cairo_paint_with_alpha (cr, task->glow_factor);
4122
4123 return FALSE(0);
4124}
4125
4126static gint
4127vnck_task_compare_alphabetically (gconstpointer a,
4128 gconstpointer b)
4129{
4130 char *text1;
4131 char *text2;
4132 gint result;
4133
4134 text1 = vnck_task_get_text (VNCK_TASK (a)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((a)), ((vnck_task_get_type ()))))))
, TRUE(!(0)), FALSE(0));
4135 text2 = vnck_task_get_text (VNCK_TASK (b)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((b)), ((vnck_task_get_type ()))))))
, TRUE(!(0)), FALSE(0));
4136
4137 result= g_utf8_collate (text1, text2);
4138
4139 g_free (text1);
4140 g_free (text2);
4141
4142 return result;
4143}
4144
4145static gint
4146compare_class_group_tasks (VnckTask *task1, VnckTask *task2)
4147{
4148 const char *name1, *name2;
4149
4150 name1 = vnck_class_group_get_name (task1->class_group);
4151 name2 = vnck_class_group_get_name (task2->class_group);
4152
4153 return g_utf8_collate (name1, name2);
4154}
4155
4156static gint
4157vnck_task_compare (gconstpointer a,
4158 gconstpointer b)
4159{
4160 VnckTask *task1 = VNCK_TASK (a)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((a)), ((vnck_task_get_type ()))))))
;
4161 VnckTask *task2 = VNCK_TASK (b)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((b)), ((vnck_task_get_type ()))))))
;
4162 gint pos1, pos2;
4163
4164 pos1 = pos2 = 0; /* silence the compiler */
Although the value stored to 'pos2' is used in the enclosing expression, the value is never actually read from 'pos2'
4165
4166 switch (task1->type)
4167 {
4168 case VNCK_TASK_CLASS_GROUP:
4169 if (task2->type == VNCK_TASK_CLASS_GROUP)
4170 return compare_class_group_tasks (task1, task2);
4171 else
4172 return -1; /* Sort groups before everything else */
4173
4174 case VNCK_TASK_WINDOW:
4175 pos1 = vnck_window_get_sort_order (task1->window);
4176 break;
4177 case VNCK_TASK_STARTUP_SEQUENCE:
4178 pos1 = G_MAXINT2147483647; /* startup sequences are sorted at the end. */
4179 break; /* Changing this will break scrolling. */
4180
4181 default:
4182 break;
4183 }
4184
4185 switch (task2->type)
4186 {
4187 case VNCK_TASK_CLASS_GROUP:
4188 if (task1->type == VNCK_TASK_CLASS_GROUP)
4189 return compare_class_group_tasks (task1, task2);
4190 else
4191 return 1; /* Sort groups before everything else */
4192
4193 case VNCK_TASK_WINDOW:
4194 pos2 = vnck_window_get_sort_order (task2->window);
4195 break;
4196 case VNCK_TASK_STARTUP_SEQUENCE:
4197 pos2 = G_MAXINT2147483647;
4198 break;
4199
4200 default:
4201 break;
4202 }
4203
4204 if (pos1 < pos2)
4205 return -1;
4206 else if (pos1 > pos2)
4207 return 1;
4208 else
4209 return 0; /* should only happen if there's multiple processes being
4210 * started, and then who cares about sort order... */
4211}
4212
4213static void
4214remove_startup_sequences_for_window (VnckTasklist *tasklist,
4215 VnckWindow *window)
4216{
4217#ifdef HAVE_STARTUP_NOTIFICATION1
4218 const char *win_id;
4219 GList *tmp;
4220
4221 win_id = _vnck_window_get_startup_id (window);
4222 if (win_id == NULL((void*)0))
4223 return;
4224
4225 tmp = tasklist->priv->startup_sequences;
4226 while (tmp != NULL((void*)0))
4227 {
4228 VnckTask *task = tmp->data;
4229 GList *next = tmp->next;
4230 const char *task_id;
4231
4232 g_assert (task->type == VNCK_TASK_STARTUP_SEQUENCE)do { if (task->type == VNCK_TASK_STARTUP_SEQUENCE) ; else g_assertion_message_expr
("Vnck", "../libvnck/tasklist.c", 4232, ((const char*) (__func__
)), "task->type == VNCK_TASK_STARTUP_SEQUENCE"); } while (
0)
;
4233
4234 task_id = sn_startup_sequence_get_id (task->startup_sequence);
4235
4236 if (task_id && strcmp (task_id, win_id) == 0)
4237 ctk_widget_destroy (task->button);
4238
4239 tmp = next;
4240 }
4241#else
4242 ; /* nothing */
4243#endif
4244}
4245
4246static VnckTask *
4247vnck_task_new_from_window (VnckTasklist *tasklist,
4248 VnckWindow *window)
4249{
4250 VnckTask *task;
4251
4252 task = g_object_new (VNCK_TYPE_TASK(vnck_task_get_type ()), NULL((void*)0));
4253 task->type = VNCK_TASK_WINDOW;
4254 task->window = g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
4255 task->class_group = g_object_ref (vnck_window_get_class_group (window))((__typeof__ (vnck_window_get_class_group (window))) (g_object_ref
) (vnck_window_get_class_group (window)))
;
4256 task->tasklist = tasklist;
4257
4258 vnck_task_create_widgets (task, tasklist->priv->relief);
4259
4260 remove_startup_sequences_for_window (tasklist, window);
4261
4262 return task;
4263}
4264
4265static VnckTask *
4266vnck_task_new_from_class_group (VnckTasklist *tasklist,
4267 VnckClassGroup *class_group)
4268{
4269 VnckTask *task;
4270
4271 task = g_object_new (VNCK_TYPE_TASK(vnck_task_get_type ()), NULL((void*)0));
4272
4273 task->type = VNCK_TASK_CLASS_GROUP;
4274 task->window = NULL((void*)0);
4275 task->class_group = g_object_ref (class_group)((__typeof__ (class_group)) (g_object_ref) (class_group));
4276 task->tasklist = tasklist;
4277
4278 vnck_task_create_widgets (task, tasklist->priv->relief);
4279
4280 return task;
4281}
4282
4283#ifdef HAVE_STARTUP_NOTIFICATION1
4284static VnckTask*
4285vnck_task_new_from_startup_sequence (VnckTasklist *tasklist,
4286 SnStartupSequence *sequence)
4287{
4288 VnckTask *task;
4289
4290 task = g_object_new (VNCK_TYPE_TASK(vnck_task_get_type ()), NULL((void*)0));
4291
4292 task->type = VNCK_TASK_STARTUP_SEQUENCE;
4293 task->window = NULL((void*)0);
4294 task->class_group = NULL((void*)0);
4295 task->startup_sequence = sequence;
4296 sn_startup_sequence_ref (task->startup_sequence);
4297 task->tasklist = tasklist;
4298
4299 vnck_task_create_widgets (task, tasklist->priv->relief);
4300
4301 return task;
4302}
4303
4304/* This should be fairly long, as it should never be required unless
4305 * apps or .desktop files are buggy, and it's confusing if
4306 * OpenOffice or whatever seems to stop launching - people
4307 * might decide they need to launch it again.
4308 */
4309#define STARTUP_TIMEOUT15000 15000
4310
4311static gboolean
4312sequence_timeout_callback (void *user_data)
4313{
4314 VnckTasklist *tasklist = user_data;
4315 GList *tmp;
4316 gint64 now;
4317 long tv_sec, tv_usec;
4318 double elapsed;
4319
4320 now = g_get_real_time ();
4321
4322 restart:
4323 tmp = tasklist->priv->startup_sequences;
4324 while (tmp != NULL((void*)0))
4325 {
4326 VnckTask *task = VNCK_TASK (tmp->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tmp->data)), ((vnck_task_get_type ()))))))
;
4327
4328 sn_startup_sequence_get_last_active_time (task->startup_sequence,
4329 &tv_sec, &tv_usec);
4330
4331 elapsed = (now - (tv_sec * G_USEC_PER_SEC1000000 + tv_usec)) / 1000.0;
4332
4333 if (elapsed > STARTUP_TIMEOUT15000)
4334 {
4335 g_assert (task->button != NULL)do { if (task->button != ((void*)0)) ; else g_assertion_message_expr
("Vnck", "../libvnck/tasklist.c", 4335, ((const char*) (__func__
)), "task->button != NULL"); } while (0)
;
4336 /* removes task from list as a side effect */
4337 ctk_widget_destroy (task->button);
4338
4339 goto restart; /* don't iterate over changed list, just restart;
4340 * not efficient but who cares here.
4341 */
4342 }
4343
4344 tmp = tmp->next;
4345 }
4346
4347 if (tasklist->priv->startup_sequences == NULL((void*)0))
4348 {
4349 tasklist->priv->startup_sequence_timeout = 0;
4350 return FALSE(0);
4351 }
4352 else
4353 return TRUE(!(0));
4354}
4355
4356static void
4357vnck_tasklist_sn_event (SnMonitorEvent *event,
4358 void *user_data)
4359{
4360 VnckTasklist *tasklist;
4361
4362 tasklist = VNCK_TASKLIST (user_data)((((VnckTasklist*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((vnck_tasklist_get_type ()))))))
;
4363
4364 switch (sn_monitor_event_get_type (event))
4365 {
4366 case SN_MONITOR_EVENT_INITIATED:
4367 {
4368 VnckTask *task;
4369
4370 task = vnck_task_new_from_startup_sequence (tasklist,
4371 sn_monitor_event_get_startup_sequence (event));
4372
4373 ctk_widget_set_parent (task->button, CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
4374 ctk_widget_show (task->button);
4375
4376 tasklist->priv->startup_sequences =
4377 g_list_prepend (tasklist->priv->startup_sequences,
4378 task);
4379
4380 if (tasklist->priv->startup_sequence_timeout == 0)
4381 {
4382 tasklist->priv->startup_sequence_timeout =
4383 g_timeout_add_seconds (1, sequence_timeout_callback,
4384 tasklist);
4385 }
4386
4387 ctk_widget_queue_resize (CTK_WIDGET (tasklist)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tasklist)), ((ctk_widget_get_type ()))))))
);
4388 }
4389 break;
4390
4391 case SN_MONITOR_EVENT_COMPLETED:
4392 {
4393 GList *tmp;
4394 tmp = tasklist->priv->startup_sequences;
4395 while (tmp != NULL((void*)0))
4396 {
4397 VnckTask *task = VNCK_TASK (tmp->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tmp->data)), ((vnck_task_get_type ()))))))
;
4398
4399 if (task->startup_sequence ==
4400 sn_monitor_event_get_startup_sequence (event))
4401 {
4402 g_assert (task->button != NULL)do { if (task->button != ((void*)0)) ; else g_assertion_message_expr
("Vnck", "../libvnck/tasklist.c", 4402, ((const char*) (__func__
)), "task->button != NULL"); } while (0)
;
4403 /* removes task from list as a side effect */
4404 ctk_widget_destroy (task->button);
4405 break;
4406 }
4407
4408 tmp = tmp->next;
4409 }
4410 }
4411 break;
4412
4413 case SN_MONITOR_EVENT_CHANGED:
4414 break;
4415
4416 case SN_MONITOR_EVENT_CANCELED:
4417 break;
4418
4419 default:
4420 break;
4421 }
4422
4423 if (tasklist->priv->startup_sequences == NULL((void*)0) &&
4424 tasklist->priv->startup_sequence_timeout != 0)
4425 {
4426 g_source_remove (tasklist->priv->startup_sequence_timeout);
4427 tasklist->priv->startup_sequence_timeout = 0;
4428 }
4429}
4430
4431static void
4432vnck_tasklist_check_end_sequence (VnckTasklist *tasklist,
4433 VnckWindow *window)
4434{
4435 const char *res_class;
4436 const char *res_name;
4437 GList *tmp;
4438
4439 if (tasklist->priv->startup_sequences == NULL((void*)0))
4440 return;
4441
4442 res_class = vnck_window_get_class_group_name (window);
4443 res_name = vnck_window_get_class_instance_name (window);
4444
4445 if (res_class == NULL((void*)0) && res_name == NULL((void*)0))
4446 return;
4447
4448 tmp = tasklist->priv->startup_sequences;
4449 while (tmp != NULL((void*)0))
4450 {
4451 VnckTask *task = VNCK_TASK (tmp->data)((((VnckTask*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tmp->data)), ((vnck_task_get_type ()))))))
;
4452 const char *wmclass;
4453
4454 wmclass = sn_startup_sequence_get_wmclass (task->startup_sequence);
4455
4456 if (wmclass != NULL((void*)0) &&
4457 ((res_class && strcmp (res_class, wmclass) == 0) ||
4458 (res_name && strcmp (res_name, wmclass) == 0)))
4459 {
4460 sn_startup_sequence_complete (task->startup_sequence);
4461
4462 g_assert (task->button != NULL)do { if (task->button != ((void*)0)) ; else g_assertion_message_expr
("Vnck", "../libvnck/tasklist.c", 4462, ((const char*) (__func__
)), "task->button != NULL"); } while (0)
;
4463 /* removes task from list as a side effect */
4464 ctk_widget_destroy (task->button);
4465
4466 /* only match one */
4467 return;
4468 }
4469
4470 tmp = tmp->next;
4471 }
4472}
4473
4474#endif /* HAVE_STARTUP_NOTIFICATION */