summaryrefslogtreecommitdiff
path: root/src/window.rs
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2016-12-10 22:44:13 -0800
committerJoe Wilm <joe@jwilm.com>2016-12-11 20:23:41 -0800
commited0b1cfff04903fe26f586340e036c38bbf30b33 (patch)
treeeb4eb3545bee57ed401cb7727c9dc3f106fabe3b /src/window.rs
parentbbd8ddbfc055e85f8810285e71fd227cdd418221 (diff)
downloadalacritty-ed0b1cfff04903fe26f586340e036c38bbf30b33.tar.gz
alacritty-ed0b1cfff04903fe26f586340e036c38bbf30b33.zip
Display manages window, renderer, rasterizer
This is part of an ongoing decoupling effort across the codebase and tidying effort in main.rs. Everything to do with showing the window with a grid of characters is now managed by the `Display` type. It owns the window, the font rasterizer, and the renderer. The only info needed from it are dimensions of characters and the window itself for sizing the terminal properly. Additionally, the I/O loop has access to wake it up when new data arrives.
Diffstat (limited to 'src/window.rs')
-rw-r--r--src/window.rs79
1 files changed, 72 insertions, 7 deletions
diff --git a/src/window.rs b/src/window.rs
index 4d8a0c02..f9f2050c 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -11,6 +11,8 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
+use std::sync::Arc;
+use std::sync::atomic::{AtomicBool, Ordering};
use std::convert::From;
use std::fmt::{self, Display};
use std::ops::Deref;
@@ -55,10 +57,17 @@ 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,
+
+ /// This flag allows calls to wakeup_event_loop to be coalesced. Waking the
+ /// event loop is potentially very slow (and indeed is on X11).
+ flag: Flag
}
/// Threadsafe APIs for the window
-pub struct Proxy(glutin::WindowProxy);
+pub struct Proxy {
+ inner: glutin::WindowProxy,
+ flag: Flag,
+}
/// Information about where the window is being displayed
///
@@ -89,6 +98,46 @@ pub struct Pixels<T>(pub T);
#[derive(Debug, Copy, Clone)]
pub struct Points<T>(pub T);
+/// A wrapper around glutin's WaitEventsIterator that clears the wakeup
+/// optimization flag on drop.
+pub struct WaitEventsIterator<'a> {
+ inner: glutin::WaitEventsIterator<'a>,
+ flag: Flag
+}
+
+impl<'a> Iterator for WaitEventsIterator<'a> {
+ type Item = glutin::Event;
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ self.inner.next()
+ }
+}
+
+impl<'a> Drop for WaitEventsIterator<'a> {
+ fn drop(&mut self) {
+ self.flag.set(false);
+ }
+}
+
+#[derive(Clone)]
+pub struct Flag(pub Arc<AtomicBool>);
+impl Flag {
+ pub fn new(initial_value: bool) -> Flag {
+ Flag(Arc::new(AtomicBool::new(initial_value)))
+ }
+
+ #[inline]
+ pub fn get(&self) -> bool {
+ self.0.load(Ordering::Acquire)
+ }
+
+ #[inline]
+ pub fn set(&self, value: bool) {
+ self.0.store(value, Ordering::Release)
+ }
+}
+
pub trait ToPoints {
fn to_points(&self, scale: f32) -> Size<Points<u32>>;
}
@@ -216,6 +265,7 @@ impl Window {
Ok(Window {
glutin_window: window,
+ flag: Flag::new(false),
})
}
@@ -256,7 +306,10 @@ impl Window {
#[inline]
pub fn create_window_proxy(&self) -> Proxy {
- Proxy(self.glutin_window.create_window_proxy())
+ Proxy {
+ inner: self.glutin_window.create_window_proxy(),
+ flag: self.flag.clone(),
+ }
}
#[inline]
@@ -267,11 +320,17 @@ impl Window {
}
/// 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(&self) -> WaitEventsIterator {
+ WaitEventsIterator {
+ inner: self.glutin_window.wait_events(),
+ flag: self.flag.clone()
+ }
+ }
+
+ /// Clear the wakeup optimization flag
+ pub fn clear_wakeup_flag(&self) {
+ self.flag.set(false);
}
/// Block waiting for events
@@ -289,7 +348,13 @@ 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.0.wakeup_event_loop();
+ // Only wake up the window event loop if it hasn't already been
+ // signaled. This is a really important optimization because waking up
+ // the event loop redundantly burns *a lot* of cycles.
+ if !self.flag.get() {
+ self.inner.wakeup_event_loop();
+ self.flag.set(true);
+ }
}
}