2 * (C) Copyright 2007 John J. Foerch
3 * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
5 * Use, modification, and distribution are subject to the terms specified in the
11 var define_window_local_hook
= simple_local_hook_definer();
12 var define_window_local_coroutine_hook
= simple_local_coroutine_hook_definer();
15 define_hook("make_window_hook");
17 var window_watcher
= Cc
["@mozilla.org/embedcomp/window-watcher;1"]
18 .getService(Ci
.nsIWindowWatcher
);
20 function generate_new_window_tag (tag
) {
22 var exact_match
= false;
23 var en
= window_watcher
.getWindowEnumerator();
28 re
= new RegExp ("^" + tag
+ "<(\\d+)>$");
30 re
= new RegExp ("^(\\d+)$");
31 while (en
.hasMoreElements()) {
32 var w
= en
.getNext().QueryInterface(Ci
.nsIDOMWindow
);
34 if (tag
&& w
.tag
== tag
) {
38 var re_result
= re
.exec(w
.tag
);
40 existing
.push(re_result
[1]);
43 if (tag
&& ! exact_match
)
46 existing
.sort(function (a
, b
) { return a
- b
; });
49 for (var i
= 0; i
< existing
.length
; i
++) {
50 if (existing
[i
] < n
) continue;
51 if (existing
[i
] == n
) { n
++; continue; }
55 return tag
+ "<" + n
+ ">";
60 function make_chrome_window (chrome_uri
, args
) {
61 return window_watcher
.openWindow(null, chrome_uri
, "_blank",
62 "chrome,dialog=no,all,resizable", args
);
65 var conkeror_chrome_uri
= "chrome://conkeror-gui/content/conkeror.xul";
68 * This is called by Conkeror to explicitly create a conkeror.xul window.
69 * However, windows are sometimes created internally be Mozilla, for example due
70 * to the logic in content-buffer.js:browser_dom_window.openURI. In that case,
71 * make_window is not called and Conkeror sees the window for the first time in
72 * window_initialize, which needs to take care of all of the initialization that
73 * would normally happen in make_window.
75 function make_window (initial_buffer_creator
, tag
) {
76 var args
= { tag
: tag
,
77 initial_buffer_creator
: initial_buffer_creator
};
78 var result
= make_chrome_window(conkeror_chrome_uri
, null);
80 make_window_hook
.run(result
);
81 window_install_close_intercept(result
);
85 function window_install_close_intercept (window
) {
86 var close
= window
.close
;
87 window
.close = function () {
88 function attempt_close () {
89 var res
= yield window_before_close_hook
.run(window
);
91 window_close_hook
.run(window
);
95 spawn(attempt_close());
99 function get_window_by_tag (tag
) {
100 var en
= window_watcher
.getWindowEnumerator();
101 while (en
.hasMoreElements()) {
102 var w
= en
.getNext().QueryInterface(Ci
.nsIDOMWindow
);
103 if ('tag' in w
&& w
.tag
== tag
)
109 /* FIXME: decide if this should include not-fully-initialized windows */
110 function for_each_window (func
) {
111 var en
= window_watcher
.getWindowEnumerator();
112 while (en
.hasMoreElements()) {
113 var w
= en
.getNext().QueryInterface(Ci
.nsIDOMWindow
);
119 function get_recent_conkeror_window () {
120 var wm
= Cc
['@mozilla.org/appshell/window-mediator;1']
121 .getService(Ci
.nsIWindowMediator
);
122 var window
= wm
.getMostRecentWindow("navigator:browser");
123 if (window
&& ("conkeror" in window
))
125 var en
= window_watcher
.getWindowEnumerator();
126 while (en
.hasMoreElements()) {
127 window
= en
.getNext().QueryInterface(Ci
.nsIDOMWindow
);
128 if ('conkeror' in window
)
134 define_window_local_hook("window_initialize_early_hook");
135 define_window_local_hook("window_initialize_hook");
136 define_window_local_hook("window_initialize_late_hook");
138 var window_extra_argument_list
= [];
140 define_variable("window_extra_argument_max_delay", 100);
143 * Called by window_initialize. If the window was created using make_window (as
144 * indicated by window.args having been set), nothing needs to be done.
145 * Otherwise, we need to perform the setup that would otherwise occur in
148 function window_setup_args (window
) {
149 if (window
.args
!= null)
152 window_install_close_intercept(window
);
155 var cur_time
= Date
.now();
158 for (i
= 0; i
< window_extra_argument_list
.length
; ++i
) {
159 var a
= window_extra_argument_list
[i
];
160 if (a
.time
> cur_time
- window_extra_argument_max_delay
) {
167 window_extra_argument_list
= window_extra_argument_list
.slice(i
);
172 window
.args
= result
;
175 function window_set_extra_arguments (args
) {
176 args
.time
= Date
.now();
177 window_extra_argument_list
.push(args
);
180 function window_get_this_browser () {
181 return this.buffers
.current
.browser
;
184 function gbrowser(win
) {
188 gbrowser
.prototype = {
189 constructor: gbrowser
,
190 toString: function () "#<gbrowser>",
191 getBrowserForContentWindow: function (win
) {
192 return this.win
.buffers
.current
.browser
;
196 function window_initialize (window
) {
197 window
.conkeror
= conkeror
;
199 // Used by get_window_from_frame to get an unwrapped window reference
200 window
.escape_wrapper = function (x
) { x(window
); };
202 window_setup_args(window
);
206 if ('tag' in window
.args
)
207 tag
= window
.args
.tag
;
208 window
.tag
= generate_new_window_tag(tag
);
210 // Add a getBrowser() and content to help certain extensions designed
211 // for Firefox work with conkeror
212 window
.getBrowser
= window_get_this_browser
;
213 window
.gBrowser
= new gbrowser(window
);
215 window
.__defineGetter__('content',
217 return this.buffers
.current
.browser
.contentWindow
;
220 // Tell Mozilla the window_initialize_late_hook to run after a timeout
222 // Do this here, before doing the rest of the window
223 // initialization, so that window_initialize_late_hook will be run
224 // prior to any other "late" hooks set up by other modules in a
225 // function registered in window_initialize{_early,}_hook.
226 window
.setTimeout(function () {
227 window_initialize_late_hook
.run(window
);
228 delete window
.window_initialize_late_hook
; // used only once
229 delete window
.args
; // get rid of args
232 window_initialize_early_hook
.run(window
);
233 delete window
.window_initialize_early_hook
; // used only once
235 window_initialize_hook
.run(window
);
236 delete window
.window_initialize_hook
; // used only once
238 window
.addEventListener("close",
240 event
.preventDefault();
241 event
.stopPropagation();
247 define_window_local_coroutine_hook("window_before_close_hook",
248 RUN_HOOK_UNTIL_FAILURE
);
249 define_window_local_hook("window_close_hook", RUN_HOOK
);
255 function define_global_window_mode (name
, hook_name
) {
257 function install (window
) {
259 throw new Error(name
+ " already initialized for window");
260 window
[name
] = new conkeror
[name
](window
);
262 function uninstall (window
) {
264 throw new Error(name
+ " not initialized for window");
265 window
[name
].uninstall();
268 define_global_mode(name
+ "_mode",
269 function () { // enable
270 add_hook(hook_name
, install
);
271 for_each_window(install
);
273 function () { // disable
274 remove_hook(hook_name
, install
);
275 for_each_window(uninstall
);
277 forward_keywords(arguments
));
279 ignore_function_for_get_caller_source_code_reference("define_global_window_mode");
288 * Default tile formatter. The page url is ignored. If there is a
289 * page_title, returns: "Page title - Conkeror". Otherwise, it
290 * returns just: "Conkeror".
292 function default_title_formatter (window
) {
293 var page_title
= window
.buffers
.current
.title
;
295 if (page_title
&& page_title
.length
> 0)
296 return page_title
+ " - Conkeror";
301 var title_format_fn
= null;
303 function set_window_title (window
) {
304 window
.document
.title
= title_format_fn(window
);
307 function init_window_title () {
308 title_format_fn
= default_title_formatter
;
310 add_hook("window_initialize_late_hook", set_window_title
);
311 add_hook("current_content_buffer_location_change_hook",
313 set_window_title(buffer
.window
);
315 add_hook("select_buffer_hook",
317 set_window_title(buffer
.window
);
319 add_hook("current_buffer_title_change_hook",
321 set_window_title(buffer
.window
);
328 function call_builtin_command (window
, command
, clear_mark
) {
329 var m
= window
.minibuffer
;
330 if (m
.active
&& m
._input_mode_enabled
) {
331 m
._restore_normal_state();
332 var e
= m
.input_element
;
333 var c
= e
.controllers
.getControllerForCommand(command
);
335 if (c
&& c
.isCommandEnabled(command
))
336 c
.doCommand(command
);
341 m
.current_state
.mark_active
= false;
343 var attempt_command
= function attempt_command (element
) {
345 if (element
.controllers
346 && (c
= element
.controllers
.getControllerForCommand(command
)) != null
347 && c
.isCommandEnabled(command
))
350 c
.doCommand(command
);
355 window
.buffers
.current
.mark_active
= false;
360 var element
= window
.buffers
.current
.focused_element
;
361 if (element
&& attempt_command(element
, command
))
363 var win
= window
.buffers
.current
.focused_frame
;
365 if (attempt_command(win
, command
))
367 if (!win
.parent
|| win
== win
.parent
)
376 * window_set_full_screen sets or toggles the fullScreen and hideChrome
377 * properties of the given window. When fullscreen is a boolean, it sets
378 * it to that value. When it is null or not given, it toggles the current
381 function window_set_full_screen (window
, fullscreen
) {
382 if (fullscreen
=== true || fullscreen
=== false) {
383 window
.fullScreen
= fullscreen
;
384 window
.hideChrome
= fullscreen
;
386 window
.fullScreen
= ! window
.fullScreen
;
387 window
.hideChrome
= window
.fullScreen
;