1706f2543Smrg/* 2706f2543SmrgDarwin event queue and event handling 3706f2543Smrg 4706f2543SmrgCopyright 2007-2008 Apple Inc. 5706f2543SmrgCopyright 2004 Kaleb S. KEITHLEY. All Rights Reserved. 6706f2543SmrgCopyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved. 7706f2543Smrg 8706f2543SmrgThis file is based on mieq.c by Keith Packard, 9706f2543Smrgwhich contains the following copyright: 10706f2543SmrgCopyright 1990, 1998 The Open Group 11706f2543Smrg 12706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its 13706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that 14706f2543Smrgthe above copyright notice appear in all copies and that both that 15706f2543Smrgcopyright notice and this permission notice appear in supporting 16706f2543Smrgdocumentation. 17706f2543Smrg 18706f2543SmrgThe above copyright notice and this permission notice shall be included in 19706f2543Smrgall copies or substantial portions of the Software. 20706f2543Smrg 21706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 25706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 26706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27706f2543Smrg 28706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be 29706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings 30706f2543Smrgin this Software without prior written authorization from The Open Group. 31706f2543Smrg */ 32706f2543Smrg 33706f2543Smrg#include "sanitizedCarbon.h" 34706f2543Smrg 35706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 36706f2543Smrg#include <dix-config.h> 37706f2543Smrg#endif 38706f2543Smrg 39706f2543Smrg#include <X11/X.h> 40706f2543Smrg#include <X11/Xmd.h> 41706f2543Smrg#include <X11/Xproto.h> 42706f2543Smrg#include "misc.h" 43706f2543Smrg#include "windowstr.h" 44706f2543Smrg#include "pixmapstr.h" 45706f2543Smrg#include "inputstr.h" 46706f2543Smrg#include "inpututils.h" 47706f2543Smrg#include "eventstr.h" 48706f2543Smrg#include "mi.h" 49706f2543Smrg#include "scrnintstr.h" 50706f2543Smrg#include "mipointer.h" 51706f2543Smrg#include "os.h" 52706f2543Smrg 53706f2543Smrg#include "darwin.h" 54706f2543Smrg#include "quartz.h" 55706f2543Smrg#include "quartzKeyboard.h" 56706f2543Smrg#include "quartzRandR.h" 57706f2543Smrg#include "darwinEvents.h" 58706f2543Smrg 59706f2543Smrg#include <sys/types.h> 60706f2543Smrg#include <sys/uio.h> 61706f2543Smrg#include <unistd.h> 62706f2543Smrg#include <pthread.h> 63706f2543Smrg#include <errno.h> 64706f2543Smrg#include <time.h> 65706f2543Smrg 66706f2543Smrg#include <IOKit/hidsystem/IOLLEvent.h> 67706f2543Smrg 68706f2543Smrg/* Fake button press/release for scroll wheel move. */ 69706f2543Smrg#define SCROLLWHEELUPFAKE 4 70706f2543Smrg#define SCROLLWHEELDOWNFAKE 5 71706f2543Smrg#define SCROLLWHEELLEFTFAKE 6 72706f2543Smrg#define SCROLLWHEELRIGHTFAKE 7 73706f2543Smrg 74706f2543Smrg#include <X11/extensions/applewmconst.h> 75706f2543Smrg#include "applewmExt.h" 76706f2543Smrg 77706f2543Smrg/* FIXME: Abstract this better */ 78706f2543Smrgextern Bool QuartzModeEventHandler(int screenNum, XQuartzEvent *e, DeviceIntPtr dev); 79706f2543Smrg 80706f2543Smrgint darwin_all_modifier_flags = 0; // last known modifier state 81706f2543Smrgint darwin_all_modifier_mask = 0; 82706f2543Smrgint darwin_x11_modifier_mask = 0; 83706f2543Smrg 84706f2543Smrg#define FD_ADD_MAX 128 85706f2543Smrgstatic int fd_add[FD_ADD_MAX]; 86706f2543Smrgint fd_add_count = 0; 87706f2543Smrgstatic pthread_mutex_t fd_add_lock = PTHREAD_MUTEX_INITIALIZER; 88706f2543Smrgstatic pthread_cond_t fd_add_ready_cond = PTHREAD_COND_INITIALIZER; 89706f2543Smrgstatic pthread_t fd_add_tid = NULL; 90706f2543Smrg 91706f2543Smrgstatic EventListPtr darwinEvents = NULL; 92706f2543Smrg 93706f2543Smrgstatic pthread_mutex_t mieq_lock = PTHREAD_MUTEX_INITIALIZER; 94706f2543Smrgstatic pthread_cond_t mieq_ready_cond = PTHREAD_COND_INITIALIZER; 95706f2543Smrg 96706f2543Smrg/*** Pthread Magics ***/ 97706f2543Smrgstatic pthread_t create_thread(void *(*func)(void *), void *arg) { 98706f2543Smrg pthread_attr_t attr; 99706f2543Smrg pthread_t tid; 100706f2543Smrg 101706f2543Smrg pthread_attr_init (&attr); 102706f2543Smrg pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); 103706f2543Smrg pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); 104706f2543Smrg pthread_create (&tid, &attr, func, arg); 105706f2543Smrg pthread_attr_destroy (&attr); 106706f2543Smrg 107706f2543Smrg return tid; 108706f2543Smrg} 109706f2543Smrg 110706f2543Smrgvoid darwinEvents_lock(void); 111706f2543Smrgvoid darwinEvents_lock(void) { 112706f2543Smrg int err; 113706f2543Smrg if((err = pthread_mutex_lock(&mieq_lock))) { 114706f2543Smrg ErrorF("%s:%s:%d: Failed to lock mieq_lock: %d\n", 115706f2543Smrg __FILE__, __FUNCTION__, __LINE__, err); 116706f2543Smrg spewCallStack(); 117706f2543Smrg } 118706f2543Smrg if(darwinEvents == NULL) { 119706f2543Smrg pthread_cond_wait(&mieq_ready_cond, &mieq_lock); 120706f2543Smrg } 121706f2543Smrg} 122706f2543Smrg 123706f2543Smrgvoid darwinEvents_unlock(void); 124706f2543Smrgvoid darwinEvents_unlock(void) { 125706f2543Smrg int err; 126706f2543Smrg if((err = pthread_mutex_unlock(&mieq_lock))) { 127706f2543Smrg ErrorF("%s:%s:%d: Failed to unlock mieq_lock: %d\n", 128706f2543Smrg __FILE__, __FUNCTION__, __LINE__, err); 129706f2543Smrg spewCallStack(); 130706f2543Smrg } 131706f2543Smrg} 132706f2543Smrg 133706f2543Smrg/* 134706f2543Smrg * DarwinPressModifierKey 135706f2543Smrg * Press or release the given modifier key (one of NX_MODIFIERKEY_* constants) 136706f2543Smrg */ 137706f2543Smrgstatic void DarwinPressModifierKey(int pressed, int key) { 138706f2543Smrg int keycode = DarwinModifierNXKeyToNXKeycode(key, 0); 139706f2543Smrg 140706f2543Smrg if (keycode == 0) { 141706f2543Smrg ErrorF("DarwinPressModifierKey bad keycode: key=%d\n", key); 142706f2543Smrg return; 143706f2543Smrg } 144706f2543Smrg 145706f2543Smrg DarwinSendKeyboardEvents(pressed, keycode); 146706f2543Smrg} 147706f2543Smrg 148706f2543Smrg/* 149706f2543Smrg * DarwinUpdateModifiers 150706f2543Smrg * Send events to update the modifier state. 151706f2543Smrg */ 152706f2543Smrg 153706f2543Smrgstatic int darwin_x11_modifier_mask_list[] = { 154706f2543Smrg#ifdef NX_DEVICELCMDKEYMASK 155706f2543Smrg NX_DEVICELCTLKEYMASK, NX_DEVICERCTLKEYMASK, 156706f2543Smrg NX_DEVICELSHIFTKEYMASK, NX_DEVICERSHIFTKEYMASK, 157706f2543Smrg NX_DEVICELCMDKEYMASK, NX_DEVICERCMDKEYMASK, 158706f2543Smrg NX_DEVICELALTKEYMASK, NX_DEVICERALTKEYMASK, 159706f2543Smrg#else 160706f2543Smrg NX_CONTROLMASK, NX_SHIFTMASK, NX_COMMANDMASK, NX_ALTERNATEMASK, 161706f2543Smrg#endif 162706f2543Smrg NX_ALPHASHIFTMASK, 163706f2543Smrg 0 164706f2543Smrg}; 165706f2543Smrg 166706f2543Smrgstatic int darwin_all_modifier_mask_additions[] = { NX_SECONDARYFNMASK, }; 167706f2543Smrg 168706f2543Smrgstatic void DarwinUpdateModifiers( 169706f2543Smrg int pressed, // KeyPress or KeyRelease 170706f2543Smrg int flags ) // modifier flags that have changed 171706f2543Smrg{ 172706f2543Smrg int *f; 173706f2543Smrg int key; 174706f2543Smrg 175706f2543Smrg /* Capslock is special. This mask is the state of capslock (on/off), 176706f2543Smrg * not the state of the button. Hopefully we can find a better solution. 177706f2543Smrg */ 178706f2543Smrg if(NX_ALPHASHIFTMASK & flags) { 179706f2543Smrg DarwinPressModifierKey(KeyPress, NX_MODIFIERKEY_ALPHALOCK); 180706f2543Smrg DarwinPressModifierKey(KeyRelease, NX_MODIFIERKEY_ALPHALOCK); 181706f2543Smrg } 182706f2543Smrg 183706f2543Smrg for(f=darwin_x11_modifier_mask_list; *f; f++) 184706f2543Smrg if(*f & flags && *f != NX_ALPHASHIFTMASK) { 185706f2543Smrg key = DarwinModifierNXMaskToNXKey(*f); 186706f2543Smrg if(key == -1) 187706f2543Smrg ErrorF("DarwinUpdateModifiers: Unsupported NXMask: 0x%x\n", *f); 188706f2543Smrg else 189706f2543Smrg DarwinPressModifierKey(pressed, key); 190706f2543Smrg } 191706f2543Smrg} 192706f2543Smrg 193706f2543Smrg/* Generic handler for Xquartz-specifc events. When possible, these should 194706f2543Smrg be moved into their own individual functions and set as handlers using 195706f2543Smrg mieqSetHandler. */ 196706f2543Smrg 197706f2543Smrgstatic void DarwinEventHandler(int screenNum, InternalEvent *ie, DeviceIntPtr dev) { 198706f2543Smrg XQuartzEvent *e = &(ie->xquartz_event); 199706f2543Smrg 200706f2543Smrg TA_SERVER(); 201706f2543Smrg 202706f2543Smrg switch(e->subtype) { 203706f2543Smrg case kXquartzControllerNotify: 204706f2543Smrg DEBUG_LOG("kXquartzControllerNotify\n"); 205706f2543Smrg AppleWMSendEvent(AppleWMControllerNotify, 206706f2543Smrg AppleWMControllerNotifyMask, 207706f2543Smrg e->data[0], 208706f2543Smrg e->data[1]); 209706f2543Smrg break; 210706f2543Smrg 211706f2543Smrg case kXquartzPasteboardNotify: 212706f2543Smrg DEBUG_LOG("kXquartzPasteboardNotify\n"); 213706f2543Smrg AppleWMSendEvent(AppleWMPasteboardNotify, 214706f2543Smrg AppleWMPasteboardNotifyMask, 215706f2543Smrg e->data[0], 216706f2543Smrg e->data[1]); 217706f2543Smrg break; 218706f2543Smrg 219706f2543Smrg case kXquartzActivate: 220706f2543Smrg DEBUG_LOG("kXquartzActivate\n"); 221706f2543Smrg QuartzShow(); 222706f2543Smrg AppleWMSendEvent(AppleWMActivationNotify, 223706f2543Smrg AppleWMActivationNotifyMask, 224706f2543Smrg AppleWMIsActive, 0); 225706f2543Smrg break; 226706f2543Smrg 227706f2543Smrg case kXquartzDeactivate: 228706f2543Smrg DEBUG_LOG("kXquartzDeactivate\n"); 229706f2543Smrg AppleWMSendEvent(AppleWMActivationNotify, 230706f2543Smrg AppleWMActivationNotifyMask, 231706f2543Smrg AppleWMIsInactive, 0); 232706f2543Smrg QuartzHide(); 233706f2543Smrg break; 234706f2543Smrg 235706f2543Smrg case kXquartzReloadPreferences: 236706f2543Smrg DEBUG_LOG("kXquartzReloadPreferences\n"); 237706f2543Smrg AppleWMSendEvent(AppleWMActivationNotify, 238706f2543Smrg AppleWMActivationNotifyMask, 239706f2543Smrg AppleWMReloadPreferences, 0); 240706f2543Smrg break; 241706f2543Smrg 242706f2543Smrg case kXquartzToggleFullscreen: 243706f2543Smrg DEBUG_LOG("kXquartzToggleFullscreen\n"); 244706f2543Smrg if(XQuartzIsRootless) 245706f2543Smrg ErrorF("Ignoring kXquartzToggleFullscreen because of rootless mode."); 246706f2543Smrg else 247706f2543Smrg QuartzRandRToggleFullscreen(); 248706f2543Smrg break; 249706f2543Smrg 250706f2543Smrg case kXquartzSetRootless: 251706f2543Smrg DEBUG_LOG("kXquartzSetRootless\n"); 252706f2543Smrg if(e->data[0]) { 253706f2543Smrg QuartzRandRSetFakeRootless(); 254706f2543Smrg } else { 255706f2543Smrg QuartzRandRSetFakeFullscreen(FALSE); 256706f2543Smrg } 257706f2543Smrg break; 258706f2543Smrg 259706f2543Smrg case kXquartzSetRootClip: 260706f2543Smrg QuartzSetRootClip((Bool)e->data[0]); 261706f2543Smrg break; 262706f2543Smrg 263706f2543Smrg case kXquartzQuit: 264706f2543Smrg GiveUp(0); 265706f2543Smrg break; 266706f2543Smrg 267706f2543Smrg case kXquartzSpaceChanged: 268706f2543Smrg DEBUG_LOG("kXquartzSpaceChanged\n"); 269706f2543Smrg QuartzSpaceChanged(e->data[0]); 270706f2543Smrg break; 271706f2543Smrg 272706f2543Smrg case kXquartzListenOnOpenFD: 273706f2543Smrg ErrorF("Calling ListenOnOpenFD() for new fd: %d\n", (int)e->data[0]); 274706f2543Smrg ListenOnOpenFD((int)e->data[0], 1); 275706f2543Smrg break; 276706f2543Smrg 277706f2543Smrg case kXquartzReloadKeymap: 278706f2543Smrg DarwinKeyboardReloadHandler(); 279706f2543Smrg break; 280706f2543Smrg 281706f2543Smrg case kXquartzDisplayChanged: 282706f2543Smrg DEBUG_LOG("kXquartzDisplayChanged\n"); 283706f2543Smrg QuartzUpdateScreens(); 284706f2543Smrg 285706f2543Smrg /* Update our RandR info */ 286706f2543Smrg QuartzRandRUpdateFakeModes(TRUE); 287706f2543Smrg break; 288706f2543Smrg 289706f2543Smrg default: 290706f2543Smrg if(!QuartzModeEventHandler(screenNum, e, dev)) 291706f2543Smrg ErrorF("Unknown application defined event type %d.\n", e->subtype); 292706f2543Smrg } 293706f2543Smrg} 294706f2543Smrg 295706f2543Smrgvoid DarwinListenOnOpenFD(int fd) { 296706f2543Smrg ErrorF("DarwinListenOnOpenFD: %d\n", fd); 297706f2543Smrg 298706f2543Smrg pthread_mutex_lock(&fd_add_lock); 299706f2543Smrg if(fd_add_count < FD_ADD_MAX) 300706f2543Smrg fd_add[fd_add_count++] = fd; 301706f2543Smrg else 302706f2543Smrg ErrorF("FD Addition buffer at max. Dropping fd addition request.\n"); 303706f2543Smrg 304706f2543Smrg pthread_cond_broadcast(&fd_add_ready_cond); 305706f2543Smrg pthread_mutex_unlock(&fd_add_lock); 306706f2543Smrg} 307706f2543Smrg 308706f2543Smrgstatic void *DarwinProcessFDAdditionQueue_thread(void *args) { 309706f2543Smrg /* TODO: Possibly adjust this to no longer be a race... maybe trigger this 310706f2543Smrg * once a client connects and claims to be the WM. 311706f2543Smrg * 312706f2543Smrg * From ajax: 313706f2543Smrg * There's already an internal callback chain for setting selection [in 1.5] 314706f2543Smrg * ownership. See the CallSelectionCallback at the bottom of 315706f2543Smrg * ProcSetSelectionOwner, and xfixes/select.c for an example of how to hook 316706f2543Smrg * into it. 317706f2543Smrg */ 318706f2543Smrg 319706f2543Smrg struct timespec sleep_for; 320706f2543Smrg struct timespec sleep_remaining; 321706f2543Smrg 322706f2543Smrg sleep_for.tv_sec = 3; 323706f2543Smrg sleep_for.tv_nsec = 0; 324706f2543Smrg 325706f2543Smrg ErrorF("X11.app: DarwinProcessFDAdditionQueue_thread: Sleeping to allow xinitrc to catchup.\n"); 326706f2543Smrg while(nanosleep(&sleep_for, &sleep_remaining) != 0) { 327706f2543Smrg sleep_for = sleep_remaining; 328706f2543Smrg } 329706f2543Smrg 330706f2543Smrg pthread_mutex_lock(&fd_add_lock); 331706f2543Smrg while(true) { 332706f2543Smrg while(fd_add_count) { 333706f2543Smrg DarwinSendDDXEvent(kXquartzListenOnOpenFD, 1, fd_add[--fd_add_count]); 334706f2543Smrg } 335706f2543Smrg pthread_cond_wait(&fd_add_ready_cond, &fd_add_lock); 336706f2543Smrg } 337706f2543Smrg 338706f2543Smrg return NULL; 339706f2543Smrg} 340706f2543Smrg 341706f2543SmrgBool DarwinEQInit(void) { 342706f2543Smrg int *p; 343706f2543Smrg 344706f2543Smrg for(p=darwin_x11_modifier_mask_list, darwin_all_modifier_mask=0; *p; p++) { 345706f2543Smrg darwin_x11_modifier_mask |= *p; 346706f2543Smrg } 347706f2543Smrg 348706f2543Smrg for(p=darwin_all_modifier_mask_additions, darwin_all_modifier_mask= darwin_x11_modifier_mask; *p; p++) { 349706f2543Smrg darwin_all_modifier_mask |= *p; 350706f2543Smrg } 351706f2543Smrg 352706f2543Smrg mieqInit(); 353706f2543Smrg mieqSetHandler(ET_XQuartz, DarwinEventHandler); 354706f2543Smrg 355706f2543Smrg /* Note that this *could* cause a potential async issue, since we're checking 356706f2543Smrg * darwinEvents without holding the lock, but darwinEvents is only ever set 357706f2543Smrg * here, so I don't bother. 358706f2543Smrg */ 359706f2543Smrg if (!darwinEvents) { 360706f2543Smrg darwinEvents = InitEventList(GetMaximumEventsNum());; 361706f2543Smrg 362706f2543Smrg if (!darwinEvents) 363706f2543Smrg FatalError("Couldn't allocate event buffer\n"); 364706f2543Smrg 365706f2543Smrg darwinEvents_lock(); 366706f2543Smrg pthread_cond_broadcast(&mieq_ready_cond); 367706f2543Smrg darwinEvents_unlock(); 368706f2543Smrg } 369706f2543Smrg 370706f2543Smrg if(!fd_add_tid) 371706f2543Smrg fd_add_tid = create_thread(DarwinProcessFDAdditionQueue_thread, NULL); 372706f2543Smrg 373706f2543Smrg return TRUE; 374706f2543Smrg} 375706f2543Smrg 376706f2543Smrg/* 377706f2543Smrg * ProcessInputEvents 378706f2543Smrg * Read and process events from the event queue until it is empty. 379706f2543Smrg */ 380706f2543Smrgvoid ProcessInputEvents(void) { 381706f2543Smrg char nullbyte; 382706f2543Smrg int x = sizeof(nullbyte); 383706f2543Smrg 384706f2543Smrg TA_SERVER(); 385706f2543Smrg 386706f2543Smrg mieqProcessInputEvents(); 387706f2543Smrg 388706f2543Smrg // Empty the signaling pipe 389706f2543Smrg while (x == sizeof(nullbyte)) { 390706f2543Smrg x = read(darwinEventReadFD, &nullbyte, sizeof(nullbyte)); 391706f2543Smrg } 392706f2543Smrg} 393706f2543Smrg 394706f2543Smrg/* Sends a null byte down darwinEventWriteFD, which will cause the 395706f2543Smrg Dispatch() event loop to check out event queue */ 396706f2543Smrgstatic void DarwinPokeEQ(void) { 397706f2543Smrg char nullbyte=0; 398706f2543Smrg // <daniels> oh, i ... er ... christ. 399706f2543Smrg write(darwinEventWriteFD, &nullbyte, sizeof(nullbyte)); 400706f2543Smrg} 401706f2543Smrg 402706f2543Smrg/* Convert from Appkit pointer input values to X input values: 403706f2543Smrg * Note: pointer_x and pointer_y are relative to the upper-left of primary 404706f2543Smrg * display. 405706f2543Smrg */ 406706f2543Smrgstatic void DarwinPrepareValuators(DeviceIntPtr pDev, int *valuators, ScreenPtr screen, 407706f2543Smrg float pointer_x, float pointer_y, 408706f2543Smrg float pressure, float tilt_x, float tilt_y) { 409706f2543Smrg /* Fix offset between darwin and X screens */ 410706f2543Smrg pointer_x -= darwinMainScreenX + screen->x; 411706f2543Smrg pointer_y -= darwinMainScreenY + screen->y; 412706f2543Smrg 413706f2543Smrg if(pointer_x < 0.0) 414706f2543Smrg pointer_x = 0.0; 415706f2543Smrg 416706f2543Smrg if(pointer_y < 0.0) 417706f2543Smrg pointer_y = 0.0; 418706f2543Smrg 419706f2543Smrg if(pDev == darwinPointer) { 420706f2543Smrg valuators[0] = pointer_x; 421706f2543Smrg valuators[1] = pointer_y; 422706f2543Smrg valuators[2] = 0; 423706f2543Smrg valuators[3] = 0; 424706f2543Smrg valuators[4] = 0; 425706f2543Smrg } else { 426706f2543Smrg /* Setup our array of values */ 427706f2543Smrg valuators[0] = XQUARTZ_VALUATOR_LIMIT * (pointer_x / (float)screenInfo.screens[0]->width); 428706f2543Smrg valuators[1] = XQUARTZ_VALUATOR_LIMIT * (pointer_y / (float)screenInfo.screens[0]->height); 429706f2543Smrg valuators[2] = XQUARTZ_VALUATOR_LIMIT * pressure; 430706f2543Smrg valuators[3] = XQUARTZ_VALUATOR_LIMIT * tilt_x; 431706f2543Smrg valuators[4] = XQUARTZ_VALUATOR_LIMIT * tilt_y; 432706f2543Smrg } 433706f2543Smrg //DEBUG_LOG("Pointer (%f, %f), Valuators: {%d,%d,%d,%d,%d}\n", pointer_x, pointer_y, 434706f2543Smrg // valuators[0], valuators[1], valuators[2], valuators[3], valuators[4]); 435706f2543Smrg} 436706f2543Smrg 437706f2543Smrgvoid DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, float pointer_x, float pointer_y, 438706f2543Smrg float pressure, float tilt_x, float tilt_y) { 439706f2543Smrg static int darwinFakeMouseButtonDown = 0; 440706f2543Smrg int i, num_events; 441706f2543Smrg ScreenPtr screen; 442706f2543Smrg int valuators[5]; 443706f2543Smrg 444706f2543Smrg //DEBUG_LOG("x=%f, y=%f, p=%f, tx=%f, ty=%f\n", pointer_x, pointer_y, pressure, tilt_x, tilt_y); 445706f2543Smrg 446706f2543Smrg if(!darwinEvents) { 447706f2543Smrg DEBUG_LOG("DarwinSendPointerEvents called before darwinEvents was initialized\n"); 448706f2543Smrg return; 449706f2543Smrg } 450706f2543Smrg 451706f2543Smrg screen = miPointerGetScreen(pDev); 452706f2543Smrg if(!screen) { 453706f2543Smrg DEBUG_LOG("DarwinSendPointerEvents called before screen was initialized\n"); 454706f2543Smrg return; 455706f2543Smrg } 456706f2543Smrg 457706f2543Smrg /* Handle fake click */ 458706f2543Smrg if (ev_type == ButtonPress && darwinFakeButtons && ev_button == 1) { 459706f2543Smrg if(darwinFakeMouseButtonDown != 0) { 460706f2543Smrg /* We're currently "down" with another button, so release it first */ 461706f2543Smrg DarwinSendPointerEvents(pDev, ButtonRelease, darwinFakeMouseButtonDown, pointer_x, pointer_y, pressure, tilt_x, tilt_y); 462706f2543Smrg darwinFakeMouseButtonDown=0; 463706f2543Smrg } 464706f2543Smrg if (darwin_all_modifier_flags & darwinFakeMouse2Mask) { 465706f2543Smrg ev_button = 2; 466706f2543Smrg darwinFakeMouseButtonDown = 2; 467706f2543Smrg DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse2Mask); 468706f2543Smrg } else if (darwin_all_modifier_flags & darwinFakeMouse3Mask) { 469706f2543Smrg ev_button = 3; 470706f2543Smrg darwinFakeMouseButtonDown = 3; 471706f2543Smrg DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse3Mask); 472706f2543Smrg } 473706f2543Smrg } 474706f2543Smrg 475706f2543Smrg if (ev_type == ButtonRelease && ev_button == 1) { 476706f2543Smrg if(darwinFakeMouseButtonDown) { 477706f2543Smrg ev_button = darwinFakeMouseButtonDown; 478706f2543Smrg } 479706f2543Smrg 480706f2543Smrg if(darwinFakeMouseButtonDown == 2) { 481706f2543Smrg DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse2Mask); 482706f2543Smrg } else if(darwinFakeMouseButtonDown == 3) { 483706f2543Smrg DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse3Mask); 484706f2543Smrg } 485706f2543Smrg 486706f2543Smrg darwinFakeMouseButtonDown = 0; 487706f2543Smrg } 488706f2543Smrg 489706f2543Smrg DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, pressure, tilt_x, tilt_y); 490706f2543Smrg darwinEvents_lock(); { 491706f2543Smrg ValuatorMask mask; 492706f2543Smrg valuator_mask_set_range(&mask, 0, (pDev == darwinTabletCurrent) ? 5 : 2, valuators); 493706f2543Smrg num_events = GetPointerEvents(darwinEvents, pDev, ev_type, ev_button, 494706f2543Smrg POINTER_ABSOLUTE, &mask); 495706f2543Smrg for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event); 496706f2543Smrg if(num_events > 0) DarwinPokeEQ(); 497706f2543Smrg } darwinEvents_unlock(); 498706f2543Smrg} 499706f2543Smrg 500706f2543Smrgvoid DarwinSendKeyboardEvents(int ev_type, int keycode) { 501706f2543Smrg int i, num_events; 502706f2543Smrg 503706f2543Smrg if(!darwinEvents) { 504706f2543Smrg DEBUG_LOG("DarwinSendKeyboardEvents called before darwinEvents was initialized\n"); 505706f2543Smrg return; 506706f2543Smrg } 507706f2543Smrg 508706f2543Smrg darwinEvents_lock(); { 509706f2543Smrg num_events = GetKeyboardEvents(darwinEvents, darwinKeyboard, ev_type, keycode + MIN_KEYCODE); 510706f2543Smrg for(i=0; i<num_events; i++) mieqEnqueue(darwinKeyboard, (InternalEvent*)darwinEvents[i].event); 511706f2543Smrg if(num_events > 0) DarwinPokeEQ(); 512706f2543Smrg } darwinEvents_unlock(); 513706f2543Smrg} 514706f2543Smrg 515706f2543Smrgvoid DarwinSendProximityEvents(int ev_type, float pointer_x, float pointer_y) { 516706f2543Smrg int i, num_events; 517706f2543Smrg ScreenPtr screen; 518706f2543Smrg DeviceIntPtr pDev = darwinTabletCurrent; 519706f2543Smrg int valuators[5]; 520706f2543Smrg 521706f2543Smrg DEBUG_LOG("DarwinSendProximityEvents(%d, %f, %f)\n", ev_type, pointer_x, pointer_y); 522706f2543Smrg 523706f2543Smrg if(!darwinEvents) { 524706f2543Smrg DEBUG_LOG("DarwinSendProximityEvents called before darwinEvents was initialized\n"); 525706f2543Smrg return; 526706f2543Smrg } 527706f2543Smrg 528706f2543Smrg screen = miPointerGetScreen(pDev); 529706f2543Smrg if(!screen) { 530706f2543Smrg DEBUG_LOG("DarwinSendPointerEvents called before screen was initialized\n"); 531706f2543Smrg return; 532706f2543Smrg } 533706f2543Smrg 534706f2543Smrg DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, 0.0f, 0.0f, 0.0f); 535706f2543Smrg darwinEvents_lock(); { 536706f2543Smrg ValuatorMask mask; 537706f2543Smrg valuator_mask_set_range(&mask, 0, 5, valuators); 538706f2543Smrg num_events = GetProximityEvents(darwinEvents, pDev, ev_type, &mask); 539706f2543Smrg for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event); 540706f2543Smrg if(num_events > 0) DarwinPokeEQ(); 541706f2543Smrg } darwinEvents_unlock(); 542706f2543Smrg} 543706f2543Smrg 544706f2543Smrg 545706f2543Smrg/* Send the appropriate number of button clicks to emulate scroll wheel */ 546706f2543Smrgvoid DarwinSendScrollEvents(float count_x, float count_y, 547706f2543Smrg float pointer_x, float pointer_y, 548706f2543Smrg float pressure, float tilt_x, float tilt_y) { 549706f2543Smrg int sign_x, sign_y; 550706f2543Smrg if(!darwinEvents) { 551706f2543Smrg DEBUG_LOG("DarwinSendScrollEvents called before darwinEvents was initialized\n"); 552706f2543Smrg return; 553706f2543Smrg } 554706f2543Smrg 555706f2543Smrg sign_x = count_x > 0.0f ? SCROLLWHEELLEFTFAKE : SCROLLWHEELRIGHTFAKE; 556706f2543Smrg sign_y = count_y > 0.0f ? SCROLLWHEELUPFAKE : SCROLLWHEELDOWNFAKE; 557706f2543Smrg count_x = fabs(count_x); 558706f2543Smrg count_y = fabs(count_y); 559706f2543Smrg 560706f2543Smrg while ((count_x > 0.0f) || (count_y > 0.0f)) { 561706f2543Smrg if (count_x > 0.0f) { 562706f2543Smrg DarwinSendPointerEvents(darwinPointer, ButtonPress, sign_x, pointer_x, pointer_y, pressure, tilt_x, tilt_y); 563706f2543Smrg DarwinSendPointerEvents(darwinPointer, ButtonRelease, sign_x, pointer_x, pointer_y, pressure, tilt_x, tilt_y); 564706f2543Smrg count_x = count_x - 1.0f; 565706f2543Smrg } 566706f2543Smrg if (count_y > 0.0f) { 567706f2543Smrg DarwinSendPointerEvents(darwinPointer, ButtonPress, sign_y, pointer_x, pointer_y, pressure, tilt_x, tilt_y); 568706f2543Smrg DarwinSendPointerEvents(darwinPointer, ButtonRelease, sign_y, pointer_x, pointer_y, pressure, tilt_x, tilt_y); 569706f2543Smrg count_y = count_y - 1.0f; 570706f2543Smrg } 571706f2543Smrg } 572706f2543Smrg} 573706f2543Smrg 574706f2543Smrg/* Send the appropriate KeyPress/KeyRelease events to GetKeyboardEvents to 575706f2543Smrg reflect changing modifier flags (alt, control, meta, etc) */ 576706f2543Smrgvoid DarwinUpdateModKeys(int flags) { 577706f2543Smrg DarwinUpdateModifiers(KeyRelease, darwin_all_modifier_flags & ~flags & darwin_x11_modifier_mask); 578706f2543Smrg DarwinUpdateModifiers(KeyPress, ~darwin_all_modifier_flags & flags & darwin_x11_modifier_mask); 579706f2543Smrg darwin_all_modifier_flags = flags; 580706f2543Smrg} 581706f2543Smrg 582706f2543Smrg/* 583706f2543Smrg * DarwinSendDDXEvent 584706f2543Smrg * Send the X server thread a message by placing it on the event queue. 585706f2543Smrg */ 586706f2543Smrgvoid DarwinSendDDXEvent(int type, int argc, ...) { 587706f2543Smrg XQuartzEvent e; 588706f2543Smrg int i; 589706f2543Smrg va_list args; 590706f2543Smrg 591706f2543Smrg memset(&e, 0, sizeof(e)); 592706f2543Smrg e.header = ET_Internal; 593706f2543Smrg e.type = ET_XQuartz; 594706f2543Smrg e.length = sizeof(e); 595706f2543Smrg e.time = GetTimeInMillis(); 596706f2543Smrg e.subtype = type; 597706f2543Smrg 598706f2543Smrg if (argc > 0 && argc < XQUARTZ_EVENT_MAXARGS) { 599706f2543Smrg va_start (args, argc); 600706f2543Smrg for (i = 0; i < argc; i++) 601706f2543Smrg e.data[i] = (uint32_t) va_arg (args, uint32_t); 602706f2543Smrg va_end (args); 603706f2543Smrg } 604706f2543Smrg 605706f2543Smrg darwinEvents_lock(); { 606706f2543Smrg mieqEnqueue(NULL, (InternalEvent*)&e); 607706f2543Smrg DarwinPokeEQ(); 608706f2543Smrg } darwinEvents_unlock(); 609706f2543Smrg} 610