From 5bf0ccc4f182e2c586b16d63f9f4737880f8fba0 Mon Sep 17 00:00:00 2001 From: abakkk Date: Thu, 25 Jun 2020 11:41:15 +0200 Subject: [PATCH] Use a St.Entry for text tool. All key events go through a hidden St Entry. * Ibus inputs support. * GS keyboard support, by moving the keyboard box above the drawing area. * All convenience keybindings of a St Entry (cursor moves, delete, paste, select all ...). * Add a writing action mode so some keybindings are disabled when writing (e.g. `Delete` and `Ctrl + A`). * Draw a thin rectangle as text cursor instead of a text character, so moving the cursor is smoother. Close #29, #34 --- draw.js | 206 ++++++++++++++++++++++++++++++++------------------- extension.js | 65 +++++++++++----- 2 files changed, 173 insertions(+), 98 deletions(-) diff --git a/draw.js b/draw.js index e97f4db..a4d79dd 100644 --- a/draw.js +++ b/draw.js @@ -29,7 +29,6 @@ const GObject = imports.gi.GObject; const Gtk = imports.gi.Gtk; const Lang = imports.lang; const PangoMatrix = imports.gi.Pango.Matrix; -const Shell = imports.gi.Shell; const St = imports.gi.St; const BoxPointer = imports.ui.boxpointer; @@ -67,7 +66,6 @@ const FULL_LINE_ICON_PATH = ICON_DIR.get_child('full-line-symbolic.svg').get_pat const Shapes = { NONE: 0, LINE: 1, ELLIPSE: 2, RECTANGLE: 3, TEXT: 4, POLYGON: 5, POLYLINE: 6 }; const Manipulations = { MOVE: 100, RESIZE: 101, MIRROR: 102 }; var Tools = Object.assign({}, Shapes, Manipulations); -const TextStates = { WRITTEN: 0, DRAWING: 1, WRITING: 2 }; const Transformations = { TRANSLATION: 0, ROTATION: 1, SCALE_PRESERVE: 2, STRETCH: 3, REFLECTION: 4, INVERSION: 5 }; const ToolNames = { 0: "Free drawing", 1: "Line", 2: "Ellipse", 3: "Rectangle", 4: "Text", 5: "Polygon", 6: "Polyline", 100: "Move", 101: "Resize", 102: "Mirror" }; const LineCapNames = { 0: 'Butt', 1: 'Round', 2: 'Square' }; @@ -121,6 +119,7 @@ var DrawingArea = new Lang.Class({ Name: 'DrawOnYourScreenDrawingArea', Extends: St.DrawingArea, Signals: { 'show-osd': { param_types: [GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_DOUBLE] }, + 'update-action-mode': {}, 'leave-drawing-mode': {} }, _init: function(params, monitor, helper, loadPersistent) { @@ -163,6 +162,10 @@ var DrawingArea = new Lang.Class({ this._menu.close(); }, + get isWriting() { + return this.textEntry ? true : false; + }, + get currentTool() { return this._currentTool; }, @@ -259,7 +262,7 @@ var DrawingArea = new Lang.Class({ if (this.currentElement) { cr.save(); this.currentElement.buildCairo(cr, { showTextCursor: this.textHasCursor, - showTextRectangle: this.currentElement.shape == Shapes.TEXT && this.currentElement.textState == TextStates.DRAWING, + showTextRectangle: this.currentElement.shape == Shapes.TEXT && !this.isWriting, dummyStroke: this.currentElement.fill && this.currentElement.line.lineWidth == 0 }); cr.stroke(); @@ -300,14 +303,13 @@ var DrawingArea = new Lang.Class({ let controlPressed = event.has_control_modifier(); let shiftPressed = event.has_shift_modifier(); - if (this.currentElement && this.currentElement.shape == Shapes.TEXT && this.currentElement.textState == TextStates.WRITING) { + if (this.currentElement && this.currentElement.shape == Shapes.TEXT && this.isWriting) // finish writing this._stopWriting(); - } if (this.helper.visible) { // hide helper - this.helper.hideHelp(); + this.toggleHelp(); return Clutter.EVENT_STOP; } @@ -333,7 +335,7 @@ var DrawingArea = new Lang.Class({ _onKeyboardPopupMenu: function() { this._stopDrawing(); if (this.helper.visible) - this.helper.hideHelp(); + this.toggleHelp(); this.menu.popup(); return Clutter.EVENT_STOP; }, @@ -353,39 +355,10 @@ var DrawingArea = new Lang.Class({ }, _onKeyPressed: function(actor, event) { - let [keySymbol, ctrlPressed] = [event.get_key_symbol(), event.has_control_modifier()]; - - if (this.currentElement && this.currentElement.shape == Shapes.TEXT && this.currentElement.textState == TextStates.WRITING) { - if (keySymbol == Clutter.KEY_Escape) { - // finish writing - this._stopWriting(); - } else if (keySymbol == Clutter.KEY_BackSpace) { - this.currentElement.text = this.currentElement.text.slice(0, -1); - this._updateTextCursorTimeout(); - } else if (ctrlPressed && keySymbol == Clutter.KEY_v) { - // Ctrl + V - St.Clipboard.get_default().get_text(St.ClipboardType.CLIPBOARD, (clipBoard, clipText) => { - this.currentElement.text += clipText; - this._updateTextCursorTimeout(); - this._redisplay(); - }); - } else if (keySymbol == Clutter.KEY_Return || keySymbol == Clutter.KEY_KP_Enter) { - // start a new line - let startNewLine = true; - this._stopWriting(startNewLine); - } else if (ctrlPressed){ - // it is a shortcut, do not write text - return Clutter.EVENT_PROPAGATE; - } else { - let unicode = event.get_key_unicode(); - this.currentElement.text += unicode; - this._updateTextCursorTimeout(); - } - this._redisplay(); - return Clutter.EVENT_STOP; - - } else if (this.currentElement && this.currentElement.shape == Shapes.LINE) { - if (keySymbol == Clutter.KEY_Return || keySymbol == Clutter.KEY_KP_Enter || keySymbol == Clutter.KEY_Control_L) { + if (this.currentElement && this.currentElement.shape == Shapes.LINE) { + if (event.get_key_symbol() == Clutter.KEY_Return || + event.get_key_symbol() == Clutter.KEY_KP_Enter || + event.get_key_symbol() == Clutter.KEY_Control_L) { if (this.currentElement.points.length == 2) this.emit('show-osd', null, _("Press %s to get a fourth control point") .format(Gtk.accelerator_get_label(Clutter.KEY_Return, 0)), "", -1); @@ -399,13 +372,13 @@ var DrawingArea = new Lang.Class({ } else if (this.currentElement && (this.currentElement.shape == Shapes.POLYGON || this.currentElement.shape == Shapes.POLYLINE) && - (keySymbol == Clutter.KEY_Return || keySymbol == Clutter.KEY_KP_Enter)) { + (event.get_key_symbol() == Clutter.KEY_Return || event.get_key_symbol() == Clutter.KEY_KP_Enter)) { this.currentElement.addPoint(); return Clutter.EVENT_STOP; - } else if (keySymbol == Clutter.KEY_Escape) { + } else if (event.get_key_symbol() == Clutter.KEY_Escape) { if (this.helper.visible) - this.helper.hideHelp(); + this.toggleHelp(); else this.emit('leave-drawing-mode'); return Clutter.EVENT_STOP; @@ -594,7 +567,6 @@ var DrawingArea = new Lang.Class({ if (this.currentTool == Shapes.TEXT) { this.currentElement.fill = false; this.currentElement.text = _("Text"); - this.currentElement.textState = TextStates.DRAWING; this.currentElement.rtl = ENABLE_RTL && this.get_text_direction() == Clutter.TextDirection.RTL; } @@ -644,15 +616,8 @@ var DrawingArea = new Lang.Class({ this.currentElement.stopDrawing(); if (this.currentElement && this.currentElement.points.length >= 2) { - if (this.currentElement.shape == Shapes.TEXT && this.currentElement.textState == TextStates.DRAWING) { - // start writing - this.currentElement.textState = TextStates.WRITING; - this.currentElement.text = ''; - this.emit('show-osd', null, _("Type your text and press %s").format(Gtk.accelerator_get_label(Clutter.KEY_Escape, 0)), "", -1); - this._updateTextCursorTimeout(); - this.textHasCursor = true; - this._redisplay(); - this.updatePointerCursor(); + if (this.currentElement.shape == Shapes.TEXT && !this.isWriting) { + this._startWriting(); return; } @@ -664,16 +629,65 @@ var DrawingArea = new Lang.Class({ this.updatePointerCursor(); }, - _stopWriting: function(startNewLine) { - this.currentElement.textState = TextStates.WRITTEN; + _startWriting: function() { + this.currentElement.text = ''; + this.currentElement.cursorPosition = 0; + this.emit('show-osd', null, _("Type your text and press %s").format(Gtk.accelerator_get_label(Clutter.KEY_Escape, 0)), "", -1); + this._updateTextCursorTimeout(); + this.textHasCursor = true; + this._redisplay(); + this.updatePointerCursor(); + this.textEntry = new St.Entry({ visible: false }); + this.get_parent().add_child(this.textEntry); + this.textEntry.grab_key_focus(); + this.updateActionMode(); + + this.textEntry.clutterText.connect('activate', (clutterText) => { + let startNewLine = true; + this._stopWriting(startNewLine); + clutterText.text = ""; + }); + + this.textEntry.clutterText.connect('text-changed', (clutterText) => { + GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { + this.currentElement.text = clutterText.text; + this.currentElement.cursorPosition = clutterText.cursorPosition; + this._updateTextCursorTimeout(); + this._redisplay(); + }); + }); + + this.textEntry.clutterText.connect('key-press-event', (clutterText, event) => { + if (event.get_key_symbol() == Clutter.KEY_Escape) { + this._stopWriting(); + return Clutter.EVENT_STOP; + } + + // 'cursor-changed' signal is not emitted if the text entry is not visible. + // So key events related to the cursor must be listened. + if (event.get_key_symbol() == Clutter.KEY_Left || event.get_key_symbol() == Clutter.KEY_Right || + event.get_key_symbol() == Clutter.KEY_Home || event.get_key_symbol() == Clutter.KEY_End) { + GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { + this.currentElement.cursorPosition = clutterText.cursorPosition; + this._updateTextCursorTimeout(); + this.textHasCursor = true; + this._redisplay(); + }); + } + + return Clutter.EVENT_PROPAGATE; + }); + }, + + _stopWriting: function(startNewLine) { if (this.currentElement.text.length > 0) this.elements.push(this.currentElement); + if (startNewLine && this.currentElement.points.length == 2) { this.currentElement.lineIndex = this.currentElement.lineIndex || 0; // copy object, the original keep existing in this.elements this.currentElement = Object.create(this.currentElement); - this.currentElement.textState = TextStates.WRITING; this.currentElement.lineIndex ++; let height = Math.abs(this.currentElement.points[1][1] - this.currentElement.points[0][1]); // define a new 'points' array, the original keep existing in this.elements @@ -685,7 +699,12 @@ var DrawingArea = new Lang.Class({ } else { this.currentElement = null; this._stopTextCursorTimeout(); + this.textEntry.destroy(); + delete this.textEntry; + this.grab_key_focus(); + this.updateActionMode(); } + this._redisplay(); }, @@ -701,7 +720,7 @@ var DrawingArea = new Lang.Class({ this.setPointerCursor('CROSSHAIR'); else if (Object.values(Manipulations).indexOf(this.currentTool) != -1) this.setPointerCursor(this.grabbedElement ? 'MOVE_OR_RESIZE_WINDOW' : 'DEFAULT'); - else if (!this.currentElement || (this.currentElement.shape == Shapes.TEXT && this.currentElement.textState == TextStates.WRITING)) + else if (!this.currentElement || (this.currentElement.shape == Shapes.TEXT && this.isWriting)) this.setPointerCursor(this.currentTool == Shapes.NONE ? 'POINTING_HAND' : 'CROSSHAIR'); else if (this.currentElement.shape != Shapes.NONE && controlPressed) this.setPointerCursor('MOVE_OR_RESIZE_WINDOW'); @@ -730,9 +749,9 @@ var DrawingArea = new Lang.Class({ }, erase: function() { + this.deleteLastElement(); this.elements = []; this.undoneElements = []; - this.currentElement = null; this._redisplay(); }, @@ -746,8 +765,9 @@ var DrawingArea = new Lang.Class({ this.disconnect(this.buttonReleasedHandler); this.buttonReleasedHandler = null; } + if (this.isWriting) + this._stopWriting(); this.currentElement = null; - this._stopTextCursorTimeout(); } else { this.elements.pop(); } @@ -877,10 +897,15 @@ var DrawingArea = new Lang.Class({ }, toggleHelp: function() { - if (this.helper.visible) + if (this.helper.visible) { this.helper.hideHelp(); - else + if (this.textEntry) + this.textEntry.grab_key_focus(); + } else { this.helper.showHelp(); + this.grab_key_focus(); + } + }, // The area is reactive when it is modal. @@ -888,7 +913,9 @@ var DrawingArea = new Lang.Class({ if (this.hasGrid) this._redisplay(); if (this.helper.visible) - this.helper.hideHelp(); + this.toggleHelp(); + if (this.textEntry && this.reactive) + this.textEntry.grab_key_focus(); }, _onDestroy: function() { @@ -898,6 +925,10 @@ var DrawingArea = new Lang.Class({ this._menu.disable(); }, + updateActionMode: function() { + this.emit('update-action-mode'); + }, + enterDrawingMode: function() { this.stageKeyPressedHandler = global.stage.connect('key-press-event', this._onStageKeyPressed.bind(this)); this.stageKeyReleasedHandler = global.stage.connect('key-release-event', this._onStageKeyReleased.bind(this)); @@ -958,7 +989,7 @@ var DrawingArea = new Lang.Class({ saveAsSvg: function() { // stop drawing or writing - if (this.currentElement && this.currentElement.shape == Shapes.TEXT && this.currentElement.textState == TextStates.WRITING) { + if (this.currentElement && this.currentElement.shape == Shapes.TEXT && this.isWriting) { this._stopWriting(); } else if (this.currentElement && this.currentElement.shape != Shapes.TEXT) { this._stopDrawing(); @@ -1002,7 +1033,7 @@ var DrawingArea = new Lang.Class({ _saveAsJson: function(name, notify) { // stop drawing or writing - if (this.currentElement && this.currentElement.shape == Shapes.TEXT && this.currentElement.textState == TextStates.WRITING) { + if (this.currentElement && this.currentElement.shape == Shapes.TEXT && this.isWriting) { this._stopWriting(); } else if (this.currentElement && this.currentElement.shape != Shapes.TEXT) { this._stopDrawing(); @@ -1067,6 +1098,15 @@ var DrawingArea = new Lang.Class({ }, _loadJson: function(name, notify) { + // stop drawing or writing + if (this.currentElement && this.currentElement.shape == Shapes.TEXT && this.isWriting) { + this._stopWriting(); + } else if (this.currentElement && this.currentElement.shape != Shapes.TEXT) { + this._stopDrawing(); + } + this.elements = []; + this.currentElement = null; + let dir = GLib.get_user_data_dir(); let path = GLib.build_filenamev([dir, Me.metadata['data-dir'], `${name}.json`]); @@ -1092,9 +1132,6 @@ var DrawingArea = new Lang.Class({ }, loadJson: function(name, notify) { - this.elements = []; - this.currentElement = null; - this._stopTextCursorTimeout(); this._loadJson(name, notify); this._redisplay(); }, @@ -1294,27 +1331,40 @@ const DrawingElement = new Lang.Class({ cr.selectFontFace(this.font.family, this.font.style, this.font.weight); cr.setFontSize(Math.abs(points[1][1] - points[0][1])); - let textWidth; + let textWidth = 0; + if (this.rtl) { - cr.save() + cr.save(); cr.setSourceRGBA(0, 0, 0, 0); + cr.setOperator(Cairo.Operator.OVER); cr.moveTo(points[1][0], Math.max(points[0][1], points[1][1])); - cr.showText(params.showTextCursor ? ("_" + this.text) : this.text); + cr.showText(this.text); textWidth = cr.getCurrentPoint()[0] - points[1][0]; cr.restore(); + } + + if (params.showTextCursor) { + let cursorPosition = this.cursorPosition == -1 ? this.text.length : this.cursorPosition; + let texts = [this.text.slice(0, cursorPosition), this.text.slice(cursorPosition)]; cr.moveTo(points[1][0] - textWidth, Math.max(points[0][1], points[1][1])); - cr.showText(params.showTextCursor ? ("_" + this.text) : this.text); + cr.showText(texts[0]); + let currentPoint1 = cr.getCurrentPoint(); + cr.rectangle(currentPoint1[0], currentPoint1[1], Math.abs(points[1][1] - points[0][1]) / 25, - Math.abs(points[1][1] - points[0][1])); + cr.fill(); + cr.moveTo(currentPoint1[0], currentPoint1[1]); + cr.showText(texts[1]); + textWidth = this.rtl ? textWidth : (cr.getCurrentPoint()[0] - points[1][0]); } else { - cr.moveTo(points[1][0], Math.max(points[0][1], points[1][1])); - cr.showText(params.showTextCursor ? (this.text + "_") : this.text); - textWidth = cr.getCurrentPoint()[0] - points[1][0]; + cr.moveTo(points[1][0] - textWidth, Math.max(points[0][1], points[1][1])); + cr.showText(this.text); + textWidth = this.rtl ? textWidth : (cr.getCurrentPoint()[0] - points[1][0]); } if (!params.showTextCursor) this.textWidth = textWidth; if (params.showTextRectangle || params.drawTextRectangle) { - cr.rectangle(points[1][0] - this.rtl * textWidth, Math.max(points[0][1], points[1][1]), + cr.rectangle(points[1][0] - (this.rtl ? textWidth : 0), Math.max(points[0][1], points[1][1]), textWidth, - Math.abs(points[1][1] - points[0][1])); if (params.showTextRectangle) setDummyStroke(cr); @@ -2004,7 +2054,7 @@ const DrawingMenu = new Lang.Class({ } else { this.area.updatePointerCursor(); // actionMode has changed, set previous actionMode in order to keep internal shortcuts working - Main.actionMode = Extension.DRAWING_ACTION_MODE | Shell.ActionMode.NORMAL; + this.area.updateActionMode(); this.area.grab_key_focus(); } }, @@ -2273,7 +2323,7 @@ const DrawingMenu = new Lang.Class({ if (!item.menu.isOpen) this._populateOpenDrawingSubMenu(); item.menu.openOld(); - } + }; menu.addMenuItem(item); }, @@ -2326,7 +2376,7 @@ const DrawingMenu = new Lang.Class({ if (!item.menu.isOpen) this._populateSaveDrawingSubMenu(); item.menu.openOld(); - } + }; menu.addMenuItem(item); }, diff --git a/extension.js b/extension.js index 6cb2616..26cefb5 100644 --- a/extension.js +++ b/extension.js @@ -41,8 +41,9 @@ const _ = imports.gettext.domain(Me.metadata['gettext-domain']).gettext; const GS_VERSION = Config.PACKAGE_VERSION; const HIDE_TIMEOUT_LONG = 2500; // ms, default is 1500 ms -// DRAWING_ACTION_MODE is a custom Shell.ActionMode -var DRAWING_ACTION_MODE = Math.pow(2,14); +// custom Shell.ActionMode, assuming that they are unused +const DRAWING_ACTION_MODE = Math.pow(2,14); +const WRITING_ACTION_MODE = Math.pow(2,15); // use 'login-dialog-message-warning' class in order to get GS theme warning color (default: #f57900) var WARNING_COLOR_STYLE_CLASS_NAME = 'login-dialog-message-warning'; @@ -167,24 +168,19 @@ var AreaManager = new Lang.Class({ container.set_size(monitor.width, monitor.height); area.set_size(monitor.width, monitor.height); area.leaveDrawingHandler = area.connect('leave-drawing-mode', this.toggleDrawing.bind(this)); + area.updateActionModeHandler = area.connect('update-action-mode', this.updateActionMode.bind(this)); area.showOsdHandler = area.connect('show-osd', this.showOsd.bind(this)); this.areas.push(area); } }, addInternalKeybindings: function() { - this.internalKeybindings = { + // unavailable when writing + this.internalKeybindings1 = { 'undo': this.activeArea.undo.bind(this.activeArea), 'redo': this.activeArea.redo.bind(this.activeArea), 'delete-last-element': this.activeArea.deleteLastElement.bind(this.activeArea), 'smooth-last-element': this.activeArea.smoothLastElement.bind(this.activeArea), - 'save-as-svg': this.activeArea.saveAsSvg.bind(this.activeArea), - 'save-as-json': this.activeArea.saveAsJson.bind(this.activeArea), - 'open-previous-json': this.activeArea.loadPreviousJson.bind(this.activeArea), - 'open-next-json': this.activeArea.loadNextJson.bind(this.activeArea), - 'toggle-background': this.activeArea.toggleBackground.bind(this.activeArea), - 'toggle-grid': this.activeArea.toggleGrid.bind(this.activeArea), - 'toggle-square-area': this.activeArea.toggleSquareArea.bind(this.activeArea), 'increment-line-width': () => this.activeArea.incrementLineWidth(1), 'decrement-line-width': () => this.activeArea.incrementLineWidth(-1), 'increment-line-width-more': () => this.activeArea.incrementLineWidth(5), @@ -203,7 +199,18 @@ var AreaManager = new Lang.Class({ 'select-polyline-shape': () => this.activeArea.selectTool(Draw.Tools.POLYLINE), 'select-move-tool': () => this.activeArea.selectTool(Draw.Tools.MOVE), 'select-resize-tool': () => this.activeArea.selectTool(Draw.Tools.RESIZE), - 'select-mirror-tool': () => this.activeArea.selectTool(Draw.Tools.MIRROR), + 'select-mirror-tool': () => this.activeArea.selectTool(Draw.Tools.MIRROR) + }; + + // available when writing + this.internalKeybindings2 = { + 'save-as-svg': this.activeArea.saveAsSvg.bind(this.activeArea), + 'save-as-json': this.activeArea.saveAsJson.bind(this.activeArea), + 'open-previous-json': this.activeArea.loadPreviousJson.bind(this.activeArea), + 'open-next-json': this.activeArea.loadNextJson.bind(this.activeArea), + 'toggle-background': this.activeArea.toggleBackground.bind(this.activeArea), + 'toggle-grid': this.activeArea.toggleGrid.bind(this.activeArea), + 'toggle-square-area': this.activeArea.toggleSquareArea.bind(this.activeArea), 'toggle-font-family': this.activeArea.toggleFontFamily.bind(this.activeArea), 'toggle-font-weight': this.activeArea.toggleFontWeight.bind(this.activeArea), 'toggle-font-style': this.activeArea.toggleFontStyle.bind(this.activeArea), @@ -213,12 +220,20 @@ var AreaManager = new Lang.Class({ 'open-preferences': this.openPreferences.bind(this) }; - for (let key in this.internalKeybindings) { + for (let key in this.internalKeybindings1) { Main.wm.addKeybinding(key, this.settings, Meta.KeyBindingFlags.NONE, DRAWING_ACTION_MODE, - this.internalKeybindings[key]); + this.internalKeybindings1[key]); + } + + for (let key in this.internalKeybindings2) { + Main.wm.addKeybinding(key, + this.settings, + Meta.KeyBindingFlags.NONE, + DRAWING_ACTION_MODE | WRITING_ACTION_MODE, + this.internalKeybindings2[key]); } for (let i = 1; i < 10; i++) { @@ -226,19 +241,20 @@ var AreaManager = new Lang.Class({ Main.wm.addKeybinding('select-color' + i, this.settings, Meta.KeyBindingFlags.NONE, - DRAWING_ACTION_MODE, + DRAWING_ACTION_MODE | WRITING_ACTION_MODE, () => this.activeArea.selectColor(iCaptured)); } }, removeInternalKeybindings: function() { - for (let key in this.internalKeybindings) { + for (let key in this.internalKeybindings1) Main.wm.removeKeybinding(key); - } - for (let i = 1; i < 10; i++) { + for (let key in this.internalKeybindings2) + Main.wm.removeKeybinding(key); + + for (let i = 1; i < 10; i++) Main.wm.removeKeybinding('select-color' + i); - } }, openPreferences: function() { @@ -320,6 +336,7 @@ var AreaManager = new Lang.Class({ let activeIndex = this.areas.indexOf(this.activeArea); if (activeContainer.get_parent() == Main.uiGroup) { + Main.uiGroup.set_child_at_index(Main.layoutManager.keyboardBox, this.oldKeyboardIndex); Main.uiGroup.remove_actor(activeContainer); Main.layoutManager._backgroundGroup.insert_child_above(activeContainer, Main.layoutManager._bgManagers[activeIndex].backgroundActor); if (!this.settings.get_boolean("drawing-on-desktop")) @@ -327,6 +344,9 @@ var AreaManager = new Lang.Class({ } else { Main.layoutManager._backgroundGroup.remove_actor(activeContainer); Main.uiGroup.add_child(activeContainer); + // move the keyboard above the area to make it available with text entries + this.oldKeyboardIndex = Main.uiGroup.get_children().indexOf(Main.layoutManager.keyboardBox); + Main.uiGroup.set_child_above_sibling(Main.layoutManager.keyboardBox, activeContainer); } }, @@ -334,7 +354,6 @@ var AreaManager = new Lang.Class({ if (!this.activeArea) return; - // The menu changes Main.actionMode. this.activeArea.closeMenu(); if (Main._findModal(this.activeArea) != -1) { @@ -344,7 +363,8 @@ var AreaManager = new Lang.Class({ this.removeInternalKeybindings(); } else { // add Shell.ActionMode.NORMAL to keep system keybindings enabled (e.g. Alt + F2 ...) - if (!Main.pushModal(this.activeArea, { actionMode: DRAWING_ACTION_MODE | Shell.ActionMode.NORMAL })) + let actionMode = (this.activeArea.isWriting ? WRITING_ACTION_MODE : DRAWING_ACTION_MODE) | Shell.ActionMode.NORMAL; + if (!Main.pushModal(this.activeArea, { actionMode: actionMode })) return false; this.addInternalKeybindings(); this.activeArea.reactive = true; @@ -389,6 +409,10 @@ var AreaManager = new Lang.Class({ this.indicator.sync(Boolean(this.activeArea)); }, + updateActionMode: function() { + Main.actionMode = (this.activeArea.isWriting ? WRITING_ACTION_MODE : DRAWING_ACTION_MODE) | Shell.ActionMode.NORMAL; + }, + // Use level -1 to set no level through a signal. showOsd: function(emitter, icon, label, color, level, long) { let activeIndex = this.areas.indexOf(this.activeArea); @@ -477,6 +501,7 @@ var AreaManager = new Lang.Class({ for (let i = 0; i < this.areas.length; i++) { let area = this.areas[i]; area.disconnect(area.leaveDrawingHandler); + area.disconnect(area.updateActionModeHandler); area.disconnect(area.showOsdHandler); let container = area.get_parent(); container.get_parent().remove_actor(container);