38
38
39
39
/**
40
40
* This class is a straightforward port of the
41
- * <a href="https://raw.githubusercontent.com/ocornut/imgui/05bc204dbd80dfebb3dab1511caf1cb980620c76/examples /imgui_impl_glfw.cpp">imgui_impl_glfw.cpp</a>.
41
+ * <a href="https://raw.githubusercontent.com/ocornut/imgui/256594575d95d56dda616c544c509740e74906b4/backends /imgui_impl_glfw.cpp">imgui_impl_glfw.cpp</a>.
42
42
* <p>
43
43
* It supports clipboard, gamepad, mouse and keyboard in the same way the original Dear ImGui code does. You can copy-paste this class in your codebase and
44
44
* modify the rendering routine in the way you'd like.
45
45
*/
46
46
public class ImGuiImplGlfw {
47
- protected static final boolean IS_WINDOWS = System .getProperty ("os.name" , "generic" ).toLowerCase ().contains ("win" );
47
+ private static final String OS = System .getProperty ("os.name" , "generic" ).toLowerCase ();
48
+ protected static final boolean IS_WINDOWS = OS .contains ("win" );
49
+ protected static final boolean IS_APPLE = OS .contains ("mac" ) || OS .contains ("darwin" );
48
50
49
51
// Pointer of the current GLFW window
50
52
private long windowPtr ;
51
53
54
+ // Some features may be available only from a specific version
55
+ private boolean glfwHawWindowTopmost ;
56
+ private boolean glfwHasWindowAlpha ;
57
+ private boolean glfwHasPerMonitorDpi ;
58
+ private boolean glfwHasFocusWindow ;
59
+ private boolean glfwHasFocusOnShow ;
60
+ private boolean glfwHasMonitorWorkArea ;
61
+ private boolean glfwHasOsxWindowPosFix ;
62
+
52
63
// For application window properties
53
64
private final int [] winWidth = new int [1 ];
54
65
private final int [] winHeight = new int [1 ];
@@ -167,6 +178,8 @@ public void monitorCallback(final long windowId, final int event) {
167
178
public boolean init (final long windowId , final boolean installCallbacks ) {
168
179
this .windowPtr = windowId ;
169
180
181
+ detectGlfwVersionAndEnabledFeatures ();
182
+
170
183
final ImGuiIO io = ImGui .getIO ();
171
184
172
185
io .addBackendFlags (ImGuiBackendFlags .HasMouseCursors | ImGuiBackendFlags .HasSetMousePos | ImGuiBackendFlags .PlatformHasViewports );
@@ -307,6 +320,22 @@ public void dispose() {
307
320
}
308
321
}
309
322
323
+ private void detectGlfwVersionAndEnabledFeatures () {
324
+ final int [] major = new int [1 ];
325
+ final int [] minor = new int [1 ];
326
+ final int [] rev = new int [1 ];
327
+ glfwGetVersion (major , minor , rev );
328
+
329
+ final int version = major [0 ] * 1000 + minor [0 ] * 100 + rev [0 ] * 10 ;
330
+
331
+ glfwHawWindowTopmost = version >= 3200 ;
332
+ glfwHasWindowAlpha = version >= 3300 ;
333
+ glfwHasPerMonitorDpi = version >= 3300 ;
334
+ glfwHasFocusWindow = version >= 3200 ;
335
+ glfwHasFocusOnShow = version >= 3300 ;
336
+ glfwHasMonitorWorkArea = version >= 3300 ;
337
+ }
338
+
310
339
private void updateMousePosAndButtons () {
311
340
final ImGuiIO io = ImGui .getIO ();
312
341
@@ -459,15 +488,17 @@ private void updateMonitors() {
459
488
final float mainSizeX = vidMode .width ();
460
489
final float mainSizeY = vidMode .height ();
461
490
462
- glfwGetMonitorWorkarea (monitor , monitorWorkAreaX , monitorWorkAreaY , monitorWorkAreaWidth , monitorWorkAreaHeight );
491
+ if (glfwHasMonitorWorkArea ) {
492
+ glfwGetMonitorWorkarea (monitor , monitorWorkAreaX , monitorWorkAreaY , monitorWorkAreaWidth , monitorWorkAreaHeight );
493
+ }
463
494
464
495
float workPosX = 0 ;
465
496
float workPosY = 0 ;
466
497
float workSizeX = 0 ;
467
498
float workSizeY = 0 ;
468
499
469
500
// Workaround a small GLFW issue reporting zero on monitor changes: https://github.com/glfw/glfw/pull/1761
470
- if (monitorWorkAreaWidth [0 ] > 0 && monitorWorkAreaHeight [0 ] > 0 ) {
501
+ if (glfwHasMonitorWorkArea && monitorWorkAreaWidth [0 ] > 0 && monitorWorkAreaHeight [0 ] > 0 ) {
471
502
workPosX = monitorWorkAreaX [0 ];
472
503
workPosY = monitorWorkAreaY [0 ];
473
504
workSizeX = monitorWorkAreaWidth [0 ];
@@ -476,7 +507,9 @@ private void updateMonitors() {
476
507
477
508
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings,
478
509
// which generally needs to be set in the manifest or at runtime.
479
- glfwGetMonitorContentScale (monitor , monitorContentScaleX , monitorContentScaleY );
510
+ if (glfwHasPerMonitorDpi ) {
511
+ glfwGetMonitorContentScale (monitor , monitorContentScaleX , monitorContentScaleY );
512
+ }
480
513
final float dpiScale = monitorContentScaleX [0 ];
481
514
482
515
platformIO .pushMonitors (mainPosX , mainPosY , mainSizeX , mainSizeY , workPosX , workPosY , workSizeX , workSizeY , dpiScale );
@@ -537,9 +570,13 @@ public void accept(final ImGuiViewport vp) {
537
570
// With GLFW 3.3, the hint GLFW_FOCUS_ON_SHOW fixes this problem
538
571
glfwWindowHint (GLFW_VISIBLE , GLFW_FALSE );
539
572
glfwWindowHint (GLFW_FOCUSED , GLFW_FALSE );
540
- glfwWindowHint (GLFW_FOCUS_ON_SHOW , GLFW_FALSE );
573
+ if (glfwHasFocusOnShow ) {
574
+ glfwWindowHint (GLFW_FOCUS_ON_SHOW , GLFW_FALSE );
575
+ }
541
576
glfwWindowHint (GLFW_DECORATED , vp .hasFlags (ImGuiViewportFlags .NoDecoration ) ? GLFW_FALSE : GLFW_TRUE );
542
- glfwWindowHint (GLFW_FLOATING , vp .hasFlags (ImGuiViewportFlags .TopMost ) ? GLFW_TRUE : GLFW_FALSE );
577
+ if (glfwHawWindowTopmost ) {
578
+ glfwWindowHint (GLFW_FLOATING , vp .hasFlags (ImGuiViewportFlags .TopMost ) ? GLFW_TRUE : GLFW_FALSE );
579
+ }
543
580
544
581
data .window = glfwCreateWindow ((int ) vp .getSizeX (), (int ) vp .getSizeY (), "No Title Yet" , NULL , windowPtr );
545
582
data .windowOwned = true ;
@@ -628,10 +665,24 @@ public void get(final ImGuiViewport vp, final ImVec2 dstImVec2) {
628
665
}
629
666
}
630
667
631
- private static final class SetWindowSizeFunction extends ImPlatformFuncViewportImVec2 {
668
+ private final class SetWindowSizeFunction extends ImPlatformFuncViewportImVec2 {
669
+ private final int [] x = new int [1 ];
670
+ private final int [] y = new int [1 ];
671
+ private final int [] width = new int [1 ];
672
+ private final int [] height = new int [1 ];
673
+
632
674
@ Override
633
675
public void accept (final ImGuiViewport vp , final ImVec2 imVec2 ) {
634
676
final ImGuiViewportDataGlfw data = (ImGuiViewportDataGlfw ) vp .getPlatformUserData ();
677
+ // Native OS windows are positioned from the bottom-left corner on macOS, whereas on other platforms they are
678
+ // positioned from the upper-left corner. GLFW makes an effort to convert macOS style coordinates, however it
679
+ // doesn't handle it when changing size. We are manually moving the window in order for changes of size to be based
680
+ // on the upper-left corner.
681
+ if (IS_APPLE && !glfwHasOsxWindowPosFix ) {
682
+ glfwGetWindowPos (data .window , x , y );
683
+ glfwGetWindowSize (data .window , width , height );
684
+ glfwSetWindowPos (data .window , x [0 ], y [0 ] - height [0 ] + (int ) imVec2 .y );
685
+ }
635
686
data .ignoreWindowSizeEventFrame = ImGui .getFrameCount ();
636
687
glfwSetWindowSize (data .window , (int ) imVec2 .x , (int ) imVec2 .y );
637
688
}
@@ -645,11 +696,13 @@ public void accept(final ImGuiViewport vp, final String str) {
645
696
}
646
697
}
647
698
648
- private static final class SetWindowFocusFunction extends ImPlatformFuncViewport {
699
+ private final class SetWindowFocusFunction extends ImPlatformFuncViewport {
649
700
@ Override
650
701
public void accept (final ImGuiViewport vp ) {
651
- final ImGuiViewportDataGlfw data = (ImGuiViewportDataGlfw ) vp .getPlatformUserData ();
652
- glfwFocusWindow (data .window );
702
+ if (glfwHasFocusWindow ) {
703
+ final ImGuiViewportDataGlfw data = (ImGuiViewportDataGlfw ) vp .getPlatformUserData ();
704
+ glfwFocusWindow (data .window );
705
+ }
653
706
}
654
707
}
655
708
@@ -669,11 +722,13 @@ public boolean get(final ImGuiViewport vp) {
669
722
}
670
723
}
671
724
672
- private static final class SetWindowAlphaFunction extends ImPlatformFuncViewportFloat {
725
+ private final class SetWindowAlphaFunction extends ImPlatformFuncViewportFloat {
673
726
@ Override
674
727
public void accept (final ImGuiViewport vp , final float f ) {
675
- final ImGuiViewportDataGlfw data = (ImGuiViewportDataGlfw ) vp .getPlatformUserData ();
676
- glfwSetWindowOpacity (data .window , f );
728
+ if (glfwHasWindowAlpha ) {
729
+ final ImGuiViewportDataGlfw data = (ImGuiViewportDataGlfw ) vp .getPlatformUserData ();
730
+ glfwSetWindowOpacity (data .window , f );
731
+ }
677
732
}
678
733
}
679
734
0 commit comments