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);
}
}
- 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);
}
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 {
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 ();
}
}
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
return xevent;
}
+
+ // don't override Dequeue like ConfigureQueue does.
}
/* a circular queue for holding X events for processing by GetMessage */