1 /*
2 * windows-view: A view showing visible windows
3 *
4 * Copyright 2012-2020 Stephan Haller <nomad@froevel.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 *
21 *
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <libxfdashboard/windows-view.h>
29
30 #include <glib/gi18n-lib.h>
31 #include <gtk/gtk.h>
32
33 #include <libxfdashboard/live-window.h>
34 #include <libxfdashboard/scaled-table-layout.h>
35 #include <libxfdashboard/stage.h>
36 #include <libxfdashboard/application.h>
37 #include <libxfdashboard/view.h>
38 #include <libxfdashboard/drop-action.h>
39 #include <libxfdashboard/quicklaunch.h>
40 #include <libxfdashboard/application-button.h>
41 #include <libxfdashboard/window-tracker.h>
42 #include <libxfdashboard/image-content.h>
43 #include <libxfdashboard/utils.h>
44 #include <libxfdashboard/marshal.h>
45 #include <libxfdashboard/enums.h>
46 #include <libxfdashboard/stage-interface.h>
47 #include <libxfdashboard/live-workspace.h>
48 #include <libxfdashboard/compat.h>
49 #include <libxfdashboard/debug.h>
50
51
52 /* Define this class in GObject system */
53 static void _xfdashboard_windows_view_focusable_iface_init(XfdashboardFocusableInterface *iface);
54
55 struct _XfdashboardWindowsViewPrivate
56 {
57 /* Properties related */
58 XfdashboardWindowTrackerWorkspace *workspace;
59 gfloat spacing;
60 gboolean preventUpscaling;
61 gboolean isScrollEventChangingWorkspace;
62
63 /* Instance related */
64 XfdashboardWindowTracker *windowTracker;
65 ClutterLayoutManager *layout;
66 gpointer selectedItem;
67
68 XfconfChannel *xfconfChannel;
69 guint xfconfScrollEventChangingWorkspaceBindingID;
70 XfdashboardStageInterface *scrollEventChangingWorkspaceStage;
71 guint scrollEventChangingWorkspaceStageSignalID;
72
73 gboolean isWindowsNumberShown;
74
75 gboolean filterMonitorWindows;
76 gboolean filterWorkspaceWindows;
77 XfdashboardStageInterface *currentStage;
78 XfdashboardWindowTrackerMonitor *currentMonitor;
79 guint currentStageMonitorBindingID;
80 };
81
82 G_DEFINE_TYPE_WITH_CODE(XfdashboardWindowsView,
83 xfdashboard_windows_view,
84 XFDASHBOARD_TYPE_VIEW,
85 G_ADD_PRIVATE(XfdashboardWindowsView)
86 G_IMPLEMENT_INTERFACE(XFDASHBOARD_TYPE_FOCUSABLE, _xfdashboard_windows_view_focusable_iface_init))
87
88 /* Properties */
89 enum
90 {
91 PROP_0,
92
93 PROP_WORKSPACE,
94 PROP_SPACING,
95 PROP_PREVENT_UPSCALING,
96 PROP_SCROLL_EVENT_CHANGES_WORKSPACE,
97 PROP_FILTER_MONITOR_WINDOWS,
98 PROP_FILTER_WORKSPACE_WINDOWS,
99
100 PROP_LAST
101 };
102
103 static GParamSpec* XfdashboardWindowsViewProperties[PROP_LAST]={ 0, };
104
105 /* Signals */
106 enum
107 {
108 ACTION_WINDOW_CLOSE,
109 ACTION_WINDOWS_SHOW_NUMBERS,
110 ACTION_WINDOWS_HIDE_NUMBERS,
111 ACTION_WINDOWS_ACTIVATE_WINDOW_ONE,
112 ACTION_WINDOWS_ACTIVATE_WINDOW_TWO,
113 ACTION_WINDOWS_ACTIVATE_WINDOW_THREE,
114 ACTION_WINDOWS_ACTIVATE_WINDOW_FOUR,
115 ACTION_WINDOWS_ACTIVATE_WINDOW_FIVE,
116 ACTION_WINDOWS_ACTIVATE_WINDOW_SIX,
117 ACTION_WINDOWS_ACTIVATE_WINDOW_SEVEN,
118 ACTION_WINDOWS_ACTIVATE_WINDOW_EIGHT,
119 ACTION_WINDOWS_ACTIVATE_WINDOW_NINE,
120 ACTION_WINDOWS_ACTIVATE_WINDOW_TEN,
121
122 SIGNAL_LAST
123 };
124
125 static guint XfdashboardWindowsViewSignals[SIGNAL_LAST]={ 0, };
126
127 /* Forward declaration */
128 static void _xfdashboard_windows_view_recreate_window_actors(XfdashboardWindowsView *self);
129 static XfdashboardLiveWindow* _xfdashboard_windows_view_create_actor(XfdashboardWindowsView *self, XfdashboardWindowTrackerWindow *inWindow);
130 static void _xfdashboard_windows_view_set_active_workspace(XfdashboardWindowsView *self, XfdashboardWindowTrackerWorkspace *inWorkspace);
131
132 /* IMPLEMENTATION: Private variables and methods */
133 #define SCROLL_EVENT_CHANGES_WORKSPACE_XFCONF_PROP "/components/windows-view/scroll-event-changes-workspace"
134
135 #define DEFAULT_VIEW_ICON "view-fullscreen"
136 #define DEFAULT_DRAG_HANDLE_SIZE 32.0f
137
138 /* Stage interface has changed monitor */
_xfdashboard_windows_view_update_on_stage_monitor_changed(XfdashboardWindowsView * self,GParamSpec * inSpec,gpointer inUserData)139 static void _xfdashboard_windows_view_update_on_stage_monitor_changed(XfdashboardWindowsView *self,
140 GParamSpec *inSpec,
141 gpointer inUserData)
142 {
143 XfdashboardWindowsViewPrivate *priv;
144
145 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
146
147 priv=self->priv;
148
149 /* Get new reference to new monitor of stage */
150 priv->currentMonitor=xfdashboard_stage_interface_get_monitor(priv->currentStage);
151
152 /* Recreate all window actors */
153 _xfdashboard_windows_view_recreate_window_actors(self);
154 }
155
156 /* Update reference to stage interface and monitor where this view is on */
_xfdashboard_windows_view_update_stage_and_monitor(XfdashboardWindowsView * self)157 static gboolean _xfdashboard_windows_view_update_stage_and_monitor(XfdashboardWindowsView *self)
158 {
159 XfdashboardWindowsViewPrivate *priv;
160 XfdashboardStageInterface *newStage;
161
162 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), FALSE);
163
164 priv=self->priv;
165
166 /* Iterate through parent actors until stage interface is reached */
167 newStage=xfdashboard_get_stage_of_actor(CLUTTER_ACTOR(self));
168
169 /* If stage did not change return immediately */
170 if(newStage==priv->currentStage) return(FALSE);
171
172 /* Release old references to stage and monitor */
173 priv->currentMonitor=NULL;
174
175 if(priv->currentStage)
176 {
177 if(priv->currentStageMonitorBindingID)
178 {
179 g_signal_handler_disconnect(priv->currentStage, priv->currentStageMonitorBindingID);
180 priv->currentStageMonitorBindingID=0;
181 }
182
183 priv->currentStage=NULL;
184 }
185
186 /* Get new references to new stage and monitor and connect signal to get notified
187 * if stage changes monitor.
188 */
189 if(newStage)
190 {
191 priv->currentStage=newStage;
192 priv->currentStageMonitorBindingID=g_signal_connect_swapped(priv->currentStage,
193 "notify::monitor",
194 G_CALLBACK(_xfdashboard_windows_view_update_on_stage_monitor_changed),
195 self);
196
197 /* Get new reference to current monitor of new stage */
198 priv->currentMonitor=xfdashboard_stage_interface_get_monitor(priv->currentStage);
199 }
200
201 /* Stage and monitor changed and references were renewed and setup */
202 return(TRUE);
203 }
204
205 /* Check if window should be shown */
_xfdashboard_windows_view_is_visible_window(XfdashboardWindowsView * self,XfdashboardWindowTrackerWindow * inWindow)206 static gboolean _xfdashboard_windows_view_is_visible_window(XfdashboardWindowsView *self,
207 XfdashboardWindowTrackerWindow *inWindow)
208 {
209 XfdashboardWindowsViewPrivate *priv;
210 XfdashboardWindowTrackerWindowState state;
211
212 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), FALSE);
213 g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), FALSE);
214
215 priv=self->priv;
216
217 /* Get state of window */
218 state=xfdashboard_window_tracker_window_get_state(inWindow);
219
220 /* Determine if windows should be shown depending on its state, size and position */
221 if(state & XFDASHBOARD_WINDOW_TRACKER_WINDOW_STATE_SKIP_PAGER)
222 {
223 return(FALSE);
224 }
225
226 if(state & XFDASHBOARD_WINDOW_TRACKER_WINDOW_STATE_SKIP_TASKLIST)
227 {
228 return(FALSE);
229 }
230
231 if(xfdashboard_window_tracker_window_is_stage(inWindow))
232 {
233 return(FALSE);
234 }
235
236 if(!priv->workspace)
237 {
238 return(FALSE);
239 }
240
241 if(!xfdashboard_window_tracker_window_is_visible(inWindow) ||
242 (priv->filterWorkspaceWindows && !xfdashboard_window_tracker_window_is_on_workspace(inWindow, priv->workspace)))
243 {
244 return(FALSE);
245 }
246
247 if(priv->filterMonitorWindows &&
248 xfdashboard_window_tracker_supports_multiple_monitors(priv->windowTracker) &&
249 (!priv->currentMonitor || !xfdashboard_window_tracker_window_is_on_monitor(inWindow, priv->currentMonitor)))
250 {
251 return(FALSE);
252 }
253
254 /* If we get here the window should be shown */
255 return(TRUE);
256 }
257
258 /* Find live window actor by window */
_xfdashboard_windows_view_find_by_window(XfdashboardWindowsView * self,XfdashboardWindowTrackerWindow * inWindow)259 static XfdashboardLiveWindow* _xfdashboard_windows_view_find_by_window(XfdashboardWindowsView *self,
260 XfdashboardWindowTrackerWindow *inWindow)
261 {
262 XfdashboardLiveWindow *liveWindow;
263 ClutterActor *child;
264 ClutterActorIter iter;
265
266 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), NULL);
267 g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), NULL);
268
269 /* Iterate through list of current actors and find the one for requested window */
270 clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self));
271 while(clutter_actor_iter_next(&iter, &child))
272 {
273 if(!XFDASHBOARD_IS_LIVE_WINDOW(child)) continue;
274
275 liveWindow=XFDASHBOARD_LIVE_WINDOW(child);
276 if(xfdashboard_live_window_simple_get_window(XFDASHBOARD_LIVE_WINDOW_SIMPLE(liveWindow))==inWindow)
277 {
278 return(liveWindow);
279 }
280 }
281
282 /* If we get here we did not find the window and we return NULL */
283 return(NULL);
284 }
285
286 /* Update window number in close button of each window actor */
_xfdashboard_windows_view_update_window_number_in_actors(XfdashboardWindowsView * self)287 static void _xfdashboard_windows_view_update_window_number_in_actors(XfdashboardWindowsView *self)
288 {
289 XfdashboardWindowsViewPrivate *priv;
290 ClutterActor *child;
291 ClutterActorIter iter;
292 gint index;
293
294 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
295
296 priv=self->priv;
297
298 /* Iterate through list of current actors and for the first ten actors
299 * change the close button to window number and the rest will still be
300 * close buttons.
301 */
302 index=1;
303 clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self));
304 while(clutter_actor_iter_next(&iter, &child))
305 {
306 /* Only live window actors can be handled */
307 if(!XFDASHBOARD_IS_LIVE_WINDOW(child)) continue;
308
309 /* If this is one of the first ten window actors change close button
310 * to window number and set number.
311 */
312 if(priv->isWindowsNumberShown && index<=10)
313 {
314 g_object_set(child, "window-number", index, NULL);
315 index++;
316 }
317 else
318 {
319 g_object_set(child, "window-number", 0, NULL);
320 }
321 }
322 }
323
324 /* Recreate all window actors in this view */
_xfdashboard_windows_view_recreate_window_actors(XfdashboardWindowsView * self)325 static void _xfdashboard_windows_view_recreate_window_actors(XfdashboardWindowsView *self)
326 {
327 XfdashboardWindowsViewPrivate *priv;
328 GList *windowsList;
329
330 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
331
332 priv=self->priv;
333
334 /* Remove weak reference at current selection and unset selection */
335 if(priv->selectedItem)
336 {
337 g_object_remove_weak_pointer(G_OBJECT(priv->selectedItem), &priv->selectedItem);
338 priv->selectedItem=NULL;
339 }
340
341 /* Destroy all actors */
342 xfdashboard_actor_destroy_all_children(CLUTTER_ACTOR(self));
343
344 /* Create live window actors for new workspace */
345 if(priv->workspace!=NULL)
346 {
347 /* Get list of all windows open */
348 windowsList=xfdashboard_window_tracker_get_windows(priv->windowTracker);
349
350 /* Iterate through list of window (from last to first), check if window
351 * is visible and create actor for it if it is.
352 */
353 windowsList=g_list_last(windowsList);
354 while(windowsList)
355 {
356 XfdashboardWindowTrackerWindow *window=XFDASHBOARD_WINDOW_TRACKER_WINDOW(windowsList->data);
357 XfdashboardLiveWindow *liveWindow;
358
359 /* Check if window is visible on this workspace */
360 if(_xfdashboard_windows_view_is_visible_window(self, window))
361 {
362 /* Create actor */
363 liveWindow=_xfdashboard_windows_view_create_actor(XFDASHBOARD_WINDOWS_VIEW(self), window);
364 if(liveWindow)
365 {
366 clutter_actor_add_child(CLUTTER_ACTOR(self), CLUTTER_ACTOR(liveWindow));
367 _xfdashboard_windows_view_update_window_number_in_actors(self);
368 }
369 }
370
371 /* Next window */
372 windowsList=g_list_previous(windowsList);
373 }
374 }
375 }
376
377 /* Move window to monitor of this window view */
_xfdashboard_windows_view_move_live_to_view(XfdashboardWindowsView * self,XfdashboardLiveWindow * inWindowActor)378 static void _xfdashboard_windows_view_move_live_to_view(XfdashboardWindowsView *self,
379 XfdashboardLiveWindow *inWindowActor)
380 {
381 XfdashboardWindowsViewPrivate *priv;
382 XfdashboardWindowTrackerWindow *window;
383 XfdashboardWindowTrackerWorkspace *sourceWorkspace;
384 XfdashboardWindowTrackerWorkspace *targetWorkspace;
385 XfdashboardWindowTrackerMonitor *sourceMonitor;
386 XfdashboardWindowTrackerMonitor *targetMonitor;
387 gint oldWindowX, oldWindowY, oldWindowWidth, oldWindowHeight;
388 gint newWindowX, newWindowY;
389 gint oldMonitorX, oldMonitorY, oldMonitorWidth, oldMonitorHeight;
390 gint newMonitorX, newMonitorY, newMonitorWidth, newMonitorHeight;
391 gfloat relativeX, relativeY;
392
393 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
394 g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(inWindowActor));
395
396 priv=self->priv;
397
398 /* Get window from window actor */
399 window=xfdashboard_live_window_simple_get_window(XFDASHBOARD_LIVE_WINDOW_SIMPLE(inWindowActor));
400
401 /* Get source and target workspace */
402 sourceWorkspace=xfdashboard_window_tracker_window_get_workspace(window);
403 targetWorkspace=priv->workspace;
404
405 /* Get source and target monitor */
406 sourceMonitor=xfdashboard_window_tracker_window_get_monitor(window);
407 targetMonitor=priv->currentMonitor;
408
409 XFDASHBOARD_DEBUG(self, ACTOR,
410 "Moving window '%s' from %s-monitor %d to %s-monitor %d and from workspace '%s' (%d) to '%s' (%d)",
411 xfdashboard_window_tracker_window_get_name(window),
412 xfdashboard_window_tracker_monitor_is_primary(sourceMonitor) ? "primary" : "secondary",
413 xfdashboard_window_tracker_monitor_get_number(sourceMonitor),
414 xfdashboard_window_tracker_monitor_is_primary(targetMonitor) ? "primary" : "secondary",
415 xfdashboard_window_tracker_monitor_get_number(targetMonitor),
416 xfdashboard_window_tracker_workspace_get_name(sourceWorkspace),
417 xfdashboard_window_tracker_workspace_get_number(sourceWorkspace),
418 xfdashboard_window_tracker_workspace_get_name(targetWorkspace),
419 xfdashboard_window_tracker_workspace_get_number(targetWorkspace));
420
421 /* Get position and size of window to move */
422 xfdashboard_window_tracker_window_get_geometry(window,
423 &oldWindowX,
424 &oldWindowY,
425 &oldWindowWidth,
426 &oldWindowHeight);
427
428 /* Calculate source x and y coordinate relative to monitor size in percent */
429 xfdashboard_window_tracker_monitor_get_geometry(sourceMonitor,
430 &oldMonitorX,
431 &oldMonitorY,
432 &oldMonitorWidth,
433 &oldMonitorHeight);
434 relativeX=((gfloat)(oldWindowX-oldMonitorX)) / ((gfloat)oldMonitorWidth);
435 relativeY=((gfloat)(oldWindowY-oldMonitorY)) / ((gfloat)oldMonitorHeight);
436
437 /* Calculate target x and y coordinate from relative size in percent to monitor size */
438 xfdashboard_window_tracker_monitor_get_geometry(targetMonitor,
439 &newMonitorX,
440 &newMonitorY,
441 &newMonitorWidth,
442 &newMonitorHeight);
443 newWindowX=newMonitorX+((gint)(relativeX*newMonitorWidth));
444 newWindowY=newMonitorY+((gint)(relativeY*newMonitorHeight));
445
446 /* Move window to workspace if they are not the same */
447 if(!xfdashboard_window_tracker_workspace_is_equal(sourceWorkspace, targetWorkspace))
448 {
449 xfdashboard_window_tracker_window_move_to_workspace(window, targetWorkspace);
450 XFDASHBOARD_DEBUG(self, ACTOR,
451 "Moved window '%s' from workspace '%s' (%d) to '%s' (%d)",
452 xfdashboard_window_tracker_window_get_name(window),
453 xfdashboard_window_tracker_workspace_get_name(sourceWorkspace),
454 xfdashboard_window_tracker_workspace_get_number(sourceWorkspace),
455 xfdashboard_window_tracker_workspace_get_name(targetWorkspace),
456 xfdashboard_window_tracker_workspace_get_number(targetWorkspace));
457 }
458
459 /* Move window to new position */
460 xfdashboard_window_tracker_window_move(window, newWindowX, newWindowY);
461 XFDASHBOARD_DEBUG(self, ACTOR,
462 "Moved window '%s' from [%d,%d] at monitor [%d,%d x %d,%d] to [%d,%d] at monitor [%d,%d x %d,%d] (relative x=%.2f, y=%.2f)",
463 xfdashboard_window_tracker_window_get_name(window),
464 oldWindowX, oldWindowY,
465 oldMonitorX, oldMonitorY, oldMonitorWidth, oldMonitorHeight,
466 newWindowX, newWindowY,
467 newMonitorX, newMonitorY, newMonitorWidth, newMonitorHeight,
468 relativeX, relativeY);
469 }
470
471 /* Drag of an actor to this view as drop target begins */
_xfdashboard_windows_view_on_drop_begin(XfdashboardWindowsView * self,XfdashboardDragAction * inDragAction,gpointer inUserData)472 static gboolean _xfdashboard_windows_view_on_drop_begin(XfdashboardWindowsView *self,
473 XfdashboardDragAction *inDragAction,
474 gpointer inUserData)
475 {
476 ClutterActor *dragSource;
477 ClutterActor *draggedActor;
478 gboolean canHandle;
479
480 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), FALSE);
481 g_return_val_if_fail(XFDASHBOARD_IS_DRAG_ACTION(inDragAction), FALSE);
482 g_return_val_if_fail(XFDASHBOARD_IS_DROP_ACTION(inUserData), FALSE);
483
484 canHandle=FALSE;
485
486 /* Get source where dragging started and actor being dragged */
487 dragSource=xfdashboard_drag_action_get_source(inDragAction);
488 draggedActor=xfdashboard_drag_action_get_actor(inDragAction);
489
490 /* We can handle dragged actor if it is an application button and its source
491 * is quicklaunch.
492 */
493 if(XFDASHBOARD_IS_QUICKLAUNCH(dragSource) &&
494 XFDASHBOARD_IS_APPLICATION_BUTTON(draggedActor))
495 {
496 canHandle=TRUE;
497 }
498
499 /* We can handle dragged actor if it is a live window and its source
500 * is windows view.
501 */
502 if(XFDASHBOARD_IS_WINDOWS_VIEW(dragSource) &&
503 XFDASHBOARD_IS_LIVE_WINDOW(draggedActor))
504 {
505 canHandle=TRUE;
506 }
507
508 /* We can handle dragged actor if it is a live window and its source
509 * is a live workspace
510 */
511 if(XFDASHBOARD_IS_LIVE_WORKSPACE(dragSource) &&
512 XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(draggedActor))
513 {
514 canHandle=TRUE;
515 }
516
517 /* Return TRUE if we can handle dragged actor in this drop target
518 * otherwise FALSE
519 */
520 return(canHandle);
521 }
522
523 /* Dragged actor was dropped on this drop target */
_xfdashboard_windows_view_on_drop_drop(XfdashboardWindowsView * self,XfdashboardDragAction * inDragAction,gfloat inX,gfloat inY,gpointer inUserData)524 static void _xfdashboard_windows_view_on_drop_drop(XfdashboardWindowsView *self,
525 XfdashboardDragAction *inDragAction,
526 gfloat inX,
527 gfloat inY,
528 gpointer inUserData)
529 {
530 XfdashboardWindowsViewPrivate *priv;
531 ClutterActor *dragSource;
532 ClutterActor *draggedActor;
533 GAppLaunchContext *context;
534
535 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
536 g_return_if_fail(XFDASHBOARD_IS_DRAG_ACTION(inDragAction));
537 g_return_if_fail(XFDASHBOARD_IS_DROP_ACTION(inUserData));
538
539 priv=self->priv;
540
541 /* Get source where dragging started and actor being dragged */
542 dragSource=xfdashboard_drag_action_get_source(inDragAction);
543 draggedActor=xfdashboard_drag_action_get_actor(inDragAction);
544
545 /* Handle drop of an application button from quicklaunch */
546 if(XFDASHBOARD_IS_QUICKLAUNCH(dragSource) &&
547 XFDASHBOARD_IS_APPLICATION_BUTTON(draggedActor))
548 {
549 /* Launch application being dragged here */
550 context=xfdashboard_create_app_context(priv->workspace);
551 xfdashboard_application_button_execute(XFDASHBOARD_APPLICATION_BUTTON(draggedActor), context);
552 g_object_unref(context);
553
554 /* Drop action handled so return here */
555 return;
556 }
557
558 /* Handle drop of an window from another windows view */
559 if(XFDASHBOARD_IS_WINDOWS_VIEW(dragSource) &&
560 XFDASHBOARD_IS_LIVE_WINDOW(draggedActor))
561 {
562 XfdashboardWindowsView *sourceWindowsView;
563 XfdashboardLiveWindow *liveWindowActor;
564
565 /* Get source windows view */
566 sourceWindowsView=XFDASHBOARD_WINDOWS_VIEW(dragSource);
567
568 /* Do nothing if source windows view is the same as target windows view
569 * that means this one.
570 */
571 if(sourceWindowsView==self)
572 {
573 XFDASHBOARD_DEBUG(self, ACTOR,
574 "Will not handle drop of %s at %s because source and target are the same.",
575 G_OBJECT_TYPE_NAME(draggedActor),
576 G_OBJECT_TYPE_NAME(dragSource));
577 return;
578 }
579
580 /* Get dragged window */
581 liveWindowActor=XFDASHBOARD_LIVE_WINDOW(draggedActor);
582
583 /* Move dragged window to monitor of this window view */
584 _xfdashboard_windows_view_move_live_to_view(self, liveWindowActor);
585
586 /* Drop action handled so return here */
587 return;
588 }
589
590 /* Handle drop of an window from a live workspace */
591 if(XFDASHBOARD_IS_LIVE_WORKSPACE(dragSource) &&
592 XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(draggedActor))
593 {
594 XfdashboardLiveWorkspace *sourceLiveWorkspace;
595 XfdashboardWindowTrackerWorkspace* sourceWorkspace;
596 XfdashboardLiveWindowSimple *liveWindowActor;
597 XfdashboardWindowTrackerWindow *window;
598
599 /* Get source live workspace and its workspace */
600 sourceLiveWorkspace=XFDASHBOARD_LIVE_WORKSPACE(dragSource);
601 sourceWorkspace=xfdashboard_live_workspace_get_workspace(sourceLiveWorkspace);
602
603 /* Do nothing if source and destination workspaces are the same as nothing
604 * is to do in this case.
605 */
606 if(xfdashboard_window_tracker_workspace_is_equal(sourceWorkspace, priv->workspace))
607 {
608 XFDASHBOARD_DEBUG(self, ACTOR,
609 "Will not handle drop of %s at %s because source and target workspaces are the same.",
610 G_OBJECT_TYPE_NAME(draggedActor),
611 G_OBJECT_TYPE_NAME(dragSource));
612 return;
613 }
614
615 /* Get dragged window */
616 liveWindowActor=XFDASHBOARD_LIVE_WINDOW_SIMPLE(draggedActor);
617 window=xfdashboard_live_window_simple_get_window(liveWindowActor);
618
619 /* Move dragged window to workspace of this window view */
620 xfdashboard_window_tracker_window_move_to_workspace(window, priv->workspace);
621
622 /* Drop action handled so return here */
623 return;
624 }
625
626 /* If we get here we did not handle drop action properly
627 * and this should never happen.
628 */
629 g_critical("Did not handle drop action for dragged actor %s of source %s at target %s",
630 G_OBJECT_TYPE_NAME(draggedActor),
631 G_OBJECT_TYPE_NAME(dragSource),
632 G_OBJECT_TYPE_NAME(self));
633 }
634
635 /* A child actor was added to view */
_xfdashboard_windows_view_on_child_added(ClutterContainer * inContainer,ClutterActor * inChild,gpointer inUserData)636 static void _xfdashboard_windows_view_on_child_added(ClutterContainer *inContainer,
637 ClutterActor *inChild,
638 gpointer inUserData)
639 {
640 ClutterActorIter iter;
641 ClutterActor *child;
642
643 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inContainer));
644
645 /* Iterate through list of current actors and enable allocation animation */
646 clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
647 while(clutter_actor_iter_next(&iter, &child))
648 {
649 if(XFDASHBOARD_IS_ACTOR(child))
650 {
651 xfdashboard_actor_enable_allocation_animation_once(XFDASHBOARD_ACTOR(child));
652 }
653 }
654 }
655
656 /* A child actor was removed from view */
_xfdashboard_windows_view_on_child_removed(ClutterContainer * inContainer,ClutterActor * inChild,gpointer inUserData)657 static void _xfdashboard_windows_view_on_child_removed(ClutterContainer *inContainer,
658 ClutterActor *inChild,
659 gpointer inUserData)
660 {
661 ClutterActorIter iter;
662 ClutterActor *child;
663
664 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inContainer));
665
666 /* Iterate through list of current actors and enable allocation animation */
667 clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
668 while(clutter_actor_iter_next(&iter, &child))
669 {
670 if(XFDASHBOARD_IS_ACTOR(child))
671 {
672 xfdashboard_actor_enable_allocation_animation_once(XFDASHBOARD_ACTOR(child));
673 }
674 }
675 }
676
677 /* Active workspace was changed */
_xfdashboard_windows_view_on_active_workspace_changed(XfdashboardWindowsView * self,XfdashboardWindowTrackerWorkspace * inPrevWorkspace,XfdashboardWindowTrackerWorkspace * inNewWorkspace,gpointer inUserData)678 static void _xfdashboard_windows_view_on_active_workspace_changed(XfdashboardWindowsView *self,
679 XfdashboardWindowTrackerWorkspace *inPrevWorkspace,
680 XfdashboardWindowTrackerWorkspace *inNewWorkspace,
681 gpointer inUserData)
682 {
683 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
684
685 /* Update window list */
686 _xfdashboard_windows_view_set_active_workspace(self, inNewWorkspace);
687 }
688
689 /* A window was opened */
_xfdashboard_windows_view_on_window_opened(XfdashboardWindowsView * self,XfdashboardWindowTrackerWindow * inWindow,gpointer inUserData)690 static void _xfdashboard_windows_view_on_window_opened(XfdashboardWindowsView *self,
691 XfdashboardWindowTrackerWindow *inWindow,
692 gpointer inUserData)
693 {
694 XfdashboardLiveWindow *liveWindow;
695
696 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
697 g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow));
698
699 /* Check if parent stage interface changed. If not just add window actor.
700 * Otherwise recreate all window actors for changed stage interface and
701 * monitor.
702 */
703 if(!_xfdashboard_windows_view_update_stage_and_monitor(self))
704 {
705 /* Check if window is visible on this workspace */
706 if(!_xfdashboard_windows_view_is_visible_window(self, inWindow)) return;
707
708 /* Create actor if it does not exist already */
709 liveWindow=_xfdashboard_windows_view_find_by_window(self, inWindow);
710 if(G_LIKELY(!liveWindow))
711 {
712 liveWindow=_xfdashboard_windows_view_create_actor(self, inWindow);
713 if(liveWindow)
714 {
715 clutter_actor_insert_child_below(CLUTTER_ACTOR(self), CLUTTER_ACTOR(liveWindow), NULL);
716 _xfdashboard_windows_view_update_window_number_in_actors(self);
717 }
718 }
719 }
720 else
721 {
722 /* Recreate all window actors because parent stage interface changed */
723 _xfdashboard_windows_view_recreate_window_actors(self);
724 }
725 }
726
727 /* A window has changed monitor */
_xfdashboard_windows_view_on_window_monitor_changed(XfdashboardWindowsView * self,XfdashboardWindowTrackerWindow * inWindow,XfdashboardWindowTrackerMonitor * inOldMonitor,XfdashboardWindowTrackerMonitor * inNewMonitor,gpointer inUserData)728 static void _xfdashboard_windows_view_on_window_monitor_changed(XfdashboardWindowsView *self,
729 XfdashboardWindowTrackerWindow *inWindow,
730 XfdashboardWindowTrackerMonitor *inOldMonitor,
731 XfdashboardWindowTrackerMonitor *inNewMonitor,
732 gpointer inUserData)
733 {
734 XfdashboardWindowsViewPrivate *priv;
735 XfdashboardLiveWindow *liveWindow;
736
737 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
738 g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow));
739 g_return_if_fail(inOldMonitor==NULL || XFDASHBOARD_IS_WINDOW_TRACKER_MONITOR(inOldMonitor));
740 g_return_if_fail(inNewMonitor==NULL || XFDASHBOARD_IS_WINDOW_TRACKER_MONITOR(inNewMonitor));
741
742 priv=self->priv;
743
744 /* Check if parent stage interface changed. If not check if window has
745 * moved away from this view and destroy it or it has moved to this view
746 * and create it. Otherwise recreate all window actors for changed stage
747 * interface and monitor.
748 */
749 if(!_xfdashboard_windows_view_update_stage_and_monitor(self) &&
750 G_LIKELY(!inOldMonitor) &&
751 G_LIKELY(!inNewMonitor))
752 {
753 /* Check if window moved away from this view */
754 if(priv->currentMonitor==inOldMonitor &&
755 !_xfdashboard_windows_view_is_visible_window(self, inWindow))
756 {
757 /* Find live window for window to destroy it */
758 liveWindow=_xfdashboard_windows_view_find_by_window(self, inWindow);
759 if(G_LIKELY(liveWindow))
760 {
761 /* Destroy actor */
762 xfdashboard_actor_destroy(CLUTTER_ACTOR(liveWindow));
763 }
764 }
765
766 /* Check if window moved to this view */
767 if(priv->currentMonitor==inNewMonitor &&
768 _xfdashboard_windows_view_is_visible_window(self, inWindow))
769 {
770 /* Create actor if it does not exist already */
771 liveWindow=_xfdashboard_windows_view_find_by_window(self, inWindow);
772 if(G_LIKELY(!liveWindow))
773 {
774 liveWindow=_xfdashboard_windows_view_create_actor(self, inWindow);
775 if(liveWindow)
776 {
777 clutter_actor_insert_child_below(CLUTTER_ACTOR(self), CLUTTER_ACTOR(liveWindow), NULL);
778 _xfdashboard_windows_view_update_window_number_in_actors(self);
779 }
780 }
781 }
782 }
783 else
784 {
785 /* Recreate all window actors because parent stage interface changed */
786 _xfdashboard_windows_view_recreate_window_actors(self);
787 }
788 }
789
790 /* A live window was clicked */
_xfdashboard_windows_view_on_window_clicked(XfdashboardWindowsView * self,gpointer inUserData)791 static void _xfdashboard_windows_view_on_window_clicked(XfdashboardWindowsView *self,
792 gpointer inUserData)
793 {
794 XfdashboardWindowsViewPrivate *priv;
795 XfdashboardLiveWindowSimple *liveWindow;
796 XfdashboardWindowTrackerWindow *window;
797 XfdashboardWindowTrackerWorkspace *activeWorkspace;
798 XfdashboardWindowTrackerWorkspace *windowWorkspace;
799
800 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
801 g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(inUserData));
802
803 priv=self->priv;
804 liveWindow=XFDASHBOARD_LIVE_WINDOW_SIMPLE(inUserData);
805
806 /* Get window to activate */
807 window=xfdashboard_live_window_simple_get_window(liveWindow);
808
809 /* Move to workspace if window to active is on a different one than the active one */
810 activeWorkspace=xfdashboard_window_tracker_get_active_workspace(priv->windowTracker);
811 if(!xfdashboard_window_tracker_window_is_on_workspace(window, activeWorkspace))
812 {
813 windowWorkspace=xfdashboard_window_tracker_window_get_workspace(window);
814 xfdashboard_window_tracker_workspace_activate(windowWorkspace);
815 }
816
817 /* Activate window */
818 xfdashboard_window_tracker_window_activate(window);
819
820 /* Quit application */
821 xfdashboard_application_suspend_or_quit(NULL);
822 }
823
824 /* The close button of a live window was clicked */
_xfdashboard_windows_view_on_window_close_clicked(XfdashboardWindowsView * self,gpointer inUserData)825 static void _xfdashboard_windows_view_on_window_close_clicked(XfdashboardWindowsView *self,
826 gpointer inUserData)
827 {
828 XfdashboardLiveWindowSimple *liveWindow;
829 XfdashboardWindowTrackerWindow *window;
830
831 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
832 g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(inUserData));
833
834 liveWindow=XFDASHBOARD_LIVE_WINDOW_SIMPLE(inUserData);
835
836 /* Close clicked window */
837 window=XFDASHBOARD_WINDOW_TRACKER_WINDOW(xfdashboard_live_window_simple_get_window(liveWindow));
838 xfdashboard_window_tracker_window_close(window);
839 }
840
841 /* A window was moved or resized */
_xfdashboard_windows_view_on_window_geometry_changed(XfdashboardWindowsView * self,gpointer inUserData)842 static void _xfdashboard_windows_view_on_window_geometry_changed(XfdashboardWindowsView *self,
843 gpointer inUserData)
844 {
845 XfdashboardLiveWindow *liveWindow;
846
847 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
848 g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(inUserData));
849
850 liveWindow=XFDASHBOARD_LIVE_WINDOW(inUserData);
851
852 /* Force a relayout to reflect new size of window */
853 clutter_actor_queue_relayout(CLUTTER_ACTOR(liveWindow));
854 }
855
856 /* A window was hidden or shown */
_xfdashboard_windows_view_on_window_visibility_changed(XfdashboardWindowsView * self,gboolean inIsVisible,gpointer inUserData)857 static void _xfdashboard_windows_view_on_window_visibility_changed(XfdashboardWindowsView *self,
858 gboolean inIsVisible,
859 gpointer inUserData)
860 {
861 XfdashboardLiveWindow *liveWindow;
862
863 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
864 g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(inUserData));
865
866 liveWindow=XFDASHBOARD_LIVE_WINDOW(inUserData);
867
868 /* If window is shown, show it in window list - otherwise hide it.
869 * We should not destroy the live window actor as the window might
870 * get visible again.
871 */
872 if(inIsVisible) clutter_actor_show(CLUTTER_ACTOR(liveWindow));
873 else
874 {
875 /* Hide actor */
876 clutter_actor_hide(CLUTTER_ACTOR(liveWindow));
877 }
878 }
879
880 /* A window changed workspace or was pinned to all workspaces */
_xfdashboard_windows_view_on_window_workspace_changed(XfdashboardWindowsView * self,XfdashboardWindowTrackerWindow * inWindow,XfdashboardWindowTrackerWorkspace * inWorkspace,gpointer inUserData)881 static void _xfdashboard_windows_view_on_window_workspace_changed(XfdashboardWindowsView *self,
882 XfdashboardWindowTrackerWindow *inWindow,
883 XfdashboardWindowTrackerWorkspace *inWorkspace,
884 gpointer inUserData)
885 {
886 XfdashboardWindowsViewPrivate *priv;
887 XfdashboardLiveWindow *liveWindow;
888
889 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
890 g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow));
891 g_return_if_fail(!inWorkspace || XFDASHBOARD_IS_WINDOW_TRACKER_WORKSPACE(inWorkspace));
892
893 priv=self->priv;
894
895 /* Check if parent stage interface changed. If not check if window has
896 * moved away from this view and destroy it or it has moved to this view
897 * and create it. Otherwise recreate all window actors for changed stage
898 * interface and monitor.
899 */
900 if(!_xfdashboard_windows_view_update_stage_and_monitor(self))
901 {
902 /* Check if window moved away from this view*/
903 if(priv->workspace!=inWorkspace &&
904 !_xfdashboard_windows_view_is_visible_window(self, inWindow))
905 {
906 /* Find live window for window to destroy it */
907 liveWindow=_xfdashboard_windows_view_find_by_window(self, inWindow);
908 if(G_LIKELY(liveWindow))
909 {
910 /* Destroy actor */
911 xfdashboard_actor_destroy(CLUTTER_ACTOR(liveWindow));
912 }
913 }
914
915 /* Check if window moved to this view */
916 if(priv->workspace==inWorkspace &&
917 _xfdashboard_windows_view_is_visible_window(self, inWindow))
918 {
919 /* Create actor if it does not exist already */
920 liveWindow=_xfdashboard_windows_view_find_by_window(self, inWindow);
921 if(G_LIKELY(!liveWindow))
922 {
923 liveWindow=_xfdashboard_windows_view_create_actor(self, inWindow);
924 if(liveWindow)
925 {
926 clutter_actor_insert_child_below(CLUTTER_ACTOR(self), CLUTTER_ACTOR(liveWindow), NULL);
927 _xfdashboard_windows_view_update_window_number_in_actors(self);
928 }
929 }
930 }
931 }
932 else
933 {
934 /* Recreate all window actors because parent stage interface changed */
935 _xfdashboard_windows_view_recreate_window_actors(self);
936 }
937 }
938
939 /* Drag of a live window begins */
_xfdashboard_windows_view_on_drag_begin(ClutterDragAction * inAction,ClutterActor * inActor,gfloat inStageX,gfloat inStageY,ClutterModifierType inModifiers,gpointer inUserData)940 static void _xfdashboard_windows_view_on_drag_begin(ClutterDragAction *inAction,
941 ClutterActor *inActor,
942 gfloat inStageX,
943 gfloat inStageY,
944 ClutterModifierType inModifiers,
945 gpointer inUserData)
946 {
947 ClutterActor *dragHandle;
948 ClutterStage *stage;
949 GdkPixbuf *windowIcon;
950 ClutterContent *image;
951 XfdashboardLiveWindowSimple *liveWindow;
952
953 g_return_if_fail(CLUTTER_IS_DRAG_ACTION(inAction));
954 g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(inActor));
955 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inUserData));
956
957 liveWindow=XFDASHBOARD_LIVE_WINDOW_SIMPLE(inActor);
958
959 /* Prevent signal "clicked" from being emitted on dragged icon */
960 g_signal_handlers_block_by_func(inActor, _xfdashboard_windows_view_on_window_clicked, inUserData);
961
962 /* Get stage */
963 stage=CLUTTER_STAGE(clutter_actor_get_stage(inActor));
964
965 /* Create a application icon for drag handle */
966 windowIcon=xfdashboard_window_tracker_window_get_icon(xfdashboard_live_window_simple_get_window(liveWindow));
967 image=xfdashboard_image_content_new_for_pixbuf(windowIcon);
968
969 dragHandle=xfdashboard_background_new();
970 clutter_actor_set_position(dragHandle, inStageX, inStageY);
971 clutter_actor_set_size(dragHandle, DEFAULT_DRAG_HANDLE_SIZE, DEFAULT_DRAG_HANDLE_SIZE);
972 xfdashboard_background_set_image(XFDASHBOARD_BACKGROUND(dragHandle), CLUTTER_IMAGE(image));
973 clutter_actor_add_child(CLUTTER_ACTOR(stage), dragHandle);
974
975 clutter_drag_action_set_drag_handle(inAction, dragHandle);
976
977 g_object_unref(image);
978 }
979
980 /* Drag of a live window ends */
_xfdashboard_windows_view_on_drag_end(ClutterDragAction * inAction,ClutterActor * inActor,gfloat inStageX,gfloat inStageY,ClutterModifierType inModifiers,gpointer inUserData)981 static void _xfdashboard_windows_view_on_drag_end(ClutterDragAction *inAction,
982 ClutterActor *inActor,
983 gfloat inStageX,
984 gfloat inStageY,
985 ClutterModifierType inModifiers,
986 gpointer inUserData)
987 {
988 ClutterActor *dragHandle;
989
990 g_return_if_fail(CLUTTER_IS_DRAG_ACTION(inAction));
991 g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(inActor));
992 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inUserData));
993
994 /* Destroy clone of application icon used as drag handle */
995 dragHandle=clutter_drag_action_get_drag_handle(inAction);
996 if(dragHandle)
997 {
998 #if CLUTTER_CHECK_VERSION(1, 14, 0)
999 /* Only unset drag handle if not running Clutter in version
1000 * 1.12. This prevents a critical warning message in 1.12.
1001 * Later versions of Clutter are fixed already.
1002 */
1003 clutter_drag_action_set_drag_handle(inAction, NULL);
1004 #endif
1005 xfdashboard_actor_destroy(dragHandle);
1006 }
1007
1008 /* Allow signal "clicked" from being emitted again */
1009 g_signal_handlers_unblock_by_func(inActor, _xfdashboard_windows_view_on_window_clicked, inUserData);
1010 }
1011
1012 /* Create actor for wnck-window and connect signals */
_xfdashboard_windows_view_create_actor(XfdashboardWindowsView * self,XfdashboardWindowTrackerWindow * inWindow)1013 static XfdashboardLiveWindow* _xfdashboard_windows_view_create_actor(XfdashboardWindowsView *self,
1014 XfdashboardWindowTrackerWindow *inWindow)
1015 {
1016 ClutterActor *actor;
1017 ClutterAction *dragAction;
1018
1019 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), NULL);
1020 g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), NULL);
1021
1022 /* Check if window opened is a stage window */
1023 if(xfdashboard_window_tracker_window_is_stage(inWindow))
1024 {
1025 XFDASHBOARD_DEBUG(self, ACTOR, "Will not create live-window actor for stage window.");
1026 return(NULL);
1027 }
1028
1029 /* Create actor and connect signals */
1030 actor=xfdashboard_live_window_new();
1031 g_signal_connect_swapped(actor, "clicked", G_CALLBACK(_xfdashboard_windows_view_on_window_clicked), self);
1032 g_signal_connect_swapped(actor, "close", G_CALLBACK(_xfdashboard_windows_view_on_window_close_clicked), self);
1033 g_signal_connect_swapped(actor, "geometry-changed", G_CALLBACK(_xfdashboard_windows_view_on_window_geometry_changed), self);
1034 g_signal_connect_swapped(actor, "visibility-changed", G_CALLBACK(_xfdashboard_windows_view_on_window_visibility_changed), self);
1035 xfdashboard_live_window_simple_set_window(XFDASHBOARD_LIVE_WINDOW_SIMPLE(actor), inWindow);
1036
1037 dragAction=xfdashboard_drag_action_new_with_source(CLUTTER_ACTOR(self));
1038 clutter_drag_action_set_drag_threshold(CLUTTER_DRAG_ACTION(dragAction), -1, -1);
1039 clutter_actor_add_action(actor, dragAction);
1040 g_signal_connect(dragAction, "drag-begin", G_CALLBACK(_xfdashboard_windows_view_on_drag_begin), self);
1041 g_signal_connect(dragAction, "drag-end", G_CALLBACK(_xfdashboard_windows_view_on_drag_end), self);
1042
1043 return(XFDASHBOARD_LIVE_WINDOW(actor));
1044 }
1045
1046 /* Set active screen */
_xfdashboard_windows_view_set_active_workspace(XfdashboardWindowsView * self,XfdashboardWindowTrackerWorkspace * inWorkspace)1047 static void _xfdashboard_windows_view_set_active_workspace(XfdashboardWindowsView *self,
1048 XfdashboardWindowTrackerWorkspace *inWorkspace)
1049 {
1050 XfdashboardWindowsViewPrivate *priv;
1051
1052 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
1053 g_return_if_fail(inWorkspace==NULL || XFDASHBOARD_IS_WINDOW_TRACKER_WORKSPACE(inWorkspace));
1054
1055 priv=XFDASHBOARD_WINDOWS_VIEW(self)->priv;
1056
1057 /* Check if parent stage interface or workspace changed. If both have not
1058 * changed do nothing and return immediately.
1059 */
1060 if(!_xfdashboard_windows_view_update_stage_and_monitor(self) &&
1061 inWorkspace==priv->workspace)
1062 {
1063 return;
1064 }
1065
1066 /* Freeze notification */
1067 g_object_freeze_notify(G_OBJECT(self));
1068
1069 /* Set new workspace if changed */
1070 if(priv->workspace!=inWorkspace)
1071 {
1072 /* Set new workspace */
1073 priv->workspace=inWorkspace;
1074
1075 /* Notify about property change */
1076 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardWindowsViewProperties[PROP_WORKSPACE]);
1077 }
1078
1079 /* Recreate all window actors */
1080 _xfdashboard_windows_view_recreate_window_actors(self);
1081
1082 /* Thaw notification */
1083 g_object_thaw_notify(G_OBJECT(self));
1084 }
1085
1086 /* A scroll event occured in workspace selector (e.g. by mouse-wheel) */
_xfdashboard_windows_view_on_scroll_event(ClutterActor * inActor,ClutterEvent * inEvent,gpointer inUserData)1087 static gboolean _xfdashboard_windows_view_on_scroll_event(ClutterActor *inActor,
1088 ClutterEvent *inEvent,
1089 gpointer inUserData)
1090 {
1091 XfdashboardWindowsView *self;
1092 XfdashboardWindowsViewPrivate *priv;
1093 gint direction;
1094 gint workspace;
1095 gint maxWorkspace;
1096 XfdashboardWindowTrackerWorkspace *activeWorkspace;
1097 XfdashboardWindowTrackerWorkspace *newWorkspace;
1098
1099 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inActor), CLUTTER_EVENT_PROPAGATE);
1100 g_return_val_if_fail(inEvent, CLUTTER_EVENT_PROPAGATE);
1101
1102 self=XFDASHBOARD_WINDOWS_VIEW(inActor);
1103 priv=self->priv;
1104
1105 /* Do not handle event if scroll event of mouse-wheel should not
1106 * change workspace. In this case propagate event to get it handled
1107 * by next actor in chain.
1108 */
1109 if(!priv->isScrollEventChangingWorkspace) return(CLUTTER_EVENT_PROPAGATE);
1110
1111 /* Get direction of scroll event */
1112 switch(clutter_event_get_scroll_direction(inEvent))
1113 {
1114 case CLUTTER_SCROLL_UP:
1115 case CLUTTER_SCROLL_LEFT:
1116 direction=-1;
1117 break;
1118
1119 case CLUTTER_SCROLL_DOWN:
1120 case CLUTTER_SCROLL_RIGHT:
1121 direction=1;
1122 break;
1123
1124 /* Unhandled directions */
1125 default:
1126 XFDASHBOARD_DEBUG(self, ACTOR,
1127 "Cannot handle scroll direction %d in %s",
1128 clutter_event_get_scroll_direction(inEvent),
1129 G_OBJECT_TYPE_NAME(self));
1130 return(CLUTTER_EVENT_PROPAGATE);
1131 }
1132
1133 /* Get next workspace in scroll direction */
1134 activeWorkspace=xfdashboard_window_tracker_get_active_workspace(priv->windowTracker);
1135 maxWorkspace=xfdashboard_window_tracker_get_workspaces_count(priv->windowTracker);
1136
1137 workspace=xfdashboard_window_tracker_workspace_get_number(activeWorkspace)+direction;
1138 if(workspace<0 || workspace>=maxWorkspace) return(CLUTTER_EVENT_STOP);
1139
1140 /* Activate new workspace */
1141 newWorkspace=xfdashboard_window_tracker_get_workspace_by_number(priv->windowTracker, workspace);
1142 xfdashboard_window_tracker_workspace_activate(newWorkspace);
1143
1144 return(CLUTTER_EVENT_STOP);
1145 }
1146
1147 /* Set flag if scroll events (e.g. mouse-wheel up or down) should change active workspace
1148 * and set up scroll event listener or remove an existing one.
1149 */
_xfdashboard_windows_view_set_scroll_event_changes_workspace(XfdashboardWindowsView * self,gboolean inMouseWheelChangingWorkspace)1150 static void _xfdashboard_windows_view_set_scroll_event_changes_workspace(XfdashboardWindowsView *self, gboolean inMouseWheelChangingWorkspace)
1151 {
1152 XfdashboardWindowsViewPrivate *priv;
1153
1154 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
1155
1156 priv=self->priv;
1157
1158 /* Set value if changed */
1159 if(priv->isScrollEventChangingWorkspace!=inMouseWheelChangingWorkspace)
1160 {
1161 /* Set value */
1162 priv->isScrollEventChangingWorkspace=inMouseWheelChangingWorkspace;
1163
1164 /* Notify about property change */
1165 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardWindowsViewProperties[PROP_SCROLL_EVENT_CHANGES_WORKSPACE]);
1166 }
1167 }
1168
1169 /* Set flag if this view should show all windows of all monitors or only the windows
1170 * which are at the monitor where this view is placed at.
1171 */
_xfdashboard_windows_view_set_filter_monitor_windows(XfdashboardWindowsView * self,gboolean inFilterMonitorWindows)1172 static void _xfdashboard_windows_view_set_filter_monitor_windows(XfdashboardWindowsView *self, gboolean inFilterMonitorWindows)
1173 {
1174 XfdashboardWindowsViewPrivate *priv;
1175
1176 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
1177
1178 priv=self->priv;
1179
1180 /* Set value if changed */
1181 if(priv->filterMonitorWindows!=inFilterMonitorWindows)
1182 {
1183 /* Set value */
1184 priv->filterMonitorWindows=inFilterMonitorWindows;
1185
1186 /* Recreate all window actors */
1187 _xfdashboard_windows_view_recreate_window_actors(self);
1188
1189 /* Notify about property change */
1190 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardWindowsViewProperties[PROP_FILTER_MONITOR_WINDOWS]);
1191 }
1192 }
1193
1194 /* Set flag if this view should show all windows of all workspaces or only the windows
1195 * which are at current workspace.
1196 */
_xfdashboard_windows_view_set_filter_workspace_windows(XfdashboardWindowsView * self,gboolean inFilterWorkspaceWindows)1197 static void _xfdashboard_windows_view_set_filter_workspace_windows(XfdashboardWindowsView *self, gboolean inFilterWorkspaceWindows)
1198 {
1199 XfdashboardWindowsViewPrivate *priv;
1200
1201 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
1202
1203 priv=self->priv;
1204
1205 /* Set value if changed */
1206 if(priv->filterWorkspaceWindows!=inFilterWorkspaceWindows)
1207 {
1208 /* Set value */
1209 priv->filterWorkspaceWindows=inFilterWorkspaceWindows;
1210
1211 /* Recreate all window actors */
1212 _xfdashboard_windows_view_recreate_window_actors(self);
1213
1214 /* Notify about property change */
1215 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardWindowsViewProperties[PROP_FILTER_WORKSPACE_WINDOWS]);
1216 }
1217 }
1218
1219 /* Action signal to close currently selected window was emitted */
_xfdashboard_windows_view_window_close(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1220 static gboolean _xfdashboard_windows_view_window_close(XfdashboardWindowsView *self,
1221 XfdashboardFocusable *inSource,
1222 const gchar *inAction,
1223 ClutterEvent *inEvent)
1224 {
1225 XfdashboardWindowsViewPrivate *priv;
1226
1227 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), CLUTTER_EVENT_PROPAGATE);
1228 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inSource), CLUTTER_EVENT_PROPAGATE);
1229
1230 priv=self->priv;
1231
1232 /* Check if a window is currenly selected */
1233 if(!priv->selectedItem)
1234 {
1235 XFDASHBOARD_DEBUG(self, ACTOR, "No window to close is selected.");
1236 return(CLUTTER_EVENT_STOP);
1237 }
1238
1239 /* Close selected window */
1240 _xfdashboard_windows_view_on_window_close_clicked(self, XFDASHBOARD_LIVE_WINDOW(priv->selectedItem));
1241
1242 /* We handled this event */
1243 return(CLUTTER_EVENT_STOP);
1244 }
1245
1246 /* Action signal to show window numbers was emitted */
_xfdashboard_windows_view_windows_show_numbers(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1247 static gboolean _xfdashboard_windows_view_windows_show_numbers(XfdashboardWindowsView *self,
1248 XfdashboardFocusable *inSource,
1249 const gchar *inAction,
1250 ClutterEvent *inEvent)
1251 {
1252 XfdashboardWindowsViewPrivate *priv;
1253
1254 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), CLUTTER_EVENT_PROPAGATE);
1255 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inSource), CLUTTER_EVENT_PROPAGATE);
1256
1257 priv=self->priv;
1258
1259 /* If window numbers are already shown do nothing */
1260 if(priv->isWindowsNumberShown) return(CLUTTER_EVENT_PROPAGATE);
1261
1262 /* Set flag that window numbers are shown already
1263 * to prevent do it twice concurrently.
1264 */
1265 priv->isWindowsNumberShown=TRUE;
1266
1267 /* Show window numbers */
1268 _xfdashboard_windows_view_update_window_number_in_actors(self);
1269
1270 /* Action handled but do not prevent further processing */
1271 return(CLUTTER_EVENT_PROPAGATE);
1272 }
1273
1274 /* Action signal to hide window numbers was emitted */
_xfdashboard_windows_view_windows_hide_numbers(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1275 static gboolean _xfdashboard_windows_view_windows_hide_numbers(XfdashboardWindowsView *self,
1276 XfdashboardFocusable *inSource,
1277 const gchar *inAction,
1278 ClutterEvent *inEvent)
1279 {
1280 XfdashboardWindowsViewPrivate *priv;
1281
1282 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), CLUTTER_EVENT_PROPAGATE);
1283 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inSource), CLUTTER_EVENT_PROPAGATE);
1284
1285 priv=self->priv;
1286
1287 /* If no window numbers are shown do nothing */
1288 if(!priv->isWindowsNumberShown) return(CLUTTER_EVENT_PROPAGATE);
1289
1290 /* Set flag that window numbers are hidden already
1291 * to prevent do it twice concurrently.
1292 */
1293 priv->isWindowsNumberShown=FALSE;
1294
1295 /* Hide window numbers */
1296 _xfdashboard_windows_view_update_window_number_in_actors(self);
1297
1298 /* Action handled but do not prevent further processing */
1299 return(CLUTTER_EVENT_PROPAGATE);
1300 }
1301
1302 /* Action signal to hide window numbers was emitted */
_xfdashboard_windows_view_windows_activate_window_by_number(XfdashboardWindowsView * self,guint inWindowNumber)1303 static gboolean _xfdashboard_windows_view_windows_activate_window_by_number(XfdashboardWindowsView *self,
1304 guint inWindowNumber)
1305 {
1306 ClutterActor *child;
1307 ClutterActorIter iter;
1308
1309 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), CLUTTER_EVENT_PROPAGATE);
1310
1311 /* Iterate through list of current actors and at each live window actor
1312 * check if its window number matches the requested one. If it does
1313 * activate this window.
1314 */
1315 clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self));
1316 while(clutter_actor_iter_next(&iter, &child))
1317 {
1318 guint windowNumber;
1319
1320 /* Only live window actors can be handled */
1321 if(!XFDASHBOARD_IS_LIVE_WINDOW(child)) continue;
1322
1323 /* Get window number set at live window actor */
1324 windowNumber=0;
1325 g_object_get(child, "window-number", &windowNumber, NULL);
1326
1327 /* If window number at live window actor matches requested one
1328 * activate this window.
1329 */
1330 if(windowNumber==inWindowNumber)
1331 {
1332 /* Activate window */
1333 _xfdashboard_windows_view_on_window_clicked(self, XFDASHBOARD_LIVE_WINDOW(child));
1334
1335 /* Action was handled */
1336 return(CLUTTER_EVENT_STOP);
1337 }
1338 }
1339
1340 /* If we get here the requested window was not found
1341 * so this action could not be handled by this actor.
1342 */
1343 return(CLUTTER_EVENT_PROPAGATE);
1344 }
1345
_xfdashboard_windows_view_windows_activate_window_one(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1346 static gboolean _xfdashboard_windows_view_windows_activate_window_one(XfdashboardWindowsView *self,
1347 XfdashboardFocusable *inSource,
1348 const gchar *inAction,
1349 ClutterEvent *inEvent)
1350 {
1351 return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 1));
1352 }
1353
_xfdashboard_windows_view_windows_activate_window_two(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1354 static gboolean _xfdashboard_windows_view_windows_activate_window_two(XfdashboardWindowsView *self,
1355 XfdashboardFocusable *inSource,
1356 const gchar *inAction,
1357 ClutterEvent *inEvent)
1358 {
1359 return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 2));
1360 }
1361
_xfdashboard_windows_view_windows_activate_window_three(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1362 static gboolean _xfdashboard_windows_view_windows_activate_window_three(XfdashboardWindowsView *self,
1363 XfdashboardFocusable *inSource,
1364 const gchar *inAction,
1365 ClutterEvent *inEvent)
1366 {
1367 return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 3));
1368 }
1369
_xfdashboard_windows_view_windows_activate_window_four(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1370 static gboolean _xfdashboard_windows_view_windows_activate_window_four(XfdashboardWindowsView *self,
1371 XfdashboardFocusable *inSource,
1372 const gchar *inAction,
1373 ClutterEvent *inEvent)
1374 {
1375 return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 4));
1376 }
1377
_xfdashboard_windows_view_windows_activate_window_five(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1378 static gboolean _xfdashboard_windows_view_windows_activate_window_five(XfdashboardWindowsView *self,
1379 XfdashboardFocusable *inSource,
1380 const gchar *inAction,
1381 ClutterEvent *inEvent)
1382 {
1383 return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 5));
1384 }
1385
_xfdashboard_windows_view_windows_activate_window_six(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1386 static gboolean _xfdashboard_windows_view_windows_activate_window_six(XfdashboardWindowsView *self,
1387 XfdashboardFocusable *inSource,
1388 const gchar *inAction,
1389 ClutterEvent *inEvent)
1390 {
1391 return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 6));
1392 }
1393
_xfdashboard_windows_view_windows_activate_window_seven(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1394 static gboolean _xfdashboard_windows_view_windows_activate_window_seven(XfdashboardWindowsView *self,
1395 XfdashboardFocusable *inSource,
1396 const gchar *inAction,
1397 ClutterEvent *inEvent)
1398 {
1399 return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 7));
1400 }
1401
_xfdashboard_windows_view_windows_activate_window_eight(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1402 static gboolean _xfdashboard_windows_view_windows_activate_window_eight(XfdashboardWindowsView *self,
1403 XfdashboardFocusable *inSource,
1404 const gchar *inAction,
1405 ClutterEvent *inEvent)
1406 {
1407 return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 8));
1408 }
1409
_xfdashboard_windows_view_windows_activate_window_nine(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1410 static gboolean _xfdashboard_windows_view_windows_activate_window_nine(XfdashboardWindowsView *self,
1411 XfdashboardFocusable *inSource,
1412 const gchar *inAction,
1413 ClutterEvent *inEvent)
1414 {
1415 return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 9));
1416 }
1417
_xfdashboard_windows_view_windows_activate_window_ten(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1418 static gboolean _xfdashboard_windows_view_windows_activate_window_ten(XfdashboardWindowsView *self,
1419 XfdashboardFocusable *inSource,
1420 const gchar *inAction,
1421 ClutterEvent *inEvent)
1422 {
1423 return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 10));
1424 }
1425
1426 /* IMPLEMENTATION: Interface XfdashboardFocusable */
1427
1428 /* Determine if actor can get the focus */
_xfdashboard_windows_view_focusable_can_focus(XfdashboardFocusable * inFocusable)1429 static gboolean _xfdashboard_windows_view_focusable_can_focus(XfdashboardFocusable *inFocusable)
1430 {
1431 XfdashboardWindowsView *self;
1432 XfdashboardFocusableInterface *selfIface;
1433 XfdashboardFocusableInterface *parentIface;
1434
1435 g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), FALSE);
1436 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inFocusable), FALSE);
1437
1438 self=XFDASHBOARD_WINDOWS_VIEW(inFocusable);
1439
1440 /* Call parent class interface function */
1441 selfIface=XFDASHBOARD_FOCUSABLE_GET_IFACE(inFocusable);
1442 parentIface=g_type_interface_peek_parent(selfIface);
1443
1444 if(parentIface && parentIface->can_focus)
1445 {
1446 if(!parentIface->can_focus(inFocusable)) return(FALSE);
1447 }
1448
1449 /* If this view is not enabled it is not focusable */
1450 if(!xfdashboard_view_get_enabled(XFDASHBOARD_VIEW(self))) return(FALSE);
1451
1452 /* If we get here this actor can be focused */
1453 return(TRUE);
1454 }
1455
1456 /* Actor lost focus */
_xfdashboard_windows_view_focusable_unset_focus(XfdashboardFocusable * inFocusable)1457 static void _xfdashboard_windows_view_focusable_unset_focus(XfdashboardFocusable *inFocusable)
1458 {
1459 XfdashboardWindowsView *self;
1460 XfdashboardFocusableInterface *selfIface;
1461 XfdashboardFocusableInterface *parentIface;
1462
1463 g_return_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable));
1464 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inFocusable));
1465
1466 self=XFDASHBOARD_WINDOWS_VIEW(inFocusable);
1467
1468 /* Call parent class interface function */
1469 selfIface=XFDASHBOARD_FOCUSABLE_GET_IFACE(inFocusable);
1470 parentIface=g_type_interface_peek_parent(selfIface);
1471
1472 if(parentIface && parentIface->unset_focus)
1473 {
1474 parentIface->unset_focus(inFocusable);
1475 }
1476
1477 /* Actor lost focus so ensure window numbers are hiding again */
1478 _xfdashboard_windows_view_windows_hide_numbers(self, XFDASHBOARD_FOCUSABLE(self), NULL, NULL);
1479 }
1480
1481 /* Determine if this actor supports selection */
_xfdashboard_windows_view_focusable_supports_selection(XfdashboardFocusable * inFocusable)1482 static gboolean _xfdashboard_windows_view_focusable_supports_selection(XfdashboardFocusable *inFocusable)
1483 {
1484 g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), FALSE);
1485 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inFocusable), FALSE);
1486
1487 /* This actor supports selection */
1488 return(TRUE);
1489 }
1490
1491 /* Get current selection */
_xfdashboard_windows_view_focusable_get_selection(XfdashboardFocusable * inFocusable)1492 static ClutterActor* _xfdashboard_windows_view_focusable_get_selection(XfdashboardFocusable *inFocusable)
1493 {
1494 XfdashboardWindowsView *self;
1495 XfdashboardWindowsViewPrivate *priv;
1496
1497 g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), NULL);
1498 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inFocusable), NULL);
1499
1500 self=XFDASHBOARD_WINDOWS_VIEW(inFocusable);
1501 priv=self->priv;
1502
1503 /* Return current selection */
1504 return(priv->selectedItem);
1505 }
1506
1507 /* Set new selection */
_xfdashboard_windows_view_focusable_set_selection(XfdashboardFocusable * inFocusable,ClutterActor * inSelection)1508 static gboolean _xfdashboard_windows_view_focusable_set_selection(XfdashboardFocusable *inFocusable,
1509 ClutterActor *inSelection)
1510 {
1511 XfdashboardWindowsView *self;
1512 XfdashboardWindowsViewPrivate *priv;
1513
1514 g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), FALSE);
1515 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inFocusable), FALSE);
1516 g_return_val_if_fail(!inSelection || CLUTTER_IS_ACTOR(inSelection), FALSE);
1517
1518 self=XFDASHBOARD_WINDOWS_VIEW(inFocusable);
1519 priv=self->priv;
1520
1521 /* Check that selection is a child of this actor */
1522 if(inSelection &&
1523 !clutter_actor_contains(CLUTTER_ACTOR(self), inSelection))
1524 {
1525 g_warning("%s is not a child of %s and cannot be selected",
1526 G_OBJECT_TYPE_NAME(inSelection),
1527 G_OBJECT_TYPE_NAME(self));
1528
1529 return(FALSE);
1530 }
1531
1532 /* Remove weak reference at current selection */
1533 if(priv->selectedItem)
1534 {
1535 g_object_remove_weak_pointer(G_OBJECT(priv->selectedItem), &priv->selectedItem);
1536 }
1537
1538 /* Set new selection */
1539 priv->selectedItem=inSelection;
1540
1541 /* Add weak reference at new selection */
1542 if(priv->selectedItem) g_object_add_weak_pointer(G_OBJECT(priv->selectedItem), &priv->selectedItem);
1543
1544 /* New selection was set successfully */
1545 return(TRUE);
1546 }
1547
1548 /* Find requested selection target depending of current selection */
_xfdashboard_windows_view_focusable_find_selection(XfdashboardFocusable * inFocusable,ClutterActor * inSelection,XfdashboardSelectionTarget inDirection)1549 static ClutterActor* _xfdashboard_windows_view_focusable_find_selection(XfdashboardFocusable *inFocusable,
1550 ClutterActor *inSelection,
1551 XfdashboardSelectionTarget inDirection)
1552 {
1553 XfdashboardWindowsView *self;
1554 XfdashboardWindowsViewPrivate *priv;
1555 ClutterActor *selection;
1556 ClutterActor *newSelection;
1557 gint numberChildren;
1558 gint rows;
1559 gint columns;
1560 gint currentSelectionIndex;
1561 gint currentSelectionRow;
1562 gint currentSelectionColumn;
1563 gint newSelectionIndex;
1564 ClutterActorIter iter;
1565 ClutterActor *child;
1566 gchar *valueName;
1567
1568 g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), NULL);
1569 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inFocusable), NULL);
1570 g_return_val_if_fail(!inSelection || CLUTTER_IS_ACTOR(inSelection), NULL);
1571 g_return_val_if_fail(inDirection>=0 && inDirection<=XFDASHBOARD_SELECTION_TARGET_NEXT, NULL);
1572
1573 self=XFDASHBOARD_WINDOWS_VIEW(inFocusable);
1574 priv=self->priv;
1575 selection=inSelection;
1576 newSelection=NULL;
1577
1578 /* If there is nothing selected, select first actor and return */
1579 if(!inSelection)
1580 {
1581 newSelection=clutter_actor_get_first_child(CLUTTER_ACTOR(self));
1582
1583 valueName=xfdashboard_get_enum_value_name(XFDASHBOARD_TYPE_SELECTION_TARGET, inDirection);
1584 XFDASHBOARD_DEBUG(self, ACTOR,
1585 "No selection at %s, so select first child %s for direction %s",
1586 G_OBJECT_TYPE_NAME(self),
1587 newSelection ? G_OBJECT_TYPE_NAME(newSelection) : "<nil>",
1588 valueName);
1589 g_free(valueName);
1590
1591 return(newSelection);
1592 }
1593
1594 /* Check that selection is a child of this actor otherwise return NULL */
1595 if(!clutter_actor_contains(CLUTTER_ACTOR(self), inSelection))
1596 {
1597 ClutterActor *parent;
1598
1599 parent=clutter_actor_get_parent(inSelection);
1600 g_warning("Cannot lookup selection target at %s because %s is a child of %s",
1601 G_OBJECT_TYPE_NAME(self),
1602 G_OBJECT_TYPE_NAME(inSelection),
1603 parent ? G_OBJECT_TYPE_NAME(parent) : "<nil>");
1604
1605 return(NULL);
1606 }
1607
1608 /* Get number of rows and columns and also get number of children
1609 * of layout manager.
1610 */
1611 numberChildren=xfdashboard_scaled_table_layout_get_number_children(XFDASHBOARD_SCALED_TABLE_LAYOUT(priv->layout));
1612 rows=xfdashboard_scaled_table_layout_get_rows(XFDASHBOARD_SCALED_TABLE_LAYOUT(priv->layout));
1613 columns=xfdashboard_scaled_table_layout_get_columns(XFDASHBOARD_SCALED_TABLE_LAYOUT(priv->layout));
1614
1615 /* Get index of current selection */
1616 currentSelectionIndex=0;
1617 clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self));
1618 while(clutter_actor_iter_next(&iter, &child) &&
1619 child!=inSelection)
1620 {
1621 currentSelectionIndex++;
1622 }
1623
1624 currentSelectionRow=(currentSelectionIndex / columns);
1625 currentSelectionColumn=(currentSelectionIndex % columns);
1626
1627 /* Find target selection */
1628 switch(inDirection)
1629 {
1630 case XFDASHBOARD_SELECTION_TARGET_LEFT:
1631 currentSelectionColumn--;
1632 if(currentSelectionColumn<0)
1633 {
1634 currentSelectionRow++;
1635 newSelectionIndex=(currentSelectionRow*columns)-1;
1636 }
1637 else newSelectionIndex=currentSelectionIndex-1;
1638
1639 newSelectionIndex=MIN(newSelectionIndex, numberChildren-1);
1640 newSelection=clutter_actor_get_child_at_index(CLUTTER_ACTOR(self), newSelectionIndex);
1641 break;
1642
1643 case XFDASHBOARD_SELECTION_TARGET_RIGHT:
1644 currentSelectionColumn++;
1645 if(currentSelectionColumn==columns ||
1646 currentSelectionIndex==numberChildren)
1647 {
1648 newSelectionIndex=(currentSelectionRow*columns);
1649 }
1650 else newSelectionIndex=currentSelectionIndex+1;
1651
1652 newSelectionIndex=MIN(newSelectionIndex, numberChildren-1);
1653 newSelection=clutter_actor_get_child_at_index(CLUTTER_ACTOR(self), newSelectionIndex);
1654 break;
1655
1656 case XFDASHBOARD_SELECTION_TARGET_UP:
1657 currentSelectionRow--;
1658 if(currentSelectionRow<0) currentSelectionRow=rows-1;
1659 newSelectionIndex=(currentSelectionRow*columns)+currentSelectionColumn;
1660
1661 newSelectionIndex=MIN(newSelectionIndex, numberChildren-1);
1662 newSelection=clutter_actor_get_child_at_index(CLUTTER_ACTOR(self), newSelectionIndex);
1663 break;
1664
1665 case XFDASHBOARD_SELECTION_TARGET_DOWN:
1666 currentSelectionRow++;
1667 if(currentSelectionRow>=rows) currentSelectionRow=0;
1668 newSelectionIndex=(currentSelectionRow*columns)+currentSelectionColumn;
1669
1670 newSelectionIndex=MIN(newSelectionIndex, numberChildren-1);
1671 newSelection=clutter_actor_get_child_at_index(CLUTTER_ACTOR(self), newSelectionIndex);
1672 break;
1673
1674 case XFDASHBOARD_SELECTION_TARGET_FIRST:
1675 newSelection=clutter_actor_get_first_child(CLUTTER_ACTOR(self));
1676 break;
1677
1678 case XFDASHBOARD_SELECTION_TARGET_LAST:
1679 newSelection=clutter_actor_get_last_child(CLUTTER_ACTOR(self));
1680 break;
1681
1682 case XFDASHBOARD_SELECTION_TARGET_NEXT:
1683 newSelection=clutter_actor_get_next_sibling(inSelection);
1684 if(!newSelection) newSelection=clutter_actor_get_previous_sibling(inSelection);
1685 break;
1686
1687 case XFDASHBOARD_SELECTION_TARGET_PAGE_LEFT:
1688 newSelectionIndex=(currentSelectionRow*columns);
1689 newSelectionIndex=MIN(newSelectionIndex, numberChildren-1);
1690 newSelection=clutter_actor_get_child_at_index(CLUTTER_ACTOR(self), newSelectionIndex);
1691 break;
1692
1693 case XFDASHBOARD_SELECTION_TARGET_PAGE_RIGHT:
1694 newSelectionIndex=((currentSelectionRow+1)*columns)-1;
1695 newSelectionIndex=MIN(newSelectionIndex, numberChildren-1);
1696 newSelection=clutter_actor_get_child_at_index(CLUTTER_ACTOR(self), newSelectionIndex);
1697 break;
1698
1699 case XFDASHBOARD_SELECTION_TARGET_PAGE_UP:
1700 newSelectionIndex=currentSelectionColumn;
1701 newSelectionIndex=MIN(newSelectionIndex, numberChildren-1);
1702 newSelection=clutter_actor_get_child_at_index(CLUTTER_ACTOR(self), newSelectionIndex);
1703 break;
1704
1705 case XFDASHBOARD_SELECTION_TARGET_PAGE_DOWN:
1706 newSelectionIndex=((rows-1)*columns)+currentSelectionColumn;
1707 newSelectionIndex=MIN(newSelectionIndex, numberChildren-1);
1708 newSelection=clutter_actor_get_child_at_index(CLUTTER_ACTOR(self), newSelectionIndex);
1709 break;
1710
1711 default:
1712 {
1713 valueName=xfdashboard_get_enum_value_name(XFDASHBOARD_TYPE_SELECTION_TARGET, inDirection);
1714 g_critical("Focusable object %s does not handle selection direction of type %s.",
1715 G_OBJECT_TYPE_NAME(self),
1716 valueName);
1717 g_free(valueName);
1718 }
1719 break;
1720 }
1721
1722 /* If new selection could be found override current selection with it */
1723 if(newSelection) selection=newSelection;
1724
1725 /* Return new selection found */
1726 XFDASHBOARD_DEBUG(self, ACTOR,
1727 "Selecting %s at %s for current selection %s in direction %u",
1728 selection ? G_OBJECT_TYPE_NAME(selection) : "<nil>",
1729 G_OBJECT_TYPE_NAME(self),
1730 inSelection ? G_OBJECT_TYPE_NAME(inSelection) : "<nil>",
1731 inDirection);
1732
1733 return(selection);
1734 }
1735
1736 /* Activate selection */
_xfdashboard_windows_view_focusable_activate_selection(XfdashboardFocusable * inFocusable,ClutterActor * inSelection)1737 static gboolean _xfdashboard_windows_view_focusable_activate_selection(XfdashboardFocusable *inFocusable,
1738 ClutterActor *inSelection)
1739 {
1740 XfdashboardWindowsView *self;
1741
1742 g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), FALSE);
1743 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inFocusable), FALSE);
1744 g_return_val_if_fail(CLUTTER_IS_ACTOR(inSelection), FALSE);
1745
1746 self=XFDASHBOARD_WINDOWS_VIEW(inFocusable);
1747
1748 /* Check that selection is a child of this actor */
1749 if(!clutter_actor_contains(CLUTTER_ACTOR(self), inSelection))
1750 {
1751 ClutterActor *parent;
1752
1753 parent=clutter_actor_get_parent(inSelection);
1754 g_warning("%s is a child of %s and cannot be activated at %s",
1755 G_OBJECT_TYPE_NAME(inSelection),
1756 parent ? G_OBJECT_TYPE_NAME(parent) : "<nil>",
1757 G_OBJECT_TYPE_NAME(self));
1758
1759 return(FALSE);
1760 }
1761
1762 /* Check that child is a live window */
1763 if(!XFDASHBOARD_IS_LIVE_WINDOW(inSelection))
1764 {
1765 g_warning("Cannot activate selection of type %s at %s because expecting type %s",
1766 G_OBJECT_TYPE_NAME(inSelection),
1767 G_OBJECT_TYPE_NAME(self),
1768 g_type_name(XFDASHBOARD_TYPE_LIVE_WINDOW));
1769
1770 return(FALSE);
1771 }
1772
1773 /* Activate selection means clicking on window */
1774 _xfdashboard_windows_view_on_window_clicked(self, XFDASHBOARD_LIVE_WINDOW(inSelection));
1775
1776 return(TRUE);
1777 }
1778
1779 /* Interface initialization
1780 * Set up default functions
1781 */
_xfdashboard_windows_view_focusable_iface_init(XfdashboardFocusableInterface * iface)1782 void _xfdashboard_windows_view_focusable_iface_init(XfdashboardFocusableInterface *iface)
1783 {
1784 iface->can_focus=_xfdashboard_windows_view_focusable_can_focus;
1785 iface->unset_focus=_xfdashboard_windows_view_focusable_unset_focus;
1786
1787 iface->supports_selection=_xfdashboard_windows_view_focusable_supports_selection;
1788 iface->get_selection=_xfdashboard_windows_view_focusable_get_selection;
1789 iface->set_selection=_xfdashboard_windows_view_focusable_set_selection;
1790 iface->find_selection=_xfdashboard_windows_view_focusable_find_selection;
1791 iface->activate_selection=_xfdashboard_windows_view_focusable_activate_selection;
1792 }
1793
1794 /* IMPLEMENTATION: ClutterActor */
1795
1796 /* Actor will be mapped */
_xfdashboard_windows_view_map(ClutterActor * inActor)1797 static void _xfdashboard_windows_view_map(ClutterActor *inActor)
1798 {
1799 XfdashboardWindowsView *self;
1800 XfdashboardWindowsViewPrivate *priv;
1801 ClutterActorClass *clutterActorClass;
1802
1803 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inActor));
1804
1805 self=XFDASHBOARD_WINDOWS_VIEW(inActor);
1806 priv=self->priv;
1807
1808 /* Call parent's virtual function */
1809 clutterActorClass=CLUTTER_ACTOR_CLASS(xfdashboard_windows_view_parent_class);
1810 if(clutterActorClass->map) clutterActorClass->map(inActor);
1811
1812 /* Disconnect signal handler if available */
1813 if(priv->scrollEventChangingWorkspaceStage)
1814 {
1815 if(priv->scrollEventChangingWorkspaceStageSignalID)
1816 {
1817 g_signal_handler_disconnect(priv->scrollEventChangingWorkspaceStage, priv->scrollEventChangingWorkspaceStageSignalID);
1818 priv->scrollEventChangingWorkspaceStageSignalID=0;
1819 }
1820
1821 priv->scrollEventChangingWorkspaceStage=NULL;
1822 }
1823
1824 /* Get stage interface where this actor belongs to and connect
1825 * signal handler if found.
1826 */
1827 priv->scrollEventChangingWorkspaceStage=xfdashboard_get_stage_of_actor(CLUTTER_ACTOR(self));
1828 if(priv->scrollEventChangingWorkspaceStage)
1829 {
1830 priv->scrollEventChangingWorkspaceStageSignalID=g_signal_connect_swapped(priv->scrollEventChangingWorkspaceStage,
1831 "scroll-event",
1832 G_CALLBACK(_xfdashboard_windows_view_on_scroll_event),
1833 self);
1834 }
1835 }
1836
1837 /* Actor will be unmapped */
_xfdashboard_windows_view_unmap(ClutterActor * inActor)1838 static void _xfdashboard_windows_view_unmap(ClutterActor *inActor)
1839 {
1840 XfdashboardWindowsView *self;
1841 XfdashboardWindowsViewPrivate *priv;
1842 ClutterActorClass *clutterActorClass;
1843
1844 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inActor));
1845
1846 self=XFDASHBOARD_WINDOWS_VIEW(inActor);
1847 priv=self->priv;
1848
1849 /* Call parent's virtual function */
1850 clutterActorClass=CLUTTER_ACTOR_CLASS(xfdashboard_windows_view_parent_class);
1851 if(clutterActorClass->unmap) clutterActorClass->unmap(inActor);
1852
1853 /* Disconnect signal handler if available */
1854 if(priv->scrollEventChangingWorkspaceStage)
1855 {
1856 if(priv->scrollEventChangingWorkspaceStageSignalID)
1857 {
1858 g_signal_handler_disconnect(priv->scrollEventChangingWorkspaceStage, priv->scrollEventChangingWorkspaceStageSignalID);
1859 priv->scrollEventChangingWorkspaceStageSignalID=0;
1860 }
1861
1862 priv->scrollEventChangingWorkspaceStage=NULL;
1863 }
1864 }
1865
1866 /* IMPLEMENTATION: GObject */
1867
1868 /* Dispose this object */
_xfdashboard_windows_view_dispose(GObject * inObject)1869 static void _xfdashboard_windows_view_dispose(GObject *inObject)
1870 {
1871 XfdashboardWindowsView *self=XFDASHBOARD_WINDOWS_VIEW(inObject);
1872 XfdashboardWindowsViewPrivate *priv=XFDASHBOARD_WINDOWS_VIEW(self)->priv;
1873
1874 /* Release allocated resources */
1875 if(priv->selectedItem)
1876 {
1877 g_object_remove_weak_pointer(G_OBJECT(priv->selectedItem), &priv->selectedItem);
1878 priv->selectedItem=NULL;
1879 }
1880
1881 if(priv->scrollEventChangingWorkspaceStage)
1882 {
1883 if(priv->scrollEventChangingWorkspaceStageSignalID)
1884 {
1885 g_signal_handler_disconnect(priv->scrollEventChangingWorkspaceStage, priv->scrollEventChangingWorkspaceStageSignalID);
1886 priv->scrollEventChangingWorkspaceStageSignalID=0;
1887 }
1888
1889 priv->scrollEventChangingWorkspaceStage=NULL;
1890 }
1891
1892 if(priv->xfconfChannel)
1893 {
1894 priv->xfconfChannel=NULL;
1895 }
1896
1897 if(priv->xfconfScrollEventChangingWorkspaceBindingID)
1898 {
1899 xfconf_g_property_unbind(priv->xfconfScrollEventChangingWorkspaceBindingID);
1900 priv->xfconfScrollEventChangingWorkspaceBindingID=0;
1901 }
1902
1903 if(priv->workspace)
1904 {
1905 _xfdashboard_windows_view_set_active_workspace(self, NULL);
1906 }
1907
1908 if(priv->layout)
1909 {
1910 priv->layout=NULL;
1911 }
1912
1913 if(priv->currentMonitor)
1914 {
1915 priv->currentMonitor=NULL;
1916 }
1917
1918 if(priv->currentStage)
1919 {
1920 if(priv->currentStageMonitorBindingID)
1921 {
1922 g_signal_handler_disconnect(priv->currentStage, priv->currentStageMonitorBindingID);
1923 priv->currentStageMonitorBindingID=0;
1924 }
1925
1926 priv->currentStage=NULL;
1927 }
1928
1929 if(priv->windowTracker)
1930 {
1931 g_signal_handlers_disconnect_by_data(priv->windowTracker, self);
1932 g_object_unref(priv->windowTracker);
1933 priv->windowTracker=NULL;
1934 }
1935
1936 /* Call parent's class dispose method */
1937 G_OBJECT_CLASS(xfdashboard_windows_view_parent_class)->dispose(inObject);
1938 }
1939
1940 /* Set/get properties */
_xfdashboard_windows_view_set_property(GObject * inObject,guint inPropID,const GValue * inValue,GParamSpec * inSpec)1941 static void _xfdashboard_windows_view_set_property(GObject *inObject,
1942 guint inPropID,
1943 const GValue *inValue,
1944 GParamSpec *inSpec)
1945 {
1946 XfdashboardWindowsView *self=XFDASHBOARD_WINDOWS_VIEW(inObject);
1947
1948 switch(inPropID)
1949 {
1950 case PROP_WORKSPACE:
1951 _xfdashboard_windows_view_set_active_workspace(self, g_value_get_object(inValue));
1952 break;
1953
1954 case PROP_SPACING:
1955 xfdashboard_windows_view_set_spacing(self, g_value_get_float(inValue));
1956 break;
1957
1958 case PROP_PREVENT_UPSCALING:
1959 xfdashboard_windows_view_set_prevent_upscaling(self, g_value_get_boolean(inValue));
1960 break;
1961
1962 case PROP_SCROLL_EVENT_CHANGES_WORKSPACE:
1963 _xfdashboard_windows_view_set_scroll_event_changes_workspace(self, g_value_get_boolean(inValue));
1964 break;
1965
1966 case PROP_FILTER_MONITOR_WINDOWS:
1967 _xfdashboard_windows_view_set_filter_monitor_windows(self, g_value_get_boolean(inValue));
1968 break;
1969
1970 case PROP_FILTER_WORKSPACE_WINDOWS:
1971 _xfdashboard_windows_view_set_filter_workspace_windows(self, g_value_get_boolean(inValue));
1972 break;
1973
1974 default:
1975 G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec);
1976 break;
1977 }
1978 }
1979
_xfdashboard_windows_view_get_property(GObject * inObject,guint inPropID,GValue * outValue,GParamSpec * inSpec)1980 static void _xfdashboard_windows_view_get_property(GObject *inObject,
1981 guint inPropID,
1982 GValue *outValue,
1983 GParamSpec *inSpec)
1984 {
1985 XfdashboardWindowsView *self=XFDASHBOARD_WINDOWS_VIEW(inObject);
1986 XfdashboardWindowsViewPrivate *priv=self->priv;
1987
1988 switch(inPropID)
1989 {
1990 case PROP_WORKSPACE:
1991 g_value_set_object(outValue, priv->workspace);
1992 break;
1993
1994 case PROP_SPACING:
1995 g_value_set_float(outValue, priv->spacing);
1996 break;
1997
1998 case PROP_PREVENT_UPSCALING:
1999 g_value_set_boolean(outValue, self->priv->preventUpscaling);
2000 break;
2001
2002 case PROP_SCROLL_EVENT_CHANGES_WORKSPACE:
2003 g_value_set_boolean(outValue, self->priv->isScrollEventChangingWorkspace);
2004 break;
2005
2006 case PROP_FILTER_MONITOR_WINDOWS:
2007 g_value_set_boolean(outValue, self->priv->filterMonitorWindows);
2008 break;
2009
2010 case PROP_FILTER_WORKSPACE_WINDOWS:
2011 g_value_set_boolean(outValue, self->priv->filterWorkspaceWindows);
2012 break;
2013
2014 default:
2015 G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec);
2016 break;
2017 }
2018 }
2019
2020 /* Class initialization
2021 * Override functions in parent classes and define properties
2022 * and signals
2023 */
xfdashboard_windows_view_class_init(XfdashboardWindowsViewClass * klass)2024 static void xfdashboard_windows_view_class_init(XfdashboardWindowsViewClass *klass)
2025 {
2026 XfdashboardActorClass *actorClass=XFDASHBOARD_ACTOR_CLASS(klass);
2027 ClutterActorClass *clutterActorClass=CLUTTER_ACTOR_CLASS(klass);
2028 GObjectClass *gobjectClass=G_OBJECT_CLASS(klass);
2029
2030 /* Override functions */
2031 gobjectClass->dispose=_xfdashboard_windows_view_dispose;
2032 gobjectClass->set_property=_xfdashboard_windows_view_set_property;
2033 gobjectClass->get_property=_xfdashboard_windows_view_get_property;
2034
2035 clutterActorClass->map=_xfdashboard_windows_view_map;
2036 clutterActorClass->unmap=_xfdashboard_windows_view_unmap;
2037
2038 klass->window_close=_xfdashboard_windows_view_window_close;
2039 klass->windows_show_numbers=_xfdashboard_windows_view_windows_show_numbers;
2040 klass->windows_hide_numbers=_xfdashboard_windows_view_windows_hide_numbers;
2041 klass->windows_activate_window_one=_xfdashboard_windows_view_windows_activate_window_one;
2042 klass->windows_activate_window_two=_xfdashboard_windows_view_windows_activate_window_two;
2043 klass->windows_activate_window_three=_xfdashboard_windows_view_windows_activate_window_three;
2044 klass->windows_activate_window_four=_xfdashboard_windows_view_windows_activate_window_four;
2045 klass->windows_activate_window_five=_xfdashboard_windows_view_windows_activate_window_five;
2046 klass->windows_activate_window_six=_xfdashboard_windows_view_windows_activate_window_six;
2047 klass->windows_activate_window_seven=_xfdashboard_windows_view_windows_activate_window_seven;
2048 klass->windows_activate_window_eight=_xfdashboard_windows_view_windows_activate_window_eight;
2049 klass->windows_activate_window_nine=_xfdashboard_windows_view_windows_activate_window_nine;
2050 klass->windows_activate_window_ten=_xfdashboard_windows_view_windows_activate_window_ten;
2051
2052 /* Define properties */
2053 XfdashboardWindowsViewProperties[PROP_WORKSPACE]=
2054 g_param_spec_object("workspace",
2055 "Current workspace",
2056 "The current workspace whose windows are shown",
2057 XFDASHBOARD_TYPE_WINDOW_TRACKER_WORKSPACE,
2058 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
2059
2060 XfdashboardWindowsViewProperties[PROP_SPACING]=
2061 g_param_spec_float("spacing",
2062 "Spacing",
2063 "Spacing between each element in view",
2064 0.0f, G_MAXFLOAT,
2065 0.0f,
2066 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
2067
2068 XfdashboardWindowsViewProperties[PROP_PREVENT_UPSCALING]=
2069 g_param_spec_boolean("prevent-upscaling",
2070 "Prevent upscaling",
2071 "Whether this view should prevent upsclaing any window beyond its real size",
2072 FALSE,
2073 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
2074
2075 XfdashboardWindowsViewProperties[PROP_SCROLL_EVENT_CHANGES_WORKSPACE]=
2076 g_param_spec_boolean("scroll-event-changes-workspace",
2077 "Scroll event changes workspace",
2078 "Whether this view should change active workspace on scroll events",
2079 FALSE,
2080 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
2081
2082 XfdashboardWindowsViewProperties[PROP_FILTER_MONITOR_WINDOWS]=
2083 g_param_spec_boolean("filter-monitor-windows",
2084 "Filter monitor windows",
2085 "Whether this view should only show windows of monitor where it placed at",
2086 FALSE,
2087 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
2088
2089 XfdashboardWindowsViewProperties[PROP_FILTER_WORKSPACE_WINDOWS]=
2090 g_param_spec_boolean("filter-workspace-windows",
2091 "Filter workspace windows",
2092 "Whether this view should only show windows of active workspace",
2093 TRUE,
2094 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
2095
2096 g_object_class_install_properties(gobjectClass, PROP_LAST, XfdashboardWindowsViewProperties);
2097
2098 /* Define stylable properties */
2099 xfdashboard_actor_install_stylable_property(actorClass, XfdashboardWindowsViewProperties[PROP_SPACING]);
2100 xfdashboard_actor_install_stylable_property(actorClass, XfdashboardWindowsViewProperties[PROP_PREVENT_UPSCALING]);
2101 xfdashboard_actor_install_stylable_property(actorClass, XfdashboardWindowsViewProperties[PROP_FILTER_MONITOR_WINDOWS]);
2102 xfdashboard_actor_install_stylable_property(actorClass, XfdashboardWindowsViewProperties[PROP_FILTER_WORKSPACE_WINDOWS]);
2103
2104 /* Define actions */
2105 XfdashboardWindowsViewSignals[ACTION_WINDOW_CLOSE]=
2106 g_signal_new("window-close",
2107 G_TYPE_FROM_CLASS(klass),
2108 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2109 G_STRUCT_OFFSET(XfdashboardWindowsViewClass, window_close),
2110 g_signal_accumulator_true_handled,
2111 NULL,
2112 _xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2113 G_TYPE_BOOLEAN,
2114 3,
2115 XFDASHBOARD_TYPE_FOCUSABLE,
2116 G_TYPE_STRING,
2117 CLUTTER_TYPE_EVENT);
2118
2119 XfdashboardWindowsViewSignals[ACTION_WINDOWS_SHOW_NUMBERS]=
2120 g_signal_new("windows-show-numbers",
2121 G_TYPE_FROM_CLASS(klass),
2122 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2123 G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_show_numbers),
2124 g_signal_accumulator_true_handled,
2125 NULL,
2126 _xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2127 G_TYPE_BOOLEAN,
2128 3,
2129 XFDASHBOARD_TYPE_FOCUSABLE,
2130 G_TYPE_STRING,
2131 CLUTTER_TYPE_EVENT);
2132
2133 XfdashboardWindowsViewSignals[ACTION_WINDOWS_HIDE_NUMBERS]=
2134 g_signal_new("windows-hide-numbers",
2135 G_TYPE_FROM_CLASS(klass),
2136 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2137 G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_hide_numbers),
2138 g_signal_accumulator_true_handled,
2139 NULL,
2140 _xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2141 G_TYPE_BOOLEAN,
2142 3,
2143 XFDASHBOARD_TYPE_FOCUSABLE,
2144 G_TYPE_STRING,
2145 CLUTTER_TYPE_EVENT);
2146
2147 XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_ONE]=
2148 g_signal_new("windows-activate-window-one",
2149 G_TYPE_FROM_CLASS(klass),
2150 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2151 G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_one),
2152 g_signal_accumulator_true_handled,
2153 NULL,
2154 _xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2155 G_TYPE_BOOLEAN,
2156 3,
2157 XFDASHBOARD_TYPE_FOCUSABLE,
2158 G_TYPE_STRING,
2159 CLUTTER_TYPE_EVENT);
2160
2161 XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_TWO]=
2162 g_signal_new("windows-activate-window-two",
2163 G_TYPE_FROM_CLASS(klass),
2164 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2165 G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_two),
2166 g_signal_accumulator_true_handled,
2167 NULL,
2168 _xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2169 G_TYPE_BOOLEAN,
2170 3,
2171 XFDASHBOARD_TYPE_FOCUSABLE,
2172 G_TYPE_STRING,
2173 CLUTTER_TYPE_EVENT);
2174
2175 XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_THREE]=
2176 g_signal_new("windows-activate-window-three",
2177 G_TYPE_FROM_CLASS(klass),
2178 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2179 G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_three),
2180 g_signal_accumulator_true_handled,
2181 NULL,
2182 _xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2183 G_TYPE_BOOLEAN,
2184 3,
2185 XFDASHBOARD_TYPE_FOCUSABLE,
2186 G_TYPE_STRING,
2187 CLUTTER_TYPE_EVENT);
2188
2189 XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_FOUR]=
2190 g_signal_new("windows-activate-window-four",
2191 G_TYPE_FROM_CLASS(klass),
2192 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2193 G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_four),
2194 g_signal_accumulator_true_handled,
2195 NULL,
2196 _xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2197 G_TYPE_BOOLEAN,
2198 3,
2199 XFDASHBOARD_TYPE_FOCUSABLE,
2200 G_TYPE_STRING,
2201 CLUTTER_TYPE_EVENT);
2202
2203 XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_FIVE]=
2204 g_signal_new("windows-activate-window-five",
2205 G_TYPE_FROM_CLASS(klass),
2206 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2207 G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_five),
2208 g_signal_accumulator_true_handled,
2209 NULL,
2210 _xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2211 G_TYPE_BOOLEAN,
2212 3,
2213 XFDASHBOARD_TYPE_FOCUSABLE,
2214 G_TYPE_STRING,
2215 CLUTTER_TYPE_EVENT);
2216
2217 XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_SIX]=
2218 g_signal_new("windows-activate-window-six",
2219 G_TYPE_FROM_CLASS(klass),
2220 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2221 G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_six),
2222 g_signal_accumulator_true_handled,
2223 NULL,
2224 _xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2225 G_TYPE_BOOLEAN,
2226 3,
2227 XFDASHBOARD_TYPE_FOCUSABLE,
2228 G_TYPE_STRING,
2229 CLUTTER_TYPE_EVENT);
2230
2231 XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_SEVEN]=
2232 g_signal_new("windows-activate-window-seven",
2233 G_TYPE_FROM_CLASS(klass),
2234 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2235 G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_seven),
2236 g_signal_accumulator_true_handled,
2237 NULL,
2238 _xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2239 G_TYPE_BOOLEAN,
2240 3,
2241 XFDASHBOARD_TYPE_FOCUSABLE,
2242 G_TYPE_STRING,
2243 CLUTTER_TYPE_EVENT);
2244
2245 XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_EIGHT]=
2246 g_signal_new("windows-activate-window-eight",
2247 G_TYPE_FROM_CLASS(klass),
2248 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2249 G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_eight),
2250 g_signal_accumulator_true_handled,
2251 NULL,
2252 _xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2253 G_TYPE_BOOLEAN,
2254 3,
2255 XFDASHBOARD_TYPE_FOCUSABLE,
2256 G_TYPE_STRING,
2257 CLUTTER_TYPE_EVENT);
2258
2259 XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_NINE]=
2260 g_signal_new("windows-activate-window-nine",
2261 G_TYPE_FROM_CLASS(klass),
2262 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2263 G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_nine),
2264 g_signal_accumulator_true_handled,
2265 NULL,
2266 _xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2267 G_TYPE_BOOLEAN,
2268 3,
2269 XFDASHBOARD_TYPE_FOCUSABLE,
2270 G_TYPE_STRING,
2271 CLUTTER_TYPE_EVENT);
2272
2273 XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_TEN]=
2274 g_signal_new("windows-activate-window-ten",
2275 G_TYPE_FROM_CLASS(klass),
2276 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2277 G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_ten),
2278 g_signal_accumulator_true_handled,
2279 NULL,
2280 _xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2281 G_TYPE_BOOLEAN,
2282 3,
2283 XFDASHBOARD_TYPE_FOCUSABLE,
2284 G_TYPE_STRING,
2285 CLUTTER_TYPE_EVENT);
2286 }
2287
2288 /* Object initialization
2289 * Create private structure and set up default values
2290 */
xfdashboard_windows_view_init(XfdashboardWindowsView * self)2291 static void xfdashboard_windows_view_init(XfdashboardWindowsView *self)
2292 {
2293 XfdashboardWindowsViewPrivate *priv;
2294 ClutterAction *action;
2295 XfdashboardWindowTrackerWorkspace *activeWorkspace;
2296
2297 self->priv=priv=xfdashboard_windows_view_get_instance_private(self);
2298
2299 /* Set up default values */
2300 priv->windowTracker=xfdashboard_window_tracker_get_default();
2301 priv->workspace=NULL;
2302 priv->spacing=0.0f;
2303 priv->preventUpscaling=FALSE;
2304 priv->selectedItem=NULL;
2305 priv->isWindowsNumberShown=FALSE;
2306 priv->xfconfChannel=xfdashboard_application_get_xfconf_channel(NULL);
2307 priv->isScrollEventChangingWorkspace=FALSE;
2308 priv->scrollEventChangingWorkspaceStage=NULL;
2309 priv->scrollEventChangingWorkspaceStageSignalID=0;
2310 priv->filterMonitorWindows=FALSE;
2311 priv->filterWorkspaceWindows=TRUE;
2312 priv->currentStage=NULL;
2313 priv->currentMonitor=NULL;
2314 priv->currentStageMonitorBindingID=0;
2315
2316 /* Set up view */
2317 xfdashboard_view_set_name(XFDASHBOARD_VIEW(self), _("Windows"));
2318 xfdashboard_view_set_icon(XFDASHBOARD_VIEW(self), DEFAULT_VIEW_ICON);
2319 xfdashboard_view_set_view_fit_mode(XFDASHBOARD_VIEW(self), XFDASHBOARD_VIEW_FIT_MODE_BOTH);
2320
2321 /* Setup actor */
2322 xfdashboard_actor_set_can_focus(XFDASHBOARD_ACTOR(self), TRUE);
2323
2324 priv->layout=xfdashboard_scaled_table_layout_new();
2325 xfdashboard_scaled_table_layout_set_relative_scale(XFDASHBOARD_SCALED_TABLE_LAYOUT(priv->layout), TRUE);
2326 xfdashboard_scaled_table_layout_set_prevent_upscaling(XFDASHBOARD_SCALED_TABLE_LAYOUT(priv->layout), priv->preventUpscaling);
2327 clutter_actor_set_layout_manager(CLUTTER_ACTOR(self), priv->layout);
2328
2329 action=xfdashboard_drop_action_new();
2330 clutter_actor_add_action(CLUTTER_ACTOR(self), action);
2331 g_signal_connect_swapped(action, "begin", G_CALLBACK(_xfdashboard_windows_view_on_drop_begin), self);
2332 g_signal_connect_swapped(action, "drop", G_CALLBACK(_xfdashboard_windows_view_on_drop_drop), self);
2333
2334 /* Bind to xfconf to react on changes */
2335 priv->xfconfScrollEventChangingWorkspaceBindingID=xfconf_g_property_bind(priv->xfconfChannel,
2336 SCROLL_EVENT_CHANGES_WORKSPACE_XFCONF_PROP,
2337 G_TYPE_BOOLEAN,
2338 self,
2339 "scroll-event-changes-workspace");
2340
2341 /* Connect signals */
2342 g_signal_connect(self,
2343 "actor-added",
2344 G_CALLBACK(_xfdashboard_windows_view_on_child_added),
2345 NULL);
2346
2347 g_signal_connect(self,
2348 "actor-removed",
2349 G_CALLBACK(_xfdashboard_windows_view_on_child_removed),
2350 NULL);
2351
2352 g_signal_connect_swapped(priv->windowTracker,
2353 "active-workspace-changed",
2354 G_CALLBACK(_xfdashboard_windows_view_on_active_workspace_changed),
2355 self);
2356
2357 g_signal_connect_swapped(priv->windowTracker,
2358 "window-workspace-changed",
2359 G_CALLBACK(_xfdashboard_windows_view_on_window_workspace_changed),
2360 self);
2361
2362 g_signal_connect_swapped(priv->windowTracker,
2363 "window-opened",
2364 G_CALLBACK(_xfdashboard_windows_view_on_window_opened),
2365 self);
2366
2367 g_signal_connect_swapped(priv->windowTracker,
2368 "window-monitor-changed",
2369 G_CALLBACK(_xfdashboard_windows_view_on_window_monitor_changed),
2370 self);
2371
2372 /* If active workspace is already available then set up this view */
2373 activeWorkspace=xfdashboard_window_tracker_get_active_workspace(priv->windowTracker);
2374 if(activeWorkspace)
2375 {
2376 _xfdashboard_windows_view_set_active_workspace(self, activeWorkspace);
2377 }
2378 }
2379
2380 /* IMPLEMENTATION: Public API */
2381
2382 /* Get/set spacing between elements */
xfdashboard_windows_view_get_spacing(XfdashboardWindowsView * self)2383 gfloat xfdashboard_windows_view_get_spacing(XfdashboardWindowsView *self)
2384 {
2385 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), 0.0f);
2386
2387 return(self->priv->spacing);
2388 }
2389
xfdashboard_windows_view_set_spacing(XfdashboardWindowsView * self,const gfloat inSpacing)2390 void xfdashboard_windows_view_set_spacing(XfdashboardWindowsView *self, const gfloat inSpacing)
2391 {
2392 XfdashboardWindowsViewPrivate *priv;
2393
2394 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
2395 g_return_if_fail(inSpacing>=0.0f);
2396
2397 priv=self->priv;
2398
2399 /* Set value if changed */
2400 if(priv->spacing!=inSpacing)
2401 {
2402 /* Set value */
2403 priv->spacing=inSpacing;
2404
2405 /* Update layout manager */
2406 if(priv->layout)
2407 {
2408 xfdashboard_scaled_table_layout_set_spacing(XFDASHBOARD_SCALED_TABLE_LAYOUT(priv->layout), priv->spacing);
2409 }
2410
2411 /* Notify about property change */
2412 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardWindowsViewProperties[PROP_SPACING]);
2413 }
2414 }
2415
2416 /* Get/set if layout manager should prevent to size any child larger than its real size */
xfdashboard_windows_view_get_prevent_upscaling(XfdashboardWindowsView * self)2417 gboolean xfdashboard_windows_view_get_prevent_upscaling(XfdashboardWindowsView *self)
2418 {
2419 g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), FALSE);
2420
2421 return(self->priv->preventUpscaling);
2422 }
2423
xfdashboard_windows_view_set_prevent_upscaling(XfdashboardWindowsView * self,gboolean inPreventUpscaling)2424 void xfdashboard_windows_view_set_prevent_upscaling(XfdashboardWindowsView *self, gboolean inPreventUpscaling)
2425 {
2426 XfdashboardWindowsViewPrivate *priv;
2427
2428 g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
2429
2430 priv=self->priv;
2431
2432 /* Set value if changed */
2433 if(priv->preventUpscaling!=inPreventUpscaling)
2434 {
2435 /* Set value */
2436 priv->preventUpscaling=inPreventUpscaling;
2437
2438 /* Update layout manager */
2439 if(priv->layout)
2440 {
2441 xfdashboard_scaled_table_layout_set_prevent_upscaling(XFDASHBOARD_SCALED_TABLE_LAYOUT(priv->layout), priv->preventUpscaling);
2442 }
2443
2444 /* Notify about property change */
2445 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardWindowsViewProperties[PROP_PREVENT_UPSCALING]);
2446 }
2447 }
2448