mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-25 14:51:30 +11:00
Add window maximization API
Implement a simple API to set a window to maximized. Implement it only for the X11 backend.
This commit is contained in:
parent
17de3f1d15
commit
a4052b8693
|
@ -402,6 +402,11 @@ pub struct WindowAttributes {
|
||||||
/// The default is `"winit window"`.
|
/// The default is `"winit window"`.
|
||||||
pub title: String,
|
pub title: String,
|
||||||
|
|
||||||
|
/// Whether the window should be maximized upon creation.
|
||||||
|
///
|
||||||
|
/// The default is `false`.
|
||||||
|
pub maximized: bool,
|
||||||
|
|
||||||
/// Whether the window should be immediately visible upon creation.
|
/// Whether the window should be immediately visible upon creation.
|
||||||
///
|
///
|
||||||
/// The default is `true`.
|
/// The default is `true`.
|
||||||
|
@ -432,6 +437,7 @@ impl Default for WindowAttributes {
|
||||||
max_dimensions: None,
|
max_dimensions: None,
|
||||||
monitor: None,
|
monitor: None,
|
||||||
title: "winit window".to_owned(),
|
title: "winit window".to_owned(),
|
||||||
|
maximized: false,
|
||||||
visible: true,
|
visible: true,
|
||||||
transparent: false,
|
transparent: false,
|
||||||
decorations: true,
|
decorations: true,
|
||||||
|
|
|
@ -309,6 +309,14 @@ impl Window2 {
|
||||||
&Window2::Wayland(ref w) => w.get_surface().ptr() as *mut _
|
&Window2::Wayland(ref w) => w.get_surface().ptr() as *mut _
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_maximized(&self, maximized: bool) {
|
||||||
|
match self {
|
||||||
|
&Window2::X(ref w) => w.set_maximized(maximized),
|
||||||
|
&Window2::Wayland(ref _w) => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn x_error_callback(dpy: *mut x11::ffi::Display, event: *mut x11::ffi::XErrorEvent)
|
unsafe extern "C" fn x_error_callback(dpy: *mut x11::ffi::Display, event: *mut x11::ffi::XErrorEvent)
|
||||||
|
|
|
@ -35,6 +35,7 @@ unsafe impl Send for WindowProxyData {}
|
||||||
pub struct XWindow {
|
pub struct XWindow {
|
||||||
display: Arc<XConnection>,
|
display: Arc<XConnection>,
|
||||||
window: ffi::Window,
|
window: ffi::Window,
|
||||||
|
root: ffi::Window,
|
||||||
is_fullscreen: bool,
|
is_fullscreen: bool,
|
||||||
screen_id: libc::c_int,
|
screen_id: libc::c_int,
|
||||||
xf86_desk_mode: Option<ffi::XF86VidModeModeInfo>,
|
xf86_desk_mode: Option<ffi::XF86VidModeModeInfo>,
|
||||||
|
@ -227,6 +228,12 @@ impl Window {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set maximization
|
||||||
|
if window_attrs.maximized {
|
||||||
|
Window::set_netwm(display, window, root, "_NET_WM_STATE_MAXIMIZED_HORZ", true);
|
||||||
|
Window::set_netwm(display, window, root, "_NET_WM_STATE_MAXIMIZED_VERT", true);
|
||||||
|
}
|
||||||
|
|
||||||
// set visibility
|
// set visibility
|
||||||
if window_attrs.visible {
|
if window_attrs.visible {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -257,48 +264,7 @@ impl Window {
|
||||||
let is_fullscreen = window_attrs.monitor.is_some();
|
let is_fullscreen = window_attrs.monitor.is_some();
|
||||||
|
|
||||||
if is_fullscreen {
|
if is_fullscreen {
|
||||||
let state_atom = unsafe {
|
Window::set_netwm(display, window, root, "_NET_WM_STATE_FULLSCREEN", true);
|
||||||
with_c_str("_NET_WM_STATE", |state|
|
|
||||||
(display.xlib.XInternAtom)(display.display, state, 0)
|
|
||||||
)
|
|
||||||
};
|
|
||||||
display.check_errors().expect("Failed to call XInternAtom");
|
|
||||||
let fullscreen_atom = unsafe {
|
|
||||||
with_c_str("_NET_WM_STATE_FULLSCREEN", |state_fullscreen|
|
|
||||||
(display.xlib.XInternAtom)(display.display, state_fullscreen, 0)
|
|
||||||
)
|
|
||||||
};
|
|
||||||
display.check_errors().expect("Failed to call XInternAtom");
|
|
||||||
|
|
||||||
let client_message_event = ffi::XClientMessageEvent {
|
|
||||||
type_: ffi::ClientMessage,
|
|
||||||
serial: 0,
|
|
||||||
send_event: 1, // true because we are sending this through `XSendEvent`
|
|
||||||
display: display.display,
|
|
||||||
window: window,
|
|
||||||
message_type: state_atom, // the _NET_WM_STATE atom is sent to change the state of a window
|
|
||||||
format: 32, // view `data` as `c_long`s
|
|
||||||
data: {
|
|
||||||
let mut data = ffi::ClientMessageData::new();
|
|
||||||
// This first `long` is the action; `1` means add/set following property.
|
|
||||||
data.set_long(0, 1);
|
|
||||||
// This second `long` is the property to set (fullscreen)
|
|
||||||
data.set_long(1, fullscreen_atom as c_long);
|
|
||||||
data
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let mut x_event = ffi::XEvent::from(client_message_event);
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
(display.xlib.XSendEvent)(
|
|
||||||
display.display,
|
|
||||||
root,
|
|
||||||
0,
|
|
||||||
ffi::SubstructureRedirectMask | ffi::SubstructureNotifyMask,
|
|
||||||
&mut x_event as *mut _
|
|
||||||
);
|
|
||||||
display.check_errors().expect("Failed to call XSendEvent");
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(mut mode_to_switch_to) = mode_to_switch_to {
|
if let Some(mut mode_to_switch_to) = mode_to_switch_to {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -375,6 +341,7 @@ impl Window {
|
||||||
x: Arc::new(XWindow {
|
x: Arc::new(XWindow {
|
||||||
display: display.clone(),
|
display: display.clone(),
|
||||||
window: window,
|
window: window,
|
||||||
|
root: root,
|
||||||
screen_id: screen_id,
|
screen_id: screen_id,
|
||||||
is_fullscreen: is_fullscreen,
|
is_fullscreen: is_fullscreen,
|
||||||
xf86_desk_mode: xf86_desk_mode,
|
xf86_desk_mode: xf86_desk_mode,
|
||||||
|
@ -418,6 +385,60 @@ impl Window {
|
||||||
Ok(window)
|
Ok(window)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_netwm(display: &Arc<XConnection>, window: u64, root: u64, property: &str, val: bool) {
|
||||||
|
let state_atom = unsafe {
|
||||||
|
with_c_str("_NET_WM_STATE", |state|
|
||||||
|
(display.xlib.XInternAtom)(display.display, state, 0)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
display.check_errors().expect("Failed to call XInternAtom");
|
||||||
|
let atom = unsafe {
|
||||||
|
with_c_str(property, |state|
|
||||||
|
(display.xlib.XInternAtom)(display.display, state, 0)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
display.check_errors().expect("Failed to call XInternAtom");
|
||||||
|
|
||||||
|
let client_message_event = ffi::XClientMessageEvent {
|
||||||
|
type_: ffi::ClientMessage,
|
||||||
|
serial: 0,
|
||||||
|
send_event: 1, // true because we are sending this through `XSendEvent`
|
||||||
|
display: display.display,
|
||||||
|
window: window,
|
||||||
|
message_type: state_atom, // the _NET_WM_STATE atom is sent to change the state of a window
|
||||||
|
format: 32, // view `data` as `c_long`s
|
||||||
|
data: {
|
||||||
|
let mut data = ffi::ClientMessageData::new();
|
||||||
|
// This first `long` is the action; `1` means add/set following property.
|
||||||
|
data.set_long(0, val as i64);
|
||||||
|
// This second `long` is the property to set (fullscreen)
|
||||||
|
data.set_long(1, atom as c_long);
|
||||||
|
data
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut x_event = ffi::XEvent::from(client_message_event);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
(display.xlib.XSendEvent)(
|
||||||
|
display.display,
|
||||||
|
root,
|
||||||
|
0,
|
||||||
|
ffi::SubstructureRedirectMask | ffi::SubstructureNotifyMask,
|
||||||
|
&mut x_event as *mut _
|
||||||
|
);
|
||||||
|
display.check_errors().expect("Failed to call XSendEvent");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_fullscreen_windowed(&self, fullscreen: bool) {
|
||||||
|
Window::set_netwm(&self.x.display, self.x.window, self.x.root, "_NET_WM_STATE_FULLSCREEN", fullscreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_maximized(&self, maximized: bool) {
|
||||||
|
Window::set_netwm(&self.x.display, self.x.window, self.x.root, "_NET_WM_STATE_MAXIMIZED_HORZ", maximized);
|
||||||
|
Window::set_netwm(&self.x.display, self.x.window, self.x.root, "_NET_WM_STATE_MAXIMIZED_VERT", maximized);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_title(&self, title: &str) {
|
pub fn set_title(&self, title: &str) {
|
||||||
let wm_name = unsafe {
|
let wm_name = unsafe {
|
||||||
(self.x.display.xlib.XInternAtom)(self.x.display.display, b"_NET_WM_NAME\0".as_ptr() as *const _, 0)
|
(self.x.display.xlib.XInternAtom)(self.x.display.display, b"_NET_WM_NAME\0".as_ptr() as *const _, 0)
|
||||||
|
|
|
@ -66,6 +66,13 @@ impl WindowBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Requests maximized mode.
|
||||||
|
#[inline]
|
||||||
|
pub fn with_maximized(mut self, maximized: bool) -> WindowBuilder {
|
||||||
|
self.window.maximized = maximized;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets whether the window will be initially hidden or visible.
|
/// Sets whether the window will be initially hidden or visible.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_visibility(mut self, visible: bool) -> WindowBuilder {
|
pub fn with_visibility(mut self, visible: bool) -> WindowBuilder {
|
||||||
|
@ -292,6 +299,12 @@ impl Window {
|
||||||
self.window.set_cursor_state(state)
|
self.window.set_cursor_state(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the window to maximized or back
|
||||||
|
#[inline]
|
||||||
|
pub fn set_maximized(&self, maximized: bool) {
|
||||||
|
self.window.set_maximized(maximized)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn id(&self) -> WindowId {
|
pub fn id(&self) -> WindowId {
|
||||||
WindowId(self.window.id())
|
WindowId(self.window.id())
|
||||||
|
|
Loading…
Reference in a new issue