1 /* 2 * SPDX-FileCopyrightText: 2017-2017 CSSlayer <wengxt@gmail.com> 3 * 4 * SPDX-License-Identifier: LGPL-2.1-or-later 5 * 6 */ 7 #ifndef _FCITX_WAYLAND_CORE_DISPLAY_H_ 8 #define _FCITX_WAYLAND_CORE_DISPLAY_H_ 9 10 #include <algorithm> 11 #include <list> 12 #include <memory> 13 #include <set> 14 #include <string> 15 #include <tuple> 16 #include <unordered_map> 17 #include <wayland-client.h> 18 #include "fcitx-utils/signals.h" 19 #include "outputinformation.h" 20 #include "wl_registry.h" 21 22 namespace fcitx { 23 namespace wayland { 24 25 class WlOutput; 26 class WlCallback; 27 28 class GlobalsFactoryBase { 29 public: ~GlobalsFactoryBase()30 virtual ~GlobalsFactoryBase() {} 31 virtual std::shared_ptr<void> create(WlRegistry &, uint32_t name, 32 uint32_t version) = 0; erase(uint32_t name)33 void erase(uint32_t name) { globals_.erase(name); } 34 globals()35 const std::set<uint32_t> &globals() { return globals_; } 36 37 protected: 38 std::set<uint32_t> globals_; 39 }; 40 41 template <typename T> 42 class GlobalsFactory : public GlobalsFactoryBase { 43 public: create(WlRegistry & registry,uint32_t name,uint32_t version)44 virtual std::shared_ptr<void> create(WlRegistry ®istry, uint32_t name, 45 uint32_t version) { 46 std::shared_ptr<T> p; 47 p.reset(registry.bind<T>(name, std::min(version, T::version))); 48 globals_.insert(name); 49 return p; 50 } 51 }; 52 53 class Display { 54 public: 55 Display(wl_display *display); 56 ~Display(); 57 fd()58 int fd() const { return wl_display_get_fd(display_.get()); } 59 60 operator wl_display *() { return display_.get(); } 61 62 void roundtrip(); 63 void sync(); 64 void flush(); 65 void run(); 66 67 WlRegistry *registry(); 68 69 const OutputInfomation *outputInformation(WlOutput *output) const; 70 71 template <typename T> getGlobals()72 std::vector<std::shared_ptr<T>> getGlobals() { 73 auto iter = requestedGlobals_.find(T::interface); 74 if (iter == requestedGlobals_.end()) { 75 return {}; 76 } 77 auto &items = iter->second->globals(); 78 std::vector<std::shared_ptr<T>> results; 79 for (uint32_t item : items) { 80 auto iter = globals_.find(item); 81 results.push_back(std::static_pointer_cast<T>( 82 std::get<std::shared_ptr<void>>(iter->second))); 83 } 84 85 return results; 86 } 87 88 template <typename T> getGlobal()89 std::shared_ptr<T> getGlobal() { 90 auto globals = getGlobals<T>(); 91 if (!globals.empty()) { 92 return globals[0]; 93 } 94 return {}; 95 } 96 97 template <typename T> getGlobal(uint32_t name)98 std::shared_ptr<T> getGlobal(uint32_t name) { 99 auto iter = globals_.find(name); 100 if (iter != globals_.end() && 101 std::get<std::string>(iter->second) == T::interface) { 102 return std::static_pointer_cast<T>( 103 std::get<std::shared_ptr<void>>(iter->second)); 104 } 105 return {}; 106 } 107 108 template <typename T> requestGlobals()109 void requestGlobals() { 110 auto result = requestedGlobals_.emplace(std::make_pair( 111 T::interface, std::make_unique<GlobalsFactory<T>>())); 112 if (result.second) { 113 auto iter = result.first; 114 for (auto &p : globals_) { 115 if (std::get<std::string>(p.second) == T::interface) { 116 createGlobalHelper(iter->second.get(), p); 117 } 118 } 119 } 120 } 121 globalCreated()122 auto &globalCreated() { return globalCreatedSignal_; } globalRemoved()123 auto &globalRemoved() { return globalRemovedSignal_; } 124 125 private: 126 void createGlobalHelper( 127 GlobalsFactoryBase *factory, 128 std::pair<const uint32_t, std::tuple<std::string, uint32_t, uint32_t, 129 std::shared_ptr<void>>> 130 &globalsPair); 131 132 void addOutput(wayland::WlOutput *output); 133 void removeOutput(wayland::WlOutput *output); 134 135 fcitx::Signal<void(const std::string &, std::shared_ptr<void>)> 136 globalCreatedSignal_; 137 fcitx::Signal<void(const std::string &, std::shared_ptr<void>)> 138 globalRemovedSignal_; 139 std::unordered_map<std::string, std::unique_ptr<GlobalsFactoryBase>> 140 requestedGlobals_; 141 UniqueCPtr<wl_display, wl_display_disconnect> display_; 142 std::unique_ptr<WlRegistry> registry_; 143 std::unordered_map<uint32_t, std::tuple<std::string, uint32_t, uint32_t, 144 std::shared_ptr<void>>> 145 globals_; 146 std::list<fcitx::Connection> conns_; 147 std::list<std::unique_ptr<WlCallback>> callbacks_; 148 std::unordered_map<WlOutput *, OutputInfomation> outputInfo_; 149 }; 150 } // namespace wayland 151 } // namespace fcitx 152 153 #endif // _FCITX_WAYLAND_CORE_DISPLAY_H_ 154