@@ -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 |