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"
24 // -----------------------------------------------------------------------
25 // ScopedGraphicsContext
27 Window::ScopedGraphicsContext::ScopedGraphicsContext(Window
& win
)
30 active(puglBackendEnter(window
.pData
->view
)) {}
32 Window::ScopedGraphicsContext::ScopedGraphicsContext(Window
& win
, Window
& transientWin
)
34 ppData(transientWin
.pData
),
37 puglBackendLeave(ppData
->view
);
38 active
= puglBackendEnter(window
.pData
->view
);
41 Window::ScopedGraphicsContext::~ScopedGraphicsContext()
46 void Window::ScopedGraphicsContext::done()
50 puglBackendLeave(window
.pData
->view
);
54 if (ppData
!= nullptr)
56 puglBackendEnter(ppData
->view
);
61 // -----------------------------------------------------------------------
64 Window::Window(Application
& app
)
65 : pData(new PrivateData(app
, this))
70 Window::Window(Application
& app
, Window
& transientParentWindow
)
71 : pData(new PrivateData(app
, this, transientParentWindow
.pData
))
76 Window::Window(Application
& app
,
77 const uintptr_t parentWindowHandle
,
78 const double scaleFactor
,
80 : pData(new PrivateData(app
, this, parentWindowHandle
, scaleFactor
, resizable
))
85 Window::Window(Application
& app
,
86 const uintptr_t parentWindowHandle
,
89 const double scaleFactor
,
91 : pData(new PrivateData(app
, this, parentWindowHandle
, width
, height
, scaleFactor
, resizable
, false))
96 Window::Window(Application
& app
,
97 const uintptr_t parentWindowHandle
,
100 const double scaleFactor
,
101 const bool resizable
,
103 const bool doPostInit
)
104 : pData(new PrivateData(app
, this, parentWindowHandle
, width
, height
, scaleFactor
, resizable
, isVST3
))
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
)
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
,);
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
)
259 if (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
))
272 if (reqRatio
> ratio
)
273 width
= static_cast<uint
>(height
* ratio
+ 0.5);
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
);
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
356 #ifndef DPF_TEST_WINDOW_CPP
357 const GraphicsContext
& Window::getGraphicsContext() const noexcept
359 return pData
->getGraphicsContext();
363 uintptr_t Window::getNativeWindowHandle() const noexcept
365 return puglGetNativeView(pData
->view
);
368 double Window::getScaleFactor() const noexcept
370 return pData
->scaleFactor
;
378 #ifndef DGL_FILE_BROWSER_DISABLED
379 bool Window::openFileBrowser(const FileBrowserOptions
& options
)
381 return pData
->openFileBrowser(options
);
385 void Window::repaint() noexcept
387 if (pData
->view
== nullptr)
390 puglPostRedisplay(pData
->view
);
393 void Window::repaint(const Rectangle
<uint
>& rect
) noexcept
395 if (pData
->view
== nullptr)
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
,
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)
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
);
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)
505 bool Window::onClose()
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*)
529 // -----------------------------------------------------------------------