[Libreoffice-commits] online.git: 2 commits - kit/ChildSession.cpp loleaflet/src

Pranav Kant pranavk at collabora.co.uk
Wed Feb 14 18:21:45 UTC 2018


 kit/ChildSession.cpp                       |   12 ++-
 loleaflet/src/control/Control.LokDialog.js |   93 +++++++++++++++++++++++------
 loleaflet/src/layer/tile/TileLayer.js      |    5 +
 loleaflet/src/map/handler/Map.Keyboard.js  |   33 +++++-----
 4 files changed, 107 insertions(+), 36 deletions(-)

New commits:
commit 199b582e06a3234a1803553bf5be88c4d462ffc6
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Wed Feb 14 18:11:31 2018 +0530

    Use real input element for user input instead of canvas
    
    This allows moving the IME candidate window according to where the
    cursor in the lok dialog is.
    
    Change-Id: Icf17f1fc1d3f6af619c8e0037c32109d2b4721fc

diff --git a/loleaflet/src/control/Control.LokDialog.js b/loleaflet/src/control/Control.LokDialog.js
index e6c92e77..20fe4b74 100644
--- a/loleaflet/src/control/Control.LokDialog.js
+++ b/loleaflet/src/control/Control.LokDialog.js
@@ -2,7 +2,7 @@
  * L.Control.LokDialog used for displaying LOK dialogs
  */
 
-/* global $ map */
+/* global $ map L */
 L.Control.LokDialog = L.Control.extend({
 
 	dialogIdPrefix: 'lokdialog-',
@@ -145,12 +145,7 @@ L.Control.LokDialog = L.Control.extend({
 				var y = parseInt(rectangle[1]);
 				height = parseInt(rectangle[3]);
 
-				var dialogCursor = L.DomUtil.get(strDlgId + '-cursor');
-				L.DomUtil.setStyle(dialogCursor, 'height', height + 'px');
-				L.DomUtil.setStyle(dialogCursor, 'display', this._dialogs[e.id].cursorVisible ? 'block' : 'none');
-				// set the position of the cursor container element
-				L.DomUtil.setStyle(this._dialogs[e.id].cursor, 'left', x + 'px');
-				L.DomUtil.setStyle(this._dialogs[e.id].cursor, 'top', y + 'px');
+				this._updateDialogCursor(e.id, x, y, height);
 			}
 		} else if (e.action === 'title_changed') {
 			if (e.title && this._dialogs[parseInt(e.id)]) {
@@ -176,7 +171,20 @@ L.Control.LokDialog = L.Control.extend({
 		this._map.sendUnoCommand(e.uno);
 	},
 
-	_launchDialogCursor: function(dialogId) {
+	_updateDialogCursor: function(dlgId, x, y, height) {
+		var strDlgId = this._toDlgPrefix(dlgId);
+		var dialogCursor = L.DomUtil.get(strDlgId + '-cursor');
+		L.DomUtil.setStyle(dialogCursor, 'height', height + 'px');
+		L.DomUtil.setStyle(dialogCursor, 'display', this._dialogs[dlgId].cursorVisible ? 'block' : 'none');
+		// set the position of the cursor container element
+		L.DomUtil.setStyle(this._dialogs[dlgId].cursor, 'left', x + 'px');
+		L.DomUtil.setStyle(this._dialogs[dlgId].cursor, 'top', y + 'px');
+
+		// update the input as well
+		this._updateDialogInput(dlgId);
+	},
+
+	_createDialogCursor: function(dialogId) {
 		var id = this._toRawDlgId(dialogId);
 		this._dialogs[id].cursor = L.DomUtil.create('div', 'leaflet-cursor-container', L.DomUtil.get(dialogId));
 		var cursor = L.DomUtil.create('div', 'leaflet-cursor lokdialog-cursor', this._dialogs[id].cursor);
@@ -184,6 +192,39 @@ L.Control.LokDialog = L.Control.extend({
 		L.DomUtil.addClass(cursor, 'blinking-cursor');
 	},
 
+	_createDialogInput: function(dialogId) {
+		var id = this._toRawDlgId(dialogId);
+		var clipDlgContainer = L.DomUtil.create('div', 'clipboard-container', L.DomUtil.get(dialogId));
+		clipDlgContainer.id = dialogId + '-clipboard-container';
+		var dlgTextArea = L.DomUtil.create('input', 'clipboard', clipDlgContainer);
+		dlgTextArea.setAttribute('type', 'text');
+		dlgTextArea.setAttribute('autocorrect', 'off');
+		dlgTextArea.setAttribute('autocapitalize', 'off');
+		dlgTextArea.setAttribute('autocomplete', 'off');
+		dlgTextArea.setAttribute('spellcheck', 'false');
+		this._dialogs[id].input = dlgTextArea;
+
+		return dlgTextArea;
+	},
+
+	_updateDialogInput: function(dlgId) {
+		if (!this._dialogs[dlgId].input)
+			return;
+
+		var strDlgId = this._toDlgPrefix(dlgId);
+		var left = parseInt(L.DomUtil.getStyle(this._dialogs[dlgId].cursor, 'left'));
+		var top = parseInt(L.DomUtil.getStyle(this._dialogs[dlgId].cursor, 'top'));
+		var dlgContainer = L.DomUtil.get(strDlgId + '-clipboard-container');
+		L.DomUtil.setPosition(dlgContainer, new L.Point(left, top));
+	},
+
+	focus: function(dlgId) {
+		if (!this._isOpen(dlgId) || !this._dialogs[dlgId].input)
+			return;
+
+		this._dialogs[dlgId].input.focus();
+	},
+
 	_launchDialog: function(strDlgId, width, height, title) {
 		var dialogContainer = L.DomUtil.create('div', 'lokdialog', document.body);
 		L.DomUtil.setStyle(dialogContainer, 'padding', '0px');
@@ -194,8 +235,6 @@ L.Control.LokDialog = L.Control.extend({
 		var dialogCanvas = L.DomUtil.create('canvas', 'lokdialog_canvas', dialogContainer);
 		dialogCanvas.width = width;
 		dialogCanvas.height = height;
-		dialogCanvas.tabIndex = '0';
-		dialogCanvas.contentEditable = true;
 		dialogCanvas.id = strDlgId + '-canvas';
 
 		L.DomEvent.on(dialogCanvas, 'contextmenu', L.DomEvent.preventDefault);
@@ -225,31 +264,38 @@ L.Control.LokDialog = L.Control.extend({
 		// don't make 'TAB' focus on this button; we want to cycle focus in the lok dialog with each TAB
 		$('.lokdialog_container button.ui-dialog-titlebar-close').attr('tabindex', '-1').blur();
 
+		this._createDialogCursor(strDlgId);
+		var dlgInput = this._createDialogInput(strDlgId);
+
 		L.DomEvent.on(dialogCanvas, 'mousedown mouseup', function(e) {
 			var buttons = 0;
 			buttons |= e.button === map['mouse'].JSButtons.left ? map['mouse'].LOButtons.left : 0;
 			buttons |= e.button === map['mouse'].JSButtons.middle ? map['mouse'].LOButtons.middle : 0;
 			buttons |= e.button === map['mouse'].JSButtons.right ? map['mouse'].LOButtons.right : 0;
+			// 'mousedown' -> 'buttondown'
 			var lokEventType = e.type.replace('mouse', 'button');
 			this._postWindowMouseEvent(lokEventType, this._toRawDlgId(strDlgId), e.offsetX, e.offsetY, 1, buttons, 0);
+			dlgInput.focus();
 		}, this);
-		L.DomEvent.on(dialogCanvas,
-		              'keyup keypress keydown compositionstart compositionupdate compositionend',
+		L.DomEvent.on(dlgInput,
+		              'keyup keypress keydown compositionstart compositionupdate compositionend textInput',
 		              function(e) {
 			              e.originalEvent = e; // _onKeyDown fn below requires real event in e.originalEvent
-			              var fn = this._postWindowKeyboardEvent;
-			              if (e.type.startsWith('composition')) {
-				              fn = this._postWindowCompositionEvent;
-			              }
-			              map['keyboard']._onKeyDown(e, L.bind(fn,
-			                                                   this,
-			                                                   this._toRawDlgId(strDlgId)));
+			              map['keyboard']._onKeyDown(e,
+			                                         L.bind(this._postWindowKeyboardEvent,
+			                                                this,
+			                                                this._toRawDlgId(strDlgId)),
+			                                         L.bind(this._postWindowCompositionEvent,
+			                                                this,
+			                                                this._toRawDlgId(strDlgId)),
+			                                         dlgInput);
+
+			              // keep map active while user is playing with dialog
+			              this._map.lastActiveTime = Date.now();
 		              }, this);
-		L.DomEvent.on(dialogCanvas, 'contextmenu', function() {
+		L.DomEvent.on(dlgInput, 'contextmenu', function() {
 			return false;
 		});
-
-		this._launchDialogCursor(strDlgId);
 	},
 
 	_postWindowCompositionEvent: function(winid, type, text) {
@@ -283,6 +329,7 @@ L.Control.LokDialog = L.Control.extend({
 		var img = new Image();
 		var canvas = document.getElementById(strDlgId + '-canvas');
 		var ctx = canvas.getContext('2d');
+		var that = this;
 		img.onload = function() {
 			var x = 0;
 			var y = 0;
@@ -297,6 +344,7 @@ L.Control.LokDialog = L.Control.extend({
 			// if dialog is hidden, show it
 			var dialogContainer = L.DomUtil.get(strDlgId);
 			$(dialogContainer).parent().show();
+			that.focus(dialogId);
 		};
 		img.src = imgData;
 	},
diff --git a/loleaflet/src/map/handler/Map.Keyboard.js b/loleaflet/src/map/handler/Map.Keyboard.js
index 7080751d..5f63b447 100644
--- a/loleaflet/src/map/handler/Map.Keyboard.js
+++ b/loleaflet/src/map/handler/Map.Keyboard.js
@@ -239,7 +239,7 @@ L.Map.Keyboard = L.Handler.extend({
 		return this.keymap[keyCode] || keyCode;
 	},
 
-	_onKeyDown: function (e, keyEventFn, compEventFn) {
+	_onKeyDown: function (e, keyEventFn, compEventFn, inputEle) {
 		if (this._map.slideShow && this._map.slideShow.fullscreen) {
 			return;
 		}
@@ -252,6 +252,9 @@ L.Map.Keyboard = L.Handler.extend({
 			// document has winid=0
 			compEventFn = L.bind(docLayer._postCompositionEvent, docLayer, 0 /* winid */);
 		}
+		if (!inputEle) {
+			inputEle = this._map._textArea;
+		}
 		this.modifier = 0;
 		var shift = e.originalEvent.shiftKey ? this.keyModifier.shift : 0;
 		var ctrl = e.originalEvent.ctrlKey ? this.keyModifier.ctrl : 0;
@@ -310,13 +313,13 @@ L.Map.Keyboard = L.Handler.extend({
 			// get the composited char codes
 			// clear the input now - best to do this ASAP so the input
 			// is clear for the next word
-			this._map._textArea.value = '';
+			inputEle.value = '';
 		}
 
 		if (!this._isComposing && e.type === 'keyup') {
 			// not compositing and keyup, clear the input so it is ready
 			// for next word (or char only)
-			this._map._textArea.value = '';
+			inputEle.value = '';
 		}
 
 		var unoKeyCode = this._toUNOKeyCode(keyCode);
commit 6d4f02ac2aff539132e66bce237ed4b6c20cc43f
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Tue Feb 13 23:05:54 2018 +0530

    Adapt to IME API changes; better reuse of Map's key handler
    
    Change-Id: I670243ea155ac698c694531d3fc16a574f418bf4

diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp
index c002e5e3..ef9bfd3d 100644
--- a/kit/ChildSession.cpp
+++ b/kit/ChildSession.cpp
@@ -771,13 +771,15 @@ bool ChildSession::insertFile(const char* /*buffer*/, int /*length*/, const std:
 bool ChildSession::extTextInputEvent(const char* /*buffer*/, int /*length*/,
                                      const std::vector<std::string>& tokens)
 {
-    int type;
+    int id, type;
     std::string text;
-    if (tokens.size() < 3 ||
-        !getTokenKeyword(tokens[1], "type",
+    if (tokens.size() < 4 ||
+        !getTokenInteger(tokens[1], "id", id) || id < 0 ||
+        !getTokenKeyword(tokens[2], "type",
                         {{"input", LOK_EXT_TEXTINPUT}, {"end", LOK_EXT_TEXTINPUT_END}},
                          type) ||
-        !getTokenString(tokens[2], "text", text))
+        !getTokenString(tokens[3], "text", text))
+
     {
         sendTextFrame("error: cmd=" + std::string(tokens[0]) + " kind=syntax");
         return false;
@@ -785,7 +787,7 @@ bool ChildSession::extTextInputEvent(const char* /*buffer*/, int /*length*/,
 
     std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
     getLOKitDocument()->setView(_viewId);
-    getLOKitDocument()->postExtTextInputEvent(type, text.c_str());
+    getLOKitDocument()->postExtTextInputEvent(id, type, text.c_str());
 
     return true;
 }
diff --git a/loleaflet/src/control/Control.LokDialog.js b/loleaflet/src/control/Control.LokDialog.js
index 7086fcac..e6c92e77 100644
--- a/loleaflet/src/control/Control.LokDialog.js
+++ b/loleaflet/src/control/Control.LokDialog.js
@@ -233,11 +233,18 @@ L.Control.LokDialog = L.Control.extend({
 			var lokEventType = e.type.replace('mouse', 'button');
 			this._postWindowMouseEvent(lokEventType, this._toRawDlgId(strDlgId), e.offsetX, e.offsetY, 1, buttons, 0);
 		}, this);
-		L.DomEvent.on(dialogCanvas, 'keyup keypress keydown', function(e) {
-			// _onKeyDown fn below requires this kind of structure but leaflet DomEvent.on doesn't pass it
-			e.originalEvent = e;
-			map['keyboard']._onKeyDown(e, L.bind(this._postWindowKeyboardEvent, this, this._toRawDlgId(strDlgId)));
-		}, this);
+		L.DomEvent.on(dialogCanvas,
+		              'keyup keypress keydown compositionstart compositionupdate compositionend',
+		              function(e) {
+			              e.originalEvent = e; // _onKeyDown fn below requires real event in e.originalEvent
+			              var fn = this._postWindowKeyboardEvent;
+			              if (e.type.startsWith('composition')) {
+				              fn = this._postWindowCompositionEvent;
+			              }
+			              map['keyboard']._onKeyDown(e, L.bind(fn,
+			                                                   this,
+			                                                   this._toRawDlgId(strDlgId)));
+		              }, this);
 		L.DomEvent.on(dialogCanvas, 'contextmenu', function() {
 			return false;
 		});
@@ -245,6 +252,10 @@ L.Control.LokDialog = L.Control.extend({
 		this._launchDialogCursor(strDlgId);
 	},
 
+	_postWindowCompositionEvent: function(winid, type, text) {
+		this._map._docLayer._postCompositionEvent(winid, type, text);
+	},
+
 	_postWindowMouseEvent: function(type, winid, x, y, count, buttons, modifier) {
 		this._map._socket.sendMessage('windowmouse id=' + winid +  ' type=' + type +
 		                              ' x=' + x + ' y=' + y + ' count=' + count +
diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index aebeaf79..93ac3cd7 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -1468,6 +1468,11 @@ L.TileLayer = L.GridLayer.extend({
 				' char=' + charcode + ' key=' + keycode);
 	},
 
+	// if winId=0, then event is posted on the document
+	_postCompositionEvent: function(winId, type, text) {
+		this._map._socket.sendMessage('textinput id=' + winId + ' type=' + type + ' text=' + text);
+	},
+
 	_postSelectGraphicEvent: function(type, x, y) {
 		this._map._socket.sendMessage('selectgraphic type=' + type +
 				' x=' + x + ' y=' + y);
diff --git a/loleaflet/src/map/handler/Map.Keyboard.js b/loleaflet/src/map/handler/Map.Keyboard.js
index 39103dd3..7080751d 100644
--- a/loleaflet/src/map/handler/Map.Keyboard.js
+++ b/loleaflet/src/map/handler/Map.Keyboard.js
@@ -239,16 +239,18 @@ L.Map.Keyboard = L.Handler.extend({
 		return this.keymap[keyCode] || keyCode;
 	},
 
-	_onKeyDown: function (e, postEventFn) {
+	_onKeyDown: function (e, keyEventFn, compEventFn) {
 		if (this._map.slideShow && this._map.slideShow.fullscreen) {
 			return;
 		}
 		var docLayer = this._map._docLayer;
-		var eventObject;
-		if (!postEventFn) {
+		if (!keyEventFn) {
 			// default is to post keyboard events on the document
-			postEventFn = docLayer._postKeyboardEvent;
-			eventObject = docLayer;
+			keyEventFn = L.bind(docLayer._postKeyboardEvent, docLayer);
+		}
+		if (!compEventFn) {
+			// document has winid=0
+			compEventFn = L.bind(docLayer._postCompositionEvent, docLayer, 0 /* winid */);
 		}
 		this.modifier = 0;
 		var shift = e.originalEvent.shiftKey ? this.keyModifier.shift : 0;
@@ -299,7 +301,7 @@ L.Map.Keyboard = L.Handler.extend({
 				txt += e.originalEvent.data[i];
 			}
 			if (txt) {
-				this._map._socket.sendMessage('textinput type=input text=' + txt);
+				compEventFn('input', txt);
 			}
 		}
 
@@ -322,7 +324,7 @@ L.Map.Keyboard = L.Handler.extend({
 		if (this.modifier) {
 			unoKeyCode |= this.modifier;
 			if (e.type !== 'keyup' && (this.modifier !== shift || (keyCode === 32 && !docLayer._isCursorVisible))) {
-				postEventFn.call(eventObject, 'input', charCode, unoKeyCode);
+				keyEventFn('input', charCode, unoKeyCode);
 				e.originalEvent.preventDefault();
 				return;
 			}
@@ -336,7 +338,7 @@ L.Map.Keyboard = L.Handler.extend({
 				this._bufferedTextInputEvent = null;
 
 				if (this._handleOnKeyDown(keyCode, this.modifier) && charCode === 0) {
-					postEventFn.call(eventObject, 'input', charCode, unoKeyCode);
+					keyEventFn('input', charCode, unoKeyCode);
 				}
 			}
 			else if ((e.type === 'keypress' || e.type === 'compositionend') &&
@@ -353,9 +355,9 @@ L.Map.Keyboard = L.Handler.extend({
 				}
 				if (e.type === 'compositionend') {
 					// Set all keycodes to zero
-					this._map._socket.sendMessage('textinput type=end text=void');
+					compEventFn('end', '');
 				} else {
-					postEventFn.call(eventObject, 'input', charCode, unoKeyCode);
+					keyEventFn('input', charCode, unoKeyCode);
 				}
 
 				this._keyHandled = true;
@@ -388,7 +390,7 @@ L.Map.Keyboard = L.Handler.extend({
 						keyEventFn('input', textInputData[idx].charCodeAt(), 0);
 					}
 				}
-				postEventFn.call(eventObject, 'up', charCode, unoKeyCode);
+				keyEventFn('up', charCode, unoKeyCode);
 
 				this._keyHandled = true;
 				this._bufferedTextInputEvent = null;
@@ -414,7 +416,7 @@ L.Map.Keyboard = L.Handler.extend({
 			else if (key in this._panKeys && e.originalEvent.shiftKey &&
 					docLayer._selections.getLayers().length !== 0) {
 				// if there is a selection and the user wants to modify it
-				postEventFn.call(eventObject, 'input', charCode, unoKeyCode);
+				keyEventFn('input', charCode, unoKeyCode);
 			}
 			else if (key in this._zoomKeys) {
 				map.setZoom(map.getZoom() + (e.shiftKey ? 3 : 1) * this._zoomKeys[key]);


More information about the Libreoffice-commits mailing list