From 3b299d92b847461c92e958d71eb5e6c20a1eac42 Mon Sep 17 00:00:00 2001 From: John Croisant Date: Sat, 10 Jul 2010 22:53:30 -0500 Subject: [PATCH] More progress on Mac support. --- lib/ruby-sdl-ffi/sdl/mac.rb | 211 ++++++++++++++++++++-------------- lib/ruby-sdl-ffi/sdl/video.rb | 8 +- 2 files changed, 126 insertions(+), 93 deletions(-) diff --git a/lib/ruby-sdl-ffi/sdl/mac.rb b/lib/ruby-sdl-ffi/sdl/mac.rb index 64bc12d..a8bfbc4 100644 --- a/lib/ruby-sdl-ffi/sdl/mac.rb +++ b/lib/ruby-sdl-ffi/sdl/mac.rb @@ -42,96 +42,89 @@ module SDL::Mac - def self.inspect_menu( menu, indent="" ) - puts "%s-%s (%s \"%s\", %d items)"%[indent, menu, menu.classname, - menu.title, menu.length] - menu.each do |ob| - if ob.hasSubmenu? - inspect_menu( ob.submenu, indent+" " ) - else - puts "%s -%s (%s \"%s\")"%[indent, ob, ob.classname, ob.title] - end + class << self + + def make_menus( app_name ) + ptr = FFI.find_type(:pointer) + + nsapp = Cocoa.NSApp + menubar = Cocoa::NSMenu.new.initWithTitle("AMainMenu") + nsapp.msg( "setMainMenu:", ptr, menubar ) + + remove_bold_menu( nsapp, menubar ) + make_app_menu( menubar, app_name ) + make_window_menu( nsapp, menubar ) + + nil + end + + private + + # Hack to remove the bold "ruby" menu (aka the "Apple" menu). + # It's a ghost menu, it haunts us but can't be modified. + def remove_bold_menu( nsapp, menubar ) + item = Cocoa::NSMenuItem.new.initWithTitle("AppleMenu") + menu = Cocoa::NSMenu.new.initWithTitle("AppleMenu") + item.submenu = menu + + nsapp.msg("setAppleMenu:", FFI.find_type(:pointer), menu) + menubar.addItem(item) + menubar.removeItem(item) + + item.release + menu.release + end + + + # Create the main menu with the app's name (Hide, Quit, etc.) + def make_app_menu( menubar, app_name ) + item = Cocoa::NSMenuItem.new.initWithTitle( app_name ) + menu = Cocoa::NSMenu.new.initWithTitle( app_name ) + item.submenu = menu + menubar.addItem(item) + + menu.addItemWithTitle("Hide #{app_name}", "hide:") + menu.addItemWithTitle("Hide Others", "hideOtherApplications:") + menu.addItemWithTitle("Show All", "unhideAllApplications:") + + # Can't get the Quit menu item to work right yet. + #menu.addItem( Cocoa::NSMenuItem.separatorItem ) + #menu.addItemWithTitle("Quit #{app_name}", "terminate:") + + item.release + menu.release + end + + + # Create the "Window" menu (Minimize, etc.) + def make_window_menu( nsapp, menubar ) + ptr = FFI.find_type(:pointer) + + item = Cocoa::NSMenuItem.new.initWithTitle("Window") + menu = Cocoa::NSMenu.new.initWithTitle("Window") + item.submenu = menu + menubar.addItem(item) + nsapp.msg("setWindowsMenu:", ptr, menu) + + menu.addItemWithTitle("Minimize", "performMiniaturize:") + + item.release + menu.release end - end - - - def self.make_menus( new_title ) - ptr = FFI.find_type(:pointer) - - nsapp = Cocoa.NSApp - - menubar = Cocoa::NSMenu.new.initWithTitle("AMainMenu") - nsapp.msg( "setMainMenu:", ptr, menubar ) - - - # "Apple" menu - actually the "ruby" menu, supposedly. - appledummy = ObjC::NSMenuItem.new.initWithTitle("Apple") - applemenu = Cocoa::NSMenu.new.initWithTitle("Apple") - appledummy.submenu = applemenu - menubar.addItem(appledummy) - nsapp.msg( "setAppleMenu:", ptr, applemenu ) - - appledummy2 = ObjC::NSMenuItem.new.initWithTitle("Apple Item") - applemenu.addItem( appledummy2 ) - - - # A new menu with the app's name - appdummy = ObjC::NSMenuItem.new.initWithTitle(new_title) - appmenu = Cocoa::NSMenu.new.initWithTitle( new_title ) - appdummy.submenu = appmenu - menubar.msg( "insertItem:atIndex:", ptr, appdummy, FFI.find_type(:int), 0 ) - appdummy.release - - appdummy2 = ObjC::NSMenuItem.new.initWithTitle("App Item") - appmenu.addItem( appdummy2 ) - - - # Window menu - windowdummy = ObjC::NSMenuItem.new.initWithTitle("Window") - windowmenu = Cocoa::NSMenu.new.initWithTitle("Window") - windowdummy.submenu = windowmenu - menubar.addItem( windowdummy ) - nsapp.msg( "setWindowsMenu:", ptr, windowmenu ) - windowdummy.release - - windowdummy2 = ObjC::NSMenuItem.new.initWithTitle("Window Item") - windowmenu.addItem( windowdummy2 ) - - inspect_menu( menubar ) - - nil - end - - - # Sets the application menu title on Mac OS X, i.e. the bold word - # in the application menu at the top of the screen. - # - def self.set_app_title( new_title ) - ptr = FFI.find_type(:pointer) - long = FFI.find_type(:long) - - nsapp = Cocoa.NSApp - - menubar = nsapp.msg( "mainMenu" ) - inspect_menu( menubar ) - - appdummy = menubar[0] - appmenu = appdummy.submenu - appmenu.title = new_title - inspect_menu( appmenu ) - menubar.msg( "itemChanged:", ptr, appdummy ) - # windowdummy = menubar.[1] - # windowmenu = windowdummy.submenu - # windowmenu.title = new_title - # inspect_menu( windowmenu ) - menubar.msg( "update" ) + def inspect_menu( menu, indent="" ) + puts "%s-%s (%s \"%s\", %d items)"%[indent, menu, menu.classname, + menu.title, menu.length] + menu.each do |ob| + if ob.hasSubmenu? + inspect_menu( ob.submenu, indent+" " ) + else + puts "%s -%s (%s \"%s\")"%[indent, ob, ob.classname, ob.title] + end + end + end - # menubar.msg( "removeItemAtIndex:", long, 0 ) - # inspect_menu( menubar ) - - nil end @@ -171,7 +164,7 @@ def self.load_nib( nibpath = :default ) count = toplevel.msg_int("count") count.times do |i| ob = toplevel.msg("objectAtIndex:", FFI.find_type(:long), i) - case ob.classname + case ob.nsclassname when "NSMenu"; menubar = Cocoa::NSMenu(ob.pointer) when "NSApplication"; app = ob end @@ -196,16 +189,23 @@ module ObjC class NSObject < NiceFFI::OpaqueStruct - # define msg, msg_ptr, msg_str, msg_int, msg_bool + def self.nsclassname; name.split("::")[-1]; end + + # define msg, msg_ptr, msg_str, msg_int, msg_bool (and class methods) ["", "_ptr", "_str", "_int", "_bool"].each do |suffix| module_eval(" def msg#{suffix}( message, *args ) ObjC.msgSend#{suffix}( @pointer, message, *args ) + end + + def self.msg#{suffix}( message, *args ) + ObjC.msgSend#{suffix}( ObjC.NSClass(self.nsclassname), + message, *args ) end") end def inspect; msg_str("description").to_s; end - def classname; ObjC.object_getClassName(@pointer); end + def nsclassname; ObjC.object_getClassName(@pointer); end def release; msg("release"); end end @@ -337,6 +337,26 @@ def addItem( item ) self end + def addItemWithTitle( title, action=nil, keyEquivalent="" ) + ptr = FFI.find_type(:pointer) + action = ObjC.sel(action) if action.is_a? String + item = msg_ptr( "addItemWithTitle:action:keyEquivalent:", + ptr, ObjC::NSString(title), + ptr, action, + ptr, ObjC::NSString(keyEquivalent)) + NSMenuItem.new(item) + end + + def removeItem( item ) + msg("removeItem:", FFI.find_type(:pointer), item) + self + end + + def removeItemAtIndex( index ) + msg("removeItemAtIndex:", FFI.find_type(:long), index) + self + end + def length msg_int( "numberOfItems" ) end @@ -356,6 +376,10 @@ def self.NSMenu( *args ) class NSMenuItem < ObjC::NSObject + def self.separatorItem + new( msg_ptr("separatorItem") ) + end + def initialize( *args ) if args.empty? super( ObjC::NSClass("NSMenuItem").msg_ptr("alloc") ) @@ -366,6 +390,7 @@ def initialize( *args ) def initWithTitle( title, action=nil, keyEquivalent="" ) ptr = FFI.find_type(:pointer) + action = ObjC.sel(action) if action.is_a? String msg( "initWithTitle:action:keyEquivalent:", ptr, ObjC::NSString(title), ptr, action, @@ -407,6 +432,14 @@ def self.NSMenuItem( *args ) NSNibTopLevelObjects = ObjC::NSString( ObjC::NSString(self.vNSNibTopLevelObjects).to_s ) + NSAlphaShiftKeyMask = 1 << 16 + NSShiftKeyMask = 1 << 17 + NSControlKeyMask = 1 << 18 + NSAlternateKeyMask = 1 << 19 + NSCommandKeyMask = 1 << 20 + NSNumericPadKeyMask = 1 << 21 + NSHelpKeyMask = 1 << 22 + NSFunctionKeyMask = 1 << 23 end diff --git a/lib/ruby-sdl-ffi/sdl/video.rb b/lib/ruby-sdl-ffi/sdl/video.rb index fa8b387..e7be99d 100644 --- a/lib/ruby-sdl-ffi/sdl/video.rb +++ b/lib/ruby-sdl-ffi/sdl/video.rb @@ -277,10 +277,10 @@ def self.release( pointer ) def self.SetVideoMode( *args ) result = __SetVideoMode(*args) if defined? SDL::Mac - SDL::Mac::HIServices.make_current_front() - SDL::Mac.load_nib - # SDL::Mac.make_menus("My App") - # SDL::Mac.set_app_title("My App") + #SDL::Mac::ObjC.msgSend(SDL::Mac::Cocoa.NSApp, "finishLaunching") + SDL::Mac::HIServices.make_current_front + # SDL::Mac.load_nib + SDL::Mac.make_menus("Rubygame Demo") end return result end