static void tcod_nextKeyOrMouseEvent(rogueEvent *returnEvent, boolean textInput, boolean colorsDance) { boolean tryAgain; TCOD_key_t key; TCOD_mouse_t mouse; uint32 theTime, waitTime; short x, y; TCOD_console_flush(); key.vk = TCODK_NONE; if (noMenu && rogue.nextGame == NG_NOTHING) rogue.nextGame = NG_NEW_GAME; for (;;) { theTime = TCOD_sys_elapsed_milli(); if (TCOD_console_is_window_closed()) { rogue.gameHasEnded = true; // causes the game loop to terminate quickly rogue.nextGame = NG_QUIT; // causes the menu to drop out immediately returnEvent->eventType = KEYSTROKE; returnEvent->param1 = ESCAPE_KEY; return; } tryAgain = false; if (bufferedKey.vk != TCODK_NONE) { rewriteKey(&bufferedKey, textInput); if (processKeystroke(bufferedKey, returnEvent, textInput)) { bufferedKey.vk = TCODK_NONE; return; } else { bufferedKey.vk = TCODK_NONE; } } if (missedMouse.lmb) { returnEvent->eventType = missedMouse.lmb; returnEvent->param1 = missedMouse.x; returnEvent->param2 = missedMouse.y; if (TCOD_console_is_key_pressed(TCODK_CONTROL)) { returnEvent->controlKey = true; } if (TCOD_console_is_key_pressed(TCODK_SHIFT)) { returnEvent->shiftKey = true; } missedMouse.lmb = missedMouse.lmb == MOUSE_DOWN ? MOUSE_UP : 0; return; } if (missedMouse.rmb) { returnEvent->eventType = missedMouse.rmb == MOUSE_DOWN ? RIGHT_MOUSE_DOWN : RIGHT_MOUSE_UP; returnEvent->param1 = missedMouse.x; returnEvent->param2 = missedMouse.y; if (TCOD_console_is_key_pressed(TCODK_CONTROL)) { returnEvent->controlKey = true; } if (TCOD_console_is_key_pressed(TCODK_SHIFT)) { returnEvent->shiftKey = true; } missedMouse.rmb = missedMouse.rmb == MOUSE_DOWN ? MOUSE_UP : 0; return; } if (!(serverMode || (SDL_GetAppState() & SDL_APPACTIVE))) { TCOD_sys_sleep_milli(100); } else { if (colorsDance) { shuffleTerrainColors(3, true); commitDraws(); } TCOD_console_flush(); } #ifdef USE_NEW_TCOD_API TCOD_sys_check_for_event(TCOD_EVENT_KEY_PRESS | TCOD_EVENT_MOUSE, &key, &mouse); #else key = TCOD_console_check_for_keypress(TCOD_KEY_PRESSED); #endif rewriteKey(&key, textInput); if (processKeystroke(key, returnEvent, textInput)) { return; } mouse = TCOD_mouse_get_status(); if (serverMode || (SDL_GetAppState() & SDL_APPACTIVE)) { x = mouse.cx; y = mouse.cy; } else { x = 0; y = 0; } if ( mouse.lbutton_pressed || mouse.rbutton_pressed || mouse.lbutton != brogueMouse.lmb || mouse.rbutton != brogueMouse.rmb || brogueMouse.x !=x || brogueMouse.y != y) { returnEvent->param1 = x; returnEvent->param2 = y; getModifiers(returnEvent); if (mouse.lbutton_pressed) { if (!brogueMouse.lmb) { // we missed a mouseDown event -- better make up for it! missedMouse.x = x; missedMouse.y = y; missedMouse.lmb = MOUSE_UP; returnEvent->eventType = MOUSE_DOWN; } else { returnEvent->eventType = MOUSE_UP; } } else if (mouse.lbutton && !brogueMouse.lmb) { returnEvent->eventType = MOUSE_DOWN; } else { returnEvent->eventType = MOUSE_ENTERED_CELL; } if (mouse.rbutton_pressed) { if (!brogueMouse.rmb) { // we missed a mouseDown event -- better make up for it! missedMouse.x = x; missedMouse.y = y; missedMouse.rmb = MOUSE_UP; returnEvent->eventType = RIGHT_MOUSE_DOWN; } else { returnEvent->eventType = RIGHT_MOUSE_UP; } } else if (mouse.rbutton && !brogueMouse.rmb) { returnEvent->eventType = RIGHT_MOUSE_DOWN; } brogueMouse.x = x; brogueMouse.y = y; brogueMouse.lmb = mouse.lbutton; brogueMouse.rmb = mouse.rbutton; if (returnEvent->eventType == MOUSE_ENTERED_CELL && !hasMouseMoved) { hasMouseMoved = true; } else { return; } } waitTime = PAUSE_BETWEEN_EVENT_POLLING + theTime - TCOD_sys_elapsed_milli(); if (waitTime > 0 && waitTime <= PAUSE_BETWEEN_EVENT_POLLING) { TCOD_sys_sleep_milli(waitTime); } } }
static void curses_nextKeyOrMouseEvent(rogueEvent *returnEvent, boolean textInput, boolean colorsDance) { int key; // TCOD_mouse_t mouse; uint32_t theTime, waitTime; // short x, y; Term.refresh(); if (noMenu && rogue.nextGame == NG_NOTHING) rogue.nextGame = NG_NEW_GAME; for (;;) { theTime = getTime(); //TCOD_sys_elapsed_milli(); /*if (TCOD_console_is_window_closed()) { rogue.gameHasEnded = true; // causes the game loop to terminate quickly returnEvent->eventType = KEYSTROKE; returnEvent->param1 = ACKNOWLEDGE_KEY; return; }*/ if (colorsDance) { shuffleTerrainColors(3, true); commitDraws(); } key = Term.getkey(); if (key == TERM_MOUSE) { if (Term.mouse.x > 0 && Term.mouse.y > 0 && Term.mouse.x < COLS && Term.mouse.y < ROWS) { returnEvent->param1 = Term.mouse.x; returnEvent->param2 = Term.mouse.y; returnEvent->eventType = KEYSTROKE; if (Term.mouse.justReleased) returnEvent->eventType = MOUSE_UP; if (Term.mouse.justPressed) returnEvent->eventType = MOUSE_DOWN; if (Term.mouse.justMoved) returnEvent->eventType = MOUSE_ENTERED_CELL; returnEvent->controlKey = Term.mouse.control; returnEvent->shiftKey = Term.mouse.shift; if (returnEvent->eventType != KEYSTROKE) return; } } else if (key != TERM_NONE) { key = rewriteKey(key, textInput); returnEvent->eventType = KEYSTROKE; returnEvent->controlKey = 0; //(key.rctrl || key.lctrl); returnEvent->shiftKey = 0; //key.shift; returnEvent->param1 = key; if (key == Term.keys.backspace || key == Term.keys.del) returnEvent->param1 = DELETE_KEY; else if (key == Term.keys.up) returnEvent->param1 = UP_ARROW; else if (key == Term.keys.down) returnEvent->param1 = DOWN_ARROW; else if (key == Term.keys.left) returnEvent->param1 = LEFT_ARROW; else if (key == Term.keys.right) returnEvent->param1 = RIGHT_ARROW; else if (key == Term.keys.quit) { rogue.gameHasEnded = true; rogue.nextGame = NG_QUIT; // causes the menu to drop out immediately } else if ((key >= 'A' && key <= 'Z')) { returnEvent->shiftKey = 1; // returnEvent->param1 += 'a' - 'A'; } // we could try to catch control keys, where possible, but we'll catch keys we mustn't /* else if ((key >= 'A'-'@' && key <= 'Z'-'@')) { returnEvent->controlKey = 1; returnEvent->param1 += 'a' - ('A'-'@'); } */ return; } waitTime = PAUSE_BETWEEN_EVENT_POLLING + theTime - getTime(); if (waitTime > 0 && waitTime <= PAUSE_BETWEEN_EVENT_POLLING) { curses_pauseForMilliseconds(waitTime); } } }
static void sodna_nextKeyOrMouseEvent( rogueEvent *returnEvent, boolean textInput, boolean colorsDance) { int time, waitTime; boolean mouseMoved = false; for (;;) { time = sodna_ms_elapsed(); if (colorsDance) { shuffleTerrainColors(3, true); commitDraws(); } sodna_flush(); sodna_Event e = get_event(true); // We get lots of mouse events, loop to flush out several consecutive // ones. Do break at some point though. if (e.type == SODNA_EVENT_MOUSE_MOVED) { for (;;) { if (mouse_pos_changed()) mouseMoved = true; // Peek at the future event, try to stop this loop at the last // mouse moved event of the sequence. if (get_event(false).type != SODNA_EVENT_MOUSE_MOVED) break; if (sodna_ms_elapsed() - time > PAUSE_BETWEEN_EVENT_POLLING) break; e = get_event(true); } } returnEvent->controlKey = ctrl_pressed; returnEvent->shiftKey = shift_pressed; if (e.type == SODNA_EVENT_CLOSE_WINDOW) { rogue.gameHasEnded = true; rogue.nextGame = NG_QUIT; // causes the menu to drop out immediately returnEvent->eventType = KEYSTROKE; returnEvent->param1 = ESCAPE_KEY; return; } if (e.type == SODNA_EVENT_MOUSE_DOWN) { returnEvent->param1 = mouse_x; returnEvent->param2 = mouse_y; if (e.button.id == SODNA_LEFT_BUTTON) { returnEvent->eventType = MOUSE_DOWN; return; } if (e.button.id == SODNA_RIGHT_BUTTON) { returnEvent->eventType = RIGHT_MOUSE_DOWN; return; } } if (e.type == SODNA_EVENT_MOUSE_UP) { returnEvent->param1 = mouse_x; returnEvent->param2 = mouse_y; if (e.button.id == SODNA_LEFT_BUTTON) { returnEvent->eventType = MOUSE_UP; return; } if (e.button.id == SODNA_RIGHT_BUTTON) { returnEvent->eventType = RIGHT_MOUSE_UP; return; } } // Reverse the effect of caps lock if it's on. if (e.type == SODNA_EVENT_CHARACTER) { // XXX: Due to a bug in SDL2, used as backend by Sodna, caps lock // state isn't maintained robustly. So we can't rely on the // modifier. Look at shift state and the character case instead. //if (caps_lock) { if ((isupper(e.ch.code) && !shift_pressed) || (islower(e.ch.code) && shift_pressed)) { if (isupper(e.ch.code)) { e.ch.code = tolower(e.ch.code); } else if (islower(e.ch.code)) { e.ch.code = toupper(e.ch.code); } } } // Keymap translation. if (e.type == SODNA_EVENT_CHARACTER && e.ch.code < 128) { int km = printable_mappings[e.ch.code]; if (km > 0) { e.ch.code = km; } else if (km < 0) { e.type = SODNA_EVENT_KEY_DOWN; e.key.layout = -km; } } else if (e.type == SODNA_EVENT_KEY_DOWN && e.key.layout < 128) { int km = unprintable_mappings[e.key.layout]; if (km > 0) { e.key.layout = km; } else if (km < 0) { e.type = SODNA_EVENT_CHARACTER; e.ch.code = -km; } } // Back to event handling. if (e.type == SODNA_EVENT_CHARACTER) { returnEvent->param1 = e.ch.code; returnEvent->eventType = KEYSTROKE; return; } if (e.type == SODNA_EVENT_KEY_DOWN) { returnEvent->eventType = KEYSTROKE; switch (e.key.layout) { #define K(sodna, brogue) case sodna: returnEvent->param1 = brogue; return; K(SODNA_KEY_UP, UP_ARROW) K(SODNA_KEY_DOWN, DOWN_ARROW) K(SODNA_KEY_LEFT, LEFT_ARROW) K(SODNA_KEY_RIGHT, RIGHT_ARROW) K(SODNA_KEY_KP_1, NUMPAD_1) K(SODNA_KEY_KP_2, NUMPAD_2) K(SODNA_KEY_KP_3, NUMPAD_3) K(SODNA_KEY_KP_4, NUMPAD_4) K(SODNA_KEY_KP_5, NUMPAD_5) K(SODNA_KEY_KP_6, NUMPAD_6) K(SODNA_KEY_KP_7, NUMPAD_7) K(SODNA_KEY_KP_8, NUMPAD_8) K(SODNA_KEY_KP_9, NUMPAD_9) K(SODNA_KEY_KP_0, NUMPAD_0) K(SODNA_KEY_TAB, TAB_KEY) K(SODNA_KEY_ENTER, RETURN_KEY) K(SODNA_KEY_KP_ENTER, ENTER_KEY) K(SODNA_KEY_BACKSPACE, DELETE_KEY) K(SODNA_KEY_ESCAPE, ESCAPE_KEY) #undef K break; } } if (mouseMoved) { returnEvent->eventType = MOUSE_ENTERED_CELL; returnEvent->param1 = mouse_x; returnEvent->param2 = mouse_y; return; } waitTime = time + PAUSE_BETWEEN_EVENT_POLLING - sodna_ms_elapsed(); if (waitTime > 0 && waitTime <= PAUSE_BETWEEN_EVENT_POLLING) { sodna_sleep_ms(waitTime); } }