Skip to content

Commit a9313d0

Browse files
committed
Use CursorGrab for panning in Game of Life example
1 parent 585d970 commit a9313d0

File tree

1 file changed

+50
-25
lines changed

1 file changed

+50
-25
lines changed

examples/game_of_life/src/main.rs

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ impl GameOfLife {
6464
match message {
6565
Message::Grid(message, version) => {
6666
if version == self.version {
67-
self.grid.update(message);
67+
return self.grid.update(message).discard();
6868
}
6969
}
7070
Message::Tick | Message::Next => {
@@ -195,6 +195,9 @@ mod grid {
195195
use iced::widget::canvas;
196196
use iced::widget::canvas::event::{self, Event};
197197
use iced::widget::canvas::{Cache, Canvas, Frame, Geometry, Path, Text};
198+
use iced::window;
199+
use iced::window::CursorGrab;
200+
use iced::Task;
198201
use iced::{
199202
Color, Element, Fill, Point, Rectangle, Renderer, Size, Theme, Vector,
200203
};
@@ -219,6 +222,7 @@ mod grid {
219222
pub enum Message {
220223
Populate(Cell),
221224
Unpopulate(Cell),
225+
Panning(bool),
222226
Translated(Vector),
223227
Scaled(f32, Option<Vector>),
224228
Ticked {
@@ -282,7 +286,7 @@ mod grid {
282286
})
283287
}
284288

285-
pub fn update(&mut self, message: Message) {
289+
pub fn update(&mut self, message: Message) -> Task<Message> {
286290
match message {
287291
Message::Populate(cell) => {
288292
self.state.populate(cell);
@@ -296,6 +300,22 @@ mod grid {
296300

297301
self.preset = Preset::Custom;
298302
}
303+
Message::Panning(panning) => {
304+
#[cfg(any(target_os = "linux", target_os = "windows"))]
305+
let cursor_grab = CursorGrab::Confined;
306+
#[cfg(any(target_os = "macos", target_arch = "wasm32"))]
307+
let cursor_grab = CursorGrab::Locked;
308+
return window::get_oldest().then(move |id| {
309+
window::cursor_grab(
310+
id.expect("there is only a single window so it must be the oldest"),
311+
if panning {
312+
cursor_grab
313+
} else {
314+
CursorGrab::None
315+
},
316+
)
317+
});
318+
}
299319
Message::Translated(translation) => {
300320
self.translation = translation;
301321

@@ -327,6 +347,8 @@ mod grid {
327347
dbg!(error);
328348
}
329349
}
350+
351+
Task::none()
330352
}
331353

332354
pub fn view(&self) -> Element<Message> {
@@ -379,13 +401,17 @@ mod grid {
379401

380402
fn update(
381403
&self,
382-
interaction: &mut Interaction,
404+
mut interaction: &mut Interaction,
383405
event: Event,
384406
bounds: Rectangle,
385407
cursor: mouse::Cursor,
386408
) -> (event::Status, Option<Message>) {
387409
if let Event::Mouse(mouse::Event::ButtonReleased(_)) = event {
388410
*interaction = Interaction::None;
411+
return (
412+
event::Status::Captured,
413+
Some(Message::Panning(false)),
414+
);
389415
}
390416

391417
let Some(cursor_position) = cursor.position_in(bounds) else {
@@ -430,36 +456,35 @@ mod grid {
430456
mouse::Button::Right => {
431457
*interaction = Interaction::Panning {
432458
translation: self.translation,
433-
start: cursor_position,
434459
};
435460

436-
None
461+
Some(Message::Panning(true))
437462
}
438463
_ => None,
439464
};
440465

441466
(event::Status::Captured, message)
442467
}
443-
mouse::Event::CursorMoved { .. } => {
444-
let message = match *interaction {
445-
Interaction::Drawing => populate,
446-
Interaction::Erasing => unpopulate,
447-
Interaction::Panning { translation, start } => {
448-
Some(Message::Translated(
449-
translation
450-
+ (cursor_position - start)
451-
* (1.0 / self.scaling),
452-
))
468+
mouse::Event::CursorMoved { .. } => match *interaction {
469+
Interaction::Drawing => {
470+
(event::Status::Captured, populate)
471+
}
472+
Interaction::Erasing => {
473+
(event::Status::Captured, unpopulate)
474+
}
475+
_ => (event::Status::Ignored, None),
476+
},
477+
mouse::Event::MouseMotion { delta } => {
478+
match &mut interaction {
479+
Interaction::Panning { translation } => {
480+
*translation += delta / self.scaling;
481+
(
482+
event::Status::Captured,
483+
Some(Message::Translated(*translation)),
484+
)
453485
}
454-
Interaction::None => None,
455-
};
456-
457-
let event_status = match interaction {
458-
Interaction::None => event::Status::Ignored,
459-
_ => event::Status::Captured,
460-
};
461-
462-
(event_status, message)
486+
_ => (event::Status::Ignored, None),
487+
}
463488
}
464489
mouse::Event::WheelScrolled { delta } => match delta {
465490
mouse::ScrollDelta::Lines { y, .. }
@@ -881,7 +906,7 @@ mod grid {
881906
None,
882907
Drawing,
883908
Erasing,
884-
Panning { translation: Vector, start: Point },
909+
Panning { translation: Vector },
885910
}
886911

887912
impl Default for Interaction {

0 commit comments

Comments
 (0)