* X11GLNative.cs: Fix behavior of WindowState when WindowBorder is

Fixed.
This commit is contained in:
the_fiddler 2008-05-04 16:09:09 +00:00
parent 6864127ea0
commit bf8a11f103

View file

@ -673,7 +673,7 @@ namespace OpenTK.Platform.X11
} }
if (minimized) if (minimized)
return OpenTK.WindowState.Minimized; return WindowState.Minimized;
else if (maximized == 2) else if (maximized == 2)
return OpenTK.WindowState.Maximized; return OpenTK.WindowState.Maximized;
else if (fullscreen) else if (fullscreen)
@ -699,17 +699,25 @@ namespace OpenTK.Platform.X11
if (current_state == OpenTK.WindowState.Minimized) if (current_state == OpenTK.WindowState.Minimized)
Functions.XMapWindow(window.Display, window.WindowHandle); Functions.XMapWindow(window.Display, window.WindowHandle);
else if (current_state == OpenTK.WindowState.Fullscreen) else if (current_state == OpenTK.WindowState.Fullscreen)
{
//WindowBorder = _previous_window_border;
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_remove, Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_remove,
_atom_net_wm_state_fullscreen, _atom_net_wm_state_fullscreen,
IntPtr.Zero); IntPtr.Zero);
}
else if (current_state == OpenTK.WindowState.Maximized) else if (current_state == OpenTK.WindowState.Maximized)
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_toggle, Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_toggle,
_atom_net_wm_state_maximized_horizontal, _atom_net_wm_state_maximized_horizontal,
_atom_net_wm_state_maximized_vertical); _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;
}
switch (value) switch (value)
{ {
case OpenTK.WindowState.Normal: case OpenTK.WindowState.Normal:
@ -718,40 +726,31 @@ namespace OpenTK.Platform.X11
break; break;
case OpenTK.WindowState.Maximized: case OpenTK.WindowState.Maximized:
// We can't resize the window if its border is fixed, so make it resizable first.
bool temporary_resizable = false;
if (WindowBorder == WindowBorder.Fixed)
{
temporary_resizable = true;
WindowBorder = WindowBorder.Resizable;
}
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_add, Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_add,
_atom_net_wm_state_maximized_horizontal, _atom_net_wm_state_maximized_horizontal,
_atom_net_wm_state_maximized_vertical); _atom_net_wm_state_maximized_vertical);
Functions.XRaiseWindow(window.Display, window.WindowHandle); Functions.XRaiseWindow(window.Display, window.WindowHandle);
if (temporary_resizable)
WindowBorder = WindowBorder.Fixed;
break; break;
case OpenTK.WindowState.Minimized: case WindowState.Minimized:
// FIXME multiscreen support // FIXME multiscreen support
Functions.XIconifyWindow(window.Display, window.WindowHandle, window.Screen); Functions.XIconifyWindow(window.Display, window.WindowHandle, window.Screen);
break; break;
case OpenTK.WindowState.Fullscreen: case WindowState.Fullscreen:
//_previous_window_border = this.WindowBorder; //_previous_window_border = this.WindowBorder;
//this.WindowBorder = WindowBorder.Hidden; //this.WindowBorder = WindowBorder.Hidden;
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_add, Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_add,
_atom_net_wm_state_fullscreen, IntPtr.Zero); _atom_net_wm_state_fullscreen, IntPtr.Zero);
Functions.XRaiseWindow(window.Display, window.WindowHandle);
break; break;
} }
if (temporary_resizable)
WindowBorder = previous_state;
} }
} }
@ -763,55 +762,13 @@ namespace OpenTK.Platform.X11
{ {
get get
{ {
//return _window_border; if (IsWindowBorderHidden)
IntPtr actual_atom;
int actual_format;
IntPtr nitems;
IntPtr bytes_after;
IntPtr prop = IntPtr.Zero;
IntPtr atom;
XWindowAttributes attributes;
bool resizable = false, hidden = false;
// IntPtr transient; // The window for which X11GLWindow is transient, if any.
//
// Functions.XGetTransientForHint(window.Display, window.WindowHandle, out transient);
// if (transient != IntPtr.Zero)
// return WindowBorder.Hidden;
if (_decorations_hidden)
return WindowBorder.Hidden; return WindowBorder.Hidden;
Functions.XGetWindowProperty(window.Display, window.WindowHandle, if (IsWindowBorderResizable)
_atom_net_wm_allowed_actions, IntPtr.Zero, new IntPtr (256), false,
IntPtr.Zero, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
if ((long)nitems > 0 && prop != IntPtr.Zero)
{
for (int i = 0; i < (long)nitems; i++)
{
atom = (IntPtr)Marshal.ReadIntPtr(prop, i * IntPtr.Size);
if (atom == _atom_net_wm_action_resize)
resizable = true;
//else if (atom
//return WindowBorder.Resizable;
// if (atom == _atom_wm_state_maximized_horizontal || atom == _atom_wm_state_maximized_vertical)
// maximized++;
// else if (atom == _atom_wm_state_minimized)
// minimized = true;
// else if (atom == _atom_wm_state_fullscreen)
// fullscreen = true;
}
Functions.XFree(prop);
}
if (resizable)
return WindowBorder.Resizable; return WindowBorder.Resizable;
else else
return WindowBorder.Fixed; return WindowBorder.Fixed;
} }
set set
{ {
@ -819,13 +776,7 @@ namespace OpenTK.Platform.X11
return; return;
if (WindowBorder == WindowBorder.Hidden) if (WindowBorder == WindowBorder.Hidden)
{
EnableWindowDecorations(); EnableWindowDecorations();
// int error = Functions.XSetTransientForHint(window.Display, window.WindowHandle, IntPtr.Zero);
// if (error == 0)
// Debug.Print("Error");
}
switch (value) switch (value)
{ {
@ -844,12 +795,9 @@ namespace OpenTK.Platform.X11
case WindowBorder.Hidden: case WindowBorder.Hidden:
Debug.Print("Making WindowBorder hidden."); Debug.Print("Making WindowBorder hidden.");
DisableWindowDecorations(); DisableWindowDecorations();
//Functions.XSetTransientForHint(window.Display, window.WindowHandle, window.RootWindow);
break; break;
} }
// Functions.SendNetWMMessage(window, _atom_wm_state, _atom_state_add,
// _atom_wm_state_fullscreen, IntPtr.Zero);
} }
} }
@ -1037,6 +985,75 @@ namespace OpenTK.Platform.X11
#region --- Private Methods --- #region --- Private Methods ---
bool IsWindowBorderResizable
{
get
{
IntPtr actual_atom;
int actual_format;
IntPtr nitems;
IntPtr bytes_after;
IntPtr prop = IntPtr.Zero;
IntPtr atom;
XWindowAttributes attributes;
Functions.XGetWindowProperty(window.Display, window.WindowHandle,
_atom_net_wm_allowed_actions, IntPtr.Zero, new IntPtr(256), false,
IntPtr.Zero, out actual_atom, out actual_format, out nitems,
out bytes_after, ref prop);
if ((long)nitems > 0 && prop != IntPtr.Zero)
{
for (int i = 0; i < (long)nitems; i++)
{
atom = (IntPtr)Marshal.ReadIntPtr(prop, i * IntPtr.Size);
if (atom == _atom_net_wm_action_resize)
return true;
}
Functions.XFree(prop);
}
return false;
}
}
#region bool IsWindowBorderHidden
bool IsWindowBorderHidden
{
get
{
IntPtr actual_atom;
int actual_format;
IntPtr nitems;
IntPtr bytes_after;
IntPtr prop = IntPtr.Zero;
IntPtr atom;
XWindowAttributes attributes;
// Test if decorations have been disabled through Motif.
IntPtr motif_hints_atom = Functions.XInternAtom(this.window.Display, MOTIF_WM_ATOM, true);
if (motif_hints_atom != IntPtr.Zero)
{
// TODO: How to check if MotifWMHints decorations have been really disabled?
if (_decorations_hidden)
return true;
}
// Some WMs remove decorations when the transient_for hint is set. Most new ones do not (but those
// should obey the Motif hint). Anyway, if this hint is set, we say the decorations have been remove
// although there is a slight chance this is not the case.
IntPtr transient_for_parent;
Functions.XGetTransientForHint(window.Display, window.WindowHandle, out transient_for_parent);
if (transient_for_parent != IntPtr.Zero)
return true;
return false;
}
}
#endregion
#region void DisableWindowDecorations() #region void DisableWindowDecorations()
void DisableWindowDecorations() void DisableWindowDecorations()
@ -1047,17 +1064,16 @@ namespace OpenTK.Platform.X11
_decorations_hidden = true; _decorations_hidden = true;
} }
//bool removed = false; // Functions.XSetTransientForHint(this.window.Display, this.Handle, this.window.RootWindow);
//if (DisableMotifDecorations()) { Debug.Print("Removed decorations through motif."); removed = true; }
//if (DisableGnomeDecorations()) { Debug.Print("Removed decorations through gnome."); removed = true; }
//if (DisableIccmDecorations()) { Debug.Print("Removed decorations through ICCM."); removed = true; }
//if (removed) // Some WMs remove decorations when this hint is set. Doesn't hurt to try.
//{ Functions.XSetTransientForHint(this.window.Display, this.Handle, this.window.RootWindow);
// Functions.XSetTransientForHint(this.window.Display, this.Handle, this.window.RootWindow);
// Functions.XUnmapWindow(this.window.Display, this.Handle); if (_decorations_hidden)
// Functions.XMapWindow(this.window.Display, this.Handle); {
//} Functions.XUnmapWindow(this.window.Display, this.Handle);
Functions.XMapWindow(this.window.Display, this.Handle);
}
} }
#region bool DisableMotifDecorations() #region bool DisableMotifDecorations()
@ -1067,10 +1083,12 @@ namespace OpenTK.Platform.X11
IntPtr atom = Functions.XInternAtom(this.window.Display, MOTIF_WM_ATOM, true); IntPtr atom = Functions.XInternAtom(this.window.Display, MOTIF_WM_ATOM, true);
if (atom != IntPtr.Zero) if (atom != IntPtr.Zero)
{ {
//Functions.XGetWindowProperty(window.Display, window.WindowHandle, atom, IntPtr.Zero, IntPtr.Zero, false,
MotifWmHints hints = new MotifWmHints(); MotifWmHints hints = new MotifWmHints();
hints.flags = (IntPtr)MotifFlags.Decorations; hints.flags = (IntPtr)MotifFlags.Decorations;
Functions.XChangeProperty(this.window.Display, this.Handle, atom, atom, 32, PropertyMode.Replace, Functions.XChangeProperty(this.window.Display, this.Handle, atom, atom, 32, PropertyMode.Replace,
ref hints, /*Marshal.SizeOf(hints) / 4*/ 5); ref hints, Marshal.SizeOf(hints) / IntPtr.Size);
return true; return true;
} }
return false; return false;
@ -1087,7 +1105,7 @@ namespace OpenTK.Platform.X11
{ {
IntPtr hints = IntPtr.Zero; IntPtr hints = IntPtr.Zero;
Functions.XChangeProperty(this.window.Display, this.Handle, atom, atom, 32, PropertyMode.Replace, Functions.XChangeProperty(this.window.Display, this.Handle, atom, atom, 32, PropertyMode.Replace,
ref hints, /*Marshal.SizeOf(hints) / 4*/ 1); ref hints, Marshal.SizeOf(hints) / IntPtr.Size);
return true; return true;
} }
@ -1096,23 +1114,6 @@ namespace OpenTK.Platform.X11
#endregion #endregion
#region bool DisableIccmDecorations()
bool DisableIccmDecorations()
{
IntPtr atom = Functions.XInternAtom(this.window.Display, ICCM_WM_ATOM, true);
if (atom != IntPtr.Zero)
{
IntPtr hints = Functions.XInternAtom(this.window.Display, "_NET_WM_STATE_FULLSCREEN", true);
Functions.XChangeProperty(this.window.Display, this.Handle, atom, atom, 32, PropertyMode.Replace,
ref hints, /*Marshal.SizeOf(hints) / 4*/ 1);
return true;
}
return false;
}
#endregion
#endregion #endregion
#region void EnableWindowDecorations() #region void EnableWindowDecorations()
@ -1124,17 +1125,16 @@ namespace OpenTK.Platform.X11
Debug.Print("Activated decorations through motif."); Debug.Print("Activated decorations through motif.");
_decorations_hidden = false; _decorations_hidden = false;
} }
//bool activated = false;
//if (EnableMotifDecorations()) { Debug.Print("Activated decorations through motif."); activated = true; }
//if (EnableGnomeDecorations()) { Debug.Print("Activated decorations through gnome."); activated = true; }
//if (EnableIccmDecorations()) { Debug.Print("Activated decorations through ICCM."); activated = true; }
//if (activated) //if (EnableGnomeDecorations()) { Debug.Print("Activated decorations through gnome."); activated = true; }
//{
// Functions.XSetTransientForHint(this.window.Display, this.Handle, this.window.RootWindow); Functions.XSetTransientForHint(this.window.Display, this.Handle, IntPtr.Zero);
// Functions.XUnmapWindow(this.window.Display, this.Handle);
// Functions.XMapWindow(this.window.Display, this.Handle); if (!_decorations_hidden)
//} {
Functions.XUnmapWindow(this.window.Display, this.Handle);
Functions.XMapWindow(this.window.Display, this.Handle);
}
} }
#region bool EnableMotifDecorations() #region bool EnableMotifDecorations()
@ -1144,7 +1144,13 @@ namespace OpenTK.Platform.X11
IntPtr atom = Functions.XInternAtom(this.window.Display, MOTIF_WM_ATOM, true); IntPtr atom = Functions.XInternAtom(this.window.Display, MOTIF_WM_ATOM, true);
if (atom != IntPtr.Zero) if (atom != IntPtr.Zero)
{ {
Functions.XDeleteProperty(this.window.Display, this.Handle, atom); //Functions.XDeleteProperty(this.window.Display, this.Handle, atom);
MotifWmHints hints = new MotifWmHints();
hints.flags = (IntPtr)MotifFlags.Decorations;
hints.decorations = (IntPtr)MotifDecorations.All;
Functions.XChangeProperty(this.window.Display, this.Handle, atom, atom, 32, PropertyMode.Replace,
ref hints, Marshal.SizeOf(hints) / IntPtr.Size);
return true; return true;
} }
return false; return false;
@ -1177,26 +1183,6 @@ namespace OpenTK.Platform.X11
#endregion #endregion
#region bool EnableIccmDecorations()
bool EnableIccmDecorations()
{
IntPtr atom = Functions.XInternAtom(this.window.Display, ICCM_WM_ATOM, true);
if (atom != IntPtr.Zero)
{
IntPtr hint = Functions.XInternAtom(this.window.Display, "_NET_WM_WINDOW_TYPE_NORMAL", true);
if (hint != IntPtr.Zero)
{
Functions.XChangeProperty(this.window.Display, this.Handle, hint, /*XA_ATOM*/(IntPtr)4, 32,
PropertyMode.Replace, hint, Marshal.SizeOf(hint) / 4);
}
return true;
}
return false;
}
#endregion
#endregion #endregion
#endregion #endregion