1 /* 2 * Copyright (C) 2017-2018 Team Kodi 3 * This file is part of Kodi - https://kodi.tv 4 * 5 * SPDX-License-Identifier: GPL-2.0-or-later 6 * See LICENSES/README.md for more information. 7 */ 8 9 #pragma once 10 11 #include "Connection.h" 12 #include "Output.h" 13 #include "Seat.h" 14 #include "SeatInputProcessing.h" 15 #include "ShellSurface.h" 16 #include "Signals.h" 17 #include "WindowDecorationHandler.h" 18 #include "threads/CriticalSection.h" 19 #include "threads/Event.h" 20 #include "utils/ActorProtocol.h" 21 #include "windowing/WinSystem.h" 22 23 #include <atomic> 24 #include <ctime> 25 #include <list> 26 #include <map> 27 #include <set> 28 #include <time.h> 29 30 #include <wayland-client.hpp> 31 #include <wayland-cursor.hpp> 32 #include <wayland-extra-protocols.hpp> 33 34 class IDispResource; 35 36 namespace KODI 37 { 38 namespace WINDOWING 39 { 40 namespace WAYLAND 41 { 42 43 class CRegistry; 44 class CWindowDecorator; 45 46 class CWinSystemWayland : public CWinSystemBase, IInputHandler, IWindowDecorationHandler, IShellSurfaceHandler 47 { 48 public: 49 CWinSystemWayland(); 50 ~CWinSystemWayland() noexcept override; 51 GetName()52 const std::string GetName() override { return "wayland"; } 53 54 bool InitWindowSystem() override; 55 bool DestroyWindowSystem() override; 56 57 bool CreateNewWindow(const std::string& name, 58 bool fullScreen, 59 RESOLUTION_INFO& res) override; 60 61 bool DestroyWindow() override; 62 63 bool ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop) override; 64 bool SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) override; 65 void FinishModeChange(RESOLUTION res) override; 66 void FinishWindowResize(int newWidth, int newHeight) override; 67 68 bool UseLimitedColor() override; 69 70 void UpdateResolutions() override; 71 72 bool CanDoWindowed() override; 73 bool Minimize() override; 74 75 bool HasCursor() override; 76 void ShowOSMouse(bool show) override; 77 78 std::string GetClipboardText() override; 79 80 float GetSyncOutputRefreshRate(); 81 float GetDisplayLatency() override; 82 float GetFrameLatencyAdjustment() override; 83 std::unique_ptr<CVideoSync> GetVideoSync(void* clock) override; 84 85 void Register(IDispResource* resource) override; 86 void Unregister(IDispResource* resource) override; 87 88 using PresentationFeedbackHandler = std::function<void(timespec /* tv */, std::uint32_t /* refresh */, std::uint32_t /* sync output id */, float /* sync output fps */, std::uint64_t /* msc */)>; 89 CSignalRegistration RegisterOnPresentationFeedback(const PresentationFeedbackHandler& handler); 90 91 // Like CWinSystemX11 92 void GetConnectedOutputs(std::vector<std::string>* outputs); 93 94 // winevents override 95 bool MessagePump() override; 96 97 protected: 98 std::unique_ptr<KODI::WINDOWING::IOSScreenSaver> GetOSScreenSaverImpl() override; GetBufferSize()99 CSizeInt GetBufferSize() const 100 { 101 return m_bufferSize; 102 } GetConnection()103 std::unique_ptr<CConnection> const& GetConnection() 104 { 105 return m_connection; 106 } GetMainSurface()107 wayland::surface_t GetMainSurface() 108 { 109 return m_surface; 110 } 111 112 void PrepareFramePresentation(); 113 void FinishFramePresentation(); 114 virtual void SetContextSize(CSizeInt size) = 0; 115 116 private: 117 // IInputHandler 118 void OnEnter(InputType type) override; 119 void OnLeave(InputType type) override; 120 void OnEvent(InputType type, XBMC_Event& event) override; 121 void OnSetCursor(std::uint32_t seatGlobalName, std::uint32_t serial) override; 122 123 // IWindowDecorationHandler 124 void OnWindowMove(const wayland::seat_t& seat, std::uint32_t serial) override; 125 void OnWindowResize(const wayland::seat_t& seat, std::uint32_t serial, wayland::shell_surface_resize edge) override; 126 void OnWindowShowContextMenu(const wayland::seat_t& seat, std::uint32_t serial, CPointInt position) override; 127 void OnWindowClose() override; 128 void OnWindowMaximize() override; 129 void OnWindowMinimize() override; 130 131 // IShellSurfaceHandler 132 void OnConfigure(std::uint32_t serial, CSizeInt size, IShellSurface::StateBitset state) override; 133 void OnClose() override; 134 135 // Registry handlers 136 void OnSeatAdded(std::uint32_t name, wayland::proxy_t&& seat); 137 void OnSeatRemoved(std::uint32_t name); 138 void OnOutputAdded(std::uint32_t name, wayland::proxy_t&& output); 139 void OnOutputRemoved(std::uint32_t name); 140 141 void LoadDefaultCursor(); 142 void SendFocusChange(bool focus); 143 bool SetResolutionExternal(bool fullScreen, RESOLUTION_INFO const& res); 144 void SetResolutionInternal(CSizeInt size, int scale, IShellSurface::StateBitset state, bool sizeIncludesDecoration, bool mustAck = false, std::uint32_t configureSerial = 0u); 145 struct Sizes 146 { 147 CSizeInt surfaceSize; 148 CSizeInt bufferSize; 149 CSizeInt configuredSize; 150 }; 151 Sizes CalculateSizes(CSizeInt size, int scale, IShellSurface::StateBitset state, bool sizeIncludesDecoration); 152 struct SizeUpdateInformation 153 { 154 bool surfaceSizeChanged : 1; 155 bool bufferSizeChanged : 1; 156 bool configuredSizeChanged : 1; 157 bool bufferScaleChanged : 1; 158 }; 159 SizeUpdateInformation UpdateSizeVariables(CSizeInt size, int scale, IShellSurface::StateBitset state, bool sizeIncludesDecoration); 160 void ApplySizeUpdate(SizeUpdateInformation update); 161 void ApplyNextState(); 162 163 std::string UserFriendlyOutputName(std::shared_ptr<COutput> const& output); 164 std::shared_ptr<COutput> FindOutputByUserFriendlyName(std::string const& name); 165 std::shared_ptr<COutput> FindOutputByWaylandOutput(wayland::output_t const& output); 166 167 // Called when wl_output::done is received for an output, i.e. associated 168 // information like modes is available 169 void OnOutputDone(std::uint32_t name); 170 void UpdateBufferScale(); 171 void ApplyBufferScale(); 172 void ApplyOpaqueRegion(); 173 void ApplyWindowGeometry(); 174 void UpdateTouchDpi(); 175 void ApplyShellSurfaceState(IShellSurface::StateBitset state); 176 177 void ProcessMessages(); 178 void AckConfigure(std::uint32_t serial); 179 180 timespec GetPresentationClockTime(); 181 182 // Globals 183 // ------- 184 std::unique_ptr<CConnection> m_connection; 185 std::unique_ptr<CRegistry> m_registry; 186 /** 187 * Registry used exclusively for wayland::seat_t 188 * 189 * Use extra registry because seats can only be registered after the surface 190 * has been created 191 */ 192 std::unique_ptr<CRegistry> m_seatRegistry; 193 wayland::compositor_t m_compositor; 194 wayland::shm_t m_shm; 195 wayland::presentation_t m_presentation; 196 197 std::unique_ptr<IShellSurface> m_shellSurface; 198 199 // Frame callback handling 200 // ----------------------- 201 wayland::callback_t m_frameCallback; 202 CEvent m_frameCallbackEvent; 203 204 // Seat handling 205 // ------------- 206 std::map<std::uint32_t, CSeat> m_seats; 207 CCriticalSection m_seatsMutex; 208 std::unique_ptr<CSeatInputProcessing> m_seatInputProcessing; 209 std::map<std::uint32_t, std::shared_ptr<COutput>> m_outputs; 210 /// outputs that did not receive their done event yet 211 std::map<std::uint32_t, std::shared_ptr<COutput>> m_outputsInPreparation; 212 CCriticalSection m_outputsMutex; 213 214 // Windowed mode 215 // ------------- 216 std::unique_ptr<CWindowDecorator> m_windowDecorator; 217 218 // Cursor 219 // ------ 220 bool m_osCursorVisible{true}; 221 wayland::cursor_theme_t m_cursorTheme; 222 wayland::buffer_t m_cursorBuffer; 223 wayland::cursor_image_t m_cursorImage; 224 wayland::surface_t m_cursorSurface; 225 226 // Presentation feedback 227 // --------------------- 228 clockid_t m_presentationClock; 229 struct SurfaceSubmission 230 { 231 timespec submissionTime; 232 float latency; 233 wayland::presentation_feedback_t feedback; 234 SurfaceSubmission(timespec const& submissionTime, wayland::presentation_feedback_t const& feedback); 235 }; 236 std::list<SurfaceSubmission> m_surfaceSubmissions; 237 CCriticalSection m_surfaceSubmissionsMutex; 238 /// Protocol object ID of the sync output returned by wp_presentation 239 std::uint32_t m_syncOutputID; 240 /// Refresh rate of sync output returned by wp_presentation 241 std::atomic<float> m_syncOutputRefreshRate{0.0f}; 242 static constexpr int LATENCY_MOVING_AVERAGE_SIZE{30}; 243 std::atomic<float> m_latencyMovingAverage; 244 CSignalHandlerList<PresentationFeedbackHandler> m_presentationFeedbackHandlers; 245 std::int64_t m_frameStartTime{}; 246 247 // IDispResource 248 // ------------- 249 std::set<IDispResource*> m_dispResources; 250 CCriticalSection m_dispResourcesMutex; 251 252 // Surface state 253 // ------------- 254 wayland::surface_t m_surface; 255 wayland::output_t m_lastSetOutput; 256 /// Set of outputs that show some part of our main surface as indicated by 257 /// compositor 258 std::set<std::shared_ptr<COutput>> m_surfaceOutputs; 259 CCriticalSection m_surfaceOutputsMutex; 260 /// Size of our surface in "surface coordinates" (i.e. without scaling applied) 261 /// and without window decorations 262 CSizeInt m_surfaceSize; 263 /// Size of the buffer that should back the surface (i.e. with scaling applied) 264 CSizeInt m_bufferSize; 265 /// Size of the whole window including window decorations as given by configure 266 CSizeInt m_configuredSize; 267 /// Scale in use for main surface buffer 268 int m_scale{1}; 269 /// Shell surface state last acked 270 IShellSurface::StateBitset m_shellSurfaceState; 271 /// Whether the shell surface is waiting for initial configure 272 bool m_shellSurfaceInitializing{false}; 273 struct 274 { 275 bool mustBeAcked{false}; 276 std::uint32_t configureSerial{}; 277 CSizeInt configuredSize; 278 int scale{1}; 279 IShellSurface::StateBitset shellSurfaceState; 280 } m_next; 281 bool m_waitingForApply{false}; 282 283 // Internal communication 284 // ---------------------- 285 /// Protocol for communicating events to the main thread 286 Actor::Protocol m_protocol; 287 288 // Configure state 289 // --------------- 290 bool m_firstSerialAcked{false}; 291 std::uint32_t m_lastAckedSerial{0u}; 292 /// Whether this is the first call to SetFullScreen 293 bool m_isInitialSetFullScreen{true}; 294 }; 295 296 297 } 298 } 299 } 300