src/video/cocoa/SDL_cocoaevents.m
author Sam Lantinga
Sat, 22 Feb 2014 17:32:18 -0800
changeset 8237 6cc44a5d9eef
parent 8149 681eb46b8ac4
child 8239 05cbb1cb4f27
permissions -rw-r--r--
Fixed bug 2395 - OSX: App name in the menu bar is not localized.

Tim McDaniel

On OSX, the app name in the menu bar is not localized. This can be fixed using the following implementation for GetApplicationName in SDL_cocoaevents.m:

static NSString *
GetApplicationName(void)
{
NSDictionary *dict;
NSString *appName = 0;

appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
if (!appName)
appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];

if (![appName length])
appName = [[NSProcessInfo processInfo] processName];

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