VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/VBoxClient/display.cpp@ 26753

Last change on this file since 26753 was 26505, checked in by vboxsync, 15 years ago

Additions: tabs -> spaces.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.7 KB
Line 
1/* $Id: display.cpp 26505 2010-02-14 09:17:44Z vboxsync $ */
2/** @file
3 * X11 guest client - display management.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/** @todo this should probably be replaced by something IPRT */
23/* For system() and WEXITSTATUS() */
24#include <stdlib.h>
25#include <sys/types.h>
26#include <sys/wait.h>
27#include <errno.h>
28
29#include <X11/Xlib.h>
30#include <X11/cursorfont.h>
31
32#include <iprt/assert.h>
33#include <iprt/err.h>
34#include <iprt/thread.h>
35#include <VBox/log.h>
36#include <VBox/VMMDev.h>
37#include <VBox/VBoxGuestLib.h>
38
39#include "VBoxClient.h"
40
41static int initDisplay()
42{
43 int rc = VINF_SUCCESS;
44 int rcSystem, rcErrno;
45 uint32_t fMouseFeatures = 0;
46
47 LogFlowFunc(("enabling dynamic resizing\n"));
48 rcSystem = system("VBoxRandR --test");
49 if (-1 == rcSystem)
50 {
51 rcErrno = errno;
52 rc = RTErrConvertFromErrno(rcErrno);
53 }
54 if (RT_SUCCESS(rc))
55 {
56 if (0 != WEXITSTATUS(rcSystem))
57 rc = VERR_NOT_SUPPORTED;
58 }
59 if (RT_SUCCESS(rc))
60 rc = VbglR3CtlFilterMask(VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, 0);
61 else
62 VbglR3CtlFilterMask(0, VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
63 /* Log and ignore the return value, as there is not much we can do with
64 * it. */
65 LogFlowFunc(("dynamic resizing: result %Rrc\n", rc));
66 /* Enable support for switching between hardware and software cursors */
67 LogFlowFunc(("enabling relative mouse re-capturing support\n"));
68 rc = VbglR3GetMouseStatus(&fMouseFeatures, NULL, NULL);
69 if (RT_SUCCESS(rc))
70 {
71 if (fMouseFeatures & VMMDEV_MOUSE_HOST_RECHECKS_NEEDS_HOST_CURSOR)
72 {
73 rc = VbglR3CtlFilterMask(VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED,
74 0);
75 if (RT_SUCCESS(rc))
76 rc = VbglR3SetMouseStatus
77 ( fMouseFeatures
78 & ~VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR);
79 }
80 else
81 rc = VERR_NOT_SUPPORTED;
82 }
83 if (RT_FAILURE(rc))
84 {
85 VbglR3CtlFilterMask(0, VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED);
86 VbglR3SetMouseStatus( fMouseFeatures
87 | VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR);
88 }
89 LogFlowFunc(("mouse re-capturing support: result %Rrc\n", rc));
90 return VINF_SUCCESS;
91}
92
93void cleanupDisplay(void)
94{
95 uint32_t fMouseFeatures = 0;
96 LogFlowFunc(("\n"));
97 VbglR3CtlFilterMask(0, VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST
98 | VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED);
99 int rc = VbglR3GetMouseStatus(&fMouseFeatures, NULL, NULL);
100 if (RT_SUCCESS(rc))
101 VbglR3SetMouseStatus( fMouseFeatures
102 | VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR);
103 LogFlowFunc(("returning\n"));
104}
105
106/** This thread just runs a dummy X11 event loop to be sure that we get
107 * terminated should the X server exit. */
108static int x11ConnectionMonitor(RTTHREAD, void *)
109{
110 XEvent ev;
111 Display *pDisplay = XOpenDisplay(NULL);
112 while (true)
113 XNextEvent(pDisplay, &ev);
114 return 0;
115}
116
117/**
118 * Display change request monitor thread function.
119 * Before entering the loop, we re-read the last request
120 * received, and if the first one received inside the
121 * loop is identical we ignore it, because it is probably
122 * stale.
123 */
124int runDisplay()
125{
126 LogFlowFunc(("\n"));
127 uint32_t cx0 = 0, cy0 = 0, cBits0 = 0, iDisplay0 = 0;
128 Display *pDisplay = XOpenDisplay(NULL);
129 if (pDisplay == NULL)
130 return VERR_NOT_FOUND;
131 Cursor hClockCursor = XCreateFontCursor(pDisplay, XC_watch);
132 Cursor hArrowCursor = XCreateFontCursor(pDisplay, XC_left_ptr);
133 int rc = RTThreadCreate(NULL, x11ConnectionMonitor, NULL, 0,
134 RTTHREADTYPE_INFREQUENT_POLLER, 0, "X11 monitor");
135 if (RT_FAILURE(rc))
136 return rc;
137 VbglR3GetDisplayChangeRequest(&cx0, &cy0, &cBits0, &iDisplay0, false);
138 while (true)
139 {
140 uint32_t fEvents = 0, cx = 0, cy = 0, cBits = 0, iDisplay = 0;
141 rc = VbglR3WaitEvent( VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST
142 | VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED,
143 RT_INDEFINITE_WAIT, &fEvents);
144 if (RT_SUCCESS(rc) && (fEvents & VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST))
145 {
146 int rc2 = VbglR3GetDisplayChangeRequest(&cx, &cy, &cBits,
147 &iDisplay, true);
148 /* Ignore the request if it is stale */
149 if ((cx != cx0) || (cy != cy0) || RT_FAILURE(rc2))
150 {
151 /* If we are not stopping, sleep for a bit to avoid using up
152 too much CPU while retrying. */
153 if (RT_FAILURE(rc2))
154 RTThreadYield();
155 else
156 {
157 system("VBoxRandR");
158 cx0 = cx;
159 cy0 = cy;
160 }
161 }
162 }
163 if ( RT_SUCCESS(rc)
164 && (fEvents & VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED))
165 {
166 XGrabPointer(pDisplay,
167 DefaultRootWindow(pDisplay), true, 0, GrabModeAsync,
168 GrabModeAsync, None, hClockCursor, CurrentTime);
169 XFlush(pDisplay);
170 XGrabPointer(pDisplay,
171 DefaultRootWindow(pDisplay), true, 0, GrabModeAsync,
172 GrabModeAsync, None, hArrowCursor, CurrentTime);
173 XFlush(pDisplay);
174 XUngrabPointer(pDisplay, CurrentTime);
175 XFlush(pDisplay);
176 }
177 }
178 LogFlowFunc(("returning VINF_SUCCESS\n"));
179 return VINF_SUCCESS;
180}
181
182class DisplayService : public VBoxClient::Service
183{
184public:
185 virtual const char *getPidFilePath()
186 {
187 return ".vboxclient-display.pid";
188 }
189 virtual int run(bool fDaemonised /* = false */)
190 {
191 int rc = initDisplay();
192 if (RT_SUCCESS(rc))
193 rc = runDisplay();
194 return rc;
195 }
196 virtual void cleanup()
197 {
198 cleanupDisplay();
199 }
200};
201
202VBoxClient::Service *VBoxClient::GetDisplayService()
203{
204 return new DisplayService;
205}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette