Skip to content

Commit 6d5b130

Browse files
committed
snowcap: add touch_area widget
This new widget allows the config to be touched aware. While there is a primitive support in iced widget, it's currently buggy, and doesn't allow to distinguish between fingers inputs and mouse inputs, meaning it's not possible to use that data to e.g. initiate a grab.
1 parent c80d5de commit 6d5b130

6 files changed

Lines changed: 584 additions & 1 deletion

File tree

snowcap/api/lua/snowcap/grpc/defs.lua

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,7 @@ local snowcap_popup_v1_Gravity = {
801801
---@field input_region snowcap.widget.v1.InputRegion?
802802
---@field mouse_area snowcap.widget.v1.MouseArea?
803803
---@field text_input snowcap.widget.v1.TextInput?
804+
---@field touch_area snowcap.widget.v1.TouchArea?
804805

805806
---@class snowcap.widget.v1.Text
806807
---@field text string?
@@ -1021,6 +1022,39 @@ local snowcap_popup_v1_Gravity = {
10211022
---@field submit google.protobuf.Empty?
10221023
---@field paste string?
10231024

1025+
---@class snowcap.widget.v1.TouchArea
1026+
---@field child snowcap.widget.v1.WidgetDef?
1027+
---@field widget_id integer?
1028+
---@field on_down boolean?
1029+
---@field on_up boolean?
1030+
---@field on_enter boolean?
1031+
---@field on_move boolean?
1032+
---@field on_exit boolean?
1033+
---@field on_cancel boolean?
1034+
1035+
---@class snowcap.widget.v1.TouchArea.Event
1036+
---@field down snowcap.widget.v1.TouchArea.DownEvent?
1037+
---@field up snowcap.widget.v1.TouchArea.Finger?
1038+
---@field enter snowcap.widget.v1.TouchArea.Finger?
1039+
---@field move snowcap.widget.v1.TouchArea.MoveEvent?
1040+
---@field exit snowcap.widget.v1.TouchArea.Finger?
1041+
---@field cancel snowcap.widget.v1.TouchArea.Finger?
1042+
1043+
---@class snowcap.widget.v1.TouchArea.Finger
1044+
---@field id integer?
1045+
1046+
---@class snowcap.widget.v1.TouchArea.Point
1047+
---@field x number?
1048+
---@field y number?
1049+
1050+
---@class snowcap.widget.v1.TouchArea.DownEvent
1051+
---@field finger snowcap.widget.v1.TouchArea.Finger?
1052+
---@field point snowcap.widget.v1.TouchArea.Point?
1053+
1054+
---@class snowcap.widget.v1.TouchArea.MoveEvent
1055+
---@field finger snowcap.widget.v1.TouchArea.Finger?
1056+
---@field point snowcap.widget.v1.TouchArea.Point?
1057+
10241058
---@class snowcap.widget.v1.GetWidgetEventsRequest
10251059
---@field layer_id integer?
10261060
---@field decoration_id integer?
@@ -1031,6 +1065,7 @@ local snowcap_popup_v1_Gravity = {
10311065
---@field button snowcap.widget.v1.Button.Event?
10321066
---@field mouse_area snowcap.widget.v1.MouseArea.Event?
10331067
---@field text_input snowcap.widget.v1.TextInput.Event?
1068+
---@field touch_area snowcap.widget.v1.TouchArea.Event?
10341069

10351070
---@class snowcap.widget.v1.GetWidgetEventsResponse
10361071
---@field widget_events snowcap.widget.v1.WidgetEvent[]?
@@ -1427,6 +1462,12 @@ snowcap.widget.v1.TextInput.Icon = {}
14271462
snowcap.widget.v1.TextInput.Style = {}
14281463
snowcap.widget.v1.TextInput.Style.Inner = {}
14291464
snowcap.widget.v1.TextInput.Event = {}
1465+
snowcap.widget.v1.TouchArea = {}
1466+
snowcap.widget.v1.TouchArea.Event = {}
1467+
snowcap.widget.v1.TouchArea.Finger = {}
1468+
snowcap.widget.v1.TouchArea.Point = {}
1469+
snowcap.widget.v1.TouchArea.DownEvent = {}
1470+
snowcap.widget.v1.TouchArea.MoveEvent = {}
14301471
snowcap.widget.v1.GetWidgetEventsRequest = {}
14311472
snowcap.widget.v1.WidgetEvent = {}
14321473
snowcap.widget.v1.GetWidgetEventsResponse = {}

snowcap/api/protobuf/snowcap/widget/v1/widget.proto

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ message WidgetDef {
168168
InputRegion input_region = 9;
169169
MouseArea mouse_area = 10;
170170
TextInput text_input = 11;
171+
TouchArea touch_area = 12;
171172
}
172173
}
173174

@@ -463,6 +464,47 @@ message TextInput {
463464
}
464465
}
465466

467+
message TouchArea {
468+
WidgetDef child = 1;
469+
optional uint32 widget_id = 2;
470+
bool on_down = 3;
471+
bool on_up = 4;
472+
bool on_enter = 5;
473+
bool on_move = 6;
474+
bool on_exit = 7;
475+
bool on_cancel = 8;
476+
477+
message Event {
478+
oneof data {
479+
DownEvent down = 1;
480+
Finger up = 2;
481+
Finger enter = 3;
482+
MoveEvent move = 4;
483+
Finger exit = 5;
484+
Finger cancel = 6;
485+
}
486+
}
487+
488+
message Finger {
489+
uint32 id = 1;
490+
}
491+
492+
message Point {
493+
float x = 1;
494+
float y = 2;
495+
}
496+
497+
message DownEvent {
498+
Finger finger = 1;
499+
Point point = 2;
500+
}
501+
502+
message MoveEvent {
503+
Finger finger = 1;
504+
Point point = 2;
505+
}
506+
}
507+
466508
message GetWidgetEventsRequest {
467509
oneof id {
468510
uint32 layer_id = 1;
@@ -478,6 +520,7 @@ message WidgetEvent {
478520
Button.Event button = 2;
479521
MouseArea.Event mouse_area = 3;
480522
TextInput.Event text_input = 4;
523+
TouchArea.Event touch_area = 5;
481524
}
482525
}
483526

snowcap/api/rust/src/widget.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ where
142142
WidgetMessage::TextInput(callbacks) => callbacks.process_event(event.into()),
143143
_ => unreachable!(),
144144
}),
145+
Event::TouchArea(_) => todo!(),
145146
}
146147
}
147148

snowcap/src/api/widget/v1.rs

Lines changed: 136 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ use crate::{
1717
layer::LayerId,
1818
popup::PopupId,
1919
util::convert::{FromApi, TryFromApi},
20-
widget::{MouseAreaEvent, TextInputEvent, ViewFn, WidgetEvent, WidgetId},
20+
widget::{
21+
MouseAreaEvent, TextInputEvent, TouchAreaEvent, ViewFn, WidgetEvent, WidgetId, touch_area,
22+
},
2123
};
2224

2325
#[tonic::async_trait]
@@ -67,6 +69,9 @@ impl widget_service_server::WidgetService for super::WidgetService {
6769
WidgetEvent::TextInput(evt) => {
6870
widget_event::Event::TextInput(evt.into())
6971
}
72+
WidgetEvent::TouchArea(evt) => {
73+
widget_event::Event::TouchArea(evt.into())
74+
}
7075
}),
7176
})
7277
.collect(),
@@ -994,6 +999,89 @@ pub fn widget_def_to_fn(def: WidgetDef) -> Option<ViewFn> {
994999
text_input.into()
9951000
});
9961001

1002+
Some(f)
1003+
}
1004+
widget_def::Widget::TouchArea(touch_area) => {
1005+
let widget::v1::TouchArea {
1006+
child,
1007+
widget_id,
1008+
on_down,
1009+
on_up,
1010+
on_enter,
1011+
on_move,
1012+
on_exit,
1013+
on_cancel,
1014+
} = *touch_area;
1015+
1016+
let child_widget_fn = child.and_then(|def| widget_def_to_fn(*def));
1017+
1018+
let f: ViewFn = Box::new(move || {
1019+
let mut touch_area = touch_area::TouchArea::new(
1020+
child_widget_fn
1021+
.as_ref()
1022+
.map(|child| child())
1023+
.unwrap_or_else(|| iced::widget::Text::new("NULL").into()),
1024+
);
1025+
1026+
if let Some(widget_id) = widget_id {
1027+
if on_down {
1028+
touch_area = touch_area.on_down(move |id, pos| {
1029+
crate::widget::SnowcapMessage::WidgetEvent(
1030+
WidgetId(widget_id),
1031+
WidgetEvent::TouchArea(TouchAreaEvent::Down(id, pos)),
1032+
)
1033+
});
1034+
}
1035+
1036+
if on_up {
1037+
touch_area = touch_area.on_up(move |id| {
1038+
crate::widget::SnowcapMessage::WidgetEvent(
1039+
WidgetId(widget_id),
1040+
WidgetEvent::TouchArea(TouchAreaEvent::Up(id)),
1041+
)
1042+
});
1043+
}
1044+
1045+
if on_enter {
1046+
touch_area = touch_area.on_enter(move |id| {
1047+
crate::widget::SnowcapMessage::WidgetEvent(
1048+
WidgetId(widget_id),
1049+
WidgetEvent::TouchArea(TouchAreaEvent::Enter(id)),
1050+
)
1051+
});
1052+
}
1053+
1054+
if on_move {
1055+
touch_area = touch_area.on_move(move |id, pos| {
1056+
crate::widget::SnowcapMessage::WidgetEvent(
1057+
WidgetId(widget_id),
1058+
WidgetEvent::TouchArea(TouchAreaEvent::Move(id, pos)),
1059+
)
1060+
});
1061+
}
1062+
1063+
if on_exit {
1064+
touch_area = touch_area.on_exit(move |id| {
1065+
crate::widget::SnowcapMessage::WidgetEvent(
1066+
WidgetId(widget_id),
1067+
WidgetEvent::TouchArea(TouchAreaEvent::Exit(id)),
1068+
)
1069+
});
1070+
}
1071+
1072+
if on_cancel {
1073+
touch_area = touch_area.on_cancel(move |id| {
1074+
crate::widget::SnowcapMessage::WidgetEvent(
1075+
WidgetId(widget_id),
1076+
WidgetEvent::TouchArea(TouchAreaEvent::Cancel(id)),
1077+
)
1078+
});
1079+
}
1080+
}
1081+
1082+
touch_area.into()
1083+
});
1084+
9971085
Some(f)
9981086
}
9991087
}
@@ -1469,3 +1557,50 @@ impl FromApi<widget::v1::text_input::Style> for crate::widget::text_input::Style
14691557
}
14701558
}
14711559
}
1560+
1561+
impl From<TouchAreaEvent> for snowcap_api_defs::snowcap::widget::v1::touch_area::Event {
1562+
fn from(value: TouchAreaEvent) -> Self {
1563+
use snowcap_api_defs::snowcap::widget::v1::touch_area::{self, event::Data};
1564+
1565+
let data = match value {
1566+
TouchAreaEvent::Down(finger, point) => {
1567+
let down_evt = touch_area::DownEvent {
1568+
finger: Some(touch_area::Finger::from_api(finger)),
1569+
point: Some(touch_area::Point::from_api(point)),
1570+
};
1571+
1572+
Data::Down(down_evt)
1573+
}
1574+
TouchAreaEvent::Up(finger) => Data::Up(touch_area::Finger::from_api(finger)),
1575+
TouchAreaEvent::Enter(finger) => Data::Enter(touch_area::Finger::from_api(finger)),
1576+
TouchAreaEvent::Move(finger, point) => {
1577+
let down_evt = touch_area::MoveEvent {
1578+
finger: Some(touch_area::Finger::from_api(finger)),
1579+
point: Some(touch_area::Point::from_api(point)),
1580+
};
1581+
1582+
Data::Move(down_evt)
1583+
}
1584+
TouchAreaEvent::Exit(finger) => Data::Exit(touch_area::Finger::from_api(finger)),
1585+
TouchAreaEvent::Cancel(finger) => Data::Cancel(touch_area::Finger::from_api(finger)),
1586+
};
1587+
1588+
Self { data: Some(data) }
1589+
}
1590+
}
1591+
1592+
impl FromApi<iced::touch::Finger> for snowcap_api_defs::snowcap::widget::v1::touch_area::Finger {
1593+
fn from_api(api_type: iced::touch::Finger) -> Self {
1594+
Self {
1595+
id: api_type.0 as u32,
1596+
}
1597+
}
1598+
}
1599+
1600+
impl FromApi<iced::Point> for snowcap_api_defs::snowcap::widget::v1::touch_area::Point {
1601+
fn from_api(api_type: iced::Point) -> Self {
1602+
let iced::Point { x, y } = api_type;
1603+
1604+
Self { x, y }
1605+
}
1606+
}

snowcap/src/widget.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod input_region;
2+
pub mod touch_area;
23

34
use iced::{Color, Theme, event::Status};
45
use iced_graphics::Viewport;
@@ -218,6 +219,7 @@ pub enum WidgetEvent {
218219
Button,
219220
MouseArea(MouseAreaEvent),
220221
TextInput(TextInputEvent),
222+
TouchArea(TouchAreaEvent),
221223
}
222224

223225
#[derive(Debug, Clone)]
@@ -242,6 +244,16 @@ pub enum TextInputEvent {
242244
Paste(String),
243245
}
244246

247+
#[derive(Debug, Clone)]
248+
pub enum TouchAreaEvent {
249+
Down(iced::touch::Finger, iced::Point),
250+
Up(iced::touch::Finger),
251+
Enter(iced::touch::Finger),
252+
Move(iced::touch::Finger, iced::Point),
253+
Exit(iced::touch::Finger),
254+
Cancel(iced::touch::Finger),
255+
}
256+
245257
pub(crate) mod text_input {
246258
#[derive(Debug, Default, Clone)]
247259
pub(crate) struct Styles {

0 commit comments

Comments
 (0)