1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * All Rights Reserved.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining
7*4882a593Smuzhiyun * a copy of this software and associated documentation files (the
8*4882a593Smuzhiyun * "Software"), to deal in the Software without restriction, including
9*4882a593Smuzhiyun * without limitation on the rights to use, copy, modify, merge,
10*4882a593Smuzhiyun * publish, distribute, sublicense, and/or sell copies of the Software,
11*4882a593Smuzhiyun * and to permit persons to whom the Software is furnished to do so,
12*4882a593Smuzhiyun * subject to the following conditions:
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * The above copyright notice and this permission notice (including the
15*4882a593Smuzhiyun * next paragraph) shall be included in all copies or substantial
16*4882a593Smuzhiyun * portions of the Software.
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19*4882a593Smuzhiyun * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*4882a593Smuzhiyun * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21*4882a593Smuzhiyun * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22*4882a593Smuzhiyun * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23*4882a593Smuzhiyun * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24*4882a593Smuzhiyun * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25*4882a593Smuzhiyun * SOFTWARE.
26*4882a593Smuzhiyun */
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /*
29*4882a593Smuzhiyun * Authors:
30*4882a593Smuzhiyun * Rickard E. (Rik) Faith <faith@redhat.com>
31*4882a593Smuzhiyun *
32*4882a593Smuzhiyun */
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun /** \file
35*4882a593Smuzhiyun * This file provides generic input support. Functions here set up
36*4882a593Smuzhiyun * input and lead to the calling of low-level device drivers for
37*4882a593Smuzhiyun * input. */
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #ifdef HAVE_DMX_CONFIG_H
40*4882a593Smuzhiyun #include <dmx-config.h>
41*4882a593Smuzhiyun #endif
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun #define DMX_WINDOW_DEBUG 0
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun #include "dmxinputinit.h"
46*4882a593Smuzhiyun #include "dmxextension.h" /* For dmxInputCount */
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #include "dmxdummy.h"
49*4882a593Smuzhiyun #include "dmxbackend.h"
50*4882a593Smuzhiyun #include "dmxconsole.h"
51*4882a593Smuzhiyun #include "dmxcommon.h"
52*4882a593Smuzhiyun #include "dmxevents.h"
53*4882a593Smuzhiyun #include "dmxmotion.h"
54*4882a593Smuzhiyun #include "dmxprop.h"
55*4882a593Smuzhiyun #include "config/dmxconfig.h"
56*4882a593Smuzhiyun #include "dmxcursor.h"
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun #include "usb-keyboard.h"
59*4882a593Smuzhiyun #include "usb-mouse.h"
60*4882a593Smuzhiyun #include "usb-other.h"
61*4882a593Smuzhiyun #include "usb-common.h"
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun #include "dmxarg.h"
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun #include "inputstr.h"
66*4882a593Smuzhiyun #include "input.h"
67*4882a593Smuzhiyun #include "mipointer.h"
68*4882a593Smuzhiyun #include "windowstr.h"
69*4882a593Smuzhiyun #include "mi.h"
70*4882a593Smuzhiyun #include "xkbsrv.h"
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun #include <X11/extensions/XI.h>
73*4882a593Smuzhiyun #include <X11/extensions/XIproto.h>
74*4882a593Smuzhiyun #include "exevents.h"
75*4882a593Smuzhiyun #include "extinit.h"
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun DMXLocalInputInfoPtr dmxLocalCorePointer, dmxLocalCoreKeyboard;
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun static DMXLocalInputInfoRec DMXDummyMou = {
80*4882a593Smuzhiyun "dummy-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
81*4882a593Smuzhiyun NULL, NULL, NULL, NULL, NULL, dmxDummyMouGetInfo
82*4882a593Smuzhiyun };
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun static DMXLocalInputInfoRec DMXDummyKbd = {
85*4882a593Smuzhiyun "dummy-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1,
86*4882a593Smuzhiyun NULL, NULL, NULL, NULL, NULL, dmxDummyKbdGetInfo
87*4882a593Smuzhiyun };
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun static DMXLocalInputInfoRec DMXBackendMou = {
90*4882a593Smuzhiyun "backend-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_BACKEND, 2,
91*4882a593Smuzhiyun dmxBackendCreatePrivate, dmxBackendDestroyPrivate,
92*4882a593Smuzhiyun dmxBackendInit, NULL, dmxBackendLateReInit, dmxBackendMouGetInfo,
93*4882a593Smuzhiyun dmxCommonMouOn, dmxCommonMouOff, dmxBackendUpdatePosition,
94*4882a593Smuzhiyun NULL, NULL, NULL,
95*4882a593Smuzhiyun dmxBackendCollectEvents, dmxBackendProcessInput, dmxBackendFunctions, NULL,
96*4882a593Smuzhiyun dmxCommonMouCtrl
97*4882a593Smuzhiyun };
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun static DMXLocalInputInfoRec DMXBackendKbd = {
100*4882a593Smuzhiyun "backend-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_BACKEND,
101*4882a593Smuzhiyun 1, /* With backend-mou or console-mou */
102*4882a593Smuzhiyun dmxCommonCopyPrivate, NULL,
103*4882a593Smuzhiyun dmxBackendInit, NULL, NULL, dmxBackendKbdGetInfo,
104*4882a593Smuzhiyun dmxCommonKbdOn, dmxCommonKbdOff, NULL,
105*4882a593Smuzhiyun NULL, NULL, NULL,
106*4882a593Smuzhiyun NULL, NULL, NULL, NULL,
107*4882a593Smuzhiyun NULL, dmxCommonKbdCtrl, dmxCommonKbdBell
108*4882a593Smuzhiyun };
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun static DMXLocalInputInfoRec DMXConsoleMou = {
111*4882a593Smuzhiyun "console-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_CONSOLE, 2,
112*4882a593Smuzhiyun dmxConsoleCreatePrivate, dmxConsoleDestroyPrivate,
113*4882a593Smuzhiyun dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleMouGetInfo,
114*4882a593Smuzhiyun dmxCommonMouOn, dmxCommonMouOff, dmxConsoleUpdatePosition,
115*4882a593Smuzhiyun NULL, NULL, NULL,
116*4882a593Smuzhiyun dmxConsoleCollectEvents, NULL, dmxConsoleFunctions, dmxConsoleUpdateInfo,
117*4882a593Smuzhiyun dmxCommonMouCtrl
118*4882a593Smuzhiyun };
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun static DMXLocalInputInfoRec DMXConsoleKbd = {
121*4882a593Smuzhiyun "console-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_CONSOLE,
122*4882a593Smuzhiyun 1, /* With backend-mou or console-mou */
123*4882a593Smuzhiyun dmxCommonCopyPrivate, NULL,
124*4882a593Smuzhiyun dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleKbdGetInfo,
125*4882a593Smuzhiyun dmxCommonKbdOn, dmxCommonKbdOff, NULL,
126*4882a593Smuzhiyun NULL, NULL, NULL,
127*4882a593Smuzhiyun NULL, NULL, NULL, NULL,
128*4882a593Smuzhiyun NULL, dmxCommonKbdCtrl, dmxCommonKbdBell
129*4882a593Smuzhiyun };
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun static DMXLocalInputInfoRec DMXLocalDevices[] = {
132*4882a593Smuzhiyun /* Dummy drivers that can compile on any OS */
133*4882a593Smuzhiyun #ifdef __linux__
134*4882a593Smuzhiyun /* USB drivers, currently only for
135*4882a593Smuzhiyun Linux, but relatively easy to port to
136*4882a593Smuzhiyun other OSs */
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun "usb-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1,
139*4882a593Smuzhiyun usbCreatePrivate, usbDestroyPrivate,
140*4882a593Smuzhiyun kbdUSBInit, NULL, NULL, kbdUSBGetInfo,
141*4882a593Smuzhiyun kbdUSBOn, usbOff, NULL,
142*4882a593Smuzhiyun NULL, NULL, NULL,
143*4882a593Smuzhiyun kbdUSBRead, NULL, NULL, NULL,
144*4882a593Smuzhiyun NULL, kbdUSBCtrl},
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun "usb-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
147*4882a593Smuzhiyun usbCreatePrivate, usbDestroyPrivate,
148*4882a593Smuzhiyun mouUSBInit, NULL, NULL, mouUSBGetInfo,
149*4882a593Smuzhiyun mouUSBOn, usbOff, NULL,
150*4882a593Smuzhiyun NULL, NULL, NULL,
151*4882a593Smuzhiyun mouUSBRead},
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun "usb-oth", DMX_LOCAL_OTHER, DMX_LOCAL_TYPE_LOCAL, 1,
154*4882a593Smuzhiyun usbCreatePrivate, usbDestroyPrivate,
155*4882a593Smuzhiyun othUSBInit, NULL, NULL, othUSBGetInfo,
156*4882a593Smuzhiyun othUSBOn, usbOff, NULL,
157*4882a593Smuzhiyun NULL, NULL, NULL,
158*4882a593Smuzhiyun othUSBRead},
159*4882a593Smuzhiyun #endif
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun "dummy-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
162*4882a593Smuzhiyun NULL, NULL, NULL, NULL, NULL, dmxDummyMouGetInfo},
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun "dummy-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1,
165*4882a593Smuzhiyun NULL, NULL, NULL, NULL, NULL, dmxDummyKbdGetInfo},
166*4882a593Smuzhiyun {NULL} /* Must be last */
167*4882a593Smuzhiyun };
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun #if 11 /*BP*/
170*4882a593Smuzhiyun void
DDXRingBell(int volume,int pitch,int duration)171*4882a593Smuzhiyun DDXRingBell(int volume, int pitch, int duration)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun /* NO-OP */
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /* taken from kdrive/src/kinput.c: */
177*4882a593Smuzhiyun static void
dmxKbdCtrl(DeviceIntPtr pDevice,KeybdCtrl * ctrl)178*4882a593Smuzhiyun dmxKbdCtrl(DeviceIntPtr pDevice, KeybdCtrl * ctrl)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun #if 0
181*4882a593Smuzhiyun KdKeyboardInfo *ki;
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun for (ki = kdKeyboards; ki; ki = ki->next) {
184*4882a593Smuzhiyun if (ki->dixdev && ki->dixdev->id == pDevice->id)
185*4882a593Smuzhiyun break;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id || !ki->driver)
189*4882a593Smuzhiyun return;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun KdSetLeds(ki, ctrl->leds);
192*4882a593Smuzhiyun ki->bellPitch = ctrl->bell_pitch;
193*4882a593Smuzhiyun ki->bellDuration = ctrl->bell_duration;
194*4882a593Smuzhiyun #endif
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun /* taken from kdrive/src/kinput.c: */
198*4882a593Smuzhiyun static void
dmxBell(int volume,DeviceIntPtr pDev,void * arg,int something)199*4882a593Smuzhiyun dmxBell(int volume, DeviceIntPtr pDev, void *arg, int something)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun #if 0
202*4882a593Smuzhiyun KeybdCtrl *ctrl = arg;
203*4882a593Smuzhiyun KdKeyboardInfo *ki = NULL;
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun for (ki = kdKeyboards; ki; ki = ki->next) {
206*4882a593Smuzhiyun if (ki->dixdev && ki->dixdev->id == pDev->id)
207*4882a593Smuzhiyun break;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun if (!ki || !ki->dixdev || ki->dixdev->id != pDev->id || !ki->driver)
211*4882a593Smuzhiyun return;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun KdRingBell(ki, volume, ctrl->bell_pitch, ctrl->bell_duration);
214*4882a593Smuzhiyun #endif
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun #endif /*BP*/
218*4882a593Smuzhiyun static void
_dmxChangePointerControl(DMXLocalInputInfoPtr dmxLocal,PtrCtrl * ctrl)219*4882a593Smuzhiyun _dmxChangePointerControl(DMXLocalInputInfoPtr dmxLocal, PtrCtrl * ctrl)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun if (!dmxLocal)
222*4882a593Smuzhiyun return;
223*4882a593Smuzhiyun dmxLocal->mctrl = *ctrl;
224*4882a593Smuzhiyun if (dmxLocal->mCtrl)
225*4882a593Smuzhiyun dmxLocal->mCtrl(&dmxLocal->pDevice->public, ctrl);
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun /** Change the pointer control information for the \a pDevice. If the
229*4882a593Smuzhiyun * device sends core events, then also change the control information
230*4882a593Smuzhiyun * for all of the pointer devices that send core events. */
231*4882a593Smuzhiyun void
dmxChangePointerControl(DeviceIntPtr pDevice,PtrCtrl * ctrl)232*4882a593Smuzhiyun dmxChangePointerControl(DeviceIntPtr pDevice, PtrCtrl * ctrl)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun GETDMXLOCALFROMPDEVICE;
235*4882a593Smuzhiyun int i, j;
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun if (dmxLocal->sendsCore) { /* Do for all core devices */
238*4882a593Smuzhiyun for (i = 0; i < dmxNumInputs; i++) {
239*4882a593Smuzhiyun DMXInputInfo *dmxInput = &dmxInputs[i];
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun if (dmxInput->detached)
242*4882a593Smuzhiyun continue;
243*4882a593Smuzhiyun for (j = 0; j < dmxInput->numDevs; j++)
244*4882a593Smuzhiyun if (dmxInput->devs[j]->sendsCore)
245*4882a593Smuzhiyun _dmxChangePointerControl(dmxInput->devs[j], ctrl);
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun else { /* Do for this device only */
249*4882a593Smuzhiyun _dmxChangePointerControl(dmxLocal, ctrl);
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun static void
_dmxKeyboardKbdCtrlProc(DMXLocalInputInfoPtr dmxLocal,KeybdCtrl * ctrl)254*4882a593Smuzhiyun _dmxKeyboardKbdCtrlProc(DMXLocalInputInfoPtr dmxLocal, KeybdCtrl * ctrl)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun dmxLocal->kctrl = *ctrl;
257*4882a593Smuzhiyun if (dmxLocal->kCtrl) {
258*4882a593Smuzhiyun dmxLocal->kCtrl(&dmxLocal->pDevice->public, ctrl);
259*4882a593Smuzhiyun if (dmxLocal->pDevice->kbdfeed) {
260*4882a593Smuzhiyun XkbEventCauseRec cause;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun XkbSetCauseUnknown(&cause);
263*4882a593Smuzhiyun /* Generate XKB events, as necessary */
264*4882a593Smuzhiyun XkbUpdateIndicators(dmxLocal->pDevice, XkbAllIndicatorsMask, False,
265*4882a593Smuzhiyun NULL, &cause);
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun /** Change the keyboard control information for the \a pDevice. If the
271*4882a593Smuzhiyun * device sends core events, then also change the control information
272*4882a593Smuzhiyun * for all of the keyboard devices that send core events. */
273*4882a593Smuzhiyun void
dmxKeyboardKbdCtrlProc(DeviceIntPtr pDevice,KeybdCtrl * ctrl)274*4882a593Smuzhiyun dmxKeyboardKbdCtrlProc(DeviceIntPtr pDevice, KeybdCtrl * ctrl)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun GETDMXLOCALFROMPDEVICE;
277*4882a593Smuzhiyun int i, j;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun if (dmxLocal->sendsCore) { /* Do for all core devices */
280*4882a593Smuzhiyun for (i = 0; i < dmxNumInputs; i++) {
281*4882a593Smuzhiyun DMXInputInfo *dmxInput = &dmxInputs[i];
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun if (dmxInput->detached)
284*4882a593Smuzhiyun continue;
285*4882a593Smuzhiyun for (j = 0; j < dmxInput->numDevs; j++)
286*4882a593Smuzhiyun if (dmxInput->devs[j]->sendsCore)
287*4882a593Smuzhiyun _dmxKeyboardKbdCtrlProc(dmxInput->devs[j], ctrl);
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun else { /* Do for this device only */
291*4882a593Smuzhiyun _dmxKeyboardKbdCtrlProc(dmxLocal, ctrl);
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun static void
_dmxKeyboardBellProc(DMXLocalInputInfoPtr dmxLocal,int percent)296*4882a593Smuzhiyun _dmxKeyboardBellProc(DMXLocalInputInfoPtr dmxLocal, int percent)
297*4882a593Smuzhiyun {
298*4882a593Smuzhiyun if (dmxLocal->kBell)
299*4882a593Smuzhiyun dmxLocal->kBell(&dmxLocal->pDevice->public,
300*4882a593Smuzhiyun percent,
301*4882a593Smuzhiyun dmxLocal->kctrl.bell,
302*4882a593Smuzhiyun dmxLocal->kctrl.bell_pitch,
303*4882a593Smuzhiyun dmxLocal->kctrl.bell_duration);
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun /** Sound the bell on the device. If the device send core events, then
307*4882a593Smuzhiyun * sound the bell on all of the devices that send core events. */
308*4882a593Smuzhiyun void
dmxKeyboardBellProc(int percent,DeviceIntPtr pDevice,void * ctrl,int unknown)309*4882a593Smuzhiyun dmxKeyboardBellProc(int percent, DeviceIntPtr pDevice,
310*4882a593Smuzhiyun void *ctrl, int unknown)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun GETDMXLOCALFROMPDEVICE;
313*4882a593Smuzhiyun int i, j;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun if (dmxLocal->sendsCore) { /* Do for all core devices */
316*4882a593Smuzhiyun for (i = 0; i < dmxNumInputs; i++) {
317*4882a593Smuzhiyun DMXInputInfo *dmxInput = &dmxInputs[i];
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun if (dmxInput->detached)
320*4882a593Smuzhiyun continue;
321*4882a593Smuzhiyun for (j = 0; j < dmxInput->numDevs; j++)
322*4882a593Smuzhiyun if (dmxInput->devs[j]->sendsCore)
323*4882a593Smuzhiyun _dmxKeyboardBellProc(dmxInput->devs[j], percent);
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun else { /* Do for this device only */
327*4882a593Smuzhiyun _dmxKeyboardBellProc(dmxLocal, percent);
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun static void
dmxKeyboardFreeNames(XkbComponentNamesPtr names)332*4882a593Smuzhiyun dmxKeyboardFreeNames(XkbComponentNamesPtr names)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun if (names->keycodes)
335*4882a593Smuzhiyun XFree(names->keycodes);
336*4882a593Smuzhiyun if (names->types)
337*4882a593Smuzhiyun XFree(names->types);
338*4882a593Smuzhiyun if (names->compat)
339*4882a593Smuzhiyun XFree(names->compat);
340*4882a593Smuzhiyun if (names->symbols)
341*4882a593Smuzhiyun XFree(names->symbols);
342*4882a593Smuzhiyun if (names->geometry)
343*4882a593Smuzhiyun XFree(names->geometry);
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun static int
dmxKeyboardOn(DeviceIntPtr pDevice,DMXLocalInitInfo * info)347*4882a593Smuzhiyun dmxKeyboardOn(DeviceIntPtr pDevice, DMXLocalInitInfo * info)
348*4882a593Smuzhiyun {
349*4882a593Smuzhiyun GETDMXINPUTFROMPDEVICE;
350*4882a593Smuzhiyun XkbRMLVOSet rmlvo;
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun rmlvo.rules = dmxConfigGetXkbRules();
353*4882a593Smuzhiyun rmlvo.model = dmxConfigGetXkbModel();
354*4882a593Smuzhiyun rmlvo.layout = dmxConfigGetXkbLayout();
355*4882a593Smuzhiyun rmlvo.variant = dmxConfigGetXkbVariant();
356*4882a593Smuzhiyun rmlvo.options = dmxConfigGetXkbOptions();
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun XkbSetRulesDflts(&rmlvo);
359*4882a593Smuzhiyun if (!info->force && (dmxInput->keycodes
360*4882a593Smuzhiyun || dmxInput->symbols || dmxInput->geometry)) {
361*4882a593Smuzhiyun if (info->freenames)
362*4882a593Smuzhiyun dmxKeyboardFreeNames(&info->names);
363*4882a593Smuzhiyun info->freenames = 0;
364*4882a593Smuzhiyun info->names.keycodes = dmxInput->keycodes;
365*4882a593Smuzhiyun info->names.types = NULL;
366*4882a593Smuzhiyun info->names.compat = NULL;
367*4882a593Smuzhiyun info->names.symbols = dmxInput->symbols;
368*4882a593Smuzhiyun info->names.geometry = dmxInput->geometry;
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun dmxLogInput(dmxInput, "XKEYBOARD: From command line: %s",
371*4882a593Smuzhiyun info->names.keycodes);
372*4882a593Smuzhiyun if (info->names.symbols && *info->names.symbols)
373*4882a593Smuzhiyun dmxLogInputCont(dmxInput, " %s", info->names.symbols);
374*4882a593Smuzhiyun if (info->names.geometry && *info->names.geometry)
375*4882a593Smuzhiyun dmxLogInputCont(dmxInput, " %s", info->names.geometry);
376*4882a593Smuzhiyun dmxLogInputCont(dmxInput, "\n");
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun else if (info->names.keycodes) {
379*4882a593Smuzhiyun dmxLogInput(dmxInput, "XKEYBOARD: From device: %s",
380*4882a593Smuzhiyun info->names.keycodes);
381*4882a593Smuzhiyun if (info->names.symbols && *info->names.symbols)
382*4882a593Smuzhiyun dmxLogInputCont(dmxInput, " %s", info->names.symbols);
383*4882a593Smuzhiyun if (info->names.geometry && *info->names.geometry)
384*4882a593Smuzhiyun dmxLogInputCont(dmxInput, " %s", info->names.geometry);
385*4882a593Smuzhiyun dmxLogInputCont(dmxInput, "\n");
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun else {
388*4882a593Smuzhiyun dmxLogInput(dmxInput, "XKEYBOARD: Defaults: %s %s %s %s %s\n",
389*4882a593Smuzhiyun dmxConfigGetXkbRules(),
390*4882a593Smuzhiyun dmxConfigGetXkbLayout(),
391*4882a593Smuzhiyun dmxConfigGetXkbModel(), dmxConfigGetXkbVariant()
392*4882a593Smuzhiyun ? dmxConfigGetXkbVariant() : "", dmxConfigGetXkbOptions()
393*4882a593Smuzhiyun ? dmxConfigGetXkbOptions() : "");
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun InitKeyboardDeviceStruct(pDevice, &rmlvo,
396*4882a593Smuzhiyun dmxKeyboardBellProc, dmxKeyboardKbdCtrlProc);
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun if (info->freenames)
399*4882a593Smuzhiyun dmxKeyboardFreeNames(&info->names);
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun return Success;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun static int
dmxDeviceOnOff(DeviceIntPtr pDevice,int what)405*4882a593Smuzhiyun dmxDeviceOnOff(DeviceIntPtr pDevice, int what)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun GETDMXINPUTFROMPDEVICE;
408*4882a593Smuzhiyun DMXLocalInitInfo info;
409*4882a593Smuzhiyun int i;
410*4882a593Smuzhiyun Atom btn_labels[MAX_BUTTONS] = { 0 }; /* FIXME */
411*4882a593Smuzhiyun Atom axis_labels[MAX_VALUATORS] = { 0 }; /* FIXME */
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun if (dmxInput->detached)
414*4882a593Smuzhiyun return Success;
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun memset(&info, 0, sizeof(info));
417*4882a593Smuzhiyun switch (what) {
418*4882a593Smuzhiyun case DEVICE_INIT:
419*4882a593Smuzhiyun if (dmxLocal->init)
420*4882a593Smuzhiyun dmxLocal->init(pDev);
421*4882a593Smuzhiyun if (dmxLocal->get_info)
422*4882a593Smuzhiyun dmxLocal->get_info(pDev, &info);
423*4882a593Smuzhiyun if (info.keyboard) { /* XKEYBOARD makes this a special case */
424*4882a593Smuzhiyun dmxKeyboardOn(pDevice, &info);
425*4882a593Smuzhiyun break;
426*4882a593Smuzhiyun }
427*4882a593Smuzhiyun if (info.keyClass) {
428*4882a593Smuzhiyun XkbRMLVOSet rmlvo;
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun rmlvo.rules = dmxConfigGetXkbRules();
431*4882a593Smuzhiyun rmlvo.model = dmxConfigGetXkbModel();
432*4882a593Smuzhiyun rmlvo.layout = dmxConfigGetXkbLayout();
433*4882a593Smuzhiyun rmlvo.variant = dmxConfigGetXkbVariant();
434*4882a593Smuzhiyun rmlvo.options = dmxConfigGetXkbOptions();
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun InitKeyboardDeviceStruct(pDevice, &rmlvo, dmxBell, dmxKbdCtrl);
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun if (info.buttonClass) {
439*4882a593Smuzhiyun InitButtonClassDeviceStruct(pDevice, info.numButtons,
440*4882a593Smuzhiyun btn_labels, info.map);
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun if (info.valuatorClass) {
443*4882a593Smuzhiyun if (info.numRelAxes && dmxLocal->sendsCore) {
444*4882a593Smuzhiyun InitValuatorClassDeviceStruct(pDevice, info.numRelAxes,
445*4882a593Smuzhiyun axis_labels,
446*4882a593Smuzhiyun GetMaximumEventsNum(), Relative);
447*4882a593Smuzhiyun for (i = 0; i < info.numRelAxes; i++)
448*4882a593Smuzhiyun InitValuatorAxisStruct(pDevice, i, axis_labels[i],
449*4882a593Smuzhiyun info.minval[i], info.maxval[i],
450*4882a593Smuzhiyun info.res[i],
451*4882a593Smuzhiyun info.minres[i], info.maxres[i],
452*4882a593Smuzhiyun Relative);
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun else if (info.numRelAxes) {
455*4882a593Smuzhiyun InitValuatorClassDeviceStruct(pDevice, info.numRelAxes,
456*4882a593Smuzhiyun axis_labels,
457*4882a593Smuzhiyun dmxPointerGetMotionBufferSize(),
458*4882a593Smuzhiyun Relative);
459*4882a593Smuzhiyun for (i = 0; i < info.numRelAxes; i++)
460*4882a593Smuzhiyun InitValuatorAxisStruct(pDevice, i, axis_labels[i],
461*4882a593Smuzhiyun info.minval[i],
462*4882a593Smuzhiyun info.maxval[i], info.res[i],
463*4882a593Smuzhiyun info.minres[i], info.maxres[i],
464*4882a593Smuzhiyun Relative);
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun else if (info.numAbsAxes) {
467*4882a593Smuzhiyun InitValuatorClassDeviceStruct(pDevice, info.numAbsAxes,
468*4882a593Smuzhiyun axis_labels,
469*4882a593Smuzhiyun dmxPointerGetMotionBufferSize(),
470*4882a593Smuzhiyun Absolute);
471*4882a593Smuzhiyun for (i = 0; i < info.numAbsAxes; i++)
472*4882a593Smuzhiyun InitValuatorAxisStruct(pDevice, i,
473*4882a593Smuzhiyun axis_labels[i],
474*4882a593Smuzhiyun info.minval[i], info.maxval[i],
475*4882a593Smuzhiyun info.res[i], info.minres[i],
476*4882a593Smuzhiyun info.maxres[i], Absolute);
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun if (info.focusClass)
480*4882a593Smuzhiyun InitFocusClassDeviceStruct(pDevice);
481*4882a593Smuzhiyun if (info.proximityClass)
482*4882a593Smuzhiyun InitProximityClassDeviceStruct(pDevice);
483*4882a593Smuzhiyun if (info.ptrFeedbackClass)
484*4882a593Smuzhiyun InitPtrFeedbackClassDeviceStruct(pDevice, dmxChangePointerControl);
485*4882a593Smuzhiyun if (info.intFeedbackClass || info.strFeedbackClass)
486*4882a593Smuzhiyun dmxLog(dmxWarning,
487*4882a593Smuzhiyun "Integer and string feedback not supported for %s\n",
488*4882a593Smuzhiyun pDevice->name);
489*4882a593Smuzhiyun if (!info.keyboard && (info.ledFeedbackClass || info.belFeedbackClass))
490*4882a593Smuzhiyun dmxLog(dmxWarning,
491*4882a593Smuzhiyun "Led and bel feedback not supported for non-keyboard %s\n",
492*4882a593Smuzhiyun pDevice->name);
493*4882a593Smuzhiyun break;
494*4882a593Smuzhiyun case DEVICE_ON:
495*4882a593Smuzhiyun if (!pDev->on) {
496*4882a593Smuzhiyun if (dmxLocal->on)
497*4882a593Smuzhiyun dmxLocal->on(pDev);
498*4882a593Smuzhiyun pDev->on = TRUE;
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun break;
501*4882a593Smuzhiyun case DEVICE_OFF:
502*4882a593Smuzhiyun case DEVICE_CLOSE:
503*4882a593Smuzhiyun /* This can get called twice consecutively: once for a
504*4882a593Smuzhiyun * detached screen (DEVICE_OFF), and then again at server
505*4882a593Smuzhiyun * generation time (DEVICE_CLOSE). */
506*4882a593Smuzhiyun if (pDev->on) {
507*4882a593Smuzhiyun if (dmxLocal->off)
508*4882a593Smuzhiyun dmxLocal->off(pDev);
509*4882a593Smuzhiyun pDev->on = FALSE;
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun break;
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun if (info.keySyms.map && info.freemap) {
514*4882a593Smuzhiyun XFree(info.keySyms.map);
515*4882a593Smuzhiyun info.keySyms.map = NULL;
516*4882a593Smuzhiyun }
517*4882a593Smuzhiyun if (info.xkb)
518*4882a593Smuzhiyun XkbFreeKeyboard(info.xkb, 0, True);
519*4882a593Smuzhiyun return Success;
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun static void
dmxProcessInputEvents(DMXInputInfo * dmxInput)523*4882a593Smuzhiyun dmxProcessInputEvents(DMXInputInfo * dmxInput)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun int i;
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun mieqProcessInputEvents();
528*4882a593Smuzhiyun #if 00 /*BP*/
529*4882a593Smuzhiyun miPointerUpdate();
530*4882a593Smuzhiyun #endif
531*4882a593Smuzhiyun if (dmxInput->detached)
532*4882a593Smuzhiyun return;
533*4882a593Smuzhiyun for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding)
534*4882a593Smuzhiyun if (dmxInput->devs[i]->process_input) {
535*4882a593Smuzhiyun dmxInput->devs[i]->process_input(dmxInput->devs[i]->private);
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun #if 11 /*BP*/
539*4882a593Smuzhiyun mieqProcessInputEvents();
540*4882a593Smuzhiyun #endif
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun static void
dmxUpdateWindowInformation(DMXInputInfo * dmxInput,DMXUpdateType type,WindowPtr pWindow)544*4882a593Smuzhiyun dmxUpdateWindowInformation(DMXInputInfo * dmxInput,
545*4882a593Smuzhiyun DMXUpdateType type, WindowPtr pWindow)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun int i;
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun #ifdef PANORAMIX
550*4882a593Smuzhiyun if (!noPanoramiXExtension && pWindow &&
551*4882a593Smuzhiyun pWindow->parent != screenInfo.screens[0]->root)
552*4882a593Smuzhiyun return;
553*4882a593Smuzhiyun #endif
554*4882a593Smuzhiyun #if DMX_WINDOW_DEBUG
555*4882a593Smuzhiyun {
556*4882a593Smuzhiyun const char *name = "Unknown";
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun switch (type) {
559*4882a593Smuzhiyun case DMX_UPDATE_REALIZE:
560*4882a593Smuzhiyun name = "Realize";
561*4882a593Smuzhiyun break;
562*4882a593Smuzhiyun case DMX_UPDATE_UNREALIZE:
563*4882a593Smuzhiyun name = "Unrealize";
564*4882a593Smuzhiyun break;
565*4882a593Smuzhiyun case DMX_UPDATE_RESTACK:
566*4882a593Smuzhiyun name = "Restack";
567*4882a593Smuzhiyun break;
568*4882a593Smuzhiyun case DMX_UPDATE_COPY:
569*4882a593Smuzhiyun name = "Copy";
570*4882a593Smuzhiyun break;
571*4882a593Smuzhiyun case DMX_UPDATE_RESIZE:
572*4882a593Smuzhiyun name = "Resize";
573*4882a593Smuzhiyun break;
574*4882a593Smuzhiyun case DMX_UPDATE_REPARENT:
575*4882a593Smuzhiyun name = "Repaint";
576*4882a593Smuzhiyun break;
577*4882a593Smuzhiyun }
578*4882a593Smuzhiyun dmxLog(dmxDebug, "Window %p changed: %s\n", pWindow, name);
579*4882a593Smuzhiyun }
580*4882a593Smuzhiyun #endif
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun if (dmxInput->detached)
583*4882a593Smuzhiyun return;
584*4882a593Smuzhiyun for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding)
585*4882a593Smuzhiyun if (dmxInput->devs[i]->update_info)
586*4882a593Smuzhiyun dmxInput->devs[i]->update_info(dmxInput->devs[i]->private,
587*4882a593Smuzhiyun type, pWindow);
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun static void
dmxCollectAll(DMXInputInfo * dmxInput)591*4882a593Smuzhiyun dmxCollectAll(DMXInputInfo * dmxInput)
592*4882a593Smuzhiyun {
593*4882a593Smuzhiyun int i;
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun if (dmxInput->detached)
596*4882a593Smuzhiyun return;
597*4882a593Smuzhiyun for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding)
598*4882a593Smuzhiyun if (dmxInput->devs[i]->collect_events)
599*4882a593Smuzhiyun dmxInput->devs[i]->collect_events(&dmxInput->devs[i]->pDevice->
600*4882a593Smuzhiyun public, dmxMotion, dmxEnqueue,
601*4882a593Smuzhiyun dmxCheckSpecialKeys, DMX_BLOCK);
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun static void
dmxBlockHandler(void * blockData,void * timeout)605*4882a593Smuzhiyun dmxBlockHandler(void *blockData, void *timeout)
606*4882a593Smuzhiyun {
607*4882a593Smuzhiyun DMXInputInfo *dmxInput = &dmxInputs[(uintptr_t) blockData];
608*4882a593Smuzhiyun static unsigned long generation = 0;
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun if (generation != serverGeneration) {
611*4882a593Smuzhiyun generation = serverGeneration;
612*4882a593Smuzhiyun dmxCollectAll(dmxInput);
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun static void
dmxSwitchReturn(void * p)617*4882a593Smuzhiyun dmxSwitchReturn(void *p)
618*4882a593Smuzhiyun {
619*4882a593Smuzhiyun DMXInputInfo *dmxInput = p;
620*4882a593Smuzhiyun int i;
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun dmxLog(dmxInfo, "Returning from VT %d\n", dmxInput->vt_switched);
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun if (!dmxInput->vt_switched)
625*4882a593Smuzhiyun dmxLog(dmxFatal, "dmxSwitchReturn called, but not switched\n");
626*4882a593Smuzhiyun for (i = 0; i < dmxInput->numDevs; i++)
627*4882a593Smuzhiyun if (dmxInput->devs[i]->vt_post_switch)
628*4882a593Smuzhiyun dmxInput->devs[i]->vt_post_switch(dmxInput->devs[i]->private);
629*4882a593Smuzhiyun dmxInput->vt_switched = 0;
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun static void
dmxWakeupHandler(void * blockData,int result)633*4882a593Smuzhiyun dmxWakeupHandler(void *blockData, int result)
634*4882a593Smuzhiyun {
635*4882a593Smuzhiyun DMXInputInfo *dmxInput = &dmxInputs[(uintptr_t) blockData];
636*4882a593Smuzhiyun int i;
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun if (dmxInput->vt_switch_pending) {
639*4882a593Smuzhiyun dmxLog(dmxInfo, "Switching to VT %d\n", dmxInput->vt_switch_pending);
640*4882a593Smuzhiyun for (i = 0; i < dmxInput->numDevs; i++)
641*4882a593Smuzhiyun if (dmxInput->devs[i]->vt_pre_switch)
642*4882a593Smuzhiyun dmxInput->devs[i]->vt_pre_switch(dmxInput->devs[i]->private);
643*4882a593Smuzhiyun dmxInput->vt_switched = dmxInput->vt_switch_pending;
644*4882a593Smuzhiyun dmxInput->vt_switch_pending = 0;
645*4882a593Smuzhiyun for (i = 0; i < dmxInput->numDevs; i++) {
646*4882a593Smuzhiyun if (dmxInput->devs[i]->vt_switch) {
647*4882a593Smuzhiyun if (!dmxInput->devs[i]->vt_switch(dmxInput->devs[i]->private,
648*4882a593Smuzhiyun dmxInput->vt_switched,
649*4882a593Smuzhiyun dmxSwitchReturn, dmxInput))
650*4882a593Smuzhiyun dmxSwitchReturn(dmxInput);
651*4882a593Smuzhiyun break; /* Only call one vt_switch routine */
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun }
655*4882a593Smuzhiyun dmxCollectAll(dmxInput);
656*4882a593Smuzhiyun }
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun static char *
dmxMakeUniqueDeviceName(DMXLocalInputInfoPtr dmxLocal)659*4882a593Smuzhiyun dmxMakeUniqueDeviceName(DMXLocalInputInfoPtr dmxLocal)
660*4882a593Smuzhiyun {
661*4882a593Smuzhiyun static int k = 0;
662*4882a593Smuzhiyun static int m = 0;
663*4882a593Smuzhiyun static int o = 0;
664*4882a593Smuzhiyun static unsigned long dmxGeneration = 0;
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun #define LEN 32
667*4882a593Smuzhiyun char *buf = malloc(LEN);
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun if (dmxGeneration != serverGeneration) {
670*4882a593Smuzhiyun k = m = o = 0;
671*4882a593Smuzhiyun dmxGeneration = serverGeneration;
672*4882a593Smuzhiyun }
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun switch (dmxLocal->type) {
675*4882a593Smuzhiyun case DMX_LOCAL_KEYBOARD:
676*4882a593Smuzhiyun snprintf(buf, LEN, "Keyboard%d", k++);
677*4882a593Smuzhiyun break;
678*4882a593Smuzhiyun case DMX_LOCAL_MOUSE:
679*4882a593Smuzhiyun snprintf(buf, LEN, "Mouse%d", m++);
680*4882a593Smuzhiyun break;
681*4882a593Smuzhiyun default:
682*4882a593Smuzhiyun snprintf(buf, LEN, "Other%d", o++);
683*4882a593Smuzhiyun break;
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun return buf;
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun static DeviceIntPtr
dmxAddDevice(DMXLocalInputInfoPtr dmxLocal)690*4882a593Smuzhiyun dmxAddDevice(DMXLocalInputInfoPtr dmxLocal)
691*4882a593Smuzhiyun {
692*4882a593Smuzhiyun DeviceIntPtr pDevice;
693*4882a593Smuzhiyun Atom atom;
694*4882a593Smuzhiyun const char *name = NULL;
695*4882a593Smuzhiyun char *devname;
696*4882a593Smuzhiyun DMXInputInfo *dmxInput;
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun if (!dmxLocal)
699*4882a593Smuzhiyun return NULL;
700*4882a593Smuzhiyun dmxInput = &dmxInputs[dmxLocal->inputIdx];
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun if (dmxLocal->sendsCore) {
703*4882a593Smuzhiyun if (dmxLocal->type == DMX_LOCAL_KEYBOARD && !dmxLocalCoreKeyboard) {
704*4882a593Smuzhiyun dmxLocal->isCore = 1;
705*4882a593Smuzhiyun dmxLocalCoreKeyboard = dmxLocal;
706*4882a593Smuzhiyun name = "keyboard";
707*4882a593Smuzhiyun }
708*4882a593Smuzhiyun if (dmxLocal->type == DMX_LOCAL_MOUSE && !dmxLocalCorePointer) {
709*4882a593Smuzhiyun dmxLocal->isCore = 1;
710*4882a593Smuzhiyun dmxLocalCorePointer = dmxLocal;
711*4882a593Smuzhiyun name = "pointer";
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun }
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun if (!name) {
716*4882a593Smuzhiyun name = "extension";
717*4882a593Smuzhiyun }
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun if (!name)
720*4882a593Smuzhiyun dmxLog(dmxFatal, "Cannot add device %s\n", dmxLocal->name);
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun pDevice = AddInputDevice(serverClient, dmxDeviceOnOff, TRUE);
723*4882a593Smuzhiyun if (!pDevice) {
724*4882a593Smuzhiyun dmxLog(dmxError, "Too many devices -- cannot add device %s\n",
725*4882a593Smuzhiyun dmxLocal->name);
726*4882a593Smuzhiyun return NULL;
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun pDevice->public.devicePrivate = dmxLocal;
729*4882a593Smuzhiyun dmxLocal->pDevice = pDevice;
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun devname = dmxMakeUniqueDeviceName(dmxLocal);
732*4882a593Smuzhiyun atom = MakeAtom((char *) devname, strlen(devname), TRUE);
733*4882a593Smuzhiyun pDevice->type = atom;
734*4882a593Smuzhiyun pDevice->name = devname;
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun if (dmxLocal->isCore && dmxLocal->type == DMX_LOCAL_MOUSE) {
737*4882a593Smuzhiyun #if 00 /*BP*/
738*4882a593Smuzhiyun miRegisterPointerDevice(screenInfo.screens[0], pDevice);
739*4882a593Smuzhiyun #else
740*4882a593Smuzhiyun /* Nothing? dmxDeviceOnOff() should get called to init, right? */
741*4882a593Smuzhiyun #endif
742*4882a593Smuzhiyun }
743*4882a593Smuzhiyun
744*4882a593Smuzhiyun if (dmxLocal->create_private)
745*4882a593Smuzhiyun dmxLocal->private = dmxLocal->create_private(pDevice);
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun dmxLogInput(dmxInput, "Added %s as %s device called %s%s\n",
748*4882a593Smuzhiyun dmxLocal->name, name, devname,
749*4882a593Smuzhiyun dmxLocal->isCore
750*4882a593Smuzhiyun ? " [core]"
751*4882a593Smuzhiyun : (dmxLocal->sendsCore ? " [sends core events]" : ""));
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun return pDevice;
754*4882a593Smuzhiyun }
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun static DMXLocalInputInfoPtr
dmxLookupLocal(const char * name)757*4882a593Smuzhiyun dmxLookupLocal(const char *name)
758*4882a593Smuzhiyun {
759*4882a593Smuzhiyun DMXLocalInputInfoPtr pt;
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun for (pt = &DMXLocalDevices[0]; pt->name; ++pt)
762*4882a593Smuzhiyun if (!strcmp(pt->name, name))
763*4882a593Smuzhiyun return pt; /* search for device name */
764*4882a593Smuzhiyun return NULL;
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun /** Copy the local input information from \a s into a new \a devs slot
768*4882a593Smuzhiyun * in \a dmxInput. */
769*4882a593Smuzhiyun DMXLocalInputInfoPtr
dmxInputCopyLocal(DMXInputInfo * dmxInput,DMXLocalInputInfoPtr s)770*4882a593Smuzhiyun dmxInputCopyLocal(DMXInputInfo * dmxInput, DMXLocalInputInfoPtr s)
771*4882a593Smuzhiyun {
772*4882a593Smuzhiyun DMXLocalInputInfoPtr dmxLocal = malloc(sizeof(*dmxLocal));
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun if (!dmxLocal)
775*4882a593Smuzhiyun dmxLog(dmxFatal, "DMXLocalInputInfoPtr: out of memory\n");
776*4882a593Smuzhiyun
777*4882a593Smuzhiyun memcpy(dmxLocal, s, sizeof(*dmxLocal));
778*4882a593Smuzhiyun dmxLocal->inputIdx = dmxInput->inputIdx;
779*4882a593Smuzhiyun dmxLocal->sendsCore = dmxInput->core;
780*4882a593Smuzhiyun dmxLocal->savedSendsCore = dmxInput->core;
781*4882a593Smuzhiyun dmxLocal->deviceId = -1;
782*4882a593Smuzhiyun
783*4882a593Smuzhiyun ++dmxInput->numDevs;
784*4882a593Smuzhiyun dmxInput->devs = reallocarray(dmxInput->devs,
785*4882a593Smuzhiyun dmxInput->numDevs, sizeof(*dmxInput->devs));
786*4882a593Smuzhiyun dmxInput->devs[dmxInput->numDevs - 1] = dmxLocal;
787*4882a593Smuzhiyun
788*4882a593Smuzhiyun return dmxLocal;
789*4882a593Smuzhiyun }
790*4882a593Smuzhiyun
791*4882a593Smuzhiyun static void
dmxPopulateLocal(DMXInputInfo * dmxInput,dmxArg a)792*4882a593Smuzhiyun dmxPopulateLocal(DMXInputInfo * dmxInput, dmxArg a)
793*4882a593Smuzhiyun {
794*4882a593Smuzhiyun int i;
795*4882a593Smuzhiyun int help = 0;
796*4882a593Smuzhiyun DMXLocalInputInfoRec *pt;
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun for (i = 1; i < dmxArgC(a); i++) {
799*4882a593Smuzhiyun const char *name = dmxArgV(a, i);
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun if ((pt = dmxLookupLocal(name))) {
802*4882a593Smuzhiyun dmxInputCopyLocal(dmxInput, pt);
803*4882a593Smuzhiyun }
804*4882a593Smuzhiyun else {
805*4882a593Smuzhiyun if (strlen(name))
806*4882a593Smuzhiyun dmxLog(dmxWarning, "Could not find a driver called %s\n", name);
807*4882a593Smuzhiyun ++help;
808*4882a593Smuzhiyun }
809*4882a593Smuzhiyun }
810*4882a593Smuzhiyun if (help) {
811*4882a593Smuzhiyun dmxLog(dmxInfo, "Available local device drivers:\n");
812*4882a593Smuzhiyun for (pt = &DMXLocalDevices[0]; pt->name; ++pt) {
813*4882a593Smuzhiyun const char *type;
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun switch (pt->type) {
816*4882a593Smuzhiyun case DMX_LOCAL_KEYBOARD:
817*4882a593Smuzhiyun type = "keyboard";
818*4882a593Smuzhiyun break;
819*4882a593Smuzhiyun case DMX_LOCAL_MOUSE:
820*4882a593Smuzhiyun type = "pointer";
821*4882a593Smuzhiyun break;
822*4882a593Smuzhiyun default:
823*4882a593Smuzhiyun type = "unknown";
824*4882a593Smuzhiyun break;
825*4882a593Smuzhiyun }
826*4882a593Smuzhiyun dmxLog(dmxInfo, " %s (%s)\n", pt->name, type);
827*4882a593Smuzhiyun }
828*4882a593Smuzhiyun dmxLog(dmxFatal, "Must have valid local device driver\n");
829*4882a593Smuzhiyun }
830*4882a593Smuzhiyun }
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun int
dmxInputExtensionErrorHandler(Display * dsp,_Xconst char * name,_Xconst char * reason)833*4882a593Smuzhiyun dmxInputExtensionErrorHandler(Display * dsp, _Xconst char *name,
834*4882a593Smuzhiyun _Xconst char *reason)
835*4882a593Smuzhiyun {
836*4882a593Smuzhiyun return 0;
837*4882a593Smuzhiyun }
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun static void
dmxInputScanForExtensions(DMXInputInfo * dmxInput,int doXI)840*4882a593Smuzhiyun dmxInputScanForExtensions(DMXInputInfo * dmxInput, int doXI)
841*4882a593Smuzhiyun {
842*4882a593Smuzhiyun XExtensionVersion *ext;
843*4882a593Smuzhiyun XDeviceInfo *devices;
844*4882a593Smuzhiyun Display *dsp;
845*4882a593Smuzhiyun int num;
846*4882a593Smuzhiyun int i, j;
847*4882a593Smuzhiyun XextErrorHandler handler;
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun if (!(dsp = XOpenDisplay(dmxInput->name)))
850*4882a593Smuzhiyun return;
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun /* Print out information about the XInput Extension. */
853*4882a593Smuzhiyun handler = XSetExtensionErrorHandler(dmxInputExtensionErrorHandler);
854*4882a593Smuzhiyun ext = XGetExtensionVersion(dsp, INAME);
855*4882a593Smuzhiyun XSetExtensionErrorHandler(handler);
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun if (!ext || ext == (XExtensionVersion *) NoSuchExtension) {
858*4882a593Smuzhiyun dmxLogInput(dmxInput, "%s is not available\n", INAME);
859*4882a593Smuzhiyun }
860*4882a593Smuzhiyun else {
861*4882a593Smuzhiyun dmxLogInput(dmxInput, "Locating devices on %s (%s version %d.%d)\n",
862*4882a593Smuzhiyun dmxInput->name, INAME,
863*4882a593Smuzhiyun ext->major_version, ext->minor_version);
864*4882a593Smuzhiyun devices = XListInputDevices(dsp, &num);
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun XFree(ext);
867*4882a593Smuzhiyun ext = NULL;
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun /* Print a list of all devices */
870*4882a593Smuzhiyun for (i = 0; i < num; i++) {
871*4882a593Smuzhiyun const char *use = "Unknown";
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun switch (devices[i].use) {
874*4882a593Smuzhiyun case IsXPointer:
875*4882a593Smuzhiyun use = "XPointer";
876*4882a593Smuzhiyun break;
877*4882a593Smuzhiyun case IsXKeyboard:
878*4882a593Smuzhiyun use = "XKeyboard";
879*4882a593Smuzhiyun break;
880*4882a593Smuzhiyun case IsXExtensionDevice:
881*4882a593Smuzhiyun use = "XExtensionDevice";
882*4882a593Smuzhiyun break;
883*4882a593Smuzhiyun case IsXExtensionPointer:
884*4882a593Smuzhiyun use = "XExtensionPointer";
885*4882a593Smuzhiyun break;
886*4882a593Smuzhiyun case IsXExtensionKeyboard:
887*4882a593Smuzhiyun use = "XExtensionKeyboard";
888*4882a593Smuzhiyun break;
889*4882a593Smuzhiyun }
890*4882a593Smuzhiyun dmxLogInput(dmxInput, " %2d %-10.10s %-16.16s\n",
891*4882a593Smuzhiyun (int) devices[i].id,
892*4882a593Smuzhiyun devices[i].name ? devices[i].name : "", use);
893*4882a593Smuzhiyun }
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun /* Search for extensions */
896*4882a593Smuzhiyun for (i = 0; i < num; i++) {
897*4882a593Smuzhiyun switch (devices[i].use) {
898*4882a593Smuzhiyun case IsXKeyboard:
899*4882a593Smuzhiyun for (j = 0; j < dmxInput->numDevs; j++) {
900*4882a593Smuzhiyun DMXLocalInputInfoPtr dmxL = dmxInput->devs[j];
901*4882a593Smuzhiyun
902*4882a593Smuzhiyun if (dmxL->type == DMX_LOCAL_KEYBOARD && dmxL->deviceId < 0) {
903*4882a593Smuzhiyun dmxL->deviceId = devices[i].id;
904*4882a593Smuzhiyun dmxL->deviceName = (devices[i].name
905*4882a593Smuzhiyun ? strdup(devices[i].name)
906*4882a593Smuzhiyun : NULL);
907*4882a593Smuzhiyun }
908*4882a593Smuzhiyun }
909*4882a593Smuzhiyun break;
910*4882a593Smuzhiyun case IsXPointer:
911*4882a593Smuzhiyun for (j = 0; j < dmxInput->numDevs; j++) {
912*4882a593Smuzhiyun DMXLocalInputInfoPtr dmxL = dmxInput->devs[j];
913*4882a593Smuzhiyun
914*4882a593Smuzhiyun if (dmxL->type == DMX_LOCAL_MOUSE && dmxL->deviceId < 0) {
915*4882a593Smuzhiyun dmxL->deviceId = devices[i].id;
916*4882a593Smuzhiyun dmxL->deviceName = (devices[i].name
917*4882a593Smuzhiyun ? xstrdup(devices[i].name)
918*4882a593Smuzhiyun : NULL);
919*4882a593Smuzhiyun }
920*4882a593Smuzhiyun }
921*4882a593Smuzhiyun break;
922*4882a593Smuzhiyun }
923*4882a593Smuzhiyun }
924*4882a593Smuzhiyun XFreeDeviceList(devices);
925*4882a593Smuzhiyun }
926*4882a593Smuzhiyun XCloseDisplay(dsp);
927*4882a593Smuzhiyun }
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun /** Re-initialize all the devices described in \a dmxInput. Called from
930*4882a593Smuzhiyun #dmxAdjustCursorBoundaries before the cursor is redisplayed. */
931*4882a593Smuzhiyun void
dmxInputReInit(DMXInputInfo * dmxInput)932*4882a593Smuzhiyun dmxInputReInit(DMXInputInfo * dmxInput)
933*4882a593Smuzhiyun {
934*4882a593Smuzhiyun int i;
935*4882a593Smuzhiyun
936*4882a593Smuzhiyun for (i = 0; i < dmxInput->numDevs; i++) {
937*4882a593Smuzhiyun DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
938*4882a593Smuzhiyun
939*4882a593Smuzhiyun if (dmxLocal->reinit)
940*4882a593Smuzhiyun dmxLocal->reinit(&dmxLocal->pDevice->public);
941*4882a593Smuzhiyun }
942*4882a593Smuzhiyun }
943*4882a593Smuzhiyun
944*4882a593Smuzhiyun /** Re-initialize all the devices described in \a dmxInput. Called from
945*4882a593Smuzhiyun #dmxAdjustCursorBoundaries after the cursor is redisplayed. */
946*4882a593Smuzhiyun void
dmxInputLateReInit(DMXInputInfo * dmxInput)947*4882a593Smuzhiyun dmxInputLateReInit(DMXInputInfo * dmxInput)
948*4882a593Smuzhiyun {
949*4882a593Smuzhiyun int i;
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun for (i = 0; i < dmxInput->numDevs; i++) {
952*4882a593Smuzhiyun DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
953*4882a593Smuzhiyun
954*4882a593Smuzhiyun if (dmxLocal->latereinit)
955*4882a593Smuzhiyun dmxLocal->latereinit(&dmxLocal->pDevice->public);
956*4882a593Smuzhiyun }
957*4882a593Smuzhiyun }
958*4882a593Smuzhiyun
959*4882a593Smuzhiyun /** Initialize all of the devices described in \a dmxInput. */
960*4882a593Smuzhiyun void
dmxInputInit(DMXInputInfo * dmxInput)961*4882a593Smuzhiyun dmxInputInit(DMXInputInfo * dmxInput)
962*4882a593Smuzhiyun {
963*4882a593Smuzhiyun dmxArg a;
964*4882a593Smuzhiyun const char *name;
965*4882a593Smuzhiyun int i;
966*4882a593Smuzhiyun int doXI = 1; /* Include by default */
967*4882a593Smuzhiyun int forceConsole = 0;
968*4882a593Smuzhiyun int doWindows = 1; /* On by default */
969*4882a593Smuzhiyun int hasXkb = 0;
970*4882a593Smuzhiyun
971*4882a593Smuzhiyun a = dmxArgParse(dmxInput->name);
972*4882a593Smuzhiyun
973*4882a593Smuzhiyun name = dmxArgV(a, 0);
974*4882a593Smuzhiyun
975*4882a593Smuzhiyun if (!strcmp(name, "local")) {
976*4882a593Smuzhiyun dmxPopulateLocal(dmxInput, a);
977*4882a593Smuzhiyun }
978*4882a593Smuzhiyun else if (!strcmp(name, "dummy")) {
979*4882a593Smuzhiyun dmxInputCopyLocal(dmxInput, &DMXDummyMou);
980*4882a593Smuzhiyun dmxInputCopyLocal(dmxInput, &DMXDummyKbd);
981*4882a593Smuzhiyun dmxLogInput(dmxInput, "Using dummy input\n");
982*4882a593Smuzhiyun }
983*4882a593Smuzhiyun else {
984*4882a593Smuzhiyun int found;
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun for (i = 1; i < dmxArgC(a); i++) {
987*4882a593Smuzhiyun switch (hasXkb) {
988*4882a593Smuzhiyun case 1:
989*4882a593Smuzhiyun dmxInput->keycodes = xstrdup(dmxArgV(a, i));
990*4882a593Smuzhiyun ++hasXkb;
991*4882a593Smuzhiyun break;
992*4882a593Smuzhiyun case 2:
993*4882a593Smuzhiyun dmxInput->symbols = xstrdup(dmxArgV(a, i));
994*4882a593Smuzhiyun ++hasXkb;
995*4882a593Smuzhiyun break;
996*4882a593Smuzhiyun case 3:
997*4882a593Smuzhiyun dmxInput->geometry = xstrdup(dmxArgV(a, i));
998*4882a593Smuzhiyun hasXkb = 0;
999*4882a593Smuzhiyun break;
1000*4882a593Smuzhiyun case 0:
1001*4882a593Smuzhiyun if (!strcmp(dmxArgV(a, i), "noxi"))
1002*4882a593Smuzhiyun doXI = 0;
1003*4882a593Smuzhiyun else if (!strcmp(dmxArgV(a, i), "xi"))
1004*4882a593Smuzhiyun doXI = 1;
1005*4882a593Smuzhiyun else if (!strcmp(dmxArgV(a, i), "console"))
1006*4882a593Smuzhiyun forceConsole = 1;
1007*4882a593Smuzhiyun else if (!strcmp(dmxArgV(a, i), "noconsole"))
1008*4882a593Smuzhiyun forceConsole = 0;
1009*4882a593Smuzhiyun else if (!strcmp(dmxArgV(a, i), "windows"))
1010*4882a593Smuzhiyun doWindows = 1;
1011*4882a593Smuzhiyun else if (!strcmp(dmxArgV(a, i), "nowindows"))
1012*4882a593Smuzhiyun doWindows = 0;
1013*4882a593Smuzhiyun else if (!strcmp(dmxArgV(a, i), "xkb"))
1014*4882a593Smuzhiyun hasXkb = 1;
1015*4882a593Smuzhiyun else {
1016*4882a593Smuzhiyun dmxLog(dmxFatal, "Unknown input argument: %s\n", dmxArgV(a, i));
1017*4882a593Smuzhiyun }
1018*4882a593Smuzhiyun }
1019*4882a593Smuzhiyun }
1020*4882a593Smuzhiyun
1021*4882a593Smuzhiyun for (found = 0, i = 0; i < dmxNumScreens; i++) {
1022*4882a593Smuzhiyun if (dmxPropertySameDisplay(&dmxScreens[i], name)) {
1023*4882a593Smuzhiyun if (dmxScreens[i].shared)
1024*4882a593Smuzhiyun dmxLog(dmxFatal,
1025*4882a593Smuzhiyun "Cannot take input from shared backend (%s)\n",
1026*4882a593Smuzhiyun name);
1027*4882a593Smuzhiyun if (!dmxInput->core) {
1028*4882a593Smuzhiyun dmxLog(dmxWarning,
1029*4882a593Smuzhiyun "Cannot use core devices on a backend (%s)"
1030*4882a593Smuzhiyun " as XInput devices\n", name);
1031*4882a593Smuzhiyun }
1032*4882a593Smuzhiyun else {
1033*4882a593Smuzhiyun char *pt;
1034*4882a593Smuzhiyun
1035*4882a593Smuzhiyun for (pt = (char *) dmxInput->name; pt && *pt; pt++)
1036*4882a593Smuzhiyun if (*pt == ',')
1037*4882a593Smuzhiyun *pt = '\0';
1038*4882a593Smuzhiyun dmxInputCopyLocal(dmxInput, &DMXBackendMou);
1039*4882a593Smuzhiyun dmxInputCopyLocal(dmxInput, &DMXBackendKbd);
1040*4882a593Smuzhiyun dmxInput->scrnIdx = i;
1041*4882a593Smuzhiyun dmxLogInput(dmxInput,
1042*4882a593Smuzhiyun "Using backend input from %s\n", name);
1043*4882a593Smuzhiyun }
1044*4882a593Smuzhiyun ++found;
1045*4882a593Smuzhiyun break;
1046*4882a593Smuzhiyun }
1047*4882a593Smuzhiyun }
1048*4882a593Smuzhiyun if (!found || forceConsole) {
1049*4882a593Smuzhiyun char *pt;
1050*4882a593Smuzhiyun
1051*4882a593Smuzhiyun if (found)
1052*4882a593Smuzhiyun dmxInput->console = TRUE;
1053*4882a593Smuzhiyun for (pt = (char *) dmxInput->name; pt && *pt; pt++)
1054*4882a593Smuzhiyun if (*pt == ',')
1055*4882a593Smuzhiyun *pt = '\0';
1056*4882a593Smuzhiyun dmxInputCopyLocal(dmxInput, &DMXConsoleMou);
1057*4882a593Smuzhiyun dmxInputCopyLocal(dmxInput, &DMXConsoleKbd);
1058*4882a593Smuzhiyun if (doWindows) {
1059*4882a593Smuzhiyun dmxInput->windows = TRUE;
1060*4882a593Smuzhiyun dmxInput->updateWindowInfo = dmxUpdateWindowInformation;
1061*4882a593Smuzhiyun }
1062*4882a593Smuzhiyun dmxLogInput(dmxInput,
1063*4882a593Smuzhiyun "Using console input from %s (%s windows)\n",
1064*4882a593Smuzhiyun name, doWindows ? "with" : "without");
1065*4882a593Smuzhiyun }
1066*4882a593Smuzhiyun }
1067*4882a593Smuzhiyun
1068*4882a593Smuzhiyun dmxArgFree(a);
1069*4882a593Smuzhiyun
1070*4882a593Smuzhiyun /* Locate extensions we may be interested in */
1071*4882a593Smuzhiyun dmxInputScanForExtensions(dmxInput, doXI);
1072*4882a593Smuzhiyun
1073*4882a593Smuzhiyun for (i = 0; i < dmxInput->numDevs; i++) {
1074*4882a593Smuzhiyun DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
1075*4882a593Smuzhiyun
1076*4882a593Smuzhiyun dmxLocal->pDevice = dmxAddDevice(dmxLocal);
1077*4882a593Smuzhiyun }
1078*4882a593Smuzhiyun
1079*4882a593Smuzhiyun dmxInput->processInputEvents = dmxProcessInputEvents;
1080*4882a593Smuzhiyun dmxInput->detached = False;
1081*4882a593Smuzhiyun
1082*4882a593Smuzhiyun RegisterBlockAndWakeupHandlers(dmxBlockHandler, dmxWakeupHandler,
1083*4882a593Smuzhiyun (void *) (uintptr_t) dmxInput->inputIdx);
1084*4882a593Smuzhiyun }
1085*4882a593Smuzhiyun
1086*4882a593Smuzhiyun static void
dmxInputFreeLocal(DMXLocalInputInfoRec * local)1087*4882a593Smuzhiyun dmxInputFreeLocal(DMXLocalInputInfoRec * local)
1088*4882a593Smuzhiyun {
1089*4882a593Smuzhiyun if (!local)
1090*4882a593Smuzhiyun return;
1091*4882a593Smuzhiyun if (local->isCore && local->type == DMX_LOCAL_MOUSE)
1092*4882a593Smuzhiyun dmxLocalCorePointer = NULL;
1093*4882a593Smuzhiyun if (local->isCore && local->type == DMX_LOCAL_KEYBOARD)
1094*4882a593Smuzhiyun dmxLocalCoreKeyboard = NULL;
1095*4882a593Smuzhiyun if (local->destroy_private)
1096*4882a593Smuzhiyun local->destroy_private(local->private);
1097*4882a593Smuzhiyun free(local->history);
1098*4882a593Smuzhiyun free(local->valuators);
1099*4882a593Smuzhiyun free((void *) local->deviceName);
1100*4882a593Smuzhiyun local->private = NULL;
1101*4882a593Smuzhiyun local->history = NULL;
1102*4882a593Smuzhiyun local->deviceName = NULL;
1103*4882a593Smuzhiyun free(local);
1104*4882a593Smuzhiyun }
1105*4882a593Smuzhiyun
1106*4882a593Smuzhiyun /** Free all of the memory associated with \a dmxInput */
1107*4882a593Smuzhiyun void
dmxInputFree(DMXInputInfo * dmxInput)1108*4882a593Smuzhiyun dmxInputFree(DMXInputInfo * dmxInput)
1109*4882a593Smuzhiyun {
1110*4882a593Smuzhiyun int i;
1111*4882a593Smuzhiyun
1112*4882a593Smuzhiyun if (!dmxInput)
1113*4882a593Smuzhiyun return;
1114*4882a593Smuzhiyun
1115*4882a593Smuzhiyun free(dmxInput->keycodes);
1116*4882a593Smuzhiyun free(dmxInput->symbols);
1117*4882a593Smuzhiyun free(dmxInput->geometry);
1118*4882a593Smuzhiyun
1119*4882a593Smuzhiyun for (i = 0; i < dmxInput->numDevs; i++) {
1120*4882a593Smuzhiyun dmxInputFreeLocal(dmxInput->devs[i]);
1121*4882a593Smuzhiyun dmxInput->devs[i] = NULL;
1122*4882a593Smuzhiyun }
1123*4882a593Smuzhiyun free(dmxInput->devs);
1124*4882a593Smuzhiyun dmxInput->devs = NULL;
1125*4882a593Smuzhiyun dmxInput->numDevs = 0;
1126*4882a593Smuzhiyun if (dmxInput->freename)
1127*4882a593Smuzhiyun free((void *) dmxInput->name);
1128*4882a593Smuzhiyun dmxInput->name = NULL;
1129*4882a593Smuzhiyun }
1130*4882a593Smuzhiyun
1131*4882a593Smuzhiyun /** Log information about all of the known devices using #dmxLog(). */
1132*4882a593Smuzhiyun void
dmxInputLogDevices(void)1133*4882a593Smuzhiyun dmxInputLogDevices(void)
1134*4882a593Smuzhiyun {
1135*4882a593Smuzhiyun int i, j;
1136*4882a593Smuzhiyun
1137*4882a593Smuzhiyun dmxLog(dmxInfo, "%d devices:\n", dmxGetInputCount());
1138*4882a593Smuzhiyun dmxLog(dmxInfo, " Id Name Classes\n");
1139*4882a593Smuzhiyun for (j = 0; j < dmxNumInputs; j++) {
1140*4882a593Smuzhiyun DMXInputInfo *dmxInput = &dmxInputs[j];
1141*4882a593Smuzhiyun const char *pt = strchr(dmxInput->name, ',');
1142*4882a593Smuzhiyun int len = (pt ? (size_t) (pt - dmxInput->name)
1143*4882a593Smuzhiyun : strlen(dmxInput->name));
1144*4882a593Smuzhiyun
1145*4882a593Smuzhiyun for (i = 0; i < dmxInput->numDevs; i++) {
1146*4882a593Smuzhiyun DeviceIntPtr pDevice = dmxInput->devs[i]->pDevice;
1147*4882a593Smuzhiyun
1148*4882a593Smuzhiyun if (pDevice) {
1149*4882a593Smuzhiyun dmxLog(dmxInfo, " %2d%c %-20.20s",
1150*4882a593Smuzhiyun pDevice->id,
1151*4882a593Smuzhiyun dmxInput->detached ? 'D' : ' ', pDevice->name);
1152*4882a593Smuzhiyun if (pDevice->key)
1153*4882a593Smuzhiyun dmxLogCont(dmxInfo, " key");
1154*4882a593Smuzhiyun if (pDevice->valuator)
1155*4882a593Smuzhiyun dmxLogCont(dmxInfo, " val");
1156*4882a593Smuzhiyun if (pDevice->button)
1157*4882a593Smuzhiyun dmxLogCont(dmxInfo, " btn");
1158*4882a593Smuzhiyun if (pDevice->focus)
1159*4882a593Smuzhiyun dmxLogCont(dmxInfo, " foc");
1160*4882a593Smuzhiyun if (pDevice->kbdfeed)
1161*4882a593Smuzhiyun dmxLogCont(dmxInfo, " fb/kbd");
1162*4882a593Smuzhiyun if (pDevice->ptrfeed)
1163*4882a593Smuzhiyun dmxLogCont(dmxInfo, " fb/ptr");
1164*4882a593Smuzhiyun if (pDevice->intfeed)
1165*4882a593Smuzhiyun dmxLogCont(dmxInfo, " fb/int");
1166*4882a593Smuzhiyun if (pDevice->stringfeed)
1167*4882a593Smuzhiyun dmxLogCont(dmxInfo, " fb/str");
1168*4882a593Smuzhiyun if (pDevice->bell)
1169*4882a593Smuzhiyun dmxLogCont(dmxInfo, " fb/bel");
1170*4882a593Smuzhiyun if (pDevice->leds)
1171*4882a593Smuzhiyun dmxLogCont(dmxInfo, " fb/led");
1172*4882a593Smuzhiyun if (!pDevice->key && !pDevice->valuator && !pDevice->button
1173*4882a593Smuzhiyun && !pDevice->focus && !pDevice->kbdfeed
1174*4882a593Smuzhiyun && !pDevice->ptrfeed && !pDevice->intfeed
1175*4882a593Smuzhiyun && !pDevice->stringfeed && !pDevice->bell && !pDevice->leds)
1176*4882a593Smuzhiyun dmxLogCont(dmxInfo, " (none)");
1177*4882a593Smuzhiyun
1178*4882a593Smuzhiyun dmxLogCont(dmxInfo, "\t[i%d/%*.*s",
1179*4882a593Smuzhiyun dmxInput->inputIdx, len, len, dmxInput->name);
1180*4882a593Smuzhiyun if (dmxInput->devs[i]->deviceId >= 0)
1181*4882a593Smuzhiyun dmxLogCont(dmxInfo, "/id%d", (int) dmxInput->devs[i]->deviceId);
1182*4882a593Smuzhiyun if (dmxInput->devs[i]->deviceName)
1183*4882a593Smuzhiyun dmxLogCont(dmxInfo, "=%s", dmxInput->devs[i]->deviceName);
1184*4882a593Smuzhiyun dmxLogCont(dmxInfo, "] %s\n",
1185*4882a593Smuzhiyun dmxInput->devs[i]->isCore
1186*4882a593Smuzhiyun ? "core"
1187*4882a593Smuzhiyun : (dmxInput->devs[i]->sendsCore
1188*4882a593Smuzhiyun ? "extension (sends core events)" : "extension"));
1189*4882a593Smuzhiyun }
1190*4882a593Smuzhiyun }
1191*4882a593Smuzhiyun }
1192*4882a593Smuzhiyun }
1193*4882a593Smuzhiyun
1194*4882a593Smuzhiyun /** Detach an input */
1195*4882a593Smuzhiyun int
dmxInputDetach(DMXInputInfo * dmxInput)1196*4882a593Smuzhiyun dmxInputDetach(DMXInputInfo * dmxInput)
1197*4882a593Smuzhiyun {
1198*4882a593Smuzhiyun int i;
1199*4882a593Smuzhiyun
1200*4882a593Smuzhiyun if (dmxInput->detached)
1201*4882a593Smuzhiyun return BadAccess;
1202*4882a593Smuzhiyun
1203*4882a593Smuzhiyun for (i = 0; i < dmxInput->numDevs; i++) {
1204*4882a593Smuzhiyun DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
1205*4882a593Smuzhiyun
1206*4882a593Smuzhiyun dmxLogInput(dmxInput, "Detaching device id %d: %s%s\n",
1207*4882a593Smuzhiyun dmxLocal->pDevice->id,
1208*4882a593Smuzhiyun dmxLocal->pDevice->name,
1209*4882a593Smuzhiyun dmxLocal->isCore
1210*4882a593Smuzhiyun ? " [core]"
1211*4882a593Smuzhiyun : (dmxLocal->sendsCore ? " [sends core events]" : ""));
1212*4882a593Smuzhiyun DisableDevice(dmxLocal->pDevice, TRUE);
1213*4882a593Smuzhiyun }
1214*4882a593Smuzhiyun dmxInput->detached = True;
1215*4882a593Smuzhiyun dmxInputLogDevices();
1216*4882a593Smuzhiyun return 0;
1217*4882a593Smuzhiyun }
1218*4882a593Smuzhiyun
1219*4882a593Smuzhiyun /** Search for input associated with \a dmxScreen, and detach. */
1220*4882a593Smuzhiyun void
dmxInputDetachAll(DMXScreenInfo * dmxScreen)1221*4882a593Smuzhiyun dmxInputDetachAll(DMXScreenInfo * dmxScreen)
1222*4882a593Smuzhiyun {
1223*4882a593Smuzhiyun int i;
1224*4882a593Smuzhiyun
1225*4882a593Smuzhiyun for (i = 0; i < dmxNumInputs; i++) {
1226*4882a593Smuzhiyun DMXInputInfo *dmxInput = &dmxInputs[i];
1227*4882a593Smuzhiyun
1228*4882a593Smuzhiyun if (dmxInput->scrnIdx == dmxScreen->index)
1229*4882a593Smuzhiyun dmxInputDetach(dmxInput);
1230*4882a593Smuzhiyun }
1231*4882a593Smuzhiyun }
1232*4882a593Smuzhiyun
1233*4882a593Smuzhiyun /** Search for input associated with \a deviceId, and detach. */
1234*4882a593Smuzhiyun int
dmxInputDetachId(int id)1235*4882a593Smuzhiyun dmxInputDetachId(int id)
1236*4882a593Smuzhiyun {
1237*4882a593Smuzhiyun DMXInputInfo *dmxInput = dmxInputLocateId(id);
1238*4882a593Smuzhiyun
1239*4882a593Smuzhiyun if (!dmxInput)
1240*4882a593Smuzhiyun return BadValue;
1241*4882a593Smuzhiyun
1242*4882a593Smuzhiyun return dmxInputDetach(dmxInput);
1243*4882a593Smuzhiyun }
1244*4882a593Smuzhiyun
1245*4882a593Smuzhiyun DMXInputInfo *
dmxInputLocateId(int id)1246*4882a593Smuzhiyun dmxInputLocateId(int id)
1247*4882a593Smuzhiyun {
1248*4882a593Smuzhiyun int i, j;
1249*4882a593Smuzhiyun
1250*4882a593Smuzhiyun for (i = 0; i < dmxNumInputs; i++) {
1251*4882a593Smuzhiyun DMXInputInfo *dmxInput = &dmxInputs[i];
1252*4882a593Smuzhiyun
1253*4882a593Smuzhiyun for (j = 0; j < dmxInput->numDevs; j++) {
1254*4882a593Smuzhiyun DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j];
1255*4882a593Smuzhiyun
1256*4882a593Smuzhiyun if (dmxLocal->pDevice->id == id)
1257*4882a593Smuzhiyun return dmxInput;
1258*4882a593Smuzhiyun }
1259*4882a593Smuzhiyun }
1260*4882a593Smuzhiyun return NULL;
1261*4882a593Smuzhiyun }
1262*4882a593Smuzhiyun
1263*4882a593Smuzhiyun static int
dmxInputAttachNew(DMXInputInfo * dmxInput,int * id)1264*4882a593Smuzhiyun dmxInputAttachNew(DMXInputInfo * dmxInput, int *id)
1265*4882a593Smuzhiyun {
1266*4882a593Smuzhiyun dmxInputInit(dmxInput);
1267*4882a593Smuzhiyun InitAndStartDevices();
1268*4882a593Smuzhiyun if (id && dmxInput->devs)
1269*4882a593Smuzhiyun *id = dmxInput->devs[0]->pDevice->id;
1270*4882a593Smuzhiyun dmxInputLogDevices();
1271*4882a593Smuzhiyun return 0;
1272*4882a593Smuzhiyun }
1273*4882a593Smuzhiyun
1274*4882a593Smuzhiyun static int
dmxInputAttachOld(DMXInputInfo * dmxInput,int * id)1275*4882a593Smuzhiyun dmxInputAttachOld(DMXInputInfo * dmxInput, int *id)
1276*4882a593Smuzhiyun {
1277*4882a593Smuzhiyun int i;
1278*4882a593Smuzhiyun
1279*4882a593Smuzhiyun dmxInput->detached = False;
1280*4882a593Smuzhiyun for (i = 0; i < dmxInput->numDevs; i++) {
1281*4882a593Smuzhiyun DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
1282*4882a593Smuzhiyun
1283*4882a593Smuzhiyun if (id)
1284*4882a593Smuzhiyun *id = dmxLocal->pDevice->id;
1285*4882a593Smuzhiyun dmxLogInput(dmxInput,
1286*4882a593Smuzhiyun "Attaching device id %d: %s%s\n",
1287*4882a593Smuzhiyun dmxLocal->pDevice->id,
1288*4882a593Smuzhiyun dmxLocal->pDevice->name,
1289*4882a593Smuzhiyun dmxLocal->isCore
1290*4882a593Smuzhiyun ? " [core]"
1291*4882a593Smuzhiyun : (dmxLocal->sendsCore ? " [sends core events]" : ""));
1292*4882a593Smuzhiyun EnableDevice(dmxLocal->pDevice, TRUE);
1293*4882a593Smuzhiyun }
1294*4882a593Smuzhiyun dmxInputLogDevices();
1295*4882a593Smuzhiyun return 0;
1296*4882a593Smuzhiyun }
1297*4882a593Smuzhiyun
1298*4882a593Smuzhiyun int
dmxInputAttachConsole(const char * name,int isCore,int * id)1299*4882a593Smuzhiyun dmxInputAttachConsole(const char *name, int isCore, int *id)
1300*4882a593Smuzhiyun {
1301*4882a593Smuzhiyun DMXInputInfo *dmxInput;
1302*4882a593Smuzhiyun int i;
1303*4882a593Smuzhiyun
1304*4882a593Smuzhiyun for (i = 0; i < dmxNumInputs; i++) {
1305*4882a593Smuzhiyun dmxInput = &dmxInputs[i];
1306*4882a593Smuzhiyun if (dmxInput->scrnIdx == -1
1307*4882a593Smuzhiyun && dmxInput->detached && !strcmp(dmxInput->name, name)) {
1308*4882a593Smuzhiyun /* Found match */
1309*4882a593Smuzhiyun dmxLogInput(dmxInput, "Reattaching detached console input\n");
1310*4882a593Smuzhiyun return dmxInputAttachOld(dmxInput, id);
1311*4882a593Smuzhiyun }
1312*4882a593Smuzhiyun }
1313*4882a593Smuzhiyun
1314*4882a593Smuzhiyun /* No match found */
1315*4882a593Smuzhiyun dmxInput = dmxConfigAddInput(xstrdup(name), isCore);
1316*4882a593Smuzhiyun dmxInput->freename = TRUE;
1317*4882a593Smuzhiyun dmxLogInput(dmxInput, "Attaching new console input\n");
1318*4882a593Smuzhiyun return dmxInputAttachNew(dmxInput, id);
1319*4882a593Smuzhiyun }
1320*4882a593Smuzhiyun
1321*4882a593Smuzhiyun int
dmxInputAttachBackend(int physicalScreen,int isCore,int * id)1322*4882a593Smuzhiyun dmxInputAttachBackend(int physicalScreen, int isCore, int *id)
1323*4882a593Smuzhiyun {
1324*4882a593Smuzhiyun DMXInputInfo *dmxInput;
1325*4882a593Smuzhiyun DMXScreenInfo *dmxScreen;
1326*4882a593Smuzhiyun int i;
1327*4882a593Smuzhiyun
1328*4882a593Smuzhiyun if (physicalScreen < 0 || physicalScreen >= dmxNumScreens)
1329*4882a593Smuzhiyun return BadValue;
1330*4882a593Smuzhiyun for (i = 0; i < dmxNumInputs; i++) {
1331*4882a593Smuzhiyun dmxInput = &dmxInputs[i];
1332*4882a593Smuzhiyun if (dmxInput->scrnIdx != -1 && dmxInput->scrnIdx == physicalScreen) {
1333*4882a593Smuzhiyun /* Found match */
1334*4882a593Smuzhiyun if (!dmxInput->detached)
1335*4882a593Smuzhiyun return BadAccess; /* Already attached */
1336*4882a593Smuzhiyun dmxScreen = &dmxScreens[physicalScreen];
1337*4882a593Smuzhiyun if (!dmxScreen->beDisplay)
1338*4882a593Smuzhiyun return BadAccess; /* Screen detached */
1339*4882a593Smuzhiyun dmxLogInput(dmxInput, "Reattaching detached backend input\n");
1340*4882a593Smuzhiyun return dmxInputAttachOld(dmxInput, id);
1341*4882a593Smuzhiyun }
1342*4882a593Smuzhiyun }
1343*4882a593Smuzhiyun /* No match found */
1344*4882a593Smuzhiyun dmxScreen = &dmxScreens[physicalScreen];
1345*4882a593Smuzhiyun if (!dmxScreen->beDisplay)
1346*4882a593Smuzhiyun return BadAccess; /* Screen detached */
1347*4882a593Smuzhiyun dmxInput = dmxConfigAddInput(dmxScreen->name, isCore);
1348*4882a593Smuzhiyun dmxLogInput(dmxInput, "Attaching new backend input\n");
1349*4882a593Smuzhiyun return dmxInputAttachNew(dmxInput, id);
1350*4882a593Smuzhiyun }
1351