From b0a43790b4589bdc00fc239a91ca7ebb57e41219 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 28 Mar 2013 21:06:48 +0400 Subject: [PATCH] do not overlay editor text when ime is active fixes #1112 --- lib/ace/css/editor.css | 5 ++- lib/ace/edit_session.js | 8 +++++ lib/ace/keyboard/textinput.js | 63 +++++++++++++++++++++++++++-------- lib/ace/virtual_renderer.js | 9 +++-- 4 files changed, 65 insertions(+), 20 deletions(-) diff --git a/lib/ace/css/editor.css b/lib/ace/css/editor.css index 81f8fbe6..834ca301 100644 --- a/lib/ace/css/editor.css +++ b/lib/ace/css/editor.css @@ -101,6 +101,8 @@ outline: none; overflow: hidden; font: inherit; + padding: 0 1px; + margin: 0 -1px; } .ace_text-input.ace_composition { @@ -108,9 +110,6 @@ color: #111; z-index: 1000; opacity: 1; - border: solid lightgray 1px; - margin: -1px; - padding: 0 1px; } .ace_layer { diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index f6744907..a58a8a5b 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -417,6 +417,14 @@ var EditSession = function(text, mode) { } }; + /** + * starts a new group in undo history + **/ + this.markUndoGroup = function() { + if (this.$syncInformUndoManager) + this.$syncInformUndoManager(); + }; + this.$defaultUndoManager = { undo: function() {}, redo: function() {}, diff --git a/lib/ace/keyboard/textinput.js b/lib/ace/keyboard/textinput.js index 6bb2469a..3f631001 100644 --- a/lib/ace/keyboard/textinput.js +++ b/lib/ace/keyboard/textinput.js @@ -59,7 +59,7 @@ var TextInput = function(parentNode, host) { var cut = false; var copied = false; var pasted = false; - var inCompostion = false; + var inComposition = false; var tempStyle = ''; var isSelectionEmpty = true; @@ -87,14 +87,14 @@ var TextInput = function(parentNode, host) { isFocused && resetSelection(isSelectionEmpty); }); var syncValue = lang.delayedCall(function() { - if (!inCompostion) { + if (!inComposition) { text.value = PLACEHOLDER; isFocused && resetSelection(); } }); function resetSelection(isEmpty) { - if (inCompostion) + if (inComposition) return; if (inputHandler) { selectionStart = 0; @@ -110,7 +110,7 @@ var TextInput = function(parentNode, host) { } function resetValue() { - if (inCompostion) + if (inComposition) return; text.value = PLACEHOLDER; //http://code.google.com/p/chromium/issues/detail?id=76516 @@ -156,7 +156,7 @@ var TextInput = function(parentNode, host) { if (inPropertyChange) return; var data = text.value; - if (inCompostion || !data || data == PLACEHOLDER) + if (inComposition || !data || data == PLACEHOLDER) return; // can happen either after delete or during insert operation if (e && data == PLACEHOLDER[0]) @@ -173,12 +173,12 @@ var TextInput = function(parentNode, host) { var keytable = { 13:1, 27:1 }; event.addListener(text, "keyup", function (e) { - if (inCompostion && (!text.value || keytable[e.keyCode])) + if (inComposition && (!text.value || keytable[e.keyCode])) setTimeout(onCompositionEnd, 0); if ((text.value.charCodeAt(0)||0) < 129) { return; } - inCompostion ? onCompositionUpdate() : onCompositionStart(); + inComposition ? onCompositionUpdate() : onCompositionStart(); }); } @@ -231,7 +231,7 @@ var TextInput = function(parentNode, host) { afterContextMenu = false; }; var onInput = function(e) { - if (inCompostion) + if (inComposition) return; var data = text.value; sendText(data); @@ -349,20 +349,55 @@ var TextInput = function(parentNode, host) { // COMPOSITION var onCompositionStart = function(e) { - inCompostion = true; + inComposition = {}; host.onCompositionStart(); setTimeout(onCompositionUpdate, 0); + host.on("mousedown", onCompositionEnd); + if (!host.selection.isEmpty()) { + host.insert(""); + host.session.markUndoGroup(); + host.selection.clearSelection(); + } + host.session.markUndoGroup(); }; var onCompositionUpdate = function() { - if (!inCompostion) return; + if (!inComposition) return; host.onCompositionUpdate(text.value); + if (inComposition.lastValue) + host.undo(); + inComposition.lastValue = text.value.replace(/\x01/g, "") + if (inComposition.lastValue) { + var r = host.selection.getRange(); + host.insert(inComposition.lastValue); + host.session.markUndoGroup(); + inComposition.range = host.selection.getRange(); + host.selection.setRange(r); + host.selection.clearSelection(); + } + }; + + var onCompositionEnd = function(e) { + var c = inComposition; + inComposition = false; + inputHandler = function compositionInputHandler(str) { + str = str.replace(/\x01/g, ""); + if (str == c.lastValue) + return ""; + if (!str) { + if (c.lastValue) + host.undo(); + } + return str; + } + host.onCompositionEnd(); + host.removeListener("mousedown", onCompositionEnd); + if (e.type == "compositionend") { + host.selection.setRange(c.range); + } }; - var onCompositionEnd = function(e) { - inCompostion = false; - host.onCompositionEnd(); - }; + var syncComposition = lang.delayedCall(onCompositionUpdate, 50); diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index a76ec222..f15afb3d 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -538,13 +538,16 @@ var VirtualRenderer = function(container, theme) { var posLeft = this.$cursorLayer.$pixelPos.left; posTop -= config.offset; - if (posTop < 0 || posTop > config.height - this.lineHeight) + var h = this.lineHeight; + if (posTop < 0 || posTop > config.height - h) return; var w = this.characterWidth; if (this.$composition) { var val = this.textarea.value.replace(/^\x01+/, ""); w *= this.session.$getStringScreenWidth(val)[0]; + h += 2; + posTop -= 1; } posLeft -= this.scrollLeft; if (posLeft > this.$size.scrollerWidth - w) @@ -552,10 +555,10 @@ var VirtualRenderer = function(container, theme) { posLeft -= this.scrollBar.width; - this.textarea.style.height = this.lineHeight + "px"; + this.textarea.style.height = h + "px"; this.textarea.style.width = w + "px"; this.textarea.style.right = Math.max(0, this.$size.scrollerWidth - posLeft - w) + "px"; - this.textarea.style.bottom = Math.max(0, this.$size.height - posTop - this.lineHeight) + "px"; + this.textarea.style.bottom = Math.max(0, this.$size.height - posTop - h) + "px"; }; /**