getevents.c revision 4642e01f
105b261ecSmrg/* 205b261ecSmrg * Copyright © 2006 Nokia Corporation 305b261ecSmrg * Copyright © 2006-2007 Daniel Stone 405b261ecSmrg * 505b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a 605b261ecSmrg * copy of this software and associated documentation files (the "Software"), 705b261ecSmrg * to deal in the Software without restriction, including without limitation 805b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 905b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the 1005b261ecSmrg * Software is furnished to do so, subject to the following conditions: 1105b261ecSmrg * 1205b261ecSmrg * The above copyright notice and this permission notice (including the next 1305b261ecSmrg * paragraph) shall be included in all copies or substantial portions of the 1405b261ecSmrg * Software. 1505b261ecSmrg * 1605b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1705b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1805b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1905b261ecSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2005b261ecSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2105b261ecSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2205b261ecSmrg * DEALINGS IN THE SOFTWARE. 2305b261ecSmrg * 2405b261ecSmrg * Author: Daniel Stone <daniel@fooishbar.org> 2505b261ecSmrg */ 2605b261ecSmrg 2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 2805b261ecSmrg#include <dix-config.h> 2905b261ecSmrg#endif 3005b261ecSmrg 3105b261ecSmrg#include <X11/X.h> 3205b261ecSmrg#include <X11/keysym.h> 3305b261ecSmrg#define NEED_EVENTS 3405b261ecSmrg#define NEED_REPLIES 3505b261ecSmrg#include <X11/Xproto.h> 3605b261ecSmrg 3705b261ecSmrg#include "misc.h" 3805b261ecSmrg#include "resource.h" 3905b261ecSmrg#include "inputstr.h" 4005b261ecSmrg#include "scrnintstr.h" 4105b261ecSmrg#include "cursorstr.h" 4205b261ecSmrg#include "dixstruct.h" 4305b261ecSmrg#include "globals.h" 4405b261ecSmrg#include "dixevents.h" 4505b261ecSmrg#include "mipointer.h" 4605b261ecSmrg 4705b261ecSmrg#ifdef XKB 4805b261ecSmrg#include <X11/extensions/XKBproto.h> 4905b261ecSmrg#include <xkbsrv.h> 5005b261ecSmrg#endif 5105b261ecSmrg 5205b261ecSmrg#ifdef PANORAMIX 5305b261ecSmrg#include "panoramiX.h" 5405b261ecSmrg#include "panoramiXsrv.h" 5505b261ecSmrg#endif 5605b261ecSmrg 5705b261ecSmrg#include <X11/extensions/XI.h> 5805b261ecSmrg#include <X11/extensions/XIproto.h> 5905b261ecSmrg#include "exglobals.h" 6005b261ecSmrg#include "exevents.h" 6105b261ecSmrg#include "exglobals.h" 6205b261ecSmrg#include "extnsionst.h" 6305b261ecSmrg 6405b261ecSmrg/* Number of motion history events to store. */ 6505b261ecSmrg#define MOTION_HISTORY_SIZE 256 6605b261ecSmrg 674642e01fSmrg/* InputEventList is the container list for all input events generated by the 684642e01fSmrg * DDX. The DDX is expected to call GetEventList() and then pass the list into 694642e01fSmrg * Get{Pointer|Keyboard}Events. 704642e01fSmrg */ 714642e01fSmrgEventListPtr InputEventList = NULL; 724642e01fSmrgint InputEventListLen = 0; 734642e01fSmrg 744642e01fSmrg_X_EXPORT int 754642e01fSmrgGetEventList(EventListPtr* list) 764642e01fSmrg{ 774642e01fSmrg *list = InputEventList; 784642e01fSmrg return InputEventListLen; 794642e01fSmrg} 8005b261ecSmrg 8105b261ecSmrg/** 8205b261ecSmrg * Pick some arbitrary size for Xi motion history. 8305b261ecSmrg */ 8405b261ecSmrg_X_EXPORT int 8505b261ecSmrgGetMotionHistorySize(void) 8605b261ecSmrg{ 8705b261ecSmrg return MOTION_HISTORY_SIZE; 8805b261ecSmrg} 8905b261ecSmrg 9005b261ecSmrgstatic void 9105b261ecSmrgset_key_down(DeviceIntPtr pDev, int key_code) 9205b261ecSmrg{ 9305b261ecSmrg pDev->key->postdown[key_code >> 3] |= (1 << (key_code & 7)); 9405b261ecSmrg} 9505b261ecSmrg 9605b261ecSmrgstatic void 9705b261ecSmrgset_key_up(DeviceIntPtr pDev, int key_code) 9805b261ecSmrg{ 9905b261ecSmrg pDev->key->postdown[key_code >> 3] &= ~(1 << (key_code & 7)); 10005b261ecSmrg} 10105b261ecSmrg 10205b261ecSmrgstatic Bool 10305b261ecSmrgkey_is_down(DeviceIntPtr pDev, int key_code) 10405b261ecSmrg{ 10505b261ecSmrg return !!(pDev->key->postdown[key_code >> 3] & (1 << (key_code & 7))); 10605b261ecSmrg} 10705b261ecSmrg 10805b261ecSmrgstatic Bool 10905b261ecSmrgkey_autorepeats(DeviceIntPtr pDev, int key_code) 11005b261ecSmrg{ 11105b261ecSmrg return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] & 11205b261ecSmrg (1 << (key_code & 7))); 11305b261ecSmrg} 11405b261ecSmrg 1154642e01fSmrg/** 1164642e01fSmrg * Rescale the coord between the two axis ranges. 1174642e01fSmrg */ 1184642e01fSmrgstatic int 1194642e01fSmrgrescaleValuatorAxis(int coord, AxisInfoPtr from, AxisInfoPtr to, 1204642e01fSmrg int defmax) 1214642e01fSmrg{ 1224642e01fSmrg int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax; 1234642e01fSmrg 1244642e01fSmrg if(from && from->min_value < from->max_value) { 1254642e01fSmrg fmin = from->min_value; 1264642e01fSmrg fmax = from->max_value; 1274642e01fSmrg } 1284642e01fSmrg if(to && to->min_value < to->max_value) { 1294642e01fSmrg tmin = to->min_value; 1304642e01fSmrg tmax = to->max_value; 1314642e01fSmrg } 1324642e01fSmrg 1334642e01fSmrg if(fmin == tmin && fmax == tmax) 1344642e01fSmrg return coord; 1354642e01fSmrg 1364642e01fSmrg if(fmax == fmin) /* avoid division by 0 */ 1374642e01fSmrg return 0; 1384642e01fSmrg 1394642e01fSmrg return roundf(((float)(coord - fmin)) * (tmax - tmin) / 1404642e01fSmrg (fmax - fmin)) + tmin; 1414642e01fSmrg} 1424642e01fSmrg 1434642e01fSmrg/** 1444642e01fSmrg * Update all coordinates when changing to a different SD 1454642e01fSmrg * to ensure that relative reporting will work as expected 1464642e01fSmrg * without loss of precision. 1474642e01fSmrg * 1484642e01fSmrg * pDev->last.valuators will be in absolute device coordinates after this 1494642e01fSmrg * function. 1504642e01fSmrg */ 1514642e01fSmrgstatic void 1524642e01fSmrgupdateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev) 1534642e01fSmrg{ 1544642e01fSmrg ScreenPtr scr = miPointerGetScreen(pDev); 1554642e01fSmrg int i; 1564642e01fSmrg DeviceIntPtr lastSlave; 1574642e01fSmrg 1584642e01fSmrg /* master->last.valuators[0]/[1] is in screen coords and the actual 1594642e01fSmrg * position of the pointer */ 1604642e01fSmrg pDev->last.valuators[0] = master->last.valuators[0]; 1614642e01fSmrg pDev->last.valuators[1] = master->last.valuators[1]; 1624642e01fSmrg 1634642e01fSmrg if (!pDev->valuator) 1644642e01fSmrg return; 1654642e01fSmrg 1664642e01fSmrg /* scale back to device coordinates */ 1674642e01fSmrg if(pDev->valuator->numAxes > 0) 1684642e01fSmrg pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], NULL, pDev->valuator->axes + 0, scr->width); 1694642e01fSmrg if(pDev->valuator->numAxes > 1) 1704642e01fSmrg pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], NULL, pDev->valuator->axes + 1, scr->height); 1714642e01fSmrg 1724642e01fSmrg /* calculate the other axis as well based on info from the old 1734642e01fSmrg * slave-device. If the old slave had less axes than this one, 1744642e01fSmrg * last.valuators is reset to 0. 1754642e01fSmrg */ 1764642e01fSmrg if ((lastSlave = master->u.lastSlave) && lastSlave->valuator) { 1774642e01fSmrg for (i = 2; i < pDev->valuator->numAxes; i++) { 1784642e01fSmrg if (i >= lastSlave->valuator->numAxes) 1794642e01fSmrg pDev->last.valuators[i] = 0; 1804642e01fSmrg else 1814642e01fSmrg pDev->last.valuators[i] = 1824642e01fSmrg rescaleValuatorAxis(pDev->last.valuators[i], 1834642e01fSmrg lastSlave->valuator->axes + i, 1844642e01fSmrg pDev->valuator->axes + i, 0); 1854642e01fSmrg } 1864642e01fSmrg } 1874642e01fSmrg 1884642e01fSmrg} 1894642e01fSmrg 19005b261ecSmrg/** 19105b261ecSmrg * Allocate the motion history buffer. 19205b261ecSmrg */ 19305b261ecSmrg_X_EXPORT void 19405b261ecSmrgAllocateMotionHistory(DeviceIntPtr pDev) 19505b261ecSmrg{ 1964642e01fSmrg int size; 19705b261ecSmrg if (pDev->valuator->motion) 19805b261ecSmrg xfree(pDev->valuator->motion); 19905b261ecSmrg 20005b261ecSmrg if (pDev->valuator->numMotionEvents < 1) 20105b261ecSmrg return; 20205b261ecSmrg 2034642e01fSmrg /* An MD must have a motion history size large enough to keep all 2044642e01fSmrg * potential valuators, plus the respective range of the valuators. 2054642e01fSmrg * 3 * INT32 for (min_val, max_val, curr_val)) 2064642e01fSmrg */ 2074642e01fSmrg if (pDev->isMaster) 2084642e01fSmrg size = sizeof(INT32) * 3 * MAX_VALUATORS; 2094642e01fSmrg else 2104642e01fSmrg size = sizeof(INT32) * pDev->valuator->numAxes; 2114642e01fSmrg 2124642e01fSmrg size += sizeof(Time); 2134642e01fSmrg 2144642e01fSmrg pDev->valuator->motion = xcalloc(pDev->valuator->numMotionEvents, size); 21505b261ecSmrg pDev->valuator->first_motion = 0; 21605b261ecSmrg pDev->valuator->last_motion = 0; 2174642e01fSmrg if (!pDev->valuator->motion) 2184642e01fSmrg ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n", 2194642e01fSmrg pDev->name, size * pDev->valuator->numMotionEvents); 22005b261ecSmrg} 22105b261ecSmrg 22205b261ecSmrg/** 22305b261ecSmrg * Dump the motion history between start and stop into the supplied buffer. 22405b261ecSmrg * Only records the event for a given screen in theory, but in practice, we 22505b261ecSmrg * sort of ignore this. 2264642e01fSmrg * 2274642e01fSmrg * If core is set, we only generate x/y, in INT16, scaled to screen coords. 22805b261ecSmrg */ 22905b261ecSmrg_X_EXPORT int 2304642e01fSmrgGetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start, 2314642e01fSmrg unsigned long stop, ScreenPtr pScreen, BOOL core) 23205b261ecSmrg{ 2334642e01fSmrg char *ibuff = NULL, *obuff; 23405b261ecSmrg int i = 0, ret = 0; 2354642e01fSmrg int j, coord; 23605b261ecSmrg Time current; 23705b261ecSmrg /* The size of a single motion event. */ 2384642e01fSmrg int size; 2394642e01fSmrg int dflt; 2404642e01fSmrg AxisInfo from, *to; /* for scaling */ 2414642e01fSmrg INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */ 2424642e01fSmrg INT16 *corebuf; 2434642e01fSmrg AxisInfo core_axis = {0}; 24405b261ecSmrg 24505b261ecSmrg if (!pDev->valuator || !pDev->valuator->numMotionEvents) 24605b261ecSmrg return 0; 24705b261ecSmrg 2484642e01fSmrg if (core && !pScreen) 2494642e01fSmrg return 0; 2504642e01fSmrg 2514642e01fSmrg if (pDev->isMaster) 2524642e01fSmrg size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time); 2534642e01fSmrg else 2544642e01fSmrg size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); 2554642e01fSmrg 2564642e01fSmrg *buff = xalloc(size * pDev->valuator->numMotionEvents); 2574642e01fSmrg if (!(*buff)) 2584642e01fSmrg return 0; 2594642e01fSmrg obuff = (char *)*buff; 2604642e01fSmrg 26105b261ecSmrg for (i = pDev->valuator->first_motion; 26205b261ecSmrg i != pDev->valuator->last_motion; 26305b261ecSmrg i = (i + 1) % pDev->valuator->numMotionEvents) { 26405b261ecSmrg /* We index the input buffer by which element we're accessing, which 26505b261ecSmrg * is not monotonic, and the output buffer by how many events we've 26605b261ecSmrg * written so far. */ 26705b261ecSmrg ibuff = (char *) pDev->valuator->motion + (i * size); 26805b261ecSmrg memcpy(¤t, ibuff, sizeof(Time)); 26905b261ecSmrg 27005b261ecSmrg if (current > stop) { 27105b261ecSmrg return ret; 27205b261ecSmrg } 27305b261ecSmrg else if (current >= start) { 2744642e01fSmrg if (core) 2754642e01fSmrg { 2764642e01fSmrg memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */ 2774642e01fSmrg 2784642e01fSmrg icbuf = (INT32*)(ibuff + sizeof(Time)); 2794642e01fSmrg corebuf = (INT16*)(obuff + sizeof(Time)); 2804642e01fSmrg 2814642e01fSmrg /* fetch x coordinate + range */ 2824642e01fSmrg memcpy(&from.min_value, icbuf++, sizeof(INT32)); 2834642e01fSmrg memcpy(&from.max_value, icbuf++, sizeof(INT32)); 2844642e01fSmrg memcpy(&coord, icbuf++, sizeof(INT32)); 2854642e01fSmrg 2864642e01fSmrg /* scale to screen coords */ 2874642e01fSmrg to = &core_axis; 2884642e01fSmrg to->max_value = pScreen->width; 2894642e01fSmrg coord = rescaleValuatorAxis(coord, &from, to, pScreen->width); 2904642e01fSmrg 2914642e01fSmrg memcpy(corebuf, &coord, sizeof(INT16)); 2924642e01fSmrg corebuf++; 2934642e01fSmrg 2944642e01fSmrg /* fetch y coordinate + range */ 2954642e01fSmrg memcpy(&from.min_value, icbuf++, sizeof(INT32)); 2964642e01fSmrg memcpy(&from.max_value, icbuf++, sizeof(INT32)); 2974642e01fSmrg memcpy(&coord, icbuf++, sizeof(INT32)); 2984642e01fSmrg 2994642e01fSmrg to->max_value = pScreen->height; 3004642e01fSmrg coord = rescaleValuatorAxis(coord, &from, to, pScreen->height); 3014642e01fSmrg memcpy(corebuf, &coord, sizeof(INT16)); 3024642e01fSmrg 3034642e01fSmrg } else if (pDev->isMaster) 3044642e01fSmrg { 3054642e01fSmrg memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */ 3064642e01fSmrg 3074642e01fSmrg ocbuf = (INT32*)(obuff + sizeof(Time)); 3084642e01fSmrg icbuf = (INT32*)(ibuff + sizeof(Time)); 3094642e01fSmrg for (j = 0; j < MAX_VALUATORS; j++) 3104642e01fSmrg { 3114642e01fSmrg if (j >= pDev->valuator->numAxes) 3124642e01fSmrg break; 3134642e01fSmrg 3144642e01fSmrg /* fetch min/max/coordinate */ 3154642e01fSmrg memcpy(&from.min_value, icbuf++, sizeof(INT32)); 3164642e01fSmrg memcpy(&from.max_value, icbuf++, sizeof(INT32)); 3174642e01fSmrg memcpy(&coord, icbuf++, sizeof(INT32)); 3184642e01fSmrg 3194642e01fSmrg to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL; 3204642e01fSmrg 3214642e01fSmrg /* x/y scaled to screen if no range is present */ 3224642e01fSmrg if (j == 0 && (from.max_value < from.min_value)) 3234642e01fSmrg from.max_value = pScreen->width; 3244642e01fSmrg else if (j == 1 && (from.max_value < from.min_value)) 3254642e01fSmrg from.max_value = pScreen->height; 3264642e01fSmrg 3274642e01fSmrg if (j == 0 && (to->max_value < to->min_value)) 3284642e01fSmrg dflt = pScreen->width; 3294642e01fSmrg else if (j == 1 && (to->max_value < to->min_value)) 3304642e01fSmrg dflt = pScreen->height; 3314642e01fSmrg else 3324642e01fSmrg dflt = 0; 3334642e01fSmrg 3344642e01fSmrg /* scale from stored range into current range */ 3354642e01fSmrg coord = rescaleValuatorAxis(coord, &from, to, 0); 3364642e01fSmrg memcpy(ocbuf, &coord, sizeof(INT32)); 3374642e01fSmrg ocbuf++; 3384642e01fSmrg } 3394642e01fSmrg } else 3404642e01fSmrg memcpy(obuff, ibuff, size); 3414642e01fSmrg 3424642e01fSmrg /* don't advance by size here. size may be different to the 3434642e01fSmrg * actually written size if the MD has less valuators than MAX */ 3444642e01fSmrg if (core) 3454642e01fSmrg obuff += sizeof(INT32) + sizeof(Time); 3464642e01fSmrg else 3474642e01fSmrg obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); 34805b261ecSmrg ret++; 34905b261ecSmrg } 35005b261ecSmrg } 35105b261ecSmrg 35205b261ecSmrg return ret; 35305b261ecSmrg} 35405b261ecSmrg 35505b261ecSmrg 35605b261ecSmrg/** 35705b261ecSmrg * Update the motion history for a specific device, with the list of 35805b261ecSmrg * valuators. 3594642e01fSmrg * 3604642e01fSmrg * Layout of the history buffer: 3614642e01fSmrg * for SDs: [time] [val0] [val1] ... [valn] 3624642e01fSmrg * for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn] 3634642e01fSmrg * 3644642e01fSmrg * For events that have some valuators unset (first_valuator > 0): 3654642e01fSmrg * min_val == max_val == val == 0. 36605b261ecSmrg */ 36705b261ecSmrgstatic void 36805b261ecSmrgupdateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator, 36905b261ecSmrg int num_valuators, int *valuators) 37005b261ecSmrg{ 37105b261ecSmrg char *buff = (char *) pDev->valuator->motion; 3724642e01fSmrg ValuatorClassPtr v; 3734642e01fSmrg int i; 37405b261ecSmrg 37505b261ecSmrg if (!pDev->valuator->numMotionEvents) 37605b261ecSmrg return; 37705b261ecSmrg 3784642e01fSmrg v = pDev->valuator; 3794642e01fSmrg if (pDev->isMaster) 3804642e01fSmrg { 3814642e01fSmrg buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) * 3824642e01fSmrg v->last_motion; 3834642e01fSmrg 3844642e01fSmrg memcpy(buff, &ms, sizeof(Time)); 3854642e01fSmrg buff += sizeof(Time); 3864642e01fSmrg 3874642e01fSmrg memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS); 3884642e01fSmrg buff += 3 * sizeof(INT32) * first_valuator; 3894642e01fSmrg 3904642e01fSmrg for (i = first_valuator; i < first_valuator + num_valuators; i++) 3914642e01fSmrg { 3924642e01fSmrg if (i >= v->numAxes) 3934642e01fSmrg break; 3944642e01fSmrg memcpy(buff, &v->axes[i].min_value, sizeof(INT32)); 3954642e01fSmrg buff += sizeof(INT32); 3964642e01fSmrg memcpy(buff, &v->axes[i].max_value, sizeof(INT32)); 3974642e01fSmrg buff += sizeof(INT32); 3984642e01fSmrg memcpy(buff, &valuators[i - first_valuator], sizeof(INT32)); 3994642e01fSmrg buff += sizeof(INT32); 4004642e01fSmrg } 4014642e01fSmrg } else 4024642e01fSmrg { 4034642e01fSmrg 4044642e01fSmrg buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) * 40505b261ecSmrg pDev->valuator->last_motion; 40605b261ecSmrg 4074642e01fSmrg memcpy(buff, &ms, sizeof(Time)); 4084642e01fSmrg buff += sizeof(Time); 40905b261ecSmrg 4104642e01fSmrg memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes); 4114642e01fSmrg buff += sizeof(INT32) * first_valuator; 41205b261ecSmrg 4134642e01fSmrg memcpy(buff, valuators, sizeof(INT32) * num_valuators); 4144642e01fSmrg } 41505b261ecSmrg 4164642e01fSmrg pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) % 4174642e01fSmrg pDev->valuator->numMotionEvents; 41805b261ecSmrg /* If we're wrapping around, just keep the circular buffer going. */ 41905b261ecSmrg if (pDev->valuator->first_motion == pDev->valuator->last_motion) 42005b261ecSmrg pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) % 42105b261ecSmrg pDev->valuator->numMotionEvents; 42205b261ecSmrg 42305b261ecSmrg return; 42405b261ecSmrg} 42505b261ecSmrg 42605b261ecSmrg 42705b261ecSmrg/** 42805b261ecSmrg * Returns the maximum number of events GetKeyboardEvents, 42905b261ecSmrg * GetKeyboardValuatorEvents, and GetPointerEvents will ever return. 43005b261ecSmrg * 43105b261ecSmrg * Should be used in DIX as: 43205b261ecSmrg * xEvent *events = xcalloc(sizeof(xEvent), GetMaximumEventsNum()); 4334642e01fSmrg * 4344642e01fSmrg * This MUST be absolutely constant, from init until exit. 43505b261ecSmrg */ 43605b261ecSmrg_X_EXPORT int 43705b261ecSmrgGetMaximumEventsNum(void) { 4384642e01fSmrg /* One base event -- device, plus valuator events. 4394642e01fSmrg * Multiply by two if we're doing non-XKB key repeats. */ 4404642e01fSmrg int ret = 1 + MAX_VALUATOR_EVENTS; 44105b261ecSmrg 44205b261ecSmrg#ifdef XKB 44305b261ecSmrg if (noXkbExtension) 44405b261ecSmrg#endif 44505b261ecSmrg ret *= 2; 44605b261ecSmrg 44705b261ecSmrg return ret; 44805b261ecSmrg} 44905b261ecSmrg 45005b261ecSmrg 45105b261ecSmrg/** 45205b261ecSmrg * Clip an axis to its bounds, which are declared in the call to 45305b261ecSmrg * InitValuatorAxisClassStruct. 45405b261ecSmrg */ 45505b261ecSmrgstatic void 45605b261ecSmrgclipAxis(DeviceIntPtr pDev, int axisNum, int *val) 45705b261ecSmrg{ 4584642e01fSmrg AxisInfoPtr axis = pDev->valuator->axes + axisNum; 4594642e01fSmrg /* InitValuatoraAxisStruct ensures that (min < max). */ 4604642e01fSmrg 4614642e01fSmrg /* If a value range is defined, clip. If not, do nothing */ 4624642e01fSmrg if (axis->max_value <= axis->min_value) 4634642e01fSmrg return; 4644642e01fSmrg 4654642e01fSmrg if (*val < axis->min_value) 4664642e01fSmrg *val = axis->min_value; 4674642e01fSmrg if (*val > axis->max_value) 4684642e01fSmrg *val = axis->max_value; 46905b261ecSmrg} 47005b261ecSmrg 47105b261ecSmrg/** 47205b261ecSmrg * Clip every axis in the list of valuators to its bounds. 47305b261ecSmrg */ 47405b261ecSmrgstatic void 47505b261ecSmrgclipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators, 47605b261ecSmrg int *valuators) 47705b261ecSmrg{ 47805b261ecSmrg AxisInfoPtr axes = pDev->valuator->axes + first_valuator; 47905b261ecSmrg int i; 48005b261ecSmrg 48105b261ecSmrg for (i = 0; i < num_valuators; i++, axes++) 48205b261ecSmrg clipAxis(pDev, i + first_valuator, &(valuators[i])); 48305b261ecSmrg} 48405b261ecSmrg 48505b261ecSmrg 48605b261ecSmrg/** 48705b261ecSmrg * Fills events with valuator events for pDev, as given by the other 48805b261ecSmrg * parameters. 48905b261ecSmrg */ 4904642e01fSmrgstatic EventList * 4914642e01fSmrggetValuatorEvents(EventList *events, DeviceIntPtr pDev, 4924642e01fSmrg int first_valuator, int num_valuators, int *valuators) { 4934642e01fSmrg deviceValuator *xv; 4944642e01fSmrg int i; 49505b261ecSmrg 4964642e01fSmrg for (i = 0; i < num_valuators; i += 6, events++) { 4974642e01fSmrg xv = (deviceValuator*)events->event; 49805b261ecSmrg xv->type = DeviceValuator; 4994642e01fSmrg xv->first_valuator = first_valuator + i; 5004642e01fSmrg xv->num_valuators = ((num_valuators - i) > 6) ? 6 : (num_valuators - i); 50105b261ecSmrg xv->deviceid = pDev->id; 5024642e01fSmrg switch (num_valuators - i) { 50305b261ecSmrg case 6: 50405b261ecSmrg xv->valuator5 = valuators[i + 5]; 50505b261ecSmrg case 5: 50605b261ecSmrg xv->valuator4 = valuators[i + 4]; 50705b261ecSmrg case 4: 50805b261ecSmrg xv->valuator3 = valuators[i + 3]; 50905b261ecSmrg case 3: 51005b261ecSmrg xv->valuator2 = valuators[i + 2]; 51105b261ecSmrg case 2: 51205b261ecSmrg xv->valuator1 = valuators[i + 1]; 51305b261ecSmrg case 1: 5144642e01fSmrg xv->valuator0 = valuators[i + 0]; 51505b261ecSmrg } 51605b261ecSmrg 5174642e01fSmrg if (i + 6 < num_valuators) 51805b261ecSmrg xv->deviceid |= MORE_EVENTS; 51905b261ecSmrg } 52005b261ecSmrg 52105b261ecSmrg return events; 52205b261ecSmrg} 52305b261ecSmrg 5244642e01fSmrg/** 5254642e01fSmrg * Create the DCCE event (does not update the master's device state yet, this 5264642e01fSmrg * is done in the event processing). 5274642e01fSmrg * Pull in the coordinates from the MD if necessary. 5284642e01fSmrg * 5294642e01fSmrg * @param events Pointer to a pre-allocated event list. 5304642e01fSmrg * @param dev The slave device that generated an event. 5314642e01fSmrg * @param num_events The current number of events, returns the number of 5324642e01fSmrg * events if a DCCE was generated. 5334642e01fSmrg * @return The updated @events pointer. 5344642e01fSmrg */ 5354642e01fSmrgstatic EventListPtr 5364642e01fSmrgupdateFromMaster(EventListPtr events, DeviceIntPtr dev, int *num_events) 5374642e01fSmrg{ 5384642e01fSmrg DeviceIntPtr master = dev->u.master; 5394642e01fSmrg if (master && master->u.lastSlave != dev) 5404642e01fSmrg { 5414642e01fSmrg updateSlaveDeviceCoords(master, dev); 5424642e01fSmrg master->u.lastSlave = dev; 5434642e01fSmrg master->last.numValuators = dev->last.numValuators; 5444642e01fSmrg } 5454642e01fSmrg return events; 5464642e01fSmrg} 5474642e01fSmrg 5484642e01fSmrg/** 5494642e01fSmrg * Move the device's pointer to the position given in the valuators. 5504642e01fSmrg * 5514642e01fSmrg * @param dev The device which's pointer is to be moved. 5524642e01fSmrg * @param x Returns the x position of the pointer after the move. 5534642e01fSmrg * @param y Returns the y position of the pointer after the move. 5544642e01fSmrg * @param first The first valuator in @valuators 5554642e01fSmrg * @param num Total number of valuators in @valuators. 5564642e01fSmrg * @param valuators Valuator data for each axis between @first and 5574642e01fSmrg * @first+@num. 5584642e01fSmrg */ 5594642e01fSmrgstatic void 5604642e01fSmrgmoveAbsolute(DeviceIntPtr dev, int *x, int *y, 5614642e01fSmrg int first, int num, int *valuators) 5624642e01fSmrg{ 5634642e01fSmrg int i; 5644642e01fSmrg 5654642e01fSmrg 5664642e01fSmrg if (num >= 1 && first == 0) 5674642e01fSmrg *x = *(valuators + 0); 5684642e01fSmrg else 5694642e01fSmrg *x = dev->last.valuators[0]; 5704642e01fSmrg 5714642e01fSmrg if (first <= 1 && num >= (2 - first)) 5724642e01fSmrg *y = *(valuators + 1 - first); 5734642e01fSmrg else 5744642e01fSmrg *y = dev->last.valuators[1]; 5754642e01fSmrg 5764642e01fSmrg clipAxis(dev, 0, x); 5774642e01fSmrg clipAxis(dev, 1, y); 5784642e01fSmrg 5794642e01fSmrg i = (first > 2) ? 0 : 2; 5804642e01fSmrg for (; i < num; i++) 5814642e01fSmrg { 5824642e01fSmrg dev->last.valuators[i + first] = valuators[i]; 5834642e01fSmrg clipAxis(dev, i, &dev->last.valuators[i + first]); 5844642e01fSmrg } 5854642e01fSmrg} 5864642e01fSmrg 5874642e01fSmrg/** 5884642e01fSmrg * Move the device's pointer by the values given in @valuators. 5894642e01fSmrg * 5904642e01fSmrg * @param dev The device which's pointer is to be moved. 5914642e01fSmrg * @param x Returns the x position of the pointer after the move. 5924642e01fSmrg * @param y Returns the y position of the pointer after the move. 5934642e01fSmrg * @param first The first valuator in @valuators 5944642e01fSmrg * @param num Total number of valuators in @valuators. 5954642e01fSmrg * @param valuators Valuator data for each axis between @first and 5964642e01fSmrg * @first+@num. 5974642e01fSmrg */ 5984642e01fSmrgstatic void 5994642e01fSmrgmoveRelative(DeviceIntPtr dev, int *x, int *y, 6004642e01fSmrg int first, int num, int *valuators) 6014642e01fSmrg{ 6024642e01fSmrg int i; 6034642e01fSmrg 6044642e01fSmrg *x = dev->last.valuators[0]; 6054642e01fSmrg *y = dev->last.valuators[1]; 6064642e01fSmrg 6074642e01fSmrg if (num >= 1 && first == 0) 6084642e01fSmrg *x += *(valuators +0); 6094642e01fSmrg 6104642e01fSmrg if (first <= 1 && num >= (2 - first)) 6114642e01fSmrg *y += *(valuators + 1 - first); 6124642e01fSmrg 6134642e01fSmrg /* if attached, clip both x and y to the defined limits (usually 6144642e01fSmrg * co-ord space limit). If it is attached, we need x/y to go over the 6154642e01fSmrg * limits to be able to change screens. */ 6164642e01fSmrg if(dev->u.master) { 6174642e01fSmrg clipAxis(dev, 0, x); 6184642e01fSmrg clipAxis(dev, 1, y); 6194642e01fSmrg } 6204642e01fSmrg 6214642e01fSmrg /* calc other axes, clip, drop back into valuators */ 6224642e01fSmrg i = (first > 2) ? 0 : 2; 6234642e01fSmrg for (; i < num; i++) 6244642e01fSmrg { 6254642e01fSmrg dev->last.valuators[i + first] += valuators[i]; 6264642e01fSmrg clipAxis(dev, i, &dev->last.valuators[i + first]); 6274642e01fSmrg valuators[i] = dev->last.valuators[i + first]; 6284642e01fSmrg } 6294642e01fSmrg} 6304642e01fSmrg 6314642e01fSmrg/** 6324642e01fSmrg * Accelerate the data in valuators based on the device's acceleration scheme. 6334642e01fSmrg * 6344642e01fSmrg * @param dev The device which's pointer is to be moved. 6354642e01fSmrg * @param first The first valuator in @valuators 6364642e01fSmrg * @param num Total number of valuators in @valuators. 6374642e01fSmrg * @param valuators Valuator data for each axis between @first and 6384642e01fSmrg * @first+@num. 6394642e01fSmrg * @param ms Current time. 6404642e01fSmrg */ 6414642e01fSmrgstatic void 6424642e01fSmrgaccelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms) 6434642e01fSmrg{ 6444642e01fSmrg if (dev->valuator->accelScheme.AccelSchemeProc) 6454642e01fSmrg dev->valuator->accelScheme.AccelSchemeProc(dev, first, num, valuators, ms); 6464642e01fSmrg} 6474642e01fSmrg 6484642e01fSmrg/** 6494642e01fSmrg * If we have HW cursors, this actually moves the visible sprite. If not, we 6504642e01fSmrg * just do all the screen crossing, etc. 6514642e01fSmrg * 6524642e01fSmrg * We scale from device to screen coordinates here, call 6534642e01fSmrg * miPointerSetPosition() and then scale back into device coordinates (if 6544642e01fSmrg * needed). miPSP will change x/y if the screen was crossed. 6554642e01fSmrg * 6564642e01fSmrg * @param dev The device to be moved. 6574642e01fSmrg * @param x Pointer to current x-axis value, may be modified. 6584642e01fSmrg * @param y Pointer to current y-axis value, may be modified. 6594642e01fSmrg * @param scr Screen the device's sprite is currently on. 6604642e01fSmrg * @param screenx Screen x coordinate the sprite is on after the update. 6614642e01fSmrg * @param screeny Screen y coordinate the sprite is on after the update. 6624642e01fSmrg */ 6634642e01fSmrgstatic void 6644642e01fSmrgpositionSprite(DeviceIntPtr dev, int *x, int *y, 6654642e01fSmrg ScreenPtr scr, int *screenx, int *screeny) 6664642e01fSmrg{ 6674642e01fSmrg /* scale x&y to screen */ 6684642e01fSmrg *screenx = rescaleValuatorAxis(*x, dev->valuator->axes + 0, NULL, scr->width); 6694642e01fSmrg *screeny = rescaleValuatorAxis(*y, dev->valuator->axes + 1, NULL, scr->height); 6704642e01fSmrg dev->last.valuators[0] = *screenx; 6714642e01fSmrg dev->last.valuators[1] = *screeny; 6724642e01fSmrg 6734642e01fSmrg /* This takes care of crossing screens for us, as well as clipping 6744642e01fSmrg * to the current screen. */ 6754642e01fSmrg miPointerSetPosition(dev, &dev->last.valuators[0], &dev->last.valuators[1]); 6764642e01fSmrg 6774642e01fSmrg if (dev->u.master) { 6784642e01fSmrg dev->u.master->last.valuators[0] = dev->last.valuators[0]; 6794642e01fSmrg dev->u.master->last.valuators[1] = dev->last.valuators[1]; 6804642e01fSmrg } 6814642e01fSmrg 6824642e01fSmrg /* Crossed screen? Scale back to device coordiantes */ 6834642e01fSmrg if(*screenx != dev->last.valuators[0]) 6844642e01fSmrg { 6854642e01fSmrg scr = miPointerGetScreen(dev); 6864642e01fSmrg *x = rescaleValuatorAxis(dev->last.valuators[0], NULL, 6874642e01fSmrg dev->valuator->axes + 0, scr->width); 6884642e01fSmrg *screenx = dev->last.valuators[0]; 6894642e01fSmrg } 6904642e01fSmrg if(*screeny != dev->last.valuators[1]) 6914642e01fSmrg { 6924642e01fSmrg scr = miPointerGetScreen(dev); 6934642e01fSmrg *screeny = dev->last.valuators[1]; 6944642e01fSmrg *y = rescaleValuatorAxis(dev->last.valuators[1], NULL, 6954642e01fSmrg dev->valuator->axes + 1, scr->height); 6964642e01fSmrg } 6974642e01fSmrg 6984642e01fSmrg /* dropy x/y (device coordinates) back into valuators for next event */ 6994642e01fSmrg dev->last.valuators[0] = *x; 7004642e01fSmrg dev->last.valuators[1] = *y; 7014642e01fSmrg} 7024642e01fSmrg 7034642e01fSmrg/** 7044642e01fSmrg * Update the motion history for the device and (if appropriate) for its 7054642e01fSmrg * master device. 7064642e01fSmrg * @param dev Slave device to update. 7074642e01fSmrg * @param first First valuator to append to history. 7084642e01fSmrg * @param num Total number of valuators to append to history. 7094642e01fSmrg * @param ms Current time 7104642e01fSmrg */ 7114642e01fSmrgstatic void 7124642e01fSmrgupdateHistory(DeviceIntPtr dev, int first, int num, CARD32 ms) 7134642e01fSmrg{ 7144642e01fSmrg updateMotionHistory(dev, ms, first, num, &dev->last.valuators[first]); 7154642e01fSmrg if (dev->u.master) 7164642e01fSmrg updateMotionHistory(dev->u.master, ms, first, num, 7174642e01fSmrg &dev->last.valuators[first]); 7184642e01fSmrg} 7194642e01fSmrg 7204642e01fSmrg/** 7214642e01fSmrg * Calculate how many DeviceValuator events are needed given a number of 7224642e01fSmrg * valuators. 7234642e01fSmrg * @param num_valuators Number of valuators to attach to event. 7244642e01fSmrg * @return the number of DeviceValuator events needed. 7254642e01fSmrg */ 7264642e01fSmrgstatic int 7274642e01fSmrgcountValuatorEvents(int num_valuators) 7284642e01fSmrg{ 7294642e01fSmrg if (num_valuators) { 7304642e01fSmrg if (((num_valuators - 1) / 6) + 1 > MAX_VALUATOR_EVENTS) 7314642e01fSmrg num_valuators = MAX_VALUATOR_EVENTS * 6; 7324642e01fSmrg return ((num_valuators - 1)/ 6) + 1; 7334642e01fSmrg } else 7344642e01fSmrg return 0; 7354642e01fSmrg} 73605b261ecSmrg 73705b261ecSmrg/** 73805b261ecSmrg * Convenience wrapper around GetKeyboardValuatorEvents, that takes no 73905b261ecSmrg * valuators. 74005b261ecSmrg */ 74105b261ecSmrg_X_EXPORT int 7424642e01fSmrgGetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) { 74305b261ecSmrg return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL); 74405b261ecSmrg} 74505b261ecSmrg 74605b261ecSmrg 74705b261ecSmrg/** 74805b261ecSmrg * Returns a set of keyboard events for KeyPress/KeyRelease, optionally 74905b261ecSmrg * also with valuator events. Handles Xi and XKB. 75005b261ecSmrg * 7514642e01fSmrg * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the 7524642e01fSmrg * event (ProcessOtherEvent). 7534642e01fSmrg * 75405b261ecSmrg * events is not NULL-terminated; the return value is the number of events. 75505b261ecSmrg * The DDX is responsible for allocating the event structure in the first 75605b261ecSmrg * place via GetMaximumEventsNum(), and for freeing it. 75705b261ecSmrg * 75805b261ecSmrg * This function does not change the core keymap to that of the device; 75905b261ecSmrg * that is done by SwitchCoreKeyboard, which is called from 76005b261ecSmrg * mieqProcessInputEvents. If replacing that function, take care to call 76105b261ecSmrg * SetCoreKeyboard before processInputProc, so keymaps are altered to suit. 76205b261ecSmrg * 76305b261ecSmrg * Note that this function recurses! If called for non-XKB, a repeating 76405b261ecSmrg * key press will trigger a matching KeyRelease, as well as the 76505b261ecSmrg * KeyPresses. 76605b261ecSmrg */ 76705b261ecSmrg_X_EXPORT int 7684642e01fSmrgGetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, 76905b261ecSmrg int key_code, int first_valuator, 77005b261ecSmrg int num_valuators, int *valuators) { 77105b261ecSmrg int numEvents = 0; 77205b261ecSmrg CARD32 ms = 0; 7734642e01fSmrg KeySym *map; 7744642e01fSmrg KeySym sym; 77505b261ecSmrg deviceKeyButtonPointer *kbp = NULL; 77605b261ecSmrg 7774642e01fSmrg if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed || 7784642e01fSmrg (type != KeyPress && type != KeyRelease) || 7794642e01fSmrg (key_code < 8 || key_code > 255)) 78005b261ecSmrg return 0; 78105b261ecSmrg 7824642e01fSmrg numEvents = 1; 78305b261ecSmrg 7844642e01fSmrg map = pDev->key->curKeySyms.map; 7854642e01fSmrg sym = map[(key_code - pDev->key->curKeySyms.minKeyCode) 7864642e01fSmrg * pDev->key->curKeySyms.mapWidth]; 78705b261ecSmrg 7884642e01fSmrg events = updateFromMaster(events, pDev, &numEvents); 78905b261ecSmrg 7904642e01fSmrg numEvents += countValuatorEvents(num_valuators); 79105b261ecSmrg 79205b261ecSmrg#ifdef XKB 79305b261ecSmrg if (noXkbExtension) 79405b261ecSmrg#endif 79505b261ecSmrg { 79605b261ecSmrg switch (sym) { 79705b261ecSmrg case XK_Num_Lock: 79805b261ecSmrg case XK_Caps_Lock: 79905b261ecSmrg case XK_Scroll_Lock: 80005b261ecSmrg case XK_Shift_Lock: 80105b261ecSmrg if (type == KeyRelease) 80205b261ecSmrg return 0; 80305b261ecSmrg else if (type == KeyPress && key_is_down(pDev, key_code)) 80405b261ecSmrg type = KeyRelease; 80505b261ecSmrg } 80605b261ecSmrg } 80705b261ecSmrg 80805b261ecSmrg /* Handle core repeating, via press/release/press/release. 80905b261ecSmrg * FIXME: In theory, if you're repeating with two keyboards in non-XKB, 81005b261ecSmrg * you could get unbalanced events here. */ 81105b261ecSmrg if (type == KeyPress && key_is_down(pDev, key_code)) { 81205b261ecSmrg /* If autorepeating is disabled either globally or just for that key, 81305b261ecSmrg * or we have a modifier, don't generate a repeat event. */ 81405b261ecSmrg if (!pDev->kbdfeed->ctrl.autoRepeat || 81505b261ecSmrg !key_autorepeats(pDev, key_code) || 81605b261ecSmrg pDev->key->modifierMap[key_code]) 81705b261ecSmrg return 0; 81805b261ecSmrg 81905b261ecSmrg#ifdef XKB 82005b261ecSmrg if (noXkbExtension) 82105b261ecSmrg#endif 82205b261ecSmrg { 8234642e01fSmrg int numReleaseEvents; 8244642e01fSmrg 8254642e01fSmrg numReleaseEvents = GetKeyboardValuatorEvents(events, pDev, 8264642e01fSmrg KeyRelease, key_code, 8274642e01fSmrg first_valuator, 8284642e01fSmrg num_valuators, 8294642e01fSmrg valuators); 8304642e01fSmrg numEvents += numReleaseEvents; 8314642e01fSmrg events += numReleaseEvents; 83205b261ecSmrg } 83305b261ecSmrg } 83405b261ecSmrg 83505b261ecSmrg ms = GetTimeInMillis(); 83605b261ecSmrg 8374642e01fSmrg kbp = (deviceKeyButtonPointer *) events->event; 83805b261ecSmrg kbp->time = ms; 83905b261ecSmrg kbp->deviceid = pDev->id; 84005b261ecSmrg kbp->detail = key_code; 84105b261ecSmrg if (type == KeyPress) { 84205b261ecSmrg kbp->type = DeviceKeyPress; 84305b261ecSmrg set_key_down(pDev, key_code); 84405b261ecSmrg } 84505b261ecSmrg else if (type == KeyRelease) { 84605b261ecSmrg kbp->type = DeviceKeyRelease; 84705b261ecSmrg set_key_up(pDev, key_code); 84805b261ecSmrg } 84905b261ecSmrg 85005b261ecSmrg events++; 85105b261ecSmrg if (num_valuators) { 85205b261ecSmrg kbp->deviceid |= MORE_EVENTS; 85305b261ecSmrg clipValuators(pDev, first_valuator, num_valuators, valuators); 85405b261ecSmrg events = getValuatorEvents(events, pDev, first_valuator, 85505b261ecSmrg num_valuators, valuators); 85605b261ecSmrg } 85705b261ecSmrg 85805b261ecSmrg return numEvents; 85905b261ecSmrg} 86005b261ecSmrg 8614642e01fSmrg/** 8624642e01fSmrg * Initialize an event list and fill with 32 byte sized events. 8634642e01fSmrg * This event list is to be passed into GetPointerEvents() and 8644642e01fSmrg * GetKeyboardEvents(). 8654642e01fSmrg * 8664642e01fSmrg * @param num_events Number of elements in list. 8674642e01fSmrg */ 8684642e01fSmrgEventListPtr 8694642e01fSmrgInitEventList(int num_events) 8704642e01fSmrg{ 8714642e01fSmrg EventListPtr events; 8724642e01fSmrg int i; 8734642e01fSmrg 8744642e01fSmrg events = (EventListPtr)xcalloc(num_events, sizeof(EventList)); 8754642e01fSmrg if (!events) 8764642e01fSmrg return NULL; 8774642e01fSmrg 8784642e01fSmrg for (i = 0; i < num_events; i++) 8794642e01fSmrg { 8804642e01fSmrg events[i].evlen = sizeof(xEvent); 8814642e01fSmrg events[i].event = xcalloc(1, sizeof(xEvent)); 8824642e01fSmrg if (!events[i].event) 8834642e01fSmrg { 8844642e01fSmrg /* rollback */ 8854642e01fSmrg while(i--) 8864642e01fSmrg xfree(events[i].event); 8874642e01fSmrg xfree(events); 8884642e01fSmrg events = NULL; 8894642e01fSmrg break; 8904642e01fSmrg } 8914642e01fSmrg } 8924642e01fSmrg 8934642e01fSmrg return events; 8944642e01fSmrg} 8954642e01fSmrg 8964642e01fSmrg/** 8974642e01fSmrg * Allocs min_size memory for each event in the list. 8984642e01fSmrg */ 8994642e01fSmrg_X_EXPORT void 9004642e01fSmrgSetMinimumEventSize(EventListPtr list, int num_events, int min_size) 9014642e01fSmrg{ 9024642e01fSmrg if (!list) 9034642e01fSmrg return; 9044642e01fSmrg 9054642e01fSmrg while(num_events--) 9064642e01fSmrg { 9074642e01fSmrg if (list[num_events].evlen < min_size) 9084642e01fSmrg { 9094642e01fSmrg list[num_events].evlen = min_size; 9104642e01fSmrg list[num_events].event = realloc(list[num_events].event, min_size); 9114642e01fSmrg if (!list[num_events].event) 9124642e01fSmrg { 9134642e01fSmrg FatalError("[dix] Failed to set event list's " 9144642e01fSmrg "min_size to %d.\n", min_size); 9154642e01fSmrg } 9164642e01fSmrg } 9174642e01fSmrg } 9184642e01fSmrg} 9194642e01fSmrg 9204642e01fSmrg/** 9214642e01fSmrg * Free an event list. 9224642e01fSmrg * 9234642e01fSmrg * @param list The list to be freed. 9244642e01fSmrg * @param num_events Number of elements in list. 9254642e01fSmrg */ 9264642e01fSmrg_X_EXPORT void 9274642e01fSmrgFreeEventList(EventListPtr list, int num_events) 9284642e01fSmrg{ 9294642e01fSmrg if (!list) 9304642e01fSmrg return; 9314642e01fSmrg while(num_events--) 9324642e01fSmrg xfree(list[num_events].event); 9334642e01fSmrg xfree(list); 9344642e01fSmrg} 93505b261ecSmrg 93605b261ecSmrg/** 9374642e01fSmrg * Generate a series of xEvents (filled into the EventList) representing 9384642e01fSmrg * pointer motion, or button presses. Xi and XKB-aware. 9394642e01fSmrg * 9404642e01fSmrg * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the 9414642e01fSmrg * event (ProcessOtherEvent). 94205b261ecSmrg * 94305b261ecSmrg * events is not NULL-terminated; the return value is the number of events. 94405b261ecSmrg * The DDX is responsible for allocating the event structure in the first 9454642e01fSmrg * place via InitEventList() and GetMaximumEventsNum(), and for freeing it. 9464642e01fSmrg * 9474642e01fSmrg * In the generated events rootX/Y will be in absolute screen coords and 9484642e01fSmrg * the valuator information in the absolute or relative device coords. 9494642e01fSmrg * 9504642e01fSmrg * last.valuators[x] of the device is always in absolute device coords. 9514642e01fSmrg * last.valuators[x] of the master device is in absolute screen coords. 9524642e01fSmrg * 9534642e01fSmrg * master->last.valuators[x] for x > 2 is undefined. 95405b261ecSmrg */ 95505b261ecSmrg_X_EXPORT int 9564642e01fSmrgGetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, 95705b261ecSmrg int flags, int first_valuator, int num_valuators, 95805b261ecSmrg int *valuators) { 9594642e01fSmrg int num_events = 1; 9604642e01fSmrg CARD32 ms; 96105b261ecSmrg deviceKeyButtonPointer *kbp = NULL; 9624642e01fSmrg int x, y, /* switches between device and screen coords */ 9634642e01fSmrg cx, cy; /* only screen coordinates */ 96405b261ecSmrg ScreenPtr scr = miPointerGetScreen(pDev); 96505b261ecSmrg 9664642e01fSmrg ms = GetTimeInMillis(); /* before pointer update to help precision */ 96705b261ecSmrg 9684642e01fSmrg if (!scr || !pDev->valuator || first_valuator < 0 || 9694642e01fSmrg ((num_valuators + first_valuator) > pDev->valuator->numAxes) || 9704642e01fSmrg (type != MotionNotify && type != ButtonPress && type != ButtonRelease) || 9714642e01fSmrg (type != MotionNotify && !pDev->button) || 9724642e01fSmrg (type == MotionNotify && num_valuators <= 0)) 97305b261ecSmrg return 0; 97405b261ecSmrg 9754642e01fSmrg num_events += countValuatorEvents(num_valuators); 97605b261ecSmrg 9774642e01fSmrg events = updateFromMaster(events, pDev, &num_events); 97805b261ecSmrg 9794642e01fSmrg if (flags & POINTER_ABSOLUTE) 9804642e01fSmrg { 9814642e01fSmrg if (flags & POINTER_SCREEN) /* valuators are in screen coords */ 9824642e01fSmrg { 98305b261ecSmrg 9844642e01fSmrg valuators[0] = rescaleValuatorAxis(valuators[0], NULL, 9854642e01fSmrg pDev->valuator->axes + 0, 9864642e01fSmrg scr->width); 9874642e01fSmrg valuators[1] = rescaleValuatorAxis(valuators[1], NULL, 9884642e01fSmrg pDev->valuator->axes + 1, 9894642e01fSmrg scr->height); 99005b261ecSmrg } 99105b261ecSmrg 9924642e01fSmrg moveAbsolute(pDev, &x, &y, first_valuator, num_valuators, valuators); 9934642e01fSmrg } else { 99405b261ecSmrg if (flags & POINTER_ACCELERATE) 9954642e01fSmrg accelPointer(pDev, first_valuator, num_valuators, valuators, ms); 9964642e01fSmrg moveRelative(pDev, &x, &y, first_valuator, num_valuators, valuators); 99705b261ecSmrg } 99805b261ecSmrg 9994642e01fSmrg positionSprite(pDev, &x, &y, scr, &cx, &cy); 10004642e01fSmrg updateHistory(pDev, first_valuator, num_valuators, ms); 100105b261ecSmrg 100205b261ecSmrg 10034642e01fSmrg /* Update the valuators with the true value sent to the client*/ 10044642e01fSmrg if (num_valuators >= 1 && first_valuator == 0) 10054642e01fSmrg valuators[0] = x; 100605b261ecSmrg if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) 10074642e01fSmrg valuators[1 - first_valuator] = y; 100805b261ecSmrg 10094642e01fSmrg kbp = (deviceKeyButtonPointer *) events->event; 10104642e01fSmrg kbp->time = ms; 10114642e01fSmrg kbp->deviceid = pDev->id; 101205b261ecSmrg 10134642e01fSmrg if (type == MotionNotify) { 10144642e01fSmrg kbp->type = DeviceMotionNotify; 10154642e01fSmrg } 10164642e01fSmrg else { 10174642e01fSmrg if (type == ButtonPress) 10184642e01fSmrg kbp->type = DeviceButtonPress; 10194642e01fSmrg else if (type == ButtonRelease) 10204642e01fSmrg kbp->type = DeviceButtonRelease; 10214642e01fSmrg kbp->detail = buttons; 10224642e01fSmrg } 102305b261ecSmrg 10244642e01fSmrg kbp->root_x = cx; /* root_x/y always in screen coords */ 10254642e01fSmrg kbp->root_y = cy; 102605b261ecSmrg 10274642e01fSmrg events++; 10284642e01fSmrg if (num_valuators) { 10294642e01fSmrg kbp->deviceid |= MORE_EVENTS; 10304642e01fSmrg if (flags & POINTER_ABSOLUTE) 103105b261ecSmrg clipValuators(pDev, first_valuator, num_valuators, valuators); 10324642e01fSmrg events = getValuatorEvents(events, pDev, first_valuator, 10334642e01fSmrg num_valuators, valuators); 103405b261ecSmrg } 103505b261ecSmrg 103605b261ecSmrg return num_events; 103705b261ecSmrg} 103805b261ecSmrg 103905b261ecSmrg 104005b261ecSmrg/** 104105b261ecSmrg * Post ProximityIn/ProximityOut events, accompanied by valuators. 104205b261ecSmrg * 104305b261ecSmrg * events is not NULL-terminated; the return value is the number of events. 104405b261ecSmrg * The DDX is responsible for allocating the event structure in the first 104505b261ecSmrg * place via GetMaximumEventsNum(), and for freeing it. 104605b261ecSmrg */ 104705b261ecSmrg_X_EXPORT int 10484642e01fSmrgGetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, 104905b261ecSmrg int first_valuator, int num_valuators, int *valuators) 105005b261ecSmrg{ 105105b261ecSmrg int num_events = 1; 10524642e01fSmrg deviceKeyButtonPointer *kbp; 10534642e01fSmrg DeviceIntPtr master; 105405b261ecSmrg 105505b261ecSmrg /* Sanity checks. */ 105605b261ecSmrg if (type != ProximityIn && type != ProximityOut) 105705b261ecSmrg return 0; 105805b261ecSmrg if (!pDev->valuator) 105905b261ecSmrg return 0; 106005b261ecSmrg /* Do we need to send a DeviceValuator event? */ 106105b261ecSmrg if ((pDev->valuator->mode & 1) == Relative) 106205b261ecSmrg num_valuators = 0; 106305b261ecSmrg 106405b261ecSmrg if (num_valuators) { 106505b261ecSmrg if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS) 106605b261ecSmrg num_valuators = MAX_VALUATOR_EVENTS * 6; 106705b261ecSmrg num_events += ((num_valuators - 1) / 6) + 1; 106805b261ecSmrg } 106905b261ecSmrg 107005b261ecSmrg /* You fail. */ 107105b261ecSmrg if (first_valuator < 0 || 107205b261ecSmrg (num_valuators + first_valuator) > pDev->valuator->numAxes) 107305b261ecSmrg return 0; 107405b261ecSmrg 10754642e01fSmrg master = pDev->u.master; 10764642e01fSmrg if (master && master->u.lastSlave != pDev) 10774642e01fSmrg { 10784642e01fSmrg updateSlaveDeviceCoords(master, pDev); 10794642e01fSmrg master->u.lastSlave = pDev; 10804642e01fSmrg master->last.numValuators = pDev->last.numValuators; 10814642e01fSmrg } 10824642e01fSmrg 10834642e01fSmrg kbp = (deviceKeyButtonPointer *) events->event; 108405b261ecSmrg kbp->type = type; 108505b261ecSmrg kbp->deviceid = pDev->id; 108605b261ecSmrg kbp->detail = 0; 108705b261ecSmrg kbp->time = GetTimeInMillis(); 108805b261ecSmrg 108905b261ecSmrg if (num_valuators) { 109005b261ecSmrg kbp->deviceid |= MORE_EVENTS; 109105b261ecSmrg events++; 109205b261ecSmrg clipValuators(pDev, first_valuator, num_valuators, valuators); 109305b261ecSmrg events = getValuatorEvents(events, pDev, first_valuator, 109405b261ecSmrg num_valuators, valuators); 109505b261ecSmrg } 109605b261ecSmrg 109705b261ecSmrg return num_events; 109805b261ecSmrg} 109905b261ecSmrg 110005b261ecSmrg/** 110105b261ecSmrg * Synthesize a single motion event for the core pointer. 110205b261ecSmrg * 110305b261ecSmrg * Used in cursor functions, e.g. when cursor confinement changes, and we need 110405b261ecSmrg * to shift the pointer to get it inside the new bounds. 110505b261ecSmrg */ 110605b261ecSmrgvoid 11074642e01fSmrgPostSyntheticMotion(DeviceIntPtr pDev, 11084642e01fSmrg int x, 11094642e01fSmrg int y, 11104642e01fSmrg int screen, 11114642e01fSmrg unsigned long time) 111205b261ecSmrg{ 111305b261ecSmrg xEvent xE; 111405b261ecSmrg 111505b261ecSmrg#ifdef PANORAMIX 111605b261ecSmrg /* Translate back to the sprite screen since processInputProc 111705b261ecSmrg will translate from sprite screen to screen 0 upon reentry 111805b261ecSmrg to the DIX layer. */ 111905b261ecSmrg if (!noPanoramiXExtension) { 112005b261ecSmrg x += panoramiXdataPtr[0].x - panoramiXdataPtr[screen].x; 112105b261ecSmrg y += panoramiXdataPtr[0].y - panoramiXdataPtr[screen].y; 112205b261ecSmrg } 112305b261ecSmrg#endif 112405b261ecSmrg 112505b261ecSmrg memset(&xE, 0, sizeof(xEvent)); 112605b261ecSmrg xE.u.u.type = MotionNotify; 112705b261ecSmrg xE.u.keyButtonPointer.rootX = x; 112805b261ecSmrg xE.u.keyButtonPointer.rootY = y; 112905b261ecSmrg xE.u.keyButtonPointer.time = time; 113005b261ecSmrg 11314642e01fSmrg (*pDev->public.processInputProc)(&xE, pDev, 1); 113205b261ecSmrg} 1133