VirtualBox

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

Last change on this file since 95994 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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