mirror of
https://github.com/wez/wezterm.git
synced 2024-11-22 22:42:48 +03:00
parent
520a8e306f
commit
e2b748a0d4
@ -22,6 +22,7 @@ As features stabilize some brief notes about them will accumulate here.
|
||||
* New [wezterm.gui.screens()](config/lua/wezterm.gui/screens.md) function for getting information about the available screens/monitors/displays
|
||||
* You may now use [wezterm.format](config/lua/wezterm/format.md) (or otherwise use strings with escape sequences) in the labels of the [Launcher Menu](config/launch.md#the-launcher-menu).
|
||||
* You may now specify `assume_emoji_presentation = true` (or `false`) in [wezterm.font()](config/lua/wezterm/font.md) and [wezterm.font_with_fallback()](config/lua/wezterm/font_with_fallback.md)
|
||||
* Wayland: `zwp_text_input_v3` is now supported, which enables IME to work in wezterm if your compositor also implements this protocol.
|
||||
|
||||
#### Fixed
|
||||
* [ActivateKeyTable](config/lua/keyassignment/ActivateKeyTable.md)'s `replace_current` field was not actually optional. Made it optional. [#2179](https://github.com/wez/wezterm/issues/2179)
|
||||
|
@ -11,7 +11,7 @@ IME support is a platform dependent feature
|
||||
|Windows |Forever |Always enabled, cannot be disabled|
|
||||
|macOS |20200113-214446-bb6251f|defaults to enabled starting in 20220319-142410-0fcdea07. Earlier versions had problems with key repeat when enabled|
|
||||
|X11 |20211204-082213-a66c61ee9|[XIM](https://en.wikipedia.org/wiki/X_Input_Method) based. Your system needs to have a running input method engine (such as ibus or fcitx) that support the XIM protocol in order for wezterm to use it.|
|
||||
|Wayland |Not yet|[#1772](https://github.com/wez/wezterm/issues/1772) is tracking IME support|
|
||||
|Wayland |Nightly builds only|Your compositor must support `zwp_text_input_v3`|
|
||||
|
||||
You can control whether the IME is enabled in your configuration file:
|
||||
|
||||
|
@ -2,11 +2,12 @@
|
||||
use super::pointer::*;
|
||||
use super::window::*;
|
||||
use crate::connection::ConnectionOps;
|
||||
use crate::os::wayland::inputhandler::InputHandler;
|
||||
use crate::os::wayland::output::OutputHandler;
|
||||
use crate::os::x11::keyboard::Keyboard;
|
||||
use crate::screen::{ScreenInfo, Screens};
|
||||
use crate::spawn::*;
|
||||
use crate::{Connection, ScreenRect};
|
||||
use crate::{Connection, ScreenRect, WindowEvent};
|
||||
use anyhow::{bail, Context};
|
||||
use mio::unix::SourceFd;
|
||||
use mio::{Events, Interest, Poll, Token};
|
||||
@ -27,11 +28,19 @@ use wayland_client::{EventQueue, Main};
|
||||
toolkit::default_environment!(MyEnvironment, desktop,
|
||||
fields=[
|
||||
output_handler: OutputHandler,
|
||||
input_handler: InputHandler,
|
||||
],
|
||||
singles=[
|
||||
wayland_protocols::wlr::unstable::output_management::v1::client::zwlr_output_manager_v1::ZwlrOutputManagerV1 => output_handler,
|
||||
wayland_protocols::unstable::text_input::v3::client::zwp_text_input_manager_v3::ZwpTextInputManagerV3 => input_handler,
|
||||
]);
|
||||
|
||||
impl MyEnvironment {
|
||||
pub fn input_handler(&mut self) -> &mut InputHandler {
|
||||
&mut self.input_handler
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WaylandConnection {
|
||||
should_terminate: RefCell<bool>,
|
||||
pub(crate) next_window_id: AtomicUsize,
|
||||
@ -61,7 +70,7 @@ pub struct WaylandConnection {
|
||||
pub(crate) key_repeat_delay: RefCell<i32>,
|
||||
pub(crate) last_serial: RefCell<u32>,
|
||||
seat_listener: SeatListener,
|
||||
pub(crate) environment: RefCell<Environment<MyEnvironment>>,
|
||||
pub(crate) environment: Environment<MyEnvironment>,
|
||||
event_q: RefCell<EventQueue>,
|
||||
pub(crate) display: RefCell<Display>,
|
||||
}
|
||||
@ -71,7 +80,10 @@ impl WaylandConnection {
|
||||
let (environment, display, event_q) = toolkit::new_default_environment!(
|
||||
MyEnvironment,
|
||||
desktop,
|
||||
fields = [output_handler: OutputHandler::new()]
|
||||
fields = [
|
||||
output_handler: OutputHandler::new(),
|
||||
input_handler: InputHandler::new(),
|
||||
]
|
||||
)?;
|
||||
|
||||
let mut pointer = None;
|
||||
@ -95,6 +107,7 @@ impl WaylandConnection {
|
||||
log::error!("keyboard_event: {:#}", err);
|
||||
}
|
||||
});
|
||||
environment.with_inner(|env| env.input_handler.advise_seat(&seat, &keyboard));
|
||||
seat_keyboards.insert(name, keyboard);
|
||||
}
|
||||
if has_ptr {
|
||||
@ -111,6 +124,7 @@ impl WaylandConnection {
|
||||
|
||||
let seat_listener;
|
||||
{
|
||||
let env = environment.clone();
|
||||
seat_listener = environment.listen_for_seats(move |seat, seat_data, _| {
|
||||
if seat_data.has_keyboard {
|
||||
if !seat_data.defunct {
|
||||
@ -131,14 +145,18 @@ impl WaylandConnection {
|
||||
// up handling key events twice.
|
||||
if !seat_keyboards.contains_key(&seat_data.name) {
|
||||
let keyboard = seat.get_keyboard();
|
||||
|
||||
keyboard.quick_assign(|keyboard, event, _| {
|
||||
let conn = Connection::get().unwrap().wayland();
|
||||
if let Err(err) = conn.keyboard_event(keyboard, event) {
|
||||
log::error!("keyboard_event: {:#}", err);
|
||||
}
|
||||
});
|
||||
env.with_inner(|env| env.input_handler.advise_seat(&seat, &keyboard));
|
||||
seat_keyboards.insert(seat_data.name.clone(), keyboard);
|
||||
}
|
||||
} else {
|
||||
env.with_inner(|env| env.input_handler.seat_defunct(&seat));
|
||||
}
|
||||
} else {
|
||||
// If we previously had a keyboard object on this seat, it's no longer valid if
|
||||
@ -158,7 +176,7 @@ impl WaylandConnection {
|
||||
|
||||
Ok(Self {
|
||||
display: RefCell::new(display),
|
||||
environment: RefCell::new(environment),
|
||||
environment,
|
||||
should_terminate: RefCell::new(false),
|
||||
next_window_id: AtomicUsize::new(1),
|
||||
windows: RefCell::new(HashMap::new()),
|
||||
@ -179,7 +197,7 @@ impl WaylandConnection {
|
||||
|
||||
fn keyboard_event(
|
||||
&self,
|
||||
_pointer: Main<WlKeyboard>,
|
||||
keyboard: Main<WlKeyboard>,
|
||||
event: WlKeyboardEvent,
|
||||
) -> anyhow::Result<()> {
|
||||
match &event {
|
||||
@ -196,13 +214,30 @@ impl WaylandConnection {
|
||||
.get(&surface.as_ref().id())
|
||||
{
|
||||
self.keyboard_window_id.borrow_mut().replace(window_id);
|
||||
self.environment.with_inner(|env| {
|
||||
if let Some(input) =
|
||||
env.input_handler.get_text_input_for_keyboard(&keyboard)
|
||||
{
|
||||
input.enable();
|
||||
input.commit();
|
||||
}
|
||||
env.input_handler.advise_surface(&surface, &keyboard);
|
||||
});
|
||||
} else {
|
||||
log::warn!("{:?}, no known surface", event);
|
||||
}
|
||||
}
|
||||
WlKeyboardEvent::Leave { serial, .. }
|
||||
| WlKeyboardEvent::Key { serial, .. }
|
||||
| WlKeyboardEvent::Modifiers { serial, .. } => {
|
||||
WlKeyboardEvent::Leave { serial, .. } => {
|
||||
if let Some(input) = self
|
||||
.environment
|
||||
.with_inner(|env| env.input_handler.get_text_input_for_keyboard(&keyboard))
|
||||
{
|
||||
input.disable();
|
||||
input.commit();
|
||||
}
|
||||
*self.last_serial.borrow_mut() = *serial;
|
||||
}
|
||||
WlKeyboardEvent::Key { serial, .. } | WlKeyboardEvent::Modifiers { serial, .. } => {
|
||||
*self.last_serial.borrow_mut() = *serial;
|
||||
}
|
||||
WlKeyboardEvent::RepeatInfo { rate, delay } => {
|
||||
@ -245,6 +280,15 @@ impl WaylandConnection {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn dispatch_to_focused_window(&self, event: WindowEvent) {
|
||||
if let Some(&window_id) = self.keyboard_window_id.borrow().as_ref() {
|
||||
if let Some(win) = self.window_by_id(window_id) {
|
||||
let mut inner = win.borrow_mut();
|
||||
inner.events.dispatch(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn next_window_id(&self) -> usize {
|
||||
self.next_window_id
|
||||
.fetch_add(1, ::std::sync::atomic::Ordering::Relaxed)
|
||||
@ -380,7 +424,6 @@ impl ConnectionOps for WaylandConnection {
|
||||
fn screens(&self) -> anyhow::Result<Screens> {
|
||||
if let Some(screens) = self
|
||||
.environment
|
||||
.borrow()
|
||||
.with_inner(|env| env.output_handler.screens())
|
||||
{
|
||||
return Ok(screens);
|
||||
@ -388,7 +431,7 @@ impl ConnectionOps for WaylandConnection {
|
||||
|
||||
let mut by_name = HashMap::new();
|
||||
let mut virtual_rect: ScreenRect = euclid::rect(0, 0, 0, 0);
|
||||
for output in self.environment.borrow().get_all_outputs() {
|
||||
for output in self.environment.get_all_outputs() {
|
||||
toolkit::output::with_output_info(&output, |info| {
|
||||
let name = if info.name.is_empty() {
|
||||
format!("{} {}", info.model, info.make)
|
||||
|
@ -78,7 +78,6 @@ impl CopyAndPaste {
|
||||
let pointer = conn.pointer.borrow();
|
||||
let primary_selection = if let Clipboard::PrimarySelection = clipboard {
|
||||
conn.environment
|
||||
.borrow()
|
||||
.get_primary_selection_manager()
|
||||
.zip(pointer.primary_selection_device.as_ref())
|
||||
} else {
|
||||
@ -111,7 +110,6 @@ impl CopyAndPaste {
|
||||
None => {
|
||||
let source = conn
|
||||
.environment
|
||||
.borrow()
|
||||
.require_global::<WlDataDeviceManager>()
|
||||
.create_data_source();
|
||||
source.quick_assign(move |_source, event, _dispatch_data| {
|
||||
|
165
window/src/os/wayland/inputhandler.rs
Normal file
165
window/src/os/wayland/inputhandler.rs
Normal file
@ -0,0 +1,165 @@
|
||||
//! Implements zwp_text_input_v3 for handling IME
|
||||
use crate::connection::ConnectionOps;
|
||||
use crate::os::wayland::{wl_id, WaylandConnection};
|
||||
use crate::{DeadKeyStatus, KeyCode, KeyEvent, Modifiers, WindowEvent};
|
||||
use smithay_client_toolkit::environment::GlobalHandler;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use wayland_client::protocol::wl_keyboard::WlKeyboard;
|
||||
use wayland_client::protocol::wl_registry::WlRegistry;
|
||||
use wayland_client::protocol::wl_seat::WlSeat;
|
||||
use wayland_client::protocol::wl_surface::WlSurface;
|
||||
use wayland_client::{Attached, DispatchData, Main};
|
||||
use wayland_protocols::unstable::text_input::v3::client::zwp_text_input_manager_v3::ZwpTextInputManagerV3;
|
||||
use wayland_protocols::unstable::text_input::v3::client::zwp_text_input_v3::{
|
||||
Event, ZwpTextInputV3,
|
||||
};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct Inner {
|
||||
input_by_seat: HashMap<u32, Attached<ZwpTextInputV3>>,
|
||||
keyboard_to_seat: HashMap<u32, u32>,
|
||||
surface_to_keyboard: HashMap<u32, u32>,
|
||||
}
|
||||
|
||||
impl Inner {
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
_input: Main<ZwpTextInputV3>,
|
||||
event: Event,
|
||||
_ddata: DispatchData,
|
||||
_inner: &Arc<Mutex<Self>>,
|
||||
) {
|
||||
log::trace!("{event:?}");
|
||||
let conn = WaylandConnection::get().unwrap().wayland();
|
||||
match event {
|
||||
Event::PreeditString {
|
||||
text,
|
||||
cursor_begin: _,
|
||||
cursor_end: _,
|
||||
} => {
|
||||
conn.dispatch_to_focused_window(WindowEvent::AdviseDeadKeyStatus(match text {
|
||||
Some(text) => DeadKeyStatus::Composing(text),
|
||||
None => DeadKeyStatus::None,
|
||||
}));
|
||||
}
|
||||
Event::CommitString { text } => {
|
||||
conn.dispatch_to_focused_window(match text {
|
||||
Some(text) => WindowEvent::KeyEvent(KeyEvent {
|
||||
key: KeyCode::composed(&text),
|
||||
modifiers: Modifiers::NONE,
|
||||
repeat_count: 1,
|
||||
key_is_down: true,
|
||||
raw: None,
|
||||
}),
|
||||
None => WindowEvent::AdviseDeadKeyStatus(DeadKeyStatus::None),
|
||||
});
|
||||
}
|
||||
Event::Done { serial: _ } => {
|
||||
conn.dispatch_to_focused_window(WindowEvent::AdviseDeadKeyStatus(
|
||||
DeadKeyStatus::None,
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InputHandler {
|
||||
mgr: Option<Attached<ZwpTextInputManagerV3>>,
|
||||
inner: Arc<Mutex<Inner>>,
|
||||
}
|
||||
|
||||
impl InputHandler {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
mgr: None,
|
||||
inner: Arc::new(Mutex::new(Inner::default())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_text_input_for_keyboard(
|
||||
&self,
|
||||
keyboard: &WlKeyboard,
|
||||
) -> Option<Attached<ZwpTextInputV3>> {
|
||||
let inner = self.inner.lock().unwrap();
|
||||
let keyboard_id = wl_id(keyboard);
|
||||
let seat_id = inner.keyboard_to_seat.get(&keyboard_id)?;
|
||||
inner.input_by_seat.get(&seat_id).cloned()
|
||||
}
|
||||
|
||||
pub fn get_text_input_for_surface(
|
||||
&self,
|
||||
surface: &WlSurface,
|
||||
) -> Option<Attached<ZwpTextInputV3>> {
|
||||
let inner = self.inner.lock().unwrap();
|
||||
let surface_id = wl_id(surface);
|
||||
let keyboard_id = inner.surface_to_keyboard.get(&surface_id)?;
|
||||
let seat_id = inner.keyboard_to_seat.get(&keyboard_id)?;
|
||||
inner.input_by_seat.get(&seat_id).cloned()
|
||||
}
|
||||
|
||||
pub fn get_text_input_for_seat(&self, seat: &WlSeat) -> Option<Attached<ZwpTextInputV3>> {
|
||||
let mgr = self.mgr.as_ref()?;
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
let seat_id = wl_id(seat);
|
||||
let input = inner.input_by_seat.entry(seat_id).or_insert_with(|| {
|
||||
let input = mgr.get_text_input(seat);
|
||||
let inner = Arc::clone(&self.inner);
|
||||
|
||||
input.quick_assign(move |input, event, ddat| {
|
||||
inner
|
||||
.lock()
|
||||
.unwrap()
|
||||
.handle_event(input, event, ddat, &inner);
|
||||
});
|
||||
|
||||
input.into()
|
||||
});
|
||||
Some(input.clone())
|
||||
}
|
||||
|
||||
pub fn advise_surface(&self, surface: &WlSurface, keyboard: &WlKeyboard) {
|
||||
let surface_id = wl_id(surface);
|
||||
let keyboard_id = wl_id(keyboard);
|
||||
self.inner
|
||||
.lock()
|
||||
.unwrap()
|
||||
.surface_to_keyboard
|
||||
.insert(surface_id, keyboard_id);
|
||||
}
|
||||
|
||||
pub fn advise_seat(&self, seat: &WlSeat, keyboard: &WlKeyboard) {
|
||||
self.get_text_input_for_seat(seat);
|
||||
let keyboard_id = wl_id(keyboard);
|
||||
let seat_id = wl_id(seat);
|
||||
self.inner
|
||||
.lock()
|
||||
.unwrap()
|
||||
.keyboard_to_seat
|
||||
.insert(keyboard_id, seat_id);
|
||||
}
|
||||
|
||||
pub fn seat_defunct(&self, seat: &WlSeat) {
|
||||
let seat_id = wl_id(seat);
|
||||
self.inner.lock().unwrap().input_by_seat.remove(&seat_id);
|
||||
}
|
||||
}
|
||||
|
||||
impl GlobalHandler<ZwpTextInputManagerV3> for InputHandler {
|
||||
fn created(
|
||||
&mut self,
|
||||
registry: Attached<WlRegistry>,
|
||||
id: u32,
|
||||
version: u32,
|
||||
_ddata: DispatchData,
|
||||
) {
|
||||
log::debug!("created ZwpTextInputV3 {id} {version}");
|
||||
let mgr = registry.bind::<ZwpTextInputManagerV3>(1, id);
|
||||
self.mgr.replace(mgr.into());
|
||||
}
|
||||
|
||||
fn get(&self) -> std::option::Option<Attached<ZwpTextInputManagerV3>> {
|
||||
self.mgr.clone()
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
#![cfg(all(unix, not(target_os = "macos")))]
|
||||
|
||||
pub mod connection;
|
||||
pub mod inputhandler;
|
||||
pub mod output;
|
||||
pub mod window;
|
||||
pub use self::window::*;
|
||||
@ -10,3 +11,16 @@ mod copy_and_paste;
|
||||
mod drag_and_drop;
|
||||
mod frame;
|
||||
mod pointer;
|
||||
|
||||
/// Returns the id of a wayland proxy object, suitable for using
|
||||
/// a key into hash maps
|
||||
pub fn wl_id<I, T>(obj: T) -> u32
|
||||
where
|
||||
I: wayland_client::Interface,
|
||||
T: AsRef<wayland_client::Proxy<I>>,
|
||||
I: AsRef<wayland_client::Proxy<I>>,
|
||||
I: From<wayland_client::Proxy<I>>,
|
||||
{
|
||||
let proxy: &wayland_client::Proxy<I> = obj.as_ref();
|
||||
proxy.id()
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
//! Dealing with Wayland outputs
|
||||
|
||||
use crate::os::wayland::wl_id;
|
||||
use crate::screen::{ScreenInfo, Screens};
|
||||
use crate::ScreenRect;
|
||||
use smithay_client_toolkit::environment::GlobalHandler;
|
||||
@ -7,7 +8,7 @@ use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use wayland_client::protocol::wl_output::Transform;
|
||||
use wayland_client::protocol::wl_registry::WlRegistry;
|
||||
use wayland_client::{Attached, DispatchData, Interface, Main, Proxy};
|
||||
use wayland_client::{Attached, DispatchData, Main};
|
||||
use wayland_protocols::wlr::unstable::output_management::v1::client::zwlr_output_head_v1::{
|
||||
Event as ZwlrOutputHeadEvent, ZwlrOutputHeadV1,
|
||||
};
|
||||
@ -55,17 +56,6 @@ struct Inner {
|
||||
zwlr_head_info: HashMap<u32, HeadInfo>,
|
||||
}
|
||||
|
||||
fn wl_id<I, T>(obj: T) -> u32
|
||||
where
|
||||
I: Interface,
|
||||
T: AsRef<Proxy<I>>,
|
||||
I: AsRef<wayland_client::Proxy<I>>,
|
||||
I: From<wayland_client::Proxy<I>>,
|
||||
{
|
||||
let proxy: &Proxy<I> = obj.as_ref();
|
||||
proxy.id()
|
||||
}
|
||||
|
||||
impl Inner {
|
||||
fn handle_zwlr_mode_event(
|
||||
&mut self,
|
||||
|
@ -3,9 +3,10 @@ use super::frame::{ConceptConfig, ConceptFrame};
|
||||
use super::pointer::*;
|
||||
use crate::connection::ConnectionOps;
|
||||
use crate::os::wayland::connection::WaylandConnection;
|
||||
use crate::os::wayland::wl_id;
|
||||
use crate::os::x11::keyboard::Keyboard;
|
||||
use crate::{
|
||||
Clipboard, Connection, Dimensions, MouseCursor, Point, RequestedWindowGeometry,
|
||||
Clipboard, Connection, Dimensions, MouseCursor, Point, Rect, RequestedWindowGeometry,
|
||||
ResolvedGeometry, ScreenPoint, Window, WindowEvent, WindowEventSender, WindowKeyEvent,
|
||||
WindowOps, WindowState,
|
||||
};
|
||||
@ -124,7 +125,7 @@ impl KeyRepeatState {
|
||||
|
||||
pub struct WaylandWindowInner {
|
||||
window_id: usize,
|
||||
events: WindowEventSender,
|
||||
pub(crate) events: WindowEventSender,
|
||||
surface: Attached<WlSurface>,
|
||||
surface_factor: i32,
|
||||
copy_and_paste: Arc<Mutex<CopyAndPaste>>,
|
||||
@ -144,6 +145,7 @@ pub struct WaylandWindowInner {
|
||||
frame_callback: Option<Main<WlCallback>>,
|
||||
invalidated: bool,
|
||||
font_config: Rc<FontConfiguration>,
|
||||
text_cursor: Option<Rect>,
|
||||
config: Option<ConfigHandle>,
|
||||
// cache the title for comparison to avoid spamming
|
||||
// the compositor with updates that don't actually change it
|
||||
@ -254,24 +256,21 @@ impl WaylandWindow {
|
||||
|
||||
let (pending_first_configure, wait_configure) = async_channel::bounded(1);
|
||||
|
||||
let surface = conn
|
||||
.environment
|
||||
.borrow_mut()
|
||||
.create_surface_with_scale_callback({
|
||||
let pending_event = Arc::clone(&pending_event);
|
||||
move |dpi, surface, _dispatch_data| {
|
||||
pending_event.lock().unwrap().dpi.replace(dpi);
|
||||
log::debug!(
|
||||
"surface id={} dpi scale changed to {}",
|
||||
surface.as_ref().id(),
|
||||
dpi
|
||||
);
|
||||
WaylandConnection::with_window_inner(window_id, move |inner| {
|
||||
inner.dispatch_pending_event();
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
});
|
||||
let surface = conn.environment.create_surface_with_scale_callback({
|
||||
let pending_event = Arc::clone(&pending_event);
|
||||
move |dpi, surface, _dispatch_data| {
|
||||
pending_event.lock().unwrap().dpi.replace(dpi);
|
||||
log::debug!(
|
||||
"surface id={} dpi scale changed to {}",
|
||||
surface.as_ref().id(),
|
||||
dpi
|
||||
);
|
||||
WaylandConnection::with_window_inner(window_id, move |inner| {
|
||||
inner.dispatch_pending_event();
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
});
|
||||
conn.surface_to_window_id
|
||||
.borrow_mut()
|
||||
.insert(surface.as_ref().id(), window_id);
|
||||
@ -293,7 +292,6 @@ impl WaylandWindow {
|
||||
|
||||
let mut window = conn
|
||||
.environment
|
||||
.borrow()
|
||||
.create_window::<ConceptFrame, _>(
|
||||
surface.clone().detach(),
|
||||
theme_manager,
|
||||
@ -373,6 +371,7 @@ impl WaylandWindow {
|
||||
title: None,
|
||||
gl_state: None,
|
||||
wegl_surface: None,
|
||||
text_cursor: None,
|
||||
}));
|
||||
|
||||
let window_handle = Window::Wayland(WaylandWindow(window_id));
|
||||
@ -461,6 +460,7 @@ impl WaylandWindowInner {
|
||||
mapper.update_modifier_state(0, 0, 0, 0);
|
||||
self.key_repeat.take();
|
||||
self.events.dispatch(WindowEvent::FocusChanged(focused));
|
||||
self.text_cursor.take();
|
||||
}
|
||||
|
||||
pub(crate) fn dispatch_dropped_files(&mut self, paths: Vec<PathBuf>) {
|
||||
@ -897,6 +897,13 @@ impl WindowOps for WaylandWindow {
|
||||
});
|
||||
}
|
||||
|
||||
fn set_text_cursor_position(&self, cursor: Rect) {
|
||||
WaylandConnection::with_window_inner(self.0, move |inner| {
|
||||
inner.set_text_cursor_position(cursor);
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
||||
fn set_title(&self, title: &str) {
|
||||
let title = title.to_owned();
|
||||
WaylandConnection::with_window_inner(self.0, move |inner| {
|
||||
@ -1113,6 +1120,31 @@ impl WaylandWindowInner {
|
||||
}
|
||||
}
|
||||
|
||||
fn set_text_cursor_position(&mut self, rect: Rect) {
|
||||
let surface_id = wl_id(&*self.surface);
|
||||
let conn = Connection::get().unwrap().wayland();
|
||||
if surface_id == *conn.active_surface_id.borrow() {
|
||||
if self.text_cursor.map(|prior| prior != rect).unwrap_or(true) {
|
||||
self.text_cursor.replace(rect);
|
||||
|
||||
conn.environment.with_inner(|env| {
|
||||
if let Some(input) = env
|
||||
.input_handler()
|
||||
.get_text_input_for_surface(&self.surface)
|
||||
{
|
||||
input.set_cursor_rectangle(
|
||||
rect.min_x() as i32,
|
||||
rect.min_y() as i32,
|
||||
rect.width() as i32,
|
||||
rect.height() as i32,
|
||||
);
|
||||
input.commit();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Change the title for the window manager
|
||||
fn set_title(&mut self, title: String) {
|
||||
if let Some(last_title) = self.title.as_ref() {
|
||||
|
@ -344,7 +344,7 @@ impl WindowOps for Window {
|
||||
match self {
|
||||
Self::X11(x) => x.set_text_cursor_position(cursor),
|
||||
#[cfg(feature = "wayland")]
|
||||
Self::Wayland(_) => {}
|
||||
Self::Wayland(w) => w.set_text_cursor_position(cursor),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user