Skip to content

Commit

Permalink
-ui/ui.cpp, ui/videoopt.cpp: Made pointer activity timeout configurable.
Browse files Browse the repository at this point in the history
-midway/wmg.cpp: Use a memory bank for NVRAM; also got rid of a really pointless trampoline function.
  • Loading branch information
cuavas committed Apr 17, 2024
1 parent 80dd068 commit 520ed5e
Show file tree
Hide file tree
Showing 6 changed files with 377 additions and 66 deletions.
46 changes: 45 additions & 1 deletion docs/source/advanced/ctrlr_config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ with a ``version`` attribute specifying the configuration format version
(currently ``10`` – MAME will not load a file using a different version). The
``mameconfig`` element contains one or more ``system`` elements, each of which
has a ``name`` attribute specifying the system(s) it applies to. Each
``system`` element contains an ``input`` element which holds the actual
``system`` element may contain an ``input`` element which holds the actual
``remap`` and ``port`` configuration elements, which will be described later.
Each ``system`` element may also contain a ``pointer_input`` element to set
pointer input options for systems with interactive artwork.

When launching an emulated system, MAME will apply configuration from ``system``
elements where the value of the ``name`` attribute meets one of the following
Expand Down Expand Up @@ -261,3 +263,45 @@ MAME applies ``mapdevice`` elements found inside the first applicable ``system``
element only. To avoid confusion, it’s simplest to place the ``system`` element
applying to all systems (``name`` attribute set to ``default``) first in the
file, and use it to assign input device numbers.


.. _ctrlrcfg-pointers:

Setting pointer input options
-----------------------------

A ``pointer_input`` element may contain ``target`` elements to set pointer input
options for each output screen or window. Each ``target`` element must have an
``index`` attribute containing the zero-based index of the screen to which it
applies.

Each ``target`` element may have an ``activity_timeout`` attribute to set the
time after which a mouse pointer that has not moved and has no buttons pressed
will be considered inactive. The value is specified in seconds, and must be in
the range of 0.1 seconds to 10 seconds, inclusive.

Each ``target`` element may have a ``hide_inactive`` element to set whether
inactive pointers may be hidden. If the value is ``0`` (zero), inactive
pointers will not be hidden. If the value is ``1``, inactive pointers may be
hidden, but layout views can still specify that inactive pointers should not be
hidden.

Here’s an example demonstrating the use of this feature:

.. code-block:: XML
<system name="default">
<pointer_input>
<target index="0" activity_timeout="1.5" />
</pointer_input>
</system>
<system name="intellec4.cpp">
<pointer_input>
<target index="0" hide_inactive="0" />
</pointer_input>
</system>
For all systems, pointers over the first output screen or window will be
considered inactive after not moving for 1.5 seconds with no buttons pressed.
For systems defined in ``intellec4.cpp``, inactive pointers over the first
window will not be hidden.
4 changes: 2 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@
# built documents.
#
# The short X.Y version.
version = '0.264'
version = '0.265'
# The full version, including alpha/beta/rc tags.
release = '0.264'
release = '0.265'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
224 changes: 212 additions & 12 deletions src/frontend/mame/ui/ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
#include "../osd/modules/lib/osdlib.h"
#include "../osd/modules/lib/osdobj_common.h"

#include <chrono>
#include <functional>
#include <type_traits>

Expand Down Expand Up @@ -189,6 +188,28 @@ struct mame_ui_manager::active_pointer
};


struct mame_ui_manager::pointer_options
{
pointer_options()
: timeout(std::chrono::seconds(3))
, hide_inactive(true)
, timeout_set(false)
, hide_inactive_set(false)
{
}

bool options_set() const
{
return timeout_set || hide_inactive_set;
}

std::chrono::steady_clock::duration timeout;
bool hide_inactive;
bool timeout_set;
bool hide_inactive_set;
};


//-------------------------------------------------
// ctor - set up the user interface
//-------------------------------------------------
Expand Down Expand Up @@ -252,8 +273,12 @@ void mame_ui_manager::init()
machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&mame_ui_manager::exit, this));
machine().configuration().config_register(
"ui_warnings",
configuration_manager::load_delegate(&mame_ui_manager::config_load, this),
configuration_manager::save_delegate(&mame_ui_manager::config_save, this));
configuration_manager::load_delegate(&mame_ui_manager::config_load_warnings, this),
configuration_manager::save_delegate(&mame_ui_manager::config_save_warnings, this));
machine().configuration().config_register(
"pointer_input",
configuration_manager::load_delegate(&mame_ui_manager::config_load_pointers, this),
configuration_manager::save_delegate(&mame_ui_manager::config_save_pointers, this));

// create mouse bitmap
uint32_t *dst = &m_mouse_bitmap.pix(0);
Expand Down Expand Up @@ -311,10 +336,14 @@ void mame_ui_manager::exit()


//-------------------------------------------------
// config_load - load configuration data
// config_load_warnings - load info on last time
// emulation status warnings showed
//-------------------------------------------------

void mame_ui_manager::config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode)
void mame_ui_manager::config_load_warnings(
config_type cfg_type,
config_level cfg_level,
util::xml::data_node const *parentnode)
{
// make sure it's relevant and there's data available
if (config_type::SYSTEM == cfg_type)
Expand Down Expand Up @@ -352,10 +381,13 @@ void mame_ui_manager::config_load(config_type cfg_type, config_level cfg_level,


//-------------------------------------------------
// config_save - save configuration data
// config_save_warnings - save information on
// last time emulation status warnings showed
//-------------------------------------------------

void mame_ui_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode)
void mame_ui_manager::config_save_warnings(
config_type cfg_type,
util::xml::data_node *parentnode)
{
// only save system-level configuration when times are valid
if ((config_type::SYSTEM == cfg_type) && (std::time_t(-1) != m_last_launch_time) && (std::time_t(-1) != m_last_warning_time))
Expand All @@ -382,6 +414,101 @@ void mame_ui_manager::config_save(config_type cfg_type, util::xml::data_node *pa
}


//-------------------------------------------------
// config_load_pointers - load pointer input
// settings
//-------------------------------------------------

void mame_ui_manager::config_load_pointers(
config_type cfg_type,
config_level cfg_level,
util::xml::data_node const *parentnode)
{
switch (cfg_type)
{
case config_type::INIT:
{
int last(-1);
for (auto const &target : machine().render().targets())
{
assert(target.index() >= 0);
if (!target.hidden())
last = (std::max)(target.index(), last);
}
m_pointer_options.resize(last + 1);
}
break;

case config_type::CONTROLLER:
case config_type::SYSTEM:
if (!parentnode)
break;
for (auto const *targetnode = parentnode->get_child("target"); targetnode; targetnode = targetnode->get_next_sibling("target"))
{
auto const index(targetnode->get_attribute_int("index", -1));
if ((0 <= index) && (m_pointer_options.size() > index))
{
auto const timeout(targetnode->get_attribute_float("activity_timeout", -1.0F));
auto const ms(std::lround(timeout * 1000.0F));
if ((100 <= ms) && (10'000 >= ms))
{
m_pointer_options[index].timeout = std::chrono::milliseconds(ms);
if (config_type::SYSTEM == cfg_type)
m_pointer_options[index].timeout_set = true;
}

auto const hide(targetnode->get_attribute_int("hide_inactive", -1));
if (0 <= hide)
{
m_pointer_options[index].hide_inactive = hide != 0;
if (config_type::SYSTEM == cfg_type)
m_pointer_options[index].hide_inactive_set = true;
}
}
}
break;

case config_type::DEFAULT:
case config_type::FINAL:
break;
}
}


//-------------------------------------------------
// config_save_pointers - save pointer input
// settings
//-------------------------------------------------

void mame_ui_manager::config_save_pointers(
config_type cfg_type,
util::xml::data_node *parentnode)
{
if (config_type::SYSTEM == cfg_type)
{
for (std::size_t i = 0; m_pointer_options.size() > i; ++i)
{
pointer_options const &options(m_pointer_options[i]);
if (options.options_set())
{
util::xml::data_node *const targetnode = parentnode->add_child("target", nullptr);
if (targetnode)
{
targetnode->set_attribute_int("index", i);
if (options.timeout_set)
{
auto const ms(std::chrono::duration_cast<std::chrono::milliseconds>(options.timeout));
targetnode->set_attribute_float("activity_timeout", float(ms.count()) * 0.001F);
}
if (options.hide_inactive_set)
targetnode->set_attribute_int("hide_inactive", options.hide_inactive);
}
}
}
}
}


//-------------------------------------------------
// initialize - initialize ui lists
//-------------------------------------------------
Expand Down Expand Up @@ -1381,14 +1508,23 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container)
display_pointer_vector pointers;
pointers.reserve(m_active_pointers.size());
auto const now(std::chrono::steady_clock::now());
auto expiry(now);
render_target *target(nullptr);
layout_view const *view(nullptr);
bool hide_inactive(true);
for (auto const &pointer : m_active_pointers)
{
layout_view const &view(pointer.target->current_view());
if (view.show_pointers())
if (pointer.target != target)
{
target = pointer.target;
view = &target->current_view();
hide_inactive = m_pointer_options[target->index()].hide_inactive && view->hide_inactive_pointers();
expiry = now - m_pointer_options[target->index()].timeout;
}
if (view->show_pointers())
{
// TODO: make timeout configurable
if (!view.hide_inactive_pointers() || (osd::ui_event_handler::pointer::PEN == pointer.type) || ((now - pointer.updated) <= std::chrono::seconds(3)))
pointers.emplace_back(display_pointer{ *pointer.target, pointer.type, pointer.x, pointer.y });
if (!hide_inactive || (osd::ui_event_handler::pointer::PEN == pointer.type) || (pointer.updated >= expiry))
pointers.emplace_back(display_pointer{ *target, pointer.type, pointer.x, pointer.y });
}
}
set_pointers(pointers.begin(), pointers.end());
Expand Down Expand Up @@ -1590,6 +1726,70 @@ void mame_ui_manager::request_quit()
}


//-------------------------------------------------
// set_pointer_activity_timeout - set per-target
// pointer activity timeout
//-------------------------------------------------

void mame_ui_manager::set_pointer_activity_timeout(int target, std::chrono::steady_clock::duration timeout) noexcept
{
assert((0 <= target) && (m_pointer_options.size() > target));
if ((0 <= target) && (m_pointer_options.size() > target))
{
m_pointer_options[target].timeout = timeout;
m_pointer_options[target].timeout_set = true;
}
}


//-------------------------------------------------
// set_hide_inactive_pointers - set per-target
// hide inactive pointers setting
//-------------------------------------------------

void mame_ui_manager::set_hide_inactive_pointers(int target, bool hide) noexcept
{
assert((0 <= target) && (m_pointer_options.size() > target));
if ((0 <= target) && (m_pointer_options.size() > target))
{
m_pointer_options[target].hide_inactive = hide;
m_pointer_options[target].hide_inactive_set = true;
}
}


//-------------------------------------------------
// pointer_activity_timeout - get per-target
// pointer activity timeout
//-------------------------------------------------

std::chrono::steady_clock::duration mame_ui_manager::pointer_activity_timeout(int target) const noexcept
{
assert((0 <= target) && (m_pointer_options.size() > target));
if ((0 <= target) && (m_pointer_options.size() > target))
return m_pointer_options[target].timeout;
else
return pointer_options().timeout;
}



//-------------------------------------------------
// hide_inactive_pointers - get per-target hide
// inactive pointers setting
//-------------------------------------------------

bool mame_ui_manager::hide_inactive_pointers(int target) const noexcept
{
assert((0 <= target) && (m_pointer_options.size() > target));
if ((0 <= target) && (m_pointer_options.size() > target))
return m_pointer_options[target].hide_inactive;
else
return pointer_options().hide_inactive;
}



/***************************************************************************
SLIDER CONTROLS
***************************************************************************/
Expand Down
Loading

2 comments on commit 520ed5e

@happppp
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This UI option is per-system, right? Not many of them have clickable artwork. Could the option be hidden for views which have no pointer? Just like the crosshair menu isn't accessible for drivers that have no crosshair.
eg. I can set the pointer delay for Space Invaders (arcade) right now and it has no effect.

Could you add CTRL+Left/Right = 1s dec/inc?

@cuavas
Copy link
Member Author

@cuavas cuavas commented on 520ed5e Apr 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The setting is per-system, per screen/window – it isn’t per view. It persists whether the current view is interactive or not. It will apply if you switch to an interactive view, or if a script marks the current view as requiring pointer display.

It isn’t really like the crosshair settings. Crosshairs are a characteristic of the machine configuration, making them more static.

Please sign in to comment.