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