]> git.decadent.org.uk Git - videolink.git/blob - browser_widget.cpp
Set the XULRunner version requirement to exclude 1.9.1
[videolink.git] / browser_widget.cpp
1 // Copyright 2005-8 Ben Hutchings <ben@decadent.org.uk>.
2 // See the file "COPYING" for licence details.
3
4 #include "browser_widget.hpp"
5
6 #include <cassert>
7 #include <cstring>
8
9 #include <limits.h>
10
11 #include "wchar_t_short.h"
12 #include <gtkmozembed_internal.h>
13 #if MOZ_VERSION_MAJOR == 1 && MOZ_VERSION_MINOR == 9
14 #include <gtkmozembed_glue.cpp>
15 #endif
16 #include "wchar_t_default.h"
17
18 #include "xpcom_support.hpp"
19
20 using xpcom_support::check;
21
22 browser_widget::browser_widget()
23         : Gtk::Bin(GTK_BIN(gtk_moz_embed_new()))
24 {
25 }
26 browser_widget::~browser_widget()
27 {
28 }
29
30 GtkMozEmbed * browser_widget::gobj()
31 {
32     return GTK_MOZ_EMBED(gobject_);
33 }
34 const GtkMozEmbed * browser_widget::gobj() const
35 {
36     return GTK_MOZ_EMBED(gobject_);
37 }
38
39 void browser_widget::load_uri(const char * uri)
40 {
41     gtk_moz_embed_load_url(gobj(), uri);
42 }
43 void browser_widget::load_uri(const std::string & uri)
44 {
45     return load_uri(uri.c_str());
46 }
47 void browser_widget::stop_load()
48 {
49     gtk_moz_embed_stop_load(gobj());
50 }
51 void browser_widget::go_back()
52 {
53     gtk_moz_embed_go_back(gobj());
54 }
55 void browser_widget::go_forward()
56 {
57     gtk_moz_embed_go_forward(gobj());
58 }
59 void browser_widget::reload(gint32 flags)
60 {
61     gtk_moz_embed_reload(gobj(), flags);
62 }
63
64 bool browser_widget::can_go_back() const
65 {
66     return gtk_moz_embed_can_go_back(const_cast<GtkMozEmbed *>(gobj()));
67 }
68 bool browser_widget::can_go_forward() const
69 {
70     return gtk_moz_embed_can_go_forward(const_cast<GtkMozEmbed *>(gobj()));
71 }
72
73 namespace
74 {
75     template<typename T>
76     class c_scoped_ptr
77     {
78     public:
79         explicit c_scoped_ptr(T * p = 0) : p_(p) {}
80         ~c_scoped_ptr() { free(p_); }
81         T * get() const { return p_; }
82         T * release()
83         {
84             T * p = p_;
85             p_ = NULL;
86             return p;
87         }
88         void reset(T * p = 0)
89         {
90             free(p_);
91             p_ = p;
92         }
93     private:
94         T * p_;
95     };
96 }
97
98 std::string browser_widget::get_link_message() const
99 {
100     c_scoped_ptr<char> str(
101         gtk_moz_embed_get_link_message(const_cast<GtkMozEmbed *>(gobj())));
102     return std::string(str.get());
103 }
104 std::string browser_widget::get_js_status() const
105 {
106     c_scoped_ptr<char> str(
107         gtk_moz_embed_get_js_status(const_cast<GtkMozEmbed *>(gobj())));
108     return std::string(str.get());
109 }
110 std::string browser_widget::get_title() const
111 {
112     c_scoped_ptr<char> str(
113         gtk_moz_embed_get_title(const_cast<GtkMozEmbed *>(gobj())));
114     return std::string(str.get());
115 }
116 std::string browser_widget::get_location() const
117 {
118     c_scoped_ptr<char> str(
119         gtk_moz_embed_get_location(const_cast<GtkMozEmbed *>(gobj())));
120     return std::string(str.get());
121 }
122 already_AddRefed<nsIWebBrowser> browser_widget::get_browser()
123 {
124     nsIWebBrowser * result = 0;
125     gtk_moz_embed_get_nsIWebBrowser(gobj(), &result);
126     assert(result);
127     return dont_AddRef(result);
128 }
129
130 namespace
131 {
132     void browser_widget_signal_link_message_callback(GtkMozEmbed * self, void * data)
133     {
134         typedef sigc::slot<void> SlotType;
135
136         if (Glib::ObjectBase::_get_current_wrapper((GObject *)self))
137         {
138             try
139             {
140                 if (sigc::slot_base * const slot =
141                     Glib::SignalProxyNormal::data_to_slot(data))
142                     (*static_cast<SlotType*>(slot))();
143             }
144             catch(...)
145             {
146                 Glib::exception_handlers_invoke();
147             }
148         }
149     }
150
151     const Glib::SignalProxyInfo browser_widget_signal_link_message_info =
152     {
153         "link_message",
154         (GCallback) &browser_widget_signal_link_message_callback,
155         (GCallback) &browser_widget_signal_link_message_callback
156     };
157
158     void browser_widget_signal_js_status_callback(GtkMozEmbed * self, void * data)
159     {
160         typedef sigc::slot<void> SlotType;
161
162         if (Glib::ObjectBase::_get_current_wrapper((GObject *)self))
163         {
164             try
165             {
166                 if (sigc::slot_base * const slot =
167                     Glib::SignalProxyNormal::data_to_slot(data))
168                     (*static_cast<SlotType*>(slot))();
169             }
170             catch(...)
171             {
172                 Glib::exception_handlers_invoke();
173             }
174         }
175     }
176
177     const Glib::SignalProxyInfo browser_widget_signal_js_status_info =
178     {
179         "js_status",
180         (GCallback) &browser_widget_signal_js_status_callback,
181         (GCallback) &browser_widget_signal_js_status_callback
182     };
183
184     void browser_widget_signal_location_callback(GtkMozEmbed * self, void * data)
185     {
186         typedef sigc::slot<void> SlotType;
187
188         if (Glib::ObjectBase::_get_current_wrapper((GObject *)self))
189         {
190             try
191             {
192                 if (sigc::slot_base * const slot =
193                     Glib::SignalProxyNormal::data_to_slot(data))
194                     (*static_cast<SlotType*>(slot))();
195             }
196             catch(...)
197             {
198                 Glib::exception_handlers_invoke();
199             }
200         }
201     }
202
203     const Glib::SignalProxyInfo browser_widget_signal_location_info =
204     {
205         "location",
206         (GCallback) &browser_widget_signal_location_callback,
207         (GCallback) &browser_widget_signal_location_callback
208     };
209
210     void browser_widget_signal_title_callback(GtkMozEmbed * self, void * data)
211     {
212         typedef sigc::slot<void> SlotType;
213
214         if (Glib::ObjectBase::_get_current_wrapper((GObject *)self))
215         {
216             try
217             {
218                 if (sigc::slot_base * const slot =
219                     Glib::SignalProxyNormal::data_to_slot(data))
220                     (*static_cast<SlotType*>(slot))();
221             }
222             catch(...)
223             {
224                 Glib::exception_handlers_invoke();
225             }
226         }
227     }
228
229     const Glib::SignalProxyInfo browser_widget_signal_title_info =
230     {
231         "title",
232         (GCallback) &browser_widget_signal_title_callback,
233         (GCallback) &browser_widget_signal_title_callback
234     };
235
236     void browser_widget_signal_progress_callback(
237         GtkMozEmbed * self, gint p0, gint p1, void * data)
238     {
239         typedef sigc::slot<void, gint, gint> SlotType;
240
241         if (Glib::ObjectBase::_get_current_wrapper((GObject *)self))
242         {
243             try
244             {
245                 if (sigc::slot_base * const slot =
246                     Glib::SignalProxyNormal::data_to_slot(data))
247                     (*static_cast<SlotType*>(slot))(p0, p1);
248             }
249             catch(...)
250             {
251                 Glib::exception_handlers_invoke();
252             }
253         }
254     }
255
256     const Glib::SignalProxyInfo browser_widget_signal_progress_info =
257     {
258         "progress",
259         (GCallback) &browser_widget_signal_progress_callback,
260         (GCallback) &browser_widget_signal_progress_callback
261     };
262
263     void browser_widget_signal_net_state_callback(
264         GtkMozEmbed * self, const char * p0, gint p1, guint p2, void * data)
265     {
266         typedef sigc::slot<void, const char *, gint, guint> SlotType;
267
268         if (Glib::ObjectBase::_get_current_wrapper((GObject *)self))
269         {
270             try
271             {
272                 if (sigc::slot_base * const slot =
273                     Glib::SignalProxyNormal::data_to_slot(data))
274                     (*static_cast<SlotType*>(slot))(p0, p1, p2);
275             }
276             catch(...)
277             {
278                 Glib::exception_handlers_invoke();
279             }
280         }
281     }
282
283     const Glib::SignalProxyInfo browser_widget_signal_net_state_info =
284     {
285         "net_state_all",
286         (GCallback) &browser_widget_signal_net_state_callback,
287         (GCallback) &browser_widget_signal_net_state_callback
288     };
289
290     void browser_widget_signal_net_start_callback(GtkMozEmbed * self, void * data)
291     {
292         typedef sigc::slot<void> SlotType;
293
294         if (Glib::ObjectBase::_get_current_wrapper((GObject *)self))
295         {
296             try
297             {
298                 if (sigc::slot_base * const slot =
299                     Glib::SignalProxyNormal::data_to_slot(data))
300                     (*static_cast<SlotType*>(slot))();
301             }
302             catch(...)
303             {
304                 Glib::exception_handlers_invoke();
305             }
306         }
307     }
308
309     const Glib::SignalProxyInfo browser_widget_signal_net_start_info =
310     {
311         "net_start",
312         (GCallback) &browser_widget_signal_net_start_callback,
313         (GCallback) &browser_widget_signal_net_start_callback
314     };
315
316     void browser_widget_signal_net_stop_callback(GtkMozEmbed * self, void * data)
317     {
318         typedef sigc::slot<void> SlotType;
319
320         if (Glib::ObjectBase::_get_current_wrapper((GObject *)self))
321         {
322             try
323             {
324                 if (sigc::slot_base * const slot =
325                     Glib::SignalProxyNormal::data_to_slot(data))
326                     (*static_cast<SlotType*>(slot))();
327             }
328             catch(...)
329             {
330                 Glib::exception_handlers_invoke();
331             }
332         }
333     }
334
335     const Glib::SignalProxyInfo browser_widget_signal_net_stop_info =
336     {
337         "net_stop",
338         (GCallback) &browser_widget_signal_net_stop_callback,
339         (GCallback) &browser_widget_signal_net_stop_callback
340     };
341
342     void browser_widget_signal_new_window_callback(
343         GtkMozEmbed * self, GtkMozEmbed ** p0, guint p1, void * data)
344     {
345         typedef sigc::slot<browser_widget *, guint> SlotType;
346
347         if (Glib::ObjectBase::_get_current_wrapper((GObject *)self))
348         {
349             try
350             {
351                 if (sigc::slot_base * const slot =
352                     Glib::SignalProxyNormal::data_to_slot(data))
353                 {
354                     if (browser_widget * result =
355                         (*static_cast<SlotType*>(slot))(p1))
356                     {
357                         *p0 = result->gobj();
358                         return;
359                     }
360                 }
361             }
362             catch(...)
363             {
364                 Glib::exception_handlers_invoke();
365             }
366         }
367
368         *p0 = NULL;
369         return;
370     }
371
372     const Glib::SignalProxyInfo browser_widget_signal_new_window_info =
373     {
374         "new_window",
375         (GCallback) &browser_widget_signal_new_window_callback,
376         (GCallback) &browser_widget_signal_new_window_callback
377     };
378
379     void browser_widget_signal_visibility_callback(
380         GtkMozEmbed * self, gboolean p0, void * data)
381     {
382         typedef sigc::slot<void, bool> SlotType;
383
384         if (Glib::ObjectBase::_get_current_wrapper((GObject *)self))
385         {
386             try
387             {
388                 if (sigc::slot_base * const slot =
389                     Glib::SignalProxyNormal::data_to_slot(data))
390                     (*static_cast<SlotType*>(slot))(p0);
391             }
392             catch(...)
393             {
394                 Glib::exception_handlers_invoke();
395             }
396         }
397     }
398
399     const Glib::SignalProxyInfo browser_widget_signal_visibility_info =
400     {
401         "visibility",
402         (GCallback) &browser_widget_signal_visibility_callback,
403         (GCallback) &browser_widget_signal_visibility_callback
404     };
405
406     void browser_widget_signal_destroy_browser_callback(
407         GtkMozEmbed * self, void * data)
408     {
409         typedef sigc::slot<void> SlotType;
410
411         if (Glib::ObjectBase::_get_current_wrapper((GObject *)self))
412         {
413             try
414             {
415                 if (sigc::slot_base * const slot =
416                     Glib::SignalProxyNormal::data_to_slot(data))
417                     (*static_cast<SlotType*>(slot))();
418             }
419             catch(...)
420             {
421                 Glib::exception_handlers_invoke();
422             }
423         }
424     }
425
426     const Glib::SignalProxyInfo browser_widget_signal_destroy_info =
427     {
428         "destroy_browser",
429         (GCallback) &browser_widget_signal_destroy_browser_callback,
430         (GCallback) &browser_widget_signal_destroy_browser_callback
431     };
432
433     gint browser_widget_signal_open_uri_callback(
434         GtkMozEmbed * self, const char * p0, void * data)
435     {
436         typedef sigc::slot<bool, const char *> SlotType;
437
438         if (Glib::ObjectBase::_get_current_wrapper((GObject *)self))
439         {
440             try
441             {
442                 if (sigc::slot_base * const slot =
443                     Glib::SignalProxyNormal::data_to_slot(data))
444                     return (*static_cast<SlotType*>(slot))(p0);
445             }
446             catch(...)
447             {
448                 Glib::exception_handlers_invoke();
449             }
450         }
451
452         return 0;
453     }
454
455     const Glib::SignalProxyInfo browser_widget_signal_open_uri_info =
456     {
457         "open_uri",
458         (GCallback) &browser_widget_signal_open_uri_callback,
459         (GCallback) &browser_widget_signal_open_uri_callback
460     };
461
462 } // namespace
463
464 Glib::SignalProxy0<void> browser_widget::signal_link_message()
465 {
466     return Glib::SignalProxy0<void>(this, &browser_widget_signal_link_message_info);
467 }
468 Glib::SignalProxy0<void> browser_widget::signal_js_status()
469 {
470     return Glib::SignalProxy0<void>(this, &browser_widget_signal_js_status_info);
471 }
472 Glib::SignalProxy0<void> browser_widget::signal_location()
473 {
474     return Glib::SignalProxy0<void>(this, &browser_widget_signal_location_info);
475 }
476 Glib::SignalProxy0<void> browser_widget::signal_title()
477 {
478     return Glib::SignalProxy0<void>(this, &browser_widget_signal_title_info);
479 }
480 Glib::SignalProxy2<void, gint /*cur*/, gint /*max*/> browser_widget::signal_progress()
481 {
482     return Glib::SignalProxy2<void, gint, gint>(
483         this, &browser_widget_signal_progress_info);
484 }
485 Glib::SignalProxy3<void, const char *, gint /*flags*/, guint /*status*/>
486 browser_widget::signal_net_state()
487 {
488     return Glib::SignalProxy3<void, const char *, gint, guint>(
489         this, &browser_widget_signal_net_state_info);
490 }
491 Glib::SignalProxy0<void> browser_widget::signal_net_start()
492 {
493     return Glib::SignalProxy0<void>(this, &browser_widget_signal_net_start_info);
494 }
495 Glib::SignalProxy0<void> browser_widget::signal_net_stop()
496 {
497     return Glib::SignalProxy0<void>(this, &browser_widget_signal_net_stop_info);
498 }
499 Glib::SignalProxy1<browser_widget *, guint /*chromemask*/> browser_widget::signal_new_window()
500 {
501     return Glib::SignalProxy1<browser_widget *, guint>(
502         this, &browser_widget_signal_new_window_info);
503 }
504 Glib::SignalProxy1<void, bool /*visibility*/> browser_widget::signal_visibility()
505 {
506     return Glib::SignalProxy1<void, bool>(
507         this, &browser_widget_signal_visibility_info);
508 }
509 Glib::SignalProxy0<void> browser_widget::signal_destroy()
510 {
511     return Glib::SignalProxy0<void>(this, &browser_widget_signal_destroy_info);
512 }
513 Glib::SignalProxy1<bool, const char * /*uri*/> browser_widget::signal_open_uri()
514 {
515     return Glib::SignalProxy1<bool, const char *>(
516         this, &browser_widget_signal_open_uri_info);
517 }
518
519 browser_widget::browser_widget(GObject * gobject, bool take_copy)
520 {
521     assert(GTK_MOZ_EMBED(gobject));
522     gobject_ = gobject;
523     if (take_copy)
524         reference();
525 }
526 Glib::ObjectBase * browser_widget::wrap_new(GObject * gobject)
527 {
528     return new browser_widget(gobject, false);
529 }
530
531 browser_widget::initialiser::initialiser()
532 {
533 #if MOZ_VERSION_MAJOR == 1 && MOZ_VERSION_MINOR == 9
534     static const GREVersionRange gre_versions = {
535         "1.9a", PR_TRUE,
536         "1.9.1", PR_FALSE
537     };
538     char path[PATH_MAX];
539     check(GRE_GetGREPathWithProperties(&gre_versions, 1, 0, 0,
540                                        path, sizeof(path)));
541
542     check(XPCOMGlueStartup(path));
543     check(GTKEmbedGlueStartup());
544     check(GTKEmbedGlueStartupInternal());
545
546     char * last_slash = std::strrchr(path, '/');
547     if (last_slash != path)
548         *last_slash = '\0';
549     gtk_moz_embed_set_path(path);
550 #else
551     gtk_moz_embed_set_comp_path(MOZ_LIB_DIR);
552 #endif
553
554     gtk_moz_embed_push_startup();
555
556     wrap_register(gtk_moz_embed_get_type(), wrap_new);
557 }
558
559 browser_widget::initialiser::~initialiser()
560 {
561     gtk_moz_embed_pop_startup();
562
563 #if MOZ_VERSION_MAJOR == 1 && MOZ_VERSION_MINOR == 9
564     XPCOMGlueShutdown();
565 #endif
566 }
567
568 namespace Glib
569 {
570     browser_widget * wrap(GtkMozEmbed * object, bool take_copy)
571     {
572         return dynamic_cast<browser_widget *>(
573             Glib::wrap_auto((GObject*)(object), take_copy));
574     }
575 }