105b261ecSmrg/* 235c4bbdfSmrg * Copyright © 1999 Keith Packard 335c4bbdfSmrg * Copyright © 2006 Nokia Corporation 405b261ecSmrg * 505b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 705b261ecSmrg * the above copyright notice appear in all copies and that both that 805b261ecSmrg * copyright notice and this permission notice appear in supporting 905b261ecSmrg * documentation, and that the name of the authors not be used in 1005b261ecSmrg * advertising or publicity pertaining to distribution of the software without 1105b261ecSmrg * specific, written prior permission. The authors make no 1205b261ecSmrg * representations about the suitability of this software for any purpose. It 1305b261ecSmrg * is provided "as is" without express or implied warranty. 1405b261ecSmrg * 1505b261ecSmrg * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1605b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1705b261ecSmrg * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1805b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1905b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 2005b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2105b261ecSmrg * PERFORMANCE OF THIS SOFTWARE. 2205b261ecSmrg */ 2305b261ecSmrg 241b5d61b8Smrg#ifdef HAVE_DIX_CONFIG_H 251b5d61b8Smrg#include <dix-config.h> 261b5d61b8Smrg#include <xkb-config.h> 2705b261ecSmrg#endif 2805b261ecSmrg#include "kdrive.h" 2905b261ecSmrg#include "inputstr.h" 3005b261ecSmrg 3105b261ecSmrg#define XK_PUBLISHING 3205b261ecSmrg#include <X11/keysym.h> 3305b261ecSmrg#if HAVE_X11_XF86KEYSYM_H 3405b261ecSmrg#include <X11/XF86keysym.h> 3505b261ecSmrg#endif 3605b261ecSmrg#include <stdio.h> 371b5d61b8Smrg#ifdef __sun 3835c4bbdfSmrg#include <sys/file.h> /* needed for FNONBLOCK & FASYNC */ 3905b261ecSmrg#endif 4005b261ecSmrg 416747b715Smrg#include "xkbsrv.h" 4205b261ecSmrg 4305b261ecSmrg#include <X11/extensions/XI.h> 4405b261ecSmrg#include <X11/extensions/XIproto.h> 4535c4bbdfSmrg#include "XIstubs.h" /* even though we don't use stubs. cute, no? */ 4605b261ecSmrg#include "exevents.h" 4705b261ecSmrg#include "extinit.h" 4805b261ecSmrg#include "exglobals.h" 496747b715Smrg#include "eventstr.h" 506747b715Smrg#include "xserver-properties.h" 519ace9065Smrg#include "inpututils.h" 5235c4bbdfSmrg#include "optionstr.h" 5305b261ecSmrg 541b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL) 551b5d61b8Smrg#include <hotplug.h> 561b5d61b8Smrg#endif 571b5d61b8Smrg 5805b261ecSmrg#define AtomFromName(x) MakeAtom(x, strlen(x), 1) 5905b261ecSmrg 6005b261ecSmrgstruct KdConfigDevice { 6105b261ecSmrg char *line; 6205b261ecSmrg struct KdConfigDevice *next; 6305b261ecSmrg}; 6405b261ecSmrg 6505b261ecSmrg/* kdKeyboards and kdPointers hold all the real devices. */ 6635c4bbdfSmrgstatic KdKeyboardInfo *kdKeyboards = NULL; 6735c4bbdfSmrgstatic KdPointerInfo *kdPointers = NULL; 6835c4bbdfSmrgstatic struct KdConfigDevice *kdConfigKeyboards = NULL; 6935c4bbdfSmrgstatic struct KdConfigDevice *kdConfigPointers = NULL; 7005b261ecSmrg 7105b261ecSmrgstatic KdKeyboardDriver *kdKeyboardDrivers = NULL; 7235c4bbdfSmrgstatic KdPointerDriver *kdPointerDrivers = NULL; 7305b261ecSmrg 7435c4bbdfSmrgstatic Bool kdInputEnabled; 7535c4bbdfSmrgstatic Bool kdOffScreen; 7635c4bbdfSmrgstatic unsigned long kdOffScreenTime; 7705b261ecSmrg 7835c4bbdfSmrgstatic KdPointerMatrix kdPointerMatrix = { 7935c4bbdfSmrg {{1, 0, 0}, 8035c4bbdfSmrg {0, 1, 0}} 8105b261ecSmrg}; 8205b261ecSmrg 8335c4bbdfSmrgextern Bool kdRawPointerCoordinates; 8405b261ecSmrg 851b5d61b8Smrgextern const char *kdGlobalXkbRules; 861b5d61b8Smrgextern const char *kdGlobalXkbModel; 871b5d61b8Smrgextern const char *kdGlobalXkbLayout; 881b5d61b8Smrgextern const char *kdGlobalXkbVariant; 891b5d61b8Smrgextern const char *kdGlobalXkbOptions; 9005b261ecSmrg 9105b261ecSmrg#ifdef FNONBLOCK 9205b261ecSmrg#define NOBLOCK FNONBLOCK 9305b261ecSmrg#else 9405b261ecSmrg#define NOBLOCK FNDELAY 9505b261ecSmrg#endif 9605b261ecSmrg 971b5d61b8Smrgstatic void 9835c4bbdfSmrgKdResetInputMachine(void) 9905b261ecSmrg{ 10005b261ecSmrg KdPointerInfo *pi; 10105b261ecSmrg 10205b261ecSmrg for (pi = kdPointers; pi; pi = pi->next) { 10305b261ecSmrg pi->mouseState = start; 10405b261ecSmrg pi->eventHeld = FALSE; 10505b261ecSmrg } 10605b261ecSmrg} 10705b261ecSmrg 10805b261ecSmrgvoid 10935c4bbdfSmrgKdDisableInput(void) 11005b261ecSmrg{ 11105b261ecSmrg KdKeyboardInfo *ki; 11205b261ecSmrg KdPointerInfo *pi; 11305b261ecSmrg 1141b5d61b8Smrg input_lock(); 11505b261ecSmrg 11605b261ecSmrg for (ki = kdKeyboards; ki; ki = ki->next) { 11705b261ecSmrg if (ki->driver && ki->driver->Disable) 11805b261ecSmrg (*ki->driver->Disable) (ki); 11905b261ecSmrg } 12005b261ecSmrg 12105b261ecSmrg for (pi = kdPointers; pi; pi = pi->next) { 12205b261ecSmrg if (pi->driver && pi->driver->Disable) 12305b261ecSmrg (*pi->driver->Disable) (pi); 12405b261ecSmrg } 12505b261ecSmrg 12605b261ecSmrg kdInputEnabled = FALSE; 12705b261ecSmrg} 12805b261ecSmrg 12905b261ecSmrgvoid 13035c4bbdfSmrgKdEnableInput(void) 13105b261ecSmrg{ 1326747b715Smrg InternalEvent ev; 13305b261ecSmrg KdKeyboardInfo *ki; 13405b261ecSmrg KdPointerInfo *pi; 1356747b715Smrg 13605b261ecSmrg kdInputEnabled = TRUE; 13705b261ecSmrg 13835c4bbdfSmrg ev.any.time = GetTimeInMillis(); 13935c4bbdfSmrg 14005b261ecSmrg for (ki = kdKeyboards; ki; ki = ki->next) { 14105b261ecSmrg if (ki->driver && ki->driver->Enable) 14205b261ecSmrg (*ki->driver->Enable) (ki); 14335c4bbdfSmrg /* reset screen saver */ 14435c4bbdfSmrg NoticeEventTime (&ev, ki->dixdev); 14505b261ecSmrg } 14605b261ecSmrg 14705b261ecSmrg for (pi = kdPointers; pi; pi = pi->next) { 14805b261ecSmrg if (pi->driver && pi->driver->Enable) 14905b261ecSmrg (*pi->driver->Enable) (pi); 15035c4bbdfSmrg /* reset screen saver */ 15135c4bbdfSmrg NoticeEventTime (&ev, pi->dixdev); 15205b261ecSmrg } 15305b261ecSmrg 1541b5d61b8Smrg input_unlock(); 15505b261ecSmrg} 15605b261ecSmrg 15705b261ecSmrgstatic KdKeyboardDriver * 15835c4bbdfSmrgKdFindKeyboardDriver(const char *name) 15905b261ecSmrg{ 16005b261ecSmrg KdKeyboardDriver *ret; 16105b261ecSmrg 16205b261ecSmrg /* ask a stupid question ... */ 16305b261ecSmrg if (!name) 16405b261ecSmrg return NULL; 1656747b715Smrg 16605b261ecSmrg for (ret = kdKeyboardDrivers; ret; ret = ret->next) { 16705b261ecSmrg if (strcmp(ret->name, name) == 0) 16805b261ecSmrg return ret; 16905b261ecSmrg } 17005b261ecSmrg 17105b261ecSmrg return NULL; 17205b261ecSmrg} 17305b261ecSmrg 17405b261ecSmrgstatic KdPointerDriver * 17535c4bbdfSmrgKdFindPointerDriver(const char *name) 17605b261ecSmrg{ 17705b261ecSmrg KdPointerDriver *ret; 17805b261ecSmrg 17905b261ecSmrg /* ask a stupid question ... */ 18005b261ecSmrg if (!name) 18105b261ecSmrg return NULL; 18205b261ecSmrg 18305b261ecSmrg for (ret = kdPointerDrivers; ret; ret = ret->next) { 18405b261ecSmrg if (strcmp(ret->name, name) == 0) 18505b261ecSmrg return ret; 18605b261ecSmrg } 18705b261ecSmrg 18805b261ecSmrg return NULL; 18905b261ecSmrg} 19005b261ecSmrg 19105b261ecSmrgstatic int 19205b261ecSmrgKdPointerProc(DeviceIntPtr pDevice, int onoff) 19305b261ecSmrg{ 19435c4bbdfSmrg DevicePtr pDev = (DevicePtr) pDevice; 19535c4bbdfSmrg KdPointerInfo *pi; 19635c4bbdfSmrg Atom xiclass; 19735c4bbdfSmrg Atom *btn_labels; 19835c4bbdfSmrg Atom *axes_labels; 19905b261ecSmrg 20005b261ecSmrg if (!pDev) 20135c4bbdfSmrg return BadImplementation; 20205b261ecSmrg 20305b261ecSmrg for (pi = kdPointers; pi; pi = pi->next) { 20405b261ecSmrg if (pi->dixdev && pi->dixdev->id == pDevice->id) 20505b261ecSmrg break; 20605b261ecSmrg } 20705b261ecSmrg 20805b261ecSmrg if (!pi || !pi->dixdev || pi->dixdev->id != pDevice->id) { 20905b261ecSmrg ErrorF("[KdPointerProc] Failed to find pointer for device %d!\n", 21005b261ecSmrg pDevice->id); 21105b261ecSmrg return BadImplementation; 21205b261ecSmrg } 21305b261ecSmrg 21435c4bbdfSmrg switch (onoff) { 21505b261ecSmrg case DEVICE_INIT: 21605b261ecSmrg#ifdef DEBUG 21705b261ecSmrg ErrorF("initialising pointer %s ...\n", pi->name); 21805b261ecSmrg#endif 21905b261ecSmrg if (!pi->driver) { 22005b261ecSmrg if (!pi->driverPrivate) { 2211b5d61b8Smrg ErrorF("no driver specified for pointer device \"%s\" (%s)\n", 2221b5d61b8Smrg pi->name ? pi->name : "(unnamed)", pi->path); 22305b261ecSmrg return BadImplementation; 22405b261ecSmrg } 22505b261ecSmrg 22605b261ecSmrg pi->driver = KdFindPointerDriver(pi->driverPrivate); 22705b261ecSmrg if (!pi->driver) { 22805b261ecSmrg ErrorF("Couldn't find pointer driver %s\n", 22905b261ecSmrg pi->driverPrivate ? (char *) pi->driverPrivate : 23005b261ecSmrg "(unnamed)"); 23105b261ecSmrg return !Success; 23205b261ecSmrg } 2336747b715Smrg free(pi->driverPrivate); 23405b261ecSmrg pi->driverPrivate = NULL; 23505b261ecSmrg } 23605b261ecSmrg 23705b261ecSmrg if (!pi->driver->Init) { 23805b261ecSmrg ErrorF("no init function\n"); 23905b261ecSmrg return BadImplementation; 24005b261ecSmrg } 24105b261ecSmrg 24205b261ecSmrg if ((*pi->driver->Init) (pi) != Success) { 24305b261ecSmrg return !Success; 24405b261ecSmrg } 24505b261ecSmrg 24635c4bbdfSmrg btn_labels = calloc(pi->nButtons, sizeof(Atom)); 24735c4bbdfSmrg if (!btn_labels) 24835c4bbdfSmrg return BadAlloc; 24935c4bbdfSmrg axes_labels = calloc(pi->nAxes, sizeof(Atom)); 25035c4bbdfSmrg if (!axes_labels) { 25135c4bbdfSmrg free(btn_labels); 25235c4bbdfSmrg return BadAlloc; 25335c4bbdfSmrg } 25435c4bbdfSmrg 25535c4bbdfSmrg switch (pi->nAxes) { 25635c4bbdfSmrg default: 25735c4bbdfSmrg case 7: 25835c4bbdfSmrg btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); 25935c4bbdfSmrg case 6: 26035c4bbdfSmrg btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); 26135c4bbdfSmrg case 5: 26235c4bbdfSmrg btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); 26335c4bbdfSmrg case 4: 26435c4bbdfSmrg btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); 26535c4bbdfSmrg case 3: 26635c4bbdfSmrg btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); 26735c4bbdfSmrg case 2: 26835c4bbdfSmrg btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); 26935c4bbdfSmrg case 1: 27035c4bbdfSmrg btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); 27135c4bbdfSmrg case 0: 27235c4bbdfSmrg break; 27335c4bbdfSmrg } 27435c4bbdfSmrg 27535c4bbdfSmrg if (pi->nAxes >= 2) { 27635c4bbdfSmrg axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); 27735c4bbdfSmrg axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); 27835c4bbdfSmrg } 27935c4bbdfSmrg 28035c4bbdfSmrg InitPointerDeviceStruct(pDev, pi->map, pi->nButtons, btn_labels, 28135c4bbdfSmrg (PtrCtrlProcPtr) NoopDDA, 28235c4bbdfSmrg GetMotionHistorySize(), pi->nAxes, axes_labels); 2836747b715Smrg 2846747b715Smrg free(btn_labels); 2856747b715Smrg free(axes_labels); 28605b261ecSmrg 28705b261ecSmrg if (pi->inputClass == KD_TOUCHSCREEN) { 28805b261ecSmrg xiclass = AtomFromName(XI_TOUCHSCREEN); 28905b261ecSmrg } 29005b261ecSmrg else { 29105b261ecSmrg xiclass = AtomFromName(XI_MOUSE); 29205b261ecSmrg } 29305b261ecSmrg 29405b261ecSmrg AssignTypeAndName(pi->dixdev, xiclass, 29505b261ecSmrg pi->name ? pi->name : "Generic KDrive Pointer"); 29605b261ecSmrg 29735c4bbdfSmrg return Success; 2986747b715Smrg 29905b261ecSmrg case DEVICE_ON: 30005b261ecSmrg if (pDev->on == TRUE) 30105b261ecSmrg return Success; 3026747b715Smrg 30305b261ecSmrg if (!pi->driver->Enable) { 30405b261ecSmrg ErrorF("no enable function\n"); 30505b261ecSmrg return BadImplementation; 30605b261ecSmrg } 30705b261ecSmrg 30805b261ecSmrg if ((*pi->driver->Enable) (pi) == Success) { 30905b261ecSmrg pDev->on = TRUE; 31005b261ecSmrg return Success; 31105b261ecSmrg } 31205b261ecSmrg else { 31305b261ecSmrg return BadImplementation; 31405b261ecSmrg } 31505b261ecSmrg 31635c4bbdfSmrg return Success; 31705b261ecSmrg 31805b261ecSmrg case DEVICE_OFF: 31905b261ecSmrg if (pDev->on == FALSE) { 32005b261ecSmrg return Success; 32105b261ecSmrg } 32205b261ecSmrg 32305b261ecSmrg if (!pi->driver->Disable) { 32405b261ecSmrg return BadImplementation; 32505b261ecSmrg } 32605b261ecSmrg else { 32705b261ecSmrg (*pi->driver->Disable) (pi); 32805b261ecSmrg pDev->on = FALSE; 32905b261ecSmrg return Success; 33005b261ecSmrg } 33105b261ecSmrg 33205b261ecSmrg return Success; 33305b261ecSmrg 33405b261ecSmrg case DEVICE_CLOSE: 33535c4bbdfSmrg if (pDev->on) { 33605b261ecSmrg if (!pi->driver->Disable) { 33705b261ecSmrg return BadImplementation; 33805b261ecSmrg } 33905b261ecSmrg (*pi->driver->Disable) (pi); 34005b261ecSmrg pDev->on = FALSE; 34105b261ecSmrg } 34205b261ecSmrg 34305b261ecSmrg if (!pi->driver->Fini) 34405b261ecSmrg return BadImplementation; 34505b261ecSmrg 34605b261ecSmrg (*pi->driver->Fini) (pi); 34705b261ecSmrg 34805b261ecSmrg KdRemovePointer(pi); 3496747b715Smrg 35005b261ecSmrg return Success; 35105b261ecSmrg } 35205b261ecSmrg 35305b261ecSmrg /* NOTREACHED */ 35405b261ecSmrg return BadImplementation; 35505b261ecSmrg} 35605b261ecSmrg 3571b5d61b8Smrgstatic void 3581b5d61b8SmrgKdRingBell(KdKeyboardInfo * ki, int volume, int pitch, int duration) 3591b5d61b8Smrg{ 3601b5d61b8Smrg if (!ki || !ki->driver || !ki->driver->Bell) 3611b5d61b8Smrg return; 3621b5d61b8Smrg 3631b5d61b8Smrg if (kdInputEnabled) 3641b5d61b8Smrg (*ki->driver->Bell) (ki, volume, pitch, duration); 3651b5d61b8Smrg} 3661b5d61b8Smrg 36705b261ecSmrgstatic void 36835c4bbdfSmrgKdBell(int volume, DeviceIntPtr pDev, void *arg, int something) 36905b261ecSmrg{ 37005b261ecSmrg KeybdCtrl *ctrl = arg; 37105b261ecSmrg KdKeyboardInfo *ki = NULL; 3726747b715Smrg 37305b261ecSmrg for (ki = kdKeyboards; ki; ki = ki->next) { 37405b261ecSmrg if (ki->dixdev && ki->dixdev->id == pDev->id) 37505b261ecSmrg break; 37605b261ecSmrg } 37705b261ecSmrg 37805b261ecSmrg if (!ki || !ki->dixdev || ki->dixdev->id != pDev->id || !ki->driver) 37905b261ecSmrg return; 3806747b715Smrg 38105b261ecSmrg KdRingBell(ki, volume, ctrl->bell_pitch, ctrl->bell_duration); 38205b261ecSmrg} 38305b261ecSmrg 38405b261ecSmrgvoid 38505b261ecSmrgDDXRingBell(int volume, int pitch, int duration) 38605b261ecSmrg{ 38705b261ecSmrg KdKeyboardInfo *ki = NULL; 38805b261ecSmrg 3891b5d61b8Smrg for (ki = kdKeyboards; ki; ki = ki->next) { 3901b5d61b8Smrg if (ki->dixdev->coreEvents) 3911b5d61b8Smrg KdRingBell(ki, volume, pitch, duration); 39205b261ecSmrg } 39305b261ecSmrg} 39405b261ecSmrg 39505b261ecSmrgstatic void 39635c4bbdfSmrgKdSetLeds(KdKeyboardInfo * ki, int leds) 39705b261ecSmrg{ 39805b261ecSmrg if (!ki || !ki->driver) 39905b261ecSmrg return; 40005b261ecSmrg 40105b261ecSmrg if (kdInputEnabled) { 40205b261ecSmrg if (ki->driver->Leds) 40305b261ecSmrg (*ki->driver->Leds) (ki, leds); 40405b261ecSmrg } 40505b261ecSmrg} 40605b261ecSmrg 4071b5d61b8Smrgstatic void 40835c4bbdfSmrgKdSetLed(KdKeyboardInfo * ki, int led, Bool on) 40905b261ecSmrg{ 41005b261ecSmrg if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed) 41105b261ecSmrg return; 41205b261ecSmrg 41335c4bbdfSmrg NoteLedState(ki->dixdev, led, on); 41435c4bbdfSmrg KdSetLeds(ki, ki->dixdev->kbdfeed->ctrl.leds); 41505b261ecSmrg} 41605b261ecSmrg 41705b261ecSmrgvoid 41835c4bbdfSmrgKdSetPointerMatrix(KdPointerMatrix * matrix) 41905b261ecSmrg{ 42005b261ecSmrg kdPointerMatrix = *matrix; 42105b261ecSmrg} 42205b261ecSmrg 42305b261ecSmrgvoid 42435c4bbdfSmrgKdComputePointerMatrix(KdPointerMatrix * m, Rotation randr, int width, 42535c4bbdfSmrg int height) 42605b261ecSmrg{ 42735c4bbdfSmrg int x_dir = 1, y_dir = 1; 42835c4bbdfSmrg int i, j; 42935c4bbdfSmrg int size[2]; 43005b261ecSmrg 43135c4bbdfSmrg size[0] = width; 43235c4bbdfSmrg size[1] = height; 43305b261ecSmrg if (randr & RR_Reflect_X) 43435c4bbdfSmrg x_dir = -1; 43505b261ecSmrg if (randr & RR_Reflect_Y) 43635c4bbdfSmrg y_dir = -1; 43705b261ecSmrg switch (randr & (RR_Rotate_All)) { 43805b261ecSmrg case RR_Rotate_0: 43935c4bbdfSmrg m->matrix[0][0] = x_dir; 44035c4bbdfSmrg m->matrix[0][1] = 0; 44135c4bbdfSmrg m->matrix[1][0] = 0; 44235c4bbdfSmrg m->matrix[1][1] = y_dir; 44335c4bbdfSmrg break; 44405b261ecSmrg case RR_Rotate_90: 44535c4bbdfSmrg m->matrix[0][0] = 0; 44635c4bbdfSmrg m->matrix[0][1] = -x_dir; 44735c4bbdfSmrg m->matrix[1][0] = y_dir; 44835c4bbdfSmrg m->matrix[1][1] = 0; 44935c4bbdfSmrg break; 45005b261ecSmrg case RR_Rotate_180: 45135c4bbdfSmrg m->matrix[0][0] = -x_dir; 45235c4bbdfSmrg m->matrix[0][1] = 0; 45335c4bbdfSmrg m->matrix[1][0] = 0; 45435c4bbdfSmrg m->matrix[1][1] = -y_dir; 45535c4bbdfSmrg break; 45605b261ecSmrg case RR_Rotate_270: 45735c4bbdfSmrg m->matrix[0][0] = 0; 45835c4bbdfSmrg m->matrix[0][1] = x_dir; 45935c4bbdfSmrg m->matrix[1][0] = -y_dir; 46035c4bbdfSmrg m->matrix[1][1] = 0; 46135c4bbdfSmrg break; 46205b261ecSmrg } 46335c4bbdfSmrg for (i = 0; i < 2; i++) { 46435c4bbdfSmrg m->matrix[i][2] = 0; 46535c4bbdfSmrg for (j = 0; j < 2; j++) 46635c4bbdfSmrg if (m->matrix[i][j] < 0) 46735c4bbdfSmrg m->matrix[i][2] = size[j] - 1; 46805b261ecSmrg } 46905b261ecSmrg} 47005b261ecSmrg 47105b261ecSmrgstatic void 47235c4bbdfSmrgKdKbdCtrl(DeviceIntPtr pDevice, KeybdCtrl * ctrl) 47305b261ecSmrg{ 47405b261ecSmrg KdKeyboardInfo *ki; 47505b261ecSmrg 47605b261ecSmrg for (ki = kdKeyboards; ki; ki = ki->next) { 47705b261ecSmrg if (ki->dixdev && ki->dixdev->id == pDevice->id) 47805b261ecSmrg break; 47905b261ecSmrg } 48005b261ecSmrg 48105b261ecSmrg if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id || !ki->driver) 48205b261ecSmrg return; 48305b261ecSmrg 48405b261ecSmrg KdSetLeds(ki, ctrl->leds); 48505b261ecSmrg ki->bellPitch = ctrl->bell_pitch; 4866747b715Smrg ki->bellDuration = ctrl->bell_duration; 48705b261ecSmrg} 48805b261ecSmrg 48905b261ecSmrgstatic int 49005b261ecSmrgKdKeyboardProc(DeviceIntPtr pDevice, int onoff) 49105b261ecSmrg{ 49235c4bbdfSmrg Bool ret; 49335c4bbdfSmrg DevicePtr pDev = (DevicePtr) pDevice; 49405b261ecSmrg KdKeyboardInfo *ki; 49505b261ecSmrg Atom xiclass; 4966747b715Smrg XkbRMLVOSet rmlvo; 49705b261ecSmrg 49805b261ecSmrg if (!pDev) 49935c4bbdfSmrg return BadImplementation; 50005b261ecSmrg 50105b261ecSmrg for (ki = kdKeyboards; ki; ki = ki->next) { 50205b261ecSmrg if (ki->dixdev && ki->dixdev->id == pDevice->id) 50305b261ecSmrg break; 50405b261ecSmrg } 50505b261ecSmrg 50605b261ecSmrg if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id) { 50705b261ecSmrg return BadImplementation; 50805b261ecSmrg } 50905b261ecSmrg 51035c4bbdfSmrg switch (onoff) { 51105b261ecSmrg case DEVICE_INIT: 51205b261ecSmrg#ifdef DEBUG 51305b261ecSmrg ErrorF("initialising keyboard %s\n", ki->name); 51405b261ecSmrg#endif 51505b261ecSmrg if (!ki->driver) { 51605b261ecSmrg if (!ki->driverPrivate) { 5171b5d61b8Smrg ErrorF("no driver specified for keyboard device \"%s\" (%s)\n", 5181b5d61b8Smrg ki->name ? ki->name : "(unnamed)", ki->path); 51905b261ecSmrg return BadImplementation; 52005b261ecSmrg } 52105b261ecSmrg 52205b261ecSmrg ki->driver = KdFindKeyboardDriver(ki->driverPrivate); 52305b261ecSmrg if (!ki->driver) { 52405b261ecSmrg ErrorF("Couldn't find keyboard driver %s\n", 52505b261ecSmrg ki->driverPrivate ? (char *) ki->driverPrivate : 52605b261ecSmrg "(unnamed)"); 52705b261ecSmrg return !Success; 52805b261ecSmrg } 5296747b715Smrg free(ki->driverPrivate); 53005b261ecSmrg ki->driverPrivate = NULL; 53105b261ecSmrg } 53205b261ecSmrg 53305b261ecSmrg if (!ki->driver->Init) { 53405b261ecSmrg ErrorF("Keyboard %s: no init function\n", ki->name); 53505b261ecSmrg return BadImplementation; 53605b261ecSmrg } 53705b261ecSmrg 5386747b715Smrg memset(&rmlvo, 0, sizeof(rmlvo)); 5396747b715Smrg rmlvo.rules = ki->xkbRules; 5406747b715Smrg rmlvo.model = ki->xkbModel; 5416747b715Smrg rmlvo.layout = ki->xkbLayout; 5426747b715Smrg rmlvo.variant = ki->xkbVariant; 5436747b715Smrg rmlvo.options = ki->xkbOptions; 54435c4bbdfSmrg ret = InitKeyboardDeviceStruct(pDevice, &rmlvo, KdBell, KdKbdCtrl); 54535c4bbdfSmrg if (!ret) { 54605b261ecSmrg ErrorF("Couldn't initialise keyboard %s\n", ki->name); 54735c4bbdfSmrg return BadImplementation; 54805b261ecSmrg } 54905b261ecSmrg 5501b5d61b8Smrg if ((*ki->driver->Init) (ki) != Success) { 5511b5d61b8Smrg return !Success; 5521b5d61b8Smrg } 5531b5d61b8Smrg 55405b261ecSmrg xiclass = AtomFromName(XI_KEYBOARD); 55505b261ecSmrg AssignTypeAndName(pDevice, xiclass, 55605b261ecSmrg ki->name ? ki->name : "Generic KDrive Keyboard"); 55705b261ecSmrg 55805b261ecSmrg KdResetInputMachine(); 55905b261ecSmrg 56005b261ecSmrg return Success; 56105b261ecSmrg 56205b261ecSmrg case DEVICE_ON: 56305b261ecSmrg if (pDev->on == TRUE) 56405b261ecSmrg return Success; 56505b261ecSmrg 56605b261ecSmrg if (!ki->driver->Enable) 56705b261ecSmrg return BadImplementation; 56805b261ecSmrg 56905b261ecSmrg if ((*ki->driver->Enable) (ki) != Success) { 57005b261ecSmrg return BadMatch; 57105b261ecSmrg } 57205b261ecSmrg 57305b261ecSmrg pDev->on = TRUE; 57405b261ecSmrg return Success; 57505b261ecSmrg 57605b261ecSmrg case DEVICE_OFF: 57705b261ecSmrg if (pDev->on == FALSE) 57805b261ecSmrg return Success; 57905b261ecSmrg 58005b261ecSmrg if (!ki->driver->Disable) 58105b261ecSmrg return BadImplementation; 58205b261ecSmrg 58305b261ecSmrg (*ki->driver->Disable) (ki); 58405b261ecSmrg pDev->on = FALSE; 58505b261ecSmrg 58605b261ecSmrg return Success; 5876747b715Smrg 58805b261ecSmrg break; 58905b261ecSmrg 59005b261ecSmrg case DEVICE_CLOSE: 59135c4bbdfSmrg if (pDev->on) { 59205b261ecSmrg if (!ki->driver->Disable) 59305b261ecSmrg return BadImplementation; 59405b261ecSmrg 59505b261ecSmrg (*ki->driver->Disable) (ki); 59605b261ecSmrg pDev->on = FALSE; 59735c4bbdfSmrg } 59805b261ecSmrg 59905b261ecSmrg if (!ki->driver->Fini) 60005b261ecSmrg return BadImplementation; 60105b261ecSmrg 60205b261ecSmrg (*ki->driver->Fini) (ki); 60305b261ecSmrg 60405b261ecSmrg KdRemoveKeyboard(ki); 60505b261ecSmrg 60605b261ecSmrg return Success; 60705b261ecSmrg } 60805b261ecSmrg 60905b261ecSmrg /* NOTREACHED */ 61005b261ecSmrg return BadImplementation; 61105b261ecSmrg} 61205b261ecSmrg 61305b261ecSmrgvoid 61435c4bbdfSmrgKdAddPointerDriver(KdPointerDriver * driver) 61505b261ecSmrg{ 61605b261ecSmrg KdPointerDriver **prev; 61705b261ecSmrg 61805b261ecSmrg if (!driver) 61905b261ecSmrg return; 62005b261ecSmrg 62105b261ecSmrg for (prev = &kdPointerDrivers; *prev; prev = &(*prev)->next) { 62205b261ecSmrg if (*prev == driver) 62305b261ecSmrg return; 62405b261ecSmrg } 62505b261ecSmrg *prev = driver; 62605b261ecSmrg} 62705b261ecSmrg 62805b261ecSmrgvoid 62935c4bbdfSmrgKdRemovePointerDriver(KdPointerDriver * driver) 63005b261ecSmrg{ 63105b261ecSmrg KdPointerDriver *tmp; 63205b261ecSmrg 63305b261ecSmrg if (!driver) 63405b261ecSmrg return; 63505b261ecSmrg 63605b261ecSmrg /* FIXME remove all pointers using this driver */ 63705b261ecSmrg for (tmp = kdPointerDrivers; tmp; tmp = tmp->next) { 63805b261ecSmrg if (tmp->next == driver) 63905b261ecSmrg tmp->next = driver->next; 64005b261ecSmrg } 64105b261ecSmrg if (tmp == driver) 64205b261ecSmrg tmp = NULL; 64305b261ecSmrg} 64405b261ecSmrg 64505b261ecSmrgvoid 64635c4bbdfSmrgKdAddKeyboardDriver(KdKeyboardDriver * driver) 64705b261ecSmrg{ 64805b261ecSmrg KdKeyboardDriver **prev; 64905b261ecSmrg 65005b261ecSmrg if (!driver) 65105b261ecSmrg return; 65205b261ecSmrg 65305b261ecSmrg for (prev = &kdKeyboardDrivers; *prev; prev = &(*prev)->next) { 65405b261ecSmrg if (*prev == driver) 65505b261ecSmrg return; 65605b261ecSmrg } 65705b261ecSmrg *prev = driver; 65805b261ecSmrg} 65905b261ecSmrg 66005b261ecSmrgvoid 66135c4bbdfSmrgKdRemoveKeyboardDriver(KdKeyboardDriver * driver) 66205b261ecSmrg{ 66305b261ecSmrg KdKeyboardDriver *tmp; 66405b261ecSmrg 66505b261ecSmrg if (!driver) 66605b261ecSmrg return; 66705b261ecSmrg 66805b261ecSmrg /* FIXME remove all keyboards using this driver */ 66905b261ecSmrg for (tmp = kdKeyboardDrivers; tmp; tmp = tmp->next) { 67005b261ecSmrg if (tmp->next == driver) 67105b261ecSmrg tmp->next = driver->next; 67205b261ecSmrg } 67305b261ecSmrg if (tmp == driver) 67405b261ecSmrg tmp = NULL; 67505b261ecSmrg} 67605b261ecSmrg 67705b261ecSmrgKdKeyboardInfo * 67835c4bbdfSmrgKdNewKeyboard(void) 67905b261ecSmrg{ 6806747b715Smrg KdKeyboardInfo *ki = calloc(sizeof(KdKeyboardInfo), 1); 68135c4bbdfSmrg 68205b261ecSmrg if (!ki) 68305b261ecSmrg return NULL; 68405b261ecSmrg 68505b261ecSmrg ki->minScanCode = 0; 68605b261ecSmrg ki->maxScanCode = 0; 68705b261ecSmrg ki->leds = 0; 68805b261ecSmrg ki->bellPitch = 1000; 68905b261ecSmrg ki->bellDuration = 200; 69005b261ecSmrg ki->next = NULL; 69105b261ecSmrg ki->options = NULL; 6921b5d61b8Smrg ki->name = strdup("Generic Keyboard"); 6931b5d61b8Smrg ki->path = NULL; 6941b5d61b8Smrg ki->xkbRules = strdup(kdGlobalXkbRules ? kdGlobalXkbRules : XKB_DFLT_RULES); 6951b5d61b8Smrg ki->xkbModel = strdup(kdGlobalXkbModel ? kdGlobalXkbModel : XKB_DFLT_MODEL); 6961b5d61b8Smrg ki->xkbLayout = strdup(kdGlobalXkbLayout ? kdGlobalXkbLayout : XKB_DFLT_LAYOUT); 6971b5d61b8Smrg ki->xkbVariant = strdup(kdGlobalXkbVariant ? kdGlobalXkbVariant :XKB_DFLT_VARIANT); 6981b5d61b8Smrg ki->xkbOptions = strdup(kdGlobalXkbOptions ? kdGlobalXkbOptions : XKB_DFLT_OPTIONS); 69905b261ecSmrg 70005b261ecSmrg return ki; 70105b261ecSmrg} 70205b261ecSmrg 70305b261ecSmrgint 70435c4bbdfSmrgKdAddConfigKeyboard(char *keyboard) 70505b261ecSmrg{ 70605b261ecSmrg struct KdConfigDevice **prev, *new; 70705b261ecSmrg 70805b261ecSmrg if (!keyboard) 70905b261ecSmrg return Success; 71005b261ecSmrg 7116747b715Smrg new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1); 71205b261ecSmrg if (!new) 71305b261ecSmrg return BadAlloc; 71405b261ecSmrg 7156747b715Smrg new->line = strdup(keyboard); 71605b261ecSmrg new->next = NULL; 71705b261ecSmrg 71805b261ecSmrg for (prev = &kdConfigKeyboards; *prev; prev = &(*prev)->next); 71905b261ecSmrg *prev = new; 72005b261ecSmrg 72105b261ecSmrg return Success; 72205b261ecSmrg} 72305b261ecSmrg 72405b261ecSmrgint 72535c4bbdfSmrgKdAddKeyboard(KdKeyboardInfo * ki) 72605b261ecSmrg{ 72705b261ecSmrg KdKeyboardInfo **prev; 72805b261ecSmrg 72905b261ecSmrg if (!ki) 73005b261ecSmrg return !Success; 7316747b715Smrg 7324642e01fSmrg ki->dixdev = AddInputDevice(serverClient, KdKeyboardProc, TRUE); 73305b261ecSmrg if (!ki->dixdev) { 73405b261ecSmrg ErrorF("Couldn't register keyboard device %s\n", 73505b261ecSmrg ki->name ? ki->name : "(unnamed)"); 73605b261ecSmrg return !Success; 73705b261ecSmrg } 73805b261ecSmrg 73905b261ecSmrg#ifdef DEBUG 74005b261ecSmrg ErrorF("added keyboard %s with dix id %d\n", ki->name, ki->dixdev->id); 74105b261ecSmrg#endif 74205b261ecSmrg 74305b261ecSmrg for (prev = &kdKeyboards; *prev; prev = &(*prev)->next); 74405b261ecSmrg *prev = ki; 74505b261ecSmrg 74605b261ecSmrg return Success; 74705b261ecSmrg} 74805b261ecSmrg 74905b261ecSmrgvoid 75035c4bbdfSmrgKdRemoveKeyboard(KdKeyboardInfo * ki) 75105b261ecSmrg{ 75205b261ecSmrg KdKeyboardInfo **prev; 75305b261ecSmrg 75405b261ecSmrg if (!ki) 75505b261ecSmrg return; 75605b261ecSmrg 75705b261ecSmrg for (prev = &kdKeyboards; *prev; prev = &(*prev)->next) { 75805b261ecSmrg if (*prev == ki) { 75905b261ecSmrg *prev = ki->next; 76005b261ecSmrg break; 76105b261ecSmrg } 76205b261ecSmrg } 76305b261ecSmrg 76405b261ecSmrg KdFreeKeyboard(ki); 76505b261ecSmrg} 76605b261ecSmrg 76705b261ecSmrgint 76835c4bbdfSmrgKdAddConfigPointer(char *pointer) 76905b261ecSmrg{ 77005b261ecSmrg struct KdConfigDevice **prev, *new; 77105b261ecSmrg 77205b261ecSmrg if (!pointer) 77305b261ecSmrg return Success; 77405b261ecSmrg 7756747b715Smrg new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1); 77605b261ecSmrg if (!new) 77705b261ecSmrg return BadAlloc; 77805b261ecSmrg 7796747b715Smrg new->line = strdup(pointer); 78005b261ecSmrg new->next = NULL; 78105b261ecSmrg 78205b261ecSmrg for (prev = &kdConfigPointers; *prev; prev = &(*prev)->next); 78305b261ecSmrg *prev = new; 78405b261ecSmrg 78505b261ecSmrg return Success; 78605b261ecSmrg} 78705b261ecSmrg 78805b261ecSmrgint 78935c4bbdfSmrgKdAddPointer(KdPointerInfo * pi) 79005b261ecSmrg{ 79105b261ecSmrg KdPointerInfo **prev; 79205b261ecSmrg 79305b261ecSmrg if (!pi) 79405b261ecSmrg return Success; 79505b261ecSmrg 79605b261ecSmrg pi->mouseState = start; 79705b261ecSmrg pi->eventHeld = FALSE; 79805b261ecSmrg 7994642e01fSmrg pi->dixdev = AddInputDevice(serverClient, KdPointerProc, TRUE); 80005b261ecSmrg if (!pi->dixdev) { 80105b261ecSmrg ErrorF("Couldn't add pointer device %s\n", 80205b261ecSmrg pi->name ? pi->name : "(unnamed)"); 80305b261ecSmrg return BadDevice; 80405b261ecSmrg } 80505b261ecSmrg 80605b261ecSmrg for (prev = &kdPointers; *prev; prev = &(*prev)->next); 80705b261ecSmrg *prev = pi; 80805b261ecSmrg 80905b261ecSmrg return Success; 81005b261ecSmrg} 81105b261ecSmrg 81205b261ecSmrgvoid 81335c4bbdfSmrgKdRemovePointer(KdPointerInfo * pi) 81405b261ecSmrg{ 81505b261ecSmrg KdPointerInfo **prev; 81605b261ecSmrg 81705b261ecSmrg if (!pi) 81805b261ecSmrg return; 81905b261ecSmrg 82005b261ecSmrg for (prev = &kdPointers; *prev; prev = &(*prev)->next) { 82105b261ecSmrg if (*prev == pi) { 82205b261ecSmrg *prev = pi->next; 82305b261ecSmrg break; 82405b261ecSmrg } 82505b261ecSmrg } 82605b261ecSmrg 82705b261ecSmrg KdFreePointer(pi); 82805b261ecSmrg} 82905b261ecSmrg 8306747b715Smrg/* 83105b261ecSmrg * You can call your kdriver server with something like: 83205b261ecSmrg * $ ./hw/kdrive/yourserver/X :1 -mouse evdev,,device=/dev/input/event4 -keybd 8336747b715Smrg * evdev,,device=/dev/input/event1,xkbmodel=abnt2,xkblayout=br 83405b261ecSmrg */ 8356747b715Smrgstatic Bool 83635c4bbdfSmrgKdGetOptions(InputOption **options, char *string) 83705b261ecSmrg{ 83835c4bbdfSmrg InputOption *newopt = NULL; 83935c4bbdfSmrg char *key = NULL, *value = NULL; 84035c4bbdfSmrg int tam_key = 0; 84105b261ecSmrg 84235c4bbdfSmrg if (strchr(string, '=')) { 84305b261ecSmrg tam_key = (strchr(string, '=') - string); 84435c4bbdfSmrg key = strndup(string, tam_key); 84535c4bbdfSmrg if (!key) 84635c4bbdfSmrg goto out; 84735c4bbdfSmrg 84835c4bbdfSmrg value = strdup(strchr(string, '=') + 1); 84935c4bbdfSmrg if (!value) 85035c4bbdfSmrg goto out; 85105b261ecSmrg } 85235c4bbdfSmrg else { 85335c4bbdfSmrg key = strdup(string); 85435c4bbdfSmrg value = NULL; 85505b261ecSmrg } 85605b261ecSmrg 85735c4bbdfSmrg newopt = input_option_new(*options, key, value); 85835c4bbdfSmrg if (newopt) 85935c4bbdfSmrg *options = newopt; 86035c4bbdfSmrg 86135c4bbdfSmrg out: 86235c4bbdfSmrg free(key); 86335c4bbdfSmrg free(value); 86435c4bbdfSmrg 86535c4bbdfSmrg return (newopt != NULL); 86605b261ecSmrg} 86705b261ecSmrg 86805b261ecSmrgstatic void 86935c4bbdfSmrgKdParseKbdOptions(KdKeyboardInfo * ki) 87005b261ecSmrg{ 87105b261ecSmrg InputOption *option = NULL; 87205b261ecSmrg 87335c4bbdfSmrg nt_list_for_each_entry(option, ki->options, list.next) { 87435c4bbdfSmrg const char *key = input_option_get_key(option); 87535c4bbdfSmrg const char *value = input_option_get_value(option); 87635c4bbdfSmrg 8771b5d61b8Smrg if ( 8781b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL) 8791b5d61b8Smrg strcasecmp(key, "xkb_rules") == 0 || 8801b5d61b8Smrg#endif 8811b5d61b8Smrg strcasecmp(key, "XkbRules") == 0) 88235c4bbdfSmrg ki->xkbRules = strdup(value); 8831b5d61b8Smrg else if ( 8841b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL) 8851b5d61b8Smrg strcasecmp(key, "xkb_model") == 0 || 8861b5d61b8Smrg#endif 8871b5d61b8Smrg strcasecmp(key, "XkbModel") == 0) 88835c4bbdfSmrg ki->xkbModel = strdup(value); 8891b5d61b8Smrg else if ( 8901b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL) 8911b5d61b8Smrg strcasecmp(key, "xkb_layout") == 0 || 8921b5d61b8Smrg#endif 8931b5d61b8Smrg strcasecmp(key, "XkbLayout") == 0) 89435c4bbdfSmrg ki->xkbLayout = strdup(value); 8951b5d61b8Smrg else if ( 8961b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL) 8971b5d61b8Smrg strcasecmp(key, "xkb_variant") == 0 || 8981b5d61b8Smrg#endif 8991b5d61b8Smrg strcasecmp(key, "XkbVariant") == 0) 90035c4bbdfSmrg ki->xkbVariant = strdup(value); 9011b5d61b8Smrg else if ( 9021b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL) 9031b5d61b8Smrg strcasecmp(key, "xkb_options") == 0 || 9041b5d61b8Smrg#endif 9051b5d61b8Smrg strcasecmp(key, "XkbOptions") == 0) 90635c4bbdfSmrg ki->xkbOptions = strdup(value); 9071b5d61b8Smrg else if (!strcasecmp(key, "device")) { 9081b5d61b8Smrg if (ki->path != NULL) 9091b5d61b8Smrg free(ki->path); 9101b5d61b8Smrg ki->path = strdup(value); 9111b5d61b8Smrg } 9121b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL) 9131b5d61b8Smrg else if (!strcasecmp(key, "path")) { 9141b5d61b8Smrg if (ki->path != NULL) 9151b5d61b8Smrg free(ki->path); 91635c4bbdfSmrg ki->path = strdup(value); 9171b5d61b8Smrg } 9181b5d61b8Smrg else if (!strcasecmp(key, "name")) { 9191b5d61b8Smrg free(ki->name); 9201b5d61b8Smrg ki->name = strdup(value); 9211b5d61b8Smrg } 9221b5d61b8Smrg#endif 9231b5d61b8Smrg else if (!strcasecmp(key, "driver")) 9241b5d61b8Smrg ki->driver = KdFindKeyboardDriver(value); 92505b261ecSmrg else 92635c4bbdfSmrg ErrorF("Kbd option key (%s) of value (%s) not assigned!\n", 92735c4bbdfSmrg key, value); 92805b261ecSmrg } 92905b261ecSmrg} 93005b261ecSmrg 9311b5d61b8Smrgstatic KdKeyboardInfo * 93235c4bbdfSmrgKdParseKeyboard(const char *arg) 93305b261ecSmrg{ 93435c4bbdfSmrg char save[1024]; 93535c4bbdfSmrg char delim; 93635c4bbdfSmrg InputOption *options = NULL; 93735c4bbdfSmrg KdKeyboardInfo *ki = NULL; 93805b261ecSmrg 93905b261ecSmrg ki = KdNewKeyboard(); 94005b261ecSmrg if (!ki) 94105b261ecSmrg return NULL; 94205b261ecSmrg 94305b261ecSmrg ki->name = strdup("Unknown KDrive Keyboard"); 94405b261ecSmrg ki->path = NULL; 94505b261ecSmrg ki->driver = NULL; 94605b261ecSmrg ki->driverPrivate = NULL; 94705b261ecSmrg ki->next = NULL; 94805b261ecSmrg 94935c4bbdfSmrg if (!arg) { 95005b261ecSmrg ErrorF("keybd: no arg\n"); 95135c4bbdfSmrg KdFreeKeyboard(ki); 95205b261ecSmrg return NULL; 95305b261ecSmrg } 95405b261ecSmrg 95535c4bbdfSmrg if (strlen(arg) >= sizeof(save)) { 95605b261ecSmrg ErrorF("keybd: arg too long\n"); 95735c4bbdfSmrg KdFreeKeyboard(ki); 95805b261ecSmrg return NULL; 95905b261ecSmrg } 96005b261ecSmrg 96135c4bbdfSmrg arg = KdParseFindNext(arg, ",", save, &delim); 96235c4bbdfSmrg if (!save[0]) { 96305b261ecSmrg ErrorF("keybd: failed on save[0]\n"); 96435c4bbdfSmrg KdFreeKeyboard(ki); 96505b261ecSmrg return NULL; 96605b261ecSmrg } 96705b261ecSmrg 96835c4bbdfSmrg if (strcmp(save, "auto") == 0) 96905b261ecSmrg ki->driverPrivate = NULL; 97005b261ecSmrg else 9716747b715Smrg ki->driverPrivate = strdup(save); 97205b261ecSmrg 97335c4bbdfSmrg if (delim != ',') { 97405b261ecSmrg return ki; 97505b261ecSmrg } 97605b261ecSmrg 97735c4bbdfSmrg arg = KdParseFindNext(arg, ",", save, &delim); 97805b261ecSmrg 97935c4bbdfSmrg while (delim == ',') { 98035c4bbdfSmrg arg = KdParseFindNext(arg, ",", save, &delim); 98105b261ecSmrg 98235c4bbdfSmrg if (!KdGetOptions(&options, save)) { 98335c4bbdfSmrg KdFreeKeyboard(ki); 98435c4bbdfSmrg return NULL; 9856747b715Smrg } 98605b261ecSmrg } 98705b261ecSmrg 98835c4bbdfSmrg if (options) { 98905b261ecSmrg ki->options = options; 99005b261ecSmrg KdParseKbdOptions(ki); 99105b261ecSmrg } 99205b261ecSmrg 99305b261ecSmrg return ki; 99405b261ecSmrg} 99505b261ecSmrg 99605b261ecSmrgstatic void 99735c4bbdfSmrgKdParsePointerOptions(KdPointerInfo * pi) 99805b261ecSmrg{ 99905b261ecSmrg InputOption *option = NULL; 100005b261ecSmrg 100135c4bbdfSmrg nt_list_for_each_entry(option, pi->options, list.next) { 100235c4bbdfSmrg const char *key = input_option_get_key(option); 100335c4bbdfSmrg const char *value = input_option_get_value(option); 100435c4bbdfSmrg 10051b5d61b8Smrg if (!strcasecmp(key, "emulatemiddle")) 100605b261ecSmrg pi->emulateMiddleButton = TRUE; 10071b5d61b8Smrg else if (!strcasecmp(key, "noemulatemiddle")) 100805b261ecSmrg pi->emulateMiddleButton = FALSE; 10091b5d61b8Smrg else if (!strcasecmp(key, "transformcoord")) 101005b261ecSmrg pi->transformCoordinates = TRUE; 10111b5d61b8Smrg else if (!strcasecmp(key, "rawcoord")) 101205b261ecSmrg pi->transformCoordinates = FALSE; 10131b5d61b8Smrg else if (!strcasecmp(key, "device")) { 10141b5d61b8Smrg if (pi->path != NULL) 10151b5d61b8Smrg free(pi->path); 101635c4bbdfSmrg pi->path = strdup(value); 10171b5d61b8Smrg } 10181b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL) 10191b5d61b8Smrg else if (!strcasecmp(key, "path")) { 10201b5d61b8Smrg if (pi->path != NULL) 10211b5d61b8Smrg free(pi->path); 10221b5d61b8Smrg pi->path = strdup(value); 10231b5d61b8Smrg } 10241b5d61b8Smrg else if (!strcasecmp(key, "name")) { 10251b5d61b8Smrg free(pi->name); 10261b5d61b8Smrg pi->name = strdup(value); 10271b5d61b8Smrg } 10281b5d61b8Smrg#endif 102935c4bbdfSmrg else if (!strcasecmp(key, "protocol")) 103035c4bbdfSmrg pi->protocol = strdup(value); 10311b5d61b8Smrg else if (!strcasecmp(key, "driver")) 10321b5d61b8Smrg pi->driver = KdFindPointerDriver(value); 103305b261ecSmrg else 10346747b715Smrg ErrorF("Pointer option key (%s) of value (%s) not assigned!\n", 103535c4bbdfSmrg key, value); 103605b261ecSmrg } 103705b261ecSmrg} 103805b261ecSmrg 10391b5d61b8Smrgstatic KdPointerInfo * 104035c4bbdfSmrgKdParsePointer(const char *arg) 104105b261ecSmrg{ 104235c4bbdfSmrg char save[1024]; 104335c4bbdfSmrg char delim; 104435c4bbdfSmrg KdPointerInfo *pi = NULL; 104535c4bbdfSmrg InputOption *options = NULL; 104635c4bbdfSmrg int i = 0; 104705b261ecSmrg 104805b261ecSmrg pi = KdNewPointer(); 104905b261ecSmrg if (!pi) 105005b261ecSmrg return NULL; 105105b261ecSmrg pi->emulateMiddleButton = kdEmulateMiddleButton; 105205b261ecSmrg pi->transformCoordinates = !kdRawPointerCoordinates; 10536747b715Smrg pi->protocol = NULL; 105435c4bbdfSmrg pi->nButtons = 5; /* XXX should not be hardcoded */ 105505b261ecSmrg pi->inputClass = KD_MOUSE; 105605b261ecSmrg 105735c4bbdfSmrg if (!arg) { 105805b261ecSmrg ErrorF("mouse: no arg\n"); 105935c4bbdfSmrg KdFreePointer(pi); 106005b261ecSmrg return NULL; 106105b261ecSmrg } 106205b261ecSmrg 106335c4bbdfSmrg if (strlen(arg) >= sizeof(save)) { 106405b261ecSmrg ErrorF("mouse: arg too long\n"); 106535c4bbdfSmrg KdFreePointer(pi); 106605b261ecSmrg return NULL; 106705b261ecSmrg } 106835c4bbdfSmrg arg = KdParseFindNext(arg, ",", save, &delim); 106935c4bbdfSmrg if (!save[0]) { 107005b261ecSmrg ErrorF("failed on save[0]\n"); 107135c4bbdfSmrg KdFreePointer(pi); 107205b261ecSmrg return NULL; 107305b261ecSmrg } 107405b261ecSmrg 107505b261ecSmrg if (strcmp(save, "auto") == 0) 107605b261ecSmrg pi->driverPrivate = NULL; 107705b261ecSmrg else 10786747b715Smrg pi->driverPrivate = strdup(save); 107905b261ecSmrg 108035c4bbdfSmrg if (delim != ',') { 108105b261ecSmrg return pi; 108205b261ecSmrg } 108305b261ecSmrg 108435c4bbdfSmrg arg = KdParseFindNext(arg, ",", save, &delim); 108505b261ecSmrg 108635c4bbdfSmrg while (delim == ',') { 108735c4bbdfSmrg arg = KdParseFindNext(arg, ",", save, &delim); 108835c4bbdfSmrg if (save[0] == '{') { 108905b261ecSmrg char *s = save + 1; 109035c4bbdfSmrg 109135c4bbdfSmrg i = 0; 109235c4bbdfSmrg while (*s && *s != '}') { 109305b261ecSmrg if ('1' <= *s && *s <= '0' + pi->nButtons) 109405b261ecSmrg pi->map[i] = *s - '0'; 109505b261ecSmrg else 109635c4bbdfSmrg UseMsg(); 109705b261ecSmrg s++; 109835c4bbdfSmrg } 109905b261ecSmrg } 110035c4bbdfSmrg else { 110135c4bbdfSmrg if (!KdGetOptions(&options, save)) { 110205b261ecSmrg KdFreePointer(pi); 110305b261ecSmrg return NULL; 110405b261ecSmrg } 110505b261ecSmrg } 110605b261ecSmrg } 110705b261ecSmrg 110835c4bbdfSmrg if (options) { 110905b261ecSmrg pi->options = options; 111005b261ecSmrg KdParsePointerOptions(pi); 111105b261ecSmrg } 111205b261ecSmrg 111305b261ecSmrg return pi; 111405b261ecSmrg} 111505b261ecSmrg 111605b261ecSmrgvoid 111735c4bbdfSmrgKdInitInput(void) 111805b261ecSmrg{ 111905b261ecSmrg KdPointerInfo *pi; 112005b261ecSmrg KdKeyboardInfo *ki; 112105b261ecSmrg struct KdConfigDevice *dev; 112205b261ecSmrg 11231b5d61b8Smrg if (kdConfigPointers || kdConfigKeyboards) 11241b5d61b8Smrg InputThreadPreInit(); 11251b5d61b8Smrg 112605b261ecSmrg kdInputEnabled = TRUE; 112705b261ecSmrg 112805b261ecSmrg for (dev = kdConfigPointers; dev; dev = dev->next) { 112905b261ecSmrg pi = KdParsePointer(dev->line); 113005b261ecSmrg if (!pi) 113105b261ecSmrg ErrorF("Failed to parse pointer\n"); 113205b261ecSmrg if (KdAddPointer(pi) != Success) 113305b261ecSmrg ErrorF("Failed to add pointer!\n"); 113405b261ecSmrg } 113505b261ecSmrg for (dev = kdConfigKeyboards; dev; dev = dev->next) { 113605b261ecSmrg ki = KdParseKeyboard(dev->line); 113705b261ecSmrg if (!ki) 113805b261ecSmrg ErrorF("Failed to parse keyboard\n"); 113905b261ecSmrg if (KdAddKeyboard(ki) != Success) 114005b261ecSmrg ErrorF("Failed to add keyboard!\n"); 114105b261ecSmrg } 114205b261ecSmrg 114305b261ecSmrg mieqInit(); 11441b5d61b8Smrg 11451b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL) 11461b5d61b8Smrg if (SeatId) /* Enable input hot-plugging */ 11471b5d61b8Smrg config_init(); 11481b5d61b8Smrg#endif 114905b261ecSmrg} 115005b261ecSmrg 115135c4bbdfSmrgvoid 115235c4bbdfSmrgKdCloseInput(void) 115335c4bbdfSmrg{ 11541b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL) 11551b5d61b8Smrg if (SeatId) /* Input hot-plugging is enabled */ 11561b5d61b8Smrg config_fini(); 11571b5d61b8Smrg#endif 11581b5d61b8Smrg 115935c4bbdfSmrg mieqFini(); 116035c4bbdfSmrg} 116135c4bbdfSmrg 116205b261ecSmrg/* 116305b261ecSmrg * Middle button emulation state machine 116405b261ecSmrg * 116505b261ecSmrg * Possible transitions: 116605b261ecSmrg * Button 1 press v1 116705b261ecSmrg * Button 1 release ^1 116805b261ecSmrg * Button 2 press v2 116905b261ecSmrg * Button 2 release ^2 117005b261ecSmrg * Button 3 press v3 117105b261ecSmrg * Button 3 release ^3 117205b261ecSmrg * Button other press vo 117305b261ecSmrg * Button other release ^o 117405b261ecSmrg * Mouse motion <> 117505b261ecSmrg * Keyboard event k 117605b261ecSmrg * timeout ... 117705b261ecSmrg * outside box <-> 117805b261ecSmrg * 117905b261ecSmrg * States: 118005b261ecSmrg * start 118105b261ecSmrg * button_1_pend 118205b261ecSmrg * button_1_down 118305b261ecSmrg * button_2_down 118405b261ecSmrg * button_3_pend 118505b261ecSmrg * button_3_down 118605b261ecSmrg * synthetic_2_down_13 118705b261ecSmrg * synthetic_2_down_3 118805b261ecSmrg * synthetic_2_down_1 118905b261ecSmrg * 119005b261ecSmrg * Transition diagram 119105b261ecSmrg * 119205b261ecSmrg * start 119305b261ecSmrg * v1 -> (hold) (settimeout) button_1_pend 119405b261ecSmrg * ^1 -> (deliver) start 119505b261ecSmrg * v2 -> (deliver) button_2_down 119605b261ecSmrg * ^2 -> (deliever) start 119705b261ecSmrg * v3 -> (hold) (settimeout) button_3_pend 119805b261ecSmrg * ^3 -> (deliver) start 119905b261ecSmrg * vo -> (deliver) start 120005b261ecSmrg * ^o -> (deliver) start 120105b261ecSmrg * <> -> (deliver) start 120205b261ecSmrg * k -> (deliver) start 120305b261ecSmrg * 120405b261ecSmrg * button_1_pend (button 1 is down, timeout pending) 120505b261ecSmrg * ^1 -> (release) (deliver) start 120605b261ecSmrg * v2 -> (release) (deliver) button_1_down 120705b261ecSmrg * ^2 -> (release) (deliver) button_1_down 120805b261ecSmrg * v3 -> (cleartimeout) (generate v2) synthetic_2_down_13 120905b261ecSmrg * ^3 -> (release) (deliver) button_1_down 121005b261ecSmrg * vo -> (release) (deliver) button_1_down 121105b261ecSmrg * ^o -> (release) (deliver) button_1_down 121205b261ecSmrg * <-> -> (release) (deliver) button_1_down 121305b261ecSmrg * <> -> (deliver) button_1_pend 121405b261ecSmrg * k -> (release) (deliver) button_1_down 121505b261ecSmrg * ... -> (release) button_1_down 121605b261ecSmrg * 121705b261ecSmrg * button_1_down (button 1 is down) 121805b261ecSmrg * ^1 -> (deliver) start 121905b261ecSmrg * v2 -> (deliver) button_1_down 122005b261ecSmrg * ^2 -> (deliver) button_1_down 122105b261ecSmrg * v3 -> (deliver) button_1_down 122205b261ecSmrg * ^3 -> (deliver) button_1_down 122305b261ecSmrg * vo -> (deliver) button_1_down 122405b261ecSmrg * ^o -> (deliver) button_1_down 122505b261ecSmrg * <> -> (deliver) button_1_down 122605b261ecSmrg * k -> (deliver) button_1_down 122705b261ecSmrg * 122805b261ecSmrg * button_2_down (button 2 is down) 122905b261ecSmrg * v1 -> (deliver) button_2_down 123005b261ecSmrg * ^1 -> (deliver) button_2_down 123105b261ecSmrg * ^2 -> (deliver) start 123205b261ecSmrg * v3 -> (deliver) button_2_down 123305b261ecSmrg * ^3 -> (deliver) button_2_down 123405b261ecSmrg * vo -> (deliver) button_2_down 123505b261ecSmrg * ^o -> (deliver) button_2_down 123605b261ecSmrg * <> -> (deliver) button_2_down 123705b261ecSmrg * k -> (deliver) button_2_down 123805b261ecSmrg * 123905b261ecSmrg * button_3_pend (button 3 is down, timeout pending) 124005b261ecSmrg * v1 -> (generate v2) synthetic_2_down 124105b261ecSmrg * ^1 -> (release) (deliver) button_3_down 124205b261ecSmrg * v2 -> (release) (deliver) button_3_down 124305b261ecSmrg * ^2 -> (release) (deliver) button_3_down 124405b261ecSmrg * ^3 -> (release) (deliver) start 124505b261ecSmrg * vo -> (release) (deliver) button_3_down 124605b261ecSmrg * ^o -> (release) (deliver) button_3_down 124705b261ecSmrg * <-> -> (release) (deliver) button_3_down 124805b261ecSmrg * <> -> (deliver) button_3_pend 124905b261ecSmrg * k -> (release) (deliver) button_3_down 125005b261ecSmrg * ... -> (release) button_3_down 125105b261ecSmrg * 125205b261ecSmrg * button_3_down (button 3 is down) 125305b261ecSmrg * v1 -> (deliver) button_3_down 125405b261ecSmrg * ^1 -> (deliver) button_3_down 125505b261ecSmrg * v2 -> (deliver) button_3_down 125605b261ecSmrg * ^2 -> (deliver) button_3_down 125705b261ecSmrg * ^3 -> (deliver) start 125805b261ecSmrg * vo -> (deliver) button_3_down 125905b261ecSmrg * ^o -> (deliver) button_3_down 126005b261ecSmrg * <> -> (deliver) button_3_down 126105b261ecSmrg * k -> (deliver) button_3_down 126205b261ecSmrg * 126305b261ecSmrg * synthetic_2_down_13 (button 1 and 3 are down) 126405b261ecSmrg * ^1 -> (generate ^2) synthetic_2_down_3 126505b261ecSmrg * v2 -> synthetic_2_down_13 126605b261ecSmrg * ^2 -> synthetic_2_down_13 126705b261ecSmrg * ^3 -> (generate ^2) synthetic_2_down_1 126805b261ecSmrg * vo -> (deliver) synthetic_2_down_13 126905b261ecSmrg * ^o -> (deliver) synthetic_2_down_13 127005b261ecSmrg * <> -> (deliver) synthetic_2_down_13 127105b261ecSmrg * k -> (deliver) synthetic_2_down_13 127205b261ecSmrg * 127305b261ecSmrg * synthetic_2_down_3 (button 3 is down) 127405b261ecSmrg * v1 -> (deliver) synthetic_2_down_3 127505b261ecSmrg * ^1 -> (deliver) synthetic_2_down_3 127605b261ecSmrg * v2 -> synthetic_2_down_3 127705b261ecSmrg * ^2 -> synthetic_2_down_3 127805b261ecSmrg * ^3 -> start 127905b261ecSmrg * vo -> (deliver) synthetic_2_down_3 128005b261ecSmrg * ^o -> (deliver) synthetic_2_down_3 128105b261ecSmrg * <> -> (deliver) synthetic_2_down_3 128205b261ecSmrg * k -> (deliver) synthetic_2_down_3 128305b261ecSmrg * 128405b261ecSmrg * synthetic_2_down_1 (button 1 is down) 128505b261ecSmrg * ^1 -> start 128605b261ecSmrg * v2 -> synthetic_2_down_1 128705b261ecSmrg * ^2 -> synthetic_2_down_1 128805b261ecSmrg * v3 -> (deliver) synthetic_2_down_1 128905b261ecSmrg * ^3 -> (deliver) synthetic_2_down_1 129005b261ecSmrg * vo -> (deliver) synthetic_2_down_1 129105b261ecSmrg * ^o -> (deliver) synthetic_2_down_1 129205b261ecSmrg * <> -> (deliver) synthetic_2_down_1 129305b261ecSmrg * k -> (deliver) synthetic_2_down_1 129405b261ecSmrg */ 12956747b715Smrg 129605b261ecSmrgtypedef enum _inputClass { 129705b261ecSmrg down_1, up_1, 129805b261ecSmrg down_2, up_2, 129905b261ecSmrg down_3, up_3, 130005b261ecSmrg down_o, up_o, 130105b261ecSmrg motion, outside_box, 130205b261ecSmrg keyboard, timeout, 130305b261ecSmrg num_input_class 130405b261ecSmrg} KdInputClass; 130505b261ecSmrg 130605b261ecSmrgtypedef enum _inputAction { 130705b261ecSmrg noop, 130805b261ecSmrg hold, 130905b261ecSmrg setto, 131005b261ecSmrg deliver, 131105b261ecSmrg release, 131205b261ecSmrg clearto, 131305b261ecSmrg gen_down_2, 131405b261ecSmrg gen_up_2 131505b261ecSmrg} KdInputAction; 131605b261ecSmrg 131705b261ecSmrg#define MAX_ACTIONS 2 131805b261ecSmrg 131905b261ecSmrgtypedef struct _inputTransition { 132035c4bbdfSmrg KdInputAction actions[MAX_ACTIONS]; 132105b261ecSmrg KdPointerState nextState; 132205b261ecSmrg} KdInputTransition; 132305b261ecSmrg 132405b261ecSmrgstatic const 132535c4bbdfSmrgKdInputTransition kdInputMachine[num_input_states][num_input_class] = { 132605b261ecSmrg /* start */ 132705b261ecSmrg { 132835c4bbdfSmrg {{hold, setto}, button_1_pend}, /* v1 */ 132935c4bbdfSmrg {{deliver, noop}, start}, /* ^1 */ 133035c4bbdfSmrg {{deliver, noop}, button_2_down}, /* v2 */ 133135c4bbdfSmrg {{deliver, noop}, start}, /* ^2 */ 133235c4bbdfSmrg {{hold, setto}, button_3_pend}, /* v3 */ 133335c4bbdfSmrg {{deliver, noop}, start}, /* ^3 */ 133435c4bbdfSmrg {{deliver, noop}, start}, /* vo */ 133535c4bbdfSmrg {{deliver, noop}, start}, /* ^o */ 133635c4bbdfSmrg {{deliver, noop}, start}, /* <> */ 133735c4bbdfSmrg {{deliver, noop}, start}, /* <-> */ 133835c4bbdfSmrg {{noop, noop}, start}, /* k */ 133935c4bbdfSmrg {{noop, noop}, start}, /* ... */ 134035c4bbdfSmrg }, 134105b261ecSmrg /* button_1_pend */ 134205b261ecSmrg { 134335c4bbdfSmrg {{noop, noop}, button_1_pend}, /* v1 */ 134435c4bbdfSmrg {{release, deliver}, start}, /* ^1 */ 134535c4bbdfSmrg {{release, deliver}, button_1_down}, /* v2 */ 134635c4bbdfSmrg {{release, deliver}, button_1_down}, /* ^2 */ 134735c4bbdfSmrg {{clearto, gen_down_2}, synth_2_down_13}, /* v3 */ 134835c4bbdfSmrg {{release, deliver}, button_1_down}, /* ^3 */ 134935c4bbdfSmrg {{release, deliver}, button_1_down}, /* vo */ 135035c4bbdfSmrg {{release, deliver}, button_1_down}, /* ^o */ 135135c4bbdfSmrg {{deliver, noop}, button_1_pend}, /* <> */ 135235c4bbdfSmrg {{release, deliver}, button_1_down}, /* <-> */ 135335c4bbdfSmrg {{noop, noop}, button_1_down}, /* k */ 135435c4bbdfSmrg {{release, noop}, button_1_down}, /* ... */ 135535c4bbdfSmrg }, 135605b261ecSmrg /* button_1_down */ 135705b261ecSmrg { 135835c4bbdfSmrg {{noop, noop}, button_1_down}, /* v1 */ 135935c4bbdfSmrg {{deliver, noop}, start}, /* ^1 */ 136035c4bbdfSmrg {{deliver, noop}, button_1_down}, /* v2 */ 136135c4bbdfSmrg {{deliver, noop}, button_1_down}, /* ^2 */ 136235c4bbdfSmrg {{deliver, noop}, button_1_down}, /* v3 */ 136335c4bbdfSmrg {{deliver, noop}, button_1_down}, /* ^3 */ 136435c4bbdfSmrg {{deliver, noop}, button_1_down}, /* vo */ 136535c4bbdfSmrg {{deliver, noop}, button_1_down}, /* ^o */ 136635c4bbdfSmrg {{deliver, noop}, button_1_down}, /* <> */ 136735c4bbdfSmrg {{deliver, noop}, button_1_down}, /* <-> */ 136835c4bbdfSmrg {{noop, noop}, button_1_down}, /* k */ 136935c4bbdfSmrg {{noop, noop}, button_1_down}, /* ... */ 137035c4bbdfSmrg }, 137105b261ecSmrg /* button_2_down */ 137205b261ecSmrg { 137335c4bbdfSmrg {{deliver, noop}, button_2_down}, /* v1 */ 137435c4bbdfSmrg {{deliver, noop}, button_2_down}, /* ^1 */ 137535c4bbdfSmrg {{noop, noop}, button_2_down}, /* v2 */ 137635c4bbdfSmrg {{deliver, noop}, start}, /* ^2 */ 137735c4bbdfSmrg {{deliver, noop}, button_2_down}, /* v3 */ 137835c4bbdfSmrg {{deliver, noop}, button_2_down}, /* ^3 */ 137935c4bbdfSmrg {{deliver, noop}, button_2_down}, /* vo */ 138035c4bbdfSmrg {{deliver, noop}, button_2_down}, /* ^o */ 138135c4bbdfSmrg {{deliver, noop}, button_2_down}, /* <> */ 138235c4bbdfSmrg {{deliver, noop}, button_2_down}, /* <-> */ 138335c4bbdfSmrg {{noop, noop}, button_2_down}, /* k */ 138435c4bbdfSmrg {{noop, noop}, button_2_down}, /* ... */ 138535c4bbdfSmrg }, 138605b261ecSmrg /* button_3_pend */ 138705b261ecSmrg { 138835c4bbdfSmrg {{clearto, gen_down_2}, synth_2_down_13}, /* v1 */ 138935c4bbdfSmrg {{release, deliver}, button_3_down}, /* ^1 */ 139035c4bbdfSmrg {{release, deliver}, button_3_down}, /* v2 */ 139135c4bbdfSmrg {{release, deliver}, button_3_down}, /* ^2 */ 139235c4bbdfSmrg {{release, deliver}, button_3_down}, /* v3 */ 139335c4bbdfSmrg {{release, deliver}, start}, /* ^3 */ 139435c4bbdfSmrg {{release, deliver}, button_3_down}, /* vo */ 139535c4bbdfSmrg {{release, deliver}, button_3_down}, /* ^o */ 139635c4bbdfSmrg {{deliver, noop}, button_3_pend}, /* <> */ 139735c4bbdfSmrg {{release, deliver}, button_3_down}, /* <-> */ 139835c4bbdfSmrg {{release, noop}, button_3_down}, /* k */ 139935c4bbdfSmrg {{release, noop}, button_3_down}, /* ... */ 140035c4bbdfSmrg }, 140105b261ecSmrg /* button_3_down */ 140205b261ecSmrg { 140335c4bbdfSmrg {{deliver, noop}, button_3_down}, /* v1 */ 140435c4bbdfSmrg {{deliver, noop}, button_3_down}, /* ^1 */ 140535c4bbdfSmrg {{deliver, noop}, button_3_down}, /* v2 */ 140635c4bbdfSmrg {{deliver, noop}, button_3_down}, /* ^2 */ 140735c4bbdfSmrg {{noop, noop}, button_3_down}, /* v3 */ 140835c4bbdfSmrg {{deliver, noop}, start}, /* ^3 */ 140935c4bbdfSmrg {{deliver, noop}, button_3_down}, /* vo */ 141035c4bbdfSmrg {{deliver, noop}, button_3_down}, /* ^o */ 141135c4bbdfSmrg {{deliver, noop}, button_3_down}, /* <> */ 141235c4bbdfSmrg {{deliver, noop}, button_3_down}, /* <-> */ 141335c4bbdfSmrg {{noop, noop}, button_3_down}, /* k */ 141435c4bbdfSmrg {{noop, noop}, button_3_down}, /* ... */ 141535c4bbdfSmrg }, 141605b261ecSmrg /* synthetic_2_down_13 */ 141705b261ecSmrg { 141835c4bbdfSmrg {{noop, noop}, synth_2_down_13}, /* v1 */ 141935c4bbdfSmrg {{gen_up_2, noop}, synth_2_down_3}, /* ^1 */ 142035c4bbdfSmrg {{noop, noop}, synth_2_down_13}, /* v2 */ 142135c4bbdfSmrg {{noop, noop}, synth_2_down_13}, /* ^2 */ 142235c4bbdfSmrg {{noop, noop}, synth_2_down_13}, /* v3 */ 142335c4bbdfSmrg {{gen_up_2, noop}, synth_2_down_1}, /* ^3 */ 142435c4bbdfSmrg {{deliver, noop}, synth_2_down_13}, /* vo */ 142535c4bbdfSmrg {{deliver, noop}, synth_2_down_13}, /* ^o */ 142635c4bbdfSmrg {{deliver, noop}, synth_2_down_13}, /* <> */ 142735c4bbdfSmrg {{deliver, noop}, synth_2_down_13}, /* <-> */ 142835c4bbdfSmrg {{noop, noop}, synth_2_down_13}, /* k */ 142935c4bbdfSmrg {{noop, noop}, synth_2_down_13}, /* ... */ 143035c4bbdfSmrg }, 143105b261ecSmrg /* synthetic_2_down_3 */ 143205b261ecSmrg { 143335c4bbdfSmrg {{deliver, noop}, synth_2_down_3}, /* v1 */ 143435c4bbdfSmrg {{deliver, noop}, synth_2_down_3}, /* ^1 */ 143535c4bbdfSmrg {{deliver, noop}, synth_2_down_3}, /* v2 */ 143635c4bbdfSmrg {{deliver, noop}, synth_2_down_3}, /* ^2 */ 143735c4bbdfSmrg {{noop, noop}, synth_2_down_3}, /* v3 */ 143835c4bbdfSmrg {{noop, noop}, start}, /* ^3 */ 143935c4bbdfSmrg {{deliver, noop}, synth_2_down_3}, /* vo */ 144035c4bbdfSmrg {{deliver, noop}, synth_2_down_3}, /* ^o */ 144135c4bbdfSmrg {{deliver, noop}, synth_2_down_3}, /* <> */ 144235c4bbdfSmrg {{deliver, noop}, synth_2_down_3}, /* <-> */ 144335c4bbdfSmrg {{noop, noop}, synth_2_down_3}, /* k */ 144435c4bbdfSmrg {{noop, noop}, synth_2_down_3}, /* ... */ 144535c4bbdfSmrg }, 144605b261ecSmrg /* synthetic_2_down_1 */ 144705b261ecSmrg { 144835c4bbdfSmrg {{noop, noop}, synth_2_down_1}, /* v1 */ 144935c4bbdfSmrg {{noop, noop}, start}, /* ^1 */ 145035c4bbdfSmrg {{deliver, noop}, synth_2_down_1}, /* v2 */ 145135c4bbdfSmrg {{deliver, noop}, synth_2_down_1}, /* ^2 */ 145235c4bbdfSmrg {{deliver, noop}, synth_2_down_1}, /* v3 */ 145335c4bbdfSmrg {{deliver, noop}, synth_2_down_1}, /* ^3 */ 145435c4bbdfSmrg {{deliver, noop}, synth_2_down_1}, /* vo */ 145535c4bbdfSmrg {{deliver, noop}, synth_2_down_1}, /* ^o */ 145635c4bbdfSmrg {{deliver, noop}, synth_2_down_1}, /* <> */ 145735c4bbdfSmrg {{deliver, noop}, synth_2_down_1}, /* <-> */ 145835c4bbdfSmrg {{noop, noop}, synth_2_down_1}, /* k */ 145935c4bbdfSmrg {{noop, noop}, synth_2_down_1}, /* ... */ 146035c4bbdfSmrg }, 146105b261ecSmrg}; 146205b261ecSmrg 146305b261ecSmrg#define EMULATION_WINDOW 10 146405b261ecSmrg#define EMULATION_TIMEOUT 100 146505b261ecSmrg 146605b261ecSmrgstatic int 146735c4bbdfSmrgKdInsideEmulationWindow(KdPointerInfo * pi, int x, int y, int z) 146805b261ecSmrg{ 146905b261ecSmrg pi->emulationDx = pi->heldEvent.x - x; 147005b261ecSmrg pi->emulationDy = pi->heldEvent.y - y; 147105b261ecSmrg 147235c4bbdfSmrg return (abs(pi->emulationDx) < EMULATION_WINDOW && 147335c4bbdfSmrg abs(pi->emulationDy) < EMULATION_WINDOW); 147405b261ecSmrg} 14756747b715Smrg 147605b261ecSmrgstatic KdInputClass 147735c4bbdfSmrgKdClassifyInput(KdPointerInfo * pi, int type, int x, int y, int z, int b) 147805b261ecSmrg{ 147905b261ecSmrg switch (type) { 148005b261ecSmrg case ButtonPress: 148135c4bbdfSmrg switch (b) { 148235c4bbdfSmrg case 1: 148335c4bbdfSmrg return down_1; 148435c4bbdfSmrg case 2: 148535c4bbdfSmrg return down_2; 148635c4bbdfSmrg case 3: 148735c4bbdfSmrg return down_3; 148835c4bbdfSmrg default: 148935c4bbdfSmrg return down_o; 149035c4bbdfSmrg } 149135c4bbdfSmrg break; 149205b261ecSmrg case ButtonRelease: 149335c4bbdfSmrg switch (b) { 149435c4bbdfSmrg case 1: 149535c4bbdfSmrg return up_1; 149635c4bbdfSmrg case 2: 149735c4bbdfSmrg return up_2; 149835c4bbdfSmrg case 3: 149935c4bbdfSmrg return up_3; 150035c4bbdfSmrg default: 150135c4bbdfSmrg return up_o; 150235c4bbdfSmrg } 150335c4bbdfSmrg break; 150405b261ecSmrg case MotionNotify: 150535c4bbdfSmrg if (pi->eventHeld && !KdInsideEmulationWindow(pi, x, y, z)) 150635c4bbdfSmrg return outside_box; 150735c4bbdfSmrg else 150835c4bbdfSmrg return motion; 150905b261ecSmrg default: 151035c4bbdfSmrg return keyboard; 151105b261ecSmrg } 151205b261ecSmrg return keyboard; 151305b261ecSmrg} 151405b261ecSmrg 15151b5d61b8Smrgstatic void 15161b5d61b8Smrg_KdEnqueuePointerEvent(KdPointerInfo * pi, int type, int x, int y, int z, 15171b5d61b8Smrg int b, int absrel, Bool force); 151805b261ecSmrg/* We return true if we're stealing the event. */ 151905b261ecSmrgstatic Bool 152035c4bbdfSmrgKdRunMouseMachine(KdPointerInfo * pi, KdInputClass c, int type, int x, int y, 152135c4bbdfSmrg int z, int b, int absrel) 152205b261ecSmrg{ 152305b261ecSmrg const KdInputTransition *t; 152435c4bbdfSmrg int a; 152505b261ecSmrg 152605b261ecSmrg c = KdClassifyInput(pi, type, x, y, z, b); 152705b261ecSmrg t = &kdInputMachine[pi->mouseState][c]; 152835c4bbdfSmrg for (a = 0; a < MAX_ACTIONS; a++) { 152935c4bbdfSmrg switch (t->actions[a]) { 153035c4bbdfSmrg case noop: 153135c4bbdfSmrg break; 153235c4bbdfSmrg case hold: 153335c4bbdfSmrg pi->eventHeld = TRUE; 153435c4bbdfSmrg pi->emulationDx = 0; 153535c4bbdfSmrg pi->emulationDy = 0; 153635c4bbdfSmrg pi->heldEvent.type = type; 153705b261ecSmrg pi->heldEvent.x = x; 153805b261ecSmrg pi->heldEvent.y = y; 153905b261ecSmrg pi->heldEvent.z = z; 154005b261ecSmrg pi->heldEvent.flags = b; 154105b261ecSmrg pi->heldEvent.absrel = absrel; 154205b261ecSmrg return TRUE; 154335c4bbdfSmrg break; 154435c4bbdfSmrg case setto: 154535c4bbdfSmrg pi->emulationTimeout = GetTimeInMillis() + EMULATION_TIMEOUT; 154635c4bbdfSmrg pi->timeoutPending = TRUE; 154735c4bbdfSmrg break; 154835c4bbdfSmrg case deliver: 154935c4bbdfSmrg _KdEnqueuePointerEvent(pi, pi->heldEvent.type, pi->heldEvent.x, 155035c4bbdfSmrg pi->heldEvent.y, pi->heldEvent.z, 155135c4bbdfSmrg pi->heldEvent.flags, pi->heldEvent.absrel, 155235c4bbdfSmrg TRUE); 155335c4bbdfSmrg break; 155435c4bbdfSmrg case release: 155535c4bbdfSmrg pi->eventHeld = FALSE; 155635c4bbdfSmrg pi->timeoutPending = FALSE; 155735c4bbdfSmrg _KdEnqueuePointerEvent(pi, pi->heldEvent.type, pi->heldEvent.x, 155835c4bbdfSmrg pi->heldEvent.y, pi->heldEvent.z, 155935c4bbdfSmrg pi->heldEvent.flags, pi->heldEvent.absrel, 156035c4bbdfSmrg TRUE); 156105b261ecSmrg return TRUE; 156235c4bbdfSmrg break; 156335c4bbdfSmrg case clearto: 156435c4bbdfSmrg pi->timeoutPending = FALSE; 156535c4bbdfSmrg break; 156635c4bbdfSmrg case gen_down_2: 156735c4bbdfSmrg _KdEnqueuePointerEvent(pi, ButtonPress, x, y, z, 2, absrel, TRUE); 156835c4bbdfSmrg pi->eventHeld = FALSE; 156905b261ecSmrg return TRUE; 157035c4bbdfSmrg break; 157135c4bbdfSmrg case gen_up_2: 157235c4bbdfSmrg _KdEnqueuePointerEvent(pi, ButtonRelease, x, y, z, 2, absrel, TRUE); 157305b261ecSmrg return TRUE; 157435c4bbdfSmrg break; 157535c4bbdfSmrg } 157605b261ecSmrg } 157705b261ecSmrg pi->mouseState = t->nextState; 157805b261ecSmrg return FALSE; 157905b261ecSmrg} 158005b261ecSmrg 158105b261ecSmrgstatic int 158235c4bbdfSmrgKdHandlePointerEvent(KdPointerInfo * pi, int type, int x, int y, int z, int b, 158335c4bbdfSmrg int absrel) 158405b261ecSmrg{ 158505b261ecSmrg if (pi->emulateMiddleButton) 158635c4bbdfSmrg return KdRunMouseMachine(pi, KdClassifyInput(pi, type, x, y, z, b), 158735c4bbdfSmrg type, x, y, z, b, absrel); 158805b261ecSmrg return FALSE; 158905b261ecSmrg} 159005b261ecSmrg 159105b261ecSmrgstatic void 15921b5d61b8Smrg_KdEnqueuePointerEvent(KdPointerInfo * pi, int type, int x, int y, int z, 15931b5d61b8Smrg int b, int absrel, Bool force) 159405b261ecSmrg{ 15951b5d61b8Smrg int valuators[3] = { x, y, z }; 15961b5d61b8Smrg ValuatorMask mask; 159705b261ecSmrg 15981b5d61b8Smrg /* TRUE from KdHandlePointerEvent, means 'we swallowed the event'. */ 15991b5d61b8Smrg if (!force && KdHandlePointerEvent(pi, type, x, y, z, b, absrel)) 16001b5d61b8Smrg return; 160105b261ecSmrg 16021b5d61b8Smrg valuator_mask_set_range(&mask, 0, 3, valuators); 160305b261ecSmrg 16041b5d61b8Smrg QueuePointerEvents(pi->dixdev, type, b, absrel, &mask); 16051b5d61b8Smrg} 160605b261ecSmrg 16071b5d61b8Smrgstatic void 16081b5d61b8SmrgKdReceiveTimeout(KdPointerInfo * pi) 16091b5d61b8Smrg{ 16101b5d61b8Smrg KdRunMouseMachine(pi, timeout, 0, 0, 0, 0, 0, 0); 161105b261ecSmrg} 161205b261ecSmrg 16131b5d61b8Smrgextern int nClients; 16141b5d61b8Smrg 161505b261ecSmrgstatic void 161635c4bbdfSmrgKdCheckLock(void) 161705b261ecSmrg{ 161835c4bbdfSmrg KeyClassPtr keyc = NULL; 161935c4bbdfSmrg Bool isSet = FALSE, shouldBeSet = FALSE; 162035c4bbdfSmrg KdKeyboardInfo *tmp = NULL; 162105b261ecSmrg 162205b261ecSmrg for (tmp = kdKeyboards; tmp; tmp = tmp->next) { 162305b261ecSmrg if (tmp->LockLed && tmp->dixdev && tmp->dixdev->key) { 162405b261ecSmrg keyc = tmp->dixdev->key; 162535c4bbdfSmrg isSet = (tmp->leds & (1 << (tmp->LockLed - 1))) != 0; 16266747b715Smrg /* FIXME: Just use XKB indicators! */ 162735c4bbdfSmrg shouldBeSet = 162835c4bbdfSmrg ! !(XkbStateFieldFromRec(&keyc->xkbInfo->state) & LockMask); 162905b261ecSmrg if (isSet != shouldBeSet) 163035c4bbdfSmrg KdSetLed(tmp, tmp->LockLed, shouldBeSet); 163105b261ecSmrg } 163205b261ecSmrg } 163305b261ecSmrg} 163405b261ecSmrg 163505b261ecSmrgvoid 163635c4bbdfSmrgKdEnqueueKeyboardEvent(KdKeyboardInfo * ki, 163735c4bbdfSmrg unsigned char scan_code, unsigned char is_up) 163805b261ecSmrg{ 163905b261ecSmrg unsigned char key_code; 164035c4bbdfSmrg int type; 164105b261ecSmrg 164205b261ecSmrg if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed || !ki->dixdev->key) 164335c4bbdfSmrg return; 16446747b715Smrg 164535c4bbdfSmrg if (scan_code >= ki->minScanCode && scan_code <= ki->maxScanCode) { 164635c4bbdfSmrg key_code = scan_code + KD_MIN_KEYCODE - ki->minScanCode; 16476747b715Smrg 164835c4bbdfSmrg /* 164935c4bbdfSmrg * Set up this event -- the type may be modified below 165035c4bbdfSmrg */ 165135c4bbdfSmrg if (is_up) 165235c4bbdfSmrg type = KeyRelease; 165335c4bbdfSmrg else 165435c4bbdfSmrg type = KeyPress; 16556747b715Smrg 165635c4bbdfSmrg QueueKeyboardEvents(ki->dixdev, type, key_code); 165705b261ecSmrg } 165805b261ecSmrg else { 165905b261ecSmrg ErrorF("driver %s wanted to post scancode %d outside of [%d, %d]!\n", 166005b261ecSmrg ki->name, scan_code, ki->minScanCode, ki->maxScanCode); 166105b261ecSmrg } 166205b261ecSmrg} 166305b261ecSmrg 166405b261ecSmrg/* 166505b261ecSmrg * kdEnqueuePointerEvent 166605b261ecSmrg * 166705b261ecSmrg * This function converts hardware mouse event information into X event 166805b261ecSmrg * information. A mouse movement event is passed off to MI to generate 166905b261ecSmrg * a MotionNotify event, if appropriate. Button events are created and 167005b261ecSmrg * passed off to MI for enqueueing. 167105b261ecSmrg */ 167205b261ecSmrg 167305b261ecSmrg/* FIXME do something a little more clever to deal with multiple axes here */ 167405b261ecSmrgvoid 167535c4bbdfSmrgKdEnqueuePointerEvent(KdPointerInfo * pi, unsigned long flags, int rx, int ry, 167605b261ecSmrg int rz) 167705b261ecSmrg{ 167805b261ecSmrg unsigned char buttons; 167935c4bbdfSmrg int x, y, z; 168035c4bbdfSmrg int (*matrix)[3] = kdPointerMatrix.matrix; 168105b261ecSmrg unsigned long button; 168235c4bbdfSmrg int n; 168335c4bbdfSmrg int dixflags = 0; 168405b261ecSmrg 168505b261ecSmrg if (!pi) 168635c4bbdfSmrg return; 168705b261ecSmrg 168805b261ecSmrg /* we don't need to transform z, so we don't. */ 168905b261ecSmrg if (flags & KD_MOUSE_DELTA) { 169035c4bbdfSmrg if (pi->transformCoordinates) { 169135c4bbdfSmrg x = matrix[0][0] * rx + matrix[0][1] * ry; 169235c4bbdfSmrg y = matrix[1][0] * rx + matrix[1][1] * ry; 169335c4bbdfSmrg } 169435c4bbdfSmrg else { 169535c4bbdfSmrg x = rx; 169635c4bbdfSmrg y = ry; 169735c4bbdfSmrg } 169805b261ecSmrg } 169905b261ecSmrg else { 170035c4bbdfSmrg if (pi->transformCoordinates) { 170135c4bbdfSmrg x = matrix[0][0] * rx + matrix[0][1] * ry + matrix[0][2]; 170235c4bbdfSmrg y = matrix[1][0] * rx + matrix[1][1] * ry + matrix[1][2]; 170335c4bbdfSmrg } 170435c4bbdfSmrg else { 170535c4bbdfSmrg x = rx; 170635c4bbdfSmrg y = ry; 170735c4bbdfSmrg } 170805b261ecSmrg } 170905b261ecSmrg z = rz; 171005b261ecSmrg 171135c4bbdfSmrg if (flags & KD_MOUSE_DELTA) { 171235c4bbdfSmrg if (x || y || z) { 17134642e01fSmrg dixflags = POINTER_RELATIVE | POINTER_ACCELERATE; 171435c4bbdfSmrg _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags, 171535c4bbdfSmrg FALSE); 17164642e01fSmrg } 171735c4bbdfSmrg } 171835c4bbdfSmrg else { 171905b261ecSmrg dixflags = POINTER_ABSOLUTE; 172035c4bbdfSmrg if (flags & KD_POINTER_DESKTOP) 172135c4bbdfSmrg dixflags |= POINTER_DESKTOP; 17224642e01fSmrg if (x != pi->dixdev->last.valuators[0] || 17234642e01fSmrg y != pi->dixdev->last.valuators[1]) 172435c4bbdfSmrg _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags, 172535c4bbdfSmrg FALSE); 17264642e01fSmrg } 172705b261ecSmrg 172805b261ecSmrg buttons = flags; 172905b261ecSmrg 173035c4bbdfSmrg for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons; button <<= 1, n++) { 173105b261ecSmrg if (((pi->buttonState & button) ^ (buttons & button)) && 173235c4bbdfSmrg !(buttons & button)) { 173305b261ecSmrg _KdEnqueuePointerEvent(pi, ButtonRelease, x, y, z, n, 173405b261ecSmrg dixflags, FALSE); 173535c4bbdfSmrg } 173605b261ecSmrg } 173735c4bbdfSmrg for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons; button <<= 1, n++) { 173835c4bbdfSmrg if (((pi->buttonState & button) ^ (buttons & button)) && 173935c4bbdfSmrg (buttons & button)) { 174005b261ecSmrg _KdEnqueuePointerEvent(pi, ButtonPress, x, y, z, n, 174105b261ecSmrg dixflags, FALSE); 174205b261ecSmrg } 174305b261ecSmrg } 174405b261ecSmrg 174505b261ecSmrg pi->buttonState = buttons; 174605b261ecSmrg} 174705b261ecSmrg 174805b261ecSmrgvoid 17491b5d61b8SmrgKdBlockHandler(ScreenPtr pScreen, void *timeo) 175005b261ecSmrg{ 175135c4bbdfSmrg KdPointerInfo *pi; 175235c4bbdfSmrg int myTimeout = 0; 17536747b715Smrg 175435c4bbdfSmrg for (pi = kdPointers; pi; pi = pi->next) { 175535c4bbdfSmrg if (pi->timeoutPending) { 175635c4bbdfSmrg int ms; 175735c4bbdfSmrg 175835c4bbdfSmrg ms = pi->emulationTimeout - GetTimeInMillis(); 175935c4bbdfSmrg if (ms < 1) 176035c4bbdfSmrg ms = 1; 176135c4bbdfSmrg if (ms < myTimeout || myTimeout == 0) 176235c4bbdfSmrg myTimeout = ms; 176335c4bbdfSmrg } 176405b261ecSmrg } 176535c4bbdfSmrg if (myTimeout > 0) 176635c4bbdfSmrg AdjustWaitForDelay(timeo, myTimeout); 176705b261ecSmrg} 176805b261ecSmrg 176905b261ecSmrgvoid 17701b5d61b8SmrgKdWakeupHandler(ScreenPtr pScreen, int result) 177105b261ecSmrg{ 177235c4bbdfSmrg KdPointerInfo *pi; 17736747b715Smrg 177435c4bbdfSmrg for (pi = kdPointers; pi; pi = pi->next) { 177535c4bbdfSmrg if (pi->timeoutPending) { 177635c4bbdfSmrg if ((long) (GetTimeInMillis() - pi->emulationTimeout) >= 0) { 177735c4bbdfSmrg pi->timeoutPending = FALSE; 17781b5d61b8Smrg input_lock(); 177935c4bbdfSmrg KdReceiveTimeout(pi); 17801b5d61b8Smrg input_unlock(); 178135c4bbdfSmrg } 178235c4bbdfSmrg } 178305b261ecSmrg } 178405b261ecSmrg} 178505b261ecSmrg 178605b261ecSmrg#define KdScreenOrigin(pScreen) (&(KdGetScreenPriv(pScreen)->screen->origin)) 178705b261ecSmrg 178805b261ecSmrgstatic Bool 178905b261ecSmrgKdCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) 179005b261ecSmrg{ 179135c4bbdfSmrg ScreenPtr pScreen = *ppScreen; 179235c4bbdfSmrg ScreenPtr pNewScreen; 179335c4bbdfSmrg int n; 179435c4bbdfSmrg int dx, dy; 179535c4bbdfSmrg int best_x, best_y; 179635c4bbdfSmrg int n_best_x, n_best_y; 179735c4bbdfSmrg CARD32 ms; 17986747b715Smrg 179905b261ecSmrg if (kdDisableZaphod || screenInfo.numScreens <= 1) 180035c4bbdfSmrg return FALSE; 180105b261ecSmrg 180205b261ecSmrg if (0 <= *x && *x < pScreen->width && 0 <= *y && *y < pScreen->height) 180335c4bbdfSmrg return FALSE; 18046747b715Smrg 180535c4bbdfSmrg ms = GetTimeInMillis(); 180605b261ecSmrg if (kdOffScreen && (int) (ms - kdOffScreenTime) < 1000) 180735c4bbdfSmrg return FALSE; 180805b261ecSmrg kdOffScreen = TRUE; 180905b261ecSmrg kdOffScreenTime = ms; 181005b261ecSmrg n_best_x = -1; 181105b261ecSmrg best_x = 32767; 181205b261ecSmrg n_best_y = -1; 181305b261ecSmrg best_y = 32767; 181435c4bbdfSmrg for (n = 0; n < screenInfo.numScreens; n++) { 181535c4bbdfSmrg pNewScreen = screenInfo.screens[n]; 181635c4bbdfSmrg if (pNewScreen == pScreen) 181735c4bbdfSmrg continue; 181835c4bbdfSmrg dx = KdScreenOrigin(pNewScreen)->x - KdScreenOrigin(pScreen)->x; 181935c4bbdfSmrg dy = KdScreenOrigin(pNewScreen)->y - KdScreenOrigin(pScreen)->y; 182035c4bbdfSmrg if (*x < 0) { 182135c4bbdfSmrg if (dx < 0 && -dx < best_x) { 182235c4bbdfSmrg best_x = -dx; 182335c4bbdfSmrg n_best_x = n; 182435c4bbdfSmrg } 182535c4bbdfSmrg } 182635c4bbdfSmrg else if (*x >= pScreen->width) { 182735c4bbdfSmrg if (dx > 0 && dx < best_x) { 182835c4bbdfSmrg best_x = dx; 182935c4bbdfSmrg n_best_x = n; 183035c4bbdfSmrg } 183135c4bbdfSmrg } 183235c4bbdfSmrg if (*y < 0) { 183335c4bbdfSmrg if (dy < 0 && -dy < best_y) { 183435c4bbdfSmrg best_y = -dy; 183535c4bbdfSmrg n_best_y = n; 183635c4bbdfSmrg } 183735c4bbdfSmrg } 183835c4bbdfSmrg else if (*y >= pScreen->height) { 183935c4bbdfSmrg if (dy > 0 && dy < best_y) { 184035c4bbdfSmrg best_y = dy; 184135c4bbdfSmrg n_best_y = n; 184235c4bbdfSmrg } 184335c4bbdfSmrg } 184405b261ecSmrg } 184505b261ecSmrg if (best_y < best_x) 184635c4bbdfSmrg n_best_x = n_best_y; 184705b261ecSmrg if (n_best_x == -1) 184835c4bbdfSmrg return FALSE; 184905b261ecSmrg pNewScreen = screenInfo.screens[n_best_x]; 18506747b715Smrg 185105b261ecSmrg if (*x < 0) 185235c4bbdfSmrg *x += pNewScreen->width; 185305b261ecSmrg if (*y < 0) 185435c4bbdfSmrg *y += pNewScreen->height; 18556747b715Smrg 185605b261ecSmrg if (*x >= pScreen->width) 185735c4bbdfSmrg *x -= pScreen->width; 185805b261ecSmrg if (*y >= pScreen->height) 185935c4bbdfSmrg *y -= pScreen->height; 18606747b715Smrg 186105b261ecSmrg *ppScreen = pNewScreen; 186205b261ecSmrg return TRUE; 186305b261ecSmrg} 186405b261ecSmrg 186505b261ecSmrgstatic void 186605b261ecSmrgKdCrossScreen(ScreenPtr pScreen, Bool entering) 186705b261ecSmrg{ 186805b261ecSmrg} 186905b261ecSmrg 187005b261ecSmrgstatic void 187135c4bbdfSmrgKdWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 187205b261ecSmrg{ 18731b5d61b8Smrg input_lock(); 18744642e01fSmrg miPointerWarpCursor(pDev, pScreen, x, y); 18751b5d61b8Smrg input_unlock(); 187605b261ecSmrg} 187705b261ecSmrg 187835c4bbdfSmrgmiPointerScreenFuncRec kdPointerScreenFuncs = { 187905b261ecSmrg KdCursorOffScreen, 188005b261ecSmrg KdCrossScreen, 188105b261ecSmrg KdWarpCursor 188205b261ecSmrg}; 188305b261ecSmrg 188405b261ecSmrgvoid 188535c4bbdfSmrgProcessInputEvents(void) 188605b261ecSmrg{ 188705b261ecSmrg mieqProcessInputEvents(); 188835c4bbdfSmrg KdCheckLock(); 188905b261ecSmrg} 189005b261ecSmrg 189105b261ecSmrg/* At the moment, absolute/relative is up to the client. */ 189205b261ecSmrgint 189305b261ecSmrgSetDeviceMode(register ClientPtr client, DeviceIntPtr pDev, int mode) 189405b261ecSmrg{ 189505b261ecSmrg return BadMatch; 189605b261ecSmrg} 189705b261ecSmrg 189805b261ecSmrgint 189905b261ecSmrgSetDeviceValuators(register ClientPtr client, DeviceIntPtr pDev, 190005b261ecSmrg int *valuators, int first_valuator, int num_valuators) 190105b261ecSmrg{ 190205b261ecSmrg return BadMatch; 190305b261ecSmrg} 190405b261ecSmrg 190505b261ecSmrgint 190605b261ecSmrgChangeDeviceControl(register ClientPtr client, DeviceIntPtr pDev, 190735c4bbdfSmrg xDeviceCtl * control) 190805b261ecSmrg{ 190905b261ecSmrg switch (control->control) { 191005b261ecSmrg case DEVICE_RESOLUTION: 191105b261ecSmrg /* FIXME do something more intelligent here */ 191205b261ecSmrg return BadMatch; 191305b261ecSmrg 191405b261ecSmrg case DEVICE_ABS_CALIB: 191505b261ecSmrg case DEVICE_ABS_AREA: 191605b261ecSmrg case DEVICE_CORE: 19174642e01fSmrg return BadMatch; 191805b261ecSmrg case DEVICE_ENABLE: 191905b261ecSmrg return Success; 192005b261ecSmrg 192105b261ecSmrg default: 192205b261ecSmrg return BadMatch; 192305b261ecSmrg } 192405b261ecSmrg 192505b261ecSmrg /* NOTREACHED */ 192605b261ecSmrg return BadImplementation; 192705b261ecSmrg} 192805b261ecSmrg 192905b261ecSmrgint 193035c4bbdfSmrgNewInputDeviceRequest(InputOption *options, InputAttributes * attrs, 19316747b715Smrg DeviceIntPtr *pdev) 193205b261ecSmrg{ 19331b5d61b8Smrg InputOption *option = NULL, *optionsdup = NULL; 193405b261ecSmrg KdPointerInfo *pi = NULL; 193505b261ecSmrg KdKeyboardInfo *ki = NULL; 193605b261ecSmrg 193735c4bbdfSmrg nt_list_for_each_entry(option, options, list.next) { 193835c4bbdfSmrg const char *key = input_option_get_key(option); 193935c4bbdfSmrg const char *value = input_option_get_value(option); 19401b5d61b8Smrg optionsdup = input_option_new(optionsdup, key, value); 194135c4bbdfSmrg 194235c4bbdfSmrg if (strcmp(key, "type") == 0) { 194335c4bbdfSmrg if (strcmp(value, "pointer") == 0) { 194405b261ecSmrg pi = KdNewPointer(); 19451b5d61b8Smrg if (!pi) { 19461b5d61b8Smrg input_option_free_list(&optionsdup); 194705b261ecSmrg return BadAlloc; 19481b5d61b8Smrg } 194905b261ecSmrg } 195035c4bbdfSmrg else if (strcmp(value, "keyboard") == 0) { 195105b261ecSmrg ki = KdNewKeyboard(); 19521b5d61b8Smrg if (!ki) { 19531b5d61b8Smrg input_option_free_list(&optionsdup); 195405b261ecSmrg return BadAlloc; 19551b5d61b8Smrg } 195605b261ecSmrg } 195705b261ecSmrg else { 195805b261ecSmrg ErrorF("unrecognised device type!\n"); 195905b261ecSmrg return BadValue; 196005b261ecSmrg } 196105b261ecSmrg } 19626747b715Smrg#ifdef CONFIG_HAL 196335c4bbdfSmrg else if (strcmp(key, "_source") == 0 && 196435c4bbdfSmrg strcmp(value, "server/hal") == 0) { 19651b5d61b8Smrg if (SeatId) { 19661b5d61b8Smrg /* Input hot-plugging is enabled */ 19671b5d61b8Smrg if (attrs->flags & ATTR_POINTER) { 19681b5d61b8Smrg pi = KdNewPointer(); 19691b5d61b8Smrg if (!pi) { 19701b5d61b8Smrg input_option_free_list(&optionsdup); 19711b5d61b8Smrg return BadAlloc; 19721b5d61b8Smrg } 19731b5d61b8Smrg } 19741b5d61b8Smrg else if (attrs->flags & ATTR_KEYBOARD) { 19751b5d61b8Smrg ki = KdNewKeyboard(); 19761b5d61b8Smrg if (!ki) { 19771b5d61b8Smrg input_option_free_list(&optionsdup); 19781b5d61b8Smrg return BadAlloc; 19791b5d61b8Smrg } 19801b5d61b8Smrg } 19811b5d61b8Smrg } 19821b5d61b8Smrg else { 19831b5d61b8Smrg ErrorF("Ignoring device from HAL.\n"); 19841b5d61b8Smrg input_option_free_list(&optionsdup); 19851b5d61b8Smrg return BadValue; 19861b5d61b8Smrg } 19876747b715Smrg } 19886747b715Smrg#endif 19896747b715Smrg#ifdef CONFIG_UDEV 199035c4bbdfSmrg else if (strcmp(key, "_source") == 0 && 199135c4bbdfSmrg strcmp(value, "server/udev") == 0) { 19921b5d61b8Smrg if (SeatId) { 19931b5d61b8Smrg /* Input hot-plugging is enabled */ 19941b5d61b8Smrg if (attrs->flags & ATTR_POINTER) { 19951b5d61b8Smrg pi = KdNewPointer(); 19961b5d61b8Smrg if (!pi) { 19971b5d61b8Smrg input_option_free_list(&optionsdup); 19981b5d61b8Smrg return BadAlloc; 19991b5d61b8Smrg } 200005b261ecSmrg } 20011b5d61b8Smrg else if (attrs->flags & ATTR_KEYBOARD) { 20021b5d61b8Smrg ki = KdNewKeyboard(); 20031b5d61b8Smrg if (!ki) { 20041b5d61b8Smrg input_option_free_list(&optionsdup); 20051b5d61b8Smrg return BadAlloc; 20061b5d61b8Smrg } 200705b261ecSmrg } 20081b5d61b8Smrg } 20091b5d61b8Smrg else { 20101b5d61b8Smrg ErrorF("Ignoring device from udev.\n"); 20111b5d61b8Smrg input_option_free_list(&optionsdup); 20121b5d61b8Smrg return BadValue; 201305b261ecSmrg } 201405b261ecSmrg } 20151b5d61b8Smrg#endif 201605b261ecSmrg } 201705b261ecSmrg 201805b261ecSmrg if (pi) { 20191b5d61b8Smrg pi->options = optionsdup; 20201b5d61b8Smrg KdParsePointerOptions(pi); 20211b5d61b8Smrg 20221b5d61b8Smrg if (!pi->driver) { 20231b5d61b8Smrg ErrorF("couldn't find driver for pointer device \"%s\" (%s)\n", 20241b5d61b8Smrg pi->name ? pi->name : "(unnamed)", pi->path); 20251b5d61b8Smrg KdFreePointer(pi); 20261b5d61b8Smrg return BadValue; 20271b5d61b8Smrg } 20281b5d61b8Smrg 202905b261ecSmrg if (KdAddPointer(pi) != Success || 20306747b715Smrg ActivateDevice(pi->dixdev, TRUE) != Success || 20316747b715Smrg EnableDevice(pi->dixdev, TRUE) != TRUE) { 20321b5d61b8Smrg ErrorF("couldn't add or enable pointer \"%s\" (%s)\n", 20331b5d61b8Smrg pi->name ? pi->name : "(unnamed)", pi->path); 20341b5d61b8Smrg KdFreePointer(pi); 203505b261ecSmrg return BadImplementation; 203605b261ecSmrg } 20371b5d61b8Smrg 20381b5d61b8Smrg *pdev = pi->dixdev; 203905b261ecSmrg } 204005b261ecSmrg else if (ki) { 20411b5d61b8Smrg ki->options = optionsdup; 20421b5d61b8Smrg KdParseKbdOptions(ki); 20431b5d61b8Smrg 20441b5d61b8Smrg if (!ki->driver) { 20451b5d61b8Smrg ErrorF("couldn't find driver for keyboard device \"%s\" (%s)\n", 20461b5d61b8Smrg ki->name ? ki->name : "(unnamed)", ki->path); 20471b5d61b8Smrg KdFreeKeyboard(ki); 20481b5d61b8Smrg return BadValue; 20491b5d61b8Smrg } 20501b5d61b8Smrg 205105b261ecSmrg if (KdAddKeyboard(ki) != Success || 20526747b715Smrg ActivateDevice(ki->dixdev, TRUE) != Success || 20536747b715Smrg EnableDevice(ki->dixdev, TRUE) != TRUE) { 20541b5d61b8Smrg ErrorF("couldn't add or enable keyboard \"%s\" (%s)\n", 20551b5d61b8Smrg ki->name ? ki->name : "(unnamed)", ki->path); 20561b5d61b8Smrg KdFreeKeyboard(ki); 205705b261ecSmrg return BadImplementation; 205805b261ecSmrg } 205905b261ecSmrg 206005b261ecSmrg *pdev = ki->dixdev; 206105b261ecSmrg } 20621b5d61b8Smrg else { 20631b5d61b8Smrg ErrorF("unrecognised device identifier: %s\n", 20641b5d61b8Smrg input_option_get_value(input_option_find(optionsdup, 20651b5d61b8Smrg "device"))); 20661b5d61b8Smrg input_option_free_list(&optionsdup); 20671b5d61b8Smrg return BadValue; 20681b5d61b8Smrg } 206905b261ecSmrg 207005b261ecSmrg return Success; 207105b261ecSmrg} 207205b261ecSmrg 207305b261ecSmrgvoid 207405b261ecSmrgDeleteInputDeviceRequest(DeviceIntPtr pDev) 207505b261ecSmrg{ 20766747b715Smrg RemoveDevice(pDev, TRUE); 207705b261ecSmrg} 20781b5d61b8Smrg 20791b5d61b8Smrgvoid 20801b5d61b8SmrgRemoveInputDeviceTraces(const char *config_info) 20811b5d61b8Smrg{ 20821b5d61b8Smrg} 2083