~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: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

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
}