getevents.c revision f7df2e56
105b261ecSmrg/* 205b261ecSmrg * Copyright © 2006 Nokia Corporation 305b261ecSmrg * Copyright © 2006-2007 Daniel Stone 44202a189Smrg * Copyright © 2008 Red Hat, Inc. 5f7df2e56Smrg * Copyright © 2011 The Chromium Authors 605b261ecSmrg * 705b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a 805b261ecSmrg * copy of this software and associated documentation files (the "Software"), 905b261ecSmrg * to deal in the Software without restriction, including without limitation 1005b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1105b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the 1205b261ecSmrg * Software is furnished to do so, subject to the following conditions: 1305b261ecSmrg * 1405b261ecSmrg * The above copyright notice and this permission notice (including the next 1505b261ecSmrg * paragraph) shall be included in all copies or substantial portions of the 1605b261ecSmrg * Software. 1705b261ecSmrg * 1805b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1905b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2005b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2105b261ecSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2205b261ecSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2305b261ecSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2405b261ecSmrg * DEALINGS IN THE SOFTWARE. 2505b261ecSmrg * 264202a189Smrg * Authors: Daniel Stone <daniel@fooishbar.org> 274202a189Smrg * Peter Hutterer <peter.hutterer@who-t.net> 2805b261ecSmrg */ 2905b261ecSmrg 3005b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 3105b261ecSmrg#include <dix-config.h> 3205b261ecSmrg#endif 3305b261ecSmrg 3405b261ecSmrg#include <X11/X.h> 3505b261ecSmrg#include <X11/keysym.h> 3605b261ecSmrg#include <X11/Xproto.h> 374202a189Smrg#include <math.h> 38f7df2e56Smrg#include <limits.h> 3905b261ecSmrg 4005b261ecSmrg#include "misc.h" 4105b261ecSmrg#include "resource.h" 4205b261ecSmrg#include "inputstr.h" 4305b261ecSmrg#include "scrnintstr.h" 4405b261ecSmrg#include "cursorstr.h" 4505b261ecSmrg#include "dixstruct.h" 4605b261ecSmrg#include "globals.h" 4705b261ecSmrg#include "dixevents.h" 4805b261ecSmrg#include "mipointer.h" 494202a189Smrg#include "eventstr.h" 504202a189Smrg#include "eventconvert.h" 5165b04b38Smrg#include "inpututils.h" 52f7df2e56Smrg#include "mi.h" 53f7df2e56Smrg#include "windowstr.h" 5405b261ecSmrg 5505b261ecSmrg#include <X11/extensions/XKBproto.h> 564202a189Smrg#include "xkbsrv.h" 5705b261ecSmrg 5805b261ecSmrg#ifdef PANORAMIX 5905b261ecSmrg#include "panoramiX.h" 6005b261ecSmrg#include "panoramiXsrv.h" 6105b261ecSmrg#endif 6205b261ecSmrg 6305b261ecSmrg#include <X11/extensions/XI.h> 64f7df2e56Smrg#include <X11/extensions/XI2.h> 6505b261ecSmrg#include <X11/extensions/XIproto.h> 664202a189Smrg#include <pixman.h> 6705b261ecSmrg#include "exglobals.h" 6805b261ecSmrg#include "exevents.h" 6905b261ecSmrg#include "extnsionst.h" 70f7df2e56Smrg#include "listdev.h" /* for sizing up DeviceClassesChangedEvent */ 71f7df2e56Smrg#include "probes.h" 7205b261ecSmrg 7305b261ecSmrg/* Number of motion history events to store. */ 7405b261ecSmrg#define MOTION_HISTORY_SIZE 256 7505b261ecSmrg 76f7df2e56Smrg/** 77f7df2e56Smrg * InputEventList is the storage for input events generated by 78f7df2e56Smrg * QueuePointerEvents, QueueKeyboardEvents, and QueueProximityEvents. 79f7df2e56Smrg * This list is allocated on startup by the DIX. 804642e01fSmrg */ 81f7df2e56SmrgInternalEvent *InputEventList = NULL; 8205b261ecSmrg 8305b261ecSmrg/** 8405b261ecSmrg * Pick some arbitrary size for Xi motion history. 8505b261ecSmrg */ 864202a189Smrgint 8705b261ecSmrgGetMotionHistorySize(void) 8805b261ecSmrg{ 8905b261ecSmrg return MOTION_HISTORY_SIZE; 9005b261ecSmrg} 9105b261ecSmrg 924202a189Smrgvoid 934202a189Smrgset_button_down(DeviceIntPtr pDev, int button, int type) 9405b261ecSmrg{ 954202a189Smrg if (type == BUTTON_PROCESSED) 964202a189Smrg SetBit(pDev->button->down, button); 974202a189Smrg else 984202a189Smrg SetBit(pDev->button->postdown, button); 9905b261ecSmrg} 10005b261ecSmrg 1014202a189Smrgvoid 1024202a189Smrgset_button_up(DeviceIntPtr pDev, int button, int type) 10305b261ecSmrg{ 1044202a189Smrg if (type == BUTTON_PROCESSED) 1054202a189Smrg ClearBit(pDev->button->down, button); 1064202a189Smrg else 1074202a189Smrg ClearBit(pDev->button->postdown, button); 10805b261ecSmrg} 10905b261ecSmrg 1104202a189SmrgBool 1114202a189Smrgbutton_is_down(DeviceIntPtr pDev, int button, int type) 1124202a189Smrg{ 1131b684552Smrg Bool ret = FALSE; 1144202a189Smrg 1154202a189Smrg if (type & BUTTON_PROCESSED) 1161b684552Smrg ret = ret || BitIsOn(pDev->button->down, button); 1174202a189Smrg if (type & BUTTON_POSTED) 1181b684552Smrg ret = ret || BitIsOn(pDev->button->postdown, button); 1194202a189Smrg 1204202a189Smrg return ret; 1214202a189Smrg} 1224202a189Smrg 1234202a189Smrgvoid 1244202a189Smrgset_key_down(DeviceIntPtr pDev, int key_code, int type) 12505b261ecSmrg{ 1264202a189Smrg if (type == KEY_PROCESSED) 1274202a189Smrg SetBit(pDev->key->down, key_code); 1284202a189Smrg else 1294202a189Smrg SetBit(pDev->key->postdown, key_code); 1304202a189Smrg} 1314202a189Smrg 1324202a189Smrgvoid 1334202a189Smrgset_key_up(DeviceIntPtr pDev, int key_code, int type) 1344202a189Smrg{ 1354202a189Smrg if (type == KEY_PROCESSED) 1364202a189Smrg ClearBit(pDev->key->down, key_code); 1374202a189Smrg else 1384202a189Smrg ClearBit(pDev->key->postdown, key_code); 1394202a189Smrg} 1404202a189Smrg 1414202a189SmrgBool 1424202a189Smrgkey_is_down(DeviceIntPtr pDev, int key_code, int type) 1434202a189Smrg{ 1441b684552Smrg Bool ret = FALSE; 1454202a189Smrg 1464202a189Smrg if (type & KEY_PROCESSED) 1471b684552Smrg ret = ret || BitIsOn(pDev->key->down, key_code); 1484202a189Smrg if (type & KEY_POSTED) 1491b684552Smrg ret = ret || BitIsOn(pDev->key->postdown, key_code); 1504202a189Smrg 1514202a189Smrg return ret; 15205b261ecSmrg} 15305b261ecSmrg 15405b261ecSmrgstatic Bool 15505b261ecSmrgkey_autorepeats(DeviceIntPtr pDev, int key_code) 15605b261ecSmrg{ 157f7df2e56Smrg return ! !(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] & 158f7df2e56Smrg (1 << (key_code & 7))); 15905b261ecSmrg} 16005b261ecSmrg 1614202a189Smrgstatic void 162f7df2e56Smrginit_touch_ownership(DeviceIntPtr dev, TouchOwnershipEvent *event, Time ms) 1634202a189Smrg{ 164f7df2e56Smrg memset(event, 0, sizeof(TouchOwnershipEvent)); 1654202a189Smrg event->header = ET_Internal; 166f7df2e56Smrg event->type = ET_TouchOwnership; 167f7df2e56Smrg event->length = sizeof(TouchOwnershipEvent); 1684202a189Smrg event->time = ms; 1694202a189Smrg event->deviceid = dev->id; 1704202a189Smrg} 1714202a189Smrg 1724202a189Smrgstatic void 1734202a189Smrginit_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail) 1744202a189Smrg{ 1754202a189Smrg memset(event, 0, sizeof(RawDeviceEvent)); 1764202a189Smrg event->header = ET_Internal; 1774202a189Smrg event->length = sizeof(RawDeviceEvent); 178f7df2e56Smrg switch (type) { 179f7df2e56Smrg case MotionNotify: 180f7df2e56Smrg event->type = ET_RawMotion; 181f7df2e56Smrg break; 182f7df2e56Smrg case ButtonPress: 183f7df2e56Smrg event->type = ET_RawButtonPress; 184f7df2e56Smrg break; 185f7df2e56Smrg case ButtonRelease: 186f7df2e56Smrg event->type = ET_RawButtonRelease; 187f7df2e56Smrg break; 188f7df2e56Smrg case KeyPress: 189f7df2e56Smrg event->type = ET_RawKeyPress; 190f7df2e56Smrg break; 191f7df2e56Smrg case KeyRelease: 192f7df2e56Smrg event->type = ET_RawKeyRelease; 193f7df2e56Smrg break; 194f7df2e56Smrg case XI_TouchBegin: 195f7df2e56Smrg event->type = ET_RawTouchBegin; 196f7df2e56Smrg break; 197f7df2e56Smrg case XI_TouchUpdate: 198f7df2e56Smrg event->type = ET_RawTouchUpdate; 199f7df2e56Smrg break; 200f7df2e56Smrg case XI_TouchEnd: 201f7df2e56Smrg event->type = ET_RawTouchEnd; 202f7df2e56Smrg break; 203f7df2e56Smrg } 2044202a189Smrg event->time = ms; 2054202a189Smrg event->deviceid = dev->id; 2064202a189Smrg event->sourceid = dev->id; 2074202a189Smrg event->detail.button = detail; 2084202a189Smrg} 2094202a189Smrg 2104202a189Smrgstatic void 211f7df2e56Smrgset_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, 212f7df2e56Smrg BOOL use_unaccel, double *data) 2134202a189Smrg{ 2144202a189Smrg int i; 2154202a189Smrg 216f7df2e56Smrg use_unaccel = use_unaccel && valuator_mask_has_unaccelerated(mask); 217f7df2e56Smrg 218f7df2e56Smrg for (i = 0; i < valuator_mask_size(mask); i++) { 219f7df2e56Smrg if (valuator_mask_isset(mask, i)) { 220f7df2e56Smrg double v; 221f7df2e56Smrg 22265b04b38Smrg SetBit(event->valuators.mask, i); 223f7df2e56Smrg 224f7df2e56Smrg if (use_unaccel) 225f7df2e56Smrg v = valuator_mask_get_unaccelerated(mask, i); 226f7df2e56Smrg else 227f7df2e56Smrg v = valuator_mask_get_double(mask, i); 228f7df2e56Smrg 229f7df2e56Smrg data[i] = v; 23065b04b38Smrg } 23165b04b38Smrg } 2324202a189Smrg} 2334202a189Smrg 2344202a189Smrgstatic void 235f7df2e56Smrgset_valuators(DeviceIntPtr dev, DeviceEvent *event, ValuatorMask *mask) 2364202a189Smrg{ 2374202a189Smrg int i; 2384202a189Smrg 23965b04b38Smrg /* Set the data to the previous value for unset absolute axes. The values 24065b04b38Smrg * may be used when sent as part of an XI 1.x valuator event. */ 241f7df2e56Smrg for (i = 0; i < valuator_mask_size(mask); i++) { 242f7df2e56Smrg if (valuator_mask_isset(mask, i)) { 24365b04b38Smrg SetBit(event->valuators.mask, i); 24465b04b38Smrg if (valuator_get_mode(dev, i) == Absolute) 24565b04b38Smrg SetBit(event->valuators.mode, i); 246f7df2e56Smrg event->valuators.data[i] = valuator_mask_get_double(mask, i); 24765b04b38Smrg } 248f7df2e56Smrg else 24965b04b38Smrg event->valuators.data[i] = dev->valuator->axisVal[i]; 2504202a189Smrg } 2514202a189Smrg} 2524202a189Smrg 2534202a189Smrgvoid 254f7df2e56SmrgCreateClassesChangedEvent(InternalEvent *event, 255f7df2e56Smrg DeviceIntPtr master, DeviceIntPtr slave, int flags) 2564202a189Smrg{ 2574202a189Smrg int i; 2584202a189Smrg DeviceChangedEvent *dce; 2594202a189Smrg CARD32 ms = GetTimeInMillis(); 2604202a189Smrg 261f7df2e56Smrg dce = &event->changed_event; 2624202a189Smrg memset(dce, 0, sizeof(DeviceChangedEvent)); 2634202a189Smrg dce->deviceid = slave->id; 264f7df2e56Smrg dce->masterid = master ? master->id : 0; 2654202a189Smrg dce->header = ET_Internal; 2664202a189Smrg dce->length = sizeof(DeviceChangedEvent); 2674202a189Smrg dce->type = ET_DeviceChanged; 2684202a189Smrg dce->time = ms; 269f7df2e56Smrg dce->flags = flags; 2704202a189Smrg dce->sourceid = slave->id; 2714202a189Smrg 272f7df2e56Smrg if (slave->button) { 2734202a189Smrg dce->buttons.num_buttons = slave->button->numButtons; 2744202a189Smrg for (i = 0; i < dce->buttons.num_buttons; i++) 2754202a189Smrg dce->buttons.names[i] = slave->button->labels[i]; 2764202a189Smrg } 277f7df2e56Smrg if (slave->valuator) { 2784202a189Smrg dce->num_valuators = slave->valuator->numAxes; 279f7df2e56Smrg for (i = 0; i < dce->num_valuators; i++) { 2804202a189Smrg dce->valuators[i].min = slave->valuator->axes[i].min_value; 2814202a189Smrg dce->valuators[i].max = slave->valuator->axes[i].max_value; 2824202a189Smrg dce->valuators[i].resolution = slave->valuator->axes[i].resolution; 28365b04b38Smrg dce->valuators[i].mode = slave->valuator->axes[i].mode; 2844202a189Smrg dce->valuators[i].name = slave->valuator->axes[i].label; 285f7df2e56Smrg dce->valuators[i].scroll = slave->valuator->axes[i].scroll; 286f7df2e56Smrg dce->valuators[i].value = slave->valuator->axisVal[i]; 2874202a189Smrg } 2884202a189Smrg } 289f7df2e56Smrg if (slave->key) { 2904202a189Smrg dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code; 2914202a189Smrg dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code; 2924202a189Smrg } 2934202a189Smrg} 2944202a189Smrg 2954642e01fSmrg/** 2964642e01fSmrg * Rescale the coord between the two axis ranges. 2974642e01fSmrg */ 298f7df2e56Smrgstatic double 299f7df2e56SmrgrescaleValuatorAxis(double coord, AxisInfoPtr from, AxisInfoPtr to, 300f7df2e56Smrg double defmin, double defmax) 3014642e01fSmrg{ 302f7df2e56Smrg double fmin = defmin, fmax = defmax; 303f7df2e56Smrg double tmin = defmin, tmax = defmax; 3044642e01fSmrg 305f7df2e56Smrg if (from && from->min_value < from->max_value) { 3064642e01fSmrg fmin = from->min_value; 307f7df2e56Smrg fmax = from->max_value + 1; 3084642e01fSmrg } 309f7df2e56Smrg if (to && to->min_value < to->max_value) { 3104642e01fSmrg tmin = to->min_value; 311f7df2e56Smrg tmax = to->max_value + 1; 3124642e01fSmrg } 3134642e01fSmrg 314f7df2e56Smrg if (fmin == tmin && fmax == tmax) 3154642e01fSmrg return coord; 3164642e01fSmrg 317f7df2e56Smrg if (fmax == fmin) /* avoid division by 0 */ 318f7df2e56Smrg return 0.0; 3194642e01fSmrg 320f7df2e56Smrg return (coord - fmin) * (tmax - tmin) / (fmax - fmin) + tmin; 3214642e01fSmrg} 3224642e01fSmrg 3234642e01fSmrg/** 3244642e01fSmrg * Update all coordinates when changing to a different SD 3254642e01fSmrg * to ensure that relative reporting will work as expected 3264642e01fSmrg * without loss of precision. 3274642e01fSmrg * 3284642e01fSmrg * pDev->last.valuators will be in absolute device coordinates after this 3294642e01fSmrg * function. 3304642e01fSmrg */ 3314642e01fSmrgstatic void 3324642e01fSmrgupdateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev) 3334642e01fSmrg{ 3344642e01fSmrg int i; 3354642e01fSmrg DeviceIntPtr lastSlave; 3364642e01fSmrg 337f7df2e56Smrg /* master->last.valuators[0]/[1] is in desktop-wide coords and the actual 3384642e01fSmrg * position of the pointer */ 3394642e01fSmrg pDev->last.valuators[0] = master->last.valuators[0]; 3404642e01fSmrg pDev->last.valuators[1] = master->last.valuators[1]; 3414642e01fSmrg 3424642e01fSmrg if (!pDev->valuator) 3434642e01fSmrg return; 3444642e01fSmrg 3454642e01fSmrg /* scale back to device coordinates */ 346f7df2e56Smrg if (pDev->valuator->numAxes > 0) { 347f7df2e56Smrg pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], 348f7df2e56Smrg NULL, 349f7df2e56Smrg pDev->valuator->axes + 0, 350f7df2e56Smrg screenInfo.x, 351f7df2e56Smrg screenInfo.width); 352f7df2e56Smrg } 353f7df2e56Smrg if (pDev->valuator->numAxes > 1) { 354f7df2e56Smrg pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], 355f7df2e56Smrg NULL, 356f7df2e56Smrg pDev->valuator->axes + 1, 357f7df2e56Smrg screenInfo.y, 358f7df2e56Smrg screenInfo.height); 359f7df2e56Smrg } 3604642e01fSmrg 3614642e01fSmrg /* calculate the other axis as well based on info from the old 3624642e01fSmrg * slave-device. If the old slave had less axes than this one, 3634642e01fSmrg * last.valuators is reset to 0. 3644642e01fSmrg */ 3654202a189Smrg if ((lastSlave = master->last.slave) && lastSlave->valuator) { 3664642e01fSmrg for (i = 2; i < pDev->valuator->numAxes; i++) { 367f7df2e56Smrg if (i >= lastSlave->valuator->numAxes) { 3684642e01fSmrg pDev->last.valuators[i] = 0; 369f7df2e56Smrg valuator_mask_set_double(pDev->last.scroll, i, 0); 370f7df2e56Smrg } 371f7df2e56Smrg else { 372f7df2e56Smrg double val = pDev->last.valuators[i]; 373f7df2e56Smrg 374f7df2e56Smrg val = rescaleValuatorAxis(val, lastSlave->valuator->axes + i, 375f7df2e56Smrg pDev->valuator->axes + i, 0, 0); 376f7df2e56Smrg pDev->last.valuators[i] = val; 377f7df2e56Smrg valuator_mask_set_double(pDev->last.scroll, i, val); 378f7df2e56Smrg } 3794642e01fSmrg } 3804642e01fSmrg } 3814642e01fSmrg 3824642e01fSmrg} 3834642e01fSmrg 38405b261ecSmrg/** 38505b261ecSmrg * Allocate the motion history buffer. 38605b261ecSmrg */ 3874202a189Smrgvoid 38805b261ecSmrgAllocateMotionHistory(DeviceIntPtr pDev) 38905b261ecSmrg{ 3904642e01fSmrg int size; 391f7df2e56Smrg 3924202a189Smrg free(pDev->valuator->motion); 39305b261ecSmrg 39405b261ecSmrg if (pDev->valuator->numMotionEvents < 1) 39505b261ecSmrg return; 39605b261ecSmrg 3974642e01fSmrg /* An MD must have a motion history size large enough to keep all 3984642e01fSmrg * potential valuators, plus the respective range of the valuators. 3994642e01fSmrg * 3 * INT32 for (min_val, max_val, curr_val)) 4004642e01fSmrg */ 4014202a189Smrg if (IsMaster(pDev)) 4024642e01fSmrg size = sizeof(INT32) * 3 * MAX_VALUATORS; 40365b04b38Smrg else { 40465b04b38Smrg ValuatorClassPtr v = pDev->valuator; 40565b04b38Smrg int numAxes; 406f7df2e56Smrg 40765b04b38Smrg /* XI1 doesn't understand mixed mode devices */ 40865b04b38Smrg for (numAxes = 0; numAxes < v->numAxes; numAxes++) 40965b04b38Smrg if (valuator_get_mode(pDev, numAxes) != valuator_get_mode(pDev, 0)) 41065b04b38Smrg break; 41165b04b38Smrg size = sizeof(INT32) * numAxes; 41265b04b38Smrg } 4134642e01fSmrg 4144642e01fSmrg size += sizeof(Time); 4154642e01fSmrg 4164202a189Smrg pDev->valuator->motion = calloc(pDev->valuator->numMotionEvents, size); 41705b261ecSmrg pDev->valuator->first_motion = 0; 41805b261ecSmrg pDev->valuator->last_motion = 0; 4194642e01fSmrg if (!pDev->valuator->motion) 4204642e01fSmrg ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n", 421f7df2e56Smrg pDev->name, size * pDev->valuator->numMotionEvents); 42205b261ecSmrg} 42305b261ecSmrg 42405b261ecSmrg/** 42505b261ecSmrg * Dump the motion history between start and stop into the supplied buffer. 42605b261ecSmrg * Only records the event for a given screen in theory, but in practice, we 42705b261ecSmrg * sort of ignore this. 4284642e01fSmrg * 4294642e01fSmrg * If core is set, we only generate x/y, in INT16, scaled to screen coords. 43005b261ecSmrg */ 4314202a189Smrgint 432f7df2e56SmrgGetMotionHistory(DeviceIntPtr pDev, xTimecoord ** buff, unsigned long start, 4334642e01fSmrg unsigned long stop, ScreenPtr pScreen, BOOL core) 43405b261ecSmrg{ 4354642e01fSmrg char *ibuff = NULL, *obuff; 43605b261ecSmrg int i = 0, ret = 0; 4374642e01fSmrg int j, coord; 43805b261ecSmrg Time current; 439f7df2e56Smrg 44005b261ecSmrg /* The size of a single motion event. */ 4414642e01fSmrg int size; 442f7df2e56Smrg AxisInfo from, *to; /* for scaling */ 443f7df2e56Smrg INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */ 4444642e01fSmrg INT16 *corebuf; 445f7df2e56Smrg AxisInfo core_axis = { 0 }; 44605b261ecSmrg 44705b261ecSmrg if (!pDev->valuator || !pDev->valuator->numMotionEvents) 44805b261ecSmrg return 0; 44905b261ecSmrg 4504642e01fSmrg if (core && !pScreen) 4514642e01fSmrg return 0; 4524642e01fSmrg 4534202a189Smrg if (IsMaster(pDev)) 4544642e01fSmrg size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time); 4554642e01fSmrg else 4564642e01fSmrg size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); 4574642e01fSmrg 4584202a189Smrg *buff = malloc(size * pDev->valuator->numMotionEvents); 4594642e01fSmrg if (!(*buff)) 4604642e01fSmrg return 0; 461f7df2e56Smrg obuff = (char *) *buff; 4624642e01fSmrg 46305b261ecSmrg for (i = pDev->valuator->first_motion; 46405b261ecSmrg i != pDev->valuator->last_motion; 46505b261ecSmrg i = (i + 1) % pDev->valuator->numMotionEvents) { 46605b261ecSmrg /* We index the input buffer by which element we're accessing, which 46705b261ecSmrg * is not monotonic, and the output buffer by how many events we've 46805b261ecSmrg * written so far. */ 46905b261ecSmrg ibuff = (char *) pDev->valuator->motion + (i * size); 47005b261ecSmrg memcpy(¤t, ibuff, sizeof(Time)); 47105b261ecSmrg 47205b261ecSmrg if (current > stop) { 47305b261ecSmrg return ret; 47405b261ecSmrg } 47505b261ecSmrg else if (current >= start) { 476f7df2e56Smrg if (core) { 477f7df2e56Smrg memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */ 4784642e01fSmrg 479f7df2e56Smrg icbuf = (INT32 *) (ibuff + sizeof(Time)); 480f7df2e56Smrg corebuf = (INT16 *) (obuff + sizeof(Time)); 4814642e01fSmrg 4824642e01fSmrg /* fetch x coordinate + range */ 4834642e01fSmrg memcpy(&from.min_value, icbuf++, sizeof(INT32)); 4844642e01fSmrg memcpy(&from.max_value, icbuf++, sizeof(INT32)); 4854642e01fSmrg memcpy(&coord, icbuf++, sizeof(INT32)); 4864642e01fSmrg 4874642e01fSmrg /* scale to screen coords */ 4884642e01fSmrg to = &core_axis; 4894642e01fSmrg to->max_value = pScreen->width; 490f7df2e56Smrg coord = 491f7df2e56Smrg rescaleValuatorAxis(coord, &from, to, 0, pScreen->width); 4924642e01fSmrg 4934642e01fSmrg memcpy(corebuf, &coord, sizeof(INT16)); 4944642e01fSmrg corebuf++; 4954642e01fSmrg 4964642e01fSmrg /* fetch y coordinate + range */ 4974642e01fSmrg memcpy(&from.min_value, icbuf++, sizeof(INT32)); 4984642e01fSmrg memcpy(&from.max_value, icbuf++, sizeof(INT32)); 4994642e01fSmrg memcpy(&coord, icbuf++, sizeof(INT32)); 5004642e01fSmrg 5014642e01fSmrg to->max_value = pScreen->height; 502f7df2e56Smrg coord = 503f7df2e56Smrg rescaleValuatorAxis(coord, &from, to, 0, pScreen->height); 5044642e01fSmrg memcpy(corebuf, &coord, sizeof(INT16)); 5054642e01fSmrg 506f7df2e56Smrg } 507f7df2e56Smrg else if (IsMaster(pDev)) { 508f7df2e56Smrg memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */ 5094642e01fSmrg 510f7df2e56Smrg ocbuf = (INT32 *) (obuff + sizeof(Time)); 511f7df2e56Smrg icbuf = (INT32 *) (ibuff + sizeof(Time)); 512f7df2e56Smrg for (j = 0; j < MAX_VALUATORS; j++) { 5134642e01fSmrg if (j >= pDev->valuator->numAxes) 5144642e01fSmrg break; 5154642e01fSmrg 5164642e01fSmrg /* fetch min/max/coordinate */ 5174642e01fSmrg memcpy(&from.min_value, icbuf++, sizeof(INT32)); 5184642e01fSmrg memcpy(&from.max_value, icbuf++, sizeof(INT32)); 5194642e01fSmrg memcpy(&coord, icbuf++, sizeof(INT32)); 5204642e01fSmrg 521f7df2e56Smrg to = (j < 522f7df2e56Smrg pDev->valuator->numAxes) ? &pDev->valuator-> 523f7df2e56Smrg axes[j] : NULL; 5244642e01fSmrg 5254642e01fSmrg /* x/y scaled to screen if no range is present */ 5264642e01fSmrg if (j == 0 && (from.max_value < from.min_value)) 5274642e01fSmrg from.max_value = pScreen->width; 5284642e01fSmrg else if (j == 1 && (from.max_value < from.min_value)) 5294642e01fSmrg from.max_value = pScreen->height; 5304642e01fSmrg 5314642e01fSmrg /* scale from stored range into current range */ 532f7df2e56Smrg coord = rescaleValuatorAxis(coord, &from, to, 0, 0); 5334642e01fSmrg memcpy(ocbuf, &coord, sizeof(INT32)); 5344642e01fSmrg ocbuf++; 5354642e01fSmrg } 536f7df2e56Smrg } 537f7df2e56Smrg else 5384642e01fSmrg memcpy(obuff, ibuff, size); 5394642e01fSmrg 5404642e01fSmrg /* don't advance by size here. size may be different to the 5414642e01fSmrg * actually written size if the MD has less valuators than MAX */ 5424642e01fSmrg if (core) 5434642e01fSmrg obuff += sizeof(INT32) + sizeof(Time); 5444642e01fSmrg else 545f7df2e56Smrg obuff += 546f7df2e56Smrg (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); 54705b261ecSmrg ret++; 54805b261ecSmrg } 54905b261ecSmrg } 55005b261ecSmrg 55105b261ecSmrg return ret; 55205b261ecSmrg} 55305b261ecSmrg 55405b261ecSmrg/** 55505b261ecSmrg * Update the motion history for a specific device, with the list of 55605b261ecSmrg * valuators. 5574642e01fSmrg * 5584642e01fSmrg * Layout of the history buffer: 5594642e01fSmrg * for SDs: [time] [val0] [val1] ... [valn] 5604642e01fSmrg * for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn] 5614642e01fSmrg * 56265b04b38Smrg * For events that have some valuators unset: 5634642e01fSmrg * min_val == max_val == val == 0. 56405b261ecSmrg */ 56505b261ecSmrgstatic void 56665b04b38SmrgupdateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask, 567f7df2e56Smrg double *valuators) 56805b261ecSmrg{ 56905b261ecSmrg char *buff = (char *) pDev->valuator->motion; 5704642e01fSmrg ValuatorClassPtr v; 5714642e01fSmrg int i; 57205b261ecSmrg 57305b261ecSmrg if (!pDev->valuator->numMotionEvents) 57405b261ecSmrg return; 57505b261ecSmrg 5764642e01fSmrg v = pDev->valuator; 577f7df2e56Smrg if (IsMaster(pDev)) { 5784642e01fSmrg buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) * 579f7df2e56Smrg v->last_motion; 5804642e01fSmrg 5814642e01fSmrg memcpy(buff, &ms, sizeof(Time)); 5824642e01fSmrg buff += sizeof(Time); 5834642e01fSmrg 5844642e01fSmrg memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS); 5854642e01fSmrg 586f7df2e56Smrg for (i = 0; i < v->numAxes; i++) { 587f7df2e56Smrg int val; 588f7df2e56Smrg 58965b04b38Smrg /* XI1 doesn't support mixed mode devices */ 59065b04b38Smrg if (valuator_get_mode(pDev, i) != valuator_get_mode(pDev, 0)) 5914642e01fSmrg break; 592f7df2e56Smrg if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) { 59365b04b38Smrg buff += 3 * sizeof(INT32); 59465b04b38Smrg continue; 59565b04b38Smrg } 5964642e01fSmrg memcpy(buff, &v->axes[i].min_value, sizeof(INT32)); 5974642e01fSmrg buff += sizeof(INT32); 5984642e01fSmrg memcpy(buff, &v->axes[i].max_value, sizeof(INT32)); 5994642e01fSmrg buff += sizeof(INT32); 600f7df2e56Smrg val = valuators[i]; 601f7df2e56Smrg memcpy(buff, &val, sizeof(INT32)); 6024642e01fSmrg buff += sizeof(INT32); 6034642e01fSmrg } 604f7df2e56Smrg } 605f7df2e56Smrg else { 6064642e01fSmrg 6074642e01fSmrg buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) * 60805b261ecSmrg pDev->valuator->last_motion; 60905b261ecSmrg 6104642e01fSmrg memcpy(buff, &ms, sizeof(Time)); 6114642e01fSmrg buff += sizeof(Time); 61205b261ecSmrg 6134642e01fSmrg memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes); 61405b261ecSmrg 615f7df2e56Smrg for (i = 0; i < MAX_VALUATORS; i++) { 616f7df2e56Smrg int val; 617f7df2e56Smrg 618f7df2e56Smrg if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) { 61965b04b38Smrg buff += sizeof(INT32); 62065b04b38Smrg continue; 62165b04b38Smrg } 622f7df2e56Smrg val = valuators[i]; 623f7df2e56Smrg memcpy(buff, &val, sizeof(INT32)); 62465b04b38Smrg buff += sizeof(INT32); 62565b04b38Smrg } 6264642e01fSmrg } 62705b261ecSmrg 6284642e01fSmrg pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) % 6294642e01fSmrg pDev->valuator->numMotionEvents; 63005b261ecSmrg /* If we're wrapping around, just keep the circular buffer going. */ 63105b261ecSmrg if (pDev->valuator->first_motion == pDev->valuator->last_motion) 63205b261ecSmrg pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) % 633f7df2e56Smrg pDev->valuator->numMotionEvents; 63405b261ecSmrg 63505b261ecSmrg return; 63605b261ecSmrg} 63705b261ecSmrg 63805b261ecSmrg/** 639f7df2e56Smrg * Returns the maximum number of events GetKeyboardEvents 640f7df2e56Smrg * and GetPointerEvents will ever return. 64105b261ecSmrg * 6424642e01fSmrg * This MUST be absolutely constant, from init until exit. 64305b261ecSmrg */ 6444202a189Smrgint 645f7df2e56SmrgGetMaximumEventsNum(void) 646f7df2e56Smrg{ 6474202a189Smrg /* One raw event 6484202a189Smrg * One device event 6494202a189Smrg * One possible device changed event 650f7df2e56Smrg * Lots of possible separate button scroll events (horiz + vert) 651f7df2e56Smrg * Lots of possible separate raw button scroll events (horiz + vert) 6524202a189Smrg */ 653f7df2e56Smrg return 100; 65405b261ecSmrg} 65505b261ecSmrg 65605b261ecSmrg/** 65705b261ecSmrg * Clip an axis to its bounds, which are declared in the call to 65805b261ecSmrg * InitValuatorAxisClassStruct. 65905b261ecSmrg */ 66005b261ecSmrgstatic void 661f7df2e56SmrgclipAxis(DeviceIntPtr pDev, int axisNum, double *val) 66205b261ecSmrg{ 6634202a189Smrg AxisInfoPtr axis; 6644202a189Smrg 6654202a189Smrg if (axisNum >= pDev->valuator->numAxes) 6664202a189Smrg return; 6674202a189Smrg 6684202a189Smrg axis = pDev->valuator->axes + axisNum; 6694642e01fSmrg 6704642e01fSmrg /* If a value range is defined, clip. If not, do nothing */ 6714642e01fSmrg if (axis->max_value <= axis->min_value) 6724642e01fSmrg return; 6734642e01fSmrg 6744642e01fSmrg if (*val < axis->min_value) 6754642e01fSmrg *val = axis->min_value; 6764642e01fSmrg if (*val > axis->max_value) 6774642e01fSmrg *val = axis->max_value; 67805b261ecSmrg} 67905b261ecSmrg 68005b261ecSmrg/** 68105b261ecSmrg * Clip every axis in the list of valuators to its bounds. 68205b261ecSmrg */ 68305b261ecSmrgstatic void 68465b04b38SmrgclipValuators(DeviceIntPtr pDev, ValuatorMask *mask) 68505b261ecSmrg{ 68605b261ecSmrg int i; 68705b261ecSmrg 68865b04b38Smrg for (i = 0; i < valuator_mask_size(mask); i++) 689f7df2e56Smrg if (valuator_mask_isset(mask, i)) { 690f7df2e56Smrg double val = valuator_mask_get_double(mask, i); 691f7df2e56Smrg 69265b04b38Smrg clipAxis(pDev, i, &val); 693f7df2e56Smrg valuator_mask_set_double(mask, i, val); 69465b04b38Smrg } 69505b261ecSmrg} 69605b261ecSmrg 6974642e01fSmrg/** 6984642e01fSmrg * Create the DCCE event (does not update the master's device state yet, this 6994642e01fSmrg * is done in the event processing). 7004642e01fSmrg * Pull in the coordinates from the MD if necessary. 7014642e01fSmrg * 702f7df2e56Smrg * @param events Pointer to a pre-allocated event array. 7034642e01fSmrg * @param dev The slave device that generated an event. 7044202a189Smrg * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT 7054642e01fSmrg * @param num_events The current number of events, returns the number of 7064642e01fSmrg * events if a DCCE was generated. 7074642e01fSmrg * @return The updated @events pointer. 7084642e01fSmrg */ 709f7df2e56SmrgInternalEvent * 710f7df2e56SmrgUpdateFromMaster(InternalEvent *events, DeviceIntPtr dev, int type, 711f7df2e56Smrg int *num_events) 7124642e01fSmrg{ 7134202a189Smrg DeviceIntPtr master; 7144202a189Smrg 715f7df2e56Smrg master = 716f7df2e56Smrg GetMaster(dev, 717f7df2e56Smrg (type & DEVCHANGE_POINTER_EVENT) ? MASTER_POINTER : 718f7df2e56Smrg MASTER_KEYBOARD); 7194202a189Smrg 720f7df2e56Smrg if (master && master->last.slave != dev) { 721f7df2e56Smrg CreateClassesChangedEvent(events, master, dev, 722f7df2e56Smrg type | DEVCHANGE_SLAVE_SWITCH); 723f7df2e56Smrg if (IsPointerDevice(master)) { 7244202a189Smrg updateSlaveDeviceCoords(master, dev); 7254202a189Smrg master->last.numValuators = dev->last.numValuators; 7264202a189Smrg } 7274202a189Smrg master->last.slave = dev; 7284202a189Smrg (*num_events)++; 7294202a189Smrg events++; 7304642e01fSmrg } 7314642e01fSmrg return events; 7324642e01fSmrg} 7334642e01fSmrg 7344642e01fSmrg/** 7354642e01fSmrg * Move the device's pointer to the position given in the valuators. 7364642e01fSmrg * 737f7df2e56Smrg * @param dev The device whose pointer is to be moved. 738f7df2e56Smrg * @param mask Valuator data for this event. 7394642e01fSmrg */ 7404642e01fSmrgstatic void 741f7df2e56SmrgclipAbsolute(DeviceIntPtr dev, ValuatorMask *mask) 7424642e01fSmrg{ 7434642e01fSmrg int i; 7444642e01fSmrg 745f7df2e56Smrg for (i = 0; i < valuator_mask_size(mask); i++) { 746f7df2e56Smrg double val; 7474642e01fSmrg 748f7df2e56Smrg if (!valuator_mask_isset(mask, i)) 749f7df2e56Smrg continue; 750f7df2e56Smrg val = valuator_mask_get_double(mask, i); 751f7df2e56Smrg clipAxis(dev, i, &val); 752f7df2e56Smrg valuator_mask_set_double(mask, i, val); 753f7df2e56Smrg } 754f7df2e56Smrg} 755f7df2e56Smrg 756f7df2e56Smrgstatic void 757f7df2e56Smrgadd_to_scroll_valuator(DeviceIntPtr dev, ValuatorMask *mask, int valuator, double value) 758f7df2e56Smrg{ 759f7df2e56Smrg double v; 7604642e01fSmrg 761f7df2e56Smrg if (!valuator_mask_fetch_double(mask, valuator, &v)) 762f7df2e56Smrg return; 7634642e01fSmrg 764f7df2e56Smrg /* protect against scrolling overflow. INT_MAX for double, because 765f7df2e56Smrg * we'll eventually write this as 32.32 fixed point */ 766f7df2e56Smrg if ((value > 0 && v > INT_MAX - value) || (value < 0 && v < INT_MIN - value)) { 767f7df2e56Smrg v = 0; 768f7df2e56Smrg 769f7df2e56Smrg /* reset last.scroll to avoid a button storm */ 770f7df2e56Smrg valuator_mask_set_double(dev->last.scroll, valuator, 0); 7714642e01fSmrg } 772f7df2e56Smrg else 773f7df2e56Smrg v += value; 774f7df2e56Smrg 775f7df2e56Smrg valuator_mask_set_double(mask, valuator, v); 776f7df2e56Smrg} 777f7df2e56Smrg 778f7df2e56Smrg 779f7df2e56Smrgstatic void 780f7df2e56Smrgscale_for_device_resolution(DeviceIntPtr dev, ValuatorMask *mask) 781f7df2e56Smrg{ 782f7df2e56Smrg double y; 783f7df2e56Smrg ValuatorClassPtr v = dev->valuator; 784f7df2e56Smrg int xrange = v->axes[0].max_value - v->axes[0].min_value + 1; 785f7df2e56Smrg int yrange = v->axes[1].max_value - v->axes[1].min_value + 1; 786f7df2e56Smrg 787f7df2e56Smrg double screen_ratio = 1.0 * screenInfo.width/screenInfo.height; 788f7df2e56Smrg double device_ratio = 1.0 * xrange/yrange; 789f7df2e56Smrg double resolution_ratio = 1.0; 790f7df2e56Smrg double ratio; 791f7df2e56Smrg 792f7df2e56Smrg if (!valuator_mask_fetch_double(mask, 1, &y)) 793f7df2e56Smrg return; 794f7df2e56Smrg 795f7df2e56Smrg if (v->axes[0].resolution != 0 && v->axes[1].resolution != 0) 796f7df2e56Smrg resolution_ratio = 1.0 * v->axes[0].resolution/v->axes[1].resolution; 797f7df2e56Smrg 798f7df2e56Smrg ratio = device_ratio/resolution_ratio/screen_ratio; 799f7df2e56Smrg valuator_mask_set_double(mask, 1, y / ratio); 8004642e01fSmrg} 8014642e01fSmrg 8024642e01fSmrg/** 8034642e01fSmrg * Move the device's pointer by the values given in @valuators. 8044642e01fSmrg * 805f7df2e56Smrg * @param dev The device whose pointer is to be moved. 806f7df2e56Smrg * @param[in,out] mask Valuator data for this event, modified in-place. 8074642e01fSmrg */ 8084642e01fSmrgstatic void 809f7df2e56SmrgmoveRelative(DeviceIntPtr dev, int flags, ValuatorMask *mask) 8104642e01fSmrg{ 8114642e01fSmrg int i; 812f7df2e56Smrg Bool clip_xy = IsMaster(dev) || !IsFloating(dev); 813f7df2e56Smrg ValuatorClassPtr v = dev->valuator; 814f7df2e56Smrg 815f7df2e56Smrg /* for abs devices in relative mode, we've just scaled wrong, since we 816f7df2e56Smrg mapped the device's shape into the screen shape. Undo this. */ 817f7df2e56Smrg if ((flags & POINTER_ABSOLUTE) == 0 && v && v->numAxes > 1 && 818f7df2e56Smrg v->axes[0].min_value < v->axes[0].max_value && 819f7df2e56Smrg v->axes[1].min_value < v->axes[1].max_value) { 820f7df2e56Smrg scale_for_device_resolution(dev, mask); 821f7df2e56Smrg } 8224642e01fSmrg 823f7df2e56Smrg /* calc other axes, clip, drop back into valuators */ 824f7df2e56Smrg for (i = 0; i < valuator_mask_size(mask); i++) { 825f7df2e56Smrg double val = dev->last.valuators[i]; 8264642e01fSmrg 827f7df2e56Smrg if (!valuator_mask_isset(mask, i)) 828f7df2e56Smrg continue; 8294642e01fSmrg 830f7df2e56Smrg add_to_scroll_valuator(dev, mask, i, val); 8314642e01fSmrg 832f7df2e56Smrg /* x & y need to go over the limits to cross screens if the SD 833f7df2e56Smrg * isn't currently attached; otherwise, clip to screen bounds. */ 834f7df2e56Smrg if (valuator_get_mode(dev, i) == Absolute && 835f7df2e56Smrg ((i != 0 && i != 1) || clip_xy)) { 836f7df2e56Smrg val = valuator_mask_get_double(mask, i); 837f7df2e56Smrg clipAxis(dev, i, &val); 838f7df2e56Smrg valuator_mask_set_double(mask, i, val); 83965b04b38Smrg } 8404642e01fSmrg } 8414642e01fSmrg} 8424642e01fSmrg 8434642e01fSmrg/** 8444642e01fSmrg * Accelerate the data in valuators based on the device's acceleration scheme. 8454642e01fSmrg * 8464642e01fSmrg * @param dev The device which's pointer is to be moved. 847f7df2e56Smrg * @param valuators Valuator mask 8484642e01fSmrg * @param ms Current time. 8494642e01fSmrg */ 8504642e01fSmrgstatic void 851f7df2e56SmrgaccelPointer(DeviceIntPtr dev, ValuatorMask *valuators, CARD32 ms) 8524642e01fSmrg{ 8534642e01fSmrg if (dev->valuator->accelScheme.AccelSchemeProc) 854f7df2e56Smrg dev->valuator->accelScheme.AccelSchemeProc(dev, valuators, ms); 855f7df2e56Smrg} 856f7df2e56Smrg 857f7df2e56Smrg/** 858f7df2e56Smrg * Scale from absolute screen coordinates to absolute coordinates in the 859f7df2e56Smrg * device's coordinate range. 860f7df2e56Smrg * 861f7df2e56Smrg * @param dev The device to scale for. 862f7df2e56Smrg * @param[in, out] mask The mask in desktop/screen coordinates, modified in place 863f7df2e56Smrg * to contain device coordinate range. 864f7df2e56Smrg * @param flags If POINTER_SCREEN is set, mask is in per-screen coordinates. 865f7df2e56Smrg * Otherwise, mask is in desktop coords. 866f7df2e56Smrg */ 867f7df2e56Smrgstatic void 868f7df2e56Smrgscale_from_screen(DeviceIntPtr dev, ValuatorMask *mask, int flags) 869f7df2e56Smrg{ 870f7df2e56Smrg double scaled; 871f7df2e56Smrg ScreenPtr scr = miPointerGetScreen(dev); 872f7df2e56Smrg 873f7df2e56Smrg if (valuator_mask_isset(mask, 0)) { 874f7df2e56Smrg scaled = valuator_mask_get_double(mask, 0); 875f7df2e56Smrg if (flags & POINTER_SCREEN) 876f7df2e56Smrg scaled += scr->x; 877f7df2e56Smrg scaled = rescaleValuatorAxis(scaled, 878f7df2e56Smrg NULL, dev->valuator->axes + 0, 879f7df2e56Smrg screenInfo.x, screenInfo.width); 880f7df2e56Smrg valuator_mask_set_double(mask, 0, scaled); 881f7df2e56Smrg } 882f7df2e56Smrg if (valuator_mask_isset(mask, 1)) { 883f7df2e56Smrg scaled = valuator_mask_get_double(mask, 1); 884f7df2e56Smrg if (flags & POINTER_SCREEN) 885f7df2e56Smrg scaled += scr->y; 886f7df2e56Smrg scaled = rescaleValuatorAxis(scaled, 887f7df2e56Smrg NULL, dev->valuator->axes + 1, 888f7df2e56Smrg screenInfo.y, screenInfo.height); 889f7df2e56Smrg valuator_mask_set_double(mask, 1, scaled); 890f7df2e56Smrg } 891f7df2e56Smrg} 892f7df2e56Smrg 893f7df2e56Smrg/** 894f7df2e56Smrg * Scale from (absolute) device to screen coordinates here, 895f7df2e56Smrg * 896f7df2e56Smrg * The coordinates provided are always absolute. see fill_pointer_events for 897f7df2e56Smrg * information on coordinate systems. 898f7df2e56Smrg * 899f7df2e56Smrg * @param dev The device to be moved. 900f7df2e56Smrg * @param mask Mask of axis values for this event 901f7df2e56Smrg * @param[out] devx x desktop-wide coordinate in device coordinate system 902f7df2e56Smrg * @param[out] devy y desktop-wide coordinate in device coordinate system 903f7df2e56Smrg * @param[out] screenx x coordinate in desktop coordinate system 904f7df2e56Smrg * @param[out] screeny y coordinate in desktop coordinate system 905f7df2e56Smrg */ 906f7df2e56Smrgstatic ScreenPtr 907f7df2e56Smrgscale_to_desktop(DeviceIntPtr dev, ValuatorMask *mask, 908f7df2e56Smrg double *devx, double *devy, double *screenx, double *screeny) 909f7df2e56Smrg{ 910f7df2e56Smrg ScreenPtr scr = miPointerGetScreen(dev); 911f7df2e56Smrg double x, y; 912f7df2e56Smrg 913f7df2e56Smrg BUG_WARN(dev->valuator && dev->valuator->numAxes < 2); 914f7df2e56Smrg if (!dev->valuator || dev->valuator->numAxes < 2) { 915f7df2e56Smrg /* if we have no axes, last.valuators must be in screen coords 916f7df2e56Smrg * anyway */ 917f7df2e56Smrg *devx = *screenx = dev->last.valuators[0]; 918f7df2e56Smrg *devy = *screeny = dev->last.valuators[1]; 919f7df2e56Smrg return scr; 920f7df2e56Smrg } 921f7df2e56Smrg 922f7df2e56Smrg if (valuator_mask_isset(mask, 0)) 923f7df2e56Smrg x = valuator_mask_get_double(mask, 0); 924f7df2e56Smrg else 925f7df2e56Smrg x = dev->last.valuators[0]; 926f7df2e56Smrg if (valuator_mask_isset(mask, 1)) 927f7df2e56Smrg y = valuator_mask_get_double(mask, 1); 928f7df2e56Smrg else 929f7df2e56Smrg y = dev->last.valuators[1]; 930f7df2e56Smrg 931f7df2e56Smrg /* scale x&y to desktop coordinates */ 932f7df2e56Smrg *screenx = rescaleValuatorAxis(x, dev->valuator->axes + 0, NULL, 933f7df2e56Smrg screenInfo.x, screenInfo.width); 934f7df2e56Smrg *screeny = rescaleValuatorAxis(y, dev->valuator->axes + 1, NULL, 935f7df2e56Smrg screenInfo.y, screenInfo.height); 936f7df2e56Smrg 937f7df2e56Smrg *devx = x; 938f7df2e56Smrg *devy = y; 939f7df2e56Smrg 940f7df2e56Smrg return scr; 9414642e01fSmrg} 9424642e01fSmrg 9434642e01fSmrg/** 9444642e01fSmrg * If we have HW cursors, this actually moves the visible sprite. If not, we 9454642e01fSmrg * just do all the screen crossing, etc. 9464642e01fSmrg * 947f7df2e56Smrg * We use the screen coordinates here, call miPointerSetPosition() and then 948f7df2e56Smrg * scale back into device coordinates (if needed). miPSP will change x/y if 949f7df2e56Smrg * the screen was crossed. 950f7df2e56Smrg * 951f7df2e56Smrg * The coordinates provided are always absolute. The parameter mode 952f7df2e56Smrg * specifies whether it was relative or absolute movement that landed us at 953f7df2e56Smrg * those coordinates. see fill_pointer_events for information on coordinate 954f7df2e56Smrg * systems. 9554642e01fSmrg * 9564642e01fSmrg * @param dev The device to be moved. 957f7df2e56Smrg * @param mode Movement mode (Absolute or Relative) 958f7df2e56Smrg * @param[out] mask Mask of axis values for this event, returns the 959f7df2e56Smrg * per-screen device coordinates after confinement 960f7df2e56Smrg * @param[in,out] devx x desktop-wide coordinate in device coordinate system 961f7df2e56Smrg * @param[in,out] devy y desktop-wide coordinate in device coordinate system 962f7df2e56Smrg * @param[in,out] screenx x coordinate in desktop coordinate system 963f7df2e56Smrg * @param[in,out] screeny y coordinate in desktop coordinate system 964f7df2e56Smrg * @param[out] nevents Number of barrier events added to events 965f7df2e56Smrg * @param[in,out] events List of events barrier events are added to 9664642e01fSmrg */ 967f7df2e56Smrgstatic ScreenPtr 968f7df2e56SmrgpositionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask, 969f7df2e56Smrg double *devx, double *devy, double *screenx, double *screeny, 970f7df2e56Smrg int *nevents, InternalEvent* events) 9714642e01fSmrg{ 972f7df2e56Smrg ScreenPtr scr = miPointerGetScreen(dev); 973f7df2e56Smrg double tmpx, tmpy; 9744202a189Smrg 975f7df2e56Smrg if (!dev->valuator || dev->valuator->numAxes < 2) 976f7df2e56Smrg return scr; 9774202a189Smrg 978f7df2e56Smrg tmpx = *screenx; 979f7df2e56Smrg tmpy = *screeny; 9804202a189Smrg 981f7df2e56Smrg /* miPointerSetPosition takes care of crossing screens for us, as well as 982f7df2e56Smrg * clipping to the current screen. Coordinates returned are in desktop 983f7df2e56Smrg * coord system */ 984f7df2e56Smrg scr = miPointerSetPosition(dev, mode, screenx, screeny, nevents, events); 985f7df2e56Smrg 986f7df2e56Smrg /* If we were constrained, rescale x/y from the screen coordinates so 987f7df2e56Smrg * the device valuators reflect the correct position. For screen 988f7df2e56Smrg * crossing this doesn't matter much, the coords would be 0 or max. 989f7df2e56Smrg */ 990f7df2e56Smrg if (tmpx != *screenx) 991f7df2e56Smrg *devx = rescaleValuatorAxis(*screenx, NULL, dev->valuator->axes + 0, 992f7df2e56Smrg screenInfo.x, screenInfo.width); 9934642e01fSmrg 994f7df2e56Smrg if (tmpy != *screeny) 995f7df2e56Smrg *devy = rescaleValuatorAxis(*screeny, NULL, dev->valuator->axes + 1, 996f7df2e56Smrg screenInfo.y, screenInfo.height); 9974642e01fSmrg 998f7df2e56Smrg /* Recalculate the per-screen device coordinates */ 999f7df2e56Smrg if (valuator_mask_isset(mask, 0)) { 1000f7df2e56Smrg double x; 1001f7df2e56Smrg 1002f7df2e56Smrg x = rescaleValuatorAxis(*screenx - scr->x, NULL, 1003f7df2e56Smrg dev->valuator->axes + 0, 0, scr->width); 1004f7df2e56Smrg valuator_mask_set_double(mask, 0, x); 10054642e01fSmrg } 1006f7df2e56Smrg if (valuator_mask_isset(mask, 1)) { 1007f7df2e56Smrg double y; 10084642e01fSmrg 1009f7df2e56Smrg y = rescaleValuatorAxis(*screeny - scr->y, NULL, 1010f7df2e56Smrg dev->valuator->axes + 1, 0, scr->height); 1011f7df2e56Smrg valuator_mask_set_double(mask, 1, y); 10124642e01fSmrg } 10134642e01fSmrg 1014f7df2e56Smrg return scr; 10154642e01fSmrg} 10164642e01fSmrg 10174642e01fSmrg/** 10184642e01fSmrg * Update the motion history for the device and (if appropriate) for its 10194642e01fSmrg * master device. 10204642e01fSmrg * @param dev Slave device to update. 102165b04b38Smrg * @param mask Bit mask of valid valuators to append to history. 10224642e01fSmrg * @param num Total number of valuators to append to history. 10234642e01fSmrg * @param ms Current time 10244642e01fSmrg */ 10254642e01fSmrgstatic void 102665b04b38SmrgupdateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms) 10274642e01fSmrg{ 102865b04b38Smrg if (!dev->valuator) 102965b04b38Smrg return; 103065b04b38Smrg 103165b04b38Smrg updateMotionHistory(dev, ms, mask, dev->last.valuators); 1032f7df2e56Smrg if (!IsMaster(dev) && !IsFloating(dev)) { 10334202a189Smrg DeviceIntPtr master = GetMaster(dev, MASTER_POINTER); 1034f7df2e56Smrg 103565b04b38Smrg updateMotionHistory(master, ms, mask, dev->last.valuators); 10364202a189Smrg } 10374642e01fSmrg} 103805b261ecSmrg 1039f7df2e56Smrgstatic void 1040f7df2e56SmrgqueueEventList(DeviceIntPtr device, InternalEvent *events, int nevents) 1041f7df2e56Smrg{ 1042f7df2e56Smrg int i; 1043f7df2e56Smrg 1044f7df2e56Smrg for (i = 0; i < nevents; i++) 1045f7df2e56Smrg mieqEnqueue(device, &events[i]); 1046f7df2e56Smrg} 1047f7df2e56Smrg 1048f7df2e56Smrgstatic void 1049f7df2e56Smrgevent_set_root_coordinates(DeviceEvent *event, double x, double y) 1050f7df2e56Smrg{ 1051f7df2e56Smrg event->root_x = trunc(x); 1052f7df2e56Smrg event->root_y = trunc(y); 1053f7df2e56Smrg event->root_x_frac = x - trunc(x); 1054f7df2e56Smrg event->root_y_frac = y - trunc(y); 1055f7df2e56Smrg} 1056f7df2e56Smrg 105705b261ecSmrg/** 1058f7df2e56Smrg * Generate internal events representing this keyboard event and enqueue 1059f7df2e56Smrg * them on the event queue. 1060f7df2e56Smrg * 1061f7df2e56Smrg * This function is not reentrant. Disable signals before calling. 1062f7df2e56Smrg * 1063f7df2e56Smrg * @param device The device to generate the event for 1064f7df2e56Smrg * @param type Event type, one of KeyPress or KeyRelease 1065f7df2e56Smrg * @param keycode Key code of the pressed/released key 1066f7df2e56Smrg * 106705b261ecSmrg */ 1068f7df2e56Smrgvoid 1069f7df2e56SmrgQueueKeyboardEvents(DeviceIntPtr device, int type, 1070f7df2e56Smrg int keycode) 1071f7df2e56Smrg{ 1072f7df2e56Smrg int nevents; 107365b04b38Smrg 1074f7df2e56Smrg nevents = GetKeyboardEvents(InputEventList, device, type, keycode); 1075f7df2e56Smrg queueEventList(device, InputEventList, nevents); 107605b261ecSmrg} 107705b261ecSmrg 107805b261ecSmrg/** 107965b04b38Smrg * Returns a set of InternalEvents for KeyPress/KeyRelease, optionally 108065b04b38Smrg * also with valuator events. 10814642e01fSmrg * 1082f7df2e56Smrg * The DDX is responsible for allocating the event list in the first 1083f7df2e56Smrg * place via InitEventList(), and for freeing it. 1084f7df2e56Smrg * 1085f7df2e56Smrg * @return the number of events written into events. 108605b261ecSmrg */ 10874202a189Smrgint 1088f7df2e56SmrgGetKeyboardEvents(InternalEvent *events, DeviceIntPtr pDev, int type, 1089f7df2e56Smrg int key_code) 1090f7df2e56Smrg{ 10914202a189Smrg int num_events = 0; 109205b261ecSmrg CARD32 ms = 0; 10934202a189Smrg DeviceEvent *event; 10944202a189Smrg RawDeviceEvent *raw; 1095f7df2e56Smrg 1096f7df2e56Smrg#if XSERVER_DTRACE 1097f7df2e56Smrg if (XSERVER_INPUT_EVENT_ENABLED()) { 1098f7df2e56Smrg XSERVER_INPUT_EVENT(pDev->id, type, key_code, 0, 0, 1099f7df2e56Smrg NULL, NULL); 1100f7df2e56Smrg } 1101f7df2e56Smrg#endif 11024202a189Smrg 11034202a189Smrg /* refuse events from disabled devices */ 11044202a189Smrg if (!pDev->enabled) 11054202a189Smrg return 0; 110605b261ecSmrg 1107f7df2e56Smrg if (!events || !pDev->key || !pDev->focus || !pDev->kbdfeed || 1108f7df2e56Smrg (type != KeyPress && type != KeyRelease) || 1109f7df2e56Smrg (key_code < 8 || key_code > 255)) 111005b261ecSmrg return 0; 111105b261ecSmrg 11124202a189Smrg num_events = 1; 111305b261ecSmrg 1114f7df2e56Smrg events = 1115f7df2e56Smrg UpdateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events); 111605b261ecSmrg 11174202a189Smrg /* Handle core repeating, via press/release/press/release. */ 11184202a189Smrg if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) { 111905b261ecSmrg /* If autorepeating is disabled either globally or just for that key, 112005b261ecSmrg * or we have a modifier, don't generate a repeat event. */ 112105b261ecSmrg if (!pDev->kbdfeed->ctrl.autoRepeat || 112205b261ecSmrg !key_autorepeats(pDev, key_code) || 11234202a189Smrg pDev->key->xkbInfo->desc->map->modmap[key_code]) 112405b261ecSmrg return 0; 112505b261ecSmrg } 112605b261ecSmrg 112705b261ecSmrg ms = GetTimeInMillis(); 112805b261ecSmrg 1129f7df2e56Smrg raw = &events->raw_event; 11304202a189Smrg events++; 11314202a189Smrg num_events++; 11324202a189Smrg 11334202a189Smrg init_raw(pDev, raw, ms, type, key_code); 11344202a189Smrg 1135f7df2e56Smrg event = &events->device_event; 1136f7df2e56Smrg init_device_event(event, pDev, ms); 11374202a189Smrg event->detail.key = key_code; 11384202a189Smrg 113905b261ecSmrg if (type == KeyPress) { 11404202a189Smrg event->type = ET_KeyPress; 1141f7df2e56Smrg set_key_down(pDev, key_code, KEY_POSTED); 114205b261ecSmrg } 114305b261ecSmrg else if (type == KeyRelease) { 11444202a189Smrg event->type = ET_KeyRelease; 1145f7df2e56Smrg set_key_up(pDev, key_code, KEY_POSTED); 114605b261ecSmrg } 114705b261ecSmrg 11484202a189Smrg return num_events; 114905b261ecSmrg} 115005b261ecSmrg 11514642e01fSmrg/** 1152f7df2e56Smrg * Initialize an event array large enough for num_events arrays. 11534642e01fSmrg * This event list is to be passed into GetPointerEvents() and 11544642e01fSmrg * GetKeyboardEvents(). 11554642e01fSmrg * 11564642e01fSmrg * @param num_events Number of elements in list. 11574642e01fSmrg */ 1158f7df2e56SmrgInternalEvent * 11594642e01fSmrgInitEventList(int num_events) 11604642e01fSmrg{ 1161f7df2e56Smrg InternalEvent *events = calloc(num_events, sizeof(InternalEvent)); 11624642e01fSmrg 11634642e01fSmrg return events; 11644642e01fSmrg} 11654642e01fSmrg 11664642e01fSmrg/** 11674642e01fSmrg * Free an event list. 11684642e01fSmrg * 11694642e01fSmrg * @param list The list to be freed. 11704642e01fSmrg * @param num_events Number of elements in list. 11714642e01fSmrg */ 11724202a189Smrgvoid 1173f7df2e56SmrgFreeEventList(InternalEvent *list, int num_events) 11744642e01fSmrg{ 11754202a189Smrg free(list); 11764202a189Smrg} 11774202a189Smrg 1178f7df2e56Smrg/** 1179f7df2e56Smrg * Transform vector x/y according to matrix m and drop the rounded coords 1180f7df2e56Smrg * back into x/y. 1181f7df2e56Smrg */ 1182f7df2e56Smrgstatic void 1183f7df2e56Smrgtransform(struct pixman_f_transform *m, double *x, double *y) 1184f7df2e56Smrg{ 1185f7df2e56Smrg struct pixman_f_vector p = {.v = {*x, *y, 1} }; 1186f7df2e56Smrg pixman_f_transform_point(m, &p); 1187f7df2e56Smrg 1188f7df2e56Smrg *x = p.v[0]; 1189f7df2e56Smrg *y = p.v[1]; 1190f7df2e56Smrg} 1191f7df2e56Smrg 1192f7df2e56Smrgstatic void 1193f7df2e56SmrgtransformRelative(DeviceIntPtr dev, ValuatorMask *mask) 1194f7df2e56Smrg{ 1195f7df2e56Smrg double x = 0, y = 0; 1196f7df2e56Smrg 1197f7df2e56Smrg valuator_mask_fetch_double(mask, 0, &x); 1198f7df2e56Smrg valuator_mask_fetch_double(mask, 1, &y); 1199f7df2e56Smrg 1200f7df2e56Smrg transform(&dev->relative_transform, &x, &y); 1201f7df2e56Smrg 1202f7df2e56Smrg if (x) 1203f7df2e56Smrg valuator_mask_set_double(mask, 0, x); 1204f7df2e56Smrg else 1205f7df2e56Smrg valuator_mask_unset(mask, 0); 1206f7df2e56Smrg 1207f7df2e56Smrg if (y) 1208f7df2e56Smrg valuator_mask_set_double(mask, 1, y); 1209f7df2e56Smrg else 1210f7df2e56Smrg valuator_mask_unset(mask, 1); 1211f7df2e56Smrg} 1212f7df2e56Smrg 1213f7df2e56Smrg/** 1214f7df2e56Smrg * Apply the device's transformation matrix to the valuator mask and replace 1215f7df2e56Smrg * the scaled values in mask. This transformation only applies to valuators 1216f7df2e56Smrg * 0 and 1, others will be untouched. 1217f7df2e56Smrg * 1218f7df2e56Smrg * @param dev The device the valuators came from 1219f7df2e56Smrg * @param[in,out] mask The valuator mask. 1220f7df2e56Smrg */ 12214202a189Smrgstatic void 122265b04b38SmrgtransformAbsolute(DeviceIntPtr dev, ValuatorMask *mask) 12234202a189Smrg{ 1224f7df2e56Smrg double x, y, ox, oy; 1225f7df2e56Smrg int has_x, has_y; 12264202a189Smrg 1227f7df2e56Smrg has_x = valuator_mask_isset(mask, 0); 1228f7df2e56Smrg has_y = valuator_mask_isset(mask, 1); 12294202a189Smrg 1230f7df2e56Smrg if (!has_x && !has_y) 1231f7df2e56Smrg return; 12324202a189Smrg 1233f7df2e56Smrg if (!has_x || !has_y) { 1234f7df2e56Smrg struct pixman_f_transform invert; 1235f7df2e56Smrg 1236f7df2e56Smrg /* undo transformation from last event */ 1237f7df2e56Smrg ox = dev->last.valuators[0]; 1238f7df2e56Smrg oy = dev->last.valuators[1]; 1239f7df2e56Smrg 1240f7df2e56Smrg pixman_f_transform_invert(&invert, &dev->scale_and_transform); 1241f7df2e56Smrg transform(&invert, &ox, &oy); 1242f7df2e56Smrg } 1243f7df2e56Smrg 1244f7df2e56Smrg if (has_x) 1245f7df2e56Smrg ox = valuator_mask_get_double(mask, 0); 1246f7df2e56Smrg 1247f7df2e56Smrg if (has_y) 1248f7df2e56Smrg oy = valuator_mask_get_double(mask, 1); 1249f7df2e56Smrg 1250f7df2e56Smrg x = ox; 1251f7df2e56Smrg y = oy; 1252f7df2e56Smrg 1253f7df2e56Smrg transform(&dev->scale_and_transform, &x, &y); 1254f7df2e56Smrg 1255f7df2e56Smrg if (has_x || ox != x) 1256f7df2e56Smrg valuator_mask_set_double(mask, 0, x); 1257f7df2e56Smrg 1258f7df2e56Smrg if (has_y || oy != y) 1259f7df2e56Smrg valuator_mask_set_double(mask, 1, y); 1260f7df2e56Smrg} 1261f7df2e56Smrg 1262f7df2e56Smrgstatic void 1263f7df2e56SmrgstoreLastValuators(DeviceIntPtr dev, ValuatorMask *mask, 1264f7df2e56Smrg int xaxis, int yaxis, double devx, double devy) 1265f7df2e56Smrg{ 1266f7df2e56Smrg int i; 1267f7df2e56Smrg 1268f7df2e56Smrg /* store desktop-wide in last.valuators */ 1269f7df2e56Smrg if (valuator_mask_isset(mask, xaxis)) 1270f7df2e56Smrg dev->last.valuators[0] = devx; 1271f7df2e56Smrg if (valuator_mask_isset(mask, yaxis)) 1272f7df2e56Smrg dev->last.valuators[1] = devy; 1273f7df2e56Smrg 1274f7df2e56Smrg for (i = 0; i < valuator_mask_size(mask); i++) { 1275f7df2e56Smrg if (i == xaxis || i == yaxis) 1276f7df2e56Smrg continue; 1277f7df2e56Smrg 1278f7df2e56Smrg if (valuator_mask_isset(mask, i)) 1279f7df2e56Smrg dev->last.valuators[i] = valuator_mask_get_double(mask, i); 1280f7df2e56Smrg } 128145bb0b75Smrg 12824642e01fSmrg} 128305b261ecSmrg 128405b261ecSmrg/** 1285f7df2e56Smrg * Generate internal events representing this pointer event and enqueue them 1286f7df2e56Smrg * on the event queue. 128705b261ecSmrg * 1288f7df2e56Smrg * This function is not reentrant. Disable signals before calling. 12894642e01fSmrg * 1290f7df2e56Smrg * @param device The device to generate the event for 1291f7df2e56Smrg * @param type Event type, one of ButtonPress, ButtonRelease, MotionNotify 1292f7df2e56Smrg * @param buttons Button number of the buttons modified. Must be 0 for 1293f7df2e56Smrg * MotionNotify 1294f7df2e56Smrg * @param flags Event modification flags 1295f7df2e56Smrg * @param mask Valuator mask for valuators present for this event. 1296f7df2e56Smrg */ 1297f7df2e56Smrgvoid 1298f7df2e56SmrgQueuePointerEvents(DeviceIntPtr device, int type, 1299f7df2e56Smrg int buttons, int flags, const ValuatorMask *mask) 1300f7df2e56Smrg{ 1301f7df2e56Smrg int nevents; 1302f7df2e56Smrg 1303f7df2e56Smrg nevents = 1304f7df2e56Smrg GetPointerEvents(InputEventList, device, type, buttons, flags, mask); 1305f7df2e56Smrg queueEventList(device, InputEventList, nevents); 1306f7df2e56Smrg} 1307f7df2e56Smrg 1308f7df2e56Smrg/** 1309f7df2e56Smrg * Helper function for GetPointerEvents, which only generates motion and 1310f7df2e56Smrg * raw motion events for the slave device: does not update the master device. 13114642e01fSmrg * 1312f7df2e56Smrg * Should not be called by anyone other than GetPointerEvents. 13134642e01fSmrg * 1314f7df2e56Smrg * We use several different coordinate systems and need to switch between 1315f7df2e56Smrg * the three in fill_pointer_events, positionSprite and 1316f7df2e56Smrg * miPointerSetPosition. "desktop" refers to the width/height of all 1317f7df2e56Smrg * screenInfo.screens[n]->width/height added up. "screen" is ScreenRec, not 1318f7df2e56Smrg * output. 1319f7df2e56Smrg * 1320f7df2e56Smrg * Coordinate systems: 1321f7df2e56Smrg * - relative events have a mask_in in relative coordinates, mapped to 1322f7df2e56Smrg * pixels. These events are mapped to the current position±delta. 1323f7df2e56Smrg * - absolute events have a mask_in in absolute device coordinates in 1324f7df2e56Smrg * device-specific range. This range is mapped to the desktop. 1325f7df2e56Smrg * - POINTER_SCREEN absolute events (x86WarpCursor) are in screen-relative 1326f7df2e56Smrg * screen coordinate range. 1327f7df2e56Smrg * - rootx/rooty in events must be be relative to the current screen's 1328f7df2e56Smrg * origin (screen coordinate system) 1329f7df2e56Smrg * - XI2 valuators must be relative to the current screen's origin. On 1330f7df2e56Smrg * the protocol the device min/max range maps to the current screen. 1331f7df2e56Smrg * 1332f7df2e56Smrg * For screen switching we need to get the desktop coordinates for each 1333f7df2e56Smrg * event, then map that to the respective position on each screen and 1334f7df2e56Smrg * position the cursor there. 1335f7df2e56Smrg * The device's last.valuator[] stores the last position in desktop-wide 1336f7df2e56Smrg * coordinates (in device range for slave devices, desktop range for master 1337f7df2e56Smrg * devices). 1338f7df2e56Smrg * 1339f7df2e56Smrg * screen-relative device coordinates requires scaling: A device coordinate 1340f7df2e56Smrg * x/y of range [n..m] that maps to positions Sx/Sy on Screen S must be 1341f7df2e56Smrg * rescaled to match Sx/Sy for [n..m]. In the simplest example, x of (m/2-1) 1342f7df2e56Smrg * is the last coordinate on the first screen and must be rescaled for the 1343f7df2e56Smrg * event to be m. XI2 clients that do their own coordinate mapping would 1344f7df2e56Smrg * otherwise interpret the position of the device elsewere to the cursor. 1345f7df2e56Smrg * However, this scaling leads to losses: 1346f7df2e56Smrg * if we have two ScreenRecs we scale from e.g. [0..44704] (Wacom I4) to 1347f7df2e56Smrg * [0..2048[. that gives us 2047.954 as desktop coord, or the per-screen 1348f7df2e56Smrg * coordinate 1023.954. Scaling that back into the device coordinate range 1349f7df2e56Smrg * gives us 44703. So off by one device unit. It's a bug, but we'll have to 1350f7df2e56Smrg * live with it because with all this scaling, we just cannot win. 1351f7df2e56Smrg * 1352f7df2e56Smrg * @return the number of events written into events. 135305b261ecSmrg */ 1354f7df2e56Smrgstatic int 1355f7df2e56Smrgfill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type, 1356f7df2e56Smrg int buttons, CARD32 ms, int flags, 1357f7df2e56Smrg const ValuatorMask *mask_in) 1358f7df2e56Smrg{ 13594642e01fSmrg int num_events = 1; 13604202a189Smrg DeviceEvent *event; 1361f7df2e56Smrg RawDeviceEvent *raw = NULL; 1362f7df2e56Smrg double screenx = 0.0, screeny = 0.0; /* desktop coordinate system */ 1363f7df2e56Smrg double devx = 0.0, devy = 0.0; /* desktop-wide in device coords */ 1364f7df2e56Smrg int sx = 0, sy = 0; /* for POINTER_SCREEN */ 136565b04b38Smrg ValuatorMask mask; 1366f7df2e56Smrg ScreenPtr scr; 1367f7df2e56Smrg int num_barrier_events = 0; 1368f7df2e56Smrg 1369f7df2e56Smrg switch (type) { 1370f7df2e56Smrg case MotionNotify: 1371f7df2e56Smrg if (!pDev->valuator) { 1372f7df2e56Smrg ErrorF("[dix] motion events from device %d without valuators\n", 1373f7df2e56Smrg pDev->id); 1374f7df2e56Smrg return 0; 1375f7df2e56Smrg } 1376f7df2e56Smrg if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0) 1377f7df2e56Smrg return 0; 1378f7df2e56Smrg break; 1379f7df2e56Smrg case ButtonPress: 1380f7df2e56Smrg case ButtonRelease: 1381f7df2e56Smrg if (!pDev->button || !buttons) 1382f7df2e56Smrg return 0; 1383f7df2e56Smrg if (mask_in && valuator_mask_size(mask_in) > 0 && !pDev->valuator) { 1384f7df2e56Smrg ErrorF 1385f7df2e56Smrg ("[dix] button event with valuator from device %d without valuators\n", 1386f7df2e56Smrg pDev->id); 1387f7df2e56Smrg return 0; 1388f7df2e56Smrg } 1389f7df2e56Smrg break; 1390f7df2e56Smrg default: 13914202a189Smrg return 0; 1392f7df2e56Smrg } 139305b261ecSmrg 1394f7df2e56Smrg valuator_mask_copy(&mask, mask_in); 139505b261ecSmrg 1396f7df2e56Smrg if ((flags & POINTER_NORAW) == 0) { 1397f7df2e56Smrg raw = &events->raw_event; 1398f7df2e56Smrg events++; 1399f7df2e56Smrg num_events++; 1400f7df2e56Smrg 1401f7df2e56Smrg init_raw(pDev, raw, ms, type, buttons); 1402f7df2e56Smrg set_raw_valuators(raw, &mask, TRUE, raw->valuators.data_raw); 140365b04b38Smrg } 140465b04b38Smrg 1405f7df2e56Smrg valuator_mask_drop_unaccelerated(&mask); 140665b04b38Smrg 1407f7df2e56Smrg /* valuators are in driver-native format (rel or abs) */ 14084202a189Smrg 1409f7df2e56Smrg if (flags & POINTER_ABSOLUTE) { 1410f7df2e56Smrg if (flags & (POINTER_SCREEN | POINTER_DESKTOP)) { /* valuators are in screen/desktop coords */ 1411f7df2e56Smrg sx = valuator_mask_get(&mask, 0); 1412f7df2e56Smrg sy = valuator_mask_get(&mask, 1); 1413f7df2e56Smrg scale_from_screen(pDev, &mask, flags); 1414f7df2e56Smrg } 14154202a189Smrg 1416f7df2e56Smrg transformAbsolute(pDev, &mask); 1417f7df2e56Smrg clipAbsolute(pDev, &mask); 1418f7df2e56Smrg if ((flags & POINTER_NORAW) == 0 && raw) 1419f7df2e56Smrg set_raw_valuators(raw, &mask, FALSE, raw->valuators.data); 1420f7df2e56Smrg } 1421f7df2e56Smrg else { 1422f7df2e56Smrg transformRelative(pDev, &mask); 1423f7df2e56Smrg 1424f7df2e56Smrg if (flags & POINTER_ACCELERATE) 1425f7df2e56Smrg accelPointer(pDev, &mask, ms); 1426f7df2e56Smrg if ((flags & POINTER_NORAW) == 0 && raw) 1427f7df2e56Smrg set_raw_valuators(raw, &mask, FALSE, raw->valuators.data); 142845bb0b75Smrg 1429f7df2e56Smrg moveRelative(pDev, flags, &mask); 143045bb0b75Smrg } 143105b261ecSmrg 1432f7df2e56Smrg /* valuators are in device coordinate system in absolute coordinates */ 1433f7df2e56Smrg scale_to_desktop(pDev, &mask, &devx, &devy, &screenx, &screeny); 143405b261ecSmrg 1435f7df2e56Smrg /* #53037 XWarpPointer's scaling back and forth between screen and 1436f7df2e56Smrg device may leave us with rounding errors. End result is that the 1437f7df2e56Smrg pointer doesn't end up on the pixel it should. 1438f7df2e56Smrg Avoid this by forcing screenx/screeny back to what the input 1439f7df2e56Smrg coordinates were. 1440f7df2e56Smrg */ 1441f7df2e56Smrg if (flags & POINTER_SCREEN) { 1442f7df2e56Smrg scr = miPointerGetScreen(pDev); 1443f7df2e56Smrg screenx = sx + scr->x; 1444f7df2e56Smrg screeny = sy + scr->y; 144505b261ecSmrg } 144605b261ecSmrg 1447f7df2e56Smrg scr = positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative, 1448f7df2e56Smrg &mask, &devx, &devy, &screenx, &screeny, 1449f7df2e56Smrg &num_barrier_events, events); 1450f7df2e56Smrg num_events += num_barrier_events; 1451f7df2e56Smrg events += num_barrier_events; 145205b261ecSmrg 1453f7df2e56Smrg /* screenx, screeny are in desktop coordinates, 1454f7df2e56Smrg mask is in device coordinates per-screen (the event data) 1455f7df2e56Smrg devx/devy is in device coordinate desktop-wide */ 145665b04b38Smrg updateHistory(pDev, &mask, ms); 145705b261ecSmrg 145865b04b38Smrg clipValuators(pDev, &mask); 14594202a189Smrg 1460f7df2e56Smrg storeLastValuators(pDev, &mask, 0, 1, devx, devy); 1461f7df2e56Smrg 1462f7df2e56Smrg /* Update the MD's co-ordinates, which are always in desktop space. */ 1463f7df2e56Smrg if (!IsMaster(pDev) && !IsFloating(pDev)) { 1464f7df2e56Smrg DeviceIntPtr master = GetMaster(pDev, MASTER_POINTER); 1465f7df2e56Smrg 1466f7df2e56Smrg master->last.valuators[0] = screenx; 1467f7df2e56Smrg master->last.valuators[1] = screeny; 1468f7df2e56Smrg } 1469f7df2e56Smrg 1470f7df2e56Smrg event = &events->device_event; 1471f7df2e56Smrg init_device_event(event, pDev, ms); 147205b261ecSmrg 14734642e01fSmrg if (type == MotionNotify) { 14744202a189Smrg event->type = ET_Motion; 14754202a189Smrg event->detail.button = 0; 14764642e01fSmrg } 14774642e01fSmrg else { 14784202a189Smrg if (type == ButtonPress) { 14794202a189Smrg event->type = ET_ButtonPress; 14804202a189Smrg set_button_down(pDev, buttons, BUTTON_POSTED); 14814202a189Smrg } 14824202a189Smrg else if (type == ButtonRelease) { 14834202a189Smrg event->type = ET_ButtonRelease; 14844202a189Smrg set_button_up(pDev, buttons, BUTTON_POSTED); 14854202a189Smrg } 14864202a189Smrg event->detail.button = buttons; 14874642e01fSmrg } 148805b261ecSmrg 1489f7df2e56Smrg /* root_x and root_y must be in per-screen co-ordinates */ 1490f7df2e56Smrg event_set_root_coordinates(event, screenx - scr->x, screeny - scr->y); 1491f7df2e56Smrg 1492f7df2e56Smrg if (flags & POINTER_EMULATED) { 1493f7df2e56Smrg if (raw) 1494f7df2e56Smrg raw->flags = XIPointerEmulated; 1495f7df2e56Smrg event->flags = XIPointerEmulated; 1496f7df2e56Smrg } 149705b261ecSmrg 149865b04b38Smrg set_valuators(pDev, event, &mask); 149905b261ecSmrg 150005b261ecSmrg return num_events; 150105b261ecSmrg} 150205b261ecSmrg 1503f7df2e56Smrg/** 1504f7df2e56Smrg * Generate events for each scroll axis that changed between before/after 1505f7df2e56Smrg * for the device. 1506f7df2e56Smrg * 1507f7df2e56Smrg * @param events The pointer to the event list to fill the events 1508f7df2e56Smrg * @param dev The device to generate the events for 1509f7df2e56Smrg * @param type The real type of the event 1510f7df2e56Smrg * @param axis The axis number to generate events for 1511f7df2e56Smrg * @param mask State before this event in absolute coords 1512f7df2e56Smrg * @param[in,out] last Last scroll state posted in absolute coords (modified 1513f7df2e56Smrg * in-place) 1514f7df2e56Smrg * @param ms Current time in ms 1515f7df2e56Smrg * @param max_events Max number of events to be generated 1516f7df2e56Smrg * @return The number of events generated 1517f7df2e56Smrg */ 1518f7df2e56Smrgstatic int 1519f7df2e56Smrgemulate_scroll_button_events(InternalEvent *events, 1520f7df2e56Smrg DeviceIntPtr dev, 1521f7df2e56Smrg int type, 1522f7df2e56Smrg int axis, 1523f7df2e56Smrg const ValuatorMask *mask, 1524f7df2e56Smrg ValuatorMask *last, CARD32 ms, int max_events) 1525f7df2e56Smrg{ 1526f7df2e56Smrg AxisInfoPtr ax; 1527f7df2e56Smrg double delta; 1528f7df2e56Smrg double incr; 1529f7df2e56Smrg int num_events = 0; 1530f7df2e56Smrg double total; 1531f7df2e56Smrg int b; 1532f7df2e56Smrg int flags = 0; 1533f7df2e56Smrg 1534f7df2e56Smrg if (dev->valuator->axes[axis].scroll.type == SCROLL_TYPE_NONE) 1535f7df2e56Smrg return 0; 1536f7df2e56Smrg 1537f7df2e56Smrg if (!valuator_mask_isset(mask, axis)) 1538f7df2e56Smrg return 0; 1539f7df2e56Smrg 1540f7df2e56Smrg ax = &dev->valuator->axes[axis]; 1541f7df2e56Smrg incr = ax->scroll.increment; 1542f7df2e56Smrg 1543f7df2e56Smrg BUG_WARN_MSG(incr == 0, "for device %s\n", dev->name); 1544f7df2e56Smrg if (incr == 0) 1545f7df2e56Smrg return 0; 1546f7df2e56Smrg 1547f7df2e56Smrg if (type != ButtonPress && type != ButtonRelease) 1548f7df2e56Smrg flags |= POINTER_EMULATED; 1549f7df2e56Smrg 1550f7df2e56Smrg if (!valuator_mask_isset(last, axis)) 1551f7df2e56Smrg valuator_mask_set_double(last, axis, 0); 1552f7df2e56Smrg 1553f7df2e56Smrg delta = 1554f7df2e56Smrg valuator_mask_get_double(mask, axis) - valuator_mask_get_double(last, 1555f7df2e56Smrg axis); 1556f7df2e56Smrg total = delta; 1557f7df2e56Smrg b = (ax->scroll.type == SCROLL_TYPE_VERTICAL) ? 5 : 7; 1558f7df2e56Smrg 1559f7df2e56Smrg if ((incr > 0 && delta < 0) || (incr < 0 && delta > 0)) 1560f7df2e56Smrg b--; /* we're scrolling up or left → button 4 or 6 */ 1561f7df2e56Smrg 1562f7df2e56Smrg while (fabs(delta) >= fabs(incr)) { 1563f7df2e56Smrg int nev_tmp; 1564f7df2e56Smrg 1565f7df2e56Smrg if (delta > 0) 1566f7df2e56Smrg delta -= fabs(incr); 1567f7df2e56Smrg else if (delta < 0) 1568f7df2e56Smrg delta += fabs(incr); 1569f7df2e56Smrg 1570f7df2e56Smrg /* fill_pointer_events() generates four events: one normal and one raw 1571f7df2e56Smrg * event for button press and button release. 1572f7df2e56Smrg * We may get a bigger scroll delta than we can generate events 1573f7df2e56Smrg * for. In that case, we keep decreasing delta, but skip events. 1574f7df2e56Smrg */ 1575f7df2e56Smrg if (num_events + 4 < max_events) { 1576f7df2e56Smrg if (type != ButtonRelease) { 1577f7df2e56Smrg nev_tmp = fill_pointer_events(events, dev, ButtonPress, b, ms, 1578f7df2e56Smrg flags, NULL); 1579f7df2e56Smrg events += nev_tmp; 1580f7df2e56Smrg num_events += nev_tmp; 1581f7df2e56Smrg } 1582f7df2e56Smrg if (type != ButtonPress) { 1583f7df2e56Smrg nev_tmp = fill_pointer_events(events, dev, ButtonRelease, b, ms, 1584f7df2e56Smrg flags, NULL); 1585f7df2e56Smrg events += nev_tmp; 1586f7df2e56Smrg num_events += nev_tmp; 1587f7df2e56Smrg } 1588f7df2e56Smrg } 1589f7df2e56Smrg } 1590f7df2e56Smrg 1591f7df2e56Smrg /* We emulated, update last.scroll */ 1592f7df2e56Smrg if (total != delta) { 1593f7df2e56Smrg total -= delta; 1594f7df2e56Smrg valuator_mask_set_double(last, axis, 1595f7df2e56Smrg valuator_mask_get_double(last, axis) + total); 1596f7df2e56Smrg } 1597f7df2e56Smrg 1598f7df2e56Smrg return num_events; 1599f7df2e56Smrg} 1600f7df2e56Smrg 160105b261ecSmrg 160205b261ecSmrg/** 1603f7df2e56Smrg * Generate a complete series of InternalEvents (filled into the EventList) 1604f7df2e56Smrg * representing pointer motion, or button presses. If the device is a slave 1605f7df2e56Smrg * device, also potentially generate a DeviceClassesChangedEvent to update 1606f7df2e56Smrg * the master device. 160705b261ecSmrg * 160805b261ecSmrg * events is not NULL-terminated; the return value is the number of events. 160905b261ecSmrg * The DDX is responsible for allocating the event structure in the first 1610f7df2e56Smrg * place via InitEventList() and GetMaximumEventsNum(), and for freeing it. 1611f7df2e56Smrg * 1612f7df2e56Smrg * In the generated events rootX/Y will be in absolute screen coords and 1613f7df2e56Smrg * the valuator information in the absolute or relative device coords. 1614f7df2e56Smrg * 1615f7df2e56Smrg * last.valuators[x] of the device is always in absolute device coords. 1616f7df2e56Smrg * last.valuators[x] of the master device is in absolute screen coords. 1617f7df2e56Smrg * 1618f7df2e56Smrg * master->last.valuators[x] for x > 2 is undefined. 1619f7df2e56Smrg */ 1620f7df2e56Smrgint 1621f7df2e56SmrgGetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, 1622f7df2e56Smrg int buttons, int flags, const ValuatorMask *mask_in) 1623f7df2e56Smrg{ 1624f7df2e56Smrg CARD32 ms = GetTimeInMillis(); 1625f7df2e56Smrg int num_events = 0, nev_tmp; 1626f7df2e56Smrg ValuatorMask mask; 1627f7df2e56Smrg ValuatorMask scroll; 1628f7df2e56Smrg int i; 1629f7df2e56Smrg int realtype = type; 1630f7df2e56Smrg 1631f7df2e56Smrg#if XSERVER_DTRACE 1632f7df2e56Smrg if (XSERVER_INPUT_EVENT_ENABLED()) { 1633f7df2e56Smrg XSERVER_INPUT_EVENT(pDev->id, type, buttons, flags, 1634f7df2e56Smrg mask_in ? mask_in->last_bit + 1 : 0, 1635f7df2e56Smrg mask_in ? mask_in->mask : NULL, 1636f7df2e56Smrg mask_in ? mask_in->valuators : NULL); 1637f7df2e56Smrg } 1638f7df2e56Smrg#endif 1639f7df2e56Smrg 1640f7df2e56Smrg BUG_RETURN_VAL(buttons >= MAX_BUTTONS, 0); 1641f7df2e56Smrg 1642f7df2e56Smrg /* refuse events from disabled devices */ 1643f7df2e56Smrg if (!pDev->enabled) 1644f7df2e56Smrg return 0; 1645f7df2e56Smrg 1646f7df2e56Smrg if (!miPointerGetScreen(pDev)) 1647f7df2e56Smrg return 0; 1648f7df2e56Smrg 1649f7df2e56Smrg events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, 1650f7df2e56Smrg &num_events); 1651f7df2e56Smrg 1652f7df2e56Smrg valuator_mask_copy(&mask, mask_in); 1653f7df2e56Smrg 1654f7df2e56Smrg /* Turn a scroll button press into a smooth-scrolling event if 1655f7df2e56Smrg * necessary. This only needs to cater for the XIScrollFlagPreferred 1656f7df2e56Smrg * axis (if more than one scrolling axis is present) */ 1657f7df2e56Smrg if (type == ButtonPress) { 1658f7df2e56Smrg double adj; 1659f7df2e56Smrg int axis; 1660f7df2e56Smrg int h_scroll_axis = -1; 1661f7df2e56Smrg int v_scroll_axis = -1; 1662f7df2e56Smrg 1663f7df2e56Smrg if (pDev->valuator) { 1664f7df2e56Smrg h_scroll_axis = pDev->valuator->h_scroll_axis; 1665f7df2e56Smrg v_scroll_axis = pDev->valuator->v_scroll_axis; 1666f7df2e56Smrg } 1667f7df2e56Smrg 1668f7df2e56Smrg /* Up is negative on valuators, down positive */ 1669f7df2e56Smrg switch (buttons) { 1670f7df2e56Smrg case 4: 1671f7df2e56Smrg adj = -1.0; 1672f7df2e56Smrg axis = v_scroll_axis; 1673f7df2e56Smrg break; 1674f7df2e56Smrg case 5: 1675f7df2e56Smrg adj = 1.0; 1676f7df2e56Smrg axis = v_scroll_axis; 1677f7df2e56Smrg break; 1678f7df2e56Smrg case 6: 1679f7df2e56Smrg adj = -1.0; 1680f7df2e56Smrg axis = h_scroll_axis; 1681f7df2e56Smrg break; 1682f7df2e56Smrg case 7: 1683f7df2e56Smrg adj = 1.0; 1684f7df2e56Smrg axis = h_scroll_axis; 1685f7df2e56Smrg break; 1686f7df2e56Smrg default: 1687f7df2e56Smrg adj = 0.0; 1688f7df2e56Smrg axis = -1; 1689f7df2e56Smrg break; 1690f7df2e56Smrg } 1691f7df2e56Smrg 1692f7df2e56Smrg if (adj != 0.0 && axis != -1) { 1693f7df2e56Smrg adj *= pDev->valuator->axes[axis].scroll.increment; 1694f7df2e56Smrg if (!valuator_mask_isset(&mask, axis)) 1695f7df2e56Smrg valuator_mask_set(&mask, axis, 0); 1696f7df2e56Smrg add_to_scroll_valuator(pDev, &mask, axis, adj); 1697f7df2e56Smrg type = MotionNotify; 1698f7df2e56Smrg buttons = 0; 1699f7df2e56Smrg flags |= POINTER_EMULATED; 1700f7df2e56Smrg } 1701f7df2e56Smrg } 1702f7df2e56Smrg 1703f7df2e56Smrg /* First fill out the original event set, with smooth-scrolling axes. */ 1704f7df2e56Smrg nev_tmp = fill_pointer_events(events, pDev, type, buttons, ms, flags, 1705f7df2e56Smrg &mask); 1706f7df2e56Smrg events += nev_tmp; 1707f7df2e56Smrg num_events += nev_tmp; 1708f7df2e56Smrg 1709f7df2e56Smrg valuator_mask_zero(&scroll); 1710f7df2e56Smrg 1711f7df2e56Smrg /* Now turn the smooth-scrolling axes back into emulated button presses 1712f7df2e56Smrg * for legacy clients, based on the integer delta between before and now */ 1713f7df2e56Smrg for (i = 0; i < valuator_mask_size(&mask); i++) { 1714f7df2e56Smrg if ( !pDev->valuator || (i >= pDev->valuator->numAxes)) 1715f7df2e56Smrg break; 1716f7df2e56Smrg 1717f7df2e56Smrg if (!valuator_mask_isset(&mask, i)) 1718f7df2e56Smrg continue; 1719f7df2e56Smrg 1720f7df2e56Smrg valuator_mask_set_double(&scroll, i, pDev->last.valuators[i]); 1721f7df2e56Smrg 1722f7df2e56Smrg nev_tmp = 1723f7df2e56Smrg emulate_scroll_button_events(events, pDev, realtype, i, &scroll, 1724f7df2e56Smrg pDev->last.scroll, ms, 1725f7df2e56Smrg GetMaximumEventsNum() - num_events); 1726f7df2e56Smrg events += nev_tmp; 1727f7df2e56Smrg num_events += nev_tmp; 1728f7df2e56Smrg } 1729f7df2e56Smrg 1730f7df2e56Smrg return num_events; 1731f7df2e56Smrg} 1732f7df2e56Smrg 1733f7df2e56Smrg/** 1734f7df2e56Smrg * Generate internal events representing this proximity event and enqueue 1735f7df2e56Smrg * them on the event queue. 1736f7df2e56Smrg * 1737f7df2e56Smrg * This function is not reentrant. Disable signals before calling. 1738f7df2e56Smrg * 1739f7df2e56Smrg * @param device The device to generate the event for 1740f7df2e56Smrg * @param type Event type, one of ProximityIn or ProximityOut 1741f7df2e56Smrg * @param keycode Key code of the pressed/released key 1742f7df2e56Smrg * @param mask Valuator mask for valuators present for this event. 1743f7df2e56Smrg * 1744f7df2e56Smrg */ 1745f7df2e56Smrgvoid 1746f7df2e56SmrgQueueProximityEvents(DeviceIntPtr device, int type, const ValuatorMask *mask) 1747f7df2e56Smrg{ 1748f7df2e56Smrg int nevents; 1749f7df2e56Smrg 1750f7df2e56Smrg nevents = GetProximityEvents(InputEventList, device, type, mask); 1751f7df2e56Smrg queueEventList(device, InputEventList, nevents); 1752f7df2e56Smrg} 1753f7df2e56Smrg 1754f7df2e56Smrg/** 1755f7df2e56Smrg * Generate ProximityIn/ProximityOut InternalEvents, accompanied by 1756f7df2e56Smrg * valuators. 1757f7df2e56Smrg * 1758f7df2e56Smrg * The DDX is responsible for allocating the events in the first place via 1759f7df2e56Smrg * InitEventList(), and for freeing it. 1760f7df2e56Smrg * 1761f7df2e56Smrg * @return the number of events written into events. 176205b261ecSmrg */ 17634202a189Smrgint 1764f7df2e56SmrgGetProximityEvents(InternalEvent *events, DeviceIntPtr pDev, int type, 1765f7df2e56Smrg const ValuatorMask *mask_in) 176605b261ecSmrg{ 176765b04b38Smrg int num_events = 1, i; 17684202a189Smrg DeviceEvent *event; 176965b04b38Smrg ValuatorMask mask; 17704202a189Smrg 1771f7df2e56Smrg#if XSERVER_DTRACE 1772f7df2e56Smrg if (XSERVER_INPUT_EVENT_ENABLED()) { 1773f7df2e56Smrg XSERVER_INPUT_EVENT(pDev->id, type, 0, 0, 1774f7df2e56Smrg mask_in ? mask_in->last_bit + 1 : 0, 1775f7df2e56Smrg mask_in ? mask_in->mask : NULL, 1776f7df2e56Smrg mask_in ? mask_in->valuators : NULL); 1777f7df2e56Smrg } 1778f7df2e56Smrg#endif 1779f7df2e56Smrg 17804202a189Smrg /* refuse events from disabled devices */ 17814202a189Smrg if (!pDev->enabled) 17824202a189Smrg return 0; 178305b261ecSmrg 178405b261ecSmrg /* Sanity checks. */ 178565b04b38Smrg if ((type != ProximityIn && type != ProximityOut) || !mask_in) 178605b261ecSmrg return 0; 1787f7df2e56Smrg if (!pDev->valuator || !pDev->proximity) 178805b261ecSmrg return 0; 178905b261ecSmrg 179065b04b38Smrg valuator_mask_copy(&mask, mask_in); 179165b04b38Smrg 179265b04b38Smrg /* ignore relative axes for proximity. */ 1793f7df2e56Smrg for (i = 0; i < valuator_mask_size(&mask); i++) { 179465b04b38Smrg if (valuator_mask_isset(&mask, i) && 179565b04b38Smrg valuator_get_mode(pDev, i) == Relative) 179665b04b38Smrg valuator_mask_unset(&mask, i); 179765b04b38Smrg } 179865b04b38Smrg 179965b04b38Smrg /* FIXME: posting proximity events with relative valuators only results 180065b04b38Smrg * in an empty event, EventToXI() will fail to convert → no event sent 180165b04b38Smrg * to client. */ 180205b261ecSmrg 1803f7df2e56Smrg events = 1804f7df2e56Smrg UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); 18054642e01fSmrg 1806f7df2e56Smrg event = &events->device_event; 1807f7df2e56Smrg init_device_event(event, pDev, GetTimeInMillis()); 18084202a189Smrg event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut; 180905b261ecSmrg 181065b04b38Smrg clipValuators(pDev, &mask); 181105b261ecSmrg 181265b04b38Smrg set_valuators(pDev, event, &mask); 18134202a189Smrg 181405b261ecSmrg return num_events; 181505b261ecSmrg} 181605b261ecSmrg 1817f7df2e56Smrgint 1818f7df2e56SmrgGetTouchOwnershipEvents(InternalEvent *events, DeviceIntPtr pDev, 1819f7df2e56Smrg TouchPointInfoPtr ti, uint8_t reason, XID resource, 1820f7df2e56Smrg uint32_t flags) 1821f7df2e56Smrg{ 1822f7df2e56Smrg TouchClassPtr t = pDev->touch; 1823f7df2e56Smrg TouchOwnershipEvent *event; 1824f7df2e56Smrg CARD32 ms = GetTimeInMillis(); 1825f7df2e56Smrg 1826f7df2e56Smrg if (!pDev->enabled || !t || !ti) 1827f7df2e56Smrg return 0; 1828f7df2e56Smrg 1829f7df2e56Smrg event = &events->touch_ownership_event; 1830f7df2e56Smrg init_touch_ownership(pDev, event, ms); 1831f7df2e56Smrg 1832f7df2e56Smrg event->touchid = ti->client_id; 1833f7df2e56Smrg event->sourceid = ti->sourceid; 1834f7df2e56Smrg event->resource = resource; 1835f7df2e56Smrg event->flags = flags; 1836f7df2e56Smrg event->reason = reason; 1837f7df2e56Smrg 1838f7df2e56Smrg return 1; 1839f7df2e56Smrg} 1840f7df2e56Smrg 1841f7df2e56Smrg/** 1842f7df2e56Smrg * Generate internal events representing this touch event and enqueue them 1843f7df2e56Smrg * on the event queue. 1844f7df2e56Smrg * 1845f7df2e56Smrg * This function is not reentrant. Disable signals before calling. 1846f7df2e56Smrg * 1847f7df2e56Smrg * @param device The device to generate the event for 1848f7df2e56Smrg * @param type Event type, one of XI_TouchBegin, XI_TouchUpdate, XI_TouchEnd 1849f7df2e56Smrg * @param touchid Touch point ID 1850f7df2e56Smrg * @param flags Event modification flags 1851f7df2e56Smrg * @param mask Valuator mask for valuators present for this event. 1852f7df2e56Smrg */ 1853f7df2e56Smrgvoid 1854f7df2e56SmrgQueueTouchEvents(DeviceIntPtr device, int type, 1855f7df2e56Smrg uint32_t ddx_touchid, int flags, const ValuatorMask *mask) 1856f7df2e56Smrg{ 1857f7df2e56Smrg int nevents; 1858f7df2e56Smrg 1859f7df2e56Smrg nevents = 1860f7df2e56Smrg GetTouchEvents(InputEventList, device, ddx_touchid, type, flags, mask); 1861f7df2e56Smrg queueEventList(device, InputEventList, nevents); 1862f7df2e56Smrg} 1863f7df2e56Smrg 1864f7df2e56Smrg/** 1865f7df2e56Smrg * Get events for a touch. Generates a TouchBegin event if end is not set and 1866f7df2e56Smrg * the touch id is not active. Generates a TouchUpdate event if end is not set 1867f7df2e56Smrg * and the touch id is active. Generates a TouchEnd event if end is set and the 1868f7df2e56Smrg * touch id is active. 1869f7df2e56Smrg * 1870f7df2e56Smrg * events is not NULL-terminated; the return value is the number of events. 1871f7df2e56Smrg * The DDX is responsible for allocating the event structure in the first 1872f7df2e56Smrg * place via GetMaximumEventsNum(), and for freeing it. 1873f7df2e56Smrg * 1874f7df2e56Smrg * @param[out] events The list of events generated 1875f7df2e56Smrg * @param dev The device to generate the events for 1876f7df2e56Smrg * @param ddx_touchid The touch ID as assigned by the DDX 1877f7df2e56Smrg * @param type XI_TouchBegin, XI_TouchUpdate or XI_TouchEnd 1878f7df2e56Smrg * @param flags Event flags 1879f7df2e56Smrg * @param mask_in Valuator information for this event 1880f7df2e56Smrg */ 1881f7df2e56Smrgint 1882f7df2e56SmrgGetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid, 1883f7df2e56Smrg uint16_t type, uint32_t flags, const ValuatorMask *mask_in) 1884f7df2e56Smrg{ 1885f7df2e56Smrg ScreenPtr scr = dev->spriteInfo->sprite->hotPhys.pScreen; 1886f7df2e56Smrg TouchClassPtr t = dev->touch; 1887f7df2e56Smrg ValuatorClassPtr v = dev->valuator; 1888f7df2e56Smrg DeviceEvent *event; 1889f7df2e56Smrg CARD32 ms = GetTimeInMillis(); 1890f7df2e56Smrg ValuatorMask mask; 1891f7df2e56Smrg double screenx = 0.0, screeny = 0.0; /* desktop coordinate system */ 1892f7df2e56Smrg double devx = 0.0, devy = 0.0; /* desktop-wide in device coords */ 1893f7df2e56Smrg int i; 1894f7df2e56Smrg int num_events = 0; 1895f7df2e56Smrg RawDeviceEvent *raw; 1896f7df2e56Smrg DDXTouchPointInfoPtr ti; 1897f7df2e56Smrg int need_rawevent = TRUE; 1898f7df2e56Smrg Bool emulate_pointer = FALSE; 1899f7df2e56Smrg int client_id = 0; 1900f7df2e56Smrg 1901f7df2e56Smrg#if XSERVER_DTRACE 1902f7df2e56Smrg if (XSERVER_INPUT_EVENT_ENABLED()) { 1903f7df2e56Smrg XSERVER_INPUT_EVENT(dev->id, type, ddx_touchid, flags, 1904f7df2e56Smrg mask_in ? mask_in->last_bit + 1 : 0, 1905f7df2e56Smrg mask_in ? mask_in->mask : NULL, 1906f7df2e56Smrg mask_in ? mask_in->valuators : NULL); 1907f7df2e56Smrg } 1908f7df2e56Smrg#endif 1909f7df2e56Smrg 1910f7df2e56Smrg if (!dev->enabled || !t || !v) 1911f7df2e56Smrg return 0; 1912f7df2e56Smrg 1913f7df2e56Smrg /* Find and/or create the DDX touch info */ 1914f7df2e56Smrg 1915f7df2e56Smrg ti = TouchFindByDDXID(dev, ddx_touchid, (type == XI_TouchBegin)); 1916f7df2e56Smrg if (!ti) { 1917f7df2e56Smrg ErrorFSigSafe("[dix] %s: unable to %s touch point %u\n", dev->name, 1918f7df2e56Smrg type == XI_TouchBegin ? "begin" : "find", ddx_touchid); 1919f7df2e56Smrg return 0; 1920f7df2e56Smrg } 1921f7df2e56Smrg client_id = ti->client_id; 1922f7df2e56Smrg 1923f7df2e56Smrg emulate_pointer = ti->emulate_pointer; 1924f7df2e56Smrg 1925f7df2e56Smrg if (!IsMaster(dev)) 1926f7df2e56Smrg events = 1927f7df2e56Smrg UpdateFromMaster(events, dev, DEVCHANGE_POINTER_EVENT, &num_events); 1928f7df2e56Smrg 1929f7df2e56Smrg valuator_mask_copy(&mask, mask_in); 1930f7df2e56Smrg 1931f7df2e56Smrg if (need_rawevent) { 1932f7df2e56Smrg raw = &events->raw_event; 1933f7df2e56Smrg events++; 1934f7df2e56Smrg num_events++; 1935f7df2e56Smrg init_raw(dev, raw, ms, type, client_id); 1936f7df2e56Smrg set_raw_valuators(raw, &mask, TRUE, raw->valuators.data_raw); 1937f7df2e56Smrg } 1938f7df2e56Smrg 1939f7df2e56Smrg event = &events->device_event; 1940f7df2e56Smrg num_events++; 1941f7df2e56Smrg 1942f7df2e56Smrg init_device_event(event, dev, ms); 1943f7df2e56Smrg 1944f7df2e56Smrg switch (type) { 1945f7df2e56Smrg case XI_TouchBegin: 1946f7df2e56Smrg event->type = ET_TouchBegin; 1947f7df2e56Smrg /* If we're starting a touch, we must have x & y co-ordinates. */ 1948f7df2e56Smrg if (!mask_in || 1949f7df2e56Smrg !valuator_mask_isset(mask_in, 0) || 1950f7df2e56Smrg !valuator_mask_isset(mask_in, 1)) { 1951f7df2e56Smrg ErrorFSigSafe("%s: Attempted to start touch without x/y " 1952f7df2e56Smrg "(driver bug)\n", dev->name); 1953f7df2e56Smrg return 0; 1954f7df2e56Smrg } 1955f7df2e56Smrg break; 1956f7df2e56Smrg case XI_TouchUpdate: 1957f7df2e56Smrg event->type = ET_TouchUpdate; 1958f7df2e56Smrg if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0) { 1959f7df2e56Smrg ErrorFSigSafe("%s: TouchUpdate with no valuators? Driver bug\n", 1960f7df2e56Smrg dev->name); 1961f7df2e56Smrg } 1962f7df2e56Smrg break; 1963f7df2e56Smrg case XI_TouchEnd: 1964f7df2e56Smrg event->type = ET_TouchEnd; 1965f7df2e56Smrg /* We can end the DDX touch here, since we don't use the active 1966f7df2e56Smrg * field below */ 1967f7df2e56Smrg TouchEndDDXTouch(dev, ti); 1968f7df2e56Smrg break; 1969f7df2e56Smrg default: 1970f7df2e56Smrg return 0; 1971f7df2e56Smrg } 1972f7df2e56Smrg 1973f7df2e56Smrg /* Get our screen event co-ordinates (root_x/root_y/event_x/event_y): 1974f7df2e56Smrg * these come from the touchpoint in Absolute mode, or the sprite in 1975f7df2e56Smrg * Relative. */ 1976f7df2e56Smrg if (t->mode == XIDirectTouch) { 1977f7df2e56Smrg for (i = 0; i < max(valuator_mask_size(&mask), 2); i++) { 1978f7df2e56Smrg double val; 1979f7df2e56Smrg 1980f7df2e56Smrg if (valuator_mask_fetch_double(&mask, i, &val)) 1981f7df2e56Smrg valuator_mask_set_double(ti->valuators, i, val); 1982f7df2e56Smrg /* If the device doesn't post new X and Y axis values, 1983f7df2e56Smrg * use the last values posted. 1984f7df2e56Smrg */ 1985f7df2e56Smrg else if (i < 2 && 1986f7df2e56Smrg valuator_mask_fetch_double(ti->valuators, i, &val)) 1987f7df2e56Smrg valuator_mask_set_double(&mask, i, val); 1988f7df2e56Smrg } 1989f7df2e56Smrg 1990f7df2e56Smrg transformAbsolute(dev, &mask); 1991f7df2e56Smrg clipAbsolute(dev, &mask); 1992f7df2e56Smrg } 1993f7df2e56Smrg else { 1994f7df2e56Smrg screenx = dev->spriteInfo->sprite->hotPhys.x; 1995f7df2e56Smrg screeny = dev->spriteInfo->sprite->hotPhys.y; 1996f7df2e56Smrg } 1997f7df2e56Smrg if (need_rawevent) 1998f7df2e56Smrg set_raw_valuators(raw, &mask, FALSE, raw->valuators.data); 1999f7df2e56Smrg 2000f7df2e56Smrg /* Indirect device touch coordinates are not used for cursor positioning. 2001f7df2e56Smrg * They are merely informational, and are provided in device coordinates. 2002f7df2e56Smrg * The device sprite is used for positioning instead, and it is already 2003f7df2e56Smrg * scaled. */ 2004f7df2e56Smrg if (t->mode == XIDirectTouch) 2005f7df2e56Smrg scr = scale_to_desktop(dev, &mask, &devx, &devy, &screenx, &screeny); 2006f7df2e56Smrg if (emulate_pointer) 2007f7df2e56Smrg scr = positionSprite(dev, Absolute, &mask, 2008f7df2e56Smrg &devx, &devy, &screenx, &screeny, NULL, NULL); 2009f7df2e56Smrg 2010f7df2e56Smrg /* see fill_pointer_events for coordinate systems */ 2011f7df2e56Smrg if (emulate_pointer) 2012f7df2e56Smrg updateHistory(dev, &mask, ms); 2013f7df2e56Smrg 2014f7df2e56Smrg clipValuators(dev, &mask); 2015f7df2e56Smrg 2016f7df2e56Smrg if (emulate_pointer) 2017f7df2e56Smrg storeLastValuators(dev, &mask, 0, 1, devx, devy); 2018f7df2e56Smrg 2019f7df2e56Smrg /* Update the MD's co-ordinates, which are always in desktop space. */ 2020f7df2e56Smrg if (emulate_pointer && !IsMaster(dev) && !IsFloating(dev)) { 2021f7df2e56Smrg DeviceIntPtr master = GetMaster(dev, MASTER_POINTER); 2022f7df2e56Smrg 2023f7df2e56Smrg master->last.valuators[0] = screenx; 2024f7df2e56Smrg master->last.valuators[1] = screeny; 2025f7df2e56Smrg } 2026f7df2e56Smrg 2027f7df2e56Smrg event->root = scr->root->drawable.id; 2028f7df2e56Smrg 2029f7df2e56Smrg event_set_root_coordinates(event, screenx - scr->x, screeny - scr->y); 2030f7df2e56Smrg event->touchid = client_id; 2031f7df2e56Smrg event->flags = flags; 2032f7df2e56Smrg 2033f7df2e56Smrg if (emulate_pointer) { 2034f7df2e56Smrg event->flags |= TOUCH_POINTER_EMULATED; 2035f7df2e56Smrg event->detail.button = 1; 2036f7df2e56Smrg } 2037f7df2e56Smrg 2038f7df2e56Smrg set_valuators(dev, event, &mask); 2039f7df2e56Smrg for (i = 0; i < v->numAxes; i++) { 2040f7df2e56Smrg if (valuator_mask_isset(&mask, i)) 2041f7df2e56Smrg v->axisVal[i] = valuator_mask_get(&mask, i); 2042f7df2e56Smrg } 2043f7df2e56Smrg 2044f7df2e56Smrg return num_events; 2045f7df2e56Smrg} 2046f7df2e56Smrg 2047f7df2e56Smrgvoid 2048f7df2e56SmrgGetDixTouchEnd(InternalEvent *ievent, DeviceIntPtr dev, TouchPointInfoPtr ti, 2049f7df2e56Smrg uint32_t flags) 2050f7df2e56Smrg{ 2051f7df2e56Smrg ScreenPtr scr = dev->spriteInfo->sprite->hotPhys.pScreen; 2052f7df2e56Smrg DeviceEvent *event = &ievent->device_event; 2053f7df2e56Smrg CARD32 ms = GetTimeInMillis(); 2054f7df2e56Smrg 2055f7df2e56Smrg BUG_WARN(!dev->enabled); 2056f7df2e56Smrg 2057f7df2e56Smrg init_device_event(event, dev, ms); 2058f7df2e56Smrg 2059f7df2e56Smrg event->sourceid = ti->sourceid; 2060f7df2e56Smrg event->type = ET_TouchEnd; 2061f7df2e56Smrg 2062f7df2e56Smrg event->root = scr->root->drawable.id; 2063f7df2e56Smrg 2064f7df2e56Smrg /* Get screen event coordinates from the sprite. Is this really the best 2065f7df2e56Smrg * we can do? */ 2066f7df2e56Smrg event_set_root_coordinates(event, 2067f7df2e56Smrg dev->last.valuators[0] - scr->x, 2068f7df2e56Smrg dev->last.valuators[1] - scr->y); 2069f7df2e56Smrg event->touchid = ti->client_id; 2070f7df2e56Smrg event->flags = flags; 2071f7df2e56Smrg 2072f7df2e56Smrg if (flags & TOUCH_POINTER_EMULATED) { 2073f7df2e56Smrg event->flags |= TOUCH_POINTER_EMULATED; 2074f7df2e56Smrg event->detail.button = 1; 2075f7df2e56Smrg } 2076f7df2e56Smrg} 2077f7df2e56Smrg 207805b261ecSmrg/** 207905b261ecSmrg * Synthesize a single motion event for the core pointer. 208005b261ecSmrg * 208105b261ecSmrg * Used in cursor functions, e.g. when cursor confinement changes, and we need 208205b261ecSmrg * to shift the pointer to get it inside the new bounds. 208305b261ecSmrg */ 208405b261ecSmrgvoid 20854642e01fSmrgPostSyntheticMotion(DeviceIntPtr pDev, 2086f7df2e56Smrg int x, int y, int screen, unsigned long time) 208705b261ecSmrg{ 20884202a189Smrg DeviceEvent ev; 208905b261ecSmrg 209005b261ecSmrg#ifdef PANORAMIX 209105b261ecSmrg /* Translate back to the sprite screen since processInputProc 209205b261ecSmrg will translate from sprite screen to screen 0 upon reentry 209305b261ecSmrg to the DIX layer. */ 209405b261ecSmrg if (!noPanoramiXExtension) { 20954202a189Smrg x += screenInfo.screens[0]->x - screenInfo.screens[screen]->x; 20964202a189Smrg y += screenInfo.screens[0]->y - screenInfo.screens[screen]->y; 209705b261ecSmrg } 209805b261ecSmrg#endif 209905b261ecSmrg 21004202a189Smrg memset(&ev, 0, sizeof(DeviceEvent)); 2101f7df2e56Smrg init_device_event(&ev, pDev, time); 21024202a189Smrg ev.root_x = x; 21034202a189Smrg ev.root_y = y; 21044202a189Smrg ev.type = ET_Motion; 21054202a189Smrg ev.time = time; 210605b261ecSmrg 21074202a189Smrg /* FIXME: MD/SD considerations? */ 2108f7df2e56Smrg (*pDev->public.processInputProc) ((InternalEvent *) &ev, pDev); 210905b261ecSmrg} 2110