Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate the builder attributes into multiple substates #603

Merged
merged 12 commits into from
Sep 21, 2015
Prev Previous commit
Next Next commit
Switch X11 and wayland to the new design
  • Loading branch information
tomaka committed Sep 21, 2015
commit 5182023fd6f14469290b80f0f5e9b0dead73048e
16 changes: 10 additions & 6 deletions src/api/wayland/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ use api::dlopen;
use api::egl;
use api::egl::Context as EglContext;

use BuilderAttribs;
use ContextError;
use CreationError;
use Event;
use PixelFormat;
use CursorState;
use MouseCursor;
use GlAttributes;
use GlContext;
use PixelFormatRequirements;
use WindowAttributes;

use std::collections::VecDeque;
use std::ops::{Deref, DerefMut};
Expand Down Expand Up @@ -241,7 +243,9 @@ impl<'a> Iterator for WaitEventsIterator<'a> {
}

impl Window {
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
pub fn new(window: &WindowAttributes, pf_reqs: &PixelFormatRequirements,
opengl: &GlAttributes<&Window>) -> Result<Window, CreationError>
{
use self::wayland::internals::FFI;

let wayland_context = match *WAYLAND_CONTEXT {
Expand All @@ -251,20 +255,20 @@ impl Window {

if !is_egl_available() { return Err(CreationError::NotSupported) }

let (w, h) = builder.window.dimensions.unwrap_or((800, 600));
let (w, h) = window.dimensions.unwrap_or((800, 600));

let surface = EGLSurface::new(
wayland_context.compositor.create_surface(),
w as i32,
h as i32
);

let mut shell_window = if let Some(PlatformMonitorID::Wayland(ref monitor)) = builder.window.monitor {
let mut shell_window = if let Some(PlatformMonitorID::Wayland(ref monitor)) = window.monitor {
let shell_surface = wayland_context.shell.get_shell_surface(surface);
shell_surface.set_fullscreen(ShellFullscreenMethod::Default, Some(&monitor.output));
ShellWindow::Plain(shell_surface)
} else {
if builder.window.decorations {
if window.decorations {
ShellWindow::Decorated(match DecoratedSurface::new(
surface,
w as i32,
Expand All @@ -291,7 +295,7 @@ impl Window {
});
try!(EglContext::new(
egl,
&builder.pf_reqs, &builder.opengl.clone().map_sharing(|_| unimplemented!()), // TODO:
pf_reqs, &opengl.clone().map_sharing(|_| unimplemented!()), // TODO:
egl::NativeDisplay::Wayland(Some(wayland_context.display.ptr() as *const _)))
.and_then(|p| p.finish((**shell_window.get_shell()).ptr() as *const _))
)
Expand Down
41 changes: 23 additions & 18 deletions src/api/x11/window.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use {Event, BuilderAttribs, MouseCursor};
use {Event, MouseCursor};
use CreationError;
use CreationError::OsError;
use libc;
Expand All @@ -12,9 +12,12 @@ use std::sync::{Arc, Mutex};
use Api;
use ContextError;
use CursorState;
use GlAttributes;
use GlContext;
use GlRequest;
use PixelFormat;
use PixelFormatRequirements;
use WindowAttributes;

use api::glx::Context as GlxContext;
use api::egl;
Expand Down Expand Up @@ -295,10 +298,13 @@ pub struct Window {
}

impl Window {
pub fn new(display: &Arc<XConnection>, builder: BuilderAttribs) -> Result<Window, CreationError> {
let dimensions = builder.window.dimensions.unwrap_or((800, 600));
pub fn new(display: &Arc<XConnection>, window_attrs: &WindowAttributes,
pf_reqs: &PixelFormatRequirements, opengl: &GlAttributes<&Window>)
-> Result<Window, CreationError>
{
let dimensions = window_attrs.dimensions.unwrap_or((800, 600));

let screen_id = match builder.window.monitor {
let screen_id = match window_attrs.monitor {
Some(PlatformMonitorID::X(MonitorID(_, monitor))) => monitor as i32,
_ => unsafe { (display.xlib.XDefaultScreen)(display.display) },
};
Expand All @@ -316,7 +322,7 @@ impl Window {
// FIXME: `XF86VidModeModeInfo` is missing its `hskew` field. Therefore we point to
// `vsyncstart` instead of `vdisplay` as a temporary hack.

let mode_to_switch_to = if builder.window.monitor.is_some() {
let mode_to_switch_to = if window_attrs.monitor.is_some() {
let matching_mode = (0 .. mode_num).map(|i| {
let m: ffi::XF86VidModeModeInfo = ptr::read(*modes.offset(i as isize) as *const _); m
}).find(|m| m.hdisplay == dimensions.0 as u16 && m.vsyncstart == dimensions.1 as u16);
Expand Down Expand Up @@ -348,24 +354,23 @@ impl Window {
Glx(::api::glx::ContextPrototype<'a>),
Egl(::api::egl::ContextPrototype<'a>),
}
let builder_clone = builder.clone();
let builder_clone_opengl_glx = builder_clone.opengl.clone().map_sharing(|_| unimplemented!()); // FIXME:
let builder_clone_opengl_egl = builder_clone.opengl.clone().map_sharing(|_| unimplemented!()); // FIXME:
let context = match builder.opengl.version {
let builder_clone_opengl_glx = opengl.clone().map_sharing(|_| unimplemented!()); // FIXME:
let builder_clone_opengl_egl = opengl.clone().map_sharing(|_| unimplemented!()); // FIXME:
let context = match opengl.version {
GlRequest::Latest | GlRequest::Specific(Api::OpenGl, _) | GlRequest::GlThenGles { .. } => {
// GLX should be preferred over EGL, otherwise crashes may occur
// on X11 – issue #314
if let Some(ref glx) = display.glx {
Prototype::Glx(try!(GlxContext::new(glx.clone(), &display.xlib, &builder_clone.pf_reqs, &builder_clone_opengl_glx, display.display)))
Prototype::Glx(try!(GlxContext::new(glx.clone(), &display.xlib, pf_reqs, &builder_clone_opengl_glx, display.display)))
} else if let Some(ref egl) = display.egl {
Prototype::Egl(try!(EglContext::new(egl.clone(), &builder_clone.pf_reqs, &builder_clone_opengl_egl, egl::NativeDisplay::X11(Some(display.display as *const _)))))
Prototype::Egl(try!(EglContext::new(egl.clone(), pf_reqs, &builder_clone_opengl_egl, egl::NativeDisplay::X11(Some(display.display as *const _)))))
} else {
return Err(CreationError::NotSupported);
}
},
GlRequest::Specific(Api::OpenGlEs, _) => {
if let Some(ref egl) = display.egl {
Prototype::Egl(try!(EglContext::new(egl.clone(), &builder_clone.pf_reqs, &builder_clone_opengl_egl, egl::NativeDisplay::X11(Some(display.display as *const _)))))
Prototype::Egl(try!(EglContext::new(egl.clone(), pf_reqs, &builder_clone_opengl_egl, egl::NativeDisplay::X11(Some(display.display as *const _)))))
} else {
return Err(CreationError::NotSupported);
}
Expand Down Expand Up @@ -417,7 +422,7 @@ impl Window {
ffi::KeyReleaseMask | ffi::ButtonPressMask |
ffi::ButtonReleaseMask | ffi::KeymapStateMask;
swa.border_pixel = 0;
if builder.window.transparent {
if window_attrs.transparent {
swa.background_pixel = 0;
}
swa.override_redirect = 0;
Expand All @@ -426,7 +431,7 @@ impl Window {

let mut window_attributes = ffi::CWBorderPixel | ffi::CWColormap | ffi::CWEventMask;

if builder.window.transparent {
if window_attrs.transparent {
window_attributes |= ffi::CWBackPixel;
}

Expand All @@ -450,7 +455,7 @@ impl Window {
};

// set visibility
if builder.window.visible {
if window_attrs.visible {
unsafe {
(display.xlib.XMapRaised)(display.display, window);
(display.xlib.XFlush)(display.display);
Expand All @@ -463,7 +468,7 @@ impl Window {
(display.xlib.XInternAtom)(display.display, delete_window, 0)
);
(display.xlib.XSetWMProtocols)(display.display, window, &mut wm_delete_window, 1);
with_c_str(&*builder.window.title, |title| {;
with_c_str(&*window_attrs.title, |title| {;
(display.xlib.XStoreName)(display.display, window, title);
});
(display.xlib.XFlush)(display.display);
Expand Down Expand Up @@ -511,7 +516,7 @@ impl Window {

// Set ICCCM WM_CLASS property based on initial window title
unsafe {
with_c_str(&*builder.window.title, |c_name| {
with_c_str(&*window_attrs.title, |c_name| {
let hint = (display.xlib.XAllocClassHint)();
(*hint).res_name = c_name as *mut libc::c_char;
(*hint).res_class = c_name as *mut libc::c_char;
Expand All @@ -520,7 +525,7 @@ impl Window {
});
}

let is_fullscreen = builder.window.monitor.is_some();
let is_fullscreen = window_attrs.monitor.is_some();

// finish creating the OpenGL context
let context = match context {
Expand Down
24 changes: 22 additions & 2 deletions src/platform/linux/api_dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,29 @@ impl<'a> Iterator for WaitEventsIterator<'a> {

impl Window {
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
let window = builder.window;
let pf_reqs = builder.pf_reqs;
let opengl = builder.opengl;

match *BACKEND {
Backend::Wayland => wayland::Window::new(builder).map(Window::Wayland),
Backend::X(ref connec) => x11::Window::new(connec, builder).map(Window::X),
Backend::Wayland => {
let opengl = opengl.map_sharing(|w| match w {
&Window::Wayland(ref w) => w,
_ => panic!() // TODO: return an error
});

wayland::Window::new(&window, &pf_reqs, &opengl).map(Window::Wayland)
},

Backend::X(ref connec) => {
let opengl = opengl.map_sharing(|w| match w {
&Window::X(ref w) => w,
_ => panic!() // TODO: return an error
});

x11::Window::new(connec, &window, &pf_reqs, &opengl).map(Window::X)
},

Backend::Error(ref error) => Err(CreationError::NoBackendAvailable(Box::new(error.clone())))
}
}
Expand Down