mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-23 02:05:33 +07:00
Unconstrain InputMethod's PopupSurface
Make IME popup to be visible inside the parent and not obscure the text input rectangle region. Fixes https://github.com/YaLTeR/niri/issues/221
This commit is contained in:
committed by
Ivan Molodetskikh
parent
c2d03d82ce
commit
279659ac90
Generated
+31
-11
@@ -889,13 +889,13 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "drm"
|
name = "drm"
|
||||||
version = "0.11.1"
|
version = "0.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a0f8a69e60d75ae7dab4ef26a59ca99f2a89d4c142089b537775ae0c198bdcde"
|
checksum = "98888c4bbd601524c11a7ed63f814b8825f420514f78e96f752c437ae9cbb5d1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"drm-ffi",
|
"drm-ffi 0.8.0",
|
||||||
"drm-fourcc",
|
"drm-fourcc",
|
||||||
"rustix 0.38.32",
|
"rustix 0.38.32",
|
||||||
]
|
]
|
||||||
@@ -906,7 +906,17 @@ version = "0.7.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "41334f8405792483e32ad05fbb9c5680ff4e84491883d2947a4757dc54cb2ac6"
|
checksum = "41334f8405792483e32ad05fbb9c5680ff4e84491883d2947a4757dc54cb2ac6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"drm-sys",
|
"drm-sys 0.6.1",
|
||||||
|
"rustix 0.38.32",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "drm-ffi"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97c98727e48b7ccb4f4aea8cfe881e5b07f702d17b7875991881b41af7278d53"
|
||||||
|
dependencies = [
|
||||||
|
"drm-sys 0.7.0",
|
||||||
"rustix 0.38.32",
|
"rustix 0.38.32",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -926,6 +936,16 @@ dependencies = [
|
|||||||
"linux-raw-sys 0.6.4",
|
"linux-raw-sys 0.6.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "drm-sys"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fd39dde40b6e196c2e8763f23d119ddb1a8714534bf7d77fa97a65b0feda3986"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "edid-rs"
|
name = "edid-rs"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -1239,11 +1259,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gbm"
|
name = "gbm"
|
||||||
version = "0.14.2"
|
version = "0.15.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "313702b30cdeb83ddc72bc14dcee67803cd0ae2d12282ea06e368c25a900c844"
|
checksum = "45bf55ba6dd53ad0ac115046ff999c5324c283444ee6e0be82454c4e8eb2f36a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.5.0",
|
||||||
"drm",
|
"drm",
|
||||||
"drm-fourcc",
|
"drm-fourcc",
|
||||||
"gbm-sys",
|
"gbm-sys",
|
||||||
@@ -2149,7 +2169,7 @@ dependencies = [
|
|||||||
"calloop 0.13.0",
|
"calloop 0.13.0",
|
||||||
"clap",
|
"clap",
|
||||||
"directories",
|
"directories",
|
||||||
"drm-ffi",
|
"drm-ffi 0.7.1",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"git-version",
|
"git-version",
|
||||||
"glam",
|
"glam",
|
||||||
@@ -3116,7 +3136,7 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "smithay"
|
name = "smithay"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/Smithay/smithay.git#c5e9a697e41f50dc56b918d9ef1e3d2e52c84ac0"
|
source = "git+https://github.com/Smithay/smithay.git#40acc58b83400aa10fc62a51a235d1991ab46be5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"appendlist",
|
"appendlist",
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
@@ -3126,7 +3146,7 @@ dependencies = [
|
|||||||
"cursor-icon",
|
"cursor-icon",
|
||||||
"downcast-rs",
|
"downcast-rs",
|
||||||
"drm",
|
"drm",
|
||||||
"drm-ffi",
|
"drm-ffi 0.8.0",
|
||||||
"drm-fourcc",
|
"drm-fourcc",
|
||||||
"errno",
|
"errno",
|
||||||
"gbm",
|
"gbm",
|
||||||
@@ -3188,7 +3208,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "smithay-drm-extras"
|
name = "smithay-drm-extras"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/Smithay/smithay.git#c5e9a697e41f50dc56b918d9ef1e3d2e52c84ac0"
|
source = "git+https://github.com/Smithay/smithay.git#40acc58b83400aa10fc62a51a235d1991ab46be5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"drm",
|
"drm",
|
||||||
"edid-rs",
|
"edid-rs",
|
||||||
|
|||||||
+11
-2
@@ -133,25 +133,34 @@ delegate_pointer_constraints!(State);
|
|||||||
|
|
||||||
impl InputMethodHandler for State {
|
impl InputMethodHandler for State {
|
||||||
fn new_popup(&mut self, surface: PopupSurface) {
|
fn new_popup(&mut self, surface: PopupSurface) {
|
||||||
let popup = PopupKind::from(surface.clone());
|
let popup = PopupKind::InputMethod(surface);
|
||||||
if let Some(output) = self.output_for_popup(&popup) {
|
if let Some(output) = self.output_for_popup(&popup) {
|
||||||
let scale = output.current_scale().integer_scale();
|
let scale = output.current_scale().integer_scale();
|
||||||
let transform = output.current_transform();
|
let transform = output.current_transform();
|
||||||
let wl_surface = surface.wl_surface();
|
let wl_surface = popup.wl_surface();
|
||||||
with_states(wl_surface, |data| {
|
with_states(wl_surface, |data| {
|
||||||
send_surface_state(wl_surface, data, scale, transform);
|
send_surface_state(wl_surface, data, scale, transform);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.unconstrain_popup(&popup);
|
||||||
|
|
||||||
if let Err(err) = self.niri.popups.track_popup(popup) {
|
if let Err(err) = self.niri.popups.track_popup(popup) {
|
||||||
warn!("error tracking ime popup {err:?}");
|
warn!("error tracking ime popup {err:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn popup_repositioned(&mut self, surface: PopupSurface) {
|
||||||
|
let popup = PopupKind::InputMethod(surface);
|
||||||
|
self.unconstrain_popup(&popup);
|
||||||
|
}
|
||||||
|
|
||||||
fn dismiss_popup(&mut self, surface: PopupSurface) {
|
fn dismiss_popup(&mut self, surface: PopupSurface) {
|
||||||
if let Some(parent) = surface.get_parent().map(|parent| parent.surface.clone()) {
|
if let Some(parent) = surface.get_parent().map(|parent| parent.surface.clone()) {
|
||||||
let _ = PopupManager::dismiss_popup(&parent, &PopupKind::from(surface));
|
let _ = PopupManager::dismiss_popup(&parent, &PopupKind::from(surface));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parent_geometry(&self, parent: &WlSurface) -> Rectangle<i32, Logical> {
|
fn parent_geometry(&self, parent: &WlSurface) -> Rectangle<i32, Logical> {
|
||||||
self.niri
|
self.niri
|
||||||
.layout
|
.layout
|
||||||
|
|||||||
+44
-16
@@ -1,5 +1,5 @@
|
|||||||
use smithay::desktop::{
|
use smithay::desktop::{
|
||||||
find_popup_root_surface, get_popup_toplevel_coords, layer_map_for_output, LayerSurface,
|
find_popup_root_surface, get_popup_toplevel_coords, layer_map_for_output, utils, LayerSurface,
|
||||||
PopupKeyboardGrab, PopupKind, PopupManager, PopupPointerGrab, PopupUngrabStrategy, Window,
|
PopupKeyboardGrab, PopupKind, PopupManager, PopupPointerGrab, PopupUngrabStrategy, Window,
|
||||||
WindowSurfaceType,
|
WindowSurfaceType,
|
||||||
};
|
};
|
||||||
@@ -177,7 +177,7 @@ impl XdgShellHandler for State {
|
|||||||
|
|
||||||
trace!("new grab for root {:?}", root);
|
trace!("new grab for root {:?}", root);
|
||||||
keyboard.set_focus(self, grab.current_grab(), serial);
|
keyboard.set_focus(self, grab.current_grab(), serial);
|
||||||
keyboard.set_grab(PopupKeyboardGrab::new(&grab), serial);
|
keyboard.set_grab(self, PopupKeyboardGrab::new(&grab), serial);
|
||||||
pointer.set_grab(self, PopupPointerGrab::new(&grab), serial, Focus::Keep);
|
pointer.set_grab(self, PopupPointerGrab::new(&grab), serial, Focus::Keep);
|
||||||
self.niri.popup_grab = Some(PopupGrabState { root, grab });
|
self.niri.popup_grab = Some(PopupGrabState { root, grab });
|
||||||
}
|
}
|
||||||
@@ -649,8 +649,11 @@ impl State {
|
|||||||
popup.send_configure().expect("initial configure failed");
|
popup.send_configure().expect("initial configure failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Input method popups don't require a configure.
|
// Input method popup can arbitrary change its geometry, so we need to unconstraint
|
||||||
PopupKind::InputMethod(_) => (),
|
// it on commit.
|
||||||
|
PopupKind::InputMethod(_) => {
|
||||||
|
self.unconstrain_popup(&popup);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -696,14 +699,7 @@ impl State {
|
|||||||
target.loc.y -= self.niri.layout.window_y(window).unwrap();
|
target.loc.y -= self.niri.layout.window_y(window).unwrap();
|
||||||
target.loc -= get_popup_toplevel_coords(popup);
|
target.loc -= get_popup_toplevel_coords(popup);
|
||||||
|
|
||||||
match popup {
|
self.position_popup_within_rect(popup, target);
|
||||||
PopupKind::Xdg(popup) => {
|
|
||||||
popup.with_pending_state(|state| {
|
|
||||||
state.geometry = unconstrain_with_padding(state.positioner, target);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
PopupKind::InputMethod(_) => todo!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unconstrain_layer_shell_popup(
|
pub fn unconstrain_layer_shell_popup(
|
||||||
@@ -724,11 +720,43 @@ impl State {
|
|||||||
target.loc -= layer_geo.loc;
|
target.loc -= layer_geo.loc;
|
||||||
target.loc -= get_popup_toplevel_coords(popup);
|
target.loc -= get_popup_toplevel_coords(popup);
|
||||||
|
|
||||||
|
self.position_popup_within_rect(popup, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn position_popup_within_rect(&self, popup: &PopupKind, target: Rectangle<i32, Logical>) {
|
||||||
match popup {
|
match popup {
|
||||||
PopupKind::Xdg(popup) => popup.with_pending_state(|state| {
|
PopupKind::Xdg(popup) => {
|
||||||
state.geometry = unconstrain_with_padding(state.positioner, target);
|
popup.with_pending_state(|state| {
|
||||||
}),
|
state.geometry = unconstrain_with_padding(state.positioner, target);
|
||||||
PopupKind::InputMethod(_) => todo!(),
|
});
|
||||||
|
}
|
||||||
|
PopupKind::InputMethod(popup) => {
|
||||||
|
let text_input_rectangle = popup.text_input_rectangle();
|
||||||
|
let mut bbox =
|
||||||
|
utils::bbox_from_surface_tree(popup.wl_surface(), text_input_rectangle.loc);
|
||||||
|
|
||||||
|
// Position bbox horizontally first.
|
||||||
|
let overflow_x = (bbox.loc.x + bbox.size.w) - (target.loc.x + target.size.w);
|
||||||
|
if overflow_x > 0 {
|
||||||
|
bbox.loc.x -= overflow_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the popup starts within the window.
|
||||||
|
bbox.loc.x = bbox.loc.x.max(target.loc.x);
|
||||||
|
|
||||||
|
// Try to position IME popup below the text input rectangle.
|
||||||
|
let mut below = bbox;
|
||||||
|
below.loc.y += text_input_rectangle.size.h;
|
||||||
|
|
||||||
|
let mut above = bbox;
|
||||||
|
above.loc.y -= bbox.size.h;
|
||||||
|
|
||||||
|
if target.loc.y + target.size.h >= below.loc.y + below.size.h {
|
||||||
|
popup.set_location(below.loc);
|
||||||
|
} else {
|
||||||
|
popup.set_location(above.loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -768,7 +768,7 @@ impl State {
|
|||||||
);
|
);
|
||||||
|
|
||||||
grab.grab.ungrab(PopupUngrabStrategy::All);
|
grab.grab.ungrab(PopupUngrabStrategy::All);
|
||||||
keyboard.unset_grab();
|
keyboard.unset_grab(self);
|
||||||
self.niri.seat.get_pointer().unwrap().unset_grab(
|
self.niri.seat.get_pointer().unwrap().unset_grab(
|
||||||
self,
|
self,
|
||||||
SERIAL_COUNTER.next_serial(),
|
SERIAL_COUNTER.next_serial(),
|
||||||
|
|||||||
Reference in New Issue
Block a user