1 /* 2 * SPDX-FileCopyrightText: 2016-2016 CSSlayer <wengxt@gmail.com> 3 * 4 * SPDX-License-Identifier: LGPL-2.1-or-later 5 * 6 */ 7 #ifndef _FCITX_INPUTCONTEXT_P_H_ 8 #define _FCITX_INPUTCONTEXT_P_H_ 9 10 #include <unordered_map> 11 #include <fcitx-utils/intrusivelist.h> 12 #include <fcitx-utils/uuid_p.h> 13 #include <fcitx/inputcontext.h> 14 #include <fcitx/inputcontextmanager.h> 15 #include <fcitx/inputcontextproperty.h> 16 #include <fcitx/inputpanel.h> 17 #include <fcitx/instance.h> 18 #include <fcitx/statusarea.h> 19 20 namespace fcitx { 21 22 class InputContextPrivate : public QPtrHolder<InputContext> { 23 public: InputContextPrivate(InputContext * q,InputContextManager & manager,const std::string & program)24 InputContextPrivate(InputContext *q, InputContextManager &manager, 25 const std::string &program) 26 : QPtrHolder(q), manager_(manager), group_(nullptr), inputPanel_(q), 27 statusArea_(q), program_(program), 28 isPreeditEnabled_(manager.isPreeditEnabledByDefault()) {} 29 30 template <typename E> postEvent(E && event)31 bool postEvent(E &&event) { 32 if (destroyed_) { 33 return true; 34 } 35 if (auto *instance = manager_.instance()) { 36 return instance->postEvent(event); 37 } 38 return false; 39 } 40 41 template <typename E, typename... Args> emplaceEvent(Args &&...args)42 bool emplaceEvent(Args &&...args) { 43 if (destroyed_) { 44 return true; 45 } 46 if (auto *instance = manager_.instance()) { 47 return instance->postEvent(E(std::forward<Args>(args)...)); 48 } 49 return false; 50 } 51 52 template <typename E, typename... Args> pushEvent(Args &&...args)53 void pushEvent(Args &&...args) { 54 if (destroyed_) { 55 return; 56 } 57 58 if (blockEventToClient_) { 59 blockedEvents_.push_back( 60 std::make_unique<E>(std::forward<Args>(args)...)); 61 } else { 62 E event(std::forward<Args>(args)...); 63 deliverEvent(event, nullptr); 64 } 65 } 66 registerProperty(int slot,InputContextProperty * property)67 void registerProperty(int slot, InputContextProperty *property) { 68 if (slot < 0) { 69 return; 70 } 71 if (static_cast<size_t>(slot) >= properties_.size()) { 72 properties_.resize(slot + 1); 73 } 74 properties_[slot].reset(property); 75 } 76 unregisterProperty(int slot)77 void unregisterProperty(int slot) { 78 properties_[slot] = std::move(properties_.back()); 79 properties_.pop_back(); 80 } 81 deliverEvent(InputContextEvent & icEvent,std::string * commitBuffer)82 void deliverEvent(InputContextEvent &icEvent, std::string *commitBuffer) { 83 FCITX_Q(); 84 if (destroyed_) { 85 return; 86 } 87 if (commitBuffer && !commitBuffer->empty() && 88 (icEvent.type() != EventType::InputContextCommitString)) { 89 q->commitStringImpl(*commitBuffer); 90 commitBuffer->clear(); 91 } 92 93 switch (icEvent.type()) { 94 case EventType::InputContextCommitString: { 95 auto &event = static_cast<CommitStringEvent &>(icEvent); 96 if (!postEvent(event)) { 97 if (commitBuffer) { 98 *commitBuffer += event.text(); 99 } else { 100 q->commitStringImpl(event.text()); 101 } 102 } 103 break; 104 } 105 case EventType::InputContextForwardKey: { 106 auto &event = static_cast<ForwardKeyEvent &>(icEvent); 107 if (!postEvent(event)) { 108 q->forwardKeyImpl(event); 109 } 110 break; 111 } 112 case EventType::InputContextUpdatePreedit: { 113 auto &event = static_cast<UpdatePreeditEvent &>(icEvent); 114 if (!postEvent(event)) { 115 q->updatePreeditImpl(); 116 } 117 break; 118 } 119 default: 120 break; 121 } 122 } 123 deliverBlockedEvents()124 void deliverBlockedEvents() { 125 FCITX_Q(); 126 std::string commitBuffer; 127 for (const auto &event : blockedEvents_) { 128 deliverEvent(*event, &commitBuffer); 129 } 130 if (!commitBuffer.empty()) { 131 q->commitStringImpl(commitBuffer); 132 } 133 blockedEvents_.clear(); 134 } 135 property(int slot)136 InputContextProperty *property(int slot) { return properties_[slot].get(); } 137 138 InputContextManager &manager_; 139 FocusGroup *group_; 140 InputPanel inputPanel_; 141 StatusArea statusArea_; 142 bool hasFocus_ = false; 143 std::string program_; 144 CapabilityFlags capabilityFlags_; 145 bool isPreeditEnabled_ = true; 146 SurroundingText surroundingText_; 147 Rect cursorRect_; 148 double scale_ = 1.0; 149 150 IntrusiveListNode listNode_; 151 IntrusiveListNode focusedListNode_; 152 ICUUID uuid_; 153 std::vector<std::unique_ptr<InputContextProperty>> properties_; 154 bool destroyed_ = false; 155 156 std::list<std::unique_ptr<InputContextEvent>> blockedEvents_; 157 bool blockEventToClient_ = false; 158 }; 159 } // namespace fcitx 160 161 #endif // _FCITX_INPUTCONTEXT_P_H_ 162