~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Additions/x11/VBoxClient/display.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2009-12-18 16:44:29 UTC
  • mfrom: (0.3.3 upstream) (0.4.6 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091218164429-jd34ccexpv5na11a
Tags: 3.1.2-dfsg-1ubuntu1
* Merge from Debian unstable (LP: #498219), remaining changes:
  - Disable update action
    - debian/patches/u01-disable-update-action.dpatch
  - VirtualBox should go in Accessories, not in System tools (LP: #288590)
    - debian/virtualbox-ose-qt.files/virtualbox-ose.desktop
  - Add Apport hook
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Add Launchpad integration
    - debian/control
    - debian/lpi-bug.xpm
    - debian/patches/u02-lp-integration.dpatch
* Fixes the following bugs:
  - Kernel module fails to build with Linux >= 2.6.32 (LP: #474625)
  - X.Org drivers need to be rebuilt against X-Server 1.7 (LP: #495935)
  - The *-source packages try to build the kernel modules even though the
    kernel headers aren't available (LP: #473334)
* Replace *-source packages with transitional packages for *-dkms.
* Adapt u01-disable-update-action.dpatch and u02-lp-integration.dpatch for
  new upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: display.cpp $ */
 
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
 
 
41
static 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
 
 
93
void 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. */
 
108
static 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
 */
 
124
int 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
 
 
182
class DisplayService : public VBoxClient::Service
 
183
{
 
184
public:
 
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
 
 
202
VBoxClient::Service *VBoxClient::GetDisplayService()
 
203
{
 
204
    return new DisplayService;
 
205
}