X11: Fix primary monitor fallback regression (#532)

This commit is contained in:
Francesca Frangipane 2018-05-22 09:07:46 -04:00 committed by GitHub
parent a34147b602
commit 17373a4e91
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -19,7 +19,20 @@ const FORCE_RANDR_COMPAT: bool = false;
const DISABLE_MONITOR_LIST_CACHING: bool = false; const DISABLE_MONITOR_LIST_CACHING: bool = false;
lazy_static! { lazy_static! {
static ref MONITORS: Mutex<Option<Vec<MonitorId>>> = Mutex::new(None); static ref XRANDR_VERSION: Mutex<Option<(c_int, c_int)>> = Mutex::default();
static ref MONITORS: Mutex<Option<Vec<MonitorId>>> = Mutex::default();
}
fn version_is_at_least(major: c_int, minor: c_int) -> bool {
if let Some((avail_major, avail_minor)) = *XRANDR_VERSION.lock() {
if avail_major == major {
avail_minor >= minor
} else {
avail_major > major
}
} else {
unreachable!();
}
} }
pub fn invalidate_cached_monitor_list() -> Option<Vec<MonitorId>> { pub fn invalidate_cached_monitor_list() -> Option<Vec<MonitorId>> {
@ -128,17 +141,20 @@ fn query_monitor_list(xconn: &Arc<XConnection>) -> Vec<MonitorId> {
} }
let mut available; let mut available;
let mut has_primary = false;
if xconn.xrandr_1_5.is_some() && !FORCE_RANDR_COMPAT { if xconn.xrandr_1_5.is_some() && version_is_at_least(1, 5) && !FORCE_RANDR_COMPAT {
// We're in XRandR >= 1.5, enumerate monitors. This supports things like MST and // We're in XRandR >= 1.5, enumerate monitors. This supports things like MST and
// videowalls. // videowalls.
let xrandr_1_5 = xconn.xrandr_1_5.as_ref().unwrap(); let xrandr_1_5 = xconn.xrandr_1_5.as_ref().unwrap();
let mut monitor_count = 0; let mut monitor_count = 0;
let monitors = (xrandr_1_5.XRRGetMonitors)(xconn.display, root, 1, &mut monitor_count); let monitors = (xrandr_1_5.XRRGetMonitors)(xconn.display, root, 1, &mut monitor_count);
assert!(monitor_count >= 0);
available = Vec::with_capacity(monitor_count as usize); available = Vec::with_capacity(monitor_count as usize);
for monitor_index in 0..monitor_count { for monitor_index in 0..monitor_count {
let monitor = monitors.offset(monitor_index as isize); let monitor = monitors.offset(monitor_index as isize);
let is_primary = (*monitor).primary != 0; let is_primary = (*monitor).primary != 0;
has_primary |= is_primary;
available.push(MonitorId::from_repr( available.push(MonitorId::from_repr(
xconn, xconn,
resources, resources,
@ -161,6 +177,7 @@ fn query_monitor_list(xconn: &Arc<XConnection>) -> Vec<MonitorId> {
if is_active { if is_active {
let crtc = util::MonitorRepr::from(crtc); let crtc = util::MonitorRepr::from(crtc);
let is_primary = crtc.get_output() == primary; let is_primary = crtc.get_output() == primary;
has_primary |= is_primary;
available.push(MonitorId::from_repr( available.push(MonitorId::from_repr(
xconn, xconn,
resources, resources,
@ -173,6 +190,14 @@ fn query_monitor_list(xconn: &Arc<XConnection>) -> Vec<MonitorId> {
} }
} }
// If no monitors were detected as being primary, we just pick one ourselves!
if !has_primary {
if let Some(ref mut fallback) = available.first_mut() {
// Setting this here will come in handy if we ever add an `is_primary` method.
fallback.primary = true;
}
}
(xconn.xrandr.XRRFreeScreenResources)(resources); (xconn.xrandr.XRRFreeScreenResources)(resources);
available available
} }
@ -194,20 +219,21 @@ pub fn get_available_monitors(xconn: &Arc<XConnection>) -> Vec<MonitorId> {
} }
#[inline] #[inline]
pub fn get_primary_monitor(x: &Arc<XConnection>) -> MonitorId { pub fn get_primary_monitor(xconn: &Arc<XConnection>) -> MonitorId {
let mut available_monitors = get_available_monitors(x).into_iter(); get_available_monitors(xconn)
available_monitors .into_iter()
.find(|m| m.primary) .find(|monitor| monitor.primary)
// If no monitors were detected as being primary, we just pick one ourselves!
.or_else(|| available_monitors.next())
.expect("[winit] Failed to find any monitors using XRandR.") .expect("[winit] Failed to find any monitors using XRandR.")
} }
pub fn select_input(xconn: &Arc<XConnection>, root: Window) -> Result<c_int, XError> { pub fn select_input(xconn: &Arc<XConnection>, root: Window) -> Result<c_int, XError> {
{
let mut version_lock = XRANDR_VERSION.lock();
if version_lock.is_none() {
let mut major = 0; let mut major = 0;
let mut minor = 0; let mut minor = 0;
let has_extension = unsafe { let has_extension = unsafe {
(xconn.xrandr.XRRQueryExtension)( (xconn.xrandr.XRRQueryVersion)(
xconn.display, xconn.display,
&mut major, &mut major,
&mut minor, &mut minor,
@ -216,6 +242,9 @@ pub fn select_input(xconn: &Arc<XConnection>, root: Window) -> Result<c_int, XEr
if has_extension != True { if has_extension != True {
panic!("[winit] XRandR extension not available."); panic!("[winit] XRandR extension not available.");
} }
*version_lock = Some((major, minor));
}
}
let mut event_offset = 0; let mut event_offset = 0;
let mut error_offset = 0; let mut error_offset = 0;