VirtualBox

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

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

Additions/x11/VBoxClient: converted logging to release logging (which is opt-in at runtime in guest R3)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.8 KB
Line 
1/* $Id: display.cpp 27709 2010-03-25 15:01:21Z 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#include <X11/extensions/Xrandr.h>
32
33#include <iprt/assert.h>
34#include <iprt/err.h>
35#include <iprt/thread.h>
36#include <VBox/log.h>
37#include <VBox/VMMDev.h>
38#include <VBox/VBoxGuestLib.h>
39
40#include "VBoxClient.h"
41
42static int initDisplay(Display *pDisplay)
43{
44 int rc = VINF_SUCCESS;
45 uint32_t fMouseFeatures = 0;
46
47 LogRelFlowFunc(("testing dynamic resizing\n"));
48 int iDummy;
49 if (!XRRQueryExtension(pDisplay, &iDummy, &iDummy))
50 rc = VERR_NOT_SUPPORTED;
51 if (RT_SUCCESS(rc))
52 rc = VbglR3CtlFilterMask(VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, 0);
53 else
54 VbglR3CtlFilterMask(0, VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
55 /* Log and ignore the return value, as there is not much we can do with
56 * it. */
57 LogRelFlowFunc(("dynamic resizing: result %Rrc\n", rc));
58 /* Enable support for switching between hardware and software cursors */
59 LogRelFlowFunc(("enabling relative mouse re-capturing support\n"));
60 rc = VbglR3GetMouseStatus(&fMouseFeatures, NULL, NULL);
61 if (RT_SUCCESS(rc))
62 {
63 if (fMouseFeatures & VMMDEV_MOUSE_HOST_RECHECKS_NEEDS_HOST_CURSOR)
64 {
65 rc = VbglR3CtlFilterMask(VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED,
66 0);
67 if (RT_SUCCESS(rc))
68 rc = VbglR3SetMouseStatus
69 ( fMouseFeatures
70 & ~VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR);
71 }
72 else
73 rc = VERR_NOT_SUPPORTED;
74 }
75 if (RT_FAILURE(rc))
76 {
77 VbglR3CtlFilterMask(0, VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED);
78 VbglR3SetMouseStatus( fMouseFeatures
79 | VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR);
80 }
81 LogRelFlowFunc(("mouse re-capturing support: result %Rrc\n", rc));
82 return VINF_SUCCESS;
83}
84
85void cleanupDisplay(void)
86{
87 uint32_t fMouseFeatures = 0;
88 LogRelFlowFunc(("\n"));
89 VbglR3CtlFilterMask(0, VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST
90 | VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED);
91 int rc = VbglR3GetMouseStatus(&fMouseFeatures, NULL, NULL);
92 if (RT_SUCCESS(rc))
93 VbglR3SetMouseStatus( fMouseFeatures
94 | VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR);
95 LogRelFlowFunc(("returning\n"));
96}
97
98/** This thread just runs a dummy X11 event loop to be sure that we get
99 * terminated should the X server exit. */
100static int x11ConnectionMonitor(RTTHREAD, void *)
101{
102 XEvent ev;
103 Display *pDisplay = XOpenDisplay(NULL);
104 while (true)
105 XNextEvent(pDisplay, &ev);
106 return 0;
107}
108
109/**
110 * This method first resets the current resolution using RandR to wake up
111 * the graphics driver, then sets the resolution requested if it is among
112 * those offered by the driver.
113 */
114static void setSize(Display *pDisplay, uint32_t cx, uint32_t cy)
115{
116 XRRScreenConfiguration *pConfig;
117 XRRScreenSize *pSizes;
118 int cSizes;
119 pConfig = XRRGetScreenInfo(pDisplay, DefaultRootWindow(pDisplay));
120 /* Reset the current mode */
121 LogRelFlowFunc(("Setting size %ux%u\n", cx, cy));
122 if (pConfig)
123 {
124 pSizes = XRRConfigSizes(pConfig, &cSizes);
125 unsigned uDist = UINT32_MAX;
126 int iMode = -1;
127 for (int i = 0; i < cSizes; ++i)
128 {
129#define VBCL_SQUARE(x) (x) * (x)
130 unsigned uThisDist = VBCL_SQUARE(pSizes[i].width - cx)
131 + VBCL_SQUARE(pSizes[i].height - cy);
132 LogRelFlowFunc(("Found size %dx%d, distance %u\n", pSizes[i].width,
133 pSizes[i].height, uThisDist));
134#undef VBCL_SQUARE
135 if (uThisDist < uDist)
136 {
137 uDist = uThisDist;
138 iMode = i;
139 }
140 }
141 if (iMode >= 0)
142 {
143 Time config_timestamp = 0;
144 XRRConfigTimes(pConfig, &config_timestamp);
145 LogRelFlowFunc(("Setting new size %d\n", iMode));
146 XRRSetScreenConfig(pDisplay, pConfig,
147 DefaultRootWindow(pDisplay), iMode,
148 RR_Rotate_0, config_timestamp);
149 }
150 XRRFreeScreenConfigInfo(pConfig);
151 }
152}
153
154/**
155 * Display change request monitor thread function.
156 * Before entering the loop, we re-read the last request
157 * received, and if the first one received inside the
158 * loop is identical we ignore it, because it is probably
159 * stale.
160 */
161static int runDisplay(Display *pDisplay)
162{
163 LogRelFlowFunc(("\n"));
164 Cursor hClockCursor = XCreateFontCursor(pDisplay, XC_watch);
165 Cursor hArrowCursor = XCreateFontCursor(pDisplay, XC_left_ptr);
166 int rc = RTThreadCreate(NULL, x11ConnectionMonitor, NULL, 0,
167 RTTHREADTYPE_INFREQUENT_POLLER, 0, "X11 monitor");
168 if (RT_FAILURE(rc))
169 return rc;
170 while (true)
171 {
172 uint32_t fEvents = 0, cx = 0, cy = 0, cBits = 0, iDisplay = 0;
173 rc = VbglR3WaitEvent( VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST
174 | VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED,
175 RT_INDEFINITE_WAIT, &fEvents);
176 /* Jiggle the mouse pointer to wake up the driver. */
177 XGrabPointer(pDisplay,
178 DefaultRootWindow(pDisplay), true, 0, GrabModeAsync,
179 GrabModeAsync, None, hClockCursor, CurrentTime);
180 XFlush(pDisplay);
181 XGrabPointer(pDisplay,
182 DefaultRootWindow(pDisplay), true, 0, GrabModeAsync,
183 GrabModeAsync, None, hArrowCursor, CurrentTime);
184 XFlush(pDisplay);
185 XUngrabPointer(pDisplay, CurrentTime);
186 XFlush(pDisplay);
187 /* And if it is a size hint, set the new size now that the video
188 * driver has had a chance to update its list. */
189 if (RT_SUCCESS(rc) && (fEvents & VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST))
190 {
191 int rc2 = VbglR3GetDisplayChangeRequest(&cx, &cy, &cBits,
192 &iDisplay, true);
193 /* If we are not stopping, sleep for a bit to avoid using up
194 too much CPU while retrying. */
195 if (RT_FAILURE(rc2))
196 RTThreadYield();
197 else
198 setSize(pDisplay, cx, cy);
199 }
200 }
201 LogRelFlowFunc(("returning VINF_SUCCESS\n"));
202 return VINF_SUCCESS;
203}
204
205class DisplayService : public VBoxClient::Service
206{
207public:
208 virtual const char *getPidFilePath()
209 {
210 return ".vboxclient-display.pid";
211 }
212 virtual int run(bool fDaemonised /* = false */)
213 {
214 Display *pDisplay = XOpenDisplay(NULL);
215 if (!pDisplay)
216 return VERR_NOT_FOUND;
217 int rc = initDisplay(pDisplay);
218 if (RT_SUCCESS(rc))
219 rc = runDisplay(pDisplay);
220 XCloseDisplay(pDisplay);
221 return rc;
222 }
223 virtual void cleanup()
224 {
225 cleanupDisplay();
226 }
227};
228
229VBoxClient::Service *VBoxClient::GetDisplayService()
230{
231 return new DisplayService;
232}
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