winit/src/platform/linux/x11/monitor.rs

107 lines
3.9 KiB
Rust
Raw Normal View History

use std::sync::Arc;
Move fullscreen modes to not touch physical resolutions (#270) * Fix X11 screen resolution change using XrandR The previous XF86 resolution switching was broken and everything seems to have moved on to xrandr. Use that instead while cleaning up the code a bit as well. * Use XRandR for actual multiscreen support in X11 * Use actual monitor names in X11 * Get rid of ptr::read usage in X11 * Use a bog standard Vec instead of VecDeque * Get rid of the XRandR mode switching stuff Wayland has made the decision that apps shouldn't change screen resolutions and just take the screens as they've been setup. In the modern world where GPU scaling is cheap and LCD panels are scaling anyway it makes no sense to make "physical" resolution changes when software should be taking care of it. This massively simplifies the code and makes it easier to extend to more niche setups like MST and videowalls. * Rename fullscreen options to match new semantics * Implement XRandR 1.5 support * Get rid of the FullScreen enum Moving to just having two states None and Some(MonitorId) and then being able to set full screen in the current monitor with something like: window.set_fullscreen(Some(window.current_monitor())); * Implement Window::get_current_monitor() Do it by iterating over the available monitors and finding which has the biggest overlap with the window. For this MonitorId needs a new get_position() that needs to be implemented for all platforms. * Add unimplemented get_position() to all MonitorId * Make get_current_monitor() platform specific * Add unimplemented get_current_monitor() to all * Implement proper primary monitor selection in X11 * Shut up some warnings * Remove libxxf86vm package from travis Since we're no longer using XF86 there's no need to keep the package around for CI. * Don't use new struct syntax * Fix indentation * Adjust Android/iOS fullscreen/maximized On Android and iOS we can assume single screen apps that are already fullscreen and maximized so there are a few methods that are implemented by just returning a fixed value or not doing anything. * Mark OSX/Win fullscreen/maximized unimplemented()! These would be safe as no-ops but we should make it explicit so there is more of an incentive to actually implement them.
2017-09-07 09:33:46 +01:00
use std::slice;
use super::XConnection;
2015-07-19 13:53:40 +02:00
#[derive(Clone)]
Move fullscreen modes to not touch physical resolutions (#270) * Fix X11 screen resolution change using XrandR The previous XF86 resolution switching was broken and everything seems to have moved on to xrandr. Use that instead while cleaning up the code a bit as well. * Use XRandR for actual multiscreen support in X11 * Use actual monitor names in X11 * Get rid of ptr::read usage in X11 * Use a bog standard Vec instead of VecDeque * Get rid of the XRandR mode switching stuff Wayland has made the decision that apps shouldn't change screen resolutions and just take the screens as they've been setup. In the modern world where GPU scaling is cheap and LCD panels are scaling anyway it makes no sense to make "physical" resolution changes when software should be taking care of it. This massively simplifies the code and makes it easier to extend to more niche setups like MST and videowalls. * Rename fullscreen options to match new semantics * Implement XRandR 1.5 support * Get rid of the FullScreen enum Moving to just having two states None and Some(MonitorId) and then being able to set full screen in the current monitor with something like: window.set_fullscreen(Some(window.current_monitor())); * Implement Window::get_current_monitor() Do it by iterating over the available monitors and finding which has the biggest overlap with the window. For this MonitorId needs a new get_position() that needs to be implemented for all platforms. * Add unimplemented get_position() to all MonitorId * Make get_current_monitor() platform specific * Add unimplemented get_current_monitor() to all * Implement proper primary monitor selection in X11 * Shut up some warnings * Remove libxxf86vm package from travis Since we're no longer using XF86 there's no need to keep the package around for CI. * Don't use new struct syntax * Fix indentation * Adjust Android/iOS fullscreen/maximized On Android and iOS we can assume single screen apps that are already fullscreen and maximized so there are a few methods that are implemented by just returning a fixed value or not doing anything. * Mark OSX/Win fullscreen/maximized unimplemented()! These would be safe as no-ops but we should make it explicit so there is more of an incentive to actually implement them.
2017-09-07 09:33:46 +01:00
pub struct MonitorId {
/// The actual id
id: u32,
/// The name of the monitor
name: String,
/// The size of the monitor
dimensions: (u32, u32),
/// The position of the monitor in the X screen
position: (i32, i32),
Move fullscreen modes to not touch physical resolutions (#270) * Fix X11 screen resolution change using XrandR The previous XF86 resolution switching was broken and everything seems to have moved on to xrandr. Use that instead while cleaning up the code a bit as well. * Use XRandR for actual multiscreen support in X11 * Use actual monitor names in X11 * Get rid of ptr::read usage in X11 * Use a bog standard Vec instead of VecDeque * Get rid of the XRandR mode switching stuff Wayland has made the decision that apps shouldn't change screen resolutions and just take the screens as they've been setup. In the modern world where GPU scaling is cheap and LCD panels are scaling anyway it makes no sense to make "physical" resolution changes when software should be taking care of it. This massively simplifies the code and makes it easier to extend to more niche setups like MST and videowalls. * Rename fullscreen options to match new semantics * Implement XRandR 1.5 support * Get rid of the FullScreen enum Moving to just having two states None and Some(MonitorId) and then being able to set full screen in the current monitor with something like: window.set_fullscreen(Some(window.current_monitor())); * Implement Window::get_current_monitor() Do it by iterating over the available monitors and finding which has the biggest overlap with the window. For this MonitorId needs a new get_position() that needs to be implemented for all platforms. * Add unimplemented get_position() to all MonitorId * Make get_current_monitor() platform specific * Add unimplemented get_current_monitor() to all * Implement proper primary monitor selection in X11 * Shut up some warnings * Remove libxxf86vm package from travis Since we're no longer using XF86 there's no need to keep the package around for CI. * Don't use new struct syntax * Fix indentation * Adjust Android/iOS fullscreen/maximized On Android and iOS we can assume single screen apps that are already fullscreen and maximized so there are a few methods that are implemented by just returning a fixed value or not doing anything. * Mark OSX/Win fullscreen/maximized unimplemented()! These would be safe as no-ops but we should make it explicit so there is more of an incentive to actually implement them.
2017-09-07 09:33:46 +01:00
/// If the monitor is the primary one
primary: bool,
}
2015-05-07 13:14:09 +02:00
Move fullscreen modes to not touch physical resolutions (#270) * Fix X11 screen resolution change using XrandR The previous XF86 resolution switching was broken and everything seems to have moved on to xrandr. Use that instead while cleaning up the code a bit as well. * Use XRandR for actual multiscreen support in X11 * Use actual monitor names in X11 * Get rid of ptr::read usage in X11 * Use a bog standard Vec instead of VecDeque * Get rid of the XRandR mode switching stuff Wayland has made the decision that apps shouldn't change screen resolutions and just take the screens as they've been setup. In the modern world where GPU scaling is cheap and LCD panels are scaling anyway it makes no sense to make "physical" resolution changes when software should be taking care of it. This massively simplifies the code and makes it easier to extend to more niche setups like MST and videowalls. * Rename fullscreen options to match new semantics * Implement XRandR 1.5 support * Get rid of the FullScreen enum Moving to just having two states None and Some(MonitorId) and then being able to set full screen in the current monitor with something like: window.set_fullscreen(Some(window.current_monitor())); * Implement Window::get_current_monitor() Do it by iterating over the available monitors and finding which has the biggest overlap with the window. For this MonitorId needs a new get_position() that needs to be implemented for all platforms. * Add unimplemented get_position() to all MonitorId * Make get_current_monitor() platform specific * Add unimplemented get_current_monitor() to all * Implement proper primary monitor selection in X11 * Shut up some warnings * Remove libxxf86vm package from travis Since we're no longer using XF86 there's no need to keep the package around for CI. * Don't use new struct syntax * Fix indentation * Adjust Android/iOS fullscreen/maximized On Android and iOS we can assume single screen apps that are already fullscreen and maximized so there are a few methods that are implemented by just returning a fixed value or not doing anything. * Mark OSX/Win fullscreen/maximized unimplemented()! These would be safe as no-ops but we should make it explicit so there is more of an incentive to actually implement them.
2017-09-07 09:33:46 +01:00
pub fn get_available_monitors(x: &Arc<XConnection>) -> Vec<MonitorId> {
let mut available = Vec::new();
unsafe {
let root = (x.xlib.XDefaultRootWindow)(x.display);
let resources = (x.xrandr.XRRGetScreenResources)(x.display, root);
Move fullscreen modes to not touch physical resolutions (#270) * Fix X11 screen resolution change using XrandR The previous XF86 resolution switching was broken and everything seems to have moved on to xrandr. Use that instead while cleaning up the code a bit as well. * Use XRandR for actual multiscreen support in X11 * Use actual monitor names in X11 * Get rid of ptr::read usage in X11 * Use a bog standard Vec instead of VecDeque * Get rid of the XRandR mode switching stuff Wayland has made the decision that apps shouldn't change screen resolutions and just take the screens as they've been setup. In the modern world where GPU scaling is cheap and LCD panels are scaling anyway it makes no sense to make "physical" resolution changes when software should be taking care of it. This massively simplifies the code and makes it easier to extend to more niche setups like MST and videowalls. * Rename fullscreen options to match new semantics * Implement XRandR 1.5 support * Get rid of the FullScreen enum Moving to just having two states None and Some(MonitorId) and then being able to set full screen in the current monitor with something like: window.set_fullscreen(Some(window.current_monitor())); * Implement Window::get_current_monitor() Do it by iterating over the available monitors and finding which has the biggest overlap with the window. For this MonitorId needs a new get_position() that needs to be implemented for all platforms. * Add unimplemented get_position() to all MonitorId * Make get_current_monitor() platform specific * Add unimplemented get_current_monitor() to all * Implement proper primary monitor selection in X11 * Shut up some warnings * Remove libxxf86vm package from travis Since we're no longer using XF86 there's no need to keep the package around for CI. * Don't use new struct syntax * Fix indentation * Adjust Android/iOS fullscreen/maximized On Android and iOS we can assume single screen apps that are already fullscreen and maximized so there are a few methods that are implemented by just returning a fixed value or not doing anything. * Mark OSX/Win fullscreen/maximized unimplemented()! These would be safe as no-ops but we should make it explicit so there is more of an incentive to actually implement them.
2017-09-07 09:33:46 +01:00
let mut major = 0;
let mut minor = 0;
(x.xrandr.XRRQueryVersion)(x.display, &mut major, &mut minor);
if ((major as u64)<<32)+(minor as u64) >= (1<<32)+5 {
// We're in XRandR >= 1.5, enumerate Monitors to handle things like MST and videowalls
let mut nmonitors = 0;
let monitors = (x.xrandr.XRRGetMonitors)(x.display, root, 1, &mut nmonitors);
for i in 0..nmonitors {
let monitor = *(monitors.offset(i as isize));
let output = (x.xrandr.XRRGetOutputInfo)(x.display, resources, *(monitor.outputs.offset(0)));
let nameslice = slice::from_raw_parts((*output).name as *mut u8, (*output).nameLen as usize);
let name = String::from_utf8_lossy(nameslice).into_owned();
(x.xrandr.XRRFreeOutputInfo)(output);
available.push(MonitorId{
id: i as u32,
name,
dimensions: (monitor.width as u32, monitor.height as u32),
position: (monitor.x as i32, monitor.y as i32),
Move fullscreen modes to not touch physical resolutions (#270) * Fix X11 screen resolution change using XrandR The previous XF86 resolution switching was broken and everything seems to have moved on to xrandr. Use that instead while cleaning up the code a bit as well. * Use XRandR for actual multiscreen support in X11 * Use actual monitor names in X11 * Get rid of ptr::read usage in X11 * Use a bog standard Vec instead of VecDeque * Get rid of the XRandR mode switching stuff Wayland has made the decision that apps shouldn't change screen resolutions and just take the screens as they've been setup. In the modern world where GPU scaling is cheap and LCD panels are scaling anyway it makes no sense to make "physical" resolution changes when software should be taking care of it. This massively simplifies the code and makes it easier to extend to more niche setups like MST and videowalls. * Rename fullscreen options to match new semantics * Implement XRandR 1.5 support * Get rid of the FullScreen enum Moving to just having two states None and Some(MonitorId) and then being able to set full screen in the current monitor with something like: window.set_fullscreen(Some(window.current_monitor())); * Implement Window::get_current_monitor() Do it by iterating over the available monitors and finding which has the biggest overlap with the window. For this MonitorId needs a new get_position() that needs to be implemented for all platforms. * Add unimplemented get_position() to all MonitorId * Make get_current_monitor() platform specific * Add unimplemented get_current_monitor() to all * Implement proper primary monitor selection in X11 * Shut up some warnings * Remove libxxf86vm package from travis Since we're no longer using XF86 there's no need to keep the package around for CI. * Don't use new struct syntax * Fix indentation * Adjust Android/iOS fullscreen/maximized On Android and iOS we can assume single screen apps that are already fullscreen and maximized so there are a few methods that are implemented by just returning a fixed value or not doing anything. * Mark OSX/Win fullscreen/maximized unimplemented()! These would be safe as no-ops but we should make it explicit so there is more of an incentive to actually implement them.
2017-09-07 09:33:46 +01:00
primary: (monitor.primary != 0),
});
}
(x.xrandr.XRRFreeMonitors)(monitors);
} else {
// We're in XRandR < 1.5, enumerate CRTCs. Everything will work but MST and
// videowall setups will show more monitors than the logical groups the user
// cares about
for i in 0..(*resources).ncrtc {
let crtcid = *((*resources).crtcs.offset(i as isize));
let crtc = (x.xrandr.XRRGetCrtcInfo)(x.display, resources, crtcid);
if (*crtc).width > 0 && (*crtc).height > 0 && (*crtc).noutput > 0 {
let output = (x.xrandr.XRRGetOutputInfo)(x.display, resources, *((*crtc).outputs.offset(0)));
let nameslice = slice::from_raw_parts((*output).name as *mut u8, (*output).nameLen as usize);
let name = String::from_utf8_lossy(nameslice).into_owned();
(x.xrandr.XRRFreeOutputInfo)(output);
available.push(MonitorId{
id: crtcid as u32,
name,
dimensions: ((*crtc).width as u32, (*crtc).height as u32),
position: ((*crtc).x as i32, (*crtc).y as i32),
Move fullscreen modes to not touch physical resolutions (#270) * Fix X11 screen resolution change using XrandR The previous XF86 resolution switching was broken and everything seems to have moved on to xrandr. Use that instead while cleaning up the code a bit as well. * Use XRandR for actual multiscreen support in X11 * Use actual monitor names in X11 * Get rid of ptr::read usage in X11 * Use a bog standard Vec instead of VecDeque * Get rid of the XRandR mode switching stuff Wayland has made the decision that apps shouldn't change screen resolutions and just take the screens as they've been setup. In the modern world where GPU scaling is cheap and LCD panels are scaling anyway it makes no sense to make "physical" resolution changes when software should be taking care of it. This massively simplifies the code and makes it easier to extend to more niche setups like MST and videowalls. * Rename fullscreen options to match new semantics * Implement XRandR 1.5 support * Get rid of the FullScreen enum Moving to just having two states None and Some(MonitorId) and then being able to set full screen in the current monitor with something like: window.set_fullscreen(Some(window.current_monitor())); * Implement Window::get_current_monitor() Do it by iterating over the available monitors and finding which has the biggest overlap with the window. For this MonitorId needs a new get_position() that needs to be implemented for all platforms. * Add unimplemented get_position() to all MonitorId * Make get_current_monitor() platform specific * Add unimplemented get_current_monitor() to all * Implement proper primary monitor selection in X11 * Shut up some warnings * Remove libxxf86vm package from travis Since we're no longer using XF86 there's no need to keep the package around for CI. * Don't use new struct syntax * Fix indentation * Adjust Android/iOS fullscreen/maximized On Android and iOS we can assume single screen apps that are already fullscreen and maximized so there are a few methods that are implemented by just returning a fixed value or not doing anything. * Mark OSX/Win fullscreen/maximized unimplemented()! These would be safe as no-ops but we should make it explicit so there is more of an incentive to actually implement them.
2017-09-07 09:33:46 +01:00
primary: true,
});
}
(x.xrandr.XRRFreeCrtcInfo)(crtc);
}
}
(x.xrandr.XRRFreeScreenResources)(resources);
}
available
}
2015-09-21 14:42:05 +02:00
#[inline]
2015-09-24 09:11:59 +02:00
pub fn get_primary_monitor(x: &Arc<XConnection>) -> MonitorId {
get_available_monitors(x).into_iter().find(|m| m.primary)
// 'no primary' case is better handled picking some existing monitor
.or_else(|| get_available_monitors(x).into_iter().next())
.expect("[winit] Failed to find any x11 monitor")
}
2015-09-24 09:11:59 +02:00
impl MonitorId {
pub fn get_name(&self) -> Option<String> {
Move fullscreen modes to not touch physical resolutions (#270) * Fix X11 screen resolution change using XrandR The previous XF86 resolution switching was broken and everything seems to have moved on to xrandr. Use that instead while cleaning up the code a bit as well. * Use XRandR for actual multiscreen support in X11 * Use actual monitor names in X11 * Get rid of ptr::read usage in X11 * Use a bog standard Vec instead of VecDeque * Get rid of the XRandR mode switching stuff Wayland has made the decision that apps shouldn't change screen resolutions and just take the screens as they've been setup. In the modern world where GPU scaling is cheap and LCD panels are scaling anyway it makes no sense to make "physical" resolution changes when software should be taking care of it. This massively simplifies the code and makes it easier to extend to more niche setups like MST and videowalls. * Rename fullscreen options to match new semantics * Implement XRandR 1.5 support * Get rid of the FullScreen enum Moving to just having two states None and Some(MonitorId) and then being able to set full screen in the current monitor with something like: window.set_fullscreen(Some(window.current_monitor())); * Implement Window::get_current_monitor() Do it by iterating over the available monitors and finding which has the biggest overlap with the window. For this MonitorId needs a new get_position() that needs to be implemented for all platforms. * Add unimplemented get_position() to all MonitorId * Make get_current_monitor() platform specific * Add unimplemented get_current_monitor() to all * Implement proper primary monitor selection in X11 * Shut up some warnings * Remove libxxf86vm package from travis Since we're no longer using XF86 there's no need to keep the package around for CI. * Don't use new struct syntax * Fix indentation * Adjust Android/iOS fullscreen/maximized On Android and iOS we can assume single screen apps that are already fullscreen and maximized so there are a few methods that are implemented by just returning a fixed value or not doing anything. * Mark OSX/Win fullscreen/maximized unimplemented()! These would be safe as no-ops but we should make it explicit so there is more of an incentive to actually implement them.
2017-09-07 09:33:46 +01:00
Some(self.name.clone())
}
2015-09-21 14:42:05 +02:00
#[inline]
pub fn get_native_identifier(&self) -> u32 {
Move fullscreen modes to not touch physical resolutions (#270) * Fix X11 screen resolution change using XrandR The previous XF86 resolution switching was broken and everything seems to have moved on to xrandr. Use that instead while cleaning up the code a bit as well. * Use XRandR for actual multiscreen support in X11 * Use actual monitor names in X11 * Get rid of ptr::read usage in X11 * Use a bog standard Vec instead of VecDeque * Get rid of the XRandR mode switching stuff Wayland has made the decision that apps shouldn't change screen resolutions and just take the screens as they've been setup. In the modern world where GPU scaling is cheap and LCD panels are scaling anyway it makes no sense to make "physical" resolution changes when software should be taking care of it. This massively simplifies the code and makes it easier to extend to more niche setups like MST and videowalls. * Rename fullscreen options to match new semantics * Implement XRandR 1.5 support * Get rid of the FullScreen enum Moving to just having two states None and Some(MonitorId) and then being able to set full screen in the current monitor with something like: window.set_fullscreen(Some(window.current_monitor())); * Implement Window::get_current_monitor() Do it by iterating over the available monitors and finding which has the biggest overlap with the window. For this MonitorId needs a new get_position() that needs to be implemented for all platforms. * Add unimplemented get_position() to all MonitorId * Make get_current_monitor() platform specific * Add unimplemented get_current_monitor() to all * Implement proper primary monitor selection in X11 * Shut up some warnings * Remove libxxf86vm package from travis Since we're no longer using XF86 there's no need to keep the package around for CI. * Don't use new struct syntax * Fix indentation * Adjust Android/iOS fullscreen/maximized On Android and iOS we can assume single screen apps that are already fullscreen and maximized so there are a few methods that are implemented by just returning a fixed value or not doing anything. * Mark OSX/Win fullscreen/maximized unimplemented()! These would be safe as no-ops but we should make it explicit so there is more of an incentive to actually implement them.
2017-09-07 09:33:46 +01:00
self.id as u32
}
pub fn get_dimensions(&self) -> (u32, u32) {
Move fullscreen modes to not touch physical resolutions (#270) * Fix X11 screen resolution change using XrandR The previous XF86 resolution switching was broken and everything seems to have moved on to xrandr. Use that instead while cleaning up the code a bit as well. * Use XRandR for actual multiscreen support in X11 * Use actual monitor names in X11 * Get rid of ptr::read usage in X11 * Use a bog standard Vec instead of VecDeque * Get rid of the XRandR mode switching stuff Wayland has made the decision that apps shouldn't change screen resolutions and just take the screens as they've been setup. In the modern world where GPU scaling is cheap and LCD panels are scaling anyway it makes no sense to make "physical" resolution changes when software should be taking care of it. This massively simplifies the code and makes it easier to extend to more niche setups like MST and videowalls. * Rename fullscreen options to match new semantics * Implement XRandR 1.5 support * Get rid of the FullScreen enum Moving to just having two states None and Some(MonitorId) and then being able to set full screen in the current monitor with something like: window.set_fullscreen(Some(window.current_monitor())); * Implement Window::get_current_monitor() Do it by iterating over the available monitors and finding which has the biggest overlap with the window. For this MonitorId needs a new get_position() that needs to be implemented for all platforms. * Add unimplemented get_position() to all MonitorId * Make get_current_monitor() platform specific * Add unimplemented get_current_monitor() to all * Implement proper primary monitor selection in X11 * Shut up some warnings * Remove libxxf86vm package from travis Since we're no longer using XF86 there's no need to keep the package around for CI. * Don't use new struct syntax * Fix indentation * Adjust Android/iOS fullscreen/maximized On Android and iOS we can assume single screen apps that are already fullscreen and maximized so there are a few methods that are implemented by just returning a fixed value or not doing anything. * Mark OSX/Win fullscreen/maximized unimplemented()! These would be safe as no-ops but we should make it explicit so there is more of an incentive to actually implement them.
2017-09-07 09:33:46 +01:00
self.dimensions
}
pub fn get_position(&self) -> (i32, i32) {
Move fullscreen modes to not touch physical resolutions (#270) * Fix X11 screen resolution change using XrandR The previous XF86 resolution switching was broken and everything seems to have moved on to xrandr. Use that instead while cleaning up the code a bit as well. * Use XRandR for actual multiscreen support in X11 * Use actual monitor names in X11 * Get rid of ptr::read usage in X11 * Use a bog standard Vec instead of VecDeque * Get rid of the XRandR mode switching stuff Wayland has made the decision that apps shouldn't change screen resolutions and just take the screens as they've been setup. In the modern world where GPU scaling is cheap and LCD panels are scaling anyway it makes no sense to make "physical" resolution changes when software should be taking care of it. This massively simplifies the code and makes it easier to extend to more niche setups like MST and videowalls. * Rename fullscreen options to match new semantics * Implement XRandR 1.5 support * Get rid of the FullScreen enum Moving to just having two states None and Some(MonitorId) and then being able to set full screen in the current monitor with something like: window.set_fullscreen(Some(window.current_monitor())); * Implement Window::get_current_monitor() Do it by iterating over the available monitors and finding which has the biggest overlap with the window. For this MonitorId needs a new get_position() that needs to be implemented for all platforms. * Add unimplemented get_position() to all MonitorId * Make get_current_monitor() platform specific * Add unimplemented get_current_monitor() to all * Implement proper primary monitor selection in X11 * Shut up some warnings * Remove libxxf86vm package from travis Since we're no longer using XF86 there's no need to keep the package around for CI. * Don't use new struct syntax * Fix indentation * Adjust Android/iOS fullscreen/maximized On Android and iOS we can assume single screen apps that are already fullscreen and maximized so there are a few methods that are implemented by just returning a fixed value or not doing anything. * Mark OSX/Win fullscreen/maximized unimplemented()! These would be safe as no-ops but we should make it explicit so there is more of an incentive to actually implement them.
2017-09-07 09:33:46 +01:00
self.position
}
#[inline]
pub fn get_hidpi_factor(&self) -> f32 {
1.0
}
}