Home | History | Annotate | Download | only in quartz
      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 (at) 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     CGDirectPaletteRef palette;            /* palette of an 8-bit display */
     95     NSOpenGLContext    *gl_context;        /* OpenGL rendering context */
     96     NSGraphicsContext  *nsgfx_context;     /* Cocoa graphics context */
     97     Uint32             width, height, bpp; /* frequently used data about the display */
     98     Uint32             flags;              /* flags for current mode, for teardown purposes */
     99     Uint32             video_set;          /* boolean; indicates if video was set correctly */
    100     Uint32             warp_flag;          /* boolean; notify to event loop that a warp just occured */
    101     Uint32             warp_ticks;         /* timestamp when the warp occured */
    102     NSWindow           *window;            /* Cocoa window to implement the SDL window */
    103     NSView             *view;              /* the window's view; draw 2D and OpenGL into this view */
    104     CGContextRef       cg_context;         /* CoreGraphics rendering context */
    105     SDL_Surface        *resize_icon;       /* icon for the resize badge, we have to draw it by hand */
    106     SDL_GrabMode       current_grab_mode;  /* default value is SDL_GRAB_OFF */
    107     SDL_Rect           **client_mode_list; /* resolution list to pass back to client */
    108     SDLKey             keymap[256];        /* Mac OS X to SDL key mapping */
    109     Uint32             current_mods;       /* current keyboard modifiers, to track modifier state */
    110     NSText             *field_edit;        /* a field editor for keyboard composition processing */
    111     Uint32             last_virtual_button;/* last virtual mouse button pressed */
    112     io_connect_t       power_connection;   /* used with IOKit to detect wake from sleep */
    113     Uint8              expect_mouse_up;    /* used to determine when to send mouse up events */
    114     Uint8              grab_state;         /* used to manage grab behavior */
    115     NSPoint            cursor_loc;         /* saved cursor coords, for activate/deactivate when grabbed */
    116     BOOL               cursor_should_be_visible;     /* tells if cursor is supposed to be visible (SDL_ShowCursor) */
    117     BOOL               cursor_visible;     /* tells if cursor is *actually* visible or not */
    118     Uint8*             sw_buffers[2];      /* pointers to the two software buffers for double-buffer emulation */
    119     SDL_Thread         *thread;            /* thread for async updates to the screen */
    120     SDL_sem            *sem1, *sem2;       /* synchronization for async screen updates */
    121     Uint8              *current_buffer;    /* the buffer being copied to the screen */
    122     BOOL               quit_thread;        /* used to quit the async blitting thread */
    123     SInt32             system_version;     /* used to dis-/enable workarounds depending on the system version */
    124 
    125     void *opengl_library;    /* dynamically loaded OpenGL library. */
    126 } SDL_PrivateVideoData;
    127 
    128 #define _THIS    SDL_VideoDevice *this
    129 #define display_id (this->hidden->display)
    130 #define mode (this->hidden->mode)
    131 #define save_mode (this->hidden->save_mode)
    132 #define use_new_mode_apis (this->hidden->use_new_mode_apis)
    133 #define allow_screensaver (this->hidden->allow_screensaver)
    134 #define palette (this->hidden->palette)
    135 #define gl_context (this->hidden->gl_context)
    136 #define nsgfx_context (this->hidden->nsgfx_context)
    137 #define device_width (this->hidden->width)
    138 #define device_height (this->hidden->height)
    139 #define device_bpp (this->hidden->bpp)
    140 #define mode_flags (this->hidden->flags)
    141 #define qz_window (this->hidden->window)
    142 #define window_view (this->hidden->view)
    143 #define cg_context (this->hidden->cg_context)
    144 #define video_set (this->hidden->video_set)
    145 #define warp_ticks (this->hidden->warp_ticks)
    146 #define warp_flag (this->hidden->warp_flag)
    147 #define resize_icon (this->hidden->resize_icon)
    148 #define current_grab_mode (this->hidden->current_grab_mode)
    149 #define client_mode_list (this->hidden->client_mode_list)
    150 #define keymap (this->hidden->keymap)
    151 #define current_mods (this->hidden->current_mods)
    152 #define field_edit (this->hidden->field_edit)
    153 #define last_virtual_button (this->hidden->last_virtual_button)
    154 #define power_connection (this->hidden->power_connection)
    155 #define expect_mouse_up (this->hidden->expect_mouse_up)
    156 #define grab_state (this->hidden->grab_state)
    157 #define cursor_loc (this->hidden->cursor_loc)
    158 #define cursor_should_be_visible (this->hidden->cursor_should_be_visible)
    159 #define cursor_visible (this->hidden->cursor_visible)
    160 #define sw_buffers (this->hidden->sw_buffers)
    161 #define sw_contexts (this->hidden->sw_contexts)
    162 #define thread (this->hidden->thread)
    163 #define sem1 (this->hidden->sem1)
    164 #define sem2 (this->hidden->sem2)
    165 #define current_buffer (this->hidden->current_buffer)
    166 #define quit_thread (this->hidden->quit_thread)
    167 #define system_version (this->hidden->system_version)
    168 #define opengl_library (this->hidden->opengl_library)
    169 
    170 /* grab states - the input is in one of these states */
    171 enum {
    172     QZ_UNGRABBED = 0,
    173     QZ_VISIBLE_GRAB,
    174     QZ_INVISIBLE_GRAB
    175 };
    176 
    177 /* grab actions - these can change the grabbed state */
    178 enum {
    179     QZ_ENABLE_GRAB = 0,
    180     QZ_DISABLE_GRAB,
    181     QZ_HIDECURSOR,
    182     QZ_SHOWCURSOR
    183 };
    184 
    185 /* Gamma Functions */
    186 int    QZ_SetGamma          (_THIS, float red, float green, float blue);
    187 int    QZ_GetGamma          (_THIS, float *red, float *green, float *blue);
    188 int    QZ_SetGammaRamp      (_THIS, Uint16 *ramp);
    189 int    QZ_GetGammaRamp      (_THIS, Uint16 *ramp);
    190 
    191 /* OpenGL functions */
    192 int    QZ_SetupOpenGL       (_THIS, int bpp, Uint32 flags);
    193 void   QZ_TearDownOpenGL    (_THIS);
    194 void*  QZ_GL_GetProcAddress (_THIS, const char *proc);
    195 int    QZ_GL_GetAttribute   (_THIS, SDL_GLattr attrib, int* value);
    196 int    QZ_GL_MakeCurrent    (_THIS);
    197 void   QZ_GL_SwapBuffers    (_THIS);
    198 int    QZ_GL_LoadLibrary    (_THIS, const char *location);
    199 
    200 /* Cursor and Mouse functions */
    201 void         QZ_FreeWMCursor     (_THIS, WMcursor *cursor);
    202 WMcursor*    QZ_CreateWMCursor   (_THIS, Uint8 *data, Uint8 *mask,
    203                                   int w, int h, int hot_x, int hot_y);
    204 int          QZ_ShowWMCursor     (_THIS, WMcursor *cursor);
    205 void         QZ_WarpWMCursor     (_THIS, Uint16 x, Uint16 y);
    206 void         QZ_MoveWMCursor     (_THIS, int x, int y);
    207 void         QZ_CheckMouseMode   (_THIS);
    208 void         QZ_UpdateMouse      (_THIS);
    209 
    210 /* Event functions */
    211 void         QZ_InitOSKeymap     (_THIS);
    212 void         QZ_PumpEvents       (_THIS);
    213 
    214 /* Window Manager functions */
    215 void         QZ_SetCaption       (_THIS, const char *title, const char *icon);
    216 void         QZ_SetIcon          (_THIS, SDL_Surface *icon, Uint8 *mask);
    217 int          QZ_IconifyWindow    (_THIS);
    218 void         QZ_SetWindowPos     (_THIS, int x, int y);
    219 void         QZ_GetWindowPos     (_THIS, int *px, int *py);
    220 int          QZ_IsWindowVisible  (_THIS, int recenter);
    221 int          QZ_GetMonitorDPI    (_THIS, int *xDpi, int *yDpi);
    222 int          QZ_GetMonitorRect   (_THIS, SDL_Rect *rect);
    223 
    224 SDL_GrabMode QZ_GrabInput        (_THIS, SDL_GrabMode grab_mode);
    225 /*int          QZ_GetWMInfo        (_THIS, SDL_SysWMinfo *info);*/
    226 
    227 /* Private functions (used internally) */
    228 void         QZ_PrivateWarpCursor (_THIS, int x, int y);
    229 void         QZ_ChangeGrabState (_THIS, int action);
    230 void         QZ_RegisterForSleepNotifications (_THIS);
    231 void         QZ_PrivateGlobalToLocal (_THIS, NSPoint *p);
    232 void         QZ_PrivateCocoaToSDL (_THIS, NSPoint *p);
    233 BOOL         QZ_IsMouseInWindow (_THIS);
    234 void         QZ_DoActivate (_THIS);
    235 void         QZ_DoDeactivate (_THIS);
    236