Feature-flag WM clients

pull/39/head
Takashi Kokubun 2 years ago
parent ecfdcb8de5
commit 4b251b1fce
No known key found for this signature in database
GPG Key ID: 6FFC433B12EE23DD

@ -13,4 +13,8 @@ lazy_static = "1.4.0"
nix = "0.23.1"
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.8"
x11 = { version = "2.19.1", features = ["xlib"] }
x11_rs = { package = "x11", version = "2.19.1", features = ["xlib"] }
[features]
sway = []
x11 = []

@ -1,2 +1,43 @@
pub mod x11_client;
pub mod sway_client;
#[cfg(feature = "sway")]
mod sway_client;
#[cfg(feature = "x11")]
mod x11_client;
#[cfg(not(any(feature = "sway", feature = "x11")))]
mod null_client;
trait Client {
fn current_wm_class(&mut self) -> Option<String>;
}
pub struct WMClient {
client: Box<dyn Client>,
}
impl WMClient {
pub fn current_wm_class(&mut self) -> Option<String> {
self.client.current_wm_class()
}
}
#[cfg(feature = "sway")]
pub fn build_client() -> WMClient {
WMClient {
client: Box::new(sway_client::SwayClient::new()),
}
}
#[cfg(feature = "x11")]
pub fn build_client() -> WMClient {
WMClient {
client: Box::new(x11_client::X11Client::new()),
}
}
#[cfg(not(any(feature = "sway", feature = "x11")))]
pub fn build_client() -> WMClient {
WMClient {
client: Box::new(null_client::NullClient::new()),
}
}

@ -0,0 +1,21 @@
use crate::client::Client;
pub struct NullClient {
called: bool,
}
impl NullClient {
pub fn new() -> NullClient {
NullClient { called: false }
}
}
impl Client for NullClient {
fn current_wm_class(&mut self) -> Option<String> {
if !self.called {
self.called = true;
println!("NullClient.supported = false");
}
None
}
}

@ -1,3 +1,4 @@
use crate::client::Client;
use std::fs::read_dir;
use std::os::unix::ffi::OsStrExt;
use std::os::unix::net::UnixStream;
@ -16,23 +17,27 @@ impl SwayClient {
}
}
pub fn supported(&mut self) -> bool {
fn supported(&mut self) -> bool {
match self.supported {
Some(supported) => supported,
None => {
self.supported = Some(false);
let mut supported = false;
if let Some(socket) = find_socket() {
if let Ok(unix_stream) = UnixStream::connect(socket) {
self.connection = Some(Connection(unix_stream));
self.supported = Some(true);
supported = true;
}
}
self.supported.unwrap()
println!("SwayClient.supported = {}", supported);
self.supported = Some(supported);
supported
}
}
}
}
pub fn current_wm_class(&mut self) -> Option<String> {
impl Client for SwayClient {
fn current_wm_class(&mut self) -> Option<String> {
if !self.supported() {
return None;
}
@ -44,7 +49,7 @@ impl SwayClient {
if let Ok(node) = connection.get_tree() {
if let Some(node) = node.find_focused(|n| n.focused) {
return node.app_id
return node.app_id;
}
}
None
@ -60,7 +65,7 @@ fn find_socket() -> Option<String> {
if let Some(fname) = path.file_name() {
if fname.as_bytes().starts_with(b"sway-ipc.") {
if let Ok(path) = path.into_os_string().into_string() {
return Some(path)
return Some(path);
}
}
}

@ -1,6 +1,9 @@
use crate::client::Client;
use x11_rs::xlib;
pub struct X11Client {
// Both of them are lazily initialized
display: Option<*mut x11::xlib::Display>,
display: Option<*mut xlib::Display>,
supported: Option<bool>,
last_wm_class: String,
}
@ -14,7 +17,7 @@ impl X11Client {
}
}
pub fn supported(&mut self) -> bool {
fn supported(&mut self) -> bool {
match self.supported {
Some(supported) => supported,
None => {
@ -24,7 +27,7 @@ impl X11Client {
} else {
let mut focused_window = 0;
let mut focus_state = 0;
unsafe { x11::xlib::XGetInputFocus(display, &mut focused_window, &mut focus_state) };
unsafe { xlib::XGetInputFocus(display, &mut focused_window, &mut focus_state) };
focused_window > 0
};
println!("X11Client.supported = {}", supported);
@ -34,7 +37,20 @@ impl X11Client {
}
}
pub fn current_wm_class(&mut self) -> Option<String> {
fn display(&mut self) -> *mut xlib::Display {
match self.display {
Some(display) => display,
None => {
let display = unsafe { xlib::XOpenDisplay(std::ptr::null()) };
self.display = Some(display);
display
}
}
}
}
impl Client for X11Client {
fn current_wm_class(&mut self) -> Option<String> {
if !self.supported() {
return None;
}
@ -42,18 +58,18 @@ impl X11Client {
let display = self.display();
let mut focused_window = 0;
let mut focus_state = 0;
unsafe { x11::xlib::XGetInputFocus(display, &mut focused_window, &mut focus_state) };
unsafe { xlib::XGetInputFocus(display, &mut focused_window, &mut focus_state) };
let mut x_class_hint = x11::xlib::XClassHint {
let mut x_class_hint = xlib::XClassHint {
res_name: std::ptr::null_mut(),
res_class: std::ptr::null_mut(),
};
let mut wm_class = String::new();
loop {
unsafe {
if x11::xlib::XGetClassHint(display, focused_window, &mut x_class_hint) == 1 {
if xlib::XGetClassHint(display, focused_window, &mut x_class_hint) == 1 {
if !x_class_hint.res_name.is_null() {
x11::xlib::XFree(x_class_hint.res_name as *mut std::ffi::c_void);
xlib::XFree(x_class_hint.res_name as *mut std::ffi::c_void);
}
if !x_class_hint.res_class.is_null() {
@ -70,11 +86,11 @@ impl X11Client {
}
let mut nchildren: u32 = 0;
let mut root: x11::xlib::Window = 0;
let mut parent: x11::xlib::Window = 0;
let mut children: *mut x11::xlib::Window = &mut 0;
let mut root: xlib::Window = 0;
let mut parent: xlib::Window = 0;
let mut children: *mut xlib::Window = &mut 0;
unsafe {
if x11::xlib::XQueryTree(
if xlib::XQueryTree(
display,
focused_window,
&mut root,
@ -88,7 +104,7 @@ impl X11Client {
}
if !children.is_null() {
unsafe {
x11::xlib::XFree(children as *mut std::ffi::c_void);
xlib::XFree(children as *mut std::ffi::c_void);
}
}
@ -105,15 +121,4 @@ impl X11Client {
}
Some(wm_class)
}
fn display(&mut self) -> *mut x11::xlib::Display {
match self.display {
Some(display) => display,
None => {
let display = unsafe { x11::xlib::XOpenDisplay(std::ptr::null()) };
self.display = Some(display);
display
}
}
}
}

@ -1,4 +1,4 @@
use crate::client::x11_client::X11Client;
use crate::client::{build_client, WMClient};
use crate::config::action::Action;
use crate::config::key_press::{KeyPress, Modifier};
use crate::config::wm_class::WMClass;
@ -11,7 +11,7 @@ use std::error::Error;
pub struct EventHandler {
device: VirtualDevice,
x11_client: X11Client,
wm_client: WMClient,
override_remap: Option<HashMap<KeyPress, Vec<Action>>>,
wm_class_cache: Option<String>,
shift: PressState,
@ -24,7 +24,7 @@ impl EventHandler {
pub fn new(device: VirtualDevice) -> EventHandler {
EventHandler {
device,
x11_client: X11Client::new(),
wm_client: build_client(),
override_remap: None,
wm_class_cache: None,
shift: PressState::new(false),
@ -213,7 +213,7 @@ impl EventHandler {
fn match_wm_class(&mut self, wm_class_matcher: &WMClass) -> bool {
// Lazily fill the wm_class cache
if let None = self.wm_class_cache {
match self.x11_client.current_wm_class() {
match self.wm_client.current_wm_class() {
Some(wm_class) => self.wm_class_cache = Some(wm_class),
None => self.wm_class_cache = Some(String::new()),
}

@ -3,7 +3,6 @@ use crate::input::{event_loop, select_device};
use getopts::Options;
use std::env;
use std::process::exit;
use crate::client::sway_client::SwayClient;
extern crate getopts;
@ -24,10 +23,6 @@ fn abort(message: &str) -> ! {
}
fn main() {
let mut client = SwayClient::new();
println!("supported: {}", client.supported());
println!("active: {:?}", client.current_wm_class());
let argv: Vec<String> = env::args().collect();
let program = argv[0].clone();

Loading…
Cancel
Save