refactored global key handling into own class

This commit is contained in:
Thomas Jentzsch 2021-10-28 14:06:13 +02:00
parent 81832e80f1
commit 68a4c23590
8 changed files with 868 additions and 724 deletions

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,7 @@ class MouseControl;
class DialogContainer; class DialogContainer;
class PhysicalJoystick; class PhysicalJoystick;
class Variant; class Variant;
class GlobalKeyHandler;
namespace GUI { namespace GUI {
class Font; class Font;
@ -34,7 +35,6 @@ namespace GUI {
#include "Event.hxx" #include "Event.hxx"
#include "EventHandlerConstants.hxx" #include "EventHandlerConstants.hxx"
#include "Control.hxx" #include "Control.hxx"
#include "StellaKeys.hxx"
#include "PKeyboardHandler.hxx" #include "PKeyboardHandler.hxx"
#include "PJoystickHandler.hxx" #include "PJoystickHandler.hxx"
#include "bspf.hxx" #include "bspf.hxx"
@ -181,6 +181,11 @@ class EventHandler
StringList getComboListForEvent(Event::Type event) const; StringList getComboListForEvent(Event::Type event) const;
void setComboListForEvent(Event::Type event, const StringList& events); void setComboListForEvent(Event::Type event, const StringList& events);
/** Provide the joystick handler for the global hotkey handler */
PhysicalJoystickHandler& joyHandler() const { return *myPJoyHandler; }
/** Provide the keyboard handler for the global hotkey handler */
PhysicalKeyboardHandler& keyHandler() const { return *myPKeyHandler; }
/** Convert keys and physical joystick events into Stella events. */ /** Convert keys and physical joystick events into Stella events. */
Event::Type eventForKey(EventMode mode, StellaKey key, StellaMod mod) const { Event::Type eventForKey(EventMode mode, StellaKey key, StellaMod mod) const {
return myPKeyHandler->eventForKey(mode, key, mod); return myPKeyHandler->eventForKey(mode, key, mod);
@ -430,114 +435,6 @@ class EventHandler
*/ */
void removePhysicalJoystick(int index); void removePhysicalJoystick(int index);
private:
enum class AdjustSetting
{
NONE = -1,
// *** Audio & Video group ***
VOLUME,
ZOOM,
FULLSCREEN,
#ifdef ADAPTABLE_REFRESH_SUPPORT
ADAPT_REFRESH,
#endif
OVERSCAN,
TVFORMAT,
VCENTER,
ASPECT_RATIO,
VSIZE,
// Palette adjustables
PALETTE,
PALETTE_PHASE,
PALETTE_RED_SCALE,
PALETTE_RED_SHIFT,
PALETTE_GREEN_SCALE,
PALETTE_GREEN_SHIFT,
PALETTE_BLUE_SCALE,
PALETTE_BLUE_SHIFT,
PALETTE_HUE,
PALETTE_SATURATION,
PALETTE_CONTRAST,
PALETTE_BRIGHTNESS,
PALETTE_GAMMA,
// NTSC filter adjustables
NTSC_PRESET,
NTSC_SHARPNESS,
NTSC_RESOLUTION,
NTSC_ARTIFACTS,
NTSC_FRINGING,
NTSC_BLEEDING,
// Other TV effects adjustables
PHOSPHOR,
SCANLINES,
INTERPOLATION,
// *** Input group ***
DEADZONE,
ANALOG_DEADZONE,
ANALOG_SENSITIVITY,
ANALOG_LINEARITY,
DEJITTER_AVERAGING,
DEJITTER_REACTION,
DIGITAL_SENSITIVITY,
AUTO_FIRE,
FOUR_DIRECTIONS,
MOD_KEY_COMBOS,
SA_PORT_ORDER,
USE_MOUSE,
PADDLE_SENSITIVITY,
TRACKBALL_SENSITIVITY,
DRIVING_SENSITIVITY,
MOUSE_CURSOR,
GRAB_MOUSE,
LEFT_PORT,
RIGHT_PORT,
SWAP_PORTS,
SWAP_PADDLES,
PADDLE_CENTER_X,
PADDLE_CENTER_Y,
MOUSE_CONTROL,
MOUSE_RANGE,
// *** Debug group ***
STATS,
P0_ENAM,
P1_ENAM,
M0_ENAM,
M1_ENAM,
BL_ENAM,
PF_ENAM,
ALL_ENAM,
P0_CX,
P1_CX,
M0_CX,
M1_CX,
BL_CX,
PF_CX,
ALL_CX,
FIXED_COL,
COLOR_LOSS,
JITTER,
// *** Only used via direct hotkeys ***
STATE,
PALETTE_CHANGE_ATTRIBUTE,
NTSC_CHANGE_ATTRIBUTE,
CHANGE_SPEED,
// *** Ranges ***
NUM_ADJ,
START_AV_ADJ = VOLUME,
END_AV_ADJ = INTERPOLATION,
START_INPUT_ADJ = DEADZONE,
END_INPUT_ADJ = MOUSE_RANGE,
START_DEBUG_ADJ = STATS,
END_DEBUG_ADJ = JITTER,
};
enum class AdjustGroup
{
AV,
INPUT,
DEBUG,
NUM_GROUPS
};
private: private:
// Define event groups // Define event groups
static const Event::EventSet MiscEvents; static const Event::EventSet MiscEvents;
@ -566,27 +463,6 @@ class EventHandler
int getEmulActionListIndex(int idx, const Event::EventSet& events) const; int getEmulActionListIndex(int idx, const Event::EventSet& events) const;
int getActionListIndex(int idx, Event::Group group) const; int getActionListIndex(int idx, Event::Group group) const;
// The following methods are used for adjusting several settings using global hotkeys
// They return the function used to adjust the currenly selected setting
AdjustGroup getAdjustGroup();
AdjustFunction cycleAdjustSetting(int direction);
AdjustFunction getAdjustSetting(AdjustSetting setting);
// Check if the current adjustment should be repeated
bool isAdjustRepeated(AdjustSetting setting);
void setAdjustSetting(AdjustSetting setting);
PhysicalJoystickHandler& joyHandler() const { return *myPJoyHandler; }
PhysicalKeyboardHandler& keyHandler() const { return *myPKeyHandler; }
bool isJoystick(const Controller& controller) const;
bool isPaddle(const Controller& controller) const;
bool isTrackball(const Controller& controller) const;
// Check if a currently non-relevant adjustment can be skipped
bool skipAVSetting() const;
bool skipInputSetting() const;
bool skipDebugSetting() const;
private: private:
// Structure used for action menu items // Structure used for action menu items
struct ActionList { struct ActionList {
@ -595,19 +471,15 @@ class EventHandler
string key; string key;
}; };
// If true, the setting is visible and its value can be changed
bool myAdjustActive{false};
// ID of the currently selected global setting
AdjustSetting myAdjustSetting{AdjustSetting::START_AV_ADJ};
// ID of the currently selected direct hotkey setting (0 if none)
AdjustSetting myAdjustDirect{AdjustSetting::NONE};
// Global Event object // Global Event object
Event myEvent; Event myEvent;
// Indicates current overlay object // Indicates current overlay object
DialogContainer* myOverlay{nullptr}; DialogContainer* myOverlay{nullptr};
// Handler for all global key events
unique_ptr<GlobalKeyHandler> myGlobalKeyHandler;
// Handler for all keyboard-related events // Handler for all keyboard-related events
unique_ptr<PhysicalKeyboardHandler> myPKeyHandler; unique_ptr<PhysicalKeyboardHandler> myPKeyHandler;

View File

@ -0,0 +1,544 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "Console.hxx"
#include "FrameBuffer.hxx"
#include "PaletteHandler.hxx"
#include "QuadTari.hxx"
#include "Sound.hxx"
#include "StateManager.hxx"
#include "TIASurface.hxx"
#include "GlobalKeyHandler.hxx"
using namespace std::placeholders;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GlobalKeyHandler::GlobalKeyHandler(OSystem& osystem)
: myOSystem{osystem}
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool GlobalKeyHandler::handleEvent(const Event::Type event, bool pressed, bool repeated)
{
// The global settings keys change settings or values as long as the setting
// message from the previous settings event is still displayed.
// Therefore, do not change global settings/values or direct values if
// a) the setting message is no longer shown
// b) other keys have been pressed
if(!myOSystem.frameBuffer().messageShown())
{
myAdjustActive = false;
myAdjustDirect = AdjustSetting::NONE;
}
const bool adjustActive = myAdjustActive;
const AdjustSetting adjustAVDirect = myAdjustDirect;
if(pressed)
{
myAdjustActive = false;
myAdjustDirect = AdjustSetting::NONE;
}
bool handled = true;
switch(event)
{
////////////////////////////////////////////////////////////////////////
// Allow adjusting several (mostly repeated) settings using the same six hotkeys
case Event::PreviousSettingGroup:
case Event::NextSettingGroup:
if(pressed && !repeated)
{
const int direction = event == Event::PreviousSettingGroup ? -1 : +1;
AdjustGroup adjustGroup = AdjustGroup(BSPF::clampw(int(getAdjustGroup()) + direction,
0, int(AdjustGroup::NUM_GROUPS) - 1));
string msg;
switch(adjustGroup)
{
case AdjustGroup::AV:
msg = "Audio & Video";
myAdjustSetting = AdjustSetting::START_AV_ADJ;
break;
case AdjustGroup::INPUT:
msg = "Input Devices & Ports";
myAdjustSetting = AdjustSetting::START_INPUT_ADJ;
break;
case AdjustGroup::DEBUG:
msg = "Debug";
myAdjustSetting = AdjustSetting::START_DEBUG_ADJ;
break;
default:
break;
}
myOSystem.frameBuffer().showTextMessage(msg + " settings");
myAdjustActive = false;
}
break;
// Allow adjusting several (mostly repeated) settings using the same four hotkeys
case Event::PreviousSetting:
case Event::NextSetting:
if(pressed && !repeated)
{
const int direction = event == Event::PreviousSetting ? -1 : +1;
// Get (and display) the previous|next adjustment function,
// but do not change its value
cycleAdjustSetting(adjustActive ? direction : 0)(0);
// Fallback message when no message is displayed by method
//if(!myOSystem.frameBuffer().messageShown())
// myOSystem.frameBuffer().showMessage("Message " + std::to_string(int(myAdjustSetting)));
myAdjustActive = true;
}
break;
case Event::SettingDecrease:
case Event::SettingIncrease:
if(pressed)
{
const int direction = event == Event::SettingDecrease ? -1 : +1;
// if a "direct only" hotkey was pressed last, use this one
if(adjustAVDirect != AdjustSetting::NONE)
{
myAdjustDirect = adjustAVDirect;
if(!repeated || isAdjustRepeated(myAdjustDirect))
getAdjustSetting(myAdjustDirect)(direction);
}
else
{
// Get (and display) the current adjustment function,
// but only change its value if the function was already active before
if(!repeated || isAdjustRepeated(myAdjustSetting))
{
getAdjustSetting(myAdjustSetting)(adjustActive ? direction : 0);
myAdjustActive = true;
}
}
}
break;
default:
handled = false;
}
return handled;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GlobalKeyHandler::setAdjustSetting(const AdjustSetting setting)
{
myAdjustSetting = setting;
myAdjustActive = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GlobalKeyHandler::setAdjustDirect(const AdjustSetting setting)
{
myAdjustDirect = setting;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const GlobalKeyHandler::AdjustGroup GlobalKeyHandler::getAdjustGroup() const
{
if(myAdjustSetting >= AdjustSetting::START_DEBUG_ADJ && myAdjustSetting <= AdjustSetting::END_DEBUG_ADJ)
return AdjustGroup::DEBUG;
if(myAdjustSetting >= AdjustSetting::START_INPUT_ADJ && myAdjustSetting <= AdjustSetting::END_INPUT_ADJ)
return AdjustGroup::INPUT;
return AdjustGroup::AV;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool GlobalKeyHandler::isJoystick(const Controller& controller) const
{
//const Controller* pleft = &controller;
//const QuadTari* pleftQT = dynamic_cast<const QuadTari*>(pleft);
//const Controller& c = (dynamic_cast<const QuadTari*>(&controller))->firstController();
return controller.type() == Controller::Type::Joystick
|| controller.type() == Controller::Type::BoosterGrip
|| controller.type() == Controller::Type::Genesis
|| (controller.type() == Controller::Type::QuadTari
&& (isJoystick(dynamic_cast<const QuadTari*>(&controller)->firstController())
|| isJoystick(dynamic_cast<const QuadTari*>(&controller)->secondController())));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool GlobalKeyHandler::isPaddle(const Controller& controller) const
{
return controller.type() == Controller::Type::Paddles
|| controller.type() == Controller::Type::PaddlesIAxDr
|| controller.type() == Controller::Type::PaddlesIAxis
|| (controller.type() == Controller::Type::QuadTari
&& (isPaddle(dynamic_cast<const QuadTari*>(&controller)->firstController())
|| isPaddle(dynamic_cast<const QuadTari*>(&controller)->secondController())));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool GlobalKeyHandler::isTrackball(const Controller& controller) const
{
return controller.type() == Controller::Type::AmigaMouse
|| controller.type() == Controller::Type::AtariMouse
|| controller.type() == Controller::Type::TrakBall;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool GlobalKeyHandler::skipAVSetting() const
{
const bool isFullScreen = myOSystem.frameBuffer().fullScreen();
const bool isCustomPalette =
myOSystem.settings().getString("palette") == PaletteHandler::SETTING_CUSTOM;
const bool isCustomFilter =
myOSystem.settings().getInt("tv.filter") == int(NTSCFilter::Preset::CUSTOM);
const bool isSoftwareRenderer =
myOSystem.settings().getString("video") == "software";
return (myAdjustSetting == AdjustSetting::OVERSCAN && !isFullScreen)
#ifdef ADAPTABLE_REFRESH_SUPPORT
|| (myAdjustSetting == AdjustSetting::ADAPT_REFRESH && !isFullScreen)
#endif
|| (myAdjustSetting >= AdjustSetting::PALETTE_PHASE
&& myAdjustSetting <= AdjustSetting::PALETTE_BLUE_SHIFT
&& !isCustomPalette)
|| (myAdjustSetting >= AdjustSetting::NTSC_SHARPNESS
&& myAdjustSetting <= AdjustSetting::NTSC_BLEEDING
&& !isCustomFilter)
|| (myAdjustSetting == AdjustSetting::INTERPOLATION && isSoftwareRenderer);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool GlobalKeyHandler::skipInputSetting() const
{
const bool grabMouseAllowed = myOSystem.frameBuffer().grabMouseAllowed();
const bool analog = myOSystem.console().leftController().isAnalog()
|| myOSystem.console().rightController().isAnalog();
const bool joystick = isJoystick(myOSystem.console().leftController())
|| isJoystick(myOSystem.console().rightController());
const bool paddle = isPaddle(myOSystem.console().leftController())
|| isPaddle(myOSystem.console().rightController());
const bool trackball = isTrackball(myOSystem.console().leftController())
|| isTrackball(myOSystem.console().rightController());
const bool driving =
myOSystem.console().leftController().type() == Controller::Type::Driving
|| myOSystem.console().rightController().type() == Controller::Type::Driving;
const bool useMouse =
BSPF::equalsIgnoreCase("always", myOSystem.settings().getString("usemouse"))
|| (BSPF::equalsIgnoreCase("analog", myOSystem.settings().getString("usemouse"))
&& analog);
const bool stelladapter = joyHandler().hasStelladaptors();
return (!grabMouseAllowed && myAdjustSetting == AdjustSetting::GRAB_MOUSE)
|| (!joystick
&& (myAdjustSetting == AdjustSetting::DEADZONE
|| myAdjustSetting == AdjustSetting::FOUR_DIRECTIONS))
|| (!paddle
&& (myAdjustSetting == AdjustSetting::ANALOG_DEADZONE
|| myAdjustSetting == AdjustSetting::ANALOG_SENSITIVITY
|| myAdjustSetting == AdjustSetting::ANALOG_LINEARITY
|| myAdjustSetting == AdjustSetting::DEJITTER_AVERAGING
|| myAdjustSetting == AdjustSetting::DEJITTER_REACTION
|| myAdjustSetting == AdjustSetting::DIGITAL_SENSITIVITY
|| myAdjustSetting == AdjustSetting::SWAP_PADDLES
|| myAdjustSetting == AdjustSetting::PADDLE_CENTER_X
|| myAdjustSetting == AdjustSetting::PADDLE_CENTER_Y))
|| ((!paddle || !useMouse)
&& myAdjustSetting == AdjustSetting::PADDLE_SENSITIVITY)
|| ((!trackball || !useMouse)
&& myAdjustSetting == AdjustSetting::TRACKBALL_SENSITIVITY)
|| (!driving
&& myAdjustSetting == AdjustSetting::DRIVING_SENSITIVITY) // also affects digital device input sensitivity
|| ((!myOSystem.eventHandler().hasMouseControl() || !useMouse)
&& myAdjustSetting == AdjustSetting::MOUSE_CONTROL)
|| ((!paddle || !useMouse)
&& myAdjustSetting == AdjustSetting::MOUSE_RANGE)
|| (!stelladapter
&& myAdjustSetting == AdjustSetting::SA_PORT_ORDER);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool GlobalKeyHandler::skipDebugSetting() const
{
const bool isPAL = myOSystem.console().timing() == ConsoleTiming::pal;
return (myAdjustSetting == AdjustSetting::COLOR_LOSS && !isPAL);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const AdjustFunction GlobalKeyHandler::cycleAdjustSetting(int direction)
{
bool skip = false;
do
{
switch(getAdjustGroup())
{
case AdjustGroup::AV:
myAdjustSetting =
AdjustSetting(BSPF::clampw(int(myAdjustSetting) + direction,
int(AdjustSetting::START_AV_ADJ), int(AdjustSetting::END_AV_ADJ)));
// skip currently non-relevant adjustments
skip = skipAVSetting();
break;
case AdjustGroup::INPUT:
myAdjustSetting =
AdjustSetting(BSPF::clampw(int(myAdjustSetting) + direction,
int(AdjustSetting::START_INPUT_ADJ), int(AdjustSetting::END_INPUT_ADJ)));
// skip currently non-relevant adjustments
skip = skipInputSetting();
break;
case AdjustGroup::DEBUG:
myAdjustSetting =
AdjustSetting(BSPF::clampw(int(myAdjustSetting) + direction,
int(AdjustSetting::START_DEBUG_ADJ), int(AdjustSetting::END_DEBUG_ADJ)));
// skip currently non-relevant adjustments
skip = skipDebugSetting();
break;
default:
break;
}
// avoid endless loop
if(skip && !direction)
direction = 1;
} while(skip);
return getAdjustSetting(myAdjustSetting);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const AdjustFunction GlobalKeyHandler::getAdjustSetting(const AdjustSetting setting) const
{
// Notes:
// - All methods MUST show a message
// - This array MUST have the same order as AdjustSetting
const AdjustFunction ADJUST_FUNCTIONS[int(AdjustSetting::NUM_ADJ)] =
{
// *** Audio & Video settings ***
std::bind(&Sound::adjustVolume, &myOSystem.sound(), _1),
std::bind(&FrameBuffer::switchVideoMode, &myOSystem.frameBuffer(), _1),
std::bind(&FrameBuffer::toggleFullscreen, &myOSystem.frameBuffer(), _1),
#ifdef ADAPTABLE_REFRESH_SUPPORT
std::bind(&FrameBuffer::toggleAdaptRefresh, &myOSystem.frameBuffer(), _1),
#endif
std::bind(&FrameBuffer::changeOverscan, &myOSystem.frameBuffer(), _1),
std::bind(&Console::selectFormat, &myOSystem.console(), _1), // property, not persisted
std::bind(&Console::changeVerticalCenter, &myOSystem.console(), _1), // property, not persisted
std::bind(&Console::toggleCorrectAspectRatio, &myOSystem.console(), _1),
std::bind(&Console::changeVSizeAdjust, &myOSystem.console(), _1),
// Palette adjustables
std::bind(&PaletteHandler::cyclePalette, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::PHASE_SHIFT, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::RED_SCALE, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::RED_SHIFT, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::GREEN_SCALE, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::GREEN_SHIFT, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::BLUE_SCALE, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::BLUE_SHIFT, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::HUE, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::SATURATION, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::CONTRAST, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::BRIGHTNESS, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::GAMMA, _1),
// NTSC filter adjustables
std::bind(&TIASurface::changeNTSC, &myOSystem.frameBuffer().tiaSurface(), _1),
std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(),
int(NTSCFilter::Adjustables::SHARPNESS), _1),
std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(),
int(NTSCFilter::Adjustables::RESOLUTION), _1),
std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(),
int(NTSCFilter::Adjustables::ARTIFACTS), _1),
std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(),
int(NTSCFilter::Adjustables::FRINGING), _1),
std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(),
int(NTSCFilter::Adjustables::BLEEDING), _1),
std::bind(&Console::changePhosphor, &myOSystem.console(), _1),
std::bind(&TIASurface::setScanlineIntensity, &myOSystem.frameBuffer().tiaSurface(), _1),
std::bind(&Console::toggleInter, &myOSystem.console(), _1),
// *** Input settings ***
std::bind(&PhysicalJoystickHandler::changeDigitalDeadZone, &joyHandler(), _1),
std::bind(&PhysicalJoystickHandler::changeAnalogPaddleDeadZone, &joyHandler(), _1),
std::bind(&PhysicalJoystickHandler::changeAnalogPaddleSensitivity, &joyHandler(), _1),
std::bind(&PhysicalJoystickHandler::changeAnalogPaddleLinearity, &joyHandler(), _1),
std::bind(&PhysicalJoystickHandler::changePaddleDejitterAveraging, &joyHandler(), _1),
std::bind(&PhysicalJoystickHandler::changePaddleDejitterReaction, &joyHandler(), _1),
std::bind(&PhysicalJoystickHandler::changeDigitalPaddleSensitivity, &joyHandler(), _1),
std::bind(&Console::changeAutoFireRate, &myOSystem.console(), _1),
std::bind(&EventHandler::toggleAllow4JoyDirections, &myOSystem.eventHandler(), _1),
std::bind(&PhysicalKeyboardHandler::toggleModKeys, &keyHandler(), _1),
std::bind(&EventHandler::toggleSAPortOrder, &myOSystem.eventHandler(), _1),
std::bind(&EventHandler::changeMouseControllerMode, &myOSystem.eventHandler(), _1),
std::bind(&PhysicalJoystickHandler::changeMousePaddleSensitivity, &joyHandler(), _1),
std::bind(&PhysicalJoystickHandler::changeMouseTrackballSensitivity, &joyHandler(), _1),
std::bind(&PhysicalJoystickHandler::changeDrivingSensitivity, &joyHandler(), _1),
std::bind(&EventHandler::changeMouseCursor, &myOSystem.eventHandler(), _1),
std::bind(&FrameBuffer::toggleGrabMouse, &myOSystem.frameBuffer(), _1),
// Game properties/Controllers
std::bind(&Console::changeLeftController, &myOSystem.console(), _1), // property, not persisted
std::bind(&Console::changeRightController, &myOSystem.console(), _1), // property, not persisted
std::bind(&Console::toggleSwapPorts, &myOSystem.console(), _1), // property, not persisted
std::bind(&Console::toggleSwapPaddles, &myOSystem.console(), _1), // property, not persisted
std::bind(&Console::changePaddleCenterX, &myOSystem.console(), _1), // property, not persisted
std::bind(&Console::changePaddleCenterY, &myOSystem.console(), _1), // property, not persisted
std::bind(&EventHandler::changeMouseControl, &myOSystem.eventHandler(), _1), // property, not persisted
std::bind(&Console::changePaddleAxesRange, &myOSystem.console(), _1), // property, not persisted
// *** Debug settings ***
std::bind(&FrameBuffer::toggleFrameStats, &myOSystem.frameBuffer(), _1),
std::bind(&Console::toggleP0Bit, &myOSystem.console(), _1), // debug, not persisted
std::bind(&Console::toggleP1Bit, &myOSystem.console(), _1), // debug, not persisted
std::bind(&Console::toggleM0Bit, &myOSystem.console(), _1), // debug, not persisted
std::bind(&Console::toggleM1Bit, &myOSystem.console(), _1), // debug, not persisted
std::bind(&Console::toggleBLBit, &myOSystem.console(), _1), // debug, not persisted
std::bind(&Console::togglePFBit, &myOSystem.console(), _1), // debug, not persisted
std::bind(&Console::toggleBits, &myOSystem.console(), _1), // debug, not persisted
std::bind(&Console::toggleP0Collision, &myOSystem.console(), _1), // debug, not persisted
std::bind(&Console::toggleP1Collision, &myOSystem.console(), _1), // debug, not persisted
std::bind(&Console::toggleM0Collision, &myOSystem.console(), _1), // debug, not persisted
std::bind(&Console::toggleM1Collision, &myOSystem.console(), _1), // debug, not persisted
std::bind(&Console::toggleBLCollision, &myOSystem.console(), _1), // debug, not persisted
std::bind(&Console::togglePFCollision, &myOSystem.console(), _1), // debug, not persisted
std::bind(&Console::toggleCollisions, &myOSystem.console(), _1), // debug, not persisted
std::bind(&Console::toggleFixedColors, &myOSystem.console(), _1), // debug, not persisted
std::bind(&Console::toggleColorLoss, &myOSystem.console(), _1),
std::bind(&Console::toggleJitter, &myOSystem.console(), _1),
// *** Following functions are not used when cycling settings, but for "direct only" hotkeys ***
std::bind(&StateManager::changeState, &myOSystem.state(), _1), // temporary, not persisted
std::bind(&PaletteHandler::changeCurrentAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), _1),
std::bind(&TIASurface::changeCurrentNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(), _1),
std::bind(&Console::changeSpeed, &myOSystem.console(), _1),
};
return ADJUST_FUNCTIONS[int(setting)];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool GlobalKeyHandler::isAdjustRepeated(const AdjustSetting setting) const
{
const bool ADJUST_REPEATED[int(AdjustSetting::NUM_ADJ)] =
{
// *** Audio & Video group ***
true, // VOLUME
false, // ZOOM (always repeating)
false, // FULLSCREEN (always repeating)
#ifdef ADAPTABLE_REFRESH_SUPPORT
false, // ADAPT_REFRESH (always repeating)
#endif
true, // OVERSCAN
false, // TVFORMAT
true, // VCENTER
false, // ASPECT_RATIO (always repeating)
true, // VSIZE
// Palette adjustables
false, // PALETTE
true, // PALETTE_PHASE
true, // PALETTE_RED_SCALE
true, // PALETTE_RED_SHIFT
true, // PALETTE_GREEN_SCALE
true, // PALETTE_GREEN_SHIFT
true, // PALETTE_BLUE_SCALE
true, // PALETTE_BLUE_SHIFT
true, // PALETTE_HUE
true, // PALETTE_SATURATION
true, // PALETTE_CONTRAST
true, // PALETTE_BRIGHTNESS
true, // PALETTE_GAMMA
// NTSC filter adjustables
false, // NTSC_PRESET
true, // NTSC_SHARPNESS
true, // NTSC_RESOLUTION
true, // NTSC_ARTIFACTS
true, // NTSC_FRINGING
true, // NTSC_BLEEDING
// Other TV effects adjustables
true, // PHOSPHOR
true, // SCANLINES
false, // INTERPOLATION
// *** Input group ***
true, // DEADZONE
true, // ANALOG_DEADZONE
true, // ANALOG_SENSITIVITY
true, // ANALOG_LINEARITY
true, // DEJITTER_AVERAGING
true, // DEJITTER_REACTION
true, // DIGITAL_SENSITIVITY
true, // AUTO_FIRE
false, // FOUR_DIRECTIONS
false, // MOD_KEY_COMBOS
false, // SA_PORT_ORDER
false, // USE_MOUSE
true, // PADDLE_SENSITIVITY
true, // TRACKBALL_SENSITIVITY
true, // DRIVING_SENSITIVITY
false, // MOUSE_CURSOR
false, // GRAB_MOUSE
false, // LEFT_PORT
false, // RIGHT_PORT
false, // SWAP_PORTS
false, // SWAP_PADDLES
true, // PADDLE_CENTER_X
true, // PADDLE_CENTER_Y
false, // MOUSE_CONTROL
true, // MOUSE_RANGE
// *** Debug group ***
false, // STATS
false, // P0_ENAM
false, // P1_ENAM
false, // M0_ENAM
false, // M1_ENAM
false, // BL_ENAM
false, // PF_ENAM
false, // ALL_ENAM
false, // P0_CX
false, // P1_CX
false, // M0_CX
false, // M1_CX
false, // BL_CX
false, // PF_CX
false, // ALL_CX
false, // FIXED_COL
false, // COLOR_LOSS
false, // JITTER
// *** Only used via direct hotkeys ***
true, // STATE
true, // PALETTE_CHANGE_ATTRIBUTE
true, // NTSC_CHANGE_ATTRIBUTE
true, // CHANGE_SPEED
};
return ADJUST_REPEATED[int(setting)];
}

View File

@ -0,0 +1,183 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#ifndef GLOBALKEYHANDLER_HXX
#define GLOBALKEYHANDLER_HXX
#include "EventHandler.hxx"
/**
This class takes care of event handling of global hotkeys.
@author Thomas Jentzsch
*/
class GlobalKeyHandler
{
public:
GlobalKeyHandler(OSystem& osystem);
public:
enum class AdjustSetting
{
NONE = -1,
// *** Audio & Video group ***
VOLUME,
ZOOM,
FULLSCREEN,
#ifdef ADAPTABLE_REFRESH_SUPPORT
ADAPT_REFRESH,
#endif
OVERSCAN,
TVFORMAT,
VCENTER,
ASPECT_RATIO,
VSIZE,
// Palette adjustables
PALETTE,
PALETTE_PHASE,
PALETTE_RED_SCALE,
PALETTE_RED_SHIFT,
PALETTE_GREEN_SCALE,
PALETTE_GREEN_SHIFT,
PALETTE_BLUE_SCALE,
PALETTE_BLUE_SHIFT,
PALETTE_HUE,
PALETTE_SATURATION,
PALETTE_CONTRAST,
PALETTE_BRIGHTNESS,
PALETTE_GAMMA,
// NTSC filter adjustables
NTSC_PRESET,
NTSC_SHARPNESS,
NTSC_RESOLUTION,
NTSC_ARTIFACTS,
NTSC_FRINGING,
NTSC_BLEEDING,
// Other TV effects adjustables
PHOSPHOR,
SCANLINES,
INTERPOLATION,
// *** Input group ***
DEADZONE,
ANALOG_DEADZONE,
ANALOG_SENSITIVITY,
ANALOG_LINEARITY,
DEJITTER_AVERAGING,
DEJITTER_REACTION,
DIGITAL_SENSITIVITY,
AUTO_FIRE,
FOUR_DIRECTIONS,
MOD_KEY_COMBOS,
SA_PORT_ORDER,
USE_MOUSE,
PADDLE_SENSITIVITY,
TRACKBALL_SENSITIVITY,
DRIVING_SENSITIVITY,
MOUSE_CURSOR,
GRAB_MOUSE,
LEFT_PORT,
RIGHT_PORT,
SWAP_PORTS,
SWAP_PADDLES,
PADDLE_CENTER_X,
PADDLE_CENTER_Y,
MOUSE_CONTROL,
MOUSE_RANGE,
// *** Debug group ***
STATS,
P0_ENAM,
P1_ENAM,
M0_ENAM,
M1_ENAM,
BL_ENAM,
PF_ENAM,
ALL_ENAM,
P0_CX,
P1_CX,
M0_CX,
M1_CX,
BL_CX,
PF_CX,
ALL_CX,
FIXED_COL,
COLOR_LOSS,
JITTER,
// *** Only used via direct hotkeys ***
STATE,
PALETTE_CHANGE_ATTRIBUTE,
NTSC_CHANGE_ATTRIBUTE,
CHANGE_SPEED,
// *** Ranges ***
NUM_ADJ,
START_AV_ADJ = VOLUME,
END_AV_ADJ = INTERPOLATION,
START_INPUT_ADJ = DEADZONE,
END_INPUT_ADJ = MOUSE_RANGE,
START_DEBUG_ADJ = STATS,
END_DEBUG_ADJ = JITTER,
};
public:
bool handleEvent(const Event::Type event, bool pressed, bool repeated);
void setAdjustSetting(const AdjustSetting setting);
void setAdjustDirect(const AdjustSetting setting);
private:
enum class AdjustGroup
{
AV,
INPUT,
DEBUG,
NUM_GROUPS
};
private:
// The following methods are used for adjusting several settings using global hotkeys
// They return the function used to adjust the currenly selected setting
const AdjustGroup getAdjustGroup() const;
const AdjustFunction cycleAdjustSetting(int direction);
const AdjustFunction getAdjustSetting(const AdjustSetting setting) const;
// Check if the current adjustment should be repeated
bool isAdjustRepeated(const AdjustSetting setting) const;
PhysicalJoystickHandler& joyHandler() const { return myOSystem.eventHandler().joyHandler(); }
PhysicalKeyboardHandler& keyHandler() const { return myOSystem.eventHandler().keyHandler(); }
bool isJoystick(const Controller& controller) const;
bool isPaddle(const Controller& controller) const;
bool isTrackball(const Controller& controller) const;
// Check if a currently non-relevant adjustment can be skipped
bool skipAVSetting() const;
bool skipInputSetting() const;
bool skipDebugSetting() const;
private:
// Global OSystem object
OSystem& myOSystem;
// If true, the setting's message is visible and its value can be changed
bool myAdjustActive{false};
// ID of the currently selected global setting
AdjustSetting myAdjustSetting{AdjustSetting::START_AV_ADJ};
// ID of the currently selected direct hotkey setting (0 if none)
AdjustSetting myAdjustDirect{AdjustSetting::NONE};
};
#endif

View File

@ -80,6 +80,16 @@ class QuadTari : public Controller
*/ */
string name() const override; string name() const override;
/**
Returns the first attached controller.
*/
const Controller& firstController() const { return *myFirstController; }
/**
Returns the second attached controller.
*/
const Controller& secondController() const { return *mySecondController; }
/** /**
Answers whether the controller is intrinsically an analog controller. Answers whether the controller is intrinsically an analog controller.
Depends on the attached controllers. Depends on the attached controllers.

View File

@ -65,6 +65,7 @@ MODULE_OBJS := \
src/emucore/FBSurface.o \ src/emucore/FBSurface.o \
src/emucore/FSNode.o \ src/emucore/FSNode.o \
src/emucore/Genesis.o \ src/emucore/Genesis.o \
src/emucore/GlobalKeyHandler.o \
src/emucore/Joystick.o \ src/emucore/Joystick.o \
src/emucore/Keyboard.o \ src/emucore/Keyboard.o \
src/emucore/KidVid.o \ src/emucore/KidVid.o \

View File

@ -879,6 +879,7 @@
<ClCompile Include="..\emucore\EmulationTiming.cxx" /> <ClCompile Include="..\emucore\EmulationTiming.cxx" />
<ClCompile Include="..\emucore\EmulationWorker.cxx" /> <ClCompile Include="..\emucore\EmulationWorker.cxx" />
<ClCompile Include="..\emucore\FBSurface.cxx" /> <ClCompile Include="..\emucore\FBSurface.cxx" />
<ClCompile Include="..\emucore\GlobalKeyHandler.cxx" />
<ClCompile Include="..\emucore\Lightgun.cxx" /> <ClCompile Include="..\emucore\Lightgun.cxx" />
<ClCompile Include="..\emucore\MindLink.cxx" /> <ClCompile Include="..\emucore\MindLink.cxx" />
<ClCompile Include="..\emucore\OSystemStandalone.cxx" /> <ClCompile Include="..\emucore\OSystemStandalone.cxx" />
@ -2070,6 +2071,7 @@
<ClInclude Include="..\emucore\FBBackend.hxx" /> <ClInclude Include="..\emucore\FBBackend.hxx" />
<ClInclude Include="..\emucore\FBSurface.hxx" /> <ClInclude Include="..\emucore\FBSurface.hxx" />
<ClInclude Include="..\emucore\FrameBufferConstants.hxx" /> <ClInclude Include="..\emucore\FrameBufferConstants.hxx" />
<ClInclude Include="..\emucore\GlobalKeyHandler.hxx" />
<ClInclude Include="..\emucore\Lightgun.hxx" /> <ClInclude Include="..\emucore\Lightgun.hxx" />
<ClInclude Include="..\emucore\MindLink.hxx" /> <ClInclude Include="..\emucore\MindLink.hxx" />
<ClInclude Include="..\emucore\OSystemStandalone.hxx" /> <ClInclude Include="..\emucore\OSystemStandalone.hxx" />

View File

@ -1113,6 +1113,9 @@
<ClCompile Include="..\debugger\gui\CartE7Widget.cxx"> <ClCompile Include="..\debugger\gui\CartE7Widget.cxx">
<Filter>Source Files\debugger</Filter> <Filter>Source Files\debugger</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\emucore\GlobalKeyHandler.cxx">
<Filter>Source Files\emucore</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\common\bspf.hxx"> <ClInclude Include="..\common\bspf.hxx">
@ -2288,6 +2291,9 @@
<ClInclude Include="..\emucore\CartE7.hxx"> <ClInclude Include="..\emucore\CartE7.hxx">
<Filter>Header Files\emucore</Filter> <Filter>Header Files\emucore</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\emucore\GlobalKeyHandler.hxx">
<Filter>Header Files\emucore</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="stella.ico"> <None Include="stella.ico">