Cleanup some previous merge errors
This commit is contained in:
parent
3cd40ef655
commit
f7d7acb3c5
5 changed files with 2 additions and 1298 deletions
149
src/platform_impl/macos/util/cursor.rs
Normal file
149
src/platform_impl/macos/util/cursor.rs
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
use cocoa::{
|
||||
appkit::NSImage, base::{id, nil, YES},
|
||||
foundation::{NSDictionary, NSPoint, NSString},
|
||||
};
|
||||
use objc::runtime::Sel;
|
||||
|
||||
use super::IntoOption;
|
||||
use MouseCursor;
|
||||
|
||||
pub enum Cursor {
|
||||
Native(&'static str),
|
||||
Undocumented(&'static str),
|
||||
WebKit(&'static str),
|
||||
}
|
||||
|
||||
impl From<MouseCursor> for Cursor {
|
||||
fn from(cursor: MouseCursor) -> Self {
|
||||
match cursor {
|
||||
MouseCursor::Arrow | MouseCursor::Default => Cursor::Native("arrowCursor"),
|
||||
MouseCursor::Hand => Cursor::Native("pointingHandCursor"),
|
||||
MouseCursor::Grabbing | MouseCursor::Grab => Cursor::Native("closedHandCursor"),
|
||||
MouseCursor::Text => Cursor::Native("IBeamCursor"),
|
||||
MouseCursor::VerticalText => Cursor::Native("IBeamCursorForVerticalLayout"),
|
||||
MouseCursor::Copy => Cursor::Native("dragCopyCursor"),
|
||||
MouseCursor::Alias => Cursor::Native("dragLinkCursor"),
|
||||
MouseCursor::NotAllowed | MouseCursor::NoDrop => Cursor::Native("operationNotAllowedCursor"),
|
||||
MouseCursor::ContextMenu => Cursor::Native("contextualMenuCursor"),
|
||||
MouseCursor::Crosshair => Cursor::Native("crosshairCursor"),
|
||||
MouseCursor::EResize => Cursor::Native("resizeRightCursor"),
|
||||
MouseCursor::NResize => Cursor::Native("resizeUpCursor"),
|
||||
MouseCursor::WResize => Cursor::Native("resizeLeftCursor"),
|
||||
MouseCursor::SResize => Cursor::Native("resizeDownCursor"),
|
||||
MouseCursor::EwResize | MouseCursor::ColResize => Cursor::Native("resizeLeftRightCursor"),
|
||||
MouseCursor::NsResize | MouseCursor::RowResize => Cursor::Native("resizeUpDownCursor"),
|
||||
|
||||
// Undocumented cursors: https://stackoverflow.com/a/46635398/5435443
|
||||
MouseCursor::Help => Cursor::Undocumented("_helpCursor"),
|
||||
MouseCursor::ZoomIn => Cursor::Undocumented("_zoomInCursor"),
|
||||
MouseCursor::ZoomOut => Cursor::Undocumented("_zoomOutCursor"),
|
||||
MouseCursor::NeResize => Cursor::Undocumented("_windowResizeNorthEastCursor"),
|
||||
MouseCursor::NwResize => Cursor::Undocumented("_windowResizeNorthWestCursor"),
|
||||
MouseCursor::SeResize => Cursor::Undocumented("_windowResizeSouthEastCursor"),
|
||||
MouseCursor::SwResize => Cursor::Undocumented("_windowResizeSouthWestCursor"),
|
||||
MouseCursor::NeswResize => Cursor::Undocumented("_windowResizeNorthEastSouthWestCursor"),
|
||||
MouseCursor::NwseResize => Cursor::Undocumented("_windowResizeNorthWestSouthEastCursor"),
|
||||
|
||||
// While these are available, the former just loads a white arrow,
|
||||
// and the latter loads an ugly deflated beachball!
|
||||
// MouseCursor::Move => Cursor::Undocumented("_moveCursor"),
|
||||
// MouseCursor::Wait => Cursor::Undocumented("_waitCursor"),
|
||||
|
||||
// An even more undocumented cursor...
|
||||
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=522349
|
||||
// This is the wrong semantics for `Wait`, but it's the same as
|
||||
// what's used in Safari and Chrome.
|
||||
MouseCursor::Wait | MouseCursor::Progress => Cursor::Undocumented("busyButClickableCursor"),
|
||||
|
||||
// For the rest, we can just snatch the cursors from WebKit...
|
||||
// They fit the style of the native cursors, and will seem
|
||||
// completely standard to macOS users.
|
||||
// https://stackoverflow.com/a/21786835/5435443
|
||||
MouseCursor::Move | MouseCursor::AllScroll => Cursor::WebKit("move"),
|
||||
MouseCursor::Cell => Cursor::WebKit("cell"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Cursor {
|
||||
fn default() -> Self {
|
||||
Cursor::Native("arrowCursor")
|
||||
}
|
||||
}
|
||||
|
||||
impl Cursor {
|
||||
pub unsafe fn load(&self) -> id {
|
||||
match self {
|
||||
Cursor::Native(cursor_name) => {
|
||||
let sel = Sel::register(cursor_name);
|
||||
msg_send![class!(NSCursor), performSelector:sel]
|
||||
},
|
||||
Cursor::Undocumented(cursor_name) => {
|
||||
let class = class!(NSCursor);
|
||||
let sel = Sel::register(cursor_name);
|
||||
let sel = if msg_send![class, respondsToSelector:sel] {
|
||||
sel
|
||||
} else {
|
||||
warn!("Cursor `{}` appears to be invalid", cursor_name);
|
||||
sel!(arrowCursor)
|
||||
};
|
||||
msg_send![class, performSelector:sel]
|
||||
},
|
||||
Cursor::WebKit(cursor_name) => load_webkit_cursor(cursor_name)
|
||||
.unwrap_or_else(|message| {
|
||||
warn!("{}", message);
|
||||
Self::default().load()
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Note that loading `busybutclickable` with this code won't animate the frames;
|
||||
// instead you'll just get them all in a column.
|
||||
unsafe fn load_webkit_cursor(cursor_name_str: &str) -> Result<id, String> {
|
||||
static CURSOR_ROOT: &'static str = "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/Resources/cursors";
|
||||
let cursor_root = NSString::alloc(nil).init_str(CURSOR_ROOT);
|
||||
let cursor_name = NSString::alloc(nil).init_str(cursor_name_str);
|
||||
let cursor_pdf = NSString::alloc(nil).init_str("cursor.pdf");
|
||||
let cursor_plist = NSString::alloc(nil).init_str("info.plist");
|
||||
let key_x = NSString::alloc(nil).init_str("hotx");
|
||||
let key_y = NSString::alloc(nil).init_str("hoty");
|
||||
|
||||
let cursor_path: id = msg_send![cursor_root,
|
||||
stringByAppendingPathComponent:cursor_name
|
||||
];
|
||||
let pdf_path: id = msg_send![cursor_path,
|
||||
stringByAppendingPathComponent:cursor_pdf
|
||||
];
|
||||
let info_path: id = msg_send![cursor_path,
|
||||
stringByAppendingPathComponent:cursor_plist
|
||||
];
|
||||
|
||||
let image = NSImage::alloc(nil)
|
||||
.initByReferencingFile_(pdf_path)
|
||||
// This will probably never be `None`, since images are loaded lazily...
|
||||
.into_option()
|
||||
// because of that, we need to check for validity.
|
||||
.filter(|image| image.isValid() == YES)
|
||||
.ok_or_else(||
|
||||
format!("Failed to read image for `{}` cursor", cursor_name_str)
|
||||
)?;
|
||||
let info = NSDictionary::dictionaryWithContentsOfFile_(nil, info_path)
|
||||
.into_option()
|
||||
.ok_or_else(||
|
||||
format!("Failed to read info for `{}` cursor", cursor_name_str)
|
||||
)?;
|
||||
let x = info.valueForKey_(key_x);
|
||||
let y = info.valueForKey_(key_y);
|
||||
let point = NSPoint::new(
|
||||
msg_send![x, doubleValue],
|
||||
msg_send![y, doubleValue],
|
||||
);
|
||||
let cursor: id = msg_send![class!(NSCursor), alloc];
|
||||
let cursor: id = msg_send![cursor, initWithImage:image hotSpot:point];
|
||||
cursor
|
||||
.into_option()
|
||||
.ok_or_else(||
|
||||
format!("Failed to initialize `{}` cursor", cursor_name_str)
|
||||
)
|
||||
}
|
||||
14
src/platform_impl/macos/util/into_option.rs
Normal file
14
src/platform_impl/macos/util/into_option.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
use cocoa::base::{id, nil};
|
||||
|
||||
pub trait IntoOption: Sized {
|
||||
fn into_option(self) -> Option<Self>;
|
||||
}
|
||||
|
||||
impl IntoOption for id {
|
||||
fn into_option(self) -> Option<Self> {
|
||||
match self != nil {
|
||||
true => Some(self),
|
||||
false => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,13 @@
|
|||
mod cursor;
|
||||
mod into_option;
|
||||
|
||||
pub use self::{cursor::Cursor, into_option::IntoOption};
|
||||
|
||||
use cocoa::appkit::NSWindowStyleMask;
|
||||
use cocoa::base::{id, nil};
|
||||
use cocoa::foundation::{NSRect, NSUInteger};
|
||||
use core_graphics::display::CGDisplay;
|
||||
use objc::runtime::{Class, Object};
|
||||
|
||||
use platform_impl::platform::ffi;
|
||||
use platform_impl::platform::window::IdRef;
|
||||
|
|
@ -25,6 +31,25 @@ pub unsafe fn set_style_mask(window: id, view: id, mask: NSWindowStyleMask) {
|
|||
window.makeFirstResponder_(view);
|
||||
}
|
||||
|
||||
pub unsafe fn toggle_style_mask(window: id, view: id, mask: NSWindowStyleMask, on: bool) {
|
||||
use cocoa::appkit::NSWindow;
|
||||
|
||||
let current_style_mask = window.styleMask();
|
||||
if on {
|
||||
window.setStyleMask_(current_style_mask | mask);
|
||||
} else {
|
||||
window.setStyleMask_(current_style_mask & (!mask));
|
||||
}
|
||||
|
||||
// If we don't do this, key handling will break. Therefore, never call `setStyleMask` directly!
|
||||
window.makeFirstResponder_(view);
|
||||
}
|
||||
|
||||
pub unsafe fn superclass<'a>(this: &'a Object) -> &'a Class {
|
||||
let superclass: id = msg_send![this, superclass];
|
||||
&*(superclass as *const _)
|
||||
}
|
||||
|
||||
pub unsafe fn create_input_context(view: id) -> IdRef {
|
||||
let input_context: id = msg_send![class!(NSTextInputContext), alloc];
|
||||
let input_context: id = msg_send![input_context, initWithClient:view];
|
||||
Loading…
Add table
Add a link
Reference in a new issue