Ok, I know am becoming a spammer ;-)

I dug in depth and found a fix for the MDI issue; MapWindow() has almost the
same inconsistent WM_SHOWWINDOW handling issue as UnmapWindow() has.

Though this fix exposed another issue that ApplicationContext could send
WM_QUIT inappropriately from ExitThreadCore(). When there is no application
loop, there is nothing to quit.

Though they are needed for XIM changes, the changes above are not about XIM.

The entire XIM patch is here: http://monoport.com/10928
(It includes this patch. Also note that this patch is dirty!)

When this patch and patch for bugs I wrote earlier are applied, I could
finally checkin this XIM change.

Atsushi Eno


Atsushi Eno wrote:
Hello,

After fixing couple of issues, I found a fix for this WaitForHwndMessage() issue. The situation is that (in some cases?) WM_SHOWWINDOW could be processed synchronously inside SendMessage() and when we reach WaitForHwndMessage(),
the MSG is already consumed and hence never shows up.

The attached patch fixes this issue. I'm still not sure why this does not
happen when we don't create XIM context for each client window, but
the sample repro in my last mail[*1] gets fixed with this patch.

If it looks okay, I'll commit this small change. I'm still not going to commit my XIM changes, as there are still pending fixes on bugzilla[*2] and there
seems another MDI issue that needs fix too.

Atsushi Eno

*1 http://monoport.com/9806
*2 #325033 and #387693


Atsushi Eno wrote:
Hi,

I'm posting it as I've been stuck with this issue for couple of days and
I still don't have a fix.

Now I'm trying to fix XIM stuff to show up IM engine UI. Currently only
scim works (I tried scim-anthy). Everything else (as far as I tried,
iiimx/atokx3 and kinput2) do not work.

It is (to my understanding) due to incorrect use of "client window" of the
input context (XIC). I fixed this issue with the patch [*1] but
it caused (or exposed) some regressions [*2][*3].

My guess is that there are some issues around X event filtering (as
XplatUIX11.WaitForHwndMessage does not finish) but I don't know how it
could be fixed.

I'll continue working on this issue but any help would be appreciated.

*1 http://monoport.com/9842
*2 Timer or Form.Close() causes infinite loop http://monoport.com/9804
... and it is not always reproducible.
*3 Form.set_Visible() causes infinite loop http://monoport.com/9806

Atsushi Eno

_______________________________________________
Mono-winforms-list maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-winforms-list



------------------------------------------------------------------------

_______________________________________________
Mono-winforms-list maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-winforms-list

Index: System.Windows.Forms/Control.cs
===================================================================
--- System.Windows.Forms/Control.cs	(revision 102695)
+++ System.Windows.Forms/Control.cs	(working copy)
@@ -5725,6 +5725,7 @@
 			if (IsDisposed)
 				return;
 
+			Form frm = this as Form;
 			if (m.WParam.ToInt32() != 0) {
 				if (m.LParam.ToInt32 () == 0) {
 					CreateControl ();
@@ -5747,8 +5748,6 @@
 			} else {
 				if (parent != null && Focused) {
 					Control	container;
-					Form frm = this as Form;
-					
 					// Need to start at parent, GetContainerControl might return ourselves if we're a container
 					container = (Control)parent.GetContainerControl();
 					if (container != null && (frm == null || !frm.IsMdiChild)) {
@@ -5757,10 +5756,12 @@
 				}
 			}
 
+			if (frm != null)
+				frm.waiting_showwindow = false;
+
 			// If the form is Max/Min, it got its OnVisibleChanged in SetVisibleCore
-			Form f = this as Form;
-			if (f != null) {
-				if (!IsRecreating && (f.IsMdiChild || f.WindowState == FormWindowState.Normal)) /* XXX make sure this works for mdi forms */
+			if (frm != null) {
+				if (!IsRecreating && (frm.IsMdiChild || frm.WindowState == FormWindowState.Normal)) /* XXX make sure this works for mdi forms */
 					OnVisibleChanged(EventArgs.Empty);
 			} else if (is_toplevel)
 				OnVisibleChanged(EventArgs.Empty);
Index: System.Windows.Forms/XplatUIX11.cs
===================================================================
--- System.Windows.Forms/XplatUIX11.cs	(revision 102695)
+++ System.Windows.Forms/XplatUIX11.cs	(working copy)
@@ -1430,10 +1430,12 @@
 
 		private void MapWindow(Hwnd hwnd, WindowType windows) {
 			if (!hwnd.mapped) {
-				if (Control.FromHandle(hwnd.Handle) is Form) {
-					Form f = Control.FromHandle(hwnd.Handle) as Form;
-					if (f.WindowState == FormWindowState.Normal)
+				Form f = Control.FromHandle(hwnd.Handle) as Form;
+				if (f != null) {
+					if (f.WindowState == FormWindowState.Normal) {
+						f.waiting_showwindow = true;
 						SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
+					}
 				}
 
 				// it's possible that our Hwnd is no
@@ -1442,44 +1444,40 @@
 				if (hwnd.zombie)
 					return;
 
-				bool need_to_wait = false;
-
 				if ((windows & WindowType.Whole) != 0) {
 					XMapWindow(DisplayHandle, hwnd.whole_window);
 				}
 				if ((windows & WindowType.Client) != 0) {
 					XMapWindow(DisplayHandle, hwnd.client_window);
-
-					need_to_wait = true;
 				}
 
 				hwnd.mapped = true;
 
-				if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
+				if (f != null && f.waiting_showwindow)
 					WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
 			}
 		}
 
 		private void UnmapWindow(Hwnd hwnd, WindowType windows) {
 			if (hwnd.mapped) {
+				Form f = null;
 				if (Control.FromHandle(hwnd.Handle) is Form) {
-					Form f = Control.FromHandle(hwnd.Handle) as Form;
-					if (f.WindowState == FormWindowState.Normal)
+					f = Control.FromHandle(hwnd.Handle) as Form;
+					if (f.WindowState == FormWindowState.Normal) {
+						f.waiting_showwindow = true;
 						SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, IntPtr.Zero, IntPtr.Zero);
+					}
 				}
 
 				// it's possible that our Hwnd is no
 				// longer valid after making that
 				// SendMessage call, so check here.
+				// FIXME: it is likely wrong, as it has already sent WM_SHOWWINDOW
 				if (hwnd.zombie)
 					return;
 
-				bool need_to_wait = false;
-
 				if ((windows & WindowType.Client) != 0) {
 					XUnmapWindow(DisplayHandle, hwnd.client_window);
-
-					need_to_wait = true;
 				}
 				if ((windows & WindowType.Whole) != 0) {
 					XUnmapWindow(DisplayHandle, hwnd.whole_window);
@@ -1487,7 +1485,7 @@
 
 				hwnd.mapped = false;
 
-				if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
+				if (f != null && f.waiting_showwindow)
 					WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
 			}
 		}
Index: System.Windows.Forms/Form.cs
===================================================================
--- System.Windows.Forms/Form.cs	(revision 102695)
+++ System.Windows.Forms/Form.cs	(working copy)
@@ -92,6 +92,7 @@
 		private bool			shown_raised;  // The shown event is only raised once
 		private bool			is_clientsize_set;
 		internal bool			suppress_closing_events;
+		internal bool			waiting_showwindow; // for XplatUIX11
 
 #if NET_2_0
 		private MenuStrip		main_menu_strip;
Index: System.Windows.Forms/ApplicationContext.cs
===================================================================
--- System.Windows.Forms/ApplicationContext.cs	(revision 102695)
+++ System.Windows.Forms/ApplicationContext.cs	(working copy)
@@ -106,7 +106,8 @@
 		}
 
 		protected virtual void ExitThreadCore() {
-			XplatUI.PostQuitMessage(0);
+			if (Application.MWFThread.Current.Context == this)
+				XplatUI.PostQuitMessage(0);
 			if (!thread_exit_raised && ThreadExit != null) {
 				thread_exit_raised = true;
 				ThreadExit(this, EventArgs.Empty);
_______________________________________________
Mono-winforms-list maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-winforms-list

Reply via email to