Skip to content

Commit 7b88c32

Browse files
committed
feat: Basic hotplug support
UI currently freezes for a bit when a keyboard is connected.
1 parent 1586831 commit 7b88c32

File tree

2 files changed

+52
-3
lines changed

2 files changed

+52
-3
lines changed

backend/src/board.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ impl Board {
116116
self.inner().daemon.as_ref()
117117
}
118118

119-
pub(crate) fn board(&self) -> BoardId {
119+
pub fn board(&self) -> BoardId {
120120
*self.inner().board
121121
}
122122

src/application/main_window.rs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,28 @@ use cascade::cascade;
22
use glib::clone;
33
use gtk::prelude::*;
44
use gtk::subclass::prelude::*;
5-
use std::rc::Rc;
6-
use std::sync::atomic::{AtomicUsize, Ordering};
5+
use std::{
6+
cell::RefCell,
7+
collections::HashSet,
8+
rc::Rc,
9+
sync::atomic::{AtomicUsize, Ordering},
10+
};
711

812
use super::{shortcuts_window, ConfiguratorApp, Keyboard, KeyboardLayer, Page, Picker};
913
use crate::DerefCell;
1014
use backend::{Board, Daemon, DaemonClient, DaemonDummy, DaemonServer};
1115

1216
#[derive(Default)]
1317
pub struct MainWindowInner {
18+
daemon: DerefCell<Rc<dyn Daemon>>,
1419
back_button: DerefCell<gtk::Button>,
1520
count: AtomicUsize,
1621
header_bar: DerefCell<gtk::HeaderBar>,
1722
keyboard_list_box: DerefCell<gtk::ListBox>,
1823
layer_switcher: DerefCell<gtk::StackSwitcher>,
1924
picker: DerefCell<Picker>,
2025
stack: DerefCell<gtk::Stack>,
26+
keyboards: RefCell<Vec<(Keyboard, gtk::ListBoxRow)>>,
2127
}
2228

2329
#[glib::object_subclass]
@@ -182,6 +188,48 @@ impl MainWindow {
182188
}
183189
}
184190

191+
window.inner().daemon.set(daemon);
192+
glib::timeout_add_seconds_local(
193+
1,
194+
clone!(@weak window => move || {
195+
let daemon = &*window.inner().daemon;
196+
197+
if let Err(err) = daemon.refresh() {
198+
error!("Failed to refresh boards: {}", err);
199+
}
200+
201+
let boards = match daemon.boards() {
202+
Ok(boards) => boards,
203+
Err(_) => return glib::Continue(true),
204+
};
205+
206+
// Remove boards that aren't detected now
207+
let mut ids = HashSet::new();
208+
window.inner().keyboards.borrow_mut().retain(|(keyboard, row)| {
209+
let board = keyboard.board().board();
210+
ids.insert(board);
211+
if boards.iter().find(|i| **i == board).is_none() {
212+
window.inner().stack.remove(keyboard);
213+
window.inner().keyboard_list_box.remove(row);
214+
return false;
215+
}
216+
true
217+
});
218+
219+
// Add new boards
220+
for i in boards {
221+
if !ids.contains(&i) {
222+
match Board::new(daemon.clone(), i) {
223+
Ok(board) => window.add_keyboard(board),
224+
Err(err) => error!("{}", err),
225+
}
226+
}
227+
}
228+
229+
glib::Continue(true)
230+
}),
231+
);
232+
185233
window
186234
}
187235

@@ -263,6 +311,7 @@ impl MainWindow {
263311
self.inner().keyboard_list_box.add(&row);
264312

265313
self.inner().stack.add(&keyboard);
314+
self.inner().keyboards.borrow_mut().push((keyboard, row));
266315

267316
// XXX if only one keyboard, show that with no back button
268317
self.inner().count.fetch_add(1, Ordering::Relaxed);

0 commit comments

Comments
 (0)