Author: toshok
Date: 2007-02-28 16:31:26 -0500 (Wed, 28 Feb 2007)
New Revision: 73571

Modified:
   
branches/mwf-handle-branch/Managed.Windows.Forms/System.Windows.Forms/Application.cs
   
branches/mwf-handle-branch/Managed.Windows.Forms/System.Windows.Forms/ApplicationContext.cs
   
branches/mwf-handle-branch/Managed.Windows.Forms/System.Windows.Forms/ChangeLog
   
branches/mwf-handle-branch/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs
   
branches/mwf-handle-branch/Managed.Windows.Forms/Test/System.Windows.Forms/ChangeLog
   
branches/mwf-handle-branch/Managed.Windows.Forms/Test/System.Windows.Forms/ControlTest.cs
Log:
In Test/System.Windows.Forms:
2007-02-28  Chris Toshok  <[EMAIL PROTECTED]>

        * ControlTest.cs: Flesh out ControlInvokeTest to make sure that
        the Control thread dies (that Application.Run returns, basically).
        This works in isolation, but for some reason it isn't exiting when
        run in concert with other tests (this test is the cause of the
        hangs running the unit tests.)  Marking NotWorking for the time
        being.  This needs to be fixed before merging back to the
        mainline, imo.

In System.Windows.Forms:
2007-02-28  Chris Toshok  <[EMAIL PROTECTED]>

        * ApplicationContext.cs: Add a flag to make sure we only raise the
        ThreadExit event once (ExitThreadCore can be indirectly called
        from a few places.)  I don't like the additional flag, but it
        makes the event ordering/count correct.

        * Application.cs (MWFThread.LoopCount): don't use an enumerator
        without locking the collection.  An enumerator doesn't give us any
        protection from modification anyway.  Lock the thread hash and
        replace the complicated enumerator loop with a foreach.
        (Application.CloseForms): make internal so it can be called from
        ApplicationContext.  This should probably be moved to MWFThread.
        (Application.ExitThread): don't call MWFThread.Current.Exit()
        here.  just call XplatUI.PostQuitMessage.  We'll exit the thread
        when the runloop exits (in response to WM_QUIT.)
        (Application.RunLoop): add a comment (and check) for
        context.MainForm being null after setting context.MainForm.Visible
        = true.  This is because you're perfectly free to dispose of a
        form in VisibilityChanged.  Chalk this up to another case where we
        need to synchronously generate WM_ACTIVATE from Control.Show.
        Also, add handling for WM_QUIT here so we'll exit the loop.
        
        * XplatUIX11.cs: clean up MapWindow and UnmapWindow a bit.  The
        fact that we don't wait if we're only unmapping the whole_window
        makes me a bit nervous, but it doesn't seem to cause any problems
        yet.

        also, add a comment about the stupid, broken and wrong resetting
        of PostQuitState to false in GetMessage().

        In PostQuitMessage, we need to add a WM_QUIT message to the
        thread's queue.  We use the FosterParent to get the right
        handle/hwnd/queue.

        Lastly, in SetVisible, we need to unmap both windows, since the
        waiting only happens when we're unmapping the client window.  So
        now, the *only* time we unmap just the whole_window is in the hack
        for resizing a control to 0,0.
        


Modified: 
branches/mwf-handle-branch/Managed.Windows.Forms/System.Windows.Forms/Application.cs
===================================================================
--- 
branches/mwf-handle-branch/Managed.Windows.Forms/System.Windows.Forms/Application.cs
        2007-02-28 21:05:20 UTC (rev 73570)
+++ 
branches/mwf-handle-branch/Managed.Windows.Forms/System.Windows.Forms/Application.cs
        2007-02-28 21:31:26 UTC (rev 73571)
@@ -80,21 +80,16 @@
 
                        public static int LoopCount {
                                get {
-                                       IEnumerator     e;
-                                       int             loops;
-                                       MWFThread       thread;
+                                       lock (threads) {
+                                               int loops = 0;
 
-                                       e = threads.Values.GetEnumerator();
-                                       loops = 0;
-
-                                       while (e.MoveNext()) {
-                                               thread = (MWFThread)e.Current;
-                                               if (thread != null && 
thread.messageloop_started) {
-                                                       loops++;
+                                               foreach (MWFThread thread in 
threads.Values) {
+                                                       if 
(thread.messageloop_started)
+                                                               loops++;
                                                }
-                                       }
 
-                                       return loops;
+                                               return loops;
+                                       }
                                }
                        }
 
@@ -133,9 +128,8 @@
                                                
Application.ApplicationExit(null, EventArgs.Empty);
                                        }
                                }
-                               lock (threads) {
-                                       threads[thread_id] = null;
-                               }
+
+                               ((MWFThread)threads[thread_id]).MessageLoop = 
false;
                        }
                        #endregion      // Methods
                }
@@ -155,7 +149,7 @@
                }
 
                #region Private Methods
-               private static void CloseForms(Thread thread) {
+               internal static void CloseForms(Thread thread) {
                        #if DebugRunLoop
                                Console.WriteLine("   CloseForms({0}) called", 
thread);
                        #endif
@@ -449,19 +443,14 @@
 #endif
 
                public static void Exit() {
+                       XplatUI.PostQuitMessage(0);
                        CloseForms(null);
-
-                       // FIXME - this needs to be fired when they're all 
closed
-                       // But CloseForms uses PostMessage, so it gets fired 
before
-                       // We need to wait on something...
-                       if (ApplicationExit != null) {
-                               ApplicationExit(null, EventArgs.Empty);
-                       }
                }
 
                public static void ExitThread() {
                        CloseForms(Thread.CurrentThread);
-                       MWFThread.Current.Exit();
+                       // this might not be right - need to investigate 
(somehow) if a WM_QUIT message is generated here
+                       XplatUI.PostQuitMessage(0);
                }
 
                public static ApartmentState OleRequired() {
@@ -537,9 +526,9 @@
                                context.MainForm.context = context;
                                context.MainForm.closing = false;
                                context.MainForm.Visible = true;        // 
Cannot use Show() or scaling gets confused by menus
-                               // FIXME - do we need this?
-                               //context.MainForm.PerformLayout();
-                               context.MainForm.Activate();
+                               // XXX the above line can be used to close the 
form. another problem with our handling of Show/Activate.
+                               if (context.MainForm != null)
+                                       context.MainForm.Activate();
                        }
 
                        #if DebugRunLoop
@@ -582,7 +571,9 @@
                        queue_id = XplatUI.StartLoop(Thread.CurrentThread);
                        thread.MessageLoop = true;
 
-                       while (XplatUI.GetMessage(queue_id, ref msg, 
IntPtr.Zero, 0, 0)) {
+                       bool quit = false;
+
+                       while (!quit && XplatUI.GetMessage(queue_id, ref msg, 
IntPtr.Zero, 0, 0)) {
                                lock (message_filters) {
                                        if (message_filters.Count > 0) {
                                                Message m;
@@ -619,6 +610,9 @@
                                                goto default;
                                        }
                                        break;
+                               case Msg.WM_QUIT:
+                                       quit = true; // make sure we exit
+                                       break;
                                default:
                                        XplatUI.TranslateMessage(ref msg);
                                        XplatUI.DispatchMessage(ref msg);

Modified: 
branches/mwf-handle-branch/Managed.Windows.Forms/System.Windows.Forms/ApplicationContext.cs
===================================================================
--- 
branches/mwf-handle-branch/Managed.Windows.Forms/System.Windows.Forms/ApplicationContext.cs
 2007-02-28 21:05:20 UTC (rev 73570)
+++ 
branches/mwf-handle-branch/Managed.Windows.Forms/System.Windows.Forms/ApplicationContext.cs
 2007-02-28 21:31:26 UTC (rev 73571)
@@ -36,6 +36,8 @@
 #if NET_2_0
                object tag;
 #endif
+               bool thread_exit_raised;
+
                #endregion      // Local Variables
 
                #region Public Constructors & Destructors
@@ -104,7 +106,9 @@
                }
 
                protected virtual void ExitThreadCore() {
-                       if (ThreadExit!=null) {
+                       XplatUI.PostQuitMessage(0);
+                       if (!thread_exit_raised && ThreadExit != null) {
+                               thread_exit_raised = true;
                                ThreadExit(this, EventArgs.Empty);
                        }
                }

Modified: 
branches/mwf-handle-branch/Managed.Windows.Forms/System.Windows.Forms/ChangeLog
===================================================================
--- 
branches/mwf-handle-branch/Managed.Windows.Forms/System.Windows.Forms/ChangeLog 
    2007-02-28 21:05:20 UTC (rev 73570)
+++ 
branches/mwf-handle-branch/Managed.Windows.Forms/System.Windows.Forms/ChangeLog 
    2007-02-28 21:31:26 UTC (rev 73571)
@@ -1,3 +1,43 @@
+2007-02-28  Chris Toshok  <[EMAIL PROTECTED]>
+
+       * ApplicationContext.cs: Add a flag to make sure we only raise the
+       ThreadExit event once (ExitThreadCore can be indirectly called
+       from a few places.)  I don't like the additional flag, but it
+       makes the event ordering/count correct.
+
+       * Application.cs (MWFThread.LoopCount): don't use an enumerator
+       without locking the collection.  An enumerator doesn't give us any
+       protection from modification anyway.  Lock the thread hash and
+       replace the complicated enumerator loop with a foreach.
+       (Application.CloseForms): make internal so it can be called from
+       ApplicationContext.  This should probably be moved to MWFThread.
+       (Application.ExitThread): don't call MWFThread.Current.Exit()
+       here.  just call XplatUI.PostQuitMessage.  We'll exit the thread
+       when the runloop exits (in response to WM_QUIT.)
+       (Application.RunLoop): add a comment (and check) for
+       context.MainForm being null after setting context.MainForm.Visible
+       = true.  This is because you're perfectly free to dispose of a
+       form in VisibilityChanged.  Chalk this up to another case where we
+       need to synchronously generate WM_ACTIVATE from Control.Show.
+       Also, add handling for WM_QUIT here so we'll exit the loop.
+       
+       * XplatUIX11.cs: clean up MapWindow and UnmapWindow a bit.  The
+       fact that we don't wait if we're only unmapping the whole_window
+       makes me a bit nervous, but it doesn't seem to cause any problems
+       yet.
+
+       also, add a comment about the stupid, broken and wrong resetting
+       of PostQuitState to false in GetMessage().
+
+       In PostQuitMessage, we need to add a WM_QUIT message to the
+       thread's queue.  We use the FosterParent to get the right
+       handle/hwnd/queue.
+
+       Lastly, in SetVisible, we need to unmap both windows, since the
+       waiting only happens when we're unmapping the client window.  So
+       now, the *only* time we unmap just the whole_window is in the hack
+       for resizing a control to 0,0.
+       
 2007-02-21  Chris Toshok  <[EMAIL PROTECTED]>
 
        * Application.cs (CloseForms): rewrite this so that we don't

Modified: 
branches/mwf-handle-branch/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs
===================================================================
--- 
branches/mwf-handle-branch/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs
 2007-02-28 21:05:20 UTC (rev 73570)
+++ 
branches/mwf-handle-branch/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs
 2007-02-28 21:31:26 UTC (rev 73571)
@@ -1292,31 +1292,41 @@
 
                private void MapWindow(Hwnd hwnd, WindowType windows) {
                        if (!hwnd.mapped) {
-                               hwnd.mapped = true;
+                               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);
 
-                                       if (Control.FromHandle(hwnd.Handle) is 
Form)
-                                               WaitForHwndMessage (hwnd, 
Msg.WM_SHOWWINDOW);
+                                       need_to_wait = true;
                                }
+
+                               hwnd.mapped = true;
+
+                               if (need_to_wait && 
Control.FromHandle(hwnd.Handle) is Form)
+                                       WaitForHwndMessage (hwnd, 
Msg.WM_SHOWWINDOW);
                        }
                }
 
                private void UnmapWindow(Hwnd hwnd, WindowType windows) {
                        if (hwnd.mapped) {
-                               hwnd.mapped = false;
+                               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);
                                }
-                               if ((windows & WindowType.Client) != 0) {
-                                       XUnmapWindow(DisplayHandle, 
hwnd.client_window);
 
-                                       if (Control.FromHandle(hwnd.Handle) is 
Form)
-                                               WaitForHwndMessage (hwnd, 
Msg.WM_SHOWWINDOW);
-                               }
+                               hwnd.mapped = false;
+
+                               if (need_to_wait && 
Control.FromHandle(hwnd.Handle) is Form)
+                                       WaitForHwndMessage (hwnd, 
Msg.WM_SHOWWINDOW);
                        }
                }
 
@@ -3269,6 +3279,14 @@
                                        }
 
                                        // We reset ourselves so GetMessage can 
be called again
+
+                                       // XXX this is *so* wrong.  if
+                                       // we've posted the quit
+                                       // message we shouldn't *be*
+                                       // called again.  Removing it,
+                                       // however, makes many of the
+                                       // ListView unit tests fail.
+                                       // should investigate why.
                                        
ThreadQueue(Thread.CurrentThread).PostQuitState = false;
 
                                        return false;
@@ -4293,7 +4311,7 @@
                }
 
                internal override void PostQuitMessage(int exitCode) {
-                       
+                       PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, 
IntPtr.Zero);
                        XFlush(DisplayHandle);
                        ThreadQueue(Thread.CurrentThread).PostQuitState = true;
                }
@@ -4858,7 +4876,7 @@
                                        SendMessage(handle, 
Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
                                }
                                else {
-                                       UnmapWindow(hwnd, WindowType.Whole);
+                                       UnmapWindow(hwnd, WindowType.Both);
                                }
                        }
                        return true;

Modified: 
branches/mwf-handle-branch/Managed.Windows.Forms/Test/System.Windows.Forms/ChangeLog
===================================================================
--- 
branches/mwf-handle-branch/Managed.Windows.Forms/Test/System.Windows.Forms/ChangeLog
        2007-02-28 21:05:20 UTC (rev 73570)
+++ 
branches/mwf-handle-branch/Managed.Windows.Forms/Test/System.Windows.Forms/ChangeLog
        2007-02-28 21:31:26 UTC (rev 73571)
@@ -1,3 +1,13 @@
+2007-02-28  Chris Toshok  <[EMAIL PROTECTED]>
+
+       * ControlTest.cs: Flesh out ControlInvokeTest to make sure that
+       the Control thread dies (that Application.Run returns, basically).
+       This works in isolation, but for some reason it isn't exiting when
+       run in concert with other tests (this test is the cause of the
+       hangs running the unit tests.)  Marking NotWorking for the time
+       being.  This needs to be fixed before merging back to the
+       mainline, imo.
+
 2007-02-12  Everaldo Canuto  <[EMAIL PROTECTED]>
 
        * LabelTest.cs: Rename PreferredSize test to PreferredWidth and

Modified: 
branches/mwf-handle-branch/Managed.Windows.Forms/Test/System.Windows.Forms/ControlTest.cs
===================================================================
--- 
branches/mwf-handle-branch/Managed.Windows.Forms/Test/System.Windows.Forms/ControlTest.cs
   2007-02-28 21:05:20 UTC (rev 73570)
+++ 
branches/mwf-handle-branch/Managed.Windows.Forms/Test/System.Windows.Forms/ControlTest.cs
   2007-02-28 21:31:26 UTC (rev 73571)
@@ -1745,6 +1745,7 @@
        }
 
        [TestFixture]
+       [Category ("NotWorking")]
        public class ControlInvokeTest {
                public delegate void TestDelegate ();
 
@@ -1753,11 +1754,13 @@
                Thread control_t;
                ApplicationContext control_context;
                bool delegateCalled = false;
+               bool threadDied = false;
 
                object m;
 
                void CreateControl ()
                {
+                       try {
                        f = new Form ();
                        f.ShowInTaskbar = false;
                        
@@ -1777,11 +1780,20 @@
                        Console.WriteLine ("control thread running");
                        Application.Run (control_context);
                        c.Dispose ();
+                       Console.WriteLine ("dying");
+                       threadDied = true;
+                       Monitor.Enter (m);
+                       Console.WriteLine ("pulsing again");
+                       Monitor.Pulse (m);
+                       Monitor.Exit (m);
+                       } catch (Exception e) { Console.WriteLine (e); }
                }
 
                [Test]
                public void InvokeTest ()
                {
+                       Console.WriteLine ("hi");
+
                        m = new object ();
 
                        control_t = new Thread(new ThreadStart(CreateControl));
@@ -1799,14 +1811,20 @@
                        result = c.BeginInvoke (new TestDelegate 
(delegate_call));
                        c.EndInvoke (result);
 
-                       Assert.AreEqual (true, delegateCalled, "Invoke1");
+                       Assert.IsTrue (delegateCalled, "Invoke1");
+
+                       Monitor.Wait (m);
+                       Assert.IsTrue (threadDied, "Invoke2");
                }
 
                public void delegate_call () {
+                       try {
                        /* invoked on control_context's thread */
                        delegateCalled = true;
                        f.Dispose ();
-                       Application.Exit ();
+                       Console.WriteLine ("calling Application.Exit");
+                       control_context.ExitThread ();
+                       } catch (Exception e) { Console.WriteLine (e); }
                }
                
        }

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

Reply via email to