Skip to content

Commit

Permalink
2006-03-31 Peter Dennis Bartok <pbartok@novell.com>
Browse files Browse the repository at this point in the history
	* XplatUIX11.cs: 
	  - We now track the mapping state of windows. If a window (or 
	    one of it's parents) is not mapped we no longer permit
	    WM_PAINT messages to be generated since we'd otherwise get 
	    lots of BadMatch X errors. Jackson did all the work figuring
	    out the problem.
	  - Destroying the caret if the window it's contained in is 
	    destroyed. Can't use regular DestroyCaret method since it
	    might fall into a drawing function (trying to remove the
	    caret) and with that generate new BadMatch errors. Again,
	    Jackson tracked this down.
	  - Changed DestroyChildWindows to SendWMDestroyMessages, we now
	    make sure we send the messages to all windows. (The old code
	    would send the WM_DESTROY to the window, and then all child
	    windows would be 'gone' because the WM_DESTROY handle lookup
	    would no longer find the destroyed window)
	* Hwnd.cs: Added Mapping property to track mapping state of hwnd
	* X11Structs.cs: Added WindowType enum for MapWindow/UnmapWindow


svn path=/trunk/mcs/; revision=58866
  • Loading branch information
Peter Dennis Bartok committed Mar 31, 2006
1 parent 9280120 commit b068dd7
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 41 deletions.
23 changes: 21 additions & 2 deletions mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog
@@ -1,3 +1,24 @@
2006-03-31 Peter Dennis Bartok <pbartok@novell.com>

* XplatUIX11.cs:
- We now track the mapping state of windows. If a window (or
one of it's parents) is not mapped we no longer permit
WM_PAINT messages to be generated since we'd otherwise get
lots of BadMatch X errors. Jackson did all the work figuring
out the problem.
- Destroying the caret if the window it's contained in is
destroyed. Can't use regular DestroyCaret method since it
might fall into a drawing function (trying to remove the
caret) and with that generate new BadMatch errors. Again,
Jackson tracked this down.
- Changed DestroyChildWindows to SendWMDestroyMessages, we now
make sure we send the messages to all windows. (The old code
would send the WM_DESTROY to the window, and then all child
windows would be 'gone' because the WM_DESTROY handle lookup
would no longer find the destroyed window)
* Hwnd.cs: Added Mapping property to track mapping state of hwnd
* X11Structs.cs: Added WindowType enum for MapWindow/UnmapWindow

2006-03-31 Jackson Harper <jackson@ximian.com>

* ScrollableControl.cs: Dont recalc if we are not visible.
Expand Down Expand Up @@ -103,7 +124,6 @@
- Making sure the active control is selected when the control is created
* CurrencyManager.cs: Removed obsolete TODO

>>>>>>> .r58862
2006-03-29 Mike Kestner <mkestner@novell.com>

* *.cs: fix remaining corcompare issues for 1.1 API with the exception
Expand Down Expand Up @@ -335,7 +355,6 @@
* ContextMenu.cs (Show): use the position parameter instead of just
showing at the MousePosition.

>>>>>>> .r58288
2006-03-21 Jackson Harper <jackson@ximian.com>

* TabControl.cs: Remove the call to ProcessKeyEventArgs and let
Expand Down
21 changes: 20 additions & 1 deletion mcs/class/Managed.Windows.Forms/System.Windows.Forms/Hwnd.cs
Expand Up @@ -54,6 +54,7 @@ internal class Hwnd : IDisposable {
internal bool allow_drop;
internal Hwnd parent;
internal bool visible;
internal bool mapped;
internal uint opacity;
internal bool enabled;
internal bool zero_sized;
Expand Down Expand Up @@ -421,6 +422,24 @@ internal class Hwnd : IDisposable {
}
}

public bool Mapped {
get {
if (!mapped) {
return false;
}

if (parent != null) {
return parent.mapped;
}

return true;
}

set {
mapped = value;
}
}

public int CaptionHeight {
get { return caption_height; }
set { caption_height = value; }
Expand Down Expand Up @@ -567,7 +586,7 @@ internal class Hwnd : IDisposable {
}

public override string ToString() {
return String.Format("Hwnd, ClientWindow:0x{0:X}, WholeWindow:0x{1:X}, Parent:[{2:X}]", client_window.ToInt32(), whole_window.ToInt32(), parent != null ? parent.ToString() : "<null>");
return String.Format("Hwnd, Mapped:{3} ClientWindow:0x{0:X}, WholeWindow:0x{1:X}, Parent:[{2:X}]", client_window.ToInt32(), whole_window.ToInt32(), parent != null ? parent.ToString() : "<null>", Mapped);
}

#endregion // Methods
Expand Down
Expand Up @@ -1599,4 +1599,12 @@ internal enum XIMProperties {
XIMStatusNothing = 0x0400,
XIMStatusNone = 0x0800,
}

[Flags]
internal enum WindowType {
Client = 1,
Whole = 2,
Both = 3
}

}
129 changes: 91 additions & 38 deletions mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs
Expand Up @@ -1067,6 +1067,26 @@ internal class XException : ApplicationException {
}
}

private void MapWindow(Hwnd hwnd, WindowType windows) {
hwnd.mapped = true;
if ((windows & WindowType.Whole) != 0) {
XMapWindow(DisplayHandle, hwnd.whole_window);
}
if ((windows & WindowType.Client) != 0) {
XMapWindow(DisplayHandle, hwnd.client_window);
}
}

private void UnmapWindow(Hwnd hwnd, WindowType windows) {
hwnd.mapped = false;
if ((windows & WindowType.Whole) != 0) {
XUnmapWindow(DisplayHandle, hwnd.whole_window);
}
if ((windows & WindowType.Client) != 0) {
XUnmapWindow(DisplayHandle, hwnd.client_window);
}
}

private void UpdateMessageQueue () {
DateTime now;
int pending;
Expand Down Expand Up @@ -1244,6 +1264,26 @@ internal class XException : ApplicationException {
break;
}

case XEventName.MapNotify: {
Hwnd hwnd;

hwnd = Hwnd.GetObjectFromWindow(xevent.MapEvent.window);
if ((hwnd != null) && (hwnd.client_window == xevent.MapEvent.window)) {
hwnd.mapped = true;
}
break;
}

case XEventName.UnmapNotify: {
Hwnd hwnd;

hwnd = Hwnd.GetObjectFromWindow(xevent.MapEvent.window);
if ((hwnd != null) && (hwnd.client_window == xevent.MapEvent.window)) {
hwnd.mapped = false;
}
break;
}

case XEventName.KeyPress:
case XEventName.KeyRelease:
case XEventName.ButtonPress:
Expand Down Expand Up @@ -1367,24 +1407,31 @@ internal class XException : ApplicationException {
return 0;
}

private void DestroyChildWindow(Control c) {
private void SendWMDestroyMessages(Control c) {
Hwnd hwnd;
int i;
Control[] controls;

if (c != null) {
controls = c.child_controls.GetAllControls ();

#if DriverDebugDestroy
Console.WriteLine("Destroying {0} [Child of {1}]", XplatUI.Window(controls[i].Handle), XplatUI.Window(controls[i].parent.Handle));
#endif

if (c.IsHandleCreated) {
hwnd = Hwnd.ObjectFromHandle(c.Handle);
SendMessage(c.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
}

for (i = 0; i < controls.Length; i++) {
SendWMDestroyMessages(controls[i]);
if (controls[i].IsHandleCreated) {
hwnd = Hwnd.ObjectFromHandle(controls[i].Handle);
#if DriverDebugDestroy
Console.WriteLine("Destroying {0} [Child of {1}]", XplatUI.Window(controls[i].Handle), XplatUI.Window(controls[i].parent.Handle));
#endif
SendMessage(controls[i].Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
hwnd.Dispose();
if (hwnd != null) {
hwnd.Dispose();
}
}
DestroyChildWindow(controls[i]);
}
}
}
Expand Down Expand Up @@ -1425,6 +1472,7 @@ internal class XException : ApplicationException {
#region Callbacks
private void MouseHover(object sender, EventArgs e) {
XEvent xevent;

HoverState.Timer.Enabled = false;

if (HoverState.Window != IntPtr.Zero) {
Expand Down Expand Up @@ -1782,7 +1830,6 @@ internal class XException : ApplicationException {


internal override void CaretVisible(IntPtr handle, bool visible) {
// Visible is cumulative; two hides require two shows before the caret is visible again
if (Caret.Hwnd == handle) {
if (visible) {
if (!Caret.Visible) {
Expand Down Expand Up @@ -2054,14 +2101,13 @@ internal class XException : ApplicationException {
XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)SelectInputMask));

if ((cp.Style & (int)WindowStyles.WS_VISIBLE) != 0) {
XMapWindow(DisplayHandle, hwnd.whole_window);
XMapWindow(DisplayHandle, hwnd.client_window);
MapWindow(hwnd, WindowType.Both);
hwnd.visible = true;
}
}

if ((cp.ExStyle & (int) WindowExStyles.WS_EX_TOPMOST) != 0) {
Console.WriteLine ("Setting transient: " + XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow));
XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
}

SetWMStyles(hwnd, cp);
Expand Down Expand Up @@ -2417,6 +2463,19 @@ internal class XException : ApplicationException {
}
}

private void DestroyCaretInternal() {
if (Caret.Visible == true) {
Caret.Timer.Stop();
}
if (Caret.gc != IntPtr.Zero) {
XFreeGC(DisplayHandle, Caret.gc);
Caret.gc = IntPtr.Zero;
}
Caret.Hwnd = IntPtr.Zero;
Caret.Visible = false;
Caret.On = false;
}

internal override void DestroyCursor(IntPtr cursor) {
lock (XlibLock) {
XFreeCursor(DisplayHandle, cursor);
Expand Down Expand Up @@ -2444,11 +2503,8 @@ internal class XException : ApplicationException {
DestroyCaret(handle);
}

// Send destroy message
SendMessage(handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);

// Mark our children as gone as well
DestroyChildWindow(Control.ControlNativeWindow.ControlFromHandle(handle));
SendWMDestroyMessages(Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle));

lock (XlibLock) {
if (hwnd.client_window != IntPtr.Zero) {
Expand Down Expand Up @@ -3101,11 +3157,15 @@ internal class XException : ApplicationException {
}

case XEventName.Expose: {
if (PostQuitState) {
if (PostQuitState || !hwnd.Mapped) {
if (client) {
hwnd.expose_pending = false;
} else {
hwnd.nc_expose_pending = false;
}
goto ProcessNextMessage;
}


if (client) {
if (!hwnd.expose_pending) {
goto ProcessNextMessage;
Expand Down Expand Up @@ -3169,6 +3229,9 @@ internal class XException : ApplicationException {

// We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
if (Caret.Window == hwnd.client_window) {
DestroyCaretInternal();
}
msg.hwnd = hwnd.client_window;
msg.message=Msg.WM_DESTROY;
hwnd.Dispose();
Expand Down Expand Up @@ -3467,7 +3530,7 @@ internal class XException : ApplicationException {

if (client) {
hwnd.client_dc = Graphics.FromHwnd (hwnd.client_window);
hwnd.client_dc.SetClip(hwnd.invalid);
//hwnd.client_dc.SetClip(hwnd.invalid);
paint_event = new PaintEventArgs(hwnd.client_dc, hwnd.invalid);
hwnd.expose_pending = false;

Expand Down Expand Up @@ -3917,21 +3980,19 @@ internal override void SetAllowDrop (IntPtr handle, bool value)

s = ((Form)Control.FromHandle(handle)).WindowState;

XMapWindow(DisplayHandle, hwnd.whole_window);
XMapWindow(DisplayHandle, hwnd.client_window);
MapWindow(hwnd, WindowType.Both);

switch(s) {
case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
}

} else {
XMapWindow(DisplayHandle, hwnd.whole_window);
XMapWindow(DisplayHandle, hwnd.client_window);
MapWindow(hwnd, WindowType.Both);
}
SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
} else {
XUnmapWindow(DisplayHandle, hwnd.whole_window);
UnmapWindow(hwnd, WindowType.Whole);
}
}
return true;
Expand Down Expand Up @@ -3986,19 +4047,14 @@ internal override void SetAllowDrop (IntPtr handle, bool value)
// X requires a sanity check for width & height; otherwise it dies
if (hwnd.zero_sized && width > 0 && height > 0) {
if (hwnd.visible) {
XMapWindow(DisplayHandle, hwnd.whole_window);
MapWindow(hwnd, WindowType.Whole);
}
hwnd.zero_sized = false;
}

if (width < 1) {
if ((width < 1) || (height < 1)) {
hwnd.zero_sized = true;
XUnmapWindow(DisplayHandle, hwnd.whole_window);
}

if (height < 1) {
hwnd.zero_sized = true;
XUnmapWindow(DisplayHandle, hwnd.whole_window);
UnmapWindow(hwnd, WindowType.Whole);
}

client_rect = Hwnd.GetClientRectangle(hwnd.border_style, hwnd.menu, hwnd.title_style, hwnd.caption_height, hwnd.tool_caption_height, width, height);
Expand Down Expand Up @@ -4048,8 +4104,7 @@ internal override void SetAllowDrop (IntPtr handle, bool value)
case FormWindowState.Normal: {
lock (XlibLock) {
if (current_state == FormWindowState.Minimized) {
XMapWindow(DisplayHandle, hwnd.whole_window);
XMapWindow(DisplayHandle, hwnd.client_window);
MapWindow(hwnd, WindowType.Both);
} else if (current_state == FormWindowState.Maximized) {
SendNetWMMessage(hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)2 /* toggle */, NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
}
Expand All @@ -4071,8 +4126,7 @@ internal override void SetAllowDrop (IntPtr handle, bool value)
case FormWindowState.Maximized: {
lock (XlibLock) {
if (current_state == FormWindowState.Minimized) {
XMapWindow(DisplayHandle, hwnd.whole_window);
XMapWindow(DisplayHandle, hwnd.client_window);
MapWindow(hwnd, WindowType.Both);
}

SendNetWMMessage(hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)1 /* Add */, NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
Expand Down Expand Up @@ -4170,8 +4224,7 @@ internal override void SetAllowDrop (IntPtr handle, bool value)
Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
#endif

XUnmapWindow(DisplayHandle, hwnd.whole_window);
XUnmapWindow(DisplayHandle, hwnd.client_window);
UnmapWindow(hwnd, WindowType.Whole);

// Oh boy.
XDestroyWindow(DisplayHandle, hwnd.client_window);
Expand Down Expand Up @@ -4239,7 +4292,7 @@ internal override void SetAllowDrop (IntPtr handle, bool value)

hwnd = Hwnd.ObjectFromHandle(handle);

XUnmapWindow(DisplayHandle, hwnd.whole_window);
UnmapWindow(hwnd, WindowType.Whole);
SetParent(hwnd.whole_window, FosterParent);

// The caller can now re-dock it later...
Expand Down

0 comments on commit b068dd7

Please sign in to comment.