mirror of
https://github.com/SFML/SFML.git
synced 2024-11-29 06:41: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/JoystickImpl.hpp
|
||||||
${SRCROOT}/OSX/SFApplication.h
|
${SRCROOT}/OSX/SFApplication.h
|
||||||
${SRCROOT}/OSX/SFApplication.m
|
${SRCROOT}/OSX/SFApplication.m
|
||||||
|
${SRCROOT}/OSX/SFApplicationDelegate.h
|
||||||
|
${SRCROOT}/OSX/SFApplicationDelegate.m
|
||||||
${SRCROOT}/OSX/SFContext.hpp
|
${SRCROOT}/OSX/SFContext.hpp
|
||||||
${SRCROOT}/OSX/SFContext.mm
|
${SRCROOT}/OSX/SFContext.mm
|
||||||
${SRCROOT}/OSX/SFKeyboardModifiersHelper.h
|
${SRCROOT}/OSX/SFKeyboardModifiersHelper.h
|
||||||
|
@ -88,7 +88,7 @@ public :
|
|||||||
/// \brief Drain the pool
|
/// \brief Drain the pool
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Drain();
|
void drain();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ void PoolWrapper::release()
|
|||||||
|
|
||||||
// Drain pool if required.
|
// Drain pool if required.
|
||||||
if (m_count == 0) {
|
if (m_count == 0) {
|
||||||
Drain();
|
drain();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SFML_DEBUG
|
#ifdef SFML_DEBUG
|
||||||
@ -165,7 +165,7 @@ void PoolWrapper::release()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void PoolWrapper::Drain()
|
void PoolWrapper::drain()
|
||||||
{
|
{
|
||||||
[m_pool drain];
|
[m_pool drain];
|
||||||
m_pool = 0;
|
m_pool = 0;
|
||||||
@ -227,7 +227,7 @@ void releasePool(void)
|
|||||||
void drainPool()
|
void drainPool()
|
||||||
{
|
{
|
||||||
if (localPool != NULL) {
|
if (localPool != NULL) {
|
||||||
localPool->Drain();
|
localPool->drain();
|
||||||
}
|
}
|
||||||
#ifdef SFML_DEBUG
|
#ifdef SFML_DEBUG
|
||||||
else {
|
else {
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#import <AppKit/AppKit.h>
|
#import <AppKit/AppKit.h>
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Event processing
|
/// \brief Event processing & Menu bar initialisation
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@interface SFApplication : NSApplication
|
@interface SFApplication : NSApplication
|
||||||
@ -43,6 +43,13 @@
|
|||||||
+(void)processEvent;
|
+(void)processEvent;
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set up the menu bar and its items
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
+(void)setUpMenuBar;
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Dispatch events
|
/// \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
|
-(void)sendEvent:(NSEvent *)anEvent
|
||||||
{
|
{
|
||||||
// Fullscreen windows have a strange behaviour with key up. To make
|
// 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.
|
/// \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.
|
/// These two methods must return YES to grab fullscreen events.
|
||||||
@ -45,4 +43,24 @@
|
|||||||
-(BOOL)acceptsFirstResponder;
|
-(BOOL)acceptsFirstResponder;
|
||||||
-(BOOL)canBecomeKeyWindow;
|
-(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
|
@end
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////
|
||||||
-(void)keyDown:(NSEvent *)theEvent
|
-(void)keyDown:(NSEvent *)theEvent
|
||||||
{
|
{
|
||||||
@ -56,4 +57,17 @@
|
|||||||
// alert to be thrown everytime the user presses a key.
|
// alert to be thrown everytime the user presses a key.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@implementation NSWindow (SFML)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
-(id)sfClose
|
||||||
|
{
|
||||||
|
[self performClose:nil];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#import <SFML/Window/OSX/cpp_objc_conversion.h>
|
#import <SFML/Window/OSX/cpp_objc_conversion.h>
|
||||||
#import <SFML/Window/OSX/AutoreleasePoolWrapper.h>
|
#import <SFML/Window/OSX/AutoreleasePoolWrapper.h>
|
||||||
#import <SFML/Window/OSX/SFApplication.h>
|
#import <SFML/Window/OSX/SFApplication.h>
|
||||||
|
#import <SFML/Window/OSX/SFApplicationDelegate.h>
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
@ -137,6 +138,14 @@ void WindowImplCocoa::setUpProcess(void)
|
|||||||
SetFrontProcess(&psn);
|
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.
|
// Tell the application to stop bouncing in the Dock.
|
||||||
[[SFApplication sharedApplication] finishLaunching];
|
[[SFApplication sharedApplication] finishLaunching];
|
||||||
// NOTE : This last call won't harm anything even if SFML window was
|
// NOTE : This last call won't harm anything even if SFML window was
|
||||||
|
Loading…
Reference in New Issue
Block a user