mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-01-11 08:25:34 +00:00
[X11] Fixed WindowBorder and WindowState setters
After many hours of fighting with xlib, the monster is slain and WindowBorder/WindowState changes now take effect without messing up the window size or position on the desktop. Phew!
This commit is contained in:
parent
ab29797079
commit
f0d0f6e53a
|
@ -111,6 +111,13 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
bool _decorations_hidden = false;
|
||||
|
||||
// Store previous border and bounds
|
||||
// when switching from WindowState.Normal
|
||||
// to a different state. When switching
|
||||
// back, reset window to these.s
|
||||
WindowBorder _previous_window_border;
|
||||
Size _previous_window_size;
|
||||
|
||||
MouseCursor cursor = MouseCursor.Default;
|
||||
IntPtr cursorHandle;
|
||||
bool cursor_visible = true;
|
||||
|
@ -1248,75 +1255,105 @@ namespace OpenTK.Platform.X11
|
|||
{
|
||||
OpenTK.WindowState current_state = this.WindowState;
|
||||
|
||||
// When switching away from normal state, store
|
||||
// the "normal" border and size. These will be used
|
||||
// for restoring to normal state.
|
||||
if (current_state == OpenTK.WindowState.Normal)
|
||||
{
|
||||
_previous_window_border = WindowBorder;
|
||||
_previous_window_size = ClientSize;
|
||||
}
|
||||
|
||||
if (current_state == value)
|
||||
return;
|
||||
|
||||
Debug.Print("GameWindow {0} changing WindowState from {1} to {2}.", window.Handle.ToString(),
|
||||
current_state.ToString(), value.ToString());
|
||||
current_state.ToString(), value.ToString());
|
||||
|
||||
using (new XLock(window.Display))
|
||||
// When minimizing the window, call XIconifyWindow and bail out.
|
||||
// For other states, we first need to restore the window, set the
|
||||
// new state and reset the window border and bounds.
|
||||
if (value != OpenTK.WindowState.Minimized)
|
||||
{
|
||||
// Reset the current window state
|
||||
if (current_state == OpenTK.WindowState.Minimized)
|
||||
Functions.XMapWindow(window.Display, window.Handle);
|
||||
else if (current_state == OpenTK.WindowState.Fullscreen)
|
||||
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_remove,
|
||||
_atom_net_wm_state_fullscreen,
|
||||
IntPtr.Zero);
|
||||
else if (current_state == OpenTK.WindowState.Maximized)
|
||||
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_toggle,
|
||||
_atom_net_wm_state_maximized_horizontal,
|
||||
_atom_net_wm_state_maximized_vertical);
|
||||
|
||||
Functions.XSync(window.Display, false);
|
||||
}
|
||||
// We can't resize the window if its border is fixed, so make it resizable first.
|
||||
bool temporary_resizable = false;
|
||||
WindowBorder previous_state = WindowBorder;
|
||||
if (WindowBorder != WindowBorder.Resizable)
|
||||
{
|
||||
temporary_resizable = true;
|
||||
WindowBorder = WindowBorder.Resizable;
|
||||
}
|
||||
|
||||
using (new XLock(window.Display))
|
||||
{
|
||||
switch (value)
|
||||
// Some WMs cannot switch between specific states directly,
|
||||
// Switch back to a regular window first.
|
||||
if (WindowBorder == WindowBorder.Fixed)
|
||||
{
|
||||
ChangeWindowBorder(WindowBorder.Resizable);
|
||||
}
|
||||
|
||||
ResetWindowState(current_state);
|
||||
}
|
||||
|
||||
// Change to the desired WindowState.
|
||||
// Note that OnWindowStateChanged is called inside
|
||||
// ProcessEvents.
|
||||
ChangeWindowState(value);
|
||||
ProcessEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void ResetWindowState(OpenTK.WindowState current_state)
|
||||
{
|
||||
if (current_state != OpenTK.WindowState.Normal)
|
||||
{
|
||||
using (new XLock(window.Display))
|
||||
{
|
||||
switch (current_state)
|
||||
{
|
||||
case OpenTK.WindowState.Normal:
|
||||
Functions.XRaiseWindow(window.Display, window.Handle);
|
||||
|
||||
break;
|
||||
|
||||
case OpenTK.WindowState.Maximized:
|
||||
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_add,
|
||||
_atom_net_wm_state_maximized_horizontal,
|
||||
_atom_net_wm_state_maximized_vertical);
|
||||
Functions.XRaiseWindow(window.Display, window.Handle);
|
||||
|
||||
break;
|
||||
|
||||
case OpenTK.WindowState.Minimized:
|
||||
// Todo: multiscreen support
|
||||
Functions.XIconifyWindow(window.Display, window.Handle, window.Screen);
|
||||
|
||||
Functions.XMapWindow(window.Display, window.Handle);
|
||||
break;
|
||||
|
||||
|
||||
case OpenTK.WindowState.Fullscreen:
|
||||
//_previous_window_border = this.WindowBorder;
|
||||
//this.WindowBorder = WindowBorder.Hidden;
|
||||
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_add,
|
||||
_atom_net_wm_state_fullscreen, IntPtr.Zero);
|
||||
Functions.XRaiseWindow(window.Display, window.Handle);
|
||||
|
||||
Functions.SendNetWMMessage(window,
|
||||
_atom_net_wm_state,
|
||||
_atom_remove,
|
||||
_atom_net_wm_state_fullscreen,
|
||||
IntPtr.Zero);
|
||||
break;
|
||||
|
||||
case OpenTK.WindowState.Maximized:
|
||||
Functions.SendNetWMMessage(window,
|
||||
_atom_net_wm_state,
|
||||
_atom_toggle,
|
||||
_atom_net_wm_state_maximized_horizontal,
|
||||
_atom_net_wm_state_maximized_vertical);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (temporary_resizable)
|
||||
WindowBorder = previous_state;
|
||||
void ChangeWindowState(OpenTK.WindowState value)
|
||||
{
|
||||
using (new XLock(window.Display))
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case OpenTK.WindowState.Normal:
|
||||
Functions.XRaiseWindow(window.Display, window.Handle);
|
||||
ChangeWindowBorder(_previous_window_border,
|
||||
_previous_window_size.Width, _previous_window_size.Height);
|
||||
break;
|
||||
|
||||
ProcessEvents();
|
||||
case OpenTK.WindowState.Maximized:
|
||||
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_add,
|
||||
_atom_net_wm_state_maximized_horizontal,
|
||||
_atom_net_wm_state_maximized_vertical);
|
||||
Functions.XRaiseWindow(window.Display, window.Handle);
|
||||
break;
|
||||
|
||||
case OpenTK.WindowState.Minimized:
|
||||
Functions.XIconifyWindow(window.Display, window.Handle, window.Screen);
|
||||
break;
|
||||
|
||||
case OpenTK.WindowState.Fullscreen:
|
||||
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_add,
|
||||
_atom_net_wm_state_fullscreen, IntPtr.Zero);
|
||||
Functions.XRaiseWindow(window.Display, window.Handle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1328,47 +1365,67 @@ namespace OpenTK.Platform.X11
|
|||
{
|
||||
get
|
||||
{
|
||||
if (IsWindowBorderHidden)
|
||||
if (IsWindowBorderHidden || WindowState == OpenTK.WindowState.Fullscreen)
|
||||
return WindowBorder.Hidden;
|
||||
|
||||
if (IsWindowBorderResizable)
|
||||
return WindowBorder.Resizable;
|
||||
else
|
||||
else if (!IsWindowBorderResizable)
|
||||
return WindowBorder.Fixed;
|
||||
else if (WindowState == OpenTK.WindowState.Maximized)
|
||||
return _previous_window_border;
|
||||
else
|
||||
return WindowBorder.Resizable;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (WindowBorder == value)
|
||||
return;
|
||||
|
||||
if (WindowBorder == WindowBorder.Hidden)
|
||||
EnableWindowDecorations();
|
||||
|
||||
switch (value)
|
||||
// We cannot change the border of a fullscreen window.
|
||||
// Record the new value and set it on the next WindowState
|
||||
// change.
|
||||
if (WindowState == OpenTK.WindowState.Fullscreen)
|
||||
{
|
||||
case WindowBorder.Fixed:
|
||||
Debug.Print("Making WindowBorder fixed.");
|
||||
SetWindowMinMax((short)Width, (short)Height, (short)Width, (short)Height);
|
||||
|
||||
break;
|
||||
|
||||
case WindowBorder.Resizable:
|
||||
Debug.Print("Making WindowBorder resizable.");
|
||||
SetWindowMinMax(_min_width, _min_height, -1, -1);
|
||||
|
||||
break;
|
||||
|
||||
case WindowBorder.Hidden:
|
||||
Debug.Print("Making WindowBorder hidden.");
|
||||
DisableWindowDecorations();
|
||||
|
||||
break;
|
||||
_previous_window_border = value;
|
||||
return;
|
||||
}
|
||||
|
||||
ChangeWindowBorder(value);
|
||||
OnWindowBorderChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeWindowBorder(WindowBorder value)
|
||||
{
|
||||
ChangeWindowBorder(value, Width, Height);
|
||||
}
|
||||
|
||||
void ChangeWindowBorder(WindowBorder value, int width, int height)
|
||||
{
|
||||
if (WindowBorder == WindowBorder.Hidden)
|
||||
EnableWindowDecorations();
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case WindowBorder.Fixed:
|
||||
Debug.Print("Making WindowBorder fixed.");
|
||||
SetWindowMinMax((short)width, (short)height, (short)width, (short)height);
|
||||
break;
|
||||
case WindowBorder.Resizable:
|
||||
Debug.Print("Making WindowBorder resizable.");
|
||||
SetWindowMinMax(_min_width, _min_height, -1, -1);
|
||||
break;
|
||||
case WindowBorder.Hidden:
|
||||
Debug.Print("Making WindowBorder hidden.");
|
||||
// Make the hidden border resizable, otherwise
|
||||
// we won't be able to maximize the window or
|
||||
// enter fullscreen mode.
|
||||
SetWindowMinMax(_min_width, _min_height, -1, -1);
|
||||
DisableWindowDecorations();
|
||||
break;
|
||||
}
|
||||
|
||||
ProcessEvents();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Cursor
|
||||
|
|
Loading…
Reference in a new issue