Skip to content

ConfigDialog: fix ButtonProgressWidget and some refreshes#4793

Merged
poire-z merged 1 commit into
koreader:masterfrom
poire-z:config_buttonprogress_refresh
Mar 14, 2019
Merged

ConfigDialog: fix ButtonProgressWidget and some refreshes#4793
poire-z merged 1 commit into
koreader:masterfrom
poire-z:config_buttonprogress_refresh

Conversation

@poire-z

@poire-z poire-z commented Mar 14, 2019

Copy link
Copy Markdown
Contributor

This internal ButtonProgressWidget widget was behaving differently from all others (OptionTextItem, OptionIconItem and ToggleSwitch) by duplicating some code from ConfigDialog:onConfigChoose() instead of calling it directly. So, similar to:

--[[
if self.values then
self.values = self.values or {}
self.config:onConfigChoice(self.name, self.values[self.position])
end
if self.event then
self.args = self.args or {}
self.config:onConfigEvent(self.event, self.args[self.position])
end
if self.events then
self.config:onConfigEvents(self.events, self.position)
end
--]]
self.config:onConfigChoose(self.values, self.name,
self.event, self.args, self.events, self.position)
UIManager:setDirty(self.config, function()
return "ui", self.dimen
end)

While making it similar to others, I noticed that onConfigChoose() did a full repaint, which was necessary for some settings to be applied (ie: Contrast) - or may be not, see below, but I don't know what did that then...
On CreDocument, this full repaint may cause some double drawing on config changes (ie: Margins, since #4691, drawing once after margin changes,and then re-positionning to previous xpointer).
So, make the need for full repaint a condition on KoptOptions.

These changes seem to make PDF and CRE settings behave all correctly. I'll still have to check on my Kobo.

But I'm still puzzled, mostly about how it works/worked with PDF.
Previously, we had a call in that ButtonProgressWidget: UIManager:setDirty("all"). It looks to me this is actually a no-op from UIManager point of view (where there is no mode provided like "full" or "ui") ! Or may be not in some situations?
So I don't know why removing it, or replacing it with a more localized UIManager:setDirty(self.config, function() return "ui", widget.diment) made contrast no more applied...

I'm pretty confident these change are fine for CreDocument, a bit less for PDF.
Changing contrast leads to the following log:

adjusted ges: tap
setDirty via a func from widget table: 0x4085d3f8
setDirty via a func from widget table: 0x4085d3f8
painting widget: table: 0x40dab098
_refresh: Enqueued fast update for region 163 514 424 32
update_mode: Update refresh mode fast to ui
_refresh: Enqueued ui update for region 163 514 424 32
setDirty via a func from widget table: 0x4085d3f8
setDirty via a func from widget table: 0x4085d3f8
_refresh: Enqueued partial update for region 0 0 600 610
setDirty partial from widget all w/ NO region
painting widget: ReaderUI
loading koptcontext from ./cache/8d22901f6040cb5e7cf1b7ffa9b3a684
painting widget: table: 0x40dab098
_refresh: Enqueued partial update for region 0 0 600 610
_refresh: Enqueued partial update for region 0 0 600 610

Previously:

adjusted ges: tap
AutoSuspend: onInputEvent
setDirty via a func from widget table: 0x41eb8bc8
painting widget: table: 0x40dd5650
_refresh: Enqueued ui update for region 163 514 424 32
setDirty nil from widget all w/ NO region
painting widget: ReaderUI
loading koptcontext from ./cache/f5078849f8b7e252f3d07136207b5e8b
painting widget: table: 0x40dd5650
no refresh got enqueued. Will do a partial full screen refresh, which might be inefficient
_refresh: Enqueued partial update for region 0 0 600 610

So, 3 instead of 1 "Enqueued partial update for region 0 0 600 610" - dunno if that means 3 EInk screen refreshes...

Pinging @NiLuJe for opinion.

This internal ButtonProgressWidget widget was behaving
differently from all others (OptionTextItem, OptionIconItem
and ToggleSwitch) by duplicating some code from
ConfigDialog:onConfigChoose() instead of calling it directly.

While making it similar to others, I noticed that onConfigChoose()
did a full repaint, which was necessary for some settings to
be applied (ie: Contrast).
On CreDocument, this full repaint may cause some double drawing
on config changes (ie: Margins, drawing once after margin changes,
and then re-positionning to previous xpointer).
So, make the need for full repaint a condition on KoptOptions.
@NiLuJe

NiLuJe commented Mar 14, 2019

Copy link
Copy Markdown
Member

Previously, we had a call in that ButtonProgressWidget: UIManager:setDirty("all"). It looks to me this is actually a no-op from UIManager point of view (where there is no mode provided like "full" or "ui") ! Or may be not in some situations?

UIManager:setDirty("all") essentially flags every top-level window as dirty, essentially forcing a repaint of the full stack (i.e., each toplevel widget's paintTo will be called).

@NiLuJe

NiLuJe commented Mar 14, 2019

Copy link
Copy Markdown
Member

And it's indeed generally overkill, if you want to enforce an eInk refresh without repainting anything, you're better off doing a UIManager:setDirty(nil, ...) instead.

Since the widget is NULL, it'll just enqueue an eInk refresh to your liking ;). The refresh settings should generally be passed as a function in this instance, to make sure it gets a chance to get merged with other queued refreshes, instead of enforcing one right now.

@poire-z

poire-z commented Mar 14, 2019

Copy link
Copy Markdown
Contributor Author

UIManager:setDirty("all") essentially flags every top-level window as dirty

But then:

self:_refresh(refreshtype, refreshregion, refreshdither)

with refreshtype / mode = nil (and no dither), this would return early:
function UIManager:_refresh(mode, region, dither)
if not mode then
-- If we're trying to float a dither hint up from a lower widget after a close, mode might be nil...
-- So use the lowest priority refresh mode (short of fast, because that'd do half-toning).
if dither then
mode = "ui"
else
return
end

so, not doing any refresh?

Or may be this call without mode would just flag the widgets as dirty, exiting there early without any refresh. And a later setDirty (possibly smaller and localized) would see all the previously set dirty widgets, and deal with them at this point? (which could explain the async'ness I see and can't explain :)

@NiLuJe

NiLuJe commented Mar 14, 2019

Copy link
Copy Markdown
Member

@poire-z : Yep, I'd forgotten that extra-quirkiness of not passing a refreshfunc at all in this case, but, yeah, you're right ;).

I tried to clean most of those up, because they're indeed unintuitive and weird and generally not the right thing to do, but I guess I missed those ;).

@NiLuJe

NiLuJe commented Mar 14, 2019

Copy link
Copy Markdown
Member

TL;DR: On paper, your change looks like the perfect way to handle that ;).

(Assuming KOpt really needs to repaint both the ConfigDialog and ReaderUI, but I'm trusting you on that front ;)).

(I'm assuming you're using a 600x610 emulator window, right?)

@poire-z

poire-z commented Mar 14, 2019

Copy link
Copy Markdown
Contributor Author

600x610 emulator window, right

Right (on a small laptop screen, 1366x768).

Assuming KOpt really needs to repaint both the ConfigDialog and the View

That surprised me, but I see that with some settings (contrast, line spacing), not with others (margins, font size).

your change looks like the perfect way to handle that

No worry with the logs and the 3 _refresh: Enqueued partial update for region 0 0 600 610 ?

_refresh: Enqueued ui update for region 163 514 424 32   must be the progress button, small h
setDirty via a func from widget table: 0x4085d3f8
setDirty via a func from widget table: 0x4085d3f8
_refresh: Enqueued partial update for region 0 0 600 610   this one might looks wrong, too early, or too big (if it's the configdialog)
setDirty partial from widget all w/ NO region  that's the one fixed to have kopt do its stuff
painting widget: ReaderUI     forcing kopt to repaint
loading koptcontext from ./cache/8d22901f6040cb5e7cf1b7ffa9b3a684  it repaings
painting widget: table: 0x40dab098   
_refresh: Enqueued partial update for region 0 0 600 610
_refresh: Enqueued partial update for region 0 0 600 610  double refresh ?

@poire-z

poire-z commented Mar 14, 2019

Copy link
Copy Markdown
Contributor Author

_refresh: Enqueued partial update for region 0 0 600 610 this one might looks wrong, too early, or too big (if it's the configdialog)
Well, no, it shouldn't be the configdialog size, as I ask it "all" "partial" to repaing kopt. So it's right I guess.
(It's for credocument that it will do only the bottom config size).

or not ... i'm confused by the order of things or how to read them:

Is that a single action:

setDirty partial from widget all w/ NO region  that's the one fixed to have kopt do its stuff
painting widget: ReaderUI     forcing kopt to repaint
loading koptcontext from ./cache/8d22901f6040cb5e7cf1b7ffa9b3a684  it repaings
painting widget: table: 0x40dab098   
_refresh: Enqueued partial update for region 0 0 600 610

or is it that:

_refresh: Enqueued partial update for region 0 0 600 610   this one might looks wrong, too early, or too big (if it's the configdialog)
setDirty partial from widget all w/ NO region  that's the one fixed to have kopt do its stuff
painting widget: ReaderUI     forcing kopt to repaint
loading koptcontext from ./cache/8d22901f6040cb5e7cf1b7ffa9b3a684  it repaings
painting widget: table: 0x40dab098   

@NiLuJe

NiLuJe commented Mar 14, 2019

Copy link
Copy Markdown
Member

Yeah, not quite sure where that first full-screen partial is from... onTapSelect & onConfigChoose don't do a partial via func... Only onCloseWidget does :?

The double refresh at the end looks normal for a "all", "partial" with two top-level widgets open, though ;).

@poire-z

poire-z commented Mar 14, 2019

Copy link
Copy Markdown
Contributor Author

Oh, just discovered verbose mode (which does not work as an option to kodev run?).
Anyway, set via Developpers option, it shows the actual screen refreshs !
These shouldn't be hidden into verbose mode only :) May be condensed into a one-liner in simple debug mode?

So, it shows somethings that actually looks good to me ! Right ?

03/14/19-17:20:49 DEBUG adjusted ges: tap
03/14/19-17:20:49 WARN  ConfigDialog:onConfigChoose:update
03/14/19-17:20:49 DEBUG setDirty via a func from widget table: 0x40c9df90
03/14/19-17:20:49 DEBUG setDirty via a func from widget table: 0x40c9df90
03/14/19-17:20:49 DEBUG painting widget: table: 0x41718850
03/14/19-17:20:49 DEBUG _refresh: Enqueued fast update for region 163 514 424 32
03/14/19-17:20:49 DEBUG update_mode: Update refresh mode fast to ui
03/14/19-17:20:49 DEBUG _refresh: Enqueued ui update for region 163 514 424 32
# 03/14/19-17:20:49  triggering refresh {
    ["dither"] = false,
    ["mode"] = "ui",
    ["region"] = {
        ["y"] = 514,
        ["x"] = 163,
        ["h"] = 32,
        ["w"] = 424
    }
}
03/14/19-17:20:49 WARN  ConfigDialog:onConfigChoose:update tickAfterNext
03/14/19-17:20:49 WARN  self:update
03/14/19-17:20:49 DEBUG setDirty via a func from widget table: 0x40c9df90
03/14/19-17:20:49 DEBUG setDirty via a func from widget table: 0x40c9df90
03/14/19-17:20:49 WARN  self:update done
03/14/19-17:20:49 WARN  self:update done setDirty(all, partial)
03/14/19-17:20:49 DEBUG _refresh: Enqueued partial update for region 0 0 600 610
03/14/19-17:20:49 DEBUG setDirty partial from widget all w/ NO region
03/14/19-17:20:49 WARN  self:update done setDirty(all, partial) done
03/14/19-17:20:49 WARN  ConfigDialog:onConfigChoose:update tickAfterNext done
03/14/19-17:20:49 DEBUG painting widget: ReaderUI
# 03/14/19-17:20:49  readerview painting {
    ["y"] = 0,
    ["x"] = 0,
    ["h"] = 610,
    ["w"] = 600
} to 0 0
03/14/19-17:20:49 DEBUG loading koptcontext from ./cache/f5078849f8b7e252f3d07136207b5e8b
03/14/19-17:20:49 DEBUG painting widget: table: 0x41718850
03/14/19-17:20:49 DEBUG _refresh: Enqueued partial update for region 0 0 600 610
03/14/19-17:20:49 DEBUG _refresh: Enqueued partial update for region 0 0 600 610
# 03/14/19-17:20:49  triggering refresh {
    ["dither"] = false,
    ["mode"] = "partial",
    ["region"] = {
        ["y"] = 0,
        ["x"] = 0,
        ["h"] = 610,
        ["w"] = 600
    }
}

The double refresh at the end looks normal for a "all", "partial" with two top-level widgets open, though ;).

So, if I get that right:

  1. the (all, partial) just sets all widgets as dirty, no real refresh or repaint
  2. UIManager makes each widget flagged as dirty paints itself (UIManager:_repaint())
  3. after a widget paints itself, there's yet another call to _refresh() where the widget says what area it has painted needs to be refreshed (so, that would be the multiple 600 610 lines) - but it looks it's just when they are refresh_funcs
  4. UIManager:_repaint() does at the end for _, refresh in ipairs(self._refresh_stack) do Screen[refresh_methods...

But I don't really get how/why the:

03/14/19-17:20:49 DEBUG painting widget: table: 0x41718850      done with all painting

03/14/19-17:20:49 DEBUG _refresh: Enqueued partial update for region 0 0 600 610
03/14/19-17:20:49 DEBUG _refresh: Enqueued partial update for region 0 0 600 610
  /\  why these 2 _refresh after all the paintings as I don't see refresh_funcs

  \/ and why/where they get condensed into a single Screen refresh:
# 03/14/19-17:20:49  triggering refresh {

@NiLuJe

NiLuJe commented Mar 14, 2019

Copy link
Copy Markdown
Member

(They're hidden behind verbose mode because of the table pretty-printing feature, IIRC).

@NiLuJe

NiLuJe commented Mar 14, 2019

Copy link
Copy Markdown
Member

And the answer to all your questions is the _refresh_stack in UIManager and how _refresh() manages it ;).

@NiLuJe

NiLuJe commented Mar 14, 2019

Copy link
Copy Markdown
Member

Oh, and I remember why I was confused by that initial partial: it's because the logs are inverted (for... Lua reasons) between setDirty and _refresh when refreshtype is not a function ;).

i.e.,

03/14/19-17:20:49 DEBUG _refresh: Enqueued partial update for region 0 0 600 610
03/14/19-17:20:49 DEBUG setDirty partial from widget all w/ NO region

That _refresh is the setDirty("all", "partial").

The other final two are the ones enqueued by ReaderUI & ConfigDialog's dirty flags following that ;).

@poire-z

poire-z commented Mar 14, 2019

Copy link
Copy Markdown
Contributor Author

OK, that now makes more sense :) Thanks for the time and explanation.
Well, so it looks good. I'll check later on my device, and if no issue, I guess it will be good to go.

@poire-z

poire-z commented Mar 14, 2019

Copy link
Copy Markdown
Contributor Author

I guess we not need to worry about the numerous things like this I see with verbose mode (with the changes from this PR reverted):

03/14/19-18:39:00 DEBUG setDirty full from widget ReaderUI w/ NO region
# 03/14/19-18:39:00  INFO: invalid widget for setDirty() stack traceback:
  frontend/ui/uimanager.lua:560: in function 'post_guard'
  frontend/dbg.lua:45: in function 'setDirty'
  frontend/apps/reader/modules/readerview.lua:709: in function 'onSetScreenMode'
  frontend/apps/reader/modules/readerview.lua:754: in function 'handleEvent'
  frontend/ui/widget/container/widgetcontainer.lua:88: in function 'propagateEvent'
  frontend/ui/widget/container/widgetcontainer.lua:106: in function 'handleEvent'
  frontend/apps/reader/readerui.lua:382: in function 'init'
  frontend/ui/widget/widget.lua:48: in function 'new'
  frontend/apps/reader/readerui.lua:515: in function 'doShowReader'
  frontend/apps/reader/readerui.lua:475: in function <frontend/apps/reader/readerui.lua:474>
03/14/19-18:39:00 DEBUG _refresh: Enqueued full update for region 0 0 600 610
03/14/19-18:39:00 DEBUG setDirty partial from widget ReaderUI w/ NO region
# 03/14/19-18:39:00  INFO: invalid widget for setDirty() stack traceback:
  frontend/ui/uimanager.lua:560: in function 'post_guard'
  frontend/dbg.lua:45: in function 'setDirty'
  frontend/apps/reader/modules/readerview.lua:603: in function 'recalculate'
  frontend/apps/reader/modules/readerview.lua:723: in function 'handleEvent'
  frontend/ui/widget/container/widgetcontainer.lua:88: in function 'propagateEvent'
  frontend/ui/widget/container/widgetcontainer.lua:106: in function 'handleEvent'
  frontend/apps/reader/modules/readerview.lua:711: in function 'onSetScreenMode'

03/14/19-18:43:48 DEBUG setDirty via a func from widget table: 0x403c6070
# 03/14/19-18:43:48  INFO: invalid widget for setDirty() stack traceback:
  frontend/ui/uimanager.lua:560: in function 'post_guard'
  frontend/dbg.lua:45: in function 'setDirty'
  frontend/ui/widget/buttonprogresswidget.lua:90: in function 'update'
  frontend/ui/widget/buttonprogresswidget.lua:97: in function 'setPosition'
  frontend/ui/widget/configdialog.lua:526: in function 'init'
  frontend/ui/widget/widget.lua:48: in function 'new'
  frontend/ui/widget/configdialog.lua:570: in function 'init'
  frontend/ui/widget/widget.lua:48: in function 'new'
  frontend/ui/widget/configdialog.lua:768: in function 'update'
  frontend/ui/widget/configdialog.lua:799: in function 'onShowConfigPanel'
  frontend/apps/reader/modules/readerconfig.lua:84: in function 'onShowConfigMenu'
  frontend/apps/reader/modules/readerconfig.lua:92: in function 'handler'
  frontend/ui/widget/container/inputcontainer.lua:248: in function 'handleEvent'
  frontend/ui/uimanager.lua:632: in function 'sendEvent'
  frontend/ui/uimanager.lua:46: in function '__default__'
  frontend/ui/uimanager.lua:966: in function 'handleInputEvent'
  frontend/ui/uimanager.lua:1027: in function 'handleInput'
  frontend/ui/uimanager.lua:1071: in function 'run'
  ./reader.lua:216: in main chunk
  [C]: at 0x560d1e6dd0c0
03/14/19-18:43:48 DEBUG setDirty via a func from widget table: 0x403c6070
# 03/14/19-18:43:48  INFO: invalid widget for setDirty() stack traceback:
  frontend/ui/uimanager.lua:560: in function 'post_guard'
  frontend/dbg.lua:45: in function 'setDirty'
  frontend/ui/widget/configdialog.lua:802: in function 'onShowConfigPanel'
  frontend/apps/reader/modules/readerconfig.lua:84: in function 'onShowConfigMenu'
  frontend/apps/reader/modules/readerconfig.lua:92: in function 'handler'
  frontend/ui/widget/container/inputcontainer.lua:248: in function 'handleEvent'
  frontend/ui/uimanager.lua:632: in function 'sendEvent'
  frontend/ui/uimanager.lua:46: in function '__default__'
  frontend/ui/uimanager.lua:966: in function 'handleInputEvent'
  frontend/ui/uimanager.lua:1027: in function 'handleInput'
  frontend/ui/uimanager.lua:1071: in function 'run'
  ./reader.lua:216: in main chunk
  [C]: at 0x560d1e6dd0c0

@NiLuJe

NiLuJe commented Mar 14, 2019 via email

Copy link
Copy Markdown
Member

@NiLuJe

NiLuJe commented Mar 14, 2019 via email

Copy link
Copy Markdown
Member

@poire-z

poire-z commented Mar 14, 2019

Copy link
Copy Markdown
Contributor Author

Looks all good on my device. So, merging.

@poire-z poire-z merged commit c060595 into koreader:master Mar 14, 2019
@poire-z poire-z deleted the config_buttonprogress_refresh branch March 14, 2019 21:23
@Frenzie Frenzie added this to the 2019.04 milestone Mar 15, 2019
mwoz123 pushed a commit to mwoz123/koreader that referenced this pull request Mar 29, 2020
)

This internal ButtonProgressWidget widget was behaving
differently from all others (OptionTextItem, OptionIconItem
and ToggleSwitch) by duplicating some code from
ConfigDialog:onConfigChoose() instead of calling it directly.

While making it similar to others, I noticed that onConfigChoose()
did a full repaint, which was necessary for some settings to
be applied (ie: Contrast).
On CreDocument, this full repaint may cause some double drawing
on config changes (ie: Margins, drawing once after margin changes,
and then re-positionning to previous xpointer).
So, make the need for full repaint a condition on KoptOptions.
@NiLuJe NiLuJe mentioned this pull request Jun 7, 2020
0xstillb pushed a commit to 0xstillb/koreader-thai that referenced this pull request May 9, 2026
)

This internal ButtonProgressWidget widget was behaving
differently from all others (OptionTextItem, OptionIconItem
and ToggleSwitch) by duplicating some code from
ConfigDialog:onConfigChoose() instead of calling it directly.

While making it similar to others, I noticed that onConfigChoose()
did a full repaint, which was necessary for some settings to
be applied (ie: Contrast).
On CreDocument, this full repaint may cause some double drawing
on config changes (ie: Margins, drawing once after margin changes,
and then re-positionning to previous xpointer).
So, make the need for full repaint a condition on KoptOptions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants