From 97c471dc05b2b9c928758ae23f2f8cafd9d36dda Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Fri, 24 Oct 2014 14:49:07 +1000 Subject: [PATCH] Add an interface for providing system wide initialization options to the windowing system. This allows setting up Linux based systems which use multithreaded OpenGL contexts. --- src/lib.rs | 2 ++ src/x11/ffi.rs | 1 + src/x11/window/mod.rs | 12 ++++++++++++ src/x11/window/monitor.rs | 3 +++ 4 files changed, 18 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 041ebeb4..b443ab7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,6 +37,8 @@ extern crate libc; extern crate cocoa; #[cfg(target_os = "macos")] extern crate core_foundation; +#[cfg(target_os = "linux")] +extern crate sync; pub use events::*; diff --git a/src/x11/ffi.rs b/src/x11/ffi.rs index 822f7558..f9dc3ad7 100644 --- a/src/x11/ffi.rs +++ b/src/x11/ffi.rs @@ -1410,6 +1410,7 @@ extern "C" { pub fn XMoveWindow(display: *mut Display, w: Window, x: libc::c_int, y: libc::c_int); pub fn XMapWindow(display: *mut Display, w: Window); pub fn XNextEvent(display: *mut Display, event_return: *mut XEvent); + pub fn XInitThreads() -> Status; pub fn XOpenDisplay(display_name: *const libc::c_char) -> *mut Display; pub fn XPeekEvent(display: *mut Display, event_return: *mut XEvent); pub fn XRefreshKeyboardMapping(event_map: *const XEvent); diff --git a/src/x11/window/mod.rs b/src/x11/window/mod.rs index cb73958c..9d29c072 100644 --- a/src/x11/window/mod.rs +++ b/src/x11/window/mod.rs @@ -3,12 +3,23 @@ use libc; use std::{mem, ptr}; use std::sync::atomic::AtomicBool; use super::ffi; +use sync::one::{Once, ONCE_INIT}; pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor}; mod events; mod monitor; +static THREAD_INIT: Once = ONCE_INIT; + +fn ensure_thread_init() { + THREAD_INIT.doit(|| { + unsafe { + ffi::XInitThreads(); + } + }); +} + pub struct Window { display: *mut ffi::Display, window: ffi::Window, @@ -24,6 +35,7 @@ pub struct Window { impl Window { pub fn new(builder: WindowBuilder) -> Result { + ensure_thread_init(); let dimensions = builder.dimensions.unwrap_or((800, 600)); // calling XOpenDisplay diff --git a/src/x11/window/monitor.rs b/src/x11/window/monitor.rs index b72ed157..a9e77d79 100644 --- a/src/x11/window/monitor.rs +++ b/src/x11/window/monitor.rs @@ -1,9 +1,11 @@ use std::{ptr}; use super::super::ffi; +use super::ensure_thread_init; pub struct MonitorID(pub uint); pub fn get_available_monitors() -> Vec { + ensure_thread_init(); let nb_monitors = unsafe { let display = ffi::XOpenDisplay(ptr::null()); if display.is_null() { @@ -20,6 +22,7 @@ pub fn get_available_monitors() -> Vec { } pub fn get_primary_monitor() -> MonitorID { + ensure_thread_init(); let primary_monitor = unsafe { let display = ffi::XOpenDisplay(ptr::null()); if display.is_null() {