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.

669 lines
22KB

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