src/video/cocoa/SDL_cocoaevents.m
author Sam Lantinga <slouken@libsdl.org>
Fri, 08 Feb 2013 00:54:08 -0800
changeset 6836 b0ca1571caf3
parent 6832 156e608ec4ef
child 6848 478ecc8a58b3
permissions -rw-r--r--
Fixed bug 1689 - Leaks galore in OS X Cocoa code.

Edward Rudd

This is to document the various leaks I'm finding in the Cocoa code in SDL 2.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 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_config.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 
    29 #if !defined(UsrActivity) && defined(__LP64__) && !defined(__POWER__)
    30 /*
    31  * Workaround for a bug in the 10.5 SDK: By accident, OSService.h does
    32  * not include Power.h at all when compiling in 64bit mode. This has
    33  * been fixed in 10.6, but for 10.5, we manually define UsrActivity
    34  * to ensure compilation works.
    35  */
    36 #define UsrActivity 1
    37 #endif
    38 
    39 /* setAppleMenu disappeared from the headers in 10.4 */
    40 @interface NSApplication(NSAppleMenu)
    41 - (void)setAppleMenu:(NSMenu *)menu;
    42 @end
    43 
    44 @interface SDLAppDelegate : NSObject
    45 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
    46 @end
    47 
    48 @implementation SDLAppDelegate : NSObject
    49 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
    50 {
    51     SDL_SendQuit();
    52     return NSTerminateCancel;
    53 }
    54 
    55 - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
    56 {
    57     return (BOOL)SDL_SendDropFile([filename UTF8String]);
    58 }
    59 @end
    60 
    61 static NSString *
    62 GetApplicationName(void)
    63 {
    64     NSDictionary *dict;
    65     NSString *appName = 0;
    66 
    67     /* Determine the application name */
    68     dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle());
    69     if (dict)
    70         appName = [dict objectForKey: @"CFBundleName"];
    71     
    72     if (![appName length])
    73         appName = [[NSProcessInfo processInfo] processName];
    74 
    75     return appName;
    76 }
    77 
    78 static void
    79 CreateApplicationMenus(void)
    80 {
    81     NSString *appName;
    82     NSString *title;
    83     NSMenu *appleMenu;
    84     NSMenu *serviceMenu;
    85     NSMenu *windowMenu;
    86     NSMenuItem *menuItem;
    87     
    88     /* Create the main menu bar */
    89     [NSApp setMainMenu:[[NSMenu alloc] init]];
    90 
    91     /* Create the application menu */
    92     appName = GetApplicationName();
    93     appleMenu = [[NSMenu alloc] initWithTitle:@""];
    94     
    95     /* Add menu items */
    96     title = [@"About " stringByAppendingString:appName];
    97     [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
    98 
    99     [appleMenu addItem:[NSMenuItem separatorItem]];
   100 
   101     [appleMenu addItemWithTitle:@"Preferences…" action:nil keyEquivalent:@","];
   102 
   103     [appleMenu addItem:[NSMenuItem separatorItem]];
   104 
   105     serviceMenu = [[NSMenu alloc] initWithTitle:@""];
   106     menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Services" action:nil keyEquivalent:@""];
   107     [menuItem setSubmenu:serviceMenu];
   108 
   109     [NSApp setServicesMenu:serviceMenu];
   110     [serviceMenu release];
   111 
   112     [appleMenu addItem:[NSMenuItem separatorItem]];
   113 
   114     title = [@"Hide " stringByAppendingString:appName];
   115     [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
   116 
   117     menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
   118     [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
   119 
   120     [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
   121 
   122     [appleMenu addItem:[NSMenuItem separatorItem]];
   123 
   124     title = [@"Quit " stringByAppendingString:appName];
   125     [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
   126     
   127     /* Put menu into the menubar */
   128     menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
   129     [menuItem setSubmenu:appleMenu];
   130     [[NSApp mainMenu] addItem:menuItem];
   131     [menuItem release];
   132 
   133     /* Tell the application object that this is now the application menu */
   134     [NSApp setAppleMenu:appleMenu];
   135     [appleMenu release];
   136 
   137 
   138     /* Create the window menu */
   139     windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
   140     
   141     /* Add menu items */
   142     [windowMenu addItemWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
   143     
   144     [windowMenu addItemWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""];
   145 
   146     /* Put menu into the menubar */
   147     menuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
   148     [menuItem setSubmenu:windowMenu];
   149     [[NSApp mainMenu] addItem:menuItem];
   150     [menuItem release];
   151     
   152     /* Tell the application object that this is now the window menu */
   153     [NSApp setWindowsMenu:windowMenu];
   154     [windowMenu release];
   155 }
   156 
   157 void
   158 Cocoa_RegisterApp(void)
   159 {
   160     /* This can get called more than once! Be careful what you initialize! */
   161     ProcessSerialNumber psn;
   162 
   163     if (!GetCurrentProcess(&psn)) {
   164         TransformProcessType(&psn, kProcessTransformToForegroundApplication);
   165         SetFrontProcess(&psn);
   166     }
   167 
   168     @autoreleasepool {
   169         if (NSApp == nil) {
   170             [NSApplication sharedApplication];
   171 
   172             if ([NSApp mainMenu] == nil) {
   173                 CreateApplicationMenus();
   174             }
   175             [NSApp finishLaunching];
   176         }
   177         if ([NSApp delegate] == nil) {
   178             [NSApp setDelegate:[[SDLAppDelegate alloc] init]];
   179         }
   180     }
   181 }
   182 
   183 void
   184 Cocoa_PumpEvents(_THIS)
   185 {
   186     /* Update activity every 30 seconds to prevent screensaver */
   187     if (_this->suspend_screensaver) {
   188         SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
   189         Uint32 now = SDL_GetTicks();
   190         if (!data->screensaver_activity ||
   191             (int)(now-data->screensaver_activity) >= 30000) {
   192             UpdateSystemActivity(UsrActivity);
   193             data->screensaver_activity = now;
   194         }
   195     }
   196 
   197     @autoreleasepool {
   198         for ( ; ; ) {
   199             NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES ];
   200             if ( event == nil ) {
   201                 break;
   202             }
   203             
   204             switch ([event type]) {
   205             case NSLeftMouseDown:
   206             case NSOtherMouseDown:
   207             case NSRightMouseDown:
   208             case NSLeftMouseUp:
   209             case NSOtherMouseUp:
   210             case NSRightMouseUp:
   211             case NSLeftMouseDragged:
   212             case NSRightMouseDragged:
   213             case NSOtherMouseDragged: /* usually middle mouse dragged */
   214             case NSMouseMoved:
   215             case NSScrollWheel:
   216                 Cocoa_HandleMouseEvent(_this, event);
   217                 break;
   218             case NSKeyDown:
   219             case NSKeyUp:
   220             case NSFlagsChanged:
   221                 Cocoa_HandleKeyEvent(_this, event);
   222                 break;
   223             default:
   224                 break;
   225             }
   226             /* Pass through to NSApp to make sure everything stays in sync */
   227             [NSApp sendEvent:event];
   228         }
   229     }
   230 }
   231 
   232 #endif /* SDL_VIDEO_DRIVER_COCOA */
   233 
   234 /* vi: set ts=4 sw=4 expandtab: */