mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
settings: route every packed-row read and write through the half accessors
The custom viewport origin and size, the window size pairs and the desktop menu window geometry each keep both axes in one settings_t word, and each menu row owns one half of it. The generic uint/int display strings, the custom viewport width/height display strings, the dropdown builders and commits, and the Qt spin box, combo box and radio button widgets all dereferenced value.target directly, so these rows showed and edited the whole word: a 960x720 viewport displayed its width as 62915280, stepped in units of 65536, clamped to 9999 in Qt, and a Qt edit or dropdown choice overwrote the partner axis. setting_uint_get/set and setting_int_get/set now live in setting_list.h so the menu and the desktop UIs share them, and all of those paths go through them. samples/settings/packed_rows drives the rows through their display strings, a right press and the dropdown, and runs in the menu harness workflow.
This commit is contained in:
1 parent
115b1eb010
commit
ea89f665f2
10 files changed
+458
-108
No files matched your search
@@ -23,6 +23,9 @@ on:
|
||||
- 'tasks/task_content*'
|
||||
- 'samples/menu/playlist_nav/**'
|
||||
- 'samples/menu/resolution_reset/**'
|
||||
- 'samples/settings/packed_rows/**'
|
||||
- 'setting_list.h'
|
||||
- 'gfx/video_defines.h'
|
||||
- '.github/workflows/Linux-menu-harness.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
@@ -32,6 +35,9 @@ on:
|
||||
- 'tasks/task_content*'
|
||||
- 'samples/menu/playlist_nav/**'
|
||||
- 'samples/menu/resolution_reset/**'
|
||||
- 'samples/settings/packed_rows/**'
|
||||
- 'setting_list.h'
|
||||
- 'gfx/video_defines.h'
|
||||
- '.github/workflows/Linux-menu-harness.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -160,6 +166,20 @@ jobs:
|
||||
./samples/menu/resolution_reset/resolution_reset_test
|
||||
make -C samples/menu/resolution_reset clean
|
||||
|
||||
- name: Build and run packed_rows_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Settings rows that each own one half of a packed settings_t
|
||||
# word - the custom viewport's origin and size, the window
|
||||
# size pair - driven through their display strings, a right
|
||||
# press and the dropdown list. Each row has to show and set
|
||||
# its own axis and leave its partner as it stands. Shares the
|
||||
# non-Qt build made above.
|
||||
samples/settings/packed_rows/build.sh
|
||||
./samples/settings/packed_rows/packed_rows_test
|
||||
make -C samples/settings/packed_rows clean
|
||||
|
||||
- name: Hot function budget
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
@@ -7572,7 +7572,7 @@ static int action_ok_push_dropdown_setting_uint_item_special(const char *path,
|
||||
value = path_value;
|
||||
}
|
||||
|
||||
*setting->value.target.unsigned_integer = value;
|
||||
setting_uint_set(setting, value);
|
||||
|
||||
if (setting->actions->change)
|
||||
setting->actions->change(setting);
|
||||
@@ -7592,12 +7592,13 @@ static int generic_action_ok_dropdown_setting(const char *path, const char *labe
|
||||
switch (setting->type)
|
||||
{
|
||||
case ST_INT:
|
||||
*setting->value.target.integer = (int32_t)((idx * setting->step) + setting->offset_by);
|
||||
setting_int_set(setting,
|
||||
(int)((idx * setting->step) + setting->offset_by));
|
||||
break;
|
||||
case ST_UINT:
|
||||
{
|
||||
unsigned value = (unsigned)((idx * setting->step) + setting->offset_by);
|
||||
*setting->value.target.unsigned_integer = value;
|
||||
setting_uint_set(setting, value);
|
||||
}
|
||||
break;
|
||||
case ST_FLOAT:
|
||||
|
||||
+12
-12
@@ -17546,7 +17546,7 @@ static bool menu_displaylist_ctl_internal(
|
||||
int32_t i_max;
|
||||
int32_t i_step;
|
||||
char val_d[16];
|
||||
int32_t orig_value = *setting->value.target.integer;
|
||||
int32_t orig_value = setting_int_get(setting);
|
||||
unsigned setting_type = MENU_SETTING_DROPDOWN_SETTING_INT_ITEM;
|
||||
float step = setting->step;
|
||||
float min = (setting->flags & SD_FLAG_ENFORCE_MINRANGE) ? setting->min : 0.00f;
|
||||
@@ -17573,7 +17573,7 @@ static bool menu_displaylist_ctl_internal(
|
||||
{
|
||||
char val_s[NAME_MAX_LENGTH];
|
||||
int val = i;
|
||||
*setting->value.target.integer = val;
|
||||
setting_int_set(setting, val);
|
||||
setting->actions->repr(setting,
|
||||
val_s, sizeof(val_s));
|
||||
if (menu_entries_append(info->list,
|
||||
@@ -17592,7 +17592,7 @@ static bool menu_displaylist_ctl_internal(
|
||||
entry_index++;
|
||||
}
|
||||
|
||||
*setting->value.target.integer = orig_value;
|
||||
setting_int_set(setting, orig_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -17710,7 +17710,7 @@ static bool menu_displaylist_ctl_internal(
|
||||
int32_t i_max;
|
||||
int32_t i_step;
|
||||
char val_d[16];
|
||||
unsigned orig_value = *setting->value.target.unsigned_integer;
|
||||
unsigned orig_value = setting_uint_get(setting);
|
||||
unsigned setting_type = MENU_SETTING_DROPDOWN_SETTING_UINT_ITEM;
|
||||
float step = setting->step;
|
||||
float min = (setting->flags & SD_FLAG_ENFORCE_MINRANGE) ? setting->min : 0.00f;
|
||||
@@ -17737,7 +17737,7 @@ static bool menu_displaylist_ctl_internal(
|
||||
{
|
||||
char val_s[NAME_MAX_LENGTH];
|
||||
int val = i;
|
||||
*setting->value.target.unsigned_integer = val;
|
||||
setting_uint_set(setting, val);
|
||||
setting->actions->repr(setting,
|
||||
val_s, sizeof(val_s));
|
||||
if (menu_entries_append(info->list,
|
||||
@@ -17756,7 +17756,7 @@ static bool menu_displaylist_ctl_internal(
|
||||
entry_index++;
|
||||
}
|
||||
|
||||
*setting->value.target.unsigned_integer = orig_value;
|
||||
setting_uint_set(setting, orig_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -17915,7 +17915,7 @@ static bool menu_displaylist_ctl_internal(
|
||||
int32_t i_max;
|
||||
int32_t i_step;
|
||||
char val_d[16];
|
||||
int32_t orig_value = *setting->value.target.integer;
|
||||
int32_t orig_value = setting_int_get(setting);
|
||||
unsigned setting_type = MENU_SETTING_DROPDOWN_SETTING_INT_ITEM_SPECIAL;
|
||||
float step = setting->step;
|
||||
float min = (setting->flags & SD_FLAG_ENFORCE_MINRANGE) ? setting->min : 0.00f;
|
||||
@@ -17942,7 +17942,7 @@ static bool menu_displaylist_ctl_internal(
|
||||
{
|
||||
char val_s[NAME_MAX_LENGTH];
|
||||
int val = i;
|
||||
*setting->value.target.integer = val;
|
||||
setting_int_set(setting, val);
|
||||
setting->actions->repr(setting,
|
||||
val_s, sizeof(val_s));
|
||||
if (menu_entries_append(info->list,
|
||||
@@ -17961,7 +17961,7 @@ static bool menu_displaylist_ctl_internal(
|
||||
entry_index++;
|
||||
}
|
||||
|
||||
*setting->value.target.integer = orig_value;
|
||||
setting_int_set(setting, orig_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -18077,7 +18077,7 @@ static bool menu_displaylist_ctl_internal(
|
||||
int32_t i_max;
|
||||
int32_t i_step;
|
||||
char val_d[16];
|
||||
unsigned orig_value = *setting->value.target.unsigned_integer;
|
||||
unsigned orig_value = setting_uint_get(setting);
|
||||
unsigned setting_type = MENU_SETTING_DROPDOWN_SETTING_UINT_ITEM_SPECIAL;
|
||||
float step = setting->step;
|
||||
float min = (setting->flags & SD_FLAG_ENFORCE_MINRANGE) ? setting->min : 0.00f;
|
||||
@@ -18104,7 +18104,7 @@ static bool menu_displaylist_ctl_internal(
|
||||
{
|
||||
char val_s[NAME_MAX_LENGTH];
|
||||
int val = i;
|
||||
*setting->value.target.unsigned_integer = val;
|
||||
setting_uint_set(setting, val);
|
||||
setting->actions->repr(setting,
|
||||
val_s, sizeof(val_s));
|
||||
if (menu_entries_append(info->list,
|
||||
@@ -18123,7 +18123,7 @@ static bool menu_displaylist_ctl_internal(
|
||||
entry_index++;
|
||||
}
|
||||
|
||||
*setting->value.target.unsigned_integer = orig_value;
|
||||
setting_uint_set(setting, orig_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+16
-58
@@ -455,51 +455,6 @@ typedef struct rarch_setting_info
|
||||
|
||||
/* SETTINGS LIST */
|
||||
|
||||
/* A UINT or INT row's value. Most rows own the word their target
|
||||
* addresses; a row flagged SD_FREE_FLAG_PACKED_HI or _LO shares one
|
||||
* with its partner axis and owns half of it -- the custom viewport's
|
||||
* four rows against settings_t's two words. The halves ride the same
|
||||
* layouts the rest of the tree reads them with, VIDEO_SCALE_PACK for
|
||||
* the size and VIDEO_POS_PACK for the origin, so nothing downstream
|
||||
* has to know a row was split. */
|
||||
static INLINE unsigned setting_uint_get(rarch_setting_t *setting)
|
||||
{
|
||||
if (setting->free_flags & SD_FREE_FLAG_PACKED_HI)
|
||||
return VIDEO_SCALE_W(*setting->value.target.unsigned_integer);
|
||||
if (setting->free_flags & SD_FREE_FLAG_PACKED_LO)
|
||||
return VIDEO_SCALE_H(*setting->value.target.unsigned_integer);
|
||||
return *setting->value.target.unsigned_integer;
|
||||
}
|
||||
|
||||
static INLINE void setting_uint_set(rarch_setting_t *setting, unsigned v)
|
||||
{
|
||||
if (setting->free_flags & SD_FREE_FLAG_PACKED_HI)
|
||||
VIDEO_SCALE_PUT_W(*setting->value.target.unsigned_integer, v);
|
||||
else if (setting->free_flags & SD_FREE_FLAG_PACKED_LO)
|
||||
VIDEO_SCALE_PUT_H(*setting->value.target.unsigned_integer, v);
|
||||
else
|
||||
*setting->value.target.unsigned_integer = v;
|
||||
}
|
||||
|
||||
static INLINE int setting_int_get(rarch_setting_t *setting)
|
||||
{
|
||||
if (setting->free_flags & SD_FREE_FLAG_PACKED_HI)
|
||||
return VIDEO_POS_X(*setting->value.target.integer);
|
||||
if (setting->free_flags & SD_FREE_FLAG_PACKED_LO)
|
||||
return VIDEO_POS_Y(*setting->value.target.integer);
|
||||
return *setting->value.target.integer;
|
||||
}
|
||||
|
||||
static INLINE void setting_int_set(rarch_setting_t *setting, int v)
|
||||
{
|
||||
if (setting->free_flags & SD_FREE_FLAG_PACKED_HI)
|
||||
VIDEO_POS_PUT_X(*setting->value.target.integer, v);
|
||||
else if (setting->free_flags & SD_FREE_FLAG_PACKED_LO)
|
||||
VIDEO_POS_PUT_Y(*setting->value.target.integer, v);
|
||||
else
|
||||
*setting->value.target.integer = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* setting_set_with_string_representation:
|
||||
* @setting : pointer to setting
|
||||
@@ -925,8 +880,7 @@ static size_t setting_get_string_representation_uint(rarch_setting_t *setting,
|
||||
char *s, size_t len)
|
||||
{
|
||||
if (setting)
|
||||
return snprintf(s, len, "%u",
|
||||
*setting->value.target.unsigned_integer);
|
||||
return snprintf(s, len, "%u", setting_uint_get(setting));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1226,7 +1180,7 @@ static size_t setting_get_string_representation_int(
|
||||
rarch_setting_t *setting, char *s, size_t len)
|
||||
{
|
||||
if (setting)
|
||||
return snprintf(s, len, "%d", *setting->value.target.integer);
|
||||
return snprintf(s, len, "%d", setting_int_get(setting));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5377,6 +5331,7 @@ static size_t setting_get_string_representation_uint_custom_vp_width(
|
||||
rarch_setting_t *setting, char *s, size_t len)
|
||||
{
|
||||
size_t _len;
|
||||
unsigned v;
|
||||
struct retro_game_geometry *geom = NULL;
|
||||
video_driver_state_t *video_st = video_state_get_ptr();
|
||||
struct retro_system_av_info *av_info = &video_st->av_info;
|
||||
@@ -5384,15 +5339,16 @@ static size_t setting_get_string_representation_uint_custom_vp_width(
|
||||
if (!setting || !av_info)
|
||||
return 0;
|
||||
geom = (struct retro_game_geometry*)&av_info->geometry;
|
||||
_len = snprintf(s, len, "%u", *setting->value.target.unsigned_integer);
|
||||
v = setting_uint_get(setting);
|
||||
_len = snprintf(s, len, "%u", v);
|
||||
if (!geom->base_width || !geom->base_height)
|
||||
return _len;
|
||||
if (!(rotation % 2) && (*setting->value.target.unsigned_integer % geom->base_width == 0))
|
||||
if (!(rotation % 2) && (v % geom->base_width == 0))
|
||||
_len += snprintf(s + _len, len - _len, " (%ux)",
|
||||
*setting->value.target.unsigned_integer / geom->base_width);
|
||||
else if ((rotation % 2) && (*setting->value.target.unsigned_integer % geom->base_height == 0))
|
||||
v / geom->base_width);
|
||||
else if ((rotation % 2) && (v % geom->base_height == 0))
|
||||
_len += snprintf(s + _len, len - _len, " (%ux)",
|
||||
*setting->value.target.unsigned_integer / geom->base_height);
|
||||
v / geom->base_height);
|
||||
return _len;
|
||||
}
|
||||
|
||||
@@ -5400,6 +5356,7 @@ static size_t setting_get_string_representation_uint_custom_vp_height(
|
||||
rarch_setting_t *setting, char *s, size_t len)
|
||||
{
|
||||
size_t _len;
|
||||
unsigned v;
|
||||
struct retro_game_geometry *geom = NULL;
|
||||
video_driver_state_t *video_st = video_state_get_ptr();
|
||||
struct retro_system_av_info *av_info = &video_st->av_info;
|
||||
@@ -5407,15 +5364,16 @@ static size_t setting_get_string_representation_uint_custom_vp_height(
|
||||
if (!setting || !av_info)
|
||||
return 0;
|
||||
geom = (struct retro_game_geometry*)&av_info->geometry;
|
||||
_len = snprintf(s, len, "%u", *setting->value.target.unsigned_integer);
|
||||
v = setting_uint_get(setting);
|
||||
_len = snprintf(s, len, "%u", v);
|
||||
if (!geom->base_width || !geom->base_height)
|
||||
return _len;
|
||||
if (!(rotation % 2) && (*setting->value.target.unsigned_integer % geom->base_height == 0))
|
||||
if (!(rotation % 2) && (v % geom->base_height == 0))
|
||||
_len += snprintf(s + _len, len - _len, " (%ux)",
|
||||
*setting->value.target.unsigned_integer / geom->base_height);
|
||||
else if ((rotation % 2) && (*setting->value.target.unsigned_integer % geom->base_width == 0))
|
||||
v / geom->base_height);
|
||||
else if ((rotation % 2) && (v % geom->base_width == 0))
|
||||
_len += snprintf(s + _len, len - _len, " (%ux)",
|
||||
*setting->value.target.unsigned_integer / geom->base_width);
|
||||
v / geom->base_width);
|
||||
return _len;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
TARGET := packed_rows_test
|
||||
|
||||
all:
|
||||
@sh ./build.sh
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET) retroarch_nomain.o retroarch_nomain.d \
|
||||
harness_main.o harness_main.d
|
||||
|
||||
.PHONY: all clean
|
||||
Executable
+69
@@ -0,0 +1,69 @@
|
||||
#!/bin/sh
|
||||
# Builds the menu packed-row settings harness.
|
||||
#
|
||||
# Like playlist_nav, this links the SHIPPING objects of a built
|
||||
# RetroArch with only main() replaced - nothing is stubbed. The rows
|
||||
# under test are the menu settings that each own one half of a packed
|
||||
# settings_t word, driven through their real action handlers, their
|
||||
# display strings and the dropdown list the menu builds for them.
|
||||
#
|
||||
# Requires a completed NON-Qt build: with Qt enabled main() lives in
|
||||
# ui_qt.o, which drags the whole Qt UI in with it. From the repo
|
||||
# root:
|
||||
#
|
||||
# ./configure --disable-qt && make
|
||||
# samples/settings/packed_rows/build.sh
|
||||
#
|
||||
# retroarch.c is recompiled here with main renamed, so the harness can
|
||||
# supply its own without having to exclude the object that holds most
|
||||
# of the frontend. Both the compile and the link reuse the project's
|
||||
# own command lines, taken from make -n, so the harness cannot drift
|
||||
# away from how the program is really built.
|
||||
set -eu
|
||||
|
||||
here=$(cd "$(dirname "$0")" && pwd)
|
||||
root=$(cd "$here/../../.." && pwd)
|
||||
|
||||
cd "$root"
|
||||
|
||||
if [ ! -f obj-unix/release/retroarch.o ]; then
|
||||
echo "build RetroArch first: ./configure --disable-qt && make" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cc_line=$(mktemp)
|
||||
ld_line=$(mktemp)
|
||||
trap 'rm -f "$cc_line" "$ld_line"' EXIT
|
||||
|
||||
# The project's own compile line for retroarch.o ...
|
||||
touch retroarch.c
|
||||
make -n 2>/dev/null | grep -E '\-o obj-unix/release/retroarch\.o' | head -1 > "$cc_line"
|
||||
if [ ! -s "$cc_line" ]; then
|
||||
echo "could not determine the compile command for retroarch.o" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ... reused twice: once for retroarch.c with main renamed out of the
|
||||
# way, once for the harness itself, so both are built exactly the way
|
||||
# the frontend is.
|
||||
sed 's#-o obj-unix/release/retroarch\.o#-Dmain=rarch_harness_unused_main -o samples/settings/packed_rows/retroarch_nomain.o#' \
|
||||
"$cc_line" | sh
|
||||
|
||||
sed -e 's#-o obj-unix/release/retroarch\.o#-o samples/settings/packed_rows/harness_main.o#' \
|
||||
-e 's# retroarch\.c# samples/settings/packed_rows/packed_rows_test.c#' \
|
||||
"$cc_line" | sh
|
||||
|
||||
# The project's own link line, with retroarch.o swapped for the pair
|
||||
# above. Removing the binary first is what makes make -n emit it.
|
||||
rm -f retroarch
|
||||
make -n 2>/dev/null | grep -E ' -o retroarch ' | tail -1 > "$ld_line"
|
||||
if [ ! -s "$ld_line" ]; then
|
||||
echo "could not determine the link command" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sed -e 's#obj-unix/release/retroarch\.o#samples/settings/packed_rows/retroarch_nomain.o samples/settings/packed_rows/harness_main.o#' \
|
||||
-e 's#-o retroarch #-o samples/settings/packed_rows/packed_rows_test #' \
|
||||
"$ld_line" | sh
|
||||
|
||||
echo "built samples/settings/packed_rows/packed_rows_test"
|
||||
@@ -0,0 +1,253 @@
|
||||
/* Menu rows that own one half of a packed settings_t word.
|
||||
*
|
||||
* The custom viewport keeps its origin and its size in one word each,
|
||||
* and the window size pair shares one the same way; the menu still
|
||||
* shows one row per axis. Links the shipping objects with only main()
|
||||
* replaced, boots the menu headless and drives those rows through
|
||||
* the paths a person takes:
|
||||
*
|
||||
* - the value a row displays is its own axis, not the whole word;
|
||||
* - a right press steps that axis by one and leaves its partner as
|
||||
* it stands;
|
||||
* - the dropdown the menu opens for a row marks the current value,
|
||||
* and choosing an entry sets that axis alone.
|
||||
*
|
||||
* Requires a completed non-Qt build:
|
||||
*
|
||||
* ./configure --disable-qt && make
|
||||
* samples/settings/packed_rows/build.sh
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <boolean.h>
|
||||
#include <lists/file_list.h>
|
||||
#include <time/rtime.h>
|
||||
#include <file/config_file.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <features/features_cpu.h>
|
||||
|
||||
#include "../../../configuration.h"
|
||||
#include "../../../retroarch.h"
|
||||
#include "../../../setting_list.h"
|
||||
#include "../../../gfx/video_defines.h"
|
||||
#include "../../../menu/menu_setting.h"
|
||||
#include "../../../menu/menu_driver.h"
|
||||
#include "../../../menu/menu_entries.h"
|
||||
#include "../../../msg_hash.h"
|
||||
#include "../../../frontend/frontend_driver.h"
|
||||
|
||||
static unsigned failures = 0;
|
||||
|
||||
#define CHECK(cond, ...) \
|
||||
do { \
|
||||
if (!(cond)) \
|
||||
{ \
|
||||
fprintf(stderr, "FAIL %s:%d: ", __FILE__, __LINE__); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
fprintf(stderr, "\n"); \
|
||||
failures++; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static long shown(rarch_setting_t *s)
|
||||
{
|
||||
char buf[128];
|
||||
buf[0] = '\0';
|
||||
if (s && s->actions && s->actions->repr)
|
||||
s->actions->repr(s, buf, sizeof(buf));
|
||||
return strtol(buf, NULL, 10);
|
||||
}
|
||||
|
||||
static void press_right(rarch_setting_t *s)
|
||||
{
|
||||
if (s->actions && s->actions->right)
|
||||
s->actions->right(s, 0, false);
|
||||
}
|
||||
|
||||
static file_list_t *selection_buf(void)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_list_t *menu_list = menu_st->entries.list;
|
||||
return menu_list ? MENU_LIST_GET_SELECTION(menu_list, 0) : NULL;
|
||||
}
|
||||
|
||||
/* Index of the dropdown entry whose path is exactly @path. */
|
||||
static int find_entry(const char *path)
|
||||
{
|
||||
file_list_t *buf = selection_buf();
|
||||
size_t i;
|
||||
if (!buf)
|
||||
return -1;
|
||||
for (i = 0; i < buf->size; i++)
|
||||
if (buf->list[i].path && !strcmp(buf->list[i].path, path))
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* One menu frame; a pushed dropdown is built on the next one. */
|
||||
static void run_frame(void)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_driver_iterate(menu_st, disp_get_ptr(), anim_get_ptr(),
|
||||
config_get_ptr(), MENU_ACTION_NOOP,
|
||||
cpu_features_get_time_usec());
|
||||
}
|
||||
|
||||
static void press_ok_at(size_t i)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_entry_t entry;
|
||||
menu_st->selection_ptr = i;
|
||||
MENU_ENTRY_INITIALIZE(entry);
|
||||
entry.flags |= MENU_ENTRY_FLAG_PATH_ENABLED
|
||||
| MENU_ENTRY_FLAG_LABEL_ENABLED
|
||||
| MENU_ENTRY_FLAG_RICH_LABEL_ENABLED
|
||||
| MENU_ENTRY_FLAG_VALUE_ENABLED
|
||||
| MENU_ENTRY_FLAG_SUBLABEL_ENABLED;
|
||||
menu_entry_get(&entry, 0, i, NULL, true);
|
||||
menu_entry_action(&entry, i, MENU_ACTION_OK);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char fixture_dir[512];
|
||||
char cmd[700];
|
||||
static char cfg_path[640];
|
||||
char *rarch_argv[8];
|
||||
int rarch_argc = 0;
|
||||
rarch_setting_t *w, *h, *x, *y, *ww;
|
||||
settings_t *settings;
|
||||
int idx;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
snprintf(fixture_dir, sizeof(fixture_dir),
|
||||
"/tmp/packed_rows_%ld", (long)getpid());
|
||||
snprintf(cmd, sizeof(cmd), "mkdir -p %s", fixture_dir);
|
||||
if (system(cmd) != 0)
|
||||
return 1;
|
||||
|
||||
rarch_argv[rarch_argc++] = (char*)"retroarch";
|
||||
rarch_argv[rarch_argc++] = (char*)"--menu";
|
||||
rarch_argv[rarch_argc++] = (char*)"--config";
|
||||
rarch_argv[rarch_argc++] = cfg_path;
|
||||
|
||||
config_file_set_io_default(config_file_io_filestream());
|
||||
rtime_init();
|
||||
retroarch_config_init();
|
||||
retroarch_ctl(RARCH_CTL_STATE_FREE, NULL);
|
||||
frontend_driver_init_first(NULL);
|
||||
{
|
||||
FILE *cfg;
|
||||
snprintf(cfg_path, sizeof(cfg_path), "%s/harness.cfg",
|
||||
fixture_dir);
|
||||
if ((cfg = fopen(cfg_path, "wb")))
|
||||
{
|
||||
fprintf(cfg, "video_driver = \"null\"\n");
|
||||
fprintf(cfg, "audio_driver = \"null\"\n");
|
||||
fprintf(cfg, "input_driver = \"null\"\n");
|
||||
fprintf(cfg, "input_joypad_driver = \"null\"\n");
|
||||
fprintf(cfg, "menu_driver = \"rgui\"\n");
|
||||
fprintf(cfg, "custom_viewport_width = \"960\"\n");
|
||||
fprintf(cfg, "custom_viewport_height = \"720\"\n");
|
||||
fprintf(cfg, "custom_viewport_x = \"-12\"\n");
|
||||
fprintf(cfg, "custom_viewport_y = \"34\"\n");
|
||||
fprintf(cfg, "video_windowed_position_width = \"1280\"\n");
|
||||
fprintf(cfg, "video_windowed_position_height = \"720\"\n");
|
||||
fclose(cfg);
|
||||
}
|
||||
}
|
||||
|
||||
if (!retroarch_main_init(rarch_argc, rarch_argv))
|
||||
{
|
||||
fprintf(stderr, "FAIL: retroarch_main_init failed\n");
|
||||
return 1;
|
||||
}
|
||||
settings = config_get_ptr();
|
||||
retroarch_menu_running();
|
||||
|
||||
w = menu_setting_find_enum(MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_WIDTH);
|
||||
h = menu_setting_find_enum(MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_HEIGHT);
|
||||
x = menu_setting_find_enum(MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_X);
|
||||
y = menu_setting_find_enum(MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_Y);
|
||||
ww = menu_setting_find_enum(MENU_ENUM_LABEL_VIDEO_WINDOW_WIDTH);
|
||||
CHECK(w && h && x && y && ww, "fixture: a packed row was not found");
|
||||
if (!(w && h && x && y && ww))
|
||||
goto done;
|
||||
|
||||
CHECK(VIDEO_SCALE_W(settings->video_vp_custom.dims) == 960
|
||||
&& VIDEO_SCALE_H(settings->video_vp_custom.dims) == 720,
|
||||
"fixture: custom viewport size did not load as 960x720");
|
||||
|
||||
/* Each row shows its own axis. */
|
||||
CHECK(shown(w) == 960, "width row shows %ld, not 960", shown(w));
|
||||
CHECK(shown(h) == 720, "height row shows %ld, not 720", shown(h));
|
||||
CHECK(shown(x) == -12, "x row shows %ld, not -12", shown(x));
|
||||
CHECK(shown(y) == 34, "y row shows %ld, not 34", shown(y));
|
||||
CHECK(shown(ww) == 1280, "window width row shows %ld, not 1280",
|
||||
shown(ww));
|
||||
|
||||
/* A right press moves one axis by one step. */
|
||||
press_right(w);
|
||||
CHECK(shown(w) == 961, "width after right shows %ld, not 961",
|
||||
shown(w));
|
||||
CHECK(VIDEO_SCALE_H(settings->video_vp_custom.dims) == 720,
|
||||
"width right press changed height to %u",
|
||||
VIDEO_SCALE_H(settings->video_vp_custom.dims));
|
||||
press_right(x);
|
||||
CHECK(shown(x) == -11, "x after right shows %ld, not -11", shown(x));
|
||||
CHECK(VIDEO_POS_Y(settings->video_vp_custom.pos) == 34,
|
||||
"x right press changed y to %d",
|
||||
VIDEO_POS_Y(settings->video_vp_custom.pos));
|
||||
|
||||
/* The dropdown for the window width row: it marks the current
|
||||
* value, building it leaves the word as it was, and choosing an
|
||||
* entry sets the width alone. */
|
||||
CHECK(ww->actions && ww->actions->ok,
|
||||
"fixture: window width row has no ok action");
|
||||
if (ww->actions && ww->actions->ok)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
unsigned before = settings->uints.window_position_dims;
|
||||
|
||||
ww->actions->ok(ww, 0, false);
|
||||
run_frame();
|
||||
CHECK(settings->uints.window_position_dims == before,
|
||||
"building the dropdown changed the window size word");
|
||||
idx = find_entry("1280");
|
||||
CHECK(idx >= 0, "dropdown has no 1280 entry");
|
||||
CHECK(idx >= 0 && menu_st->selection_ptr == (size_t)idx,
|
||||
"dropdown marks entry %u, not the current 1280 at %d",
|
||||
(unsigned)menu_st->selection_ptr, idx);
|
||||
idx = find_entry("1288");
|
||||
CHECK(idx >= 0, "dropdown has no 1288 entry");
|
||||
if (idx >= 0)
|
||||
{
|
||||
press_ok_at((size_t)idx);
|
||||
run_frame();
|
||||
CHECK(VIDEO_SCALE_W(settings->uints.window_position_dims) == 1288,
|
||||
"choosing 1288 set width %u",
|
||||
VIDEO_SCALE_W(settings->uints.window_position_dims));
|
||||
CHECK(VIDEO_SCALE_H(settings->uints.window_position_dims) == 720,
|
||||
"choosing a width changed height to %u",
|
||||
VIDEO_SCALE_H(settings->uints.window_position_dims));
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
snprintf(cmd, sizeof(cmd), "rm -rf %s", fixture_dir);
|
||||
if (system(cmd) != 0) { /* fixture dir left behind; harmless */ }
|
||||
|
||||
if (failures)
|
||||
{
|
||||
fprintf(stderr, "packed_rows_test: %u failure(s)\n", failures);
|
||||
return 1;
|
||||
}
|
||||
printf("packed_rows_test: all packed rows edit their own half\n");
|
||||
return 0;
|
||||
}
|
||||
+56
-5
@@ -16,9 +16,15 @@
|
||||
#ifndef __SETTING_LIST_H
|
||||
#define __SETTING_LIST_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
#include <retro_common_api.h>
|
||||
#include <retro_inline.h>
|
||||
|
||||
#include "gfx/video_defines.h"
|
||||
|
||||
#include "command.h"
|
||||
#include "msg_hash.h"
|
||||
@@ -103,12 +109,14 @@ enum settings_free_flags
|
||||
* target that addresses a packed word rather than a value of its
|
||||
* own, and the bit says which half of it the row edits: the high
|
||||
* half for a width or an x, the low half for a height or a y.
|
||||
* Set on the custom viewport's four rows, whose settings_t pair
|
||||
* is one word each for the origin and the size.
|
||||
* Set on every row whose settings_t value shares one word with a
|
||||
* partner axis: the custom viewport's origin and size, the window
|
||||
* size pairs and the desktop menu window geometry.
|
||||
*
|
||||
* Reads and writes of such a row go through setting_uint_get /
|
||||
* setting_uint_set and the signed pair, never through
|
||||
* value.target directly. */
|
||||
* Anything that can reach such a row - the generic ST_UINT and
|
||||
* ST_INT handlers, the dropdown lists and the desktop UIs - reads
|
||||
* and writes it through setting_uint_get / setting_uint_set and
|
||||
* the signed pair below, never through value.target directly. */
|
||||
SD_FREE_FLAG_PACKED_HI = (1 << 4),
|
||||
SD_FREE_FLAG_PACKED_LO = (1 << 5)
|
||||
};
|
||||
@@ -220,6 +228,49 @@ struct rarch_setting
|
||||
uint8_t index;
|
||||
};
|
||||
|
||||
/* An ST_UINT or ST_INT row's value. Most rows own the word their
|
||||
* target addresses; a row flagged SD_FREE_FLAG_PACKED_HI or _LO owns
|
||||
* one half of it, in VIDEO_SCALE_PACK's layout for a uint row and
|
||||
* VIDEO_POS_PACK's for an int row, and a write leaves the partner
|
||||
* half as it stands. */
|
||||
static INLINE unsigned setting_uint_get(const rarch_setting_t *setting)
|
||||
{
|
||||
if (setting->free_flags & SD_FREE_FLAG_PACKED_HI)
|
||||
return VIDEO_SCALE_W(*setting->value.target.unsigned_integer);
|
||||
if (setting->free_flags & SD_FREE_FLAG_PACKED_LO)
|
||||
return VIDEO_SCALE_H(*setting->value.target.unsigned_integer);
|
||||
return *setting->value.target.unsigned_integer;
|
||||
}
|
||||
|
||||
static INLINE void setting_uint_set(rarch_setting_t *setting, unsigned v)
|
||||
{
|
||||
if (setting->free_flags & SD_FREE_FLAG_PACKED_HI)
|
||||
VIDEO_SCALE_PUT_W(*setting->value.target.unsigned_integer, v);
|
||||
else if (setting->free_flags & SD_FREE_FLAG_PACKED_LO)
|
||||
VIDEO_SCALE_PUT_H(*setting->value.target.unsigned_integer, v);
|
||||
else
|
||||
*setting->value.target.unsigned_integer = v;
|
||||
}
|
||||
|
||||
static INLINE int setting_int_get(const rarch_setting_t *setting)
|
||||
{
|
||||
if (setting->free_flags & SD_FREE_FLAG_PACKED_HI)
|
||||
return VIDEO_POS_X(*setting->value.target.integer);
|
||||
if (setting->free_flags & SD_FREE_FLAG_PACKED_LO)
|
||||
return VIDEO_POS_Y(*setting->value.target.integer);
|
||||
return *setting->value.target.integer;
|
||||
}
|
||||
|
||||
static INLINE void setting_int_set(rarch_setting_t *setting, int v)
|
||||
{
|
||||
if (setting->free_flags & SD_FREE_FLAG_PACKED_HI)
|
||||
VIDEO_POS_PUT_X(*setting->value.target.integer, v);
|
||||
else if (setting->free_flags & SD_FREE_FLAG_PACKED_LO)
|
||||
VIDEO_POS_PUT_Y(*setting->value.target.integer, v);
|
||||
else
|
||||
*setting->value.target.integer = v;
|
||||
}
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -545,7 +545,6 @@ void StringComboBox::paintEvent(QPaintEvent *event)
|
||||
UIntComboBox::UIntComboBox(rarch_setting_t *setting, QWidget *parent) :
|
||||
QComboBox(parent)
|
||||
,m_setting(setting)
|
||||
,m_value(setting->value.target.unsigned_integer)
|
||||
{
|
||||
float min = (setting->flags & SD_FLAG_ENFORCE_MINRANGE) ? setting->min : 0.00f;
|
||||
float max = (setting->flags & SD_FLAG_ENFORCE_MAXRANGE) ? setting->max : 999.00f;
|
||||
@@ -560,7 +559,6 @@ UIntComboBox::UIntComboBox(rarch_setting_t *setting, QWidget *parent) :
|
||||
UIntComboBox::UIntComboBox(rarch_setting_t *setting, double min, double max, QWidget *parent) :
|
||||
QComboBox(parent)
|
||||
,m_setting(setting)
|
||||
,m_value(setting->value.target.unsigned_integer)
|
||||
{
|
||||
populate(min, max);
|
||||
|
||||
@@ -572,7 +570,7 @@ UIntComboBox::UIntComboBox(rarch_setting_t *setting, double min, double max, QWi
|
||||
void UIntComboBox::populate(double min, double max)
|
||||
{
|
||||
float i;
|
||||
unsigned orig_value = *m_setting->value.target.unsigned_integer;
|
||||
unsigned orig_value = setting_uint_get(m_setting);
|
||||
float step = m_setting->step;
|
||||
bool checked_found = false;
|
||||
unsigned count = 0;
|
||||
@@ -584,7 +582,7 @@ void UIntComboBox::populate(double min, double max)
|
||||
char val_s[NAME_MAX_LENGTH];
|
||||
unsigned val = (unsigned)i;
|
||||
|
||||
*m_setting->value.target.unsigned_integer = val;
|
||||
setting_uint_set(m_setting, val);
|
||||
|
||||
m_setting->actions->repr(m_setting, val_s, sizeof(val_s));
|
||||
|
||||
@@ -600,7 +598,7 @@ void UIntComboBox::populate(double min, double max)
|
||||
count++;
|
||||
}
|
||||
|
||||
*m_setting->value.target.unsigned_integer = orig_value;
|
||||
setting_uint_set(m_setting, orig_value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -616,21 +614,20 @@ void UIntComboBox::onCurrentIndexChanged(int index)
|
||||
{
|
||||
(void)(index);
|
||||
|
||||
*m_value = currentData().toUInt();
|
||||
setting_uint_set(m_setting, currentData().toUInt());
|
||||
|
||||
setting_generic_handle_change(m_setting);
|
||||
}
|
||||
|
||||
void UIntComboBox::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
setCurrentText(m_hash.value(*m_value));
|
||||
setCurrentText(m_hash.value(setting_uint_get(m_setting)));
|
||||
QComboBox::paintEvent(event);
|
||||
}
|
||||
|
||||
UIntSpinBox::UIntSpinBox(rarch_setting_t *setting, QWidget *parent) :
|
||||
QSpinBox(parent)
|
||||
,m_setting(setting)
|
||||
,m_value(setting->value.target.unsigned_integer)
|
||||
{
|
||||
setRange(
|
||||
qt_setting_bound(setting, SD_FLAG_ENFORCE_MINRANGE, setting->min, 0),
|
||||
@@ -648,13 +645,13 @@ UIntSpinBox::UIntSpinBox(msg_hash_enums enum_idx, QWidget *parent) :
|
||||
|
||||
void UIntSpinBox::onValueChanged(int value)
|
||||
{
|
||||
*m_value = value;
|
||||
setting_uint_set(m_setting, (unsigned)value);
|
||||
setting_generic_handle_change(m_setting);
|
||||
}
|
||||
|
||||
void UIntSpinBox::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
int shown = qt_spinbox_shown(this, (double)*m_value);
|
||||
int shown = qt_spinbox_shown(this, (double)setting_uint_get(m_setting));
|
||||
|
||||
if (value() != shown)
|
||||
{
|
||||
@@ -717,17 +714,16 @@ void SizeSpinBox::paintEvent(QPaintEvent *event)
|
||||
UIntRadioButton::UIntRadioButton(msg_hash_enums enum_idx, unsigned value, QWidget *parent) :
|
||||
QRadioButton(parent)
|
||||
,m_setting(menu_setting_find_enum(enum_idx))
|
||||
,m_target(m_setting->value.target.unsigned_integer)
|
||||
,m_value(value)
|
||||
{
|
||||
char val_s[NAME_MAX_LENGTH];
|
||||
unsigned orig_value = *m_setting->value.target.unsigned_integer;
|
||||
unsigned orig_value = setting_uint_get(m_setting);
|
||||
|
||||
*m_setting->value.target.unsigned_integer = value;
|
||||
setting_uint_set(m_setting, value);
|
||||
|
||||
m_setting->actions->repr(m_setting, val_s, sizeof(val_s));
|
||||
|
||||
*m_setting->value.target.unsigned_integer = orig_value;
|
||||
setting_uint_set(m_setting, orig_value);
|
||||
|
||||
setText(val_s);
|
||||
|
||||
@@ -741,7 +737,6 @@ UIntRadioButton::UIntRadioButton(const QString &text,
|
||||
rarch_setting_t *setting, unsigned value, QWidget *parent) :
|
||||
QRadioButton(text, parent)
|
||||
,m_setting(setting)
|
||||
,m_target(setting->value.target.unsigned_integer)
|
||||
,m_value(value)
|
||||
{
|
||||
connect(this, SIGNAL(clicked(bool)), this, SLOT(onClicked(bool)));
|
||||
@@ -749,13 +744,13 @@ UIntRadioButton::UIntRadioButton(const QString &text,
|
||||
|
||||
void UIntRadioButton::onClicked(bool)
|
||||
{
|
||||
*m_target = m_value;
|
||||
setting_uint_set(m_setting, m_value);
|
||||
setting_generic_handle_change(m_setting);
|
||||
}
|
||||
|
||||
void UIntRadioButton::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
if (*m_target == m_value)
|
||||
if (setting_uint_get(m_setting) == m_value)
|
||||
setChecked(true);
|
||||
else
|
||||
setChecked(false);
|
||||
@@ -766,7 +761,6 @@ void UIntRadioButton::paintEvent(QPaintEvent *event)
|
||||
UIntRadioButtons::UIntRadioButtons(rarch_setting_t *setting, QWidget *parent) :
|
||||
QGroupBox(setting->short_description, parent)
|
||||
,m_setting(setting)
|
||||
,m_value(setting->value.target.unsigned_integer)
|
||||
,m_buttonGroup(new QButtonGroup(this))
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
@@ -776,7 +770,7 @@ UIntRadioButtons::UIntRadioButtons(rarch_setting_t *setting, QWidget *parent) :
|
||||
* is bounded to [0, INT_MAX], and at most QT_RADIO_BUTTONS_MAX
|
||||
* buttons are made, which also bounds a row with no enforced
|
||||
* maximum. */
|
||||
unsigned orig_value = *setting->value.target.unsigned_integer;
|
||||
unsigned orig_value = setting_uint_get(setting);
|
||||
unsigned min = (unsigned)qt_setting_bound(setting,
|
||||
SD_FLAG_ENFORCE_MINRANGE, setting->min < 0.0f ? 0.0 : setting->min, 0);
|
||||
unsigned max = (unsigned)qt_setting_bound(setting,
|
||||
@@ -800,7 +794,7 @@ UIntRadioButtons::UIntRadioButtons(rarch_setting_t *setting, QWidget *parent) :
|
||||
char val_s[NAME_MAX_LENGTH];
|
||||
QRadioButton *button = NULL;
|
||||
|
||||
*setting->value.target.unsigned_integer = i;
|
||||
setting_uint_set(setting, i);
|
||||
|
||||
setting->actions->repr(setting, val_s, sizeof(val_s));
|
||||
|
||||
@@ -821,7 +815,7 @@ UIntRadioButtons::UIntRadioButtons(rarch_setting_t *setting, QWidget *parent) :
|
||||
i += step;
|
||||
}
|
||||
|
||||
*setting->value.target.unsigned_integer = orig_value;
|
||||
setting_uint_set(setting, orig_value);
|
||||
}
|
||||
add_sublabel_and_whats_this(this, m_setting);
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
@@ -836,7 +830,7 @@ UIntRadioButtons::UIntRadioButtons(msg_hash_enums enum_idx, QWidget *parent) :
|
||||
|
||||
void UIntRadioButtons::onButtonClicked(int id)
|
||||
{
|
||||
*m_value = id;
|
||||
setting_uint_set(m_setting, (unsigned)id);
|
||||
|
||||
setting_generic_handle_change(m_setting);
|
||||
}
|
||||
@@ -844,7 +838,6 @@ void UIntRadioButtons::onButtonClicked(int id)
|
||||
IntSpinBox::IntSpinBox(rarch_setting_t *setting, QWidget *parent) :
|
||||
QSpinBox(parent)
|
||||
,m_setting(setting)
|
||||
,m_value(setting->value.target.integer)
|
||||
{
|
||||
setRange(
|
||||
qt_setting_bound(setting, SD_FLAG_ENFORCE_MINRANGE, setting->min, INT_MIN),
|
||||
@@ -859,13 +852,13 @@ IntSpinBox::IntSpinBox(rarch_setting_t *setting, QWidget *parent) :
|
||||
|
||||
void IntSpinBox::onValueChanged(int value)
|
||||
{
|
||||
*m_value = value;
|
||||
setting_int_set(m_setting, value);
|
||||
setting_generic_handle_change(m_setting);
|
||||
}
|
||||
|
||||
void IntSpinBox::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
int shown = qt_spinbox_shown(this, (double)*m_value);
|
||||
int shown = qt_spinbox_shown(this, (double)setting_int_get(m_setting));
|
||||
|
||||
if (value() != shown)
|
||||
{
|
||||
|
||||
@@ -364,7 +364,6 @@ private slots:
|
||||
private:
|
||||
void populate(double min, double max);
|
||||
rarch_setting_t *m_setting;
|
||||
unsigned *m_value;
|
||||
QHash<unsigned, QString> m_hash;
|
||||
};
|
||||
|
||||
@@ -379,7 +378,6 @@ private slots:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
private:
|
||||
rarch_setting_t *m_setting;
|
||||
unsigned *m_target;
|
||||
unsigned m_value;
|
||||
};
|
||||
|
||||
@@ -395,7 +393,6 @@ private slots:
|
||||
void onButtonClicked(int id);
|
||||
private:
|
||||
rarch_setting_t *m_setting;
|
||||
unsigned *m_value;
|
||||
QButtonGroup *m_buttonGroup;
|
||||
};
|
||||
|
||||
@@ -410,7 +407,6 @@ private slots:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
private:
|
||||
rarch_setting_t *m_setting;
|
||||
unsigned *m_value;
|
||||
};
|
||||
|
||||
class SizeSpinBox : public QSpinBox
|
||||
@@ -438,7 +434,6 @@ private slots:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
private:
|
||||
rarch_setting_t *m_setting;
|
||||
int *m_value;
|
||||
};
|
||||
|
||||
class FloatSpinBox : public QDoubleSpinBox
|
||||
|
||||
Reference in new issue
Block a user