gi-gtkosxapplication-2.0.17: GtkosxApplication bindings

CopyrightWill Thompson Iñaki García Etxebarria and Jonas Platte
LicenseLGPL-2.1
MaintainerIñaki García Etxebarria
Safe HaskellNone
LanguageHaskell2010

GI.GtkosxApplication.Objects.Application

Contents

Description

Exposes to the Gtk+ program important functions of OS X's NSApplication class for use by Gtk+ applications running with the quartz Gdk backend and provides addtional functions for integrating a Gtk+ program into the OS X user environment.

Using GtkosxApplication is pretty simple. First, create an instance at startup:

C code

GtkosxApplication *theApp = g_object_new(GTKOSX_TYPE_APPLICATION, NULL);

Do this early in your program, shortly after you run > >gtk_init()

Don't forget to guard it, and all other calls into the library, with > >#ifdef MAC_INTEGRATION

You don't want your Linux users' builds failing because of this. The application object is a singleton, so you can call g_object_new as often as you like. You'll always get the same pointer back. There's no need to pass it around as an argument. Do note that all of the GtkosxApplication functions take theApp as an argument, even if they don't use it. This seems silly in C, and perhaps it is, but it's needed to make the Python binding logic recognize that they're class methods.

Just having the application object created will get you some benefits, like having the Quit menu item in the dock menu work. But you'll obviously want more. So the next place to visit is your main window code. If you have a simple application, you might be constructing the menu by hand, but you're more likely to be using GtkBuilder. In either case, you need to get a pointer to the menubar. If you're building by hand, you've already got it lying around because you needed it to add the menus to. With GtkBuilder, you need to ask the GtkUIManager for a pointer. Once everything is more-or-less set up on the Gtk+ side, you need only hide the menu and call gtkosx_application_set_main_menu(). Here's an example with GtkBuilder:

Setting the MenuBar

C code

 GtkUIManager *mgr = gtk_ui_manager_new();
 GtkosxApplication *theApp = g_object_new(GTKOSX_TYPE_APPLICATION, NULL);
 ...
 mergeid = gtk_ui_manager_add_ui_from_file(mgr, "src/testui.xml", &err);
 ...
 menubar = gtk_ui_manager_get_widget(mgr, "/menubar");
 gtk_widget_hide (menubar);
 gtkosx_application_set_menu_bar(theApp, GTK_MENU_SHELL(menubar));

There are a couple of wrinkles, though, if you use accelerators. First off, there are two event paths for accelerators: Quartz, where the keystroke is processed by OS X and the menu item action event is placed on the event queue by OS X, or Gtk, where the accelerator key event is passed through to Gtk to recognize. This is controlled by applicationSetUseQuartzAccelerators (you can test the value with applicationUseQuartzAccelerators), and the default is to use Quartz handling. This has two advantages:

  • It works without any extra steps
  • It changes stock accelerators (like Ctrl-O for open file) to

the stock OS X keyEquivalent (Cmd-O in that case).

If you need to use Gtk+ keyboard accelerator handling *and* you're using GtkMenuItems instead of GtkActions, you'll need to connect a special handler as shown in the following example: == Enabling Accelerators on Hidden Menus

C code

static gboolean
can_activate_cb(GtkWidget* widget, guint signal_id, gpointer data)
{
  return gtk_widget_is_sensitive(widget);
}
...
  g_signal_connect(menubar, "can-activate-accel",
                   G_CALLBACK(can_activate_cb), NULL);

The next task to make your application appear more normal for Mac users is to move some menu items from their normal Gtk locations to the so-called "App" menu. That's the menu all the way at the left of the menubar that has the currently-running application's name. There are 3 menu items that normally go there:

  • Help|About
  • Edit|Preferences
  • File|Quit

File|Quit is a special case, because OS X handles it itself and automatically includes it, so the only thing you need do is hide it on the File menu so that it doesn't show up twice: > >gtk_widget_hide(GTK_WIDGET(file_quit_menu_item));

The other two must be moved in code, and there are two functions for doing that. The first one creates "goups", which is just an easy way to manage separators, and the second adds the actual menu items to the groups. Here's an example: > > GtkosxApplicationMenuGroup *group; > GtkMenuItem *about_item, *preferences_item; > about_item = gtk_ui_manager_get_widget(mgr, "menubarHelp/About"); > preferences_item = gtk_ui_manager_get_widget(mgr, "menubarEdit/Preferences"); > > group = gtkosx_application_add_app_menu_group (theApp); > gtkosx_application_add_app_menu_item (theApp, group, > GTK_MENU_ITEM (about_item)); > > group = gtkosx_application_add_app_menu_group (theApp); > gtkosx_application_add_app_menu_item (theApp, group, > GTK_MENU_ITEM (preferences_item));

Once we have everything set up for as many windows as we're going to open before we call gtk_main_loop(), we need to tell OS X that we're ready: > >gtkosx_application_ready(theApp);

If you add other windows later, you must do everything above for each one's menubar. Most of the time the internal notifictations will ensure that the GtkosxApplication is able to keep everything in sync. However, if you at any time disconnect or block signals and change the menu (perhaps because of a context change within a window, as with changing pages in a GtkNotebook) you need to call > >gtkosx_application_sync_menubar(theApp)

N.B.: One GtkMenu function, menuReorderChild, changes the menu appearance without emitting a signal, so if you use that function in your code you'll need to call applicationSyncMenubar afterwards.

Dock Support

The dock is that bar of icons that normally lives at the bottom of the display on a Mac (though it can be moved to one of the other sides; this author likes his on the left, which is where it was originally on a NeXT). Each running application has a "dock tile", an icon on the dock. Users can, if they like, add application (or document) icons to the dock, and those can be used to launch the application. Apple allows limited customization of the dock tile, and GtkosxApplication has an interface for adding to the dock's menu and for changing the icon that is displayed for the the application. GtkosxApplication also provides an interface to AttentionRequest, which bounces the dock tile if the application doesn't have focus. You might want to do that at the end of a long task so that the user will know that it's finished if she's switched to another application while she waits for yours. They're all pretty simple, so you can just read the details below.

Bundle Support

The last feature to which GtkosxApplication provides an interface is the bundle. Normally in OS X, graphical applications are packaged along with their non-standard dependencies and their resources (graphical elements, translations, and such) in special directory structures called "bundles". To easily package your Gtk+ application, have a look at gtk-mac-bundler, also available from the Gtk-OSX project.

OS X provides a variety of functions pertaining to bundles, most of which are not likely to interest someone porting a Gtk+ application. GtkosxApplication has wrapped a few that might be:

The first three just get a UTF8-encoded path. An interesting note is that they'll return the path to the executable or the folder it's in regardless of whether it's actually in a bundle. To find out if one is actually dealing with a bundle, applicationGetBundleId will return "" if it can't find the key CFBundleIdentifier from the bundle's Info.plist -- which it won't if the application isn't in a bundle or wasn't launched by opening the bundle. (In other words, even if you have your application installed in Foo.app, if you launch it from the command line as > >$ Foo.appContentsMacOS/Foo

the Info.plist won't have been opened and applicationGetBundleId will return "". Of course, it will also return "" if you didn't set CFBundleIdentifier in the Info.plist, so make sure that you do!

The last function, applicationGetBundleInfo, will return the value associated with an arbitrary key from Info.plist as long as that value is a string. If it isn't, then the function returns a null string ("").

Notifications

Finally, notice the signals. These are emitted in response to the indicated OS X notifications. Except for NSApplicationBlockTermination, most programs won't need to do anything with them. NSApplicationBlockTermination is telling you that OS X is planning to shut down your program. If you have any cleanup to do (like saving open files), or if you want to ask the user if it's OK, you should connect to the signal and do your cleanup. Your handler can return True to prevent the application from quitting.

Synopsis

Exported types

newtype Application Source #

Memory-managed wrapper type.

Constructors

Application (ManagedPtr Application) 
Instances
Eq Application Source # 
Instance details

Defined in GI.GtkosxApplication.Objects.Application

GObject Application Source # 
Instance details

Defined in GI.GtkosxApplication.Objects.Application

Methods

gobjectType :: IO GType

IsGValue Application Source #

Convert Application to and from GValue with toGValue and fromGValue.

Instance details

Defined in GI.GtkosxApplication.Objects.Application

Methods

toGValue :: Application -> IO GValue

fromGValue :: GValue -> IO Application

HasParentTypes Application Source # 
Instance details

Defined in GI.GtkosxApplication.Objects.Application

type ParentTypes Application Source # 
Instance details

Defined in GI.GtkosxApplication.Objects.Application

type ParentTypes Application = Object ': ([] :: [Type])

class (GObject o, IsDescendantOf Application o) => IsApplication o Source #

Type class for types which can be safely cast to Application, for instance with toApplication.

Instances
(GObject o, IsDescendantOf Application o) => IsApplication o Source # 
Instance details

Defined in GI.GtkosxApplication.Objects.Application

toApplication :: (MonadIO m, IsApplication o) => o -> m Application Source #

Cast to Application, for types for which this is known to be safe. For general casts, use castTo.

Methods

Overloaded methods

attentionRequest

applicationAttentionRequest :: (HasCallStack, MonadIO m, IsApplication a) => a -> ApplicationAttentionType -> m Int32 Source #

No description available in the introspection data.

cancelAttentionRequest

applicationCancelAttentionRequest :: (HasCallStack, MonadIO m, IsApplication a) => a -> Int32 -> m () Source #

No description available in the introspection data.

get

applicationGet Source #

Arguments

:: (HasCallStack, MonadIO m) 
=> m Application

Returns: the singleton application object.

No description available in the introspection data.

getBundleId

applicationGetBundleId :: (HasCallStack, MonadIO m) => m Text Source #

No description available in the introspection data.

getBundleInfo

applicationGetBundleInfo :: (HasCallStack, MonadIO m) => Text -> m Text Source #

No description available in the introspection data.

getBundlePath

applicationGetBundlePath :: (HasCallStack, MonadIO m) => m Text Source #

No description available in the introspection data.

getExecutablePath

applicationGetExecutablePath :: (HasCallStack, MonadIO m) => m Text Source #

No description available in the introspection data.

getResourcePath

applicationGetResourcePath :: (HasCallStack, MonadIO m) => m Text Source #

No description available in the introspection data.

insertAppMenuItem

applicationInsertAppMenuItem :: (HasCallStack, MonadIO m, IsApplication a, IsWidget b) => a -> b -> Int32 -> m () Source #

No description available in the introspection data.

ready

applicationReady :: (HasCallStack, MonadIO m, IsApplication a) => a -> m () Source #

No description available in the introspection data.

setAboutItem

applicationSetAboutItem :: (HasCallStack, MonadIO m, IsApplication a, IsWidget b) => a -> b -> m () Source #

No description available in the introspection data.

setDockIconPixbuf

applicationSetDockIconPixbuf :: (HasCallStack, MonadIO m, IsApplication a, IsPixbuf b) => a -> b -> m () Source #

No description available in the introspection data.

setDockIconResource

applicationSetDockIconResource :: (HasCallStack, MonadIO m, IsApplication a) => a -> Text -> Text -> Text -> m () Source #

No description available in the introspection data.

setDockMenu

applicationSetDockMenu :: (HasCallStack, MonadIO m, IsApplication a, IsMenuShell b) => a -> b -> m () Source #

No description available in the introspection data.

setHelpMenu

applicationSetHelpMenu :: (HasCallStack, MonadIO m, IsApplication a, IsMenuItem b) => a -> b -> m () Source #

No description available in the introspection data.

setMenuBar

applicationSetMenuBar :: (HasCallStack, MonadIO m, IsApplication a, IsMenuShell b) => a -> b -> m () Source #

No description available in the introspection data.

setUseQuartzAccelerators

applicationSetUseQuartzAccelerators Source #

Arguments

:: (HasCallStack, MonadIO m, IsApplication a) 
=> a

self: The GtkosxApplication pointer.

-> Bool

useQuartzAccelerators: Gboolean

-> m () 

Set quartz accelerator handling; TRUE (default) uses quartz; FALSE uses Gtk+. Quartz accelerator handling is required for normal OS X accelerators (e.g., command-q to quit) to work.

setWindowMenu

applicationSetWindowMenu :: (HasCallStack, MonadIO m, IsApplication a, IsMenuItem b) => a -> b -> m () Source #

No description available in the introspection data.

syncMenubar

applicationSyncMenubar :: (HasCallStack, MonadIO m, IsApplication a) => a -> m () Source #

No description available in the introspection data.

useQuartzAccelerators

applicationUseQuartzAccelerators Source #

Arguments

:: (HasCallStack, MonadIO m, IsApplication a) 
=> a

self: The GtkosxApplication pointer.

-> m Bool

Returns: a gboolean

Are we using Quartz or Gtk+ accelerator handling?

Signals

nSApplicationBlockTermination

type ApplicationNSApplicationBlockTerminationCallback = IO Bool Source #

No description available in the introspection data.

type C_ApplicationNSApplicationBlockTerminationCallback = Ptr () -> Ptr () -> IO CInt Source #

Type for the callback on the (unwrapped) C side.

afterApplicationNSApplicationBlockTermination :: (IsApplication a, MonadIO m) => a -> ApplicationNSApplicationBlockTerminationCallback -> m SignalHandlerId Source #

Connect a signal handler for the NSApplicationBlockTermination signal, to be run after the default handler. When overloading is enabled, this is equivalent to

after application #NSApplicationBlockTermination callback

onApplicationNSApplicationBlockTermination :: (IsApplication a, MonadIO m) => a -> ApplicationNSApplicationBlockTerminationCallback -> m SignalHandlerId Source #

Connect a signal handler for the NSApplicationBlockTermination signal, to be run before the default handler. When overloading is enabled, this is equivalent to

on application #NSApplicationBlockTermination callback

nSApplicationDidBecomeActive

type ApplicationNSApplicationDidBecomeActiveCallback = IO () Source #

No description available in the introspection data.

type C_ApplicationNSApplicationDidBecomeActiveCallback = Ptr () -> Ptr () -> IO () Source #

Type for the callback on the (unwrapped) C side.

afterApplicationNSApplicationDidBecomeActive :: (IsApplication a, MonadIO m) => a -> ApplicationNSApplicationDidBecomeActiveCallback -> m SignalHandlerId Source #

Connect a signal handler for the NSApplicationDidBecomeActive signal, to be run after the default handler. When overloading is enabled, this is equivalent to

after application #NSApplicationDidBecomeActive callback

onApplicationNSApplicationDidBecomeActive :: (IsApplication a, MonadIO m) => a -> ApplicationNSApplicationDidBecomeActiveCallback -> m SignalHandlerId Source #

Connect a signal handler for the NSApplicationDidBecomeActive signal, to be run before the default handler. When overloading is enabled, this is equivalent to

on application #NSApplicationDidBecomeActive callback

nSApplicationOpenFile

type ApplicationNSApplicationOpenFileCallback = Text -> IO Bool Source #

No description available in the introspection data.

type C_ApplicationNSApplicationOpenFileCallback = Ptr () -> CString -> Ptr () -> IO CInt Source #

Type for the callback on the (unwrapped) C side.

afterApplicationNSApplicationOpenFile :: (IsApplication a, MonadIO m) => a -> ApplicationNSApplicationOpenFileCallback -> m SignalHandlerId Source #

Connect a signal handler for the NSApplicationOpenFile signal, to be run after the default handler. When overloading is enabled, this is equivalent to

after application #NSApplicationOpenFile callback

onApplicationNSApplicationOpenFile :: (IsApplication a, MonadIO m) => a -> ApplicationNSApplicationOpenFileCallback -> m SignalHandlerId Source #

Connect a signal handler for the NSApplicationOpenFile signal, to be run before the default handler. When overloading is enabled, this is equivalent to

on application #NSApplicationOpenFile callback

nSApplicationWillResignActive

type ApplicationNSApplicationWillResignActiveCallback = IO () Source #

No description available in the introspection data.

type C_ApplicationNSApplicationWillResignActiveCallback = Ptr () -> Ptr () -> IO () Source #

Type for the callback on the (unwrapped) C side.

afterApplicationNSApplicationWillResignActive :: (IsApplication a, MonadIO m) => a -> ApplicationNSApplicationWillResignActiveCallback -> m SignalHandlerId Source #

Connect a signal handler for the NSApplicationWillResignActive signal, to be run after the default handler. When overloading is enabled, this is equivalent to

after application #NSApplicationWillResignActive callback

onApplicationNSApplicationWillResignActive :: (IsApplication a, MonadIO m) => a -> ApplicationNSApplicationWillResignActiveCallback -> m SignalHandlerId Source #

Connect a signal handler for the NSApplicationWillResignActive signal, to be run before the default handler. When overloading is enabled, this is equivalent to

on application #NSApplicationWillResignActive callback

nSApplicationWillTerminate

type ApplicationNSApplicationWillTerminateCallback = IO () Source #

No description available in the introspection data.

type C_ApplicationNSApplicationWillTerminateCallback = Ptr () -> Ptr () -> IO () Source #

Type for the callback on the (unwrapped) C side.

afterApplicationNSApplicationWillTerminate :: (IsApplication a, MonadIO m) => a -> ApplicationNSApplicationWillTerminateCallback -> m SignalHandlerId Source #

Connect a signal handler for the NSApplicationWillTerminate signal, to be run after the default handler. When overloading is enabled, this is equivalent to

after application #NSApplicationWillTerminate callback

onApplicationNSApplicationWillTerminate :: (IsApplication a, MonadIO m) => a -> ApplicationNSApplicationWillTerminateCallback -> m SignalHandlerId Source #

Connect a signal handler for the NSApplicationWillTerminate signal, to be run before the default handler. When overloading is enabled, this is equivalent to

on application #NSApplicationWillTerminate callback