Skip to content

Commit

Permalink
Fix startup delay
Browse files Browse the repository at this point in the history
- port to version 1.2 of sugargame, which fixes a 600ms startup delay
  between toolbar and canvas rendering,

- wait for first VIDEORESIZE event before initialising graphic element
  sizes.

Tested-by: Rahul Bothra <f2016015@pilani.bits-pilani.ac.in>
Signed-off-by: James Cameron <quozl@laptop.org>
  • Loading branch information
quozl committed Jan 18, 2018
1 parent ae057e7 commit 1c77266
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 96 deletions.
9 changes: 8 additions & 1 deletion Mancala.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ def flush_queue(self):
for event in pygame.event.get(): flushing=True

def run(self):
# g.init and self.manc require that we know the display size first
for event in pygame.event.get():
if event.type==pygame.QUIT:
return
elif event.type == pygame.VIDEORESIZE:
pygame.display.set_mode(event.size, pygame.RESIZABLE)
break
g.init()
if not self.journal: utils.load()
self.manc=manc.Manc()
Expand All @@ -107,7 +114,7 @@ def run(self):

# Pump PyGame messages.
for event in pygame.event.get():
if event.type==pygame.QUIT: # only in standalone version
if event.type==pygame.QUIT:
if not self.journal: utils.save()
going=False
elif event.type == pygame.MOUSEMOTION:
Expand Down
12 changes: 5 additions & 7 deletions activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,18 @@ def __init__(self, handle):
stop_button.show()
self.show_all()


# Create the game instance.
self.game = Mancala.Mancala()

# Build the Pygame canvas.
self._pygamecanvas = \
sugargame.canvas.PygameCanvas(self)
self.game.canvas = self._pygamecanvas = \
sugargame.canvas.PygameCanvas(self,
main=self.game.run,
modules=[pygame.display, pygame.font])

# Note that set_canvas implicitly calls
# read_file when resuming from the Journal.
self.set_canvas(self._pygamecanvas)
self.game.canvas=self._pygamecanvas

# Start the game running.
self._pygamecanvas.run_pygame(self.game.run)

def read_file(self, file_path):
try:
Expand Down
2 changes: 1 addition & 1 deletion sugargame/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '1.1'
__version__ = '1.2'
80 changes: 48 additions & 32 deletions sugargame/canvas.py
Original file line number Diff line number Diff line change
@@ -1,70 +1,86 @@
import os
from gi.repository import Gtk
from gi.repository import GObject
from gi.repository import GLib
from sugar3.activity.activity import PREVIEW_SIZE
import pygame
import event

CANVAS = None

class PygameCanvas(Gtk.EventBox):

"""
mainwindow is the activity intself.
"""
def __init__(self, mainwindow, pointer_hint = True):
class PygameCanvas(Gtk.EventBox):
def __init__(self, activity, pointer_hint=True,
main=None, modules=[pygame]):
GObject.GObject.__init__(self)

global CANVAS
assert CANVAS == None, "Only one PygameCanvas can be created, ever."
CANVAS = self

# Initialize Events translator before widget gets "realized".
self.translator = event.Translator(mainwindow, self)
self.translator = event.Translator(activity, self)

self._mainwindow = mainwindow
self._activity = activity
self._main = main
self._modules = modules

self.set_can_focus(True)

self._socket = Gtk.Socket()
self._socket.connect('realize', self._realize_cb)
self.add(self._socket)

self._initialized = False

self.show_all()

def run_pygame(self, main_fn):
# Run the main loop after a short delay. The reason for the delay is that the
# Sugar activity is not properly created until after its constructor returns.
# If the Pygame main loop is called from the activity constructor, the
# constructor never returns and the activity freezes.
GObject.idle_add(self._run_pygame_cb, main_fn)

def _run_pygame_cb(self, main_fn):
# PygameCanvas.run_pygame can only be called once
if self._initialized:
return
def _realize_cb(self, widget):

# Preinitialize Pygame with the X window ID.
os.environ['SDL_WINDOWID'] = str(self._socket.get_id())
if pygame.display.get_surface() is not None:
pygame.display.quit()
pygame.init()
os.environ['SDL_WINDOWID'] = str(widget.get_id())
for module in self._modules:
module.init()

# Restore the default cursor.
self._socket.props.window.set_cursor(None)
widget.props.window.set_cursor(None)

# Initialize the Pygame window.
# Confine the Pygame surface to the canvas size
r = self.get_allocation()
pygame.display.set_mode((r.width, r.height), pygame.RESIZABLE)
self._screen = pygame.display.set_mode((r.width, r.height),
pygame.RESIZABLE)

# Hook certain Pygame functions with GTK equivalents.
self.translator.hook_pygame()

# Run the Pygame main loop.
main_fn()

self._initialized = True
return False
# Call the caller's main loop as an idle source
if self._main:
GLib.idle_add(self._main)

def get_pygame_widget(self):
return self._socket

def get_preview(self):
"""
Return preview of main surface
How to use in activity:
def get_preview(self):
return self.game_canvas.get_preview()
"""

if not hasattr(self, '_screen'):
return None

_tmp_dir = os.path.join(self._activity.get_activity_root(),
'tmp')
_file_path = os.path.join(_tmp_dir, 'preview.png')

width = PREVIEW_SIZE[0]
height = PREVIEW_SIZE[1]
_surface = pygame.transform.scale(self._screen, (width, height))
pygame.image.save(_surface, _file_path)

f = open(_file_path, 'r')
preview = f.read()
f.close()
os.remove(_file_path)

return preview
Loading

0 comments on commit 1c77266

Please sign in to comment.