@@ -274,10 +274,10 @@ BASE_OPTS = -O2 -ffast-math -fdata-sections -ffunction-sections | |||
endif | |||
ifeq ($(DEBUG),true) | |||
BASE_FLAGS += -DDEBUG -O0 -g | |||
ifneq ($(HAIKU),true) | |||
BASE_FLAGS += -fsanitize=address | |||
endif | |||
BASE_FLAGS += -DDEBUG -DDPF_DEBUG -O0 -g | |||
# ifneq ($(HAIKU),true) | |||
# BASE_FLAGS += -fsanitize=address | |||
# endif | |||
LINK_OPTS = | |||
ifeq ($(WASM),true) | |||
LINK_OPTS += -sASSERTIONS=1 | |||
@@ -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 | |||
@@ -600,6 +601,14 @@ ifneq ($(WINDOWS_ICON_ID),) | |||
BUILD_CXX_FLAGS += -DDGL_WINDOWS_ICON_ID=$(WINDOWS_ICON_ID) | |||
endif | |||
ifneq ($(X11_WINDOW_ICON_NAME),) | |||
BUILD_CXX_FLAGS += -DDGL_X11_WINDOW_ICON_NAME=$(X11_WINDOW_ICON_NAME) | |||
endif | |||
ifneq ($(X11_WINDOW_ICON_SIZE),) | |||
BUILD_CXX_FLAGS += -DDGL_X11_WINDOW_ICON_SIZE=$(X11_WINDOW_ICON_SIZE) | |||
endif | |||
ifeq ($(USE_GLES2),true) | |||
BUILD_CXX_FLAGS += -DDGL_USE_OPENGL3 -DDGL_USE_GLES -DDGL_USE_GLES2 | |||
endif | |||
@@ -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 | |||
@@ -296,9 +296,9 @@ static = $(TARGET_DIR)/$(NAME).a | |||
ifeq ($(MACOS),true) | |||
BUNDLE_RESOURCES = Info.plist PkgInfo Resources/empty.lproj | |||
vst2files += $(BUNDLE_RESOURCES=%:$(TARGET_DIR)/$(NAME).vst/Contents/%) | |||
vst3files += $(BUNDLE_RESOURCES=%:$(TARGET_DIR)/$(NAME).vst3/Contents/%) | |||
clapfiles += $(BUNDLE_RESOURCES=%:$(TARGET_DIR)/$(NAME).clap/Contents/%) | |||
vst2files += $(BUNDLE_RESOURCES:%=$(TARGET_DIR)/$(NAME).vst/Contents/%) | |||
vst3files += $(BUNDLE_RESOURCES:%=$(TARGET_DIR)/$(NAME).vst3/Contents/%) | |||
clapfiles += $(BUNDLE_RESOURCES:%=$(TARGET_DIR)/$(NAME).clap/Contents/%) | |||
endif | |||
ifneq ($(HAVE_DGL),true) | |||
@@ -380,6 +380,8 @@ function(dpf__build_lv2 NAME HAS_UI MONOLITHIC) | |||
dpf__add_lv2_ttl_generator() | |||
add_dependencies("${NAME}-lv2" lv2_ttl_generator) | |||
separate_arguments(CMAKE_CROSSCOMPILING_EMULATOR) | |||
add_custom_command(TARGET "${NAME}-lv2" POST_BUILD | |||
COMMAND | |||
${CMAKE_CROSSCOMPILING_EMULATOR} | |||
@@ -732,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 | |||
} | |||
@@ -160,17 +160,15 @@ void Application::PrivateData::quit() | |||
double Application::PrivateData::getTime() const | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(world != nullptr, 0.0); | |||
return puglGetTime(world); | |||
return world != nullptr ? puglGetTime(world) : 0.0; | |||
} | |||
void Application::PrivateData::setClassName(const char* const name) | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(world != nullptr,); | |||
DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',); | |||
puglSetClassName(world, name); | |||
if (world != nullptr) | |||
puglSetWorldString(world, PUGL_CLASS_NAME, name); | |||
} | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
@@ -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> | |||
* Copyright (C) 2019-2021 Jean Pierre Cimalando <jp-dev@inbox.ru> | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
@@ -290,7 +290,6 @@ static cairo_format_t asCairoImageFormat(const ImageFormat format) noexcept | |||
case kImageFormatNull: | |||
break; | |||
case kImageFormatGrayscale: | |||
return CAIRO_FORMAT_A8; | |||
case kImageFormatBGR: | |||
case kImageFormatRGB: | |||
return CAIRO_FORMAT_RGB24; | |||
@@ -375,11 +374,13 @@ CairoImage::~CairoImage() | |||
void CairoImage::loadFromMemory(const char* const rdata, const Size<uint>& s, const ImageFormat fmt) noexcept | |||
{ | |||
const cairo_format_t cairoformat = asCairoImageFormat(fmt); | |||
DISTRHO_SAFE_ASSERT_RETURN(cairoformat != CAIRO_FORMAT_INVALID,); | |||
const int width = static_cast<int>(s.getWidth()); | |||
const int height = static_cast<int>(s.getHeight()); | |||
const int stride = cairo_format_stride_for_width(cairoformat, width); | |||
uchar* const newdata = (uchar*)std::malloc(static_cast<size_t>(width * height * stride * 4)); | |||
uchar* const newdata = static_cast<uchar*>(std::malloc(static_cast<size_t>(width * height * stride * 4))); | |||
DISTRHO_SAFE_ASSERT_RETURN(newdata != nullptr,); | |||
cairo_surface_t* const newsurface = cairo_image_surface_create_for_data(newdata, cairoformat, width, height, stride); | |||
@@ -392,19 +393,30 @@ void CairoImage::loadFromMemory(const char* const rdata, const Size<uint>& s, co | |||
if (datarefcount != nullptr && --(*datarefcount) == 0) | |||
std::free(surfacedata); | |||
else | |||
datarefcount = (int*)malloc(sizeof(*datarefcount)); | |||
datarefcount = static_cast<int*>(std::malloc(sizeof(int))); | |||
surface = newsurface; | |||
surfacedata = newdata; | |||
*datarefcount = 1; | |||
const uchar* const urdata = reinterpret_cast<const uchar*>(rdata); | |||
switch (fmt) | |||
{ | |||
case kImageFormatNull: | |||
break; | |||
case kImageFormatGrayscale: | |||
// Grayscale to A8 | |||
// TODO | |||
// Grayscale to CAIRO_FORMAT_RGB24 | |||
for (int h = 0; h < height; ++h) | |||
{ | |||
for (int w = 0; w < width; ++w) | |||
{ | |||
newdata[h*width*4+w*4+0] = urdata[h*width+w]; | |||
newdata[h*width*4+w*4+1] = urdata[h*width+w]; | |||
newdata[h*width*4+w*4+2] = urdata[h*width+w]; | |||
newdata[h*width*4+w*4+3] = 0; | |||
} | |||
} | |||
break; | |||
case kImageFormatBGR: | |||
// BGR8 to CAIRO_FORMAT_RGB24 | |||
@@ -412,42 +424,53 @@ void CairoImage::loadFromMemory(const char* const rdata, const Size<uint>& s, co | |||
{ | |||
for (int w = 0; w < width; ++w) | |||
{ | |||
newdata[h*width*4+w*4+0] = static_cast<uchar>(rdata[h*width*3+w*3+0]); | |||
newdata[h*width*4+w*4+1] = static_cast<uchar>(rdata[h*width*3+w*3+1]); | |||
newdata[h*width*4+w*4+2] = static_cast<uchar>(rdata[h*width*3+w*3+2]); | |||
newdata[h*width*4+w*4+0] = urdata[h*width*3+w*3+0]; | |||
newdata[h*width*4+w*4+1] = urdata[h*width*3+w*3+1]; | |||
newdata[h*width*4+w*4+2] = urdata[h*width*3+w*3+2]; | |||
newdata[h*width*4+w*4+3] = 0; | |||
} | |||
} | |||
break; | |||
case kImageFormatBGRA: | |||
// BGRA8 to CAIRO_FORMAT_ARGB32 | |||
// FIXME something is wrong here... | |||
for (int h = 0, t; h < height; ++h) | |||
for (int h = 0; h < height; ++h) | |||
{ | |||
for (int w = 0; w < width; ++w) | |||
{ | |||
if ((t = rdata[h*width*4+w*4+3]) != 0) | |||
{ | |||
newdata[h*width*4+w*4+0] = static_cast<uchar>(rdata[h*width*4+w*4+0]); | |||
newdata[h*width*4+w*4+1] = static_cast<uchar>(rdata[h*width*4+w*4+1]); | |||
newdata[h*width*4+w*4+2] = static_cast<uchar>(rdata[h*width*4+w*4+2]); | |||
newdata[h*width*4+w*4+3] = static_cast<uchar>(t); | |||
} | |||
else | |||
{ | |||
// make all pixels zero, cairo does not render full transparency otherwise | |||
memset(&newdata[h*width*4+w*4], 0, 4); | |||
} | |||
const uchar a = urdata[h*width*4+w*4+3]; | |||
newdata[h*width*4+w*4+0] = (urdata[h*width*4+w*4+0] * a) >> 8; | |||
newdata[h*width*4+w*4+1] = (urdata[h*width*4+w*4+1] * a) >> 8; | |||
newdata[h*width*4+w*4+2] = (urdata[h*width*4+w*4+2] * a) >> 8; | |||
newdata[h*width*4+w*4+3] = a; | |||
} | |||
} | |||
break; | |||
case kImageFormatRGB: | |||
// RGB8 to CAIRO_FORMAT_RGB24 | |||
// TODO | |||
for (int h = 0; h < height; ++h) | |||
{ | |||
for (int w = 0; w < width; ++w) | |||
{ | |||
newdata[h*width*4+w*4+0] = urdata[h*width*3+w*3+2]; | |||
newdata[h*width*4+w*4+1] = urdata[h*width*3+w*3+1]; | |||
newdata[h*width*4+w*4+2] = urdata[h*width*3+w*3+0]; | |||
newdata[h*width*4+w*4+3] = 0; | |||
} | |||
} | |||
break; | |||
case kImageFormatRGBA: | |||
// RGBA8 to CAIRO_FORMAT_ARGB32 | |||
// TODO | |||
for (int h = 0; h < height; ++h) | |||
{ | |||
for (int w = 0; w < width; ++w) | |||
{ | |||
const uchar a = urdata[h*width*4+w*4+3]; | |||
newdata[h*width*4+w*4+0] = (urdata[h*width*4+w*4+2] * a) >> 8; | |||
newdata[h*width*4+w*4+1] = (urdata[h*width*4+w*4+1] * a) >> 8; | |||
newdata[h*width*4+w*4+2] = (urdata[h*width*4+w*4+0] * a) >> 8; | |||
newdata[h*width*4+w*4+3] = a; | |||
} | |||
} | |||
break; | |||
} | |||
@@ -506,8 +529,7 @@ void CairoImage::loadFromPNG(const char* const pngData, const uint pngSize) noex | |||
void CairoImage::drawAt(const GraphicsContext& context, const Point<int>& pos) | |||
{ | |||
if (surface == nullptr) | |||
return; | |||
DISTRHO_SAFE_ASSERT_RETURN(surface != nullptr,); | |||
cairo_t* const handle = ((const CairoGraphicsContext&)context).handle; | |||
@@ -615,14 +637,9 @@ static int getBytesPerPixel(const cairo_format_t format) noexcept | |||
{ | |||
case CAIRO_FORMAT_ARGB32: | |||
case CAIRO_FORMAT_RGB24: | |||
case CAIRO_FORMAT_RGB30: | |||
return 4; | |||
case CAIRO_FORMAT_RGB16_565: | |||
return 2; | |||
case CAIRO_FORMAT_A8: | |||
return 1; | |||
case CAIRO_FORMAT_A1: | |||
return 0; | |||
default: | |||
DISTRHO_SAFE_ASSERT(false); | |||
return 0; | |||
@@ -632,10 +649,10 @@ static int getBytesPerPixel(const cairo_format_t format) noexcept | |||
static cairo_surface_t* getRegion(cairo_surface_t* origsurface, int x, int y, int width, int height) noexcept | |||
{ | |||
const cairo_format_t format = cairo_image_surface_get_format(origsurface); | |||
const int bpp = getBytesPerPixel(format); | |||
DISTRHO_SAFE_ASSERT_RETURN(format != CAIRO_FORMAT_INVALID, nullptr); | |||
if (bpp == 0) | |||
return nullptr; | |||
const int bpp = getBytesPerPixel(format); | |||
DISTRHO_SAFE_ASSERT_RETURN(bpp != 0, nullptr); | |||
const int fullWidth = cairo_image_surface_get_width(origsurface); | |||
const int fullHeight = cairo_image_surface_get_height(origsurface); | |||
@@ -786,16 +803,12 @@ void TopLevelWidget::PrivateData::display() | |||
cairo_get_matrix(handle, &matrix); | |||
// full viewport size | |||
cairo_translate(handle, 0, 0); | |||
if (window.pData->autoScaling) | |||
{ | |||
cairo_translate(handle, 0, 0); | |||
cairo_scale(handle, autoScaleFactor, autoScaleFactor); | |||
} | |||
else | |||
{ | |||
cairo_translate(handle, 0, 0); | |||
cairo_scale(handle, 1.0, 1.0); | |||
} | |||
// main widget drawing | |||
self->onDisplay(); | |||
@@ -707,26 +707,21 @@ void SubWidget::PrivateData::display(const uint width, const uint height, const | |||
else if (needsFullViewportForDrawing || (absolutePos.isZero() && self->getSize() == Size<uint>(width, height))) | |||
{ | |||
// full viewport size | |||
glViewport(0, | |||
-static_cast<int>(height * autoScaleFactor - height + 0.5), | |||
static_cast<int>(width * autoScaleFactor + 0.5), | |||
static_cast<int>(height * autoScaleFactor + 0.5)); | |||
glViewport(0, 0, static_cast<int>(width), static_cast<int>(height)); | |||
} | |||
else | |||
{ | |||
// set viewport pos | |||
glViewport(static_cast<int>(absolutePos.getX() * autoScaleFactor + 0.5), | |||
-static_cast<int>(std::round((height * autoScaleFactor - height) | |||
+ (absolutePos.getY() * autoScaleFactor))), | |||
static_cast<int>(std::round(width * autoScaleFactor)), | |||
static_cast<int>(std::round(height * autoScaleFactor))); | |||
-static_cast<int>(absolutePos.getY() * autoScaleFactor + 0.5), | |||
static_cast<int>(width), | |||
static_cast<int>(height)); | |||
// then cut the outer bounds | |||
glScissor(static_cast<int>(absolutePos.getX() * autoScaleFactor + 0.5), | |||
static_cast<int>(height - std::round((static_cast<int>(self->getHeight()) + absolutePos.getY()) | |||
* autoScaleFactor)), | |||
static_cast<int>(std::round(self->getWidth() * autoScaleFactor)), | |||
static_cast<int>(std::round(self->getHeight() * autoScaleFactor))); | |||
static_cast<int>(height - (self->getHeight() + absolutePos.getY()) * autoScaleFactor + 0.5), | |||
static_cast<int>(self->getWidth() * autoScaleFactor + 0.5), | |||
static_cast<int>(self->getHeight() * autoScaleFactor + 0.5)); | |||
glEnable(GL_SCISSOR_TEST); | |||
needsDisableScissor = true; | |||
@@ -752,26 +747,14 @@ void TopLevelWidget::PrivateData::display() | |||
const uint width = size.getWidth(); | |||
const uint height = size.getHeight(); | |||
const double autoScaleFactor = window.pData->autoScaleFactor; | |||
// full viewport size | |||
if (window.pData->autoScaling) | |||
{ | |||
glViewport(0, | |||
-static_cast<int>(height * autoScaleFactor - height + 0.5), | |||
static_cast<int>(width * autoScaleFactor + 0.5), | |||
static_cast<int>(height * autoScaleFactor + 0.5)); | |||
} | |||
else | |||
{ | |||
glViewport(0, 0, static_cast<int>(width), static_cast<int>(height)); | |||
} | |||
glViewport(0, 0, static_cast<int>(width), static_cast<int>(height)); | |||
// main widget drawing | |||
self->onDisplay(); | |||
// now draw subwidgets if there are any | |||
selfw->pData->displaySubWidgets(width, height, autoScaleFactor); | |||
selfw->pData->displaySubWidgets(width, height, window.pData->autoScaleFactor); | |||
} | |||
// ----------------------------------------------------------------------- | |||
@@ -135,9 +135,9 @@ bool TopLevelWidget::PrivateData::scrollEvent(const ScrollEvent& ev) | |||
return selfw->pData->giveScrollEventForSubWidgets(rev); | |||
} | |||
void TopLevelWidget::PrivateData::fallbackOnResize() | |||
void TopLevelWidget::PrivateData::fallbackOnResize(const uint width, const uint height) | |||
{ | |||
puglFallbackOnResize(window.pData->view); | |||
puglFallbackOnResize(window.pData->view, width, height); | |||
} | |||
// ----------------------------------------------------------------------- | |||
@@ -38,7 +38,7 @@ struct TopLevelWidget::PrivateData { | |||
bool mouseEvent(const MouseEvent& ev); | |||
bool motionEvent(const MotionEvent& ev); | |||
bool scrollEvent(const ScrollEvent& ev); | |||
void fallbackOnResize(); | |||
void fallbackOnResize(uint width, uint height); | |||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData) | |||
}; | |||
@@ -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 | |||
@@ -27,17 +27,20 @@ START_NAMESPACE_DGL | |||
Window::ScopedGraphicsContext::ScopedGraphicsContext(Window& win) | |||
: window(win), | |||
ppData(nullptr), | |||
active(puglBackendEnter(window.pData->view)), | |||
active(window.pData->view != nullptr && puglBackendEnter(window.pData->view)), | |||
reenter(false) {} | |||
Window::ScopedGraphicsContext::ScopedGraphicsContext(Window& win, Window& transientWin) | |||
: window(win), | |||
ppData(transientWin.pData), | |||
active(false), | |||
reenter(true) | |||
reenter(window.pData->view != nullptr) | |||
{ | |||
puglBackendLeave(ppData->view); | |||
active = puglBackendEnter(window.pData->view); | |||
if (reenter) | |||
{ | |||
puglBackendLeave(ppData->view); | |||
active = puglBackendEnter(window.pData->view); | |||
} | |||
} | |||
Window::ScopedGraphicsContext::~ScopedGraphicsContext() | |||
@@ -162,7 +165,8 @@ void Window::close() | |||
bool Window::isResizable() const noexcept | |||
{ | |||
return puglGetViewHint(pData->view, PUGL_RESIZABLE) == PUGL_TRUE; | |||
return pData->view != nullptr | |||
&& puglGetViewHint(pData->view, PUGL_RESIZABLE) == PUGL_TRUE; | |||
} | |||
void Window::setResizable(const bool resizable) | |||
@@ -204,7 +208,11 @@ void Window::setOffsetY(const int y) | |||
void Window::setOffset(const int x, const int y) | |||
{ | |||
puglSetPosition(pData->view, x, y); | |||
// do not call this for embed windows! | |||
DISTRHO_SAFE_ASSERT_RETURN(!pData->isEmbed,); | |||
if (pData->view != nullptr) | |||
puglSetPosition(pData->view, x, y); | |||
} | |||
void Window::setOffset(const Point<int>& offset) | |||
@@ -302,7 +310,7 @@ void Window::setSize(uint width, uint height) | |||
topLevelWidget->requestSizeChange(width, height); | |||
} | |||
else | |||
else if (pData->view != nullptr) | |||
{ | |||
puglSetSizeAndDefault(pData->view, width, height); | |||
} | |||
@@ -315,23 +323,25 @@ void Window::setSize(const Size<uint>& size) | |||
const char* Window::getTitle() const noexcept | |||
{ | |||
return 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 | |||
{ | |||
return puglGetViewHint(pData->view, PUGL_IGNORE_KEY_REPEAT) == PUGL_TRUE; | |||
return pData->view != nullptr | |||
&& puglGetViewHint(pData->view, PUGL_IGNORE_KEY_REPEAT) == PUGL_TRUE; | |||
} | |||
void Window::setIgnoringKeyRepeat(const bool ignore) noexcept | |||
{ | |||
puglSetViewHint(pData->view, PUGL_IGNORE_KEY_REPEAT, ignore); | |||
if (pData->view != nullptr) | |||
puglSetViewHint(pData->view, PUGL_IGNORE_KEY_REPEAT, ignore); | |||
} | |||
const void* Window::getClipboard(size_t& dataSize) | |||
@@ -341,12 +351,14 @@ const void* Window::getClipboard(size_t& dataSize) | |||
bool Window::setClipboard(const char* const mimeType, const void* const data, const size_t dataSize) | |||
{ | |||
return puglSetClipboard(pData->view, mimeType != nullptr ? mimeType : "text/plain", data, dataSize) == PUGL_SUCCESS; | |||
return pData->view != nullptr | |||
&& puglSetClipboard(pData->view, mimeType != nullptr ? mimeType : "text/plain", data, dataSize) == PUGL_SUCCESS; | |||
} | |||
bool Window::setCursor(const MouseCursor cursor) | |||
{ | |||
return puglSetCursor(pData->view, static_cast<PuglCursor>(cursor)) == PUGL_SUCCESS; | |||
return pData->view != nullptr | |||
&& puglSetCursor(pData->view, static_cast<PuglCursor>(cursor)) == PUGL_SUCCESS; | |||
} | |||
bool Window::addIdleCallback(IdleCallback* const callback, const uint timerFrequencyInMs) | |||
@@ -377,7 +389,7 @@ const GraphicsContext& Window::getGraphicsContext() const noexcept | |||
uintptr_t Window::getNativeWindowHandle() const noexcept | |||
{ | |||
return puglGetNativeView(pData->view); | |||
return pData->view != nullptr ? puglGetNativeView(pData->view) : 0; | |||
} | |||
double Window::getScaleFactor() const noexcept | |||
@@ -399,10 +411,8 @@ bool Window::openFileBrowser(const FileBrowserOptions& options) | |||
void Window::repaint() noexcept | |||
{ | |||
if (pData->view == nullptr) | |||
return; | |||
puglPostRedisplay(pData->view); | |||
if (pData->view != nullptr) | |||
puglPostRedisplay(pData->view); | |||
} | |||
void Window::repaint(const Rectangle<uint>& rect) noexcept | |||
@@ -448,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; | |||
@@ -482,13 +496,17 @@ void Window::setGeometryConstraints(uint minimumWidth, | |||
void Window::setTransientParent(const uintptr_t transientParentWindowHandle) | |||
{ | |||
puglSetTransientParent(pData->view, transientParentWindowHandle); | |||
if (pData->view != nullptr) | |||
puglSetTransientParent(pData->view, transientParentWindowHandle); | |||
} | |||
std::vector<ClipboardDataOffer> Window::getClipboardDataOfferTypes() | |||
{ | |||
std::vector<ClipboardDataOffer> offerTypes; | |||
if (pData->view == nullptr) | |||
return offerTypes; | |||
if (const uint32_t numTypes = puglGetNumClipboardTypes(pData->view)) | |||
{ | |||
offerTypes.reserve(numTypes); | |||
@@ -526,9 +544,10 @@ void Window::onFocus(bool, CrossingMode) | |||
{ | |||
} | |||
void Window::onReshape(uint, uint) | |||
void Window::onReshape(const uint width, const uint height) | |||
{ | |||
puglFallbackOnResize(pData->view); | |||
if (pData->view != nullptr) | |||
puglFallbackOnResize(pData->view, width, height); | |||
} | |||
void Window::onScaleFactorChanged(double) | |||
@@ -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,21 +60,22 @@ 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; | |||
} | |||
static PuglView* puglNewViewWithTransientParent(PuglWorld* const world, PuglView* const transientParentView) | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(world != nullptr, nullptr); | |||
if (world == nullptr) | |||
return nullptr; | |||
if (PuglView* const view = puglNewView(world)) | |||
{ | |||
@@ -79,11 +88,16 @@ static PuglView* puglNewViewWithTransientParent(PuglWorld* const world, PuglView | |||
static PuglView* puglNewViewWithParentWindow(PuglWorld* const world, const uintptr_t parentWindowHandle) | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(world != nullptr, nullptr); | |||
if (world == nullptr) | |||
return nullptr; | |||
if (PuglView* const view = puglNewView(world)) | |||
{ | |||
puglSetParentWindow(view, parentWindowHandle); | |||
if (parentWindowHandle != 0) | |||
puglSetPosition(view, 0, 0); | |||
return view; | |||
} | |||
@@ -102,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), | |||
@@ -113,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); | |||
@@ -142,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); | |||
@@ -162,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), | |||
@@ -173,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); | |||
@@ -194,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), | |||
@@ -205,14 +219,11 @@ 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() | |||
{ | |||
if (isEmbed) | |||
puglSetParentWindow(view, parentWindowHandle); | |||
initPre(width != 0 ? width : DEFAULT_WIDTH, height != 0 ? height : DEFAULT_HEIGHT, resizable); | |||
} | |||
@@ -227,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; | |||
@@ -289,7 +300,7 @@ bool Window::PrivateData::initPost() | |||
if (isEmbed) | |||
{ | |||
appData->oneWindowShown(); | |||
puglShow(view); | |||
puglShow(view, PUGL_SHOW_PASSIVE); | |||
} | |||
return true; | |||
@@ -344,7 +355,7 @@ void Window::PrivateData::show() | |||
#elif defined(DISTRHO_OS_MAC) | |||
puglMacOSShowCentered(view); | |||
#else | |||
puglShow(view); | |||
puglShow(view, PUGL_SHOW_RAISE); | |||
#endif | |||
} | |||
else | |||
@@ -352,7 +363,7 @@ void Window::PrivateData::show() | |||
#ifdef DISTRHO_OS_WINDOWS | |||
puglWin32RestoreWindow(view); | |||
#else | |||
puglShow(view); | |||
puglShow(view, PUGL_SHOW_RAISE); | |||
#endif | |||
} | |||
@@ -433,7 +444,7 @@ void Window::PrivateData::idleCallback() | |||
bool Window::PrivateData::addIdleCallback(IdleCallback* const callback, const uint timerFrequencyInMs) | |||
{ | |||
if (ignoreIdleCallbacks) | |||
if (ignoreIdleCallbacks || view == nullptr) | |||
return false; | |||
if (timerFrequencyInMs == 0) | |||
@@ -447,7 +458,7 @@ bool Window::PrivateData::addIdleCallback(IdleCallback* const callback, const ui | |||
bool Window::PrivateData::removeIdleCallback(IdleCallback* const callback) | |||
{ | |||
if (ignoreIdleCallbacks) | |||
if (ignoreIdleCallbacks || view == nullptr) | |||
return false; | |||
if (std::find(appData->idleCallbacks.begin(), | |||
@@ -472,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), | |||
@@ -574,9 +585,13 @@ void Window::PrivateData::onPuglConfigure(const double width, const double heigh | |||
const double scaleVertical = height / static_cast<double>(minHeight); | |||
autoScaleFactor = scaleHorizontal < scaleVertical ? scaleHorizontal : scaleVertical; | |||
} | |||
else | |||
{ | |||
autoScaleFactor = 1.0; | |||
} | |||
const uint uwidth = static_cast<uint>(width + 0.5); | |||
const uint uheight = static_cast<uint>(height + 0.5); | |||
const uint uwidth = static_cast<uint>(width / autoScaleFactor + 0.5); | |||
const uint uheight = static_cast<uint>(height / autoScaleFactor + 0.5); | |||
self->onReshape(uwidth, uheight); | |||
@@ -880,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) | |||
@@ -954,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) | |||
@@ -969,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; | |||
@@ -987,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,19 +603,28 @@ 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 | |||
const int width = EM_ASM_INT({ | |||
var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; | |||
canvasWrapper.style.setProperty("--device-pixel-ratio", window.devicePixelRatio); | |||
return canvasWrapper.clientWidth; | |||
}, className); | |||
if ($1) { | |||
return window.innerWidth; | |||
} else { | |||
return canvasWrapper.clientWidth; | |||
} | |||
}, className, isFullscreen); | |||
const int height = EM_ASM_INT({ | |||
var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; | |||
return canvasWrapper.clientHeight; | |||
}, className); | |||
if ($1) { | |||
return window.innerHeight; | |||
} else { | |||
var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; | |||
return canvasWrapper.clientHeight; | |||
} | |||
}, className, isFullscreen); | |||
if (!width || !height) | |||
return EM_FALSE; | |||
@@ -627,13 +636,24 @@ 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) { | |||
EM_ASM({ | |||
document.getElementById("pedalboard-dashboard").style.transform = "scale(1.0)"; | |||
}); | |||
} | |||
#endif | |||
return EM_TRUE; | |||
} | |||
@@ -648,29 +668,36 @@ puglFullscreenChangeCallback(const int eventType, const EmscriptenFullscreenChan | |||
#ifdef __MOD_DEVICES__ | |||
scaleFactor *= MOD_SCALE_FACTOR_MULT; | |||
#endif | |||
view->world->impl->scaleFactor = scaleFactor; | |||
if (fscEvent->isFullscreen) { | |||
PuglEvent event = {{PUGL_CONFIGURE, 0}}; | |||
event.configure.x = 0; | |||
event.configure.y = 0; | |||
event.configure.width = fscEvent->elementWidth * scaleFactor; | |||
event.configure.height = fscEvent->elementHeight * scaleFactor; | |||
puglDispatchEvent(view, &event); | |||
if (!fscEvent->isFullscreen) | |||
return puglUiCallback(0, NULL, userData); | |||
const int width = EM_ASM_INT({ | |||
return window.innerWidth; | |||
}); | |||
const int height = EM_ASM_INT({ | |||
return window.innerHeight; | |||
}); | |||
emscripten_set_canvas_element_size(view->world->className, | |||
fscEvent->elementWidth * scaleFactor, | |||
fscEvent->elementHeight * scaleFactor); | |||
PuglEvent event = {{PUGL_CONFIGURE, 0}}; | |||
event.configure.x = 0; | |||
event.configure.y = 0; | |||
event.configure.width = width; | |||
event.configure.height = height; | |||
puglDispatchEvent(view, &event); | |||
emscripten_set_canvas_element_size(view->world->strings[PUGL_CLASS_NAME], width, height); | |||
#ifdef __MOD_DEVICES__ | |||
EM_ASM({ | |||
document.getElementById("pedalboard-dashboard").style.transform = "scale(1.0)"; | |||
}); | |||
EM_ASM({ | |||
document.getElementById("pedalboard-dashboard").style.transform = "scale(1.0)"; | |||
}); | |||
#endif | |||
return EM_TRUE; | |||
} | |||
return puglUiCallback(0, NULL, userData); | |||
return EM_TRUE; | |||
} | |||
static EM_BOOL | |||
@@ -678,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; | |||
} | |||
@@ -701,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 | |||
@@ -721,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); | |||
@@ -769,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); | |||
} | |||
@@ -779,7 +800,7 @@ puglShow(PuglView* const view) | |||
PuglStatus | |||
puglHide(PuglView* const view) | |||
{ | |||
view->visible = false; | |||
view->impl->visible = false; | |||
return PUGL_FAILURE; | |||
} | |||
@@ -839,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; | |||
} | |||
@@ -852,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); | |||
} | |||
@@ -883,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; | |||
} | |||
@@ -1072,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 | |||
@@ -1135,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,3 +1,6 @@ | |||
# Copyright 2020-2022 David Robillard <d@drobilla.net> | |||
# SPDX-License-Identifier: 0BSD OR ISC | |||
--- | |||
AlignConsecutiveAssignments: true | |||
AlignConsecutiveDeclarations: true | |||
@@ -0,0 +1,19 @@ | |||
# Copyright 2020-2022 David Robillard <d@drobilla.net> | |||
# SPDX-License-Identifier: 0BSD OR ISC | |||
Checks: > | |||
*, | |||
-*-magic-numbers, | |||
-altera*, | |||
-bugprone-assignment-in-if-condition, | |||
-clang-diagnostic-unused-function, | |||
-clang-diagnostic-unused-macros, | |||
-llvmlibc-*, | |||
-readability-identifier-length, | |||
CheckOptions: | |||
- key: hicpp-uppercase-literal-suffix.NewSuffixes | |||
value: L;U;f | |||
- key: readability-uppercase-literal-suffix.NewSuffixes | |||
value: L;U;f | |||
FormatStyle: file | |||
HeaderFilterRegex: 'pugl/.*' |
@@ -1,3 +1,10 @@ | |||
build/ | |||
__pycache__ | |||
# Copyright 2021-2023 David Robillard <d@drobilla.net> | |||
# SPDX-License-Identifier: 0BSD OR ISC | |||
*.pyc | |||
.meson-subproject-wrap-hash.txt | |||
__pycache__ | |||
build/ | |||
subprojects/packagecache/ | |||
subprojects/sphinxygen-1.0.0/ | |||
subprojects/sphinxygen/ |
@@ -1,137 +1,105 @@ | |||
stages: | |||
- build | |||
- deploy | |||
# Copyright 2018-2022 David Robillard <d@drobilla.net> | |||
# SPDX-License-Identifier: 0BSD OR ISC | |||
.build_template: &build_definition | |||
stage: build | |||
arm32_dbg: | |||
<<: *build_definition | |||
image: lv2plugin/debian-arm32 | |||
script: | |||
- meson setup build --cross-file=/usr/share/meson/cross/arm-linux-gnueabihf.ini -Dbuildtype=debug -Ddocs=disabled -Dstrict=true -Dwerror=true | |||
- ninja -C build | |||
arm32_rel: | |||
<<: *build_definition | |||
image: lv2plugin/debian-arm32 | |||
script: | |||
- meson setup build --cross-file=/usr/share/meson/cross/arm-linux-gnueabihf.ini -Dbuildtype=release -Ddocs=disabled -Dstrict=true -Dwerror=true | |||
- ninja -C build | |||
arm64_dbg: | |||
<<: *build_definition | |||
image: lv2plugin/debian-arm64 | |||
script: | |||
- meson setup build --cross-file=/usr/share/meson/cross/aarch64-linux-gnu.ini -Dbuildtype=debug -Ddocs=disabled -Dstrict=true -Dwerror=true | |||
- ninja -C build | |||
stages: [build, deploy] | |||
arm64_rel: | |||
<<: *build_definition | |||
image: lv2plugin/debian-arm64 | |||
default: | |||
stage: build | |||
image: lv2plugin/debian-x64 | |||
script: | |||
- meson setup build --cross-file=/usr/share/meson/cross/aarch64-linux-gnu.ini -Dbuildtype=release -Ddocs=disabled -Dstrict=true -Dwerror=true | |||
- meson setup build -Dwerror=true | |||
- ninja -C build | |||
x64_dbg: | |||
<<: *build_definition | |||
dev: | |||
stage: build | |||
image: lv2plugin/debian-x64 | |||
script: | |||
- meson setup build -Dbuildtype=debug -Ddocs=enabled -Dstrict=true -Dwerror=true | |||
- meson setup build -Dbuildtype=debug -Ddocs=enabled -Ddocs_cpp=false -Dwarning_level=3 -Dwerror=true -Dlint=true | |||
- ninja -C build | |||
- meson configure -Dbuildtype=release build | |||
- ninja -C build | |||
artifacts: | |||
paths: | |||
- build/doc | |||
x64_rel: | |||
<<: *build_definition | |||
static: | |||
stage: build | |||
image: lv2plugin/debian-x64 | |||
script: | |||
- meson setup build -Dbuildtype=release -Ddocs=disabled -Dstrict=true -Dwerror=true | |||
- meson setup build -Ddefault_library=static -Ddocs=disabled -Dwarning_level=3 -Dwerror=true | |||
- ninja -C build | |||
x64_static: | |||
<<: *build_definition | |||
image: lv2plugin/debian-x64 | |||
script: | |||
- meson setup build -Ddefault_library=static -Ddocs=disabled -Dstrict=true -Dwerror=true | |||
- meson configure -Dbuildtype=release build | |||
- ninja -C build | |||
# Linux Platforms | |||
x64_sanitize: | |||
<<: *build_definition | |||
image: lv2plugin/debian-x64-clang | |||
arm32: | |||
stage: build | |||
image: lv2plugin/debian-arm32 | |||
script: | |||
- meson setup build -Db_lundef=false -Dbuildtype=plain -Ddocs=disabled -Dstrict=true -Dwerror=true | |||
- meson setup build --cross-file=/usr/share/meson/cross/arm-linux-gnueabihf.ini -Dbuildtype=debug -Ddocs=disabled -Dwarning_level=3 -Dwerror=true | |||
- ninja -C build | |||
- meson configure -Dbuildtype=release build | |||
- ninja -C build | |||
variables: | |||
CC: "clang" | |||
CXX: "clang++" | |||
CFLAGS: "-fno-sanitize-recover=all -fsanitize=address -fsanitize=undefined -fsanitize=float-divide-by-zero -fsanitize=unsigned-integer-overflow -fsanitize=implicit-conversion -fsanitize=local-bounds -fsanitize=nullability" | |||
CXXFLAGS: "-fno-sanitize-recover=all -fsanitize=address -fsanitize=undefined -fsanitize=float-divide-by-zero -fsanitize=unsigned-integer-overflow -fsanitize=implicit-conversion -fsanitize=local-bounds -fsanitize=nullability" | |||
LDFLAGS: "-fno-sanitize-recover=all -fsanitize=address -fsanitize=undefined -fsanitize=float-divide-by-zero -fsanitize=unsigned-integer-overflow -fsanitize=implicit-conversion -fsanitize=local-bounds -fsanitize=nullability" | |||
mingw32_dbg: | |||
<<: *build_definition | |||
image: lv2plugin/debian-mingw32 | |||
arm64: | |||
stage: build | |||
image: lv2plugin/debian-arm64 | |||
script: | |||
- meson setup build --cross-file=/usr/share/meson/cross/i686-w64-mingw32.ini -Dbuildtype=debug -Ddocs=disabled -Dstrict=true -Dwerror=true | |||
- meson setup build --cross-file=/usr/share/meson/cross/aarch64-linux-gnu.ini -Dbuildtype=debug -Ddocs=disabled -Dwarning_level=3 -Dwerror=true | |||
- ninja -C build | |||
- meson configure -Dbuildtype=release build | |||
- ninja -C build | |||
mingw32_rel: | |||
<<: *build_definition | |||
mingw32: | |||
stage: build | |||
image: lv2plugin/debian-mingw32 | |||
script: | |||
- meson setup build --cross-file=/usr/share/meson/cross/i686-w64-mingw32.ini -Dbuildtype=release -Ddocs=disabled -Dstrict=true -Dwerror=true | |||
- meson setup build --cross-file=/usr/share/meson/cross/i686-w64-mingw32.ini -Dbuildtype=debug -Ddocs=disabled -Dwarning_level=everything -Dwerror=true | |||
- ninja -C build | |||
mingw64_dbg: | |||
<<: *build_definition | |||
image: lv2plugin/debian-mingw64 | |||
script: | |||
- meson setup build --cross-file=/usr/share/meson/cross/x86_64-w64-mingw32.ini -Dbuildtype=debug -Ddocs=disabled -Dstrict=true -Dwerror=true | |||
- meson configure -Dbuildtype=release build | |||
- ninja -C build | |||
variables: | |||
WINEPATH: "Z:\\usr\\lib\\gcc\\i686-w64-mingw32\\10-win32" | |||
mingw64_rel: | |||
<<: *build_definition | |||
mingw64: | |||
stage: build | |||
image: lv2plugin/debian-mingw64 | |||
script: | |||
- meson setup build --cross-file=/usr/share/meson/cross/x86_64-w64-mingw32.ini -Dbuildtype=release -Ddocs=disabled -Dstrict=true -Dwerror=true | |||
- meson setup build --cross-file=/usr/share/meson/cross/x86_64-w64-mingw32.ini -Dbuildtype=debug -Ddocs=disabled -Dwarning_level=everything -Dwerror=true | |||
- ninja -C build | |||
- meson configure -Dbuildtype=release build | |||
- ninja -C build | |||
# Linux Distributions | |||
mac_dbg: | |||
<<: *build_definition | |||
tags: [macos] | |||
fedora: | |||
stage: build | |||
image: lv2plugin/fedora-big | |||
script: | |||
- meson setup build -Dbuildtype=debug -Ddocs=disabled -Dstrict=true -Dwerror=true | |||
- meson setup build -Dbuildtype=plain -Dwarning_level=3 -Dwerror=true | |||
- ninja -C build | |||
variables: | |||
CFLAGS: -O2 -D_FORTIFY_SOURCE=2 | |||
# Non-Linux/Docker rows (not hosted) | |||
mac_rel: | |||
<<: *build_definition | |||
mac: | |||
stage: build | |||
tags: [macos] | |||
script: | |||
- meson setup build -Dbuildtype=release -Ddocs=disabled -Dstrict=true -Dwerror=true | |||
- meson setup build -Dbuildtype=debug -Ddocs=disabled -Dwarning_level=everything -Dwerror=true | |||
- ninja -C build | |||
win_dbg: | |||
<<: *build_definition | |||
tags: [windows,meson] | |||
script: | |||
- meson setup build -Dbuildtype=debug -Ddocs=disabled -Dstrict=true -Dwerror=true | |||
- meson configure -Dbuildtype=release build | |||
- ninja -C build | |||
win_rel: | |||
<<: *build_definition | |||
win: | |||
stage: build | |||
tags: [windows,meson] | |||
script: | |||
- meson setup build -Dbuildtype=release -Ddocs=disabled -Dstrict=true -Dwerror=true | |||
- meson setup build -Dbuildtype=debug -Ddocs=disabled -Dwarning_level=everything -Dwerror=true | |||
- ninja -C build | |||
- meson configure -Dbuildtype=release build | |||
- ninja -C build | |||
pages: | |||
@@ -141,13 +109,11 @@ pages: | |||
- mkdir public/c | |||
- mkdir public/cpp | |||
- mv build/doc/c/singlehtml/ public/c/singlehtml/ | |||
- mv build/doc/cpp/singlehtml/ public/cpp/singlehtml/ | |||
- mv build/doc/c/html/ public/c/html/ | |||
- mv build/doc/cpp/html/ public/cpp/html/ | |||
dependencies: | |||
- x64_dbg | |||
needs: | |||
- dev | |||
artifacts: | |||
paths: | |||
- public | |||
only: | |||
- master | |||
- main |
@@ -3,14 +3,26 @@ Upstream-Name: pugl | |||
Upstream-Contact: David Robillard <d@drobilla.net> | |||
Source: https://gitlab.com/lv2/pugl | |||
Files: **/meson.build *.md */.clang* .clang* .clant.json .editorconfig .git* .includes.imp AUTHORS doc/*.in meson_options.txt resources/Info.plist.in | |||
Files: *.md .clant.json .editorconfig .includes.imp | |||
Copyright: 2021 David Robillard <d@drobilla.net> | |||
License: CC0-1.0 OR ISC | |||
Comment: Contributed to the Commons as a tool configuration | |||
License: 0BSD OR ISC | |||
Files: doc/*.rst examples/glad/glad.c examples/glad/glad.h resources/pugl.ipe resources/pugl.png resources/pugl.svg | |||
Copyright: 2021 David Robillard <d@drobilla.net> | |||
Files: AUTHORS resources/Info.plist.in | |||
Copyright: 2012-2022 David Robillard <d@drobilla.net> | |||
Comment: Contributed to the Commons as a representation of simple facts | |||
License: 0BSD OR ISC | |||
Files: examples/glad/glad.c examples/glad/glad.h | |||
Copyright: 2019 David Robillard <d@drobilla.net> | |||
Comment: Generated code | |||
License: ISC | |||
Files: examples/glad/khrplatform.h | |||