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

« back to all changes in this revision

Viewing changes to services/plugins/dndcp/copyPasteDnDX11.cpp

  • 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) 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
 * @file copyPasteDnDX11.cpp
 
21
 *
 
22
 * Implementation class for DnD and copy paste on X11 platform.
 
23
 */
 
24
 
 
25
#define G_LOG_DOMAIN "dndcp"
 
26
 
 
27
#include "copyPasteDnDWrapper.h"
 
28
#include "copyPasteDnDX11.h"
 
29
#include "dndPluginIntX11.h"
 
30
 
 
31
Window gXRoot;
 
32
Display *gXDisplay;
 
33
GtkWidget *gUserMainWidget;
 
34
 
 
35
 
 
36
extern "C" {
 
37
#include "copyPasteCompat.h"
 
38
#include "dndGuest.h"
 
39
#include "vmware/tools/plugin.h"
 
40
#if defined(NOT_YET)
 
41
#include "unity.h"
 
42
#endif
 
43
 
 
44
void CopyPaste_Register(GtkWidget *mainWnd, ToolsAppCtx *ctx);
 
45
void CopyPaste_Unregister(GtkWidget *mainWnd);
 
46
}
 
47
 
 
48
#include "pointer.h"
 
49
 
 
50
 
 
51
/**
 
52
 *
 
53
 * BlockingService - a singleton class responsible for initializing and
 
54
 * cleaning up blocking state (vmblock).
 
55
 */
 
56
 
 
57
class BlockService {
 
58
public:
 
59
   static BlockService *GetInstance();
 
60
   void Init(ToolsAppCtx *);
 
61
   DnDBlockControl *GetBlockCtrl() { return &m_blockCtrl; }
 
62
 
 
63
private:
 
64
   BlockService();
 
65
   ~BlockService();
 
66
 
 
67
   void Shutdown();
 
68
   static gboolean ShutdownSignalHandler(const siginfo_t *, gpointer);
 
69
 
 
70
   GSource *m_shutdownSrc;
 
71
   DnDBlockControl m_blockCtrl;
 
72
   bool m_initialized;
 
73
 
 
74
   static BlockService *m_instance;
 
75
};
 
76
 
 
77
BlockService *BlockService::m_instance = 0;
 
78
 
 
79
 
 
80
/**
 
81
 *
 
82
 * Constructor.
 
83
 */
 
84
 
 
85
BlockService::BlockService() :
 
86
   m_shutdownSrc(0),
 
87
   m_initialized(false)
 
88
{
 
89
   memset(&m_blockCtrl, 0, sizeof m_blockCtrl);
 
90
   m_blockCtrl.fd = -1;
 
91
}
 
92
 
 
93
 
 
94
/**
 
95
 *
 
96
 * Get an instance of BlockService, which is an application singleton.
 
97
 *
 
98
 * @return a pointer to the singleton BlockService object, or NULL if
 
99
 * for some reason it could not be allocated.
 
100
 */
 
101
 
 
102
BlockService *
 
103
BlockService::GetInstance()
 
104
{
 
105
   g_debug("%s: enter\n", __FUNCTION__);
 
106
 
 
107
   if (!m_instance) {
 
108
      m_instance = new BlockService();
 
109
   }
 
110
 
 
111
   ASSERT(m_instance);
 
112
   return m_instance;
 
113
}
 
114
 
 
115
 
 
116
/**
 
117
 *
 
118
 * Initialize blocking subsystem so that GTK+ DnD operations won't
 
119
 * time out. Also install SIGUSR1 handler so we can disconnect from
 
120
 * blcoing subsystem upon request.
 
121
 *
 
122
 * @param[in] ctx tools app context.
 
123
 */
 
124
 
 
125
void
 
126
BlockService::Init(ToolsAppCtx *ctx)
 
127
{
 
128
   g_debug("%s: enter\n", __FUNCTION__);
 
129
 
 
130
   if (!m_initialized && ctx) {
 
131
      m_blockCtrl.fd = ctx->blockFD;
 
132
      m_blockCtrl.fd >= 0 ?
 
133
         DnD_CompleteBlockInitialization(m_blockCtrl.fd, &m_blockCtrl) :
 
134
         DnD_InitializeBlocking(&m_blockCtrl);
 
135
 
 
136
      m_shutdownSrc = VMTools_NewSignalSource(SIGUSR1);
 
137
      VMTOOLSAPP_ATTACH_SOURCE(ctx, m_shutdownSrc, ShutdownSignalHandler,
 
138
                               ctx, NULL);
 
139
 
 
140
      m_initialized = true;
 
141
   }
 
142
}
 
143
 
 
144
 
 
145
/**
 
146
 *
 
147
 * Signal handler called when we receive SIGUSR1 which is a hint for us
 
148
 * to disconnect from blocking subsystem so that it can be upgraded.
 
149
 *
 
150
 * @param[in] siginfo unused.
 
151
 * @param[in] data    unused.
 
152
 *
 
153
 * @return always TRUE.
 
154
 */
 
155
 
 
156
gboolean
 
157
BlockService::ShutdownSignalHandler(const siginfo_t *siginfo,
 
158
                                    gpointer data)
 
159
{
 
160
   g_debug("%s: enter\n", __FUNCTION__);
 
161
 
 
162
   GetInstance()->Shutdown();
 
163
 
 
164
   return FALSE;
 
165
}
 
166
 
 
167
 
 
168
/**
 
169
 *
 
170
 * Shut down blocking susbsystem so that we can perform upgrade.
 
171
 */
 
172
 
 
173
void
 
174
BlockService::Shutdown()
 
175
{
 
176
   g_debug("%s: enter\n", __FUNCTION__);
 
177
 
 
178
   if (m_initialized) {
 
179
      g_source_destroy(m_shutdownSrc);
 
180
      g_source_unref(m_shutdownSrc);
 
181
      m_shutdownSrc = 0;
 
182
 
 
183
      if (DnD_BlockIsReady(&m_blockCtrl)) {
 
184
         DnD_UninitializeBlocking(&m_blockCtrl);
 
185
      }
 
186
 
 
187
      m_initialized = false;
 
188
   }
 
189
}
 
190
 
 
191
 
 
192
extern "C" {
 
193
 
 
194
/**
 
195
 *
 
196
 * Enter or leave unity mode.
 
197
 *
 
198
 * @param[in] mode enter unity mode if TRUE, else leave.
 
199
 */
 
200
 
 
201
#if defined(NOT_YET)
 
202
void
 
203
CopyPasteDnDX11_SetUnityMode(Bool mode)
 
204
{
 
205
   CopyPasteDnDWrapper *wrapper = CopyPasteDnDWrapper::GetInstance();
 
206
   ASSERT(wrapper);
 
207
 
 
208
   wrapper->SetUnityMode(mode);
 
209
}
 
210
#endif
 
211
}
 
212
 
 
213
/**
 
214
 *
 
215
 * Constructor.
 
216
 */
 
217
 
 
218
CopyPasteDnDX11::CopyPasteDnDX11() :
 
219
   m_copyPasteUI(NULL),
 
220
   m_dndUI(NULL)
 
221
{
 
222
}
 
223
 
 
224
 
 
225
/**
 
226
 *
 
227
 * Initialize Win32 platform DnD/CP. Initialize Gtk+, and create detection
 
228
 * windows.
 
229
 *
 
230
 * @param[in] ctx tools app context.
 
231
 */
 
232
 
 
233
gboolean
 
234
CopyPasteDnDX11::Init(ToolsAppCtx *ctx)
 
235
{
 
236
   g_debug("%s: enter\n", __FUNCTION__);
 
237
   CopyPasteDnDWrapper *wrapper = CopyPasteDnDWrapper::GetInstance();
 
238
 
 
239
   ASSERT(ctx);
 
240
   int argc = 1;
 
241
   char *argv[] = {"", NULL};
 
242
   m_main = new Gtk::Main(&argc, (char ***) &argv, false);
 
243
 
 
244
   if (wrapper) {
 
245
      BlockService::GetInstance()->Init(ctx);
 
246
   }
 
247
 
 
248
   gUserMainWidget = gtk_invisible_new();
 
249
   gXDisplay = GDK_WINDOW_XDISPLAY(gUserMainWidget->window);
 
250
   gXRoot = RootWindow(gXDisplay, DefaultScreen(gXDisplay));
 
251
 
 
252
   /*
 
253
    * Register legacy (backdoor) version of copy paste.
 
254
    */
 
255
   CopyPaste_SetVersion(1);
 
256
   CopyPaste_Register(gUserMainWidget, ctx);
 
257
 
 
258
   return TRUE;
 
259
}
 
260
 
 
261
 
 
262
/**
 
263
 *
 
264
 * Destructor.
 
265
 */
 
266
 
 
267
CopyPasteDnDX11::~CopyPasteDnDX11()
 
268
{
 
269
   if (m_copyPasteUI) {
 
270
      delete m_copyPasteUI;
 
271
   }
 
272
   if (m_dndUI) {
 
273
      delete m_dndUI;
 
274
   }
 
275
   if (m_main) {
 
276
      delete m_main;
 
277
   }
 
278
 
 
279
   /*
 
280
    * Legacy CP.
 
281
    */
 
282
   CopyPaste_Unregister(gUserMainWidget);
 
283
 
 
284
   if (gUserMainWidget) {
 
285
      gtk_widget_destroy(gUserMainWidget);
 
286
   }
 
287
}
 
288
 
 
289
 
 
290
/**
 
291
 *
 
292
 * Register copy and paste capabilities with the VMX.
 
293
 *
 
294
 * @return TRUE on success, FALSE on failure
 
295
 */
 
296
 
 
297
gboolean
 
298
CopyPasteDnDX11::RegisterCP()
 
299
{
 
300
   g_debug("%s: enter\n", __FUNCTION__);
 
301
   CopyPasteDnDWrapper *wrapper = CopyPasteDnDWrapper::GetInstance();
 
302
 
 
303
   if (wrapper->IsCPRegistered()) {
 
304
      return TRUE;
 
305
   }
 
306
 
 
307
   if (!wrapper->IsCPEnabled()) {
 
308
      return FALSE;
 
309
   }
 
310
 
 
311
   m_copyPasteUI = new CopyPasteUIX11();
 
312
   if (m_copyPasteUI) {
 
313
      if (m_copyPasteUI->Init()) {
 
314
         BlockService *bs = BlockService::GetInstance();
 
315
         m_copyPasteUI->SetBlockControl(bs->GetBlockCtrl());
 
316
         wrapper->SetCPIsRegistered(TRUE);
 
317
         int version = wrapper->GetCPVersion();
 
318
         g_debug("%s: version is %d\n", __FUNCTION__, version);
 
319
 
 
320
         if (version >= 3) {
 
321
            CopyPasteVersionChanged(version);
 
322
            m_copyPasteUI->SetCopyPasteAllowed(TRUE);
 
323
         }
 
324
         /*
 
325
          * Set legacy copy/paste version.
 
326
          */
 
327
         CopyPaste_SetVersion(version);
 
328
      } else {
 
329
         delete m_copyPasteUI;
 
330
         m_copyPasteUI = NULL;
 
331
      }
 
332
   }
 
333
   return wrapper->IsCPRegistered();
 
334
}
 
335
 
 
336
 
 
337
/**
 
338
 *
 
339
 * Register DnD capabilities with the VMX.
 
340
 *
 
341
 * @return TRUE on success, FALSE on failure
 
342
 */
 
343
 
 
344
gboolean
 
345
CopyPasteDnDX11::RegisterDnD()
 
346
{
 
347
   g_debug("%s: enter\n", __FUNCTION__);
 
348
   CopyPasteDnDWrapper *wrapper = CopyPasteDnDWrapper::GetInstance();
 
349
 
 
350
   if (!wrapper->IsDnDEnabled()) {
 
351
      return FALSE;
 
352
   }
 
353
 
 
354
   if (!wrapper->IsDnDRegistered()) {
 
355
      m_dndUI = new DnDUIX11(wrapper->GetToolsAppCtx());
 
356
      if (m_dndUI) {
 
357
         BlockService *bs = BlockService::GetInstance();
 
358
         m_dndUI->SetBlockControl(bs->GetBlockCtrl());
 
359
         if (m_dndUI->Init()) {
 
360
#if defined(NOT_YET)
 
361
            UnityDnD state;
 
362
            state.detWnd = m_dndUI->GetDetWndAsWidget();
 
363
            state.setMode = CopyPasteDnDX11_SetUnityMode;
 
364
            Unity_SetActiveDnDDetWnd(&state);
 
365
#endif
 
366
            wrapper->SetDnDIsRegistered(TRUE);
 
367
            m_dndUI->SetDnDAllowed(TRUE);
 
368
            int version = wrapper->GetDnDVersion();
 
369
            g_debug("%s: dnd version is %d\n", __FUNCTION__, version);
 
370
            if (version >= 3) {
 
371
               DnDVersionChanged(version);
 
372
            }
 
373
         } else {
 
374
            delete m_dndUI;
 
375
            m_dndUI = NULL;
 
376
         }
 
377
      }
 
378
   }
 
379
 
 
380
   g_debug("%s: dnd is registered? %d\n", __FUNCTION__, (int) wrapper->IsDnDRegistered());
 
381
   return wrapper->IsDnDRegistered();
 
382
}
 
383
 
 
384
 
 
385
/**
 
386
 *
 
387
 * Unregister copy paste capabilities and do general cleanup.
 
388
 */
 
389
 
 
390
void
 
391
CopyPasteDnDX11::UnregisterCP()
 
392
{
 
393
   g_debug("%s: enter\n", __FUNCTION__);
 
394
   CopyPasteDnDWrapper *wrapper = CopyPasteDnDWrapper::GetInstance();
 
395
   if (wrapper->IsCPRegistered()) {
 
396
      if (m_copyPasteUI) {
 
397
         delete m_copyPasteUI;
 
398
         m_copyPasteUI = NULL;
 
399
      }
 
400
      wrapper->SetCPIsRegistered(FALSE);
 
401
      wrapper->SetCPVersion(-1);
 
402
   }
 
403
}
 
404
 
 
405
 
 
406
/**
 
407
 *
 
408
 * Unregister DnD capabilities and do general cleanup.
 
409
 */
 
410
 
 
411
void
 
412
CopyPasteDnDX11::UnregisterDnD()
 
413
{
 
414
   g_debug("%s: enter\n", __FUNCTION__);
 
415
   CopyPasteDnDWrapper *wrapper = CopyPasteDnDWrapper::GetInstance();
 
416
   if (wrapper->IsDnDRegistered()) {
 
417
      /*
 
418
       * Detach the DnD detection window from Unity.
 
419
       */
 
420
#if defined(NOT_YET)
 
421
      UnityDnD state = { NULL, NULL };
 
422
      Unity_SetActiveDnDDetWnd(&state);
 
423
#endif
 
424
 
 
425
      if (m_dndUI) {
 
426
         delete m_dndUI;
 
427
         m_dndUI = NULL;
 
428
      }
 
429
      wrapper->SetDnDIsRegistered(false);
 
430
      wrapper->SetDnDVersion(-1);
 
431
      return;
 
432
   }
 
433
}
 
434
 
 
435
 
 
436
/**
 
437
 *
 
438
 * Communicate dnd allowed to platform implementation.
 
439
 *
 
440
 * @param[allowed] if TRUE, dnd allowed.
 
441
 */
 
442
 
 
443
void
 
444
CopyPasteDnDX11::SetDnDAllowed(bool allowed)
 
445
{
 
446
   ASSERT(m_dndUI);
 
447
   g_debug("%s: enter\n", __FUNCTION__);
 
448
   m_dndUI->SetDnDAllowed(allowed);
 
449
}
 
450
 
 
451
 
 
452
/**
 
453
 *
 
454
 * Communicate copypaste allowed to platform implementation.
 
455
 *
 
456
 * @param[allowed] if TRUE, copy paste allowed.
 
457
 */
 
458
 
 
459
void
 
460
CopyPasteDnDX11::SetCopyPasteAllowed(bool allowed)
 
461
{
 
462
   ASSERT(m_copyPasteUI);
 
463
   g_debug("%s: enter\n", __FUNCTION__);
 
464
   m_copyPasteUI->SetCopyPasteAllowed(allowed);
 
465
}
 
466
 
 
467
 
 
468
/**
 
469
 * Communicate copy paste version change to the platform implementation.
 
470
 *
 
471
 * @param[in] version the new version
 
472
 */
 
473
 
 
474
void
 
475
CopyPasteDnDX11::CopyPasteVersionChanged(int version)
 
476
{
 
477
   g_debug("%s: enter\n", __FUNCTION__);
 
478
   CopyPasteDnDWrapper *wrapper = CopyPasteDnDWrapper::GetInstance();
 
479
   ToolsAppCtx *ctx = wrapper->GetToolsAppCtx();
 
480
   g_debug("%s: calling VmxCopyPasteVersionChanged (version %d)\n",
 
481
          __FUNCTION__, version);
 
482
   if (ctx) {
 
483
      m_copyPasteUI->VmxCopyPasteVersionChanged(ctx->rpc, version);
 
484
   }
 
485
}
 
486
 
 
487
 
 
488
/**
 
489
 * Communicate DnD version change by calling the platform implementation.
 
490
 *
 
491
 * @param[in] version the new version.
 
492
 */
 
493
 
 
494
void
 
495
CopyPasteDnDX11::DnDVersionChanged(int version)
 
496
{
 
497
   g_debug("%s: enter\n", __FUNCTION__);
 
498
   CopyPasteDnDWrapper *wrapper = CopyPasteDnDWrapper::GetInstance();
 
499
   ToolsAppCtx *ctx = wrapper->GetToolsAppCtx();
 
500
   g_debug("%s: calling VmxDnDVersionChanged (version %d)\n",
 
501
          __FUNCTION__, version);
 
502
   ASSERT(ctx);
 
503
   ASSERT(m_dndUI);
 
504
   m_dndUI->VmxDnDVersionChanged(ctx->rpc, version);
 
505
}
 
506
 
 
507
 
 
508
/**
 
509
 *
 
510
 * Initialize pointer code.
 
511
 */
 
512
 
 
513
void
 
514
CopyPasteDnDX11::PointerInit()
 
515
{
 
516
   g_debug("%s: enter\n", __FUNCTION__);
 
517
   CopyPasteDnDWrapper *wrapper = CopyPasteDnDWrapper::GetInstance();
 
518
 
 
519
   ASSERT(wrapper);
 
520
 
 
521
   ToolsAppCtx *ctx = wrapper->GetToolsAppCtx();
 
522
   ASSERT(ctx);
 
523
 
 
524
   Pointer_Init(ctx);
 
525
}
 
526
 
 
527
 
 
528
/**
 
529
 * Return platform DnD/CP caps.
 
530
 *
 
531
 * @return 32-bit caps vector.
 
532
 */
 
533
 
 
534
uint32
 
535
CopyPasteDnDX11::GetCaps()
 
536
{
 
537
   return DND_CP_CAP_VALID |
 
538
          DND_CP_CAP_DND |
 
539
          DND_CP_CAP_CP |
 
540
          DND_CP_CAP_FORMATS_ALL |
 
541
          DND_CP_CAP_ACTIVE_CP |
 
542
          DND_CP_CAP_BIG_BUFFER;
 
543
}