From 96bd813fe449f0079792441e05e471d1d5c87042 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Fri, 27 Mar 2020 17:44:21 +0300 Subject: [PATCH] [X11] When not mapped change _NET_WM_STATE property directly See https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html#idm46175134492192 --- src/Avalonia.X11/X11Window.cs | 46 +++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 2492f5a43a..8419e7dab2 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -546,14 +546,14 @@ namespace Avalonia.X11 } else if (value == WindowState.Maximized) { - SendNetWMMessage(_x11.Atoms._NET_WM_STATE, (IntPtr)0, _x11.Atoms._NET_WM_STATE_HIDDEN, IntPtr.Zero); - SendNetWMMessage(_x11.Atoms._NET_WM_STATE, (IntPtr)1, _x11.Atoms._NET_WM_STATE_MAXIMIZED_VERT, + ChangeWMAtoms(false, _x11.Atoms._NET_WM_STATE_HIDDEN); + ChangeWMAtoms(true, _x11.Atoms._NET_WM_STATE_MAXIMIZED_VERT, _x11.Atoms._NET_WM_STATE_MAXIMIZED_HORZ); } else { - SendNetWMMessage(_x11.Atoms._NET_WM_STATE, (IntPtr)0, _x11.Atoms._NET_WM_STATE_HIDDEN, IntPtr.Zero); - SendNetWMMessage(_x11.Atoms._NET_WM_STATE, (IntPtr)0, _x11.Atoms._NET_WM_STATE_MAXIMIZED_VERT, + ChangeWMAtoms(false, _x11.Atoms._NET_WM_STATE_HIDDEN); + ChangeWMAtoms(false, _x11.Atoms._NET_WM_STATE_MAXIMIZED_VERT, _x11.Atoms._NET_WM_STATE_MAXIMIZED_HORZ); } } @@ -989,8 +989,7 @@ namespace Avalonia.X11 public void SetTopmost(bool value) { - SendNetWMMessage(_x11.Atoms._NET_WM_STATE, - (IntPtr)(value ? 1 : 0), _x11.Atoms._NET_WM_STATE_ABOVE, IntPtr.Zero); + ChangeWMAtoms(value, _x11.Atoms._NET_WM_STATE_ABOVE); } public void ShowDialog(IWindowImpl parent) @@ -1017,8 +1016,41 @@ namespace Avalonia.X11 public void ShowTaskbarIcon(bool value) { + ChangeWMAtoms(!value, _x11.Atoms._NET_WM_STATE_SKIP_TASKBAR); + } + + void ChangeWMAtoms(bool enable, params IntPtr[] atoms) + { + if (atoms.Length < 1 || atoms.Length > 4) + throw new ArgumentException(); + + if (!_mapped) + { + XGetWindowProperty(_x11.Display, _handle, _x11.Atoms._NET_WM_STATE, IntPtr.Zero, new IntPtr(256), + false, (IntPtr)Atom.XA_ATOM, out _, out _, out var nitems, out _, + out var prop); + var ptr = (IntPtr*)prop.ToPointer(); + var newAtoms = new HashSet(); + for (var c = 0; c < nitems.ToInt64(); c++) + newAtoms.Add(*ptr); + XFree(prop); + foreach(var atom in atoms) + if (enable) + newAtoms.Add(atom); + else + newAtoms.Remove(atom); + + XChangeProperty(_x11.Display, _handle, _x11.Atoms._NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, + PropertyMode.Replace, newAtoms.ToArray(), newAtoms.Count); + } + SendNetWMMessage(_x11.Atoms._NET_WM_STATE, - (IntPtr)(value ? 0 : 1), _x11.Atoms._NET_WM_STATE_SKIP_TASKBAR, IntPtr.Zero); + (IntPtr)(enable ? 1 : 0), + atoms[0], + atoms.Length > 1 ? atoms[1] : IntPtr.Zero, + atoms.Length > 2 ? atoms[2] : IntPtr.Zero, + atoms.Length > 3 ? atoms[3] : IntPtr.Zero + ); } public IPopupPositioner PopupPositioner { get; }