getevents.c revision 65b04b38
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" 4965b04b38Smrg#include "inpututils.h" 5005b261ecSmrg 5105b261ecSmrg#include <X11/extensions/XKBproto.h> 524202a189Smrg#include "xkbsrv.h" 5305b261ecSmrg 5405b261ecSmrg#ifdef PANORAMIX 5505b261ecSmrg#include "panoramiX.h" 5605b261ecSmrg#include "panoramiXsrv.h" 5705b261ecSmrg#endif 5805b261ecSmrg 5905b261ecSmrg#include <X11/extensions/XI.h> 6005b261ecSmrg#include <X11/extensions/XIproto.h> 614202a189Smrg#include <pixman.h> 6205b261ecSmrg#include "exglobals.h" 6305b261ecSmrg#include "exevents.h" 6405b261ecSmrg#include "exglobals.h" 6505b261ecSmrg#include "extnsionst.h" 664202a189Smrg#include "listdev.h" /* for sizing up DeviceClassesChangedEvent */ 6705b261ecSmrg 6805b261ecSmrg/* Number of motion history events to store. */ 6905b261ecSmrg#define MOTION_HISTORY_SIZE 256 7005b261ecSmrg 714642e01fSmrg/* InputEventList is the container list for all input events generated by the 724642e01fSmrg * DDX. The DDX is expected to call GetEventList() and then pass the list into 734642e01fSmrg * Get{Pointer|Keyboard}Events. 744642e01fSmrg */ 754642e01fSmrgEventListPtr InputEventList = NULL; 764642e01fSmrgint InputEventListLen = 0; 774642e01fSmrg 784202a189Smrgint 794642e01fSmrgGetEventList(EventListPtr* list) 804642e01fSmrg{ 814642e01fSmrg *list = InputEventList; 824642e01fSmrg return InputEventListLen; 834642e01fSmrg} 8405b261ecSmrg 8505b261ecSmrg/** 8605b261ecSmrg * Pick some arbitrary size for Xi motion history. 8705b261ecSmrg */ 884202a189Smrgint 8905b261ecSmrgGetMotionHistorySize(void) 9005b261ecSmrg{ 9105b261ecSmrg return MOTION_HISTORY_SIZE; 9205b261ecSmrg} 9305b261ecSmrg 944202a189Smrgvoid 954202a189Smrgset_button_down(DeviceIntPtr pDev, int button, int type) 9605b261ecSmrg{ 974202a189Smrg if (type == BUTTON_PROCESSED) 984202a189Smrg SetBit(pDev->button->down, button); 994202a189Smrg else 1004202a189Smrg SetBit(pDev->button->postdown, button); 10105b261ecSmrg} 10205b261ecSmrg 1034202a189Smrgvoid 1044202a189Smrgset_button_up(DeviceIntPtr pDev, int button, int type) 10505b261ecSmrg{ 1064202a189Smrg if (type == BUTTON_PROCESSED) 1074202a189Smrg ClearBit(pDev->button->down, button); 1084202a189Smrg else 1094202a189Smrg ClearBit(pDev->button->postdown, button); 11005b261ecSmrg} 11105b261ecSmrg 1124202a189SmrgBool 1134202a189Smrgbutton_is_down(DeviceIntPtr pDev, int button, int type) 1144202a189Smrg{ 1151b684552Smrg Bool ret = FALSE; 1164202a189Smrg 1174202a189Smrg if (type & BUTTON_PROCESSED) 1181b684552Smrg ret = ret || BitIsOn(pDev->button->down, button); 1194202a189Smrg if (type & BUTTON_POSTED) 1201b684552Smrg ret = ret || BitIsOn(pDev->button->postdown, button); 1214202a189Smrg 1224202a189Smrg return ret; 1234202a189Smrg} 1244202a189Smrg 1254202a189Smrgvoid 1264202a189Smrgset_key_down(DeviceIntPtr pDev, int key_code, int type) 12705b261ecSmrg{ 1284202a189Smrg if (type == KEY_PROCESSED) 1294202a189Smrg SetBit(pDev->key->down, key_code); 1304202a189Smrg else 1314202a189Smrg SetBit(pDev->key->postdown, key_code); 1324202a189Smrg} 1334202a189Smrg 1344202a189Smrgvoid 1354202a189Smrgset_key_up(DeviceIntPtr pDev, int key_code, int type) 1364202a189Smrg{ 1374202a189Smrg if (type == KEY_PROCESSED) 1384202a189Smrg ClearBit(pDev->key->down, key_code); 1394202a189Smrg else 1404202a189Smrg ClearBit(pDev->key->postdown, key_code); 1414202a189Smrg} 1424202a189Smrg 1434202a189SmrgBool 1444202a189Smrgkey_is_down(DeviceIntPtr pDev, int key_code, int type) 1454202a189Smrg{ 1461b684552Smrg Bool ret = FALSE; 1474202a189Smrg 1484202a189Smrg if (type & KEY_PROCESSED) 1491b684552Smrg ret = ret || BitIsOn(pDev->key->down, key_code); 1504202a189Smrg if (type & KEY_POSTED) 1511b684552Smrg ret = ret || BitIsOn(pDev->key->postdown, key_code); 1524202a189Smrg 1534202a189Smrg return ret; 15405b261ecSmrg} 15505b261ecSmrg 15605b261ecSmrgstatic Bool 15705b261ecSmrgkey_autorepeats(DeviceIntPtr pDev, int key_code) 15805b261ecSmrg{ 15905b261ecSmrg return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] & 16005b261ecSmrg (1 << (key_code & 7))); 16105b261ecSmrg} 16205b261ecSmrg 1634202a189Smrgstatic void 1644202a189Smrginit_event(DeviceIntPtr dev, DeviceEvent* event, Time ms) 1654202a189Smrg{ 1664202a189Smrg memset(event, 0, sizeof(DeviceEvent)); 1674202a189Smrg event->header = ET_Internal; 1684202a189Smrg event->length = sizeof(DeviceEvent); 1694202a189Smrg event->time = ms; 1704202a189Smrg event->deviceid = dev->id; 1714202a189Smrg event->sourceid = dev->id; 1724202a189Smrg} 1734202a189Smrg 1744202a189Smrgstatic void 1754202a189Smrginit_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail) 1764202a189Smrg{ 1774202a189Smrg memset(event, 0, sizeof(RawDeviceEvent)); 1784202a189Smrg event->header = ET_Internal; 1794202a189Smrg event->length = sizeof(RawDeviceEvent); 1804202a189Smrg event->type = ET_RawKeyPress - ET_KeyPress + type; 1814202a189Smrg event->time = ms; 1824202a189Smrg event->deviceid = dev->id; 1834202a189Smrg event->sourceid = dev->id; 1844202a189Smrg event->detail.button = detail; 1854202a189Smrg} 1864202a189Smrg 1874202a189Smrgstatic void 18865b04b38Smrgset_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, int32_t* data) 1894202a189Smrg{ 1904202a189Smrg int i; 1914202a189Smrg 19265b04b38Smrg for (i = 0; i < valuator_mask_size(mask); i++) 19365b04b38Smrg { 19465b04b38Smrg if (valuator_mask_isset(mask, i)) 19565b04b38Smrg { 19665b04b38Smrg SetBit(event->valuators.mask, i); 19765b04b38Smrg data[i] = valuator_mask_get(mask, i); 19865b04b38Smrg } 19965b04b38Smrg } 2004202a189Smrg} 2014202a189Smrg 2024202a189Smrg 2034202a189Smrgstatic void 20465b04b38Smrgset_valuators(DeviceIntPtr dev, DeviceEvent* event, ValuatorMask *mask) 2054202a189Smrg{ 2064202a189Smrg int i; 2074202a189Smrg 20865b04b38Smrg /* Set the data to the previous value for unset absolute axes. The values 20965b04b38Smrg * may be used when sent as part of an XI 1.x valuator event. */ 21065b04b38Smrg for (i = 0; i < valuator_mask_size(mask); i++) 2114202a189Smrg { 21265b04b38Smrg if (valuator_mask_isset(mask, i)) 21365b04b38Smrg { 21465b04b38Smrg SetBit(event->valuators.mask, i); 21565b04b38Smrg if (valuator_get_mode(dev, i) == Absolute) 21665b04b38Smrg SetBit(event->valuators.mode, i); 21765b04b38Smrg event->valuators.data[i] = valuator_mask_get(mask, i); 21865b04b38Smrg event->valuators.data_frac[i] = 21965b04b38Smrg dev->last.remainder[i] * (1 << 16) * (1 << 16); 22065b04b38Smrg } 22165b04b38Smrg else if (valuator_get_mode(dev, i) == Absolute) 22265b04b38Smrg event->valuators.data[i] = dev->valuator->axisVal[i]; 2234202a189Smrg } 2244202a189Smrg} 2254202a189Smrg 2264202a189Smrgvoid 2274202a189SmrgCreateClassesChangedEvent(EventList* event, 2284202a189Smrg DeviceIntPtr master, 2294202a189Smrg DeviceIntPtr slave, 2304202a189Smrg int type) 2314202a189Smrg{ 2324202a189Smrg int i; 2334202a189Smrg DeviceChangedEvent *dce; 2344202a189Smrg CARD32 ms = GetTimeInMillis(); 2354202a189Smrg 2364202a189Smrg dce = (DeviceChangedEvent*)event->event; 2374202a189Smrg memset(dce, 0, sizeof(DeviceChangedEvent)); 2384202a189Smrg dce->deviceid = slave->id; 2394202a189Smrg dce->masterid = master->id; 2404202a189Smrg dce->header = ET_Internal; 2414202a189Smrg dce->length = sizeof(DeviceChangedEvent); 2424202a189Smrg dce->type = ET_DeviceChanged; 2434202a189Smrg dce->time = ms; 2444202a189Smrg dce->flags = type; 2454202a189Smrg dce->flags |= DEVCHANGE_SLAVE_SWITCH; 2464202a189Smrg dce->sourceid = slave->id; 2474202a189Smrg 2484202a189Smrg if (slave->button) 2494202a189Smrg { 2504202a189Smrg dce->buttons.num_buttons = slave->button->numButtons; 2514202a189Smrg for (i = 0; i < dce->buttons.num_buttons; i++) 2524202a189Smrg dce->buttons.names[i] = slave->button->labels[i]; 2534202a189Smrg } 2544202a189Smrg if (slave->valuator) 2554202a189Smrg { 2564202a189Smrg dce->num_valuators = slave->valuator->numAxes; 2574202a189Smrg for (i = 0; i < dce->num_valuators; i++) 2584202a189Smrg { 2594202a189Smrg dce->valuators[i].min = slave->valuator->axes[i].min_value; 2604202a189Smrg dce->valuators[i].max = slave->valuator->axes[i].max_value; 2614202a189Smrg dce->valuators[i].resolution = slave->valuator->axes[i].resolution; 26265b04b38Smrg dce->valuators[i].mode = slave->valuator->axes[i].mode; 2634202a189Smrg dce->valuators[i].name = slave->valuator->axes[i].label; 2644202a189Smrg } 2654202a189Smrg } 2664202a189Smrg if (slave->key) 2674202a189Smrg { 2684202a189Smrg dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code; 2694202a189Smrg dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code; 2704202a189Smrg } 2714202a189Smrg} 2724202a189Smrg 2734642e01fSmrg/** 2744642e01fSmrg * Rescale the coord between the two axis ranges. 2754642e01fSmrg */ 2764642e01fSmrgstatic int 2774202a189SmrgrescaleValuatorAxis(int coord, float remainder, float *remainder_return, AxisInfoPtr from, AxisInfoPtr to, 2784642e01fSmrg int defmax) 2794642e01fSmrg{ 2804202a189Smrg int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax, coord_return; 2814202a189Smrg float value; 2824642e01fSmrg 2834642e01fSmrg if(from && from->min_value < from->max_value) { 2844642e01fSmrg fmin = from->min_value; 2854642e01fSmrg fmax = from->max_value; 2864642e01fSmrg } 2874642e01fSmrg if(to && to->min_value < to->max_value) { 2884642e01fSmrg tmin = to->min_value; 2894642e01fSmrg tmax = to->max_value; 2904642e01fSmrg } 2914642e01fSmrg 2924202a189Smrg if(fmin == tmin && fmax == tmax) { 2934202a189Smrg if (remainder_return) 2944202a189Smrg *remainder_return = remainder; 2954642e01fSmrg return coord; 2964202a189Smrg } 2974642e01fSmrg 2984202a189Smrg if(fmax == fmin) { /* avoid division by 0 */ 2994202a189Smrg if (remainder_return) 3004202a189Smrg *remainder_return = 0.0; 3014642e01fSmrg return 0; 3024202a189Smrg } 3034642e01fSmrg 3044202a189Smrg value = (coord + remainder - fmin) * (tmax - tmin) / (fmax - fmin) + tmin; 3054202a189Smrg coord_return = lroundf(value); 3064202a189Smrg if (remainder_return) 3074202a189Smrg *remainder_return = value - coord_return; 3084202a189Smrg return coord_return; 3094642e01fSmrg} 3104642e01fSmrg 3114642e01fSmrg/** 3124642e01fSmrg * Update all coordinates when changing to a different SD 3134642e01fSmrg * to ensure that relative reporting will work as expected 3144642e01fSmrg * without loss of precision. 3154642e01fSmrg * 3164642e01fSmrg * pDev->last.valuators will be in absolute device coordinates after this 3174642e01fSmrg * function. 3184642e01fSmrg */ 3194642e01fSmrgstatic void 3204642e01fSmrgupdateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev) 3214642e01fSmrg{ 3224642e01fSmrg ScreenPtr scr = miPointerGetScreen(pDev); 3234642e01fSmrg int i; 3244642e01fSmrg DeviceIntPtr lastSlave; 3254642e01fSmrg 3264642e01fSmrg /* master->last.valuators[0]/[1] is in screen coords and the actual 3274642e01fSmrg * position of the pointer */ 3284642e01fSmrg pDev->last.valuators[0] = master->last.valuators[0]; 3294642e01fSmrg pDev->last.valuators[1] = master->last.valuators[1]; 3304642e01fSmrg 3314642e01fSmrg if (!pDev->valuator) 3324642e01fSmrg return; 3334642e01fSmrg 3344642e01fSmrg /* scale back to device coordinates */ 3354642e01fSmrg if(pDev->valuator->numAxes > 0) 3364202a189Smrg pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], pDev->last.remainder[0], 3374202a189Smrg &pDev->last.remainder[0], NULL, pDev->valuator->axes + 0, scr->width); 3384642e01fSmrg if(pDev->valuator->numAxes > 1) 3394202a189Smrg pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], pDev->last.remainder[1], 3404202a189Smrg &pDev->last.remainder[1], NULL, pDev->valuator->axes + 1, scr->height); 3414642e01fSmrg 3424642e01fSmrg /* calculate the other axis as well based on info from the old 3434642e01fSmrg * slave-device. If the old slave had less axes than this one, 3444642e01fSmrg * last.valuators is reset to 0. 3454642e01fSmrg */ 3464202a189Smrg if ((lastSlave = master->last.slave) && lastSlave->valuator) { 3474642e01fSmrg for (i = 2; i < pDev->valuator->numAxes; i++) { 3484642e01fSmrg if (i >= lastSlave->valuator->numAxes) 3494642e01fSmrg pDev->last.valuators[i] = 0; 3504642e01fSmrg else 3514642e01fSmrg pDev->last.valuators[i] = 3524642e01fSmrg rescaleValuatorAxis(pDev->last.valuators[i], 3534202a189Smrg pDev->last.remainder[i], 3544202a189Smrg &pDev->last.remainder[i], 3554642e01fSmrg lastSlave->valuator->axes + i, 3564642e01fSmrg pDev->valuator->axes + i, 0); 3574642e01fSmrg } 3584642e01fSmrg } 3594642e01fSmrg 3604642e01fSmrg} 3614642e01fSmrg 36205b261ecSmrg/** 36305b261ecSmrg * Allocate the motion history buffer. 36405b261ecSmrg */ 3654202a189Smrgvoid 36605b261ecSmrgAllocateMotionHistory(DeviceIntPtr pDev) 36705b261ecSmrg{ 3684642e01fSmrg int size; 3694202a189Smrg free(pDev->valuator->motion); 37005b261ecSmrg 37105b261ecSmrg if (pDev->valuator->numMotionEvents < 1) 37205b261ecSmrg return; 37305b261ecSmrg 3744642e01fSmrg /* An MD must have a motion history size large enough to keep all 3754642e01fSmrg * potential valuators, plus the respective range of the valuators. 3764642e01fSmrg * 3 * INT32 for (min_val, max_val, curr_val)) 3774642e01fSmrg */ 3784202a189Smrg if (IsMaster(pDev)) 3794642e01fSmrg size = sizeof(INT32) * 3 * MAX_VALUATORS; 38065b04b38Smrg else { 38165b04b38Smrg ValuatorClassPtr v = pDev->valuator; 38265b04b38Smrg int numAxes; 38365b04b38Smrg /* XI1 doesn't understand mixed mode devices */ 38465b04b38Smrg for (numAxes = 0; numAxes < v->numAxes; numAxes++) 38565b04b38Smrg if (valuator_get_mode(pDev, numAxes) != valuator_get_mode(pDev, 0)) 38665b04b38Smrg break; 38765b04b38Smrg size = sizeof(INT32) * numAxes; 38865b04b38Smrg } 3894642e01fSmrg 3904642e01fSmrg size += sizeof(Time); 3914642e01fSmrg 3924202a189Smrg pDev->valuator->motion = calloc(pDev->valuator->numMotionEvents, size); 39305b261ecSmrg pDev->valuator->first_motion = 0; 39405b261ecSmrg pDev->valuator->last_motion = 0; 3954642e01fSmrg if (!pDev->valuator->motion) 3964642e01fSmrg ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n", 3974642e01fSmrg pDev->name, size * pDev->valuator->numMotionEvents); 39805b261ecSmrg} 39905b261ecSmrg 40005b261ecSmrg/** 40105b261ecSmrg * Dump the motion history between start and stop into the supplied buffer. 40205b261ecSmrg * Only records the event for a given screen in theory, but in practice, we 40305b261ecSmrg * sort of ignore this. 4044642e01fSmrg * 4054642e01fSmrg * If core is set, we only generate x/y, in INT16, scaled to screen coords. 40605b261ecSmrg */ 4074202a189Smrgint 4084642e01fSmrgGetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start, 4094642e01fSmrg unsigned long stop, ScreenPtr pScreen, BOOL core) 41005b261ecSmrg{ 4114642e01fSmrg char *ibuff = NULL, *obuff; 41205b261ecSmrg int i = 0, ret = 0; 4134642e01fSmrg int j, coord; 41405b261ecSmrg Time current; 41505b261ecSmrg /* The size of a single motion event. */ 4164642e01fSmrg int size; 4174642e01fSmrg int dflt; 4184642e01fSmrg AxisInfo from, *to; /* for scaling */ 4194642e01fSmrg INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */ 4204642e01fSmrg INT16 *corebuf; 4214642e01fSmrg AxisInfo core_axis = {0}; 42205b261ecSmrg 42305b261ecSmrg if (!pDev->valuator || !pDev->valuator->numMotionEvents) 42405b261ecSmrg return 0; 42505b261ecSmrg 4264642e01fSmrg if (core && !pScreen) 4274642e01fSmrg return 0; 4284642e01fSmrg 4294202a189Smrg if (IsMaster(pDev)) 4304642e01fSmrg size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time); 4314642e01fSmrg else 4324642e01fSmrg size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); 4334642e01fSmrg 4344202a189Smrg *buff = malloc(size * pDev->valuator->numMotionEvents); 4354642e01fSmrg if (!(*buff)) 4364642e01fSmrg return 0; 4374642e01fSmrg obuff = (char *)*buff; 4384642e01fSmrg 43905b261ecSmrg for (i = pDev->valuator->first_motion; 44005b261ecSmrg i != pDev->valuator->last_motion; 44105b261ecSmrg i = (i + 1) % pDev->valuator->numMotionEvents) { 44205b261ecSmrg /* We index the input buffer by which element we're accessing, which 44305b261ecSmrg * is not monotonic, and the output buffer by how many events we've 44405b261ecSmrg * written so far. */ 44505b261ecSmrg ibuff = (char *) pDev->valuator->motion + (i * size); 44605b261ecSmrg memcpy(¤t, ibuff, sizeof(Time)); 44705b261ecSmrg 44805b261ecSmrg if (current > stop) { 44905b261ecSmrg return ret; 45005b261ecSmrg } 45105b261ecSmrg else if (current >= start) { 4524642e01fSmrg if (core) 4534642e01fSmrg { 4544642e01fSmrg memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */ 4554642e01fSmrg 4564642e01fSmrg icbuf = (INT32*)(ibuff + sizeof(Time)); 4574642e01fSmrg corebuf = (INT16*)(obuff + sizeof(Time)); 4584642e01fSmrg 4594642e01fSmrg /* fetch x coordinate + range */ 4604642e01fSmrg memcpy(&from.min_value, icbuf++, sizeof(INT32)); 4614642e01fSmrg memcpy(&from.max_value, icbuf++, sizeof(INT32)); 4624642e01fSmrg memcpy(&coord, icbuf++, sizeof(INT32)); 4634642e01fSmrg 4644642e01fSmrg /* scale to screen coords */ 4654642e01fSmrg to = &core_axis; 4664642e01fSmrg to->max_value = pScreen->width; 4674202a189Smrg coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->width); 4684642e01fSmrg 4694642e01fSmrg memcpy(corebuf, &coord, sizeof(INT16)); 4704642e01fSmrg corebuf++; 4714642e01fSmrg 4724642e01fSmrg /* fetch y coordinate + range */ 4734642e01fSmrg memcpy(&from.min_value, icbuf++, sizeof(INT32)); 4744642e01fSmrg memcpy(&from.max_value, icbuf++, sizeof(INT32)); 4754642e01fSmrg memcpy(&coord, icbuf++, sizeof(INT32)); 4764642e01fSmrg 4774642e01fSmrg to->max_value = pScreen->height; 4784202a189Smrg coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->height); 4794642e01fSmrg memcpy(corebuf, &coord, sizeof(INT16)); 4804642e01fSmrg 4814202a189Smrg } else if (IsMaster(pDev)) 4824642e01fSmrg { 4834642e01fSmrg memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */ 4844642e01fSmrg 4854642e01fSmrg ocbuf = (INT32*)(obuff + sizeof(Time)); 4864642e01fSmrg icbuf = (INT32*)(ibuff + sizeof(Time)); 4874642e01fSmrg for (j = 0; j < MAX_VALUATORS; j++) 4884642e01fSmrg { 4894642e01fSmrg if (j >= pDev->valuator->numAxes) 4904642e01fSmrg break; 4914642e01fSmrg 4924642e01fSmrg /* fetch min/max/coordinate */ 4934642e01fSmrg memcpy(&from.min_value, icbuf++, sizeof(INT32)); 4944642e01fSmrg memcpy(&from.max_value, icbuf++, sizeof(INT32)); 4954642e01fSmrg memcpy(&coord, icbuf++, sizeof(INT32)); 4964642e01fSmrg 4974642e01fSmrg to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL; 4984642e01fSmrg 4994642e01fSmrg /* x/y scaled to screen if no range is present */ 5004642e01fSmrg if (j == 0 && (from.max_value < from.min_value)) 5014642e01fSmrg from.max_value = pScreen->width; 5024642e01fSmrg else if (j == 1 && (from.max_value < from.min_value)) 5034642e01fSmrg from.max_value = pScreen->height; 5044642e01fSmrg 5054642e01fSmrg if (j == 0 && (to->max_value < to->min_value)) 5064642e01fSmrg dflt = pScreen->width; 5074642e01fSmrg else if (j == 1 && (to->max_value < to->min_value)) 5084642e01fSmrg dflt = pScreen->height; 5094642e01fSmrg else 5104642e01fSmrg dflt = 0; 5114642e01fSmrg 5124642e01fSmrg /* scale from stored range into current range */ 5134202a189Smrg coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, 0); 5144642e01fSmrg memcpy(ocbuf, &coord, sizeof(INT32)); 5154642e01fSmrg ocbuf++; 5164642e01fSmrg } 5174642e01fSmrg } else 5184642e01fSmrg memcpy(obuff, ibuff, size); 5194642e01fSmrg 5204642e01fSmrg /* don't advance by size here. size may be different to the 5214642e01fSmrg * actually written size if the MD has less valuators than MAX */ 5224642e01fSmrg if (core) 5234642e01fSmrg obuff += sizeof(INT32) + sizeof(Time); 5244642e01fSmrg else 5254642e01fSmrg obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); 52605b261ecSmrg ret++; 52705b261ecSmrg } 52805b261ecSmrg } 52905b261ecSmrg 53005b261ecSmrg return ret; 53105b261ecSmrg} 53205b261ecSmrg 53305b261ecSmrg 53405b261ecSmrg/** 53505b261ecSmrg * Update the motion history for a specific device, with the list of 53605b261ecSmrg * valuators. 5374642e01fSmrg * 5384642e01fSmrg * Layout of the history buffer: 5394642e01fSmrg * for SDs: [time] [val0] [val1] ... [valn] 5404642e01fSmrg * for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn] 5414642e01fSmrg * 54265b04b38Smrg * For events that have some valuators unset: 5434642e01fSmrg * min_val == max_val == val == 0. 54405b261ecSmrg */ 54505b261ecSmrgstatic void 54665b04b38SmrgupdateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask, 54765b04b38Smrg int *valuators) 54805b261ecSmrg{ 54905b261ecSmrg char *buff = (char *) pDev->valuator->motion; 5504642e01fSmrg ValuatorClassPtr v; 5514642e01fSmrg int i; 55205b261ecSmrg 55305b261ecSmrg if (!pDev->valuator->numMotionEvents) 55405b261ecSmrg return; 55505b261ecSmrg 5564642e01fSmrg v = pDev->valuator; 5574202a189Smrg if (IsMaster(pDev)) 5584642e01fSmrg { 5594642e01fSmrg buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) * 5604642e01fSmrg v->last_motion; 5614642e01fSmrg 5624642e01fSmrg memcpy(buff, &ms, sizeof(Time)); 5634642e01fSmrg buff += sizeof(Time); 5644642e01fSmrg 5654642e01fSmrg memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS); 5664642e01fSmrg 56765b04b38Smrg for (i = 0; i < v->numAxes; i++) 5684642e01fSmrg { 56965b04b38Smrg /* XI1 doesn't support mixed mode devices */ 57065b04b38Smrg if (valuator_get_mode(pDev, i) != valuator_get_mode(pDev, 0)) 5714642e01fSmrg break; 57265b04b38Smrg if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) 57365b04b38Smrg { 57465b04b38Smrg buff += 3 * sizeof(INT32); 57565b04b38Smrg continue; 57665b04b38Smrg } 5774642e01fSmrg memcpy(buff, &v->axes[i].min_value, sizeof(INT32)); 5784642e01fSmrg buff += sizeof(INT32); 5794642e01fSmrg memcpy(buff, &v->axes[i].max_value, sizeof(INT32)); 5804642e01fSmrg buff += sizeof(INT32); 58165b04b38Smrg memcpy(buff, &valuators[i], sizeof(INT32)); 5824642e01fSmrg buff += sizeof(INT32); 5834642e01fSmrg } 5844642e01fSmrg } else 5854642e01fSmrg { 5864642e01fSmrg 5874642e01fSmrg buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) * 58805b261ecSmrg pDev->valuator->last_motion; 58905b261ecSmrg 5904642e01fSmrg memcpy(buff, &ms, sizeof(Time)); 5914642e01fSmrg buff += sizeof(Time); 59205b261ecSmrg 5934642e01fSmrg memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes); 59405b261ecSmrg 59565b04b38Smrg for (i = 0; i < MAX_VALUATORS; i++) 59665b04b38Smrg { 59765b04b38Smrg if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) 59865b04b38Smrg { 59965b04b38Smrg buff += sizeof(INT32); 60065b04b38Smrg continue; 60165b04b38Smrg } 60265b04b38Smrg memcpy(buff, &valuators[i], sizeof(INT32)); 60365b04b38Smrg buff += sizeof(INT32); 60465b04b38Smrg } 6054642e01fSmrg } 60605b261ecSmrg 6074642e01fSmrg pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) % 6084642e01fSmrg pDev->valuator->numMotionEvents; 60905b261ecSmrg /* If we're wrapping around, just keep the circular buffer going. */ 61005b261ecSmrg if (pDev->valuator->first_motion == pDev->valuator->last_motion) 61105b261ecSmrg pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) % 61205b261ecSmrg pDev->valuator->numMotionEvents; 61305b261ecSmrg 61405b261ecSmrg return; 61505b261ecSmrg} 61605b261ecSmrg 61705b261ecSmrg 61805b261ecSmrg/** 61905b261ecSmrg * Returns the maximum number of events GetKeyboardEvents, 62005b261ecSmrg * GetKeyboardValuatorEvents, and GetPointerEvents will ever return. 62105b261ecSmrg * 6224642e01fSmrg * This MUST be absolutely constant, from init until exit. 62305b261ecSmrg */ 6244202a189Smrgint 62505b261ecSmrgGetMaximumEventsNum(void) { 6264202a189Smrg /* One raw event 6274202a189Smrg * One device event 6284202a189Smrg * One possible device changed event 6294202a189Smrg */ 6304202a189Smrg return 3; 63105b261ecSmrg} 63205b261ecSmrg 63305b261ecSmrg 63405b261ecSmrg/** 63505b261ecSmrg * Clip an axis to its bounds, which are declared in the call to 63605b261ecSmrg * InitValuatorAxisClassStruct. 63705b261ecSmrg */ 63805b261ecSmrgstatic void 63905b261ecSmrgclipAxis(DeviceIntPtr pDev, int axisNum, int *val) 64005b261ecSmrg{ 6414202a189Smrg AxisInfoPtr axis; 6424202a189Smrg 6434202a189Smrg if (axisNum >= pDev->valuator->numAxes) 6444202a189Smrg return; 6454202a189Smrg 6464202a189Smrg axis = pDev->valuator->axes + axisNum; 6474642e01fSmrg 6484642e01fSmrg /* If a value range is defined, clip. If not, do nothing */ 6494642e01fSmrg if (axis->max_value <= axis->min_value) 6504642e01fSmrg return; 6514642e01fSmrg 6524642e01fSmrg if (*val < axis->min_value) 6534642e01fSmrg *val = axis->min_value; 6544642e01fSmrg if (*val > axis->max_value) 6554642e01fSmrg *val = axis->max_value; 65605b261ecSmrg} 65705b261ecSmrg 65805b261ecSmrg/** 65905b261ecSmrg * Clip every axis in the list of valuators to its bounds. 66005b261ecSmrg */ 66105b261ecSmrgstatic void 66265b04b38SmrgclipValuators(DeviceIntPtr pDev, ValuatorMask *mask) 66305b261ecSmrg{ 66405b261ecSmrg int i; 66505b261ecSmrg 66665b04b38Smrg for (i = 0; i < valuator_mask_size(mask); i++) 66765b04b38Smrg if (valuator_mask_isset(mask, i)) 66865b04b38Smrg { 66965b04b38Smrg int val = valuator_mask_get(mask, i); 67065b04b38Smrg clipAxis(pDev, i, &val); 67165b04b38Smrg valuator_mask_set(mask, i, val); 67265b04b38Smrg } 67305b261ecSmrg} 67405b261ecSmrg 6754642e01fSmrg/** 6764642e01fSmrg * Create the DCCE event (does not update the master's device state yet, this 6774642e01fSmrg * is done in the event processing). 6784642e01fSmrg * Pull in the coordinates from the MD if necessary. 6794642e01fSmrg * 6804642e01fSmrg * @param events Pointer to a pre-allocated event list. 6814642e01fSmrg * @param dev The slave device that generated an event. 6824202a189Smrg * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT 6834642e01fSmrg * @param num_events The current number of events, returns the number of 6844642e01fSmrg * events if a DCCE was generated. 6854642e01fSmrg * @return The updated @events pointer. 6864642e01fSmrg */ 6874202a189SmrgEventListPtr 6884202a189SmrgUpdateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events) 6894642e01fSmrg{ 6904202a189Smrg DeviceIntPtr master; 6914202a189Smrg 6924202a189Smrg master = GetMaster(dev, (type & DEVCHANGE_POINTER_EVENT) ? MASTER_POINTER : MASTER_KEYBOARD); 6934202a189Smrg 6944202a189Smrg if (master && master->last.slave != dev) 6954642e01fSmrg { 6964202a189Smrg CreateClassesChangedEvent(events, master, dev, type); 6974202a189Smrg if (IsPointerDevice(master)) 6984202a189Smrg { 6994202a189Smrg updateSlaveDeviceCoords(master, dev); 7004202a189Smrg master->last.numValuators = dev->last.numValuators; 7014202a189Smrg } 7024202a189Smrg master->last.slave = dev; 7034202a189Smrg (*num_events)++; 7044202a189Smrg events++; 7054642e01fSmrg } 7064642e01fSmrg return events; 7074642e01fSmrg} 7084642e01fSmrg 7094642e01fSmrg/** 7104642e01fSmrg * Move the device's pointer to the position given in the valuators. 7114642e01fSmrg * 7124642e01fSmrg * @param dev The device which's pointer is to be moved. 7134642e01fSmrg * @param x Returns the x position of the pointer after the move. 7144642e01fSmrg * @param y Returns the y position of the pointer after the move. 71565b04b38Smrg * @param mask Bit mask of valid valuators. 7164642e01fSmrg * @param valuators Valuator data for each axis between @first and 7174642e01fSmrg * @first+@num. 7184642e01fSmrg */ 7194642e01fSmrgstatic void 72065b04b38SmrgmoveAbsolute(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask) 7214642e01fSmrg{ 7224642e01fSmrg int i; 7234642e01fSmrg 72465b04b38Smrg if (valuator_mask_isset(mask, 0)) 72565b04b38Smrg *x = valuator_mask_get(mask, 0); 7264642e01fSmrg else 7274642e01fSmrg *x = dev->last.valuators[0]; 7284642e01fSmrg 72965b04b38Smrg if (valuator_mask_isset(mask, 1)) 73065b04b38Smrg *y = valuator_mask_get(mask, 1); 7314642e01fSmrg else 7324642e01fSmrg *y = dev->last.valuators[1]; 7334642e01fSmrg 7344642e01fSmrg clipAxis(dev, 0, x); 7354642e01fSmrg clipAxis(dev, 1, y); 7364642e01fSmrg 73765b04b38Smrg for (i = 2; i < valuator_mask_size(mask); i++) 7384642e01fSmrg { 73965b04b38Smrg if (valuator_mask_isset(mask, i)) 74065b04b38Smrg { 74165b04b38Smrg dev->last.valuators[i] = valuator_mask_get(mask, i); 74265b04b38Smrg clipAxis(dev, i, &dev->last.valuators[i]); 74365b04b38Smrg } 7444642e01fSmrg } 7454642e01fSmrg} 7464642e01fSmrg 7474642e01fSmrg/** 7484642e01fSmrg * Move the device's pointer by the values given in @valuators. 7494642e01fSmrg * 7504642e01fSmrg * @param dev The device which's pointer is to be moved. 7514642e01fSmrg * @param x Returns the x position of the pointer after the move. 7524642e01fSmrg * @param y Returns the y position of the pointer after the move. 75365b04b38Smrg * @param mask Bit mask of valid valuators. 7544642e01fSmrg * @param valuators Valuator data for each axis between @first and 7554642e01fSmrg * @first+@num. 7564642e01fSmrg */ 7574642e01fSmrgstatic void 75865b04b38SmrgmoveRelative(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask) 7594642e01fSmrg{ 7604642e01fSmrg int i; 7614642e01fSmrg 7624642e01fSmrg *x = dev->last.valuators[0]; 7634642e01fSmrg *y = dev->last.valuators[1]; 7644642e01fSmrg 76565b04b38Smrg if (valuator_mask_isset(mask, 0)) 76665b04b38Smrg *x += valuator_mask_get(mask, 0); 7674642e01fSmrg 76865b04b38Smrg if (valuator_mask_isset(mask, 1)) 76965b04b38Smrg *y += valuator_mask_get(mask, 1); 7704642e01fSmrg 7714642e01fSmrg /* if attached, clip both x and y to the defined limits (usually 7724642e01fSmrg * co-ord space limit). If it is attached, we need x/y to go over the 7734642e01fSmrg * limits to be able to change screens. */ 77465b04b38Smrg if(dev->u.master && dev->valuator) { 77565b04b38Smrg if (valuator_get_mode(dev, 0) == Absolute) 77665b04b38Smrg clipAxis(dev, 0, x); 77765b04b38Smrg if (valuator_get_mode(dev, 1) == Absolute) 77865b04b38Smrg clipAxis(dev, 1, y); 7794642e01fSmrg } 7804642e01fSmrg 7814642e01fSmrg /* calc other axes, clip, drop back into valuators */ 78265b04b38Smrg for (i = 2; i < valuator_mask_size(mask); i++) 7834642e01fSmrg { 78465b04b38Smrg if (valuator_mask_isset(mask, i)) 78565b04b38Smrg { 78665b04b38Smrg dev->last.valuators[i] += valuator_mask_get(mask, i); 78765b04b38Smrg if (valuator_get_mode(dev, i) == Absolute) 78865b04b38Smrg clipAxis(dev, i, &dev->last.valuators[i]); 78965b04b38Smrg valuator_mask_set(mask, i, dev->last.valuators[i]); 79065b04b38Smrg } 7914642e01fSmrg } 7924642e01fSmrg} 7934642e01fSmrg 7944642e01fSmrg/** 7954642e01fSmrg * Accelerate the data in valuators based on the device's acceleration scheme. 7964642e01fSmrg * 7974642e01fSmrg * @param dev The device which's pointer is to be moved. 7984642e01fSmrg * @param first The first valuator in @valuators 7994642e01fSmrg * @param num Total number of valuators in @valuators. 8004642e01fSmrg * @param valuators Valuator data for each axis between @first and 8014642e01fSmrg * @first+@num. 8024642e01fSmrg * @param ms Current time. 8034642e01fSmrg */ 8044642e01fSmrgstatic void 8054642e01fSmrgaccelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms) 8064642e01fSmrg{ 8074642e01fSmrg if (dev->valuator->accelScheme.AccelSchemeProc) 8084642e01fSmrg dev->valuator->accelScheme.AccelSchemeProc(dev, first, num, valuators, ms); 8094642e01fSmrg} 8104642e01fSmrg 8114642e01fSmrg/** 8124642e01fSmrg * If we have HW cursors, this actually moves the visible sprite. If not, we 8134642e01fSmrg * just do all the screen crossing, etc. 8144642e01fSmrg * 8154642e01fSmrg * We scale from device to screen coordinates here, call 8164642e01fSmrg * miPointerSetPosition() and then scale back into device coordinates (if 8174642e01fSmrg * needed). miPSP will change x/y if the screen was crossed. 8184642e01fSmrg * 8194642e01fSmrg * @param dev The device to be moved. 8204642e01fSmrg * @param x Pointer to current x-axis value, may be modified. 8214642e01fSmrg * @param y Pointer to current y-axis value, may be modified. 8224202a189Smrg * @param x_frac Fractional part of current x-axis value, may be modified. 8234202a189Smrg * @param y_frac Fractional part of current y-axis value, may be modified. 8244642e01fSmrg * @param scr Screen the device's sprite is currently on. 8254642e01fSmrg * @param screenx Screen x coordinate the sprite is on after the update. 8264642e01fSmrg * @param screeny Screen y coordinate the sprite is on after the update. 8274202a189Smrg * @param screenx_frac Fractional part of screen x coordinate, as above. 8284202a189Smrg * @param screeny_frac Fractional part of screen y coordinate, as above. 8294642e01fSmrg */ 8304642e01fSmrgstatic void 8314202a189SmrgpositionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac, 8324202a189Smrg ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac) 8334642e01fSmrg{ 8344202a189Smrg int old_screenx, old_screeny; 8354202a189Smrg 8364642e01fSmrg /* scale x&y to screen */ 83765b04b38Smrg if (dev->valuator && dev->valuator->numAxes > 0) { 8384202a189Smrg *screenx = rescaleValuatorAxis(*x, x_frac, screenx_frac, 8394202a189Smrg dev->valuator->axes + 0, NULL, scr->width); 8404202a189Smrg } else { 8414202a189Smrg *screenx = dev->last.valuators[0]; 8424202a189Smrg *screenx_frac = dev->last.remainder[0]; 8434202a189Smrg } 8444202a189Smrg 84565b04b38Smrg if (dev->valuator && dev->valuator->numAxes > 1) { 8464202a189Smrg *screeny = rescaleValuatorAxis(*y, y_frac, screeny_frac, 8474202a189Smrg dev->valuator->axes + 1, NULL, scr->height); 8484202a189Smrg } else { 8494202a189Smrg *screeny = dev->last.valuators[1]; 8504202a189Smrg *screeny_frac = dev->last.remainder[1]; 8514202a189Smrg } 8524202a189Smrg 8534202a189Smrg /* Hit the left screen edge? */ 8544202a189Smrg if (*screenx <= 0 && *screenx_frac < 0.0f) 8554202a189Smrg { 8564202a189Smrg *screenx_frac = 0.0f; 8574202a189Smrg x_frac = 0.0f; 8584202a189Smrg } 8594202a189Smrg if (*screeny <= 0 && *screeny_frac < 0.0f) 8604202a189Smrg { 8614202a189Smrg *screeny_frac = 0.0f; 8624202a189Smrg y_frac = 0.0f; 8634202a189Smrg } 8644202a189Smrg 8654642e01fSmrg 8664202a189Smrg old_screenx = *screenx; 8674202a189Smrg old_screeny = *screeny; 8684642e01fSmrg /* This takes care of crossing screens for us, as well as clipping 8694642e01fSmrg * to the current screen. */ 8704202a189Smrg miPointerSetPosition(dev, screenx, screeny); 8714642e01fSmrg 8724202a189Smrg if (dev->u.master) { 8734202a189Smrg dev->u.master->last.valuators[0] = *screenx; 8744202a189Smrg dev->u.master->last.valuators[1] = *screeny; 8754202a189Smrg dev->u.master->last.remainder[0] = *screenx_frac; 8764202a189Smrg dev->u.master->last.remainder[1] = *screeny_frac; 8774642e01fSmrg } 8784642e01fSmrg 87965b04b38Smrg if (dev->valuator) 8804642e01fSmrg { 88165b04b38Smrg /* Crossed screen? Scale back to device coordiantes */ 88265b04b38Smrg if(*screenx != old_screenx) 88365b04b38Smrg { 88465b04b38Smrg scr = miPointerGetScreen(dev); 88565b04b38Smrg *x = rescaleValuatorAxis(*screenx, *screenx_frac, &x_frac, NULL, 88665b04b38Smrg dev->valuator->axes + 0, scr->width); 88765b04b38Smrg } 88865b04b38Smrg if(*screeny != old_screeny) 88965b04b38Smrg { 89065b04b38Smrg scr = miPointerGetScreen(dev); 89165b04b38Smrg *y = rescaleValuatorAxis(*screeny, *screeny_frac, &y_frac, NULL, 89265b04b38Smrg dev->valuator->axes + 1, scr->height); 89365b04b38Smrg } 8944642e01fSmrg } 8954642e01fSmrg 8964642e01fSmrg /* dropy x/y (device coordinates) back into valuators for next event */ 8974642e01fSmrg dev->last.valuators[0] = *x; 8984642e01fSmrg dev->last.valuators[1] = *y; 8994202a189Smrg dev->last.remainder[0] = x_frac; 9004202a189Smrg dev->last.remainder[1] = y_frac; 9014642e01fSmrg} 9024642e01fSmrg 9034642e01fSmrg/** 9044642e01fSmrg * Update the motion history for the device and (if appropriate) for its 9054642e01fSmrg * master device. 9064642e01fSmrg * @param dev Slave device to update. 90765b04b38Smrg * @param mask Bit mask of valid valuators to append to history. 9084642e01fSmrg * @param num Total number of valuators to append to history. 9094642e01fSmrg * @param ms Current time 9104642e01fSmrg */ 9114642e01fSmrgstatic void 91265b04b38SmrgupdateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms) 9134642e01fSmrg{ 91465b04b38Smrg if (!dev->valuator) 91565b04b38Smrg return; 91665b04b38Smrg 91765b04b38Smrg updateMotionHistory(dev, ms, mask, dev->last.valuators); 9184642e01fSmrg if (dev->u.master) 9194202a189Smrg { 9204202a189Smrg DeviceIntPtr master = GetMaster(dev, MASTER_POINTER); 92165b04b38Smrg updateMotionHistory(master, ms, mask, dev->last.valuators); 9224202a189Smrg } 9234642e01fSmrg} 92405b261ecSmrg 92505b261ecSmrg/** 92605b261ecSmrg * Convenience wrapper around GetKeyboardValuatorEvents, that takes no 92705b261ecSmrg * valuators. 92805b261ecSmrg */ 9294202a189Smrgint 9304642e01fSmrgGetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) { 93165b04b38Smrg ValuatorMask mask; 93265b04b38Smrg 93365b04b38Smrg valuator_mask_zero(&mask); 93465b04b38Smrg return GetKeyboardValuatorEvents(events, pDev, type, key_code, &mask); 93505b261ecSmrg} 93605b261ecSmrg 93705b261ecSmrg 93805b261ecSmrg/** 93965b04b38Smrg * Returns a set of InternalEvents for KeyPress/KeyRelease, optionally 94065b04b38Smrg * also with valuator events. 9414642e01fSmrg * 94205b261ecSmrg * events is not NULL-terminated; the return value is the number of events. 94305b261ecSmrg * The DDX is responsible for allocating the event structure in the first 94405b261ecSmrg * place via GetMaximumEventsNum(), and for freeing it. 94505b261ecSmrg */ 9464202a189Smrgint 9474642e01fSmrgGetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, 94865b04b38Smrg int key_code, const ValuatorMask *mask_in) { 9494202a189Smrg int num_events = 0; 95005b261ecSmrg CARD32 ms = 0; 9514202a189Smrg DeviceEvent *event; 9524202a189Smrg RawDeviceEvent *raw; 95365b04b38Smrg ValuatorMask mask; 9544202a189Smrg 9554202a189Smrg /* refuse events from disabled devices */ 9564202a189Smrg if (!pDev->enabled) 9574202a189Smrg return 0; 95805b261ecSmrg 9594642e01fSmrg if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed || 9604642e01fSmrg (type != KeyPress && type != KeyRelease) || 9614642e01fSmrg (key_code < 8 || key_code > 255)) 96205b261ecSmrg return 0; 96305b261ecSmrg 9644202a189Smrg num_events = 1; 96505b261ecSmrg 9664202a189Smrg events = UpdateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events); 96705b261ecSmrg 9684202a189Smrg /* Handle core repeating, via press/release/press/release. */ 9694202a189Smrg if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) { 97005b261ecSmrg /* If autorepeating is disabled either globally or just for that key, 97105b261ecSmrg * or we have a modifier, don't generate a repeat event. */ 97205b261ecSmrg if (!pDev->kbdfeed->ctrl.autoRepeat || 97305b261ecSmrg !key_autorepeats(pDev, key_code) || 9744202a189Smrg pDev->key->xkbInfo->desc->map->modmap[key_code]) 97505b261ecSmrg return 0; 97605b261ecSmrg } 97705b261ecSmrg 97805b261ecSmrg ms = GetTimeInMillis(); 97905b261ecSmrg 9804202a189Smrg raw = (RawDeviceEvent*)events->event; 9814202a189Smrg events++; 9824202a189Smrg num_events++; 9834202a189Smrg 98465b04b38Smrg valuator_mask_copy(&mask, mask_in); 9854202a189Smrg 9864202a189Smrg init_raw(pDev, raw, ms, type, key_code); 98765b04b38Smrg set_raw_valuators(raw, &mask, raw->valuators.data_raw); 9884202a189Smrg 98965b04b38Smrg clipValuators(pDev, &mask); 9904202a189Smrg 99165b04b38Smrg set_raw_valuators(raw, &mask, raw->valuators.data); 9924202a189Smrg 9934202a189Smrg event = (DeviceEvent*) events->event; 9944202a189Smrg init_event(pDev, event, ms); 9954202a189Smrg event->detail.key = key_code; 9964202a189Smrg 99705b261ecSmrg if (type == KeyPress) { 9984202a189Smrg event->type = ET_KeyPress; 9994202a189Smrg set_key_down(pDev, key_code, KEY_POSTED); 100005b261ecSmrg } 100105b261ecSmrg else if (type == KeyRelease) { 10024202a189Smrg event->type = ET_KeyRelease; 10034202a189Smrg set_key_up(pDev, key_code, KEY_POSTED); 100405b261ecSmrg } 100505b261ecSmrg 100665b04b38Smrg clipValuators(pDev, &mask); 100705b261ecSmrg 100865b04b38Smrg set_valuators(pDev, event, &mask); 10094202a189Smrg 10104202a189Smrg return num_events; 101105b261ecSmrg} 101205b261ecSmrg 10134642e01fSmrg/** 10144642e01fSmrg * Initialize an event list and fill with 32 byte sized events. 10154642e01fSmrg * This event list is to be passed into GetPointerEvents() and 10164642e01fSmrg * GetKeyboardEvents(). 10174642e01fSmrg * 10184642e01fSmrg * @param num_events Number of elements in list. 10194642e01fSmrg */ 10204642e01fSmrgEventListPtr 10214642e01fSmrgInitEventList(int num_events) 10224642e01fSmrg{ 10234642e01fSmrg EventListPtr events; 10244642e01fSmrg int i; 10254642e01fSmrg 10264202a189Smrg events = (EventListPtr)calloc(num_events, sizeof(EventList)); 10274642e01fSmrg if (!events) 10284642e01fSmrg return NULL; 10294642e01fSmrg 10304642e01fSmrg for (i = 0; i < num_events; i++) 10314642e01fSmrg { 10324202a189Smrg events[i].evlen = sizeof(InternalEvent); 10334202a189Smrg events[i].event = calloc(1, sizeof(InternalEvent)); 10344642e01fSmrg if (!events[i].event) 10354642e01fSmrg { 10364642e01fSmrg /* rollback */ 10374642e01fSmrg while(i--) 10384202a189Smrg free(events[i].event); 10394202a189Smrg free(events); 10404642e01fSmrg events = NULL; 10414642e01fSmrg break; 10424642e01fSmrg } 10434642e01fSmrg } 10444642e01fSmrg 10454642e01fSmrg return events; 10464642e01fSmrg} 10474642e01fSmrg 10484642e01fSmrg/** 10494642e01fSmrg * Free an event list. 10504642e01fSmrg * 10514642e01fSmrg * @param list The list to be freed. 10524642e01fSmrg * @param num_events Number of elements in list. 10534642e01fSmrg */ 10544202a189Smrgvoid 10554642e01fSmrgFreeEventList(EventListPtr list, int num_events) 10564642e01fSmrg{ 10574642e01fSmrg if (!list) 10584642e01fSmrg return; 10594642e01fSmrg while(num_events--) 10604202a189Smrg free(list[num_events].event); 10614202a189Smrg free(list); 10624202a189Smrg} 10634202a189Smrg 10644202a189Smrgstatic void 106565b04b38SmrgtransformAbsolute(DeviceIntPtr dev, ValuatorMask *mask) 10664202a189Smrg{ 106765b04b38Smrg struct pixman_f_vector p; 10684202a189Smrg 10694202a189Smrg /* p' = M * p in homogeneous coordinates */ 107065b04b38Smrg p.v[0] = (valuator_mask_isset(mask, 0) ? valuator_mask_get(mask, 0) : 107165b04b38Smrg dev->last.valuators[0]); 107265b04b38Smrg p.v[1] = (valuator_mask_isset(mask, 1) ? valuator_mask_get(mask, 1) : 107365b04b38Smrg dev->last.valuators[1]); 107465b04b38Smrg p.v[2] = 1.0; 10754202a189Smrg 10764202a189Smrg pixman_f_transform_point(&dev->transform, &p); 10774202a189Smrg 107865b04b38Smrg if (lround(p.v[0]) != dev->last.valuators[0]) 107965b04b38Smrg valuator_mask_set(mask, 0, lround(p.v[0])); 108065b04b38Smrg if (lround(p.v[1]) != dev->last.valuators[1]) 108165b04b38Smrg valuator_mask_set(mask, 1, lround(p.v[1])); 10824642e01fSmrg} 108305b261ecSmrg 108405b261ecSmrg/** 108565b04b38Smrg * Generate a series of InternalEvents (filled into the EventList) 108665b04b38Smrg * representing pointer motion, or button presses. 108705b261ecSmrg * 108805b261ecSmrg * events is not NULL-terminated; the return value is the number of events. 108905b261ecSmrg * The DDX is responsible for allocating the event structure in the first 10904642e01fSmrg * place via InitEventList() and GetMaximumEventsNum(), and for freeing it. 10914642e01fSmrg * 10924642e01fSmrg * In the generated events rootX/Y will be in absolute screen coords and 10934642e01fSmrg * the valuator information in the absolute or relative device coords. 10944642e01fSmrg * 10954642e01fSmrg * last.valuators[x] of the device is always in absolute device coords. 10964642e01fSmrg * last.valuators[x] of the master device is in absolute screen coords. 10974642e01fSmrg * 10984642e01fSmrg * master->last.valuators[x] for x > 2 is undefined. 109905b261ecSmrg */ 11004202a189Smrgint 11014642e01fSmrgGetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, 110265b04b38Smrg int flags, const ValuatorMask *mask_in) { 11034642e01fSmrg int num_events = 1; 11044642e01fSmrg CARD32 ms; 11054202a189Smrg DeviceEvent *event; 11064202a189Smrg RawDeviceEvent *raw; 11074202a189Smrg int x = 0, y = 0, /* device coords */ 11084642e01fSmrg cx, cy; /* only screen coordinates */ 11094202a189Smrg float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac; 111005b261ecSmrg ScreenPtr scr = miPointerGetScreen(pDev); 111165b04b38Smrg ValuatorMask mask; 11124202a189Smrg 11134202a189Smrg /* refuse events from disabled devices */ 11144202a189Smrg if (!pDev->enabled) 11154202a189Smrg return 0; 111605b261ecSmrg 111765b04b38Smrg if (!scr) 111805b261ecSmrg return 0; 111905b261ecSmrg 112065b04b38Smrg switch (type) 112165b04b38Smrg { 112265b04b38Smrg case MotionNotify: 112365b04b38Smrg if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0) 112465b04b38Smrg return 0; 112565b04b38Smrg break; 112665b04b38Smrg case ButtonPress: 112765b04b38Smrg case ButtonRelease: 112865b04b38Smrg if (!pDev->button || !buttons) 112965b04b38Smrg return 0; 113065b04b38Smrg break; 113165b04b38Smrg default: 113265b04b38Smrg return 0; 113365b04b38Smrg } 113465b04b38Smrg 113565b04b38Smrg ms = GetTimeInMillis(); /* before pointer update to help precision */ 113665b04b38Smrg 11374202a189Smrg events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); 11384202a189Smrg 11394202a189Smrg raw = (RawDeviceEvent*)events->event; 11404202a189Smrg events++; 11414202a189Smrg num_events++; 114205b261ecSmrg 114365b04b38Smrg valuator_mask_copy(&mask, mask_in); 11444202a189Smrg 11454202a189Smrg init_raw(pDev, raw, ms, type, buttons); 114665b04b38Smrg set_raw_valuators(raw, &mask, raw->valuators.data_raw); 114705b261ecSmrg 11484642e01fSmrg if (flags & POINTER_ABSOLUTE) 11494642e01fSmrg { 11504642e01fSmrg if (flags & POINTER_SCREEN) /* valuators are in screen coords */ 11514642e01fSmrg { 115265b04b38Smrg int scaled; 115305b261ecSmrg 115465b04b38Smrg if (valuator_mask_isset(&mask, 0)) 115565b04b38Smrg { 115665b04b38Smrg scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 0), 115765b04b38Smrg 0.0, &x_frac, NULL, 115865b04b38Smrg pDev->valuator->axes + 0, 115965b04b38Smrg scr->width); 116065b04b38Smrg valuator_mask_set(&mask, 0, scaled); 116165b04b38Smrg } 116265b04b38Smrg if (valuator_mask_isset(&mask, 1)) 116365b04b38Smrg { 116465b04b38Smrg scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 1), 116565b04b38Smrg 0.0, &y_frac, NULL, 116665b04b38Smrg pDev->valuator->axes + 1, 116765b04b38Smrg scr->height); 116865b04b38Smrg valuator_mask_set(&mask, 1, scaled); 116965b04b38Smrg } 117005b261ecSmrg } 117105b261ecSmrg 117265b04b38Smrg transformAbsolute(pDev, &mask); 117365b04b38Smrg moveAbsolute(pDev, &x, &y, &mask); 11744642e01fSmrg } else { 11754202a189Smrg if (flags & POINTER_ACCELERATE) { 117665b04b38Smrg /* FIXME: Pointer acceleration only requires X and Y values. This 117765b04b38Smrg * should be converted to masked valuators. */ 117865b04b38Smrg int vals[2]; 117965b04b38Smrg vals[0] = valuator_mask_isset(&mask, 0) ? 118065b04b38Smrg valuator_mask_get(&mask, 0) : 0; 118165b04b38Smrg vals[1] = valuator_mask_isset(&mask, 1) ? 118265b04b38Smrg valuator_mask_get(&mask, 1) : 0; 118365b04b38Smrg accelPointer(pDev, 0, 2, vals, ms); 118465b04b38Smrg 118565b04b38Smrg if (valuator_mask_isset(&mask, 0)) 118665b04b38Smrg valuator_mask_set(&mask, 0, vals[0]); 118765b04b38Smrg if (valuator_mask_isset(&mask, 1)) 118865b04b38Smrg valuator_mask_set(&mask, 1, vals[1]); 118965b04b38Smrg 11904202a189Smrg /* The pointer acceleration code modifies the fractional part 11914202a189Smrg * in-place, so we need to extract this information first */ 11924202a189Smrg x_frac = pDev->last.remainder[0]; 11934202a189Smrg y_frac = pDev->last.remainder[1]; 11944202a189Smrg } 119565b04b38Smrg moveRelative(pDev, &x, &y, &mask); 119605b261ecSmrg } 119705b261ecSmrg 119865b04b38Smrg set_raw_valuators(raw, &mask, raw->valuators.data); 119905b261ecSmrg 12004202a189Smrg positionSprite(pDev, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac); 120165b04b38Smrg updateHistory(pDev, &mask, ms); 120205b261ecSmrg 12034642e01fSmrg /* Update the valuators with the true value sent to the client*/ 120465b04b38Smrg if (valuator_mask_isset(&mask, 0)) 120565b04b38Smrg valuator_mask_set(&mask, 0, x); 120665b04b38Smrg if (valuator_mask_isset(&mask, 1)) 120765b04b38Smrg valuator_mask_set(&mask, 1, y); 120805b261ecSmrg 120965b04b38Smrg clipValuators(pDev, &mask); 12104202a189Smrg 12114202a189Smrg event = (DeviceEvent*) events->event; 12124202a189Smrg init_event(pDev, event, ms); 121305b261ecSmrg 12144642e01fSmrg if (type == MotionNotify) { 12154202a189Smrg event->type = ET_Motion; 12164202a189Smrg event->detail.button = 0; 12174642e01fSmrg } 12184642e01fSmrg else { 12194202a189Smrg if (type == ButtonPress) { 12204202a189Smrg event->type = ET_ButtonPress; 12214202a189Smrg set_button_down(pDev, buttons, BUTTON_POSTED); 12224202a189Smrg } 12234202a189Smrg else if (type == ButtonRelease) { 12244202a189Smrg event->type = ET_ButtonRelease; 12254202a189Smrg set_button_up(pDev, buttons, BUTTON_POSTED); 12264202a189Smrg } 12274202a189Smrg event->detail.button = buttons; 12284642e01fSmrg } 122905b261ecSmrg 12304202a189Smrg event->root_x = cx; /* root_x/y always in screen coords */ 12314202a189Smrg event->root_y = cy; 12324202a189Smrg event->root_x_frac = cx_frac; 12334202a189Smrg event->root_y_frac = cy_frac; 123405b261ecSmrg 123565b04b38Smrg set_valuators(pDev, event, &mask); 123605b261ecSmrg 123705b261ecSmrg return num_events; 123805b261ecSmrg} 123905b261ecSmrg 124005b261ecSmrg 124105b261ecSmrg/** 124265b04b38Smrg * Generate ProximityIn/ProximityOut InternalEvents, accompanied by 124365b04b38Smrg * valuators. 124405b261ecSmrg * 124505b261ecSmrg * events is not NULL-terminated; the return value is the number of events. 124605b261ecSmrg * The DDX is responsible for allocating the event structure in the first 124705b261ecSmrg * place via GetMaximumEventsNum(), and for freeing it. 124805b261ecSmrg */ 12494202a189Smrgint 125065b04b38SmrgGetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, const ValuatorMask *mask_in) 125105b261ecSmrg{ 125265b04b38Smrg int num_events = 1, i; 12534202a189Smrg DeviceEvent *event; 125465b04b38Smrg ValuatorMask mask; 12554202a189Smrg 12564202a189Smrg /* refuse events from disabled devices */ 12574202a189Smrg if (!pDev->enabled) 12584202a189Smrg return 0; 125905b261ecSmrg 126005b261ecSmrg /* Sanity checks. */ 126165b04b38Smrg if ((type != ProximityIn && type != ProximityOut) || !mask_in) 126205b261ecSmrg return 0; 126305b261ecSmrg if (!pDev->valuator) 126405b261ecSmrg return 0; 126505b261ecSmrg 126665b04b38Smrg valuator_mask_copy(&mask, mask_in); 126765b04b38Smrg 126865b04b38Smrg /* ignore relative axes for proximity. */ 126965b04b38Smrg for (i = 0; i < valuator_mask_size(&mask); i++) 127065b04b38Smrg { 127165b04b38Smrg if (valuator_mask_isset(&mask, i) && 127265b04b38Smrg valuator_get_mode(pDev, i) == Relative) 127365b04b38Smrg valuator_mask_unset(&mask, i); 127465b04b38Smrg } 127565b04b38Smrg 127665b04b38Smrg /* FIXME: posting proximity events with relative valuators only results 127765b04b38Smrg * in an empty event, EventToXI() will fail to convert → no event sent 127865b04b38Smrg * to client. */ 127905b261ecSmrg 12804202a189Smrg events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); 12814642e01fSmrg 12824202a189Smrg event = (DeviceEvent *) events->event; 12834202a189Smrg init_event(pDev, event, GetTimeInMillis()); 12844202a189Smrg event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut; 128505b261ecSmrg 128665b04b38Smrg clipValuators(pDev, &mask); 128705b261ecSmrg 128865b04b38Smrg set_valuators(pDev, event, &mask); 12894202a189Smrg 129005b261ecSmrg return num_events; 129105b261ecSmrg} 129205b261ecSmrg 129305b261ecSmrg/** 129405b261ecSmrg * Synthesize a single motion event for the core pointer. 129505b261ecSmrg * 129605b261ecSmrg * Used in cursor functions, e.g. when cursor confinement changes, and we need 129705b261ecSmrg * to shift the pointer to get it inside the new bounds. 129805b261ecSmrg */ 129905b261ecSmrgvoid 13004642e01fSmrgPostSyntheticMotion(DeviceIntPtr pDev, 13014642e01fSmrg int x, 13024642e01fSmrg int y, 13034642e01fSmrg int screen, 13044642e01fSmrg unsigned long time) 130505b261ecSmrg{ 13064202a189Smrg DeviceEvent ev; 130705b261ecSmrg 130805b261ecSmrg#ifdef PANORAMIX 130905b261ecSmrg /* Translate back to the sprite screen since processInputProc 131005b261ecSmrg will translate from sprite screen to screen 0 upon reentry 131105b261ecSmrg to the DIX layer. */ 131205b261ecSmrg if (!noPanoramiXExtension) { 13134202a189Smrg x += screenInfo.screens[0]->x - screenInfo.screens[screen]->x; 13144202a189Smrg y += screenInfo.screens[0]->y - screenInfo.screens[screen]->y; 131505b261ecSmrg } 131605b261ecSmrg#endif 131705b261ecSmrg 13184202a189Smrg memset(&ev, 0, sizeof(DeviceEvent)); 13194202a189Smrg init_event(pDev, &ev, time); 13204202a189Smrg ev.root_x = x; 13214202a189Smrg ev.root_y = y; 13224202a189Smrg ev.type = ET_Motion; 13234202a189Smrg ev.time = time; 132405b261ecSmrg 13254202a189Smrg /* FIXME: MD/SD considerations? */ 13264202a189Smrg (*pDev->public.processInputProc)((InternalEvent*)&ev, pDev); 132705b261ecSmrg} 1328