diff --git a/frontend/apps/reader/modules/readerdictionary.lua b/frontend/apps/reader/modules/readerdictionary.lua index c588407cd..1342917bc 100644 --- a/frontend/apps/reader/modules/readerdictionary.lua +++ b/frontend/apps/reader/modules/readerdictionary.lua @@ -646,17 +646,18 @@ function ReaderDictionary:cleanSelection(text) return text end -function ReaderDictionary:showLookupInfo(word) +function ReaderDictionary:showLookupInfo(word, show_delay) local text = T(self.lookup_msg, word) - self.lookup_progress_msg = InfoMessage:new{text=text, no_refresh_on_close=true} + self.lookup_progress_msg = InfoMessage:new{ + text = text, + show_delay = show_delay, + } UIManager:show(self.lookup_progress_msg) - -- UIManager:forceRePaint() end function ReaderDictionary:dismissLookupInfo() if self.lookup_progress_msg then UIManager:close(self.lookup_progress_msg) - -- UIManager:forceRePaint() end self.lookup_progress_msg = nil end @@ -819,12 +820,9 @@ function ReaderDictionary:stardictLookup(word, dict_names, fuzzy_search, box, li return end - if fuzzy_search then - UIManager:scheduleIn(0.5, self.showLookupInfo, self, word) - end + self:showLookupInfo(word, 0.5) local results = self:startSdcv(word, dict_names, fuzzy_search) - UIManager:unschedule(self.showLookupInfo) self:showDict(word, tidyMarkup(results), box, link) end @@ -857,17 +855,22 @@ function ReaderDictionary:showDict(word, results, box, link) self:onHtmlDictionaryLinkTapped(dictionary, html_link) end, } + table.insert(self.dict_window_list, self.dict_window) + UIManager:show(self.dict_window) if self.lookup_progress_msg then - -- If we have a lookup InfoMessage, and it's taller than us, make it refresh on close - if self.lookup_progress_msg[1][1] and self.lookup_progress_msg[1][1].dimen and self.lookup_progress_msg[1][1].dimen.h >= self.dict_window.height then - self.lookup_progress_msg.no_refresh_on_close = nil + -- If we have a lookup InfoMessage that ended up being displayed, make + -- it *not* refresh on close if it is hidden by our DictQuickLookup + -- to avoid refreshes competition and possible glitches + local msg_dimen = self.lookup_progress_msg:getVisibleArea() + if msg_dimen then -- not invisible + local dict_dimen = self.dict_window:getInitialVisibleArea() + if dict_dimen and dict_dimen:contains(msg_dimen) then + self.lookup_progress_msg.no_refresh_on_close = true + end end end - table.insert(self.dict_window_list, self.dict_window) - UIManager:show(self.dict_window) end - -- Delay the dismiss, so we can flip the no_refresh_on_close flag if the InfoMessage is taller than the DictQuickLookup... self:dismissLookupInfo() if results and results[1] then UIManager:show(self.dict_window) diff --git a/frontend/ui/widget/container/movablecontainer.lua b/frontend/ui/widget/container/movablecontainer.lua index 1d6f95e85..12f0c63fd 100644 --- a/frontend/ui/widget/container/movablecontainer.lua +++ b/frontend/ui/widget/container/movablecontainer.lua @@ -189,6 +189,9 @@ end function MovableContainer:onMovableSwipe(_, ges) logger.dbg("MovableContainer:onMovableSwipe", ges) + if not self.dimen then -- not yet painted + return false + end if not ges.pos:intersectWith(self.dimen) then -- with swipe, ges.pos is swipe's start position, which should -- be on us to consider it @@ -216,6 +219,9 @@ function MovableContainer:onMovableTouch(_, ges) -- First "pan" event may already be outsise us, we need to -- remember any "touch" event on us prior to "pan" logger.dbg("MovableContainer:onMovableTouch", ges) + if not self.dimen then -- not yet painted + return false + end if ges.pos:intersectWith(self.dimen) then self._touch_pre_pan_was_inside = true self._move_relative_x = ges.pos.x @@ -228,6 +234,9 @@ end function MovableContainer:onMovableHold(_, ges) logger.dbg("MovableContainer:onMovableHold", ges) + if not self.dimen then -- not yet painted + return false + end if ges.pos:intersectWith(self.dimen) then self._moving = true -- start of pan self._move_relative_x = ges.pos.x @@ -239,6 +248,9 @@ end function MovableContainer:onMovableHoldPan(_, ges) logger.dbg("MovableContainer:onMovableHoldPan", ges) + if not self.dimen then -- not yet painted + return false + end -- we may sometimes not see the "hold" event if ges.pos:intersectWith(self.dimen) or self._moving or self._touch_pre_pan_was_inside then self._touch_pre_pan_was_inside = false -- reset it @@ -250,6 +262,9 @@ end function MovableContainer:onMovableHoldRelease(_, ges) logger.dbg("MovableContainer:onMovableHoldRelease", ges) + if not self.dimen then -- not yet painted + return false + end if self._moving or self._touch_pre_pan_was_inside then self._moving = false if not self._move_relative_x or not self._move_relative_y then @@ -273,6 +288,9 @@ end function MovableContainer:onMovablePan(_, ges) logger.dbg("MovableContainer:onMovablePan", ges) + if not self.dimen then -- not yet painted + return false + end if ges.pos:intersectWith(self.dimen) or self._moving or self._touch_pre_pan_was_inside then self._touch_pre_pan_was_inside = false -- reset it self._moving = true @@ -285,6 +303,9 @@ end function MovableContainer:onMovablePanRelease(_, ges) logger.dbg("MovableContainer:onMovablePanRelease", ges) + if not self.dimen then -- not yet painted + return false + end if self._moving then self:_moveBy(self._move_relative_x, self._move_relative_y) self._moving = false diff --git a/frontend/ui/widget/dictquicklookup.lua b/frontend/ui/widget/dictquicklookup.lua index 259f507e5..3423ecc05 100644 --- a/frontend/ui/widget/dictquicklookup.lua +++ b/frontend/ui/widget/dictquicklookup.lua @@ -607,6 +607,26 @@ function DictQuickLookup:update() end) end +function DictQuickLookup:getInitialVisibleArea() + -- Some positionning happens only at paintTo() time, but we want + -- to know this before. So, do a bit like WidgetContainer does + -- (without any MovableContainer offset) + local dict_size = self.dict_frame:getSize() + local area = Geom:new{ + w = dict_size.w, + h = dict_size.h, + x = self.region.x + math.floor((self.region.w - dict_size.w)/2) + } + if self.align == "top" then + area.y = self.region.y + elseif self.align == "bottom" then + area.y = self.region.y + self.region.h - dict_size.h + elseif self.align == "center" then + area.x = self.region.y + math.floor((self.region.h - dict_size.h)/2) + end + return area +end + function DictQuickLookup:onCloseWidget() -- Free our widget and subwidgets' resources (especially -- definitions' TextBoxWidget bb, HtmlBoxWidget bb and MuPDF instance, diff --git a/frontend/ui/widget/infomessage.lua b/frontend/ui/widget/infomessage.lua index f53b8e771..0f9a3dfcb 100644 --- a/frontend/ui/widget/infomessage.lua +++ b/frontend/ui/widget/infomessage.lua @@ -67,6 +67,8 @@ local InfoMessage = InputContainer:new{ auto_para_direction = nil, -- Don't call setDirty when closing the widget no_refresh_on_close = nil, + -- Only have it painted after this delay (dismissing still works before it's shown) + show_delay = nil, } function InfoMessage:init() @@ -184,9 +186,18 @@ function InfoMessage:init() end end end + + if self.show_delay then + -- Don't have UIManager setDirty us yet + self.invisible = true + end end function InfoMessage:onCloseWidget() + if self.invisible then + -- Still invisible, no setDirty needed + return true + end if self.no_refresh_on_close then return true end @@ -198,28 +209,58 @@ function InfoMessage:onCloseWidget() end function InfoMessage:onShow() - -- triggered by the UIManager after we got successfully shown (not yet painted) + -- triggered by the UIManager after we got successfully show()'n (not yet painted) + if self.show_delay and self.invisible then + -- Let us be shown after this delay + self._delayed_show_action = function() + self._delayed_show_action = nil + self.invisible = false + self:onShow() + end + UIManager:scheduleIn(self.show_delay, self._delayed_show_action) + return true + end + -- set our region to be dirty, so UImanager will call our paintTo() UIManager:setDirty(self, function() return "ui", self[1][1].dimen end) + -- schedule us to close ourself if timeout provided if self.timeout then UIManager:scheduleIn(self.timeout, function() UIManager:close(self) end) end return true end -function InfoMessage:onAnyKeyPressed() - -- triggered by our defined key events +function InfoMessage:getVisibleArea() + if not self.invisible then + return self[1][1].dimen + end +end + +function InfoMessage:paintTo(bb, x, y) + if self.invisible then + return + end + InputContainer.paintTo(self, bb, x, y) +end + +function InfoMessage:dismiss() + if self._delayed_show_action then + UIManager:unschedule(self._delayed_show_action) + end self.dismiss_callback() UIManager:close(self) +end + +function InfoMessage:onAnyKeyPressed() + self:dismiss() if self.readonly ~= true then return true end end function InfoMessage:onTapClose() - self.dismiss_callback() - UIManager:close(self) + self:dismiss() if self.readonly ~= true then return true end