Center window on screen

This commit is contained in:
Armin Friedl 2022-06-06 21:08:50 +02:00
parent e37563eb7a
commit 39a888c7ba
2 changed files with 55 additions and 31 deletions

View file

@ -3,14 +3,15 @@ log_level = "trace"
[completions] [completions]
"e" = "emacs" "e" = "emacs"
"f" = "firefox" "f" = "firefox"
"t" = "terminal" "t" = "xfce4-terminal"
"j" = "jetbrains"
[sources.primary] [sources.primary]
matcher = "Flex" matcher = "Prefix"
source = "Windows" source = "Windows"
[sources.additional] [sources.additional]
matcher = "Flex" matcher = "Fuse"
source = ["Apps", "Shell", "Test"] source = ["Apps", "Shell", "Test"]
[theme] [theme]

View file

@ -22,6 +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;
pub fn build_window() -> Result<(Window, EventLoop<()>)> { pub fn build_window() -> Result<(Window, EventLoop<()>)> {
trace! {"Initialize `winit` event loop"} trace! {"Initialize `winit` event loop"}
@ -32,7 +33,6 @@ pub fn build_window() -> Result<(Window, EventLoop<()>)> {
.with_decorations(false) .with_decorations(false)
.with_transparent(true) .with_transparent(true)
.with_title("roftl") .with_title("roftl")
.with_visible(true)
.with_always_on_top(true) .with_always_on_top(true)
.with_override_redirect(true) .with_override_redirect(true)
.build(&event_loop)?; .build(&event_loop)?;
@ -49,11 +49,7 @@ fn postprocess_window(window: &Window) -> Result<()> {
trace! {"Post-process window for x11"} trace! {"Post-process window for x11"}
trace! {"Get low level connection and data"} trace! {"Get low level connection and data"}
let screen_id = window let xcb_window = unsafe {
.xlib_screen_id()
.ok_or(anyhow! {"Could not get X11 screen id for the window"})?;
let xcb_window: xcb::x::Window = unsafe {
xcb::x::Window::new( xcb::x::Window::new(
window window
.xlib_window() .xlib_window()
@ -61,36 +57,67 @@ fn postprocess_window(window: &Window) -> Result<()> {
) )
}; };
let xcb_conn_raw = window let xcb_con = unsafe {
.xcb_connection() let con_raw = window
.ok_or(anyhow! {"Cannot get raw xcb connection"})?; .xcb_connection()
.ok_or(anyhow! {"Cannot get raw xcb connection"})?;
let xcb_conn = unsafe { let con = xcb::Connection::from_raw_conn(con_raw as *mut xcb_connection_t);
mem::ManuallyDrop::new(xcb::Connection::from_raw_conn(mem::transmute(xcb_conn_raw))) // 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 req = xcb::x::UnmapWindow { window: xcb_window };
let cookie = xcb_conn.send_request_checked(&req); xcb_con.send_and_check_request(&req)?;
xcb_conn.check_request(cookie)?;
trace! {"Hide window from taskbar"} 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( let window_state = xcb_wm::ewmh::proto::SendWmState::new(
&ewmh_conn, &ewmh_con,
xcb_window, xcb_window,
PropMode::Append, PropMode::Append,
[ [
ewmh_conn.atoms._NET_WM_STATE, ewmh_con.atoms._NET_WM_STATE,
ewmh_conn.atoms._NET_WM_STATE_SKIP_TASKBAR, ewmh_con.atoms._NET_WM_STATE_SKIP_TASKBAR,
], ],
1, 1,
); );
ewmh_conn.send_request(&window_state); ewmh_con.send_request(&window_state);
let req = xcb::x::MapWindow { window: xcb_window }; trace! {"Center window on screen"}
xcb_conn.send_request(&req); 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"} trace! {"Grab keyboard"}
let req = xcb::x::GrabKeyboard { let req = xcb::x::GrabKeyboard {
@ -100,11 +127,7 @@ fn postprocess_window(window: &Window) -> Result<()> {
pointer_mode: GrabMode::Async, pointer_mode: GrabMode::Async,
keyboard_mode: GrabMode::Async, keyboard_mode: GrabMode::Async,
}; };
xcb_conn.send_request(&req); xcb_con.send_request(&req);
mem::forget(xcb_conn);
// trace! {"Center window on screen"}
Ok(()) Ok(())
} }