Skip to content

Commit 667ec1b

Browse files
committed
add KeyboardTextEdit for some sane defaults
1 parent d5ecb41 commit 667ec1b

File tree

7 files changed

+197
-14
lines changed

7 files changed

+197
-14
lines changed

src/wayland/input_method/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ qt_add_library(quickshell-wayland-input-method STATIC
55
key_map_state.cpp
66
manager.cpp
77
qml.cpp
8+
qml_helpers.cpp
89
)
910

1011
qt_add_qml_module(quickshell-wayland-input-method

src/wayland/input_method/keyboard_grab.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,11 @@ void InputMethodKeyboardGrab::zwp_input_method_keyboard_grab_v2_key(
7575

7676
key += 8;
7777

78-
qInfo() << KeyMapState::keyStateName(static_cast<wl_keyboard_key_state>(state))
78+
#if 0
79+
qDebug() << KeyMapState::keyStateName(static_cast<wl_keyboard_key_state>(state))
7980
<< this->mKeyMapState.keyName(key) << "[" << key << "]"
8081
<< this->mKeyMapState.getChar(key);
82+
#endif
8183

8284
xkb_keysym_t sym = this->mKeyMapState.getOneSym(key);
8385

@@ -90,19 +92,19 @@ void InputMethodKeyboardGrab::zwp_input_method_keyboard_grab_v2_key(
9092
return;
9193
}
9294
if (sym == XKB_KEY_Up) {
93-
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) emit directionPress(UP);
95+
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) emit directionPress(DirectionKey::UP);
9496
return;
9597
}
9698
if (sym == XKB_KEY_Down) {
97-
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) emit directionPress(DOWN);
99+
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) emit directionPress(DirectionKey::DOWN);
98100
return;
99101
}
100102
if (sym == XKB_KEY_Left) {
101-
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) emit directionPress(LEFT);
103+
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) emit directionPress(DirectionKey::LEFT);
102104
return;
103105
}
104106
if (sym == XKB_KEY_Right) {
105-
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) emit directionPress(RIGHT);
107+
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) emit directionPress(DirectionKey::RIGHT);
106108
return;
107109
}
108110
if (sym == XKB_KEY_BackSpace) {

src/wayland/input_method/qml.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ void Keyboard::setKeyboard(QPointer<InputMethodKeyboardGrab> keyboard) {
158158
this->mKeyboard,
159159
&InputMethodKeyboardGrab::directionPress,
160160
this,
161-
&Keyboard::directionPress
161+
&Keyboard::onDirectionPress
162162
);
163163
QObject::connect(
164164
this->mKeyboard,
@@ -174,4 +174,20 @@ void Keyboard::setKeyboard(QPointer<InputMethodKeyboardGrab> keyboard) {
174174
);
175175
}
176176

177+
void Keyboard::onDirectionPress(impl::DirectionKey direction) {
178+
emit directionPress(KeyboardDirectionKey::fromDirection(direction));
179+
}
180+
181+
QString KeyboardDirectionKey::toString(Enum direction) {
182+
switch (direction) {
183+
case UP: return "UP";
184+
case DOWN: return "DOWN";
185+
case LEFT: return "LEFT";
186+
case RIGHT: return "RIGHT";
187+
}
188+
}
189+
KeyboardDirectionKey::Enum KeyboardDirectionKey::fromDirection(impl::DirectionKey direction) {
190+
return static_cast<KeyboardDirectionKey::Enum>(direction);
191+
}
192+
177193
} // namespace qs::wayland::input_method

src/wayland/input_method/qml.hpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,24 @@ class InputMethodHandle;
1414
class InputMethodKeyboardGrab;
1515
} // namespace impl
1616

17+
class KeyboardDirectionKey: public QObject {
18+
Q_OBJECT;
19+
QML_NAMED_ELEMENT(DirectionKey);
20+
QML_SINGLETON;
21+
22+
public:
23+
enum Enum : quint8 {
24+
UP = static_cast<quint8>(impl::DirectionKey::UP),
25+
DOWN = static_cast<quint8>(impl::DirectionKey::DOWN),
26+
LEFT = static_cast<quint8>(impl::DirectionKey::LEFT),
27+
RIGHT = static_cast<quint8>(impl::DirectionKey::RIGHT),
28+
};
29+
Q_ENUM(Enum);
30+
31+
Q_INVOKABLE static QString toString(Enum direction);
32+
static Enum fromDirection(impl::DirectionKey direction);
33+
};
34+
1735
class Keyboard: public QObject {
1836
Q_OBJECT;
1937
/// The surface that will be created for the keyboard. Must create a @@KeyboardSurface$.
@@ -30,10 +48,13 @@ class Keyboard: public QObject {
3048
void keyPress(QChar character);
3149
void returnPress();
3250
void escapePress();
33-
void directionPress(DirectionKey);
51+
void directionPress(KeyboardDirectionKey::Enum);
3452
void backspacePress();
3553
void deletePress();
3654

55+
private slots:
56+
void onDirectionPress(impl::DirectionKey direction);
57+
3758
private:
3859
QPointer<impl::InputMethodKeyboardGrab> mKeyboard = nullptr;
3960
// QQmlComponent* mSurfaceComponent = nullptr;
@@ -58,7 +79,7 @@ class InputMethod: public QObject {
5879
keyboardComponentChanged
5980
);
6081
Q_CLASSINFO("DefaultProperty", "keyboard");
61-
QML_NAMED_ELEMENT(InputPicker);
82+
QML_NAMED_ELEMENT(QSInputMethod);
6283

6384
public:
6485
explicit InputMethod(QObject* parent = nullptr);
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#include "qml_helpers.hpp"
2+
3+
namespace qs::wayland::input_method {
4+
5+
KeyboardTextEdit::KeyboardTextEdit(QObject* parent): Keyboard(parent) {
6+
QObject::connect(this, &Keyboard::keyPress, this, &KeyboardTextEdit::onKeyPress);
7+
QObject::connect(this, &Keyboard::returnPress, this, &KeyboardTextEdit::onReturnPress);
8+
QObject::connect(this, &Keyboard::directionPress, this, &KeyboardTextEdit::onDirectionPress);
9+
QObject::connect(this, &Keyboard::backspacePress, this, &KeyboardTextEdit::onBackspacePress);
10+
QObject::connect(this, &Keyboard::deletePress, this, &KeyboardTextEdit::onDeletePress);
11+
}
12+
13+
QJSValue KeyboardTextEdit::transform() const { return this->mTransform; }
14+
15+
void KeyboardTextEdit::setTransform(const QJSValue& callback) {
16+
if (!callback.isCallable()) {
17+
qmlInfo(this) << "Transform must be a callable function";
18+
return;
19+
}
20+
this->mTransform = callback;
21+
}
22+
23+
int KeyboardTextEdit::cursor() const { return this->mCursor; }
24+
void KeyboardTextEdit::setCursor(int value) {
25+
if (value < 0) value = 0;
26+
if (value >= this->mEditText.size()) value = static_cast<int>(this->mEditText.size());
27+
if (this->mCursor == value) return;
28+
this->mCursor = value;
29+
this->updatePreedit();
30+
emit cursorChanged();
31+
}
32+
33+
QString KeyboardTextEdit::editText() const { return this->mEditText; }
34+
void KeyboardTextEdit::setEditText(const QString& value) {
35+
if (this->mEditText == value) return;
36+
this->mEditText = value;
37+
this->updatePreedit();
38+
emit editTextChanged();
39+
}
40+
41+
void KeyboardTextEdit::updatePreedit() {
42+
auto* inputMethod = dynamic_cast<InputMethod*>(parent());
43+
if (!inputMethod) {
44+
return;
45+
}
46+
inputMethod->sendPreeditString(this->mEditText, this->mCursor, this->mCursor);
47+
}
48+
49+
void KeyboardTextEdit::onKeyPress(QChar character) {
50+
this->mEditText.insert(this->mCursor, character);
51+
this->updatePreedit();
52+
emit editTextChanged();
53+
this->setCursor(this->mCursor + 1);
54+
}
55+
void KeyboardTextEdit::onBackspacePress() {
56+
if (this->mCursor == 0) return;
57+
this->mEditText.remove(this->mCursor - 1, 1);
58+
this->updatePreedit();
59+
emit editTextChanged();
60+
this->setCursor(this->mCursor - 1);
61+
}
62+
void KeyboardTextEdit::onDeletePress() {
63+
if (this->mCursor == this->mEditText.size()) return;
64+
this->mEditText.remove(this->mCursor, 1);
65+
this->updatePreedit();
66+
emit editTextChanged();
67+
}
68+
69+
void KeyboardTextEdit::onDirectionPress(KeyboardDirectionKey::Enum direction) {
70+
switch (direction) {
71+
case KeyboardDirectionKey::LEFT: {
72+
this->setCursor(this->mCursor - 1);
73+
return;
74+
}
75+
case KeyboardDirectionKey::RIGHT: {
76+
this->setCursor(this->mCursor + 1);
77+
return;
78+
}
79+
default: return;
80+
}
81+
}
82+
83+
void KeyboardTextEdit::onReturnPress() {
84+
auto* inputMethod = dynamic_cast<InputMethod*>(parent());
85+
if (!inputMethod) return;
86+
QString text = "";
87+
if (this->mTransform.isCallable())
88+
text = this->mTransform.call(QJSValueList({this->mEditText})).toString();
89+
inputMethod->sendString(text);
90+
this->setEditText("");
91+
inputMethod->releaseKeyboard();
92+
}
93+
94+
} // namespace qs::wayland::input_method
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#pragma once
2+
3+
#include <qqmlintegration.h>
4+
#include <qstring.h>
5+
#include <qtmetamacros.h>
6+
7+
#include "qml.hpp"
8+
9+
namespace qs::wayland::input_method {
10+
11+
class KeyboardTextEdit: public Keyboard {
12+
Q_OBJECT;
13+
Q_PROPERTY(QJSValue transform READ transform WRITE setTransform NOTIFY transformChanged FINAL)
14+
Q_PROPERTY(int cursor MEMBER mCursor READ cursor WRITE setCursor NOTIFY cursorChanged);
15+
Q_PROPERTY(
16+
QString editText MEMBER mEditText READ editText WRITE setEditText NOTIFY editTextChanged
17+
);
18+
QML_ELEMENT;
19+
20+
public:
21+
KeyboardTextEdit(QObject* parent = nullptr);
22+
23+
Q_INVOKABLE [[nodiscard]] QJSValue transform() const;
24+
Q_INVOKABLE void setTransform(const QJSValue& callback);
25+
26+
Q_INVOKABLE [[nodiscard]] int cursor() const;
27+
Q_INVOKABLE void setCursor(int value);
28+
29+
Q_INVOKABLE [[nodiscard]] QString editText() const;
30+
Q_INVOKABLE void setEditText(const QString& value);
31+
32+
signals:
33+
void transformChanged();
34+
void cursorChanged();
35+
void editTextChanged();
36+
37+
private slots:
38+
void onKeyPress(QChar character);
39+
void onReturnPress();
40+
void onDirectionPress(KeyboardDirectionKey::Enum direction);
41+
void onBackspacePress();
42+
void onDeletePress();
43+
44+
private:
45+
void updatePreedit();
46+
47+
QJSValue mTransform;
48+
int mCursor = 0;
49+
QString mEditText = "";
50+
};
51+
52+
} // namespace qs::wayland::input_method

src/wayland/input_method/types.hpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,14 @@
33
#include <qobject.h>
44
#include <qtclasshelpermacros.h>
55

6-
namespace qs::wayland::input_method {
7-
enum DirectionKey { UP, DOWN, LEFT, RIGHT };
6+
namespace qs::wayland::input_method::impl {
7+
enum class DirectionKey : uint8_t { UP, DOWN, LEFT, RIGHT };
88

9-
namespace impl {
109
struct FreeDeleter {
1110
void operator()(const char* p) const {
1211
std::free(const_cast<std::remove_const_t<char>*>(p)); // NOLINT
1312
}
1413
};
1514
// Dont use this for literals, only c strings that were allocated
1615
using uniqueCString = std::unique_ptr<const char, FreeDeleter>;
17-
} // namespace impl
18-
19-
} // namespace qs::wayland::input_method
16+
} // namespace qs::wayland::input_method::impl

0 commit comments

Comments
 (0)