1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2012 Sam Lantinga 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Library General Public 7 License as published by the Free Software Foundation; either 8 version 2 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Library General Public License for more details. 14 15 You should have received a copy of the GNU Library General Public 16 License along with this library; if not, write to the Free 17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 19 Sam Lantinga 20 slouken@libsdl.org 21 */ 22 #include "SDL_config.h" 23 24 /* 25 @file SDL_QuartzVideo.h 26 @author Darrell Walisser, Max Horn, et al. 27 28 @abstract SDL video driver for Mac OS X. 29 30 @discussion 31 32 TODO 33 - Hardware Cursor support with NSCursor instead of Carbon 34 - Keyboard repeat/mouse speed adjust (if needed) 35 - Multiple monitor support (currently only main display) 36 - Accelerated blitting support 37 - Fix white OpenGL window on minimize (fixed) (update: broken again on 10.2) 38 - Find out what events should be sent/ignored if window is minimized 39 - Find a way to deal with external resolution/depth switch while app is running 40 - Check accuracy of QZ_SetGamma() 41 Problems: 42 - OGL not working in full screen with software renderer 43 - SetColors sets palette correctly but clears framebuffer 44 - Crash in CG after several mode switches (I think this has been fixed) 45 - Retained windows don't draw their title bar quite right (OS Bug) (not using retained windows) 46 - Cursor in 8 bit modes is screwy (might just be Radeon PCI bug) (update: not just Radeon) 47 - Warping cursor delays mouse events for a fraction of a second, 48 there is a hack around this that helps a bit 49 */ 50 51 /* Needs to be first, so QuickTime.h doesn't include glext.h (10.4) */ 52 #include "SDL_opengl.h" 53 54 #include <Cocoa/Cocoa.h> 55 #include <Carbon/Carbon.h> 56 #include <OpenGL/OpenGL.h> /* For CGL functions and types */ 57 #include <IOKit/IOKitLib.h> /* For powersave handling */ 58 #include <pthread.h> 59 60 #include "SDL_thread.h" 61 #include "SDL_video.h" 62 #include "SDL_error.h" 63 #include "SDL_timer.h" 64 #include "SDL_loadso.h" 65 #include "SDL_syswm.h" 66 #include "../SDL_sysvideo.h" 67 #include "../SDL_pixels_c.h" 68 #include "../../events/SDL_events_c.h" 69 70 71 #ifdef __powerpc__ 72 /* 73 This is a workaround to directly access NSOpenGLContext's CGL context 74 We need this to check for errors NSOpenGLContext doesn't support 75 Please note this is only used on PowerPC (Intel Macs are guaranteed to 76 have a better API for this, since it showed up in Mac OS X 10.3). 77 */ 78 @interface NSOpenGLContext (CGLContextAccess) 79 - (CGLContextObj) cglContext; 80 @end 81 #endif 82 83 /* use this to get the CGLContext; it handles Cocoa interface changes. */ 84 CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx); 85 86 87 /* Main driver structure to store required state information */ 88 typedef struct SDL_PrivateVideoData { 89 BOOL use_new_mode_apis; /* 1 == >= 10.6 APIs available */ 90 BOOL allow_screensaver; /* 0 == disable screensaver */ 91 CGDirectDisplayID display; /* 0 == main display (only support single display) */ 92 const void *mode; /* current mode of the display */ 93 const void *save_mode; /* original mode of the display */ 94 #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) 95 CGDirectPaletteRef palette; /* palette of an 8-bit display */ 96 #endif 97 NSOpenGLContext *gl_context; /* OpenGL rendering context */ 98 NSGraphicsContext *nsgfx_context; /* Cocoa graphics context */ 99 Uint32 width, height, bpp; /* frequently used data about the display */ 100 Uint32 flags; /* flags for current mode, for teardown purposes */ 101 Uint32 video_set; /* boolean; indicates if video was set correctly */ 102 Uint32 warp_flag; /* boolean; notify to event loop that a warp just occured */ 103 Uint32 warp_ticks; /* timestamp when the warp occured */ 104 NSWindow *window; /* Cocoa window to implement the SDL window */ 105 NSView *view; /* the window's view; draw 2D and OpenGL into this view */ 106 CGContextRef cg_context; /* CoreGraphics rendering context */ 107 SDL_Surface *resize_icon; /* icon for the resize badge, we have to draw it by hand */ 108 SDL_GrabMode current_grab_mode; /* default value is SDL_GRAB_OFF */ 109 SDL_Rect **client_mode_list; /* resolution list to pass back to client */ 110 SDLKey keymap[256]; /* Mac OS X to SDL key mapping */ 111 Uint32 current_mods; /* current keyboard modifiers, to track modifier state */ 112 NSText *field_edit; /* a field editor for keyboard composition processing */ 113 Uint32 last_virtual_button;/* last virtual mouse button pressed */ 114 io_connect_t power_connection; /* used with IOKit to detect wake from sleep */ 115 Uint8 expect_mouse_up; /* used to determine when to send mouse up events */ 116 Uint8 grab_state; /* used to manage grab behavior */ 117 NSPoint cursor_loc; /* saved cursor coords, for activate/deactivate when grabbed */ 118 BOOL cursor_should_be_visible; /* tells if cursor is supposed to be visible (SDL_ShowCursor) */ 119 BOOL cursor_visible; /* tells if cursor is *actually* visible or not */ 120 Uint8* sw_buffers[2]; /* pointers to the two software buffers for double-buffer emulation */ 121 SDL_Thread *thread; /* thread for async updates to the screen */ 122 SDL_sem *sem1, *sem2; /* synchronization for async screen updates */ 123 Uint8 *current_buffer; /* the buffer being copied to the screen */ 124 BOOL quit_thread; /* used to quit the async blitting thread */ 125 SInt32 system_version; /* used to dis-/enable workarounds depending on the system version */ 126 127 void *opengl_library; /* dynamically loaded OpenGL library. */ 128 } SDL_PrivateVideoData; 129 130 #define _THIS SDL_VideoDevice *this 131 #define display_id (this->hidden->display) 132 #define mode (this->hidden->mode) 133 #define save_mode (this->hidden->save_mode) 134 #define use_new_mode_apis (this->hidden->use_new_mode_apis) 135 #define allow_screensaver (this->hidden->allow_screensaver) 136 #define palette (this->hidden->palette) 137 #define gl_context (this->hidden->gl_context) 138 #define nsgfx_context (this->hidden->nsgfx_context) 139 #define device_width (this->hidden->width) 140 #define device_height (this->hidden->height) 141 #define device_bpp (this->hidden->bpp) 142 #define mode_flags (this->hidden->flags) 143 #define qz_window (this->hidden->window) 144 #define window_view (this->hidden->view) 145 #define cg_context (this->hidden->cg_context) 146 #define video_set (this->hidden->video_set) 147 #define warp_ticks (this->hidden->warp_ticks) 148 #define warp_flag (this->hidden->warp_flag) 149 #define resize_icon (this->hidden->resize_icon) 150 #define current_grab_mode (this->hidden->current_grab_mode) 151 #define client_mode_list (this->hidden->client_mode_list) 152 #define keymap (this->hidden->keymap) 153 #define current_mods (this->hidden->current_mods) 154 #define field_edit (this->hidden->field_edit) 155 #define last_virtual_button (this->hidden->last_virtual_button) 156 #define power_connection (this->hidden->power_connection) 157 #define expect_mouse_up (this->hidden->expect_mouse_up) 158 #define grab_state (this->hidden->grab_state) 159 #define cursor_loc (this->hidden->cursor_loc) 160 #define cursor_should_be_visible (this->hidden->cursor_should_be_visible) 161 #define cursor_visible (this->hidden->cursor_visible) 162 #define sw_buffers (this->hidden->sw_buffers) 163 #define sw_contexts (this->hidden->sw_contexts) 164 #define thread (this->hidden->thread) 165 #define sem1 (this->hidden->sem1) 166 #define sem2 (this->hidden->sem2) 167 #define current_buffer (this->hidden->current_buffer) 168 #define quit_thread (this->hidden->quit_thread) 169 #define system_version (this->hidden->system_version) 170 #define opengl_library (this->hidden->opengl_library) 171 172 /* grab states - the input is in one of these states */ 173 enum { 174 QZ_UNGRABBED = 0, 175 QZ_VISIBLE_GRAB, 176 QZ_INVISIBLE_GRAB 177 }; 178 179 /* grab actions - these can change the grabbed state */ 180 enum { 181 QZ_ENABLE_GRAB = 0, 182 QZ_DISABLE_GRAB, 183 QZ_HIDECURSOR, 184 QZ_SHOWCURSOR 185 }; 186 187 /* Gamma Functions */ 188 int QZ_SetGamma (_THIS, float red, float green, float blue); 189 int QZ_GetGamma (_THIS, float *red, float *green, float *blue); 190 int QZ_SetGammaRamp (_THIS, Uint16 *ramp); 191 int QZ_GetGammaRamp (_THIS, Uint16 *ramp); 192 193 /* OpenGL functions */ 194 int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags); 195 void QZ_TearDownOpenGL (_THIS); 196 void* QZ_GL_GetProcAddress (_THIS, const char *proc); 197 int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value); 198 int QZ_GL_MakeCurrent (_THIS); 199 void QZ_GL_SwapBuffers (_THIS); 200 int QZ_GL_LoadLibrary (_THIS, const char *location); 201 202 /* Cursor and Mouse functions */ 203 void QZ_FreeWMCursor (_THIS, WMcursor *cursor); 204 WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask, 205 int w, int h, int hot_x, int hot_y); 206 int QZ_ShowWMCursor (_THIS, WMcursor *cursor); 207 void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y); 208 void QZ_MoveWMCursor (_THIS, int x, int y); 209 void QZ_CheckMouseMode (_THIS); 210 void QZ_UpdateMouse (_THIS); 211 212 /* Event functions */ 213 void QZ_InitOSKeymap (_THIS); 214 void QZ_PumpEvents (_THIS); 215 216 /* Window Manager functions */ 217 void QZ_SetCaption (_THIS, const char *title, const char *icon); 218 void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask); 219 int QZ_IconifyWindow (_THIS); 220 void QZ_SetWindowPos (_THIS, int x, int y); 221 void QZ_GetWindowPos (_THIS, int *px, int *py); 222 int QZ_IsWindowVisible (_THIS, int recenter); 223 int QZ_GetMonitorDPI (_THIS, int *xDpi, int *yDpi); 224 int QZ_GetMonitorRect (_THIS, SDL_Rect *rect); 225 226 SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode); 227 /*int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info);*/ 228 229 /* Private functions (used internally) */ 230 void QZ_PrivateWarpCursor (_THIS, int x, int y); 231 void QZ_ChangeGrabState (_THIS, int action); 232 void QZ_RegisterForSleepNotifications (_THIS); 233 void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p); 234 void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p); 235 BOOL QZ_IsMouseInWindow (_THIS); 236 void QZ_DoActivate (_THIS); 237 void QZ_DoDeactivate (_THIS); 238