mirror of
https://github.com/wez/wezterm.git
synced 2025-01-03 03:04:04 +03:00
IME support on X11 (#1043)
* WIP: IME support for X11 * Handle text generated by IME. * Set IME position according to the cursor position. * Improve IME position handling. Geometry as well as window focus changes are now handled. * Dispatch IME strings like it's done on windows. * Make sure not to silently drop IME errors. * Respect `use_ime` configuration. * Add xcb-util as dependency. * Only update IME position if necessary. * Formatting. * Update xcb-imdkit-rs. * Set IME position under the start of the cursor. This seems to be the way it is commonly done among gui frameworks. (Tested with Firefox for GTK and Konsole for QT). * Update xcb-imdkit-rs. * Handle systems only providing libxcb-util0-dev. * Add libxcb to freebsd dependencies. Required by xcb-imdkit-rs. * Update xcb-imdkit-rs. * Try to use more recent gcc on centos7. * More recent C++ compiler on centos7 as well. * Also setup correct env on centos7 for tests.
This commit is contained in:
parent
98206f0bf8
commit
6404099d25
17
.github/workflows/gen_centos7.yml
vendored
17
.github/workflows/gen_centos7.yml
vendored
@ -31,9 +31,10 @@ jobs:
|
|||||||
- name: "Install Git from source"
|
- name: "Install Git from source"
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
|
||||||
yum install -y wget curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker make
|
yum install -y wget curl-devel expat-devel gettext-devel openssl-devel zlib-devel centos-release-scl-rh perl-ExtUtils-MakeMaker make
|
||||||
|
yum install -y devtoolset-9-gcc devtoolset-9-gcc-c++
|
||||||
|
|
||||||
if test ! -x /usr/local/git/bin/git ; then
|
if test ! -x /usr/local/git/bin/git ; then
|
||||||
cd /tmp
|
cd /tmp
|
||||||
wget https://github.com/git/git/archive/v2.26.2.tar.gz
|
wget https://github.com/git/git/archive/v2.26.2.tar.gz
|
||||||
@ -41,9 +42,9 @@ jobs:
|
|||||||
cd git-2.26.2
|
cd git-2.26.2
|
||||||
make prefix=/usr/local/git install
|
make prefix=/usr/local/git install
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ln -s /usr/local/git/bin/git /usr/local/bin/git
|
ln -s /usr/local/git/bin/git /usr/local/bin/git
|
||||||
|
|
||||||
|
|
||||||
- name: "Install curl"
|
- name: "Install curl"
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -84,10 +85,10 @@ jobs:
|
|||||||
run: "cargo fmt --all -- --check"
|
run: "cargo fmt --all -- --check"
|
||||||
- name: "Build (Release mode)"
|
- name: "Build (Release mode)"
|
||||||
shell: bash
|
shell: bash
|
||||||
run: "cargo build --all --release"
|
run: "source /opt/rh/devtoolset-9/enable && cargo build --all --release"
|
||||||
- name: "Test (Release mode)"
|
- name: "Test (Release mode)"
|
||||||
shell: bash
|
shell: bash
|
||||||
run: "cargo test --all --release"
|
run: "source /opt/rh/devtoolset-9/enable && cargo test --all --release"
|
||||||
- name: "Package"
|
- name: "Package"
|
||||||
shell: bash
|
shell: bash
|
||||||
run: "bash ci/deploy.sh"
|
run: "bash ci/deploy.sh"
|
||||||
@ -96,7 +97,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir pkg_
|
mkdir pkg_
|
||||||
mv ~/rpmbuild/RPMS/*/*.rpm pkg_
|
mv ~/rpmbuild/RPMS/*/*.rpm pkg_
|
||||||
|
|
||||||
|
|
||||||
- name: "Upload artifact"
|
- name: "Upload artifact"
|
||||||
uses: actions/upload-artifact@master
|
uses: actions/upload-artifact@master
|
||||||
|
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -5339,6 +5339,7 @@ dependencies = [
|
|||||||
"winreg 0.6.2",
|
"winreg 0.6.2",
|
||||||
"x11",
|
"x11",
|
||||||
"xcb 0.9.0",
|
"xcb 0.9.0",
|
||||||
|
"xcb-imdkit",
|
||||||
"xcb-util",
|
"xcb-util",
|
||||||
"xkbcommon",
|
"xkbcommon",
|
||||||
]
|
]
|
||||||
@ -5453,6 +5454,18 @@ dependencies = [
|
|||||||
"x11",
|
"x11",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xcb-imdkit"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/H-M-H/xcb-imdkit-rs#3cb940863f64d13a9cdbc09eea67d2a69e0a2737"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cc",
|
||||||
|
"lazy_static",
|
||||||
|
"pkg-config",
|
||||||
|
"xcb 0.9.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xcb-util"
|
name = "xcb-util"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
7
get-deps
7
get-deps
@ -77,6 +77,7 @@ if test -e /etc/centos-release || test -e /etc/fedora-release; then
|
|||||||
libxkbcommon-x11-devel \
|
libxkbcommon-x11-devel \
|
||||||
wayland-devel \
|
wayland-devel \
|
||||||
mesa-libEGL-devel \
|
mesa-libEGL-devel \
|
||||||
|
xcb-util-devel \
|
||||||
xcb-util-keysyms-devel \
|
xcb-util-keysyms-devel \
|
||||||
xcb-util-image-devel \
|
xcb-util-image-devel \
|
||||||
xcb-util-wm-devel \
|
xcb-util-wm-devel \
|
||||||
@ -101,6 +102,7 @@ if test -x /usr/bin/lsb_release && test `lsb_release -si` = "openSUSE"; then
|
|||||||
libxkbcommon-x11-devel \
|
libxkbcommon-x11-devel \
|
||||||
wayland-devel \
|
wayland-devel \
|
||||||
Mesa-libEGL-devel \
|
Mesa-libEGL-devel \
|
||||||
|
xcb-util-devel \
|
||||||
xcb-util-keysyms-devel \
|
xcb-util-keysyms-devel \
|
||||||
xcb-util-image-devel \
|
xcb-util-image-devel \
|
||||||
xcb-util-wm-devel \
|
xcb-util-wm-devel \
|
||||||
@ -110,6 +112,7 @@ fi
|
|||||||
|
|
||||||
if test -e /etc/debian_version ; then
|
if test -e /etc/debian_version ; then
|
||||||
APT="$SUDO apt-get"
|
APT="$SUDO apt-get"
|
||||||
|
apt-cache show libxcb-util-dev > /dev/null 2>&1 && XCBUTIL="libxcb-util-dev" || XCBUTIL="libxcb-util0-dev"
|
||||||
$APT install -y \
|
$APT install -y \
|
||||||
bsdutils \
|
bsdutils \
|
||||||
cmake \
|
cmake \
|
||||||
@ -130,6 +133,7 @@ if test -e /etc/debian_version ; then
|
|||||||
libxcb-xkb-dev \
|
libxcb-xkb-dev \
|
||||||
libxkbcommon-dev \
|
libxkbcommon-dev \
|
||||||
libxkbcommon-x11-dev \
|
libxkbcommon-x11-dev \
|
||||||
|
"$XCBUTIL" \
|
||||||
lsb-release \
|
lsb-release \
|
||||||
python3 \
|
python3 \
|
||||||
xdg-utils \
|
xdg-utils \
|
||||||
@ -151,6 +155,7 @@ if test -e /etc/arch-release ; then
|
|||||||
'python3' \
|
'python3' \
|
||||||
'rust' \
|
'rust' \
|
||||||
'wayland' \
|
'wayland' \
|
||||||
|
'xcb-util' \
|
||||||
'xcb-util-image' \
|
'xcb-util-image' \
|
||||||
'xcb-util-keysyms' \
|
'xcb-util-keysyms' \
|
||||||
'xcb-util-wm'
|
'xcb-util-wm'
|
||||||
@ -183,6 +188,8 @@ case $OSTYPE in
|
|||||||
python3 \
|
python3 \
|
||||||
rust \
|
rust \
|
||||||
wayland \
|
wayland \
|
||||||
|
libxcb \
|
||||||
|
xcb-util \
|
||||||
xcb-util-image \
|
xcb-util-image \
|
||||||
xcb-util-keysyms \
|
xcb-util-keysyms \
|
||||||
xcb-util-wm \
|
xcb-util-wm \
|
||||||
|
@ -73,6 +73,7 @@ smithay-client-toolkit = {version = "0.14", default-features=false, optional=tru
|
|||||||
wayland-protocols = {version="0.28", optional=true}
|
wayland-protocols = {version="0.28", optional=true}
|
||||||
wayland-client = {version="0.28", optional=true}
|
wayland-client = {version="0.28", optional=true}
|
||||||
wayland-egl = {version="0.28", optional=true}
|
wayland-egl = {version="0.28", optional=true}
|
||||||
|
xcb-imdkit = { version="0.1", git = "https://github.com/H-M-H/xcb-imdkit-rs" }
|
||||||
|
|
||||||
[target.'cfg(target_os="macos")'.dependencies]
|
[target.'cfg(target_os="macos")'.dependencies]
|
||||||
cocoa = "0.20"
|
cocoa = "0.20"
|
||||||
|
@ -46,6 +46,8 @@ pub struct XConnection {
|
|||||||
pub(crate) visual: xcb::xproto::Visualtype,
|
pub(crate) visual: xcb::xproto::Visualtype,
|
||||||
pub(crate) depth: u8,
|
pub(crate) depth: u8,
|
||||||
pub(crate) gl_connection: RefCell<Option<Rc<crate::egl::GlConnection>>>,
|
pub(crate) gl_connection: RefCell<Option<Rc<crate::egl::GlConnection>>>,
|
||||||
|
pub(crate) ime: RefCell<std::pin::Pin<Box<xcb_imdkit::ImeClient>>>,
|
||||||
|
pub(crate) ime_process_event_result: RefCell<anyhow::Result<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::Deref for XConnection {
|
impl std::ops::Deref for XConnection {
|
||||||
@ -275,7 +277,7 @@ impl XConnection {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(event) => {
|
Some(event) => {
|
||||||
if let Err(err) = self.process_xcb_event(&event) {
|
if let Err(err) = self.process_xcb_event_ime(&event) {
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -285,12 +287,23 @@ impl XConnection {
|
|||||||
loop {
|
loop {
|
||||||
match self.conn.poll_for_queued_event() {
|
match self.conn.poll_for_queued_event() {
|
||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
Some(event) => self.process_xcb_event(&event)?,
|
Some(event) => self.process_xcb_event_ime(&event)?,
|
||||||
}
|
}
|
||||||
self.conn.flush();
|
self.conn.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn process_xcb_event_ime(&self, event: &xcb::GenericEvent) -> anyhow::Result<()> {
|
||||||
|
// check for previous errors produced by the IME forward_event callback
|
||||||
|
self.ime_process_event_result.replace(Ok(()))?;
|
||||||
|
|
||||||
|
if config::configuration().use_ime && self.ime.borrow_mut().process_event(event) {
|
||||||
|
self.ime_process_event_result.replace(Ok(()))
|
||||||
|
} else {
|
||||||
|
self.process_xcb_event(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn process_xcb_event(&self, event: &xcb::GenericEvent) -> anyhow::Result<()> {
|
fn process_xcb_event(&self, event: &xcb::GenericEvent) -> anyhow::Result<()> {
|
||||||
if let Some(window_id) = window_id_from_event(event) {
|
if let Some(window_id) = window_id_from_event(event) {
|
||||||
self.process_window_event(window_id, event)?;
|
self.process_window_event(window_id, event)?;
|
||||||
@ -326,7 +339,7 @@ impl XConnection {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn create_new() -> anyhow::Result<XConnection> {
|
pub(crate) fn create_new() -> anyhow::Result<Rc<XConnection>> {
|
||||||
let (conn, screen_num) = connect_with_xlib_display()?;
|
let (conn, screen_num) = connect_with_xlib_display()?;
|
||||||
let conn = xcb_util::ewmh::Connection::connect(conn)
|
let conn = xcb_util::ewmh::Connection::connect(conn)
|
||||||
.map_err(|_| anyhow!("failed to init ewmh"))?;
|
.map_err(|_| anyhow!("failed to init ewmh"))?;
|
||||||
@ -441,7 +454,17 @@ impl XConnection {
|
|||||||
|
|
||||||
let default_dpi = RefCell::new(compute_default_dpi(&xrm, &xsettings));
|
let default_dpi = RefCell::new(compute_default_dpi(&xrm, &xsettings));
|
||||||
|
|
||||||
let conn = XConnection {
|
xcb_imdkit::ImeClient::set_logger(|msg| log::debug!("Ime: {}", msg));
|
||||||
|
let ime = unsafe {
|
||||||
|
xcb_imdkit::ImeClient::unsafe_new(
|
||||||
|
&conn,
|
||||||
|
screen_num,
|
||||||
|
xcb_imdkit::InputStyle::DEFAULT,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let conn = Rc::new(XConnection {
|
||||||
conn,
|
conn,
|
||||||
default_dpi,
|
default_dpi,
|
||||||
xsettings: RefCell::new(xsettings),
|
xsettings: RefCell::new(xsettings),
|
||||||
@ -472,7 +495,36 @@ impl XConnection {
|
|||||||
depth,
|
depth,
|
||||||
visual,
|
visual,
|
||||||
gl_connection: RefCell::new(None),
|
gl_connection: RefCell::new(None),
|
||||||
};
|
ime: RefCell::new(ime),
|
||||||
|
ime_process_event_result: RefCell::new(Ok(())),
|
||||||
|
});
|
||||||
|
|
||||||
|
{
|
||||||
|
let conn = conn.clone();
|
||||||
|
conn.clone()
|
||||||
|
.ime
|
||||||
|
.borrow_mut()
|
||||||
|
.set_commit_string_cb(move |window_id, input| {
|
||||||
|
if let Some(window) = conn.window_by_id(window_id) {
|
||||||
|
let mut inner = window.lock().unwrap();
|
||||||
|
inner.dispatch_ime_text(input);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let conn = conn.clone();
|
||||||
|
conn.clone()
|
||||||
|
.ime
|
||||||
|
.borrow_mut()
|
||||||
|
.set_forward_event_cb(move |_win, e| {
|
||||||
|
if let err @ Err(_) = conn.process_xcb_event(unsafe { std::mem::transmute(e) })
|
||||||
|
{
|
||||||
|
if let Err(err) = conn.ime_process_event_result.replace(err) {
|
||||||
|
log::warn!("IME process event error dropped: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Ok(conn)
|
Ok(conn)
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@ use crate::os::xkeysyms;
|
|||||||
use crate::os::{Connection, Window};
|
use crate::os::{Connection, Window};
|
||||||
use crate::{
|
use crate::{
|
||||||
Appearance, Clipboard, Dimensions, MouseButtons, MouseCursor, MouseEvent, MouseEventKind,
|
Appearance, Clipboard, Dimensions, MouseButtons, MouseCursor, MouseEvent, MouseEventKind,
|
||||||
MousePress, Point, ScreenPoint, WindowDecorations, WindowEvent, WindowEventSender, WindowOps,
|
MousePress, Point, Rect, ScreenPoint, WindowDecorations, WindowEvent, WindowEventSender,
|
||||||
WindowState,
|
WindowOps, WindowState,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Context as _};
|
use anyhow::{anyhow, Context as _};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
@ -19,6 +19,7 @@ use std::convert::TryInto;
|
|||||||
use std::rc::{Rc, Weak};
|
use std::rc::{Rc, Weak};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use wezterm_font::FontConfiguration;
|
use wezterm_font::FontConfiguration;
|
||||||
|
use wezterm_input_types::{KeyCode, KeyEvent, Modifiers};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct CopyAndPaste {
|
struct CopyAndPaste {
|
||||||
@ -64,6 +65,8 @@ pub(crate) struct XWindowInner {
|
|||||||
config: ConfigHandle,
|
config: ConfigHandle,
|
||||||
appearance: Appearance,
|
appearance: Appearance,
|
||||||
title: String,
|
title: String,
|
||||||
|
has_focus: bool,
|
||||||
|
last_cursor_position: Rect,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for XWindowInner {
|
impl Drop for XWindowInner {
|
||||||
@ -167,6 +170,8 @@ impl XWindowInner {
|
|||||||
self.expose(expose.x(), expose.y(), expose.width(), expose.height());
|
self.expose(expose.x(), expose.y(), expose.width(), expose.height());
|
||||||
}
|
}
|
||||||
xcb::CONFIGURE_NOTIFY => {
|
xcb::CONFIGURE_NOTIFY => {
|
||||||
|
self.update_ime_position();
|
||||||
|
|
||||||
let cfg: &xcb::ConfigureNotifyEvent = unsafe { xcb::cast_event(event) };
|
let cfg: &xcb::ConfigureNotifyEvent = unsafe { xcb::cast_event(event) };
|
||||||
let width = cfg.width();
|
let width = cfg.width();
|
||||||
let height = cfg.height();
|
let height = cfg.height();
|
||||||
@ -331,10 +336,13 @@ impl XWindowInner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
xcb::FOCUS_IN => {
|
xcb::FOCUS_IN => {
|
||||||
|
self.has_focus = true;
|
||||||
|
self.update_ime_position();
|
||||||
log::trace!("Calling focus_change(true)");
|
log::trace!("Calling focus_change(true)");
|
||||||
self.events.dispatch(WindowEvent::FocusChanged(true));
|
self.events.dispatch(WindowEvent::FocusChanged(true));
|
||||||
}
|
}
|
||||||
xcb::FOCUS_OUT => {
|
xcb::FOCUS_OUT => {
|
||||||
|
self.has_focus = false;
|
||||||
log::trace!("Calling focus_change(false)");
|
log::trace!("Calling focus_change(false)");
|
||||||
self.events.dispatch(WindowEvent::FocusChanged(false));
|
self.events.dispatch(WindowEvent::FocusChanged(false));
|
||||||
}
|
}
|
||||||
@ -346,6 +354,20 @@ impl XWindowInner {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn dispatch_ime_text(&mut self, text: &str) {
|
||||||
|
let key_event = KeyEvent {
|
||||||
|
key: KeyCode::Composed(text.into()),
|
||||||
|
raw_key: None,
|
||||||
|
raw_modifiers: Modifiers::NONE,
|
||||||
|
raw_code: None,
|
||||||
|
modifiers: Modifiers::NONE,
|
||||||
|
repeat_count: 1,
|
||||||
|
key_is_down: true,
|
||||||
|
}
|
||||||
|
.normalize_shift();
|
||||||
|
self.events.dispatch(WindowEvent::KeyEvent(key_event));
|
||||||
|
}
|
||||||
|
|
||||||
/// If we own the selection, make sure that the X server reflects
|
/// If we own the selection, make sure that the X server reflects
|
||||||
/// that and vice versa.
|
/// that and vice versa.
|
||||||
fn update_selection_owner(&mut self, clipboard: Clipboard) {
|
fn update_selection_owner(&mut self, clipboard: Clipboard) {
|
||||||
@ -758,6 +780,8 @@ impl XWindow {
|
|||||||
copy_and_paste: CopyAndPaste::default(),
|
copy_and_paste: CopyAndPaste::default(),
|
||||||
cursors: CursorInfo::new(&conn),
|
cursors: CursorInfo::new(&conn),
|
||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
|
has_focus: false,
|
||||||
|
last_cursor_position: Rect::default(),
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -872,6 +896,25 @@ impl XWindowInner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_text_cursor_position(&mut self, cursor: Rect) {
|
||||||
|
if self.last_cursor_position == cursor {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.last_cursor_position = cursor;
|
||||||
|
self.update_ime_position();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_ime_position(&mut self) {
|
||||||
|
if !self.has_focus {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.conn().ime.borrow_mut().update_pos(
|
||||||
|
self.window_id,
|
||||||
|
self.last_cursor_position.min_x() as i16,
|
||||||
|
self.last_cursor_position.max_y() as i16,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn set_icon(&mut self, image: &dyn BitmapImage) {
|
fn set_icon(&mut self, image: &dyn BitmapImage) {
|
||||||
let (width, height) = image.image_dimensions();
|
let (width, height) = image.image_dimensions();
|
||||||
|
|
||||||
@ -1012,6 +1055,13 @@ impl WindowOps for XWindow {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_text_cursor_position(&self, cursor: Rect) {
|
||||||
|
XConnection::with_window_inner(self.0, move |inner| {
|
||||||
|
inner.set_text_cursor_position(cursor);
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn set_icon(&self, image: Image) {
|
fn set_icon(&self, image: Image) {
|
||||||
XConnection::with_window_inner(self.0, move |inner| {
|
XConnection::with_window_inner(self.0, move |inner| {
|
||||||
inner.set_icon(&image);
|
inner.set_icon(&image);
|
||||||
|
@ -7,7 +7,7 @@ use crate::os::wayland::connection::WaylandConnection;
|
|||||||
use crate::os::wayland::window::WaylandWindow;
|
use crate::os::wayland::window::WaylandWindow;
|
||||||
use crate::os::x11::connection::XConnection;
|
use crate::os::x11::connection::XConnection;
|
||||||
use crate::os::x11::window::XWindow;
|
use crate::os::x11::window::XWindow;
|
||||||
use crate::{Clipboard, MouseCursor, ScreenPoint, WindowEvent, WindowOps};
|
use crate::{Clipboard, MouseCursor, Rect, ScreenPoint, WindowEvent, WindowOps};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use config::ConfigHandle;
|
use config::ConfigHandle;
|
||||||
use promise::*;
|
use promise::*;
|
||||||
@ -43,7 +43,7 @@ impl Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Connection::X11(Rc::new(XConnection::create_new()?)))
|
Ok(Connection::X11(XConnection::create_new()?))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn new_window<F>(
|
pub async fn new_window<F>(
|
||||||
@ -277,6 +277,12 @@ impl WindowOps for Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_text_cursor_position(&self, cursor: Rect) {
|
||||||
|
if let Self::X11(x) = self {
|
||||||
|
x.set_text_cursor_position(cursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_clipboard(&self, clipboard: Clipboard) -> Future<String> {
|
fn get_clipboard(&self, clipboard: Clipboard) -> Future<String> {
|
||||||
match self {
|
match self {
|
||||||
Self::X11(x) => x.get_clipboard(clipboard),
|
Self::X11(x) => x.get_clipboard(clipboard),
|
||||||
|
Loading…
Reference in New Issue
Block a user