diff --git a/Source/Editor/GUI/Docking/FloatWindowDockPanel.cs b/Source/Editor/GUI/Docking/FloatWindowDockPanel.cs
index c96614217..f46b1469b 100644
--- a/Source/Editor/GUI/Docking/FloatWindowDockPanel.cs
+++ b/Source/Editor/GUI/Docking/FloatWindowDockPanel.cs
@@ -11,6 +11,39 @@ namespace FlaxEditor.GUI.Docking
///
public class FloatWindowDockPanel : DockPanel
{
+ private class FloatWindowDecorations : WindowDecorations
+ {
+ private FloatWindowDockPanel _panel;
+
+ public FloatWindowDecorations(FloatWindowDockPanel panel) : base(panel.RootWindow)
+ {
+ _panel = panel;
+ }
+
+ ///
+ public override bool OnMouseDown(Float2 location, MouseButton button)
+ {
+ if (Title.Bounds.Contains(location) && button == MouseButton.Left)
+ {
+ _panel.BeginDrag();
+ return true;
+ }
+ return base.OnMouseDown(location, button);
+ }
+
+ ///
+ protected override WindowHitCodes OnHitTest(ref Float2 mouse)
+ {
+ var hit = base.OnHitTest(ref mouse);
+ if (hit == WindowHitCodes.Caption)
+ {
+ // Override the system behaviour when interacting with the caption area
+ hit = WindowHitCodes.Client;
+ }
+ return hit;
+ }
+ }
+
private MasterDockPanel _masterPanel;
private WindowRootControl _window;
@@ -40,6 +73,26 @@ namespace FlaxEditor.GUI.Docking
Parent = window;
_window.Window.Closing += OnClosing;
_window.Window.LeftButtonHit += OnLeftButtonHit;
+
+ if (Utilities.Utils.UseCustomWindowDecorations())
+ {
+ var decorations = Parent.AddChild(new FloatWindowDecorations(this));
+ decorations.SetAnchorPreset(AnchorPresets.HorizontalStretchTop, false);
+ }
+ }
+
+ ///
+ protected override void PerformLayoutBeforeChildren()
+ {
+ base.PerformLayoutBeforeChildren();
+
+ var decorations = Parent.GetChild();
+ if (decorations != null)
+ {
+ // Apply offset for the title bar
+ foreach (var child in Children)
+ child.Bounds = child.Bounds with { Y = decorations.Height, Height = Parent.Height - decorations.Height };
+ }
}
///
@@ -87,6 +140,12 @@ namespace FlaxEditor.GUI.Docking
settings.ShowAfterFirstPaint = false;
settings.ShowInTaskbar = true;
settings.StartPosition = startPosition;
+
+ if (Utilities.Utils.UseCustomWindowDecorations())
+ {
+ settings.HasBorder = false;
+ //settings.HasSizingFrame = false;
+ }
// Create window
return Platform.CreateWindow(ref settings);
diff --git a/Source/Editor/GUI/MainMenu.cs b/Source/Editor/GUI/MainMenu.cs
index 3dccf399c..30f988fe1 100644
--- a/Source/Editor/GUI/MainMenu.cs
+++ b/Source/Editor/GUI/MainMenu.cs
@@ -12,16 +12,6 @@ namespace FlaxEditor.GUI
///
public sealed class MainMenu : ContainerControl
{
-#if PLATFORM_WINDOWS || PLATFORM_SDL
- private bool _useCustomWindowSystem;
- private Image _icon;
- private Label _title;
- private Button _closeButton;
- private Button _minimizeButton;
- private Button _maximizeButton;
- private LocalizedString _charChromeRestore, _charChromeMaximize;
- private Window _window;
-#endif
private MainMenuButton _selected;
///
@@ -60,202 +50,15 @@ namespace FlaxEditor.GUI
///
/// Initializes a new instance of the class.
///
- /// The main window.
- public MainMenu(RootControl mainWindow)
+ public MainMenu()
: base(0, 0, 0, 20)
{
AutoFocus = false;
AnchorPreset = AnchorPresets.HorizontalStretchTop;
+ BackgroundColor = Style.Current.LightBackground;
-#if PLATFORM_WINDOWS || PLATFORM_SDL
- _useCustomWindowSystem = !Editor.Instance.Options.Options.Interface.UseNativeWindowSystem;
- if (_useCustomWindowSystem)
- {
- BackgroundColor = Style.Current.LightBackground;
+ if (Utilities.Utils.UseCustomWindowDecorations())
Height = 28;
-
- var windowIcon = FlaxEngine.Content.LoadAsyncInternal(EditorAssets.WindowIcon);
- FontAsset windowIconsFont = FlaxEngine.Content.LoadAsyncInternal(EditorAssets.WindowIconsFont);
- Font iconFont = windowIconsFont?.CreateFont(9);
-
- _window = mainWindow.RootWindow.Window;
- _window.HitTest += OnHitTest;
- _window.Closed += OnWindowClosed;
-
- ScriptsBuilder.GetBinariesConfiguration(out _, out _, out _, out var configuration);
-
- var driver = Platform.DisplayServer;
-
- _icon = new Image
- {
- Margin = new Margin(6, 6, 6, 6),
- Brush = new TextureBrush(windowIcon),
- Color = Style.Current.Foreground,
- KeepAspectRatio = false,
- TooltipText = string.Format("{0}\nVersion {1}\nConfiguration {3}\nGraphics {2} {4}", _window.Title, Globals.EngineVersion, GPUDevice.Instance.RendererType, configuration, driver),
- Parent = this,
- };
-
- _title = new Label(0, 0, Width, Height)
- {
- Text = _window.Title,
- HorizontalAlignment = TextAlignment.Center,
- VerticalAlignment = TextAlignment.Center,
- ClipText = true,
- TextColor = Style.Current.ForegroundGrey,
- TextColorHighlighted = Style.Current.ForegroundGrey,
- Parent = this,
- };
-
- _closeButton = new Button
- {
- Text = ((char)EditorAssets.SegMDL2Icons.ChromeClose).ToString(),
- Font = new FontReference(iconFont),
- BackgroundColor = Color.Transparent,
- BorderColor = Color.Transparent,
- BorderColorHighlighted = Color.Transparent,
- BorderColorSelected = Color.Transparent,
- TextColor = Style.Current.Foreground,
- Width = 46,
- BackgroundColorHighlighted = Color.Red,
- BackgroundColorSelected = Color.Red.RGBMultiplied(1.3f),
- Parent = this,
- };
- _closeButton.Clicked += () => _window.Close(ClosingReason.User);
-
- _minimizeButton = new Button
- {
- Text = ((char)EditorAssets.SegMDL2Icons.ChromeMinimize).ToString(),
- Font = new FontReference(iconFont),
- BackgroundColor = Color.Transparent,
- BorderColor = Color.Transparent,
- BorderColorHighlighted = Color.Transparent,
- BorderColorSelected = Color.Transparent,
- TextColor = Style.Current.Foreground,
- Width = 46,
- BackgroundColorHighlighted = Style.Current.LightBackground.RGBMultiplied(1.3f),
- Parent = this,
- };
- _minimizeButton.Clicked += () => _window.Minimize();
-
- _maximizeButton = new Button
- {
- Text = ((char)(_window.IsMaximized ? EditorAssets.SegMDL2Icons.ChromeRestore : EditorAssets.SegMDL2Icons.ChromeMaximize)).ToString(),
- Font = new FontReference(iconFont),
- BackgroundColor = Color.Transparent,
- BorderColor = Color.Transparent,
- BorderColorHighlighted = Color.Transparent,
- BorderColorSelected = Color.Transparent,
- TextColor = Style.Current.Foreground,
- Width = 46,
- BackgroundColorHighlighted = Style.Current.LightBackground.RGBMultiplied(1.3f),
- Parent = this,
- };
- _maximizeButton.Clicked += () =>
- {
- if (_window.IsMaximized)
- _window.Restore();
- else
- _window.Maximize();
- };
- _charChromeRestore = ((char)EditorAssets.SegMDL2Icons.ChromeRestore).ToString();
- _charChromeMaximize = ((char)EditorAssets.SegMDL2Icons.ChromeMaximize).ToString();
- }
- else
-#endif
- {
- BackgroundColor = Style.Current.LightBackground;
- }
- }
-
-#if PLATFORM_WINDOWS || PLATFORM_SDL
- ///
- public override void Update(float deltaTime)
- {
- base.Update(deltaTime);
-
- if (_maximizeButton != null)
- {
- _maximizeButton.Text = _window.IsMaximized ? _charChromeRestore : _charChromeMaximize;
- }
- }
-
- private void OnWindowClosed()
- {
- if (_window != null)
- {
- _window.HitTest = null;
- _window = null;
- }
- }
-
- private WindowHitCodes OnHitTest(ref Float2 mouse)
- {
- var dpiScale = _window.DpiScale;
-
- if (_window.IsMinimized)
- return WindowHitCodes.NoWhere;
-
- if (!_window.IsMaximized)
- {
- var pos = _window.ScreenToClient(mouse * dpiScale); // pos is not DPI adjusted
- var winSize = _window.Size;
-
- // Distance from which the mouse is considered to be on the border/corner
- float distance = 5.0f * dpiScale;
-
- if (pos.Y > winSize.Y - distance && pos.X < distance)
- return WindowHitCodes.BottomLeft;
-
- if (pos.X > winSize.X - distance && pos.Y > winSize.Y - distance)
- return WindowHitCodes.BottomRight;
-
- if (pos.Y < distance && pos.X < distance)
- return WindowHitCodes.TopLeft;
-
- if (pos.Y < distance && pos.X > winSize.X - distance)
- return WindowHitCodes.TopRight;
-
- if (pos.X > winSize.X - distance)
- return WindowHitCodes.Right;
-
- if (pos.X < distance)
- return WindowHitCodes.Left;
-
- if (pos.Y < distance)
- return WindowHitCodes.Top;
-
- if (pos.Y > winSize.Y - distance)
- return WindowHitCodes.Bottom;
- }
-
- var mousePos = PointFromScreen(mouse * dpiScale);
- var controlUnderMouse = GetChildAt(mousePos);
- var isMouseOverSth = controlUnderMouse != null && controlUnderMouse != _title;
- var rb = GetRightButton();
- if (rb != null && _minimizeButton != null && new Rectangle(rb.UpperRight, _minimizeButton.BottomLeft - rb.UpperRight).Contains(ref mousePos) && !isMouseOverSth)
- return WindowHitCodes.Caption;
-
- return WindowHitCodes.Client;
- }
-#endif
-
- ///
- /// Return the rightmost button.
- ///
- /// Rightmost button, null if there is no
- private MainMenuButton GetRightButton()
- {
- MainMenuButton b = null;
- foreach (var control in Children)
- {
- if (b == null && control is MainMenuButton)
- b = (MainMenuButton)control;
-
- if (control is MainMenuButton && control.Right > b.Right)
- b = (MainMenuButton)control;
- }
- return b;
}
///
@@ -300,26 +103,6 @@ namespace FlaxEditor.GUI
return result;
}
- ///
- public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
- {
- if (base.OnMouseDoubleClick(location, button))
- return true;
-
-#if PLATFORM_WINDOWS || PLATFORM_SDL
- var child = GetChildAtRecursive(location);
- if (_useCustomWindowSystem && child is not Button && child is not MainMenuButton)
- {
- if (_window.IsMaximized)
- _window.Restore();
- else
- _window.Maximize();
- }
-#endif
-
- return true;
- }
-
///
public override bool OnKeyDown(KeyboardKeys key)
{
@@ -334,17 +117,14 @@ namespace FlaxEditor.GUI
///
protected override void PerformLayoutAfterChildren()
{
- float x = 0;
-
-#if PLATFORM_WINDOWS || PLATFORM_SDL
- if (_useCustomWindowSystem)
+ WindowDecorations decorations = Parent.GetChild();
+ if (decorations == null)
{
- // Icon
- _icon.X = x;
- _icon.Size = new Float2(Height);
- x += _icon.Width;
+ Width = Parent.Width;
+ return;
}
-#endif
+
+ float x = decorations.Icon?.Width ?? 0;
// Arrange controls
MainMenuButton rightMostButton = null;
@@ -363,37 +143,16 @@ namespace FlaxEditor.GUI
x += b.Width;
}
}
-
-#if PLATFORM_WINDOWS || PLATFORM_SDL
- if (_useCustomWindowSystem)
- {
- // Buttons
- _closeButton.Height = Height;
- _closeButton.X = Width - _closeButton.Width;
- _maximizeButton.Height = Height;
- _maximizeButton.X = _closeButton.X - _maximizeButton.Width;
- _minimizeButton.Height = Height;
- _minimizeButton.X = _maximizeButton.X - _minimizeButton.Width;
-
- // Title
- _title.Bounds = new Rectangle(x + 2, 0, _minimizeButton.Left - x - 4, Height);
- //_title.Text = _title.Width < 300.0f ? Editor.Instance.ProjectInfo.Name : _window.Title;
- }
-#endif
+ Width = x;
}
-#if PLATFORM_WINDOWS || PLATFORM_SDL
///
public override void OnDestroy()
{
base.OnDestroy();
-
- if (_window != null)
- {
- _window.Closed -= OnWindowClosed;
- OnWindowClosed();
- }
+
+ if (_selected != null)
+ Selected = null;
}
-#endif
}
}
diff --git a/Source/Editor/GUI/MainMenuButton.cs b/Source/Editor/GUI/MainMenuButton.cs
index 2c64b59c1..5007af92e 100644
--- a/Source/Editor/GUI/MainMenuButton.cs
+++ b/Source/Editor/GUI/MainMenuButton.cs
@@ -42,14 +42,12 @@ namespace FlaxEditor.GUI
Text = text;
var style = Style.Current;
-#if PLATFORM_WINDOWS || PLATFORM_SDL
- if (Editor.Instance.Options.Options.Interface.UseNativeWindowSystem)
+ if (!Utilities.Utils.UseCustomWindowDecorations())
{
BackgroundColorMouseOver = style.BackgroundHighlighted;
BackgroundColorMouseOverOpened = style.Background;
}
else
-#endif
{
BackgroundColorMouseOver = BackgroundColorMouseOverOpened = style.LightBackground * 1.3f;
}
diff --git a/Source/Editor/GUI/WindowDecorations.cs b/Source/Editor/GUI/WindowDecorations.cs
new file mode 100644
index 000000000..35c026b6e
--- /dev/null
+++ b/Source/Editor/GUI/WindowDecorations.cs
@@ -0,0 +1,314 @@
+// Copyright (c) Wojciech Figat. All rights reserved.
+
+using System;
+using FlaxEditor.GUI.Docking;
+using FlaxEditor.Options;
+using FlaxEngine;
+using FlaxEngine.GUI;
+
+namespace FlaxEditor.GUI;
+
+///
+/// Represents the title bar of the window with buttons.
+///
+///
+public class WindowDecorations : ContainerControl
+{
+ private Image _icon;
+ private Label _title;
+ private Button _closeButton;
+ private Button _minimizeButton;
+ private Button _maximizeButton;
+ private LocalizedString _charChromeRestore, _charChromeMaximize;
+ private Window _window;
+
+ ///
+ /// The title label in the title bar.
+ ///
+ public Label Title => _title;
+
+ ///
+ /// The icon used in the title bar.
+ ///
+ public Image Icon => _icon;
+
+ ///
+ /// The tooltip shown when hovering over the icon.
+ ///
+ public string IconTooltipText
+ {
+ get => _icon?.TooltipText ?? null;
+ set
+ {
+ if (_icon != null)
+ _icon.TooltipText = value;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The window.
+ public WindowDecorations(RootControl window)
+ : base(0, 0, 0, 20)
+ {
+ AutoFocus = false;
+ AnchorPreset = AnchorPresets.HorizontalStretchTop;
+
+ //BackgroundColor = Style.Current.LightBackground;
+ BackgroundColor = Color.Transparent;
+ Height = 28;
+
+ var windowIcon = FlaxEngine.Content.LoadAsyncInternal(EditorAssets.WindowIcon);
+ FontAsset windowIconsFont = FlaxEngine.Content.LoadAsyncInternal(EditorAssets.WindowIconsFont);
+ Font iconFont = windowIconsFont?.CreateFont(9);
+
+ _window = window.RootWindow.Window;
+ _window.HitTest += OnHitTest;
+ _window.Closed += OnWindowClosed;
+
+ _icon = new Image
+ {
+ Margin = new Margin(6, 6, 6, 6),
+ Brush = new TextureBrush(windowIcon),
+ Color = Style.Current.Foreground,
+ BackgroundColor = Style.Current.LightBackground,
+ KeepAspectRatio = false,
+ Parent = this,
+ };
+
+ _title = new Label(0, 0, Width, Height)
+ {
+ Text = _window.Title,
+ HorizontalAlignment = TextAlignment.Center,
+ VerticalAlignment = TextAlignment.Center,
+ ClipText = true,
+ TextColor = Style.Current.ForegroundGrey,
+ TextColorHighlighted = Style.Current.ForegroundGrey,
+ BackgroundColor = Style.Current.LightBackground,
+ Parent = this,
+ };
+
+ _closeButton = new Button
+ {
+ Text = ((char)EditorAssets.SegMDL2Icons.ChromeClose).ToString(),
+ Font = new FontReference(iconFont),
+ BackgroundColor = Style.Current.LightBackground,
+ BorderColor = Color.Transparent,
+ BorderColorHighlighted = Color.Transparent,
+ BorderColorSelected = Color.Transparent,
+ TextColor = Style.Current.Foreground,
+ Width = 46,
+ BackgroundColorHighlighted = Color.Red,
+ BackgroundColorSelected = Color.Red.RGBMultiplied(1.3f),
+ Parent = this,
+ };
+ _closeButton.Clicked += () => _window.Close(ClosingReason.User);
+
+ _minimizeButton = new Button
+ {
+ Text = ((char)EditorAssets.SegMDL2Icons.ChromeMinimize).ToString(),
+ Font = new FontReference(iconFont),
+ BackgroundColor = Style.Current.LightBackground,
+ BorderColor = Color.Transparent,
+ BorderColorHighlighted = Color.Transparent,
+ BorderColorSelected = Color.Transparent,
+ TextColor = Style.Current.Foreground,
+ Width = 46,
+ BackgroundColorHighlighted = Style.Current.LightBackground.RGBMultiplied(1.3f),
+ Parent = this,
+ };
+ _minimizeButton.Clicked += () => _window.Minimize();
+
+ _maximizeButton = new Button
+ {
+ Text = ((char)(_window.IsMaximized ? EditorAssets.SegMDL2Icons.ChromeRestore : EditorAssets.SegMDL2Icons.ChromeMaximize)).ToString(),
+ Font = new FontReference(iconFont),
+ BackgroundColor = Style.Current.LightBackground,
+ BorderColor = Color.Transparent,
+ BorderColorHighlighted = Color.Transparent,
+ BorderColorSelected = Color.Transparent,
+ TextColor = Style.Current.Foreground,
+ Width = 46,
+ BackgroundColorHighlighted = Style.Current.LightBackground.RGBMultiplied(1.3f),
+ Parent = this,
+ };
+ _maximizeButton.Clicked += () =>
+ {
+ if (_window.IsMaximized)
+ _window.Restore();
+ else
+ _window.Maximize();
+ };
+
+ _charChromeRestore = ((char)EditorAssets.SegMDL2Icons.ChromeRestore).ToString();
+ _charChromeMaximize = ((char)EditorAssets.SegMDL2Icons.ChromeMaximize).ToString();
+ }
+
+ ///
+ public override void Update(float deltaTime)
+ {
+ base.Update(deltaTime);
+
+ if (_maximizeButton != null)
+ {
+ var maximizeText = _window.IsMaximized ? _charChromeRestore : _charChromeMaximize;
+ if (_maximizeButton.Text != maximizeText)
+ _maximizeButton.Text = maximizeText;
+ }
+ }
+
+ private void OnWindowClosed()
+ {
+ if (_window != null)
+ {
+ _window.HitTest -= OnHitTest;
+ _window = null;
+ }
+ }
+
+ ///
+ /// Perform hit test on the window.
+ ///
+ /// The mouse position
+ /// The hit code for given position.
+ protected virtual WindowHitCodes OnHitTest(ref Float2 mouse)
+ {
+ if (_window.IsMinimized)
+ return WindowHitCodes.NoWhere;
+
+ var dpiScale = _window.DpiScale;
+ var pos = _window.ScreenToClient(mouse * dpiScale); // pos is not DPI adjusted
+ if (!_window.IsMaximized)
+ {
+ var winSize = _window.Size;
+
+ // Distance from which the mouse is considered to be on the border/corner
+ float distance = 5.0f * dpiScale;
+
+ if (pos.Y > winSize.Y - distance && pos.X < distance)
+ return WindowHitCodes.BottomLeft;
+
+ if (pos.X > winSize.X - distance && pos.Y > winSize.Y - distance)
+ return WindowHitCodes.BottomRight;
+
+ if (pos.Y < distance && pos.X < distance)
+ return WindowHitCodes.TopLeft;
+
+ if (pos.Y < distance && pos.X > winSize.X - distance)
+ return WindowHitCodes.TopRight;
+
+ if (pos.X > winSize.X - distance)
+ return WindowHitCodes.Right;
+
+ if (pos.X < distance)
+ return WindowHitCodes.Left;
+
+ if (pos.Y < distance)
+ return WindowHitCodes.Top;
+
+ if (pos.Y > winSize.Y - distance)
+ return WindowHitCodes.Bottom;
+ }
+
+ var controlUnderMouse = GetChildAt(pos, control => control != _title);
+ if (_title.Bounds.Contains(pos) && controlUnderMouse == null)
+ return WindowHitCodes.Caption;
+
+ return WindowHitCodes.Client;
+ }
+
+ ///
+ public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
+ {
+ // These may not work with main window due to SDL not passing mouse events
+ // when interacting with hit tests on caption area...
+
+ if (Title.Bounds.Contains(location) && button == MouseButton.Left)
+ {
+ if (_window.IsMaximized)
+ _window.Restore();
+ else
+ _window.Maximize();
+ return true;
+ }
+ else if (Icon.Bounds.Contains(location) && button == MouseButton.Left)
+ {
+ _window.Close(ClosingReason.User);
+ return true;
+ }
+ return base.OnMouseDoubleClick(location, button);
+ }
+
+ ///
+ protected override void PerformLayoutAfterChildren()
+ {
+ // Calculate extents for title bounds area excluding the icon and main menu area
+ float x = 0;
+
+ // Icon
+ _icon.X = x;
+ _icon.Size = new Float2(Height);
+ x += _icon.Width;
+
+ // Main menu if present
+ if (Parent.GetChild() is MainMenu mainMenu)
+ {
+ for (int i = 0; i < mainMenu.Children.Count; i++)
+ {
+ var c = mainMenu.Children[i];
+ if (c is MainMenuButton b && c.Visible)
+ {
+ b.Bounds = new Rectangle(x, 0, b.Width, Height);
+ x += b.Width;
+ }
+ }
+ }
+
+ // Buttons
+ _closeButton.Height = Height;
+ _closeButton.X = Width - _closeButton.Width;
+ _maximizeButton.Height = Height;
+ _maximizeButton.X = _closeButton.X - _maximizeButton.Width;
+ _minimizeButton.Height = Height;
+ _minimizeButton.X = _maximizeButton.X - _minimizeButton.Width;
+
+ // Title
+ _title.Text = _window.Title;
+ _title.Bounds = new Rectangle(x, 0, _minimizeButton.Left - x, Height);
+ }
+
+ ///
+ public override void Draw()
+ {
+ base.Draw();
+ DrawBorders();
+ }
+
+ ///
+ /// Draw borders around the window.
+ ///
+ public virtual void DrawBorders()
+ {
+ var win = RootWindow.Window;
+ if (win.IsMaximized)
+ return;
+
+ const float thickness = 1.0f;
+ Color color = Editor.Instance.UI.StatusBar.StatusColor;
+ Rectangle rect = new Rectangle(thickness * 0.5f, thickness * 0.5f, Parent.Width - thickness, Parent.Height - thickness);
+ Render2D.DrawRectangle(rect, color);
+ }
+
+ ///
+ public override void OnDestroy()
+ {
+ base.OnDestroy();
+
+ if (_window != null)
+ {
+ _window.Closed -= OnWindowClosed;
+ OnWindowClosed();
+ }
+ }
+}
diff --git a/Source/Editor/Modules/UIModule.cs b/Source/Editor/Modules/UIModule.cs
index 191f3a975..7969ec6a8 100644
--- a/Source/Editor/Modules/UIModule.cs
+++ b/Source/Editor/Modules/UIModule.cs
@@ -16,7 +16,6 @@ using FlaxEditor.Windows;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Json;
-using WindowDragHelper = FlaxEditor.GUI.Docking.WindowDragHelper;
using MasterDockPanel = FlaxEditor.GUI.Docking.MasterDockPanel;
using FlaxEditor.Content.Settings;
using FlaxEditor.Options;
@@ -29,6 +28,40 @@ namespace FlaxEditor.Modules
///
public sealed class UIModule : EditorModule
{
+ private class MainWindowDecorations : WindowDecorations
+ {
+ public MainWindowDecorations(RootControl window)
+ : base(window)
+ {
+ }
+
+ ///
+ public override bool OnKeyDown(KeyboardKeys key)
+ {
+ if (base.OnKeyDown(key))
+ return true;
+
+ // Fallback to the edit window for shortcuts
+ var editor = Editor.Instance;
+ return editor.Windows.EditWin.InputActions.Process(editor, this, key);
+ }
+
+ ///
+ public override void DrawBorders()
+ {
+ // Draw main window borders if using a custom style
+ var win = RootWindow.Window;
+ if (win.IsMaximized)
+ return;
+
+ var color = Editor.Instance.UI.StatusBar.StatusColor;
+ var rect = new Rectangle(0.5f, 0.5f, Parent.Width - 1.0f, Parent.Height - 1.0f - StatusBar.DefaultHeight);
+ Render2D.DrawLine(rect.UpperLeft, rect.UpperRight, color);
+ Render2D.DrawLine(rect.UpperLeft, rect.BottomLeft, color);
+ Render2D.DrawLine(rect.UpperRight, rect.BottomRight, color);
+ }
+ }
+
private Label _progressLabel;
private ProgressBar _progressBar;
private Button _outputLogButton;
@@ -97,6 +130,11 @@ namespace FlaxEditor.Modules
///
public MainMenu MainMenu;
+ ///
+ /// The window decorations (title bar with buttons)
+ ///
+ public WindowDecorations WindowDecorations;
+
///
/// The tool strip control.
///
@@ -377,19 +415,11 @@ namespace FlaxEditor.Modules
InitToolstrip(mainWindow);
InitStatusBar(mainWindow);
InitDockPanel(mainWindow);
+ InitWindowDecorations(mainWindow);
Editor.Options.OptionsChanged += OnOptionsChanged;
-
- // Add dummy control for drawing the main window borders if using a custom style
-#if PLATFORM_WINDOWS || PLATFORM_SDL
- if (!Editor.Options.Options.Interface.UseNativeWindowSystem)
-#endif
- {
- mainWindow.AddChild(new CustomWindowBorderControl
- {
- Size = Float2.Zero,
- });
- }
+
+ mainWindow.PerformLayout(true);
}
///
@@ -410,23 +440,6 @@ namespace FlaxEditor.Modules
}
}
- private class CustomWindowBorderControl : Control
- {
- ///
- public override void Draw()
- {
- var win = RootWindow.Window;
- if (win.IsMaximized)
- return;
-
- var color = Editor.Instance.UI.StatusBar.StatusColor;
- var rect = new Rectangle(0.5f, 0.5f, Parent.Width - 1.0f, Parent.Height - 1.0f - StatusBar.DefaultHeight);
- Render2D.DrawLine(rect.UpperLeft, rect.UpperRight, color);
- Render2D.DrawLine(rect.UpperLeft, rect.BottomLeft, color);
- Render2D.DrawLine(rect.UpperRight, rect.BottomRight, color);
- }
- }
-
///
public override void OnEndInit()
{
@@ -511,7 +524,7 @@ namespace FlaxEditor.Modules
private void InitMainMenu(RootControl mainWindow)
{
- MainMenu = new MainMenu(mainWindow)
+ MainMenu = new MainMenu()
{
Parent = mainWindow
};
@@ -654,6 +667,23 @@ namespace FlaxEditor.Modules
cm.AddButton("Information about Flax", () => new AboutDialog().Show());
}
+ private void InitWindowDecorations(RootControl mainWindow)
+ {
+ if (!Utilities.Utils.UseCustomWindowDecorations(isMainWindow: true))
+ return;
+
+ ScriptsBuilder.GetBinariesConfiguration(out _, out _, out _, out var configuration);
+ var driver = Platform.DisplayServer;
+ if (!string.IsNullOrEmpty(driver))
+ driver = $" ({driver})";
+
+ WindowDecorations = new MainWindowDecorations(mainWindow)
+ {
+ Parent = mainWindow,
+ IconTooltipText = $"{mainWindow.RootWindow.Title}\nVersion {Globals.EngineVersion}\nConfiguration {configuration}\nGraphics {GPUDevice.Instance.RendererType}{driver}",
+ };
+ }
+
private void OnOptionsChanged(EditorOptions options)
{
var inputOptions = options.Input;
@@ -1063,6 +1093,7 @@ namespace FlaxEditor.Modules
{
// Clear UI references (GUI cannot be used after window closing)
MainMenu = null;
+ WindowDecorations = null;
ToolStrip = null;
MasterPanel = null;
StatusBar = null;
diff --git a/Source/Editor/Modules/WindowsModule.cs b/Source/Editor/Modules/WindowsModule.cs
index 3e7ce2d9f..a87531f74 100644
--- a/Source/Editor/Modules/WindowsModule.cs
+++ b/Source/Editor/Modules/WindowsModule.cs
@@ -761,17 +761,16 @@ namespace FlaxEditor.Modules
settings.MinimumSize = new Float2(200, 150);
settings.StartPosition = WindowStartPosition.CenterScreen;
settings.ShowAfterFirstPaint = true;
-#if PLATFORM_WINDOWS
- if (!Editor.Instance.Options.Options.Interface.UseNativeWindowSystem)
+
+ if (Utilities.Utils.UseCustomWindowDecorations(isMainWindow: true))
{
settings.HasBorder = false;
-
-#if !PLATFORM_SDL
+#if PLATFORM_WINDOWS && !PLATFORM_SDL
// Skip OS sizing frame and implement it using LeftButtonHit
settings.HasSizingFrame = false;
#endif
}
-#elif PLATFORM_LINUX
+#if PLATFORM_LINUX && !PLATFORM_SDL
settings.HasBorder = false;
#endif
MainWindow = Platform.CreateWindow(ref settings);
diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs
index ffa13ac29..af804e1df 100644
--- a/Source/Editor/Options/InterfaceOptions.cs
+++ b/Source/Editor/Options/InterfaceOptions.cs
@@ -160,21 +160,47 @@ namespace FlaxEditor.Options
GameWindowThenRestore,
}
+ ///
+ /// Options for type of window decorations to use.
+ ///
+ public enum WindowDecorationsType
+ {
+ ///
+ /// Determined automatically based on the system and any known compatibility issues with native decorations.
+ ///
+ Auto,
+
+ ///
+ /// Automatically choose most compatible window decorations for child windows, prefer custom decorations on main window.
+ ///
+ [EditorDisplay(Name = "Auto (Child Only)")]
+ AutoChildOnly,
+
+ ///
+ /// Use native system window decorations on all windows.
+ ///
+ Native,
+
+ ///
+ /// Use custom client-side window decorations on all windows.
+ ///
+ [EditorDisplay(Name = "Client-side")]
+ ClientSide,
+ }
+
///
/// Gets or sets the Editor User Interface scale. Applied to all UI elements, windows and text. Can be used to scale the interface up on a bigger display. Editor restart required.
///
[DefaultValue(1.0f), Limit(0.1f, 10.0f)]
[EditorDisplay("Interface"), EditorOrder(10), Tooltip("Editor User Interface scale. Applied to all UI elements, windows and text. Can be used to scale the interface up on a bigger display. Editor restart required.")]
public float InterfaceScale { get; set; } = 1.0f;
-
-#if PLATFORM_WINDOWS || PLATFORM_SDL
+
///
- /// Gets or sets a value indicating whether use native window title bar. Editor restart required.
+ /// Gets or sets a value indicating whether use native window title bar decorations in child windows. Editor restart required.
///
- [DefaultValue(false)]
- [EditorDisplay("Interface"), EditorOrder(70), Tooltip("Determines whether use native window title bar. Editor restart required.")]
- public bool UseNativeWindowSystem { get; set; } = false;
-#endif
+ [DefaultValue(WindowDecorationsType.Auto)]
+ [EditorDisplay("Interface"), EditorOrder(70), Tooltip("Determines whether use native window title bar decorations. Editor restart required.")]
+ public WindowDecorationsType WindowDecorations { get; set; } = WindowDecorationsType.Auto;
///
/// Gets or sets a value indicating whether show selected camera preview in the editor window.
diff --git a/Source/Editor/Utilities/Utils.cs b/Source/Editor/Utilities/Utils.cs
index 949479783..284a0b6c6 100644
--- a/Source/Editor/Utilities/Utils.cs
+++ b/Source/Editor/Utilities/Utils.cs
@@ -1559,5 +1559,17 @@ namespace FlaxEditor.Utilities
c = c.Parent;
return c as ISceneEditingContext;
}
+
+ internal static bool UseCustomWindowDecorations(bool isMainWindow = false)
+ {
+ return Editor.Instance.Options.Options.Interface.WindowDecorations switch
+ {
+ Options.InterfaceOptions.WindowDecorationsType.Auto => !Platform.SupportsNativeDecorations,
+ Options.InterfaceOptions.WindowDecorationsType.AutoChildOnly => !isMainWindow ? !Platform.SupportsNativeDecorations : true,
+ Options.InterfaceOptions.WindowDecorationsType.Native => false,
+ Options.InterfaceOptions.WindowDecorationsType.ClientSide => true,
+ _ => throw new ArgumentOutOfRangeException()
+ };
+ }
}
}
diff --git a/Source/Engine/Platform/Base/PlatformBase.cpp b/Source/Engine/Platform/Base/PlatformBase.cpp
index d16521c24..7a93c24ed 100644
--- a/Source/Engine/Platform/Base/PlatformBase.cpp
+++ b/Source/Engine/Platform/Base/PlatformBase.cpp
@@ -269,6 +269,11 @@ String PlatformBase::GetDisplayServer()
return String::Empty;
}
+bool PlatformBase::SupportsNativeDecorations()
+{
+ return true;
+}
+
#endif
bool PlatformBase::Is64BitApp()
diff --git a/Source/Engine/Platform/Base/PlatformBase.h b/Source/Engine/Platform/Base/PlatformBase.h
index ae8f6537e..97928c376 100644
--- a/Source/Engine/Platform/Base/PlatformBase.h
+++ b/Source/Engine/Platform/Base/PlatformBase.h
@@ -374,6 +374,11 @@ public:
///
API_PROPERTY() static String GetDisplayServer();
+ ///
+ /// Returns true if system provides decorations for windows.
+ ///
+ API_PROPERTY() static bool SupportsNativeDecorations();
+
///
/// Returns true if is running 64 bit application (otherwise 32 bit). It's compile-time constant.
///
diff --git a/Source/Engine/Platform/SDL/SDLPlatform.Linux.cpp b/Source/Engine/Platform/SDL/SDLPlatform.Linux.cpp
index 4b300a3f0..3d7e72e83 100644
--- a/Source/Engine/Platform/SDL/SDLPlatform.Linux.cpp
+++ b/Source/Engine/Platform/SDL/SDLPlatform.Linux.cpp
@@ -35,6 +35,12 @@
#include
#include
+namespace SDLImpl
+{
+ extern String WaylandDisplayEnv;
+ extern String XDGCurrentDesktop;
+}
+
class LinuxDropFilesData : public IGuiData
{
public:
@@ -1611,8 +1617,7 @@ bool SDLPlatform::InitInternal()
if (!CommandLine::Options.Headless.IsTrue() && waylandRequested)
{
// Ignore in X11 session
- String waylandDisplayEnv;
- if (!GetEnvironmentVariable(String("WAYLAND_DISPLAY"), waylandDisplayEnv))
+ if (!SDLImpl::WaylandDisplayEnv.IsEmpty())
{
WaylandImpl::WaylandDisplay = (wl_display*)SDL_GetPointerProperty(SDL_GetGlobalProperties(), SDL_PROP_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER, nullptr);
if (WaylandImpl::WaylandDisplay != nullptr)
@@ -1721,11 +1726,15 @@ DragDropEffect SDLWindow::DoDragDrop(const StringView& data, const Float2& offse
if (SDLPlatform::UsesWayland())
{
Float2 dragOffset = offset;
- if (_settings.HasBorder && dragSourceWindow == this)
+ if (SDLPlatform::SupportsNativeDecorations() && _settings.HasBorder && dragSourceWindow == this)
{
// Wayland includes the decorations in the client-space coordinates, adjust the offset for it.
- // Assume the title decoration is 25px thick...
+ // Assume the title decoration based on the current desktop environment...
float topOffset = 25.0f;
+ if (SDLImpl::XDGCurrentDesktop.Compare(String("KDE"), StringSearchCase::IgnoreCase) == 0)
+ topOffset = 25.0f;
+ else if (SDLImpl::XDGCurrentDesktop.Compare(String("GNOME"), StringSearchCase::IgnoreCase) == 0)
+ topOffset = 48.0f;
dragOffset += Float2(0.0f, topOffset);
}
diff --git a/Source/Engine/Platform/SDL/SDLPlatform.cpp b/Source/Engine/Platform/SDL/SDLPlatform.cpp
index b245a6e22..71bf02625 100644
--- a/Source/Engine/Platform/SDL/SDLPlatform.cpp
+++ b/Source/Engine/Platform/SDL/SDLPlatform.cpp
@@ -27,25 +27,34 @@
#define DefaultDPI 96
-namespace
+namespace SDLImpl
{
int32 SystemDpi = 96;
String UserLocale("en");
+ bool WindowDecorationsSupported = true;
+ String WaylandDisplayEnv;
+ String XDGCurrentDesktop;
}
bool SDLPlatform::Init()
{
#if PLATFORM_LINUX
+ bool waylandSession = false;
+ if (!GetEnvironmentVariable(String("WAYLAND_DISPLAY"), SDLImpl::WaylandDisplayEnv))
+ waylandSession = true;
+ GetEnvironmentVariable(String("XDG_CURRENT_DESKTOP"), SDLImpl::XDGCurrentDesktop);
+
if (CommandLine::Options.X11.IsTrue())
+ {
SDL_SetHintWithPriority(SDL_HINT_VIDEO_DRIVER, "x11", SDL_HINT_OVERRIDE);
+ waylandSession = false;
+ }
else if (CommandLine::Options.Wayland.IsTrue())
SDL_SetHintWithPriority(SDL_HINT_VIDEO_DRIVER, "wayland", SDL_HINT_OVERRIDE);
- else
+ else if (waylandSession)
{
// Override the X11 preference when running in Wayland session
- String waylandDisplayEnv;
- if (!GetEnvironmentVariable(String("WAYLAND_DISPLAY"), waylandDisplayEnv))
- SDL_SetHintWithPriority(SDL_HINT_VIDEO_DRIVER, "wayland", SDL_HINT_OVERRIDE);
+ SDL_SetHintWithPriority(SDL_HINT_VIDEO_DRIVER, "wayland", SDL_HINT_OVERRIDE);
}
#endif
@@ -80,6 +89,13 @@ bool SDLPlatform::Init()
SDL_SetHint(SDL_HINT_VIDEO_WAYLAND_SCALE_TO_DISPLAY, "1");
+ // Workaround for libdecor in Gnome+Wayland causing freezes when interacting with the native decorations
+ if (waylandSession && SDLImpl::XDGCurrentDesktop.Compare(String("GNOME"), StringSearchCase::IgnoreCase) == 0)
+ {
+ SDL_SetHint(SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR, "0");
+ SDLImpl::WindowDecorationsSupported = false;
+ }
+
//if (InitInternal())
// return true;
@@ -95,9 +111,9 @@ bool SDLPlatform::Init()
if (language.StartsWith("en"))
{
if (country != nullptr)
- UserLocale = String::Format(TEXT("{0}-{1}"), String(language), String(locales[i]->country));
+ SDLImpl::UserLocale = String::Format(TEXT("{0}-{1}"), String(language), String(locales[i]->country));
else
- UserLocale = String(language);
+ SDLImpl::UserLocale = String(language);
break;
}
}
@@ -124,7 +140,7 @@ bool SDLPlatform::Init()
SDLInput::Init();
SDLWindow::Init();
- SystemDpi = (int)(SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()) * DefaultDPI);
+ SDLImpl::SystemDpi = (int)(SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()) * DefaultDPI);
//SDL_StartTextInput(); // TODO: Call this only when text input is expected (shows virtual keyboard in some cases)
@@ -183,6 +199,11 @@ String SDLPlatform::GetDisplayServer()
#endif
}
+bool SDLPlatform::SupportsNativeDecorations()
+{
+ return SDLImpl::WindowDecorationsSupported;
+}
+
BatteryInfo SDLPlatform::GetBatteryInfo()
{
BatteryInfo info;
@@ -213,12 +234,12 @@ BatteryInfo SDLPlatform::GetBatteryInfo()
int32 SDLPlatform::GetDpi()
{
- return SystemDpi;
+ return SDLImpl::SystemDpi;
}
String SDLPlatform::GetUserLocaleName()
{
- return UserLocale;
+ return SDLImpl::UserLocale;
}
void SDLPlatform::OpenUrl(const StringView& url)
diff --git a/Source/Engine/Platform/SDL/SDLPlatform.h b/Source/Engine/Platform/SDL/SDLPlatform.h
index a30c8d8c3..b7e556395 100644
--- a/Source/Engine/Platform/SDL/SDLPlatform.h
+++ b/Source/Engine/Platform/SDL/SDLPlatform.h
@@ -74,6 +74,7 @@ public:
static void LogInfo();
static void Tick();
static String GetDisplayServer();
+ static bool SupportsNativeDecorations();
static void SetHighDpiAwarenessEnabled(bool enable);
static BatteryInfo GetBatteryInfo();
static int32 GetDpi();
diff --git a/Source/Engine/Platform/SDL/SDLWindow.cpp b/Source/Engine/Platform/SDL/SDLWindow.cpp
index 6879d0659..13c759b1d 100644
--- a/Source/Engine/Platform/SDL/SDLWindow.cpp
+++ b/Source/Engine/Platform/SDL/SDLWindow.cpp
@@ -25,7 +25,6 @@
#define NOGDI
#include
-#include
#include
#include
#undef CreateWindow
@@ -45,12 +44,12 @@ static_assert(false, "Unsupported Platform");
#define DefaultDPI 96
-namespace WindowImpl
+namespace SDLImpl
{
SDLWindow* LastEventWindow = nullptr;
- static SDL_Cursor* Cursors[SDL_SYSTEM_CURSOR_COUNT] = { nullptr };
+ SDL_Cursor* Cursors[SDL_SYSTEM_CURSOR_COUNT] = { nullptr };
+ extern String XDGCurrentDesktop;
}
-using namespace WindowImpl;
SDL_HitTestResult OnWindowHitTest(SDL_Window* win, const SDL_Point* area, void* data);
void GetRelativeWindowOffset(WindowType type, SDLWindow* parentWindow, Int2& positionOffset);
@@ -208,7 +207,7 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings)
}
#endif
- LastEventWindow = this;
+ SDLImpl::LastEventWindow = this;
#if PLATFORM_LINUX
// Initialize using the shared Display instance from SDL
@@ -263,8 +262,8 @@ void* SDLWindow::GetX11Display() const
SDLWindow::~SDLWindow()
{
- if (LastEventWindow == this)
- LastEventWindow = nullptr;
+ if (SDLImpl::LastEventWindow == this)
+ SDLImpl::LastEventWindow = nullptr;
if (_window == nullptr)
return;
@@ -281,45 +280,48 @@ SDLWindow::~SDLWindow()
_visible = false;
}
+WindowHitCodes SDLWindow::OnWindowHit(const Float2 point)
+{
+ WindowHitCodes hit = WindowHitCodes::Client;
+ if (!IsFullscreen())
+ {
+ Float2 screenPosition = ClientToScreen(point);
+ bool handled = false;
+ OnHitTest(screenPosition, hit, handled);
+ if (!handled)
+ {
+ int margin = _settings.HasBorder ? 0 : 0;
+ auto size = GetClientSize();
+ //if (point.Y < 0)
+ // hit = WindowHitCodes::Caption;
+ if (point.Y < margin && point.X < margin)
+ hit = WindowHitCodes::TopLeft;
+ else if (point.Y < margin && point.X > size.X - margin)
+ hit = WindowHitCodes::TopRight;
+ else if (point.Y < margin)
+ hit = WindowHitCodes::Top;
+ else if (point.X < margin && point.Y > size.Y - margin)
+ hit = WindowHitCodes::BottomLeft;
+ else if (point.X < margin)
+ hit = WindowHitCodes::Left;
+ else if (point.X > size.X - margin && point.Y > size.Y - margin)
+ hit = WindowHitCodes::BottomRight;
+ else if (point.X > size.X - margin)
+ hit = WindowHitCodes::Right;
+ else if (point.Y > size.Y - margin)
+ hit = WindowHitCodes::Bottom;
+ else
+ hit = WindowHitCodes::Client;
+ }
+ }
+ return hit;
+}
+
SDL_HitTestResult OnWindowHitTest(SDL_Window* win, const SDL_Point* area, void* data)
{
- SDLWindow* window = (SDLWindow*)data;
- if (window->IsFullscreen())
- return SDL_HITTEST_NORMAL;
-
- Float2 clientPosition = Float2(static_cast(area->x), static_cast(area->y));
- Float2 screenPosition = window->ClientToScreen(clientPosition);
-
- WindowHitCodes hit = WindowHitCodes::Client;
- bool handled = false;
- window->OnHitTest(screenPosition, hit, handled);
-
- if (!handled)
- {
- int margin = window->GetSettings().HasBorder ? 0 : 0;
- auto size = window->GetClientSize();
- //if (clientPosition.Y < 0)
- // return SDL_HITTEST_DRAGGABLE;
- if (clientPosition.Y < margin && clientPosition.X < margin)
- return SDL_HITTEST_RESIZE_TOPLEFT;
- else if (clientPosition.Y < margin && clientPosition.X > size.X - margin)
- return SDL_HITTEST_RESIZE_TOPRIGHT;
- else if (clientPosition.Y < margin)
- return SDL_HITTEST_RESIZE_TOP;
- else if (clientPosition.X < margin && clientPosition.Y > size.Y - margin)
- return SDL_HITTEST_RESIZE_BOTTOMLEFT;
- else if (clientPosition.X < margin)
- return SDL_HITTEST_RESIZE_LEFT;
- else if (clientPosition.X > size.X - margin && clientPosition.Y > size.Y - margin)
- return SDL_HITTEST_RESIZE_BOTTOMRIGHT;
- else if (clientPosition.X > size.X - margin)
- return SDL_HITTEST_RESIZE_RIGHT;
- else if (clientPosition.Y > size.Y - margin)
- return SDL_HITTEST_RESIZE_BOTTOM;
- else
- return SDL_HITTEST_NORMAL;
- }
-
+ SDLWindow* window = static_cast(data);
+ const Float2 point(static_cast(area->x), static_cast(area->y));
+ WindowHitCodes hit = window->OnWindowHit(point);
switch (hit)
{
case WindowHitCodes::Caption:
@@ -350,9 +352,9 @@ SDLWindow* SDLWindow::GetWindowFromEvent(const SDL_Event& event)
SDL_Window* window = SDL_GetWindowFromEvent(&event);
if (window == nullptr)
return nullptr;
- if (LastEventWindow == nullptr || window != LastEventWindow->_window)
- LastEventWindow = GetWindowWithSDLWindow(window);
- return LastEventWindow;
+ if (SDLImpl::LastEventWindow == nullptr || window != SDLImpl::LastEventWindow->_window)
+ SDLImpl::LastEventWindow = GetWindowWithSDLWindow(window);
+ return SDLImpl::LastEventWindow;
}
SDLWindow* SDLWindow::GetWindowWithSDLWindow(SDL_Window* window)
@@ -779,8 +781,8 @@ Float2 SDLWindow::ClientToScreen(const Float2& clientPos) const
void SDLWindow::FlashWindow()
{
#if PLATFORM_LINUX
- // Flashing brings the window on top of other windows, disable it for now
- if (SDLPlatform::UsesWayland())
+ // KDE bug: flashing brings the window on top of other windows, disable it for now...
+ if (SDLPlatform::UsesWayland() && SDLImpl::XDGCurrentDesktop.Compare(String("KDE"), StringSearchCase::IgnoreCase) == 0)
return;
#endif
SDL_FlashWindow(_window, SDL_FLASH_UNTIL_FOCUSED);
@@ -989,9 +991,9 @@ void SDLWindow::UpdateCursor()
break;
}
- if (Cursors[index] == nullptr)
- Cursors[index] = SDL_CreateSystemCursor(static_cast(index));
- SDL_SetCursor(Cursors[index]);
+ if (SDLImpl::Cursors[index] == nullptr)
+ SDLImpl::Cursors[index] = SDL_CreateSystemCursor(static_cast(index));
+ SDL_SetCursor(SDLImpl::Cursors[index]);
}
void SDLWindow::SetIcon(TextureData& icon)
diff --git a/Source/Engine/Platform/SDL/SDLWindow.h b/Source/Engine/Platform/SDL/SDLWindow.h
index 3c3f02f26..24dbc49cc 100644
--- a/Source/Engine/Platform/SDL/SDLWindow.h
+++ b/Source/Engine/Platform/SDL/SDLWindow.h
@@ -69,6 +69,7 @@ public:
void* GetWaylandDisplay() const;
void* GetX11Display() const;
#endif
+ WindowHitCodes OnWindowHit(const Float2 point);
// [WindowBase]
void* GetNativePtr() const override;