Skip to content

Commit

Permalink
feat: support ext-virtual-keyboard
Browse files Browse the repository at this point in the history
  • Loading branch information
Decodetalkers committed Apr 2, 2024
1 parent 55e5a5a commit 7873dac
Show file tree
Hide file tree
Showing 8 changed files with 345 additions and 14 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions iced_examples/counter_virtual_keyboard/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "counter_virtual_keyboard"
authors.workspace = true
edition.workspace = true
version.workspace = true
license.workspace = true
repository.workspace = true
description.workspace = true
keywords.workspace = true
readme.workspace = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
iced.workspace = true
iced_runtime.workspace = true
iced_layershell.workspace = true
xkbcommon = "0.6.0"
tempfile.workspace = true
207 changes: 207 additions & 0 deletions iced_examples/counter_virtual_keyboard/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
use std::ffi::CString;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

use iced::widget::{button, column, row, text, text_input};
use iced::{Alignment, Command, Element, Length, Theme};
use iced_layershell::actions::LayershellCustomActions;
use iced_layershell::reexport::{Anchor, KeyboardInteractivity};
use iced_layershell::settings::{LayerShellSettings, Settings, VirtualKeyboardSettings};
use iced_layershell::Application;

use iced_layershell::reexport::wl_keyboard::{KeyState, KeymapFormat};
use xkbcommon::xkb;

pub fn get_keymap_as_file() -> (File, u32) {
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);

let keymap = xkb::Keymap::new_from_names(
&context,
"",
"",
"us", // if no , it is norwegian
"",
None,
xkb::KEYMAP_COMPILE_NO_FLAGS,
)
.expect("xkbcommon keymap panicked!");
let xkb_state = xkb::State::new(&keymap);
let keymap = xkb_state
.get_keymap()
.get_as_string(xkb::KEYMAP_FORMAT_TEXT_V1);
let keymap = CString::new(keymap).expect("Keymap should not contain interior nul bytes");
let keymap = keymap.as_bytes_with_nul();
let dir = std::env::var_os("XDG_RUNTIME_DIR")
.map(PathBuf::from)
.unwrap_or_else(std::env::temp_dir);
let mut file = tempfile::tempfile_in(dir).expect("File could not be created!");
file.write_all(keymap).unwrap();
file.flush().unwrap();
(file, keymap.len() as u32)
}

pub fn main() -> Result<(), iced_layershell::Error> {
let (file, keymap_size) = get_keymap_as_file();
Counter::run(Settings {
layer_settings: LayerShellSettings {
size: Some((0, 400)),
exclusize_zone: 400,
anchor: Anchor::Bottom | Anchor::Left | Anchor::Right,
keyboard_interactivity: KeyboardInteractivity::None,
..Default::default()
},
virtual_keyboard_support: Some(VirtualKeyboardSettings {
file,
keymap_size,
keymap_format: KeymapFormat::XkbV1,
}),
..Default::default()
})
}

struct Counter {
value: i32,
text: String,
}

#[derive(Debug, Clone, Copy)]
enum WindowDirection {
Top,
Left,
Right,
Bottom,
}

#[derive(Debug, Clone)]
enum Message {
IncrementPressed,
DecrementPressed,
TextInput(String),
Direction(WindowDirection),
InputTest,
}

impl Application for Counter {
type Message = Message;
type Flags = ();
type Theme = Theme;
type Executor = iced::executor::Default;

fn new(_flags: ()) -> (Self, Command<Message>) {
(
Self {
value: 0,
text: "eee".to_string(),
},
Command::none(),
)
}

fn namespace(&self) -> String {
String::from("Counter - Iced")
}

fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::IncrementPressed => {
self.value += 1;
Command::none()
}
Message::DecrementPressed => {
self.value -= 1;
Command::none()
}
Message::TextInput(text) => {
self.text = text;
Command::none()
}
Message::InputTest => Command::single(
LayershellCustomActions::VirtualKeyboardPressed {
time: 100,
key: 16,
keystate: KeyState::Pressed,
}
.into(),
),
Message::Direction(direction) => match direction {
WindowDirection::Left => Command::batch(vec![
Command::single(
LayershellCustomActions::AnchorChange(
Anchor::Left | Anchor::Top | Anchor::Bottom,
)
.into(),
),
Command::single(LayershellCustomActions::SizeChange((400, 0)).into()),
]),
WindowDirection::Right => Command::batch(vec![
Command::single(
LayershellCustomActions::AnchorChange(
Anchor::Right | Anchor::Top | Anchor::Bottom,
)
.into(),
),
Command::single(LayershellCustomActions::SizeChange((400, 0)).into()),
]),
WindowDirection::Bottom => Command::batch(vec![
Command::single(
LayershellCustomActions::AnchorChange(
Anchor::Bottom | Anchor::Left | Anchor::Right,
)
.into(),
),
Command::single(LayershellCustomActions::SizeChange((0, 400)).into()),
]),
WindowDirection::Top => Command::batch(vec![
Command::single(
LayershellCustomActions::AnchorChange(
Anchor::Top | Anchor::Left | Anchor::Right,
)
.into(),
),
Command::single(LayershellCustomActions::SizeChange((0, 400)).into()),
]),
},
}
}

fn view(&self) -> Element<Message> {
let center = column![
button("Increment").on_press(Message::IncrementPressed),
text(self.value).size(50),
button("test_q").on_press(Message::InputTest),
button("Decrement").on_press(Message::DecrementPressed)
]
.padding(20)
.align_items(Alignment::Center)
.width(Length::Fill)
.height(Length::Fill);
row![
button("left")
.on_press(Message::Direction(WindowDirection::Left))
.height(Length::Fill),
column![
button("top")
.on_press(Message::Direction(WindowDirection::Top))
.width(Length::Fill),
center,
text_input("hello", &self.text)
.on_input(Message::TextInput)
.padding(10),
button("bottom")
.on_press(Message::Direction(WindowDirection::Bottom))
.width(Length::Fill),
]
.width(Length::Fill),
button("right")
.on_press(Message::Direction(WindowDirection::Right))
.height(Length::Fill),
]
.padding(20)
.spacing(10)
.align_items(Alignment::Center)
.width(Length::Fill)
.height(Length::Fill)
.into()
}
}
7 changes: 6 additions & 1 deletion iced_layershell/src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::reexport::{Anchor, Layer};
use iced::window::Id as IcedId;
use iced_core::mouse::Interaction;
use iced_runtime::command::Action;
use layershellev::id::Id as LayerId;
use layershellev::{id::Id as LayerId, reexport::wayland_client::KeyState};
#[allow(unused)]
#[derive(Debug, Clone)]
pub(crate) enum LayerShellActions {
Expand All @@ -18,6 +18,11 @@ pub enum LayershellCustomActions {
AnchorChange(Anchor),
LayerChange(Layer),
SizeChange((u32, u32)),
VirtualKeyboardPressed {
time: u32,
key: u32,
keystate: KeyState,
},
}

#[derive(Debug, Clone, Copy)]
Expand Down
48 changes: 43 additions & 5 deletions iced_layershell/src/application.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
mod state;

use std::{mem::ManuallyDrop, sync::Arc};
use std::{mem::ManuallyDrop, os::fd::AsFd, sync::Arc};

use crate::{
actions::{LayerShellActions, LayershellCustomActions},
clipboard::LayerShellClipboard,
conversion,
error::Error,
settings::VirtualKeyboardSettings,
};

use iced_graphics::Compositor;
Expand All @@ -21,7 +22,10 @@ use iced_style::application::StyleSheet;
use iced_futures::{Executor, Runtime, Subscription};

use layershellev::{
reexport::wayland_client::{KeyState, WEnum},
reexport::{
wayland_client::{KeyState, WEnum},
zwp_virtual_keyboard_v1,
},
LayerEvent, ReturnData, WindowState, WindowWrapper,
};

Expand Down Expand Up @@ -192,12 +196,36 @@ where
let mut key_event: Option<IcedLayerEvent<A::Message>> = None;
let mut key_ping_count: u32 = 400;

let mut virtuan_keyboard = None;
let _ = ev.running_with_proxy(message_receiver, move |event, ev, _| {
use layershellev::DispatchMessage;
let mut def_returndata = ReturnData::None;
match event {
LayerEvent::InitRequest => {}
LayerEvent::InitRequest => {
if settings.virtual_keyboard_support.is_some() {
def_returndata = ReturnData::RequestBind;
}
}
// TODO: maybe use it later
LayerEvent::BindProvide(_, _) => {}
LayerEvent::BindProvide(globals, qh) => {
let virtual_keyboard_manager = globals
.bind::<zwp_virtual_keyboard_v1::ZwpVirtualKeyboardManagerV1, _, _>(
qh,
1..=1,
(),
)
.expect("no support virtual_keyboard");
let VirtualKeyboardSettings {
file,
keymap_size,
keymap_format,
} = settings.virtual_keyboard_support.as_ref().unwrap();
let seat = ev.get_seat();
let virtual_keyboard_in =
virtual_keyboard_manager.create_virtual_keyboard(seat, qh, ());
virtual_keyboard_in.keymap((*keymap_format).into(), file.as_fd(), *keymap_size);
virtuan_keyboard = Some(virtual_keyboard_in);
}
LayerEvent::RequestMessages(message) => {
match message {
DispatchMessage::MouseEnter { serial, .. } => {
Expand Down Expand Up @@ -268,6 +296,16 @@ where
LayershellCustomActions::SizeChange((width, height)) => {
ev.main_window().set_size((width, height));
}
LayershellCustomActions::VirtualKeyboardPressed {
time,
key,
keystate,
} => {
virtuan_keyboard
.as_ref()
.unwrap()
.key(time, key, keystate.into());
}
}
}
}
Expand All @@ -292,7 +330,7 @@ where
}
}
}
ReturnData::None
def_returndata
}
task::Poll::Ready(_) => ReturnData::RequestExist,
}
Expand Down
1 change: 1 addition & 0 deletions iced_layershell/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub mod reexport {
pub use layershellev::reexport::Anchor;
pub use layershellev::reexport::KeyboardInteractivity;
pub use layershellev::reexport::Layer;
pub use layershellev::reexport::wayland_client::wl_keyboard;
}

use settings::Settings;
Expand Down
Loading

0 comments on commit 7873dac

Please sign in to comment.