Skip to content

Commit

Permalink
Stop using NSFullSizeContentViewWindowMask to get borderless windows,
Browse files Browse the repository at this point in the history
because that disables the swap interval.

This hack is very simple but a little evil. We get the superview of the
content view, which is the `NSThemeFrame`, and install an OpenGL context
into it.  `NSThemeFrame` is a private class, but we only call public
`NSView` APIs on it here, so this seems OK in terms of being supported
by Apple going forward.

The reason for using this hack as opposed to
`NSFullSizeContentViewWindowMask` is that the latter forces the window
to be Core Animation-backed, which results in us rendering to an off
screen surface. Not only does this inject another compositor into the
system, but it also results in us rendering to an off-screen surface,
disabling the swap interval.

This depends on a `cocoa-rs` upgrade to add a binding to the `-[NSView
superview]` method.

Known issues:

* The traffic light buttons are not drawn but still function if you
  click on them. This can be worked around in browser.html.

* The top border is not rounded, although the shadow properly displays.
  This should be able to be worked around in browser.html.

* The title bar reappears if you go to full screen and then go back.
  This is the most serious issue, but I suspect it'll be fixable and
  it's better than what we have right now.

This should fix servo/servo#9431.
  • Loading branch information
pcwalton committed Feb 3, 2016
1 parent d78affc commit 7278f83
Showing 1 changed file with 24 additions and 10 deletions.
34 changes: 24 additions & 10 deletions src/api/cocoa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ impl Window {
Some(window) => window,
None => { return Err(OsError(format!("Couldn't create NSWindow"))); },
};
let view = match Window::create_view(*window) {
let view = match Window::get_or_create_view(*window, win_attribs.decorations) {
Some(view) => view,
None => { return Err(OsError(format!("Couldn't create NSView"))); },
};
Expand Down Expand Up @@ -412,8 +412,7 @@ impl Window {
NSClosableWindowMask as NSUInteger |
NSMiniaturizableWindowMask as NSUInteger |
NSResizableWindowMask as NSUInteger |
NSTitledWindowMask as NSUInteger |
NSFullSizeContentViewWindowMask as NSUInteger
NSTitledWindowMask as NSUInteger
};

let window = IdRef::new(NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
Expand Down Expand Up @@ -443,14 +442,29 @@ impl Window {
}
}

fn create_view(window: id) -> Option<IdRef> {
fn get_or_create_view(window: id, decorations: bool) -> Option<IdRef> {
unsafe {
let view = IdRef::new(NSView::alloc(nil).init());
view.non_nil().map(|view| {
view.setWantsBestResolutionOpenGLSurface_(YES);
window.setContentView_(*view);
view
})
if decorations {
let view = IdRef::new(NSView::alloc(nil).init());
return view.non_nil().map(|view| {
view.setWantsBestResolutionOpenGLSurface_(YES);
window.setContentView_(*view);
view
})
}

// This hack is a little evil. We get the superview of the content view, which is the
// `NSThemeFrame`, and install an OpenGL context into it. `NSThemeFrame` is a private
// class, but we only call public `NSView` APIs on it here, so this seems OK.
//
// The reason for using this hack as opposed to `NSFullSizeContentViewWindowMask` is
// that the latter forces the window to be Core Animation-backed, which results in us
// rendering to an off screen surface. Not only does this inject another compositor
// into the system, but it also results in us rendering to an off-screen surface,
// disabling the swap interval.
let view = window.contentView().superview();
view.setWantsBestResolutionOpenGLSurface_(YES);
Some(IdRef::new(view))
}
}

Expand Down

0 comments on commit 7278f83

Please sign in to comment.