Merge branch 'dev' into 'master'

v9

See merge request abakkk/DrawOnYourScreen!19
This commit is contained in:
abakkk 2020-10-12 11:25:25 +02:00
commit ea11a92689
6 changed files with 189 additions and 128 deletions

6
NEWS
View File

@ -1,3 +1,9 @@
v9 - October 2020
=================
* Split the drawing area in several layers (performance)
* Start a new line with "Shift + Enter" (text tool)
v8.1 - October 2020 v8.1 - October 2020
=================== ===================

256
area.js
View File

@ -45,8 +45,6 @@ const Menu = Me.imports.menu;
const _ = imports.gettext.domain(Me.metadata['gettext-domain']).gettext; const _ = imports.gettext.domain(Me.metadata['gettext-domain']).gettext;
const pgettext = imports.gettext.domain(Me.metadata['gettext-domain']).pgettext; const pgettext = imports.gettext.domain(Me.metadata['gettext-domain']).pgettext;
const CAIRO_DEBUG_EXTENDS = false;
const SVG_DEBUG_EXTENDS = false;
const MOTION_TIME = 1; // ms, time accuracy for free drawing, max is about 33 ms. The lower it is, the smoother the drawing is. const MOTION_TIME = 1; // ms, time accuracy for free drawing, max is about 33 ms. The lower it is, the smoother the drawing is.
const TEXT_CURSOR_TIME = 600; // ms const TEXT_CURSOR_TIME = 600; // ms
const ELEMENT_GRABBER_TIME = 80; // ms, default is about 16 ms const ELEMENT_GRABBER_TIME = 80; // ms, default is about 16 ms
@ -83,12 +81,47 @@ const getColorFromString = function(string, fallback) {
return color; return color;
}; };
// DrawingArea is the widget in which we draw, thanks to Cairo. // Drawing layers are the proper drawing area widgets (painted thanks to Cairo).
// It creates and manages a DrawingElement for each "brushstroke". const DrawingLayer = new Lang.Class({
Name: `${UUID}-DrawingLayer`,
Extends: St.DrawingArea,
_init: function(repaintFunction, getHasImageFunction) {
this._repaint = repaintFunction;
this._getHasImage = getHasImageFunction || (() => false);
this.parent();
},
// Bind the size of layers and layer container.
vfunc_parent_set: function() {
this.clear_constraints();
if (this.get_parent())
this.add_constraint(new Clutter.BindConstraint({ coordinate: Clutter.BindCoordinate.SIZE, source: this.get_parent() }));
},
vfunc_repaint: function() {
let cr = this.get_context();
try {
this._repaint(cr);
} catch(e) {
logError(e, "An error occured while painting");
}
cr.$dispose();
if (this._getHasImage())
System.gc();
}
});
// Darwing area is a container that manages drawing elements and drawing layers.
// There is a drawing element for each "brushstroke".
// There is a separated layer for the current element so only the current element is redisplayed when drawing.
// It handles pointer/mouse/(touch?) events and some keyboard events. // It handles pointer/mouse/(touch?) events and some keyboard events.
var DrawingArea = new Lang.Class({ var DrawingArea = new Lang.Class({
Name: `${UUID}-DrawingArea`, Name: `${UUID}-DrawingArea`,
Extends: St.DrawingArea, Extends: St.Widget,
Signals: { 'show-osd': { param_types: [Gio.Icon.$gtype, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_DOUBLE, GObject.TYPE_BOOLEAN] }, Signals: { 'show-osd': { param_types: [Gio.Icon.$gtype, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_DOUBLE, GObject.TYPE_BOOLEAN] },
'update-action-mode': {}, 'update-action-mode': {},
'leave-drawing-mode': {} }, 'leave-drawing-mode': {} },
@ -98,6 +131,18 @@ var DrawingArea = new Lang.Class({
this.monitor = monitor; this.monitor = monitor;
this.helper = helper; this.helper = helper;
this.layerContainer = new St.Widget({ width: monitor.width, height: monitor.height });
this.add_child(this.layerContainer);
this.add_child(this.helper);
this.backLayer = new DrawingLayer(this._repaintBack.bind(this), this._getHasImageBack.bind(this));
this.layerContainer.add_child(this.backLayer);
this.foreLayer = new DrawingLayer(this._repaintFore.bind(this), this._getHasImageFore.bind(this));
this.layerContainer.add_child(this.foreLayer);
this.gridLayer = new DrawingLayer(this._repaintGrid.bind(this));
this.gridLayer.hide();
this.layerContainer.add_child(this.gridLayer);
this.elements = []; this.elements = [];
this.undoneElements = []; this.undoneElements = [];
this.currentElement = null; this.currentElement = null;
@ -113,7 +158,6 @@ var DrawingArea = new Lang.Class({
this.currentLineCap = Cairo.LineCap.ROUND; this.currentLineCap = Cairo.LineCap.ROUND;
this.currentFillRule = Cairo.FillRule.WINDING; this.currentFillRule = Cairo.FillRule.WINDING;
this.isSquareArea = false; this.isSquareArea = false;
this.hasGrid = false;
this.hasBackground = false; this.hasBackground = false;
this.textHasCursor = false; this.textHasCursor = false;
this.dashedLine = false; this.dashedLine = false;
@ -225,25 +269,6 @@ var DrawingArea = new Lang.Class({
return this._fontFamilies; return this._fontFamilies;
}, },
vfunc_repaint: function() {
let cr = this.get_context();
try {
this._repaint(cr);
} catch(e) {
logError(e, "An error occured while painting");
}
cr.$dispose();
if (this.elements.some(element => element.shape == Shapes.IMAGE) || this.currentElement && this.currentElement.shape == Shapes.IMAGE)
System.gc();
},
_redisplay: function() {
// force area to emit 'repaint'
this.queue_repaint();
},
_onDrawingSettingsChanged: function() { _onDrawingSettingsChanged: function() {
this.palettes = Me.drawingSettings.get_value('palettes').deep_unpack(); this.palettes = Me.drawingSettings.get_value('palettes').deep_unpack();
if (!this.colors) { if (!this.colors) {
@ -284,12 +309,7 @@ var DrawingArea = new Lang.Class({
} }
}, },
_repaint: function(cr) { _repaintBack: function(cr) {
if (CAIRO_DEBUG_EXTENDS) {
cr.scale(0.5, 0.5);
cr.translate(this.monitor.width, this.monitor.height);
}
for (let i = 0; i < this.elements.length; i++) { for (let i = 0; i < this.elements.length; i++) {
cr.save(); cr.save();
@ -309,41 +329,72 @@ var DrawingArea = new Lang.Class({
cr.restore(); cr.restore();
} }
if (this.currentElement) { if (this.currentElement && this.currentElement.eraser) {
cr.save();
this.currentElement.buildCairo(cr, { showTextCursor: this.textHasCursor, this.currentElement.buildCairo(cr, { showTextCursor: this.textHasCursor,
showTextRectangle: this.currentElement.shape != Shapes.TEXT || !this.isWriting, showTextRectangle: this.currentElement.shape != Shapes.TEXT || !this.isWriting,
dummyStroke: this.currentElement.fill && this.currentElement.line.lineWidth == 0 }); dummyStroke: this.currentElement.fill && this.currentElement.line.lineWidth == 0 });
cr.stroke(); cr.stroke();
cr.restore();
} }
},
_repaintFore: function(cr) {
if (!this.currentElement || this.currentElement.eraser)
return;
if (this.reactive && this.hasGrid) { this.currentElement.buildCairo(cr, { showTextCursor: this.textHasCursor,
cr.save(); showTextRectangle: this.currentElement.shape != Shapes.TEXT || !this.isWriting,
Clutter.cairo_set_source_color(cr, this.gridColor); dummyStroke: this.currentElement.fill && this.currentElement.line.lineWidth == 0 });
cr.stroke();
let [gridX, gridY] = [0, 0]; },
while (gridX < this.monitor.width / 2) {
cr.setLineWidth((gridX / this.gridLineSpacing) % 5 ? this.gridLineWidth / 2 : this.gridLineWidth); _repaintGrid: function(cr) {
cr.moveTo(this.monitor.width / 2 + gridX, 0); if (!this.reactive)
cr.lineTo(this.monitor.width / 2 + gridX, this.monitor.height); return;
cr.moveTo(this.monitor.width / 2 - gridX, 0);
cr.lineTo(this.monitor.width / 2 - gridX, this.monitor.height); Clutter.cairo_set_source_color(cr, this.gridColor);
gridX += this.gridLineSpacing;
cr.stroke(); let [gridX, gridY] = [0, 0];
} while (gridX < this.monitor.width / 2) {
while (gridY < this.monitor.height / 2) { cr.setLineWidth((gridX / this.gridLineSpacing) % 5 ? this.gridLineWidth / 2 : this.gridLineWidth);
cr.setLineWidth((gridY / this.gridLineSpacing) % 5 ? this.gridLineWidth / 2 : this.gridLineWidth); cr.moveTo(this.monitor.width / 2 + gridX, 0);
cr.moveTo(0, this.monitor.height / 2 + gridY); cr.lineTo(this.monitor.width / 2 + gridX, this.monitor.height);
cr.lineTo(this.monitor.width, this.monitor.height / 2 + gridY); cr.moveTo(this.monitor.width / 2 - gridX, 0);
cr.moveTo(0, this.monitor.height / 2 - gridY); cr.lineTo(this.monitor.width / 2 - gridX, this.monitor.height);
cr.lineTo(this.monitor.width, this.monitor.height / 2 - gridY); gridX += this.gridLineSpacing;
gridY += this.gridLineSpacing; cr.stroke();
cr.stroke();
}
cr.restore();
} }
while (gridY < this.monitor.height / 2) {
cr.setLineWidth((gridY / this.gridLineSpacing) % 5 ? this.gridLineWidth / 2 : this.gridLineWidth);
cr.moveTo(0, this.monitor.height / 2 + gridY);
cr.lineTo(this.monitor.width, this.monitor.height / 2 + gridY);
cr.moveTo(0, this.monitor.height / 2 - gridY);
cr.lineTo(this.monitor.width, this.monitor.height / 2 - gridY);
gridY += this.gridLineSpacing;
cr.stroke();
}
},
_getHasImageBack: function() {
return this.elements.some(element => element.shape == Shapes.IMAGE);
},
_getHasImageFore: function() {
return this.currentElement && this.currentElement.shape == Shapes.IMAGE || false;
},
_redisplay: function() {
// force area to emit 'repaint'
this.backLayer.queue_repaint();
this.foreLayer.queue_repaint();
if (this.hasGrid)
this.gridLayer.queue_repaint();
},
_transformStagePoint: function(x, y) {
if (!this.layerContainer.get_allocation_box().contains(x, y))
return [false, 0, 0];
return this.layerContainer.transform_stage_point(x, y);
}, },
_onButtonPressed: function(actor, event) { _onButtonPressed: function(actor, event) {
@ -479,7 +530,7 @@ var DrawingArea = new Lang.Class({
this.elementGrabberTimestamp = event.get_time(); this.elementGrabberTimestamp = event.get_time();
let coords = event.get_coords(); let coords = event.get_coords();
let [s, x, y] = this.transform_stage_point(coords[0], coords[1]); let [s, x, y] = this._transformStagePoint(coords[0], coords[1]);
if (!s) if (!s)
return; return;
@ -499,7 +550,7 @@ var DrawingArea = new Lang.Class({
}, },
_startTransforming: function(stageX, stageY, controlPressed, duplicate) { _startTransforming: function(stageX, stageY, controlPressed, duplicate) {
let [success, startX, startY] = this.transform_stage_point(stageX, stageY); let [success, startX, startY] = this._transformStagePoint(stageX, stageY);
if (!success) if (!success)
return; return;
@ -549,7 +600,7 @@ var DrawingArea = new Lang.Class({
return; return;
let coords = event.get_coords(); let coords = event.get_coords();
let [s, x, y] = this.transform_stage_point(coords[0], coords[1]); let [s, x, y] = this._transformStagePoint(coords[0], coords[1]);
if (!s) if (!s)
return; return;
let controlPressed = event.has_control_modifier(); let controlPressed = event.has_control_modifier();
@ -605,8 +656,7 @@ var DrawingArea = new Lang.Class({
}, },
_startDrawing: function(stageX, stageY, shiftPressed) { _startDrawing: function(stageX, stageY, shiftPressed) {
let [success, startX, startY] = this.transform_stage_point(stageX, stageY); let [success, startX, startY] = this._transformStagePoint(stageX, stageY);
if (!success) if (!success)
return; return;
@ -665,9 +715,10 @@ var DrawingArea = new Lang.Class({
return; return;
let coords = event.get_coords(); let coords = event.get_coords();
let [s, x, y] = this.transform_stage_point(coords[0], coords[1]); let [s, x, y] = this._transformStagePoint(coords[0], coords[1]);
if (!s) if (!s)
return; return;
let controlPressed = event.has_control_modifier(); let controlPressed = event.has_control_modifier();
this._updateDrawing(x, y, controlPressed); this._updateDrawing(x, y, controlPressed);
@ -682,7 +733,7 @@ var DrawingArea = new Lang.Class({
if (!success) if (!success)
return GLib.SOURCE_CONTINUE; return GLib.SOURCE_CONTINUE;
let [s, x, y] = this.transform_stage_point(coords.x, coords.y); let [s, x, y] = this._transformStagePoint(coords.x, coords.y);
if (!s) if (!s)
return GLib.SOURCE_CONTINUE; return GLib.SOURCE_CONTINUE;
@ -703,7 +754,10 @@ var DrawingArea = new Lang.Class({
this.currentElement.updateDrawing(x, y, controlPressed); this.currentElement.updateDrawing(x, y, controlPressed);
this._redisplay(); if (this.currentElement.eraser)
this._redisplay();
else
this.foreLayer.queue_repaint();
this.updatePointerCursor(controlPressed); this.updatePointerCursor(controlPressed);
}, },
@ -748,15 +802,15 @@ var DrawingArea = new Lang.Class({
this.currentElement.text = ''; this.currentElement.text = '';
this.currentElement.cursorPosition = 0; this.currentElement.cursorPosition = 0;
// Translators: %s is a key label // Translators: %s is a key label
this.emit('show-osd', Files.Icons.TOOL_TEXT, _("Type your text and press <i>%s</i>") this.emit('show-osd', Files.Icons.TOOL_TEXT, _("Press <i>%s</i>\nto start a new line")
.format(Gtk.accelerator_get_label(Clutter.KEY_Escape, 0)), "", -1, true); .format(Gtk.accelerator_get_label(Clutter.KEY_Return, 1)), "", -1, true);
this._updateTextCursorTimeout(); this._updateTextCursorTimeout();
this.textHasCursor = true; this.textHasCursor = true;
this._redisplay(); this._redisplay();
// Do not hide and do not set opacity to 0 because ibusCandidatePopup need a mapped text entry to init correctly its position. // Do not hide and do not set opacity to 0 because ibusCandidatePopup need a mapped text entry to init correctly its position.
this.textEntry = new St.Entry({ opacity: 1, x: stageX + x, y: stageY + y }); this.textEntry = new St.Entry({ opacity: 1, x: stageX + x, y: stageY + y });
this.get_parent().insert_child_below(this.textEntry, this); this.insert_child_below(this.textEntry, null);
this.textEntry.grab_key_focus(); this.textEntry.grab_key_focus();
this.updateActionMode(); this.updateActionMode();
this.updatePointerCursor(); this.updatePointerCursor();
@ -766,7 +820,7 @@ var DrawingArea = new Lang.Class({
if (ibusCandidatePopup) { if (ibusCandidatePopup) {
this.ibusHandler = ibusCandidatePopup.connect('notify::visible', () => { this.ibusHandler = ibusCandidatePopup.connect('notify::visible', () => {
if (ibusCandidatePopup.visible) { if (ibusCandidatePopup.visible) {
this.get_parent().set_child_above_sibling(this.textEntry, this); this.set_child_above_sibling(this.textEntry, null);
this.textEntry.opacity = 255; this.textEntry.opacity = 255;
} }
}); });
@ -774,9 +828,7 @@ var DrawingArea = new Lang.Class({
} }
this.textEntry.clutterText.connect('activate', (clutterText) => { this.textEntry.clutterText.connect('activate', (clutterText) => {
let startNewLine = true; this._stopWriting();
this._stopWriting(startNewLine);
clutterText.text = "";
}); });
this.textEntry.clutterText.connect('text-changed', (clutterText) => { this.textEntry.clutterText.connect('text-changed', (clutterText) => {
@ -790,8 +842,16 @@ var DrawingArea = new Lang.Class({
this.textEntry.clutterText.connect('key-press-event', (clutterText, event) => { this.textEntry.clutterText.connect('key-press-event', (clutterText, event) => {
if (event.get_key_symbol() == Clutter.KEY_Escape) { if (event.get_key_symbol() == Clutter.KEY_Escape) {
this.currentElement.text = "";
this._stopWriting(); this._stopWriting();
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} else if (event.has_shift_modifier() &&
(event.get_key_symbol() == Clutter.KEY_Return ||
event.get_key_symbol() == Clutter.KEY_KP_Enter)) {
let startNewLine = true;
this._stopWriting(startNewLine);
clutterText.text = "";
return Clutter.EVENT_STOP;
} }
// 'cursor-changed' signal is not emitted if the text entry is not visible. // 'cursor-changed' signal is not emitted if the text entry is not visible.
@ -884,8 +944,12 @@ var DrawingArea = new Lang.Class({
// A priori there is nothing to stop, except transformations, if there is no current element. // A priori there is nothing to stop, except transformations, if there is no current element.
// 'force' argument is passed when leaving drawing mode to ensure all is clean, as a workaround for possible bugs. // 'force' argument is passed when leaving drawing mode to ensure all is clean, as a workaround for possible bugs.
_stopAll: function(force) { _stopAll: function(force) {
if (this.grabbedElement) if (this.grabbedElement) {
this._stopTransforming(); this._stopTransforming();
this.grabbedElement = null;
this.grabbedElementLocked = null;
this.updatePointerCursor();
}
if (!this.currentElement && !force) if (!this.currentElement && !force)
return; return;
@ -948,24 +1012,28 @@ var DrawingArea = new Lang.Class({
toggleBackground: function() { toggleBackground: function() {
this.hasBackground = !this.hasBackground; this.hasBackground = !this.hasBackground;
this.get_parent().set_background_color(this.hasBackground ? this.areaBackgroundColor : null); this.set_background_color(this.hasBackground ? this.areaBackgroundColor : null);
},
get hasGrid() {
return this.gridLayer.visible;
}, },
toggleGrid: function() { toggleGrid: function() {
this.hasGrid = !this.hasGrid; // The grid layer is repainted when the visibility changes.
this._redisplay(); this.gridLayer.visible = !this.gridLayer.visible;
}, },
toggleSquareArea: function() { toggleSquareArea: function() {
this.isSquareArea = !this.isSquareArea; this.isSquareArea = !this.isSquareArea;
if (this.isSquareArea) { if (this.isSquareArea) {
this.set_position((this.monitor.width - this.squareAreaSize) / 2, (this.monitor.height - this.squareAreaSize) / 2); this.layerContainer.set_position((this.monitor.width - this.squareAreaSize) / 2, (this.monitor.height - this.squareAreaSize) / 2);
this.set_size(this.squareAreaSize, this.squareAreaSize); this.layerContainer.set_size(this.squareAreaSize, this.squareAreaSize);
this.add_style_class_name('draw-on-your-screen-square-area'); this.layerContainer.add_style_class_name('draw-on-your-screen-square-area');
} else { } else {
this.set_position(0, 0); this.layerContainer.set_position(0, 0);
this.set_size(this.monitor.width, this.monitor.height); this.layerContainer.set_size(this.monitor.width, this.monitor.height);
this.remove_style_class_name('draw-on-your-screen-square-area'); this.layerContainer.remove_style_class_name('draw-on-your-screen-square-area');
} }
}, },
@ -1215,7 +1283,7 @@ var DrawingArea = new Lang.Class({
this.buttonPressedHandler = this.connect('button-press-event', this._onButtonPressed.bind(this)); this.buttonPressedHandler = this.connect('button-press-event', this._onButtonPressed.bind(this));
this.keyboardPopupMenuHandler = this.connect('popup-menu', this._onKeyboardPopupMenu.bind(this)); this.keyboardPopupMenuHandler = this.connect('popup-menu', this._onKeyboardPopupMenu.bind(this));
this.scrollHandler = this.connect('scroll-event', this._onScroll.bind(this)); this.scrollHandler = this.connect('scroll-event', this._onScroll.bind(this));
this.get_parent().set_background_color(this.reactive && this.hasBackground ? this.areaBackgroundColor : null); this.set_background_color(this.reactive && this.hasBackground ? this.areaBackgroundColor : null);
}, },
leaveDrawingMode: function(save, erase) { leaveDrawingMode: function(save, erase) {
@ -1242,7 +1310,7 @@ var DrawingArea = new Lang.Class({
this.erase(); this.erase();
this.closeMenu(); this.closeMenu();
this.get_parent().set_background_color(null); this.set_background_color(null);
Files.Images.reset(); Files.Images.reset();
if (save) if (save)
this.savePersistent(); this.savePersistent();
@ -1273,7 +1341,7 @@ var DrawingArea = new Lang.Class({
}; };
let getImageSvgContent = () => { let getImageSvgContent = () => {
return `<svg viewBox="0 0 ${this.width} ${this.height}" ${prefixes}>${elementsContent}\n</svg>`; return `<svg viewBox="0 0 ${this.layerContainer.width} ${this.layerContainer.height}" ${prefixes}>${elementsContent}\n</svg>`;
}; };
return [getGiconSvgContent, getImageSvgContent]; return [getGiconSvgContent, getImageSvgContent];
@ -1285,23 +1353,15 @@ var DrawingArea = new Lang.Class({
let prefixes = 'xmlns="http://www.w3.org/2000/svg"'; let prefixes = 'xmlns="http://www.w3.org/2000/svg"';
if (this.elements.some(element => element.shape == Shapes.IMAGE)) if (this.elements.some(element => element.shape == Shapes.IMAGE))
prefixes += ' xmlns:xlink="http://www.w3.org/1999/xlink"'; prefixes += ' xmlns:xlink="http://www.w3.org/1999/xlink"';
let content = `<svg viewBox="0 0 ${this.width} ${this.height}" ${prefixes}>`; let content = `<svg viewBox="0 0 ${this.layerContainer.width} ${this.layerContainer.height}" ${prefixes}>`;
if (SVG_DEBUG_EXTENDS)
content = `<svg viewBox="${-this.width} ${-this.height} ${2 * this.width} ${2 * this.height}" xmlns="http://www.w3.org/2000/svg">`;
let backgroundColorString = this.hasBackground ? String(this.areaBackgroundColor) : 'transparent'; let backgroundColorString = this.hasBackground ? String(this.areaBackgroundColor) : 'transparent';
if (backgroundColorString != 'transparent') { if (backgroundColorString != 'transparent')
content += `\n <rect id="background" width="100%" height="100%" fill="${backgroundColorString}"/>`; content += `\n <rect id="background" width="100%" height="100%" fill="${backgroundColorString}"/>`;
}
if (SVG_DEBUG_EXTENDS) {
content += `\n <line stroke="black" x1="0" y1="${-this.height}" x2="0" y2="${this.height}"/>`;
content += `\n <line stroke="black" x1="${-this.width}" y1="0" x2="${this.width}" y2="0"/>`;
}
this.elements.forEach(element => content += element.buildSVG(backgroundColorString)); this.elements.forEach(element => content += element.buildSVG(backgroundColorString));
content += "\n</svg>"; content += "\n</svg>";
if (Files.saveSvg(content)) { if (Files.saveSvg(content)) {
// pass the parent (bgContainer) to Flashspot because coords of this are relative let flashspot = new Screenshot.Flashspot(this);
let flashspot = new Screenshot.Flashspot(this.get_parent());
flashspot.fire(); flashspot.fire();
if (global.play_theme_sound) { if (global.play_theme_sound) {
global.play_theme_sound(0, 'screen-capture', "Save as SVG", null); global.play_theme_sound(0, 'screen-capture', "Save as SVG", null);

View File

@ -577,11 +577,12 @@ const _DrawingElement = new Lang.Class({
}, },
stopTransformation: function() { stopTransformation: function() {
this.showSymmetryElement = false;
// Clean transformations // Clean transformations
let transformation = this.lastTransformation; let transformation = this.lastTransformation;
if (!transformation)
if (transformation.type == Transformations.REFLECTION || transformation.type == Transformations.INVERSION) return;
this.showSymmetryElement = false;
if (transformation.type == Transformations.REFLECTION && if (transformation.type == Transformations.REFLECTION &&
getNearness([transformation.startX, transformation.startY], [transformation.endX, transformation.endY], MIN_REFLECTION_LINE_LENGTH) || getNearness([transformation.startX, transformation.startY], [transformation.endX, transformation.endY], MIN_REFLECTION_LINE_LENGTH) ||

View File

@ -131,9 +131,9 @@ const AreaManager = new Lang.Class({
onDesktopSettingChanged: function() { onDesktopSettingChanged: function() {
if (this.onDesktop) if (this.onDesktop)
this.areas.forEach(area => area.get_parent().show()); this.areas.forEach(area => area.show());
else else
this.areas.forEach(area => area.get_parent().hide()); this.areas.forEach(area => area.hide());
}, },
onPersistentOverRestartsSettingChanged: function() { onPersistentOverRestartsSettingChanged: function() {
@ -167,19 +167,15 @@ const AreaManager = new Lang.Class({
for (let i = 0; i < this.monitors.length; i++) { for (let i = 0; i < this.monitors.length; i++) {
let monitor = this.monitors[i]; let monitor = this.monitors[i];
let container = new St.Widget({ name: 'drawOnYourSreenContainer' + i });
let helper = new Helper.DrawingHelper({ name: 'drawOnYourSreenHelper' + i }, monitor); let helper = new Helper.DrawingHelper({ name: 'drawOnYourSreenHelper' + i }, monitor);
let loadPersistent = i == Main.layoutManager.primaryIndex && this.persistentOverRestarts; let loadPersistent = i == Main.layoutManager.primaryIndex && this.persistentOverRestarts;
let area = new Area.DrawingArea({ name: 'drawOnYourSreenArea' + i }, monitor, helper, loadPersistent); let area = new Area.DrawingArea({ name: 'drawOnYourSreenArea' + i }, monitor, helper, loadPersistent);
container.add_child(area);
container.add_child(helper);
Main.layoutManager._backgroundGroup.insert_child_above(container, Main.layoutManager._bgManagers[i].backgroundActor); Main.layoutManager._backgroundGroup.insert_child_above(area, Main.layoutManager._bgManagers[i].backgroundActor);
if (!this.onDesktop) if (!this.onDesktop)
container.hide(); area.hide();
container.set_position(monitor.x, monitor.y); area.set_position(monitor.x, monitor.y);
container.set_size(monitor.width, monitor.height);
area.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.leaveDrawingHandler = area.connect('leave-drawing-mode', this.toggleDrawing.bind(this));
area.updateActionModeHandler = area.connect('update-action-mode', this.updateActionMode.bind(this)); area.updateActionModeHandler = area.connect('update-action-mode', this.updateActionMode.bind(this));
@ -333,25 +329,24 @@ const AreaManager = new Lang.Class({
} }
}, },
toggleContainer: function() { toggleArea: function() {
if (!this.activeArea) if (!this.activeArea)
return; return;
let activeContainer = this.activeArea.get_parent();
let activeIndex = this.areas.indexOf(this.activeArea); let activeIndex = this.areas.indexOf(this.activeArea);
if (activeContainer.get_parent() == Main.uiGroup) { if (this.activeArea.get_parent() == Main.uiGroup) {
Main.uiGroup.set_child_at_index(Main.layoutManager.keyboardBox, this.oldKeyboardIndex); Main.uiGroup.set_child_at_index(Main.layoutManager.keyboardBox, this.oldKeyboardIndex);
Main.uiGroup.remove_actor(activeContainer); Main.uiGroup.remove_actor(this.activeArea);
Main.layoutManager._backgroundGroup.insert_child_above(activeContainer, Main.layoutManager._bgManagers[activeIndex].backgroundActor); Main.layoutManager._backgroundGroup.insert_child_above(this.activeArea, Main.layoutManager._bgManagers[activeIndex].backgroundActor);
if (!this.onDesktop) if (!this.onDesktop)
activeContainer.hide(); this.activeArea.hide();
} else { } else {
Main.layoutManager._backgroundGroup.remove_actor(activeContainer); Main.layoutManager._backgroundGroup.remove_actor(this.activeArea);
Main.uiGroup.add_child(activeContainer); Main.uiGroup.add_child(this.activeArea);
// move the keyboard above the area to make it available with text entries // move the keyboard above the area to make it available with text entries
this.oldKeyboardIndex = Main.uiGroup.get_children().indexOf(Main.layoutManager.keyboardBox); this.oldKeyboardIndex = Main.uiGroup.get_children().indexOf(Main.layoutManager.keyboardBox);
Main.uiGroup.set_child_above_sibling(Main.layoutManager.keyboardBox, activeContainer); Main.uiGroup.set_child_above_sibling(Main.layoutManager.keyboardBox, this.activeArea);
} }
}, },
@ -397,23 +392,24 @@ const AreaManager = new Lang.Class({
if (Main._findModal(this.activeArea) != -1) if (Main._findModal(this.activeArea) != -1)
this.toggleModal(); this.toggleModal();
this.toggleContainer(); this.toggleArea();
this.activeArea = null; this.activeArea = null;
} else { } else {
// avoid to deal with Meta changes (global.display/global.screen) // avoid to deal with Meta changes (global.display/global.screen)
let currentIndex = Main.layoutManager.monitors.indexOf(Main.layoutManager.currentMonitor); let currentIndex = Main.layoutManager.monitors.indexOf(Main.layoutManager.currentMonitor);
this.activeArea = this.areas[currentIndex]; this.activeArea = this.areas[currentIndex];
this.toggleContainer(); this.toggleArea();
if (!this.toggleModal()) { if (!this.toggleModal()) {
this.toggleContainer(); this.toggleArea();
this.activeArea = null; this.activeArea = null;
return; return;
} }
this.activeArea.enterDrawingMode(); this.activeArea.enterDrawingMode();
this.osdDisabled = Me.settings.get_boolean('osd-disabled'); this.osdDisabled = Me.settings.get_boolean('osd-disabled');
// <span size="medium"> is a clutter/mutter 3.38 bug workaround: https://gitlab.gnome.org/GNOME/mutter/-/issues/1467
// Translators: %s is a key label // Translators: %s is a key label
let label = "<small>" + _("Press <i>%s</i> for help").format(this.activeArea.helper.helpKeyLabel) + "</small>\n\n" + _("Entering drawing mode"); let label = `<small>${_("Press <i>%s</i> for help").format(this.activeArea.helper.helpKeyLabel)}</small>\n\n<span size="medium">${_("Entering drawing mode")}</span>`;
this.showOsd(null, Files.Icons.ENTER, label, null, null, true); this.showOsd(null, Files.Icons.ENTER, label, null, null, true);
} }
@ -517,9 +513,7 @@ const AreaManager = new Lang.Class({
area.disconnect(area.leaveDrawingHandler); area.disconnect(area.leaveDrawingHandler);
area.disconnect(area.updateActionModeHandler); area.disconnect(area.updateActionModeHandler);
area.disconnect(area.showOsdHandler); area.disconnect(area.showOsdHandler);
let container = area.get_parent(); area.destroy();
container.get_parent().remove_actor(container);
container.destroy();
} }
this.areas = []; this.areas = [];
}, },

View File

@ -44,7 +44,7 @@ msgstr ""
#. Translators: %s is a key label #. Translators: %s is a key label
#, javascript-format #, javascript-format
msgid "Type your text and press <i>%s</i>" msgid "Press <i>%s</i>\nto start a new line"
msgstr "" msgstr ""
#. Translators: It is displayed in an OSD notification to ask the user to start picking, so it should use the imperative mood. #. Translators: It is displayed in an OSD notification to ask the user to start picking, so it should use the imperative mood.

View File

@ -18,5 +18,5 @@
"3.36", "3.36",
"3.38" "3.38"
], ],
"version": 8.1 "version": 9
} }