Skip to content

Commit c8fed14

Browse files
authored
Merge pull request #2073 from iced-rs/event-helpers
Add `keyboard` subscriptions and rename `subscription::events` to `event::listen`
2 parents a56b25b + d21f069 commit c8fed14

15 files changed

Lines changed: 208 additions & 139 deletions

File tree

examples/events/src/main.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use iced::alignment;
2+
use iced::event::{self, Event};
23
use iced::executor;
3-
use iced::subscription;
44
use iced::widget::{button, checkbox, container, text, Column};
55
use iced::window;
6-
use iced::Event;
76
use iced::{
87
Alignment, Application, Command, Element, Length, Settings, Subscription,
98
Theme,
@@ -71,7 +70,7 @@ impl Application for Events {
7170
}
7271

7372
fn subscription(&self) -> Subscription<Message> {
74-
subscription::events().map(Message::EventOccurred)
73+
event::listen().map(Message::EventOccurred)
7574
}
7675

7776
fn view(&self) -> Element<Message> {

examples/modal/src/main.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
use iced::event::{self, Event};
12
use iced::executor;
23
use iced::keyboard;
3-
use iced::subscription::{self, Subscription};
44
use iced::theme;
55
use iced::widget::{
66
self, button, column, container, horizontal_space, pick_list, row, text,
77
text_input,
88
};
9-
use iced::{Alignment, Application, Command, Element, Event, Length, Settings};
9+
use iced::{
10+
Alignment, Application, Command, Element, Length, Settings, Subscription,
11+
};
1012

1113
use modal::Modal;
1214
use std::fmt;
@@ -49,7 +51,7 @@ impl Application for App {
4951
}
5052

5153
fn subscription(&self) -> Subscription<Self::Message> {
52-
subscription::events().map(Message::Event)
54+
event::listen().map(Message::Event)
5355
}
5456

5557
fn update(&mut self, message: Message) -> Command<Message> {

examples/pane_grid/src/main.rs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use iced::alignment::{self, Alignment};
2-
use iced::event::{self, Event};
32
use iced::executor;
43
use iced::keyboard;
5-
use iced::subscription;
64
use iced::theme::{self, Theme};
75
use iced::widget::pane_grid::{self, PaneGrid};
86
use iced::widget::{
@@ -146,18 +144,12 @@ impl Application for Example {
146144
}
147145

148146
fn subscription(&self) -> Subscription<Message> {
149-
subscription::events_with(|event, status| {
150-
if let event::Status::Captured = status {
147+
keyboard::on_key_press(|key_code, modifiers| {
148+
if !modifiers.command() {
151149
return None;
152150
}
153151

154-
match event {
155-
Event::Keyboard(keyboard::Event::KeyPressed {
156-
modifiers,
157-
key_code,
158-
}) if modifiers.command() => handle_hotkey(key_code),
159-
_ => None,
160-
}
152+
handle_hotkey(key_code)
161153
})
162154
}
163155

examples/screenshot/src/main.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ use iced::theme::{Button, Container};
44
use iced::widget::{button, column, container, image, row, text, text_input};
55
use iced::window::screenshot::{self, Screenshot};
66
use iced::{
7-
event, executor, keyboard, subscription, Alignment, Application, Command,
8-
ContentFit, Element, Event, Length, Rectangle, Renderer, Subscription,
9-
Theme,
7+
event, executor, keyboard, Alignment, Application, Command, ContentFit,
8+
Element, Event, Length, Rectangle, Renderer, Subscription, Theme,
109
};
1110

1211
use ::image as img;
@@ -254,7 +253,7 @@ impl Application for Example {
254253
}
255254

256255
fn subscription(&self) -> Subscription<Self::Message> {
257-
subscription::events_with(|event, status| {
256+
event::listen_with(|event, status| {
258257
if let event::Status::Captured = status {
259258
return None;
260259
}

examples/stopwatch/src/main.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use iced::alignment;
22
use iced::executor;
3+
use iced::keyboard;
34
use iced::theme::{self, Theme};
45
use iced::time;
56
use iced::widget::{button, column, container, row, text};
@@ -77,12 +78,25 @@ impl Application for Stopwatch {
7778
}
7879

7980
fn subscription(&self) -> Subscription<Message> {
80-
match self.state {
81+
let tick = match self.state {
8182
State::Idle => Subscription::none(),
8283
State::Ticking { .. } => {
8384
time::every(Duration::from_millis(10)).map(Message::Tick)
8485
}
86+
};
87+
88+
fn handle_hotkey(
89+
key_code: keyboard::KeyCode,
90+
_modifiers: keyboard::Modifiers,
91+
) -> Option<Message> {
92+
match key_code {
93+
keyboard::KeyCode::Space => Some(Message::Toggle),
94+
keyboard::KeyCode::R => Some(Message::Reset),
95+
_ => None,
96+
}
8597
}
98+
99+
Subscription::batch(vec![tick, keyboard::on_key_press(handle_hotkey)])
86100
}
87101

88102
fn view(&self) -> Element<Message> {

examples/toast/src/main.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
use iced::event::{self, Event};
12
use iced::executor;
23
use iced::keyboard;
3-
use iced::subscription::{self, Subscription};
44
use iced::widget::{
55
self, button, column, container, pick_list, row, slider, text, text_input,
66
};
7-
use iced::{Alignment, Application, Command, Element, Event, Length, Settings};
7+
use iced::{
8+
Alignment, Application, Command, Element, Length, Settings, Subscription,
9+
};
810

911
use toast::{Status, Toast};
1012

@@ -57,7 +59,7 @@ impl Application for App {
5759
}
5860

5961
fn subscription(&self) -> Subscription<Self::Message> {
60-
subscription::events().map(Message::Event)
62+
event::listen().map(Message::Event)
6163
}
6264

6365
fn update(&mut self, message: Message) -> Command<Message> {

examples/todos/src/main.rs

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use iced::alignment::{self, Alignment};
2-
use iced::event::{self, Event};
32
use iced::font::{self, Font};
4-
use iced::keyboard::{self, KeyCode, Modifiers};
5-
use iced::subscription;
3+
use iced::keyboard;
64
use iced::theme::{self, Theme};
75
use iced::widget::{
86
self, button, checkbox, column, container, row, scrollable, text,
@@ -52,7 +50,7 @@ enum Message {
5250
FilterChanged(Filter),
5351
TaskMessage(usize, TaskMessage),
5452
TabPressed { shift: bool },
55-
ToggleFullscreen(window::Mode),
53+
ChangeWindowMode(window::Mode),
5654
}
5755

5856
impl Application for Todos {
@@ -163,7 +161,7 @@ impl Application for Todos {
163161
widget::focus_next()
164162
}
165163
}
166-
Message::ToggleFullscreen(mode) => {
164+
Message::ChangeWindowMode(mode) => {
167165
window::change_mode(mode)
168166
}
169167
_ => Command::none(),
@@ -262,33 +260,19 @@ impl Application for Todos {
262260
}
263261

264262
fn subscription(&self) -> Subscription<Message> {
265-
subscription::events_with(|event, status| match (event, status) {
266-
(
267-
Event::Keyboard(keyboard::Event::KeyPressed {
268-
key_code: keyboard::KeyCode::Tab,
269-
modifiers,
270-
..
263+
keyboard::on_key_press(|key_code, modifiers| {
264+
match (key_code, modifiers) {
265+
(keyboard::KeyCode::Tab, _) => Some(Message::TabPressed {
266+
shift: modifiers.shift(),
271267
}),
272-
event::Status::Ignored,
273-
) => Some(Message::TabPressed {
274-
shift: modifiers.shift(),
275-
}),
276-
(
277-
Event::Keyboard(keyboard::Event::KeyPressed {
278-
key_code,
279-
modifiers: Modifiers::SHIFT,
280-
}),
281-
event::Status::Ignored,
282-
) => match key_code {
283-
KeyCode::Up => {
284-
Some(Message::ToggleFullscreen(window::Mode::Fullscreen))
268+
(keyboard::KeyCode::Up, keyboard::Modifiers::SHIFT) => {
269+
Some(Message::ChangeWindowMode(window::Mode::Fullscreen))
285270
}
286-
KeyCode::Down => {
287-
Some(Message::ToggleFullscreen(window::Mode::Windowed))
271+
(keyboard::KeyCode::Down, keyboard::Modifiers::SHIFT) => {
272+
Some(Message::ChangeWindowMode(window::Mode::Windowed))
288273
}
289274
_ => None,
290-
},
291-
_ => None,
275+
}
292276
})
293277
}
294278
}

examples/url_handler/src/main.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use iced::event::{Event, MacOS, PlatformSpecific};
1+
use iced::event::{self, Event};
22
use iced::executor;
3-
use iced::subscription;
43
use iced::widget::{container, text};
54
use iced::{
65
Application, Command, Element, Length, Settings, Subscription, Theme,
@@ -37,9 +36,11 @@ impl Application for App {
3736
fn update(&mut self, message: Message) -> Command<Message> {
3837
match message {
3938
Message::EventOccurred(event) => {
40-
if let Event::PlatformSpecific(PlatformSpecific::MacOS(
41-
MacOS::ReceivedUrl(url),
42-
)) = event
39+
if let Event::PlatformSpecific(
40+
event::PlatformSpecific::MacOS(event::MacOS::ReceivedUrl(
41+
url,
42+
)),
43+
) = event
4344
{
4445
self.url = Some(url);
4546
}
@@ -50,7 +51,7 @@ impl Application for App {
5051
}
5152

5253
fn subscription(&self) -> Subscription<Message> {
53-
subscription::events().map(Message::EventOccurred)
54+
event::listen().map(Message::EventOccurred)
5455
}
5556

5657
fn view(&self) -> Element<Message> {

examples/visible_bounds/src/main.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1+
use iced::event::{self, Event};
12
use iced::executor;
23
use iced::mouse;
3-
use iced::subscription::{self, Subscription};
44
use iced::theme::{self, Theme};
55
use iced::widget::{
66
column, container, horizontal_space, row, scrollable, text, vertical_space,
77
};
88
use iced::window;
99
use iced::{
10-
Alignment, Application, Color, Command, Element, Event, Font, Length,
11-
Point, Rectangle, Settings,
10+
Alignment, Application, Color, Command, Element, Font, Length, Point,
11+
Rectangle, Settings, Subscription,
1212
};
1313

1414
pub fn main() -> iced::Result {
@@ -163,7 +163,7 @@ impl Application for Example {
163163
}
164164

165165
fn subscription(&self) -> Subscription<Message> {
166-
subscription::events_with(|event, _| match event {
166+
event::listen_with(|event, _| match event {
167167
Event::Mouse(mouse::Event::CursorMoved { position }) => {
168168
Some(Message::MouseMoved(position))
169169
}

futures/src/event.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//! Listen to runtime events.
2+
use crate::core::event::{self, Event};
3+
use crate::core::window;
4+
use crate::subscription::{self, Subscription};
5+
use crate::MaybeSend;
6+
7+
/// Returns a [`Subscription`] to all the ignored runtime events.
8+
///
9+
/// This subscription will notify your application of any [`Event`] that was
10+
/// not captured by any widget.
11+
pub fn listen() -> Subscription<Event> {
12+
listen_with(|event, status| match status {
13+
event::Status::Ignored => Some(event),
14+
event::Status::Captured => None,
15+
})
16+
}
17+
18+
/// Creates a [`Subscription`] that listens and filters all the runtime events
19+
/// with the provided function, producing messages accordingly.
20+
///
21+
/// This subscription will call the provided function for every [`Event`]
22+
/// handled by the runtime. If the function:
23+
///
24+
/// - Returns `None`, the [`Event`] will be discarded.
25+
/// - Returns `Some` message, the `Message` will be produced.
26+
pub fn listen_with<Message>(
27+
f: fn(Event, event::Status) -> Option<Message>,
28+
) -> Subscription<Message>
29+
where
30+
Message: 'static + MaybeSend,
31+
{
32+
#[derive(Hash)]
33+
struct EventsWith;
34+
35+
subscription::filter_map(
36+
(EventsWith, f),
37+
move |event, status| match event {
38+
Event::Window(window::Event::RedrawRequested(_)) => None,
39+
_ => f(event, status),
40+
},
41+
)
42+
}
43+
44+
/// Creates a [`Subscription`] that produces a message for every runtime event,
45+
/// including the redraw request events.
46+
///
47+
/// **Warning:** This [`Subscription`], if unfiltered, may produce messages in
48+
/// an infinite loop.
49+
pub fn listen_raw<Message>(
50+
f: fn(Event, event::Status) -> Option<Message>,
51+
) -> Subscription<Message>
52+
where
53+
Message: 'static + MaybeSend,
54+
{
55+
#[derive(Hash)]
56+
struct RawEvents;
57+
58+
subscription::filter_map((RawEvents, f), f)
59+
}

0 commit comments

Comments
 (0)