getevents.c revision 7e31ba66
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; 10957e31ba66Smrg enum DeviceEventSource source_type = EVENT_SOURCE_NORMAL; 1096f7df2e56Smrg 1097f7df2e56Smrg#if XSERVER_DTRACE 1098f7df2e56Smrg if (XSERVER_INPUT_EVENT_ENABLED()) { 1099f7df2e56Smrg XSERVER_INPUT_EVENT(pDev->id, type, key_code, 0, 0, 1100f7df2e56Smrg NULL, NULL); 1101f7df2e56Smrg } 1102f7df2e56Smrg#endif 11034202a189Smrg 11047e31ba66Smrg if (type == EnterNotify) { 11057e31ba66Smrg source_type = EVENT_SOURCE_FOCUS; 11067e31ba66Smrg type = KeyPress; 11077e31ba66Smrg } else if (type == LeaveNotify) { 11087e31ba66Smrg source_type = EVENT_SOURCE_FOCUS; 11097e31ba66Smrg type = KeyRelease; 11107e31ba66Smrg } 11117e31ba66Smrg 11124202a189Smrg /* refuse events from disabled devices */ 11134202a189Smrg if (!pDev->enabled) 11144202a189Smrg return 0; 111505b261ecSmrg 1116f7df2e56Smrg if (!events || !pDev->key || !pDev->focus || !pDev->kbdfeed || 1117f7df2e56Smrg (type != KeyPress && type != KeyRelease) || 1118f7df2e56Smrg (key_code < 8 || key_code > 255)) 111905b261ecSmrg return 0; 112005b261ecSmrg 11214202a189Smrg num_events = 1; 112205b261ecSmrg 1123f7df2e56Smrg events = 1124f7df2e56Smrg UpdateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events); 112505b261ecSmrg 11264202a189Smrg /* Handle core repeating, via press/release/press/release. */ 11274202a189Smrg if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) { 112805b261ecSmrg /* If autorepeating is disabled either globally or just for that key, 112905b261ecSmrg * or we have a modifier, don't generate a repeat event. */ 113005b261ecSmrg if (!pDev->kbdfeed->ctrl.autoRepeat || 113105b261ecSmrg !key_autorepeats(pDev, key_code) || 11324202a189Smrg pDev->key->xkbInfo->desc->map->modmap[key_code]) 113305b261ecSmrg return 0; 113405b261ecSmrg } 113505b261ecSmrg 113605b261ecSmrg ms = GetTimeInMillis(); 113705b261ecSmrg 11387e31ba66Smrg if (source_type == EVENT_SOURCE_NORMAL) { 11397e31ba66Smrg raw = &events->raw_event; 11407e31ba66Smrg init_raw(pDev, raw, ms, type, key_code); 11417e31ba66Smrg events++; 11427e31ba66Smrg num_events++; 11437e31ba66Smrg } 11444202a189Smrg 1145f7df2e56Smrg event = &events->device_event; 11467e31ba66Smrg init_device_event(event, pDev, ms, source_type); 11474202a189Smrg event->detail.key = key_code; 11484202a189Smrg 114905b261ecSmrg if (type == KeyPress) { 11504202a189Smrg event->type = ET_KeyPress; 1151f7df2e56Smrg set_key_down(pDev, key_code, KEY_POSTED); 115205b261ecSmrg } 115305b261ecSmrg else if (type == KeyRelease) { 11544202a189Smrg event->type = ET_KeyRelease; 1155f7df2e56Smrg set_key_up(pDev, key_code, KEY_POSTED); 115605b261ecSmrg } 115705b261ecSmrg 11584202a189Smrg return num_events; 115905b261ecSmrg} 116005b261ecSmrg 11614642e01fSmrg/** 1162f7df2e56Smrg * Initialize an event array large enough for num_events arrays. 11634642e01fSmrg * This event list is to be passed into GetPointerEvents() and 11644642e01fSmrg * GetKeyboardEvents(). 11654642e01fSmrg * 11664642e01fSmrg * @param num_events Number of elements in list. 11674642e01fSmrg */ 1168f7df2e56SmrgInternalEvent * 11694642e01fSmrgInitEventList(int num_events) 11704642e01fSmrg{ 1171f7df2e56Smrg InternalEvent *events = calloc(num_events, sizeof(InternalEvent)); 11724642e01fSmrg 11734642e01fSmrg return events; 11744642e01fSmrg} 11754642e01fSmrg 11764642e01fSmrg/** 11774642e01fSmrg * Free an event list. 11784642e01fSmrg * 11794642e01fSmrg * @param list The list to be freed. 11804642e01fSmrg * @param num_events Number of elements in list. 11814642e01fSmrg */ 11824202a189Smrgvoid 1183f7df2e56SmrgFreeEventList(InternalEvent *list, int num_events) 11844642e01fSmrg{ 11854202a189Smrg free(list); 11864202a189Smrg} 11874202a189Smrg 1188f7df2e56Smrg/** 1189f7df2e56Smrg * Transform vector x/y according to matrix m and drop the rounded coords 1190f7df2e56Smrg * back into x/y. 1191f7df2e56Smrg */ 1192f7df2e56Smrgstatic void 1193f7df2e56Smrgtransform(struct pixman_f_transform *m, double *x, double *y) 1194f7df2e56Smrg{ 1195f7df2e56Smrg struct pixman_f_vector p = {.v = {*x, *y, 1} }; 1196f7df2e56Smrg pixman_f_transform_point(m, &p); 1197f7df2e56Smrg 1198f7df2e56Smrg *x = p.v[0]; 1199f7df2e56Smrg *y = p.v[1]; 1200f7df2e56Smrg} 1201f7df2e56Smrg 1202f7df2e56Smrgstatic void 1203f7df2e56SmrgtransformRelative(DeviceIntPtr dev, ValuatorMask *mask) 1204f7df2e56Smrg{ 1205f7df2e56Smrg double x = 0, y = 0; 1206f7df2e56Smrg 1207f7df2e56Smrg valuator_mask_fetch_double(mask, 0, &x); 1208f7df2e56Smrg valuator_mask_fetch_double(mask, 1, &y); 1209f7df2e56Smrg 1210f7df2e56Smrg transform(&dev->relative_transform, &x, &y); 1211f7df2e56Smrg 1212f7df2e56Smrg if (x) 1213f7df2e56Smrg valuator_mask_set_double(mask, 0, x); 1214f7df2e56Smrg else 1215f7df2e56Smrg valuator_mask_unset(mask, 0); 1216f7df2e56Smrg 1217f7df2e56Smrg if (y) 1218f7df2e56Smrg valuator_mask_set_double(mask, 1, y); 1219f7df2e56Smrg else 1220f7df2e56Smrg valuator_mask_unset(mask, 1); 1221f7df2e56Smrg} 1222f7df2e56Smrg 1223f7df2e56Smrg/** 1224f7df2e56Smrg * Apply the device's transformation matrix to the valuator mask and replace 1225f7df2e56Smrg * the scaled values in mask. This transformation only applies to valuators 1226f7df2e56Smrg * 0 and 1, others will be untouched. 1227f7df2e56Smrg * 1228f7df2e56Smrg * @param dev The device the valuators came from 1229f7df2e56Smrg * @param[in,out] mask The valuator mask. 1230f7df2e56Smrg */ 12314202a189Smrgstatic void 123265b04b38SmrgtransformAbsolute(DeviceIntPtr dev, ValuatorMask *mask) 12334202a189Smrg{ 12347e31ba66Smrg double x, y, ox = 0.0, oy = 0.0; 1235f7df2e56Smrg int has_x, has_y; 12364202a189Smrg 1237f7df2e56Smrg has_x = valuator_mask_isset(mask, 0); 1238f7df2e56Smrg has_y = valuator_mask_isset(mask, 1); 12394202a189Smrg 1240f7df2e56Smrg if (!has_x && !has_y) 1241f7df2e56Smrg return; 12424202a189Smrg 1243f7df2e56Smrg if (!has_x || !has_y) { 1244f7df2e56Smrg struct pixman_f_transform invert; 1245f7df2e56Smrg 1246f7df2e56Smrg /* undo transformation from last event */ 1247f7df2e56Smrg ox = dev->last.valuators[0]; 1248f7df2e56Smrg oy = dev->last.valuators[1]; 1249f7df2e56Smrg 1250f7df2e56Smrg pixman_f_transform_invert(&invert, &dev->scale_and_transform); 1251f7df2e56Smrg transform(&invert, &ox, &oy); 1252f7df2e56Smrg } 1253f7df2e56Smrg 1254f7df2e56Smrg if (has_x) 1255f7df2e56Smrg ox = valuator_mask_get_double(mask, 0); 1256f7df2e56Smrg 1257f7df2e56Smrg if (has_y) 1258f7df2e56Smrg oy = valuator_mask_get_double(mask, 1); 1259f7df2e56Smrg 1260f7df2e56Smrg x = ox; 1261f7df2e56Smrg y = oy; 1262f7df2e56Smrg 1263f7df2e56Smrg transform(&dev->scale_and_transform, &x, &y); 1264f7df2e56Smrg 1265f7df2e56Smrg if (has_x || ox != x) 1266f7df2e56Smrg valuator_mask_set_double(mask, 0, x); 1267f7df2e56Smrg 1268f7df2e56Smrg if (has_y || oy != y) 1269f7df2e56Smrg valuator_mask_set_double(mask, 1, y); 1270f7df2e56Smrg} 1271f7df2e56Smrg 1272f7df2e56Smrgstatic void 1273f7df2e56SmrgstoreLastValuators(DeviceIntPtr dev, ValuatorMask *mask, 1274f7df2e56Smrg int xaxis, int yaxis, double devx, double devy) 1275f7df2e56Smrg{ 1276f7df2e56Smrg int i; 1277f7df2e56Smrg 1278f7df2e56Smrg /* store desktop-wide in last.valuators */ 1279f7df2e56Smrg if (valuator_mask_isset(mask, xaxis)) 1280f7df2e56Smrg dev->last.valuators[0] = devx; 1281f7df2e56Smrg if (valuator_mask_isset(mask, yaxis)) 1282f7df2e56Smrg dev->last.valuators[1] = devy; 1283f7df2e56Smrg 1284f7df2e56Smrg for (i = 0; i < valuator_mask_size(mask); i++) { 1285f7df2e56Smrg if (i == xaxis || i == yaxis) 1286f7df2e56Smrg continue; 1287f7df2e56Smrg 1288f7df2e56Smrg if (valuator_mask_isset(mask, i)) 1289f7df2e56Smrg dev->last.valuators[i] = valuator_mask_get_double(mask, i); 1290f7df2e56Smrg } 129145bb0b75Smrg 12924642e01fSmrg} 129305b261ecSmrg 129405b261ecSmrg/** 1295f7df2e56Smrg * Generate internal events representing this pointer event and enqueue them 1296f7df2e56Smrg * on the event queue. 129705b261ecSmrg * 1298f7df2e56Smrg * This function is not reentrant. Disable signals before calling. 12994642e01fSmrg * 1300f7df2e56Smrg * @param device The device to generate the event for 1301f7df2e56Smrg * @param type Event type, one of ButtonPress, ButtonRelease, MotionNotify 1302f7df2e56Smrg * @param buttons Button number of the buttons modified. Must be 0 for 1303f7df2e56Smrg * MotionNotify 1304f7df2e56Smrg * @param flags Event modification flags 1305f7df2e56Smrg * @param mask Valuator mask for valuators present for this event. 1306f7df2e56Smrg */ 1307f7df2e56Smrgvoid 1308f7df2e56SmrgQueuePointerEvents(DeviceIntPtr device, int type, 1309f7df2e56Smrg int buttons, int flags, const ValuatorMask *mask) 1310f7df2e56Smrg{ 1311f7df2e56Smrg int nevents; 1312f7df2e56Smrg 1313f7df2e56Smrg nevents = 1314f7df2e56Smrg GetPointerEvents(InputEventList, device, type, buttons, flags, mask); 1315f7df2e56Smrg queueEventList(device, InputEventList, nevents); 1316f7df2e56Smrg} 1317f7df2e56Smrg 1318f7df2e56Smrg/** 1319f7df2e56Smrg * Helper function for GetPointerEvents, which only generates motion and 1320f7df2e56Smrg * raw motion events for the slave device: does not update the master device. 13214642e01fSmrg * 1322f7df2e56Smrg * Should not be called by anyone other than GetPointerEvents. 13234642e01fSmrg * 1324f7df2e56Smrg * We use several different coordinate systems and need to switch between 1325f7df2e56Smrg * the three in fill_pointer_events, positionSprite and 1326f7df2e56Smrg * miPointerSetPosition. "desktop" refers to the width/height of all 1327f7df2e56Smrg * screenInfo.screens[n]->width/height added up. "screen" is ScreenRec, not 1328f7df2e56Smrg * output. 1329f7df2e56Smrg * 1330f7df2e56Smrg * Coordinate systems: 1331f7df2e56Smrg * - relative events have a mask_in in relative coordinates, mapped to 1332f7df2e56Smrg * pixels. These events are mapped to the current position±delta. 1333f7df2e56Smrg * - absolute events have a mask_in in absolute device coordinates in 1334f7df2e56Smrg * device-specific range. This range is mapped to the desktop. 1335f7df2e56Smrg * - POINTER_SCREEN absolute events (x86WarpCursor) are in screen-relative 1336f7df2e56Smrg * screen coordinate range. 1337f7df2e56Smrg * - rootx/rooty in events must be be relative to the current screen's 1338f7df2e56Smrg * origin (screen coordinate system) 1339f7df2e56Smrg * - XI2 valuators must be relative to the current screen's origin. On 1340f7df2e56Smrg * the protocol the device min/max range maps to the current screen. 1341f7df2e56Smrg * 1342f7df2e56Smrg * For screen switching we need to get the desktop coordinates for each 1343f7df2e56Smrg * event, then map that to the respective position on each screen and 1344f7df2e56Smrg * position the cursor there. 1345f7df2e56Smrg * The device's last.valuator[] stores the last position in desktop-wide 1346f7df2e56Smrg * coordinates (in device range for slave devices, desktop range for master 1347f7df2e56Smrg * devices). 1348f7df2e56Smrg * 1349f7df2e56Smrg * screen-relative device coordinates requires scaling: A device coordinate 1350f7df2e56Smrg * x/y of range [n..m] that maps to positions Sx/Sy on Screen S must be 1351f7df2e56Smrg * rescaled to match Sx/Sy for [n..m]. In the simplest example, x of (m/2-1) 1352f7df2e56Smrg * is the last coordinate on the first screen and must be rescaled for the 1353f7df2e56Smrg * event to be m. XI2 clients that do their own coordinate mapping would 1354f7df2e56Smrg * otherwise interpret the position of the device elsewere to the cursor. 1355f7df2e56Smrg * However, this scaling leads to losses: 1356f7df2e56Smrg * if we have two ScreenRecs we scale from e.g. [0..44704] (Wacom I4) to 1357f7df2e56Smrg * [0..2048[. that gives us 2047.954 as desktop coord, or the per-screen 1358f7df2e56Smrg * coordinate 1023.954. Scaling that back into the device coordinate range 1359f7df2e56Smrg * gives us 44703. So off by one device unit. It's a bug, but we'll have to 1360f7df2e56Smrg * live with it because with all this scaling, we just cannot win. 1361f7df2e56Smrg * 1362f7df2e56Smrg * @return the number of events written into events. 136305b261ecSmrg */ 1364f7df2e56Smrgstatic int 1365f7df2e56Smrgfill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type, 1366f7df2e56Smrg int buttons, CARD32 ms, int flags, 1367f7df2e56Smrg const ValuatorMask *mask_in) 1368f7df2e56Smrg{ 13694642e01fSmrg int num_events = 1; 13704202a189Smrg DeviceEvent *event; 1371f7df2e56Smrg RawDeviceEvent *raw = NULL; 1372f7df2e56Smrg double screenx = 0.0, screeny = 0.0; /* desktop coordinate system */ 1373f7df2e56Smrg double devx = 0.0, devy = 0.0; /* desktop-wide in device coords */ 1374f7df2e56Smrg int sx = 0, sy = 0; /* for POINTER_SCREEN */ 137565b04b38Smrg ValuatorMask mask; 1376f7df2e56Smrg ScreenPtr scr; 1377f7df2e56Smrg int num_barrier_events = 0; 1378f7df2e56Smrg 1379f7df2e56Smrg switch (type) { 1380f7df2e56Smrg case MotionNotify: 1381f7df2e56Smrg if (!pDev->valuator) { 1382f7df2e56Smrg ErrorF("[dix] motion events from device %d without valuators\n", 1383f7df2e56Smrg pDev->id); 1384f7df2e56Smrg return 0; 1385f7df2e56Smrg } 1386f7df2e56Smrg if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0) 1387f7df2e56Smrg return 0; 1388f7df2e56Smrg break; 1389f7df2e56Smrg case ButtonPress: 1390f7df2e56Smrg case ButtonRelease: 1391f7df2e56Smrg if (!pDev->button || !buttons) 1392f7df2e56Smrg return 0; 1393f7df2e56Smrg if (mask_in && valuator_mask_size(mask_in) > 0 && !pDev->valuator) { 1394f7df2e56Smrg ErrorF 1395f7df2e56Smrg ("[dix] button event with valuator from device %d without valuators\n", 1396f7df2e56Smrg pDev->id); 1397f7df2e56Smrg return 0; 1398f7df2e56Smrg } 1399f7df2e56Smrg break; 1400f7df2e56Smrg default: 14014202a189Smrg return 0; 1402f7df2e56Smrg } 140305b261ecSmrg 1404f7df2e56Smrg valuator_mask_copy(&mask, mask_in); 140505b261ecSmrg 1406f7df2e56Smrg if ((flags & POINTER_NORAW) == 0) { 1407f7df2e56Smrg raw = &events->raw_event; 1408f7df2e56Smrg events++; 1409f7df2e56Smrg num_events++; 1410f7df2e56Smrg 1411f7df2e56Smrg init_raw(pDev, raw, ms, type, buttons); 1412f7df2e56Smrg set_raw_valuators(raw, &mask, TRUE, raw->valuators.data_raw); 141365b04b38Smrg } 141465b04b38Smrg 1415f7df2e56Smrg valuator_mask_drop_unaccelerated(&mask); 141665b04b38Smrg 1417f7df2e56Smrg /* valuators are in driver-native format (rel or abs) */ 14184202a189Smrg 1419f7df2e56Smrg if (flags & POINTER_ABSOLUTE) { 1420f7df2e56Smrg if (flags & (POINTER_SCREEN | POINTER_DESKTOP)) { /* valuators are in screen/desktop coords */ 1421f7df2e56Smrg sx = valuator_mask_get(&mask, 0); 1422f7df2e56Smrg sy = valuator_mask_get(&mask, 1); 1423f7df2e56Smrg scale_from_screen(pDev, &mask, flags); 1424f7df2e56Smrg } 14254202a189Smrg 1426f7df2e56Smrg transformAbsolute(pDev, &mask); 1427f7df2e56Smrg clipAbsolute(pDev, &mask); 1428f7df2e56Smrg if ((flags & POINTER_NORAW) == 0 && raw) 1429f7df2e56Smrg set_raw_valuators(raw, &mask, FALSE, raw->valuators.data); 1430f7df2e56Smrg } 1431f7df2e56Smrg else { 1432f7df2e56Smrg transformRelative(pDev, &mask); 1433f7df2e56Smrg 1434f7df2e56Smrg if (flags & POINTER_ACCELERATE) 1435f7df2e56Smrg accelPointer(pDev, &mask, ms); 1436f7df2e56Smrg if ((flags & POINTER_NORAW) == 0 && raw) 1437f7df2e56Smrg set_raw_valuators(raw, &mask, FALSE, raw->valuators.data); 143845bb0b75Smrg 1439f7df2e56Smrg moveRelative(pDev, flags, &mask); 144045bb0b75Smrg } 144105b261ecSmrg 1442f7df2e56Smrg /* valuators are in device coordinate system in absolute coordinates */ 1443f7df2e56Smrg scale_to_desktop(pDev, &mask, &devx, &devy, &screenx, &screeny); 144405b261ecSmrg 1445f7df2e56Smrg /* #53037 XWarpPointer's scaling back and forth between screen and 1446f7df2e56Smrg device may leave us with rounding errors. End result is that the 1447f7df2e56Smrg pointer doesn't end up on the pixel it should. 1448f7df2e56Smrg Avoid this by forcing screenx/screeny back to what the input 1449f7df2e56Smrg coordinates were. 1450f7df2e56Smrg */ 1451f7df2e56Smrg if (flags & POINTER_SCREEN) { 1452f7df2e56Smrg scr = miPointerGetScreen(pDev); 1453f7df2e56Smrg screenx = sx + scr->x; 1454f7df2e56Smrg screeny = sy + scr->y; 145505b261ecSmrg } 145605b261ecSmrg 1457f7df2e56Smrg scr = positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative, 1458f7df2e56Smrg &mask, &devx, &devy, &screenx, &screeny, 1459f7df2e56Smrg &num_barrier_events, events); 1460f7df2e56Smrg num_events += num_barrier_events; 1461f7df2e56Smrg events += num_barrier_events; 146205b261ecSmrg 1463f7df2e56Smrg /* screenx, screeny are in desktop coordinates, 1464f7df2e56Smrg mask is in device coordinates per-screen (the event data) 1465f7df2e56Smrg devx/devy is in device coordinate desktop-wide */ 146665b04b38Smrg updateHistory(pDev, &mask, ms); 146705b261ecSmrg 146865b04b38Smrg clipValuators(pDev, &mask); 14694202a189Smrg 1470f7df2e56Smrg storeLastValuators(pDev, &mask, 0, 1, devx, devy); 1471f7df2e56Smrg 1472f7df2e56Smrg /* Update the MD's co-ordinates, which are always in desktop space. */ 1473f7df2e56Smrg if (!IsMaster(pDev) && !IsFloating(pDev)) { 1474f7df2e56Smrg DeviceIntPtr master = GetMaster(pDev, MASTER_POINTER); 1475f7df2e56Smrg 1476f7df2e56Smrg master->last.valuators[0] = screenx; 1477f7df2e56Smrg master->last.valuators[1] = screeny; 1478f7df2e56Smrg } 1479f7df2e56Smrg 1480f7df2e56Smrg event = &events->device_event; 14817e31ba66Smrg init_device_event(event, pDev, ms, EVENT_SOURCE_NORMAL); 148205b261ecSmrg 14834642e01fSmrg if (type == MotionNotify) { 14844202a189Smrg event->type = ET_Motion; 14854202a189Smrg event->detail.button = 0; 14864642e01fSmrg } 14874642e01fSmrg else { 14884202a189Smrg if (type == ButtonPress) { 14894202a189Smrg event->type = ET_ButtonPress; 14904202a189Smrg set_button_down(pDev, buttons, BUTTON_POSTED); 14914202a189Smrg } 14924202a189Smrg else if (type == ButtonRelease) { 14934202a189Smrg event->type = ET_ButtonRelease; 14944202a189Smrg set_button_up(pDev, buttons, BUTTON_POSTED); 14954202a189Smrg } 14964202a189Smrg event->detail.button = buttons; 14974642e01fSmrg } 149805b261ecSmrg 1499f7df2e56Smrg /* root_x and root_y must be in per-screen co-ordinates */ 1500f7df2e56Smrg event_set_root_coordinates(event, screenx - scr->x, screeny - scr->y); 1501f7df2e56Smrg 1502f7df2e56Smrg if (flags & POINTER_EMULATED) { 1503f7df2e56Smrg if (raw) 1504f7df2e56Smrg raw->flags = XIPointerEmulated; 1505f7df2e56Smrg event->flags = XIPointerEmulated; 1506f7df2e56Smrg } 150705b261ecSmrg 150865b04b38Smrg set_valuators(pDev, event, &mask); 150905b261ecSmrg 151005b261ecSmrg return num_events; 151105b261ecSmrg} 151205b261ecSmrg 1513f7df2e56Smrg/** 1514f7df2e56Smrg * Generate events for each scroll axis that changed between before/after 1515f7df2e56Smrg * for the device. 1516f7df2e56Smrg * 1517f7df2e56Smrg * @param events The pointer to the event list to fill the events 1518f7df2e56Smrg * @param dev The device to generate the events for 1519f7df2e56Smrg * @param type The real type of the event 1520f7df2e56Smrg * @param axis The axis number to generate events for 1521f7df2e56Smrg * @param mask State before this event in absolute coords 1522f7df2e56Smrg * @param[in,out] last Last scroll state posted in absolute coords (modified 1523f7df2e56Smrg * in-place) 1524f7df2e56Smrg * @param ms Current time in ms 1525f7df2e56Smrg * @param max_events Max number of events to be generated 1526f7df2e56Smrg * @return The number of events generated 1527f7df2e56Smrg */ 1528f7df2e56Smrgstatic int 1529f7df2e56Smrgemulate_scroll_button_events(InternalEvent *events, 1530f7df2e56Smrg DeviceIntPtr dev, 1531f7df2e56Smrg int type, 1532f7df2e56Smrg int axis, 1533f7df2e56Smrg const ValuatorMask *mask, 1534f7df2e56Smrg ValuatorMask *last, CARD32 ms, int max_events) 1535f7df2e56Smrg{ 1536f7df2e56Smrg AxisInfoPtr ax; 1537f7df2e56Smrg double delta; 1538f7df2e56Smrg double incr; 1539f7df2e56Smrg int num_events = 0; 1540f7df2e56Smrg double total; 1541f7df2e56Smrg int b; 1542f7df2e56Smrg int flags = 0; 1543f7df2e56Smrg 1544f7df2e56Smrg if (dev->valuator->axes[axis].scroll.type == SCROLL_TYPE_NONE) 1545f7df2e56Smrg return 0; 1546f7df2e56Smrg 1547f7df2e56Smrg if (!valuator_mask_isset(mask, axis)) 1548f7df2e56Smrg return 0; 1549f7df2e56Smrg 1550f7df2e56Smrg ax = &dev->valuator->axes[axis]; 1551f7df2e56Smrg incr = ax->scroll.increment; 1552f7df2e56Smrg 1553f7df2e56Smrg BUG_WARN_MSG(incr == 0, "for device %s\n", dev->name); 1554f7df2e56Smrg if (incr == 0) 1555f7df2e56Smrg return 0; 1556f7df2e56Smrg 1557f7df2e56Smrg if (type != ButtonPress && type != ButtonRelease) 1558f7df2e56Smrg flags |= POINTER_EMULATED; 1559f7df2e56Smrg 1560f7df2e56Smrg if (!valuator_mask_isset(last, axis)) 1561f7df2e56Smrg valuator_mask_set_double(last, axis, 0); 1562f7df2e56Smrg 1563f7df2e56Smrg delta = 1564f7df2e56Smrg valuator_mask_get_double(mask, axis) - valuator_mask_get_double(last, 1565f7df2e56Smrg axis); 1566f7df2e56Smrg total = delta; 1567f7df2e56Smrg b = (ax->scroll.type == SCROLL_TYPE_VERTICAL) ? 5 : 7; 1568f7df2e56Smrg 1569f7df2e56Smrg if ((incr > 0 && delta < 0) || (incr < 0 && delta > 0)) 1570f7df2e56Smrg b--; /* we're scrolling up or left → button 4 or 6 */ 1571f7df2e56Smrg 1572f7df2e56Smrg while (fabs(delta) >= fabs(incr)) { 1573f7df2e56Smrg int nev_tmp; 1574f7df2e56Smrg 1575f7df2e56Smrg if (delta > 0) 1576f7df2e56Smrg delta -= fabs(incr); 1577f7df2e56Smrg else if (delta < 0) 1578f7df2e56Smrg delta += fabs(incr); 1579f7df2e56Smrg 1580f7df2e56Smrg /* fill_pointer_events() generates four events: one normal and one raw 1581f7df2e56Smrg * event for button press and button release. 1582f7df2e56Smrg * We may get a bigger scroll delta than we can generate events 1583f7df2e56Smrg * for. In that case, we keep decreasing delta, but skip events. 1584f7df2e56Smrg */ 1585f7df2e56Smrg if (num_events + 4 < max_events) { 1586f7df2e56Smrg if (type != ButtonRelease) { 1587f7df2e56Smrg nev_tmp = fill_pointer_events(events, dev, ButtonPress, b, ms, 1588f7df2e56Smrg flags, NULL); 1589f7df2e56Smrg events += nev_tmp; 1590f7df2e56Smrg num_events += nev_tmp; 1591f7df2e56Smrg } 1592f7df2e56Smrg if (type != ButtonPress) { 1593f7df2e56Smrg nev_tmp = fill_pointer_events(events, dev, ButtonRelease, b, ms, 1594f7df2e56Smrg flags, NULL); 1595f7df2e56Smrg events += nev_tmp; 1596f7df2e56Smrg num_events += nev_tmp; 1597f7df2e56Smrg } 1598f7df2e56Smrg } 1599f7df2e56Smrg } 1600f7df2e56Smrg 1601f7df2e56Smrg /* We emulated, update last.scroll */ 1602f7df2e56Smrg if (total != delta) { 1603f7df2e56Smrg total -= delta; 1604f7df2e56Smrg valuator_mask_set_double(last, axis, 1605f7df2e56Smrg valuator_mask_get_double(last, axis) + total); 1606f7df2e56Smrg } 1607f7df2e56Smrg 1608f7df2e56Smrg return num_events; 1609f7df2e56Smrg} 1610f7df2e56Smrg 161105b261ecSmrg 161205b261ecSmrg/** 1613f7df2e56Smrg * Generate a complete series of InternalEvents (filled into the EventList) 1614f7df2e56Smrg * representing pointer motion, or button presses. If the device is a slave 1615f7df2e56Smrg * device, also potentially generate a DeviceClassesChangedEvent to update 1616f7df2e56Smrg * the master device. 161705b261ecSmrg * 161805b261ecSmrg * events is not NULL-terminated; the return value is the number of events. 161905b261ecSmrg * The DDX is responsible for allocating the event structure in the first 1620f7df2e56Smrg * place via InitEventList() and GetMaximumEventsNum(), and for freeing it. 1621f7df2e56Smrg * 1622f7df2e56Smrg * In the generated events rootX/Y will be in absolute screen coords and 1623f7df2e56Smrg * the valuator information in the absolute or relative device coords. 1624f7df2e56Smrg * 1625f7df2e56Smrg * last.valuators[x] of the device is always in absolute device coords. 1626f7df2e56Smrg * last.valuators[x] of the master device is in absolute screen coords. 1627f7df2e56Smrg * 1628f7df2e56Smrg * master->last.valuators[x] for x > 2 is undefined. 1629f7df2e56Smrg */ 1630f7df2e56Smrgint 1631f7df2e56SmrgGetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, 1632f7df2e56Smrg int buttons, int flags, const ValuatorMask *mask_in) 1633f7df2e56Smrg{ 1634f7df2e56Smrg CARD32 ms = GetTimeInMillis(); 1635f7df2e56Smrg int num_events = 0, nev_tmp; 1636f7df2e56Smrg ValuatorMask mask; 1637f7df2e56Smrg ValuatorMask scroll; 1638f7df2e56Smrg int i; 1639f7df2e56Smrg int realtype = type; 1640f7df2e56Smrg 1641f7df2e56Smrg#if XSERVER_DTRACE 1642f7df2e56Smrg if (XSERVER_INPUT_EVENT_ENABLED()) { 1643f7df2e56Smrg XSERVER_INPUT_EVENT(pDev->id, type, buttons, flags, 1644f7df2e56Smrg mask_in ? mask_in->last_bit + 1 : 0, 1645f7df2e56Smrg mask_in ? mask_in->mask : NULL, 1646f7df2e56Smrg mask_in ? mask_in->valuators : NULL); 1647f7df2e56Smrg } 1648f7df2e56Smrg#endif 1649f7df2e56Smrg 1650f7df2e56Smrg BUG_RETURN_VAL(buttons >= MAX_BUTTONS, 0); 1651f7df2e56Smrg 1652f7df2e56Smrg /* refuse events from disabled devices */ 1653f7df2e56Smrg if (!pDev->enabled) 1654f7df2e56Smrg return 0; 1655f7df2e56Smrg 1656f7df2e56Smrg if (!miPointerGetScreen(pDev)) 1657f7df2e56Smrg return 0; 1658f7df2e56Smrg 1659f7df2e56Smrg events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, 1660f7df2e56Smrg &num_events); 1661f7df2e56Smrg 1662f7df2e56Smrg valuator_mask_copy(&mask, mask_in); 1663f7df2e56Smrg 1664f7df2e56Smrg /* Turn a scroll button press into a smooth-scrolling event if 1665f7df2e56Smrg * necessary. This only needs to cater for the XIScrollFlagPreferred 1666f7df2e56Smrg * axis (if more than one scrolling axis is present) */ 1667f7df2e56Smrg if (type == ButtonPress) { 1668f7df2e56Smrg double adj; 1669f7df2e56Smrg int axis; 1670f7df2e56Smrg int h_scroll_axis = -1; 1671f7df2e56Smrg int v_scroll_axis = -1; 1672f7df2e56Smrg 1673f7df2e56Smrg if (pDev->valuator) { 1674f7df2e56Smrg h_scroll_axis = pDev->valuator->h_scroll_axis; 1675f7df2e56Smrg v_scroll_axis = pDev->valuator->v_scroll_axis; 1676f7df2e56Smrg } 1677f7df2e56Smrg 1678f7df2e56Smrg /* Up is negative on valuators, down positive */ 1679f7df2e56Smrg switch (buttons) { 1680f7df2e56Smrg case 4: 1681f7df2e56Smrg adj = -1.0; 1682f7df2e56Smrg axis = v_scroll_axis; 1683f7df2e56Smrg break; 1684f7df2e56Smrg case 5: 1685f7df2e56Smrg adj = 1.0; 1686f7df2e56Smrg axis = v_scroll_axis; 1687f7df2e56Smrg break; 1688f7df2e56Smrg case 6: 1689f7df2e56Smrg adj = -1.0; 1690f7df2e56Smrg axis = h_scroll_axis; 1691f7df2e56Smrg break; 1692f7df2e56Smrg case 7: 1693f7df2e56Smrg adj = 1.0; 1694f7df2e56Smrg axis = h_scroll_axis; 1695f7df2e56Smrg break; 1696f7df2e56Smrg default: 1697f7df2e56Smrg adj = 0.0; 1698f7df2e56Smrg axis = -1; 1699f7df2e56Smrg break; 1700f7df2e56Smrg } 1701f7df2e56Smrg 1702f7df2e56Smrg if (adj != 0.0 && axis != -1) { 1703f7df2e56Smrg adj *= pDev->valuator->axes[axis].scroll.increment; 1704f7df2e56Smrg if (!valuator_mask_isset(&mask, axis)) 1705f7df2e56Smrg valuator_mask_set(&mask, axis, 0); 1706f7df2e56Smrg add_to_scroll_valuator(pDev, &mask, axis, adj); 1707f7df2e56Smrg type = MotionNotify; 1708f7df2e56Smrg buttons = 0; 1709f7df2e56Smrg flags |= POINTER_EMULATED; 1710f7df2e56Smrg } 1711f7df2e56Smrg } 1712f7df2e56Smrg 1713f7df2e56Smrg /* First fill out the original event set, with smooth-scrolling axes. */ 1714f7df2e56Smrg nev_tmp = fill_pointer_events(events, pDev, type, buttons, ms, flags, 1715f7df2e56Smrg &mask); 1716f7df2e56Smrg events += nev_tmp; 1717f7df2e56Smrg num_events += nev_tmp; 1718f7df2e56Smrg 1719f7df2e56Smrg valuator_mask_zero(&scroll); 1720f7df2e56Smrg 1721f7df2e56Smrg /* Now turn the smooth-scrolling axes back into emulated button presses 1722f7df2e56Smrg * for legacy clients, based on the integer delta between before and now */ 1723f7df2e56Smrg for (i = 0; i < valuator_mask_size(&mask); i++) { 1724f7df2e56Smrg if ( !pDev->valuator || (i >= pDev->valuator->numAxes)) 1725f7df2e56Smrg break; 1726f7df2e56Smrg 1727f7df2e56Smrg if (!valuator_mask_isset(&mask, i)) 1728f7df2e56Smrg continue; 1729f7df2e56Smrg 1730f7df2e56Smrg valuator_mask_set_double(&scroll, i, pDev->last.valuators[i]); 1731f7df2e56Smrg 1732f7df2e56Smrg nev_tmp = 1733f7df2e56Smrg emulate_scroll_button_events(events, pDev, realtype, i, &scroll, 1734f7df2e56Smrg pDev->last.scroll, ms, 1735f7df2e56Smrg GetMaximumEventsNum() - num_events); 1736f7df2e56Smrg events += nev_tmp; 1737f7df2e56Smrg num_events += nev_tmp; 1738f7df2e56Smrg } 1739f7df2e56Smrg 1740f7df2e56Smrg return num_events; 1741f7df2e56Smrg} 1742f7df2e56Smrg 1743f7df2e56Smrg/** 1744f7df2e56Smrg * Generate internal events representing this proximity event and enqueue 1745f7df2e56Smrg * them on the event queue. 1746f7df2e56Smrg * 1747f7df2e56Smrg * This function is not reentrant. Disable signals before calling. 1748f7df2e56Smrg * 1749f7df2e56Smrg * @param device The device to generate the event for 1750f7df2e56Smrg * @param type Event type, one of ProximityIn or ProximityOut 1751f7df2e56Smrg * @param keycode Key code of the pressed/released key 1752f7df2e56Smrg * @param mask Valuator mask for valuators present for this event. 1753f7df2e56Smrg * 1754f7df2e56Smrg */ 1755f7df2e56Smrgvoid 1756f7df2e56SmrgQueueProximityEvents(DeviceIntPtr device, int type, const ValuatorMask *mask) 1757f7df2e56Smrg{ 1758f7df2e56Smrg int nevents; 1759f7df2e56Smrg 1760f7df2e56Smrg nevents = GetProximityEvents(InputEventList, device, type, mask); 1761f7df2e56Smrg queueEventList(device, InputEventList, nevents); 1762f7df2e56Smrg} 1763f7df2e56Smrg 1764f7df2e56Smrg/** 1765f7df2e56Smrg * Generate ProximityIn/ProximityOut InternalEvents, accompanied by 1766f7df2e56Smrg * valuators. 1767f7df2e56Smrg * 1768f7df2e56Smrg * The DDX is responsible for allocating the events in the first place via 1769f7df2e56Smrg * InitEventList(), and for freeing it. 1770f7df2e56Smrg * 1771f7df2e56Smrg * @return the number of events written into events. 177205b261ecSmrg */ 17734202a189Smrgint 1774f7df2e56SmrgGetProximityEvents(InternalEvent *events, DeviceIntPtr pDev, int type, 1775f7df2e56Smrg const ValuatorMask *mask_in) 177605b261ecSmrg{ 177765b04b38Smrg int num_events = 1, i; 17784202a189Smrg DeviceEvent *event; 177965b04b38Smrg ValuatorMask mask; 17804202a189Smrg 1781f7df2e56Smrg#if XSERVER_DTRACE 1782f7df2e56Smrg if (XSERVER_INPUT_EVENT_ENABLED()) { 1783f7df2e56Smrg XSERVER_INPUT_EVENT(pDev->id, type, 0, 0, 1784f7df2e56Smrg mask_in ? mask_in->last_bit + 1 : 0, 1785f7df2e56Smrg mask_in ? mask_in->mask : NULL, 1786f7df2e56Smrg mask_in ? mask_in->valuators : NULL); 1787f7df2e56Smrg } 1788f7df2e56Smrg#endif 1789f7df2e56Smrg 17904202a189Smrg /* refuse events from disabled devices */ 17914202a189Smrg if (!pDev->enabled) 17924202a189Smrg return 0; 179305b261ecSmrg 179405b261ecSmrg /* Sanity checks. */ 179565b04b38Smrg if ((type != ProximityIn && type != ProximityOut) || !mask_in) 179605b261ecSmrg return 0; 1797f7df2e56Smrg if (!pDev->valuator || !pDev->proximity) 179805b261ecSmrg return 0; 179905b261ecSmrg 180065b04b38Smrg valuator_mask_copy(&mask, mask_in); 180165b04b38Smrg 180265b04b38Smrg /* ignore relative axes for proximity. */ 1803f7df2e56Smrg for (i = 0; i < valuator_mask_size(&mask); i++) { 180465b04b38Smrg if (valuator_mask_isset(&mask, i) && 180565b04b38Smrg valuator_get_mode(pDev, i) == Relative) 180665b04b38Smrg valuator_mask_unset(&mask, i); 180765b04b38Smrg } 180865b04b38Smrg 180965b04b38Smrg /* FIXME: posting proximity events with relative valuators only results 181065b04b38Smrg * in an empty event, EventToXI() will fail to convert → no event sent 181165b04b38Smrg * to client. */ 181205b261ecSmrg 1813f7df2e56Smrg events = 1814f7df2e56Smrg UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); 18154642e01fSmrg 1816f7df2e56Smrg event = &events->device_event; 18177e31ba66Smrg init_device_event(event, pDev, GetTimeInMillis(), EVENT_SOURCE_NORMAL); 18184202a189Smrg event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut; 181905b261ecSmrg 182065b04b38Smrg clipValuators(pDev, &mask); 182105b261ecSmrg 182265b04b38Smrg set_valuators(pDev, event, &mask); 18234202a189Smrg 182405b261ecSmrg return num_events; 182505b261ecSmrg} 182605b261ecSmrg 1827f7df2e56Smrgint 1828f7df2e56SmrgGetTouchOwnershipEvents(InternalEvent *events, DeviceIntPtr pDev, 1829f7df2e56Smrg TouchPointInfoPtr ti, uint8_t reason, XID resource, 1830f7df2e56Smrg uint32_t flags) 1831f7df2e56Smrg{ 1832f7df2e56Smrg TouchClassPtr t = pDev->touch; 1833f7df2e56Smrg TouchOwnershipEvent *event; 1834f7df2e56Smrg CARD32 ms = GetTimeInMillis(); 1835f7df2e56Smrg 1836f7df2e56Smrg if (!pDev->enabled || !t || !ti) 1837f7df2e56Smrg return 0; 1838f7df2e56Smrg 1839f7df2e56Smrg event = &events->touch_ownership_event; 1840f7df2e56Smrg init_touch_ownership(pDev, event, ms); 1841f7df2e56Smrg 1842f7df2e56Smrg event->touchid = ti->client_id; 1843f7df2e56Smrg event->sourceid = ti->sourceid; 1844f7df2e56Smrg event->resource = resource; 1845f7df2e56Smrg event->flags = flags; 1846f7df2e56Smrg event->reason = reason; 1847f7df2e56Smrg 1848f7df2e56Smrg return 1; 1849f7df2e56Smrg} 1850f7df2e56Smrg 1851f7df2e56Smrg/** 1852f7df2e56Smrg * Generate internal events representing this touch event and enqueue them 1853f7df2e56Smrg * on the event queue. 1854f7df2e56Smrg * 1855f7df2e56Smrg * This function is not reentrant. Disable signals before calling. 1856f7df2e56Smrg * 1857f7df2e56Smrg * @param device The device to generate the event for 1858f7df2e56Smrg * @param type Event type, one of XI_TouchBegin, XI_TouchUpdate, XI_TouchEnd 1859f7df2e56Smrg * @param touchid Touch point ID 1860f7df2e56Smrg * @param flags Event modification flags 1861f7df2e56Smrg * @param mask Valuator mask for valuators present for this event. 1862f7df2e56Smrg */ 1863f7df2e56Smrgvoid 1864f7df2e56SmrgQueueTouchEvents(DeviceIntPtr device, int type, 1865f7df2e56Smrg uint32_t ddx_touchid, int flags, const ValuatorMask *mask) 1866f7df2e56Smrg{ 1867f7df2e56Smrg int nevents; 1868f7df2e56Smrg 1869f7df2e56Smrg nevents = 1870f7df2e56Smrg GetTouchEvents(InputEventList, device, ddx_touchid, type, flags, mask); 1871f7df2e56Smrg queueEventList(device, InputEventList, nevents); 1872f7df2e56Smrg} 1873f7df2e56Smrg 1874f7df2e56Smrg/** 1875f7df2e56Smrg * Get events for a touch. Generates a TouchBegin event if end is not set and 1876f7df2e56Smrg * the touch id is not active. Generates a TouchUpdate event if end is not set 1877f7df2e56Smrg * and the touch id is active. Generates a TouchEnd event if end is set and the 1878f7df2e56Smrg * touch id is active. 1879f7df2e56Smrg * 1880f7df2e56Smrg * events is not NULL-terminated; the return value is the number of events. 1881f7df2e56Smrg * The DDX is responsible for allocating the event structure in the first 1882f7df2e56Smrg * place via GetMaximumEventsNum(), and for freeing it. 1883f7df2e56Smrg * 1884f7df2e56Smrg * @param[out] events The list of events generated 1885f7df2e56Smrg * @param dev The device to generate the events for 1886f7df2e56Smrg * @param ddx_touchid The touch ID as assigned by the DDX 1887f7df2e56Smrg * @param type XI_TouchBegin, XI_TouchUpdate or XI_TouchEnd 1888f7df2e56Smrg * @param flags Event flags 1889f7df2e56Smrg * @param mask_in Valuator information for this event 1890f7df2e56Smrg */ 1891f7df2e56Smrgint 1892f7df2e56SmrgGetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid, 1893f7df2e56Smrg uint16_t type, uint32_t flags, const ValuatorMask *mask_in) 1894f7df2e56Smrg{ 1895f7df2e56Smrg ScreenPtr scr = dev->spriteInfo->sprite->hotPhys.pScreen; 1896f7df2e56Smrg TouchClassPtr t = dev->touch; 1897f7df2e56Smrg ValuatorClassPtr v = dev->valuator; 1898f7df2e56Smrg DeviceEvent *event; 1899f7df2e56Smrg CARD32 ms = GetTimeInMillis(); 1900f7df2e56Smrg ValuatorMask mask; 1901f7df2e56Smrg double screenx = 0.0, screeny = 0.0; /* desktop coordinate system */ 1902f7df2e56Smrg double devx = 0.0, devy = 0.0; /* desktop-wide in device coords */ 1903f7df2e56Smrg int i; 1904f7df2e56Smrg int num_events = 0; 1905f7df2e56Smrg RawDeviceEvent *raw; 1906f7df2e56Smrg DDXTouchPointInfoPtr ti; 1907f7df2e56Smrg int need_rawevent = TRUE; 1908f7df2e56Smrg Bool emulate_pointer = FALSE; 1909f7df2e56Smrg int client_id = 0; 1910f7df2e56Smrg 1911f7df2e56Smrg#if XSERVER_DTRACE 1912f7df2e56Smrg if (XSERVER_INPUT_EVENT_ENABLED()) { 1913f7df2e56Smrg XSERVER_INPUT_EVENT(dev->id, type, ddx_touchid, flags, 1914f7df2e56Smrg mask_in ? mask_in->last_bit + 1 : 0, 1915f7df2e56Smrg mask_in ? mask_in->mask : NULL, 1916f7df2e56Smrg mask_in ? mask_in->valuators : NULL); 1917f7df2e56Smrg } 1918f7df2e56Smrg#endif 1919f7df2e56Smrg 1920f7df2e56Smrg if (!dev->enabled || !t || !v) 1921f7df2e56Smrg return 0; 1922f7df2e56Smrg 1923f7df2e56Smrg /* Find and/or create the DDX touch info */ 1924f7df2e56Smrg 1925f7df2e56Smrg ti = TouchFindByDDXID(dev, ddx_touchid, (type == XI_TouchBegin)); 1926f7df2e56Smrg if (!ti) { 1927f7df2e56Smrg ErrorFSigSafe("[dix] %s: unable to %s touch point %u\n", dev->name, 1928f7df2e56Smrg type == XI_TouchBegin ? "begin" : "find", ddx_touchid); 1929f7df2e56Smrg return 0; 1930f7df2e56Smrg } 1931f7df2e56Smrg client_id = ti->client_id; 1932f7df2e56Smrg 1933f7df2e56Smrg emulate_pointer = ti->emulate_pointer; 1934f7df2e56Smrg 1935f7df2e56Smrg if (!IsMaster(dev)) 1936f7df2e56Smrg events = 1937f7df2e56Smrg UpdateFromMaster(events, dev, DEVCHANGE_POINTER_EVENT, &num_events); 1938f7df2e56Smrg 1939f7df2e56Smrg valuator_mask_copy(&mask, mask_in); 1940f7df2e56Smrg 1941f7df2e56Smrg if (need_rawevent) { 1942f7df2e56Smrg raw = &events->raw_event; 1943f7df2e56Smrg events++; 1944f7df2e56Smrg num_events++; 1945f7df2e56Smrg init_raw(dev, raw, ms, type, client_id); 1946f7df2e56Smrg set_raw_valuators(raw, &mask, TRUE, raw->valuators.data_raw); 1947f7df2e56Smrg } 1948f7df2e56Smrg 1949f7df2e56Smrg event = &events->device_event; 1950f7df2e56Smrg num_events++; 1951f7df2e56Smrg 19527e31ba66Smrg init_device_event(event, dev, ms, EVENT_SOURCE_NORMAL); 1953f7df2e56Smrg 1954f7df2e56Smrg switch (type) { 1955f7df2e56Smrg case XI_TouchBegin: 1956f7df2e56Smrg event->type = ET_TouchBegin; 1957f7df2e56Smrg /* If we're starting a touch, we must have x & y co-ordinates. */ 1958f7df2e56Smrg if (!mask_in || 1959f7df2e56Smrg !valuator_mask_isset(mask_in, 0) || 1960f7df2e56Smrg !valuator_mask_isset(mask_in, 1)) { 1961f7df2e56Smrg ErrorFSigSafe("%s: Attempted to start touch without x/y " 1962f7df2e56Smrg "(driver bug)\n", dev->name); 1963f7df2e56Smrg return 0; 1964f7df2e56Smrg } 1965f7df2e56Smrg break; 1966f7df2e56Smrg case XI_TouchUpdate: 1967f7df2e56Smrg event->type = ET_TouchUpdate; 1968f7df2e56Smrg if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0) { 1969f7df2e56Smrg ErrorFSigSafe("%s: TouchUpdate with no valuators? Driver bug\n", 1970f7df2e56Smrg dev->name); 1971f7df2e56Smrg } 1972f7df2e56Smrg break; 1973f7df2e56Smrg case XI_TouchEnd: 1974f7df2e56Smrg event->type = ET_TouchEnd; 1975f7df2e56Smrg /* We can end the DDX touch here, since we don't use the active 1976f7df2e56Smrg * field below */ 1977f7df2e56Smrg TouchEndDDXTouch(dev, ti); 1978f7df2e56Smrg break; 1979f7df2e56Smrg default: 1980f7df2e56Smrg return 0; 1981f7df2e56Smrg } 1982f7df2e56Smrg 1983f7df2e56Smrg /* Get our screen event co-ordinates (root_x/root_y/event_x/event_y): 1984f7df2e56Smrg * these come from the touchpoint in Absolute mode, or the sprite in 1985f7df2e56Smrg * Relative. */ 1986f7df2e56Smrg if (t->mode == XIDirectTouch) { 1987f7df2e56Smrg for (i = 0; i < max(valuator_mask_size(&mask), 2); i++) { 1988f7df2e56Smrg double val; 1989f7df2e56Smrg 1990f7df2e56Smrg if (valuator_mask_fetch_double(&mask, i, &val)) 1991f7df2e56Smrg valuator_mask_set_double(ti->valuators, i, val); 1992f7df2e56Smrg /* If the device doesn't post new X and Y axis values, 1993f7df2e56Smrg * use the last values posted. 1994f7df2e56Smrg */ 1995f7df2e56Smrg else if (i < 2 && 1996f7df2e56Smrg valuator_mask_fetch_double(ti->valuators, i, &val)) 1997f7df2e56Smrg valuator_mask_set_double(&mask, i, val); 1998f7df2e56Smrg } 1999f7df2e56Smrg 2000f7df2e56Smrg transformAbsolute(dev, &mask); 2001f7df2e56Smrg clipAbsolute(dev, &mask); 2002f7df2e56Smrg } 2003f7df2e56Smrg else { 2004f7df2e56Smrg screenx = dev->spriteInfo->sprite->hotPhys.x; 2005f7df2e56Smrg screeny = dev->spriteInfo->sprite->hotPhys.y; 2006f7df2e56Smrg } 2007f7df2e56Smrg if (need_rawevent) 2008f7df2e56Smrg set_raw_valuators(raw, &mask, FALSE, raw->valuators.data); 2009f7df2e56Smrg 2010f7df2e56Smrg /* Indirect device touch coordinates are not used for cursor positioning. 2011f7df2e56Smrg * They are merely informational, and are provided in device coordinates. 2012f7df2e56Smrg * The device sprite is used for positioning instead, and it is already 2013f7df2e56Smrg * scaled. */ 2014f7df2e56Smrg if (t->mode == XIDirectTouch) 2015f7df2e56Smrg scr = scale_to_desktop(dev, &mask, &devx, &devy, &screenx, &screeny); 2016f7df2e56Smrg if (emulate_pointer) 2017f7df2e56Smrg scr = positionSprite(dev, Absolute, &mask, 2018f7df2e56Smrg &devx, &devy, &screenx, &screeny, NULL, NULL); 2019f7df2e56Smrg 2020f7df2e56Smrg /* see fill_pointer_events for coordinate systems */ 2021f7df2e56Smrg if (emulate_pointer) 2022f7df2e56Smrg updateHistory(dev, &mask, ms); 2023f7df2e56Smrg 2024f7df2e56Smrg clipValuators(dev, &mask); 2025f7df2e56Smrg 2026f7df2e56Smrg if (emulate_pointer) 2027f7df2e56Smrg storeLastValuators(dev, &mask, 0, 1, devx, devy); 2028f7df2e56Smrg 2029f7df2e56Smrg /* Update the MD's co-ordinates, which are always in desktop space. */ 2030f7df2e56Smrg if (emulate_pointer && !IsMaster(dev) && !IsFloating(dev)) { 2031f7df2e56Smrg DeviceIntPtr master = GetMaster(dev, MASTER_POINTER); 2032f7df2e56Smrg 2033f7df2e56Smrg master->last.valuators[0] = screenx; 2034f7df2e56Smrg master->last.valuators[1] = screeny; 2035f7df2e56Smrg } 2036f7df2e56Smrg 2037f7df2e56Smrg event->root = scr->root->drawable.id; 2038f7df2e56Smrg 2039f7df2e56Smrg event_set_root_coordinates(event, screenx - scr->x, screeny - scr->y); 2040f7df2e56Smrg event->touchid = client_id; 2041f7df2e56Smrg event->flags = flags; 2042f7df2e56Smrg 2043f7df2e56Smrg if (emulate_pointer) { 2044f7df2e56Smrg event->flags |= TOUCH_POINTER_EMULATED; 2045f7df2e56Smrg event->detail.button = 1; 2046f7df2e56Smrg } 2047f7df2e56Smrg 2048f7df2e56Smrg set_valuators(dev, event, &mask); 2049f7df2e56Smrg for (i = 0; i < v->numAxes; i++) { 2050f7df2e56Smrg if (valuator_mask_isset(&mask, i)) 2051f7df2e56Smrg v->axisVal[i] = valuator_mask_get(&mask, i); 2052f7df2e56Smrg } 2053f7df2e56Smrg 2054f7df2e56Smrg return num_events; 2055f7df2e56Smrg} 2056f7df2e56Smrg 2057f7df2e56Smrgvoid 2058f7df2e56SmrgGetDixTouchEnd(InternalEvent *ievent, DeviceIntPtr dev, TouchPointInfoPtr ti, 2059f7df2e56Smrg uint32_t flags) 2060f7df2e56Smrg{ 2061f7df2e56Smrg ScreenPtr scr = dev->spriteInfo->sprite->hotPhys.pScreen; 2062f7df2e56Smrg DeviceEvent *event = &ievent->device_event; 2063f7df2e56Smrg CARD32 ms = GetTimeInMillis(); 2064f7df2e56Smrg 2065f7df2e56Smrg BUG_WARN(!dev->enabled); 2066f7df2e56Smrg 20677e31ba66Smrg init_device_event(event, dev, ms, EVENT_SOURCE_NORMAL); 2068f7df2e56Smrg 2069f7df2e56Smrg event->sourceid = ti->sourceid; 2070f7df2e56Smrg event->type = ET_TouchEnd; 2071f7df2e56Smrg 2072f7df2e56Smrg event->root = scr->root->drawable.id; 2073f7df2e56Smrg 2074f7df2e56Smrg /* Get screen event coordinates from the sprite. Is this really the best 2075f7df2e56Smrg * we can do? */ 2076f7df2e56Smrg event_set_root_coordinates(event, 2077f7df2e56Smrg dev->last.valuators[0] - scr->x, 2078f7df2e56Smrg dev->last.valuators[1] - scr->y); 2079f7df2e56Smrg event->touchid = ti->client_id; 2080f7df2e56Smrg event->flags = flags; 2081f7df2e56Smrg 2082f7df2e56Smrg if (flags & TOUCH_POINTER_EMULATED) { 2083f7df2e56Smrg event->flags |= TOUCH_POINTER_EMULATED; 2084f7df2e56Smrg event->detail.button = 1; 2085f7df2e56Smrg } 2086f7df2e56Smrg} 2087f7df2e56Smrg 208805b261ecSmrg/** 208905b261ecSmrg * Synthesize a single motion event for the core pointer. 209005b261ecSmrg * 209105b261ecSmrg * Used in cursor functions, e.g. when cursor confinement changes, and we need 209205b261ecSmrg * to shift the pointer to get it inside the new bounds. 209305b261ecSmrg */ 209405b261ecSmrgvoid 20954642e01fSmrgPostSyntheticMotion(DeviceIntPtr pDev, 2096f7df2e56Smrg int x, int y, int screen, unsigned long time) 209705b261ecSmrg{ 20984202a189Smrg DeviceEvent ev; 209905b261ecSmrg 210005b261ecSmrg#ifdef PANORAMIX 210105b261ecSmrg /* Translate back to the sprite screen since processInputProc 210205b261ecSmrg will translate from sprite screen to screen 0 upon reentry 210305b261ecSmrg to the DIX layer. */ 210405b261ecSmrg if (!noPanoramiXExtension) { 21054202a189Smrg x += screenInfo.screens[0]->x - screenInfo.screens[screen]->x; 21064202a189Smrg y += screenInfo.screens[0]->y - screenInfo.screens[screen]->y; 210705b261ecSmrg } 210805b261ecSmrg#endif 210905b261ecSmrg 21104202a189Smrg memset(&ev, 0, sizeof(DeviceEvent)); 21117e31ba66Smrg init_device_event(&ev, pDev, time, EVENT_SOURCE_NORMAL); 21124202a189Smrg ev.root_x = x; 21134202a189Smrg ev.root_y = y; 21144202a189Smrg ev.type = ET_Motion; 21154202a189Smrg ev.time = time; 211605b261ecSmrg 21174202a189Smrg /* FIXME: MD/SD considerations? */ 2118f7df2e56Smrg (*pDev->public.processInputProc) ((InternalEvent *) &ev, pDev); 211905b261ecSmrg} 2120