aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarret Rennie <barret@brennie.ca>2017-10-21 17:03:58 -0600
committerJoe Wilm <jwilm@users.noreply.github.com>2017-10-21 16:03:58 -0700
commitf6f2bcd024146678c7c206903453974cd0f392dc (patch)
tree1e0f6994dbcc14325275e4d79030093f80f07b78
parentb79574ee823900c21759628f92cf036271847afc (diff)
downloadalacritty-f6f2bcd024146678c7c206903453974cd0f392dc.tar.gz
alacritty-f6f2bcd024146678c7c206903453974cd0f392dc.zip
Set urgent WM flag on bell on X11 systems (#812)
Sets the urgent WM flag when bell is emitted on X11 systems. Additionally, the flag is cleared on focus because not all WMs clear it automatically.
-rw-r--r--src/display.rs8
-rw-r--r--src/event.rs9
-rw-r--r--src/term/mod.rs3
-rw-r--r--src/window.rs41
4 files changed, 61 insertions, 0 deletions
diff --git a/src/display.rs b/src/display.rs
index bdd9a9f2..fc5a5d40 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -322,6 +322,14 @@ impl Display {
self.window.set_title(&title);
}
+ if let Some(is_urgent) = terminal.next_is_urgent.take() {
+ // We don't need to set the urgent flag if we already have the
+ // user's attention.
+ if !is_urgent || !self.window.is_focused {
+ self.window.set_urgent(is_urgent);
+ }
+ }
+
let size_info = *terminal.size_info();
let visual_bell_intensity = terminal.visual_bell.intensity();
diff --git a/src/event.rs b/src/event.rs
index dda18652..0a79e804 100644
--- a/src/event.rs
+++ b/src/event.rs
@@ -251,6 +251,7 @@ impl<N: Notify> Processor<N> {
ref_test: bool,
resize_tx: &mpsc::Sender<(u32, u32)>,
hide_cursor: &mut bool,
+ window_is_focused: &mut bool,
) {
match event {
// Pass on device events
@@ -322,8 +323,11 @@ impl<N: Notify> Processor<N> {
processor.ctx.terminal.dirty = true;
},
Focused(is_focused) => {
+ *window_is_focused = is_focused;
+
if is_focused {
processor.ctx.terminal.dirty = true;
+ processor.ctx.terminal.next_is_urgent = Some(false);
} else {
*hide_cursor = false;
}
@@ -395,6 +399,8 @@ impl<N: Notify> Processor<N> {
mouse_bindings: &self.mouse_bindings[..],
};
+ let mut window_is_focused = window.is_focused;
+
// Scope needed to that hide_cursor isn't borrowed after the scope
// ends.
{
@@ -409,6 +415,7 @@ impl<N: Notify> Processor<N> {
ref_test,
resize_tx,
hide_cursor,
+ &mut window_is_focused,
);
};
@@ -423,6 +430,8 @@ impl<N: Notify> Processor<N> {
window.set_cursor_visible(!self.hide_cursor);
}
+ window.is_focused = window_is_focused;
+
if processor.ctx.selection_modified {
processor.ctx.terminal.dirty = true;
}
diff --git a/src/term/mod.rs b/src/term/mod.rs
index 97460421..59cf6baf 100644
--- a/src/term/mod.rs
+++ b/src/term/mod.rs
@@ -689,6 +689,7 @@ pub struct Term {
pub dirty: bool,
pub visual_bell: VisualBell,
+ pub next_is_urgent: Option<bool>,
/// Saved cursor from main grid
cursor_save: Cursor,
@@ -791,6 +792,7 @@ impl Term {
next_title: None,
dirty: false,
visual_bell: VisualBell::new(config),
+ next_is_urgent: None,
input_needs_wrap: false,
grid: grid,
alt_grid: alt,
@@ -1459,6 +1461,7 @@ impl ansi::Handler for Term {
fn bell(&mut self) {
trace!("bell");
self.visual_bell.ring();
+ self.next_is_urgent = Some(true);
}
#[inline]
diff --git a/src/window.rs b/src/window.rs
index f24def3a..a50daf87 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -39,6 +39,9 @@ pub struct Window {
event_loop: EventsLoop,
window: glutin::GlWindow,
cursor_visible: bool,
+
+ /// Whether or not the window is the focused window.
+ pub is_focused: bool,
}
/// Threadsafe APIs for the window
@@ -204,6 +207,7 @@ impl Window {
event_loop: event_loop,
window: window,
cursor_visible: true,
+ is_focused: true,
};
window.run_os_extensions();
@@ -308,6 +312,43 @@ impl Window {
}
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))]
+ pub fn set_urgent(&self, is_urgent: bool) {
+ use glutin::os::unix::WindowExt;
+ use std::os::raw;
+ use x11_dl::xlib::{self, XUrgencyHint};
+
+ 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");
+
+ unsafe {
+ let mut hints = (xlib.XGetWMHints)(xlib_display as _, xlib_window as _);
+
+ if hints.is_null() {
+ hints = (xlib.XAllocWMHints)();
+ }
+
+ if is_urgent {
+ (*hints).flags |= XUrgencyHint;
+ } else {
+ (*hints).flags &= !XUrgencyHint;
+ }
+
+ (xlib.XSetWMHints)(xlib_display as _, xlib_window as _, hints);
+
+ (xlib.XFree)(hints as *mut raw::c_void);
+ }
+ }
+
+ }
+
+ #[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")))]
+ pub fn set_urgent(&self, is_urgent: bool) {
+ }
+
+ #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))]
pub fn send_xim_spot(&self, x: i16, y: i16) {
use glutin::os::unix::WindowExt;
self.window.send_xim_spot(x, y);