1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
3 | #include "Managers/BsRenderWindowManager.h" |
4 | #include "Platform/BsPlatform.h" |
5 | #include "BsCoreApplication.h" |
6 | |
7 | using namespace std::placeholders; |
8 | |
9 | namespace bs |
10 | { |
11 | SPtr<RenderWindow> RenderWindowManager::create(RENDER_WINDOW_DESC& desc, SPtr<RenderWindow> parentWindow) |
12 | { |
13 | UINT32 id = ct::RenderWindowManager::instance().mNextWindowId.fetch_add(1, std::memory_order_relaxed); |
14 | |
15 | SPtr<RenderWindow> renderWindow = createImpl(desc, id, parentWindow); |
16 | renderWindow->_setThisPtr(renderWindow); |
17 | |
18 | { |
19 | Lock lock(mWindowMutex); |
20 | |
21 | mWindows[renderWindow->mWindowId] = renderWindow.get(); |
22 | } |
23 | |
24 | if (renderWindow->getProperties().isModal) |
25 | mModalWindowStack.push_back(renderWindow.get()); |
26 | |
27 | renderWindow->initialize(); |
28 | |
29 | return renderWindow; |
30 | } |
31 | |
32 | void RenderWindowManager::notifyWindowDestroyed(RenderWindow* window) |
33 | { |
34 | { |
35 | Lock lock(mWindowMutex); |
36 | |
37 | auto iterFind = std::find(begin(mMovedOrResizedWindows), end(mMovedOrResizedWindows), window); |
38 | |
39 | if(iterFind != mMovedOrResizedWindows.end()) |
40 | mMovedOrResizedWindows.erase(iterFind); |
41 | |
42 | if (mNewWindowInFocus == window) |
43 | mNewWindowInFocus = nullptr; |
44 | |
45 | mWindows.erase(window->mWindowId); |
46 | mDirtyProperties.erase(window); |
47 | } |
48 | |
49 | { |
50 | auto iterFind = std::find(begin(mModalWindowStack), end(mModalWindowStack), window); |
51 | if(iterFind != mModalWindowStack.end()) |
52 | mModalWindowStack.erase(iterFind); |
53 | } |
54 | } |
55 | |
56 | void RenderWindowManager::notifyFocusReceived(ct::RenderWindow* coreWindow) |
57 | { |
58 | Lock lock(mWindowMutex); |
59 | |
60 | RenderWindow* window = getNonCore(coreWindow); |
61 | mNewWindowInFocus = window; |
62 | } |
63 | |
64 | void RenderWindowManager::notifyFocusLost(ct::RenderWindow* coreWindow) |
65 | { |
66 | Lock lock(mWindowMutex); |
67 | |
68 | mNewWindowInFocus = nullptr; |
69 | } |
70 | |
71 | void RenderWindowManager::notifyMovedOrResized(ct::RenderWindow* coreWindow) |
72 | { |
73 | Lock lock(mWindowMutex); |
74 | |
75 | RenderWindow* window = getNonCore(coreWindow); |
76 | if (window == nullptr) |
77 | return; |
78 | |
79 | auto iterFind = std::find(begin(mMovedOrResizedWindows), end(mMovedOrResizedWindows), window); |
80 | if (iterFind == end(mMovedOrResizedWindows)) |
81 | mMovedOrResizedWindows.push_back(window); |
82 | } |
83 | |
84 | void RenderWindowManager::notifyMouseLeft(ct::RenderWindow* coreWindow) |
85 | { |
86 | Lock lock(mWindowMutex); |
87 | |
88 | RenderWindow* window = getNonCore(coreWindow); |
89 | auto iterFind = std::find(begin(mMouseLeftWindows), end(mMouseLeftWindows), window); |
90 | |
91 | if (iterFind == end(mMouseLeftWindows)) |
92 | mMouseLeftWindows.push_back(window); |
93 | } |
94 | |
95 | void RenderWindowManager::notifyCloseRequested(ct::RenderWindow* coreWindow) |
96 | { |
97 | Lock lock(mWindowMutex); |
98 | |
99 | RenderWindow* window = getNonCore(coreWindow); |
100 | auto iterFind = std::find(begin(mCloseRequestedWindows), end(mCloseRequestedWindows), window); |
101 | |
102 | if (iterFind == end(mCloseRequestedWindows)) |
103 | mCloseRequestedWindows.push_back(window); |
104 | } |
105 | |
106 | void RenderWindowManager::notifySyncDataDirty(ct::RenderWindow* coreWindow) |
107 | { |
108 | Lock lock(mWindowMutex); |
109 | |
110 | RenderWindow* window = getNonCore(coreWindow); |
111 | |
112 | if (window != nullptr) |
113 | mDirtyProperties.insert(window); |
114 | } |
115 | |
116 | void RenderWindowManager::_update() |
117 | { |
118 | RenderWindow* newWinInFocus = nullptr; |
119 | Vector<RenderWindow*> movedOrResizedWindows; |
120 | Vector<RenderWindow*> mouseLeftWindows; |
121 | Vector<RenderWindow*> closeRequestedWindows; |
122 | |
123 | { |
124 | Lock lock(mWindowMutex); |
125 | newWinInFocus = mNewWindowInFocus; |
126 | |
127 | std::swap(mMovedOrResizedWindows, movedOrResizedWindows); |
128 | std::swap(mMouseLeftWindows, mouseLeftWindows); |
129 | |
130 | for (auto& dirtyPropertyWindow : mDirtyProperties) |
131 | dirtyPropertyWindow->syncProperties(); |
132 | |
133 | mDirtyProperties.clear(); |
134 | |
135 | std::swap(mCloseRequestedWindows, closeRequestedWindows); |
136 | } |
137 | |
138 | if(mWindowInFocus != newWinInFocus) |
139 | { |
140 | if(mWindowInFocus != nullptr) |
141 | onFocusLost(*mWindowInFocus); |
142 | |
143 | if(newWinInFocus != nullptr) |
144 | onFocusGained(*newWinInFocus); |
145 | |
146 | mWindowInFocus = newWinInFocus; |
147 | } |
148 | |
149 | for (auto& window : movedOrResizedWindows) |
150 | window->onResized(); |
151 | |
152 | if (!onMouseLeftWindow.empty()) |
153 | { |
154 | for (auto& window : mouseLeftWindows) |
155 | onMouseLeftWindow(*window); |
156 | } |
157 | |
158 | SPtr<RenderWindow> primaryWindow = gCoreApplication().getPrimaryWindow(); |
159 | for(auto& entry : closeRequestedWindows) |
160 | { |
161 | // Default behaviour for primary window is to quit the app on close |
162 | if(entry == primaryWindow.get() && entry->onCloseRequested.empty()) |
163 | { |
164 | gCoreApplication().quitRequested(); |
165 | continue; |
166 | } |
167 | |
168 | entry->onCloseRequested(); |
169 | } |
170 | } |
171 | |
172 | Vector<RenderWindow*> RenderWindowManager::getRenderWindows() const |
173 | { |
174 | Lock lock(mWindowMutex); |
175 | |
176 | Vector<RenderWindow*> windows; |
177 | for (auto& windowPair : mWindows) |
178 | windows.push_back(windowPair.second); |
179 | |
180 | return windows; |
181 | } |
182 | |
183 | RenderWindow* RenderWindowManager::getTopMostModal() const |
184 | { |
185 | if (mModalWindowStack.empty()) |
186 | return nullptr; |
187 | |
188 | return mModalWindowStack.back(); |
189 | } |
190 | |
191 | RenderWindow* RenderWindowManager::getNonCore(const ct::RenderWindow* window) const |
192 | { |
193 | auto iterFind = mWindows.find(window->mWindowId); |
194 | |
195 | if (iterFind != mWindows.end()) |
196 | return iterFind->second; |
197 | |
198 | return nullptr; |
199 | } |
200 | |
201 | namespace ct |
202 | { |
203 | |
204 | RenderWindowManager::RenderWindowManager() |
205 | { |
206 | mNextWindowId = 0; |
207 | } |
208 | |
209 | void RenderWindowManager::_update() |
210 | { |
211 | Lock lock(mWindowMutex); |
212 | |
213 | for (auto& dirtyPropertyWindow : mDirtyProperties) |
214 | dirtyPropertyWindow->syncProperties(); |
215 | |
216 | mDirtyProperties.clear(); |
217 | } |
218 | |
219 | void RenderWindowManager::windowCreated(RenderWindow* window) |
220 | { |
221 | Lock lock(mWindowMutex); |
222 | |
223 | mCreatedWindows.push_back(window); |
224 | } |
225 | |
226 | void RenderWindowManager::windowDestroyed(RenderWindow* window) |
227 | { |
228 | { |
229 | Lock lock(mWindowMutex); |
230 | |
231 | auto iterFind = std::find(begin(mCreatedWindows), end(mCreatedWindows), window); |
232 | |
233 | if (iterFind == mCreatedWindows.end()) |
234 | BS_EXCEPT(InternalErrorException, "Trying to destroy a window that is not in the created windows list." ); |
235 | |
236 | mCreatedWindows.erase(iterFind); |
237 | mDirtyProperties.erase(window); |
238 | } |
239 | } |
240 | |
241 | Vector<RenderWindow*> RenderWindowManager::getRenderWindows() const |
242 | { |
243 | Lock lock(mWindowMutex); |
244 | |
245 | return mCreatedWindows; |
246 | } |
247 | |
248 | void RenderWindowManager::notifySyncDataDirty(RenderWindow* window) |
249 | { |
250 | Lock lock(mWindowMutex); |
251 | |
252 | mDirtyProperties.insert(window); |
253 | } |
254 | } |
255 | } |