|
|
|
@@ -22,7 +22,9 @@
|
|
|
|
|
|
|
|
|
|
#include "gtkapplicationprivate.h"
|
|
|
|
|
#include "gtkbuilder.h"
|
|
|
|
|
#include "gtknative.h"
|
|
|
|
|
#import <Cocoa/Cocoa.h>
|
|
|
|
|
#include <gdk/macos/GdkMacosWindow.h>
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
@@ -126,6 +128,49 @@ G_DEFINE_TYPE (GtkApplicationImplQuartz, gtk_application_impl_quartz, GTK_TYPE_A
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
static GtkWindow*
|
|
|
|
|
gtk_application_impl_quartz_find_window(GdkMacosWindow *keyWindow)
|
|
|
|
|
{
|
|
|
|
|
GListModel *top_levels = gtk_window_get_toplevels ();
|
|
|
|
|
|
|
|
|
|
for (guint i = 0; i < g_list_model_get_n_items (top_levels); i++)
|
|
|
|
|
{
|
|
|
|
|
GtkWindow *win = (GtkWindow *) g_list_model_get_item (top_levels, i);
|
|
|
|
|
if (gtk_native_get_surface (GTK_NATIVE (win)) == (GdkSurface *) [keyWindow gdkSurface])
|
|
|
|
|
return win;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_application_impl_quartz_send_action (const gchar *action_name, SEL action)
|
|
|
|
|
{
|
|
|
|
|
static guint semaphore = 0;
|
|
|
|
|
NSWindow *keyWindow = [NSApp keyWindow];
|
|
|
|
|
|
|
|
|
|
if (keyWindow == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (semaphore == 0 && [keyWindow isKindOfClass:[GdkMacosWindow class]])
|
|
|
|
|
{
|
|
|
|
|
GtkWindow *window = gtk_application_impl_quartz_find_window ((GdkMacosWindow *) keyWindow);
|
|
|
|
|
|
|
|
|
|
if (window)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *focus = gtk_window_get_focus (window);
|
|
|
|
|
if (focus)
|
|
|
|
|
{
|
|
|
|
|
semaphore += 1;
|
|
|
|
|
gtk_widget_activate_action (focus, action_name, NULL);
|
|
|
|
|
semaphore -= 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
[NSApp sendAction:action to:nil from:NSApp];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* these exist only for accel handling */
|
|
|
|
|
static void
|
|
|
|
|
gtk_application_impl_quartz_hide (GSimpleAction *action,
|
|
|
|
@@ -151,12 +196,84 @@ gtk_application_impl_quartz_show_all (GSimpleAction *action,
|
|
|
|
|
[NSApp unhideAllApplications:NSApp];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GActionEntry gtk_application_impl_quartz_actions[] = {
|
|
|
|
|
static GActionEntry gtk_application_impl_quartz_internal_actions[] = {
|
|
|
|
|
{ "hide", gtk_application_impl_quartz_hide },
|
|
|
|
|
{ "hide-others", gtk_application_impl_quartz_hide_others },
|
|
|
|
|
{ "show-all", gtk_application_impl_quartz_show_all }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_application_impl_quartz_undo (GSimpleAction *action,
|
|
|
|
|
GVariant *parameter,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
gtk_application_impl_quartz_send_action ("text.undo", @selector(undo:));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_application_impl_quartz_redo (GSimpleAction *action,
|
|
|
|
|
GVariant *parameter,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
gtk_application_impl_quartz_send_action ("text.redo", @selector(redo:));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GActionEntry gtk_application_impl_quartz_text_actions[] = {
|
|
|
|
|
{ "undo", gtk_application_impl_quartz_undo },
|
|
|
|
|
{ "redo", gtk_application_impl_quartz_redo }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_application_impl_quartz_cut (GSimpleAction *action,
|
|
|
|
|
GVariant *parameter,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
gtk_application_impl_quartz_send_action ("clipboard.cut", @selector(cut:));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_application_impl_quartz_copy (GSimpleAction *action,
|
|
|
|
|
GVariant *parameter,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
gtk_application_impl_quartz_send_action ("clipboard.copy", @selector(copy:));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_application_impl_quartz_paste (GSimpleAction *action,
|
|
|
|
|
GVariant *parameter,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
gtk_application_impl_quartz_send_action ("clipboard.paste", @selector(paste:));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GActionEntry gtk_application_impl_quartz_clipboard_actions[] = {
|
|
|
|
|
{ "cut", gtk_application_impl_quartz_cut },
|
|
|
|
|
{ "copy", gtk_application_impl_quartz_copy },
|
|
|
|
|
{ "paste", gtk_application_impl_quartz_paste }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_application_impl_quartz_delete (GSimpleAction *action,
|
|
|
|
|
GVariant *parameter,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
gtk_application_impl_quartz_send_action ("selection.delete", @selector(delete:));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_application_impl_quartz_select_all (GSimpleAction *action,
|
|
|
|
|
GVariant *parameter,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
gtk_application_impl_quartz_send_action ("selection.select-all", @selector(selectAll:));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GActionEntry gtk_application_impl_quartz_selection_actions[] = {
|
|
|
|
|
{ "delete", gtk_application_impl_quartz_delete },
|
|
|
|
|
{ "select-all", gtk_application_impl_quartz_select_all }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_application_impl_quartz_set_app_menu (GtkApplicationImpl *impl,
|
|
|
|
|
GMenuModel *app_menu)
|
|
|
|
@@ -185,11 +302,19 @@ gtk_application_impl_quartz_startup (GtkApplicationImpl *impl,
|
|
|
|
|
gboolean register_session)
|
|
|
|
|
{
|
|
|
|
|
GtkApplicationImplQuartz *quartz = (GtkApplicationImplQuartz *) impl;
|
|
|
|
|
GSimpleActionGroup *gtkinternal;
|
|
|
|
|
GSimpleActionGroup *group;
|
|
|
|
|
GMenuModel *menubar;
|
|
|
|
|
const char *pref_accel[] = {"<Meta>comma", NULL};
|
|
|
|
|
const char *hide_others_accel[] = {"<Meta><Alt>h", NULL};
|
|
|
|
|
const char *hide_accel[] = {"<Meta>h", NULL};
|
|
|
|
|
const char *quit_accel[] = {"<Meta>q", NULL};
|
|
|
|
|
const char *undo_accel[] = {"<Meta>z", NULL};
|
|
|
|
|
const char *redo_accel[] = {"<Meta><Shift>z", NULL};
|
|
|
|
|
const char *cut_accel[] = {"<Meta>x", NULL};
|
|
|
|
|
const char *copy_accel[] = {"<Meta>c", NULL};
|
|
|
|
|
const char *paste_accel[] = {"<Meta>v", NULL};
|
|
|
|
|
const char *delete_accel[] = {"Delete", NULL};
|
|
|
|
|
const char *select_all_accel[] = {"<Meta>a", NULL};
|
|
|
|
|
|
|
|
|
|
if (register_session)
|
|
|
|
|
{
|
|
|
|
@@ -205,13 +330,38 @@ gtk_application_impl_quartz_startup (GtkApplicationImpl *impl,
|
|
|
|
|
gtk_application_set_accels_for_action (impl->application, "gtkinternal.hide-others", hide_others_accel);
|
|
|
|
|
gtk_application_set_accels_for_action (impl->application, "gtkinternal.hide", hide_accel);
|
|
|
|
|
gtk_application_set_accels_for_action (impl->application, "app.quit", quit_accel);
|
|
|
|
|
gtk_application_set_accels_for_action (impl->application, "text.undo", undo_accel);
|
|
|
|
|
gtk_application_set_accels_for_action (impl->application, "text.redo", redo_accel);
|
|
|
|
|
gtk_application_set_accels_for_action (impl->application, "clipboard.cut", cut_accel);
|
|
|
|
|
gtk_application_set_accels_for_action (impl->application, "clipboard.copy", copy_accel);
|
|
|
|
|
gtk_application_set_accels_for_action (impl->application, "clipboard.paste", paste_accel);
|
|
|
|
|
gtk_application_set_accels_for_action (impl->application, "selection.delete", delete_accel);
|
|
|
|
|
gtk_application_set_accels_for_action (impl->application, "selection.select-all", select_all_accel);
|
|
|
|
|
|
|
|
|
|
/* and put code behind the 'special' accels */
|
|
|
|
|
gtkinternal = g_simple_action_group_new ();
|
|
|
|
|
g_action_map_add_action_entries (G_ACTION_MAP (gtkinternal), gtk_application_impl_quartz_actions,
|
|
|
|
|
G_N_ELEMENTS (gtk_application_impl_quartz_actions), quartz);
|
|
|
|
|
gtk_application_insert_action_group (impl->application, "gtkinternal", G_ACTION_GROUP (gtkinternal));
|
|
|
|
|
g_object_unref (gtkinternal);
|
|
|
|
|
group = g_simple_action_group_new ();
|
|
|
|
|
g_action_map_add_action_entries (G_ACTION_MAP (group), gtk_application_impl_quartz_internal_actions,
|
|
|
|
|
G_N_ELEMENTS (gtk_application_impl_quartz_internal_actions), quartz);
|
|
|
|
|
gtk_application_insert_action_group (impl->application, "gtkinternal", G_ACTION_GROUP (group));
|
|
|
|
|
g_object_unref (group);
|
|
|
|
|
|
|
|
|
|
group = g_simple_action_group_new ();
|
|
|
|
|
g_action_map_add_action_entries (G_ACTION_MAP (group), gtk_application_impl_quartz_text_actions,
|
|
|
|
|
G_N_ELEMENTS (gtk_application_impl_quartz_text_actions), quartz);
|
|
|
|
|
gtk_application_insert_action_group (impl->application, "text", G_ACTION_GROUP (group));
|
|
|
|
|
g_object_unref (group);
|
|
|
|
|
|
|
|
|
|
group = g_simple_action_group_new ();
|
|
|
|
|
g_action_map_add_action_entries (G_ACTION_MAP (group), gtk_application_impl_quartz_clipboard_actions,
|
|
|
|
|
G_N_ELEMENTS (gtk_application_impl_quartz_clipboard_actions), quartz);
|
|
|
|
|
gtk_application_insert_action_group (impl->application, "clipboard", G_ACTION_GROUP (group));
|
|
|
|
|
g_object_unref (group);
|
|
|
|
|
|
|
|
|
|
group = g_simple_action_group_new ();
|
|
|
|
|
g_action_map_add_action_entries (G_ACTION_MAP (group), gtk_application_impl_quartz_selection_actions,
|
|
|
|
|
G_N_ELEMENTS (gtk_application_impl_quartz_selection_actions), quartz);
|
|
|
|
|
gtk_application_insert_action_group (impl->application, "selection", G_ACTION_GROUP (group));
|
|
|
|
|
g_object_unref (group);
|
|
|
|
|
|
|
|
|
|
/* now setup the menu */
|
|
|
|
|
if (quartz->standard_app_menu == NULL)
|
|
|
|
@@ -231,7 +381,19 @@ gtk_application_impl_quartz_startup (GtkApplicationImpl *impl,
|
|
|
|
|
gtk_application_impl_quartz_set_app_menu (impl, quartz->standard_app_menu);
|
|
|
|
|
|
|
|
|
|
/* This may or may not add an item to 'combined' */
|
|
|
|
|
gtk_application_impl_set_menubar (impl, gtk_application_get_menubar (impl->application));
|
|
|
|
|
menubar = gtk_application_get_menubar (impl->application);
|
|
|
|
|
if (menubar == NULL)
|
|
|
|
|
{
|
|
|
|
|
GtkBuilder *builder;
|
|
|
|
|
|
|
|
|
|
/* Provide a fallback menu, so keyboard shortcuts work in native windows too.
|
|
|
|
|
*/
|
|
|
|
|
builder = gtk_builder_new_from_resource ("/org/gtk/libgtk/ui/gtkapplication-quartz.ui");
|
|
|
|
|
menubar = G_MENU_MODEL (g_object_ref (gtk_builder_get_object (builder, "default-menu")));
|
|
|
|
|
g_object_unref (builder);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gtk_application_impl_set_menubar (impl, menubar);
|
|
|
|
|
|
|
|
|
|
/* OK. Now put it in the menu. */
|
|
|
|
|
gtk_application_impl_quartz_setup_menu (G_MENU_MODEL (quartz->combined), quartz->muxer);
|
|
|
|
|