Run cargo fmt on source files (#106)
* Run cargo fmt on source files * Update with rustfmt.toml * Change rustfmt configuration and run it again
This commit is contained in:
parent
9fbfe18f9a
commit
2a894c6bc9
|
@ -1,2 +1,3 @@
|
||||||
fn_args_layout = "Compressed"
|
fn_args_layout = "Compressed"
|
||||||
|
use_small_heuristics = "Max"
|
||||||
use_field_init_shorthand = true
|
use_field_init_shorthand = true
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use rtrb::{RingBuffer, Consumer};
|
use rtrb::{Consumer, RingBuffer};
|
||||||
|
|
||||||
use baseview::{Event, EventStatus, Window, WindowHandler, WindowScalePolicy};
|
use baseview::{Event, EventStatus, Window, WindowHandler, WindowScalePolicy};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum Message {
|
enum Message {
|
||||||
Hello
|
Hello,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OpenWindowExample {
|
struct OpenWindowExample {
|
||||||
|
@ -40,18 +40,13 @@ fn main() {
|
||||||
|
|
||||||
let (mut tx, rx) = RingBuffer::new(128).split();
|
let (mut tx, rx) = RingBuffer::new(128).split();
|
||||||
|
|
||||||
::std::thread::spawn(move || {
|
::std::thread::spawn(move || loop {
|
||||||
loop {
|
::std::thread::sleep(Duration::from_secs(5));
|
||||||
::std::thread::sleep(Duration::from_secs(5));
|
|
||||||
|
|
||||||
if let Err(_) = tx.push(Message::Hello) {
|
if let Err(_) = tx.push(Message::Hello) {
|
||||||
println!("Failed sending message");
|
println!("Failed sending message");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Window::open_blocking(
|
Window::open_blocking(window_open_options, |_| OpenWindowExample { rx });
|
||||||
window_open_options,
|
|
||||||
|_| OpenWindowExample { rx }
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use keyboard_types::KeyboardEvent;
|
use keyboard_types::KeyboardEvent;
|
||||||
|
|
||||||
use crate::{WindowInfo, Point};
|
use crate::{Point, WindowInfo};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum MouseButton {
|
pub enum MouseButton {
|
||||||
|
@ -83,7 +82,6 @@ pub enum Event {
|
||||||
Window(WindowEvent),
|
Window(WindowEvent),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Return value for [WindowHandler::on_event](`crate::WindowHandler::on_event()`),
|
/// Return value for [WindowHandler::on_event](`crate::WindowHandler::on_event()`),
|
||||||
/// indicating whether the event was handled by your window or should be passed
|
/// indicating whether the event was handled by your window or should be passed
|
||||||
/// back to the platform.
|
/// back to the platform.
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
use keyboard_types::{Code, Location};
|
use keyboard_types::{Code, Location};
|
||||||
|
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||||
/// Map key code to location.
|
/// Map key code to location.
|
||||||
///
|
///
|
||||||
|
@ -52,4 +51,4 @@ pub fn code_to_location(code: Code) -> Location {
|
||||||
| Code::NumpadSubtract => Location::Numpad,
|
| Code::NumpadSubtract => Location::Numpad,
|
||||||
_ => Location::Standard,
|
_ => Location::Standard,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
mod macos;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
mod win;
|
mod win;
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
mod x11;
|
mod x11;
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
mod macos;
|
|
||||||
|
|
||||||
mod event;
|
mod event;
|
||||||
mod keyboard;
|
mod keyboard;
|
||||||
|
|
|
@ -19,14 +19,13 @@
|
||||||
//! Conversion of platform keyboard event into cross-platform event.
|
//! Conversion of platform keyboard event into cross-platform event.
|
||||||
|
|
||||||
use cocoa::appkit::{NSEvent, NSEventModifierFlags, NSEventType};
|
use cocoa::appkit::{NSEvent, NSEventModifierFlags, NSEventType};
|
||||||
use cocoa::foundation::NSString;
|
|
||||||
use cocoa::base::id;
|
use cocoa::base::id;
|
||||||
use keyboard_types::{Code, KeyState, Key, KeyboardEvent, Modifiers};
|
use cocoa::foundation::NSString;
|
||||||
|
use keyboard_types::{Code, Key, KeyState, KeyboardEvent, Modifiers};
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, sel, sel_impl};
|
||||||
|
|
||||||
use crate::keyboard::code_to_location;
|
use crate::keyboard::code_to_location;
|
||||||
|
|
||||||
|
|
||||||
pub(crate) fn from_nsstring(s: id) -> String {
|
pub(crate) fn from_nsstring(s: id) -> String {
|
||||||
unsafe {
|
unsafe {
|
||||||
let slice = std::slice::from_raw_parts(s.UTF8String() as *const _, s.len());
|
let slice = std::slice::from_raw_parts(s.UTF8String() as *const _, s.len());
|
||||||
|
@ -245,7 +244,6 @@ fn code_to_key(code: Code) -> Option<Key> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn is_valid_key(s: &str) -> bool {
|
fn is_valid_key(s: &str) -> bool {
|
||||||
match s.chars().next() {
|
match s.chars().next() {
|
||||||
None => false,
|
None => false,
|
||||||
|
@ -253,7 +251,6 @@ fn is_valid_key(s: &str) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn is_modifier_code(code: Code) -> bool {
|
fn is_modifier_code(code: Code) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
code,
|
code,
|
||||||
|
@ -270,7 +267,6 @@ fn is_modifier_code(code: Code) -> bool {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl KeyboardState {
|
impl KeyboardState {
|
||||||
pub(crate) fn new() -> KeyboardState {
|
pub(crate) fn new() -> KeyboardState {
|
||||||
let last_mods = NSEventModifierFlags::empty();
|
let last_mods = NSEventModifierFlags::empty();
|
||||||
|
@ -329,33 +325,21 @@ impl KeyboardState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let event = KeyboardEvent {
|
let event =
|
||||||
code,
|
KeyboardEvent { code, key, location, modifiers, state, is_composing, repeat };
|
||||||
key,
|
|
||||||
location,
|
|
||||||
modifiers,
|
|
||||||
state,
|
|
||||||
is_composing,
|
|
||||||
repeat,
|
|
||||||
};
|
|
||||||
Some(event)
|
Some(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const MODIFIER_MAP: &[(NSEventModifierFlags, Modifiers)] = &[
|
const MODIFIER_MAP: &[(NSEventModifierFlags, Modifiers)] = &[
|
||||||
(NSEventModifierFlags::NSShiftKeyMask, Modifiers::SHIFT),
|
(NSEventModifierFlags::NSShiftKeyMask, Modifiers::SHIFT),
|
||||||
(NSEventModifierFlags::NSAlternateKeyMask, Modifiers::ALT),
|
(NSEventModifierFlags::NSAlternateKeyMask, Modifiers::ALT),
|
||||||
(NSEventModifierFlags::NSControlKeyMask, Modifiers::CONTROL),
|
(NSEventModifierFlags::NSControlKeyMask, Modifiers::CONTROL),
|
||||||
(NSEventModifierFlags::NSCommandKeyMask, Modifiers::META),
|
(NSEventModifierFlags::NSCommandKeyMask, Modifiers::META),
|
||||||
(
|
(NSEventModifierFlags::NSAlphaShiftKeyMask, Modifiers::CAPS_LOCK),
|
||||||
NSEventModifierFlags::NSAlphaShiftKeyMask,
|
|
||||||
Modifiers::CAPS_LOCK,
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
pub(crate) fn make_modifiers(raw: NSEventModifierFlags) -> Modifiers {
|
pub(crate) fn make_modifiers(raw: NSEventModifierFlags) -> Modifiers {
|
||||||
let mut modifiers = Modifiers::empty();
|
let mut modifiers = Modifiers::empty();
|
||||||
for &(flags, mods) in MODIFIER_MAP {
|
for &(flags, mods) in MODIFIER_MAP {
|
||||||
|
@ -364,4 +348,4 @@ pub(crate) fn make_modifiers(raw: NSEventModifierFlags) -> Modifiers {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
modifiers
|
modifiers
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mod keyboard;
|
mod keyboard;
|
||||||
mod window;
|
|
||||||
mod view;
|
mod view;
|
||||||
|
mod window;
|
||||||
|
|
||||||
pub use window::*;
|
pub use window::*;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
|
|
||||||
use cocoa::appkit::{NSEvent, NSView, NSWindow};
|
use cocoa::appkit::{NSEvent, NSView, NSWindow};
|
||||||
use cocoa::base::{id, nil, BOOL, YES, NO};
|
use cocoa::base::{id, nil, BOOL, NO, YES};
|
||||||
use cocoa::foundation::{NSArray, NSPoint, NSRect, NSSize};
|
use cocoa::foundation::{NSArray, NSPoint, NSRect, NSSize};
|
||||||
|
|
||||||
use objc::{
|
use objc::{
|
||||||
|
@ -13,16 +13,17 @@ use objc::{
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{Event, EventStatus, MouseButton, MouseEvent, Point, Size, WindowEvent, WindowInfo, WindowOpenOptions};
|
|
||||||
use crate::MouseEvent::{ButtonPressed, ButtonReleased};
|
use crate::MouseEvent::{ButtonPressed, ButtonReleased};
|
||||||
|
use crate::{
|
||||||
|
Event, EventStatus, MouseButton, MouseEvent, Point, Size, WindowEvent, WindowInfo,
|
||||||
|
WindowOpenOptions,
|
||||||
|
};
|
||||||
|
|
||||||
use super::window::WindowState;
|
use super::window::WindowState;
|
||||||
|
|
||||||
|
|
||||||
/// Name of the field used to store the `WindowState` pointer.
|
/// Name of the field used to store the `WindowState` pointer.
|
||||||
pub(super) const BASEVIEW_STATE_IVAR: &str = "baseview_state";
|
pub(super) const BASEVIEW_STATE_IVAR: &str = "baseview_state";
|
||||||
|
|
||||||
|
|
||||||
macro_rules! add_simple_mouse_class_method {
|
macro_rules! add_simple_mouse_class_method {
|
||||||
($class:ident, $sel:ident, $event:expr) => {
|
($class:ident, $sel:ident, $event:expr) => {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
|
@ -41,7 +42,6 @@ macro_rules! add_simple_mouse_class_method {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
macro_rules! add_simple_keyboard_class_method {
|
macro_rules! add_simple_keyboard_class_method {
|
||||||
($class:ident, $sel:ident) => {
|
($class:ident, $sel:ident) => {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
|
@ -70,25 +70,18 @@ macro_rules! add_simple_keyboard_class_method {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) unsafe fn create_view(window_options: &WindowOpenOptions) -> id {
|
||||||
pub(super) unsafe fn create_view(
|
|
||||||
window_options: &WindowOpenOptions,
|
|
||||||
) -> id {
|
|
||||||
let class = create_view_class();
|
let class = create_view_class();
|
||||||
|
|
||||||
let view: id = msg_send![class, alloc];
|
let view: id = msg_send![class, alloc];
|
||||||
|
|
||||||
let size = window_options.size;
|
let size = window_options.size;
|
||||||
|
|
||||||
view.initWithFrame_(NSRect::new(
|
view.initWithFrame_(NSRect::new(NSPoint::new(0., 0.), NSSize::new(size.width, size.height)));
|
||||||
NSPoint::new(0., 0.),
|
|
||||||
NSSize::new(size.width, size.height),
|
|
||||||
));
|
|
||||||
|
|
||||||
view
|
view
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsafe fn create_view_class() -> &'static Class {
|
unsafe fn create_view_class() -> &'static Class {
|
||||||
// Use unique class names so that there are no conflicts between different
|
// Use unique class names so that there are no conflicts between different
|
||||||
// instances. The class is deleted when the view is released. Previously,
|
// instances. The class is deleted when the view is released. Previously,
|
||||||
|
@ -100,102 +93,47 @@ unsafe fn create_view_class() -> &'static Class {
|
||||||
|
|
||||||
class.add_method(
|
class.add_method(
|
||||||
sel!(acceptsFirstResponder),
|
sel!(acceptsFirstResponder),
|
||||||
property_yes as extern "C" fn(&Object, Sel) -> BOOL
|
property_yes as extern "C" fn(&Object, Sel) -> BOOL,
|
||||||
);
|
|
||||||
class.add_method(
|
|
||||||
sel!(isFlipped),
|
|
||||||
property_yes as extern "C" fn(&Object, Sel) -> BOOL
|
|
||||||
);
|
);
|
||||||
|
class.add_method(sel!(isFlipped), property_yes as extern "C" fn(&Object, Sel) -> BOOL);
|
||||||
class.add_method(
|
class.add_method(
|
||||||
sel!(preservesContentInLiveResize),
|
sel!(preservesContentInLiveResize),
|
||||||
property_no as extern "C" fn(&Object, Sel) -> BOOL
|
property_no as extern "C" fn(&Object, Sel) -> BOOL,
|
||||||
);
|
);
|
||||||
class.add_method(
|
class.add_method(
|
||||||
sel!(acceptsFirstMouse:),
|
sel!(acceptsFirstMouse:),
|
||||||
accepts_first_mouse as extern "C" fn(&Object, Sel, id) -> BOOL
|
accepts_first_mouse as extern "C" fn(&Object, Sel, id) -> BOOL,
|
||||||
);
|
);
|
||||||
|
|
||||||
class.add_method(
|
class.add_method(sel!(release), release as extern "C" fn(&mut Object, Sel));
|
||||||
sel!(release),
|
class.add_method(sel!(dealloc), dealloc as extern "C" fn(&mut Object, Sel));
|
||||||
release as extern "C" fn(&mut Object, Sel)
|
|
||||||
);
|
|
||||||
class.add_method(
|
|
||||||
sel!(dealloc),
|
|
||||||
dealloc as extern "C" fn(&mut Object, Sel)
|
|
||||||
);
|
|
||||||
class.add_method(
|
class.add_method(
|
||||||
sel!(viewWillMoveToWindow:),
|
sel!(viewWillMoveToWindow:),
|
||||||
view_will_move_to_window as extern "C" fn(&Object, Sel, id)
|
view_will_move_to_window as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
class.add_method(
|
class.add_method(
|
||||||
sel!(updateTrackingAreas:),
|
sel!(updateTrackingAreas:),
|
||||||
update_tracking_areas as extern "C" fn(&Object, Sel, id)
|
update_tracking_areas as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
|
|
||||||
class.add_method(
|
class.add_method(sel!(mouseMoved:), mouse_moved as extern "C" fn(&Object, Sel, id));
|
||||||
sel!(mouseMoved:),
|
class.add_method(sel!(mouseDragged:), mouse_moved as extern "C" fn(&Object, Sel, id));
|
||||||
mouse_moved as extern "C" fn(&Object, Sel, id),
|
class.add_method(sel!(rightMouseDragged:), mouse_moved as extern "C" fn(&Object, Sel, id));
|
||||||
);
|
class.add_method(sel!(otherMouseDragged:), mouse_moved as extern "C" fn(&Object, Sel, id));
|
||||||
class.add_method(
|
|
||||||
sel!(mouseDragged:),
|
|
||||||
mouse_moved as extern "C" fn(&Object, Sel, id),
|
|
||||||
);
|
|
||||||
class.add_method(
|
|
||||||
sel!(rightMouseDragged:),
|
|
||||||
mouse_moved as extern "C" fn(&Object, Sel, id),
|
|
||||||
);
|
|
||||||
class.add_method(
|
|
||||||
sel!(otherMouseDragged:),
|
|
||||||
mouse_moved as extern "C" fn(&Object, Sel, id),
|
|
||||||
);
|
|
||||||
|
|
||||||
class.add_method(
|
class.add_method(
|
||||||
sel!(viewDidChangeBackingProperties:),
|
sel!(viewDidChangeBackingProperties:),
|
||||||
view_did_change_backing_properties as extern "C" fn(&Object, Sel, id),
|
view_did_change_backing_properties as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
add_simple_mouse_class_method!(class, mouseDown, ButtonPressed(MouseButton::Left));
|
||||||
|
add_simple_mouse_class_method!(class, mouseUp, ButtonReleased(MouseButton::Left));
|
||||||
add_simple_mouse_class_method!(
|
add_simple_mouse_class_method!(class, rightMouseDown, ButtonPressed(MouseButton::Right));
|
||||||
class,
|
add_simple_mouse_class_method!(class, rightMouseUp, ButtonReleased(MouseButton::Right));
|
||||||
mouseDown,
|
add_simple_mouse_class_method!(class, otherMouseDown, ButtonPressed(MouseButton::Middle));
|
||||||
ButtonPressed(MouseButton::Left)
|
add_simple_mouse_class_method!(class, otherMouseUp, ButtonReleased(MouseButton::Middle));
|
||||||
);
|
add_simple_mouse_class_method!(class, mouseEntered, MouseEvent::CursorEntered);
|
||||||
add_simple_mouse_class_method!(
|
add_simple_mouse_class_method!(class, mouseExited, MouseEvent::CursorLeft);
|
||||||
class,
|
|
||||||
mouseUp,
|
|
||||||
ButtonReleased(MouseButton::Left)
|
|
||||||
);
|
|
||||||
add_simple_mouse_class_method!(
|
|
||||||
class,
|
|
||||||
rightMouseDown,
|
|
||||||
ButtonPressed(MouseButton::Right)
|
|
||||||
);
|
|
||||||
add_simple_mouse_class_method!(
|
|
||||||
class,
|
|
||||||
rightMouseUp,
|
|
||||||
ButtonReleased(MouseButton::Right)
|
|
||||||
);
|
|
||||||
add_simple_mouse_class_method!(
|
|
||||||
class,
|
|
||||||
otherMouseDown,
|
|
||||||
ButtonPressed(MouseButton::Middle)
|
|
||||||
);
|
|
||||||
add_simple_mouse_class_method!(
|
|
||||||
class,
|
|
||||||
otherMouseUp,
|
|
||||||
ButtonReleased(MouseButton::Middle)
|
|
||||||
);
|
|
||||||
add_simple_mouse_class_method!(
|
|
||||||
class,
|
|
||||||
mouseEntered,
|
|
||||||
MouseEvent::CursorEntered
|
|
||||||
);
|
|
||||||
add_simple_mouse_class_method!(
|
|
||||||
class,
|
|
||||||
mouseExited,
|
|
||||||
MouseEvent::CursorLeft
|
|
||||||
);
|
|
||||||
|
|
||||||
add_simple_keyboard_class_method!(class, keyDown);
|
add_simple_keyboard_class_method!(class, keyDown);
|
||||||
add_simple_keyboard_class_method!(class, keyUp);
|
add_simple_keyboard_class_method!(class, keyUp);
|
||||||
|
@ -206,32 +144,18 @@ unsafe fn create_view_class() -> &'static Class {
|
||||||
class.register()
|
class.register()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn property_yes(_this: &Object, _sel: Sel) -> BOOL {
|
||||||
extern "C" fn property_yes(
|
|
||||||
_this: &Object,
|
|
||||||
_sel: Sel,
|
|
||||||
) -> BOOL {
|
|
||||||
YES
|
YES
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn property_no(_this: &Object, _sel: Sel) -> BOOL {
|
||||||
extern "C" fn property_no(
|
|
||||||
_this: &Object,
|
|
||||||
_sel: Sel,
|
|
||||||
) -> BOOL {
|
|
||||||
NO
|
NO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn accepts_first_mouse(_this: &Object, _sel: Sel, _event: id) -> BOOL {
|
||||||
extern "C" fn accepts_first_mouse(
|
|
||||||
_this: &Object,
|
|
||||||
_sel: Sel,
|
|
||||||
_event: id
|
|
||||||
) -> BOOL {
|
|
||||||
YES
|
YES
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" fn release(this: &mut Object, _sel: Sel) {
|
extern "C" fn release(this: &mut Object, _sel: Sel) {
|
||||||
// Hack for breaking circular references. We store the value of retainCount
|
// Hack for breaking circular references. We store the value of retainCount
|
||||||
// after build(), and then when retainCount drops back to that value, we
|
// after build(), and then when retainCount drops back to that value, we
|
||||||
|
@ -250,23 +174,18 @@ extern "C" fn release(this: &mut Object, _sel: Sel) {
|
||||||
|
|
||||||
let state_ptr: *mut c_void = *this.get_ivar(BASEVIEW_STATE_IVAR);
|
let state_ptr: *mut c_void = *this.get_ivar(BASEVIEW_STATE_IVAR);
|
||||||
|
|
||||||
if !state_ptr.is_null(){
|
if !state_ptr.is_null() {
|
||||||
let retain_count_after_build = WindowState::from_field(this)
|
let retain_count_after_build = WindowState::from_field(this).retain_count_after_build;
|
||||||
.retain_count_after_build;
|
|
||||||
|
|
||||||
if retain_count <= retain_count_after_build {
|
if retain_count <= retain_count_after_build {
|
||||||
WindowState::from_field(this).remove_timer();
|
WindowState::from_field(this).remove_timer();
|
||||||
|
|
||||||
this.set_ivar(
|
this.set_ivar(BASEVIEW_STATE_IVAR, ::std::ptr::null() as *const c_void);
|
||||||
BASEVIEW_STATE_IVAR,
|
|
||||||
::std::ptr::null() as *const c_void
|
|
||||||
);
|
|
||||||
|
|
||||||
// Drop WindowState
|
// Drop WindowState
|
||||||
Box::from_raw(state_ptr as *mut WindowState);
|
Box::from_raw(state_ptr as *mut WindowState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -287,39 +206,33 @@ extern "C" fn dealloc(this: &mut Object, _sel: Sel) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn view_did_change_backing_properties(this: &Object, _:Sel, _:id) {
|
extern "C" fn view_did_change_backing_properties(this: &Object, _: Sel, _: id) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ns_window: *mut Object = msg_send![this, window];
|
let ns_window: *mut Object = msg_send![this, window];
|
||||||
|
|
||||||
let scale_factor: f64 = if ns_window.is_null() {
|
let scale_factor: f64 =
|
||||||
1.0
|
if ns_window.is_null() { 1.0 } else { NSWindow::backingScaleFactor(ns_window) as f64 };
|
||||||
} else {
|
|
||||||
NSWindow::backingScaleFactor(ns_window) as f64
|
|
||||||
};
|
|
||||||
|
|
||||||
let state: &mut WindowState = WindowState::from_field(this);
|
let state: &mut WindowState = WindowState::from_field(this);
|
||||||
|
|
||||||
let bounds: NSRect = msg_send![this, bounds];
|
let bounds: NSRect = msg_send![this, bounds];
|
||||||
|
|
||||||
let window_info = WindowInfo::from_logical_size(
|
let window_info = WindowInfo::from_logical_size(
|
||||||
Size::new(bounds.size.width, bounds.size.height),
|
Size::new(bounds.size.width, bounds.size.height),
|
||||||
scale_factor
|
scale_factor,
|
||||||
);
|
|
||||||
|
|
||||||
state.trigger_event(
|
|
||||||
Event::Window(WindowEvent::Resized(window_info))
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
state.trigger_event(Event::Window(WindowEvent::Resized(window_info)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Init/reinit tracking area
|
/// Init/reinit tracking area
|
||||||
///
|
///
|
||||||
/// Info:
|
/// Info:
|
||||||
/// https://developer.apple.com/documentation/appkit/nstrackingarea
|
/// https://developer.apple.com/documentation/appkit/nstrackingarea
|
||||||
/// https://developer.apple.com/documentation/appkit/nstrackingarea/options
|
/// https://developer.apple.com/documentation/appkit/nstrackingarea/options
|
||||||
/// https://developer.apple.com/documentation/appkit/nstrackingareaoptions
|
/// https://developer.apple.com/documentation/appkit/nstrackingareaoptions
|
||||||
unsafe fn reinit_tracking_area(this: &Object, tracking_area: *mut Object){
|
unsafe fn reinit_tracking_area(this: &Object, tracking_area: *mut Object) {
|
||||||
let options: usize = {
|
let options: usize = {
|
||||||
let mouse_entered_and_exited = 0x01;
|
let mouse_entered_and_exited = 0x01;
|
||||||
let tracking_mouse_moved = 0x02;
|
let tracking_mouse_moved = 0x02;
|
||||||
|
@ -328,9 +241,12 @@ unsafe fn reinit_tracking_area(this: &Object, tracking_area: *mut Object){
|
||||||
let tracking_in_visible_rect = 0x200;
|
let tracking_in_visible_rect = 0x200;
|
||||||
let tracking_enabled_during_mouse_drag = 0x400;
|
let tracking_enabled_during_mouse_drag = 0x400;
|
||||||
|
|
||||||
mouse_entered_and_exited | tracking_mouse_moved |
|
mouse_entered_and_exited
|
||||||
tracking_cursor_update | tracking_active_in_active_app |
|
| tracking_mouse_moved
|
||||||
tracking_in_visible_rect | tracking_enabled_during_mouse_drag
|
| tracking_cursor_update
|
||||||
|
| tracking_active_in_active_app
|
||||||
|
| tracking_in_visible_rect
|
||||||
|
| tracking_enabled_during_mouse_drag
|
||||||
};
|
};
|
||||||
|
|
||||||
let bounds: NSRect = msg_send![this, bounds];
|
let bounds: NSRect = msg_send![this, bounds];
|
||||||
|
@ -343,27 +259,20 @@ unsafe fn reinit_tracking_area(this: &Object, tracking_area: *mut Object){
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn view_will_move_to_window(this: &Object, _self: Sel, new_window: id) {
|
||||||
extern "C" fn view_will_move_to_window(
|
|
||||||
this: &Object,
|
|
||||||
_self: Sel,
|
|
||||||
new_window: id
|
|
||||||
){
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let tracking_areas: *mut Object = msg_send![this, trackingAreas];
|
let tracking_areas: *mut Object = msg_send![this, trackingAreas];
|
||||||
let tracking_area_count = NSArray::count(tracking_areas);
|
let tracking_area_count = NSArray::count(tracking_areas);
|
||||||
|
|
||||||
let _: () = msg_send![class!(NSEvent), setMouseCoalescingEnabled:NO];
|
let _: () = msg_send![class!(NSEvent), setMouseCoalescingEnabled: NO];
|
||||||
|
|
||||||
if new_window == nil {
|
if new_window == nil {
|
||||||
if tracking_area_count != 0 {
|
if tracking_area_count != 0 {
|
||||||
let tracking_area = NSArray::objectAtIndex(tracking_areas, 0);
|
let tracking_area = NSArray::objectAtIndex(tracking_areas, 0);
|
||||||
|
|
||||||
|
let _: () = msg_send![this, removeTrackingArea: tracking_area];
|
||||||
let _: () = msg_send![this, removeTrackingArea:tracking_area];
|
|
||||||
let _: () = msg_send![tracking_area, release];
|
let _: () = msg_send![tracking_area, release];
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if tracking_area_count == 0 {
|
if tracking_area_count == 0 {
|
||||||
let class = Class::get("NSTrackingArea").unwrap();
|
let class = Class::get("NSTrackingArea").unwrap();
|
||||||
|
@ -372,27 +281,22 @@ extern "C" fn view_will_move_to_window(
|
||||||
|
|
||||||
reinit_tracking_area(this, tracking_area);
|
reinit_tracking_area(this, tracking_area);
|
||||||
|
|
||||||
let _: () = msg_send![this, addTrackingArea:tracking_area];
|
let _: () = msg_send![this, addTrackingArea: tracking_area];
|
||||||
}
|
}
|
||||||
|
|
||||||
let _: () = msg_send![new_window, setAcceptsMouseMovedEvents:YES];
|
let _: () = msg_send![new_window, setAcceptsMouseMovedEvents: YES];
|
||||||
let _: () = msg_send![new_window, makeFirstResponder:this];
|
let _: () = msg_send![new_window, makeFirstResponder: this];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let superclass = msg_send![this, superclass];
|
let superclass = msg_send![this, superclass];
|
||||||
|
|
||||||
let () = msg_send![super(this, superclass), viewWillMoveToWindow:new_window];
|
let () = msg_send![super(this, superclass), viewWillMoveToWindow: new_window];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn update_tracking_areas(this: &Object, _self: Sel, _: id) {
|
||||||
extern "C" fn update_tracking_areas(
|
|
||||||
this: &Object,
|
|
||||||
_self: Sel,
|
|
||||||
_: id
|
|
||||||
){
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let tracking_areas: *mut Object = msg_send![this, trackingAreas];
|
let tracking_areas: *mut Object = msg_send![this, trackingAreas];
|
||||||
let tracking_area = NSArray::objectAtIndex(tracking_areas, 0);
|
let tracking_area = NSArray::objectAtIndex(tracking_areas, 0);
|
||||||
|
@ -401,15 +305,8 @@ extern "C" fn update_tracking_areas(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn mouse_moved(this: &Object, _sel: Sel, event: id) {
|
||||||
extern "C" fn mouse_moved(
|
let state: &mut WindowState = unsafe { WindowState::from_field(this) };
|
||||||
this: &Object,
|
|
||||||
_sel: Sel,
|
|
||||||
event: id
|
|
||||||
){
|
|
||||||
let state: &mut WindowState = unsafe {
|
|
||||||
WindowState::from_field(this)
|
|
||||||
};
|
|
||||||
|
|
||||||
let point: NSPoint = unsafe {
|
let point: NSPoint = unsafe {
|
||||||
let point = NSEvent::locationInWindow(event);
|
let point = NSEvent::locationInWindow(event);
|
||||||
|
@ -417,12 +314,7 @@ extern "C" fn mouse_moved(
|
||||||
msg_send![this, convertPoint:point fromView:nil]
|
msg_send![this, convertPoint:point fromView:nil]
|
||||||
};
|
};
|
||||||
|
|
||||||
let position = Point {
|
let position = Point { x: point.x, y: point.y };
|
||||||
x: point.x,
|
|
||||||
y: point.y
|
|
||||||
};
|
|
||||||
|
|
||||||
state.trigger_event(
|
state.trigger_event(Event::Mouse(MouseEvent::CursorMoved { position }));
|
||||||
Event::Mouse(MouseEvent::CursorMoved { position })
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
|
|
||||||
use cocoa::appkit::{
|
use cocoa::appkit::{
|
||||||
NSApp, NSApplication, NSApplicationActivationPolicyRegular,
|
NSApp, NSApplication, NSApplicationActivationPolicyRegular, NSBackingStoreBuffered, NSWindow,
|
||||||
NSBackingStoreBuffered, NSWindow, NSWindowStyleMask,
|
NSWindowStyleMask,
|
||||||
};
|
};
|
||||||
use cocoa::base::{id, nil, NO};
|
use cocoa::base::{id, nil, NO};
|
||||||
use cocoa::foundation::{NSAutoreleasePool, NSPoint, NSRect, NSSize, NSString};
|
use cocoa::foundation::{NSAutoreleasePool, NSPoint, NSRect, NSSize, NSString};
|
||||||
use core_foundation::runloop::{
|
use core_foundation::runloop::{
|
||||||
CFRunLoop, CFRunLoopTimer, CFRunLoopTimerContext, __CFRunLoopTimer,
|
CFRunLoop, CFRunLoopTimer, CFRunLoopTimerContext, __CFRunLoopTimer, kCFRunLoopDefaultMode,
|
||||||
kCFRunLoopDefaultMode,
|
|
||||||
};
|
};
|
||||||
use keyboard_types::KeyboardEvent;
|
use keyboard_types::KeyboardEvent;
|
||||||
|
|
||||||
|
@ -16,14 +15,10 @@ use objc::{msg_send, runtime::Object, sel, sel_impl};
|
||||||
|
|
||||||
use raw_window_handle::{macos::MacOSHandle, HasRawWindowHandle, RawWindowHandle};
|
use raw_window_handle::{macos::MacOSHandle, HasRawWindowHandle, RawWindowHandle};
|
||||||
|
|
||||||
use crate::{
|
use crate::{Event, EventStatus, WindowHandler, WindowInfo, WindowOpenOptions, WindowScalePolicy};
|
||||||
Event, EventStatus, WindowHandler, WindowOpenOptions, WindowScalePolicy,
|
|
||||||
WindowInfo,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::view::{create_view, BASEVIEW_STATE_IVAR};
|
|
||||||
use super::keyboard::KeyboardState;
|
use super::keyboard::KeyboardState;
|
||||||
|
use super::view::{create_view, BASEVIEW_STATE_IVAR};
|
||||||
|
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
/// Only set if we created the parent window, i.e. we are running in
|
/// Only set if we created the parent window, i.e. we are running in
|
||||||
|
@ -51,10 +46,7 @@ impl Window {
|
||||||
|
|
||||||
let ns_view = unsafe { create_view(&options) };
|
let ns_view = unsafe { create_view(&options) };
|
||||||
|
|
||||||
let window = Window {
|
let window = Window { ns_window: None, ns_view };
|
||||||
ns_window: None,
|
|
||||||
ns_view,
|
|
||||||
};
|
|
||||||
|
|
||||||
Self::init(window, build);
|
Self::init(window, build);
|
||||||
|
|
||||||
|
@ -76,10 +68,7 @@ impl Window {
|
||||||
|
|
||||||
let ns_view = unsafe { create_view(&options) };
|
let ns_view = unsafe { create_view(&options) };
|
||||||
|
|
||||||
let window = Window {
|
let window = Window { ns_window: None, ns_view };
|
||||||
ns_window: None,
|
|
||||||
ns_view,
|
|
||||||
};
|
|
||||||
|
|
||||||
let raw_window_handle = window.raw_window_handle();
|
let raw_window_handle = window.raw_window_handle();
|
||||||
|
|
||||||
|
@ -108,42 +97,34 @@ impl Window {
|
||||||
let app = unsafe { NSApp() };
|
let app = unsafe { NSApp() };
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
app.setActivationPolicy_(
|
app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
|
||||||
NSApplicationActivationPolicyRegular
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let scaling = match options.scale {
|
let scaling = match options.scale {
|
||||||
WindowScalePolicy::ScaleFactor(scale) => scale,
|
WindowScalePolicy::ScaleFactor(scale) => scale,
|
||||||
WindowScalePolicy::SystemScaleFactor => 1.0,
|
WindowScalePolicy::SystemScaleFactor => 1.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let window_info = WindowInfo::from_logical_size(
|
let window_info = WindowInfo::from_logical_size(options.size, scaling);
|
||||||
options.size,
|
|
||||||
scaling
|
|
||||||
);
|
|
||||||
|
|
||||||
let rect = NSRect::new(
|
let rect = NSRect::new(
|
||||||
NSPoint::new(0.0, 0.0),
|
NSPoint::new(0.0, 0.0),
|
||||||
NSSize::new(
|
NSSize::new(
|
||||||
window_info.logical_size().width as f64,
|
window_info.logical_size().width as f64,
|
||||||
window_info.logical_size().height as f64
|
window_info.logical_size().height as f64,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
let ns_window = unsafe {
|
let ns_window = unsafe {
|
||||||
let ns_window = NSWindow::alloc(nil)
|
let ns_window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
|
||||||
.initWithContentRect_styleMask_backing_defer_(
|
rect,
|
||||||
rect,
|
NSWindowStyleMask::NSTitledWindowMask,
|
||||||
NSWindowStyleMask::NSTitledWindowMask,
|
NSBackingStoreBuffered,
|
||||||
NSBackingStoreBuffered,
|
NO,
|
||||||
NO,
|
);
|
||||||
);
|
|
||||||
ns_window.center();
|
ns_window.center();
|
||||||
|
|
||||||
let title = NSString::alloc(nil)
|
let title = NSString::alloc(nil).init_str(&options.title).autorelease();
|
||||||
.init_str(&options.title)
|
|
||||||
.autorelease();
|
|
||||||
ns_window.setTitle_(title);
|
ns_window.setTitle_(title);
|
||||||
|
|
||||||
ns_window.makeKeyAndOrderFront_(nil);
|
ns_window.makeKeyAndOrderFront_(nil);
|
||||||
|
@ -153,10 +134,7 @@ impl Window {
|
||||||
|
|
||||||
let ns_view = unsafe { create_view(&options) };
|
let ns_view = unsafe { create_view(&options) };
|
||||||
|
|
||||||
let window = Window {
|
let window = Window { ns_window: Some(ns_window), ns_view };
|
||||||
ns_window: Some(ns_window),
|
|
||||||
ns_view,
|
|
||||||
};
|
|
||||||
|
|
||||||
Self::init(window, build);
|
Self::init(window, build);
|
||||||
|
|
||||||
|
@ -170,19 +148,15 @@ impl Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init<H, B>(
|
fn init<H, B>(mut window: Window, build: B)
|
||||||
mut window: Window,
|
where
|
||||||
build: B
|
H: WindowHandler + 'static,
|
||||||
)
|
B: FnOnce(&mut crate::Window) -> H,
|
||||||
where H: WindowHandler + 'static,
|
B: Send + 'static,
|
||||||
B: FnOnce(&mut crate::Window) -> H,
|
|
||||||
B: Send + 'static,
|
|
||||||
{
|
{
|
||||||
let window_handler = Box::new(build(&mut crate::Window::new(&mut window)));
|
let window_handler = Box::new(build(&mut crate::Window::new(&mut window)));
|
||||||
|
|
||||||
let retain_count_after_build: usize = unsafe {
|
let retain_count_after_build: usize = unsafe { msg_send![window.ns_view, retainCount] };
|
||||||
msg_send![window.ns_view, retainCount]
|
|
||||||
};
|
|
||||||
|
|
||||||
let window_state_ptr = Box::into_raw(Box::new(WindowState {
|
let window_state_ptr = Box::into_raw(Box::new(WindowState {
|
||||||
window,
|
window,
|
||||||
|
@ -193,17 +167,14 @@ impl Window {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
(*(*window_state_ptr).window.ns_view).set_ivar(
|
(*(*window_state_ptr).window.ns_view)
|
||||||
BASEVIEW_STATE_IVAR,
|
.set_ivar(BASEVIEW_STATE_IVAR, window_state_ptr as *mut c_void);
|
||||||
window_state_ptr as *mut c_void
|
|
||||||
);
|
|
||||||
|
|
||||||
WindowState::setup_timer(window_state_ptr);
|
WindowState::setup_timer(window_state_ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub(super) struct WindowState {
|
pub(super) struct WindowState {
|
||||||
window: Window,
|
window: Window,
|
||||||
window_handler: Box<dyn WindowHandler>,
|
window_handler: Box<dyn WindowHandler>,
|
||||||
|
@ -212,7 +183,6 @@ pub(super) struct WindowState {
|
||||||
pub retain_count_after_build: usize,
|
pub retain_count_after_build: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl WindowState {
|
impl WindowState {
|
||||||
/// Returns a mutable reference to a WindowState from an Objective-C field
|
/// Returns a mutable reference to a WindowState from an Objective-C field
|
||||||
///
|
///
|
||||||
|
@ -226,32 +196,22 @@ impl WindowState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn trigger_event(&mut self, event: Event) -> EventStatus {
|
pub(super) fn trigger_event(&mut self, event: Event) -> EventStatus {
|
||||||
self.window_handler
|
self.window_handler.on_event(&mut crate::Window::new(&mut self.window), event)
|
||||||
.on_event(&mut crate::Window::new(&mut self.window), event)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn trigger_frame(&mut self) {
|
pub(super) fn trigger_frame(&mut self) {
|
||||||
self.window_handler
|
self.window_handler.on_frame(&mut crate::Window::new(&mut self.window));
|
||||||
.on_frame(&mut crate::Window::new(&mut self.window));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn process_native_key_event(
|
pub(super) fn process_native_key_event(&mut self, event: *mut Object) -> Option<KeyboardEvent> {
|
||||||
&mut self,
|
|
||||||
event: *mut Object
|
|
||||||
) -> Option<KeyboardEvent> {
|
|
||||||
self.keyboard_state.process_native_event(event)
|
self.keyboard_state.process_native_event(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Don't call until WindowState pointer is stored in view
|
/// Don't call until WindowState pointer is stored in view
|
||||||
unsafe fn setup_timer(window_state_ptr: *mut WindowState) {
|
unsafe fn setup_timer(window_state_ptr: *mut WindowState) {
|
||||||
extern "C" fn timer_callback(
|
extern "C" fn timer_callback(_: *mut __CFRunLoopTimer, window_state_ptr: *mut c_void) {
|
||||||
_: *mut __CFRunLoopTimer,
|
|
||||||
window_state_ptr: *mut c_void,
|
|
||||||
) {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let window_state = &mut *(
|
let window_state = &mut *(window_state_ptr as *mut WindowState);
|
||||||
window_state_ptr as *mut WindowState
|
|
||||||
);
|
|
||||||
|
|
||||||
window_state.trigger_frame();
|
window_state.trigger_frame();
|
||||||
}
|
}
|
||||||
|
@ -265,18 +225,10 @@ impl WindowState {
|
||||||
copyDescription: None,
|
copyDescription: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let timer = CFRunLoopTimer::new(
|
let timer = CFRunLoopTimer::new(0.0, 0.015, 0, 0, timer_callback, &mut timer_context);
|
||||||
0.0,
|
|
||||||
0.015,
|
CFRunLoop::get_current().add_timer(&timer, kCFRunLoopDefaultMode);
|
||||||
0,
|
|
||||||
0,
|
|
||||||
timer_callback,
|
|
||||||
&mut timer_context,
|
|
||||||
);
|
|
||||||
|
|
||||||
CFRunLoop::get_current()
|
|
||||||
.add_timer(&timer, kCFRunLoopDefaultMode);
|
|
||||||
|
|
||||||
let window_state = &mut *(window_state_ptr);
|
let window_state = &mut *(window_state_ptr);
|
||||||
|
|
||||||
window_state.frame_timer = Some(timer);
|
window_state.frame_timer = Some(timer);
|
||||||
|
@ -285,18 +237,14 @@ impl WindowState {
|
||||||
/// Call when freeing view
|
/// Call when freeing view
|
||||||
pub(super) unsafe fn remove_timer(&mut self) {
|
pub(super) unsafe fn remove_timer(&mut self) {
|
||||||
if let Some(frame_timer) = self.frame_timer.take() {
|
if let Some(frame_timer) = self.frame_timer.take() {
|
||||||
CFRunLoop::get_current()
|
CFRunLoop::get_current().remove_timer(&frame_timer, kCFRunLoopDefaultMode);
|
||||||
.remove_timer(&frame_timer, kCFRunLoopDefaultMode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsafe impl HasRawWindowHandle for Window {
|
unsafe impl HasRawWindowHandle for Window {
|
||||||
fn raw_window_handle(&self) -> RawWindowHandle {
|
fn raw_window_handle(&self) -> RawWindowHandle {
|
||||||
let ns_window = self.ns_window.unwrap_or(
|
let ns_window = self.ns_window.unwrap_or(::std::ptr::null_mut()) as *mut c_void;
|
||||||
::std::ptr::null_mut()
|
|
||||||
) as *mut c_void;
|
|
||||||
|
|
||||||
RawWindowHandle::MacOS(MacOSHandle {
|
RawWindowHandle::MacOS(MacOSHandle {
|
||||||
ns_window,
|
ns_window,
|
||||||
|
|
|
@ -23,7 +23,7 @@ use std::convert::TryInto;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
use keyboard_types::{Code, Key, KeyboardEvent, KeyState, Location, Modifiers};
|
use keyboard_types::{Code, Key, KeyState, KeyboardEvent, Location, Modifiers};
|
||||||
|
|
||||||
use winapi::shared::minwindef::{HKL, INT, LPARAM, UINT, WPARAM};
|
use winapi::shared::minwindef::{HKL, INT, LPARAM, UINT, WPARAM};
|
||||||
use winapi::shared::ntdef::SHORT;
|
use winapi::shared::ntdef::SHORT;
|
||||||
|
@ -502,14 +502,8 @@ impl KeyboardState {
|
||||||
let stash_vk = None;
|
let stash_vk = None;
|
||||||
let stash_utf16 = Vec::new();
|
let stash_utf16 = Vec::new();
|
||||||
let has_altgr = false;
|
let has_altgr = false;
|
||||||
let mut result = KeyboardState {
|
let mut result =
|
||||||
hkl,
|
KeyboardState { hkl, key_vals, dead_keys, has_altgr, stash_vk, stash_utf16 };
|
||||||
key_vals,
|
|
||||||
dead_keys,
|
|
||||||
has_altgr,
|
|
||||||
stash_vk,
|
|
||||||
stash_utf16,
|
|
||||||
};
|
|
||||||
result.load_keyboard_layout();
|
result.load_keyboard_layout();
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -548,11 +542,7 @@ impl KeyboardState {
|
||||||
/// a valid `HKL` reference in the `WM_INPUTLANGCHANGE` message. Actual danger
|
/// a valid `HKL` reference in the `WM_INPUTLANGCHANGE` message. Actual danger
|
||||||
/// is likely low, though.
|
/// is likely low, though.
|
||||||
pub(crate) unsafe fn process_message(
|
pub(crate) unsafe fn process_message(
|
||||||
&mut self,
|
&mut self, hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM,
|
||||||
hwnd: HWND,
|
|
||||||
msg: UINT,
|
|
||||||
wparam: WPARAM,
|
|
||||||
lparam: LPARAM,
|
|
||||||
) -> Option<KeyboardEvent> {
|
) -> Option<KeyboardEvent> {
|
||||||
match msg {
|
match msg {
|
||||||
WM_KEYDOWN | WM_SYSKEYDOWN => {
|
WM_KEYDOWN | WM_SYSKEYDOWN => {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
mod window;
|
|
||||||
mod keyboard;
|
mod keyboard;
|
||||||
|
mod window;
|
||||||
|
|
||||||
pub use window::*;
|
pub use window::*;
|
||||||
|
|
|
@ -3,35 +3,29 @@ use winapi::shared::minwindef::{ATOM, FALSE, LPARAM, LRESULT, UINT, WPARAM};
|
||||||
use winapi::shared::windef::{HWND, RECT};
|
use winapi::shared::windef::{HWND, RECT};
|
||||||
use winapi::um::combaseapi::CoCreateGuid;
|
use winapi::um::combaseapi::CoCreateGuid;
|
||||||
use winapi::um::winuser::{
|
use winapi::um::winuser::{
|
||||||
AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DispatchMessageW,
|
AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW,
|
||||||
GetMessageW, GetWindowLongPtrW, PostMessageW, RegisterClassW, SetTimer,
|
GetCapture, GetDpiForWindow, GetMessageW, GetWindowLongPtrW, IsWindow, LoadCursorW,
|
||||||
SetWindowLongPtrW, TranslateMessage, UnregisterClassW, LoadCursorW,
|
PostMessageW, RegisterClassW, ReleaseCapture, SetCapture, SetProcessDpiAwarenessContext,
|
||||||
DestroyWindow, SetProcessDpiAwarenessContext, SetWindowPos,
|
SetTimer, SetWindowLongPtrW, SetWindowPos, TranslateMessage, UnregisterClassW, CS_OWNDC,
|
||||||
GetDpiForWindow,
|
GET_XBUTTON_WPARAM, GWLP_USERDATA, IDC_ARROW, MSG, SWP_NOMOVE, SWP_NOZORDER, WHEEL_DELTA,
|
||||||
CS_OWNDC, GWLP_USERDATA, IDC_ARROW,
|
WM_CHAR, WM_CLOSE, WM_CREATE, WM_DPICHANGED, WM_INPUTLANGCHANGE, WM_KEYDOWN, WM_KEYUP,
|
||||||
MSG, WM_CLOSE, WM_CREATE, WM_MOUSEMOVE, WM_MOUSEWHEEL, WHEEL_DELTA, WM_SHOWWINDOW, WM_TIMER,
|
WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEMOVE, WM_MOUSEWHEEL,
|
||||||
WM_NCDESTROY, WNDCLASSW, WS_CAPTION, WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX,
|
WM_NCDESTROY, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SHOWWINDOW, WM_SIZE, WM_SYSCHAR, WM_SYSKEYDOWN,
|
||||||
WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE, WM_DPICHANGED, WM_CHAR, WM_SYSCHAR, WM_KEYDOWN,
|
WM_SYSKEYUP, WM_TIMER, WM_XBUTTONDOWN, WM_XBUTTONUP, WNDCLASSW, WS_CAPTION, WS_CHILD,
|
||||||
WM_SYSKEYDOWN, WM_KEYUP, WM_SYSKEYUP, WM_INPUTLANGCHANGE, WM_SIZE,
|
WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX, WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE,
|
||||||
GET_XBUTTON_WPARAM, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP,
|
XBUTTON1, XBUTTON2,
|
||||||
WM_RBUTTONDOWN, WM_RBUTTONUP, WM_XBUTTONDOWN, WM_XBUTTONUP, XBUTTON1, XBUTTON2,
|
|
||||||
SetCapture, GetCapture, ReleaseCapture, IsWindow, SWP_NOZORDER, SWP_NOMOVE
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ffi::{OsStr, c_void};
|
use std::ffi::{c_void, OsStr};
|
||||||
use std::os::windows::ffi::OsStrExt;
|
use std::os::windows::ffi::OsStrExt;
|
||||||
use std::ptr::null_mut;
|
use std::ptr::null_mut;
|
||||||
|
|
||||||
use raw_window_handle::{
|
use raw_window_handle::{windows::WindowsHandle, HasRawWindowHandle, RawWindowHandle};
|
||||||
windows::WindowsHandle,
|
|
||||||
HasRawWindowHandle,
|
|
||||||
RawWindowHandle
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Event, MouseButton, MouseEvent, ScrollDelta, WindowEvent,
|
Event, MouseButton, MouseEvent, PhyPoint, PhySize, ScrollDelta, WindowEvent, WindowHandler,
|
||||||
WindowHandler, WindowInfo, WindowOpenOptions, WindowScalePolicy, PhyPoint, PhySize
|
WindowInfo, WindowOpenOptions, WindowScalePolicy,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::keyboard::KeyboardState;
|
use super::keyboard::KeyboardState;
|
||||||
|
@ -83,19 +77,17 @@ unsafe extern "system" fn wnd_proc(
|
||||||
|
|
||||||
window_state.handler.on_event(
|
window_state.handler.on_event(
|
||||||
&mut window,
|
&mut window,
|
||||||
Event::Mouse(MouseEvent::CursorMoved {
|
Event::Mouse(MouseEvent::CursorMoved { position: logical_pos }),
|
||||||
position: logical_pos,
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
WM_MOUSEWHEEL => {
|
WM_MOUSEWHEEL => {
|
||||||
let value = (wparam >> 16) as i16;
|
let value = (wparam >> 16) as i16;
|
||||||
let value = value as i32;
|
let value = value as i32;
|
||||||
let value = value as f32 / WHEEL_DELTA as f32;
|
let value = value as f32 / WHEEL_DELTA as f32;
|
||||||
|
|
||||||
let mut window_state = (&*window_state_ptr).borrow_mut();
|
let mut window_state = (&*window_state_ptr).borrow_mut();
|
||||||
|
|
||||||
window_state.handler.on_event(
|
window_state.handler.on_event(
|
||||||
&mut window,
|
&mut window,
|
||||||
Event::Mouse(MouseEvent::WheelScrolled(ScrollDelta::Lines {
|
Event::Mouse(MouseEvent::WheelScrolled(ScrollDelta::Lines {
|
||||||
|
@ -105,9 +97,8 @@ unsafe extern "system" fn wnd_proc(
|
||||||
);
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
WM_LBUTTONDOWN | WM_LBUTTONUP | WM_MBUTTONDOWN | WM_MBUTTONUP |
|
WM_LBUTTONDOWN | WM_LBUTTONUP | WM_MBUTTONDOWN | WM_MBUTTONUP | WM_RBUTTONDOWN
|
||||||
WM_RBUTTONDOWN | WM_RBUTTONUP | WM_XBUTTONDOWN | WM_XBUTTONUP => {
|
| WM_RBUTTONUP | WM_XBUTTONDOWN | WM_XBUTTONUP => {
|
||||||
|
|
||||||
let mut mouse_button_counter = (&*window_state_ptr).borrow().mouse_button_counter;
|
let mut mouse_button_counter = (&*window_state_ptr).borrow().mouse_button_counter;
|
||||||
|
|
||||||
let button = match msg {
|
let button = match msg {
|
||||||
|
@ -136,7 +127,7 @@ unsafe extern "system" fn wnd_proc(
|
||||||
if mouse_button_counter == 0 {
|
if mouse_button_counter == 0 {
|
||||||
ReleaseCapture();
|
ReleaseCapture();
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseEvent::ButtonReleased(button)
|
MouseEvent::ButtonReleased(button)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -146,7 +137,8 @@ unsafe extern "system" fn wnd_proc(
|
||||||
|
|
||||||
(&*window_state_ptr).borrow_mut().mouse_button_counter = mouse_button_counter;
|
(&*window_state_ptr).borrow_mut().mouse_button_counter = mouse_button_counter;
|
||||||
|
|
||||||
(&*window_state_ptr).borrow_mut()
|
(&*window_state_ptr)
|
||||||
|
.borrow_mut()
|
||||||
.handler
|
.handler
|
||||||
.on_event(&mut window, Event::Mouse(event));
|
.on_event(&mut window, Event::Mouse(event));
|
||||||
}
|
}
|
||||||
|
@ -169,14 +161,16 @@ unsafe extern "system" fn wnd_proc(
|
||||||
// return 0;
|
// return 0;
|
||||||
return DefWindowProcW(hwnd, msg, wparam, lparam);
|
return DefWindowProcW(hwnd, msg, wparam, lparam);
|
||||||
}
|
}
|
||||||
WM_CHAR | WM_SYSCHAR | WM_KEYDOWN | WM_SYSKEYDOWN | WM_KEYUP
|
WM_CHAR | WM_SYSCHAR | WM_KEYDOWN | WM_SYSKEYDOWN | WM_KEYUP | WM_SYSKEYUP
|
||||||
| WM_SYSKEYUP | WM_INPUTLANGCHANGE => {
|
| WM_INPUTLANGCHANGE => {
|
||||||
let opt_event = (&*window_state_ptr).borrow_mut()
|
let opt_event = (&*window_state_ptr)
|
||||||
|
.borrow_mut()
|
||||||
.keyboard_state
|
.keyboard_state
|
||||||
.process_message(hwnd, msg, wparam, lparam);
|
.process_message(hwnd, msg, wparam, lparam);
|
||||||
|
|
||||||
if let Some(event) = opt_event {
|
if let Some(event) = opt_event {
|
||||||
(&*window_state_ptr).borrow_mut()
|
(&*window_state_ptr)
|
||||||
|
.borrow_mut()
|
||||||
.handler
|
.handler
|
||||||
.on_event(&mut window, Event::Keyboard(event));
|
.on_event(&mut window, Event::Keyboard(event));
|
||||||
}
|
}
|
||||||
|
@ -198,10 +192,9 @@ unsafe extern "system" fn wnd_proc(
|
||||||
|
|
||||||
let window_info = window_state.window_info;
|
let window_info = window_state.window_info;
|
||||||
|
|
||||||
window_state.handler.on_event(
|
window_state
|
||||||
&mut window,
|
.handler
|
||||||
Event::Window(WindowEvent::Resized(window_info)),
|
.on_event(&mut window, Event::Window(WindowEvent::Resized(window_info)));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
WM_DPICHANGED => {
|
WM_DPICHANGED => {
|
||||||
// To avoid weirdness with the realtime borrow checker.
|
// To avoid weirdness with the realtime borrow checker.
|
||||||
|
@ -256,8 +249,6 @@ unsafe extern "system" fn wnd_proc(
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return DefWindowProcW(hwnd, msg, wparam, lparam);
|
return DefWindowProcW(hwnd, msg, wparam, lparam);
|
||||||
|
@ -266,9 +257,7 @@ unsafe extern "system" fn wnd_proc(
|
||||||
unsafe fn register_wnd_class() -> ATOM {
|
unsafe fn register_wnd_class() -> ATOM {
|
||||||
// We generate a unique name for the new window class to prevent name collisions
|
// We generate a unique name for the new window class to prevent name collisions
|
||||||
let class_name_str = format!("Baseview-{}", generate_guid());
|
let class_name_str = format!("Baseview-{}", generate_guid());
|
||||||
let mut class_name: Vec<u16> = OsStr::new(&class_name_str)
|
let mut class_name: Vec<u16> = OsStr::new(&class_name_str).encode_wide().collect();
|
||||||
.encode_wide()
|
|
||||||
.collect();
|
|
||||||
class_name.push(0);
|
class_name.push(0);
|
||||||
|
|
||||||
let wnd_class = WNDCLASSW {
|
let wnd_class = WNDCLASSW {
|
||||||
|
@ -359,30 +348,24 @@ impl Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open<H, B>(
|
fn open<H, B>(parented: bool, parent: HWND, options: WindowOpenOptions, build: B) -> HWND
|
||||||
parented: bool,
|
where
|
||||||
parent: HWND,
|
H: WindowHandler + 'static,
|
||||||
options: WindowOpenOptions,
|
B: FnOnce(&mut crate::Window) -> H,
|
||||||
build: B
|
B: Send + 'static,
|
||||||
) -> HWND
|
|
||||||
where H: WindowHandler + 'static,
|
|
||||||
B: FnOnce(&mut crate::Window) -> H,
|
|
||||||
B: Send + 'static,
|
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut title: Vec<u16> = OsStr::new(&options.title[..])
|
let mut title: Vec<u16> = OsStr::new(&options.title[..]).encode_wide().collect();
|
||||||
.encode_wide()
|
|
||||||
.collect();
|
|
||||||
title.push(0);
|
title.push(0);
|
||||||
|
|
||||||
let window_class = register_wnd_class();
|
let window_class = register_wnd_class();
|
||||||
// todo: manage error ^
|
// todo: manage error ^
|
||||||
|
|
||||||
let scaling = match options.scale {
|
let scaling = match options.scale {
|
||||||
WindowScalePolicy::SystemScaleFactor => 1.0,
|
WindowScalePolicy::SystemScaleFactor => 1.0,
|
||||||
WindowScalePolicy::ScaleFactor(scale) => scale
|
WindowScalePolicy::ScaleFactor(scale) => scale,
|
||||||
};
|
};
|
||||||
|
|
||||||
let window_info = WindowInfo::from_logical_size(options.size, scaling);
|
let window_info = WindowInfo::from_logical_size(options.size, scaling);
|
||||||
|
|
||||||
let mut rect = RECT {
|
let mut rect = RECT {
|
||||||
|
@ -502,4 +485,4 @@ unsafe impl HasRawWindowHandle for Window {
|
||||||
..WindowsHandle::empty()
|
..WindowsHandle::empty()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,7 @@ pub struct Window<'a> {
|
||||||
|
|
||||||
impl<'a> Window<'a> {
|
impl<'a> Window<'a> {
|
||||||
pub(crate) fn new(window: &mut platform::Window) -> Window {
|
pub(crate) fn new(window: &mut platform::Window) -> Window {
|
||||||
Window {
|
Window { window, phantom: PhantomData }
|
||||||
window,
|
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_parented<P, H, B>(parent: &P, options: WindowOpenOptions, build: B)
|
pub fn open_parented<P, H, B>(parent: &P, options: WindowOpenOptions, build: B)
|
||||||
|
|
|
@ -16,12 +16,7 @@ impl WindowInfo {
|
||||||
height: (logical_size.height * scale).round() as u32,
|
height: (logical_size.height * scale).round() as u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Self { logical_size, physical_size, scale, scale_recip }
|
||||||
logical_size,
|
|
||||||
physical_size,
|
|
||||||
scale,
|
|
||||||
scale_recip,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_physical_size(physical_size: PhySize, scale: f64) -> Self {
|
pub fn from_physical_size(physical_size: PhySize, scale: f64) -> Self {
|
||||||
|
@ -32,12 +27,7 @@ impl WindowInfo {
|
||||||
height: f64::from(physical_size.height) * scale_recip,
|
height: f64::from(physical_size.height) * scale_recip,
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Self { logical_size, physical_size, scale, scale_recip }
|
||||||
logical_size,
|
|
||||||
physical_size,
|
|
||||||
scale,
|
|
||||||
scale_recip,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The logical size of the window
|
/// The logical size of the window
|
||||||
|
@ -65,7 +55,7 @@ impl WindowInfo {
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
pub struct Point {
|
pub struct Point {
|
||||||
pub x: f64,
|
pub x: f64,
|
||||||
pub y: f64
|
pub y: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Point {
|
impl Point {
|
||||||
|
@ -88,7 +78,7 @@ impl Point {
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
pub struct PhyPoint {
|
pub struct PhyPoint {
|
||||||
pub x: i32,
|
pub x: i32,
|
||||||
pub y: i32
|
pub y: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PhyPoint {
|
impl PhyPoint {
|
||||||
|
@ -151,4 +141,4 @@ impl PhySize {
|
||||||
height: f64::from(self.height) * window_info.scale_recip(),
|
height: f64::from(self.height) * window_info.scale_recip(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,9 +35,8 @@ fn create_empty_cursor(display: *mut x11::xlib::Display) -> Option<u32> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_cursor(display: *mut x11::xlib::Display, name: &[u8]) -> Option<u32> {
|
fn load_cursor(display: *mut x11::xlib::Display, name: &[u8]) -> Option<u32> {
|
||||||
let xcursor = unsafe {
|
let xcursor =
|
||||||
x11::xcursor::XcursorLibraryLoadCursor(display, name.as_ptr() as *const c_char)
|
unsafe { x11::xcursor::XcursorLibraryLoadCursor(display, name.as_ptr() as *const c_char) };
|
||||||
};
|
|
||||||
|
|
||||||
if xcursor == 0 {
|
if xcursor == 0 {
|
||||||
None
|
None
|
||||||
|
@ -47,7 +46,8 @@ fn load_cursor(display: *mut x11::xlib::Display, name: &[u8]) -> Option<u32> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_first_existing_cursor(display: *mut x11::xlib::Display, names: &[&[u8]]) -> Option<u32> {
|
fn load_first_existing_cursor(display: *mut x11::xlib::Display, names: &[&[u8]]) -> Option<u32> {
|
||||||
names.iter()
|
names
|
||||||
|
.iter()
|
||||||
.map(|name| load_cursor(display, name))
|
.map(|name| load_cursor(display, name))
|
||||||
.find(|xcursor| xcursor.is_some())
|
.find(|xcursor| xcursor.is_some())
|
||||||
.unwrap_or(None)
|
.unwrap_or(None)
|
||||||
|
@ -101,7 +101,5 @@ pub(super) fn get_xcursor(display: *mut x11::xlib::Display, cursor: MouseCursor)
|
||||||
MouseCursor::RowResize => loadn(&[b"split_v\0", b"v_double_arrow\0"]),
|
MouseCursor::RowResize => loadn(&[b"split_v\0", b"v_double_arrow\0"]),
|
||||||
};
|
};
|
||||||
|
|
||||||
cursor
|
cursor.or(load(b"left_ptr\0")).unwrap_or(0)
|
||||||
.or(load(b"left_ptr\0"))
|
|
||||||
.unwrap_or(0)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ use keyboard_types::*;
|
||||||
|
|
||||||
use crate::keyboard::code_to_location;
|
use crate::keyboard::code_to_location;
|
||||||
|
|
||||||
|
|
||||||
/// Convert a hardware scan code to a key.
|
/// Convert a hardware scan code to a key.
|
||||||
///
|
///
|
||||||
/// Note: this is a hardcoded layout. We need to detect the user's
|
/// Note: this is a hardcoded layout. We need to detect the user's
|
||||||
|
@ -202,7 +201,6 @@ fn code_to_key(code: Code, m: Modifiers) -> Key {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
/// Map hardware keycode to code.
|
/// Map hardware keycode to code.
|
||||||
///
|
///
|
||||||
|
@ -385,10 +383,7 @@ fn key_mods(mods: u16) -> Modifiers {
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn convert_key_press_event(key_press: &xcb::KeyPressEvent) -> KeyboardEvent {
|
||||||
pub(super) fn convert_key_press_event(
|
|
||||||
key_press: &xcb::KeyPressEvent,
|
|
||||||
) -> KeyboardEvent {
|
|
||||||
let hw_keycode = key_press.detail();
|
let hw_keycode = key_press.detail();
|
||||||
let code = hardware_keycode_to_code(hw_keycode.into());
|
let code = hardware_keycode_to_code(hw_keycode.into());
|
||||||
let modifiers = key_mods(key_press.state());
|
let modifiers = key_mods(key_press.state());
|
||||||
|
@ -396,21 +391,10 @@ pub(super) fn convert_key_press_event(
|
||||||
let location = code_to_location(code);
|
let location = code_to_location(code);
|
||||||
let state = KeyState::Down;
|
let state = KeyState::Down;
|
||||||
|
|
||||||
KeyboardEvent {
|
KeyboardEvent { code, key, modifiers, location, state, repeat: false, is_composing: false }
|
||||||
code,
|
|
||||||
key,
|
|
||||||
modifiers,
|
|
||||||
location,
|
|
||||||
state,
|
|
||||||
repeat: false,
|
|
||||||
is_composing: false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn convert_key_release_event(key_release: &xcb::KeyReleaseEvent) -> KeyboardEvent {
|
||||||
pub(super) fn convert_key_release_event(
|
|
||||||
key_release: &xcb::KeyReleaseEvent
|
|
||||||
) -> KeyboardEvent {
|
|
||||||
let hw_keycode = key_release.detail();
|
let hw_keycode = key_release.detail();
|
||||||
let code = hardware_keycode_to_code(hw_keycode.into());
|
let code = hardware_keycode_to_code(hw_keycode.into());
|
||||||
let modifiers = key_mods(key_release.state());
|
let modifiers = key_mods(key_release.state());
|
||||||
|
@ -418,13 +402,5 @@ pub(super) fn convert_key_release_event(
|
||||||
let location = code_to_location(code);
|
let location = code_to_location(code);
|
||||||
let state = KeyState::Up;
|
let state = KeyState::Up;
|
||||||
|
|
||||||
KeyboardEvent {
|
KeyboardEvent { code, key, modifiers, location, state, repeat: false, is_composing: false }
|
||||||
code,
|
}
|
||||||
key,
|
|
||||||
modifiers,
|
|
||||||
location,
|
|
||||||
state,
|
|
||||||
repeat: false,
|
|
||||||
is_composing: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,4 +5,4 @@ mod window;
|
||||||
pub use window::*;
|
pub use window::*;
|
||||||
|
|
||||||
mod cursor;
|
mod cursor;
|
||||||
mod keyboard;
|
mod keyboard;
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
use std::os::raw::{c_ulong, c_void};
|
use std::os::raw::{c_ulong, c_void};
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::time::*;
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
use std::time::*;
|
||||||
|
|
||||||
use raw_window_handle::{
|
use raw_window_handle::{unix::XlibHandle, HasRawWindowHandle, RawWindowHandle};
|
||||||
unix::XlibHandle,
|
|
||||||
HasRawWindowHandle,
|
|
||||||
RawWindowHandle
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::XcbConnection;
|
use super::XcbConnection;
|
||||||
use crate::{
|
use crate::{
|
||||||
Event, MouseButton, MouseCursor, MouseEvent, ScrollDelta,
|
Event, MouseButton, MouseCursor, MouseEvent, PhyPoint, PhySize, ScrollDelta, WindowEvent,
|
||||||
WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions,
|
WindowHandler, WindowInfo, WindowOpenOptions, WindowScalePolicy,
|
||||||
WindowScalePolicy, PhyPoint, PhySize,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::keyboard::{convert_key_press_event, convert_key_release_event};
|
use super::keyboard::{convert_key_press_event, convert_key_release_event};
|
||||||
|
@ -94,13 +89,12 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn window_thread<H, B>(
|
fn window_thread<H, B>(
|
||||||
parent: Option<u32>,
|
parent: Option<u32>, options: WindowOpenOptions, build: B,
|
||||||
options: WindowOpenOptions, build: B,
|
|
||||||
tx: mpsc::SyncSender<WindowOpenResult>,
|
tx: mpsc::SyncSender<WindowOpenResult>,
|
||||||
)
|
) where
|
||||||
where H: WindowHandler + 'static,
|
H: WindowHandler + 'static,
|
||||||
B: FnOnce(&mut crate::Window) -> H,
|
B: FnOnce(&mut crate::Window) -> H,
|
||||||
B: Send + 'static,
|
B: Send + 'static,
|
||||||
{
|
{
|
||||||
// Connect to the X server
|
// Connect to the X server
|
||||||
// FIXME: baseview error type instead of unwrap()
|
// FIXME: baseview error type instead of unwrap()
|
||||||
|
@ -108,10 +102,7 @@ impl Window {
|
||||||
|
|
||||||
// Get screen information (?)
|
// Get screen information (?)
|
||||||
let setup = xcb_connection.conn.get_setup();
|
let setup = xcb_connection.conn.get_setup();
|
||||||
let screen = setup
|
let screen = setup.roots().nth(xcb_connection.xlib_display as usize).unwrap();
|
||||||
.roots()
|
|
||||||
.nth(xcb_connection.xlib_display as usize)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let foreground = xcb_connection.conn.generate_id();
|
let foreground = xcb_connection.conn.generate_id();
|
||||||
|
|
||||||
|
@ -121,15 +112,12 @@ impl Window {
|
||||||
&xcb_connection.conn,
|
&xcb_connection.conn,
|
||||||
foreground,
|
foreground,
|
||||||
parent_id,
|
parent_id,
|
||||||
&[
|
&[(xcb::GC_FOREGROUND, screen.black_pixel()), (xcb::GC_GRAPHICS_EXPOSURES, 0)],
|
||||||
(xcb::GC_FOREGROUND, screen.black_pixel()),
|
|
||||||
(xcb::GC_GRAPHICS_EXPOSURES, 0),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let scaling = match options.scale {
|
let scaling = match options.scale {
|
||||||
WindowScalePolicy::SystemScaleFactor => xcb_connection.get_scaling().unwrap_or(1.0),
|
WindowScalePolicy::SystemScaleFactor => xcb_connection.get_scaling().unwrap_or(1.0),
|
||||||
WindowScalePolicy::ScaleFactor(scale) => scale
|
WindowScalePolicy::ScaleFactor(scale) => scale,
|
||||||
};
|
};
|
||||||
|
|
||||||
let window_info = WindowInfo::from_logical_size(options.size, scaling);
|
let window_info = WindowInfo::from_logical_size(options.size, scaling);
|
||||||
|
@ -140,11 +128,11 @@ impl Window {
|
||||||
xcb::COPY_FROM_PARENT as u8,
|
xcb::COPY_FROM_PARENT as u8,
|
||||||
window_id,
|
window_id,
|
||||||
parent_id,
|
parent_id,
|
||||||
0, // x coordinate of the new window
|
0, // x coordinate of the new window
|
||||||
0, // y coordinate of the new window
|
0, // y coordinate of the new window
|
||||||
window_info.physical_size().width as u16, // window width
|
window_info.physical_size().width as u16, // window width
|
||||||
window_info.physical_size().height as u16, // window height
|
window_info.physical_size().height as u16, // window height
|
||||||
0, // window border
|
0, // window border
|
||||||
xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
|
xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
|
||||||
screen.root_visual(),
|
screen.root_visual(),
|
||||||
&[(
|
&[(
|
||||||
|
@ -173,16 +161,16 @@ impl Window {
|
||||||
title.as_bytes(),
|
title.as_bytes(),
|
||||||
);
|
);
|
||||||
|
|
||||||
xcb_connection.atoms.wm_protocols
|
xcb_connection.atoms.wm_protocols.zip(xcb_connection.atoms.wm_delete_window).map(
|
||||||
.zip(xcb_connection.atoms.wm_delete_window)
|
|(wm_protocols, wm_delete_window)| {
|
||||||
.map(|(wm_protocols, wm_delete_window)| {
|
|
||||||
xcb_util::icccm::set_wm_protocols(
|
xcb_util::icccm::set_wm_protocols(
|
||||||
&xcb_connection.conn,
|
&xcb_connection.conn,
|
||||||
window_id,
|
window_id,
|
||||||
wm_protocols,
|
wm_protocols,
|
||||||
&[wm_delete_window],
|
&[wm_delete_window],
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
xcb_connection.conn.flush();
|
xcb_connection.conn.flush();
|
||||||
|
|
||||||
|
@ -204,7 +192,7 @@ impl Window {
|
||||||
// the correct dpi scaling.
|
// the correct dpi scaling.
|
||||||
handler.on_event(
|
handler.on_event(
|
||||||
&mut crate::Window::new(&mut window),
|
&mut crate::Window::new(&mut window),
|
||||||
Event::Window(WindowEvent::Resized(window_info))
|
Event::Window(WindowEvent::Resized(window_info)),
|
||||||
);
|
);
|
||||||
|
|
||||||
let _ = tx.send(Ok(SendableRwh(window.raw_window_handle())));
|
let _ = tx.send(Ok(SendableRwh(window.raw_window_handle())));
|
||||||
|
@ -218,7 +206,7 @@ impl Window {
|
||||||
|
|
||||||
pub fn set_mouse_cursor(&mut self, mouse_cursor: MouseCursor) {
|
pub fn set_mouse_cursor(&mut self, mouse_cursor: MouseCursor) {
|
||||||
if self.mouse_cursor == mouse_cursor {
|
if self.mouse_cursor == mouse_cursor {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let xid = self.xcb_connection.get_cursor_xid(mouse_cursor);
|
let xid = self.xcb_connection.get_cursor_xid(mouse_cursor);
|
||||||
|
@ -227,7 +215,7 @@ impl Window {
|
||||||
xcb::change_window_attributes(
|
xcb::change_window_attributes(
|
||||||
&self.xcb_connection.conn,
|
&self.xcb_connection.conn,
|
||||||
self.window_id,
|
self.window_id,
|
||||||
&[(xcb::CW_CURSOR, xid)]
|
&[(xcb::CW_CURSOR, xid)],
|
||||||
);
|
);
|
||||||
|
|
||||||
self.xcb_connection.conn.flush();
|
self.xcb_connection.conn.flush();
|
||||||
|
@ -248,16 +236,13 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(size) = self.new_physical_size.take() {
|
if let Some(size) = self.new_physical_size.take() {
|
||||||
self.window_info = WindowInfo::from_physical_size(
|
self.window_info = WindowInfo::from_physical_size(size, self.window_info.scale());
|
||||||
size,
|
|
||||||
self.window_info.scale()
|
|
||||||
);
|
|
||||||
|
|
||||||
let window_info = self.window_info;
|
let window_info = self.window_info;
|
||||||
|
|
||||||
handler.on_event(
|
handler.on_event(
|
||||||
&mut crate::Window::new(self),
|
&mut crate::Window::new(self),
|
||||||
Event::Window(WindowEvent::Resized(window_info))
|
Event::Window(WindowEvent::Resized(window_info)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,13 +328,13 @@ impl Window {
|
||||||
let data = event.data().data;
|
let data = event.data().data;
|
||||||
let (_, data32, _) = unsafe { data.align_to::<u32>() };
|
let (_, data32, _) = unsafe { data.align_to::<u32>() };
|
||||||
|
|
||||||
let wm_delete_window = self.xcb_connection.atoms.wm_delete_window
|
let wm_delete_window =
|
||||||
.unwrap_or(xcb::NONE);
|
self.xcb_connection.atoms.wm_delete_window.unwrap_or(xcb::NONE);
|
||||||
|
|
||||||
if wm_delete_window == data32[0] {
|
if wm_delete_window == data32[0] {
|
||||||
handler.on_event(
|
handler.on_event(
|
||||||
&mut crate::Window::new(self),
|
&mut crate::Window::new(self),
|
||||||
Event::Window(WindowEvent::WillClose)
|
Event::Window(WindowEvent::WillClose),
|
||||||
);
|
);
|
||||||
|
|
||||||
// FIXME: handler should decide whether window stays open or not
|
// FIXME: handler should decide whether window stays open or not
|
||||||
|
@ -362,7 +347,9 @@ impl Window {
|
||||||
|
|
||||||
let new_physical_size = PhySize::new(event.width() as u32, event.height() as u32);
|
let new_physical_size = PhySize::new(event.width() as u32, event.height() as u32);
|
||||||
|
|
||||||
if self.new_physical_size.is_some() || new_physical_size != self.window_info.physical_size() {
|
if self.new_physical_size.is_some()
|
||||||
|
|| new_physical_size != self.window_info.physical_size()
|
||||||
|
{
|
||||||
self.new_physical_size = Some(new_physical_size);
|
self.new_physical_size = Some(new_physical_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -375,14 +362,13 @@ impl Window {
|
||||||
let detail = event.detail();
|
let detail = event.detail();
|
||||||
|
|
||||||
if detail != 4 && detail != 5 {
|
if detail != 4 && detail != 5 {
|
||||||
let physical_pos = PhyPoint::new(event.event_x() as i32, event.event_y() as i32);
|
let physical_pos =
|
||||||
|
PhyPoint::new(event.event_x() as i32, event.event_y() as i32);
|
||||||
let logical_pos = physical_pos.to_logical(&self.window_info);
|
let logical_pos = physical_pos.to_logical(&self.window_info);
|
||||||
|
|
||||||
handler.on_event(
|
handler.on_event(
|
||||||
&mut crate::Window::new(self),
|
&mut crate::Window::new(self),
|
||||||
Event::Mouse(MouseEvent::CursorMoved {
|
Event::Mouse(MouseEvent::CursorMoved { position: logical_pos }),
|
||||||
position: logical_pos,
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -414,7 +400,7 @@ impl Window {
|
||||||
let button_id = mouse_id(detail);
|
let button_id = mouse_id(detail);
|
||||||
handler.on_event(
|
handler.on_event(
|
||||||
&mut crate::Window::new(self),
|
&mut crate::Window::new(self),
|
||||||
Event::Mouse(MouseEvent::ButtonPressed(button_id))
|
Event::Mouse(MouseEvent::ButtonPressed(button_id)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -428,7 +414,7 @@ impl Window {
|
||||||
let button_id = mouse_id(detail);
|
let button_id = mouse_id(detail);
|
||||||
handler.on_event(
|
handler.on_event(
|
||||||
&mut crate::Window::new(self),
|
&mut crate::Window::new(self),
|
||||||
Event::Mouse(MouseEvent::ButtonReleased(button_id))
|
Event::Mouse(MouseEvent::ButtonReleased(button_id)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -441,7 +427,7 @@ impl Window {
|
||||||
|
|
||||||
handler.on_event(
|
handler.on_event(
|
||||||
&mut crate::Window::new(self),
|
&mut crate::Window::new(self),
|
||||||
Event::Keyboard(convert_key_press_event(&event))
|
Event::Keyboard(convert_key_press_event(&event)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,7 +436,7 @@ impl Window {
|
||||||
|
|
||||||
handler.on_event(
|
handler.on_event(
|
||||||
&mut crate::Window::new(self),
|
&mut crate::Window::new(self),
|
||||||
Event::Keyboard(convert_key_release_event(&event))
|
Event::Keyboard(convert_key_release_event(&event)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
/// A very light abstraction around the XCB connection.
|
/// A very light abstraction around the XCB connection.
|
||||||
///
|
///
|
||||||
/// Keeps track of the xcb connection itself and the xlib display ID that was used to connect.
|
/// Keeps track of the xcb connection itself and the xlib display ID that was used to connect.
|
||||||
|
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use crate::MouseCursor;
|
use crate::MouseCursor;
|
||||||
|
|
||||||
use super::cursor;
|
use super::cursor;
|
||||||
|
|
||||||
|
|
||||||
pub(crate) struct Atoms {
|
pub(crate) struct Atoms {
|
||||||
pub wm_protocols: Option<u32>,
|
pub wm_protocols: Option<u32>,
|
||||||
pub wm_delete_window: Option<u32>,
|
pub wm_delete_window: Option<u32>,
|
||||||
|
@ -48,19 +46,16 @@ impl XcbConnection {
|
||||||
|
|
||||||
conn.set_event_queue_owner(xcb::base::EventQueueOwner::Xcb);
|
conn.set_event_queue_owner(xcb::base::EventQueueOwner::Xcb);
|
||||||
|
|
||||||
let (wm_protocols, wm_delete_window, wm_normal_hints) = intern_atoms!(&conn, WM_PROTOCOLS, WM_DELETE_WINDOW, WM_NORMAL_HINTS);
|
let (wm_protocols, wm_delete_window, wm_normal_hints) =
|
||||||
|
intern_atoms!(&conn, WM_PROTOCOLS, WM_DELETE_WINDOW, WM_NORMAL_HINTS);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
conn,
|
conn,
|
||||||
xlib_display,
|
xlib_display,
|
||||||
|
|
||||||
atoms: Atoms {
|
atoms: Atoms { wm_protocols, wm_delete_window, wm_normal_hints },
|
||||||
wm_protocols,
|
|
||||||
wm_delete_window,
|
|
||||||
wm_normal_hints,
|
|
||||||
},
|
|
||||||
|
|
||||||
cursor_cache: HashMap::new()
|
cursor_cache: HashMap::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,10 +74,7 @@ impl XcbConnection {
|
||||||
if !rms.is_null() {
|
if !rms.is_null() {
|
||||||
let db = XrmGetStringDatabase(rms);
|
let db = XrmGetStringDatabase(rms);
|
||||||
if !db.is_null() {
|
if !db.is_null() {
|
||||||
let mut value = XrmValue {
|
let mut value = XrmValue { size: 0, addr: std::ptr::null_mut() };
|
||||||
size: 0,
|
|
||||||
addr: std::ptr::null_mut(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut value_type: *mut std::os::raw::c_char = std::ptr::null_mut();
|
let mut value_type: *mut std::os::raw::c_char = std::ptr::null_mut();
|
||||||
let name_c_str = CString::new("Xft.dpi").unwrap();
|
let name_c_str = CString::new("Xft.dpi").unwrap();
|
||||||
|
@ -144,16 +136,13 @@ impl XcbConnection {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_scaling(&self) -> Option<f64> {
|
pub fn get_scaling(&self) -> Option<f64> {
|
||||||
self.get_scaling_xft()
|
self.get_scaling_xft().or(self.get_scaling_screen_dimensions())
|
||||||
.or(self.get_scaling_screen_dimensions())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_cursor_xid(&mut self, cursor: MouseCursor) -> u32 {
|
pub fn get_cursor_xid(&mut self, cursor: MouseCursor) -> u32 {
|
||||||
let dpy = self.conn.get_raw_dpy();
|
let dpy = self.conn.get_raw_dpy();
|
||||||
|
|
||||||
*self.cursor_cache
|
*self.cursor_cache.entry(cursor).or_insert_with(|| cursor::get_xcursor(dpy, cursor))
|
||||||
.entry(cursor)
|
|
||||||
.or_insert_with(|| cursor::get_xcursor(dpy, cursor))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue