Skip to content

Commit b0b8443

Browse files
committed
Add the focus property to mouse events.
1 parent da638ae commit b0b8443

File tree

9 files changed

+57
-11
lines changed

9 files changed

+57
-11
lines changed

druid-shell/src/mouse.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ pub struct MouseEvent {
3434
/// The number of mouse clicks associated with this event. This will always
3535
/// be `0` for a mouse-up and mouse-move events.
3636
pub count: u8,
37+
/// Focus is `true` on macOS when the mouse-down event (or its companion mouse-up event)
38+
/// with `MouseButton::Left` was the event that caused the window to gain focus.
39+
pub focus: bool,
3740
/// The button that was pressed down in the case of mouse-down,
3841
/// or the button that was released in the case of mouse-up.
3942
/// This will always be `MouseButton::None` in the case of mouse-move.

druid-shell/src/platform/gtk/window.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ impl WindowBuilder {
296296
buttons: get_mouse_buttons_from_modifiers(button_state).with(button),
297297
mods: get_modifiers(button_state),
298298
count: get_mouse_click_count(event.get_event_type()),
299+
focus: false,
299300
button,
300301
},
301302
);
@@ -319,6 +320,7 @@ impl WindowBuilder {
319320
buttons: get_mouse_buttons_from_modifiers(button_state).without(button),
320321
mods: get_modifiers(button_state),
321322
count: 0,
323+
focus: false,
322324
button,
323325
},
324326
);
@@ -339,6 +341,7 @@ impl WindowBuilder {
339341
buttons: get_mouse_buttons_from_modifiers(motion_state),
340342
mods: get_modifiers(motion_state),
341343
count: 0,
344+
focus: false,
342345
button: MouseButton::None,
343346
};
344347

@@ -360,6 +363,7 @@ impl WindowBuilder {
360363
buttons: get_mouse_buttons_from_modifiers(crossing_state),
361364
mods: get_modifiers(crossing_state),
362365
count: 0,
366+
focus: false,
363367
button: MouseButton::None,
364368
};
365369

druid-shell/src/platform/mac/window.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ struct ViewState {
104104
handler: Box<dyn WinHandler>,
105105
idle_queue: Arc<Mutex<Vec<IdleKind>>>,
106106
last_mods: KeyModifiers,
107+
/// Tracks window focusing left clicks
108+
focus_click: bool,
107109
}
108110

109111
impl WindowBuilder {
@@ -232,11 +234,17 @@ lazy_static! {
232234
extern "C" fn acceptsFirstResponder(_this: &Object, _sel: Sel) -> BOOL {
233235
YES
234236
}
237+
// acceptsFirstMouse is called when a left mouse click would focus the window
235238
decl.add_method(
236239
sel!(acceptsFirstMouse:),
237240
acceptsFirstMouse as extern "C" fn(&Object, Sel, id) -> BOOL,
238241
);
239-
extern "C" fn acceptsFirstMouse(_this: &Object, _sel: Sel, _nsevent: id) -> BOOL {
242+
extern "C" fn acceptsFirstMouse(this: &Object, _sel: Sel, _nsevent: id) -> BOOL {
243+
unsafe {
244+
let view_state: *mut c_void = *this.get_ivar("viewState");
245+
let view_state = &mut *(view_state as *mut ViewState);
246+
view_state.focus_click = true;
247+
}
240248
YES
241249
}
242250
decl.add_method(sel!(dealloc), dealloc as extern "C" fn(&Object, Sel));
@@ -346,6 +354,7 @@ fn make_view(handler: Box<dyn WinHandler>) -> (id, Weak<Mutex<Vec<IdleKind>>>) {
346354
handler,
347355
idle_queue,
348356
last_mods: KeyModifiers::default(),
357+
focus_click: false,
349358
};
350359
let state_ptr = Box::into_raw(Box::new(state));
351360
(*view).set_ivar("viewState", state_ptr as *mut c_void);
@@ -367,7 +376,7 @@ extern "C" fn set_frame_size(this: &mut Object, _: Sel, size: NSSize) {
367376
}
368377
}
369378

370-
fn mouse_event(nsevent: id, view: id, count: u8, button: MouseButton) -> MouseEvent {
379+
fn mouse_event(nsevent: id, view: id, count: u8, focus: bool, button: MouseButton) -> MouseEvent {
371380
unsafe {
372381
let point = nsevent.locationInWindow();
373382
let view_point = view.convertPoint_fromView_(point, nil);
@@ -379,6 +388,7 @@ fn mouse_event(nsevent: id, view: id, count: u8, button: MouseButton) -> MouseEv
379388
buttons,
380389
mods: modifiers,
381390
count,
391+
focus,
382392
button,
383393
}
384394
}
@@ -436,7 +446,8 @@ fn mouse_down(this: &mut Object, nsevent: id, button: MouseButton) {
436446
let view_state: *mut c_void = *this.get_ivar("viewState");
437447
let view_state = &mut *(view_state as *mut ViewState);
438448
let count = nsevent.clickCount() as u8;
439-
let event = mouse_event(nsevent, this as id, count, button);
449+
let focus = view_state.focus_click && button == MouseButton::Left;
450+
let event = mouse_event(nsevent, this as id, count, focus, button);
440451
(*view_state).handler.mouse_down(&event);
441452
}
442453
}
@@ -461,7 +472,13 @@ fn mouse_up(this: &mut Object, nsevent: id, button: MouseButton) {
461472
unsafe {
462473
let view_state: *mut c_void = *this.get_ivar("viewState");
463474
let view_state = &mut *(view_state as *mut ViewState);
464-
let event = mouse_event(nsevent, this as id, 0, button);
475+
let focus = if view_state.focus_click && button == MouseButton::Left {
476+
view_state.focus_click = false;
477+
true
478+
} else {
479+
false
480+
};
481+
let event = mouse_event(nsevent, this as id, 0, focus, button);
465482
(*view_state).handler.mouse_up(&event);
466483
}
467484
}
@@ -470,7 +487,7 @@ extern "C" fn mouse_move(this: &mut Object, _: Sel, nsevent: id) {
470487
unsafe {
471488
let view_state: *mut c_void = *this.get_ivar("viewState");
472489
let view_state = &mut *(view_state as *mut ViewState);
473-
let event = mouse_event(nsevent, this as id, 0, MouseButton::None);
490+
let event = mouse_event(nsevent, this as id, 0, false, MouseButton::None);
474491
(*view_state).handler.mouse_move(&event);
475492
}
476493
}

druid-shell/src/platform/web/window.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ fn setup_mouse_down_callback(ws: &Rc<WindowState>) {
147147
buttons,
148148
mods: get_modifiers!(event),
149149
count: 1,
150+
focus: false,
150151
button,
151152
};
152153
state.handler.borrow_mut().mouse_down(&event);
@@ -164,6 +165,7 @@ fn setup_mouse_up_callback(ws: &Rc<WindowState>) {
164165
buttons,
165166
mods: get_modifiers!(event),
166167
count: 0,
168+
focus: false,
167169
button,
168170
};
169171
state.handler.borrow_mut().mouse_up(&event);
@@ -180,6 +182,7 @@ fn setup_mouse_move_callback(ws: &Rc<WindowState>) {
180182
buttons,
181183
mods: get_modifiers!(event),
182184
count: 0,
185+
focus: false,
183186
button: MouseButton::None,
184187
};
185188
state.handler.borrow_mut().mouse_move(&event);

druid-shell/src/platform/windows/window.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,7 @@ impl WndProc for MyWndProc {
728728
buttons,
729729
mods,
730730
count: 0,
731+
focus: false,
731732
button: MouseButton::None,
732733
};
733734
s.handler.mouse_move(&event);
@@ -794,6 +795,7 @@ impl WndProc for MyWndProc {
794795
buttons,
795796
mods,
796797
count,
798+
focus: false,
797799
button,
798800
};
799801
if count > 0 {

druid-shell/src/platform/x11/window.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,7 @@ impl Window {
565565
meta: false,
566566
},
567567
count: 1,
568+
focus: false,
568569
button: MouseButton::Left,
569570
};
570571
match self.handler.try_borrow_mut() {
@@ -597,6 +598,7 @@ impl Window {
597598
meta: false,
598599
},
599600
count: 0,
601+
focus: false,
600602
button: MouseButton::Left,
601603
};
602604
match self.handler.try_borrow_mut() {
@@ -629,6 +631,7 @@ impl Window {
629631
meta: false,
630632
},
631633
count: 0,
634+
focus: false,
632635
button: MouseButton::None,
633636
};
634637
match self.handler.try_borrow_mut() {

druid/src/mouse.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ pub struct MouseEvent {
3636
/// The number of mouse clicks associated with this event. This will always
3737
/// be `0` for a mouse-up and mouse-move events.
3838
pub count: u8,
39+
/// Focus is `true` on macOS when the mouse-down event (or its companion mouse-up event)
40+
/// with `MouseButton::Left` was the event that caused the window to gain focus.
41+
///
42+
/// This is primarily used in relation to text selection.
43+
/// If there is some text selected in some text widget and it receives a click
44+
/// with `focus` set to `true` then the widget should gain focus (i.e. start blinking a cursor)
45+
/// but it should not change the text selection. Text selection should only be changed
46+
/// when the click has `focus` set to `false`.
47+
pub focus: bool,
3948
/// The button that was pressed down in the case of mouse-down,
4049
/// or the button that was released in the case of mouse-up.
4150
/// This will always be `MouseButton::None` in the case of mouse-move.
@@ -49,6 +58,7 @@ impl From<druid_shell::MouseEvent> for MouseEvent {
4958
buttons,
5059
mods,
5160
count,
61+
focus,
5262
button,
5363
} = src;
5464
MouseEvent {
@@ -57,6 +67,7 @@ impl From<druid_shell::MouseEvent> for MouseEvent {
5767
buttons,
5868
mods,
5969
count,
70+
focus,
6071
button,
6172
}
6273
}

druid/src/tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ fn propogate_hot() {
7979
buttons: MouseButtons::default(),
8080
mods: KeyModifiers::default(),
8181
count: 0,
82+
focus: false,
8283
button: MouseButton::None,
8384
}
8485
}

druid/src/widget/textbox.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -243,12 +243,14 @@ impl Widget<String> for TextBox {
243243
ctx.request_focus();
244244
ctx.set_active(true);
245245

246-
let cursor_offset = self.offset_for_point(mouse.pos, &text_layout);
247-
edit_action = Some(EditAction::Click(MouseAction {
248-
row: 0,
249-
column: cursor_offset,
250-
mods: mouse.mods,
251-
}));
246+
if !mouse.focus {
247+
let cursor_offset = self.offset_for_point(mouse.pos, &text_layout);
248+
edit_action = Some(EditAction::Click(MouseAction {
249+
row: 0,
250+
column: cursor_offset,
251+
mods: mouse.mods,
252+
}));
253+
}
252254

253255
ctx.request_paint();
254256
}

0 commit comments

Comments
 (0)