@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * DISTRHO Plugin Framework (DPF) | ||||
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com> | |||||
* Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com> | |||||
* | * | ||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | * Permission to use, copy, modify, and/or distribute this software for any purpose with | ||||
* or without fee is hereby granted, provided that the above copyright notice and this | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -189,7 +189,7 @@ void Window::setOffsetY(const int y) | |||||
void Window::setOffset(const int x, const int y) | void Window::setOffset(const int x, const int y) | ||||
{ | { | ||||
puglSetWindowOffset(pData->view, x, y); | |||||
puglSetPosition(pData->view, x, y); | |||||
} | } | ||||
void Window::setOffset(const Point<int>& offset) | void Window::setOffset(const Point<int>& offset) | ||||
@@ -289,7 +289,7 @@ void Window::setSize(uint width, uint height) | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
puglSetWindowSize(pData->view, width, height); | |||||
puglSetSizeAndDefault(pData->view, width, height); | |||||
} | } | ||||
} | } | ||||
@@ -326,10 +326,7 @@ bool Window::setClipboard(const char* const mimeType, const void* const data, co | |||||
const void* Window::getClipboard(const char*& mimeType, size_t& dataSize) | const void* Window::getClipboard(const char*& mimeType, size_t& dataSize) | ||||
{ | { | ||||
DISTRHO_SAFE_ASSERT_RETURN(!pData->ignoreEvents, nullptr); | |||||
pData->ignoreEvents = true; | |||||
const void* const clipboard = puglGetClipboard(pData->view, &mimeType, &dataSize); | |||||
pData->ignoreEvents = false; | |||||
const void* const clipboard = nullptr; // puglGetClipboard(pData->view, &mimeType, &dataSize); | |||||
return clipboard; | return clipboard; | ||||
} | } | ||||
@@ -400,10 +397,10 @@ void Window::repaint(const Rectangle<uint>& rect) noexcept | |||||
return; | return; | ||||
PuglRect prect = { | PuglRect prect = { | ||||
static_cast<double>(rect.getX()), | |||||
static_cast<double>(rect.getY()), | |||||
static_cast<double>(rect.getWidth()), | |||||
static_cast<double>(rect.getHeight()), | |||||
static_cast<PuglCoord>(rect.getX()), | |||||
static_cast<PuglCoord>(rect.getY()), | |||||
static_cast<PuglSpan>(rect.getWidth()), | |||||
static_cast<PuglSpan>(rect.getHeight()), | |||||
}; | }; | ||||
if (pData->autoScaling) | if (pData->autoScaling) | ||||
{ | { | ||||
@@ -52,39 +52,63 @@ START_NAMESPACE_DGL | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
static double getDesktopScaleFactor(const PuglView* const view) | |||||
static double getScaleFactorFromParent(const PuglView* const view) | |||||
{ | { | ||||
// allow custom scale for testing | // allow custom scale for testing | ||||
if (const char* const scale = getenv("DPF_SCALE_FACTOR")) | if (const char* const scale = getenv("DPF_SCALE_FACTOR")) | ||||
return std::max(1.0, std::atof(scale)); | return std::max(1.0, std::atof(scale)); | ||||
if (view != nullptr) | if (view != nullptr) | ||||
return puglGetDesktopScaleFactor(view); | |||||
return puglGetScaleFactorFromParent(view); | |||||
return 1.0; | return 1.0; | ||||
} | } | ||||
static PuglView* puglNewViewWithTransientParent(PuglWorld* const world, PuglView* const transientParentView) | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(world != nullptr, nullptr); | |||||
if (PuglView* const view = puglNewView(world)) | |||||
{ | |||||
puglSetTransientParent(view, puglGetNativeWindow(transientParentView)); | |||||
return view; | |||||
} | |||||
return nullptr; | |||||
} | |||||
static PuglView* puglNewViewWithParentWindow(PuglWorld* const world, const uintptr_t parentWindowHandle) | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(world != nullptr, nullptr); | |||||
if (PuglView* const view = puglNewView(world)) | |||||
{ | |||||
puglSetParentWindow(view, parentWindowHandle); | |||||
return view; | |||||
} | |||||
return nullptr; | |||||
} | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
Window::PrivateData::PrivateData(Application& a, Window* const s) | Window::PrivateData::PrivateData(Application& a, Window* const s) | ||||
: app(a), | : app(a), | ||||
appData(a.pData), | appData(a.pData), | ||||
self(s), | self(s), | ||||
view(puglNewView(appData->world)), | |||||
transientParentView(nullptr), | |||||
view(appData->world != nullptr ? puglNewView(appData->world) : nullptr), | |||||
topLevelWidgets(), | topLevelWidgets(), | ||||
isClosed(true), | isClosed(true), | ||||
isVisible(false), | isVisible(false), | ||||
isEmbed(false), | isEmbed(false), | ||||
usesSizeRequest(false), | usesSizeRequest(false), | ||||
scaleFactor(getDesktopScaleFactor(view)), | |||||
scaleFactor(getScaleFactorFromParent(view)), | |||||
autoScaling(false), | autoScaling(false), | ||||
autoScaleFactor(1.0), | autoScaleFactor(1.0), | ||||
minWidth(0), | minWidth(0), | ||||
minHeight(0), | minHeight(0), | ||||
keepAspectRatio(false), | keepAspectRatio(false), | ||||
ignoreIdleCallbacks(false), | ignoreIdleCallbacks(false), | ||||
ignoreEvents(false), | |||||
filenameToRenderInto(nullptr), | filenameToRenderInto(nullptr), | ||||
#ifndef DGL_FILE_BROWSER_DISABLED | #ifndef DGL_FILE_BROWSER_DISABLED | ||||
fileBrowserHandle(nullptr), | fileBrowserHandle(nullptr), | ||||
@@ -98,8 +122,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, PrivateData* c | |||||
: app(a), | : app(a), | ||||
appData(a.pData), | appData(a.pData), | ||||
self(s), | self(s), | ||||
view(puglNewView(appData->world)), | |||||
transientParentView(ppData->view), | |||||
view(puglNewViewWithTransientParent(appData->world, ppData->view)), | |||||
topLevelWidgets(), | topLevelWidgets(), | ||||
isClosed(true), | isClosed(true), | ||||
isVisible(false), | isVisible(false), | ||||
@@ -112,15 +135,12 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, PrivateData* c | |||||
minHeight(0), | minHeight(0), | ||||
keepAspectRatio(false), | keepAspectRatio(false), | ||||
ignoreIdleCallbacks(false), | ignoreIdleCallbacks(false), | ||||
ignoreEvents(false), | |||||
filenameToRenderInto(nullptr), | filenameToRenderInto(nullptr), | ||||
#ifndef DGL_FILE_BROWSER_DISABLED | #ifndef DGL_FILE_BROWSER_DISABLED | ||||
fileBrowserHandle(nullptr), | fileBrowserHandle(nullptr), | ||||
#endif | #endif | ||||
modal(ppData) | modal(ppData) | ||||
{ | { | ||||
puglSetTransientFor(view, puglGetNativeWindow(transientParentView)); | |||||
initPre(DEFAULT_WIDTH, DEFAULT_HEIGHT, false); | initPre(DEFAULT_WIDTH, DEFAULT_HEIGHT, false); | ||||
} | } | ||||
@@ -130,30 +150,25 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, | |||||
: app(a), | : app(a), | ||||
appData(a.pData), | appData(a.pData), | ||||
self(s), | self(s), | ||||
view(puglNewView(appData->world)), | |||||
transientParentView(nullptr), | |||||
view(puglNewViewWithParentWindow(appData->world, parentWindowHandle)), | |||||
topLevelWidgets(), | topLevelWidgets(), | ||||
isClosed(parentWindowHandle == 0), | isClosed(parentWindowHandle == 0), | ||||
isVisible(parentWindowHandle != 0), | isVisible(parentWindowHandle != 0), | ||||
isEmbed(parentWindowHandle != 0), | isEmbed(parentWindowHandle != 0), | ||||
usesSizeRequest(false), | usesSizeRequest(false), | ||||
scaleFactor(scale != 0.0 ? scale : getDesktopScaleFactor(view)), | |||||
scaleFactor(scale != 0.0 ? scale : getScaleFactorFromParent(view)), | |||||
autoScaling(false), | autoScaling(false), | ||||
autoScaleFactor(1.0), | autoScaleFactor(1.0), | ||||
minWidth(0), | minWidth(0), | ||||
minHeight(0), | minHeight(0), | ||||
keepAspectRatio(false), | keepAspectRatio(false), | ||||
ignoreIdleCallbacks(false), | ignoreIdleCallbacks(false), | ||||
ignoreEvents(false), | |||||
filenameToRenderInto(nullptr), | filenameToRenderInto(nullptr), | ||||
#ifndef DGL_FILE_BROWSER_DISABLED | #ifndef DGL_FILE_BROWSER_DISABLED | ||||
fileBrowserHandle(nullptr), | fileBrowserHandle(nullptr), | ||||
#endif | #endif | ||||
modal() | modal() | ||||
{ | { | ||||
if (isEmbed) | |||||
puglSetParentWindow(view, parentWindowHandle); | |||||
initPre(DEFAULT_WIDTH, DEFAULT_HEIGHT, resizable); | initPre(DEFAULT_WIDTH, DEFAULT_HEIGHT, resizable); | ||||
} | } | ||||
@@ -164,21 +179,19 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, | |||||
: app(a), | : app(a), | ||||
appData(a.pData), | appData(a.pData), | ||||
self(s), | self(s), | ||||
view(appData->world != nullptr ? puglNewView(appData->world) : nullptr), | |||||
transientParentView(nullptr), | |||||
view(puglNewViewWithParentWindow(appData->world, parentWindowHandle)), | |||||
topLevelWidgets(), | topLevelWidgets(), | ||||
isClosed(parentWindowHandle == 0), | isClosed(parentWindowHandle == 0), | ||||
isVisible(parentWindowHandle != 0 && view != nullptr), | isVisible(parentWindowHandle != 0 && view != nullptr), | ||||
isEmbed(parentWindowHandle != 0), | isEmbed(parentWindowHandle != 0), | ||||
usesSizeRequest(isVST3), | usesSizeRequest(isVST3), | ||||
scaleFactor(scale != 0.0 ? scale : getDesktopScaleFactor(view)), | |||||
scaleFactor(scale != 0.0 ? scale : getScaleFactorFromParent(view)), | |||||
autoScaling(false), | autoScaling(false), | ||||
autoScaleFactor(1.0), | autoScaleFactor(1.0), | ||||
minWidth(0), | minWidth(0), | ||||
minHeight(0), | minHeight(0), | ||||
keepAspectRatio(false), | keepAspectRatio(false), | ||||
ignoreIdleCallbacks(false), | ignoreIdleCallbacks(false), | ||||
ignoreEvents(false), | |||||
filenameToRenderInto(nullptr), | filenameToRenderInto(nullptr), | ||||
#ifndef DGL_FILE_BROWSER_DISABLED | #ifndef DGL_FILE_BROWSER_DISABLED | ||||
fileBrowserHandle(nullptr), | fileBrowserHandle(nullptr), | ||||
@@ -230,11 +243,11 @@ void Window::PrivateData::initPre(const uint width, const uint height, const boo | |||||
} | } | ||||
puglSetMatchingBackendForCurrentBuild(view); | puglSetMatchingBackendForCurrentBuild(view); | ||||
puglSetHandle(view, this); | |||||
puglClearMinSize(view); | |||||
puglSetWindowSize(view, width, height); | |||||
// FIXME? | |||||
// puglClearMinSize(view); | |||||
puglSetHandle(view, this); | |||||
puglSetViewHint(view, PUGL_RESIZABLE, resizable ? PUGL_TRUE : PUGL_FALSE); | puglSetViewHint(view, PUGL_RESIZABLE, resizable ? PUGL_TRUE : PUGL_FALSE); | ||||
puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, PUGL_FALSE); | puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, PUGL_FALSE); | ||||
#if DGL_USE_RGBA | #if DGL_USE_RGBA | ||||
@@ -249,6 +262,9 @@ void Window::PrivateData::initPre(const uint width, const uint height, const boo | |||||
#endif | #endif | ||||
// PUGL_SAMPLES ?? | // PUGL_SAMPLES ?? | ||||
puglSetEventFunc(view, puglEventCallback); | puglSetEventFunc(view, puglEventCallback); | ||||
// setting default size triggers system-level calls, do it last | |||||
puglSetSizeHint(view, PUGL_DEFAULT_SIZE, width, height); | |||||
} | } | ||||
bool Window::PrivateData::initPost() | bool Window::PrivateData::initPost() | ||||
@@ -314,8 +330,8 @@ void Window::PrivateData::show() | |||||
appData->oneWindowShown(); | appData->oneWindowShown(); | ||||
// FIXME | // FIXME | ||||
PuglRect rect = puglGetFrame(view); | |||||
puglSetWindowSize(view, static_cast<uint>(rect.width), static_cast<uint>(rect.height)); | |||||
// PuglRect rect = puglGetFrame(view); | |||||
// puglSetWindowSize(view, static_cast<uint>(rect.width), static_cast<uint>(rect.height)); | |||||
#if defined(DISTRHO_OS_WINDOWS) | #if defined(DISTRHO_OS_WINDOWS) | ||||
puglWin32ShowCentered(view); | puglWin32ShowCentered(view); | ||||
@@ -378,11 +394,7 @@ void Window::PrivateData::focus() | |||||
if (! isEmbed) | if (! isEmbed) | ||||
puglRaiseWindow(view); | puglRaiseWindow(view); | ||||
#if defined(HAVE_X11) && !defined(DISTRHO_OS_MAC) && !defined(DISTRHO_OS_WINDOWS) | |||||
puglX11GrabFocus(view); | |||||
#else | |||||
puglGrabFocus(view); | puglGrabFocus(view); | ||||
#endif | |||||
} | } | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -393,10 +405,7 @@ void Window::PrivateData::setResizable(const bool resizable) | |||||
DGL_DBG("Window setResizable called\n"); | DGL_DBG("Window setResizable called\n"); | ||||
puglSetViewHint(view, PUGL_RESIZABLE, resizable ? PUGL_TRUE : PUGL_FALSE); | |||||
#ifdef DISTRHO_OS_WINDOWS | |||||
puglWin32SetWindowResizable(view, resizable); | |||||
#endif | |||||
puglSetResizable(view, resizable); | |||||
} | } | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -795,8 +804,6 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||||
///< View must be drawn, a #PuglEventExpose | ///< View must be drawn, a #PuglEventExpose | ||||
case PUGL_EXPOSE: | case PUGL_EXPOSE: | ||||
if (pData->ignoreEvents) | |||||
break; | |||||
// unused x, y, width, height (double) | // unused x, y, width, height (double) | ||||
pData->onPuglExpose(); | pData->onPuglExpose(); | ||||
break; | break; | ||||
@@ -810,8 +817,6 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||||
case PUGL_FOCUS_IN: | case PUGL_FOCUS_IN: | ||||
///< Keyboard focus left view, a #PuglEventFocus | ///< Keyboard focus left view, a #PuglEventFocus | ||||
case PUGL_FOCUS_OUT: | case PUGL_FOCUS_OUT: | ||||
if (pData->ignoreEvents) | |||||
break; | |||||
pData->onPuglFocus(event->type == PUGL_FOCUS_IN, | pData->onPuglFocus(event->type == PUGL_FOCUS_IN, | ||||
static_cast<CrossingMode>(event->focus.mode)); | static_cast<CrossingMode>(event->focus.mode)); | ||||
break; | break; | ||||
@@ -821,8 +826,6 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||||
///< Key released, a #PuglEventKey | ///< Key released, a #PuglEventKey | ||||
case PUGL_KEY_RELEASE: | case PUGL_KEY_RELEASE: | ||||
{ | { | ||||
if (pData->ignoreEvents) | |||||
break; | |||||
// unused x, y, xRoot, yRoot (double) | // unused x, y, xRoot, yRoot (double) | ||||
Widget::KeyboardEvent ev; | Widget::KeyboardEvent ev; | ||||
ev.mod = event->key.state; | ev.mod = event->key.state; | ||||
@@ -846,8 +849,6 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||||
///< Character entered, a #PuglEventText | ///< Character entered, a #PuglEventText | ||||
case PUGL_TEXT: | case PUGL_TEXT: | ||||
{ | { | ||||
if (pData->ignoreEvents) | |||||
break; | |||||
// unused x, y, xRoot, yRoot (double) | // unused x, y, xRoot, yRoot (double) | ||||
Widget::CharacterInputEvent ev; | Widget::CharacterInputEvent ev; | ||||
ev.mod = event->text.state; | ev.mod = event->text.state; | ||||
@@ -872,13 +873,11 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||||
///< Mouse button released, a #PuglEventButton | ///< Mouse button released, a #PuglEventButton | ||||
case PUGL_BUTTON_RELEASE: | case PUGL_BUTTON_RELEASE: | ||||
{ | { | ||||
if (pData->ignoreEvents) | |||||
break; | |||||
Widget::MouseEvent ev; | Widget::MouseEvent ev; | ||||
ev.mod = event->button.state; | ev.mod = event->button.state; | ||||
ev.flags = event->button.flags; | ev.flags = event->button.flags; | ||||
ev.time = static_cast<uint>(event->button.time * 1000.0 + 0.5); | ev.time = static_cast<uint>(event->button.time * 1000.0 + 0.5); | ||||
ev.button = event->button.button; | |||||
ev.button = event->button.button + 1; | |||||
ev.press = event->type == PUGL_BUTTON_PRESS; | ev.press = event->type == PUGL_BUTTON_PRESS; | ||||
ev.pos = Point<double>(event->button.x, event->button.y); | ev.pos = Point<double>(event->button.x, event->button.y); | ||||
ev.absolutePos = ev.pos; | ev.absolutePos = ev.pos; | ||||
@@ -889,8 +888,6 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||||
///< Pointer moved, a #PuglEventMotion | ///< Pointer moved, a #PuglEventMotion | ||||
case PUGL_MOTION: | case PUGL_MOTION: | ||||
{ | { | ||||
if (pData->ignoreEvents) | |||||
break; | |||||
Widget::MotionEvent ev; | Widget::MotionEvent ev; | ||||
ev.mod = event->motion.state; | ev.mod = event->motion.state; | ||||
ev.flags = event->motion.flags; | ev.flags = event->motion.flags; | ||||
@@ -904,8 +901,6 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||||
///< Scrolled, a #PuglEventScroll | ///< Scrolled, a #PuglEventScroll | ||||
case PUGL_SCROLL: | case PUGL_SCROLL: | ||||
{ | { | ||||
if (pData->ignoreEvents) | |||||
break; | |||||
Widget::ScrollEvent ev; | Widget::ScrollEvent ev; | ||||
ev.mod = event->scroll.state; | ev.mod = event->scroll.state; | ||||
ev.flags = event->scroll.flags; | ev.flags = event->scroll.flags; | ||||
@@ -924,8 +919,6 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||||
///< Timer triggered, a #PuglEventTimer | ///< Timer triggered, a #PuglEventTimer | ||||
case PUGL_TIMER: | case PUGL_TIMER: | ||||
if (pData->ignoreEvents) | |||||
break; | |||||
if (IdleCallback* const idleCallback = reinterpret_cast<IdleCallback*>(event->timer.id)) | if (IdleCallback* const idleCallback = reinterpret_cast<IdleCallback*>(event->timer.id)) | ||||
idleCallback->idleCallback(); | idleCallback->idleCallback(); | ||||
break; | break; | ||||
@@ -937,6 +930,14 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||||
///< Recursive loop left, a #PuglEventLoopLeave | ///< Recursive loop left, a #PuglEventLoopLeave | ||||
case PUGL_LOOP_LEAVE: | case PUGL_LOOP_LEAVE: | ||||
break; | break; | ||||
///< Data offered from clipboard, a #PuglDataOfferEvent | |||||
case PUGL_DATA_OFFER: | |||||
break; | |||||
///< Data available from clipboard, a #PuglDataEvent | |||||
case PUGL_DATA: | |||||
break; | |||||
} | } | ||||
return PUGL_SUCCESS; | return PUGL_SUCCESS; | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * DISTRHO Plugin Framework (DPF) | ||||
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com> | |||||
* Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com> | |||||
* | * | ||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | * Permission to use, copy, modify, and/or distribute this software for any purpose with | ||||
* or without fee is hereby granted, provided that the above copyright notice and this | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -45,7 +45,7 @@ struct Window::PrivateData : IdleCallback { | |||||
PuglView* view; | PuglView* view; | ||||
/** Pugl view instance of the transient parent window. */ | /** Pugl view instance of the transient parent window. */ | ||||
PuglView* const transientParentView; | |||||
// PuglView* const transientParentView; | |||||
/** Reserved space for graphics context. */ | /** Reserved space for graphics context. */ | ||||
mutable uint8_t graphicsContext[sizeof(void*)]; | mutable uint8_t graphicsContext[sizeof(void*)]; | ||||
@@ -80,9 +80,6 @@ struct Window::PrivateData : IdleCallback { | |||||
/** Whether to ignore idle callback requests, useful for temporary windows. */ | /** Whether to ignore idle callback requests, useful for temporary windows. */ | ||||
bool ignoreIdleCallbacks; | bool ignoreIdleCallbacks; | ||||
/** Whether to ignore pugl events (except create and destroy), used for puglGetClipboard. */ | |||||
bool ignoreEvents; | |||||
/** Render to a picture file when non-null, automatically free+unset after saving. */ | /** Render to a picture file when non-null, automatically free+unset after saving. */ | ||||
char* filenameToRenderInto; | char* filenameToRenderInto; | ||||
@@ -1 +1 @@ | |||||
Subproject commit b1d9703ecbdb0a033fe0b9acdf58b90f7d81a8e5 | |||||
Subproject commit 9691a6810283ffd5a99b1cc974fc638e80f94979 |
@@ -16,10 +16,24 @@ | |||||
#include "pugl.hpp" | #include "pugl.hpp" | ||||
// -------------------------------------------------------------------------------------------------------------------- | |||||
// include base headers | |||||
#ifdef DGL_CAIRO | |||||
# include <cairo/cairo.h> | |||||
#endif | |||||
#ifdef DGL_OPENGL | |||||
# include "../OpenGL-include.hpp" | |||||
#endif | |||||
#ifdef DGL_VULKAN | |||||
# include <vulkan/vulkan_core.h> | |||||
#endif | |||||
/* we will include all header files used in pugl in their C++ friendly form, then pugl stuff in custom namespace */ | /* we will include all header files used in pugl in their C++ friendly form, then pugl stuff in custom namespace */ | ||||
#include <cassert> | #include <cassert> | ||||
#include <cmath> | #include <cmath> | ||||
#include <cstdlib> | #include <cstdlib> | ||||
#include <cstdio> | |||||
#include <cstring> | #include <cstring> | ||||
#include <ctime> | #include <ctime> | ||||
@@ -57,9 +71,10 @@ | |||||
# endif | # endif | ||||
#else | #else | ||||
# include <dlfcn.h> | # include <dlfcn.h> | ||||
# include <limits.h> | |||||
# include <unistd.h> | # include <unistd.h> | ||||
# include <sys/select.h> | # include <sys/select.h> | ||||
# include <sys/time.h> | |||||
// # include <sys/time.h> | |||||
# include <X11/X.h> | # include <X11/X.h> | ||||
# include <X11/Xatom.h> | # include <X11/Xatom.h> | ||||
# include <X11/Xlib.h> | # include <X11/Xlib.h> | ||||
@@ -68,7 +83,7 @@ | |||||
# include <X11/keysym.h> | # include <X11/keysym.h> | ||||
# ifdef HAVE_XCURSOR | # ifdef HAVE_XCURSOR | ||||
# include <X11/Xcursor/Xcursor.h> | # include <X11/Xcursor/Xcursor.h> | ||||
# include <X11/cursorfont.h> | |||||
// # include <X11/cursorfont.h> | |||||
# endif | # endif | ||||
# ifdef HAVE_XRANDR | # ifdef HAVE_XRANDR | ||||
# include <X11/extensions/Xrandr.h> | # include <X11/extensions/Xrandr.h> | ||||
@@ -78,15 +93,12 @@ | |||||
# include <X11/extensions/syncconst.h> | # include <X11/extensions/syncconst.h> | ||||
# endif | # endif | ||||
# ifdef DGL_CAIRO | # ifdef DGL_CAIRO | ||||
# include <cairo.h> | |||||
# include <cairo-xlib.h> | # include <cairo-xlib.h> | ||||
# endif | # endif | ||||
# ifdef DGL_OPENGL | # ifdef DGL_OPENGL | ||||
# include <GL/gl.h> | |||||
# include <GL/glx.h> | # include <GL/glx.h> | ||||
# endif | # endif | ||||
# ifdef DGL_VULKAN | # ifdef DGL_VULKAN | ||||
# include <vulkan/vulkan_core.h> | |||||
# include <vulkan/vulkan_xlib.h> | # include <vulkan/vulkan_xlib.h> | ||||
# endif | # endif | ||||
#endif | #endif | ||||
@@ -101,6 +113,8 @@ | |||||
#ifndef DISTRHO_OS_MAC | #ifndef DISTRHO_OS_MAC | ||||
START_NAMESPACE_DGL | START_NAMESPACE_DGL | ||||
#else | |||||
USE_NAMESPACE_DGL | |||||
#endif | #endif | ||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
@@ -113,9 +127,6 @@ START_NAMESPACE_DGL | |||||
# define PuglWrapperView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWrapperView) | # define PuglWrapperView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWrapperView) | ||||
# define PuglWindow DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWindow) | # define PuglWindow DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWindow) | ||||
# endif | # endif | ||||
# ifndef __MAC_10_9 | |||||
# define NSModalResponseOK NSOKButton | |||||
# endif | |||||
# pragma clang diagnostic push | # pragma clang diagnostic push | ||||
# pragma clang diagnostic ignored "-Wdeprecated-declarations" | # pragma clang diagnostic ignored "-Wdeprecated-declarations" | ||||
# import "pugl-upstream/src/mac.m" | # import "pugl-upstream/src/mac.m" | ||||
@@ -159,7 +170,7 @@ START_NAMESPACE_DGL | |||||
#include "pugl-upstream/src/implementation.c" | #include "pugl-upstream/src/implementation.c" | ||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
// expose backend enter | |||||
// DGL specific, expose backend enter | |||||
bool puglBackendEnter(PuglView* const view) | bool puglBackendEnter(PuglView* const view) | ||||
{ | { | ||||
@@ -167,109 +178,39 @@ bool puglBackendEnter(PuglView* const view) | |||||
} | } | ||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
// expose backend leave | |||||
void puglBackendLeave(PuglView* const view) | |||||
{ | |||||
view->backend->leave(view, nullptr); | |||||
} | |||||
// -------------------------------------------------------------------------------------------------------------------- | |||||
// clear minimum size to 0 | |||||
void puglClearMinSize(PuglView* const view) | |||||
{ | |||||
view->minWidth = 0; | |||||
view->minHeight = 0; | |||||
} | |||||
// -------------------------------------------------------------------------------------------------------------------- | |||||
// missing in pugl, directly returns transient parent | |||||
// DGL specific, expose backend leave | |||||
PuglNativeView puglGetTransientParent(const PuglView* const view) | |||||
bool puglBackendLeave(PuglView* const view) | |||||
{ | { | ||||
return view->transientParent; | |||||
return view->backend->leave(view, nullptr) == PUGL_SUCCESS; | |||||
} | } | ||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
// missing in pugl, directly returns title char* pointer | |||||
// DGL specific, assigns backend that matches current DGL build | |||||
const char* puglGetWindowTitle(const PuglView* const view) | |||||
void puglSetMatchingBackendForCurrentBuild(PuglView* const view) | |||||
{ | { | ||||
return view->title; | |||||
#ifdef DGL_CAIRO | |||||
puglSetBackend(view, puglCairoBackend()); | |||||
#endif | |||||
#ifdef DGL_OPENGL | |||||
puglSetBackend(view, puglGlBackend()); | |||||
#endif | |||||
#ifdef DGL_VULKAN | |||||
puglSetBackend(view, puglVulkanBackend()); | |||||
#endif | |||||
if (view->backend == nullptr) | |||||
puglSetBackend(view, puglStubBackend()); | |||||
} | } | ||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
// get global scale factor | |||||
double puglGetDesktopScaleFactor(const PuglView* const view) | |||||
{ | |||||
#if defined(DISTRHO_OS_MAC) | |||||
if (NSWindow* const window = view->impl->window ? view->impl->window | |||||
: [view->impl->wrapperView window]) | |||||
return [window screen].backingScaleFactor; | |||||
return [NSScreen mainScreen].backingScaleFactor; | |||||
#elif defined(DISTRHO_OS_WINDOWS) | |||||
if (const HMODULE Shcore = LoadLibraryA("Shcore.dll")) | |||||
{ | |||||
typedef HRESULT(WINAPI* PFN_GetProcessDpiAwareness)(HANDLE, DWORD*); | |||||
typedef HRESULT(WINAPI* PFN_GetScaleFactorForMonitor)(HMONITOR, DWORD*); | |||||
# if defined(__GNUC__) && (__GNUC__ >= 9) | |||||
# pragma GCC diagnostic push | |||||
# pragma GCC diagnostic ignored "-Wcast-function-type" | |||||
# endif | |||||
const PFN_GetProcessDpiAwareness GetProcessDpiAwareness | |||||
= (PFN_GetProcessDpiAwareness)GetProcAddress(Shcore, "GetProcessDpiAwareness"); | |||||
const PFN_GetScaleFactorForMonitor GetScaleFactorForMonitor | |||||
= (PFN_GetScaleFactorForMonitor)GetProcAddress(Shcore, "GetScaleFactorForMonitor"); | |||||
# if defined(__GNUC__) && (__GNUC__ >= 9) | |||||
# pragma GCC diagnostic pop | |||||
# endif | |||||
DWORD dpiAware = 0; | |||||
if (GetProcessDpiAwareness && GetScaleFactorForMonitor | |||||
&& GetProcessDpiAwareness(NULL, &dpiAware) == 0 && dpiAware != 0) | |||||
{ | |||||
const HMONITOR hMon = MonitorFromWindow(view->impl->hwnd, MONITOR_DEFAULTTOPRIMARY); | |||||
DWORD scaleFactor = 0; | |||||
if (GetScaleFactorForMonitor(hMon, &scaleFactor) == 0 && scaleFactor != 0) | |||||
{ | |||||
FreeLibrary(Shcore); | |||||
return static_cast<double>(scaleFactor) / 100.0; | |||||
} | |||||
} | |||||
FreeLibrary(Shcore); | |||||
} | |||||
#elif defined(HAVE_X11) | |||||
XrmInitialize(); | |||||
if (char* const rms = XResourceManagerString(view->world->impl->display)) | |||||
{ | |||||
if (const XrmDatabase sdb = XrmGetStringDatabase(rms)) | |||||
{ | |||||
char* type = nullptr; | |||||
XrmValue ret; | |||||
if (XrmGetResource(sdb, "Xft.dpi", "String", &type, &ret) | |||||
&& ret.addr != nullptr | |||||
&& type != nullptr | |||||
&& std::strncmp("String", type, 6) == 0) | |||||
{ | |||||
if (const double dpi = std::atof(ret.addr)) | |||||
return dpi / 96; | |||||
} | |||||
} | |||||
} | |||||
#else | |||||
// unused | |||||
(void)view; | |||||
#endif | |||||
// clear minimum size to 0 | |||||
return 1.0; | |||||
} | |||||
// void puglClearMinSize(PuglView* const view) | |||||
// { | |||||
// view->sizeHints[PUGL_MIN_SIZE].width = 0; | |||||
// view->sizeHints[PUGL_MIN_SIZE].height = 0; | |||||
// } | |||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
// bring view window into the foreground, aka "raise" window | // bring view window into the foreground, aka "raise" window | ||||
@@ -284,48 +225,55 @@ void puglRaiseWindow(PuglView* const view) | |||||
SetForegroundWindow(view->impl->hwnd); | SetForegroundWindow(view->impl->hwnd); | ||||
SetActiveWindow(view->impl->hwnd); | SetActiveWindow(view->impl->hwnd); | ||||
#else | #else | ||||
XRaiseWindow(view->impl->display, view->impl->win); | |||||
XRaiseWindow(view->world->impl->display, view->impl->win); | |||||
#endif | #endif | ||||
} | } | ||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
// set backend that matches current build | |||||
// get scale factor from parent window if possible, fallback to puglGetScaleFactor | |||||
void puglSetMatchingBackendForCurrentBuild(PuglView* const view) | |||||
double puglGetScaleFactorFromParent(const PuglView* const view) | |||||
{ | { | ||||
#ifdef DGL_CAIRO | |||||
puglSetBackend(view, puglCairoBackend()); | |||||
#endif | |||||
#ifdef DGL_OPENGL | |||||
puglSetBackend(view, puglGlBackend()); | |||||
#endif | |||||
#ifdef DGL_VULKAN | |||||
puglSetBackend(view, puglVulkanBackend()); | |||||
const PuglNativeView parent = view->parent ? view->parent : view->transientParent ? view->transientParent : 0; | |||||
#if defined(DISTRHO_OS_MAC) | |||||
NSWindow* const window = parent != 0 ? [(NSView*)parent window] | |||||
: view->impl->window ? view->impl->window : [view->impl->wrapperView window]); | |||||
NSScreen* const screen = window != nullptr ? [window screen] : [NSScreen mainScreen]; | |||||
return [screen backingScaleFactor]; | |||||
#elif defined(DISTRHO_OS_WINDOWS) | |||||
const HWND hwnd = parent != 0 ? (HWND)parent : view->impl->hwnd; | |||||
return puglWinGetViewScaleFactor(hwnd); | |||||
#else | |||||
return puglGetScaleFactor(view); | |||||
// unused | |||||
(void)parent; | |||||
#endif | #endif | ||||
if (view->backend == nullptr) | |||||
puglSetBackend(view, puglStubBackend()); | |||||
} | } | ||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
// Combine puglSetMinSize and puglSetAspectRatio | |||||
// Combined puglSetSizeHint using PUGL_MIN_SIZE and PUGL_FIXED_ASPECT | |||||
PuglStatus puglSetGeometryConstraints(PuglView* const view, const uint width, const uint height, const bool aspect) | PuglStatus puglSetGeometryConstraints(PuglView* const view, const uint width, const uint height, const bool aspect) | ||||
{ | { | ||||
view->minWidth = (int)width; | |||||
view->minHeight = (int)height; | |||||
if (aspect) { | |||||
view->minAspectX = (int)width; | |||||
view->minAspectY = (int)height; | |||||
view->maxAspectX = (int)width; | |||||
view->maxAspectY = (int)height; | |||||
view->sizeHints[PUGL_MIN_SIZE].width = width; | |||||
view->sizeHints[PUGL_MIN_SIZE].height = height; | |||||
if (aspect) | |||||
{ | |||||
view->sizeHints[PUGL_FIXED_ASPECT].width = width; | |||||
view->sizeHints[PUGL_FIXED_ASPECT].height = height; | |||||
} | } | ||||
#if defined(DISTRHO_OS_MAC) | #if defined(DISTRHO_OS_MAC) | ||||
puglSetMinSize(view, width, height); | |||||
if (view->impl->window) | |||||
{ | |||||
PuglStatus status; | |||||
if ((status = updateSizeHint(view, PUGL_MIN_SIZE)) != PUGL_SUCCESS) | |||||
return status; | |||||
if (aspect) { | |||||
puglSetAspectRatio(view, width, height, width, height); | |||||
if (aspect && (status = updateSizeHint(view, PUGL_FIXED_ASPECT)) != PUGL_SUCCESS) | |||||
return status; | |||||
} | } | ||||
#elif defined(DISTRHO_OS_WINDOWS) | #elif defined(DISTRHO_OS_WINDOWS) | ||||
// nothing | // nothing | ||||
@@ -333,92 +281,90 @@ PuglStatus puglSetGeometryConstraints(PuglView* const view, const uint width, co | |||||
if (const PuglStatus status = updateSizeHints(view)) | if (const PuglStatus status = updateSizeHints(view)) | ||||
return status; | return status; | ||||
XFlush(view->impl->display); | |||||
XFlush(view->world->impl->display); | |||||
#endif | #endif | ||||
return PUGL_SUCCESS; | return PUGL_SUCCESS; | ||||
} | } | ||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
// set window offset without changing size | |||||
// set view as resizable (or not) during runtime | |||||
PuglStatus puglSetWindowOffset(PuglView* const view, const int x, const int y) | |||||
void puglSetResizable(PuglView* const view, const bool resizable) | |||||
{ | { | ||||
// TODO custom setFrame version | |||||
PuglRect rect = puglGetFrame(view); | |||||
rect.x = x; | |||||
rect.y = y; | |||||
return puglSetFrame(view, rect); | |||||
puglSetViewHint(view, PUGL_RESIZABLE, resizable ? PUGL_TRUE : PUGL_FALSE); | |||||
#if defined(DISTRHO_OS_MAC) | |||||
if (PuglWindow* const window = view->impl->window) | |||||
{ | |||||
const uint style = (NSClosableWindowMask | NSTitledWindowMask | NSMiniaturizableWindowMask) | |||||
| (resizable ? NSResizableWindowMask : 0x0); | |||||
[window setStyleMask:style]; | |||||
} | |||||
// FIXME use [view setAutoresizingMask:NSViewNotSizable] ? | |||||
#elif defined(DISTRHO_OS_WINDOWS) | |||||
if (const HWND hwnd = view->impl->hwnd) | |||||
{ | |||||
const uint winFlags = resizable ? GetWindowLong(hwnd, GWL_STYLE) | (WS_SIZEBOX | WS_MAXIMIZEBOX) | |||||
: GetWindowLong(hwnd, GWL_STYLE) & ~(WS_SIZEBOX | WS_MAXIMIZEBOX); | |||||
SetWindowLong(hwnd, GWL_STYLE, winFlags); | |||||
} | |||||
#else | |||||
updateSizeHints(view); | |||||
#endif | |||||
} | } | ||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
// set window size with default size and without changing frame x/y position | |||||
// set window size while also changing default | |||||
PuglStatus puglSetWindowSize(PuglView* const view, const uint width, const uint height) | |||||
PuglStatus puglSetSizeAndDefault(PuglView* view, uint width, uint height) | |||||
{ | { | ||||
view->defaultWidth = width; | |||||
view->defaultHeight = height; | |||||
view->frame.width = width; | |||||
view->frame.height = height; | |||||
if (width > INT16_MAX || height > INT16_MAX) | |||||
return PUGL_BAD_PARAMETER; | |||||
view->sizeHints[PUGL_DEFAULT_SIZE].width = view->frame.width = static_cast<PuglSpan>(width); | |||||
view->sizeHints[PUGL_DEFAULT_SIZE].height = view->frame.height = static_cast<PuglSpan>(height); | |||||
#if defined(DISTRHO_OS_MAC) | #if defined(DISTRHO_OS_MAC) | ||||
// replace setFrame with setFrameSize | |||||
// mostly matches upstream pugl, simplified | |||||
PuglInternals* const impl = view->impl; | PuglInternals* const impl = view->impl; | ||||
const PuglRect frame = view->frame; | const PuglRect frame = view->frame; | ||||
const NSRect framePx = rectToNsRect(frame); | const NSRect framePx = rectToNsRect(frame); | ||||
const NSRect framePt = nsRectToPoints(view, framePx); | const NSRect framePt = nsRectToPoints(view, framePx); | ||||
if (impl->window) | |||||
if (PuglWindow* const window = view->impl->window) | |||||
{ | { | ||||
// Resize window to fit new content rect | |||||
const NSRect screenPt = rectToScreen(viewScreen(view), framePt); | const NSRect screenPt = rectToScreen(viewScreen(view), framePt); | ||||
const NSRect winFrame = [impl->window frameRectForContentRect:screenPt]; | |||||
[impl->window setFrame:winFrame display:NO]; | |||||
const NSRect winFrame = [window frameRectForContentRect:screenPt]; | |||||
[window setFrame:winFrame display:NO]; | |||||
} | } | ||||
// Resize views | |||||
const NSSize sizePx = NSMakeSize(frame.width, frame.height); | const NSSize sizePx = NSMakeSize(frame.width, frame.height); | ||||
const NSSize sizePt = [impl->drawView convertSizeFromBacking:sizePx]; | const NSSize sizePt = [impl->drawView convertSizeFromBacking:sizePx]; | ||||
[impl->wrapperView setFrameSize:(impl->window ? sizePt : framePt.size)]; | |||||
[impl->wrapperView setFrameSize:sizePt]; | |||||
[impl->drawView setFrameSize:sizePt]; | [impl->drawView setFrameSize:sizePt]; | ||||
#elif defined(DISTRHO_OS_WINDOWS) | #elif defined(DISTRHO_OS_WINDOWS) | ||||
// matches upstream pugl, except we add SWP_NOMOVE flag | |||||
if (view->impl->hwnd) | |||||
// matches upstream pugl, except we re-enter context after resize | |||||
if (const HWND hwnd = view->impl->hwnd) | |||||
{ | { | ||||
const PuglRect frame = view->frame; | |||||
RECT rect = { (long)frame.x, | |||||
(long)frame.y, | |||||
(long)frame.x + (long)frame.width, | |||||
(long)frame.y + (long)frame.height }; | |||||
const RECT rect = adjustedWindowRect(view, view->frame.x, view->frame.y, | |||||
static_cast<long>(width), static_cast<long>(height)); | |||||
AdjustWindowRectEx(&rect, puglWinGetWindowFlags(view), FALSE, puglWinGetWindowExFlags(view)); | |||||
if (SetWindowPos(view->impl->hwnd, | |||||
HWND_TOP, | |||||
rect.left, | |||||
rect.top, | |||||
rect.right - rect.left, | |||||
rect.bottom - rect.top, | |||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER)) | |||||
{ | |||||
// make sure to return context back to ourselves | |||||
view->backend->enter(view, nullptr); | |||||
return PUGL_SUCCESS; | |||||
} | |||||
if (!SetWindowPos(hwnd, HWND_TOP, 0, 0, rect.right - rect.left, rect.bottom - rect.top, | |||||
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE)) | |||||
return PUGL_UNKNOWN_ERROR; | |||||
return PUGL_UNKNOWN_ERROR; | |||||
// make sure to return context back to ourselves | |||||
puglBackendEnter(view); | |||||
} | } | ||||
#else | #else | ||||
// matches upstream pugl, except we use XResizeWindow instead of XMoveResizeWindow | |||||
if (view->impl->win) | |||||
// matches upstream pugl, all in one | |||||
if (const Window window = view->impl->win) | |||||
{ | { | ||||
Display* const display = view->impl->display; | |||||
Display* const display = view->world->impl->display; | |||||
if (! XResizeWindow(display, view->impl->win, width, height)) | |||||
if (! XResizeWindow(display, window, width, height)) | |||||
return PUGL_UNKNOWN_ERROR; | return PUGL_UNKNOWN_ERROR; | ||||
if (const PuglStatus status = updateSizeHints(view)) | if (const PuglStatus status = updateSizeHints(view)) | ||||
@@ -456,6 +402,10 @@ void puglFallbackOnResize(PuglView* const view) | |||||
glViewport(0, 0, static_cast<GLsizei>(view->frame.width), static_cast<GLsizei>(view->frame.height)); | glViewport(0, 0, static_cast<GLsizei>(view->frame.width), static_cast<GLsizei>(view->frame.height)); | ||||
glMatrixMode(GL_MODELVIEW); | glMatrixMode(GL_MODELVIEW); | ||||
glLoadIdentity(); | glLoadIdentity(); | ||||
#else | |||||
return; | |||||
// unused | |||||
(void)view; | |||||
#endif | #endif | ||||
} | } | ||||
@@ -603,67 +553,33 @@ void puglWin32ShowCentered(PuglView* const view) | |||||
SetFocus(impl->hwnd); | SetFocus(impl->hwnd); | ||||
} | } | ||||
// -------------------------------------------------------------------------------------------------------------------- | |||||
// win32 specific, set or unset WS_SIZEBOX style flag | |||||
void puglWin32SetWindowResizable(PuglView* const view, const bool resizable) | |||||
{ | |||||
PuglInternals* impl = view->impl; | |||||
DISTRHO_SAFE_ASSERT_RETURN(impl->hwnd != nullptr,); | |||||
const int winFlags = resizable ? GetWindowLong(impl->hwnd, GWL_STYLE) | WS_SIZEBOX | |||||
: GetWindowLong(impl->hwnd, GWL_STYLE) & ~WS_SIZEBOX; | |||||
SetWindowLong(impl->hwnd, GWL_STYLE, winFlags); | |||||
} | |||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
#elif defined(HAVE_X11) | #elif defined(HAVE_X11) | ||||
// -------------------------------------------------------------------------------------------------------------------- | |||||
// X11 specific, safer way to grab focus | |||||
PuglStatus puglX11GrabFocus(const PuglView* const view) | |||||
{ | |||||
const PuglInternals* const impl = view->impl; | |||||
XWindowAttributes wa; | |||||
std::memset(&wa, 0, sizeof(wa)); | |||||
DISTRHO_SAFE_ASSERT_RETURN(XGetWindowAttributes(impl->display, impl->win, &wa), PUGL_UNKNOWN_ERROR); | |||||
if (wa.map_state == IsViewable) | |||||
{ | |||||
XRaiseWindow(impl->display, impl->win); | |||||
XSetInputFocus(impl->display, impl->win, RevertToPointerRoot, CurrentTime); | |||||
XSync(impl->display, False); | |||||
} | |||||
return PUGL_SUCCESS; | |||||
} | |||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
// X11 specific, set dialog window type and pid hints | // X11 specific, set dialog window type and pid hints | ||||
void puglX11SetWindowTypeAndPID(const PuglView* const view, const bool isStandalone) | void puglX11SetWindowTypeAndPID(const PuglView* const view, const bool isStandalone) | ||||
{ | { | ||||
const PuglInternals* const impl = view->impl; | |||||
const PuglInternals* const impl = view->impl; | |||||
Display* const display = view->world->impl->display; | |||||
const pid_t pid = getpid(); | const pid_t pid = getpid(); | ||||
const Atom _nwp = XInternAtom(impl->display, "_NET_WM_PID", False); | |||||
XChangeProperty(impl->display, impl->win, _nwp, XA_CARDINAL, 32, PropModeReplace, (const uchar*)&pid, 1); | |||||
const Atom _nwp = XInternAtom(display, "_NET_WM_PID", False); | |||||
XChangeProperty(display, impl->win, _nwp, XA_CARDINAL, 32, PropModeReplace, (const uchar*)&pid, 1); | |||||
const Atom _wt = XInternAtom(impl->display, "_NET_WM_WINDOW_TYPE", False); | |||||
const Atom _wt = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False); | |||||
Atom _wts[2]; | Atom _wts[2]; | ||||
int numAtoms = 0; | int numAtoms = 0; | ||||
if (! isStandalone) | if (! isStandalone) | ||||
_wts[numAtoms++] = XInternAtom(impl->display, "_NET_WM_WINDOW_TYPE_DIALOG", False); | |||||
_wts[numAtoms++] = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False); | |||||
_wts[numAtoms++] = XInternAtom(impl->display, "_NET_WM_WINDOW_TYPE_NORMAL", False); | |||||
_wts[numAtoms++] = XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False); | |||||
XChangeProperty(impl->display, impl->win, _wt, XA_ATOM, 32, PropModeReplace, (const uchar*)&_wts, numAtoms); | |||||
XChangeProperty(display, impl->win, _wt, XA_ATOM, 32, PropModeReplace, (const uchar*)&_wts, numAtoms); | |||||
} | } | ||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
@@ -19,7 +19,7 @@ | |||||
#include "../Base.hpp" | #include "../Base.hpp" | ||||
/* we will include all header files used in pugl in their C++ friendly form, then pugl stuff in custom namespace */ | |||||
/* we will include all header files used in pugl.h in their C++ friendly form, then pugl stuff in custom namespace */ | |||||
#include <cstddef> | #include <cstddef> | ||||
#ifdef DISTRHO_PROPER_CPP11_SUPPORT | #ifdef DISTRHO_PROPER_CPP11_SUPPORT | ||||
# include <cstdbool> | # include <cstdbool> | ||||
@@ -29,75 +29,58 @@ | |||||
# include <stdint.h> | # include <stdint.h> | ||||
#endif | #endif | ||||
// hidden api | |||||
#define PUGL_API | #define PUGL_API | ||||
#define PUGL_DISABLE_DEPRECATED | #define PUGL_DISABLE_DEPRECATED | ||||
#define PUGL_NO_INCLUDE_GL_H | |||||
#define PUGL_NO_INCLUDE_GLU_H | #define PUGL_NO_INCLUDE_GLU_H | ||||
// do not set extern "C" | |||||
// #define __cplusplus_backup __cplusplus | |||||
// #undef __cplusplus | |||||
// give warning if defined as something else | |||||
// #define PUGL_BEGIN_DECLS | |||||
// #define PUGL_END_DECLS | |||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
#ifndef DISTRHO_OS_MAC | |||||
START_NAMESPACE_DGL | START_NAMESPACE_DGL | ||||
#else | |||||
USE_NAMESPACE_DGL | |||||
#endif | |||||
#include "pugl-upstream/include/pugl/pugl.h" | #include "pugl-upstream/include/pugl/pugl.h" | ||||
// -------------------------------------------------------------------------------------------------------------------- | |||||
PUGL_BEGIN_DECLS | |||||
// DGL specific, expose backend enter | |||||
bool puglBackendEnter(PuglView* view); | |||||
// expose backend enter | |||||
PUGL_API bool | |||||
puglBackendEnter(PuglView* view); | |||||
// DGL specific, expose backend leave | |||||
bool puglBackendLeave(PuglView* view); | |||||
// expose backend leave | |||||
PUGL_API void | |||||
puglBackendLeave(PuglView* view); | |||||
// DGL specific, assigns backend that matches current DGL build | |||||
void puglSetMatchingBackendForCurrentBuild(PuglView* view); | |||||
// clear minimum size to 0 | // clear minimum size to 0 | ||||
PUGL_API void | |||||
puglClearMinSize(PuglView* view); | |||||
// missing in pugl, directly returns transient parent | |||||
PUGL_API PuglNativeView | |||||
puglGetTransientParent(const PuglView* view); | |||||
// missing in pugl, directly returns title char* pointer | |||||
PUGL_API const char* | |||||
puglGetWindowTitle(const PuglView* view); | |||||
// get global scale factor | |||||
PUGL_API double | |||||
puglGetDesktopScaleFactor(const PuglView* view); | |||||
void puglClearMinSize(PuglView* view); | |||||
// bring view window into the foreground, aka "raise" window | // bring view window into the foreground, aka "raise" window | ||||
PUGL_API void | |||||
puglRaiseWindow(PuglView* view); | |||||
void puglRaiseWindow(PuglView* view); | |||||
// DGL specific, assigns backend that matches current DGL build | |||||
PUGL_API void | |||||
puglSetMatchingBackendForCurrentBuild(PuglView* view); | |||||
// get scale factor from parent window if possible, fallback to puglGetScaleFactor | |||||
double puglGetScaleFactorFromParent(const PuglView* view); | |||||
// Combine puglSetMinSize and puglSetAspectRatio | |||||
PUGL_API PuglStatus | |||||
puglSetGeometryConstraints(PuglView* view, uint width, uint height, bool aspect); | |||||
// combined puglSetSizeHint using PUGL_MIN_SIZE, PUGL_MIN_ASPECT and PUGL_MAX_ASPECT | |||||
PuglStatus puglSetGeometryConstraints(PuglView* view, uint width, uint height, bool aspect); | |||||
// set window offset without changing size | |||||
PUGL_API PuglStatus | |||||
puglSetWindowOffset(PuglView* view, int x, int y); | |||||
// set view as resizable (or not) during runtime | |||||
void puglSetResizable(PuglView* view, bool resizable); | |||||
// set window size with default size and without changing frame x/y position | |||||
PUGL_API PuglStatus | |||||
puglSetWindowSize(PuglView* view, uint width, uint height); | |||||
// set window size while also changing default | |||||
PuglStatus puglSetSizeAndDefault(PuglView* view, uint width, uint height); | |||||
// DGL specific, build-specific drawing prepare | // DGL specific, build-specific drawing prepare | ||||
PUGL_API void | |||||
puglOnDisplayPrepare(PuglView* view); | |||||
void puglOnDisplayPrepare(PuglView* view); | |||||
// DGL specific, build-specific fallback resize | // DGL specific, build-specific fallback resize | ||||
PUGL_API void | |||||
puglFallbackOnResize(PuglView* view); | |||||
void puglFallbackOnResize(PuglView* view); | |||||
#if defined(DISTRHO_OS_MAC) | #if defined(DISTRHO_OS_MAC) | ||||
@@ -127,28 +110,18 @@ puglWin32RestoreWindow(PuglView* view); | |||||
PUGL_API void | PUGL_API void | ||||
puglWin32ShowCentered(PuglView* view); | puglWin32ShowCentered(PuglView* view); | ||||
// win32 specific, set or unset WS_SIZEBOX style flag | |||||
PUGL_API void | |||||
puglWin32SetWindowResizable(PuglView* view, bool resizable); | |||||
#elif defined(HAVE_X11) | #elif defined(HAVE_X11) | ||||
// X11 specific, safer way to grab focus | |||||
PUGL_API PuglStatus | |||||
puglX11GrabFocus(const PuglView* view); | |||||
// X11 specific, set dialog window type and pid hints | // X11 specific, set dialog window type and pid hints | ||||
PUGL_API void | |||||
puglX11SetWindowTypeAndPID(const PuglView* view, bool isStandalone); | |||||
void puglX11SetWindowTypeAndPID(const PuglView* view, bool isStandalone); | |||||
#endif | #endif | ||||
PUGL_END_DECLS | |||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
#ifndef DISTRHO_OS_MAC | |||||
END_NAMESPACE_DGL | END_NAMESPACE_DGL | ||||
#endif | |||||
// #define __cplusplus __cplusplus_backup | |||||
// #undef __cplusplus_backup | |||||
#endif // DGL_PUGL_HPP_INCLUDED | #endif // DGL_PUGL_HPP_INCLUDED |
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * DISTRHO Plugin Framework (DPF) | ||||
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com> | |||||
* Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com> | |||||
* | * | ||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | * Permission to use, copy, modify, and/or distribute this software for any purpose with | ||||
* or without fee is hereby granted, provided that the above copyright notice and this | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -234,7 +234,7 @@ public: | |||||
#ifdef DISTRHO_PLUGIN_TARGET_VST3 | #ifdef DISTRHO_PLUGIN_TARGET_VST3 | ||||
void setSizeForVST3(const uint width, const uint height) | void setSizeForVST3(const uint width, const uint height) | ||||
{ | { | ||||
puglSetWindowSize(pData->view, width, height); | |||||
puglSetSizeAndDefault(pData->view, width, height); | |||||
} | } | ||||
#endif | #endif | ||||
@@ -0,0 +1,9 @@ | |||||
puglClearMinSize needed? | |||||
clipboard todo | |||||
puglSetWindowSize was used on first show, still needed? | |||||
pugl namespace details finalized | |||||
window starts centered for screen or parent finalized |