browser-next-form-field: skip non-visible elements
[conkeror.git] / modules / window.js
blobb74d7736673fd21dfa5b89d0e1c217f773991983
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-gui/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     result._close = result.close;
76     result.close = function () {
77       if (window_before_close_hook.run(result))
78         result._close();
79     };
80     return result;
83 function get_window_by_tag(tag)
85     var en = window_watcher.getWindowEnumerator ();
86     while (en.hasMoreElements ()) {
87         var w = en.getNext().QueryInterface (Ci.nsIDOMWindow);
88         if ('tag' in w && w.tag == tag)
89             return w;
90     }
91     return null;
94 /* FIXME: decide if this should include not-fully-initialized windows  */
95 function for_each_window(func)
97     var en = window_watcher.getWindowEnumerator ();
98     while (en.hasMoreElements ()) {
99         var w = en.getNext().QueryInterface (Ci.nsIDOMWindow);
100         if ('conkeror' in w)
101             func(w);
102     }
105 function get_recent_conkeror_window()
107     var window = window_watcher.activeWindow;
108     if (window && ("conkeror" in window))
109         return window;
110     var en = window_watcher.getWindowEnumerator ();
111     while (en.hasMoreElements ()) {
112         window = en.getNext().QueryInterface (Ci.nsIDOMWindow);
113         if ('conkeror' in window)
114             return window;
115     }
116     return null;
119 define_window_local_hook("window_initialize_early_hook");
120 define_window_local_hook("window_initialize_hook");
121 define_window_local_hook("window_initialize_late_hook");
123 var window_extra_argument_list = [];
125 define_variable("window_extra_argument_max_delay", 100);
127 function window_setup_args(window) {
128     if (window.args != null)
129         return;
131     var cur_time = Date.now();
132     var i;
133     var result = null;
134     for (i = 0; i < window_extra_argument_list.length; ++i) {
135         var a = window_extra_argument_list[i];
136         if (a.time > cur_time - window_extra_argument_max_delay) {
137             delete a.time;
138             result = a;
139             i++;
140             break;
141         }
142     }
143     window_extra_argument_list = window_extra_argument_list.slice(i);
145     if (result == null)
146         window.args = {};
147     else
148         window.args = result;
151 function window_set_extra_arguments(args) {
152     args.time = Date.now();
153     window_extra_argument_list.push(args);
156 function window_get_this_browser() {
157     return this.buffers.current.browser;
160 function window_initialize(window)
162     window.conkeror = conkeror;
164     // Used by get_window_from_frame to get an unwrapped window reference
165     window.escape_wrapper = function (x) { x(window); };
167     window_setup_args(window);
169     // Set tag
170     var tag = null;
171     if ('tag' in window.args)
172         tag = window.args.tag;
173     window.tag = generate_new_window_tag(tag);
175     // Add a getBrowser() function to help certain extensions designed for Firefox work with conkeror
176     window.getBrowser = window_get_this_browser;
178     window_initialize_early_hook.run(window);
179     delete window.initialize_early_hook; // used only once
181     window_initialize_hook.run(window);
182     delete window.initialize_hook; // used only once
184     window.setTimeout(function(){
185             window_initialize_late_hook.run(window);
186             delete window.window_initialize_late_hook; // used only once
187             delete window.args; // get rid of args
188         },0);
190     window.addEventListener("close", window_close_maybe, true /* capture */, false);
193 define_window_local_hook("window_before_close_hook", RUN_HOOK_UNTIL_FAILURE);
194 define_window_local_hook("window_close_hook", RUN_HOOK);
195 function window_close_maybe(event) {
196     var window = this;
198     if (!window_before_close_hook.run(window)) {
199         event.preventDefault();
200         event.stopPropagation();
201         return;
202     }
204     window_close_hook.run(window);
207 function define_global_window_mode(name, hook_name) {
208     function install(window) {
209         if (window[name])
210             throw new Error(name + " already initialized for window");
211         window[name] = new conkeror[name](window);
212     }
213     function uninstall(window) {
214         if (!window[name])
215             throw new Error(name + " not initialized for window");
216         window[name].uninstall();
217         delete window[name];
218     }
219     define_global_mode(name + "_mode",
220                        function () { // enable
221                            add_hook(hook_name, install);
222                            for_each_window(install);
223                        },
224                        function () { // disable
225                            remove_hook(hook_name, install);
226                            for_each_window(uninstall);
227                        });
229 ignore_function_for_get_caller_source_code_reference("define_global_window_mode");
233 /// Window title formatting
236  * Default tile formatter.  The page url is ignored.  If there is a
237  * page_title, returns: "Page title - Conkeror".  Otherwise, it
238  * returns just: "Conkeror".
239  */
240 function default_title_formatter (window)
242     var page_title = window.buffers.current.title;
244     if (page_title && page_title.length > 0)
245         return page_title + " - Conkeror";
246     else
247         return "Conkeror";
250 var title_format_fn = null;
252 function set_window_title (window)
254     window.document.title = title_format_fn(window);
257 function init_window_title ()
259     title_format_fn = default_title_formatter;
261     add_hook("window_initialize_late_hook", set_window_title);
262     add_hook("current_content_buffer_location_change_hook",
263              function (buffer) {
264                  set_window_title(buffer.window);
265              });
266     add_hook("select_buffer_hook", function (buffer) { set_window_title(buffer.window); }, true);
267     add_hook("current_buffer_title_change_hook",
268              function (buffer) {
269                  set_window_title(buffer.window);
270              });
273 init_window_title ();