1st person camera, "free view" style

I combined several code snippets I could find and came up with my “own” version of a mouse look class. It seems to work fine. The problem I have is when looking using mouse up/down and left/right together the camera starts to rotate and I don’t know why. Maybe someone of you knows?

The class:

from pandac.PandaModules import * 
from direct.task import Task 
from direct.showbase.DirectObject import DirectObject 

class MouseLook (DirectObject):
	"""
	simple camera mouse look and WASD key control
	r and f keys move camera up/down
	q and e keys rotate camera	
	hit enter to start/stop controls
	"""

	def __init__(self,camera):
	
		self.camera  = camera
		self.running = False
		self.time    = 0
		self.centX   = base.win.getProperties().getXSize()/2
		self.centY   = base.win.getProperties().getYSize()/2

		# key controls
		self.forward   = False 
		self.backward  = False 
		self.left      = False 
		self.right     = False 
		self.up        = False 
		self.down      = False 
		self.up        = False 
		self.down      = False 
		self.rollLeft  = False 
		self.rollRight = False 

		# sensitivity settings
		self.movSens  = 2
		self.rollSens = 50
		self.sensX = self.sensY = 0.2		
		
		self.accept("enter",self.toggle) 			

	# camera rotation task 
	def cameraTask(self,task):
		dt = task.time - self.time
		
		# handle mouse look
		md = base.win.getPointer(0) 	   
		x = md.getX() 
		y = md.getY() 
		
		if base.win.movePointer(0, self.centX, self.centY):	
			self.camera.setH(self.camera,self.camera.getH(self.camera) - (x - self.centX) * self.sensX)
			self.camera.setP(self.camera,self.camera.getP(self.camera) - (y - self.centY) * self.sensY)		

		# handle keys:

		if self.forward == True: 
			self.camera.setY(self.camera, self.camera.getY(self.camera) + self.movSens*dt) 
		if self.backward == True: 
			self.camera.setY(self.camera, self.camera.getY(self.camera) - self.movSens*dt) 
		if self.left == True: 
			self.camera.setX(self.camera, self.camera.getX(self.camera) - self.movSens*dt) 
		if self.right == True: 
			self.camera.setX(self.camera, self.camera.getX(self.camera) + self.movSens*dt) 
		if self.up == True: 
			self.camera.setZ(self.camera, self.camera.getZ(self.camera) + self.movSens*dt) 
		if self.down == True: 
			self.camera.setZ(self.camera, self.camera.getZ(self.camera) - self.movSens*dt) 			
		if self.rollLeft == True: 
			self.camera.setR(self.camera, self.camera.getR(self.camera) - self.rollSens*dt) 
		if self.rollRight == True: 
			self.camera.setR(self.camera, self.camera.getR(self.camera) + self.rollSens*dt) 
			
		self.time = task.time		
		return task.cont 

	def start(self):	
		base.disableMouse() 
		# hide mouse cursor, comment these 3 lines to see the cursor 
		props = WindowProperties() 
		props.setCursorHidden(True) 
		base.win.requestProperties(props) 
		# reset mouse to start position:
		base.win.movePointer(0, self.centX, self.centY)				
		taskMgr.add(self.cameraTask, 'HxMouseLook::cameraTask') 		
		#Task for changing direction/position 
		self.accept("w",setattr,[self,"forward",True]) 
		self.accept("w-up",setattr,[self,"forward",False]) 
		self.accept("s",setattr,[self,"backward",True]) 
		self.accept("s-up",setattr,[self,"backward",False]) 
		self.accept("a",setattr,[self,"left",True]) 
		self.accept("a-up",setattr,[self,"left",False]) 
		self.accept("d",setattr,[self,"right",True]) 
		self.accept("d-up",setattr,[self,"right",False]) 
		self.accept("r",setattr,[self,"up",True]) 
		self.accept("r-up",setattr,[self,"up",False]) 
		self.accept("f",setattr,[self,"down",True]) 
		self.accept("f-up",setattr,[self,"down",False]) 
		self.accept("q",setattr,[self,"rollLeft",True]) 
		self.accept("q-up",setattr,[self,"rollLeft",False]) 
		self.accept("e",setattr,[self,"rollRight",True]) 
		self.accept("e-up",setattr,[self,"rollRight",False]) 
		
	def stop(self):
		taskMgr.remove("HxMouseLook::cameraTask") 

		base.enableMouse()
		props = WindowProperties() 
		props.setCursorHidden(False) 
		base.win.requestProperties(props) 		
		
		self.forward  = False 
		self.backward = False 
		self.left     = False 
		self.right    = False 
		self.up       = False 
		self.down     = False 
		self.rollLeft = False 

		self.ignore("w") 
		self.ignore("w-up") 
		self.ignore("s") 
		self.ignore("s-up") 
		self.ignore("a") 
		self.ignore("a-up") 
		self.ignore("d") 
		self.ignore("d-up") 
		self.ignore("r") 
		self.ignore("r-up") 
		self.ignore("f") 
		self.ignore("f-up") 
		self.ignore("q") 
		self.ignore("q-up") 
		self.ignore("e") 
		self.ignore("e-up") 				
		
	#call to stop control system 
	def toggle(self): 
		if(self.running):
			self.stop()
			self.running=False
		else:
			self.start() 
			self.running=True

Example of usage:

from direct.showbase.ShowBase import ShowBase
from MouseLook import *
 
class MyApp(ShowBase):

	def __init__(self):
		ShowBase.__init__(self)

		# Load the environment model.
		self.environ = self.loader.loadModel("models/environment")
		# Reparent the model to render.
		self.environ.reparentTo(self.render)
		# Apply scale and position transforms on the model.
		self.environ.setScale(0.25, 0.25, 0.25)
		self.environ.setPos(-8, 42, 0)
		
		self.mouseLook = MouseLook(base.cam)


app = MyApp()
app.run()