| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * 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 | |||
| * 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) | |||
| { | |||
| puglSetWindowOffset(pData->view, x, y); | |||
| puglSetPosition(pData->view, x, y); | |||
| } | |||
| void Window::setOffset(const Point<int>& offset) | |||
| @@ -289,7 +289,7 @@ void Window::setSize(uint width, uint height) | |||
| } | |||
| 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) | |||
| { | |||
| 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; | |||
| } | |||
| @@ -400,10 +397,10 @@ void Window::repaint(const Rectangle<uint>& rect) noexcept | |||
| return; | |||
| 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) | |||
| { | |||
| @@ -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 | |||
| if (const char* const scale = getenv("DPF_SCALE_FACTOR")) | |||
| return std::max(1.0, std::atof(scale)); | |||
| if (view != nullptr) | |||
| return puglGetDesktopScaleFactor(view); | |||
| return puglGetScaleFactorFromParent(view); | |||
| 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) | |||
| : app(a), | |||
| appData(a.pData), | |||
| self(s), | |||
| view(puglNewView(appData->world)), | |||
| transientParentView(nullptr), | |||
| view(appData->world != nullptr ? puglNewView(appData->world) : nullptr), | |||
| topLevelWidgets(), | |||
| isClosed(true), | |||
| isVisible(false), | |||
| isEmbed(false), | |||
| usesSizeRequest(false), | |||
| scaleFactor(getDesktopScaleFactor(view)), | |||
| scaleFactor(getScaleFactorFromParent(view)), | |||
| autoScaling(false), | |||
| autoScaleFactor(1.0), | |||
| minWidth(0), | |||
| minHeight(0), | |||
| keepAspectRatio(false), | |||
| ignoreIdleCallbacks(false), | |||
| ignoreEvents(false), | |||
| filenameToRenderInto(nullptr), | |||
| #ifndef DGL_FILE_BROWSER_DISABLED | |||
| fileBrowserHandle(nullptr), | |||
| @@ -98,8 +122,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, PrivateData* c | |||
| : app(a), | |||
| appData(a.pData), | |||
| self(s), | |||
| view(puglNewView(appData->world)), | |||
| transientParentView(ppData->view), | |||
| view(puglNewViewWithTransientParent(appData->world, ppData->view)), | |||
| topLevelWidgets(), | |||
| isClosed(true), | |||
| isVisible(false), | |||
| @@ -112,15 +135,12 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, PrivateData* c | |||
| minHeight(0), | |||
| keepAspectRatio(false), | |||
| ignoreIdleCallbacks(false), | |||
| ignoreEvents(false), | |||
| filenameToRenderInto(nullptr), | |||
| #ifndef DGL_FILE_BROWSER_DISABLED | |||
| fileBrowserHandle(nullptr), | |||
| #endif | |||
| modal(ppData) | |||
| { | |||
| puglSetTransientFor(view, puglGetNativeWindow(transientParentView)); | |||
| initPre(DEFAULT_WIDTH, DEFAULT_HEIGHT, false); | |||
| } | |||
| @@ -130,30 +150,25 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, | |||
| : app(a), | |||
| appData(a.pData), | |||
| self(s), | |||
| view(puglNewView(appData->world)), | |||
| transientParentView(nullptr), | |||
| view(puglNewViewWithParentWindow(appData->world, parentWindowHandle)), | |||
| topLevelWidgets(), | |||
| isClosed(parentWindowHandle == 0), | |||
| isVisible(parentWindowHandle != 0), | |||
| isEmbed(parentWindowHandle != 0), | |||
| usesSizeRequest(false), | |||
| scaleFactor(scale != 0.0 ? scale : getDesktopScaleFactor(view)), | |||
| scaleFactor(scale != 0.0 ? scale : getScaleFactorFromParent(view)), | |||
| autoScaling(false), | |||
| autoScaleFactor(1.0), | |||
| minWidth(0), | |||
| minHeight(0), | |||
| keepAspectRatio(false), | |||
| ignoreIdleCallbacks(false), | |||
| ignoreEvents(false), | |||
| filenameToRenderInto(nullptr), | |||
| #ifndef DGL_FILE_BROWSER_DISABLED | |||
| fileBrowserHandle(nullptr), | |||
| #endif | |||
| modal() | |||
| { | |||
| if (isEmbed) | |||
| puglSetParentWindow(view, parentWindowHandle); | |||
| initPre(DEFAULT_WIDTH, DEFAULT_HEIGHT, resizable); | |||
| } | |||
| @@ -164,21 +179,19 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, | |||
| : app(a), | |||
| appData(a.pData), | |||
| self(s), | |||
| view(appData->world != nullptr ? puglNewView(appData->world) : nullptr), | |||
| transientParentView(nullptr), | |||
| view(puglNewViewWithParentWindow(appData->world, parentWindowHandle)), | |||
| topLevelWidgets(), | |||
| isClosed(parentWindowHandle == 0), | |||
| isVisible(parentWindowHandle != 0 && view != nullptr), | |||
| isEmbed(parentWindowHandle != 0), | |||
| usesSizeRequest(isVST3), | |||
| scaleFactor(scale != 0.0 ? scale : getDesktopScaleFactor(view)), | |||
| scaleFactor(scale != 0.0 ? scale : getScaleFactorFromParent(view)), | |||
| autoScaling(false), | |||
| autoScaleFactor(1.0), | |||
| minWidth(0), | |||
| minHeight(0), | |||
| keepAspectRatio(false), | |||
| ignoreIdleCallbacks(false), | |||
| ignoreEvents(false), | |||
| filenameToRenderInto(nullptr), | |||
| #ifndef DGL_FILE_BROWSER_DISABLED | |||
| fileBrowserHandle(nullptr), | |||
| @@ -230,11 +243,11 @@ void Window::PrivateData::initPre(const uint width, const uint height, const boo | |||
| } | |||
| 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_IGNORE_KEY_REPEAT, PUGL_FALSE); | |||
| #if DGL_USE_RGBA | |||
| @@ -249,6 +262,9 @@ void Window::PrivateData::initPre(const uint width, const uint height, const boo | |||
| #endif | |||
| // PUGL_SAMPLES ?? | |||
| puglSetEventFunc(view, puglEventCallback); | |||
| // setting default size triggers system-level calls, do it last | |||
| puglSetSizeHint(view, PUGL_DEFAULT_SIZE, width, height); | |||
| } | |||
| bool Window::PrivateData::initPost() | |||
| @@ -314,8 +330,8 @@ void Window::PrivateData::show() | |||
| appData->oneWindowShown(); | |||
| // 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) | |||
| puglWin32ShowCentered(view); | |||
| @@ -378,11 +394,7 @@ void Window::PrivateData::focus() | |||
| if (! isEmbed) | |||
| puglRaiseWindow(view); | |||
| #if defined(HAVE_X11) && !defined(DISTRHO_OS_MAC) && !defined(DISTRHO_OS_WINDOWS) | |||
| puglX11GrabFocus(view); | |||
| #else | |||
| puglGrabFocus(view); | |||
| #endif | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -393,10 +405,7 @@ void Window::PrivateData::setResizable(const bool resizable) | |||
| 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 | |||
| case PUGL_EXPOSE: | |||
| if (pData->ignoreEvents) | |||
| break; | |||
| // unused x, y, width, height (double) | |||
| pData->onPuglExpose(); | |||
| break; | |||
| @@ -810,8 +817,6 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||
| case PUGL_FOCUS_IN: | |||
| ///< Keyboard focus left view, a #PuglEventFocus | |||
| case PUGL_FOCUS_OUT: | |||
| if (pData->ignoreEvents) | |||
| break; | |||
| pData->onPuglFocus(event->type == PUGL_FOCUS_IN, | |||
| static_cast<CrossingMode>(event->focus.mode)); | |||
| break; | |||
| @@ -821,8 +826,6 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||
| ///< Key released, a #PuglEventKey | |||
| case PUGL_KEY_RELEASE: | |||
| { | |||
| if (pData->ignoreEvents) | |||
| break; | |||
| // unused x, y, xRoot, yRoot (double) | |||
| Widget::KeyboardEvent ev; | |||
| ev.mod = event->key.state; | |||
| @@ -846,8 +849,6 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||
| ///< Character entered, a #PuglEventText | |||
| case PUGL_TEXT: | |||
| { | |||
| if (pData->ignoreEvents) | |||
| break; | |||
| // unused x, y, xRoot, yRoot (double) | |||
| Widget::CharacterInputEvent ev; | |||
| ev.mod = event->text.state; | |||
| @@ -872,13 +873,11 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||
| ///< Mouse button released, a #PuglEventButton | |||
| case PUGL_BUTTON_RELEASE: | |||
| { | |||
| if (pData->ignoreEvents) | |||
| break; | |||
| Widget::MouseEvent ev; | |||
| ev.mod = event->button.state; | |||
| ev.flags = event->button.flags; | |||
| 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.pos = Point<double>(event->button.x, event->button.y); | |||
| ev.absolutePos = ev.pos; | |||
| @@ -889,8 +888,6 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||
| ///< Pointer moved, a #PuglEventMotion | |||
| case PUGL_MOTION: | |||
| { | |||
| if (pData->ignoreEvents) | |||
| break; | |||
| Widget::MotionEvent ev; | |||
| ev.mod = event->motion.state; | |||
| ev.flags = event->motion.flags; | |||
| @@ -904,8 +901,6 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||
| ///< Scrolled, a #PuglEventScroll | |||
| case PUGL_SCROLL: | |||
| { | |||
| if (pData->ignoreEvents) | |||
| break; | |||
| Widget::ScrollEvent ev; | |||
| ev.mod = event->scroll.state; | |||
| ev.flags = event->scroll.flags; | |||
| @@ -924,8 +919,6 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||
| ///< Timer triggered, a #PuglEventTimer | |||
| case PUGL_TIMER: | |||
| if (pData->ignoreEvents) | |||
| break; | |||
| if (IdleCallback* const idleCallback = reinterpret_cast<IdleCallback*>(event->timer.id)) | |||
| idleCallback->idleCallback(); | |||
| break; | |||
| @@ -937,6 +930,14 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||
| ///< Recursive loop left, a #PuglEventLoopLeave | |||
| case PUGL_LOOP_LEAVE: | |||
| 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; | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * 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 | |||
| * or without fee is hereby granted, provided that the above copyright notice and this | |||
| @@ -45,7 +45,7 @@ struct Window::PrivateData : IdleCallback { | |||
| PuglView* view; | |||
| /** Pugl view instance of the transient parent window. */ | |||
| PuglView* const transientParentView; | |||
| // PuglView* const transientParentView; | |||
| /** Reserved space for graphics context. */ | |||
| mutable uint8_t graphicsContext[sizeof(void*)]; | |||
| @@ -80,9 +80,6 @@ struct Window::PrivateData : IdleCallback { | |||
| /** Whether to ignore idle callback requests, useful for temporary windows. */ | |||
| 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. */ | |||
| char* filenameToRenderInto; | |||
| @@ -1 +1 @@ | |||
| Subproject commit b1d9703ecbdb0a033fe0b9acdf58b90f7d81a8e5 | |||
| Subproject commit 9691a6810283ffd5a99b1cc974fc638e80f94979 | |||
| @@ -16,10 +16,24 @@ | |||
| #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 */ | |||
| #include <cassert> | |||
| #include <cmath> | |||
| #include <cstdlib> | |||
| #include <cstdio> | |||
| #include <cstring> | |||
| #include <ctime> | |||
| @@ -57,9 +71,10 @@ | |||
| # endif | |||
| #else | |||
| # include <dlfcn.h> | |||
| # include <limits.h> | |||
| # include <unistd.h> | |||
| # include <sys/select.h> | |||
| # include <sys/time.h> | |||
| // # include <sys/time.h> | |||
| # include <X11/X.h> | |||
| # include <X11/Xatom.h> | |||
| # include <X11/Xlib.h> | |||
| @@ -68,7 +83,7 @@ | |||
| # include <X11/keysym.h> | |||
| # ifdef HAVE_XCURSOR | |||
| # include <X11/Xcursor/Xcursor.h> | |||
| # include <X11/cursorfont.h> | |||
| // # include <X11/cursorfont.h> | |||
| # endif | |||
| # ifdef HAVE_XRANDR | |||
| # include <X11/extensions/Xrandr.h> | |||
| @@ -78,15 +93,12 @@ | |||
| # include <X11/extensions/syncconst.h> | |||
| # endif | |||
| # ifdef DGL_CAIRO | |||
| # include <cairo.h> | |||
| # include <cairo-xlib.h> | |||
| # endif | |||
| # ifdef DGL_OPENGL | |||
| # include <GL/gl.h> | |||
| # include <GL/glx.h> | |||
| # endif | |||
| # ifdef DGL_VULKAN | |||
| # include <vulkan/vulkan_core.h> | |||
| # include <vulkan/vulkan_xlib.h> | |||
| # endif | |||
| #endif | |||
| @@ -101,6 +113,8 @@ | |||
| #ifndef DISTRHO_OS_MAC | |||
| START_NAMESPACE_DGL | |||
| #else | |||
| USE_NAMESPACE_DGL | |||
| #endif | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| @@ -113,9 +127,6 @@ START_NAMESPACE_DGL | |||
| # define PuglWrapperView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWrapperView) | |||
| # define PuglWindow DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWindow) | |||
| # endif | |||
| # ifndef __MAC_10_9 | |||
| # define NSModalResponseOK NSOKButton | |||
| # endif | |||
| # pragma clang diagnostic push | |||
| # pragma clang diagnostic ignored "-Wdeprecated-declarations" | |||
| # import "pugl-upstream/src/mac.m" | |||
| @@ -159,7 +170,7 @@ START_NAMESPACE_DGL | |||
| #include "pugl-upstream/src/implementation.c" | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // expose backend enter | |||
| // DGL specific, expose backend enter | |||
| 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 | |||
| @@ -284,48 +225,55 @@ void puglRaiseWindow(PuglView* const view) | |||
| SetForegroundWindow(view->impl->hwnd); | |||
| SetActiveWindow(view->impl->hwnd); | |||
| #else | |||
| XRaiseWindow(view->impl->display, view->impl->win); | |||
| XRaiseWindow(view->world->impl->display, view->impl->win); | |||
| #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 | |||
| 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) | |||
| { | |||
| 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) | |||
| 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) | |||
| // nothing | |||
| @@ -333,92 +281,90 @@ PuglStatus puglSetGeometryConstraints(PuglView* const view, const uint width, co | |||
| if (const PuglStatus status = updateSizeHints(view)) | |||
| return status; | |||
| XFlush(view->impl->display); | |||
| XFlush(view->world->impl->display); | |||
| #endif | |||
| 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) | |||
| // replace setFrame with setFrameSize | |||
| // mostly matches upstream pugl, simplified | |||
| PuglInternals* const impl = view->impl; | |||
| const PuglRect frame = view->frame; | |||
| const NSRect framePx = rectToNsRect(frame); | |||
| 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 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 sizePt = [impl->drawView convertSizeFromBacking:sizePx]; | |||
| [impl->wrapperView setFrameSize:(impl->window ? sizePt : framePt.size)]; | |||
| [impl->wrapperView setFrameSize:sizePt]; | |||
| [impl->drawView setFrameSize:sizePt]; | |||
| #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 | |||
| // 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; | |||
| 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)); | |||
| glMatrixMode(GL_MODELVIEW); | |||
| glLoadIdentity(); | |||
| #else | |||
| return; | |||
| // unused | |||
| (void)view; | |||
| #endif | |||
| } | |||
| @@ -603,67 +553,33 @@ void puglWin32ShowCentered(PuglView* const view) | |||
| 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) | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // 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 | |||
| 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 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]; | |||
| int numAtoms = 0; | |||
| 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" | |||
| /* 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> | |||
| #ifdef DISTRHO_PROPER_CPP11_SUPPORT | |||
| # include <cstdbool> | |||
| @@ -29,75 +29,58 @@ | |||
| # include <stdint.h> | |||
| #endif | |||
| // hidden api | |||
| #define PUGL_API | |||
| #define PUGL_DISABLE_DEPRECATED | |||
| #define PUGL_NO_INCLUDE_GL_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 | |||
| #else | |||
| USE_NAMESPACE_DGL | |||
| #endif | |||
| #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 | |||
| 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 | |||
| 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 | |||
| PUGL_API void | |||
| puglOnDisplayPrepare(PuglView* view); | |||
| void puglOnDisplayPrepare(PuglView* view); | |||
| // DGL specific, build-specific fallback resize | |||
| PUGL_API void | |||
| puglFallbackOnResize(PuglView* view); | |||
| void puglFallbackOnResize(PuglView* view); | |||
| #if defined(DISTRHO_OS_MAC) | |||
| @@ -127,28 +110,18 @@ puglWin32RestoreWindow(PuglView* view); | |||
| PUGL_API void | |||
| puglWin32ShowCentered(PuglView* view); | |||
| // win32 specific, set or unset WS_SIZEBOX style flag | |||
| PUGL_API void | |||
| puglWin32SetWindowResizable(PuglView* view, bool resizable); | |||
| #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 | |||
| PUGL_API void | |||
| puglX11SetWindowTypeAndPID(const PuglView* view, bool isStandalone); | |||
| void puglX11SetWindowTypeAndPID(const PuglView* view, bool isStandalone); | |||
| #endif | |||
| PUGL_END_DECLS | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| #ifndef DISTRHO_OS_MAC | |||
| END_NAMESPACE_DGL | |||
| #endif | |||
| // #define __cplusplus __cplusplus_backup | |||
| // #undef __cplusplus_backup | |||
| #endif // DGL_PUGL_HPP_INCLUDED | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * 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 | |||
| * or without fee is hereby granted, provided that the above copyright notice and this | |||
| @@ -234,7 +234,7 @@ public: | |||
| #ifdef DISTRHO_PLUGIN_TARGET_VST3 | |||
| void setSizeForVST3(const uint width, const uint height) | |||
| { | |||
| puglSetWindowSize(pData->view, width, height); | |||
| puglSetSizeAndDefault(pData->view, width, height); | |||
| } | |||
| #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 | |||