Skip to content

Commit d92ced5

Browse files
committed
wayland: input method protocol
1 parent a5431dd commit d92ced5

22 files changed

+1971
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ boption(SCREENCOPY " Screencopy" ON REQUIRES WAYLAND)
6060
boption(SCREENCOPY_ICC " Image Copy Capture" ON REQUIRES WAYLAND)
6161
boption(SCREENCOPY_WLR " Wlroots Screencopy" ON REQUIRES WAYLAND)
6262
boption(SCREENCOPY_HYPRLAND_TOPLEVEL " Hyprland Toplevel Export" ON REQUIRES WAYLAND)
63+
boption(INPUT_METHOD " Input Method" ON REQUIRES WAYLAND)
6364
boption(X11 "X11" ON)
6465
boption(I3 "I3/Sway" ON)
6566
boption(I3_IPC " I3/Sway IPC" ON REQUIRES I3)

src/wayland/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ if (HYPRLAND)
114114
add_subdirectory(hyprland)
115115
endif()
116116

117+
if (INPUT_METHOD)
118+
add_subdirectory(input_method)
119+
list(APPEND WAYLAND_MODULES Quickshell.Wayland._InputMethod)
120+
endif()
121+
117122
# widgets for qmenu
118123
target_link_libraries(quickshell-wayland PRIVATE
119124
Qt::Quick Qt::Widgets Qt::WaylandClient Qt::WaylandClientPrivate
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
set(INPUT_METHOD_PRINT_KETS OFF)
2+
3+
qt_add_library(quickshell-wayland-input-method STATIC
4+
input_method.cpp
5+
keyboard_grab.cpp
6+
virtual_keyboard.cpp
7+
key_map_state.cpp
8+
manager.cpp
9+
qml.cpp
10+
qml_helpers.cpp
11+
c_helpers.cpp
12+
)
13+
14+
target_compile_definitions(quickshell-wayland-input-method PRIVATE INPUT_METHOD_PRINT=0)
15+
16+
qt_add_qml_module(quickshell-wayland-input-method
17+
URI Quickshell.Wayland._InputMethod
18+
VERSION 0.1
19+
DEPENDENCIES QtQml
20+
)
21+
22+
qs_add_module_deps_light(quickshell-wayland-input-method
23+
Quickshell Quickshell.Wayland
24+
)
25+
26+
install_qml_module(quickshell-wayland-input-method)
27+
28+
wl_proto(zwp-input-method input-method-unstable-v2 "${CMAKE_CURRENT_SOURCE_DIR}")
29+
wl_proto(zwp-virtual-keyboard virtual-keyboard-unstable-v1 "${CMAKE_CURRENT_SOURCE_DIR}")
30+
31+
target_link_libraries(quickshell-wayland-input-method PRIVATE
32+
Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
33+
zwp-input-method zwp-virtual-keyboard
34+
)
35+
36+
qs_module_pch(quickshell-wayland-input-method SET large)
37+
38+
target_link_libraries(quickshell PRIVATE quickshell-wayland-input-methodplugin)
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include "c_helpers.hpp"
2+
#include <cstddef>
3+
#include <cstdio>
4+
#include <cstring>
5+
#include <utility>
6+
7+
#include <qdebug.h>
8+
#include <qlogging.h>
9+
#include <sys/mman.h>
10+
#include <sys/shm.h>
11+
#include <unistd.h>
12+
13+
namespace qs::wayland::input_method::impl {
14+
15+
void FreeDeleter::operator()(const char* p) const {
16+
std::free(const_cast<std::remove_const_t<char>*>(p)); // NOLINT
17+
}
18+
19+
SharedMemory::SharedMemory(const char* shmName, int oFlag, size_t size)
20+
: mShmName(shmName)
21+
, mSize(size)
22+
, fd(shm_open(this->mShmName, oFlag, 0))
23+
, map(nullptr) {
24+
if (this->fd == -1) {
25+
perror("");
26+
qDebug() << "Virtual keyboard failed to open shared memory";
27+
return;
28+
}
29+
if (ftruncate(this->fd, static_cast<int>(size)) == -1) {
30+
this->fd = -1;
31+
perror("");
32+
qDebug() << "Virtual keyboard failed to resize shared memory to" << size;
33+
return;
34+
}
35+
this->map = static_cast<char*>(mmap(nullptr, this->mSize, PROT_WRITE, MAP_SHARED, this->fd, 0));
36+
if (this->map == MAP_FAILED) {
37+
perror("");
38+
qDebug() << "Virtual keyboard failed to open shared memory";
39+
return;
40+
}
41+
}
42+
SharedMemory::~SharedMemory() {
43+
if (this->fd != -1) {
44+
close(this->fd);
45+
shm_unlink(this->mShmName);
46+
}
47+
if (this->map != nullptr) {
48+
munmap(this->map, this->mSize);
49+
}
50+
}
51+
SharedMemory::SharedMemory(SharedMemory&& other) noexcept
52+
: mShmName(std::exchange(other.mShmName, nullptr))
53+
, mSize(std::exchange(other.mSize, 0))
54+
, fd(std::exchange(other.fd, -1))
55+
, map(std::exchange(other.map, nullptr)) {}
56+
SharedMemory& SharedMemory::operator=(SharedMemory&& other) noexcept {
57+
this->mShmName = std::exchange(other.mShmName, nullptr);
58+
this->mSize = std::exchange(other.mSize, 0);
59+
this->fd = std::exchange(other.fd, -1);
60+
this->map = std::exchange(other.map, nullptr);
61+
return *this;
62+
}
63+
64+
SharedMemory::operator bool() const { return fd != -1 && map != MAP_FAILED; }
65+
[[nodiscard]] int SharedMemory::get() const { return fd; }
66+
67+
void SharedMemory::write(const char* string) {
68+
if (!this->map) return;
69+
strcpy(this->map, string);
70+
}
71+
72+
} // namespace qs::wayland::input_method::impl
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#pragma once
2+
3+
#include <memory>
4+
5+
#include <sys/mman.h>
6+
7+
namespace qs::wayland::input_method::impl {
8+
9+
struct FreeDeleter {
10+
void operator()(const char* p) const;
11+
};
12+
// Dont use this for literals, only c strings that were allocated
13+
using uniqueCString = std::unique_ptr<const char, FreeDeleter>;
14+
15+
// this is a bit half baked but works for what I need it for
16+
class SharedMemory {
17+
public:
18+
SharedMemory(const char* shmName, int oFlag, size_t size);
19+
~SharedMemory();
20+
SharedMemory(const SharedMemory&) = delete;
21+
SharedMemory(SharedMemory&& other) noexcept;
22+
SharedMemory& operator=(const SharedMemory&) = delete;
23+
SharedMemory& operator=(SharedMemory&& other) noexcept;
24+
25+
[[nodiscard]] operator bool() const;
26+
[[nodiscard]] int get() const;
27+
28+
void write(const char* string);
29+
30+
private:
31+
const char* mShmName;
32+
size_t mSize;
33+
int fd;
34+
char* map = nullptr;
35+
};
36+
37+
} // namespace qs::wayland::input_method::impl

0 commit comments

Comments
 (0)