medfall

A super great game engine
Log | Files | Refs

cocoa_init.m (12782B)


      1 //========================================================================
      2 // GLFW 3.3 macOS - www.glfw.org
      3 //------------------------------------------------------------------------
      4 // Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
      5 //
      6 // This software is provided 'as-is', without any express or implied
      7 // warranty. In no event will the authors be held liable for any damages
      8 // arising from the use of this software.
      9 //
     10 // Permission is granted to anyone to use this software for any purpose,
     11 // including commercial applications, and to alter it and redistribute it
     12 // freely, subject to the following restrictions:
     13 //
     14 // 1. The origin of this software must not be misrepresented; you must not
     15 //    claim that you wrote the original software. If you use this software
     16 //    in a product, an acknowledgment in the product documentation would
     17 //    be appreciated but is not required.
     18 //
     19 // 2. Altered source versions must be plainly marked as such, and must not
     20 //    be misrepresented as being the original software.
     21 //
     22 // 3. This notice may not be removed or altered from any source
     23 //    distribution.
     24 //
     25 //========================================================================
     26 
     27 #include "internal.h"
     28 #include <sys/param.h> // For MAXPATHLEN
     29 
     30 
     31 // Change to our application bundle's resources directory, if present
     32 //
     33 static void changeToResourcesDirectory(void)
     34 {
     35     char resourcesPath[MAXPATHLEN];
     36 
     37     CFBundleRef bundle = CFBundleGetMainBundle();
     38     if (!bundle)
     39         return;
     40 
     41     CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
     42 
     43     CFStringRef last = CFURLCopyLastPathComponent(resourcesURL);
     44     if (CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo)
     45     {
     46         CFRelease(last);
     47         CFRelease(resourcesURL);
     48         return;
     49     }
     50 
     51     CFRelease(last);
     52 
     53     if (!CFURLGetFileSystemRepresentation(resourcesURL,
     54                                           true,
     55                                           (UInt8*) resourcesPath,
     56                                           MAXPATHLEN))
     57     {
     58         CFRelease(resourcesURL);
     59         return;
     60     }
     61 
     62     CFRelease(resourcesURL);
     63 
     64     chdir(resourcesPath);
     65 }
     66 
     67 // Create key code translation tables
     68 //
     69 static void createKeyTables(void)
     70 {
     71     int scancode;
     72 
     73     memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes));
     74     memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes));
     75 
     76     _glfw.ns.keycodes[0x1D] = GLFW_KEY_0;
     77     _glfw.ns.keycodes[0x12] = GLFW_KEY_1;
     78     _glfw.ns.keycodes[0x13] = GLFW_KEY_2;
     79     _glfw.ns.keycodes[0x14] = GLFW_KEY_3;
     80     _glfw.ns.keycodes[0x15] = GLFW_KEY_4;
     81     _glfw.ns.keycodes[0x17] = GLFW_KEY_5;
     82     _glfw.ns.keycodes[0x16] = GLFW_KEY_6;
     83     _glfw.ns.keycodes[0x1A] = GLFW_KEY_7;
     84     _glfw.ns.keycodes[0x1C] = GLFW_KEY_8;
     85     _glfw.ns.keycodes[0x19] = GLFW_KEY_9;
     86     _glfw.ns.keycodes[0x00] = GLFW_KEY_A;
     87     _glfw.ns.keycodes[0x0B] = GLFW_KEY_B;
     88     _glfw.ns.keycodes[0x08] = GLFW_KEY_C;
     89     _glfw.ns.keycodes[0x02] = GLFW_KEY_D;
     90     _glfw.ns.keycodes[0x0E] = GLFW_KEY_E;
     91     _glfw.ns.keycodes[0x03] = GLFW_KEY_F;
     92     _glfw.ns.keycodes[0x05] = GLFW_KEY_G;
     93     _glfw.ns.keycodes[0x04] = GLFW_KEY_H;
     94     _glfw.ns.keycodes[0x22] = GLFW_KEY_I;
     95     _glfw.ns.keycodes[0x26] = GLFW_KEY_J;
     96     _glfw.ns.keycodes[0x28] = GLFW_KEY_K;
     97     _glfw.ns.keycodes[0x25] = GLFW_KEY_L;
     98     _glfw.ns.keycodes[0x2E] = GLFW_KEY_M;
     99     _glfw.ns.keycodes[0x2D] = GLFW_KEY_N;
    100     _glfw.ns.keycodes[0x1F] = GLFW_KEY_O;
    101     _glfw.ns.keycodes[0x23] = GLFW_KEY_P;
    102     _glfw.ns.keycodes[0x0C] = GLFW_KEY_Q;
    103     _glfw.ns.keycodes[0x0F] = GLFW_KEY_R;
    104     _glfw.ns.keycodes[0x01] = GLFW_KEY_S;
    105     _glfw.ns.keycodes[0x11] = GLFW_KEY_T;
    106     _glfw.ns.keycodes[0x20] = GLFW_KEY_U;
    107     _glfw.ns.keycodes[0x09] = GLFW_KEY_V;
    108     _glfw.ns.keycodes[0x0D] = GLFW_KEY_W;
    109     _glfw.ns.keycodes[0x07] = GLFW_KEY_X;
    110     _glfw.ns.keycodes[0x10] = GLFW_KEY_Y;
    111     _glfw.ns.keycodes[0x06] = GLFW_KEY_Z;
    112 
    113     _glfw.ns.keycodes[0x27] = GLFW_KEY_APOSTROPHE;
    114     _glfw.ns.keycodes[0x2A] = GLFW_KEY_BACKSLASH;
    115     _glfw.ns.keycodes[0x2B] = GLFW_KEY_COMMA;
    116     _glfw.ns.keycodes[0x18] = GLFW_KEY_EQUAL;
    117     _glfw.ns.keycodes[0x32] = GLFW_KEY_GRAVE_ACCENT;
    118     _glfw.ns.keycodes[0x21] = GLFW_KEY_LEFT_BRACKET;
    119     _glfw.ns.keycodes[0x1B] = GLFW_KEY_MINUS;
    120     _glfw.ns.keycodes[0x2F] = GLFW_KEY_PERIOD;
    121     _glfw.ns.keycodes[0x1E] = GLFW_KEY_RIGHT_BRACKET;
    122     _glfw.ns.keycodes[0x29] = GLFW_KEY_SEMICOLON;
    123     _glfw.ns.keycodes[0x2C] = GLFW_KEY_SLASH;
    124     _glfw.ns.keycodes[0x0A] = GLFW_KEY_WORLD_1;
    125 
    126     _glfw.ns.keycodes[0x33] = GLFW_KEY_BACKSPACE;
    127     _glfw.ns.keycodes[0x39] = GLFW_KEY_CAPS_LOCK;
    128     _glfw.ns.keycodes[0x75] = GLFW_KEY_DELETE;
    129     _glfw.ns.keycodes[0x7D] = GLFW_KEY_DOWN;
    130     _glfw.ns.keycodes[0x77] = GLFW_KEY_END;
    131     _glfw.ns.keycodes[0x24] = GLFW_KEY_ENTER;
    132     _glfw.ns.keycodes[0x35] = GLFW_KEY_ESCAPE;
    133     _glfw.ns.keycodes[0x7A] = GLFW_KEY_F1;
    134     _glfw.ns.keycodes[0x78] = GLFW_KEY_F2;
    135     _glfw.ns.keycodes[0x63] = GLFW_KEY_F3;
    136     _glfw.ns.keycodes[0x76] = GLFW_KEY_F4;
    137     _glfw.ns.keycodes[0x60] = GLFW_KEY_F5;
    138     _glfw.ns.keycodes[0x61] = GLFW_KEY_F6;
    139     _glfw.ns.keycodes[0x62] = GLFW_KEY_F7;
    140     _glfw.ns.keycodes[0x64] = GLFW_KEY_F8;
    141     _glfw.ns.keycodes[0x65] = GLFW_KEY_F9;
    142     _glfw.ns.keycodes[0x6D] = GLFW_KEY_F10;
    143     _glfw.ns.keycodes[0x67] = GLFW_KEY_F11;
    144     _glfw.ns.keycodes[0x6F] = GLFW_KEY_F12;
    145     _glfw.ns.keycodes[0x69] = GLFW_KEY_F13;
    146     _glfw.ns.keycodes[0x6B] = GLFW_KEY_F14;
    147     _glfw.ns.keycodes[0x71] = GLFW_KEY_F15;
    148     _glfw.ns.keycodes[0x6A] = GLFW_KEY_F16;
    149     _glfw.ns.keycodes[0x40] = GLFW_KEY_F17;
    150     _glfw.ns.keycodes[0x4F] = GLFW_KEY_F18;
    151     _glfw.ns.keycodes[0x50] = GLFW_KEY_F19;
    152     _glfw.ns.keycodes[0x5A] = GLFW_KEY_F20;
    153     _glfw.ns.keycodes[0x73] = GLFW_KEY_HOME;
    154     _glfw.ns.keycodes[0x72] = GLFW_KEY_INSERT;
    155     _glfw.ns.keycodes[0x7B] = GLFW_KEY_LEFT;
    156     _glfw.ns.keycodes[0x3A] = GLFW_KEY_LEFT_ALT;
    157     _glfw.ns.keycodes[0x3B] = GLFW_KEY_LEFT_CONTROL;
    158     _glfw.ns.keycodes[0x38] = GLFW_KEY_LEFT_SHIFT;
    159     _glfw.ns.keycodes[0x37] = GLFW_KEY_LEFT_SUPER;
    160     _glfw.ns.keycodes[0x6E] = GLFW_KEY_MENU;
    161     _glfw.ns.keycodes[0x47] = GLFW_KEY_NUM_LOCK;
    162     _glfw.ns.keycodes[0x79] = GLFW_KEY_PAGE_DOWN;
    163     _glfw.ns.keycodes[0x74] = GLFW_KEY_PAGE_UP;
    164     _glfw.ns.keycodes[0x7C] = GLFW_KEY_RIGHT;
    165     _glfw.ns.keycodes[0x3D] = GLFW_KEY_RIGHT_ALT;
    166     _glfw.ns.keycodes[0x3E] = GLFW_KEY_RIGHT_CONTROL;
    167     _glfw.ns.keycodes[0x3C] = GLFW_KEY_RIGHT_SHIFT;
    168     _glfw.ns.keycodes[0x36] = GLFW_KEY_RIGHT_SUPER;
    169     _glfw.ns.keycodes[0x31] = GLFW_KEY_SPACE;
    170     _glfw.ns.keycodes[0x30] = GLFW_KEY_TAB;
    171     _glfw.ns.keycodes[0x7E] = GLFW_KEY_UP;
    172 
    173     _glfw.ns.keycodes[0x52] = GLFW_KEY_KP_0;
    174     _glfw.ns.keycodes[0x53] = GLFW_KEY_KP_1;
    175     _glfw.ns.keycodes[0x54] = GLFW_KEY_KP_2;
    176     _glfw.ns.keycodes[0x55] = GLFW_KEY_KP_3;
    177     _glfw.ns.keycodes[0x56] = GLFW_KEY_KP_4;
    178     _glfw.ns.keycodes[0x57] = GLFW_KEY_KP_5;
    179     _glfw.ns.keycodes[0x58] = GLFW_KEY_KP_6;
    180     _glfw.ns.keycodes[0x59] = GLFW_KEY_KP_7;
    181     _glfw.ns.keycodes[0x5B] = GLFW_KEY_KP_8;
    182     _glfw.ns.keycodes[0x5C] = GLFW_KEY_KP_9;
    183     _glfw.ns.keycodes[0x45] = GLFW_KEY_KP_ADD;
    184     _glfw.ns.keycodes[0x41] = GLFW_KEY_KP_DECIMAL;
    185     _glfw.ns.keycodes[0x4B] = GLFW_KEY_KP_DIVIDE;
    186     _glfw.ns.keycodes[0x4C] = GLFW_KEY_KP_ENTER;
    187     _glfw.ns.keycodes[0x51] = GLFW_KEY_KP_EQUAL;
    188     _glfw.ns.keycodes[0x43] = GLFW_KEY_KP_MULTIPLY;
    189     _glfw.ns.keycodes[0x4E] = GLFW_KEY_KP_SUBTRACT;
    190 
    191     for (scancode = 0;  scancode < 256;  scancode++)
    192     {
    193         // Store the reverse translation for faster key name lookup
    194         if (_glfw.ns.keycodes[scancode] >= 0)
    195             _glfw.ns.scancodes[_glfw.ns.keycodes[scancode]] = scancode;
    196     }
    197 }
    198 
    199 // Retrieve Unicode data for the current keyboard layout
    200 //
    201 static GLFWbool updateUnicodeDataNS(void)
    202 {
    203     if (_glfw.ns.inputSource)
    204     {
    205         CFRelease(_glfw.ns.inputSource);
    206         _glfw.ns.inputSource = NULL;
    207         _glfw.ns.unicodeData = nil;
    208     }
    209 
    210     _glfw.ns.inputSource = TISCopyCurrentKeyboardLayoutInputSource();
    211     if (!_glfw.ns.inputSource)
    212     {
    213         _glfwInputError(GLFW_PLATFORM_ERROR,
    214                         "Cocoa: Failed to retrieve keyboard layout input source");
    215         return GLFW_FALSE;
    216     }
    217 
    218     _glfw.ns.unicodeData = TISGetInputSourceProperty(_glfw.ns.inputSource,
    219                                                      kTISPropertyUnicodeKeyLayoutData);
    220     if (!_glfw.ns.unicodeData)
    221     {
    222         _glfwInputError(GLFW_PLATFORM_ERROR,
    223                         "Cocoa: Failed to retrieve keyboard layout Unicode data");
    224         return GLFW_FALSE;
    225     }
    226 
    227     return GLFW_TRUE;
    228 }
    229 
    230 // Load HIToolbox.framework and the TIS symbols we need from it
    231 //
    232 static GLFWbool initializeTIS(void)
    233 {
    234     // This works only because Cocoa has already loaded it properly
    235     _glfw.ns.tis.bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
    236     if (!_glfw.ns.tis.bundle)
    237     {
    238         _glfwInputError(GLFW_PLATFORM_ERROR,
    239                         "Cocoa: Failed to load HIToolbox.framework");
    240         return GLFW_FALSE;
    241     }
    242 
    243     CFStringRef* kPropertyUnicodeKeyLayoutData =
    244         CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,
    245                                       CFSTR("kTISPropertyUnicodeKeyLayoutData"));
    246     _glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource =
    247         CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
    248                                           CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));
    249     _glfw.ns.tis.GetInputSourceProperty =
    250         CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
    251                                           CFSTR("TISGetInputSourceProperty"));
    252     _glfw.ns.tis.GetKbdType =
    253         CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
    254                                           CFSTR("LMGetKbdType"));
    255 
    256     if (!kPropertyUnicodeKeyLayoutData ||
    257         !TISCopyCurrentKeyboardLayoutInputSource ||
    258         !TISGetInputSourceProperty ||
    259         !LMGetKbdType)
    260     {
    261         _glfwInputError(GLFW_PLATFORM_ERROR,
    262                         "Cocoa: Failed to load TIS API symbols");
    263         return GLFW_FALSE;
    264     }
    265 
    266     _glfw.ns.tis.kPropertyUnicodeKeyLayoutData =
    267         *kPropertyUnicodeKeyLayoutData;
    268 
    269     return updateUnicodeDataNS();
    270 }
    271 
    272 @interface GLFWLayoutListener : NSObject
    273 @end
    274 
    275 @implementation GLFWLayoutListener
    276 
    277 - (void)selectedKeyboardInputSourceChanged:(NSObject* )object
    278 {
    279     updateUnicodeDataNS();
    280 }
    281 
    282 @end
    283 
    284 
    285 //////////////////////////////////////////////////////////////////////////
    286 //////                       GLFW platform API                      //////
    287 //////////////////////////////////////////////////////////////////////////
    288 
    289 int _glfwPlatformInit(void)
    290 {
    291     _glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
    292 
    293     if (_glfw.hints.init.ns.chdir)
    294         changeToResourcesDirectory();
    295 
    296     _glfw.ns.listener = [[GLFWLayoutListener alloc] init];
    297     [[NSNotificationCenter defaultCenter]
    298         addObserver:_glfw.ns.listener
    299            selector:@selector(selectedKeyboardInputSourceChanged:)
    300                name:NSTextInputContextKeyboardSelectionDidChangeNotification
    301              object:nil];
    302 
    303     createKeyTables();
    304 
    305     _glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
    306     if (!_glfw.ns.eventSource)
    307         return GLFW_FALSE;
    308 
    309     CGEventSourceSetLocalEventsSuppressionInterval(_glfw.ns.eventSource, 0.0);
    310 
    311     if (!initializeTIS())
    312         return GLFW_FALSE;
    313 
    314     _glfwInitTimerNS();
    315     _glfwInitJoysticksNS();
    316 
    317     _glfwPollMonitorsNS();
    318     return GLFW_TRUE;
    319 }
    320 
    321 void _glfwPlatformTerminate(void)
    322 {
    323     if (_glfw.ns.inputSource)
    324     {
    325         CFRelease(_glfw.ns.inputSource);
    326         _glfw.ns.inputSource = NULL;
    327         _glfw.ns.unicodeData = nil;
    328     }
    329 
    330     if (_glfw.ns.eventSource)
    331     {
    332         CFRelease(_glfw.ns.eventSource);
    333         _glfw.ns.eventSource = NULL;
    334     }
    335 
    336     if (_glfw.ns.delegate)
    337     {
    338         [NSApp setDelegate:nil];
    339         [_glfw.ns.delegate release];
    340         _glfw.ns.delegate = nil;
    341     }
    342 
    343     if (_glfw.ns.listener)
    344     {
    345         [[NSNotificationCenter defaultCenter]
    346             removeObserver:_glfw.ns.listener
    347                       name:NSTextInputContextKeyboardSelectionDidChangeNotification
    348                     object:nil];
    349         [[NSNotificationCenter defaultCenter]
    350             removeObserver:_glfw.ns.listener];
    351         [_glfw.ns.listener release];
    352         _glfw.ns.listener = nil;
    353     }
    354 
    355     [_glfw.ns.cursor release];
    356     _glfw.ns.cursor = nil;
    357 
    358     free(_glfw.ns.clipboardString);
    359 
    360     _glfwTerminateNSGL();
    361     _glfwTerminateJoysticksNS();
    362 
    363     [_glfw.ns.autoreleasePool release];
    364     _glfw.ns.autoreleasePool = nil;
    365 }
    366 
    367 const char* _glfwPlatformGetVersionString(void)
    368 {
    369     return _GLFW_VERSION_NUMBER " Cocoa NSGL"
    370 #if defined(_GLFW_BUILD_DLL)
    371         " dynamic"
    372 #endif
    373         ;
    374 }
    375