From: Ben Hutchings Date: Tue, 20 Dec 2005 00:29:40 +0000 (+0000) Subject: Renamed various types to fit lower_case_with_underscores convention. X-Git-Tag: 0.6~12 X-Git-Url: https://git.decadent.org.uk/gitweb/?p=videolink.git;a=commitdiff_plain;h=0acb5f1329d294faf42e247f8c2daf68d82150f6 Renamed various types to fit lower_case_with_underscores convention. Renamed FrameBuffer to the more specific x_frame_buffer and removed "x_" from its accessor function names. Renamed files to match function/class names. --- diff --git a/Makefile b/Makefile index 989ef7d..caffd0f 100644 --- a/Makefile +++ b/Makefile @@ -31,9 +31,9 @@ else endif cxxsources := \ - auto_proc.cpp browserwidget.cpp childiterator.cpp framebuffer.cpp \ - linkiterator.cpp pixbufs.cpp stylesheets.cpp temp_file.cpp video.cpp \ - webdvd.cpp xpcom_support.cpp + auto_proc.cpp browser_widget.cpp child_iterator.cpp \ + link_iterator.cpp pixbufs.cpp style_sheets.cpp temp_file.cpp video.cpp \ + webdvd.cpp x_frame_buffer.cpp xpcom_support.cpp csources := jquant2.c webdvd : $(cxxsources:.cpp=.o) $(csources:.c=.o) @@ -52,7 +52,7 @@ install : .PHONY : clean distclean install -browserwidget.% : CPPFLAGS += -DMOZ_LIB_DIR='"$(moz_lib_dir)"' +browser_widget.% : CPPFLAGS += -DMOZ_LIB_DIR='"$(moz_lib_dir)"' webdvd.% \ : CPPFLAGS += -DWEBDVD_LIB_DIR='"$(webdvd_lib_dir)"' \ @@ -60,16 +60,16 @@ webdvd.% \ -DMOZ_VERSION_MINOR=$(moz_version_minor) \ -DMOZ_VERSION_PATCHLEVEL=$(moz_version_patchlevel) -browserwidget.% pixbufs.% temp_file.% webdvd.% \ +browser_widget.% pixbufs.% temp_file.% webdvd.% \ : CPPFLAGS += $(shell pkg-config --cflags gtkmm-2.0) -browserwidget.% childiterator.o linkiterator.% stylesheets.% webdvd.% \ -xpcom_support.% \ +browser_widget.% child_iterator.o link_iterator.% style_sheets.% webdvd.% \ +xpcom_support.% \ : CPPFLAGS += $(shell pkg-config --cflags mozilla-gtkmozembed) # These dig a bit deeper into Mozilla -linkiterator.% stylesheets.% webdvd.% \ - : CPPFLAGS += $(addprefix -I$(moz_include_dir)/, \ +link_iterator.% style_sheets.% webdvd.% \ + : CPPFLAGS += $(addprefix -I$(moz_include_dir)/, \ content docshell dom gfx layout necko webshell widget) %.d : %.cpp diff --git a/browser_widget.cpp b/browser_widget.cpp new file mode 100644 index 0000000..0f6b53d --- /dev/null +++ b/browser_widget.cpp @@ -0,0 +1,539 @@ +// Copyright 2005 Ben Hutchings . +// See the file "COPYING" for licence details. + +#include "browser_widget.hpp" + +#include + +#include + +browser_widget::browser_widget() + : Gtk::Bin(GTK_BIN(gtk_moz_embed_new())) +{ +} +browser_widget::~browser_widget() +{ +} + +GtkMozEmbed * browser_widget::gobj() +{ + return GTK_MOZ_EMBED(gobject_); +} +const GtkMozEmbed * browser_widget::gobj() const +{ + return GTK_MOZ_EMBED(gobject_); +} + +void browser_widget::load_uri(const char * uri) +{ + gtk_moz_embed_load_url(gobj(), uri); +} +void browser_widget::load_uri(const std::string & uri) +{ + return load_uri(uri.c_str()); +} +void browser_widget::stop_load() +{ + gtk_moz_embed_stop_load(gobj()); +} +void browser_widget::go_back() +{ + gtk_moz_embed_go_back(gobj()); +} +void browser_widget::go_forward() +{ + gtk_moz_embed_go_forward(gobj()); +} +void browser_widget::reload(gint32 flags) +{ + gtk_moz_embed_reload(gobj(), flags); +} + +bool browser_widget::can_go_back() const +{ + return gtk_moz_embed_can_go_back(const_cast(gobj())); +} +bool browser_widget::can_go_forward() const +{ + return gtk_moz_embed_can_go_forward(const_cast(gobj())); +} + +namespace +{ + template + class c_scoped_ptr + { + public: + explicit c_scoped_ptr(T * p = 0) : p_(p) {} + ~c_scoped_ptr() { free(p_); } + T * get() const { return p_; } + T * release() + { + T * p = p_; + p_ = NULL; + return p; + } + void reset(T * p = 0) + { + free(p_); + p_ = p; + } + private: + T * p_; + }; +} + +std::string browser_widget::get_link_message() const +{ + c_scoped_ptr str( + gtk_moz_embed_get_link_message(const_cast(gobj()))); + return std::string(str.get()); +} +std::string browser_widget::get_js_status() const +{ + c_scoped_ptr str( + gtk_moz_embed_get_js_status(const_cast(gobj()))); + return std::string(str.get()); +} +std::string browser_widget::get_title() const +{ + c_scoped_ptr str( + gtk_moz_embed_get_title(const_cast(gobj()))); + return std::string(str.get()); +} +std::string browser_widget::get_location() const +{ + c_scoped_ptr str( + gtk_moz_embed_get_location(const_cast(gobj()))); + return std::string(str.get()); +} +already_AddRefed browser_widget::get_browser() +{ + nsIWebBrowser * result = 0; + gtk_moz_embed_get_nsIWebBrowser(gobj(), &result); + assert(result); + return dont_AddRef(result); +} + +namespace +{ + void browser_widget_signal_link_message_callback(GtkMozEmbed * self, void * data) + { + typedef SigC::Slot0 SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) + { + try + { + if (SigC::SlotNode * const slot = + Glib::SignalProxyNormal::data_to_slot(data)) + (*(SlotType::Proxy)(slot->proxy_))(slot); + } + catch(...) + { + Glib::exception_handlers_invoke(); + } + } + } + + const Glib::SignalProxyInfo browser_widget_signal_link_message_info = + { + "link_message", + (GCallback) &browser_widget_signal_link_message_callback, + (GCallback) &browser_widget_signal_link_message_callback + }; + + void browser_widget_signal_js_status_callback(GtkMozEmbed * self, void * data) + { + typedef SigC::Slot0 SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) + { + try + { + if (SigC::SlotNode * const slot = + Glib::SignalProxyNormal::data_to_slot(data)) + (*(SlotType::Proxy)(slot->proxy_))(slot); + } + catch(...) + { + Glib::exception_handlers_invoke(); + } + } + } + + const Glib::SignalProxyInfo browser_widget_signal_js_status_info = + { + "js_status", + (GCallback) &browser_widget_signal_js_status_callback, + (GCallback) &browser_widget_signal_js_status_callback + }; + + void browser_widget_signal_location_callback(GtkMozEmbed * self, void * data) + { + typedef SigC::Slot0 SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) + { + try + { + if (SigC::SlotNode * const slot = + Glib::SignalProxyNormal::data_to_slot(data)) + (*(SlotType::Proxy)(slot->proxy_))(slot); + } + catch(...) + { + Glib::exception_handlers_invoke(); + } + } + } + + const Glib::SignalProxyInfo browser_widget_signal_location_info = + { + "location", + (GCallback) &browser_widget_signal_location_callback, + (GCallback) &browser_widget_signal_location_callback + }; + + void browser_widget_signal_title_callback(GtkMozEmbed * self, void * data) + { + typedef SigC::Slot0 SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) + { + try + { + if (SigC::SlotNode * const slot = + Glib::SignalProxyNormal::data_to_slot(data)) + (*(SlotType::Proxy)(slot->proxy_))(slot); + } + catch(...) + { + Glib::exception_handlers_invoke(); + } + } + } + + const Glib::SignalProxyInfo browser_widget_signal_title_info = + { + "title", + (GCallback) &browser_widget_signal_title_callback, + (GCallback) &browser_widget_signal_title_callback + }; + + void browser_widget_signal_progress_callback( + GtkMozEmbed * self, gint p0, gint p1, void * data) + { + typedef SigC::Slot2 SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) + { + try + { + if (SigC::SlotNode * const slot = + Glib::SignalProxyNormal::data_to_slot(data)) + (*(SlotType::Proxy)(slot->proxy_))(p0, p1, slot); + } + catch(...) + { + Glib::exception_handlers_invoke(); + } + } + } + + const Glib::SignalProxyInfo browser_widget_signal_progress_info = + { + "progress", + (GCallback) &browser_widget_signal_progress_callback, + (GCallback) &browser_widget_signal_progress_callback + }; + + void browser_widget_signal_net_state_callback( + GtkMozEmbed * self, const char * p0, gint p1, guint p2, void * data) + { + typedef SigC::Slot3 SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) + { + try + { + if (SigC::SlotNode * const slot = + Glib::SignalProxyNormal::data_to_slot(data)) + (*(SlotType::Proxy)(slot->proxy_))(p0, p1, p2, slot); + } + catch(...) + { + Glib::exception_handlers_invoke(); + } + } + } + + const Glib::SignalProxyInfo browser_widget_signal_net_state_info = + { + "net_state_all", + (GCallback) &browser_widget_signal_net_state_callback, + (GCallback) &browser_widget_signal_net_state_callback + }; + + void browser_widget_signal_net_start_callback(GtkMozEmbed * self, void * data) + { + typedef SigC::Slot0 SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) + { + try + { + if (SigC::SlotNode * const slot = + Glib::SignalProxyNormal::data_to_slot(data)) + (*(SlotType::Proxy)(slot->proxy_))(slot); + } + catch(...) + { + Glib::exception_handlers_invoke(); + } + } + } + + const Glib::SignalProxyInfo browser_widget_signal_net_start_info = + { + "net_start", + (GCallback) &browser_widget_signal_net_start_callback, + (GCallback) &browser_widget_signal_net_start_callback + }; + + void browser_widget_signal_net_stop_callback(GtkMozEmbed * self, void * data) + { + typedef SigC::Slot0 SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) + { + try + { + if (SigC::SlotNode * const slot = + Glib::SignalProxyNormal::data_to_slot(data)) + (*(SlotType::Proxy)(slot->proxy_))(slot); + } + catch(...) + { + Glib::exception_handlers_invoke(); + } + } + } + + const Glib::SignalProxyInfo browser_widget_signal_net_stop_info = + { + "net_stop", + (GCallback) &browser_widget_signal_net_stop_callback, + (GCallback) &browser_widget_signal_net_stop_callback + }; + + void browser_widget_signal_new_window_callback( + GtkMozEmbed * self, GtkMozEmbed ** p0, guint p1, void * data) + { + typedef SigC::Slot1 SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) + { + try + { + if (SigC::SlotNode * const slot = + Glib::SignalProxyNormal::data_to_slot(data)) + { + if (browser_widget * result = + (*(SlotType::Proxy)(slot->proxy_))(p1, slot)) + { + *p0 = result->gobj(); + return; + } + } + } + catch(...) + { + Glib::exception_handlers_invoke(); + } + } + + *p0 = NULL; + return; + } + + const Glib::SignalProxyInfo browser_widget_signal_new_window_info = + { + "new_window", + (GCallback) &browser_widget_signal_new_window_callback, + (GCallback) &browser_widget_signal_new_window_callback + }; + + void browser_widget_signal_visibility_callback( + GtkMozEmbed * self, gboolean p0, void * data) + { + typedef SigC::Slot1 SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) + { + try + { + if (SigC::SlotNode * const slot = + Glib::SignalProxyNormal::data_to_slot(data)) + (*(SlotType::Proxy)(slot->proxy_))(p0, slot); + } + catch(...) + { + Glib::exception_handlers_invoke(); + } + } + } + + const Glib::SignalProxyInfo browser_widget_signal_visibility_info = + { + "visibility", + (GCallback) &browser_widget_signal_visibility_callback, + (GCallback) &browser_widget_signal_visibility_callback + }; + + void browser_widget_signal_destroy_browser_callback( + GtkMozEmbed * self, void * data) + { + typedef SigC::Slot0 SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) + { + try + { + if (SigC::SlotNode * const slot = + Glib::SignalProxyNormal::data_to_slot(data)) + (*(SlotType::Proxy)(slot->proxy_))(slot); + } + catch(...) + { + Glib::exception_handlers_invoke(); + } + } + } + + const Glib::SignalProxyInfo browser_widget_signal_destroy_info = + { + "destroy_browser", + (GCallback) &browser_widget_signal_destroy_browser_callback, + (GCallback) &browser_widget_signal_destroy_browser_callback + }; + + gint browser_widget_signal_open_uri_callback( + GtkMozEmbed * self, const char * p0, void * data) + { + typedef SigC::Slot1 SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) + { + try + { + if (SigC::SlotNode * const slot = + Glib::SignalProxyNormal::data_to_slot(data)) + return (*(SlotType::Proxy)(slot->proxy_))(p0, slot); + } + catch(...) + { + Glib::exception_handlers_invoke(); + } + } + + return 0; + } + + const Glib::SignalProxyInfo browser_widget_signal_open_uri_info = + { + "open_uri", + (GCallback) &browser_widget_signal_open_uri_callback, + (GCallback) &browser_widget_signal_open_uri_callback + }; + +} // namespace + +Glib::SignalProxy0 browser_widget::signal_link_message() +{ + return Glib::SignalProxy0(this, &browser_widget_signal_link_message_info); +} +Glib::SignalProxy0 browser_widget::signal_js_status() +{ + return Glib::SignalProxy0(this, &browser_widget_signal_js_status_info); +} +Glib::SignalProxy0 browser_widget::signal_location() +{ + return Glib::SignalProxy0(this, &browser_widget_signal_location_info); +} +Glib::SignalProxy0 browser_widget::signal_title() +{ + return Glib::SignalProxy0(this, &browser_widget_signal_title_info); +} +Glib::SignalProxy2 browser_widget::signal_progress() +{ + return Glib::SignalProxy2( + this, &browser_widget_signal_progress_info); +} +Glib::SignalProxy3 +browser_widget::signal_net_state() +{ + return Glib::SignalProxy3( + this, &browser_widget_signal_net_state_info); +} +Glib::SignalProxy0 browser_widget::signal_net_start() +{ + return Glib::SignalProxy0(this, &browser_widget_signal_net_start_info); +} +Glib::SignalProxy0 browser_widget::signal_net_stop() +{ + return Glib::SignalProxy0(this, &browser_widget_signal_net_stop_info); +} +Glib::SignalProxy1 browser_widget::signal_new_window() +{ + return Glib::SignalProxy1( + this, &browser_widget_signal_new_window_info); +} +Glib::SignalProxy1 browser_widget::signal_visibility() +{ + return Glib::SignalProxy1( + this, &browser_widget_signal_visibility_info); +} +Glib::SignalProxy0 browser_widget::signal_destroy() +{ + return Glib::SignalProxy0(this, &browser_widget_signal_destroy_info); +} +Glib::SignalProxy1 browser_widget::signal_open_uri() +{ + return Glib::SignalProxy1( + this, &browser_widget_signal_open_uri_info); +} + +browser_widget::browser_widget(GObject * gobject, bool take_copy) +{ + assert(GTK_MOZ_EMBED(gobject)); + gobject_ = gobject; + if (take_copy) + reference(); +} +Glib::ObjectBase * browser_widget::wrap_new(GObject * gobject) +{ + return new browser_widget(gobject, false); +} + +browser_widget::initialiser::initialiser() +{ + gtk_moz_embed_set_comp_path(MOZ_LIB_DIR); + gtk_moz_embed_push_startup(); + + wrap_register(gtk_moz_embed_get_type(), wrap_new); +} + +browser_widget::initialiser::~initialiser() +{ + gtk_moz_embed_pop_startup(); +} + +namespace Glib +{ + browser_widget * wrap(GtkMozEmbed * object, bool take_copy) + { + return dynamic_cast( + Glib::wrap_auto((GObject*)(object), take_copy)); + } +} diff --git a/browser_widget.hpp b/browser_widget.hpp new file mode 100644 index 0000000..16d3023 --- /dev/null +++ b/browser_widget.hpp @@ -0,0 +1,73 @@ +// Copyright 2005 Ben Hutchings . +// See the file "COPYING" for licence details. + +#ifndef INC_BROWSER_WIDGET_HPP +#define INC_BROWSER_WIDGET_HPP + +#include +#include + +#include +#include + +class browser_widget; +class nsIWebBrowser; + +namespace Glib +{ + browser_widget * wrap(GtkMozEmbed * object, bool take_copy = false); +} + +class browser_widget : public Gtk::Bin +{ +public: + browser_widget(); + virtual ~browser_widget(); + GtkMozEmbed * gobj(); + const GtkMozEmbed * gobj() const; + + void load_uri(const char * uri); + void load_uri(const std::string & uri); + void stop_load(); + void go_back(); + void go_forward(); + void reload(gint32 flags = GTK_MOZ_EMBED_FLAG_RELOADNORMAL); + + bool can_go_back() const; + bool can_go_forward() const; + + std::string get_link_message() const; + std::string get_js_status() const; + std::string get_title() const; + std::string get_location() const; + already_AddRefed get_browser(); + + Glib::SignalProxy0 signal_link_message(); + Glib::SignalProxy0 signal_js_status(); + Glib::SignalProxy0 signal_location(); + Glib::SignalProxy0 signal_title(); + Glib::SignalProxy2 signal_progress(); + Glib::SignalProxy3 + signal_net_state(); + Glib::SignalProxy0 signal_net_start(); + Glib::SignalProxy0 signal_net_stop(); + Glib::SignalProxy1 signal_new_window(); + Glib::SignalProxy1 signal_visibility(); + Glib::SignalProxy0 signal_destroy(); + Glib::SignalProxy1 signal_open_uri(); + + // This must be instantiated after Gtk initialisation and before + // instantiation of browser_widget. + struct initialiser + { + initialiser(); + ~initialiser(); + }; + +private: + browser_widget(GObject * gobject, bool take_copy); + static Glib::ObjectBase * wrap_new(GObject * gobject); + friend browser_widget * Glib::wrap(GtkMozEmbed * object, bool take_copy); +}; + +#endif // !INC_BROWSER_WIDGET_HPP diff --git a/browserwidget.cpp b/browserwidget.cpp deleted file mode 100644 index a2bed64..0000000 --- a/browserwidget.cpp +++ /dev/null @@ -1,539 +0,0 @@ -// Copyright 2005 Ben Hutchings . -// See the file "COPYING" for licence details. - -#include "browserwidget.hpp" - -#include - -#include - -BrowserWidget::BrowserWidget() - : Gtk::Bin(GTK_BIN(gtk_moz_embed_new())) -{ -} -BrowserWidget::~BrowserWidget() -{ -} - -GtkMozEmbed * BrowserWidget::gobj() -{ - return GTK_MOZ_EMBED(gobject_); -} -const GtkMozEmbed * BrowserWidget::gobj() const -{ - return GTK_MOZ_EMBED(gobject_); -} - -void BrowserWidget::load_uri(const char * uri) -{ - gtk_moz_embed_load_url(gobj(), uri); -} -void BrowserWidget::load_uri(const std::string & uri) -{ - return load_uri(uri.c_str()); -} -void BrowserWidget::stop_load() -{ - gtk_moz_embed_stop_load(gobj()); -} -void BrowserWidget::go_back() -{ - gtk_moz_embed_go_back(gobj()); -} -void BrowserWidget::go_forward() -{ - gtk_moz_embed_go_forward(gobj()); -} -void BrowserWidget::reload(gint32 flags) -{ - gtk_moz_embed_reload(gobj(), flags); -} - -bool BrowserWidget::can_go_back() const -{ - return gtk_moz_embed_can_go_back(const_cast(gobj())); -} -bool BrowserWidget::can_go_forward() const -{ - return gtk_moz_embed_can_go_forward(const_cast(gobj())); -} - -namespace -{ - template - class c_scoped_ptr - { - public: - explicit c_scoped_ptr(T * p = 0) : p_(p) {} - ~c_scoped_ptr() { free(p_); } - T * get() const { return p_; } - T * release() - { - T * p = p_; - p_ = NULL; - return p; - } - void reset(T * p = 0) - { - free(p_); - p_ = p; - } - private: - T * p_; - }; -} - -std::string BrowserWidget::get_link_message() const -{ - c_scoped_ptr str( - gtk_moz_embed_get_link_message(const_cast(gobj()))); - return std::string(str.get()); -} -std::string BrowserWidget::get_js_status() const -{ - c_scoped_ptr str( - gtk_moz_embed_get_js_status(const_cast(gobj()))); - return std::string(str.get()); -} -std::string BrowserWidget::get_title() const -{ - c_scoped_ptr str( - gtk_moz_embed_get_title(const_cast(gobj()))); - return std::string(str.get()); -} -std::string BrowserWidget::get_location() const -{ - c_scoped_ptr str( - gtk_moz_embed_get_location(const_cast(gobj()))); - return std::string(str.get()); -} -already_AddRefed BrowserWidget::get_browser() -{ - nsIWebBrowser * result = 0; - gtk_moz_embed_get_nsIWebBrowser(gobj(), &result); - assert(result); - return dont_AddRef(result); -} - -namespace -{ - void BrowserWidget_signal_link_message_callback(GtkMozEmbed * self, void * data) - { - typedef SigC::Slot0 SlotType; - - if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) - { - try - { - if (SigC::SlotNode * const slot = - Glib::SignalProxyNormal::data_to_slot(data)) - (*(SlotType::Proxy)(slot->proxy_))(slot); - } - catch(...) - { - Glib::exception_handlers_invoke(); - } - } - } - - const Glib::SignalProxyInfo BrowserWidget_signal_link_message_info = - { - "link_message", - (GCallback) &BrowserWidget_signal_link_message_callback, - (GCallback) &BrowserWidget_signal_link_message_callback - }; - - void BrowserWidget_signal_js_status_callback(GtkMozEmbed * self, void * data) - { - typedef SigC::Slot0 SlotType; - - if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) - { - try - { - if (SigC::SlotNode * const slot = - Glib::SignalProxyNormal::data_to_slot(data)) - (*(SlotType::Proxy)(slot->proxy_))(slot); - } - catch(...) - { - Glib::exception_handlers_invoke(); - } - } - } - - const Glib::SignalProxyInfo BrowserWidget_signal_js_status_info = - { - "js_status", - (GCallback) &BrowserWidget_signal_js_status_callback, - (GCallback) &BrowserWidget_signal_js_status_callback - }; - - void BrowserWidget_signal_location_callback(GtkMozEmbed * self, void * data) - { - typedef SigC::Slot0 SlotType; - - if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) - { - try - { - if (SigC::SlotNode * const slot = - Glib::SignalProxyNormal::data_to_slot(data)) - (*(SlotType::Proxy)(slot->proxy_))(slot); - } - catch(...) - { - Glib::exception_handlers_invoke(); - } - } - } - - const Glib::SignalProxyInfo BrowserWidget_signal_location_info = - { - "location", - (GCallback) &BrowserWidget_signal_location_callback, - (GCallback) &BrowserWidget_signal_location_callback - }; - - void BrowserWidget_signal_title_callback(GtkMozEmbed * self, void * data) - { - typedef SigC::Slot0 SlotType; - - if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) - { - try - { - if (SigC::SlotNode * const slot = - Glib::SignalProxyNormal::data_to_slot(data)) - (*(SlotType::Proxy)(slot->proxy_))(slot); - } - catch(...) - { - Glib::exception_handlers_invoke(); - } - } - } - - const Glib::SignalProxyInfo BrowserWidget_signal_title_info = - { - "title", - (GCallback) &BrowserWidget_signal_title_callback, - (GCallback) &BrowserWidget_signal_title_callback - }; - - void BrowserWidget_signal_progress_callback( - GtkMozEmbed * self, gint p0, gint p1, void * data) - { - typedef SigC::Slot2 SlotType; - - if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) - { - try - { - if (SigC::SlotNode * const slot = - Glib::SignalProxyNormal::data_to_slot(data)) - (*(SlotType::Proxy)(slot->proxy_))(p0, p1, slot); - } - catch(...) - { - Glib::exception_handlers_invoke(); - } - } - } - - const Glib::SignalProxyInfo BrowserWidget_signal_progress_info = - { - "progress", - (GCallback) &BrowserWidget_signal_progress_callback, - (GCallback) &BrowserWidget_signal_progress_callback - }; - - void BrowserWidget_signal_net_state_callback( - GtkMozEmbed * self, const char * p0, gint p1, guint p2, void * data) - { - typedef SigC::Slot3 SlotType; - - if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) - { - try - { - if (SigC::SlotNode * const slot = - Glib::SignalProxyNormal::data_to_slot(data)) - (*(SlotType::Proxy)(slot->proxy_))(p0, p1, p2, slot); - } - catch(...) - { - Glib::exception_handlers_invoke(); - } - } - } - - const Glib::SignalProxyInfo BrowserWidget_signal_net_state_info = - { - "net_state_all", - (GCallback) &BrowserWidget_signal_net_state_callback, - (GCallback) &BrowserWidget_signal_net_state_callback - }; - - void BrowserWidget_signal_net_start_callback(GtkMozEmbed * self, void * data) - { - typedef SigC::Slot0 SlotType; - - if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) - { - try - { - if (SigC::SlotNode * const slot = - Glib::SignalProxyNormal::data_to_slot(data)) - (*(SlotType::Proxy)(slot->proxy_))(slot); - } - catch(...) - { - Glib::exception_handlers_invoke(); - } - } - } - - const Glib::SignalProxyInfo BrowserWidget_signal_net_start_info = - { - "net_start", - (GCallback) &BrowserWidget_signal_net_start_callback, - (GCallback) &BrowserWidget_signal_net_start_callback - }; - - void BrowserWidget_signal_net_stop_callback(GtkMozEmbed * self, void * data) - { - typedef SigC::Slot0 SlotType; - - if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) - { - try - { - if (SigC::SlotNode * const slot = - Glib::SignalProxyNormal::data_to_slot(data)) - (*(SlotType::Proxy)(slot->proxy_))(slot); - } - catch(...) - { - Glib::exception_handlers_invoke(); - } - } - } - - const Glib::SignalProxyInfo BrowserWidget_signal_net_stop_info = - { - "net_stop", - (GCallback) &BrowserWidget_signal_net_stop_callback, - (GCallback) &BrowserWidget_signal_net_stop_callback - }; - - void BrowserWidget_signal_new_window_callback( - GtkMozEmbed * self, GtkMozEmbed ** p0, guint p1, void * data) - { - typedef SigC::Slot1 SlotType; - - if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) - { - try - { - if (SigC::SlotNode * const slot = - Glib::SignalProxyNormal::data_to_slot(data)) - { - if (BrowserWidget * result = - (*(SlotType::Proxy)(slot->proxy_))(p1, slot)) - { - *p0 = result->gobj(); - return; - } - } - } - catch(...) - { - Glib::exception_handlers_invoke(); - } - } - - *p0 = NULL; - return; - } - - const Glib::SignalProxyInfo BrowserWidget_signal_new_window_info = - { - "new_window", - (GCallback) &BrowserWidget_signal_new_window_callback, - (GCallback) &BrowserWidget_signal_new_window_callback - }; - - void BrowserWidget_signal_visibility_callback( - GtkMozEmbed * self, gboolean p0, void * data) - { - typedef SigC::Slot1 SlotType; - - if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) - { - try - { - if (SigC::SlotNode * const slot = - Glib::SignalProxyNormal::data_to_slot(data)) - (*(SlotType::Proxy)(slot->proxy_))(p0, slot); - } - catch(...) - { - Glib::exception_handlers_invoke(); - } - } - } - - const Glib::SignalProxyInfo BrowserWidget_signal_visibility_info = - { - "visibility", - (GCallback) &BrowserWidget_signal_visibility_callback, - (GCallback) &BrowserWidget_signal_visibility_callback - }; - - void BrowserWidget_signal_destroy_browser_callback( - GtkMozEmbed * self, void * data) - { - typedef SigC::Slot0 SlotType; - - if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) - { - try - { - if (SigC::SlotNode * const slot = - Glib::SignalProxyNormal::data_to_slot(data)) - (*(SlotType::Proxy)(slot->proxy_))(slot); - } - catch(...) - { - Glib::exception_handlers_invoke(); - } - } - } - - const Glib::SignalProxyInfo BrowserWidget_signal_destroy_info = - { - "destroy_browser", - (GCallback) &BrowserWidget_signal_destroy_browser_callback, - (GCallback) &BrowserWidget_signal_destroy_browser_callback - }; - - gint BrowserWidget_signal_open_uri_callback( - GtkMozEmbed * self, const char * p0, void * data) - { - typedef SigC::Slot1 SlotType; - - if (Glib::ObjectBase::_get_current_wrapper((GObject *)self)) - { - try - { - if (SigC::SlotNode * const slot = - Glib::SignalProxyNormal::data_to_slot(data)) - return (*(SlotType::Proxy)(slot->proxy_))(p0, slot); - } - catch(...) - { - Glib::exception_handlers_invoke(); - } - } - - return 0; - } - - const Glib::SignalProxyInfo BrowserWidget_signal_open_uri_info = - { - "open_uri", - (GCallback) &BrowserWidget_signal_open_uri_callback, - (GCallback) &BrowserWidget_signal_open_uri_callback - }; - -} // namespace - -Glib::SignalProxy0 BrowserWidget::signal_link_message() -{ - return Glib::SignalProxy0(this, &BrowserWidget_signal_link_message_info); -} -Glib::SignalProxy0 BrowserWidget::signal_js_status() -{ - return Glib::SignalProxy0(this, &BrowserWidget_signal_js_status_info); -} -Glib::SignalProxy0 BrowserWidget::signal_location() -{ - return Glib::SignalProxy0(this, &BrowserWidget_signal_location_info); -} -Glib::SignalProxy0 BrowserWidget::signal_title() -{ - return Glib::SignalProxy0(this, &BrowserWidget_signal_title_info); -} -Glib::SignalProxy2 BrowserWidget::signal_progress() -{ - return Glib::SignalProxy2( - this, &BrowserWidget_signal_progress_info); -} -Glib::SignalProxy3 -BrowserWidget::signal_net_state() -{ - return Glib::SignalProxy3( - this, &BrowserWidget_signal_net_state_info); -} -Glib::SignalProxy0 BrowserWidget::signal_net_start() -{ - return Glib::SignalProxy0(this, &BrowserWidget_signal_net_start_info); -} -Glib::SignalProxy0 BrowserWidget::signal_net_stop() -{ - return Glib::SignalProxy0(this, &BrowserWidget_signal_net_stop_info); -} -Glib::SignalProxy1 BrowserWidget::signal_new_window() -{ - return Glib::SignalProxy1( - this, &BrowserWidget_signal_new_window_info); -} -Glib::SignalProxy1 BrowserWidget::signal_visibility() -{ - return Glib::SignalProxy1( - this, &BrowserWidget_signal_visibility_info); -} -Glib::SignalProxy0 BrowserWidget::signal_destroy() -{ - return Glib::SignalProxy0(this, &BrowserWidget_signal_destroy_info); -} -Glib::SignalProxy1 BrowserWidget::signal_open_uri() -{ - return Glib::SignalProxy1( - this, &BrowserWidget_signal_open_uri_info); -} - -BrowserWidget::BrowserWidget(GObject * gobject, bool take_copy) -{ - assert(GTK_MOZ_EMBED(gobject)); - gobject_ = gobject; - if (take_copy) - reference(); -} -Glib::ObjectBase * BrowserWidget::wrap_new(GObject * gobject) -{ - return new BrowserWidget(gobject, false); -} - -BrowserWidget::Initialiser::Initialiser() -{ - gtk_moz_embed_set_comp_path(MOZ_LIB_DIR); - gtk_moz_embed_push_startup(); - - wrap_register(gtk_moz_embed_get_type(), wrap_new); -} - -BrowserWidget::Initialiser::~Initialiser() -{ - gtk_moz_embed_pop_startup(); -} - -namespace Glib -{ - BrowserWidget * wrap(GtkMozEmbed * object, bool take_copy) - { - return dynamic_cast( - Glib::wrap_auto((GObject*)(object), take_copy)); - } -} diff --git a/browserwidget.hpp b/browserwidget.hpp deleted file mode 100644 index 2cfc1d7..0000000 --- a/browserwidget.hpp +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2005 Ben Hutchings . -// See the file "COPYING" for licence details. - -#ifndef INC_BROWSERWIDGET_HPP -#define INC_BROWSERWIDGET_HPP - -#include -#include - -#include -#include - -class BrowserWidget; -class nsIWebBrowser; - -namespace Glib -{ - BrowserWidget * wrap(GtkMozEmbed * object, bool take_copy = false); -} - -class BrowserWidget : public Gtk::Bin -{ -public: - BrowserWidget(); - virtual ~BrowserWidget(); - GtkMozEmbed * gobj(); - const GtkMozEmbed * gobj() const; - - void load_uri(const char * uri); - void load_uri(const std::string & uri); - void stop_load(); - void go_back(); - void go_forward(); - void reload(gint32 flags = GTK_MOZ_EMBED_FLAG_RELOADNORMAL); - - bool can_go_back() const; - bool can_go_forward() const; - - std::string get_link_message() const; - std::string get_js_status() const; - std::string get_title() const; - std::string get_location() const; - already_AddRefed get_browser(); - - Glib::SignalProxy0 signal_link_message(); - Glib::SignalProxy0 signal_js_status(); - Glib::SignalProxy0 signal_location(); - Glib::SignalProxy0 signal_title(); - Glib::SignalProxy2 signal_progress(); - Glib::SignalProxy3 - signal_net_state(); - Glib::SignalProxy0 signal_net_start(); - Glib::SignalProxy0 signal_net_stop(); - Glib::SignalProxy1 signal_new_window(); - Glib::SignalProxy1 signal_visibility(); - Glib::SignalProxy0 signal_destroy(); - Glib::SignalProxy1 signal_open_uri(); - - // This must be instantiated after Gtk initialisation and before - // instantiation of BrowserWidget. - struct Initialiser - { - Initialiser(); - ~Initialiser(); - }; - -private: - BrowserWidget(GObject * gobject, bool take_copy); - static Glib::ObjectBase * wrap_new(GObject * gobject); - friend BrowserWidget * Glib::wrap(GtkMozEmbed * object, bool take_copy); -}; - -#endif // !INC_BROWSERWIDGET_HPP diff --git a/child_iterator.cpp b/child_iterator.cpp new file mode 100644 index 0000000..d6e708e --- /dev/null +++ b/child_iterator.cpp @@ -0,0 +1,46 @@ +// Copyright 2005 Ben Hutchings . +// See the file "COPYING" for licence details. + +#include "child_iterator.hpp" + +#include + +#include "xpcom_support.hpp" + +using xpcom_support::check; + +child_iterator::child_iterator() + : node_(0) +{} + +child_iterator::child_iterator(nsIDOMNode * node) +{ + check(node->GetFirstChild(&node_)); +} + +child_iterator::~child_iterator() +{ + if (node_) + node_->Release(); +} + +already_AddRefed child_iterator::operator*() const +{ + assert(node_); + node_->AddRef(); + return node_; +} + +child_iterator & child_iterator::operator++() +{ + nsIDOMNode * next; + check(node_->GetNextSibling(&next)); + node_->Release(); + node_ = next; + return *this; +} + +bool child_iterator::operator==(const child_iterator & other) const +{ + return node_ == other.node_; +} diff --git a/child_iterator.hpp b/child_iterator.hpp new file mode 100644 index 0000000..e099676 --- /dev/null +++ b/child_iterator.hpp @@ -0,0 +1,33 @@ +// Copyright 2005 Ben Hutchings . +// See the file "COPYING" for licence details. + +#ifndef INC_CHILD_ITERATOR_HPP +#define INC_CHILD_ITERATOR_HPP + +#include + +#include +#include + +class child_iterator + : public std::iterator, + void, void, void> +{ +public: + child_iterator(); + explicit child_iterator(nsIDOMNode * node); + ~child_iterator(); + + already_AddRefed operator*() const; + child_iterator & operator++(); + bool operator==(const child_iterator &) const; + bool operator!=(const child_iterator & other) const + { + return !(*this == other); + } + +private: + nsIDOMNode * node_; +}; + +#endif // !INC_CHILD_ITERATOR_HPP diff --git a/childiterator.cpp b/childiterator.cpp deleted file mode 100644 index 285b4a8..0000000 --- a/childiterator.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2005 Ben Hutchings . -// See the file "COPYING" for licence details. - -#include "childiterator.hpp" - -#include - -#include "xpcom_support.hpp" - -using xpcom_support::check; - -ChildIterator::ChildIterator() - : node_(0) -{} - -ChildIterator::ChildIterator(nsIDOMNode * node) -{ - check(node->GetFirstChild(&node_)); -} - -ChildIterator::~ChildIterator() -{ - if (node_) - node_->Release(); -} - -already_AddRefed ChildIterator::operator*() const -{ - assert(node_); - node_->AddRef(); - return node_; -} - -ChildIterator & ChildIterator::operator++() -{ - nsIDOMNode * next; - check(node_->GetNextSibling(&next)); - node_->Release(); - node_ = next; - return *this; -} - -bool ChildIterator::operator==(const ChildIterator & other) const -{ - return node_ == other.node_; -} diff --git a/childiterator.hpp b/childiterator.hpp deleted file mode 100644 index edc937c..0000000 --- a/childiterator.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2005 Ben Hutchings . -// See the file "COPYING" for licence details. - -#ifndef INC_CHILDITERATOR_HPP -#define INC_CHILDITERATOR_HPP - -#include - -#include -#include - -class ChildIterator - : public std::iterator, - void, void, void> -{ -public: - ChildIterator(); - explicit ChildIterator(nsIDOMNode * node); - ~ChildIterator(); - - already_AddRefed operator*() const; - ChildIterator & operator++(); - bool operator==(const ChildIterator &) const; - bool operator!=(const ChildIterator & other) const - { - return !(*this == other); - } - -private: - nsIDOMNode * node_; -}; - -#endif // !INC_CHILDITERATOR_HPP diff --git a/framebuffer.cpp b/framebuffer.cpp deleted file mode 100644 index 2ae42cd..0000000 --- a/framebuffer.cpp +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright 2005 Ben Hutchings . -// See the file "COPYING" for licence details. - -#include "framebuffer.hpp" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "auto_fd.hpp" -#include "auto_handle.hpp" -#include "temp_file.hpp" - -namespace -{ - struct addrinfo_factory - { - addrinfo * operator()() const { return NULL; } - }; - struct addrinfo_closer - { - void operator()(addrinfo * addr_list) const - { - if (addr_list) - freeaddrinfo(addr_list); - } - }; - typedef auto_handle - auto_addrinfo; - - int select_display_num(auto_fd & tcp4_socket, auto_fd & tcp6_socket) - { - // Minimum and maximum display numbers to use. Xvnc and ssh's - // proxies start at 10, so we'll follow that convention. We - // have to put a limit on iteration somewhere, and 100 - // displays seems rather excessive so we'll stop there. - const int min_display_num = 10; - const int max_display_num = 99; - - for (int display_num = min_display_num; - display_num <= max_display_num; - ++display_num) - { - // Check that there's no lock file for the local socket - // for this display. We could also check for stale locks, - // but this will probably do. - char lock_file_name[20]; - std::sprintf(lock_file_name, "/tmp/.X%d-lock", display_num); - if (!(access(lock_file_name, 0) == -1 && errno == ENOENT)) - continue; - - // Attempt to create TCP socket(s) and bind them to the - // appropriate port number. We won't set the X server to - // listen on a TCP socket but this does ensure that ssh - // isn't using and won't use this display number. This is - // roughly based on the x11_create_display_inet function - // in OpenSSH. - - auto_addrinfo addr_list; - - { - addrinfo hints = {}; - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - char port_str[5 + 1]; - std::sprintf(port_str, "%d", 6000 + display_num); - addrinfo * addr_list_temp; - int error = getaddrinfo(NULL, port_str, &hints, - &addr_list_temp); - if (error != 0) - throw std::runtime_error( - std::string("getaddrinfo: ") - .append(gai_strerror(error))); - addr_list.reset(addr_list_temp); - } - - const addrinfo * addr; - - for (addr = addr_list.get(); addr != NULL; addr = addr->ai_next) - { - // We're only interested in TCPv4 and TCPv6. - if (addr->ai_family != AF_INET && addr->ai_family != AF_INET6) - continue; - auto_fd & tcp_socket = - (addr->ai_family == AF_INET) ? tcp4_socket : tcp6_socket; - - tcp_socket.reset(socket(addr->ai_family, - SOCK_STREAM, - addr->ai_protocol)); - if (tcp_socket.get() < 0) - { - // If the family is unsupported, no-one can bind - // to this address, so this is not a problem. - if (errno == EAFNOSUPPORT -# ifdef EPFNOSUPPORT - || errno == EPFNOSUPPORT -# endif - ) - continue; - throw std::runtime_error( - std::string("socket: ").append(strerror(errno))); - } - - // Don't let TCPv6 sockets interfere with TCPv4 sockets. -# ifdef IPV6_V6ONLY - if (addr->ai_family == AF_INET6) - { - int on = 1; - if (setsockopt(tcp_socket.get(), IPPROTO_IPV6, IPV6_V6ONLY, - &on, sizeof(on)) != 0) - { - throw std::runtime_error( - std::string("setsockopt IPV6_V6ONLY: ") - .append(strerror(errno))); - } - } -# endif - - if (bind(tcp_socket.get(), addr->ai_addr, addr->ai_addrlen) - != 0) - break; - } - - // If we reached the end of the address list, we've - // successfully bound to all appropriate addresses for - // this display number, so we can use it. - if (addr == NULL) - return display_num; - } - - throw std::runtime_error("did not find a free X display"); - } - - void get_random_bytes(unsigned char * buf, int len) - { - assert(len > 0); - auto_fd random_fd(open("/dev/urandom", O_RDONLY)); - if (random_fd.get() == -1 || read(random_fd.get(), buf, len) != len) - throw std::runtime_error(std::strerror(errno)); - } - - std::auto_ptr create_temp_auth_file(int display_num) - { - std::auto_ptr auth_file(new temp_file("Xvfb-auth-")); - - // An xauth entry consists of the following fields. All u16 fields - // are big-endian and unaligned. Character arrays are not null- - // terminated. - // u16 address family (= 256 for local socket) - // u16 length of address - // char[] address (= hostname) - // u16 length of display number - // char[] display number - // u16 auth type name length - // char[] auth type name (= "MIT-MAGIC-COOKIE-1") - // u16 length of auth data (= 16) - // char[] auth data (= random bytes) - uint16_t family = htons(0x100); - write(auth_file->get_fd(), &family, sizeof(family)); - utsname my_uname; - uname(&my_uname); - uint16_t len = htons(strlen(my_uname.nodename)); - write(auth_file->get_fd(), &len, sizeof(len)); - write(auth_file->get_fd(), - my_uname.nodename, strlen(my_uname.nodename)); - char display[15]; - std::sprintf(display, "%d", display_num); - len = htons(strlen(display)); - write(auth_file->get_fd(), &len, sizeof(len)); - write(auth_file->get_fd(), display, strlen(display)); - static const char auth_type[] = "MIT-MAGIC-COOKIE-1"; - len = htons(sizeof(auth_type) - 1); - write(auth_file->get_fd(), &len, sizeof(len)); - write(auth_file->get_fd(), auth_type, sizeof(auth_type) - 1); - unsigned char auth_key[16]; - get_random_bytes(auth_key, sizeof(auth_key)); - len = htons(sizeof(auth_key)); - write(auth_file->get_fd(), &len, sizeof(len)); - write(auth_file->get_fd(), auth_key, sizeof(auth_key)); - - return auth_file; - } - - // Run the X server with the specified auth file, dimensions and - // assigned display number. - auto_kill_proc spawn_x_server(int display_num, - const std::string & auth_file_name, - int width, int height, int depth) - { - char display[15]; - std::sprintf(display, ":%d", display_num); - const char * auth_file_c_str = auth_file_name.c_str(); - std::fflush(NULL); - auto_kill_proc server_proc(fork()); - if (server_proc.get() == -1) - throw std::runtime_error(std::strerror(errno)); - - if (server_proc.get() == 0) - { - char dimensions[40]; - std::sprintf(dimensions, "%dx%dx%d", width, height, depth); - execlp("Xvfb", - "Xvfb", - "-auth", auth_file_c_str, - "-nolisten", "tcp", - "-screen", "0", dimensions, - "-terminate", - display, - NULL); - _exit(128 + errno); - } - - // Wait for the lock file to appear or the server to exit. We can't - // really wait on both of these, so poll at 1-second intervals. - char lock_file_name[20]; - std::sprintf(lock_file_name, "/tmp/.X%d-lock", display_num); - for (;;) - { - if (access(lock_file_name, 0) == 0) - break; - if (errno != ENOENT) // huh? - throw std::runtime_error(std::strerror(errno)); - if (waitpid(server_proc.get(), NULL, WNOHANG) == server_proc.get()) - { - server_proc.release(); // pid is now invalid - // TODO: Get the exit status and decode it properly. - throw std::runtime_error("X server failed to create display"); - } - sleep(1); - } - - return server_proc; - } -} - -FrameBuffer::FrameBuffer(int width, int height, int depth) - : display_num_(select_display_num(tcp4_socket_, tcp6_socket_)), - auth_file_(create_temp_auth_file(display_num_)), - server_proc_(spawn_x_server(display_num_, - get_x_authority(), - width, height, depth)) -{} - -std::string FrameBuffer::get_x_authority() const -{ - return auth_file_->get_name(); -} - -std::string FrameBuffer::get_x_display() const -{ - char display[15]; - std::sprintf(display, ":%d", display_num_); - return display; -} diff --git a/framebuffer.hpp b/framebuffer.hpp deleted file mode 100644 index 3e49875..0000000 --- a/framebuffer.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2005 Ben Hutchings . -// See the file "COPYING" for licence details. - -#ifndef INC_FRAMEBUFFER_HPP -#define INC_FRAMEBUFFER_HPP - -#include -#include - -#include "auto_fd.hpp" -#include "auto_proc.hpp" -#include "temp_file.hpp" - -// Run Xvfb with a frame buffer of the given dimensions. -class FrameBuffer -{ -public: - FrameBuffer(int width, int height, int depth); - std::string get_x_authority() const; - std::string get_x_display() const; - -private: - auto_fd tcp4_socket_, tcp6_socket_; - int display_num_; - std::auto_ptr auth_file_; - auto_kill_proc server_proc_; -}; - -#endif // !INC_FRAMEBUFFER_HPP diff --git a/link_iterator.cpp b/link_iterator.cpp new file mode 100644 index 0000000..20d4b4c --- /dev/null +++ b/link_iterator.cpp @@ -0,0 +1,52 @@ +// Copyright 2005 Ben Hutchings . +// See the file "COPYING" for licence details. + +#include "link_iterator.hpp" + +#include + +#include +#include + +link_iterator::link_iterator() +{} + +link_iterator::link_iterator(nsIDOMDocument * document) +{ + nsCOMPtr htmlDoc(do_QueryInterface(document)); + if (!htmlDoc) + return; + + htmlDoc->GetLinks(getter_AddRefs(collection_)); + assert(collection_); + + index_ = 0; + length_ = 0; + collection_->GetLength(&length_); + if (length_ == 0) + collection_ = 0; +} + +already_AddRefed link_iterator::operator*() const +{ + assert(collection_); + nsIDOMNode * result = 0; + collection_->Item(index_, &result); + assert(result); + return dont_AddRef(result); +} + +link_iterator & link_iterator::operator++() +{ + assert(collection_); + ++index_; + if (index_ == length_) + collection_ = 0; + return *this; +} + +bool link_iterator::operator==(const link_iterator & other) const +{ + return (collection_ == other.collection_ + && (!collection_ || index_ == other.index_)); +} diff --git a/link_iterator.hpp b/link_iterator.hpp new file mode 100644 index 0000000..d2b7a1a --- /dev/null +++ b/link_iterator.hpp @@ -0,0 +1,36 @@ +// Copyright 2005 Ben Hutchings . +// See the file "COPYING" for licence details. + +#ifndef INC_LINK_ITERATOR_HPP +#define INC_LINK_ITERATOR_HPP + +#include + +#include +#include +#include + +class nsIDOMDocument; + +class link_iterator + : public std::iterator, + void, void, void> +{ +public: + link_iterator(); + explicit link_iterator(nsIDOMDocument * document); + + already_AddRefed operator*() const; + link_iterator & operator++(); + bool operator==(const link_iterator &) const; + bool operator!=(const link_iterator & other) const + { + return !(*this == other); + } + +private: + nsCOMPtr collection_; + unsigned int index_, length_; +}; + +#endif // !INC_LINK_ITERATOR_HPP diff --git a/linkiterator.cpp b/linkiterator.cpp deleted file mode 100644 index b751c1d..0000000 --- a/linkiterator.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2005 Ben Hutchings . -// See the file "COPYING" for licence details. - -#include "linkiterator.hpp" - -#include - -#include -#include - -LinkIterator::LinkIterator() -{} - -LinkIterator::LinkIterator(nsIDOMDocument * document) -{ - nsCOMPtr htmlDoc(do_QueryInterface(document)); - if (!htmlDoc) - return; - - htmlDoc->GetLinks(getter_AddRefs(collection_)); - assert(collection_); - - index_ = 0; - length_ = 0; - collection_->GetLength(&length_); - if (length_ == 0) - collection_ = 0; -} - -already_AddRefed LinkIterator::operator*() const -{ - assert(collection_); - nsIDOMNode * result = 0; - collection_->Item(index_, &result); - assert(result); - return dont_AddRef(result); -} - -LinkIterator & LinkIterator::operator++() -{ - assert(collection_); - ++index_; - if (index_ == length_) - collection_ = 0; - return *this; -} - -bool LinkIterator::operator==(const LinkIterator & other) const -{ - return (collection_ == other.collection_ - && (!collection_ || index_ == other.index_)); -} diff --git a/linkiterator.hpp b/linkiterator.hpp deleted file mode 100644 index 2f93a2f..0000000 --- a/linkiterator.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2005 Ben Hutchings . -// See the file "COPYING" for licence details. - -#ifndef INC_LINKITERATOR_HPP -#define INC_LINKITERATOR_HPP - -#include - -#include -#include -#include - -class nsIDOMDocument; - -class LinkIterator - : public std::iterator, - void, void, void> -{ -public: - LinkIterator(); - explicit LinkIterator(nsIDOMDocument * document); - - already_AddRefed operator*() const; - LinkIterator & operator++(); - bool operator==(const LinkIterator &) const; - bool operator!=(const LinkIterator & other) const - { - return !(*this == other); - } - -private: - nsCOMPtr collection_; - unsigned int index_, length_; -}; - -#endif // !INC_LINKITERATOR_HPP diff --git a/style_sheets.cpp b/style_sheets.cpp new file mode 100644 index 0000000..5767800 --- /dev/null +++ b/style_sheets.cpp @@ -0,0 +1,50 @@ +// Copyright 2005 Ben Hutchings . +// See the file "COPYING" for licence details. + +#include "style_sheets.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include "xpcom_support.hpp" + +using xpcom_support::check; + +// Load a CSS from an (absolute) URI. +// TODO: Support loading from an absolute, or better, relative filename. +already_AddRefed load_css(const char * uri) +{ + nsCOMPtr css_loader; + static const nsCID css_loader_cid = NS_CSS_LOADER_CID; + check(CallGetService(css_loader_cid, + getter_AddRefs(css_loader))); + + nsCOMPtr style_sheet_uri; + check(NS_NewURI(getter_AddRefs(style_sheet_uri), nsCString(uri))); + + nsICSSStyleSheet * style_sheet; + check(css_loader->LoadAgentSheet(style_sheet_uri, &style_sheet)); + return style_sheet; +} + +// Apply a style-sheet to a given presentation shell as the top-priority +// agent style-sheet and disable the preferences-derived style rules. +void apply_style_sheet(nsIStyleSheet * style_sheet, nsIPresShell * pres_shell) +{ + nsCOMArray style_sheets; + check(pres_shell->GetAgentStyleSheets(style_sheets)); + check(style_sheets.InsertObjectAt(style_sheet, 0)); + check(pres_shell->SetAgentStyleSheets(style_sheets)); + + check(pres_shell->EnablePrefStyleRules(false)); + + // Update the display + check(pres_shell->ReconstructStyleData()); + check(pres_shell->FlushPendingNotifications(true)); +} + diff --git a/style_sheets.hpp b/style_sheets.hpp new file mode 100644 index 0000000..aa9d942 --- /dev/null +++ b/style_sheets.hpp @@ -0,0 +1,20 @@ +// Copyright 2005 Ben Hutchings . +// See the file "COPYING" for licence details. + +#ifndef INC_STYLESHEETS_HPP +#define INC_STYLESHEETS_HPP + +#include +#include + +class nsIPresShell; + +// Load a CSS from an (absolute) URI. +// TODO: Support loading from an absolute, or better, relative filename. +already_AddRefed load_css(const char * uri); + +// Apply a style-sheet to a given presentation shell as the top-priority +// agent style-sheet and disable the preferences-derived style rules. +void apply_style_sheet(nsIStyleSheet *, nsIPresShell *); + +#endif // !INC_STYLESHEETS_HPP diff --git a/stylesheets.cpp b/stylesheets.cpp deleted file mode 100644 index aa34643..0000000 --- a/stylesheets.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2005 Ben Hutchings . -// See the file "COPYING" for licence details. - -#include "stylesheets.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#include "xpcom_support.hpp" - -using xpcom_support::check; - -// Load a CSS from an (absolute) URI. -// TODO: Support loading from an absolute, or better, relative filename. -already_AddRefed load_css(const char * uri) -{ - nsCOMPtr css_loader; - static const nsCID css_loader_cid = NS_CSS_LOADER_CID; - check(CallGetService(css_loader_cid, - getter_AddRefs(css_loader))); - - nsCOMPtr style_sheet_uri; - check(NS_NewURI(getter_AddRefs(style_sheet_uri), nsCString(uri))); - - nsICSSStyleSheet * style_sheet; - check(css_loader->LoadAgentSheet(style_sheet_uri, &style_sheet)); - return style_sheet; -} - -// Apply a style-sheet to a given presentation shell as the top-priority -// agent style-sheet and disable the preferences-derived style rules. -void apply_style_sheet(nsIStyleSheet * style_sheet, nsIPresShell * pres_shell) -{ - nsCOMArray style_sheets; - check(pres_shell->GetAgentStyleSheets(style_sheets)); - check(style_sheets.InsertObjectAt(style_sheet, 0)); - check(pres_shell->SetAgentStyleSheets(style_sheets)); - - check(pres_shell->EnablePrefStyleRules(false)); - - // Update the display - check(pres_shell->ReconstructStyleData()); - check(pres_shell->FlushPendingNotifications(true)); -} - diff --git a/stylesheets.hpp b/stylesheets.hpp deleted file mode 100644 index aa9d942..0000000 --- a/stylesheets.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2005 Ben Hutchings . -// See the file "COPYING" for licence details. - -#ifndef INC_STYLESHEETS_HPP -#define INC_STYLESHEETS_HPP - -#include -#include - -class nsIPresShell; - -// Load a CSS from an (absolute) URI. -// TODO: Support loading from an absolute, or better, relative filename. -already_AddRefed load_css(const char * uri); - -// Apply a style-sheet to a given presentation shell as the top-priority -// agent style-sheet and disable the preferences-derived style rules. -void apply_style_sheet(nsIStyleSheet *, nsIPresShell *); - -#endif // !INC_STYLESHEETS_HPP diff --git a/webdvd.cpp b/webdvd.cpp index 5eca6c8..9a5dd04 100644 --- a/webdvd.cpp +++ b/webdvd.cpp @@ -50,15 +50,15 @@ #include #include -#include "browserwidget.hpp" -#include "childiterator.hpp" +#include "browser_widget.hpp" +#include "child_iterator.hpp" #include "dvd.hpp" -#include "framebuffer.hpp" -#include "linkiterator.hpp" +#include "link_iterator.hpp" #include "pixbufs.hpp" -#include "stylesheets.hpp" +#include "style_sheets.hpp" #include "temp_file.hpp" #include "video.hpp" +#include "x_frame_buffer.hpp" #include "xpcom_support.hpp" using xpcom_support::check; @@ -126,7 +126,7 @@ namespace result.bottom = result.top + height; // Merge bounding boxes of all child elements - for (ChildIterator it = ChildIterator(elem), end; it != end; ++it) + for (child_iterator it = child_iterator(elem), end; it != end; ++it) { nsCOMPtr child_node(*it); PRUint16 child_type; @@ -142,10 +142,10 @@ namespace return result; } - class WebDvdWindow : public Gtk::Window + class webdvd_window : public Gtk::Window { public: - WebDvdWindow( + webdvd_window( const video::frame_params & frame_params, const std::string & main_page_uri, const std::string & output_dir); @@ -162,14 +162,14 @@ namespace nsIDOMWindow * dom_window); void generate_dvd(); - enum ResourceType { page_resource, video_resource }; - typedef std::pair ResourceEntry; + enum resource_type { page_resource, video_resource }; + typedef std::pair resource_entry; video::frame_params frame_params_; std::string output_dir_; - BrowserWidget browser_widget_; + browser_widget browser_widget_; nsCOMPtr stylesheet_; std::queue page_queue_; - std::map resource_map_; + std::map resource_map_; std::vector > page_links_; std::vector video_paths_; bool pending_window_update_; @@ -181,7 +181,7 @@ namespace std::vector > page_temp_files_; }; - WebDvdWindow::WebDvdWindow( + webdvd_window::webdvd_window( const video::frame_params & frame_params, const std::string & main_page_uri, const std::string & output_dir) @@ -198,27 +198,27 @@ namespace add(browser_widget_); browser_widget_.show(); browser_widget_.signal_net_state().connect( - SigC::slot(*this, &WebDvdWindow::on_net_state_change)); + SigC::slot(*this, &webdvd_window::on_net_state_change)); add_page(main_page_uri); load_next_page(); } - void WebDvdWindow::add_page(const std::string & uri) + void webdvd_window::add_page(const std::string & uri) { if (resource_map_.insert( - std::make_pair(uri, ResourceEntry(page_resource, 0))) + std::make_pair(uri, resource_entry(page_resource, 0))) .second) { page_queue_.push(uri); } } - void WebDvdWindow::add_video(const std::string & uri) + void webdvd_window::add_video(const std::string & uri) { if (resource_map_.insert( - std::make_pair(uri, ResourceEntry(video_resource, - video_paths_.size() + 1))) + std::make_pair(uri, resource_entry(video_resource, + video_paths_.size() + 1))) .second) { Glib::ustring hostname; @@ -231,7 +231,7 @@ namespace } } - void WebDvdWindow::load_next_page() + void webdvd_window::load_next_page() { assert(!page_queue_.empty()); const std::string & uri = page_queue_.front(); @@ -244,11 +244,11 @@ namespace browser_widget_.load_uri(uri); } - void WebDvdWindow::on_net_state_change(const char * uri, + void webdvd_window::on_net_state_change(const char * uri, gint flags, guint status) { # ifdef DEBUG_ON_NET_STATE_CHANGE - std::cout << "WebDvdWindow::on_net_state_change("; + std::cout << "webdvd_window::on_net_state_change("; if (uri) std::cout << '"' << uri << '"'; else @@ -335,7 +335,7 @@ namespace } } - bool WebDvdWindow::process_page() + bool webdvd_window::process_page() { assert(!page_queue_.empty()); @@ -399,7 +399,7 @@ namespace return true; } - void WebDvdWindow::save_screenshot() + void webdvd_window::save_screenshot() { Glib::RefPtr window(get_window()); assert(window); @@ -415,7 +415,7 @@ namespace ->save(background_temp_->get_name(), "png"); } - struct WebDvdWindow::page_state + struct webdvd_window::page_state { page_state(nsIDOMDocument * doc, int width, int height) : diff_pixbuf(Gdk::Pixbuf::create( @@ -440,14 +440,14 @@ namespace temp_file links_temp; int link_num; - LinkIterator links_it, links_end; + link_iterator links_it, links_end; rectangle link_rect; bool link_changing; Glib::RefPtr norm_pixbuf; }; - void WebDvdWindow::process_links(nsIPresShell * pres_shell, + void webdvd_window::process_links(nsIPresShell * pres_shell, nsIPresContext * pres_context, nsIDOMWindow * dom_window) { @@ -707,7 +707,7 @@ namespace void generate_page_dispatch(std::ostream &, int indent, int first_page, int last_page); - void WebDvdWindow::generate_dvd() + void webdvd_window::generate_dvd() { temp_file temp("webdvd-dvdauthor-"); temp.close(); @@ -818,7 +818,7 @@ namespace " g1 = " << link_num * link_mult + page_num << ";"; // Jump to appropriate resource. - const ResourceEntry & resource_loc = + const resource_entry & resource_loc = resource_map_[page_links[link_num - 1]]; if (resource_loc.first == page_resource) file << @@ -1050,16 +1050,17 @@ int main(int argc, char ** argv) } } - std::auto_ptr fb; + std::auto_ptr fb; if (!preview_mode) { // Spawn Xvfb and set env variables so that Xlib will use it // Use 8 bits each for RGB components, which should translate into // "enough" bits for YUV components. - fb.reset(new FrameBuffer(frame_params.width, frame_params.height, - 3 * 8)); - setenv("XAUTHORITY", fb->get_x_authority().c_str(), true); - setenv("DISPLAY", fb->get_x_display().c_str(), true); + fb.reset(new x_frame_buffer(frame_params.width, + frame_params.height, + 3 * 8)); + setenv("XAUTHORITY", fb->get_authority().c_str(), true); + setenv("DISPLAY", fb->get_display().c_str(), true); } // Initialise Gtk @@ -1118,11 +1119,11 @@ int main(int argc, char ** argv) output_dir = argv[argi + 1]; // Initialise Mozilla - BrowserWidget::Initialiser browser_init; + browser_widget::initialiser browser_init; set_browser_preferences(); // Run the browser/converter - WebDvdWindow window(frame_params, menu_url, output_dir); + webdvd_window window(frame_params, menu_url, output_dir); Gtk::Main::run(window); } catch (std::exception & e) diff --git a/x_frame_buffer.cpp b/x_frame_buffer.cpp new file mode 100644 index 0000000..75d9595 --- /dev/null +++ b/x_frame_buffer.cpp @@ -0,0 +1,265 @@ +// Copyright 2005 Ben Hutchings . +// See the file "COPYING" for licence details. + +#include "x_frame_buffer.hpp" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "auto_fd.hpp" +#include "auto_handle.hpp" +#include "temp_file.hpp" + +namespace +{ + struct addrinfo_factory + { + addrinfo * operator()() const { return NULL; } + }; + struct addrinfo_closer + { + void operator()(addrinfo * addr_list) const + { + if (addr_list) + freeaddrinfo(addr_list); + } + }; + typedef auto_handle + auto_addrinfo; + + int select_display_num(auto_fd & tcp4_socket, auto_fd & tcp6_socket) + { + // Minimum and maximum display numbers to use. Xvnc and ssh's + // proxies start at 10, so we'll follow that convention. We + // have to put a limit on iteration somewhere, and 100 + // displays seems rather excessive so we'll stop there. + const int min_display_num = 10; + const int max_display_num = 99; + + for (int display_num = min_display_num; + display_num <= max_display_num; + ++display_num) + { + // Check that there's no lock file for the local socket + // for this display. We could also check for stale locks, + // but this will probably do. + char lock_file_name[20]; + std::sprintf(lock_file_name, "/tmp/.X%d-lock", display_num); + if (!(access(lock_file_name, 0) == -1 && errno == ENOENT)) + continue; + + // Attempt to create TCP socket(s) and bind them to the + // appropriate port number. We won't set the X server to + // listen on a TCP socket but this does ensure that ssh + // isn't using and won't use this display number. This is + // roughly based on the x11_create_display_inet function + // in OpenSSH. + + auto_addrinfo addr_list; + + { + addrinfo hints = {}; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + char port_str[5 + 1]; + std::sprintf(port_str, "%d", 6000 + display_num); + addrinfo * addr_list_temp; + int error = getaddrinfo(NULL, port_str, &hints, + &addr_list_temp); + if (error != 0) + throw std::runtime_error( + std::string("getaddrinfo: ") + .append(gai_strerror(error))); + addr_list.reset(addr_list_temp); + } + + const addrinfo * addr; + + for (addr = addr_list.get(); addr != NULL; addr = addr->ai_next) + { + // We're only interested in TCPv4 and TCPv6. + if (addr->ai_family != AF_INET && addr->ai_family != AF_INET6) + continue; + auto_fd & tcp_socket = + (addr->ai_family == AF_INET) ? tcp4_socket : tcp6_socket; + + tcp_socket.reset(socket(addr->ai_family, + SOCK_STREAM, + addr->ai_protocol)); + if (tcp_socket.get() < 0) + { + // If the family is unsupported, no-one can bind + // to this address, so this is not a problem. + if (errno == EAFNOSUPPORT +# ifdef EPFNOSUPPORT + || errno == EPFNOSUPPORT +# endif + ) + continue; + throw std::runtime_error( + std::string("socket: ").append(strerror(errno))); + } + + // Don't let TCPv6 sockets interfere with TCPv4 sockets. +# ifdef IPV6_V6ONLY + if (addr->ai_family == AF_INET6) + { + int on = 1; + if (setsockopt(tcp_socket.get(), IPPROTO_IPV6, IPV6_V6ONLY, + &on, sizeof(on)) != 0) + { + throw std::runtime_error( + std::string("setsockopt IPV6_V6ONLY: ") + .append(strerror(errno))); + } + } +# endif + + if (bind(tcp_socket.get(), addr->ai_addr, addr->ai_addrlen) + != 0) + break; + } + + // If we reached the end of the address list, we've + // successfully bound to all appropriate addresses for + // this display number, so we can use it. + if (addr == NULL) + return display_num; + } + + throw std::runtime_error("did not find a free X display"); + } + + void get_random_bytes(unsigned char * buf, int len) + { + assert(len > 0); + auto_fd random_fd(open("/dev/urandom", O_RDONLY)); + if (random_fd.get() == -1 || read(random_fd.get(), buf, len) != len) + throw std::runtime_error(std::strerror(errno)); + } + + std::auto_ptr create_temp_auth_file(int display_num) + { + std::auto_ptr auth_file(new temp_file("Xvfb-auth-")); + + // An xauth entry consists of the following fields. All u16 fields + // are big-endian and unaligned. Character arrays are not null- + // terminated. + // u16 address family (= 256 for local socket) + // u16 length of address + // char[] address (= hostname) + // u16 length of display number + // char[] display number + // u16 auth type name length + // char[] auth type name (= "MIT-MAGIC-COOKIE-1") + // u16 length of auth data (= 16) + // char[] auth data (= random bytes) + uint16_t family = htons(0x100); + write(auth_file->get_fd(), &family, sizeof(family)); + utsname my_uname; + uname(&my_uname); + uint16_t len = htons(strlen(my_uname.nodename)); + write(auth_file->get_fd(), &len, sizeof(len)); + write(auth_file->get_fd(), + my_uname.nodename, strlen(my_uname.nodename)); + char display[15]; + std::sprintf(display, "%d", display_num); + len = htons(strlen(display)); + write(auth_file->get_fd(), &len, sizeof(len)); + write(auth_file->get_fd(), display, strlen(display)); + static const char auth_type[] = "MIT-MAGIC-COOKIE-1"; + len = htons(sizeof(auth_type) - 1); + write(auth_file->get_fd(), &len, sizeof(len)); + write(auth_file->get_fd(), auth_type, sizeof(auth_type) - 1); + unsigned char auth_key[16]; + get_random_bytes(auth_key, sizeof(auth_key)); + len = htons(sizeof(auth_key)); + write(auth_file->get_fd(), &len, sizeof(len)); + write(auth_file->get_fd(), auth_key, sizeof(auth_key)); + + return auth_file; + } + + // Run the X server with the specified auth file, dimensions and + // assigned display number. + auto_kill_proc spawn_x_server(int display_num, + const std::string & auth_file_name, + int width, int height, int depth) + { + char display[15]; + std::sprintf(display, ":%d", display_num); + const char * auth_file_c_str = auth_file_name.c_str(); + std::fflush(NULL); + auto_kill_proc server_proc(fork()); + if (server_proc.get() == -1) + throw std::runtime_error(std::strerror(errno)); + + if (server_proc.get() == 0) + { + char dimensions[40]; + std::sprintf(dimensions, "%dx%dx%d", width, height, depth); + execlp("Xvfb", + "Xvfb", + "-auth", auth_file_c_str, + "-nolisten", "tcp", + "-screen", "0", dimensions, + "-terminate", + display, + NULL); + _exit(128 + errno); + } + + // Wait for the lock file to appear or the server to exit. We can't + // really wait on both of these, so poll at 1-second intervals. + char lock_file_name[20]; + std::sprintf(lock_file_name, "/tmp/.X%d-lock", display_num); + for (;;) + { + if (access(lock_file_name, 0) == 0) + break; + if (errno != ENOENT) // huh? + throw std::runtime_error(std::strerror(errno)); + if (waitpid(server_proc.get(), NULL, WNOHANG) == server_proc.get()) + { + server_proc.release(); // pid is now invalid + // TODO: Get the exit status and decode it properly. + throw std::runtime_error("X server failed to create display"); + } + sleep(1); + } + + return server_proc; + } +} + +x_frame_buffer::x_frame_buffer(int width, int height, int depth) + : display_num_(select_display_num(tcp4_socket_, tcp6_socket_)), + auth_file_(create_temp_auth_file(display_num_)), + server_proc_(spawn_x_server(display_num_, + get_authority(), + width, height, depth)) +{} + +std::string x_frame_buffer::get_authority() const +{ + return auth_file_->get_name(); +} + +std::string x_frame_buffer::get_display() const +{ + char display[15]; + std::sprintf(display, ":%d", display_num_); + return display; +} diff --git a/x_frame_buffer.hpp b/x_frame_buffer.hpp new file mode 100644 index 0000000..198d586 --- /dev/null +++ b/x_frame_buffer.hpp @@ -0,0 +1,29 @@ +// Copyright 2005 Ben Hutchings . +// See the file "COPYING" for licence details. + +#ifndef INC_X_FRAME_BUFFER_HPP +#define INC_X_FRAME_BUFFER_HPP + +#include +#include + +#include "auto_fd.hpp" +#include "auto_proc.hpp" +#include "temp_file.hpp" + +// Run Xvfb with a frame buffer of the given dimensions. +class x_frame_buffer +{ +public: + x_frame_buffer(int width, int height, int depth); + std::string get_authority() const; + std::string get_display() const; + +private: + auto_fd tcp4_socket_, tcp6_socket_; + int display_num_; + std::auto_ptr auth_file_; + auto_kill_proc server_proc_; +}; + +#endif // !INC_X_FRAME_BUFFER_HPP