summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortcmal <me@aria.rip>2024-06-27 00:13:33 +0100
committertcmal <me@aria.rip>2024-06-27 00:13:33 +0100
commit112d094b9b2b549208d94af372a2526bfac009fd (patch)
treef42e6776dd6b40a1b5624129c416cc30afbfbc0e
parentbc641d4a0b5dde80c751feb9bf3403fefd2cbb50 (diff)
send take focus event
-rw-r--r--src/clients/mod.rs16
-rw-r--r--src/conn_info/mod.rs50
2 files changed, 54 insertions, 12 deletions
diff --git a/src/clients/mod.rs b/src/clients/mod.rs
index 823a501..76c30bb 100644
--- a/src/clients/mod.rs
+++ b/src/clients/mod.rs
@@ -10,7 +10,8 @@ use xcb::{
x::{
self, ChangeProperty, ConfigWindow, ConfigureNotifyEvent, ConfigureRequestEvent,
ConfigureWindow, DeleteProperty, DestroyNotifyEvent, Drawable, EventMask, GetGeometry,
- GetWindowAttributes, InputFocus, MapRequestEvent, SetInputFocus, UnmapNotifyEvent, Window,
+ GetWindowAttributes, InputFocus, MapRequestEvent, PropMode, SetInputFocus,
+ UnmapNotifyEvent, Window,
},
xinerama::{self},
BaseEvent, Extension,
@@ -257,16 +258,19 @@ impl ClientState {
new.set_border(conn, conn.colours.border_focused());
new.set_urgent(false);
if !new.never_focus() {
- // XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
conn.send_request(&SetInputFocus {
revert_to: InputFocus::PointerRoot,
focus: new.window(),
time: x::CURRENT_TIME,
});
- // XChangeProperty(dpy, root, netatom[NetActiveWindow],
- // XA_WINDOW, 32, PropModeReplace,
- // (unsigned char *) &(c->win), 1);
- // TODO: sendevent(c, wmatom[WMTakeFocus]);
+ conn.send_request(&ChangeProperty {
+ window: conn.root(),
+ mode: PropMode::Replace,
+ property: conn.atoms.net_active_window,
+ r#type: x::ATOM_WINDOW,
+ data: &[new.window()],
+ });
+ conn.send_event(new.window(), conn.atoms.wm_take_focus);
}
} else {
conn.send_request(&SetInputFocus {
diff --git a/src/conn_info/mod.rs b/src/conn_info/mod.rs
index 7bf09ba..ce7934b 100644
--- a/src/conn_info/mod.rs
+++ b/src/conn_info/mod.rs
@@ -3,10 +3,11 @@
use std::fmt::Debug;
use xcb::{
x::{
- self, ChangeProperty, ChangeWindowAttributes, CreateWindow, DeleteProperty, DestroyWindow,
- Window, WindowClass,
+ self, Atom, ChangeProperty, ChangeWindowAttributes, ClientMessageData, ClientMessageEvent,
+ CreateWindow, DeleteProperty, DestroyWindow, EventMask, GetProperty, SendEvent,
+ SendEventDest, Window, WindowClass,
},
- Connection as RawConnection, VoidCookieChecked,
+ Connection as RawConnection, VoidCookieChecked, Xid,
};
#[doc(hidden)]
@@ -161,10 +162,10 @@ impl<'a> Connection<'a> {
Ok(Self {
colours: Colours::new_with(conn, screen.default_colormap())?,
- atoms: Atoms::intern_all(conn)?,
- cursors: Cursors::new_with(conn)?,
+ atoms,
+ cursors,
keyboard_state: KeyboardInfo::new_with(conn)?,
- check_window: conn.generate_id(),
+ check_window,
conn,
screen_num,
root: screen.root(),
@@ -177,6 +178,43 @@ impl<'a> Connection<'a> {
Ok(())
}
+ /// Send event to window `w`, if the event is supported.
+ pub fn send_event(&self, window: Window, event: Atom) {
+ let Ok(protocols) = self.wait_for_reply(self.send_request(&GetProperty {
+ delete: false,
+ window,
+ property: self.atoms.wm_protocols,
+ r#type: x::ATOM_ATOM,
+ long_offset: 0,
+ long_length: 100000,
+ })) else {
+ return;
+ };
+
+ if protocols.r#type() != x::ATOM_ATOM || protocols.format() != 32 {
+ return;
+ }
+
+ let supported = protocols
+ .value::<u32>()
+ .iter()
+ .find(|a| **a == event.resource_id())
+ .is_some();
+
+ if supported {
+ self.send_request(&SendEvent {
+ propagate: false,
+ destination: SendEventDest::Window(window),
+ event_mask: EventMask::NO_EVENT,
+ event: &ClientMessageEvent::new(
+ window,
+ self.atoms.wm_protocols,
+ ClientMessageData::Data32([event.resource_id(), x::CURRENT_TIME, 0, 0, 0]),
+ ),
+ });
+ }
+ }
+
/// Delegate for [`RawConnection::send_request`]
pub fn send_request<R>(&self, req: &R) -> R::Cookie
where