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