6bdd276d05
Former-commit-id: fd56571888259555122d8a0f58c68838229cea2b
845 lines
25 KiB
Diff
845 lines
25 KiB
Diff
From 99be0cbaccfc53b374055085f778a971a5758566 Mon Sep 17 00:00:00 2001
|
|
From: Michael Natterer <mitch@lanedo.com>
|
|
Date: Tue, 29 Nov 2011 16:09:31 +0100
|
|
Subject: [PATCH 40/68] gtk: add new widget GtkNSView which alows to embed an
|
|
NSView
|
|
|
|
---
|
|
gtk/Makefile.am | 2 +
|
|
gtk/gtk.h | 4 +
|
|
gtk/gtknsview.c | 470 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
gtk/gtknsview.h | 62 +++++++
|
|
tests/Makefile.am | 10 +-
|
|
tests/testnsview.c | 190 +++++++++++++++++++++
|
|
6 files changed, 737 insertions(+), 1 deletion(-)
|
|
create mode 100644 gtk/gtknsview.c
|
|
create mode 100644 gtk/gtknsview.h
|
|
create mode 100644 tests/testnsview.c
|
|
|
|
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
|
|
index 31dfd19..59a6742 100644
|
|
--- a/gtk/Makefile.am
|
|
+++ b/gtk/Makefile.am
|
|
@@ -737,6 +737,7 @@ gtk_use_win32_c_sources = \
|
|
gtkwin32embedwidget.c \
|
|
gtkmountoperation-stub.c
|
|
gtk_use_quartz_c_sources = \
|
|
+ gtknsview.c \
|
|
gtksearchenginequartz.c \
|
|
gtkplug-stub.c \
|
|
gtksocket-stub.c \
|
|
@@ -757,6 +758,7 @@ else
|
|
if USE_QUARTZ
|
|
libgtk_quartz_2_0_la_CFLAGS = "-xobjective-c"
|
|
gtk_private_h_sources += gtksearchenginequartz.h
|
|
+gtk_public_h_sources += gtknsview.h
|
|
gtk_c_sources += $(gtk_use_quartz_c_sources)
|
|
else
|
|
gtk_c_sources += $(gtk_use_stub_c_sources)
|
|
diff --git a/gtk/gtk.h b/gtk/gtk.h
|
|
index 94e0b61..cc5834a 100644
|
|
--- a/gtk/gtk.h
|
|
+++ b/gtk/gtk.h
|
|
@@ -218,6 +218,10 @@
|
|
#include <gtk/gtkwidget.h>
|
|
#include <gtk/gtkwindow.h>
|
|
|
|
+#ifdef GDK_WINDOWING_QUARTZ
|
|
+#include <gtk/gtknsview.h>
|
|
+#endif
|
|
+
|
|
/* Broken */
|
|
#include <gtk/gtktext.h>
|
|
#include <gtk/gtktree.h>
|
|
diff --git a/gtk/gtknsview.c b/gtk/gtknsview.c
|
|
new file mode 100644
|
|
index 0000000..40c6a9b
|
|
--- /dev/null
|
|
+++ b/gtk/gtknsview.c
|
|
@@ -0,0 +1,470 @@
|
|
+/* GTK - The GIMP Toolkit
|
|
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
|
+ *
|
|
+ * GtkNSView - Native NSView embedding widget
|
|
+ * Copyright (C) 2011 Michael Natterer <mitch@lanedo.com>
|
|
+ *
|
|
+ * This library is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Library General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This library is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Library General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Library General Public
|
|
+ * License along with this library; if not, write to the
|
|
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
+ * Boston, MA 02111-1307, USA.
|
|
+ */
|
|
+
|
|
+#include "config.h"
|
|
+
|
|
+#include <gdk/gdk.h>
|
|
+#include <gdk/gdkkeysyms.h>
|
|
+#include <gdk/quartz/gdkquartz.h>
|
|
+#include <objc/runtime.h>
|
|
+
|
|
+#include "gtknsview.h"
|
|
+#include "gtkprivate.h"
|
|
+#include "gtkintl.h"
|
|
+#include "gtkalias.h"
|
|
+
|
|
+
|
|
+/* #define DEBUG_FOCUS 1 */
|
|
+
|
|
+
|
|
+enum
|
|
+{
|
|
+ PROP_0,
|
|
+ PROP_VIEW
|
|
+};
|
|
+
|
|
+
|
|
+struct _GtkNSViewPrivate
|
|
+{
|
|
+ NSView *view;
|
|
+};
|
|
+
|
|
+#define GTK_NS_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
|
|
+ GTK_TYPE_NS_VIEW, GtkNSViewPrivate))
|
|
+
|
|
+
|
|
+static void gtk_ns_view_finalize (GObject *object);
|
|
+static void gtk_ns_view_set_property (GObject *object,
|
|
+ guint prop_id,
|
|
+ const GValue *value,
|
|
+ GParamSpec *pspec);
|
|
+static void gtk_ns_view_get_property (GObject *object,
|
|
+ guint prop_id,
|
|
+ GValue *value,
|
|
+ GParamSpec *pspec);
|
|
+static void gtk_ns_view_notify (GObject *object,
|
|
+ GParamSpec *pspec);
|
|
+
|
|
+static void gtk_ns_view_unrealize (GtkWidget *widget);
|
|
+static void gtk_ns_view_map (GtkWidget *widget);
|
|
+static void gtk_ns_view_unmap (GtkWidget *widget);
|
|
+static void gtk_ns_view_size_request (GtkWidget *widget,
|
|
+ GtkRequisition *requisition);
|
|
+static void gtk_ns_view_size_allocate (GtkWidget *widget,
|
|
+ GtkAllocation *allocation);
|
|
+static void gtk_ns_view_grab_focus (GtkWidget *widget);
|
|
+static gboolean gtk_ns_view_key_press (GtkWidget *widget,
|
|
+ GdkEventKey *event);
|
|
+static gboolean gtk_ns_view_key_release (GtkWidget *widget,
|
|
+ GdkEventKey *event);
|
|
+
|
|
+static void gtk_ns_view_native_child_event (GdkWindow *window,
|
|
+ NSView *view,
|
|
+ NSEvent *event,
|
|
+ GtkNSView *ns_view);
|
|
+static gboolean gtk_ns_view_forward_event (GtkWidget *widget,
|
|
+ GdkEventKey *event);
|
|
+
|
|
+
|
|
+G_DEFINE_TYPE (GtkNSView, gtk_ns_view, GTK_TYPE_WIDGET)
|
|
+
|
|
+
|
|
+static void
|
|
+gtk_ns_view_class_init (GtkNSViewClass *klass)
|
|
+{
|
|
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
|
+
|
|
+ g_type_class_add_private (klass, sizeof (GtkNSViewPrivate));
|
|
+
|
|
+ object_class->finalize = gtk_ns_view_finalize;
|
|
+ object_class->set_property = gtk_ns_view_set_property;
|
|
+ object_class->get_property = gtk_ns_view_get_property;
|
|
+ object_class->notify = gtk_ns_view_notify;
|
|
+
|
|
+ widget_class->unrealize = gtk_ns_view_unrealize;
|
|
+ widget_class->map = gtk_ns_view_map;
|
|
+ widget_class->unmap = gtk_ns_view_unmap;
|
|
+ widget_class->size_request = gtk_ns_view_size_request;
|
|
+ widget_class->size_allocate = gtk_ns_view_size_allocate;
|
|
+ widget_class->grab_focus = gtk_ns_view_grab_focus;
|
|
+ widget_class->key_press_event = gtk_ns_view_key_press;
|
|
+ widget_class->key_release_event = gtk_ns_view_key_release;
|
|
+
|
|
+ /**
|
|
+ * GtkNSView:view:
|
|
+ *
|
|
+ * The widget's NSView.
|
|
+ *
|
|
+ * Since: 2.24
|
|
+ */
|
|
+ g_object_class_install_property (object_class,
|
|
+ PROP_VIEW,
|
|
+ g_param_spec_pointer ("view",
|
|
+ P_("View"),
|
|
+ P_("The NSView"),
|
|
+ GTK_PARAM_READWRITE |
|
|
+ G_PARAM_CONSTRUCT_ONLY));
|
|
+}
|
|
+
|
|
+static void
|
|
+gtk_ns_view_init (GtkNSView *ns_view)
|
|
+{
|
|
+ ns_view->priv = GTK_NS_VIEW_GET_PRIVATE (ns_view);
|
|
+
|
|
+ gtk_widget_set_has_window (GTK_WIDGET (ns_view), FALSE);
|
|
+}
|
|
+
|
|
+static void
|
|
+gtk_ns_view_finalize (GObject *object)
|
|
+{
|
|
+ GtkNSView *ns_view = GTK_NS_VIEW (object);
|
|
+
|
|
+ if (ns_view->priv->view)
|
|
+ {
|
|
+ [ns_view->priv->view release];
|
|
+ ns_view->priv->view = NULL;
|
|
+ }
|
|
+
|
|
+ G_OBJECT_CLASS (gtk_ns_view_parent_class)->finalize (object);
|
|
+}
|
|
+
|
|
+static void
|
|
+gtk_ns_view_set_property (GObject *object,
|
|
+ guint prop_id,
|
|
+ const GValue *value,
|
|
+ GParamSpec *pspec)
|
|
+{
|
|
+ GtkNSView *ns_view = GTK_NS_VIEW (object);
|
|
+
|
|
+ switch (prop_id)
|
|
+ {
|
|
+ case PROP_VIEW:
|
|
+ ns_view->priv->view = g_value_get_pointer (value);
|
|
+ if (ns_view->priv->view)
|
|
+ {
|
|
+ [ns_view->priv->view retain];
|
|
+ gtk_widget_set_can_focus (GTK_WIDGET (ns_view),
|
|
+ [ns_view->priv->view acceptsFirstResponder]);
|
|
+
|
|
+#if DEBUG_FOCUS
|
|
+ g_printerr ("%s can focus: %d\n",
|
|
+ class_getName ([ns_view->priv->view class]),
|
|
+ gtk_widget_get_can_focus (GTK_WIDGET (ns_view)));
|
|
+#endif
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+gtk_ns_view_get_property (GObject *object,
|
|
+ guint prop_id,
|
|
+ GValue *value,
|
|
+ GParamSpec *pspec)
|
|
+{
|
|
+ GtkNSView *ns_view = GTK_NS_VIEW (object);
|
|
+
|
|
+ switch (prop_id)
|
|
+ {
|
|
+ case PROP_VIEW:
|
|
+ g_value_set_pointer (value, ns_view->priv->view);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+gtk_ns_view_notify (GObject *object,
|
|
+ GParamSpec *pspec)
|
|
+{
|
|
+ GtkNSView *ns_view = GTK_NS_VIEW (object);
|
|
+
|
|
+ if (G_OBJECT_CLASS (gtk_ns_view_parent_class)->notify)
|
|
+ G_OBJECT_CLASS (gtk_ns_view_parent_class)->notify (object, pspec);
|
|
+
|
|
+ if (!strcmp (pspec->name, "has-focus"))
|
|
+ {
|
|
+ NSWindow *ns_window = [ns_view->priv->view window];
|
|
+
|
|
+#if DEBUG_FOCUS
|
|
+ g_printerr ("%s has-focus: %d\n",
|
|
+ class_getName ([ns_view->priv->view class]),
|
|
+ gtk_widget_has_focus (GTK_WIDGET (object)));
|
|
+#endif
|
|
+
|
|
+ if (gtk_widget_has_focus (GTK_WIDGET (object)))
|
|
+ [ns_window makeFirstResponder:ns_view->priv->view];
|
|
+ else
|
|
+ [ns_window makeFirstResponder:nil];
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+gtk_ns_view_position_view (GtkNSView *ns_view,
|
|
+ GtkAllocation *allocation)
|
|
+{
|
|
+ GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (ns_view));
|
|
+ GdkWindow *native;
|
|
+ gdouble x, y;
|
|
+ NSSize size;
|
|
+ NSPoint origin;
|
|
+
|
|
+ x = allocation->x;
|
|
+ y = allocation->y;
|
|
+
|
|
+ /* convert to the coordinate system of the innermost parent window
|
|
+ * that has an NSView
|
|
+ */
|
|
+ native = window;
|
|
+ while (! gdk_window_has_native (native))
|
|
+ {
|
|
+ gdk_window_coords_to_parent (native, x, y, &x, &y);
|
|
+ native = gdk_window_get_parent (native);
|
|
+ }
|
|
+
|
|
+ size.width = allocation->width;
|
|
+ size.height = allocation->height;
|
|
+ [ns_view->priv->view setFrameSize:size];
|
|
+
|
|
+ origin.x = x;
|
|
+ origin.y = y;
|
|
+ [ns_view->priv->view setFrameOrigin:origin];
|
|
+}
|
|
+
|
|
+static void
|
|
+gtk_ns_view_unrealize (GtkWidget *widget)
|
|
+{
|
|
+ if (gtk_widget_get_mapped (widget))
|
|
+ gtk_widget_unmap (widget);
|
|
+
|
|
+ GTK_WIDGET_CLASS (gtk_ns_view_parent_class)->unrealize (widget);
|
|
+}
|
|
+
|
|
+static void
|
|
+gtk_ns_view_map (GtkWidget *widget)
|
|
+{
|
|
+ GtkNSView *ns_view = GTK_NS_VIEW (widget);
|
|
+ GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
|
|
+ GtkAllocation allocation;
|
|
+ NSView *parent_view;
|
|
+
|
|
+ gtk_widget_get_allocation (widget, &allocation);
|
|
+ gtk_ns_view_position_view (ns_view, &allocation);
|
|
+
|
|
+ parent_view = gdk_quartz_window_get_nsview (gtk_widget_get_window (widget));
|
|
+ [parent_view addSubview:ns_view->priv->view];
|
|
+
|
|
+ [ns_view->priv->view setNextKeyView:nil];
|
|
+
|
|
+ g_signal_connect_object (gtk_widget_get_window (toplevel), "native-child-event",
|
|
+ G_CALLBACK (gtk_ns_view_native_child_event),
|
|
+ G_OBJECT (widget), 0);
|
|
+
|
|
+ GTK_WIDGET_CLASS (gtk_ns_view_parent_class)->map (widget);
|
|
+}
|
|
+
|
|
+static void
|
|
+gtk_ns_view_unmap (GtkWidget *widget)
|
|
+{
|
|
+ GtkNSView *ns_view = GTK_NS_VIEW (widget);
|
|
+ GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
|
|
+
|
|
+ g_signal_handlers_disconnect_by_func (gtk_widget_get_window (toplevel),
|
|
+ gtk_ns_view_native_child_event,
|
|
+ widget);
|
|
+
|
|
+ [ns_view->priv->view removeFromSuperview];
|
|
+
|
|
+ GTK_WIDGET_CLASS (gtk_ns_view_parent_class)->unmap (widget);
|
|
+}
|
|
+
|
|
+static void
|
|
+gtk_ns_view_size_request (GtkWidget *widget,
|
|
+ GtkRequisition *requisition)
|
|
+{
|
|
+ requisition->width = 1;
|
|
+ requisition->height = 1;
|
|
+}
|
|
+
|
|
+static void
|
|
+gtk_ns_view_size_allocate (GtkWidget *widget,
|
|
+ GtkAllocation *allocation)
|
|
+{
|
|
+ GtkNSView *ns_view = GTK_NS_VIEW (widget);
|
|
+
|
|
+ widget->allocation = *allocation;
|
|
+
|
|
+ if (gtk_widget_get_mapped (widget))
|
|
+ gtk_ns_view_position_view (ns_view, allocation);
|
|
+}
|
|
+
|
|
+static void
|
|
+gtk_ns_view_grab_focus (GtkWidget *widget)
|
|
+{
|
|
+ GtkNSView *ns_view = GTK_NS_VIEW (widget);
|
|
+ NSWindow *ns_window;
|
|
+
|
|
+ GTK_WIDGET_CLASS (gtk_ns_view_parent_class)->grab_focus (widget);
|
|
+
|
|
+ ns_window = [ns_view->priv->view window];
|
|
+ [ns_window makeFirstResponder:ns_view->priv->view];
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+gtk_ns_view_key_press (GtkWidget *widget,
|
|
+ GdkEventKey *event)
|
|
+{
|
|
+ GtkNSView *ns_view = GTK_NS_VIEW (widget);
|
|
+ NSEvent *nsevent = gdk_quartz_event_get_nsevent ((GdkEvent *) event);
|
|
+ NSWindow *ns_window;
|
|
+
|
|
+ if (gtk_ns_view_forward_event (widget, event))
|
|
+ {
|
|
+ ns_window = [ns_view->priv->view window];
|
|
+ [ns_window sendEvent:nsevent];
|
|
+
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
+ return GTK_WIDGET_CLASS (gtk_ns_view_parent_class)->key_press_event (widget, event);
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+gtk_ns_view_key_release (GtkWidget *widget,
|
|
+ GdkEventKey *event)
|
|
+{
|
|
+ GtkNSView *ns_view = GTK_NS_VIEW (widget);
|
|
+ NSEvent *nsevent = gdk_quartz_event_get_nsevent ((GdkEvent *) event);
|
|
+ NSWindow *ns_window;
|
|
+
|
|
+ if (gtk_ns_view_forward_event (widget, event))
|
|
+ {
|
|
+ ns_window = [ns_view->priv->view window];
|
|
+ [ns_window sendEvent:nsevent];
|
|
+
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
+ return GTK_WIDGET_CLASS (gtk_ns_view_parent_class)->key_release_event (widget, event);
|
|
+}
|
|
+
|
|
+static void
|
|
+gtk_ns_view_native_child_event (GdkWindow *window,
|
|
+ NSView *view,
|
|
+ NSEvent *event,
|
|
+ GtkNSView *ns_view)
|
|
+{
|
|
+ if (view == ns_view->priv->view)
|
|
+ {
|
|
+#if 0
|
|
+ g_printerr ("native child event on %s\n",
|
|
+ class_getName ([ns_view->priv->view class]));
|
|
+#endif
|
|
+
|
|
+ switch ([event type])
|
|
+ {
|
|
+ case NSLeftMouseDown:
|
|
+ if (! gtk_widget_has_focus (GTK_WIDGET (ns_view)) &&
|
|
+
|
|
+ /* other code can set can-focus, so check for both */
|
|
+ gtk_widget_get_can_focus (GTK_WIDGET (ns_view)) &&
|
|
+ [ns_view->priv->view acceptsFirstResponder])
|
|
+ {
|
|
+#if DEBUG_FOCUS
|
|
+ g_printerr ("grabbing focus on %s\n",
|
|
+ class_getName ([ns_view->priv->view class]));
|
|
+#endif
|
|
+
|
|
+ gtk_widget_grab_focus (GTK_WIDGET (ns_view));
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+gtk_ns_view_forward_event (GtkWidget *widget,
|
|
+ GdkEventKey *event)
|
|
+{
|
|
+ GtkNSView *ns_view = GTK_NS_VIEW (widget);
|
|
+ NSWindow *ns_window;
|
|
+ NSResponder *first_responder;
|
|
+ NSView *next_key_view;
|
|
+
|
|
+ if (event->type != GDK_KEY_PRESS ||
|
|
+ (event->keyval != GDK_KEY_Tab &&
|
|
+ event->keyval != GDK_KEY_ISO_Left_Tab))
|
|
+ {
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
+ ns_window = [ns_view->priv->view window];
|
|
+ first_responder = [ns_window firstResponder];
|
|
+
|
|
+#if DEBUG_FOCUS
|
|
+ g_printerr ("first reponder: %p %s\n", first_responder,
|
|
+ class_getName ([first_responder class]));
|
|
+#endif
|
|
+
|
|
+ if (event->keyval == GDK_KEY_Tab)
|
|
+ next_key_view = [first_responder nextValidKeyView];
|
|
+ else
|
|
+ next_key_view = [first_responder previousValidKeyView];
|
|
+
|
|
+#if DEBUG_FOCUS
|
|
+ g_printerr ("next key view: %p %s\n", next_key_view,
|
|
+ class_getName ([next_key_view class]));
|
|
+#endif
|
|
+
|
|
+ if (next_key_view &&
|
|
+ next_key_view != ns_view->priv->view &&
|
|
+ [next_key_view isDescendantOf:ns_view->priv->view])
|
|
+ {
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+GtkWidget *
|
|
+gtk_ns_view_new (gpointer nsview)
|
|
+{
|
|
+ g_return_val_if_fail (nsview != NULL, NULL);
|
|
+
|
|
+ return g_object_new (GTK_TYPE_NS_VIEW,
|
|
+ "view", nsview,
|
|
+ NULL);
|
|
+}
|
|
+
|
|
+#define __GTK_NS_VIEW_C__
|
|
+#include "gtkaliasdef.c"
|
|
diff --git a/gtk/gtknsview.h b/gtk/gtknsview.h
|
|
new file mode 100644
|
|
index 0000000..2c0aab7
|
|
--- /dev/null
|
|
+++ b/gtk/gtknsview.h
|
|
@@ -0,0 +1,62 @@
|
|
+/* GTK - The GIMP Toolkit
|
|
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
|
+ *
|
|
+ * GtkNSView - Native NSView embedding widget
|
|
+ * Copyright (C) 2011 Michael Natterer <mitch@lanedo.com>
|
|
+ *
|
|
+ * This library is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Library General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This library is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Library General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Library General Public
|
|
+ * License along with this library; if not, write to the
|
|
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
+ * Boston, MA 02111-1307, USA.
|
|
+ */
|
|
+
|
|
+#ifndef __GTK_NS_VIEW_H__
|
|
+#define __GTK_NS_VIEW_H__
|
|
+
|
|
+#if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
|
+#error "Only <gtk/gtk.h> can be included directly."
|
|
+#endif
|
|
+
|
|
+#include <gtk/gtkwidget.h>
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+#define GTK_TYPE_NS_VIEW (gtk_ns_view_get_type ())
|
|
+#define GTK_NS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_NS_VIEW, GtkNSView))
|
|
+#define GTK_NS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_NS_VIEW, GtkNSViewClass))
|
|
+#define GTK_IS_NS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_NS_VIEW))
|
|
+#define GTK_IS_NS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_NS_VIEW))
|
|
+#define GTK_NS_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_NS_VIEW, GtkNSViewClass))
|
|
+
|
|
+typedef struct _GtkNSView GtkNSView;
|
|
+typedef struct _GtkNSViewClass GtkNSViewClass;
|
|
+typedef struct _GtkNSViewPrivate GtkNSViewPrivate;
|
|
+
|
|
+struct _GtkNSView
|
|
+{
|
|
+ GtkWidget parent_instance;
|
|
+
|
|
+ GtkNSViewPrivate *priv;
|
|
+};
|
|
+
|
|
+struct _GtkNSViewClass
|
|
+{
|
|
+ GtkWidgetClass parent_class;
|
|
+};
|
|
+
|
|
+GType gtk_ns_view_get_type (void) G_GNUC_CONST;
|
|
+GtkWidget * gtk_ns_view_new (gpointer nsview);
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /* __GTK_NS_VIEW_H__ */
|
|
diff --git a/tests/Makefile.am b/tests/Makefile.am
|
|
index 3888826..af098f6 100644
|
|
--- a/tests/Makefile.am
|
|
+++ b/tests/Makefile.am
|
|
@@ -8,7 +8,8 @@ INCLUDES = \
|
|
-DGDK_DISABLE_DEPRECATED \
|
|
-DGTK_DISABLE_DEPRECATED \
|
|
$(GTK_DEBUG_FLAGS) \
|
|
- $(GTK_DEP_CFLAGS)
|
|
+ $(GTK_DEP_CFLAGS) \
|
|
+ -xobjective-c
|
|
|
|
DEPS = \
|
|
$(top_builddir)/gdk/$(gdktargetlib) \
|
|
@@ -57,6 +58,7 @@ noinst_PROGRAMS = $(TEST_PROGS) \
|
|
testmultiscreen \
|
|
testnotebookdnd \
|
|
testnouiprint \
|
|
+ testnsview \
|
|
testoffscreen \
|
|
testoffscreenwindow \
|
|
testorientable \
|
|
@@ -134,6 +136,7 @@ testmultidisplay_DEPENDENCIES = $(TEST_DEPS)
|
|
testmultiscreen_DEPENDENCIES = $(TEST_DEPS)
|
|
testnotebookdnd_DEPENDENCIES = $(TEST_DEPS)
|
|
testnouiprint_DEPENDENCIES = $(TEST_DEPS)
|
|
+testnsview_DEPENDENCIES = $(TEST_DEPS)
|
|
testoffscreen_DEPENDENCIES = $(TEST_DEPS)
|
|
testoffscreenwindow_DEPENDENCIES = $(TEST_DEPS)
|
|
testorientable_DEPENDENCIES = $(TEST_DEPS)
|
|
@@ -166,6 +169,8 @@ testtooltips_DEPENDENCIES = $(TEST_DEPS)
|
|
testvolumebutton_DEPENDENCIES = $(TEST_DEPS)
|
|
testwindows_DEPENDENCIES = $(TEST_DEPS)
|
|
|
|
+testnsview_LDFLAGS = -framework WebKit
|
|
+
|
|
testentrycompletion_SOURCES = \
|
|
prop-editor.c \
|
|
testentrycompletion.c
|
|
@@ -262,6 +267,9 @@ testrecentchoosermenu_SOURCES = \
|
|
testvolumebutton_SOURCES = \
|
|
testvolumebutton.c
|
|
|
|
+testnsview_SOURCES = \
|
|
+ testnsview.c
|
|
+
|
|
testoffscreen_SOURCES = \
|
|
gtkoffscreenbox.c \
|
|
gtkoffscreenbox.h \
|
|
diff --git a/tests/testnsview.c b/tests/testnsview.c
|
|
new file mode 100644
|
|
index 0000000..7c9ccb7
|
|
--- /dev/null
|
|
+++ b/tests/testnsview.c
|
|
@@ -0,0 +1,190 @@
|
|
+/* testnsview.c
|
|
+ * Copyright (C) 2011 Michael Natterer <mitch@lanedo.com>
|
|
+ *
|
|
+ * This library is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Library General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This library is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Library General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Library General Public
|
|
+ * License along with this library; if not, write to the
|
|
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
+ * Boston, MA 02111-1307, USA.
|
|
+ */
|
|
+
|
|
+#include "config.h"
|
|
+
|
|
+#include <WebKit/WebKit.h>
|
|
+#include <gtk/gtk.h>
|
|
+
|
|
+
|
|
+static void
|
|
+back_clicked (GtkToolItem *item,
|
|
+ WebView *webview)
|
|
+{
|
|
+ [webview goBack];
|
|
+}
|
|
+
|
|
+static void
|
|
+forward_clicked (GtkToolItem *item,
|
|
+ WebView *webview)
|
|
+{
|
|
+ [webview goForward];
|
|
+}
|
|
+
|
|
+gint
|
|
+main (gint argc,
|
|
+ gchar *argv[])
|
|
+{
|
|
+ GtkWidget *window;
|
|
+ GtkWidget *vbox;
|
|
+ GtkWidget *toolbar;
|
|
+ GtkToolItem *item;
|
|
+ WebView *webview;
|
|
+ NSRect web_rect = { { 0.0, 0.0 }, { 100.0, 100.0 } };
|
|
+ NSURL *url;
|
|
+ NSURLRequest *request;
|
|
+ GtkWidget *ns_view;
|
|
+
|
|
+ gtk_init (&argc, &argv);
|
|
+
|
|
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
|
+ gtk_window_set_title (GTK_WINDOW (window), "GtkNSView featuring WebView");
|
|
+
|
|
+ g_signal_connect (window, "destroy",
|
|
+ G_CALLBACK (gtk_main_quit),
|
|
+ NULL);
|
|
+
|
|
+ vbox = gtk_vbox_new (FALSE, 0);
|
|
+ gtk_container_add (GTK_CONTAINER (window), vbox);
|
|
+ gtk_widget_show (vbox);
|
|
+
|
|
+ toolbar = gtk_toolbar_new ();
|
|
+ gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, FALSE, 0);
|
|
+ gtk_widget_show (toolbar);
|
|
+
|
|
+ webview = [WebView alloc];
|
|
+
|
|
+ item = gtk_tool_button_new_from_stock (GTK_STOCK_GO_BACK);
|
|
+ gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
|
|
+ gtk_widget_show (GTK_WIDGET (item));
|
|
+
|
|
+ g_signal_connect (item, "clicked",
|
|
+ G_CALLBACK (back_clicked),
|
|
+ webview);
|
|
+
|
|
+ item = gtk_tool_button_new_from_stock (GTK_STOCK_GO_FORWARD);
|
|
+ gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
|
|
+ gtk_widget_show (GTK_WIDGET (item));
|
|
+
|
|
+ g_signal_connect (item, "clicked",
|
|
+ G_CALLBACK (forward_clicked),
|
|
+ webview);
|
|
+
|
|
+ [webview initWithFrame:web_rect
|
|
+ frameName:@"foo"
|
|
+ groupName:@"bar"];
|
|
+
|
|
+ url = [NSURL URLWithString:@"http://www.gimp.org/"];
|
|
+ request = [NSURLRequest requestWithURL:url];
|
|
+
|
|
+ [[webview mainFrame] loadRequest:request];
|
|
+
|
|
+ ns_view = gtk_ns_view_new ((NSView *) webview);
|
|
+ gtk_widget_set_size_request (ns_view, 300, 200);
|
|
+ gtk_box_pack_end (GTK_BOX (vbox), ns_view, TRUE, TRUE, 0);
|
|
+ gtk_widget_show (ns_view);
|
|
+
|
|
+ [webview release];
|
|
+
|
|
+ {
|
|
+ GtkWidget *button;
|
|
+
|
|
+ button = gtk_button_new_with_label ("hide webview");
|
|
+ gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
|
+ gtk_widget_show (button);
|
|
+
|
|
+ g_signal_connect_swapped (button, "clicked",
|
|
+ G_CALLBACK (gtk_widget_hide),
|
|
+ ns_view);
|
|
+
|
|
+ button = gtk_button_new_with_label ("show webview");
|
|
+ gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
|
+ gtk_widget_show (button);
|
|
+
|
|
+ g_signal_connect_swapped (button, "clicked",
|
|
+ G_CALLBACK (gtk_widget_show),
|
|
+ ns_view);
|
|
+ }
|
|
+
|
|
+ /* add an entry in an event box to test living inside another gdkwindow */
|
|
+ {
|
|
+ GtkWidget *event_box;
|
|
+ GtkWidget *abox;
|
|
+ GtkWidget *hbox;
|
|
+ NSRect label_rect = { { 0.0, 0.0 }, { 100.0, 12.0 } };
|
|
+ NSRect text_rect = { { 0.0, 0.0 }, { 100.0, 12.0 } };
|
|
+ NSTextField *text_field;
|
|
+
|
|
+ event_box = gtk_event_box_new ();
|
|
+ gtk_widget_set_state (event_box, GTK_STATE_ACTIVE);
|
|
+ gtk_box_pack_start (GTK_BOX (vbox), event_box, FALSE, FALSE, 0);
|
|
+ gtk_widget_show (event_box);
|
|
+
|
|
+ abox = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
|
|
+ gtk_container_set_border_width (GTK_CONTAINER (abox), 10);
|
|
+ gtk_container_add (GTK_CONTAINER (event_box), abox);
|
|
+ gtk_widget_show (abox);
|
|
+
|
|
+ hbox = gtk_hbox_new (FALSE, 10);
|
|
+ gtk_container_add (GTK_CONTAINER (abox), hbox);
|
|
+ gtk_widget_show (hbox);
|
|
+
|
|
+ /* a non-editable text label */
|
|
+ text_field = [[NSTextField alloc] initWithFrame:label_rect];
|
|
+ [text_field setEditable:NO];
|
|
+ [text_field setDrawsBackground:NO];
|
|
+ [text_field setBordered:NO];
|
|
+ [text_field setStringValue:@"A Text Label"];
|
|
+
|
|
+ ns_view = gtk_ns_view_new ((NSView *) text_field);
|
|
+ gtk_widget_set_size_request (ns_view, 100, 20);
|
|
+ gtk_box_pack_start (GTK_BOX (hbox), ns_view, FALSE, FALSE, 0);
|
|
+ gtk_widget_show (ns_view);
|
|
+
|
|
+ [text_field release];
|
|
+
|
|
+ /* an editable text field */
|
|
+ text_field = [[NSTextField alloc] initWithFrame:text_rect];
|
|
+ [text_field setEditable:YES];
|
|
+ [text_field setStringValue:@"An editable text entry"];
|
|
+
|
|
+ ns_view = gtk_ns_view_new ((NSView *) text_field);
|
|
+ gtk_widget_set_size_request (ns_view, 100, 20);
|
|
+ gtk_box_pack_start (GTK_BOX (hbox), ns_view, TRUE, TRUE, 0);
|
|
+ gtk_widget_show (ns_view);
|
|
+
|
|
+ [text_field release];
|
|
+ }
|
|
+
|
|
+ /* and a normal GtkEntry to check focus */
|
|
+ {
|
|
+ GtkWidget *entry;
|
|
+
|
|
+ entry = gtk_entry_new ();
|
|
+ gtk_entry_set_text (GTK_ENTRY (entry), "Normal GTK+ entry");
|
|
+ gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
|
|
+ gtk_widget_show (entry);
|
|
+ }
|
|
+
|
|
+ gtk_widget_show (window);
|
|
+
|
|
+ gtk_main ();
|
|
+
|
|
+ return 0;
|
|
+}
|
|
--
|
|
1.7.10.2 (Apple Git-33)
|