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.

678 lines
23KB

  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_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. #ifndef DISTRHO_OS_MAC
  117. START_NAMESPACE_DGL
  118. #endif
  119. // --------------------------------------------------------------------------------------------------------------------
  120. #if defined(DISTRHO_OS_HAIKU)
  121. # include "pugl-extra/haiku.cpp"
  122. # include "pugl-extra/haiku_stub.cpp"
  123. # ifdef DGL_OPENGL
  124. # include "pugl-extra/haiku_gl.cpp"
  125. # endif
  126. #elif defined(DISTRHO_OS_MAC)
  127. # ifndef DISTRHO_MACOS_NAMESPACE_MACRO
  128. # define DISTRHO_MACOS_NAMESPACE_MACRO_HELPER(NS, SEP, INTERFACE) NS ## SEP ## INTERFACE
  129. # define DISTRHO_MACOS_NAMESPACE_MACRO(NS, INTERFACE) DISTRHO_MACOS_NAMESPACE_MACRO_HELPER(NS, _, INTERFACE)
  130. # define PuglCairoView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglCairoView)
  131. # define PuglOpenGLView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglOpenGLView)
  132. # define PuglStubView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglStubView)
  133. # define PuglVulkanView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglVulkanView)
  134. # define PuglWindow DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWindow)
  135. # define PuglWindowDelegate DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWindowDelegate)
  136. # define PuglWrapperView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWrapperView)
  137. # endif
  138. # pragma clang diagnostic push
  139. # pragma clang diagnostic ignored "-Wdeprecated-declarations"
  140. # import "pugl-upstream/src/mac.m"
  141. # import "pugl-upstream/src/mac_stub.m"
  142. # ifdef DGL_CAIRO
  143. # import "pugl-upstream/src/mac_cairo.m"
  144. # endif
  145. # ifdef DGL_OPENGL
  146. # import "pugl-upstream/src/mac_gl.m"
  147. # endif
  148. # ifdef DGL_VULKAN
  149. # import "pugl-upstream/src/mac_vulkan.m"
  150. # endif
  151. # pragma clang diagnostic pop
  152. #elif defined(DISTRHO_OS_WASM)
  153. # include "pugl-extra/wasm.c"
  154. # include "pugl-extra/wasm_stub.c"
  155. # ifdef DGL_OPENGL
  156. # include "pugl-extra/wasm_gl.c"
  157. # endif
  158. #elif defined(DISTRHO_OS_WINDOWS)
  159. # include "pugl-upstream/src/win.c"
  160. # include "pugl-upstream/src/win_stub.c"
  161. # ifdef DGL_CAIRO
  162. # include "pugl-upstream/src/win_cairo.c"
  163. # endif
  164. # ifdef DGL_OPENGL
  165. # include "pugl-upstream/src/win_gl.c"
  166. # endif
  167. # ifdef DGL_VULKAN
  168. # include "pugl-upstream/src/win_vulkan.c"
  169. # endif
  170. #elif defined(HAVE_X11)
  171. # include "pugl-upstream/src/x11.c"
  172. # include "pugl-upstream/src/x11_stub.c"
  173. # ifdef DGL_CAIRO
  174. # include "pugl-upstream/src/x11_cairo.c"
  175. # endif
  176. # ifdef DGL_OPENGL
  177. # include "pugl-upstream/src/x11_gl.c"
  178. # endif
  179. # ifdef DGL_VULKAN
  180. # include "pugl-upstream/src/x11_vulkan.c"
  181. # endif
  182. #endif
  183. #include "pugl-upstream/src/common.c"
  184. #include "pugl-upstream/src/internal.c"
  185. // --------------------------------------------------------------------------------------------------------------------
  186. // DGL specific, expose backend enter
  187. bool puglBackendEnter(PuglView* const view)
  188. {
  189. return view->backend->enter(view, nullptr) == PUGL_SUCCESS;
  190. }
  191. // --------------------------------------------------------------------------------------------------------------------
  192. // DGL specific, expose backend leave
  193. bool puglBackendLeave(PuglView* const view)
  194. {
  195. return view->backend->leave(view, nullptr) == PUGL_SUCCESS;
  196. }
  197. // --------------------------------------------------------------------------------------------------------------------
  198. // DGL specific, assigns backend that matches current DGL build
  199. void puglSetMatchingBackendForCurrentBuild(PuglView* const view)
  200. {
  201. #ifdef DGL_CAIRO
  202. puglSetBackend(view, puglCairoBackend());
  203. #endif
  204. #ifdef DGL_OPENGL
  205. puglSetBackend(view, puglGlBackend());
  206. #endif
  207. #ifdef DGL_VULKAN
  208. puglSetBackend(view, puglVulkanBackend());
  209. #endif
  210. if (view->backend != nullptr)
  211. {
  212. #ifdef DGL_OPENGL
  213. #if defined(DGL_USE_GLES2)
  214. puglSetViewHint(view, PUGL_USE_COMPAT_PROFILE, PUGL_FALSE);
  215. puglSetViewHint(view, PUGL_CONTEXT_VERSION_MAJOR, 2);
  216. #elif defined(DGL_USE_OPENGL3)
  217. puglSetViewHint(view, PUGL_USE_COMPAT_PROFILE, PUGL_FALSE);
  218. puglSetViewHint(view, PUGL_CONTEXT_VERSION_MAJOR, 3);
  219. #else
  220. puglSetViewHint(view, PUGL_USE_COMPAT_PROFILE, PUGL_TRUE);
  221. puglSetViewHint(view, PUGL_CONTEXT_VERSION_MAJOR, 2);
  222. #endif
  223. #endif
  224. }
  225. else
  226. {
  227. puglSetBackend(view, puglStubBackend());
  228. }
  229. }
  230. // --------------------------------------------------------------------------------------------------------------------
  231. // bring view window into the foreground, aka "raise" window
  232. void puglRaiseWindow(PuglView* const view)
  233. {
  234. #if defined(DISTRHO_OS_HAIKU)
  235. #elif defined(DISTRHO_OS_MAC)
  236. if (NSWindow* const window = view->impl->window ? view->impl->window
  237. : [view->impl->wrapperView window])
  238. [window orderFrontRegardless];
  239. #elif defined(DISTRHO_OS_WASM)
  240. // nothing
  241. #elif defined(DISTRHO_OS_WINDOWS)
  242. SetForegroundWindow(view->impl->hwnd);
  243. SetActiveWindow(view->impl->hwnd);
  244. #elif defined(HAVE_X11)
  245. XRaiseWindow(view->world->impl->display, view->impl->win);
  246. #endif
  247. }
  248. // --------------------------------------------------------------------------------------------------------------------
  249. // get scale factor from parent window if possible, fallback to puglGetScaleFactor
  250. double puglGetScaleFactorFromParent(const PuglView* const view)
  251. {
  252. const PuglNativeView parent = view->parent ? view->parent : view->transientParent ? view->transientParent : 0;
  253. #if defined(DISTRHO_OS_HAIKU)
  254. // TODO
  255. return 1.0;
  256. #elif defined(DISTRHO_OS_MAC)
  257. // some of these can return 0 as backingScaleFactor, pick the most relevant valid one
  258. const NSWindow* possibleWindows[] = {
  259. parent != 0 ? [(NSView*)parent window] : nullptr,
  260. view->impl->window,
  261. [view->impl->wrapperView window]
  262. };
  263. for (size_t i=0; i<ARRAY_SIZE(possibleWindows); ++i)
  264. {
  265. if (possibleWindows[i] == nullptr)
  266. continue;
  267. if (const double scaleFactor = [[possibleWindows[i] screen] backingScaleFactor])
  268. return scaleFactor;
  269. }
  270. return [[NSScreen mainScreen] backingScaleFactor];
  271. #elif defined(DISTRHO_OS_WINDOWS)
  272. const HWND hwnd = parent != 0 ? (HWND)parent : view->impl->hwnd;
  273. return puglWinGetViewScaleFactor(hwnd);
  274. #else
  275. return puglGetScaleFactor(view);
  276. // unused
  277. (void)parent;
  278. #endif
  279. }
  280. // --------------------------------------------------------------------------------------------------------------------
  281. // Combined puglSetSizeHint using PUGL_MIN_SIZE and PUGL_FIXED_ASPECT
  282. PuglStatus puglSetGeometryConstraints(PuglView* const view, const uint width, const uint height, const bool aspect)
  283. {
  284. view->sizeHints[PUGL_MIN_SIZE].width = width;
  285. view->sizeHints[PUGL_MIN_SIZE].height = height;
  286. if (aspect)
  287. {
  288. view->sizeHints[PUGL_FIXED_ASPECT].width = width;
  289. view->sizeHints[PUGL_FIXED_ASPECT].height = height;
  290. }
  291. #if defined(DISTRHO_OS_HAIKU)
  292. #elif defined(DISTRHO_OS_MAC)
  293. if (view->impl->window)
  294. {
  295. PuglStatus status;
  296. if ((status = updateSizeHint(view, PUGL_MIN_SIZE)) != PUGL_SUCCESS)
  297. return status;
  298. if (aspect && (status = updateSizeHint(view, PUGL_FIXED_ASPECT)) != PUGL_SUCCESS)
  299. return status;
  300. }
  301. #elif defined(DISTRHO_OS_WASM)
  302. // nothing
  303. #elif defined(DISTRHO_OS_WINDOWS)
  304. // nothing
  305. #elif defined(HAVE_X11)
  306. if (const PuglStatus status = updateSizeHints(view))
  307. return status;
  308. XFlush(view->world->impl->display);
  309. #endif
  310. return PUGL_SUCCESS;
  311. }
  312. // --------------------------------------------------------------------------------------------------------------------
  313. // set view as resizable (or not) during runtime
  314. void puglSetResizable(PuglView* const view, const bool resizable)
  315. {
  316. puglSetViewHint(view, PUGL_RESIZABLE, resizable ? PUGL_TRUE : PUGL_FALSE);
  317. #if defined(DISTRHO_OS_HAIKU)
  318. #elif defined(DISTRHO_OS_MAC)
  319. if (PuglWindow* const window = view->impl->window)
  320. {
  321. const uint style = (NSClosableWindowMask | NSTitledWindowMask | NSMiniaturizableWindowMask)
  322. | (resizable ? NSResizableWindowMask : 0x0);
  323. [window setStyleMask:style];
  324. }
  325. // FIXME use [view setAutoresizingMask:NSViewNotSizable] ?
  326. #elif defined(DISTRHO_OS_WASM)
  327. // nothing
  328. #elif defined(DISTRHO_OS_WINDOWS)
  329. if (const HWND hwnd = view->impl->hwnd)
  330. {
  331. const uint winFlags = resizable ? GetWindowLong(hwnd, GWL_STYLE) | (WS_SIZEBOX | WS_MAXIMIZEBOX)
  332. : GetWindowLong(hwnd, GWL_STYLE) & ~(WS_SIZEBOX | WS_MAXIMIZEBOX);
  333. SetWindowLong(hwnd, GWL_STYLE, winFlags);
  334. }
  335. #elif defined(HAVE_X11)
  336. updateSizeHints(view);
  337. #endif
  338. }
  339. // --------------------------------------------------------------------------------------------------------------------
  340. // set window size while also changing default
  341. PuglStatus puglSetSizeAndDefault(PuglView* view, uint width, uint height)
  342. {
  343. if (width > INT16_MAX || height > INT16_MAX)
  344. return PUGL_BAD_PARAMETER;
  345. view->sizeHints[PUGL_DEFAULT_SIZE].width = view->frame.width = static_cast<PuglSpan>(width);
  346. view->sizeHints[PUGL_DEFAULT_SIZE].height = view->frame.height = static_cast<PuglSpan>(height);
  347. #if defined(DISTRHO_OS_HAIKU)
  348. #elif defined(DISTRHO_OS_MAC)
  349. // mostly matches upstream pugl, simplified
  350. PuglInternals* const impl = view->impl;
  351. const PuglRect frame = view->frame;
  352. const NSRect framePx = rectToNsRect(frame);
  353. const NSRect framePt = nsRectToPoints(view, framePx);
  354. if (PuglWindow* const window = view->impl->window)
  355. {
  356. const NSRect screenPt = rectToScreen(viewScreen(view), framePt);
  357. const NSRect winFrame = [window frameRectForContentRect:screenPt];
  358. [window setFrame:winFrame display:NO];
  359. }
  360. const NSSize sizePx = NSMakeSize(frame.width, frame.height);
  361. const NSSize sizePt = [impl->drawView convertSizeFromBacking:sizePx];
  362. [impl->wrapperView setFrameSize:sizePt];
  363. [impl->drawView setFrameSize:sizePt];
  364. #elif defined(DISTRHO_OS_WASM)
  365. d_stdout("className is %s", view->world->className);
  366. emscripten_set_canvas_element_size(view->world->className, width, height);
  367. #elif defined(DISTRHO_OS_WINDOWS)
  368. // matches upstream pugl, except we re-enter context after resize
  369. if (const HWND hwnd = view->impl->hwnd)
  370. {
  371. const RECT rect = adjustedWindowRect(view, view->frame.x, view->frame.y,
  372. static_cast<long>(width), static_cast<long>(height));
  373. if (!SetWindowPos(hwnd, HWND_TOP, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
  374. SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE))
  375. return PUGL_UNKNOWN_ERROR;
  376. // make sure to return context back to ourselves
  377. puglBackendEnter(view);
  378. }
  379. #elif defined(HAVE_X11)
  380. // matches upstream pugl, all in one
  381. if (const Window window = view->impl->win)
  382. {
  383. Display* const display = view->world->impl->display;
  384. if (! XResizeWindow(display, window, width, height))
  385. return PUGL_UNKNOWN_ERROR;
  386. if (const PuglStatus status = updateSizeHints(view))
  387. return status;
  388. XFlush(display);
  389. }
  390. #endif
  391. return PUGL_SUCCESS;
  392. }
  393. // --------------------------------------------------------------------------------------------------------------------
  394. // DGL specific, build-specific drawing prepare
  395. void puglOnDisplayPrepare(PuglView*)
  396. {
  397. #ifdef DGL_OPENGL
  398. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  399. #ifndef DGL_USE_OPENGL3
  400. glLoadIdentity();
  401. #endif
  402. #endif
  403. }
  404. // --------------------------------------------------------------------------------------------------------------------
  405. // DGL specific, build-specific fallback resize
  406. void puglFallbackOnResize(PuglView* const view)
  407. {
  408. #ifdef DGL_OPENGL
  409. glEnable(GL_BLEND);
  410. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  411. #ifdef DGL_USE_OPENGL3
  412. glViewport(0, 0, static_cast<GLsizei>(view->frame.width), static_cast<GLsizei>(view->frame.height));
  413. #else
  414. glMatrixMode(GL_PROJECTION);
  415. glLoadIdentity();
  416. glOrtho(0.0, static_cast<GLdouble>(view->frame.width), static_cast<GLdouble>(view->frame.height), 0.0, 0.0, 1.0);
  417. glViewport(0, 0, static_cast<GLsizei>(view->frame.width), static_cast<GLsizei>(view->frame.height));
  418. glMatrixMode(GL_MODELVIEW);
  419. glLoadIdentity();
  420. #endif
  421. #else
  422. return;
  423. // unused
  424. (void)view;
  425. #endif
  426. }
  427. // --------------------------------------------------------------------------------------------------------------------
  428. #if defined(DISTRHO_OS_HAIKU)
  429. // --------------------------------------------------------------------------------------------------------------------
  430. #elif defined(DISTRHO_OS_MAC)
  431. // --------------------------------------------------------------------------------------------------------------------
  432. // macOS specific, add another view's window as child
  433. PuglStatus
  434. puglMacOSAddChildWindow(PuglView* const view, PuglView* const child)
  435. {
  436. if (NSWindow* const viewWindow = view->impl->window ? view->impl->window
  437. : [view->impl->wrapperView window])
  438. {
  439. if (NSWindow* const childWindow = child->impl->window ? child->impl->window
  440. : [child->impl->wrapperView window])
  441. {
  442. [viewWindow addChildWindow:childWindow ordered:NSWindowAbove];
  443. return PUGL_SUCCESS;
  444. }
  445. }
  446. return PUGL_FAILURE;
  447. }
  448. // --------------------------------------------------------------------------------------------------------------------
  449. // macOS specific, remove another view's window as child
  450. PuglStatus
  451. puglMacOSRemoveChildWindow(PuglView* const view, PuglView* const child)
  452. {
  453. if (NSWindow* const viewWindow = view->impl->window ? view->impl->window
  454. : [view->impl->wrapperView window])
  455. {
  456. if (NSWindow* const childWindow = child->impl->window ? child->impl->window
  457. : [child->impl->wrapperView window])
  458. {
  459. [viewWindow removeChildWindow:childWindow];
  460. return PUGL_SUCCESS;
  461. }
  462. }
  463. return PUGL_FAILURE;
  464. }
  465. // --------------------------------------------------------------------------------------------------------------------
  466. // macOS specific, center view based on parent coordinates (if there is one)
  467. void puglMacOSShowCentered(PuglView* const view)
  468. {
  469. if (puglShow(view) != PUGL_SUCCESS)
  470. return;
  471. if (view->transientParent != 0)
  472. {
  473. NSWindow* const transientWindow = [(NSView*)view->transientParent window];
  474. DISTRHO_SAFE_ASSERT_RETURN(transientWindow != nullptr,);
  475. const NSRect ourFrame = [view->impl->window frame];
  476. const NSRect transientFrame = [transientWindow frame];
  477. const int x = transientFrame.origin.x + (transientFrame.size.width - ourFrame.size.width) / 2;
  478. const int y = transientFrame.origin.y + (transientFrame.size.height - ourFrame.size.height) / 2;
  479. [view->impl->window setFrameTopLeftPoint:NSMakePoint(x, y)];
  480. }
  481. else
  482. {
  483. [view->impl->window center];
  484. }
  485. }
  486. // --------------------------------------------------------------------------------------------------------------------
  487. #elif defined(DISTRHO_OS_WINDOWS)
  488. // --------------------------------------------------------------------------------------------------------------------
  489. // win32 specific, call ShowWindow with SW_RESTORE
  490. void puglWin32RestoreWindow(PuglView* const view)
  491. {
  492. PuglInternals* impl = view->impl;
  493. DISTRHO_SAFE_ASSERT_RETURN(impl->hwnd != nullptr,);
  494. ShowWindow(impl->hwnd, SW_RESTORE);
  495. SetFocus(impl->hwnd);
  496. }
  497. // --------------------------------------------------------------------------------------------------------------------
  498. // win32 specific, center view based on parent coordinates (if there is one)
  499. void puglWin32ShowCentered(PuglView* const view)
  500. {
  501. PuglInternals* impl = view->impl;
  502. DISTRHO_SAFE_ASSERT_RETURN(impl->hwnd != nullptr,);
  503. RECT rectChild, rectParent;
  504. if (view->transientParent != 0 &&
  505. GetWindowRect(impl->hwnd, &rectChild) &&
  506. GetWindowRect((HWND)view->transientParent, &rectParent))
  507. {
  508. SetWindowPos(impl->hwnd, HWND_TOP,
  509. rectParent.left + (rectParent.right-rectParent.left)/2 - (rectChild.right-rectChild.left)/2,
  510. rectParent.top + (rectParent.bottom-rectParent.top)/2 - (rectChild.bottom-rectChild.top)/2,
  511. 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE);
  512. }
  513. else
  514. {
  515. #ifdef DGL_WINDOWS_ICON_ID
  516. WNDCLASSEX wClass;
  517. std::memset(&wClass, 0, sizeof(wClass));
  518. const HINSTANCE hInstance = GetModuleHandle(nullptr);
  519. if (GetClassInfoEx(hInstance, view->world->className, &wClass))
  520. wClass.hIcon = LoadIcon(nullptr, MAKEINTRESOURCE(DGL_WINDOWS_ICON_ID));
  521. SetClassLongPtr(impl->hwnd, GCLP_HICON, (LONG_PTR) LoadIcon(hInstance, MAKEINTRESOURCE(DGL_WINDOWS_ICON_ID)));
  522. #endif
  523. MONITORINFO mInfo;
  524. std::memset(&mInfo, 0, sizeof(mInfo));
  525. mInfo.cbSize = sizeof(mInfo);
  526. if (GetMonitorInfo(MonitorFromWindow(impl->hwnd, MONITOR_DEFAULTTOPRIMARY), &mInfo))
  527. SetWindowPos(impl->hwnd, HWND_TOP,
  528. mInfo.rcWork.left + (mInfo.rcWork.right - mInfo.rcWork.left - view->frame.width) / 2,
  529. mInfo.rcWork.top + (mInfo.rcWork.bottom - mInfo.rcWork.top - view->frame.height) / 2,
  530. 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE);
  531. else
  532. ShowWindow(impl->hwnd, SW_NORMAL);
  533. }
  534. SetFocus(impl->hwnd);
  535. }
  536. // --------------------------------------------------------------------------------------------------------------------
  537. #elif defined(DISTRHO_OS_WASM)
  538. // nothing here yet
  539. // --------------------------------------------------------------------------------------------------------------------
  540. #elif defined(HAVE_X11)
  541. PuglStatus puglX11UpdateWithoutExposures(PuglWorld* const world)
  542. {
  543. const bool wasDispatchingEvents = world->impl->dispatchingEvents;
  544. world->impl->dispatchingEvents = true;
  545. PuglStatus st = PUGL_SUCCESS;
  546. const double startTime = puglGetTime(world);
  547. const double endTime = startTime + 0.03;
  548. for (double t = startTime; !st && t < endTime; t = puglGetTime(world))
  549. {
  550. pollX11Socket(world, endTime - t);
  551. st = dispatchX11Events(world);
  552. }
  553. world->impl->dispatchingEvents = wasDispatchingEvents;
  554. return st;
  555. }
  556. // --------------------------------------------------------------------------------------------------------------------
  557. // X11 specific, set dialog window type and pid hints
  558. void puglX11SetWindowTypeAndPID(const PuglView* const view, const bool isStandalone)
  559. {
  560. const PuglInternals* const impl = view->impl;
  561. Display* const display = view->world->impl->display;
  562. const pid_t pid = getpid();
  563. const Atom _nwp = XInternAtom(display, "_NET_WM_PID", False);
  564. XChangeProperty(display, impl->win, _nwp, XA_CARDINAL, 32, PropModeReplace, (const uchar*)&pid, 1);
  565. const Atom _wt = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
  566. Atom _wts[2];
  567. int numAtoms = 0;
  568. if (! isStandalone)
  569. _wts[numAtoms++] = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
  570. _wts[numAtoms++] = XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
  571. XChangeProperty(display, impl->win, _wt, XA_ATOM, 32, PropModeReplace, (const uchar*)&_wts, numAtoms);
  572. }
  573. // --------------------------------------------------------------------------------------------------------------------
  574. #endif // HAVE_X11
  575. #ifndef DISTRHO_OS_MAC
  576. END_NAMESPACE_DGL
  577. #endif