| @@ -427,6 +427,7 @@ endif | |||
| else ifeq ($(WINDOWS),true) | |||
| DGL_SYSTEM_LIBS += -lcomdlg32 | |||
| DGL_SYSTEM_LIBS += -ldwmapi | |||
| DGL_SYSTEM_LIBS += -lgdi32 | |||
| # DGL_SYSTEM_LIBS += -lole32 | |||
| @@ -46,7 +46,7 @@ endif | |||
| DGL_BUILD_DIR = $(DPF_PATH)/build$(BUILD_DIR_SUFFIX) | |||
| BUILD_C_FLAGS += -I. | |||
| BUILD_CXX_FLAGS += -I. -I$(DPF_PATH)/distrho -I$(DPF_PATH)/dgl | |||
| BUILD_CXX_FLAGS += -I. -I$(DPF_PATH)/distrho -I$(DPF_PATH)/dgl -I$(DPF_PATH)/dgl/src/pugl-upstream/include | |||
| ifeq ($(HAVE_ALSA),true) | |||
| BASE_FLAGS += -DHAVE_ALSA | |||
| @@ -734,7 +734,7 @@ function(dpf__add_dgl_system_libs) | |||
| elseif(HAIKU) | |||
| target_link_libraries(dgl-system-libs INTERFACE "be") | |||
| elseif(WIN32) | |||
| target_link_libraries(dgl-system-libs INTERFACE "gdi32" "comdlg32") | |||
| target_link_libraries(dgl-system-libs INTERFACE "comdlg32" "dwmapi" "gdi32") | |||
| else() | |||
| find_package(PkgConfig) | |||
| pkg_check_modules(DBUS "dbus-1") | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2023 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 | |||
| @@ -62,55 +62,87 @@ enum Modifier { | |||
| */ | |||
| enum Key { | |||
| // Convenience symbols for ASCII control characters | |||
| kKeyBackspace = 0x08, | |||
| kKeyEscape = 0x1B, | |||
| kKeyDelete = 0x7F, | |||
| kKeyBackspace = 0x00000008U, ///< Backspace | |||
| kKeyEnter = 0x0000000DU, ///< Enter | |||
| kKeyEscape = 0x0000001BU, ///< Escape | |||
| kKeyDelete = 0x0000007FU, ///< Delete | |||
| kKeySpace = 0x00000020U, ///< Space | |||
| // Unicode Private Use Area | |||
| kKeyF1 = 0x0000E000U, ///< F1 | |||
| kKeyF2, ///< F2 | |||
| kKeyF3, ///< F3 | |||
| kKeyF4, ///< F4 | |||
| kKeyF5, ///< F5 | |||
| kKeyF6, ///< F6 | |||
| kKeyF7, ///< F7 | |||
| kKeyF8, ///< F8 | |||
| kKeyF9, ///< F9 | |||
| kKeyF10, ///< F10 | |||
| kKeyF11, ///< F11 | |||
| kKeyF12, ///< F12 | |||
| kKeyPageUp = 0xE031, ///< Page Up | |||
| kKeyPageDown, ///< Page Down | |||
| kKeyEnd, ///< End | |||
| kKeyHome, ///< Home | |||
| kKeyLeft, ///< Left | |||
| kKeyUp, ///< Up | |||
| kKeyRight, ///< Right | |||
| kKeyDown, ///< Down | |||
| kKeyPrintScreen = 0xE041U, ///< Print Screen | |||
| kKeyInsert, ///< Insert | |||
| kKeyPause, ///< Pause/Break | |||
| kKeyMenu, ///< Menu | |||
| kKeyNumLock, ///< Num Lock | |||
| kKeyScrollLock, ///< Scroll Lock | |||
| kKeyCapsLock, ///< Caps Lock | |||
| kKeyShiftL = 0xE051U, ///< Left Shift, | |||
| kKeyShiftR, ///< Right Shift | |||
| kKeyControlL, ///< Left Control | |||
| kKeyControlR, ///< Right Control | |||
| kKeyAltL, ///< Left Alt | |||
| kKeyAltR, ///< Right Alt / AltGr | |||
| kKeySuperL, ///< Left Super | |||
| kKeySuperR, ///< Right Super | |||
| kKeyPad0 = 0xE060U, ///< Keypad 0 | |||
| kKeyPad1, ///< Keypad 1 | |||
| kKeyPad2, ///< Keypad 2 | |||
| kKeyPad3, ///< Keypad 3 | |||
| kKeyPad4, ///< Keypad 4 | |||
| kKeyPad5, ///< Keypad 5 | |||
| kKeyPad6, ///< Keypad 6 | |||
| kKeyPad7, ///< Keypad 7 | |||
| kKeyPad8, ///< Keypad 8 | |||
| kKeyPad9, ///< Keypad 9 | |||
| kKeyPadEnter, ///< Keypad Enter | |||
| kKeyPadPageUp = 0xE071U, ///< Keypad Page Up | |||
| kKeyPadPageDown, ///< Keypad Page Down | |||
| kKeyPadEnd, ///< Keypad End | |||
| kKeyPadHome, ///< Keypad Home | |||
| kKeyPadLeft, ///< Keypad Left | |||
| kKeyPadUp, ///< Keypad Up | |||
| kKeyPadRight, ///< Keypad Right | |||
| kKeyPadDown, ///< Keypad Down | |||
| kKeyPadClear = 0xE09DU, ///< Keypad Clear/Begin | |||
| kKeyPadInsert, ///< Keypad Insert | |||
| kKeyPadDelete, ///< Keypad Delete | |||
| kKeyPadEqual, ///< Keypad Equal | |||
| kKeyPadMultiply = 0xE0AAU, ///< Keypad Multiply | |||
| kKeyPadAdd, ///< Keypad Add | |||
| kKeyPadSeparator, ///< Keypad Separator | |||
| kKeyPadSubtract, ///< Keypad Subtract | |||
| kKeyPadDecimal, ///< Keypad Decimal | |||
| kKeyPadDivide, ///< Keypad Divide | |||
| // Backwards compatibility with old DPF | |||
| kCharBackspace DISTRHO_DEPRECATED_BY("kKeyBackspace") = kKeyBackspace, | |||
| kCharEscape DISTRHO_DEPRECATED_BY("kKeyEscape") = kKeyEscape, | |||
| kCharDelete DISTRHO_DEPRECATED_BY("kKeyDelete") = kKeyDelete, | |||
| // Unicode Private Use Area | |||
| kKeyF1 = 0xE000, | |||
| kKeyF2, | |||
| kKeyF3, | |||
| kKeyF4, | |||
| kKeyF5, | |||
| kKeyF6, | |||
| kKeyF7, | |||
| kKeyF8, | |||
| kKeyF9, | |||
| kKeyF10, | |||
| kKeyF11, | |||
| kKeyF12, | |||
| kKeyLeft, | |||
| kKeyUp, | |||
| kKeyRight, | |||
| kKeyDown, | |||
| kKeyPageUp, | |||
| kKeyPageDown, | |||
| kKeyHome, | |||
| kKeyEnd, | |||
| kKeyInsert, | |||
| kKeyShift, | |||
| kKeyShiftL = kKeyShift, | |||
| kKeyShiftR, | |||
| kKeyControl, | |||
| kKeyControlL = kKeyControl, | |||
| kKeyControlR, | |||
| kKeyAlt, | |||
| kKeyAltL = kKeyAlt, | |||
| kKeyAltR, | |||
| kKeySuper, | |||
| kKeySuperL = kKeySuper, | |||
| kKeySuperR, | |||
| kKeyMenu, | |||
| kKeyCapsLock, | |||
| kKeyScrollLock, | |||
| kKeyNumLock, | |||
| kKeyPrintScreen, | |||
| kKeyPause | |||
| kKeyShift DISTRHO_DEPRECATED_BY("kKeyShiftL") = kKeyShiftL, | |||
| kKeyControl DISTRHO_DEPRECATED_BY("kKeyControlL") = kKeyControlL, | |||
| kKeyAlt DISTRHO_DEPRECATED_BY("kKeyAltL") = kKeyAltL, | |||
| kKeySuper DISTRHO_DEPRECATED_BY("kKeySuperL") = kKeySuperL, | |||
| }; | |||
| /** | |||
| @@ -159,15 +191,20 @@ enum MouseButton { | |||
| This is a portable subset of mouse cursors that exist on X11, MacOS, and Windows. | |||
| */ | |||
| enum MouseCursor { | |||
| kMouseCursorArrow, ///< Default pointing arrow | |||
| kMouseCursorCaret, ///< Caret (I-Beam) for text entry | |||
| kMouseCursorCrosshair, ///< Cross-hair | |||
| kMouseCursorHand, ///< Hand with a pointing finger | |||
| kMouseCursorNotAllowed, ///< Operation not allowed | |||
| kMouseCursorLeftRight, ///< Left/right arrow for horizontal resize | |||
| kMouseCursorUpDown, ///< Up/down arrow for vertical resize | |||
| kMouseCursorDiagonal, ///< Top-left to bottom-right arrow for diagonal resize | |||
| kMouseCursorAntiDiagonal ///< Bottom-left to top-right arrow for diagonal resize | |||
| kMouseCursorArrow, ///< Default pointing arrow | |||
| kMouseCursorCaret, ///< Caret (I-Beam) for text entry | |||
| kMouseCursorCrosshair, ///< Cross-hair | |||
| kMouseCursorHand, ///< Hand with a pointing finger | |||
| kMouseCursorNotAllowed, ///< Operation not allowed | |||
| kMouseCursorLeftRight, ///< Left/right arrow for horizontal resize | |||
| kMouseCursorUpDown, ///< Up/down arrow for vertical resize | |||
| kMouseCursorUpLeftDownRight, ///< Diagonal arrow for down/right resize | |||
| kMouseCursorUpRightDownLeft, ///< Diagonal arrow for down/left resize | |||
| kMouseCursorAllScroll, ///< Omnidirectional "arrow" for scrolling | |||
| // Backwards compatibility with old DPF | |||
| kMouseCursorDiagonal DISTRHO_DEPRECATED_BY("kMouseCursorUpLeftDownRight") = kMouseCursorUpLeftDownRight, | |||
| kMouseCursorAntiDiagonal DISTRHO_DEPRECATED_BY("kMouseCursorUpRightDownLeft") = kMouseCursorUpRightDownLeft | |||
| }; | |||
| /** | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2023 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 | |||
| @@ -47,7 +47,7 @@ static bool isThisTheMainThread(const d_ThreadHandle mainThreadHandle) noexcept | |||
| const char* Application::getClassName() const noexcept | |||
| { | |||
| return puglGetClassName(pData->world); | |||
| return puglGetWorldString(pData->world, PUGL_CLASS_NAME); | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| @@ -68,9 +68,9 @@ Application::PrivateData::PrivateData(const bool standalone) | |||
| puglSetWorldHandle(world, this); | |||
| #ifdef __EMSCRIPTEN__ | |||
| puglSetClassName(world, "canvas"); | |||
| puglSetWorldString(world, PUGL_CLASS_NAME, "canvas"); | |||
| #else | |||
| puglSetClassName(world, DISTRHO_MACRO_AS_STRING(DGL_NAMESPACE)); | |||
| puglSetWorldString(world, PUGL_CLASS_NAME, DISTRHO_MACRO_AS_STRING(DGL_NAMESPACE)); | |||
| #endif | |||
| } | |||
| @@ -168,7 +168,7 @@ void Application::PrivateData::setClassName(const char* const name) | |||
| DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',); | |||
| if (world != nullptr) | |||
| puglSetClassName(world, name); | |||
| puglSetWorldString(world, PUGL_CLASS_NAME, "canvas"); | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| @@ -801,9 +801,10 @@ void TopLevelWidget::PrivateData::display() | |||
| cairo_matrix_t matrix; | |||
| cairo_get_matrix(handle, &matrix); | |||
| cairo_translate(handle, 0, 0); | |||
| // full viewport size | |||
| cairo_translate(handle, 0, 0); | |||
| if (window.pData->autoScaling) | |||
| cairo_scale(handle, autoScaleFactor, autoScaleFactor); | |||
| else | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2023 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 | |||
| @@ -323,13 +323,13 @@ void Window::setSize(const Size<uint>& size) | |||
| const char* Window::getTitle() const noexcept | |||
| { | |||
| return pData->view != nullptr ? puglGetWindowTitle(pData->view) : ""; | |||
| return pData->view != nullptr ? puglGetViewString(pData->view, PUGL_WINDOW_TITLE) : ""; | |||
| } | |||
| void Window::setTitle(const char* const title) | |||
| { | |||
| if (pData->view != nullptr) | |||
| puglSetWindowTitle(pData->view, title); | |||
| puglSetViewString(pData->view, PUGL_WINDOW_TITLE, title); | |||
| } | |||
| bool Window::isIgnoringKeyRepeat() const noexcept | |||
| @@ -458,11 +458,15 @@ void Window::setGeometryConstraints(uint minimumWidth, | |||
| uint minimumHeight, | |||
| const bool keepAspectRatio, | |||
| const bool automaticallyScale, | |||
| const bool resizeNowIfAutoScaling) | |||
| bool resizeNowIfAutoScaling) | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(minimumWidth > 0,); | |||
| DISTRHO_SAFE_ASSERT_RETURN(minimumHeight > 0,); | |||
| // prevent auto-scaling up 2x | |||
| if (resizeNowIfAutoScaling && automaticallyScale && pData->autoScaling == automaticallyScale) | |||
| resizeNowIfAutoScaling = false; | |||
| pData->minWidth = minimumWidth; | |||
| pData->minHeight = minimumHeight; | |||
| pData->autoScaling = automaticallyScale; | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2023 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 | |||
| @@ -29,8 +29,16 @@ | |||
| # endif | |||
| #endif | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| # include <windows.h> | |||
| #endif | |||
| START_NAMESPACE_DGL | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| # include "pugl-upstream/src/win.h" | |||
| #endif | |||
| #ifdef DGL_DEBUG_EVENTS | |||
| # define DGL_DBG(msg) std::fprintf(stderr, "%s", msg); | |||
| # define DGL_DBGp(...) std::fprintf(stderr, __VA_ARGS__); | |||
| @@ -52,14 +60,14 @@ START_NAMESPACE_DGL | |||
| // ----------------------------------------------------------------------- | |||
| static double getScaleFactorFromParent(const PuglView* const view) | |||
| static double getScaleFactor(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 puglGetScaleFactorFromParent(view); | |||
| return puglGetScaleFactor(view); | |||
| return 1.0; | |||
| } | |||
| @@ -108,7 +116,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s) | |||
| isVisible(false), | |||
| isEmbed(false), | |||
| usesSizeRequest(false), | |||
| scaleFactor(getScaleFactorFromParent(view)), | |||
| scaleFactor(DGL_NAMESPACE::getScaleFactor(view)), | |||
| autoScaling(false), | |||
| autoScaleFactor(1.0), | |||
| minWidth(0), | |||
| @@ -119,9 +127,9 @@ Window::PrivateData::PrivateData(Application& a, Window* const s) | |||
| waitingForClipboardEvents(false), | |||
| clipboardTypeId(0), | |||
| filenameToRenderInto(nullptr), | |||
| #ifndef DGL_FILE_BROWSER_DISABLED | |||
| #ifndef DGL_FILE_BROWSER_DISABLED | |||
| fileBrowserHandle(nullptr), | |||
| #endif | |||
| #endif | |||
| modal() | |||
| { | |||
| initPre(DEFAULT_WIDTH, DEFAULT_HEIGHT, false); | |||
| @@ -148,9 +156,9 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, PrivateData* c | |||
| waitingForClipboardEvents(false), | |||
| clipboardTypeId(0), | |||
| filenameToRenderInto(nullptr), | |||
| #ifndef DGL_FILE_BROWSER_DISABLED | |||
| #ifndef DGL_FILE_BROWSER_DISABLED | |||
| fileBrowserHandle(nullptr), | |||
| #endif | |||
| #endif | |||
| modal(ppData) | |||
| { | |||
| initPre(DEFAULT_WIDTH, DEFAULT_HEIGHT, false); | |||
| @@ -168,7 +176,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, | |||
| isVisible(parentWindowHandle != 0), | |||
| isEmbed(parentWindowHandle != 0), | |||
| usesSizeRequest(false), | |||
| scaleFactor(scale != 0.0 ? scale : getScaleFactorFromParent(view)), | |||
| scaleFactor(scale != 0.0 ? scale : DGL_NAMESPACE::getScaleFactor(view)), | |||
| autoScaling(false), | |||
| autoScaleFactor(1.0), | |||
| minWidth(0), | |||
| @@ -179,9 +187,9 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, | |||
| waitingForClipboardEvents(false), | |||
| clipboardTypeId(0), | |||
| filenameToRenderInto(nullptr), | |||
| #ifndef DGL_FILE_BROWSER_DISABLED | |||
| #ifndef DGL_FILE_BROWSER_DISABLED | |||
| fileBrowserHandle(nullptr), | |||
| #endif | |||
| #endif | |||
| modal() | |||
| { | |||
| initPre(DEFAULT_WIDTH, DEFAULT_HEIGHT, resizable); | |||
| @@ -200,7 +208,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, | |||
| isVisible(parentWindowHandle != 0 && view != nullptr), | |||
| isEmbed(parentWindowHandle != 0), | |||
| usesSizeRequest(usesSizeRequest_), | |||
| scaleFactor(scale != 0.0 ? scale : getScaleFactorFromParent(view)), | |||
| scaleFactor(scale != 0.0 ? scale : DGL_NAMESPACE::getScaleFactor(view)), | |||
| autoScaling(false), | |||
| autoScaleFactor(1.0), | |||
| minWidth(0), | |||
| @@ -211,9 +219,9 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, | |||
| waitingForClipboardEvents(false), | |||
| clipboardTypeId(0), | |||
| filenameToRenderInto(nullptr), | |||
| #ifndef DGL_FILE_BROWSER_DISABLED | |||
| #ifndef DGL_FILE_BROWSER_DISABLED | |||
| fileBrowserHandle(nullptr), | |||
| #endif | |||
| #endif | |||
| modal() | |||
| { | |||
| initPre(width != 0 ? width : DEFAULT_WIDTH, height != 0 ? height : DEFAULT_HEIGHT, resizable); | |||
| @@ -230,10 +238,10 @@ Window::PrivateData::~PrivateData() | |||
| if (isEmbed) | |||
| { | |||
| #ifndef DGL_FILE_BROWSER_DISABLED | |||
| #ifndef DGL_FILE_BROWSER_DISABLED | |||
| if (fileBrowserHandle != nullptr) | |||
| fileBrowserClose(fileBrowserHandle); | |||
| #endif | |||
| #endif | |||
| puglHide(view); | |||
| appData->oneWindowClosed(); | |||
| isClosed = true; | |||
| @@ -292,7 +300,7 @@ bool Window::PrivateData::initPost() | |||
| if (isEmbed) | |||
| { | |||
| appData->oneWindowShown(); | |||
| puglShow(view); | |||
| puglShow(view, PUGL_SHOW_PASSIVE); | |||
| } | |||
| return true; | |||
| @@ -347,7 +355,7 @@ void Window::PrivateData::show() | |||
| #elif defined(DISTRHO_OS_MAC) | |||
| puglMacOSShowCentered(view); | |||
| #else | |||
| puglShow(view); | |||
| puglShow(view, PUGL_SHOW_RAISE); | |||
| #endif | |||
| } | |||
| else | |||
| @@ -355,7 +363,7 @@ void Window::PrivateData::show() | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| puglWin32RestoreWindow(view); | |||
| #else | |||
| puglShow(view); | |||
| puglShow(view, PUGL_SHOW_RAISE); | |||
| #endif | |||
| } | |||
| @@ -475,7 +483,7 @@ bool Window::PrivateData::openFileBrowser(const FileBrowserOptions& options) | |||
| FileBrowserOptions options2 = options; | |||
| if (options2.title == nullptr) | |||
| options2.title = puglGetWindowTitle(view); | |||
| options2.title = puglGetViewString(view, PUGL_WINDOW_TITLE); | |||
| fileBrowserHandle = fileBrowserCreate(isEmbed, | |||
| puglGetNativeView(view), | |||
| @@ -887,58 +895,61 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||
| case PUGL_NOTHING: | |||
| break; | |||
| ///< View created, a #PuglEventCreate | |||
| case PUGL_CREATE: | |||
| #ifdef DGL_USING_X11 | |||
| if (! pData->isEmbed) | |||
| ///< View realized, a #PuglRealizeEvent | |||
| case PUGL_REALIZE: | |||
| if (! pData->isEmbed && ! puglGetTransientParent(view)) | |||
| { | |||
| #if defined(DISTRHO_OS_WINDOWS) && defined(DGL_WINDOWS_ICON_ID) | |||
| WNDCLASSEX wClass = {}; | |||
| const HINSTANCE hInstance = GetModuleHandle(nullptr); | |||
| if (GetClassInfoEx(hInstance, view->world->strings[PUGL_CLASS_NAME], &wClass)) | |||
| wClass.hIcon = LoadIcon(nullptr, MAKEINTRESOURCE(DGL_WINDOWS_ICON_ID)); | |||
| SetClassLongPtr(view->impl->hwnd, GCLP_HICON, (LONG_PTR) LoadIcon(hInstance, MAKEINTRESOURCE(DGL_WINDOWS_ICON_ID))); | |||
| #endif | |||
| #ifdef DGL_USING_X11 | |||
| puglX11SetWindowTypeAndPID(view, pData->appData->isStandalone); | |||
| #endif | |||
| #endif | |||
| } | |||
| break; | |||
| ///< View destroyed, a #PuglEventDestroy | |||
| case PUGL_DESTROY: | |||
| ///< View unrealizeed, a #PuglUnrealizeEvent | |||
| case PUGL_UNREALIZE: | |||
| break; | |||
| ///< View moved/resized, a #PuglEventConfigure | |||
| ///< View configured, a #PuglConfigureEvent | |||
| case PUGL_CONFIGURE: | |||
| // unused x, y (double) | |||
| pData->onPuglConfigure(event->configure.width, event->configure.height); | |||
| break; | |||
| ///< View made visible, a #PuglEventMap | |||
| case PUGL_MAP: | |||
| break; | |||
| ///< View made invisible, a #PuglEventUnmap | |||
| case PUGL_UNMAP: | |||
| break; | |||
| ///< View ready to draw, a #PuglEventUpdate | |||
| ///< View ready to draw, a #PuglUpdateEvent | |||
| case PUGL_UPDATE: | |||
| break; | |||
| ///< View must be drawn, a #PuglEventExpose | |||
| ///< View must be drawn, a #PuglExposeEvent | |||
| case PUGL_EXPOSE: | |||
| // unused x, y, width, height (double) | |||
| pData->onPuglExpose(); | |||
| break; | |||
| ///< View will be closed, a #PuglEventClose | |||
| ///< View will be closed, a #PuglCloseEvent | |||
| case PUGL_CLOSE: | |||
| pData->onPuglClose(); | |||
| break; | |||
| ///< Keyboard focus entered view, a #PuglEventFocus | |||
| ///< Keyboard focus entered view, a #PuglFocusEvent | |||
| case PUGL_FOCUS_IN: | |||
| ///< Keyboard focus left view, a #PuglEventFocus | |||
| ///< Keyboard focus left view, a #PuglFocusEvent | |||
| case PUGL_FOCUS_OUT: | |||
| pData->onPuglFocus(event->type == PUGL_FOCUS_IN, | |||
| static_cast<CrossingMode>(event->focus.mode)); | |||
| break; | |||
| ///< Key pressed, a #PuglEventKey | |||
| ///< Key pressed, a #PuglKeyEvent | |||
| case PUGL_KEY_PRESS: | |||
| ///< Key released, a #PuglEventKey | |||
| ///< Key released, a #PuglKeyEvent | |||
| case PUGL_KEY_RELEASE: | |||
| { | |||
| // unused x, y, xRoot, yRoot (double) | |||
| @@ -961,7 +972,7 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||
| break; | |||
| } | |||
| ///< Character entered, a #PuglEventText | |||
| ///< Character entered, a #PuglTextEvent | |||
| case PUGL_TEXT: | |||
| { | |||
| // unused x, y, xRoot, yRoot (double) | |||
| @@ -976,16 +987,16 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||
| break; | |||
| } | |||
| ///< Pointer entered view, a #PuglEventCrossing | |||
| ///< Pointer entered view, a #PuglCrossingEvent | |||
| case PUGL_POINTER_IN: | |||
| break; | |||
| ///< Pointer left view, a #PuglEventCrossing | |||
| ///< Pointer left view, a #PuglCrossingEvent | |||
| case PUGL_POINTER_OUT: | |||
| break; | |||
| ///< Mouse button pressed, a #PuglEventButton | |||
| ///< Mouse button pressed, a #PuglButtonEvent | |||
| case PUGL_BUTTON_PRESS: | |||
| ///< Mouse button released, a #PuglEventButton | |||
| ///< Mouse button released, a #PuglButtonEvent | |||
| case PUGL_BUTTON_RELEASE: | |||
| { | |||
| Widget::MouseEvent ev; | |||
| @@ -994,51 +1005,76 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||
| ev.time = static_cast<uint>(event->button.time * 1000.0 + 0.5); | |||
| ev.button = event->button.button + 1; | |||
| ev.press = event->type == PUGL_BUTTON_PRESS; | |||
| ev.pos = Point<double>(event->button.x, event->button.y); | |||
| if (pData->autoScaling && 0) | |||
| { | |||
| const double scaleFactor = pData->autoScaleFactor; | |||
| ev.pos = Point<double>(event->button.x / scaleFactor, event->button.y / scaleFactor); | |||
| } | |||
| else | |||
| { | |||
| ev.pos = Point<double>(event->button.x, event->button.y); | |||
| } | |||
| ev.absolutePos = ev.pos; | |||
| pData->onPuglMouse(ev); | |||
| break; | |||
| } | |||
| ///< Pointer moved, a #PuglEventMotion | |||
| ///< Pointer moved, a #PuglMotionEvent | |||
| case PUGL_MOTION: | |||
| { | |||
| Widget::MotionEvent ev; | |||
| ev.mod = event->motion.state; | |||
| ev.flags = event->motion.flags; | |||
| ev.time = static_cast<uint>(event->motion.time * 1000.0 + 0.5); | |||
| ev.pos = Point<double>(event->motion.x, event->motion.y); | |||
| if (pData->autoScaling && 0) | |||
| { | |||
| const double scaleFactor = pData->autoScaleFactor; | |||
| ev.pos = Point<double>(event->motion.x / scaleFactor, event->motion.y / scaleFactor); | |||
| } | |||
| else | |||
| { | |||
| ev.pos = Point<double>(event->motion.x, event->motion.y); | |||
| } | |||
| ev.absolutePos = ev.pos; | |||
| pData->onPuglMotion(ev); | |||
| break; | |||
| } | |||
| ///< Scrolled, a #PuglEventScroll | |||
| ///< Scrolled, a #PuglScrollEvent | |||
| case PUGL_SCROLL: | |||
| { | |||
| Widget::ScrollEvent ev; | |||
| ev.mod = event->scroll.state; | |||
| ev.flags = event->scroll.flags; | |||
| ev.time = static_cast<uint>(event->scroll.time * 1000.0 + 0.5); | |||
| ev.pos = Point<double>(event->scroll.x, event->scroll.y); | |||
| ev.delta = Point<double>(event->scroll.dx, event->scroll.dy); | |||
| if (pData->autoScaling && 0) | |||
| { | |||
| const double scaleFactor = pData->autoScaleFactor; | |||
| ev.pos = Point<double>(event->scroll.x / scaleFactor, event->scroll.y / scaleFactor); | |||
| ev.delta = Point<double>(event->scroll.dx / scaleFactor, event->scroll.dy / scaleFactor); | |||
| } | |||
| else | |||
| { | |||
| ev.pos = Point<double>(event->scroll.x, event->scroll.y); | |||
| ev.delta = Point<double>(event->scroll.dx, event->scroll.dy); | |||
| } | |||
| ev.direction = static_cast<ScrollDirection>(event->scroll.direction); | |||
| ev.absolutePos = ev.pos; | |||
| pData->onPuglScroll(ev); | |||
| break; | |||
| } | |||
| ///< Custom client message, a #PuglEventClient | |||
| ///< Custom client message, a #PuglClientEvent | |||
| case PUGL_CLIENT: | |||
| break; | |||
| ///< Timer triggered, a #PuglEventTimer | |||
| ///< Timer triggered, a #PuglTimerEvent | |||
| case PUGL_TIMER: | |||
| if (IdleCallback* const idleCallback = reinterpret_cast<IdleCallback*>(event->timer.id)) | |||
| idleCallback->idleCallback(); | |||
| break; | |||
| ///< Recursive loop entered, a #PuglEventLoopEnter | |||
| ///< Recursive loop left, a #PuglLoopLeaveEvent | |||
| case PUGL_LOOP_ENTER: | |||
| break; | |||
| @@ -173,7 +173,7 @@ puglKeyCallback(const int eventType, const EmscriptenKeyboardEvent* const keyEve | |||
| { | |||
| PuglView* const view = (PuglView*)userData; | |||
| if (!view->visible) { | |||
| if (!view->impl->visible) { | |||
| return EM_FALSE; | |||
| } | |||
| @@ -253,7 +253,7 @@ puglMouseCallback(const int eventType, const EmscriptenMouseEvent* const mouseEv | |||
| { | |||
| PuglView* const view = (PuglView*)userData; | |||
| if (!view->visible) { | |||
| if (!view->impl->visible) { | |||
| return EM_FALSE; | |||
| } | |||
| @@ -286,7 +286,7 @@ puglMouseCallback(const int eventType, const EmscriptenMouseEvent* const mouseEv | |||
| const long canvasX = mouseEvent->canvasX; | |||
| const long canvasY = mouseEvent->canvasY; | |||
| #else | |||
| const char* const className = view->world->className; | |||
| const char* const className = view->world->strings[PUGL_CLASS_NAME]; | |||
| const double canvasX = mouseEvent->clientX - EM_ASM_DOUBLE({ | |||
| var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; | |||
| return canvasWrapper.getBoundingClientRect().x; | |||
| @@ -365,7 +365,7 @@ puglMouseCallback(const int eventType, const EmscriptenMouseEvent* const mouseEv | |||
| #ifdef PUGL_WASM_AUTO_POINTER_LOCK | |||
| switch (eventType) { | |||
| case EMSCRIPTEN_EVENT_MOUSEDOWN: | |||
| emscripten_request_pointerlock(view->world->className, false); | |||
| emscripten_request_pointerlock(view->world->strings[PUGL_CLASS_NAME], false); | |||
| break; | |||
| case EMSCRIPTEN_EVENT_MOUSEUP: | |||
| emscripten_exit_pointerlock(); | |||
| @@ -397,7 +397,7 @@ puglTouchCallback(const int eventType, const EmscriptenTouchEvent* const touchEv | |||
| PuglView* const view = (PuglView*)userData; | |||
| PuglInternals* const impl = view->impl; | |||
| const char* const className = view->world->className; | |||
| const char* const className = view->world->strings[PUGL_CLASS_NAME]; | |||
| if (impl->supportsTouch == PUGL_DONT_CARE) { | |||
| impl->supportsTouch = PUGL_TRUE; | |||
| @@ -407,7 +407,7 @@ puglTouchCallback(const int eventType, const EmscriptenTouchEvent* const touchEv | |||
| emscripten_set_mouseup_callback(className, view, false, NULL); | |||
| } | |||
| if (!view->visible) { | |||
| if (!view->impl->visible) { | |||
| return EM_FALSE; | |||
| } | |||
| @@ -519,7 +519,7 @@ puglFocusCallback(const int eventType, const EmscriptenFocusEvent* /*const focus | |||
| { | |||
| PuglView* const view = (PuglView*)userData; | |||
| if (!view->visible) { | |||
| if (!view->impl->visible) { | |||
| return EM_FALSE; | |||
| } | |||
| @@ -549,7 +549,7 @@ puglWheelCallback(const int eventType, const EmscriptenWheelEvent* const wheelEv | |||
| { | |||
| PuglView* const view = (PuglView*)userData; | |||
| if (!view->visible) { | |||
| if (!view->impl->visible) { | |||
| return EM_FALSE; | |||
| } | |||
| @@ -569,7 +569,7 @@ puglWheelCallback(const int eventType, const EmscriptenWheelEvent* const wheelEv | |||
| const long canvasX = wheelEvent->mouse.canvasX; | |||
| const long canvasY = wheelEvent->mouse.canvasY; | |||
| #else | |||
| const char* const className = view->world->className; | |||
| const char* const className = view->world->strings[PUGL_CLASS_NAME]; | |||
| const double canvasX = wheelEvent->mouse.canvasX - EM_ASM_INT({ | |||
| var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; | |||
| return canvasWrapper.getBoundingClientRect().x; | |||
| @@ -603,7 +603,7 @@ static EM_BOOL | |||
| puglUiCallback(const int eventType, const EmscriptenUiEvent* const uiEvent, void* const userData) | |||
| { | |||
| PuglView* const view = (PuglView*)userData; | |||
| const char* const className = view->world->className; | |||
| const char* const className = view->world->strings[PUGL_CLASS_NAME]; | |||
| const bool isFullscreen = view->impl->isFullscreen; | |||
| // FIXME | |||
| @@ -636,13 +636,15 @@ puglUiCallback(const int eventType, const EmscriptenUiEvent* const uiEvent, void | |||
| view->world->impl->scaleFactor = scaleFactor; | |||
| PuglEvent event = {{PUGL_CONFIGURE, 0}}; | |||
| event.configure.x = view->frame.x; | |||
| event.configure.y = view->frame.y; | |||
| event.configure.x = view->lastConfigure.x; | |||
| event.configure.y = view->lastConfigure.y; | |||
| event.configure.width = width * scaleFactor; | |||
| event.configure.height = height * scaleFactor; | |||
| puglDispatchEvent(view, &event); | |||
| emscripten_set_canvas_element_size(view->world->className, width * scaleFactor, height * scaleFactor); | |||
| emscripten_set_canvas_element_size(view->world->strings[PUGL_CLASS_NAME], | |||
| width * scaleFactor, | |||
| height * scaleFactor); | |||
| #ifdef __MOD_DEVICES__ | |||
| if (isFullscreen) { | |||
| @@ -659,7 +661,6 @@ static EM_BOOL | |||
| puglFullscreenChangeCallback(const int eventType, const EmscriptenFullscreenChangeEvent* const fscEvent, void* const userData) | |||
| { | |||
| PuglView* const view = (PuglView*)userData; | |||
| const char* const className = view->world->className; | |||
| view->impl->isFullscreen = fscEvent->isFullscreen; | |||
| @@ -688,7 +689,7 @@ puglFullscreenChangeCallback(const int eventType, const EmscriptenFullscreenChan | |||
| event.configure.height = height; | |||
| puglDispatchEvent(view, &event); | |||
| emscripten_set_canvas_element_size(view->world->className, width, height); | |||
| emscripten_set_canvas_element_size(view->world->strings[PUGL_CLASS_NAME], width, height); | |||
| #ifdef __MOD_DEVICES__ | |||
| EM_ASM({ | |||
| @@ -704,9 +705,7 @@ puglVisibilityChangeCallback(const int eventType, const EmscriptenVisibilityChan | |||
| { | |||
| PuglView* const view = (PuglView*)userData; | |||
| view->visible = visibilityChangeEvent->hidden == EM_FALSE; | |||
| PuglEvent event = {{ view->visible ? PUGL_MAP : PUGL_UNMAP, 0}}; | |||
| puglDispatchEvent(view, &event); | |||
| view->impl->visible = visibilityChangeEvent->hidden == EM_FALSE; | |||
| return EM_FALSE; | |||
| } | |||
| @@ -727,18 +726,12 @@ puglRealize(PuglView* const view) | |||
| return PUGL_BAD_BACKEND; | |||
| } | |||
| const char* const className = view->world->className; | |||
| const char* const className = view->world->strings[PUGL_CLASS_NAME]; | |||
| d_stdout("className is %s", className); | |||
| // Set the size to the default if it has not already been set | |||
| if (view->frame.width <= 0.0 && view->frame.height <= 0.0) { | |||
| PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; | |||
| if (!defaultSize.width || !defaultSize.height) { | |||
| return PUGL_BAD_CONFIGURATION; | |||
| } | |||
| view->frame.width = defaultSize.width; | |||
| view->frame.height = defaultSize.height; | |||
| PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; | |||
| if (!defaultSize.width || !defaultSize.height) { | |||
| return PUGL_BAD_CONFIGURATION; | |||
| } | |||
| // Configure and create the backend | |||
| @@ -747,25 +740,27 @@ puglRealize(PuglView* const view) | |||
| return st; | |||
| } | |||
| if (view->title) { | |||
| puglSetWindowTitle(view, view->title); | |||
| if (view->strings[PUGL_WINDOW_TITLE]) { | |||
| emscripten_set_window_title(view->strings[PUGL_WINDOW_TITLE]); | |||
| } | |||
| puglDispatchSimpleEvent(view, PUGL_CREATE); | |||
| puglDispatchSimpleEvent(view, PUGL_REALIZE); | |||
| PuglEvent event = {{PUGL_CONFIGURE, 0}}; | |||
| event.configure.x = view->frame.x; | |||
| event.configure.y = view->frame.y; | |||
| event.configure.width = view->frame.width; | |||
| event.configure.height = view->frame.height; | |||
| event.configure.x = view->defaultX; | |||
| event.configure.y = view->defaultY; | |||
| event.configure.width = defaultSize.width; | |||
| event.configure.height = defaultSize.height; | |||
| puglDispatchEvent(view, &event); | |||
| view->impl->created = true; | |||
| EM_ASM({ | |||
| var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; | |||
| canvasWrapper.style.setProperty("--device-pixel-ratio", window.devicePixelRatio); | |||
| }, className); | |||
| emscripten_set_canvas_element_size(className, view->frame.width, view->frame.height); | |||
| emscripten_set_canvas_element_size(className, defaultSize.width, defaultSize.height); | |||
| #ifndef PUGL_WASM_NO_KEYBOARD_INPUT | |||
| // emscripten_set_keypress_callback(className, view, false, puglKeyCallback); | |||
| emscripten_set_keydown_callback(className, view, false, puglKeyCallback); | |||
| @@ -795,9 +790,9 @@ puglRealize(PuglView* const view) | |||
| } | |||
| PuglStatus | |||
| puglShow(PuglView* const view) | |||
| puglShow(PuglView* const view, PuglShowCommand) | |||
| { | |||
| view->visible = true; | |||
| view->impl->visible = true; | |||
| view->impl->needsRepaint = true; | |||
| return puglPostRedisplay(view); | |||
| } | |||
| @@ -805,7 +800,7 @@ puglShow(PuglView* const view) | |||
| PuglStatus | |||
| puglHide(PuglView* const view) | |||
| { | |||
| view->visible = false; | |||
| view->impl->visible = false; | |||
| return PUGL_FAILURE; | |||
| } | |||
| @@ -865,7 +860,7 @@ puglUpdate(PuglWorld* const world, const double timeout) | |||
| for (size_t i = 0; i < world->numViews; ++i) { | |||
| PuglView* const view = world->views[i]; | |||
| if (!view->visible) { | |||
| if (!view->impl->visible) { | |||
| continue; | |||
| } | |||
| @@ -878,10 +873,10 @@ puglUpdate(PuglWorld* const world, const double timeout) | |||
| view->impl->needsRepaint = false; | |||
| PuglEvent event = {{PUGL_EXPOSE, 0}}; | |||
| event.expose.x = view->frame.x; | |||
| event.expose.y = view->frame.y; | |||
| event.expose.width = view->frame.width; | |||
| event.expose.height = view->frame.height; | |||
| event.expose.x = view->lastConfigure.x; | |||
| event.expose.y = view->lastConfigure.y; | |||
| event.expose.width = view->lastConfigure.width; | |||
| event.expose.height = view->lastConfigure.height; | |||
| puglDispatchEvent(view, &event); | |||
| } | |||
| @@ -909,10 +904,16 @@ puglGetNativeView(PuglView* const view) | |||
| } | |||
| PuglStatus | |||
| puglSetWindowTitle(PuglView* const view, const char* const title) | |||
| puglViewStringChanged(PuglView*, const PuglStringHint key, const char* const value) | |||
| { | |||
| puglSetString(&view->title, title); | |||
| emscripten_set_window_title(title); | |||
| switch (key) { | |||
| case PUGL_CLASS_NAME: | |||
| break; | |||
| case PUGL_WINDOW_TITLE: | |||
| emscripten_set_window_title(value); | |||
| break; | |||
| } | |||
| return PUGL_SUCCESS; | |||
| } | |||
| @@ -1098,7 +1099,7 @@ puglSetClipboard(PuglView* const view, | |||
| return PUGL_UNSUPPORTED; | |||
| } | |||
| const char* const className = view->world->className; | |||
| const char* const className = view->world->strings[PUGL_CLASS_NAME]; | |||
| const char* const text = (const char*)data; | |||
| #ifdef PUGL_WASM_ASYNC_CLIPBOARD | |||
| @@ -1161,7 +1162,14 @@ puglSetPosition(PuglView* const view, const int x, const int y) | |||
| return PUGL_BAD_PARAMETER; | |||
| } | |||
| view->frame.x = (PuglCoord)x; | |||
| view->frame.y = (PuglCoord)y; | |||
| return PUGL_FAILURE; | |||
| if (!view->impl->created) { | |||
| // Set defaults to be used when realized | |||
| view->defaultX = x; | |||
| view->defaultY = y; | |||
| return PUGL_SUCCESS; | |||
| } | |||
| view->lastConfigure.x = (PuglCoord)x; | |||
| view->lastConfigure.y = (PuglCoord)y; | |||
| return puglPostRedisplay(view); | |||
| } | |||
| @@ -29,6 +29,8 @@ struct PuglInternalsImpl { | |||
| bool isFullscreen; | |||
| bool needsRepaint; | |||
| bool pointerLocked; | |||
| bool created; | |||
| bool visible; | |||
| uint32_t numTimers; | |||
| LastMotionValues lastMotion; | |||
| long buttonPressTimeout; | |||
| @@ -1 +1 @@ | |||
| Subproject commit 2e98e220b5b860c1c8cd5809fad61baf27380a37 | |||
| Subproject commit 88dc250bfd4ca1ccd47801acf071ebf79e1450d7 | |||
| @@ -228,13 +228,16 @@ void puglSetMatchingBackendForCurrentBuild(PuglView* const view) | |||
| { | |||
| #ifdef DGL_OPENGL | |||
| #if defined(DGL_USE_GLES2) | |||
| puglSetViewHint(view, PUGL_USE_COMPAT_PROFILE, PUGL_FALSE); | |||
| puglSetViewHint(view, PUGL_CONTEXT_API, PUGL_OPENGL_ES_API); | |||
| puglSetViewHint(view, PUGL_CONTEXT_PROFILE, PUGL_OPENGL_CORE_PROFILE); | |||
| puglSetViewHint(view, PUGL_CONTEXT_VERSION_MAJOR, 2); | |||
| #elif defined(DGL_USE_OPENGL3) | |||
| puglSetViewHint(view, PUGL_USE_COMPAT_PROFILE, PUGL_FALSE); | |||
| puglSetViewHint(view, PUGL_CONTEXT_API, PUGL_OPENGL_API); | |||
| puglSetViewHint(view, PUGL_CONTEXT_PROFILE, PUGL_OPENGL_CORE_PROFILE); | |||
| puglSetViewHint(view, PUGL_CONTEXT_VERSION_MAJOR, 3); | |||
| #else | |||
| puglSetViewHint(view, PUGL_USE_COMPAT_PROFILE, PUGL_TRUE); | |||
| puglSetViewHint(view, PUGL_CONTEXT_API, PUGL_OPENGL_API); | |||
| puglSetViewHint(view, PUGL_CONTEXT_PROFILE, PUGL_OPENGL_COMPATIBILITY_PROFILE); | |||
| puglSetViewHint(view, PUGL_CONTEXT_VERSION_MAJOR, 2); | |||
| #endif | |||
| #endif | |||
| @@ -265,40 +268,6 @@ void puglRaiseWindow(PuglView* const view) | |||
| #endif | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // get scale factor from parent window if possible, fallback to puglGetScaleFactor | |||
| double puglGetScaleFactorFromParent(const PuglView* const view) | |||
| { | |||
| const PuglNativeView parent = view->parent ? view->parent : view->transientParent ? view->transientParent : 0; | |||
| #if defined(DISTRHO_OS_HAIKU) | |||
| // TODO | |||
| return 1.0; | |||
| #elif defined(DISTRHO_OS_MAC) | |||
| // some of these can return 0 as backingScaleFactor, pick the most relevant valid one | |||
| const NSWindow* possibleWindows[] = { | |||
| parent != 0 ? [(NSView*)parent window] : nullptr, | |||
| view->impl->window, | |||
| [view->impl->wrapperView window] | |||
| }; | |||
| for (size_t i=0; i<ARRAY_SIZE(possibleWindows); ++i) | |||
| { | |||
| if (possibleWindows[i] == nullptr) | |||
| continue; | |||
| if (const double scaleFactor = [[possibleWindows[i] screen] backingScaleFactor]) | |||
| return scaleFactor; | |||
| } | |||
| return [[NSScreen mainScreen] 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 | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // Combined puglSetSizeHint using PUGL_MIN_SIZE and PUGL_FIXED_ASPECT | |||
| @@ -317,12 +286,10 @@ PuglStatus puglSetGeometryConstraints(PuglView* const view, const uint width, co | |||
| #elif defined(DISTRHO_OS_MAC) | |||
| if (view->impl->window) | |||
| { | |||
| PuglStatus status; | |||
| if ((status = updateSizeHint(view, PUGL_MIN_SIZE)) != PUGL_SUCCESS) | |||
| if (const PuglStatus status = updateSizeHint(view, PUGL_MIN_SIZE)) | |||
| return status; | |||
| if (aspect && (status = updateSizeHint(view, PUGL_FIXED_ASPECT)) != PUGL_SUCCESS) | |||
| if (const PuglStatus status = updateSizeHint(view, PUGL_FIXED_ASPECT)) | |||
| return status; | |||
| } | |||
| #elif defined(DISTRHO_OS_WASM) | |||
| @@ -330,10 +297,13 @@ PuglStatus puglSetGeometryConstraints(PuglView* const view, const uint width, co | |||
| #elif defined(DISTRHO_OS_WINDOWS) | |||
| // nothing | |||
| #elif defined(HAVE_X11) | |||
| if (const PuglStatus status = updateSizeHints(view)) | |||
| return status; | |||
| if (view->impl->win) | |||
| { | |||
| if (const PuglStatus status = updateSizeHints(view)) | |||
| return status; | |||
| XFlush(view->world->impl->display); | |||
| XFlush(view->world->impl->display); | |||
| } | |||
| #endif | |||
| return PUGL_SUCCESS; | |||
| @@ -377,59 +347,48 @@ PuglStatus puglSetSizeAndDefault(PuglView* view, uint width, uint 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); | |||
| // set default size first | |||
| view->sizeHints[PUGL_DEFAULT_SIZE].width = static_cast<PuglSpan>(width); | |||
| view->sizeHints[PUGL_DEFAULT_SIZE].height = static_cast<PuglSpan>(height); | |||
| #if defined(DISTRHO_OS_HAIKU) | |||
| #elif defined(DISTRHO_OS_MAC) | |||
| // 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 (PuglWindow* const window = view->impl->window) | |||
| // matches upstream pugl | |||
| if (view->impl->wrapperView) | |||
| { | |||
| const NSRect screenPt = rectToScreen(viewScreen(view), framePt); | |||
| const NSRect winFrame = [window frameRectForContentRect:screenPt]; | |||
| [window setFrame:winFrame display:NO]; | |||
| } | |||
| if (const PuglStatus status = puglSetSize(view, width, height)) | |||
| return status; | |||
| const NSSize sizePx = NSMakeSize(frame.width, frame.height); | |||
| const NSSize sizePt = [impl->drawView convertSizeFromBacking:sizePx]; | |||
| [impl->wrapperView setFrameSize:sizePt]; | |||
| [impl->drawView setFrameSize:sizePt]; | |||
| // nothing to do for PUGL_DEFAULT_SIZE hint | |||
| } | |||
| #elif defined(DISTRHO_OS_WASM) | |||
| d_stdout("className is %s", view->world->className); | |||
| emscripten_set_canvas_element_size(view->world->className, width, height); | |||
| d_stdout("className is %s", view->world->strings[PUGL_CLASS_NAME]); | |||
| emscripten_set_canvas_element_size(view->world->strings[PUGL_CLASS_NAME], width, height); | |||
| #elif defined(DISTRHO_OS_WINDOWS) | |||
| // matches upstream pugl, except we re-enter context after resize | |||
| if (const HWND hwnd = view->impl->hwnd) | |||
| if (view->impl->hwnd) | |||
| { | |||
| const RECT rect = adjustedWindowRect(view, view->frame.x, view->frame.y, | |||
| static_cast<long>(width), static_cast<long>(height)); | |||
| if (const PuglStatus status = puglSetSize(view, width, height)) | |||
| return status; | |||
| 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; | |||
| // nothing to do for PUGL_DEFAULT_SIZE hint | |||
| // make sure to return context back to ourselves | |||
| puglBackendEnter(view); | |||
| } | |||
| #elif defined(HAVE_X11) | |||
| // matches upstream pugl, all in one | |||
| if (const Window window = view->impl->win) | |||
| // matches upstream pugl, adds flush at the end | |||
| if (view->impl->win) | |||
| { | |||
| Display* const display = view->world->impl->display; | |||
| if (! XResizeWindow(display, window, width, height)) | |||
| return PUGL_UNKNOWN_ERROR; | |||
| if (const PuglStatus status = puglSetSize(view, width, height)) | |||
| return status; | |||
| // handle new PUGL_DEFAULT_SIZE hint | |||
| if (const PuglStatus status = updateSizeHints(view)) | |||
| return status; | |||
| XFlush(display); | |||
| // flush size changes | |||
| XFlush(view->world->impl->display); | |||
| } | |||
| #endif | |||
| @@ -452,18 +411,18 @@ void puglOnDisplayPrepare(PuglView*) | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // DGL specific, build-specific fallback resize | |||
| void puglFallbackOnResize(PuglView* const view, uint, uint) | |||
| void puglFallbackOnResize(PuglView* const view, const uint width, const uint height) | |||
| { | |||
| #ifdef DGL_OPENGL | |||
| glEnable(GL_BLEND); | |||
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |||
| #ifdef DGL_USE_OPENGL3 | |||
| glViewport(0, 0, static_cast<GLsizei>(view->frame.width), static_cast<GLsizei>(view->frame.height)); | |||
| glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height)); | |||
| #else | |||
| glMatrixMode(GL_PROJECTION); | |||
| glLoadIdentity(); | |||
| glOrtho(0.0, static_cast<GLdouble>(view->frame.width), static_cast<GLdouble>(view->frame.height), 0.0, 0.0, 1.0); | |||
| glViewport(0, 0, static_cast<GLsizei>(view->frame.width), static_cast<GLsizei>(view->frame.height)); | |||
| glOrtho(0.0, static_cast<GLdouble>(width), static_cast<GLdouble>(height), 0.0, 0.0, 1.0); | |||
| glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height)); | |||
| glMatrixMode(GL_MODELVIEW); | |||
| glLoadIdentity(); | |||
| #endif | |||
| @@ -527,7 +486,7 @@ puglMacOSRemoveChildWindow(PuglView* const view, PuglView* const child) | |||
| void puglMacOSShowCentered(PuglView* const view) | |||
| { | |||
| if (puglShow(view) != PUGL_SUCCESS) | |||
| if (puglShow(view, PUGL_SHOW_RAISE) != PUGL_SUCCESS) | |||
| return; | |||
| if (view->transientParent != 0) | |||
| @@ -586,26 +545,14 @@ void puglWin32ShowCentered(PuglView* const view) | |||
| } | |||
| else | |||
| { | |||
| #ifdef DGL_WINDOWS_ICON_ID | |||
| WNDCLASSEX wClass; | |||
| std::memset(&wClass, 0, sizeof(wClass)); | |||
| const HINSTANCE hInstance = GetModuleHandle(nullptr); | |||
| if (GetClassInfoEx(hInstance, view->world->className, &wClass)) | |||
| wClass.hIcon = LoadIcon(nullptr, MAKEINTRESOURCE(DGL_WINDOWS_ICON_ID)); | |||
| SetClassLongPtr(impl->hwnd, GCLP_HICON, (LONG_PTR) LoadIcon(hInstance, MAKEINTRESOURCE(DGL_WINDOWS_ICON_ID))); | |||
| #endif | |||
| MONITORINFO mInfo; | |||
| std::memset(&mInfo, 0, sizeof(mInfo)); | |||
| mInfo.cbSize = sizeof(mInfo); | |||
| if (GetMonitorInfo(MonitorFromWindow(impl->hwnd, MONITOR_DEFAULTTOPRIMARY), &mInfo)) | |||
| SetWindowPos(impl->hwnd, HWND_TOP, | |||
| mInfo.rcWork.left + (mInfo.rcWork.right - mInfo.rcWork.left - view->frame.width) / 2, | |||
| mInfo.rcWork.top + (mInfo.rcWork.bottom - mInfo.rcWork.top - view->frame.height) / 2, | |||
| mInfo.rcWork.left + (mInfo.rcWork.right - mInfo.rcWork.left - view->lastConfigure.width) / 2, | |||
| mInfo.rcWork.top + (mInfo.rcWork.bottom - mInfo.rcWork.top - view->lastConfigure.height) / 2, | |||
| 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE); | |||
| else | |||
| ShowWindow(impl->hwnd, SW_NORMAL); | |||
| @@ -29,9 +29,26 @@ | |||
| # include <stdint.h> | |||
| #endif | |||
| // hidden api | |||
| // custom attributes | |||
| #define PUGL_ATTRIBUTES_H | |||
| #define PUGL_BEGIN_DECLS | |||
| #define PUGL_END_DECLS | |||
| #define PUGL_API | |||
| #define PUGL_DISABLE_DEPRECATED | |||
| // GCC function attributes | |||
| #if defined(__GNUC__) && !defined(__clang__) | |||
| #define PUGL_CONST_FUNC __attribute__((const)) | |||
| #define PUGL_MALLOC_FUNC __attribute__((malloc)) | |||
| #else | |||
| #define PUGL_CONST_FUNC | |||
| #define PUGL_MALLOC_FUNC | |||
| #endif | |||
| #define PUGL_CONST_API PUGL_CONST_FUNC | |||
| #define PUGL_MALLOC_API PUGL_MALLOC_FUNC | |||
| // we do our own OpenGL inclusion | |||
| #define PUGL_NO_INCLUDE_GL_H | |||
| #define PUGL_NO_INCLUDE_GLU_H | |||
| @@ -39,7 +56,7 @@ | |||
| START_NAMESPACE_DGL | |||
| #endif | |||
| #include "pugl-upstream/include/pugl/pugl.h" | |||
| #include "pugl/pugl.h" | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| @@ -55,9 +72,6 @@ void puglSetMatchingBackendForCurrentBuild(PuglView* view); | |||
| // bring view window into the foreground, aka "raise" window | |||
| void puglRaiseWindow(PuglView* view); | |||
| // get scale factor from parent window if possible, fallback to puglGetScaleFactor | |||
| double puglGetScaleFactorFromParent(const PuglView* view); | |||
| // combined puglSetSizeHint using PUGL_MIN_SIZE, PUGL_MIN_ASPECT and PUGL_MAX_ASPECT | |||
| PuglStatus puglSetGeometryConstraints(PuglView* view, uint width, uint height, bool aspect); | |||
| @@ -248,7 +248,7 @@ uint translateVstKeyCode(bool& special, const int16_t keychar, const int16_t key | |||
| // 18 print | |||
| // 19 \n (handled below) | |||
| // 20 snapshot | |||
| case 22: return kKeyDelete; | |||
| case 22: return kKeyDelete; | |||
| // 23 help | |||
| // 57 = (handled below) | |||
| // numpad stuff follows | |||
| @@ -295,9 +295,9 @@ uint translateVstKeyCode(bool& special, const int16_t keychar, const int16_t key | |||
| case 10: return kKeyHome; | |||
| case 9: return kKeyEnd; | |||
| case 21: return kKeyInsert; | |||
| case 54: return kKeyShift; | |||
| case 55: return kKeyControl; | |||
| case 56: return kKeyAlt; | |||
| case 54: return kKeyShiftL; | |||
| case 55: return kKeyControlL; | |||
| case 56: return kKeyAltL; | |||
| case 58: return kKeyMenu; | |||
| case 52: return kKeyNumLock; | |||
| case 53: return kKeyScrollLock; | |||
| @@ -254,19 +254,22 @@ public: | |||
| switch (key) | |||
| { | |||
| case kKeyShift: | |||
| case kKeyShiftL: | |||
| case kKeyShiftR: | |||
| if (down) | |||
| fKeyboardModifiers |= kModifierShift; | |||
| else | |||
| fKeyboardModifiers &= ~kModifierShift; | |||
| break; | |||
| case kKeyControl: | |||
| case kKeyControlL: | |||
| case kKeyControlR: | |||
| if (down) | |||
| fKeyboardModifiers |= kModifierControl; | |||
| else | |||
| fKeyboardModifiers &= ~kModifierControl; | |||
| break; | |||
| case kKeyAlt: | |||
| case kKeyAltL: | |||
| case kKeyAltR: | |||
| if (down) | |||
| fKeyboardModifiers |= kModifierAlt; | |||
| else | |||
| @@ -167,7 +167,7 @@ private: | |||
| return; | |||
| hasCursor = shouldHaveCursor; | |||
| setCursor(shouldHaveCursor ? kMouseCursorDiagonal : kMouseCursorArrow); | |||
| setCursor(shouldHaveCursor ? kMouseCursorUpLeftDownRight : kMouseCursorArrow); | |||
| } | |||
| void resetArea() | |||