From 9722d7f55494b87ed15ed46914ef926bba7e1811 Mon Sep 17 00:00:00 2001 From: stephena Date: Thu, 26 May 2005 15:43:44 +0000 Subject: [PATCH] Added continuous key event support to the DialogContainer. That means one can hold down a key, and after a small delay, the key event will be repeated. This is much better than having to push the 'down arrow' 100 times in a large scroll box. Still TODO is handle mouse clicks in the same way. The code is there, but it's commented out. This will be much harder, since the GUI code from ScummVM wasn't designed to work that way. Removed x,y items when sending joystick events, since that information isn't available in SDL joystick motion. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@439 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- stella/src/emucore/EventHandler.cxx | 28 +++++++-- stella/src/emucore/EventHandler.hxx | 8 ++- stella/src/gui/Dialog.cxx | 10 ++-- stella/src/gui/Dialog.hxx | 8 +-- stella/src/gui/DialogContainer.cxx | 81 +++++++++++++++++++++++---- stella/src/gui/DialogContainer.hxx | 45 +++++++++++---- stella/src/gui/EventMappingDialog.cxx | 6 +- stella/src/gui/EventMappingDialog.hxx | 4 +- stella/src/gui/Widget.hxx | 8 +-- stella/src/unix/OSystemUNIX.cxx | 6 +- 10 files changed, 153 insertions(+), 51 deletions(-) diff --git a/stella/src/emucore/EventHandler.cxx b/stella/src/emucore/EventHandler.cxx index 73e1c4417..185891db9 100644 --- a/stella/src/emucore/EventHandler.cxx +++ b/stella/src/emucore/EventHandler.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: EventHandler.cxx,v 1.61 2005-05-25 23:22:11 stephena Exp $ +// $Id: EventHandler.cxx,v 1.62 2005-05-26 15:43:43 stephena Exp $ //============================================================================ #include @@ -222,7 +222,7 @@ void EventHandler::setupJoysticks() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void EventHandler::poll() +void EventHandler::poll(uInt32 time) { SDL_Event event; @@ -450,6 +450,22 @@ void EventHandler::poll() } #endif } + + // Update the current dialog container at regular intervals + // Used to implement continuous events + switch(myState) + { + case S_MENU: + myOSystem->menu().updateTime(time); + break; + + case S_LAUNCHER: + myOSystem->launcher().updateTime(time); + break; + + default: + break; + } } @@ -622,11 +638,11 @@ void EventHandler::handleKeyEvent(SDLKey key, SDLMod mod, uInt8 state) myEvent->clear(); return; } - myOSystem->menu().handleKeyEvent((uInt16) key, (Int32) mod, state); + myOSystem->menu().handleKeyEvent(key, mod, state); break; case S_LAUNCHER: - myOSystem->launcher().handleKeyEvent((uInt16) key, (Int32) mod, state); + myOSystem->launcher().handleKeyEvent(key, mod, state); break; case S_DEBUGGER: @@ -762,11 +778,11 @@ void EventHandler::handleJoyEvent(uInt8 stick, uInt32 code, uInt8 state) break; case S_MENU: - myOSystem->menu().handleJoyEvent(0, 0, stick, code, state); // FIXME - get x,y + myOSystem->menu().handleJoyEvent(stick, code, state); break; case S_LAUNCHER: - myOSystem->launcher().handleJoyEvent(0, 0, stick, code, state); // FIXME - get x,y + myOSystem->launcher().handleJoyEvent(stick, code, state); break; case S_DEBUGGER: diff --git a/stella/src/emucore/EventHandler.hxx b/stella/src/emucore/EventHandler.hxx index 3dd9db1b3..64fd0fcb3 100644 --- a/stella/src/emucore/EventHandler.hxx +++ b/stella/src/emucore/EventHandler.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: EventHandler.hxx,v 1.31 2005-05-25 23:22:11 stephena Exp $ +// $Id: EventHandler.hxx,v 1.32 2005-05-26 15:43:44 stephena Exp $ //============================================================================ #ifndef EVENTHANDLER_HXX @@ -74,7 +74,7 @@ struct Stella_Joystick { mapping can take place. @author Stephen Anthony - @version $Id: EventHandler.hxx,v 1.31 2005-05-25 23:22:11 stephena Exp $ + @version $Id: EventHandler.hxx,v 1.32 2005-05-26 15:43:44 stephena Exp $ */ class EventHandler { @@ -109,8 +109,10 @@ class EventHandler /** Collects and dispatches any pending events. This method should be called regularly (at X times per second, where X is the game framerate). + + @param time The current time in milliseconds. */ - void poll(); + void poll(uInt32 time); /** Bind a key to an event/action diff --git a/stella/src/gui/Dialog.cxx b/stella/src/gui/Dialog.cxx index 04cbf63d7..bee3f7a0f 100644 --- a/stella/src/gui/Dialog.cxx +++ b/stella/src/gui/Dialog.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: Dialog.cxx,v 1.16 2005-05-25 23:22:11 stephena Exp $ +// $Id: Dialog.cxx,v 1.17 2005-05-26 15:43:44 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -284,19 +284,19 @@ void Dialog::handleMouseMoved(int x, int y, int button) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Dialog::handleJoyDown(int x, int y, int stick, int button) +void Dialog::handleJoyDown(int stick, int button) { // Focused widget receives joystick events if(_focusedWidget) - _focusedWidget->handleJoyDown(x, y, stick, button); + _focusedWidget->handleJoyDown(stick, button); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Dialog::handleJoyUp(int x, int y, int stick, int button) +void Dialog::handleJoyUp(int stick, int button) { // Focused widget receives joystick events if(_focusedWidget) - _focusedWidget->handleJoyUp(x, y, stick, button); + _focusedWidget->handleJoyUp(stick, button); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stella/src/gui/Dialog.hxx b/stella/src/gui/Dialog.hxx index 9e7b68990..34ea28b78 100644 --- a/stella/src/gui/Dialog.hxx +++ b/stella/src/gui/Dialog.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: Dialog.hxx,v 1.14 2005-05-25 23:22:11 stephena Exp $ +// $Id: Dialog.hxx,v 1.15 2005-05-26 15:43:44 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -35,7 +35,7 @@ class DialogContainer; This is the base class for all dialog boxes. @author Stephen Anthony - @version $Id: Dialog.hxx,v 1.14 2005-05-25 23:22:11 stephena Exp $ + @version $Id: Dialog.hxx,v 1.15 2005-05-26 15:43:44 stephena Exp $ */ class Dialog : public GuiObject { @@ -68,8 +68,8 @@ class Dialog : public GuiObject virtual void handleMouseUp(int x, int y, int button, int clickCount); virtual void handleMouseWheel(int x, int y, int direction); virtual void handleMouseMoved(int x, int y, int button); - virtual void handleJoyDown(int x, int y, int stick, int button); - virtual void handleJoyUp(int x, int y, int stick, int button); + virtual void handleJoyDown(int stick, int button); + virtual void handleJoyUp(int stick, int button); virtual void handleCommand(CommandSender* sender, int cmd, int data); virtual void handleScreenChanged() {} diff --git a/stella/src/gui/DialogContainer.cxx b/stella/src/gui/DialogContainer.cxx index dfcace37a..6ab9096c5 100644 --- a/stella/src/gui/DialogContainer.cxx +++ b/stella/src/gui/DialogContainer.cxx @@ -13,21 +13,24 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: DialogContainer.cxx,v 1.6 2005-05-25 23:22:11 stephena Exp $ +// $Id: DialogContainer.cxx,v 1.7 2005-05-26 15:43:44 stephena Exp $ //============================================================================ #include "OSystem.hxx" #include "Dialog.hxx" #include "Stack.hxx" +#include "EventHandler.hxx" #include "bspf.hxx" #include "DialogContainer.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DialogContainer::DialogContainer(OSystem* osystem) : myOSystem(osystem), - myBaseDialog(NULL) + myBaseDialog(NULL), + myTime(0) { myCurrentKeyDown.keycode = 0; + myCurrentMouseDown.button = -1; myLastClick.x = myLastClick.y = 0; myLastClick.time = 0; myLastClick.count = 0; @@ -40,6 +43,36 @@ DialogContainer::~DialogContainer() delete myBaseDialog; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void DialogContainer::updateTime(uInt32 time) +{ + // We only need millisecond precision + myTime = time / 1000; + + if(myDialogStack.empty()) + return; + + // Check for pending continuous events and send them to the active dialog box + Dialog* activeDialog = myDialogStack.top(); + + if(myCurrentKeyDown.keycode != 0 && myKeyRepeatTime < myTime) + { + activeDialog->handleKeyDown(myCurrentKeyDown.ascii, myCurrentKeyDown.keycode, + myCurrentKeyDown.flags); + myKeyRepeatTime = myTime + kKeyRepeatSustainDelay; + } + +/* FIXME - there are still some problems with this code + if(myCurrentMouseDown.button != -1 && myClickRepeatTime < myTime) + { + activeDialog->handleMouseDown(myCurrentMouseDown.x - activeDialog->_x, + myCurrentMouseDown.y - activeDialog->_y, + myCurrentMouseDown.button, 1); + myClickRepeatTime = myTime + kClickRepeatSustainDelay; + } +*/ +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DialogContainer::draw() { @@ -78,6 +111,13 @@ void DialogContainer::reStack() // Now make sure all dialog boxes are in a known (closed) state myBaseDialog->reset(); + + // Reset all continuous events + myCurrentKeyDown.keycode = 0; + myCurrentMouseDown.button = -1; + myLastClick.x = myLastClick.y = 0; + myLastClick.time = 0; + myLastClick.count = 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -89,9 +129,22 @@ void DialogContainer::handleKeyEvent(int key, int mod, uInt8 state) // Send the event to the dialog box on the top of the stack Dialog* activeDialog = myDialogStack.top(); if(state == 1) + { + myCurrentKeyDown.ascii = key; + myCurrentKeyDown.keycode = key; + myCurrentKeyDown.flags = mod; + myKeyRepeatTime = myTime + kKeyRepeatInitialDelay; + activeDialog->handleKeyDown(key, key, mod); + } else + { activeDialog->handleKeyUp(key, key, mod); + + // Only stop firing events if it's the current key + if (key == myCurrentKeyDown.keycode) + myCurrentKeyDown.keycode = 0; + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -116,9 +169,6 @@ void DialogContainer::handleMouseButtonEvent(MouseButton b, int x, int y, uInt8 // Send the event to the dialog box on the top of the stack Dialog* activeDialog = myDialogStack.top(); - // Get the current time for detecting double clicks - int time = myOSystem->getTicks() / 1000; // we only need millisecond precision - switch(b) { case EVENT_LBUTTONDOWN: @@ -131,7 +181,7 @@ void DialogContainer::handleMouseButtonEvent(MouseButton b, int x, int y, uInt8 myLastClick.count = 0; } - if(myLastClick.count && (time < myLastClick.time + 500) // DoubleClickDelay + if(myLastClick.count && (myTime < myLastClick.time + kDoubleClickDelay) && ABS(myLastClick.x - x) < 3 && ABS(myLastClick.y - y) < 3) { @@ -143,7 +193,14 @@ void DialogContainer::handleMouseButtonEvent(MouseButton b, int x, int y, uInt8 myLastClick.y = y; myLastClick.count = 1; } - myLastClick.time = time; + myLastClick.time = myTime; + + // Now account for repeated mouse events (click and hold) + myCurrentMouseDown.x = x; + myCurrentMouseDown.y = y; + myCurrentMouseDown.button = 1; // in the future, we may differentiate buttons + myClickRepeatTime = myTime + kClickRepeatInitialDelay; + activeDialog->handleMouseDown(x - activeDialog->_x, y - activeDialog->_y, 1, myLastClick.count); break; @@ -152,6 +209,9 @@ void DialogContainer::handleMouseButtonEvent(MouseButton b, int x, int y, uInt8 case EVENT_RBUTTONUP: activeDialog->handleMouseUp(x - activeDialog->_x, y - activeDialog->_y, 1, myLastClick.count); + // Since all buttons are treated equally, we don't need to check which button + //if (button == myCurrentClickDown.button) + myCurrentMouseDown.button = -1; break; case EVENT_WHEELUP: @@ -165,8 +225,7 @@ void DialogContainer::handleMouseButtonEvent(MouseButton b, int x, int y, uInt8 } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void DialogContainer::handleJoyEvent(int x, int y, int stick, int button, - uInt8 state) +void DialogContainer::handleJoyEvent(int stick, int button, uInt8 state) { if(myDialogStack.empty()) return; @@ -174,7 +233,7 @@ void DialogContainer::handleJoyEvent(int x, int y, int stick, int button, // Send the event to the dialog box on the top of the stack Dialog* activeDialog = myDialogStack.top(); if(state == 1) - activeDialog->handleJoyDown(x, y, stick, button); + activeDialog->handleJoyDown(stick, button); else - activeDialog->handleJoyUp(x, y, stick, button); + activeDialog->handleJoyUp(stick, button); } diff --git a/stella/src/gui/DialogContainer.hxx b/stella/src/gui/DialogContainer.hxx index a69408b1a..eb75b9362 100644 --- a/stella/src/gui/DialogContainer.hxx +++ b/stella/src/gui/DialogContainer.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: DialogContainer.hxx,v 1.3 2005-05-25 23:22:11 stephena Exp $ +// $Id: DialogContainer.hxx,v 1.4 2005-05-26 15:43:44 stephena Exp $ //============================================================================ #ifndef DIALOG_CONTAINER_HXX @@ -37,7 +37,7 @@ typedef FixedStack DialogStack; a stack, and handles their events. @author Stephen Anthony - @version $Id: DialogContainer.hxx,v 1.3 2005-05-25 23:22:11 stephena Exp $ + @version $Id: DialogContainer.hxx,v 1.4 2005-05-26 15:43:44 stephena Exp $ */ class DialogContainer { @@ -53,6 +53,14 @@ class DialogContainer virtual ~DialogContainer(); public: + /** + Update the dialog container with the current time. + This is useful if we want to trigger events at some specified time. + + @param time The current time in microseconds + */ + void updateTime(uInt32 time); + /** Handle a keyboard event. @@ -84,13 +92,11 @@ class DialogContainer /** Handle a joystick button event. - @param x The x location - @param y The y location @param stick The joystick number @param button The joystick button @param state The state (pressed or released) */ - void handleJoyEvent(int x, int y, int stick, int button, uInt8 state); + void handleJoyEvent(int stick, int button, uInt8 state); /** Draw the stack of menus. @@ -123,19 +129,38 @@ class DialogContainer Dialog* myBaseDialog; DialogStack myDialogStack; + enum { + kDoubleClickDelay = 500, + kKeyRepeatInitialDelay = 400, + kKeyRepeatSustainDelay = 50, + kClickRepeatInitialDelay = kKeyRepeatInitialDelay, + kClickRepeatSustainDelay = kKeyRepeatSustainDelay + }; + + // Indicates the most current time (in milliseconds) as set by updateTime() + uInt32 myTime; + // For continuous events (keyDown) struct { int ascii; - uInt8 flags; int keycode; + uInt8 flags; } myCurrentKeyDown; - int myKeyRepeatTime; + uInt32 myKeyRepeatTime; + + // For continuous events (mouseDown) + struct { + int x; + int y; + int button; + } myCurrentMouseDown; + uInt32 myClickRepeatTime; // Position and time of last mouse click (used to detect double clicks) struct { - int x, y; // Position of mouse when the click occured - int time; // Time - int count; // How often was it already pressed? + int x, y; // Position of mouse when the click occured + uInt32 time; // Time + int count; // How often was it already pressed? } myLastClick; }; diff --git a/stella/src/gui/EventMappingDialog.cxx b/stella/src/gui/EventMappingDialog.cxx index 93a6ee19f..a5c9e9699 100644 --- a/stella/src/gui/EventMappingDialog.cxx +++ b/stella/src/gui/EventMappingDialog.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: EventMappingDialog.cxx,v 1.11 2005-05-25 23:22:11 stephena Exp $ +// $Id: EventMappingDialog.cxx,v 1.12 2005-05-26 15:43:44 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -191,7 +191,7 @@ void EventMappingDialog::handleKeyDown(int ascii, int keycode, int modifiers) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void EventMappingDialog::handleJoyDown(int x, int y, int stick, int button) +void EventMappingDialog::handleJoyDown(int stick, int button) { // Remap joystick buttons in remap mode, otherwise pass to listwidget if(myRemapStatus && myActionSelected >= 0) @@ -202,7 +202,7 @@ void EventMappingDialog::handleJoyDown(int x, int y, int stick, int button) stopRemapping(); } else - myActionsList->handleJoyDown(x, y, stick, button); + myActionsList->handleJoyDown(stick, button); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stella/src/gui/EventMappingDialog.hxx b/stella/src/gui/EventMappingDialog.hxx index e35354920..c1d3d3049 100644 --- a/stella/src/gui/EventMappingDialog.hxx +++ b/stella/src/gui/EventMappingDialog.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: EventMappingDialog.hxx,v 1.8 2005-05-25 23:22:11 stephena Exp $ +// $Id: EventMappingDialog.hxx,v 1.9 2005-05-26 15:43:44 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -40,7 +40,7 @@ class EventMappingDialog : public Dialog ~EventMappingDialog(); virtual void handleKeyDown(int ascii, int keycode, int modifiers); - virtual void handleJoyDown(int x, int y, int stick, int button); + virtual void handleJoyDown(int stick, int button); protected: ButtonWidget* myMapButton; diff --git a/stella/src/gui/Widget.hxx b/stella/src/gui/Widget.hxx index cb8df9e4a..1172337b6 100644 --- a/stella/src/gui/Widget.hxx +++ b/stella/src/gui/Widget.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: Widget.hxx,v 1.12 2005-05-25 23:22:11 stephena Exp $ +// $Id: Widget.hxx,v 1.13 2005-05-26 15:43:44 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -65,7 +65,7 @@ enum { This is the base class for all widgets. @author Stephen Anthony - @version $Id: Widget.hxx,v 1.12 2005-05-25 23:22:11 stephena Exp $ + @version $Id: Widget.hxx,v 1.13 2005-05-26 15:43:44 stephena Exp $ */ class Widget : public GuiObject { @@ -86,8 +86,8 @@ class Widget : public GuiObject virtual void handleMouseWheel(int x, int y, int direction) {} virtual bool handleKeyDown(int ascii, int keycode, int modifiers) { return false; } virtual bool handleKeyUp(int ascii, int keycode, int modifiers) { return false; } - virtual void handleJoyDown(int x, int y, int stick, int button) {} - virtual void handleJoyUp(int x, int y, int stick, int button) {} + virtual void handleJoyDown(int stick, int button) {} + virtual void handleJoyUp(int stick, int button) {} virtual void handleTickle() {} void draw(); diff --git a/stella/src/unix/OSystemUNIX.cxx b/stella/src/unix/OSystemUNIX.cxx index 296df71f5..439872c5f 100644 --- a/stella/src/unix/OSystemUNIX.cxx +++ b/stella/src/unix/OSystemUNIX.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: OSystemUNIX.cxx,v 1.9 2005-05-25 17:17:38 stephena Exp $ +// $Id: OSystemUNIX.cxx,v 1.10 2005-05-26 15:43:44 stephena Exp $ //============================================================================ #include @@ -96,7 +96,7 @@ void OSystemUNIX::mainLoop() break; startTime = getTicks(); - myEventHandler->poll(); + myEventHandler->poll(startTime); myFrameBuffer->update(); // Now, waste time if we need to so that we are at the desired frame rate @@ -129,7 +129,7 @@ void OSystemUNIX::mainLoop() break; startTime = getTicks(); - myEventHandler->poll(); + myEventHandler->poll(startTime); myFrameBuffer->update(); currentTime = getTicks();