hterm: fix mouse events to adjust for screen padding
Bug introduced when padding was added in crrev.com/c/2143311.
We clamp to the nearest value when click is in padding.
Bug: 267654
Change-Id: I82744a84a375bac165ff590ea35262e78f7a8ba6
Reviewed-on: https://chromium-review.googlesource.com/c/apps/libapps/+/2172936
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/hterm/js/hterm_scrollport.js b/hterm/js/hterm_scrollport.js
index 91c6ab7..1c07f2e 100644
--- a/hterm/js/hterm_scrollport.js
+++ b/hterm/js/hterm_scrollport.js
@@ -822,6 +822,16 @@
};
/**
+ * Get the horizontal position in px where the scrollbar starts.
+ *
+ * @return {number}
+ */
+hterm.ScrollPort.prototype.getScrollbarX = function() {
+ return hterm.getClientSize(lib.notNull(this.screen_)).width -
+ this.currentScrollbarWidthPx;
+};
+
+/**
* Return the document that holds the visible rows of this hterm.ScrollPort.
*
* @return {!Document}
diff --git a/hterm/js/hterm_terminal.js b/hterm/js/hterm_terminal.js
index 13ca6b4..3a3a94a 100644
--- a/hterm/js/hterm_terminal.js
+++ b/hterm/js/hterm_terminal.js
@@ -597,7 +597,6 @@
console.error(`Invalid screen padding size: ${v}`);
return;
}
- terminal.setCssVar('screen-padding-size', `${v}px`);
terminal.setScreenPaddingSize(v);
},
@@ -1172,6 +1171,7 @@
* @param {number} size
*/
hterm.Terminal.prototype.setScreenPaddingSize = function(size) {
+ this.setCssVar('screen-padding-size', `${size}px`);
this.scrollPort_.setScreenPaddingSize(size);
};
@@ -3818,14 +3818,19 @@
}
// One based row/column stored on the mouse event.
+ const padding = this.scrollPort_.screenPaddingSize;
e.terminalRow = Math.floor(
- (e.clientY - this.scrollPort_.visibleRowTopMargin) /
+ (e.clientY - this.scrollPort_.visibleRowTopMargin - padding) /
this.scrollPort_.characterSize.height) + 1;
e.terminalColumn = Math.floor(
- e.clientX / this.scrollPort_.characterSize.width) + 1;
+ (e.clientX - padding) / this.scrollPort_.characterSize.width) + 1;
- if (e.type == 'mousedown' && e.terminalColumn > this.screenSize.width) {
- // Mousedown in the scrollbar area.
+ // Clamp row and column.
+ e.terminalRow = lib.f.clamp(e.terminalRow, 1, this.screenSize.height);
+ e.terminalColumn = lib.f.clamp(e.terminalColumn, 1, this.screenSize.width);
+
+ // Ignore mousedown in the scrollbar area.
+ if (e.type == 'mousedown' && e.clientX >= this.scrollPort_.getScrollbarX()) {
return;
}
diff --git a/hterm/js/hterm_terminal_tests.js b/hterm/js/hterm_terminal_tests.js
index 85065dc..a1130ac 100644
--- a/hterm/js/hterm_terminal_tests.js
+++ b/hterm/js/hterm_terminal_tests.js
@@ -701,6 +701,74 @@
});
/**
+ * Check mouse row and column.
+ */
+it('mouse-row-column', function() {
+ const terminal = this.terminal;
+ let e;
+
+ // Turn on mouse click reporting.
+ terminal.vt.setDECMode('1000', true);
+
+ let eventReported = false;
+ terminal.onMouse = (e) => {
+ eventReported = true;
+ };
+ const send = (type, x, y) => {
+ eventReported = false;
+ const e = MockTerminalMouseEvent(type, {clientX: x, clientY: y});
+ terminal.onMouse_(e);
+ return e;
+ };
+
+ const padding = terminal.scrollPort_.screenPaddingSize;
+ const charWidth = terminal.scrollPort_.characterSize.width;
+ const charHeight = terminal.scrollPort_.characterSize.height;
+ const screenWidth = terminal.screenSize.width;
+ const screenHeight = terminal.screenSize.height;
+
+ // Cell 10, 10.
+ const x10 = padding + 9.5 * charWidth;
+ const y10 = padding + 9.5 * charHeight;
+ e = send('mousedown', x10, y10);
+ assert.isTrue(eventReported);
+ assert.equal(e.terminalRow, 10);
+ assert.equal(e.terminalColumn, 10);
+
+ // Top padding, clamp to row 1.
+ e = send('mousedown', x10, 0);
+ assert.isTrue(eventReported);
+ assert.equal(e.terminalRow, 1);
+ assert.equal(e.terminalColumn, 10);
+
+ // Right padding, clamp to width.
+ e = send('mousedown', padding + (screenWidth * charWidth) + 1, y10);
+ assert.isTrue(eventReported);
+ assert.equal(e.terminalRow, 10);
+ assert.equal(e.terminalColumn, screenWidth);
+
+ // Scrollbar area, ignore mousedown.
+ e = send('mousedown', (2 * padding) + (screenWidth * charWidth) + 1, y10);
+ assert.isFalse(eventReported);
+ e = send('mousemove', (2 * padding) + (screenWidth * charWidth) + 1, y10);
+ assert.isTrue(eventReported);
+ assert.equal(e.terminalRow, 10);
+ assert.equal(e.terminalColumn, screenWidth);
+
+ // Bottom padding, clamp to height.
+ e = send('mousedown', x10, padding + (screenHeight * charHeight) + 1);
+ assert.isTrue(eventReported);
+ assert.equal(e.terminalRow, screenHeight);
+ assert.equal(e.terminalColumn, 10);
+
+ // Left padding, clamp to column 1.
+ e = send('mousedown', 0, y10);
+ assert.isTrue(eventReported);
+ assert.equal(e.terminalRow, 10);
+ assert.equal(e.terminalColumn, 1);
+});
+
+/**
* Check paste() is working correctly. Note that we do not test the legacy
* pasting using document.execCommand() because it is hard to simulate the
* behavior.