commit 3f93c66d2536ae85a0880b98425fedb507ad8503 Author: Damian Johnson atagar@torproject.org Date: Mon Aug 8 08:30:48 2011 -0700
Periodically refreshing display
On some platforms the terminal gets into a screwed up state, displaying scrambled content (I haven't reproduced this on my system, but seen it on an Ubuntu netbook).
Redrawing the display, reguardless of if the content has changed every five seconds so this glitches will correct themselves. Arm had previously done this but I took it out when the display code had stabilized (to cut down on load). However, this doesn't have a noticeable cpu cost so might as well put it back.
This also simplifies some of the redrawing logic, centralizing it in the controller. --- armrc.sample | 5 ++ src/cli/controller.py | 75 +++++++++++++++++++----------------- src/cli/graphing/bandwidthStats.py | 2 +- src/cli/graphing/graphPanel.py | 2 +- src/cli/headerPanel.py | 2 +- src/cli/menu/item.py | 2 +- src/cli/menu/menu.py | 2 +- src/cli/wizard.py | 6 +- 8 files changed, 53 insertions(+), 43 deletions(-)
diff --git a/armrc.sample b/armrc.sample index 1edd024..d547b6c 100644 --- a/armrc.sample +++ b/armrc.sample @@ -57,6 +57,11 @@ features.showFdUsage false # Seconds to wait on user input before refreshing content features.redrawRate 5
+# Rate (seconds) to periodically redraw the screen, disabled if zero. This +# shouldn't be necessary, but can correct issues if the terminal gets into a +# funky state. +features.refreshRate 5 + # Confirms promt to confirm when quiting if true features.confirmQuit true
diff --git a/src/cli/controller.py b/src/cli/controller.py index 1554949..d2c9d73 100644 --- a/src/cli/controller.py +++ b/src/cli/controller.py @@ -37,6 +37,7 @@ CONFIG = {"startup.events": "N3", "features.panels.show.config": True, "features.panels.show.torrc": True, "features.redrawRate": 5, + "features.refreshRate": 5, "features.confirmQuit": True, "features.graph.type": 1, "features.graph.bw.prepopulate": True, @@ -171,6 +172,7 @@ class Controller: self._forceRedraw = False self._isDone = False self._torManager = TorManager(self) + self._lastDrawn = 0 self.setMsg() # initializes our control message
def getScreen(self): @@ -310,39 +312,49 @@ class Controller:
return allPanels
- def requestRedraw(self, immediate = False): + def redraw(self, force = True): """ - Requests that all content is redrawn when the interface is next rendered. + Redraws the displayed panel content.
Arguments: - immediate - redraws now if true, otherwise waits for when next normally - drawn + force - redraws reguardless of if it's needed if true, otherwise ignores + the request when there arne't changes to be displayed """
- if immediate: - displayPanels = self.getDisplayPanels() - - occupiedContent = 0 - for panelImpl in displayPanels: - panelImpl.setTop(occupiedContent) - occupiedContent += panelImpl.getHeight() - - for panelImpl in displayPanels: - panelImpl.redraw(True) - else: - self._forceRedraw = True + force |= self._forceRedraw + self._forceRedraw = False + + currentTime = time.time() + if CONFIG["features.refreshRate"] != 0: + if self._lastDrawn + CONFIG["features.refreshRate"] <= currentTime: + force = True + + displayPanels = self.getDisplayPanels() + + occupiedContent = 0 + for panelImpl in displayPanels: + panelImpl.setTop(occupiedContent) + occupiedContent += panelImpl.getHeight() + + for panelImpl in displayPanels: + panelImpl.redraw(force) + + if force: self._lastDrawn = currentTime
- def isRedrawRequested(self, clearFlag = False): + def requestRedraw(self): + """ + Requests that all content is redrawn when the interface is next rendered. """ - True if a full redraw has been requested, false otherwise.
- Arguments: - clearFlag - request clears the flag if true + self._forceRedraw = True + + def getLastRedrawTime(self): + """ + Provides the time when the content was last redrawn, zero if the content + has never been drawn. """
- returnValue = self._forceRedraw - if clearFlag: self._forceRedraw = False - return returnValue + return self._lastDrawn
def setMsg(self, msg = None, attr = None, redraw = False): """ @@ -612,7 +624,9 @@ def startTorMonitor(startTime):
# initializes interface configs config = conf.getConfig("arm") - config.update(CONFIG) + config.update(CONFIG, { + "features.redrawRate": 1, + "features.refreshRate": 0})
cli.graphing.graphPanel.loadConfig(config) cli.connections.connEntry.loadConfig(config) @@ -710,17 +724,8 @@ def drawTorMonitor(stdscr, startTime): for panelImpl in control.getAllPanels(): panelImpl.setVisible(panelImpl in displayPanels)
- # panel placement - occupiedContent = 0 - for panelImpl in displayPanels: - panelImpl.setTop(occupiedContent) - occupiedContent += panelImpl.getHeight() - - # redraws visible content - forceRedraw = control.isRedrawRequested(True) - for panelImpl in displayPanels: - panelImpl.redraw(forceRedraw) - + # redraws the interface if it's needed + control.redraw(False) stdscr.refresh()
# wait for user keyboard input until timeout, unless an override was set diff --git a/src/cli/graphing/bandwidthStats.py b/src/cli/graphing/bandwidthStats.py index 654443c..9782d9f 100644 --- a/src/cli/graphing/bandwidthStats.py +++ b/src/cli/graphing/bandwidthStats.py @@ -100,7 +100,7 @@ class BandwidthStats(graphPanel.GraphStats): self.isAccounting = isAccountingEnabled
# redraws the whole screen since our height changed - cli.controller.getController().requestRedraw(True) + cli.controller.getController().redraw()
# redraws to reflect changes (this especially noticeable when we have # accounting and shut down since it then gives notice of the shutdown) diff --git a/src/cli/graphing/graphPanel.py b/src/cli/graphing/graphPanel.py index b080871..76221ff 100644 --- a/src/cli/graphing/graphPanel.py +++ b/src/cli/graphing/graphPanel.py @@ -324,7 +324,7 @@ class GraphPanel(panel.Panel): self.setGraphHeight(self.graphHeight - 1) elif uiTools.isSelectionKey(key): break
- control.requestRedraw(True) + control.redraw() finally: control.setMsg() panel.CURSES_LOCK.release() diff --git a/src/cli/headerPanel.py b/src/cli/headerPanel.py index e64a6de..4e78f6c 100644 --- a/src/cli/headerPanel.py +++ b/src/cli/headerPanel.py @@ -427,7 +427,7 @@ class HeaderPanel(panel.Panel, threading.Thread): # We're toggling between being a relay and client, causing the height # of this panel to change. Redraw all content so we don't get # overlapping content. - cli.controller.getController().requestRedraw(True) + cli.controller.getController().redraw() else: # just need to redraw ourselves self.redraw(True) diff --git a/src/cli/menu/item.py b/src/cli/menu/item.py index f46cdbb..1ed3f1f 100644 --- a/src/cli/menu/item.py +++ b/src/cli/menu/item.py @@ -58,7 +58,7 @@ class MenuItem(): if self._callback: control = cli.controller.getController() control.setMsg() - control.requestRedraw(True) + control.redraw() self._callback() return True
diff --git a/src/cli/menu/menu.py b/src/cli/menu/menu.py index 8302551..a93a1e0 100644 --- a/src/cli/menu/menu.py +++ b/src/cli/menu/menu.py @@ -114,7 +114,7 @@ def showMenu(): cursor.handleKey(key)
# redraws the rest of the interface if we're rendering on it again - if not cursor.isDone(): control.requestRedraw(True) + if not cursor.isDone(): control.redraw() finally: control.setMsg() cli.popups.finalize() diff --git a/src/cli/wizard.py b/src/cli/wizard.py index f0c14a8..82b2825 100644 --- a/src/cli/wizard.py +++ b/src/cli/wizard.py @@ -342,7 +342,7 @@ def showWizard(): generatedTorrc = getTorrc(relayType, config, disabledOpt)
torrcLocation = manager.getTorrcPath() - controller.requestRedraw(True) + controller.redraw() confirmationSelection = showConfirmationDialog(generatedTorrc, torrcLocation)
if confirmationSelection == NEXT: @@ -463,7 +463,7 @@ def showWizard(): elif confirmationSelection == CANCEL: break
# redraws screen to clear away the dialog we just showed - cli.controller.getController().requestRedraw(True) + cli.controller.getController().redraw()
def promptRelayType(initialSelection): """ @@ -621,7 +621,7 @@ def promptConfigOptions(relayType, config, disabledOpt): try: options[selection].setValue(newValue.strip()) except ValueError, exc: cli.popups.showMsg(str(exc), 3) - cli.controller.getController().requestRedraw(True) + cli.controller.getController().redraw() elif key == 27: selection, key = -1, curses.KEY_ENTER # esc - cancel finally: cli.popups.finalize()
tor-commits@lists.torproject.org