VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/vboxmouse/vboxmouse_15.c@ 32163

Last change on this file since 32163 was 30442, checked in by vboxsync, 14 years ago

Additions/x11/vboxmouse: properly fix spurious mouse event notifications

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 9.6 KB
Line 
1/** @file
2 * VirtualBox X11 Guest Additions, mouse driver for X.Org server 1.5
3 */
4
5/*
6 * Copyright (C) 2006-2007 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 * --------------------------------------------------------------------
16 *
17 * This code is based on evdev.c from X.Org with the following copyright
18 * and permission notice:
19 *
20 * Copyright © 2004-2008 Red Hat, Inc.
21 *
22 * Permission to use, copy, modify, distribute, and sell this software
23 * and its documentation for any purpose is hereby granted without
24 * fee, provided that the above copyright notice appear in all copies
25 * and that both that copyright notice and this permission notice
26 * appear in supporting documentation, and that the name of Red Hat
27 * not be used in advertising or publicity pertaining to distribution
28 * of the software without specific, written prior permission. Red
29 * Hat makes no representations about the suitability of this software
30 * for any purpose. It is provided "as is" without express or implied
31 * warranty.
32 *
33 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
34 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
35 * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
36 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
37 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
38 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
39 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
40 *
41 * Authors:
42 * Kristian Høgsberg ([email protected])
43 * Adam Jackson ([email protected])
44 */
45
46#include <VBox/VMMDev.h>
47#include <VBox/VBoxGuestLib.h>
48#include <iprt/err.h>
49#include <xf86.h>
50#include <xf86Xinput.h>
51#include <mipointer.h>
52
53#include <xf86Module.h>
54
55#include <errno.h>
56#include <fcntl.h>
57#include <unistd.h>
58
59#include "product-generated.h"
60
61static void
62VBoxReadInput(InputInfoPtr pInfo)
63{
64 uint32_t cx, cy, fFeatures;
65
66 /* Read a byte from the device to acknowledge the event */
67 char c;
68 read(pInfo->fd, &c, 1);
69 /* The first test here is a workaround for an apparent bug in Xorg Server 1.5 */
70 if (
71#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 2
72 miPointerCurrentScreen() != NULL
73#else
74 miPointerGetScreen(pInfo->dev) != NULL
75#endif
76 && RT_SUCCESS(VbglR3GetMouseStatus(&fFeatures, &cx, &cy))
77 && (fFeatures & VMMDEV_MOUSE_HOST_CAN_ABSOLUTE))
78 {
79#if ABI_XINPUT_VERSION == SET_ABI_VERSION(2, 0)
80 /* Bug in the 1.4 X server series - conversion_proc was no longer
81 * called, but the server didn't yet do the conversion itself. */
82 cx = (cx * screenInfo.screens[0]->width) / 65535;
83 cy = (cy * screenInfo.screens[0]->height) / 65535;
84#endif
85 /* send absolute movement */
86 xf86PostMotionEvent(pInfo->dev, 1, 0, 2, cx, cy);
87 }
88}
89
90static void
91VBoxPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
92{
93 /* Nothing to do, dix handles all settings */
94}
95
96static int
97VBoxInit(DeviceIntPtr device)
98{
99 CARD8 map[2] = { 0, 1 };
100 Atom axis_labels[2] = { 0, 0 };
101 Atom button_labels[2] = { 0, 0 };
102 if (!InitPointerDeviceStruct((DevicePtr)device, map, 2,
103#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
104 button_labels,
105#endif
106#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 2
107 miPointerGetMotionEvents, VBoxPtrCtrlProc,
108 miPointerGetMotionBufferSize()
109#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
110 GetMotionHistory, VBoxPtrCtrlProc,
111 GetMotionHistorySize(), 2 /* Number of axes */
112
113#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
114 VBoxPtrCtrlProc, GetMotionHistorySize(),
115 2 /* Number of axes */
116#else
117# error Unsupported version of X.Org
118#endif
119#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
120 , axis_labels
121#endif
122 ))
123 return !Success;
124
125 /* Tell the server about the range of axis values we report */
126#if ABI_XINPUT_VERSION <= SET_ABI_VERSION(2, 0)
127 xf86InitValuatorAxisStruct(device, 0, 0, -1, 1, 0, 1);
128 xf86InitValuatorAxisStruct(device, 1, 0, -1, 1, 0, 1);
129#else
130 xf86InitValuatorAxisStruct(device, 0,
131# if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
132 axis_labels[0],
133# endif
134 0 /* min X */, 65536 /* max X */,
135 10000, 0, 10000);
136
137 xf86InitValuatorAxisStruct(device, 1,
138# if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
139 axis_labels[1],
140# endif
141 0 /* min Y */, 65536 /* max Y */,
142 10000, 0, 10000);
143#endif
144 xf86InitValuatorDefaults(device, 0);
145 xf86InitValuatorDefaults(device, 1);
146 xf86MotionHistoryAllocate(device->public.devicePrivate);
147
148 return Success;
149}
150
151static int
152VBoxProc(DeviceIntPtr device, int what)
153{
154 InputInfoPtr pInfo;
155 int rc, xrc;
156 uint32_t fFeatures = 0;
157
158 pInfo = device->public.devicePrivate;
159
160 switch (what)
161 {
162 case DEVICE_INIT:
163 xrc = VBoxInit(device);
164 if (xrc != Success) {
165 VbglR3Term();
166 return xrc;
167 }
168 break;
169
170 case DEVICE_ON:
171 xf86Msg(X_INFO, "%s: On.\n", pInfo->name);
172 if (device->public.on)
173 break;
174 /* Tell the host that we want absolute co-ordinates */
175 rc = VbglR3GetMouseStatus(&fFeatures, NULL, NULL);
176 if (RT_SUCCESS(rc))
177 rc = VbglR3SetMouseStatus( fFeatures
178 | VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE
179 | VMMDEV_MOUSE_GUEST_USES_VMMDEV);
180 if (!RT_SUCCESS(rc)) {
181 xf86Msg(X_ERROR, "%s: Failed to switch guest mouse into absolute mode\n",
182 pInfo->name);
183 return !Success;
184 }
185
186 xf86AddEnabledDevice(pInfo);
187 device->public.on = TRUE;
188 break;
189
190 case DEVICE_OFF:
191 xf86Msg(X_INFO, "%s: Off.\n", pInfo->name);
192 rc = VbglR3GetMouseStatus(&fFeatures, NULL, NULL);
193 if (RT_SUCCESS(rc))
194 rc = VbglR3SetMouseStatus( fFeatures
195 & ~VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE
196 & ~VMMDEV_MOUSE_GUEST_USES_VMMDEV);
197 xf86RemoveEnabledDevice(pInfo);
198 device->public.on = FALSE;
199 break;
200
201 case DEVICE_CLOSE:
202 VbglR3Term();
203 xf86Msg(X_INFO, "%s: Close\n", pInfo->name);
204 break;
205 }
206
207 return Success;
208}
209
210static int
211VBoxProbe(InputInfoPtr pInfo)
212{
213 int rc = VbglR3Init();
214 if (!RT_SUCCESS(rc)) {
215 xf86Msg(X_ERROR, "%s: Failed to open the VirtualBox device (error %d)\n",
216 pInfo->name, rc);
217 return !Success;
218 }
219
220 return Success;
221}
222
223static Bool
224VBoxConvert(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2,
225 int v3, int v4, int v5, int *x, int *y)
226{
227 if (first == 0) {
228 *x = xf86ScaleAxis(v0, 0, screenInfo.screens[0]->width, 0, 65536);
229 *y = xf86ScaleAxis(v1, 0, screenInfo.screens[0]->height, 0, 65536);
230 return TRUE;
231 } else
232 return FALSE;
233}
234
235static InputInfoPtr
236VBoxPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
237{
238 InputInfoPtr pInfo;
239 const char *device;
240
241 if (!(pInfo = xf86AllocateInput(drv, 0)))
242 return NULL;
243
244 /* Initialise the InputInfoRec. */
245 pInfo->name = dev->identifier;
246 pInfo->device_control = VBoxProc;
247 pInfo->read_input = VBoxReadInput;
248 pInfo->conf_idev = dev;
249 /* Unlike evdev, we set this unconditionally, as we don't handle keyboards. */
250 pInfo->type_name = XI_MOUSE;
251 pInfo->conversion_proc = VBoxConvert;
252 pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS |
253 XI86_ALWAYS_CORE;
254
255 xf86CollectInputOptions(pInfo, NULL, NULL);
256 xf86ProcessCommonOptions(pInfo, pInfo->options);
257
258 device = xf86CheckStrOption(dev->commonOptions, "Device",
259 "/dev/vboxguest");
260
261 xf86Msg(X_CONFIG, "%s: Device: \"%s\"\n", pInfo->name, device);
262 do {
263 pInfo->fd = open(device, O_RDWR, 0);
264 }
265 while (pInfo->fd < 0 && errno == EINTR);
266
267 if (pInfo->fd < 0) {
268 xf86Msg(X_ERROR, "Unable to open VirtualBox device \"%s\".\n", device);
269 xf86DeleteInput(pInfo, 0);
270 return NULL;
271 }
272
273 if (VBoxProbe(pInfo) != Success) {
274 xf86DeleteInput(pInfo, 0);
275 return NULL;
276 }
277
278 pInfo->flags |= XI86_CONFIGURED;
279 return pInfo;
280}
281
282_X_EXPORT InputDriverRec VBOXMOUSE = {
283 1,
284 "vboxmouse",
285 NULL,
286 VBoxPreInit,
287 NULL,
288 NULL,
289 0
290};
291
292static pointer
293VBoxPlug(pointer module,
294 pointer options,
295 int *errmaj,
296 int *errmin)
297{
298 xf86AddInputDriver(&VBOXMOUSE, module, 0);
299 xf86Msg(X_CONFIG, "Load address of symbol \"VBOXMOUSE\" is %p\n",
300 (void *)&VBOXMOUSE);
301 return module;
302}
303
304static XF86ModuleVersionInfo VBoxVersionRec =
305{
306 "vboxmouse",
307 VBOX_VENDOR,
308 MODINFOSTRING1,
309 MODINFOSTRING2,
310 0, /* Missing from SDK: XORG_VERSION_CURRENT, */
311 1, 0, 0,
312 ABI_CLASS_XINPUT,
313 ABI_XINPUT_VERSION,
314 MOD_CLASS_XINPUT,
315 {0, 0, 0, 0}
316};
317
318_X_EXPORT XF86ModuleData vboxmouseModuleData =
319{
320 &VBoxVersionRec,
321 VBoxPlug,
322 NULL
323};
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