mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 06:11:30 +11:00
Conflicts: .travis.yml Cargo.toml examples/fullscreen.rs src/api/android/mod.rs src/api/cocoa/headless.rs src/api/cocoa/helpers.rs src/api/cocoa/mod.rs src/api/glx/mod.rs src/api/osmesa/mod.rs src/api/win32/callback.rs src/headless.rs src/lib.rs src/platform/linux/mod.rs src/window.rs
This commit is contained in:
commit
7f6ae8910e
10
.travis.yml
10
.travis.yml
|
@ -4,6 +4,8 @@ rust:
|
||||||
- nightly
|
- nightly
|
||||||
- stable
|
- stable
|
||||||
|
|
||||||
|
cache: cargo
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
packages:
|
packages:
|
||||||
|
@ -18,14 +20,6 @@ os:
|
||||||
- osx
|
- osx
|
||||||
|
|
||||||
after_success:
|
after_success:
|
||||||
- |
|
|
||||||
[ $TRAVIS_BRANCH = master ] &&
|
|
||||||
[ $TRAVIS_PULL_REQUEST = false ] &&
|
|
||||||
cargo doc &&
|
|
||||||
echo '<meta http-equiv=refresh content=0;url=glutin/index.html>' > target/doc/index.html &&
|
|
||||||
sudo pip install ghp-import &&
|
|
||||||
ghp-import -n target/doc &&
|
|
||||||
git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
|
|
||||||
- |
|
- |
|
||||||
[ $TRAVIS_BRANCH = master ] &&
|
[ $TRAVIS_BRANCH = master ] &&
|
||||||
[ $TRAVIS_PULL_REQUEST = false ] &&
|
[ $TRAVIS_PULL_REQUEST = false ] &&
|
||||||
|
|
17
Cargo.toml
17
Cargo.toml
|
@ -7,27 +7,30 @@ keywords = ["windowing"]
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
repository = "https://github.com/tomaka/winit"
|
repository = "https://github.com/tomaka/winit"
|
||||||
documentation = "https://tomaka.github.io/winit/"
|
documentation = "https://docs.rs/winit"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lazy_static = "0.1.10"
|
lazy_static = "0.2.0"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
shared_library = "0.1.0"
|
shared_library = "0.1.0"
|
||||||
|
|
||||||
[target.arm-linux-androideabi.dependencies.android_glue]
|
# [build-dependencies]
|
||||||
|
# gl_generator = "0.5"
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "android")'.dependencies.android_glue]
|
||||||
version = "0.2"
|
version = "0.2"
|
||||||
|
|
||||||
[target.'cfg(target_os="ios")'.dependencies]
|
[target.'cfg(target_os = "ios")'.dependencies]
|
||||||
objc = "0.2"
|
objc = "0.2"
|
||||||
|
|
||||||
[target.'cfg(target_os="macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
objc = "0.2"
|
objc = "0.2"
|
||||||
cgl = "0.1"
|
cgl = "0.1"
|
||||||
cocoa = "0.3"
|
cocoa = "0.3.2"
|
||||||
core-foundation = "0"
|
core-foundation = "0"
|
||||||
core-graphics = "0.3"
|
core-graphics = "0.3"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
winapi = "0.2"
|
winapi = "0.2"
|
||||||
shell32-sys = "0.1"
|
shell32-sys = "0.1"
|
||||||
gdi32-sys = "0.1"
|
gdi32-sys = "0.1"
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
[![](http://meritbadge.herokuapp.com/glutin)](https://crates.io/crates/glutin)
|
[![](http://meritbadge.herokuapp.com/glutin)](https://crates.io/crates/glutin)
|
||||||
|
|
||||||
|
[![Docs.rs](https://docs.rs/glutin/badge.svg)](https://docs.rs/glutin)
|
||||||
|
|
||||||
Alternative to GLFW in pure Rust.
|
Alternative to GLFW in pure Rust.
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/tomaka/glutin.png?branch=master)](https://travis-ci.org/tomaka/glutin)
|
[![Build Status](https://travis-ci.org/tomaka/glutin.png?branch=master)](https://travis-ci.org/tomaka/glutin)
|
||||||
|
@ -13,7 +15,7 @@ Alternative to GLFW in pure Rust.
|
||||||
glutin = "*"
|
glutin = "*"
|
||||||
```
|
```
|
||||||
|
|
||||||
## [Documentation](http://tomaka.github.io/glutin/)
|
## [Documentation](https://docs.rs/glutin)
|
||||||
|
|
||||||
## Try it!
|
## Try it!
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ fn main() {
|
||||||
};
|
};
|
||||||
|
|
||||||
let window = winit::WindowBuilder::new()
|
let window = winit::WindowBuilder::new()
|
||||||
.with_title("Hello world!".to_string())
|
.with_title("Hello world!")
|
||||||
.with_fullscreen(monitor)
|
.with_fullscreen(monitor)
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -31,7 +31,7 @@ fn main() {
|
||||||
|
|
||||||
Event::Closed => break,
|
Event::Closed => break,
|
||||||
|
|
||||||
a @ Event::MouseMoved(_) => {
|
a @ Event::MouseMoved(_, _) => {
|
||||||
println!("{:?}", a);
|
println!("{:?}", a);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
|
|
||||||
use libc;
|
use libc;
|
||||||
|
use std::os::raw;
|
||||||
|
|
||||||
#[link(name = "android")]
|
#[link(name = "android")]
|
||||||
#[link(name = "EGL")]
|
#[link(name = "EGL")]
|
||||||
|
@ -13,12 +14,12 @@ extern {}
|
||||||
/**
|
/**
|
||||||
* asset_manager.h
|
* asset_manager.h
|
||||||
*/
|
*/
|
||||||
pub type AAssetManager = ();
|
pub type AAssetManager = raw::c_void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* native_window.h
|
* native_window.h
|
||||||
*/
|
*/
|
||||||
pub type ANativeWindow = ();
|
pub type ANativeWindow = raw::c_void;
|
||||||
|
|
||||||
extern {
|
extern {
|
||||||
pub fn ANativeWindow_getHeight(window: *const ANativeWindow) -> libc::int32_t;
|
pub fn ANativeWindow_getHeight(window: *const ANativeWindow) -> libc::int32_t;
|
||||||
|
|
|
@ -56,9 +56,9 @@ impl MonitorId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct PlatformSpecificWindowBuilderAttributes;
|
pub struct PlatformSpecificWindowBuilderAttributes;
|
||||||
#[derive(Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct PlatformSpecificHeadlessBuilderAttributes;
|
pub struct PlatformSpecificHeadlessBuilderAttributes;
|
||||||
|
|
||||||
pub struct PollEventsIterator<'a> {
|
pub struct PollEventsIterator<'a> {
|
||||||
|
|
|
@ -6,6 +6,7 @@ use libc;
|
||||||
|
|
||||||
use WindowAttributes;
|
use WindowAttributes;
|
||||||
use native_monitor::NativeMonitorId;
|
use native_monitor::NativeMonitorId;
|
||||||
|
use os::macos::ActivationPolicy;
|
||||||
|
|
||||||
use objc::runtime::{Class, Object, Sel, BOOL, YES, NO};
|
use objc::runtime::{Class, Object, Sel, BOOL, YES, NO};
|
||||||
use objc::declare::ClassDecl;
|
use objc::declare::ClassDecl;
|
||||||
|
@ -15,9 +16,7 @@ use cgl::{CGLEnable, kCGLCECrashOnRemovedFunctions, CGLSetParameter, kCGLCPSurfa
|
||||||
use cocoa::base::{id, nil};
|
use cocoa::base::{id, nil};
|
||||||
use cocoa::foundation::{NSAutoreleasePool, NSDate, NSDefaultRunLoopMode, NSPoint, NSRect, NSSize,
|
use cocoa::foundation::{NSAutoreleasePool, NSDate, NSDefaultRunLoopMode, NSPoint, NSRect, NSSize,
|
||||||
NSString, NSUInteger};
|
NSString, NSUInteger};
|
||||||
use cocoa::appkit;
|
use cocoa::appkit::{self, NSApplication, NSEvent, NSOpenGLContext, NSOpenGLPixelFormat, NSView, NSWindow};
|
||||||
use cocoa::appkit::*;
|
|
||||||
use cocoa::appkit::NSEventSubtype::*;
|
|
||||||
|
|
||||||
use core_foundation::base::TCFType;
|
use core_foundation::base::TCFType;
|
||||||
use core_foundation::string::CFString;
|
use core_foundation::string::CFString;
|
||||||
|
@ -30,12 +29,9 @@ use std::collections::VecDeque;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::str::from_utf8;
|
use std::str::from_utf8;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::ascii::AsciiExt;
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use events::ElementState::{Pressed, Released};
|
use events::ElementState;
|
||||||
use events::Event::{Awakened, MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput};
|
|
||||||
use events::Event::{MouseWheel, Closed, Focused, TouchpadPressure};
|
|
||||||
use events::{self, MouseButton, TouchPhase};
|
use events::{self, MouseButton, TouchPhase};
|
||||||
|
|
||||||
pub use self::monitor::{MonitorId, get_available_monitors, get_primary_monitor};
|
pub use self::monitor::{MonitorId, get_available_monitors, get_primary_monitor};
|
||||||
|
@ -72,7 +68,7 @@ impl WindowDelegate {
|
||||||
unsafe {
|
unsafe {
|
||||||
let state: *mut c_void = *this.get_ivar("glutinState");
|
let state: *mut c_void = *this.get_ivar("glutinState");
|
||||||
let state = state as *mut DelegateState;
|
let state = state as *mut DelegateState;
|
||||||
(*state).pending_events.lock().unwrap().push_back(Closed);
|
(*state).pending_events.lock().unwrap().push_back(Event::Closed);
|
||||||
}
|
}
|
||||||
YES
|
YES
|
||||||
}
|
}
|
||||||
|
@ -101,7 +97,7 @@ impl WindowDelegate {
|
||||||
|
|
||||||
let state: *mut c_void = *this.get_ivar("glutinState");
|
let state: *mut c_void = *this.get_ivar("glutinState");
|
||||||
let state = state as *mut DelegateState;
|
let state = state as *mut DelegateState;
|
||||||
(*state).pending_events.lock().unwrap().push_back(Focused(true));
|
(*state).pending_events.lock().unwrap().push_back(Event::Focused(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +105,7 @@ impl WindowDelegate {
|
||||||
unsafe {
|
unsafe {
|
||||||
let state: *mut c_void = *this.get_ivar("glutinState");
|
let state: *mut c_void = *this.get_ivar("glutinState");
|
||||||
let state = state as *mut DelegateState;
|
let state = state as *mut DelegateState;
|
||||||
(*state).pending_events.lock().unwrap().push_back(Focused(false));
|
(*state).pending_events.lock().unwrap().push_back(Event::Focused(false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,8 +163,10 @@ impl Drop for WindowDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct PlatformSpecificWindowBuilderAttributes;
|
pub struct PlatformSpecificWindowBuilderAttributes {
|
||||||
|
pub activation_policy: ActivationPolicy,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
view: IdRef,
|
view: IdRef,
|
||||||
|
@ -188,9 +186,9 @@ impl WindowProxy {
|
||||||
let pool = NSAutoreleasePool::new(nil);
|
let pool = NSAutoreleasePool::new(nil);
|
||||||
let event =
|
let event =
|
||||||
NSEvent::otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_(
|
NSEvent::otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_(
|
||||||
nil, NSApplicationDefined, NSPoint::new(0.0, 0.0), NSEventModifierFlags::empty(),
|
nil, appkit::NSApplicationDefined, NSPoint::new(0.0, 0.0), appkit::NSEventModifierFlags::empty(),
|
||||||
0.0, 0, nil, NSApplicationActivatedEventType, 0, 0);
|
0.0, 0, nil, appkit::NSEventSubtype::NSApplicationActivatedEventType, 0, 0);
|
||||||
NSApp().postEvent_atStart_(event, NO);
|
appkit::NSApp().postEvent_atStart_(event, NO);
|
||||||
pool.drain();
|
pool.drain();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,8 +210,8 @@ impl<'a> Iterator for PollEventsIterator<'a> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let pool = NSAutoreleasePool::new(nil);
|
let pool = NSAutoreleasePool::new(nil);
|
||||||
|
|
||||||
let nsevent = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
|
let nsevent = appkit::NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
|
||||||
NSAnyEventMask.bits() | NSEventMaskPressure.bits(),
|
appkit::NSAnyEventMask.bits() | appkit::NSEventMaskPressure.bits(),
|
||||||
NSDate::distantPast(nil),
|
NSDate::distantPast(nil),
|
||||||
NSDefaultRunLoopMode,
|
NSDefaultRunLoopMode,
|
||||||
YES);
|
YES);
|
||||||
|
@ -241,8 +239,8 @@ impl<'a> Iterator for WaitEventsIterator<'a> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let pool = NSAutoreleasePool::new(nil);
|
let pool = NSAutoreleasePool::new(nil);
|
||||||
|
|
||||||
let nsevent = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
|
let nsevent = appkit::NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
|
||||||
NSAnyEventMask.bits() | NSEventMaskPressure.bits(),
|
appkit::NSAnyEventMask.bits() | appkit::NSEventMaskPressure.bits(),
|
||||||
NSDate::distantFuture(nil),
|
NSDate::distantFuture(nil),
|
||||||
NSDefaultRunLoopMode,
|
NSDefaultRunLoopMode,
|
||||||
YES);
|
YES);
|
||||||
|
@ -252,7 +250,7 @@ impl<'a> Iterator for WaitEventsIterator<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if event.is_none() {
|
if event.is_none() {
|
||||||
return Some(Awakened);
|
return Some(Event::Awakened);
|
||||||
} else {
|
} else {
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
@ -261,14 +259,15 @@ impl<'a> Iterator for WaitEventsIterator<'a> {
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
pub fn new(win_attribs: &WindowAttributes,
|
pub fn new(win_attribs: &WindowAttributes,
|
||||||
_: &PlatformSpecificWindowBuilderAttributes)
|
pl_attribs: &PlatformSpecificWindowBuilderAttributes)
|
||||||
-> Result<Window, CreationError>
|
-> Result<Window, CreationError>
|
||||||
{
|
{
|
||||||
// not implemented
|
// not implemented
|
||||||
assert!(win_attribs.min_dimensions.is_none());
|
assert!(win_attribs.min_dimensions.is_none());
|
||||||
assert!(win_attribs.max_dimensions.is_none());
|
assert!(win_attribs.max_dimensions.is_none());
|
||||||
|
|
||||||
let app = match Window::create_app() {
|
// let app = match Window::create_app() {
|
||||||
|
let app = match Window::create_app(pl_attribs.activation_policy) {
|
||||||
Some(app) => app,
|
Some(app) => app,
|
||||||
None => { return Err(OsError(format!("Couldn't create NSApplication"))); },
|
None => { return Err(OsError(format!("Couldn't create NSApplication"))); },
|
||||||
};
|
};
|
||||||
|
@ -312,13 +311,13 @@ impl Window {
|
||||||
Ok(window)
|
Ok(window)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_app() -> Option<id> {
|
fn create_app(activation_policy: ActivationPolicy) -> Option<id> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let app = NSApp();
|
let app = appkit::NSApp();
|
||||||
if app == nil {
|
if app == nil {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
|
app.setActivationPolicy_(activation_policy.into());
|
||||||
app.finishLaunching();
|
app.finishLaunching();
|
||||||
Some(app)
|
Some(app)
|
||||||
}
|
}
|
||||||
|
@ -334,13 +333,13 @@ impl Window {
|
||||||
_ => panic!("OS X monitors should always have a numeric native ID")
|
_ => panic!("OS X monitors should always have a numeric native ID")
|
||||||
};
|
};
|
||||||
let matching_screen = {
|
let matching_screen = {
|
||||||
let screens = NSScreen::screens(nil);
|
let screens = appkit::NSScreen::screens(nil);
|
||||||
let count: NSUInteger = msg_send![screens, count];
|
let count: NSUInteger = msg_send![screens, count];
|
||||||
let key = IdRef::new(NSString::alloc(nil).init_str("NSScreenNumber"));
|
let key = IdRef::new(NSString::alloc(nil).init_str("NSScreenNumber"));
|
||||||
let mut matching_screen: Option<id> = None;
|
let mut matching_screen: Option<id> = None;
|
||||||
for i in 0..count {
|
for i in 0..count {
|
||||||
let screen = msg_send![screens, objectAtIndex:i as NSUInteger];
|
let screen = msg_send![screens, objectAtIndex:i as NSUInteger];
|
||||||
let device_description = NSScreen::deviceDescription(screen);
|
let device_description = appkit::NSScreen::deviceDescription(screen);
|
||||||
let value: id = msg_send![device_description, objectForKey:*key];
|
let value: id = msg_send![device_description, objectForKey:*key];
|
||||||
if value != nil {
|
if value != nil {
|
||||||
let screen_number: NSUInteger = msg_send![value, unsignedIntegerValue];
|
let screen_number: NSUInteger = msg_send![value, unsignedIntegerValue];
|
||||||
|
@ -352,12 +351,12 @@ impl Window {
|
||||||
}
|
}
|
||||||
matching_screen
|
matching_screen
|
||||||
};
|
};
|
||||||
Some(matching_screen.unwrap_or(NSScreen::mainScreen(nil)))
|
Some(matching_screen.unwrap_or(appkit::NSScreen::mainScreen(nil)))
|
||||||
},
|
},
|
||||||
None => None
|
None => None
|
||||||
};
|
};
|
||||||
let frame = match screen {
|
let frame = match screen {
|
||||||
Some(screen) => NSScreen::frame(screen),
|
Some(screen) => appkit::NSScreen::frame(screen),
|
||||||
None => {
|
None => {
|
||||||
let (width, height) = attrs.dimensions.unwrap_or((800, 600));
|
let (width, height) = attrs.dimensions.unwrap_or((800, 600));
|
||||||
NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64))
|
NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64))
|
||||||
|
@ -366,42 +365,43 @@ impl Window {
|
||||||
|
|
||||||
let masks = if screen.is_some() || attrs.transparent {
|
let masks = if screen.is_some() || attrs.transparent {
|
||||||
// Fullscreen or transparent window
|
// Fullscreen or transparent window
|
||||||
NSBorderlessWindowMask as NSUInteger |
|
appkit::NSBorderlessWindowMask as NSUInteger |
|
||||||
NSResizableWindowMask as NSUInteger |
|
appkit::NSResizableWindowMask as NSUInteger |
|
||||||
NSTitledWindowMask as NSUInteger
|
appkit::NSTitledWindowMask as NSUInteger
|
||||||
} else if attrs.decorations {
|
} else if attrs.decorations {
|
||||||
// Classic opaque window with titlebar
|
// Classic opaque window with titlebar
|
||||||
NSClosableWindowMask as NSUInteger |
|
appkit::NSClosableWindowMask as NSUInteger |
|
||||||
NSMiniaturizableWindowMask as NSUInteger |
|
appkit::NSMiniaturizableWindowMask as NSUInteger |
|
||||||
NSResizableWindowMask as NSUInteger |
|
appkit::NSResizableWindowMask as NSUInteger |
|
||||||
NSTitledWindowMask as NSUInteger
|
appkit::NSTitledWindowMask as NSUInteger
|
||||||
} else {
|
} else {
|
||||||
// Opaque window without a titlebar
|
// Opaque window without a titlebar
|
||||||
NSClosableWindowMask as NSUInteger |
|
appkit::NSClosableWindowMask as NSUInteger |
|
||||||
NSMiniaturizableWindowMask as NSUInteger |
|
appkit::NSMiniaturizableWindowMask as NSUInteger |
|
||||||
NSResizableWindowMask as NSUInteger |
|
appkit::NSResizableWindowMask as NSUInteger |
|
||||||
NSTitledWindowMask as NSUInteger |
|
appkit::NSTitledWindowMask as NSUInteger |
|
||||||
NSFullSizeContentViewWindowMask as NSUInteger
|
appkit::NSFullSizeContentViewWindowMask as NSUInteger
|
||||||
};
|
};
|
||||||
|
|
||||||
let window = IdRef::new(NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
|
let window = IdRef::new(NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
|
||||||
frame,
|
frame,
|
||||||
masks,
|
masks,
|
||||||
NSBackingStoreBuffered,
|
appkit::NSBackingStoreBuffered,
|
||||||
NO,
|
NO,
|
||||||
));
|
));
|
||||||
window.non_nil().map(|window| {
|
window.non_nil().map(|window| {
|
||||||
let title = IdRef::new(NSString::alloc(nil).init_str(&attrs.title));
|
let title = IdRef::new(NSString::alloc(nil).init_str(&attrs.title));
|
||||||
|
window.setReleasedWhenClosed_(NO);
|
||||||
window.setTitle_(*title);
|
window.setTitle_(*title);
|
||||||
window.setAcceptsMouseMovedEvents_(YES);
|
window.setAcceptsMouseMovedEvents_(YES);
|
||||||
|
|
||||||
if !attrs.decorations {
|
if !attrs.decorations {
|
||||||
window.setTitleVisibility_(NSWindowTitleVisibility::NSWindowTitleHidden);
|
window.setTitleVisibility_(appkit::NSWindowTitleVisibility::NSWindowTitleHidden);
|
||||||
window.setTitlebarAppearsTransparent_(YES);
|
window.setTitlebarAppearsTransparent_(YES);
|
||||||
}
|
}
|
||||||
|
|
||||||
if screen.is_some() {
|
if screen.is_some() {
|
||||||
window.setLevel_(NSMainMenuWindowLevel as i64 + 1);
|
window.setLevel_(appkit::NSMainMenuWindowLevel as i64 + 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
window.center();
|
window.center();
|
||||||
|
@ -511,11 +511,11 @@ impl Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn modifier_event(event: id, keymask: NSEventModifierFlags, key: events::VirtualKeyCode, key_pressed: bool) -> Option<Event> {
|
unsafe fn modifier_event(event: id, keymask: appkit::NSEventModifierFlags, key: events::VirtualKeyCode, key_pressed: bool) -> Option<Event> {
|
||||||
if !key_pressed && NSEvent::modifierFlags(event).contains(keymask) {
|
if !key_pressed && NSEvent::modifierFlags(event).contains(keymask) {
|
||||||
return Some(KeyboardInput(Pressed, NSEvent::keyCode(event) as u8, Some(key)));
|
return Some(Event::KeyboardInput(ElementState::Pressed, NSEvent::keyCode(event) as u8, Some(key)));
|
||||||
} else if key_pressed && !NSEvent::modifierFlags(event).contains(keymask) {
|
} else if key_pressed && !NSEvent::modifierFlags(event).contains(keymask) {
|
||||||
return Some(KeyboardInput(Released, NSEvent::keyCode(event) as u8, Some(key)));
|
return Some(Event::KeyboardInput(ElementState::Released, NSEvent::keyCode(event) as u8, Some(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return None;
|
return None;
|
||||||
|
@ -609,7 +609,10 @@ impl Window {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// TODO: Check for errors.
|
// TODO: Check for errors.
|
||||||
let _ = CGWarpMouseCursorPosition(CGPoint { x: cursor_x as CGFloat, y: cursor_y as CGFloat });
|
let _ = CGWarpMouseCursorPosition(appkit::CGPoint {
|
||||||
|
x: cursor_x as appkit::CGFloat,
|
||||||
|
y: cursor_y as appkit::CGFloat,
|
||||||
|
});
|
||||||
let _ = CGAssociateMouseAndMouseCursorPosition(true);
|
let _ = CGAssociateMouseAndMouseCursorPosition(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -661,22 +664,22 @@ impl Clone for IdRef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case, non_upper_case_globals)]
|
||||||
unsafe fn NSEventToEvent(window: &Window, nsevent: id) -> Option<Event> {
|
unsafe fn NSEventToEvent(window: &Window, nsevent: id) -> Option<Event> {
|
||||||
if nsevent == nil { return None; }
|
if nsevent == nil { return None; }
|
||||||
|
|
||||||
let event_type = nsevent.eventType();
|
let event_type = nsevent.eventType();
|
||||||
NSApp().sendEvent_(if let NSKeyDown = event_type { nil } else { nsevent });
|
appkit::NSApp().sendEvent_(if let appkit::NSKeyDown = event_type { nil } else { nsevent });
|
||||||
|
|
||||||
match event_type {
|
match event_type {
|
||||||
NSLeftMouseDown => { Some(MouseInput(Pressed, MouseButton::Left)) },
|
appkit::NSLeftMouseDown => { Some(Event::MouseInput(ElementState::Pressed, MouseButton::Left)) },
|
||||||
NSLeftMouseUp => { Some(MouseInput(Released, MouseButton::Left)) },
|
appkit::NSLeftMouseUp => { Some(Event::MouseInput(ElementState::Released, MouseButton::Left)) },
|
||||||
NSRightMouseDown => { Some(MouseInput(Pressed, MouseButton::Right)) },
|
appkit::NSRightMouseDown => { Some(Event::MouseInput(ElementState::Pressed, MouseButton::Right)) },
|
||||||
NSRightMouseUp => { Some(MouseInput(Released, MouseButton::Right)) },
|
appkit::NSRightMouseUp => { Some(Event::MouseInput(ElementState::Released, MouseButton::Right)) },
|
||||||
NSMouseMoved |
|
appkit::NSMouseMoved |
|
||||||
NSLeftMouseDragged |
|
appkit::NSLeftMouseDragged |
|
||||||
NSOtherMouseDragged |
|
appkit::NSOtherMouseDragged |
|
||||||
NSRightMouseDragged => {
|
appkit::NSRightMouseDragged => {
|
||||||
let window_point = nsevent.locationInWindow();
|
let window_point = nsevent.locationInWindow();
|
||||||
let cWindow: id = msg_send![nsevent, window];
|
let cWindow: id = msg_send![nsevent, window];
|
||||||
let view_point = if cWindow == nil {
|
let view_point = if cWindow == nil {
|
||||||
|
@ -688,29 +691,29 @@ unsafe fn NSEventToEvent(window: &Window, nsevent: id) -> Option<Event> {
|
||||||
let view_rect = NSView::frame(*window.view);
|
let view_rect = NSView::frame(*window.view);
|
||||||
let scale_factor = window.hidpi_factor();
|
let scale_factor = window.hidpi_factor();
|
||||||
|
|
||||||
Some(MouseMoved(((scale_factor * view_point.x as f32) as i32,
|
Some(Event::MouseMoved((scale_factor * view_point.x as f32) as i32,
|
||||||
(scale_factor * (view_rect.size.height - view_point.y) as f32) as i32)))
|
(scale_factor * (view_rect.size.height - view_point.y) as f32) as i32))
|
||||||
},
|
},
|
||||||
NSKeyDown => {
|
appkit::NSKeyDown => {
|
||||||
let mut events = VecDeque::new();
|
let mut events = VecDeque::new();
|
||||||
let received_c_str = nsevent.characters().UTF8String();
|
let received_c_str = nsevent.characters().UTF8String();
|
||||||
let received_str = CStr::from_ptr(received_c_str);
|
let received_str = CStr::from_ptr(received_c_str);
|
||||||
for received_char in from_utf8(received_str.to_bytes()).unwrap().chars() {
|
for received_char in from_utf8(received_str.to_bytes()).unwrap().chars() {
|
||||||
events.push_back(ReceivedCharacter(received_char));
|
events.push_back(Event::ReceivedCharacter(received_char));
|
||||||
}
|
}
|
||||||
|
|
||||||
let vkey = event::vkeycode_to_element(NSEvent::keyCode(nsevent));
|
let vkey = event::vkeycode_to_element(NSEvent::keyCode(nsevent));
|
||||||
events.push_back(KeyboardInput(Pressed, NSEvent::keyCode(nsevent) as u8, vkey));
|
events.push_back(Event::KeyboardInput(ElementState::Pressed, NSEvent::keyCode(nsevent) as u8, vkey));
|
||||||
let event = events.pop_front();
|
let event = events.pop_front();
|
||||||
window.delegate.state.pending_events.lock().unwrap().extend(events.into_iter());
|
window.delegate.state.pending_events.lock().unwrap().extend(events.into_iter());
|
||||||
event
|
event
|
||||||
},
|
},
|
||||||
NSKeyUp => {
|
appkit::NSKeyUp => {
|
||||||
let vkey = event::vkeycode_to_element(NSEvent::keyCode(nsevent));
|
let vkey = event::vkeycode_to_element(NSEvent::keyCode(nsevent));
|
||||||
|
|
||||||
Some(KeyboardInput(Released, NSEvent::keyCode(nsevent) as u8, vkey))
|
Some(Event::KeyboardInput(ElementState::Released, NSEvent::keyCode(nsevent) as u8, vkey))
|
||||||
},
|
},
|
||||||
NSFlagsChanged => {
|
appkit::NSFlagsChanged => {
|
||||||
let mut events = VecDeque::new();
|
let mut events = VecDeque::new();
|
||||||
let shift_modifier = Window::modifier_event(nsevent, appkit::NSShiftKeyMask, events::VirtualKeyCode::LShift, shift_pressed);
|
let shift_modifier = Window::modifier_event(nsevent, appkit::NSShiftKeyMask, events::VirtualKeyCode::LShift, shift_pressed);
|
||||||
if shift_modifier.is_some() {
|
if shift_modifier.is_some() {
|
||||||
|
@ -736,7 +739,7 @@ unsafe fn NSEventToEvent(window: &Window, nsevent: id) -> Option<Event> {
|
||||||
window.delegate.state.pending_events.lock().unwrap().extend(events.into_iter());
|
window.delegate.state.pending_events.lock().unwrap().extend(events.into_iter());
|
||||||
event
|
event
|
||||||
},
|
},
|
||||||
NSScrollWheel => {
|
appkit::NSScrollWheel => {
|
||||||
use events::MouseScrollDelta::{LineDelta, PixelDelta};
|
use events::MouseScrollDelta::{LineDelta, PixelDelta};
|
||||||
let scale_factor = window.hidpi_factor();
|
let scale_factor = window.hidpi_factor();
|
||||||
let delta = if nsevent.hasPreciseScrollingDeltas() == YES {
|
let delta = if nsevent.hasPreciseScrollingDeltas() == YES {
|
||||||
|
@ -747,14 +750,14 @@ unsafe fn NSEventToEvent(window: &Window, nsevent: id) -> Option<Event> {
|
||||||
scale_factor * nsevent.scrollingDeltaY() as f32)
|
scale_factor * nsevent.scrollingDeltaY() as f32)
|
||||||
};
|
};
|
||||||
let phase = match nsevent.phase() {
|
let phase = match nsevent.phase() {
|
||||||
NSEventPhaseMayBegin | NSEventPhaseBegan => TouchPhase::Started,
|
appkit::NSEventPhaseMayBegin | appkit::NSEventPhaseBegan => TouchPhase::Started,
|
||||||
NSEventPhaseEnded => TouchPhase::Ended,
|
appkit::NSEventPhaseEnded => TouchPhase::Ended,
|
||||||
_ => TouchPhase::Moved,
|
_ => TouchPhase::Moved,
|
||||||
};
|
};
|
||||||
Some(MouseWheel(delta, phase))
|
Some(Event::MouseWheel(delta, phase))
|
||||||
},
|
},
|
||||||
NSEventTypePressure => {
|
appkit::NSEventTypePressure => {
|
||||||
Some(TouchpadPressure(nsevent.pressure(), nsevent.stage()))
|
Some(Event::TouchpadPressure(nsevent.pressure(), nsevent.stage()))
|
||||||
},
|
},
|
||||||
_ => { None },
|
_ => { None },
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,7 +177,7 @@ impl MonitorId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct PlatformSpecificWindowBuilderAttributes;
|
pub struct PlatformSpecificWindowBuilderAttributes;
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
|
|
|
@ -52,7 +52,7 @@ pub fn translate_event(
|
||||||
if known_surfaces.contains(&surface) {
|
if known_surfaces.contains(&surface) {
|
||||||
focuses.pointer_on = Some(surface);
|
focuses.pointer_on = Some(surface);
|
||||||
focuses.pointer_at = Some((x, y));
|
focuses.pointer_at = Some((x, y));
|
||||||
Some((GlutinEvent::MouseMoved((x as i32, y as i32)), surface))
|
Some((GlutinEvent::MouseMoved(x as i32, y as i32), surface))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ pub fn translate_event(
|
||||||
WlPointerEvent::Motion(_, x, y) => {
|
WlPointerEvent::Motion(_, x, y) => {
|
||||||
if let Some(surface) = focuses.pointer_on {
|
if let Some(surface) = focuses.pointer_on {
|
||||||
focuses.pointer_at = Some((x, y));
|
focuses.pointer_at = Some((x, y));
|
||||||
Some((GlutinEvent::MouseMoved((x as i32, y as i32)), surface))
|
Some((GlutinEvent::MouseMoved(x as i32, y as i32), surface))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,15 +136,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT,
|
||||||
let x = winapi::GET_X_LPARAM(lparam) as i32;
|
let x = winapi::GET_X_LPARAM(lparam) as i32;
|
||||||
let y = winapi::GET_Y_LPARAM(lparam) as i32;
|
let y = winapi::GET_Y_LPARAM(lparam) as i32;
|
||||||
|
|
||||||
let mut mouse_track = winapi::TRACKMOUSEEVENT {
|
send_event(window, MouseMoved(x, y));
|
||||||
cbSize: mem::size_of::<winapi::TRACKMOUSEEVENT>() as winapi::DWORD,
|
|
||||||
dwFlags: winapi::TME_HOVER | winapi::TME_LEAVE,
|
|
||||||
hwndTrack: window,
|
|
||||||
dwHoverTime: winapi::HOVER_DEFAULT
|
|
||||||
};
|
|
||||||
user32::TrackMouseEvent(&mut mouse_track);
|
|
||||||
|
|
||||||
send_event(window, MouseMoved((x, y)));
|
|
||||||
|
|
||||||
0
|
0
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub fn keycode_to_element(scancode: libc::c_uint) -> Option<VirtualKeyCode> {
|
||||||
//ffi::XK_Sys_Req => events::VirtualKeyCode::Sys_req,
|
//ffi::XK_Sys_Req => events::VirtualKeyCode::Sys_req,
|
||||||
ffi::XK_Escape => events::VirtualKeyCode::Escape,
|
ffi::XK_Escape => events::VirtualKeyCode::Escape,
|
||||||
ffi::XK_Delete => events::VirtualKeyCode::Delete,
|
ffi::XK_Delete => events::VirtualKeyCode::Delete,
|
||||||
//ffi::XK_Multi_key => events::VirtualKeyCode::Multi_key,
|
ffi::XK_Multi_key => events::VirtualKeyCode::Compose,
|
||||||
//ffi::XK_Kanji => events::VirtualKeyCode::Kanji,
|
//ffi::XK_Kanji => events::VirtualKeyCode::Kanji,
|
||||||
//ffi::XK_Muhenkan => events::VirtualKeyCode::Muhenkan,
|
//ffi::XK_Muhenkan => events::VirtualKeyCode::Muhenkan,
|
||||||
//ffi::XK_Henkan_Mode => events::VirtualKeyCode::Henkan_mode,
|
//ffi::XK_Henkan_Mode => events::VirtualKeyCode::Henkan_mode,
|
||||||
|
|
|
@ -241,7 +241,7 @@ impl XInputEventHandler {
|
||||||
let new_cursor_pos = (event_data.event_x, event_data.event_y);
|
let new_cursor_pos = (event_data.event_x, event_data.event_y);
|
||||||
if new_cursor_pos != self.current_state.cursor_pos {
|
if new_cursor_pos != self.current_state.cursor_pos {
|
||||||
self.current_state.cursor_pos = new_cursor_pos;
|
self.current_state.cursor_pos = new_cursor_pos;
|
||||||
Some(MouseMoved((new_cursor_pos.0 as i32, new_cursor_pos.1 as i32)))
|
Some(MouseMoved(new_cursor_pos.0 as i32, new_cursor_pos.1 as i32))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use CreationError;
|
||||||
use CreationError::OsError;
|
use CreationError::OsError;
|
||||||
use libc;
|
use libc;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::{mem, ptr};
|
use std::{mem, ptr, cmp};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
@ -285,11 +285,23 @@ impl Window {
|
||||||
pub fn new(display: &Arc<XConnection>, window_attrs: &WindowAttributes)
|
pub fn new(display: &Arc<XConnection>, window_attrs: &WindowAttributes)
|
||||||
-> Result<Window, CreationError>
|
-> Result<Window, CreationError>
|
||||||
{
|
{
|
||||||
let dimensions = window_attrs.dimensions.unwrap_or((800, 600));
|
let dimensions = {
|
||||||
|
|
||||||
// not implemented
|
// x11 only applies constraints when the window is actively resized
|
||||||
assert!(window_attrs.min_dimensions.is_none());
|
// by the user, so we have to manually apply the initial constraints
|
||||||
assert!(window_attrs.max_dimensions.is_none());
|
let mut dimensions = window_attrs.dimensions.unwrap_or((800, 600));
|
||||||
|
if let Some(max) = window_attrs.max_dimensions {
|
||||||
|
dimensions.0 = cmp::min(dimensions.0, max.0);
|
||||||
|
dimensions.1 = cmp::min(dimensions.1, max.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(min) = window_attrs.min_dimensions {
|
||||||
|
dimensions.0 = cmp::max(dimensions.0, min.0);
|
||||||
|
dimensions.1 = cmp::max(dimensions.1, min.1);
|
||||||
|
}
|
||||||
|
dimensions
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
let screen_id = match window_attrs.monitor {
|
let screen_id = match window_attrs.monitor {
|
||||||
Some(PlatformMonitorId::X(MonitorId(_, monitor))) => monitor as i32,
|
Some(PlatformMonitorId::X(MonitorId(_, monitor))) => monitor as i32,
|
||||||
|
@ -502,6 +514,32 @@ impl Window {
|
||||||
(display.xf86vmode.XF86VidModeSetViewPort)(display.display, screen_id, 0, 0);
|
(display.xf86vmode.XF86VidModeSetViewPort)(display.display, screen_id, 0, 0);
|
||||||
display.check_errors().expect("Failed to call XF86VidModeSetViewPort");
|
display.check_errors().expect("Failed to call XF86VidModeSetViewPort");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// set size hints
|
||||||
|
let mut size_hints: ffi::XSizeHints = unsafe { mem::zeroed() };
|
||||||
|
size_hints.flags = ffi::PSize;
|
||||||
|
size_hints.width = dimensions.0 as i32;
|
||||||
|
size_hints.height = dimensions.1 as i32;
|
||||||
|
|
||||||
|
if let Some(dimensions) = window_attrs.min_dimensions {
|
||||||
|
size_hints.flags |= ffi::PMinSize;
|
||||||
|
size_hints.min_width = dimensions.0 as i32;
|
||||||
|
size_hints.min_height = dimensions.1 as i32;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(dimensions) = window_attrs.max_dimensions {
|
||||||
|
size_hints.flags |= ffi::PMaxSize;
|
||||||
|
size_hints.max_width = dimensions.0 as i32;
|
||||||
|
size_hints.max_height = dimensions.1 as i32;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
(display.xlib.XSetNormalHints)(display.display, window, &mut size_hints);
|
||||||
|
display.check_errors().expect("Failed to call XSetNormalHints");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// creating the window object
|
// creating the window object
|
||||||
|
@ -706,51 +744,115 @@ impl Window {
|
||||||
|
|
||||||
pub fn set_cursor(&self, cursor: MouseCursor) {
|
pub fn set_cursor(&self, cursor: MouseCursor) {
|
||||||
unsafe {
|
unsafe {
|
||||||
use std::ffi::CString;
|
let load = |name: &str| {
|
||||||
let cursor_name = match cursor {
|
self.load_cursor(name)
|
||||||
MouseCursor::Alias => "link",
|
};
|
||||||
MouseCursor::Arrow => "arrow",
|
|
||||||
MouseCursor::Cell => "plus",
|
let loadn = |names: &[&str]| {
|
||||||
MouseCursor::Copy => "copy",
|
self.load_first_existing_cursor(names)
|
||||||
MouseCursor::Crosshair => "crosshair",
|
};
|
||||||
MouseCursor::Default => "left_ptr",
|
|
||||||
MouseCursor::Grabbing => "grabbing",
|
// Try multiple names in some cases where the name
|
||||||
MouseCursor::Hand | MouseCursor::Grab => "hand",
|
// differs on the desktop environments or themes.
|
||||||
MouseCursor::Help => "question_arrow",
|
//
|
||||||
MouseCursor::Move => "move",
|
// Try the better looking (or more suiting) names first.
|
||||||
MouseCursor::NoDrop => "circle",
|
let mut xcursor = match cursor {
|
||||||
MouseCursor::NotAllowed => "crossed_circle",
|
MouseCursor::Alias => load("link"),
|
||||||
MouseCursor::Progress => "left_ptr_watch",
|
MouseCursor::Arrow => load("arrow"),
|
||||||
|
MouseCursor::Cell => load("plus"),
|
||||||
|
MouseCursor::Copy => load("copy"),
|
||||||
|
MouseCursor::Crosshair => load("crosshair"),
|
||||||
|
MouseCursor::Default => load("left_ptr"),
|
||||||
|
MouseCursor::Hand => load("hand1"),
|
||||||
|
MouseCursor::Help => load("question_arrow"),
|
||||||
|
MouseCursor::Move => load("move"),
|
||||||
|
MouseCursor::Grab => loadn(&["openhand", "grab"]),
|
||||||
|
MouseCursor::Grabbing => loadn(&["closedhand", "grabbing"]),
|
||||||
|
MouseCursor::Progress => load("left_ptr_watch"),
|
||||||
|
MouseCursor::AllScroll => load("all-scroll"),
|
||||||
|
MouseCursor::ContextMenu => load("context-menu"),
|
||||||
|
|
||||||
|
MouseCursor::NoDrop => loadn(&["no-drop", "circle"]),
|
||||||
|
MouseCursor::NotAllowed => load("crossed_circle"),
|
||||||
|
|
||||||
|
|
||||||
/// Resize cursors
|
/// Resize cursors
|
||||||
MouseCursor::EResize => "right_side",
|
MouseCursor::EResize => load("right_side"),
|
||||||
MouseCursor::NResize => "top_side",
|
MouseCursor::NResize => load("top_side"),
|
||||||
MouseCursor::NeResize => "top_right_corner",
|
MouseCursor::NeResize => load("top_right_corner"),
|
||||||
MouseCursor::NwResize => "top_left_corner",
|
MouseCursor::NwResize => load("top_left_corner"),
|
||||||
MouseCursor::SResize => "bottom_side",
|
MouseCursor::SResize => load("bottom_side"),
|
||||||
MouseCursor::SeResize => "bottom_right_corner",
|
MouseCursor::SeResize => load("bottom_right_corner"),
|
||||||
MouseCursor::SwResize => "bottom_left_corner",
|
MouseCursor::SwResize => load("bottom_left_corner"),
|
||||||
MouseCursor::WResize => "left_side",
|
MouseCursor::WResize => load("left_side"),
|
||||||
MouseCursor::EwResize | MouseCursor::ColResize => "h_double_arrow",
|
MouseCursor::EwResize => load("h_double_arrow"),
|
||||||
MouseCursor::NsResize | MouseCursor::RowResize => "v_double_arrow",
|
MouseCursor::NsResize => load("v_double_arrow"),
|
||||||
MouseCursor::NwseResize => "bd_double_arrow",
|
MouseCursor::NwseResize => loadn(&["bd_double_arrow", "size_bdiag"]),
|
||||||
MouseCursor::NeswResize => "fd_double_arrow",
|
MouseCursor::NeswResize => loadn(&["fd_double_arrow", "size_fdiag"]),
|
||||||
|
MouseCursor::ColResize => loadn(&["split_h", "h_double_arrow"]),
|
||||||
|
MouseCursor::RowResize => loadn(&["split_v", "v_double_arrow"]),
|
||||||
|
|
||||||
MouseCursor::Text | MouseCursor::VerticalText => "xterm",
|
MouseCursor::Text => loadn(&["text", "xterm"]),
|
||||||
MouseCursor::Wait => "watch",
|
MouseCursor::VerticalText => load("vertical-text"),
|
||||||
|
|
||||||
/// TODO: Find matching X11 cursors
|
MouseCursor::Wait => load("watch"),
|
||||||
MouseCursor::ContextMenu | MouseCursor::NoneCursor |
|
|
||||||
MouseCursor::AllScroll | MouseCursor::ZoomIn |
|
MouseCursor::ZoomIn => load("zoom-in"),
|
||||||
MouseCursor::ZoomOut => "left_ptr",
|
MouseCursor::ZoomOut => load("zoom-out"),
|
||||||
|
|
||||||
|
MouseCursor::NoneCursor => self.create_empty_cursor(),
|
||||||
};
|
};
|
||||||
let c_string = CString::new(cursor_name.as_bytes().to_vec()).unwrap();
|
|
||||||
let xcursor = (self.x.display.xcursor.XcursorLibraryLoadCursor)(self.x.display.display, c_string.as_ptr());
|
|
||||||
self.x.display.check_errors().expect("Failed to call XcursorLibraryLoadCursor");
|
|
||||||
(self.x.display.xlib.XDefineCursor)(self.x.display.display, self.x.window, xcursor);
|
(self.x.display.xlib.XDefineCursor)(self.x.display.display, self.x.window, xcursor);
|
||||||
(self.x.display.xlib.XFlush)(self.x.display.display);
|
if xcursor != 0 {
|
||||||
(self.x.display.xlib.XFreeCursor)(self.x.display.display, xcursor);
|
(self.x.display.xlib.XFreeCursor)(self.x.display.display, xcursor);
|
||||||
self.x.display.check_errors().expect("Failed to call XDefineCursor");
|
}
|
||||||
|
self.x.display.check_errors().expect("Failed to set or free the cursor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_cursor(&self, name: &str) -> ffi::Cursor {
|
||||||
|
use std::ffi::CString;
|
||||||
|
unsafe {
|
||||||
|
let c_string = CString::new(name.as_bytes()).unwrap();
|
||||||
|
(self.x.display.xcursor.XcursorLibraryLoadCursor)(self.x.display.display, c_string.as_ptr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_first_existing_cursor(&self, names :&[&str]) -> ffi::Cursor {
|
||||||
|
for name in names.iter() {
|
||||||
|
let xcursor = self.load_cursor(name);
|
||||||
|
if xcursor != 0 {
|
||||||
|
return xcursor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This could maybe be cached. I don't think it's worth
|
||||||
|
// the complexity, since cursor changes are not so common,
|
||||||
|
// and this is just allocating a 1x1 pixmap...
|
||||||
|
fn create_empty_cursor(&self) -> ffi::Cursor {
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
let data = 0;
|
||||||
|
unsafe {
|
||||||
|
let pixmap = (self.x.display.xlib.XCreateBitmapFromData)(self.x.display.display, self.x.window, &data, 1, 1);
|
||||||
|
if pixmap == 0 {
|
||||||
|
// Failed to allocate
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't care about this color, since it only fills bytes
|
||||||
|
// in the pixmap which are not 0 in the mask.
|
||||||
|
let dummy_color: ffi::XColor = mem::uninitialized();
|
||||||
|
let cursor = (self.x.display.xlib.XCreatePixmapCursor)(self.x.display.display,
|
||||||
|
pixmap,
|
||||||
|
pixmap,
|
||||||
|
&dummy_color as *const _ as *mut _,
|
||||||
|
&dummy_color as *const _ as *mut _, 0, 0);
|
||||||
|
(self.x.display.xlib.XFreePixmap)(self.x.display.display, pixmap);
|
||||||
|
cursor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -772,13 +874,10 @@ impl Window {
|
||||||
},
|
},
|
||||||
Normal => {},
|
Normal => {},
|
||||||
Hide => {
|
Hide => {
|
||||||
|
// NB: Calling XDefineCursor with None (aka 0)
|
||||||
|
// as a value resets the cursor to the default.
|
||||||
unsafe {
|
unsafe {
|
||||||
let xcursor = (self.x.display.xlib.XCreateFontCursor)(self.x.display.display, 68/*XC_left_ptr*/);
|
(self.x.display.xlib.XDefineCursor)(self.x.display.display, self.x.window, 0);
|
||||||
self.x.display.check_errors().expect("Failed to call XCreateFontCursor");
|
|
||||||
(self.x.display.xlib.XDefineCursor)(self.x.display.display, self.x.window, xcursor);
|
|
||||||
self.x.display.check_errors().expect("Failed to call XDefineCursor");
|
|
||||||
(self.x.display.xlib.XFlush)(self.x.display.display);
|
|
||||||
(self.x.display.xlib.XFreeCursor)(self.x.display.display, xcursor);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -787,25 +886,20 @@ impl Window {
|
||||||
match state {
|
match state {
|
||||||
Normal => Ok(()),
|
Normal => Ok(()),
|
||||||
Hide => {
|
Hide => {
|
||||||
let data = &[0, 0, 0, 0, 0, 0, 0, 0];
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut black = ffi::XColor {
|
let cursor = self.create_empty_cursor();
|
||||||
red: 0, green: 0, blue: 0,
|
|
||||||
pad: 0, pixel: 0, flags: 0,
|
|
||||||
};
|
|
||||||
let bitmap = (self.x.display.xlib.XCreateBitmapFromData)(self.x.display.display, self.x.window, data.as_ptr(), 8, 8);
|
|
||||||
let cursor = (self.x.display.xlib.XCreatePixmapCursor)(self.x.display.display, bitmap, bitmap, &mut black, &mut black, 0, 0);
|
|
||||||
(self.x.display.xlib.XDefineCursor)(self.x.display.display, self.x.window, cursor);
|
(self.x.display.xlib.XDefineCursor)(self.x.display.display, self.x.window, cursor);
|
||||||
self.x.display.check_errors().expect("Failed to call XDefineCursor");
|
if cursor != 0 {
|
||||||
(self.x.display.xlib.XFreeCursor)(self.x.display.display, cursor);
|
(self.x.display.xlib.XFreeCursor)(self.x.display.display, cursor);
|
||||||
(self.x.display.xlib.XFreePixmap)(self.x.display.display, bitmap);
|
}
|
||||||
|
self.x.display.check_errors().expect("Failed to call XDefineCursor or free the empty cursor");
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
Grab => {
|
Grab => {
|
||||||
unsafe {
|
unsafe {
|
||||||
match (self.x.display.xlib.XGrabPointer)(
|
match (self.x.display.xlib.XGrabPointer)(
|
||||||
self.x.display.display, self.x.window, ffi::False,
|
self.x.display.display, self.x.window, ffi::True,
|
||||||
(ffi::ButtonPressMask | ffi::ButtonReleaseMask | ffi::EnterWindowMask |
|
(ffi::ButtonPressMask | ffi::ButtonReleaseMask | ffi::EnterWindowMask |
|
||||||
ffi::LeaveWindowMask | ffi::PointerMotionMask | ffi::PointerMotionHintMask |
|
ffi::LeaveWindowMask | ffi::PointerMotionMask | ffi::PointerMotionHintMask |
|
||||||
ffi::Button1MotionMask | ffi::Button2MotionMask | ffi::Button3MotionMask |
|
ffi::Button1MotionMask | ffi::Button2MotionMask | ffi::Button3MotionMask |
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub enum Event {
|
||||||
/// The cursor has moved on the window.
|
/// The cursor has moved on the window.
|
||||||
///
|
///
|
||||||
/// The parameter are the (x,y) coords in pixels relative to the top-left corner of the window.
|
/// The parameter are the (x,y) coords in pixels relative to the top-left corner of the window.
|
||||||
MouseMoved((i32, i32)),
|
MouseMoved(i32, i32),
|
||||||
|
|
||||||
/// A mouse wheel movement or touchpad scroll occurred.
|
/// A mouse wheel movement or touchpad scroll occurred.
|
||||||
MouseWheel(MouseScrollDelta, TouchPhase),
|
MouseWheel(MouseScrollDelta, TouchPhase),
|
||||||
|
@ -220,6 +220,9 @@ pub enum VirtualKeyCode {
|
||||||
/// The space bar.
|
/// The space bar.
|
||||||
Space,
|
Space,
|
||||||
|
|
||||||
|
/// The "Compose" key on Linux.
|
||||||
|
Compose,
|
||||||
|
|
||||||
Numlock,
|
Numlock,
|
||||||
Numpad0,
|
Numpad0,
|
||||||
Numpad1,
|
Numpad1,
|
||||||
|
|
16
src/lib.rs
16
src/lib.rs
|
@ -61,7 +61,7 @@ extern crate x11_dl;
|
||||||
extern crate wayland_client;
|
extern crate wayland_client;
|
||||||
|
|
||||||
pub use events::*;
|
pub use events::*;
|
||||||
pub use window::{WindowBuilder, WindowProxy, PollEventsIterator, WaitEventsIterator};
|
pub use window::{WindowProxy, PollEventsIterator, WaitEventsIterator};
|
||||||
pub use window::{AvailableMonitorsIter, MonitorId, get_available_monitors, get_primary_monitor};
|
pub use window::{AvailableMonitorsIter, MonitorId, get_available_monitors, get_primary_monitor};
|
||||||
pub use native_monitor::NativeMonitorId;
|
pub use native_monitor::NativeMonitorId;
|
||||||
|
|
||||||
|
@ -99,6 +99,16 @@ pub struct Window {
|
||||||
window: platform::Window,
|
window: platform::Window,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Object that allows you to build windows.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct WindowBuilder {
|
||||||
|
/// The attributes to use to create the window.
|
||||||
|
pub window: WindowAttributes,
|
||||||
|
|
||||||
|
/// Platform-specific configuration.
|
||||||
|
platform_specific: platform::PlatformSpecificWindowBuilderAttributes,
|
||||||
|
}
|
||||||
|
|
||||||
/// Error that can happen while creating a window or a headless renderer.
|
/// Error that can happen while creating a window or a headless renderer.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum CreationError {
|
pub enum CreationError {
|
||||||
|
@ -128,7 +138,7 @@ impl std::error::Error for CreationError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
pub enum MouseCursor {
|
pub enum MouseCursor {
|
||||||
/// The platform-dependent default cursor.
|
/// The platform-dependent default cursor.
|
||||||
Default,
|
Default,
|
||||||
|
@ -185,7 +195,7 @@ pub enum MouseCursor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Describes how glutin handles the cursor.
|
/// Describes how glutin handles the cursor.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
pub enum CursorState {
|
pub enum CursorState {
|
||||||
/// Normal cursor behavior.
|
/// Normal cursor behavior.
|
||||||
Normal,
|
Normal,
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#![cfg(target_os = "macos")]
|
#![cfg(target_os = "macos")]
|
||||||
|
|
||||||
|
use std::convert::From;
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
use Window;
|
use cocoa::appkit::NSApplicationActivationPolicy;
|
||||||
|
use {Window, WindowBuilder};
|
||||||
|
|
||||||
/// Additional methods on `Window` that are specific to MacOS.
|
/// Additional methods on `Window` that are specific to MacOS.
|
||||||
pub trait WindowExt {
|
pub trait WindowExt {
|
||||||
|
@ -17,3 +19,47 @@ impl WindowExt for Window {
|
||||||
self.window.platform_window() as *mut c_void
|
self.window.platform_window() as *mut c_void
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Corresponds to `NSApplicationActivationPolicy`.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub enum ActivationPolicy {
|
||||||
|
/// Corresponds to `NSApplicationActivationPolicyRegular`.
|
||||||
|
Regular,
|
||||||
|
/// Corresponds to `NSApplicationActivationPolicyAccessory`.
|
||||||
|
Accessory,
|
||||||
|
/// Corresponds to `NSApplicationActivationPolicyProhibited`.
|
||||||
|
Prohibited,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ActivationPolicy {
|
||||||
|
fn default() -> Self {
|
||||||
|
ActivationPolicy::Regular
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ActivationPolicy> for NSApplicationActivationPolicy {
|
||||||
|
fn from(activation_policy: ActivationPolicy) -> Self {
|
||||||
|
match activation_policy {
|
||||||
|
ActivationPolicy::Regular =>
|
||||||
|
NSApplicationActivationPolicy::NSApplicationActivationPolicyRegular,
|
||||||
|
ActivationPolicy::Accessory =>
|
||||||
|
NSApplicationActivationPolicy::NSApplicationActivationPolicyAccessory,
|
||||||
|
ActivationPolicy::Prohibited =>
|
||||||
|
NSApplicationActivationPolicy::NSApplicationActivationPolicyProhibited,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Additional methods on `WindowBuilder` that are specific to MacOS.
|
||||||
|
pub trait WindowBuilderExt<'a> {
|
||||||
|
fn with_activation_policy(mut self, activation_policy: ActivationPolicy) -> WindowBuilder<'a>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> WindowBuilderExt<'a> for WindowBuilder<'a> {
|
||||||
|
/// Sets the activation policy for the window being built
|
||||||
|
#[inline]
|
||||||
|
fn with_activation_policy(mut self, activation_policy: ActivationPolicy) -> WindowBuilder<'a> {
|
||||||
|
self.platform_specific.activation_policy = activation_policy;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ impl GlContext for HeadlessContext {
|
||||||
unsafe impl Send for HeadlessContext {}
|
unsafe impl Send for HeadlessContext {}
|
||||||
unsafe impl Sync for HeadlessContext {}
|
unsafe impl Sync for HeadlessContext {}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct PlatformSpecificWindowBuilderAttributes;
|
pub struct PlatformSpecificWindowBuilderAttributes;
|
||||||
#[derive(Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct PlatformSpecificHeadlessBuilderAttributes;
|
pub struct PlatformSpecificHeadlessBuilderAttributes;
|
||||||
|
|
|
@ -8,7 +8,7 @@ use ContextError;
|
||||||
|
|
||||||
pub use api::ios::*;
|
pub use api::ios::*;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct PlatformSpecificHeadlessBuilderAttributes;
|
pub struct PlatformSpecificHeadlessBuilderAttributes;
|
||||||
|
|
||||||
pub struct HeadlessContext(i32);
|
pub struct HeadlessContext(i32);
|
||||||
|
|
|
@ -17,7 +17,7 @@ use api::x11::XConnection;
|
||||||
use api::x11::XError;
|
use api::x11::XError;
|
||||||
use api::x11::XNotSupported;
|
use api::x11::XNotSupported;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct PlatformSpecificWindowBuilderAttributes;
|
pub struct PlatformSpecificWindowBuilderAttributes;
|
||||||
|
|
||||||
enum Backend {
|
enum Backend {
|
||||||
|
|
|
@ -9,9 +9,9 @@ use WindowAttributes;
|
||||||
|
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct PlatformSpecificWindowBuilderAttributes;
|
pub struct PlatformSpecificWindowBuilderAttributes;
|
||||||
#[derive(Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct PlatformSpecificHeadlessBuilderAttributes;
|
pub struct PlatformSpecificHeadlessBuilderAttributes;
|
||||||
|
|
||||||
/// The Win32 implementation of the main `Window` object.
|
/// The Win32 implementation of the main `Window` object.
|
||||||
|
|
|
@ -1,26 +1,16 @@
|
||||||
use std::collections::vec_deque::IntoIter as VecDequeIter;
|
use std::collections::vec_deque::IntoIter as VecDequeIter;
|
||||||
use std::default::Default;
|
|
||||||
|
|
||||||
use CreationError;
|
use CreationError;
|
||||||
use CursorState;
|
use CursorState;
|
||||||
use Event;
|
use Event;
|
||||||
use MouseCursor;
|
use MouseCursor;
|
||||||
use Window;
|
use Window;
|
||||||
use WindowAttributes;
|
use WindowBuilder;
|
||||||
use native_monitor::NativeMonitorId;
|
use native_monitor::NativeMonitorId;
|
||||||
|
|
||||||
use libc;
|
use libc;
|
||||||
use platform;
|
use platform;
|
||||||
|
|
||||||
/// Object that allows you to build windows.
|
|
||||||
pub struct WindowBuilder {
|
|
||||||
/// The attributes to use to create the window.
|
|
||||||
pub window: WindowAttributes,
|
|
||||||
|
|
||||||
/// Platform-specific configuration.
|
|
||||||
platform_specific: platform::PlatformSpecificWindowBuilderAttributes,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WindowBuilder {
|
impl WindowBuilder {
|
||||||
/// Initializes a new `WindowBuilder` with default values.
|
/// Initializes a new `WindowBuilder` with default values.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -60,8 +50,8 @@ impl WindowBuilder {
|
||||||
|
|
||||||
/// Requests a specific title for the window.
|
/// Requests a specific title for the window.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_title(mut self, title: String) -> WindowBuilder {
|
pub fn with_title<T: Into<String>>(mut self, title: T) -> WindowBuilder {
|
||||||
self.window.title = title;
|
self.window.title = title.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue