* 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 50ff7cdc08
commit 523c4de774

View file

@ -20,7 +20,7 @@ using OpenTK.Graphics;
//using OpenTK.Graphics.OpenGL;
namespace OpenTK.Platform.X11
{
{
/// <summary>
/// Drives GameWindow on X11.
/// This class supports OpenTK, and is not intended for use by OpenTK programs.
@ -32,42 +32,42 @@ namespace OpenTK.Platform.X11
// TODO: Mouse/keyboard grabbing/wrapping.
// TODO: PointToWindow, PointToScreen
#region --- Fields ---
#region --- Fields ---
const int _min_width = 30, _min_height = 30;
X11WindowInfo window = new X11WindowInfo();
X11Input driver;
// Window manager hints for fullscreen windows.
// Not used right now (the code is written, but is not 64bit-correct), but could be useful for older WMs which
// are not ICCM compliant, but may support MOTIF hints.
// Window manager hints for fullscreen windows.
// Not used right now (the code is written, but is not 64bit-correct), but could be useful for older WMs which
// are not ICCM compliant, but may support MOTIF hints.
const string MOTIF_WM_ATOM = "_MOTIF_WM_HINTS";
const string KDE_WM_ATOM = "KWM_WIN_DECORATION";
const string KDE_NET_WM_ATOM = "_KDE_NET_WM_WINDOW_TYPE";
const string ICCM_WM_ATOM = "_NET_WM_WINDOW_TYPE";
// The Atom class from Mono might be useful to avoid calling XInternAtom by hand (somewhat error prone).
IntPtr _atom_wm_destroy;
IntPtr _atom_net_wm_state;
IntPtr _atom_net_wm_state_minimized;
IntPtr _atom_net_wm_state_fullscreen;
IntPtr _atom_net_wm_state_maximized_horizontal;
IntPtr _atom_net_wm_state_maximized_vertical;
IntPtr _atom_net_wm_allowed_actions;
IntPtr _atom_net_wm_action_resize;
IntPtr _atom_net_wm_action_maximize_horizontally;
IntPtr _atom_net_wm_action_maximize_vertically;
IntPtr _atom_motif_wm_hints;
IntPtr _atom_kde_wm_hints;
IntPtr _atom_kde_net_wm_hints;
static readonly IntPtr _atom_remove = (IntPtr)0;
static readonly IntPtr _atom_add = (IntPtr)1;
static readonly IntPtr _atom_toggle = (IntPtr)2;
// The Atom class from Mono might be useful to avoid calling XInternAtom by hand (somewhat error prone).
IntPtr _atom_wm_destroy;
IntPtr _atom_net_wm_state;
IntPtr _atom_net_wm_state_minimized;
IntPtr _atom_net_wm_state_fullscreen;
IntPtr _atom_net_wm_state_maximized_horizontal;
IntPtr _atom_net_wm_state_maximized_vertical;
IntPtr _atom_net_wm_allowed_actions;
IntPtr _atom_net_wm_action_resize;
IntPtr _atom_net_wm_action_maximize_horizontally;
IntPtr _atom_net_wm_action_maximize_vertically;
IntPtr _atom_motif_wm_hints;
IntPtr _atom_kde_wm_hints;
IntPtr _atom_kde_net_wm_hints;
static readonly IntPtr _atom_remove = (IntPtr)0;
static readonly IntPtr _atom_add = (IntPtr)1;
static readonly IntPtr _atom_toggle = (IntPtr)2;
// Number of pending events.
int pending = 0;
@ -91,11 +91,11 @@ namespace OpenTK.Platform.X11
// Fields used for fullscreen mode changes.
int pre_fullscreen_width, pre_fullscreen_height;
//bool fullscreen = false;
bool _decorations_hidden = false;
//OpenTK.WindowState _window_state, _previous_window_state;
//bool fullscreen = false;
bool _decorations_hidden = false;
//OpenTK.WindowState _window_state, _previous_window_state;
//OpenTK.WindowBorder _window_border, _previous_window_border;
#endregion
@ -141,9 +141,9 @@ namespace OpenTK.Platform.X11
Functions.XUnlockDisplay(window.Display);
}
Debug.Print("Display: {0}, Screen {1}, Root window: {2}", window.Display, window.Screen,
window.RootWindow);
Debug.Print("Display: {0}, Screen {1}, Root window: {2}", window.Display, window.Screen,
window.RootWindow);
RegisterAtoms(window);
}
finally
@ -161,31 +161,31 @@ namespace OpenTK.Platform.X11
/// Registers the necessary atoms for GameWindow.
/// </summary>
private void RegisterAtoms(X11WindowInfo window)
{
Debug.WriteLine("Registering atoms.");
_atom_wm_destroy = Functions.XInternAtom(window.Display, "WM_DELETE_WINDOW", true);
_atom_net_wm_state = Functions.XInternAtom(window.Display, "_NET_WM_STATE", false);
_atom_net_wm_state_minimized = Functions.XInternAtom(window.Display, "_NET_WM_STATE_MINIMIZED", false);
_atom_net_wm_state_fullscreen = Functions.XInternAtom(window.Display, "_NET_WM_STATE_FULLSCREEN", false);
_atom_net_wm_state_maximized_horizontal =
Functions.XInternAtom(window.Display, "_NET_WM_STATE_MAXIMIZED_HORZ", false);
_atom_net_wm_state_maximized_vertical =
Functions.XInternAtom(window.Display, "_NET_WM_STATE_MAXIMIZED_VERT", false);
_atom_net_wm_allowed_actions =
Functions.XInternAtom(window.Display, "_NET_WM_ALLOWED_ACTIONS", false);
_atom_net_wm_action_resize =
Functions.XInternAtom(window.Display, "_NET_WM_ACTION_RESIZE", false);
_atom_net_wm_action_maximize_horizontally =
Functions.XInternAtom(window.Display, "_NET_WM_ACTION_MAXIMIZE_HORZ", false);
_atom_net_wm_action_maximize_vertically =
Functions.XInternAtom(window.Display, "_NET_WM_ACTION_MAXIMIZE_VERT", false);
{
Debug.WriteLine("Registering atoms.");
_atom_wm_destroy = Functions.XInternAtom(window.Display, "WM_DELETE_WINDOW", true);
_atom_net_wm_state = Functions.XInternAtom(window.Display, "_NET_WM_STATE", false);
_atom_net_wm_state_minimized = Functions.XInternAtom(window.Display, "_NET_WM_STATE_MINIMIZED", false);
_atom_net_wm_state_fullscreen = Functions.XInternAtom(window.Display, "_NET_WM_STATE_FULLSCREEN", false);
_atom_net_wm_state_maximized_horizontal =
Functions.XInternAtom(window.Display, "_NET_WM_STATE_MAXIMIZED_HORZ", false);
_atom_net_wm_state_maximized_vertical =
Functions.XInternAtom(window.Display, "_NET_WM_STATE_MAXIMIZED_VERT", false);
_atom_net_wm_allowed_actions =
Functions.XInternAtom(window.Display, "_NET_WM_ALLOWED_ACTIONS", false);
_atom_net_wm_action_resize =
Functions.XInternAtom(window.Display, "_NET_WM_ACTION_RESIZE", false);
_atom_net_wm_action_maximize_horizontally =
Functions.XInternAtom(window.Display, "_NET_WM_ACTION_MAXIMIZE_HORZ", false);
_atom_net_wm_action_maximize_vertically =
Functions.XInternAtom(window.Display, "_NET_WM_ACTION_MAXIMIZE_VERT", false);
// string[] atom_names = new string[]
// {
// //"WM_TITLE",
// //"UTF8_STRING"
// //"UTF8_STRING"
// };
// IntPtr[] atoms = new IntPtr[atom_names.Length];
// //Functions.XInternAtoms(window.Display, atom_names, atom_names.Length, false, atoms);
@ -246,8 +246,8 @@ namespace OpenTK.Platform.X11
}
context = new GraphicsContext(mode, window);
// Set the window hints
SetWindowMinMax(_min_width, _min_height, -1, -1);
// Set the window hints
SetWindowMinMax(_min_width, _min_height, -1, -1);
XSizeHints hints = new XSizeHints();
hints.x = 0;
@ -282,22 +282,22 @@ namespace OpenTK.Platform.X11
//context.CreateContext(true, null);
driver = new X11Input(window);
// HACK: This seems to reduce thread issues on Linux, due to race conditions.
// It does *not* solve the root cause, which is unknown at this point.
//
// What I suspect happens, is that either the glXChooseContext or glXCreateContext functions are called
// before the window is ready - or maybe before the window size is set which renders the viewport invalid?
// (can this happen?) or that there are pending events that somehow botch context creation up (seems like
// the fglrx driver is spawning a new thread, or waiting on something?)
// This issue *must* be resolved before the 1.0 release.
// Note that this has the side effect that sometimes, a resize event is missed.
//Functions.XSync(window.Display, true);
driver = new X11Input(window);
// HACK: This seems to reduce thread issues on Linux, due to race conditions.
// It does *not* solve the root cause, which is unknown at this point.
//
// What I suspect happens, is that either the glXChooseContext or glXCreateContext functions are called
// before the window is ready - or maybe before the window size is set which renders the viewport invalid?
// (can this happen?) or that there are pending events that somehow botch context creation up (seems like
// the fglrx driver is spawning a new thread, or waiting on something?)
// This issue *must* be resolved before the 1.0 release.
// Note that this has the side effect that sometimes, a resize event is missed.
//Functions.XSync(window.Display, true);
Debug.WriteLine("X11GLNative window created successfully!");
Debug.Unindent();
Debug.Unindent();
exists = true;
}
@ -333,12 +333,12 @@ namespace OpenTK.Platform.X11
// A child was was created - nothing to do
break;
case XEventName.ClientMessage:
case XEventName.ClientMessage:
if (e.ClientMessageEvent.ptr1 == _atom_wm_destroy)
this.OnDestroy(EventArgs.Empty);
else
Debug.Print("Niar");
this.OnDestroy(EventArgs.Empty);
else
Debug.Print("Niar");
break;
@ -426,7 +426,7 @@ namespace OpenTK.Platform.X11
public bool Fullscreen
{
get
{
{
return false;
//return fullscreen;
}
@ -436,7 +436,7 @@ namespace OpenTK.Platform.X11
// {
// Debug.Print("Going fullscreen");
// Debug.Indent();
// DisableWindowDecorations();
// DisableWindowDecorations();
// pre_fullscreen_height = this.Height;
// pre_fullscreen_width = this.Width;
// //Functions.XRaiseWindow(this.window.Display, this.Handle);
@ -640,118 +640,117 @@ namespace OpenTK.Platform.X11
{
get
{
IntPtr actual_atom;
int actual_format;
IntPtr nitems;
IntPtr bytes_after;
IntPtr prop = IntPtr.Zero;
IntPtr atom;
XWindowAttributes attributes;
bool fullscreen = false;
int maximized = 0;
bool minimized = false;
Functions.XGetWindowProperty(window.Display, window.WindowHandle,
_atom_net_wm_state, 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_state_maximized_horizontal ||
atom == _atom_net_wm_state_maximized_vertical)
maximized++;
else if (atom == _atom_net_wm_state_minimized)
minimized = true;
else if (atom == _atom_net_wm_state_fullscreen)
fullscreen = true;
}
Functions.XFree(prop);
}
if (minimized)
return OpenTK.WindowState.Minimized;
else if (maximized == 2)
return OpenTK.WindowState.Maximized;
else if (fullscreen)
return OpenTK.WindowState.Fullscreen;
/*
attributes = new XWindowAttributes();
Functions.XGetWindowAttributes(window.Display, window.WindowHandle, ref attributes);
if (attributes.map_state == MapState.IsUnmapped)
return (OpenTK.WindowState)(-1);
*/
IntPtr actual_atom;
int actual_format;
IntPtr nitems;
IntPtr bytes_after;
IntPtr prop = IntPtr.Zero;
IntPtr atom;
XWindowAttributes attributes;
bool fullscreen = false;
int maximized = 0;
bool minimized = false;
Functions.XGetWindowProperty(window.Display, window.WindowHandle,
_atom_net_wm_state, 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_state_maximized_horizontal ||
atom == _atom_net_wm_state_maximized_vertical)
maximized++;
else if (atom == _atom_net_wm_state_minimized)
minimized = true;
else if (atom == _atom_net_wm_state_fullscreen)
fullscreen = true;
}
Functions.XFree(prop);
}
if (minimized)
return WindowState.Minimized;
else if (maximized == 2)
return OpenTK.WindowState.Maximized;
else if (fullscreen)
return OpenTK.WindowState.Fullscreen;
/*
attributes = new XWindowAttributes();
Functions.XGetWindowAttributes(window.Display, window.WindowHandle, ref attributes);
if (attributes.map_state == MapState.IsUnmapped)
return (OpenTK.WindowState)(-1);
*/
return OpenTK.WindowState.Normal;
}
set
{
OpenTK.WindowState current_state = this.WindowState;
if (current_state == value)
return;
Debug.Print("GameWindow {0} changing WindowState from {1} to {2}.", window.WindowHandle.ToString(),
current_state.ToString(), value.ToString());
if (current_state == OpenTK.WindowState.Minimized)
Functions.XMapWindow(window.Display, window.WindowHandle);
else if (current_state == OpenTK.WindowState.Fullscreen)
{
//WindowBorder = _previous_window_border;
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);
{
OpenTK.WindowState current_state = this.WindowState;
if (current_state == value)
return;
Debug.Print("GameWindow {0} changing WindowState from {1} to {2}.", window.WindowHandle.ToString(),
current_state.ToString(), value.ToString());
if (current_state == OpenTK.WindowState.Minimized)
Functions.XMapWindow(window.Display, window.WindowHandle);
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;
}
switch (value)
{
case OpenTK.WindowState.Normal:
Functions.XRaiseWindow(window.Display, window.WindowHandle);
break;
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,
_atom_net_wm_state_maximized_horizontal,
_atom_net_wm_state_maximized_vertical);
Functions.XRaiseWindow(window.Display, window.WindowHandle);
if (temporary_resizable)
WindowBorder = WindowBorder.Fixed;
break;
case OpenTK.WindowState.Minimized:
// FIXME multiscreen support
Functions.XIconifyWindow(window.Display, window.WindowHandle, window.Screen);
break;
case OpenTK.WindowState.Fullscreen:
switch (value)
{
case OpenTK.WindowState.Normal:
Functions.XRaiseWindow(window.Display, window.WindowHandle);
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.WindowHandle);
break;
case WindowState.Minimized:
// FIXME multiscreen support
Functions.XIconifyWindow(window.Display, window.WindowHandle, window.Screen);
break;
case 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);
break;
}
//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.WindowHandle);
break;
}
if (temporary_resizable)
WindowBorder = previous_state;
}
}
@ -763,133 +762,82 @@ namespace OpenTK.Platform.X11
{
get
{
//return _window_border;
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;
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)
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;
else
return WindowBorder.Fixed;
if (IsWindowBorderHidden)
return WindowBorder.Hidden;
if (IsWindowBorderResizable)
return WindowBorder.Resizable;
else
return WindowBorder.Fixed;
}
set
{
if (WindowBorder == value)
return;
if (WindowBorder == WindowBorder.Hidden)
{
EnableWindowDecorations();
// int error = Functions.XSetTransientForHint(window.Display, window.WindowHandle, IntPtr.Zero);
// if (error == 0)
// Debug.Print("Error");
}
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.");
DisableWindowDecorations();
//Functions.XSetTransientForHint(window.Display, window.WindowHandle, window.RootWindow);
break;
}
// Functions.SendNetWMMessage(window, _atom_wm_state, _atom_state_add,
// _atom_wm_state_fullscreen, IntPtr.Zero);
{
if (WindowBorder == value)
return;
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.");
DisableWindowDecorations();
break;
}
}
}
#endregion
#endregion
void SetWindowMinMax(short min_width, short min_height, short max_width, short max_height)
{
IntPtr dummy;
XSizeHints hints = new XSizeHints();
Functions.XGetWMNormalHints(window.Display, window.WindowHandle, ref hints, out dummy);
if (min_width > 0 || min_height > 0)
{
hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
hints.min_width = min_width;
hints.min_height = min_height;
}
else
hints.flags = (IntPtr)((int)hints.flags & ~(int)XSizeHintsFlags.PMinSize);
if (max_width > 0 || max_height > 0)
{
hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
hints.max_width = max_width;
hints.max_height = max_height;
}
else
hints.flags = (IntPtr)((int)hints.flags & ~(int)XSizeHintsFlags.PMaxSize);
if (hints.flags != IntPtr.Zero)
{
// The Metacity team has decided that they won't care about this when clicking the maximize
// icon, will maximize the window to fill the screen/parent no matter what.
// http://bugzilla.ximian.com/show_bug.cgi?id=80021
Functions.XSetWMNormalHints(window.Display, window.WindowHandle, ref hints);
}
#endregion
#endregion
void SetWindowMinMax(short min_width, short min_height, short max_width, short max_height)
{
IntPtr dummy;
XSizeHints hints = new XSizeHints();
Functions.XGetWMNormalHints(window.Display, window.WindowHandle, ref hints, out dummy);
if (min_width > 0 || min_height > 0)
{
hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
hints.min_width = min_width;
hints.min_height = min_height;
}
else
hints.flags = (IntPtr)((int)hints.flags & ~(int)XSizeHintsFlags.PMinSize);
if (max_width > 0 || max_height > 0)
{
hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
hints.max_width = max_width;
hints.max_height = max_height;
}
else
hints.flags = (IntPtr)((int)hints.flags & ~(int)XSizeHintsFlags.PMaxSize);
if (hints.flags != IntPtr.Zero)
{
// The Metacity team has decided that they won't care about this when clicking the maximize
// icon, will maximize the window to fill the screen/parent no matter what.
// http://bugzilla.ximian.com/show_bug.cgi?id=80021
Functions.XSetWMNormalHints(window.Display, window.WindowHandle, ref hints);
}
}
#region --- IResizable Members ---
@ -1035,29 +983,97 @@ namespace OpenTK.Platform.X11
#endregion
#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()
void DisableWindowDecorations()
{
if (DisableMotifDecorations())
{
Debug.Print("Removed decorations through motif.");
_decorations_hidden = true;
}
//bool removed = false;
//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 (DisableMotifDecorations())
{
Debug.Print("Removed decorations through motif.");
_decorations_hidden = true;
}
// Functions.XSetTransientForHint(this.window.Display, this.Handle, this.window.RootWindow);
// Some WMs remove decorations when this hint is set. Doesn't hurt to try.
Functions.XSetTransientForHint(this.window.Display, this.Handle, this.window.RootWindow);
//if (removed)
//{
// Functions.XSetTransientForHint(this.window.Display, this.Handle, this.window.RootWindow);
// 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 DisableMotifDecorations()
@ -1066,11 +1082,13 @@ namespace OpenTK.Platform.X11
{
IntPtr atom = Functions.XInternAtom(this.window.Display, MOTIF_WM_ATOM, true);
if (atom != IntPtr.Zero)
{
{
//Functions.XGetWindowProperty(window.Display, window.WindowHandle, atom, IntPtr.Zero, IntPtr.Zero, false,
MotifWmHints hints = new MotifWmHints();
hints.flags = (IntPtr)MotifFlags.Decorations;
Functions.XChangeProperty(this.window.Display, this.Handle, atom, atom, 32, PropertyMode.Replace,
ref hints, /*Marshal.SizeOf(hints) / 4*/ 5);
Functions.XChangeProperty(this.window.Display, this.Handle, atom, atom, 32, PropertyMode.Replace,
ref hints, Marshal.SizeOf(hints) / IntPtr.Size);
return true;
}
return false;
@ -1086,8 +1104,8 @@ namespace OpenTK.Platform.X11
if (atom != IntPtr.Zero)
{
IntPtr hints = IntPtr.Zero;
Functions.XChangeProperty(this.window.Display, this.Handle, atom, atom, 32, PropertyMode.Replace,
ref hints, /*Marshal.SizeOf(hints) / 4*/ 1);
Functions.XChangeProperty(this.window.Display, this.Handle, atom, atom, 32, PropertyMode.Replace,
ref hints, Marshal.SizeOf(hints) / IntPtr.Size);
return true;
}
@ -1096,45 +1114,27 @@ namespace OpenTK.Platform.X11
#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
#region void EnableWindowDecorations()
void EnableWindowDecorations()
{
if (EnableMotifDecorations())
{
Debug.Print("Activated decorations through motif.");
_decorations_hidden = false;
}
//bool activated = false;
//if (EnableMotifDecorations()) { Debug.Print("Activated decorations through motif."); activated = true; }
{
if (EnableMotifDecorations())
{
Debug.Print("Activated decorations through motif.");
_decorations_hidden = false;
}
//if (EnableGnomeDecorations()) { Debug.Print("Activated decorations through gnome."); activated = true; }
//if (EnableIccmDecorations()) { Debug.Print("Activated decorations through ICCM."); activated = true; }
Functions.XSetTransientForHint(this.window.Display, this.Handle, IntPtr.Zero);
//if (activated)
//{
// Functions.XSetTransientForHint(this.window.Display, this.Handle, this.window.RootWindow);
// 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()
@ -1143,8 +1143,14 @@ namespace OpenTK.Platform.X11
{
IntPtr atom = Functions.XInternAtom(this.window.Display, MOTIF_WM_ATOM, true);
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 false;
@ -1177,26 +1183,6 @@ namespace OpenTK.Platform.X11
#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