~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to services/plugins/unity/unitylib/unityPlatformX11.cc

  • Committer: Package Import Robot
  • Author(s): Nate Muench
  • Date: 2012-01-23 16:09:45 UTC
  • mfrom: (1.4.6) (2.4.26 sid)
  • Revision ID: package-import@ubuntu.com-20120123160945-b6s0r1vkcovucpf3
Tags: 2011.12.20-562307-0ubuntu1
* Merge latest upstream git tag. Fixes building on Precise
  (LP: #898289, LP: #905612)

* Items merged from Debian unstable:
  - debian/control:
    + open-vm-tools recommends open-vm-dkms. (LP: #598933)
    + open-vm-tools now suggests open-vm-toolbox. (LP: #604998)
  (From 2011.08.21-471295-1 release)
  - Updating maintainer and uploaders fields.
  - Removing vcs fields.
  - Removing references to Daniel's old email address.
  - Updating years in copyright file.
  - Updating to standards version 3.9.2.
  - Updating to debhelper version 8.
  - Switching to source format 3.0 (quilt).
  - Removing manual chrpath setting.
  - Removing exclusion from plugins from debhelper shlibs.
  - Rediffing kvers.patch.
  (From 2011.09.23-491607-1 release)
  - Marking binary architecture-dependend packages as linux and kfreebsd
  only.
  - Removing liburiparser-dev from build-depends as upstream dropped
  unity support.
  - Building with libproc-dev on amd64 again.
  - Dropping disabling of dnet support.
  (From 2011.09.23-491607-2 release)
  - Adding doxygen to build-depends for api documentation.
  - Adding libcunit1-dev to build-depends for test suites.
  - Minimizing rules file.
  - Adding open-vm-tools-dev package, containing only the api
    documentation for now.
  (From 2011.09.23-491607-3 release)
  - Sorting overrides in rules alphabetically.
  - Compacting copyright file.
  - Adding udev rule to set timeout for vmware scsi devices
  (From 2011.12.20-562307-1 release)
  - Adding patch to correct typo in upstreams dkms configuration

* Remaining Changes:
  - Remove Stable part of version numbering.
  - debian folder:
    + Re-added open-vm-dkms.postinst & open-vm-dkms.prerm.
      * Allows dkms modules to compile upon installation.
  - debian/control:
    + Re-add open-vm-source and make into a transitional package
      for open-vm-toolbox.
    + Return dependancies that were moved to open-vm-tools back to
      open-vm-toolbox.
  - debian/rules and debian/open-vm-toolbox.lintian-overrides:
    + Make vmware-user-suid-wrapper suid-root
  - debian/rules:
    + Added CFLAGS field with -Wno-deprecated-declarations
      * Will suppress issues with glib 2.31 or later.
    + Add line to copy vmware-xdg-detect-de into place.
    + Install vmware-user.desktop through toolbox package.
  - debian/open-vm-tools.init:
    + Re-add 'modprobe [-r] vmblock'.
    + Add 'modprobe [-r] vmxnet'.
      * Incase it's not loaded during boot.
    + Remove and re-add pcnet32 module
      * Will be done before (remove) and after (readd) vmxnet module
        is added.
      * If vmxnet doesn't exist (aka modules fail to build), pcnet32 can be
        still used for network connectivity.
      * Workaround until a better fix can be done.
  - Re-add gnome-session to debian/local/xautostart.conf
  - Manpages removed (from debian/manpages):
    + vmmemctl.9
    + vmxnet3.9
    + Remove references to manpages that have been removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*********************************************************
2
 
 * Copyright (C) 2007-2008 VMware, Inc. All rights reserved.
3
 
 *
4
 
 * This program is free software; you can redistribute it and/or modify it
5
 
 * under the terms of the GNU Lesser General Public License as published
6
 
 * by the Free Software Foundation version 2.1 and no later version.
7
 
 *
8
 
 * This program is distributed in the hope that it will be useful, but
9
 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
 
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
11
 
 * License for more details.
12
 
 *
13
 
 * You should have received a copy of the GNU Lesser General Public License
14
 
 * along with this program; if not, write to the Free Software Foundation, Inc.,
15
 
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
16
 
 *
17
 
 *********************************************************/
18
 
 
19
 
/**
20
 
 * @file unityPlatformX11.c
21
 
 *
22
 
 * Implementation of Unity for guest operating systems that use the X11 windowing
23
 
 * system. This file holds the basic things such as initialization/destruction of the
24
 
 * UnityPlatform object, overall event handling, and handling of some Unity
25
 
 * RPCs that are not window-centric.
26
 
 */
27
 
 
28
 
#include "unityX11.h"
29
 
 
30
 
extern "C" {
31
 
#include "appUtil.h"
32
 
#include "region.h"
33
 
#include <sys/time.h>
34
 
 
35
 
#include <X11/extensions/Xinerama.h>
36
 
#include <X11/extensions/XTest.h>
37
 
 
38
 
#ifndef NO_XCOMPOSITE
39
 
#   include <X11/extensions/Xcomposite.h>
40
 
#endif
41
 
}
42
 
 
43
 
typedef struct {
44
 
   Window realWindowID;
45
 
   XEvent xevent;
46
 
} UnityTemporaryEvent;
47
 
 
48
 
static UnitySpecialWindow *USWindowCreate(UnityPlatform *up,
49
 
                                           UnitySpecialEventHandler evHandler,
50
 
                                           Window *windows,
51
 
                                           int windowCount);
52
 
static void USWindowUpdate(UnityPlatform *up,
53
 
                           UnitySpecialWindow *usw,
54
 
                           Window *windows,
55
 
                           int windowCount);
56
 
static UnitySpecialWindow *USWindowLookup(UnityPlatform *up, Window window);
57
 
static void USWindowDestroy(UnityPlatform *up, UnitySpecialWindow *usw);
58
 
 
59
 
static void UnityPlatformProcessXEvent(UnityPlatform *up,
60
 
                                       const XEvent *xevent,
61
 
                                       Window realEventWindow);
62
 
static Window UnityPlatformGetRealEventWindow(UnityPlatform *up, const XEvent *xevent);
63
 
static void USRootWindowsProcessEvent(UnityPlatform *up,
64
 
                                       UnitySpecialWindow *usw,
65
 
                                       const XEvent *xevent,
66
 
                                       Window window);
67
 
static int UnityPlatformXErrorHandler(Display *dpy, XErrorEvent *xev);
68
 
static UnitySpecialWindow *UnityPlatformMakeRootWindowsObject(UnityPlatform *up);
69
 
 
70
 
static void UnityPlatformSendClientMessageFull(Display *d,
71
 
                                               Window destWindow,
72
 
                                               Window w,
73
 
                                               Atom messageType,
74
 
                                               int format,
75
 
                                               uint numItems,
76
 
                                               const void *data);
77
 
static void UnityPlatformStackDnDDetWnd(UnityPlatform *up);
78
 
static void UnityPlatformDnDSendClientMessage(UnityPlatform *up,
79
 
                                              Window destWindow,
80
 
                                              Window w,
81
 
                                              Atom messageType,
82
 
                                              int format,
83
 
                                              int numItems,
84
 
                                              const void *data);
85
 
 
86
 
static Bool GetRelevantWMWindow(UnityPlatform *up,
87
 
                                UnityWindowId windowId,
88
 
                                Window *wmWindow);
89
 
static Bool SetWindowStickiness(UnityPlatform *up,
90
 
                                UnityWindowId windowId,
91
 
                                Bool wantSticky);
92
 
static UnitySpecialWindow *MakeCompositeOverlaysObject(UnityPlatform *up);
93
 
 
94
 
/*
95
 
 * Has to be global for UnityPlatformXErrorHandler
96
 
 */
97
 
static int unityX11ErrorCount = 0;
98
 
 
99
 
/*
100
 
 *----------------------------------------------------------------------------
101
 
 *
102
 
 * UnityPlatformIsSupported --
103
 
 *
104
 
 *      Determine whether this guest supports unity.
105
 
 *
106
 
 * Results:
107
 
 *      TRUE if the guest supports Unity
108
 
 *      FALSE otherwise
109
 
 *
110
 
 * Side effects:
111
 
 *      None
112
 
 *
113
 
 *----------------------------------------------------------------------------
114
 
 */
115
 
 
116
 
Bool
117
 
UnityPlatformIsSupported(void)
118
 
{
119
 
   Display *dpy;
120
 
   int major;
121
 
   int event_base;
122
 
   int error_base;
123
 
 
124
 
   dpy = GDK_DISPLAY();
125
 
   /*
126
 
    * Unity/X11 doesn't yet work with the new vmwgfx driver.  Until that is
127
 
    * fixed, we have to disable the feature.
128
 
    *
129
 
    * As for detecting which driver is in use, the legacy driver provides the
130
 
    * VMWARE_CTRL extension for resolution and topology operations, while the
131
 
    * new driver is instead controlled via XRandR.  If we don't find said
132
 
    * extension, then we'll assume the new driver is in use and disable Unity.
133
 
    */
134
 
   if (XQueryExtension(dpy, "VMWARE_CTRL", &major, &event_base, &error_base) ==
135
 
       False) {
136
 
      Debug("Unity is not yet supported under the vmwgfx driver.\n");
137
 
      return FALSE;
138
 
   }
139
 
 
140
 
   return TRUE;
141
 
}
142
 
 
143
 
 
144
 
/*
145
 
 *----------------------------------------------------------------------------
146
 
 *
147
 
 * UnityPlatformInit --
148
 
 *
149
 
 *      Initialize the UnityPlatform object that represents the platform-specific state.
150
 
 *
151
 
 * Results:
152
 
 *      Pointer to newly allocated UnityPlatform data.
153
 
 *
154
 
 * Side effects:
155
 
 *      No.
156
 
 *
157
 
 *----------------------------------------------------------------------------
158
 
 */
159
 
 
160
 
UnityPlatform *
161
 
UnityPlatformInit(UnityWindowTracker *tracker,                            // IN
162
 
                  UnityHostCallbacks hostCallbacks)                       // IN:
163
 
{
164
 
   UnityPlatform *up;
165
 
   char *displayName;
166
 
 
167
 
   ASSERT(tracker);
168
 
 
169
 
   Debug("UnityPlatformInit: Running\n");
170
 
 
171
 
   up = (UnityPlatform*)Util_SafeCalloc(1, sizeof *up);
172
 
   up->tracker = tracker;
173
 
   up->hostCallbacks = hostCallbacks;
174
 
 
175
 
   up->savedScreenSaverTimeout = -1;
176
 
 
177
 
   /*
178
 
    * Because GDK filters events heavily, and we need to do a lot of low-level X work, we
179
 
    * just open another connection to the same display.
180
 
    */
181
 
   displayName = gdk_get_display();
182
 
   up->display = XOpenDisplay(displayName);
183
 
   if (!up->display) {
184
 
      free(up);
185
 
      return NULL; // We couldn't connect to the display for some strange reason
186
 
   }
187
 
   XSetErrorHandler(UnityPlatformXErrorHandler);
188
 
   XSynchronize(up->display, TRUE); // So error counting works properly...
189
 
 
190
 
   /*
191
 
    * Certain applications, like gnome-session during logout, may grab the X
192
 
    * server before displaying a modal window.  With the server grabbed, we're
193
 
    * unable to correctly track and display windows.
194
 
    *
195
 
    * The following snippet attempts to work around this by using the XTest
196
 
    * extension's ability to make ourselves impervious to X server grabs.
197
 
    */
198
 
   {
199
 
      int dummy1;
200
 
      int dummy2;
201
 
      int major;
202
 
      int minor;
203
 
 
204
 
      if ((XTestQueryExtension(up->display, &dummy1, &dummy2,
205
 
                               &major, &minor) == True) &&
206
 
          ((major > 2) || (major == 2 && minor >= 2))) {
207
 
         if (XTestGrabControl(up->display, True) != 1) {
208
 
            Debug("XTestGrabControl failed.\n");
209
 
         }
210
 
      } else {
211
 
         Debug("XTest extension not available.\n");
212
 
      }
213
 
   }
214
 
 
215
 
   up->allWindows = HashTable_Alloc(128, HASH_INT_KEY, NULL);
216
 
   up->specialWindows = HashTable_Alloc(32, HASH_INT_KEY, NULL);
217
 
   up->desktopWindow = NULL;
218
 
   up->desktopInfo.initialDesktop = UNITY_X11_INITIALDESKTOP_UNSET;
219
 
 
220
 
   /*
221
 
    * Find the values of all the atoms
222
 
    */
223
 
#  define INIT_ATOM(x) up->atoms.x = XInternAtom(up->display, #x, False)
224
 
 
225
 
   INIT_ATOM(_NET_WM_WINDOW_TYPE);
226
 
   INIT_ATOM(_NET_WM_WINDOW_TYPE_DESKTOP);
227
 
   INIT_ATOM(_NET_WM_WINDOW_TYPE_DOCK);
228
 
   INIT_ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR);
229
 
   INIT_ATOM(_NET_WM_WINDOW_TYPE_TOOLTIP);
230
 
   INIT_ATOM(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU);
231
 
   INIT_ATOM(_NET_WM_WINDOW_TYPE_POPUP_MENU);
232
 
   INIT_ATOM(_NET_WM_WINDOW_TYPE_MENU);
233
 
   INIT_ATOM(_NET_WM_WINDOW_TYPE_UTILITY);
234
 
   INIT_ATOM(_NET_WM_WINDOW_TYPE_SPLASH);
235
 
   INIT_ATOM(_NET_WM_WINDOW_TYPE_DIALOG);
236
 
   INIT_ATOM(_NET_WM_WINDOW_TYPE_NORMAL);
237
 
   INIT_ATOM(_NET_WM_WINDOW_TYPE_DND);
238
 
   INIT_ATOM(_NET_WM_STATE);
239
 
   INIT_ATOM(_NET_WM_STATE_HIDDEN);
240
 
   INIT_ATOM(_NET_WM_STATE_MODAL);
241
 
   INIT_ATOM(_NET_WM_STATE_STICKY);
242
 
   INIT_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
243
 
   INIT_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
244
 
   INIT_ATOM(_NET_WM_STATE_MINIMIZED);
245
 
   INIT_ATOM(_NET_WM_STATE_SHADED);
246
 
   INIT_ATOM(_NET_WM_STATE_SKIP_TASKBAR);
247
 
   INIT_ATOM(_NET_WM_STATE_SKIP_PAGER);
248
 
   INIT_ATOM(_NET_WM_STATE_FULLSCREEN);
249
 
   INIT_ATOM(_NET_WM_STATE_ABOVE);
250
 
   INIT_ATOM(_NET_WM_STATE_BELOW);
251
 
   INIT_ATOM(_NET_WM_STATE_DEMANDS_ATTENTION);
252
 
   INIT_ATOM(_NET_WM_USER_TIME);
253
 
   INIT_ATOM(_NET_WM_USER_TIME_WINDOW);
254
 
   INIT_ATOM(_NET_ACTIVE_WINDOW);
255
 
   INIT_ATOM(_NET_RESTACK_WINDOW);
256
 
   INIT_ATOM(_NET_WM_ICON);
257
 
   INIT_ATOM(_NET_WM_PID);
258
 
   INIT_ATOM(_NET_WM_STRUT);
259
 
   INIT_ATOM(_NET_WM_STRUT_PARTIAL);
260
 
   INIT_ATOM(_NET_MOVERESIZE_WINDOW);
261
 
   INIT_ATOM(_NET_CLOSE_WINDOW);
262
 
   INIT_ATOM(_NET_WM_ALLOWED_ACTIONS);
263
 
   INIT_ATOM(_NET_WM_ACTION_MOVE);
264
 
   INIT_ATOM(_NET_WM_ACTION_RESIZE);
265
 
   INIT_ATOM(_NET_WM_ACTION_MINIMIZE);
266
 
   INIT_ATOM(_NET_WM_ACTION_SHADE);
267
 
   INIT_ATOM(_NET_WM_ACTION_STICK);
268
 
   INIT_ATOM(_NET_WM_ACTION_MAXIMIZE_HORZ);
269
 
   INIT_ATOM(_NET_WM_ACTION_MAXIMIZE_VERT);
270
 
   INIT_ATOM(_NET_WM_ACTION_FULLSCREEN);
271
 
   INIT_ATOM(_NET_WM_ACTION_CHANGE_DESKTOP);
272
 
   INIT_ATOM(_NET_WM_ACTION_CLOSE);
273
 
   INIT_ATOM(_NET_NUMBER_OF_DESKTOPS);
274
 
   INIT_ATOM(_NET_WM_DESKTOP);
275
 
   INIT_ATOM(_NET_CURRENT_DESKTOP);
276
 
   INIT_ATOM(_NET_DESKTOP_LAYOUT);
277
 
   INIT_ATOM(_NET_SUPPORTED);
278
 
   INIT_ATOM(_NET_FRAME_EXTENTS);
279
 
   INIT_ATOM(WM_CLASS);
280
 
   INIT_ATOM(WM_CLIENT_LEADER);
281
 
   INIT_ATOM(WM_DELETE_WINDOW);
282
 
   INIT_ATOM(WM_ICON);
283
 
   INIT_ATOM(WM_NAME);
284
 
   INIT_ATOM(WM_PROTOCOLS);
285
 
   INIT_ATOM(WM_STATE);
286
 
   INIT_ATOM(WM_TRANSIENT_FOR);
287
 
   INIT_ATOM(WM_WINDOW_ROLE);
288
 
   INIT_ATOM(COMPOUND_TEXT);
289
 
   INIT_ATOM(UTF8_STRING);
290
 
 
291
 
#  undef INIT_ATOM
292
 
 
293
 
#if defined(VM_HAVE_X11_SHAPE_EXT)
294
 
   if (!XShapeQueryExtension(up->display, &up->shapeEventBase, &up->shapeErrorBase)) {
295
 
      up->shapeEventBase = 0;
296
 
   }
297
 
#endif
298
 
 
299
 
   up->wpFactory = new vmware::tools::unity::WindowPathFactory(up->display);
300
 
 
301
 
   return up;
302
 
}
303
 
 
304
 
 
305
 
/*
306
 
 *----------------------------------------------------------------------------
307
 
 *
308
 
 * UnityPlatformCleanup --
309
 
 *
310
 
 *      One-time platform-specific cleanup code.
311
 
 *
312
 
 * Results:
313
 
 *      None.
314
 
 *
315
 
 * Side effects:
316
 
 *      None.
317
 
 *
318
 
 *----------------------------------------------------------------------------
319
 
 */
320
 
 
321
 
void
322
 
UnityPlatformCleanup(UnityPlatform *up) // IN
323
 
{
324
 
   if (!up) {
325
 
      return;
326
 
   }
327
 
 
328
 
   /*
329
 
    * Caller should've called Unity_Exit first.
330
 
    */
331
 
   ASSERT(!up->isRunning);
332
 
   ASSERT(up->glibSource == NULL);
333
 
 
334
 
   delete up->wpFactory;
335
 
 
336
 
   if (up->specialWindows) {
337
 
      HashTable_Free(up->specialWindows);
338
 
      up->specialWindows = NULL;
339
 
   }
340
 
   if (up->allWindows) {
341
 
      HashTable_Free(up->allWindows);
342
 
      up->allWindows = NULL;
343
 
   }
344
 
 
345
 
   if (up->display) {
346
 
      XCloseDisplay(up->display);
347
 
      up->display = NULL;
348
 
   }
349
 
 
350
 
   up->desktopWindow = NULL;
351
 
 
352
 
   free(up);
353
 
}
354
 
 
355
 
 
356
 
/*****************************************************************************
357
 
 * Unity main loop and event handling                                        *
358
 
 *****************************************************************************/
359
 
 
360
 
 
361
 
/*
362
 
 *-----------------------------------------------------------------------------
363
 
 *
364
 
 * USWindowCreate --
365
 
 *
366
 
 *      Creates a new UnitySpecialWindow. Ownership of the 'windows' memory is taken over
367
 
 *      by the newly created object, but that memory MUST be malloc'd...
368
 
 *
369
 
 * Results:
370
 
 *      New UnitySpecialWindow object.
371
 
 *
372
 
 * Side effects:
373
 
 *      Allocates memory.
374
 
 *
375
 
 *-----------------------------------------------------------------------------
376
 
 */
377
 
 
378
 
static UnitySpecialWindow *
379
 
USWindowCreate(UnityPlatform *up,                    // IN
380
 
               UnitySpecialEventHandler evHandler,   // IN
381
 
               Window *windows,                      // IN
382
 
               int windowCount)                      // IN
383
 
{
384
 
   UnitySpecialWindow *usw;
385
 
 
386
 
   ASSERT(up);
387
 
 
388
 
   usw = (UnitySpecialWindow*)Util_SafeCalloc(1, sizeof *usw);
389
 
   usw->evHandler = evHandler;
390
 
   USWindowUpdate(up, usw, windows, windowCount);
391
 
 
392
 
   return usw;
393
 
}
394
 
 
395
 
 
396
 
/*
397
 
 *-----------------------------------------------------------------------------
398
 
 *
399
 
 * USWindowUpdate --
400
 
 *
401
 
 *      Updates this USWindow with a new list of X windows. Ownership of the 'windows'
402
 
 *      memory is taken over by this USWindow object. That memory MUST be malloc'd...
403
 
 *
404
 
 * Results:
405
 
 *      None.
406
 
 *
407
 
 * Side effects:
408
 
 *      Old window list may be destroyed and freed.
409
 
 *
410
 
 *-----------------------------------------------------------------------------
411
 
 */
412
 
 
413
 
static void
414
 
USWindowUpdate(UnityPlatform *up,       // IN
415
 
               UnitySpecialWindow *usw, // IN
416
 
               Window *windows,         // IN
417
 
               int windowCount)         // IN
418
 
{
419
 
   ASSERT(up);
420
 
   ASSERT(usw);
421
 
 
422
 
   for (unsigned int i = 0; i < usw->numWindows; i++) {
423
 
      XSelectInput(up->display, usw->windows[i], 0);
424
 
      HashTable_Delete(up->specialWindows, GUINT_TO_POINTER(usw->windows[i]));
425
 
   }
426
 
 
427
 
   free(usw->windows);
428
 
   usw->windows = windows;
429
 
   usw->numWindows = windowCount;
430
 
 
431
 
   for (int i = 0; i < windowCount; i++) {
432
 
      HashTable_Insert(up->specialWindows, GUINT_TO_POINTER(windows[i]), usw);
433
 
   }
434
 
}
435
 
 
436
 
 
437
 
/*
438
 
 *-----------------------------------------------------------------------------
439
 
 *
440
 
 * USWindowLookup --
441
 
 *
442
 
 *      Looks up a special window
443
 
 *
444
 
 * Results:
445
 
 *      UnitySpecialWindow object
446
 
 *
447
 
 * Side effects:
448
 
 *      None.
449
 
 *
450
 
 *-----------------------------------------------------------------------------
451
 
 */
452
 
 
453
 
static UnitySpecialWindow *
454
 
USWindowLookup(UnityPlatform *up, // IN
455
 
               Window window)     // IN
456
 
{
457
 
   UnitySpecialWindow *retval = NULL;
458
 
 
459
 
   HashTable_Lookup(up->specialWindows, GUINT_TO_POINTER(window), (void **)&retval);
460
 
 
461
 
   return retval;
462
 
}
463
 
 
464
 
 
465
 
/*
466
 
 *-----------------------------------------------------------------------------
467
 
 *
468
 
 * USWindowDestroy --
469
 
 *
470
 
 *      Destroys a UnitySpecialWindow
471
 
 *
472
 
 * Results:
473
 
 *      None.
474
 
 *
475
 
 * Side effects:
476
 
 *      Memory is freed.
477
 
 *
478
 
 *-----------------------------------------------------------------------------
479
 
 */
480
 
 
481
 
static void
482
 
USWindowDestroy(UnityPlatform *up,       // IN
483
 
                UnitySpecialWindow *usw) // IN
484
 
{
485
 
   ASSERT(up);
486
 
   ASSERT(usw);
487
 
 
488
 
   for (unsigned int i = 0; i < usw->numWindows; i++) {
489
 
      HashTable_Delete(up->specialWindows, GUINT_TO_POINTER(usw->windows[i]));
490
 
 
491
 
      if (usw->windowsAreOwned) {
492
 
         XDestroyWindow(up->display, usw->windows[i]);
493
 
      } else {
494
 
         /*
495
 
          * For now, assume we don't have any special windows that get extension events
496
 
          * and need a call like XScreenSaverSelectInput...
497
 
          */
498
 
         XSelectInput(up->display, usw->windows[i], 0);
499
 
      }
500
 
   }
501
 
   free(usw->windows);
502
 
 
503
 
   free(usw);
504
 
}
505
 
 
506
 
 
507
 
/*
508
 
 *-----------------------------------------------------------------------------
509
 
 *
510
 
 * UnityPlatformMakeRootWindowsObject --
511
 
 *
512
 
 *      Creates a UnitySpecialWindow to handle the root windows.
513
 
 *
514
 
 * Results:
515
 
 *      UnitySpecialWindow
516
 
 *
517
 
 * Side effects:
518
 
 *      Selects for events on the root windows.
519
 
 *
520
 
 *-----------------------------------------------------------------------------
521
 
 */
522
 
 
523
 
static UnitySpecialWindow *
524
 
UnityPlatformMakeRootWindowsObject(UnityPlatform *up) // IN
525
 
{
526
 
   static const long eventMask =
527
 
      StructureNotifyMask
528
 
      | PropertyChangeMask
529
 
      | SubstructureNotifyMask
530
 
      | FocusChangeMask;
531
 
   int i;
532
 
   int numRootWindows;
533
 
   Window *rootWindows;
534
 
 
535
 
   ASSERT(up);
536
 
 
537
 
   numRootWindows = ScreenCount(up->display);
538
 
   ASSERT(numRootWindows > 0);
539
 
 
540
 
   rootWindows = (Window*)Util_SafeCalloc(numRootWindows, sizeof rootWindows[0]);
541
 
   for (i = 0; i < numRootWindows; i++) {
542
 
      rootWindows[i] = RootWindow(up->display, i);
543
 
   }
544
 
 
545
 
   for (i = 0; i < numRootWindows; i++) {
546
 
      XSelectInput(up->display, rootWindows[i], eventMask);
547
 
   }
548
 
 
549
 
   return USWindowCreate(up, USRootWindowsProcessEvent, rootWindows, numRootWindows);
550
 
}
551
 
 
552
 
 
553
 
/*
554
 
 *-----------------------------------------------------------------------------
555
 
 *
556
 
 * UnityPlatformGetErrorCount --
557
 
 *
558
 
 *      Retrieves the current count of X11 errors received by Unity.
559
 
 *
560
 
 * Results:
561
 
 *      Current error count.
562
 
 *
563
 
 * Side effects:
564
 
 *      None.
565
 
 *
566
 
 *-----------------------------------------------------------------------------
567
 
 */
568
 
 
569
 
int
570
 
UnityPlatformGetErrorCount(UnityPlatform *up) // IN
571
 
{
572
 
   return unityX11ErrorCount;
573
 
}
574
 
 
575
 
 
576
 
/*
577
 
 *-----------------------------------------------------------------------------
578
 
 *
579
 
 * UnityPlatformResetErrorCount --
580
 
 *
581
 
 *      Resets the Unity X11 error count to zero.
582
 
 *
583
 
 * Results:
584
 
 *      None.
585
 
 *
586
 
 * Side effects:
587
 
 *      Error count reset.
588
 
 *
589
 
 *-----------------------------------------------------------------------------
590
 
 */
591
 
 
592
 
void
593
 
UnityPlatformResetErrorCount(UnityPlatform *up) // IN
594
 
{
595
 
   unityX11ErrorCount = 0;
596
 
}
597
 
 
598
 
 
599
 
/*
600
 
 *-----------------------------------------------------------------------------
601
 
 *
602
 
 * UnityPlatformXErrorHandler --
603
 
 *
604
 
 *      Handler for all X event errors.
605
 
 *
606
 
 * Results:
607
 
 *      1.
608
 
 *
609
 
 * Side effects:
610
 
 *      Updates our X11 error counter.
611
 
 *
612
 
 *-----------------------------------------------------------------------------
613
 
 */
614
 
 
615
 
static int
616
 
UnityPlatformXErrorHandler(Display *dpy,     // IN
617
 
                           XErrorEvent *xev) // IN
618
 
{
619
 
   char buf[1024];
620
 
   XGetErrorText(dpy, xev->error_code, buf, sizeof buf);
621
 
   Debug("> VMwareUserXErrorHandler: error %s on resource %#lx for request %d\n",
622
 
         buf, xev->resourceid, xev->request_code);
623
 
 
624
 
   unityX11ErrorCount++;
625
 
 
626
 
   return 1;
627
 
}
628
 
 
629
 
 
630
 
/*
631
 
 *-----------------------------------------------------------------------------
632
 
 *
633
 
 * UnityPlatformGetServerTime --
634
 
 *
635
 
 *      Returns an educated guess at the X server's current timestamp
636
 
 *
637
 
 * Results:
638
 
 *      X server timestamp
639
 
 *
640
 
 * Side effects:
641
 
 *      None.
642
 
 *
643
 
 *-----------------------------------------------------------------------------
644
 
 */
645
 
 
646
 
Time
647
 
UnityPlatformGetServerTime(UnityPlatform *up) // IN
648
 
{
649
 
   Time retval;
650
 
   struct timeval tv;
651
 
 
652
 
   gettimeofday(&tv, NULL);
653
 
   retval = up->eventTimeDiff + (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
654
 
 
655
 
   Debug("UserTime is guessed at %lu\n", retval);
656
 
 
657
 
   return retval;
658
 
}
659
 
 
660
 
 
661
 
/*
662
 
 *-----------------------------------------------------------------------------
663
 
 *
664
 
 * ComparePointers --
665
 
 *
666
 
 *      Compares two pointers to see whether they're equal.
667
 
 *
668
 
 * Results:
669
 
 *      -1, 0, or 1 (same meaning as strcmp return values)
670
 
 *
671
 
 * Side effects:
672
 
 *      None.
673
 
 *
674
 
 *-----------------------------------------------------------------------------
675
 
 */
676
 
 
677
 
static INLINE int
678
 
ComparePointers(const void *p1, // IN
679
 
                const void *p2) // IN
680
 
{
681
 
   /*
682
 
    * Helper function for UnityPlatformKillHelperThreads
683
 
    */
684
 
   char** ptr1 = (char**)p1;
685
 
   char** ptr2 = (char**)p2;
686
 
   ptrdiff_t diff = (*ptr2 - *ptr1);
687
 
 
688
 
   if (diff < 0) {
689
 
      return -1;
690
 
   } else if (diff > 0) {
691
 
      return 1;
692
 
   }
693
 
 
694
 
   return 0;
695
 
}
696
 
 
697
 
 
698
 
/*
699
 
 *----------------------------------------------------------------------------
700
 
 *
701
 
 * UnityPlatformExitUnity --
702
 
 *
703
 
 *      Tears down the Unity "running" state.
704
 
 *
705
 
 * Results:
706
 
 *      None.
707
 
 *
708
 
 * Side effects:
709
 
 *      Restores system settings.
710
 
 *
711
 
 *----------------------------------------------------------------------------
712
 
 */
713
 
 
714
 
void
715
 
UnityPlatformExitUnity(UnityPlatform *up) // IN
716
 
{
717
 
   UnityPlatformWindow **upwList;
718
 
   UnitySpecialWindow **uswList;
719
 
   size_t i;
720
 
   size_t numWindows;
721
 
 
722
 
   if (!up || !up->isRunning) {
723
 
      ASSERT(up->glibSource == NULL);
724
 
      return;
725
 
   }
726
 
 
727
 
   UnityX11EventTeardownSource(up);
728
 
 
729
 
   up->desktopInfo.numDesktops = 0; // Zero means host has not set virtual desktop config
730
 
   free(up->desktopInfo.guestDesktopToUnity);
731
 
   up->desktopInfo.guestDesktopToUnity = NULL;
732
 
   free(up->desktopInfo.unityDesktopToGuest);
733
 
   up->desktopInfo.unityDesktopToGuest = NULL;
734
 
 
735
 
   UnityX11RestoreSystemSettings(up);
736
 
 
737
 
   HashTable_ToArray(up->allWindows,
738
 
                     (void ***)&upwList,
739
 
                     &numWindows);
740
 
   qsort(upwList, numWindows, sizeof *upwList, ComparePointers);
741
 
   for (i = 0; i < numWindows; i++) {
742
 
      if (i < (numWindows - 1) && upwList[i] == upwList[i + 1]) {
743
 
         continue;
744
 
      }
745
 
 
746
 
      UPWindow_Unref(up, upwList[i]);
747
 
   }
748
 
   free(upwList);
749
 
 
750
 
   up->workAreas = NULL;
751
 
   up->rootWindows = NULL;
752
 
   HashTable_ToArray(up->specialWindows,
753
 
                     (void ***)&uswList,
754
 
                     &numWindows);
755
 
   qsort(uswList, numWindows, sizeof *uswList, ComparePointers);
756
 
   for (i = 0; i < numWindows; i++) {
757
 
      if (i < (numWindows - 1) && uswList[i] == uswList[i + 1]) {
758
 
         continue;
759
 
      }
760
 
 
761
 
      USWindowDestroy(up, uswList[i]);
762
 
   }
763
 
   free(uswList);
764
 
 
765
 
   XSync(up->display, TRUE);
766
 
   up->desktopInfo.initialDesktop = UNITY_X11_INITIALDESKTOP_UNSET;
767
 
   up->isRunning = FALSE;
768
 
 
769
 
   Debug("Leaving unity mode\n");
770
 
}
771
 
 
772
 
 
773
 
/*
774
 
 *-----------------------------------------------------------------------------
775
 
 *
776
 
 * UnityX11GetWMProtocols --
777
 
 *
778
 
 *      Updates the list of protocols supported by the window manager.
779
 
 *
780
 
 * Results:
781
 
 *      None.
782
 
 *
783
 
 * Side effects:
784
 
 *      None.
785
 
 *
786
 
 *-----------------------------------------------------------------------------
787
 
 */
788
 
 
789
 
static void
790
 
UnityX11GetWMProtocols(UnityPlatform *up) // IN
791
 
{
792
 
   Atom propertyType;
793
 
   int propertyFormat;
794
 
   unsigned long itemsReturned;
795
 
   unsigned long bytesRemaining;
796
 
   Atom *valueReturned = NULL;
797
 
 
798
 
   ASSERT(up);
799
 
 
800
 
   memset(up->wmProtocols, 0, sizeof up->wmProtocols);
801
 
   if (XGetWindowProperty(up->display, up->rootWindows->windows[0],
802
 
                          up->atoms._NET_SUPPORTED, 0,
803
 
                          1024, False, AnyPropertyType,
804
 
                          &propertyType, &propertyFormat, &itemsReturned,
805
 
                          &bytesRemaining, (unsigned char **)&valueReturned)
806
 
      != Success) {
807
 
      return;
808
 
   }
809
 
 
810
 
   if ((propertyType == XA_ATOM || propertyType == XA_CARDINAL)
811
 
       && propertyFormat == 32) {
812
 
      unsigned long i;
813
 
 
814
 
      for (i = 0; i < itemsReturned; i++) {
815
 
         if (valueReturned[i] == up->atoms._NET_MOVERESIZE_WINDOW) {
816
 
            up->wmProtocols[UNITY_X11_WM__NET_MOVERESIZE_WINDOW] = TRUE;
817
 
         } else if (valueReturned[i] == up->atoms._NET_CLOSE_WINDOW) {
818
 
            up->wmProtocols[UNITY_X11_WM__NET_CLOSE_WINDOW] = TRUE;
819
 
         } else if (valueReturned[i] == up->atoms._NET_RESTACK_WINDOW) {
820
 
            up->wmProtocols[UNITY_X11_WM__NET_RESTACK_WINDOW] = TRUE;
821
 
         } else if (valueReturned[i] == up->atoms._NET_ACTIVE_WINDOW) {
822
 
            up->wmProtocols[UNITY_X11_WM__NET_ACTIVE_WINDOW] = TRUE;
823
 
         } else if (valueReturned[i] == up->atoms._NET_WM_ACTION_MINIMIZE) {
824
 
            up->wmProtocols[UNITY_X11_WM__NET_WM_ACTION_MINIMIZE] = TRUE;
825
 
         } else if (valueReturned[i] == up->atoms._NET_WM_ACTION_CLOSE) {
826
 
            up->wmProtocols[UNITY_X11_WM__NET_WM_ACTION_CLOSE] = TRUE;
827
 
         } else if (valueReturned[i] == up->atoms._NET_WM_ACTION_SHADE) {
828
 
            up->wmProtocols[UNITY_X11_WM__NET_WM_ACTION_SHADE] = TRUE;
829
 
         } else if (valueReturned[i] == up->atoms._NET_WM_ACTION_STICK) {
830
 
            up->wmProtocols[UNITY_X11_WM__NET_WM_ACTION_STICK] = TRUE;
831
 
         } else if (valueReturned[i] == up->atoms._NET_WM_ACTION_FULLSCREEN) {
832
 
            up->wmProtocols[UNITY_X11_WM__NET_WM_ACTION_FULLSCREEN] = TRUE;
833
 
         } else if (valueReturned[i] == up->atoms._NET_WM_ACTION_MAXIMIZE_HORZ) {
834
 
            up->wmProtocols[UNITY_X11_WM__NET_WM_ACTION_MAXIMIZE_HORZ] = TRUE;
835
 
         } else if (valueReturned[i] == up->atoms._NET_WM_ACTION_MAXIMIZE_VERT) {
836
 
            up->wmProtocols[UNITY_X11_WM__NET_WM_ACTION_MAXIMIZE_VERT] = TRUE;
837
 
         } else if (valueReturned[i] == up->atoms._NET_FRAME_EXTENTS) {
838
 
            up->wmProtocols[UNITY_X11_WM__NET_FRAME_EXTENTS] = TRUE;
839
 
         } else if (valueReturned[i] == up->atoms._NET_WM_STRUT_PARTIAL) {
840
 
            up->wmProtocols[UNITY_X11_WM__NET_WM_STRUT_PARTIAL] = TRUE;
841
 
         } else if (valueReturned[i] == up->atoms._NET_WM_STATE_HIDDEN) {
842
 
            up->wmProtocols[UNITY_X11_WM__NET_WM_STATE_HIDDEN] = TRUE;
843
 
         } else if (valueReturned[i] == up->atoms._NET_WM_STATE_MINIMIZED) {
844
 
            up->wmProtocols[UNITY_X11_WM__NET_WM_STATE_MINIMIZED] = TRUE;
845
 
         }
846
 
      }
847
 
   }
848
 
 
849
 
   XFree(valueReturned);
850
 
}
851
 
 
852
 
 
853
 
/*
854
 
 *----------------------------------------------------------------------------
855
 
 *
856
 
 * UnityPlatformEnterUnity --
857
 
 *
858
 
 *      Start Unity running.
859
 
 *
860
 
 * Results:
861
 
 *      TRUE if successful
862
 
 *      FALSE otherwise
863
 
 *
864
 
 * Side effects:
865
 
 *      Saves and changes system settings.
866
 
 *      Starts watching for windowing system events.
867
 
 *
868
 
 *----------------------------------------------------------------------------
869
 
 */
870
 
 
871
 
Bool
872
 
UnityPlatformEnterUnity(UnityPlatform *up) // IN
873
 
{
874
 
   UnityDesktopId activeDesktop;
875
 
 
876
 
   ASSERT(up);
877
 
   ASSERT(up->glibSource == NULL);
878
 
 
879
 
   XSync(up->display, TRUE);
880
 
   up->rootWindows = UnityPlatformMakeRootWindowsObject(up);
881
 
   MakeCompositeOverlaysObject(up);
882
 
   up->isRunning = TRUE;
883
 
   up->eventTimeDiff = 0;
884
 
 
885
 
   UnityX11SaveSystemSettings(up);
886
 
 
887
 
   UnityX11GetWMProtocols(up);
888
 
 
889
 
   if (up->desktopInfo.numDesktops == 0) {
890
 
      /*
891
 
       * PR 633099:  Host UI hasn't set the desktop config yet.  In that case,
892
 
       * let's go ahead and initialize our the host:guest desktop mappings
893
 
       * based on the guest's current configuration.  (This avoids unnecessarily
894
 
       * changing the guest desktop layout.)
895
 
       *
896
 
       * XXX Consider factoring this out of UPSetDesktopConfig.
897
 
       */
898
 
      unsigned int i;
899
 
 
900
 
      ASSERT(up->desktopInfo.guestDesktopToUnity == NULL);
901
 
      ASSERT(up->desktopInfo.unityDesktopToGuest == NULL);
902
 
 
903
 
      up->desktopInfo.numDesktops = UnityPlatformGetNumVirtualDesktops(up);
904
 
      if (up->desktopInfo.numDesktops == 0) {
905
 
         Warning("%s: _NET_NUMBER_OF_DESKTOPS set to 0; impossible.\n", __FUNCTION__);
906
 
         return FALSE;
907
 
      }
908
 
 
909
 
      up->desktopInfo.guestDesktopToUnity = (UnityDesktopId*)
910
 
         Util_SafeMalloc(up->desktopInfo.numDesktops *
911
 
                         sizeof up->desktopInfo.guestDesktopToUnity[0]);
912
 
      up->desktopInfo.unityDesktopToGuest = (uint32*)
913
 
         Util_SafeMalloc(up->desktopInfo.numDesktops *
914
 
                         sizeof up->desktopInfo.unityDesktopToGuest[0]);
915
 
 
916
 
      for (i = 0; i < up->desktopInfo.numDesktops; i++) {
917
 
         up->desktopInfo.guestDesktopToUnity[i] =
918
 
            up->desktopInfo.unityDesktopToGuest[i] = i;
919
 
      }
920
 
   }
921
 
 
922
 
   UnityPlatformSyncDesktopConfig(up);
923
 
 
924
 
   if (up->desktopInfo.initialDesktop != UNITY_X11_INITIALDESKTOP_UNSET) {
925
 
      Debug("%s: Setting activeDesktop to initialDesktop (%u).\n", __func__,
926
 
            up->desktopInfo.initialDesktop);
927
 
      activeDesktop = up->desktopInfo.initialDesktop;
928
 
   } else {
929
 
      activeDesktop = UnityWindowTracker_GetActiveDesktop(up->tracker);
930
 
   }
931
 
   if (UnityPlatformSetDesktopActive(up, activeDesktop)) {;
932
 
      /*
933
 
       * XXX Rather than setting this directly here, should we instead wait for a
934
 
       * PropertyNotify event from the window manager to one of the root windows?
935
 
       * Doing so may be safer in that it confirms that our request was honored by
936
 
       * the window manager.
937
 
       */
938
 
      UnityWindowTracker_ChangeActiveDesktop(up->tracker, activeDesktop);
939
 
   }
940
 
 
941
 
   if (up->needWorkAreas) {
942
 
      /*
943
 
       * UNEXPECTED: The host called SetDesktopWorkArea before entering Unity mode, so we
944
 
       * need to go back and apply the remembered work area info.
945
 
       */
946
 
 
947
 
      UnityPlatformSetDesktopWorkAreas(up, up->needWorkAreas, up->needNumWorkAreas);
948
 
      free(up->needWorkAreas);
949
 
      up->needWorkAreas = NULL;
950
 
   }
951
 
 
952
 
   /*
953
 
    * Set up a callback in the glib main loop to listen for incoming X events on the
954
 
    * unity display connection.
955
 
    */
956
 
   UnityX11EventEstablishSource(up);
957
 
 
958
 
   return TRUE;
959
 
}
960
 
 
961
 
 
962
 
/*
963
 
 *----------------------------------------------------------------------------
964
 
 *
965
 
 * UnityPlatformIsUnityRunning --
966
 
 *
967
 
 *      Check to see if we are still in the unity mode.
968
 
 *
969
 
 * Results:
970
 
 *      TRUE if we are in Unity mode
971
 
 *      FALSE otherwise.
972
 
 *
973
 
 * Side effects:
974
 
 *      None.
975
 
 *
976
 
 *----------------------------------------------------------------------------
977
 
 */
978
 
 
979
 
Bool
980
 
UnityPlatformIsUnityRunning(UnityPlatform *up) // IN
981
 
{
982
 
   ASSERT(up);
983
 
 
984
 
   return up->isRunning;
985
 
}
986
 
 
987
 
 
988
 
/*
989
 
 *----------------------------------------------------------------------------
990
 
 *
991
 
 * UnityPlatformLock --
992
 
 *
993
 
 *      Does nothing - our implementation is not threaded.
994
 
 *
995
 
 * Results:
996
 
 *      None.
997
 
 *
998
 
 * Side effects:
999
 
 *      None (really).
1000
 
 *
1001
 
 *----------------------------------------------------------------------------
1002
 
 */
1003
 
 
1004
 
void
1005
 
UnityPlatformLock(UnityPlatform *up) // IN
1006
 
{
1007
 
}
1008
 
 
1009
 
 
1010
 
/*
1011
 
 *----------------------------------------------------------------------------
1012
 
 *
1013
 
 * UnityPlatformUnlock --
1014
 
 *
1015
 
 *      Does nothing - our implementation is not threaded.
1016
 
 *
1017
 
 * Results:
1018
 
 *      None.
1019
 
 *
1020
 
 * Side effects:
1021
 
 *      None.
1022
 
 *
1023
 
 *----------------------------------------------------------------------------
1024
 
 */
1025
 
 
1026
 
void
1027
 
UnityPlatformUnlock(UnityPlatform *up) // IN
1028
 
{
1029
 
}
1030
 
 
1031
 
 
1032
 
/*
1033
 
 *----------------------------------------------------------------------------
1034
 
 *
1035
 
 * UnityPlatformUpdateZOrder --
1036
 
 *
1037
 
 *      Push the Z-Order of all windows into the window tracker.
1038
 
 *
1039
 
 * Results:
1040
 
 *      None.
1041
 
 *
1042
 
 * Side effects:
1043
 
 *      None.
1044
 
 *
1045
 
 *----------------------------------------------------------------------------
1046
 
 */
1047
 
 
1048
 
static void
1049
 
UnityPlatformUpdateZOrder(UnityPlatform *up) // IN
1050
 
{
1051
 
   UnityWindowId *elements;
1052
 
   size_t numElements;
1053
 
   UnityPlatformWindow *curWindow;
1054
 
 
1055
 
   ASSERT(up);
1056
 
   if (!up->stackingChanged) {
1057
 
      return;
1058
 
   }
1059
 
 
1060
 
   elements = (UnityWindowId*)alloca(UNITY_MAX_WINDOWS * sizeof elements[0]);
1061
 
   for (numElements = 0, curWindow = up->topWindow;
1062
 
        curWindow; curWindow = curWindow->lowerWindow) {
1063
 
      if (curWindow->isRelevant) {
1064
 
         elements[numElements++] = curWindow->toplevelWindow;
1065
 
      }
1066
 
   }
1067
 
 
1068
 
   UnityWindowTracker_SetZOrder(up->tracker,
1069
 
                                elements,
1070
 
                                numElements);
1071
 
   up->stackingChanged = FALSE;
1072
 
}
1073
 
 
1074
 
 
1075
 
/*
1076
 
 *----------------------------------------------------------------------------
1077
 
 *
1078
 
 * UnityPlatformUpdateWindowState --
1079
 
 *
1080
 
 *      Walk through /all/ the windows on the guest, pushing everything we know about
1081
 
 *      them into the unity window tracker.
1082
 
 *
1083
 
 * Results:
1084
 
 *      TRUE indicating we need help from the common code to generate
1085
 
 *      remove window events (see unity.c)
1086
 
 *
1087
 
 * Side effects:
1088
 
 *      None
1089
 
 *
1090
 
 *----------------------------------------------------------------------------
1091
 
 */
1092
 
 
1093
 
Bool
1094
 
UnityPlatformUpdateWindowState(UnityPlatform *up,               // IN
1095
 
                               UnityWindowTracker *tracker)     // IN
1096
 
{
1097
 
   unsigned int curRoot;
1098
 
   Window lowerWindow = None;
1099
 
 
1100
 
   if (!up || !up->rootWindows) {
1101
 
      Debug("BUG: UpdateWindowState was called before we are fully in Unity mode...\n");
1102
 
      return FALSE;
1103
 
   }
1104
 
 
1105
 
   for (curRoot = 0; curRoot < up->rootWindows->numWindows; curRoot++) {
1106
 
      unsigned int i;
1107
 
      Window dummyWin;
1108
 
      Window *children;
1109
 
      unsigned int numChildren;
1110
 
 
1111
 
      XQueryTree(up->display, up->rootWindows->windows[curRoot],
1112
 
                 &dummyWin, &dummyWin, &children, &numChildren);
1113
 
 
1114
 
      for (i = 0; i < numChildren; i++) {
1115
 
         UnityPlatformWindow *upw;
1116
 
 
1117
 
         if (!HashTable_Lookup(up->allWindows,
1118
 
                               GUINT_TO_POINTER(children[i]),
1119
 
                               (void **)&upw)) {
1120
 
            upw = UPWindow_Create(up, children[i]);
1121
 
            if (!upw) {
1122
 
               continue; // Window may have disappeared since the XQueryTree
1123
 
            }
1124
 
            UPWindow_CheckRelevance(up, upw, NULL);
1125
 
            UPWindow_Restack(up, upw, lowerWindow);
1126
 
         }
1127
 
 
1128
 
         lowerWindow = upw->toplevelWindow;
1129
 
      }
1130
 
 
1131
 
      XFree(children);
1132
 
   }
1133
 
 
1134
 
   UnityPlatformUpdateZOrder(up);
1135
 
   /*
1136
 
    * up is not populated with the window layout structure when
1137
 
    * UnityPlatformUpdateDnDDetWnd is intially called.
1138
 
    */
1139
 
   UnityPlatformStackDnDDetWnd(up);
1140
 
 
1141
 
   if (up->needTaskbarSetting) {
1142
 
      up->needTaskbarSetting = FALSE;
1143
 
      /*
1144
 
       * This is called in this seemingly random spot to make sure that the taskbar
1145
 
       * visibility is properly set once we have a full picture of the windowing system
1146
 
       * state. Although the routine is called prior to this by SaveSystemSettings(), the
1147
 
       * up->allWindows hash table is not complete until this point, which occurs at a
1148
 
       * random time of the host's choosing.
1149
 
       */
1150
 
      UnityPlatformSetTaskbarVisible(up, up->currentSettings[UNITY_UI_TASKBAR_VISIBLE]);
1151
 
   }
1152
 
 
1153
 
   return FALSE;
1154
 
}
1155
 
 
1156
 
 
1157
 
/*
1158
 
 *-----------------------------------------------------------------------------
1159
 
 *
1160
 
 * UnityX11HandleEvents --
1161
 
 *
1162
 
 *      Handle incoming events
1163
 
 *
1164
 
 * Results:
1165
 
 *      TRUE if the main loop should continue watching for events from the display.
1166
 
 *
1167
 
 * Side effects:
1168
 
 *      Events read from the X display and processed.
1169
 
 *
1170
 
 *-----------------------------------------------------------------------------
1171
 
 */
1172
 
 
1173
 
gboolean
1174
 
UnityX11HandleEvents(gpointer data) // IN
1175
 
{
1176
 
   UnityPlatform *up = (UnityPlatform *) data;
1177
 
   GList *incomingEvents = NULL;
1178
 
   Bool restackDetWnd = FALSE;
1179
 
 
1180
 
   ASSERT(up);
1181
 
   ASSERT(up->isRunning);
1182
 
 
1183
 
   while (XEventsQueued(up->display, QueuedAfterFlush)) {
1184
 
      /*
1185
 
       * This outer loop is here to make sure we really process all available events
1186
 
       * before returning.
1187
 
       */
1188
 
 
1189
 
      while (XEventsQueued(up->display, QueuedAlready)) {
1190
 
         UnityTemporaryEvent *ev;
1191
 
 
1192
 
         ev = (UnityTemporaryEvent*)Util_SafeCalloc(1, sizeof *ev);
1193
 
         XNextEvent(up->display, &ev->xevent);
1194
 
         ev->realWindowID = UnityPlatformGetRealEventWindow(up, &ev->xevent);
1195
 
 
1196
 
         /*
1197
 
          * Restack dnd detection window when either
1198
 
          *   1.  the desktop window may overlap detection window, or
1199
 
          *   2.  a window is inserted directly above the desktop (and therefore
1200
 
          *       below the DND window).
1201
 
          */
1202
 
         if (up->desktopWindow &&
1203
 
             ev->xevent.type == ConfigureNotify &&
1204
 
             (up->desktopWindow->toplevelWindow == ev->realWindowID ||
1205
 
              up->desktopWindow->toplevelWindow == ev->xevent.xconfigure.above)) {
1206
 
            restackDetWnd = TRUE;
1207
 
         }
1208
 
 
1209
 
         if (ev->xevent.type == DestroyNotify) {
1210
 
            /*
1211
 
             * Unfortunately, X's event-driven model has an inherent race condition for
1212
 
             * parties that are observing events on windows that are controlled by other
1213
 
             * applications. Basically, if we're processing an event on a window, that
1214
 
             * window may have already been destroyed, and there doesn't seem to really
1215
 
             * be a way to detect this. We just have to try to cut down the probability
1216
 
             * of those as much as possible, by discarding any events on a window if
1217
 
             * they're immediately followed by a DestroyNotify on the same window...
1218
 
             */
1219
 
            GList *curItem;
1220
 
            GList *nextItem = NULL;
1221
 
 
1222
 
            for (curItem = incomingEvents; curItem; curItem = nextItem) {
1223
 
               UnityTemporaryEvent *otherEvent = (UnityTemporaryEvent*)curItem->data;
1224
 
               nextItem = curItem->next;
1225
 
 
1226
 
               if (otherEvent->realWindowID == ev->realWindowID) {
1227
 
                  free(curItem->data);
1228
 
                  incomingEvents = g_list_remove_link(incomingEvents, curItem);
1229
 
               }
1230
 
            }
1231
 
         }
1232
 
 
1233
 
         incomingEvents = g_list_append(incomingEvents, ev);
1234
 
      }
1235
 
 
1236
 
      while (incomingEvents) {
1237
 
         GList *nextItem;
1238
 
         UnityTemporaryEvent *tempEvent = (UnityTemporaryEvent*)incomingEvents->data;
1239
 
 
1240
 
         UnityPlatformProcessXEvent(up, &tempEvent->xevent, tempEvent->realWindowID);
1241
 
 
1242
 
         nextItem = incomingEvents->next;
1243
 
         free(incomingEvents->data);
1244
 
         g_list_free_1(incomingEvents);
1245
 
         incomingEvents = nextItem;
1246
 
      }
1247
 
 
1248
 
      if (restackDetWnd) {
1249
 
         UnityPlatformStackDnDDetWnd(up);
1250
 
      }
1251
 
      UnityPlatformUpdateZOrder(up);
1252
 
      UnityPlatformDoUpdate(up, TRUE);
1253
 
   }
1254
 
 
1255
 
   return TRUE;
1256
 
}
1257
 
 
1258
 
 
1259
 
/*
1260
 
 *-----------------------------------------------------------------------------
1261
 
 *
1262
 
 * UnityPlatformGetEventString --
1263
 
 *
1264
 
 *      Allows stringifying events for debugging purposes
1265
 
 *
1266
 
 * Results:
1267
 
 *      A stringified version of the event name. It's a static value - do not free this.
1268
 
 *
1269
 
 * Side effects:
1270
 
 *      None.
1271
 
 *-----------------------------------------------------------------------------
1272
 
 */
1273
 
 
1274
 
const char *
1275
 
UnityPlatformGetEventString(UnityPlatform *up, // IN
1276
 
                            int type)          // IN
1277
 
{
1278
 
#if defined(VM_HAVE_X11_SHAPE_EXT)
1279
 
   if (up->shapeEventBase
1280
 
       && type == (up->shapeEventBase + ShapeNotify)) {
1281
 
      return "ShapeNotify";
1282
 
   }
1283
 
#endif
1284
 
 
1285
 
   switch (type) {
1286
 
   case KeyPress: return "KeyPress";
1287
 
   case KeyRelease: return "KeyRelease";
1288
 
   case ButtonPress: return "ButtonPress";
1289
 
   case ButtonRelease: return "ButtonRelease";
1290
 
   case MotionNotify: return "MotionNotify";
1291
 
   case EnterNotify: return "EnterNotify";
1292
 
   case LeaveNotify: return "LeaveNotify";
1293
 
   case FocusIn: return "FocusIn";
1294
 
   case FocusOut: return "FocusOut";
1295
 
   case KeymapNotify: return "KeymapNotify";
1296
 
   case Expose: return "Expose";
1297
 
   case GraphicsExpose: return "GraphicsExpose";
1298
 
   case NoExpose: return "NoExpose";
1299
 
   case VisibilityNotify: return "VisibilityNotify";
1300
 
   case CreateNotify: return "CreateNotify";
1301
 
   case DestroyNotify: return "DestroyNotify";
1302
 
   case UnmapNotify: return "UnmapNotify";
1303
 
   case MapNotify: return "MapNotify";
1304
 
   case MapRequest: return "MapRequest";
1305
 
   case ReparentNotify: return "ReparentNotify";
1306
 
   case ConfigureNotify: return "ConfigureNotify";
1307
 
   case ConfigureRequest: return "ConfigureRequest";
1308
 
   case GravityNotify: return "GravityNotify";
1309
 
   case ResizeRequest: return "ResizeRequest";
1310
 
   case CirculateNotify: return "CirculateNotify";
1311
 
   case CirculateRequest: return "CirculateRequest";
1312
 
   case PropertyNotify: return "PropertyNotify";
1313
 
   case SelectionClear: return "SelectionClear";
1314
 
   case SelectionRequest: return "SelectionRequest";
1315
 
   case SelectionNotify: return "SelectionNotify";
1316
 
   case ColormapNotify: return "ColormapNotify";
1317
 
   case ClientMessage: return "ClientMessage";
1318
 
   case MappingNotify: return "MappingNotify";
1319
 
   default: return "<Unknown>";
1320
 
   }
1321
 
}
1322
 
 
1323
 
 
1324
 
/*
1325
 
 *-----------------------------------------------------------------------------
1326
 
 *
1327
 
 * UnityPlatformGetRealEventWindow --
1328
 
 *
1329
 
 *      For debugging purposes, retrieves the window that the event happened on (as
1330
 
 *      opposed to the window the event was sent to)
1331
 
 *
1332
 
 * Results:
1333
 
 *      The window that the event actually happened on.
1334
 
 *
1335
 
 * Side effects:
1336
 
 *      None.
1337
 
 *
1338
 
 *-----------------------------------------------------------------------------
1339
 
 */
1340
 
 
1341
 
static Window
1342
 
UnityPlatformGetRealEventWindow(UnityPlatform *up,    // IN
1343
 
                                const XEvent *xevent) // IN
1344
 
{
1345
 
#if defined(VM_HAVE_X11_SHAPE_EXT)
1346
 
   if (up->shapeEventBase
1347
 
       && xevent->type == (up->shapeEventBase + ShapeNotify)) {
1348
 
      XShapeEvent *sev = (XShapeEvent *) xevent;
1349
 
 
1350
 
      return sev->window;
1351
 
   }
1352
 
#endif
1353
 
 
1354
 
   switch (xevent->type) {
1355
 
   case CreateNotify:
1356
 
      return xevent->xcreatewindow.window;
1357
 
 
1358
 
   case DestroyNotify:
1359
 
      return xevent->xdestroywindow.window;
1360
 
 
1361
 
   case MapNotify:
1362
 
      return xevent->xmap.window;
1363
 
 
1364
 
   case UnmapNotify:
1365
 
      return xevent->xunmap.window;
1366
 
 
1367
 
   case ReparentNotify:
1368
 
      return xevent->xreparent.window;
1369
 
 
1370
 
   case ConfigureNotify:
1371
 
      return xevent->xconfigure.window;
1372
 
 
1373
 
   case CirculateNotify:
1374
 
      return xevent->xcirculate.window;
1375
 
 
1376
 
   case PropertyNotify:
1377
 
      return xevent->xproperty.window;
1378
 
 
1379
 
   case FocusIn:
1380
 
   case FocusOut:
1381
 
      return xevent->xfocus.window;
1382
 
 
1383
 
   default:
1384
 
      return xevent->xany.window;
1385
 
 
1386
 
   }
1387
 
}
1388
 
 
1389
 
 
1390
 
/*
1391
 
 *-----------------------------------------------------------------------------
1392
 
 *
1393
 
 * UnityPlatformUpdateEventTimeDiff --
1394
 
 *
1395
 
 *      Updates our idea of the difference between X server time and our local time.
1396
 
 *
1397
 
 * Results:
1398
 
 *      None.
1399
 
 *
1400
 
 * Side effects:
1401
 
 *      Updated event time diff.
1402
 
 *
1403
 
 *-----------------------------------------------------------------------------
1404
 
 */
1405
 
 
1406
 
static void
1407
 
UnityPlatformUpdateEventTimeDiff(UnityPlatform *up,    // IN
1408
 
                                 const XEvent *xevent) // IN
1409
 
{
1410
 
   Time serverTime;
1411
 
   Time localTime;
1412
 
   struct timeval localTv;
1413
 
 
1414
 
   switch (xevent->type) {
1415
 
   case KeyPress:
1416
 
   case KeyRelease:
1417
 
      serverTime = xevent->xkey.time;
1418
 
      break;
1419
 
   case ButtonPress:
1420
 
   case ButtonRelease:
1421
 
      serverTime = xevent->xbutton.time;
1422
 
      break;
1423
 
   case MotionNotify:
1424
 
      serverTime = xevent->xmotion.time;
1425
 
      break;
1426
 
   case EnterNotify:
1427
 
   case LeaveNotify:
1428
 
      serverTime = xevent->xcrossing.time;
1429
 
      break;
1430
 
   case PropertyNotify:
1431
 
      serverTime = xevent->xproperty.time;
1432
 
      break;
1433
 
   case SelectionClear:
1434
 
      serverTime = xevent->xselectionclear.time;
1435
 
      break;
1436
 
   case SelectionRequest:
1437
 
      serverTime = xevent->xselectionrequest.time;
1438
 
      break;
1439
 
   case SelectionNotify:
1440
 
      serverTime = xevent->xselection.time;
1441
 
      break;
1442
 
 
1443
 
   default:
1444
 
      return;
1445
 
   }
1446
 
 
1447
 
   gettimeofday(&localTv, NULL);
1448
 
   localTime = (localTv.tv_sec * 1000) + (localTv.tv_usec / 1000); // Convert to ms
1449
 
   up->eventTimeDiff = serverTime - localTime;
1450
 
}
1451
 
 
1452
 
 
1453
 
/*
1454
 
 *-----------------------------------------------------------------------------
1455
 
 *
1456
 
 * UnityPlatformProcessXEvent --
1457
 
 *
1458
 
 *      Processes an incoming X event.
1459
 
 *
1460
 
 * Results:
1461
 
 *      None.
1462
 
 *
1463
 
 * Side effects:
1464
 
 *      May create or destroy UnityPlatformWindow objects.
1465
 
 *
1466
 
 *-----------------------------------------------------------------------------
1467
 
 */
1468
 
 
1469
 
static void
1470
 
UnityPlatformProcessXEvent(UnityPlatform *up,      // IN
1471
 
                           const XEvent *xevent,   // IN
1472
 
                           Window realEventWindow) // IN
1473
 
{
1474
 
   UnityPlatformWindow *upw = NULL;
1475
 
   const char *eventName;
1476
 
 
1477
 
   ASSERT(up);
1478
 
   ASSERT(xevent);
1479
 
 
1480
 
   UnityPlatformUpdateEventTimeDiff(up, xevent);
1481
 
 
1482
 
   eventName = UnityPlatformGetEventString(up, xevent->type);
1483
 
   upw = UPWindow_Lookup(up, realEventWindow);
1484
 
   if (!upw) {
1485
 
      UnitySpecialWindow *usw = USWindowLookup(up, realEventWindow);
1486
 
      if (usw) {
1487
 
         if (usw->evHandler) {
1488
 
            usw->evHandler(up, usw, xevent, realEventWindow);
1489
 
         }
1490
 
 
1491
 
         return;
1492
 
      } else if (xevent->type == CreateNotify) {
1493
 
         /* Ignore decoration widgets.  They'll be reparented later. */
1494
 
         if (UnityX11Util_IsWindowDecorationWidget(up, realEventWindow)) {
1495
 
            Debug("%s: Window %#lx is a decoration widget.  Ignore it.\n",
1496
 
                  __func__, realEventWindow);
1497
 
            return;
1498
 
         }
1499
 
 
1500
 
         /*
1501
 
          * It may be a new window that we don't know about yet. Let's create an object
1502
 
          * to track it.
1503
 
          */
1504
 
         upw = UPWindow_Create(up, realEventWindow);
1505
 
         if (upw) {
1506
 
            UPWindow_CheckRelevance(up, upw, NULL);
1507
 
         } else {
1508
 
            Debug("UnityX11ThreadProcessEvent BOMBED:"
1509
 
                  " %s on window %#lx (reported to %#lx)\n",
1510
 
                  eventName, realEventWindow, xevent->xany.window);
1511
 
         }
1512
 
      } else {
1513
 
         /*
1514
 
          * If we use them on non-CreateNotify events, the above lines of code wind up
1515
 
          * trying to create objects for crazy windows that don't exist...
1516
 
          */
1517
 
         Debug("Ignoring %s event on unknown window %#lx (reported to %#lx)\n",
1518
 
               eventName, realEventWindow, xevent->xany.window);
1519
 
      }
1520
 
   }
1521
 
 
1522
 
   if (upw) {
1523
 
      UPWindow_ProcessEvent(up, upw, realEventWindow, xevent);
1524
 
      if (upw->deleteWhenSafe) {
1525
 
         Debug("%s: refs %u, deleteWhenSafe %u\n", __func__, upw->refs,
1526
 
               upw->deleteWhenSafe);
1527
 
         UPWindow_Unref(up, upw);
1528
 
      }
1529
 
   }
1530
 
}
1531
 
 
1532
 
 
1533
 
/*
1534
 
 *-----------------------------------------------------------------------------
1535
 
 *
1536
 
 * UnityPlatformIsRootWindow --
1537
 
 *
1538
 
 *      Checks whether a given window ID is the root window. Necessary because each
1539
 
 *      screen has a separate root window, which makes checking a little more complicated
1540
 
 *      than ==.
1541
 
 *
1542
 
 * Results:
1543
 
 *      TRUE if the given window is a root window, FALSE otherwise.
1544
 
 *
1545
 
 * Side effects:
1546
 
 *      None.
1547
 
 *
1548
 
 *-----------------------------------------------------------------------------
1549
 
 */
1550
 
 
1551
 
Bool
1552
 
UnityPlatformIsRootWindow(UnityPlatform *up, // IN
1553
 
                          Window window)     // IN
1554
 
{
1555
 
   ASSERT(up);
1556
 
 
1557
 
   return (USWindowLookup(up, window) == up->rootWindows);
1558
 
}
1559
 
 
1560
 
 
1561
 
/*
1562
 
 *-----------------------------------------------------------------------------
1563
 
 *
1564
 
 * UnityX11SetCurrentDesktop --
1565
 
 *
1566
 
 *      Sets the active virtual desktop.
1567
 
 *
1568
 
 * Results:
1569
 
 *      None.
1570
 
 *
1571
 
 * Side effects:
1572
 
 *      Changes the virtual desktop.
1573
 
 *
1574
 
 *-----------------------------------------------------------------------------
1575
 
 */
1576
 
 
1577
 
void
1578
 
UnityX11SetCurrentDesktop(UnityPlatform *up,     // IN
1579
 
                          uint32 currentDesktop) // IN: guest-side desktop ID
1580
 
{
1581
 
   Atom data[5] = {0,0,0,0,0};
1582
 
 
1583
 
   ASSERT(up);
1584
 
   ASSERT(up->rootWindows->windows);
1585
 
 
1586
 
   up->desktopInfo.currentDesktop = currentDesktop;
1587
 
   data[0] = currentDesktop;
1588
 
   data[1] = UnityPlatformGetServerTime(up);
1589
 
   UnityPlatformSendClientMessage(up,
1590
 
                                  up->rootWindows->windows[0],
1591
 
                                  up->rootWindows->windows[0],
1592
 
                                  up->atoms._NET_CURRENT_DESKTOP,
1593
 
                                  32, 5, data);
1594
 
}
1595
 
 
1596
 
 
1597
 
/*
1598
 
 *-----------------------------------------------------------------------------
1599
 
 *
1600
 
 * UnityX11GetCurrentDesktop --
1601
 
 *
1602
 
 *      Gets the active virtual desktop.
1603
 
 *
1604
 
 * Results:
1605
 
 *      The active virtual desktop. If it cannot be retrieved for any reason, a
1606
 
 *      reasonable default of '0' will be returned.
1607
 
 *
1608
 
 * Side effects:
1609
 
 *      None.
1610
 
 *
1611
 
 *-----------------------------------------------------------------------------
1612
 
 */
1613
 
 
1614
 
uint32
1615
 
UnityX11GetCurrentDesktop(UnityPlatform *up) // IN
1616
 
{
1617
 
   Atom propertyType;
1618
 
   int propertyFormat;
1619
 
   unsigned long itemsReturned;
1620
 
   unsigned long bytesRemaining;
1621
 
   Atom *valueReturned;
1622
 
   uint32 currentDesktop;
1623
 
 
1624
 
   ASSERT(up);
1625
 
   ASSERT(up->rootWindows);
1626
 
 
1627
 
   if (XGetWindowProperty(up->display, up->rootWindows->windows[0],
1628
 
                          up->atoms._NET_CURRENT_DESKTOP, 0,
1629
 
                          1024, False, AnyPropertyType,
1630
 
                          &propertyType, &propertyFormat, &itemsReturned,
1631
 
                          &bytesRemaining, (unsigned char **)&valueReturned)
1632
 
       == Success
1633
 
       && propertyType == XA_CARDINAL
1634
 
       && propertyFormat == 32) {
1635
 
      ASSERT(itemsReturned == 1);
1636
 
 
1637
 
      currentDesktop = valueReturned[0];
1638
 
   } else {
1639
 
      currentDesktop = 0;
1640
 
   }
1641
 
   XFree(valueReturned);
1642
 
 
1643
 
   return currentDesktop;
1644
 
}
1645
 
 
1646
 
 
1647
 
/*
1648
 
 *-----------------------------------------------------------------------------
1649
 
 *
1650
 
 * USRootWindowsUpdateCurrentDesktop --
1651
 
 *
1652
 
 *      Looks at the root window to figure out the current desktop
1653
 
 *
1654
 
 * Results:
1655
 
 *      None.
1656
 
 *
1657
 
 * Side effects:
1658
 
 *      Updates UnityWindowTracker.
1659
 
 *
1660
 
 *-----------------------------------------------------------------------------
1661
 
 */
1662
 
 
1663
 
static void
1664
 
USRootWindowsUpdateCurrentDesktop(UnityPlatform *up,       // IN
1665
 
                                  UnitySpecialWindow *usw, // IN
1666
 
                                  Window window)           // IN
1667
 
{
1668
 
   uint32 currentDesktop;
1669
 
   UnityDesktopId unityDesktop;
1670
 
 
1671
 
   /*
1672
 
    * XXX right now this is going to break if there are multiple screens in the guest,
1673
 
    * since each one can have an independant 'current' desktop...
1674
 
    */
1675
 
 
1676
 
   ASSERT(up);
1677
 
   currentDesktop = UnityX11GetCurrentDesktop(up);
1678
 
 
1679
 
   if (currentDesktop >= up->desktopInfo.numDesktops) {
1680
 
      Warning("Active desktop is out of range for some strange reason\n");
1681
 
      currentDesktop = 0;
1682
 
   }
1683
 
 
1684
 
   unityDesktop = up->desktopInfo.guestDesktopToUnity[currentDesktop];
1685
 
   Debug("%s: currentDesktop %u, unityDesktop %u\n", __func__, currentDesktop, unityDesktop);
1686
 
   UnityWindowTracker_ChangeActiveDesktop(up->tracker, unityDesktop);
1687
 
}
1688
 
 
1689
 
 
1690
 
/*
1691
 
 *-----------------------------------------------------------------------------
1692
 
 *
1693
 
 * USRootWindowsProcessEvent --
1694
 
 *
1695
 
 *      Processes an event that occurred on one of the root windows.
1696
 
 *
1697
 
 * Results:
1698
 
 *      None.
1699
 
 *
1700
 
 * Side effects:
1701
 
 *      None.
1702
 
 *
1703
 
 *-----------------------------------------------------------------------------
1704
 
 */
1705
 
 
1706
 
static void
1707
 
USRootWindowsProcessEvent(UnityPlatform *up,       // IN
1708
 
                          UnitySpecialWindow *usw, // IN
1709
 
                          const XEvent *xevent,    // IN
1710
 
                          Window window)           // IN
1711
 
{
1712
 
 
1713
 
   /*
1714
 
    * XXX Do we need to handle situations where the root window changes size? Any other
1715
 
    * properties?
1716
 
    */
1717
 
   switch (xevent->type) {
1718
 
   case PropertyNotify:
1719
 
      if (xevent->xproperty.atom == up->atoms._NET_CURRENT_DESKTOP) {
1720
 
         USRootWindowsUpdateCurrentDesktop(up, usw, window);
1721
 
      } else if (xevent->xproperty.atom == up->atoms._NET_NUMBER_OF_DESKTOPS) {
1722
 
         size_t numDesktops;
1723
 
 
1724
 
         numDesktops = UnityPlatformGetNumVirtualDesktops(up);
1725
 
         if (numDesktops != up->desktopInfo.numDesktops) {
1726
 
            UnityPlatformSyncDesktopConfig(up);
1727
 
         }
1728
 
      } else if (xevent->xproperty.atom == up->atoms._NET_DESKTOP_LAYOUT) {
1729
 
         Atom layoutData[4];
1730
 
 
1731
 
         UnityPlatformGetVirtualDesktopLayout(up, layoutData);
1732
 
         if (memcmp(layoutData, up->desktopInfo.layoutData, sizeof layoutData) != 0) {
1733
 
            UnityPlatformSyncDesktopConfig(up);
1734
 
         }
1735
 
      }
1736
 
      break;
1737
 
   }
1738
 
}
1739
 
 
1740
 
 
1741
 
/*
1742
 
 *-----------------------------------------------------------------------------
1743
 
 *
1744
 
 * UnityPlatformWMProtocolSupported --
1745
 
 *
1746
 
 *      Returns whether the window manager supports a particular protocol.
1747
 
 *
1748
 
 * Results:
1749
 
 *      TRUE if the protocol is supported, FALSE otherwise.
1750
 
 *
1751
 
 * Side effects:
1752
 
 *      None.
1753
 
 *
1754
 
 *-----------------------------------------------------------------------------
1755
 
 */
1756
 
 
1757
 
Bool
1758
 
UnityPlatformWMProtocolSupported(UnityPlatform *up,         // IN
1759
 
                                 UnityX11WMProtocol proto)  // IN
1760
 
{
1761
 
   ASSERT(up);
1762
 
   ASSERT(proto < UNITY_X11_MAX_WM_PROTOCOLS);
1763
 
 
1764
 
   return up->wmProtocols[proto];
1765
 
}
1766
 
 
1767
 
 
1768
 
/*
1769
 
 *----------------------------------------------------------------------------
1770
 
 *
1771
 
 * UnityPlatformSendClientMessageFull --
1772
 
 *
1773
 
 *      Sends an XSendEvent.
1774
 
 *
1775
 
 * Results:
1776
 
 *
1777
 
 * Side effects:
1778
 
 *
1779
 
 *----------------------------------------------------------------------------
1780
 
 */
1781
 
 
1782
 
 
1783
 
static void
1784
 
UnityPlatformSendClientMessageFull(Display *d,        // IN
1785
 
                                   Window destWindow, // IN: Window to send msg to
1786
 
                                   Window w,          // IN: What the msg's "To:"
1787
 
                                                      // header should be, so to speak.
1788
 
                                   Atom messageType,  // IN
1789
 
                                   int format,        // IN
1790
 
                                   uint numItems,     // IN
1791
 
                                   const void *data)  // IN
1792
 
{
1793
 
   XClientMessageEvent ev;
1794
 
   uint i;
1795
 
 
1796
 
   memset(&ev, 0, sizeof ev);
1797
 
   ev.type = ClientMessage;
1798
 
   ev.window = w;
1799
 
   ev.message_type = messageType;
1800
 
   ev.format = format;
1801
 
   switch (format) {
1802
 
   case 8:
1803
 
      ASSERT(numItems <= ARRAYSIZE(ev.data.b));
1804
 
      for (i = 0; i < numItems; i++) {
1805
 
         const char *datab = (const char*)data;
1806
 
         ev.data.b[i] = datab[i];
1807
 
      }
1808
 
      break;
1809
 
   case 16:
1810
 
      ASSERT(numItems <= ARRAYSIZE(ev.data.s));
1811
 
      for (i = 0; i < numItems; i++) {
1812
 
         const short *datas = (const short*)data;
1813
 
         ev.data.s[i] = datas[i];
1814
 
      }
1815
 
      break;
1816
 
   case 32:
1817
 
      ASSERT(numItems <= ARRAYSIZE(ev.data.l));
1818
 
      for (i = 0; i < numItems; i++) {
1819
 
         const Atom *datal = (const Atom*)data;
1820
 
         ev.data.l[i] = datal[i];
1821
 
      }
1822
 
      break;
1823
 
   }
1824
 
   if (! XSendEvent(d, destWindow, False,
1825
 
                    PropertyChangeMask|SubstructureRedirectMask|SubstructureNotifyMask, (XEvent *)&ev)) {
1826
 
      Debug("XSendEvent failed\n");
1827
 
   }
1828
 
}
1829
 
 
1830
 
/*
1831
 
 *-----------------------------------------------------------------------------
1832
 
 *
1833
 
 * UnityPlatformSendClientMessage --
1834
 
 *
1835
 
 *      Sends an XClientMessageEvent (such as one of the _NET_WM messages)
1836
 
 *
1837
 
 * Results:
1838
 
 *      None.
1839
 
 *
1840
 
 * Side effects:
1841
 
 *      None.
1842
 
 *
1843
 
 *-----------------------------------------------------------------------------
1844
 
 */
1845
 
 
1846
 
void
1847
 
UnityPlatformSendClientMessage(UnityPlatform *up, // IN
1848
 
                               Window destWindow, // IN: Window to actually send msg to
1849
 
                               Window w,          // IN: What the msg's "To:" header
1850
 
                                                  // should be, so to speak.
1851
 
                               Atom messageType,  // IN
1852
 
                               int format,        // IN
1853
 
                               int numItems,      // IN
1854
 
                               const void *data)  // IN
1855
 
{
1856
 
   UnityPlatformSendClientMessageFull(up->display, destWindow, w, messageType,
1857
 
                                      format, numItems, data);
1858
 
}
1859
 
 
1860
 
 
1861
 
/*****************************************************************************
1862
 
 * Misc Unity RPCs that need to be handled                                   *
1863
 
 *****************************************************************************/
1864
 
 
1865
 
 
1866
 
/*
1867
 
 *----------------------------------------------------------------------------
1868
 
 *
1869
 
 * UnityPlatformSetTopWindowGroup --
1870
 
 *
1871
 
 *      Set the group of windows on top of all others.
1872
 
 *
1873
 
 * Results:
1874
 
 *      TRUE if success,
1875
 
 *      FALSE otherwise.
1876
 
 *
1877
 
 * Side effects:
1878
 
 *      None
1879
 
 *
1880
 
 *----------------------------------------------------------------------------
1881
 
 */
1882
 
 
1883
 
Bool
1884
 
UnityPlatformSetTopWindowGroup(UnityPlatform *up,        // IN: Platform data
1885
 
                               UnityWindowId *windows,   // IN: array of window ids
1886
 
                               unsigned int windowCount) // IN: # of windows in the array
1887
 
{
1888
 
   Window sibling = None;
1889
 
   uint i;
1890
 
 
1891
 
   ASSERT(up);
1892
 
   ASSERT(windows);
1893
 
   ASSERT(windowCount);
1894
 
 
1895
 
   /*
1896
 
    * Restack everything bottom to top.
1897
 
    */
1898
 
   for (i = 0; i < windowCount; i++) {
1899
 
      UnityPlatformWindow *upw;
1900
 
      Window curWindow;
1901
 
      Atom data[5] = {0,0,0,0,0};
1902
 
 
1903
 
      upw = UPWindow_Lookup(up, windows[i]);
1904
 
      if (!upw) {
1905
 
         continue;
1906
 
      }
1907
 
 
1908
 
      curWindow = upw->clientWindow ? upw->clientWindow : upw->toplevelWindow;
1909
 
      UPWindow_SetUserTime(up, upw);
1910
 
 
1911
 
      if (UnityPlatformWMProtocolSupported(up, UNITY_X11_WM__NET_RESTACK_WINDOW)) {
1912
 
         data[0] = 2;           // Magic source indicator to give full control
1913
 
         data[1] = sibling;
1914
 
         data[2] = Above;
1915
 
 
1916
 
         UnityPlatformSendClientMessage(up, up->rootWindows->windows[0],
1917
 
                                        curWindow,
1918
 
                                        up->atoms._NET_RESTACK_WINDOW,
1919
 
                                        32, 5, data);
1920
 
      } else {
1921
 
         XWindowChanges winch = {0,};
1922
 
         winch.stack_mode = Above;
1923
 
         winch.sibling = sibling;
1924
 
         unsigned int valueMask = CWStackMode;
1925
 
 
1926
 
         if (sibling != None) {
1927
 
            valueMask |= CWSibling;
1928
 
         }
1929
 
 
1930
 
         /*
1931
 
          * As of writing, Metacity doesn't support _NET_RESTACK_WINDOW and
1932
 
          * will block our attempt to raise a window unless it's active, so
1933
 
          * we activate the window first.
1934
 
          */
1935
 
         if (UnityPlatformWMProtocolSupported(up, UNITY_X11_WM__NET_ACTIVE_WINDOW)) {
1936
 
            data[0] = 2;           // Magic source indicator to give full control
1937
 
            data[1] = UnityPlatformGetServerTime(up);
1938
 
            data[2] = None;
1939
 
            UnityPlatformSendClientMessage(up, up->rootWindows->windows[0],
1940
 
                                           curWindow,
1941
 
                                           up->atoms._NET_ACTIVE_WINDOW,
1942
 
                                           32, 5, data);
1943
 
         }
1944
 
 
1945
 
         XReconfigureWMWindow(up->display, upw->toplevelWindow, 0, valueMask, &winch);
1946
 
      }
1947
 
 
1948
 
      sibling = upw->toplevelWindow;
1949
 
   }
1950
 
 
1951
 
   XSync(up->display, False);
1952
 
 
1953
 
   return TRUE;
1954
 
}
1955
 
 
1956
 
 
1957
 
/*
1958
 
 *-----------------------------------------------------------------------------
1959
 
 *
1960
 
 * UnityPlatformDnDSendClientMessage --
1961
 
 *
1962
 
 *      XXX This is a hack because UnityPlatformSendClientMessage doesn't work
1963
 
 *      for dnd windows.
1964
 
 *      Sends an XClientMessageEvent (such as one of the _NET_WM messages)
1965
 
 *
1966
 
 * Results:
1967
 
 *      None.
1968
 
 *
1969
 
 * Side effects:
1970
 
 *      None.
1971
 
 *
1972
 
 *-----------------------------------------------------------------------------
1973
 
 */
1974
 
 
1975
 
static void
1976
 
UnityPlatformDnDSendClientMessage(UnityPlatform *up, // IN
1977
 
                                  Window destWindow, // IN: Window to send msg to
1978
 
                                  Window w,          // IN: What the msg's "To:"
1979
 
                                                     // header should be, so to speak.
1980
 
                                  Atom messageType,  // IN
1981
 
                                  int format,        // IN
1982
 
                                  int numItems,      // IN
1983
 
                                  const void *data)  // IN
1984
 
{
1985
 
   UnityPlatformSendClientMessageFull(GDK_DISPLAY(), destWindow, w,
1986
 
                                      messageType, format, numItems, data);
1987
 
}
1988
 
 
1989
 
 
1990
 
/*
1991
 
 *----------------------------------------------------------------------------
1992
 
 *
1993
 
 * UnityPlatformStackDnDDetWnd --
1994
 
 *
1995
 
 *      Updates the stacking order of the dnd detection window.
1996
 
 *
1997
 
 * Results:
1998
 
 *      None.
1999
 
 *
2000
 
 * Side effects:
2001
 
 *      None.
2002
 
 *
2003
 
 *----------------------------------------------------------------------------
2004
 
 */
2005
 
 
2006
 
static void
2007
 
UnityPlatformStackDnDDetWnd(UnityPlatform *up)
2008
 
{
2009
 
   static const Atom onDesktop[] = { 0xFFFFFFFF, 0, 0, 0, 0 };
2010
 
 
2011
 
   if (!up->dnd.setMode || !up->dnd.detWnd) {
2012
 
      Debug("%s: DnD not yet initialized.\n", __func__);
2013
 
      return;
2014
 
   }
2015
 
 
2016
 
   if (!up->desktopWindow) {
2017
 
      Debug("Desktop Window not cached. Tracker isn't populated.\n");
2018
 
      return;
2019
 
   }
2020
 
 
2021
 
   /* Show the window on every desktop. */
2022
 
   UnityPlatformDnDSendClientMessage(up,
2023
 
                                     up->rootWindows->windows[0],
2024
 
                                     GDK_WINDOW_XWINDOW(up->dnd.detWnd->window),
2025
 
                                     up->atoms._NET_WM_DESKTOP,
2026
 
                                     32, 5, onDesktop);
2027
 
 
2028
 
   if (up->desktopWindow) {
2029
 
      XWindowChanges ch;
2030
 
      XSetWindowAttributes sa;
2031
 
      Window desktop = up->desktopWindow->toplevelWindow;
2032
 
 
2033
 
      /* Prevent the window manager from managing our detection window. */
2034
 
      sa.override_redirect = True;
2035
 
      XChangeWindowAttributes(GDK_DISPLAY(),
2036
 
                              GDK_WINDOW_XWINDOW(up->dnd.detWnd->window),
2037
 
                              CWOverrideRedirect, &sa);
2038
 
 
2039
 
      /* Resize and restack the detection window. */
2040
 
      ch.x = 0;
2041
 
      ch.y = 0;
2042
 
      ch.width = 65535;
2043
 
      ch.height = 65535;
2044
 
      ch.sibling = desktop;
2045
 
      ch.stack_mode = Above;
2046
 
 
2047
 
      XConfigureWindow(GDK_DISPLAY(), GDK_WINDOW_XWINDOW(up->dnd.detWnd->window),
2048
 
                       CWX|CWY|CWWidth|CWHeight|CWStackMode | CWSibling, &ch);
2049
 
 
2050
 
      Debug("Restacking dnd detection window.\n");
2051
 
   } else {
2052
 
      /*
2053
 
       * Attempt to rely on window manager if we cannot find a window to stack
2054
 
       * above.
2055
 
       */
2056
 
      Atom position[] = { _NET_WM_STATE_ADD,
2057
 
      up->atoms._NET_WM_STATE_STICKY,
2058
 
      up->atoms._NET_WM_STATE_BELOW, 0, 0 };
2059
 
 
2060
 
      Debug("Unable to locate desktop window to restack detection window above.\n");
2061
 
      UnityPlatformDnDSendClientMessage(up,
2062
 
                                        up->rootWindows->windows[0],
2063
 
                                        GDK_WINDOW_XWINDOW(up->dnd.detWnd->window),
2064
 
                                        up->atoms._NET_WM_STATE,
2065
 
                                        32, 5, position);
2066
 
      XMoveResizeWindow(GDK_DISPLAY(),
2067
 
                        GDK_WINDOW_XWINDOW(up->dnd.detWnd->window),
2068
 
                        0, 0, 65535, 65535);
2069
 
   }
2070
 
}
2071
 
 
2072
 
 
2073
 
/*
2074
 
 *------------------------------------------------------------------------------
2075
 
 *
2076
 
 * UnityPlatformUpdateDnDDetWnd --
2077
 
 *
2078
 
 *     Shows/hides a full-screen drag detection wnd for unity guest->host DnD.
2079
 
 *
2080
 
 * Results:
2081
 
 *     None.
2082
 
 *
2083
 
 * Side effects:
2084
 
 *     None.
2085
 
 *
2086
 
 *------------------------------------------------------------------------------
2087
 
 */
2088
 
 
2089
 
void
2090
 
UnityPlatformUpdateDnDDetWnd(UnityPlatform *up, // IN
2091
 
                             Bool show)         // IN
2092
 
{
2093
 
 
2094
 
   if (!up || !up->dnd.setMode || !up->dnd.detWnd) {
2095
 
      /*
2096
 
       * This function may potentially be called during UnityPlatform destruction.
2097
 
       */
2098
 
      return;
2099
 
   }
2100
 
 
2101
 
   if (show) {
2102
 
      gtk_widget_show(up->dnd.detWnd);
2103
 
      UnityPlatformStackDnDDetWnd(up);
2104
 
      Debug("Showing dnd detection window.\n");
2105
 
   } else {
2106
 
      gtk_widget_hide(up->dnd.detWnd);
2107
 
      Debug("Hiding dnd detection window.\n");
2108
 
   }
2109
 
 
2110
 
   up->dnd.setMode(show);
2111
 
}
2112
 
 
2113
 
 
2114
 
/*
2115
 
 *------------------------------------------------------------------------------
2116
 
 *
2117
 
 * UnityPlatformSetActiveDnDDetWnd --
2118
 
 *
2119
 
 *     Set current full-screen drag detection wnd. The caller retains ownership
2120
 
 *     of the data. The caller is responsible for updating the active dnd det
2121
 
 *     wnd.
2122
 
 *
2123
 
 * Results:
2124
 
 *     None.
2125
 
 *
2126
 
 * Side effects:
2127
 
 *     None.
2128
 
 *
2129
 
 *------------------------------------------------------------------------------
2130
 
 */
2131
 
 
2132
 
void
2133
 
UnityPlatformSetActiveDnDDetWnd(UnityPlatform *up, // IN
2134
 
                                UnityDnD *data)      // IN
2135
 
{
2136
 
   up->dnd = *data;
2137
 
}
2138
 
 
2139
 
 
2140
 
/*
2141
 
 *------------------------------------------------------------------------------
2142
 
 *
2143
 
 * UnityPlatformSetDesktopWorkAreas --
2144
 
 *
2145
 
 *     Sets the work areas for all screens.
2146
 
 *
2147
 
 * Results:
2148
 
 *     None.
2149
 
 *
2150
 
 * Side effects:
2151
 
 *     None.
2152
 
 *
2153
 
 *------------------------------------------------------------------------------
2154
 
 */
2155
 
 
2156
 
Bool
2157
 
UnityPlatformSetDesktopWorkAreas(UnityPlatform *up,     // IN
2158
 
                                 UnityRect workAreas[], // IN
2159
 
                                 uint32 numWorkAreas)   // IN
2160
 
{
2161
 
   int iScreens;
2162
 
   uint i;
2163
 
   XineramaScreenInfo *screenInfo = NULL;
2164
 
   int numScreens;
2165
 
   RegionPtr strutsRegion;
2166
 
   RegionPtr screenRegion;
2167
 
   RegionPtr workAreasRegion;
2168
 
   XID (*strutInfos)[12];
2169
 
   uint numStrutInfos;
2170
 
 
2171
 
   if (!up->rootWindows) {
2172
 
      /*
2173
 
       * We're not in Unity mode yet. Save the info until we are.
2174
 
       */
2175
 
 
2176
 
      up->needWorkAreas = (UnityRect*)Util_SafeMalloc(numWorkAreas * sizeof *up->needWorkAreas);
2177
 
      memcpy(up->needWorkAreas, workAreas, numWorkAreas * sizeof *up->needWorkAreas);
2178
 
      up->needNumWorkAreas = numWorkAreas;
2179
 
      return TRUE;
2180
 
   }
2181
 
 
2182
 
   if (!UnityPlatformWMProtocolSupported(up, UNITY_X11_WM__NET_WM_STRUT_PARTIAL)) {
2183
 
      Debug("Window manager does not support _NET_WM_STRUT_PARTIAL - not setting desktop work area.\n");
2184
 
      return FALSE;
2185
 
   }
2186
 
 
2187
 
   ASSERT(up);
2188
 
   ASSERT(up->rootWindows);
2189
 
 
2190
 
   /*
2191
 
    * Get the geometry of all attached screens.  If we're running multi-mon,
2192
 
    * we'll query the Xinerama extension.  Otherwise we just fall back to
2193
 
    * examining our root window's geometry.
2194
 
    */
2195
 
   int q;
2196
 
   if (XineramaQueryExtension(up->display, &q, &q)) {
2197
 
      screenInfo = XineramaQueryScreens(up->display, &numScreens);
2198
 
   }
2199
 
 
2200
 
   if (!screenInfo) {
2201
 
      int32 rootX;
2202
 
      int32 rootY;
2203
 
      uint rootWidth;
2204
 
      uint rootHeight;
2205
 
      uint dummy;
2206
 
      Window winDummy;
2207
 
 
2208
 
      if (numWorkAreas > 1) {
2209
 
         Debug("Xinerama extension not present, or XineramaQueryScreens failed,"
2210
 
               " but multiple work areas were requested.\n");
2211
 
         return FALSE;
2212
 
      }
2213
 
 
2214
 
      if (!XGetGeometry(up->display, up->rootWindows->windows[0], &winDummy,
2215
 
                        &rootX, &rootY, &rootWidth, &rootHeight,
2216
 
                        &dummy, &dummy)) {
2217
 
         return FALSE;
2218
 
      }
2219
 
 
2220
 
      screenInfo = (XineramaScreenInfo*)Util_SafeCalloc(1, sizeof *screenInfo);
2221
 
      numScreens = 1;
2222
 
 
2223
 
      screenInfo->x_org = rootX;
2224
 
      screenInfo->y_org = rootY;
2225
 
      screenInfo->width = rootWidth;
2226
 
      screenInfo->height = rootHeight;
2227
 
   }
2228
 
 
2229
 
   if ((uint32)numScreens != numWorkAreas) {
2230
 
      Warning("Mismatch between host-specified work areas and available "
2231
 
              "screens.  Request dropped.\n");
2232
 
      free(screenInfo);
2233
 
      return FALSE;
2234
 
   }
2235
 
 
2236
 
   /*
2237
 
    * New and improved wild'n'crazy scheme to map the host's work area
2238
 
    * coordinates to a collection of struts.
2239
 
    *
2240
 
    * This implementation depends upon the y-x banded rectangles
2241
 
    * implementation of lib/region.
2242
 
    *
2243
 
    * In short, here's how things go:
2244
 
    *
2245
 
    *    1.  For each Xinerama screen (or the root window in case we have no
2246
 
    *        Xinerama) and host work area, a region is created.  A strut
2247
 
    *        region is then created by subtracting the work area region from
2248
 
    *        the screen region.
2249
 
    *
2250
 
    *    2.  This remaining region will contain between 0 and 4 rectangles,
2251
 
    *        each of which will be transformed into a strut window.
2252
 
    *
2253
 
    *        For each of these rectangles, we infer based on their dimensions
2254
 
    *        which screen boundary the resulting strut should be bound to.
2255
 
    *
2256
 
    *        a.  Boxes touching both the left and right sides of the screen
2257
 
    *            are either top or bottom struts, depending on whether they
2258
 
    *            also touch the top or bottom edge.
2259
 
    *
2260
 
    *        b.  Any remaining box will touch either the left OR the right
2261
 
    *            side, but not both.  (Such an irregular layout cannot be
2262
 
    *            described by the work areas RPC.)  That box's strut will
2263
 
    *            then be attached to the same side of the screen.
2264
 
    *
2265
 
    * While also not perfect, this algorithm should do a better job of creating
2266
 
    * struts along their correct sides of a screen than its predecessor.  It
2267
 
    * will let us assume the common case that what we define as a strut attached
2268
 
    * to the left or right side really should be attached to the left or right,
2269
 
    * rather than attached to the top or bottom and spanning the height of the
2270
 
    * display.
2271
 
    *
2272
 
    * Pathological case:
2273
 
    *    1.  Screen geometry: 1280x960.
2274
 
    *        Left strut: 100px wide, 600px tall.  Touches top of screen.
2275
 
    *        Right strut: 1180px wide, 100px tall.  Touches top of screen.
2276
 
    *
2277
 
    *    2.  Note that these struts touch each other.  We'd interpret the resulting
2278
 
    *        work area as follows:
2279
 
    *
2280
 
    *        Top strut: 1280px wide, 100px tall.
2281
 
    *        Left strut: 100px wide, 500px tall, starting from y = 100.
2282
 
    *
2283
 
    * I believe this sort of layout to be uncommon enough that we can accept
2284
 
    * failure here.  If we -really- want to get these things right, then
2285
 
    * we should send strut information explicitly, rather than having the
2286
 
    * guest try to deduce it from work area geometry.
2287
 
    */
2288
 
 
2289
 
   /*
2290
 
    * One strut per screen edge = at most 4 strutInfos.
2291
 
    */
2292
 
   strutInfos = (XID(*)[12])alloca(4 * sizeof *strutInfos * numScreens);
2293
 
   memset(strutInfos, 0, 4 * sizeof *strutInfos * numScreens);
2294
 
   numStrutInfos = 0;
2295
 
 
2296
 
   for (iScreens = 0; iScreens < numScreens; iScreens++) {
2297
 
      int iRects;
2298
 
 
2299
 
      xRectangle screenRect;
2300
 
      xRectangle workAreaRect;
2301
 
 
2302
 
      /*
2303
 
       * Steps 1a. Create screen, work area regions.
2304
 
       */
2305
 
      screenRect.x = screenInfo[iScreens].x_org;
2306
 
      screenRect.y = screenInfo[iScreens].y_org;
2307
 
      screenRect.width = screenInfo[iScreens].width;
2308
 
      screenRect.height = screenInfo[iScreens].height;
2309
 
      screenRect.info.type = UpdateRect;
2310
 
 
2311
 
      workAreaRect.x = workAreas[iScreens].x;
2312
 
      workAreaRect.y = workAreas[iScreens].y;
2313
 
      workAreaRect.width = workAreas[iScreens].width;
2314
 
      workAreaRect.height = workAreas[iScreens].height;
2315
 
      workAreaRect.info.type = UpdateRect;
2316
 
 
2317
 
      screenRegion = miRectsToRegion(1, &screenRect, 0);
2318
 
      workAreasRegion = miRectsToRegion(1, &workAreaRect, 0);
2319
 
 
2320
 
      /*
2321
 
       * Step 1b.  Create struts region by subtracting work area from screen.
2322
 
       */
2323
 
      strutsRegion = miRegionCreate(NULL, 0);
2324
 
      miSubtract(strutsRegion, screenRegion, workAreasRegion);
2325
 
      miRegionDestroy(workAreasRegion);
2326
 
      miRegionDestroy(screenRegion);
2327
 
 
2328
 
      /*
2329
 
       * Step 2.  Transform struts region rectangles into individual struts.
2330
 
       */
2331
 
      for (iRects = 0; iRects < REGION_NUM_RECTS(strutsRegion);
2332
 
           iRects++, numStrutInfos++) {
2333
 
         BoxPtr p = REGION_RECTS(strutsRegion) + iRects;
2334
 
         int bounds = 0;
2335
 
#define TOUCHES_LEFT          0x1
2336
 
#define TOUCHES_RIGHT         0x2
2337
 
#define TOUCHES_TOP           0x4
2338
 
#define TOUCHES_BOTTOM        0x8
2339
 
 
2340
 
         if (p->x1 == screenRect.x) { bounds |= TOUCHES_LEFT; }
2341
 
         if (p->x2 == screenRect.x + screenRect.width) { bounds |= TOUCHES_RIGHT; }
2342
 
         if (p->y1 == screenRect.y) { bounds |= TOUCHES_TOP; }
2343
 
         if (p->y2 == screenRect.y + screenRect.height) { bounds |= TOUCHES_BOTTOM; }
2344
 
 
2345
 
         /*
2346
 
          * strutInfos is passed directly to
2347
 
          * XSetProperty(..._NET_WM_STRUTS_PARTIAL).  I.e., look up that
2348
 
          * property's entry in NetWM/wm-spec for more info on the indices.
2349
 
          *
2350
 
          * I went the switch/case route only because it does a better job
2351
 
          * (for me) of organizing & showing -all- possible cases.  YMMV.
2352
 
          *
2353
 
          * The region code treats rectanges as ranges from [x1,x2) and
2354
 
          * [y1,y2).  In other words, x2 and y2 are OUTSIDE the region.  I
2355
 
          * guess it makes calculating widths/heights easier.  However, the
2356
 
          * strut width/height dimensions are INCLUSIVE, so we'll subtract 1
2357
 
          * from the "end" (as opposed to "start") value.
2358
 
          *
2359
 
          * (Ex:  A 1600x1200 display with a 25px top strut would be marked
2360
 
          * as top = 25, top_start_x = 0, top_end_x = 1599.)
2361
 
          */
2362
 
         switch (bounds) {
2363
 
         case TOUCHES_LEFT | TOUCHES_RIGHT | TOUCHES_TOP:
2364
 
            /* Top strut. */
2365
 
            strutInfos[numStrutInfos][2] = p->y2 - p->y1;
2366
 
            strutInfos[numStrutInfos][8] = p->x1;
2367
 
            strutInfos[numStrutInfos][9] = p->x2 - 1;
2368
 
            break;
2369
 
         case TOUCHES_LEFT | TOUCHES_RIGHT | TOUCHES_BOTTOM:
2370
 
            /* Bottom strut. */
2371
 
            strutInfos[numStrutInfos][3] = p->y2 - p->y1;
2372
 
            strutInfos[numStrutInfos][10] = p->x1;
2373
 
            strutInfos[numStrutInfos][11] = p->x2 - 1;
2374
 
            break;
2375
 
         case TOUCHES_LEFT:
2376
 
         case TOUCHES_LEFT | TOUCHES_TOP:
2377
 
         case TOUCHES_LEFT | TOUCHES_BOTTOM:
2378
 
         case TOUCHES_LEFT | TOUCHES_TOP | TOUCHES_BOTTOM:
2379
 
            /* Left strut. */
2380
 
            strutInfos[numStrutInfos][0] = p->x2 - p->x1;
2381
 
            strutInfos[numStrutInfos][4] = p->y1;
2382
 
            strutInfos[numStrutInfos][5] = p->y2 - 1;
2383
 
            break;
2384
 
         case TOUCHES_RIGHT:
2385
 
         case TOUCHES_RIGHT | TOUCHES_TOP:
2386
 
         case TOUCHES_RIGHT | TOUCHES_BOTTOM:
2387
 
         case TOUCHES_RIGHT | TOUCHES_TOP | TOUCHES_BOTTOM:
2388
 
            /* Right strut. */
2389
 
            strutInfos[numStrutInfos][1] = p->x2 - p->x1;
2390
 
            strutInfos[numStrutInfos][6] = p->y1;
2391
 
            strutInfos[numStrutInfos][7] = p->y2 - 1;
2392
 
            break;
2393
 
         case TOUCHES_LEFT | TOUCHES_RIGHT | TOUCHES_TOP | TOUCHES_BOTTOM:
2394
 
            Warning("%s: Struts occupy entire display.", __func__);
2395
 
            /* FALLTHROUGH */
2396
 
         default:
2397
 
            Warning("%s: Irregular strut configuration: bounds %4x\n", __func__, bounds);
2398
 
            miRegionDestroy(strutsRegion);
2399
 
            goto out;
2400
 
            break;
2401
 
         }
2402
 
      }
2403
 
#undef TOUCHES_LEFT
2404
 
#undef TOUCHES_RIGHT
2405
 
#undef TOUCHES_TOP
2406
 
#undef TOUCHES_BOTTOM
2407
 
 
2408
 
      miRegionDestroy(strutsRegion);
2409
 
   }
2410
 
 
2411
 
   /*
2412
 
    * The first step is making sure we have enough windows in existence to list the
2413
 
    * _NET_WM_STRUT_PARTIAL properties for each screen.
2414
 
    */
2415
 
   if (!up->workAreas
2416
 
       || up->workAreas->numWindows != numStrutInfos) {
2417
 
      Window *newWinList;
2418
 
 
2419
 
      newWinList = (Window*)Util_SafeCalloc(numStrutInfos, sizeof *newWinList);
2420
 
      if (up->workAreas) {
2421
 
         memcpy(newWinList, up->workAreas->windows,
2422
 
                MIN(numStrutInfos, up->workAreas->numWindows) * sizeof *newWinList);
2423
 
      }
2424
 
 
2425
 
      /*
2426
 
       * Destroy unneeded windows
2427
 
       */
2428
 
      for (i = numStrutInfos; i < (up->workAreas ? up->workAreas->numWindows : 0); i++) {
2429
 
         XDestroyWindow(up->display, up->workAreas->windows[i]);
2430
 
      }
2431
 
 
2432
 
      /*
2433
 
       * Create additional windows as needed.
2434
 
       */
2435
 
      for (i = up->workAreas ? up->workAreas->numWindows : 0; i < numStrutInfos; i++) {
2436
 
         static const char strutWindowName[] = "vmware-user workarea struts";
2437
 
         Atom allDesktops = -1;
2438
 
         newWinList[i] = XCreateWindow(up->display, up->rootWindows->windows[0],
2439
 
                                       -50, -50, 1, 1, 0, CopyFromParent, InputOnly,
2440
 
                                       CopyFromParent, 0, NULL);
2441
 
         XChangeProperty(up->display, newWinList[i], up->atoms._NET_WM_WINDOW_TYPE,
2442
 
                         XA_ATOM, 32, PropModeReplace,
2443
 
                         (unsigned char *)&up->atoms._NET_WM_WINDOW_TYPE_DOCK, 1);
2444
 
         XChangeProperty(up->display, newWinList[i], up->atoms._NET_WM_DESKTOP,
2445
 
                         XA_CARDINAL, 32, PropModeReplace,
2446
 
                         (unsigned char *)&allDesktops, 1);
2447
 
         XStoreName(up->display, newWinList[i], strutWindowName);
2448
 
         XMapWindow(up->display, newWinList[i]);
2449
 
      }
2450
 
 
2451
 
      if (up->workAreas) {
2452
 
         USWindowUpdate(up, up->workAreas, newWinList, numStrutInfos);
2453
 
      } else {
2454
 
         up->workAreas = USWindowCreate(up, NULL, newWinList, numStrutInfos);
2455
 
         up->workAreas->windowsAreOwned = TRUE;
2456
 
      }
2457
 
   }
2458
 
 
2459
 
   /*
2460
 
    * Now actually set the _NET_WM_STRUT_PARTIAL property on our special 'struts'
2461
 
    * windows.
2462
 
    */
2463
 
   for (i = 0; i < numStrutInfos; i++) {
2464
 
      Window strutWindow;
2465
 
 
2466
 
      strutWindow = up->workAreas->windows[i];
2467
 
 
2468
 
      XChangeProperty(up->display, strutWindow, up->atoms._NET_WM_STRUT_PARTIAL, XA_CARDINAL,
2469
 
                      32, PropModeReplace, (unsigned char *)strutInfos[i], ARRAYSIZE(strutInfos[i]));
2470
 
   }
2471
 
 
2472
 
out:
2473
 
   free(screenInfo);
2474
 
 
2475
 
   return TRUE;
2476
 
}
2477
 
 
2478
 
 
2479
 
/*
2480
 
 *-----------------------------------------------------------------------------
2481
 
 *
2482
 
 * UnityPlatformGetNumVirtualDesktops --
2483
 
 *
2484
 
 *      Retrieves the number of virtual desktops currently set in the guest.
2485
 
 *
2486
 
 * Results:
2487
 
 *      Number of desktops.
2488
 
 *
2489
 
 * Side effects:
2490
 
 *      None
2491
 
 *
2492
 
 *-----------------------------------------------------------------------------
2493
 
 */
2494
 
 
2495
 
size_t
2496
 
UnityPlatformGetNumVirtualDesktops(UnityPlatform *up) // IN
2497
 
{
2498
 
   Atom propertyType;
2499
 
   int propertyFormat;
2500
 
   unsigned long itemsReturned;
2501
 
   unsigned long bytesRemaining;
2502
 
   Atom *valueReturned;
2503
 
   size_t retval;
2504
 
 
2505
 
   ASSERT(up);
2506
 
   if (XGetWindowProperty(up->display, up->rootWindows->windows[0],
2507
 
                          up->atoms._NET_NUMBER_OF_DESKTOPS, 0,
2508
 
                          1024, False, AnyPropertyType,
2509
 
                          &propertyType, &propertyFormat, &itemsReturned,
2510
 
                          &bytesRemaining, (unsigned char **)&valueReturned)
2511
 
       == Success
2512
 
       && propertyType == XA_CARDINAL
2513
 
       && propertyFormat == 32) {
2514
 
      ASSERT(itemsReturned == 1);
2515
 
 
2516
 
      retval = valueReturned[0];
2517
 
   } else {
2518
 
      retval = 1;
2519
 
   }
2520
 
   XFree(valueReturned);
2521
 
 
2522
 
   return retval;
2523
 
}
2524
 
 
2525
 
 
2526
 
/*
2527
 
 *-----------------------------------------------------------------------------
2528
 
 *
2529
 
 * UnityPlatformGetVirtualDesktopLayout --
2530
 
 *
2531
 
 *      Retrieves the guest's current virtual desktop layout info, and stores it in
2532
 
 *      'layoutData' (an array of 4 Atoms).
2533
 
 *
2534
 
 * Results:
2535
 
 *      Desktop layout stored in 'layoutData'
2536
 
 *
2537
 
 * Side effects:
2538
 
 *      None.
2539
 
 *
2540
 
 *-----------------------------------------------------------------------------
2541
 
 */
2542
 
 
2543
 
void
2544
 
UnityPlatformGetVirtualDesktopLayout(UnityPlatform *up, // IN
2545
 
                                     Atom *layoutData)  // OUT
2546
 
{
2547
 
   Atom propertyType;
2548
 
   int propertyFormat;
2549
 
   unsigned long itemsReturned;
2550
 
   unsigned long bytesRemaining;
2551
 
   Atom *valueReturned;
2552
 
 
2553
 
   ASSERT(up);
2554
 
 
2555
 
   layoutData[3] = _NET_WM_TOPLEFT;
2556
 
   if (XGetWindowProperty(up->display, up->rootWindows->windows[0],
2557
 
                          up->atoms._NET_DESKTOP_LAYOUT, 0,
2558
 
                          1024, False, AnyPropertyType,
2559
 
                          &propertyType, &propertyFormat, &itemsReturned,
2560
 
                          &bytesRemaining, (unsigned char **)&valueReturned)
2561
 
       == Success
2562
 
       && propertyType == XA_CARDINAL
2563
 
       && propertyFormat == 32) {
2564
 
      ASSERT(itemsReturned == 3 || itemsReturned == 4);
2565
 
 
2566
 
      memcpy(layoutData,
2567
 
             valueReturned,
2568
 
             itemsReturned * sizeof *valueReturned);
2569
 
   } else {
2570
 
      layoutData[0] = _NET_WM_ORIENTATION_HORZ;
2571
 
      layoutData[1] = 0;
2572
 
      layoutData[2] = 1;
2573
 
   }
2574
 
   XFree(valueReturned);
2575
 
}
2576
 
 
2577
 
 
2578
 
/*
2579
 
 *-----------------------------------------------------------------------------
2580
 
 *
2581
 
 * UnityPlatformSyncDesktopConfig --
2582
 
 *
2583
 
 *      This routine takes the virtual desktop configuration stored in UnityPlatform and
2584
 
 *      makes sure that the guest's actual virtual desktop configuration matches. This is
2585
 
 *      done in three situations:
2586
 
 *        1. Updating the guest's virtual desktop config to match the host's, right after
2587
 
 *        the host's virtual desktop config has changed.
2588
 
 *        2. Forcing the guest's virtual desktop config back to the host's, right after
2589
 
 *        the user uses the guest's pager to alter the guest virtual desktop config.
2590
 
 *        3. Restoring the guest's virtual desktop configuration when exiting Unity mode.
2591
 
 *
2592
 
 * Results:
2593
 
 *      None.
2594
 
 *
2595
 
 * Side effects:
2596
 
 *      Guest windows may jump to different virtual desktops if desktops are removed.
2597
 
 *
2598
 
 *-----------------------------------------------------------------------------
2599
 
 */
2600
 
 
2601
 
void
2602
 
UnityPlatformSyncDesktopConfig(UnityPlatform *up) // IN
2603
 
{
2604
 
   Atom data[5] = {0, 0, 0, 0, 0};
2605
 
 
2606
 
   ASSERT(up);
2607
 
 
2608
 
   if (!up->rootWindows || !up->display) {
2609
 
      return; // This function might be called while not in Unity mode
2610
 
   }
2611
 
 
2612
 
   data[0] = up->desktopInfo.numDesktops;
2613
 
   UnityPlatformSendClientMessage(up,
2614
 
                                  up->rootWindows->windows[0],
2615
 
                                  up->rootWindows->windows[0],
2616
 
                                  up->atoms._NET_NUMBER_OF_DESKTOPS,
2617
 
                                  32, 5,
2618
 
                                  data);
2619
 
   XChangeProperty(up->display, up->rootWindows->windows[0],
2620
 
                   up->atoms._NET_DESKTOP_LAYOUT, XA_CARDINAL,
2621
 
                   32, PropModeReplace, (unsigned char *)up->desktopInfo.layoutData, 4);
2622
 
}
2623
 
 
2624
 
 
2625
 
/*
2626
 
 *------------------------------------------------------------------------------
2627
 
 *
2628
 
 * UnityPlatformSetDesktopConfig --
2629
 
 *
2630
 
 *     Set the virtual desktop configuration as specified by the host.
2631
 
 *
2632
 
 * Results:
2633
 
 *     Returns TRUE if successful, and FALSE otherwise.
2634
 
 *
2635
 
 * Side effects:
2636
 
 *     None.
2637
 
 *
2638
 
 *------------------------------------------------------------------------------
2639
 
 */
2640
 
 
2641
 
Bool
2642
 
UnityPlatformSetDesktopConfig(UnityPlatform *up,                             // IN
2643
 
                              const UnityVirtualDesktopArray *desktopConfig) // IN
2644
 
{
2645
 
   uint i;
2646
 
   int x;
2647
 
   int y;
2648
 
   UnityVirtualDesktop minDesktop;
2649
 
   UnityVirtualDesktop maxDesktop;
2650
 
   UnityVirtualDesktop desktopSpread;
2651
 
   int unityDesktopLayout[MAX_VIRT_DESK][MAX_VIRT_DESK];
2652
 
   int guestDesktopLayout[MAX_VIRT_DESK][MAX_VIRT_DESK];
2653
 
 
2654
 
   ASSERT(up);
2655
 
   ASSERT(desktopConfig);
2656
 
   ASSERT(desktopConfig->desktopCount >= 1);
2657
 
 
2658
 
   /*
2659
 
    * This long section of code mainly exists to verify that the host's virtual desktop
2660
 
    * setup can be represented on our end, and to figure out how best to do it. We could
2661
 
    * do this simply, if we didn't have to deal with the possibility of having 5 virtual
2662
 
    * desktops in a 3x2 layout, which is a very real possibility on Linux hosts...
2663
 
    */
2664
 
   memset(unityDesktopLayout, 0xFF, sizeof unityDesktopLayout); // Set all entries to -1
2665
 
   minDesktop = desktopConfig->desktops[0];
2666
 
   maxDesktop = minDesktop;
2667
 
   for (i = 1; i < desktopConfig->desktopCount; i++) {
2668
 
      if (desktopConfig->desktops[i].x < minDesktop.x) {
2669
 
         minDesktop.x = desktopConfig->desktops[i].x;
2670
 
      }
2671
 
      if (desktopConfig->desktops[i].y < minDesktop.y) {
2672
 
         minDesktop.y = desktopConfig->desktops[i].y;
2673
 
      }
2674
 
      if (desktopConfig->desktops[i].x > maxDesktop.x) {
2675
 
         maxDesktop.x = desktopConfig->desktops[i].x;
2676
 
      }
2677
 
      if (desktopConfig->desktops[i].y > maxDesktop.y) {
2678
 
         maxDesktop.y = desktopConfig->desktops[i].y;
2679
 
      }
2680
 
   }
2681
 
   desktopSpread.x = maxDesktop.x - minDesktop.x;
2682
 
   desktopSpread.y = maxDesktop.y - minDesktop.y;
2683
 
 
2684
 
   for (i = 0; i < desktopConfig->desktopCount; i++) {
2685
 
      int32 localX = desktopConfig->desktops[i].x - minDesktop.x;
2686
 
      int32 localY = desktopConfig->desktops[i].y - minDesktop.y;
2687
 
 
2688
 
      if (localY >= MAX_VIRT_DESK || localX >= MAX_VIRT_DESK) {
2689
 
         Warning("Unity virtual desktop layout has holes that are too big to handle\n");
2690
 
         return FALSE;
2691
 
      }
2692
 
 
2693
 
      unityDesktopLayout[localX][localY] = i;
2694
 
   }
2695
 
 
2696
 
   for (x = 0; x < desktopSpread.x; x++) {
2697
 
      for (y = 0; y < desktopSpread.y; y++) {
2698
 
         if (unityDesktopLayout[x][y] < 0) {
2699
 
            Warning("Unity virtual desktop layout has holes that we can't handle.\n");
2700
 
            return FALSE;
2701
 
         }
2702
 
      }
2703
 
   }
2704
 
 
2705
 
   /*
2706
 
    * Check along the left edge to make sure that there aren't any gaps between virtual
2707
 
    * desktops.
2708
 
    */
2709
 
   for (x = desktopSpread.x, y = 0; y <= desktopSpread.y; y++) {
2710
 
      if (unityDesktopLayout[x][y] < 0) {
2711
 
         break;
2712
 
      }
2713
 
   }
2714
 
   for (; y <= desktopSpread.y; y++) {
2715
 
      if (unityDesktopLayout[x][y] >= 0) {
2716
 
         Warning("Unity virtual desktop layout has holes along the right edge.\n");
2717
 
         return FALSE;
2718
 
      }
2719
 
   }
2720
 
 
2721
 
   /*
2722
 
    * Check along the bottom edge to make sure that there aren't any gaps between virtual
2723
 
    * desktops.
2724
 
    */
2725
 
   for (y = desktopSpread.y, x = 0; x <= desktopSpread.x; x++) {
2726
 
      if (unityDesktopLayout[x][y] < 0) {
2727
 
         break;
2728
 
      }
2729
 
   }
2730
 
   for (; x <= desktopSpread.x; x++) {
2731
 
      if (unityDesktopLayout[x][y] >= 0) {
2732
 
         Warning("Unity virtual desktop layout has holes along the bottom edge.\n");
2733
 
         return FALSE;
2734
 
      }
2735
 
   }
2736
 
 
2737
 
   /*
2738
 
    * Now we know we have a workable virtual desktop layout - let's figure out how to
2739
 
    * communicate it to the window manager & pager.
2740
 
    */
2741
 
   up->desktopInfo.layoutData[0] = _NET_WM_ORIENTATION_HORZ; // Orientation
2742
 
   up->desktopInfo.layoutData[1] = (desktopSpread.x + 1); // # of columns
2743
 
   up->desktopInfo.layoutData[2] = (desktopSpread.y + 1); // # of rows
2744
 
   up->desktopInfo.layoutData[3] = _NET_WM_TOPLEFT; // Starting corner
2745
 
 
2746
 
   if (((desktopSpread.x + 1) * (desktopSpread.y + 1)) >= (int)desktopConfig->desktopCount
2747
 
       && desktopSpread.x > 0
2748
 
       && desktopSpread.y > 1
2749
 
       && unityDesktopLayout[desktopSpread.x][desktopSpread.y - 1] < 0) {
2750
 
      /*
2751
 
       * We know there is are least two holes at the end of the layout, /and/ the holes
2752
 
       * go up the right side, so therefore we need to use vertical orientation for the
2753
 
       * EWMH layout.
2754
 
       */
2755
 
      up->desktopInfo.layoutData[0] = _NET_WM_ORIENTATION_VERT;
2756
 
   }
2757
 
 
2758
 
   /*
2759
 
    * Figure out what the guest-side desktop IDs will be, based on our chosen
2760
 
    * orientation.
2761
 
    */
2762
 
   i = 0;
2763
 
   memset(guestDesktopLayout, 0xFF, sizeof guestDesktopLayout); // Set all entries to -1
2764
 
   if (up->desktopInfo.layoutData[0] == _NET_WM_ORIENTATION_HORZ) {
2765
 
      for (y = 0; y <= desktopSpread.y; y++) {
2766
 
         for (x = 0; x <= desktopSpread.x; x++) {
2767
 
            if (unityDesktopLayout[x][y] >= 0) {
2768
 
               guestDesktopLayout[x][y] = i++;
2769
 
            }
2770
 
         }
2771
 
      }
2772
 
   } else {
2773
 
      for (x = 0; x <= desktopSpread.x; x++) {
2774
 
         for (y = 0; y <= desktopSpread.y; y++) {
2775
 
            if (unityDesktopLayout[x][y] >= 0) {
2776
 
               guestDesktopLayout[x][y] = i++;
2777
 
            }
2778
 
         }
2779
 
      }
2780
 
   }
2781
 
 
2782
 
   up->desktopInfo.numDesktops = desktopConfig->desktopCount;
2783
 
 
2784
 
   /*
2785
 
    * Build tables to translate between guest-side and Unity-side desktop IDs.
2786
 
    */
2787
 
   up->desktopInfo.guestDesktopToUnity = (UnityDesktopId*)
2788
 
      Util_SafeRealloc(up->desktopInfo.guestDesktopToUnity,
2789
 
                       up->desktopInfo.numDesktops
2790
 
                       * sizeof up->desktopInfo.guestDesktopToUnity[0]);
2791
 
   up->desktopInfo.unityDesktopToGuest = (uint32*)
2792
 
      Util_SafeRealloc(up->desktopInfo.unityDesktopToGuest,
2793
 
                       up->desktopInfo.numDesktops
2794
 
                       * sizeof up->desktopInfo.unityDesktopToGuest[0]);
2795
 
   for (i = 0; i < up->desktopInfo.numDesktops; i++) {
2796
 
      int guestNum;
2797
 
      UnityVirtualDesktop curDesk = desktopConfig->desktops[i];
2798
 
 
2799
 
      guestNum = guestDesktopLayout[curDesk.x - minDesktop.x][curDesk.y - minDesktop.y];
2800
 
      up->desktopInfo.guestDesktopToUnity[guestNum] = i;
2801
 
      up->desktopInfo.unityDesktopToGuest[i] = guestNum;
2802
 
   }
2803
 
 
2804
 
   /*
2805
 
    * Make the configuration actually take effect.
2806
 
    */
2807
 
   UnityPlatformSyncDesktopConfig(up);
2808
 
 
2809
 
   return TRUE;
2810
 
}
2811
 
 
2812
 
 
2813
 
/*
2814
 
 *------------------------------------------------------------------------------
2815
 
 *
2816
 
 * UnityPlatformSetInitialDesktop --
2817
 
 *
2818
 
 *     Set a desktop specified by the desktop id as the initial state.
2819
 
 *
2820
 
 * Results:
2821
 
 *     Returns TRUE if successful, and FALSE otherwise.
2822
 
 *
2823
 
 * Side effects:
2824
 
 *     Some windows might be hidden and some shown.
2825
 
 *
2826
 
 *------------------------------------------------------------------------------
2827
 
 */
2828
 
 
2829
 
Bool
2830
 
UnityPlatformSetInitialDesktop(UnityPlatform *up,         // IN
2831
 
                               UnityDesktopId desktopId)  // IN
2832
 
{
2833
 
   ASSERT(up);
2834
 
   up->desktopInfo.initialDesktop = desktopId;
2835
 
   return UnityPlatformSetDesktopActive(up, desktopId);
2836
 
}
2837
 
 
2838
 
 
2839
 
/*
2840
 
 *------------------------------------------------------------------------------
2841
 
 *
2842
 
 * UnityPlatformSetDesktopActive --
2843
 
 *
2844
 
 *     Switch to the specified virtual desktop. The desktopId is an index
2845
 
 *     into the desktop configuration array.
2846
 
 *
2847
 
 * Results:
2848
 
 *     Returns TRUE if successful, and FALSE otherwise.
2849
 
 *
2850
 
 * Side effects:
2851
 
 *     None.
2852
 
 *
2853
 
 *------------------------------------------------------------------------------
2854
 
 */
2855
 
 
2856
 
Bool
2857
 
UnityPlatformSetDesktopActive(UnityPlatform *up,         // IN
2858
 
                              UnityDesktopId desktopId)  // IN
2859
 
{
2860
 
   ASSERT(up);
2861
 
 
2862
 
   /*
2863
 
    * Update the uwt with the new active desktop info.
2864
 
    */
2865
 
 
2866
 
   UnityWindowTracker_ChangeActiveDesktop(up->tracker, desktopId);
2867
 
 
2868
 
   if (desktopId >= (UnityDesktopId)up->desktopInfo.numDesktops) {
2869
 
      return FALSE;
2870
 
   }
2871
 
 
2872
 
   if (!up->rootWindows) {
2873
 
      /*
2874
 
       * We may not be into Unity mode yet, but we pretend it succeeded, and then do the
2875
 
       * switch later for real.
2876
 
       */
2877
 
      return TRUE;
2878
 
   }
2879
 
 
2880
 
   UnityX11SetCurrentDesktop(up, up->desktopInfo.unityDesktopToGuest[desktopId]);
2881
 
 
2882
 
   return TRUE;
2883
 
}
2884
 
 
2885
 
 
2886
 
/*
2887
 
 *-----------------------------------------------------------------------------
2888
 
 *
2889
 
 * UnityPlatformDoUpdate --
2890
 
 *
2891
 
 *      This function is used to (possibly asynchronously) collect Unity window
2892
 
 *      updates and send them to the host via the RPCI update channel.
2893
 
 *
2894
 
 * Results:
2895
 
 *      Updates will be collected.  Updates may be sent.
2896
 
 *
2897
 
 * Side effects:
2898
 
 *      None.
2899
 
 *
2900
 
 *-----------------------------------------------------------------------------
2901
 
 */
2902
 
 
2903
 
void
2904
 
UnityPlatformDoUpdate(UnityPlatform *up,        // IN:
2905
 
                      Bool incremental)         // IN: Incremental vs. full update
2906
 
{
2907
 
   int flags = 0;
2908
 
 
2909
 
   ASSERT(up);
2910
 
 
2911
 
   if (incremental) {
2912
 
      flags |= UNITY_UPDATE_INCREMENTAL;
2913
 
   } else {
2914
 
      /*
2915
 
       * Only update the window state for full updates. Incremental updates can be
2916
 
       * satisfied by the current state in the tracker.
2917
 
       */
2918
 
      UnityPlatformUpdateWindowState(up, up->tracker);
2919
 
   }
2920
 
 
2921
 
   up->hostCallbacks.buildUpdateCB(up->hostCallbacks.updateCbCtx, flags);
2922
 
}
2923
 
 
2924
 
 
2925
 
/*
2926
 
 *----------------------------------------------------------------------------
2927
 
 *
2928
 
 * Unity_UnityToLocalPoint --
2929
 
 *
2930
 
 *      Initializes localPt structure based on the input unityPt structure.
2931
 
 *      Translate point from Unity coordinate to local coordinate.
2932
 
 *
2933
 
 * Results:
2934
 
 *      None
2935
 
 *
2936
 
 * Side effects:
2937
 
 *      None
2938
 
 *----------------------------------------------------------------------------
2939
 
 */
2940
 
 
2941
 
void
2942
 
Unity_UnityToLocalPoint(UnityPoint *localPt, // IN/OUT
2943
 
                        UnityPoint *unityPt) // IN
2944
 
{
2945
 
   ASSERT(localPt);
2946
 
   ASSERT(unityPt);
2947
 
   localPt->x = unityPt->x;
2948
 
   localPt->y = unityPt->y;
2949
 
}
2950
 
 
2951
 
 
2952
 
/*
2953
 
 *----------------------------------------------------------------------------
2954
 
 *
2955
 
 * Unity_LocalToUnityPoint --
2956
 
 *
2957
 
 *      Initializes unityPt structure based on the input localPt structure.
2958
 
 *      Translate point from local coordinate to Unity coordinate.
2959
 
 *
2960
 
 * Results:
2961
 
 *      None
2962
 
 *
2963
 
 * Side effects:
2964
 
 *      None
2965
 
 *----------------------------------------------------------------------------
2966
 
 */
2967
 
 
2968
 
void
2969
 
Unity_LocalToUnityPoint(UnityPoint *unityPt, // IN/OUT
2970
 
                        UnityPoint *localPt) // IN
2971
 
{
2972
 
   ASSERT(unityPt);
2973
 
   ASSERT(localPt);
2974
 
   unityPt->x = localPt->x;
2975
 
   unityPt->y = localPt->y;
2976
 
}
2977
 
 
2978
 
 
2979
 
/*
2980
 
 ******************************************************************************
2981
 
 * UnityPlatformStickWindow --                                           */ /**
2982
 
 *
2983
 
 * @brief "Stick" a window to the desktop.
2984
 
 *
2985
 
 * @param[in] up       Platform context.
2986
 
 * @param[in] windowId Operand window.
2987
 
 *
2988
 
 * @retval TRUE  Success.
2989
 
 * @retval FALSE Failure.
2990
 
 *
2991
 
 ******************************************************************************
2992
 
 */
2993
 
 
2994
 
Bool
2995
 
UnityPlatformStickWindow(UnityPlatform *up,      // IN
2996
 
                         UnityWindowId windowId) // IN
2997
 
{
2998
 
   return SetWindowStickiness(up, windowId, TRUE);
2999
 
}
3000
 
 
3001
 
 
3002
 
/*
3003
 
 ******************************************************************************
3004
 
 * UnityPlatformUnstickWindow --                                         */ /**
3005
 
 *
3006
 
 * @brief "Unstick" a window from the desktop.
3007
 
 *
3008
 
 * @param[in] up       Platform context.
3009
 
 * @param[in] windowId Operand window.
3010
 
 *
3011
 
 * @retval TRUE  Success.
3012
 
 * @retval FALSE Failure.
3013
 
 *
3014
 
 ******************************************************************************
3015
 
 */
3016
 
 
3017
 
Bool
3018
 
UnityPlatformUnstickWindow(UnityPlatform *up,      // IN
3019
 
                           UnityWindowId windowId) // IN
3020
 
{
3021
 
   return SetWindowStickiness(up, windowId, FALSE);
3022
 
}
3023
 
 
3024
 
 
3025
 
/*
3026
 
 *-----------------------------------------------------------------------------
3027
 
 *
3028
 
 * UnityPlatformSetConfigDesktopColor --
3029
 
 *
3030
 
 *      Set the preferred desktop background color for use when in Unity Mode.
3031
 
 *
3032
 
 * Results:
3033
 
 *      None.
3034
 
 *
3035
 
 * Side effects:
3036
 
 *      None.
3037
 
 *
3038
 
 *-----------------------------------------------------------------------------
3039
 
 */
3040
 
 
3041
 
void
3042
 
UnityPlatformSetConfigDesktopColor(UnityPlatform *up, int desktopColor)
3043
 
{
3044
 
   ASSERT(up);
3045
 
}
3046
 
 
3047
 
 
3048
 
/*
3049
 
 *-----------------------------------------------------------------------------
3050
 
 *
3051
 
 * UnityPlatformRequestWindowContents --
3052
 
 *
3053
 
 *     Validate the list of supplied window IDs and once validated add them to a list
3054
 
 *     of windows whose contents should be sent to the host.
3055
 
 *
3056
 
 * Results:
3057
 
 *      None.
3058
 
 *
3059
 
 * Side effects:
3060
 
 *      None.
3061
 
 *
3062
 
 *-----------------------------------------------------------------------------
3063
 
 */
3064
 
 
3065
 
Bool
3066
 
UnityPlatformRequestWindowContents(UnityPlatform *up,
3067
 
                                   UnityWindowId windowIds[],
3068
 
                                   uint32 numWindowIds)
3069
 
{
3070
 
   ASSERT(up);
3071
 
 
3072
 
   /* Not implemented */
3073
 
   return FALSE;
3074
 
}
3075
 
 
3076
 
 
3077
 
/*
3078
 
 *-----------------------------------------------------------------------------
3079
 
 *
3080
 
 * UnityPlatformConfirmMinimizeOperation --
3081
 
 *
3082
 
 *     Minimize a window (if allowed) by the host.
3083
 
 *
3084
 
 * Results:
3085
 
 *     Returns TRUE if successful, and FALSE otherwise.
3086
 
 *
3087
 
 * Side effects:
3088
 
 *     None.
3089
 
 *
3090
 
 *------------------------------------------------------------------------------
3091
 
 */
3092
 
 
3093
 
Bool
3094
 
UnityPlatformConfirmMinimizeOperation(UnityPlatform *up,        // IN
3095
 
                                      UnityWindowId windowId,   // IN
3096
 
                                      uint32 sequence,          // IN
3097
 
                                      Bool allow)               // IN
3098
 
{
3099
 
   ASSERT(up);
3100
 
   return FALSE;
3101
 
}
3102
 
 
3103
 
 
3104
 
/*
3105
 
 *-----------------------------------------------------------------------------
3106
 
 *
3107
 
 * UnityPlatformSetInterlockMinimizeOperation --
3108
 
 *
3109
 
 *     Enable (or Disable) the interlocking (relaying) of minimize operations
3110
 
 *     through the host.
3111
 
 *
3112
 
 * Results:
3113
 
 *     None.
3114
 
 *
3115
 
 * Side effects:
3116
 
 *     None.
3117
 
 *
3118
 
 *------------------------------------------------------------------------------
3119
 
 */
3120
 
 
3121
 
void UnityPlatformSetInterlockMinimizeOperation(UnityPlatform *up,   // IN
3122
 
                                                Bool enabled)        // IN
3123
 
{
3124
 
   ASSERT(up);
3125
 
}
3126
 
 
3127
 
 
3128
 
/*
3129
 
 *-----------------------------------------------------------------------------
3130
 
 *
3131
 
 * UnityPlatformSetDisableCompositing --
3132
 
 *
3133
 
 *     Disable (or Enable) the compositing features of the window manager the
3134
 
 *     next time Unity starts.
3135
 
 *
3136
 
 * Results:
3137
 
 *     None.
3138
 
 *
3139
 
 * Side effects:
3140
 
 *     None.
3141
 
 *
3142
 
 *------------------------------------------------------------------------------
3143
 
 */
3144
 
 
3145
 
void UnityPlatformSetDisableCompositing(UnityPlatform *up,      // IN
3146
 
                                        Bool disabled)          // IN
3147
 
{
3148
 
   ASSERT(up);
3149
 
}
3150
 
 
3151
 
 
3152
 
/*
3153
 
 ******************************************************************************
3154
 
 * Begin file-scope functions.
3155
 
 *
3156
 
 */
3157
 
 
3158
 
 
3159
 
/*
3160
 
 ******************************************************************************
3161
 
 * GetRelevantWMWindow --                                                */ /**
3162
 
 *
3163
 
 * @brief Given a UnityWindowId, return the X11 window relevant to WM operations.
3164
 
 *
3165
 
 * Starting with a Unity window, look for and return its associated
3166
 
 * clientWindow.  If there is no clientWindow, then return the top-level window.
3167
 
 *
3168
 
 * @param[in]  up        Unity/X11 context.
3169
 
 * @param[in]  windowId  Window search for.
3170
 
 * @param[out] wmWindow  Set to the relevant X11 window.
3171
 
 *
3172
 
 * @todo Consider exporting this for use in unityPlatformX11Window.c.
3173
 
 *
3174
 
 * @retval TRUE  Relevant window found and recorded in @a wmWindow.
3175
 
 * @retval FALSE Unable to find @a windowId.
3176
 
 *
3177
 
 ******************************************************************************
3178
 
 */
3179
 
 
3180
 
static Bool
3181
 
GetRelevantWMWindow(UnityPlatform *up,          // IN
3182
 
                    UnityWindowId windowId,     // IN
3183
 
                    Window *wmWindow)           // OUT
3184
 
{
3185
 
   UnityPlatformWindow *upw;
3186
 
 
3187
 
   ASSERT(up);
3188
 
 
3189
 
   upw = UPWindow_Lookup(up, windowId);
3190
 
   if (!upw) {
3191
 
      return FALSE;
3192
 
   }
3193
 
 
3194
 
   *wmWindow = upw->clientWindow ? upw->clientWindow : upw->toplevelWindow;
3195
 
   return TRUE;
3196
 
}
3197
 
 
3198
 
 
3199
 
/*
3200
 
 ******************************************************************************
3201
 
 * SetWindowStickiness --                                                */ /**
3202
 
 *
3203
 
 * @brief Sets or clears a window's sticky state.
3204
 
 *
3205
 
 * @param[in] up         Unity/X11 context.
3206
 
 * @param[in] windowId   Operand window.
3207
 
 * @param[in] wantSticky Set to TRUE to stick a window, FALSE to unstick it.
3208
 
 *
3209
 
 * @retval TRUE  Request successfully sent to X server.
3210
 
 * @retval FALSE Request failed.
3211
 
 *
3212
 
 ******************************************************************************
3213
 
 */
3214
 
 
3215
 
static Bool
3216
 
SetWindowStickiness(UnityPlatform *up,          // IN
3217
 
                    UnityWindowId windowId,     // IN
3218
 
                    Bool wantSticky)            // IN
3219
 
{
3220
 
   GdkWindow *gdkWindow;
3221
 
   Window curWindow;
3222
 
 
3223
 
   ASSERT(up);
3224
 
 
3225
 
   if (!GetRelevantWMWindow(up, windowId, &curWindow)) {
3226
 
      Debug("%s: Lookup against window %#x failed.\n", __func__, windowId);
3227
 
      return FALSE;
3228
 
   }
3229
 
 
3230
 
   gdkWindow = gdk_window_foreign_new(curWindow);
3231
 
   if (gdkWindow == NULL) {
3232
 
      Debug("%s: Unable to create Gdk window?! (%#x)\n", __func__, windowId);
3233
 
      return FALSE;
3234
 
   }
3235
 
 
3236
 
   if (wantSticky) {
3237
 
      gdk_window_stick(gdkWindow);
3238
 
   } else {
3239
 
      gdk_window_unstick(gdkWindow);
3240
 
   }
3241
 
 
3242
 
   gdk_flush();
3243
 
   g_object_unref(G_OBJECT(gdkWindow));
3244
 
 
3245
 
   return TRUE;
3246
 
}
3247
 
 
3248
 
 
3249
 
/*
3250
 
 *-----------------------------------------------------------------------------
3251
 
 *
3252
 
 * UnityPlatformSendMouseWheel --
3253
 
 *
3254
 
 *     Sends the given mouse wheel event to the window at the given location.
3255
 
 *
3256
 
 * Results:
3257
 
 *     Returns TRUE if successful, and FALSE otherwise.
3258
 
 *
3259
 
 * Side effects:
3260
 
 *     None.
3261
 
 *
3262
 
 *------------------------------------------------------------------------------
3263
 
 */
3264
 
 
3265
 
Bool
3266
 
UnityPlatformSendMouseWheel(UnityPlatform *up,    // IN
3267
 
                            int32 deltaX,         // IN
3268
 
                            int32 deltaY,         // IN
3269
 
                            int32 deltaZ,         // IN
3270
 
                            uint32 modifierFlags) // IN
3271
 
{
3272
 
   ASSERT(up);
3273
 
   return FALSE;
3274
 
}
3275
 
 
3276
 
 
3277
 
/*
3278
 
 *-----------------------------------------------------------------------------
3279
 
 *
3280
 
 * MakeCompositeOverlaysObject --
3281
 
 *
3282
 
 *      Probes X server for any composite overlay windows.  If found, they're
3283
 
 *      monitored as UnitySpecialWindows whereby we won't mistakenly place them
3284
 
 *      in the global window tracker.
3285
 
 *
3286
 
 * Results:
3287
 
 *      Returns pointer to new UnitySpecialWindow on success, NULL on failure.
3288
 
 *
3289
 
 * Side effects:
3290
 
 *      If overlay windows haven't yet been mapped, they will be (temporarily).
3291
 
 *
3292
 
 *      Caller doesn't need to free returned UnitySpecialWindow*.  That's handled
3293
 
 *      automatically when exiting Unity.
3294
 
 *
3295
 
 *-----------------------------------------------------------------------------
3296
 
 */
3297
 
 
3298
 
static UnitySpecialWindow *
3299
 
MakeCompositeOverlaysObject(UnityPlatform *up)  // IN
3300
 
{
3301
 
   ASSERT(up);
3302
 
   ASSERT(up->rootWindows);
3303
 
 
3304
 
#ifndef NO_XCOMPOSITE
3305
 
   int eventBase;
3306
 
   int errorBase;
3307
 
   if (XCompositeQueryExtension(up->display, &eventBase, &errorBase)) {
3308
 
      /*
3309
 
       * XCompositeGetOverlayWindow didn't appear until XComposite 0.3.
3310
 
       */
3311
 
      int major = 0;
3312
 
      int minor = 0;
3313
 
      XCompositeQueryVersion(up->display, &major, &minor);
3314
 
      if (major > 0 || (major == 0 && minor >= 3)) {
3315
 
         size_t nWindows = up->rootWindows->numWindows;
3316
 
         Window *overlays = (Window*)Util_SafeCalloc(nWindows, sizeof *overlays);
3317
 
         for (unsigned int i = 0; i < nWindows; i++) {
3318
 
            overlays[i] = XCompositeGetOverlayWindow(up->display,
3319
 
                                                     up->rootWindows->windows[i]);
3320
 
            XCompositeReleaseOverlayWindow(up->display, overlays[i]);
3321
 
         }
3322
 
 
3323
 
         /*
3324
 
          * Note 1: See above. Caller doesn't need to need to track this explicitly.
3325
 
          * Note 2: The NULL event handler parameter is how we tell the X event handling
3326
 
          *         pieces to ignore this window, thereby keeping it out of the window
3327
 
          *         tracker.
3328
 
          */
3329
 
         return USWindowCreate(up, NULL, overlays, nWindows);
3330
 
      }
3331
 
   }
3332
 
#endif // ifndef NO_XCOMPOSITE
3333
 
 
3334
 
   return NULL;
3335
 
}
3336
 
 
3337
 
/*
3338
 
 *
3339
 
 * End file-scope functions.
3340
 
 ******************************************************************************
3341
 
 */