|
|
1.1 root 1: /*
1.1.1.5 root 2: Hatari - shortcut.c
3:
1.1.1.16 root 4: This file is distributed under the GNU General Public License, version 2
5: or at your option any later version. Read the file gpl.txt for details.
1.1 root 6:
7: Shortcut keys
8: */
1.1.1.12 root 9: const char ShortCut_fileid[] = "Hatari shortcut.c : " __DATE__ " " __TIME__;
1.1 root 10:
1.1.1.2 root 11: #include <SDL.h>
12:
1.1 root 13: #include "main.h"
14: #include "dialog.h"
15: #include "audio.h"
1.1.1.10 root 16: #include "file.h"
17: #include "floppy.h"
1.1 root 18: #include "joy.h"
1.1.1.18 root 19: #include "keymap.h"
1.1 root 20: #include "memorySnapShot.h"
21: #include "reset.h"
22: #include "screen.h"
23: #include "screenSnapShot.h"
1.1.1.8 root 24: #include "configuration.h"
1.1 root 25: #include "shortcut.h"
1.1.1.10 root 26: #include "debugui.h"
1.1 root 27: #include "sound.h"
1.1.1.10 root 28: #include "sdlgui.h"
1.1.1.13 root 29: #include "video.h"
30: #include "avi_record.h"
1.1.1.14 root 31: #include "clocks_timings.h"
1.1.1.19 root 32: #include "statusbar.h"
1.1.1.2 root 33:
1.1.1.8 root 34: static SHORTCUTKEYIDX ShortCutKey = SHORTCUT_NONE; /* current shortcut key */
1.1 root 35:
1.1.1.4 root 36:
1.1.1.2 root 37: /*-----------------------------------------------------------------------*/
1.1.1.9 root 38: /**
39: * Shortcut to toggle full-screen
40: */
1.1.1.5 root 41: static void ShortCut_FullScreen(void)
1.1 root 42: {
1.1.1.20! root 43: static Uint32 last_ticks = 0;
! 44: Uint32 cur_ticks;
! 45:
! 46: /* SDL2 sometimes reports multiple key up and down events when toggling
! 47: * fullscreen mode, even though the key has not been released inbetween
! 48: * (likely because the SDL window focus is lost when switching mode).
! 49: * To avoid that we're going back and forth between fullscreen mode and
! 50: * windowed mode in this case, we have to ignore full screen shortcut
! 51: * events that happen too often. */
! 52: cur_ticks = SDL_GetTicks();
! 53: if (cur_ticks - last_ticks < 200)
! 54: return;
! 55: last_ticks = cur_ticks;
! 56:
1.1.1.9 root 57: if (!bInFullScreen)
58: {
59: Screen_EnterFullScreen();
60: }
61: else
62: {
63: Screen_ReturnFromFullScreen();
64: }
1.1 root 65: }
66:
1.1.1.20! root 67: /*-----------------------------------------------------------------------*/
! 68: /**
! 69: * Shortcut to toggle borders
! 70: */
! 71: static void ShortCut_Borders(void)
! 72: {
! 73: ConfigureParams.Screen.bAllowOverscan = !ConfigureParams.Screen.bAllowOverscan;
! 74: Screen_ModeChanged(false); /* false: re-create window only if size changed */
! 75: }
1.1.1.4 root 76:
77: /*-----------------------------------------------------------------------*/
1.1.1.9 root 78: /**
1.1.1.13 root 79: * Shortcut to toggle mouse grabbing mode
1.1.1.9 root 80: */
1.1.1.13 root 81: static void ShortCut_MouseGrab(void)
1.1 root 82: {
1.1.1.9 root 83: bGrabMouse = !bGrabMouse; /* Toggle flag */
1.1 root 84:
1.1.1.9 root 85: /* If we are in windowed mode, toggle the mouse cursor mode now: */
86: if (!bInFullScreen)
87: {
88: if (bGrabMouse)
89: {
90: SDL_WM_GrabInput(SDL_GRAB_ON);
91: }
92: else
93: {
94: SDL_WM_GrabInput(SDL_GRAB_OFF);
95: }
96: }
1.1 root 97: }
98:
1.1.1.4 root 99:
1.1.1.5 root 100: /*-----------------------------------------------------------------------*/
1.1.1.9 root 101: /**
102: * Shortcut to toggle YM/WAV sound recording
103: */
1.1.1.5 root 104: static void ShortCut_RecordSound(void)
1.1 root 105: {
1.1.1.9 root 106: /* Is working? */
107: if (bSoundWorking)
108: {
109: /* Are we currently recording? If so stop */
110: if (Sound_AreWeRecording())
111: {
112: /* Stop, and save */
113: Sound_EndRecording();
114: }
115: else
116: {
117: /* Begin recording */
118: Sound_BeginRecording(ConfigureParams.Sound.szYMCaptureFileName);
119: }
120: }
1.1 root 121: }
122:
1.1.1.5 root 123:
124: /*-----------------------------------------------------------------------*/
1.1.1.9 root 125: /**
126: * Shortcut to toggle screen animation recording
127: */
1.1.1.5 root 128: static void ShortCut_RecordAnimation(void)
1.1 root 129: {
1.1.1.9 root 130: /* Are we currently recording? If so stop */
1.1.1.13 root 131: if (Avi_AreWeRecording())
1.1.1.9 root 132: {
133: /* Stop */
1.1.1.13 root 134: Avi_StopRecording();
1.1.1.9 root 135: }
136: else
137: {
138: /* Start animation */
1.1.1.14 root 139: Avi_StartRecording ( ConfigureParams.Video.AviRecordFile , ConfigureParams.Screen.bCrop ,
140: ConfigureParams.Video.AviRecordFps == 0 ?
141: ClocksTimings_GetVBLPerSec ( ConfigureParams.System.nMachineType , nScreenRefreshRate ) :
142: (Uint32)ConfigureParams.Video.AviRecordFps << CLOCKS_TIMINGS_SHIFT_VBL ,
143: 1 << CLOCKS_TIMINGS_SHIFT_VBL ,
144: ConfigureParams.Video.AviRecordVcodec );
1.1.1.9 root 145: }
1.1 root 146: }
147:
1.1.1.4 root 148:
149: /*-----------------------------------------------------------------------*/
1.1.1.9 root 150: /**
151: * Shortcut to sound on/off
152: */
1.1.1.5 root 153: static void ShortCut_SoundOnOff(void)
1.1 root 154: {
1.1.1.9 root 155: /* Toggle sound on/off */
1.1.1.12 root 156: ConfigureParams.Sound.bEnableSound ^= true;
1.1.1.9 root 157:
158: /* And start/stop if need to */
159: if (!ConfigureParams.Sound.bEnableSound)
160: {
161: if (Sound_AreWeRecording())
162: Sound_EndRecording();
163: Audio_UnInit();
164: }
165: else
166: {
167: Audio_Init();
168: }
1.1 root 169: }
170:
1.1.1.5 root 171:
172: /*-----------------------------------------------------------------------*/
1.1.1.9 root 173: /**
1.1.1.10 root 174: * Shortcut to fast forward
1.1.1.9 root 175: */
1.1.1.10 root 176: static void ShortCut_FastForward(void)
1.1 root 177: {
1.1.1.9 root 178: /* If already on max speed, switch back to normal */
1.1.1.12 root 179: if (ConfigureParams.System.bFastForward == true)
1.1.1.9 root 180: {
181: /* Restore */
1.1.1.12 root 182: ConfigureParams.System.bFastForward = false;
1.1.1.9 root 183:
184: /* Reset the sound emulation variables: */
1.1.1.14 root 185: Sound_BufferIndexNeedReset = true;
1.1.1.9 root 186: }
187: else
188: {
189: /* Set maximum speed */
1.1.1.12 root 190: ConfigureParams.System.bFastForward = true;
1.1.1.9 root 191: }
1.1 root 192: }
193:
1.1.1.5 root 194:
195: /*-----------------------------------------------------------------------*/
1.1.1.9 root 196: /**
197: * Shortcut to 'Boss' key, ie minmize Window and switch to another application
198: */
1.1.1.5 root 199: static void ShortCut_BossKey(void)
1.1 root 200: {
1.1.1.9 root 201: /* If we are in full-screen, then return to a window */
202: Screen_ReturnFromFullScreen();
1.1.1.5 root 203:
1.1.1.9 root 204: if (bGrabMouse)
205: {
206: SDL_WM_GrabInput(SDL_GRAB_OFF);
1.1.1.12 root 207: bGrabMouse = false;
1.1.1.9 root 208: }
1.1.1.12 root 209: Main_PauseEmulation(true);
1.1.1.5 root 210:
1.1.1.9 root 211: /* Minimize Window and give up processing to next one! */
1.1.1.18 root 212: #if WITH_SDL2
213: SDL_MinimizeWindow(sdlWindow);
214: #else
1.1.1.9 root 215: SDL_WM_IconifyWindow();
1.1.1.18 root 216: #endif
1.1 root 217: }
218:
1.1.1.4 root 219:
220: /*-----------------------------------------------------------------------*/
1.1.1.9 root 221: /**
1.1.1.12 root 222: * Shorcut to debug interface
1.1.1.10 root 223: */
1.1.1.12 root 224: static void ShortCut_Debug(void)
1.1.1.10 root 225: {
1.1.1.12 root 226: int running;
1.1.1.10 root 227:
1.1.1.12 root 228: /* Call the debugger */
229: running = Main_PauseEmulation(true);
1.1.1.15 root 230: DebugUI(REASON_USER);
1.1.1.12 root 231: if (running)
232: Main_UnPauseEmulation();
1.1.1.10 root 233: }
234:
235:
1.1.1.12 root 236: /*-----------------------------------------------------------------------*/
237: /**
238: * Shorcut to pausing
239: */
240: static void ShortCut_Pause(void)
241: {
242: if (!Main_UnPauseEmulation())
243: Main_PauseEmulation(true);
244: }
245:
1.1.1.10 root 246: /**
247: * Shorcut to load a disk image
248: */
249: static void ShortCut_InsertDisk(int drive)
250: {
251: char *selname, *zip_path = NULL;
252: const char *tmpname;
1.1.1.17 root 253: char FileNameB[ FILENAME_MAX ];
1.1.1.10 root 254:
255: if (SDLGui_SetScreen(sdlscrn))
256: return;
257:
1.1.1.17 root 258: /* Save current names for drive 1 before checking autoinsert */
259: strcpy ( FileNameB , ConfigureParams.DiskImage.szDiskFileName[ 1 ] );
260:
1.1.1.10 root 261: if (ConfigureParams.DiskImage.szDiskFileName[drive][0])
262: tmpname = ConfigureParams.DiskImage.szDiskFileName[drive];
263: else
264: tmpname = ConfigureParams.DiskImage.szDiskImageDirectory;
265:
1.1.1.12 root 266: Main_PauseEmulation(true);
1.1.1.18 root 267: selname = SDLGui_FileSelect("Floppy image:", tmpname, &zip_path, false);
1.1.1.10 root 268: if (selname)
269: {
270: if (File_Exists(selname))
1.1.1.11 root 271: Floppy_SetDiskFileName(drive, selname, zip_path);
1.1.1.10 root 272: else
273: Floppy_SetDiskFileNameNone(drive);
1.1.1.11 root 274:
1.1.1.19 root 275: free(zip_path);
1.1.1.10 root 276: free(selname);
1.1.1.11 root 277:
278: Floppy_InsertDiskIntoDrive(0);
1.1.1.17 root 279:
280: /* Check if inserting into drive 0 also changed drive 1 with autoinsert */
281: if ( ( strcmp ( FileNameB , ConfigureParams.DiskImage.szDiskFileName[ 1 ] ) != 0 )
282: || ( strcmp ( FileNameB , ConfigureParams.DiskImage.szDiskZipPath[ 1 ] ) != 0 ) )
283: Floppy_InsertDiskIntoDrive(1);
284:
1.1.1.10 root 285: }
286: Main_UnPauseEmulation();
287: }
288:
289:
290: /*-----------------------------------------------------------------------*/
291: /**
1.1.1.9 root 292: * Check to see if pressed any shortcut keys, and call handling function
293: */
1.1.1.8 root 294: void ShortCut_ActKey(void)
1.1.1.5 root 295: {
1.1.1.9 root 296: if (ShortCutKey == SHORTCUT_NONE)
297: return;
1.1.1.8 root 298:
1.1.1.9 root 299: switch (ShortCutKey)
300: {
301: case SHORTCUT_OPTIONS:
1.1.1.19 root 302: Dialog_DoProperty(); /* Show options dialog */
1.1.1.9 root 303: break;
304: case SHORTCUT_FULLSCREEN:
1.1.1.19 root 305: ShortCut_FullScreen(); /* Switch between fullscreen/windowed mode */
1.1.1.9 root 306: break;
1.1.1.20! root 307: case SHORTCUT_BORDERS:
! 308: ShortCut_Borders(); /* Toggle Atari borders */
! 309: break;
1.1.1.13 root 310: case SHORTCUT_MOUSEGRAB:
1.1.1.19 root 311: ShortCut_MouseGrab(); /* Toggle mouse grab */
1.1.1.9 root 312: break;
313: case SHORTCUT_COLDRESET:
1.1.1.10 root 314: Main_UnPauseEmulation();
1.1.1.19 root 315: Reset_Cold(); /* Reset emulator with 'cold' (clear all) */
316: Statusbar_UpdateInfo(); /* Some infos can change after 'reset' */
1.1.1.9 root 317: break;
318: case SHORTCUT_WARMRESET:
1.1.1.10 root 319: Main_UnPauseEmulation();
1.1.1.19 root 320: Reset_Warm(); /* Emulator 'warm' reset */
321: Statusbar_UpdateInfo(); /* Some infos can change after 'reset' */
1.1.1.9 root 322: break;
323: case SHORTCUT_SCREENSHOT:
1.1.1.19 root 324: ScreenSnapShot_SaveScreen(); /* Grab screenshot */
1.1.1.9 root 325: break;
326: case SHORTCUT_BOSSKEY:
1.1.1.19 root 327: ShortCut_BossKey(); /* Boss key */
1.1.1.9 root 328: break;
1.1.1.19 root 329: case SHORTCUT_CURSOREMU: /* Toggle joystick emu on/off */
1.1.1.9 root 330: Joy_ToggleCursorEmulation();
331: break;
1.1.1.10 root 332: case SHORTCUT_FASTFORWARD:
1.1.1.19 root 333: ShortCut_FastForward(); /* Toggle Min/Max speed */
1.1.1.9 root 334: break;
335: case SHORTCUT_RECANIM:
1.1.1.19 root 336: ShortCut_RecordAnimation(); /* Record animation */
1.1.1.9 root 337: break;
338: case SHORTCUT_RECSOUND:
1.1.1.19 root 339: ShortCut_RecordSound(); /* Toggle sound recording */
1.1.1.9 root 340: break;
341: case SHORTCUT_SOUND:
1.1.1.19 root 342: ShortCut_SoundOnOff(); /* Enable/disable sound */
1.1.1.9 root 343: break;
1.1.1.12 root 344: case SHORTCUT_DEBUG:
1.1.1.19 root 345: ShortCut_Debug(); /* Invoke the Debug UI */
1.1.1.12 root 346: break;
1.1.1.10 root 347: case SHORTCUT_PAUSE:
1.1.1.19 root 348: ShortCut_Pause(); /* Invoke Pause */
1.1.1.10 root 349: break;
1.1.1.18 root 350: case SHORTCUT_JOY_0:
351: Joy_SwitchMode(0);
352: break;
353: case SHORTCUT_JOY_1:
354: Joy_SwitchMode(1);
355: break;
356: case SHORTCUT_PAD_A:
357: Joy_SwitchMode(2);
358: break;
359: case SHORTCUT_PAD_B:
360: Joy_SwitchMode(3);
361: break;
1.1.1.9 root 362: case SHORTCUT_QUIT:
1.1.1.17 root 363: Main_RequestQuit(0);
1.1.1.9 root 364: break;
365: case SHORTCUT_LOADMEM:
1.1.1.12 root 366: MemorySnapShot_Restore(ConfigureParams.Memory.szMemoryCaptureFileName, true);
1.1.1.9 root 367: break;
368: case SHORTCUT_SAVEMEM:
1.1.1.12 root 369: MemorySnapShot_Capture(ConfigureParams.Memory.szMemoryCaptureFileName, true);
1.1.1.9 root 370: break;
1.1.1.10 root 371: case SHORTCUT_INSERTDISKA:
372: ShortCut_InsertDisk(0);
373: break;
1.1.1.9 root 374: case SHORTCUT_KEYS:
375: case SHORTCUT_NONE:
376: /* ERROR: cannot happen, just make compiler happy */
377: break;
378: }
379: ShortCutKey = SHORTCUT_NONE;
380: }
381:
382:
383: /*-----------------------------------------------------------------------*/
384: /**
1.1.1.10 root 385: * Invoke shortcut identified by name. This supports only keys for
386: * functionality that cannot be invoked with command line options
1.1.1.12 root 387: * or otherwise for remote GUIs etc.
1.1.1.10 root 388: */
389: bool Shortcut_Invoke(const char *shortcut)
390: {
391: struct {
392: SHORTCUTKEYIDX id;
393: const char *name;
394: } shortcuts[] = {
1.1.1.13 root 395: { SHORTCUT_MOUSEGRAB, "mousegrab" },
1.1.1.10 root 396: { SHORTCUT_COLDRESET, "coldreset" },
397: { SHORTCUT_WARMRESET, "warmreset" },
398: { SHORTCUT_SCREENSHOT, "screenshot" },
399: { SHORTCUT_BOSSKEY, "bosskey" },
400: { SHORTCUT_RECANIM, "recanim" },
401: { SHORTCUT_RECSOUND, "recsound" },
402: { SHORTCUT_SAVEMEM, "savemem" },
403: { SHORTCUT_QUIT, "quit" },
404: { SHORTCUT_NONE, NULL }
405: };
406: int i;
407:
408: if (ShortCutKey != SHORTCUT_NONE)
409: {
410: fprintf(stderr, "Shortcut invocation failed, shortcut already active\n");
1.1.1.12 root 411: return false;
1.1.1.10 root 412: }
413: for (i = 0; shortcuts[i].name; i++)
414: {
415: if (strcmp(shortcut, shortcuts[i].name) == 0)
416: {
417: ShortCutKey = shortcuts[i].id;
418: ShortCut_ActKey();
419: ShortCutKey = SHORTCUT_NONE;
1.1.1.12 root 420: return true;
1.1.1.10 root 421: }
422: }
423: fprintf(stderr, "WARNING: unknown shortcut '%s'\n\n", shortcut);
424: fprintf(stderr, "Hatari shortcuts are:\n");
425: for (i = 0; shortcuts[i].name; i++)
426: {
427: fprintf(stderr, "- %s\n", shortcuts[i].name);
428: }
1.1.1.12 root 429: return false;
1.1.1.10 root 430: }
431:
432:
433: /*-----------------------------------------------------------------------*/
434: /**
1.1.1.9 root 435: * Check whether given key was any of the ones in given shortcut array.
436: * Return corresponding array index or SHORTCUT_NONE for no match
437: */
1.1.1.8 root 438: static SHORTCUTKEYIDX ShortCut_CheckKey(int symkey, int *keys)
439: {
1.1.1.9 root 440: SHORTCUTKEYIDX key;
1.1.1.12 root 441: for (key = SHORTCUT_OPTIONS; key < SHORTCUT_KEYS; key++)
1.1.1.9 root 442: {
443: if (symkey == keys[key])
444: return key;
445: }
446: return SHORTCUT_NONE;
1.1.1.8 root 447: }
448:
449: /*-----------------------------------------------------------------------*/
1.1.1.9 root 450: /**
451: * Check which Shortcut key is pressed/released.
452: * If press is set, store the key array index.
453: * Return zero if key didn't match to a shortcut
454: */
1.1.1.10 root 455: int ShortCut_CheckKeys(int modkey, int symkey, bool press)
1.1.1.8 root 456: {
1.1.1.9 root 457: SHORTCUTKEYIDX key;
1.1.1.8 root 458:
1.1.1.9 root 459: if (modkey & (KMOD_RALT|KMOD_LMETA|KMOD_RMETA|KMOD_MODE))
460: key = ShortCut_CheckKey(symkey, ConfigureParams.Shortcut.withModifier);
461: else
462: key = ShortCut_CheckKey(symkey, ConfigureParams.Shortcut.withoutModifier);
463:
464: if (key == SHORTCUT_NONE)
465: return 0;
466: if (press)
467: ShortCutKey = key;
468: return 1;
1.1.1.5 root 469: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.