~n-muench/ubuntu/precise/open-vm-tools/open-vm-tools-precise.sid-merge1

« back to all changes in this revision

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

  • 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) 2009 VMware, Inc. All rights reserved.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms of the GNU Lesser General Public License as published
 
6
 * by the Free Software Foundation version 2.1 and no later version.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
10
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
 
11
 * License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public License
 
14
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 
15
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
 
16
 *
 
17
 *********************************************************/
 
18
 
 
19
/**
 
20
 * @file x11Event.c
 
21
 *
 
22
 * Provides code relating the Glib main loop and Xlib/X11 event sources.
 
23
 */
 
24
 
 
25
 
 
26
extern "C" {
 
27
#include <stdlib.h>
 
28
#include <stdio.h>
 
29
#include "vmware.h"
 
30
}
 
31
 
 
32
#include "unityX11.h"
 
33
 
 
34
 
 
35
/*
 
36
 * File scope prototypes.
 
37
 */
 
38
 
 
39
 
 
40
static void ConnectionWatch(Display *display, XPointer client_data, int fd,
 
41
                            int opening, XPointer *watch_data);
 
42
static gboolean TeardownHashRemove(gpointer key, gpointer value,
 
43
                                   gpointer user_data);
 
44
static gboolean USourcePrepare(GSource *source, gint *timeout);
 
45
static gboolean USourceCheck(GSource *source);
 
46
static gboolean USourceDispatch(GSource *source, GSourceFunc callback,
 
47
                                gpointer cbData);
 
48
 
 
49
 
 
50
/*
 
51
 * Library scope functions.
 
52
 */
 
53
 
 
54
 
 
55
/*
 
56
 ******************************************************************************
 
57
 * UnityX11EstablishSource --                                            */ /**
 
58
 *
 
59
 * @brief Creates Glib event source for X11 events.  Attaches to the Glib event
 
60
 * loop.
 
61
 *
 
62
 * @param[in] up        Our Unity platform context.
 
63
 *
 
64
 ******************************************************************************
 
65
 */
 
66
 
 
67
void
 
68
UnityX11EventEstablishSource(UnityPlatform *up) // IN
 
69
{
 
70
   static GSourceFuncs unitySourceFuncs = {0};
 
71
   unitySourceFuncs.prepare = USourcePrepare;
 
72
   unitySourceFuncs.check = USourceCheck;
 
73
   unitySourceFuncs.dispatch = USourceDispatch;
 
74
 
 
75
   UnityGSource *uSource;
 
76
 
 
77
   ASSERT(up);
 
78
   ASSERT(up->display);
 
79
 
 
80
   uSource = (UnityGSource *)g_source_new(&unitySourceFuncs, sizeof *uSource);
 
81
   uSource->up = up;
 
82
   uSource->fdTable = g_hash_table_new(g_direct_hash, g_direct_equal);
 
83
 
 
84
   up->glibSource = uSource;
 
85
 
 
86
   /* Hook our main X11 connection into our event source. */
 
87
   ConnectionWatch(up->display, (XPointer)up, ConnectionNumber(up->display), TRUE,
 
88
                   NULL);
 
89
 
 
90
   /* If Xlib opens an internal connection, bind it to the source, too. */
 
91
   XAddConnectionWatch(up->display, &ConnectionWatch, (XPointer)up);
 
92
 
 
93
   /* Attach the source to the event loop. */
 
94
   g_source_set_callback((GSource*)uSource, UnityX11HandleEvents, up, NULL);
 
95
   g_source_attach((GSource*)uSource, NULL);
 
96
 
 
97
   /* Transfer ownership to the event loop. */
 
98
   g_source_unref((GSource*)uSource);
 
99
}
 
100
 
 
101
 
 
102
/*
 
103
 ******************************************************************************
 
104
 * UnityX11TeardownSource --                                             */ /**
 
105
 *
 
106
 * @brief Detach Unity from our Glib event loop.
 
107
 *
 
108
 * @param[in] up        Our Unity platform context.
 
109
 *
 
110
 ******************************************************************************
 
111
 */
 
112
 
 
113
void
 
114
UnityX11EventTeardownSource(UnityPlatform *up) // IN
 
115
{
 
116
   UnityGSource *uSource = up->glibSource;
 
117
 
 
118
   ASSERT(up);
 
119
   ASSERT(uSource);
 
120
 
 
121
   /* Detach Xlib internal connection notification from the Glib event loop. */
 
122
   XRemoveConnectionWatch(up->display, &ConnectionWatch, (XPointer)up);
 
123
 
 
124
   /* Detach all Xlib file descriptors from our Glib event source. */
 
125
   g_hash_table_foreach_remove(uSource->fdTable, TeardownHashRemove, uSource);
 
126
   g_hash_table_unref(uSource->fdTable);
 
127
   uSource->fdTable = NULL;
 
128
 
 
129
   /* Destroy the Glib event source. */
 
130
   g_source_destroy((GSource*)uSource);
 
131
   up->glibSource = NULL;
 
132
}
 
133
 
 
134
 
 
135
/*
 
136
 * File scope functions.
 
137
 */
 
138
 
 
139
 
 
140
/*
 
141
 ******************************************************************************
 
142
 * ConnectionWatch --                                                    */ /**
 
143
 *
 
144
 * @brief Binds Xlib internal connections to Glib event sources.
 
145
 *
 
146
 * When Xlib or its extensions create new X11 connections, they're bound to
 
147
 * a @a Display as <em>"internal connections"</em>.  When Xlib processes the
 
148
 * incoming event queue, it pulls requests from @em all of these connections,
 
149
 * not just the main event connection.  As such, we should monitor all of
 
150
 * them.
 
151
 *
 
152
 * @param[in] display     X11 display context.
 
153
 * @param[in] client_data Our UnityPlatform context.
 
154
 * @param[in] fd          Relevant file descriptor.
 
155
 * @param[in] opening     TRUE when @a fd is opened, FALSE when @a fd is closed.
 
156
 * @param[in] watch_data  Unused.
 
157
 *
 
158
 * @sa XAddConnectionWatch
 
159
 *
 
160
 ******************************************************************************
 
161
 */
 
162
 
 
163
static void
 
164
ConnectionWatch(Display *display,       // IN
 
165
                XPointer client_data,   // IN
 
166
                int fd,                 // IN
 
167
                int opening,            // IN
 
168
                XPointer *watch_data)   // UNUSED
 
169
{
 
170
   UnityPlatform *up;
 
171
   UnityGSource *uSource;
 
172
 
 
173
   up = (UnityPlatform *)client_data;
 
174
 
 
175
   ASSERT(up);             // Make sure we're correctly registered.
 
176
   ASSERT(up->isRunning);  // This cb should be stripped before we exit Unity.
 
177
   ASSERT(up->glibSource); // This function is useless w/o an established source.
 
178
   ASSERT(display == up->display);
 
179
 
 
180
   uSource = up->glibSource;
 
181
 
 
182
   if (opening) {
 
183
      /*
 
184
       * Add new a new file descriptor to the poll array.
 
185
       */
 
186
      GPollFD *newFd = g_new0(GPollFD, 1);
 
187
 
 
188
      ASSERT(g_hash_table_lookup(uSource->fdTable, GINT_TO_POINTER(fd)) == NULL);
 
189
 
 
190
      newFd->fd = fd;
 
191
      newFd->events = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
 
192
 
 
193
      g_hash_table_insert(uSource->fdTable, GINT_TO_POINTER(fd), newFd);
 
194
      g_source_add_poll((GSource*)uSource, newFd);
 
195
   } else {
 
196
      /*
 
197
       * Remove a file descriptor from the poll array.
 
198
       */
 
199
      GPollFD *oldFd = (GPollFD*)g_hash_table_lookup(uSource->fdTable, GINT_TO_POINTER(fd));
 
200
 
 
201
      if (oldFd) {
 
202
         g_source_remove_poll((GSource *)uSource, oldFd);
 
203
         g_hash_table_remove(uSource->fdTable, GINT_TO_POINTER(fd));
 
204
         g_free(oldFd);
 
205
      }
 
206
   }
 
207
}
 
208
 
 
209
 
 
210
/*
 
211
 ******************************************************************************
 
212
 * TeardownHashRemove --                                                 */ /**
 
213
 *
 
214
 * @brief Assists TeardownSource with destroying its GPollFD hash table.
 
215
 *
 
216
 * @param[in] key       GINT_TO_POINTER-converted file descriptor.
 
217
 * @param[in] value     Corresponding GPollFD *.
 
218
 * @param[in] user_data Our UnityGSource.
 
219
 *
 
220
 * @see g_hash_table_foreach_remove
 
221
 *
 
222
 ******************************************************************************
 
223
 */
 
224
 
 
225
static gboolean
 
226
TeardownHashRemove(gpointer key,        // IN
 
227
                   gpointer value,      // IN
 
228
                   gpointer user_data)  // IN
 
229
{
 
230
   GPollFD *oldFd = (GPollFD*)value;
 
231
   UnityGSource *uSource = (UnityGSource*)user_data;
 
232
 
 
233
   ASSERT(value);
 
234
   ASSERT(user_data);
 
235
 
 
236
   g_source_remove_poll((GSource *)uSource, oldFd);
 
237
   g_free(oldFd);
 
238
 
 
239
   return TRUE;
 
240
}
 
241
 
 
242
 
 
243
/*
 
244
 ******************************************************************************
 
245
 * USourcePrepare --                                                     */ /**
 
246
 *
 
247
 * @brief See GSourceFuncs::prepare.
 
248
 *
 
249
 * @param[in]  source   Points to our UnityGSource.
 
250
 * @param[out] timeout  May specify a maximum timeout value for poll(2).
 
251
 *
 
252
 * @retval TRUE  Source is ready.
 
253
 * @retval FALSE Source not yet ready.
 
254
 *
 
255
 ******************************************************************************
 
256
 */
 
257
 
 
258
static gboolean
 
259
USourcePrepare(GSource *source, // IN
 
260
               gint *timeout)   // OUT
 
261
{
 
262
   UnityGSource *uSource = (UnityGSource *)source;
 
263
 
 
264
   /*
 
265
    * "It sets the returned timeout to -1 to indicate that it doesn't mind how
 
266
    * long the poll() call blocks."
 
267
    *  - http://library.gnome.org/devel/glib/unstable/glib-The-Main-Event-Loop.html#GSourceFuncs
 
268
    */
 
269
   *timeout = -1;
 
270
 
 
271
   return XQLength(uSource->up->display) > 0;
 
272
}
 
273
 
 
274
 
 
275
/*
 
276
 ******************************************************************************
 
277
 * USourceCheck --                                                       */ /**
 
278
 *
 
279
 * @brief See GSourceFuncs::check.
 
280
 *
 
281
 * @param[in]  source   Points to our UnityGSource.
 
282
 *
 
283
 * @retval TRUE  Source is ready.
 
284
 * @retval FALSE Source not yet ready.
 
285
 *
 
286
 * @todo Should exit Unity upon file descriptor error.
 
287
 *
 
288
 ******************************************************************************
 
289
 */
 
290
 
 
291
static gboolean
 
292
USourceCheck(GSource *source)   // IN
 
293
{
 
294
   UnityGSource *uSource = (UnityGSource *)source;
 
295
   gboolean haveData = FALSE;
 
296
 
 
297
   /*
 
298
    * XXX Could/should test for FD errors here.
 
299
    */
 
300
   if (XQLength(uSource->up->display)) {
 
301
      haveData = TRUE;
 
302
   } else {
 
303
      GList *pollFds;
 
304
      GList *listIter;
 
305
 
 
306
      pollFds = g_hash_table_get_values(uSource->fdTable);
 
307
 
 
308
      for (listIter = pollFds; listIter; listIter = listIter->next) {
 
309
         GPollFD *pollFd = (GPollFD*)listIter->data;
 
310
 
 
311
         if (pollFd->revents & G_IO_IN) {
 
312
            haveData = TRUE;
 
313
            break;
 
314
         }
 
315
      }
 
316
 
 
317
      g_list_free(pollFds);
 
318
   }
 
319
 
 
320
   return haveData;
 
321
}
 
322
 
 
323
 
 
324
/*
 
325
 ******************************************************************************
 
326
 * USourceDispatch --                                                    */ /**
 
327
 *
 
328
 * @brief See GSourceFuncs::dispatch.
 
329
 *
 
330
 * @param[in] source    Points to our UnityGSource.
 
331
 * @param[in] callback  Points to the user's callback.
 
332
 * @param[in] cbData    Points to user's callback data.
 
333
 *
 
334
 * @retval TRUE  Glib should continue monitoring the source.
 
335
 * @retval FALSE Glib should stop monitoring the source.
 
336
 *
 
337
 ******************************************************************************
 
338
 */
 
339
 
 
340
static gboolean
 
341
USourceDispatch(GSource *source,      // IN
 
342
                GSourceFunc callback, // IN
 
343
                gpointer cbData)      // IN
 
344
{
 
345
   /*
 
346
    * Remind callers to attach a callback.
 
347
    */
 
348
   ASSERT(callback);
 
349
   ASSERT(cbData);
 
350
 
 
351
   return callback(cbData);
 
352
}