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

« back to all changes in this revision

Viewing changes to services/plugins/unity/ghIntegration/icon.cc

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

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

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*********************************************************
2
 
 * Copyright (C) 2010 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
 
 * icon.c --
21
 
 *
22
 
 *      GHI/X11 icon collection code.
23
 
 */
24
 
 
25
 
 
26
 
#include <math.h>
27
 
 
28
 
#include <gtk/gtk.h>
29
 
#include <glib.h>
30
 
#include <gio/gdesktopappinfo.h>
31
 
 
32
 
extern "C" {
33
 
#include "vmware.h"
34
 
#include "guest_msg_def.h"
35
 
}
36
 
 
37
 
#include "ghiX11icon.h"
38
 
 
39
 
 
40
 
/*
41
 
 * GHI/X11 still pumps icons over GuestMsg, which limits us to 64K.  Until we
42
 
 * switch transports, we'll have to scale down icons to fit within limits.
43
 
 */
44
 
 
45
 
static const size_t MAX_ICON_SIZE = GUESTMSG_MAX_IN_SIZE - 1024;
46
 
 
47
 
 
48
 
/*
49
 
 * Local function declarations.
50
 
 */
51
 
 
52
 
static void  AppendFileToArray(const gchar* iconPath,
53
 
                               std::list<GHIBinaryIconInfo>& iconList);
54
 
static void  AppendPixbufToArray(const GdkPixbuf* pixbuf,
55
 
                                 std::list<GHIBinaryIconInfo>& iconList,
56
 
                                 bool scaleHint = false);
57
 
static gint* GetIconSizesDescending(GtkIconTheme *iconTheme,
58
 
                                    const gchar* iconName);
59
 
static Bool  GetIconsForGIcon(GIcon* gicon,
60
 
                              std::list<GHIBinaryIconInfo>& iconList);
61
 
static GdkPixbuf* ShrinkPixbuf(const GdkPixbuf* pixbuf, size_t maxSize);
62
 
 
63
 
 
64
 
/*
65
 
 *-----------------------------------------------------------------------------
66
 
 *
67
 
 * GHIX11IconGetIconsForDesktopFile --
68
 
 *
69
 
 *      Given an application's .desktop file, look up and return the app's icons
70
 
 *      as BGRA data.  Icons are sorted in descending order by size.
71
 
 *
72
 
 * Results:
73
 
 *      Returns FALSE if any errors were encountered and TRUE otherwise.
74
 
 *
75
 
 * Side effects:
76
 
 *      iconList.size() may grow.
77
 
 *
78
 
 *-----------------------------------------------------------------------------
79
 
 */
80
 
 
81
 
Bool
82
 
GHIX11IconGetIconsForDesktopFile(const char* desktopFile,                // IN
83
 
                                 std::list<GHIBinaryIconInfo>& iconList) // OUT
84
 
{
85
 
   GDesktopAppInfo* desktopAppInfo = NULL;
86
 
   GIcon* gicon = NULL;
87
 
   Bool success = FALSE;
88
 
 
89
 
   desktopAppInfo = g_desktop_app_info_new_from_filename(desktopFile);
90
 
   if (desktopAppInfo) {
91
 
      GAppInfo* appInfo = (GAppInfo*)G_APP_INFO(desktopAppInfo);
92
 
      gicon = g_app_info_get_icon(appInfo);
93
 
      if (gicon) {
94
 
         success = GetIconsForGIcon(gicon, iconList);
95
 
      }
96
 
      g_object_unref(desktopAppInfo);
97
 
   }
98
 
 
99
 
   return success;
100
 
}
101
 
 
102
 
 
103
 
/*
104
 
 *-----------------------------------------------------------------------------
105
 
 *
106
 
 * GHIX11IconGetIconsByName --
107
 
 *
108
 
 *      Try to find icons identified by a string.  The string may refer to a
109
 
 *      generic name leading to searching an icon theme, or it may be an
110
 
 *      absolute path to an icon file.
111
 
 *
112
 
 * Results:
113
 
 *      Returns FALSE if any errors were encountered and TRUE otherwise.
114
 
 *
115
 
 * Side effects:
116
 
 *      iconList.size() may grow.
117
 
 *
118
 
 *-----------------------------------------------------------------------------
119
 
 */
120
 
 
121
 
Bool
122
 
GHIX11IconGetIconsByName(const char* iconName,                          // IN
123
 
                         std::list<GHIBinaryIconInfo>& iconList)        // OUT
124
 
{
125
 
   GIcon *gicon;
126
 
   Bool retval = FALSE;
127
 
 
128
 
   gicon = g_icon_new_for_string(iconName, NULL);
129
 
   if (gicon) {
130
 
      retval = GetIconsForGIcon(gicon, iconList);
131
 
      g_object_unref(G_OBJECT(gicon));
132
 
   }
133
 
 
134
 
   return retval;
135
 
}
136
 
 
137
 
 
138
 
/*
139
 
 * Local functions
140
 
 */
141
 
 
142
 
 
143
 
/*
144
 
 *-----------------------------------------------------------------------------
145
 
 *
146
 
 * GetIconsForGIcon --
147
 
 *
148
 
 *      Given a GLib GIcon, search the default icon theme or filesystem for
149
 
 *      icons.
150
 
 *
151
 
 * Results:
152
 
 *      Returns FALSE if any errors were encountered and TRUE otherwise.
153
 
 *
154
 
 * Side effects:
155
 
 *      iconList.size() may grow.
156
 
 *
157
 
 *-----------------------------------------------------------------------------
158
 
 */
159
 
 
160
 
static Bool
161
 
GetIconsForGIcon(GIcon* gicon,                                  // IN
162
 
                 std::list<GHIBinaryIconInfo>& iconList)        // OUT
163
 
{
164
 
   gchar* iconName = NULL;
165
 
   GtkIconTheme* iconTheme;
166
 
   Bool success = FALSE;
167
 
 
168
 
   ASSERT(gicon);
169
 
 
170
 
   /*
171
 
    * We can handle two icon types, themed and file.  A themed icon is
172
 
    * provided by and varies by icon theme whereas a file icon is stored
173
 
    * in a single file.  (There's a special case where GIO thinks we have
174
 
    * a themed icon, but it turns out to be a file icon.  More on that later.)
175
 
    */
176
 
 
177
 
   iconName = g_icon_to_string(gicon);
178
 
   iconTheme = gtk_icon_theme_get_default();
179
 
 
180
 
   if (G_IS_THEMED_ICON(gicon) && gtk_icon_theme_has_icon(iconTheme, iconName)) {
181
 
 
182
 
      /*
183
 
       * Sweet - GTK claims that our icon is themed and can give us pixbufs for
184
 
       * it at various sizes.
185
 
       *
186
 
       * Remember what I said about GIO thinking we have a themed icon that might
187
 
       * not be?  If an icon doesn't have a size, then it's one of those such
188
 
       * icons, and we have to fall back to loading directly from a file ourselves.
189
 
       */
190
 
 
191
 
      gint* iconSizes = GetIconSizesDescending(iconTheme, iconName);
192
 
 
193
 
      if (iconSizes && *iconSizes != 0) {
194
 
         gint* sizeIter;
195
 
 
196
 
         for (sizeIter = iconSizes; *sizeIter; sizeIter++) {
197
 
            GdkPixbuf* pixbuf;
198
 
 
199
 
            pixbuf = gtk_icon_theme_load_icon(iconTheme, iconName, *sizeIter,
200
 
                                              (GtkIconLookupFlags)0, NULL);
201
 
            if (pixbuf) {
202
 
               AppendPixbufToArray(pixbuf, iconList);
203
 
               g_object_unref(pixbuf);
204
 
            }
205
 
         }
206
 
      } else if (iconSizes && *iconSizes == 0) {
207
 
         GtkIconInfo* iconInfo;
208
 
 
209
 
         iconInfo = gtk_icon_theme_lookup_icon(iconTheme, iconName, 0,
210
 
                                               (GtkIconLookupFlags)0);
211
 
         if (iconInfo) {
212
 
            AppendFileToArray(gtk_icon_info_get_filename(iconInfo), iconList);
213
 
            gtk_icon_info_free(iconInfo);
214
 
         }
215
 
      }
216
 
 
217
 
      g_free(iconSizes);
218
 
   } else if (G_IS_FILE_ICON(gicon)) {
219
 
      GFileIcon* fileIcon;
220
 
      GFile* file;
221
 
      char* path;
222
 
 
223
 
      fileIcon = G_FILE_ICON(gicon);
224
 
      file = g_file_icon_get_file(fileIcon);
225
 
      path = g_file_get_path(file);
226
 
      ASSERT(path);
227
 
 
228
 
      AppendFileToArray(path, iconList);
229
 
 
230
 
      g_free(path);
231
 
   } else {
232
 
      /* Give up. */
233
 
      goto out;
234
 
   }
235
 
 
236
 
   success = TRUE;
237
 
 
238
 
out:
239
 
   if (iconName) {
240
 
      g_free(iconName);
241
 
   }
242
 
   return success;
243
 
}
244
 
 
245
 
 
246
 
/*
247
 
 *-----------------------------------------------------------------------------
248
 
 *
249
 
 * AppendFileToArray --
250
 
 *
251
 
 *      Load an icon from a file into a pixbuf, then append it to a GPtrArray of
252
 
 *      GHIX11Icons.
253
 
 *
254
 
 * Results:
255
 
 *      Appends an icon on success, no-op on failure.
256
 
 *
257
 
 * Side effects:
258
 
 *      None.
259
 
 *
260
 
 *-----------------------------------------------------------------------------
261
 
 */
262
 
 
263
 
static void
264
 
AppendFileToArray(const gchar* iconPath,                  // IN
265
 
                  std::list<GHIBinaryIconInfo>& iconList) // OUT
266
 
{
267
 
   GdkPixbuf* pixbuf;
268
 
 
269
 
   if ((pixbuf = gdk_pixbuf_new_from_file(iconPath, NULL)) != NULL) {
270
 
      AppendPixbufToArray(pixbuf, iconList, true);
271
 
      g_object_unref(pixbuf);
272
 
   }
273
 
}
274
 
 
275
 
 
276
 
/*
277
 
 *-----------------------------------------------------------------------------
278
 
 *
279
 
 * AppendPixbufToArray --
280
 
 *
281
 
 *      Appends a pixbuf to a GPtrArray of GHIX11Icons.
282
 
 *
283
 
 * Results:
284
 
 *      Appends an icon on success, no-op on failure.
285
 
 *
286
 
 * Side effects:
287
 
 *      None.
288
 
 *
289
 
 *-----------------------------------------------------------------------------
290
 
 */
291
 
 
292
 
static void
293
 
AppendPixbufToArray(
294
 
   const GdkPixbuf* pixbuf,                // IN
295
 
   std::list<GHIBinaryIconInfo>& iconList, // OUT
296
 
   bool scaleHint)                         // IN: Scale icon to fit GuestMsg
297
 
{
298
 
   GHIBinaryIconInfo ghiIcon;
299
 
   guchar* pixels;
300
 
   guint width;
301
 
   guint height;
302
 
   guint x, y;
303
 
   guint rowstride;
304
 
   guint n_channels;
305
 
   guint bgraStride;
306
 
   bool scaled = false;
307
 
   GdkPixbuf *scaledPixbuf = NULL;
308
 
 
309
 
rescaled:
310
 
   ASSERT(pixbuf);
311
 
   ASSERT(gdk_pixbuf_get_colorspace(pixbuf) == GDK_COLORSPACE_RGB);
312
 
   ASSERT(gdk_pixbuf_get_bits_per_sample(pixbuf) == 8);
313
 
 
314
 
   rowstride = gdk_pixbuf_get_rowstride(pixbuf);
315
 
   n_channels = gdk_pixbuf_get_n_channels(pixbuf);
316
 
   pixels = gdk_pixbuf_get_pixels(pixbuf);
317
 
 
318
 
   ghiIcon.width = width = gdk_pixbuf_get_width(pixbuf);
319
 
   ghiIcon.height = height = gdk_pixbuf_get_height(pixbuf);
320
 
   bgraStride = width * 4;
321
 
   ghiIcon.dataBGRA.resize(height * bgraStride);
322
 
 
323
 
   if (   !scaled
324
 
       && scaleHint
325
 
       && height * bgraStride > MAX_ICON_SIZE) {
326
 
      scaled = true;
327
 
      pixbuf = scaledPixbuf = ShrinkPixbuf(pixbuf, MAX_ICON_SIZE);
328
 
      goto rescaled;
329
 
   }
330
 
 
331
 
   /* GetBinaryInfo icons are bottom-to-top. */
332
 
   for (y = 0; y < height; y++) {
333
 
      for (x = 0; x < width; x++) {
334
 
         guchar* b; // Pointer to BGRA data in ghiIcon.
335
 
         guchar* p; // Pointer to RGBA data in GdkPixbuf
336
 
         gint bgraOffset = y * bgraStride + x * 4;
337
 
         gint pixbufOffset = (height - y - 1) * rowstride + x * n_channels;
338
 
 
339
 
         b = &ghiIcon.dataBGRA[bgraOffset];
340
 
         p = &pixels[pixbufOffset];
341
 
 
342
 
         b[0] = p[2];
343
 
         b[1] = p[1];
344
 
         b[2] = p[0];
345
 
         b[3] = (n_channels > 3) ? p[3] : 0xFF;
346
 
      }
347
 
   }
348
 
 
349
 
   iconList.push_back(ghiIcon);
350
 
 
351
 
   if (scaledPixbuf) {
352
 
      g_object_unref(G_OBJECT(scaledPixbuf));
353
 
   }
354
 
}
355
 
 
356
 
 
357
 
/*
358
 
 *-----------------------------------------------------------------------------
359
 
 *
360
 
 * GetIconSizesDescending --
361
 
 *
362
 
 *      Query an icon theme for an icon's sizes.  Return the sizes as a gint
363
 
 *      array in descending order.
364
 
 *
365
 
 * Results:
366
 
 *      Pointer to a gint array on success or NULL on failure.
367
 
 *
368
 
 * Side effects:
369
 
 *      None.
370
 
 *
371
 
 *-----------------------------------------------------------------------------
372
 
 */
373
 
 
374
 
static int
375
 
DescendingIntCmp(const void* a,
376
 
                 const void* b)
377
 
{
378
 
   gint ia = *(gint* )a;
379
 
   gint ib = *(gint* )b;
380
 
 
381
 
   return (ia < ib) ? 1 : (ia == ib) ? 0 : -1;
382
 
}
383
 
 
384
 
static gint*
385
 
GetIconSizesDescending(GtkIconTheme* iconTheme, // IN
386
 
                       const gchar* iconName)   // IN
387
 
{
388
 
   gint* iconSizes = NULL;
389
 
   gint* iter;
390
 
   size_t nsizes;
391
 
 
392
 
   if (!gtk_icon_theme_has_icon(iconTheme, iconName)) {
393
 
      return NULL;
394
 
   }
395
 
 
396
 
   iconSizes = gtk_icon_theme_get_icon_sizes(iconTheme, iconName);
397
 
   ASSERT(iconSizes);
398
 
 
399
 
   /*
400
 
    * iconSizes is a 0-terminated array. If there are no sizes or the
401
 
    * array has only 1 element, this function has no remaining work to do.
402
 
    * (No point sorting a 1 element array.)
403
 
    */
404
 
   if (!iconSizes || *iconSizes == 0) {
405
 
      return iconSizes;
406
 
   }
407
 
 
408
 
   /*
409
 
    * Sort the array in descending order.  First we have to determine its
410
 
    * size, then we'll just pass it off to qsort.  Note that we don't consider
411
 
    * the final, terminating element when sorting, because the icon array may
412
 
    * contain a -1 to signify a scalable icon.
413
 
    */
414
 
   for (iter = iconSizes, nsizes = 0; *iter; iter++, nsizes++);
415
 
   qsort(iconSizes, nsizes, sizeof *iter, DescendingIntCmp);
416
 
 
417
 
   return iconSizes;
418
 
}
419
 
 
420
 
 
421
 
/*
422
 
 *-----------------------------------------------------------------------------
423
 
 *
424
 
 * ShrinkPixbuf --
425
 
 *
426
 
 *      Scale a pixbuf to fit within transport size constraints.
427
 
 *
428
 
 * Results:
429
 
 *      Pointer to new pixbuf.  Caller should free with g_object_unref.
430
 
 *
431
 
 * Side effects:
432
 
 *      None.
433
 
 *
434
 
 *-----------------------------------------------------------------------------
435
 
 */
436
 
 
437
 
GdkPixbuf*
438
 
ShrinkPixbuf(const GdkPixbuf* pixbuf, // IN
439
 
             size_t maxSize)          // IN: Must scale to less than this.
440
 
{
441
 
   GdkPixbuf *newIcon;
442
 
   volatile double newWidth;
443
 
   volatile double newHeight;
444
 
   volatile double scaleFactor;
445
 
 
446
 
   newWidth = gdk_pixbuf_get_width(pixbuf);
447
 
   newHeight = gdk_pixbuf_get_height(pixbuf);
448
 
   scaleFactor = maxSize / (newWidth * newHeight * 4.0);
449
 
   /*
450
 
    * Ensures that we remove at least a little bit of data from the icon.
451
 
    * Otherwise we can get things like scalefactors of '0.999385' which result
452
 
    * in an image of exactly the same size. A scaleFactor of 0.95 will remove at
453
 
    * least one row or column from any icon large enough to go past the limit.
454
 
    */
455
 
   scaleFactor = MIN(scaleFactor, 0.95);
456
 
 
457
 
   newWidth *= scaleFactor;
458
 
   newHeight *= scaleFactor;
459
 
   newIcon = gdk_pixbuf_scale_simple(pixbuf,
460
 
                                     (int)ceil(newWidth),
461
 
                                     (int)ceil(newHeight),
462
 
                                     GDK_INTERP_HYPER);
463
 
   return newIcon;
464
 
}