download-manager.js: fix bug resulting in un-killable special buffers
[conkeror.git] / modules / window.js
blob518c78e624ea8e89ad1ea1d2aa26e97df23dcf65
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"].getService(Ci.nsIWindowWatcher);
18 function generate_new_window_tag(tag)
20     var existing = [];
21     var exact_match = false;
22     var en = window_watcher.getWindowEnumerator ();
23     if (tag == '') { tag = null; }
24     var re;
25     if (tag) {
26         re = new RegExp ("^" + tag + "<(\\d+)>$");
27     } else {
28         re = new RegExp ("^(\\d+)$");
29     }
30     while (en.hasMoreElements ()) {
31         var w = en.getNext().QueryInterface (Ci.nsIDOMWindow);
32         if ('tag' in w)  {
33             if (tag && w.tag == tag) {
34                 exact_match = true;
35                 continue;
36             }
37             var re_result = re.exec (w.tag);
38             if (re_result)
39                 existing.push (re_result[1]);
40         }
41     }
42     if (tag && ! exact_match)
43         return tag;
45     existing.sort (function (a, b) { return a - b; });
47     var n = 1;
48     for (var i = 0; i < existing.length; i++) {
49         if (existing[i] < n) continue;
50         if (existing[i] == n) { n++; continue; }
51         break;
52     }
53     if (tag) {
54         return tag + "<" + n + ">";
55     } else {
56         return n;
57     }
60 function make_chrome_window(chrome_URI, args)
62     return window_watcher.openWindow(null, chrome_URI, "_blank",
63                                      "chrome,dialog=no,all,resizable", args);
66 var conkeror_chrome_URI = "chrome://conkeror/content/conkeror.xul";
68 function make_window(initial_buffer_creator, tag)
70     var args = { tag: tag,
71                  initial_buffer_creator: initial_buffer_creator };
72     var result = make_chrome_window(conkeror_chrome_URI, null);
73     result.args = args;
74     make_window_hook.run(result);
75     return result;
78 function get_window_by_tag(tag)
80     var en = window_watcher.getWindowEnumerator ();
81     while (en.hasMoreElements ()) {
82         var w = en.getNext().QueryInterface (Ci.nsIDOMWindow);
83         if ('tag' in w && w.tag == tag)
84             return w;
85     }
86     return null;
89 /* FIXME: decide if this should include not-fully-initialized windows  */
90 function for_each_window(func)
92     var en = window_watcher.getWindowEnumerator ();
93     while (en.hasMoreElements ()) {
94         var w = en.getNext().QueryInterface (Ci.nsIDOMWindow);
95         if ('conkeror' in w)
96             func(w);
97     }
100 function get_recent_conkeror_window()
102     var window = window_watcher.activeWindow;
103     if (window && ("conkeror" in window))
104         return window;
105     var en = window_watcher.getWindowEnumerator ();
106     while (en.hasMoreElements ()) {
107         window = en.getNext().QueryInterface (Ci.nsIDOMWindow);
108         if ('conkeror' in window)
109             return window;
110     }
111     return null;
114 define_window_local_hook("window_initialize_early_hook");
115 define_window_local_hook("window_initialize_hook");
116 define_window_local_hook("window_initialize_late_hook");
118 var window_extra_argument_list = [];
120 define_variable("window_extra_argument_max_delay", 100);
122 function window_setup_args(window) {
123     if (window.args != null)
124         return;
126     var cur_time = Date.now();
127     var i;
128     var result = null;
129     for (i = 0; i < window_extra_argument_list.length; ++i) {
130         var a = window_extra_argument_list[i];
131         if (a.time > cur_time - window_extra_argument_max_delay) {
132             delete a.time;
133             result = a;
134             i++;
135             break;
136         }
137     }
138     window_extra_argument_list = window_extra_argument_list.slice(i);
140     if (result == null)
141         window.args = {};
142     else
143         window.args = result;
146 function window_set_extra_arguments(args) {
147     args.time = Date.now();
148     window_extra_argument_list.push(args);
151 function window_get_this_browser() {
152     return this.buffers.current.browser;
155 function window_initialize(window)
157     window.conkeror = conkeror;
159     // Used by get_window_from_frame to get an unwrapped window reference
160     window.escape_wrapper = function (x) { x(window); }
162     window_setup_args(window);
164     // Set tag
165     var tag = null;
166     if ('tag' in window.args)
167         tag = window.args.tag;
168     window.tag = generate_new_window_tag(tag);
170     // Add a getBrowser() function to help certain extensions designed for Firefox work with conkeror
171     window.getBrowser = window_get_this_browser;
173     window_initialize_early_hook.run(window);
174     delete window.initialize_early_hook; // used only once
176     window_initialize_hook.run(window);
177     delete window.initialize_hook; // used only once
179     window.setTimeout(function(){
180             window_initialize_late_hook.run(window);
181             delete window.window_initialize_late_hook; // used only once
182             delete window.args; // get rid of args
183         },0);
185     window.addEventListener("close", window_close_maybe, true /* capture */, false);
188 define_window_local_hook("window_before_close_hook", RUN_HOOK_UNTIL_FAILURE);
189 define_window_local_hook("window_close_hook", RUN_HOOK);
190 function window_close_maybe(event) {
191     var window = this;
193     if (!window_before_close_hook.run(window)) {
194         event.preventDefault();
195         event.stopPropagation();
196         return;
197     }
199     window_close_hook.run(window);
202 function define_global_window_mode(name, hook_name) {
203     function install(window) {
204         if (window[name])
205             throw new Error(name + " already initialized for window");
206         window[name] = new conkeror[name](window);
207     }
208     function uninstall(window) {
209         if (!window[name])
210             throw new Error(name + " not initialized for window");
211         window[name].uninstall();
212         delete window[name];
213     }
214     define_global_mode(name + "_mode",
215                        function () { // enable
216                            add_hook(hook_name, install);
217                            for_each_window(install);
218                        },
219                        function () { // disable
220                            remove_hook(hook_name, install);
221                            for_each_window(uninstall);
222                        });
224 ignore_function_for_get_caller_source_code_reference("define_global_window_mode");