|
From: <br...@us...> - 2009-03-01 05:11:07
|
Revision: 3815
http://openvrml.svn.sourceforge.net/openvrml/?rev=3815&view=rev
Author: braden
Date: 2009-03-01 05:11:00 +0000 (Sun, 01 Mar 2009)
Log Message:
-----------
Moved D-Bus interaction out of the main (GTK+) thread and into its own background thread. This avoids a deadlock when a resource fetch comes from the rendering thread and waits on feedback that will happen via D-Bus.
Modified Paths:
--------------
trunk/ChangeLog
trunk/src/openvrml-xembed/browser.cpp
trunk/src/openvrml-xembed/browser.h
trunk/src/openvrml-xembed/browserfactory.cpp
trunk/src/openvrml-xembed/browserfactory.h
trunk/src/openvrml-xembed/main.cpp
trunk/src/openvrml-xembed/plugin_streambuf.cpp
trunk/src/openvrml-xembed/plugin_streambuf.h
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2009-02-27 07:56:25 UTC (rev 3814)
+++ trunk/ChangeLog 2009-03-01 05:11:00 UTC (rev 3815)
@@ -1,3 +1,224 @@
+2009-03-01 Braden McDaniel <br...@en...>
+
+ Moved D-Bus interaction out of the main (GTK+) thread and into its
+ own background thread. This avoids a deadlock when a resource
+ fetch comes from the rendering thread and waits on feedback that
+ will happen via D-Bus.
+
+ openvrml-xembed's "browser" now exists in two parts:
+ OpenvrmlXembedBrowser is primarily responsible for interaction
+ with the host (via D-Bus) and OpenvrmlXembedBrowserPlug is a GTK+
+ widget that is responsible for rendering and interaction with
+ GTK+.
+
+ * src/openvrml-xembed/browser.cpp
+ (browser_listener): Contain a reference to the
+ OpenvrmlXembedBrowser (instead of the GtkGLViewer).
+ (OpenvrmlXembedBrowserPrivate_): Removed drawing_area and viewer
+ members; those have moved to OpenvrmlXembedBrowserPlugPrivate_.
+ Added listener, browser_plug, browser_plug_mutex,
+ browser_plug_set_cond, browser_initialized_mutex, and
+ browser_initialized.
+ (openvrml_xembed_browser_class_init(OpenvrmlXembedBrowserClass *)):
+ Set constructor and finalize function pointers; use
+ g_param_spec_object to define the control-host-proxy property.
+ (openvrml_xembed_browser_constructor(GType, guint,
+ GObjectConstructParam *)): Since OpenvrmlXembedBrowser isn't a
+ widget anymore, moved the initialization code that was in _realize
+ here.
+ (openvrml_xembed_browser_finalize(GObject *)): Destroy the stuff
+ that was created in _constructor.
+ (openvrml_xembed_browser_set_property(GObject *, guint, const
+ GValue *, GParamSpec *)): Use g_value_get_object to get the value
+ for control-host-property
+ (openvrml_xembed_browser_get_property(GObject *, guint, GValue *,
+ GParamSpec *)): Use g_value_set_object to set the value for
+ control-host-proxy property.
+ (openvrml_xembed_browser_new(DBusGProxy *, gboolean,
+ GMainContext *, GdkNativeWindow)): Create an OpenvrmlXembedBrowser
+ and send an event to the GTK+ thread to create an
+ OpenvrmlXembedBrowserPlug.
+ (openvrml_xembed_browser_new_for_display(DBusGProxy *,
+ GdkDisplay *, GdkNativeWindow, gboolean)): Removed.
+ (load_url): Moved out of GtkGLViewer; lock the
+ OpenvrmlXembedBrowser's browser_initialized_mutex.
+ (openvrml_xembed_browser_load_url(OpenvrmlXembedBrowser *, const
+ gchar **, const gchar **, GError **)): Handle exceptions by
+ setting the GError.
+ (openvrml_xembed_browser_get_id(OpenvrmlXembedBrowser *)): We
+ don't have the plug's ID until the OpenvrmlXembedBrowserPlug has
+ been created; wait for browser_plug_set_cond.
+ (openvrml_xembed_browser_initialized(OpenvrmlXembedBrowser *)):
+ Indicate whether the underlying openvrml::browser has emitted an
+ "initialized" event.
+ (GtkGLViewer): Removed friendship declarations for
+ openvrml_xembed_browser_load_url,
+ openvrml_xembed_browser_get_world_url,
+ openvrml_xembed_browser_timeout_callback, and
+ openvrml_xembed_browser_motion_notify_event. Changed friendship
+ declaration for openvrml_xembed_browser_expose_event to
+ openvrml_xembed_browser_plug_expose_event. Grant friendship to
+ openvrml_xembed_browser_plug_realize and browser_initialized.
+ Removed browser_listener_, browser_initialized_, and
+ browser_initialized_mutex_ members; these were moved to
+ OpenvrmlXembedBrowser.
+ (OpenvrmlXembedBrowserPlugPrivate_): Private data for
+ OpenvrmlXembedBrowserPlug.
+ (openvrml_xembed_browser_plug_init(OpenvrmlXembedBrowserPlug *)):
+ Initialize the OpenvrmlXembedBrowserPlug instance.
+ (openvrml_xembed_browser_plug_class_init(OpenvrmlXembedBrowserPlugClass *)):
+ Initialized the OpenvrmlXembedBrowserPlug class object.
+ (openvrml_xembed_browser_plug_set_property(GObject *, gint, const
+ GValue *, GParamSpec *)): OpenvrmlXembedBrowserPlug property
+ mutator.
+ (openvrml_xembed_browser_plug_get_property(GObject *, gint,
+ GValue *, GParamSpec *)): OpenvrmlXembedBrowserPlug property
+ accessor.
+ (openvrml_xembed_browser_plug_new(OpenvrmlXembedBrowser *,
+ GdkNativeWindow)): Create an OpenvrmlXembedBrowserPlug.
+ (browser_initialized(OpenvrmlXembedBrowser *,
+ OpenvrmlXembedBrowserPlug *)): Callback called once the underlying
+ openvrml::browser emits an "initialized" event.
+ (openvrml_xembed_browser_plug_realize(GtkWidget *)): Instantiate
+ the GtkGLViewer, set up the GtkDrawingArea, and attach the various
+ signal handlers.
+ (openvrml_xembed_browser_plug_unrealize(GtkWidget *)): Destroy the
+ GtkGLViewer and the GtkDrawingArea.
+ (openvrml_xembed_drawing_area_expose_event(GtkWidget *,
+ GdkEventExpose *, OpenvrmlXembedBrowserPlug *)): Moved from
+ openvrml_xembed_browser_expose_event.
+ (openvrml_xembed_drawing_area_configure_event(GtkWidget *,
+ GdkEventConfigure *, OpenvrmlXembedBrowserPlug *)): Moved from
+ openvrml_xembed_browser_configure_event.
+ (openvrml_xembed_drawing_area_key_press_event(GtkWidget *,
+ GdkEventKey *, OpenvrmlXembedBrowserPlug *)): Moved from
+ openvrml_xembed_browser_key_press_event.
+ (openvrml_xembed_drawing_area_button_press_event(GtkWidget *,
+ GdkEventButton *, OpenvrmlXembedBrowserPlug *)): Moved from
+ openvrml_xembed_browser_button_press_event.
+ (openvrml_xembed_drawing_area_button_release_event(GtkWidget *,
+ GdkEventButton *, OpenvrmlXembedBrowserPlug *)): Moved from
+ openvrml_xembed_browser_button_release_event.
+ (openvrml_xembed_drawing_area_motion_notify_event(GtkWidget *,
+ GdkEventMotion *, OpenvrmlXembedBrowserPlug *)): Moved from
+ openvrml_xembed_browser_motion_notify_event.
+ (openvrml_xembed_browser_plug_timeout_callback(gpointer)): Moved
+ from openvrml_xembed_browser_timeout_callback.
+ (browser_listener::browser_listener(OpenvrmlXembedBrowser &)):
+ Hold a reference to the OpenvrmlXembedBrowser instead of the
+ GtkGLViewer.
+ (browser_listener::do_browser_changed(const
+ openvrml::browser_event &)): For "initialized", just emit the
+ signal and set browser_initialized on the OpenvrmlXembedBrowser.
+ Anything we need to do in the OpenvrmlXembedBrowserPlug can be
+ handled with a GObject signal handler.
+ (GtkGLViewer::GtkGLViewer(OpenvrmlXembedBrowserPlug &)): Take a
+ reference to the OpenvrmlXembedBrowserPlug instead of the
+ OpenvrmlXembedBrowser. We no longer handle the listener here.
+ (GtkGLViewer::~GtkGLViewer()): We no longer handle the listener
+ here.
+ (OpenvrmlXembedBrowserReadySource): The event source used to
+ trigger creation of the OpenvrmlXembedBrowserPlug in the GTK+ main
+ thread.
+ (openvrml_xembed_browser_ready_source_new(OpenvrmlXembedBrowser *,
+ guint64)): Create an OpenvrmlXembedBrowserReadySource.
+ (openvrml_xembed_browser_ready_prepare(GSource *, gint *)): Set
+ timeout to 0 and return true;
+ (openvrml_xembed_browser_ready_check(GSource *)): Return true.
+ (openvrml_xembed_browser_ready_dispatch(GSource *, GSourceFunc,
+ gpointer)): Create, realize, and show the
+ OpenvrmlXembedBrowserPlug.
+ (openvrml_xembed_browser_ready_finalize(GSource *)): Do nothing.
+ * src/openvrml-xembed/browser.h
+ (OpenvrmlXembedBrowser_): Inherit GObject instead of GtkPlug.
+ (OpenvrmlXembedBrowserClass_): Inherit GObjectClass instead of
+ GtkPlugClass.
+ (openvrml_xembed_browser_new(DBusGProxy *, gboolean,
+ GMainContext *, GdkNativeWindow)): Take the GMainContext
+ associated with the GTK+ main thread as an argument.
+ (openvrml_xembed_browser_constructor(GType, guint,
+ GObjectConstructParam *)): plugin_streambuf needs to grant
+ friendship to this.
+ (OpenvrmlXembedBrowserPlug): A GTK+ widget to handle rendering.
+ (OpenvrmlXembedBrowserPlugClass): Class object for
+ OpenvrmlXembedBrowserPlug.
+ (openvrml_xembed_browser_plug_new(OpenvrmlXembedBrowser *,
+ GtkNativeWindow)): Create a new OpenvrmlXembedBrowserPlug.
+ (openvrml_xembed_browser_plug_get_type(void)): Get the GType for
+ OpenvrmlXembedBrowserPlug.
+ * src/openvrml-xembed/browserfactory.cpp
+ (OpenvrmlXembedBrowserFactoryPrivate_): Removed driver_proxy
+ member; added connection and main_thread_context members.
+ (openvrml_xembed_browser_factory_constructor(GType, guint,
+ GObjectConstructParam *)): Register the D-Bus object
+ "/org/openvrml/BrowserFactory" and request the
+ "org.openvrml.BrowserControl" name.
+ (openvrml_xembed_browser_factory_class_init(OpenvrmlXembedBrowserFactory *)):
+ Set the property accessor and mutator functions; add the
+ "connection" and "main-thread-context" properties.
+ (openvrml_xembed_browser_factory_set_property(GObject *, guint,
+ const GValue *, GParamSpec *)): Property mutator.
+ (openvrml_xembed_browser_factory_get_property(GObject *, guint,
+ GValue *, GParamSpec *)): Property accessor.
+ (openvrml_xembed_browser_factory_create_control(OpenvrmlXembedBrowserFactory *,
+ const char *, const char *, guint64, gboolean,
+ DBusGMethodInvocation *)): Don't realize/show the widget here;
+ that's now taken care of by
+ openvrml_xembed_browser_ready_dispatch.
+ (openvrml_xembed_browser_factory_remove_hosts_for_owner(OpenvrmlXembedBrowserFactory *,
+ const char *)): Remove references to hosts for the named owner.
+ (openvrml_xembed_browser_factory_has_hosts(OpenvrmlXembedBrowserFactory *)):
+ Indicate whether any hosts are associated with the factory.
+ (openvrml_xembed_browser_factory_name_owner_changed(DBusGProxy *,
+ const gchar *, const gchar *, const gchar *, gpointer)): Moved to
+ main.cpp.
+ * src/openvrml-xembed/browserfactory.h
+ (OpenvrmlXembedBrowserFactoryClass_): Removed connection member.
+ Establishing the bus connection is no longer the responsibility of
+ OpenvrmlXembedBrowserFactory.
+ (openvrml_xembed_browser_factory_remove_hosts_for_owner(OpenvrmlXembedBrowserFactory *,
+ const gchar *)): Added public function.
+ (openvrml_xembed_browser_factory_has_hosts(OpenvrmlXembedBrowserFactory *)):
+ Added public function.
+ * src/openvrml-xembed/main.cpp
+ (bus_get(GMainContext *, DBusBusType, GError **)): Get a
+ DBusGConnection using a particular GMainContext.
+ (name_owner_changed_callback_data): Data propagated to
+ openvrml_xembed_name_owner_changed.
+ (dbus_thread_loop): Function object for the D-Bus thread main
+ loop.
+ (main(int, char *[])): Start, and ultimately join, a thread for
+ D-Bus interactions.
+ (openvrml_xembed_name_owner_changed(DBusGProxy *, const gchar *,
+ const gchar *, const gchar *, gpointer)): Callback to clean up the
+ browser(s) associated with a host (and exit if there are no more
+ hosts).
+ * src/openvrml-xembed/plugin_streambuf.cpp
+ (openvrml_xembed::plugin_streambuf::plugin_streambuf(const
+ std::string &, uninitialized_plugin_streambuf_map &,
+ plugin_streambuf_map &)): Removed initialization of member
+ "initialized_".
+ (openvrml_xembed::plugin_streambuf::set_get_url_result(int)): Only
+ notify waiting threads if the "GetUrl" result indicates success;
+ the only reason anyone should be waiting on this is if the fetch
+ operation has (at least partially) succeeded.
+ (openvrml_xembed::plugin_streambuf::get_url_result() const):
+ Removed.
+ (openvrml_xembed::plugin_streambuf::init(size_t, const
+ std::string&, const std::string &)): Wait for set_get_url_result
+ to be called.
+ (openvrml_xembed::plugin_streambuf::url() const): Check state_
+ instead of initialized_.
+ (openvrml_xembed::plugin_streambuf::type() const): Check state_
+ instead of initialized_.
+ (openvrml_xembed::plugin_streambuf::underflow()): Check state_
+ instead of initialized_.
+ * src/openvrml-xembed/plugin_streambuf.h
+ (openvrml_xembed::plugin_streambuf): Removed friend declaration
+ for openvrml_xembed_browser_realize; grant friendship to
+ openvrml_xembed_browser_constructor. Removed member
+ "initialized_". Removed "get_url_result" member function.
+
2009-02-27 Braden McDaniel <br...@en...>
* src/libopenvrml/openvrml/script.cpp
Modified: trunk/src/openvrml-xembed/browser.cpp
===================================================================
--- trunk/src/openvrml-xembed/browser.cpp 2009-02-27 07:56:25 UTC (rev 3814)
+++ trunk/src/openvrml-xembed/browser.cpp 2009-03-01 05:11:00 UTC (rev 3815)
@@ -31,6 +31,7 @@
# include <openvrml/gl/viewer.h>
# include "browser.h"
# include "browser-server-glue.h"
+# include "browser-host-client-glue.h"
# include "plugin_streambuf.h"
# include <gtk/gtkgl.h>
# include <gtk/gtkdrawingarea.h>
@@ -56,60 +57,22 @@
GParamSpec * pspec);
//
- // GtkWidget overrides
- //
- G_GNUC_INTERNAL void openvrml_xembed_browser_realize(GtkWidget * widget);
- G_GNUC_INTERNAL void openvrml_xembed_browser_unrealize(GtkWidget * widget);
-
- //
// OpenvrmlXembedStreamClient implementation
//
G_GNUC_INTERNAL
void
openvrml_xembed_browser_stream_client_interface_init(gpointer g_iface,
gpointer iface_data);
-
- //
- // Signal handlers
- //
- G_GNUC_INTERNAL
- gboolean openvrml_xembed_browser_expose_event(GtkWidget * widget,
- GdkEventExpose * event,
- gpointer data);
- G_GNUC_INTERNAL
- gboolean openvrml_xembed_browser_configure_event(GtkWidget * widget,
- GdkEventConfigure * event,
- gpointer data);
- G_GNUC_INTERNAL
- gboolean openvrml_xembed_browser_key_press_event(GtkWidget * widget,
- GdkEventKey * event,
- gpointer data);
- G_GNUC_INTERNAL
- gboolean openvrml_xembed_browser_button_press_event(GtkWidget * widget,
- GdkEventButton * event,
- gpointer data);
- G_GNUC_INTERNAL
- gboolean openvrml_xembed_browser_button_release_event(GtkWidget * widget,
- GdkEventButton * event,
- gpointer data);
- G_GNUC_INTERNAL
- gboolean openvrml_xembed_browser_motion_notify_event(GtkWidget * widget,
- GdkEventMotion * event,
- gpointer data);
-
- G_GNUC_INTERNAL gint openvrml_xembed_browser_timeout_callback(gpointer ptr);
}
G_DEFINE_TYPE_WITH_CODE(OpenvrmlXembedBrowser,
openvrml_xembed_browser,
- GTK_TYPE_PLUG,
+ G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE(
OPENVRML_XEMBED_TYPE_STREAM_CLIENT,
openvrml_xembed_browser_stream_client_interface_init))
namespace {
- G_GNUC_INTERNAL GdkGLConfig * gl_config;
-
class G_GNUC_INTERNAL resource_fetcher : public openvrml::resource_fetcher {
DBusGProxy & control_host_;
openvrml_xembed::uninitialized_plugin_streambuf_map &
@@ -132,84 +95,32 @@
do_get_resource(const std::string & uri);
};
+ class G_GNUC_INTERNAL browser_listener : public openvrml::browser_listener {
+ OpenvrmlXembedBrowser & browser_;
- class GtkGLViewer;
-
- class G_GNUC_INTERNAL browser_listener :
- public openvrml::browser_listener {
-
- GtkGLViewer & viewer_;
-
public:
- explicit browser_listener(GtkGLViewer & viewer);
+ explicit browser_listener(OpenvrmlXembedBrowser & browser);
private:
virtual void do_browser_changed(const openvrml::browser_event & event);
};
-
-
- class G_GNUC_INTERNAL GtkGLViewer : public openvrml::gl::viewer {
- friend class browser_listener;
-
- friend gboolean
- (::openvrml_xembed_browser_load_url)(OpenvrmlXembedBrowser * browser,
- const gchar ** url,
- const gchar ** parameter,
- GError **);
-
- friend gchar *
- (::openvrml_xembed_browser_get_world_url)(
- OpenvrmlXembedBrowser * vrml_browser,
- GError ** error);
-
- friend gint (::openvrml_xembed_browser_timeout_callback)(gpointer ptr);
- friend gboolean (::openvrml_xembed_browser_expose_event)(
- GtkWidget *,
- GdkEventExpose *,
- gpointer);
- friend gboolean
- (::openvrml_xembed_browser_motion_notify_event)(GtkWidget *,
- GdkEventMotion *,
- gpointer);
-
- struct load_url;
-
- ::browser_listener browser_listener_;
- bool browser_initialized_;
- openvrml::read_write_mutex browser_initialized_mutex_;
- OpenvrmlXembedBrowser & vrml_browser_;
- guint timer;
-
- public:
- bool redrawNeeded;
-
- explicit GtkGLViewer(OpenvrmlXembedBrowser & vrml_browser);
- virtual ~GtkGLViewer() throw ();
-
- void timer_update();
-
- protected:
- //
- // Implement pure virtual methods from openvrml::gl::viewer.
- //
- virtual void post_redraw();
- virtual void set_cursor(openvrml::gl::viewer::cursor_style);
- virtual void swap_buffers();
- virtual void set_timer(double);
- };
}
struct OpenvrmlXembedBrowserPrivate_ {
DBusGProxy * control_host;
::resource_fetcher * resource_fetcher;
openvrml::browser * browser;
- GtkDrawingArea * drawing_area;
- GtkGLViewer * viewer;
+ browser_listener * listener;
+ OpenvrmlXembedBrowserPlug * browser_plug;
+ GMutex * browser_plug_mutex;
+ GCond * browser_plug_set_cond;
+ GMutex * browser_initialized_mutex;
openvrml_xembed::uninitialized_plugin_streambuf_map * uninitialized_streambuf_map;
openvrml_xembed::plugin_streambuf_map * streambuf_map;
boost::thread * initial_stream_reader_thread;
bool expect_initial_stream;
bool got_initial_stream;
+ bool browser_initialized;
};
# define OPENVRML_XEMBED_BROWSER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), OPENVRML_XEMBED_TYPE_BROWSER, OpenvrmlXembedBrowserPrivate))
@@ -234,14 +145,20 @@
G_GNUC_INTERNAL guint signals[last_signal_id];
}
+extern "C" {
+ G_GNUC_INTERNAL void openvrml_xembed_browser_finalize(GObject * obj);
+}
+
void
openvrml_xembed_browser_class_init(OpenvrmlXembedBrowserClass * const klass)
{
- G_OBJECT_CLASS(klass)->set_property = openvrml_xembed_browser_set_property;
- G_OBJECT_CLASS(klass)->get_property = openvrml_xembed_browser_get_property;
- GTK_WIDGET_CLASS(klass)->realize = openvrml_xembed_browser_realize;
- GTK_WIDGET_CLASS(klass)->unrealize = openvrml_xembed_browser_unrealize;
+ GObjectClass * const g_object_class = G_OBJECT_CLASS(klass);
+ g_object_class->constructor = openvrml_xembed_browser_constructor;
+ g_object_class->finalize = openvrml_xembed_browser_finalize;
+ g_object_class->set_property = openvrml_xembed_browser_set_property;
+ g_object_class->get_property = openvrml_xembed_browser_get_property;
+
signals[initialized_id] =
g_signal_new("initialized",
G_OBJECT_CLASS_TYPE(klass),
@@ -261,12 +178,13 @@
G_TYPE_NONE, 0);
GParamSpec * pspec =
- g_param_spec_pointer(
+ g_param_spec_object(
"control-host-proxy",
"BrowserHost proxy",
"DBusGProxy for a BrowserHost",
+ DBUS_TYPE_G_PROXY,
GParamFlags(G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
- g_object_class_install_property(G_OBJECT_CLASS(klass),
+ g_object_class_install_property(g_object_class,
control_host_proxy_id,
pspec);
@@ -281,47 +199,14 @@
expect_initial_stream_id,
pspec);
- g_type_class_add_private(G_OBJECT_CLASS(klass),
+ g_type_class_add_private(g_object_class,
sizeof (OpenvrmlXembedBrowserPrivate));
- dbus_g_object_type_install_info(OPENVRML_XEMBED_TYPE_BROWSER,
- &dbus_glib_openvrml_xembed_browser_object_info);
+ dbus_g_object_type_install_info(
+ OPENVRML_XEMBED_TYPE_BROWSER,
+ &dbus_glib_openvrml_xembed_browser_object_info);
}
-void openvrml_xembed_browser_set_property(GObject * const obj,
- const guint property_id,
- const GValue * const value,
- GParamSpec * const pspec)
-{
- OpenvrmlXembedBrowser * const browser = OPENVRML_XEMBED_BROWSER(obj);
- switch (property_id) {
- case control_host_proxy_id:
- browser->priv->control_host =
- static_cast<DBusGProxy *>(g_value_get_pointer(value));
- break;
- case expect_initial_stream_id:
- browser->priv->expect_initial_stream = g_value_get_boolean(value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
- }
-}
-
-void openvrml_xembed_browser_get_property(GObject * const obj,
- const guint property_id,
- GValue * const value,
- GParamSpec * const pspec)
-{
- OpenvrmlXembedBrowser * const browser = OPENVRML_XEMBED_BROWSER(obj);
- switch (property_id) {
- case control_host_proxy_id:
- g_value_set_pointer(value, browser->priv->control_host);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
- }
-}
-
namespace {
//
// We don't already know what the URI of the initial stream is until we
@@ -384,17 +269,26 @@
};
}
-void openvrml_xembed_browser_realize(GtkWidget * const widget)
+GObject *
+openvrml_xembed_browser_constructor(
+ GType type,
+ guint n_construct_properties,
+ GObjectConstructParam * construct_properties)
{
- GtkWidgetClass * klass =
- GTK_WIDGET_CLASS(g_type_class_peek(OPENVRML_XEMBED_TYPE_BROWSER));
- GtkWidgetClass * parent_class =
- GTK_WIDGET_CLASS(g_type_class_peek_parent(klass));
- parent_class->realize(widget);
+ GObject * obj;
+ {
+ OpenvrmlXembedBrowserClass * const klass =
+ OPENVRML_XEMBED_BROWSER_CLASS(
+ g_type_class_peek(OPENVRML_XEMBED_TYPE_BROWSER));
+ GObjectClass * const parent_class =
+ G_OBJECT_CLASS(g_type_class_peek_parent(klass));
+ obj = parent_class->constructor(type,
+ n_construct_properties,
+ construct_properties);
+ }
- OpenvrmlXembedBrowser * const browser = OPENVRML_XEMBED_BROWSER(widget);
-
try {
+ OpenvrmlXembedBrowser * const browser = OPENVRML_XEMBED_BROWSER(obj);
browser->priv->uninitialized_streambuf_map =
new openvrml_xembed::uninitialized_plugin_streambuf_map;
browser->priv->streambuf_map =
@@ -407,10 +301,16 @@
new openvrml::browser(*browser->priv->resource_fetcher,
std::cout,
std::cerr);
- browser->priv->drawing_area =
- GTK_DRAWING_AREA(g_object_new(GTK_TYPE_DRAWING_AREA, 0));
- browser->priv->viewer = new GtkGLViewer(*browser);
+ browser->priv->listener = new browser_listener(*browser);
+ browser->priv->browser->add_listener(*browser->priv->listener);
+ browser->priv->browser_plug = 0;
+ browser->priv->browser_plug_mutex = g_mutex_new();
+ browser->priv->browser_plug_set_cond = g_cond_new();
+
+ browser->priv->browser_initialized = false;
+ browser->priv->browser_initialized_mutex = g_mutex_new();
+
//
// If necessary, create the initial stream.
//
@@ -439,92 +339,64 @@
// ex is most likely std::bad_alloc or boost::thread_resource_error.
//
g_critical("%s", ex.what());
- return;
+ return 0;
}
-
- if (!::gl_config) {
- static const int attrib_list[] = {
- // GDK_GL_ALPHA_SIZE, 1,
- GDK_GL_DOUBLEBUFFER,
- GDK_GL_DEPTH_SIZE, 1,
- GDK_GL_RGBA,
- GDK_GL_RED_SIZE, 1,
- GDK_GL_ATTRIB_LIST_NONE
- };
- ::gl_config = gdk_gl_config_new(attrib_list);
- }
-
- static GdkGLContext * const share_list = 0;
- static const gboolean direct = false;
- static const int render_type = GDK_GL_RGBA_TYPE;
- gtk_widget_set_gl_capability(GTK_WIDGET(browser->priv->drawing_area),
- ::gl_config,
- share_list,
- direct,
- render_type);
-
- gtk_widget_add_events(GTK_WIDGET(browser->priv->drawing_area),
- GDK_EXPOSURE_MASK
- | GDK_POINTER_MOTION_MASK
- | GDK_BUTTON_PRESS_MASK
- | GDK_BUTTON_RELEASE_MASK
- | GDK_KEY_PRESS_MASK
- | GDK_FOCUS_CHANGE_MASK);
-
- g_object_set(G_OBJECT(browser->priv->drawing_area),
- "can-focus", true,
- NULL);
-
- g_object_connect(
- G_OBJECT(browser->priv->drawing_area),
-
- "signal::expose_event",
- G_CALLBACK(openvrml_xembed_browser_expose_event),
- browser->priv->viewer,
-
- "signal::configure_event",
- G_CALLBACK(openvrml_xembed_browser_configure_event),
- browser->priv->viewer,
-
- "signal::key_press_event",
- G_CALLBACK(openvrml_xembed_browser_key_press_event),
- browser->priv->viewer,
-
- "signal::button_press_event",
- G_CALLBACK(openvrml_xembed_browser_button_press_event),
- browser->priv->viewer,
-
- "signal::button_release_event",
- G_CALLBACK(openvrml_xembed_browser_button_release_event),
- browser->priv->viewer,
-
- "signal::motion_notify_event",
- G_CALLBACK(openvrml_xembed_browser_motion_notify_event),
- browser->priv->viewer,
- NULL);
-
- gtk_container_add(GTK_CONTAINER(widget),
- GTK_WIDGET(browser->priv->drawing_area));
+ return obj;
}
-void openvrml_xembed_browser_unrealize(GtkWidget * const widget)
+void openvrml_xembed_browser_finalize(GObject * const obj)
{
- OpenvrmlXembedBrowser * const browser = OPENVRML_XEMBED_BROWSER(widget);
+ OpenvrmlXembedBrowser * const browser = OPENVRML_XEMBED_BROWSER(obj);
if (browser->priv->expect_initial_stream) {
browser->priv->initial_stream_reader_thread->join();
delete browser->priv->initial_stream_reader_thread;
}
- delete browser->priv->viewer;
+ g_mutex_free(browser->priv->browser_initialized_mutex);
+ g_cond_free(browser->priv->browser_plug_set_cond);
+ g_mutex_free(browser->priv->browser_plug_mutex);
+ browser->priv->browser->remove_listener(*browser->priv->listener);
+ delete browser->priv->listener;
+ delete browser->priv->browser;
+ delete browser->priv->resource_fetcher;
+ delete browser->priv->streambuf_map;
+ delete browser->priv->uninitialized_streambuf_map;
+}
- GtkWidgetClass * klass =
- GTK_WIDGET_CLASS(g_type_class_peek(OPENVRML_XEMBED_TYPE_BROWSER));
- GtkWidgetClass * parent_class =
- GTK_WIDGET_CLASS(g_type_class_peek_parent(klass));
- parent_class->unrealize(widget);
+void openvrml_xembed_browser_set_property(GObject * const obj,
+ const guint property_id,
+ const GValue * const value,
+ GParamSpec * const pspec)
+{
+ OpenvrmlXembedBrowser * const browser = OPENVRML_XEMBED_BROWSER(obj);
+ switch (property_id) {
+ case control_host_proxy_id:
+ browser->priv->control_host = DBUS_G_PROXY(g_value_get_object(value));
+ break;
+ case expect_initial_stream_id:
+ browser->priv->expect_initial_stream = g_value_get_boolean(value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
+ }
}
+void openvrml_xembed_browser_get_property(GObject * const obj,
+ const guint property_id,
+ GValue * const value,
+ GParamSpec * const pspec)
+{
+ OpenvrmlXembedBrowser * const browser = OPENVRML_XEMBED_BROWSER(obj);
+ switch (property_id) {
+ case control_host_proxy_id:
+ g_value_set_object(value, browser->priv->control_host);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
+ }
+}
+
void
openvrml_xembed_browser_stream_client_interface_init(const gpointer g_iface,
gpointer /* iface_data */)
@@ -536,30 +408,39 @@
iface->write = openvrml_xembed_browser_write;
}
-GtkWidget * openvrml_xembed_browser_new(DBusGProxy * const host_proxy,
- const GdkNativeWindow socket_id,
- const gboolean expect_initial_stream)
+G_GNUC_INTERNAL
+GSource *
+openvrml_xembed_browser_ready_source_new(OpenvrmlXembedBrowser * browser,
+ guint64 host_id);
+
+OpenvrmlXembedBrowser *
+openvrml_xembed_browser_new(DBusGProxy * const host_proxy,
+ const gboolean expect_initial_stream,
+ GMainContext * const gtk_thread_context,
+ const GdkNativeWindow socket_id)
{
- GtkWidget * browser =
- GTK_WIDGET(g_object_new(OPENVRML_XEMBED_TYPE_BROWSER,
- "control-host-proxy", host_proxy,
- "expect-initial-stream", expect_initial_stream,
- 0));
- gtk_plug_construct(GTK_PLUG(browser), socket_id);
- return browser;
-}
+ OpenvrmlXembedBrowser * const browser =
+ OPENVRML_XEMBED_BROWSER(
+ g_object_new(OPENVRML_XEMBED_TYPE_BROWSER,
+ "control-host-proxy", host_proxy,
+ "expect-initial-stream", expect_initial_stream,
+ 0));
+ if (!browser) { return 0; }
+ scope_guard browser_guard = make_guard(g_object_unref, browser);
-GtkWidget * openvrml_xembed_browser_new_for_display(DBusGProxy * const host_proxy,
- GdkDisplay * const display,
- const GdkNativeWindow socket_id,
- const gboolean expect_initial_stream)
-{
- GtkWidget * browser =
- GTK_WIDGET(g_object_new(OPENVRML_XEMBED_TYPE_BROWSER,
- "control-host-proxy", host_proxy,
- "expect-initial-stream", expect_initial_stream,
- 0));
- gtk_plug_construct_for_display(GTK_PLUG(browser), display, socket_id);
+ GSource * const browser_ready_source =
+ openvrml_xembed_browser_ready_source_new(browser, socket_id);
+ if (!browser_ready_source) { return 0; }
+ scope_guard browser_ready_source_guard =
+ make_guard(g_object_unref, browser_ready_source);
+
+ gdk_threads_enter();
+ g_source_attach(browser_ready_source, gtk_thread_context);
+ gdk_threads_leave();
+
+ browser_ready_source_guard.dismiss();
+ browser_guard.dismiss();
+
return browser;
}
@@ -597,7 +478,7 @@
return false;
}
}
- g_assert(streambuf->state() == plugin_streambuf::uninitialized);
+ g_assert(streambuf->state() != plugin_streambuf::initialized);
streambuf->init(stream_id, url, type);
return true;
}
@@ -659,52 +540,542 @@
return true;
}
-gboolean openvrml_xembed_browser_expose_event(GtkWidget * const widget,
- GdkEventExpose * const event,
- const gpointer user_data)
+namespace {
+ struct G_GNUC_INTERNAL load_url {
+ load_url(OpenvrmlXembedBrowser & browser,
+ const std::vector<std::string> & url,
+ const std::vector<std::string> & parameter):
+ browser_(browser),
+ url_(url),
+ parameter_(parameter)
+ {}
+
+ void operator()() const OPENVRML_NOTHROW
+ {
+ try {
+ g_mutex_lock(this->browser_.priv->browser_initialized_mutex);
+ this->browser_.priv->browser_initialized = false;
+ g_mutex_unlock(this->browser_.priv->browser_initialized_mutex);
+ this->browser_.priv->browser->load_url(this->url_,
+ this->parameter_);
+ } catch (std::exception & ex) {
+ this->browser_.priv->browser->err(ex.what());
+ }
+ }
+
+ private:
+ OpenvrmlXembedBrowser & browser_;
+ const std::vector<std::string> url_, parameter_;
+ };
+}
+
+gboolean
+openvrml_xembed_browser_load_url(OpenvrmlXembedBrowser * const vrml_browser,
+ const gchar ** url,
+ const gchar ** parameter,
+ GError ** error)
{
+ using std::string;
+ using std::vector;
+
+ try {
+ vector<string> url_vec, param_vec;
+ while (url && *url) { url_vec.push_back(*(url++)); }
+ while (parameter && *parameter) { param_vec.push_back(*(parameter++)); }
+
+ vrml_browser->priv->resource_fetcher
+ ->create_thread(load_url(*vrml_browser, url_vec, param_vec));
+ } catch (const std::bad_alloc & ex) {
+ *error = g_error_new(OPENVRML_XEMBED_ERROR,
+ OPENVRML_XEMBED_ERROR_NO_MEMORY,
+ "out of memory");
+ return false;
+ } catch (const std::exception & ex) {
+ *error = g_error_new(OPENVRML_XEMBED_ERROR,
+ OPENVRML_XEMBED_ERROR_FAILED,
+ ex.what());
+ return false;
+ }
+ return true;
+}
+
+guint64 openvrml_xembed_browser_get_id(OpenvrmlXembedBrowser * const browser)
+{
+ g_assert(browser);
+ g_mutex_lock(browser->priv->browser_plug_mutex);
+ while (!browser->priv->browser_plug) {
+ g_cond_wait(browser->priv->browser_plug_set_cond,
+ browser->priv->browser_plug_mutex);
+ }
+ g_assert(browser->priv->browser_plug);
+ const guint64 id = gtk_plug_get_id(GTK_PLUG(browser->priv->browser_plug));
+ g_mutex_unlock(browser->priv->browser_plug_mutex);
+ return id;
+}
+
+gboolean
+openvrml_xembed_browser_new_stream(OpenvrmlXembedBrowser * const browser,
+ const guint64 stream_id,
+ const char * const type,
+ const char * const url,
+ GError ** const error)
+{
+ return openvrml_xembed_stream_client_new_stream(
+ OPENVRML_XEMBED_STREAM_CLIENT(browser),
+ stream_id,
+ type,
+ url,
+ error);
+}
+
+gboolean
+openvrml_xembed_browser_destroy_stream(OpenvrmlXembedBrowser * const browser,
+ const guint64 stream_id,
+ GError ** const error)
+{
+ return openvrml_xembed_stream_client_destroy_stream(
+ OPENVRML_XEMBED_STREAM_CLIENT(browser),
+ stream_id,
+ error);
+}
+
+gboolean openvrml_xembed_browser_write(OpenvrmlXembedBrowser * const browser,
+ const guint64 stream_id,
+ const GArray * const data,
+ GError ** const error)
+{
+ return openvrml_xembed_stream_client_write(
+ OPENVRML_XEMBED_STREAM_CLIENT(browser),
+ stream_id,
+ data,
+ error);
+}
+
+gchar *
+openvrml_xembed_browser_get_world_url(
+ OpenvrmlXembedBrowser * const vrml_browser,
+ GError ** /* error */)
+{
+ return g_strdup(vrml_browser->priv->browser->world_url().c_str());
+}
+
+gboolean
+openvrml_xembed_browser_initialized(OpenvrmlXembedBrowser * const browser)
+{
+ g_mutex_lock(browser->priv->browser_initialized_mutex);
+ const bool browser_initialized = browser->priv->browser_initialized;
+ g_mutex_unlock(browser->priv->browser_initialized_mutex);
+ return browser_initialized;
+}
+
+
+G_DEFINE_TYPE(OpenvrmlXembedBrowserPlug,
+ openvrml_xembed_browser_plug,
+ GTK_TYPE_PLUG);
+
+extern "C" {
+ G_GNUC_INTERNAL
+ void openvrml_xembed_browser_plug_set_property(GObject * obj,
+ guint property_id,
+ const GValue * value,
+ GParamSpec * pspec);
+
+ G_GNUC_INTERNAL
+ void openvrml_xembed_browser_plug_get_property(GObject * obj,
+ guint property_id,
+ GValue * value,
+ GParamSpec * pspec);
+
+ G_GNUC_INTERNAL
+ void openvrml_xembed_browser_plug_realize(GtkWidget * widget);
+
+ G_GNUC_INTERNAL
+ void openvrml_xembed_browser_plug_unrealize(GtkWidget * widget);
+
+ //
+ // Signal handlers
+ //
+ G_GNUC_INTERNAL
+ gboolean
+ openvrml_xembed_drawing_area_expose_event(
+ GtkWidget * widget,
+ GdkEventExpose * event,
+ OpenvrmlXembedBrowserPlug * browser_plug);
+
+ G_GNUC_INTERNAL
+ gboolean
+ openvrml_xembed_drawing_area_configure_event(
+ GtkWidget * widget,
+ GdkEventConfigure * event,
+ OpenvrmlXembedBrowserPlug * browser_plug);
+
+ G_GNUC_INTERNAL
+ gboolean
+ openvrml_xembed_drawing_area_key_press_event(
+ GtkWidget * widget,
+ GdkEventKey * event,
+ OpenvrmlXembedBrowserPlug * browser_plug);
+
+ G_GNUC_INTERNAL
+ gboolean
+ openvrml_xembed_drawing_area_button_press_event(
+ GtkWidget * widget,
+ GdkEventButton * event,
+ OpenvrmlXembedBrowserPlug * browser_plug);
+
+ G_GNUC_INTERNAL
+ gboolean
+ openvrml_xembed_drawing_area_button_release_event(
+ GtkWidget * widget,
+ GdkEventButton * event,
+ OpenvrmlXembedBrowserPlug * browser_plug);
+
+ G_GNUC_INTERNAL
+ gboolean
+ openvrml_xembed_drawing_area_motion_notify_event(
+ GtkWidget * widget,
+ GdkEventMotion * event,
+ OpenvrmlXembedBrowserPlug * browser_plug);
+
+ G_GNUC_INTERNAL
+ gint openvrml_xembed_browser_plug_timeout_callback(gpointer ptr);
+
+ G_GNUC_INTERNAL
+ void browser_initialized(OpenvrmlXembedBrowser *,
+ OpenvrmlXembedBrowserPlug *);
+}
+
+namespace {
+
+ G_GNUC_INTERNAL GdkGLConfig * gl_config;
+
+
+ class G_GNUC_INTERNAL GtkGLViewer : public openvrml::gl::viewer {
+ friend
+ void (::openvrml_xembed_browser_plug_realize)(GtkWidget * widget);
+
+ friend gboolean
+ (::openvrml_xembed_drawing_area_expose_event)(
+ GtkWidget *,
+ GdkEventExpose *,
+ OpenvrmlXembedBrowserPlug *);
+
+ friend void (::browser_initialized)(OpenvrmlXembedBrowser *,
+ OpenvrmlXembedBrowserPlug *);
+
+ OpenvrmlXembedBrowserPlug & browser_plug_;
+ guint timer;
+
+ public:
+ explicit GtkGLViewer(OpenvrmlXembedBrowserPlug & browser_plug);
+ virtual ~GtkGLViewer() throw ();
+
+ void timer_update();
+
+ protected:
+ //
+ // Implement pure virtual methods from openvrml::gl::viewer.
+ //
+ virtual void post_redraw();
+ virtual void set_cursor(openvrml::gl::viewer::cursor_style);
+ virtual void swap_buffers();
+ virtual void set_timer(double);
+ };
+}
+
+struct OpenvrmlXembedBrowserPlugPrivate_ {
+ OpenvrmlXembedBrowser * browser;
+ GtkDrawingArea * drawing_area;
+ GtkGLViewer * viewer;
+ bool redraw_needed;
+};
+
+# define OPENVRML_XEMBED_BROWSER_PLUG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), OPENVRML_XEMBED_TYPE_BROWSER_PLUG, OpenvrmlXembedBrowserPlugPrivate))
+
+void
+openvrml_xembed_browser_plug_init(
+ OpenvrmlXembedBrowserPlug * const browser_plug)
+{
+ browser_plug->priv = OPENVRML_XEMBED_BROWSER_PLUG_GET_PRIVATE(browser_plug);
+}
+
+namespace {
+ enum browser_plug_property_id {
+ browser_id = 1
+ };
+}
+
+void
+openvrml_xembed_browser_plug_class_init(
+ OpenvrmlXembedBrowserPlugClass * const klass)
+{
+ GObjectClass * const g_object_class = G_OBJECT_CLASS(klass);
+ g_object_class->set_property = openvrml_xembed_browser_plug_set_property;
+ g_object_class->get_property = openvrml_xembed_browser_plug_get_property;
+
+ GtkWidgetClass * const gtk_widget_class = GTK_WIDGET_CLASS(klass);
+ gtk_widget_class->realize = openvrml_xembed_browser_plug_realize;
+ gtk_widget_class->unrealize = openvrml_xembed_browser_plug_unrealize;
+
+ GParamSpec * pspec =
+ g_param_spec_object(
+ "browser",
+ "OpenvrmlXembedBrowser",
+ "The OpenvrmlXembedBrowser associated with the plug",
+ OPENVRML_XEMBED_TYPE_BROWSER,
+ GParamFlags(G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
+ g_object_class_install_property(g_object_class, browser_id, pspec);
+
+ g_type_class_add_private(g_object_class,
+ sizeof (OpenvrmlXembedBrowserPrivate));
+}
+
+void openvrml_xembed_browser_plug_set_property(GObject * const obj,
+ const guint property_id,
+ const GValue * const value,
+ GParamSpec * const pspec)
+{
+ OpenvrmlXembedBrowserPlug * const browser_plug =
+ OPENVRML_XEMBED_BROWSER_PLUG(obj);
+ switch (property_id) {
+ case browser_id:
+ g_assert(browser_plug->priv->browser == 0);
+ browser_plug->priv->browser =
+ OPENVRML_XEMBED_BROWSER(g_value_get_object(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
+ }
+}
+
+void openvrml_xembed_browser_plug_get_property(GObject * const obj,
+ const guint property_id,
+ GValue * const value,
+ GParamSpec * const pspec)
+{
+ OpenvrmlXembedBrowserPlug * const browser_plug =
+ OPENVRML_XEMBED_BROWSER_PLUG(obj);
+ switch (property_id) {
+ case browser_id:
+ g_value_set_object(value, browser_plug->priv->browser);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
+ }
+}
+
+GtkWidget *
+openvrml_xembed_browser_plug_new(OpenvrmlXembedBrowser * browser,
+ GdkNativeWindow socket_id)
+{
+ GtkWidget * browser_plug =
+ GTK_WIDGET(g_object_new(OPENVRML_XEMBED_TYPE_BROWSER_PLUG,
+ "browser", browser,
+ 0));
+ gtk_plug_construct(GTK_PLUG(browser_plug), socket_id);
+
+ g_signal_connect_data(browser,
+ "initialized",
+ G_CALLBACK(browser_initialized),
+ browser_plug,
+ 0,
+ GConnectFlags(0));
+
+ return browser_plug;
+}
+
+void browser_initialized(OpenvrmlXembedBrowser * /* browser */,
+ OpenvrmlXembedBrowserPlug * const browser_plug)
+{
+ g_assert(OPENVRML_XEMBED_IS_BROWSER_PLUG(browser_plug));
+ //
+ // Set redraw_needed to false to ensure that the following call to
+ // post_redraw results in a redraw.
+ //
+ browser_plug->priv->redraw_needed = false;
+
+ //
+ // viewer will be nonnull if the plug has been realized.
+ //
+ if (browser_plug->priv->viewer) {
+ browser_plug->priv->viewer->post_redraw();
+ }
+}
+
+void openvrml_xembed_browser_plug_realize(GtkWidget * const widget)
+{
+ GtkWidgetClass * klass =
+ GTK_WIDGET_CLASS(
+ g_type_class_peek(OPENVRML_XEMBED_TYPE_BROWSER_PLUG));
+ GtkWidgetClass * parent_class =
+ GTK_WIDGET_CLASS(g_type_class_peek_parent(klass));
+ parent_class->realize(widget);
+
+ OpenvrmlXembedBrowserPlug * const browser_plug =
+ OPENVRML_XEMBED_BROWSER_PLUG(widget);
+
+ {
+ OpenvrmlXembedBrowser * browser = 0;
+ g_object_get(browser_plug,
+ "browser", &browser,
+ NULL);
+
+ g_assert(browser);
+ scope_guard browser_guard = make_guard(g_object_unref, browser);
+ boost::ignore_unused_variable_warning(browser_guard);
+
+ browser_plug->priv->drawing_area =
+ GTK_DRAWING_AREA(g_object_new(GTK_TYPE_DRAWING_AREA, 0));
+
+ try {
+ browser_plug->priv->viewer = new GtkGLViewer(*browser_plug);
+ } catch (const std::exception & ex) {
+ //
+ // ex is most likely std::bad_alloc.
+ //
+ g_critical("%s", ex.what());
+ return;
+ }
+ } // unref the OpenvrmlXembedBrowser.
+
+ if (!::gl_config) {
+ static const int attrib_list[] = {
+ // GDK_GL_ALPHA_SIZE, 1,
+ GDK_GL_DOUBLEBUFFER,
+ GDK_GL_DEPTH_SIZE, 1,
+ GDK_GL_RGBA,
+ GDK_GL_RED_SIZE, 1,
+ GDK_GL_ATTRIB_LIST_NONE
+ };
+ ::gl_config = gdk_gl_config_new(attrib_list);
+ }
+
+ static GdkGLContext * const share_list = 0;
+ static const gboolean direct = false;
+ static const int render_type = GDK_GL_RGBA_TYPE;
+ gtk_widget_set_gl_capability(GTK_WIDGET(browser_plug->priv->drawing_area),
+ ::gl_config,
+ share_list,
+ direct,
+ render_type);
+
+ gtk_widget_add_events(GTK_WIDGET(browser_plug->priv->drawing_area),
+ GDK_EXPOSURE_MASK
+ | GDK_POINTER_MOTION_MASK
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK
+ | GDK_KEY_PRESS_MASK
+ | GDK_FOCUS_CHANGE_MASK);
+
+ g_object_set(G_OBJECT(browser_plug->priv->drawing_area),
+ "can-focus", true,
+ NULL);
+
+ g_object_connect(
+ G_OBJECT(browser_plug->priv->drawing_area),
+
+ "signal::expose_event",
+ G_CALLBACK(openvrml_xembed_drawing_area_expose_event),
+ browser_plug,
+
+ "signal::configure_event",
+ G_CALLBACK(openvrml_xembed_drawing_area_configure_event),
+ browser_plug,
+
+ "signal::key_press_event",
+ G_CALLBACK(openvrml_xembed_drawing_area_key_press_event),
+ browser_plug,
+
+ "signal::button_press_event",
+ G_CALLBACK(openvrml_xembed_drawing_area_button_press_event),
+ browser_plug,
+
+ "signal::button_release_event",
+ G_CALLBACK(openvrml_xembed_drawing_area_button_release_event),
+ browser_plug,
+
+ "signal::motion_notify_event",
+ G_CALLBACK(openvrml_xembed_drawing_area_motion_notify_event),
+ browser_plug,
+ NULL);
+
+ gtk_container_add(GTK_CONTAINER(widget),
+ GTK_WIDGET(browser_plug->priv->drawing_area));
+
+ //
+ // If the browser has already been initialized, get things moving.
+ //
+ if (openvrml_xembed_browser_initialized(browser_plug->priv->browser)) {
+ browser_plug->priv->viewer->post_redraw();
+ }
+}
+
+void openvrml_xembed_browser_plug_unrealize(GtkWidget * const widget)
+{
+ OpenvrmlXembedBrowserPlug * const browser_plug =
+ OPENVRML_XEMBED_BROWSER_PLUG(widget);
+
+ delete browser_plug->priv->viewer;
+ browser_plug->priv->viewer = 0;
+ gtk_widget_destroy(GTK_WIDGET(browser_plug->priv->drawing_area));
+ browser_plug->priv->drawing_area = 0;
+
+ GtkWidgetClass * klass =
+ GTK_WIDGET_CLASS(g_type_class_peek(OPENVRML_XEMBED_TYPE_BROWSER_PLUG));
+ GtkWidgetClass * parent_class =
+ GTK_WIDGET_CLASS(g_type_class_peek_parent(klass));
+ parent_class->unrealize(widget);
+}
+
+gboolean
+openvrml_xembed_drawing_area_expose_event(
+ GtkWidget * const widget,
+ GdkEventExpose * const event,
+ OpenvrmlXembedBrowserPlug * const browser_plug)
+{
GdkGLDrawable * const gl_drawable = gtk_widget_get_gl_drawable(widget);
g_assert(gl_drawable);
GdkGLContext * const gl_context = gtk_widget_get_gl_context(widget);
g_assert(gl_context);
- GtkGLViewer * viewer = static_cast<GtkGLViewer *>(user_data);
- g_return_val_if_fail(viewer, true);
- {
- openvrml::read_write_mutex::scoped_read_lock
- lock(viewer->browser_initialized_mutex_);
- if (!viewer->browser_initialized_) { return true; }
+
+ if (!openvrml_xembed_browser_initialized(browser_plug->priv->browser)) {
+ return true;
}
if (event->count == 0
&& gdk_gl_drawable_make_current(gl_drawable, gl_context)) {
- viewer->redraw();
+ browser_plug->priv->viewer->redraw();
}
- viewer->redrawNeeded = false;
- if (viewer->timer == 0) { viewer->timer_update(); }
+ browser_plug->priv->redraw_needed = false;
+ if (browser_plug->priv->viewer->timer == 0) {
+ browser_plug->priv->viewer->timer_update();
+ }
return true;
}
-gboolean openvrml_xembed_browser_configure_event(GtkWidget * const widget,
- GdkEventConfigure *,
- const gpointer user_data)
+gboolean
+openvrml_xembed_drawing_area_configure_event(
+ GtkWidget * const widget,
+ GdkEventConfigure *,
+ OpenvrmlXembedBrowserPlug * const browser_plug)
{
GdkGLDrawable * const gl_drawable = gtk_widget_get_gl_drawable(widget);
g_assert(gl_drawable);
GdkGLContext * const gl_context = gtk_widget_get_gl_context(widget);
g_assert(gl_context);
- GtkGLViewer * const viewer = static_cast<GtkGLViewer *>(user_data);
- g_return_val_if_fail(viewer, true);
-
if (gdk_gl_drawable_make_current(gl_drawable, gl_context)) {
- viewer->resize(widget->allocation.width, widget->allocation.height);
+ browser_plug->priv->viewer->resize(widget->allocation.width,
+ widget->allocation.height);
}
return true;
}
-gboolean openvrml_xembed_browser_key_press_event(GtkWidget * const widget,
- GdkEventKey * const event,
- const gpointer user_data)
+gboolean
+openvrml_xembed_drawing_area_key_press_event(
+ GtkWidget * const widget,
+ GdkEventKey * const event,
+ OpenvrmlXembedBrowserPlug * const browser_plug)
{
using openvrml::gl::viewer;
@@ -749,16 +1120,16 @@
GdkGLContext * const gl_context = gtk_widget_get_gl_context(widget);
g_assert(gl_context);
if (gdk_gl_drawable_make_current(gl_drawable, gl_context)) {
- GtkGLViewer * const viewer = static_cast<GtkGLViewer *>(user_data);
- viewer->input(&info);
+ browser_plug->priv->viewer->input(&info);
}
return true;
}
gboolean
-openvrml_xembed_browser_button_press_event(GtkWidget * const widget,
- GdkEventButton * const event,
- const gpointer user_data)
+openvrml_xembed_drawing_area_button_press_event(
+ GtkWidget * const widget,
+ GdkEventButton * const event,
+ OpenvrmlXembedBrowserPlug * const browser_plug)
{
using openvrml::gl::viewer;
@@ -788,16 +1159,16 @@
GdkGLContext * const gl_context = gtk_widget_get_gl_context(widget);
g_assert(gl_context);
if (gdk_gl_drawable_make_current(gl_drawable, gl_context)) {
- GtkGLViewer * const viewer = static_cast<GtkGLViewer *>(user_data);
- viewer->input(&info);
+ browser_plug->priv->viewer->input(&info);
}
return true;
}
gboolean
-openvrml_xembed_browser_button_release_event(GtkWidget * const widget,
- GdkEventButton * const event,
- const gpointer user_data)
+openvrml_xembed_drawing_area_button_release_event(
+ GtkWidget * const widget,
+ GdkEventButton * const event,
+ OpenvrmlXembedBrowserPlug * const browser_plug)
{
using openvrml::gl::viewer;
@@ -825,16 +1196,16 @@
GdkGLContext * const gl_context = gtk_widget_get_gl_context(widget);
g_assert(gl_context);
if (gdk_gl_drawable_make_current(gl_drawable, gl_context)) {
- GtkGLViewer * const viewer = static_cast<GtkGLViewer *>(user_data);
- viewer->input(&info);
+ browser_plug->priv->viewer->input(&info);
}
return true;
}
gboolean
-openvrml_xembed_browser_motion_notify_event(GtkWidget * const widget,
- GdkEventMotion * const event,
- const gpointer user_data)
+openvrml_xembed_drawing_area_motion_notify_event(
+ GtkWidget * const widget,
+ GdkEventMotion * const event,
+ OpenvrmlXembedBrowserPlug * const browser_plug)
{
using openvrml::gl::viewer;
@@ -859,16 +1230,15 @@
g_assert(gl_context);
if (gdk_gl_drawable_make_current(gl_drawable, gl_context)) {
- GtkGLViewer * const viewer = static_cast<GtkGLViewer *>(user_data);
- openvrml::read_write_mutex::scoped_read_lock
- lock(viewer->browser_initialized_mutex_);
- if (!viewer->browser_initialized_) { return true; }
- viewer->input(&info);
+ if (!openvrml_xembed_browser_initialized(browser_plug->priv->browser)) {
+ return true;
+ }
+ browser_plug->priv->viewer->input(&info);
}
return true;
}
-gint openvrml_xembed_browser_timeout_callback(const gpointer ptr)
+gint openvrml_xembed_browser_plug_timeout_callback(const gpointer ptr)
{
g_assert(ptr);
@@ -878,141 +1248,7 @@
}
namespace {
- struct GtkGLViewer::load_url {
- load_url(GtkGLViewer & viewer,
- const std::vector<std::string> & url,
- const std::vector<std::string> & parameter):
- viewer_(&viewer),
- url_(url),
- parameter_(parameter)
- {}
- void operator()() const OPENVRML_NOTHROW
- {
- try {
- {
- openvrml::read_write_mutex::scoped_write_lock
- lock(this->viewer_->browser_initialized_mutex_);
- this->viewer_->browser_initialized_ = false;
- }
- this->viewer_->vrml_browser_.priv->browser
- ->load_url(this->url_, this->parameter_);
- } catch (std::exception & ex) {
- this->viewer_->vrml_browser_.priv->browser->err(ex.what());
- }
- }
-
- private:
- GtkGLViewer * const viewer_;
- const std::vector<std::string> url_, parameter_;
- };
-}
-
-gboolean
-openvrml_xembed_browser_load_url(OpenvrmlXembedBrowser * const vrml_browser,
- const gchar ** url,
- const gchar ** parameter,
- GError ** /* error */)
-{
- using std::string;
- using std::vector;
-
- vector<string> url_vec, param_vec;
- while (url && *url) { url_vec.push_back(*(url++)); }
- while (parameter && *parameter) { param_vec.push_back(*(parameter++)); }
-
- vrml_browser->priv->resource_fetcher
- ->create_thread(GtkGLViewer::load_url(*vrml_browser->priv->viewer,
- url_vec, param_vec));
- return true;
-}
-
-guint64 openvrml_xembed_browser_get_id(OpenvrmlXembedBrowser * const browser)
-{
- g_assert(browser);
-// gdk_threads_enter();
-// scope_guard gdk_threads_guard = make_guard(gdk_threads_leave);
- return gtk_plug_get_id(&browser->parent);
-}
-
-gboolean openvrml_xembed_browser_new_stream(OpenvrmlXembedBrowser * const browser,
- const guint64 stream_id,
- const char * const type,
- const char * const url,
- GError ** const error)
-{
- return openvrml_xembed_stream_client_new_stream(
- OPENVRML_XEMBED_STREAM_CLIENT(browser),
- stream_id,
- type,
- url,
- error);
-}
-
-gboolean
-openvrml_xembed_browser_destroy_stream(OpenvrmlXembedBrowser * const browser,
- const guint64 stream_id,
- GError ** const error)
-{
- return openvrml_xembed_stream_client_destroy_stream(
- OPENVRML_XEMBED_STREAM_CLIENT(browser),
- stream_id,
- error);
-}
-
-gboolean openvrml_xembed_browser_write(OpenvrmlXembedBrowser * const browser,
- const guint64 stream_id,
- const GArray * const data,
- GError ** const error)
-{
- return openvrml_xembed_stream_client_write(
- OPENVRML_XEMBED_STREAM_CLIENT(browser),
- stream_id,
- data,
- error);
-}
-
-gchar *
-openvrml_xembed_browser_get_world_url(
- OpenvrmlXembedBrowser * const vrml_browser,
- GError ** /* error */)
-{
- return g_strdup(vrml_browser->priv->browser->world_url().c_str());
-}
-
-extern "C"
-OPENVRML_LOCAL
-void openvrml_xembed_get_url_notify(DBusGProxy * const proxy,
- DBusGProxyCall * const call_id,
- void * const user_data)
-{
- using openvrml_xembed::plugin_streambuf;
-
- gint get_url_result;
-
- GError * error = 0;
- scope_guard error_guard = make_guard(g_error_free, boost::ref(error));
- const gboolean result =
- dbus_g_proxy_end_call(proxy, call_id, &error,
- G_TYPE_INT, &get_url_result,
- G_TYPE_INVALID);
-
- if (!result) {
- g_critical("Call to org.openvrml.BrowserHost.GetUrl failed: %s",
- error->message);
- return;
- }
-
- plugin_streambuf * const streambuf =
- static_cast<plugin_streambuf *>(user_data);
-
- streambuf->set_get_url_result(get_url_result);
-
- error_guard.dismiss();
-}
-
-namespace {
-
resource_fetcher::resource_fetcher(
DBusGProxy & control_host,
openvrml_xembed::uninitialized_plugin_streambuf_map &
@@ -1071,28 +1307,22 @@
GError * error = 0;
scope_guard error_guard = make_guard(g_error_free,
boost::ref(error));
- DBusGProxyCall * get_url_call =
- ...
[truncated message content] |