summaryrefslogtreecommitdiff
path: root/src/test/EventTest.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/EventTest.py')
-rw-r--r--src/test/EventTest.py1086
1 files changed, 1086 insertions, 0 deletions
diff --git a/src/test/EventTest.py b/src/test/EventTest.py
new file mode 100644
index 0000000..afdfe94
--- /dev/null
+++ b/src/test/EventTest.py
@@ -0,0 +1,1086 @@
+# -*- coding: utf-8 -*-
+# libavg - Media Playback Engine.
+# Copyright (C) 2003-2014 Ulrich von Zadow
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Current versions can be found at www.libavg.de
+#
+
+from libavg import avg, player
+from testcase import *
+
+def dumpMouseEvent(Event):
+ print Event
+ print " type: "+str(Event.type)
+ print " leftbuttonstate: "+str(Event.leftbuttonstate)
+ print " middlebuttonstate: "+str(Event.middlebuttonstate)
+ print " rightbuttonstate: "+str(Event.rightbuttonstate)
+ print " position: "+str(Event.x)+","+str(Event.y)
+ print " node: "+Event.node.id
+
+mainMouseUpCalled = False
+mainMouseDownCalled = False
+
+def mainMouseUp(Event):
+ global mainMouseUpCalled
+ assert (Event.type == avg.Event.CURSOR_UP)
+ mainMouseUpCalled = True
+
+def mainMouseDown(Event):
+ global mainMouseDownCalled
+ assert (Event.type == avg.Event.CURSOR_DOWN)
+ mainMouseDownCalled = True
+
+
+class EventTestCase(AVGTestCase):
+ def __init__(self, testFuncName):
+ AVGTestCase.__init__(self, testFuncName)
+
+ def testKeyEvents(self):
+ def onKeyDown(event):
+ if event.keystring == 'A' and event.keycode == 65 and event.unicode == 65:
+ self.keyDownCalled = True
+
+ def onKeyUp(event):
+ if event.keystring == 'A' and event.keycode == 65 and event.unicode == 65:
+ self.keyUpCalled = True
+
+ def onSubscribeKeyDown(event):
+ self.subscribeKeyDownCalled = True
+
+ def onSubscribeKeyUp(event):
+ self.subscribeKeyUpCalled = True
+
+ root = self.loadEmptyScene()
+ root.setEventHandler(avg.Event.KEY_DOWN, avg.Event.NONE, onKeyDown)
+ root.setEventHandler(avg.Event.KEY_UP, avg.Event.NONE, onKeyUp)
+ player.subscribe(avg.Player.KEY_DOWN, onSubscribeKeyDown)
+ player.subscribe(avg.Player.KEY_UP, onSubscribeKeyUp)
+ self.start(False,
+ (lambda: Helper.fakeKeyEvent(avg.Event.KEY_DOWN, 65, 65, "A", 65,
+ avg.KEYMOD_NONE),
+ lambda: self.assert_(self.keyDownCalled and self.subscribeKeyDownCalled),
+ lambda: Helper.fakeKeyEvent(avg.Event.KEY_UP, 65, 65, "A", 65,
+ avg.KEYMOD_NONE),
+ lambda: self.assert_(self.keyUpCalled and self.subscribeKeyUpCalled)
+ ))
+
+ def testSimpleEvents(self):
+ def getMouseState():
+ Event = player.getMouseState()
+ self.assertEqual(Event.pos, avg.Point2D(10,10))
+
+ root = self.loadEmptyScene()
+ img1 = avg.ImageNode(pos=(0,0), href="rgb24-65x65.png", parent=root)
+ handlerTester1 = NodeHandlerTester(self, img1)
+
+ img2 = avg.ImageNode(pos=(64,0), href="rgb24-65x65.png", parent=root)
+ handlerTester2 = NodeHandlerTester(self, img2)
+
+ self.start(False,
+ (# down, getMouseState(), move, up.
+ # events are inside img1 but outside img2.
+ lambda: self.assert_(not(player.isMultitouchAvailable())),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 10, 10),
+ lambda: handlerTester1.assertState(
+ (avg.Node.CURSOR_DOWN, avg.Node.CURSOR_OVER)),
+ lambda: handlerTester2.assertState(()),
+ getMouseState,
+
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_MOTION, 12, 12),
+ lambda: handlerTester1.assertState((avg.Node.CURSOR_MOTION,)),
+
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 12, 12),
+ lambda: handlerTester1.assertState((avg.Node.CURSOR_UP,))
+
+ ))
+
+ def testTilted(self):
+ root = self.loadEmptyScene()
+ img = avg.ImageNode(pos=(0,0), href="rgb24-65x65.png", angle=0.785, parent=root)
+ handlerTester = NodeHandlerTester(self, img)
+
+ self.start(False,
+ (lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 32, 32),
+ lambda: handlerTester.assertState(
+ (avg.Node.CURSOR_DOWN, avg.Node.CURSOR_OVER)),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 0, 0),
+ lambda: handlerTester.assertState((avg.Node.CURSOR_OUT,)),
+ ))
+
+ def testWordsClicks(self):
+ root = self.loadEmptyScene()
+ words = avg.WordsNode(pos=(40,40), alignment="right", text="test", parent=root)
+ handlerTester = NodeHandlerTester(self, words)
+ self.start(False,
+ (lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 45, 45),
+ lambda: handlerTester.assertState(()),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 35, 45),
+ lambda: handlerTester.assertState(
+ (avg.Node.CURSOR_UP, avg.Node.CURSOR_OVER)),
+ ))
+
+ def testDivEvents(self):
+ root = self.loadEmptyScene()
+ div = avg.DivNode(pos=(0,0), parent=root)
+ divHandlerTester = NodeHandlerTester(self, div)
+
+ img = avg.ImageNode(pos=(0,0), href="rgb24-65x65.png", parent=div)
+ imgHandlerTester = NodeHandlerTester(self, img)
+
+ self.start(False,
+ (# down, move, up.
+ # events are inside img and therefore should bubble to div.
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 10, 10),
+ lambda: divHandlerTester.assertState(
+ (avg.Node.CURSOR_DOWN, avg.Node.CURSOR_OVER)),
+ lambda: imgHandlerTester.assertState(
+ (avg.Node.CURSOR_DOWN, avg.Node.CURSOR_OVER)),
+
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_MOTION, 12, 12),
+ lambda: divHandlerTester.assertState((avg.Node.CURSOR_MOTION,)),
+ lambda: imgHandlerTester.assertState((avg.Node.CURSOR_MOTION,)),
+
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 12, 12),
+ lambda: divHandlerTester.assertState((avg.Node.CURSOR_UP,)),
+ lambda: imgHandlerTester.assertState((avg.Node.CURSOR_UP,))
+ ))
+
+ def testDivNegativePos(self):
+ root = self.loadEmptyScene()
+ div = avg.DivNode(pos=(10,10), parent=root)
+ divHandlerTester = NodeHandlerTester(self, div)
+
+ img = avg.ImageNode(pos=(-10,-10), href="rgb24-65x65.png", parent=div)
+ imgHandlerTester = NodeHandlerTester(self, img)
+
+ self.start(False,
+ (lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 1, 1),
+ lambda: divHandlerTester.assertState(
+ (avg.Node.CURSOR_DOWN, avg.Node.CURSOR_OVER)),
+ lambda: imgHandlerTester.assertState(
+ (avg.Node.CURSOR_DOWN, avg.Node.CURSOR_OVER)),
+ ))
+
+ def testUnlinkInHandler(self):
+ def onImgDown(event):
+ self.__imgDownCalled = True
+ self.div.unlink(True)
+
+ def onDivDown(event):
+ self.__divDownCalled = True
+
+ def checkState():
+ self.assert_(self.__imgDownCalled and not(self.__divDownCalled))
+
+ self.__imgDownCalled = False
+ self.__divDownCalled = False
+ root = self.loadEmptyScene()
+ self.div = avg.DivNode(pos=(0,0), parent=root)
+ self.div.connectEventHandler(avg.Event.CURSOR_DOWN, avg.Event.MOUSE, self,
+ onDivDown)
+
+ img = avg.ImageNode(pos=(0,0), href="rgb24-65x65.png", parent=self.div)
+ img.connectEventHandler(avg.Event.CURSOR_DOWN, avg.Event.MOUSE, self, onImgDown)
+
+ self.start(False,
+ (lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 10, 10),
+ checkState))
+
+
+ def testConnectHandler(self):
+ def onDown1(event):
+ self.down1Called = True
+
+ def onDown2(event):
+ self.down2Called = True
+
+ def resetDownCalled():
+ self.down1Called = False
+ self.down2Called = False
+
+ def connectTwoHandlers():
+ self.img.connectEventHandler(avg.Event.CURSOR_DOWN, avg.Event.MOUSE, self,
+ onDown1)
+ self.img.connectEventHandler(avg.Event.CURSOR_DOWN, avg.Event.MOUSE, self,
+ onDown2)
+
+ def connectUnlinkHandler():
+ self.img.disconnectEventHandler(self)
+ self.img.connectEventHandler(avg.Event.CURSOR_DOWN, avg.Event.MOUSE, self,
+ unlinkHandler)
+ self.img.connectEventHandler(avg.Event.CURSOR_DOWN, avg.Event.MOUSE, self,
+ onDown2)
+
+ def unlinkHandler(event):
+ self.img.disconnectEventHandler(self)
+
+ root = self.loadEmptyScene()
+ self.img = avg.ImageNode(pos=(0,0), href="rgb24-65x65.png", parent=root)
+ connectTwoHandlers()
+ self.img.disconnectEventHandler(self, onDown1)
+ self.img.disconnectEventHandler(self, onDown2)
+ connectTwoHandlers()
+ self.img.disconnectEventHandler(self)
+
+ resetDownCalled()
+ self.start(False,
+ (connectTwoHandlers,
+ lambda: self.fakeClick(10,10),
+ lambda: self.assert_(self.down1Called and self.down2Called),
+ resetDownCalled,
+ lambda: self.img.disconnectEventHandler(self, onDown1),
+ lambda: self.fakeClick(10,10),
+ lambda: self.assert_(not(self.down1Called) and self.down2Called),
+ connectUnlinkHandler,
+ lambda: self.fakeClick(10,10),
+ ))
+
+ def testPublisher(self):
+ def onDown(event):
+ self.assert_(event.type == avg.Event.CURSOR_DOWN)
+ curEvent = player.getCurrentEvent()
+ self.assert_(curEvent.type == avg.Event.CURSOR_DOWN)
+ self.assert_(curEvent.when == event.when)
+ self.downCalled = True
+
+ def unsubscribe():
+ self.assert_(self.img.isSubscribed(avg.Node.CURSOR_DOWN, onDown))
+ self.img.unsubscribe(avg.Node.CURSOR_DOWN, onDown)
+ self.assert_(not(self.img.isSubscribed(avg.Node.CURSOR_DOWN, onDown)))
+ self.assert_(self.img.getNumSubscribers(avg.Node.CURSOR_DOWN) == 0)
+ self.downCalled = False
+ self.assertException(
+ lambda: self.img.unsubscribe(avg.Node.CURSOR_DOWN, onDown))
+
+ def initUnsubscribeInEvent(useMessageID):
+ self.subscriberID = self.img.subscribe(avg.Node.CURSOR_DOWN,
+ lambda event: onDownUnsubscribe(event, useMessageID))
+
+ def onDownUnsubscribe(event, useMessageID):
+ if useMessageID:
+ self.img.unsubscribe(avg.Node.CURSOR_DOWN, self.subscriberID)
+ self.assertException(lambda:
+ self.img.unsubscribe(avg.Node.CURSOR_DOWN, self.subscriberID))
+ else:
+ self.img.unsubscribe(self.subscriberID)
+ self.assertException(lambda: self.img.unsubscribe(self.subscriberID))
+
+ self.downCalled = True
+
+ def onFrame():
+ self.onFrameCalled = True
+
+ self.downCalled = False
+ self.onFrameCalled = False
+ root = self.loadEmptyScene()
+ player.subscribe(player.ON_FRAME, onFrame)
+ self.img = avg.ImageNode(pos=(0,0), href="rgb24-65x65.png", parent=root)
+ self.img.subscribe(avg.Node.CURSOR_DOWN, onDown)
+ self.assertException(lambda: self.img.subscribe(23, onDown))
+ self.assertException(lambda: self.img.unsubscribe(avg.Node.CURSOR_DOWN, 23))
+ self.start(False,
+ (lambda: self.fakeClick(10,10),
+ lambda: self.assert_(self.downCalled),
+ lambda: self.assert_(self.onFrameCalled),
+
+ unsubscribe,
+ lambda: self.fakeClick(10,10),
+ lambda: self.assert_(not(self.downCalled)),
+
+ lambda: initUnsubscribeInEvent(True),
+ lambda: self.fakeClick(10,10),
+ lambda: self.assert_(self.downCalled),
+
+ lambda: initUnsubscribeInEvent(False),
+ lambda: self.fakeClick(10,10),
+ lambda: self.assert_(self.downCalled),
+ ))
+
+ def testComplexPublisher(self):
+ def setupUnsubscribe():
+ self.downCalled = [False, False]
+ self.msgIDs = []
+ for i in range(0,2):
+ self.msgIDs.append(self.img.subscribe(avg.Node.CURSOR_DOWN,
+ lambda event, i=i: onUnsubscribeDown(i)))
+
+ def onUnsubscribeDown(i):
+ self.downCalled[i] = True
+ for j in range(0,2):
+ self.img.unsubscribe(avg.Node.CURSOR_DOWN, self.msgIDs[j])
+
+ def assertCorrectUnsubscribe():
+ # Exactly one of the two callbacks should have been invoked
+ self.assert_(self.downCalled[0] != self.downCalled[1])
+
+ def setupSubscribe():
+ self.downCalled = [False, False]
+ self.msgIDs = []
+ self.msgIDs.append(self.img.subscribe(avg.Node.CURSOR_DOWN,
+ lambda event: onSubscribeDown()))
+
+ def onSubscribeDown():
+ self.downCalled[0] = True
+ self.msgIDs.append(self.img.subscribe(avg.Node.CURSOR_DOWN,
+ lambda event: onSecondSubscribeDown()))
+
+ def onSecondSubscribeDown():
+ self.downCalled[1] = True
+
+ def assertDownsCalled(expectedState):
+ self.assert_(self.downCalled == expectedState)
+
+ root = self.loadEmptyScene()
+ self.img = avg.ImageNode(pos=(0,0), href="rgb24-65x65.png", parent=root)
+
+ self.start(False,
+ (# Subscribe twice to an event, unsubscribe both during processing of the
+ # first. Second shouldn't be called anymore.
+ lambda: setupUnsubscribe(),
+ lambda: self.fakeClick(10,10),
+ assertCorrectUnsubscribe,
+
+ # Subscribe to an event, subscribe again during event processing.
+ # The second one shouldn't be called immediately.
+ lambda: setupSubscribe(),
+ lambda: self.fakeClick(10,10),
+ lambda: assertDownsCalled([True, False]),
+ lambda: self.fakeClick(10,10),
+ lambda: assertDownsCalled([True, True]),
+ ))
+
+ def testPublisherAutoDelete(self):
+
+ class TestSubscriber():
+ def __init__(self):
+ self.__downCalled = False
+
+ def subscribe(self, node):
+ node.subscribe(avg.Node.CURSOR_DOWN, self.onDown)
+
+ def subscribeLambda(self, node):
+ node.subscribe(avg.Node.CURSOR_DOWN, lambda event: self.onDown(event))
+
+ def onDown(self, event):
+ self.__downCalled = True
+
+ def hasClicked(self):
+ return self.__downCalled
+
+ def removeSubscriber():
+ del self.subscriber;
+
+ root = self.loadEmptyScene()
+ self.img = avg.ImageNode(pos=(0,0), href="rgb24-65x65.png", parent=root)
+ self.subscriber = TestSubscriber()
+ self.subscriber.subscribe(self.img)
+ self.start(False,
+ (lambda: self.fakeClick(10,10),
+ lambda: self.assert_(self.subscriber.hasClicked()),
+ removeSubscriber,
+ lambda: self.fakeClick(10,10),
+ lambda: self.assert_(
+ self.img.getNumSubscribers(avg.Node.CURSOR_DOWN) == 0)
+ ))
+
+
+ def testPublisherNestedUnsubscribe(self):
+
+ class TestPublisher(avg.Publisher):
+
+ OUTER_EVENT = avg.Publisher.genMessageID()
+ INNER_EVENT = avg.Publisher.genMessageID()
+
+ def __init__(self):
+ super(TestPublisher, self).__init__()
+ self.publish(TestPublisher.OUTER_EVENT)
+ self.publish(TestPublisher.INNER_EVENT)
+
+ def generateEvent(self):
+ self.notifySubscribers(TestPublisher.OUTER_EVENT, [])
+
+ def generateInnerEvent(self):
+ self.notifySubscribers(TestPublisher.INNER_EVENT, [])
+
+ def onEvent():
+ self.publisher.generateInnerEvent()
+
+ def onEvent2():
+ self.event2Called = True;
+
+ def onInnerEvent():
+ self.publisher.unsubscribe(TestPublisher.OUTER_EVENT, onEvent)
+ self.publisher.unsubscribe(TestPublisher.OUTER_EVENT, onEvent2)
+
+ self.loadEmptyScene()
+ self.publisher = TestPublisher()
+ self.publisher.subscribe(TestPublisher.OUTER_EVENT, onEvent2)
+ self.publisher.subscribe(TestPublisher.OUTER_EVENT, onEvent)
+ self.publisher.subscribe(TestPublisher.INNER_EVENT, onInnerEvent)
+ self.event2Called = False
+ self.start(False,
+ (self.publisher.generateEvent,
+ ))
+ self.assert_(not(self.event2Called))
+
+
+ def testObscuringEvents(self):
+ root = self.loadEmptyScene()
+ img1 = avg.ImageNode(pos=(0,0), href="rgb24-65x65.png", parent=root)
+ handlerTester1 = NodeHandlerTester(self, img1)
+
+ img2 = avg.ImageNode(pos=(0,0), href="rgb24-65x65.png", parent=root)
+ handlerTester2 = NodeHandlerTester(self, img2)
+ self.start(False,
+ (# down, move, up.
+ # events should only arrive at img2 because img1 is obscured by img1.
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 10, 10),
+ lambda: handlerTester1.assertState(()),
+ lambda: handlerTester2.assertState(
+ (avg.Node.CURSOR_DOWN, avg.Node.CURSOR_OVER)),
+
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_MOTION, 12, 12),
+ lambda: handlerTester1.assertState(()),
+ lambda: handlerTester2.assertState((avg.Node.CURSOR_MOTION,)),
+
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 12, 12),
+ lambda: handlerTester1.assertState(()),
+ lambda: handlerTester2.assertState((avg.Node.CURSOR_UP,))
+ ))
+
+ def testSensitive(self):
+ # Tests both sensitive and active attributes.
+ def activateNode(node, useSensitiveAttr, b):
+ if useSensitiveAttr:
+ node.sensitive = b
+ else:
+ node.active = b
+
+ def onNode2Down(event):
+ self.__node2Down = True
+
+ for useSensitiveAttr in (True, False):
+ root = self.loadEmptyScene()
+ self.img = avg.ImageNode(pos=(0,0), href="rgb24-65x65.png", parent=root)
+ handlerTester = NodeHandlerTester(self, self.img)
+
+ activateNode(self.img, useSensitiveAttr, False)
+ self.start(False,
+ (# Node is inactive -> no events.
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 10, 10),
+ lambda: handlerTester.assertState(()),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 10, 10),
+
+ # Activate the node -> events arrive.
+ lambda: activateNode(self.img, useSensitiveAttr, True),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 10, 10),
+ lambda: handlerTester.assertState(
+ (avg.Node.CURSOR_DOWN, avg.Node.CURSOR_OVER)),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 10, 10),
+ ))
+ self.img = None
+
+ # Check if sensitive is deactivated immediately, not at the end of the frame.
+ root = self.loadEmptyScene()
+ self.img1 = avg.ImageNode(pos=(0,0), href="rgb24-65x65.png", parent=root)
+ self.img2 = avg.ImageNode(pos=(64,0), href="rgb24-65x65.png", parent=root)
+ self.img1.connectEventHandler(avg.Event.CURSOR_DOWN, avg.Event.TOUCH, self,
+ lambda event: activateNode(self.img2, useSensitiveAttr, False))
+ self.img2.connectEventHandler(avg.Event.CURSOR_DOWN, avg.Event.TOUCH, self,
+ onNode2Down)
+ self.__node2Down = False
+
+ self.start(False,
+ (lambda: self._sendTouchEvents((
+ (1, avg.Event.CURSOR_DOWN, 10, 10),
+ (2, avg.Event.CURSOR_DOWN, 80, 10),)),
+ lambda: self.assert_(not(self.__node2Down)),
+ ))
+
+ def testChangingHandlers(self):
+ root = self.loadEmptyScene()
+ img = avg.ImageNode(pos=(0,0), href="rgb24-65x65.png", parent=root)
+ handlerTester = NodeHandlerTester(self, img)
+
+ self.start(False,
+ (lambda: handlerTester.clearHandlers(),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 10, 10),
+ lambda: handlerTester.assertState(()),
+ lambda: handlerTester.setHandlers(),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 10, 10),
+ lambda: handlerTester.assertState((avg.Node.CURSOR_UP,)),
+ ))
+
+ def testEventCapture(self):
+ def onMainMouseDown(Event):
+ self.mainMouseDownCalled = True
+
+ def onMouseDown(Event):
+ self.mouseDownCalled = True
+
+ def captureEvent():
+ self.mouseDownCalled = False
+ self.mainMouseDownCalled = False
+ self.img.setEventCapture()
+
+ def noCaptureEvent():
+ self.mouseDownCalled = False
+ self.mainMouseDownCalled = False
+ self.img.releaseEventCapture()
+
+ def doubleCaptureEvent():
+ self.mouseDownCalled = False
+ self.mainMouseDownCalled = False
+ self.img.setEventCapture()
+ self.img.setEventCapture()
+ self.img.releaseEventCapture()
+
+ def releaseTooMuch():
+ self.img.releaseEventCapture()
+ self.assertException(self.img.releaseEventCapture)
+
+ self.mouseDownCalled = False
+ self.mainMouseDownCalled = False
+
+ root = self.loadEmptyScene()
+ root.setEventHandler(avg.Event.CURSOR_DOWN, avg.Event.MOUSE, onMainMouseDown)
+ self.img = avg.ImageNode(pos=(0,0), href="rgb24-65x65.png", parent=root)
+ self.img.setEventHandler(avg.Event.CURSOR_DOWN, avg.Event.MOUSE, onMouseDown)
+
+ self.start(False,
+ (lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 10, 10),
+ lambda: self.assert_(self.mouseDownCalled),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 10, 10),
+ captureEvent,
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 100, 10),
+ lambda: self.assert_(self.mouseDownCalled and
+ self.mainMouseDownCalled),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 100, 10),
+ noCaptureEvent,
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 100, 10),
+ lambda: self.assert_(not(self.mouseDownCalled) and
+ self.mainMouseDownCalled),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 100, 10),
+ doubleCaptureEvent,
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 100, 10),
+ lambda: self.assert_(self.mouseDownCalled and
+ self.mainMouseDownCalled),
+ releaseTooMuch,
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 100, 10),
+ ))
+ self.img = None
+
+ def testMouseOver(self):
+ def onImg2MouseOver(Event):
+ self.img2MouseOverCalled = True
+
+ def onImg2MouseOut(Event):
+ self.img2MouseOutCalled = True
+
+ def onDivMouseOver(Event):
+ self.divMouseOverCalled = True
+
+ def onDivMouseOut(Event):
+ self.divMouseOutCalled = True
+
+ def onAVGMouseOver(Event):
+ self.avgMouseOverCalled = True
+
+ def onImg1MouseOver(Event):
+ self.img1MouseOverCalled = True
+
+ def printState():
+ print "----"
+ print "img2MouseOverCalled=", self.img2MouseOverCalled
+ print "img2MouseOutCalled=", self.img2MouseOutCalled
+ print "divMouseOverCalled=", self.divMouseOverCalled
+ print "divMouseOutCalled=", self.divMouseOutCalled
+ print "avgMouseOverCalled=", self.avgMouseOverCalled
+ print "img1MouseOverCalled=", self.img1MouseOverCalled
+
+ def resetState():
+ self.img2MouseOverCalled = False
+ self.img2MouseOutCalled = False
+ self.divMouseOverCalled = False
+ self.divMouseOutCalled = False
+ self.avgMouseOverCalled = False
+ self.img1MouseOverCalled = False
+
+ def killNodeUnderCursor():
+ Parent = img1.parent
+ Parent.removeChild(Parent.indexOf(img1))
+
+ root = self.loadEmptyScene()
+ img1 = avg.ImageNode(href="rgb24-65x65.png", parent=root)
+ div = avg.DivNode(pos=(65,0), parent=root)
+ img3 = avg.ImageNode(href="rgb24-65x65.png", parent=div)
+ img2 = avg.ImageNode(pos=(0,65), href="rgb24-65x65.png", parent=div)
+
+ img2.setEventHandler(avg.Event.CURSOR_OVER, avg.Event.MOUSE, onImg2MouseOver)
+ img2.setEventHandler(avg.Event.CURSOR_OUT, avg.Event.MOUSE, onImg2MouseOut)
+ div.setEventHandler(avg.Event.CURSOR_OVER, avg.Event.MOUSE, onDivMouseOver)
+ div.setEventHandler(avg.Event.CURSOR_OUT, avg.Event.MOUSE, onDivMouseOut)
+ root.setEventHandler(avg.Event.CURSOR_OVER, avg.Event.MOUSE, onAVGMouseOver)
+ img1.setEventHandler(avg.Event.CURSOR_OVER, avg.Event.MOUSE, onImg1MouseOver)
+ self.start(False,
+ (resetState,
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 70, 70),
+ lambda: self.assert_(
+ self.img2MouseOverCalled and
+ self.divMouseOverCalled and
+ self.avgMouseOverCalled and
+ not(self.img2MouseOutCalled) and
+ not(self.divMouseOutCalled) and
+ not(self.img1MouseOverCalled)),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 70, 70),
+ resetState,
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 70, 10),
+ lambda: self.assert_(
+ not(self.img2MouseOverCalled) and
+ not(self.divMouseOverCalled) and
+ not(self.avgMouseOverCalled) and
+ self.img2MouseOutCalled and
+ not(self.divMouseOutCalled) and
+ not(self.img1MouseOverCalled)),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 70, 10),
+
+ resetState,
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 10, 10),
+ lambda: self.assert_(
+ not(self.img2MouseOverCalled) and
+ not(self.divMouseOverCalled) and
+ not(self.avgMouseOverCalled) and
+ not(self.img2MouseOutCalled) and
+ self.divMouseOutCalled and
+ self.img1MouseOverCalled),
+
+ resetState,
+ killNodeUnderCursor,
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 10, 10),
+ lambda: self.assert_(
+ not(self.img2MouseOverCalled) and
+ not(self.divMouseOverCalled) and
+ not(self.avgMouseOverCalled) and
+ not(self.img2MouseOutCalled) and
+ not(self.divMouseOutCalled) and
+ not(self.img1MouseOverCalled)),
+
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 10, 10),
+ resetState,
+ lambda: img2.setEventCapture(),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 70, 70),
+ lambda: self.assert_(
+ self.img2MouseOverCalled and
+ self.divMouseOverCalled and
+ not(self.avgMouseOverCalled) and
+ not(self.img2MouseOutCalled) and
+ not(self.divMouseOutCalled) and
+ not(self.img1MouseOverCalled)),
+
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 70, 70),
+ resetState,
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 10, 10),
+ lambda: self.assert_(
+ not(self.img2MouseOverCalled) and
+ not(self.divMouseOverCalled) and
+ not(self.avgMouseOverCalled) and
+ self.img2MouseOutCalled and
+ self.divMouseOutCalled and
+ not(self.img1MouseOverCalled))
+ ))
+
+ def testMouseDisable(self):
+ def checkMouseWorking(working):
+ if working:
+ downTestEvents = (avg.Node.CURSOR_DOWN, avg.Node.CURSOR_OVER)
+ upTestEvents = (avg.Node.CURSOR_UP,)
+ else:
+ downTestEvents = ()
+ upTestEvents = ()
+
+ return (lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 10, 10),
+ lambda: handlerTester.assertState(downTestEvents),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 10, 10),
+ lambda: handlerTester.assertState(upTestEvents)
+ )
+
+ root = self.loadEmptyScene()
+ img = avg.ImageNode(pos=(0,0), href="rgb24-65x65.png", parent=root)
+ handlerTester = NodeHandlerTester(self, img)
+ player.enableMouse(False)
+
+ self.start(False,
+ (checkMouseWorking(False),
+ lambda: player.enableMouse(True),
+ checkMouseWorking(True),
+ lambda: player.enableMouse(False),
+ checkMouseWorking(False),
+ lambda: player.enableMouse(True),
+ ))
+
+ def testEventErr(self):
+ def onErrMouseOver(Event):
+ undefinedFunction()
+
+ root = self.loadEmptyScene()
+ root.setEventHandler(avg.Event.CURSOR_DOWN, avg.Event.MOUSE, onErrMouseOver)
+ self.assertException(lambda:
+ self.start(False,
+ (lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 10, 10),
+ )))
+
+ def testEventHook(self):
+ def resetState():
+ self.ehookMouseEvent = False
+ self.ehookKeyboardEvent = False
+
+ def cleanup():
+ resetState()
+ player.setEventHook(None)
+
+ def handleEvent(event):
+ if isinstance(event, avg.MouseEvent) and event.source == avg.Event.MOUSE:
+ if event.type == avg.Event.CURSOR_DOWN:
+ self.ehookMouseEvent = True
+ elif isinstance(event, avg.KeyEvent):
+ self.ehookKeyboardEvent = True
+ else:
+ self.fail()
+
+ self.loadEmptyScene()
+ resetState()
+
+ player.setEventHook(handleEvent)
+ self.start(False,
+ (lambda: self.fakeClick(10, 10),
+ lambda: self.assert_(self.ehookMouseEvent),
+ lambda: Helper.fakeKeyEvent(avg.Event.KEY_DOWN, 65, 65, "A", 65, 0),
+ lambda: self.assert_(self.ehookKeyboardEvent),
+ cleanup,
+ lambda: self.fakeClick(10, 10),
+ lambda: self.assert_(not self.ehookMouseEvent),
+ lambda: Helper.fakeKeyEvent(avg.Event.KEY_DOWN, 65, 65, "A", 65, 0),
+ lambda: self.assert_(not self.ehookKeyboardEvent),
+ ))
+
+ def testException(self):
+
+ class TestException(Exception):
+ pass
+
+ def throwException(event):
+ raise TestException
+
+ rect = avg.RectNode(size = (50, 50))
+ rect.setEventHandler(avg.Event.CURSOR_DOWN, avg.Event.MOUSE, throwException)
+
+ root = self.loadEmptyScene()
+ root.appendChild(rect)
+
+ self.__exceptionThrown = False
+ try:
+ self.start(False,
+ (lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 10, 10),
+ lambda: None
+ ))
+ except TestException:
+ self.__exceptionThrown = True
+
+ self.assert_(self.__exceptionThrown)
+
+ def testContacts(self):
+
+ def onDown(event):
+ contact = event.contact
+ self.assertEqual(event.cursorid, contact.id)
+ self.assertEqual(contact.age, 0)
+ self.assertEqual(contact.distancefromstart, 0)
+ self.assertEqual(contact.motionangle, 0)
+ self.assertEqual(contact.motionvec, (0,0))
+ self.assertEqual(contact.distancetravelled, 0)
+ self.assertEqual(contact.events[0].pos, event.pos)
+ self.assertEqual(len(contact.events), 1)
+ contact.connectListener(onMotion, onUp)
+ contact.subscribe(avg.Contact.CURSOR_MOTION, onMotionSubscribe)
+ contact.subscribe(avg.Contact.CURSOR_UP, onUpSubscribe)
+
+ def onMotion(event):
+ contact = event.contact
+ self.assertEqual(event.cursorid, contact.id)
+ self.assertEqual(contact.age, 40)
+ self.assertEqual(contact.distancefromstart, 10)
+ self.assertEqual(contact.motionangle, 0)
+ self.assertEqual(contact.motionvec, (10,0))
+ self.assertEqual(contact.distancetravelled, 10)
+ self.assertEqual(contact.events[-1].pos, event.pos)
+ self.assert_(len(contact.events) > 1)
+ self.numContactCallbacks += 1
+
+ def onUp(event):
+ contact = event.contact
+ self.assertEqual(event.cursorid, contact.id)
+ self.assertEqual(contact.age, 80)
+ self.assertEqual(contact.distancefromstart, 0)
+ self.assertEqual(contact.motionangle, 0)
+ self.assertEqual(contact.motionvec, (0,0))
+ self.assertEqual(contact.distancetravelled, 20)
+ self.assertEqual(contact.events[-1].pos, event.pos)
+ self.assert_(len(contact.events) > 1)
+ self.numContactCallbacks += 1
+
+ def onMotionSubscribe(event):
+ self.motionCalled = True
+
+ def onUpSubscribe(event):
+ self.upCalled = True
+
+ def onOver(event):
+ self.numOverCallbacks += 1
+ self.assertEqual(event.cursorid, event.contact.id)
+
+ def onOut(event):
+ self.numOutCallbacks += 1
+ self.assertEqual(event.cursorid, event.contact.id)
+
+ root = self.loadEmptyScene()
+ root.subscribe(avg.Node.CURSOR_DOWN, onDown)
+ self.numContactCallbacks = 0
+ rect = avg.RectNode(pos=(5,5), size=(10,10), parent=root)
+ rect.subscribe(avg.Node.CURSOR_OVER, onOver)
+ self.numOverCallbacks = 0
+ rect.subscribe(avg.Node.CURSOR_OUT, onOut)
+ self.numOutCallbacks = 0
+ player.setFakeFPS(25)
+ self.motionCalled = False
+ self.upCalled = False
+ self.start(False,
+ (lambda: self._sendTouchEvent(1, avg.Event.CURSOR_DOWN, 10, 10),
+ lambda: self._sendTouchEvent(1, avg.Event.CURSOR_MOTION, 20, 10),
+ lambda: self._sendTouchEvent(1, avg.Event.CURSOR_UP, 10, 10),
+ ))
+ self.assertEqual(self.numContactCallbacks, 2)
+ self.assertEqual(self.numOverCallbacks, 2)
+ self.assertEqual(self.numOutCallbacks, 2)
+ self.assert_(self.motionCalled and self.upCalled)
+
+ root = self.loadEmptyScene()
+ root.subscribe(avg.Node.CURSOR_DOWN, onDown)
+ self.numContactCallbacks = 0
+ self.start(False,
+ (lambda: self._sendMouseEvent(avg.Event.CURSOR_DOWN, 10, 10),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_MOTION, 20, 10),
+ lambda: self._sendMouseEvent(avg.Event.CURSOR_UP, 10, 10),
+ ))
+ self.assertEqual(self.numContactCallbacks, 2)
+
+ def testContactRegistration(self):
+
+ def onDown(event):
+ root.setEventCapture(event.cursorid)
+ root.releaseEventCapture(event.cursorid)
+
+ def onMotion(event):
+ contact = event.contact
+ self.contactID = contact.subscribe(avg.Contact.CURSOR_MOTION, onContactMotion)
+ self.numMotionCallbacks += 1
+ root.unsubscribe(avg.Node.CURSOR_DOWN, onDown)
+ root.unsubscribe(avg.Node.CURSOR_MOTION, onMotion)
+
+ def onContactMotion(event):
+ contact = event.contact
+ contact.unsubscribe(self.contactID)
+ self.assertException(lambda: contact.unsubscribe(self.contactID))
+ self.numContactCallbacks += 1
+
+ root = self.loadEmptyScene()
+ root.subscribe(avg.Node.CURSOR_DOWN, onDown)
+ self.numMotionCallbacks = 0
+ root.subscribe(avg.Node.CURSOR_MOTION, onMotion)
+ self.numContactCallbacks = 0
+ player.setFakeFPS(25)
+ self.start(False,
+ (lambda: self._sendTouchEvent(1, avg.Event.CURSOR_DOWN, 10, 10),
+ lambda: self._sendTouchEvent(1, avg.Event.CURSOR_MOTION, 20, 10),
+ lambda: self._sendTouchEvent(1, avg.Event.CURSOR_MOTION, 30, 10),
+ lambda: self._sendTouchEvent(1, avg.Event.CURSOR_MOTION, 40, 10),
+ ))
+ self.assertEqual(self.numContactCallbacks, 1)
+ self.assertEqual(self.numMotionCallbacks, 1)
+
+ def testMultiContactRegistration(self):
+
+ def onDown(event):
+ contact = event.contact
+ self.motionListenerID = contact.subscribe(avg.Contact.CURSOR_MOTION, onContact2)
+ self.upListenerID = contact.subscribe(avg.Contact.CURSOR_UP, onContact2)
+ contact.subscribe(avg.Contact.CURSOR_MOTION, onContact1)
+ contact.subscribe(avg.Contact.CURSOR_UP, onContact1)
+
+ def onContact1(event):
+ if self.numContact1Callbacks == 0:
+ event.contact.unsubscribe(self.motionListenerID)
+ event.contact.unsubscribe(self.upListenerID)
+ self.numContact1Callbacks += 1
+
+ def onContact2(event):
+ self.assertEqual(self.numContact1Callbacks, 0)
+ self.numContact2Callbacks += 1
+
+ root = self.loadEmptyScene()
+ root.subscribe(avg.Node.CURSOR_DOWN, onDown)
+ player.setFakeFPS(25)
+ self.numContact1Callbacks = 0
+ self.numContact2Callbacks = 0
+ self.start(False,
+ (lambda: self._sendTouchEvent(1, avg.Event.CURSOR_DOWN, 10, 10),
+ lambda: self._sendTouchEvent(1, avg.Event.CURSOR_MOTION, 20, 10),
+ lambda: self._sendTouchEvent(1, avg.Event.CURSOR_UP, 10, 10),
+ ))
+ self.assertEqual(self.numContact1Callbacks, 2)
+ # The order of callbacks is unspecified, so onContact2 might be called once.
+ self.assert_(self.numContact2Callbacks <= 1)
+
+ def testPlaybackMessages(self):
+
+ self.loadEmptyScene()
+ messageTester = MessageTester(player,
+ [avg.Player.PLAYBACK_START, avg.Player.PLAYBACK_END], self)
+ self.start(False,
+ (lambda: messageTester.assertState([avg.Player.PLAYBACK_START]),
+ ))
+ messageTester.assertState([avg.Player.PLAYBACK_END])
+
+ def testImageSizeChanged(self):
+ def onResize(newSize):
+ self.assert_(newSize == self.sizeExpected)
+ self.messageReceived = True
+
+ def changeHref():
+ self.messageReceived = False
+ self.sizeExpected = (32,32)
+ self.image.href="rgb24-32x32.png"
+ self.assert_(self.messageReceived)
+
+ def explicitChangeSize():
+ self.messageReceived = False
+ self.sizeExpected = (64,64)
+ self.image.size = self.sizeExpected
+ self.assert_(self.messageReceived)
+
+ def changeWidth():
+ self.messageReceived = False
+ self.sizeExpected = (32,64)
+ self.image.width = 32
+ self.assert_(self.messageReceived)
+
+ def move():
+ self.messageReceived = False
+ self.image.x = 4
+ self.assert_(not(self.messageReceived))
+
+ root = self.loadEmptyScene()
+ self.image = avg.ImageNode(href="rgb24-64x64.png", parent=root)
+ self.image.subscribe(avg.AreaNode.SIZE_CHANGED, onResize)
+ self.sizeExpected = (64, 64)
+ self.start(False,
+ (changeHref,
+ explicitChangeSize,
+ changeWidth,
+ move,
+ ))
+
+ def testWordsSizeChanged(self):
+ def onResize(newSize):
+ self.messageReceived = True
+
+ def checkMessageReceived():
+ self.assert_(self.messageReceived)
+ self.messageReceived = False
+
+ def changeText():
+ self.words.text="NewText"
+ checkMessageReceived()
+
+ self.messageReceived = False
+ root = self.loadEmptyScene()
+ self.words = avg.WordsNode(text="Test", parent=root)
+ self.words.subscribe(self.words.SIZE_CHANGED, onResize)
+ self.start(False,
+ (checkMessageReceived,
+ changeText,
+ ))
+
+ def testVideoSizeChanged(self):
+
+ def onResize(newSize):
+ self.messageReceived = True
+
+ self.messageReceived = False
+ root = self.loadEmptyScene()
+ self.video = avg.VideoNode(href="mpeg1-48x48.mov", parent=root)
+ self.video.subscribe(self.video.SIZE_CHANGED, onResize)
+ self.video.play()
+ self.assert_(self.messageReceived)
+
+ def testRectSizeChanged(self):
+
+ def onResize(newSize):
+ self.messageReceived = True
+
+ self.messageReceived = False
+ root = self.loadEmptyScene()
+ self.rect = avg.RectNode(size=(10,10), parent=root)
+ self.rect.subscribe(self.rect.SIZE_CHANGED, onResize)
+ self.rect.size=(100,100)
+ self.assert_(self.messageReceived)
+
+
+def eventTestSuite(tests):
+ availableTests = (
+ "testKeyEvents",
+ "testSimpleEvents",
+ "testTilted",
+ "testWordsClicks",
+ "testDivEvents",
+ "testDivNegativePos",
+ "testUnlinkInHandler",
+ "testConnectHandler",
+ "testPublisher",
+ "testComplexPublisher",
+ "testPublisherAutoDelete",
+ "testPublisherNestedUnsubscribe",
+ "testObscuringEvents",
+ "testSensitive",
+ "testChangingHandlers",
+ "testEventCapture",
+ "testMouseOver",
+ "testMouseDisable",
+ "testEventErr",
+ "testEventHook",
+ "testException",
+ "testContacts",
+ "testContactRegistration",
+ "testMultiContactRegistration",
+ "testPlaybackMessages",
+ "testImageSizeChanged",
+ "testWordsSizeChanged",
+ "testVideoSizeChanged",
+ "testRectSizeChanged",
+ )
+ return createAVGTestSuite(availableTests, EventTestCase, tests)
+
+Helper = player.getTestHelper()