aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoe Wilm <jwilm@users.noreply.github.com>2017-07-20 10:50:50 -0700
committerGitHub <noreply@github.com>2017-07-20 10:50:50 -0700
commit8e7dd009a4335e6d6673c1aabb2b92d27f86155c (patch)
tree9e1dddb26693ea2085f700d43ae9bc2d800df52d /src
parentc8e4f366e740b98377bf6faf157af358b3bc70d2 (diff)
downloadalacritty-8e7dd009a4335e6d6673c1aabb2b92d27f86155c.tar.gz
alacritty-8e7dd009a4335e6d6673c1aabb2b92d27f86155c.zip
Update to latest Glutin/winit (#671)
* Update to latest Glutin/winit This *finally* gets us off the fork of Glutin we've been on for so long and will unblock a number of other items. Functionality should be the same as before. The update forced our hand on a compiler update. It's no longer feasible to pin on an old version. From now on, we require latest stable.
Diffstat (limited to 'src')
-rw-r--r--src/config.rs324
-rw-r--r--src/display.rs14
-rw-r--r--src/event.rs237
-rw-r--r--src/input.rs163
-rw-r--r--src/lib.rs1
-rw-r--r--src/window.rs130
6 files changed, 479 insertions, 390 deletions
diff --git a/src/config.rs b/src/config.rs
index e4f17ae7..59c675cd 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -21,6 +21,8 @@ use serde::de::Error as SerdeError;
use serde::de::{Visitor, MapVisitor, Unexpected};
use notify::{Watcher as WatcherApi, RecommendedWatcher as FileWatcher, op};
+use glutin::ModifiersState;
+
use input::{Action, Binding, MouseBinding, KeyBinding};
use index::{Line, Column};
@@ -297,10 +299,10 @@ impl Default for Config {
///
/// Our deserialize impl wouldn't be covered by a derive(Deserialize); see the
/// impl below.
-struct ModsWrapper(::glutin::Mods);
+struct ModsWrapper(ModifiersState);
impl ModsWrapper {
- fn into_inner(self) -> ::glutin::Mods {
+ fn into_inner(self) -> ModifiersState {
self.0
}
}
@@ -321,14 +323,13 @@ impl de::Deserialize for ModsWrapper {
fn visit_str<E>(self, value: &str) -> ::std::result::Result<ModsWrapper, E>
where E: de::Error,
{
- use ::glutin::{mods, Mods};
- let mut res = Mods::empty();
+ let mut res = ModifiersState::default();
for modifier in value.split('|') {
match modifier.trim() {
- "Command" | "Super" => res |= mods::SUPER,
- "Shift" => res |= mods::SHIFT,
- "Alt" | "Option" => res |= mods::ALT,
- "Control" => res |= mods::CONTROL,
+ "Command" | "Super" => res.logo = true,
+ "Shift" => res.shift = true,
+ "Alt" | "Option" => res.alt = true,
+ "Control" => res.ctrl = true,
_ => err_println!("unknown modifier {:?}", modifier),
}
}
@@ -482,7 +483,7 @@ impl de::Deserialize for MouseButton {
struct RawBinding {
key: Option<::glutin::VirtualKeyCode>,
mouse: Option<::glutin::MouseButton>,
- mods: ::glutin::Mods,
+ mods: ModifiersState,
mode: TermMode,
notmode: TermMode,
action: Action,
@@ -583,7 +584,7 @@ impl de::Deserialize for RawBinding {
) -> ::std::result::Result<RawBinding, V::Error>
where V: MapVisitor,
{
- let mut mods: Option<::glutin::Mods> = None;
+ let mut mods: Option<ModifiersState> = None;
let mut key: Option<::glutin::VirtualKeyCode> = None;
let mut chars: Option<String> = None;
let mut action: Option<::input::Action> = None;
@@ -670,7 +671,7 @@ impl de::Deserialize for RawBinding {
let mode = mode.unwrap_or_else(TermMode::empty);
let not_mode = not_mode.unwrap_or_else(TermMode::empty);
- let mods = mods.unwrap_or_else(::glutin::Mods::empty);
+ let mods = mods.unwrap_or_else(ModifiersState::default);
if mouse.is_none() && key.is_none() {
return Err(V::Error::custom("bindings require mouse button or key"));
@@ -1644,158 +1645,159 @@ enum Key {
impl Key {
fn to_glutin_key(&self) -> ::glutin::VirtualKeyCode {
+ use ::glutin::VirtualKeyCode::*;
// Thank you, vim macros!
match *self {
- Key::Key1 => ::glutin::VirtualKeyCode::Key1,
- Key::Key2 => ::glutin::VirtualKeyCode::Key2,
- Key::Key3 => ::glutin::VirtualKeyCode::Key3,
- Key::Key4 => ::glutin::VirtualKeyCode::Key4,
- Key::Key5 => ::glutin::VirtualKeyCode::Key5,
- Key::Key6 => ::glutin::VirtualKeyCode::Key6,
- Key::Key7 => ::glutin::VirtualKeyCode::Key7,
- Key::Key8 => ::glutin::VirtualKeyCode::Key8,
- Key::Key9 => ::glutin::VirtualKeyCode::Key9,
- Key::Key0 => ::glutin::VirtualKeyCode::Key0,
- Key::A => ::glutin::VirtualKeyCode::A,
- Key::B => ::glutin::VirtualKeyCode::B,
- Key::C => ::glutin::VirtualKeyCode::C,
- Key::D => ::glutin::VirtualKeyCode::D,
- Key::E => ::glutin::VirtualKeyCode::E,
- Key::F => ::glutin::VirtualKeyCode::F,
- Key::G => ::glutin::VirtualKeyCode::G,
- Key::H => ::glutin::VirtualKeyCode::H,
- Key::I => ::glutin::VirtualKeyCode::I,
- Key::J => ::glutin::VirtualKeyCode::J,
- Key::K => ::glutin::VirtualKeyCode::K,
- Key::L => ::glutin::VirtualKeyCode::L,
- Key::M => ::glutin::VirtualKeyCode::M,
- Key::N => ::glutin::VirtualKeyCode::N,
- Key::O => ::glutin::VirtualKeyCode::O,
- Key::P => ::glutin::VirtualKeyCode::P,
- Key::Q => ::glutin::VirtualKeyCode::Q,
- Key::R => ::glutin::VirtualKeyCode::R,
- Key::S => ::glutin::VirtualKeyCode::S,
- Key::T => ::glutin::VirtualKeyCode::T,
- Key::U => ::glutin::VirtualKeyCode::U,
- Key::V => ::glutin::VirtualKeyCode::V,
- Key::W => ::glutin::VirtualKeyCode::W,
- Key::X => ::glutin::VirtualKeyCode::X,
- Key::Y => ::glutin::VirtualKeyCode::Y,
- Key::Z => ::glutin::VirtualKeyCode::Z,
- Key::Escape => ::glutin::VirtualKeyCode::Escape,
- Key::F1 => ::glutin::VirtualKeyCode::F1,
- Key::F2 => ::glutin::VirtualKeyCode::F2,
- Key::F3 => ::glutin::VirtualKeyCode::F3,
- Key::F4 => ::glutin::VirtualKeyCode::F4,
- Key::F5 => ::glutin::VirtualKeyCode::F5,
- Key::F6 => ::glutin::VirtualKeyCode::F6,
- Key::F7 => ::glutin::VirtualKeyCode::F7,
- Key::F8 => ::glutin::VirtualKeyCode::F8,
- Key::F9 => ::glutin::VirtualKeyCode::F9,
- Key::F10 => ::glutin::VirtualKeyCode::F10,
- Key::F11 => ::glutin::VirtualKeyCode::F11,
- Key::F12 => ::glutin::VirtualKeyCode::F12,
- Key::F13 => ::glutin::VirtualKeyCode::F13,
- Key::F14 => ::glutin::VirtualKeyCode::F14,
- Key::F15 => ::glutin::VirtualKeyCode::F15,
- Key::Snapshot => ::glutin::VirtualKeyCode::Snapshot,
- Key::Scroll => ::glutin::VirtualKeyCode::Scroll,
- Key::Pause => ::glutin::VirtualKeyCode::Pause,
- Key::Insert => ::glutin::VirtualKeyCode::Insert,
- Key::Home => ::glutin::VirtualKeyCode::Home,
- Key::Delete => ::glutin::VirtualKeyCode::Delete,
- Key::End => ::glutin::VirtualKeyCode::End,
- Key::PageDown => ::glutin::VirtualKeyCode::PageDown,
- Key::PageUp => ::glutin::VirtualKeyCode::PageUp,
- Key::Left => ::glutin::VirtualKeyCode::Left,
- Key::Up => ::glutin::VirtualKeyCode::Up,
- Key::Right => ::glutin::VirtualKeyCode::Right,
- Key::Down => ::glutin::VirtualKeyCode::Down,
- Key::Back => ::glutin::VirtualKeyCode::Back,
- Key::Return => ::glutin::VirtualKeyCode::Return,
- Key::Space => ::glutin::VirtualKeyCode::Space,
- Key::Compose => ::glutin::VirtualKeyCode::Compose,
- Key::Numlock => ::glutin::VirtualKeyCode::Numlock,
- Key::Numpad0 => ::glutin::VirtualKeyCode::Numpad0,
- Key::Numpad1 => ::glutin::VirtualKeyCode::Numpad1,
- Key::Numpad2 => ::glutin::VirtualKeyCode::Numpad2,
- Key::Numpad3 => ::glutin::VirtualKeyCode::Numpad3,
- Key::Numpad4 => ::glutin::VirtualKeyCode::Numpad4,
- Key::Numpad5 => ::glutin::VirtualKeyCode::Numpad5,
- Key::Numpad6 => ::glutin::VirtualKeyCode::Numpad6,
- Key::Numpad7 => ::glutin::VirtualKeyCode::Numpad7,
- Key::Numpad8 => ::glutin::VirtualKeyCode::Numpad8,
- Key::Numpad9 => ::glutin::VirtualKeyCode::Numpad9,
- Key::AbntC1 => ::glutin::VirtualKeyCode::AbntC1,
- Key::AbntC2 => ::glutin::VirtualKeyCode::AbntC2,
- Key::Add => ::glutin::VirtualKeyCode::Add,
- Key::Apostrophe => ::glutin::VirtualKeyCode::Apostrophe,
- Key::Apps => ::glutin::VirtualKeyCode::Apps,
- Key::At => ::glutin::VirtualKeyCode::At,
- Key::Ax => ::glutin::VirtualKeyCode::Ax,
- Key::Backslash => ::glutin::VirtualKeyCode::Backslash,
- Key::Calculator => ::glutin::VirtualKeyCode::Calculator,
- Key::Capital => ::glutin::VirtualKeyCode::Capital,
- Key::Colon => ::glutin::VirtualKeyCode::Colon,
- Key::Comma => ::glutin::VirtualKeyCode::Comma,
- Key::Convert => ::glutin::VirtualKeyCode::Convert,
- Key::Decimal => ::glutin::VirtualKeyCode::Decimal,
- Key::Divide => ::glutin::VirtualKeyCode::Divide,
- Key::Equals => ::glutin::VirtualKeyCode::Equals,
- Key::Grave => ::glutin::VirtualKeyCode::Grave,
- Key::Kana => ::glutin::VirtualKeyCode::Kana,
- Key::Kanji => ::glutin::VirtualKeyCode::Kanji,
- Key::LAlt => ::glutin::VirtualKeyCode::LAlt,
- Key::LBracket => ::glutin::VirtualKeyCode::LBracket,
- Key::LControl => ::glutin::VirtualKeyCode::LControl,
- Key::LMenu => ::glutin::VirtualKeyCode::LMenu,
- Key::LShift => ::glutin::VirtualKeyCode::LShift,
- Key::LWin => ::glutin::VirtualKeyCode::LWin,
- Key::Mail => ::glutin::VirtualKeyCode::Mail,
- Key::MediaSelect => ::glutin::VirtualKeyCode::MediaSelect,
- Key::MediaStop => ::glutin::VirtualKeyCode::MediaStop,
- Key::Minus => ::glutin::VirtualKeyCode::Minus,
- Key::Multiply => ::glutin::VirtualKeyCode::Multiply,
- Key::Mute => ::glutin::VirtualKeyCode::Mute,
- Key::MyComputer => ::glutin::VirtualKeyCode::MyComputer,
- Key::NavigateForward => ::glutin::VirtualKeyCode::NavigateForward,
- Key::NavigateBackward => ::glutin::VirtualKeyCode::NavigateBackward,
- Key::NextTrack => ::glutin::VirtualKeyCode::NextTrack,
- Key::NoConvert => ::glutin::VirtualKeyCode::NoConvert,
- Key::NumpadComma => ::glutin::VirtualKeyCode::NumpadComma,
- Key::NumpadEnter => ::glutin::VirtualKeyCode::NumpadEnter,
- Key::NumpadEquals => ::glutin::VirtualKeyCode::NumpadEquals,
- Key::OEM102 => ::glutin::VirtualKeyCode::OEM102,
- Key::Period => ::glutin::VirtualKeyCode::Period,
- Key::PlayPause => ::glutin::VirtualKeyCode::PlayPause,
- Key::Power => ::glutin::VirtualKeyCode::Power,
- Key::PrevTrack => ::glutin::VirtualKeyCode::PrevTrack,
- Key::RAlt => ::glutin::VirtualKeyCode::RAlt,
- Key::RBracket => ::glutin::VirtualKeyCode::RBracket,
- Key::RControl => ::glutin::VirtualKeyCode::RControl,
- Key::RMenu => ::glutin::VirtualKeyCode::RMenu,
- Key::RShift => ::glutin::VirtualKeyCode::RShift,
- Key::RWin => ::glutin::VirtualKeyCode::RWin,
- Key::Semicolon => ::glutin::VirtualKeyCode::Semicolon,
- Key::Slash => ::glutin::VirtualKeyCode::Slash,
- Key::Sleep => ::glutin::VirtualKeyCode::Sleep,
- Key::Stop => ::glutin::VirtualKeyCode::Stop,
- Key::Subtract => ::glutin::VirtualKeyCode::Subtract,
- Key::Sysrq => ::glutin::VirtualKeyCode::Sysrq,
- Key::Tab => ::glutin::VirtualKeyCode::Tab,
- Key::Underline => ::glutin::VirtualKeyCode::Underline,
- Key::Unlabeled => ::glutin::VirtualKeyCode::Unlabeled,
- Key::VolumeDown => ::glutin::VirtualKeyCode::VolumeDown,
- Key::VolumeUp => ::glutin::VirtualKeyCode::VolumeUp,
- Key::Wake => ::glutin::VirtualKeyCode::Wake,
- Key::WebBack => ::glutin::VirtualKeyCode::WebBack,
- Key::WebFavorites => ::glutin::VirtualKeyCode::WebFavorites,
- Key::WebForward => ::glutin::VirtualKeyCode::WebForward,
- Key::WebHome => ::glutin::VirtualKeyCode::WebHome,
- Key::WebRefresh => ::glutin::VirtualKeyCode::WebRefresh,
- Key::WebSearch => ::glutin::VirtualKeyCode::WebSearch,
- Key::WebStop => ::glutin::VirtualKeyCode::WebStop,
- Key::Yen => ::glutin::VirtualKeyCode::Yen,
+ Key::Key1 => Key1,
+ Key::Key2 => Key2,
+ Key::Key3 => Key3,
+ Key::Key4 => Key4,
+ Key::Key5 => Key5,
+ Key::Key6 => Key6,
+ Key::Key7 => Key7,
+ Key::Key8 => Key8,
+ Key::Key9 => Key9,
+ Key::Key0 => Key0,
+ Key::A => A,
+ Key::B => B,
+ Key::C => C,
+ Key::D => D,
+ Key::E => E,
+ Key::F => F,
+ Key::G => G,
+ Key::H => H,
+ Key::I => I,
+ Key::J => J,
+ Key::K => K,
+ Key::L => L,
+ Key::M => M,
+ Key::N => N,
+ Key::O => O,
+ Key::P => P,
+ Key::Q => Q,
+ Key::R => R,
+ Key::S => S,
+ Key::T => T,
+ Key::U => U,
+ Key::V => V,
+ Key::W => W,
+ Key::X => X,
+ Key::Y => Y,
+ Key::Z => Z,
+ Key::Escape => Escape,
+ Key::F1 => F1,
+ Key::F2 => F2,
+ Key::F3 => F3,
+ Key::F4 => F4,
+ Key::F5 => F5,
+ Key::F6 => F6,
+ Key::F7 => F7,
+ Key::F8 => F8,
+ Key::F9 => F9,
+ Key::F10 => F10,
+ Key::F11 => F11,
+ Key::F12 => F12,
+ Key::F13 => F13,
+ Key::F14 => F14,
+ Key::F15 => F15,
+ Key::Snapshot => Snapshot,
+ Key::Scroll => Scroll,
+ Key::Pause => Pause,
+ Key::Insert => Insert,
+ Key::Home => Home,
+ Key::Delete => Delete,
+ Key::End => End,
+ Key::PageDown => PageDown,
+ Key::PageUp => PageUp,
+ Key::Left => Left,
+ Key::Up => Up,
+ Key::Right => Right,
+ Key::Down => Down,
+ Key::Back => Back,
+ Key::Return => Return,
+ Key::Space => Space,
+ Key::Compose => Compose,
+ Key::Numlock => Numlock,
+ Key::Numpad0 => Numpad0,
+ Key::Numpad1 => Numpad1,
+ Key::Numpad2 => Numpad2,
+ Key::Numpad3 => Numpad3,
+ Key::Numpad4 => Numpad4,
+ Key::Numpad5 => Numpad5,
+ Key::Numpad6 => Numpad6,
+ Key::Numpad7 => Numpad7,
+ Key::Numpad8 => Numpad8,
+ Key::Numpad9 => Numpad9,
+ Key::AbntC1 => AbntC1,
+ Key::AbntC2 => AbntC2,
+ Key::Add => Add,
+ Key::Apostrophe => Apostrophe,
+ Key::Apps => Apps,
+ Key::At => At,
+ Key::Ax => Ax,
+ Key::Backslash => Backslash,
+ Key::Calculator => Calculator,
+ Key::Capital => Capital,
+ Key::Colon => Colon,
+ Key::Comma => Comma,
+ Key::Convert => Convert,
+ Key::Decimal => Decimal,
+ Key::Divide => Divide,
+ Key::Equals => Equals,
+ Key::Grave => Grave,
+ Key::Kana => Kana,
+ Key::Kanji => Kanji,
+ Key::LAlt => LAlt,
+ Key::LBracket => LBracket,
+ Key::LControl => LControl,
+ Key::LMenu => LMenu,
+ Key::LShift => LShift,
+ Key::LWin => LWin,
+ Key::Mail => Mail,
+ Key::MediaSelect => MediaSelect,
+ Key::MediaStop => MediaStop,
+ Key::Minus => Minus,
+ Key::Multiply => Multiply,
+ Key::Mute => Mute,
+ Key::MyComputer => MyComputer,
+ Key::NavigateForward => NavigateForward,
+ Key::NavigateBackward => NavigateBackward,
+ Key::NextTrack => NextTrack,
+ Key::NoConvert => NoConvert,
+ Key::NumpadComma => NumpadComma,
+ Key::NumpadEnter => NumpadEnter,
+ Key::NumpadEquals => NumpadEquals,
+ Key::OEM102 => OEM102,
+ Key::Period => Period,
+ Key::PlayPause => PlayPause,
+ Key::Power => Power,
+ Key::PrevTrack => PrevTrack,
+ Key::RAlt => RAlt,
+ Key::RBracket => RBracket,
+ Key::RControl => RControl,
+ Key::RMenu => RMenu,
+ Key::RShift => RShift,
+ Key::RWin => RWin,
+ Key::Semicolon => Semicolon,
+ Key::Slash => Slash,
+ Key::Sleep => Sleep,
+ Key::Stop => Stop,
+ Key::Subtract => Subtract,
+ Key::Sysrq => Sysrq,
+ Key::Tab => Tab,
+ Key::Underline => Underline,
+ Key::Unlabeled => Unlabeled,
+ Key::VolumeDown => VolumeDown,
+ Key::VolumeUp => VolumeUp,
+ Key::Wake => Wake,
+ Key::WebBack => WebBack,
+ Key::WebFavorites => WebFavorites,
+ Key::WebForward => WebForward,
+ Key::WebHome => WebHome,
+ Key::WebRefresh => WebRefresh,
+ Key::WebSearch => WebSearch,
+ Key::WebStop => WebStop,
+ Key::Yen => Yen,
}
}
}
diff --git a/src/display.rs b/src/display.rs
index 00427e34..0f2c526f 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -211,7 +211,7 @@ impl Display {
// Clear screen
renderer.with_api(config, &size_info, 0. /* visual bell intensity */, |api| api.clear());
- let mut display = Display {
+ Ok(Display {
window: window,
renderer: renderer,
glyph_cache: glyph_cache,
@@ -220,16 +220,7 @@ impl Display {
rx: rx,
meter: Meter::new(),
size_info: size_info,
- };
-
- let resize_tx = display.resize_channel();
- let proxy = display.window.create_window_proxy();
- display.window.set_resize_callback(move |width, height| {
- let _ = resize_tx.send((width, height));
- proxy.wakeup_event_loop();
- });
-
- Ok(display)
+ })
}
#[inline]
@@ -267,6 +258,7 @@ impl Display {
item.on_resize(size)
}
+ self.window.resize(w, h);
self.renderer.resize(w as i32, h as i32);
}
diff --git a/src/event.rs b/src/event.rs
index 2987fce0..f91b3129 100644
--- a/src/event.rs
+++ b/src/event.rs
@@ -7,7 +7,7 @@ use std::time::{Instant};
use serde_json as json;
use parking_lot::MutexGuard;
-use glutin::{self, ElementState};
+use glutin::{self, ModifiersState, Event, ElementState};
use copypasta::{Clipboard, Load, Store};
use config::{self, Config};
@@ -37,6 +37,9 @@ pub struct ActionContext<'a, N: 'a> {
pub size_info: &'a SizeInfo,
pub mouse: &'a mut Mouse,
pub selection_modified: bool,
+ pub received_count: &'a mut usize,
+ pub suppress_chars: &'a mut bool,
+ pub last_modifiers: &'a mut ModifiersState,
}
impl<'a, N: Notify + 'a> input::ActionContext for ActionContext<'a, N> {
@@ -108,6 +111,21 @@ impl<'a, N: Notify + 'a> input::ActionContext for ActionContext<'a, N> {
fn mouse_mut(&mut self) -> &mut Mouse {
self.mouse
}
+
+ #[inline]
+ fn received_count(&mut self) -> &mut usize {
+ &mut self.received_count
+ }
+
+ #[inline]
+ fn suppress_chars(&mut self) -> &mut bool {
+ &mut self.suppress_chars
+ }
+
+ #[inline]
+ fn last_modifiers(&mut self) -> &mut ModifiersState {
+ &mut self.last_modifiers
+ }
}
pub enum ClickState {
@@ -164,6 +182,10 @@ pub struct Processor<N> {
pub selection: Option<Selection>,
hide_cursor_when_typing: bool,
hide_cursor: bool,
+ received_count: usize,
+ suppress_chars: bool,
+ last_modifiers: ModifiersState,
+ pending_events: Vec<Event>,
}
/// Notify that the terminal was resized
@@ -202,6 +224,10 @@ impl<N: Notify> Processor<N> {
size_info: size_info,
hide_cursor_when_typing: config.hide_cursor_when_typing(),
hide_cursor: false,
+ received_count: 0,
+ suppress_chars: false,
+ last_modifiers: Default::default(),
+ pending_events: Vec::with_capacity(4),
}
}
@@ -210,77 +236,95 @@ impl<N: Notify> Processor<N> {
/// Doesn't take self mutably due to borrow checking. Kinda uggo but w/e.
fn handle_event<'a>(
processor: &mut input::Processor<'a, ActionContext<'a, N>>,
- event: glutin::Event,
+ event: Event,
ref_test: bool,
resize_tx: &mpsc::Sender<(u32, u32)>,
hide_cursor: &mut bool,
) {
match event {
- glutin::Event::Closed => {
- if ref_test {
- // dump grid state
- let grid = processor.ctx.terminal.grid();
-
- let serialized_grid = json::to_string(&grid)
- .expect("serialize grid");
-
- let serialized_size = json::to_string(processor.ctx.terminal.size_info())
- .expect("serialize size");
-
- File::create("./grid.json")
- .and_then(|mut f| f.write_all(serialized_grid.as_bytes()))
- .expect("write grid.json");
-
- File::create("./size.json")
- .and_then(|mut f| f.write_all(serialized_size.as_bytes()))
- .expect("write size.json");
- }
-
- // FIXME should do a more graceful shutdown
- ::std::process::exit(0);
- },
- glutin::Event::Resized(w, h) => {
- resize_tx.send((w, h)).expect("send new size");
- processor.ctx.terminal.dirty = true;
- },
- glutin::Event::KeyboardInput(state, _code, key, mods, string) => {
- // Ensure that key event originates from our window. For example using a shortcut
- // to switch windows could generate a release key event.
- if state == ElementState::Pressed {
- *hide_cursor = true;
+ // Pass on device events
+ Event::DeviceEvent { .. } => (),
+ Event::WindowEvent { event, .. } => {
+ use glutin::WindowEvent::*;
+ match event {
+ Closed => {
+ if ref_test {
+ // dump grid state
+ let grid = processor.ctx.terminal.grid();
+
+ let serialized_grid = json::to_string(&grid)
+ .expect("serialize grid");
+
+ let serialized_size = json::to_string(processor.ctx.terminal.size_info())
+ .expect("serialize size");
+
+ File::create("./grid.json")
+ .and_then(|mut f| f.write_all(serialized_grid.as_bytes()))
+ .expect("write grid.json");
+
+ File::create("./size.json")
+ .and_then(|mut f| f.write_all(serialized_size.as_bytes()))
+ .expect("write size.json");
+ }
+
+ // FIXME should do a more graceful shutdown
+ ::std::process::exit(0);
+ },
+ Resized(w, h) => {
+ resize_tx.send((w, h)).expect("send new size");
+ processor.ctx.terminal.dirty = true;
+ },
+ KeyboardInput { input, .. } => {
+ let glutin::KeyboardInput { state, virtual_keycode, modifiers, .. } = input;
+ processor.process_key(state, virtual_keycode, &modifiers);
+ if state == ElementState::Pressed {
+ // Hide cursor while typing
+ *hide_cursor = true;
+ }
+ },
+ ReceivedCharacter(c) => {
+ processor.received_char(c);
+ },
+ MouseInput { state, button, .. } => {
+ *hide_cursor = false;
+ processor.mouse_input(state, button);
+ processor.ctx.terminal.dirty = true;
+ },
+ MouseMoved { position: (x, y), .. } => {
+ let x = x as i32;
+ let y = y as i32;
+ let x = limit(x, 0, processor.ctx.size_info.width as i32);
+ let y = limit(y, 0, processor.ctx.size_info.height as i32);
+
+ *hide_cursor = false;
+ processor.mouse_moved(x as u32, y as u32);
+
+ if !processor.ctx.selection.is_none() {
+ processor.ctx.terminal.dirty = true;
+ }
+ },
+ MouseWheel { delta, phase, .. } => {
+ *hide_cursor = false;
+ processor.on_mouse_wheel(delta, phase);
+ },
+ Refresh => {
+ processor.ctx.terminal.dirty = true;
+ },
+ Focused(is_focused) => {
+ if is_focused {
+ processor.ctx.terminal.dirty = true;
+ } else {
+ *hide_cursor = false;
+ }
+
+ processor.on_focus_change(is_focused);
+ }
+ _ => (),
}
- processor.process_key(state, key, mods, string);
- },
- glutin::Event::MouseInput(state, button) => {
- *hide_cursor = false;
- processor.mouse_input(state, button);
- processor.ctx.terminal.dirty = true;
},
- glutin::Event::MouseMoved(x, y) => {
- let x = limit(x, 0, processor.ctx.size_info.width as i32);
- let y = limit(y, 0, processor.ctx.size_info.height as i32);
-
- *hide_cursor = false;
- processor.mouse_moved(x as u32, y as u32);
- },
- glutin::Event::MouseWheel(scroll_delta, touch_phase) => {
- *hide_cursor = false;
- processor.on_mouse_wheel(scroll_delta, touch_phase);
- },
- glutin::Event::Refresh |
- glutin::Event::Awakened => {
+ Event::Awakened => {
processor.ctx.terminal.dirty = true;
- },
- glutin::Event::Focused(is_focused) => {
- if is_focused {
- processor.ctx.terminal.dirty = true;
- } else {
- *hide_cursor = false;
- }
-
- processor.on_focus_change(is_focused);
}
- _ => (),
}
}
@@ -296,32 +340,28 @@ impl<N: Notify> Processor<N> {
// be blocked the entire time we wait for input!
let mut terminal;
+ self.pending_events.clear();
+
{
// Ditto on lazy initialization for context and processor.
let context;
let mut processor: input::Processor<ActionContext<N>>;
- // Convenience macro which curries most arguments to handle_event.
- macro_rules! process {
- ($event:expr) => {
- if self.print_events {
- println!("glutin event: {:?}", $event);
- }
- Processor::handle_event(
- &mut processor,
- $event,
- self.ref_test,
- &self.resize_tx,
- &mut self.hide_cursor,
- )
- }
- }
+ let print_events = self.print_events;
- let event = if self.wait_for_event {
- window.wait_events().next()
- } else {
- None
- };
+ let ref_test = self.ref_test;
+ let resize_tx = &self.resize_tx;
+
+ if self.wait_for_event {
+ // A Vec is used here since wait_events can potentially yield
+ // multiple events before the interrupt is handled. For example,
+ // Resize and Moved events.
+ let pending_events = &mut self.pending_events;
+ window.wait_events(|e| {
+ pending_events.push(e);
+ glutin::ControlFlow::Break
+ });
+ }
terminal = term.lock();
@@ -332,21 +372,40 @@ impl<N: Notify> Processor<N> {
mouse: &mut self.mouse,
size_info: &self.size_info,
selection_modified: false,
+ received_count: &mut self.received_count,
+ suppress_chars: &mut self.suppress_chars,
+ last_modifiers: &mut self.last_modifiers,
};
processor = input::Processor {
ctx: context,
mouse_config: &self.mouse_config,
key_bindings: &self.key_bindings[..],
- mouse_bindings: &self.mouse_bindings[..]
+ mouse_bindings: &self.mouse_bindings[..],
};
- if let Some(event) = event {
- process!(event);
- }
+ // Scope needed to that hide_cursor isn't borrowed after the scope
+ // ends.
+ {
+ let hide_cursor = &mut self.hide_cursor;
+ let mut process = |event| {
+ if print_events {
+ println!("glutin event: {:?}", event);
+ }
+ Processor::handle_event(
+ &mut processor,
+ event,
+ ref_test,
+ resize_tx,
+ hide_cursor,
+ );
+ };
+
+ for event in self.pending_events.drain(..) {
+ process(event);
+ }
- for event in window.poll_events() {
- process!(event);
+ window.poll_events(process);
}
if self.hide_cursor_when_typing {
diff --git a/src/input.rs b/src/input.rs
index 468e9ef3..6e3d6d0d 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -24,9 +24,8 @@ use std::process::Command;
use std::time::Instant;
use copypasta::{Clipboard, Load, Buffer};
-use glutin::{ElementState, VirtualKeyCode, MouseButton};
-use glutin::{Mods, mods};
-use glutin::{TouchPhase, MouseScrollDelta};
+use glutin::{ElementState, VirtualKeyCode, MouseButton, TouchPhase, MouseScrollDelta};
+use glutin::ModifiersState;
use config;
use event::{ClickState, Mouse};
@@ -60,6 +59,9 @@ pub trait ActionContext {
fn line_selection(&mut self, point: Point);
fn mouse_mut(&mut self) -> &mut Mouse;
fn mouse_coords(&self) -> Option<Point>;
+ fn received_count(&mut self) -> &mut usize;
+ fn suppress_chars(&mut self) -> &mut bool;
+ fn last_modifiers(&mut self) -> &mut ModifiersState;
}
/// Describes a state and action to take in that state
@@ -68,7 +70,7 @@ pub trait ActionContext {
#[derive(Debug, Clone)]
pub struct Binding<T> {
/// Modifier keys required to activate binding
- pub mods: Mods,
+ pub mods: ModifiersState,
/// String to send to pty if mods and mode match
pub action: Action,
@@ -96,7 +98,7 @@ impl<T: Eq> Binding<T> {
fn is_triggered_by(
&self,
mode: TermMode,
- mods: &Mods,
+ mods: &ModifiersState,
input: &T
) -> bool {
// Check input first since bindings are stored in one big list. This is
@@ -126,9 +128,15 @@ impl<T> Binding<T> {
self.notmode.is_empty() || !mode.intersects(self.notmode)
}
+ /// Check that two mods descriptions for equivalence
+ ///
+ /// Optimized to use single check instead of four (one per modifier)
#[inline]
- fn mods_match(&self, mods: &Mods) -> bool {
- self.mods.is_all() || *mods == self.mods
+ fn mods_match(&self, mods: &ModifiersState) -> bool {
+ debug_assert!(4 == mem::size_of::<ModifiersState>());
+ unsafe {
+ mem::transmute_copy::<_, u32>(&self.mods) == mem::transmute_copy::<_, u32>(mods)
+ }
}
}
@@ -414,37 +422,52 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> {
return;
}
- self.process_mouse_bindings(mods::NONE, button);
+ self.process_mouse_bindings(&ModifiersState::default(), button);
}
+ /// Process key input
+ ///
+ /// If a keybinding was run, returns true. Otherwise returns false.
pub fn process_key(
&mut self,
state: ElementState,
key: Option<VirtualKeyCode>,
- mods: Mods,
- string: Option<String>,
+ mods: &ModifiersState,
) {
- if let Some(key) = key {
- // Ignore release events
- if state == ElementState::Released {
- return;
- }
+ match (key, state) {
+ (Some(key), ElementState::Pressed) => {
+ *self.ctx.last_modifiers() = *mods;
+ *self.ctx.received_count() = 0;
+ *self.ctx.suppress_chars() = false;
+
+ if self.process_key_bindings(&mods, key) {
+ *self.ctx.suppress_chars() = true;
+ }
+ },
+ (_, ElementState::Released) => *self.ctx.suppress_chars() = false,
+ _ => ()
+ }
+ }
- if self.process_key_bindings(mods, key) {
- return;
- }
+ /// Process a received character
+ pub fn received_char(&mut self, c: char) {
+ if !*self.ctx.suppress_chars() {
+ self.ctx.clear_selection();
- }
+ let utf8_len = c.len_utf8();
+ if *self.ctx.received_count() == 0 && self.ctx.last_modifiers().alt && utf8_len == 1 {
+ self.ctx.write_to_pty(b"\x1b".to_vec());
+ }
- // Didn't process a binding; print the provided character
- if let Some(mut string) = string {
- // from ST
- if string.len() == 1 && mods.contains(mods::ALT) {
- string.insert(0, '\x1b');
+ let mut bytes = Vec::with_capacity(utf8_len);
+ unsafe {
+ bytes.set_len(utf8_len);
+ c.encode_utf8(&mut bytes[..]);
}
- self.ctx.write_to_pty(string.into_bytes());
- self.ctx.clear_selection();
+ self.ctx.write_to_pty(bytes);
+
+ *self.ctx.received_count() += 1;
}
}
@@ -454,9 +477,9 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> {
/// for its action to be executed.
///
/// Returns true if an action is executed.
- fn process_key_bindings(&mut self, mods: Mods, key: VirtualKeyCode) -> bool {
+ fn process_key_bindings(&mut self, mods: &ModifiersState, key: VirtualKeyCode) -> bool {
for binding in self.key_bindings {
- if binding.is_triggered_by(self.ctx.terminal_mode(), &mods, &key) {
+ if binding.is_triggered_by(self.ctx.terminal_mode(), mods, &key) {
// binding was triggered; run the action
binding.execute(&mut self.ctx);
return true;
@@ -472,9 +495,9 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> {
/// for its action to be executed.
///
/// Returns true if an action is executed.
- fn process_mouse_bindings(&mut self, mods: Mods, button: MouseButton) -> bool {
+ fn process_mouse_bindings(&mut self, mods: &ModifiersState, button: MouseButton) -> bool {
for binding in self.mouse_bindings {
- if binding.is_triggered_by(self.ctx.terminal_mode(), &mods, &button) {
+ if binding.is_triggered_by(self.ctx.terminal_mode(), mods, &button) {
// binding was triggered; run the action
binding.execute(&mut self.ctx);
return true;
@@ -490,7 +513,7 @@ mod tests {
use std::borrow::Cow;
use std::time::Duration;
- use glutin::{mods, VirtualKeyCode, Event, ElementState, MouseButton};
+ use glutin::{VirtualKeyCode, Event, WindowEvent, ElementState, MouseButton, ModifiersState};
use term::{SizeInfo, Term, TermMode, mode};
use event::{Mouse, ClickState};
@@ -515,6 +538,9 @@ mod tests {
pub size_info: &'a SizeInfo,
pub mouse: &'a mut Mouse,
pub last_action: MultiClick,
+ pub received_count: usize,
+ pub suppress_chars: bool,
+ pub last_modifiers: ModifiersState,
}
impl <'a>super::ActionContext for ActionContext<'a> {
@@ -555,6 +581,15 @@ mod tests {
fn mouse_mut(&mut self) -> &mut Mouse {
self.mouse
}
+ fn received_count(&mut self) -> &mut usize {
+ &mut self.received_count
+ }
+ fn suppress_chars(&mut self) -> &mut bool {
+ &mut self.suppress_chars
+ }
+ fn last_modifiers(&mut self) -> &mut ModifiersState {
+ &mut self.last_modifiers
+ }
}
macro_rules! test_clickstate {
@@ -590,6 +625,9 @@ mod tests {
mouse: &mut mouse,
size_info: &size,
last_action: MultiClick::None,
+ received_count: 0,
+ suppress_chars: false,
+ last_modifiers: ModifiersState::default(),
};
let mut processor = Processor {
@@ -606,8 +644,8 @@ mod tests {
mouse_bindings: &config.mouse_bindings()[..],
};
- if let Event::MouseInput(state, input) = $input {
- processor.mouse_input(state, input);
+ if let Event::WindowEvent { event: WindowEvent::MouseInput { state, button, .. }, .. } = $input {
+ processor.mouse_input(state, button);
};
assert!(match mouse.click_state {
@@ -640,7 +678,14 @@ mod tests {
test_clickstate! {
name: single_click,
initial_state: ClickState::None,
- input: Event::MouseInput(ElementState::Pressed, MouseButton::Left),
+ input: Event::WindowEvent {
+ event: WindowEvent::MouseInput {
+ state: ElementState::Pressed,
+ button: MouseButton::Left,
+ device_id: unsafe { ::std::mem::transmute_copy(&0) },
+ },
+ window_id: unsafe { ::std::mem::transmute_copy(&0) },
+ },
end_state: ClickState::Click,
last_action: MultiClick::None
}
@@ -648,7 +693,14 @@ mod tests {
test_clickstate! {
name: double_click,
initial_state: ClickState::Click,
- input: Event::MouseInput(ElementState::Pressed, MouseButton::Left),
+ input: Event::WindowEvent {
+ event: WindowEvent::MouseInput {
+ state: ElementState::Pressed,
+ button: MouseButton::Left,
+ device_id: unsafe { ::std::mem::transmute_copy(&0) },
+ },
+ window_id: unsafe { ::std::mem::transmute_copy(&0) },
+ },
end_state: ClickState::DoubleClick,
last_action: MultiClick::DoubleClick
}
@@ -656,72 +708,79 @@ mod tests {
test_clickstate! {
name: triple_click,
initial_state: ClickState::DoubleClick,
- input: Event::MouseInput(ElementState::Pressed, MouseButton::Left),
+ input: Event::WindowEvent {
+ event: WindowEvent::MouseInput {
+ state: ElementState::Pressed,
+ button: MouseButton::Left,
+ device_id: unsafe { ::std::mem::transmute_copy(&0) },
+ },
+ window_id: unsafe { ::std::mem::transmute_copy(&0) },
+ },
end_state: ClickState::TripleClick,
last_action: MultiClick::TripleClick
}
test_process_binding! {
name: process_binding_nomode_shiftmod_require_shift,
- binding: Binding { trigger: KEY, mods: mods::SHIFT, action: Action::from("\x1b[1;2D"), mode: mode::NONE, notmode: mode::NONE },
+ binding: Binding { trigger: KEY, mods: ModifiersState { shift: true, ctrl: false, alt: false, logo: false }, action: Action::from("\x1b[1;2D"), mode: mode::NONE, notmode: mode::NONE },
triggers: true,
mode: mode::NONE,
- mods: mods::SHIFT
+ mods: ModifiersState { shift: true, ctrl: false, alt: false, logo: false }
}
test_process_binding! {
name: process_binding_nomode_nomod_require_shift,
- binding: Binding { trigger: KEY, mods: mods::SHIFT, action: Action::from("\x1b[1;2D"), mode: mode::NONE, notmode: mode::NONE },
+ binding: Binding { trigger: KEY, mods: ModifiersState { shift: true, ctrl: false, alt: false, logo: false }, action: Action::from("\x1b[1;2D"), mode: mode::NONE, notmode: mode::NONE },
triggers: false,
mode: mode::NONE,
- mods: mods::NONE
+ mods: ModifiersState { shift: false, ctrl: false, alt: false, logo: false }
}
test_process_binding! {
name: process_binding_nomode_controlmod,
- binding: Binding { trigger: KEY, mods: mods::CONTROL, action: Action::from("\x1b[1;5D"), mode: mode::NONE, notmode: mode::NONE },
+ binding: Binding { trigger: KEY, mods: ModifiersState { ctrl: true, shift: false, alt: false, logo: false }, action: Action::from("\x1b[1;5D"), mode: mode::NONE, notmode: mode::NONE },
triggers: true,
mode: mode::NONE,
- mods: mods::CONTROL
+ mods: ModifiersState { ctrl: true, shift: false, alt: false, logo: false }
}
test_process_binding! {
name: process_binding_nomode_nomod_require_not_appcursor,
- binding: Binding { trigger: KEY, mods: mods::ANY, action: Action::from("\x1b[D"), mode: mode::NONE, notmode: mode::APP_CURSOR },
+ binding: Binding { trigger: KEY, mods: ModifiersState { shift: false, ctrl: false, alt: false, logo: false }, action: Action::from("\x1b[D"), mode: mode::NONE, notmode: mode::APP_CURSOR },
triggers: true,
mode: mode::NONE,
- mods: mods::NONE
+ mods: ModifiersState { shift: false, ctrl: false, alt: false, logo: false }
}
test_process_binding! {
name: process_binding_appcursormode_nomod_require_appcursor,
- binding: Binding { trigger: KEY, mods: mods::ANY, action: Action::from("\x1bOD"), mode: mode::APP_CURSOR, notmode: mode::NONE },
+ binding: Binding { trigger: KEY, mods: ModifiersState { shift: false, ctrl: false, alt: false, logo: false }, action: Action::from("\x1bOD"), mode: mode::APP_CURSOR, notmode: mode::NONE },
triggers: true,
mode: mode::APP_CURSOR,
- mods: mods::NONE
+ mods: ModifiersState { shift: false, ctrl: false, alt: false, logo: false }
}
test_process_binding! {
name: process_binding_nomode_nomod_require_appcursor,
- binding: Binding { trigger: KEY, mods: mods::ANY, action: Action::from("\x1bOD"), mode: mode::APP_CURSOR, notmode: mode::NONE },
+ binding: Binding { trigger: KEY, mods: ModifiersState { shift: false, ctrl: false, alt: false, logo: false }, action: Action::from("\x1bOD"), mode: mode::APP_CURSOR, notmode: mode::NONE },
triggers: false,
mode: mode::NONE,
- mods: mods::NONE
+ mods: ModifiersState { shift: false, ctrl: false, alt: false, logo: false }
}
test_process_binding! {
name: process_binding_appcursormode_appkeypadmode_nomod_require_appcursor,
- binding: Binding { trigger: KEY, mods: mods::ANY, action: Action::from("\x1bOD"), mode: mode::APP_CURSOR, notmode: mode::NONE },
+ binding: Binding { trigger: KEY, mods: ModifiersState { shift: false, ctrl: false, alt: false, logo: false }, action: Action::from("\x1bOD"), mode: mode::APP_CURSOR, notmode: mode::NONE },
triggers: true,
mode: mode::APP_CURSOR | mode::APP_KEYPAD,
- mods: mods::NONE
+ mods: ModifiersState { shift: false, ctrl: false, alt: false, logo: false }
}
test_process_binding! {
name: process_binding_fail_with_extra_mods,
- binding: Binding { trigger: KEY, mods: mods::SUPER, action: Action::from("arst"), mode: mode::NONE, notmode: mode::NONE },
+ binding: Binding { trigger: KEY, mods: ModifiersState { shift: false, ctrl: false, alt: false, logo: true }, action: Action::from("arst"), mode: mode::NONE, notmode: mode::NONE },
triggers: false,
mode: mode::NONE,
- mods: mods::SUPER | mods::ALT
+ mods: ModifiersState { shift: false, ctrl: false, alt: true, logo: true }
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 684e89af..90f4aa5d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -24,7 +24,6 @@
#[macro_use] extern crate bitflags;
#[macro_use] extern crate clap;
-#[macro_use] extern crate lazy_static;
#[macro_use] extern crate log;
#[macro_use] extern crate serde_derive;
diff --git a/src/window.rs b/src/window.rs
index d0a51e6b..4fbe8631 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -14,32 +14,16 @@
use std::convert::From;
use std::fmt::{self, Display};
use std::ops::Deref;
-use std::sync::Mutex;
use gl;
-use glutin;
-
-/// Resize handling for Mac and maybe other platforms
-///
-/// This delegates to a statically referenced closure for convenience. The
-/// C-style callback doesn't receive a pointer or anything, so we are forced to
-/// use static storage.
-///
-/// This will fail horribly if more than one window is created. Don't do that :)
-fn window_resize_handler(width: u32, height: u32) {
- RESIZE_CALLBACK.lock().unwrap().as_ref().map(|func| (*func)(width, height));
-}
-
-lazy_static! {
- /// The resize callback invoked by `window_resize_handler`
- static ref RESIZE_CALLBACK: Mutex<Option<Box<Fn(u32, u32) + 'static + Send>>> = Mutex::new(None);
-}
+use glutin::{self, EventsLoop, WindowBuilder, Event, CursorState, ControlFlow, ContextBuilder};
+use glutin::GlContext;
/// Window errors
#[derive(Debug)]
pub enum Error {
/// Error creating the window
- Creation(glutin::CreationError),
+ ContextCreation(glutin::CreationError),
/// Error manipulating the rendering context
Context(glutin::ContextError),
@@ -52,13 +36,14 @@ type Result<T> = ::std::result::Result<T, Error>;
///
/// Wraps the underlying windowing library to provide a stable API in Alacritty
pub struct Window {
- glutin_window: glutin::Window,
+ event_loop: EventsLoop,
+ window: glutin::GlWindow,
cursor_visible: bool,
}
/// Threadsafe APIs for the window
pub struct Proxy {
- inner: glutin::WindowProxy,
+ inner: glutin::EventsLoopProxy,
}
/// Information about where the window is being displayed
@@ -152,14 +137,14 @@ impl<T: Display> Display for Points<T> {
impl ::std::error::Error for Error {
fn cause(&self) -> Option<&::std::error::Error> {
match *self {
- Error::Creation(ref err) => Some(err),
+ Error::ContextCreation(ref err) => Some(err),
Error::Context(ref err) => Some(err),
}
}
fn description(&self) -> &str {
match *self {
- Error::Creation(ref _err) => "Error creating glutin Window",
+ Error::ContextCreation(ref _err) => "Error creating gl context",
Error::Context(ref _err) => "Error operating on render context",
}
}
@@ -168,8 +153,8 @@ impl ::std::error::Error for Error {
impl Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
- Error::Creation(ref err) => {
- write!(f, "Error creating glutin::Window; {}", err)
+ Error::ContextCreation(ref err) => {
+ write!(f, "Error creating GL context; {}", err)
},
Error::Context(ref err) => {
write!(f, "Error operating on render context; {}", err)
@@ -180,7 +165,7 @@ impl Display for Error {
impl From<glutin::CreationError> for Error {
fn from(val: glutin::CreationError) -> Error {
- Error::Creation(val)
+ Error::ContextCreation(val)
}
}
@@ -197,28 +182,24 @@ impl Window {
pub fn new(
title: &str
) -> Result<Window> {
- /// Create a glutin::Window
- let mut window = glutin::WindowBuilder::new()
- .with_vsync()
- .with_title(title)
- .build()?;
-
- /// Set the glutin window resize callback for *this* window. The
- /// function pointer must be a C-style callback. This sets such a
- /// callback which simply delegates to a statically referenced Rust
- /// closure.
- window.set_window_resize_callback(Some(window_resize_handler as fn(u32, u32)));
+ let event_loop = EventsLoop::new();
+ let window = WindowBuilder::new()
+ .with_title(title);
+ let context = ContextBuilder::new()
+ .with_vsync(true);
+ let window = ::glutin::GlWindow::new(window, context, &event_loop)?;
/// Set OpenGL symbol loader
gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
- /// Make the window's context current so OpenGL operations can run
+ /// Make the context current so OpenGL operations can run
unsafe {
window.make_current()?;
}
let window = Window {
- glutin_window: window,
+ event_loop: event_loop,
+ window: window,
cursor_visible: true,
};
@@ -233,74 +214,71 @@ impl Window {
/// rasterization depend on DPI and scale factor.
pub fn device_properties(&self) -> DeviceProperties {
DeviceProperties {
- scale_factor: self.glutin_window.hidpi_factor(),
+ scale_factor: self.window.hidpi_factor(),
}
}
- /// Set the window resize callback
- ///
- /// Pass a `move` closure which will be called with the new width and height
- /// when the window is resized. According to the glutin docs, this can be
- /// used to draw during resizing.
- ///
- /// This method takes self mutably to ensure there's no race condition
- /// setting the callback.
- pub fn set_resize_callback<F: Fn(u32, u32) + 'static + Send>(&mut self, func: F) {
- let mut guard = RESIZE_CALLBACK.lock().unwrap();
- *guard = Some(Box::new(func));
- }
-
pub fn inner_size_pixels(&self) -> Option<Size<Pixels<u32>>> {
- self.glutin_window
+ self.window
.get_inner_size_pixels()
.map(|(w, h)| Size { width: Pixels(w), height: Pixels(h) })
}
#[inline]
pub fn hidpi_factor(&self) -> f32 {
- self.glutin_window.hidpi_factor()
+ self.window.hidpi_factor()
}
#[inline]
pub fn create_window_proxy(&self) -> Proxy {
Proxy {
- inner: self.glutin_window.create_window_proxy(),
+ inner: self.event_loop.create_proxy(),
}
}
#[inline]
pub fn swap_buffers(&self) -> Result<()> {
- self.glutin_window
+ self.window
.swap_buffers()
.map_err(From::from)
}
/// Poll for any available events
#[inline]
- pub fn poll_events(&self) -> glutin::PollEventsIterator {
- self.glutin_window.poll_events()
+ pub fn poll_events<F>(&mut self, func: F)
+ where F: FnMut(Event)
+ {
+ self.event_loop.poll_events(func);
+ }
+
+ #[inline]
+ pub fn resize(&self, width: u32, height: u32) {
+ self.window.resize(width, height);
}
/// Block waiting for events
- ///
- /// FIXME should return our own type
#[inline]
- pub fn wait_events(&self) -> glutin::WaitEventsIterator {
- self.glutin_window.wait_events()
+ pub fn wait_events<F>(&mut self, func: F)
+ where F: FnMut(Event) -> ControlFlow
+ {
+ self.event_loop.run_forever(func);
}
/// Set the window title
#[inline]
pub fn set_title(&self, title: &str) {
- self.glutin_window.set_title(title);
+ self.window.set_title(title);
}
/// Set cursor visible
pub fn set_cursor_visible(&mut self, visible: bool) {
if visible != self.cursor_visible {
self.cursor_visible = visible;
- self.glutin_window.set_cursor_state(if visible { glutin::CursorState::Normal }
- else { glutin::CursorState::Hide }).unwrap();
+ self.window.set_cursor_state(if visible {
+ CursorState::Normal
+ } else {
+ CursorState::Hide
+ }).unwrap();
}
}
@@ -308,7 +286,7 @@ impl Window {
pub fn get_window_id(&self) -> Option<usize> {
use glutin::os::unix::WindowExt;
- match self.glutin_window.get_xlib_window() {
+ match self.window.get_xlib_window() {
Some(xlib_window) => Some(xlib_window as usize),
None => None
}
@@ -330,14 +308,14 @@ impl OsExtensions for Window { }
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os="dragonfly", target_os="openbsd"))]
impl OsExtensions for Window {
fn run_os_extensions(&self) {
- use ::glutin::os::unix::WindowExt;
- use ::x11_dl::xlib::{self, XA_CARDINAL, PropModeReplace};
- use ::std::ffi::{CStr};
- use ::std::ptr;
- use ::libc::getpid;
+ use glutin::os::unix::WindowExt;
+ use x11_dl::xlib::{self, XA_CARDINAL, PropModeReplace};
+ use std::ffi::{CStr};
+ use std::ptr;
+ use libc::getpid;
- let xlib_display = self.glutin_window.get_xlib_display();
- let xlib_window = self.glutin_window.get_xlib_window();
+ let xlib_display = self.window.get_xlib_display();
+ let xlib_window = self.window.get_xlib_window();
if let (Some(xlib_window), Some(xlib_display)) = (xlib_window, xlib_display) {
let xlib = xlib::Xlib::open().expect("get xlib");
@@ -370,7 +348,7 @@ impl Proxy {
/// This is useful for triggering a draw when the renderer would otherwise
/// be waiting on user input.
pub fn wakeup_event_loop(&self) {
- self.inner.wakeup_event_loop();
+ self.inner.wakeup().unwrap();
}
}
@@ -381,6 +359,6 @@ pub trait SetInnerSize<T> {
impl SetInnerSize<Pixels<u32>> for Window {
fn set_inner_size<T: ToPoints>(&mut self, size: &T) {
let size = size.to_points(self.hidpi_factor());
- self.glutin_window.set_inner_size(*size.width as _, *size.height as _);
+ self.window.set_inner_size(*size.width as _, *size.height as _);
}
}