Sending key events through script task before processing them in the compositor.

Fixes #4163
This commit is contained in:
Nathan E. Egge 2014-12-12 10:19:04 -05:00
parent f451005f4f
commit b0552cb98e
10 changed files with 131 additions and 66 deletions

View file

@ -21,6 +21,7 @@ use gleam::gl;
use layers::geometry::DevicePixel;
use layers::platform::surface::NativeGraphicsMetadata;
use libc::{c_char, c_void};
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;
@ -260,6 +261,10 @@ impl WindowMethods for Window {
let frame = frame.downcast();
*frame.url.borrow_mut() = load_data.url.to_string()
}
fn handle_key(&self, _: Key, _: KeyModifiers) {
// TODO(negge)
}
}
struct CefCompositorProxy {

View file

@ -26,6 +26,7 @@ use libc::c_int;
use msg::compositor_msg::{Blank, FinishedLoading, IdlePaintState, Loading, PaintState};
use msg::compositor_msg::{PaintingPaintState, PerformingLayout, ReadyState};
use msg::constellation_msg::{mod, LoadData};
use msg::constellation_msg::{Key, KeyModifiers, KeyEscape, KeyEqual, KeyMinus, KeyBackspace, KeyPageUp, KeyPageDown, CONTROL, SHIFT};
use std::cell::{Cell, RefCell};
use std::comm::Receiver;
use std::rc::Rc;
@ -206,6 +207,35 @@ impl WindowMethods for Window {
box receiver as Box<CompositorReceiver>)
}
/// Helper function to handle keyboard events.
fn handle_key(&self, key: Key, mods: KeyModifiers) {
match key {
KeyEscape => self.glfw_window.set_should_close(true),
KeyEqual if mods.contains(CONTROL) => { // Ctrl-+
self.event_queue.borrow_mut().push(ZoomWindowEvent(1.1));
}
KeyMinus if mods.contains(CONTROL) => { // Ctrl--
self.event_queue.borrow_mut().push(ZoomWindowEvent(1.0/1.1));
}
KeyBackspace if mods.contains(SHIFT) => { // Shift-Backspace
self.event_queue.borrow_mut().push(NavigationWindowEvent(Forward));
}
KeyBackspace => { // Backspace
self.event_queue.borrow_mut().push(NavigationWindowEvent(Back));
}
KeyPageDown => {
let (_, height) = self.glfw_window.get_size();
self.scroll_window(0.0, -height as f32);
}
KeyPageUp => {
let (_, height) = self.glfw_window.get_size();
self.scroll_window(0.0, height as f32);
}
_ => {}
}
}
fn prepare_for_composite(&self) -> bool {
true
}
@ -221,9 +251,6 @@ impl Window {
fn handle_window_event(&self, window: &glfw::Window, event: glfw::WindowEvent) {
match event {
glfw::KeyEvent(key, _, action, mods) => {
if action == glfw::Press {
self.handle_key(key, mods);
}
let key = glfw_key_to_script_key(key);
let state = match action {
glfw::Press => constellation_msg::Pressed,
@ -333,34 +360,6 @@ impl Window {
}
}
/// Helper function to handle keyboard events.
fn handle_key(&self, key: glfw::Key, mods: glfw::Modifiers) {
match key {
glfw::KeyEscape => self.glfw_window.set_should_close(true),
glfw::KeyEqual if mods.contains(glfw::Control) => { // Ctrl-+
self.event_queue.borrow_mut().push(ZoomWindowEvent(1.1));
}
glfw::KeyMinus if mods.contains(glfw::Control) => { // Ctrl--
self.event_queue.borrow_mut().push(ZoomWindowEvent(1.0/1.1));
}
glfw::KeyBackspace if mods.contains(glfw::Shift) => { // Shift-Backspace
self.event_queue.borrow_mut().push(NavigationWindowEvent(Forward));
}
glfw::KeyBackspace => { // Backspace
self.event_queue.borrow_mut().push(NavigationWindowEvent(Back));
}
glfw::KeyPageDown => {
let (_, height) = self.glfw_window.get_size();
self.scroll_window(0.0, -height as f32);
}
glfw::KeyPageUp => {
let (_, height) = self.glfw_window.get_size();
self.scroll_window(0.0, height as f32);
}
_ => {}
}
}
/// Helper function to handle a click
fn handle_mouse(&self, button: glfw::MouseButton, action: glfw::Action, x: c_int, y: c_int) {
// FIXME(tkuehn): max pixel dist should be based on pixel density

View file

@ -5,7 +5,7 @@
//! A windowing implementation using glutin.
use compositing::compositor_task::{mod, CompositorProxy, CompositorReceiver};
use compositing::windowing::{WindowEvent, WindowMethods};
use compositing::windowing::{WindowEvent, WindowMethods, KeyEvent};
use compositing::windowing::{IdleWindowEvent, ResizeWindowEvent};
use compositing::windowing::{MouseWindowEventClass, MouseWindowMoveEventClass, ScrollWindowEvent};
use compositing::windowing::{ZoomWindowEvent, PinchZoomWindowEvent, NavigationWindowEvent};
@ -17,6 +17,8 @@ use geom::scale_factor::ScaleFactor;
use geom::size::TypedSize2D;
use layers::geometry::DevicePixel;
use layers::platform::surface::NativeGraphicsMetadata;
use msg::constellation_msg;
use msg::constellation_msg::{Key, KeyEscape, KeyEqual, KeyMinus, KeyBackspace, KeyPageUp, KeyPageDown, CONTROL, SHIFT, ALT};
use msg::compositor_msg::{IdlePaintState, PaintState, PaintingPaintState};
use msg::compositor_msg::{FinishedLoading, Blank, Loading, PerformingLayout, ReadyState};
use msg::constellation_msg::LoadData;
@ -253,6 +255,33 @@ impl WindowMethods for Window {
display: GetCurrentDisplay(),
}
}
/// Helper function to handle keyboard events.
fn handle_key(&self, key: Key, mods: constellation_msg::KeyModifiers) {
match key {
// TODO(negge): handle window close event
KeyEscape => {},
KeyEqual if mods.contains(CONTROL) => { // Ctrl-+
self.event_queue.borrow_mut().push(ZoomWindowEvent(1.1));
}
KeyMinus if mods.contains(CONTROL) => { // Ctrl--
self.event_queue.borrow_mut().push(ZoomWindowEvent(1.0/1.1));
}
KeyBackspace if mods.contains(SHIFT) => { // Shift-Backspace
self.event_queue.borrow_mut().push(NavigationWindowEvent(Forward));
}
KeyBackspace => { // Backspace
self.event_queue.borrow_mut().push(NavigationWindowEvent(Back));
}
KeyPageDown => {
self.scroll_window(0.0, -self.framebuffer_size().as_f32().to_untyped().height);
}
KeyPageUp => {
self.scroll_window(0.0, self.framebuffer_size().as_f32().to_untyped().height);
}
_ => {}
}
}
}
impl Window {
@ -293,6 +322,33 @@ impl Window {
}
}
fn glutin_mods_to_script_mods(modifiers: KeyModifiers) -> constellation_msg::KeyModifiers {
let mut result = constellation_msg::KeyModifiers::from_bits(0).unwrap();
if modifiers.intersects(LEFT_SHIFT | RIGHT_SHIFT) {
result.insert(SHIFT);
}
if modifiers.intersects(LEFT_CONTROL | RIGHT_CONTROL) {
result.insert(CONTROL);
}
if modifiers.intersects(LEFT_ALT | RIGHT_ALT) {
result.insert(ALT);
}
result
}
fn glutin_key_to_script_key(key: glutin::VirtualKeyCode) -> Result<constellation_msg::Key, ()> {
// TODO(negge): add more key mappings
match key {
glutin::Escape => Ok(KeyEscape),
glutin::Equals => Ok(KeyEqual),
glutin::Minus => Ok(KeyMinus),
glutin::Back => Ok(KeyBackspace),
glutin::PageDown => Ok(KeyPageDown),
glutin::PageUp => Ok(KeyPageUp),
_ => Err(()),
}
}
impl Window {
fn handle_window_event(&self, event: glutin::Event) -> bool {
match event {
@ -307,7 +363,16 @@ impl Window {
(_, glutin::RShift) => self.toggle_modifier(RIGHT_SHIFT),
(_, glutin::LAlt) => self.toggle_modifier(LEFT_ALT),
(_, glutin::RAlt) => self.toggle_modifier(RIGHT_ALT),
(glutin::Pressed, key_code) => return self.handle_key(key_code),
(glutin::Pressed, key_code) => {
match glutin_key_to_script_key(key_code) {
Ok(key) => {
let state = constellation_msg::Pressed;
let modifiers = glutin_mods_to_script_mods(self.key_modifiers.get());
self.event_queue.borrow_mut().push(KeyEvent(key, state, modifiers));
}
_ => {}
}
}
(_, _) => {}
}
}
@ -371,34 +436,6 @@ impl Window {
self.event_queue.borrow_mut().push(event);
}
/// Helper function to handle keyboard events.
fn handle_key(&self, key: glutin::VirtualKeyCode) -> bool {
match key {
glutin::Escape => return true,
glutin::Equals if self.ctrl_pressed() => { // Ctrl-+
self.event_queue.borrow_mut().push(ZoomWindowEvent(1.1));
}
glutin::Minus if self.ctrl_pressed() => { // Ctrl--
self.event_queue.borrow_mut().push(ZoomWindowEvent(1.0/1.1));
}
glutin::Back if self.shift_pressed() => { // Shift-Backspace
self.event_queue.borrow_mut().push(NavigationWindowEvent(Forward));
}
glutin::Back => { // Backspace
self.event_queue.borrow_mut().push(NavigationWindowEvent(Back));
}
glutin::PageDown => {
self.scroll_window(0.0, -self.framebuffer_size().as_f32().to_untyped().height);
}
glutin::PageUp => {
self.scroll_window(0.0, self.framebuffer_size().as_f32().to_untyped().height);
}
_ => {}
}
false
}
/// Helper function to handle a click
fn handle_mouse(&self, button: glutin::MouseButton, action: glutin::ElementState, x: int, y: int) {
// FIXME(tkuehn): max pixel dist should be based on pixel density