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) {