예제 #1
0
파일: event.cpp 프로젝트: N02775223/scummvm
SciEvent EventManager::getScummVMEvent() {
	SciEvent input = { SCI_EVENT_NONE, 0, 0, 0, Common::Point(0, 0) };
	SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, 0, Common::Point(0, 0) };

	Common::EventManager *em = g_system->getEventManager();
	Common::Event ev;

	bool found = em->pollEvent(ev);

	// Don't generate events for mouse movement
	while (found && ev.type == Common::EVENT_MOUSEMOVE)
		found = em->pollEvent(ev);

	// Save the mouse position
	//
	// We call getMousePos of the event manager here, since we also want to
	// store the mouse position in case of keyboard events, which do not feature
	// any mouse position information itself.
	// This should be safe, since the mouse position in the event manager should
	// only be updated when a mouse related event has been taken from the queue
	// via pollEvent.
	// We also adjust the position based on the scaling of the screen.
	Common::Point mousePos = em->getMousePos();
	g_sci->_gfxScreen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x);

	noEvent.mousePos = input.mousePos = mousePos;

	if (!found || ev.type == Common::EVENT_MOUSEMOVE) {
		int modifiers = em->getModifierState();
		noEvent.modifiers =
			((modifiers & Common::KBD_ALT) ? SCI_KEYMOD_ALT : 0) |
			((modifiers & Common::KBD_CTRL) ? SCI_KEYMOD_CTRL : 0) |
			((modifiers & Common::KBD_SHIFT) ? SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT : 0);

		return noEvent;
	}
	if (ev.type == Common::EVENT_QUIT) {
		input.type = SCI_EVENT_QUIT;
		return input;
	}

	// Handle mouse events
	for (int i = 0; i < ARRAYSIZE(mouseEventMappings); i++) {
		if (mouseEventMappings[i].commonType == ev.type) {
			input.type = mouseEventMappings[i].sciType;
			input.data = mouseEventMappings[i].data;
			return input;
		}
	}

	// If we reached here, make sure that it's a keydown event
	if (ev.type != Common::EVENT_KEYDOWN)
		return noEvent;

	// Check for Control-D (debug console)
	if (ev.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_SHIFT) && ev.kbd.keycode == Common::KEYCODE_d) {
		// Open debug console
		Console *con = g_sci->getSciDebugger();
		con->attach();
		return noEvent;
	}

	// Process keyboard events

	int modifiers = em->getModifierState();
	bool numlockOn = (ev.kbd.flags & Common::KBD_NUM);

	input.data = ev.kbd.keycode;
	input.character = ev.kbd.ascii;
	input.type = SCI_EVENT_KEYBOARD;

	input.modifiers =
		((modifiers & Common::KBD_ALT) ? SCI_KEYMOD_ALT : 0) |
		((modifiers & Common::KBD_CTRL) ? SCI_KEYMOD_CTRL : 0) |
		((modifiers & Common::KBD_SHIFT) ? SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT : 0);

	// Caps lock and Scroll lock have been removed, cause we already handle upper
	// case keys ad Scroll lock doesn't seem to be used anywhere
		//((ev.kbd.flags & Common::KBD_CAPS) ? SCI_KEYMOD_CAPSLOCK : 0) |
		//((ev.kbd.flags & Common::KBD_SCRL) ? SCI_KEYMOD_SCRLOCK : 0) |

	if ((input.character) && (input.character <= 0xFF)) {
		// Directly accept most common keys without conversion
		if ((input.character >= 0x80) && (input.character <= 0xFF)) {
			// If there is no extended font, we will just clear the
			// current event.
			// Sierra SCI actually accepted those characters, but
			// didn't display them inside text edit controls because
			// the characters were missing inside the font(s).
			// We filter them out for non-multilingual games because
			// of that.
			if (!_fontIsExtended)
				return noEvent;
			// Convert 8859-1 characters to DOS (cp850/437) for
			// multilingual SCI01 games
			input.character = codepagemap_88591toDOS[input.character & 0x7f];
		}
		if (input.data == Common::KEYCODE_TAB) {
			input.character = input.data = SCI_KEY_TAB;
			if (modifiers & Common::KBD_SHIFT)
				input.character = SCI_KEY_SHIFT_TAB;
		}
		if (input.data == Common::KEYCODE_DELETE)
			input.data = input.character = SCI_KEY_DELETE;
	} else if ((input.data >= Common::KEYCODE_F1) && input.data <= Common::KEYCODE_F10) {
		// SCI_K_F1 == 59 << 8
		// SCI_K_SHIFT_F1 == 84 << 8
		input.character = input.data = SCI_KEY_F1 + ((input.data - Common::KEYCODE_F1)<<8);
		if (modifiers & Common::KBD_SHIFT)
			input.character = input.data + 0x1900;
	} else {
		// Special keys that need conversion
		for (int i = 0; i < ARRAYSIZE(keyMappings); i++) {
			if (keyMappings[i].scummVMKey == ev.kbd.keycode) {
				input.character = input.data = numlockOn ? keyMappings[i].sciKeyNumlockOn : keyMappings[i].sciKeyNumlockOff;
				break;
			}
		}
	}

	// When Ctrl AND Alt are pressed together with a regular key, Linux will give us control-key, Windows will give
	//  us the actual key. My opinion is that windows is right, because under DOS the keys worked the same, anyway
	//  we support the other case as well
	if ((modifiers & Common::KBD_ALT) && input.character > 0 && input.character < 27)
		input.character += 96; // 0x01 -> 'a'

	// Scancodify if appropriate
	if (modifiers & Common::KBD_ALT)
		input.character = altify(input.character);
	if (getSciVersion() <= SCI_VERSION_1_MIDDLE && (modifiers & Common::KBD_CTRL) && input.character > 0 && input.character < 27)
		input.character += 96; // 0x01 -> 'a'

	// If no actual key was pressed (e.g. if only a modifier key was pressed),
	// ignore the event
	if (!input.character)
		return noEvent;

	return input;
}
예제 #2
0
TestExitStatus EventTests::mouseEvents() {

	Testsuite::clearScreen();
	Common::String info = "Testing Mouse events.\n "
	"Any movement/click generated by L/R/M mouse buttons or the mouse wheel should be detected.\n"
	"Press X to exit";

	if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) {
		Testsuite::logPrintf("Info! Skipping test : keyboard events\n");
		return kTestSkipped;
	}

	Common::EventManager *eventMan = g_system->getEventManager();

	Common::Point pt(0, 30);
	Common::Rect rectInfo = Testsuite::writeOnScreen("Generate mouse events make L/R/M button clicks, move wheel", pt);
	pt.y += 15;
	Testsuite::writeOnScreen("Press X to exit", pt);
	pt.y = 70;
	Common::Rect rectLB = Testsuite::writeOnScreen("Left-button click : Not tested", pt);
	pt.y += 15;
	Common::Rect rectRB = Testsuite::writeOnScreen("Right-button click : Not tested", pt);
	pt.y += 15;
	Common::Rect rectMB = Testsuite::writeOnScreen("Middle-button click : Not tested", pt);
	pt.y += 15;
	Common::Rect rectWheel = Testsuite::writeOnScreen("Wheel Movements : Not tested", pt);


	// Init Mouse Palette
	GFXtests::initMousePalette();
	Common::Rect finishZone = drawFinishZone();

	bool quitLoop = false;
	TestExitStatus passed = kTestPassed;
	// handle all mouse events
	Common::Event event;
	while (!quitLoop) {
		// Show mouse
		CursorMan.showMouse(true);
		g_system->updateScreen();

		while (eventMan->pollEvent(event)) {
			// Quit if explicitly requested
			if (Engine::shouldQuit()) {
				return passed;
			}
			switch (event.type) {
			case Common::EVENT_MOUSEMOVE:
				// Movements havee already been tested in GFX
				break;
			case Common::EVENT_LBUTTONDOWN:
				Testsuite::clearScreen(rectInfo);
				Testsuite::writeOnScreen("Mouse left-button pressed", Common::Point(rectInfo.left, rectInfo.top));
				break;
			case Common::EVENT_RBUTTONDOWN:
				Testsuite::clearScreen(rectInfo);
				Testsuite::writeOnScreen("Mouse right-button pressed", Common::Point(rectInfo.left, rectInfo.top));
				break;
			case Common::EVENT_WHEELDOWN:
				Testsuite::clearScreen(rectInfo);
				Testsuite::writeOnScreen("Mouse wheel moved down", Common::Point(rectInfo.left, rectInfo.top));
				Testsuite::writeOnScreen("Wheel Movements : Done!", Common::Point(rectWheel.left, rectWheel.top));
				break;
			case Common::EVENT_MBUTTONDOWN:
				Testsuite::clearScreen(rectInfo);
				Testsuite::writeOnScreen("Mouse middle-button pressed ", Common::Point(rectInfo.left, rectInfo.top));
				break;
			case Common::EVENT_LBUTTONUP:
				Testsuite::clearScreen(rectInfo);
				if (finishZone.contains(eventMan->getMousePos())) {
					quitLoop = true;
				}
				Testsuite::writeOnScreen("Mouse left-button released", Common::Point(rectInfo.left, rectInfo.top));
				Testsuite::writeOnScreen("Left-button clicks : Done!", Common::Point(rectLB.left, rectLB.top));
				break;
			case Common::EVENT_RBUTTONUP:
				Testsuite::clearScreen(rectInfo);
				Testsuite::writeOnScreen("Mouse right-button released", Common::Point(rectInfo.left, rectInfo.top));
				Testsuite::writeOnScreen("Right-button clicks : Done!", Common::Point(rectRB.left, rectRB.top));
				break;
			case Common::EVENT_WHEELUP:
				Testsuite::clearScreen(rectInfo);
				Testsuite::writeOnScreen("Mouse wheel moved up", Common::Point(rectInfo.left, rectInfo.top));
				Testsuite::writeOnScreen("Wheel Movements : Done!", Common::Point(rectWheel.left, rectWheel.top));
				break;
			case Common::EVENT_MBUTTONUP:
				Testsuite::clearScreen(rectInfo);
				Testsuite::writeOnScreen("Mouse middle-button released ", Common::Point(rectInfo.left, rectInfo.top));
				Testsuite::writeOnScreen("Middle-button clicks : Done!", Common::Point(rectMB.left, rectMB.top));
				break;
			case Common::EVENT_KEYDOWN:
				if (event.kbd.keycode == Common::KEYCODE_x) {
					Testsuite::clearScreen(rectInfo);
					Testsuite::writeOnScreen("Exit requested", Common::Point(rectInfo.left, rectInfo.top));
					quitLoop = true;
				}
				break;
			default:
				break;
			}

		}
	}

	CursorMan.showMouse(false);

	// Verify results now!
	if (Testsuite::handleInteractiveInput("Were mouse clicks (L/R/M buttons) and wheel movements identfied ?", "Yes", "No", kOptionRight)) {
		Testsuite::logDetailedPrintf("Mouse clicks (L/R/M buttons) and wheel movements failed");
		passed = kTestFailed;
	}

	return passed;
}
예제 #3
0
파일: event.cpp 프로젝트: Cruel/scummvm
SciEvent EventManager::getScummVMEvent() {
#ifdef ENABLE_SCI32
	SciEvent input = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point() };
	SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point() };
#else
	SciEvent input = { SCI_EVENT_NONE, 0, 0, Common::Point() };
	SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, Common::Point() };
#endif

	Common::EventManager *em = g_system->getEventManager();
	Common::Event ev;

	bool found = em->pollEvent(ev);

	// Don't generate events for mouse movement
	while (found && ev.type == Common::EVENT_MOUSEMOVE)
		found = em->pollEvent(ev);

	// Save the mouse position
	//
	// We call getMousePos of the event manager here, since we also want to
	// store the mouse position in case of keyboard events, which do not feature
	// any mouse position information itself.
	// This should be safe, since the mouse position in the event manager should
	// only be updated when a mouse related event has been taken from the queue
	// via pollEvent.
	// We also adjust the position based on the scaling of the screen.
	Common::Point mousePos = em->getMousePos();

#if ENABLE_SCI32
	if (getSciVersion() >= SCI_VERSION_2) {
		Buffer &screen = g_sci->_gfxFrameout->getCurrentBuffer();

		Common::Point mousePosSci = mousePos;
		mulru(mousePosSci, Ratio(screen.scriptWidth, screen.screenWidth), Ratio(screen.scriptHeight, screen.screenHeight));
		noEvent.mousePosSci = input.mousePosSci = mousePosSci;
	} else {
#endif
		g_sci->_gfxScreen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x);
#if ENABLE_SCI32
	}
#endif

	noEvent.mousePos = input.mousePos = mousePos;

	if (!found || ev.type == Common::EVENT_MOUSEMOVE) {
		int modifiers = em->getModifierState();
		noEvent.modifiers =
			((modifiers & Common::KBD_ALT) ? SCI_KEYMOD_ALT : 0) |
			((modifiers & Common::KBD_CTRL) ? SCI_KEYMOD_CTRL : 0) |
			((modifiers & Common::KBD_SHIFT) ? SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT : 0);

		return noEvent;
	}
	if (ev.type == Common::EVENT_QUIT) {
		input.type = SCI_EVENT_QUIT;
		return input;
	}

	int scummVMKeyFlags;

	switch (ev.type) {
	case Common::EVENT_KEYDOWN:
	case Common::EVENT_KEYUP:
		// Use keyboard modifiers directly in case this is a keyboard event
		scummVMKeyFlags = ev.kbd.flags;
		break;
	default:
		// Otherwise get them from EventManager
		scummVMKeyFlags = em->getModifierState();
		break;
	}

	input.modifiers =
		((scummVMKeyFlags & Common::KBD_ALT) ? SCI_KEYMOD_ALT : 0) |
		((scummVMKeyFlags & Common::KBD_CTRL) ? SCI_KEYMOD_CTRL : 0) |
		((scummVMKeyFlags & Common::KBD_SHIFT) ? SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT : 0);
		// Caps lock and Scroll lock have been removed, cause we already handle upper
		// case keys and Scroll lock doesn't seem to be used anywhere
		//((ourModifiers & Common::KBD_CAPS) ? SCI_KEYMOD_CAPSLOCK : 0) |
		//((ourModifiers & Common::KBD_SCRL) ? SCI_KEYMOD_SCRLOCK : 0) |

	// Handle mouse events
	for (int i = 0; i < ARRAYSIZE(mouseEventMappings); i++) {
		if (mouseEventMappings[i].commonType == ev.type) {
			input.type = mouseEventMappings[i].sciType;
			// Sierra passed keyboard modifiers for mouse events, too.

			// Sierra also set certain modifiers within their mouse interrupt handler
			// This whole thing was probably meant for people using a mouse, that only featured 1 button
			// So the user was able to press Ctrl and click the mouse button to create a right click.
			switch (ev.type) {
			case Common::EVENT_RBUTTONDOWN: // right button
			case Common::EVENT_RBUTTONUP:
				input.modifiers |= (SCI_KEYMOD_RSHIFT | SCI_KEYMOD_LSHIFT); // this value was hardcoded in the mouse interrupt handler
				break;
			case Common::EVENT_MBUTTONDOWN: // middle button
			case Common::EVENT_MBUTTONUP:
				input.modifiers |= SCI_KEYMOD_CTRL; // this value was hardcoded in the mouse interrupt handler
				break;
			default:
				break;
			}
			return input;
		}
	}

	// If we reached here, make sure that it's a keydown event
	if (ev.type != Common::EVENT_KEYDOWN)
		return noEvent;

	// Check for Control-Shift-D (debug console)
	if (ev.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_SHIFT) && ev.kbd.keycode == Common::KEYCODE_d) {
		// Open debug console
		Console *con = g_sci->getSciDebugger();
		con->attach();
		return noEvent;
	}

	// Process keyboard events

	bool numlockOn = (ev.kbd.flags & Common::KBD_NUM);

	Common::KeyCode scummVMKeycode = ev.kbd.keycode;

	input.character = ev.kbd.ascii;
	input.type = SCI_EVENT_KEYBOARD;

	if (scummVMKeycode >= Common::KEYCODE_KP0 && scummVMKeycode <= Common::KEYCODE_KP9) {
		if (!(scummVMKeyFlags & Common::KBD_NUM)) {
			// HACK: Num-Lock not enabled
			// We shouldn't get a valid ascii code in these cases. We fix it here, so that cursor keys
			// on the numpad work properly.
			input.character = 0;
		}
	}

	if ((input.character) && (input.character <= 0xFF)) {
		// Directly accept most common keys without conversion
		if ((input.character >= 0x80) && (input.character <= 0xFF)) {
			// If there is no extended font, we will just clear the
			// current event.
			// Sierra SCI actually accepted those characters, but
			// didn't display them inside text edit controls because
			// the characters were missing inside the font(s).
			// We filter them out for non-multilingual games because
			// of that.
			if (!_fontIsExtended)
				return noEvent;
			// Convert 8859-1 characters to DOS (cp850/437) for
			// multilingual SCI01 games
			input.character = codePageMap88591ToDOS[input.character & 0x7f];
		}
		if (scummVMKeycode == Common::KEYCODE_TAB) {
			input.character = SCI_KEY_TAB;
			if (scummVMKeyFlags & Common::KBD_SHIFT)
				input.character = SCI_KEY_SHIFT_TAB;
		}
		if (scummVMKeycode == Common::KEYCODE_DELETE)
			input.character = SCI_KEY_DELETE;
	} else if ((scummVMKeycode >= Common::KEYCODE_F1) && scummVMKeycode <= Common::KEYCODE_F10) {
		// SCI_K_F1 == 59 << 8
		// SCI_K_SHIFT_F1 == 84 << 8
		if (!(scummVMKeyFlags & Common::KBD_SHIFT))
			input.character = SCI_KEY_F1 + ((scummVMKeycode - Common::KEYCODE_F1)<<8);
		else
			input.character = SCI_KEY_SHIFT_F1 + ((scummVMKeycode - Common::KEYCODE_F1)<<8);
	} else {
		// Special keys that need conversion
		for (int i = 0; i < ARRAYSIZE(keyMappings); i++) {
			if (keyMappings[i].scummVMKey == scummVMKeycode) {
				input.character = numlockOn ? keyMappings[i].sciKeyNumlockOn : keyMappings[i].sciKeyNumlockOff;
				break;
			}
		}
	}

	// When Ctrl AND Alt are pressed together with a regular key, Linux will give us control-key, Windows will give
	//  us the actual key. My opinion is that windows is right, because under DOS the keys worked the same, anyway
	//  we support the other case as well
	if ((scummVMKeyFlags & Common::KBD_ALT) && input.character > 0 && input.character < 27)
		input.character += 96; // 0x01 -> 'a'

	// Scancodify if appropriate
	if (scummVMKeyFlags & Common::KBD_ALT)
		input.character = altify(input.character);
	if (getSciVersion() <= SCI_VERSION_1_MIDDLE && (scummVMKeyFlags & Common::KBD_CTRL) && input.character > 0 && input.character < 27)
		input.character += 96; // 0x01 -> 'a'
#ifdef ENABLE_SCI32
	if (getSciVersion() >= SCI_VERSION_2 && (scummVMKeyFlags & Common::KBD_CTRL) && input.character == 'c') {
		input.character = SCI_KEY_ETX;
	}
#endif

	// If no actual key was pressed (e.g. if only a modifier key was pressed),
	// ignore the event
	if (!input.character)
		return noEvent;

	return input;
}