Read config from xdg directory
This commit is contained in:
parent
39a888c7ba
commit
c5ca08f556
8 changed files with 86 additions and 172 deletions
|
@ -19,6 +19,7 @@ serde = { version = "1.0", features = ["derive"] }
|
||||||
|
|
||||||
# read and parse configuration
|
# read and parse configuration
|
||||||
config = "0.13"
|
config = "0.13"
|
||||||
|
shellexpand = "2.1"
|
||||||
|
|
||||||
# dependencies for building the `window` surface
|
# dependencies for building the `window` surface
|
||||||
winit = { git = "https://github.com/rust-windowing/winit" }
|
winit = { git = "https://github.com/rust-windowing/winit" }
|
||||||
|
|
28
default.toml
28
default.toml
|
@ -1,28 +0,0 @@
|
||||||
log_level = "trace"
|
|
||||||
|
|
||||||
[completions]
|
|
||||||
"e" = "emacs"
|
|
||||||
"f" = "firefox"
|
|
||||||
"t" = "xfce4-terminal"
|
|
||||||
"j" = "jetbrains"
|
|
||||||
|
|
||||||
[sources.primary]
|
|
||||||
matcher = "Prefix"
|
|
||||||
source = "Windows"
|
|
||||||
|
|
||||||
[sources.additional]
|
|
||||||
matcher = "Fuse"
|
|
||||||
source = ["Apps", "Shell", "Test"]
|
|
||||||
|
|
||||||
[theme]
|
|
||||||
font = ["Sans Regular", 13]
|
|
||||||
border = 2
|
|
||||||
divider = 3
|
|
||||||
|
|
||||||
[theme.color_scheme]
|
|
||||||
base = [0.13, 0.05, 0.23, 0.9]
|
|
||||||
border = [0.23, 0.05, 0.11, 1.0]
|
|
||||||
highlight = [0.12, 0.04, 0.08, 0.9]
|
|
||||||
divider = [0.23, 0.05, 0.11, 1.0]
|
|
||||||
text = [0.87, 0.95, 0.77, 1.0]
|
|
||||||
text_highlight = [0.6, 0.8, 0.4, 1.0]
|
|
|
@ -1,8 +1,10 @@
|
||||||
use config::Config;
|
use config::builder::DefaultState;
|
||||||
use config::ConfigError;
|
use config::ConfigError;
|
||||||
|
use config::{Config, ConfigBuilder};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Color(f64, f64, f64, f64);
|
pub struct Color(f64, f64, f64, f64);
|
||||||
|
@ -98,16 +100,27 @@ pub struct Settings {
|
||||||
|
|
||||||
impl Settings {
|
impl Settings {
|
||||||
pub fn parse() -> Result<Self, ConfigError> {
|
pub fn parse() -> Result<Self, ConfigError> {
|
||||||
let mut config: Config = Config::builder()
|
let mut config: ConfigBuilder<DefaultState> = Config::builder();
|
||||||
.add_source(config::File::with_name("default"))
|
|
||||||
.add_source(
|
|
||||||
config::Environment::with_prefix("roftl")
|
|
||||||
.ignore_empty(true)
|
|
||||||
.separator("_"),
|
|
||||||
)
|
|
||||||
.build()?;
|
|
||||||
|
|
||||||
config.try_deserialize()
|
let xdg_path_expanded = shellexpand::tilde("~/.config/roftl/config.toml");
|
||||||
|
let xdg_config_path = Path::new(xdg_path_expanded.as_ref());
|
||||||
|
let cwd_config_path = Path::new("default.toml");
|
||||||
|
|
||||||
|
if xdg_config_path.exists() {
|
||||||
|
config = config.add_source(config::File::from(xdg_config_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
if cwd_config_path.exists() {
|
||||||
|
config = config.add_source(config::File::from(cwd_config_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
config = config.add_source(
|
||||||
|
config::Environment::with_prefix("roftl")
|
||||||
|
.ignore_empty(true)
|
||||||
|
.separator("_"),
|
||||||
|
);
|
||||||
|
|
||||||
|
config.build()?.try_deserialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn primary_matcher(&self) -> Box<dyn super::shared::Matcher> {
|
pub fn primary_matcher(&self) -> Box<dyn super::shared::Matcher> {
|
||||||
|
|
|
@ -3,10 +3,8 @@ use std::collections::HashMap;
|
||||||
use super::core::shared::{Entry, Source};
|
use super::core::shared::{Entry, Source};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use winit::platform::unix::x11::ffi::Connection;
|
use winit::platform::unix::x11::ffi::Connection;
|
||||||
use xcb::x::{InputFocus, CURRENT_TIME};
|
|
||||||
use xcb::{Xid, XidNew};
|
use xcb::{Xid, XidNew};
|
||||||
use xcb_wm::ewmh;
|
use xcb_wm::ewmh;
|
||||||
use xcb_wm::ewmh::proto::{GetActiveWindow, GetWmDesktop};
|
|
||||||
use xcb_wm::icccm;
|
use xcb_wm::icccm;
|
||||||
|
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
|
@ -21,11 +19,15 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_normal_window(&self, con: &ewmh::Connection, window: xcb::x::Window) -> bool {
|
fn is_normal_window(&self, con: &ewmh::Connection, window: xcb::x::Window) -> bool {
|
||||||
let wm_type_request = ewmh::proto::GetWmWindowType(window);
|
let wm_type_request = ewmh::GetWmWindowType(window);
|
||||||
let wm_types = con
|
let wm_types = con
|
||||||
.wait_for_reply(con.send_request(&wm_type_request))
|
.wait_for_reply(con.send_request(&wm_type_request))
|
||||||
.window_types;
|
.window_types;
|
||||||
|
|
||||||
|
if wm_types.is_empty() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
for atom in wm_types {
|
for atom in wm_types {
|
||||||
if atom == con.atoms._NET_WM_WINDOW_TYPE_NORMAL {
|
if atom == con.atoms._NET_WM_WINDOW_TYPE_NORMAL {
|
||||||
return true;
|
return true;
|
||||||
|
@ -35,84 +37,28 @@ impl Window {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn window_category(
|
fn window_category(&self, con: &icccm::Connection, window: xcb::x::Window) -> String {
|
||||||
// &self,
|
let wm_category_request = con.send_request(&icccm::GetWmClass::new(window));
|
||||||
// con: &ewmh::Connection,
|
let wm_category = con.wait_for_reply(wm_category_request);
|
||||||
// window: u32,
|
wm_category.class
|
||||||
// ) -> Result<String, xcb::ReplyError> {
|
}
|
||||||
// Ok(icccm::get_wm_class(&con, window)
|
|
||||||
// .get_reply()?
|
|
||||||
// .class()
|
|
||||||
// .into())
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn window_title(&self, con: &ewmh::Connection, window: xcb::x::Window) -> String {
|
fn window_title(&self, con: &ewmh::Connection, window: xcb::x::Window) -> String {
|
||||||
let wm_name_request = ewmh::proto::GetWmName(window);
|
let wm_name_request = ewmh::GetWmName(window);
|
||||||
let wm_name = con.wait_for_reply(con.send_request(&wm_name_request));
|
let wm_name = con.wait_for_reply(con.send_request(&wm_name_request));
|
||||||
wm_name.name
|
wm_name.name
|
||||||
}
|
}
|
||||||
|
|
||||||
fn switch_window(&self, con: &ewmh::Connection, window: u32) {
|
fn switch_window(&self, con: &ewmh::Connection, window: u32) {
|
||||||
let change_active_window = ewmh::proto::SendActiveWindow::new(
|
let change_active_window = ewmh::SendActiveWindow::new(
|
||||||
con,
|
con,
|
||||||
unsafe { xcb::x::Window::new(window.into()) },
|
unsafe { xcb::x::Window::new(window.into()) },
|
||||||
1,
|
1,
|
||||||
xcb::x::CURRENT_TIME,
|
xcb::x::CURRENT_TIME,
|
||||||
Option::None,
|
Option::None,
|
||||||
);
|
);
|
||||||
con.send_request(&change_active_window);
|
con.send_and_check_request(&change_active_window).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn toggle_maximize_window(
|
|
||||||
// &self,
|
|
||||||
// con: &ewmh::Connection,
|
|
||||||
// window: u32,
|
|
||||||
// screen: i32,
|
|
||||||
// ) -> Result<(), xcb::ReplyError> {
|
|
||||||
// let max_horz_atom = ewmh::Connection::WM_STATE_MAXIMIZED_HORZ(con);
|
|
||||||
// let max_vert_atom = ewmh::Connection::WM_STATE_MAXIMIZED_VERT(con);
|
|
||||||
// let action_atom = ewmh::STATE_TOGGLE;
|
|
||||||
//
|
|
||||||
// debug! {"Toggle maximize for {}", window}
|
|
||||||
// ewmh::request_change_wm_state(
|
|
||||||
// con,
|
|
||||||
// screen,
|
|
||||||
// window,
|
|
||||||
// action_atom,
|
|
||||||
// max_horz_atom,
|
|
||||||
// max_vert_atom,
|
|
||||||
// 0,
|
|
||||||
// )
|
|
||||||
// .request_check()?;
|
|
||||||
//
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn close_window(
|
|
||||||
// &self,
|
|
||||||
// con: &ewmh::Connection,
|
|
||||||
// window: u32,
|
|
||||||
// screen: i32,
|
|
||||||
// ) -> Result<(), xcb::ReplyError> {
|
|
||||||
// debug! {"Toggle maximize for {}", window}
|
|
||||||
// ewmh::request_close_window(con, screen, window, XCB_CURRENT_TIME, 0).request_check()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn toggle_hide_window(
|
|
||||||
// &self,
|
|
||||||
// con: &ewmh::Connection,
|
|
||||||
// window: u32,
|
|
||||||
// screen: i32,
|
|
||||||
// ) -> Result<(), xcb::ReplyError> {
|
|
||||||
// let hidden_atom = ewmh::Connection::WM_STATE_HIDDEN(con);
|
|
||||||
// let action_atom = ewmh::STATE_TOGGLE;
|
|
||||||
//
|
|
||||||
// debug! {"Toggle hidden for {}", window}
|
|
||||||
// ewmh::request_change_wm_state(con, screen, window, action_atom, hidden_atom, 0, 0)
|
|
||||||
// .request_check()?;
|
|
||||||
//
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Source for Window {
|
impl Source for Window {
|
||||||
|
@ -123,29 +69,30 @@ impl Source for Window {
|
||||||
fn entries(&mut self) -> Vec<Entry> {
|
fn entries(&mut self) -> Vec<Entry> {
|
||||||
let (xcb_conn, screen_num) =
|
let (xcb_conn, screen_num) =
|
||||||
xcb::Connection::connect(None).expect("Could not connect to X server");
|
xcb::Connection::connect(None).expect("Could not connect to X server");
|
||||||
let ewmh_conn = ewmh::Connection::connect(&xcb_conn);
|
let ewmh_con = ewmh::Connection::connect(&xcb_conn);
|
||||||
|
let icccm_con = icccm::Connection::connect(&xcb_conn);
|
||||||
|
|
||||||
let client_list_reply = ewmh_conn.send_request(&xcb_wm::ewmh::proto::GetClientList);
|
let client_list_reply = ewmh_con.send_request(&xcb_wm::ewmh::GetClientList);
|
||||||
let windows = ewmh_conn.wait_for_reply(client_list_reply).clients;
|
let windows = ewmh_con.wait_for_reply(client_list_reply).clients;
|
||||||
|
|
||||||
let mut entries: Vec<Entry> = vec![];
|
let mut entries: Vec<Entry> = vec![];
|
||||||
|
|
||||||
let mut count: u64 = 0;
|
let mut count: u64 = 0;
|
||||||
for w in windows {
|
for w in windows {
|
||||||
match self.is_normal_window(&ewmh_conn, w) {
|
match self.is_normal_window(&ewmh_con, w) {
|
||||||
true => {}
|
true => {}
|
||||||
false => continue,
|
false => continue,
|
||||||
}
|
}
|
||||||
|
|
||||||
let title = self.window_title(&ewmh_conn, w);
|
let title = self.window_title(&ewmh_con, w);
|
||||||
let category: String = "Test".into(); //self.window_category(&ewmh_conn, *w).unwrap();
|
let category: String = self.window_category(&icccm_con, w);
|
||||||
|
|
||||||
debug!("Found window {} - {}", title, category);
|
debug!("Found window {} - {}", title, category);
|
||||||
|
|
||||||
entries.push(Entry {
|
entries.push(Entry {
|
||||||
source: self.name(),
|
source: self.name(),
|
||||||
name: title.clone(),
|
name: category,
|
||||||
description: title.clone(),
|
description: title,
|
||||||
identifier: count,
|
identifier: count,
|
||||||
});
|
});
|
||||||
self.action_data
|
self.action_data
|
||||||
|
@ -157,8 +104,17 @@ impl Source for Window {
|
||||||
entries
|
entries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn actions(&self, _entry: &Entry) -> Vec<String> {
|
||||||
|
vec![
|
||||||
|
"Switch".into(),
|
||||||
|
"Toggle maximize".into(),
|
||||||
|
"Toggle hide".into(),
|
||||||
|
"Close".into(),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
fn exec_action(&self, entry: &Entry, action: u8) {
|
fn exec_action(&self, entry: &Entry, action: u8) {
|
||||||
debug!("Doing action {:?} for entry {}", action, entry.name);
|
debug!("Executing action {:?} for entry {}", action, entry.name);
|
||||||
|
|
||||||
match action {
|
match action {
|
||||||
0 => {
|
0 => {
|
||||||
|
@ -169,47 +125,7 @@ impl Source for Window {
|
||||||
self.switch_window(&ewmh_conn, window);
|
self.switch_window(&ewmh_conn, window);
|
||||||
xcb_conn.flush().unwrap();
|
xcb_conn.flush().unwrap();
|
||||||
}
|
}
|
||||||
// 1 => {
|
|
||||||
// let (window, screen) = *self.action_data.get(&entry.identifier).unwrap();
|
|
||||||
// let (xcb_conn, _screen_num) =
|
|
||||||
// xcb::base::Connection::connect(None).expect("Could not connect to X server");
|
|
||||||
// let ewmh_conn = ewmh::Connection::connect(xcb_conn)
|
|
||||||
// .map_err(|(e, _)| e)
|
|
||||||
// .unwrap();
|
|
||||||
// self.toggle_maximize_window(&ewmh_conn, window, screen)
|
|
||||||
// .unwrap();
|
|
||||||
// self.switch_window(&ewmh_conn, window, screen).unwrap()
|
|
||||||
// }
|
|
||||||
// 2 => {
|
|
||||||
// let (window, screen) = *self.action_data.get(&entry.identifier).unwrap();
|
|
||||||
// let (xcb_conn, _screen_num) =
|
|
||||||
// xcb::base::Connection::connect(None).expect("Could not connect to X server");
|
|
||||||
// let ewmh_conn = ewmh::Connection::connect(xcb_conn)
|
|
||||||
// .map_err(|(e, _)| e)
|
|
||||||
// .unwrap();
|
|
||||||
//
|
|
||||||
// self.toggle_hide_window(&ewmh_conn, window, screen).unwrap();
|
|
||||||
// }
|
|
||||||
// 3 => {
|
|
||||||
// let (window, screen) = *self.action_data.get(&entry.identifier).unwrap();
|
|
||||||
// let (xcb_conn, _screen_num) =
|
|
||||||
// xcb::base::Connection::connect(None).expect("Could not connect to X server");
|
|
||||||
// let ewmh_conn = ewmh::Connection::connect(xcb_conn)
|
|
||||||
// .map_err(|(e, _)| e)
|
|
||||||
// .unwrap();
|
|
||||||
//
|
|
||||||
// self.close_window(&ewmh_conn, window, screen).unwrap();
|
|
||||||
// }
|
|
||||||
_ => panic! {"Unknown action {:?}", action},
|
_ => panic! {"Unknown action {:?}", action},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn actions(&self, _entry: &Entry) -> Vec<String> {
|
|
||||||
vec![
|
|
||||||
"Switch".into(),
|
|
||||||
"Toggle maximize".into(),
|
|
||||||
"Toggle hide".into(),
|
|
||||||
"Close".into(),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ impl<'a> Painter<'a> {
|
||||||
x: T,
|
x: T,
|
||||||
y: T,
|
y: T,
|
||||||
source: &'a str,
|
source: &'a str,
|
||||||
result: &'a str,
|
result: [&str; 2],
|
||||||
indices: &[usize],
|
indices: &[usize],
|
||||||
selected: bool,
|
selected: bool,
|
||||||
) where
|
) where
|
||||||
|
@ -107,10 +107,17 @@ impl<'a> Painter<'a> {
|
||||||
ctx.fill().unwrap();
|
ctx.fill().unwrap();
|
||||||
|
|
||||||
// draw text
|
// draw text
|
||||||
|
//source
|
||||||
ctx.move_to(x + 0.2, y);
|
ctx.move_to(x + 0.2, y);
|
||||||
ctx.theme_text(&source, selected, &[], &self.theme);
|
ctx.theme_text(&source, selected, &[], &self.theme);
|
||||||
|
|
||||||
|
// category
|
||||||
ctx.move_to(x + 3.5, y);
|
ctx.move_to(x + 3.5, y);
|
||||||
ctx.theme_text(&result, selected, indices, &self.theme);
|
ctx.theme_text(result[0], selected, indices, &self.theme);
|
||||||
|
|
||||||
|
// title
|
||||||
|
ctx.move_to(x + 3.5 + 10.0, y);
|
||||||
|
ctx.theme_text(result[1], selected, indices, &self.theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn divider<T>(&self, x: T, y: T)
|
pub fn divider<T>(&self, x: T, y: T)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use pangocairo::pango::{self, AttrInt, AttrList, Attribute, FontDescription};
|
use pangocairo::pango::{self, AttrInt, AttrList, Attribute, EllipsizeMode, FontDescription};
|
||||||
|
|
||||||
// (r,g,b,a)
|
// (r,g,b,a)
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
@ -126,7 +126,9 @@ impl ThemedContextExt for cairo::Context {
|
||||||
font.set_size(theme.font.1 * pango::SCALE);
|
font.set_size(theme.font.1 * pango::SCALE);
|
||||||
layout.set_font_description(Some(&font));
|
layout.set_font_description(Some(&font));
|
||||||
|
|
||||||
|
layout.set_width(200 * pango::SCALE);
|
||||||
layout.set_spacing(0);
|
layout.set_spacing(0);
|
||||||
|
layout.set_ellipsize(EllipsizeMode::End);
|
||||||
|
|
||||||
layout.set_text(text);
|
layout.set_text(text);
|
||||||
|
|
||||||
|
|
17
src/ui/ui.rs
17
src/ui/ui.rs
|
@ -22,7 +22,8 @@ pub fn draw(window: &Window, input: &str, result: Vec<(&Entry, Vec<usize>)>, sel
|
||||||
|
|
||||||
result.iter().enumerate().for_each(|(i, r)| {
|
result.iter().enumerate().for_each(|(i, r)| {
|
||||||
let e = r.0;
|
let e = r.0;
|
||||||
painter.result_box(0, 1 + (i as u32), &e.source, &e.name, &r.1, selection == i);
|
let result = [e.name.as_str(), e.description.as_str()];
|
||||||
|
painter.result_box(0, 1 + (i as u32), &e.source, result, &r.1, selection == i);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,25 +37,27 @@ pub fn redraw_quick(window: &Window, result: Vec<(&Entry, Vec<usize>)>, selectio
|
||||||
|
|
||||||
result.iter().enumerate().for_each(|(i, r)| {
|
result.iter().enumerate().for_each(|(i, r)| {
|
||||||
let e = r.0;
|
let e = r.0;
|
||||||
|
let result = [e.name.as_str(), e.description.as_str()];
|
||||||
|
|
||||||
// clear first and last as these may produce artifacts otherwise
|
// clear first and last as these may produce artifacts otherwise
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
painter.result_box(0, 1 + (i as u32), &e.source, &e.name, &r.1, false)
|
painter.result_box(0, 1 + (i as u32), &e.source, result, &r.1, false)
|
||||||
}
|
}
|
||||||
if i == result.len() - 1 {
|
if i == result.len() - 1 {
|
||||||
painter.result_box(0, 1 + (i as u32), &e.source, &e.name, &r.1, false)
|
painter.result_box(0, 1 + (i as u32), &e.source, result, &r.1, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear boxes around selection as these could be the old selection
|
// clear boxes around selection as these could be the old selection
|
||||||
if selection > 0 && i == (selection - 1) {
|
if selection > 0 && i == (selection - 1) {
|
||||||
painter.result_box(0, 1 + (i as u32), &e.source, &e.name, &r.1, false)
|
painter.result_box(0, 1 + (i as u32), &e.source, result, &r.1, false)
|
||||||
}
|
}
|
||||||
if i == (selection + 1) {
|
if i == (selection + 1) {
|
||||||
painter.result_box(0, 1 + (i as u32), &e.source, &e.name, &r.1, false)
|
painter.result_box(0, 1 + (i as u32), &e.source, result, &r.1, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark selection, note that this negates any unmarking above in case they are the same
|
// mark selection, note that this negates any unmarking above in case they are the same
|
||||||
if i == selection {
|
if i == selection {
|
||||||
painter.result_box(0, 1 + (i as u32), &e.source, &e.name, &r.1, true)
|
painter.result_box(0, 1 + (i as u32), &e.source, result, &r.1, true)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -75,7 +78,7 @@ pub fn draw_actions(window: &Window, actions: Vec<String>, input: &str) {
|
||||||
0,
|
0,
|
||||||
1 + (i as u32),
|
1 + (i as u32),
|
||||||
&usize::to_string(&(i + 1)),
|
&usize::to_string(&(i + 1)),
|
||||||
r,
|
[r.as_str(), ""],
|
||||||
&[],
|
&[],
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
|
@ -22,7 +22,7 @@ use winit::window::{Window, WindowBuilder};
|
||||||
use xcb::ffi::xcb_connection_t;
|
use xcb::ffi::xcb_connection_t;
|
||||||
use xcb::x::{GrabMode, PropMode};
|
use xcb::x::{GrabMode, PropMode};
|
||||||
use xcb::XidNew;
|
use xcb::XidNew;
|
||||||
use xcb_wm::ewmh;
|
use xcb_wm::{ewmh, icccm};
|
||||||
|
|
||||||
pub fn build_window() -> Result<(Window, EventLoop<()>)> {
|
pub fn build_window() -> Result<(Window, EventLoop<()>)> {
|
||||||
trace! {"Initialize `winit` event loop"}
|
trace! {"Initialize `winit` event loop"}
|
||||||
|
@ -68,25 +68,24 @@ fn postprocess_window(window: &Window) -> Result<()> {
|
||||||
mem::ManuallyDrop::new(con)
|
mem::ManuallyDrop::new(con)
|
||||||
};
|
};
|
||||||
|
|
||||||
let ewmh_con = xcb_wm::ewmh::Connection::connect(&xcb_con);
|
let ewmh_con = ewmh::Connection::connect(&xcb_con);
|
||||||
let icccm_con = xcb_wm::icccm::Connection::connect(&xcb_con);
|
let icccm_con = icccm::Connection::connect(&xcb_con);
|
||||||
|
|
||||||
trace! {"Unmap window"}
|
trace! {"Unmap window"}
|
||||||
let req = xcb::x::UnmapWindow { window: xcb_window };
|
let req = xcb::x::UnmapWindow { window: xcb_window };
|
||||||
xcb_con.send_and_check_request(&req)?;
|
xcb_con.send_and_check_request(&req)?;
|
||||||
|
|
||||||
trace! {"Hide window from taskbar"}
|
trace! {"Hide window from taskbar"}
|
||||||
let window_state = xcb_wm::ewmh::proto::SendWmState::new(
|
ewmh_con.send_and_check_request(&ewmh::SendWmState::new(
|
||||||
&ewmh_con,
|
&ewmh_con,
|
||||||
xcb_window,
|
xcb_window,
|
||||||
PropMode::Append,
|
xcb::x::PropMode::Append,
|
||||||
[
|
[
|
||||||
ewmh_con.atoms._NET_WM_STATE,
|
ewmh_con.atoms._NET_WM_STATE,
|
||||||
ewmh_con.atoms._NET_WM_STATE_SKIP_TASKBAR,
|
ewmh_con.atoms._NET_WM_STATE_SKIP_TASKBAR,
|
||||||
],
|
],
|
||||||
1,
|
1,
|
||||||
);
|
))?;
|
||||||
ewmh_con.send_request(&window_state);
|
|
||||||
|
|
||||||
trace! {"Center window on screen"}
|
trace! {"Center window on screen"}
|
||||||
let screen_pixel = window
|
let screen_pixel = window
|
||||||
|
@ -101,7 +100,7 @@ fn postprocess_window(window: &Window) -> Result<()> {
|
||||||
.position();
|
.position();
|
||||||
|
|
||||||
// Configure the window to the center with a size of 800x600 pixels.
|
// Configure the window to the center with a size of 800x600 pixels.
|
||||||
let window_width = 800u32;
|
let window_width = 1000u32;
|
||||||
let window_height = 300u32;
|
let window_height = 300u32;
|
||||||
let x = screen_position.x as i32 + (screen_pixel.width as i32 / 2 - window_width as i32 / 2);
|
let x = screen_position.x as i32 + (screen_pixel.width as i32 / 2 - window_width as i32 / 2);
|
||||||
let y = screen_position.y as i32 + (screen_pixel.height as i32 / 2 - window_height as i32 / 2);
|
let y = screen_position.y as i32 + (screen_pixel.height as i32 / 2 - window_height as i32 / 2);
|
||||||
|
@ -129,5 +128,6 @@ fn postprocess_window(window: &Window) -> Result<()> {
|
||||||
};
|
};
|
||||||
xcb_con.send_request(&req);
|
xcb_con.send_request(&req);
|
||||||
|
|
||||||
|
xcb_con.flush()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue