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