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.
This commit is contained in:
Barret Rennie 2017-10-21 17:03:58 -06:00 committed by Joe Wilm
parent b79574ee82
commit f6f2bcd024
4 changed files with 61 additions and 0 deletions

View File

@ -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();

View File

@ -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;
}

View File

@ -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]

View File

@ -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();
@ -307,6 +311,43 @@ impl Window {
pub fn platform_window_init() {
}
#[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;