X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mcs%2Fclass%2FManaged.Windows.Forms%2FSystem.Windows.Forms.X11Internal%2FX11ThreadQueue.cs;h=cf07045de7b753f157749512ec9ae62043c460b8;hb=9f3ef8e4bac11601a2cf2670cbab337e6276103b;hp=954b4f7b6bb924b4532249facb2937572664ce99;hpb=881f83658281916d8f0784df7c726ecb7cc289db;p=mono.git diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/X11ThreadQueue.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/X11ThreadQueue.cs index 954b4f7b6bb..cf07045de7b 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/X11ThreadQueue.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/X11ThreadQueue.cs @@ -67,6 +67,25 @@ namespace System.Windows.Forms.X11Internal { public void EnqueueUnlocked (XEvent xevent) { + switch (xevent.type) { + case XEventName.KeyPress: + case XEventName.KeyRelease: + case XEventName.ButtonPress: + case XEventName.ButtonRelease: + NeedDispatchIdle = true; + break; + case XEventName.MotionNotify: + if (xqueue.Count > 0) { + XEvent peek = xqueue.Peek (); + if (peek.AnyEvent.type == XEventName.MotionNotify) + return; // we've already got a pending motion notify. + } + + // otherwise fall through and enqueue + // the event. + break; + } + xqueue.Enqueue (xevent); // wake up any thread blocking in DequeueUnlocked Monitor.PulseAll (lockobj); @@ -79,70 +98,102 @@ namespace System.Windows.Forms.X11Internal { } } - public bool DequeueUnlocked (out XEvent xevent) + public bool Dequeue (out XEvent xevent) { - try_again: - if (xqueue.Count > 0) { - xevent = xqueue.Dequeue (); - return true; - } + StartOver: + bool got_xevent = false; - if (paint_queue.Count > 0 || configure_queue.Count > 0) { - xevent = new XEvent (); - return false; + lock (lockobj) { + if (xqueue.Count > 0) { + got_xevent = true; + xevent = xqueue.Dequeue (); + } + else + xevent = new XEvent (); /* not strictly needed, but mcs complains */ } - // both queues are empty. go to sleep until NextTimeout - // (or until there's an event to handle). + if (got_xevent) { + if (xevent.AnyEvent.type == XEventName.Expose) { +#if spew + Console.Write ("E"); + Console.Out.Flush (); +#endif + X11Hwnd hwnd = (X11Hwnd)Hwnd.GetObjectFromWindow (xevent.AnyEvent.window); + hwnd.AddExpose (xevent.AnyEvent.window == hwnd.ClientWindow, + xevent.ExposeEvent.x, xevent.ExposeEvent.y, + xevent.ExposeEvent.width, xevent.ExposeEvent.height); + goto StartOver; + } + else if (xevent.AnyEvent.type == XEventName.ConfigureNotify) { +#if spew + Console.Write ("C"); + Console.Out.Flush (); +#endif + X11Hwnd hwnd = (X11Hwnd)Hwnd.GetObjectFromWindow (xevent.AnyEvent.window); + hwnd.AddConfigureNotify (xevent); + goto StartOver; + } + else { +#if spew + Console.Write ("X"); + Console.Out.Flush (); +#endif + /* it was an event we can deal with directly, return it */ + return true; + } + } + else { + if (paint_queue.Count > 0) { + xevent = paint_queue.Dequeue (); +#if spew + Console.Write ("e"); + Console.Out.Flush (); +#endif + return true; + } + else if (configure_queue.Count > 0) { + xevent = configure_queue.Dequeue (); +#if spew + Console.Write ("c"); + Console.Out.Flush (); +#endif + return true; + } + } if (dispatch_idle && need_dispatch_idle) { OnIdle (EventArgs.Empty); need_dispatch_idle = false; } - if (Monitor.Wait (lockobj, NextTimeout (), true)) { - /* the lock was reaquired before timeout. - i.e. we have an event now */ - goto try_again; - } - else { - xevent = new XEvent (); - return false; - } - } - - public bool Dequeue (out XEvent xevent) - { lock (lockobj) { - return DequeueUnlocked (out xevent); + if (CountUnlocked > 0) + goto StartOver; + + if (Monitor.Wait (lockobj, NextTimeout (), true)) { + // the lock was reaquired before the + // timeout. meaning an event was + // enqueued by X11Display.XEventThread. + goto StartOver; + } + else { + CheckTimers (); + return false; + } } } - public void RemovePaintUnlocked (Hwnd hwnd) - { - paint_queue.Remove (hwnd); - } - public void RemovePaint (Hwnd hwnd) { - lock (lockobj) { - RemovePaintUnlocked (hwnd); - } - } - - public void AddPaintUnlocked (Hwnd hwnd) - { - paint_queue.Enqueue (hwnd); + paint_queue.Remove (hwnd); } public void AddPaint (Hwnd hwnd) { - lock (lockobj) { - AddPaintUnlocked (hwnd); - } + paint_queue.Enqueue (hwnd); } - public void AddConfigureUnlocked (Hwnd hwnd) + public void AddConfigure (Hwnd hwnd) { configure_queue.Enqueue (hwnd); } @@ -258,10 +309,15 @@ namespace System.Windows.Forms.X11Internal { public abstract class HwndEventQueue { protected ArrayList hwnds; - +#if DebugHwndEventQueue + protected ArrayList stacks; +#endif public HwndEventQueue (int size) { - hwnds = new ArrayList(size); + hwnds = new ArrayList (size); +#if DebugHwndEventQueue + stacks = new ArrayList (size); +#endif } public int Count { @@ -271,31 +327,39 @@ namespace System.Windows.Forms.X11Internal { public void Enqueue (Hwnd hwnd) { if (hwnds.Contains (hwnd)) { +#if DebugHwndEventQueue Console.WriteLine ("hwnds can only appear in the queue once."); Console.WriteLine (Environment.StackTrace); + Console.WriteLine ("originally added here:"); + Console.WriteLine (stacks[hwnds.IndexOf (hwnd)]); +#endif + return; } hwnds.Add(hwnd); +#if DebugHwndEventQueue + stacks.Add(Environment.StackTrace); +#endif } public void Remove(Hwnd hwnd) { +#if DebugHwndEventQueue + int index = hwnds.IndexOf(hwnd); + if (index != -1) + stacks.RemoveAt(index); +#endif hwnds.Remove(hwnd); } protected abstract XEvent Peek (); - public XEvent Dequeue () + public virtual XEvent Dequeue () { if (hwnds.Count == 0) throw new Exception ("Attempt to dequeue empty queue."); - // populate the xevent - XEvent xevent = Peek (); - - hwnds.RemoveAt(0); - - return xevent; + return Peek (); } } @@ -321,6 +385,19 @@ namespace System.Windows.Forms.X11Internal { return xevent; } + + public override XEvent Dequeue () + { + XEvent xev = base.Dequeue (); + + + hwnds.RemoveAt(0); +#if DebugHwndEventQueue + stacks.RemoveAt(0); +#endif + + return xev; + } } public class PaintQueue : HwndEventQueue @@ -349,6 +426,8 @@ namespace System.Windows.Forms.X11Internal { return xevent; } + + // don't override Dequeue like ConfigureQueue does. } /* a circular queue for holding X events for processing by GetMessage */