pugl.cpp (22921B)
1 /* 2 * DISTRHO Plugin Framework (DPF) 3 * Copyright (C) 2012-2024 Filipe Coelho <falktx@falktx.com> 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any purpose with 6 * or without fee is hereby granted, provided that the above copyright notice and this 7 * permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD 10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN 11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "pugl.hpp" 18 19 // -------------------------------------------------------------------------------------------------------------------- 20 // include base headers 21 22 #ifdef DGL_CAIRO 23 # include <cairo.h> 24 #endif 25 #ifdef DGL_OPENGL 26 # include "../OpenGL-include.hpp" 27 #endif 28 #ifdef DGL_VULKAN 29 # include <vulkan/vulkan_core.h> 30 #endif 31 32 /* we will include all header files used in pugl in their C++ friendly form, then pugl stuff in custom namespace */ 33 #include <cassert> 34 #include <cmath> 35 #include <cstdlib> 36 #include <cstdio> 37 #include <cstring> 38 #include <ctime> 39 40 #if defined(DISTRHO_OS_HAIKU) 41 # include <Application.h> 42 # include <Window.h> 43 # ifdef DGL_OPENGL 44 # include <GL/gl.h> 45 # include <opengl/GLView.h> 46 # endif 47 #elif defined(DISTRHO_OS_MAC) 48 # import <Cocoa/Cocoa.h> 49 # include <dlfcn.h> 50 # include <mach/mach_time.h> 51 # ifdef DGL_CAIRO 52 # include <cairo-quartz.h> 53 # endif 54 # ifdef DGL_VULKAN 55 # import <QuartzCore/CAMetalLayer.h> 56 # include <vulkan/vulkan_macos.h> 57 # endif 58 #elif defined(DISTRHO_OS_WASM) 59 # include <emscripten/emscripten.h> 60 # include <emscripten/html5.h> 61 # ifdef DGL_OPENGL 62 # include <EGL/egl.h> 63 # endif 64 #elif defined(DISTRHO_OS_WINDOWS) 65 # include <wctype.h> 66 # include <winsock2.h> 67 # include <windows.h> 68 # include <windowsx.h> 69 # ifdef DGL_CAIRO 70 # include <cairo-win32.h> 71 # endif 72 # ifdef DGL_OPENGL 73 # include <GL/gl.h> 74 # endif 75 # ifdef DGL_VULKAN 76 # include <vulkan/vulkan.h> 77 # include <vulkan/vulkan_win32.h> 78 # endif 79 #elif defined(HAVE_X11) 80 # include <dlfcn.h> 81 # include <limits.h> 82 # include <unistd.h> 83 # include <sys/select.h> 84 // # include <sys/time.h> 85 # include <X11/X.h> 86 # include <X11/Xatom.h> 87 # include <X11/Xlib.h> 88 # include <X11/Xresource.h> 89 # include <X11/Xutil.h> 90 # include <X11/keysym.h> 91 # ifdef HAVE_XCURSOR 92 # include <X11/Xcursor/Xcursor.h> 93 // # include <X11/cursorfont.h> 94 # endif 95 # ifdef HAVE_XRANDR 96 # include <X11/extensions/Xrandr.h> 97 # endif 98 # ifdef HAVE_XSYNC 99 # include <X11/extensions/sync.h> 100 # include <X11/extensions/syncconst.h> 101 # endif 102 # ifdef DGL_CAIRO 103 # include <cairo-xlib.h> 104 # endif 105 # ifdef DGL_OPENGL 106 # include <GL/glx.h> 107 # endif 108 # ifdef DGL_VULKAN 109 # include <vulkan/vulkan_xlib.h> 110 # endif 111 #endif 112 113 #ifndef DGL_FILE_BROWSER_DISABLED 114 # define FILE_BROWSER_DIALOG_DGL_NAMESPACE 115 # define FILE_BROWSER_DIALOG_NAMESPACE DGL_NAMESPACE 116 # define DGL_FILE_BROWSER_DIALOG_HPP_INCLUDED 117 START_NAMESPACE_DGL 118 # include "../../distrho/extra/FileBrowserDialogImpl.hpp" 119 END_NAMESPACE_DGL 120 # include "../../distrho/extra/FileBrowserDialogImpl.cpp" 121 #endif 122 123 #if defined(DGL_USING_X11) && defined(DGL_X11_WINDOW_ICON_NAME) 124 extern const ulong* DGL_X11_WINDOW_ICON_NAME; 125 #endif 126 127 #ifndef DISTRHO_OS_MAC 128 START_NAMESPACE_DGL 129 #endif 130 131 // -------------------------------------------------------------------------------------------------------------------- 132 133 #if defined(DISTRHO_OS_HAIKU) 134 # include "pugl-extra/haiku.cpp" 135 # include "pugl-extra/haiku_stub.cpp" 136 # ifdef DGL_OPENGL 137 # include "pugl-extra/haiku_gl.cpp" 138 # endif 139 #elif defined(DISTRHO_OS_MAC) 140 # ifndef DISTRHO_MACOS_NAMESPACE_MACRO 141 # ifndef DISTRHO_MACOS_NAMESPACE_TIME 142 # define DISTRHO_MACOS_NAMESPACE_TIME __apple_build_version__ 143 # endif 144 # define DISTRHO_MACOS_NAMESPACE_MACRO_HELPER(NS, SEP, TIME, INTERFACE) NS ## SEP ## TIME ## SEP ## INTERFACE 145 # define DISTRHO_MACOS_NAMESPACE_MACRO(NS, TIME, INTERFACE) DISTRHO_MACOS_NAMESPACE_MACRO_HELPER(NS, _, TIME, INTERFACE) 146 # define PuglCairoView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, DISTRHO_MACOS_NAMESPACE_TIME, PuglCairoView) 147 # define PuglOpenGLView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, DISTRHO_MACOS_NAMESPACE_TIME, PuglOpenGLView) 148 # define PuglStubView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, DISTRHO_MACOS_NAMESPACE_TIME, PuglStubView) 149 # define PuglVulkanView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, DISTRHO_MACOS_NAMESPACE_TIME, PuglVulkanView) 150 # define PuglWindow DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, DISTRHO_MACOS_NAMESPACE_TIME, PuglWindow) 151 # define PuglWindowDelegate DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, DISTRHO_MACOS_NAMESPACE_TIME, PuglWindowDelegate) 152 # define PuglWrapperView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, DISTRHO_MACOS_NAMESPACE_TIME, PuglWrapperView) 153 # endif 154 # pragma clang diagnostic push 155 # pragma clang diagnostic ignored "-Wdeprecated-declarations" 156 # import "pugl-upstream/src/mac.m" 157 # import "pugl-upstream/src/mac_stub.m" 158 # ifdef DGL_CAIRO 159 # import "pugl-upstream/src/mac_cairo.m" 160 # endif 161 # ifdef DGL_OPENGL 162 # import "pugl-upstream/src/mac_gl.m" 163 # endif 164 # ifdef DGL_VULKAN 165 # import "pugl-upstream/src/mac_vulkan.m" 166 # endif 167 # pragma clang diagnostic pop 168 #elif defined(DISTRHO_OS_WASM) 169 # include "pugl-extra/wasm.c" 170 # include "pugl-extra/wasm_stub.c" 171 # ifdef DGL_OPENGL 172 # include "pugl-extra/wasm_gl.c" 173 # endif 174 #elif defined(DISTRHO_OS_WINDOWS) 175 # include "pugl-upstream/src/win.c" 176 # include "pugl-upstream/src/win_stub.c" 177 # ifdef DGL_CAIRO 178 # include "pugl-upstream/src/win_cairo.c" 179 # endif 180 # ifdef DGL_OPENGL 181 # include "pugl-upstream/src/win_gl.c" 182 # endif 183 # ifdef DGL_VULKAN 184 # include "pugl-upstream/src/win_vulkan.c" 185 # endif 186 #elif defined(HAVE_X11) 187 # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) 188 # pragma GCC diagnostic push 189 # pragma GCC diagnostic ignored "-Wsign-conversion" 190 # endif 191 # include "pugl-upstream/src/x11.c" 192 # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) 193 # pragma GCC diagnostic pop 194 # endif 195 # include "pugl-upstream/src/x11_stub.c" 196 # ifdef DGL_CAIRO 197 # include "pugl-upstream/src/x11_cairo.c" 198 # endif 199 # ifdef DGL_OPENGL 200 # include "pugl-upstream/src/x11_gl.c" 201 # endif 202 # ifdef DGL_VULKAN 203 # include "pugl-upstream/src/x11_vulkan.c" 204 # endif 205 #endif 206 207 #include "pugl-upstream/src/common.c" 208 #include "pugl-upstream/src/internal.c" 209 210 // -------------------------------------------------------------------------------------------------------------------- 211 // DGL specific, expose backend enter 212 213 bool puglBackendEnter(PuglView* const view) 214 { 215 return view->backend->enter(view, nullptr) == PUGL_SUCCESS; 216 } 217 218 // -------------------------------------------------------------------------------------------------------------------- 219 // DGL specific, expose backend leave 220 221 bool puglBackendLeave(PuglView* const view) 222 { 223 return view->backend->leave(view, nullptr) == PUGL_SUCCESS; 224 } 225 226 // -------------------------------------------------------------------------------------------------------------------- 227 // DGL specific, assigns backend that matches current DGL build 228 229 void puglSetMatchingBackendForCurrentBuild(PuglView* const view) 230 { 231 #ifdef DGL_CAIRO 232 puglSetBackend(view, puglCairoBackend()); 233 #endif 234 #ifdef DGL_OPENGL 235 puglSetBackend(view, puglGlBackend()); 236 #endif 237 #ifdef DGL_VULKAN 238 puglSetBackend(view, puglVulkanBackend()); 239 #endif 240 241 if (view->backend != nullptr) 242 { 243 #ifdef DGL_OPENGL 244 #if defined(DGL_USE_GLES2) 245 puglSetViewHint(view, PUGL_CONTEXT_API, PUGL_OPENGL_ES_API); 246 puglSetViewHint(view, PUGL_CONTEXT_PROFILE, PUGL_OPENGL_CORE_PROFILE); 247 puglSetViewHint(view, PUGL_CONTEXT_VERSION_MAJOR, 2); 248 #elif defined(DGL_USE_OPENGL3) 249 puglSetViewHint(view, PUGL_CONTEXT_API, PUGL_OPENGL_API); 250 puglSetViewHint(view, PUGL_CONTEXT_PROFILE, PUGL_OPENGL_CORE_PROFILE); 251 puglSetViewHint(view, PUGL_CONTEXT_VERSION_MAJOR, 3); 252 #else 253 puglSetViewHint(view, PUGL_CONTEXT_API, PUGL_OPENGL_API); 254 puglSetViewHint(view, PUGL_CONTEXT_PROFILE, PUGL_OPENGL_COMPATIBILITY_PROFILE); 255 puglSetViewHint(view, PUGL_CONTEXT_VERSION_MAJOR, 2); 256 #endif 257 #endif 258 } 259 else 260 { 261 puglSetBackend(view, puglStubBackend()); 262 } 263 } 264 265 // -------------------------------------------------------------------------------------------------------------------- 266 // bring view window into the foreground, aka "raise" window 267 268 void puglRaiseWindow(PuglView* const view) 269 { 270 #if defined(DISTRHO_OS_HAIKU) 271 #elif defined(DISTRHO_OS_MAC) 272 if (NSWindow* const window = view->impl->window ? view->impl->window 273 : [view->impl->wrapperView window]) 274 [window orderFrontRegardless]; 275 #elif defined(DISTRHO_OS_WASM) 276 // nothing 277 #elif defined(DISTRHO_OS_WINDOWS) 278 SetForegroundWindow(view->impl->hwnd); 279 SetActiveWindow(view->impl->hwnd); 280 #elif defined(HAVE_X11) 281 XRaiseWindow(view->world->impl->display, view->impl->win); 282 #endif 283 } 284 285 // -------------------------------------------------------------------------------------------------------------------- 286 // Combined puglSetSizeHint using PUGL_MIN_SIZE and PUGL_FIXED_ASPECT 287 288 PuglStatus puglSetGeometryConstraints(PuglView* const view, const uint width, const uint height, const bool aspect) 289 { 290 view->sizeHints[PUGL_MIN_SIZE].width = static_cast<PuglSpan>(width); 291 view->sizeHints[PUGL_MIN_SIZE].height = static_cast<PuglSpan>(height); 292 293 if (aspect) 294 { 295 view->sizeHints[PUGL_FIXED_ASPECT].width = static_cast<PuglSpan>(width); 296 view->sizeHints[PUGL_FIXED_ASPECT].height = static_cast<PuglSpan>(height); 297 } 298 299 #if defined(DISTRHO_OS_HAIKU) 300 #elif defined(DISTRHO_OS_MAC) 301 if (view->impl->window) 302 { 303 if (const PuglStatus status = updateSizeHint(view, PUGL_MIN_SIZE)) 304 return status; 305 306 if (const PuglStatus status = updateSizeHint(view, PUGL_FIXED_ASPECT)) 307 return status; 308 } 309 #elif defined(DISTRHO_OS_WASM) 310 // nothing 311 #elif defined(DISTRHO_OS_WINDOWS) 312 // nothing 313 #elif defined(HAVE_X11) 314 if (view->impl->win) 315 { 316 if (const PuglStatus status = updateSizeHints(view)) 317 return status; 318 319 XFlush(view->world->impl->display); 320 } 321 #endif 322 323 return PUGL_SUCCESS; 324 } 325 326 // -------------------------------------------------------------------------------------------------------------------- 327 // set view as resizable (or not) during runtime 328 329 void puglSetResizable(PuglView* const view, const bool resizable) 330 { 331 puglSetViewHint(view, PUGL_RESIZABLE, resizable ? PUGL_TRUE : PUGL_FALSE); 332 333 #if defined(DISTRHO_OS_HAIKU) 334 #elif defined(DISTRHO_OS_MAC) 335 if (PuglWindow* const window = view->impl->window) 336 { 337 const uint style = (NSClosableWindowMask | NSTitledWindowMask | NSMiniaturizableWindowMask) 338 | (resizable ? NSResizableWindowMask : 0x0); 339 [window setStyleMask:style]; 340 } 341 // FIXME use [view setAutoresizingMask:NSViewNotSizable] ? 342 #elif defined(DISTRHO_OS_WASM) 343 // nothing 344 #elif defined(DISTRHO_OS_WINDOWS) 345 if (const HWND hwnd = view->impl->hwnd) 346 { 347 const uint winFlags = resizable ? GetWindowLong(hwnd, GWL_STYLE) | (WS_SIZEBOX | WS_MAXIMIZEBOX) 348 : GetWindowLong(hwnd, GWL_STYLE) & ~(WS_SIZEBOX | WS_MAXIMIZEBOX); 349 SetWindowLong(hwnd, GWL_STYLE, winFlags); 350 } 351 #elif defined(HAVE_X11) 352 updateSizeHints(view); 353 #endif 354 } 355 356 // -------------------------------------------------------------------------------------------------------------------- 357 // set window size while also changing default 358 359 PuglStatus puglSetSizeAndDefault(PuglView* view, uint width, uint height) 360 { 361 if (width > INT16_MAX || height > INT16_MAX) 362 return PUGL_BAD_PARAMETER; 363 364 #ifdef DGL_USING_X11 365 // workaround issues in fluxbox, see https://github.com/lv2/pugl/issues/118 366 if (view->impl->win && !view->parent && !view->transientParent) 367 { 368 view->sizeHints[PUGL_DEFAULT_SIZE].width = view->sizeHints[PUGL_DEFAULT_SIZE].height = 0; 369 } 370 else 371 #endif 372 // set default size first 373 { 374 view->sizeHints[PUGL_DEFAULT_SIZE].width = static_cast<PuglSpan>(width); 375 view->sizeHints[PUGL_DEFAULT_SIZE].height = static_cast<PuglSpan>(height); 376 } 377 378 #if defined(DISTRHO_OS_HAIKU) 379 #elif defined(DISTRHO_OS_MAC) 380 // matches upstream pugl 381 if (view->impl->wrapperView) 382 { 383 if (const PuglStatus status = puglSetSize(view, width, height)) 384 return status; 385 386 // nothing to do for PUGL_DEFAULT_SIZE hint 387 } 388 #elif defined(DISTRHO_OS_WASM) 389 d_stdout("className is %s", view->world->strings[PUGL_CLASS_NAME]); 390 emscripten_set_canvas_element_size(view->world->strings[PUGL_CLASS_NAME], width, height); 391 #elif defined(DISTRHO_OS_WINDOWS) 392 // matches upstream pugl, except we re-enter context after resize 393 if (view->impl->hwnd) 394 { 395 if (const PuglStatus status = puglSetSize(view, width, height)) 396 return status; 397 398 // nothing to do for PUGL_DEFAULT_SIZE hint 399 400 // make sure to return context back to ourselves 401 puglBackendEnter(view); 402 } 403 #elif defined(HAVE_X11) 404 // matches upstream pugl, adds flush at the end 405 if (view->impl->win) 406 { 407 if (const PuglStatus status = puglSetSize(view, width, height)) 408 return status; 409 410 // updateSizeHints will use last known size, which is not yet updated 411 const PuglSpan lastWidth = view->lastConfigure.width; 412 const PuglSpan lastHeight = view->lastConfigure.height; 413 view->lastConfigure.width = static_cast<PuglSpan>(width); 414 view->lastConfigure.height = static_cast<PuglSpan>(height); 415 416 updateSizeHints(view); 417 418 view->lastConfigure.width = lastWidth; 419 view->lastConfigure.height = lastHeight; 420 421 // flush size changes 422 XFlush(view->world->impl->display); 423 } 424 #endif 425 426 return PUGL_SUCCESS; 427 } 428 429 // -------------------------------------------------------------------------------------------------------------------- 430 // DGL specific, build-specific drawing prepare 431 432 void puglOnDisplayPrepare(PuglView*) 433 { 434 #ifdef DGL_OPENGL 435 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 436 #ifndef DGL_USE_OPENGL3 437 glLoadIdentity(); 438 #endif 439 #endif 440 } 441 442 // -------------------------------------------------------------------------------------------------------------------- 443 // DGL specific, build-specific fallback resize 444 445 void puglFallbackOnResize(PuglView* const view, const uint width, const uint height) 446 { 447 #ifdef DGL_OPENGL 448 glEnable(GL_BLEND); 449 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 450 #ifdef DGL_USE_OPENGL3 451 glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height)); 452 #else 453 glMatrixMode(GL_PROJECTION); 454 glLoadIdentity(); 455 glOrtho(0.0, static_cast<GLdouble>(width), static_cast<GLdouble>(height), 0.0, 0.0, 1.0); 456 glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height)); 457 glMatrixMode(GL_MODELVIEW); 458 glLoadIdentity(); 459 #endif 460 #else 461 return; 462 // unused 463 (void)view; 464 #endif 465 } 466 467 // -------------------------------------------------------------------------------------------------------------------- 468 469 #if defined(DISTRHO_OS_HAIKU) 470 471 // -------------------------------------------------------------------------------------------------------------------- 472 473 #elif defined(DISTRHO_OS_MAC) 474 475 // -------------------------------------------------------------------------------------------------------------------- 476 // macOS specific, add another view's window as child 477 478 PuglStatus 479 puglMacOSAddChildWindow(PuglView* const view, PuglView* const child) 480 { 481 if (NSWindow* const viewWindow = view->impl->window ? view->impl->window 482 : [view->impl->wrapperView window]) 483 { 484 if (NSWindow* const childWindow = child->impl->window ? child->impl->window 485 : [child->impl->wrapperView window]) 486 { 487 [viewWindow addChildWindow:childWindow ordered:NSWindowAbove]; 488 return PUGL_SUCCESS; 489 } 490 } 491 492 return PUGL_FAILURE; 493 } 494 495 // -------------------------------------------------------------------------------------------------------------------- 496 // macOS specific, remove another view's window as child 497 498 PuglStatus 499 puglMacOSRemoveChildWindow(PuglView* const view, PuglView* const child) 500 { 501 if (NSWindow* const viewWindow = view->impl->window ? view->impl->window 502 : [view->impl->wrapperView window]) 503 { 504 if (NSWindow* const childWindow = child->impl->window ? child->impl->window 505 : [child->impl->wrapperView window]) 506 { 507 [viewWindow removeChildWindow:childWindow]; 508 return PUGL_SUCCESS; 509 } 510 } 511 512 return PUGL_FAILURE; 513 } 514 515 // -------------------------------------------------------------------------------------------------------------------- 516 // macOS specific, center view based on parent coordinates (if there is one) 517 518 void puglMacOSShowCentered(PuglView* const view) 519 { 520 if (puglShow(view, PUGL_SHOW_RAISE) != PUGL_SUCCESS) 521 return; 522 523 if (view->transientParent != 0) 524 { 525 NSWindow* const transientWindow = [(NSView*)view->transientParent window]; 526 DISTRHO_SAFE_ASSERT_RETURN(transientWindow != nullptr,); 527 528 const NSRect ourFrame = [view->impl->window frame]; 529 const NSRect transientFrame = [transientWindow frame]; 530 531 const int x = transientFrame.origin.x + (transientFrame.size.width - ourFrame.size.width) / 2; 532 const int y = transientFrame.origin.y + (transientFrame.size.height - ourFrame.size.height) / 2; 533 534 [view->impl->window setFrameTopLeftPoint:NSMakePoint(x, y)]; 535 } 536 else 537 { 538 [view->impl->window center]; 539 } 540 } 541 542 // -------------------------------------------------------------------------------------------------------------------- 543 544 #elif defined(DISTRHO_OS_WINDOWS) 545 546 // -------------------------------------------------------------------------------------------------------------------- 547 // win32 specific, call ShowWindow with SW_RESTORE 548 549 void puglWin32RestoreWindow(PuglView* const view) 550 { 551 PuglInternals* impl = view->impl; 552 DISTRHO_SAFE_ASSERT_RETURN(impl->hwnd != nullptr,); 553 554 ShowWindow(impl->hwnd, SW_RESTORE); 555 SetFocus(impl->hwnd); 556 } 557 558 // -------------------------------------------------------------------------------------------------------------------- 559 // win32 specific, center view based on parent coordinates (if there is one) 560 561 void puglWin32ShowCentered(PuglView* const view) 562 { 563 PuglInternals* impl = view->impl; 564 DISTRHO_SAFE_ASSERT_RETURN(impl->hwnd != nullptr,); 565 566 RECT rectChild, rectParent; 567 568 if (view->transientParent != 0 && 569 GetWindowRect(impl->hwnd, &rectChild) && 570 GetWindowRect((HWND)view->transientParent, &rectParent)) 571 { 572 SetWindowPos(impl->hwnd, HWND_TOP, 573 rectParent.left + (rectParent.right-rectParent.left)/2 - (rectChild.right-rectChild.left)/2, 574 rectParent.top + (rectParent.bottom-rectParent.top)/2 - (rectChild.bottom-rectChild.top)/2, 575 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE); 576 } 577 else 578 { 579 MONITORINFO mInfo; 580 std::memset(&mInfo, 0, sizeof(mInfo)); 581 mInfo.cbSize = sizeof(mInfo); 582 583 if (GetMonitorInfo(MonitorFromWindow(impl->hwnd, MONITOR_DEFAULTTOPRIMARY), &mInfo)) 584 SetWindowPos(impl->hwnd, HWND_TOP, 585 mInfo.rcWork.left + (mInfo.rcWork.right - mInfo.rcWork.left - view->lastConfigure.width) / 2, 586 mInfo.rcWork.top + (mInfo.rcWork.bottom - mInfo.rcWork.top - view->lastConfigure.height) / 2, 587 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE); 588 else 589 ShowWindow(impl->hwnd, SW_NORMAL); 590 } 591 592 SetFocus(impl->hwnd); 593 } 594 595 // -------------------------------------------------------------------------------------------------------------------- 596 597 #elif defined(DISTRHO_OS_WASM) 598 599 // nothing here yet 600 601 // -------------------------------------------------------------------------------------------------------------------- 602 603 #elif defined(HAVE_X11) 604 605 // -------------------------------------------------------------------------------------------------------------------- 606 // X11 specific, update world without triggering exposure events 607 608 PuglStatus puglX11UpdateWithoutExposures(PuglWorld* const world) 609 { 610 const bool wasDispatchingEvents = world->impl->dispatchingEvents; 611 world->impl->dispatchingEvents = true; 612 PuglStatus st = PUGL_SUCCESS; 613 614 const double startTime = puglGetTime(world); 615 const double endTime = startTime + 0.03; 616 617 for (double t = startTime; !st && t < endTime; t = puglGetTime(world)) 618 { 619 pollX11Socket(world, endTime - t); 620 st = dispatchX11Events(world); 621 } 622 623 world->impl->dispatchingEvents = wasDispatchingEvents; 624 return st; 625 } 626 627 // -------------------------------------------------------------------------------------------------------------------- 628 // X11 specific, set dialog window type and pid hints 629 630 void puglX11SetWindowTypeAndPID(const PuglView* const view, const bool isStandalone) 631 { 632 const PuglInternals* const impl = view->impl; 633 Display* const display = view->world->impl->display; 634 635 const pid_t pid = getpid(); 636 const Atom _nwp = XInternAtom(display, "_NET_WM_PID", False); 637 XChangeProperty(display, impl->win, _nwp, XA_CARDINAL, 32, PropModeReplace, (const uchar*)&pid, 1); 638 639 #if defined(DGL_X11_WINDOW_ICON_NAME) && defined(DGL_X11_WINDOW_ICON_SIZE) 640 if (isStandalone) 641 { 642 const Atom _nwi = XInternAtom(display, "_NET_WM_ICON", False); 643 XChangeProperty(display, impl->win, _nwi, XA_CARDINAL, 32, PropModeReplace, 644 (const uchar*)DGL_X11_WINDOW_ICON_NAME, DGL_X11_WINDOW_ICON_SIZE); 645 } 646 #endif 647 648 const Atom _wt = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False); 649 650 Atom _wts[2]; 651 int numAtoms = 0; 652 653 if (! isStandalone) 654 _wts[numAtoms++] = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False); 655 656 _wts[numAtoms++] = XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False); 657 658 XChangeProperty(display, impl->win, _wt, XA_ATOM, 32, PropModeReplace, (const uchar*)&_wts, numAtoms); 659 } 660 661 // -------------------------------------------------------------------------------------------------------------------- 662 663 #endif // HAVE_X11 664 665 #ifndef DISTRHO_OS_MAC 666 END_NAMESPACE_DGL 667 #endif