DISTRHO Plugin Framework
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

640 lines
21KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2022 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. #include "pugl.hpp"
  17. // --------------------------------------------------------------------------------------------------------------------
  18. // include base headers
  19. #ifdef DGL_CAIRO
  20. # include <cairo.h>
  21. #endif
  22. #ifdef DGL_OPENGL
  23. # include "../OpenGL-include.hpp"
  24. #endif
  25. #ifdef DGL_VULKAN
  26. # include <vulkan/vulkan_core.h>
  27. #endif
  28. /* we will include all header files used in pugl in their C++ friendly form, then pugl stuff in custom namespace */
  29. #include <cassert>
  30. #include <cmath>
  31. #include <cstdlib>
  32. #include <cstdio>
  33. #include <cstring>
  34. #include <ctime>
  35. #if defined(DISTRHO_OS_MAC)
  36. # import <Cocoa/Cocoa.h>
  37. # include <dlfcn.h>
  38. # include <mach/mach_time.h>
  39. # ifdef DGL_CAIRO
  40. # include <cairo-quartz.h>
  41. # endif
  42. # ifdef DGL_OPENGL
  43. # include <OpenGL/gl.h>
  44. # endif
  45. # ifdef DGL_VULKAN
  46. # import <QuartzCore/CAMetalLayer.h>
  47. # include <vulkan/vulkan_macos.h>
  48. # endif
  49. #elif defined(DISTRHO_OS_WASM)
  50. # include <emscripten/emscripten.h>
  51. # include <emscripten/html5.h>
  52. # ifdef DGL_OPENGL
  53. # include <EGL/egl.h>
  54. # endif
  55. #elif defined(DISTRHO_OS_WINDOWS)
  56. # include <wctype.h>
  57. # include <winsock2.h>
  58. # include <windows.h>
  59. # include <windowsx.h>
  60. # ifdef DGL_CAIRO
  61. # include <cairo-win32.h>
  62. # endif
  63. # ifdef DGL_OPENGL
  64. # include <GL/gl.h>
  65. # endif
  66. # ifdef DGL_VULKAN
  67. # include <vulkan/vulkan.h>
  68. # include <vulkan/vulkan_win32.h>
  69. # endif
  70. #elif defined(HAVE_X11)
  71. # include <dlfcn.h>
  72. # include <limits.h>
  73. # include <unistd.h>
  74. # include <sys/select.h>
  75. // # include <sys/time.h>
  76. # include <X11/X.h>
  77. # include <X11/Xatom.h>
  78. # include <X11/Xlib.h>
  79. # include <X11/Xresource.h>
  80. # include <X11/Xutil.h>
  81. # include <X11/keysym.h>
  82. # ifdef HAVE_XCURSOR
  83. # include <X11/Xcursor/Xcursor.h>
  84. // # include <X11/cursorfont.h>
  85. # endif
  86. # ifdef HAVE_XRANDR
  87. # include <X11/extensions/Xrandr.h>
  88. # endif
  89. # ifdef HAVE_XSYNC
  90. # include <X11/extensions/sync.h>
  91. # include <X11/extensions/syncconst.h>
  92. # endif
  93. # ifdef DGL_CAIRO
  94. # include <cairo-xlib.h>
  95. # endif
  96. # ifdef DGL_OPENGL
  97. # include <GL/glx.h>
  98. # endif
  99. # ifdef DGL_VULKAN
  100. # include <vulkan/vulkan_xlib.h>
  101. # endif
  102. #endif
  103. #ifndef DGL_FILE_BROWSER_DISABLED
  104. # define FILE_BROWSER_DIALOG_DGL_NAMESPACE
  105. # define FILE_BROWSER_DIALOG_NAMESPACE DGL_NAMESPACE
  106. # define DGL_FILE_BROWSER_DIALOG_HPP_INCLUDED
  107. START_NAMESPACE_DGL
  108. # include "../../distrho/extra/FileBrowserDialogImpl.hpp"
  109. END_NAMESPACE_DGL
  110. # include "../../distrho/extra/FileBrowserDialogImpl.cpp"
  111. #endif
  112. #ifndef DISTRHO_OS_MAC
  113. START_NAMESPACE_DGL
  114. #endif
  115. // --------------------------------------------------------------------------------------------------------------------
  116. #if defined(DISTRHO_OS_MAC)
  117. # ifndef DISTRHO_MACOS_NAMESPACE_MACRO
  118. # define DISTRHO_MACOS_NAMESPACE_MACRO_HELPER(NS, SEP, INTERFACE) NS ## SEP ## INTERFACE
  119. # define DISTRHO_MACOS_NAMESPACE_MACRO(NS, INTERFACE) DISTRHO_MACOS_NAMESPACE_MACRO_HELPER(NS, _, INTERFACE)
  120. # define PuglCairoView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglCairoView)
  121. # define PuglOpenGLView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglOpenGLView)
  122. # define PuglStubView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglStubView)
  123. # define PuglVulkanView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglVulkanView)
  124. # define PuglWindow DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWindow)
  125. # define PuglWindowDelegate DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWindowDelegate)
  126. # define PuglWrapperView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWrapperView)
  127. # endif
  128. # pragma clang diagnostic push
  129. # pragma clang diagnostic ignored "-Wdeprecated-declarations"
  130. # import "pugl-upstream/src/mac.m"
  131. # import "pugl-upstream/src/mac_stub.m"
  132. # ifdef DGL_CAIRO
  133. # import "pugl-upstream/src/mac_cairo.m"
  134. # endif
  135. # ifdef DGL_OPENGL
  136. # import "pugl-upstream/src/mac_gl.m"
  137. # endif
  138. # ifdef DGL_VULKAN
  139. # import "pugl-upstream/src/mac_vulkan.m"
  140. # endif
  141. # pragma clang diagnostic pop
  142. #elif defined(DISTRHO_OS_WASM)
  143. # include "pugl-upstream/src/wasm.c"
  144. # include "pugl-upstream/src/wasm_stub.c"
  145. # ifdef DGL_OPENGL
  146. # include "pugl-upstream/src/wasm_gl.c"
  147. # endif
  148. #elif defined(DISTRHO_OS_WINDOWS)
  149. # include "pugl-upstream/src/win.c"
  150. # include "pugl-upstream/src/win_stub.c"
  151. # ifdef DGL_CAIRO
  152. # include "pugl-upstream/src/win_cairo.c"
  153. # endif
  154. # ifdef DGL_OPENGL
  155. # include "pugl-upstream/src/win_gl.c"
  156. # endif
  157. # ifdef DGL_VULKAN
  158. # include "pugl-upstream/src/win_vulkan.c"
  159. # endif
  160. #elif defined(HAVE_X11)
  161. # include "pugl-upstream/src/x11.c"
  162. # include "pugl-upstream/src/x11_stub.c"
  163. # ifdef DGL_CAIRO
  164. # include "pugl-upstream/src/x11_cairo.c"
  165. # endif
  166. # ifdef DGL_OPENGL
  167. # include "pugl-upstream/src/x11_gl.c"
  168. # endif
  169. # ifdef DGL_VULKAN
  170. # include "pugl-upstream/src/x11_vulkan.c"
  171. # endif
  172. #endif
  173. #include "pugl-upstream/src/common.c"
  174. #include "pugl-upstream/src/internal.c"
  175. // --------------------------------------------------------------------------------------------------------------------
  176. // DGL specific, expose backend enter
  177. bool puglBackendEnter(PuglView* const view)
  178. {
  179. return view->backend->enter(view, nullptr) == PUGL_SUCCESS;
  180. }
  181. // --------------------------------------------------------------------------------------------------------------------
  182. // DGL specific, expose backend leave
  183. bool puglBackendLeave(PuglView* const view)
  184. {
  185. return view->backend->leave(view, nullptr) == PUGL_SUCCESS;
  186. }
  187. // --------------------------------------------------------------------------------------------------------------------
  188. // DGL specific, assigns backend that matches current DGL build
  189. void puglSetMatchingBackendForCurrentBuild(PuglView* const view)
  190. {
  191. #ifdef DGL_CAIRO
  192. puglSetBackend(view, puglCairoBackend());
  193. #endif
  194. #ifdef DGL_OPENGL
  195. puglSetBackend(view, puglGlBackend());
  196. #endif
  197. #ifdef DGL_VULKAN
  198. puglSetBackend(view, puglVulkanBackend());
  199. #endif
  200. if (view->backend == nullptr)
  201. puglSetBackend(view, puglStubBackend());
  202. }
  203. // --------------------------------------------------------------------------------------------------------------------
  204. // bring view window into the foreground, aka "raise" window
  205. void puglRaiseWindow(PuglView* const view)
  206. {
  207. #if defined(DISTRHO_OS_MAC)
  208. if (NSWindow* const window = view->impl->window ? view->impl->window
  209. : [view->impl->wrapperView window])
  210. [window orderFrontRegardless];
  211. #elif defined(DISTRHO_OS_WASM)
  212. // nothing
  213. #elif defined(DISTRHO_OS_WINDOWS)
  214. SetForegroundWindow(view->impl->hwnd);
  215. SetActiveWindow(view->impl->hwnd);
  216. #elif defined(HAVE_X11)
  217. XRaiseWindow(view->world->impl->display, view->impl->win);
  218. #endif
  219. }
  220. // --------------------------------------------------------------------------------------------------------------------
  221. // get scale factor from parent window if possible, fallback to puglGetScaleFactor
  222. double puglGetScaleFactorFromParent(const PuglView* const view)
  223. {
  224. const PuglNativeView parent = view->parent ? view->parent : view->transientParent ? view->transientParent : 0;
  225. #if defined(DISTRHO_OS_MAC)
  226. // some of these can return 0 as backingScaleFactor, pick the most relevant valid one
  227. const NSWindow* possibleWindows[] = {
  228. parent != 0 ? [(NSView*)parent window] : nullptr,
  229. view->impl->window,
  230. [view->impl->wrapperView window]
  231. };
  232. for (size_t i=0; i<ARRAY_SIZE(possibleWindows); ++i)
  233. {
  234. if (possibleWindows[i] == nullptr)
  235. continue;
  236. if (const double scaleFactor = [[possibleWindows[i] screen] backingScaleFactor])
  237. return scaleFactor;
  238. }
  239. return [[NSScreen mainScreen] backingScaleFactor];
  240. #elif defined(DISTRHO_OS_WINDOWS)
  241. const HWND hwnd = parent != 0 ? (HWND)parent : view->impl->hwnd;
  242. return puglWinGetViewScaleFactor(hwnd);
  243. #else
  244. return puglGetScaleFactor(view);
  245. // unused
  246. (void)parent;
  247. #endif
  248. }
  249. // --------------------------------------------------------------------------------------------------------------------
  250. // Combined puglSetSizeHint using PUGL_MIN_SIZE and PUGL_FIXED_ASPECT
  251. PuglStatus puglSetGeometryConstraints(PuglView* const view, const uint width, const uint height, const bool aspect)
  252. {
  253. view->sizeHints[PUGL_MIN_SIZE].width = width;
  254. view->sizeHints[PUGL_MIN_SIZE].height = height;
  255. if (aspect)
  256. {
  257. view->sizeHints[PUGL_FIXED_ASPECT].width = width;
  258. view->sizeHints[PUGL_FIXED_ASPECT].height = height;
  259. }
  260. #if defined(DISTRHO_OS_MAC)
  261. if (view->impl->window)
  262. {
  263. PuglStatus status;
  264. if ((status = updateSizeHint(view, PUGL_MIN_SIZE)) != PUGL_SUCCESS)
  265. return status;
  266. if (aspect && (status = updateSizeHint(view, PUGL_FIXED_ASPECT)) != PUGL_SUCCESS)
  267. return status;
  268. }
  269. #elif defined(DISTRHO_OS_WASM)
  270. // nothing
  271. #elif defined(DISTRHO_OS_WINDOWS)
  272. // nothing
  273. #elif defined(HAVE_X11)
  274. if (const PuglStatus status = updateSizeHints(view))
  275. return status;
  276. XFlush(view->world->impl->display);
  277. #endif
  278. return PUGL_SUCCESS;
  279. }
  280. // --------------------------------------------------------------------------------------------------------------------
  281. // set view as resizable (or not) during runtime
  282. void puglSetResizable(PuglView* const view, const bool resizable)
  283. {
  284. puglSetViewHint(view, PUGL_RESIZABLE, resizable ? PUGL_TRUE : PUGL_FALSE);
  285. #if defined(DISTRHO_OS_MAC)
  286. if (PuglWindow* const window = view->impl->window)
  287. {
  288. const uint style = (NSClosableWindowMask | NSTitledWindowMask | NSMiniaturizableWindowMask)
  289. | (resizable ? NSResizableWindowMask : 0x0);
  290. [window setStyleMask:style];
  291. }
  292. // FIXME use [view setAutoresizingMask:NSViewNotSizable] ?
  293. #elif defined(DISTRHO_OS_WASM)
  294. // nothing
  295. #elif defined(DISTRHO_OS_WINDOWS)
  296. if (const HWND hwnd = view->impl->hwnd)
  297. {
  298. const uint winFlags = resizable ? GetWindowLong(hwnd, GWL_STYLE) | (WS_SIZEBOX | WS_MAXIMIZEBOX)
  299. : GetWindowLong(hwnd, GWL_STYLE) & ~(WS_SIZEBOX | WS_MAXIMIZEBOX);
  300. SetWindowLong(hwnd, GWL_STYLE, winFlags);
  301. }
  302. #elif defined(HAVE_X11)
  303. updateSizeHints(view);
  304. #endif
  305. }
  306. // --------------------------------------------------------------------------------------------------------------------
  307. // set window size while also changing default
  308. PuglStatus puglSetSizeAndDefault(PuglView* view, uint width, uint height)
  309. {
  310. if (width > INT16_MAX || height > INT16_MAX)
  311. return PUGL_BAD_PARAMETER;
  312. view->sizeHints[PUGL_DEFAULT_SIZE].width = view->frame.width = static_cast<PuglSpan>(width);
  313. view->sizeHints[PUGL_DEFAULT_SIZE].height = view->frame.height = static_cast<PuglSpan>(height);
  314. #if defined(DISTRHO_OS_MAC)
  315. // mostly matches upstream pugl, simplified
  316. PuglInternals* const impl = view->impl;
  317. const PuglRect frame = view->frame;
  318. const NSRect framePx = rectToNsRect(frame);
  319. const NSRect framePt = nsRectToPoints(view, framePx);
  320. if (PuglWindow* const window = view->impl->window)
  321. {
  322. const NSRect screenPt = rectToScreen(viewScreen(view), framePt);
  323. const NSRect winFrame = [window frameRectForContentRect:screenPt];
  324. [window setFrame:winFrame display:NO];
  325. }
  326. const NSSize sizePx = NSMakeSize(frame.width, frame.height);
  327. const NSSize sizePt = [impl->drawView convertSizeFromBacking:sizePx];
  328. [impl->wrapperView setFrameSize:sizePt];
  329. [impl->drawView setFrameSize:sizePt];
  330. #elif defined(DISTRHO_OS_WASM)
  331. d_stdout("className is %s", view->world->className);
  332. emscripten_set_canvas_element_size(view->world->className, width, height);
  333. #elif defined(DISTRHO_OS_WINDOWS)
  334. // matches upstream pugl, except we re-enter context after resize
  335. if (const HWND hwnd = view->impl->hwnd)
  336. {
  337. const RECT rect = adjustedWindowRect(view, view->frame.x, view->frame.y,
  338. static_cast<long>(width), static_cast<long>(height));
  339. if (!SetWindowPos(hwnd, HWND_TOP, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
  340. SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE))
  341. return PUGL_UNKNOWN_ERROR;
  342. // make sure to return context back to ourselves
  343. puglBackendEnter(view);
  344. }
  345. #elif defined(HAVE_X11)
  346. // matches upstream pugl, all in one
  347. if (const Window window = view->impl->win)
  348. {
  349. Display* const display = view->world->impl->display;
  350. if (! XResizeWindow(display, window, width, height))
  351. return PUGL_UNKNOWN_ERROR;
  352. if (const PuglStatus status = updateSizeHints(view))
  353. return status;
  354. XFlush(display);
  355. }
  356. #endif
  357. return PUGL_SUCCESS;
  358. }
  359. // --------------------------------------------------------------------------------------------------------------------
  360. // DGL specific, build-specific drawing prepare
  361. void puglOnDisplayPrepare(PuglView*)
  362. {
  363. #ifdef DGL_OPENGL
  364. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  365. # ifndef DGL_USE_GLES
  366. glLoadIdentity();
  367. # endif
  368. #endif
  369. }
  370. // --------------------------------------------------------------------------------------------------------------------
  371. // DGL specific, build-specific fallback resize
  372. void puglFallbackOnResize(PuglView* const view)
  373. {
  374. #ifdef DGL_OPENGL
  375. glEnable(GL_BLEND);
  376. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  377. # ifndef DGL_USE_GLES
  378. glMatrixMode(GL_PROJECTION);
  379. glLoadIdentity();
  380. glOrtho(0.0, static_cast<GLdouble>(view->frame.width), static_cast<GLdouble>(view->frame.height), 0.0, 0.0, 1.0);
  381. glViewport(0, 0, static_cast<GLsizei>(view->frame.width), static_cast<GLsizei>(view->frame.height));
  382. glMatrixMode(GL_MODELVIEW);
  383. glLoadIdentity();
  384. # else
  385. glViewport(0, 0, static_cast<GLsizei>(view->frame.width), static_cast<GLsizei>(view->frame.height));
  386. # endif
  387. #else
  388. return;
  389. // unused
  390. (void)view;
  391. #endif
  392. }
  393. // --------------------------------------------------------------------------------------------------------------------
  394. #if defined(DISTRHO_OS_MAC)
  395. // --------------------------------------------------------------------------------------------------------------------
  396. // macOS specific, add another view's window as child
  397. PuglStatus
  398. puglMacOSAddChildWindow(PuglView* const view, PuglView* const child)
  399. {
  400. if (NSWindow* const viewWindow = view->impl->window ? view->impl->window
  401. : [view->impl->wrapperView window])
  402. {
  403. if (NSWindow* const childWindow = child->impl->window ? child->impl->window
  404. : [child->impl->wrapperView window])
  405. {
  406. [viewWindow addChildWindow:childWindow ordered:NSWindowAbove];
  407. return PUGL_SUCCESS;
  408. }
  409. }
  410. return PUGL_FAILURE;
  411. }
  412. // --------------------------------------------------------------------------------------------------------------------
  413. // macOS specific, remove another view's window as child
  414. PuglStatus
  415. puglMacOSRemoveChildWindow(PuglView* const view, PuglView* const child)
  416. {
  417. if (NSWindow* const viewWindow = view->impl->window ? view->impl->window
  418. : [view->impl->wrapperView window])
  419. {
  420. if (NSWindow* const childWindow = child->impl->window ? child->impl->window
  421. : [child->impl->wrapperView window])
  422. {
  423. [viewWindow removeChildWindow:childWindow];
  424. return PUGL_SUCCESS;
  425. }
  426. }
  427. return PUGL_FAILURE;
  428. }
  429. // --------------------------------------------------------------------------------------------------------------------
  430. // macOS specific, center view based on parent coordinates (if there is one)
  431. void puglMacOSShowCentered(PuglView* const view)
  432. {
  433. if (puglShow(view) != PUGL_SUCCESS)
  434. return;
  435. if (view->transientParent != 0)
  436. {
  437. NSWindow* const transientWindow = [(NSView*)view->transientParent window];
  438. DISTRHO_SAFE_ASSERT_RETURN(transientWindow != nullptr,);
  439. const NSRect ourFrame = [view->impl->window frame];
  440. const NSRect transientFrame = [transientWindow frame];
  441. const int x = transientFrame.origin.x + (transientFrame.size.width - ourFrame.size.width) / 2;
  442. const int y = transientFrame.origin.y + (transientFrame.size.height - ourFrame.size.height) / 2;
  443. [view->impl->window setFrameTopLeftPoint:NSMakePoint(x, y)];
  444. }
  445. else
  446. {
  447. [view->impl->window center];
  448. }
  449. }
  450. // --------------------------------------------------------------------------------------------------------------------
  451. #elif defined(DISTRHO_OS_WINDOWS)
  452. // --------------------------------------------------------------------------------------------------------------------
  453. // win32 specific, call ShowWindow with SW_RESTORE
  454. void puglWin32RestoreWindow(PuglView* const view)
  455. {
  456. PuglInternals* impl = view->impl;
  457. DISTRHO_SAFE_ASSERT_RETURN(impl->hwnd != nullptr,);
  458. ShowWindow(impl->hwnd, SW_RESTORE);
  459. SetFocus(impl->hwnd);
  460. }
  461. // --------------------------------------------------------------------------------------------------------------------
  462. // win32 specific, center view based on parent coordinates (if there is one)
  463. void puglWin32ShowCentered(PuglView* const view)
  464. {
  465. PuglInternals* impl = view->impl;
  466. DISTRHO_SAFE_ASSERT_RETURN(impl->hwnd != nullptr,);
  467. RECT rectChild, rectParent;
  468. if (view->transientParent != 0 &&
  469. GetWindowRect(impl->hwnd, &rectChild) &&
  470. GetWindowRect((HWND)view->transientParent, &rectParent))
  471. {
  472. SetWindowPos(impl->hwnd, (HWND)view->transientParent,
  473. rectParent.left + (rectChild.right-rectChild.left)/2,
  474. rectParent.top + (rectChild.bottom-rectChild.top)/2,
  475. 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE);
  476. }
  477. else
  478. {
  479. #ifdef DGL_WINDOWS_ICON_ID
  480. WNDCLASSEX wClass;
  481. std::memset(&wClass, 0, sizeof(wClass));
  482. const HINSTANCE hInstance = GetModuleHandle(nullptr);
  483. if (GetClassInfoEx(hInstance, view->world->className, &wClass))
  484. wClass.hIcon = LoadIcon(nullptr, MAKEINTRESOURCE(DGL_WINDOWS_ICON_ID));
  485. SetClassLongPtr(impl->hwnd, GCLP_HICON, (LONG_PTR) LoadIcon(hInstance, MAKEINTRESOURCE(DGL_WINDOWS_ICON_ID)));
  486. #endif
  487. MONITORINFO mInfo;
  488. std::memset(&mInfo, 0, sizeof(mInfo));
  489. mInfo.cbSize = sizeof(mInfo);
  490. if (GetMonitorInfo(MonitorFromWindow(impl->hwnd, MONITOR_DEFAULTTOPRIMARY), &mInfo))
  491. SetWindowPos(impl->hwnd,
  492. HWND_TOP,
  493. mInfo.rcWork.left + (mInfo.rcWork.right - mInfo.rcWork.left - view->frame.width) / 2,
  494. mInfo.rcWork.top + (mInfo.rcWork.bottom - mInfo.rcWork.top - view->frame.height) / 2,
  495. 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE);
  496. else
  497. ShowWindow(impl->hwnd, SW_NORMAL);
  498. }
  499. SetFocus(impl->hwnd);
  500. }
  501. // --------------------------------------------------------------------------------------------------------------------
  502. #elif defined(DISTRHO_OS_WASM)
  503. // nothing here yet
  504. // --------------------------------------------------------------------------------------------------------------------
  505. #elif defined(HAVE_X11)
  506. PuglStatus puglX11UpdateWithoutExposures(PuglWorld* const world)
  507. {
  508. const bool wasDispatchingEvents = world->impl->dispatchingEvents;
  509. world->impl->dispatchingEvents = true;
  510. PuglStatus st = PUGL_SUCCESS;
  511. const double startTime = puglGetTime(world);
  512. const double endTime = startTime + 0.03;
  513. for (double t = startTime; !st && t < endTime; t = puglGetTime(world))
  514. {
  515. pollX11Socket(world, endTime - t);
  516. st = dispatchX11Events(world);
  517. }
  518. world->impl->dispatchingEvents = wasDispatchingEvents;
  519. return st;
  520. }
  521. // --------------------------------------------------------------------------------------------------------------------
  522. // X11 specific, set dialog window type and pid hints
  523. void puglX11SetWindowTypeAndPID(const PuglView* const view, const bool isStandalone)
  524. {
  525. const PuglInternals* const impl = view->impl;
  526. Display* const display = view->world->impl->display;
  527. const pid_t pid = getpid();
  528. const Atom _nwp = XInternAtom(display, "_NET_WM_PID", False);
  529. XChangeProperty(display, impl->win, _nwp, XA_CARDINAL, 32, PropModeReplace, (const uchar*)&pid, 1);
  530. const Atom _wt = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
  531. Atom _wts[2];
  532. int numAtoms = 0;
  533. if (! isStandalone)
  534. _wts[numAtoms++] = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
  535. _wts[numAtoms++] = XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
  536. XChangeProperty(display, impl->win, _wt, XA_ATOM, 32, PropModeReplace, (const uchar*)&_wts, numAtoms);
  537. }
  538. // --------------------------------------------------------------------------------------------------------------------
  539. #endif // HAVE_X11
  540. #ifndef DISTRHO_OS_MAC
  541. END_NAMESPACE_DGL
  542. #endif