Mercurial > hg > pub > prymula > com
comparison DPF-Prymula-audioplugins/dpf/dgl/src/Window.cpp @ 3:84e66ea83026
DPF-Prymula-audioplugins-0.231015-2
author | prymula <prymula76@outlook.com> |
---|---|
date | Mon, 16 Oct 2023 21:53:34 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:cf2cb71d31dd | 3:84e66ea83026 |
---|---|
1 /* | |
2 * DISTRHO Plugin Framework (DPF) | |
3 * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com> | |
4 * | |
5 * Permission to use, copy, modify, and/or distribute this software for any purpose with | |
6 * or without fee is hereby granted, provided that the above copyright notice and this | |
7 * permission notice appear in all copies. | |
8 * | |
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |
10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |
11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |
13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 */ | |
16 | |
17 #include "WindowPrivateData.hpp" | |
18 #include "../TopLevelWidget.hpp" | |
19 | |
20 #include "pugl.hpp" | |
21 | |
22 START_NAMESPACE_DGL | |
23 | |
24 // ----------------------------------------------------------------------- | |
25 // ScopedGraphicsContext | |
26 | |
27 Window::ScopedGraphicsContext::ScopedGraphicsContext(Window& win) | |
28 : window(win), | |
29 ppData(nullptr), | |
30 active(puglBackendEnter(window.pData->view)), | |
31 reenter(false) {} | |
32 | |
33 Window::ScopedGraphicsContext::ScopedGraphicsContext(Window& win, Window& transientWin) | |
34 : window(win), | |
35 ppData(transientWin.pData), | |
36 active(false), | |
37 reenter(true) | |
38 { | |
39 puglBackendLeave(ppData->view); | |
40 active = puglBackendEnter(window.pData->view); | |
41 } | |
42 | |
43 Window::ScopedGraphicsContext::~ScopedGraphicsContext() | |
44 { | |
45 done(); | |
46 } | |
47 | |
48 void Window::ScopedGraphicsContext::done() | |
49 { | |
50 if (active) | |
51 { | |
52 puglBackendLeave(window.pData->view); | |
53 active = false; | |
54 } | |
55 | |
56 if (reenter) | |
57 { | |
58 reenter = false; | |
59 DISTRHO_SAFE_ASSERT_RETURN(ppData != nullptr,); | |
60 | |
61 puglBackendEnter(ppData->view); | |
62 } | |
63 } | |
64 | |
65 void Window::ScopedGraphicsContext::reinit() | |
66 { | |
67 DISTRHO_SAFE_ASSERT_RETURN(!active,); | |
68 DISTRHO_SAFE_ASSERT_RETURN(!reenter,); | |
69 DISTRHO_SAFE_ASSERT_RETURN(ppData != nullptr,); | |
70 | |
71 reenter = true; | |
72 puglBackendLeave(ppData->view); | |
73 active = puglBackendEnter(window.pData->view); | |
74 } | |
75 | |
76 // ----------------------------------------------------------------------- | |
77 // Window | |
78 | |
79 Window::Window(Application& app) | |
80 : pData(new PrivateData(app, this)) | |
81 { | |
82 pData->initPost(); | |
83 } | |
84 | |
85 Window::Window(Application& app, Window& transientParentWindow) | |
86 : pData(new PrivateData(app, this, transientParentWindow.pData)) | |
87 { | |
88 pData->initPost(); | |
89 } | |
90 | |
91 Window::Window(Application& app, | |
92 const uintptr_t parentWindowHandle, | |
93 const double scaleFactor, | |
94 const bool resizable) | |
95 : pData(new PrivateData(app, this, parentWindowHandle, scaleFactor, resizable)) | |
96 { | |
97 pData->initPost(); | |
98 } | |
99 | |
100 Window::Window(Application& app, | |
101 const uintptr_t parentWindowHandle, | |
102 const uint width, | |
103 const uint height, | |
104 const double scaleFactor, | |
105 const bool resizable) | |
106 : pData(new PrivateData(app, this, parentWindowHandle, width, height, scaleFactor, resizable, false)) | |
107 { | |
108 pData->initPost(); | |
109 } | |
110 | |
111 Window::Window(Application& app, | |
112 const uintptr_t parentWindowHandle, | |
113 const uint width, | |
114 const uint height, | |
115 const double scaleFactor, | |
116 const bool resizable, | |
117 const bool isVST3, | |
118 const bool doPostInit) | |
119 : pData(new PrivateData(app, this, parentWindowHandle, width, height, scaleFactor, resizable, isVST3)) | |
120 { | |
121 if (doPostInit) | |
122 pData->initPost(); | |
123 } | |
124 | |
125 Window::~Window() | |
126 { | |
127 delete pData; | |
128 } | |
129 | |
130 bool Window::isEmbed() const noexcept | |
131 { | |
132 return pData->isEmbed; | |
133 } | |
134 | |
135 bool Window::isVisible() const noexcept | |
136 { | |
137 return pData->isVisible; | |
138 } | |
139 | |
140 void Window::setVisible(const bool visible) | |
141 { | |
142 if (visible) | |
143 pData->show(); | |
144 else | |
145 pData->hide(); | |
146 } | |
147 | |
148 void Window::show() | |
149 { | |
150 pData->show(); | |
151 } | |
152 | |
153 void Window::hide() | |
154 { | |
155 pData->hide(); | |
156 } | |
157 | |
158 void Window::close() | |
159 { | |
160 pData->close(); | |
161 } | |
162 | |
163 bool Window::isResizable() const noexcept | |
164 { | |
165 return puglGetViewHint(pData->view, PUGL_RESIZABLE) == PUGL_TRUE; | |
166 } | |
167 | |
168 void Window::setResizable(const bool resizable) | |
169 { | |
170 pData->setResizable(resizable); | |
171 } | |
172 | |
173 int Window::getOffsetX() const noexcept | |
174 { | |
175 DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, 0); | |
176 | |
177 return puglGetFrame(pData->view).x; | |
178 } | |
179 | |
180 int Window::getOffsetY() const noexcept | |
181 { | |
182 DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, 0); | |
183 | |
184 return puglGetFrame(pData->view).y; | |
185 } | |
186 | |
187 Point<int> Window::getOffset() const noexcept | |
188 { | |
189 DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, Point<int>()); | |
190 | |
191 const PuglRect rect = puglGetFrame(pData->view); | |
192 return Point<int>(rect.x, rect.y); | |
193 } | |
194 | |
195 void Window::setOffsetX(const int x) | |
196 { | |
197 setOffset(x, getOffsetY()); | |
198 } | |
199 | |
200 void Window::setOffsetY(const int y) | |
201 { | |
202 setOffset(getOffsetX(), y); | |
203 } | |
204 | |
205 void Window::setOffset(const int x, const int y) | |
206 { | |
207 puglSetPosition(pData->view, x, y); | |
208 } | |
209 | |
210 void Window::setOffset(const Point<int>& offset) | |
211 { | |
212 setOffset(offset.getX(), offset.getY()); | |
213 } | |
214 | |
215 uint Window::getWidth() const noexcept | |
216 { | |
217 DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, 0); | |
218 | |
219 const double width = puglGetFrame(pData->view).width; | |
220 DISTRHO_SAFE_ASSERT_RETURN(width >= 0.0, 0); | |
221 return static_cast<uint>(width + 0.5); | |
222 } | |
223 | |
224 uint Window::getHeight() const noexcept | |
225 { | |
226 DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, 0); | |
227 | |
228 const double height = puglGetFrame(pData->view).height; | |
229 DISTRHO_SAFE_ASSERT_RETURN(height >= 0.0, 0); | |
230 return static_cast<uint>(height + 0.5); | |
231 } | |
232 | |
233 Size<uint> Window::getSize() const noexcept | |
234 { | |
235 DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, Size<uint>()); | |
236 | |
237 const PuglRect rect = puglGetFrame(pData->view); | |
238 DISTRHO_SAFE_ASSERT_RETURN(rect.width >= 0.0, Size<uint>()); | |
239 DISTRHO_SAFE_ASSERT_RETURN(rect.height >= 0.0, Size<uint>()); | |
240 return Size<uint>(static_cast<uint>(rect.width + 0.5), | |
241 static_cast<uint>(rect.height + 0.5)); | |
242 } | |
243 | |
244 void Window::setWidth(const uint width) | |
245 { | |
246 setSize(width, getHeight()); | |
247 } | |
248 | |
249 void Window::setHeight(const uint height) | |
250 { | |
251 setSize(getWidth(), height); | |
252 } | |
253 | |
254 void Window::setSize(uint width, uint height) | |
255 { | |
256 DISTRHO_SAFE_ASSERT_UINT2_RETURN(width > 1 && height > 1, width, height,); | |
257 | |
258 if (pData->isEmbed) | |
259 { | |
260 const double scaleFactor = pData->scaleFactor; | |
261 uint minWidth = pData->minWidth; | |
262 uint minHeight = pData->minHeight; | |
263 | |
264 if (pData->autoScaling && scaleFactor != 1.0) | |
265 { | |
266 minWidth *= scaleFactor; | |
267 minHeight *= scaleFactor; | |
268 } | |
269 | |
270 // handle geometry constraints here | |
271 if (width < minWidth) | |
272 width = minWidth; | |
273 | |
274 if (height < minHeight) | |
275 height = minHeight; | |
276 | |
277 if (pData->keepAspectRatio) | |
278 { | |
279 const double ratio = static_cast<double>(pData->minWidth) | |
280 / static_cast<double>(pData->minHeight); | |
281 const double reqRatio = static_cast<double>(width) | |
282 / static_cast<double>(height); | |
283 | |
284 if (d_isNotEqual(ratio, reqRatio)) | |
285 { | |
286 // fix width | |
287 if (reqRatio > ratio) | |
288 width = static_cast<uint>(height * ratio + 0.5); | |
289 // fix height | |
290 else | |
291 height = static_cast<uint>(static_cast<double>(width) / ratio + 0.5); | |
292 } | |
293 } | |
294 } | |
295 | |
296 if (pData->usesSizeRequest) | |
297 { | |
298 DISTRHO_SAFE_ASSERT_RETURN(pData->topLevelWidgets.size() != 0,); | |
299 | |
300 TopLevelWidget* const topLevelWidget = pData->topLevelWidgets.front(); | |
301 DISTRHO_SAFE_ASSERT_RETURN(topLevelWidget != nullptr,); | |
302 | |
303 topLevelWidget->requestSizeChange(width, height); | |
304 } | |
305 else | |
306 { | |
307 puglSetSizeAndDefault(pData->view, width, height); | |
308 } | |
309 } | |
310 | |
311 void Window::setSize(const Size<uint>& size) | |
312 { | |
313 setSize(size.getWidth(), size.getHeight()); | |
314 } | |
315 | |
316 const char* Window::getTitle() const noexcept | |
317 { | |
318 return puglGetWindowTitle(pData->view); | |
319 } | |
320 | |
321 void Window::setTitle(const char* const title) | |
322 { | |
323 if (pData->view != nullptr) | |
324 puglSetWindowTitle(pData->view, title); | |
325 } | |
326 | |
327 bool Window::isIgnoringKeyRepeat() const noexcept | |
328 { | |
329 return puglGetViewHint(pData->view, PUGL_IGNORE_KEY_REPEAT) == PUGL_TRUE; | |
330 } | |
331 | |
332 void Window::setIgnoringKeyRepeat(const bool ignore) noexcept | |
333 { | |
334 puglSetViewHint(pData->view, PUGL_IGNORE_KEY_REPEAT, ignore); | |
335 } | |
336 | |
337 const void* Window::getClipboard(size_t& dataSize) | |
338 { | |
339 return pData->getClipboard(dataSize); | |
340 } | |
341 | |
342 bool Window::setClipboard(const char* const mimeType, const void* const data, const size_t dataSize) | |
343 { | |
344 return puglSetClipboard(pData->view, mimeType != nullptr ? mimeType : "text/plain", data, dataSize) == PUGL_SUCCESS; | |
345 } | |
346 | |
347 bool Window::setCursor(const MouseCursor cursor) | |
348 { | |
349 return puglSetCursor(pData->view, static_cast<PuglCursor>(cursor)) == PUGL_SUCCESS; | |
350 } | |
351 | |
352 bool Window::addIdleCallback(IdleCallback* const callback, const uint timerFrequencyInMs) | |
353 { | |
354 DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr, false) | |
355 | |
356 return pData->addIdleCallback(callback, timerFrequencyInMs); | |
357 } | |
358 | |
359 bool Window::removeIdleCallback(IdleCallback* const callback) | |
360 { | |
361 DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr, false) | |
362 | |
363 return pData->removeIdleCallback(callback); | |
364 } | |
365 | |
366 Application& Window::getApp() const noexcept | |
367 { | |
368 return pData->app; | |
369 } | |
370 | |
371 #ifndef DPF_TEST_WINDOW_CPP | |
372 const GraphicsContext& Window::getGraphicsContext() const noexcept | |
373 { | |
374 return pData->getGraphicsContext(); | |
375 } | |
376 #endif | |
377 | |
378 uintptr_t Window::getNativeWindowHandle() const noexcept | |
379 { | |
380 return puglGetNativeView(pData->view); | |
381 } | |
382 | |
383 double Window::getScaleFactor() const noexcept | |
384 { | |
385 return pData->scaleFactor; | |
386 } | |
387 | |
388 void Window::focus() | |
389 { | |
390 pData->focus(); | |
391 } | |
392 | |
393 #ifndef DGL_FILE_BROWSER_DISABLED | |
394 bool Window::openFileBrowser(const FileBrowserOptions& options) | |
395 { | |
396 return pData->openFileBrowser(options); | |
397 } | |
398 #endif | |
399 | |
400 void Window::repaint() noexcept | |
401 { | |
402 if (pData->view == nullptr) | |
403 return; | |
404 | |
405 puglPostRedisplay(pData->view); | |
406 } | |
407 | |
408 void Window::repaint(const Rectangle<uint>& rect) noexcept | |
409 { | |
410 if (pData->view == nullptr) | |
411 return; | |
412 | |
413 PuglRect prect = { | |
414 static_cast<PuglCoord>(rect.getX()), | |
415 static_cast<PuglCoord>(rect.getY()), | |
416 static_cast<PuglSpan>(rect.getWidth()), | |
417 static_cast<PuglSpan>(rect.getHeight()), | |
418 }; | |
419 if (pData->autoScaling) | |
420 { | |
421 const double autoScaleFactor = pData->autoScaleFactor; | |
422 | |
423 prect.x *= autoScaleFactor; | |
424 prect.y *= autoScaleFactor; | |
425 prect.width *= autoScaleFactor; | |
426 prect.height *= autoScaleFactor; | |
427 } | |
428 puglPostRedisplayRect(pData->view, prect); | |
429 } | |
430 | |
431 void Window::renderToPicture(const char* const filename) | |
432 { | |
433 pData->filenameToRenderInto = strdup(filename); | |
434 } | |
435 | |
436 void Window::runAsModal(bool blockWait) | |
437 { | |
438 pData->runAsModal(blockWait); | |
439 } | |
440 | |
441 Size<uint> Window::getGeometryConstraints(bool& keepAspectRatio) | |
442 { | |
443 keepAspectRatio = pData->keepAspectRatio; | |
444 return Size<uint>(pData->minWidth, pData->minHeight); | |
445 } | |
446 | |
447 void Window::setGeometryConstraints(uint minimumWidth, | |
448 uint minimumHeight, | |
449 const bool keepAspectRatio, | |
450 const bool automaticallyScale, | |
451 const bool resizeNowIfAutoScaling) | |
452 { | |
453 DISTRHO_SAFE_ASSERT_RETURN(minimumWidth > 0,); | |
454 DISTRHO_SAFE_ASSERT_RETURN(minimumHeight > 0,); | |
455 | |
456 pData->minWidth = minimumWidth; | |
457 pData->minHeight = minimumHeight; | |
458 pData->autoScaling = automaticallyScale; | |
459 pData->keepAspectRatio = keepAspectRatio; | |
460 | |
461 if (pData->view == nullptr) | |
462 return; | |
463 | |
464 const double scaleFactor = pData->scaleFactor; | |
465 | |
466 if (automaticallyScale && scaleFactor != 1.0) | |
467 { | |
468 minimumWidth *= scaleFactor; | |
469 minimumHeight *= scaleFactor; | |
470 } | |
471 | |
472 puglSetGeometryConstraints(pData->view, minimumWidth, minimumHeight, keepAspectRatio); | |
473 | |
474 if (scaleFactor != 1.0 && automaticallyScale && resizeNowIfAutoScaling) | |
475 { | |
476 const Size<uint> size(getSize()); | |
477 | |
478 setSize(static_cast<uint>(size.getWidth() * scaleFactor + 0.5), | |
479 static_cast<uint>(size.getHeight() * scaleFactor + 0.5)); | |
480 } | |
481 } | |
482 | |
483 void Window::setTransientParent(const uintptr_t transientParentWindowHandle) | |
484 { | |
485 puglSetTransientParent(pData->view, transientParentWindowHandle); | |
486 } | |
487 | |
488 std::vector<ClipboardDataOffer> Window::getClipboardDataOfferTypes() | |
489 { | |
490 std::vector<ClipboardDataOffer> offerTypes; | |
491 | |
492 if (const uint32_t numTypes = puglGetNumClipboardTypes(pData->view)) | |
493 { | |
494 offerTypes.reserve(numTypes); | |
495 | |
496 for (uint32_t i=0; i<numTypes; ++i) | |
497 { | |
498 const ClipboardDataOffer offer = { i + 1, puglGetClipboardType(pData->view, i) }; | |
499 offerTypes.push_back(offer); | |
500 } | |
501 } | |
502 | |
503 return offerTypes; | |
504 } | |
505 | |
506 uint32_t Window::onClipboardDataOffer() | |
507 { | |
508 std::vector<ClipboardDataOffer> offers(getClipboardDataOfferTypes()); | |
509 | |
510 for (std::vector<ClipboardDataOffer>::iterator it=offers.begin(), end=offers.end(); it != end;++it) | |
511 { | |
512 const ClipboardDataOffer offer = *it; | |
513 if (std::strcmp(offer.type, "text/plain") == 0) | |
514 return offer.id; | |
515 } | |
516 | |
517 return 0; | |
518 } | |
519 | |
520 bool Window::onClose() | |
521 { | |
522 return true; | |
523 } | |
524 | |
525 void Window::onFocus(bool, CrossingMode) | |
526 { | |
527 } | |
528 | |
529 void Window::onReshape(uint, uint) | |
530 { | |
531 puglFallbackOnResize(pData->view); | |
532 } | |
533 | |
534 void Window::onScaleFactorChanged(double) | |
535 { | |
536 } | |
537 | |
538 #ifndef DGL_FILE_BROWSER_DISABLED | |
539 void Window::onFileSelected(const char*) | |
540 { | |
541 } | |
542 #endif | |
543 | |
544 // ----------------------------------------------------------------------- | |
545 | |
546 END_NAMESPACE_DGL |