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]
"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]

View file

@ -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
let xcb_con = unsafe {
let con_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 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(())
}