mirror of
https://github.com/SFML/SFML.git
synced 2024-11-25 12:51:05 +08:00
Implement Application Menu for OS X (close #11)
This commit is contained in:
parent
369b7faa1c
commit
a6dba586ee
@ -80,6 +80,8 @@ else() # MACOSX
|
||||
${SRCROOT}/OSX/JoystickImpl.hpp
|
||||
${SRCROOT}/OSX/SFApplication.h
|
||||
${SRCROOT}/OSX/SFApplication.m
|
||||
${SRCROOT}/OSX/SFApplicationDelegate.h
|
||||
${SRCROOT}/OSX/SFApplicationDelegate.m
|
||||
${SRCROOT}/OSX/SFContext.hpp
|
||||
${SRCROOT}/OSX/SFContext.mm
|
||||
${SRCROOT}/OSX/SFKeyboardModifiersHelper.h
|
||||
|
@ -88,7 +88,7 @@ public :
|
||||
/// \brief Drain the pool
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void Drain();
|
||||
void drain();
|
||||
|
||||
private:
|
||||
|
||||
@ -155,7 +155,7 @@ void PoolWrapper::release()
|
||||
|
||||
// Drain pool if required.
|
||||
if (m_count == 0) {
|
||||
Drain();
|
||||
drain();
|
||||
}
|
||||
|
||||
#ifdef SFML_DEBUG
|
||||
@ -165,7 +165,7 @@ void PoolWrapper::release()
|
||||
#endif
|
||||
}
|
||||
|
||||
void PoolWrapper::Drain()
|
||||
void PoolWrapper::drain()
|
||||
{
|
||||
[m_pool drain];
|
||||
m_pool = 0;
|
||||
@ -227,7 +227,7 @@ void releasePool(void)
|
||||
void drainPool()
|
||||
{
|
||||
if (localPool != NULL) {
|
||||
localPool->Drain();
|
||||
localPool->drain();
|
||||
}
|
||||
#ifdef SFML_DEBUG
|
||||
else {
|
||||
|
@ -30,7 +30,7 @@
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Event processing
|
||||
/// \brief Event processing & Menu bar initialisation
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
@interface SFApplication : NSApplication
|
||||
@ -43,6 +43,13 @@
|
||||
+(void)processEvent;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set up the menu bar and its items
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
+(void)setUpMenuBar;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Dispatch events
|
||||
///
|
||||
|
@ -48,6 +48,203 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
+(void)setUpMenuBar
|
||||
{
|
||||
[SFApplication sharedApplication]; // Make sure NSApp exists
|
||||
|
||||
// Set the main menu bar
|
||||
NSMenu* mainMenu = [NSApp mainMenu];
|
||||
if (mainMenu != nil) return;
|
||||
mainMenu = [[NSMenu alloc] initWithTitle:@""];
|
||||
[NSApp setMainMenu:mainMenu];
|
||||
|
||||
// Application Menu (aka Apple Menu)
|
||||
NSMenuItem* appleItem = [mainMenu addItemWithTitle:@"" action:nil keyEquivalent:@""];
|
||||
NSMenu* appleMenu = [[SFApplication createAppleMenu] autorelease];
|
||||
[appleItem setSubmenu:appleMenu];
|
||||
|
||||
// File Menu
|
||||
NSMenuItem* fileItem = [mainMenu addItemWithTitle:@"" action:nil keyEquivalent:@""];
|
||||
NSMenu* fileMenu = [[SFApplication createFileMenu] autorelease];
|
||||
[fileItem setSubmenu:fileMenu];
|
||||
|
||||
// Window menu
|
||||
NSMenuItem* windowItem = [mainMenu addItemWithTitle:@"" action:nil keyEquivalent:@""];
|
||||
NSMenu* windowMenu = [[SFApplication createWindowMenu] autorelease];
|
||||
[windowItem setSubmenu:windowMenu];
|
||||
[NSApp setWindowsMenu:windowMenu];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
+(NSMenu *)createAppleMenu
|
||||
{
|
||||
// Apple menu is as follow:
|
||||
//
|
||||
// AppName >
|
||||
// About AppName
|
||||
// --------------------
|
||||
// Preferences... [greyed]
|
||||
// --------------------
|
||||
// Services >
|
||||
// / default empty menu /
|
||||
// --------------------
|
||||
// Hide AppName ⌘H
|
||||
// Hide Others ⌥⌘H
|
||||
// Show All
|
||||
// --------------------
|
||||
// Quit AppName ⌘Q
|
||||
|
||||
NSString* appName = [SFApplication applicationName];
|
||||
|
||||
// APPLE MENU
|
||||
NSMenu* appleMenu = [[NSMenu alloc] initWithTitle:@""];
|
||||
|
||||
// ABOUT
|
||||
[appleMenu addItemWithTitle:[@"About " stringByAppendingString:appName]
|
||||
action:@selector(orderFrontStandardAboutPanel:)
|
||||
keyEquivalent:@""];
|
||||
|
||||
// SEPARATOR
|
||||
[appleMenu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
// PREFERENCES
|
||||
[appleMenu addItemWithTitle:@"Preferences…"
|
||||
action:nil
|
||||
keyEquivalent:@""];
|
||||
|
||||
// SEPARATOR
|
||||
[appleMenu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
// SERVICES
|
||||
NSMenu* serviceMenu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
|
||||
NSMenuItem* serviceItem = [appleMenu addItemWithTitle:@"Services"
|
||||
action:nil
|
||||
keyEquivalent:@""];
|
||||
[serviceItem setSubmenu:serviceMenu];
|
||||
[NSApp setServicesMenu:serviceMenu];
|
||||
|
||||
// SEPARATOR
|
||||
[appleMenu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
// HIDE
|
||||
[appleMenu addItemWithTitle:[@"Hide " stringByAppendingString:appName]
|
||||
action:@selector(hide:)
|
||||
keyEquivalent:@"h"];
|
||||
|
||||
// HIDE OTHER
|
||||
NSMenuItem* hideOtherItem = [appleMenu addItemWithTitle:@"Hide Others"
|
||||
action:@selector(hideOtherApplications:)
|
||||
keyEquivalent:@"h"];
|
||||
[hideOtherItem setKeyEquivalentModifierMask:(NSAlternateKeyMask | NSCommandKeyMask)];
|
||||
|
||||
// SHOW ALL
|
||||
[appleMenu addItemWithTitle:@"Show All"
|
||||
action:@selector(unhideAllApplications:)
|
||||
keyEquivalent:@""];
|
||||
|
||||
// SEPARATOR
|
||||
[appleMenu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
// QUIT
|
||||
[appleMenu addItemWithTitle:[@"Quit " stringByAppendingString:appName]
|
||||
action:@selector(terminate:)
|
||||
keyEquivalent:@"q"];
|
||||
|
||||
return appleMenu;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
+(NSMenu *)createFileMenu
|
||||
{
|
||||
// The File menu is as follow:
|
||||
//
|
||||
// File >
|
||||
// Close ⌘W
|
||||
|
||||
// FILE MENU
|
||||
NSMenu* fileMenu = [[NSMenu alloc] initWithTitle:@"File"];
|
||||
|
||||
// CLOSE WINDOW
|
||||
NSMenuItem* closeItem = [[NSMenuItem alloc] initWithTitle:@"Close Window"
|
||||
action:@selector(performClose:)
|
||||
keyEquivalent:@"w"];
|
||||
[fileMenu addItem:closeItem];
|
||||
[closeItem release];
|
||||
|
||||
return fileMenu;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
+(NSMenu *)createWindowMenu
|
||||
{
|
||||
// The Window menu is as follow:
|
||||
//
|
||||
// Window >
|
||||
// Minimize ⌘M
|
||||
// Zoom
|
||||
// --------------------
|
||||
// Bring All to Front
|
||||
|
||||
// WINDOW MENU
|
||||
NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
|
||||
|
||||
// MINIMIZE
|
||||
NSMenuItem* minimizeItem = [[NSMenuItem alloc] initWithTitle:@"Minimize"
|
||||
action:@selector(performMiniaturize:)
|
||||
keyEquivalent:@"m"];
|
||||
[windowMenu addItem:minimizeItem];
|
||||
[minimizeItem release];
|
||||
|
||||
// ZOOM
|
||||
[windowMenu addItemWithTitle:@"Zoom"
|
||||
action:@selector(performZoom:)
|
||||
keyEquivalent:@""];
|
||||
|
||||
// SEPARATOR
|
||||
[windowMenu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
// BRING ALL TO FRONT
|
||||
[windowMenu addItemWithTitle:@"Bring All to Front"
|
||||
action:@selector(bringAllToFront:)
|
||||
keyEquivalent:@""];
|
||||
|
||||
return windowMenu;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
+(NSString *)applicationName
|
||||
{
|
||||
// First, try localized name
|
||||
NSString* appName = [[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:@"CFBundleDisplayName"];
|
||||
|
||||
// Then, try non-localized name
|
||||
if (appName == nil || [appName length] == 0) {
|
||||
appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
|
||||
}
|
||||
|
||||
// Finally, fallback to the process info
|
||||
if (appName == nil || [appName length] == 0) {
|
||||
appName = [[NSProcessInfo processInfo] processName];
|
||||
}
|
||||
|
||||
return appName;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
-(void)bringAllToFront:(id)sender
|
||||
{
|
||||
[[NSApp windows] makeObjectsPerformSelector:@selector(orderFrontRegardless)];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
-(void)sendEvent:(NSEvent *)anEvent
|
||||
{
|
||||
// Fullscreen windows have a strange behaviour with key up. To make
|
||||
|
42
src/SFML/Window/OSX/SFApplicationDelegate.h
Normal file
42
src/SFML/Window/OSX/SFApplicationDelegate.h
Normal file
@ -0,0 +1,42 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 Marco Antognini (antognini.marco@gmail.com),
|
||||
// Laurent Gomila (laurent.gom@gmail.com),
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it freely,
|
||||
// subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented;
|
||||
// you must not claim that you wrote the original software.
|
||||
// If you use this software in a product, an acknowledgment
|
||||
// in the product documentation would be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such,
|
||||
// and must not be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Process some application specific events
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
@interface SFApplicationDelegate : NSObject <NSApplicationDelegate>
|
||||
|
||||
-(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
|
||||
-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication;
|
||||
|
||||
@end
|
52
src/SFML/Window/OSX/SFApplicationDelegate.m
Normal file
52
src/SFML/Window/OSX/SFApplicationDelegate.m
Normal file
@ -0,0 +1,52 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 Marco Antognini (antognini.marco@gmail.com),
|
||||
// Laurent Gomila (laurent.gom@gmail.com),
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it freely,
|
||||
// subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented;
|
||||
// you must not claim that you wrote the original software.
|
||||
// If you use this software in a product, an acknowledgment
|
||||
// in the product documentation would be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such,
|
||||
// and must not be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#import <SFML/Window/OSX/SFApplicationDelegate.h>
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@implementation SFApplicationDelegate
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
-(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
||||
{
|
||||
// TODO generate close event for each SFML window
|
||||
[NSApp makeWindowsPerform:@selector(sfClose) inOrder:NO];
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
@ -32,9 +32,7 @@
|
||||
/// \brief Here we redefine some methods to allow grabing fullscreen events.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
@interface SFWindow : NSWindow {
|
||||
|
||||
}
|
||||
@interface SFWindow : NSWindow
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// These two methods must return YES to grab fullscreen events.
|
||||
@ -45,4 +43,24 @@
|
||||
-(BOOL)acceptsFirstResponder;
|
||||
-(BOOL)canBecomeKeyWindow;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Override default implementation of keyDown: to prevent
|
||||
/// system alert
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
-(void)keyDown:(NSEvent *)theEvent;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface NSWindow (SFML)
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Proxy for performClose: for the app delegate
|
||||
///
|
||||
/// Always return nil
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
-(id)sfClose;
|
||||
|
||||
@end
|
||||
|
@ -44,6 +44,7 @@
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
-(void)keyDown:(NSEvent *)theEvent
|
||||
{
|
||||
@ -56,4 +57,17 @@
|
||||
// alert to be thrown everytime the user presses a key.
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation NSWindow (SFML)
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
-(id)sfClose
|
||||
{
|
||||
[self performClose:nil];
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -35,6 +35,7 @@
|
||||
#import <SFML/Window/OSX/cpp_objc_conversion.h>
|
||||
#import <SFML/Window/OSX/AutoreleasePoolWrapper.h>
|
||||
#import <SFML/Window/OSX/SFApplication.h>
|
||||
#import <SFML/Window/OSX/SFApplicationDelegate.h>
|
||||
|
||||
namespace sf
|
||||
{
|
||||
@ -137,6 +138,14 @@ void WindowImplCocoa::setUpProcess(void)
|
||||
SetFrontProcess(&psn);
|
||||
}
|
||||
|
||||
// Register an application delegate if there is none
|
||||
if (![[SFApplication sharedApplication] delegate]) {
|
||||
[NSApp setDelegate:[[SFApplicationDelegate alloc] init]];
|
||||
}
|
||||
|
||||
// Create menus for the application (before finishing launching!)
|
||||
[SFApplication setUpMenuBar];
|
||||
|
||||
// Tell the application to stop bouncing in the Dock.
|
||||
[[SFApplication sharedApplication] finishLaunching];
|
||||
// NOTE : This last call won't harm anything even if SFML window was
|
||||
|
Loading…
Reference in New Issue
Block a user