Audio plugin host https://kx.studio/carla
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.

676 lines
22KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2021 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. /* we will include all header files used in pugl in their C++ friendly form, then pugl stuff in custom namespace */
  18. #include <cassert>
  19. #include <cmath>
  20. #include <cstdlib>
  21. #include <cstring>
  22. #include <ctime>
  23. #if defined(DISTRHO_OS_MAC)
  24. # import <Cocoa/Cocoa.h>
  25. # include <dlfcn.h>
  26. # include <mach/mach_time.h>
  27. # ifdef DGL_CAIRO
  28. # include <cairo.h>
  29. # include <cairo-quartz.h>
  30. # endif
  31. # ifdef DGL_OPENGL
  32. # include <OpenGL/gl.h>
  33. # endif
  34. # ifdef DGL_VULKAN
  35. # import <QuartzCore/CAMetalLayer.h>
  36. # include <vulkan/vulkan_core.h>
  37. # include <vulkan/vulkan_macos.h>
  38. # endif
  39. #elif defined(DISTRHO_OS_WINDOWS)
  40. # include <wctype.h>
  41. # include <winsock2.h>
  42. # include <windows.h>
  43. # include <windowsx.h>
  44. # ifdef DGL_CAIRO
  45. # include <cairo.h>
  46. # include <cairo-win32.h>
  47. # endif
  48. # ifdef DGL_OPENGL
  49. # include <GL/gl.h>
  50. # endif
  51. # ifdef DGL_VULKAN
  52. # include <vulkan/vulkan.h>
  53. # include <vulkan/vulkan_win32.h>
  54. # endif
  55. #else
  56. # include <dlfcn.h>
  57. # include <unistd.h>
  58. # include <sys/select.h>
  59. # include <sys/time.h>
  60. # include <X11/X.h>
  61. # include <X11/Xatom.h>
  62. # include <X11/Xlib.h>
  63. # include <X11/Xresource.h>
  64. # include <X11/Xutil.h>
  65. # include <X11/keysym.h>
  66. # ifdef HAVE_XCURSOR
  67. # include <X11/Xcursor/Xcursor.h>
  68. # include <X11/cursorfont.h>
  69. # endif
  70. # ifdef HAVE_XRANDR
  71. # include <X11/extensions/Xrandr.h>
  72. # endif
  73. # ifdef HAVE_XSYNC
  74. # include <X11/extensions/sync.h>
  75. # include <X11/extensions/syncconst.h>
  76. # endif
  77. # ifdef DGL_CAIRO
  78. # include <cairo.h>
  79. # include <cairo-xlib.h>
  80. # endif
  81. # ifdef DGL_OPENGL
  82. # include <GL/gl.h>
  83. # include <GL/glx.h>
  84. # endif
  85. # ifdef DGL_VULKAN
  86. # include <vulkan/vulkan_core.h>
  87. # include <vulkan/vulkan_xlib.h>
  88. # endif
  89. #endif
  90. #ifndef DGL_FILE_BROWSER_DISABLED
  91. # ifdef DISTRHO_OS_MAC
  92. # import "../../distrho/extra/FileBrowserDialog.cpp"
  93. # else
  94. # include "../../distrho/extra/FileBrowserDialog.cpp"
  95. # endif
  96. #endif
  97. #ifndef DISTRHO_OS_MAC
  98. START_NAMESPACE_DGL
  99. #endif
  100. // --------------------------------------------------------------------------------------------------------------------
  101. #if defined(DISTRHO_OS_MAC)
  102. # ifndef DISTRHO_MACOS_NAMESPACE_MACRO
  103. # define DISTRHO_MACOS_NAMESPACE_MACRO_HELPER(NS, SEP, INTERFACE) NS ## SEP ## INTERFACE
  104. # define DISTRHO_MACOS_NAMESPACE_MACRO(NS, INTERFACE) DISTRHO_MACOS_NAMESPACE_MACRO_HELPER(NS, _, INTERFACE)
  105. # define PuglStubView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglStubView)
  106. # define PuglWrapperView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWrapperView)
  107. # define PuglWindow DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWindow)
  108. # endif
  109. # ifndef __MAC_10_9
  110. # define NSModalResponseOK NSOKButton
  111. # endif
  112. # pragma clang diagnostic push
  113. # pragma clang diagnostic ignored "-Wdeprecated-declarations"
  114. # import "pugl-upstream/src/mac.m"
  115. # import "pugl-upstream/src/mac_stub.m"
  116. # ifdef DGL_CAIRO
  117. # import "pugl-upstream/src/mac_cairo.m"
  118. # endif
  119. # ifdef DGL_OPENGL
  120. # import "pugl-upstream/src/mac_gl.m"
  121. # endif
  122. # ifdef DGL_VULKAN
  123. # import "pugl-upstream/src/mac_vulkan.m"
  124. # endif
  125. # pragma clang diagnostic pop
  126. #elif defined(DISTRHO_OS_WINDOWS)
  127. # include "pugl-upstream/src/win.c"
  128. # include "pugl-upstream/src/win_stub.c"
  129. # ifdef DGL_CAIRO
  130. # include "pugl-upstream/src/win_cairo.c"
  131. # endif
  132. # ifdef DGL_OPENGL
  133. # include "pugl-upstream/src/win_gl.c"
  134. # endif
  135. # ifdef DGL_VULKAN
  136. # include "pugl-upstream/src/win_vulkan.c"
  137. # endif
  138. #else
  139. # include "pugl-upstream/src/x11.c"
  140. # include "pugl-upstream/src/x11_stub.c"
  141. # ifdef DGL_CAIRO
  142. # include "pugl-upstream/src/x11_cairo.c"
  143. # endif
  144. # ifdef DGL_OPENGL
  145. # include "pugl-upstream/src/x11_gl.c"
  146. # endif
  147. # ifdef DGL_VULKAN
  148. # include "pugl-upstream/src/x11_vulkan.c"
  149. # endif
  150. #endif
  151. #include "pugl-upstream/src/implementation.c"
  152. // --------------------------------------------------------------------------------------------------------------------
  153. // expose backend enter
  154. bool puglBackendEnter(PuglView* const view)
  155. {
  156. return view->backend->enter(view, nullptr) == PUGL_SUCCESS;
  157. }
  158. // --------------------------------------------------------------------------------------------------------------------
  159. // expose backend leave
  160. void puglBackendLeave(PuglView* const view)
  161. {
  162. view->backend->leave(view, nullptr);
  163. }
  164. // --------------------------------------------------------------------------------------------------------------------
  165. // clear minimum size to 0
  166. void puglClearMinSize(PuglView* const view)
  167. {
  168. view->minWidth = 0;
  169. view->minHeight = 0;
  170. }
  171. // --------------------------------------------------------------------------------------------------------------------
  172. // missing in pugl, directly returns transient parent
  173. PuglNativeView puglGetTransientParent(const PuglView* const view)
  174. {
  175. return view->transientParent;
  176. }
  177. // --------------------------------------------------------------------------------------------------------------------
  178. // missing in pugl, directly returns title char* pointer
  179. const char* puglGetWindowTitle(const PuglView* const view)
  180. {
  181. return view->title;
  182. }
  183. // --------------------------------------------------------------------------------------------------------------------
  184. // get global scale factor
  185. double puglGetDesktopScaleFactor(const PuglView* const view)
  186. {
  187. #if defined(DISTRHO_OS_MAC)
  188. if (NSWindow* const window = view->impl->window ? view->impl->window
  189. : [view->impl->wrapperView window])
  190. return [window screen].backingScaleFactor;
  191. return [NSScreen mainScreen].backingScaleFactor;
  192. #elif defined(DISTRHO_OS_WINDOWS)
  193. if (const HMODULE Shcore = LoadLibraryA("Shcore.dll"))
  194. {
  195. typedef HRESULT(WINAPI* PFN_GetProcessDpiAwareness)(HANDLE, DWORD*);
  196. typedef HRESULT(WINAPI* PFN_GetScaleFactorForMonitor)(HMONITOR, DWORD*);
  197. # if defined(__GNUC__) && (__GNUC__ >= 9)
  198. # pragma GCC diagnostic push
  199. # pragma GCC diagnostic ignored "-Wcast-function-type"
  200. # endif
  201. const PFN_GetProcessDpiAwareness GetProcessDpiAwareness
  202. = (PFN_GetProcessDpiAwareness)GetProcAddress(Shcore, "GetProcessDpiAwareness");
  203. const PFN_GetScaleFactorForMonitor GetScaleFactorForMonitor
  204. = (PFN_GetScaleFactorForMonitor)GetProcAddress(Shcore, "GetScaleFactorForMonitor");
  205. # if defined(__GNUC__) && (__GNUC__ >= 9)
  206. # pragma GCC diagnostic pop
  207. # endif
  208. DWORD dpiAware = 0;
  209. if (GetProcessDpiAwareness && GetScaleFactorForMonitor
  210. && GetProcessDpiAwareness(NULL, &dpiAware) == 0 && dpiAware != 0)
  211. {
  212. const HMONITOR hMon = MonitorFromWindow(view->impl->hwnd, MONITOR_DEFAULTTOPRIMARY);
  213. DWORD scaleFactor = 0;
  214. if (GetScaleFactorForMonitor(hMon, &scaleFactor) == 0 && scaleFactor != 0)
  215. {
  216. FreeLibrary(Shcore);
  217. return static_cast<double>(scaleFactor) / 100.0;
  218. }
  219. }
  220. FreeLibrary(Shcore);
  221. }
  222. #elif defined(HAVE_X11)
  223. XrmInitialize();
  224. if (char* const rms = XResourceManagerString(view->world->impl->display))
  225. {
  226. if (const XrmDatabase sdb = XrmGetStringDatabase(rms))
  227. {
  228. char* type = nullptr;
  229. XrmValue ret;
  230. if (XrmGetResource(sdb, "Xft.dpi", "String", &type, &ret)
  231. && ret.addr != nullptr
  232. && type != nullptr
  233. && std::strncmp("String", type, 6) == 0)
  234. {
  235. if (const double dpi = std::atof(ret.addr))
  236. return dpi / 96;
  237. }
  238. }
  239. }
  240. #else
  241. // unused
  242. (void)view;
  243. #endif
  244. return 1.0;
  245. }
  246. // --------------------------------------------------------------------------------------------------------------------
  247. // bring view window into the foreground, aka "raise" window
  248. void puglRaiseWindow(PuglView* const view)
  249. {
  250. #if defined(DISTRHO_OS_MAC)
  251. if (NSWindow* const window = view->impl->window ? view->impl->window
  252. : [view->impl->wrapperView window])
  253. [window orderFrontRegardless];
  254. #elif defined(DISTRHO_OS_WINDOWS)
  255. SetForegroundWindow(view->impl->hwnd);
  256. SetActiveWindow(view->impl->hwnd);
  257. #else
  258. XRaiseWindow(view->impl->display, view->impl->win);
  259. #endif
  260. }
  261. // --------------------------------------------------------------------------------------------------------------------
  262. // set backend that matches current build
  263. void puglSetMatchingBackendForCurrentBuild(PuglView* const view)
  264. {
  265. #ifdef DGL_CAIRO
  266. puglSetBackend(view, puglCairoBackend());
  267. #endif
  268. #ifdef DGL_OPENGL
  269. puglSetBackend(view, puglGlBackend());
  270. #endif
  271. #ifdef DGL_VULKAN
  272. puglSetBackend(view, puglVulkanBackend());
  273. #endif
  274. if (view->backend == nullptr)
  275. puglSetBackend(view, puglStubBackend());
  276. }
  277. // --------------------------------------------------------------------------------------------------------------------
  278. // Combine puglSetMinSize and puglSetAspectRatio
  279. PuglStatus puglSetGeometryConstraints(PuglView* const view, const uint width, const uint height, const bool aspect)
  280. {
  281. view->minWidth = (int)width;
  282. view->minHeight = (int)height;
  283. if (aspect) {
  284. view->minAspectX = (int)width;
  285. view->minAspectY = (int)height;
  286. view->maxAspectX = (int)width;
  287. view->maxAspectY = (int)height;
  288. }
  289. #if defined(DISTRHO_OS_MAC)
  290. puglSetMinSize(view, width, height);
  291. if (aspect) {
  292. puglSetAspectRatio(view, width, height, width, height);
  293. }
  294. #elif defined(DISTRHO_OS_WINDOWS)
  295. // nothing
  296. #else
  297. if (const PuglStatus status = updateSizeHints(view))
  298. return status;
  299. XFlush(view->impl->display);
  300. #endif
  301. return PUGL_SUCCESS;
  302. }
  303. // --------------------------------------------------------------------------------------------------------------------
  304. // set window offset without changing size
  305. PuglStatus puglSetWindowOffset(PuglView* const view, const int x, const int y)
  306. {
  307. // TODO custom setFrame version
  308. PuglRect rect = puglGetFrame(view);
  309. rect.x = x;
  310. rect.y = y;
  311. return puglSetFrame(view, rect);
  312. }
  313. // --------------------------------------------------------------------------------------------------------------------
  314. // set window size with default size and without changing frame x/y position
  315. PuglStatus puglSetWindowSize(PuglView* const view, const uint width, const uint height)
  316. {
  317. view->defaultWidth = width;
  318. view->defaultHeight = height;
  319. view->frame.width = width;
  320. view->frame.height = height;
  321. #if defined(DISTRHO_OS_MAC)
  322. // replace setFrame with setFrameSize
  323. PuglInternals* const impl = view->impl;
  324. const PuglRect frame = view->frame;
  325. const NSRect framePx = rectToNsRect(frame);
  326. const NSRect framePt = nsRectToPoints(view, framePx);
  327. if (impl->window)
  328. {
  329. // Resize window to fit new content rect
  330. const NSRect screenPt = rectToScreen(viewScreen(view), framePt);
  331. const NSRect winFrame = [impl->window frameRectForContentRect:screenPt];
  332. [impl->window setFrame:winFrame display:NO];
  333. }
  334. // Resize views
  335. const NSSize sizePx = NSMakeSize(frame.width, frame.height);
  336. const NSSize sizePt = [impl->drawView convertSizeFromBacking:sizePx];
  337. [impl->wrapperView setFrameSize:(impl->window ? sizePt : framePt.size)];
  338. [impl->drawView setFrameSize:sizePt];
  339. #elif defined(DISTRHO_OS_WINDOWS)
  340. // matches upstream pugl, except we add SWP_NOMOVE flag
  341. if (view->impl->hwnd)
  342. {
  343. const PuglRect frame = view->frame;
  344. RECT rect = { (long)frame.x,
  345. (long)frame.y,
  346. (long)frame.x + (long)frame.width,
  347. (long)frame.y + (long)frame.height };
  348. AdjustWindowRectEx(&rect, puglWinGetWindowFlags(view), FALSE, puglWinGetWindowExFlags(view));
  349. if (SetWindowPos(view->impl->hwnd,
  350. HWND_TOP,
  351. rect.left,
  352. rect.top,
  353. rect.right - rect.left,
  354. rect.bottom - rect.top,
  355. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER))
  356. {
  357. // make sure to return context back to ourselves
  358. view->backend->enter(view, nullptr);
  359. return PUGL_SUCCESS;
  360. }
  361. return PUGL_UNKNOWN_ERROR;
  362. }
  363. #else
  364. // matches upstream pugl, except we use XResizeWindow instead of XMoveResizeWindow
  365. if (view->impl->win)
  366. {
  367. Display* const display = view->impl->display;
  368. if (! XResizeWindow(display, view->impl->win, width, height))
  369. return PUGL_UNKNOWN_ERROR;
  370. if (const PuglStatus status = updateSizeHints(view))
  371. return status;
  372. XFlush(display);
  373. }
  374. #endif
  375. return PUGL_SUCCESS;
  376. }
  377. // --------------------------------------------------------------------------------------------------------------------
  378. // DGL specific, build-specific drawing prepare
  379. void puglOnDisplayPrepare(PuglView*)
  380. {
  381. #ifdef DGL_OPENGL
  382. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  383. glLoadIdentity();
  384. #endif
  385. }
  386. // --------------------------------------------------------------------------------------------------------------------
  387. // DGL specific, build-specific fallback resize
  388. void puglFallbackOnResize(PuglView* const view)
  389. {
  390. #ifdef DGL_OPENGL
  391. glEnable(GL_BLEND);
  392. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  393. glMatrixMode(GL_PROJECTION);
  394. glLoadIdentity();
  395. glOrtho(0.0, static_cast<GLdouble>(view->frame.width), static_cast<GLdouble>(view->frame.height), 0.0, 0.0, 1.0);
  396. glViewport(0, 0, static_cast<GLsizei>(view->frame.width), static_cast<GLsizei>(view->frame.height));
  397. glMatrixMode(GL_MODELVIEW);
  398. glLoadIdentity();
  399. #endif
  400. }
  401. #if defined(DISTRHO_OS_MAC)
  402. // --------------------------------------------------------------------------------------------------------------------
  403. // macOS specific, allow standalone window to gain focus
  404. void puglMacOSActivateApp()
  405. {
  406. [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
  407. [NSApp activateIgnoringOtherApps:YES];
  408. }
  409. // --------------------------------------------------------------------------------------------------------------------
  410. // macOS specific, add another view's window as child
  411. PuglStatus
  412. puglMacOSAddChildWindow(PuglView* const view, PuglView* const child)
  413. {
  414. if (NSWindow* const viewWindow = view->impl->window ? view->impl->window
  415. : [view->impl->wrapperView window])
  416. {
  417. if (NSWindow* const childWindow = child->impl->window ? child->impl->window
  418. : [child->impl->wrapperView window])
  419. {
  420. [viewWindow addChildWindow:childWindow ordered:NSWindowAbove];
  421. return PUGL_SUCCESS;
  422. }
  423. }
  424. return PUGL_FAILURE;
  425. }
  426. // --------------------------------------------------------------------------------------------------------------------
  427. // macOS specific, remove another view's window as child
  428. PuglStatus
  429. puglMacOSRemoveChildWindow(PuglView* const view, PuglView* const child)
  430. {
  431. if (NSWindow* const viewWindow = view->impl->window ? view->impl->window
  432. : [view->impl->wrapperView window])
  433. {
  434. if (NSWindow* const childWindow = child->impl->window ? child->impl->window
  435. : [child->impl->wrapperView window])
  436. {
  437. [viewWindow removeChildWindow:childWindow];
  438. return PUGL_SUCCESS;
  439. }
  440. }
  441. return PUGL_FAILURE;
  442. }
  443. // --------------------------------------------------------------------------------------------------------------------
  444. // macOS specific, center view based on parent coordinates (if there is one)
  445. void puglMacOSShowCentered(PuglView* const view)
  446. {
  447. if (puglShow(view) != PUGL_SUCCESS)
  448. return;
  449. if (view->transientParent != 0)
  450. {
  451. NSWindow* const transientWindow = [(NSView*)view->transientParent window];
  452. DISTRHO_SAFE_ASSERT_RETURN(transientWindow != nullptr,);
  453. const NSRect ourFrame = [view->impl->window frame];
  454. const NSRect transientFrame = [transientWindow frame];
  455. const int x = transientFrame.origin.x + transientFrame.size.width / 2 - ourFrame.size.width / 2;
  456. const int y = transientFrame.origin.y + transientFrame.size.height / 2 + ourFrame.size.height / 2;
  457. [view->impl->window setFrameTopLeftPoint:NSMakePoint(x, y)];
  458. }
  459. else
  460. {
  461. [view->impl->window center];
  462. }
  463. }
  464. // --------------------------------------------------------------------------------------------------------------------
  465. #elif defined(DISTRHO_OS_WINDOWS)
  466. // --------------------------------------------------------------------------------------------------------------------
  467. // win32 specific, call ShowWindow with SW_RESTORE
  468. void puglWin32RestoreWindow(PuglView* const view)
  469. {
  470. PuglInternals* impl = view->impl;
  471. DISTRHO_SAFE_ASSERT_RETURN(impl->hwnd != nullptr,);
  472. ShowWindow(impl->hwnd, SW_RESTORE);
  473. SetFocus(impl->hwnd);
  474. }
  475. // --------------------------------------------------------------------------------------------------------------------
  476. // win32 specific, center view based on parent coordinates (if there is one)
  477. void puglWin32ShowCentered(PuglView* const view)
  478. {
  479. PuglInternals* impl = view->impl;
  480. DISTRHO_SAFE_ASSERT_RETURN(impl->hwnd != nullptr,);
  481. RECT rectChild, rectParent;
  482. if (view->transientParent != 0 &&
  483. GetWindowRect(impl->hwnd, &rectChild) &&
  484. GetWindowRect((HWND)view->transientParent, &rectParent))
  485. {
  486. SetWindowPos(impl->hwnd, (HWND)view->transientParent,
  487. rectParent.left + (rectChild.right-rectChild.left)/2,
  488. rectParent.top + (rectChild.bottom-rectChild.top)/2,
  489. 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE);
  490. }
  491. else
  492. {
  493. #ifdef DGL_WINDOWS_ICON_ID
  494. WNDCLASSEX wClass;
  495. std::memset(&wClass, 0, sizeof(wClass));
  496. const HINSTANCE hInstance = GetModuleHandle(nullptr);
  497. if (GetClassInfoEx(hInstance, view->world->className, &wClass))
  498. wClass.hIcon = LoadIcon(nullptr, MAKEINTRESOURCE(DGL_WINDOWS_ICON_ID));
  499. SetClassLongPtr(impl->hwnd, GCLP_HICON, (LONG_PTR) LoadIcon(hInstance, MAKEINTRESOURCE(DGL_WINDOWS_ICON_ID)));
  500. #endif
  501. MONITORINFO mInfo;
  502. std::memset(&mInfo, 0, sizeof(mInfo));
  503. mInfo.cbSize = sizeof(mInfo);
  504. if (GetMonitorInfo(MonitorFromWindow(impl->hwnd, MONITOR_DEFAULTTOPRIMARY), &mInfo))
  505. SetWindowPos(impl->hwnd,
  506. HWND_TOP,
  507. mInfo.rcWork.left + (mInfo.rcWork.right - view->frame.width) / 2,
  508. mInfo.rcWork.top + (mInfo.rcWork.bottom - view->frame.height) / 2,
  509. 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE);
  510. else
  511. ShowWindow(impl->hwnd, SW_NORMAL);
  512. }
  513. SetFocus(impl->hwnd);
  514. }
  515. // --------------------------------------------------------------------------------------------------------------------
  516. // win32 specific, set or unset WS_SIZEBOX style flag
  517. void puglWin32SetWindowResizable(PuglView* const view, const bool resizable)
  518. {
  519. PuglInternals* impl = view->impl;
  520. DISTRHO_SAFE_ASSERT_RETURN(impl->hwnd != nullptr,);
  521. const int winFlags = resizable ? GetWindowLong(impl->hwnd, GWL_STYLE) | WS_SIZEBOX
  522. : GetWindowLong(impl->hwnd, GWL_STYLE) & ~WS_SIZEBOX;
  523. SetWindowLong(impl->hwnd, GWL_STYLE, winFlags);
  524. }
  525. // --------------------------------------------------------------------------------------------------------------------
  526. #elif defined(HAVE_X11)
  527. // --------------------------------------------------------------------------------------------------------------------
  528. // X11 specific, safer way to grab focus
  529. PuglStatus puglX11GrabFocus(const PuglView* const view)
  530. {
  531. const PuglInternals* const impl = view->impl;
  532. XWindowAttributes wa;
  533. std::memset(&wa, 0, sizeof(wa));
  534. DISTRHO_SAFE_ASSERT_RETURN(XGetWindowAttributes(impl->display, impl->win, &wa), PUGL_UNKNOWN_ERROR);
  535. if (wa.map_state == IsViewable)
  536. {
  537. XRaiseWindow(impl->display, impl->win);
  538. XSetInputFocus(impl->display, impl->win, RevertToPointerRoot, CurrentTime);
  539. XSync(impl->display, False);
  540. }
  541. return PUGL_SUCCESS;
  542. }
  543. // --------------------------------------------------------------------------------------------------------------------
  544. // X11 specific, set dialog window type and pid hints
  545. void puglX11SetWindowTypeAndPID(const PuglView* const view, const bool isStandalone)
  546. {
  547. const PuglInternals* const impl = view->impl;
  548. const pid_t pid = getpid();
  549. const Atom _nwp = XInternAtom(impl->display, "_NET_WM_PID", False);
  550. XChangeProperty(impl->display, impl->win, _nwp, XA_CARDINAL, 32, PropModeReplace, (const uchar*)&pid, 1);
  551. const Atom _wt = XInternAtom(impl->display, "_NET_WM_WINDOW_TYPE", False);
  552. Atom _wts[2];
  553. int numAtoms = 0;
  554. if (! isStandalone)
  555. _wts[numAtoms++] = XInternAtom(impl->display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
  556. _wts[numAtoms++] = XInternAtom(impl->display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
  557. XChangeProperty(impl->display, impl->win, _wt, XA_ATOM, 32, PropModeReplace, (const uchar*)&_wts, numAtoms);
  558. }
  559. // --------------------------------------------------------------------------------------------------------------------
  560. #endif // HAVE_X11
  561. #ifndef DISTRHO_OS_MAC
  562. END_NAMESPACE_DGL
  563. #endif