[banshee] OSX: Move to cocoa API (bgo#677866)
- From: Bertrand Lorentz <blorentz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [banshee] OSX: Move to cocoa API (bgo#677866)
- Date: Wed, 27 Jun 2012 20:01:41 +0000 (UTC)
commit 26a176399705748c01ddd7e1a4be7ac50908328a
Author: Timo DÃrr <timo latecrew de>
Date: Mon Jun 11 16:12:14 2012 +0200
OSX: Move to cocoa API (bgo#677866)
This commit moves from the ige-/gtk-mac-integration API to the
GtkOSXApplication API (which is still provided by the same library
called 'gtk-mac-integration', not to be confused with the API name).
This means banshee no longer uses any OS X carbon functions (which are
deprecated), but cocoa only. The Banshee.Osx backend also now fully
relies on gtk-mac-integration as interface to OS X specific functions
and does no longer contain own DllImports into OS X core framework.
This drops the support for closing the banshee main window (via
Cmd+Close) since GtkOSXApplication does not handle this properly right
now. Banshee is a single-window only application at the moment, so this
shouldn't be a usecase anyway.
Signed-off-by: Bertrand Lorentz <bertrand lorentz gmail com>
src/Backends/Banshee.Osx/Banshee.Osx.csproj | 25 +-
.../Banshee.Osx/Banshee.OsxBackend/OsxService.cs | 149 ++---
src/Backends/Banshee.Osx/Makefile.am | 15 +-
.../OsxIntegration.Framework/AppleEvent.cs | 41 --
.../OsxIntegration.Framework/ApplicationEvents.cs | 219 ------
.../Banshee.Osx/OsxIntegration.Framework/Carbon.cs | 692 -------------------
.../OsxIntegration.Framework/CoreFoundation.cs | 95 ---
.../OsxIntegration.Framework/HIToolbox.cs | 713 --------------------
.../OsxIntegration.Framework/NavDialog.cs | 513 --------------
.../GtkOsxApplication.cs | 103 +++
.../Banshee.Osx/OsxIntegration.Ige/IgeMacMenu.cs | 74 --
.../OsxIntegration.Ige/IgeMacMenuGroup.cs | 54 --
src/Backends/Banshee.Osx/Resources/osx_accel_map | 81 +++
.../Resources/core-ui-actions-layout.xml | 2 +-
14 files changed, 261 insertions(+), 2515 deletions(-)
---
diff --git a/src/Backends/Banshee.Osx/Banshee.Osx.csproj b/src/Backends/Banshee.Osx/Banshee.Osx.csproj
index 5ef2d12..4e58bf9 100644
--- a/src/Backends/Banshee.Osx/Banshee.Osx.csproj
+++ b/src/Backends/Banshee.Osx/Banshee.Osx.csproj
@@ -20,7 +20,6 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
- <WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
<OutputPath>..\..\..\bin</OutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@@ -29,7 +28,6 @@
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
- <WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
<OutputPath>..\..\..\bin</OutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@@ -63,31 +61,27 @@
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
- <Reference Include="gtk-sharp">
- <SpecificVersion>False</SpecificVersion>
- </Reference>
+ <Reference Include="gtk-sharp" />
<Reference Include="Mono.Posix">
- <SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..bin\Mono.Posix.dll</HintPath>
</Reference>
<Reference Include="MonoMac, Version=0.0.0.0, Culture=neutral" />
+ <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+ <Private>False</Private>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Banshee.OsxBackend\HardwareManager.cs" />
<Compile Include="Banshee.OsxBackend\OsxService.cs" />
- <Compile Include="OsxIntegration.Ige\IgeMacMenu.cs" />
- <Compile Include="OsxIntegration.Ige\IgeMacMenuGroup.cs" />
- <Compile Include="OsxIntegration.Framework\AppleEvent.cs" />
- <Compile Include="OsxIntegration.Framework\ApplicationEvents.cs" />
- <Compile Include="OsxIntegration.Framework\Carbon.cs" />
- <Compile Include="OsxIntegration.Framework\CoreFoundation.cs" />
- <Compile Include="OsxIntegration.Framework\HIToolbox.cs" />
- <Compile Include="OsxIntegration.Framework\NavDialog.cs" />
+ <Compile Include="OsxIntegration.GtkOsxApplication\GtkOsxApplication.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Banshee.Osx.addin.xml">
<LogicalName>Banshee.Osx.addin.xml</LogicalName>
</EmbeddedResource>
+ <EmbeddedResource Include="Resources\osx_accel_map">
+ <LogicalName>osx_accel_map</LogicalName>
+ </EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
@@ -106,6 +100,7 @@
</MonoDevelop>
</ProjectExtensions>
<ItemGroup>
- <Folder Include="OsxIntegration.Ige\" />
+ <Folder Include="OsxIntegration.GtkOsxApplication\" />
+ <Folder Include="Resources\" />
</ItemGroup>
</Project>
diff --git a/src/Backends/Banshee.Osx/Banshee.OsxBackend/OsxService.cs b/src/Backends/Banshee.Osx/Banshee.OsxBackend/OsxService.cs
index 432e208..57ae1cd 100644
--- a/src/Backends/Banshee.Osx/Banshee.OsxBackend/OsxService.cs
+++ b/src/Backends/Banshee.Osx/Banshee.OsxBackend/OsxService.cs
@@ -30,14 +30,16 @@
using System;
using System.Collections;
+using System.IO;
+using System.Reflection;
using Gtk;
using Mono.Unix;
using Banshee.ServiceStack;
using Banshee.Gui;
-using OsxIntegration.Ige;
-using OsxIntegration.Framework;
+using OsxIntegration.GtkOsxApplication;
+using Hyena;
namespace Banshee.OsxBackend
{
@@ -45,8 +47,7 @@ namespace Banshee.OsxBackend
{
private GtkElementsService elements_service;
private InterfaceActionService interface_action_service;
- private uint ui_manager_id;
- private bool disposed;
+ private string accel_map_filename = "osx_accel_map";
void IExtensionService.Initialize ()
{
@@ -83,110 +84,82 @@ namespace Banshee.OsxBackend
private void Initialize ()
{
- elements_service.PrimaryWindow.WindowStateEvent += OnWindowStateEvent;
-
- // add close action
- interface_action_service.GlobalActions.Add (new ActionEntry [] {
- new ActionEntry ("CloseAction", Stock.Close,
- Catalog.GetString ("_Close"), "<Control>W",
- Catalog.GetString ("Close"), CloseWindow)
- });
-
- // merge close menu item
- ui_manager_id = interface_action_service.UIManager.AddUiFromString (@"
- <ui>
- <menubar name=""MainMenu"">
- <menu name=""MediaMenu"" action=""MediaMenuAction"">
- <placeholder name=""ClosePlaceholder"">
- <menuitem name=""Close"" action=""CloseAction""/>
- </placeholder>
- </menu>
- </menubar>
- </ui>
- ");
-
- RegisterCloseHandler ();
- ConfigureOsxMainMenu ();
-
- IgeMacMenu.GlobalKeyHandlerEnabled = false;
-
- ApplicationEvents.Quit += (o, e) => {
- Banshee.ServiceStack.Application.Shutdown ();
- e.Handled = true;
- };
+ // load OS X specific key mappings, possibly overriding default mappings
+ // set in GlobalActions or $HOME/.config/banshee-1/gtk_accel_map
+ string accel_map = Paths.Combine (Paths.ApplicationData, accel_map_filename);
+ if (!File.Exists (accel_map)) {
+ // copy our template
+ CopyAccelMapToDataDir ();
+ }
+ Gtk.AccelMap.Load (accel_map);
- ApplicationEvents.Reopen += (o, e) => {
- SetWindowVisibility (true);
- e.Handled = true;
- };
+ ConfigureOsxMainMenu ();
}
public void Dispose ()
{
- if (disposed) {
- return;
- }
-
- elements_service.PrimaryWindowClose = null;
-
- interface_action_service.GlobalActions.Remove ("CloseAction");
- interface_action_service.UIManager.RemoveUi (ui_manager_id);
-
- disposed = true;
}
private void ConfigureOsxMainMenu ()
{
- IgeMacMenu.MenuBar = (MenuShell)interface_action_service.UIManager.GetWidget ("/MainMenu");
+ var osx_app = new GtkOsxApplication ();
- var ui = interface_action_service.UIManager;
-
- IgeMacMenu.QuitMenuItem = ui.GetWidget ("/MainMenu/MediaMenu/Quit") as MenuItem;
+ // remove the "Quit" item as this is auto-added by gtk-mac-integration to the AppMenu
+ var quit_item = ((MenuItem)interface_action_service.UIManager.GetWidget ( "/MainMenu/MediaMenu/Quit"));
+ if(quit_item != null) {
+ quit_item.Hide ();
+ }
- var group = IgeMacMenu.AddAppMenuGroup ();
- group.AddMenuItem (ui.GetWidget ("/MainMenu/HelpMenu/About") as MenuItem, null);
- group.AddMenuItem (ui.GetWidget ("/MainMenu/EditMenu/Preferences") as MenuItem, null);
- }
+ MenuShell shell = (MenuShell) interface_action_service.UIManager.GetWidget ("/MainMenu");
+ if (shell != null) {
+ osx_app.SetMenu (shell);
+ }
- private void RegisterCloseHandler ()
- {
- if (elements_service.PrimaryWindowClose == null) {
- elements_service.PrimaryWindowClose = () => {
- CloseWindow (null, null);
- return true;
- };
+ // place the "about" and "preferences" menu items into the OS X application menu
+ // as every OS X app uses this convention
+ var about_item = interface_action_service.UIManager.GetWidget ("/MainMenu/HelpMenu/About") as MenuItem;
+ if (about_item != null) {
+ osx_app.InsertIntoAppMenu (about_item, 0);
}
- }
- private void CloseWindow (object o, EventArgs args)
- {
- SetWindowVisibility (false);
- }
+ // place a separator between the About and the Preferences dialog
+ var separator = new SeparatorMenuItem ();
+ osx_app.InsertIntoAppMenu (separator, 1);
- private void SetCloseMenuItemSensitivity (bool sensitivity)
- {
- ((MenuItem)interface_action_service.UIManager.GetWidget (
- "/MainMenu/MediaMenu/ClosePlaceholder/Close")).Sensitive = sensitivity;
- }
+ var preferences_item = interface_action_service.UIManager.GetWidget ("/MainMenu/EditMenu/Preferences") as MenuItem;
+ if (preferences_item != null) {
+ osx_app.InsertIntoAppMenu (preferences_item, 2);
+ }
- private void SetWindowVisibility (bool visible)
- {
- SetCloseMenuItemSensitivity (visible);
- if (elements_service.PrimaryWindow.Visible != visible) {
- elements_service.PrimaryWindow.ToggleVisibility ();
+ // remove unnecessary separator as we have moved the preferences item
+ var preferences_seperator = interface_action_service.UIManager.GetWidget ("/MainMenu/EditMenu/PreferencesSeparator") as SeparatorMenuItem;
+ if (preferences_seperator != null) {
+ preferences_seperator.Destroy ();
}
+
+ // actually performs the menu binding
+ osx_app.Ready ();
}
- private void OnWindowStateEvent (object obj, WindowStateEventArgs args)
+ /// <summary>
+ /// Copies the OSX specific accel map from embedded resource
+ /// to the user's data dir for future loading
+ /// </summary>
+ public void CopyAccelMapToDataDir ()
{
- switch (args.Event.NewWindowState) {
- case Gdk.WindowState.Iconified:
- SetCloseMenuItemSensitivity (false);
- break;
- case (Gdk.WindowState)0:
- SetCloseMenuItemSensitivity (true);
- break;
- }
+ byte[] buffer = new byte[1024];
+ var assembly = Assembly.GetExecutingAssembly ();
+ var accel_map = Paths.Combine (Paths.ApplicationData, accel_map_filename);
+
+ // perform the copy
+ using (Stream output = File.OpenWrite(accel_map)) {
+ using (Stream resource_stream = assembly.GetManifestResourceStream (accel_map_filename)) {
+ int bytes = -1;
+ while ((bytes = resource_stream.Read(buffer, 0, buffer.Length)) > 0) {
+ output.Write(buffer, 0, bytes);
+ }
+ }
+ }
}
string IService.ServiceName {
diff --git a/src/Backends/Banshee.Osx/Makefile.am b/src/Backends/Banshee.Osx/Makefile.am
index 9a5fb23..7ed14a1 100644
--- a/src/Backends/Banshee.Osx/Makefile.am
+++ b/src/Backends/Banshee.Osx/Makefile.am
@@ -7,16 +7,11 @@ INSTALL_DIR = $(BACKENDS_INSTALL_DIR)
SOURCES = \
Banshee.OsxBackend/HardwareManager.cs \
Banshee.OsxBackend/OsxService.cs \
- OsxIntegration.Framework/AppleEvent.cs \
- OsxIntegration.Framework/ApplicationEvents.cs \
- OsxIntegration.Framework/Carbon.cs \
- OsxIntegration.Framework/CoreFoundation.cs \
- OsxIntegration.Framework/HIToolbox.cs \
- OsxIntegration.Framework/NavDialog.cs \
- OsxIntegration.Ige/IgeMacMenu.cs \
- OsxIntegration.Ige/IgeMacMenuGroup.cs
-
-RESOURCES = Banshee.Osx.addin.xml
+ OsxIntegration.GtkOsxApplication/GtkOsxApplication.cs
+
+RESOURCES = \
+ Banshee.Osx.addin.xml \
+ Resources/osx_accel_map
EXTRA_BUNDLE = $(MONOMAC_ASSEMBLIES)
diff --git a/src/Backends/Banshee.Osx/OsxIntegration.GtkOsxApplication/GtkOsxApplication.cs b/src/Backends/Banshee.Osx/OsxIntegration.GtkOsxApplication/GtkOsxApplication.cs
new file mode 100644
index 0000000..60455fd
--- /dev/null
+++ b/src/Backends/Banshee.Osx/OsxIntegration.GtkOsxApplication/GtkOsxApplication.cs
@@ -0,0 +1,103 @@
+//
+// GtkOsxApplication.cs
+//
+// Author:
+// Timo DÃrr <timo latecrew de>
+//
+// Copyright 2012 Timo DÃrr
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Runtime.InteropServices;
+using Gtk;
+
+namespace OsxIntegration.GtkOsxApplication
+{
+ /// <summary>
+ /// Wraps the native GtkOsxApplicationBinding function to C# style API
+ /// </summary>
+ public class GtkOsxApplication
+ {
+ // Main application handle
+ private IntPtr theApp;
+
+ public GtkOsxApplication ()
+ {
+ IntPtr osx_app = gtk_osxapplication_get_type ();
+ theApp = new GLib.GType (osx_app).Val;
+
+ }
+
+ // Takes the Gtk.MenuShell and sets it as OS X application menu
+ public void SetMenu (MenuShell shell)
+ {
+ gtk_osxapplication_set_menu_bar (theApp, shell.Handle);
+ }
+
+ // Places MenuItems into the OS X specific "Application" menu
+ // (the menu right next to the Apple-Menu)
+ // It's convention on OS X to put the about and the preferences
+ // dialog in there
+ public void InsertIntoAppMenu (MenuItem item, int index)
+ {
+ gtk_osxapplication_insert_app_menu_item (theApp, item.Handle, index);
+ gtk_osxapplication_sync_menubar (theApp);
+ }
+
+ public void SetWindowMenu (MenuItem item)
+ {
+ gtk_osxapplication_set_window_menu (theApp, item.Handle);
+ gtk_osxapplication_sync_menubar (theApp);
+ }
+ public void Ready ()
+ {
+ gtk_osxapplication_ready (theApp);
+ }
+
+ // Bindings against native gtk-mac-integration/GtkOSXApplication
+ // which uses cocoa instead of deprecated carbon
+ // for documentation of these functions, see:
+ // http://gtk-osx.sourceforge.net/ige-mac-integration/GtkOSXApplication.html
+
+ [DllImport ("libgtkmacintegration.dylib")]
+ protected extern static IntPtr gtk_osxapplication_get_type ();
+
+ [DllImport ("libgtkmacintegration.dylib")]
+ protected extern static void gtk_osxapplication_ready (IntPtr app);
+
+ [DllImport ("libgtkmacintegration.dylib")]
+ protected extern static void gtk_osxapplication_set_menu_bar (IntPtr app, IntPtr menu_shell);
+
+ [DllImport ("libgtkmacintegration.dylib")]
+ protected extern static void gtk_osxapplication_insert_app_menu_item (IntPtr app, IntPtr menu_item, int index);
+
+ [DllImport ("libgtkmacintegration.dylib")]
+ protected extern static void gtk_osxapplication_sync_menubar (IntPtr app);
+
+ [DllImport ("libgtkmacintegration.dylib")]
+ protected extern static void gtk_osxapplication_set_dock_menu (IntPtr app, IntPtr menu_shell);
+
+ [DllImport ("libgtkmacintegration.dylib")]
+ protected extern static void gtk_osxapplication_set_window_menu (IntPtr app, IntPtr menu_item);
+
+ // TODO add more functions from GtkOsxApplication
+
+ }
+}
\ No newline at end of file
diff --git a/src/Backends/Banshee.Osx/Resources/osx_accel_map b/src/Backends/Banshee.Osx/Resources/osx_accel_map
new file mode 100644
index 0000000..e881a8b
--- /dev/null
+++ b/src/Backends/Banshee.Osx/Resources/osx_accel_map
@@ -0,0 +1,81 @@
+; Nereid GtkAccelMap rc-file -*- scheme -*-
+; OS X accelerator mappings
+
+;;; OS X Application menu
+(gtk_accel_path "<Actions>/Global/PreferencesAction" "<Primary>comma")
+(gtk_accel_path "<Actions>/Global/QuitAction" "<Primary>q")
+
+;;; MEDIA MENU
+
+; use CMD-O as in iTunes to import media
+(gtk_accel_path "<Actions>/Global/ImportAction" "<Primary>o")
+
+; open location (not present in itunes)
+(gtk_accel_path "<Actions>/Global/OpenLocationAction" "<Primary><Alt>o")
+
+; Close window (mac only)
+(gtk_accel_path "<Actions>/Global/CloseAction" "<Primary>w")
+
+; New Playlist
+(gtk_accel_path "<Actions>/Source/NewPlaylistAction" "<Primary>n")
+
+; New smart playlist
+(gtk_accel_path "<Actions>/Source/NewSmartPlaylistAction" "<Primary><Alt>n")
+
+; (gtk_accel_path "<Actions>/Track/TrackEditorAction" "e")
+; (gtk_accel_path "<Actions>/Track/RemoveTracksFromLibraryAction" "")
+
+
+;;; EDIT MENU
+
+; remove from library (don't delete from disk)
+(gtk_accel_path "<Actions>/Track/RemoveTracksAction" "BackSpace")
+
+; remove from disk drive (delete)
+(gtk_accel_path "<Actions>/Track/DeleteTracksFromDriveAction" "<Primary>BackSpace")
+
+; source properties (like show id3 info etc.)
+(gtk_accel_path "<Actions>/Track/TrackPropertiesAction" "<Primary>i")
+
+; select all
+(gtk_accel_path "<Actions>/Track/SelectAllAction" "<Primary>a")
+
+; select none
+(gtk_accel_path "<Actions>/Track/SelectNoneAction" "<Shift><Primary>a")
+
+; show/hide the browser
+(gtk_accel_path "<Actions>/BrowserView/BrowserVisibleAction" "<Primary>b")
+
+;;; VIEW MENU
+
+; this is alt-cmd-2 in iTunes but its window related
+(gtk_accel_path "<Actions>/View/ShowEqualizerAction" "<Primary>e")
+
+; fullscreen
+(gtk_accel_path "<Actions>/View/FullScreenAction" "<Control><Primary>f")
+
+
+;;; HELP MENU
+
+(gtk_accel_path "<Actions>/Global/UserHelp" "<Primary>question")
+
+
+;;; TRACK NAVIGATION
+
+; next track
+(gtk_accel_path "<Actions>/Playback/NextAction" "<Primary>Right")
+
+; previous track
+(gtk_accel_path "<Actions>/Playback/PreviousAction" "<Primary>Left")
+
+; show current track in file browser
+(gtk_accel_path "<Actions>/Track/OpenContainingFolderAction" "<Primary><Shift>r")
+
+; jump to current track
+(gtk_accel_path "<Actions>/Playback/JumpToPlayingTrackAction" "<Primary>l")
+
+; Play/Pause
+(gtk_accel_path "<Actions>/Playback/PlayPauseAction" "space")
+
+; stop when finished playing this track
+(gtk_accel_path "<Actions>/Playback/StopWhenFinishedAction" "<Shift>space")
diff --git a/src/Core/Banshee.ThickClient/Resources/core-ui-actions-layout.xml b/src/Core/Banshee.ThickClient/Resources/core-ui-actions-layout.xml
index 7908e13..290d330 100644
--- a/src/Core/Banshee.ThickClient/Resources/core-ui-actions-layout.xml
+++ b/src/Core/Banshee.ThickClient/Resources/core-ui-actions-layout.xml
@@ -76,7 +76,7 @@
<menuitem name="SourceProperties" action="SourcePropertiesAction"/>
<menuitem name="UnmapSource" action="UnmapSourceAction"/>
<menuitem name="TrackProperties" action="TrackPropertiesAction"/>
- <separator/>
+ <separator name="PreferencesSeparator" />
<menuitem name="Preferences" action="PreferencesAction"/>
</menu>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]