getevents.c revision 1b684552
105b261ecSmrg/* 205b261ecSmrg * Copyright © 2006 Nokia Corporation 305b261ecSmrg * Copyright © 2006-2007 Daniel Stone 44202a189Smrg * Copyright © 2008 Red Hat, Inc. 505b261ecSmrg * 605b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a 705b261ecSmrg * copy of this software and associated documentation files (the "Software"), 805b261ecSmrg * to deal in the Software without restriction, including without limitation 905b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1005b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the 1105b261ecSmrg * Software is furnished to do so, subject to the following conditions: 1205b261ecSmrg * 1305b261ecSmrg * The above copyright notice and this permission notice (including the next 1405b261ecSmrg * paragraph) shall be included in all copies or substantial portions of the 1505b261ecSmrg * Software. 1605b261ecSmrg * 1705b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1805b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1905b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2005b261ecSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2105b261ecSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2205b261ecSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2305b261ecSmrg * DEALINGS IN THE SOFTWARE. 2405b261ecSmrg * 254202a189Smrg * Authors: Daniel Stone <daniel@fooishbar.org> 264202a189Smrg * Peter Hutterer <peter.hutterer@who-t.net> 2705b261ecSmrg */ 2805b261ecSmrg 2905b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 3005b261ecSmrg#include <dix-config.h> 3105b261ecSmrg#endif 3205b261ecSmrg 3305b261ecSmrg#include <X11/X.h> 3405b261ecSmrg#include <X11/keysym.h> 3505b261ecSmrg#include <X11/Xproto.h> 364202a189Smrg#include <math.h> 3705b261ecSmrg 3805b261ecSmrg#include "misc.h" 3905b261ecSmrg#include "resource.h" 4005b261ecSmrg#include "inputstr.h" 4105b261ecSmrg#include "scrnintstr.h" 4205b261ecSmrg#include "cursorstr.h" 4305b261ecSmrg#include "dixstruct.h" 4405b261ecSmrg#include "globals.h" 4505b261ecSmrg#include "dixevents.h" 4605b261ecSmrg#include "mipointer.h" 474202a189Smrg#include "eventstr.h" 484202a189Smrg#include "eventconvert.h" 4905b261ecSmrg 5005b261ecSmrg#include <X11/extensions/XKBproto.h> 514202a189Smrg#include "xkbsrv.h" 5205b261ecSmrg 5305b261ecSmrg#ifdef PANORAMIX 5405b261ecSmrg#include "panoramiX.h" 5505b261ecSmrg#include "panoramiXsrv.h" 5605b261ecSmrg#endif 5705b261ecSmrg 5805b261ecSmrg#include <X11/extensions/XI.h> 5905b261ecSmrg#include <X11/extensions/XIproto.h> 604202a189Smrg#include <pixman.h> 6105b261ecSmrg#include "exglobals.h" 6205b261ecSmrg#include "exevents.h" 6305b261ecSmrg#include "exglobals.h" 6405b261ecSmrg#include "extnsionst.h" 654202a189Smrg#include "listdev.h" /* for sizing up DeviceClassesChangedEvent */ 6605b261ecSmrg 6705b261ecSmrg/* Number of motion history events to store. */ 6805b261ecSmrg#define MOTION_HISTORY_SIZE 256 6905b261ecSmrg 704642e01fSmrg/* InputEventList is the container list for all input events generated by the 714642e01fSmrg * DDX. The DDX is expected to call GetEventList() and then pass the list into 724642e01fSmrg * Get{Pointer|Keyboard}Events. 734642e01fSmrg */ 744642e01fSmrgEventListPtr InputEventList = NULL; 754642e01fSmrgint InputEventListLen = 0; 764642e01fSmrg 774202a189Smrgint 784642e01fSmrgGetEventList(EventListPtr* list) 794642e01fSmrg{ 804642e01fSmrg *list = InputEventList; 814642e01fSmrg return InputEventListLen; 824642e01fSmrg} 8305b261ecSmrg 8405b261ecSmrg/** 8505b261ecSmrg * Pick some arbitrary size for Xi motion history. 8605b261ecSmrg */ 874202a189Smrgint 8805b261ecSmrgGetMotionHistorySize(void) 8905b261ecSmrg{ 9005b261ecSmrg return MOTION_HISTORY_SIZE; 9105b261ecSmrg} 9205b261ecSmrg 934202a189Smrgvoid 944202a189Smrgset_button_down(DeviceIntPtr pDev, int button, int type) 9505b261ecSmrg{ 964202a189Smrg if (type == BUTTON_PROCESSED) 974202a189Smrg SetBit(pDev->button->down, button); 984202a189Smrg else 994202a189Smrg SetBit(pDev->button->postdown, button); 10005b261ecSmrg} 10105b261ecSmrg 1024202a189Smrgvoid 1034202a189Smrgset_button_up(DeviceIntPtr pDev, int button, int type) 10405b261ecSmrg{ 1054202a189Smrg if (type == BUTTON_PROCESSED) 1064202a189Smrg ClearBit(pDev->button->down, button); 1074202a189Smrg else 1084202a189Smrg ClearBit(pDev->button->postdown, button); 10905b261ecSmrg} 11005b261ecSmrg 1114202a189SmrgBool 1124202a189Smrgbutton_is_down(DeviceIntPtr pDev, int button, int type) 1134202a189Smrg{ 1141b684552Smrg Bool ret = FALSE; 1154202a189Smrg 1164202a189Smrg if (type & BUTTON_PROCESSED) 1171b684552Smrg ret = ret || BitIsOn(pDev->button->down, button); 1184202a189Smrg if (type & BUTTON_POSTED) 1191b684552Smrg ret = ret || BitIsOn(pDev->button->postdown, button); 1204202a189Smrg 1214202a189Smrg return ret; 1224202a189Smrg} 1234202a189Smrg 1244202a189Smrgvoid 1254202a189Smrgset_key_down(DeviceIntPtr pDev, int key_code, int type) 12605b261ecSmrg{ 1274202a189Smrg if (type == KEY_PROCESSED) 1284202a189Smrg SetBit(pDev->key->down, key_code); 1294202a189Smrg else 1304202a189Smrg SetBit(pDev->key->postdown, key_code); 1314202a189Smrg} 1324202a189Smrg 1334202a189Smrgvoid 1344202a189Smrgset_key_up(DeviceIntPtr pDev, int key_code, int type) 1354202a189Smrg{ 1364202a189Smrg if (type == KEY_PROCESSED) 1374202a189Smrg ClearBit(pDev->key->down, key_code); 1384202a189Smrg else 1394202a189Smrg ClearBit(pDev->key->postdown, key_code); 1404202a189Smrg} 1414202a189Smrg 1424202a189SmrgBool 1434202a189Smrgkey_is_down(DeviceIntPtr pDev, int key_code, int type) 1444202a189Smrg{ 1451b684552Smrg Bool ret = FALSE; 1464202a189Smrg 1474202a189Smrg if (type & KEY_PROCESSED) 1481b684552Smrg ret = ret || BitIsOn(pDev->key->down, key_code); 1494202a189Smrg if (type & KEY_POSTED) 1501b684552Smrg ret = ret || BitIsOn(pDev->key->postdown, key_code); 1514202a189Smrg 1524202a189Smrg return ret; 15305b261ecSmrg} 15405b261ecSmrg 15505b261ecSmrgstatic Bool 15605b261ecSmrgkey_autorepeats(DeviceIntPtr pDev, int key_code) 15705b261ecSmrg{ 15805b261ecSmrg return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] & 15905b261ecSmrg (1 << (key_code & 7))); 16005b261ecSmrg} 16105b261ecSmrg 1624202a189Smrgstatic void 1634202a189Smrginit_event(DeviceIntPtr dev, DeviceEvent* event, Time ms) 1644202a189Smrg{ 1654202a189Smrg memset(event, 0, sizeof(DeviceEvent)); 1664202a189Smrg event->header = ET_Internal; 1674202a189Smrg event->length = sizeof(DeviceEvent); 1684202a189Smrg event->time = ms; 1694202a189Smrg event->deviceid = dev->id; 1704202a189Smrg event->sourceid = dev->id; 1714202a189Smrg} 1724202a189Smrg 1734202a189Smrgstatic void 1744202a189Smrginit_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail) 1754202a189Smrg{ 1764202a189Smrg memset(event, 0, sizeof(RawDeviceEvent)); 1774202a189Smrg event->header = ET_Internal; 1784202a189Smrg event->length = sizeof(RawDeviceEvent); 1794202a189Smrg event->type = ET_RawKeyPress - ET_KeyPress + type; 1804202a189Smrg event->time = ms; 1814202a189Smrg event->deviceid = dev->id; 1824202a189Smrg event->sourceid = dev->id; 1834202a189Smrg event->detail.button = detail; 1844202a189Smrg} 1854202a189Smrg 1864202a189Smrgstatic void 1874202a189Smrgset_raw_valuators(RawDeviceEvent *event, int first, int num, int *valuators, int32_t* data) 1884202a189Smrg{ 1894202a189Smrg int i; 1904202a189Smrg for (i = first; i < first + num; i++) 1914202a189Smrg SetBit(event->valuators.mask, i); 1924202a189Smrg 1934202a189Smrg memcpy(&data[first], valuators, num * sizeof(uint32_t)); 1944202a189Smrg} 1954202a189Smrg 1964202a189Smrg 1974202a189Smrgstatic void 1984202a189Smrgset_valuators(DeviceIntPtr dev, DeviceEvent* event, int first_valuator, 1994202a189Smrg int num_valuators, int *valuators) 2004202a189Smrg{ 2014202a189Smrg int i; 2024202a189Smrg 2034202a189Smrg for (i = first_valuator; i < first_valuator + num_valuators; i++) 2044202a189Smrg { 2054202a189Smrg SetBit(event->valuators.mask, i); 2064202a189Smrg if (dev->valuator->mode == Absolute) 2074202a189Smrg SetBit(event->valuators.mode, i); 2084202a189Smrg event->valuators.data_frac[i] = 2094202a189Smrg dev->last.remainder[i] * (1 << 16) * (1 << 16); 2104202a189Smrg } 2114202a189Smrg 2124202a189Smrg memcpy(&event->valuators.data[first_valuator], 2131b684552Smrg valuators, num_valuators * sizeof(int32_t)); 2144202a189Smrg 2154202a189Smrg} 2164202a189Smrg 2174202a189Smrgvoid 2184202a189SmrgCreateClassesChangedEvent(EventList* event, 2194202a189Smrg DeviceIntPtr master, 2204202a189Smrg DeviceIntPtr slave, 2214202a189Smrg int type) 2224202a189Smrg{ 2234202a189Smrg int i; 2244202a189Smrg DeviceChangedEvent *dce; 2254202a189Smrg CARD32 ms = GetTimeInMillis(); 2264202a189Smrg 2274202a189Smrg dce = (DeviceChangedEvent*)event->event; 2284202a189Smrg memset(dce, 0, sizeof(DeviceChangedEvent)); 2294202a189Smrg dce->deviceid = slave->id; 2304202a189Smrg dce->masterid = master->id; 2314202a189Smrg dce->header = ET_Internal; 2324202a189Smrg dce->length = sizeof(DeviceChangedEvent); 2334202a189Smrg dce->type = ET_DeviceChanged; 2344202a189Smrg dce->time = ms; 2354202a189Smrg dce->flags = type; 2364202a189Smrg dce->flags |= DEVCHANGE_SLAVE_SWITCH; 2374202a189Smrg dce->sourceid = slave->id; 2384202a189Smrg 2394202a189Smrg if (slave->button) 2404202a189Smrg { 2414202a189Smrg dce->buttons.num_buttons = slave->button->numButtons; 2424202a189Smrg for (i = 0; i < dce->buttons.num_buttons; i++) 2434202a189Smrg dce->buttons.names[i] = slave->button->labels[i]; 2444202a189Smrg } 2454202a189Smrg if (slave->valuator) 2464202a189Smrg { 2474202a189Smrg dce->num_valuators = slave->valuator->numAxes; 2484202a189Smrg for (i = 0; i < dce->num_valuators; i++) 2494202a189Smrg { 2504202a189Smrg dce->valuators[i].min = slave->valuator->axes[i].min_value; 2514202a189Smrg dce->valuators[i].max = slave->valuator->axes[i].max_value; 2524202a189Smrg dce->valuators[i].resolution = slave->valuator->axes[i].resolution; 2534202a189Smrg /* This should, eventually, be a per-axis mode */ 2544202a189Smrg dce->valuators[i].mode = slave->valuator->mode; 2554202a189Smrg dce->valuators[i].name = slave->valuator->axes[i].label; 2564202a189Smrg } 2574202a189Smrg } 2584202a189Smrg if (slave->key) 2594202a189Smrg { 2604202a189Smrg dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code; 2614202a189Smrg dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code; 2624202a189Smrg } 2634202a189Smrg} 2644202a189Smrg 2654642e01fSmrg/** 2664642e01fSmrg * Rescale the coord between the two axis ranges. 2674642e01fSmrg */ 2684642e01fSmrgstatic int 2694202a189SmrgrescaleValuatorAxis(int coord, float remainder, float *remainder_return, AxisInfoPtr from, AxisInfoPtr to, 2704642e01fSmrg int defmax) 2714642e01fSmrg{ 2724202a189Smrg int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax, coord_return; 2734202a189Smrg float value; 2744642e01fSmrg 2754642e01fSmrg if(from && from->min_value < from->max_value) { 2764642e01fSmrg fmin = from->min_value; 2774642e01fSmrg fmax = from->max_value; 2784642e01fSmrg } 2794642e01fSmrg if(to && to->min_value < to->max_value) { 2804642e01fSmrg tmin = to->min_value; 2814642e01fSmrg tmax = to->max_value; 2824642e01fSmrg } 2834642e01fSmrg 2844202a189Smrg if(fmin == tmin && fmax == tmax) { 2854202a189Smrg if (remainder_return) 2864202a189Smrg *remainder_return = remainder; 2874642e01fSmrg return coord; 2884202a189Smrg } 2894642e01fSmrg 2904202a189Smrg if(fmax == fmin) { /* avoid division by 0 */ 2914202a189Smrg if (remainder_return) 2924202a189Smrg *remainder_return = 0.0; 2934642e01fSmrg return 0; 2944202a189Smrg } 2954642e01fSmrg 2964202a189Smrg value = (coord + remainder - fmin) * (tmax - tmin) / (fmax - fmin) + tmin; 2974202a189Smrg coord_return = lroundf(value); 2984202a189Smrg if (remainder_return) 2994202a189Smrg *remainder_return = value - coord_return; 3004202a189Smrg return coord_return; 3014642e01fSmrg} 3024642e01fSmrg 3034642e01fSmrg/** 3044642e01fSmrg * Update all coordinates when changing to a different SD 3054642e01fSmrg * to ensure that relative reporting will work as expected 3064642e01fSmrg * without loss of precision. 3074642e01fSmrg * 3084642e01fSmrg * pDev->last.valuators will be in absolute device coordinates after this 3094642e01fSmrg * function. 3104642e01fSmrg */ 3114642e01fSmrgstatic void 3124642e01fSmrgupdateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev) 3134642e01fSmrg{ 3144642e01fSmrg ScreenPtr scr = miPointerGetScreen(pDev); 3154642e01fSmrg int i; 3164642e01fSmrg DeviceIntPtr lastSlave; 3174642e01fSmrg 3184642e01fSmrg /* master->last.valuators[0]/[1] is in screen coords and the actual 3194642e01fSmrg * position of the pointer */ 3204642e01fSmrg pDev->last.valuators[0] = master->last.valuators[0]; 3214642e01fSmrg pDev->last.valuators[1] = master->last.valuators[1]; 3224642e01fSmrg 3234642e01fSmrg if (!pDev->valuator) 3244642e01fSmrg return; 3254642e01fSmrg 3264642e01fSmrg /* scale back to device coordinates */ 3274642e01fSmrg if(pDev->valuator->numAxes > 0) 3284202a189Smrg pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], pDev->last.remainder[0], 3294202a189Smrg &pDev->last.remainder[0], NULL, pDev->valuator->axes + 0, scr->width); 3304642e01fSmrg if(pDev->valuator->numAxes > 1) 3314202a189Smrg pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], pDev->last.remainder[1], 3324202a189Smrg &pDev->last.remainder[1], NULL, pDev->valuator->axes + 1, scr->height); 3334642e01fSmrg 3344642e01fSmrg /* calculate the other axis as well based on info from the old 3354642e01fSmrg * slave-device. If the old slave had less axes than this one, 3364642e01fSmrg * last.valuators is reset to 0. 3374642e01fSmrg */ 3384202a189Smrg if ((lastSlave = master->last.slave) && lastSlave->valuator) { 3394642e01fSmrg for (i = 2; i < pDev->valuator->numAxes; i++) { 3404642e01fSmrg if (i >= lastSlave->valuator->numAxes) 3414642e01fSmrg pDev->last.valuators[i] = 0; 3424642e01fSmrg else 3434642e01fSmrg pDev->last.valuators[i] = 3444642e01fSmrg rescaleValuatorAxis(pDev->last.valuators[i], 3454202a189Smrg pDev->last.remainder[i], 3464202a189Smrg &pDev->last.remainder[i], 3474642e01fSmrg lastSlave->valuator->axes + i, 3484642e01fSmrg pDev->valuator->axes + i, 0); 3494642e01fSmrg } 3504642e01fSmrg } 3514642e01fSmrg 3524642e01fSmrg} 3534642e01fSmrg 35405b261ecSmrg/** 35505b261ecSmrg * Allocate the motion history buffer. 35605b261ecSmrg */ 3574202a189Smrgvoid 35805b261ecSmrgAllocateMotionHistory(DeviceIntPtr pDev) 35905b261ecSmrg{ 3604642e01fSmrg int size; 3614202a189Smrg free(pDev->valuator->motion); 36205b261ecSmrg 36305b261ecSmrg if (pDev->valuator->numMotionEvents < 1) 36405b261ecSmrg return; 36505b261ecSmrg 3664642e01fSmrg /* An MD must have a motion history size large enough to keep all 3674642e01fSmrg * potential valuators, plus the respective range of the valuators. 3684642e01fSmrg * 3 * INT32 for (min_val, max_val, curr_val)) 3694642e01fSmrg */ 3704202a189Smrg if (IsMaster(pDev)) 3714642e01fSmrg size = sizeof(INT32) * 3 * MAX_VALUATORS; 3724642e01fSmrg else 3734642e01fSmrg size = sizeof(INT32) * pDev->valuator->numAxes; 3744642e01fSmrg 3754642e01fSmrg size += sizeof(Time); 3764642e01fSmrg 3774202a189Smrg pDev->valuator->motion = calloc(pDev->valuator->numMotionEvents, size); 37805b261ecSmrg pDev->valuator->first_motion = 0; 37905b261ecSmrg pDev->valuator->last_motion = 0; 3804642e01fSmrg if (!pDev->valuator->motion) 3814642e01fSmrg ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n", 3824642e01fSmrg pDev->name, size * pDev->valuator->numMotionEvents); 38305b261ecSmrg} 38405b261ecSmrg 38505b261ecSmrg/** 38605b261ecSmrg * Dump the motion history between start and stop into the supplied buffer. 38705b261ecSmrg * Only records the event for a given screen in theory, but in practice, we 38805b261ecSmrg * sort of ignore this. 3894642e01fSmrg * 3904642e01fSmrg * If core is set, we only generate x/y, in INT16, scaled to screen coords. 39105b261ecSmrg */ 3924202a189Smrgint 3934642e01fSmrgGetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start, 3944642e01fSmrg unsigned long stop, ScreenPtr pScreen, BOOL core) 39505b261ecSmrg{ 3964642e01fSmrg char *ibuff = NULL, *obuff; 39705b261ecSmrg int i = 0, ret = 0; 3984642e01fSmrg int j, coord; 39905b261ecSmrg Time current; 40005b261ecSmrg /* The size of a single motion event. */ 4014642e01fSmrg int size; 4024642e01fSmrg int dflt; 4034642e01fSmrg AxisInfo from, *to; /* for scaling */ 4044642e01fSmrg INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */ 4054642e01fSmrg INT16 *corebuf; 4064642e01fSmrg AxisInfo core_axis = {0}; 40705b261ecSmrg 40805b261ecSmrg if (!pDev->valuator || !pDev->valuator->numMotionEvents) 40905b261ecSmrg return 0; 41005b261ecSmrg 4114642e01fSmrg if (core && !pScreen) 4124642e01fSmrg return 0; 4134642e01fSmrg 4144202a189Smrg if (IsMaster(pDev)) 4154642e01fSmrg size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time); 4164642e01fSmrg else 4174642e01fSmrg size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); 4184642e01fSmrg 4194202a189Smrg *buff = malloc(size * pDev->valuator->numMotionEvents); 4204642e01fSmrg if (!(*buff)) 4214642e01fSmrg return 0; 4224642e01fSmrg obuff = (char *)*buff; 4234642e01fSmrg 42405b261ecSmrg for (i = pDev->valuator->first_motion; 42505b261ecSmrg i != pDev->valuator->last_motion; 42605b261ecSmrg i = (i + 1) % pDev->valuator->numMotionEvents) { 42705b261ecSmrg /* We index the input buffer by which element we're accessing, which 42805b261ecSmrg * is not monotonic, and the output buffer by how many events we've 42905b261ecSmrg * written so far. */ 43005b261ecSmrg ibuff = (char *) pDev->valuator->motion + (i * size); 43105b261ecSmrg memcpy(¤t, ibuff, sizeof(Time)); 43205b261ecSmrg 43305b261ecSmrg if (current > stop) { 43405b261ecSmrg return ret; 43505b261ecSmrg } 43605b261ecSmrg else if (current >= start) { 4374642e01fSmrg if (core) 4384642e01fSmrg { 4394642e01fSmrg memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */ 4404642e01fSmrg 4414642e01fSmrg icbuf = (INT32*)(ibuff + sizeof(Time)); 4424642e01fSmrg corebuf = (INT16*)(obuff + sizeof(Time)); 4434642e01fSmrg 4444642e01fSmrg /* fetch x coordinate + range */ 4454642e01fSmrg memcpy(&from.min_value, icbuf++, sizeof(INT32)); 4464642e01fSmrg memcpy(&from.max_value, icbuf++, sizeof(INT32)); 4474642e01fSmrg memcpy(&coord, icbuf++, sizeof(INT32)); 4484642e01fSmrg 4494642e01fSmrg /* scale to screen coords */ 4504642e01fSmrg to = &core_axis; 4514642e01fSmrg to->max_value = pScreen->width; 4524202a189Smrg coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->width); 4534642e01fSmrg 4544642e01fSmrg memcpy(corebuf, &coord, sizeof(INT16)); 4554642e01fSmrg corebuf++; 4564642e01fSmrg 4574642e01fSmrg /* fetch y coordinate + range */ 4584642e01fSmrg memcpy(&from.min_value, icbuf++, sizeof(INT32)); 4594642e01fSmrg memcpy(&from.max_value, icbuf++, sizeof(INT32)); 4604642e01fSmrg memcpy(&coord, icbuf++, sizeof(INT32)); 4614642e01fSmrg 4624642e01fSmrg to->max_value = pScreen->height; 4634202a189Smrg coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->height); 4644642e01fSmrg memcpy(corebuf, &coord, sizeof(INT16)); 4654642e01fSmrg 4664202a189Smrg } else if (IsMaster(pDev)) 4674642e01fSmrg { 4684642e01fSmrg memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */ 4694642e01fSmrg 4704642e01fSmrg ocbuf = (INT32*)(obuff + sizeof(Time)); 4714642e01fSmrg icbuf = (INT32*)(ibuff + sizeof(Time)); 4724642e01fSmrg for (j = 0; j < MAX_VALUATORS; j++) 4734642e01fSmrg { 4744642e01fSmrg if (j >= pDev->valuator->numAxes) 4754642e01fSmrg break; 4764642e01fSmrg 4774642e01fSmrg /* fetch min/max/coordinate */ 4784642e01fSmrg memcpy(&from.min_value, icbuf++, sizeof(INT32)); 4794642e01fSmrg memcpy(&from.max_value, icbuf++, sizeof(INT32)); 4804642e01fSmrg memcpy(&coord, icbuf++, sizeof(INT32)); 4814642e01fSmrg 4824642e01fSmrg to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL; 4834642e01fSmrg 4844642e01fSmrg /* x/y scaled to screen if no range is present */ 4854642e01fSmrg if (j == 0 && (from.max_value < from.min_value)) 4864642e01fSmrg from.max_value = pScreen->width; 4874642e01fSmrg else if (j == 1 && (from.max_value < from.min_value)) 4884642e01fSmrg from.max_value = pScreen->height; 4894642e01fSmrg 4904642e01fSmrg if (j == 0 && (to->max_value < to->min_value)) 4914642e01fSmrg dflt = pScreen->width; 4924642e01fSmrg else if (j == 1 && (to->max_value < to->min_value)) 4934642e01fSmrg dflt = pScreen->height; 4944642e01fSmrg else 4954642e01fSmrg dflt = 0; 4964642e01fSmrg 4974642e01fSmrg /* scale from stored range into current range */ 4984202a189Smrg coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, 0); 4994642e01fSmrg memcpy(ocbuf, &coord, sizeof(INT32)); 5004642e01fSmrg ocbuf++; 5014642e01fSmrg } 5024642e01fSmrg } else 5034642e01fSmrg memcpy(obuff, ibuff, size); 5044642e01fSmrg 5054642e01fSmrg /* don't advance by size here. size may be different to the 5064642e01fSmrg * actually written size if the MD has less valuators than MAX */ 5074642e01fSmrg if (core) 5084642e01fSmrg obuff += sizeof(INT32) + sizeof(Time); 5094642e01fSmrg else 5104642e01fSmrg obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); 51105b261ecSmrg ret++; 51205b261ecSmrg } 51305b261ecSmrg } 51405b261ecSmrg 51505b261ecSmrg return ret; 51605b261ecSmrg} 51705b261ecSmrg 51805b261ecSmrg 51905b261ecSmrg/** 52005b261ecSmrg * Update the motion history for a specific device, with the list of 52105b261ecSmrg * valuators. 5224642e01fSmrg * 5234642e01fSmrg * Layout of the history buffer: 5244642e01fSmrg * for SDs: [time] [val0] [val1] ... [valn] 5254642e01fSmrg * for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn] 5264642e01fSmrg * 5274642e01fSmrg * For events that have some valuators unset (first_valuator > 0): 5284642e01fSmrg * min_val == max_val == val == 0. 52905b261ecSmrg */ 53005b261ecSmrgstatic void 53105b261ecSmrgupdateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator, 53205b261ecSmrg int num_valuators, int *valuators) 53305b261ecSmrg{ 53405b261ecSmrg char *buff = (char *) pDev->valuator->motion; 5354642e01fSmrg ValuatorClassPtr v; 5364642e01fSmrg int i; 53705b261ecSmrg 53805b261ecSmrg if (!pDev->valuator->numMotionEvents) 53905b261ecSmrg return; 54005b261ecSmrg 5414642e01fSmrg v = pDev->valuator; 5424202a189Smrg if (IsMaster(pDev)) 5434642e01fSmrg { 5444642e01fSmrg buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) * 5454642e01fSmrg v->last_motion; 5464642e01fSmrg 5474642e01fSmrg memcpy(buff, &ms, sizeof(Time)); 5484642e01fSmrg buff += sizeof(Time); 5494642e01fSmrg 5504642e01fSmrg memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS); 5514642e01fSmrg buff += 3 * sizeof(INT32) * first_valuator; 5524642e01fSmrg 5534642e01fSmrg for (i = first_valuator; i < first_valuator + num_valuators; i++) 5544642e01fSmrg { 5554642e01fSmrg if (i >= v->numAxes) 5564642e01fSmrg break; 5574642e01fSmrg memcpy(buff, &v->axes[i].min_value, sizeof(INT32)); 5584642e01fSmrg buff += sizeof(INT32); 5594642e01fSmrg memcpy(buff, &v->axes[i].max_value, sizeof(INT32)); 5604642e01fSmrg buff += sizeof(INT32); 5614642e01fSmrg memcpy(buff, &valuators[i - first_valuator], sizeof(INT32)); 5624642e01fSmrg buff += sizeof(INT32); 5634642e01fSmrg } 5644642e01fSmrg } else 5654642e01fSmrg { 5664642e01fSmrg 5674642e01fSmrg buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) * 56805b261ecSmrg pDev->valuator->last_motion; 56905b261ecSmrg 5704642e01fSmrg memcpy(buff, &ms, sizeof(Time)); 5714642e01fSmrg buff += sizeof(Time); 57205b261ecSmrg 5734642e01fSmrg memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes); 5744642e01fSmrg buff += sizeof(INT32) * first_valuator; 57505b261ecSmrg 5764642e01fSmrg memcpy(buff, valuators, sizeof(INT32) * num_valuators); 5774642e01fSmrg } 57805b261ecSmrg 5794642e01fSmrg pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) % 5804642e01fSmrg pDev->valuator->numMotionEvents; 58105b261ecSmrg /* If we're wrapping around, just keep the circular buffer going. */ 58205b261ecSmrg if (pDev->valuator->first_motion == pDev->valuator->last_motion) 58305b261ecSmrg pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) % 58405b261ecSmrg pDev->valuator->numMotionEvents; 58505b261ecSmrg 58605b261ecSmrg return; 58705b261ecSmrg} 58805b261ecSmrg 58905b261ecSmrg 59005b261ecSmrg/** 59105b261ecSmrg * Returns the maximum number of events GetKeyboardEvents, 59205b261ecSmrg * GetKeyboardValuatorEvents, and GetPointerEvents will ever return. 59305b261ecSmrg * 5944642e01fSmrg * This MUST be absolutely constant, from init until exit. 59505b261ecSmrg */ 5964202a189Smrgint 59705b261ecSmrgGetMaximumEventsNum(void) { 5984202a189Smrg /* One raw event 5994202a189Smrg * One device event 6004202a189Smrg * One possible device changed event 6014202a189Smrg */ 6024202a189Smrg return 3; 60305b261ecSmrg} 60405b261ecSmrg 60505b261ecSmrg 60605b261ecSmrg/** 60705b261ecSmrg * Clip an axis to its bounds, which are declared in the call to 60805b261ecSmrg * InitValuatorAxisClassStruct. 60905b261ecSmrg */ 61005b261ecSmrgstatic void 61105b261ecSmrgclipAxis(DeviceIntPtr pDev, int axisNum, int *val) 61205b261ecSmrg{ 6134202a189Smrg AxisInfoPtr axis; 6144202a189Smrg 6154202a189Smrg if (axisNum >= pDev->valuator->numAxes) 6164202a189Smrg return; 6174202a189Smrg 6184202a189Smrg axis = pDev->valuator->axes + axisNum; 6194642e01fSmrg 6204642e01fSmrg /* If a value range is defined, clip. If not, do nothing */ 6214642e01fSmrg if (axis->max_value <= axis->min_value) 6224642e01fSmrg return; 6234642e01fSmrg 6244642e01fSmrg if (*val < axis->min_value) 6254642e01fSmrg *val = axis->min_value; 6264642e01fSmrg if (*val > axis->max_value) 6274642e01fSmrg *val = axis->max_value; 62805b261ecSmrg} 62905b261ecSmrg 63005b261ecSmrg/** 63105b261ecSmrg * Clip every axis in the list of valuators to its bounds. 63205b261ecSmrg */ 63305b261ecSmrgstatic void 63405b261ecSmrgclipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators, 63505b261ecSmrg int *valuators) 63605b261ecSmrg{ 63705b261ecSmrg int i; 63805b261ecSmrg 6394202a189Smrg for (i = 0; i < num_valuators; i++) 64005b261ecSmrg clipAxis(pDev, i + first_valuator, &(valuators[i])); 64105b261ecSmrg} 64205b261ecSmrg 6434642e01fSmrg/** 6444642e01fSmrg * Create the DCCE event (does not update the master's device state yet, this 6454642e01fSmrg * is done in the event processing). 6464642e01fSmrg * Pull in the coordinates from the MD if necessary. 6474642e01fSmrg * 6484642e01fSmrg * @param events Pointer to a pre-allocated event list. 6494642e01fSmrg * @param dev The slave device that generated an event. 6504202a189Smrg * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT 6514642e01fSmrg * @param num_events The current number of events, returns the number of 6524642e01fSmrg * events if a DCCE was generated. 6534642e01fSmrg * @return The updated @events pointer. 6544642e01fSmrg */ 6554202a189SmrgEventListPtr 6564202a189SmrgUpdateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events) 6574642e01fSmrg{ 6584202a189Smrg DeviceIntPtr master; 6594202a189Smrg 6604202a189Smrg master = GetMaster(dev, (type & DEVCHANGE_POINTER_EVENT) ? MASTER_POINTER : MASTER_KEYBOARD); 6614202a189Smrg 6624202a189Smrg if (master && master->last.slave != dev) 6634642e01fSmrg { 6644202a189Smrg CreateClassesChangedEvent(events, master, dev, type); 6654202a189Smrg if (IsPointerDevice(master)) 6664202a189Smrg { 6674202a189Smrg updateSlaveDeviceCoords(master, dev); 6684202a189Smrg master->last.numValuators = dev->last.numValuators; 6694202a189Smrg } 6704202a189Smrg master->last.slave = dev; 6714202a189Smrg (*num_events)++; 6724202a189Smrg events++; 6734642e01fSmrg } 6744642e01fSmrg return events; 6754642e01fSmrg} 6764642e01fSmrg 6774642e01fSmrg/** 6784642e01fSmrg * Move the device's pointer to the position given in the valuators. 6794642e01fSmrg * 6804642e01fSmrg * @param dev The device which's pointer is to be moved. 6814642e01fSmrg * @param x Returns the x position of the pointer after the move. 6824642e01fSmrg * @param y Returns the y position of the pointer after the move. 6834642e01fSmrg * @param first The first valuator in @valuators 6844642e01fSmrg * @param num Total number of valuators in @valuators. 6854642e01fSmrg * @param valuators Valuator data for each axis between @first and 6864642e01fSmrg * @first+@num. 6874642e01fSmrg */ 6884642e01fSmrgstatic void 6894642e01fSmrgmoveAbsolute(DeviceIntPtr dev, int *x, int *y, 6904642e01fSmrg int first, int num, int *valuators) 6914642e01fSmrg{ 6924642e01fSmrg int i; 6934642e01fSmrg 6944642e01fSmrg 6954642e01fSmrg if (num >= 1 && first == 0) 6964642e01fSmrg *x = *(valuators + 0); 6974642e01fSmrg else 6984642e01fSmrg *x = dev->last.valuators[0]; 6994642e01fSmrg 7004642e01fSmrg if (first <= 1 && num >= (2 - first)) 7014642e01fSmrg *y = *(valuators + 1 - first); 7024642e01fSmrg else 7034642e01fSmrg *y = dev->last.valuators[1]; 7044642e01fSmrg 7054642e01fSmrg clipAxis(dev, 0, x); 7064642e01fSmrg clipAxis(dev, 1, y); 7074642e01fSmrg 7084642e01fSmrg i = (first > 2) ? 0 : 2; 7094642e01fSmrg for (; i < num; i++) 7104642e01fSmrg { 7114642e01fSmrg dev->last.valuators[i + first] = valuators[i]; 7124642e01fSmrg clipAxis(dev, i, &dev->last.valuators[i + first]); 7134642e01fSmrg } 7144642e01fSmrg} 7154642e01fSmrg 7164642e01fSmrg/** 7174642e01fSmrg * Move the device's pointer by the values given in @valuators. 7184642e01fSmrg * 7194642e01fSmrg * @param dev The device which's pointer is to be moved. 7204642e01fSmrg * @param x Returns the x position of the pointer after the move. 7214642e01fSmrg * @param y Returns the y position of the pointer after the move. 7224642e01fSmrg * @param first The first valuator in @valuators 7234642e01fSmrg * @param num Total number of valuators in @valuators. 7244642e01fSmrg * @param valuators Valuator data for each axis between @first and 7254642e01fSmrg * @first+@num. 7264642e01fSmrg */ 7274642e01fSmrgstatic void 7284642e01fSmrgmoveRelative(DeviceIntPtr dev, int *x, int *y, 7294642e01fSmrg int first, int num, int *valuators) 7304642e01fSmrg{ 7314642e01fSmrg int i; 7324642e01fSmrg 7334642e01fSmrg *x = dev->last.valuators[0]; 7344642e01fSmrg *y = dev->last.valuators[1]; 7354642e01fSmrg 7364642e01fSmrg if (num >= 1 && first == 0) 7374642e01fSmrg *x += *(valuators +0); 7384642e01fSmrg 7394642e01fSmrg if (first <= 1 && num >= (2 - first)) 7404642e01fSmrg *y += *(valuators + 1 - first); 7414642e01fSmrg 7424642e01fSmrg /* if attached, clip both x and y to the defined limits (usually 7434642e01fSmrg * co-ord space limit). If it is attached, we need x/y to go over the 7444642e01fSmrg * limits to be able to change screens. */ 7454202a189Smrg if(dev->u.master && dev->valuator->mode == Absolute) { 7464642e01fSmrg clipAxis(dev, 0, x); 7474642e01fSmrg clipAxis(dev, 1, y); 7484642e01fSmrg } 7494642e01fSmrg 7504642e01fSmrg /* calc other axes, clip, drop back into valuators */ 7514642e01fSmrg i = (first > 2) ? 0 : 2; 7524642e01fSmrg for (; i < num; i++) 7534642e01fSmrg { 7544642e01fSmrg dev->last.valuators[i + first] += valuators[i]; 7554202a189Smrg if (dev->valuator->mode == Absolute) 7564202a189Smrg clipAxis(dev, i, &dev->last.valuators[i + first]); 7574642e01fSmrg valuators[i] = dev->last.valuators[i + first]; 7584642e01fSmrg } 7594642e01fSmrg} 7604642e01fSmrg 7614642e01fSmrg/** 7624642e01fSmrg * Accelerate the data in valuators based on the device's acceleration scheme. 7634642e01fSmrg * 7644642e01fSmrg * @param dev The device which's pointer is to be moved. 7654642e01fSmrg * @param first The first valuator in @valuators 7664642e01fSmrg * @param num Total number of valuators in @valuators. 7674642e01fSmrg * @param valuators Valuator data for each axis between @first and 7684642e01fSmrg * @first+@num. 7694642e01fSmrg * @param ms Current time. 7704642e01fSmrg */ 7714642e01fSmrgstatic void 7724642e01fSmrgaccelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms) 7734642e01fSmrg{ 7744642e01fSmrg if (dev->valuator->accelScheme.AccelSchemeProc) 7754642e01fSmrg dev->valuator->accelScheme.AccelSchemeProc(dev, first, num, valuators, ms); 7764642e01fSmrg} 7774642e01fSmrg 7784642e01fSmrg/** 7794642e01fSmrg * If we have HW cursors, this actually moves the visible sprite. If not, we 7804642e01fSmrg * just do all the screen crossing, etc. 7814642e01fSmrg * 7824642e01fSmrg * We scale from device to screen coordinates here, call 7834642e01fSmrg * miPointerSetPosition() and then scale back into device coordinates (if 7844642e01fSmrg * needed). miPSP will change x/y if the screen was crossed. 7854642e01fSmrg * 7864642e01fSmrg * @param dev The device to be moved. 7874642e01fSmrg * @param x Pointer to current x-axis value, may be modified. 7884642e01fSmrg * @param y Pointer to current y-axis value, may be modified. 7894202a189Smrg * @param x_frac Fractional part of current x-axis value, may be modified. 7904202a189Smrg * @param y_frac Fractional part of current y-axis value, may be modified. 7914642e01fSmrg * @param scr Screen the device's sprite is currently on. 7924642e01fSmrg * @param screenx Screen x coordinate the sprite is on after the update. 7934642e01fSmrg * @param screeny Screen y coordinate the sprite is on after the update. 7944202a189Smrg * @param screenx_frac Fractional part of screen x coordinate, as above. 7954202a189Smrg * @param screeny_frac Fractional part of screen y coordinate, as above. 7964642e01fSmrg */ 7974642e01fSmrgstatic void 7984202a189SmrgpositionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac, 7994202a189Smrg ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac) 8004642e01fSmrg{ 8014202a189Smrg int old_screenx, old_screeny; 8024202a189Smrg 8034642e01fSmrg /* scale x&y to screen */ 8044202a189Smrg if (dev->valuator->numAxes > 0) { 8054202a189Smrg *screenx = rescaleValuatorAxis(*x, x_frac, screenx_frac, 8064202a189Smrg dev->valuator->axes + 0, NULL, scr->width); 8074202a189Smrg } else { 8084202a189Smrg *screenx = dev->last.valuators[0]; 8094202a189Smrg *screenx_frac = dev->last.remainder[0]; 8104202a189Smrg } 8114202a189Smrg 8124202a189Smrg if (dev->valuator->numAxes > 1) { 8134202a189Smrg *screeny = rescaleValuatorAxis(*y, y_frac, screeny_frac, 8144202a189Smrg dev->valuator->axes + 1, NULL, scr->height); 8154202a189Smrg } else { 8164202a189Smrg *screeny = dev->last.valuators[1]; 8174202a189Smrg *screeny_frac = dev->last.remainder[1]; 8184202a189Smrg } 8194202a189Smrg 8204202a189Smrg /* Hit the left screen edge? */ 8214202a189Smrg if (*screenx <= 0 && *screenx_frac < 0.0f) 8224202a189Smrg { 8234202a189Smrg *screenx_frac = 0.0f; 8244202a189Smrg x_frac = 0.0f; 8254202a189Smrg } 8264202a189Smrg if (*screeny <= 0 && *screeny_frac < 0.0f) 8274202a189Smrg { 8284202a189Smrg *screeny_frac = 0.0f; 8294202a189Smrg y_frac = 0.0f; 8304202a189Smrg } 8314202a189Smrg 8324642e01fSmrg 8334202a189Smrg old_screenx = *screenx; 8344202a189Smrg old_screeny = *screeny; 8354642e01fSmrg /* This takes care of crossing screens for us, as well as clipping 8364642e01fSmrg * to the current screen. */ 8374202a189Smrg miPointerSetPosition(dev, screenx, screeny); 8384642e01fSmrg 8394202a189Smrg if (dev->u.master) { 8404202a189Smrg dev->u.master->last.valuators[0] = *screenx; 8414202a189Smrg dev->u.master->last.valuators[1] = *screeny; 8424202a189Smrg dev->u.master->last.remainder[0] = *screenx_frac; 8434202a189Smrg dev->u.master->last.remainder[1] = *screeny_frac; 8444642e01fSmrg } 8454642e01fSmrg 8464642e01fSmrg /* Crossed screen? Scale back to device coordiantes */ 8474202a189Smrg if(*screenx != old_screenx) 8484642e01fSmrg { 8494642e01fSmrg scr = miPointerGetScreen(dev); 8504202a189Smrg *x = rescaleValuatorAxis(*screenx, *screenx_frac, &x_frac, NULL, 8514642e01fSmrg dev->valuator->axes + 0, scr->width); 8524642e01fSmrg } 8534202a189Smrg if(*screeny != old_screeny) 8544642e01fSmrg { 8554642e01fSmrg scr = miPointerGetScreen(dev); 8564202a189Smrg *y = rescaleValuatorAxis(*screeny, *screeny_frac, &y_frac, NULL, 8574642e01fSmrg dev->valuator->axes + 1, scr->height); 8584642e01fSmrg } 8594642e01fSmrg 8604642e01fSmrg /* dropy x/y (device coordinates) back into valuators for next event */ 8614642e01fSmrg dev->last.valuators[0] = *x; 8624642e01fSmrg dev->last.valuators[1] = *y; 8634202a189Smrg dev->last.remainder[0] = x_frac; 8644202a189Smrg dev->last.remainder[1] = y_frac; 8654642e01fSmrg} 8664642e01fSmrg 8674642e01fSmrg/** 8684642e01fSmrg * Update the motion history for the device and (if appropriate) for its 8694642e01fSmrg * master device. 8704642e01fSmrg * @param dev Slave device to update. 8714642e01fSmrg * @param first First valuator to append to history. 8724642e01fSmrg * @param num Total number of valuators to append to history. 8734642e01fSmrg * @param ms Current time 8744642e01fSmrg */ 8754642e01fSmrgstatic void 8764642e01fSmrgupdateHistory(DeviceIntPtr dev, int first, int num, CARD32 ms) 8774642e01fSmrg{ 8784642e01fSmrg updateMotionHistory(dev, ms, first, num, &dev->last.valuators[first]); 8794642e01fSmrg if (dev->u.master) 8804202a189Smrg { 8814202a189Smrg DeviceIntPtr master = GetMaster(dev, MASTER_POINTER); 8824202a189Smrg updateMotionHistory(master, ms, first, num, &dev->last.valuators[first]); 8834202a189Smrg } 8844642e01fSmrg} 88505b261ecSmrg 88605b261ecSmrg/** 88705b261ecSmrg * Convenience wrapper around GetKeyboardValuatorEvents, that takes no 88805b261ecSmrg * valuators. 88905b261ecSmrg */ 8904202a189Smrgint 8914642e01fSmrgGetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) { 89205b261ecSmrg return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL); 89305b261ecSmrg} 89405b261ecSmrg 89505b261ecSmrg 89605b261ecSmrg/** 89705b261ecSmrg * Returns a set of keyboard events for KeyPress/KeyRelease, optionally 89805b261ecSmrg * also with valuator events. Handles Xi and XKB. 89905b261ecSmrg * 9004642e01fSmrg * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the 9014642e01fSmrg * event (ProcessOtherEvent). 9024642e01fSmrg * 90305b261ecSmrg * events is not NULL-terminated; the return value is the number of events. 90405b261ecSmrg * The DDX is responsible for allocating the event structure in the first 90505b261ecSmrg * place via GetMaximumEventsNum(), and for freeing it. 90605b261ecSmrg * 90705b261ecSmrg * This function does not change the core keymap to that of the device; 90805b261ecSmrg * that is done by SwitchCoreKeyboard, which is called from 90905b261ecSmrg * mieqProcessInputEvents. If replacing that function, take care to call 91005b261ecSmrg * SetCoreKeyboard before processInputProc, so keymaps are altered to suit. 91105b261ecSmrg */ 9124202a189Smrgint 9134642e01fSmrgGetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, 91405b261ecSmrg int key_code, int first_valuator, 9154202a189Smrg int num_valuators, int *valuators_in) { 9164202a189Smrg int num_events = 0; 91705b261ecSmrg CARD32 ms = 0; 9184202a189Smrg DeviceEvent *event; 9194202a189Smrg RawDeviceEvent *raw; 9204202a189Smrg int valuators[MAX_VALUATORS]; 9214202a189Smrg 9224202a189Smrg /* refuse events from disabled devices */ 9234202a189Smrg if (!pDev->enabled) 9244202a189Smrg return 0; 92505b261ecSmrg 9264642e01fSmrg if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed || 9274202a189Smrg num_valuators > MAX_VALUATORS || 9284642e01fSmrg (type != KeyPress && type != KeyRelease) || 9294642e01fSmrg (key_code < 8 || key_code > 255)) 93005b261ecSmrg return 0; 93105b261ecSmrg 9324202a189Smrg num_events = 1; 93305b261ecSmrg 9344202a189Smrg events = UpdateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events); 93505b261ecSmrg 9364202a189Smrg /* Handle core repeating, via press/release/press/release. */ 9374202a189Smrg if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) { 93805b261ecSmrg /* If autorepeating is disabled either globally or just for that key, 93905b261ecSmrg * or we have a modifier, don't generate a repeat event. */ 94005b261ecSmrg if (!pDev->kbdfeed->ctrl.autoRepeat || 94105b261ecSmrg !key_autorepeats(pDev, key_code) || 9424202a189Smrg pDev->key->xkbInfo->desc->map->modmap[key_code]) 94305b261ecSmrg return 0; 94405b261ecSmrg } 94505b261ecSmrg 94605b261ecSmrg ms = GetTimeInMillis(); 94705b261ecSmrg 9484202a189Smrg raw = (RawDeviceEvent*)events->event; 9494202a189Smrg events++; 9504202a189Smrg num_events++; 9514202a189Smrg 9524202a189Smrg memcpy(valuators, valuators_in, num_valuators * sizeof(int)); 9534202a189Smrg 9544202a189Smrg init_raw(pDev, raw, ms, type, key_code); 9554202a189Smrg set_raw_valuators(raw, first_valuator, num_valuators, valuators, 9564202a189Smrg raw->valuators.data_raw); 9574202a189Smrg 9584202a189Smrg if (num_valuators) 9594202a189Smrg clipValuators(pDev, first_valuator, num_valuators, valuators); 9604202a189Smrg 9614202a189Smrg set_raw_valuators(raw, first_valuator, num_valuators, valuators, 9624202a189Smrg raw->valuators.data); 9634202a189Smrg 9644202a189Smrg event = (DeviceEvent*) events->event; 9654202a189Smrg init_event(pDev, event, ms); 9664202a189Smrg event->detail.key = key_code; 9674202a189Smrg 96805b261ecSmrg if (type == KeyPress) { 9694202a189Smrg event->type = ET_KeyPress; 9704202a189Smrg set_key_down(pDev, key_code, KEY_POSTED); 97105b261ecSmrg } 97205b261ecSmrg else if (type == KeyRelease) { 9734202a189Smrg event->type = ET_KeyRelease; 9744202a189Smrg set_key_up(pDev, key_code, KEY_POSTED); 97505b261ecSmrg } 97605b261ecSmrg 9774202a189Smrg if (num_valuators) 97805b261ecSmrg clipValuators(pDev, first_valuator, num_valuators, valuators); 97905b261ecSmrg 9804202a189Smrg set_valuators(pDev, event, first_valuator, num_valuators, valuators); 9814202a189Smrg 9824202a189Smrg return num_events; 98305b261ecSmrg} 98405b261ecSmrg 9854642e01fSmrg/** 9864642e01fSmrg * Initialize an event list and fill with 32 byte sized events. 9874642e01fSmrg * This event list is to be passed into GetPointerEvents() and 9884642e01fSmrg * GetKeyboardEvents(). 9894642e01fSmrg * 9904642e01fSmrg * @param num_events Number of elements in list. 9914642e01fSmrg */ 9924642e01fSmrgEventListPtr 9934642e01fSmrgInitEventList(int num_events) 9944642e01fSmrg{ 9954642e01fSmrg EventListPtr events; 9964642e01fSmrg int i; 9974642e01fSmrg 9984202a189Smrg events = (EventListPtr)calloc(num_events, sizeof(EventList)); 9994642e01fSmrg if (!events) 10004642e01fSmrg return NULL; 10014642e01fSmrg 10024642e01fSmrg for (i = 0; i < num_events; i++) 10034642e01fSmrg { 10044202a189Smrg events[i].evlen = sizeof(InternalEvent); 10054202a189Smrg events[i].event = calloc(1, sizeof(InternalEvent)); 10064642e01fSmrg if (!events[i].event) 10074642e01fSmrg { 10084642e01fSmrg /* rollback */ 10094642e01fSmrg while(i--) 10104202a189Smrg free(events[i].event); 10114202a189Smrg free(events); 10124642e01fSmrg events = NULL; 10134642e01fSmrg break; 10144642e01fSmrg } 10154642e01fSmrg } 10164642e01fSmrg 10174642e01fSmrg return events; 10184642e01fSmrg} 10194642e01fSmrg 10204642e01fSmrg/** 10214642e01fSmrg * Free an event list. 10224642e01fSmrg * 10234642e01fSmrg * @param list The list to be freed. 10244642e01fSmrg * @param num_events Number of elements in list. 10254642e01fSmrg */ 10264202a189Smrgvoid 10274642e01fSmrgFreeEventList(EventListPtr list, int num_events) 10284642e01fSmrg{ 10294642e01fSmrg if (!list) 10304642e01fSmrg return; 10314642e01fSmrg while(num_events--) 10324202a189Smrg free(list[num_events].event); 10334202a189Smrg free(list); 10344202a189Smrg} 10354202a189Smrg 10364202a189Smrgstatic void 10371b684552SmrgtransformAbsolute(DeviceIntPtr dev, int first, int num, int *valuators) 10384202a189Smrg{ 10391b684552Smrg struct pixman_f_vector p = { .v = {0.0, 0.0, 1.0} }; 10404202a189Smrg 10414202a189Smrg /* p' = M * p in homogeneous coordinates */ 10421b684552Smrg if (num >= 1 && first == 0) 10431b684552Smrg p.v[0] = *(valuators + 0); 10441b684552Smrg 10451b684552Smrg if (first <= 1 && num >= (2 - first)) 10461b684552Smrg p.v[1] = *(valuators + 1 - first); 10474202a189Smrg 10484202a189Smrg pixman_f_transform_point(&dev->transform, &p); 10494202a189Smrg 10501b684552Smrg valuators[0] = lround(p.v[0]); 10511b684552Smrg valuators[1] = lround(p.v[1]); 10524642e01fSmrg} 105305b261ecSmrg 105405b261ecSmrg/** 10554642e01fSmrg * Generate a series of xEvents (filled into the EventList) representing 10564642e01fSmrg * pointer motion, or button presses. Xi and XKB-aware. 10574642e01fSmrg * 10584642e01fSmrg * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the 10594642e01fSmrg * event (ProcessOtherEvent). 106005b261ecSmrg * 106105b261ecSmrg * events is not NULL-terminated; the return value is the number of events. 106205b261ecSmrg * The DDX is responsible for allocating the event structure in the first 10634642e01fSmrg * place via InitEventList() and GetMaximumEventsNum(), and for freeing it. 10644642e01fSmrg * 10654642e01fSmrg * In the generated events rootX/Y will be in absolute screen coords and 10664642e01fSmrg * the valuator information in the absolute or relative device coords. 10674642e01fSmrg * 10684642e01fSmrg * last.valuators[x] of the device is always in absolute device coords. 10694642e01fSmrg * last.valuators[x] of the master device is in absolute screen coords. 10704642e01fSmrg * 10714642e01fSmrg * master->last.valuators[x] for x > 2 is undefined. 107205b261ecSmrg */ 10734202a189Smrgint 10744642e01fSmrgGetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, 107505b261ecSmrg int flags, int first_valuator, int num_valuators, 10764202a189Smrg int *valuators_in) { 10774642e01fSmrg int num_events = 1; 10784642e01fSmrg CARD32 ms; 10794202a189Smrg DeviceEvent *event; 10804202a189Smrg RawDeviceEvent *raw; 10814202a189Smrg int x = 0, y = 0, /* device coords */ 10824642e01fSmrg cx, cy; /* only screen coordinates */ 10834202a189Smrg float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac; 108405b261ecSmrg ScreenPtr scr = miPointerGetScreen(pDev); 10854202a189Smrg int valuators[MAX_VALUATORS]; 10864202a189Smrg 10874202a189Smrg /* refuse events from disabled devices */ 10884202a189Smrg if (!pDev->enabled) 10894202a189Smrg return 0; 109005b261ecSmrg 10914642e01fSmrg ms = GetTimeInMillis(); /* before pointer update to help precision */ 109205b261ecSmrg 10934642e01fSmrg if (!scr || !pDev->valuator || first_valuator < 0 || 10944202a189Smrg num_valuators > MAX_VALUATORS || 10954642e01fSmrg ((num_valuators + first_valuator) > pDev->valuator->numAxes) || 10964642e01fSmrg (type != MotionNotify && type != ButtonPress && type != ButtonRelease) || 10974642e01fSmrg (type != MotionNotify && !pDev->button) || 10984202a189Smrg ((type == ButtonPress || type == ButtonRelease) && !buttons) || 10994642e01fSmrg (type == MotionNotify && num_valuators <= 0)) 110005b261ecSmrg return 0; 110105b261ecSmrg 11024202a189Smrg events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); 11034202a189Smrg 11044202a189Smrg raw = (RawDeviceEvent*)events->event; 11054202a189Smrg events++; 11064202a189Smrg num_events++; 110705b261ecSmrg 11084202a189Smrg memcpy(valuators, valuators_in, num_valuators * sizeof(int)); 11094202a189Smrg 11104202a189Smrg init_raw(pDev, raw, ms, type, buttons); 11114202a189Smrg set_raw_valuators(raw, first_valuator, num_valuators, valuators, 11124202a189Smrg raw->valuators.data_raw); 111305b261ecSmrg 11144642e01fSmrg if (flags & POINTER_ABSOLUTE) 11154642e01fSmrg { 11164642e01fSmrg if (flags & POINTER_SCREEN) /* valuators are in screen coords */ 11174642e01fSmrg { 111805b261ecSmrg 11194202a189Smrg if (num_valuators >= 1 && first_valuator == 0) 11204202a189Smrg valuators[0] = rescaleValuatorAxis(valuators[0], 0.0, &x_frac, NULL, 11214202a189Smrg pDev->valuator->axes + 0, 11224202a189Smrg scr->width); 11234202a189Smrg if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) 11244202a189Smrg valuators[1 - first_valuator] = rescaleValuatorAxis(valuators[1 - first_valuator], 0.0, &y_frac, NULL, 11254202a189Smrg pDev->valuator->axes + 1, 11264202a189Smrg scr->height); 112705b261ecSmrg } 112805b261ecSmrg 11291b684552Smrg transformAbsolute(pDev, first_valuator, num_valuators, valuators); 11304642e01fSmrg moveAbsolute(pDev, &x, &y, first_valuator, num_valuators, valuators); 11314642e01fSmrg } else { 11324202a189Smrg if (flags & POINTER_ACCELERATE) { 11334642e01fSmrg accelPointer(pDev, first_valuator, num_valuators, valuators, ms); 11344202a189Smrg /* The pointer acceleration code modifies the fractional part 11354202a189Smrg * in-place, so we need to extract this information first */ 11364202a189Smrg x_frac = pDev->last.remainder[0]; 11374202a189Smrg y_frac = pDev->last.remainder[1]; 11384202a189Smrg } 11394642e01fSmrg moveRelative(pDev, &x, &y, first_valuator, num_valuators, valuators); 114005b261ecSmrg } 114105b261ecSmrg 11424202a189Smrg set_raw_valuators(raw, first_valuator, num_valuators, valuators, 11434202a189Smrg raw->valuators.data); 114405b261ecSmrg 11454202a189Smrg positionSprite(pDev, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac); 11464202a189Smrg updateHistory(pDev, first_valuator, num_valuators, ms); 114705b261ecSmrg 11484642e01fSmrg /* Update the valuators with the true value sent to the client*/ 11494642e01fSmrg if (num_valuators >= 1 && first_valuator == 0) 11504642e01fSmrg valuators[0] = x; 115105b261ecSmrg if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) 11524642e01fSmrg valuators[1 - first_valuator] = y; 115305b261ecSmrg 11544202a189Smrg if (num_valuators) 11554202a189Smrg clipValuators(pDev, first_valuator, num_valuators, valuators); 11564202a189Smrg 11574202a189Smrg event = (DeviceEvent*) events->event; 11584202a189Smrg init_event(pDev, event, ms); 115905b261ecSmrg 11604642e01fSmrg if (type == MotionNotify) { 11614202a189Smrg event->type = ET_Motion; 11624202a189Smrg event->detail.button = 0; 11634642e01fSmrg } 11644642e01fSmrg else { 11654202a189Smrg if (type == ButtonPress) { 11664202a189Smrg event->type = ET_ButtonPress; 11674202a189Smrg set_button_down(pDev, buttons, BUTTON_POSTED); 11684202a189Smrg } 11694202a189Smrg else if (type == ButtonRelease) { 11704202a189Smrg event->type = ET_ButtonRelease; 11714202a189Smrg set_button_up(pDev, buttons, BUTTON_POSTED); 11724202a189Smrg } 11734202a189Smrg event->detail.button = buttons; 11744642e01fSmrg } 117505b261ecSmrg 11764202a189Smrg event->root_x = cx; /* root_x/y always in screen coords */ 11774202a189Smrg event->root_y = cy; 11784202a189Smrg event->root_x_frac = cx_frac; 11794202a189Smrg event->root_y_frac = cy_frac; 118005b261ecSmrg 11814202a189Smrg set_valuators(pDev, event, first_valuator, num_valuators, valuators); 118205b261ecSmrg 118305b261ecSmrg return num_events; 118405b261ecSmrg} 118505b261ecSmrg 118605b261ecSmrg 118705b261ecSmrg/** 118805b261ecSmrg * Post ProximityIn/ProximityOut events, accompanied by valuators. 118905b261ecSmrg * 119005b261ecSmrg * events is not NULL-terminated; the return value is the number of events. 119105b261ecSmrg * The DDX is responsible for allocating the event structure in the first 119205b261ecSmrg * place via GetMaximumEventsNum(), and for freeing it. 119305b261ecSmrg */ 11944202a189Smrgint 11954642e01fSmrgGetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, 11964202a189Smrg int first_valuator, int num_valuators, int *valuators_in) 119705b261ecSmrg{ 119805b261ecSmrg int num_events = 1; 11994202a189Smrg DeviceEvent *event; 12004202a189Smrg int valuators[MAX_VALUATORS]; 12014202a189Smrg 12024202a189Smrg /* refuse events from disabled devices */ 12034202a189Smrg if (!pDev->enabled) 12044202a189Smrg return 0; 120505b261ecSmrg 120605b261ecSmrg /* Sanity checks. */ 120705b261ecSmrg if (type != ProximityIn && type != ProximityOut) 120805b261ecSmrg return 0; 120905b261ecSmrg if (!pDev->valuator) 121005b261ecSmrg return 0; 121105b261ecSmrg /* Do we need to send a DeviceValuator event? */ 121205b261ecSmrg if ((pDev->valuator->mode & 1) == Relative) 121305b261ecSmrg num_valuators = 0; 121405b261ecSmrg 121505b261ecSmrg /* You fail. */ 12164202a189Smrg if (first_valuator < 0 || num_valuators > MAX_VALUATORS || 121705b261ecSmrg (num_valuators + first_valuator) > pDev->valuator->numAxes) 121805b261ecSmrg return 0; 121905b261ecSmrg 12204202a189Smrg events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); 12214642e01fSmrg 12224202a189Smrg event = (DeviceEvent *) events->event; 12234202a189Smrg init_event(pDev, event, GetTimeInMillis()); 12244202a189Smrg event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut; 122505b261ecSmrg 122605b261ecSmrg if (num_valuators) { 12274202a189Smrg memcpy(valuators, valuators_in, num_valuators * sizeof(int)); 122805b261ecSmrg clipValuators(pDev, first_valuator, num_valuators, valuators); 122905b261ecSmrg } 123005b261ecSmrg 12314202a189Smrg set_valuators(pDev, event, first_valuator, num_valuators, valuators); 12324202a189Smrg 123305b261ecSmrg return num_events; 123405b261ecSmrg} 123505b261ecSmrg 123605b261ecSmrg/** 123705b261ecSmrg * Synthesize a single motion event for the core pointer. 123805b261ecSmrg * 123905b261ecSmrg * Used in cursor functions, e.g. when cursor confinement changes, and we need 124005b261ecSmrg * to shift the pointer to get it inside the new bounds. 124105b261ecSmrg */ 124205b261ecSmrgvoid 12434642e01fSmrgPostSyntheticMotion(DeviceIntPtr pDev, 12444642e01fSmrg int x, 12454642e01fSmrg int y, 12464642e01fSmrg int screen, 12474642e01fSmrg unsigned long time) 124805b261ecSmrg{ 12494202a189Smrg DeviceEvent ev; 125005b261ecSmrg 125105b261ecSmrg#ifdef PANORAMIX 125205b261ecSmrg /* Translate back to the sprite screen since processInputProc 125305b261ecSmrg will translate from sprite screen to screen 0 upon reentry 125405b261ecSmrg to the DIX layer. */ 125505b261ecSmrg if (!noPanoramiXExtension) { 12564202a189Smrg x += screenInfo.screens[0]->x - screenInfo.screens[screen]->x; 12574202a189Smrg y += screenInfo.screens[0]->y - screenInfo.screens[screen]->y; 125805b261ecSmrg } 125905b261ecSmrg#endif 126005b261ecSmrg 12614202a189Smrg memset(&ev, 0, sizeof(DeviceEvent)); 12624202a189Smrg init_event(pDev, &ev, time); 12634202a189Smrg ev.root_x = x; 12644202a189Smrg ev.root_y = y; 12654202a189Smrg ev.type = ET_Motion; 12664202a189Smrg ev.time = time; 126705b261ecSmrg 12684202a189Smrg /* FIXME: MD/SD considerations? */ 12694202a189Smrg (*pDev->public.processInputProc)((InternalEvent*)&ev, pDev); 127005b261ecSmrg} 1271