mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 06:11:30 +11:00
Introduce a WindowProxy for accessing a subset of functionality
from other threads. This currently provides a way for other threads to wakeup a blocked event loop on X11. Other platforms have stub functions that need to be implemented. This is similar to the functionality of glfwPostEmptyEvent.
This commit is contained in:
parent
19d120b8b1
commit
9dc5689eef
|
@ -207,6 +207,10 @@ impl Window {
|
|||
pub fn set_inner_size(&self, _x: uint, _y: uint) {
|
||||
}
|
||||
|
||||
pub fn create_window_proxy(&self) -> WindowProxy {
|
||||
WindowProxy
|
||||
}
|
||||
|
||||
pub fn poll_events(&self) -> Vec<Event> {
|
||||
use std::time::Duration;
|
||||
use std::io::timer;
|
||||
|
@ -271,6 +275,16 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "window")]
|
||||
#[deriving(Clone)]
|
||||
pub struct WindowProxy;
|
||||
|
||||
impl WindowProxy {
|
||||
pub fn wakeup_event_loop(&self) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for Window {
|
||||
fn drop(&mut self) {
|
||||
|
|
|
@ -31,6 +31,9 @@ pub enum Event {
|
|||
|
||||
/// An event from the mouse has been received.
|
||||
MouseInput(ElementState, MouseButton),
|
||||
|
||||
/// The window should be redrawn.
|
||||
Refresh,
|
||||
}
|
||||
|
||||
pub type ScanCode = u8;
|
||||
|
|
31
src/lib.rs
31
src/lib.rs
|
@ -473,6 +473,15 @@ impl Window {
|
|||
pub fn get_api(&self) -> Api {
|
||||
self.window.get_api()
|
||||
}
|
||||
|
||||
/// Create a window proxy for this window, that can be freely
|
||||
/// passed to different threads.
|
||||
#[inline]
|
||||
pub fn create_window_proxy(&self) -> WindowProxy {
|
||||
WindowProxy {
|
||||
proxy: self.window.create_window_proxy()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "window")]
|
||||
|
@ -482,6 +491,28 @@ impl gl_common::GlFunctionsSource for Window {
|
|||
}
|
||||
}
|
||||
|
||||
/// Represents a thread safe subset of operations that can be called
|
||||
/// on a window. This structure can be safely cloned and sent between
|
||||
/// threads.
|
||||
///
|
||||
#[cfg(feature = "window")]
|
||||
#[deriving(Clone)]
|
||||
pub struct WindowProxy {
|
||||
proxy: winimpl::WindowProxy,
|
||||
}
|
||||
|
||||
#[cfg(feature = "window")]
|
||||
impl WindowProxy {
|
||||
|
||||
/// Triggers a blocked event loop to wake up. This is
|
||||
/// typically called when another thread wants to wake
|
||||
/// up the blocked rendering thread to cause a refresh.
|
||||
#[inline]
|
||||
pub fn wakeup_event_loop(&self) {
|
||||
self.proxy.wakeup_event_loop();
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a headless OpenGL context.
|
||||
#[cfg(feature = "headless")]
|
||||
pub struct HeadlessContext {
|
||||
|
|
|
@ -74,6 +74,16 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "window")]
|
||||
#[deriving(Clone)]
|
||||
pub struct WindowProxy;
|
||||
|
||||
impl WindowProxy {
|
||||
pub fn wakeup_event_loop(&self) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
extern fn window_should_close(this: id, _: id) -> id {
|
||||
unsafe {
|
||||
let mut stored_value = ptr::null_mut();
|
||||
|
@ -278,6 +288,10 @@ impl Window {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn create_window_proxy(&self) -> WindowProxy {
|
||||
WindowProxy
|
||||
}
|
||||
|
||||
pub fn poll_events(&self) -> Vec<Event> {
|
||||
let mut events = Vec::new();
|
||||
|
||||
|
|
|
@ -83,6 +83,16 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "window")]
|
||||
#[deriving(Clone)]
|
||||
pub struct WindowProxy;
|
||||
|
||||
impl WindowProxy {
|
||||
pub fn wakeup_event_loop(&self) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
impl Window {
|
||||
/// See the docs in the crate root file.
|
||||
pub fn is_closed(&self) -> bool {
|
||||
|
@ -180,6 +190,10 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn create_window_proxy(&self) -> WindowProxy {
|
||||
WindowProxy
|
||||
}
|
||||
|
||||
/// See the docs in the crate root file.
|
||||
// TODO: return iterator
|
||||
pub fn poll_events(&self) -> Vec<Event> {
|
||||
|
|
|
@ -1420,6 +1420,8 @@ extern "C" {
|
|||
x_return: *mut libc::c_int, y_return: *mut libc::c_int,
|
||||
width_return: *mut libc::c_uint, height_return: *mut libc::c_uint,
|
||||
border_width_return: *mut libc::c_uint, depth_return: *mut libc::c_uint) -> Status;
|
||||
pub fn XSendEvent(display: *mut Display, window: Window, propagate: Bool,
|
||||
event_mask: libc::c_long, event_send: *mut XEvent) -> Status;
|
||||
pub fn XInternAtom(display: *mut Display, atom_name: *const libc::c_char,
|
||||
only_if_exists: Bool) -> Atom;
|
||||
pub fn XKeycodeToKeysym(display: *mut Display, keycode: KeyCode,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
pub use self::headless::HeadlessContext;
|
||||
|
||||
#[cfg(feature = "window")]
|
||||
pub use self::window::{Window, MonitorID, get_available_monitors, get_primary_monitor};
|
||||
pub use self::window::{Window, WindowProxy, MonitorID, get_available_monitors, get_primary_monitor};
|
||||
|
||||
mod ffi;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::{mem, ptr};
|
|||
use std::cell::Cell;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use super::ffi;
|
||||
use std::sync::{Once, ONCE_INIT};
|
||||
use std::sync::{Arc, Once, ONCE_INIT};
|
||||
|
||||
pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};
|
||||
|
||||
|
@ -23,17 +23,65 @@ fn ensure_thread_init() {
|
|||
});
|
||||
}
|
||||
|
||||
pub struct Window {
|
||||
struct XWindow {
|
||||
display: *mut ffi::Display,
|
||||
window: ffi::Window,
|
||||
im: ffi::XIM,
|
||||
ic: ffi::XIC,
|
||||
context: ffi::GLXContext,
|
||||
is_fullscreen: bool,
|
||||
screen_id: libc::c_int,
|
||||
xf86_desk_mode: *mut ffi::XF86VidModeModeInfo,
|
||||
ic: ffi::XIC,
|
||||
im: ffi::XIM,
|
||||
}
|
||||
|
||||
impl Drop for XWindow {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::glx::MakeCurrent(self.display, 0, ptr::null());
|
||||
ffi::glx::DestroyContext(self.display, self.context);
|
||||
|
||||
if self.is_fullscreen {
|
||||
ffi::XF86VidModeSwitchToMode(self.display, self.screen_id, self.xf86_desk_mode);
|
||||
ffi::XF86VidModeSetViewPort(self.display, self.screen_id, 0, 0);
|
||||
}
|
||||
|
||||
ffi::XDestroyIC(self.ic);
|
||||
ffi::XCloseIM(self.im);
|
||||
ffi::XDestroyWindow(self.display, self.window);
|
||||
ffi::XCloseDisplay(self.display);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct WindowProxy {
|
||||
x: Arc<XWindow>,
|
||||
}
|
||||
|
||||
impl WindowProxy {
|
||||
pub fn wakeup_event_loop(&self) {
|
||||
let mut xev = ffi::XClientMessageEvent {
|
||||
type_: ffi::ClientMessage,
|
||||
window: self.x.window,
|
||||
format: 32,
|
||||
message_type: 0,
|
||||
serial: 0,
|
||||
send_event: 0,
|
||||
display: self.x.display,
|
||||
l: [0, 0, 0, 0, 0],
|
||||
};
|
||||
|
||||
unsafe {
|
||||
ffi::XSendEvent(self.x.display, self.x.window, 0, 0, mem::transmute(&mut xev));
|
||||
ffi::XFlush(self.x.display);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Window {
|
||||
x: Arc<XWindow>,
|
||||
is_closed: AtomicBool,
|
||||
wm_delete_window: ffi::Atom,
|
||||
xf86_desk_mode: *mut ffi::XF86VidModeModeInfo,
|
||||
screen_id: libc::c_int,
|
||||
is_fullscreen: bool,
|
||||
current_size: Cell<(libc::c_int, libc::c_int)>,
|
||||
}
|
||||
|
||||
|
@ -257,7 +305,7 @@ impl Window {
|
|||
});
|
||||
|
||||
let share = if let Some(win) = builder.sharing {
|
||||
win.window.context
|
||||
win.window.x.context
|
||||
} else {
|
||||
ptr::null()
|
||||
};
|
||||
|
@ -278,16 +326,18 @@ impl Window {
|
|||
|
||||
// creating the window object
|
||||
let window = Window {
|
||||
display: display,
|
||||
window: window,
|
||||
im: im,
|
||||
ic: ic,
|
||||
context: context,
|
||||
x: Arc::new(XWindow {
|
||||
display: display,
|
||||
window: window,
|
||||
im: im,
|
||||
ic: ic,
|
||||
context: context,
|
||||
screen_id: screen_id,
|
||||
is_fullscreen: builder.monitor.is_some(),
|
||||
xf86_desk_mode: xf86_desk_mode,
|
||||
}),
|
||||
is_closed: AtomicBool::new(false),
|
||||
wm_delete_window: wm_delete_window,
|
||||
xf86_desk_mode: xf86_desk_mode,
|
||||
screen_id: screen_id,
|
||||
is_fullscreen: builder.monitor.is_some(),
|
||||
current_size: Cell::new((0, 0)),
|
||||
};
|
||||
|
||||
|
@ -303,22 +353,22 @@ impl Window {
|
|||
pub fn set_title(&self, title: &str) {
|
||||
let c_title = title.to_c_str();
|
||||
unsafe {
|
||||
ffi::XStoreName(self.display, self.window, c_title.as_ptr());
|
||||
ffi::XFlush(self.display);
|
||||
ffi::XStoreName(self.x.display, self.x.window, c_title.as_ptr());
|
||||
ffi::XFlush(self.x.display);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show(&self) {
|
||||
unsafe {
|
||||
ffi::XMapRaised(self.display, self.window);
|
||||
ffi::XFlush(self.display);
|
||||
ffi::XMapRaised(self.x.display, self.x.window);
|
||||
ffi::XFlush(self.x.display);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hide(&self) {
|
||||
unsafe {
|
||||
ffi::XUnmapWindow(self.display, self.window);
|
||||
ffi::XFlush(self.display);
|
||||
ffi::XUnmapWindow(self.x.display, self.x.window);
|
||||
ffi::XFlush(self.x.display);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,7 +384,7 @@ impl Window {
|
|||
let mut border: libc::c_uint = mem::uninitialized();
|
||||
let mut depth: libc::c_uint = mem::uninitialized();
|
||||
|
||||
if ffi::XGetGeometry(self.display, self.window,
|
||||
if ffi::XGetGeometry(self.x.display, self.x.window,
|
||||
&mut root, &mut x, &mut y, &mut width, &mut height,
|
||||
&mut border, &mut depth) == 0
|
||||
{
|
||||
|
@ -350,7 +400,7 @@ impl Window {
|
|||
}
|
||||
|
||||
pub fn set_position(&self, x: int, y: int) {
|
||||
unsafe { ffi::XMoveWindow(self.display, self.window, x as libc::c_int, y as libc::c_int) }
|
||||
unsafe { ffi::XMoveWindow(self.x.display, self.x.window, x as libc::c_int, y as libc::c_int) }
|
||||
}
|
||||
|
||||
pub fn get_inner_size(&self) -> Option<(uint, uint)> {
|
||||
|
@ -365,6 +415,12 @@ impl Window {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn create_window_proxy(&self) -> WindowProxy {
|
||||
WindowProxy {
|
||||
x: self.x.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn poll_events(&self) -> Vec<Event> {
|
||||
use std::mem;
|
||||
|
||||
|
@ -374,10 +430,10 @@ impl Window {
|
|||
use std::num::Int;
|
||||
|
||||
let mut xev = unsafe { mem::uninitialized() };
|
||||
let res = unsafe { ffi::XCheckMaskEvent(self.display, Int::max_value(), &mut xev) };
|
||||
let res = unsafe { ffi::XCheckMaskEvent(self.x.display, Int::max_value(), &mut xev) };
|
||||
|
||||
if res == 0 {
|
||||
let res = unsafe { ffi::XCheckTypedEvent(self.display, ffi::ClientMessage, &mut xev) };
|
||||
let res = unsafe { ffi::XCheckTypedEvent(self.x.display, ffi::ClientMessage, &mut xev) };
|
||||
|
||||
if res == 0 {
|
||||
break
|
||||
|
@ -390,7 +446,7 @@ impl Window {
|
|||
},
|
||||
|
||||
ffi::ClientMessage => {
|
||||
use events::Event::Closed;
|
||||
use events::Event::{Closed, Refresh};
|
||||
use std::sync::atomic::Relaxed;
|
||||
|
||||
let client_msg: &ffi::XClientMessageEvent = unsafe { mem::transmute(&xev) };
|
||||
|
@ -398,6 +454,8 @@ impl Window {
|
|||
if client_msg.l[0] == self.wm_delete_window as libc::c_long {
|
||||
self.is_closed.store(true, Relaxed);
|
||||
events.push(Closed);
|
||||
} else {
|
||||
events.push(Refresh);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -424,7 +482,7 @@ impl Window {
|
|||
|
||||
if event.type_ == ffi::KeyPress {
|
||||
let raw_ev: *mut ffi::XKeyEvent = event;
|
||||
unsafe { ffi::XFilterEvent(mem::transmute(raw_ev), self.window) };
|
||||
unsafe { ffi::XFilterEvent(mem::transmute(raw_ev), self.x.window) };
|
||||
}
|
||||
|
||||
let state = if xev.type_ == ffi::KeyPress { Pressed } else { Released };
|
||||
|
@ -434,7 +492,7 @@ impl Window {
|
|||
|
||||
let mut buffer: [u8, ..16] = [mem::uninitialized(), ..16];
|
||||
let raw_ev: *mut ffi::XKeyEvent = event;
|
||||
let count = ffi::Xutf8LookupString(self.ic, mem::transmute(raw_ev),
|
||||
let count = ffi::Xutf8LookupString(self.x.ic, mem::transmute(raw_ev),
|
||||
mem::transmute(buffer.as_mut_ptr()),
|
||||
buffer.len() as libc::c_int, ptr::null_mut(), ptr::null_mut());
|
||||
|
||||
|
@ -447,7 +505,7 @@ impl Window {
|
|||
}
|
||||
|
||||
let keysym = unsafe {
|
||||
ffi::XKeycodeToKeysym(self.display, event.keycode as ffi::KeyCode, 0)
|
||||
ffi::XKeycodeToKeysym(self.x.display, event.keycode as ffi::KeyCode, 0)
|
||||
};
|
||||
|
||||
let vkey = events::keycode_to_element(keysym as libc::c_uint);
|
||||
|
@ -500,7 +558,7 @@ impl Window {
|
|||
// this will block until an event arrives, but doesn't remove
|
||||
// it from the queue
|
||||
let mut xev = unsafe { mem::uninitialized() };
|
||||
unsafe { ffi::XPeekEvent(self.display, &mut xev) };
|
||||
unsafe { ffi::XPeekEvent(self.x.display, &mut xev) };
|
||||
|
||||
// calling poll_events()
|
||||
let ev = self.poll_events();
|
||||
|
@ -511,7 +569,7 @@ impl Window {
|
|||
}
|
||||
|
||||
pub unsafe fn make_current(&self) {
|
||||
let res = ffi::glx::MakeCurrent(self.display, self.window, self.context);
|
||||
let res = ffi::glx::MakeCurrent(self.x.display, self.x.window, self.x.context);
|
||||
if res == 0 {
|
||||
panic!("glx::MakeCurrent failed");
|
||||
}
|
||||
|
@ -529,11 +587,11 @@ impl Window {
|
|||
}
|
||||
|
||||
pub fn swap_buffers(&self) {
|
||||
unsafe { ffi::glx::SwapBuffers(self.display, self.window) }
|
||||
unsafe { ffi::glx::SwapBuffers(self.x.display, self.x.window) }
|
||||
}
|
||||
|
||||
pub fn platform_display(&self) -> *mut libc::c_void {
|
||||
self.display as *mut libc::c_void
|
||||
self.x.display as *mut libc::c_void
|
||||
}
|
||||
|
||||
/// See the docs in the crate root file.
|
||||
|
@ -541,20 +599,3 @@ impl Window {
|
|||
::Api::OpenGl
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Window {
|
||||
fn drop(&mut self) {
|
||||
unsafe { ffi::glx::MakeCurrent(self.display, 0, ptr::null()); }
|
||||
unsafe { ffi::glx::DestroyContext(self.display, self.context); }
|
||||
|
||||
if self.is_fullscreen {
|
||||
unsafe { ffi::XF86VidModeSwitchToMode(self.display, self.screen_id, self.xf86_desk_mode); }
|
||||
unsafe { ffi::XF86VidModeSetViewPort(self.display, self.screen_id, 0, 0); }
|
||||
}
|
||||
|
||||
unsafe { ffi::XDestroyIC(self.ic); }
|
||||
unsafe { ffi::XCloseIM(self.im); }
|
||||
unsafe { ffi::XDestroyWindow(self.display, self.window); }
|
||||
unsafe { ffi::XCloseDisplay(self.display); }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue