Mercurial > tablet-emu
annotate src/main.rs @ 5:cdbf3a2c9af8
Add a very simple menu.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Sun, 01 Nov 2020 14:34:02 +0100 |
parents | 2e074d185151 |
children | dd10331549c6 |
rev | line source |
---|---|
0 | 1 use gio::prelude::*; |
2 use gtk::prelude::*; | |
5
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
3 use glib::clone; |
0 | 4 |
5 use std::env::args; | |
6 use std::fs::{File, OpenOptions}; | |
7 use std::io::ErrorKind; | |
8 use std::sync::{Arc, Mutex}; | |
9 | |
10 use input_linux::{ | |
11 sys::input_event, sys::timeval, AbsoluteAxis, AbsoluteInfo, AbsoluteInfoSetup, EventKind, | |
1
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
12 InputId, InputProperty, Key, MiscKind, SynchronizeKind, UInputHandle, |
0 | 13 }; |
14 | |
15 const WIDTH: i32 = 320; | |
16 const HEIGHT: i32 = 180; | |
17 | |
18 const MAX_X: i32 = 69920; | |
19 const MAX_Y: i32 = 39980; | |
20 | |
21 fn create_uinput_device() -> std::io::Result<UInputHandle<File>> { | |
22 let file = OpenOptions::new().write(true).open("/dev/uinput")?; | |
23 let dev = UInputHandle::new(file); | |
24 | |
25 dev.set_evbit(EventKind::Synchronize)?; | |
26 dev.set_evbit(EventKind::Key)?; | |
27 dev.set_evbit(EventKind::Absolute)?; | |
28 dev.set_evbit(EventKind::Misc)?; | |
29 dev.set_keybit(Key::ButtonToolPen)?; | |
30 dev.set_keybit(Key::ButtonToolRubber)?; | |
31 dev.set_keybit(Key::ButtonToolBrush)?; | |
32 dev.set_keybit(Key::ButtonToolPencil)?; | |
33 dev.set_keybit(Key::ButtonToolAirbrush)?; | |
34 dev.set_keybit(Key::ButtonTouch)?; | |
35 dev.set_keybit(Key::ButtonStylus)?; | |
36 dev.set_keybit(Key::ButtonStylus2)?; | |
37 dev.set_keybit(Key::ButtonStylus3)?; | |
38 dev.set_mscbit(MiscKind::Serial)?; | |
39 dev.set_propbit(InputProperty::Direct)?; | |
40 | |
41 dev.set_absbit(AbsoluteAxis::X)?; | |
42 dev.set_absbit(AbsoluteAxis::Y)?; | |
43 dev.set_absbit(AbsoluteAxis::Z)?; | |
44 dev.set_absbit(AbsoluteAxis::Wheel)?; | |
45 dev.set_absbit(AbsoluteAxis::Pressure)?; | |
46 dev.set_absbit(AbsoluteAxis::Distance)?; | |
47 dev.set_absbit(AbsoluteAxis::TiltX)?; | |
48 dev.set_absbit(AbsoluteAxis::TiltY)?; | |
49 dev.set_absbit(AbsoluteAxis::Misc)?; | |
50 | |
51 let id = InputId { | |
52 bustype: 3, | |
53 vendor: 0x56a, | |
54 product: 0x350, | |
55 version: 0xb, | |
56 }; | |
57 | |
58 let x = AbsoluteInfoSetup { | |
59 axis: AbsoluteAxis::X, | |
60 info: AbsoluteInfo { | |
61 value: 0, | |
62 minimum: 0, | |
63 maximum: MAX_X, | |
64 fuzz: 0, | |
65 flat: 0, | |
66 resolution: 200, | |
67 }, | |
68 }; | |
69 let y = AbsoluteInfoSetup { | |
70 axis: AbsoluteAxis::Y, | |
71 info: AbsoluteInfo { | |
72 value: 0, | |
73 minimum: 0, | |
74 maximum: MAX_Y, | |
75 fuzz: 0, | |
76 flat: 0, | |
77 resolution: 200, | |
78 }, | |
79 }; | |
80 let z = AbsoluteInfoSetup { | |
81 axis: AbsoluteAxis::Z, | |
82 info: AbsoluteInfo { | |
83 value: 0, | |
84 minimum: -900, | |
85 maximum: 899, | |
86 fuzz: 0, | |
87 flat: 0, | |
88 resolution: 287, | |
89 }, | |
90 }; | |
91 let wheel = AbsoluteInfoSetup { | |
92 axis: AbsoluteAxis::Wheel, | |
93 info: AbsoluteInfo { | |
94 value: 0, | |
95 minimum: 0, | |
96 maximum: 2047, | |
97 fuzz: 0, | |
98 flat: 0, | |
99 resolution: 0, | |
100 }, | |
101 }; | |
102 let pressure = AbsoluteInfoSetup { | |
103 axis: AbsoluteAxis::Pressure, | |
104 info: AbsoluteInfo { | |
105 value: 0, | |
106 minimum: 0, | |
107 maximum: 8196, | |
108 fuzz: 0, | |
109 flat: 0, | |
110 resolution: 0, | |
111 }, | |
112 }; | |
113 let distance = AbsoluteInfoSetup { | |
114 axis: AbsoluteAxis::Distance, | |
115 info: AbsoluteInfo { | |
116 value: 0, | |
117 minimum: 0, | |
118 maximum: 63, | |
119 fuzz: 0, | |
120 flat: 0, | |
121 resolution: 0, | |
122 }, | |
123 }; | |
124 let tilt_x = AbsoluteInfoSetup { | |
125 axis: AbsoluteAxis::TiltX, | |
126 info: AbsoluteInfo { | |
127 value: 0, | |
128 minimum: -64, | |
129 maximum: 63, | |
130 fuzz: 0, | |
131 flat: 0, | |
132 resolution: 57, | |
133 }, | |
134 }; | |
135 let tilt_y = AbsoluteInfoSetup { | |
136 axis: AbsoluteAxis::TiltY, | |
137 info: AbsoluteInfo { | |
138 value: 0, | |
139 minimum: -64, | |
140 maximum: 63, | |
141 fuzz: 0, | |
142 flat: 0, | |
143 resolution: 57, | |
144 }, | |
145 }; | |
146 let misc = AbsoluteInfoSetup { | |
147 axis: AbsoluteAxis::Misc, | |
148 info: AbsoluteInfo { | |
149 value: 0, | |
150 minimum: 0, | |
151 maximum: 0, | |
152 fuzz: 0, | |
153 flat: 0, | |
154 resolution: 0, | |
155 }, | |
156 }; | |
157 | |
158 dev.create( | |
159 &id, | |
160 b"TabletEmu", | |
161 0, | |
162 &[x, y, z, wheel, pressure, distance, tilt_x, tilt_y, misc], | |
163 )?; | |
164 Ok(dev) | |
165 } | |
166 | |
1
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
167 fn input_event_new(type_: EventKind, code: u16, value: i32) -> input_event { |
0 | 168 input_event { |
169 time: timeval { | |
170 tv_sec: 0, | |
171 tv_usec: 0, | |
172 }, | |
173 type_: type_ as u16, | |
1
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
174 code, |
0 | 175 value, |
176 } | |
177 } | |
178 | |
1
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
179 fn input_axis_new(code: AbsoluteAxis, value: i32) -> input_event { |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
180 input_event_new(EventKind::Absolute, code as u16, value) |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
181 } |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
182 |
2
39f87ef69b2a
Add support for selecting tools.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
183 fn input_key_new(code: Key, value: i32) -> input_event { |
39f87ef69b2a
Add support for selecting tools.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
184 input_event_new(EventKind::Key, code as u16, value) |
39f87ef69b2a
Add support for selecting tools.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
185 } |
39f87ef69b2a
Add support for selecting tools.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
186 |
1
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
187 fn input_misc_new(code: MiscKind, value: i32) -> input_event { |
2
39f87ef69b2a
Add support for selecting tools.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
188 input_event_new(EventKind::Misc, code as u16, value) |
1
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
189 } |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
190 |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
191 fn input_synchronize_new(code: SynchronizeKind, value: i32) -> input_event { |
2
39f87ef69b2a
Add support for selecting tools.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
192 input_event_new(EventKind::Synchronize, code as u16, value) |
1
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
193 } |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
194 |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
195 struct State { |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
196 dev: UInputHandle<File>, |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
197 width: f64, |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
198 height: f64, |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
199 selected_tool: Key, |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
200 pressed: bool, |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
201 } |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
202 |
0 | 203 fn build_ui(application: >k::Application) { |
5
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
204 let quit = gio::SimpleAction::new("quit", None); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
205 application.set_accels_for_action("app.quit", &["<Control>q"]); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
206 application.add_action(&quit); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
207 quit.connect_activate(clone!(@weak application => move |_, _| application.quit())); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
208 |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
209 let about = gio::SimpleAction::new("about", None); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
210 application.add_action(&about); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
211 about.connect_activate(|_, _| { |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
212 let about = gtk::AboutDialog::new(); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
213 about.set_program_name("TabletEmu"); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
214 about.set_logo_icon_name(Some("input-tablet")); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
215 about.set_website(Some("https://hg.linkmauve.fr/tablet-emu")); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
216 about.set_version(Some("0.1")); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
217 about.set_license_type(gtk::License::Agpl30); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
218 about.set_program_name("TabletEmu"); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
219 about.run(); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
220 unsafe { about.destroy(); } |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
221 }); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
222 |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
223 let menu = gio::Menu::new(); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
224 { |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
225 let file = gio::Menu::new(); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
226 file.append(Some("_Quit"), Some("app.quit")); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
227 menu.append_submenu(Some("_File"), &file); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
228 } |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
229 { |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
230 let help = gio::Menu::new(); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
231 help.append(Some("_About"), Some("app.about")); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
232 menu.append_submenu(Some("_Help"), &help); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
233 } |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
234 application.set_menubar(Some(&menu)); |
cdbf3a2c9af8
Add a very simple menu.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
4
diff
changeset
|
235 |
0 | 236 let dev = match create_uinput_device() { |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
237 Ok(dev) => dev, |
0 | 238 Err(err) => { |
239 match err.kind() { | |
240 ErrorKind::NotFound => { | |
241 eprintln!("Couldn’t find /dev/uinput: {}", err); | |
242 eprintln!("Maybe you forgot to `modprobe uinput`?"); | |
243 } | |
244 ErrorKind::PermissionDenied => { | |
245 eprintln!("Couldn’t open /dev/uinput for writing: {}", err); | |
246 eprintln!("Maybe you aren’t allowed to create input devices?"); | |
247 } | |
248 _ => eprintln!("Couldn’t open /dev/uinput for writing: {}", err), | |
249 } | |
250 return; | |
251 } | |
252 }; | |
253 println!( | |
254 "New device at {:?} ({:?})", | |
255 dev.evdev_path().unwrap(), | |
256 dev.sys_path().unwrap() | |
257 ); | |
258 | |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
259 let state = Arc::new(Mutex::new(State { |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
260 dev, |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
261 width: WIDTH as f64, |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
262 height: HEIGHT as f64, |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
263 selected_tool: Key::ButtonToolPen, |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
264 pressed: false, |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
265 })); |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
266 |
0 | 267 let window = gtk::ApplicationWindow::new(application); |
268 | |
269 window.set_title("tablet-emu"); | |
270 window.set_position(gtk::WindowPosition::Center); | |
271 | |
272 let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 0); | |
273 let tools_box = gtk::Box::new(gtk::Orientation::Vertical, 0); | |
274 | |
4
2e074d185151
Simplify tool buttons.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
3
diff
changeset
|
275 macro_rules! impl_tool { |
2e074d185151
Simplify tool buttons.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
3
diff
changeset
|
276 ($tool:tt) => { |
2e074d185151
Simplify tool buttons.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
3
diff
changeset
|
277 let tool = gtk::Button::with_label($tool); |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
278 let state_weak = Arc::downgrade(&state); |
4
2e074d185151
Simplify tool buttons.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
3
diff
changeset
|
279 tool.connect_clicked(move |b| { |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
280 let state = state_weak.upgrade().unwrap(); |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
281 let mut state = state.lock().unwrap(); |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
282 state.selected_tool = match b.get_label().unwrap().as_str() { |
2
39f87ef69b2a
Add support for selecting tools.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
283 "Pen" => Key::ButtonToolPen, |
39f87ef69b2a
Add support for selecting tools.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
284 "Rubber" => Key::ButtonToolRubber, |
39f87ef69b2a
Add support for selecting tools.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
285 "Brush" => Key::ButtonToolBrush, |
39f87ef69b2a
Add support for selecting tools.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
286 "Pencil" => Key::ButtonToolPencil, |
39f87ef69b2a
Add support for selecting tools.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
287 "Airbrush" => Key::ButtonToolAirbrush, |
39f87ef69b2a
Add support for selecting tools.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
288 _ => unreachable!(), |
39f87ef69b2a
Add support for selecting tools.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
289 }; |
0 | 290 }); |
4
2e074d185151
Simplify tool buttons.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
3
diff
changeset
|
291 tools_box.add(&tool); |
0 | 292 }; |
293 }; | |
4
2e074d185151
Simplify tool buttons.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
3
diff
changeset
|
294 impl_tool!("Pen"); |
2e074d185151
Simplify tool buttons.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
3
diff
changeset
|
295 impl_tool!("Rubber"); |
2e074d185151
Simplify tool buttons.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
3
diff
changeset
|
296 impl_tool!("Brush"); |
2e074d185151
Simplify tool buttons.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
3
diff
changeset
|
297 impl_tool!("Pencil"); |
2e074d185151
Simplify tool buttons.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
3
diff
changeset
|
298 impl_tool!("Airbrush"); |
0 | 299 |
300 let drawing_area = gtk::DrawingArea::new(); | |
301 drawing_area.set_size_request(WIDTH, HEIGHT); | |
302 drawing_area.set_hexpand(true); | |
303 drawing_area.set_events( | |
304 gdk::EventMask::BUTTON_PRESS_MASK | |
305 | gdk::EventMask::BUTTON_RELEASE_MASK | |
306 | gdk::EventMask::POINTER_MOTION_MASK, | |
307 ); | |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
308 let state_weak = Arc::downgrade(&state); |
0 | 309 drawing_area.connect_configure_event(move |_, event| { |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
310 let state = state_weak.upgrade().unwrap(); |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
311 let mut state = state.lock().unwrap(); |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
312 match event.get_size() { |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
313 (width, height) => { |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
314 state.width = width as f64; |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
315 state.height = height as f64; |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
316 } |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
317 } |
0 | 318 true |
319 }); | |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
320 let state_weak = Arc::downgrade(&state); |
0 | 321 drawing_area.connect_button_press_event(move |_, event| { |
322 if event.get_button() != 1 { | |
323 return Inhibit(false); | |
324 } | |
325 | |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
326 let state = state_weak.upgrade().unwrap(); |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
327 let mut state = state.lock().unwrap(); |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
328 state.pressed = true; |
0 | 329 let (x, y) = event.get_position(); |
2
39f87ef69b2a
Add support for selecting tools.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
330 //println!("press tool {} at {}, {}", current_tool.lock().unwrap(), x, y); |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
331 state.dev.write(&[ |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
332 input_axis_new(AbsoluteAxis::X, (x * MAX_X as f64 / state.width) as i32), |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
333 input_axis_new(AbsoluteAxis::Y, (y * MAX_Y as f64 / state.height) as i32), |
1
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
334 input_axis_new(AbsoluteAxis::Z, 0), |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
335 input_axis_new(AbsoluteAxis::Wheel, 0), |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
336 input_axis_new(AbsoluteAxis::Pressure, 1024), |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
337 input_axis_new(AbsoluteAxis::Distance, 0), |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
338 input_axis_new(AbsoluteAxis::TiltX, 16), |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
339 input_axis_new(AbsoluteAxis::TiltY, 0), |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
340 input_misc_new(MiscKind::Serial, 0), |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
341 input_key_new(state.selected_tool, 1), |
1
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
342 input_synchronize_new(SynchronizeKind::Report, 0), |
0 | 343 ]) |
344 .unwrap(); | |
345 Inhibit(false) | |
346 }); | |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
347 let state_weak = Arc::downgrade(&state); |
0 | 348 drawing_area.connect_button_release_event(move |_, event| { |
349 if event.get_button() != 1 { | |
350 return Inhibit(false); | |
351 } | |
352 | |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
353 let state = state_weak.upgrade().unwrap(); |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
354 let mut state = state.lock().unwrap(); |
0 | 355 let (x, y) = event.get_position(); |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
356 state.pressed = false; |
0 | 357 //println!("release {}, {}", x, y); |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
358 state.dev.write(&[ |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
359 input_axis_new(AbsoluteAxis::X, (x * MAX_X as f64 / state.width) as i32), |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
360 input_axis_new(AbsoluteAxis::Y, (y * MAX_Y as f64 / state.height) as i32), |
1
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
361 input_axis_new(AbsoluteAxis::Z, 0), |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
362 input_axis_new(AbsoluteAxis::Wheel, 0), |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
363 input_axis_new(AbsoluteAxis::Pressure, 0), |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
364 input_axis_new(AbsoluteAxis::Distance, 16), |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
365 input_axis_new(AbsoluteAxis::TiltX, 16), |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
366 input_axis_new(AbsoluteAxis::TiltY, 0), |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
367 input_misc_new(MiscKind::Serial, 0), |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
368 input_key_new(state.selected_tool, 1), |
1
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
369 input_synchronize_new(SynchronizeKind::Report, 0), |
0 | 370 ]) |
371 .unwrap(); | |
372 Inhibit(false) | |
373 }); | |
374 drawing_area.connect_motion_notify_event(move |_, event| { | |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
375 let state = state.lock().unwrap(); |
0 | 376 let (x, y) = event.get_position(); |
377 //println!("motion {}, {}", x, y); | |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
378 state.dev.write(&[ |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
379 input_axis_new(AbsoluteAxis::X, (x * MAX_X as f64 / state.width) as i32), |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
380 input_axis_new(AbsoluteAxis::Y, (y * MAX_Y as f64 / state.height) as i32), |
1
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
381 input_axis_new(AbsoluteAxis::Z, 0), |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
382 input_axis_new(AbsoluteAxis::Wheel, 0), |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
383 input_axis_new(AbsoluteAxis::Pressure, if state.pressed { 2048 } else { 0 }), |
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
384 input_axis_new(AbsoluteAxis::Distance, if state.pressed { 0 } else { 32 }), |
1
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
385 input_axis_new(AbsoluteAxis::TiltX, 16), |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
386 input_axis_new(AbsoluteAxis::TiltY, 0), |
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
387 input_misc_new(MiscKind::Serial, 0), |
3
72e63d6a3f8a
Simplify state handling into a single struct.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
388 input_key_new(state.selected_tool, 1), |
1
6dbe2bbeef70
Improve input event types with helper functions.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
389 input_synchronize_new(SynchronizeKind::Report, 0), |
0 | 390 ]) |
391 .unwrap(); | |
392 Inhibit(false) | |
393 }); | |
394 drawing_area.connect_draw(move |_, ctx| { | |
395 //println!("drawing {}", drawing_area); | |
396 ctx.set_source_rgb(1., 0., 0.); | |
397 ctx.set_operator(cairo::Operator::Screen); | |
398 ctx.paint(); | |
399 Inhibit(false) | |
400 }); | |
401 | |
402 hbox.add(&tools_box); | |
403 hbox.add(&drawing_area); | |
404 | |
405 window.add(&hbox); | |
406 | |
407 window.show_all(); | |
408 } | |
409 | |
410 fn main() { | |
411 let application = gtk::Application::new( | |
412 Some("fr.linkmauve.TabletEmu"), | |
413 gio::ApplicationFlags::empty(), | |
414 ) | |
415 .expect("Initialisation failed…"); | |
416 application.connect_activate(build_ui); | |
417 application.run(&args().collect::<Vec<_>>()); | |
418 } |