4 Mac OS X OpenGL and input module, using Carbon and AGL
6 Copyright (C) 2005-2006 Mathieu Olivier
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <OpenGL/OpenGL.h>
28 #include <Carbon/Carbon.h>
29 #include <IOKit/hidsystem/IOHIDLib.h>
30 #include <IOKit/hidsystem/event_status_driver.h>
31 #include "vid_agl_mackeys.h" // this is SDL/src/video/maccommon/SDL_mackeys.h
34 #ifndef kCGLCEMPEngine
35 #define kCGLCEMPEngine 313
38 // Tell startup code that we have a client
39 int cl_available = true;
41 qboolean vid_supportrefreshrate = true;
44 AGLPixelFormat (*qaglChoosePixelFormat) (const AGLDevice *gdevs, GLint ndev, const GLint *attribList);
45 AGLContext (*qaglCreateContext) (AGLPixelFormat pix, AGLContext share);
46 GLboolean (*qaglDestroyContext) (AGLContext ctx);
47 void (*qaglDestroyPixelFormat) (AGLPixelFormat pix);
48 const GLubyte* (*qaglErrorString) (GLenum code);
49 GLenum (*qaglGetError) (void);
50 GLboolean (*qaglSetCurrentContext) (AGLContext ctx);
51 GLboolean (*qaglSetDrawable) (AGLContext ctx, AGLDrawable draw);
52 GLboolean (*qaglSetFullScreen) (AGLContext ctx, GLsizei width, GLsizei height, GLsizei freq, GLint device);
53 GLboolean (*qaglSetInteger) (AGLContext ctx, GLenum pname, const GLint *params);
54 void (*qaglSwapBuffers) (AGLContext ctx);
55 CGLError (*qCGLEnable) (CGLContextObj ctx, CGLContextEnable pname);
56 CGLError (*qCGLDisable) (CGLContextObj ctx, CGLContextEnable pname);
57 CGLContextObj (*qCGLGetCurrentContext) (void);
59 static qboolean multithreadedgl;
60 static qboolean mouse_avail = true;
61 static qboolean vid_usingmouse = false;
62 static float mouse_x, mouse_y;
64 static qboolean vid_isfullscreen = false;
65 static qboolean vid_usingvsync = false;
67 static qboolean sound_active = true;
69 static int scr_width, scr_height;
71 static cvar_t apple_multithreadedgl = {CVAR_SAVE, "apple_multithreadedgl", "1", "makes use of a second thread for the OpenGL driver (if possible) rather than using the engine thread (note: this is done automatically on most other operating systems)"};
72 static cvar_t apple_mouse_noaccel = {CVAR_SAVE, "apple_mouse_noaccel", "1", "disables mouse acceleration while DarkPlaces is active"};
74 static AGLContext context;
75 static WindowRef window;
77 static double originalMouseSpeed = 0.0;
79 void VID_GetWindowSize (int *x, int *y, int *width, int *height)
86 static void IN_Activate( qboolean grab )
90 if (!vid_usingmouse && mouse_avail && window)
96 CGDisplayHideCursor(CGMainDisplayID());
98 // Put the mouse cursor at the center of the window
99 GetWindowBounds (window, kWindowContentRgn, &winBounds);
100 winCenter.x = (winBounds.left + winBounds.right) / 2;
101 winCenter.y = (winBounds.top + winBounds.bottom) / 2;
102 CGWarpMouseCursorPosition(winCenter);
104 // Lock the mouse pointer at its current position
105 CGAssociateMouseAndMouseCursorPosition(false);
107 // Save the status of mouse acceleration
108 originalMouseSpeed = 0.0; // in case of error
109 if(apple_mouse_noaccel.integer)
111 NXEventHandle mouseDev = NXOpenEventStatus();
114 if(IOHIDGetMouseAcceleration((io_connect_t) mouseDev, &originalMouseSpeed) == kIOReturnSuccess)
116 if(IOHIDSetMouseAcceleration((io_connect_t) mouseDev, 0.0) != kIOReturnSuccess)
118 Con_Print("Could not disable mouse acceleration (failed at IOHIDSetMouseAcceleration).\n");
119 Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
124 Con_Print("Could not disable mouse acceleration (failed at IOHIDGetMouseAcceleration).\n");
125 Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
127 NXCloseEventStatus(mouseDev);
131 Con_Print("Could not disable mouse acceleration (failed at NXOpenEventStatus).\n");
132 Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
136 mouse_x = mouse_y = 0;
137 vid_usingmouse = true;
144 if(originalMouseSpeed != 0.0)
146 NXEventHandle mouseDev = NXOpenEventStatus();
149 if(IOHIDSetMouseAcceleration((io_connect_t) mouseDev, originalMouseSpeed) != kIOReturnSuccess)
150 Con_Print("Could not re-enable mouse acceleration (failed at IOHIDSetMouseAcceleration).\n");
151 NXCloseEventStatus(mouseDev);
154 Con_Print("Could not re-enable mouse acceleration (failed at NXOpenEventStatus).\n");
157 CGAssociateMouseAndMouseCursorPosition(true);
158 CGDisplayShowCursor(CGMainDisplayID());
160 vid_usingmouse = false;
165 #define GAMMA_TABLE_SIZE 256
166 void VID_Finish (qboolean allowmousegrab)
168 qboolean vid_usemouse;
169 qboolean vid_usevsync;
171 // handle the mouse state when windowed if that's changed
172 vid_usemouse = false;
173 if (allowmousegrab && vid_mouse.integer && !key_consoleactive && (key_dest != key_game || !cls.demoplayback))
175 if (!vid_activewindow)
176 vid_usemouse = false;
177 if (vid_isfullscreen)
179 IN_Activate(vid_usemouse);
181 // handle changes of the vsync option
182 vid_usevsync = (vid_vsync.integer && !cls.timedemo);
183 if (vid_usingvsync != vid_usevsync)
185 GLint sync = (vid_usevsync ? 1 : 0);
187 if (qaglSetInteger(context, AGL_SWAP_INTERVAL, &sync) == GL_TRUE)
189 vid_usingvsync = vid_usevsync;
190 Con_DPrintf("Vsync %s\n", vid_usevsync ? "activated" : "deactivated");
193 Con_Printf("ERROR: can't %s vsync\n", vid_usevsync ? "activate" : "deactivate");
196 if (r_render.integer)
199 if (r_speeds.integer || gl_finish.integer)
201 qglFinish();CHECKGLERROR
203 qaglSwapBuffers(context);
205 VID_UpdateGamma(false, GAMMA_TABLE_SIZE);
207 if (apple_multithreadedgl.integer)
209 if (!multithreadedgl)
211 if(qCGLGetCurrentContext && qCGLEnable && qCGLDisable)
213 CGLContextObj ctx = qCGLGetCurrentContext();
214 CGLError e = qCGLEnable(ctx, kCGLCEMPEngine);
216 multithreadedgl = true;
219 Con_Printf("WARNING: can't enable multithreaded GL, error %d\n", (int) e);
220 Cvar_SetValueQuick(&apple_multithreadedgl, 0);
225 Con_Printf("WARNING: can't enable multithreaded GL, CGL functions not present\n");
226 Cvar_SetValueQuick(&apple_multithreadedgl, 0);
234 if(qCGLGetCurrentContext && qCGLEnable && qCGLDisable)
236 CGLContextObj ctx = qCGLGetCurrentContext();
237 qCGLDisable(ctx, kCGLCEMPEngine);
238 multithreadedgl = false;
244 int VID_SetGamma(unsigned short *ramps, int rampsize)
246 CGGammaValue table_red [GAMMA_TABLE_SIZE];
247 CGGammaValue table_green [GAMMA_TABLE_SIZE];
248 CGGammaValue table_blue [GAMMA_TABLE_SIZE];
251 // Convert the unsigned short table into 3 float tables
252 for (i = 0; i < rampsize; i++)
253 table_red[i] = (float)ramps[i] / 65535.0f;
254 for (i = 0; i < rampsize; i++)
255 table_green[i] = (float)ramps[i + rampsize] / 65535.0f;
256 for (i = 0; i < rampsize; i++)
257 table_blue[i] = (float)ramps[i + 2 * rampsize] / 65535.0f;
259 if (CGSetDisplayTransferByTable(CGMainDisplayID(), rampsize, table_red, table_green, table_blue) != CGDisplayNoErr)
261 Con_Print("VID_SetGamma: ERROR: CGSetDisplayTransferByTable failed!\n");
268 int VID_GetGamma(unsigned short *ramps, int rampsize)
270 CGGammaValue table_red [GAMMA_TABLE_SIZE];
271 CGGammaValue table_green [GAMMA_TABLE_SIZE];
272 CGGammaValue table_blue [GAMMA_TABLE_SIZE];
273 CGTableCount actualsize = 0;
276 // Get the gamma ramps from the system
277 if (CGGetDisplayTransferByTable(CGMainDisplayID(), rampsize, table_red, table_green, table_blue, &actualsize) != CGDisplayNoErr)
279 Con_Print("VID_GetGamma: ERROR: CGGetDisplayTransferByTable failed!\n");
282 if (actualsize != (unsigned int)rampsize)
284 Con_Printf("VID_GetGamma: ERROR: invalid gamma table size (%u != %u)\n", actualsize, rampsize);
288 // Convert the 3 float tables into 1 unsigned short table
289 for (i = 0; i < rampsize; i++)
290 ramps[i] = table_red[i] * 65535.0f;
291 for (i = 0; i < rampsize; i++)
292 ramps[i + rampsize] = table_green[i] * 65535.0f;
293 for (i = 0; i < rampsize; i++)
294 ramps[i + 2 * rampsize] = table_blue[i] * 65535.0f;
299 void signal_handler(int sig)
301 printf("Received signal %d, exiting...\n", sig);
302 VID_RestoreSystemGamma();
308 signal(SIGHUP, signal_handler);
309 signal(SIGINT, signal_handler);
310 signal(SIGQUIT, signal_handler);
311 signal(SIGILL, signal_handler);
312 signal(SIGTRAP, signal_handler);
313 signal(SIGIOT, signal_handler);
314 signal(SIGBUS, signal_handler);
315 signal(SIGFPE, signal_handler);
316 signal(SIGSEGV, signal_handler);
317 signal(SIGTERM, signal_handler);
322 InitSig(); // trap evil signals
323 Cvar_RegisterVariable(&apple_multithreadedgl);
324 Cvar_RegisterVariable(&apple_mouse_noaccel);
325 // COMMANDLINEOPTION: Input: -nomouse disables mouse support (see also vid_mouse cvar)
326 if (COM_CheckParm ("-nomouse"))
330 static void *prjobj = NULL;
331 static void *cglobj = NULL;
333 static void GL_CloseLibrary(void)
344 gl_platformextensions = "";
347 static int GL_OpenLibrary(void)
349 const char *name = "/System/Library/Frameworks/AGL.framework/AGL";
350 const char *name2 = "/System/Library/Frameworks/OpenGL.framework/OpenGL";
352 Con_Printf("Loading OpenGL driver %s\n", name);
354 if (!(prjobj = dlopen(name, RTLD_LAZY)))
356 Con_Printf("Unable to open symbol list for %s\n", name);
359 strlcpy(gl_driver, name, sizeof(gl_driver));
361 Con_Printf("Loading OpenGL driver %s\n", name2);
362 if (!(cglobj = dlopen(name2, RTLD_LAZY)))
363 Con_Printf("Unable to open symbol list for %s; multithreaded GL disabled\n", name);
368 void *GL_GetProcAddress(const char *name)
370 return dlsym(prjobj, name);
373 static void *CGL_GetProcAddress(const char *name)
377 return dlsym(cglobj, name);
380 void VID_Shutdown(void)
382 if (context == NULL && window == NULL)
386 VID_RestoreSystemGamma();
390 qaglDestroyContext(context);
394 if (vid_isfullscreen)
395 CGReleaseAllDisplays();
399 DisposeWindow(window);
404 vid_isfullscreen = false;
410 // Since the event handler can be called at any time, we store the events for later processing
411 static qboolean AsyncEvent_Quitting = false;
412 static qboolean AsyncEvent_Collapsed = false;
413 static OSStatus MainWindowEventHandler (EventHandlerCallRef nextHandler, EventRef event, void *userData)
415 OSStatus err = noErr;
417 switch (GetEventKind (event))
419 case kEventWindowClosed:
420 AsyncEvent_Quitting = true;
424 case kEventWindowCollapsing:
425 AsyncEvent_Collapsed = true;
428 // Undocked / restored (end)
429 case kEventWindowExpanded:
430 AsyncEvent_Collapsed = false;
434 err = eventNotHandledErr;
441 static void VID_AppFocusChanged(qboolean windowIsActive)
443 if (vid_activewindow != windowIsActive)
445 vid_activewindow = windowIsActive;
446 if (!vid_activewindow)
447 VID_RestoreSystemGamma();
450 if (sound_active != windowIsActive)
452 sound_active = windowIsActive;
460 static void VID_ProcessPendingAsyncEvents (void)
462 // Collapsed / expanded
463 if (AsyncEvent_Collapsed != vid_hidden)
465 vid_hidden = !vid_hidden;
466 VID_AppFocusChanged(!vid_hidden);
470 if (AsyncEvent_Quitting)
474 static void VID_BuildAGLAttrib(GLint *attrib, qboolean stencil, qboolean fullscreen, qboolean stereobuffer)
476 *attrib++ = AGL_RGBA;
477 *attrib++ = AGL_RED_SIZE;*attrib++ = 1;
478 *attrib++ = AGL_GREEN_SIZE;*attrib++ = 1;
479 *attrib++ = AGL_BLUE_SIZE;*attrib++ = 1;
480 *attrib++ = AGL_DOUBLEBUFFER;
481 *attrib++ = AGL_DEPTH_SIZE;*attrib++ = 1;
483 // if stencil is enabled, ask for alpha too
486 *attrib++ = AGL_STENCIL_SIZE;*attrib++ = 8;
487 *attrib++ = AGL_ALPHA_SIZE;*attrib++ = 1;
490 *attrib++ = AGL_FULLSCREEN;
492 *attrib++ = AGL_STEREO;
493 *attrib++ = AGL_NONE;
496 int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer)
498 const EventTypeSpec winEvents[] =
500 { kEventClassWindow, kEventWindowClosed },
501 { kEventClassWindow, kEventWindowCollapsing },
502 { kEventClassWindow, kEventWindowExpanded },
504 OSStatus carbonError;
506 CFStringRef windowTitle;
507 AGLPixelFormat pixelFormat;
508 GLint attributes [32];
511 if (!GL_OpenLibrary())
513 Con_Printf("Unable to load GL driver\n");
517 if ((qaglChoosePixelFormat = (AGLPixelFormat (*) (const AGLDevice *gdevs, GLint ndev, const GLint *attribList))GL_GetProcAddress("aglChoosePixelFormat")) == NULL
518 || (qaglCreateContext = (AGLContext (*) (AGLPixelFormat pix, AGLContext share))GL_GetProcAddress("aglCreateContext")) == NULL
519 || (qaglDestroyContext = (GLboolean (*) (AGLContext ctx))GL_GetProcAddress("aglDestroyContext")) == NULL
520 || (qaglDestroyPixelFormat = (void (*) (AGLPixelFormat pix))GL_GetProcAddress("aglDestroyPixelFormat")) == NULL
521 || (qaglErrorString = (const GLubyte* (*) (GLenum code))GL_GetProcAddress("aglErrorString")) == NULL
522 || (qaglGetError = (GLenum (*) (void))GL_GetProcAddress("aglGetError")) == NULL
523 || (qaglSetCurrentContext = (GLboolean (*) (AGLContext ctx))GL_GetProcAddress("aglSetCurrentContext")) == NULL
524 || (qaglSetDrawable = (GLboolean (*) (AGLContext ctx, AGLDrawable draw))GL_GetProcAddress("aglSetDrawable")) == NULL
525 || (qaglSetFullScreen = (GLboolean (*) (AGLContext ctx, GLsizei width, GLsizei height, GLsizei freq, GLint device))GL_GetProcAddress("aglSetFullScreen")) == NULL
526 || (qaglSetInteger = (GLboolean (*) (AGLContext ctx, GLenum pname, const GLint *params))GL_GetProcAddress("aglSetInteger")) == NULL
527 || (qaglSwapBuffers = (void (*) (AGLContext ctx))GL_GetProcAddress("aglSwapBuffers")) == NULL
530 Con_Printf("AGL functions not found\n");
531 ReleaseWindow(window);
535 qCGLEnable = (CGLError (*) (CGLContextObj ctx, CGLContextEnable pname)) CGL_GetProcAddress("CGLEnable");
536 qCGLDisable = (CGLError (*) (CGLContextObj ctx, CGLContextEnable pname)) CGL_GetProcAddress("CGLDisable");
537 qCGLGetCurrentContext = (CGLContextObj (*) (void)) CGL_GetProcAddress("CGLGetCurrentContext");
538 if(!qCGLEnable || !qCGLDisable || !qCGLGetCurrentContext)
539 Con_Printf("CGL functions not found; disabling multithreaded OpenGL\n");
541 // Ignore the events from the previous window
542 AsyncEvent_Quitting = false;
543 AsyncEvent_Collapsed = false;
545 // Create the window, a bit towards the center of the screen
546 windowBounds.left = 100;
547 windowBounds.top = 100;
548 windowBounds.right = width + 100;
549 windowBounds.bottom = height + 100;
550 carbonError = CreateNewWindow(kDocumentWindowClass, kWindowStandardFloatingAttributes | kWindowStandardHandlerAttribute, &windowBounds, &window);
551 if (carbonError != noErr || window == NULL)
553 Con_Printf("Unable to create window (error %u)\n", (unsigned)carbonError);
557 // Set the window title
558 windowTitle = CFSTR("DarkPlaces AGL");
559 SetWindowTitleWithCFString(window, windowTitle);
561 // Install the callback function for the window events we can't get
562 // through ReceiveNextEvent (i.e. close, collapse, and expand)
563 InstallWindowEventHandler (window, NewEventHandlerUPP (MainWindowEventHandler),
564 GetEventTypeCount(winEvents), winEvents, window, NULL);
566 // Create the desired attribute list
567 VID_BuildAGLAttrib(attributes, bpp == 32, fullscreen, stereobuffer);
572 pixelFormat = qaglChoosePixelFormat(NULL, 0, attributes);
573 error = qaglGetError();
574 if (error != AGL_NO_ERROR)
576 Con_Printf("qaglChoosePixelFormat FAILED: %s\n",
577 (char *)qaglErrorString(error));
578 ReleaseWindow(window);
582 else // Output is fullScreen
584 CGDirectDisplayID mainDisplay;
585 CFDictionaryRef refDisplayMode;
588 // Get the mainDisplay and set resolution to current
589 mainDisplay = CGMainDisplayID();
590 CGDisplayCapture(mainDisplay);
592 // TOCHECK: not sure whether or not it's necessary to change the resolution
593 // "by hand", or if aglSetFullscreen does the job anyway
594 refDisplayMode = CGDisplayBestModeForParametersAndRefreshRate(mainDisplay, bpp, width, height, refreshrate, NULL);
595 CGDisplaySwitchToMode(mainDisplay, refDisplayMode);
596 DMGetGDeviceByDisplayID((DisplayIDType)mainDisplay, &gdhDisplay, false);
598 // Set pixel format with built attribs
599 // Note: specifying a device is *required* for AGL_FullScreen
600 pixelFormat = qaglChoosePixelFormat(&gdhDisplay, 1, attributes);
601 error = qaglGetError();
602 if (error != AGL_NO_ERROR)
604 Con_Printf("qaglChoosePixelFormat FAILED: %s\n",
605 (char *)qaglErrorString(error));
606 ReleaseWindow(window);
611 // Create a context using the pform
612 context = qaglCreateContext(pixelFormat, NULL);
613 error = qaglGetError();
614 if (error != AGL_NO_ERROR)
616 Con_Printf("qaglCreateContext FAILED: %s\n",
617 (char *)qaglErrorString(error));
620 // Make the context the current one ('enable' it)
621 qaglSetCurrentContext(context);
622 error = qaglGetError();
623 if (error != AGL_NO_ERROR)
625 Con_Printf("qaglSetCurrentContext FAILED: %s\n",
626 (char *)qaglErrorString(error));
627 ReleaseWindow(window);
632 qaglDestroyPixelFormat(pixelFormat);
634 // Attempt fullscreen if requested
637 qaglSetFullScreen (context, width, height, refreshrate, 0);
638 error = qaglGetError();
639 if (error != AGL_NO_ERROR)
641 Con_Printf("qaglSetFullScreen FAILED: %s\n",
642 (char *)qaglErrorString(error));
648 // Set Window as Drawable
649 qaglSetDrawable(context, GetWindowPort(window));
650 error = qaglGetError();
651 if (error != AGL_NO_ERROR)
653 Con_Printf("qaglSetDrawable FAILED: %s\n",
654 (char *)qaglErrorString(error));
655 ReleaseWindow(window);
663 if ((qglGetString = (const GLubyte* (GLAPIENTRY *)(GLenum name))GL_GetProcAddress("glGetString")) == NULL)
664 Sys_Error("glGetString not found in %s", gl_driver);
666 gl_renderer = (const char *)qglGetString(GL_RENDERER);
667 gl_vendor = (const char *)qglGetString(GL_VENDOR);
668 gl_version = (const char *)qglGetString(GL_VERSION);
669 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
671 gl_videosyncavailable = true;
673 multithreadedgl = false;
674 vid_isfullscreen = fullscreen;
675 vid_usingmouse = false;
677 vid_activewindow = true;
681 SelectWindow(window);
687 static void Handle_KeyMod(UInt32 keymod)
689 const struct keymod_to_event_s { UInt32 keybit; keynum_t event; } keymod_events [] =
692 { shiftKey, K_SHIFT },
693 { alphaLock, K_CAPSLOCK },
694 { optionKey, K_ALT },
695 { controlKey, K_CTRL },
696 { kEventKeyModifierNumLockMask, K_NUMLOCK },
697 { kEventKeyModifierFnMask, K_AUX2 }
699 static UInt32 prev_keymod = 0;
703 modChanges = prev_keymod ^ keymod;
707 for (i = 0; i < sizeof(keymod_events) / sizeof(keymod_events[0]); i++)
709 UInt32 keybit = keymod_events[i].keybit;
711 if ((modChanges & keybit) != 0)
712 Key_Event(keymod_events[i].event, '\0', (keymod & keybit) != 0);
715 prev_keymod = keymod;
718 static void Handle_Key(unsigned char charcode, UInt32 mackeycode, qboolean keypressed)
720 unsigned int keycode = 0;
765 keycode = K_SCROLLOCK;
771 keycode = K_BACKSPACE;
786 keycode = K_KP_EQUALS;
789 keycode = K_KP_DIVIDE;
792 keycode = K_KP_MULTIPLY;
816 keycode = K_KP_MINUS;
819 keycode = K_CAPSLOCK;
847 keycode = K_KP_ENTER;
853 keycode = K_KP_PERIOD;
858 case kUpArrowCharCode:
861 case kLeftArrowCharCode:
862 keycode = K_LEFTARROW;
864 case kDownArrowCharCode:
865 keycode = K_DOWNARROW;
867 case kRightArrowCharCode:
868 keycode = K_RIGHTARROW;
872 // characters 0 and 191 are sent by the mouse buttons (?!)
875 if ('A' <= charcode && charcode <= 'Z')
877 keycode = charcode + ('a' - 'A'); // lowercase it
880 else if (charcode >= 32)
886 Con_Printf(">> UNKNOWN char/keycode: %d/%u <<\n", charcode, (unsigned) mackeycode);
891 Key_Event(keycode, ascii, keypressed);
894 void Sys_SendKeyEvents(void)
897 EventTargetRef theTarget;
899 // Start by processing the asynchronous events we received since the previous frame
900 VID_ProcessPendingAsyncEvents();
902 theTarget = GetEventDispatcherTarget();
903 while (ReceiveNextEvent(0, NULL, kEventDurationNoWait, true, &theEvent) == noErr)
905 UInt32 eventClass = GetEventClass(theEvent);
906 UInt32 eventKind = GetEventKind(theEvent);
910 case kEventClassMouse:
912 EventMouseButton theButton;
917 case kEventMouseDown:
919 GetEventParameter(theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(theButton), NULL, &theButton);
923 case kEventMouseButtonPrimary:
926 case kEventMouseButtonSecondary:
929 case kEventMouseButtonTertiary:
933 Key_Event(key, '\0', eventKind == kEventMouseDown);
936 // Note: These two events are mutual exclusives
937 // Treat MouseDragged in the same statement, so we don't block MouseMoved while a mousebutton is held
938 case kEventMouseMoved:
939 case kEventMouseDragged:
943 GetEventParameter(theEvent, kEventParamMouseDelta, typeHIPoint, NULL, sizeof(deltaPos), NULL, &deltaPos);
945 mouse_x += deltaPos.x;
946 mouse_y += deltaPos.y;
950 case kEventMouseWheelMoved:
953 unsigned int wheelEvent;
955 GetEventParameter(theEvent, kEventParamMouseWheelDelta, typeSInt32, NULL, sizeof(delta), NULL, &delta);
957 wheelEvent = (delta > 0) ? K_MWHEELUP : K_MWHEELDOWN;
958 Key_Event(wheelEvent, 0, true);
959 Key_Event(wheelEvent, 0, false);
964 Con_Printf (">> kEventClassMouse (UNKNOWN eventKind: %u) <<\n", (unsigned)eventKind);
969 case kEventClassKeyboard:
976 case kEventRawKeyDown:
977 GetEventParameter(theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(charcode), NULL, &charcode);
978 GetEventParameter(theEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(keycode), NULL, &keycode);
979 Handle_Key(charcode, keycode, true);
982 case kEventRawKeyRepeat:
986 GetEventParameter(theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(charcode), NULL, &charcode);
987 GetEventParameter(theEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(keycode), NULL, &keycode);
988 Handle_Key(charcode, keycode, false);
991 case kEventRawKeyModifiersChanged:
994 GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(keymod), NULL, &keymod);
995 Handle_KeyMod(keymod);
999 case kEventHotKeyPressed:
1002 case kEventHotKeyReleased:
1005 case kEventMouseWheelMoved:
1009 Con_Printf (">> kEventClassKeyboard (UNKNOWN eventKind: %u) <<\n", (unsigned)eventKind);
1015 case kEventClassTextInput:
1016 Con_Printf(">> kEventClassTextInput (%d) <<\n", (int)eventKind);
1019 case kEventClassApplication:
1022 case kEventAppActivated :
1023 VID_AppFocusChanged(true);
1025 case kEventAppDeactivated:
1026 VID_AppFocusChanged(false);
1031 case kEventAppActiveWindowChanged:
1034 Con_Printf(">> kEventClassApplication (UNKNOWN eventKind: %u) <<\n", (unsigned)eventKind);
1039 case kEventClassAppleEvent:
1042 case kEventAppleEvent :
1045 Con_Printf(">> kEventClassAppleEvent (UNKNOWN eventKind: %u) <<\n", (unsigned)eventKind);
1050 case kEventClassWindow:
1053 case kEventWindowUpdate :
1056 Con_Printf(">> kEventClassWindow (UNKNOWN eventKind: %u) <<\n", (unsigned)eventKind);
1061 case kEventClassControl:
1065 /*Con_Printf(">> UNKNOWN eventClass: %c%c%c%c, eventKind: %d <<\n",
1066 eventClass >> 24, (eventClass >> 16) & 0xFF,
1067 (eventClass >> 8) & 0xFF, eventClass & 0xFF,
1072 SendEventToEventTarget (theEvent, theTarget);
1073 ReleaseEvent(theEvent);
1081 in_mouse_x = mouse_x;
1082 in_mouse_y = mouse_y;