From 112d094b9b2b549208d94af372a2526bfac009fd Mon Sep 17 00:00:00 2001 From: tcmal Date: Thu, 27 Jun 2024 00:13:33 +0100 Subject: send take focus event --- src/clients/mod.rs | 16 ++++++++++------ src/conn_info/mod.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 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::() + .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(&self, req: &R) -> R::Cookie where -- cgit v1.2.3