1 /* 2 * Copyright (C) 2005-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 "DirtyRegionTracker.h" 12 #include "GUIWindow.h" 13 #include "IMsgTargetCallback.h" 14 #include "IWindowManagerCallback.h" 15 #include "guilib/WindowIDs.h" 16 #include "messaging/IMessageTarget.h" 17 18 #include <list> 19 #include <unordered_map> 20 #include <utility> 21 #include <vector> 22 23 class CGUIDialog; 24 class CGUIMediaWindow; 25 26 #ifdef TARGET_WINDOWS_STORE 27 #pragma pack(push, 8) 28 #endif 29 enum class DialogModalityType; 30 #ifdef TARGET_WINDOWS_STORE 31 #pragma pack(pop) 32 #endif 33 34 namespace KODI 35 { 36 namespace MESSAGING 37 { 38 class CApplicationMessenger; 39 } 40 } 41 42 #define WINDOW_ID_MASK 0xffff 43 44 /*! 45 \ingroup winman 46 \brief 47 */ 48 class CGUIWindowManager : public KODI::MESSAGING::IMessageTarget 49 { 50 friend CGUIDialog; 51 friend CGUIMediaWindow; 52 public: 53 CGUIWindowManager(); 54 ~CGUIWindowManager() override; 55 bool SendMessage(CGUIMessage& message); 56 bool SendMessage(int message, int senderID, int destID, int param1 = 0, int param2 = 0); 57 bool SendMessage(CGUIMessage& message, int window); 58 void Initialize(); 59 void Add(CGUIWindow* pWindow); 60 void AddUniqueInstance(CGUIWindow *window); 61 void AddCustomWindow(CGUIWindow* pWindow); 62 void Remove(int id); 63 void Delete(int id); 64 void ActivateWindow(int iWindowID, const std::string &strPath = ""); 65 void ForceActivateWindow(int iWindowID, const std::string &strPath = ""); 66 void ChangeActiveWindow(int iNewID, const std::string &strPath = ""); 67 void ActivateWindow(int iWindowID, const std::vector<std::string>& params, bool swappingWindows = false, bool force = false); 68 void PreviousWindow(); 69 70 void CloseDialogs(bool forceClose = false) const; 71 void CloseInternalModalDialogs(bool forceClose = false) const; 72 73 void OnApplicationMessage(KODI::MESSAGING::ThreadMessage* pMsg) override; 74 int GetMessageMask() override; 75 76 // OnAction() runs through our active dialogs and windows and sends the message 77 // off to the callbacks (application, python, playlist player) and to the 78 // currently focused window(s). Returns true only if the message is handled. 79 bool OnAction(const CAction &action) const; 80 81 /*! \brief Process active controls allowing them to animate before rendering. 82 */ 83 void Process(unsigned int currentTime); 84 85 /*! \brief Mark the screen as dirty, forcing a redraw at the next Render() 86 */ 87 void MarkDirty(); 88 89 /*! \brief Mark a region as dirty, forcing a redraw at the next Render() 90 */ 91 void MarkDirty(const CRect& rect); 92 93 /*! \brief Rendering of the current window and any dialogs 94 Render is called every frame to draw the current window and any dialogs. 95 It should only be called from the application thread. 96 Returns true only if it has rendered something. 97 */ 98 bool Render(); 99 100 void RenderEx() const; 101 102 /*! \brief Do any post render activities. 103 */ 104 void AfterRender(); 105 106 /*! \brief Per-frame updating of the current window and any dialogs 107 FrameMove is called every frame to update the current window and any dialogs 108 on screen. It should only be called from the application thread. 109 */ 110 void FrameMove(); 111 112 /*! \brief Return whether the window manager is initialized. 113 The window manager is initialized on skin load - if the skin isn't yet loaded, 114 no windows should be able to be initialized. 115 \return true if the window manager is initialized, false otherwise. 116 */ Initialized()117 bool Initialized() const { return m_initialized; }; 118 119 /*! \brief Create and initialize all windows and dialogs 120 */ 121 void CreateWindows(); 122 123 /*! \brief Destroy and remove all windows and dialogs 124 * 125 * \return true on success, false if destruction fails for any window 126 */ 127 bool DestroyWindows(); 128 129 /*! \brief Destroy and remove the window or dialog with the given id 130 * 131 *\param id the window id 132 */ 133 void DestroyWindow(int id); 134 135 /*! \brief Return the window of type \code{T} with the given id or 136 * null if no window exists with the given id. 137 * 138 * \tparam T the window class type 139 * \param id the window id 140 * \return the window with for the given type \code{T} or null 141 */ 142 template<typename T, typename std::enable_if<std::is_base_of<CGUIWindow,T>::value>::type* = nullptr> GetWindow(int id)143 T* GetWindow(int id) const { return dynamic_cast<T *>(GetWindow(id)); }; 144 145 /*! \brief Return the window with the given id or null. 146 * 147 * \param id the window id 148 * \return the window with the given id or null 149 */ 150 CGUIWindow* GetWindow(int id) const; 151 152 /*! \brief Return the dialog window with the given id or null. 153 * 154 * \param id the dialog window id 155 * \return the dialog window with the given id or null 156 */ 157 CGUIDialog* GetDialog(int id) const; 158 159 void SetCallback(IWindowManagerCallback& callback); 160 void DeInitialize(); 161 162 /*! \brief Register a dialog as active dialog 163 * 164 * \param dialog The dialog to register as active dialog 165 */ 166 void RegisterDialog(CGUIWindow* dialog); 167 void RemoveDialog(int id); 168 169 /*! \brief Get the ID of the topmost dialog 170 * 171 * \param ignoreClosing ignore dialog is closing 172 * \return the ID of the topmost dialog or WINDOW_INVALID if no dialog is active 173 */ 174 int GetTopmostDialog(bool ignoreClosing = false) const; 175 176 /*! \brief Get the ID of the topmost modal dialog 177 * 178 * \param ignoreClosing ignore dialog is closing 179 * \return the ID of the topmost modal dialog or WINDOW_INVALID if no modal dialog is active 180 */ 181 int GetTopmostModalDialog(bool ignoreClosing = false) const; 182 183 void SendThreadMessage(CGUIMessage& message, int window = 0); 184 void DispatchThreadMessages(); 185 // method to removed queued messages with message id in the requested message id list. 186 // pMessageIDList: point to first integer of a 0 ends integer array. 187 int RemoveThreadMessageByMessageIds(int *pMessageIDList); 188 void AddMsgTarget( IMsgTargetCallback* pMsgTarget ); 189 int GetActiveWindow() const; 190 int GetActiveWindowOrDialog() const; 191 bool HasModalDialog(bool ignoreClosing) const; 192 bool HasVisibleModalDialog() const; 193 bool IsDialogTopmost(int id, bool modal = false) const; 194 bool IsDialogTopmost(const std::string &xmlFile, bool modal = false) const; 195 bool IsModalDialogTopmost(int id) const; 196 bool IsModalDialogTopmost(const std::string &xmlFile) const; 197 bool IsWindowActive(int id, bool ignoreClosing = true) const; 198 bool IsWindowVisible(int id) const; 199 bool IsWindowActive(const std::string &xmlFile, bool ignoreClosing = true) const; 200 bool IsWindowVisible(const std::string &xmlFile) const; 201 /*! \brief Checks if the given window is an addon window. 202 * 203 * \return true if the given window is an addon window, otherwise false. 204 */ IsAddonWindow(int id)205 bool IsAddonWindow(int id) const { return (id >= WINDOW_ADDON_START && id <= WINDOW_ADDON_END); }; 206 /*! \brief Checks if the given window is a python window. 207 * 208 * \return true if the given window is a python window, otherwise false. 209 */ IsPythonWindow(int id)210 bool IsPythonWindow(int id) const { return (id >= WINDOW_PYTHON_START && id <= WINDOW_PYTHON_END); }; 211 212 bool HasVisibleControls(); 213 214 #ifdef _DEBUG 215 void DumpTextureUse(); 216 #endif 217 private: 218 void RenderPass() const; 219 220 void LoadNotOnDemandWindows(); 221 void UnloadNotOnDemandWindows(); 222 void AddToWindowHistory(int newWindowID); 223 224 /*! 225 \brief Check if the given window id is in the window history, and if so, remove this 226 window and all overlying windows from the history so that we always have a predictable 227 "Back" behaviour for each window. 228 229 \param windowID the window id to remove from the window history 230 */ 231 void RemoveFromWindowHistory(int windowID); 232 void ClearWindowHistory(); 233 void CloseWindowSync(CGUIWindow *window, int nextWindowID = 0); 234 int GetTopmostDialog(bool modal, bool ignoreClosing) const; 235 236 friend class KODI::MESSAGING::CApplicationMessenger; 237 238 /*! \brief Activate the given window. 239 * 240 * \param windowID The window ID to activate. 241 * \param params Parameter 242 * \param swappingWindows True if the window should be swapped with the previous window instead of put it in the window history, otherwise false 243 * \param force True to ignore checks which refuses opening the window, otherwise false 244 */ 245 void ActivateWindow_Internal(int windowID, const std::vector<std::string> ¶ms, bool swappingWindows, bool force = false); 246 247 bool ProcessRenderLoop(bool renderOnly); 248 249 bool HandleAction(const CAction &action) const; 250 251 std::unordered_map<int, CGUIWindow*> m_mapWindows; 252 std::vector<CGUIWindow*> m_vecCustomWindows; 253 std::vector<CGUIWindow*> m_activeDialogs; 254 std::vector<CGUIWindow*> m_deleteWindows; 255 256 std::deque<int> m_windowHistory; 257 258 IWindowManagerCallback* m_pCallback; 259 std::list< std::pair<CGUIMessage*,int> > m_vecThreadMessages; 260 CCriticalSection m_critSection; 261 std::vector<IMsgTargetCallback*> m_vecMsgTargets; 262 263 int m_iNested; 264 bool m_initialized; 265 mutable bool m_touchGestureActive{false}; 266 mutable bool m_inhibitTouchGestureEvents{false}; 267 268 CDirtyRegionList m_dirtyregions; 269 CDirtyRegionTracker m_tracker; 270 }; 271