Fix up space-to-pan event handling

pull/5312/head
Nick O'Leary 2025-10-20 13:15:37 +01:00
parent 9cedcd0a78
commit 3bbdc77300
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
1 changed files with 94 additions and 68 deletions

View File

@ -398,8 +398,9 @@ RED.view = (function() {
lasso.remove();
lasso = null;
}
} else if (mouse_mode === RED.state.PANNING && d3.event.buttons !== 4) {
resetMouseVars();
} else if (mouse_mode === RED.state.PANNING) {
// ensure the cursor is set to grab when re-entering the canvas while panning
outer.style('cursor', 'grabbing');
} else if (slicePath) {
if (d3.event.buttons !== 2) {
slicePath.remove();
@ -597,9 +598,9 @@ RED.view = (function() {
}
d3.event.preventDefault();
});
const handleAltToggle = (event) => {
const handleChartKeyboardEvents = (event) => {
// Handle Alt toggle for pulling nodes out of groups
if (mouse_mode === RED.state.MOVING_ACTIVE && event.key === 'Alt' && groupAddParentGroup) {
RED.nodes.group(groupAddParentGroup).dirty = true
for (let n = 0; n<movingSet.length(); n++) {
@ -618,54 +619,57 @@ RED.view = (function() {
}
}
RED.view.redraw()
}
}
document.addEventListener("keyup", handleAltToggle)
document.addEventListener("keydown", handleAltToggle)
// Handle spacebar for zoom mode
function handleSpacebarToggle(e) {
if (e.keyCode === 32 || e.key === ' ') {
// Always prevent default space scrolling behavior
e.preventDefault();
e.stopPropagation();
if (e.type === "keydown" && !spacebarPressed) {
spacebarPressed = true;
// Change cursor to grab hand when spacebar is pressed
outer.style('cursor', 'grab');
} else if (e.type === "keyup" && spacebarPressed) {
spacebarPressed = false;
// Revert cursor when spacebar is released
outer.style('cursor', '');
} else if (event.keyCode === 32 || event.key === ' ') {
if (mouse_mode === RED.state.PANNING) {
// Already in panning mode - just prevent the event default handler
event.preventDefault()
event.stopPropagation()
if (event.type === 'keyup' && spacebarPressed) {
spacebarPressed = false
}
} else if (mouse_mode === RED.state.DEFAULT) {
// Handle spacebar for panning
event.preventDefault();
event.stopPropagation();
if (event.type === "keydown" && !spacebarPressed) {
spacebarPressed = true;
// Change cursor to grab hand when spacebar is pressed
outer.style('cursor', 'grab');
} else if (event.type === "keyup" && spacebarPressed) {
spacebarPressed = false;
// Revert cursor when spacebar is released
outer.style('cursor', '');
}
}
}
}
chart.on("keydown", handleChartKeyboardEvents)
chart.on("keyup", handleChartKeyboardEvents)
// Window-level keyup listener to catch spacebar release when cursor is outside canvas
function handleWindowSpacebarUp(e) {
if ((e.keyCode === 32 || e.key === ' ') && spacebarPressed) {
spacebarPressed = false;
// Revert cursor when spacebar is released outside canvas
outer.style('cursor', '');
e.preventDefault();
e.stopPropagation();
}
}
document.addEventListener("keyup", handleSpacebarToggle)
document.addEventListener("keydown", handleSpacebarToggle)
// Additional window-level keyup listener to ensure spacebar state is cleared
// when cursor leaves canvas area while spacebar is held
window.addEventListener("keyup", handleWindowSpacebarUp)
// // // Window-level keyup listener to catch spacebar release when cursor is outside canvas
// // function handleWindowSpacebarUp(e) {
// // if ((e.keyCode === 32 || e.key === ' ') && spacebarPressed) {
// // spacebarPressed = false;
// // // Revert cursor when spacebar is released outside canvas
// // outer.style('cursor', '');
// // e.preventDefault();
// // e.stopPropagation();
// // }
// // }
// // chart.on("keyup", handleSpacebarToggle)
// // chart.on("keydown", handleSpacebarToggle)
// // Additional window-level keyup listener to ensure spacebar state is cleared
// // when cursor leaves canvas area while spacebar is held
// window.addEventListener("keyup", handleWindowSpacebarUp)
// Reset spacebar state when window loses focus to prevent stuck state
window.addEventListener("blur", function() {
if (spacebarPressed) {
spacebarPressed = false;
// Revert cursor when window loses focus
outer.style('cursor', '');
}
})
// // Reset spacebar state when window loses focus to prevent stuck state
// window.addEventListener("blur", function() {
// if (spacebarPressed) {
// spacebarPressed = false;
// // Revert cursor when window loses focus
// outer.style('cursor', '');
// }
// })
// Recalculate minimum zoom when window resizes
$(window).on("resize.red-ui-view", function() {
@ -811,6 +815,10 @@ RED.view = (function() {
}, { passive: false });
chart.on("wheel", function(evt) {
if (mouse_mode === RED.state.PANNING) {
// Ignore wheel events while panning
return;
}
// ctrlKey is set during pinch gestures on trackpads
if (evt.ctrlKey || evt.altKey || spacebarPressed) {
evt.preventDefault();
@ -2138,6 +2146,27 @@ RED.view = (function() {
redraw();
}
function startPanning () {
}
window.addEventListener('mousemove', function (event) {
if (mouse_mode === RED.state.PANNING) {
var pos = [event.pageX, event.pageY];
// if (d3.event.touches) {
// var touch0 = d3.event.touches.item(0);
// pos = [touch0.pageX, touch0.pageY];
// }
var deltaPos = [
mouse_position[0]-pos[0],
mouse_position[1]-pos[1]
];
chart.scrollLeft(scroll_position[0]+deltaPos[0])
chart.scrollTop(scroll_position[1]+deltaPos[1])
RED.events.emit("view:navigate");
return
}
})
function canvasMouseMove() {
var i;
var node;
@ -2152,19 +2181,8 @@ RED.view = (function() {
//console.log(d3.mouse(this),container.offsetWidth,container.offsetHeight,container.scrollLeft,container.scrollTop);
if (mouse_mode === RED.state.PANNING) {
var pos = [d3.event.pageX,d3.event.pageY];
if (d3.event.touches) {
var touch0 = d3.event.touches.item(0);
pos = [touch0.pageX, touch0.pageY];
}
var deltaPos = [
mouse_position[0]-pos[0],
mouse_position[1]-pos[1]
];
chart.scrollLeft(scroll_position[0]+deltaPos[0])
chart.scrollTop(scroll_position[1]+deltaPos[1])
RED.events.emit("view:navigate");
// A window-level handler is used for panning so the mouse can leave the confines of the chart
// but continue panning
return
}
@ -2495,11 +2513,6 @@ RED.view = (function() {
canvasMouseUp.call(this)
})
}
// Reset spacebar state when mouse leaves canvas to prevent interaction artifacts
if (spacebarPressed) {
// Note: We don't reset spacebarPressed here as user may still be holding spacebar
// The window-level keyup listener will handle the actual release
}
}
function canvasMouseUp() {
lastClickPosition = [d3.event.offsetX/scaleFactor,d3.event.offsetY/scaleFactor];
@ -3055,11 +3068,9 @@ RED.view = (function() {
function zoomView(factor, focalPoint) {
console.log('=== ZOOM VIEW CALLED ===', 'factor:', factor, 'focalPoint:', focalPoint);
// Early return if scale factor isn't actually changing
// This prevents focal point shifts when at zoom limits
if (Math.abs(scaleFactor - factor) < 0.001) {
console.log('Zoom view SKIPPED - already at target zoom');
return;
}
@ -3992,6 +4003,9 @@ RED.view = (function() {
function portMouseDown(d,portType,portIndex, evt) {
if (RED.view.DEBUG) { console.warn("portMouseDown", mouse_mode,d,portType,portIndex); }
if (spacebarPressed) {
return
}
RED.contextMenu.hide();
evt = evt || d3.event;
if (evt === 1) {
@ -4420,6 +4434,9 @@ RED.view = (function() {
d3.event.stopPropagation();
return;
}
if (spacebarPressed) {
return
}
clearTimeout(portLabelHoverTimeout);
var active = (mouse_mode!=RED.state.JOINING && mouse_mode != RED.state.QUICK_JOINING) || // Not currently joining - all ports active
(
@ -4576,6 +4593,9 @@ RED.view = (function() {
}
function nodeMouseDown(d) {
if (RED.view.DEBUG) { console.warn("nodeMouseDown", mouse_mode,d); }
if (spacebarPressed) {
return
}
focusView();
RED.contextMenu.hide();
if (d3.event.button === 1) {
@ -4753,6 +4773,9 @@ RED.view = (function() {
function nodeMouseOver(d) {
if (RED.view.DEBUG) { console.warn("nodeMouseOver", mouse_mode,d); }
if (spacebarPressed) {
return
}
if (mouse_mode === 0 || mouse_mode === RED.state.SELECTING_NODE) {
if (mouse_mode === RED.state.SELECTING_NODE && selectNodesOptions && selectNodesOptions.filter) {
if (selectNodesOptions.filter(d)) {
@ -4926,6 +4949,9 @@ RED.view = (function() {
if (RED.view.DEBUG) {
console.warn("groupMouseDown", { mouse_mode, point: mouse, event: d3.event });
}
if (spacebarPressed) {
return
}
RED.contextMenu.hide();
focusView();
if (d3.event.button === 1) {