File: qfcitxplatforminputcontext.h

package info (click to toggle)
fcitx-qt5 1.2.7-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 940 kB
  • sloc: cpp: 6,202; xml: 340; makefile: 12; sh: 4
file content (247 lines) | stat: -rw-r--r-- 8,640 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
/*
 * Copyright (C) 2011~2017 by CSSlayer
 * wengxt@gmail.com
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above Copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above Copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the authors nor the names of its contributors
 *    may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 */

#ifndef QFCITXPLATFORMINPUTCONTEXT_H
#define QFCITXPLATFORMINPUTCONTEXT_H

#include "fcitxinputcontextproxy.h"
#include "fcitxqtdbustypes.h"
#include "fcitxwatcher.h"
#include <QDBusConnection>
#include <QDBusServiceWatcher>
#include <QGuiApplication>
#include <QKeyEvent>
#include <QPointer>
#include <QRect>
#include <QWindow>
#include <memory>
#include <qpa/qplatforminputcontext.h>
#include <unordered_map>
#include <xkbcommon/xkbcommon-compose.h>

class QFileSystemWatcher;
enum FcitxKeyEventType { FCITX_PRESS_KEY, FCITX_RELEASE_KEY };

enum FcitxCapabilityFlags {
    CAPACITY_NONE = 0,
    CAPACITY_CLIENT_SIDE_UI = (1 << 0),
    CAPACITY_PREEDIT = (1 << 1),
    CAPACITY_CLIENT_SIDE_CONTROL_STATE = (1 << 2),
    CAPACITY_PASSWORD = (1 << 3),
    CAPACITY_FORMATTED_PREEDIT = (1 << 4),
    CAPACITY_CLIENT_UNFOCUS_COMMIT = (1 << 5),
    CAPACITY_SURROUNDING_TEXT = (1 << 6),
    CAPACITY_EMAIL = (1 << 7),
    CAPACITY_DIGIT = (1 << 8),
    CAPACITY_UPPERCASE = (1 << 9),
    CAPACITY_LOWERCASE = (1 << 10),
    CAPACITY_NOAUTOUPPERCASE = (1 << 11),
    CAPACITY_URL = (1 << 12),
    CAPACITY_DIALABLE = (1 << 13),
    CAPACITY_NUMBER = (1 << 14),
    CAPACITY_NO_ON_SCREEN_KEYBOARD = (1 << 15),
    CAPACITY_SPELLCHECK = (1 << 16),
    CAPACITY_NO_SPELLCHECK = (1 << 17),
    CAPACITY_WORD_COMPLETION = (1 << 18),
    CAPACITY_UPPERCASE_WORDS = (1 << 19),
    CAPACITY_UPPERCASE_SENTENCES = (1 << 20),
    CAPACITY_ALPHA = (1 << 21),
    CAPACITY_NAME = (1 << 22),
    CAPACITY_GET_IM_INFO_ON_FOCUS = (1 << 23),
    CAPACITY_RELATIVE_CURSOR_RECT = (1 << 24),
};

enum FcitxKeyState {
    FcitxKeyState_None = 0,
    FcitxKeyState_Shift = 1 << 0,
    FcitxKeyState_CapsLock = 1 << 1,
    FcitxKeyState_Ctrl = 1 << 2,
    FcitxKeyState_Alt = 1 << 3,
    FcitxKeyState_Alt_Shift = FcitxKeyState_Alt | FcitxKeyState_Shift,
    FcitxKeyState_Ctrl_Shift = FcitxKeyState_Ctrl | FcitxKeyState_Shift,
    FcitxKeyState_Ctrl_Alt = FcitxKeyState_Ctrl | FcitxKeyState_Alt,
    FcitxKeyState_Ctrl_Alt_Shift =
        FcitxKeyState_Ctrl | FcitxKeyState_Alt | FcitxKeyState_Shift,
    FcitxKeyState_NumLock = 1 << 4,
    FcitxKeyState_Super = 1 << 6,
    FcitxKeyState_ScrollLock = 1 << 7,
    FcitxKeyState_MousePressed = 1 << 8,
    FcitxKeyState_HandledMask = 1 << 24,
    FcitxKeyState_IgnoredMask = 1 << 25,
    FcitxKeyState_Super2 = 1 << 26,
    FcitxKeyState_Hyper = 1 << 27,
    FcitxKeyState_Meta = 1 << 28,
    FcitxKeyState_UsedMask = 0x5c001fff
};

struct FcitxQtICData {
    FcitxQtICData(FcitxWatcher *watcher)
        : proxy(new FcitxInputContextProxy(watcher, watcher)),
          surroundingAnchor(-1), surroundingCursor(-1) {}
    FcitxQtICData(const FcitxQtICData &that) = delete;
    ~FcitxQtICData() {
        if (proxy) {
            delete proxy;
        }
    }
    QFlags<FcitxCapabilityFlags> capability;
    FcitxInputContextProxy *proxy;
    QRect rect;
    // Last key event forwarded.
    std::unique_ptr<QKeyEvent> event;
    QString surroundingText;
    int surroundingAnchor;
    int surroundingCursor;
};

class ProcessKeyWatcher : public QDBusPendingCallWatcher {
    Q_OBJECT
public:
    ProcessKeyWatcher(const QKeyEvent &event, QWindow *window,
                      const QDBusPendingCall &call, QObject *parent = 0)
        : QDBusPendingCallWatcher(call, parent),
          m_event(event.type(), event.key(), event.modifiers(),
                  event.nativeScanCode(), event.nativeVirtualKey(),
                  event.nativeModifiers(), event.text(), event.isAutoRepeat(),
                  event.count()),
          m_window(window) {}

    virtual ~ProcessKeyWatcher() {}

    const QKeyEvent &keyEvent() { return m_event; }

    QWindow *window() { return m_window.data(); }

private:
    QKeyEvent m_event;
    QPointer<QWindow> m_window;
};

struct XkbContextDeleter {
    static inline void cleanup(struct xkb_context *pointer) {
        if (pointer)
            xkb_context_unref(pointer);
    }
};

struct XkbComposeTableDeleter {
    static inline void cleanup(struct xkb_compose_table *pointer) {
        if (pointer)
            xkb_compose_table_unref(pointer);
    }
};

struct XkbComposeStateDeleter {
    static inline void cleanup(struct xkb_compose_state *pointer) {
        if (pointer)
            xkb_compose_state_unref(pointer);
    }
};

class FcitxQtInputMethodProxy;

class QFcitxPlatformInputContext : public QPlatformInputContext {
    Q_OBJECT
public:
    QFcitxPlatformInputContext();
    virtual ~QFcitxPlatformInputContext();

    virtual bool filterEvent(const QEvent *event) Q_DECL_OVERRIDE;
    virtual bool isValid() const Q_DECL_OVERRIDE;
    virtual void invokeAction(QInputMethod::Action,
                              int cursorPosition) Q_DECL_OVERRIDE;
    virtual void reset() Q_DECL_OVERRIDE;
    virtual void commit() Q_DECL_OVERRIDE;
    virtual void update(Qt::InputMethodQueries quries) Q_DECL_OVERRIDE;
    virtual void setFocusObject(QObject *object) Q_DECL_OVERRIDE;
    virtual QLocale locale() const Q_DECL_OVERRIDE;

public Q_SLOTS:
    void cursorRectChanged();
    void commitString(const QString &str);
    void updateFormattedPreedit(const FcitxFormattedPreeditList &preeditList,
                                int cursorPos);
    void deleteSurroundingText(int offset, uint nchar);
    void forwardKey(uint keyval, uint state, bool type);
    void createInputContextFinished();
    void cleanUp();
    void windowDestroyed(QObject *object);
    void updateCurrentIM(const QString &name, const QString &uniqueName,
                         const QString &langCode);

private:
    bool processCompose(uint keyval, uint state, bool isRelaese);
    QKeyEvent *createKeyEvent(uint keyval, uint state, bool isRelaese,
                              const QKeyEvent *event);
    void forwardEvent(QWindow *window, const QKeyEvent &event);

    void addCapability(FcitxQtICData &data,
                       QFlags<FcitxCapabilityFlags> capability,
                       bool forceUpdate = false) {
        QFlags<FcitxCapabilityFlags> newcaps = data.capability | capability;
        if (data.capability != newcaps || forceUpdate) {
            data.capability = newcaps;
            updateCapability(data);
        }
    }

    void removeCapability(FcitxQtICData &data,
                          QFlags<FcitxCapabilityFlags> capability,
                          bool forceUpdate = false) {
        QFlags<FcitxCapabilityFlags> newcaps = data.capability & (~capability);
        if (data.capability != newcaps || forceUpdate) {
            data.capability = newcaps;
            updateCapability(data);
        }
    }

    void updateCapability(const FcitxQtICData &data);
    void commitPreedit(QPointer<QObject> input = qApp->focusObject());
    void createICData(QWindow *w);
    FcitxInputContextProxy *validIC();
    FcitxInputContextProxy *validICByWindow(QWindow *window);
    bool filterEventFallback(uint keyval, uint keycode, uint state,
                             bool isRelaese);

    FcitxWatcher *m_watcher;
    QString m_preedit;
    QString m_commitPreedit;
    FcitxFormattedPreeditList m_preeditList;
    int m_cursorPos;
    bool m_useSurroundingText;
    bool m_syncMode;
    QString m_lastSurroundingText;
    int m_lastSurroundingAnchor = 0;
    int m_lastSurroundingCursor = 0;
    std::unordered_map<QWindow *, FcitxQtICData> m_icMap;
    QPointer<QWindow> m_lastWindow;
    QPointer<QObject> m_lastObject;
    bool m_destroy;
    QScopedPointer<struct xkb_context, XkbContextDeleter> m_xkbContext;
    QScopedPointer<struct xkb_compose_table, XkbComposeTableDeleter>
        m_xkbComposeTable;
    QScopedPointer<struct xkb_compose_state, XkbComposeStateDeleter>
        m_xkbComposeState;
    QLocale m_locale;
private Q_SLOTS:
    void processKeyEventFinished(QDBusPendingCallWatcher *);
};

#endif // QFCITXPLATFORMINPUTCONTEXT_H