From 27839f303def20b6392af34792c3fb6fe9066bdf Mon Sep 17 00:00:00 2001 From: Martin Stubenschrott Date: Sun, 12 Aug 2007 00:03:44 +0000 Subject: [PATCH] commandline and MIW try to keep focus now changed commandline handling in general autosize MIW on new content new handling should be more robust, but there may be bugs, please report --- NEWS | 1 + chrome/content/vimperator/events.js | 17 +-- chrome/content/vimperator/ui.js | 161 ++++++++++++----------- chrome/content/vimperator/vimperator.js | 11 +- chrome/content/vimperator/vimperator.xul | 6 +- 5 files changed, 103 insertions(+), 93 deletions(-) diff --git a/NEWS b/NEWS index 122bb7c6..8857f046 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@
 2007-08-*:
 	* version 0.5
+	* the command line keeps focus now, even when clicking outside of it
 	* vimperator.events.feedkeys("2zi") support for scripts
 	* Ctrl-U/Ctrl-D for scrolling the window up/down and the associated
 	'scroll' option
diff --git a/chrome/content/vimperator/events.js b/chrome/content/vimperator/events.js
index b8649a7e..90cee437 100644
--- a/chrome/content/vimperator/events.js
+++ b/chrome/content/vimperator/events.js
@@ -46,18 +46,19 @@ function Events() //{{{
     tabcontainer.addEventListener("TabOpen",   function(event) {
         vimperator.statusline.updateTabCount();
         vimperator.buffer.updateBufferList();
-        vimperator.setMode(); // trick to reshow the mode in the command line
+        //vimperator.setMode(); // trick to reshow the mode in the command line
     }, false);
     tabcontainer.addEventListener("TabClose",  function(event) {
         vimperator.statusline.updateTabCount()
         vimperator.buffer.updateBufferList();
-        vimperator.setMode(); // trick to reshow the mode in the command line
+        //vimperator.setMode(); // trick to reshow the mode in the command line
     }, false);
     tabcontainer.addEventListener("TabSelect", function(event) {
         vimperator.statusline.updateTabCount();
         vimperator.buffer.updateBufferList();
-        vimperator.setMode(); // trick to reshow the mode in the command line
+        //vimperator.setMode(); // trick to reshow the mode in the command line
         vimperator.tabs.updateSelectionHistory();
+        setTimeout(vimperator.focusContent, 10); // just make sure, that no widget has focus
     }, false);
 
     // this adds an event which is is called on each page load, even if the
@@ -205,7 +206,9 @@ function Events() //{{{
     this.destroy = function()
     {
         // BIG TODO: removeEventListeners() to avoid mem leaks
-        window.dump("TODO: remove eventlisteners");
+        window.dump("TODO: remove all eventlisteners");
+
+        getBrowser().removeProgressListener(this.progressListener);
     }
 
     // This method pushes keys into the event queue from vimperator
@@ -337,16 +340,15 @@ function Events() //{{{
         if (!vimperator.hasMode(vimperator.modes.ESCAPE_ONE_KEY))
         {
             vimperator.setMode(vimperator.modes.NORMAL);
-            vimperator.echo("");
+            vimperator.commandline.clear();
             vimperator.hints.disableHahMode();
-            vimperator.focusContent();
             vimperator.statusline.updateUrl();
+            vimperator.focusContent();
         }
     }
 
     this.onKeyPress = function(event)
     {
-        //var key = event.toString()
         var key = vimperator.events.toString(event);
         if (!key)
              return false;
@@ -562,7 +564,6 @@ function Events() //{{{
     }
     window.addEventListener("keypress", this.onKeyPress, true);
 
-
     this.progressListener =
     {
         QueryInterface: function(aIID)
diff --git a/chrome/content/vimperator/ui.js b/chrome/content/vimperator/ui.js
index 2f59815b..a476283e 100644
--- a/chrome/content/vimperator/ui.js
+++ b/chrome/content/vimperator/ui.js
@@ -69,7 +69,7 @@ function CommandLine() //{{{
     multiline_output_widget.collapsed = false;
     setTimeout(function() { multiline_output_widget.collapsed = true; }, 0);
 
-    // The widget used for multiline output
+    // The widget used for multiline iutput
     var multiline_input_widget = document.getElementById("vimperator-multiline-input");
 
     // we need to save the mode which were in before opening the command line
@@ -81,10 +81,6 @@ function CommandLine() //{{{
     var old_mode = null; // when we leave the command prompt this mode is restored
     var old_extended_mode = null;
 
-    // an ugly hack that we allow the :echo(err) commands after hitting enter
-    // and before the blur() event gets fired
-    var echo_allowed = false;
-
     // save the arguments for the inputMultiline method which are needed in the event handler
     var multiline_regexp = null;
     var multiline_callback = null;
@@ -100,7 +96,8 @@ function CommandLine() //{{{
     }
     function setMessageStyle()
     {
-        command_widget.inputField.setAttribute("style", "font-family: monospace; color:magenta; font-weight: bold");
+        prompt_widget.setAttribute("style", "font-family: monospace; color:magenta; font-weight: bold");
+        command_widget.inputField.setAttribute("style","font-family: monospace;");
     }
     function setErrorStyle()
     {
@@ -142,14 +139,14 @@ function CommandLine() //{{{
 
         multiline_input_widget.collapsed = true;
 
-        vimperator.log(content_height);
+        // vimperator.log(content_height);
         cmd = cmd.replace(/\n|\\n/g, "
") + "
Press ENTER or type command to continue"; multiline_output_widget.contentDocument.body.innerHTML = cmd; // TODO: resize upon a window resize var available_height = getBrowser().mPanelContainer.boxObject.height; var content_height = multiline_output_widget.contentDocument.height; - vimperator.log(content_height); + // vimperator.log(content_height); var height = content_height < available_height ? content_height : available_height; multiline_output_widget.style.height = height + "px"; @@ -157,10 +154,26 @@ function CommandLine() //{{{ setTimeout(function() { multiline_output_widget.focus(); }, 10); - vimperator.log(content_height); + //vimperator.log(content_height); multiline_output_widget.contentWindow.scrollTo(0, content_height); // scroll to the end when 'nomore' is set } + function autosizeMultilineInputWidget() + { + // XXX: faster/better method? + + var lines = 0; + var str = multiline_input_widget.value; + for (var i = 0; i < str.length; i++) + { + if (str[i] == "\n") + lines++; + } + if (lines == 0) + lines = 1; + multiline_input_widget.setAttribute("rows", lines.toString()); + } + function addToHistory(str) { if (str.length < 1) @@ -199,9 +212,12 @@ function CommandLine() //{{{ history_index = UNINITIALIZED; completion_index = UNINITIALIZED; - // the command_widget.focus() method calls setPrompt() and setCommand() - // this is done, because for follow-mouse window managers, we receive - // blur and focus events once the user leaves the Firefox window with the mouse + // save the mode, because we need to restore it + [old_mode, old_extended_mode] = vimperator.getMode(); + vimperator.setMode(vimperator.modes.COMMAND_LINE, cur_extended_mode, true); + setPrompt(cur_prompt); + setCommand(cur_command); + command_widget.focus(); }; @@ -209,7 +225,7 @@ function CommandLine() //{{{ this.echo = function(str, flags) { var focused = document.commandDispatcher.focusedElement; - if (!echo_allowed && focused && focused == command_widget.inputField) + if (/*!echo_allowed && focused && */focused == command_widget.inputField) return false; if (typeof str != "string") @@ -222,8 +238,6 @@ function CommandLine() //{{{ } else { - multiline_output_widget.collapsed = true; - multiline_input_widget.collapsed = true; setPrompt(""); setCommand(str); } @@ -234,7 +248,7 @@ function CommandLine() //{{{ this.echoErr = function(str) { var focused = document.commandDispatcher.focusedElement; - if (!echo_allowed && focused && focused == command_widget.inputField) + if (/*!echo_allowed && focused && */focused == command_widget.inputField) return false; setErrorStyle(); @@ -250,9 +264,9 @@ function CommandLine() //{{{ { // TODO: unfinished, need to find out how/if we can block the execution of code // to make this code synchronous or at least use a callback - setPrompt(""); setMessageStyle(); - setCommand(str); + setPrompt(str); + setCommand(""); return "not implemented"; }; @@ -261,8 +275,8 @@ function CommandLine() //{{{ this.inputMultiline = function(until_regexp, callback_func) { // save the mode, because we need to restore it on blur() -// [old_mode, old_extended_mode] = vimperator.getMode(); -// vimperator.setMode(vimperator.modes.COMMAND_LINE, vimperator.modes.READ_MULTLINE, true); + [old_mode, old_extended_mode] = vimperator.getMode(); + vimperator.setMode(vimperator.modes.COMMAND_LINE, vimperator.modes.READ_MULTILINE, true); // save the arguments, they are needed in the event handler onEvent multiline_regexp = until_regexp; @@ -270,15 +284,19 @@ function CommandLine() //{{{ multiline_input_widget.collapsed = false; multiline_input_widget.value = ""; + autosizeMultilineInputWidget(); + setTimeout(function() { multiline_input_widget.focus(); }, 10); - }; this.clear = function() { - setPrompt(" "); // looks faster than an empty string + multiline_input_widget.collapsed = true; + multiline_output_widget.collapsed = true; + + setPrompt(" "); // looks faster than an empty string as most prompts are 1 char long setCommand(""); setNormalStyle(); }; @@ -289,53 +307,18 @@ function CommandLine() //{{{ if (event.type == "blur") { - // when we do a command_widget.focus() we get a blur event immediately, - // so check if the target is the actualy input field - if (event.target == command_widget.inputField) - { - var silent = false; - if (old_mode == vimperator.modes.NORMAL) - silent = true; - vimperator.setMode(old_mode || vimperator.modes.NORMAL, old_extended_mode || null, silent); - cur_command = command; - - // don't add the echoed command to the history, on pressing , the - // command is saved right into the kepress handler - if (!echo_allowed) - addToHistory(command); - - completionlist.hide(); - vimperator.statusline.updateProgress(""); // we may have a "match x of y" visible - } + // prevent losing focus, there should be a better way, but it just didn't work otherwise + if (vimperator.hasMode(vimperator.modes.COMMAND_LINE)) + setTimeout(function() { command_widget.inputField.focus(); }, 0); } else if (event.type == "focus") { - // if we manually click into the command line, don't open it - if (event.target == command_widget.inputField && cur_extended_mode != null) - { - // save the mode, because we need to restore it on blur() - [old_mode, old_extended_mode] = vimperator.getMode(); - vimperator.setMode(vimperator.modes.COMMAND_LINE, cur_extended_mode); - - setPrompt(cur_prompt); - setCommand(cur_command); - } - else - { - //event.stopPropagation(); // XXX: doesnt seem to work - //event.preventDefault(); // so we need to use the hack below --mst - - // NOTE: echo_allowed is a misleading name here, actually this flag is set - // so that we don't save a history entry if the user clicks into the text field - echo_allowed = true; + if (!cur_extended_mode) event.target.blur(); - echo_allowed = false; - return false; - } } else if (event.type == "input") { - vimperator.triggerCallback("change", command); + vimperator.triggerCallback("change", cur_extended_mode, command); } else if (event.type == "keypress") { @@ -344,20 +327,24 @@ function CommandLine() //{{{ /* user pressed ENTER to carry out a command */ if (vimperator.events.isAcceptKey(key)) { - echo_allowed = true; + var mode = cur_extended_mode; // save it here, as setMode() resets it addToHistory(command); - var res = vimperator.triggerCallback("submit", command); + vimperator.setMode(old_mode, old_extended_mode); vimperator.focusContent(); - echo_allowed = false; - return res; + completionlist.hide(); + vimperator.statusline.updateProgress(""); // we may have a "match x of y" visible + return vimperator.triggerCallback("submit", mode, command); } /* user pressed ESCAPE to cancel this prompt */ else if (vimperator.events.isCancelKey(key)) { - var res = vimperator.triggerCallback("cancel"); - // the command history item is saved in the blur() handler + var res = vimperator.triggerCallback("cancel", cur_extended_mode); + addToHistory(command); + vimperator.setMode(old_mode, old_extended_mode); vimperator.focusContent(); + completionlist.hide(); + vimperator.statusline.updateProgress(""); // we may have a "match x of y" visible this.clear(); return res; } @@ -422,12 +409,12 @@ function CommandLine() //{{{ completion_prefix = command.substring(0, command_widget.selectionStart); completion_postfix = command.substring(command_widget.selectionStart); - var res = vimperator.triggerCallback("complete", completion_prefix); + var res = vimperator.triggerCallback("complete", cur_extended_mode, completion_prefix); if (res) [completion_start_index, completions] = res; // Sort the completion list - if (vimperator.options["wildoptions"].match(/\bsort\b/)) + if (vimperator.options["wildoptions"].search(/\bsort\b/)) { completions.sort(function(a, b) { if (a[0] < b[0]) @@ -545,24 +532,42 @@ function CommandLine() //{{{ this.onMultilineInputEvent = function(event) { - var key = vimperator.events.toString(event); - if (vimperator.events.isAcceptKey(key)) + if (event.type == "keypress") { - //var lines = multiline_input_widget.value.substr(0, multiline_input_widget.selectionStart).split(/\n/); - var text = multiline_input_widget.value.substr(0, multiline_input_widget.selectionStart); - if (text.match(multiline_regexp)) + var key = vimperator.events.toString(event); + if (vimperator.events.isAcceptKey(key)) { - text = text.replace(multiline_regexp, ""); - multiline_callback.call(this, text); + //var lines = multiline_input_widget.value.substr(0, multiline_input_widget.selectionStart).split(/\n/); + var text = multiline_input_widget.value.substr(0, multiline_input_widget.selectionStart); + if (text.match(multiline_regexp)) + { + text = text.replace(multiline_regexp, ""); + vimperator.setMode(old_mode, old_extended_mode); + multiline_input_widget.collapsed = true; + multiline_callback.call(this, text); + } + } + else if (vimperator.events.isCancelKey(key)) + { + vimperator.setMode(old_mode, old_extended_mode); multiline_input_widget.collapsed = true; } } + else if (event.type == "blur") + { + if (vimperator.hasMode(vimperator.modes.READ_MULTILINE)) + setTimeout(function() { multiline_input_widget.inputField.focus(); }, 0); + } + else if (event.type == "input") + { + autosizeMultilineInputWidget(); + } } this.onMultilineOutputEvent = function(event) { var key = vimperator.events.toString(event); - if (vimperator.events.isAcceptKey(key)) + if (vimperator.events.isAcceptKey(key) || vimperator.events.isCancelKey(key)) { multiline_output_widget.collapsed = true; vimperator.focusContent(); diff --git a/chrome/content/vimperator/vimperator.js b/chrome/content/vimperator/vimperator.js index fc337fb9..36ebdf56 100644 --- a/chrome/content/vimperator/vimperator.js +++ b/chrome/content/vimperator/vimperator.js @@ -42,7 +42,7 @@ const vimperator = (function() //{{{ COMMAND_LINE: 1 << 4, // extended modes EX: 1 << 10, - READ_MULTLINE: 1 << 11, + READ_MULTILINE: 1 << 11, SEARCH_FORWARD: 1 << 12, SEARCH_BACKWARD: 1 << 13, ESCAPE_ONE_KEY: 1 << 14, @@ -125,12 +125,13 @@ const vimperator = (function() //{{{ count: -1 // parsed count from the input buffer }, - /** TODO: for now, these callbacks are mostly for the command line, move there? - * @param type Can be: + /** + * @param type can be: * "submit": when the user pressed enter in the command line * "change" * "cancel" * "complete" + * TODO: "zoom": if the zoom value of the current buffer changed */ registerCallback: function(type, mode, func) { @@ -138,12 +139,12 @@ const vimperator = (function() //{{{ callbacks.push([type, mode, func]); }, - triggerCallback: function(type, data) + triggerCallback: function(type, mode, data) { for (var i in callbacks) { var [thistype, thismode, thisfunc] = callbacks[i]; - if (vimperator.hasMode(thismode) && type == thistype) + if (mode == thismode && type == thistype) return thisfunc.call(this, data); } return false; diff --git a/chrome/content/vimperator/vimperator.xul b/chrome/content/vimperator/vimperator.xul index f69a3516..2d6be2ad 100644 --- a/chrome/content/vimperator/vimperator.xul +++ b/chrome/content/vimperator/vimperator.xul @@ -105,12 +105,14 @@ the terms of any one of the MPL, the GPL or the LGPL. onkeypress="vimperator.commandline.onMultilineOutputEvent(event)"/>