1 /*
2  * SPDX-FileCopyrightText: 2020~2020 CSSlayer <wengxt@gmail.com>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  */
7 #ifndef _FCITX5_FRONTEND_WAYLANDIM_WAYLANDIMSERVERV2_H_
8 #define _FCITX5_FRONTEND_WAYLANDIM_WAYLANDIMSERVERV2_H_
9 
10 #include <fcitx-utils/event.h>
11 #include <fcitx/focusgroup.h>
12 #include <fcitx/instance.h>
13 #include <xkbcommon/xkbcommon.h>
14 #include "display.h"
15 #include "zwp_input_method_keyboard_grab_v2.h"
16 #include "zwp_input_method_manager_v2.h"
17 #include "zwp_input_method_v2.h"
18 #include "zwp_virtual_keyboard_manager_v1.h"
19 #include "zwp_virtual_keyboard_v1.h"
20 
21 namespace fcitx {
22 class WaylandIMModule;
23 class WaylandIMInputContextV2;
24 
25 class WaylandIMServerV2 {
26     friend class WaylandIMInputContextV2;
27 
28 public:
29     WaylandIMServerV2(wl_display *display, FocusGroup *group,
30                       const std::string &name, WaylandIMModule *waylandim);
31 
32     ~WaylandIMServerV2();
33 
34     InputContextManager &inputContextManager();
35 
36     void init();
37     void refreshSeat();
38     void activate(wayland::ZwpInputMethodV2 *id);
39     void deactivate(wayland::ZwpInputMethodV2 *id);
40     void add(WaylandIMInputContextV2 *ic, wayland::WlSeat *seat);
41     void remove(wayland::WlSeat *seat);
42     Instance *instance();
group()43     FocusGroup *group() { return group_; }
xkbState()44     auto *xkbState() { return state_.get(); }
inputMethodManagerV2()45     auto *inputMethodManagerV2() { return inputMethodManagerV2_.get(); }
46 
47 private:
48     FocusGroup *group_;
49     std::string name_;
50     bool init_ = false;
51     WaylandIMModule *parent_;
52     std::shared_ptr<wayland::ZwpInputMethodManagerV2> inputMethodManagerV2_;
53     std::shared_ptr<wayland::ZwpVirtualKeyboardManagerV1>
54         virtualKeyboardManagerV1_;
55 
56     UniqueCPtr<struct xkb_context, xkb_context_unref> context_;
57     std::vector<char> keymapData_;
58     UniqueCPtr<struct xkb_keymap, xkb_keymap_unref> keymap_;
59     UniqueCPtr<struct xkb_state, xkb_state_unref> state_;
60 
61     wayland::Display *display_;
62     ScopedConnection globalConn_;
63 
64     struct StateMask {
65         uint32_t shift_mask = 0;
66         uint32_t lock_mask = 0;
67         uint32_t control_mask = 0;
68         uint32_t mod1_mask = 0;
69         uint32_t mod2_mask = 0;
70         uint32_t mod3_mask = 0;
71         uint32_t mod4_mask = 0;
72         uint32_t mod5_mask = 0;
73         uint32_t super_mask = 0;
74         uint32_t hyper_mask = 0;
75         uint32_t meta_mask = 0;
76     } stateMask_;
77 
78     KeyStates modifiers_;
79 
80     std::unordered_map<wayland::WlSeat *, WaylandIMInputContextV2 *> icMap_;
81 };
82 
83 class WaylandIMInputContextV2 : public InputContext {
84 public:
85     WaylandIMInputContextV2(InputContextManager &inputContextManager,
86                             WaylandIMServerV2 *server,
87                             std::shared_ptr<wayland::WlSeat> seat,
88                             wayland::ZwpVirtualKeyboardV1 *vk);
89     ~WaylandIMInputContextV2();
90 
frontend()91     const char *frontend() const override { return "wayland_v2"; }
92 
inputMethodV2()93     auto inputMethodV2() { return ic_.get(); }
94 
95 protected:
commitStringImpl(const std::string & text)96     void commitStringImpl(const std::string &text) override {
97         ic_->commitString(text.c_str());
98         ic_->commit(serial_);
99     }
deleteSurroundingTextImpl(int offset,unsigned int size)100     void deleteSurroundingTextImpl(int offset, unsigned int size) override {
101         ic_->deleteSurroundingText(-offset, offset + size);
102         ic_->commit(serial_);
103     }
104     void forwardKeyImpl(const ForwardKeyEvent &key) override;
105 
106     void updatePreeditImpl() override;
107 
108 private:
109     void repeat();
110     void surroundingTextCallback(const char *text, uint32_t cursor,
111                                  uint32_t anchor);
112     void resetCallback();
113     void contentTypeCallback(uint32_t hint, uint32_t purpose);
114     void commitStateCallback(uint32_t serial);
115 
116     void keymapCallback(uint32_t format, int32_t fd, uint32_t size);
117     void keyCallback(uint32_t serial, uint32_t time, uint32_t key,
118                      uint32_t state);
119     void modifiersCallback(uint32_t serial, uint32_t mods_depressed,
120                            uint32_t mods_latched, uint32_t mods_locked,
121                            uint32_t group);
122     void repeatInfoCallback(int32_t rate, int32_t delay);
123 
124     WaylandIMServerV2 *server_;
125     std::shared_ptr<wayland::WlSeat> seat_;
126     std::unique_ptr<wayland::ZwpInputMethodV2> ic_;
127     std::unique_ptr<wayland::ZwpInputMethodKeyboardGrabV2> keyboardGrab_;
128     std::unique_ptr<wayland::ZwpVirtualKeyboardV1> vk_;
129     std::unique_ptr<EventSourceTime> timeEvent_;
130 
131     bool pendingActivate_ = false;
132     bool pendingDeactivate_ = false;
133 
134     uint32_t serial_ = 0;
135     uint32_t time_ = 0;
136 
137     uint32_t repeatKey_ = 0;
138     uint32_t repeatTime_ = 0;
139     KeySym repeatSym_ = FcitxKey_None;
140 
141     int32_t repeatRate_ = 40, repeatDelay_ = 400;
142 };
143 
144 } // namespace fcitx
145 
146 #endif // _FCITX5_FRONTEND_WAYLANDIM_WAYLANDIMSERVERV2_H_
147