aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authortomaka <pierre.krieger1708@gmail.com>2015-11-11 20:38:12 +0100
committertomaka <pierre.krieger1708@gmail.com>2015-11-11 20:38:12 +0100
commit6a3ee2af759cf803d787cf6dcbafcdcc4e0243cd (patch)
tree370fce1fb081e0e1233fcf3eef848d6d92100cf5 /src
parent5ca4e89dd4427464a11417cd127c67ee96d5fae1 (diff)
parentc068a770f0faec9a0fed199e9e9dfc0a00599e97 (diff)
downloadglutin-6a3ee2af759cf803d787cf6dcbafcdcc4e0243cd.tar.gz
glutin-6a3ee2af759cf803d787cf6dcbafcdcc4e0243cd.zip
Merge pull request #646 from adambadawy/master
Fix fullscreen on X11
Diffstat (limited to 'src')
-rw-r--r--src/api/x11/window.rs91
1 files changed, 73 insertions, 18 deletions
diff --git a/src/api/x11/window.rs b/src/api/x11/window.rs
index b964fed..d82c5dd 100644
--- a/src/api/x11/window.rs
+++ b/src/api/x11/window.rs
@@ -54,7 +54,7 @@ pub struct XWindow {
pub context: Context,
is_fullscreen: bool,
screen_id: libc::c_int,
- xf86_desk_mode: *mut ffi::XF86VidModeModeInfo,
+ xf86_desk_mode: ffi::XF86VidModeModeInfo,
ic: ffi::XIC,
im: ffi::XIM,
colormap: ffi::Colormap,
@@ -87,7 +87,7 @@ impl Drop for XWindow {
let _lock = GLOBAL_XOPENIM_LOCK.lock().unwrap();
if self.is_fullscreen {
- (self.display.xf86vmode.XF86VidModeSwitchToMode)(self.display.display, self.screen_id, self.xf86_desk_mode);
+ (self.display.xf86vmode.XF86VidModeSwitchToMode)(self.display.display, self.screen_id, &mut self.xf86_desk_mode);
(self.display.xf86vmode.XF86VidModeSetViewPort)(self.display.display, self.screen_id, 0, 0);
}
@@ -317,15 +317,12 @@ impl Window {
return Err(OsError(format!("Could not query the video modes")));
}
- let xf86_desk_mode = *modes.offset(0);
-
- // FIXME: `XF86VidModeModeInfo` is missing its `hskew` field. Therefore we point to
- // `vsyncstart` instead of `vdisplay` as a temporary hack.
+ 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.vsyncstart == dimensions.1 as u16);
+ }).find(|m| m.hdisplay == dimensions.0 as u16 && m.vdisplay == dimensions.1 as u16);
if let Some(matching_mode) = matching_mode {
Some(matching_mode)
@@ -333,7 +330,7 @@ impl Window {
} 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.vsyncstart == dimensions.1 as u16);
+ }).find(|m| m.hdisplay >= dimensions.0 as u16 && m.vdisplay >= dimensions.1 as u16);
match m {
Some(m) => Some(m),
@@ -435,16 +432,6 @@ impl Window {
window_attributes |= ffi::CWBackPixel;
}
- // switching to fullscreen
- if let Some(mut mode_to_switch_to) = mode_to_switch_to {
- window_attributes |= ffi::CWOverrideRedirect;
- unsafe {
- (display.xf86vmode.XF86VidModeSwitchToMode)(display.display, screen_id, &mut mode_to_switch_to);
- (display.xf86vmode.XF86VidModeSetViewPort)(display.display, screen_id, 0, 0);
- set_win_attr.override_redirect = 1;
- }
- }
-
// finally creating the window
let window = unsafe {
let win = (display.xlib.XCreateWindow)(display.display, root, 0, 0, dimensions.0 as libc::c_uint,
@@ -527,6 +514,64 @@ 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)
+ )
+ };
+ let fullscreen_atom = unsafe {
+ with_c_str("_NET_WM_STATE_FULLSCREEN", |state_fullscreen|
+ (display.xlib.XInternAtom)(display.display, state_fullscreen, 0)
+ )
+ };
+
+ 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 i64);
+ 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 _
+ );
+ }
+
+ 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
+ );
+ }
+ }
+ else {
+ println!("[glutin] Unexpected state: `mode` is None creating fullscreen window");
+ }
+ unsafe {
+ (display.xf86vmode.XF86VidModeSetViewPort)(display.display, screen_id, 0, 0);
+ }
+ }
+
// finish creating the OpenGL context
let context = match context {
Prototype::Glx(ctxt) => {
@@ -565,6 +610,16 @@ impl Window {
input_handler: Mutex::new(XInputEventHandler::new(display, window, ic, window_attrs))
};
+ unsafe {
+ let ref x_window: &XWindow = window.x.borrow();
+ (display.xlib.XSetInputFocus)(
+ display.display,
+ x_window.window,
+ ffi::RevertToParent,
+ ffi::CurrentTime
+ );
+ }
+
// returning
Ok(window)
}