diff options
Diffstat (limited to 'src/test/EventTest.py')
-rw-r--r-- | src/test/EventTest.py | 1086 |
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() |