Mercurial > sdl-ios-xcode
diff src/video/maccommon/SDL_macevents.c @ 0:74212992fb08
Initial revision
author | Sam Lantinga <slouken@lokigames.com> |
---|---|
date | Thu, 26 Apr 2001 16:45:43 +0000 |
parents | |
children | ee3bb7cd06b5 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/video/maccommon/SDL_macevents.c Thu Apr 26 16:45:43 2001 +0000 @@ -0,0 +1,677 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id$"; +#endif + +#include <stdio.h> + +#if TARGET_API_MAC_CARBON +#include <Carbon.h> +#else +#include <Script.h> +#include <LowMem.h> +#include <Devices.h> +#include <DiskInit.h> +#include <ToolUtils.h> +#endif + +#include "SDL_events.h" +#include "SDL_video.h" +#include "SDL_error.h" +#include "SDL_syswm.h" +#include "SDL_events_c.h" +#include "SDL_cursor_c.h" +#include "SDL_sysevents.h" +#include "SDL_macevents_c.h" +#include "SDL_mackeys.h" +#include "SDL_macmouse_c.h" + +/* Define this to be able to collapse SDL windows. +#define USE_APPEARANCE_MANAGER + */ + +/* Macintosh resource constants */ +#define mApple 128 /* Apple menu resource */ +#define iAbout 1 /* About menu item */ + +/* Functions to handle the About menu */ +static void Mac_DoAppleMenu(_THIS, long item); + +/* The translation table from a macintosh key scancode to a SDL keysym */ +static SDLKey MAC_keymap[256]; +static SDL_keysym *TranslateKey(int scancode, int modifiers, + SDL_keysym *keysym, int pressed); + +/* Handle activation and deactivation -- returns whether an event was posted */ +static int Mac_HandleActivate(int activate) +{ + if ( activate ) { + /* Show the current SDL application cursor */ + SDL_SetCursor(NULL); + + /* put our mask back case it changed during context switch */ + SetEventMask(everyEvent - autoKeyMask); + } else { +#if TARGET_API_MAC_CARBON + { Cursor cursor; + SetCursor(GetQDGlobalsArrow(&cursor)); + } +#else + SetCursor(&theQD->arrow); +#endif + if ( ! Mac_cursor_showing ) { + ShowCursor(); + Mac_cursor_showing = 1; + } + } + return(SDL_PrivateAppActive(activate, SDL_APPINPUTFOCUS)); +} + +static void myGlobalToLocal(_THIS, Point *pt) +{ + if ( SDL_VideoSurface && !(SDL_VideoSurface->flags&SDL_FULLSCREEN) ) { + GrafPtr saveport; + GetPort(&saveport); +#if TARGET_API_MAC_CARBON + SetPort(GetWindowPort(SDL_Window)); +#else + SetPort(SDL_Window); +#endif + GlobalToLocal(pt); + SetPort(saveport); + } +} + +/* The main MacOS event handler */ +static int Mac_HandleEvents(_THIS, int wait4it) +{ + int i; + EventRecord event; + +#if TARGET_API_MAC_CARBON + /* There's no GetOSEvent() in the Carbon API. *sigh* */ +#define cooperative_multitasking 1 +#else + int cooperative_multitasking; + /* If we're running fullscreen, we can hog the MacOS events, + otherwise we had better play nicely with the other apps. + */ + if ( this->screen && (this->screen->flags & SDL_FULLSCREEN) ) { + cooperative_multitasking = 0; + } else { + cooperative_multitasking = 1; + } +#endif + + /* If we call WaitNextEvent(), MacOS will check other processes + * and allow them to run, and perform other high-level processing. + */ + if ( cooperative_multitasking || wait4it ) { + UInt32 wait_time; + + /* Are we polling or not? */ + if ( wait4it ) { + wait_time = 2147483647; + } else { + wait_time = 0; + } + WaitNextEvent(everyEvent, &event, wait_time, nil); + } else { +#if ! TARGET_API_MAC_CARBON + GetOSEvent(everyEvent, &event); +#endif + } + +#if TARGET_API_MAC_CARBON + /* for some reason, event.where isn't set ? */ + GetGlobalMouse ( &event.where ); +#endif + + /* Check for mouse motion */ + if ( (event.where.h != last_where.h) || + (event.where.v != last_where.v) ) { + Point pt; + pt = last_where = event.where; + myGlobalToLocal(this, &pt); + SDL_PrivateMouseMotion(0, 0, pt.h, pt.v); + } + + /* Check the current state of the keyboard */ + if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) { + KeyMap keys; + + /* Check for special non-event keys */ + if ( event.modifiers != last_mods ) { + static struct { + EventModifiers mask; + SDLKey key; + } mods[] = { + { alphaLock, SDLK_CAPSLOCK }, +#if 0 /* These are handled below in the GetKeys() code */ + { cmdKey, SDLK_LMETA }, + { shiftKey, SDLK_LSHIFT }, + { rightShiftKey, SDLK_RSHIFT }, + { optionKey, SDLK_LALT }, + { rightOptionKey, SDLK_RALT }, + { controlKey, SDLK_LCTRL }, + { rightControlKey, SDLK_RCTRL }, +#endif /* 0 */ + { 0, 0 } + }; + SDL_keysym keysym; + Uint8 mode; + EventModifiers mod, mask; + + + /* Set up the keyboard event */ + keysym.scancode = 0; + keysym.sym = SDLK_UNKNOWN; + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + + /* See what has changed, and generate events */ + mod = event.modifiers; + for ( i=0; mods[i].mask; ++i ) { + mask = mods[i].mask; + if ( (mod&mask) != (last_mods&mask) ) { + keysym.sym = mods[i].key; + if ( (mod&mask) || + (mods[i].key == SDLK_CAPSLOCK) ) { + mode = SDL_PRESSED; + } else { + mode = SDL_RELEASED; + } + SDL_PrivateKeyboard(mode, &keysym); + } + } + + /* Save state for next time */ + last_mods = mod; + } + + /* Check for normal event keys, but we have to scan the + actual keyboard state because on MacOS X a keydown event + is immediately followed by a keyup event. + */ + GetKeys(keys); + if ( (keys[0] != last_keys[0]) || (keys[1] != last_keys[1]) || + (keys[2] != last_keys[2]) || (keys[3] != last_keys[3]) ) { + SDL_keysym keysym; + int old_bit, new_bit; + +#ifdef DEBUG_KEYBOARD + fprintf(sterr, "New keys: 0x%x 0x%x 0x%x 0x%x\n", + new_keys[0], new_keys[1], + new_keys[2], new_keys[3]); +#endif + for ( i=0; i<128; ++i ) { + old_bit = (((Uint8 *)last_keys)[i/8]>>(i%8)) & 0x01; + new_bit = (((Uint8 *)keys)[i/8]>>(i%8)) & 0x01; + if ( old_bit != new_bit ) { + /* Post the keyboard event */ +#ifdef DEBUG_KEYBOARD + fprintf(stderr,"Scancode: 0x%2.2X\n",i); +#endif + SDL_PrivateKeyboard(new_bit, + TranslateKey(i, event.modifiers, + &keysym, new_bit)); + } + } + + /* Save state for next time */ + last_keys[0] = keys[0]; + last_keys[1] = keys[1]; + last_keys[2] = keys[2]; + last_keys[3] = keys[3]; + } + } + + /* Handle normal events */ + switch (event.what) { + case mouseDown: { + WindowRef win; + short area; + + area = FindWindow(event.where, &win); + /* Support switching between the SIOUX console + and SDL_Window by clicking in the window. + */ + if ( win && (win != FrontWindow()) ) { + SelectWindow(win); + } + switch (area) { + case inMenuBar: /* Only the apple menu exists */ + Mac_DoAppleMenu(this, MenuSelect(event.where)); + HiliteMenu(0); + break; + case inDrag: +#if TARGET_API_MAC_CARBON + DragWindow(win, event.where, NULL); +#else + DragWindow(win, event.where, &theQD->screenBits.bounds); +#endif + break; + case inGoAway: + if ( TrackGoAway(win, event.where) ) { + SDL_PrivateQuit(); + } + break; + case inContent: + myGlobalToLocal(this, &event.where); + /* Treat command-click as right mouse button */ + if ( event.modifiers & optionKey ) { + SDL_PrivateMouseButton(SDL_PRESSED, + 2,event.where.h,event.where.v); + } + else if ( event.modifiers & cmdKey ) { + SDL_PrivateMouseButton(SDL_PRESSED, + 3,event.where.h,event.where.v); + } else { + SDL_PrivateMouseButton(SDL_PRESSED, + 1,event.where.h,event.where.v); + } + break; + case inGrow: { + int newSize; + + /* Don't allow resize if video mode isn't resizable */ + if ( ! SDL_PublicSurface || + ! (SDL_PublicSurface->flags & SDL_RESIZABLE) ) { + break; + } +#if TARGET_API_MAC_CARBON + newSize = GrowWindow(win, event.where, NULL); +#else + newSize = GrowWindow(win, event.where, &theQD->screenBits.bounds); +#endif + if ( newSize ) { +#if !TARGET_API_MAC_CARBON + EraseRect ( &theQD->screenBits.bounds ); +#endif + SizeWindow ( win, LoWord (newSize), HiWord (newSize), 1 ); + SDL_PrivateResize ( LoWord (newSize), HiWord (newSize) ); + } + } break; + case inZoomIn: + case inZoomOut: + if ( TrackBox (win, event.where, area )) { + Rect rect; +#if !TARGET_API_MAC_CARBON + EraseRect ( &theQD->screenBits.bounds ); +#endif + ZoomWindow ( win, area, 0); + if ( area == inZoomIn ) { + GetWindowUserState(SDL_Window, &rect); + } else { + GetWindowStandardState(SDL_Window, &rect); + } + SDL_PrivateResize (rect.right-rect.left, + rect.bottom-rect.top); + } + break; +#if TARGET_API_MAC_CARBON + case inCollapseBox: + if ( TrackBox (win, event.where, area )) { + if ( IsWindowCollapsable(win) ) { + CollapseWindow (win, !IsWindowCollapsed(win)); + // There should be something done like in inGrow case, but... + } + } + break; +#endif /* TARGET_API_MAC_CARBON */ + case inSysWindow: +#if TARGET_API_MAC_CARBON + /* Never happens in Carbon? */ +#else + SystemClick(&event, win); +#endif + break; + default: + break; + } + } + break; + case mouseUp: { + myGlobalToLocal(this, &event.where); + /* Treat command-click as right mouse button */ + if ( event.modifiers & cmdKey ) { + SDL_PrivateMouseButton(SDL_RELEASED, + 3, event.where.h, event.where.v); + } + else if ( event.modifiers & optionKey ) { + SDL_PrivateMouseButton(SDL_RELEASED, + 2,event.where.h,event.where.v); + } else { + SDL_PrivateMouseButton(SDL_RELEASED, + 1, event.where.h, event.where.v); + } + } + break; +#if 0 /* Handled above the switch statement */ + case keyDown: { + SDL_keysym keysym; + + SDL_PrivateKeyboard(SDL_PRESSED, + TranslateKey((event.message&keyCodeMask)>>8 + event.modifiers, &keysym, 1)); + } + break; + case keyUp: { + SDL_keysym keysym; + + SDL_PrivateKeyboard(SDL_RELEASED, + TranslateKey((event.message&keyCodeMask)>>8 + event.modifiers, &keysym, 0)); + } + break; +#endif + case updateEvt: { + BeginUpdate(SDL_Window); + if ( (SDL_VideoSurface->flags & SDL_HWSURFACE) == + SDL_SWSURFACE ) { + SDL_UpdateRect(SDL_VideoSurface, 0, 0, 0, 0); + } + EndUpdate(SDL_Window); + } + /* If this was an update event for the SIOUX console, we return 0 + in order to stop an endless series of updates being triggered. + */ + if ( (WindowRef) event.message != SDL_Window ) { + return 0; + } + break; + case activateEvt: { + Mac_HandleActivate(!!(event.modifiers & activeFlag)); + } + break; + case diskEvt: { +#if TARGET_API_MAC_CARBON + /* What are we supposed to do? */; +#else + if ( ((event.message>>16)&0xFFFF) != noErr ) { + Point spot; + SetPt(&spot, 0x0070, 0x0050); + DIBadMount(spot, event.message); + } +#endif + } + break; + case osEvt: { + switch ((event.message>>24) & 0xFF) { +#if 0 /* Handled above the switch statement */ + case mouseMovedMessage: { + myGlobalToLocal(this, &event.where); + SDL_PrivateMouseMotion(0, 0, + event.where.h, event.where.v); + } + break; +#endif /* 0 */ + case suspendResumeMessage: { + Mac_HandleActivate(!!(event.message & resumeFlag)); + } + break; + } + } + break; + default: { + ; + } + break; + } + return (event.what != nullEvent); +} + + +void Mac_PumpEvents(_THIS) +{ + /* Process pending MacOS events */ + while ( Mac_HandleEvents(this, 0) ) { + /* Loop and check again */; + } +} + +void Mac_InitOSKeymap(_THIS) +{ + int i; + + /* Map the MAC keysyms */ + for ( i=0; i<SDL_TABLESIZE(MAC_keymap); ++i ) + MAC_keymap[i] = SDLK_UNKNOWN; + + /* Wierd, these keys are on my iBook under MacOS X */ + MAC_keymap[MK_IBOOK_ENTER] = SDLK_KP_ENTER; + MAC_keymap[MK_IBOOK_RIGHT] = SDLK_RIGHT; + MAC_keymap[MK_IBOOK_DOWN] = SDLK_DOWN; + MAC_keymap[MK_IBOOK_UP] = SDLK_UP; + MAC_keymap[MK_IBOOK_LEFT] = SDLK_LEFT; + + /* Defined MAC_* constants */ + MAC_keymap[MK_ESCAPE] = SDLK_ESCAPE; + MAC_keymap[MK_F1] = SDLK_F1; + MAC_keymap[MK_F2] = SDLK_F2; + MAC_keymap[MK_F3] = SDLK_F3; + MAC_keymap[MK_F4] = SDLK_F4; + MAC_keymap[MK_F5] = SDLK_F5; + MAC_keymap[MK_F6] = SDLK_F6; + MAC_keymap[MK_F7] = SDLK_F7; + MAC_keymap[MK_F8] = SDLK_F8; + MAC_keymap[MK_F9] = SDLK_F9; + MAC_keymap[MK_F10] = SDLK_F10; + MAC_keymap[MK_F11] = SDLK_F11; + MAC_keymap[MK_F12] = SDLK_F12; + MAC_keymap[MK_PRINT] = SDLK_PRINT; + MAC_keymap[MK_SCROLLOCK] = SDLK_SCROLLOCK; + MAC_keymap[MK_PAUSE] = SDLK_PAUSE; + MAC_keymap[MK_POWER] = SDLK_POWER; + MAC_keymap[MK_BACKQUOTE] = SDLK_BACKQUOTE; + MAC_keymap[MK_1] = SDLK_1; + MAC_keymap[MK_2] = SDLK_2; + MAC_keymap[MK_3] = SDLK_3; + MAC_keymap[MK_4] = SDLK_4; + MAC_keymap[MK_5] = SDLK_5; + MAC_keymap[MK_6] = SDLK_6; + MAC_keymap[MK_7] = SDLK_7; + MAC_keymap[MK_8] = SDLK_8; + MAC_keymap[MK_9] = SDLK_9; + MAC_keymap[MK_0] = SDLK_0; + MAC_keymap[MK_MINUS] = SDLK_MINUS; + MAC_keymap[MK_EQUALS] = SDLK_EQUALS; + MAC_keymap[MK_BACKSPACE] = SDLK_BACKSPACE; + MAC_keymap[MK_INSERT] = SDLK_INSERT; + MAC_keymap[MK_HOME] = SDLK_HOME; + MAC_keymap[MK_PAGEUP] = SDLK_PAGEUP; + MAC_keymap[MK_NUMLOCK] = SDLK_NUMLOCK; + MAC_keymap[MK_KP_EQUALS] = SDLK_KP_EQUALS; + MAC_keymap[MK_KP_DIVIDE] = SDLK_KP_DIVIDE; + MAC_keymap[MK_KP_MULTIPLY] = SDLK_KP_MULTIPLY; + MAC_keymap[MK_TAB] = SDLK_TAB; + MAC_keymap[MK_q] = SDLK_q; + MAC_keymap[MK_w] = SDLK_w; + MAC_keymap[MK_e] = SDLK_e; + MAC_keymap[MK_r] = SDLK_r; + MAC_keymap[MK_t] = SDLK_t; + MAC_keymap[MK_y] = SDLK_y; + MAC_keymap[MK_u] = SDLK_u; + MAC_keymap[MK_i] = SDLK_i; + MAC_keymap[MK_o] = SDLK_o; + MAC_keymap[MK_p] = SDLK_p; + MAC_keymap[MK_LEFTBRACKET] = SDLK_LEFTBRACKET; + MAC_keymap[MK_RIGHTBRACKET] = SDLK_RIGHTBRACKET; + MAC_keymap[MK_BACKSLASH] = SDLK_BACKSLASH; + MAC_keymap[MK_DELETE] = SDLK_DELETE; + MAC_keymap[MK_END] = SDLK_END; + MAC_keymap[MK_PAGEDOWN] = SDLK_PAGEDOWN; + MAC_keymap[MK_KP7] = SDLK_KP7; + MAC_keymap[MK_KP8] = SDLK_KP8; + MAC_keymap[MK_KP9] = SDLK_KP9; + MAC_keymap[MK_KP_MINUS] = SDLK_KP_MINUS; + MAC_keymap[MK_CAPSLOCK] = SDLK_CAPSLOCK; + MAC_keymap[MK_a] = SDLK_a; + MAC_keymap[MK_s] = SDLK_s; + MAC_keymap[MK_d] = SDLK_d; + MAC_keymap[MK_f] = SDLK_f; + MAC_keymap[MK_g] = SDLK_g; + MAC_keymap[MK_h] = SDLK_h; + MAC_keymap[MK_j] = SDLK_j; + MAC_keymap[MK_k] = SDLK_k; + MAC_keymap[MK_l] = SDLK_l; + MAC_keymap[MK_SEMICOLON] = SDLK_SEMICOLON; + MAC_keymap[MK_QUOTE] = SDLK_QUOTE; + MAC_keymap[MK_RETURN] = SDLK_RETURN; + MAC_keymap[MK_KP4] = SDLK_KP4; + MAC_keymap[MK_KP5] = SDLK_KP5; + MAC_keymap[MK_KP6] = SDLK_KP6; + MAC_keymap[MK_KP_PLUS] = SDLK_KP_PLUS; + MAC_keymap[MK_LSHIFT] = SDLK_LSHIFT; + MAC_keymap[MK_z] = SDLK_z; + MAC_keymap[MK_x] = SDLK_x; + MAC_keymap[MK_c] = SDLK_c; + MAC_keymap[MK_v] = SDLK_v; + MAC_keymap[MK_b] = SDLK_b; + MAC_keymap[MK_n] = SDLK_n; + MAC_keymap[MK_m] = SDLK_m; + MAC_keymap[MK_COMMA] = SDLK_COMMA; + MAC_keymap[MK_PERIOD] = SDLK_PERIOD; + MAC_keymap[MK_SLASH] = SDLK_SLASH; +#if 0 /* These are the same as the left versions - use left by default */ + MAC_keymap[MK_RSHIFT] = SDLK_RSHIFT; +#endif + MAC_keymap[MK_UP] = SDLK_UP; + MAC_keymap[MK_KP1] = SDLK_KP1; + MAC_keymap[MK_KP2] = SDLK_KP2; + MAC_keymap[MK_KP3] = SDLK_KP3; + MAC_keymap[MK_KP_ENTER] = SDLK_KP_ENTER; + MAC_keymap[MK_LCTRL] = SDLK_LCTRL; + MAC_keymap[MK_LALT] = SDLK_LALT; + MAC_keymap[MK_LMETA] = SDLK_LMETA; + MAC_keymap[MK_SPACE] = SDLK_SPACE; +#if 0 /* These are the same as the left versions - use left by default */ + MAC_keymap[MK_RMETA] = SDLK_RMETA; + MAC_keymap[MK_RALT] = SDLK_RALT; + MAC_keymap[MK_RCTRL] = SDLK_RCTRL; +#endif + MAC_keymap[MK_LEFT] = SDLK_LEFT; + MAC_keymap[MK_DOWN] = SDLK_DOWN; + MAC_keymap[MK_RIGHT] = SDLK_RIGHT; + MAC_keymap[MK_KP0] = SDLK_KP0; + MAC_keymap[MK_KP_PERIOD] = SDLK_KP_PERIOD; +} + +static SDL_keysym *TranslateKey(int scancode, int modifiers, + SDL_keysym *keysym, int pressed) +{ + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = MAC_keymap[keysym->scancode]; + keysym->mod = KMOD_NONE; + keysym->unicode = 0; + if ( pressed && SDL_TranslateUNICODE ) { + static unsigned long state = 0; + static Ptr keymap = nil; + Ptr new_keymap; + + /* Get the current keyboard map resource */ + new_keymap = (Ptr)GetScriptManagerVariable(smKCHRCache); + if ( new_keymap != keymap ) { + keymap = new_keymap; + state = 0; + } + keysym->unicode = KeyTranslate(keymap, + keysym->scancode|modifiers, &state) & 0xFFFF; + } + return(keysym); +} + +void Mac_InitEvents(_THIS) +{ + /* Create apple menu bar */ + apple_menu = GetMenu(mApple); + if ( apple_menu != nil ) { + AppendResMenu(apple_menu, 'DRVR'); + InsertMenu(apple_menu, 0); + } + DrawMenuBar(); + + /* Get rid of spurious events at startup */ + FlushEvents(everyEvent, 0); + + /* Allow every event but keyrepeat */ + SetEventMask(everyEvent - autoKeyMask); +} + +void Mac_QuitEvents(_THIS) +{ + ClearMenuBar(); + if ( apple_menu != nil ) { + ReleaseResource((char **)apple_menu); + } + + /* Clean up pending events */ + FlushEvents(everyEvent, 0); +} + +static void Mac_DoAppleMenu(_THIS, long choice) +{ +#if !TARGET_API_MAC_CARBON /* No Apple menu in OS X */ + short menu, item; + + item = (choice&0xFFFF); + choice >>= 16; + menu = (choice&0xFFFF); + + switch (menu) { + case mApple: { + switch (item) { + case iAbout: { + /* Run the about box */; + } + break; + default: { + Str255 name; + + GetMenuItemText(apple_menu, item, name); + OpenDeskAcc(name); + } + break; + } + } + break; + default: { + /* Ignore other menus */; + } + } +#endif /* !TARGET_API_MAC_CARBON */ +} + +#if !TARGET_API_MAC_CARBON +/* Since we don't initialize QuickDraw, we need to get a pointer to qd */ +QDGlobals *theQD = NULL; + +/* Exported to the macmain code */ +void SDL_InitQuickDraw(struct QDGlobals *the_qd) +{ + theQD = the_qd; +} +#endif