105b261ecSmrg/* 205b261ecSmrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. 305b261ecSmrg * 405b261ecSmrg *Permission is hereby granted, free of charge, to any person obtaining 505b261ecSmrg * a copy of this software and associated documentation files (the 605b261ecSmrg *"Software"), to deal in the Software without restriction, including 705b261ecSmrg *without limitation the rights to use, copy, modify, merge, publish, 805b261ecSmrg *distribute, sublicense, and/or sell copies of the Software, and to 905b261ecSmrg *permit persons to whom the Software is furnished to do so, subject to 1005b261ecSmrg *the following conditions: 1105b261ecSmrg * 1205b261ecSmrg *The above copyright notice and this permission notice shall be 1305b261ecSmrg *included in all copies or substantial portions of the Software. 1405b261ecSmrg * 1505b261ecSmrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1605b261ecSmrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1705b261ecSmrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1805b261ecSmrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR 1905b261ecSmrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 2005b261ecSmrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2105b261ecSmrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2205b261ecSmrg * 2305b261ecSmrg *Except as contained in this notice, the name of the XFree86 Project 2405b261ecSmrg *shall not be used in advertising or otherwise to promote the sale, use 2505b261ecSmrg *or other dealings in this Software without prior written authorization 2605b261ecSmrg *from the XFree86 Project. 2705b261ecSmrg * 2805b261ecSmrg * Authors: Dakshinamurthy Karra 2905b261ecSmrg * Suhaib M Siddiqi 3005b261ecSmrg * Peter Busch 3105b261ecSmrg * Harold L Hunt II 3205b261ecSmrg */ 3305b261ecSmrg 3405b261ecSmrg#ifdef HAVE_XWIN_CONFIG_H 3505b261ecSmrg#include <xwin-config.h> 3605b261ecSmrg#endif 3705b261ecSmrg#include "win.h" 3805b261ecSmrg 3905b261ecSmrg#include "inputstr.h" 4035c4bbdfSmrg#include "exevents.h" /* for button/axes labels */ 416747b715Smrg#include "xserver-properties.h" 429ace9065Smrg#include "inpututils.h" 4305b261ecSmrg 4405b261ecSmrg/* Peek the internal button mapping */ 4505b261ecSmrgstatic CARD8 const *g_winMouseButtonMap = NULL; 4605b261ecSmrg 4705b261ecSmrg/* 4805b261ecSmrg * Local prototypes 4905b261ecSmrg */ 5005b261ecSmrg 5105b261ecSmrgstatic void 5235c4bbdfSmrg winMouseCtrl(DeviceIntPtr pDevice, PtrCtrl * pCtrl); 5305b261ecSmrg 5405b261ecSmrgstatic void 5535c4bbdfSmrgwinMouseCtrl(DeviceIntPtr pDevice, PtrCtrl * pCtrl) 5605b261ecSmrg{ 5705b261ecSmrg} 5805b261ecSmrg 5905b261ecSmrg/* 6005b261ecSmrg * See Porting Layer Definition - p. 18 6105b261ecSmrg * This is known as a DeviceProc 6205b261ecSmrg */ 6305b261ecSmrg 6405b261ecSmrgint 6535c4bbdfSmrgwinMouseProc(DeviceIntPtr pDeviceInt, int iState) 6605b261ecSmrg{ 6735c4bbdfSmrg int lngMouseButtons, i; 6835c4bbdfSmrg int lngWheelEvents = 4; 6935c4bbdfSmrg CARD8 *map; 7035c4bbdfSmrg DevicePtr pDevice = (DevicePtr) pDeviceInt; 7135c4bbdfSmrg Atom btn_labels[9]; 7235c4bbdfSmrg Atom axes_labels[2]; 7335c4bbdfSmrg 7435c4bbdfSmrg switch (iState) { 7505b261ecSmrg case DEVICE_INIT: 7635c4bbdfSmrg /* Get number of mouse buttons */ 7735c4bbdfSmrg lngMouseButtons = GetSystemMetrics(SM_CMOUSEBUTTONS); 7835c4bbdfSmrg winMsg(X_PROBED, "%d mouse buttons found\n", lngMouseButtons); 7935c4bbdfSmrg 8035c4bbdfSmrg /* Mapping of windows events to X events: 8135c4bbdfSmrg * LEFT:1 MIDDLE:2 RIGHT:3 8235c4bbdfSmrg * SCROLL_UP:4 SCROLL_DOWN:5 8335c4bbdfSmrg * TILT_LEFT:6 TILT_RIGHT:7 8435c4bbdfSmrg * XBUTTON 1:8 XBUTTON 2:9 (most commonly 'back' and 'forward') 8535c4bbdfSmrg * ... 8635c4bbdfSmrg * 8735c4bbdfSmrg * The current Windows API only defines 2 extra buttons, so we don't 8835c4bbdfSmrg * expect more than 5 buttons to be reported, but more than that 8935c4bbdfSmrg * should be handled correctly 9035c4bbdfSmrg */ 9135c4bbdfSmrg 9235c4bbdfSmrg /* 9335c4bbdfSmrg * To map scroll wheel correctly we need at least the 3 normal buttons 9435c4bbdfSmrg */ 9535c4bbdfSmrg if (lngMouseButtons < 3) 9635c4bbdfSmrg lngMouseButtons = 3; 9735c4bbdfSmrg 9835c4bbdfSmrg /* allocate memory: 9935c4bbdfSmrg * number of buttons + 4 x mouse wheel event + 1 extra (offset for map) 10035c4bbdfSmrg */ 10135c4bbdfSmrg map = malloc(sizeof(CARD8) * (lngMouseButtons + lngWheelEvents + 1)); 10235c4bbdfSmrg 103ed6184dfSmrg /* initialize button map */ 10435c4bbdfSmrg map[0] = 0; 10535c4bbdfSmrg for (i = 1; i <= lngMouseButtons + lngWheelEvents; i++) 10635c4bbdfSmrg map[i] = i; 10735c4bbdfSmrg 10835c4bbdfSmrg btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); 10935c4bbdfSmrg btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); 11035c4bbdfSmrg btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); 11135c4bbdfSmrg btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); 11235c4bbdfSmrg btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); 11335c4bbdfSmrg btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); 11435c4bbdfSmrg btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); 11535c4bbdfSmrg btn_labels[7] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_BACK); 11635c4bbdfSmrg btn_labels[8] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_FORWARD); 11735c4bbdfSmrg 11835c4bbdfSmrg axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); 11935c4bbdfSmrg axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); 12035c4bbdfSmrg 12135c4bbdfSmrg InitPointerDeviceStruct(pDevice, 12235c4bbdfSmrg map, 12335c4bbdfSmrg lngMouseButtons + lngWheelEvents, 12435c4bbdfSmrg btn_labels, 12535c4bbdfSmrg winMouseCtrl, 12635c4bbdfSmrg GetMotionHistorySize(), 2, axes_labels); 12735c4bbdfSmrg free(map); 12835c4bbdfSmrg 12935c4bbdfSmrg g_winMouseButtonMap = pDeviceInt->button->map; 13035c4bbdfSmrg break; 13105b261ecSmrg 13205b261ecSmrg case DEVICE_ON: 13335c4bbdfSmrg pDevice->on = TRUE; 13435c4bbdfSmrg break; 13505b261ecSmrg 13605b261ecSmrg case DEVICE_CLOSE: 13735c4bbdfSmrg g_winMouseButtonMap = NULL; 1389ace9065Smrg 13905b261ecSmrg case DEVICE_OFF: 14035c4bbdfSmrg pDevice->on = FALSE; 14135c4bbdfSmrg break; 14205b261ecSmrg } 14335c4bbdfSmrg return Success; 14405b261ecSmrg} 14505b261ecSmrg 14605b261ecSmrg/* Handle the mouse wheel */ 14705b261ecSmrgint 14835c4bbdfSmrgwinMouseWheel(int *iTotalDeltaZ, int iDeltaZ, int iButtonUp, int iButtonDown) 14905b261ecSmrg{ 15035c4bbdfSmrg int button; 15135c4bbdfSmrg 15235c4bbdfSmrg /* Do we have any previous delta stored? */ 15335c4bbdfSmrg if ((*iTotalDeltaZ > 0 && iDeltaZ > 0) 15435c4bbdfSmrg || (*iTotalDeltaZ < 0 && iDeltaZ < 0)) { 15535c4bbdfSmrg /* Previous delta and of same sign as current delta */ 15635c4bbdfSmrg iDeltaZ += *iTotalDeltaZ; 15735c4bbdfSmrg *iTotalDeltaZ = 0; 15805b261ecSmrg } 15935c4bbdfSmrg else { 16035c4bbdfSmrg /* 16135c4bbdfSmrg * Previous delta of different sign, or zero. 16235c4bbdfSmrg * We will set it to zero for either case, 16335c4bbdfSmrg * as blindly setting takes just as much time 16435c4bbdfSmrg * as checking, then setting if necessary :) 16535c4bbdfSmrg */ 16635c4bbdfSmrg *iTotalDeltaZ = 0; 16705b261ecSmrg } 16805b261ecSmrg 16935c4bbdfSmrg /* 17035c4bbdfSmrg * Only process this message if the wheel has moved further than 17135c4bbdfSmrg * WHEEL_DELTA 17235c4bbdfSmrg */ 17335c4bbdfSmrg if (iDeltaZ >= WHEEL_DELTA || (-1 * iDeltaZ) >= WHEEL_DELTA) { 17435c4bbdfSmrg *iTotalDeltaZ = 0; 17535c4bbdfSmrg 17635c4bbdfSmrg /* Figure out how many whole deltas of the wheel we have */ 17735c4bbdfSmrg iDeltaZ /= WHEEL_DELTA; 17805b261ecSmrg } 17935c4bbdfSmrg else { 18035c4bbdfSmrg /* 18135c4bbdfSmrg * Wheel has not moved past WHEEL_DELTA threshold; 18235c4bbdfSmrg * we will store the wheel delta until the threshold 18335c4bbdfSmrg * has been reached. 18435c4bbdfSmrg */ 18535c4bbdfSmrg *iTotalDeltaZ = iDeltaZ; 18635c4bbdfSmrg return 0; 18705b261ecSmrg } 18805b261ecSmrg 18935c4bbdfSmrg /* Set the button to indicate up or down wheel delta */ 19035c4bbdfSmrg if (iDeltaZ > 0) { 19135c4bbdfSmrg button = iButtonUp; 19205b261ecSmrg } 19335c4bbdfSmrg else { 19435c4bbdfSmrg button = iButtonDown; 19505b261ecSmrg } 19605b261ecSmrg 19735c4bbdfSmrg /* 19835c4bbdfSmrg * Flip iDeltaZ to positive, if negative, 19935c4bbdfSmrg * because always need to generate a *positive* number of 20035c4bbdfSmrg * button clicks for the Z axis. 20135c4bbdfSmrg */ 20235c4bbdfSmrg if (iDeltaZ < 0) { 20335c4bbdfSmrg iDeltaZ *= -1; 20405b261ecSmrg } 20505b261ecSmrg 20635c4bbdfSmrg /* Generate X input messages for each wheel delta we have seen */ 20735c4bbdfSmrg while (iDeltaZ--) { 20835c4bbdfSmrg /* Push the wheel button */ 20935c4bbdfSmrg winMouseButtonsSendEvent(ButtonPress, button); 21005b261ecSmrg 21135c4bbdfSmrg /* Release the wheel button */ 21235c4bbdfSmrg winMouseButtonsSendEvent(ButtonRelease, button); 21305b261ecSmrg } 21405b261ecSmrg 21535c4bbdfSmrg return 0; 21605b261ecSmrg} 21705b261ecSmrg 21805b261ecSmrg/* 21905b261ecSmrg * Enqueue a mouse button event 22005b261ecSmrg */ 22105b261ecSmrg 22205b261ecSmrgvoid 22335c4bbdfSmrgwinMouseButtonsSendEvent(int iEventType, int iButton) 22405b261ecSmrg{ 22535c4bbdfSmrg ValuatorMask mask; 2266747b715Smrg 22735c4bbdfSmrg if (g_winMouseButtonMap) 22835c4bbdfSmrg iButton = g_winMouseButtonMap[iButton]; 2296747b715Smrg 23035c4bbdfSmrg valuator_mask_zero(&mask); 23135c4bbdfSmrg QueuePointerEvents(g_pwinPointer, iEventType, iButton, 23235c4bbdfSmrg POINTER_RELATIVE, &mask); 2336747b715Smrg 2346747b715Smrg#if CYGDEBUG 23535c4bbdfSmrg ErrorF("winMouseButtonsSendEvent: iEventType: %d, iButton: %d\n", 23635c4bbdfSmrg iEventType, iButton); 23705b261ecSmrg#endif 23805b261ecSmrg} 23905b261ecSmrg 24005b261ecSmrg/* 24105b261ecSmrg * Decide what to do with a Windows mouse message 24205b261ecSmrg */ 24305b261ecSmrg 24405b261ecSmrgint 24535c4bbdfSmrgwinMouseButtonsHandle(ScreenPtr pScreen, 24635c4bbdfSmrg int iEventType, int iButton, WPARAM wParam) 24705b261ecSmrg{ 24835c4bbdfSmrg winScreenPriv(pScreen); 24935c4bbdfSmrg winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 25035c4bbdfSmrg 25135c4bbdfSmrg /* Send button events right away if emulate 3 buttons is off */ 25235c4bbdfSmrg if (pScreenInfo->iE3BTimeout == WIN_E3B_OFF) { 25335c4bbdfSmrg /* Emulate 3 buttons is off, send the button event */ 25435c4bbdfSmrg winMouseButtonsSendEvent(iEventType, iButton); 25535c4bbdfSmrg return 0; 25605b261ecSmrg } 25705b261ecSmrg 25835c4bbdfSmrg /* Emulate 3 buttons is on, let the fun begin */ 25935c4bbdfSmrg if (iEventType == ButtonPress 26035c4bbdfSmrg && pScreenPriv->iE3BCachedPress == 0 26135c4bbdfSmrg && !pScreenPriv->fE3BFakeButton2Sent) { 26235c4bbdfSmrg /* 26335c4bbdfSmrg * Button was pressed, no press is cached, 26435c4bbdfSmrg * and there is no fake button 2 release pending. 26535c4bbdfSmrg */ 26635c4bbdfSmrg 26735c4bbdfSmrg /* Store button press type */ 26835c4bbdfSmrg pScreenPriv->iE3BCachedPress = iButton; 26935c4bbdfSmrg 27035c4bbdfSmrg /* 27135c4bbdfSmrg * Set a timer to send this button press if the other button 27235c4bbdfSmrg * is not pressed within the timeout time. 27335c4bbdfSmrg */ 27435c4bbdfSmrg SetTimer(pScreenPriv->hwndScreen, 27535c4bbdfSmrg WIN_E3B_TIMER_ID, pScreenInfo->iE3BTimeout, NULL); 27605b261ecSmrg } 27735c4bbdfSmrg else if (iEventType == ButtonPress 27835c4bbdfSmrg && pScreenPriv->iE3BCachedPress != 0 27935c4bbdfSmrg && pScreenPriv->iE3BCachedPress != iButton 28035c4bbdfSmrg && !pScreenPriv->fE3BFakeButton2Sent) { 28135c4bbdfSmrg /* 28235c4bbdfSmrg * Button press is cached, other button was pressed, 28335c4bbdfSmrg * and there is no fake button 2 release pending. 28435c4bbdfSmrg */ 28535c4bbdfSmrg 28635c4bbdfSmrg /* Mouse button was cached and other button was pressed */ 28735c4bbdfSmrg KillTimer(pScreenPriv->hwndScreen, WIN_E3B_TIMER_ID); 28835c4bbdfSmrg pScreenPriv->iE3BCachedPress = 0; 28935c4bbdfSmrg 29035c4bbdfSmrg /* Send fake middle button */ 29135c4bbdfSmrg winMouseButtonsSendEvent(ButtonPress, Button2); 29235c4bbdfSmrg 29335c4bbdfSmrg /* Indicate that a fake middle button event was sent */ 29435c4bbdfSmrg pScreenPriv->fE3BFakeButton2Sent = TRUE; 29505b261ecSmrg } 29635c4bbdfSmrg else if (iEventType == ButtonRelease 29735c4bbdfSmrg && pScreenPriv->iE3BCachedPress == iButton) { 29835c4bbdfSmrg /* 29935c4bbdfSmrg * Cached button was released before timer ran out, 30035c4bbdfSmrg * and before the other mouse button was pressed. 30135c4bbdfSmrg */ 30235c4bbdfSmrg KillTimer(pScreenPriv->hwndScreen, WIN_E3B_TIMER_ID); 30335c4bbdfSmrg pScreenPriv->iE3BCachedPress = 0; 30435c4bbdfSmrg 30535c4bbdfSmrg /* Send cached press, then send release */ 30635c4bbdfSmrg winMouseButtonsSendEvent(ButtonPress, iButton); 30735c4bbdfSmrg winMouseButtonsSendEvent(ButtonRelease, iButton); 30805b261ecSmrg } 30935c4bbdfSmrg else if (iEventType == ButtonRelease 31035c4bbdfSmrg && pScreenPriv->fE3BFakeButton2Sent && !(wParam & MK_LBUTTON) 31135c4bbdfSmrg && !(wParam & MK_RBUTTON)) { 31235c4bbdfSmrg /* 31335c4bbdfSmrg * Fake button 2 was sent and both mouse buttons have now been released 31435c4bbdfSmrg */ 31535c4bbdfSmrg pScreenPriv->fE3BFakeButton2Sent = FALSE; 31635c4bbdfSmrg 31735c4bbdfSmrg /* Send middle mouse button release */ 31835c4bbdfSmrg winMouseButtonsSendEvent(ButtonRelease, Button2); 31905b261ecSmrg } 32035c4bbdfSmrg else if (iEventType == ButtonRelease 32135c4bbdfSmrg && pScreenPriv->iE3BCachedPress == 0 32235c4bbdfSmrg && !pScreenPriv->fE3BFakeButton2Sent) { 32335c4bbdfSmrg /* 32435c4bbdfSmrg * Button was release, no button is cached, 32535c4bbdfSmrg * and there is no fake button 2 release is pending. 32635c4bbdfSmrg */ 32735c4bbdfSmrg winMouseButtonsSendEvent(ButtonRelease, iButton); 32805b261ecSmrg } 32905b261ecSmrg 33035c4bbdfSmrg return 0; 33105b261ecSmrg} 3326747b715Smrg 3336747b715Smrg/** 3346747b715Smrg * Enqueue a motion event. 3356747b715Smrg * 3366747b715Smrg */ 33735c4bbdfSmrgvoid 33835c4bbdfSmrgwinEnqueueMotion(int x, int y) 3396747b715Smrg{ 34035c4bbdfSmrg int valuators[2]; 34135c4bbdfSmrg ValuatorMask mask; 34235c4bbdfSmrg 34335c4bbdfSmrg valuators[0] = x; 34435c4bbdfSmrg valuators[1] = y; 34535c4bbdfSmrg 34635c4bbdfSmrg valuator_mask_set_range(&mask, 0, 2, valuators); 34735c4bbdfSmrg QueuePointerEvents(g_pwinPointer, MotionNotify, 0, 34835c4bbdfSmrg POINTER_ABSOLUTE | POINTER_SCREEN, &mask); 34935c4bbdfSmrg 3506747b715Smrg} 351