From 99be0cbaccfc53b374055085f778a971a5758566 Mon Sep 17 00:00:00 2001 From: Michael Natterer 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 #include +#ifdef GDK_WINDOWING_QUARTZ +#include +#endif + /* Broken */ #include #include 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 + * + * 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 +#include +#include +#include + +#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 + * + * 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 can be included directly." +#endif + +#include + +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 + * + * 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 +#include + + +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)