Mercurial > hg > ucis.core
comparison FBGUI/FBGUI.cs @ 82:0d389692be32
FBGUI: Separated locking in renderer so Invalidate does not block while Painting in timer callback
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Mon, 17 Feb 2014 22:35:52 +0100 |
parents | 4e4c600031e2 |
children | 4ca44dd25a6a |
comparison
equal
deleted
inserted
replaced
80:4714531734b3 | 82:0d389692be32 |
---|---|
628 private FBGCursor cursor = null; | 628 private FBGCursor cursor = null; |
629 private Point cursorposition = Point.Empty; | 629 private Point cursorposition = Point.Empty; |
630 public IFramebuffer Framebuffer { get; private set; } | 630 public IFramebuffer Framebuffer { get; private set; } |
631 private Bitmap Frontbuffer = null; | 631 private Bitmap Frontbuffer = null; |
632 protected Object RenderLock = new object(); | 632 protected Object RenderLock = new object(); |
633 private Object StatusLock = new object(); | |
633 public event EventHandler<InvalidateEventArgs> Painted; | 634 public event EventHandler<InvalidateEventArgs> Painted; |
634 protected Size size = Size.Empty; | 635 protected Size size = Size.Empty; |
635 private ThreadingTimer PaintTimer = null; | 636 private ThreadingTimer PaintTimer = null; |
636 private Boolean PaintScheduled = false; | 637 private Boolean PaintScheduled = false; |
637 private int PaintDelay = 0; | 638 private int PaintDelay = 0; |
638 public Boolean SuspendDrawing { | 639 public Boolean SuspendDrawing { |
639 get { return suspenddrawing; } | 640 get { return suspenddrawing; } |
640 set { | 641 set { |
642 lock (StatusLock) suspenddrawing = value; | |
643 if (value) return; | |
641 lock (RenderLock) { | 644 lock (RenderLock) { |
642 suspenddrawing = value; | 645 Refresh(DirtyRectangle); |
643 if (!value) { | 646 DirtyRectangle = Rectangle.Empty; |
644 Refresh(DirtyRectangle); | |
645 DirtyRectangle = Rectangle.Empty; | |
646 } | |
647 } | 647 } |
648 } | 648 } |
649 } | 649 } |
650 public int RedrawDelay { | 650 public int RedrawDelay { |
651 get { return PaintDelay; } | 651 get { return PaintDelay; } |
652 set { | 652 set { |
653 lock (RenderLock) { | 653 lock (StatusLock) { |
654 if (value < 0) throw new ArgumentOutOfRangeException("value"); | 654 if (value < 0) throw new ArgumentOutOfRangeException("value"); |
655 PaintDelay = value; | 655 PaintDelay = value; |
656 if (PaintDelay == 0) { | 656 if (PaintDelay == 0) { |
657 if (PaintTimer != null) PaintTimer.Dispose(); | 657 if (PaintTimer != null) PaintTimer.Dispose(); |
658 PaintTimer = null; | 658 PaintTimer = null; |
659 if (PaintScheduled) PaintTimerCallback(null); | |
660 } else { | 659 } else { |
661 PaintTimer = new ThreadingTimer(PaintTimerCallback); | 660 PaintTimer = new ThreadingTimer(PaintTimerCallback); |
662 } | 661 } |
663 } | 662 } |
663 if (PaintScheduled) PaintTimerCallback(null); | |
664 } | 664 } |
665 } | 665 } |
666 private Boolean suspenddrawing = false; | 666 private Boolean suspenddrawing = false; |
667 private Rectangle DirtyRectangle; | 667 private Rectangle DirtyRectangle; |
668 | 668 |
707 e.Area = new Rectangle(PointFromChild(sender, e.Area.Location), e.Area.Size); | 707 e.Area = new Rectangle(PointFromChild(sender, e.Area.Location), e.Area.Size); |
708 Invalidate(e.Area); | 708 Invalidate(e.Area); |
709 } | 709 } |
710 public override void Invalidate(Rectangle rect) { | 710 public override void Invalidate(Rectangle rect) { |
711 if (rect.Width == 0 || rect.Height == 0) return; | 711 if (rect.Width == 0 || rect.Height == 0) return; |
712 lock (RenderLock) { | 712 Boolean drawDirect = false; |
713 lock (StatusLock) { | |
713 if (SuspendDrawing || PaintTimer != null) { | 714 if (SuspendDrawing || PaintTimer != null) { |
714 DirtyRectangle = DirtyRectangle.IsEmpty ? rect : Rectangle.Union(DirtyRectangle, rect); | 715 DirtyRectangle = DirtyRectangle.IsEmpty ? rect : Rectangle.Union(DirtyRectangle, rect); |
715 if (!SuspendDrawing && !PaintScheduled) { | 716 if (!SuspendDrawing && !PaintScheduled) { |
716 PaintScheduled = true; | 717 PaintScheduled = true; |
717 PaintTimer.Change(PaintDelay, Timeout.Infinite); | 718 PaintTimer.Change(PaintDelay, Timeout.Infinite); |
718 } | 719 } |
719 } else { | 720 } else { |
720 Refresh(rect); | 721 drawDirect = true; |
721 } | 722 } |
722 } | 723 } |
724 if (drawDirect) Refresh(rect); | |
723 } | 725 } |
724 private void PaintTimerCallback(Object state) { | 726 private void PaintTimerCallback(Object state) { |
725 try { | 727 try { |
726 lock (RenderLock) { | 728 Rectangle rect; |
729 lock (StatusLock) { | |
727 PaintScheduled = false; | 730 PaintScheduled = false; |
728 Refresh(DirtyRectangle); | 731 rect = DirtyRectangle; |
729 DirtyRectangle = Rectangle.Empty; | 732 DirtyRectangle = Rectangle.Empty; |
730 } | 733 } |
734 Refresh(rect); | |
731 } catch (Exception ex) { | 735 } catch (Exception ex) { |
732 Debug.WriteLine(ex); | 736 Debug.WriteLine(ex); |
733 Console.Error.WriteLine(ex); | 737 Console.Error.WriteLine(ex); |
734 } | 738 } |
735 } | 739 } |
774 } | 778 } |
775 protected override Boolean CaptureKeyboard(bool capture) { | 779 protected override Boolean CaptureKeyboard(bool capture) { |
776 return true; | 780 return true; |
777 } | 781 } |
778 public virtual void Dispose() { | 782 public virtual void Dispose() { |
779 lock (RenderLock) { | 783 lock (StatusLock) { |
780 if (PaintTimer != null) PaintTimer.Dispose(); | 784 if (PaintTimer != null) PaintTimer.Dispose(); |
781 PaintTimer = null; | 785 PaintTimer = null; |
782 } | 786 } |
783 Orphaned(); | 787 Orphaned(); |
784 lock (RenderLock) { | 788 lock (RenderLock) { |