mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
compositing: Implement cursor
per CSS3-UI § 8.1.1 in the CEF/Mac port.
I'm not sure how we want to handle Linux cursors, and GLFW has no ability to set cursors (short of disabling it and managing it yourself).
This commit is contained in:
parent
636641f905
commit
7371e0b8e3
23 changed files with 564 additions and 171 deletions
1
ports/cef/Cargo.lock
generated
1
ports/cef/Cargo.lock
generated
|
@ -469,6 +469,7 @@ dependencies = [
|
|||
"hyper 0.0.1 (git+https://github.com/servo/hyper?ref=servo)",
|
||||
"io_surface 0.1.0 (git+https://github.com/servo/rust-io-surface)",
|
||||
"layers 0.1.0 (git+https://github.com/servo/rust-layers)",
|
||||
"style 0.0.1",
|
||||
"url 0.1.0 (git+https://github.com/servo/rust-url)",
|
||||
"util 0.0.1",
|
||||
]
|
||||
|
|
|
@ -109,6 +109,13 @@ cef_class_impl! {
|
|||
}
|
||||
}
|
||||
|
||||
fn send_mouse_move_event(&_this, event: *const cef_mouse_event, _mouse_exited: c_int)
|
||||
-> () {
|
||||
let event: &cef_mouse_event = event;
|
||||
let point = TypedPoint2D((*event).x as f32, (*event).y as f32);
|
||||
core::send_window_event(WindowEvent::MouseWindowMoveEventClass(point))
|
||||
}
|
||||
|
||||
fn send_mouse_wheel_event(&_this,
|
||||
event: *const cef_mouse_event,
|
||||
delta_x: c_int,
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
use eutil::Downcast;
|
||||
use interfaces::CefBrowser;
|
||||
use render_handler::CefRenderHandlerExtensions;
|
||||
use types::cef_rect_t;
|
||||
use types::{cef_cursor_handle_t, cef_rect_t};
|
||||
use wrappers::Utf16Encoder;
|
||||
|
||||
use compositing::compositor_task::{mod, CompositorProxy, CompositorReceiver};
|
||||
|
@ -25,10 +25,22 @@ use servo_msg::constellation_msg::{Key, KeyModifiers};
|
|||
use servo_msg::compositor_msg::{Blank, FinishedLoading, Loading, PerformingLayout, PaintState};
|
||||
use servo_msg::compositor_msg::{ReadyState};
|
||||
use servo_msg::constellation_msg::LoadData;
|
||||
use servo_util::cursor::Cursor;
|
||||
use servo_util::geometry::ScreenPx;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
use servo_util::cursor::{AliasCursor, AllScrollCursor, ColResizeCursor, ContextMenuCursor};
|
||||
#[cfg(target_os="macos")]
|
||||
use servo_util::cursor::{CopyCursor, CrosshairCursor, EResizeCursor, EwResizeCursor};
|
||||
#[cfg(target_os="macos")]
|
||||
use servo_util::cursor::{GrabCursor, GrabbingCursor, NResizeCursor, NoCursor, NoDropCursor};
|
||||
#[cfg(target_os="macos")]
|
||||
use servo_util::cursor::{NsResizeCursor, NotAllowedCursor, PointerCursor, RowResizeCursor};
|
||||
#[cfg(target_os="macos")]
|
||||
use servo_util::cursor::{SResizeCursor, TextCursor, VerticalTextCursor, WResizeCursor};
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
use std::ptr;
|
||||
|
||||
|
@ -87,6 +99,42 @@ impl Window {
|
|||
pub fn wait_events(&self) -> WindowEvent {
|
||||
WindowEvent::Idle
|
||||
}
|
||||
|
||||
/// Returns the Cocoa cursor for a CSS cursor. These match Firefox, except where Firefox
|
||||
/// bundles custom resources (which we don't yet do).
|
||||
#[cfg(target_os="macos")]
|
||||
fn cursor_handle_for_cursor(&self, cursor: Cursor) -> cef_cursor_handle_t {
|
||||
use cocoa::base::{class, msg_send, selector};
|
||||
|
||||
let cocoa_name = match cursor {
|
||||
NoCursor => return 0 as cef_cursor_handle_t,
|
||||
ContextMenuCursor => "contextualMenuCursor",
|
||||
GrabbingCursor => "closedHandCursor",
|
||||
CrosshairCursor => "crosshairCursor",
|
||||
CopyCursor => "dragCopyCursor",
|
||||
AliasCursor => "dragLinkCursor",
|
||||
TextCursor => "IBeamCursor",
|
||||
GrabCursor | AllScrollCursor => "openHandCursor",
|
||||
NoDropCursor | NotAllowedCursor => "operationNotAllowedCursor",
|
||||
PointerCursor => "pointingHandCursor",
|
||||
SResizeCursor => "resizeDownCursor",
|
||||
WResizeCursor => "resizeLeftCursor",
|
||||
EwResizeCursor | ColResizeCursor => "resizeLeftRightCursor",
|
||||
EResizeCursor => "resizeRightCursor",
|
||||
NResizeCursor => "resizeUpCursor",
|
||||
NsResizeCursor | RowResizeCursor => "resizeUpDownCursor",
|
||||
VerticalTextCursor => "IBeamCursorForVerticalLayout",
|
||||
_ => "arrowCursor",
|
||||
};
|
||||
unsafe {
|
||||
msg_send()(class("NSCursor"), selector(cocoa_name))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os="macos"))]
|
||||
fn cursor_handle_for_cursor(&self, _: Cursor) -> cef_cursor_handle_t {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl WindowMethods for Window {
|
||||
|
@ -265,6 +313,20 @@ impl WindowMethods for Window {
|
|||
fn handle_key(&self, _: Key, _: KeyModifiers) {
|
||||
// TODO(negge)
|
||||
}
|
||||
|
||||
fn set_cursor(&self, cursor: Cursor) {
|
||||
let browser = self.cef_browser.borrow();
|
||||
match *browser {
|
||||
None => {}
|
||||
Some(ref browser) => {
|
||||
let cursor_handle = self.cursor_handle_for_cursor(cursor);
|
||||
browser.get_host()
|
||||
.get_client()
|
||||
.get_render_handler()
|
||||
.on_cursor_change(browser.clone(), cursor_handle)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CefCompositorProxy {
|
||||
|
|
|
@ -32,6 +32,7 @@ use std::comm::Receiver;
|
|||
use std::num::Float;
|
||||
use std::rc::Rc;
|
||||
use time::{mod, Timespec};
|
||||
use util::cursor::Cursor;
|
||||
use util::geometry::ScreenPx;
|
||||
|
||||
/// The type of a window.
|
||||
|
@ -241,6 +242,12 @@ impl WindowMethods for Window {
|
|||
true
|
||||
}
|
||||
|
||||
fn set_cursor(&self, _: Cursor) {
|
||||
// No-op. We could take over mouse handling ourselves and draw the cursor as an extra
|
||||
// layer with our own custom bitmaps or something, but it doesn't seem worth the
|
||||
// trouble.
|
||||
}
|
||||
|
||||
fn load_end(&self) {}
|
||||
|
||||
fn set_page_title(&self, _: Option<String>) {}
|
||||
|
@ -269,14 +276,7 @@ impl Window {
|
|||
self.event_queue.borrow_mut().push(Refresh);
|
||||
},
|
||||
glfw::MouseButtonEvent(button, action, _mods) => {
|
||||
let (x, y) = window.get_cursor_pos();
|
||||
//handle hidpi displays, since GLFW returns non-hi-def coordinates.
|
||||
let (backing_size, _) = window.get_framebuffer_size();
|
||||
let (window_size, _) = window.get_size();
|
||||
let hidpi = (backing_size as f32) / (window_size as f32);
|
||||
let x = x as f32 * hidpi;
|
||||
let y = y as f32 * hidpi;
|
||||
|
||||
let cursor_position = self.cursor_position();
|
||||
match button {
|
||||
glfw::MouseButton::Button5 => { // Back button (might be different per platform)
|
||||
self.event_queue.borrow_mut().push(Navigation(Back));
|
||||
|
@ -285,14 +285,18 @@ impl Window {
|
|||
self.event_queue.borrow_mut().push(Navigation(Forward));
|
||||
},
|
||||
glfw::MouseButtonLeft | glfw::MouseButtonRight => {
|
||||
self.handle_mouse(button, action, x as i32, y as i32);
|
||||
self.handle_mouse(button,
|
||||
action,
|
||||
cursor_position.x.get() as i32,
|
||||
cursor_position.y.get() as i32);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
},
|
||||
glfw::CursorPosEvent(xpos, ypos) => {
|
||||
self.event_queue.borrow_mut().push(
|
||||
MouseWindowMoveEventClass(TypedPoint2D(xpos as f32, ypos as f32)));
|
||||
glfw::CursorPosEvent(..) => {
|
||||
self.event_queue
|
||||
.borrow_mut()
|
||||
.push(MouseWindowMoveEventClass(self.cursor_position()));
|
||||
},
|
||||
glfw::ScrollEvent(xpos, ypos) => {
|
||||
match (window.get_key(glfw::Key::LeftControl),
|
||||
|
@ -393,6 +397,14 @@ impl Window {
|
|||
};
|
||||
self.event_queue.borrow_mut().push(MouseWindowEventClass(event));
|
||||
}
|
||||
|
||||
/// Returns the cursor position, properly accounting for HiDPI.
|
||||
fn cursor_position(&self) -> TypedPoint2D<DevicePixel,f32> {
|
||||
// Handle hidpi displays, since GLFW returns non-hi-def coordinates.
|
||||
let (x, y) = self.glfw_window.get_cursor_pos();
|
||||
let hidpi_factor = self.hidpi_factor();
|
||||
Point2D::from_untyped(&Point2D(x as f32, y as f32)) * hidpi_factor
|
||||
}
|
||||
}
|
||||
|
||||
struct GlfwCompositorProxy {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue