Protect all Xlib calls with XLockDisplay/XUnlockDisplay. Fixes issue [#1354]: "Application always run in windowed mode when using shared contexts".

This commit is contained in:
the_fiddler 2009-11-09 19:05:41 +00:00
parent d3ba9e61e0
commit 089b72c9c8
3 changed files with 220 additions and 157 deletions

View file

@ -1590,15 +1590,32 @@ XF86VidModeGetGammaRampSize(
}
*/
// Helper structure for calling XLock/UnlockDisplay
struct XLock : IDisposable
{
readonly IntPtr Display;
IntPtr _display;
public IntPtr Display
{
get
{
if (_display == IntPtr.Zero)
throw new InvalidOperationException("Internal error (XLockDisplay with IntPtr.Zero). Please report this at http://www.opentk.com/node/add/project-issue/opentk");
return _display;
}
set
{
if (value == IntPtr.Zero)
throw new ArgumentException();
_display = value;
}
}
public XLock(IntPtr display)
: this()
{
Functions.XLockDisplay(display);
Display = display;
Functions.XLockDisplay(Display);
}
public void Dispose()

View file

@ -280,7 +280,10 @@ namespace OpenTK.Platform.X11
IntPtr dummy;
XSizeHints hints = new XSizeHints();
using (new XLock(window.Display))
{
Functions.XGetWMNormalHints(window.Display, window.WindowHandle, ref hints, out dummy);
}
if (min_width > 0 || min_height > 0)
{
@ -300,15 +303,17 @@ namespace OpenTK.Platform.X11
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
using (new XLock(window.Display))
{
Functions.XSetWMNormalHints(window.Display, window.WindowHandle, ref hints);
}
}
}
#endregion
@ -326,6 +331,8 @@ namespace OpenTK.Platform.X11
IntPtr atom;
//XWindowAttributes attributes;
using (new XLock(window.Display))
{
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,
@ -341,6 +348,7 @@ namespace OpenTK.Platform.X11
}
Functions.XFree(prop);
}
}
return false;
}
@ -362,6 +370,8 @@ namespace OpenTK.Platform.X11
//IntPtr atom;
//XWindowAttributes attributes;
using (new XLock(window.Display))
{
// 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)
@ -382,6 +392,7 @@ namespace OpenTK.Platform.X11
return false;
}
}
}
#endregion
@ -395,6 +406,8 @@ namespace OpenTK.Platform.X11
_decorations_hidden = true;
}
using (new XLock(window.Display))
{
// Functions.XSetTransientForHint(this.window.Display, this.Handle, this.window.RootWindow);
// Some WMs remove decorations when this hint is set. Doesn't hurt to try.
@ -406,6 +419,7 @@ namespace OpenTK.Platform.X11
Functions.XMapWindow(this.window.Display, this.Handle);
}
}
}
#region bool DisableMotifDecorations()
@ -459,6 +473,8 @@ namespace OpenTK.Platform.X11
//if (EnableGnomeDecorations()) { Debug.Print("Activated decorations through gnome."); activated = true; }
using (new XLock(window.Display))
{
Functions.XSetTransientForHint(this.window.Display, this.Handle, IntPtr.Zero);
if (!_decorations_hidden)
@ -467,10 +483,13 @@ namespace OpenTK.Platform.X11
Functions.XMapWindow(this.window.Display, this.Handle);
}
}
}
#region bool EnableMotifDecorations()
bool EnableMotifDecorations()
{
using (new XLock(window.Display))
{
IntPtr atom = Functions.XInternAtom(this.window.Display, MOTIF_WM_ATOM, true);
if (atom != IntPtr.Zero)
@ -486,12 +505,15 @@ namespace OpenTK.Platform.X11
}
return false;
}
}
#endregion
#region bool EnableGnomeDecorations()
bool EnableGnomeDecorations()
{
using (new XLock(window.Display))
{
// Restore window layer.
//XEvent xev = new XEvent();
@ -511,6 +533,7 @@ namespace OpenTK.Platform.X11
return false;
}
}
#endregion
@ -519,6 +542,8 @@ namespace OpenTK.Platform.X11
#region DeleteIconPixmaps
static void DeleteIconPixmaps(IntPtr display, IntPtr window)
{
using (new XLock(display))
{
IntPtr wmHints_ptr = Functions.XGetWMHints(display, window);
@ -543,6 +568,7 @@ namespace OpenTK.Platform.X11
Functions.XFree(wmHints_ptr);
}
}
}
#endregion
@ -862,10 +888,13 @@ namespace OpenTK.Platform.X11
// Note: it seems that Gnome/Metacity does not respect the _NET_WM_ICON hint.
// For this reason, we'll also set the icon using XSetWMHints.
if (value == null)
{
using (new XLock(window.Display))
{
Functions.XDeleteProperty(window.Display, window.WindowHandle, _atom_net_wm_icon);
DeleteIconPixmaps(window.Display, window.WindowHandle);
}
}
else
{
// Set _NET_WM_ICON
@ -881,12 +910,17 @@ namespace OpenTK.Platform.X11
for (int x = 0; x < bitmap.Width; x++)
data[index++] = (IntPtr)bitmap.GetPixel(x, y).ToArgb();
using (new XLock(window.Display))
{
Functions.XChangeProperty(window.Display, window.WindowHandle,
_atom_net_wm_icon, _atom_xa_cardinal, 32,
PropertyMode.Replace, data, size);
}
// Set XWMHints
DeleteIconPixmaps(window.Display, window.WindowHandle);
using (new XLock(window.Display))
{
IntPtr wmHints_ptr = Functions.XGetWMHints(window.Display, window.WindowHandle);
if (wmHints_ptr == IntPtr.Zero)
@ -903,6 +937,7 @@ namespace OpenTK.Platform.X11
Functions.XSync(window.Display, false);
}
}
icon = value;
if (IconChanged != null)
@ -941,9 +976,12 @@ namespace OpenTK.Platform.X11
int maximized = 0;
bool minimized = false;
using (new XLock(window.Display))
{
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)
{
@ -959,8 +997,11 @@ namespace OpenTK.Platform.X11
else if (atom == _atom_net_wm_state_fullscreen)
fullscreen = true;
}
using (new XLock(window.Display))
{
Functions.XFree(prop);
}
}
if (minimized)
return OpenTK.WindowState.Minimized;
@ -986,6 +1027,8 @@ namespace OpenTK.Platform.X11
Debug.Print("GameWindow {0} changing WindowState from {1} to {2}.", window.WindowHandle.ToString(),
current_state.ToString(), value.ToString());
using (new XLock(window.Display))
{
if (current_state == OpenTK.WindowState.Minimized)
Functions.XMapWindow(window.Display, window.WindowHandle);
else if (current_state == OpenTK.WindowState.Fullscreen)
@ -998,7 +1041,7 @@ namespace OpenTK.Platform.X11
_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;
@ -1008,6 +1051,8 @@ namespace OpenTK.Platform.X11
WindowBorder = WindowBorder.Resizable;
}
using (new XLock(window.Display))
{
switch (value)
{
case OpenTK.WindowState.Normal:
@ -1038,6 +1083,7 @@ namespace OpenTK.Platform.X11
break;
}
}
if (temporary_resizable)
WindowBorder = previous_state;