Merge pull request #9019 from penpot/azazeln28-fix-pointer-selection

🐛 Fix text editor v3 pointer selection
This commit is contained in:
Elena Torró 2026-04-15 17:15:20 +02:00 committed by GitHub
commit e186a27174
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 21 additions and 16 deletions

View File

@ -23,7 +23,6 @@
[app.main.store :as st]
[app.main.ui.workspace.sidebar.assets.components :as wsac]
[app.main.ui.workspace.viewport.viewport-ref :as uwvv]
[app.render-wasm.api :as wasm.api]
[app.util.dom :as dom]
[app.util.dom.dnd :as dnd]
[app.util.dom.normalize-wheel :as nw]
@ -280,7 +279,6 @@
(.releasePointerCapture target (.-pointerId event)))
(let [native-event (dom/event->native-event event)
off-pt (dom/get-offset-position native-event)
ctrl? (kbd/ctrl? native-event)
shift? (kbd/shift? native-event)
alt? (kbd/alt? native-event)
@ -290,10 +288,7 @@
middle-click? (= 2 (.-which native-event))]
(when left-click?
(st/emit! (mse/->MouseEvent :up ctrl? shift? alt? meta?))
(when (wasm.api/text-editor-has-focus?)
(wasm.api/text-editor-pointer-up (.-x off-pt) (.-y off-pt))))
(st/emit! (mse/->MouseEvent :up ctrl? shift? alt? meta?)))
(when middle-click?
(dom/prevent-default native-event)
@ -354,9 +349,7 @@
(let [last-position (mf/use-var nil)]
(mf/use-fn
(fn [event]
(let [native-event (unchecked-get event "nativeEvent")
off-pt (dom/get-offset-position native-event)
raw-pt (dom/get-client-position event)
(let [raw-pt (dom/get-client-position event)
pt (uwvv/point->viewport raw-pt)
;; We calculate the delta because Safari's MouseEvent.movementX/Y drop
@ -365,13 +358,6 @@
(gpt/subtract raw-pt @last-position)
(gpt/point 0 0))]
;; IMPORTANT! This function, right now it's called on EVERY pointermove. I think
;; in the future (when we handle the UI in the render) should be better to
;; have a "wasm.api/pointer-move" function that works as an entry point for
;; all the pointer-move events.
(when (wasm.api/text-editor-has-focus?)
(wasm.api/text-editor-pointer-move (.-x off-pt) (.-y off-pt)))
(rx/push! move-stream pt)
(reset! last-position raw-pt)
(st/emit! (mse/->PointerEvent :delta delta

View File

@ -327,6 +327,7 @@ pub struct TextEditorState {
// This property indicates that we've started
// selecting something with the pointer.
pub is_pointer_selection_active: bool,
pub is_click_event_skipped: bool,
pub active_shape_id: Option<Uuid>,
pub cursor_visible: bool,
pub last_blink_time: f64,
@ -346,6 +347,7 @@ impl TextEditorState {
composition: TextComposition::new(),
has_focus: false,
is_pointer_selection_active: false,
is_click_event_skipped: false,
active_shape_id: None,
cursor_visible: true,
last_blink_time: 0.0,

View File

@ -208,16 +208,20 @@ pub extern "C" fn text_editor_pointer_move(x: f32, y: f32) {
if !state.text_editor_state.has_focus {
return;
}
let point = Point::new(x, y);
let Some(shape_id) = state.text_editor_state.active_shape_id else {
return;
};
let Some(shape) = state.shapes.get(&shape_id) else {
return;
};
if !state.text_editor_state.is_pointer_selection_active {
return;
}
let Type::Text(text_content) = &shape.shape_type else {
return;
};
@ -226,6 +230,9 @@ pub extern "C" fn text_editor_pointer_move(x: f32, y: f32) {
state
.text_editor_state
.extend_selection_from_position(&position);
// We need this flag to prevent handling the click behavior
// just after a pointerup event.
state.text_editor_state.is_click_event_skipped = true;
state.text_editor_state.update_styles(text_content);
}
});
@ -263,6 +270,13 @@ pub extern "C" fn text_editor_pointer_up(x: f32, y: f32) {
#[no_mangle]
pub extern "C" fn text_editor_set_cursor_from_offset(x: f32, y: f32) {
with_state_mut!(state, {
// We need this flag to prevent handling the click behavior
// just after a pointerup event.
if state.text_editor_state.is_click_event_skipped {
state.text_editor_state.is_click_event_skipped = false;
return;
}
if !state.text_editor_state.has_focus {
return;
}
@ -271,12 +285,15 @@ pub extern "C" fn text_editor_set_cursor_from_offset(x: f32, y: f32) {
let Some(shape_id) = state.text_editor_state.active_shape_id else {
return;
};
let Some(shape) = state.shapes.get(&shape_id) else {
return;
};
let Type::Text(text_content) = &shape.shape_type else {
return;
};
if let Some(position) = text_content.get_caret_position_from_shape_coords(&point) {
state.text_editor_state.set_caret_from_position(&position);
}