Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ boption(SCREENCOPY " Screencopy" ON REQUIRES WAYLAND)
boption(SCREENCOPY_ICC " Image Copy Capture" ON REQUIRES WAYLAND)
boption(SCREENCOPY_WLR " Wlroots Screencopy" ON REQUIRES WAYLAND)
boption(SCREENCOPY_HYPRLAND_TOPLEVEL " Hyprland Toplevel Export" ON REQUIRES WAYLAND)
boption(INPUT_METHOD " Input Method" ON REQUIRES WAYLAND)
boption(X11 "X11" ON)
boption(I3 "I3/Sway" ON)
boption(I3_IPC " I3/Sway IPC" ON REQUIRES I3)
Expand Down
5 changes: 5 additions & 0 deletions src/wayland/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ if (HYPRLAND)
add_subdirectory(hyprland)
endif()

if (INPUT_METHOD)
add_subdirectory(input_method)
list(APPEND WAYLAND_MODULES Quickshell.Wayland._InputMethod)
endif()

add_subdirectory(idle_inhibit)
list(APPEND WAYLAND_MODULES Quickshell.Wayland._IdleInhibitor)

Expand Down
40 changes: 40 additions & 0 deletions src/wayland/input_method/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
set(INPUT_METHOD_PRINT_KETS OFF)

qt_add_library(quickshell-wayland-input-method STATIC
input_method.cpp
keyboard_grab.cpp
virtual_keyboard.cpp
key_map_state.cpp
manager.cpp
qml.cpp
qml_helpers.cpp
c_helpers.cpp
types.cpp
)

target_compile_definitions(quickshell-wayland-input-method PRIVATE INPUT_METHOD_PRINT=0)

qt_add_qml_module(quickshell-wayland-input-method
URI Quickshell.Wayland._InputMethod
VERSION 0.1
DEPENDENCIES QtQml
)

qs_add_module_deps_light(quickshell-wayland-input-method
Quickshell Quickshell.Wayland
)

install_qml_module(quickshell-wayland-input-method)

wl_proto(zwp-input-method input-method-unstable-v2 "${CMAKE_CURRENT_SOURCE_DIR}")
wl_proto(zwp-virtual-keyboard virtual-keyboard-unstable-v1 "${CMAKE_CURRENT_SOURCE_DIR}")
wl_proto(zwp-text-input text-input-unstable-v3 "${WAYLAND_PROTOCOLS}/unstable/text-input")

target_link_libraries(quickshell-wayland-input-method PRIVATE
Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
zwp-input-method zwp-virtual-keyboard zwp-text-input
)

qs_module_pch(quickshell-wayland-input-method SET large)

target_link_libraries(quickshell PRIVATE quickshell-wayland-input-methodplugin)
70 changes: 70 additions & 0 deletions src/wayland/input_method/c_helpers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include "c_helpers.hpp"
#include <cstddef>
#include <cstdio>
#include <cstring>
#include <utility>

#include <qdebug.h>
#include <qlogging.h>
#include <sys/mman.h>
#include <unistd.h>

namespace qs::wayland::input_method::impl {

void FreeDeleter::operator()(const char* p) const {
std::free(const_cast<std::remove_const_t<char>*>(p)); // NOLINT
}

SharedMemory::SharedMemory(const char* shmName, int oFlag, size_t size)
: mShmName(shmName)
, mSize(size)
, fd(shm_open(this->mShmName, oFlag, 0)) {
if (this->fd == -1) {
perror("");
qDebug() << "Virtual keyboard failed to open shared memory";
return;
}
if (ftruncate(this->fd, static_cast<int>(size)) == -1) {
this->fd = -1;
perror("");
qDebug() << "Virtual keyboard failed to resize shared memory to" << size;
return;
}
this->map = static_cast<char*>(mmap(nullptr, this->mSize, PROT_WRITE, MAP_SHARED, this->fd, 0));
if (this->map == MAP_FAILED) {
perror("");
qDebug() << "Virtual keyboard failed to open shared memory";
return;
}
}
SharedMemory::~SharedMemory() {
if (this->fd != -1) {
close(this->fd);
shm_unlink(this->mShmName);
}
if (this->map != nullptr) {
munmap(this->map, this->mSize);
}
}
SharedMemory::SharedMemory(SharedMemory&& other) noexcept
: mShmName(std::exchange(other.mShmName, nullptr))
, mSize(std::exchange(other.mSize, 0))
, fd(std::exchange(other.fd, -1))
, map(std::exchange(other.map, nullptr)) {}
SharedMemory& SharedMemory::operator=(SharedMemory&& other) noexcept {
this->mShmName = std::exchange(other.mShmName, nullptr);
this->mSize = std::exchange(other.mSize, 0);
this->fd = std::exchange(other.fd, -1);
this->map = std::exchange(other.map, nullptr);
return *this;
}

SharedMemory::operator bool() const { return this->fd != -1 && this->map != MAP_FAILED; }
[[nodiscard]] int SharedMemory::get() const { return this->fd; }

void SharedMemory::write(const char* string) {
if (!this->map) return;
strcpy(this->map, string);
}

} // namespace qs::wayland::input_method::impl
38 changes: 38 additions & 0 deletions src/wayland/input_method/c_helpers.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#pragma once

#include <memory>

#include <sys/mman.h>

namespace qs::wayland::input_method::impl {

struct FreeDeleter {
void operator()(const char* p) const;
};
// Dont use this for literals, only c strings that were allocated
using uniqueCString = std::unique_ptr<const char, FreeDeleter>;

// this is a bit half baked but works for what I need it for
/// Handles the lifetime of a memory mapped shm
class SharedMemory {
public:
SharedMemory(const char* shmName, int oFlag, size_t size);
~SharedMemory();
SharedMemory(const SharedMemory&) = delete;
SharedMemory(SharedMemory&& other) noexcept;
SharedMemory& operator=(const SharedMemory&) = delete;
SharedMemory& operator=(SharedMemory&& other) noexcept;

[[nodiscard]] operator bool() const;
[[nodiscard]] int get() const;

void write(const char* string);

private:
const char* mShmName;
size_t mSize;
int fd;
char* map = nullptr;
};

} // namespace qs::wayland::input_method::impl
Loading