Commits

timfel committed 8a4ae64

add input primitives, using a bad queue for now. this'll go away once we get the SDL event queue working with this.

  • Participants
  • Parent commits 4530b0b

Comments (0)

Files changed (3)

File spyvm/display.py

 from rpython.rlib.rarithmetic import r_uint
 from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rlib.runicode import unicode_encode_utf_8
 
 from rsdl import RSDL, RSDL_helper
 
 
+class SDLEventQueue(object):
+    def __init__(self, default, maxlen=10):
+        assert default
+        self.default = default
+        self.ary = []
+        self.maxlen = 10
+
+    def push(self, event):
+        if len(self.ary) == self.maxlen:
+            self.ary.pop(0)
+        self.ary.append(event)
+
+    def shift(self):
+        if not self.ary:
+            self.ary += self.default
+        return self.ary.pop(0)
+
+    def peek(self):
+        if self.ary:
+            return self.ary[0]
+        else:
+            return self.default[0]
+
+    def size(self):
+        if not self.ary:
+            return len(self.default)
+        else:
+            return len(self.ary)
+
+
 class SDLDisplay(object):
-    _attrs_ = ["screen", "width", "height", "depth", "surface", "has_surface"]
+    _attrs_ = ["screen", "width", "height", "depth", "surface", "has_surface",
+               "last_mouse_position", "mouse_downs", "mouse_ups", "key_ups", "key_downs"]
 
-    def __init__(self):
+    def __init__(self, title):
         assert RSDL.Init(RSDL.INIT_VIDEO) >= 0
+        RSDL.WM_SetCaption(title, "RSqueakVM")
+        RSDL.EnableUNICODE(1)
         self.has_surface = False
+        self.last_mouse_position = [0, 0]
+        self.mouse_downs = SDLEventQueue([0])
+        self.mouse_ups = SDLEventQueue([0])
+        self.key_ups = SDLEventQueue([0])
+        self.key_downs = SDLEventQueue([0])
 
     def set_video_mode(self, w, h, d):
         assert w > 0 and h > 0
     def blit(self):
         RSDL.BlitSurface(self.surface, lltype.nullptr(RSDL.Rect), self.screen, lltype.nullptr(RSDL.Rect))
         RSDL.Flip(self.screen)
+
+    def get_next_event(self):
+        event = lltype.malloc(RSDL.Event, flavor="raw")
+        ok = 1
+        try:
+            while ok == 1:
+                ok = rffi.cast(lltype.Signed, RSDL.PollEvent(event))
+                if ok == 1:
+                    c_type = rffi.getintfield(event, 'c_type')
+                    if c_type == RSDL.MOUSEBUTTONDOWN or c_type == RSDL.MOUSEBUTTONUP:
+                        b = rffi.cast(RSDL.MouseButtonEventPtr, event)
+                        btn = rffi.getintfield(b, 'c_button')
+                        if btn == RSDL.BUTTON_LEFT:
+                            btn = 1
+                        elif btn == RSDL.BUTTON_MIDDLE:
+                            btn = 2
+                        elif btn == RSDL.BUTTON_RIGHT:
+                            btn = 4
+
+                        if c_type == RSDL.MOUSEBUTTONDOWN:
+                            self.mouse_downs.push(btn)
+                        else:
+                            self.mouse_ups.push(btn)
+                    elif c_type == RSDL.MOUSEMOTION:
+                        m = rffi.cast(RSDL.MouseMotionEventPtr, event)
+                        x = rffi.getintfield(m, "c_x")
+                        y = rffi.getintfield(m, "c_y")
+                        self.last_mouse_position = [x, y]
+                    elif c_type == RSDL.KEYUP or c_type == RSDL.KEYDOWN:
+                        p = rffi.cast(RSDL.KeyboardEventPtr, event)
+                        char = rffi.getintfield(p.c_keysym, 'c_unicode')
+                        if char != 0:
+                            for c in unicode_encode_utf_8(unichr(char), 1, "ignore"):
+                                if c_type == RSDL.KEYUP:
+                                    self.key_ups.push(ord(c))
+                                else:
+                                    self.key_downs.push(ord(c))
+        finally:
+            lltype.free(event, flavor='raw')
+
+    def mouse_point(self):
+        self.get_next_event()
+        return self.last_mouse_position
+
+    def mouse_button(self):
+        self.get_next_event()
+        return self.mouse_ups.shift()
+
+    def next_keycode(self):
+        self.get_next_event()
+        return self.key_downs.shift()
+
+    def peek_keycode(self):
+        self.get_next_event()
+        return self.key_downs.peek()

File spyvm/objspace.py

 from spyvm import constants, model, shadow, wrapper
-from spyvm.error import UnwrappingError, WrappingError
+from spyvm.error import UnwrappingError, WrappingError, PrimitiveFailedError
 from rpython.rlib.objectmodel import instantiate, specialize
 from rpython.rlib.rarithmetic import intmask, r_uint, int_between
 
         assert isinstance(w_array, model.W_PointersObject)
         
         return [w_array.at0(self, i) for i in range(w_array.size())]
-        
+
+    def get_display(self):
+        w_display = self.objtable['w_display']
+        if w_display:
+            w_bitmap = w_display.fetch(self, 0)
+            if isinstance(w_bitmap, model.W_DisplayBitmap):
+                return w_bitmap.display
+        raise PrimitiveFailedError()
+
     def _freeze_(self):
         return True
 

File spyvm/primitives.py

 KBD_PEEK = 109
 
 
+@expose_primitive(MOUSE_POINT, unwrap_spec=[object])
+def func(interp, s_frame, w_rcvr):
+    x, y = interp.space.get_display().mouse_point()
+    w_point = model.W_PointersObject(interp.space.w_Point, 2)
+    w_point.store(interp.space, 0, interp.space.wrap_int(x))
+    w_point.store(interp.space, 1, interp.space.wrap_int(y))
+    return w_point
+
 @expose_primitive(GET_NEXT_EVENT, unwrap_spec=[object])
 def func(interp, s_frame, w_rcvr):
     raise PrimitiveNotYetWrittenError()
     else:
         assert isinstance(w_bitmap, model.W_WordsObject)
         if not sdldisplay:
-            sdldisplay = display.SDLDisplay()
+            sdldisplay = display.SDLDisplay(interp.image_name)
         w_display_bitmap = model.W_DisplayBitmap(w_bitmap.getclass(interp.space), w_bitmap.size(), depth, sdldisplay)
         for idx, word in enumerate(w_bitmap.words):
             w_display_bitmap.setword(idx, word)
         w_rcvr.atput0(interp.space, i0, w_replacement.at0(interp.space, repOff + i0))
     return w_rcvr
 
-
 @expose_primitive(SCREEN_SIZE, unwrap_spec=[object])
 def func(interp, s_frame, w_rcvr):
     # XXX get the real screen size
     point.store_y(480)
     return w_res
 
+@expose_primitive(MOUSE_BUTTONS, unwrap_spec=[object])
+def func(interp, s_frame, w_rcvr):
+    btn = interp.space.get_display().mouse_button()
+    return interp.space.wrap_int(btn)
+
+@expose_primitive(KBD_NEXT, unwrap_spec=[object])
+def func(interp, s_frame, w_rcvr):
+    return interp.space.wrap_int(interp.space.get_display().next_keycode())
+
+@expose_primitive(KBD_PEEK, unwrap_spec=[object])
+def func(interp, s_frame, w_rcvr):
+    return interp.space.wrap_int(interp.space.get_display().peek_keycode())
+
+
 # ___________________________________________________________________________
 # Control Primitives