mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 22:01:31 +11:00
commit
3ac5f6d115
|
@ -1,5 +1,8 @@
|
|||
language: rust
|
||||
|
||||
install:
|
||||
- sudo apt-get install libXxf86vm-dev
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
|
18
src/lib.rs
18
src/lib.rs
|
@ -7,9 +7,9 @@
|
|||
//! platforms as possible.
|
||||
//!
|
||||
//! # Building a window
|
||||
//!
|
||||
//!
|
||||
//! There are two ways to create a window:
|
||||
//!
|
||||
//!
|
||||
//! - Calling `Window::new()`.
|
||||
//! - Calling `let builder = WindowBuilder::new()` then `builder.build()`.
|
||||
//!
|
||||
|
@ -104,7 +104,7 @@ impl WindowBuilder {
|
|||
}
|
||||
|
||||
/// Builds the window.
|
||||
///
|
||||
///
|
||||
/// Error should be very rare and only occur in case of permission denied, incompatible system,
|
||||
/// out of memory, etc.
|
||||
pub fn build(mut self) -> Result<Window, String> {
|
||||
|
@ -129,16 +129,16 @@ impl WindowBuilder {
|
|||
///
|
||||
/// ```ignore
|
||||
/// let window = Window::new().unwrap();
|
||||
///
|
||||
///
|
||||
/// unsafe { window.make_current() };
|
||||
///
|
||||
///
|
||||
/// loop {
|
||||
/// for event in window.poll_events() {
|
||||
/// // process events here
|
||||
/// _ => ()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
///
|
||||
/// // draw everything here
|
||||
///
|
||||
/// window.swap_buffers();
|
||||
|
@ -159,7 +159,7 @@ impl Window {
|
|||
/// Creates a new OpenGL context, and a Window for platforms where this is appropriate.
|
||||
///
|
||||
/// This function is equivalent to `WindowBuilder::new().build()`.
|
||||
///
|
||||
///
|
||||
/// Error should be very rare and only occur in case of permission denied, incompatible system,
|
||||
/// out of memory, etc.
|
||||
#[inline]
|
||||
|
@ -249,7 +249,7 @@ impl Window {
|
|||
}
|
||||
|
||||
/// Returns an iterator to all the events that are currently in the window's events queue.
|
||||
///
|
||||
///
|
||||
/// Contrary to `wait_events`, this function never blocks.
|
||||
#[inline]
|
||||
pub fn poll_events(&self) -> PollEventsIterator {
|
||||
|
@ -258,7 +258,7 @@ impl Window {
|
|||
|
||||
/// Waits for an event, then returns an iterator to all the events that are currently
|
||||
/// in the window's events queue.
|
||||
///
|
||||
///
|
||||
/// If there are no events in queue when you call the function,
|
||||
/// this function will block until there is one.
|
||||
#[inline]
|
||||
|
|
|
@ -29,6 +29,7 @@ pub type XrmDatabase = *const (); // TODO: not sure
|
|||
pub type XIC = *mut ();
|
||||
pub type XID = uint;
|
||||
pub type XIM = *mut ();
|
||||
pub type Screen = ();
|
||||
|
||||
pub static AllocNone: libc::c_int = 0;
|
||||
pub static AllocAll: libc::c_int = 1;
|
||||
|
@ -1337,8 +1338,26 @@ pub struct XButtonEvent {
|
|||
pub same_screen: Bool,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct XF86VidModeModeInfo {
|
||||
pub dotclock: libc::c_uint,
|
||||
pub hdisplay: libc::c_ushort,
|
||||
pub hsyncstart: libc::c_ushort,
|
||||
pub hsyncend: libc::c_ushort,
|
||||
pub htotal: libc::c_ushort,
|
||||
pub hskew: libc::c_ushort,
|
||||
pub vdisplay: libc::c_ushort,
|
||||
pub vsyncstart: libc::c_ushort,
|
||||
pub vsyncend: libc::c_ushort,
|
||||
pub vtotal: libc::c_ushort,
|
||||
pub flags: libc::c_uint,
|
||||
privsize: libc::c_int,
|
||||
private: libc::c_long,
|
||||
}
|
||||
|
||||
#[link(name = "GL")]
|
||||
#[link(name = "X11")]
|
||||
#[link(name = "Xxf86vm")]
|
||||
extern "C" {
|
||||
pub fn XCloseDisplay(display: *mut Display);
|
||||
pub fn XCheckMaskEvent(display: *mut Display, event_mask: libc::c_long,
|
||||
|
@ -1375,6 +1394,10 @@ extern "C" {
|
|||
pub fn XSetWMProtocols(display: *mut Display, w: Window, protocols: *mut Atom,
|
||||
count: libc::c_int) -> Status;
|
||||
pub fn XStoreName(display: *mut Display, w: Window, window_name: *const libc::c_char);
|
||||
pub fn XScreenCount(display: *mut Display) -> libc::c_int;
|
||||
pub fn XScreenOfDisplay(display: *mut Display, screen_number: libc::c_int) -> *const Screen;
|
||||
pub fn XWidthOfScreen(screen: *const Screen) -> libc::c_int;
|
||||
pub fn XHeightOfScreen(screen: *const Screen) -> libc::c_int;
|
||||
|
||||
pub fn XCloseIM(im: XIM) -> Status;
|
||||
pub fn XOpenIM(display: *mut Display, db: XrmDatabase, res_name: *mut libc::c_char,
|
||||
|
@ -1408,6 +1431,13 @@ extern "C" {
|
|||
pub fn glXSwapBuffers(dpy: *mut Display, drawable: GLXDrawable);
|
||||
|
||||
pub fn XkbSetDetectableAutoRepeat(dpy: *mut Display, detectable: bool, supported_rtm: *mut bool) -> bool;
|
||||
|
||||
pub fn XF86VidModeSwitchToMode(dpy: *mut Display, screen: libc::c_int,
|
||||
modeline: *mut XF86VidModeModeInfo) -> Bool;
|
||||
pub fn XF86VidModeSetViewPort(dpy: *mut Display, screen: libc::c_int,
|
||||
x: libc::c_int, y: libc::c_int) -> Bool;
|
||||
pub fn XF86VidModeGetAllModeLines(dpy: *mut Display, screen: libc::c_int,
|
||||
modecount_return: *mut libc::c_int, modesinfo: *mut *mut *mut XF86VidModeModeInfo) -> Bool;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
102
src/x11/mod.rs
102
src/x11/mod.rs
|
@ -3,8 +3,11 @@ use libc;
|
|||
use std::{mem, ptr};
|
||||
use std::sync::atomics::AtomicBool;
|
||||
|
||||
pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};
|
||||
|
||||
mod events;
|
||||
mod ffi;
|
||||
mod monitor;
|
||||
|
||||
pub struct Window {
|
||||
display: *mut ffi::Display,
|
||||
|
@ -14,32 +17,14 @@ pub struct Window {
|
|||
context: ffi::GLXContext,
|
||||
is_closed: AtomicBool,
|
||||
wm_delete_window: ffi::Atom,
|
||||
}
|
||||
|
||||
pub struct MonitorID(uint);
|
||||
|
||||
pub fn get_available_monitors() -> Vec<MonitorID> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn get_primary_monitor() -> MonitorID {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
impl MonitorID {
|
||||
pub fn get_name(&self) -> Option<String> {
|
||||
Some("<Unknown>".to_string())
|
||||
}
|
||||
|
||||
pub fn get_dimensions(&self) -> (uint, uint) {
|
||||
unimplemented!()
|
||||
}
|
||||
xf86_desk_mode: *mut ffi::XF86VidModeModeInfo,
|
||||
screen_id: libc::c_int,
|
||||
is_fullscreen: bool,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
pub fn new(builder: WindowBuilder) -> Result<Window, String> {
|
||||
// TODO: temporary
|
||||
let dimensions = builder.dimensions;
|
||||
let dimensions = builder.dimensions.unwrap_or((800, 600));
|
||||
|
||||
// calling XOpenDisplay
|
||||
let display = unsafe {
|
||||
|
@ -50,7 +35,9 @@ impl Window {
|
|||
display
|
||||
};
|
||||
|
||||
// TODO: set error handler?
|
||||
let screen_id = unsafe {
|
||||
ffi::XDefaultScreen(display)
|
||||
};
|
||||
|
||||
// getting the FBConfig
|
||||
let fb_config = unsafe {
|
||||
|
@ -81,6 +68,31 @@ impl Window {
|
|||
preferred_fb
|
||||
};
|
||||
|
||||
let mut best_mode = -1;
|
||||
let modes = unsafe {
|
||||
let mut mode_num: libc::c_int = mem::uninitialized();
|
||||
let mut modes: *mut *mut ffi::XF86VidModeModeInfo = mem::uninitialized();
|
||||
if ffi::XF86VidModeGetAllModeLines(display, screen_id, &mut mode_num, &mut modes) == 0 {
|
||||
return Err(format!("Could not query the video modes"));
|
||||
}
|
||||
|
||||
for i in range(0, mode_num) {
|
||||
let mode: ffi::XF86VidModeModeInfo = **modes.offset(i as int);
|
||||
if mode.hdisplay == dimensions.val0() as u16 && mode.vdisplay == dimensions.val1() as u16 {
|
||||
best_mode = i;
|
||||
}
|
||||
};
|
||||
if best_mode == -1 {
|
||||
return Err(format!("Could not find a suitable graphics mode"));
|
||||
}
|
||||
|
||||
modes
|
||||
};
|
||||
|
||||
let xf86_desk_mode = unsafe {
|
||||
*modes.offset(0)
|
||||
};
|
||||
|
||||
// getting the visual infos
|
||||
let visual_infos = unsafe {
|
||||
let vi = ffi::glXGetVisualFromFBConfig(display, fb_config);
|
||||
|
@ -109,18 +121,28 @@ impl Window {
|
|||
swa.colormap = cmap;
|
||||
swa.event_mask = ffi::ExposureMask | ffi::ResizeRedirectMask |
|
||||
ffi::VisibilityChangeMask | ffi::KeyPressMask | ffi::PointerMotionMask |
|
||||
ffi::KeyPressMask | ffi::KeyReleaseMask | ffi::ButtonPressMask |
|
||||
ffi::KeyReleaseMask | ffi::ButtonPressMask |
|
||||
ffi::ButtonReleaseMask | ffi::KeymapStateMask;
|
||||
swa.border_pixel = 0;
|
||||
swa.override_redirect = 0;
|
||||
swa
|
||||
};
|
||||
|
||||
let mut window_attributes = ffi::CWBorderPixel | ffi::CWColormap | ffi:: CWEventMask;
|
||||
if builder.monitor.is_some() {
|
||||
window_attributes |= ffi::CWOverrideRedirect;
|
||||
unsafe {
|
||||
ffi::XF86VidModeSwitchToMode(display, screen_id, *modes.offset(best_mode as int));
|
||||
ffi::XF86VidModeSetViewPort(display, screen_id, 0, 0);
|
||||
set_win_attr.override_redirect = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// finally creating the window
|
||||
let window = unsafe {
|
||||
let dimensions = dimensions.unwrap_or((800, 600));
|
||||
|
||||
let win = ffi::XCreateWindow(display, root, 50, 50, dimensions.val0() as libc::c_uint,
|
||||
let win = ffi::XCreateWindow(display, root, 0, 0, dimensions.val0() as libc::c_uint,
|
||||
dimensions.val1() as libc::c_uint, 0, visual_infos.depth, ffi::InputOutput,
|
||||
visual_infos.visual, ffi::CWColormap | ffi::CWEventMask,
|
||||
visual_infos.visual, window_attributes,
|
||||
&mut set_win_attr);
|
||||
win
|
||||
};
|
||||
|
@ -148,7 +170,7 @@ impl Window {
|
|||
addr = ffi::glXGetProcAddress(b"glXCreateContextAttribsARB".as_ptr()
|
||||
as *const u8) as *const ();
|
||||
}
|
||||
|
||||
|
||||
addr.to_option().map(|addr| {
|
||||
let addr: extern "system" fn(*mut ffi::Display, ffi::GLXFBConfig, ffi::GLXContext,
|
||||
ffi::Bool, *const libc::c_int) -> ffi::GLXContext = mem::transmute(addr);
|
||||
|
@ -202,13 +224,13 @@ impl Window {
|
|||
}
|
||||
|
||||
attributes.push(0);
|
||||
|
||||
|
||||
let context = if create_context_attribs.is_some() {
|
||||
let create_context_attribs = create_context_attribs.unwrap();
|
||||
create_context_attribs(display, fb_config, ptr::null(), 1,
|
||||
attributes.as_ptr())
|
||||
} else {
|
||||
ffi::glXCreateNewContext(display, fb_config, ffi::GLX_RGBA_TYPE, ptr::null(), 1)
|
||||
ffi::glXCreateContext(display, &visual_infos, ptr::null(), 1)
|
||||
};
|
||||
|
||||
if context.is_null() {
|
||||
|
@ -227,6 +249,9 @@ impl Window {
|
|||
context: context,
|
||||
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(),
|
||||
};
|
||||
|
||||
// calling glViewport
|
||||
|
@ -300,9 +325,9 @@ impl Window {
|
|||
|
||||
pub fn poll_events(&self) -> Vec<Event> {
|
||||
use std::mem;
|
||||
|
||||
|
||||
let mut events = Vec::new();
|
||||
|
||||
|
||||
loop {
|
||||
use std::num::Bounded;
|
||||
|
||||
|
@ -362,7 +387,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.ic, mem::transmute(raw_ev),
|
||||
mem::transmute(buffer.as_mut_ptr()),
|
||||
buffer.len() as libc::c_int, ptr::mut_null(), ptr::mut_null());
|
||||
|
||||
|
@ -402,7 +427,7 @@ impl Window {
|
|||
};
|
||||
|
||||
match button {
|
||||
Some(button) =>
|
||||
Some(button) =>
|
||||
events.push(MouseInput(state, button)),
|
||||
None => ()
|
||||
};
|
||||
|
@ -457,7 +482,14 @@ impl Window {
|
|||
|
||||
impl Drop for Window {
|
||||
fn drop(&mut self) {
|
||||
unsafe { ffi::glXMakeCurrent(self.display, 0, ptr::null()); }
|
||||
unsafe { ffi::glXDestroyContext(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); }
|
||||
|
|
55
src/x11/monitor.rs
Normal file
55
src/x11/monitor.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
use std::{ptr};
|
||||
use super::ffi;
|
||||
|
||||
pub struct MonitorID(uint);
|
||||
|
||||
pub fn get_available_monitors() -> Vec<MonitorID> {
|
||||
let nb_monitors = unsafe {
|
||||
let display = ffi::XOpenDisplay(ptr::null());
|
||||
if display.is_null() {
|
||||
fail!("get_available_monitors failed");
|
||||
}
|
||||
let nb_monitors = ffi::XScreenCount(display);
|
||||
ffi::XCloseDisplay(display);
|
||||
nb_monitors
|
||||
};
|
||||
|
||||
let mut vec = Vec::new();
|
||||
vec.grow_fn(nb_monitors as uint, |i| MonitorID(i));
|
||||
vec
|
||||
}
|
||||
|
||||
pub fn get_primary_monitor() -> MonitorID {
|
||||
let primary_monitor = unsafe {
|
||||
let display = ffi::XOpenDisplay(ptr::null());
|
||||
if display.is_null() {
|
||||
fail!("get_available_monitors failed");
|
||||
}
|
||||
let primary_monitor = ffi::XDefaultScreen(display);
|
||||
ffi::XCloseDisplay(display);
|
||||
primary_monitor
|
||||
};
|
||||
|
||||
MonitorID(primary_monitor as uint)
|
||||
}
|
||||
|
||||
impl MonitorID {
|
||||
pub fn get_name(&self) -> Option<String> {
|
||||
let MonitorID(screen_num) = *self;
|
||||
Some(format!("Monitor #{}", screen_num))
|
||||
}
|
||||
|
||||
pub fn get_dimensions(&self) -> (uint, uint) {
|
||||
let dimensions = unsafe {
|
||||
let display = ffi::XOpenDisplay(ptr::null());
|
||||
let MonitorID(screen_num) = *self;
|
||||
let screen = ffi::XScreenOfDisplay(display, screen_num as i32);
|
||||
let width = ffi::XWidthOfScreen(screen);
|
||||
let height = ffi::XHeightOfScreen(screen);
|
||||
(width as uint, height as uint)
|
||||
};
|
||||
|
||||
dimensions
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in a new issue