[GTK3] More work on preferences done

This commit is contained in:
Maximilian Mader 2019-09-27 23:10:28 +02:00
parent 4b15dc9cdf
commit f3f2e66faf
Signed by: Max
GPG Key ID: F71D56A3151C4FB3
6 changed files with 182 additions and 80 deletions

10
gtk3/macros.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef macros_h
#define macros_h
#define str(x) #x
#define xstr(x) str(x)
#define get_object(id) gtk_builder_get_object(builder, id)
#define gtkget(type, id) type(gtk_builder_get_object(builder, id))
#define itoa(val) g_strdup_printf("%i", val)
#endif /* macros_h */

View File

@ -6,12 +6,10 @@
#include <string.h>
#include <Core/gb.h>
#include "macros.h"
#include "settings.h"
#include "shader.h"
#define str(x) #x
#define xstr(x) str(x)
typedef struct UserData {
bool fullscreen;
GFile *file;
@ -57,11 +55,6 @@ static uint32_t tileset_buffer[tileset_buffer_length] = {0};
static const size_t tilemap_buffer_length = 256 * 256 * 4;
static uint32_t tilemap_buffer[tilemap_buffer_length] = {0};
// Returns a GObject by ID from our GtkBuilder instance
static GObject *get_object(gchararray id) {
return gtk_builder_get_object(builder, id);
}
static unsigned char number_of_buffers(void) {
bool should_blend = true;
@ -296,11 +289,11 @@ G_MODULE_EXPORT void gl_draw() {
G_MODULE_EXPORT void gl_finish() { }
G_MODULE_EXPORT void on_vram_viewer_realize(gpointer visible) {
G_MODULE_EXPORT void on_vram_viewer_realize() {
vram_viewer_visible = true;
}
G_MODULE_EXPORT void on_vram_viewer_unrealize(gpointer visible) {
G_MODULE_EXPORT void on_vram_viewer_unrealize() {
vram_viewer_visible = false;
}
@ -412,7 +405,19 @@ G_MODULE_EXPORT void on_rewind_duration_changed(GtkWidget *w, gpointer user_data
G_MODULE_EXPORT void on_boot_rom_location_changed(GtkWidget *w, gpointer user_data_gptr) {
GtkComboBox *box = GTK_COMBO_BOX(w);
g_print("New value: %s\n", gtk_combo_box_get_active_id(box));
const gchar *id = gtk_combo_box_get_active_id(box);
if (g_strcmp0(id, "other") == 0) {
g_print("TODO: Open path picker\n");
update_boot_rom_selector(builder);
}
else {
config.boot_rom_path = (gchar *)id;
}
}
G_MODULE_EXPORT void on_color_menubar_override_changed(GtkWidget *w, gpointer user_data_gptr) {
config.menubar_override = (gchar *)gtk_combo_box_get_active_id(GTK_COMBO_BOX(w));
}
// This functions gets called immediately after registration of the GApplication
@ -422,18 +427,25 @@ static void startup(GApplication *app, gpointer user_data_gptr) {
builder = gtk_builder_new_from_resource(RESOURCE_PREFIX "ui/window.ui");
gtk_builder_connect_signals(builder, NULL);
// Setup application actions
g_action_map_add_action_entries(G_ACTION_MAP(app), app_entries, G_N_ELEMENTS(app_entries), app);
GtkWindow *preferences = GTK_WINDOW(get_object("preferences"));
set_combo_box_row_separator_func(GTK_CONTAINER(preferences));
#if NDEBUG
// Disable when not compiled in debug mode
g_simple_action_set_enabled(G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "open_gtk_debugger")), false);
// Remove the menubar override
gtk_widget_destroy(gtkget(GTK_WIDGET, "menubar_override_selector_label"));
gtk_widget_destroy(gtkget(GTK_WIDGET, "menubar_override_selector"));
#endif
GtkWindow *preferences = GTK_WINDOW(get_object("preferences"));
g_signal_connect(preferences, "realize", G_CALLBACK(on_preferences_realize), (gpointer) builder);
init_settings(user_data->config_path, preferences);
vram_viewer = GTK_WINDOW(get_object("vram_viewer"));
set_combo_box_row_separator_func(GTK_CONTAINER(vram_viewer));
memory_viewer = GTK_WINDOW(get_object("memory_viewer"));
set_combo_box_row_separator_func(GTK_CONTAINER(memory_viewer));
console = GTK_WINDOW(get_object("console"));
printer = GTK_WINDOW(get_object("printer"));
@ -446,6 +458,11 @@ static void startup(GApplication *app, gpointer user_data_gptr) {
gl_area = GTK_GL_AREA(gtk_gl_area_new());
gtk_gl_area_set_auto_render(gl_area, false);
// Insert separators into `GtkComboBox`es
set_combo_box_row_separator_func(GTK_CONTAINER(preferences));
set_combo_box_row_separator_func(GTK_CONTAINER(vram_viewer));
set_combo_box_row_separator_func(GTK_CONTAINER(memory_viewer));
// Connect signal handlers
g_signal_connect(gl_area, "realize", G_CALLBACK(gl_init), NULL);
g_signal_connect(gl_area, "render", G_CALLBACK(gl_draw), NULL);
@ -468,9 +485,10 @@ static void startup(GApplication *app, gpointer user_data_gptr) {
gtk_container_add(GTK_CONTAINER(main_window), GTK_WIDGET(gl_area));
// Handle the whole menubar situation …
GMenuModel *menubar = get_menu_model(app, "menubar");
if (show_menubar()) {
// Show a classic menubar
GMenuModel *menubar = get_menu_model(app, "menubar");
gtk_application_set_menubar(GTK_APPLICATION(app), menubar);
}
else {
@ -483,8 +501,7 @@ static void startup(GApplication *app, gpointer user_data_gptr) {
// Hook menubar up to the hamburger button
GtkMenuButton *hamburger_button = GTK_MENU_BUTTON(get_object("hamburger_button"));
GMenuModel *hamburger_menu = get_menu_model(app, "menubar");
gtk_menu_button_set_menu_model(hamburger_button, hamburger_menu);
gtk_menu_button_set_menu_model(hamburger_button, menubar);
}
gtk_window_set_title(GTK_WINDOW(main_window), "SameBoy");

View File

@ -388,6 +388,7 @@ Author: Maximilian Mader
<item>
<attribute name="label" translatable="yes">Show GTK Debugger</attribute>
<attribute name="action">app.open_gtk_debugger</attribute>
<attribute name="hidden-when">action-disabled</attribute>
</item>
</section>
</submenu>

View File

@ -318,13 +318,7 @@ Maximilian Mader https://github.com/max-m</property>
<property name="can_focus">False</property>
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="active">0</property>
<property name="active_id">auto</property>
<items>
<item id="auto" translatable="yes">Use Built-in Boot ROMs</item>
<item translatable="yes">&lt;separator&gt;</item>
<item id="other" translatable="yes">Other</item>
</items>
<items></items>
<signal name="changed" handler="on_boot_rom_location_changed" swapped="no"/>
</object>
<packing>
@ -346,13 +340,11 @@ Maximilian Mader https://github.com/max-m</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText">
<object class="GtkComboBoxText" id="rewind_duration_selector">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="active">0</property>
<property name="active_id">10</property>
<items>
<item id="10" translatable="yes">10 Seconds</item>
<item id="30" translatable="yes">30 Seconds</item>
@ -394,13 +386,12 @@ Maximilian Mader https://github.com/max-m</property>
</packing>
</child>
<child>
<object class="GtkComboBox">
<object class="GtkComboBox" id="dmg_revision_selector">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="model">dmg_models</property>
<property name="active">3</property>
<property name="id_column">0</property>
<signal name="changed" handler="on_dmg_model_changed" swapped="no"/>
<child>
@ -431,13 +422,11 @@ Maximilian Mader https://github.com/max-m</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText">
<object class="GtkComboBoxText" id="sgb_revision_selector">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="active">0</property>
<property name="active_id">SGB1_NTSC</property>
<items>
<item id="SGB1_NTSC" translatable="yes">Super Game Boy (NTSC)</item>
<item id="SGB1_PAL" translatable="yes">Super Game Boy (PAL)</item>
@ -464,13 +453,12 @@ Maximilian Mader https://github.com/max-m</property>
</packing>
</child>
<child>
<object class="GtkComboBox">
<object class="GtkComboBox" id="cgb_revision_selector">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="model">cgb_models</property>
<property name="active">5</property>
<property name="id_column">0</property>
<signal name="changed" handler="on_cgb_model_changed" swapped="no"/>
<child>
@ -548,13 +536,11 @@ Maximilian Mader https://github.com/max-m</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText">
<object class="GtkComboBoxText" id="shader_selector">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="active">0</property>
<property name="active_id">nearest_neighbour</property>
<items>
<item id="NearestNeighbor" translatable="yes">Nearest Neighbor (Pixelated)</item>
<item id="Bilinear" translatable="yes">Bilinear (Blurry)</item>
@ -591,13 +577,11 @@ Maximilian Mader https://github.com/max-m</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText">
<object class="GtkComboBoxText" id="color_correction_selector">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="active">2</property>
<property name="active_id">emulate_hardware</property>
<items>
<item id="disabled" translatable="yes">Disabled</item>
<item id="correct_color_curves" translatable="yes">Correct Color Curves</item>
@ -613,14 +597,30 @@ Maximilian Mader https://github.com/max-m</property>
</packing>
</child>
<child>
<object class="GtkCheckButton">
<object class="GtkCheckButton" id="aspect_ratio_toggle">
<property name="label" translatable="yes">Keep Aspect Ratio</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_keep_aspect_ratio_changed" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="integer_scaling_toggle">
<property name="label" translatable="yes">Use Integer Scaling</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_use_integer_scaling_changed" swapped="no"/>
</object>
@ -631,21 +631,32 @@ Maximilian Mader https://github.com/max-m</property>
</packing>
</child>
<child>
<object class="GtkCheckButton">
<property name="label" translatable="yes">Keep Aspect Ratio</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_keep_aspect_ratio_changed" swapped="no"/>
<object class="GtkLabel" id="menubar_override_selector_label">
<property name="visible">False</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Main Menu Override</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
<property name="position">6</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="menubar_override_selector">
<property name="visible">False</property>
<property name="can_focus">False</property>
<items>
<item id="auto" translatable="yes">Automatic</item>
<item id="show" translatable="yes">Force Menubar</item>
<item id="hide" translatable="yes">Force Hamburger Menu</item>
</items>
<signal name="changed" handler="on_color_menubar_override_changed" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">7</property>
</packing>
</child>
</object>
@ -712,12 +723,11 @@ Maximilian Mader https://github.com/max-m</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText">
<object class="GtkComboBoxText" id="highpass_filter_selector">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="active">0</property>
<items>
<item id="disabled" translatable="yes">Disabled (Keep DC Offset)</item>
<item id="emulate_hardware" translatable="yes">Accurate (Emulate Hardware)</item>
@ -806,7 +816,6 @@ Maximilian Mader https://github.com/max-m</property>
<property name="margin_left">5</property>
<property name="margin_right">5</property>
<property name="active">0</property>
<property name="active_id">0</property>
<items>
<item id="0" translatable="yes">Player 1</item>
<item id="1" translatable="yes">Player 2</item>
@ -873,7 +882,6 @@ Maximilian Mader https://github.com/max-m</property>
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="active">0</property>
<property name="active_id">none</property>
<items>
<item id="none" translatable="yes">None</item>
</items>
@ -1098,6 +1106,19 @@ Maximilian Mader https://github.com/max-m</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkDrawingArea" id="printer_canvas">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>

View File

@ -13,7 +13,7 @@ void print_config(config_t *config) {
g_print("[%s]\n", #group_name); \
members
#define EXPAND_GROUP_MEMBER(member, key_type) \
#define EXPAND_GROUP_MEMBER(member, key_type, default_value) \
g_print("%s="FORMAT_FOR_KEY_TYPE(key_type)"\n", #member, config->member);
EXPAND_CONFIG
@ -33,10 +33,13 @@ void load_config_from_key_file(config_t *config, GKeyFile *key_file) {
members \
}
#define EXPAND_GROUP_MEMBER(member, key_type) \
#define EXPAND_GROUP_MEMBER(member, key_type, default_value) \
config->member = g_key_file_get_##key_type(key_file, group_name, #member, &error); \
if (error != NULL) { \
config->member = default_value; \
print_config_error(error); \
g_clear_error(&error);
g_clear_error(&error); \
}
EXPAND_CONFIG
@ -57,10 +60,10 @@ void save_config_to_key_file(config_t *config, GKeyFile *key_file) {
group_name = #name; \
members
#define EXPAND_GROUP_MEMBER_IF_0(member, key_type) \
#define EXPAND_GROUP_MEMBER_IF_0(member, key_type, default_value) \
g_key_file_set_##key_type(key_file, group_name, #member, config->member);
#define EXPAND_GROUP_MEMBER_IF_1(member, key_type) \
#define EXPAND_GROUP_MEMBER_IF_1(member, key_type, default_value) \
if (config->member != NULL) { \
g_key_file_set_##key_type(key_file, group_name, #member, config->member); \
} \
@ -76,9 +79,9 @@ void save_config_to_key_file(config_t *config, GKeyFile *key_file) {
} \
}
#define EXPAND_GROUP_MEMBER_IF_EVAL(y, member, key_type) EXPAND_GROUP_MEMBER_IF_ ## y(member, key_type)
#define EXPAND_GROUP_MEMBER_IF(member, key_type, is_pointer) EXPAND_GROUP_MEMBER_IF_EVAL(is_pointer, member, key_type)
#define EXPAND_GROUP_MEMBER(member, key_type) EXPAND_GROUP_MEMBER_IF(member, key_type, GTYPE_IS_POINTER(key_type))
#define EXPAND_GROUP_MEMBER_IF_EVAL(y, member, key_type, default_value) EXPAND_GROUP_MEMBER_IF_ ## y(member, key_type, default_value)
#define EXPAND_GROUP_MEMBER_IF(member, key_type, is_pointer, default_value) EXPAND_GROUP_MEMBER_IF_EVAL(is_pointer, member, key_type, default_value)
#define EXPAND_GROUP_MEMBER(member, key_type, default_value) EXPAND_GROUP_MEMBER_IF(member, key_type, GTYPE_IS_POINTER(key_type), default_value)
EXPAND_CONFIG
@ -90,6 +93,33 @@ void save_config_to_key_file(config_t *config, GKeyFile *key_file) {
#undef EXPAND_GROUP_MEMBER_IF_1
}
G_MODULE_EXPORT void on_preferences_realize(GtkWidget *w, gpointer builder_ptr) {
GtkWindow *preferences = GTK_WINDOW(w);
GtkBuilder *builder = (GtkBuilder *) builder_ptr;
update_boot_rom_selector(builder);
// Hook up the static preferences
gtk_combo_box_set_active_id(gtkget(GTK_COMBO_BOX, "rewind_duration_selector"), itoa(config.rewind_duration));
gtk_combo_box_set_active_id(gtkget(GTK_COMBO_BOX, "dmg_revision_selector"), config.dmg_revision_name);
gtk_combo_box_set_active_id(gtkget(GTK_COMBO_BOX, "sgb_revision_selector"), config.sgb_revision_name);
gtk_combo_box_set_active_id(gtkget(GTK_COMBO_BOX, "cgb_revision_selector"), config.cgb_revision_name);
gtk_combo_box_set_active_id(gtkget(GTK_COMBO_BOX, "shader_selector"), config.shader);
gtk_combo_box_set_active_id(gtkget(GTK_COMBO_BOX, "color_correction_selector"), config.color_correction_id);
gtk_toggle_button_set_active(gtkget(GTK_TOGGLE_BUTTON, "integer_scaling_toggle"), config.use_integer_scaling);
gtk_toggle_button_set_active(gtkget(GTK_TOGGLE_BUTTON, "aspect_ratio_toggle"), config.keep_aspect_ratio);
gtk_combo_box_set_active_id(gtkget(GTK_COMBO_BOX, "highpass_filter_selector"), config.high_pass_filter_id);
#if ! NDEBUG
gtk_combo_box_set_active_id(gtkget(GTK_COMBO_BOX, "menubar_override_selector"), config.menubar_override);
#else
if (gtkget(GTK_COMBO_BOX, "menubar_override_selector") != NULL) {
gtk_widget_destroy(GTK_WIDGET(gtkget(GTK_COMBO_BOX, "menubar_override_selector")));
gtk_widget_destroy(GTK_WIDGET(gtkget(GTK_COMBO_BOX, "menubar_override_selector_label")));
}
#endif
}
void init_settings(gchar *path, GtkWindow *preferences) {
free_settings();
key_file = g_key_file_new();
@ -148,6 +178,19 @@ void free_settings(void) {
}
}
void update_boot_rom_selector(GtkBuilder *builder) {
GtkComboBoxText *combo_box = gtkget(GTK_COMBO_BOX_TEXT, "boot_rom_selector");
gtk_combo_box_text_remove_all(combo_box);
gtk_combo_box_text_append(combo_box, "auto", "Use Built-in Boot ROMs");
gtk_combo_box_set_active_id(GTK_COMBO_BOX(combo_box), "auto");
if (config.boot_rom_path != NULL && !g_str_equal(config.boot_rom_path, "auto") && !g_str_equal(config.boot_rom_path, "other")) {
gtk_combo_box_text_append(combo_box, config.boot_rom_path, config.boot_rom_path);
gtk_combo_box_set_active_id(GTK_COMBO_BOX(combo_box), config.boot_rom_path);
}
gtk_combo_box_text_append_text(combo_box, "<separator>");
gtk_combo_box_text_append(combo_box, "other", "Other");
}
enum menubar_override get_show_menubar(void) {
if (config.menubar_override == NULL) goto default_value;

View File

@ -3,6 +3,7 @@
#include <gtk/gtk.h>
#include <Core/gb.h>
#include "macros.h"
#define SETTINGS_FILE "sameboy-gtk3-settings.ini"
@ -22,23 +23,28 @@
#define GTYPE_IS_POINTER_boolean 0
// Note: Make sure to use a member name only once for the whole config struct
//
// Macro usage:
// EXPAND_CONFIG(EXPAND_GROUP(…) EXPAND_GROUP(…) …)
// EXPAND_GROUP(group_name, group_members)
// EXPAND_GROUP_MEMBER(member_name, key_type, default_value)
#define EXPAND_CONFIG \
EXPAND_GROUP(Emulation, \
EXPAND_GROUP_MEMBER(boot_rom_path, string) /* overrides search location for boot ROMs by name */ \
EXPAND_GROUP_MEMBER(rewind_duration, integer) \
EXPAND_GROUP_MEMBER(dmg_revision_name, string) \
EXPAND_GROUP_MEMBER(sgb_revision_name, string) \
EXPAND_GROUP_MEMBER(cgb_revision_name, string) \
EXPAND_GROUP_MEMBER(boot_rom_path, string, "auto") /* overrides search location for boot ROMs by name */ \
EXPAND_GROUP_MEMBER(rewind_duration, integer, 0) \
EXPAND_GROUP_MEMBER(dmg_revision_name, string, "DMG_CPU_C") \
EXPAND_GROUP_MEMBER(sgb_revision_name, string, "SGB2") \
EXPAND_GROUP_MEMBER(cgb_revision_name, string, "CPU_CGB_E") \
) \
EXPAND_GROUP(Video, \
EXPAND_GROUP_MEMBER(shader, string) \
EXPAND_GROUP_MEMBER(color_correction_id, string) \
EXPAND_GROUP_MEMBER(keep_aspect_ratio, boolean) \
EXPAND_GROUP_MEMBER(use_integer_scaling, boolean) \
EXPAND_GROUP_MEMBER(menubar_override, string) \
EXPAND_GROUP_MEMBER(shader, string, "NearestNeighbour") \
EXPAND_GROUP_MEMBER(color_correction_id, string, "emulate_hardware") \
EXPAND_GROUP_MEMBER(keep_aspect_ratio, boolean, true) \
EXPAND_GROUP_MEMBER(use_integer_scaling, boolean, true) \
EXPAND_GROUP_MEMBER(menubar_override, string, "auto") \
) \
EXPAND_GROUP(Audio, \
EXPAND_GROUP_MEMBER(high_pass_filter_id, string) \
EXPAND_GROUP_MEMBER(high_pass_filter_id, string, "emulate_hardware") \
) \
EXPAND_GROUP(Controls, \
\
@ -46,7 +52,7 @@
typedef struct config_t {
#define EXPAND_GROUP(group_name, members) members
#define EXPAND_GROUP_MEMBER(member, key_type) GTYPE_OF_KEY_TYPE(key_type) member;
#define EXPAND_GROUP_MEMBER(member, key_type, default_value) GTYPE_OF_KEY_TYPE(key_type) member;
EXPAND_CONFIG
#undef EXPAND_GROUP
#undef EXPAND_GROUP_MEMBER
@ -62,6 +68,8 @@ gchar* settings_file_path;
GKeyFile *key_file;
config_t config;
G_MODULE_EXPORT void on_preferences_realize(GtkWidget *w, gpointer builder_ptr);
void print_config(config_t *config);
void load_config_from_key_file(config_t *config, GKeyFile *key_file);
@ -70,6 +78,8 @@ int load_settings(void);
void save_settings(void);
void free_settings(void);
void update_boot_rom_selector(GtkBuilder *builder);
enum menubar_override get_show_menubar(void);
void set_show_menubar(enum menubar_override);