From 6e318abf0498e94e4572a142367d890d7cb2b9d5 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Tue, 28 Dec 2021 11:38:52 -0500 Subject: [PATCH] refactor X and recenter app_library when size changes --- examples/app_library/main.rs | 9 +++ examples/app_library/window/mod.rs | 109 ++++++++++++++++++++++++----- examples/launcher/window/mod.rs | 2 +- 3 files changed, 101 insertions(+), 19 deletions(-) diff --git a/examples/app_library/main.rs b/examples/app_library/main.rs index a9a65c51..e3315579 100644 --- a/examples/app_library/main.rs +++ b/examples/app_library/main.rs @@ -8,9 +8,13 @@ use gtk::prelude::*; use gtk4 as gtk; use gtk4::CssProvider; use gtk4::StyleContext; +use once_cell::sync::OnceCell; +use x11rb::rust_connection::RustConnection; use window::Window; +static X11_CONN: OnceCell = OnceCell::new(); + fn main() { let app = gtk::Application::new(Some("com.cosmic.app_library"), Default::default()); app.connect_startup(|app| { @@ -41,5 +45,10 @@ fn load_css() { fn build_ui(app: >k::Application) { // Create a new custom window and show it let window = Window::new(app); + let (conn, _screen_num) = x11rb::connect(None).expect("Failed to connect to X"); + if X11_CONN.set(conn).is_err() { + println!("failed to set X11_CONN. Exiting"); + std::process::exit(1); + }; window.show(); } diff --git a/examples/app_library/window/mod.rs b/examples/app_library/window/mod.rs index 9ba6a5e2..8678d9d8 100644 --- a/examples/app_library/window/mod.rs +++ b/examples/app_library/window/mod.rs @@ -1,24 +1,31 @@ mod imp; use crate::app_group::AppGroup; use crate::app_group::AppGroupData; +use crate::grid_item::GridItem; use crate::utils::data_path; use crate::utils::set_group_scroll_policy; +use crate::X11_CONN; +use gdk4::Rectangle; +use gdk4_x11::X11Display; +use gdk4_x11::X11Surface; use glib::FromVariant; -use glib::Variant; -use gtk4 as gtk; -use gtk4::Dialog; -use gtk4::Entry; -use gtk4::Label; -use std::fs::File; - -use crate::grid_item::GridItem; use glib::Object; +use glib::Variant; use gtk::prelude::*; use gtk::subclass::prelude::*; use gtk::{gio, glib}; use gtk::{Application, SignalListItemFactory}; - +use gtk4 as gtk; +use gtk4::Dialog; +use gtk4::Entry; +use gtk4::Label; use libcosmic::x; +use std::fs::File; +use x11rb::connection::Connection; +use x11rb::protocol::xproto; +use x11rb::protocol::xproto::ConnectionExt as OtherConnectionExt; +use x11rb::protocol::xproto::*; +use x11rb::wrapper::ConnectionExt; glib::wrapper! { pub struct Window(ObjectSubclass) @@ -394,15 +401,81 @@ impl Window { window.connect_realize(move |window| { if let Some((display, surface)) = x::get_window_x11(window) { - unsafe { - x::change_property( - &display, - &surface, - "_NET_WM_WINDOW_TYPE", - x::PropMode::Replace, - &[x::Atom::new(&display, "_NET_WM_WINDOW_TYPE_DIALOG").unwrap()], - ); - } + // ignore all x11 errors... + let xdisplay = display + .clone() + .downcast::() + .expect("Failed to downgrade X11 Display."); + xdisplay.error_trap_push(); + let conn = X11_CONN.get().expect("Failed to get X11 connection"); + let window_type_atom = conn + .intern_atom(false, b"_NET_WM_WINDOW_TYPE") + .unwrap() + .reply() + .unwrap() + .atom; + let dock_type_atom = conn + .intern_atom(false, b"_NET_WM_WINDOW_TYPE_DIALOG") + .unwrap() + .reply() + .unwrap() + .atom; + conn.change_property32( + PropMode::REPLACE, + surface.xid().try_into().unwrap(), + window_type_atom, + AtomEnum::ATOM, + &[dock_type_atom], + ) + .unwrap(); + let resize = glib::clone!(@weak window => move || { + let s = window.surface().expect("Failed to get Surface for Window"); + let height = window.height(); + let width = window.width(); + + if let Some((display, _surface)) = x::get_window_x11(&window) { + let monitor = display + .primary_monitor() + .expect("Failed to get Monitor"); + let Rectangle { + x: monitor_x, + y: monitor_y, + width: monitor_width, + height: monitor_height, + } = monitor.geometry(); + // dbg!(monitor_width); + // dbg!(monitor_height); + // dbg!(width); + // dbg!(height); + let w_conf = xproto::ConfigureWindowAux::default() + .x(monitor_x + monitor_width / 2 - width / 2) + .y(monitor_y + monitor_height / 2 - height / 2); + let conn = X11_CONN.get().expect("Failed to get X11_CONN"); + + let x11surface = gdk4_x11::X11Surface::xid( + &s.clone().downcast::() + .expect("Failed to downcast Surface to X11Surface"), + ); + conn.configure_window( + x11surface.try_into().expect("Failed to convert XID"), + &w_conf, + ) + .expect("failed to configure window..."); + conn.flush().expect("failed to flush"); + } + }); + let s = window.surface().expect("Failed to get Surface for Window"); + let resize_height = resize.clone(); + s.connect_height_notify(move |_s| { + glib::source::idle_add_local_once(resize_height.clone()); + }); + let resize_width = resize.clone(); + s.connect_width_notify(move |_s| { + glib::source::idle_add_local_once(resize_width.clone()); + }); + s.connect_scale_factor_notify(move |_s| { + glib::source::idle_add_local_once(resize.clone()); + }); } else { println!("failed to get X11 window"); } diff --git a/examples/launcher/window/mod.rs b/examples/launcher/window/mod.rs index 93eb1919..c05a9d10 100644 --- a/examples/launcher/window/mod.rs +++ b/examples/launcher/window/mod.rs @@ -145,7 +145,7 @@ impl Window { xdisplay.error_trap_push(); let conn = X11_CONN.get().expect("Failed to get X11 connection"); let window_type_atom = conn.intern_atom(false, b"_NET_WM_WINDOW_TYPE").unwrap().reply().unwrap().atom; - let dock_type_atom = conn.intern_atom(false, b"_NET_WM_WINDOW_TYPE_DOCK").unwrap().reply().unwrap().atom; + let dock_type_atom = conn.intern_atom(false, b"_NET_WM_WINDOW_TYPE_DIALOG").unwrap().reply().unwrap().atom; conn.change_property32( PropMode::REPLACE, surface.xid().try_into().unwrap(),