X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fevents.c;h=f33b31169202c335e2bd30b789359515abe54262;hp=5a0d57757190049faa3f55349d201346c48ce4cf;hb=5f9b6d3b52c7f8dc10c01782d466a1e8f5ca5f26;hpb=64e7c54dce6ea8c063f04198c64c5057d751c928 diff --git a/src/events.c b/src/events.c index 5a0d5775..f33b3116 100644 --- a/src/events.c +++ b/src/events.c @@ -39,30 +39,30 @@ static int cursor_mode_last = CURSOR_DEFAULT; static unsigned int special_cursor_delay = 0; static unsigned int special_cursor_delay_value = 1000; +static boolean virtual_button_pressed = FALSE; + // forward declarations for internal use static void HandleNoEvent(void); static void HandleEventActions(void); -/* event filter especially needed for SDL event filtering due to - delay problems with lots of mouse motion events when mouse button - not pressed (X11 can handle this with 'PointerMotionHintMask') */ +// event filter especially needed for SDL event filtering due to +// delay problems with lots of mouse motion events when mouse button +// not pressed (X11 can handle this with 'PointerMotionHintMask') -/* event filter addition for SDL2: as SDL2 does not have a function to enable - or disable keyboard auto-repeat, filter repeated keyboard events instead */ +// event filter addition for SDL2: as SDL2 does not have a function to enable +// or disable keyboard auto-repeat, filter repeated keyboard events instead static int FilterEvents(const Event *event) { MotionEvent *motion; -#if defined(TARGET_SDL2) // skip repeated key press events if keyboard auto-repeat is disabled if (event->type == EVENT_KEYPRESS && event->key.repeat && !keyrepeat_status) return 0; -#endif if (event->type == EVENT_BUTTONPRESS || event->type == EVENT_BUTTONRELEASE) @@ -106,9 +106,9 @@ static int FilterEvents(const Event *event) return 1; } -/* to prevent delay problems, skip mouse motion events if the very next - event is also a mouse motion event (and therefore effectively only - handling the last of a row of mouse motion events in the event queue) */ +// to prevent delay problems, skip mouse motion events if the very next +// event is also a mouse motion event (and therefore effectively only +// handling the last of a row of mouse motion events in the event queue) static boolean SkipPressedMouseMotionEvent(const Event *event) { @@ -185,7 +185,6 @@ static void HandleEvents(void) HandleMotionEvent((MotionEvent *) &event); break; -#if defined(TARGET_SDL2) case EVENT_WHEELMOTION: HandleWheelEvent((WheelEvent *) &event); break; @@ -210,7 +209,6 @@ static void HandleEvents(void) case SDL_APP_DIDENTERFOREGROUND: HandlePauseResumeEvent((PauseResumeEvent *) &event); break; -#endif case EVENT_KEYPRESS: case EVENT_KEYRELEASE: @@ -238,8 +236,8 @@ void HandleOtherEvents(Event *event) case EVENT_UNMAPNOTIFY: #if 0 - /* This causes the game to stop not only when iconified, but also - when on another virtual desktop, which might be not desired. */ + // This causes the game to stop not only when iconified, but also + // when on another virtual desktop, which might be not desired. SleepWhileUnmapped(); #endif break; @@ -253,8 +251,6 @@ void HandleOtherEvents(Event *event) HandleClientMessageEvent((ClientMessageEvent *) event); break; -#if defined(TARGET_SDL) -#if defined(TARGET_SDL2) case SDL_CONTROLLERBUTTONDOWN: case SDL_CONTROLLERBUTTONUP: // for any game controller button event, disable overlay buttons @@ -266,17 +262,19 @@ void HandleOtherEvents(Event *event) case SDL_CONTROLLERDEVICEADDED: case SDL_CONTROLLERDEVICEREMOVED: case SDL_CONTROLLERAXISMOTION: -#endif case SDL_JOYAXISMOTION: case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: HandleJoystickEvent(event); break; - case SDL_SYSWMEVENT: - HandleWindowManagerEvent(event); + case SDL_DROPFILE: + HandleDropFileEvent(event); + break; + + case SDL_DROPTEXT: + HandleDropTextEvent(event); break; -#endif default: break; @@ -330,8 +328,8 @@ void EventLoop(void) // execute event related actions after pending events have been processed HandleEventActions(); - /* don't use all CPU time when idle; the main loop while playing - has its own synchronization and is CPU friendly, too */ + // don't use all CPU time when idle; the main loop while playing + // has its own synchronization and is CPU friendly, too if (game_status == GAME_MODE_PLAYING) HandleGameActions(); @@ -349,7 +347,6 @@ void EventLoop(void) void ClearAutoRepeatKeyEvents(void) { -#if defined(TARGET_SDL2) while (PendingEvent()) { Event next_event; @@ -363,7 +360,6 @@ void ClearAutoRepeatKeyEvents(void) else break; } -#endif } void ClearEventQueue(void) @@ -382,12 +378,10 @@ void ClearEventQueue(void) ClearPlayerAction(); break; -#if defined(TARGET_SDL2) case SDL_CONTROLLERBUTTONUP: HandleJoystickEvent(&event); ClearPlayerAction(); break; -#endif default: HandleOtherEvents(&event); @@ -467,22 +461,19 @@ void SleepWhileUnmapped(void) key_joystick_mapping = 0; break; -#if defined(TARGET_SDL2) case SDL_CONTROLLERBUTTONUP: HandleJoystickEvent(&event); key_joystick_mapping = 0; break; -#endif case EVENT_MAPNOTIFY: window_unmapped = FALSE; break; case EVENT_UNMAPNOTIFY: - /* this is only to surely prevent the 'should not happen' case - * of recursively looping between 'SleepWhileUnmapped()' and - * 'HandleOtherEvents()' which usually calls this funtion. - */ + // this is only to surely prevent the 'should not happen' case + // of recursively looping between 'SleepWhileUnmapped()' and + // 'HandleOtherEvents()' which usually calls this funtion. break; default: @@ -541,8 +532,6 @@ void HandleMotionEvent(MotionEvent *event) HandleButton(event->x, event->y, button_status, button_status); } -#if defined(TARGET_SDL2) - void HandleWheelEvent(WheelEvent *event) { int button_nr; @@ -739,6 +728,8 @@ static void HandleFingerEvent_VirtualButtons(FingerEvent *event) "KEY_PRESSED"); int i; + virtual_button_pressed = (key_status == KEY_PRESSED && key != KSYM_UNDEFINED); + // for any touch input event, enable overlay buttons (if activated) SetOverlayEnabled(TRUE); @@ -1038,8 +1029,6 @@ void HandleFingerEvent(FingerEvent *event) HandleFingerEvent_WipeGestures(event); } -#endif - static void HandleButtonOrFinger_WipeGestures_MM(int mx, int my, int button) { static int old_mx = 0, old_my = 0; @@ -1399,8 +1388,6 @@ static void HandleButtonOrFinger(int mx, int my, int button) } } -#if defined(TARGET_SDL2) - static boolean checkTextInputKeyModState(void) { // when playing, only handle raw key events and ignore text input @@ -1449,8 +1436,6 @@ void HandlePauseResumeEvent(PauseResumeEvent *event) } } -#endif - void HandleKeyEvent(KeyEvent *event) { int key_status = (event->type == EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED); @@ -1475,22 +1460,24 @@ void HandleKeyEvent(KeyEvent *event) // always map the "back" button to the "escape" key on Android devices key = KSYM_Escape; } + else if (key == KSYM_Menu) + { + // the "menu" button can be used to toggle displaying virtual buttons + if (key_status == KEY_PRESSED) + SetOverlayEnabled(!GetOverlayEnabled()); + } else { - // for any key event other than "back" button, disable overlay buttons + // for any other "real" key event, disable virtual buttons SetOverlayEnabled(FALSE); } #endif HandleKeyModState(keymod, key_status); -#if defined(TARGET_SDL2) // only handle raw key input without text modifier keys pressed if (!checkTextInputKeyModState()) HandleKey(key, key_status); -#else - HandleKey(key, key_status); -#endif } void HandleFocusEvent(FocusChangeEvent *event) @@ -1520,8 +1507,7 @@ void HandleFocusEvent(FocusChangeEvent *event) The effect would be keyboard auto repeat while playing the game (game_status == GAME_MODE_PLAYING), which is not desired. To avoid this special case, we just wait 1/10 second before - processing the 'FocusIn' event. - */ + processing the 'FocusIn' event. */ if (game_status == GAME_MODE_PLAYING) { @@ -1540,11 +1526,47 @@ void HandleClientMessageEvent(ClientMessageEvent *event) CloseAllAndExit(0); } -void HandleWindowManagerEvent(Event *event) +static void HandleDropFileEventExt(char *filename) { -#if defined(TARGET_SDL) - SDLHandleWindowManagerEvent(event); -#endif + Error(ERR_DEBUG, "DROP FILE EVENT: '%s'", filename); + + // check and extract dropped zip files into correct user data directory + if (strSuffixLower(filename, ".zip")) + { + int tree_type = GetZipFileTreeType(filename); + char *directory = TREE_USERDIR(tree_type); + + if (directory == NULL) + { + Error(ERR_WARN, "zip file '%s' has invalid content!", filename); + + return; + } + + char *top_dir = ExtractZipFileIntoDirectory(filename, directory, tree_type); + + if (top_dir != NULL) + AddUserTreeSetToTreeInfo(top_dir, tree_type); + } +} + +static void HandleDropTextEventExt(char *text) +{ + Error(ERR_DEBUG, "DROP TEXT EVENT: '%s'", text); +} + +void HandleDropFileEvent(Event *event) +{ + HandleDropFileEventExt(event->drop.file); + + SDL_free(event->drop.file); +} + +void HandleDropTextEvent(Event *event) +{ + HandleDropTextEventExt(event->drop.file); + + SDL_free(event->drop.file); } void HandleButton(int mx, int my, int button, int button_nr) @@ -1569,10 +1591,13 @@ void HandleButton(int mx, int my, int button, int button_nr) #if defined(PLATFORM_ANDROID) // when playing, only handle gadgets when using "follow finger" controls // or when using touch controls in combination with the MM game engine + // or when using gadgets that do not overlap with virtual buttons handle_gadgets = (game_status != GAME_MODE_PLAYING || level.game_engine_type == GAME_ENGINE_TYPE_MM || - strEqual(setup.touch.control_type, TOUCH_CONTROL_FOLLOW_FINGER)); + strEqual(setup.touch.control_type, TOUCH_CONTROL_FOLLOW_FINGER) || + (strEqual(setup.touch.control_type, TOUCH_CONTROL_VIRTUAL_BUTTONS) && + !virtual_button_pressed)); #endif if (HandleGlobalAnimClicks(mx, my, button)) @@ -1780,6 +1805,22 @@ static void HandleKeysSpecial(Key key) { DumpBrush_Small(); } + + if (GetKeyModState() & (KMOD_Control | KMOD_Meta)) + { + if (letter == 'x') // copy brush to clipboard (small size) + { + CopyBrushToClipboard_Small(); + } + else if (letter == 'c') // copy brush to clipboard (normal size) + { + CopyBrushToClipboard(); + } + else if (letter == 'v') // paste brush from Clipboard + { + CopyClipboardToBrush(); + } + } } // special key shortcuts for all game modes @@ -1792,11 +1833,14 @@ static void HandleKeysSpecial(Key key) } } -void HandleKeysDebug(Key key) +boolean HandleKeysDebug(Key key, int key_status) { #ifdef DEBUG int i; + if (key_status != KEY_PRESSED) + return FALSE; + if (game_status == GAME_MODE_PLAYING || !setup.debug.frame_delay_game_only) { boolean mod_key_pressed = ((GetKeyModState() & KMOD_Valid) != KMOD_None); @@ -1823,7 +1867,7 @@ void HandleKeysDebug(Key key) else Error(ERR_DEBUG, "frame delay == 0 ms (maximum speed)"); - break; + return TRUE; } } } @@ -1836,14 +1880,20 @@ void HandleKeysDebug(Key key) Error(ERR_DEBUG, "debug mode %s", (options.debug ? "enabled" : "disabled")); + + return TRUE; } else if (key == KSYM_v) { Error(ERR_DEBUG, "currently using game engine version %d", game.engine_version); + + return TRUE; } } #endif + + return FALSE; } void HandleKey(Key key, int key_status) @@ -1870,13 +1920,14 @@ void HandleKey(Key key, int key_status) int joy = 0; int i; -#if defined(TARGET_SDL2) + if (HandleKeysDebug(key, key_status)) + return; // do not handle already processed keys again + // map special keys (media keys / remote control buttons) to default keys if (key == KSYM_PlayPause) key = KSYM_space; else if (key == KSYM_Select) key = KSYM_Return; -#endif HandleSpecialGameControllerKeys(key, key_status); @@ -2041,7 +2092,7 @@ void HandleKey(Key key, int key_status) return; } - if (game_status == GAME_MODE_PLAYING && AllPlayersGone && + if (game_status == GAME_MODE_PLAYING && game.all_players_gone && (key == KSYM_Return || key == setup.shortcut.toggle_pause)) { GameEnd(); @@ -2097,10 +2148,7 @@ void HandleKey(Key key, int key_status) HandleKeysSpecial(key); if (HandleGadgetsKeyInput(key)) - { - if (key != KSYM_Escape) // always allow ESC key to be handled - key = KSYM_UNDEFINED; - } + return; // do not handle already processed keys again switch (game_status) { @@ -2217,8 +2265,6 @@ void HandleKey(Key key, int key_status) return; } } - - HandleKeysDebug(key); } void HandleNoEvent(void) @@ -2356,6 +2402,16 @@ void HandleJoystick(void) return; } + if (newbutton && (game_status == GAME_MODE_PSEUDO_TYPENAME || + anyTextGadgetActive())) + { + // leave name input in main menu or text input gadget + HandleKey(KSYM_Escape, KEY_PRESSED); + HandleKey(KSYM_Escape, KEY_RELEASED); + + return; + } + if (level.game_engine_type == GAME_ENGINE_TYPE_MM) { if (game_status == GAME_MODE_PLAYING) @@ -2427,7 +2483,7 @@ void HandleJoystick(void) newbutton = ((joy & JOY_BUTTON) != 0); #endif - if (newbutton && AllPlayersGone) + if (newbutton && game.all_players_gone) { GameEnd(); @@ -2457,7 +2513,6 @@ void HandleJoystick(void) void HandleSpecialGameControllerButtons(Event *event) { -#if defined(TARGET_SDL2) int key_status; Key key; @@ -2490,12 +2545,10 @@ void HandleSpecialGameControllerButtons(Event *event) } HandleKey(key, key_status); -#endif } void HandleSpecialGameControllerKeys(Key key, int key_status) { -#if defined(TARGET_SDL2) #if defined(KSYM_Rewind) && defined(KSYM_FastForward) int button = SDL_CONTROLLER_BUTTON_INVALID; @@ -2520,7 +2573,6 @@ void HandleSpecialGameControllerKeys(Key key, int key_status) HandleJoystickEvent(&event); } #endif -#endif } boolean DoKeysymAction(int keysym)