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

« back to all changes in this revision

Viewing changes to services/plugins/unity/unityWindowTracker/unityWindowTracker.c

  • 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 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
 
 * unityWindowTracker.h --
21
 
 *
22
 
 *    Used to buffer state about a window manager.
23
 
 */
24
 
 
25
 
#include <stdio.h>
26
 
#include "vmware.h"
27
 
#include "str.h"
28
 
#include "strutil.h"
29
 
#include "util.h"
30
 
#include "log.h"
31
 
#include "unityWindowTracker.h"
32
 
 
33
 
#define LOGLEVEL_MODULE uwt
34
 
#include "loglevel_user.h"
35
 
 
36
 
/*
37
 
 * Helper Functions --
38
 
 */
39
 
 
40
 
static void FreeWindowInfo(UnityWindowInfo *info);
41
 
static int RemoveUntouchedWindow(const char *key, void *value,
42
 
                                 void *clientData);
43
 
static int GarbageCollectRemovedWindows(const char *key, void *value,
44
 
                                        void *clientData);
45
 
static int ResetChangedBits(const char *key, void *value, void *clientData);
46
 
static int PushUpdates(const char *key, void *value, void *clientData);
47
 
static int PushRemoveWindow(const char *key, void *value, void *clientData);
48
 
static Bool TitlesEqual(DynBuf *first, DynBuf *second);
49
 
static int PushZOrder(UnityWindowTracker *tracker);
50
 
static int PushActiveDesktop(UnityWindowTracker *tracker);
51
 
 
52
 
 
53
 
/*
54
 
 *----------------------------------------------------------------------------
55
 
 *
56
 
 * UnityWindowTracker_Init --
57
 
 *
58
 
 *      Create a new unity window tracker.  The client should pass in a
59
 
 *      callbacks object, which will be used to notify them of updates
60
 
 *      in UnityWindowTracker_RequestUpdates.
61
 
 *
62
 
 * Results:
63
 
 *      None.
64
 
 *
65
 
 * Side effects:
66
 
 *      None.
67
 
 *
68
 
 *----------------------------------------------------------------------------
69
 
 */
70
 
 
71
 
void
72
 
UnityWindowTracker_Init(UnityWindowTracker *tracker,     // IN
73
 
                        UnityUpdateCallback cb)          // IN
74
 
{
75
 
   memset(tracker, 0, sizeof(UnityWindowTracker));
76
 
   tracker->cb = cb;
77
 
   tracker->windows = HashTable_Alloc(128, HASH_INT_KEY,
78
 
                                      (HashTableFreeEntryFn)FreeWindowInfo);
79
 
}
80
 
 
81
 
 
82
 
/*
83
 
 *----------------------------------------------------------------------------
84
 
 *
85
 
 * UnityWindowTracker_Cleanup --
86
 
 *
87
 
 *      Destory a unity window tracker.
88
 
 *
89
 
 * Results:
90
 
 *      None.
91
 
 *
92
 
 * Side effects:
93
 
 *      None.
94
 
 *
95
 
 *----------------------------------------------------------------------------
96
 
 */
97
 
 
98
 
void
99
 
UnityWindowTracker_Cleanup(UnityWindowTracker *tracker)  // IN
100
 
{
101
 
   if (NULL != tracker->windows) {
102
 
      HashTable_Free(tracker->windows);
103
 
   }
104
 
   memset(tracker, 0, sizeof(UnityWindowTracker));
105
 
}
106
 
 
107
 
 
108
 
/*
109
 
 *-----------------------------------------------------------------------------
110
 
 *
111
 
 * UnityWindowTracker_SetDataFreeFunc --
112
 
 *
113
 
 *      Sets the function that will be called to free the app data associated with a
114
 
 *      window.
115
 
 *
116
 
 * Results:
117
 
 *      None.
118
 
 *
119
 
 * Side effects:
120
 
 *      None.
121
 
 *
122
 
 *-----------------------------------------------------------------------------
123
 
 */
124
 
 
125
 
void
126
 
UnityWindowTracker_SetDataFreeFunc(UnityWindowTracker *tracker,  // IN
127
 
                                   UnityDataFreeFunc freeFn)     // IN
128
 
{
129
 
   tracker->freeFn = freeFn;
130
 
}
131
 
 
132
 
 
133
 
/*
134
 
 *----------------------------------------------------------------------------
135
 
 *
136
 
 * UnityWindowTracker_LookupWindow --
137
 
 *
138
 
 *      Returns the window with the specified window id, or NULL if no
139
 
 *      such window exists.
140
 
 *
141
 
 * Results:
142
 
 *      See above.
143
 
 *
144
 
 * Side effects:
145
 
 *      None.
146
 
 *
147
 
 *----------------------------------------------------------------------------
148
 
 */
149
 
 
150
 
UnityWindowInfo *
151
 
UnityWindowTracker_LookupWindow(UnityWindowTracker *tracker,      // IN
152
 
                                UnityWindowId id)                 // IN
153
 
{
154
 
   UnityWindowInfo *info = NULL;
155
 
   HashTable_Lookup(tracker->windows, (const char *)(long)id, (void **)&info);
156
 
   return info;
157
 
}
158
 
 
159
 
 
160
 
/*
161
 
 *----------------------------------------------------------------------------
162
 
 *
163
 
 * UnityWindowTracker_AddWindow --
164
 
 *
165
 
 *      Add a new window to the window tracker
166
 
 *
167
 
 * Results:
168
 
 *      A pointer to the UnityWindowInfo for the added window
169
 
 *
170
 
 * Side effects:
171
 
 *      None.
172
 
 *
173
 
 *----------------------------------------------------------------------------
174
 
 */
175
 
 
176
 
UnityWindowInfo *
177
 
UnityWindowTracker_AddWindow(UnityWindowTracker *tracker,   // IN
178
 
                             UnityWindowId id,              // IN
179
 
                             DynBuf *windowPathUtf8,        // IN
180
 
                             DynBuf *execPathUtf8)          // IN
181
 
{
182
 
   UnityWindowInfo *info = UnityWindowTracker_LookupWindow(tracker, id);
183
 
   if (!info) {
184
 
      size_t windowPathSize;
185
 
      size_t execPathSize;
186
 
 
187
 
      info = (UnityWindowInfo *)Util_SafeCalloc(1, sizeof(UnityWindowInfo));
188
 
      info->tracker = tracker;
189
 
      info->id = id;
190
 
      info->type = UNITY_WINDOW_TYPE_NONE;
191
 
      info->desktopId = tracker->activeDesktopId;
192
 
      DynBuf_Init(&info->titleUtf8);
193
 
      DynBuf_Init(&info->windowPathUtf8);
194
 
      DynBuf_Init(&info->execPathUtf8);
195
 
 
196
 
      /*
197
 
       * Ensure that the provided paths only include one NUL terminator
198
 
       * at the end of the buffer, or keep the paths empty otherwise.
199
 
       */
200
 
      windowPathSize = DynBuf_GetSize(windowPathUtf8);
201
 
      if (windowPathSize > 0) {
202
 
         Bool isNullTerminated = Str_Strlen((char *)DynBuf_Get(windowPathUtf8),
203
 
                                            windowPathSize) == windowPathSize - 1;
204
 
         ASSERT(isNullTerminated);
205
 
         if (isNullTerminated) {
206
 
            DynBuf_Copy(windowPathUtf8, &info->windowPathUtf8);
207
 
         }
208
 
      }
209
 
      execPathSize = DynBuf_GetSize(execPathUtf8);
210
 
      if (execPathSize > 0) {
211
 
         Bool isNullTerminated = Str_Strlen((char *)DynBuf_Get(execPathUtf8),
212
 
                                            execPathSize) == execPathSize - 1;
213
 
         ASSERT(isNullTerminated);
214
 
         if (isNullTerminated) {
215
 
            DynBuf_Copy(execPathUtf8, &info->execPathUtf8);
216
 
         }
217
 
      }
218
 
 
219
 
      LOG(2, ("Unity adding new window (id:%d)\n", id));
220
 
      HashTable_Insert(tracker->windows, (const char *)(long)id, info);
221
 
      info->changed |= UNITY_CHANGED_ADDED;
222
 
      info->changed |= UNITY_CHANGED_WINDOW_DESKTOP;
223
 
   } else {
224
 
      info->changed &= ~UNITY_CHANGED_REMOVED;
225
 
      LOG(2, ("Window already exists in UnityAddWindow (id:%d)\n", id));
226
 
   }
227
 
   info->touched = TRUE;
228
 
 
229
 
   return info;
230
 
}
231
 
 
232
 
 
233
 
/*
234
 
 *----------------------------------------------------------------------------
235
 
 *
236
 
 * UnityWindowTracker_AddWindowWithData --
237
 
 *
238
 
 *      Add a new window to the window tracker, and sets its application data to the
239
 
 *      specified 'data'. The tracker's DataFreeFunc will be used to free 'data' when it
240
 
 *      needs to be destroyed (see UnityWindowTracker_SetDataFreeFunc).  If the window
241
 
 *      already exists and has 'data' set on it, that will be destroyed and replaced with
242
 
 *      the new 'data' pointer.
243
 
 *
244
 
 * Results:
245
 
 *      A pointer to the UnityWindowInfo for the added window.
246
 
 *
247
 
 * Side effects:
248
 
 *      None.
249
 
 *
250
 
 *----------------------------------------------------------------------------
251
 
 */
252
 
 
253
 
UnityWindowInfo *
254
 
UnityWindowTracker_AddWindowWithData(UnityWindowTracker *tracker,    // IN
255
 
                                     UnityWindowId id,               // IN
256
 
                                     DynBuf *windowPathUtf8,         // IN
257
 
                                     DynBuf *execPathUtf8,           // IN
258
 
                                     void *data)                     // IN
259
 
{
260
 
   UnityWindowInfo *info = UnityWindowTracker_AddWindow(tracker,
261
 
                                                        id,
262
 
                                                        windowPathUtf8,
263
 
                                                        execPathUtf8);
264
 
 
265
 
   if (info) {
266
 
      if (info->data
267
 
          && tracker->freeFn
268
 
          && (info->data != data)) {
269
 
         tracker->freeFn(tracker, info, info->data);
270
 
      }
271
 
 
272
 
      info->data = data;
273
 
   }
274
 
 
275
 
   return info;
276
 
}
277
 
 
278
 
 
279
 
/*
280
 
 *----------------------------------------------------------------------------
281
 
 *
282
 
 * UnityWindowTracker_MoveWindow --
283
 
 *
284
 
 *      Notify the window tracker that the window with the specified id
285
 
 *      has moved.
286
 
 *
287
 
 * Results:
288
 
 *      None.
289
 
 *
290
 
 * Side effects:
291
 
 *      None.
292
 
 *
293
 
 *----------------------------------------------------------------------------
294
 
 */
295
 
 
296
 
void
297
 
UnityWindowTracker_MoveWindow(UnityWindowTracker *tracker,  // IN
298
 
                              UnityWindowId id,             // IN
299
 
                              int x1,                       // IN
300
 
                              int y1,                       // IN
301
 
                              int x2,                       // IN
302
 
                              int y2)                       // IN
303
 
{
304
 
   UnityWindowInfo *info = UnityWindowTracker_LookupWindow(tracker, id);
305
 
   if (info) {
306
 
      info->touched = TRUE;
307
 
      if (info->rect.x1 != x1 || info->rect.y1 != y1
308
 
          || x2 != info->rect.x2 || y2 != info->rect.y2) {
309
 
         LOG(2, ("Unity moving window (id:%d pos:%d,%d, %d,%d)\n", id, x1, y1, x2, y2));
310
 
         info->rect.x1 = x1;
311
 
         info->rect.y1 = y1;
312
 
         info->rect.x2 = x2;
313
 
         info->rect.y2 = y2;
314
 
         info->changed |= UNITY_CHANGED_POSITION;
315
 
      }
316
 
   }
317
 
}
318
 
 
319
 
 
320
 
/*
321
 
 *----------------------------------------------------------------------------
322
 
 *
323
 
 * UnityWindowTracker_SetWindowTitle --
324
 
 *
325
 
 *      Notify the window tracker that the window with the specified id
326
 
 *      has changed its title.
327
 
 *
328
 
 *      This function does not take ownership of the DynBuf; caller
329
 
 *      is assumed to free it.
330
 
 *
331
 
 * Results:
332
 
 *      None.
333
 
 *
334
 
 * Side effects:
335
 
 *      None.
336
 
 *
337
 
 *----------------------------------------------------------------------------
338
 
 */
339
 
 
340
 
void
341
 
UnityWindowTracker_SetWindowTitle(UnityWindowTracker *tracker,  // IN
342
 
                                  UnityWindowId id,             // IN
343
 
                                  DynBuf *titleUtf8)            // IN
344
 
{
345
 
   UnityWindowInfo *info = UnityWindowTracker_LookupWindow(tracker, id);
346
 
   if (info) {
347
 
      info->touched = TRUE;
348
 
      if (!TitlesEqual(&info->titleUtf8, titleUtf8)) {
349
 
         LOG(2, ("Unity setting window title (id:%d title:%s)\n", id,
350
 
             (const unsigned char*)DynBuf_Get(titleUtf8)));
351
 
         info->changed |= UNITY_CHANGED_TITLE;
352
 
         DynBuf_Destroy(&info->titleUtf8);
353
 
         DynBuf_Copy(titleUtf8, &info->titleUtf8);
354
 
      }
355
 
   }
356
 
}
357
 
 
358
 
 
359
 
/*
360
 
 *----------------------------------------------------------------------------
361
 
 *
362
 
 * UnityWindowTracker_ChangeWindowRegion --
363
 
 *
364
 
 *      Change the window region of the specified window.  A NULL region
365
 
 *      means the window region is simply the bounds of the window.
366
 
 *
367
 
 *      This function does not take ownership of the RegionPtr; caller is
368
 
 *      assumed to free it.
369
 
 *
370
 
 * Results:
371
 
 *      None.
372
 
 *
373
 
 * Side effects:
374
 
 *      None.
375
 
 *
376
 
 *----------------------------------------------------------------------------
377
 
 */
378
 
 
379
 
void
380
 
UnityWindowTracker_ChangeWindowRegion(UnityWindowTracker *tracker,   // IN
381
 
                                      UnityWindowId id,              // IN
382
 
                                      RegionPtr region)              // IN
383
 
{
384
 
   UnityWindowInfo *info = UnityWindowTracker_LookupWindow(tracker, id);
385
 
   if (info) {
386
 
      info->touched = TRUE;
387
 
      if (region) {
388
 
         if (!info->region) {
389
 
            LOG(2, ("Unity adding window region (id:%d)\n", id));
390
 
            info->changed |= UNITY_CHANGED_REGION;
391
 
            info->region = miRegionCreate(&miEmptyBox, 0);
392
 
         }
393
 
         if (!miRegionsEqual(info->region, region)) {
394
 
            LOG(2, ("Unity changing window region (id:%d)\n", id));
395
 
            info->changed |= UNITY_CHANGED_REGION;
396
 
            miRegionCopy(info->region, region);
397
 
         }
398
 
      } else {
399
 
         if (info->region) {
400
 
            LOG(2, ("Unity removing window region (id:%d)\n", id));
401
 
            info->changed |= UNITY_CHANGED_REGION;
402
 
            miRegionDestroy(info->region);
403
 
            info->region = NULL;
404
 
         }
405
 
      }
406
 
   }
407
 
}
408
 
 
409
 
 
410
 
/*
411
 
 *----------------------------------------------------------------------------
412
 
 *
413
 
 * UnityWindowTracker_ChangeWindowState --
414
 
 *
415
 
 *      Change window state (minimized or not) of the specified window.
416
 
 *
417
 
 * Results:
418
 
 *      None.
419
 
 *
420
 
 * Side effects:
421
 
 *      None.
422
 
 *
423
 
 *----------------------------------------------------------------------------
424
 
 */
425
 
 
426
 
void
427
 
UnityWindowTracker_ChangeWindowState(UnityWindowTracker *tracker,  // IN
428
 
                                     UnityWindowId id,             // IN
429
 
                                     uint32 state)                 // IN
430
 
{
431
 
   UnityWindowInfo *info = UnityWindowTracker_LookupWindow(tracker, id);
432
 
   if (info) {
433
 
      info->touched = TRUE;
434
 
      if (state != info->state) {
435
 
         info->changed |= UNITY_CHANGED_WINDOW_STATE;
436
 
         info->state = state;
437
 
         LOG(2, ("Unity changing window state (id:%d) to %d\n", id, state));
438
 
      }
439
 
   }
440
 
}
441
 
 
442
 
 
443
 
/*
444
 
 *----------------------------------------------------------------------------
445
 
 *
446
 
 * UnityWindowTracker_GetWindowState --
447
 
 *
448
 
 *      Get window state (minimized or not) of the specified window.
449
 
 *
450
 
 * Results:
451
 
 *      TRUE if the window exists in the window tracker.
452
 
 *      FALSE otherwise.
453
 
 *
454
 
 * Side effects:
455
 
 *      None.
456
 
 *
457
 
 *----------------------------------------------------------------------------
458
 
 */
459
 
 
460
 
Bool
461
 
UnityWindowTracker_GetWindowState(UnityWindowTracker *tracker,  // IN
462
 
                                  UnityWindowId id,             // IN
463
 
                                  uint32 *state)                // IN
464
 
{
465
 
   UnityWindowInfo *info = UnityWindowTracker_LookupWindow(tracker, id);
466
 
   ASSERT(state);
467
 
   if (info) {
468
 
      *state = info->state;
469
 
      return TRUE;
470
 
   }
471
 
   return FALSE;
472
 
}
473
 
 
474
 
 
475
 
/*
476
 
 *-----------------------------------------------------------------------------
477
 
 *
478
 
 * UnityWindowTracker_ChangeWindowAttribute --
479
 
 *
480
 
 *      Sets the value of a particular attribute on a particular window.
481
 
 *
482
 
 * Results:
483
 
 *      None.
484
 
 *
485
 
 * Side effects:
486
 
 *      Marks the window tracker as having updates.
487
 
 *
488
 
 *-----------------------------------------------------------------------------
489
 
 */
490
 
 
491
 
void
492
 
UnityWindowTracker_ChangeWindowAttribute(UnityWindowTracker *tracker, // IN
493
 
                                         UnityWindowId id,            // IN
494
 
                                         UnityWindowAttribute attr,   // IN
495
 
                                         Bool enabled)                // IN
496
 
{
497
 
   UnityWindowInfo *info;
498
 
   ASSERT(tracker);
499
 
   ASSERT(attr < UNITY_MAX_ATTRIBUTES);
500
 
 
501
 
   info = UnityWindowTracker_LookupWindow(tracker, id);
502
 
   if (info) {
503
 
      info->touched = TRUE;
504
 
 
505
 
      /*
506
 
       * If this is a new attribute (that didn't exist before) or
507
 
       * if the attribute value has changed, remember the new value
508
 
       * (enabled or disabled) and mark it as existing and
509
 
       * changed.
510
 
       */
511
 
 
512
 
      if (!(info->attributes[attr] & UNITY_INFO_ATTR_EXISTS) ||
513
 
          ((info->attributes[attr] & UNITY_INFO_ATTR_ENABLED) !=
514
 
           (enabled ? UNITY_INFO_ATTR_ENABLED : 0))) {
515
 
         info->changed |= UNITY_CHANGED_WINDOW_ATTRIBUTES;
516
 
         info->attributes[attr] = (UNITY_INFO_ATTR_EXISTS |
517
 
                                   UNITY_INFO_ATTR_CHANGED |
518
 
                                   (enabled ? UNITY_INFO_ATTR_ENABLED : 0));
519
 
         LOG(2, ("Unity changing window (id:%d) attribute %d = %s\n",
520
 
                 id, attr, enabled ? "TRUE" : "FALSE"));
521
 
      }
522
 
   }
523
 
}
524
 
 
525
 
 
526
 
/*
527
 
 *-----------------------------------------------------------------------------
528
 
 *
529
 
 * UnityWindowTracker_GetWindowAttribute --
530
 
 *
531
 
 *      Retrieves the current value of a window attribute.
532
 
 *
533
 
 * Results:
534
 
 *      TRUE if the attribute value was retrieved successfully.
535
 
 *      FALSE if the attribute had never been set on the specified window, or if the
536
 
 *      window does not exist.
537
 
 *
538
 
 * Side effects:
539
 
 *      None.
540
 
 *
541
 
 *-----------------------------------------------------------------------------
542
 
 */
543
 
 
544
 
Bool
545
 
UnityWindowTracker_GetWindowAttribute(UnityWindowTracker *tracker,  // IN
546
 
                                      UnityWindowId id,             // IN
547
 
                                      UnityWindowAttribute attr,    // IN
548
 
                                      Bool *enabled)                // IN
549
 
{
550
 
   Bool retval = FALSE;
551
 
   UnityWindowInfo *info;
552
 
   ASSERT(tracker);
553
 
   ASSERT(attr < UNITY_MAX_ATTRIBUTES);
554
 
 
555
 
   info = UnityWindowTracker_LookupWindow(tracker, id);
556
 
   if (info
557
 
       && (info->attributes[attr] & UNITY_INFO_ATTR_EXISTS)) {
558
 
      *enabled = (info->attributes[attr] & UNITY_INFO_ATTR_ENABLED) ? TRUE : FALSE;
559
 
      retval = TRUE;
560
 
   }
561
 
 
562
 
   return retval;
563
 
}
564
 
 
565
 
 
566
 
/*
567
 
 *-----------------------------------------------------------------------------
568
 
 *
569
 
 * UnityWindowTracker_ChangeWindowType --
570
 
 *
571
 
 *      Sets the window type of the specified window.
572
 
 *
573
 
 * Results:
574
 
 *      None.
575
 
 *
576
 
 * Side effects:
577
 
 *      Marks the window tracker as having updates.
578
 
 *
579
 
 *-----------------------------------------------------------------------------
580
 
 */
581
 
 
582
 
void
583
 
UnityWindowTracker_ChangeWindowType(UnityWindowTracker *tracker,  // IN
584
 
                                    UnityWindowId id,             // IN
585
 
                                    UnityWindowType winType)      // IN
586
 
{
587
 
   UnityWindowInfo *info;
588
 
   ASSERT(tracker);
589
 
 
590
 
   info = UnityWindowTracker_LookupWindow(tracker, id);
591
 
   if (info) {
592
 
      info->touched = TRUE;
593
 
      if (winType != info->type) {
594
 
         info->changed |= UNITY_CHANGED_WINDOW_TYPE;
595
 
         info->type = winType;
596
 
         LOG(2, ("Unity changing window (id:%d) type to %d\n",
597
 
                 id, winType));
598
 
      }
599
 
   }
600
 
}
601
 
 
602
 
 
603
 
/*
604
 
 *-----------------------------------------------------------------------------
605
 
 *
606
 
 * UnityWindowTracker_GetWindowType --
607
 
 *
608
 
 *      Retrieves the window type of the specified window.
609
 
 *
610
 
 * Results:
611
 
 *      TRUE if successful, FALSE if failed.
612
 
 *
613
 
 * Side effects:
614
 
 *      None.
615
 
 *
616
 
 *-----------------------------------------------------------------------------
617
 
 */
618
 
 
619
 
Bool
620
 
UnityWindowTracker_GetWindowType(UnityWindowTracker *tracker, // IN
621
 
                                 UnityWindowId id,            // IN
622
 
                                 UnityWindowType *winType)    // IN
623
 
{
624
 
   Bool retval = FALSE;
625
 
   UnityWindowInfo *info;
626
 
 
627
 
   ASSERT(tracker);
628
 
   ASSERT(winType);
629
 
 
630
 
   info = UnityWindowTracker_LookupWindow(tracker, id);
631
 
   if (info) {
632
 
      *winType = info->type;
633
 
      retval = TRUE;
634
 
   }
635
 
 
636
 
   return retval;
637
 
}
638
 
 
639
 
 
640
 
/*
641
 
 *-----------------------------------------------------------------------------
642
 
 *
643
 
 * UnityWindowTracker_NotifyIconChanged --
644
 
 *
645
 
 *      Marks the window tracker as having a changed icon for a window.
646
 
 *
647
 
 * Results:
648
 
 *      None.
649
 
 *
650
 
 * Side effects:
651
 
 *      None.
652
 
 *
653
 
 *-----------------------------------------------------------------------------
654
 
 */
655
 
 
656
 
void
657
 
UnityWindowTracker_NotifyIconChanged(UnityWindowTracker *tracker, // IN
658
 
                                     UnityWindowId id,            // IN
659
 
                                     UnityIconType iconType)      // IN
660
 
{
661
 
   UnityWindowInfo *info;
662
 
 
663
 
   ASSERT(tracker);
664
 
   ASSERT(iconType < UNITY_MAX_ICONS);
665
 
 
666
 
   info = UnityWindowTracker_LookupWindow(tracker, id);
667
 
   if (info) {
668
 
      LOG(2, ("Unity icon changed on window (id:%d)\n", id));
669
 
      info->touched = TRUE;
670
 
      info->changed |= UNITY_CHANGED_WINDOW_ICONS;
671
 
      info->icons[iconType] |= UNITY_INFO_ATTR_CHANGED | UNITY_INFO_ATTR_EXISTS;
672
 
   }
673
 
}
674
 
 
675
 
 
676
 
/*
677
 
 *-----------------------------------------------------------------------------
678
 
 *
679
 
 * UnityWindowTracker_ChangeWindowDesktop --
680
 
 *
681
 
 *      Saves the window desktop information if that was changed.
682
 
 *
683
 
 * Results:
684
 
 *      None.
685
 
 *
686
 
 * Side effects:
687
 
 *      Window desktop information might be updated.
688
 
 *      Window marked as touched.
689
 
 *
690
 
 *-----------------------------------------------------------------------------
691
 
 */
692
 
 
693
 
void
694
 
UnityWindowTracker_ChangeWindowDesktop(UnityWindowTracker *tracker,  // IN
695
 
                                       UnityWindowId id,             // IN
696
 
                                       UnityDesktopId desktopId)     // IN
697
 
{
698
 
   UnityWindowInfo *info;
699
 
   ASSERT(tracker);
700
 
 
701
 
   info = UnityWindowTracker_LookupWindow(tracker, id);
702
 
   if (info) {
703
 
      info->touched = TRUE;
704
 
      if (desktopId != info->desktopId) {
705
 
         info->changed |= UNITY_CHANGED_WINDOW_DESKTOP;
706
 
         info->desktopId = desktopId;
707
 
         LOG(2, ("Unity changing window (id:%u) desktop to %d\n",
708
 
                 id, desktopId));
709
 
      }
710
 
   }
711
 
}
712
 
 
713
 
 
714
 
/*
715
 
 *-----------------------------------------------------------------------------
716
 
 *
717
 
 * UnityWindowTracker_GetWindowDesktop --
718
 
 *
719
 
 *      Get the window desktop information.
720
 
 *
721
 
 * Results:
722
 
 *      TRUE if this window exists in the window tracker, desktopId contains
723
 
 *      window desktop.
724
 
 *      FALSE otherwise, desktopId undefined.
725
 
 *
726
 
 * Side effects:
727
 
 *      None
728
 
 *
729
 
 *-----------------------------------------------------------------------------
730
 
 */
731
 
 
732
 
Bool
733
 
UnityWindowTracker_GetWindowDesktop(UnityWindowTracker *tracker,  // IN
734
 
                                    UnityWindowId id,             // IN
735
 
                                    UnityDesktopId *desktopId)    // OUT
736
 
{
737
 
   Bool retval = FALSE;
738
 
   UnityWindowInfo *info;
739
 
 
740
 
   ASSERT(tracker);
741
 
   ASSERT(desktopId);
742
 
 
743
 
   info = UnityWindowTracker_LookupWindow(tracker, id);
744
 
   if (info) {
745
 
      *desktopId = info->desktopId;
746
 
      retval = TRUE;
747
 
   }
748
 
 
749
 
   return retval;
750
 
}
751
 
 
752
 
 
753
 
/*
754
 
 *-----------------------------------------------------------------------------
755
 
 *
756
 
 * UnityWindowTracker_ChangeActiveDesktop --
757
 
 *
758
 
 *      Saves the active desktop information if that was changed.
759
 
 *
760
 
 * Results:
761
 
 *      None.
762
 
 *
763
 
 * Side effects:
764
 
 *      Active desktop information might be updated.
765
 
 *
766
 
 *-----------------------------------------------------------------------------
767
 
 */
768
 
 
769
 
void
770
 
UnityWindowTracker_ChangeActiveDesktop(UnityWindowTracker *tracker,  // IN
771
 
                                       UnityDesktopId desktopId)     // IN
772
 
{
773
 
   if (desktopId != tracker->activeDesktopId) {
774
 
      tracker->activeDesktopId = desktopId;
775
 
      tracker->activeDesktopChanged = TRUE;
776
 
   }
777
 
}
778
 
 
779
 
 
780
 
/*
781
 
 *-----------------------------------------------------------------------------
782
 
 *
783
 
 * UnityWindowTracker_GetActiveDesktop --
784
 
 *
785
 
 *      Return the active desktop id.
786
 
 *
787
 
 * Results:
788
 
 *      Active desktop id.
789
 
 *
790
 
 * Side effects:
791
 
 *      None.
792
 
 *
793
 
 *-----------------------------------------------------------------------------
794
 
 */
795
 
 
796
 
UnityDesktopId
797
 
UnityWindowTracker_GetActiveDesktop(UnityWindowTracker *tracker)    // IN
798
 
{
799
 
   return tracker->activeDesktopId;
800
 
}
801
 
 
802
 
 
803
 
/*
804
 
 *----------------------------------------------------------------------------
805
 
 *
806
 
 * UnityWindowTracker_RemoveWindow --
807
 
 *
808
 
 *      Remove the window with the specified id from the tracker.
809
 
 *
810
 
 * Results:
811
 
 *      None.
812
 
 *
813
 
 * Side effects:
814
 
 *      None.
815
 
 *
816
 
 *----------------------------------------------------------------------------
817
 
 */
818
 
 
819
 
void
820
 
UnityWindowTracker_RemoveWindow(UnityWindowTracker *tracker,      // IN
821
 
                                UnityWindowId id)                 // IN
822
 
{
823
 
   UnityWindowInfo *info = UnityWindowTracker_LookupWindow(tracker, id);
824
 
   if (info) {
825
 
      LOG(2, ("Unity removing window (id:%d)\n", id));
826
 
      info->changed |= UNITY_CHANGED_REMOVED;
827
 
      info->touched = TRUE;
828
 
      /*
829
 
       * Don't remove it yet.  We can only do so later...
830
 
       */
831
 
   }
832
 
}
833
 
 
834
 
/*
835
 
 *------------------------------------------------------------------------------
836
 
 *
837
 
 * UnityWindowTracker_RemoveAllWindows --
838
 
 *
839
 
 *      Removes all the windows from the window tracker, *without* notifying
840
 
 *      the client. This function is meant to be used to "reset" the tracker
841
 
 *      state after we have exited Unity.
842
 
 *
843
 
 * Results:
844
 
 *      None.
845
 
 *
846
 
 * Side effects:
847
 
 *      None.
848
 
 *
849
 
 *------------------------------------------------------------------------------
850
 
 */
851
 
 
852
 
 
853
 
void
854
 
UnityWindowTracker_RemoveAllWindows(UnityWindowTracker *tracker)
855
 
{
856
 
   HashTable_Clear(tracker->windows);
857
 
}
858
 
 
859
 
 
860
 
/*
861
 
 *----------------------------------------------------------------------------
862
 
 *
863
 
 * UnityWindowTracker_SendUpdate --
864
 
 *
865
 
 *      Update the window tracker via a UnityUpdate structure instead
866
 
 *      of a call to AddWindow, MoveWindow, etc.  Useful for forwarding
867
 
 *      notifications between unity windows trackers without writing
868
 
 *      a ton of boilerplate.
869
 
 *
870
 
 * Results:
871
 
 *      None.
872
 
 *
873
 
 * Side effects:
874
 
 *      None.
875
 
 *
876
 
 *----------------------------------------------------------------------------
877
 
 */
878
 
 
879
 
void
880
 
UnityWindowTracker_SendUpdate(UnityWindowTracker *tracker,        // IN
881
 
                              UnityUpdate *update)                // IN
882
 
{
883
 
   switch (update->type) {
884
 
   case UNITY_UPDATE_ADD_WINDOW:
885
 
      UnityWindowTracker_AddWindow(tracker,
886
 
                                   update->u.addWindow.id,
887
 
                                   &update->u.addWindow.windowPathUtf8,
888
 
                                   &update->u.addWindow.execPathUtf8);
889
 
      break;
890
 
 
891
 
   case UNITY_UPDATE_MOVE_WINDOW:
892
 
      UnityWindowTracker_MoveWindow(tracker,
893
 
                                    update->u.moveWindow.id,
894
 
                                    update->u.moveWindow.rect.x1,
895
 
                                    update->u.moveWindow.rect.y1,
896
 
                                    update->u.moveWindow.rect.x2,
897
 
                                    update->u.moveWindow.rect.y2);
898
 
      break;
899
 
 
900
 
   case UNITY_UPDATE_REMOVE_WINDOW:
901
 
      UnityWindowTracker_RemoveWindow(tracker,
902
 
                                      update->u.removeWindow.id);
903
 
      break;
904
 
 
905
 
   case UNITY_UPDATE_CHANGE_WINDOW_REGION:
906
 
      UnityWindowTracker_ChangeWindowRegion(tracker,
907
 
                                            update->u.changeWindowRegion.id,
908
 
                                            update->u.changeWindowRegion.region);
909
 
      break;
910
 
 
911
 
   case UNITY_UPDATE_CHANGE_WINDOW_TITLE:
912
 
      UnityWindowTracker_SetWindowTitle(tracker,
913
 
                                        update->u.changeWindowTitle.id,
914
 
                                        &update->u.changeWindowTitle.titleUtf8);
915
 
      break;
916
 
 
917
 
   case UNITY_UPDATE_CHANGE_ZORDER:
918
 
      UnityWindowTracker_SetZOrder(tracker, update->u.zorder.ids,
919
 
                                   update->u.zorder.count);
920
 
      /*
921
 
       * This function is only every called from the host. Thus, if we get
922
 
       * a zorder changed event from the guest it's safe to blindly trust it
923
 
       * mark the zorder as changed. See bug 409742 for more info.
924
 
       */
925
 
      tracker->zorderChanged = TRUE;
926
 
      break;
927
 
 
928
 
   case UNITY_UPDATE_CHANGE_WINDOW_STATE:
929
 
      UnityWindowTracker_ChangeWindowState(tracker,
930
 
                                           update->u.changeWindowState.id,
931
 
                                           update->u.changeWindowState.state);
932
 
      break;
933
 
 
934
 
   case UNITY_UPDATE_CHANGE_WINDOW_ATTRIBUTE:
935
 
      UnityWindowTracker_ChangeWindowAttribute(tracker,
936
 
                                               update->u.changeWindowAttribute.id,
937
 
                                               update->u.changeWindowAttribute.attr,
938
 
                                               update->u.changeWindowAttribute.value);
939
 
      break;
940
 
 
941
 
   case UNITY_UPDATE_CHANGE_WINDOW_TYPE:
942
 
      UnityWindowTracker_ChangeWindowType(tracker,
943
 
                                          update->u.changeWindowType.id,
944
 
                                          update->u.changeWindowType.winType);
945
 
      break;
946
 
 
947
 
   case UNITY_UPDATE_CHANGE_WINDOW_ICON:
948
 
      UnityWindowTracker_NotifyIconChanged(tracker,
949
 
                                           update->u.changeWindowIcon.id,
950
 
                                           update->u.changeWindowIcon.iconType);
951
 
      break;
952
 
   case UNITY_UPDATE_CHANGE_WINDOW_DESKTOP:
953
 
      UnityWindowTracker_ChangeWindowDesktop(tracker,
954
 
                                             update->u.changeWindowDesktop.id,
955
 
                                             update->u.changeWindowDesktop.desktopId);
956
 
      break;
957
 
 
958
 
   case UNITY_UPDATE_CHANGE_ACTIVE_DESKTOP:
959
 
      UnityWindowTracker_ChangeActiveDesktop(tracker,
960
 
                                             update->u.changeActiveDesktop.desktopId);
961
 
      break;
962
 
 
963
 
   default:
964
 
      NOT_IMPLEMENTED();
965
 
   }
966
 
}
967
 
 
968
 
 
969
 
/*
970
 
 *----------------------------------------------------------------------------
971
 
 *
972
 
 * UnityWindowTracker_SetZOrder --
973
 
 *
974
 
 *      Notify the window tracker of the Z-order of all windows.  Window ids
975
 
 *      at the front of the list are at the top of the z-order.
976
 
 *
977
 
 * Results:
978
 
 *      None.
979
 
 *
980
 
 * Side effects:
981
 
 *      None.
982
 
 *
983
 
 *----------------------------------------------------------------------------
984
 
 */
985
 
 
986
 
void
987
 
UnityWindowTracker_SetZOrder(UnityWindowTracker *tracker,   // IN
988
 
                             UnityWindowId zorder[],        // IN
989
 
                             int count)                     // IN
990
 
{
991
 
   count = MIN(count, ARRAYSIZE(tracker->zorder));
992
 
 
993
 
   if ((count != tracker->count) ||
994
 
         (memcmp(tracker->zorder, zorder, count * sizeof(tracker->zorder[0])) != 0)) {
995
 
      memcpy(tracker->zorder, zorder, count * sizeof(tracker->zorder[0]));
996
 
      tracker->count = count;
997
 
      tracker->zorderChanged = TRUE;
998
 
   }
999
 
}
1000
 
 
1001
 
 
1002
 
/*
1003
 
 *----------------------------------------------------------------------------
1004
 
 *
1005
 
 * UnityWindowTracker_SetZPosition --
1006
 
 *
1007
 
 *      Notify the window tracker of the Z-order of one window.
1008
 
 *
1009
 
 * Results:
1010
 
 *      None.
1011
 
 *
1012
 
 * Side effects:
1013
 
 *      Updates the Z-ordering of the tracker.
1014
 
 *
1015
 
 *----------------------------------------------------------------------------
1016
 
 */
1017
 
 
1018
 
void
1019
 
UnityWindowTracker_SetZPosition(UnityWindowTracker *tracker, // IN
1020
 
                                UnityWindowId id,            // IN
1021
 
                                uint32 zorder)               // IN
1022
 
{
1023
 
   int newIndex, oldIndex;
1024
 
 
1025
 
   /* First, figure out where the window will be in the list */
1026
 
   switch(zorder) {
1027
 
   case UNITY_WINDOW_ORDER_BOTTOM:
1028
 
      newIndex = tracker->count - 1;
1029
 
      break;
1030
 
   case UNITY_WINDOW_ORDER_TOP:
1031
 
   default:
1032
 
      newIndex = zorder;
1033
 
      break;
1034
 
   }
1035
 
 
1036
 
   /* Then, find where the window is the list. If it's not there, it's an error. */
1037
 
   for (oldIndex = 0; oldIndex < tracker->count; oldIndex++) {
1038
 
      if (id == tracker->zorder[oldIndex]) {
1039
 
         break;
1040
 
      }
1041
 
   }
1042
 
   ASSERT(oldIndex < tracker->count);
1043
 
 
1044
 
   /* Next, make space for the WindowId at its new spot */
1045
 
   if (newIndex < oldIndex) {
1046
 
      memmove(tracker->zorder + newIndex + 1, tracker->zorder + newIndex,
1047
 
              oldIndex - newIndex);
1048
 
   } else if (newIndex > oldIndex) {
1049
 
      memmove(tracker->zorder + oldIndex, tracker->zorder + oldIndex + 1,
1050
 
              newIndex - oldIndex);
1051
 
   }
1052
 
 
1053
 
   /* Finally, put it in place */
1054
 
   tracker->zorder[newIndex] = id;
1055
 
   tracker->zorderChanged = TRUE;
1056
 
}
1057
 
 
1058
 
 
1059
 
/*
1060
 
 *----------------------------------------------------------------------------
1061
 
 *
1062
 
 * UnityWindowTracker_RequestUpdates --
1063
 
 *
1064
 
 *      Request a summary of all the updates pushed into the window tracker
1065
 
 *      since the last call to UnityWindowTracker_RequestUpdates.
1066
 
 *
1067
 
 *      If UNITY_UPDATE_INCREMENTAL is set in flags, callbacks will only
1068
 
 *      fire for elements which have changed since the last call to
1069
 
 *      UnityWindowTracker_RequestUpdates.  Otherwise the entire state of
1070
 
 *      the window tracker is sent via the callbacks.
1071
 
 *
1072
 
 *      If UNITY_UPDATE_REMOVE_UNTOUCHED is set in flags, windows for
1073
 
 *      which there have been no updates since the last
1074
 
 *      UnityWindowTracker_RequestUpdates call will be automatically removed.
1075
 
 *      Useful if the client has no way of getting remove window notifications.
1076
 
 *
1077
 
 * Results:
1078
 
 *      None.
1079
 
 *
1080
 
 * Side effects:
1081
 
 *      Lots of callbacks are fired.
1082
 
 *
1083
 
 *----------------------------------------------------------------------------
1084
 
 */
1085
 
 
1086
 
void
1087
 
UnityWindowTracker_RequestUpdates(UnityWindowTracker *tracker, // IN
1088
 
                                  uint32 flags,                // IN
1089
 
                                  void *param)                 // IN
1090
 
{
1091
 
   tracker->cbparam = param;
1092
 
   tracker->updateFlags = flags;
1093
 
 
1094
 
   /*
1095
 
    * If necessary, remove windows which didn't receive updates.
1096
 
    */
1097
 
   if (flags & UNITY_UPDATE_REMOVE_UNTOUCHED) {
1098
 
      HashTable_ForEach(tracker->windows, RemoveUntouchedWindow, tracker);
1099
 
   }
1100
 
 
1101
 
   /*
1102
 
    * Push updates for the windows remaining...
1103
 
    * We push removed windows last to prevent temporary periods where a guest
1104
 
    * app has no windows.
1105
 
    */
1106
 
   HashTable_ForEach(tracker->windows, PushUpdates, tracker);
1107
 
   HashTable_ForEach(tracker->windows, PushRemoveWindow, tracker);
1108
 
 
1109
 
   /* Push Z order */
1110
 
   PushZOrder(tracker);
1111
 
 
1112
 
   /* Push active desktop info */
1113
 
   PushActiveDesktop(tracker);
1114
 
 
1115
 
   /*
1116
 
    * ...then really delete things which were removed...
1117
 
    */
1118
 
   while (HashTable_ForEach(tracker->windows, GarbageCollectRemovedWindows,
1119
 
          tracker)) {
1120
 
      continue;
1121
 
   }
1122
 
 
1123
 
   /*
1124
 
    * ...and clear all the changed and touched bits of what's left to get ready
1125
 
    * for the next iteration.
1126
 
    */
1127
 
   HashTable_ForEach(tracker->windows, ResetChangedBits, NULL);
1128
 
}
1129
 
 
1130
 
 
1131
 
/*
1132
 
 *----------------------------------------------------------------------------
1133
 
 *
1134
 
 * FreeWindowInfo --
1135
 
 *
1136
 
 *      Destroy a window.
1137
 
 *
1138
 
 * Results:
1139
 
 *      None.
1140
 
 *
1141
 
 * Side effects:
1142
 
 *      None.
1143
 
 *
1144
 
 *----------------------------------------------------------------------------
1145
 
 */
1146
 
 
1147
 
static void
1148
 
FreeWindowInfo(UnityWindowInfo *info)              // IN
1149
 
{
1150
 
   if (info) {
1151
 
      UnityWindowTracker *tracker = info->tracker;
1152
 
 
1153
 
      if (tracker->freeFn && info->data) {
1154
 
         tracker->freeFn(tracker, info, info->data);
1155
 
      }
1156
 
 
1157
 
      if (info->region) {
1158
 
         miRegionDestroy(info->region);
1159
 
      }
1160
 
      DynBuf_Destroy(&info->titleUtf8);
1161
 
      DynBuf_Destroy(&info->windowPathUtf8);
1162
 
      DynBuf_Destroy(&info->execPathUtf8);
1163
 
      free(info);
1164
 
   }
1165
 
}
1166
 
 
1167
 
 
1168
 
/*
1169
 
 *----------------------------------------------------------------------------
1170
 
 *
1171
 
 * RemoveUntouchedWindow --
1172
 
 *
1173
 
 *      If the window specified hasn't been touched (i.e. an update function
1174
 
 *      has been called on it), remove it from the window tracker.
1175
 
 *
1176
 
 * Results:
1177
 
 *      None.
1178
 
 *
1179
 
 * Side effects:
1180
 
 *      None.
1181
 
 *
1182
 
 *----------------------------------------------------------------------------
1183
 
 */
1184
 
 
1185
 
int
1186
 
RemoveUntouchedWindow(const char *key,       // IN: window id
1187
 
                      void *value,           // IN: UnityWindowInfo
1188
 
                      void *clientData)      // IN: UnityWindowTracker
1189
 
{
1190
 
   UnityWindowTracker *tracker = (UnityWindowTracker *)clientData;
1191
 
   UnityWindowInfo *info = (UnityWindowInfo *)value;
1192
 
   if (!info->touched) {
1193
 
      UnityWindowId id = (UnityWindowId)(long)key;
1194
 
      LOG(2, ("Removing untouched window (id:%d)\n", id));
1195
 
      UnityWindowTracker_RemoveWindow(tracker, id);
1196
 
   }
1197
 
   return 0;
1198
 
}
1199
 
 
1200
 
 
1201
 
/*
1202
 
 *----------------------------------------------------------------------------
1203
 
 *
1204
 
 * GarbageCollectRemovedWindows --
1205
 
 *
1206
 
 *      Delete all window objects for windows which are marked as
1207
 
 *      removed.
1208
 
 *
1209
 
 * Results:
1210
 
 *      None.
1211
 
 *
1212
 
 * Side effects:
1213
 
 *      None.
1214
 
 *
1215
 
 *----------------------------------------------------------------------------
1216
 
 */
1217
 
 
1218
 
int
1219
 
GarbageCollectRemovedWindows(const char *key,       // IN: window id
1220
 
                             void *value,           // IN: UnityWindowInfo
1221
 
                             void *clientData)      // IN: UnityWindowTracker
1222
 
{
1223
 
   UnityWindowTracker *tracker = (UnityWindowTracker *)clientData;
1224
 
   UnityWindowInfo *info = (UnityWindowInfo *)value;
1225
 
   if (info->reap) {
1226
 
      LOG(2, ("Destroying window (id:%d)\n", (UnityWindowId)(long)key));
1227
 
      HashTable_Delete(tracker->windows, key);
1228
 
      return 1;
1229
 
   }
1230
 
   return 0;
1231
 
}
1232
 
 
1233
 
 
1234
 
/*
1235
 
 *----------------------------------------------------------------------------
1236
 
 *
1237
 
 * ResetChangedBits --
1238
 
 *
1239
 
 *      Reset the changed and touched bits for this window.
1240
 
 *
1241
 
 * Results:
1242
 
 *      None.
1243
 
 *
1244
 
 * Side effects:
1245
 
 *      None.
1246
 
 *
1247
 
 *----------------------------------------------------------------------------
1248
 
 */
1249
 
 
1250
 
int
1251
 
ResetChangedBits(const char *key,       // IN: window id
1252
 
                 void *value,           // IN: UnityWindowInfo
1253
 
                 void *clientData)      // IN: UnityWindowTracker
1254
 
{
1255
 
   UnityWindowInfo *info = (UnityWindowInfo *)value;
1256
 
   int i;
1257
 
 
1258
 
   if (info->changed & UNITY_CHANGED_WINDOW_ATTRIBUTES) {
1259
 
      for (i = 0; i < UNITY_MAX_ATTRIBUTES; i++) {
1260
 
         info->attributes[i] &= ~UNITY_INFO_ATTR_CHANGED;
1261
 
      }
1262
 
   }
1263
 
 
1264
 
   if (info->changed & UNITY_CHANGED_WINDOW_ICONS) {
1265
 
      for (i = 0; i < UNITY_MAX_ICONS; i++) {
1266
 
         info->icons[i] &= ~UNITY_INFO_ATTR_CHANGED;
1267
 
      }
1268
 
   }
1269
 
 
1270
 
   info->changed = 0;
1271
 
   info->touched = FALSE;
1272
 
   return 0;
1273
 
}
1274
 
 
1275
 
 
1276
 
/*
1277
 
 *----------------------------------------------------------------------------
1278
 
 *
1279
 
 * PushRemoveWindow --
1280
 
 *
1281
 
 *      Sends a remove window update for this window.
1282
 
 *
1283
 
 * Results:
1284
 
 *      None.
1285
 
 *
1286
 
 * Side effects:
1287
 
 *      None.
1288
 
 *
1289
 
 *----------------------------------------------------------------------------
1290
 
 */
1291
 
 
1292
 
int
1293
 
PushRemoveWindow(const char *key,       // IN: window id
1294
 
                 void *value,           // IN: UnityWindowInfo
1295
 
                 void *clientData)      // IN: UnityWindowTracker
1296
 
{
1297
 
   UnityWindowInfo *info = (UnityWindowInfo *)value;
1298
 
 
1299
 
   if (info->changed & UNITY_CHANGED_REMOVED) {
1300
 
      UnityWindowTracker *tracker = (UnityWindowTracker *)clientData;
1301
 
      UnityWindowId id = (UnityWindowId)(long)key;
1302
 
      UnityUpdate update;
1303
 
 
1304
 
      /*
1305
 
       * Now that we've sent the update, mark the window as deleted
1306
 
       * so it will be reaped.
1307
 
       */
1308
 
      info->reap = TRUE;
1309
 
      update.type = UNITY_UPDATE_REMOVE_WINDOW;
1310
 
      update.u.removeWindow.id = id;
1311
 
      (*tracker->cb)(tracker->cbparam, &update);
1312
 
   }
1313
 
 
1314
 
   return 0;
1315
 
}
1316
 
 
1317
 
 
1318
 
/*
1319
 
 *----------------------------------------------------------------------------
1320
 
 *
1321
 
 * PushUpdates --
1322
 
 *
1323
 
 *      Fire all callback functions relevant for this window (as determined
1324
 
 *      by the changed bits).
1325
 
 *
1326
 
 * Results:
1327
 
 *      None.
1328
 
 *
1329
 
 * Side effects:
1330
 
 *      None.
1331
 
 *
1332
 
 *----------------------------------------------------------------------------
1333
 
 */
1334
 
 
1335
 
int
1336
 
PushUpdates(const char *key,       // IN: window id
1337
 
            void *value,           // IN: UnityWindowInfo
1338
 
            void *clientData)      // IN: UnityWindowTracker
1339
 
{
1340
 
   UnityWindowTracker *tracker = (UnityWindowTracker *)clientData;
1341
 
   UnityWindowInfo *info = (UnityWindowInfo *)value;
1342
 
   UnityWindowId id = (UnityWindowId)(long)key;
1343
 
   UnityUpdate update;
1344
 
   Bool incremental = (tracker->updateFlags & UNITY_UPDATE_INCREMENTAL) != 0;
1345
 
 
1346
 
   if (info->changed & UNITY_CHANGED_REMOVED) {
1347
 
      // This is handled in PushRemoveWindow.
1348
 
      return 0;
1349
 
   }
1350
 
 
1351
 
   if (!incremental || (info->changed & UNITY_CHANGED_ADDED)) {
1352
 
      update.type = UNITY_UPDATE_ADD_WINDOW;
1353
 
      update.u.addWindow.id = id;
1354
 
      DynBuf_Init(&update.u.addWindow.windowPathUtf8);
1355
 
      DynBuf_Init(&update.u.addWindow.execPathUtf8);
1356
 
      if (DynBuf_GetSize(&info->windowPathUtf8)) {
1357
 
         DynBuf_Copy(&info->windowPathUtf8, &update.u.addWindow.windowPathUtf8);
1358
 
      }
1359
 
      if (DynBuf_GetSize(&info->execPathUtf8)) {
1360
 
         DynBuf_Copy(&info->execPathUtf8, &update.u.addWindow.execPathUtf8);
1361
 
      }
1362
 
      (*tracker->cb)(tracker->cbparam, &update);
1363
 
      DynBuf_Destroy(&update.u.addWindow.windowPathUtf8);
1364
 
      DynBuf_Destroy(&update.u.addWindow.execPathUtf8);
1365
 
   }
1366
 
   if (!incremental || (info->changed & UNITY_CHANGED_POSITION)) {
1367
 
      update.type = UNITY_UPDATE_MOVE_WINDOW;
1368
 
      update.u.moveWindow.id = id;
1369
 
      update.u.moveWindow.rect = info->rect;
1370
 
      (*tracker->cb)(tracker->cbparam, &update);
1371
 
   }
1372
 
   if (!incremental || (info->changed & UNITY_CHANGED_REGION)) {
1373
 
      update.type = UNITY_UPDATE_CHANGE_WINDOW_REGION;
1374
 
      update.u.changeWindowRegion.id = id;
1375
 
      update.u.changeWindowRegion.region = info->region;
1376
 
      (*tracker->cb)(tracker->cbparam, &update);
1377
 
   }
1378
 
   if (!incremental || (info->changed & UNITY_CHANGED_TITLE)) {
1379
 
      update.type = UNITY_UPDATE_CHANGE_WINDOW_TITLE;
1380
 
      update.u.changeWindowTitle.id = id;
1381
 
      DynBuf_Init(&update.u.changeWindowTitle.titleUtf8);
1382
 
      DynBuf_Copy(&info->titleUtf8, &update.u.changeWindowTitle.titleUtf8);
1383
 
      (*tracker->cb)(tracker->cbparam, &update);
1384
 
      DynBuf_Destroy(&update.u.changeWindowTitle.titleUtf8);
1385
 
   }
1386
 
   if (!incremental || (info->changed & UNITY_CHANGED_WINDOW_ICONS)) {
1387
 
      UnityIconType i;
1388
 
 
1389
 
      update.type = UNITY_UPDATE_CHANGE_WINDOW_ICON;
1390
 
      update.u.changeWindowIcon.id = id;
1391
 
      for (i = 0; i < UNITY_MAX_ICONS; i++) {
1392
 
         if ((info->icons[i] & UNITY_INFO_ATTR_EXISTS)
1393
 
             && (!incremental
1394
 
                 || (info->icons[i] & UNITY_INFO_ATTR_CHANGED))) {
1395
 
            update.u.changeWindowIcon.iconType = i;
1396
 
            (*tracker->cb)(tracker->cbparam, &update);
1397
 
         }
1398
 
      }
1399
 
   }
1400
 
   if (!incremental || (info->changed & UNITY_CHANGED_WINDOW_TYPE)) {
1401
 
      update.type = UNITY_UPDATE_CHANGE_WINDOW_TYPE;
1402
 
      update.u.changeWindowType.id = id;
1403
 
      update.u.changeWindowType.winType = info->type;
1404
 
      (*tracker->cb)(tracker->cbparam, &update);
1405
 
   }
1406
 
 
1407
 
   /*
1408
 
    * Please make sure WINDOW_ATTRIBUTES is checked before WINDOW_STATE, to allow
1409
 
    * vmware-vmx on the host side to only pay attention to WINDOW_ATTRIBUTES if
1410
 
    * desired.
1411
 
    */
1412
 
   if (!incremental || (info->changed & UNITY_CHANGED_WINDOW_ATTRIBUTES)) {
1413
 
      UnityWindowAttribute i;
1414
 
 
1415
 
      update.type = UNITY_UPDATE_CHANGE_WINDOW_ATTRIBUTE;
1416
 
      update.u.changeWindowAttribute.id = id;
1417
 
      for (i = 0; i < UNITY_MAX_ATTRIBUTES; i++) {
1418
 
         if ((info->attributes[i] & UNITY_INFO_ATTR_EXISTS)
1419
 
             && (!incremental ||
1420
 
                 (info->attributes[i] & UNITY_INFO_ATTR_CHANGED))) {
1421
 
            update.u.changeWindowAttribute.attr = i;
1422
 
            update.u.changeWindowAttribute.value =
1423
 
               (info->attributes[i] & UNITY_INFO_ATTR_ENABLED) ? TRUE : FALSE;
1424
 
            (*tracker->cb)(tracker->cbparam, &update);
1425
 
         }
1426
 
      }
1427
 
   }
1428
 
 
1429
 
   if (!incremental || (info->changed & UNITY_CHANGED_WINDOW_STATE)) {
1430
 
      update.type = UNITY_UPDATE_CHANGE_WINDOW_STATE;
1431
 
      update.u.changeWindowState.id = id;
1432
 
      update.u.changeWindowState.state = info->state;
1433
 
      (*tracker->cb)(tracker->cbparam, &update);
1434
 
   }
1435
 
 
1436
 
   if (!incremental || (info->changed & UNITY_CHANGED_WINDOW_DESKTOP)) {
1437
 
      update.type = UNITY_UPDATE_CHANGE_WINDOW_DESKTOP;
1438
 
      update.u.changeWindowDesktop.id = id;
1439
 
      update.u.changeWindowDesktop.desktopId = info->desktopId;
1440
 
      (*tracker->cb)(tracker->cbparam, &update);
1441
 
   }
1442
 
 
1443
 
   return 0;
1444
 
}
1445
 
 
1446
 
 
1447
 
/*
1448
 
 *----------------------------------------------------------------------------
1449
 
 *
1450
 
 * PushZOrder --
1451
 
 *
1452
 
 *      Fire callback function if Z Order was changed
1453
 
 *
1454
 
 * Results:
1455
 
 *      None.
1456
 
 *
1457
 
 * Side effects:
1458
 
 *      None.
1459
 
 *
1460
 
 *----------------------------------------------------------------------------
1461
 
 */
1462
 
 
1463
 
int
1464
 
PushZOrder(UnityWindowTracker *tracker)     // IN: UnityWindowTracker
1465
 
{
1466
 
   UnityUpdate update;
1467
 
   Bool incremental = (tracker->updateFlags & UNITY_UPDATE_INCREMENTAL) != 0;
1468
 
   if (!incremental || tracker->zorderChanged) {
1469
 
      update.type = UNITY_UPDATE_CHANGE_ZORDER;
1470
 
      update.u.zorder.count = tracker->count;
1471
 
      memcpy(&update.u.zorder.ids, tracker->zorder,
1472
 
             tracker->count * sizeof(update.u.zorder.ids[0]));
1473
 
      (*tracker->cb)(tracker->cbparam, &update);
1474
 
 
1475
 
      tracker->zorderChanged = FALSE;
1476
 
   }
1477
 
   return 0;
1478
 
}
1479
 
 
1480
 
 
1481
 
/*
1482
 
 *----------------------------------------------------------------------------
1483
 
 *
1484
 
 * PushActiveDesktop --
1485
 
 *
1486
 
 *      Fire callback function if the active desktop was changed.
1487
 
 *
1488
 
 * Results:
1489
 
 *      None.
1490
 
 *
1491
 
 * Side effects:
1492
 
 *      None.
1493
 
 *
1494
 
 *----------------------------------------------------------------------------
1495
 
 */
1496
 
 
1497
 
int
1498
 
PushActiveDesktop(UnityWindowTracker *tracker)     // IN: UnityWindowTracker
1499
 
{
1500
 
   UnityUpdate update;
1501
 
   Bool incremental = (tracker->updateFlags & UNITY_UPDATE_INCREMENTAL) != 0;
1502
 
   if (!incremental || tracker->activeDesktopChanged) {
1503
 
      update.type = UNITY_UPDATE_CHANGE_ACTIVE_DESKTOP;
1504
 
      update.u.changeActiveDesktop.desktopId = tracker->activeDesktopId;
1505
 
      (*tracker->cb)(tracker->cbparam, &update);
1506
 
 
1507
 
      tracker->activeDesktopChanged = FALSE;
1508
 
   }
1509
 
   return 0;
1510
 
}
1511
 
 
1512
 
 
1513
 
/*
1514
 
 *----------------------------------------------------------------------------
1515
 
 *
1516
 
 * TitlesEqual--
1517
 
 *
1518
 
 *      Performs string comparison on the titles held in DynBufs
1519
 
 *
1520
 
 * Results:
1521
 
 *       TRUE  if first == second
1522
 
 *       FALSE if first != second
1523
 
 *
1524
 
 * Side effects:
1525
 
 *      None.
1526
 
 *
1527
 
 *----------------------------------------------------------------------------
1528
 
 */
1529
 
 
1530
 
Bool
1531
 
TitlesEqual(DynBuf *first,       // IN: First window title
1532
 
            DynBuf *second)      // IN: Second window title
1533
 
{
1534
 
   if (DynBuf_GetSize(first) != DynBuf_GetSize(second)) {
1535
 
      return FALSE;
1536
 
   }
1537
 
   return (strncmp((const unsigned char*)DynBuf_Get(first),
1538
 
                   (const unsigned char*)DynBuf_Get(second),
1539
 
                   DynBuf_GetSize(first)) == 0) ? TRUE : FALSE;
1540
 
}
1541
 
 
1542
 
 
1543
 
/*
1544
 
 *-----------------------------------------------------------------------------
1545
 
 *
1546
 
 * UnityWindowTracker_ParseUnityUpdate --
1547
 
 *
1548
 
 *      Validate and parse Unity update command strings. The caller
1549
 
 *      should pass in a UnityUpdateCallback function (see lib/public/
1550
 
 *      unityWindowTracker.h).  The callback will fire once for each
1551
 
 *      window update in the result string.
1552
 
 *
1553
 
 * Results:
1554
 
 *      None
1555
 
 *
1556
 
 * Side effects:
1557
 
 *      None
1558
 
 *
1559
 
 *-----------------------------------------------------------------------------
1560
 
 */
1561
 
 
1562
 
void
1563
 
UnityWindowTracker_ParseUnityUpdate(const char *result,     // IN
1564
 
                                    int len,                // IN
1565
 
                                    UnityUpdateCallback cb, // IN
1566
 
                                    void *param)            // IN
1567
 
{
1568
 
   if (result && len > 1) {
1569
 
      uint32 id = 0;
1570
 
      int x1, y1, x2, y2;
1571
 
      const char *buf;
1572
 
 
1573
 
      /*
1574
 
       * Protect against malicious guests.  If the string is not double
1575
 
       * null terminated, ignore it completely.
1576
 
       */
1577
 
 
1578
 
      if (result[len - 1] || result[len - 2]) {
1579
 
         Warning("%s called with non-double null terminated string!\n",
1580
 
                 __FUNCTION__);
1581
 
 
1582
 
         return;
1583
 
      }
1584
 
 
1585
 
      /*
1586
 
       * Parse the result
1587
 
       */
1588
 
 
1589
 
      for (buf = result; *buf; buf += strlen(buf) + 1) {
1590
 
         UnityUpdate update;
1591
 
         Bool ok = FALSE;
1592
 
 
1593
 
         if (StrUtil_StartsWith(buf, "add ")) {
1594
 
            const char *argumentStart = buf + strlen("add ");
1595
 
            unsigned int index = 0;
1596
 
 
1597
 
            DynBuf_Init(&update.u.addWindow.windowPathUtf8);
1598
 
            DynBuf_Init(&update.u.addWindow.execPathUtf8);
1599
 
 
1600
 
            /*
1601
 
             * The arguments take the form 'add <id> [arguments]' where [arguments] are
1602
 
             * space seperated 'key=value' pairs, if an argument is simply key= the value
1603
 
             * should be treated as an empty string.
1604
 
             * Only the <id> may be present if the guest is running certain older
1605
 
             * versions of tools.
1606
 
             */
1607
 
            ok = StrUtil_GetNextUintToken(&id, &index, argumentStart, " ");
1608
 
 
1609
 
            /*
1610
 
             * If we failed to get the required <id> argument there's little point
1611
 
             * carrying on. However failure to receive any of the following arguments
1612
 
             * is not an error (they're optional) - it's also not an error to get
1613
 
             * an expected key here since we may well add new keys in the future and
1614
 
             * don't want to log needless error messages if the host hasn't been updated
1615
 
             * to match.
1616
 
             */
1617
 
            if (ok) {
1618
 
               char *field;
1619
 
               update.type = UNITY_UPDATE_ADD_WINDOW;
1620
 
               update.u.addWindow.id = id;
1621
 
               while ((field = StrUtil_GetNextToken(&index, argumentStart, " "))) {
1622
 
 
1623
 
                  if (StrUtil_StartsWith(field, "windowPath=")) {
1624
 
                     ok = DynBuf_AppendString(&update.u.addWindow.windowPathUtf8,
1625
 
                                              field + strlen("windowPath="));
1626
 
                  }
1627
 
 
1628
 
                  if (StrUtil_StartsWith(field, "execPath=")) {
1629
 
                     ok = DynBuf_AppendString(&update.u.addWindow.execPathUtf8,
1630
 
                                              field + strlen("execPath="));
1631
 
                  }
1632
 
 
1633
 
                  /*
1634
 
                   * Free the results of the tokenization (field)
1635
 
                   */
1636
 
                  free(field);
1637
 
               }
1638
 
            } else {
1639
 
               LOG(0, ("TOOLS Expected window id but no id found in string.\n"));
1640
 
            }
1641
 
         } else if (StrUtil_StartsWith(buf, "remove ")) {
1642
 
            if (sscanf(buf, "remove %u", &id) == 1) {
1643
 
               update.type = UNITY_UPDATE_REMOVE_WINDOW;
1644
 
               update.u.removeWindow.id = id;
1645
 
               ok = TRUE;
1646
 
            }
1647
 
         } else if (StrUtil_StartsWith(buf, "move ")) {
1648
 
            if (sscanf(buf, "move %u %d %d %d %d", &id, &x1, &y1,
1649
 
                       &x2, &y2) == 5) {
1650
 
               update.type = UNITY_UPDATE_MOVE_WINDOW;
1651
 
               update.u.moveWindow.id = id;
1652
 
               RECT_SETRECT(&update.u.moveWindow.rect, x1, y1, x2, y2);
1653
 
               ok = TRUE;
1654
 
            }
1655
 
         } else if (StrUtil_StartsWith(buf, "title ")) {
1656
 
            const char *titleInfo = buf + 6;
1657
 
 
1658
 
            /* StrUtil_* functions do not like NULL strings. */
1659
 
            if (*titleInfo) {
1660
 
               unsigned int index = 0;
1661
 
               if (StrUtil_GetNextUintToken(&id, &index, titleInfo, " ")) {
1662
 
                  char *titleUtf8 = NULL;
1663
 
                  update.u.changeWindowTitle.id = id;
1664
 
 
1665
 
                  if (titleInfo[index] == ' ') {
1666
 
                     index++; // Skip the space
1667
 
                     if (titleInfo[index]) {
1668
 
                        titleUtf8 = StrUtil_GetNextToken(&index, titleInfo,
1669
 
                                                         "");
1670
 
                     }
1671
 
                  }
1672
 
                  if (!titleUtf8) {
1673
 
                     titleUtf8 = Util_SafeStrdup("");
1674
 
                  }
1675
 
 
1676
 
                  DynBuf_Init(&update.u.changeWindowTitle.titleUtf8);
1677
 
                  if (DynBuf_AppendString(&update.u.changeWindowTitle.titleUtf8,
1678
 
                                          titleUtf8)) {
1679
 
                     update.type = UNITY_UPDATE_CHANGE_WINDOW_TITLE;
1680
 
                     ok = TRUE;
1681
 
                  }
1682
 
                  free(titleUtf8);
1683
 
               } else {
1684
 
                  LOG(0,
1685
 
                      ("TOOLS Malformed title string, couldn't get the window id.\n"));
1686
 
               }
1687
 
            } else {
1688
 
               LOG(0, ("TOOLS Empty title string, couldn't get the title.\n"));
1689
 
            }
1690
 
         } else if (StrUtil_StartsWith(buf, "zorder ")) {
1691
 
            int count = 0;
1692
 
            int i = 0;
1693
 
            const char *bufPtr = buf;
1694
 
            bufPtr = strchr(bufPtr, ' ');
1695
 
            if (sscanf(bufPtr, " %d", &count) == 1) {
1696
 
               count = MIN(count, ARRAYSIZE(update.u.zorder.ids));
1697
 
               bufPtr = strchr(++bufPtr, ' ');
1698
 
               while (bufPtr && *bufPtr && i < count &&
1699
 
                        sscanf(bufPtr, " %u", update.u.zorder.ids + i) == 1) {
1700
 
                  i++;
1701
 
                  bufPtr = strchr(++bufPtr, ' ');
1702
 
               }
1703
 
               if (i == count) {
1704
 
                  update.type = UNITY_UPDATE_CHANGE_ZORDER;
1705
 
                  update.u.zorder.count = count;
1706
 
                  ok = TRUE;
1707
 
               } else {
1708
 
                  LOG(0, ("TOOLS Expected %d but received %d in zorder string.\n",
1709
 
                          count, i));
1710
 
               }
1711
 
            } else {
1712
 
               LOG(0, ("TOOLS Malformed zorder string, couldn't scan count.\n"));
1713
 
            }
1714
 
         } else if (StrUtil_StartsWith(buf, "region ")) {
1715
 
            int current = 0, numRects;
1716
 
            if (sscanf(buf, "region %u %d", &id, &numRects) == 2) {
1717
 
               RegionPtr region = NULL;
1718
 
 
1719
 
               update.type = UNITY_UPDATE_CHANGE_WINDOW_REGION;
1720
 
               update.u.changeWindowRegion.region = NULL;
1721
 
               update.u.changeWindowRegion.id = id;
1722
 
 
1723
 
               if (numRects) {
1724
 
                  BoxRec rc;
1725
 
                  RECT_SETRECT(&rc, 0, 0, 0, 0);
1726
 
                  region = miRegionCreate(&rc, 0);
1727
 
 
1728
 
                  do {
1729
 
                     buf += strlen(buf) + 1;
1730
 
                     current++;
1731
 
                     if (sscanf(buf, "rect %d %d %d %d", &x1, &y1, &x2, &y2) == 4) {
1732
 
                        RECT_SETRECT(&rc, x1, y1, x2, y2);
1733
 
                        miApplyRect(region, region, &rc, miUnion);
1734
 
                     } else {
1735
 
                        Warning("Malformed processing unity region" \
1736
 
                                " (attempting to continue): %s.\n",
1737
 
                                buf);
1738
 
                     }
1739
 
                  } while (current < numRects && *buf);
1740
 
               }
1741
 
               update.u.changeWindowRegion.region = region;
1742
 
               ok = TRUE;
1743
 
            } else {
1744
 
               Warning("Malformed processing unity region %s.\n", buf);
1745
 
            }
1746
 
         } else if (StrUtil_StartsWith(buf, "state ")) {
1747
 
            uint32 state = 0;
1748
 
 
1749
 
            update.type = UNITY_UPDATE_CHANGE_WINDOW_STATE;
1750
 
            if (sscanf(buf, "state %u %d", &id, &state) == 2) {
1751
 
               update.u.changeWindowState.id = id;
1752
 
               update.u.changeWindowState.state = state;
1753
 
               ok = TRUE;
1754
 
            }
1755
 
         } else if (StrUtil_StartsWith(buf, "attr ")) {
1756
 
            update.type = UNITY_UPDATE_CHANGE_WINDOW_ATTRIBUTE;
1757
 
            if (sscanf(buf, "attr %u %u %u",
1758
 
                       &update.u.changeWindowAttribute.id,
1759
 
                       (unsigned int *)&update.u.changeWindowAttribute.attr,
1760
 
                       &update.u.changeWindowAttribute.value) == 3 &&
1761
 
                update.u.changeWindowAttribute.attr < UNITY_MAX_ATTRIBUTES) {
1762
 
               ok = TRUE;
1763
 
            }
1764
 
         } else if (StrUtil_StartsWith(buf, "type ")) {
1765
 
            update.type = UNITY_UPDATE_CHANGE_WINDOW_TYPE;
1766
 
            if (sscanf(buf, "type %u %d", &update.u.changeWindowType.id,
1767
 
                       (int *)&update.u.changeWindowType.winType) == 2 &&
1768
 
                update.u.changeWindowType.winType < UNITY_MAX_WINDOW_TYPES) {
1769
 
               ok = TRUE;
1770
 
            }
1771
 
         } else if (StrUtil_StartsWith(buf, "icon ")) {
1772
 
            update.type = UNITY_UPDATE_CHANGE_WINDOW_ICON;
1773
 
            if (sscanf(buf, "icon %u %u", &update.u.changeWindowIcon.id,
1774
 
                       (unsigned int *)&update.u.changeWindowIcon.iconType) == 2 &&
1775
 
                update.u.changeWindowIcon.iconType < UNITY_MAX_ICONS) {
1776
 
               ok = TRUE;
1777
 
            }
1778
 
         } else if (StrUtil_StartsWith(buf, "desktop ")) {
1779
 
            update.type = UNITY_UPDATE_CHANGE_WINDOW_DESKTOP;
1780
 
            if (sscanf(buf, "desktop %u %d", &update.u.changeWindowDesktop.id,
1781
 
               &update.u.changeWindowDesktop.desktopId) == 2) {
1782
 
               ok = TRUE;
1783
 
            }
1784
 
         } else if (StrUtil_StartsWith(buf, "activedesktop ")) {
1785
 
            update.type = UNITY_UPDATE_CHANGE_ACTIVE_DESKTOP;
1786
 
            if (sscanf(buf, "activedesktop %d",
1787
 
                       &update.u.changeActiveDesktop.desktopId) == 1) {
1788
 
               ok = TRUE;
1789
 
            }
1790
 
         }
1791
 
 
1792
 
         if (ok) {
1793
 
            (*cb)(param, &update);
1794
 
         } else {
1795
 
            Warning("Malformed unity response string: %s.\n", buf);
1796
 
         }
1797
 
 
1798
 
         if (ok && (update.type == UNITY_UPDATE_ADD_WINDOW)) {
1799
 
            DynBuf_Destroy(&update.u.addWindow.windowPathUtf8);
1800
 
            DynBuf_Destroy(&update.u.addWindow.execPathUtf8);
1801
 
         }
1802
 
 
1803
 
         if (ok && (update.type == UNITY_UPDATE_CHANGE_WINDOW_TITLE)) {
1804
 
            DynBuf_Destroy(&update.u.changeWindowTitle.titleUtf8);
1805
 
         }
1806
 
 
1807
 
         if (ok &&
1808
 
             (update.type == UNITY_UPDATE_CHANGE_WINDOW_REGION) &&
1809
 
             (update.u.changeWindowRegion.region != NULL)) {
1810
 
            miRegionDestroy(update.u.changeWindowRegion.region);
1811
 
         }
1812
 
      }
1813
 
   }
1814
 
}