1 /*************************************************************************** 2 * Copyright (C) 2011~2012 by CSSlayer * 3 * * 4 * This program is free software; you can redistribute it and/or modify * 5 * it under the terms of the GNU General Public License as published by * 6 * the Free Software Foundation; either version 2 of the License, or * 7 * (at your option) any later version. * 8 * * 9 * This program is distributed in the hope that it will be useful, * 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 12 * GNU General Public License for more details. * 13 * * 14 * You should have received a copy of the GNU General Public License * 15 * along with this program; if not, write to the * 16 * Free Software Foundation, Inc., * 17 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * 18 ***************************************************************************/ 19 20 #ifndef __FCITX_INPUT_CONTEXT_H_ 21 #define __FCITX_INPUT_CONTEXT_H_ 22 23 #include "config.h" 24 25 #include <QApplication> 26 #include <QDBusConnection> 27 #include <QDir> 28 #include <QInputContext> 29 #include <QList> 30 #include <QWeakPointer> 31 32 #include "fcitx-config/hotkey.h" 33 #include "fcitx/ime.h" 34 #include "fcitxinputcontextproxy.h" 35 #include "fcitxwatcher.h" 36 #include <xkbcommon/xkbcommon-compose.h> 37 38 #include "fcitx/frontend.h" 39 #include <X11/Xlib.h> 40 41 struct FcitxQtICData { FcitxQtICDataFcitxQtICData42 FcitxQtICData(FcitxWatcher *watcher) 43 : capacity(0), proxy(new FcitxInputContextProxy(watcher, watcher)), 44 surroundingAnchor(-1), surroundingCursor(-1) {} ~FcitxQtICDataFcitxQtICData45 ~FcitxQtICData() { delete proxy; } 46 QFlags<FcitxCapacityFlags> capacity; 47 FcitxInputContextProxy *proxy; 48 QRect rect; 49 QString surroundingText; 50 int surroundingAnchor; 51 int surroundingCursor; 52 }; 53 54 class FcitxQtConnection; 55 56 class ProcessKeyWatcher : public QDBusPendingCallWatcher { 57 Q_OBJECT 58 public: 59 ProcessKeyWatcher(XEvent *e, KeySym s, const QDBusPendingCall &call, 60 QObject *parent = 0) QDBusPendingCallWatcher(call,parent)61 : QDBusPendingCallWatcher(call, parent) { 62 event = static_cast<XEvent *>(malloc(sizeof(XEvent))); 63 *event = *e; 64 sym = s; 65 } 66 ~ProcessKeyWatcher()67 virtual ~ProcessKeyWatcher() { free(event); } 68 69 public slots: processEvent()70 void processEvent() { 71 qApp->x11ProcessEvent(event); 72 deleteLater(); 73 } 74 75 public: 76 XEvent *event; 77 KeySym sym; 78 }; 79 80 #define FCITX_IDENTIFIER_NAME "fcitx" 81 82 struct XkbContextDeleter { cleanupXkbContextDeleter83 static inline void cleanup(struct xkb_context *pointer) { 84 if (pointer) 85 xkb_context_unref(pointer); 86 } 87 }; 88 89 struct XkbComposeTableDeleter { cleanupXkbComposeTableDeleter90 static inline void cleanup(struct xkb_compose_table *pointer) { 91 if (pointer) 92 xkb_compose_table_unref(pointer); 93 } 94 }; 95 96 struct XkbComposeStateDeleter { cleanupXkbComposeStateDeleter97 static inline void cleanup(struct xkb_compose_state *pointer) { 98 if (pointer) 99 xkb_compose_state_unref(pointer); 100 } 101 }; 102 103 class QFcitxInputContext : public QInputContext { 104 Q_OBJECT 105 public: 106 QFcitxInputContext(); 107 ~QFcitxInputContext(); 108 109 virtual QString identifierName(); 110 virtual QString language(); 111 virtual void reset(); 112 virtual bool isComposing() const; 113 virtual void update(); 114 virtual void setFocusWidget(QWidget *w); 115 116 virtual void widgetDestroyed(QWidget *w); 117 118 virtual bool x11FilterEvent(QWidget *keywidget, XEvent *event); 119 virtual void mouseHandler(int x, QMouseEvent *event); 120 121 private Q_SLOTS: 122 void createInputContextFinished(); 123 void cleanUp(); 124 void commitString(const QString &str); 125 void updateFormattedPreedit(const FcitxFormattedPreeditList &preeditList, 126 int cursorPos); 127 void forwardKey(uint keyval, uint state, bool isRelease); 128 void deleteSurroundingText(int offset, uint nchar); 129 void updateCursor(); 130 void x11ProcessKeyEventCallback(QDBusPendingCallWatcher *watcher); 131 132 private: 133 QWidget *validFocusWidget(); 134 bool processCompose(uint keyval, uint state, FcitxKeyEventType event); 135 bool x11FilterEventFallback(XEvent *event, KeySym sym); 136 XEvent *createXEvent(Display *dpy, WId wid, uint keyval, uint state, 137 bool isRelease); 138 bool isValid(); 139 FcitxInputContextProxy *validIC(); 140 FcitxInputContextProxy *validICByWidget(QWidget *w); 141 142 void addCapacity(FcitxQtICData *data, QFlags<FcitxCapacityFlags> capacity, 143 bool forceUpdate = false) { 144 QFlags<FcitxCapacityFlags> newcaps = data->capacity | capacity; 145 if (data->capacity != newcaps || forceUpdate) { 146 data->capacity = newcaps; 147 updateCapacity(data); 148 } 149 } 150 151 void removeCapacity(FcitxQtICData *data, 152 QFlags<FcitxCapacityFlags> capacity, 153 bool forceUpdate = false) { 154 QFlags<FcitxCapacityFlags> newcaps = data->capacity & (~capacity); 155 if (data->capacity != newcaps || forceUpdate) { 156 data->capacity = newcaps; 157 updateCapacity(data); 158 } 159 } 160 161 void updateCapacity(FcitxQtICData *data); 162 void commitPreedit(); 163 void createICData(QWidget *w); 164 165 QString m_preedit; 166 QString m_commitPreedit; 167 FcitxFormattedPreeditList m_preeditList; 168 int m_cursorPos; 169 bool m_useSurroundingText; 170 bool m_syncMode; 171 FcitxWatcher *m_watcher; 172 QHash<WId, FcitxQtICData *> m_icMap; 173 QScopedPointer<struct xkb_context, XkbContextDeleter> m_xkbContext; 174 QScopedPointer<struct xkb_compose_table, XkbComposeTableDeleter> 175 m_xkbComposeTable; 176 QScopedPointer<struct xkb_compose_state, XkbComposeStateDeleter> 177 m_xkbComposeState; 178 }; 179 180 #endif //__FCITX_INPUT_CONTEXT_H_ 181 182 // kate: indent-mode cstyle; space-indent on; indent-width 0; 183