Ticket #8532: keyboard-repeat3.diff
File keyboard-repeat3.diff, 18.7 KB (added by , 17 years ago) |
---|
-
gui/newgui.cpp
50 50 51 51 enum { 52 52 kDoubleClickDelay = 500, // milliseconds 53 kCursorAnimateDelay = 250, 54 kKeyRepeatInitialDelay = 400, 55 kKeyRepeatSustainDelay = 100 53 kCursorAnimateDelay = 250 56 54 }; 57 55 58 56 void GuiObject::reflowLayout() { … … 91 89 // Clear the cursor 92 90 memset(_cursor, 0xFF, sizeof(_cursor)); 93 91 94 // Reset key repeat95 _currentKeyDown.keycode = 0;96 97 92 bool loadClassicTheme = true; 98 93 #ifndef DISABLE_FANCY_THEMES 99 94 ConfMan.registerDefault("gui_theme", "default"); … … 272 267 273 268 switch (event.type) { 274 269 case OSystem::EVENT_KEYDOWN: 275 #if !defined(PALMOS_MODE)276 // init continuous event stream277 // not done on PalmOS because keyboard is emulated and keyup is not generated278 _currentKeyDown.ascii = event.kbd.ascii;279 _currentKeyDown.keycode = event.kbd.keycode;280 _currentKeyDown.flags = event.kbd.flags;281 _keyRepeatTime = time + kKeyRepeatInitialDelay;282 #endif283 270 activeDialog->handleKeyDown(event.kbd.ascii, event.kbd.keycode, event.kbd.flags); 284 271 break; 285 272 case OSystem::EVENT_KEYUP: 286 273 activeDialog->handleKeyUp(event.kbd.ascii, event.kbd.keycode, event.kbd.flags); 287 if (event.kbd.keycode == _currentKeyDown.keycode)288 // only stop firing events if it's the current key289 _currentKeyDown.keycode = 0;290 274 break; 291 275 case OSystem::EVENT_MOUSEMOVE: 292 276 activeDialog->handleMouseMoved(mouse.x, mouse.y, 0); … … 327 311 } 328 312 } 329 313 330 // check if event should be sent again (keydown)331 if (_currentKeyDown.keycode != 0 && activeDialog == getTopDialog()) {332 if (_keyRepeatTime < time) {333 // fire event334 activeDialog->handleKeyDown(_currentKeyDown.ascii, _currentKeyDown.keycode, _currentKeyDown.flags);335 _keyRepeatTime = time + kKeyRepeatSustainDelay;336 }337 }338 339 314 // Delay for a moment 340 315 _system->delayMillis(10); 341 316 } … … 353 328 354 329 void NewGui::saveState() { 355 330 // Backup old cursor 356 _currentKeyDown.keycode = 0;357 331 _lastClick.x = _lastClick.y = 0; 358 332 _lastClick.time = 0; 359 333 _lastClick.count = 0; -
gui/newgui.h
99 99 100 100 bool _useStdCursor; 101 101 102 // for continuous events (keyDown)103 struct {104 uint16 ascii;105 byte flags;106 int keycode;107 } _currentKeyDown;108 uint32 _keyRepeatTime;109 110 102 // position and time of last mouse click (used to detect double clicks) 111 103 struct { 112 104 int16 x, y; // Position of mouse when the click occured -
common/system.h
747 747 struct Event { 748 748 /** The type of the event. */ 749 749 EventType type; 750 /** Flag to indicate if the event is real or synthetic. E.g. keyboard 751 * repeat events are synthetic. 752 */ 753 bool synthetic; 750 754 /** 751 755 * Keyboard data; only valid for keyboard events (EVENT_KEYDOWN and 752 756 * EVENT_KEYUP). For all other event types, content is undefined. -
engines/sword1/control.h
139 139 uint8 *_font, *_redFont; 140 140 uint8 *_screenBuf; 141 141 uint8 _keyPressed; 142 uint8 _keyRepeat;143 uint32 _keyRepeatTime;144 142 void delay(uint32 msecs); 145 143 uint16 _mouseX, _mouseY, _mouseState; 146 144 bool _mouseDown; -
engines/sword1/control.cpp
42 42 43 43 namespace Sword1 { 44 44 45 enum {46 kKeyRepeatInitialDelay = 400,47 kKeyRepeatSustainDelay = 10048 };49 50 45 enum LangStrings { 51 46 STR_PAUSED = 0, 52 47 STR_INSERT_CD_A, … … 171 166 _music = pMusic; 172 167 _sound = pSound; 173 168 _lStrings = _languageStrings + SwordEngine::_systemVars.language * 20; 174 _keyRepeat = 0;175 _keyRepeatTime = 0;176 169 _selectedButton = 255; 177 170 } 178 171 … … 1053 1046 _keyPressed = 8; 1054 1047 else 1055 1048 _keyPressed = (byte)event.kbd.ascii; 1056 _keyRepeatTime = now + kKeyRepeatInitialDelay;1057 _keyRepeat = _keyPressed;1058 1049 // we skip the rest of the delay and return immediately 1059 1050 // to handle keyboard input 1060 1051 return; 1061 case OSystem::EVENT_KEYUP:1062 _keyRepeatTime = 0;1063 _keyRepeat = 0;1064 break;1065 1052 case OSystem::EVENT_MOUSEMOVE: 1066 1053 _mouseX = event.mouse.x; 1067 1054 _mouseY = event.mouse.y; … … 1093 1080 break; 1094 1081 } 1095 1082 } 1096 if (_keyRepeatTime && now > _keyRepeatTime) {1097 _keyRepeatTime += kKeyRepeatSustainDelay;1098 _keyPressed = _keyRepeat;1099 }1100 1083 1101 1084 _system->updateScreen(); 1102 1085 _system->delayMillis(10); -
engines/sword2/sword2.cpp
187 187 _debugger = NULL; 188 188 189 189 _keyboardEvent.pending = false; 190 _keyboardEvent.repeat = 0;191 190 _mouseEvent.pending = false; 192 191 193 192 _wantSfxDebug = false; … … 377 376 378 377 if (ke) { 379 378 if ((ke->modifiers == OSystem::KBD_CTRL && ke->keycode == 'd') || ke->ascii == '#' || ke->ascii == '~') { 380 // HACK: We have to clear the 'repeat' flag, or381 // it will probably trigger a keyboard repeat382 // immediately after the debug console closes.383 _keyboardEvent.repeat = 0;384 379 _debugger->attach(); 385 380 } else if (ke->modifiers == 0 || ke->modifiers == OSystem::KBD_SHIFT) { 386 381 switch (ke->keycode) { … … 555 550 } 556 551 if (!(_inputEventFilter & RD_KEYDOWN)) { 557 552 _keyboardEvent.pending = true; 558 _keyboardEvent.repeat = now + 400;559 553 _keyboardEvent.ascii = event.kbd.ascii; 560 554 _keyboardEvent.keycode = event.kbd.keycode; 561 555 _keyboardEvent.modifiers = event.kbd.flags; 562 556 } 563 557 break; 564 case OSystem::EVENT_KEYUP:565 _keyboardEvent.repeat = 0;566 break;567 558 case OSystem::EVENT_MOUSEMOVE: 568 559 if (!(_inputEventFilter & RD_KEYDOWN)) { 569 560 _mouse->setPos(event.mouse.x, event.mouse.y - MENUDEEP); … … 612 603 break; 613 604 } 614 605 } 615 616 // Handle keyboard auto-repeat617 if (!_keyboardEvent.pending && _keyboardEvent.repeat && now >= _keyboardEvent.repeat) {618 _keyboardEvent.pending = true;619 _keyboardEvent.repeat = now + 100;620 }621 606 } 622 607 623 608 void Sword2Engine::gameCycle() { -
engines/sword2/sword2.h
74 74 75 75 struct KeyboardEvent { 76 76 bool pending; 77 uint32 repeat;78 77 uint16 ascii; 79 78 int keycode; 80 79 int modifiers; -
engines/agos/agos.h
200 200 const GameSpecificSettings *gss; 201 201 202 202 byte _keyPressed; 203 byte _keyRepeatKey;204 uint32 _keyRepeatTime;205 203 206 204 typedef enum { 207 205 FORMAT_NONE, -
engines/agos/event.cpp
375 375 _keyPressed = 8; 376 376 else 377 377 _keyPressed = (byte)event.kbd.ascii; 378 379 _keyRepeatTime = _system->getMillis() + 400;380 _keyRepeatKey = _keyPressed;381 378 break; 382 case OSystem::EVENT_KEYUP:383 _keyRepeatKey = 0;384 _keyRepeatTime = 0;385 break;386 379 case OSystem::EVENT_MOUSEMOVE: 387 380 _sdlMouseX = event.mouse.x; 388 381 _sdlMouseY = event.mouse.y; … … 435 428 436 429 cur = _system->getMillis(); 437 430 } while (cur < start + amount); 438 439 if (_keyPressed == 0 && _keyRepeatKey != 0 && _keyRepeatTime != 0 && cur >= _keyRepeatTime) {440 _keyPressed = _keyRepeatKey;441 _keyRepeatTime = cur + 100;442 }443 431 } 444 432 445 433 void AGOSEngine::timer_callback() { -
engines/agos/agos.cpp
81 81 _debugger = 0; 82 82 83 83 _keyPressed = 0; 84 _keyRepeatKey = 0;85 _keyRepeatTime = 0;86 84 87 85 _gameFile = 0; 88 86 -
engines/agi/agi.cpp
113 113 switch (key = event.kbd.keycode) { 114 114 case 256 + 20: // left arrow 115 115 case 260: // key pad 4 116 key = KEY_LEFT; 116 if (!event.synthetic) 117 key = KEY_LEFT; 117 118 break; 118 119 case 256 + 19: // right arrow 119 120 case 262: // key pad 6 120 key = KEY_RIGHT; 121 if (!event.synthetic) 122 key = KEY_RIGHT; 121 123 break; 122 124 case 256 + 17: // up arrow 123 125 case 264: // key pad 8 124 key = KEY_UP; 126 if (!event.synthetic) 127 key = KEY_UP; 125 128 break; 126 129 case 256 + 18: // down arrow 127 130 case 258: // key pad 2 128 key = KEY_DOWN; 131 if (!event.synthetic) 132 key = KEY_DOWN; 129 133 break; 130 134 case 256 + 24: // page up 131 135 case 265: // key pad 9 132 key = KEY_UP_RIGHT; 136 if (!event.synthetic) 137 key = KEY_UP_RIGHT; 133 138 break; 134 139 case 256 + 25: // page down 135 140 case 259: // key pad 3 136 key = KEY_DOWN_RIGHT; 141 if (!event.synthetic) 142 key = KEY_DOWN_RIGHT; 137 143 break; 138 144 case 256 + 22: // home 139 145 case 263: // key pad 7 140 key = KEY_UP_LEFT; 146 if (!event.synthetic) 147 key = KEY_UP_LEFT; 141 148 break; 142 149 case 256 + 23: // end 143 150 case 257: // key pad 1 144 key = KEY_DOWN_LEFT; 151 if (!event.synthetic) 152 key = KEY_DOWN_LEFT; 145 153 break; 146 154 case 261: // key pad 5 147 155 key = KEY_STATIONARY; -
engines/kyra/gui.cpp
597 597 calcCoords(_menu[i]); 598 598 599 599 _menuRestoreScreen = true; 600 _keyboardEvent.pending = 0; 601 _keyboardEvent.repeat = 0; 600 _keyPressed = 0; 602 601 _mousePressFlag = false; 603 602 604 603 _toplevelMenu = 0; … … 835 834 _mouseWheel = 1; 836 835 break; 837 836 case OSystem::EVENT_KEYDOWN: 838 _keyboardEvent.pending = true; 839 _keyboardEvent.repeat = now + 400; 840 _keyboardEvent.ascii = event.kbd.ascii; 837 _keyPressed = event.kbd.ascii; 841 838 break; 842 case OSystem::EVENT_KEYUP:843 _keyboardEvent.repeat = 0;844 break;845 839 default: 846 840 break; 847 841 } … … 852 846 lastScreenUpdate = now; 853 847 } 854 848 855 if (!_keyboardEvent.pending && _keyboardEvent.repeat && now >= _keyboardEvent.repeat) {856 _keyboardEvent.pending = true;857 _keyboardEvent.repeat = now + 100;858 }859 849 _system->delayMillis(3); 860 850 } 861 851 … … 1020 1010 void KyraEngine::gui_updateSavegameString() { 1021 1011 int length; 1022 1012 1023 if (_key boardEvent.pending && _keyboardEvent.ascii) {1013 if (_keyPressed) { 1024 1014 length = strlen(_savegameName); 1025 1015 1026 if (_key boardEvent.ascii > 31 && _keyboardEvent.ascii< 127) {1016 if (_keyPressed > 31 && _keyPressed < 127) { 1027 1017 if (length < 31) { 1028 _savegameName[length] = _key boardEvent.ascii;1018 _savegameName[length] = _keyPressed; 1029 1019 _savegameName[length+1] = 0; 1030 1020 gui_redrawTextfield(); 1031 1021 } 1032 } else if (_key boardEvent.ascii == 8 ||_keyboardEvent.ascii== 127) {1022 } else if (_keyPressed == 8 ||_keyPressed == 127) { 1033 1023 if (length > 0) { 1034 1024 _savegameName[length-1] = 0; 1035 1025 gui_redrawTextfield(); 1036 1026 } 1037 } else if (_key boardEvent.ascii== 13) {1027 } else if (_keyPressed == 13) { 1038 1028 _displaySubMenu = false; 1039 1029 } 1040 1030 } 1041 1031 1042 _key boardEvent.pending = false;1032 _keyPressed = 0; 1043 1033 } 1044 1034 1045 1035 int KyraEngine::gui_saveGame(Button *button) { -
engines/kyra/kyra.h
227 227 MenuItem item[6]; 228 228 }; 229 229 230 struct KeyboardEvent {231 bool pending;232 uint32 repeat;233 uint8 ascii;234 };235 236 230 class KyraEngine : public Engine { 237 231 friend class MusicPlayer; 238 232 friend class Debugger; … … 839 833 int _gameToLoad; 840 834 char _savegameName[31]; 841 835 const char *_specialSavegameString; 842 KeyboardEvent _keyboardEvent;836 uint8 _keyPressed; 843 837 844 838 struct KyragemState { 845 839 uint16 nextOperation; -
engines/saga/input.cpp
121 121 break; 122 122 } 123 123 break; 124 case OSystem::EVENT_KEYUP:125 _interface->processKeyUp(event.kbd.ascii);126 break;127 124 case OSystem::EVENT_LBUTTONUP: 128 125 _leftMouseButtonPressed = false; 129 126 break; -
engines/saga/interface.h
222 222 void drawStatusBar(); 223 223 void setVerbState(int verb, int state); 224 224 225 bool processAscii(uint16 ascii, bool synthetic = false); 226 void processKeyUp(uint16 ascii); 225 bool processAscii(uint16 ascii); 227 226 228 227 void keyBoss(); 229 228 void keyBossExit(); … … 243 242 } 244 243 245 244 private: 246 static void textInputRepeatCallback(void *refCon);247 248 245 void drawInventory(Surface *backBuffer); 249 246 void updateInventory(int pos); 250 247 void inventoryChangePos(int chg); … … 343 340 void calcOptionSaveSlider(); 344 341 bool processTextInput(uint16 ascii); 345 342 void processStatusTextInput(uint16 ascii); 346 void textInputStartRepeat(uint16 ascii);347 void textInputRepeat(void);348 343 349 344 public: 350 345 void converseInit(void); … … 452 447 453 448 uint _statusTextInputPos; 454 449 455 int _textInputRepeatPhase;456 uint16 _textInputRepeatChar;457 458 450 PalEntry _mapSavedPal[PAL_ENTRIES]; 459 451 bool _mapPanelCrossHairState; 460 452 -
engines/saga/interface.cpp
212 212 error("Interface::Interface(): not enough memory"); 213 213 } 214 214 215 _textInputRepeatPhase = 0;216 215 _textInput = false; 217 216 _statusTextInput = false; 218 217 _statusTextInputState = kStatusTextInputFirstRun; … … 316 315 _textInput = true; 317 316 _textInputStringLength = strlen(_textInputString); 318 317 _textInputPos = _textInputStringLength + 1; 319 _textInputRepeatPhase = 0;320 318 break; 321 319 case kPanelMap: 322 320 mapPanelShow(); … … 337 335 _textInputString[0] = 0; 338 336 _textInputStringLength = 0; 339 337 _textInputPos = _textInputStringLength + 1; 340 _textInputRepeatPhase = 0;341 338 break; 342 339 } 343 340 344 341 draw(); 345 342 } 346 343 347 bool Interface::processAscii(uint16 ascii , bool synthetic) {344 bool Interface::processAscii(uint16 ascii) { 348 345 // TODO: Checking for Esc and Enter below is a bit hackish, and 349 346 // and probably only works with the English version. Maybe we should 350 347 // add a flag to the button so it can indicate if it's the default or … … 352 349 353 350 int i; 354 351 PanelButton *panelButton; 355 if (!synthetic)356 _textInputRepeatPhase = 0;357 352 if (_statusTextInput) { 358 353 processStatusTextInput(ascii); 359 354 return true; … … 536 531 return false; 537 532 } 538 533 539 #define KEYBOARD_REPEAT_DELAY1 300000L540 #define KEYBOARD_REPEAT_DELAY2 50000L541 542 void Interface::textInputRepeatCallback(void *refCon) {543 ((Interface *)refCon)->textInputRepeat();544 }545 546 void Interface::textInputStartRepeat(uint16 ascii) {547 if (!_textInputRepeatPhase) {548 _textInputRepeatPhase = 1;549 _vm->_timer->removeTimerProc(&textInputRepeatCallback);550 _vm->_timer->installTimerProc(&textInputRepeatCallback, KEYBOARD_REPEAT_DELAY1, this);551 }552 553 _textInputRepeatChar = ascii;554 }555 556 void Interface::textInputRepeat() {557 if (_textInputRepeatPhase == 1) {558 _textInputRepeatPhase = 2;559 _vm->_timer->removeTimerProc(&textInputRepeatCallback);560 _vm->_timer->installTimerProc(&textInputRepeatCallback, KEYBOARD_REPEAT_DELAY2, this);561 } else if (_textInputRepeatPhase == 2) {562 processAscii(_textInputRepeatChar, true);563 }564 }565 566 void Interface::processKeyUp(uint16 ascii) {567 if (_textInputRepeatPhase) {568 _vm->_timer->removeTimerProc(&textInputRepeatCallback);569 _textInputRepeatPhase = 0;570 }571 }572 573 534 void Interface::setStatusText(const char *text, int statusColor) { 574 535 assert(text != NULL); 575 536 assert(strlen(text) < STATUS_TEXT_LEN); … … 928 889 929 890 void Interface::processStatusTextInput(uint16 ascii) { 930 891 931 textInputStartRepeat(ascii);932 892 switch (ascii) { 933 893 case 27: // esc 934 894 _statusTextInputState = kStatusTextInputAborted; … … 968 928 memset(tempString, 0, SAVE_TITLE_SIZE); 969 929 ch[1] = 0; 970 930 971 textInputStartRepeat(ascii);972 973 931 switch (ascii) { 974 932 case 13: 975 933 return false; -
backends/events/default/default-events.cpp
33 33 _shouldQuit(false) { 34 34 35 35 assert(_boss); 36 37 // Reset key repeat 38 _currentKeyDown.keycode = 0; 36 39 } 37 40 38 41 DefaultEventManager::~DefaultEventManager() { … … 40 43 } 41 44 42 45 bool DefaultEventManager::pollEvent(OSystem::Event &event) { 46 uint32 time = _boss->getMillis(); 43 47 bool result; 44 48 45 49 result = _boss->pollEvent(event); 46 50 47 51 if (result) { 52 event.synthetic = false; 48 53 switch (event.type) { 49 54 case OSystem::EVENT_KEYDOWN: 55 _modifierState = event.kbd.flags; 56 57 // init continuous event stream 58 // not done on PalmOS because keyboard is emulated and keyup is not generated 59 #if !defined(PALMOS_MODE) 60 _currentKeyDown.ascii = event.kbd.ascii; 61 _currentKeyDown.keycode = event.kbd.keycode; 62 _currentKeyDown.flags = event.kbd.flags; 63 _keyRepeatTime = time + kKeyRepeatInitialDelay; 64 #endif 65 break; 50 66 case OSystem::EVENT_KEYUP: 51 67 _modifierState = event.kbd.flags; 68 if (event.kbd.keycode == _currentKeyDown.keycode) { 69 // Only stop firing events if it's the current key 70 _currentKeyDown.keycode = 0; 71 } 52 72 break; 73 53 74 case OSystem::EVENT_MOUSEMOVE: 54 75 _mousePos = event.mouse; 55 76 break; … … 79 100 default: 80 101 break; 81 102 } 103 } else { 104 // Check if event should be sent again (keydown) 105 if (_currentKeyDown.keycode != 0 && _keyRepeatTime < time) { 106 // fire event 107 event.type = OSystem::EVENT_KEYDOWN; 108 event.synthetic = true; 109 event.kbd.ascii = _currentKeyDown.ascii; 110 event.kbd.keycode = _currentKeyDown.keycode; 111 event.kbd.flags = _currentKeyDown.flags; 112 _keyRepeatTime = time + kKeyRepeatSustainDelay; 113 result = true; 114 } 82 115 } 83 116 84 117 return result; -
backends/events/default/default-events.h
46 46 int _modifierState; 47 47 bool _shouldQuit; 48 48 49 // for continuous events (keyDown) 50 enum { 51 kKeyRepeatInitialDelay = 400, 52 kKeyRepeatSustainDelay = 100 53 }; 54 55 struct { 56 uint16 ascii; 57 byte flags; 58 int keycode; 59 } _currentKeyDown; 60 uint32 _keyRepeatTime; 61 49 62 public: 50 63 DefaultEventManager(OSystem *boss); 51 64 ~DefaultEventManager();