From 5d4048e533173963d27ebcccf915f8c543bb04ac Mon Sep 17 00:00:00 2001
From: James Cameron <quozl@laptop.org>
Date: Mon, 26 Jul 2010 15:26:57 +1000
Subject: [PATCH] avoid race that leads to waveform capture image corruption #2119
On certain hardware the palette popdown for the capture button palette
occurs sufficiently late that the resulting expose event is not
handled by the time the screenshot is taken.
This patch forces the palette popdown and flushes it to the display,
triggering an expose event which returns by the time a 10ms delay has
been scheduled.
Also reviewed all uses of timeout_add to ensure that the called
function explicitly returns False in order to avoid being called
again.
---
journal.py | 1 +
sensor_toolbar.py | 1 +
sound_toolbar.py | 33 ++++++++++++++++++++++-----------
3 files changed, 24 insertions(+), 11 deletions(-)
diff --git a/journal.py b/journal.py
index 684f0a2..cd7cf0d 100644
a
|
b
|
class JournalInteraction(): |
203 | 203 | finally: |
204 | 204 | log.debug("$$$ in outermost finally!!") |
205 | 205 | self._stopped = True |
| 206 | return False |
206 | 207 | |
207 | 208 | def get_number_of_cols(self): |
208 | 209 | """Returns the maximum number of columns amongst all the data""" |
diff --git a/sensor_toolbar.py b/sensor_toolbar.py
index 9843bec..dd92c5c 100644
a
|
b
|
class SensorToolbar(gtk.Toolbar): |
231 | 231 | self.activity.audiograb.set_sensor_type(self.mode) |
232 | 232 | self._update_string_for_textbox() |
233 | 233 | self.activity.wave.set_trigger(self.activity.wave.TRIGGER_NONE) |
| 234 | return False |
234 | 235 | |
235 | 236 | def _update_string_for_textbox(self, value=None): |
236 | 237 | """ Update the status field at the bottom of the canvas. """ |
diff --git a/sound_toolbar.py b/sound_toolbar.py
index 4397e7b..01a910b 100644
a
|
b
|
class SoundToolbar(gtk.Toolbar): |
148 | 148 | self._record = ToolButton('media-record') |
149 | 149 | self.insert(self._record, -1) |
150 | 150 | self._record.set_tooltip(_('Capture sample now')) |
151 | | |
| 151 | |
152 | 152 | self._record.connect('clicked', self.record_control) |
153 | 153 | |
154 | 154 | if self.activity.has_toolbarbox: |
… |
… |
class SoundToolbar(gtk.Toolbar): |
207 | 207 | |
208 | 208 | return |
209 | 209 | |
210 | | def record_control(self, data=None): |
| 210 | def _set_icon_ready(self): |
| 211 | self._record.set_icon('media-record') |
| 212 | self._record.show() |
| 213 | return False |
| 214 | |
| 215 | def _set_icon_stop(self): |
| 216 | self._record.set_icon('record-stop') |
| 217 | self._record.show() |
| 218 | return False |
| 219 | |
| 220 | def record_control_delayed(self, data=None): |
211 | 221 | """Depending upon the selected interval, either starts/stops |
212 | 222 | a logging session, or just logs the current buffer""" |
213 | 223 | if not self.activity.LOGGING_IN_SESSION: |
… |
… |
class SoundToolbar(gtk.Toolbar): |
219 | 229 | self.logginginterval_status) |
220 | 230 | self.activity.audiograb.set_logging_params(True, interval, True) |
221 | 231 | self.activity.LOGGING_IN_SESSION = True |
222 | | self._record.set_icon('record-stop') |
223 | | self._record.show() |
| 232 | self._set_icon_stop() |
224 | 233 | if interval == 0: |
225 | 234 | # Flash the stop button when grabbing just one image |
226 | | self._record.set_icon('record-stop') |
227 | | self._record.show() |
228 | | gobject.timeout_add(250, self._record.set_icon, 'media-record') |
229 | | self._record.show() |
| 235 | gobject.timeout_add(250, self._set_icon_ready) |
230 | 236 | self.record_state = False |
231 | 237 | self.activity.LOGGING_IN_SESSION = False |
232 | 238 | self.logging_status = False |
233 | 239 | else: |
234 | 240 | self.activity.audiograb.set_logging_params(False) |
235 | 241 | self.activity.LOGGING_IN_SESSION = False |
236 | | self._record.set_icon('media-record') |
237 | | self._record.show() |
| 242 | self._set_icon_ready() |
238 | 243 | self._set_record_button_tooltip() |
239 | | return |
| 244 | return False |
| 245 | |
| 246 | def record_control(self, data=None): |
| 247 | self._record.palette.popdown() |
| 248 | gtk.gdk.flush() |
| 249 | gobject.timeout_add(10, self.record_control_delayed, data) |
240 | 250 | |
241 | 251 | def interval_convert(self): |
242 | 252 | """Converts picture/time interval to an integer that denotes the number |
… |
… |
class SoundToolbar(gtk.Toolbar): |
418 | 428 | self.activity.wave.set_mag_params(self.gain, self.y_mag) |
419 | 429 | self._update_string_for_textbox() |
420 | 430 | self.update_trigger_control() |
| 431 | return False |
421 | 432 | |
422 | 433 | def _update_string_for_textbox(self): |
423 | 434 | """ Update the text at the bottom of the canvas """ |