mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-02-02 23:06:32 +11:00
Merge pull request #130 from pedrocr/maximization
Maximization and Windowed Fullscreen
This commit is contained in:
commit
f7a8bcddb8
10 changed files with 331 additions and 174 deletions
|
@ -1,7 +1,7 @@
|
|||
extern crate winit;
|
||||
|
||||
use std::io::{self, Write};
|
||||
use winit::{ControlFlow, Event, WindowEvent};
|
||||
use winit::{ControlFlow, Event, WindowEvent, FullScreenState};
|
||||
|
||||
fn main() {
|
||||
// enumerating monitors
|
||||
|
@ -27,7 +27,7 @@ fn main() {
|
|||
|
||||
let _window = winit::WindowBuilder::new()
|
||||
.with_title("Hello world!")
|
||||
.with_fullscreen(monitor)
|
||||
.with_fullscreen(FullScreenState::Exclusive(monitor))
|
||||
.build(&events_loop)
|
||||
.unwrap();
|
||||
|
||||
|
|
20
src/lib.rs
20
src/lib.rs
|
@ -356,6 +356,14 @@ pub enum MouseCursor {
|
|||
RowResize,
|
||||
}
|
||||
|
||||
/// Describes if the Window is in one of the fullscreen modes
|
||||
#[derive(Clone)]
|
||||
pub enum FullScreenState {
|
||||
None,
|
||||
Windowed,
|
||||
Exclusive(MonitorId),
|
||||
}
|
||||
|
||||
/// Describes how winit handles the cursor.
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum CursorState {
|
||||
|
@ -392,16 +400,21 @@ pub struct WindowAttributes {
|
|||
/// The default is `None`.
|
||||
pub max_dimensions: Option<(u32, u32)>,
|
||||
|
||||
/// If `Some`, the window will be in fullscreen mode with the given monitor.
|
||||
/// Whether the window should be set as fullscreen upon creation.
|
||||
///
|
||||
/// The default is `None`.
|
||||
pub monitor: Option<platform::MonitorId>,
|
||||
pub fullscreen: FullScreenState,
|
||||
|
||||
/// The title of the window in the title bar.
|
||||
///
|
||||
/// The default is `"winit window"`.
|
||||
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.
|
||||
///
|
||||
/// The default is `true`.
|
||||
|
@ -430,8 +443,9 @@ impl Default for WindowAttributes {
|
|||
dimensions: None,
|
||||
min_dimensions: None,
|
||||
max_dimensions: None,
|
||||
monitor: None,
|
||||
title: "winit window".to_owned(),
|
||||
maximized: false,
|
||||
fullscreen: FullScreenState::None,
|
||||
visible: true,
|
||||
transparent: false,
|
||||
decorations: true,
|
||||
|
|
|
@ -15,6 +15,7 @@ use std::collections::VecDeque;
|
|||
|
||||
use CursorState;
|
||||
use WindowAttributes;
|
||||
use FullScreenState;
|
||||
use native_monitor::NativeMonitorId;
|
||||
|
||||
gen_api_transition!();
|
||||
|
@ -260,6 +261,14 @@ impl Window {
|
|||
pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_maximized(&self, maximized: bool) {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_fullscreen(&self, state: FullScreenState) {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for Window {}
|
||||
|
|
|
@ -71,7 +71,7 @@ use objc::runtime::{Class, Object, Sel, BOOL, YES };
|
|||
use objc::declare::{ ClassDecl };
|
||||
|
||||
use native_monitor::NativeMonitorId;
|
||||
use { CreationError, CursorState, MouseCursor, WindowAttributes };
|
||||
use { CreationError, CursorState, MouseCursor, WindowAttributes, FullScreenState };
|
||||
use WindowEvent as Event;
|
||||
use events::{ Touch, TouchPhase };
|
||||
|
||||
|
@ -449,6 +449,13 @@ impl Window {
|
|||
WindowProxy
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_maximized(&self, maximized: bool) {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_fullscreen(&self, state: FullScreenState) {
|
||||
}
|
||||
}
|
||||
|
||||
impl WindowProxy {
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::collections::VecDeque;
|
|||
use std::sync::Arc;
|
||||
use std::env;
|
||||
|
||||
use {CreationError, CursorState, EventsLoopClosed, MouseCursor, ControlFlow};
|
||||
use {CreationError, CursorState, EventsLoopClosed, MouseCursor, ControlFlow, FullScreenState};
|
||||
use libc;
|
||||
|
||||
use self::x11::XConnection;
|
||||
|
@ -309,6 +309,22 @@ impl Window2 {
|
|||
&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) => {},
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_fullscreen(&self, state: FullScreenState) {
|
||||
match self {
|
||||
&Window2::X(ref w) => w.set_fullscreen(state),
|
||||
&Window2::Wayland(ref _w) => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn x_error_callback(dpy: *mut x11::ffi::Display, event: *mut x11::ffi::XErrorEvent)
|
||||
|
|
|
@ -4,8 +4,10 @@ use std::sync::atomic::AtomicBool;
|
|||
use wayland_client::{EventQueue, EventQueueHandle, Proxy};
|
||||
use wayland_client::protocol::{wl_display,wl_surface};
|
||||
|
||||
use {CreationError, MouseCursor, CursorState, WindowAttributes};
|
||||
use {CreationError, MouseCursor, CursorState, WindowAttributes, FullScreenState};
|
||||
use platform::MonitorId as PlatformMonitorId;
|
||||
use window::MonitorId as RootMonitorId;
|
||||
use super::context::MonitorId as WaylandMonitorId;
|
||||
|
||||
use super::{WaylandContext, EventsLoop};
|
||||
use super::wayland_window;
|
||||
|
@ -54,7 +56,7 @@ impl Window {
|
|||
*(decorated.handler()) = Some(DecoratedHandler::new());
|
||||
|
||||
// set fullscreen if necessary
|
||||
if let Some(PlatformMonitorId::Wayland(ref monitor_id)) = attributes.monitor {
|
||||
if let FullScreenState::Exclusive(RootMonitorId(PlatformMonitorId::Wayland(ref monitor_id))) = attributes.fullscreen {
|
||||
ctxt.with_output(monitor_id.clone(), |output| {
|
||||
decorated.set_fullscreen(Some(output))
|
||||
});
|
||||
|
|
|
@ -11,12 +11,16 @@ use std::time::Duration;
|
|||
|
||||
use CursorState;
|
||||
use WindowAttributes;
|
||||
use FullScreenState;
|
||||
use platform::PlatformSpecificWindowBuilderAttributes;
|
||||
|
||||
use platform::MonitorId as PlatformMonitorId;
|
||||
use window::MonitorId as RootMonitorId;
|
||||
|
||||
use super::{ffi};
|
||||
use super::{MonitorId, XConnection, WindowId, EventsLoop};
|
||||
use super::{XConnection, WindowId, EventsLoop};
|
||||
|
||||
use super::MonitorId as X11MonitorId;
|
||||
|
||||
// TODO: remove me
|
||||
fn with_c_str<F, T>(s: &str, f: F) -> T where F: FnOnce(*const libc::c_char) -> T {
|
||||
|
@ -35,9 +39,9 @@ unsafe impl Send for WindowProxyData {}
|
|||
pub struct XWindow {
|
||||
display: Arc<XConnection>,
|
||||
window: ffi::Window,
|
||||
is_fullscreen: bool,
|
||||
screen_id: libc::c_int,
|
||||
xf86_desk_mode: Option<ffi::XF86VidModeModeInfo>,
|
||||
root: ffi::Window,
|
||||
// screen we're using, original screen mode if we've switched
|
||||
fullscreen: Arc<Mutex<(i32, Option<ffi::XF86VidModeModeInfo>)>>,
|
||||
window_proxy_data: Arc<Mutex<Option<WindowProxyData>>>,
|
||||
}
|
||||
|
||||
|
@ -47,22 +51,105 @@ unsafe impl Sync for XWindow {}
|
|||
unsafe impl Send for Window {}
|
||||
unsafe impl Sync for Window {}
|
||||
|
||||
impl XWindow {
|
||||
fn switch_to_fullscreen_mode(&self, monitor: i32, width: u16, height: u16) {
|
||||
let original_monitor = {
|
||||
let fullscreen = self.fullscreen.lock().unwrap();
|
||||
fullscreen.0
|
||||
};
|
||||
if monitor != original_monitor {
|
||||
// We're setting fullscreen on a new screen so first revert the original screen
|
||||
self.switch_from_fullscreen_mode();
|
||||
}
|
||||
|
||||
let current_mode = unsafe {
|
||||
let mut mode_num: libc::c_int = mem::uninitialized();
|
||||
let mut modes: *mut *mut ffi::XF86VidModeModeInfo = mem::uninitialized();
|
||||
if (self.display.xf86vmode.XF86VidModeGetAllModeLines)(self.display.display, monitor, &mut mode_num, &mut modes) == 0 {
|
||||
eprintln!("[winit] Couldn't get current resolution mode");
|
||||
return
|
||||
}
|
||||
ptr::read(*modes.offset(0))
|
||||
};
|
||||
|
||||
let new_mode = unsafe {
|
||||
let mut mode_num: libc::c_int = mem::uninitialized();
|
||||
let mut modes: *mut *mut ffi::XF86VidModeModeInfo = mem::uninitialized();
|
||||
if (self.display.xf86vmode.XF86VidModeGetAllModeLines)(self.display.display, monitor, &mut mode_num, &mut modes) == 0 {
|
||||
// There are no modes, mighty weird
|
||||
eprintln!("[winit] X has no valid modes");
|
||||
return
|
||||
} else {
|
||||
let matching_mode = (0 .. mode_num).map(|i| {
|
||||
let m: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(i as isize) as *const _); m
|
||||
}).find(|m| m.hdisplay == width && m.vdisplay == height);
|
||||
|
||||
if let Some(matching_mode) = matching_mode {
|
||||
matching_mode
|
||||
} else {
|
||||
let m = (0 .. mode_num).map(|i| {
|
||||
let m: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(i as isize) as *const _); m
|
||||
}).find(|m| m.hdisplay >= width && m.vdisplay >= height);
|
||||
|
||||
match m {
|
||||
Some(m) => m,
|
||||
None => {
|
||||
eprintln!("[winit] Could not find a suitable graphics mode");
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if new_mode != current_mode {
|
||||
// We actually need to change modes
|
||||
self.set_mode(monitor, new_mode);
|
||||
let mut fullscreen = self.fullscreen.lock().unwrap();
|
||||
if fullscreen.1.is_none() {
|
||||
// It's our first mode switch, save the original mode
|
||||
fullscreen.1 = Some(current_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn switch_from_fullscreen_mode(&self) {
|
||||
let (monitor, mode) = {
|
||||
let fullscreen = self.fullscreen.lock().unwrap();
|
||||
(fullscreen.0, fullscreen.1)
|
||||
};
|
||||
|
||||
if let Some(mode) = mode {
|
||||
self.set_mode(monitor, mode);
|
||||
let mut fullscreen = self.fullscreen.lock().unwrap();
|
||||
fullscreen.1 = None;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_mode(&self, monitor: i32, mode: ffi::XF86VidModeModeInfo) {
|
||||
unsafe {
|
||||
let mut mode_to_switch_to = mode;
|
||||
(self.display.xf86vmode.XF86VidModeSwitchToMode)(
|
||||
self.display.display,
|
||||
monitor,
|
||||
&mut mode_to_switch_to
|
||||
);
|
||||
self.display.check_errors().expect("Failed to call XF86VidModeSwitchToMode");
|
||||
|
||||
(self.display.xf86vmode.XF86VidModeSetViewPort)(self.display.display, monitor, 0, 0);
|
||||
self.display.check_errors().expect("Failed to call XF86VidModeSetViewPort");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for XWindow {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// Clear out the window proxy data arc, so that any window proxy objects
|
||||
// are no longer able to send messages to this window.
|
||||
*self.window_proxy_data.lock().unwrap() = None;
|
||||
// Clear out the window proxy data arc, so that any window proxy objects
|
||||
// are no longer able to send messages to this window.
|
||||
*self.window_proxy_data.lock().unwrap() = None;
|
||||
|
||||
if self.is_fullscreen {
|
||||
if let Some(mut xf86_desk_mode) = self.xf86_desk_mode {
|
||||
(self.display.xf86vmode.XF86VidModeSwitchToMode)(self.display.display, self.screen_id, &mut xf86_desk_mode);
|
||||
}
|
||||
(self.display.xf86vmode.XF86VidModeSetViewPort)(self.display.display, self.screen_id, 0, 0);
|
||||
}
|
||||
|
||||
(self.display.xlib.XDestroyWindow)(self.display.display, self.window);
|
||||
}
|
||||
// Make sure we return the display to the original resolution if we've changed it
|
||||
self.switch_from_fullscreen_mode();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,44 +214,12 @@ impl Window {
|
|||
|
||||
let screen_id = match pl_attribs.screen_id {
|
||||
Some(id) => id,
|
||||
None => match window_attrs.monitor {
|
||||
Some(PlatformMonitorId::X(MonitorId(_, monitor))) => monitor as i32,
|
||||
None => match window_attrs.fullscreen {
|
||||
FullScreenState::Exclusive(RootMonitorId(PlatformMonitorId::X(X11MonitorId(_, monitor)))) => monitor as i32,
|
||||
_ => unsafe { (display.xlib.XDefaultScreen)(display.display) },
|
||||
}
|
||||
};
|
||||
|
||||
// finding the mode to switch to if necessary
|
||||
let (mode_to_switch_to, xf86_desk_mode) = unsafe {
|
||||
let mut mode_num: libc::c_int = mem::uninitialized();
|
||||
let mut modes: *mut *mut ffi::XF86VidModeModeInfo = mem::uninitialized();
|
||||
if (display.xf86vmode.XF86VidModeGetAllModeLines)(display.display, screen_id, &mut mode_num, &mut modes) == 0 {
|
||||
(None, None)
|
||||
} else {
|
||||
let xf86_desk_mode: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(0));
|
||||
let mode_to_switch_to = if window_attrs.monitor.is_some() {
|
||||
let matching_mode = (0 .. mode_num).map(|i| {
|
||||
let m: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(i as isize) as *const _); m
|
||||
}).find(|m| m.hdisplay == dimensions.0 as u16 && m.vdisplay == dimensions.1 as u16);
|
||||
if let Some(matching_mode) = matching_mode {
|
||||
Some(matching_mode)
|
||||
} else {
|
||||
let m = (0 .. mode_num).map(|i| {
|
||||
let m: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(i as isize) as *const _); m
|
||||
}).find(|m| m.hdisplay >= dimensions.0 as u16 && m.vdisplay >= dimensions.1 as u16);
|
||||
|
||||
match m {
|
||||
Some(m) => Some(m),
|
||||
None => return Err(OsError(format!("Could not find a suitable graphics mode")))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
(display.xlib.XFree)(modes as *mut _);
|
||||
(mode_to_switch_to, Some(xf86_desk_mode))
|
||||
}
|
||||
};
|
||||
|
||||
// getting the root window
|
||||
let root = ctx.root;
|
||||
|
||||
|
@ -254,95 +309,24 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
let is_fullscreen = window_attrs.monitor.is_some();
|
||||
|
||||
if is_fullscreen {
|
||||
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 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 {
|
||||
unsafe {
|
||||
(display.xf86vmode.XF86VidModeSwitchToMode)(
|
||||
display.display,
|
||||
screen_id,
|
||||
&mut mode_to_switch_to
|
||||
);
|
||||
display.check_errors().expect("Failed to call XF86VidModeSwitchToMode");
|
||||
}
|
||||
}
|
||||
else {
|
||||
println!("[glutin] Unexpected state: `mode` is None creating fullscreen window");
|
||||
}
|
||||
unsafe {
|
||||
(display.xf86vmode.XF86VidModeSetViewPort)(display.display, screen_id, 0, 0);
|
||||
display.check_errors().expect("Failed to call XF86VidModeSetViewPort");
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// set size hints
|
||||
let mut size_hints: ffi::XSizeHints = unsafe { mem::zeroed() };
|
||||
size_hints.flags = ffi::PSize;
|
||||
size_hints.width = dimensions.0 as i32;
|
||||
size_hints.height = dimensions.1 as i32;
|
||||
|
||||
if let Some(dimensions) = window_attrs.min_dimensions {
|
||||
size_hints.flags |= ffi::PMinSize;
|
||||
size_hints.min_width = dimensions.0 as i32;
|
||||
size_hints.min_height = dimensions.1 as i32;
|
||||
}
|
||||
|
||||
if let Some(dimensions) = window_attrs.max_dimensions {
|
||||
size_hints.flags |= ffi::PMaxSize;
|
||||
size_hints.max_width = dimensions.0 as i32;
|
||||
size_hints.max_height = dimensions.1 as i32;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
(display.xlib.XSetNormalHints)(display.display, window, &mut size_hints);
|
||||
display.check_errors().expect("Failed to call XSetNormalHints");
|
||||
}
|
||||
|
||||
// set size hints
|
||||
let mut size_hints: ffi::XSizeHints = unsafe { mem::zeroed() };
|
||||
size_hints.flags = ffi::PSize;
|
||||
size_hints.width = dimensions.0 as i32;
|
||||
size_hints.height = dimensions.1 as i32;
|
||||
if let Some(dimensions) = window_attrs.min_dimensions {
|
||||
size_hints.flags |= ffi::PMinSize;
|
||||
size_hints.min_width = dimensions.0 as i32;
|
||||
size_hints.min_height = dimensions.1 as i32;
|
||||
}
|
||||
if let Some(dimensions) = window_attrs.max_dimensions {
|
||||
size_hints.flags |= ffi::PMaxSize;
|
||||
size_hints.max_width = dimensions.0 as i32;
|
||||
size_hints.max_height = dimensions.1 as i32;
|
||||
}
|
||||
unsafe {
|
||||
(display.xlib.XSetNormalHints)(display.display, window, &mut size_hints);
|
||||
display.check_errors().expect("Failed to call XSetNormalHints");
|
||||
}
|
||||
|
||||
// Select XInput2 events
|
||||
|
@ -375,9 +359,8 @@ impl Window {
|
|||
x: Arc::new(XWindow {
|
||||
display: display.clone(),
|
||||
window: window,
|
||||
screen_id: screen_id,
|
||||
is_fullscreen: is_fullscreen,
|
||||
xf86_desk_mode: xf86_desk_mode,
|
||||
root: root,
|
||||
fullscreen: Arc::new(Mutex::new((screen_id, None))),
|
||||
window_proxy_data: window_proxy_data,
|
||||
}),
|
||||
cursor_state: Mutex::new(CursorState::Normal),
|
||||
|
@ -385,6 +368,8 @@ impl Window {
|
|||
|
||||
window.set_title(&window_attrs.title);
|
||||
window.set_decorations(window_attrs.decorations);
|
||||
window.set_maximized(window_attrs.maximized);
|
||||
window.set_fullscreen(window_attrs.fullscreen.clone());
|
||||
|
||||
if window_attrs.visible {
|
||||
unsafe {
|
||||
|
@ -418,6 +403,78 @@ impl 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(&self, state: FullScreenState) {
|
||||
match state {
|
||||
FullScreenState::None => {
|
||||
self.x.switch_from_fullscreen_mode();
|
||||
Window::set_netwm(&self.x.display, self.x.window, self.x.root, "_NET_WM_STATE_FULLSCREEN", false);
|
||||
},
|
||||
FullScreenState::Windowed => {
|
||||
self.x.switch_from_fullscreen_mode();
|
||||
Window::set_netwm(&self.x.display, self.x.window, self.x.root, "_NET_WM_STATE_FULLSCREEN", true);
|
||||
},
|
||||
FullScreenState::Exclusive(RootMonitorId(PlatformMonitorId::X(X11MonitorId(_, monitor)))) => {
|
||||
if let Some(dimensions) = self.get_inner_size() {
|
||||
self.x.switch_to_fullscreen_mode(monitor as i32, dimensions.0 as u16, dimensions.1 as u16);
|
||||
Window::set_netwm(&self.x.display, self.x.window, self.x.root, "_NET_WM_STATE_FULLSCREEN", true);
|
||||
} else {
|
||||
eprintln!("[winit] Couldn't get window dimensions to go 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) {
|
||||
let wm_name = unsafe {
|
||||
(self.x.display.xlib.XInternAtom)(self.x.display.display, b"_NET_WM_NAME\0".as_ptr() as *const _, 0)
|
||||
|
@ -563,7 +620,12 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn get_xlib_screen_id(&self) -> *mut libc::c_void {
|
||||
self.x.screen_id as *mut libc::c_void
|
||||
let screen_id = {
|
||||
let fullscreen = self.x.fullscreen.lock().unwrap();
|
||||
fullscreen.0
|
||||
};
|
||||
|
||||
screen_id as *mut libc::c_void
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -774,11 +836,16 @@ impl Window {
|
|||
}
|
||||
|
||||
pub fn hidpi_factor(&self) -> f32 {
|
||||
let screen_id = {
|
||||
let fullscreen = self.x.fullscreen.lock().unwrap();
|
||||
fullscreen.0
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let x_px = (self.x.display.xlib.XDisplayWidth)(self.x.display.display, self.x.screen_id);
|
||||
let y_px = (self.x.display.xlib.XDisplayHeight)(self.x.display.display, self.x.screen_id);
|
||||
let x_mm = (self.x.display.xlib.XDisplayWidthMM)(self.x.display.display, self.x.screen_id);
|
||||
let y_mm = (self.x.display.xlib.XDisplayHeightMM)(self.x.display.display, self.x.screen_id);
|
||||
let x_px = (self.x.display.xlib.XDisplayWidth)(self.x.display.display, screen_id);
|
||||
let y_px = (self.x.display.xlib.XDisplayHeight)(self.x.display.display, screen_id);
|
||||
let x_mm = (self.x.display.xlib.XDisplayWidthMM)(self.x.display.display, screen_id);
|
||||
let y_mm = (self.x.display.xlib.XDisplayHeightMM)(self.x.display.display, screen_id);
|
||||
let ppmm = ((x_px as f32 * y_px as f32) / (x_mm as f32 * y_mm as f32)).sqrt();
|
||||
((ppmm * (12.0 * 25.4 / 96.0)).round() / 12.0).max(1.0) // quantize with 1/12 step size.
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use CreationError::OsError;
|
|||
use libc;
|
||||
|
||||
use WindowAttributes;
|
||||
use FullScreenState;
|
||||
use native_monitor::NativeMonitorId;
|
||||
use os::macos::ActivationPolicy;
|
||||
use os::macos::WindowExt;
|
||||
|
@ -383,8 +384,8 @@ impl Window {
|
|||
|
||||
fn create_window(attrs: &WindowAttributes) -> Option<IdRef> {
|
||||
unsafe {
|
||||
let screen = match attrs.monitor {
|
||||
Some(ref monitor_id) => {
|
||||
let screen = match attrs.fullscreen {
|
||||
FullScreenState::Exclusive(ref monitor_id) => {
|
||||
let native_id = match monitor_id.get_native_identifier() {
|
||||
NativeMonitorId::Numeric(num) => num,
|
||||
_ => panic!("OS X monitors should always have a numeric native ID")
|
||||
|
@ -410,7 +411,7 @@ impl Window {
|
|||
};
|
||||
Some(matching_screen.unwrap_or(appkit::NSScreen::mainScreen(nil)))
|
||||
},
|
||||
None => None
|
||||
_ => None,
|
||||
};
|
||||
let frame = match screen {
|
||||
Some(screen) => appkit::NSScreen::frame(screen),
|
||||
|
@ -637,6 +638,14 @@ impl Window {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_maximized(&self, maximized: bool) {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_fullscreen(&self, state: FullScreenState) {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the `cocoa::base::id` associated with a window to a usize to use as a unique identifier
|
||||
|
|
|
@ -20,6 +20,8 @@ use CreationError;
|
|||
use CursorState;
|
||||
use MouseCursor;
|
||||
use WindowAttributes;
|
||||
use FullScreenState;
|
||||
use MonitorId as RootMonitorId;
|
||||
|
||||
use dwmapi;
|
||||
use kernel32;
|
||||
|
@ -276,6 +278,14 @@ impl Window {
|
|||
pub fn id(&self) -> WindowId {
|
||||
WindowId(self.window.0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_maximized(&self, maximized: bool) {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_fullscreen(&self, state: FullScreenState) {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Window {
|
||||
|
@ -319,13 +329,15 @@ unsafe fn init(window: WindowAttributes, pl_attribs: PlatformSpecificWindowBuild
|
|||
// switching to fullscreen if necessary
|
||||
// this means adjusting the window's position so that it overlaps the right monitor,
|
||||
// and change the monitor's resolution if necessary
|
||||
if window.monitor.is_some() {
|
||||
let monitor = window.monitor.as_ref().unwrap();
|
||||
let fullscreen = if let FullScreenState::Exclusive(RootMonitorId(ref monitor)) = window.fullscreen {
|
||||
try!(switch_to_fullscreen(&mut rect, monitor));
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
// computing the style and extended style of the window
|
||||
let (ex_style, style) = if window.monitor.is_some() || !window.decorations {
|
||||
let (ex_style, style) = if fullscreen || !window.decorations {
|
||||
(winapi::WS_EX_APPWINDOW,
|
||||
//winapi::WS_POPUP is incompatible with winapi::WS_CHILD
|
||||
if pl_attribs.parent.is_some() {
|
||||
|
@ -345,13 +357,13 @@ unsafe fn init(window: WindowAttributes, pl_attribs: PlatformSpecificWindowBuild
|
|||
|
||||
// creating the real window this time, by using the functions in `extra_functions`
|
||||
let real_window = {
|
||||
let (width, height) = if window.monitor.is_some() || window.dimensions.is_some() {
|
||||
let (width, height) = if fullscreen || window.dimensions.is_some() {
|
||||
(Some(rect.right - rect.left), Some(rect.bottom - rect.top))
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
|
||||
let (x, y) = if window.monitor.is_some() {
|
||||
let (x, y) = if fullscreen {
|
||||
(Some(rect.left), Some(rect.top))
|
||||
} else {
|
||||
(None, None)
|
||||
|
@ -425,7 +437,7 @@ unsafe fn init(window: WindowAttributes, pl_attribs: PlatformSpecificWindowBuild
|
|||
}
|
||||
|
||||
// calling SetForegroundWindow if fullscreen
|
||||
if window.monitor.is_some() {
|
||||
if fullscreen {
|
||||
user32::SetForegroundWindow(real_window.0);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ use MouseCursor;
|
|||
use Window;
|
||||
use WindowBuilder;
|
||||
use WindowId;
|
||||
use FullScreenState;
|
||||
use native_monitor::NativeMonitorId;
|
||||
|
||||
use libc;
|
||||
|
@ -56,13 +57,19 @@ impl WindowBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
/// Requests fullscreen mode.
|
||||
/// Sets the fullscreen mode.
|
||||
///
|
||||
/// If you don't specify dimensions for the window, it will match the monitor's.
|
||||
#[inline]
|
||||
pub fn with_fullscreen(mut self, monitor: MonitorId) -> WindowBuilder {
|
||||
let MonitorId(monitor) = monitor;
|
||||
self.window.monitor = Some(monitor);
|
||||
pub fn with_fullscreen(mut self, state: FullScreenState) -> WindowBuilder {
|
||||
self.window.fullscreen = state;
|
||||
self
|
||||
}
|
||||
|
||||
/// Requests maximized mode.
|
||||
#[inline]
|
||||
pub fn with_maximized(mut self, maximized: bool) -> WindowBuilder {
|
||||
self.window.maximized = maximized;
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -100,8 +107,10 @@ impl WindowBuilder {
|
|||
/// out of memory, etc.
|
||||
pub fn build(mut self, events_loop: &EventsLoop) -> Result<Window, CreationError> {
|
||||
// resizing the window to the dimensions of the monitor when fullscreen
|
||||
if self.window.dimensions.is_none() && self.window.monitor.is_some() {
|
||||
self.window.dimensions = Some(self.window.monitor.as_ref().unwrap().get_dimensions())
|
||||
if self.window.dimensions.is_none() {
|
||||
if let FullScreenState::Exclusive(ref monitor) = self.window.fullscreen {
|
||||
self.window.dimensions = Some(monitor.get_dimensions());
|
||||
}
|
||||
}
|
||||
|
||||
// default dimensions
|
||||
|
@ -292,6 +301,18 @@ impl Window {
|
|||
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)
|
||||
}
|
||||
|
||||
/// Sets the window to fullscreen or back
|
||||
#[inline]
|
||||
pub fn set_fullscreen(&self, state: FullScreenState) {
|
||||
self.window.set_fullscreen(state)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn id(&self) -> WindowId {
|
||||
WindowId(self.window.id())
|
||||
|
@ -350,7 +371,7 @@ pub fn get_primary_monitor() -> MonitorId {
|
|||
|
||||
/// Identifier for a monitor.
|
||||
#[derive(Clone)]
|
||||
pub struct MonitorId(platform::MonitorId);
|
||||
pub struct MonitorId(pub platform::MonitorId);
|
||||
|
||||
impl MonitorId {
|
||||
/// Returns a human-readable name of the monitor.
|
||||
|
|
Loading…
Add table
Reference in a new issue