Permalink
Browse files

window/input: first pass to implement screen rotation.

window.size reflect the size of the rotated screen.
window.system_size reflect the real size of the screen.
touch.scale_for_screen take rotation in parameter
keybinding module is able to rotate the screen (F9 key)
  • Loading branch information...
1 parent 3909e4d commit 02da308428731b67971feb9c4b1d165e1d07a4ae @tito committed Oct 24, 2010
Showing with 128 additions and 28 deletions.
  1. +2 −1 pymt/base.py
  2. +10 −7 pymt/input/providers/mouse.py
  3. +18 −3 pymt/input/touch.py
  4. +19 −7 pymt/modules/keybinding.py
  5. +79 −10 pymt/ui/window/__init__.py
View
@@ -136,7 +136,8 @@ def post_dispatch_input(self, event, touch):
root_window = wid.get_root_window()
if wid != root_window and root_window is not None:
touch.push()
- touch.scale_for_screen(*root_window.size)
+ w, h = root_window.system_size
+ touch.scale_for_screen(w, h, rotation=root_window.rotation)
parent = wid.parent
# and do to_local until the widget
try:
@@ -75,7 +75,7 @@ def test_activity(self):
return False
def find_touch(self, x, y):
- factor = 10. / self.window.width
+ factor = 10. / self.window.system_size[0]
for t in self.touches.itervalues():
if abs(x-t.sx) < factor and abs(y-t.sy) < factor:
return t
@@ -97,8 +97,9 @@ def remove_touch(self, cur):
self.waiting_event.append(('up', cur))
def on_mouse_motion(self, x, y, modifiers):
- rx = x / float(self.window.width)
- ry = 1. - y / float(self.window.height)
+ width, height = self.window.system_size
+ rx = x / float(width)
+ ry = 1. - y / float(height)
if self.current_drag:
cur = self.current_drag
cur.move([rx, ry])
@@ -112,8 +113,9 @@ def on_mouse_motion(self, x, y, modifiers):
def on_mouse_press(self, x, y, button, modifiers):
if self.test_activity():
return
- rx = x / float(self.window.width)
- ry = 1. - y / float(self.window.height)
+ width, height = self.window.system_size
+ rx = x / float(width)
+ ry = 1. - y / float(height)
newTouch = self.find_touch(rx, ry)
if newTouch:
self.current_drag = newTouch
@@ -126,8 +128,9 @@ def on_mouse_press(self, x, y, button, modifiers):
return True
def on_mouse_release(self, x, y, button, modifiers):
- rx = x / float(self.window.width)
- ry = 1. - y / float(self.window.height)
+ width, height = self.window.system_size
+ rx = x / float(width)
+ ry = 1. - y / float(height)
cur = self.find_touch(rx, ry)
if button == 'left' and cur and not ('ctrl' in modifiers):
self.remove_touch(cur)
View
@@ -190,10 +190,25 @@ def move(self, args):
self.dszpos = self.sz
self.depack(args)
- def scale_for_screen(self, w, h, p=None):
+ def scale_for_screen(self, w, h, p=None, rotation=0):
'''Scale position for the screen'''
- self.x = self.sx * float(w)
- self.y = self.sy * float(h)
+ sx, sy = self.sx, self.sy
+ if rotation == 0:
+ self.x = sx * float(w)
+ self.y = sy * float(h)
+ elif rotation == 90:
+ sx, sy = sy, 1-sx
+ self.x = sx * float(h)
+ self.y = sy * float(w)
+ elif rotation == 180:
+ sx, sy = 1-sx, 1-sy
+ self.x = sx * float(w)
+ self.y = sy * float(h)
+ elif rotation == 270:
+ sx, sy = 1-sy, sx
+ self.x = sx * float(h)
+ self.y = sy * float(w)
+
if p:
self.z = self.sz * float(p)
if self.oxpos is None:
View
@@ -74,7 +74,8 @@ def _on_draw():
w2 = win.width / 2.
h2 = win.height / 2.
y = 0
- k = {'font_size': 24}
+ k = {'font_size': 20}
+ ydiff = 25
# draw help
drawLabel('PyMT Keybinding',
@@ -85,23 +86,32 @@ def _on_draw():
pos=(w2, win.height - 180), font_size=12)
drawLabel('F1 - Show Help',
pos=(w2, h2), **k)
- y += 35
+ y += ydiff
drawLabel('F2 - Show FPS (%s)' % str(win.show_fps),
pos=(w2, h2 - y), **k)
- y += 35
+ y += ydiff
drawLabel('F3 - Show Cache state',
pos=(w2, h2 - y), **k)
- y += 35
+ y += ydiff
drawLabel('F4 - Show Calibration screen',
pos=(w2, h2 - y), **k)
if _can_fullscreen():
- y += 35
+ y += ydiff
drawLabel('F5 - Toggle fullscreen',
pos=(w2, h2 - y), **k)
- y += 35
+ y += ydiff
drawLabel('F6 - Show log',
pos=(w2, h2 - y), **k)
- y += 35
+ y += ydiff
+ drawLabel('F7 - Reload CSS',
+ pos=(w2, h2 - y), **k)
+ y += ydiff
+ drawLabel('F8 - Show widget tree',
+ pos=(w2, h2 - y), **k)
+ y += ydiff
+ drawLabel('F9 - Rotate the screen (%d)' % win.rotation,
+ pos=(w2, h2 - y), **k)
+ y += ydiff
drawLabel('F12 - Screenshot',
pos=(w2, h2 - y), **k)
@@ -349,6 +359,8 @@ def _on_keyboard_handler(key, scancode, unicode):
css_reload()
elif key == 289: # F8
toggle_scene_graph()
+ elif key == 290: # F9
+ win.rotation = win.rotation + 90
elif key == 293:
_screenshot()
View
@@ -17,7 +17,7 @@
GL_MODELVIEW, GL_PROJECTION, \
glGetString, glClear, glClearColor, glEnable, glHint, \
glViewport, glMatrixMode, glLoadIdentity, glFrustum, glScalef, \
- glTranslatef
+ glTranslatef, glRotatef
import pymt
from pymt.utils import SafeList
@@ -93,9 +93,11 @@ def __init__(self, **kwargs):
# init privates
self._modifiers = []
self._size = (0, 0)
+ self._rotation = 0
# event subsystem
self.register_event_type('on_flip')
+ self.register_event_type('on_rotate')
self.register_event_type('on_draw')
self.register_event_type('on_update')
self.register_event_type('on_resize')
@@ -235,18 +237,36 @@ def _get_modifiers(self):
return self._modifiers
modifiers = property(_get_modifiers)
+ def _get_size(self):
+ r = self._rotation
+ w, h = self._size
+ if r == 0 or r == 180:
+ return w, h
+ return h, w
def _set_size(self, size):
if super(BaseWindow, self)._set_size(size):
pymt_logger.debug('Window: Resize window to %s' % str(self.size))
self.dispatch_event('on_resize', *size)
return True
return False
- size = property(EventDispatcher._get_size, _set_size)
+ size = property(_get_size, _set_size)
# make some property read-only
- width = property(EventDispatcher._get_width)
- height = property(EventDispatcher._get_height)
- center = property(EventDispatcher._get_center)
+ @property
+ def width(self):
+ r = self._rotation
+ if r == 0 or r == 180:
+ return self._size[0]
+ return self._size[1]
+ @property
+ def height(self):
+ r = self._rotation
+ if r == 0 or r == 180:
+ return self._size[1]
+ return self._size[0]
+ @property
+ def center(self):
+ return self.width / 2., self.height / 2.
def _get_wallpaper(self):
return self._wallpaper
@@ -387,35 +407,60 @@ def on_draw(self):
def on_touch_down(self, touch):
'''Event called when a touch is down'''
- touch.scale_for_screen(*self.size)
+ w, h = self.system_size
+ touch.scale_for_screen(w, h, rotation=self._rotation)
for w in reversed(self.children[:]):
if w.dispatch_event('on_touch_down', touch):
return True
def on_touch_move(self, touch):
'''Event called when a touch move'''
- touch.scale_for_screen(*self.size)
+ w, h = self.system_size
+ touch.scale_for_screen(w, h, rotation=self._rotation)
for w in reversed(self.children[:]):
if w.dispatch_event('on_touch_move', touch):
return True
def on_touch_up(self, touch):
'''Event called when a touch up'''
- touch.scale_for_screen(*self.size)
+ w, h = self.system_size
+ touch.scale_for_screen(w, h, rotation=self._rotation)
for w in reversed(self.children[:]):
if w.dispatch_event('on_touch_up', touch):
return True
def on_resize(self, width, height):
'''Event called when the window is resized'''
+ self.update_viewport()
+
+ def update_viewport(self):
+ width, height = self.system_size
+ w2 = width / 2.
+ h2 = height / 2.
+
+ # prepare the viewport
glViewport(0, 0, width, height)
+
+ # set the projection
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
- glFrustum(-width / 2, width / 2, -height / 2, height / 2, .1, 1000)
+ glFrustum(-w2, w2, -h2, h2, .1, 1000)
glScalef(5000, 5000, 1)
- glTranslatef(-width / 2, -height / 2, -500)
+
+ # use the rotated size.
+ width, height = self.size
+ w2 = width / 2.
+ h2 = height / 2.
+ glTranslatef(-w2, -h2, -500)
+
+ # set the model view
glMatrixMode(GL_MODELVIEW)
+ glLoadIdentity()
+ glTranslatef(w2, h2, 0)
+ glRotatef(self._rotation, 0, 0, 1)
+ glTranslatef(-w2, -h2, 0)
+ # update window size
for w in self.children:
shw, shh = w.size_hint
if shw and shh:
@@ -425,6 +470,30 @@ def on_resize(self, width, height):
elif shh:
w.height = shh * height
+ def _get_rotation(self):
+ return self._rotation
+ def _set_rotation(self, x):
+ x = int(x % 360)
+ if x == self._rotation:
+ return
+ if x not in (0, 90, 180, 270):
+ raise ValueError('can rotate only 0,90,180,270 degrees')
+ self._rotation = x
+ self.dispatch_event('on_resize', *self.size)
+ self.dispatch_event('on_rotate', x)
+ rotation = property(_get_rotation, _set_rotation,
+ 'Get/set the window content rotation. Can be one of '
+ '0, 90, 180, 270 degrees.')
+
+ @property
+ def system_size(self):
+ return self._size
+
+ def on_rotate(self, rotation):
+ '''Event called when the screen have been rotated
+ '''
+ pass
+
def on_close(self, *largs):
'''Event called when the window is closed'''
pymt_modules.unregister_window(self)

0 comments on commit 02da308

Please sign in to comment.