1
/*********************************************************
2
* Copyright (C) 2010 VMware, Inc. All rights reserved.
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.
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.
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.
17
*********************************************************/
20
* @file copyPasteDnDX11.cpp
22
* Implementation class for DnD and copy paste on X11 platform.
25
#define G_LOG_DOMAIN "dndcp"
27
#include "copyPasteDnDWrapper.h"
28
#include "copyPasteDnDX11.h"
29
#include "dndPluginIntX11.h"
33
GtkWidget *gUserMainWidget;
37
#include "copyPasteCompat.h"
39
#include "vmware/tools/plugin.h"
44
void CopyPaste_Register(GtkWidget *mainWnd, ToolsAppCtx *ctx);
45
void CopyPaste_Unregister(GtkWidget *mainWnd);
53
* BlockingService - a singleton class responsible for initializing and
54
* cleaning up blocking state (vmblock).
59
static BlockService *GetInstance();
60
void Init(ToolsAppCtx *);
61
DnDBlockControl *GetBlockCtrl() { return &m_blockCtrl; }
68
static gboolean ShutdownSignalHandler(const siginfo_t *, gpointer);
70
GSource *m_shutdownSrc;
71
DnDBlockControl m_blockCtrl;
74
static BlockService *m_instance;
77
BlockService *BlockService::m_instance = 0;
85
BlockService::BlockService() :
89
memset(&m_blockCtrl, 0, sizeof m_blockCtrl);
96
* Get an instance of BlockService, which is an application singleton.
98
* @return a pointer to the singleton BlockService object, or NULL if
99
* for some reason it could not be allocated.
103
BlockService::GetInstance()
105
g_debug("%s: enter\n", __FUNCTION__);
108
m_instance = new BlockService();
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.
122
* @param[in] ctx tools app context.
126
BlockService::Init(ToolsAppCtx *ctx)
128
g_debug("%s: enter\n", __FUNCTION__);
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);
136
m_shutdownSrc = VMTools_NewSignalSource(SIGUSR1);
137
VMTOOLSAPP_ATTACH_SOURCE(ctx, m_shutdownSrc, ShutdownSignalHandler,
140
m_initialized = true;
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.
150
* @param[in] siginfo unused.
151
* @param[in] data unused.
153
* @return always TRUE.
157
BlockService::ShutdownSignalHandler(const siginfo_t *siginfo,
160
g_debug("%s: enter\n", __FUNCTION__);
162
GetInstance()->Shutdown();
170
* Shut down blocking susbsystem so that we can perform upgrade.
174
BlockService::Shutdown()
176
g_debug("%s: enter\n", __FUNCTION__);
179
g_source_destroy(m_shutdownSrc);
180
g_source_unref(m_shutdownSrc);
183
if (DnD_BlockIsReady(&m_blockCtrl)) {
184
DnD_UninitializeBlocking(&m_blockCtrl);
187
m_initialized = false;
196
* Enter or leave unity mode.
198
* @param[in] mode enter unity mode if TRUE, else leave.
203
CopyPasteDnDX11_SetUnityMode(Bool mode)
205
CopyPasteDnDWrapper *wrapper = CopyPasteDnDWrapper::GetInstance();
208
wrapper->SetUnityMode(mode);
218
CopyPasteDnDX11::CopyPasteDnDX11() :
227
* Initialize Win32 platform DnD/CP. Initialize Gtk+, and create detection
230
* @param[in] ctx tools app context.
234
CopyPasteDnDX11::Init(ToolsAppCtx *ctx)
236
g_debug("%s: enter\n", __FUNCTION__);
237
CopyPasteDnDWrapper *wrapper = CopyPasteDnDWrapper::GetInstance();
241
char *argv[] = {"", NULL};
242
m_main = new Gtk::Main(&argc, (char ***) &argv, false);
245
BlockService::GetInstance()->Init(ctx);
248
gUserMainWidget = gtk_invisible_new();
249
gXDisplay = GDK_WINDOW_XDISPLAY(gUserMainWidget->window);
250
gXRoot = RootWindow(gXDisplay, DefaultScreen(gXDisplay));
253
* Register legacy (backdoor) version of copy paste.
255
CopyPaste_SetVersion(1);
256
CopyPaste_Register(gUserMainWidget, ctx);
267
CopyPasteDnDX11::~CopyPasteDnDX11()
270
delete m_copyPasteUI;
282
CopyPaste_Unregister(gUserMainWidget);
284
if (gUserMainWidget) {
285
gtk_widget_destroy(gUserMainWidget);
292
* Register copy and paste capabilities with the VMX.
294
* @return TRUE on success, FALSE on failure
298
CopyPasteDnDX11::RegisterCP()
300
g_debug("%s: enter\n", __FUNCTION__);
301
CopyPasteDnDWrapper *wrapper = CopyPasteDnDWrapper::GetInstance();
303
if (wrapper->IsCPRegistered()) {
307
if (!wrapper->IsCPEnabled()) {
311
m_copyPasteUI = new CopyPasteUIX11();
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);
321
CopyPasteVersionChanged(version);
322
m_copyPasteUI->SetCopyPasteAllowed(TRUE);
325
* Set legacy copy/paste version.
327
CopyPaste_SetVersion(version);
329
delete m_copyPasteUI;
330
m_copyPasteUI = NULL;
333
return wrapper->IsCPRegistered();
339
* Register DnD capabilities with the VMX.
341
* @return TRUE on success, FALSE on failure
345
CopyPasteDnDX11::RegisterDnD()
347
g_debug("%s: enter\n", __FUNCTION__);
348
CopyPasteDnDWrapper *wrapper = CopyPasteDnDWrapper::GetInstance();
350
if (!wrapper->IsDnDEnabled()) {
354
if (!wrapper->IsDnDRegistered()) {
355
m_dndUI = new DnDUIX11(wrapper->GetToolsAppCtx());
357
BlockService *bs = BlockService::GetInstance();
358
m_dndUI->SetBlockControl(bs->GetBlockCtrl());
359
if (m_dndUI->Init()) {
362
state.detWnd = m_dndUI->GetDetWndAsWidget();
363
state.setMode = CopyPasteDnDX11_SetUnityMode;
364
Unity_SetActiveDnDDetWnd(&state);
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);
371
DnDVersionChanged(version);
380
g_debug("%s: dnd is registered? %d\n", __FUNCTION__, (int) wrapper->IsDnDRegistered());
381
return wrapper->IsDnDRegistered();
387
* Unregister copy paste capabilities and do general cleanup.
391
CopyPasteDnDX11::UnregisterCP()
393
g_debug("%s: enter\n", __FUNCTION__);
394
CopyPasteDnDWrapper *wrapper = CopyPasteDnDWrapper::GetInstance();
395
if (wrapper->IsCPRegistered()) {
397
delete m_copyPasteUI;
398
m_copyPasteUI = NULL;
400
wrapper->SetCPIsRegistered(FALSE);
401
wrapper->SetCPVersion(-1);
408
* Unregister DnD capabilities and do general cleanup.
412
CopyPasteDnDX11::UnregisterDnD()
414
g_debug("%s: enter\n", __FUNCTION__);
415
CopyPasteDnDWrapper *wrapper = CopyPasteDnDWrapper::GetInstance();
416
if (wrapper->IsDnDRegistered()) {
418
* Detach the DnD detection window from Unity.
421
UnityDnD state = { NULL, NULL };
422
Unity_SetActiveDnDDetWnd(&state);
429
wrapper->SetDnDIsRegistered(false);
430
wrapper->SetDnDVersion(-1);
438
* Communicate dnd allowed to platform implementation.
440
* @param[allowed] if TRUE, dnd allowed.
444
CopyPasteDnDX11::SetDnDAllowed(bool allowed)
447
g_debug("%s: enter\n", __FUNCTION__);
448
m_dndUI->SetDnDAllowed(allowed);
454
* Communicate copypaste allowed to platform implementation.
456
* @param[allowed] if TRUE, copy paste allowed.
460
CopyPasteDnDX11::SetCopyPasteAllowed(bool allowed)
462
ASSERT(m_copyPasteUI);
463
g_debug("%s: enter\n", __FUNCTION__);
464
m_copyPasteUI->SetCopyPasteAllowed(allowed);
469
* Communicate copy paste version change to the platform implementation.
471
* @param[in] version the new version
475
CopyPasteDnDX11::CopyPasteVersionChanged(int version)
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);
483
m_copyPasteUI->VmxCopyPasteVersionChanged(ctx->rpc, version);
489
* Communicate DnD version change by calling the platform implementation.
491
* @param[in] version the new version.
495
CopyPasteDnDX11::DnDVersionChanged(int version)
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);
504
m_dndUI->VmxDnDVersionChanged(ctx->rpc, version);
510
* Initialize pointer code.
514
CopyPasteDnDX11::PointerInit()
516
g_debug("%s: enter\n", __FUNCTION__);
517
CopyPasteDnDWrapper *wrapper = CopyPasteDnDWrapper::GetInstance();
521
ToolsAppCtx *ctx = wrapper->GetToolsAppCtx();
529
* Return platform DnD/CP caps.
531
* @return 32-bit caps vector.
535
CopyPasteDnDX11::GetCaps()
537
return DND_CP_CAP_VALID |
540
DND_CP_CAP_FORMATS_ALL |
541
DND_CP_CAP_ACTIVE_CP |
542
DND_CP_CAP_BIG_BUFFER;