Fixing fullrefresh

This commit is contained in:
Mirek Fidler 2024-10-17 10:10:36 +02:00
parent 04c14131cc
commit 7fccf6c5a0
6 changed files with 27 additions and 30 deletions

View file

@ -209,6 +209,7 @@ void Ctrl::StateH(int reason)
if((*statehook()[i])(this, reason))
return;
StateDeep(reason);
FullRefreshCleanup();
}
bool Ctrl::Accept()

View file

@ -565,7 +565,9 @@ private:
bool layout_id_literal:1; // info_ptr points to layout char * literal, no heap involved
bool multi_frame:1; // there is more than single frame, they are stored in heap
bool top:1;
bool megarect:1; // support for large virtual screen area - SetRect > 16000
bool megarect:1; // support for large virtual screen area - SetRect.TopLeft > 16000
static bool was_fullrefresh; // indicates that some widgets might have fullrefresh true
static Ptr<Ctrl> eventCtrl;
static Ptr<Ctrl> mouseCtrl;
@ -647,6 +649,8 @@ private:
Image DispatchMouseEvent(int e, Point p, int zd = 0);
void LogMouseEvent(const char *f, const Ctrl *ctrl, int event, Point p, int zdelta, dword keyflags);
static bool ProcessEvent(bool *quit = NULL);
struct CallBox;
static void PerformCall(CallBox *cbox);
@ -688,6 +692,7 @@ private:
void PaintCaret(SystemDraw& w);
void CtrlPaint(SystemDraw& w, const Rect& clip);
void RemoveFullRefresh();
static void FullRefreshCleanup();
bool PaintOpaqueAreas(SystemDraw& w, const Rect& r, const Rect& clip, bool nochild = false);
void GatherTransparentAreas(Vector<Rect>& area, SystemDraw& w, Rect r, const Rect& clip);
void ExcludeDHCtrls(SystemDraw& w, const Rect& r, const Rect& clip);
@ -1343,7 +1348,6 @@ public:
void SetAlpha(byte alpha);
static bool IsWaitingEvent();
static bool ProcessEvent(bool *quit = NULL);
static bool ProcessEvents(bool *quit = NULL);
static int GetEventLevel() { return EventLevel; }

View file

@ -8,6 +8,8 @@ namespace Upp {
bool Ctrl::globalbackpaint;
bool Ctrl::globalbackbuffer;
bool Ctrl::was_fullrefresh;
static void sCheckGuiLock()
{
ASSERT_(ThreadHasGuiLock(), "Using GUI in non-main thread without GuiLock");
@ -17,7 +19,7 @@ void Ctrl::RefreshFrame(const Rect& r) {
LTIMING("RefreshFrame");
sCheckGuiLock();
GuiLock __; // Beware: Even if we have ThreadHasGuiLock ASSERT, we still can be the main thread!
DLOG("RefreshFrame " << Name() << ' ' << r);
DLOG("RefreshFrame " << Name() << ' ' << r << " version 1");
if(!IsOpen() || !IsVisible() || r.IsEmpty()) return;
DLOG("RefreshRect A");
if(GuiPlatformRefreshFrameSpecial(r))
@ -50,7 +52,6 @@ void Ctrl::Refresh(const Rect& area) {
Refresh0(area);
}
#if 0 // CHANGE TO 1 TO TEST THE FIX
void Ctrl::Refresh() {
sCheckGuiLock();
GuiLock __; // Beware: Even if we have ThreadHasGuiLock ASSERT, we still can be the main thread!
@ -60,20 +61,9 @@ void Ctrl::Refresh() {
if(r.IsEmpty())
return;
if(!GuiPlatformSetFullRefreshSpecial())
fullrefresh = true; // Needs to be set ahead because of possible MT ICall that can cause repaint during Refresh0
was_fullrefresh = fullrefresh = true; // Needs to be set ahead because of possible MT ICall that can cause repaint during Refresh0
Refresh0(r);
}
#else
void Ctrl::Refresh() {
sCheckGuiLock();
GuiLock __; // Beware: Even if we have ThreadHasGuiLock ASSERT, we still can be the main thread!
DLOG("Refresh " << Name() << " full:" << fullrefresh << " rect: " << GetRect());
if(fullrefresh || !IsVisible() || !IsOpen()) return;
if(!GuiPlatformSetFullRefreshSpecial())
fullrefresh = true; // Needs to be set ahead because of possible MT ICall that can cause repaint during Refresh0
Refresh0(Rect(GetSize()).Inflated(OverPaint()));
}
#endif
void Ctrl::Refresh(int x, int y, int cx, int cy) {
Refresh(RectC(x, y, cx, cy));
@ -579,6 +569,17 @@ void Ctrl::RemoveFullRefresh()
q->RemoveFullRefresh();
}
void Ctrl::FullRefreshCleanup()
{ // remove any potentially stuck fullrefresh
GuiLock __;
if(was_fullrefresh) {
DTIMESTOP("FullRefreshCleanup");
for(Ctrl *q : GetTopCtrls())
q->RemoveFullRefresh();
was_fullrefresh = false;
}
}
Ctrl *Ctrl::GetTopRect(Rect& r, bool inframe, bool clip)
{
GuiLock __;

View file

@ -155,7 +155,7 @@ void Ctrl::SyncLayout(int force)
if(destroying)
return;
LLOG("SyncLayout " << Name() << " size: " << GetSize());
// fullrefresh = false; // UNCOMMENT TO TEST THE FIX
fullrefresh = false;
bool refresh = false;
Rect oview = GetView();
Rect view = GetRect().Size();

View file

@ -154,6 +154,7 @@ void Ctrl::TimerProc(dword time)
}
LLOG("----");
sTimerLock.Leave();
FullRefreshCleanup();
}
void Ctrl::InitTimer()

View file

@ -2361,24 +2361,14 @@ system. Ctrl must be open.&]
event in input queue.&]
[s3;%- &]
[s4;%- &]
[s5;:Ctrl`:`:ProcessEvent`(bool`*`):%- [@(0.0.255) static] [@(0.0.255) bool]_[* ProcessEven
t]([@(0.0.255) bool]_`*[*@3 quit]_`=_NULL)&]
[s2;b17;a17; Processes single event from input queue. When there
is no pending event, returns immediately. (Processing event involves
usually involves dispatching it via virtual methods to proper
Ctrls).&]
[s7;i1120;a17; [%-*C@3 quit]-|Assigned true when WM`_QUIT message is
intercepted (Win32 specific).&]
[s7;i1120;a17; [*/ Return value]-|True indicates that event was processed,
false that queue was empty.&]
[s3;%- &]
[s4;%- &]
[s5;:Ctrl`:`:ProcessEvents`(bool`*`):%- [@(0.0.255) static] [@(0.0.255) bool]_[* ProcessEve
nts]([@(0.0.255) bool]_`*[*@3 quit]_`=_NULL)&]
[s2;b17;a17; Processes all events from input queue. When there is
no pending event, returns immediately. (Processing event involves
usually involves dispatching it via virtual methods to proper
Ctrls).&]
Ctrls). Additionally, after all input events are processed, all
pending timer events are processed and all Refreshed areas of
windows are repainted.&]
[s7;i1120;a17; [%-*C@3 quit]-|Assigned true when WM`_QUIT message is
intercepted (Win32 specific).&]
[s7;i1120;a17; [*/ Return value]-|True indicates that one or more events