mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Sending key events through script task before processing them in the compositor.
Fixes #4163
This commit is contained in:
parent
f451005f4f
commit
b0552cb98e
10 changed files with 131 additions and 66 deletions
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use compositor_layer::{CompositorData, CompositorLayer, DoesntWantScrollEvents};
|
use compositor_layer::{CompositorData, CompositorLayer, DoesntWantScrollEvents};
|
||||||
use compositor_layer::{WantsScrollEvents};
|
use compositor_layer::{WantsScrollEvents};
|
||||||
|
use compositor_task;
|
||||||
use compositor_task::{ChangePageLoadData, ChangePageTitle, ChangePaintState, ChangeReadyState};
|
use compositor_task::{ChangePageLoadData, ChangePageTitle, ChangePaintState, ChangeReadyState};
|
||||||
use compositor_task::{CompositorEventListener, CompositorProxy, CompositorReceiver};
|
use compositor_task::{CompositorEventListener, CompositorProxy, CompositorReceiver};
|
||||||
use compositor_task::{CompositorTask, CreateOrUpdateDescendantLayer, CreateOrUpdateRootLayer};
|
use compositor_task::{CompositorTask, CreateOrUpdateDescendantLayer, CreateOrUpdateRootLayer};
|
||||||
|
@ -336,6 +337,10 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(compositor_task::KeyEvent(key, modified), NotShuttingDown) => {
|
||||||
|
self.window.handle_key(key, modified);
|
||||||
|
}
|
||||||
|
|
||||||
// When we are shutting_down, we need to avoid performing operations
|
// When we are shutting_down, we need to avoid performing operations
|
||||||
// such as Paint that may crash because we have begun tearing down
|
// such as Paint that may crash because we have begun tearing down
|
||||||
// the rest of our resources.
|
// the rest of our resources.
|
||||||
|
|
|
@ -20,6 +20,7 @@ use layers::layers::LayerBufferSet;
|
||||||
use servo_msg::compositor_msg::{Epoch, LayerId, LayerMetadata, ReadyState};
|
use servo_msg::compositor_msg::{Epoch, LayerId, LayerMetadata, ReadyState};
|
||||||
use servo_msg::compositor_msg::{PaintListener, PaintState, ScriptListener, ScrollPolicy};
|
use servo_msg::compositor_msg::{PaintListener, PaintState, ScriptListener, ScrollPolicy};
|
||||||
use servo_msg::constellation_msg::{ConstellationChan, LoadData, PipelineId};
|
use servo_msg::constellation_msg::{ConstellationChan, LoadData, PipelineId};
|
||||||
|
use servo_msg::constellation_msg::{Key, KeyState, KeyModifiers, Pressed};
|
||||||
use servo_util::memory::MemoryProfilerChan;
|
use servo_util::memory::MemoryProfilerChan;
|
||||||
use servo_util::time::TimeProfilerChan;
|
use servo_util::time::TimeProfilerChan;
|
||||||
use std::comm::{channel, Sender, Receiver};
|
use std::comm::{channel, Sender, Receiver};
|
||||||
|
@ -85,6 +86,12 @@ impl ScriptListener for Box<CompositorProxy+'static+Send> {
|
||||||
fn set_title(&mut self, pipeline_id: PipelineId, title: Option<String>) {
|
fn set_title(&mut self, pipeline_id: PipelineId, title: Option<String>) {
|
||||||
self.send(ChangePageTitle(pipeline_id, title))
|
self.send(ChangePageTitle(pipeline_id, title))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn send_key_event(&mut self, key: Key, state: KeyState, modifiers: KeyModifiers) {
|
||||||
|
if state == Pressed {
|
||||||
|
self.send(KeyEvent(key, modifiers));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information about each layer that the compositor keeps.
|
/// Information about each layer that the compositor keeps.
|
||||||
|
@ -204,6 +211,8 @@ pub enum Msg {
|
||||||
/// Indicates that the scrolling timeout with the given starting timestamp has happened and a
|
/// Indicates that the scrolling timeout with the given starting timestamp has happened and a
|
||||||
/// composite should happen. (See the `scrolling` module.)
|
/// composite should happen. (See the `scrolling` module.)
|
||||||
ScrollTimeout(u64),
|
ScrollTimeout(u64),
|
||||||
|
/// Sends an unconsumed key event back to the compositor.
|
||||||
|
KeyEvent(Key, KeyModifiers),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Show for Msg {
|
impl Show for Msg {
|
||||||
|
@ -226,6 +235,7 @@ impl Show for Msg {
|
||||||
FrameTreeUpdateMsg(..) => write!(f, "FrameTreeUpdateMsg"),
|
FrameTreeUpdateMsg(..) => write!(f, "FrameTreeUpdateMsg"),
|
||||||
LoadComplete => write!(f, "LoadComplete"),
|
LoadComplete => write!(f, "LoadComplete"),
|
||||||
ScrollTimeout(..) => write!(f, "ScrollTimeout"),
|
ScrollTimeout(..) => write!(f, "ScrollTimeout"),
|
||||||
|
KeyEvent(..) => write!(f, "KeyEvent"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use compositor_task::{GetGraphicsMetadata, CreateOrUpdateRootLayer, CreateOrUpda
|
||||||
use compositor_task::{Exit, ChangeReadyState, LoadComplete, Paint, ScrollFragmentPoint, SetIds};
|
use compositor_task::{Exit, ChangeReadyState, LoadComplete, Paint, ScrollFragmentPoint, SetIds};
|
||||||
use compositor_task::{SetLayerOrigin, ShutdownComplete, ChangePaintState, PaintMsgDiscarded};
|
use compositor_task::{SetLayerOrigin, ShutdownComplete, ChangePaintState, PaintMsgDiscarded};
|
||||||
use compositor_task::{CompositorEventListener, CompositorReceiver, ScrollTimeout, ChangePageTitle};
|
use compositor_task::{CompositorEventListener, CompositorReceiver, ScrollTimeout, ChangePageTitle};
|
||||||
use compositor_task::{ChangePageLoadData, FrameTreeUpdateMsg};
|
use compositor_task::{ChangePageLoadData, FrameTreeUpdateMsg, KeyEvent};
|
||||||
use windowing::WindowEvent;
|
use windowing::WindowEvent;
|
||||||
|
|
||||||
use geom::scale_factor::ScaleFactor;
|
use geom::scale_factor::ScaleFactor;
|
||||||
|
@ -106,7 +106,7 @@ impl CompositorEventListener for NullCompositor {
|
||||||
SetLayerOrigin(..) | Paint(..) |
|
SetLayerOrigin(..) | Paint(..) |
|
||||||
ChangeReadyState(..) | ChangePaintState(..) | ScrollFragmentPoint(..) |
|
ChangeReadyState(..) | ChangePaintState(..) | ScrollFragmentPoint(..) |
|
||||||
LoadComplete | PaintMsgDiscarded(..) | ScrollTimeout(..) | ChangePageTitle(..) |
|
LoadComplete | PaintMsgDiscarded(..) | ScrollTimeout(..) | ChangePageTitle(..) |
|
||||||
ChangePageLoadData(..) => ()
|
ChangePageLoadData(..) | KeyEvent(..) => ()
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,5 +123,7 @@ pub trait WindowMethods {
|
||||||
/// some type of platform-specific graphics context current. Returns true if the composite may
|
/// some type of platform-specific graphics context current. Returns true if the composite may
|
||||||
/// proceed and false if it should not.
|
/// proceed and false if it should not.
|
||||||
fn prepare_for_composite(&self) -> bool;
|
fn prepare_for_composite(&self) -> bool;
|
||||||
}
|
|
||||||
|
|
||||||
|
/// Process a key event.
|
||||||
|
fn handle_key(&self, key: Key, mods: KeyModifiers);
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use azure::azure_hl::Color;
|
use azure::azure_hl::Color;
|
||||||
|
use constellation_msg::{Key, KeyState, KeyModifiers};
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use layers::platform::surface::NativeGraphicsMetadata;
|
use layers::platform::surface::NativeGraphicsMetadata;
|
||||||
|
@ -115,4 +116,5 @@ pub trait ScriptListener {
|
||||||
fn set_title(&mut self, pipeline_id: PipelineId, new_title: Option<String>);
|
fn set_title(&mut self, pipeline_id: PipelineId, new_title: Option<String>);
|
||||||
fn close(&mut self);
|
fn close(&mut self);
|
||||||
fn dup(&mut self) -> Box<ScriptListener+'static>;
|
fn dup(&mut self) -> Box<ScriptListener+'static>;
|
||||||
|
fn send_key_event(&mut self, key: Key, state: KeyState, modifiers: KeyModifiers);
|
||||||
}
|
}
|
||||||
|
|
|
@ -505,11 +505,12 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLInputElement> {
|
||||||
} else if "keydown" == event.Type().as_slice() && !event.DefaultPrevented() &&
|
} else if "keydown" == event.Type().as_slice() && !event.DefaultPrevented() &&
|
||||||
(self.input_type.get() == InputText || self.input_type.get() == InputPassword) {
|
(self.input_type.get() == InputText || self.input_type.get() == InputPassword) {
|
||||||
let keyevent: Option<JSRef<KeyboardEvent>> = KeyboardEventCast::to_ref(event);
|
let keyevent: Option<JSRef<KeyboardEvent>> = KeyboardEventCast::to_ref(event);
|
||||||
keyevent.map(|event| {
|
keyevent.map(|keyevent| {
|
||||||
match self.textinput.borrow_mut().handle_keydown(event) {
|
match self.textinput.borrow_mut().handle_keydown(keyevent) {
|
||||||
TriggerDefaultAction => (),
|
TriggerDefaultAction => (),
|
||||||
DispatchInput => {
|
DispatchInput => {
|
||||||
self.force_relayout();
|
self.force_relayout();
|
||||||
|
event.PreventDefault();
|
||||||
}
|
}
|
||||||
Nothing => (),
|
Nothing => (),
|
||||||
}
|
}
|
||||||
|
|
|
@ -946,6 +946,10 @@ impl ScriptTask {
|
||||||
// TODO: if keypress event is canceled, prevent firing input events
|
// TODO: if keypress event is canceled, prevent firing input events
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !prevented {
|
||||||
|
self.compositor.borrow_mut().send_key_event(key, state, modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
// This behavior is unspecced
|
// This behavior is unspecced
|
||||||
// We are supposed to dispatch synthetic click activation for Space and/or Return,
|
// We are supposed to dispatch synthetic click activation for Space and/or Return,
|
||||||
// however *when* we do it is up to us
|
// however *when* we do it is up to us
|
||||||
|
|
|
@ -21,6 +21,7 @@ use gleam::gl;
|
||||||
use layers::geometry::DevicePixel;
|
use layers::geometry::DevicePixel;
|
||||||
use layers::platform::surface::NativeGraphicsMetadata;
|
use layers::platform::surface::NativeGraphicsMetadata;
|
||||||
use libc::{c_char, c_void};
|
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::{Blank, FinishedLoading, Loading, PerformingLayout, PaintState};
|
||||||
use servo_msg::compositor_msg::{ReadyState};
|
use servo_msg::compositor_msg::{ReadyState};
|
||||||
use servo_msg::constellation_msg::LoadData;
|
use servo_msg::constellation_msg::LoadData;
|
||||||
|
@ -260,6 +261,10 @@ impl WindowMethods for Window {
|
||||||
let frame = frame.downcast();
|
let frame = frame.downcast();
|
||||||
*frame.url.borrow_mut() = load_data.url.to_string()
|
*frame.url.borrow_mut() = load_data.url.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_key(&self, _: Key, _: KeyModifiers) {
|
||||||
|
// TODO(negge)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CefCompositorProxy {
|
struct CefCompositorProxy {
|
||||||
|
|
|
@ -26,6 +26,7 @@ use libc::c_int;
|
||||||
use msg::compositor_msg::{Blank, FinishedLoading, IdlePaintState, Loading, PaintState};
|
use msg::compositor_msg::{Blank, FinishedLoading, IdlePaintState, Loading, PaintState};
|
||||||
use msg::compositor_msg::{PaintingPaintState, PerformingLayout, ReadyState};
|
use msg::compositor_msg::{PaintingPaintState, PerformingLayout, ReadyState};
|
||||||
use msg::constellation_msg::{mod, LoadData};
|
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::cell::{Cell, RefCell};
|
||||||
use std::comm::Receiver;
|
use std::comm::Receiver;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -206,6 +207,35 @@ impl WindowMethods for Window {
|
||||||
box receiver as Box<CompositorReceiver>)
|
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 {
|
fn prepare_for_composite(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -221,9 +251,6 @@ impl Window {
|
||||||
fn handle_window_event(&self, window: &glfw::Window, event: glfw::WindowEvent) {
|
fn handle_window_event(&self, window: &glfw::Window, event: glfw::WindowEvent) {
|
||||||
match event {
|
match event {
|
||||||
glfw::KeyEvent(key, _, action, mods) => {
|
glfw::KeyEvent(key, _, action, mods) => {
|
||||||
if action == glfw::Press {
|
|
||||||
self.handle_key(key, mods);
|
|
||||||
}
|
|
||||||
let key = glfw_key_to_script_key(key);
|
let key = glfw_key_to_script_key(key);
|
||||||
let state = match action {
|
let state = match action {
|
||||||
glfw::Press => constellation_msg::Pressed,
|
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
|
/// Helper function to handle a click
|
||||||
fn handle_mouse(&self, button: glfw::MouseButton, action: glfw::Action, x: c_int, y: c_int) {
|
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
|
// FIXME(tkuehn): max pixel dist should be based on pixel density
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//! A windowing implementation using glutin.
|
//! A windowing implementation using glutin.
|
||||||
|
|
||||||
use compositing::compositor_task::{mod, CompositorProxy, CompositorReceiver};
|
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::{IdleWindowEvent, ResizeWindowEvent};
|
||||||
use compositing::windowing::{MouseWindowEventClass, MouseWindowMoveEventClass, ScrollWindowEvent};
|
use compositing::windowing::{MouseWindowEventClass, MouseWindowMoveEventClass, ScrollWindowEvent};
|
||||||
use compositing::windowing::{ZoomWindowEvent, PinchZoomWindowEvent, NavigationWindowEvent};
|
use compositing::windowing::{ZoomWindowEvent, PinchZoomWindowEvent, NavigationWindowEvent};
|
||||||
|
@ -17,6 +17,8 @@ use geom::scale_factor::ScaleFactor;
|
||||||
use geom::size::TypedSize2D;
|
use geom::size::TypedSize2D;
|
||||||
use layers::geometry::DevicePixel;
|
use layers::geometry::DevicePixel;
|
||||||
use layers::platform::surface::NativeGraphicsMetadata;
|
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::{IdlePaintState, PaintState, PaintingPaintState};
|
||||||
use msg::compositor_msg::{FinishedLoading, Blank, Loading, PerformingLayout, ReadyState};
|
use msg::compositor_msg::{FinishedLoading, Blank, Loading, PerformingLayout, ReadyState};
|
||||||
use msg::constellation_msg::LoadData;
|
use msg::constellation_msg::LoadData;
|
||||||
|
@ -253,6 +255,33 @@ impl WindowMethods for Window {
|
||||||
display: GetCurrentDisplay(),
|
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 {
|
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 {
|
impl Window {
|
||||||
fn handle_window_event(&self, event: glutin::Event) -> bool {
|
fn handle_window_event(&self, event: glutin::Event) -> bool {
|
||||||
match event {
|
match event {
|
||||||
|
@ -307,7 +363,16 @@ impl Window {
|
||||||
(_, glutin::RShift) => self.toggle_modifier(RIGHT_SHIFT),
|
(_, glutin::RShift) => self.toggle_modifier(RIGHT_SHIFT),
|
||||||
(_, glutin::LAlt) => self.toggle_modifier(LEFT_ALT),
|
(_, glutin::LAlt) => self.toggle_modifier(LEFT_ALT),
|
||||||
(_, glutin::RAlt) => self.toggle_modifier(RIGHT_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);
|
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
|
/// Helper function to handle a click
|
||||||
fn handle_mouse(&self, button: glutin::MouseButton, action: glutin::ElementState, x: int, y: int) {
|
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
|
// FIXME(tkuehn): max pixel dist should be based on pixel density
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue