view-as-mime-type: fix bug in interactive declaration
[conkeror.git] / modules / window.js
blob6cc51e5b192079b821a98676f0bcd8d856968477
1 /**
2  * (C) Copyright 2007 John J. Foerch
3  * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
4  *
5  * Use, modification, and distribution are subject to the terms specified in the
6  * COPYING file.
7 **/
9 require("mode.js");
11 var define_window_local_hook = simple_local_hook_definer();
14 define_hook("make_window_hook");
16 var window_watcher = Cc["@mozilla.org/embedcomp/window-watcher;1"]
17     .getService(Ci.nsIWindowWatcher);
19 function generate_new_window_tag(tag)
21     var existing = [];
22     var exact_match = false;
23     var en = window_watcher.getWindowEnumerator ();
24     if (tag == '') { tag = null; }
25     var re;
26     if (tag) {
27         re = new RegExp ("^" + tag + "<(\\d+)>$");
28     } else {
29         re = new RegExp ("^(\\d+)$");
30     }
31     while (en.hasMoreElements ()) {
32         var w = en.getNext().QueryInterface (Ci.nsIDOMWindow);
33         if ('tag' in w)  {
34             if (tag && w.tag == tag) {
35                 exact_match = true;
36                 continue;
37             }
38             var re_result = re.exec (w.tag);
39             if (re_result)
40                 existing.push (re_result[1]);
41         }
42     }
43     if (tag && ! exact_match)
44         return tag;
46     existing.sort (function (a, b) { return a - b; });
48     var n = 1;
49     for (var i = 0; i < existing.length; i++) {
50         if (existing[i] < n) continue;
51         if (existing[i] == n) { n++; continue; }
52         break;
53     }
54     if (tag) {
55         return tag + "<" + n + ">";
56     } else {
57         return n;
58     }
61 function make_chrome_window(chrome_URI, args)
63     return window_watcher.openWindow(null, chrome_URI, "_blank",
64                                      "chrome,dialog=no,all,resizable", args);
67 var conkeror_chrome_URI = "chrome://conkeror-gui/content/conkeror.xul";
69 function make_window(initial_buffer_creator, tag)
71     var args = { tag: tag,
72                  initial_buffer_creator: initial_buffer_creator };
73     var result = make_chrome_window(conkeror_chrome_URI, null);
74     result.args = args;
75     make_window_hook.run(result);
76     result._close = result.close;
77     result.close = function () {
78       if (window_before_close_hook.run(result))
79         result._close();
80     };
81     return result;
84 function get_window_by_tag(tag)
86     var en = window_watcher.getWindowEnumerator ();
87     while (en.hasMoreElements ()) {
88         var w = en.getNext().QueryInterface (Ci.nsIDOMWindow);
89         if ('tag' in w && w.tag == tag)
90             return w;
91     }
92     return null;
95 /* FIXME: decide if this should include not-fully-initialized windows  */
96 function for_each_window(func)
98     var en = window_watcher.getWindowEnumerator ();
99     while (en.hasMoreElements ()) {
100         var w = en.getNext().QueryInterface (Ci.nsIDOMWindow);
101         if ('conkeror' in w)
102             func(w);
103     }
106 function get_recent_conkeror_window()
108     var window = window_watcher.activeWindow;
109     if (window && ("conkeror" in window))
110         return window;
111     var en = window_watcher.getWindowEnumerator ();
112     while (en.hasMoreElements ()) {
113         window = en.getNext().QueryInterface (Ci.nsIDOMWindow);
114         if ('conkeror' in window)
115             return window;
116     }
117     return null;
120 define_window_local_hook("window_initialize_early_hook");
121 define_window_local_hook("window_initialize_hook");
122 define_window_local_hook("window_initialize_late_hook");
124 var window_extra_argument_list = [];
126 define_variable("window_extra_argument_max_delay", 100);
128 function window_setup_args(window) {
129     if (window.args != null)
130         return;
132     var cur_time = Date.now();
133     var i;
134     var result = null;
135     for (i = 0; i < window_extra_argument_list.length; ++i) {
136         var a = window_extra_argument_list[i];
137         if (a.time > cur_time - window_extra_argument_max_delay) {
138             delete a.time;
139             result = a;
140             i++;
141             break;
142         }
143     }
144     window_extra_argument_list = window_extra_argument_list.slice(i);
146     if (result == null)
147         window.args = {};
148     else
149         window.args = result;
152 function window_set_extra_arguments(args) {
153     args.time = Date.now();
154     window_extra_argument_list.push(args);
157 function window_get_this_browser() {
158     return this.buffers.current.browser;
161 function window_initialize(window)
163     window.conkeror = conkeror;
165     // Used by get_window_from_frame to get an unwrapped window reference
166     window.escape_wrapper = function (x) { x(window); };
168     window_setup_args(window);
170     // Set tag
171     var tag = null;
172     if ('tag' in window.args)
173         tag = window.args.tag;
174     window.tag = generate_new_window_tag(tag);
176     // Add a getBrowser() function to help certain extensions designed for Firefox work with conkeror
177     window.getBrowser = window_get_this_browser;
179     window_initialize_early_hook.run(window);
180     delete window.window_initialize_early_hook; // used only once
182     window_initialize_hook.run(window);
183     delete window.window_initialize_hook; // used only once
185     window.setTimeout(function(){
186             window_initialize_late_hook.run(window);
187             delete window.window_initialize_late_hook; // used only once
188             delete window.args; // get rid of args
189         },0);
191     window.addEventListener("close", window_close_maybe, true /* capture */, false);
194 define_window_local_hook("window_before_close_hook", RUN_HOOK_UNTIL_FAILURE);
195 define_window_local_hook("window_close_hook", RUN_HOOK);
196 function window_close_maybe(event) {
197     var window = this;
199     if (!window_before_close_hook.run(window)) {
200         event.preventDefault();
201         event.stopPropagation();
202         return;
203     }
205     window_close_hook.run(window);
208 function define_global_window_mode(name, hook_name) {
209     function install(window) {
210         if (window[name])
211             throw new Error(name + " already initialized for window");
212         window[name] = new conkeror[name](window);
213     }
214     function uninstall(window) {
215         if (!window[name])
216             throw new Error(name + " not initialized for window");
217         window[name].uninstall();
218         delete window[name];
219     }
220     define_global_mode(name + "_mode",
221                        function () { // enable
222                            add_hook(hook_name, install);
223                            for_each_window(install);
224                        },
225                        function () { // disable
226                            remove_hook(hook_name, install);
227                            for_each_window(uninstall);
228                        });
230 ignore_function_for_get_caller_source_code_reference("define_global_window_mode");
234 /// Window title formatting
237  * Default tile formatter.  The page url is ignored.  If there is a
238  * page_title, returns: "Page title - Conkeror".  Otherwise, it
239  * returns just: "Conkeror".
240  */
241 function default_title_formatter (window)
243     var page_title = window.buffers.current.title;
245     if (page_title && page_title.length > 0)
246         return page_title + " - Conkeror";
247     else
248         return "Conkeror";
251 var title_format_fn = null;
253 function set_window_title (window)
255     window.document.title = title_format_fn(window);
258 function init_window_title ()
260     title_format_fn = default_title_formatter;
262     add_hook("window_initialize_late_hook", set_window_title);
263     add_hook("current_content_buffer_location_change_hook",
264              function (buffer) {
265                  set_window_title(buffer.window);
266              });
267     add_hook("select_buffer_hook", function (buffer) { set_window_title(buffer.window); }, true);
268     add_hook("current_buffer_title_change_hook",
269              function (buffer) {
270                  set_window_title(buffer.window);
271              });
274 init_window_title ();