cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_cocoaevents.m (10648B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
      4
      5  This software is provided 'as-is', without any express or implied
      6  warranty.  In no event will the authors be held liable for any damages
      7  arising from the use of this software.
      8
      9  Permission is granted to anyone to use this software for any purpose,
     10  including commercial applications, and to alter it and redistribute it
     11  freely, subject to the following restrictions:
     12
     13  1. The origin of this software must not be misrepresented; you must not
     14     claim that you wrote the original software. If you use this software
     15     in a product, an acknowledgment in the product documentation would be
     16     appreciated but is not required.
     17  2. Altered source versions must be plainly marked as such, and must not be
     18     misrepresented as being the original software.
     19  3. This notice may not be removed or altered from any source distribution.
     20*/
     21#include "../../SDL_internal.h"
     22
     23#if SDL_VIDEO_DRIVER_COCOA
     24#include "SDL_timer.h"
     25
     26#include "SDL_cocoavideo.h"
     27#include "../../events/SDL_events_c.h"
     28#include "SDL_assert.h"
     29
     30@interface SDLApplication : NSApplication
     31
     32- (void)terminate:(id)sender;
     33
     34@end
     35
     36@implementation SDLApplication
     37
     38// Override terminate to handle Quit and System Shutdown smoothly.
     39- (void)terminate:(id)sender
     40{
     41    SDL_SendQuit();
     42}
     43
     44@end // SDLApplication
     45
     46/* setAppleMenu disappeared from the headers in 10.4 */
     47@interface NSApplication(NSAppleMenu)
     48- (void)setAppleMenu:(NSMenu *)menu;
     49@end
     50
     51@interface SDLAppDelegate : NSObject <NSApplicationDelegate> {
     52@public
     53    BOOL seenFirstActivate;
     54}
     55
     56- (id)init;
     57@end
     58
     59@implementation SDLAppDelegate : NSObject
     60- (id)init
     61{
     62    self = [super init];
     63    if (self) {
     64        seenFirstActivate = NO;
     65        [[NSNotificationCenter defaultCenter] addObserver:self
     66                                                 selector:@selector(focusSomeWindow:)
     67                                                     name:NSApplicationDidBecomeActiveNotification
     68                                                   object:nil];
     69    }
     70
     71    return self;
     72}
     73
     74- (void)dealloc
     75{
     76    [[NSNotificationCenter defaultCenter] removeObserver:self];
     77    [super dealloc];
     78}
     79
     80- (void)focusSomeWindow:(NSNotification *)aNotification
     81{
     82    /* HACK: Ignore the first call. The application gets a
     83     * applicationDidBecomeActive: a little bit after the first window is
     84     * created, and if we don't ignore it, a window that has been created with
     85     * SDL_WINDOW_MINIZED will ~immediately be restored.
     86     */
     87    if (!seenFirstActivate) {
     88        seenFirstActivate = YES;
     89        return;
     90    }
     91
     92    SDL_VideoDevice *device = SDL_GetVideoDevice();
     93    if (device && device->windows) {
     94        SDL_Window *window = device->windows;
     95        int i;
     96        for (i = 0; i < device->num_displays; ++i) {
     97            SDL_Window *fullscreen_window = device->displays[i].fullscreen_window;
     98            if (fullscreen_window) {
     99                if (fullscreen_window->flags & SDL_WINDOW_MINIMIZED) {
    100                    SDL_RestoreWindow(fullscreen_window);
    101                }
    102                return;
    103            }
    104        }
    105
    106        if (window->flags & SDL_WINDOW_MINIMIZED) {
    107            SDL_RestoreWindow(window);
    108        } else {
    109            SDL_RaiseWindow(window);
    110        }
    111    }
    112}
    113
    114- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
    115{
    116    return (BOOL)SDL_SendDropFile([filename UTF8String]);
    117}
    118@end
    119
    120static SDLAppDelegate *appDelegate = nil;
    121
    122static NSString *
    123GetApplicationName(void)
    124{
    125    NSString *appName;
    126
    127    /* Determine the application name */
    128    appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
    129    if (!appName) {
    130        appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
    131    }
    132
    133    if (![appName length]) {
    134        appName = [[NSProcessInfo processInfo] processName];
    135    }
    136
    137    return appName;
    138}
    139
    140static void
    141CreateApplicationMenus(void)
    142{
    143    NSString *appName;
    144    NSString *title;
    145    NSMenu *appleMenu;
    146    NSMenu *serviceMenu;
    147    NSMenu *windowMenu;
    148    NSMenu *viewMenu;
    149    NSMenuItem *menuItem;
    150    NSMenu *mainMenu;
    151
    152    if (NSApp == nil) {
    153        return;
    154    }
    155
    156    mainMenu = [[NSMenu alloc] init];
    157
    158    /* Create the main menu bar */
    159    [NSApp setMainMenu:mainMenu];
    160
    161    [mainMenu release];  /* we're done with it, let NSApp own it. */
    162    mainMenu = nil;
    163
    164    /* Create the application menu */
    165    appName = GetApplicationName();
    166    appleMenu = [[NSMenu alloc] initWithTitle:@""];
    167
    168    /* Add menu items */
    169    title = [@"About " stringByAppendingString:appName];
    170    [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
    171
    172    [appleMenu addItem:[NSMenuItem separatorItem]];
    173
    174    [appleMenu addItemWithTitle:@"Preferences…" action:nil keyEquivalent:@","];
    175
    176    [appleMenu addItem:[NSMenuItem separatorItem]];
    177
    178    serviceMenu = [[NSMenu alloc] initWithTitle:@""];
    179    menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Services" action:nil keyEquivalent:@""];
    180    [menuItem setSubmenu:serviceMenu];
    181
    182    [NSApp setServicesMenu:serviceMenu];
    183    [serviceMenu release];
    184
    185    [appleMenu addItem:[NSMenuItem separatorItem]];
    186
    187    title = [@"Hide " stringByAppendingString:appName];
    188    [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
    189
    190    menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
    191    [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
    192
    193    [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
    194
    195    [appleMenu addItem:[NSMenuItem separatorItem]];
    196
    197    title = [@"Quit " stringByAppendingString:appName];
    198    [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
    199
    200    /* Put menu into the menubar */
    201    menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
    202    [menuItem setSubmenu:appleMenu];
    203    [[NSApp mainMenu] addItem:menuItem];
    204    [menuItem release];
    205
    206    /* Tell the application object that this is now the application menu */
    207    [NSApp setAppleMenu:appleMenu];
    208    [appleMenu release];
    209
    210
    211    /* Create the window menu */
    212    windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
    213
    214    /* Add menu items */
    215    [windowMenu addItemWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
    216
    217    [windowMenu addItemWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""];
    218
    219    /* Put menu into the menubar */
    220    menuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
    221    [menuItem setSubmenu:windowMenu];
    222    [[NSApp mainMenu] addItem:menuItem];
    223    [menuItem release];
    224
    225    /* Tell the application object that this is now the window menu */
    226    [NSApp setWindowsMenu:windowMenu];
    227    [windowMenu release];
    228
    229
    230    /* Add the fullscreen view toggle menu option, if supported */
    231    if ([NSApp respondsToSelector:@selector(setPresentationOptions:)]) {
    232        /* Create the view menu */
    233        viewMenu = [[NSMenu alloc] initWithTitle:@"View"];
    234
    235        /* Add menu items */
    236        menuItem = [viewMenu addItemWithTitle:@"Toggle Full Screen" action:@selector(toggleFullScreen:) keyEquivalent:@"f"];
    237        [menuItem setKeyEquivalentModifierMask:NSControlKeyMask | NSCommandKeyMask];
    238
    239        /* Put menu into the menubar */
    240        menuItem = [[NSMenuItem alloc] initWithTitle:@"View" action:nil keyEquivalent:@""];
    241        [menuItem setSubmenu:viewMenu];
    242        [[NSApp mainMenu] addItem:menuItem];
    243        [menuItem release];
    244
    245        [viewMenu release];
    246    }
    247}
    248
    249void
    250Cocoa_RegisterApp(void)
    251{ @autoreleasepool
    252{
    253    /* This can get called more than once! Be careful what you initialize! */
    254    ProcessSerialNumber psn;
    255
    256    if (!GetCurrentProcess(&psn)) {
    257        TransformProcessType(&psn, kProcessTransformToForegroundApplication);
    258        SetFrontProcess(&psn);
    259    }
    260
    261    if (NSApp == nil) {
    262        [SDLApplication sharedApplication];
    263        SDL_assert(NSApp != nil);
    264
    265        if ([NSApp mainMenu] == nil) {
    266            CreateApplicationMenus();
    267        }
    268        [NSApp finishLaunching];
    269        NSDictionary *appDefaults = [[NSDictionary alloc] initWithObjectsAndKeys:
    270            [NSNumber numberWithBool:NO], @"AppleMomentumScrollSupported",
    271            [NSNumber numberWithBool:NO], @"ApplePressAndHoldEnabled",
    272            [NSNumber numberWithBool:YES], @"ApplePersistenceIgnoreState",
    273            nil];
    274        [[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
    275        [appDefaults release];
    276    }
    277    if (NSApp && !appDelegate) {
    278        appDelegate = [[SDLAppDelegate alloc] init];
    279
    280        /* If someone else has an app delegate, it means we can't turn a
    281         * termination into SDL_Quit, and we can't handle application:openFile:
    282         */
    283        if (![NSApp delegate]) {
    284            [(NSApplication *)NSApp setDelegate:appDelegate];
    285        } else {
    286            appDelegate->seenFirstActivate = YES;
    287        }
    288    }
    289}}
    290
    291void
    292Cocoa_PumpEvents(_THIS)
    293{ @autoreleasepool
    294{
    295    /* Update activity every 30 seconds to prevent screensaver */
    296    if (_this->suspend_screensaver) {
    297        SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
    298        Uint32 now = SDL_GetTicks();
    299        if (!data->screensaver_activity ||
    300            SDL_TICKS_PASSED(now, data->screensaver_activity + 30000)) {
    301            UpdateSystemActivity(UsrActivity);
    302            data->screensaver_activity = now;
    303        }
    304    }
    305
    306    for ( ; ; ) {
    307        NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES ];
    308        if ( event == nil ) {
    309            break;
    310        }
    311
    312        switch ([event type]) {
    313        case NSLeftMouseDown:
    314        case NSOtherMouseDown:
    315        case NSRightMouseDown:
    316        case NSLeftMouseUp:
    317        case NSOtherMouseUp:
    318        case NSRightMouseUp:
    319        case NSLeftMouseDragged:
    320        case NSRightMouseDragged:
    321        case NSOtherMouseDragged: /* usually middle mouse dragged */
    322        case NSMouseMoved:
    323        case NSScrollWheel:
    324            Cocoa_HandleMouseEvent(_this, event);
    325            break;
    326        case NSKeyDown:
    327        case NSKeyUp:
    328        case NSFlagsChanged:
    329            Cocoa_HandleKeyEvent(_this, event);
    330            break;
    331        default:
    332            break;
    333        }
    334        /* Pass through to NSApp to make sure everything stays in sync */
    335        [NSApp sendEvent:event];
    336    }
    337}}
    338
    339#endif /* SDL_VIDEO_DRIVER_COCOA */
    340
    341/* vi: set ts=4 sw=4 expandtab: */