|
|
|
@ -4,7 +4,10 @@ use x11rb::{
|
|
|
|
|
connect,
|
|
|
|
|
connection::Connection,
|
|
|
|
|
protocol::{
|
|
|
|
|
xproto::{Atom, AtomEnum, ChangeWindowAttributesAux, ConnectionExt, EventMask, Window, InputFocus},
|
|
|
|
|
xproto::{
|
|
|
|
|
Atom, AtomEnum, ChangeWindowAttributesAux, ClientMessageData, ClientMessageEvent,
|
|
|
|
|
ConnectionExt, EventMask, Window, CLIENT_MESSAGE_EVENT, InputFocus,
|
|
|
|
|
},
|
|
|
|
|
Event,
|
|
|
|
|
},
|
|
|
|
|
rust_connection::RustConnection,
|
|
|
|
@ -14,9 +17,7 @@ use crate::{Bounds, UnderlayEvent};
|
|
|
|
|
|
|
|
|
|
const WM_NAME_BUFSIZE: u32 = 512;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static TARGET: AtomicPtr<Arc<Mutex<Window>>> =
|
|
|
|
|
AtomicPtr::new(std::ptr::null_mut());
|
|
|
|
|
static TARGET: AtomicPtr<Arc<Mutex<Window>>> = AtomicPtr::new(std::ptr::null_mut());
|
|
|
|
|
|
|
|
|
|
struct Target {
|
|
|
|
|
title: String,
|
|
|
|
@ -38,35 +39,34 @@ struct AtomCollection {
|
|
|
|
|
impl AtomCollection {
|
|
|
|
|
fn new(conn: &RustConnection) -> Option<Self> {
|
|
|
|
|
Some(Self {
|
|
|
|
|
net_active_window: Self::_get(conn, "_NET_ACTIVE_WINDOW")?,
|
|
|
|
|
net_wm_name: Self::_get(conn, "_NET_WM_NAME")?,
|
|
|
|
|
utf8_string: Self::_get(conn, "UTF8_STRING")?,
|
|
|
|
|
net_wm_state: Self::_get(conn, "_NET_WM_STATE")?,
|
|
|
|
|
net_wm_state_fullscreen: Self::_get(conn, "_NET_WM_STATE_FULLSCREEN")?,
|
|
|
|
|
net_active_window: get_atom(conn, "_NET_ACTIVE_WINDOW")?,
|
|
|
|
|
net_wm_name: get_atom(conn, "_NET_WM_NAME")?,
|
|
|
|
|
utf8_string: get_atom(conn, "UTF8_STRING")?,
|
|
|
|
|
net_wm_state: get_atom(conn, "_NET_WM_STATE")?,
|
|
|
|
|
net_wm_state_fullscreen: get_atom(conn, "_NET_WM_STATE_FULLSCREEN")?,
|
|
|
|
|
// net_wm_state_skip_taskbar: Self::_get(conn, "_NET_WM_STATE_SKIP_TASKBAR")?,
|
|
|
|
|
// net_wm_state_skip_pager: Self::_get(conn, "_NET_WM_STATE_SKIP_PAGER")?,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn _get<T: Into<String>>(conn: &RustConnection, name: T) -> Option<Atom> {
|
|
|
|
|
Some(
|
|
|
|
|
conn.intern_atom(false, name.into().as_bytes())
|
|
|
|
|
.ok()?
|
|
|
|
|
.reply()
|
|
|
|
|
.ok()?
|
|
|
|
|
.atom,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
fn get_atom<T: Into<String>>(conn: &RustConnection, name: T) -> Option<Atom> {
|
|
|
|
|
Some(
|
|
|
|
|
conn.intern_atom(false, name.into().as_bytes())
|
|
|
|
|
.ok()?
|
|
|
|
|
.reply()
|
|
|
|
|
.ok()?
|
|
|
|
|
.atom,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn focus_target() {
|
|
|
|
|
unsafe {
|
|
|
|
|
if let Ok(target) =
|
|
|
|
|
(*TARGET.load(std::sync::atomic::Ordering::Relaxed)).lock()
|
|
|
|
|
{
|
|
|
|
|
if let Ok(target) = (*TARGET.load(std::sync::atomic::Ordering::Relaxed)).lock() {
|
|
|
|
|
if *target != x11rb::NONE {
|
|
|
|
|
if let Ok((conn, _)) = connect(None) {
|
|
|
|
|
if let Ok((conn, screen_num)) = connect(None) {
|
|
|
|
|
conn.set_input_focus(InputFocus::PARENT, *target, x11rb::CURRENT_TIME).ok();
|
|
|
|
|
conn.flush().ok();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -107,9 +107,7 @@ impl Runtime {
|
|
|
|
|
fn set_target(&mut self, wid: Window) {
|
|
|
|
|
self.target.wid = wid;
|
|
|
|
|
unsafe {
|
|
|
|
|
if let Ok(mut target) =
|
|
|
|
|
(*TARGET.load(std::sync::atomic::Ordering::Relaxed)).lock()
|
|
|
|
|
{
|
|
|
|
|
if let Ok(mut target) = (*TARGET.load(std::sync::atomic::Ordering::Relaxed)).lock() {
|
|
|
|
|
*target = wid;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -390,6 +388,11 @@ pub fn init(
|
|
|
|
|
|
|
|
|
|
runtime.conn.flush().ok();
|
|
|
|
|
|
|
|
|
|
TARGET.store(
|
|
|
|
|
Box::into_raw(Box::new(Arc::new(Mutex::new(x11rb::NONE)))),
|
|
|
|
|
std::sync::atomic::Ordering::Relaxed,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
log::trace!("Initialized, listning for events");
|
|
|
|
|
while let Ok(event) = runtime.conn.wait_for_event() {
|
|
|
|
|
log::trace!("Got event");
|
|
|
|
|