Unconditionally set input focus on activation
Wine windows had WM_HINTS.input set to False, and expected use of the WM_TAKE_FOCUS protocol, but Wayland input is much more absolute, so this protocol is useless to us. Always focusing windows seems to be fine, so just do that. Should fix #35.
This commit is contained in:
parent
891d056497
commit
03a0e1754d
3 changed files with 22 additions and 95 deletions
|
|
@ -255,6 +255,9 @@ impl SurfaceData {
|
||||||
let activated = states.contains(&(u32::from(xdg_toplevel::State::Activated) as u8));
|
let activated = states.contains(&(u32::from(xdg_toplevel::State::Activated) as u8));
|
||||||
|
|
||||||
if activated {
|
if activated {
|
||||||
|
// Technically this is wrong - activated doesn't necessarily mean focused
|
||||||
|
// - but it works and no one's complained yet.
|
||||||
|
// TODO: base focus on keyboard enter instead.
|
||||||
state.to_focus = Some(self.window.unwrap());
|
state.to_focus = Some(self.window.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -697,7 +697,6 @@ bitflags! {
|
||||||
bitflags! {
|
bitflags! {
|
||||||
/// https://tronche.com/gui/x/icccm/sec-4.html#s-4.1.2.4
|
/// https://tronche.com/gui/x/icccm/sec-4.html#s-4.1.2.4
|
||||||
pub struct WmHintsFlags: u32 {
|
pub struct WmHintsFlags: u32 {
|
||||||
const Input = 1;
|
|
||||||
const WindowGroup = 64;
|
const WindowGroup = 64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -739,7 +738,6 @@ impl From<&[u32]> for WmNormalHints {
|
||||||
|
|
||||||
#[derive(Default, Debug, PartialEq, Eq)]
|
#[derive(Default, Debug, PartialEq, Eq)]
|
||||||
pub struct WmHints {
|
pub struct WmHints {
|
||||||
pub input: Option<bool>,
|
|
||||||
pub window_group: Option<x::Window>,
|
pub window_group: Option<x::Window>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -748,9 +746,6 @@ impl From<&[u32]> for WmHints {
|
||||||
let mut ret = Self::default();
|
let mut ret = Self::default();
|
||||||
let flags = WmHintsFlags::from_bits_truncate(value[0]);
|
let flags = WmHintsFlags::from_bits_truncate(value[0]);
|
||||||
|
|
||||||
if flags.contains(WmHintsFlags::Input) {
|
|
||||||
ret.input = Some(value[1] == 1);
|
|
||||||
}
|
|
||||||
if flags.contains(WmHintsFlags::WindowGroup) {
|
if flags.contains(WmHintsFlags::WindowGroup) {
|
||||||
let window = unsafe { x::Window::new(value[8]) };
|
let window = unsafe { x::Window::new(value[8]) };
|
||||||
ret.window_group = Some(window);
|
ret.window_group = Some(window);
|
||||||
|
|
@ -817,30 +812,11 @@ impl super::XConnection for Arc<xcb::Connection> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focus_window(&mut self, window: x::Window, atoms: Self::ExtraData) {
|
fn focus_window(&mut self, window: x::Window, atoms: Self::ExtraData) {
|
||||||
let prop =
|
unwrap_or_skip_bad_window!(self.send_and_check_request(&x::SetInputFocus {
|
||||||
unwrap_or_skip_bad_window!(self.wait_for_reply(self.send_request(&x::GetProperty {
|
focus: window,
|
||||||
delete: false,
|
revert_to: x::InputFocus::None,
|
||||||
window,
|
time: x::CURRENT_TIME,
|
||||||
property: x::ATOM_WM_HINTS,
|
}));
|
||||||
r#type: x::ATOM_WM_HINTS,
|
|
||||||
long_offset: 0,
|
|
||||||
long_length: 9,
|
|
||||||
})));
|
|
||||||
|
|
||||||
let set_focus = if prop.r#type() == x::ATOM_NONE {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
WmHints::from(prop.value()).input.unwrap_or(true)
|
|
||||||
};
|
|
||||||
|
|
||||||
if set_focus {
|
|
||||||
// might fail if window is not visible but who cares
|
|
||||||
let _ = self.send_and_check_request(&x::SetInputFocus {
|
|
||||||
focus: window,
|
|
||||||
revert_to: x::InputFocus::None,
|
|
||||||
time: x::CURRENT_TIME,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
unwrap_or_skip_bad_window!(self.send_and_check_request(&x::ChangeProperty {
|
unwrap_or_skip_bad_window!(self.send_and_check_request(&x::ChangeProperty {
|
||||||
mode: x::PropMode::Replace,
|
mode: x::PropMode::Replace,
|
||||||
|
|
|
||||||
|
|
@ -482,68 +482,22 @@ fn input_focus() {
|
||||||
let mut f = Fixture::new();
|
let mut f = Fixture::new();
|
||||||
let mut connection = Connection::new(&f.display);
|
let mut connection = Connection::new(&f.display);
|
||||||
|
|
||||||
fn tst(
|
let win = connection.new_window(connection.root, 0, 0, 20, 20, false);
|
||||||
f: &mut Fixture,
|
connection.map_window(win);
|
||||||
connection: &mut Connection,
|
f.wait_and_dispatch();
|
||||||
set_props: impl FnOnce(&mut Connection, x::Window),
|
let surface = f
|
||||||
check: impl FnOnce(/* win: */ x::Window, /* focus: */ x::Window),
|
.testwl
|
||||||
) {
|
.last_created_surface_id()
|
||||||
let win = connection.new_window(connection.root, 0, 0, 20, 20, false);
|
.expect("No surface created!");
|
||||||
set_props(connection, win);
|
f.configure_and_verify_new_toplevel(&mut connection, win, surface);
|
||||||
connection.map_window(win);
|
|
||||||
f.wait_and_dispatch();
|
|
||||||
let surface = f
|
|
||||||
.testwl
|
|
||||||
.last_created_surface_id()
|
|
||||||
.expect("No surface created!");
|
|
||||||
f.configure_and_verify_new_toplevel(connection, win, surface);
|
|
||||||
|
|
||||||
let focus = connection
|
let focus = connection
|
||||||
.wait_for_reply(connection.send_request(&x::GetInputFocus {}))
|
.wait_for_reply(connection.send_request(&x::GetInputFocus {}))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.focus();
|
.focus();
|
||||||
check(win, focus);
|
assert_eq!(win, focus);
|
||||||
|
|
||||||
f.close_toplevel(connection, win, surface);
|
f.close_toplevel(&mut connection, win, surface);
|
||||||
}
|
|
||||||
|
|
||||||
// Input field unset
|
|
||||||
tst(
|
|
||||||
&mut f,
|
|
||||||
&mut connection,
|
|
||||||
|_, _| {},
|
|
||||||
|win, focus| assert_eq!(win, focus),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Input field set to false
|
|
||||||
tst(
|
|
||||||
&mut f,
|
|
||||||
&mut connection,
|
|
||||||
|connection, win| {
|
|
||||||
connection.set_property(
|
|
||||||
win,
|
|
||||||
x::ATOM_WM_HINTS,
|
|
||||||
x::ATOM_WM_HINTS,
|
|
||||||
&[WmHintsFlags::Input.bits(), 0],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|win, focus| assert_ne!(win, focus),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Input field set to true
|
|
||||||
tst(
|
|
||||||
&mut f,
|
|
||||||
&mut connection,
|
|
||||||
|connection, win| {
|
|
||||||
connection.set_property(
|
|
||||||
win,
|
|
||||||
x::ATOM_WM_HINTS,
|
|
||||||
x::ATOM_WM_HINTS,
|
|
||||||
&[WmHintsFlags::Input.bits(), 1],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|win, focus| assert_eq!(win, focus),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -558,12 +512,6 @@ fn quick_delete() {
|
||||||
.testwl
|
.testwl
|
||||||
.last_created_surface_id()
|
.last_created_surface_id()
|
||||||
.expect("No surface created");
|
.expect("No surface created");
|
||||||
connection.set_property(
|
|
||||||
window,
|
|
||||||
x::ATOM_WM_HINTS,
|
|
||||||
x::ATOM_WM_HINTS,
|
|
||||||
&[WmHintsFlags::Input.bits(), 0],
|
|
||||||
);
|
|
||||||
connection.set_property(
|
connection.set_property(
|
||||||
window,
|
window,
|
||||||
x::ATOM_STRING,
|
x::ATOM_STRING,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue