Cleanup
[carla.git] / source / modules / dgl / src / Window.cpp
blob37c61d119fe8e7d32d82153412dcb12c3a947808
1 /*
2 * DISTRHO Plugin Framework (DPF)
3 * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com>
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.
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.
17 #include "WindowPrivateData.hpp"
18 #include "../TopLevelWidget.hpp"
20 #include "pugl.hpp"
22 START_NAMESPACE_DGL
24 // -----------------------------------------------------------------------
25 // ScopedGraphicsContext
27 Window::ScopedGraphicsContext::ScopedGraphicsContext(Window& win)
28 : window(win),
29 ppData(nullptr),
30 active(puglBackendEnter(window.pData->view)) {}
32 Window::ScopedGraphicsContext::ScopedGraphicsContext(Window& win, Window& transientWin)
33 : window(win),
34 ppData(transientWin.pData),
35 active(false)
37 puglBackendLeave(ppData->view);
38 active = puglBackendEnter(window.pData->view);
41 Window::ScopedGraphicsContext::~ScopedGraphicsContext()
43 done();
46 void Window::ScopedGraphicsContext::done()
48 if (active)
50 puglBackendLeave(window.pData->view);
51 active = false;
54 if (ppData != nullptr)
56 puglBackendEnter(ppData->view);
57 ppData = nullptr;
61 // -----------------------------------------------------------------------
62 // Window
64 Window::Window(Application& app)
65 : pData(new PrivateData(app, this))
67 pData->initPost();
70 Window::Window(Application& app, Window& transientParentWindow)
71 : pData(new PrivateData(app, this, transientParentWindow.pData))
73 pData->initPost();
76 Window::Window(Application& app,
77 const uintptr_t parentWindowHandle,
78 const double scaleFactor,
79 const bool resizable)
80 : pData(new PrivateData(app, this, parentWindowHandle, scaleFactor, resizable))
82 pData->initPost();
85 Window::Window(Application& app,
86 const uintptr_t parentWindowHandle,
87 const uint width,
88 const uint height,
89 const double scaleFactor,
90 const bool resizable)
91 : pData(new PrivateData(app, this, parentWindowHandle, width, height, scaleFactor, resizable, false))
93 pData->initPost();
96 Window::Window(Application& app,
97 const uintptr_t parentWindowHandle,
98 const uint width,
99 const uint height,
100 const double scaleFactor,
101 const bool resizable,
102 const bool isVST3,
103 const bool doPostInit)
104 : pData(new PrivateData(app, this, parentWindowHandle, width, height, scaleFactor, resizable, isVST3))
106 if (doPostInit)
107 pData->initPost();
110 Window::~Window()
112 delete pData;
115 bool Window::isEmbed() const noexcept
117 return pData->isEmbed;
120 bool Window::isVisible() const noexcept
122 return pData->isVisible;
125 void Window::setVisible(const bool visible)
127 if (visible)
128 pData->show();
129 else
130 pData->hide();
133 void Window::show()
135 pData->show();
138 void Window::hide()
140 pData->hide();
143 void Window::close()
145 pData->close();
148 bool Window::isResizable() const noexcept
150 return puglGetViewHint(pData->view, PUGL_RESIZABLE) == PUGL_TRUE;
153 void Window::setResizable(const bool resizable)
155 pData->setResizable(resizable);
158 int Window::getOffsetX() const noexcept
160 DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, 0);
162 return puglGetFrame(pData->view).x;
165 int Window::getOffsetY() const noexcept
167 DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, 0);
169 return puglGetFrame(pData->view).y;
172 Point<int> Window::getOffset() const noexcept
174 DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, Point<int>());
176 const PuglRect rect = puglGetFrame(pData->view);
177 return Point<int>(rect.x, rect.y);
180 void Window::setOffsetX(const int x)
182 setOffset(x, getOffsetY());
185 void Window::setOffsetY(const int y)
187 setOffset(getOffsetX(), y);
190 void Window::setOffset(const int x, const int y)
192 puglSetPosition(pData->view, x, y);
195 void Window::setOffset(const Point<int>& offset)
197 setOffset(offset.getX(), offset.getY());
200 uint Window::getWidth() const noexcept
202 DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, 0);
204 const double width = puglGetFrame(pData->view).width;
205 DISTRHO_SAFE_ASSERT_RETURN(width >= 0.0, 0);
206 return static_cast<uint>(width + 0.5);
209 uint Window::getHeight() const noexcept
211 DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, 0);
213 const double height = puglGetFrame(pData->view).height;
214 DISTRHO_SAFE_ASSERT_RETURN(height >= 0.0, 0);
215 return static_cast<uint>(height + 0.5);
218 Size<uint> Window::getSize() const noexcept
220 DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, Size<uint>());
222 const PuglRect rect = puglGetFrame(pData->view);
223 DISTRHO_SAFE_ASSERT_RETURN(rect.width >= 0.0, Size<uint>());
224 DISTRHO_SAFE_ASSERT_RETURN(rect.height >= 0.0, Size<uint>());
225 return Size<uint>(static_cast<uint>(rect.width + 0.5),
226 static_cast<uint>(rect.height + 0.5));
229 void Window::setWidth(const uint width)
231 setSize(width, getHeight());
234 void Window::setHeight(const uint height)
236 setSize(getWidth(), height);
239 void Window::setSize(uint width, uint height)
241 DISTRHO_SAFE_ASSERT_UINT2_RETURN(width > 1 && height > 1, width, height,);
243 if (pData->isEmbed)
245 const double scaleFactor = pData->scaleFactor;
246 uint minWidth = pData->minWidth;
247 uint minHeight = pData->minHeight;
249 if (pData->autoScaling && scaleFactor != 1.0)
251 minWidth *= scaleFactor;
252 minHeight *= scaleFactor;
255 // handle geometry constraints here
256 if (width < minWidth)
257 width = minWidth;
259 if (height < minHeight)
260 height = minHeight;
262 if (pData->keepAspectRatio)
264 const double ratio = static_cast<double>(pData->minWidth)
265 / static_cast<double>(pData->minHeight);
266 const double reqRatio = static_cast<double>(width)
267 / static_cast<double>(height);
269 if (d_isNotEqual(ratio, reqRatio))
271 // fix width
272 if (reqRatio > ratio)
273 width = static_cast<uint>(height * ratio + 0.5);
274 // fix height
275 else
276 height = static_cast<uint>(static_cast<double>(width) / ratio + 0.5);
281 if (pData->usesSizeRequest)
283 DISTRHO_SAFE_ASSERT_RETURN(pData->topLevelWidgets.size() != 0,);
285 TopLevelWidget* const topLevelWidget = pData->topLevelWidgets.front();
286 DISTRHO_SAFE_ASSERT_RETURN(topLevelWidget != nullptr,);
288 topLevelWidget->requestSizeChange(width, height);
290 else
292 puglSetSizeAndDefault(pData->view, width, height);
296 void Window::setSize(const Size<uint>& size)
298 setSize(size.getWidth(), size.getHeight());
301 const char* Window::getTitle() const noexcept
303 return puglGetWindowTitle(pData->view);
306 void Window::setTitle(const char* const title)
308 if (pData->view != nullptr)
309 puglSetWindowTitle(pData->view, title);
312 bool Window::isIgnoringKeyRepeat() const noexcept
314 return puglGetViewHint(pData->view, PUGL_IGNORE_KEY_REPEAT) == PUGL_TRUE;
317 void Window::setIgnoringKeyRepeat(const bool ignore) noexcept
319 puglSetViewHint(pData->view, PUGL_IGNORE_KEY_REPEAT, ignore);
322 const void* Window::getClipboard(size_t& dataSize)
324 return pData->getClipboard(dataSize);
327 bool Window::setClipboard(const char* const mimeType, const void* const data, const size_t dataSize)
329 return puglSetClipboard(pData->view, mimeType != nullptr ? mimeType : "text/plain", data, dataSize) == PUGL_SUCCESS;
332 bool Window::setCursor(const MouseCursor cursor)
334 return puglSetCursor(pData->view, static_cast<PuglCursor>(cursor)) == PUGL_SUCCESS;
337 bool Window::addIdleCallback(IdleCallback* const callback, const uint timerFrequencyInMs)
339 DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr, false)
341 return pData->addIdleCallback(callback, timerFrequencyInMs);
344 bool Window::removeIdleCallback(IdleCallback* const callback)
346 DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr, false)
348 return pData->removeIdleCallback(callback);
351 Application& Window::getApp() const noexcept
353 return pData->app;
356 #ifndef DPF_TEST_WINDOW_CPP
357 const GraphicsContext& Window::getGraphicsContext() const noexcept
359 return pData->getGraphicsContext();
361 #endif
363 uintptr_t Window::getNativeWindowHandle() const noexcept
365 return puglGetNativeView(pData->view);
368 double Window::getScaleFactor() const noexcept
370 return pData->scaleFactor;
373 void Window::focus()
375 pData->focus();
378 #ifndef DGL_FILE_BROWSER_DISABLED
379 bool Window::openFileBrowser(const FileBrowserOptions& options)
381 return pData->openFileBrowser(options);
383 #endif
385 void Window::repaint() noexcept
387 if (pData->view == nullptr)
388 return;
390 puglPostRedisplay(pData->view);
393 void Window::repaint(const Rectangle<uint>& rect) noexcept
395 if (pData->view == nullptr)
396 return;
398 PuglRect prect = {
399 static_cast<PuglCoord>(rect.getX()),
400 static_cast<PuglCoord>(rect.getY()),
401 static_cast<PuglSpan>(rect.getWidth()),
402 static_cast<PuglSpan>(rect.getHeight()),
404 if (pData->autoScaling)
406 const double autoScaleFactor = pData->autoScaleFactor;
408 prect.x *= autoScaleFactor;
409 prect.y *= autoScaleFactor;
410 prect.width *= autoScaleFactor;
411 prect.height *= autoScaleFactor;
413 puglPostRedisplayRect(pData->view, prect);
416 void Window::renderToPicture(const char* const filename)
418 pData->filenameToRenderInto = strdup(filename);
421 void Window::runAsModal(bool blockWait)
423 pData->runAsModal(blockWait);
426 Size<uint> Window::getGeometryConstraints(bool& keepAspectRatio)
428 keepAspectRatio = pData->keepAspectRatio;
429 return Size<uint>(pData->minWidth, pData->minHeight);
432 void Window::setGeometryConstraints(uint minimumWidth,
433 uint minimumHeight,
434 const bool keepAspectRatio,
435 const bool automaticallyScale,
436 const bool resizeNowIfAutoScaling)
438 DISTRHO_SAFE_ASSERT_RETURN(minimumWidth > 0,);
439 DISTRHO_SAFE_ASSERT_RETURN(minimumHeight > 0,);
441 pData->minWidth = minimumWidth;
442 pData->minHeight = minimumHeight;
443 pData->autoScaling = automaticallyScale;
444 pData->keepAspectRatio = keepAspectRatio;
446 if (pData->view == nullptr)
447 return;
449 const double scaleFactor = pData->scaleFactor;
451 if (automaticallyScale && scaleFactor != 1.0)
453 minimumWidth *= scaleFactor;
454 minimumHeight *= scaleFactor;
457 puglSetGeometryConstraints(pData->view, minimumWidth, minimumHeight, keepAspectRatio);
459 if (scaleFactor != 1.0 && automaticallyScale && resizeNowIfAutoScaling)
461 const Size<uint> size(getSize());
463 setSize(static_cast<uint>(size.getWidth() * scaleFactor + 0.5),
464 static_cast<uint>(size.getHeight() * scaleFactor + 0.5));
468 void Window::setTransientParent(const uintptr_t transientParentWindowHandle)
470 puglSetTransientParent(pData->view, transientParentWindowHandle);
473 std::vector<ClipboardDataOffer> Window::getClipboardDataOfferTypes()
475 std::vector<ClipboardDataOffer> offerTypes;
477 if (const uint32_t numTypes = puglGetNumClipboardTypes(pData->view))
479 offerTypes.reserve(numTypes);
481 for (uint32_t i=0; i<numTypes; ++i)
483 const ClipboardDataOffer offer = { i + 1, puglGetClipboardType(pData->view, i) };
484 offerTypes.push_back(offer);
488 return offerTypes;
491 uint32_t Window::onClipboardDataOffer()
493 std::vector<ClipboardDataOffer> offers(getClipboardDataOfferTypes());
495 for (std::vector<ClipboardDataOffer>::iterator it=offers.begin(), end=offers.end(); it != end;++it)
497 const ClipboardDataOffer offer = *it;
498 if (std::strcmp(offer.type, "text/plain") == 0)
499 return offer.id;
502 return 0;
505 bool Window::onClose()
507 return true;
510 void Window::onFocus(bool, CrossingMode)
514 void Window::onReshape(uint, uint)
516 puglFallbackOnResize(pData->view);
519 void Window::onScaleFactorChanged(double)
523 #ifndef DGL_FILE_BROWSER_DISABLED
524 void Window::onFileSelected(const char*)
527 #endif
529 // -----------------------------------------------------------------------
531 END_NAMESPACE_DGL