VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

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