1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
use super::*;
impl X11Platform {
pub(super) fn handle_event(&mut self, event: XEvent) -> PlatformResult<Option<Event>> {
match event {
XEvent::MapRequest(ev) => self.manage_new_window(ev.window),
XEvent::ConfigureRequest(ev) => {
if self.xid_to_core.contains_key(&ev.window) {
// We own layout for managed clients; just ack with a
// synthetic ConfigureNotify carrying real geometry.
let geom = self.conn.get_geometry(ev.window).map_err(err)?.reply().map_err(err)?;
let notify = x11rb::protocol::xproto::ConfigureNotifyEvent {
response_type: x11rb::protocol::xproto::CONFIGURE_NOTIFY_EVENT,
sequence: 0,
event: ev.window,
window: ev.window,
above_sibling: x11rb::NONE,
x: geom.x,
y: geom.y,
width: geom.width,
height: geom.height,
border_width: 0,
override_redirect: false,
};
self.conn.send_event(false, ev.window, EventMask::STRUCTURE_NOTIFY, notify).map_err(err)?;
} else {
let aux = ConfigureWindowAux::from_configure_request(&ev);
self.conn.configure_window(ev.window, &aux).map_err(err)?;
}
self.conn.flush().map_err(err)?;
Ok(None)
}
XEvent::UnmapNotify(ev) => Ok(self.unmanage(ev.window)),
XEvent::DestroyNotify(ev) => Ok(self.unmanage(ev.window)),
XEvent::ButtonPress(ev) => {
let (x, y) = (ev.root_x as i32, ev.root_y as i32);
let hit = self.wm.borrow().hit_test(x, y);
if let Some((id, hit)) = hit {
self.raise_and_focus(id)?;
match hit {
TitlebarHit::Drag => self.wm.borrow_mut().start_drag(id, x, y),
TitlebarHit::Close => self.request_close(id)?,
TitlebarHit::Maximize => {
self.wm.borrow_mut().toggle_maximize(id);
self.sync_geometry(id)?;
}
TitlebarHit::Minimize => {
self.wm.borrow_mut().minimize_window(id);
if let Some(frame) = self.frame_for(id) {
self.conn.unmap_window(frame).map_err(err)?;
}
}
TitlebarHit::Resize(edge) => self.wm.borrow_mut().start_resize(id, edge, x, y),
}
self.conn.flush().map_err(err)?;
}
// Let the click through to the client (we grabbed it SYNC).
self.conn.allow_events(x11rb::protocol::xproto::Allow::REPLAY_POINTER, ev.time).map_err(err)?;
self.conn.flush().map_err(err)?;
Ok(Some(Event::MouseButtonPress { button: MouseButton::Left, x, y }))
}
XEvent::ButtonRelease(ev) => {
let mut wm = self.wm.borrow_mut();
let was_dragging = wm.is_dragging();
let was_resizing = wm.is_resizing();
let dragged_id = wm.focused_id();
if was_dragging {
wm.end_drag();
} else if was_resizing {
wm.end_resize();
}
drop(wm);
if was_dragging || was_resizing {
if let Some(id) = dragged_id {
self.sync_geometry(id)?;
}
}
Ok(Some(Event::MouseButtonRelease { button: MouseButton::Left, x: ev.root_x as i32, y: ev.root_y as i32 }))
}
XEvent::MotionNotify(ev) => {
let (x, y) = (ev.root_x as i32, ev.root_y as i32);
let mut wm = self.wm.borrow_mut();
let id = wm.focused_id();
if wm.is_dragging() {
wm.update_drag(x, y);
} else if wm.is_resizing() {
wm.update_resize(x, y);
} else {
return Ok(Some(Event::MouseMotion { x, y }));
}
drop(wm);
if let Some(id) = id {
self.sync_geometry(id)?;
}
Ok(Some(Event::MouseMotion { x, y }))
}
XEvent::KeyPress(ev) => {
let keysym = self.keycode_to_keysym(ev.detail);
let Some(key_name) = keysyms::keysym_to_name(keysym) else { return Ok(None) };
Ok(Some(Event::KeyPress { key_name, modifiers: Self::modifiers_from_state(ev.state.into()) }))
}
XEvent::KeyRelease(ev) => {
let keysym = self.keycode_to_keysym(ev.detail);
let Some(key_name) = keysyms::keysym_to_name(keysym) else { return Ok(None) };
Ok(Some(Event::KeyRelease { key_name, modifiers: Self::modifiers_from_state(ev.state.into()) }))
}
XEvent::Expose(ev) => {
let target = self.frames.iter().find(|(_, f)| f.frame == ev.window).map(|(&id, _)| id);
if let Some(id) = target {
let w = self.wm.borrow().window(id).cloned_for_render();
if let Some(w) = w {
let focused = self.wm.borrow().focused_id() == Some(id);
let _ = self.redraw_decoration(id, &w, focused);
}
}
Ok(None)
}
_ => Ok(None),
}
}
}
|