From 39a888c7baf4bd840de7d56dc45281488baf8adf Mon Sep 17 00:00:00 2001 From: Armin Friedl Date: Mon, 6 Jun 2022 21:08:50 +0200 Subject: [PATCH] Center window on screen --- default.toml | 7 +++-- src/window.rs | 79 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 55 insertions(+), 31 deletions(-) diff --git a/default.toml b/default.toml index 1d92d36..1ef885e 100644 --- a/default.toml +++ b/default.toml @@ -3,14 +3,15 @@ log_level = "trace" [completions] "e" = "emacs" "f" = "firefox" -"t" = "terminal" +"t" = "xfce4-terminal" +"j" = "jetbrains" [sources.primary] -matcher = "Flex" +matcher = "Prefix" source = "Windows" [sources.additional] -matcher = "Flex" +matcher = "Fuse" source = ["Apps", "Shell", "Test"] [theme] diff --git a/src/window.rs b/src/window.rs index e1a2ab9..cb475f9 100644 --- a/src/window.rs +++ b/src/window.rs @@ -22,6 +22,7 @@ use winit::window::{Window, WindowBuilder}; use xcb::ffi::xcb_connection_t; use xcb::x::{GrabMode, PropMode}; use xcb::XidNew; +use xcb_wm::ewmh; pub fn build_window() -> Result<(Window, EventLoop<()>)> { trace! {"Initialize `winit` event loop"} @@ -32,7 +33,6 @@ pub fn build_window() -> Result<(Window, EventLoop<()>)> { .with_decorations(false) .with_transparent(true) .with_title("roftl") - .with_visible(true) .with_always_on_top(true) .with_override_redirect(true) .build(&event_loop)?; @@ -49,11 +49,7 @@ fn postprocess_window(window: &Window) -> Result<()> { trace! {"Post-process window for x11"} trace! {"Get low level connection and data"} - let screen_id = window - .xlib_screen_id() - .ok_or(anyhow! {"Could not get X11 screen id for the window"})?; - - let xcb_window: xcb::x::Window = unsafe { + let xcb_window = unsafe { xcb::x::Window::new( window .xlib_window() @@ -61,36 +57,67 @@ fn postprocess_window(window: &Window) -> Result<()> { ) }; - let xcb_conn_raw = window - .xcb_connection() - .ok_or(anyhow! {"Cannot get raw xcb connection"})?; - - let xcb_conn = unsafe { - mem::ManuallyDrop::new(xcb::Connection::from_raw_conn(mem::transmute(xcb_conn_raw))) + let xcb_con = unsafe { + let con_raw = window + .xcb_connection() + .ok_or(anyhow! {"Cannot get raw xcb connection"})?; + let con = xcb::Connection::from_raw_conn(con_raw as *mut xcb_connection_t); + // xcb::Connection closes the underlying x connection on drop + // since the connection is actually owned by the window we have + // to prevent the drop + mem::ManuallyDrop::new(con) }; + let ewmh_con = xcb_wm::ewmh::Connection::connect(&xcb_con); + let icccm_con = xcb_wm::icccm::Connection::connect(&xcb_con); + + trace! {"Unmap window"} let req = xcb::x::UnmapWindow { window: xcb_window }; - let cookie = xcb_conn.send_request_checked(&req); - xcb_conn.check_request(cookie)?; + xcb_con.send_and_check_request(&req)?; trace! {"Hide window from taskbar"} - let xcb_conn = unsafe { xcb::Connection::from_raw_conn(mem::transmute(xcb_conn_raw)) }; - let ewmh_conn = xcb_wm::ewmh::Connection::connect(&xcb_conn); - let window_state = xcb_wm::ewmh::proto::SendWmState::new( - &ewmh_conn, + &ewmh_con, xcb_window, PropMode::Append, [ - ewmh_conn.atoms._NET_WM_STATE, - ewmh_conn.atoms._NET_WM_STATE_SKIP_TASKBAR, + ewmh_con.atoms._NET_WM_STATE, + ewmh_con.atoms._NET_WM_STATE_SKIP_TASKBAR, ], 1, ); - ewmh_conn.send_request(&window_state); + ewmh_con.send_request(&window_state); - let req = xcb::x::MapWindow { window: xcb_window }; - xcb_conn.send_request(&req); + trace! {"Center window on screen"} + let screen_pixel = window + .current_monitor() + .ok_or(anyhow! {"Cannot get screen size"})? + .size(); + + // usually 0,0 except in multi-head settings (or large display (see icccm spec) which we actually don't consider) + let screen_position = window + .current_monitor() + .ok_or(anyhow! {"Cannot get screen position"})? + .position(); + + // Configure the window to the center with a size of 800x600 pixels. + let window_width = 800u32; + let window_height = 300u32; + 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); + + xcb_con.send_and_check_request(&xcb::x::ConfigureWindow { + window: xcb_window, + value_list: &[ + xcb::x::ConfigWindow::X(x), + xcb::x::ConfigWindow::Y(y), + xcb::x::ConfigWindow::Width(window_width), + xcb::x::ConfigWindow::Height(window_height), + ], + })?; + + trace! {"Map window"} + xcb_con.send_and_check_request(&xcb::x::MapWindow { window: xcb_window })?; trace! {"Grab keyboard"} let req = xcb::x::GrabKeyboard { @@ -100,11 +127,7 @@ fn postprocess_window(window: &Window) -> Result<()> { pointer_mode: GrabMode::Async, keyboard_mode: GrabMode::Async, }; - xcb_conn.send_request(&req); - - mem::forget(xcb_conn); - - // trace! {"Center window on screen"} + xcb_con.send_request(&req); Ok(()) }