diff --git a/gtk/meson.build b/gtk/meson.build index 9973f089..f4cbf9fa 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -23,12 +23,9 @@ args += [ '-DDATADIR="' + appdatadir + '"', '-DSNES9XLOCALEDIR="' + localedir + subdir('data') subdir('po') -glib_dep = dependency('glib-2.0', version: '> 2.28') -gthread_dep = dependency('gthread-2.0', version: '>= 2.6') -gobject_dep = dependency('gobject-2.0', version: '>= 2.6') sdl2_dep = dependency('sdl2') -deps += [ glib_dep, gthread_dep, gobject_dep, sdl2_dep ] +deps += sdl2_dep c_compiler = meson.get_compiler('c') @@ -36,16 +33,7 @@ if c_compiler.version().version_compare('>=7.0.0') and c_compiler.get_id() == 'g args += '-Wno-format-truncation' endif -if get_option('gtk3') and not get_option('gtk2') - message('Building with GTK+-3.0') - gtk_dep = dependency('gtk+-3.0', version: '>= 3.22') - gtk_ver = 3 -else - message('Building with GTK+-2.0') - gtk_dep = dependency('gtk+-2.0', version: '>= 2.16') - gtk_ver = 2 -endif - +gtk_dep = dependency('gtkmm-3.0', version: '>= 3.22') deps += gtk_dep x11_dep = c_compiler.find_library('X11') @@ -125,7 +113,7 @@ if slang and opengl endif wayland = get_option('wayland') -if wayland and gtk_ver == 3 +if wayland wayland_dep = dependency('wayland-egl', required: false) if wayland_dep.found() @@ -320,7 +308,7 @@ srcs += [ '../filter/snes_ntsc.h', '../filter/snes_ntsc_impl.h', '../filter/snes_ntsc.c', - 'src/gtk_2_3_compat.h', + 'src/gtk_compat.h', 'src/gtk_sound_driver_sdl.h', 'src/gtk_sound_driver_sdl.cpp', '../fxinst.cpp', @@ -405,7 +393,7 @@ libjma_srcs = [ libjma = static_library('jma', libjma_srcs, c_args: args, - cpp_args: [args, '-fexceptions'], + cpp_args: args, include_directories: include_directories(includes)) sourcify = executable('sourcify', 'src/sourcify.c', native: true) @@ -418,7 +406,7 @@ snes9x_gtk = executable('snes9x-gtk', srcs, gtk_snes9x_ui_cpp, c_args: args, - cpp_args: [args, '-fno-exceptions', '-fno-rtti'], + cpp_args: args, dependencies: deps, include_directories: include_directories(includes), link_with: libjma, @@ -431,7 +419,6 @@ summary = [ ' appdatadir: ' + appdatadir, ' localedir: ' + localedir, '[Options] Build type: ' + get_option('buildtype'), - ' GTK+ version: ' + gtk_ver.to_string(), ' Wayland: ' + wayland.to_string(), ' OpenGL: ' + opengl.to_string(), ' slang shaders: ' + slang.to_string(), diff --git a/gtk/meson_options.txt b/gtk/meson_options.txt index b458b3b5..2f6a7964 100644 --- a/gtk/meson_options.txt +++ b/gtk/meson_options.txt @@ -11,8 +11,6 @@ option('xbrz', type: 'boolean', value: true, description: 'Enable th option('zlib', type: 'boolean', value: true, description: 'Enable gzip compression') option('system-zip', type: 'boolean', value: true, description: 'Build using system minizip library') option('screenshot', type: 'boolean', value: true, description: 'Enable screenshots') -option('gtk3', type: 'boolean', value: true, description: 'Build with GTK+ 3.0 as the toolkit') option('wayland', type: 'boolean', value: true, description: 'Build support for Wayland') -option('gtk2', type: 'boolean', value: false, description: 'Build with GTK+ 2.0 as the toolkit') option('dangerous-hacks', type: 'boolean', value: false, description: 'Allow dangerous hacks to be enabled') option('appdatadir', type: 'string' , value: '', description: 'Snes9x-only data directory (default: datadir/snes9x)') diff --git a/gtk/src/background_particles.h b/gtk/src/background_particles.h index 132279ce..c0dfbb4e 100644 --- a/gtk/src/background_particles.h +++ b/gtk/src/background_particles.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef __BACKGROUND_PARTICLES_H +#define __BACKGROUND_PARTICLES_H #include #include #include @@ -49,4 +50,5 @@ class Particles uint16_t color_table[32]; }; -} // namespace Background \ No newline at end of file +} // namespace Background +#endif // __BACKGROUND_PARTICLES_H \ No newline at end of file diff --git a/gtk/src/gtk_2_3_compat.h b/gtk/src/gtk_2_3_compat.h deleted file mode 100644 index acef998b..00000000 --- a/gtk/src/gtk_2_3_compat.h +++ /dev/null @@ -1,60 +0,0 @@ -/*****************************************************************************\ - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - This file is licensed under the Snes9x License. - For further information, consult the LICENSE file in the root directory. -\*****************************************************************************/ - -#ifndef __GTK_2_3_COMPAT_H -#define __GTK_2_3_COMPAT_H - -#include -#include -#include - -#if GTK_MAJOR_VERSION >= 3 - -#include - -#ifndef USE_WAYLAND -#undef GDK_WINDOWING_WAYLAND -#endif - -#ifdef GDK_WINDOWING_WAYLAND -#include -#endif - -#else // GTK+ 2.0 - -#define GDK_WINDOWING_X11 -#define GDK_IS_X11_WINDOW(window) true -#define GDK_IS_X11_DISPLAY(display) true -#define gdk_x11_window_get_xid(window) GDK_WINDOW_XWINDOW (window) - -inline void gdk_x11_display_error_trap_push(GdkDisplay *dpy) -{ - gdk_error_trap_push(); -} - -inline void gdk_x11_display_error_trap_pop_ignored(GdkDisplay *dpy) -{ - if (gdk_error_trap_pop()) - { - } -} - -inline void gdk_window_get_geometry (GdkWindow *window, - gint *x, - gint *y, - gint *width, - gint *height) -{ - gdk_window_get_geometry (window, x, y, width, height, NULL); -} - -#endif - -#ifdef GDK_WINDOWING_X11 -#include -#endif - -#endif diff --git a/gtk/src/gtk_binding.cpp b/gtk/src/gtk_binding.cpp index dfa2cf21..51241d5e 100644 --- a/gtk/src/gtk_binding.cpp +++ b/gtk/src/gtk_binding.cpp @@ -10,22 +10,22 @@ #include "gtk_s9x.h" #include "gtk_binding.h" -Binding::Binding () +Binding::Binding() { value = 0; } -Binding::Binding (GdkEventKey *event) +Binding::Binding(GdkEventKey *event) { - event->keyval = gdk_keyval_to_lower (event->keyval); + event->keyval = gdk_keyval_to_lower(event->keyval); value = BINDING_KEY | (event->keyval & BINDING_KEY_MASK); /* Strip modifiers from modifiers */ if (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R || - event->keyval == GDK_Shift_L || - event->keyval == GDK_Shift_R || - event->keyval == GDK_Alt_L || + event->keyval == GDK_Shift_L || + event->keyval == GDK_Shift_R || + event->keyval == GDK_Alt_L || event->keyval == GDK_Alt_R) { return; @@ -41,7 +41,7 @@ Binding::Binding (GdkEventKey *event) value |= BINDING_ALT; } -Binding::Binding (unsigned int key, bool ctrl, bool shift, bool alt) +Binding::Binding(unsigned int key, bool ctrl, bool shift, bool alt) { value = BINDING_KEY; @@ -54,23 +54,21 @@ Binding::Binding (unsigned int key, bool ctrl, bool shift, bool alt) value |= BINDING_ALT; } -Binding::Binding (unsigned int device, - unsigned int button, - unsigned int threshold) +Binding::Binding(unsigned int device, unsigned int button, unsigned int threshold) { value = BINDING_JOY; - value |= JOY_DEVICE_MASK (device + 1); + value |= JOY_DEVICE_MASK(device + 1); value |= BINDING_KEY_MASK & button; if (button >= 512) - value |= THRESHOLD_MASK (threshold); + value |= THRESHOLD_MASK(threshold); } -Binding::Binding (unsigned int val) +Binding::Binding(unsigned int val) { value = val; } -Binding::Binding (const Binding& binding) +Binding::Binding(const Binding &binding) { this->value = binding.value; } @@ -83,88 +81,75 @@ Binding &Binding::operator=(const Binding &binding) bool Binding::operator==(const Binding &binding) { - if ((value & ~BINDING_THRESHOLD_MASK) == - (binding.value & ~BINDING_THRESHOLD_MASK)) + if ((value & ~BINDING_THRESHOLD_MASK) == (binding.value & ~BINDING_THRESHOLD_MASK)) return true; return false; } -void -Binding::clear () +void Binding::clear() { value = 0; } -unsigned int -Binding::hex () +unsigned int Binding::hex() { return value; } -unsigned int -Binding::base_hex () +unsigned int Binding::base_hex() { return (value & ~BINDING_THRESHOLD_MASK); } -bool -Binding::is_joy () +bool Binding::is_joy() { return (value & BINDING_JOY); } -bool -Binding::is_key () +bool Binding::is_key() { return (value & BINDING_KEY); } -unsigned int -Binding::get_key () +unsigned int Binding::get_key() { return (value & BINDING_KEY_MASK); } -unsigned int -Binding::get_device () +unsigned int Binding::get_device() { - return JOY_DEVICE_UNMASK (value); + return JOY_DEVICE_UNMASK(value); } -unsigned int -Binding::get_threshold () +unsigned int Binding::get_threshold() { - return THRESHOLD_UNMASK (value); + return THRESHOLD_UNMASK(value); } -unsigned int -Binding::get_axis () +unsigned int Binding::get_axis() { - return JOY_AXIS_UNMASK (value); + return JOY_AXIS_UNMASK(value); } -GdkModifierType -Binding::get_gdk_modifiers () +Gdk::ModifierType Binding::get_gdk_modifiers() { - return (GdkModifierType) (((BINDING_CTRL & value) ? GDK_CONTROL_MASK : 0) | - ((BINDING_ALT & value) ? GDK_MOD1_MASK : 0) | - ((BINDING_SHIFT & value) ? GDK_SHIFT_MASK : 0)); + return (Gdk::ModifierType)(((BINDING_CTRL & value) ? Gdk::CONTROL_MASK : 0) | + ((BINDING_ALT & value) ? Gdk::MOD1_MASK : 0) | + ((BINDING_SHIFT & value) ? Gdk::SHIFT_MASK : 0)); } -bool -Binding::is_positive () +bool Binding::is_positive() { - return JOY_DIRECTION_UNMASK (value) == AXIS_POS; + return JOY_DIRECTION_UNMASK(value) == AXIS_POS; } -bool -Binding::is_negative () +bool Binding::is_negative() { - return JOY_DIRECTION_UNMASK (value) == AXIS_NEG; + return JOY_DIRECTION_UNMASK(value) == AXIS_NEG; } -Binding::Binding (const char *raw_string) +Binding::Binding(const char *raw_string) { value = 0; @@ -172,33 +157,33 @@ Binding::Binding (const char *raw_string) return; char substr[80]; - if (sscanf (raw_string, "Keyboard %79s", substr) == 1) + if (sscanf(raw_string, "Keyboard %79s", substr) == 1) { bool ctrl = false; bool shift = false; - bool alt= false; + bool alt = false; bool direct = false; unsigned int keyval = 0; char *key; - if (!strchr (substr, '+')) + if (!strchr(substr, '+')) direct = true; - key = strtok (substr, "+"); + key = strtok(substr, "+"); while (key) { - if (strstr (key, "Alt") && !direct) + if (strstr(key, "Alt") && !direct) alt = true; - else if (strstr (key, "Ctrl") && !direct) + else if (strstr(key, "Ctrl") && !direct) ctrl = true; - else if (strstr (key, "Shift") && !direct) + else if (strstr(key, "Shift") && !direct) shift = true; else { - keyval = gdk_keyval_from_name (key); + keyval = gdk_keyval_from_name(key); } - key = strtok (NULL, "+"); + key = strtok(NULL, "+"); } if (keyval != GDK_KEY_VoidSymbol) @@ -206,7 +191,7 @@ Binding::Binding (const char *raw_string) else value = 0; } - else if (!strncmp (raw_string, "Joystick", 8)) + else if (!strncmp(raw_string, "Joystick", 8)) { unsigned int axis; unsigned int button; @@ -215,15 +200,14 @@ Binding::Binding (const char *raw_string) char posneg; const char *substr = &raw_string[8]; - if (sscanf (substr, "%u Axis %u %c %u", &device, &axis, &posneg, &percent) == 4) + if (sscanf(substr, "%u Axis %u %c %u", &device, &axis, &posneg, &percent) == 4) { - value = Binding(device - 1, JOY_AXIS (axis, posneg == '+' ? AXIS_POS : AXIS_NEG), percent).value; + value = Binding(device - 1, JOY_AXIS(axis, posneg == '+' ? AXIS_POS : AXIS_NEG), percent).value; } - else if (sscanf (substr, "%u Button %u", &device, &button) == 2) + else if (sscanf(substr, "%u Button %u", &device, &button) == 2) { value = Binding(device - 1, button, 0).value; } - } } @@ -234,8 +218,7 @@ std::string Binding::as_string() return std::string(buf); } -void -Binding::to_string (char *str, bool translate) +void Binding::to_string(char *str, bool translate) { char buf[256]; @@ -244,22 +227,22 @@ Binding::to_string (char *str, bool translate) str[0] = '\0'; - if (is_key ()) + if (is_key()) { char *keyval_name = NULL; - unsigned int keyval = gdk_keyval_to_lower (get_key ()); - keyval_name = gdk_keyval_name (keyval); + unsigned int keyval = gdk_keyval_to_lower(get_key()); + keyval_name = gdk_keyval_name(keyval); if (keyval_name == NULL) { - sprintf (buf, _("Unknown")); + sprintf(buf, _("Unknown")); } else { - memset (buf, 0, 256); - strncpy (buf, - keyval_name, - 255); + memset(buf, 0, 256); + strncpy(buf, + keyval_name, + 255); } if (translate) @@ -267,29 +250,29 @@ Binding::to_string (char *str, bool translate) if (buf[i] == '_') buf[i] = ' '; - sprintf (str, _("Keyboard %s%s%s%s"), - (value & BINDING_SHIFT) ? "Shift+" : "", - (value & BINDING_CTRL) ? "Ctrl+" : "", - (value & BINDING_ALT) ? "Alt+" : "", - buf); + sprintf(str, _("Keyboard %s%s%s%s"), + (value & BINDING_SHIFT) ? "Shift+" : "", + (value & BINDING_CTRL) ? "Ctrl+" : "", + (value & BINDING_ALT) ? "Alt+" : "", + buf); } - else if (is_joy ()) + else if (is_joy()) { - if ((get_key ()) >= 512) - sprintf (buf, - _("Axis %u %s %u%%"), - get_axis (), - is_positive () ? "+" : "-", - get_threshold ()); + if ((get_key()) >= 512) + sprintf(buf, + _("Axis %u %s %u%%"), + get_axis(), + is_positive() ? "+" : "-", + get_threshold()); else - sprintf (buf, _("Button %u"), get_key ()); + sprintf(buf, _("Button %u"), get_key()); - sprintf (str, _("Joystick %u %s"), get_device (), buf); + sprintf(str, _("Joystick %u %s"), get_device(), buf); } else { - sprintf (str, _("Unset")); + sprintf(str, _("Unset")); } } diff --git a/gtk/src/gtk_binding.h b/gtk/src/gtk_binding.h index 2ecf9433..1c2ec3ed 100644 --- a/gtk/src/gtk_binding.h +++ b/gtk/src/gtk_binding.h @@ -7,7 +7,7 @@ #ifndef __GTK_BINDING_H #define __GTK_BINDING_H -#include "gtk_2_3_compat.h" +#include "gtk_compat.h" #include #define AXIS_POS 1 @@ -32,36 +32,36 @@ #define BINDING_MOUSE_BUTTON1 0x42000001 #define BINDING_MOUSE_BUTTON2 0x42000002 -class Binding +class Binding { - public: - Binding (unsigned int key, bool ctrl, bool shift, bool alt); - Binding (unsigned int device, unsigned int button, unsigned int threshold); - Binding (const Binding &binding); - Binding &operator=(const Binding &binding); - bool operator==(const Binding &binding); - Binding (GdkEventKey *event); - Binding (unsigned int); - Binding (); - Binding (const char *str); - void to_string (char *str, bool translate = true); - std::string as_string(); - unsigned int hex (); - unsigned int base_hex (); - void clear (); - bool is_joy (); - bool is_key (); - bool is_mouse (); - bool is_positive (); - bool is_negative (); - unsigned int get_key (); - unsigned int get_device (); - unsigned int get_threshold (); - unsigned int get_axis (); - GdkModifierType get_gdk_modifiers (); - - private: - unsigned int value; + public: + Binding(unsigned int key, bool ctrl, bool shift, bool alt); + Binding(unsigned int device, unsigned int button, unsigned int threshold); + Binding(const Binding &binding); + Binding &operator=(const Binding &binding); + bool operator==(const Binding &binding); + Binding(GdkEventKey *event); + Binding(unsigned int); + Binding(); + Binding(const char *str); + void to_string(char *str, bool translate = true); + std::string as_string(); + unsigned int hex(); + unsigned int base_hex(); + void clear(); + bool is_joy(); + bool is_key(); + bool is_mouse(); + bool is_positive(); + bool is_negative(); + unsigned int get_key(); + unsigned int get_device(); + unsigned int get_threshold(); + unsigned int get_axis(); + Gdk::ModifierType get_gdk_modifiers(); + + private: + unsigned int value; }; - + #endif /* __GTK_BINDING_H_ */ diff --git a/gtk/src/gtk_builder_window.cpp b/gtk/src/gtk_builder_window.cpp index 846301e4..4fc5cb5f 100644 --- a/gtk/src/gtk_builder_window.cpp +++ b/gtk/src/gtk_builder_window.cpp @@ -9,242 +9,147 @@ #include "gtk_builder_window.h" extern const unsigned char snes9x_ui[]; -extern const int snes9x_ui_size; +extern const int snes9x_ui_size; -GtkBuilderWindow::GtkBuilderWindow (const char *root) +Glib::RefPtr global_builder; +bool global_builder_created = false; + +GtkBuilderWindow::GtkBuilderWindow(const char *root) { - builder = gtk_builder_new (); - gtk_builder_add_from_string (builder, - (const gchar *) snes9x_ui, - snes9x_ui_size, - NULL); - - window = get_widget (root); -} - -GtkBuilderWindow::~GtkBuilderWindow () -{ - gtk_widget_destroy (window); - g_object_unref (builder); -} - -GtkWidget * -GtkBuilderWindow::get_widget (const char *name) -{ - return GTK_WIDGET (gtk_builder_get_object (builder, name)); -} - -void -GtkBuilderWindow::signal_connection_func (GtkBuilder *builder, - GObject *object, - const gchar *signal_name, - const char *handler_name, - GObject *connect_object, - GConnectFlags flags, - gpointer data) -{ - GCallback function = NULL; - GtkBuilderWindow *window = (GtkBuilderWindow *) data; - GtkBuilderWindowCallbacks *callbacks = window->callbacks; - - for (int i = 0; callbacks[i].signal; i++) + if (!global_builder_created) { - if (!strcmp (handler_name, callbacks[i].signal)) - { - function = callbacks[i].function; - break; - } + global_builder = Gtk::Builder::create(); + global_builder->add_from_string((const gchar *)snes9x_ui, snes9x_ui_size); + global_builder_created = true; } - if (function) - { - if (connect_object) - { - fprintf (stderr, "Error: found a persistent object signal.\n"); - g_signal_connect_object (object, - signal_name, - function, - connect_object, - flags); - } - else - { - g_signal_connect_data (object, - signal_name, - function, - data, - NULL, - flags); - } - } - else - { - } + window = get_object(root); } -void -GtkBuilderWindow::signal_connect (GtkBuilderWindowCallbacks *callbacks) +GtkBuilderWindow::~GtkBuilderWindow() { - if (!callbacks) - return; - - this->callbacks = callbacks; - - gtk_builder_connect_signals_full (builder, - signal_connection_func, - (gpointer) this); - - this->callbacks = NULL; } -void -GtkBuilderWindow::enable_widget (const char *name, bool state) +void GtkBuilderWindow::enable_widget(const char *name, bool state) { - gtk_widget_set_sensitive (get_widget (name), state); + auto widget = get_object(name); + widget->set_sensitive(state); } -void -GtkBuilderWindow::resize (int width, int height) +void GtkBuilderWindow::show_widget(const char *name, bool state) { - if (width > 0 && height > 0) - gtk_window_resize (GTK_WINDOW (window), width, height); + auto widget = get_object(name); + widget->set_visible(state); } -void -GtkBuilderWindow::refresh () +void GtkBuilderWindow::resize(int width, int height) { - gtk_widget_queue_draw (GTK_WIDGET (window)); + window->resize(width, height); } -int -GtkBuilderWindow::get_width () +void GtkBuilderWindow::refresh() { - int width, height; - - gtk_window_get_size (GTK_WINDOW (window), &width, &height); - - return width; + window->queue_draw(); } -int -GtkBuilderWindow::get_height () +int GtkBuilderWindow::get_width() { - int width, height; - - gtk_window_get_size (GTK_WINDOW (window), &width, &height); - - return height; + return window->get_width(); } -void -GtkBuilderWindow::set_button_label (const char *name, const char *label) +int GtkBuilderWindow::get_height() { - gtk_button_set_label (GTK_BUTTON (get_widget (name)), label); + return window->get_height(); } -unsigned char -GtkBuilderWindow::get_check (const char *name) +void GtkBuilderWindow::set_button_label(const char *name, const char *label) { - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (get_widget (name)))) - return 1; - return 0; + get_object(name)->set_label(label); +} + +bool GtkBuilderWindow::get_check(const char *name) +{ + return get_object(name)->get_active(); } int GtkBuilderWindow::get_entry_value(const char *name) { - return atoi (gtk_entry_get_text (GTK_ENTRY (get_widget (name))));; + auto text = get_object(name)->get_text(); + return std::stoi(text); } -const char * -GtkBuilderWindow::get_entry_text (const char *name) +std::string GtkBuilderWindow::get_entry_text(const char *name) { - return gtk_entry_get_text (GTK_ENTRY (get_widget (name))); + return get_object(name)->get_text(); } -float -GtkBuilderWindow::get_slider (const char *name) +void GtkBuilderWindow::set_entry_value(const char *name, unsigned int value) { - return (float) gtk_range_get_value (GTK_RANGE (get_widget (name))); + get_object(name)->set_text(std::to_string(value)); } -unsigned char -GtkBuilderWindow::get_combo (const char *name) +void GtkBuilderWindow::set_entry_text(const char *name, const char *text) { - return gtk_combo_box_get_active (GTK_COMBO_BOX (get_widget (name))); + get_object(name)->set_text(text); } -void -GtkBuilderWindow::set_slider (const char *name, float value) +float GtkBuilderWindow::get_slider(const char *name) { - gtk_range_set_value (GTK_RANGE (get_widget (name)), (double) value); + return get_object(name)->get_value(); } -void -GtkBuilderWindow::set_check (const char *name, bool value) +int GtkBuilderWindow::get_combo(const char *name) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (get_widget (name)), - value); + return get_object(name)->get_active_row_number(); } -void -GtkBuilderWindow::set_entry_value (const char *name, unsigned int value) +void GtkBuilderWindow::set_slider(const char *name, float value) { - char text[80]; - - snprintf (text, 80, "%u", value); - gtk_entry_set_text (GTK_ENTRY (get_widget (name)), text); + get_object(name)->set_value(value); } -void -GtkBuilderWindow::set_entry_text (const char *name, const char *text) +void GtkBuilderWindow::set_check(const char *name, bool value) { - gtk_entry_set_text (GTK_ENTRY (get_widget (name)), text); + get_object(name)->set_active(value); } -void -GtkBuilderWindow::set_combo (const char *name, unsigned char value) +void GtkBuilderWindow::set_combo(const char *name, unsigned char value) { - gtk_combo_box_set_active (GTK_COMBO_BOX (get_widget (name)), value); + get_object(name)->set_active(value); } -void -GtkBuilderWindow::set_spin (const char *name, double value) +void GtkBuilderWindow::set_spin(const char *name, double value) { - gtk_spin_button_set_value (GTK_SPIN_BUTTON (get_widget (name)), - (double) value); + get_object(name)->set_value(value); } -void -GtkBuilderWindow::combo_box_append (const char *name, const char *value) +double GtkBuilderWindow::get_spin(const char *name) { - combo_box_append (GTK_COMBO_BOX (get_widget (name)), value); + return get_object(name)->get_value(); } -void -GtkBuilderWindow::combo_box_append (GtkComboBox *combo, const char *value) +void GtkBuilderWindow::combo_box_append(const char *name, const char *value) +{ + return combo_box_append(get_object(name).get(), value); +} + +void GtkBuilderWindow::combo_box_append(Gtk::ComboBox *combo, const char *value) { GtkListStore *store; GtkTreeIter iter; - store = GTK_LIST_STORE (gtk_combo_box_get_model (combo)); + store = GTK_LIST_STORE(combo->get_model()->gobj()); - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, value, -1); + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, value, -1); } -GtkWindow * -GtkBuilderWindow::get_window () +GtkWindow *GtkBuilderWindow::get_window() { - return GTK_WINDOW (window); -} - -double -GtkBuilderWindow::get_spin (const char *name) -{ - return gtk_spin_button_get_value (GTK_SPIN_BUTTON (get_widget (name))); + return window->gobj(); } bool GtkBuilderWindow::has_focus(const char *widget) { - return gtk_widget_is_focus (get_widget (widget)); + return get_object(widget)->is_focus(); } diff --git a/gtk/src/gtk_builder_window.h b/gtk/src/gtk_builder_window.h index 95abd06e..a5bbc3db 100644 --- a/gtk/src/gtk_builder_window.h +++ b/gtk/src/gtk_builder_window.h @@ -7,51 +7,54 @@ #ifndef __GTK_BUILDER_WINDOW_H #define __GTK_BUILDER_WINDOW_H -#include "gtk_2_3_compat.h" +#include "gtk_compat.h" -typedef struct -{ - const char *signal; - GCallback function; -} GtkBuilderWindowCallbacks; +extern Glib::RefPtr global_builder; class GtkBuilderWindow { - public: - GtkBuilderWindow (const char *root); - ~GtkBuilderWindow (); - GtkWidget *get_widget (const char *name); - void resize (int width, int height); - GtkWindow *get_window (); - void refresh (); - int get_width (); - int get_height (); + public: + GtkBuilderWindow(const char *root); + ~GtkBuilderWindow(); - void signal_connect (GtkBuilderWindowCallbacks *callbacks); - void enable_widget (const char *name, bool state); - void set_button_label (const char *name, const char *label); - unsigned char get_check (const char *name); - int get_entry_value (const char *name); - const char *get_entry_text (const char *name); - unsigned char get_combo (const char *name); - void combo_box_append (const char *name, const char *value); - void combo_box_append (GtkComboBox *combo, const char *value); - double get_spin (const char *name); - float get_slider (const char *name); - void set_check (const char *name, bool value); - void set_entry_value (const char *name, unsigned int value); - void set_entry_text (const char *name, const char *text); - void set_combo (const char *name, unsigned char value); - void set_spin (const char *name, double value); - void set_slider (const char *name, float value); - bool has_focus (const char *widget); + template + Glib::RefPtr get_object(const char *name) + { + auto object = global_builder->get_object(name); + if (!object) + { + printf("No object named %s\n", name); + exit(1); + } + return Glib::RefPtr::cast_static(object); + } -protected: - static void signal_connection_func (GtkBuilder *, GObject *, const gchar *, const char *, GObject *, GConnectFlags, gpointer); + void resize(int width, int height); + GtkWindow *get_window(); + void refresh(); + int get_width(); + int get_height(); - GtkWidget *window; - GtkBuilder *builder; - GtkBuilderWindowCallbacks *callbacks; + void enable_widget(const char *name, bool state); + void show_widget(const char *name, bool state); + void set_button_label(const char *name, const char *label); + bool get_check(const char *name); + int get_entry_value(const char *name); + std::string get_entry_text(const char *name); + int get_combo(const char *name); + void combo_box_append(const char *name, const char *value); + void combo_box_append(Gtk::ComboBox *combo, const char *value); + double get_spin(const char *name); + float get_slider(const char *name); + void set_check(const char *name, bool value); + void set_entry_value(const char *name, unsigned int value); + void set_entry_text(const char *name, const char *text); + void set_combo(const char *name, unsigned char value); + void set_spin(const char *name, double value); + void set_slider(const char *name, float value); + bool has_focus(const char *widget); + + Glib::RefPtr window; }; #endif /* __GTK_BUILDER_WINDOW_H */ diff --git a/gtk/src/gtk_cheat.cpp b/gtk/src/gtk_cheat.cpp index d6a4c3a1..edc37a5f 100644 --- a/gtk/src/gtk_cheat.cpp +++ b/gtk/src/gtk_cheat.cpp @@ -4,13 +4,12 @@ For further information, consult the LICENSE file in the root directory. \*****************************************************************************/ -#include "gtk_s9xcore.h" - #include "gtk_s9x.h" #include "gtk_cheat.h" +#include "cheats.h" +#include "display.h" -enum -{ +enum { COLUMN_ENABLED = 0, COLUMN_DESCRIPTION = 1, COLUMN_CHEAT = 2, @@ -19,225 +18,128 @@ enum extern SCheatData Cheat; -static void -display_errorbox (const char *error) +static void display_errorbox(const char *error) { - GtkWidget *dialog = gtk_message_dialog_new (NULL, - GTK_DIALOG_MODAL, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - "%s", - error); - gtk_window_set_title (GTK_WINDOW (dialog), _("Error")); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); + auto dialog = Gtk::MessageDialog(error, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + dialog.set_title(_("Error")); + dialog.run(); + dialog.hide(); } -static void -event_add_code (GtkButton *button, gpointer data) +static Snes9xCheats *cheats_dialog = nullptr; +void open_snes9x_cheats_dialog() { - ((Snes9xCheats *) data)->add_code (); + if (!cheats_dialog) + cheats_dialog = new Snes9xCheats; + + cheats_dialog->show(); } -static void -event_update_code (GtkButton *button, gpointer data) +Snes9xCheats::Snes9xCheats() + : GtkBuilderWindow("cheat_window") { - ((Snes9xCheats *) data)->update_code (); -} - -static void -event_disable_all (GtkButton *button, gpointer data) -{ - ((Snes9xCheats *) data)->disable_all (); -} - -static void -event_remove_code (GtkButton *button, gpointer data) -{ - ((Snes9xCheats *) data)->remove_code (); -} - -static void -event_search_database (GtkButton *button, gpointer data) -{ - ((Snes9xCheats *) data)->search_database (); -} - -static void -event_delete_all_cheats (GtkButton *button, gpointer data) -{ - ((Snes9xCheats *) data)->delete_all_cheats (); -} - -static void -event_code_toggled (GtkCellRendererToggle *cell_renderer, - gchar *path, - gpointer data) -{ - int enabled = !gtk_cell_renderer_toggle_get_active (cell_renderer); - - ((Snes9xCheats *) data)->toggle_code (path, enabled); -} - -static void -event_row_activated (GtkTreeView *tree_view, - GtkTreePath *path, - GtkTreeViewColumn *column, - gpointer data) -{ - ((Snes9xCheats *) data)->row_activated (path); -} - -static void -event_row_inserted (GtkTreeModel *tree_model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer data) -{ - int *indices = gtk_tree_path_get_indices (path); - ((Snes9xCheats *) data)->row_inserted (indices[0]); -} - -static void -event_row_deleted (GtkTreeModel *tree_model, - GtkTreePath *path, - gpointer data) -{ - int *indices = gtk_tree_path_get_indices (path); - ((Snes9xCheats *) data)->row_deleted (indices[0]); -} - -void -event_enabled_column_clicked (GtkTreeViewColumn *treeviewcolumn, - gpointer data) -{ - ((Snes9xCheats *) data)->sort_cheats (); -} - -Snes9xCheats::Snes9xCheats () - : GtkBuilderWindow ("cheat_window") -{ - GtkTreeView *view; - GtkCellRenderer *renderer; - GtkBuilderWindowCallbacks callbacks[] = - { - { "add_code", G_CALLBACK (event_add_code) }, - { "update_code", G_CALLBACK (event_update_code) }, - { "remove_code", G_CALLBACK (event_remove_code) }, - { "search_database", G_CALLBACK (event_search_database) }, - { "disable_all", G_CALLBACK (event_disable_all) }, - { "delete_all_cheats", G_CALLBACK (event_delete_all_cheats) }, - { NULL, NULL} - }; - dst_row = -1; - view = GTK_TREE_VIEW (get_widget ("cheat_treeview")); + auto view = get_object("cheat_treeview"); + view->signal_row_activated().connect(sigc::mem_fun(*this, &Snes9xCheats::row_activated)); + view->set_reorderable(); - g_signal_connect (view, "row-activated", G_CALLBACK (event_row_activated), (gpointer) this); + auto toggle_renderer = new Gtk::CellRendererToggle(); + toggle_renderer->set_activatable(); + toggle_renderer->signal_toggled().connect(sigc::mem_fun(*this, &Snes9xCheats::toggle_code)); - gtk_tree_view_set_reorderable (view, true); + view->insert_column("\xe2\x86\x91", *toggle_renderer, COLUMN_ENABLED); + auto column = view->get_column(COLUMN_ENABLED); + column->set_clickable(); + column->set_alignment(0.5); + column->add_attribute(*toggle_renderer, "active", COLUMN_ENABLED); + column->signal_clicked().connect([&] { + sort_cheats(); + }); - renderer = gtk_cell_renderer_toggle_new (); - gtk_cell_renderer_toggle_set_activatable (GTK_CELL_RENDERER_TOGGLE (renderer), true); - gtk_tree_view_insert_column_with_attributes (view, - -1, - "\xe2\x86\x91", - renderer, - "active", COLUMN_ENABLED, - NULL); - GtkTreeViewColumn *column = gtk_tree_view_get_column (view, 0); - gtk_tree_view_column_set_clickable (column, true); - gtk_tree_view_column_set_alignment (column, 0.5f); - g_signal_connect (column, "clicked", G_CALLBACK (event_enabled_column_clicked), (gpointer) this); + auto text_renderer = new Gtk::CellRendererText(); + view->insert_column(_("Description"), *text_renderer, COLUMN_DESCRIPTION); + column = view->get_column(COLUMN_DESCRIPTION); + column->set_resizable(); + column->set_min_width(40); + column->add_attribute(*text_renderer, "text", COLUMN_DESCRIPTION); - g_signal_connect (renderer, - "toggled", - G_CALLBACK (event_code_toggled), - (gpointer) this); + view->insert_column(_("Cheat"), *text_renderer, COLUMN_CHEAT); + column = view->get_column(COLUMN_CHEAT); + column->set_resizable(); + column->set_min_width(40); + column->add_attribute(*text_renderer, "text", COLUMN_CHEAT); - renderer = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes (view, - -1, - _("Description"), - renderer, - "text", COLUMN_DESCRIPTION, - NULL); - column = gtk_tree_view_get_column (view, 1); - gtk_tree_view_column_set_resizable (column, true); - gtk_tree_view_column_set_min_width (column, 40); + Gtk::TreeModelColumn column1; + Gtk::TreeModelColumn column2; + Gtk::TreeModelColumn column3; + Gtk::TreeModelColumnRecord record; + record.add(column1); + record.add(column2); + record.add(column3); - renderer = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes (view, - -1, - _("Cheat"), - renderer, - "text", COLUMN_CHEAT, - NULL); - column = gtk_tree_view_get_column (view, 2); - gtk_tree_view_column_set_resizable (column, true); - gtk_tree_view_column_set_min_width (column, 40); + store = Gtk::ListStore::create(record); + view->set_model(store); - store = gtk_list_store_new (NUM_COLS, - G_TYPE_BOOLEAN, - G_TYPE_STRING, - G_TYPE_STRING); + delete_id = store->signal_row_deleted().connect([&](const Gtk::TreeModel::Path &path) { + row_deleted(get_index_from_path(path)); + }); - gtk_tree_view_set_model (view, GTK_TREE_MODEL (store)); - delete_id = g_signal_connect (store, "row-deleted", G_CALLBACK (event_row_deleted), (gpointer) this); - insert_id = g_signal_connect (store, "row-inserted", G_CALLBACK (event_row_inserted), (gpointer) this); + insert_id = store->signal_row_inserted().connect([&](const Gtk::TreeModel::Path &path, const Gtk::TreeModel::iterator &iter) { + row_inserted(get_index_from_path(path)); + }); - gtk_widget_realize (window); + get_object("add_code")->signal_clicked().connect(sigc::mem_fun(*this, &Snes9xCheats::add_code)); + get_object("remove_code")->signal_clicked().connect(sigc::mem_fun(*this, &Snes9xCheats::remove_code)); + get_object("update_button")->signal_clicked().connect(sigc::mem_fun(*this, &Snes9xCheats::update_code)); + get_object("disable_all_button")->signal_clicked().connect(sigc::mem_fun(*this, &Snes9xCheats::disable_all)); + get_object("delete_all_cheats_button")->signal_clicked().connect(sigc::mem_fun(*this, &Snes9xCheats::delete_all_cheats)); + get_object("cheat_search_button")->signal_clicked().connect(sigc::mem_fun(*this, &Snes9xCheats::search_database)); + get_object("update_button")->signal_clicked().connect(sigc::mem_fun(*this, &Snes9xCheats::update_code)); - signal_connect (callbacks); + gtk_widget_realize(GTK_WIDGET(window->gobj())); } -Snes9xCheats::~Snes9xCheats () +Snes9xCheats::~Snes9xCheats() { - gtk_widget_destroy (window); - - g_object_unref (store); } -void -Snes9xCheats::enable_dnd (bool enable) +void Snes9xCheats::enable_dnd(bool enable) { if (enable) { - g_signal_handler_unblock (G_OBJECT (store), delete_id); - g_signal_handler_unblock (G_OBJECT (store), insert_id); + delete_id.unblock(); + insert_id.unblock(); } else { - g_signal_handler_block (G_OBJECT (store), delete_id); - g_signal_handler_block (G_OBJECT (store), insert_id); + delete_id.block(); + insert_id.unblock(); } } -void -Snes9xCheats::show () +void Snes9xCheats::show() { - top_level->pause_from_focus_change (); + top_level->pause_from_focus_change(); - gtk_window_set_transient_for (GTK_WINDOW (window), - top_level->get_window ()); + window->set_transient_for(*top_level->window.get()); - refresh_tree_view (); + refresh_tree_view(); + Glib::RefPtr::cast_static(window)->run(); + window->hide(); - gtk_dialog_run (GTK_DIALOG (window)); - - top_level->unpause_from_focus_change (); + top_level->unpause_from_focus_change(); } -static void cheat_move (int src, int dst) +static void cheat_move(int src, int dst) { - Cheat.g.insert (Cheat.g.begin() + dst, Cheat.g[src]); + Cheat.g.insert(Cheat.g.begin() + dst, Cheat.g[src]); if (dst < src) src++; - Cheat.g.erase (Cheat.g.begin() + src); + Cheat.g.erase(Cheat.g.begin() + src); } -static void cheat_gather_enabled () +static void cheat_gather_enabled() { unsigned int enabled = 0; @@ -251,311 +153,259 @@ static void cheat_gather_enabled () } } -void -Snes9xCheats::row_deleted (int src_row) +void Snes9xCheats::row_deleted(int src_row) { if (dst_row >= 0) { if (src_row >= dst_row) src_row--; - cheat_move (src_row, dst_row); + cheat_move(src_row, dst_row); dst_row = -1; } } -void -Snes9xCheats::row_inserted (int new_row) +void Snes9xCheats::row_inserted(int new_row) { dst_row = new_row; } -int -Snes9xCheats::get_selected_index () +int Snes9xCheats::get_selected_index() { - GtkTreeSelection *selection; - GList *rows; - gint *indices; - int index; - GtkTreeModel *model = GTK_TREE_MODEL (store); + auto selection = get_object("cheat_treeview")->get_selection(); + auto rows = selection->get_selected_rows(); + if (rows.empty()) + return -1; + auto indices = gtk_tree_path_get_indices(rows[0].gobj()); + return indices[0]; +} - selection = - gtk_tree_view_get_selection ( - GTK_TREE_VIEW (get_widget ("cheat_treeview"))); - - rows = gtk_tree_selection_get_selected_rows (selection, - &model); - - if (rows) - { - indices = gtk_tree_path_get_indices ((GtkTreePath *) (rows->data)); - - index = indices[0]; - - for (GList *i = rows; i; i = i->next) - gtk_tree_path_free ((GtkTreePath *)(i->data)); - - g_list_free (rows); - } - else - index = -1; +int Snes9xCheats::get_index_from_path(Gtk::TreeModel::Path path) +{ + gint *indices = gtk_tree_path_get_indices(path.gobj()); + int index = indices[0]; return index; } -int -Snes9xCheats::get_index_from_path (const gchar *path) +int Snes9xCheats::get_index_from_path(const Glib::ustring &path) { - GtkTreePath *tree_path = gtk_tree_path_new_from_string (path); - gint *indices = gtk_tree_path_get_indices (tree_path); - int index = indices[0]; - gtk_tree_path_free (tree_path); - - return index; + return get_index_from_path(Gtk::TreeModel::Path(path)); } -void -Snes9xCheats::refresh_tree_view () +void Snes9xCheats::refresh_tree_view() { - GtkTreeIter iter; - unsigned int list_size; + enable_dnd(false); - enable_dnd (false); - list_size = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL); + auto list_size = store->children().size(); - if (Cheat.g.size () == 0) + if (Cheat.g.size() == 0) return; for (unsigned int i = 0; i < Cheat.g.size() - list_size; i++) - gtk_list_store_append (store, &iter); - - gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter); + store->append(); + auto iter = store->children().begin(); for (unsigned int i = 0; i < Cheat.g.size (); i++) { - char *str = S9xCheatGroupToText (i); - - if (i > 0) - gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter); - - gtk_list_store_set (store, &iter, - COLUMN_DESCRIPTION, - !strcmp (Cheat.g [i].name, "") ? _("No description") - : Cheat.g [i].name, - COLUMN_CHEAT, str, - COLUMN_ENABLED, Cheat.g [i].enabled, - -1); + char *str = S9xCheatGroupToText(i); + Glib::ustring description = Cheat.g[i].name[0] == '\0' ? "" :Cheat.g[i].name; + iter->set_value(COLUMN_ENABLED, Cheat.g[i].enabled); + iter->set_value(COLUMN_DESCRIPTION, description); + iter->set_value(COLUMN_CHEAT, Glib::ustring(str)); + iter++; delete[] str; } - enable_dnd (true); + enable_dnd(true); } -void -Snes9xCheats::add_code () +void Snes9xCheats::add_code() { - const char *description; - const gchar *code = get_entry_text ("code_entry"); + std::string code = get_entry_text("code_entry"); + std::string description = get_entry_text("description_entry"); - description = get_entry_text ("description_entry"); - if (description[0] == '\0') + if (description.empty()) description = _("No description"); - if (S9xAddCheatGroup (description, code) < 0) + if (S9xAddCheatGroup(description.c_str(), code.c_str()) < 0) { - display_errorbox (_("Couldn't find any cheat codes in input.")); + display_errorbox(_("Couldn't find any cheat codes in input.")); return; } - code = (const gchar *) S9xCheatGroupToText (Cheat.g.size () - 1); - set_entry_text ("code_entry", code); - delete[] code; + auto parsed_code = S9xCheatGroupToText(Cheat.g.size() - 1); + set_entry_text("code_entry", parsed_code); + delete[] parsed_code; - gtk_widget_grab_focus (get_widget ("code_entry")); + get_object("code_entry")->grab_focus(); - refresh_tree_view (); + refresh_tree_view(); - while (gtk_events_pending ()) - gtk_main_iteration (); + while (Gtk::Main::events_pending()) + Gtk::Main::iteration(false); - GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (get_widget ("cheat_treeview"))); - GtkTreePath *path = gtk_tree_path_new_from_indices (Cheat.g.size () - 1, -1); - gtk_tree_selection_select_path (selection, path); - gtk_tree_path_free (path); + auto selection = get_object("cheat_treeview")->get_selection(); + Gtk::TreePath path; + path.push_back(Cheat.g.size() - 1); + selection->select(path); - GtkScrolledWindow *scroll = GTK_SCROLLED_WINDOW (get_widget ("cheat_scrolledwindow")); - GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment (scroll); - gtk_adjustment_set_value (adj, gtk_adjustment_get_upper (adj)); + auto adj = get_object("cheat_scrolledwindow")->get_vadjustment(); + adj->set_value(adj->get_upper()); } -void -Snes9xCheats::remove_code () +void Snes9xCheats::remove_code() { - int index = get_selected_index (); - GtkTreeIter iter; + int index = get_selected_index(); if (index < 0) return; - enable_dnd (false); - gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store), &iter, NULL, index); - gtk_list_store_remove (store, &iter); - enable_dnd (true); + enable_dnd(false); - S9xDeleteCheatGroup (index); + Gtk::TreePath path; + path.push_back(index); + + auto iter = store->get_iter(path); + store->erase(iter); + + enable_dnd(true); + + S9xDeleteCheatGroup(index); } -void -Snes9xCheats::delete_all_cheats () +void Snes9xCheats::delete_all_cheats() { - enable_dnd (false); - S9xDeleteCheats (); - gtk_list_store_clear (store); - enable_dnd (true); + enable_dnd(false); + S9xDeleteCheats(); + store->clear(); + enable_dnd(true); } -void -Snes9xCheats::search_database () +void Snes9xCheats::search_database() { std::string filename; int result; int reason = 0; - filename = S9xGetDirectory (CHEAT_DIR); + filename = S9xGetDirectory(CHEAT_DIR); filename += "/cheats.bml"; - if (!(result = S9xImportCheatsFromDatabase (filename.c_str ()))) + if (!(result = S9xImportCheatsFromDatabase(filename.c_str()))) { - refresh_tree_view (); + refresh_tree_view(); return; } if (result < reason) reason = result; - filename = get_config_dir () + "/cheats.bml"; - if (!(result = S9xImportCheatsFromDatabase (filename.c_str ()))) + filename = get_config_dir() + "/cheats.bml"; + if (!(result = S9xImportCheatsFromDatabase(filename.c_str()))) { - refresh_tree_view (); + refresh_tree_view(); return; } if (result < reason) reason = result; - filename = std::string (DATADIR) + "/cheats.bml"; - if (!(result = S9xImportCheatsFromDatabase (filename.c_str ()))) + filename = std::string(DATADIR) + "/cheats.bml"; + if (!(result = S9xImportCheatsFromDatabase(filename.c_str()))) { - refresh_tree_view (); + refresh_tree_view(); return; } if (result < reason) reason = result; - filename = S9xGetDirectory (ROM_DIR); + filename = S9xGetDirectory(ROM_DIR); filename += "/cheats.bml"; - if (!(result = S9xImportCheatsFromDatabase (filename.c_str ()))) + if (!(result = S9xImportCheatsFromDatabase(filename.c_str()))) { - refresh_tree_view (); + refresh_tree_view(); return; } if (result < reason) reason = result; - GtkMessageDialog *dialog; - GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT; - dialog = GTK_MESSAGE_DIALOG (gtk_message_dialog_new (get_window (), - flags, - GTK_MESSAGE_INFO, - GTK_BUTTONS_CLOSE, - reason == -1 ? _("Couldn't Find Cheats Database") : - _("No Matching Game Found"))); - gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG (dialog), - reason == -1 ? - _("The database file cheats.bml was not found. It is normally installed with " - "Snes9x, but you may also place a custom copy in your configuration or cheats directory.") : - _("No matching game was found in the databases. If you are using a non-official " - "translation or modified copy, you may be able to find and manually enter the codes.")); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (GTK_WIDGET (dialog)); + auto dialog = Gtk::MessageDialog(*window.get(), reason == -1 ? _("Couldn't Find Cheats Database") : _("No Matching Game Found"), true); + dialog.set_secondary_text(reason == -1 ? _("The database file cheats.bml was not found. It is normally installed with " + "Snes9x, but you may also place a custom copy in your configuration or cheats directory.") + : _("No matching game was found in the databases. If you are using a non-official " + "translation or modified copy, you may be able to find and manually enter the codes.")); + dialog.run(); + dialog.hide(); } -void -Snes9xCheats::sort_cheats () +void Snes9xCheats::sort_cheats() { - cheat_gather_enabled (); - refresh_tree_view (); + cheat_gather_enabled(); + refresh_tree_view(); } -void -Snes9xCheats::row_activated (GtkTreePath *path) +void Snes9xCheats::row_activated(const Gtk::TreeModel::Path &path, Gtk::TreeViewColumn *column) { - gint *indices = gtk_tree_path_get_indices (path); + int index = get_index_from_path(path); char *cheat_text; - cheat_text = S9xCheatGroupToText (indices[0]); - set_entry_text ("code_entry", cheat_text); + cheat_text = S9xCheatGroupToText(index); + set_entry_text("code_entry", cheat_text); delete[] cheat_text; - set_entry_text ("description_entry", Cheat.g[indices[0]].name); + set_entry_text("description_entry", Cheat.g[index].name); } -void -Snes9xCheats::toggle_code (const gchar *path, int enabled) +void Snes9xCheats::toggle_code(const Glib::ustring &path) { - GtkTreeIter iter; - int index = get_index_from_path (path); - - GtkTreePath *treepath = gtk_tree_path_new_from_string (path); - gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, treepath); - gtk_list_store_set (store, &iter, COLUMN_ENABLED, enabled, -1); + int index = get_index_from_path(path); + auto iter = store->get_iter(path); + bool enabled; + iter->get_value(COLUMN_ENABLED, enabled); + enabled = !enabled; + iter->set_value(COLUMN_ENABLED, enabled); if (enabled) - S9xEnableCheatGroup (index); + S9xEnableCheatGroup(index); else - S9xDisableCheatGroup (index); + S9xDisableCheatGroup(index); } -void -Snes9xCheats::update_code () +void Snes9xCheats::update_code() { - int index = get_selected_index (); + int index = get_selected_index(); if (index < 0) return; - const char *description; - char *code = (char *) get_entry_text ("code_entry"); - - description = get_entry_text ("description_entry"); - if (description[0] == '\0') + std::string code = get_entry_text("code_entry"); + std::string description = get_entry_text("description_entry"); + if (description.empty()) description = _("No description"); - code = S9xCheatValidate (code); - if (!code) + auto parsed_code = S9xCheatValidate(code.c_str()); + if (!parsed_code) { - display_errorbox (_("Couldn't find any cheat codes in input.")); + display_errorbox(_("Couldn't find any cheat codes in input.")); return; } - S9xModifyCheatGroup (index, description, code); - set_entry_text ("code_entry", code); - delete[] code; + S9xModifyCheatGroup(index, description.c_str(), parsed_code); + set_entry_text("code_entry", parsed_code); + delete[] parsed_code; - gtk_widget_grab_focus (get_widget ("code_entry")); + get_object("code_entry")->grab_focus(); - refresh_tree_view (); + refresh_tree_view(); } -void -Snes9xCheats::disable_all () +void Snes9xCheats::disable_all() { for (unsigned int i = 0; i < Cheat.g.size(); i++) { if (Cheat.g[i].enabled) - S9xDisableCheatGroup (i); + S9xDisableCheatGroup(i); } - refresh_tree_view (); + refresh_tree_view(); } - diff --git a/gtk/src/gtk_cheat.h b/gtk/src/gtk_cheat.h index e85d9273..161fd39f 100644 --- a/gtk/src/gtk_cheat.h +++ b/gtk/src/gtk_cheat.h @@ -9,41 +9,43 @@ #include "gtk_builder_window.h" -enum -{ - TYPE_GAME_GENIE = 0, +void open_snes9x_cheats_dialog(); + +enum { + TYPE_GAME_GENIE = 0, TYPE_ACTION_REPLAY = 1, - TYPE_GOLDFINGER = 2 + TYPE_GOLDFINGER = 2 }; class Snes9xCheats : public GtkBuilderWindow { - public: - Snes9xCheats (); - ~Snes9xCheats (); - void show (); - void add_code (); - void remove_code (); - void search_database (); - void delete_all_cheats (); - void toggle_code (const gchar *path, int enabled); - void row_activated (GtkTreePath *path); - void row_deleted (int src_row); - void row_inserted (int row); - void enable_dnd (bool); - void sort_cheats (); - void update_code (); - void disable_all (); + public: + Snes9xCheats(); + ~Snes9xCheats(); + void show(); + void add_code(); + void remove_code(); + void search_database(); + void delete_all_cheats(); + void toggle_code(const Glib::ustring &path); + void row_activated(const Gtk::TreeModel::Path &path, Gtk::TreeViewColumn *column); + void row_deleted(int src_row); + void row_inserted(int row); + void enable_dnd(bool); + void sort_cheats(); + void update_code(); + void disable_all(); - private: - void refresh_tree_view (); - int get_selected_index (); - int get_index_from_path (const gchar *path); + private: + void refresh_tree_view(); + int get_selected_index(); + int get_index_from_path(const Glib::ustring &path); + int get_index_from_path(Gtk::TreeModel::Path path); - unsigned long insert_id; - unsigned long delete_id; - int dst_row; - GtkListStore *store; + sigc::connection insert_id; + sigc::connection delete_id; + int dst_row; + Glib::RefPtr store; }; #endif /* __GTK_CHEAT_H */ diff --git a/gtk/src/gtk_compat.h b/gtk/src/gtk_compat.h new file mode 100644 index 00000000..f48fecf6 --- /dev/null +++ b/gtk/src/gtk_compat.h @@ -0,0 +1,29 @@ +/*****************************************************************************\ + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + This file is licensed under the Snes9x License. + For further information, consult the LICENSE file in the root directory. +\*****************************************************************************/ + +#ifndef __GTK_COMPAT_H +#define __GTK_COMPAT_H + +#include + +#include +#include +#include +#include + +#ifndef USE_WAYLAND +#undef GDK_WINDOWING_WAYLAND +#endif + +#ifdef GDK_WINDOWING_WAYLAND +#include +#endif + +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#endif diff --git a/gtk/src/gtk_config.cpp b/gtk/src/gtk_config.cpp index cba365b4..c259ea52 100644 --- a/gtk/src/gtk_config.cpp +++ b/gtk/src/gtk_config.cpp @@ -14,6 +14,10 @@ #include "gtk_sound.h" #include "gtk_display.h" #include "conffile.h" +#include "cheats.h" +#include "apu/apu.h" +#include "netplay.h" +#include "controls.h" static bool directory_exists(std::string str) { @@ -38,7 +42,7 @@ std::string get_config_dir() if (!env_home && !env_xdg_config_home) { - return std::string(".snes9x"); + return std::string{".snes9x"}; } std::string config; @@ -70,7 +74,6 @@ void S9xParsePortConfig(ConfigFile &conf, int pass) Snes9xConfig::Snes9xConfig() { - joystick = NULL; joystick_threshold = 40; } @@ -103,8 +106,8 @@ int Snes9xConfig::load_defaults() default_esc_behavior = 1; prevent_screensaver = false; sound_driver = 0; - sound_buffer_size = 32; - sound_playback_rate = 5; + sound_buffer_size = 48; + sound_playback_rate = 7; sound_input_rate = 31950; auto_input_rate = true; last_directory.clear(); @@ -149,7 +152,7 @@ int Snes9xConfig::load_defaults() sync_to_vblank = true; use_pbos = true; pbo_format = 0; - npot_textures = false; + npot_textures = true; use_shaders = false; shader_filename.clear(); use_glfinish = false; @@ -206,26 +209,26 @@ int Snes9xConfig::load_defaults() void Snes9xConfig::joystick_register_centers() { - for (int i = 0; joystick[i] != NULL; i++) - joystick[i]->register_centers(); + for (auto &j : joystick) + j.register_centers(); } void Snes9xConfig::flush_joysticks() { - for (int i = 0; joystick[i] != NULL; i++) - joystick[i]->flush(); + for (auto &j : joystick) + j.flush(); } void Snes9xConfig::set_joystick_mode(int mode) { - for (int i = 0; joystick[i] != NULL; i++) - joystick[i]->mode = mode; + for (auto &j : joystick) + j.mode = mode; } int Snes9xConfig::save_config_file() { ConfigFile cf; - std::string section = ""; + std::string section; auto outbool = [&](std::string name, bool b, std::string comment = "") { cf.SetBool((section + "::" + name).c_str(), b, "true", "false", comment.c_str()); diff --git a/gtk/src/gtk_config.h b/gtk/src/gtk_config.h index cef3520d..ce856b43 100644 --- a/gtk/src/gtk_config.h +++ b/gtk/src/gtk_config.h @@ -7,14 +7,14 @@ #ifndef __GTK_CONFIG_H #define __GTK_CONFIG_H +#include "gtk_control.h" +#include "filter/snes_ntsc.h" + #include #include #include #include -#include "gtk_control.h" -#include "filter/snes_ntsc.h" - enum { HWA_NONE = 0, HWA_OPENGL = 1, @@ -53,14 +53,14 @@ enum { class Snes9xConfig { public: - Snes9xConfig (); - int load_config_file (); - int save_config_file (); - int load_defaults (); - void rebind_keys (); - void flush_joysticks (); - void set_joystick_mode (int mode); - void joystick_register_centers (); + Snes9xConfig(); + int load_config_file(); + int save_config_file(); + int load_defaults(); + void rebind_keys(); + void flush_joysticks(); + void set_joystick_mode(int mode); + void joystick_register_centers(); /* Screen options */ bool full_screen_on_open; @@ -167,11 +167,11 @@ class Snes9xConfig bool use_sync_control; #endif - JoyDevice **joystick; + std::vector joystick; int joystick_threshold; }; -std::string get_config_dir (); -std::string get_config_file_name (); +std::string get_config_dir(); +std::string get_config_file_name(); #endif /* __GTK_CONFIG_H */ diff --git a/gtk/src/gtk_control.cpp b/gtk/src/gtk_control.cpp index c4442bc8..8af3ee70 100644 --- a/gtk/src/gtk_control.cpp +++ b/gtk/src/gtk_control.cpp @@ -6,12 +6,17 @@ #include -#include "gtk_s9xcore.h" +#include "SDL_joystick.h" #include "gtk_s9x.h" #include "gtk_config.h" #include "gtk_control.h" #include "gtk_file.h" +#include "snes9x.h" +#include "controls.h" +#include "display.h" +#include "gfx.h" + const BindingLink b_links[] = { /* Joypad-specific bindings. "Joypad# " will be prepended */ @@ -122,17 +127,17 @@ const int b_breaks[] = static int joystick_lock = 0; -bool S9xPollButton (uint32 id, bool *pressed) +bool S9xPollButton(uint32 id, bool *pressed) { return true; } -bool S9xPollAxis (uint32 id, int16 *value) +bool S9xPollAxis(uint32 id, int16 *value) { return true; } -bool S9xPollPointer (uint32 id, int16 *x, int16 *y) +bool S9xPollPointer(uint32 id, int16 *x, int16 *y) { *x = top_level->snes_mouse_x; *y = top_level->snes_mouse_y; @@ -140,14 +145,14 @@ bool S9xPollPointer (uint32 id, int16 *x, int16 *y) return true; } -bool S9xIsMousePluggedIn () +bool S9xIsMousePluggedIn() { enum controllers ctl; int8 id1, id2, id3, id4; for (int i = 0; i <= 1; i++) { - S9xGetController (i, &ctl, &id1, &id2, &id3, &id4); + S9xGetController(i, &ctl, &id1, &id2, &id3, &id4); if (ctl == CTL_MOUSE || ctl == CTL_SUPERSCOPE) return true; } @@ -155,7 +160,7 @@ bool S9xIsMousePluggedIn () return false; } -bool S9xGrabJoysticks () +bool S9xGrabJoysticks() { if (joystick_lock) return false; @@ -165,12 +170,12 @@ bool S9xGrabJoysticks () return true; } -void S9xReleaseJoysticks () +void S9xReleaseJoysticks() { joystick_lock--; } -static void swap_controllers_1_2 () +static void swap_controllers_1_2() { JoypadBinding interrim; @@ -178,10 +183,10 @@ static void swap_controllers_1_2 () gui_config->pad[0] = gui_config->pad[1]; gui_config->pad[1] = interrim; - gui_config->rebind_keys (); + gui_config->rebind_keys(); } -static void change_slot (int difference) +static void change_slot(int difference) { static char buf[256]; @@ -192,12 +197,12 @@ static void change_slot (int difference) if (!gui_config->rom_loaded) return; - snprintf (buf, 256, "State Slot: %d", gui_config->current_save_slot); - S9xSetInfoString (buf); + snprintf(buf, 256, "State Slot: %d", gui_config->current_save_slot); + S9xSetInfoString(buf); GFX.InfoStringTimeout = 60; } -void S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2) +void S9xHandlePortCommand(s9xcommand_t cmd, int16 data1, int16 data2) { static bool quit_binding_down = false; @@ -215,109 +220,93 @@ void S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2) { quit_binding_down = false; } - if (cmd.port[0] == PORT_COMMAND_FULLSCREEN) { - top_level->toggle_fullscreen_mode (); + top_level->toggle_fullscreen_mode(); } - else if (cmd.port[0] == PORT_COMMAND_SAVE_SPC) { - top_level->save_spc_dialog (); + top_level->save_spc_dialog(); } - else if (cmd.port[0] == PORT_OPEN_ROM) { - top_level->open_rom_dialog (); + top_level->open_rom_dialog(); } - else if (cmd.port[0] == PORT_PAUSE) { if (!(top_level->user_pause)) - top_level->pause_from_user (); + top_level->pause_from_user(); else - top_level->unpause_from_user (); + top_level->unpause_from_user(); } - else if (cmd.port[0] == PORT_REWIND) { Settings.Rewinding = false; } - else if (cmd.port[0] == PORT_SEEK_TO_FRAME) { - top_level->movie_seek_dialog (); + top_level->movie_seek_dialog(); } - else if (cmd.port[0] == PORT_SWAP_CONTROLLERS) { - swap_controllers_1_2 (); + swap_controllers_1_2(); } - else if (cmd.port[0] == PORT_QUIT) { if (quit_binding_down) - S9xExit (); + S9xExit(); } - else if (cmd.port[0] >= PORT_QUICKLOAD0 && cmd.port[0] <= PORT_QUICKLOAD9) { - S9xQuickLoadSlot (cmd.port[0] - PORT_QUICKLOAD0); + S9xQuickLoadSlot(cmd.port[0] - PORT_QUICKLOAD0); } - else if (cmd.port[0] == PORT_SAVESLOT) { - S9xQuickSaveSlot (gui_config->current_save_slot); + S9xQuickSaveSlot(gui_config->current_save_slot); } - else if (cmd.port[0] == PORT_LOADSLOT) { - S9xQuickLoadSlot (gui_config->current_save_slot); + S9xQuickLoadSlot(gui_config->current_save_slot); } - else if (cmd.port[0] == PORT_INCREMENTSAVESLOT) { - change_slot (1); - S9xQuickSaveSlot (gui_config->current_save_slot); + change_slot(1); + S9xQuickSaveSlot(gui_config->current_save_slot); } - else if (cmd.port[0] == PORT_DECREMENTLOADSLOT) { - change_slot (-1); - S9xQuickLoadSlot (gui_config->current_save_slot); + change_slot(-1); + S9xQuickLoadSlot(gui_config->current_save_slot); } - else if (cmd.port[0] == PORT_INCREMENTSLOT) { - change_slot (1); + change_slot(1); } - else if (cmd.port[0] == PORT_DECREMENTSLOT) { - change_slot (-1); + change_slot(-1); } - else if (cmd.port[0] == PORT_GRABMOUSE) { - top_level->toggle_grab_mouse (); + top_level->toggle_grab_mouse(); } } } -Binding S9xGetBindingByName (const char *name) +Binding S9xGetBindingByName(const char *name) { for (int i = 0; i < NUM_EMU_LINKS; i++) { - if (!strcasecmp (b_links[i + NUM_JOYPAD_LINKS].snes9x_name, name)) + if (!strcasecmp(b_links[i + NUM_JOYPAD_LINKS].snes9x_name, name)) { return gui_config->shortcut[i]; } } - return Binding (); + return Binding(); } -s9xcommand_t S9xGetPortCommandT (const char *name) +s9xcommand_t S9xGetPortCommandT(const char *name) { s9xcommand_t cmd; @@ -329,248 +318,214 @@ s9xcommand_t S9xGetPortCommandT (const char *name) cmd.port[2] = 0; cmd.port[3] = 0; - if (!strcasecmp (name, "GTK_fullscreen")) + if (!strcasecmp(name, "GTK_fullscreen")) { cmd.port[0] = PORT_COMMAND_FULLSCREEN; } - - else if (!strcasecmp (name, "GTK_save_spc")) + else if (!strcasecmp(name, "GTK_save_spc")) { cmd.port[0] = PORT_COMMAND_SAVE_SPC; } - - else if (!strcasecmp (name, "GTK_open_rom")) + else if (!strcasecmp(name, "GTK_open_rom")) { cmd.port[0] = PORT_OPEN_ROM; } - - else if (!strcasecmp (name, "GTK_pause")) + else if (!strcasecmp(name, "GTK_pause")) { cmd.port[0] = PORT_PAUSE; } - - else if (!strcasecmp (name, "GTK_seek_to_frame")) + else if (!strcasecmp(name, "GTK_seek_to_frame")) { cmd.port[0] = PORT_SEEK_TO_FRAME; } - - else if (!strcasecmp (name, "GTK_quit")) + else if (!strcasecmp(name, "GTK_quit")) { cmd.port[0] = PORT_QUIT; } - - else if (!strcasecmp (name, "GTK_swap_controllers")) + else if (!strcasecmp(name, "GTK_swap_controllers")) { cmd.port[0] = PORT_SWAP_CONTROLLERS; } - - else if (!strcasecmp (name, "GTK_rewind")) + else if (!strcasecmp(name, "GTK_rewind")) { cmd.port[0] = PORT_REWIND; } - - else if (strstr (name, "QuickLoad000")) + else if (strstr(name, "QuickLoad000")) { cmd.port[0] = PORT_QUICKLOAD0; } - - else if (strstr (name, "QuickLoad001")) + else if (strstr(name, "QuickLoad001")) { cmd.port[0] = PORT_QUICKLOAD1; } - - else if (strstr (name, "QuickLoad002")) + else if (strstr(name, "QuickLoad002")) { cmd.port[0] = PORT_QUICKLOAD2; } - - else if (strstr (name, "QuickLoad003")) + else if (strstr(name, "QuickLoad003")) { cmd.port[0] = PORT_QUICKLOAD3; } - - else if (strstr (name, "QuickLoad004")) + else if (strstr(name, "QuickLoad004")) { cmd.port[0] = PORT_QUICKLOAD4; } - - else if (strstr (name, "QuickLoad005")) + else if (strstr(name, "QuickLoad005")) { cmd.port[0] = PORT_QUICKLOAD5; } - - else if (strstr (name, "QuickLoad006")) + else if (strstr(name, "QuickLoad006")) { cmd.port[0] = PORT_QUICKLOAD6; } - - else if (strstr (name, "QuickLoad007")) + else if (strstr(name, "QuickLoad007")) { cmd.port[0] = PORT_QUICKLOAD7; } - - else if (strstr (name, "QuickLoad008")) + else if (strstr(name, "QuickLoad008")) { cmd.port[0] = PORT_QUICKLOAD8; } - - else if (strstr (name, "QuickLoad009")) + else if (strstr(name, "QuickLoad009")) { cmd.port[0] = PORT_QUICKLOAD9; } - - else if (strstr (name, "GTK_state_save_current")) + else if (strstr(name, "GTK_state_save_current")) { cmd.port[0] = PORT_SAVESLOT; } - - else if (strstr (name, "GTK_state_load_current")) + else if (strstr(name, "GTK_state_load_current")) { cmd.port[0] = PORT_LOADSLOT; } - - else if (strstr (name, "GTK_state_increment_save")) + else if (strstr(name, "GTK_state_increment_save")) { cmd.port[0] = PORT_INCREMENTSAVESLOT; } - - else if (strstr (name, "GTK_state_decrement_load")) + else if (strstr(name, "GTK_state_decrement_load")) { cmd.port[0] = PORT_DECREMENTLOADSLOT; } - - else if (strstr (name, "GTK_state_increment")) + else if (strstr(name, "GTK_state_increment")) { cmd.port[0] = PORT_INCREMENTSLOT; } - - else if (strstr (name, "GTK_state_decrement")) + else if (strstr(name, "GTK_state_decrement")) { cmd.port[0] = PORT_DECREMENTSLOT; } - - else if (strstr (name, "GTK_grab_mouse")) + else if (strstr(name, "GTK_grab_mouse")) { cmd.port[0] = PORT_GRABMOUSE; } - - else { - cmd = S9xGetCommandT (name); + cmd = S9xGetCommandT(name); } return cmd; } -void S9xProcessEvents (bool8 block) +void S9xProcessEvents(bool8 block) { JoyEvent event; Binding binding; - if (S9xGrabJoysticks ()) + if (S9xGrabJoysticks()) { - for (int i = 0; gui_config->joystick[i]; i++) + for (size_t i = 0; i < gui_config->joystick.size(); i++) { - while (gui_config->joystick[i]->get_event (&event)) + while (gui_config->joystick[i].get_event(&event)) { - binding = Binding (i, event.parameter, 0); - S9xReportButton (binding.hex (), event.state == JOY_PRESSED ? 1 : 0); + binding = Binding(i, event.parameter, 0); + S9xReportButton(binding.hex(), event.state == JOY_PRESSED ? 1 : 0); gui_config->screensaver_needs_reset = true; } } - S9xReleaseJoysticks (); + S9xReleaseJoysticks(); } } -static void poll_joystick_events () +static void poll_joystick_events() { SDL_Event event; - while (SDL_PollEvent (&event)) + while (SDL_PollEvent(&event)) { if (event.type == SDL_JOYAXISMOTION) { - gui_config->joystick[event.jaxis.which]->handle_event (&event); + gui_config->joystick[event.jaxis.which].handle_event(&event); } - else if (event.type == SDL_JOYHATMOTION) { - gui_config->joystick[event.jhat.which]->handle_event (&event); + gui_config->joystick[event.jhat.which].handle_event(&event); } - else if (event.type == SDL_JOYBUTTONUP || event.type == SDL_JOYBUTTONDOWN) { - gui_config->joystick[event.jbutton.which]->handle_event (&event); + gui_config->joystick[event.jbutton.which].handle_event(&event); } } } -void S9xInitInputDevices () +void S9xInitInputDevices() { - SDL_Init (SDL_INIT_JOYSTICK); + SDL_Init(SDL_INIT_JOYSTICK); + size_t num_joysticks = SDL_NumJoysticks(); + gui_config->joystick.resize(num_joysticks); - for (int i = 0; ; i++) + for (size_t i = 0; i < num_joysticks; i++) { - gui_config->joystick = (JoyDevice **) - realloc (gui_config->joystick, - sizeof (JoyDevice *) * (i + 1)); - - gui_config->joystick[i] = new JoyDevice (i); - - if (!gui_config->joystick[i]->enabled) - { - delete gui_config->joystick[i]; - gui_config->joystick[i] = NULL; - break; - } - else - { - gui_config->joystick[i]->joynum = i; - } + gui_config->joystick[i].set_sdl_joystick_num(i); } //First plug in both, they'll change later as needed - S9xSetController (0, CTL_JOYPAD, 0, 0, 0, 0); - S9xSetController (1, CTL_JOYPAD, 1, 0, 0, 0); + S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0); } -void S9xDeinitInputDevices () +void S9xDeinitInputDevices() { - for (int i = 0; gui_config->joystick[i] != NULL; i++) - { - delete gui_config->joystick[i]; - } - - free (gui_config->joystick); - - SDL_Quit (); + gui_config->joystick.clear(); + SDL_Quit(); } -JoyDevice::JoyDevice (unsigned int device_num) +JoyDevice::JoyDevice() { enabled = false; - axis = NULL; filedes = NULL; mode = JOY_MODE_INDIVIDUAL; +} - if ((int) device_num >= SDL_NumJoysticks ()) - return; +JoyDevice::~JoyDevice() +{ + if (enabled) + { + SDL_JoystickClose(filedes); + } +} - filedes = SDL_JoystickOpen (device_num); +bool JoyDevice::set_sdl_joystick_num(unsigned int device_num) +{ + if ((int)device_num >= SDL_NumJoysticks()) + { + enabled = false; + return false; + } + + filedes = SDL_JoystickOpen(device_num); if (!filedes) - return; + return false; enabled = true; - num_axes = SDL_JoystickNumAxes (filedes); - num_hats = SDL_JoystickNumHats (filedes); - axis = new int[num_axes]; - hat = new int[num_hats]; - calibration = new Calibration[num_axes]; + int num_axes = SDL_JoystickNumAxes(filedes); + int num_hats = SDL_JoystickNumHats(filedes); + axis.resize(num_axes); + hat.resize(num_hats); + calibration.resize(num_axes); for (int i = 0; i < num_axes; i++) { @@ -579,41 +534,31 @@ JoyDevice::JoyDevice (unsigned int device_num) calibration[i].center = 0; } - printf ("Joystick %d, %s:\n %d axes, %d buttons, %d hats\n", - device_num + 1, - SDL_JoystickName (filedes), - SDL_JoystickNumButtons (filedes), - num_axes, - num_hats); + printf("Joystick %d, %s:\n %d axes, %d buttons, %d hats\n", + device_num + 1, + SDL_JoystickName(filedes), + SDL_JoystickNumButtons(filedes), + num_axes, + num_hats); - memset (axis, 0, sizeof (int) * num_axes); + for (auto &i : axis) + i = 0; + + return true; } -JoyDevice::~JoyDevice () -{ - if (enabled) - { - SDL_JoystickClose (filedes); - delete[] axis; - delete[] hat; - delete[] calibration; - } - - enabled = false; -} - -void JoyDevice::add_event (unsigned int parameter, unsigned int state) +void JoyDevice::add_event(unsigned int parameter, unsigned int state) { JoyEvent event = { parameter, state }; - queue.push (event); + queue.push(event); } -void JoyDevice::register_centers () +void JoyDevice::register_centers() { - for (int i = 0; i < num_axes; i++) + for (size_t i = 0; i < axis.size(); i++) { - calibration[i].center = SDL_JoystickGetAxis (filedes, i); + calibration[i].center = SDL_JoystickGetAxis(filedes, i); /* Snap centers to specific target points */ if (calibration[i].center < -24576) @@ -629,7 +574,7 @@ void JoyDevice::register_centers () } } -void JoyDevice::handle_event (SDL_Event *event) +void JoyDevice::handle_event(SDL_Event *event) { if (event->type == SDL_JOYAXISMOTION) { @@ -644,20 +589,20 @@ void JoyDevice::handle_event (SDL_Event *event) { for (int i = 0; i < NUM_JOYPADS; i++) { - Binding *pad = (Binding *) &(gui_config->pad[i]); + Binding *pad = (Binding *)&(gui_config->pad[i]); for (int j = 0; j < NUM_JOYPAD_LINKS; j++) { - if (pad[j].get_axis () == event->jaxis.axis && - pad[j].get_device () == (unsigned int) (joynum + 1)) + if (pad[j].get_axis() == event->jaxis.axis && + pad[j].get_device() == (unsigned int)(joynum + 1)) { - t = pad[j].get_threshold (); + t = pad[j].get_threshold(); - if (pad[j].is_positive ()) + if (pad[j].is_positive()) { ax_max = (cal_max - cal_cen) * t / 100 + cal_cen; } - else if (pad[j].is_negative ()) + else if (pad[j].is_negative()) { ax_min = (cal_min - cal_cen) * t / 100 + cal_cen; } @@ -667,16 +612,16 @@ void JoyDevice::handle_event (SDL_Event *event) for (int i = 0; i < NUM_EMU_LINKS; i++) { - if (gui_config->shortcut[i].get_axis () == event->jaxis.axis && - gui_config->shortcut[i].get_device () == - (unsigned int) (joynum + 1)) + if (gui_config->shortcut[i].get_axis() == event->jaxis.axis && + gui_config->shortcut[i].get_device() == + (unsigned int)(joynum + 1)) { - t = gui_config->shortcut[i].get_threshold (); - if (gui_config->shortcut[i].is_positive ()) + t = gui_config->shortcut[i].get_threshold(); + if (gui_config->shortcut[i].is_positive()) { ax_max = (cal_max - cal_cen) * t / 100 + cal_cen; } - else if (gui_config->shortcut[i].is_negative ()) + else if (gui_config->shortcut[i].is_negative()) { ax_min = (cal_min - cal_cen) * t / 100 + cal_cen; } @@ -698,38 +643,37 @@ void JoyDevice::handle_event (SDL_Event *event) ax_max = cal_cen + 1; if (event->jaxis.value <= ax_min && - axis[event->jaxis.axis] > ax_min) + axis[event->jaxis.axis] > ax_min) { - add_event (JOY_AXIS (event->jaxis.axis, AXIS_NEG), 1); + add_event(JOY_AXIS(event->jaxis.axis, AXIS_NEG), 1); } if (event->jaxis.value > ax_min && - axis[event->jaxis.axis] <= ax_min) + axis[event->jaxis.axis] <= ax_min) { - add_event (JOY_AXIS (event->jaxis.axis, AXIS_NEG), 0); + add_event(JOY_AXIS(event->jaxis.axis, AXIS_NEG), 0); } if (event->jaxis.value >= ax_max && - axis[event->jaxis.axis] < ax_max) + axis[event->jaxis.axis] < ax_max) { - add_event (JOY_AXIS (event->jaxis.axis, AXIS_POS), 1); + add_event(JOY_AXIS(event->jaxis.axis, AXIS_POS), 1); } if (event->jaxis.value < ax_max && - axis[event->jaxis.axis] >= ax_max) + axis[event->jaxis.axis] >= ax_max) { - add_event (JOY_AXIS (event->jaxis.axis, AXIS_POS), 0); + add_event(JOY_AXIS(event->jaxis.axis, AXIS_POS), 0); } axis[event->jaxis.axis] = event->jaxis.value; - } else if (event->type == SDL_JOYBUTTONUP || - event->type == SDL_JOYBUTTONDOWN) + event->type == SDL_JOYBUTTONDOWN) { - add_event (event->jbutton.button, - event->jbutton.state == SDL_PRESSED ? 1 : 0); + add_event(event->jbutton.button, + event->jbutton.state == SDL_PRESSED ? 1 : 0); } else if (event->type == SDL_JOYHATMOTION) @@ -737,83 +681,83 @@ void JoyDevice::handle_event (SDL_Event *event) if ((event->jhat.value & SDL_HAT_UP) && !(hat[event->jhat.hat] & SDL_HAT_UP)) { - add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2), AXIS_POS), 1); + add_event(JOY_AXIS(axis.size() + (event->jhat.hat * 2), AXIS_POS), 1); } if (!(event->jhat.value & SDL_HAT_UP) && (hat[event->jhat.hat] & SDL_HAT_UP)) { - add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2), AXIS_POS), 0); + add_event(JOY_AXIS(axis.size() + (event->jhat.hat * 2), AXIS_POS), 0); } if ((event->jhat.value & SDL_HAT_DOWN) && !(hat[event->jhat.hat] & SDL_HAT_DOWN)) { - add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2), AXIS_NEG), 1); + add_event(JOY_AXIS(axis.size() + (event->jhat.hat * 2), AXIS_NEG), 1); } if (!(event->jhat.value & SDL_HAT_DOWN) && (hat[event->jhat.hat] & SDL_HAT_DOWN)) { - add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2), AXIS_NEG), 0); + add_event(JOY_AXIS(axis.size() + (event->jhat.hat * 2), AXIS_NEG), 0); } if ((event->jhat.value & SDL_HAT_LEFT) && !(hat[event->jhat.hat] & SDL_HAT_LEFT)) { - add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2) + 1, AXIS_NEG), 1); + add_event(JOY_AXIS(axis.size() + (event->jhat.hat * 2) + 1, AXIS_NEG), 1); } if (!(event->jhat.value & SDL_HAT_LEFT) && (hat[event->jhat.hat] & SDL_HAT_LEFT)) { - add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2) + 1, AXIS_NEG), 0); + add_event(JOY_AXIS(axis.size() + (event->jhat.hat * 2) + 1, AXIS_NEG), 0); } if ((event->jhat.value & SDL_HAT_RIGHT) && !(hat[event->jhat.hat] & SDL_HAT_RIGHT)) { - add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2) + 1, AXIS_POS), 1); + add_event(JOY_AXIS(axis.size() + (event->jhat.hat * 2) + 1, AXIS_POS), 1); } if (!(event->jhat.value & SDL_HAT_RIGHT) && (hat[event->jhat.hat] & SDL_HAT_RIGHT)) { - add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2) + 1, AXIS_POS), 0); + add_event(JOY_AXIS(axis.size() + (event->jhat.hat * 2) + 1, AXIS_POS), 0); } hat[event->jhat.hat] = event->jhat.value; } } -int JoyDevice::get_event (JoyEvent *event) +int JoyDevice::get_event(JoyEvent *event) { - poll_events (); + poll_events(); - if (queue.empty ()) + if (queue.empty()) return 0; - event->parameter = queue.front ().parameter; - event->state = queue.front ().state; + event->parameter = queue.front().parameter; + event->state = queue.front().state; - queue.pop (); + queue.pop(); return 1; } -void JoyDevice::poll_events () +void JoyDevice::poll_events() { - poll_joystick_events (); + poll_joystick_events(); } -void JoyDevice::flush () +void JoyDevice::flush() { SDL_Event event; - while (SDL_PollEvent (&event)) + while (SDL_PollEvent(&event)) { } - while (!queue.empty ()) - queue.pop (); + while (!queue.empty()) + queue.pop(); } diff --git a/gtk/src/gtk_control.h b/gtk/src/gtk_control.h index 05e0b18e..ba7c306b 100644 --- a/gtk/src/gtk_control.h +++ b/gtk/src/gtk_control.h @@ -18,21 +18,18 @@ const int NUM_JOYPADS = 10; -enum -{ +enum { JOY_MODE_GLOBAL = 0, JOY_MODE_INDIVIDUAL = 1, JOY_MODE_CALIBRATE = 2 }; -enum -{ +enum { JOY_RELEASED = 0, JOY_PRESSED = 1 }; -enum -{ +enum { PORT_COMMAND_FULLSCREEN = 1, PORT_COMMAND_SAVE_SPC = 2, PORT_OPEN_ROM = 3, @@ -70,15 +67,15 @@ typedef struct BindingLink extern const BindingLink b_links[]; extern const int b_breaks[]; const int NUM_JOYPAD_LINKS = 24; -const int NUM_EMU_LINKS = 62; +const int NUM_EMU_LINKS = 62; typedef struct JoypadBinding { std::array data; } JoypadBinding; -bool S9xGrabJoysticks (); -void S9xReleaseJoysticks (); +bool S9xGrabJoysticks(); +void S9xReleaseJoysticks(); typedef struct JoyEvent { @@ -97,31 +94,30 @@ typedef struct Calibration class JoyDevice { public: - JoyDevice (unsigned int device_num); - ~JoyDevice (); - int get_event (JoyEvent *event); - void flush (); - void handle_event (SDL_Event *event); - void register_centers (); + JoyDevice(); + ~JoyDevice(); + int get_event(JoyEvent *event); + void flush(); + void handle_event(SDL_Event *event); + void register_centers(); + bool set_sdl_joystick_num(unsigned int device_num); - SDL_Joystick *filedes; - Calibration *calibration; + SDL_Joystick *filedes; std::queue queue; - int mode; - int joynum; - int num_axes; - int num_hats; - int *axis; - int *hat; - bool enabled; + int mode; + int joynum; + std::vector calibration; + std::vector axis; + std::vector hat; + bool enabled; private: - void poll_events (); - void add_event (unsigned int parameter, unsigned int state); + void poll_events(); + void add_event(unsigned int parameter, unsigned int state); }; -void S9xDeinitInputDevices (); -Binding S9xGetBindingByName (const char *name); -bool S9xIsMousePluggedIn (); +void S9xDeinitInputDevices(); +Binding S9xGetBindingByName(const char *name); +bool S9xIsMousePluggedIn(); #endif /* __GTK_CONTROL_H*/ diff --git a/gtk/src/gtk_display.cpp b/gtk/src/gtk_display.cpp index a00c3f9a..4cfb454c 100644 --- a/gtk/src/gtk_display.cpp +++ b/gtk/src/gtk_display.cpp @@ -4,7 +4,7 @@ For further information, consult the LICENSE file in the root directory. \*****************************************************************************/ -#include "gtk_2_3_compat.h" +#include "gtk_compat.h" #include #include "gtk_s9x.h" @@ -12,6 +12,13 @@ #include "gtk_display_driver.h" #include "gtk_display_driver_gtk.h" +#include "snes9x.h" +#include "memmap.h" +#include "cpuexec.h" +#include "ppu.h" +#include "gfx.h" +#include "netplay.h" + #if defined(USE_XV) && defined(GDK_WINDOWING_X11) #include "gtk_display_driver_xv.h" #endif @@ -1284,12 +1291,12 @@ void S9xDisplayReconfigure() void S9xQueryDrivers() { - GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (top_level->get_window())); + GdkDisplay *gdk_display = top_level->window->get_display()->gobj(); gui_config->allow_xv = false; #if defined(USE_XV) && defined(GDK_WINDOWING_X11) - if (GDK_IS_X11_DISPLAY (display)) - gui_config->allow_xv = S9xXVDisplayDriver::query_availability (); + if (GDK_IS_X11_DISPLAY(gdk_display)) + gui_config->allow_xv = S9xXVDisplayDriver::query_availability(); #endif #ifdef USE_OPENGL @@ -1300,10 +1307,10 @@ void S9xQueryDrivers() gui_config->allow_xrandr = false; #ifdef GDK_WINDOWING_X11 - if (GDK_IS_X11_DISPLAY(display)) + if (GDK_IS_X11_DISPLAY(gdk_display)) { - Display *dpy = gdk_x11_display_get_xdisplay(gtk_widget_get_display(GTK_WIDGET(top_level->get_window()))); - Window xid = gdk_x11_window_get_xid(gtk_widget_get_window(GTK_WIDGET(top_level->get_window()))); + Display *dpy = gdk_x11_display_get_xdisplay(gdk_display); + Window xid = gdk_x11_window_get_xid(top_level->window->get_window()->gobj()); gui_config->allow_xrandr = true; gui_config->xrr_screen_resources = XRRGetScreenResourcesCurrent(dpy, xid); @@ -1397,31 +1404,29 @@ bool8 S9xDeinitUpdate(int width, int height) static void S9xInitDriver() { + // Only OpenGL is supported on Wayland #ifdef GDK_WINDOWING_WAYLAND if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) { gui_config->hw_accel = HWA_OPENGL; } #endif + switch (gui_config->hw_accel) { #ifdef USE_OPENGL case HWA_OPENGL: - - driver = new S9xOpenGLDisplayDriver(top_level, - gui_config); - + driver = new S9xOpenGLDisplayDriver(top_level, gui_config); break; #endif + #if defined(USE_XV) && defined(GDK_WINDOWING_X11) case HWA_XV: - driver = new S9xXVDisplayDriver(top_level, gui_config); - break; #endif - default: + default: driver = new S9xGTKDisplayDriver(top_level, gui_config); } @@ -1430,7 +1435,6 @@ static void S9xInitDriver() if (gui_config->hw_accel > 0) { delete driver; - gui_config->hw_accel = HWA_NONE; S9xInitDriver(); @@ -1452,7 +1456,8 @@ S9xDisplayDriver *S9xDisplayGetDriver() void S9xDeinitDisplay() { - driver->deinit(); + if (driver) + driver->deinit(); delete driver; if (pool) diff --git a/gtk/src/gtk_display.h b/gtk/src/gtk_display.h index 3b2fae8b..6607b526 100644 --- a/gtk/src/gtk_display.h +++ b/gtk/src/gtk_display.h @@ -20,8 +20,7 @@ #include "filter_epx_unsafe.h" #include "filter/snes_ntsc.h" -enum -{ +enum { FILTER_NONE = 0, FILTER_SUPEREAGLE = 1, FILTER_2XSAI = 2, @@ -42,21 +41,18 @@ enum NUM_FILTERS = 17 }; -enum -{ +enum { NTSC_COMPOSITE = 0, NTSC_SVIDEO = 1, NTSC_RGB = 2 }; -enum -{ +enum { ENDIAN_NORMAL = 0, ENDIAN_SWAPPED = 1 }; -enum -{ +enum { JOB_FILTER = 0, JOB_CONVERT = 1, JOB_SCALE_AND_CONVERT = 2, @@ -81,52 +77,53 @@ typedef struct thread_job_t volatile bool complete; } thread_job_t; -struct S9xRect { +struct S9xRect +{ int x; int y; int w; int h; }; -void S9xRegisterYUVTables (uint8 *y, uint8 *u, uint8 *v); -void S9xSetEndianess (int type); -double S9xGetAspect (); -S9xRect S9xApplyAspect (int, int, int, int); -void S9xConvertYUV (void *src_buffer, - void *dst_buffer, +void S9xRegisterYUVTables(uint8 *y, uint8 *u, uint8 *v); +void S9xSetEndianess(int type); +double S9xGetAspect(); +S9xRect S9xApplyAspect(int, int, int, int); +void S9xConvertYUV(void *src_buffer, + void *dst_buffer, + int src_pitch, + int dst_pitch, + int width, + int height); +void S9xConvert(void *src, + void *dst, + int src_pitch, + int dst_pitch, + int width, + int height, + int bpp); +void S9xConvertMask(void *src, + void *dst, int src_pitch, int dst_pitch, int width, - int height); -void S9xConvert (void *src, - void *dst, - int src_pitch, - int dst_pitch, - int width, - int height, - int bpp); -void S9xConvertMask (void *src, - void *dst, - int src_pitch, - int dst_pitch, - int width, - int height, - int rshift, - int gshift, - int bshift, - int bpp); -void S9xFilter (uint8 *src_buffer, - int src_pitch, - uint8 *dst_buffer, - int dst_pitch, - int& width, - int& height); -void get_filter_scale (int& width, int& height); -void S9xDisplayRefresh (int width, int height); -void S9xReinitDisplay (); -void S9xDisplayReconfigure (); -void S9xQueryDrivers (); -S9xDisplayDriver *S9xDisplayGetDriver (); -bool S9xDisplayDriverIsReady (); + int height, + int rshift, + int gshift, + int bshift, + int bpp); +void S9xFilter(uint8 *src_buffer, + int src_pitch, + uint8 *dst_buffer, + int dst_pitch, + int &width, + int &height); +void get_filter_scale(int &width, int &height); +void S9xDisplayRefresh(int width, int height); +void S9xReinitDisplay(); +void S9xDisplayReconfigure(); +void S9xQueryDrivers(); +S9xDisplayDriver *S9xDisplayGetDriver(); +bool S9xDisplayDriverIsReady(); #endif /* __GTK_DISPLAY_H */ diff --git a/gtk/src/gtk_display_driver.h b/gtk/src/gtk_display_driver.h index aa535860..e84172a3 100644 --- a/gtk/src/gtk_display_driver.h +++ b/gtk/src/gtk_display_driver.h @@ -26,7 +26,7 @@ class S9xDisplayDriver protected: Snes9xWindow *window; Snes9xConfig *config; - GtkWidget *drawing_area; + Gtk::DrawingArea *drawing_area; }; #endif /* __GTK_DISPLAY_DRIVER_H*/ diff --git a/gtk/src/gtk_display_driver_gtk.cpp b/gtk/src/gtk_display_driver_gtk.cpp index 6bfc80f6..e7206b17 100644 --- a/gtk/src/gtk_display_driver_gtk.cpp +++ b/gtk/src/gtk_display_driver_gtk.cpp @@ -4,29 +4,25 @@ For further information, consult the LICENSE file in the root directory. \*****************************************************************************/ -#include "gtk_2_3_compat.h" +#include "gtk_compat.h" #include #include "gtk_display.h" #include "gtk_display_driver_gtk.h" +#include "snes9x.h" S9xGTKDisplayDriver::S9xGTKDisplayDriver(Snes9xWindow *window, Snes9xConfig *config) { this->window = window; this->config = config; - this->drawing_area = GTK_WIDGET(window->drawing_area); + this->drawing_area = window->drawing_area; } void S9xGTKDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels) { - GtkAllocation allocation; - if (width <= 0) return; - - gtk_widget_get_allocation(drawing_area, &allocation); - - S9xRect dst = S9xApplyAspect(width, height, allocation.width, allocation.height); + S9xRect dst = S9xApplyAspect(width, height, drawing_area->get_width(), drawing_area->get_height()); output(buffer, stride_in_pixels * 2, dst.x, dst.y, width, height, dst.w, dst.h); } @@ -48,7 +44,6 @@ void S9xGTKDisplayDriver::output(void *src, } cairo_t *cr = window->get_cairo(); - cairo_surface_t *surface; surface = cairo_image_surface_create_for_data((unsigned char *)src, CAIRO_FORMAT_RGB16_565, width, height, src_pitch); @@ -94,12 +89,8 @@ void S9xGTKDisplayDriver::deinit() void S9xGTKDisplayDriver::clear() { - int width, height; - GtkAllocation allocation; - - gtk_widget_get_allocation(drawing_area, &allocation); - width = allocation.width; - height = allocation.height; + int width = drawing_area->get_width(); + int height = drawing_area->get_height(); cairo_t *cr = window->get_cairo(); diff --git a/gtk/src/gtk_display_driver_opengl.cpp b/gtk/src/gtk_display_driver_opengl.cpp index 9ce296d3..ec48e159 100644 --- a/gtk/src/gtk_display_driver_opengl.cpp +++ b/gtk/src/gtk_display_driver_opengl.cpp @@ -4,7 +4,7 @@ For further information, consult the LICENSE file in the root directory. \*****************************************************************************/ -#include "gtk_2_3_compat.h" +#include "gtk_compat.h" #include #include #include @@ -85,26 +85,23 @@ S9xOpenGLDisplayDriver::S9xOpenGLDisplayDriver(Snes9xWindow *window, Snes9xConfi { this->window = window; this->config = config; - this->drawing_area = GTK_WIDGET(window->drawing_area); + this->drawing_area = window->drawing_area; } void S9xOpenGLDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels) { - GtkAllocation allocation; - gtk_widget_get_allocation(drawing_area, &allocation); + Gtk::Allocation allocation = drawing_area->get_allocation(); - if (output_window_width != allocation.width || - output_window_height != allocation.height) + if (output_window_width != allocation.get_width() || + output_window_height != allocation.get_height()) { resize(); } -#if GTK_CHECK_VERSION(3, 10, 0) - int gdk_scale_factor = gdk_window_get_scale_factor(gdk_window); + int scale_factor = drawing_area->get_scale_factor(); - allocation.width *= gdk_scale_factor; - allocation.height *= gdk_scale_factor; -#endif + allocation.set_width(allocation.get_width() * scale_factor); + allocation.set_height(allocation.get_height() * scale_factor); if (!legacy) glActiveTexture(GL_TEXTURE0); @@ -118,8 +115,8 @@ void S9xOpenGLDisplayDriver::update(uint16_t *buffer, int width, int height, int glClear(GL_COLOR_BUFFER_BIT); - S9xRect content = S9xApplyAspect(width, height, allocation.width, allocation.height); - glViewport(content.x, allocation.height - content.y - content.h, content.w, content.h); + S9xRect content = S9xApplyAspect(width, height, allocation.get_width(), allocation.get_height()); + glViewport(content.x, allocation.get_height() - content.y - content.h, content.w, content.h); window->set_mouseable_area(content.x, content.y, content.w, content.h); update_texture_size(width, height); @@ -183,7 +180,7 @@ void S9xOpenGLDisplayDriver::update(uint16_t *buffer, int width, int height, int if (using_glsl_shaders) { - glsl_shader->render(texmap, width, height, content.x, allocation.height - content.y - content.h, content.w, content.h, S9xViewportCallback); + glsl_shader->render(texmap, width, height, content.x, allocation.get_height() - content.y - content.h, content.w, content.h, S9xViewportCallback); swap_buffers(); return; } @@ -468,24 +465,26 @@ void S9xOpenGLDisplayDriver::resize() bool S9xOpenGLDisplayDriver::create_context() { - gdk_window = gtk_widget_get_window(drawing_area); + gdk_window = drawing_area->get_window()->gobj(); + GdkDisplay *gdk_display = drawing_area->get_display()->gobj(); #ifdef GDK_WINDOWING_WAYLAND if (GDK_IS_WAYLAND_WINDOW(gdk_window)) { + if (!wl.attach(GTK_WIDGET(drawing_area->gobj()))) + return false; context = &wl; } #endif #ifdef GDK_WINDOWING_X11 if (GDK_IS_X11_WINDOW(gdk_window)) { + if (!glx.attach(gdk_x11_display_get_xdisplay(gdk_display), gdk_x11_window_get_xid(gdk_window))) + return false; context = &glx; } #endif - if (!context->attach(drawing_area)) - return false; - if (!context->create_context()) return false; diff --git a/gtk/src/gtk_display_driver_opengl.h b/gtk/src/gtk_display_driver_opengl.h index 95f00548..9a80d58f 100644 --- a/gtk/src/gtk_display_driver_opengl.h +++ b/gtk/src/gtk_display_driver_opengl.h @@ -14,7 +14,7 @@ #include "gtk_opengl_context.h" -#include "gtk_2_3_compat.h" +#include "gtk_compat.h" #ifdef GDK_WINDOWING_X11 #include "gtk_glx_context.h" #endif diff --git a/gtk/src/gtk_display_driver_xv.cpp b/gtk/src/gtk_display_driver_xv.cpp index 094440f2..674811e8 100644 --- a/gtk/src/gtk_display_driver_xv.cpp +++ b/gtk/src/gtk_display_driver_xv.cpp @@ -4,7 +4,7 @@ For further information, consult the LICENSE file in the root directory. \*****************************************************************************/ -#include "gtk_2_3_compat.h" +#include "gtk_compat.h" #include #include #include @@ -31,15 +31,14 @@ static int get_inv_shift(uint32 mask, int bpp) return (bpp - i); } -S9xXVDisplayDriver::S9xXVDisplayDriver(Snes9xWindow *window, - Snes9xConfig *config) +S9xXVDisplayDriver::S9xXVDisplayDriver(Snes9xWindow *window, Snes9xConfig *config) { this->window = window; this->config = config; - this->drawing_area = GTK_WIDGET(window->drawing_area); - display = - gdk_x11_display_get_xdisplay(gtk_widget_get_display(drawing_area)); - last_known_width = last_known_height = -1; + this->drawing_area = window->drawing_area; + display = gdk_x11_display_get_xdisplay(drawing_area->get_display()->gobj()); + last_known_width = -1; + last_known_height = -1; } void S9xXVDisplayDriver::resize_window(int width, int height) @@ -59,12 +58,13 @@ void S9xXVDisplayDriver::create_window(int width, int height) window_attr.y = 0; window_attr.wclass = GDK_INPUT_OUTPUT; window_attr.window_type = GDK_WINDOW_CHILD; - window_attr.visual = gdk_x11_screen_lookup_visual(gtk_widget_get_screen(drawing_area), vi->visualid); + window_attr.visual = gdk_x11_screen_lookup_visual(drawing_area->get_screen()->gobj(), vi->visualid); - gdk_window = gdk_window_new(gtk_widget_get_window(drawing_area), + gdk_window = gdk_window_new(drawing_area->get_window()->gobj(), &window_attr, GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL); - gdk_window_set_user_data(gdk_window, (gpointer)drawing_area); + + gdk_window_set_user_data(gdk_window, (gpointer)drawing_area->gobj()); gdk_window_show(gdk_window); xwindow = gdk_x11_window_get_xid(gdk_window); @@ -76,26 +76,22 @@ void S9xXVDisplayDriver::create_window(int width, int height) void S9xXVDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels) { int current_width, current_height; - GtkAllocation allocation; - gtk_widget_get_allocation(drawing_area, &allocation); + auto allocation = drawing_area->get_allocation(); - if (output_window_width != allocation.width || - output_window_height != allocation.height) + if (output_window_width != allocation.get_width() || + output_window_height != allocation.get_height()) { - resize_window(allocation.width, allocation.height); + resize_window(allocation.get_width(), allocation.get_height()); } -#if GTK_CHECK_VERSION(3, 10, 0) - int gdk_scale_factor = gdk_window_get_scale_factor(gdk_window); + int scale_factor = drawing_area->get_scale_factor(); - allocation.width *= gdk_scale_factor; - allocation.height *= gdk_scale_factor; + allocation.set_width(allocation.get_width() * scale_factor); + allocation.set_height(allocation.get_height() * scale_factor); -#endif - - current_width = allocation.width; - current_height = allocation.height; + current_width = allocation.get_width(); + current_height = allocation.get_height(); update_image_size(width, height); @@ -178,7 +174,7 @@ void S9xXVDisplayDriver::update_image_size(int width, int height) { /* Can't recover, send exit. */ fprintf(stderr, "Couldn't reallocate shared memory.\n"); - S9xExit(); + exit(1); } else if (shm.shmaddr != (void *)-1) { @@ -209,10 +205,10 @@ int S9xXVDisplayDriver::init() GdkWindow *root; /* Setup XV */ - gtk_widget_realize(drawing_area); + gtk_widget_realize(GTK_WIDGET(drawing_area->gobj())); - display = gdk_x11_display_get_xdisplay(gtk_widget_get_display(drawing_area)); - screen = gtk_widget_get_screen(drawing_area); + display = gdk_x11_display_get_xdisplay(drawing_area->get_display()->gobj()); + screen = drawing_area->get_screen()->gobj(); root = gdk_screen_get_root_window(screen); xv_portid = -1; @@ -391,7 +387,7 @@ int S9xXVDisplayDriver::init() } xcolormap = XCreateColormap(display, - gdk_x11_window_get_xid(gtk_widget_get_window(drawing_area)), + gdk_x11_window_get_xid(drawing_area->get_window()->gobj()), vi->visual, AllocNone); @@ -443,20 +439,10 @@ void S9xXVDisplayDriver::deinit() void S9xXVDisplayDriver::clear() { - int width, height; - GtkAllocation allocation; GC xgc = XDefaultGC(display, XDefaultScreen(display)); - gtk_widget_get_allocation(drawing_area, &allocation); -#if GTK_CHECK_VERSION(3, 10, 0) - int gdk_scale_factor = gdk_window_get_scale_factor(gdk_window); - - allocation.width *= gdk_scale_factor; - allocation.height *= gdk_scale_factor; - -#endif - width = allocation.width; - height = allocation.height; + int width = drawing_area->get_width() * drawing_area->get_scale_factor(); + int height = drawing_area->get_height() * drawing_area->get_scale_factor(); if (window->last_width <= 0 || window->last_height <= 0) { diff --git a/gtk/src/gtk_display_driver_xv.h b/gtk/src/gtk_display_driver_xv.h index 8c4863ef..5dd84241 100644 --- a/gtk/src/gtk_display_driver_xv.h +++ b/gtk/src/gtk_display_driver_xv.h @@ -7,14 +7,14 @@ #ifndef __GTK_DISPLAY_DRIVER_XV_H #define __GTK_DISPLAY_DRIVER_XV_H +#include "gtk_s9x.h" +#include "gtk_display_driver.h" + #include #include #include #include -#include "gtk_s9x.h" -#include "gtk_display_driver.h" - const uint32 FOURCC_YUY2 = 0x32595559; class S9xXVDisplayDriver : public S9xDisplayDriver diff --git a/gtk/src/gtk_file.cpp b/gtk/src/gtk_file.cpp index b0e34e98..5b83acc7 100644 --- a/gtk/src/gtk_file.cpp +++ b/gtk/src/gtk_file.cpp @@ -7,27 +7,29 @@ #include #include -#include "gtk_2_3_compat.h" +#include "gtk_compat.h" #include "gtk_s9x.h" +#include "display.h" +#include "memmap.h" +#include "snapshot.h" +#include "cheats.h" static char buf[PATH_MAX]; -const char * -S9xChooseMovieFilename (bool8 read_only) +const char *S9xChooseMovieFilename(bool8 read_only) { static char path[PATH_MAX]; if (!gui_config->rom_loaded) return ""; - const char *str = top_level->open_movie_dialog (read_only); - strcpy (path, str); + auto filename = top_level->open_movie_dialog(read_only); + strcpy(path, filename.c_str()); return path; } -const char * -S9xChooseFilename (bool8 read_only) +const char *S9xChooseFilename(bool8 read_only) { return ""; } @@ -37,11 +39,10 @@ S9xChooseFilename (bool8 read_only) #define SLASH_CHAR '/' #endif -void -_splitpath (const char *path, char *drive, char *dir, char *fname, char *ext) +void _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext) { - char *slash = strrchr ((char *) path, SLASH_CHAR); - char *dot = strrchr ((char *) path, '.'); + char *slash = strrchr((char *)path, SLASH_CHAR); + char *dot = strrchr((char *)path, '.'); *drive = '\0'; @@ -53,12 +54,12 @@ _splitpath (const char *path, char *drive, char *dir, char *fname, char *ext) if (!slash) { *dir = '\0'; - strcpy (fname, path); + strcpy(fname, path); if (dot) { fname[dot - path] = '\0'; - strcpy (ext, dot + 1); + strcpy(ext, dot + 1); } else { @@ -67,14 +68,14 @@ _splitpath (const char *path, char *drive, char *dir, char *fname, char *ext) } else { - strcpy (dir, path); + strcpy(dir, path); dir[slash - path] = '\0'; - strcpy (fname, slash + 1); + strcpy(fname, slash + 1); if (dot) { fname[(dot - slash) - 1] = '\0'; - strcpy (ext, dot + 1); + strcpy(ext, dot + 1); } else { @@ -83,57 +84,49 @@ _splitpath (const char *path, char *drive, char *dir, char *fname, char *ext) } } -void -_makepath (char *path, - const char *drive, - const char *dir, - const char *fname, - const char *ext) +void _makepath(char *path, const char *drive, const char *dir, const char *fname, const char *ext) { if (dir && *dir) { - strcpy (path, dir); - strcat (path, "/"); + strcpy(path, dir); + strcat(path, "/"); } else *path = '\0'; - strcat (path, fname); + strcat(path, fname); if (ext && *ext) { - strcat (path, "."); - strcat (path, ext); + strcat(path, "."); + strcat(path, ext); } } -const char * -S9xGetFilenameInc (const char *e, enum s9x_getdirtype dirtype) +const char *S9xGetFilenameInc(const char *e, enum s9x_getdirtype dirtype) { - static char filename[PATH_MAX + 1]; - char dir[_MAX_DIR + 1]; - char drive[_MAX_DRIVE + 1]; - char fname[_MAX_FNAME + 1]; - char ext[_MAX_EXT + 1]; + static char filename[PATH_MAX + 1]; + char dir[_MAX_DIR + 1]; + char drive[_MAX_DRIVE + 1]; + char fname[_MAX_FNAME + 1]; + char ext[_MAX_EXT + 1]; unsigned int i = 0; - struct stat buf; - const char *d; + struct stat buf; + const char *d; - _splitpath (Memory.ROMFilename, drive, dir, fname, ext); - d = S9xGetDirectory (dirtype); + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + d = S9xGetDirectory(dirtype); do { - snprintf (filename, PATH_MAX, "%s" SLASH_STR "%s%03d%s", d, fname, i, e); + snprintf(filename, PATH_MAX, "%s" SLASH_STR "%s%03d%s", d, fname, i, e); i++; - } - while (stat (filename, &buf) == 0 && i != 0); /* Overflow? ...riiight :-) */ + } while (stat(filename, &buf) == 0 && i != 0); /* Overflow? ...riiight :-) */ return (filename); } -const char * -S9xGetDirectory (enum s9x_getdirtype dirtype) +const char *S9xGetDirectory(enum s9x_getdirtype dirtype) { static char path[PATH_MAX + 1]; @@ -187,15 +180,15 @@ S9xGetDirectory (enum s9x_getdirtype dirtype) { char *loc; - strcpy (path, Memory.ROMFilename); + strcpy(path, Memory.ROMFilename); - loc = strrchr (path, SLASH_CHAR); + loc = strrchr(path, SLASH_CHAR); if (loc == NULL) { - if (getcwd (path, PATH_MAX + 1) == NULL) + if (getcwd(path, PATH_MAX + 1) == NULL) { - strcpy (path, getenv ("HOME")); + strcpy(path, getenv("HOME")); } } else @@ -207,279 +200,197 @@ S9xGetDirectory (enum s9x_getdirtype dirtype) return path; } -const char * -S9xGetFilename (const char *ex, enum s9x_getdirtype dirtype) +const char *S9xGetFilename(const char *ex, enum s9x_getdirtype dirtype) { static char filename[PATH_MAX + 1]; - char dir[_MAX_DIR + 1]; - char drive[_MAX_DRIVE + 1]; - char fname[_MAX_FNAME + 1]; - char ext[_MAX_EXT + 1]; + char dir[_MAX_DIR + 1]; + char drive[_MAX_DRIVE + 1]; + char fname[_MAX_FNAME + 1]; + char ext[_MAX_EXT + 1]; - _splitpath (Memory.ROMFilename, drive, dir, fname, ext); + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); - snprintf (filename, sizeof (filename), "%s" SLASH_STR "%s%s", - S9xGetDirectory (dirtype), fname, ex); + snprintf(filename, sizeof(filename), "%s" SLASH_STR "%s%s", + S9xGetDirectory(dirtype), fname, ex); return (filename); } -const char * -S9xBasename (const char *f) +const char *S9xBasename(const char *f) { const char *p; - if ((p = strrchr (f, '/')) != NULL || (p = strrchr (f, '\\')) != NULL) + if ((p = strrchr(f, '/')) != NULL || (p = strrchr(f, '\\')) != NULL) return (p + 1); return f; } -const char * -S9xBasenameNoExt (const char *f) +const char *S9xBasenameNoExt(const char *f) { static char filename[PATH_MAX]; const char *base, *ext; - if (!(base = strrchr (f, SLASH_CHAR))) + if (!(base = strrchr(f, SLASH_CHAR))) base = f; else base += 1; - ext = strrchr (f, '.'); + ext = strrchr(f, '.'); if (!ext) - snprintf (filename, PATH_MAX, "%s", base); + snprintf(filename, PATH_MAX, "%s", base); else { int len = ext - base; - strncpy (filename, base, len); + strncpy(filename, base, len); filename[len] = '\0'; } return filename; } -static int -file_exists (const char *name) +static int file_exists(const char *name) { FILE *f = NULL; - f = fopen (name, "r"); + f = fopen(name, "r"); if (!f) return 0; else { - fclose (f); + fclose(f); return 1; } } -bool8 -S9xOpenSnapshotFile (const char *fname, bool8 read_only, STREAM *file) +bool8 S9xOpenSnapshotFile(const char *fname, bool8 read_only, STREAM *file) { - char filename [PATH_MAX + 1]; - char drive [_MAX_DRIVE + 1]; - char dir [_MAX_DIR + 1]; - char ext [_MAX_EXT + 1]; + char filename[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1]; + char dir[_MAX_DIR + 1]; + char ext[_MAX_EXT + 1]; - _splitpath (fname, drive, dir, filename, ext); + _splitpath(fname, drive, dir, filename, ext); if (*drive || *dir == '/' || (*dir == '.' && (*(dir + 1) == '/'))) { - snprintf (filename, PATH_MAX + 1, "%s", fname); + snprintf(filename, PATH_MAX + 1, "%s", fname); - if (!file_exists (filename)) + if (!file_exists(filename)) { if (!*ext) - strcat (filename, ".s9x"); + strcat(filename, ".s9x"); } } else { - strcpy (filename, S9xGetDirectory (SNAPSHOT_DIR)); - strcat (filename, SLASH_STR); - strcat (filename, fname); + strcpy(filename, S9xGetDirectory(SNAPSHOT_DIR)); + strcat(filename, SLASH_STR); + strcat(filename, fname); - if (!file_exists (filename)) + if (!file_exists(filename)) { if (!*ext) - strcat (filename, ".s9x"); + strcat(filename, ".s9x"); } } #ifdef ZLIB if (read_only) { - if ((*file = OPEN_STREAM (filename, "rb"))) + if ((*file = OPEN_STREAM(filename, "rb"))) return (true); else - fprintf (stderr, - "Failed to open file stream for reading. (%s)\n", - zError (errno)); + fprintf(stderr, + "Failed to open file stream for reading. (%s)\n", + zError(errno)); } else { - if ((*file = OPEN_STREAM (filename, "wb"))) + if ((*file = OPEN_STREAM(filename, "wb"))) { return (true); } else { - fprintf (stderr, - "Couldn't open stream with zlib. (%s)\n", - zError (errno)); + fprintf(stderr, + "Couldn't open stream with zlib. (%s)\n", + zError(errno)); } } - fprintf (stderr, "zlib: Couldn't open snapshot file:\n%s\n", filename); + fprintf(stderr, "zlib: Couldn't open snapshot file:\n%s\n", filename); #else - char command [PATH_MAX]; + char command[PATH_MAX]; if (read_only) { - sprintf (command, "gzip -d <\"%s\"", filename); - if (*file = popen (command, "r")) + sprintf(command, "gzip -d <\"%s\"", filename); + if (*file = popen(command, "r")) return (true); } else { - sprintf (command, "gzip --best >\"%s\"", filename); - if (*file = popen (command, "wb")) + sprintf(command, "gzip --best >\"%s\"", filename); + if (*file = popen(command, "wb")) return (true); } - fprintf (stderr, "gzip: Couldn't open snapshot file:\n%s\n", filename); + fprintf(stderr, "gzip: Couldn't open snapshot file:\n%s\n", filename); #endif return (false); } -void S9xCloseSnapshotFile (STREAM file) +void S9xCloseSnapshotFile(STREAM file) { #ifdef ZLIB - CLOSE_STREAM (file); + CLOSE_STREAM(file); #else - pclose (file); + pclose(file); #endif } -void -S9xAutoSaveSRAM () +void S9xAutoSaveSRAM() { - Memory.SaveSRAM (S9xGetFilename (".srm", SRAM_DIR)); - S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR)); + Memory.SaveSRAM(S9xGetFilename(".srm", SRAM_DIR)); + S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); } -void -S9xLoadState (const char *filename) +void S9xLoadState(const char *filename) { - S9xFreezeGame (S9xGetFilename (".undo", SNAPSHOT_DIR)); + S9xFreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR)); - if (S9xUnfreezeGame (filename)) + if (S9xUnfreezeGame(filename)) { - sprintf (buf, "%s loaded", filename); - S9xSetInfoString (buf); + sprintf(buf, "%s loaded", filename); + S9xSetInfoString(buf); } else { - fprintf (stderr, "Failed to load state file: %s\n", filename); + fprintf(stderr, "Failed to load state file: %s\n", filename); } } -void -S9xSaveState (const char *filename) +void S9xSaveState(const char *filename) { - if (S9xFreezeGame (filename)) + if (S9xFreezeGame(filename)) { - sprintf (buf, "%s saved", filename); - S9xSetInfoString (buf); + sprintf(buf, "%s saved", filename); + S9xSetInfoString(buf); } else { - fprintf (stderr, "Couldn't save state file: %s\n", filename); + fprintf(stderr, "Couldn't save state file: %s\n", filename); } } -char * -S9xOpenROMDialog () -{ - GtkWidget *dialog; - GtkFileFilter *filter; - char *filename = NULL; - gint result; - const char *extensions[] = - { - "*.smc", "*.SMC", "*.fig", "*.FIG", "*.sfc", "*.SFC", - "*.jma", "*.JMA", "*.zip", "*.ZIP", "*.gd3", "*.GD3", - "*.swc", "*.SWC", "*.gz" , "*.GZ", "*.bs", "*.BS", - NULL - }; - - top_level->pause_from_focus_change (); - - dialog = gtk_file_chooser_dialog_new (_("Open SNES ROM Image"), - top_level->get_window (), - GTK_FILE_CHOOSER_ACTION_OPEN, - "gtk-cancel", GTK_RESPONSE_CANCEL, - "gtk-open", GTK_RESPONSE_ACCEPT, - NULL); - - filter = gtk_file_filter_new (); - gtk_file_filter_set_name (filter, _("SNES ROM Images")); - for (int i = 0; extensions[i]; i++) - { - gtk_file_filter_add_pattern (filter, extensions[i]); - } - gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); - - filter = gtk_file_filter_new (); - gtk_file_filter_set_name (filter, _("All Files")); - gtk_file_filter_add_pattern (filter, "*.*"); - gtk_file_filter_add_pattern (filter, "*"); - gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); - - if (!gui_config->last_directory.empty ()) - { - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), - gui_config->last_directory.c_str ()); - } - - result = gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_hide (dialog); - - if (result == GTK_RESPONSE_ACCEPT) - { - char *directory; - - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - directory = - gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)); - if (directory) - { - gui_config->last_directory = directory; - g_free (directory); - } - } - - else - { - filename = NULL; - } - - gtk_widget_destroy (dialog); - - top_level->unpause_from_focus_change (); - - return filename; -} - /* QuickSave/Load from S9x base controls.cpp */ -void -S9xQuickSaveSlot (int slot) +void S9xQuickSaveSlot(int slot) { char def[PATH_MAX]; char filename[PATH_MAX]; @@ -490,21 +401,21 @@ S9xQuickSaveSlot (int slot) if (!gui_config->rom_loaded) return; - _splitpath (Memory.ROMFilename, drive, dir, def, ext); + _splitpath(Memory.ROMFilename, drive, dir, def, ext); - snprintf (filename, PATH_MAX, "%s%s%s.%03d", - S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, def, + snprintf(filename, PATH_MAX, "%s%s%s.%03d", + S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, slot); - if (S9xFreezeGame (filename)) + if (S9xFreezeGame(filename)) { - snprintf (buf, PATH_MAX, "%s.%03d saved", def, slot); + snprintf(buf, PATH_MAX, "%s.%03d saved", def, slot); - S9xSetInfoString (buf); + S9xSetInfoString(buf); } } -void S9xQuickLoadSlot (int slot) +void S9xQuickLoadSlot(int slot) { char def[PATH_MAX]; char filename[PATH_MAX]; @@ -515,44 +426,43 @@ void S9xQuickLoadSlot (int slot) if (!gui_config->rom_loaded) return; - _splitpath (Memory.ROMFilename, drive, dir, def, ext); + _splitpath(Memory.ROMFilename, drive, dir, def, ext); - snprintf (filename, PATH_MAX, "%s%s%s.%03d", - S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, def, + snprintf(filename, PATH_MAX, "%s%s%s.%03d", + S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, slot); - if (file_exists (filename)) - S9xFreezeGame (S9xGetFilename (".undo", SNAPSHOT_DIR)); + if (file_exists(filename)) + S9xFreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR)); - if (S9xUnfreezeGame (filename)) + if (S9xUnfreezeGame(filename)) { - snprintf (buf, PATH_MAX, "%s.%03d loaded", def, slot); - S9xSetInfoString (buf); + snprintf(buf, PATH_MAX, "%s.%03d loaded", def, slot); + S9xSetInfoString(buf); return; } static const char *digits = "t123456789"; - _splitpath (Memory.ROMFilename, drive, dir, def, ext); + _splitpath(Memory.ROMFilename, drive, dir, def, ext); - snprintf (filename, PATH_MAX, "%s%s%s.zs%c", - S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, - def, digits[slot]); + snprintf(filename, PATH_MAX, "%s%s%s.zs%c", + S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, + def, digits[slot]); - if (file_exists (filename)) - S9xFreezeGame (S9xGetFilename (".undo", SNAPSHOT_DIR)); + if (file_exists(filename)) + S9xFreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR)); - if (S9xUnfreezeGame (filename)) + if (S9xUnfreezeGame(filename)) { - snprintf (buf, PATH_MAX, - "Loaded ZSNES freeze file %s.zs%c", - def, digits [slot]); - S9xSetInfoString (buf); + snprintf(buf, PATH_MAX, + "Loaded ZSNES freeze file %s.zs%c", + def, digits[slot]); + S9xSetInfoString(buf); return; } - S9xMessage (S9X_ERROR, - S9X_FREEZE_FILE_NOT_FOUND, - "Freeze file not found"); + S9xMessage(S9X_ERROR, + S9X_FREEZE_FILE_NOT_FOUND, + "Freeze file not found"); } - diff --git a/gtk/src/gtk_file.h b/gtk/src/gtk_file.h index b4f42709..4ee91408 100644 --- a/gtk/src/gtk_file.h +++ b/gtk/src/gtk_file.h @@ -7,13 +7,12 @@ #ifndef __GTK_FILE_H #define __GTK_FILE_H -char *S9xOpenROMDialog (); -const char *S9xBasenameNoExt (const char *); +const char *S9xBasenameNoExt(const char *); -void S9xLoadState (const char *filename); -void S9xSaveState (const char *filename); +void S9xLoadState(const char *filename); +void S9xSaveState(const char *filename); -void S9xQuickSaveSlot (int slot); -void S9xQuickLoadSlot (int slot); +void S9xQuickSaveSlot(int slot); +void S9xQuickLoadSlot(int slot); #endif /* __GTK_FILE_H */ diff --git a/gtk/src/gtk_glx_context.cpp b/gtk/src/gtk_glx_context.cpp index 868bc8a0..3dff5efb 100644 --- a/gtk/src/gtk_glx_context.cpp +++ b/gtk/src/gtk_glx_context.cpp @@ -6,99 +6,61 @@ #include #include +#include #include "gtk_s9x.h" #include "gtk_glx_context.h" -#include "gtk_2_3_compat.h" -GTKGLXContext::GTKGLXContext () +GTKGLXContext::GTKGLXContext() { - gdk_display = NULL; - parent_gdk_window = NULL; - gdk_window = NULL; - display = NULL; - vi = NULL; - context = NULL; + display = NULL; + context = NULL; - version_major = -1; - version_minor = -1; + version_major = -1; + version_minor = -1; use_oml_sync_control = false; ust = msc = sbc = 0; } -GTKGLXContext::~GTKGLXContext () +GTKGLXContext::~GTKGLXContext() { if (context) - glXDestroyContext (display, context); - - if (gdk_window) - gdk_window_destroy (gdk_window); - - if (vi) - XFree (vi); + glXDestroyContext(display, context); } -bool GTKGLXContext::attach (GtkWidget *widget) +bool GTKGLXContext::attach(Display *dpy, Window xid) { - GdkScreen *gdk_screen; - GdkWindow *window; GLXFBConfig *fbconfigs; - int num_fbconfigs; + int num_fbconfigs; int attribs[] = { GLX_DOUBLEBUFFER, True, GLX_X_RENDERABLE, True, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, None }; - window = gtk_widget_get_window (widget); - this->widget = widget; + this->xid = xid; + display = dpy; - if (!GDK_IS_X11_WINDOW (window)) - return false; - - parent_gdk_window = window; - gdk_display = gdk_window_get_display (window); - gdk_screen = gdk_window_get_screen (window); - screen = gdk_x11_screen_get_screen_number (gdk_screen); - display = GDK_DISPLAY_XDISPLAY (gdk_display); - - glXQueryVersion (display, &version_major, &version_minor); + glXQueryVersion(display, &version_major, &version_minor); if (version_major < 2 && version_minor < 3) return false; - fbconfigs = glXChooseFBConfig (display, screen, attribs, &num_fbconfigs); + fbconfigs = glXChooseFBConfig(display, screen, attribs, &num_fbconfigs); if (!fbconfigs || num_fbconfigs < 1) { - printf ("Couldn't match a GLX framebuffer config.\n"); + printf("Couldn't match a GLX framebuffer config.\n"); return false; } fbconfig = fbconfigs[0]; - XFree(fbconfigs); - - vi = glXGetVisualFromFBConfig (display, fbconfig); - - gdk_window_get_geometry (parent_gdk_window, &x, &y, &width, &height); - memset (&window_attr, 0, sizeof (GdkWindowAttr)); - window_attr.event_mask = GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK; - window_attr.width = width; - window_attr.height = height; - window_attr.wclass = GDK_INPUT_OUTPUT; - window_attr.window_type = GDK_WINDOW_CHILD; - window_attr.visual = gdk_x11_screen_lookup_visual (gdk_screen, vi->visualid); - - gdk_window = gdk_window_new (window, &window_attr, GDK_WA_VISUAL); - gdk_window_set_user_data (gdk_window, (gpointer) widget); - gdk_window_show (gdk_window); - xid = gdk_x11_window_get_xid (gdk_window); return true; } -bool GTKGLXContext::create_context () +bool GTKGLXContext::create_context() { int context_attribs[] = { GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, @@ -107,18 +69,21 @@ bool GTKGLXContext::create_context () None }; - const char *extensions = glXQueryExtensionsString (display, screen); + const char *extensions = glXQueryExtensionsString(display, screen); - gdk_x11_display_error_trap_push(gdk_display); - if (strstr (extensions, "GLX_ARB_create_context")) - context = glXCreateContextAttribsARB (display, fbconfig, NULL, True, context_attribs); + XSetErrorHandler([](Display *dpy, XErrorEvent *event) -> int { + printf("XError: type: %d code: %d\n", event->type, event->error_code); + return X_OK; + }); + if (strstr(extensions, "GLX_ARB_create_context")) + context = glXCreateContextAttribsARB(display, fbconfig, NULL, True, context_attribs); if (!context) - context = glXCreateNewContext (display, fbconfig, GLX_RGBA_TYPE, NULL, True); - gdk_x11_display_error_trap_pop_ignored(gdk_display); + context = glXCreateNewContext(display, fbconfig, GLX_RGBA_TYPE, NULL, True); + XSetErrorHandler(nullptr); if (!context) { - printf ("Couldn't create GLX context.\n"); + printf("Couldn't create GLX context.\n"); return false; } @@ -128,31 +93,27 @@ bool GTKGLXContext::create_context () return true; } -void GTKGLXContext::resize () +void GTKGLXContext::resize() { - gdk_window_get_geometry (parent_gdk_window, &x, &y, &width, &height); + while (!ready()) + usleep(100); - if (window_attr.width == width && window_attr.height == height) - return; + unsigned int width; + unsigned int height; + glXQueryDrawable(display, xid, GLX_WIDTH, &width); + glXQueryDrawable(display, xid, GLX_HEIGHT, &height); - window_attr.width = width; - window_attr.height = height; - - gdk_window_destroy (gdk_window); - gdk_window = gdk_window_new (parent_gdk_window, &window_attr, GDK_WA_VISUAL); - gdk_window_set_user_data (gdk_window, (gpointer) widget); - gdk_window_show (gdk_window); - xid = gdk_x11_window_get_xid (gdk_window); - - make_current (); + this->width = width; + this->height = height; + make_current(); } -void GTKGLXContext::swap_buffers () +void GTKGLXContext::swap_buffers() { if (use_oml_sync_control) glXGetSyncValuesOML(display, xid, &ust, &msc, &sbc); - glXSwapBuffers (display, xid); + glXSwapBuffers(display, xid); } bool GTKGLXContext::ready() @@ -170,21 +131,19 @@ bool GTKGLXContext::ready() return true; } -void GTKGLXContext::make_current () +void GTKGLXContext::make_current() { - glXMakeCurrent (display, xid, context); + glXMakeCurrent(display, xid, context); } -void GTKGLXContext::swap_interval (int frames) +void GTKGLXContext::swap_interval(int frames) { - if (epoxy_has_glx_extension (display, screen, "GLX_EXT_swap_control")) - glXSwapIntervalEXT (display, xid, frames); - else if (epoxy_has_glx_extension (display, screen, "GLX_SGI_swap_control")) - glXSwapIntervalSGI (frames); + if (epoxy_has_glx_extension(display, screen, "GLX_EXT_swap_control")) + glXSwapIntervalEXT(display, xid, frames); + else if (epoxy_has_glx_extension(display, screen, "GLX_SGI_swap_control")) + glXSwapIntervalSGI(frames); #ifdef GLX_MESA_swap_control - else if (epoxy_has_glx_extension (display, screen, "GLX_MESA_swap_control")) - glXSwapIntervalMESA (frames); + else if (epoxy_has_glx_extension(display, screen, "GLX_MESA_swap_control")) + glXSwapIntervalMESA(frames); #endif } - - diff --git a/gtk/src/gtk_glx_context.h b/gtk/src/gtk_glx_context.h index 8ee7c91a..59c954f1 100644 --- a/gtk/src/gtk_glx_context.h +++ b/gtk/src/gtk_glx_context.h @@ -7,36 +7,27 @@ #ifndef __GTK_GLX_CONTEXT_H #define __GTK_GLX_CONTEXT_H -#include "gtk_2_3_compat.h" -#include - #include "gtk_opengl_context.h" +#include + class GTKGLXContext : public OpenGLContext { public: - GTKGLXContext (); - ~GTKGLXContext (); - bool attach (GtkWidget *widget); - bool create_context (); - void resize (); - void swap_buffers (); - void swap_interval (int frames); - void make_current (); + GTKGLXContext(); + ~GTKGLXContext(); + bool attach(Display *dpy, Window xid); + bool create_context(); + void resize(); + void swap_buffers(); + void swap_interval(int frames); + void make_current(); bool ready(); - GtkWidget *widget; - - GdkDisplay *gdk_display; - GdkWindow *parent_gdk_window; - GdkWindow *gdk_window; - GdkWindowAttr window_attr; - GLXContext context; GLXFBConfig fbconfig; Display *display; int screen; - XVisualInfo *vi; Window xid; int version_major; diff --git a/gtk/src/gtk_netplay.cpp b/gtk/src/gtk_netplay.cpp index 50e792fc..14ff839b 100644 --- a/gtk/src/gtk_netplay.cpp +++ b/gtk/src/gtk_netplay.cpp @@ -10,133 +10,132 @@ #include "gtk_netplay_dialog.h" #include "gtk_netplay.h" #include "gtk_sound.h" +#include "snes9x.h" +#include "memmap.h" +#include "netplay.h" +#include "cpuexec.h" +#include "display.h" +#include "ppu.h" -uint16 MovieGetJoypad (int i); -void MovieSetJoypad (int i, uint16 buttons); +uint16 MovieGetJoypad(int i); +void MovieSetJoypad(int i, uint16 buttons); static uint32 local_joypads[8], joypads[8]; static GThread *npthread; extern SNPServer NPServer; -static void -S9xNetplayPreconnect () +static void S9xNetplayPreconnect() { - S9xNetplayDisconnect (); + S9xNetplayDisconnect(); if (gui_config->rom_loaded) { - S9xAutoSaveSRAM (); + S9xAutoSaveSRAM(); } NetPlay.MaxBehindFrameCount = gui_config->netplay_max_frame_loss; NetPlay.Waiting4EmulationThread = false; } -static void -S9xNetplayConnect () +static void S9xNetplayConnect() { GtkWidget *msg; - S9xNetplayPreconnect (); + S9xNetplayPreconnect(); uint32 flags = CPU.Flags; - if (!gui_config->netplay_last_rom.empty () && - !top_level->try_open_rom (gui_config->netplay_last_rom.c_str ())) + if (!gui_config->netplay_last_rom.empty() && + !top_level->try_open_rom(gui_config->netplay_last_rom)) { return; } - if (!S9xNPConnectToServer (gui_config->netplay_last_host.c_str (), - gui_config->netplay_last_port, - Memory.ROMName)) + if (!S9xNPConnectToServer(gui_config->netplay_last_host.c_str(), + gui_config->netplay_last_port, + Memory.ROMName)) { - msg = gtk_message_dialog_new (NULL, - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "Couldn't connect to server: %s:%d", - gui_config->netplay_last_host.c_str (), - gui_config->netplay_last_port); - gtk_window_set_title (GTK_WINDOW (msg), _("Connection Error")); + msg = gtk_message_dialog_new(NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Couldn't connect to server: %s:%d", + gui_config->netplay_last_host.c_str(), + gui_config->netplay_last_port); + gtk_window_set_title(GTK_WINDOW(msg), _("Connection Error")); - gtk_dialog_run (GTK_DIALOG (msg)); - gtk_widget_destroy (msg); + gtk_dialog_run(GTK_DIALOG(msg)); + gtk_widget_destroy(msg); } gui_config->netplay_activated = true; /* If no rom is specified, assume we'll get it from the server */ - if (gui_config->netplay_last_rom.empty ()) + if (gui_config->netplay_last_rom.empty()) { Settings.StopEmulation = false; - S9xROMLoaded (); + S9xROMLoaded(); } - S9xReset (); + S9xReset(); CPU.Flags = flags; - top_level->configure_widgets (); + top_level->configure_widgets(); } -void -S9xNetplaySyncClients () +void S9xNetplaySyncClients() { if (Settings.NetPlay && Settings.NetPlayServer) - S9xNPServerQueueSyncAll (); + S9xNPServerQueueSyncAll(); } -void -S9xNetplayStopServer () +void S9xNetplayStopServer() { - S9xNPStopServer (); + S9xNPStopServer(); - g_thread_join (npthread); + g_thread_join(npthread); Settings.NetPlayServer = false; gui_config->netplay_server_up = false; } -void -S9xNetplayDisconnect () +void S9xNetplayDisconnect() { if (Settings.NetPlay) { if (NetPlay.Connected) - S9xNPDisconnect (); + S9xNPDisconnect(); } if (gui_config->netplay_server_up) { - S9xNetplayStopServer (); + S9xNetplayStopServer(); } gui_config->netplay_activated = false; NetPlay.Paused = false; - top_level->configure_widgets (); + top_level->configure_widgets(); } -static gpointer -S9xNetplayServerThread (gpointer) +static gpointer S9xNetplayServerThread(gpointer) { - S9xNPStartServer (gui_config->netplay_default_port); + S9xNPStartServer(gui_config->netplay_default_port); return NULL; } -void -S9xNetplayStartServer () +void S9xNetplayStartServer() { uint32 flags; - S9xNetplayPreconnect (); + S9xNetplayPreconnect(); flags = CPU.Flags; - if (gui_config->netplay_last_rom.empty () || - !top_level->try_open_rom (gui_config->netplay_last_rom.c_str ())) + if (gui_config->netplay_last_rom.empty() || + !top_level->try_open_rom(gui_config->netplay_last_rom)) { return; } @@ -145,105 +144,103 @@ S9xNetplayStartServer () NPServer.SyncByReset = gui_config->netplay_sync_reset; NPServer.SendROMImageOnConnect = gui_config->netplay_send_rom; - npthread = g_thread_new (NULL, S9xNetplayServerThread, NULL); + npthread = g_thread_new(NULL, S9xNetplayServerThread, NULL); /* Sleep to let the server create itself */ - usleep (10000); + usleep(10000); - S9xNPConnectToServer ("127.0.0.1", - gui_config->netplay_default_port, - Memory.ROMName); + S9xNPConnectToServer("127.0.0.1", + gui_config->netplay_default_port, + Memory.ROMName); - S9xReset (); + S9xReset(); - S9xROMLoaded (); + S9xROMLoaded(); gui_config->netplay_activated = true; gui_config->netplay_server_up = true; CPU.Flags = flags; - top_level->configure_widgets (); + top_level->configure_widgets(); } -void -S9xNetplayDialogOpen () +void S9xNetplayDialogOpen() { Snes9xNetplayDialog *np_dialog; - top_level->pause_from_focus_change (); + top_level->pause_from_focus_change(); - np_dialog = new Snes9xNetplayDialog (gui_config); + np_dialog = new Snes9xNetplayDialog(gui_config); - gtk_window_set_transient_for (np_dialog->get_window (), - top_level->get_window ()); + gtk_window_set_transient_for(np_dialog->get_window(), + top_level->get_window()); - if (np_dialog->show ()) + if (np_dialog->show()) { if (!gui_config->netplay_is_server) { - S9xNetplayConnect (); + S9xNetplayConnect(); } else { - S9xNetplayStartServer (); + S9xNetplayStartServer(); } - S9xSoundStart (); + S9xSoundStart(); } delete np_dialog; - top_level->unpause_from_focus_change (); + top_level->unpause_from_focus_change(); } -int -S9xNetplaySyncSpeed () +int S9xNetplaySyncSpeed() { if (!Settings.NetPlay || !NetPlay.Connected) return 0; // Send 1st joypad's position update to server - S9xNPSendJoypadUpdate (local_joypads[0]); + S9xNPSendJoypadUpdate(local_joypads[0]); // set input from network for (int i = 0; i < NP_MAX_CLIENTS; i++) - joypads[i] = S9xNPGetJoypad (i); + joypads[i] = S9xNPGetJoypad(i); - if (!S9xNPCheckForHeartBeat ()) + if (!S9xNPCheckForHeartBeat()) { // No heartbeats already arrived, have to wait for one. - NetPlay.PendingWait4Sync = !S9xNPWaitForHeartBeatDelay (100); + NetPlay.PendingWait4Sync = !S9xNPWaitForHeartBeatDelay(100); IPPU.RenderThisFrame = true; IPPU.SkippedFrames = 0; } else { - int difference = (int) (NetPlay.MySequenceNum) - - (int) (NetPlay.ServerSequenceNum); + int difference = (int)(NetPlay.MySequenceNum) - + (int)(NetPlay.ServerSequenceNum); if (difference < 0) difference += 256; if (NetPlay.Waiting4EmulationThread) { - if ((unsigned int) difference <= (NetPlay.MaxBehindFrameCount / 2)) + if ((unsigned int)difference <= (NetPlay.MaxBehindFrameCount / 2)) { NetPlay.Waiting4EmulationThread = false; - S9xNPSendPause (false); + S9xNPSendPause(false); } } else { - if ((unsigned int) difference >= (NetPlay.MaxBehindFrameCount)) + if ((unsigned int)difference >= (NetPlay.MaxBehindFrameCount)) { NetPlay.Waiting4EmulationThread = true; - S9xNPSendPause (true); + S9xNPSendPause(true); } } - NetPlay.PendingWait4Sync = !S9xNPWaitForHeartBeatDelay (200); + NetPlay.PendingWait4Sync = !S9xNPWaitForHeartBeatDelay(200); if (IPPU.SkippedFrames < NetPlay.MaxFrameSkip) { @@ -260,27 +257,26 @@ S9xNetplaySyncSpeed () if (!NetPlay.PendingWait4Sync) { NetPlay.FrameCount++; - S9xNPStepJoypadHistory (); + S9xNPStepJoypadHistory(); } return 1; } -int -S9xNetplayPush () +int S9xNetplayPush() { if (gui_config->netplay_activated && (!Settings.NetPlay || !NetPlay.Connected)) - S9xNetplayDisconnect (); + S9xNetplayDisconnect(); if (!Settings.NetPlay) return 0; - if (NetPlay.PendingWait4Sync && !S9xNPWaitForHeartBeatDelay (100)) + if (NetPlay.PendingWait4Sync && !S9xNPWaitForHeartBeatDelay(100)) { - S9xProcessEvents (false); + S9xProcessEvents(false); - S9xSoundStop (); + S9xSoundStop(); NetPlay.Paused = true; return 1; @@ -288,36 +284,31 @@ S9xNetplayPush () NetPlay.Paused = false; - S9xSoundStart (); + S9xSoundStart(); /* Save the joypad input */ for (int i = 0; i < 8; i++) { - local_joypads[i] = MovieGetJoypad (i); + local_joypads[i] = MovieGetJoypad(i); - MovieSetJoypad (i, joypads[i]); + MovieSetJoypad(i, joypads[i]); } if (NetPlay.PendingWait4Sync) { NetPlay.PendingWait4Sync = false; NetPlay.FrameCount++; - S9xNPStepJoypadHistory (); + S9xNPStepJoypadHistory(); } return 0; } -void -S9xNetplayPop () +void S9xNetplayPop() { if (!Settings.NetPlay) return; for (int i = 0; i < 8; i++) - MovieSetJoypad (i, local_joypads[i]); + MovieSetJoypad(i, local_joypads[i]); } - - - - diff --git a/gtk/src/gtk_netplay.h b/gtk/src/gtk_netplay.h index 46426da5..65a9a0d2 100644 --- a/gtk/src/gtk_netplay.h +++ b/gtk/src/gtk_netplay.h @@ -7,11 +7,11 @@ #ifndef __GTK_NETPLAY_H #define __GTK_NETPLAY_H -void S9xNetplayDialogOpen (); -int S9xNetplayPush (); -void S9xNetplayPop (); -int S9xNetplaySyncSpeed (); -void S9xNetplaySyncClients (); -void S9xNetplayDisconnect (); +void S9xNetplayDialogOpen(); +int S9xNetplayPush(); +void S9xNetplayPop(); +int S9xNetplaySyncSpeed(); +void S9xNetplaySyncClients(); +void S9xNetplayDisconnect(); #endif /* __GTK_NETPLAY_H */ diff --git a/gtk/src/gtk_netplay_dialog.cpp b/gtk/src/gtk_netplay_dialog.cpp index 87778650..3aa8c145 100644 --- a/gtk/src/gtk_netplay_dialog.cpp +++ b/gtk/src/gtk_netplay_dialog.cpp @@ -6,133 +6,91 @@ #include "gtk_netplay_dialog.h" #include "gtk_s9x.h" -#include "gtk_file.h" -static void -event_browse_clicked (GtkButton *button, gpointer data) +Snes9xNetplayDialog::Snes9xNetplayDialog(Snes9xConfig *config) + : GtkBuilderWindow("netplay_dialog") { - char *filename; - Snes9xNetplayDialog *np_dialog = (Snes9xNetplayDialog *) data; + get_object("host_radio")->signal_toggled().connect([&] { + update_state(); + }); - filename = S9xOpenROMDialog (); + get_object("clear_netplay")->signal_clicked().connect([&] { + get_object("rom_image")->set_text(""); + }); - if (filename) - { - gtk_entry_set_text (GTK_ENTRY (np_dialog->get_widget ("rom_image")), - filename); - - g_free (filename); - } -} - -static void -event_clear_clicked (GtkButton *button, gpointer data) -{ - Snes9xNetplayDialog *np_dialog = (Snes9xNetplayDialog *) data; - - gtk_entry_set_text (GTK_ENTRY (np_dialog->get_widget ("rom_image")), ""); -} - -static void -event_server_toggled (GtkToggleButton *toggle, gpointer data) -{ - Snes9xNetplayDialog *np_dialog = (Snes9xNetplayDialog *) data; - - np_dialog->update_state (); -} - -Snes9xNetplayDialog::Snes9xNetplayDialog (Snes9xConfig *config) : - GtkBuilderWindow ("netplay_dialog") -{ - GtkBuilderWindowCallbacks callbacks[] = - { - { "server_toggled", G_CALLBACK (event_server_toggled) }, - { "browse_clicked", G_CALLBACK (event_browse_clicked) }, - { "clear_clicked", G_CALLBACK (event_clear_clicked) }, - { NULL, NULL } - }; - - signal_connect (callbacks); + get_object("browse_button")->signal_clicked().connect([&] { + auto filename = top_level->open_rom_dialog(false); + if (!filename.empty()) + get_object("rom_image")->set_text(filename); + }); this->config = config; } -void -Snes9xNetplayDialog::update_state () +Snes9xNetplayDialog::~Snes9xNetplayDialog() { - if (get_check ("host_radio")) +} + +void Snes9xNetplayDialog::update_state() +{ + if (get_check("host_radio")) { - enable_widget ("connect_box", false); - enable_widget ("default_port_box", true); - enable_widget ("sync_reset", true); - enable_widget ("send_image", true); + enable_widget("connect_box", false); + enable_widget("default_port_box", true); + enable_widget("sync_reset", true); + enable_widget("send_image", true); } else { - enable_widget ("connect_box", true); - enable_widget ("default_port_box", false); - enable_widget ("sync_reset", false); - enable_widget ("send_image", false); + enable_widget("connect_box", true); + enable_widget("default_port_box", false); + enable_widget("sync_reset", false); + enable_widget("send_image", false); } } -void -Snes9xNetplayDialog::settings_to_dialog () +void Snes9xNetplayDialog::settings_to_dialog() { - set_entry_text ("rom_image", config->netplay_last_rom.c_str ()); - set_entry_text ("ip_entry", config->netplay_last_host.c_str ()); - set_check ("sync_reset", config->netplay_sync_reset); - set_check ("send_image", config->netplay_send_rom); - set_spin ("port", config->netplay_last_port); - set_spin ("default_port", config->netplay_default_port); - set_spin ("frames_behind", config->netplay_max_frame_loss); - set_check ("connect_radio", !config->netplay_is_server); - set_check ("host_radio", config->netplay_is_server); + set_entry_text("rom_image", config->netplay_last_rom.c_str()); + set_entry_text("ip_entry", config->netplay_last_host.c_str()); + set_check("sync_reset", config->netplay_sync_reset); + set_check("send_image", config->netplay_send_rom); + set_spin("port", config->netplay_last_port); + set_spin("default_port", config->netplay_default_port); + set_spin("frames_behind", config->netplay_max_frame_loss); + set_check("connect_radio", !config->netplay_is_server); + set_check("host_radio", config->netplay_is_server); - update_state (); + update_state(); } -void -Snes9xNetplayDialog::settings_from_dialog () +void Snes9xNetplayDialog::settings_from_dialog() { - config->netplay_last_rom = get_entry_text ("rom_image"); - config->netplay_last_host = get_entry_text ("ip_entry"); - config->netplay_sync_reset = get_check ("sync_reset"); - config->netplay_send_rom = get_check ("send_image"); - config->netplay_last_port = get_spin ("port"); - config->netplay_default_port = get_spin ("default_port"); - config->netplay_max_frame_loss = get_spin ("frames_behind"); - config->netplay_is_server = get_check ("host_radio"); + config->netplay_last_rom = get_entry_text("rom_image"); + config->netplay_last_host = get_entry_text("ip_entry"); + config->netplay_sync_reset = get_check("sync_reset"); + config->netplay_send_rom = get_check("send_image"); + config->netplay_last_port = get_spin("port"); + config->netplay_default_port = get_spin("default_port"); + config->netplay_max_frame_loss = get_spin("frames_behind"); + config->netplay_is_server = get_check("host_radio"); - config->save_config_file (); + config->save_config_file(); } bool Snes9xNetplayDialog::show() { - int result; + settings_to_dialog(); - settings_to_dialog (); + auto result = Glib::RefPtr::cast_static(window)->run(); + window->hide(); - result = gtk_dialog_run (GTK_DIALOG (window)); - - gtk_widget_hide (window); - - if (result == GTK_RESPONSE_OK) + if (result == Gtk::RESPONSE_OK) { - settings_from_dialog (); - + settings_from_dialog(); return true; } - else - { - return false; - } - -} - -Snes9xNetplayDialog::~Snes9xNetplayDialog () -{ - gtk_widget_destroy (window); + return false; } diff --git a/gtk/src/gtk_netplay_dialog.h b/gtk/src/gtk_netplay_dialog.h index bca8e7a1..0f8e326f 100644 --- a/gtk/src/gtk_netplay_dialog.h +++ b/gtk/src/gtk_netplay_dialog.h @@ -12,17 +12,16 @@ class Snes9xNetplayDialog : public GtkBuilderWindow { - public: - Snes9xNetplayDialog (Snes9xConfig *config); - ~Snes9xNetplayDialog (); - bool show (); - void update_state (); + public: + Snes9xNetplayDialog(Snes9xConfig *config); + ~Snes9xNetplayDialog(); + bool show(); + void update_state(); - private: - Snes9xConfig *config; - void settings_to_dialog (); - void settings_from_dialog (); + private: + Snes9xConfig *config; + void settings_to_dialog(); + void settings_from_dialog(); }; - #endif /* __GTK_NETPLAY_DIALOG_H */ diff --git a/gtk/src/gtk_opengl_context.h b/gtk/src/gtk_opengl_context.h index 8146860b..62b1c10e 100644 --- a/gtk/src/gtk_opengl_context.h +++ b/gtk/src/gtk_opengl_context.h @@ -7,19 +7,19 @@ #ifndef __GTK_OPENGL_CONTEXT_H #define __GTK_OPENGL_CONTEXT_H -#include "gtk_2_3_compat.h" - class OpenGLContext { public: - virtual ~OpenGLContext () {}; - virtual bool attach (GtkWidget *widget) = 0; - virtual bool create_context () = 0; - virtual void resize () = 0; - virtual void swap_buffers () = 0; - virtual void swap_interval (int frames) = 0; - virtual void make_current () = 0; - virtual bool ready() { return true; }; + virtual ~OpenGLContext(){}; + virtual bool create_context() = 0; + virtual void resize() = 0; + virtual void swap_buffers() = 0; + virtual void swap_interval(int frames) = 0; + virtual void make_current() = 0; + virtual bool ready() + { + return true; + }; int x; int y; diff --git a/gtk/src/gtk_preferences.cpp b/gtk/src/gtk_preferences.cpp index 09014f96..800c1fdd 100644 --- a/gtk/src/gtk_preferences.cpp +++ b/gtk/src/gtk_preferences.cpp @@ -6,397 +6,68 @@ #include #include -#include "gtk_2_3_compat.h" +#include "gtk_compat.h" #include "gtk_preferences.h" #include "gtk_config.h" -#include "gtk_s9xcore.h" #include "gtk_control.h" #include "gtk_sound.h" #include "gtk_display.h" #include "gtk_binding.h" +#include "snes9x.h" +#include "gfx.h" +#include "display.h" + #define SAME_AS_GAME _("Same location as current game") -gboolean -snes9x_preferences_open (GtkWidget *widget, - gpointer data) +void snes9x_preferences_open(Snes9xWindow *window, Snes9xConfig *config) { - Snes9xWindow *window = ((Snes9xWindow *) data); - Snes9xConfig *config = window->config; + static Snes9xPreferences *preferences = nullptr; + + if (!preferences) + { + preferences = new Snes9xPreferences(config); + } window->pause_from_focus_change (); - Snes9xPreferences preferences (config); - gtk_window_set_transient_for (preferences.get_window (), - window->get_window ()); + preferences->window->set_transient_for(*window->window.get()); - config->set_joystick_mode (JOY_MODE_GLOBAL); + config->set_joystick_mode(JOY_MODE_GLOBAL); + preferences->show(); + window->unpause_from_focus_change(); - preferences.show (); - window->unpause_from_focus_change (); + config->set_joystick_mode(JOY_MODE_INDIVIDUAL); - config->set_joystick_mode (JOY_MODE_INDIVIDUAL); - - config->rebind_keys (); - window->update_accels (); - - return true; + config->rebind_keys(); + window->update_accelerators(); } -static void -event_sram_folder_browse (GtkButton *widget, gpointer data) +gboolean poll_joystick(gpointer data) { - ((Snes9xPreferences *) data)->browse_folder_dialog (); -} + Snes9xPreferences *window = (Snes9xPreferences *)data; + JoyEvent event; + Binding binding; + int focus; -static void -event_calibrate (GtkButton *widget, gpointer data) -{ - ((Snes9xPreferences *) data)->calibration_dialog (); -} - -static void -event_control_toggle (GtkToggleButton *widget, gpointer data) -{ - Snes9xPreferences *window = (Snes9xPreferences *) data; - static bool toggle_lock = false; - const gchar *name; - bool state; - - if (toggle_lock) + for (size_t i = 0; i < window->config->joystick.size(); i++) { - return; - } - - window->last_toggled = widget; - name = gtk_buildable_get_name (GTK_BUILDABLE (widget)); - state = gtk_toggle_button_get_active (widget); - - toggle_lock = true; - - for (int i = 0; b_links[i].button_name; i++) - { - if (strcasecmp (name, b_links[i].button_name)) - { - gtk_toggle_button_set_active ( - GTK_TOGGLE_BUTTON (window->get_widget (b_links[i].button_name)), - false); - } - } - - gtk_toggle_button_set_active (widget, state); - - toggle_lock = false; -} - -static gboolean -event_key_press (GtkWidget *widget, GdkEventKey *event, gpointer user_data) -{ - Binding key_binding; - int focus; - GtkNotebook *notebook; - GtkToggleButton *toggle; - Snes9xPreferences *window = (Snes9xPreferences *) user_data; - - if ((focus = window->get_focused_binding ()) < 0) - { - return false; /* Don't keep key for ourselves */ - } - - /* Allow modifier keys to be used if page is set to the joypad bindings. */ - notebook = GTK_NOTEBOOK (window->get_widget ("preferences_notebook")); - toggle = GTK_TOGGLE_BUTTON (window->get_widget ("use_modifiers")); - - if (gtk_notebook_get_current_page (notebook) != 4 || - !gtk_toggle_button_get_active (toggle)) - { - /* Don't allow modifiers that we track to be bound */ - if (event->keyval == GDK_Control_L || - event->keyval == GDK_Control_R || - event->keyval == GDK_Shift_L || - event->keyval == GDK_Shift_R || - event->keyval == GDK_Alt_L || - event->keyval == GDK_Alt_R) - { - return false; - } - } - - key_binding = Binding (event); - - /* Allows ESC key to clear the key binding */ - if (event->keyval == GDK_Escape) - { - if (event->state & GDK_SHIFT_MASK) - { - key_binding.clear (); - } - else - { - window->focus_next (); - return true; - } - } - - window->store_binding (b_links[focus].button_name, key_binding); - - return true; -} - -static void -event_ntsc_composite_preset (GtkButton *widget, gpointer data) -{ - Snes9xPreferences *window = (Snes9xPreferences *) data; - window->config->ntsc_setup = snes_ntsc_composite; - window->load_ntsc_settings (); -} - -static void -event_ntsc_svideo_preset (GtkButton *widget, gpointer data) -{ - Snes9xPreferences *window = (Snes9xPreferences *) data; - window->config->ntsc_setup = snes_ntsc_svideo; - window->load_ntsc_settings (); -} - -static void -event_ntsc_rgb_preset (GtkButton *widget, gpointer data) -{ - Snes9xPreferences *window = (Snes9xPreferences *) data; - window->config->ntsc_setup = snes_ntsc_rgb; - window->load_ntsc_settings (); -} - -static void -event_ntsc_monochrome_preset (GtkButton *widget, gpointer data) -{ - Snes9xPreferences *window = (Snes9xPreferences *) data; - window->config->ntsc_setup = snes_ntsc_monochrome; - window->load_ntsc_settings (); -} - - -static void -event_swap_with (GtkButton *widget, gpointer data) -{ - ((Snes9xPreferences *) data)->swap_with (); -} - -static void -event_reset_current_joypad (GtkButton *widget, gpointer data) -{ - ((Snes9xPreferences *) data)->reset_current_joypad (); -} - -static void -event_shader_select (GtkButton *widget, gpointer data) -{ -#ifdef USE_OPENGL - Snes9xPreferences *window = (Snes9xPreferences *) data; - GtkWidget *dialog; - gint result; - GtkEntry *entry; - - entry = GTK_ENTRY (window->get_widget ("fragment_shader")); - - dialog = gtk_file_chooser_dialog_new ("Select Shader File", - window->get_window (), - GTK_FILE_CHOOSER_ACTION_OPEN, - "gtk-cancel", GTK_RESPONSE_CANCEL, - "gtk-open", GTK_RESPONSE_ACCEPT, - NULL); - - if (!gui_config->last_shader_directory.empty ()) - { - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), - gui_config->last_shader_directory.c_str ()); - } - else - { - if (strlen (gtk_entry_get_text (entry))) - gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), - gtk_entry_get_text (entry)); - } - - - result = gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_hide (dialog); - - if (result == GTK_RESPONSE_ACCEPT) - { - char *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - char *folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)); - - if (folder) - gui_config->last_shader_directory = folder; - if (filename) - gtk_entry_set_text (entry, filename); - - g_free (filename); - g_free (folder); - } - - gtk_widget_destroy (dialog); -#endif -} - -static void -event_game_data_clear (GtkEntry *entry, - GtkEntryIconPosition icon_pos, - GdkEvent *event, - gpointer user_data) -{ - gtk_entry_set_text (entry, SAME_AS_GAME); -} - -static void event_binding_icon_clear(GtkEntry *entry, - GtkEntryIconPosition icon_pos, - GdkEvent *event, - gpointer user_data) -{ - auto window = (Snes9xPreferences *)user_data; - window->clear_binding(gtk_buildable_get_name(GTK_BUILDABLE(entry))); -} - -static void -event_game_data_browse (GtkButton *widget, gpointer data) -{ - Snes9xPreferences *window = (Snes9xPreferences *) data; - GtkWidget *dialog; - char *filename = NULL; - gint result; - GtkEntry *entry; - char entry_name[256]; - - strcpy (entry_name, gtk_buildable_get_name (GTK_BUILDABLE (widget))); - - sprintf (strstr (entry_name, "_browse"), "_directory"); - entry = GTK_ENTRY (window->get_widget (entry_name)); - - dialog = gtk_file_chooser_dialog_new ("Select directory", - window->get_window (), - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, - "gtk-cancel", GTK_RESPONSE_CANCEL, - "gtk-open", GTK_RESPONSE_ACCEPT, - NULL); - - if (!gui_config->last_directory.empty ()) - { - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), - gui_config->last_directory.c_str ()); - } - - if (strcmp (gtk_entry_get_text (entry), SAME_AS_GAME)) - gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), - gtk_entry_get_text (entry)); - - result = gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_hide (dialog); - - if (result == GTK_RESPONSE_ACCEPT) - { - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - if (filename != NULL) - { - gtk_entry_set_text (entry, filename); - g_free (filename); - } - } - - gtk_widget_destroy (dialog); -} - -static void -event_hw_accel_changed (GtkComboBox *widget, gpointer data) -{ - Snes9xPreferences *window = (Snes9xPreferences *) data; - GtkComboBox *combo = - GTK_COMBO_BOX (window->get_widget ("hw_accel")); - int value = gtk_combo_box_get_active (combo); - - value = window->hw_accel_value (value); - - switch (value) - { - case HWA_NONE: - gtk_widget_show (window->get_widget ("bilinear_filter")); - gtk_widget_hide (window->get_widget ("opengl_frame")); - gtk_widget_hide (window->get_widget ("xv_frame")); - break; - case HWA_OPENGL: - gtk_widget_show (window->get_widget ("bilinear_filter")); - gtk_widget_show (window->get_widget ("opengl_frame")); - gtk_widget_hide (window->get_widget ("xv_frame")); - break; - case HWA_XV: - gtk_widget_hide (window->get_widget ("bilinear_filter")); - gtk_widget_show (window->get_widget ("xv_frame")); - gtk_widget_hide (window->get_widget ("opengl_frame")); - break; - } -} - -static void -event_scale_method_changed (GtkComboBox *widget, gpointer user_data) -{ - Snes9xPreferences *window = (Snes9xPreferences *) user_data; - GtkComboBox *combo = - GTK_COMBO_BOX (window->get_widget ("scale_method_combo")); - - if (gtk_combo_box_get_active (combo) == FILTER_NTSC) - { - gtk_widget_show (window->get_widget ("ntsc_alignment")); - } - else - { - gtk_widget_hide (window->get_widget ("ntsc_alignment")); - } - - if (gtk_combo_box_get_active (combo) == FILTER_SCANLINES) - { - gtk_widget_show (window->get_widget ("scanline_alignment")); - } - else - { - gtk_widget_hide (window->get_widget ("scanline_alignment")); - } -} - -static void -event_control_combo_changed (GtkComboBox *widget, gpointer user_data) -{ - Snes9xPreferences *window = (Snes9xPreferences *) user_data; - - window->bindings_to_dialog (gtk_combo_box_get_active (widget)); -} - -static gboolean -poll_joystick (gpointer data) -{ - Snes9xPreferences *window = (Snes9xPreferences *) data; - JoyEvent event; - Binding binding; - int i, focus; - - for (i = 0; window->config->joystick[i]; i++) - { - while (window->config->joystick[i]->get_event (&event)) + while (window->config->joystick[i].get_event(&event)) { if (event.state == JOY_PRESSED) { - if ((focus = window->get_focused_binding ()) >= 0) + if ((focus = window->get_focused_binding()) >= 0) { - binding = Binding (i, - event.parameter, - window->config->joystick_threshold); + binding = Binding(i, + event.parameter, + window->config->joystick_threshold); - window->store_binding (b_links[focus].button_name, - binding); + window->store_binding(b_links[focus].button_name, + binding); - window->config->flush_joysticks (); + window->config->flush_joysticks(); return true; } - } } } @@ -404,275 +75,392 @@ poll_joystick (gpointer data) return true; } -void -Snes9xPreferences::calibration_dialog () +Snes9xPreferences::Snes9xPreferences(Snes9xConfig *config) + : GtkBuilderWindow("preferences_window") { - GtkWidget *dialog; + this->config = config; - config->joystick_register_centers (); - dialog = gtk_message_dialog_new (NULL, - (GtkDialogFlags) 0, - GTK_MESSAGE_INFO, - GTK_BUTTONS_OK, - _("Current joystick centers have been saved.")); - gtk_window_set_title (GTK_WINDOW (dialog), _("Calibration Complete")); + gtk_widget_realize(GTK_WIDGET(window->gobj())); + connect_signals(); - gtk_dialog_run (GTK_DIALOG (dialog)); - - gtk_widget_destroy (dialog); -} - -static void -event_input_rate_changed (GtkRange *range, gpointer data) -{ - char text[256]; - GtkLabel *label = GTK_LABEL (data); - double value = gtk_range_get_value (range) / 32040.0 * 60.09881389744051; - - snprintf (text, 256, "%.4f hz", value); - - gtk_label_set_text (label, text); -} - -void -event_auto_input_rate_toggled (GtkToggleButton *togglebutton, gpointer data) -{ - Snes9xPreferences *preferences = (Snes9xPreferences *) data; - - if (gtk_toggle_button_get_active (togglebutton)) + for (int i = 0; b_links[i].button_name; i++) { - preferences->set_slider("sound_input_rate", top_level->get_auto_input_rate ()); - gtk_widget_set_sensitive (preferences->get_widget("sound_input_rate"), false); + const BindingLink &link = b_links[i]; + auto entry = get_object(link.button_name); + entry->set_icon_from_icon_name("edit-clear", Gtk::ENTRY_ICON_SECONDARY); + entry->set_icon_activatable(true, Gtk::ENTRY_ICON_SECONDARY); + entry->signal_icon_release().connect([i, this](Gtk::EntryIconPosition pos, const GdkEventButton *) { + clear_binding(b_links[i].button_name); + }); + } + + #ifdef GDK_WINDOWING_X11 + if (config->allow_xrandr) + { + char size_string[256]; + + for (int i = 0; i < config->xrr_screen_resources->nmode; i++) + { + XRRModeInfo *m = &config->xrr_screen_resources->modes[i]; + unsigned long dotClock = m->dotClock; + if (m->modeFlags & RR_ClockDivideBy2) + dotClock /= 2; + if (m->modeFlags & RR_DoubleScan) + dotClock /= 2; + if (m->modeFlags & RR_DoubleClock) + dotClock *= 2; + + snprintf(size_string, + 256, + "%dx%d @ %.3fHz", + m->width, + m->height, + (double)dotClock / m->hTotal / m->vTotal); + + combo_box_append("resolution_combo", size_string); + } + + if (config->xrr_index > config->xrr_screen_resources->nmode) + config->xrr_index = 0; } else +#endif { - gtk_widget_set_sensitive (preferences->get_widget("sound_input_rate"), true); + show_widget("resolution_box", false); + } + +#ifdef USE_HQ2X + combo_box_append("scale_method_combo", _("HQ2x")); + combo_box_append("scale_method_combo", _("HQ3x")); + combo_box_append("scale_method_combo", _("HQ4x")); +#endif + +#ifdef USE_XBRZ + combo_box_append("scale_method_combo", _("2xBRZ")); + combo_box_append("scale_method_combo", _("3xBRZ")); + combo_box_append("scale_method_combo", _("4xBRZ")); +#endif + + combo_box_append("hw_accel", _("None - Use software scaler")); + + if (config->allow_opengl) + combo_box_append("hw_accel", + _("OpenGL - Use 3D graphics hardware")); + + if (config->allow_xv) + combo_box_append("hw_accel", + _("XVideo - Use hardware video blitter")); + +#ifdef USE_PORTAUDIO + combo_box_append("sound_driver", _("PortAudio")); +#endif +#ifdef USE_OSS + combo_box_append("sound_driver", _("Open Sound System")); +#endif + combo_box_append("sound_driver", _("SDL")); +#ifdef USE_ALSA + combo_box_append("sound_driver", _("ALSA")); +#endif +#ifdef USE_PULSEAUDIO + combo_box_append("sound_driver", _("PulseAudio")); +#endif +} + +Snes9xPreferences::~Snes9xPreferences () +{ +} + +void Snes9xPreferences::connect_signals() +{ + window->signal_key_press_event().connect(sigc::mem_fun(*this, &Snes9xPreferences::key_pressed), false); + + get_object("control_combo")->signal_changed().connect([&] { + bindings_to_dialog(get_object("control_combo")->get_active_row_number()); + }); + get_object("scale_method_combo")->signal_changed().connect([&] { + int id = get_combo("scale_method_combo"); + show_widget("ntsc_alignment", id == FILTER_NTSC); + show_widget("scanline_alignment", id == FILTER_SCANLINES); + }); + + get_object("hw_accel")->signal_changed().connect([&] { + int id = get_combo("hw_accel"); + show_widget("bilinear_filter", id != HWA_XV); + show_widget("opengl_frame", id == HWA_OPENGL); + show_widget("xv_frame", id == HWA_XV); + }); + + get_object("reset_current_joypad")->signal_pressed().connect(sigc::mem_fun(*this, &Snes9xPreferences::reset_current_joypad)); + get_object("swap_with")->signal_pressed().connect(sigc::mem_fun(*this, &Snes9xPreferences::swap_with)); + get_object("ntsc_composite_preset")->signal_pressed().connect([&] { + config->ntsc_setup = snes_ntsc_composite; + load_ntsc_settings(); + }); + get_object("ntsc_svideo_preset")->signal_pressed().connect([&] { + config->ntsc_setup = snes_ntsc_svideo; + load_ntsc_settings(); + }); + get_object("ntsc_rgb_preset")->signal_pressed().connect([&] { + config->ntsc_setup = snes_ntsc_rgb; + load_ntsc_settings(); + }); + + get_object("ntsc_monochrome_preset")->signal_pressed().connect([&] { + config->ntsc_setup = snes_ntsc_monochrome; + load_ntsc_settings(); + }); + + get_object("fragment_shader_button")->signal_pressed().connect(sigc::mem_fun(*this, &Snes9xPreferences::shader_select)); + get_object("calibrate_button")->signal_pressed().connect(sigc::mem_fun(*this, &Snes9xPreferences::calibration_dialog)); + get_object("sound_input_rate")->signal_value_changed().connect(sigc::mem_fun(*this, &Snes9xPreferences::input_rate_changed)); + get_object("about_button")->signal_clicked().connect(sigc::mem_fun(*this, &Snes9xPreferences::about_dialog)); + get_object("auto_input_rate")->signal_toggled().connect([&] { + auto toggle_button = get_object("auto_input_rate"); + enable_widget("sound_input_rate", toggle_button->get_active()); + if (toggle_button->get_active()) + set_slider("sound_input_rate", top_level->get_auto_input_rate()); + }); + + std::array browse_buttons = { "sram", "savestate", "cheat", "patch", "export" }; + for (auto &name : browse_buttons) + { + get_object((name + "_browse").c_str())->signal_clicked().connect([&, name] { + game_data_browse(name); + }); + + auto entry = get_object((name + "_directory").c_str()); + entry->set_icon_activatable(true, Gtk::ENTRY_ICON_SECONDARY); + entry->signal_icon_release().connect([&, name](Gtk::EntryIconPosition pos, const GdkEventButton *) { + get_object((name + "_directory").c_str())->set_text(SAME_AS_GAME); + }); } } -static void -event_about_clicked (GtkButton *widget, gpointer data) +void Snes9xPreferences::about_dialog() { std::string version_string; - GtkBuilderWindow *about_dialog = new GtkBuilderWindow ("about_dialog"); - Snes9xPreferences *preferences = (Snes9xPreferences *) data; + GtkBuilderWindow about_dialog("about_dialog"); ((version_string += _("Snes9x version: ")) += VERSION) += ", "; ((version_string += _("GTK+ port version: ")) += SNES9X_GTK_VERSION) += "\n"; (version_string += SNES9X_GTK_AUTHORS) += "\n"; (version_string += _("English localization by Brandon Wright")) += "\n"; - GtkLabel *version_string_label = GTK_LABEL (about_dialog->get_widget ("version_string_label")); - gtk_label_set_label (version_string_label, version_string.c_str ()); - gtk_label_set_justify (version_string_label, GTK_JUSTIFY_LEFT); + auto label = get_object("version_string_label"); + label->set_label(version_string); + label->set_justify(Gtk::JUSTIFY_LEFT); + about_dialog.show_widget("preferences_splash", false); - gtk_widget_hide (about_dialog->get_widget ("preferences_splash")); + auto provider = Gtk::CssProvider::create(); + provider->load_from_data("textview {" + " font-family: \"monospace\";" + " font-size: 8pt;" + "}"); + get_object("about_text_view")->reset_style(); + get_object("about_text_view")->get_style_context()->add_provider(provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); -#if GTK_MAJOR_VERSION >= 3 - GtkCssProvider *provider; - GtkStyleContext *context; - - provider = gtk_css_provider_new (); - gtk_css_provider_load_from_data (provider, - "textview {" - " font-family: \"monospace\";" - " font-size: 8pt;" - "}", - -1, - NULL); - context = gtk_widget_get_style_context (about_dialog->get_widget ("about_text_view")); - gtk_style_context_add_provider (context, - GTK_STYLE_PROVIDER (provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); -#else - PangoFontDescription *monospace; - - monospace = pango_font_description_from_string ("Monospace 7"); - gtk_widget_modify_font (about_dialog->get_widget ("about_text_view"), - monospace); - pango_font_description_free (monospace); -#endif - - - gtk_window_set_transient_for (about_dialog->get_window (), - preferences->get_window ()); - - gtk_dialog_run (GTK_DIALOG (about_dialog->get_window ())); - - delete about_dialog; + about_dialog.window->set_transient_for(*window.get()); + about_dialog.window->set_modal(); + Glib::RefPtr::cast_static(about_dialog.window)->run(); + about_dialog.window->hide(); } -Snes9xPreferences::Snes9xPreferences (Snes9xConfig *config) : - GtkBuilderWindow ("preferences_window") +void Snes9xPreferences::game_data_browse(std::string folder) { - GtkBuilderWindowCallbacks callbacks[] = + auto entry = get_object((folder + "_directory").c_str()); + auto dialog = Gtk::FileChooserDialog(*window.get(), _("Select directory"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER); + dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); + dialog.add_button(Gtk::StockID("gtk-open"), Gtk::RESPONSE_ACCEPT); + + + if (!config->last_directory.empty()) + dialog.set_current_folder(config->last_directory); + + if (entry->get_text().compare(SAME_AS_GAME) != 0) + dialog.set_filename(entry->get_text()); + + auto result = dialog.run(); + dialog.hide(); + + if (result == Gtk::RESPONSE_ACCEPT) + entry->set_text(dialog.get_filename()); +} + +void Snes9xPreferences::input_rate_changed() +{ + double value = get_object("sound_input_rate")->get_value(); + value = value / 32040.0 * 60.09881389744051; + char text[256]; + snprintf(text, 256, "%.4f Hz", value); + get_object("relative_video_rate")->set_label(text); +} + +bool Snes9xPreferences::key_pressed(GdkEventKey *event) +{ + int focus = get_focused_binding(); + + if (focus < 0) + return false; // Pass event on to Gtk + + // Disallow modifier keys if page isn't set to the joypad bindings. + if (get_object("preferences_notebook")->get_current_page() != 4 || + !get_object("use_modifiers")->get_active()) { - { "control_toggle", G_CALLBACK (event_control_toggle) }, - { "on_key_press", G_CALLBACK (event_key_press) }, - { "control_combo_changed", G_CALLBACK (event_control_combo_changed) }, - { "sram_folder_browse", G_CALLBACK (event_sram_folder_browse) }, - { "scale_method_changed", G_CALLBACK (event_scale_method_changed) }, - { "hw_accel_changed", G_CALLBACK (event_hw_accel_changed) }, - { "reset_current_joypad", G_CALLBACK (event_reset_current_joypad) }, - { "swap_with", G_CALLBACK (event_swap_with) }, - { "ntsc_composite_preset", G_CALLBACK (event_ntsc_composite_preset) }, - { "ntsc_svideo_preset", G_CALLBACK (event_ntsc_svideo_preset) }, - { "ntsc_rgb_preset", G_CALLBACK (event_ntsc_rgb_preset) }, - { "ntsc_monochrome_preset", G_CALLBACK (event_ntsc_monochrome_preset) }, - { "shader_select", G_CALLBACK (event_shader_select) }, - { "game_data_browse", G_CALLBACK (event_game_data_browse) }, - { "game_data_clear", G_CALLBACK (event_game_data_clear) }, - { "about_clicked", G_CALLBACK (event_about_clicked) }, - { "auto_input_rate_toggled", G_CALLBACK (event_auto_input_rate_toggled) }, - { "calibrate", G_CALLBACK (event_calibrate) }, - { NULL, NULL } - }; - - last_toggled = NULL; - this->config = config; - - mode_indices = NULL; - - gtk_widget_realize (window); - - signal_connect (callbacks); - - g_signal_connect_data (get_widget ("sound_input_rate"), - "value-changed", - G_CALLBACK (event_input_rate_changed), - get_widget ("relative_video_rate"), - NULL, - (GConnectFlags) 0); - - for (int i = 0; ; i++) - { - const BindingLink &link = b_links[i]; - if (!link.button_name) - break; - - GtkWidget *entry = get_widget(link.button_name); - gtk_entry_set_icon_from_icon_name(GTK_ENTRY(entry), - GTK_ENTRY_ICON_SECONDARY, - "edit-clear"); - gtk_entry_set_icon_activatable(GTK_ENTRY(entry), - GTK_ENTRY_ICON_SECONDARY, - true); - g_signal_connect_data((gpointer)entry, - "icon-release", - G_CALLBACK(event_binding_icon_clear), - (gpointer)this, - NULL, - (GConnectFlags)0); + // Don't allow modifiers that we track to be bound + if (event->keyval == GDK_Control_L || + event->keyval == GDK_Control_R || + event->keyval == GDK_Shift_L || + event->keyval == GDK_Shift_R || + event->keyval == GDK_Alt_L || + event->keyval == GDK_Alt_R) + { + return false; + } } + + Binding key_binding = Binding(event); + + // Allows ESC key to clear the key binding + if (event->keyval == GDK_Escape) + { + if (event->state & GDK_SHIFT_MASK) + { + key_binding.clear(); + } + else + { + focus_next(); + return true; + } + } + + store_binding(b_links[focus].button_name, key_binding); + + return true; } -Snes9xPreferences::~Snes9xPreferences () +void Snes9xPreferences::shader_select() { - delete[] mode_indices; +#ifdef USE_OPENGL + auto entry = get_object("fragment_shader"); + + auto dialog = Gtk::FileChooserDialog(*window.get(), _("Select Shader File")); + dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); + dialog.add_button(Gtk::StockID("gtk-open"), Gtk::RESPONSE_ACCEPT); + if (!config->last_shader_directory.empty()) + dialog.set_current_folder(config->last_shader_directory); + else + dialog.set_filename(entry->get_text()); + + auto result = dialog.run(); + dialog.hide(); + + if (result == Gtk::RESPONSE_ACCEPT) + { + auto folder = dialog.get_current_folder(); + auto filename = dialog.get_filename(); + + if (!folder.empty()) + config->last_shader_directory = folder; + if (!filename.empty()) + entry->set_text(filename); + } +#endif } -void -Snes9xPreferences::load_ntsc_settings () +void Snes9xPreferences::load_ntsc_settings() { - set_slider ("ntsc_artifacts", config->ntsc_setup.artifacts); - set_slider ("ntsc_bleed", config->ntsc_setup.bleed); - set_slider ("ntsc_brightness", config->ntsc_setup.brightness); - set_slider ("ntsc_contrast", config->ntsc_setup.contrast); - set_slider ("ntsc_fringing", config->ntsc_setup.fringing); - set_slider ("ntsc_gamma", config->ntsc_setup.gamma); - set_slider ("ntsc_hue", config->ntsc_setup.hue); - set_check ("ntsc_merge_fields", config->ntsc_setup.merge_fields); - set_slider ("ntsc_resolution", config->ntsc_setup.resolution); - set_slider ("ntsc_saturation", config->ntsc_setup.saturation); - set_slider ("ntsc_sharpness", config->ntsc_setup.sharpness); + set_slider("ntsc_artifacts", config->ntsc_setup.artifacts); + set_slider("ntsc_bleed", config->ntsc_setup.bleed); + set_slider("ntsc_brightness", config->ntsc_setup.brightness); + set_slider("ntsc_contrast", config->ntsc_setup.contrast); + set_slider("ntsc_fringing", config->ntsc_setup.fringing); + set_slider("ntsc_gamma", config->ntsc_setup.gamma); + set_slider("ntsc_hue", config->ntsc_setup.hue); + set_check("ntsc_merge_fields", config->ntsc_setup.merge_fields); + set_slider("ntsc_resolution", config->ntsc_setup.resolution); + set_slider("ntsc_saturation", config->ntsc_setup.saturation); + set_slider("ntsc_sharpness", config->ntsc_setup.sharpness); } -void -Snes9xPreferences::store_ntsc_settings () +void Snes9xPreferences::store_ntsc_settings() { - config->ntsc_setup.artifacts = get_slider ("ntsc_artifacts"); - config->ntsc_setup.bleed = get_slider ("ntsc_bleed"); - config->ntsc_setup.brightness = get_slider ("ntsc_brightness"); - config->ntsc_setup.contrast = get_slider ("ntsc_contrast"); - config->ntsc_setup.fringing = get_slider ("ntsc_fringing"); - config->ntsc_setup.gamma = get_slider ("ntsc_gamma"); - config->ntsc_setup.hue = get_slider ("ntsc_hue"); - config->ntsc_setup.merge_fields = get_check ("ntsc_merge_fields"); - config->ntsc_setup.resolution = get_slider ("ntsc_resolution"); - config->ntsc_setup.saturation = get_slider ("ntsc_saturation"); - config->ntsc_setup.sharpness = get_slider ("ntsc_sharpness"); + config->ntsc_setup.artifacts = get_slider("ntsc_artifacts"); + config->ntsc_setup.bleed = get_slider("ntsc_bleed"); + config->ntsc_setup.brightness = get_slider("ntsc_brightness"); + config->ntsc_setup.contrast = get_slider("ntsc_contrast"); + config->ntsc_setup.fringing = get_slider("ntsc_fringing"); + config->ntsc_setup.gamma = get_slider("ntsc_gamma"); + config->ntsc_setup.hue = get_slider("ntsc_hue"); + config->ntsc_setup.merge_fields = get_check("ntsc_merge_fields"); + config->ntsc_setup.resolution = get_slider("ntsc_resolution"); + config->ntsc_setup.saturation = get_slider("ntsc_saturation"); + config->ntsc_setup.sharpness = get_slider("ntsc_sharpness"); } -void -Snes9xPreferences::move_settings_to_dialog () +void Snes9xPreferences::move_settings_to_dialog() { - set_check ("full_screen_on_open", config->full_screen_on_open); - set_check ("show_time", Settings.DisplayTime); - set_check ("show_frame_rate", Settings.DisplayFrameRate); - set_check ("show_pressed_keys", Settings.DisplayPressedKeys); - set_check ("change_display_resolution", config->change_display_resolution); - set_check ("scale_to_fit", config->scale_to_fit); - set_check ("overscan", config->overscan); - set_check ("multithreading", config->multithreading); - set_combo ("hires_effect", config->hires_effect); - set_check ("maintain_aspect_ratio", config->maintain_aspect_ratio); - set_combo ("aspect_ratio", config->aspect_ratio); - if (config->sram_directory.empty ()) - set_entry_text ("sram_directory", SAME_AS_GAME); + set_check("full_screen_on_open", config->full_screen_on_open); + set_check("show_time", Settings.DisplayTime); + set_check("show_frame_rate", Settings.DisplayFrameRate); + set_check("show_pressed_keys", Settings.DisplayPressedKeys); + set_check("change_display_resolution", config->change_display_resolution); + set_check("scale_to_fit", config->scale_to_fit); + set_check("overscan", config->overscan); + set_check("multithreading", config->multithreading); + set_combo("hires_effect", config->hires_effect); + set_check("maintain_aspect_ratio", config->maintain_aspect_ratio); + set_combo("aspect_ratio", config->aspect_ratio); + if (config->sram_directory.empty()) + set_entry_text("sram_directory", SAME_AS_GAME); else - set_entry_text ("sram_directory", config->sram_directory.c_str ()); - if (config->savestate_directory.empty ()) - set_entry_text ("savestate_directory", SAME_AS_GAME); + set_entry_text("sram_directory", config->sram_directory.c_str()); + if (config->savestate_directory.empty()) + set_entry_text("savestate_directory", SAME_AS_GAME); else - set_entry_text ("savestate_directory", config->savestate_directory.c_str ()); - if (config->patch_directory.empty ()) - set_entry_text ("patch_directory", SAME_AS_GAME); + set_entry_text("savestate_directory", config->savestate_directory.c_str()); + if (config->patch_directory.empty()) + set_entry_text("patch_directory", SAME_AS_GAME); else - set_entry_text ("patch_directory", config->patch_directory.c_str ()); - if (config->cheat_directory.empty ()) - set_entry_text ("cheat_directory", SAME_AS_GAME); + set_entry_text("patch_directory", config->patch_directory.c_str()); + if (config->cheat_directory.empty()) + set_entry_text("cheat_directory", SAME_AS_GAME); else - set_entry_text ("cheat_directory", config->cheat_directory.c_str ()); - if (config->export_directory.empty ()) - set_entry_text ("export_directory", SAME_AS_GAME); + set_entry_text("cheat_directory", config->cheat_directory.c_str()); + if (config->export_directory.empty()) + set_entry_text("export_directory", SAME_AS_GAME); else - set_entry_text ("export_directory", config->export_directory.c_str ()); + set_entry_text("export_directory", config->export_directory.c_str()); - set_combo ("resolution_combo", config->xrr_index); - set_combo ("scale_method_combo", config->scale_method); - set_entry_value ("save_sram_after_sec", Settings.AutoSaveDelay); - set_check ("allow_invalid_vram_access", !Settings.BlockInvalidVRAMAccessMaster); - set_check ("upanddown", Settings.UpAndDown); - set_combo ("default_esc_behavior", config->default_esc_behavior); - set_check ("prevent_screensaver", config->prevent_screensaver); - set_check ("force_inverted_byte_order", config->force_inverted_byte_order); - set_combo ("playback_combo", 7 - config->sound_playback_rate); - set_combo ("hw_accel", combo_value (config->hw_accel)); - set_check ("pause_emulation_on_switch", config->pause_emulation_on_switch); - set_spin ("num_threads", config->num_threads); - set_check ("mute_sound_check", config->mute_sound); - set_check ("mute_sound_turbo_check", config->mute_sound_turbo); - set_slider ("sound_input_rate", config->sound_input_rate); - if (top_level->get_auto_input_rate () == 0) + set_combo("resolution_combo", config->xrr_index); + set_combo("scale_method_combo", config->scale_method); + set_entry_value("save_sram_after_sec", Settings.AutoSaveDelay); + set_check("allow_invalid_vram_access", !Settings.BlockInvalidVRAMAccessMaster); + set_check("upanddown", Settings.UpAndDown); + set_combo("default_esc_behavior", config->default_esc_behavior); + set_check("prevent_screensaver", config->prevent_screensaver); + set_check("force_inverted_byte_order", config->force_inverted_byte_order); + set_combo("playback_combo", 7 - config->sound_playback_rate); + set_combo("hw_accel", combo_value (config->hw_accel)); + set_check("pause_emulation_on_switch", config->pause_emulation_on_switch); + set_spin ("num_threads", config->num_threads); + set_check("mute_sound_check", config->mute_sound); + set_check("mute_sound_turbo_check", config->mute_sound_turbo); + set_slider("sound_input_rate", config->sound_input_rate); + if (top_level->get_auto_input_rate() == 0) { config->auto_input_rate = 0; - gtk_widget_set_sensitive (get_widget ("auto_input_rate"), false); + enable_widget("auto_input_rate", false); } set_check ("auto_input_rate", config->auto_input_rate); - gtk_widget_set_sensitive (get_widget("sound_input_rate"), - config->auto_input_rate ? false : true); + enable_widget("sound_input_rate", config->auto_input_rate ? false : true); set_spin ("sound_buffer_size", config->sound_buffer_size); - set_check ("dynamic_rate_control", Settings.DynamicRateControl); set_spin ("dynamic_rate_limit", Settings.DynamicRateLimit / 1000.0); set_spin ("rewind_buffer_size", config->rewind_buffer_size); set_spin ("rewind_granularity", config->rewind_granularity); set_spin ("superfx_multiplier", Settings.SuperFXClockMultiplier); set_combo ("splash_background", config->splash_image); - -#if GTK_MAJOR_VERSION < 3 - gtk_widget_hide (get_widget ("force_enable_icons")); -#endif set_check ("force_enable_icons", config->enable_icons); int num_sound_drivers = 0; @@ -695,25 +483,10 @@ Snes9xPreferences::move_settings_to_dialog () set_combo ("sound_driver", config->sound_driver); - if (config->scale_method == FILTER_NTSC) - { - gtk_widget_show (get_widget ("ntsc_alignment")); - } - else - { - gtk_widget_hide (get_widget ("ntsc_alignment")); - } + show_widget("ntsc_alignment", config->scale_method == FILTER_NTSC); + show_widget("scanline_alignment", config->scale_method == FILTER_SCANLINES); - if (config->scale_method == FILTER_SCANLINES) - { - gtk_widget_show (get_widget ("scanline_alignment")); - } - else - { - gtk_widget_hide (get_widget ("scanline_alignment")); - } - - load_ntsc_settings (); + load_ntsc_settings(); set_combo ("ntsc_scanline_intensity", config->ntsc_scanline_intensity); set_combo ("scanline_filter_intensity", config->scanline_filter_intensity); @@ -735,135 +508,130 @@ Snes9xPreferences::move_settings_to_dialog () /* Control bindings */ pad = config->pad; shortcut = config->shortcut; - bindings_to_dialog (0); + bindings_to_dialog(0); - set_combo ("joypad_to_swap_with", 0); + set_combo("joypad_to_swap_with", 0); #ifdef ALLOW_CPU_OVERCLOCK - gtk_widget_show (get_widget ("cpu_overclock")); - gtk_widget_show (get_widget ("remove_sprite_limit")); - gtk_widget_show (get_widget ("allow_invalid_vram_access")); - gtk_widget_show (get_widget ("echo_buffer_hack")); - gtk_widget_show (get_widget ("soundfilterhbox")); + show_widget("cpu_overclock", true); + show_widget("remove_sprite_limit", true); + show_widget("allow_invalid_vram_access", true); + show_widget("echo_buffer_hack", true); + show_widget("soundfilterhbox", true); - set_check ("cpu_overclock", Settings.OneClockCycle != 6); - set_check ("remove_sprite_limit", Settings.MaxSpriteTilesPerLine != 34); - set_check ("echo_buffer_hack", Settings.SeparateEchoBuffer); - set_combo ("sound_filter", Settings.InterpolationMethod); + set_check("cpu_overclock", Settings.OneClockCycle != 6); + set_check("remove_sprite_limit", Settings.MaxSpriteTilesPerLine != 34); + set_check("echo_buffer_hack", Settings.SeparateEchoBuffer); + set_combo("sound_filter", Settings.InterpolationMethod); #endif } -void -Snes9xPreferences::get_settings_from_dialog () +void Snes9xPreferences::get_settings_from_dialog() { bool sound_needs_restart = false; bool gfx_needs_restart = false; bool sound_sync = false; - Settings.SkipFrames = get_combo ("frameskip_combo"); + Settings.SkipFrames = get_combo("frameskip_combo"); if (Settings.SkipFrames == THROTTLE_SOUND_SYNC) sound_sync = true; - if ((config->sound_driver != get_combo ("sound_driver")) || - (config->mute_sound != get_check ("mute_sound_check")) || - (config->sound_buffer_size != (int) get_spin ("sound_buffer_size")) || - (config->sound_playback_rate != (7 - (get_combo ("playback_combo")))) || - (config->sound_input_rate != get_slider ("sound_input_rate")) || - (config->auto_input_rate != get_check ("auto_input_rate")) || + if ((config->sound_driver != get_combo("sound_driver")) || + (config->mute_sound != get_check("mute_sound_check")) || + (config->sound_buffer_size != (int) get_spin("sound_buffer_size")) || + (config->sound_playback_rate != (7 - (get_combo("playback_combo")))) || + (config->sound_input_rate != get_slider("sound_input_rate")) || + (config->auto_input_rate != get_check("auto_input_rate")) || (Settings.SoundSync != sound_sync) || - (Settings.DynamicRateControl != get_check ("dynamic_rate_control"))) + (Settings.DynamicRateControl != get_check("dynamic_rate_control"))) { sound_needs_restart = true; } - if ((config->change_display_resolution != get_check ("change_display_resolution") || + if ((config->change_display_resolution != get_check("change_display_resolution") || (config->change_display_resolution && - (config->xrr_index != get_combo ("resolution_combo")))) && + (config->xrr_index != get_combo("resolution_combo")))) && config->fullscreen) { top_level->leave_fullscreen_mode (); - config->xrr_index = get_combo ("resolution_combo"); - config->change_display_resolution = get_check ("change_display_resolution"); + config->xrr_index = get_combo("resolution_combo"); + config->change_display_resolution = get_check("change_display_resolution"); top_level->enter_fullscreen_mode (); } else { - config->xrr_index = get_combo ("resolution_combo"); + config->xrr_index = get_combo("resolution_combo"); } - config->change_display_resolution = get_check ("change_display_resolution"); + config->change_display_resolution = get_check("change_display_resolution"); - if (config->splash_image != get_combo ("splash_background")) + if (config->splash_image != get_combo("splash_background")) { - config->splash_image = get_combo ("splash_background"); + config->splash_image = get_combo("splash_background"); if (!config->rom_loaded) { top_level->last_width = top_level->last_height = -1; - top_level->expose(); + top_level->refresh(); } } - config->splash_image = get_combo ("splash_background"); + config->splash_image = get_combo("splash_background"); - if (config->multithreading != get_check ("multithreading")) + if (config->multithreading != get_check("multithreading")) gfx_needs_restart = true; - if (config->hw_accel != hw_accel_value (get_combo ("hw_accel"))) + if (config->hw_accel != hw_accel_value (get_combo("hw_accel"))) gfx_needs_restart = true; - if (config->force_inverted_byte_order != get_check ("force_inverted_byte_order")) + if (config->force_inverted_byte_order != get_check("force_inverted_byte_order")) gfx_needs_restart = true; - config->enable_icons = get_check ("force_enable_icons"); -#if GTK_MAJOR_VERSION >= 3 - auto settings = gtk_settings_get_default(); - g_object_set(settings, - "gtk-menu-images", gui_config->enable_icons, - "gtk_button_images", gui_config->enable_icons, - NULL); -#endif + config->enable_icons = get_check("force_enable_icons"); + auto settings = Gtk::Settings::get_default(); + settings->set_property("gtk-menu-images", gui_config->enable_icons); + settings->set_property("gtk-button-images", gui_config->enable_icons); - config->full_screen_on_open = get_check ("full_screen_on_open"); - Settings.DisplayTime = get_check ("show_time"); - Settings.DisplayFrameRate = get_check ("show_frame_rate"); - Settings.DisplayPressedKeys = get_check ("show_pressed_keys"); - config->scale_to_fit = get_check ("scale_to_fit"); - config->overscan = get_check ("overscan"); - config->maintain_aspect_ratio = get_check ("maintain_aspect_ratio"); - config->aspect_ratio = get_combo ("aspect_ratio"); - config->scale_method = get_combo ("scale_method_combo"); - config->hires_effect = get_combo ("hires_effect"); - config->force_inverted_byte_order = get_check ("force_inverted_byte_order"); - Settings.AutoSaveDelay = get_entry_value ("save_sram_after_sec"); - config->multithreading = get_check ("multithreading"); - config->pause_emulation_on_switch = get_check ("pause_emulation_on_switch"); - Settings.BlockInvalidVRAMAccessMaster = !get_check ("allow_invalid_vram_access"); - Settings.UpAndDown = get_check ("upanddown"); - Settings.SuperFXClockMultiplier = get_spin ("superfx_multiplier"); - config->sound_driver = get_combo ("sound_driver"); - config->sound_playback_rate = 7 - (get_combo ("playback_combo")); - config->sound_buffer_size = get_spin ("sound_buffer_size"); - config->sound_input_rate = get_slider ("sound_input_rate"); - config->auto_input_rate = get_check ("auto_input_rate"); + config->full_screen_on_open = get_check("full_screen_on_open"); + Settings.DisplayTime = get_check("show_time"); + Settings.DisplayFrameRate = get_check("show_frame_rate"); + Settings.DisplayPressedKeys = get_check("show_pressed_keys"); + config->scale_to_fit = get_check("scale_to_fit"); + config->overscan = get_check("overscan"); + config->maintain_aspect_ratio = get_check("maintain_aspect_ratio"); + config->aspect_ratio = get_combo("aspect_ratio"); + config->scale_method = get_combo("scale_method_combo"); + config->hires_effect = get_combo("hires_effect"); + config->force_inverted_byte_order = get_check("force_inverted_byte_order"); + Settings.AutoSaveDelay = get_entry_value("save_sram_after_sec"); + config->multithreading = get_check("multithreading"); + config->pause_emulation_on_switch = get_check("pause_emulation_on_switch"); + Settings.BlockInvalidVRAMAccessMaster = !get_check("allow_invalid_vram_access"); + Settings.UpAndDown = get_check("upanddown"); + Settings.SuperFXClockMultiplier = get_spin("superfx_multiplier"); + config->sound_driver = get_combo("sound_driver"); + config->sound_playback_rate = 7 - (get_combo("playback_combo")); + config->sound_buffer_size = get_spin("sound_buffer_size"); + config->sound_input_rate = get_slider("sound_input_rate"); + config->auto_input_rate = get_check("auto_input_rate"); Settings.SoundSync = sound_sync; - config->mute_sound = get_check ("mute_sound_check"); - config->mute_sound_turbo = get_check ("mute_sound_turbo_check"); - Settings.DynamicRateControl = get_check ("dynamic_rate_control"); - Settings.DynamicRateLimit = (uint32) (get_spin ("dynamic_rate_limit") * 1000); - - store_ntsc_settings (); - config->ntsc_scanline_intensity = get_combo ("ntsc_scanline_intensity"); - config->scanline_filter_intensity = get_combo ("scanline_filter_intensity"); - config->hw_accel = hw_accel_value (get_combo ("hw_accel")); - Settings.BilinearFilter = get_check ("bilinear_filter"); - config->num_threads = get_spin ("num_threads"); - config->default_esc_behavior = get_combo ("default_esc_behavior"); - config->prevent_screensaver = get_check ("prevent_screensaver"); - config->rewind_buffer_size = get_spin ("rewind_buffer_size"); - config->rewind_granularity = get_spin ("rewind_granularity"); + config->mute_sound = get_check("mute_sound_check"); + config->mute_sound_turbo = get_check("mute_sound_turbo_check"); + Settings.DynamicRateControl = get_check("dynamic_rate_control"); + Settings.DynamicRateLimit = (uint32) (get_spin("dynamic_rate_limit") * 1000); + store_ntsc_settings(); + config->ntsc_scanline_intensity = get_combo("ntsc_scanline_intensity"); + config->scanline_filter_intensity = get_combo("scanline_filter_intensity"); + config->hw_accel = hw_accel_value(get_combo("hw_accel")); + Settings.BilinearFilter = get_check("bilinear_filter"); + config->num_threads = get_spin("num_threads"); + config->default_esc_behavior = get_combo("default_esc_behavior"); + config->prevent_screensaver = get_check("prevent_screensaver"); + config->rewind_buffer_size = get_spin("rewind_buffer_size"); + config->rewind_granularity = get_spin("rewind_granularity"); + config->joystick_threshold = get_spin("joystick_threshold"); #ifdef ALLOW_CPU_OVERCLOCK - if (get_check ("cpu_overclock")) + if (get_check("cpu_overclock")) { Settings.OneClockCycle = 4; Settings.OneSlowClockCycle = 5; @@ -876,7 +644,7 @@ Snes9xPreferences::get_settings_from_dialog () Settings.TwoClockCycles = 12; } - if (get_check ("remove_sprite_limit")) + if (get_check("remove_sprite_limit")) { Settings.MaxSpriteTilesPerLine = 128; } @@ -885,81 +653,75 @@ Snes9xPreferences::get_settings_from_dialog () Settings.MaxSpriteTilesPerLine = 34; } - Settings.SeparateEchoBuffer = get_check ("echo_buffer_hack"); - Settings.InterpolationMethod = get_combo ("sound_filter"); + Settings.SeparateEchoBuffer = get_check("echo_buffer_hack"); + Settings.InterpolationMethod = get_combo("sound_filter"); #endif - config->joystick_threshold = get_spin ("joystick_threshold"); - #ifdef USE_OPENGL - int pbo_format = get_combo ("pixel_format") == 1 ? 32 : 16; + int pbo_format = get_combo("pixel_format") == 1 ? 32 : 16; - if (config->sync_to_vblank != get_check ("sync_to_vblank") || - config->use_sync_control != get_check ("use_sync_control") || - config->npot_textures != get_check ("npot_textures") || - config->use_pbos != get_check ("use_pbos") || - config->pbo_format != pbo_format || - config->use_shaders != get_check ("use_shaders") || + if (config->sync_to_vblank != get_check("sync_to_vblank") || + config->use_sync_control != get_check("use_sync_control") || + config->npot_textures != get_check("npot_textures") || + config->use_pbos != get_check("use_pbos") || + config->pbo_format != pbo_format || + config->use_shaders != get_check("use_shaders") || (config->shader_filename.compare(get_entry_text("fragment_shader")))) { gfx_needs_restart = true; } - config->sync_to_vblank = get_check ("sync_to_vblank"); - config->use_pbos = get_check ("use_pbos"); - config->npot_textures = get_check ("npot_textures"); - config->use_shaders = get_check ("use_shaders"); - config->use_glfinish = get_check ("use_glfinish"); - config->use_sync_control = get_check ("use_sync_control"); - - config->shader_filename = get_entry_text ("fragment_shader"); - - config->pbo_format = pbo_format; + config->sync_to_vblank = get_check("sync_to_vblank"); + config->use_pbos = get_check("use_pbos"); + config->npot_textures = get_check("npot_textures"); + config->use_shaders = get_check("use_shaders"); + config->use_glfinish = get_check("use_glfinish"); + config->use_sync_control = get_check("use_sync_control"); + config->shader_filename = get_entry_text ("fragment_shader"); + config->pbo_format = pbo_format; #endif - std::string new_sram_directory = get_entry_text ("sram_directory"); - config->savestate_directory = get_entry_text ("savestate_directory"); - config->patch_directory = get_entry_text ("patch_directory"); - config->cheat_directory = get_entry_text ("cheat_directory"); - config->export_directory = get_entry_text ("export_directory"); + std::string new_sram_directory = get_entry_text("sram_directory"); + config->savestate_directory = get_entry_text("savestate_directory"); + config->patch_directory = get_entry_text("patch_directory"); + config->cheat_directory = get_entry_text("cheat_directory"); + config->export_directory = get_entry_text("export_directory"); - for (auto &i: { &new_sram_directory, - &config->savestate_directory, - &config->patch_directory, - &config->cheat_directory, - &config->export_directory }) + for (auto &i : { &new_sram_directory, + &config->savestate_directory, + &config->patch_directory, + &config->cheat_directory, + &config->export_directory }) { - if (!i->compare (SAME_AS_GAME)) - i->clear (); + if (!i->compare(SAME_AS_GAME)) + i->clear(); } - if (new_sram_directory.compare (config->sram_directory) && config->rom_loaded) + if (new_sram_directory.compare(config->sram_directory) && config->rom_loaded) { - GtkWidget *msg; - int responseid; + auto msg = Gtk::MessageDialog( + *window.get(), + _("Changing the SRAM directory with a game loaded will replace the .srm file in the selected directory with the SRAM from the running game. If this is not what you want, click 'cancel'."), + false, + Gtk::MESSAGE_WARNING, + Gtk::BUTTONS_OK_CANCEL, + true); + msg.set_title(_("Warning: Possible File Overwrite")); - msg = gtk_message_dialog_new (GTK_WINDOW (this->window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_OK_CANCEL, - _("Changing the SRAM directory with a game loaded will replace the .srm file in the selected directory with the SRAM from the running game. If this is not what you want, click 'cancel'.")); - gtk_window_set_title (GTK_WINDOW (msg), _("Warning: Possible File Overwrite")); + auto result = msg.run(); + msg.hide(); - responseid = gtk_dialog_run (GTK_DIALOG (msg)); - - if (responseid == GTK_RESPONSE_OK) + if (result == Gtk::RESPONSE_OK) { config->sram_directory = new_sram_directory; } else { if (config->sram_directory.empty ()) - set_entry_text ("sram_directory", SAME_AS_GAME); + set_entry_text("sram_directory", SAME_AS_GAME); else - set_entry_text ("sram_directory", config->sram_directory.c_str ()); + set_entry_text("sram_directory", config->sram_directory.c_str ()); } - - gtk_widget_destroy (msg); } else { @@ -971,27 +733,26 @@ Snes9xPreferences::get_settings_from_dialog () if (sound_needs_restart) { - S9xPortSoundReinit (); + S9xPortSoundReinit(); } if (gfx_needs_restart) { - S9xReinitDisplay (); + S9xReinitDisplay(); } - S9xDisplayReconfigure (); - S9xDisplayRefresh (top_level->last_width, top_level->last_height); + S9xDisplayReconfigure(); + S9xDisplayRefresh(top_level->last_width, top_level->last_height); - S9xDeinitUpdate (top_level->last_width, top_level->last_height); + S9xDeinitUpdate(top_level->last_width, top_level->last_height); - top_level->configure_widgets (); + top_level->configure_widgets(); if (config->default_esc_behavior != ESC_TOGGLE_MENUBAR) - top_level->leave_fullscreen_mode (); + top_level->leave_fullscreen_mode(); } -int -Snes9xPreferences::hw_accel_value (int combo_value) +int Snes9xPreferences::hw_accel_value(int combo_value) { if (config->allow_opengl && config->allow_xv) return combo_value; @@ -1003,8 +764,7 @@ Snes9xPreferences::hw_accel_value (int combo_value) return combo_value ? 1 : 0; } -int -Snes9xPreferences::combo_value (int hw_accel) +int Snes9xPreferences::combo_value(int hw_accel) { if (config->allow_opengl && config->allow_xv) return hw_accel; @@ -1016,173 +776,50 @@ Snes9xPreferences::combo_value (int hw_accel) return hw_accel == HWA_OPENGL ? 1 : 0; } - -void -Snes9xPreferences::browse_folder_dialog () +void Snes9xPreferences::show() { - GtkWidget *dialog; - char *filename; - gint result; + bool close_dialog; + guint source_id = -1; - dialog = gtk_file_chooser_dialog_new (_("Select Folder"), - GTK_WINDOW (this->window), - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, - "gtk-cancel", GTK_RESPONSE_CANCEL, - "gtk-open", GTK_RESPONSE_ACCEPT, - NULL); + move_settings_to_dialog(); - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), - S9xGetDirectory (HOME_DIR)); - - result = gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_hide (dialog); - - if (result == GTK_RESPONSE_ACCEPT) - { - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - - gtk_entry_set_text (GTK_ENTRY (get_widget ("custom_folder_entry")), - filename); - - g_free (filename); - } - - else - { - } - - gtk_widget_destroy (dialog); -} - -void -Snes9xPreferences::show () -{ - gint result; - GtkWidget *combo; - bool close_dialog; - guint source_id = -1; - -#ifdef GDK_WINDOWING_X11 - if (config->allow_xrandr) - { - char size_string[256]; - - combo = get_widget ("resolution_combo"); - - for (int i = 0; i < config->xrr_screen_resources->nmode; i++) - { - XRRModeInfo *m = &config->xrr_screen_resources->modes[i]; - unsigned long dotClock = m->dotClock; - if (m->modeFlags & RR_ClockDivideBy2) - dotClock /= 2; - if (m->modeFlags & RR_DoubleScan) - dotClock /= 2; - if (m->modeFlags & RR_DoubleClock) - dotClock *= 2; - - snprintf (size_string, - 256, - "%dx%d @ %.3fHz", - m->width, - m->height, - (double) dotClock / m->hTotal / m->vTotal); - - combo_box_append (GTK_COMBO_BOX (combo), size_string); - } - - if (config->xrr_index > config->xrr_screen_resources->nmode) - config->xrr_index = 0; - } - else -#endif - { - gtk_widget_hide (get_widget ("resolution_box")); - } - -#ifdef USE_HQ2X - combo = get_widget ("scale_method_combo"); - combo_box_append (GTK_COMBO_BOX (combo), _("HQ2x")); - combo_box_append (GTK_COMBO_BOX (combo), _("HQ3x")); - combo_box_append (GTK_COMBO_BOX (combo), _("HQ4x")); -#endif - -#ifdef USE_XBRZ - combo = get_widget ("scale_method_combo"); - combo_box_append (GTK_COMBO_BOX (combo), _("2xBRZ")); - combo_box_append (GTK_COMBO_BOX (combo), _("3xBRZ")); - combo_box_append (GTK_COMBO_BOX (combo), _("4xBRZ")); -#endif - - combo = get_widget ("hw_accel"); - combo_box_append (GTK_COMBO_BOX (combo), - _("None - Use software scaler")); - - if (config->allow_opengl) - combo_box_append (GTK_COMBO_BOX (combo), - _("OpenGL - Use 3D graphics hardware")); - - if (config->allow_xv) - combo_box_append (GTK_COMBO_BOX (combo), - _("XVideo - Use hardware video blitter")); - - combo = get_widget ("sound_driver"); - -#ifdef USE_PORTAUDIO - combo_box_append (GTK_COMBO_BOX (combo), - _("PortAudio")); -#endif -#ifdef USE_OSS - combo_box_append (GTK_COMBO_BOX (combo), - _("Open Sound System")); -#endif - combo_box_append (GTK_COMBO_BOX (combo), - _("SDL")); -#ifdef USE_ALSA - combo_box_append (GTK_COMBO_BOX (combo), - _("ALSA")); -#endif -#ifdef USE_PULSEAUDIO - combo_box_append (GTK_COMBO_BOX (combo), - _("PulseAudio")); -#endif - - move_settings_to_dialog (); - - S9xGrabJoysticks (); - source_id = g_timeout_add (100, poll_joystick, (gpointer) this); + S9xGrabJoysticks(); + source_id = g_timeout_add(100, poll_joystick, (gpointer)this); if (config->preferences_width > 0 && config->preferences_height > 0) resize (config->preferences_width, config->preferences_height); - gtk_notebook_set_current_page(GTK_NOTEBOOK(get_widget("display_notebook")), config->current_display_tab); + get_object("display_notebook")->set_current_page(config->current_display_tab); + + auto dialog = Glib::RefPtr::cast_static(window); for (close_dialog = false; !close_dialog; ) { - gtk_widget_show (window); - result = gtk_dialog_run (GTK_DIALOG (window)); + dialog->show(); + auto result = dialog->run(); - config->preferences_width = get_width (); - config->preferences_height = get_height (); - config->current_display_tab = gtk_notebook_get_current_page(GTK_NOTEBOOK(get_widget("display_notebook"))); + config->preferences_width = get_width(); + config->preferences_height = get_height(); + config->current_display_tab = get_object("display_notebook")->get_current_page(); switch (result) { case GTK_RESPONSE_OK: - get_settings_from_dialog (); - config->save_config_file (); + get_settings_from_dialog(); + config->save_config_file(); close_dialog = true; - gtk_widget_hide (window); + dialog->hide(); break; case GTK_RESPONSE_APPLY: - get_settings_from_dialog (); - config->save_config_file (); + get_settings_from_dialog(); + config->save_config_file(); break; case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_CLOSE: case GTK_RESPONSE_DELETE_EVENT: - gtk_widget_hide (window); + dialog->hide(); close_dialog = true; break; @@ -1191,65 +828,59 @@ Snes9xPreferences::show () } } - g_source_remove (source_id); - S9xReleaseJoysticks (); - - gtk_widget_destroy (window); + g_source_remove(source_id); + S9xReleaseJoysticks(); } -void -Snes9xPreferences::focus_next () +void Snes9xPreferences::focus_next() { - int next = get_focused_binding () + 1; + int next = get_focused_binding() + 1; - for (int i = 0; b_breaks [i] != -1; i++) + for (int i = 0; b_breaks[i] != -1; i++) { if (b_breaks[i] == next) next = -1; } if (next > 0) - gtk_widget_grab_focus (get_widget (b_links [next].button_name)); + get_object(b_links[next].button_name)->grab_focus(); else - gtk_widget_grab_focus (get_widget ("cancel_button")); + get_object("cancel_button")->grab_focus(); } -void -Snes9xPreferences::swap_with () +void Snes9xPreferences::swap_with() { - JoypadBinding mediator; - int source_joypad = get_combo ("control_combo"); - int dest_joypad = get_combo ("joypad_to_swap_with"); + JoypadBinding tmp; + int source_joypad = get_combo("control_combo"); + int dest_joypad = get_combo("joypad_to_swap_with"); - mediator = pad[source_joypad]; + tmp = pad[source_joypad]; pad[source_joypad] = pad[dest_joypad]; - pad[dest_joypad] = mediator; + pad[dest_joypad] = tmp; - bindings_to_dialog (source_joypad); + bindings_to_dialog(source_joypad); } -void -Snes9xPreferences::reset_current_joypad () +void Snes9xPreferences::reset_current_joypad() { - int joypad = get_combo ("control_combo"); + int joypad = get_combo("control_combo"); for (unsigned int i = 0; i < NUM_JOYPAD_LINKS; i++) { pad[joypad].data[i].clear(); } - bindings_to_dialog (joypad); + bindings_to_dialog(joypad); } -void -Snes9xPreferences::store_binding (const char *string, Binding binding) +void Snes9xPreferences::store_binding(const char *string, Binding binding) { - int current_joypad = get_combo ("control_combo"); - Binding *pad_bindings = (Binding *) (&pad[current_joypad]); + int current_joypad = get_combo("control_combo"); + Binding *pad_bindings = (Binding *)(&pad[current_joypad]); for (int i = 0; i < NUM_JOYPAD_LINKS; i++) { - if (!strcmp (b_links[i].button_name, string)) + if (!strcmp(b_links[i].button_name, string)) { pad_bindings[i] = binding; } @@ -1260,7 +891,7 @@ Snes9xPreferences::store_binding (const char *string, Binding binding) for (int i = NUM_JOYPAD_LINKS; b_links[i].button_name; i++) { - if (!strcmp (b_links[i].button_name, string)) + if (!strcmp(b_links[i].button_name, string)) { shortcut[i - NUM_JOYPAD_LINKS] = binding; } @@ -1268,22 +899,21 @@ Snes9xPreferences::store_binding (const char *string, Binding binding) { if (shortcut[i - NUM_JOYPAD_LINKS] == binding) { - shortcut[i - NUM_JOYPAD_LINKS].clear (); + shortcut[i - NUM_JOYPAD_LINKS].clear(); } } } - focus_next (); + focus_next(); - bindings_to_dialog (get_combo ("control_combo")); + bindings_to_dialog(get_combo("control_combo")); } -int -Snes9xPreferences::get_focused_binding () +int Snes9xPreferences::get_focused_binding() { for (int i = 0; b_links[i].button_name; i++) { - if (has_focus (b_links[i].button_name)) + if (has_focus(b_links[i].button_name)) return i; } @@ -1324,23 +954,31 @@ void Snes9xPreferences::clear_binding(const char *name) } } -void -Snes9xPreferences::bindings_to_dialog (int joypad) +void Snes9xPreferences::bindings_to_dialog(int joypad) { - char name[256]; - Binding *bindings = (Binding *) &pad[joypad].data; + char name[256]; + Binding *bindings = (Binding *)&pad[joypad].data; - set_combo ("control_combo", joypad); + set_combo("control_combo", joypad); for (int i = 0; i < NUM_JOYPAD_LINKS; i++) { - bindings[i].to_string (name); - set_entry_text (b_links[i].button_name, name); + bindings[i].to_string(name); + set_entry_text(b_links[i].button_name, name); } for (int i = NUM_JOYPAD_LINKS; b_links[i].button_name; i++) { - shortcut[i - NUM_JOYPAD_LINKS].to_string (name); - set_entry_text (b_links[i].button_name, name); + shortcut[i - NUM_JOYPAD_LINKS].to_string(name); + set_entry_text(b_links[i].button_name, name); } } + +void Snes9xPreferences::calibration_dialog() +{ + config->joystick_register_centers(); + auto dialog = Gtk::MessageDialog(_("Current joystick centers have been saved.")); + dialog.set_title(_("Calibration Complete")); + dialog.run(); + dialog.hide(); +} diff --git a/gtk/src/gtk_preferences.h b/gtk/src/gtk_preferences.h index 9deee112..8d6acd7f 100644 --- a/gtk/src/gtk_preferences.h +++ b/gtk/src/gtk_preferences.h @@ -7,45 +7,47 @@ #ifndef __GTK_PREFERENCES_H #define __GTK_PREFERENCES_H -#include "gtk_2_3_compat.h" +#include "gtk_compat.h" #include "gtk_s9x.h" #include "gtk_builder_window.h" -gboolean snes9x_preferences_open (GtkWidget *widget, - gpointer data); +void snes9x_preferences_open(Snes9xWindow *window, Snes9xConfig *config); class Snes9xPreferences : public GtkBuilderWindow { - public: - Snes9xPreferences (Snes9xConfig *config); - ~Snes9xPreferences (); - void show (); - void bindings_to_dialog (int joypad); - int get_focused_binding (); - void store_binding (const char *string, Binding binding); - void browse_folder_dialog (); - int hw_accel_value (int combo_value); - int combo_value (int hw_accel); - void focus_next (); - void swap_with (); - void clear_binding (const char *name); - void reset_current_joypad (); - void load_ntsc_settings (); - void store_ntsc_settings (); - void calibration_dialog (); + public: + Snes9xPreferences(Snes9xConfig *config); + ~Snes9xPreferences(); + void show(); + void bindings_to_dialog(int joypad); + int get_focused_binding(); + void store_binding(const char *string, Binding binding); + int hw_accel_value(int combo_value); + int combo_value(int hw_accel); + void focus_next(); + void swap_with(); + void clear_binding(const char *name); + void reset_current_joypad(); + void load_ntsc_settings(); + void store_ntsc_settings(); + void calibration_dialog(); + void connect_signals(); + void input_rate_changed(); + bool key_pressed(GdkEventKey *event); + void scale_method_changed(); + void shader_select(); + void game_data_browse(std::string folder); + void about_dialog(); - Snes9xConfig *config; - GtkToggleButton *last_toggled; - bool awaiting_key; - bool polling_joystick; - std::array pad; - std::array shortcut; + Snes9xConfig *config; + bool awaiting_key; + bool polling_joystick; + std::array pad; + std::array shortcut; - private: - void get_settings_from_dialog (); - void move_settings_to_dialog (); - - unsigned int *mode_indices; + private: + void get_settings_from_dialog(); + void move_settings_to_dialog(); }; #endif /* __GTK_PREFERENCES_H */ diff --git a/gtk/src/gtk_s9x.cpp b/gtk/src/gtk_s9x.cpp index 3645eb40..ce4a649a 100644 --- a/gtk/src/gtk_s9x.cpp +++ b/gtk/src/gtk_s9x.cpp @@ -6,7 +6,9 @@ #include #include -#include "gtk_2_3_compat.h" +#include "giomm/application.h" +#include "glibmm/main.h" +#include "gtk_compat.h" #include "gtk_config.h" #include "gtk_s9x.h" #include "gtk_control.h" @@ -15,84 +17,85 @@ #include "gtk_netplay.h" #include "statemanager.h" #include "background_particles.h" +#include "snes9x.h" +#include "display.h" +#include "apu/apu.h" +#include "netplay.h" +#include "movie.h" +#include "controls.h" +#include "snapshot.h" +#include "gfx.h" +#include "memmap.h" +#include "ppu.h" -void S9xPostRomInit (); -static void S9xThrottle (int); -static void S9xCheckPointerTimer (); -static gboolean S9xIdleFunc (gpointer data); -static gboolean S9xPauseFunc (gpointer data); -static gboolean S9xScreenSaverCheckFunc (gpointer data); +static void S9xThrottle(int); +static void S9xCheckPointerTimer(); +static bool S9xIdleFunc(); +static bool S9xPauseFunc(); +static bool S9xScreenSaverCheckFunc(); Snes9xWindow *top_level; Snes9xConfig *gui_config; StateManager state_manager; -gint64 frame_clock = -1; -gint64 pointer_timestamp = -1; +gint64 frame_clock = -1; +gint64 pointer_timestamp = -1; -Background::Particles particles(Background::Particles::Mode::Snow); +Background::Particles particles(Background::Particles::Snow); -void S9xTerm (int signal) +static void S9xTerm(int signal) { - S9xExit (); + S9xExit(); } -int main (int argc, char *argv[]) +int main(int argc, char *argv[]) { struct sigaction sig_callback; + auto app = Gtk::Application::create(argc, argv, "com.snes9x.gtk", Gio::APPLICATION_NON_UNIQUE); - gtk_init (&argc, &argv); + setlocale(LC_ALL, ""); + bindtextdomain(GETTEXT_PACKAGE, SNES9XLOCALEDIR); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + textdomain(GETTEXT_PACKAGE); - setlocale (LC_ALL, ""); - bindtextdomain (GETTEXT_PACKAGE, SNES9XLOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); + memset(&Settings, 0, sizeof(Settings)); - memset (&Settings, 0, sizeof (Settings)); + // Original config fills out values this port doesn't. + S9xLoadConfigFiles(argv, argc); - /* Allow original config file for backend settings */ - S9xLoadConfigFiles (argv, argc); + gui_config = new Snes9xConfig(); - /* Perform our config here */ - gui_config = new Snes9xConfig (); + S9xInitInputDevices(); - S9xInitInputDevices (); + gui_config->load_config_file(); - gui_config->load_config_file (); + char *rom_filename = S9xParseArgs(argv, argc); - char *rom_filename = S9xParseArgs (argv, argc); + auto settings = Gtk::Settings::get_default(); + settings->set_property("gtk-menu-images", gui_config->enable_icons); + settings->set_property("gtk-button-images", gui_config->enable_icons); -#if GTK_MAJOR_VERSION >= 3 - auto settings = gtk_settings_get_default(); - g_object_set(settings, - "gtk-menu-images", gui_config->enable_icons, - "gtk_button_images", gui_config->enable_icons, - NULL); -#endif + S9xReportControllers(); - S9xReportControllers (); + if (!Memory.Init() || !S9xInitAPU()) + exit(3); - if (!Memory.Init () || !S9xInitAPU ()) - exit (3); + top_level = new Snes9xWindow(gui_config); - top_level = new Snes9xWindow (gui_config); - - /* If we're going to fullscreen, do it before showing window to avoid flicker. */ + // Setting fullscreen before showing the window avoids some flicker. if ((gui_config->full_screen_on_open && rom_filename) || (gui_config->fullscreen)) - gtk_window_fullscreen (top_level->get_window ()); + top_level->window->fullscreen(); - top_level->show (); + top_level->show(); - S9xInitDisplay (argc, argv); + S9xInitDisplay(argc, argv); - Memory.PostRomInitFunc = S9xPostRomInit; - - S9xPortSoundInit (); + S9xPortSoundInit(); for (int port = 0; port < 2; port++) { enum controllers type; int8 id; - S9xGetController (port, &type, &id, &id, &id, &id); + S9xGetController(port, &type, &id, &id, &id, &id); std::string device_type; switch (type) @@ -113,96 +116,97 @@ int main (int argc, char *argv[]) device_type = "nothingpluggedin"; } - device_type += std::to_string (port + 1); - top_level->set_menu_item_selected (device_type.c_str ()); + device_type += std::to_string(port + 1); + top_level->set_menu_item_selected(device_type.c_str()); } - gui_config->rebind_keys (); - top_level->update_accels (); + gui_config->rebind_keys(); + top_level->update_accelerators(); Settings.Paused = true; - g_timeout_add (100, S9xPauseFunc, NULL); - g_timeout_add (10000, S9xScreenSaverCheckFunc, NULL); - S9xNoROMLoaded (); + Glib::signal_timeout().connect(sigc::ptr_fun(S9xPauseFunc), 100); + Glib::signal_timeout().connect(sigc::ptr_fun(S9xScreenSaverCheckFunc), 10000); + + S9xNoROMLoaded(); if (rom_filename) { - if (S9xOpenROM (rom_filename) && gui_config->full_screen_on_open) - gtk_window_unfullscreen (top_level->get_window()); + if (S9xOpenROM(rom_filename) && gui_config->full_screen_on_open) + top_level->window->unfullscreen(); } - memset (&sig_callback, 0, sizeof (struct sigaction)); + memset(&sig_callback, 0, sizeof(struct sigaction)); sig_callback.sa_handler = S9xTerm; - sigaction (15 /* SIGTERM */, &sig_callback, NULL); - sigaction (3 /* SIGQUIT */, &sig_callback, NULL); - sigaction (2 /* SIGINT */, &sig_callback, NULL); + sigaction(15, &sig_callback, NULL); // SIGTERM + sigaction(3, &sig_callback, NULL); // SIGQUIT + sigaction(2, &sig_callback, NULL); // SIGINT + // Perform the complete fullscreen process, including mode sets, which + // didn't happen in the earlier Gtk call. if (gui_config->fullscreen) - { - top_level->enter_fullscreen_mode (); - } + top_level->enter_fullscreen_mode(); - gui_config->flush_joysticks (); + gui_config->flush_joysticks(); if (rom_filename && *Settings.InitialSnapshotFilename) S9xUnfreezeGame(Settings.InitialSnapshotFilename); - gtk_main (); + app->run(*top_level->window.get()); return 0; } -int S9xOpenROM (const char *rom_filename) +int S9xOpenROM(const char *rom_filename) { uint32 flags; - bool loaded; + bool loaded; if (gui_config->rom_loaded) { - S9xAutoSaveSRAM (); + S9xAutoSaveSRAM(); } - S9xNetplayDisconnect (); + S9xNetplayDisconnect(); flags = CPU.Flags; loaded = false; if (Settings.Multi) - loaded = Memory.LoadMultiCart (Settings.CartAName, Settings.CartBName); + loaded = Memory.LoadMultiCart(Settings.CartAName, Settings.CartBName); else if (rom_filename) - loaded = Memory.LoadROM (rom_filename); + loaded = Memory.LoadROM(rom_filename); Settings.StopEmulation = !loaded; if (!loaded && rom_filename) { - char dir [_MAX_DIR + 1]; - char drive [_MAX_DRIVE + 1]; - char name [_MAX_FNAME + 1]; - char ext [_MAX_EXT + 1]; - char fname [_MAX_PATH + 1]; + char dir[_MAX_DIR + 1]; + char drive[_MAX_DRIVE + 1]; + char name[_MAX_FNAME + 1]; + char ext[_MAX_EXT + 1]; + char fname[_MAX_PATH + 1]; - _splitpath (rom_filename, drive, dir, name, ext); - _makepath (fname, drive, dir, name, ext); + _splitpath(rom_filename, drive, dir, name, ext); + _makepath(fname, drive, dir, name, ext); - strcpy (fname, S9xGetDirectory (ROM_DIR)); - strcat (fname, SLASH_STR); - strcat (fname, name); + strcpy(fname, S9xGetDirectory(ROM_DIR)); + strcat(fname, SLASH_STR); + strcat(fname, name); - if (ext [0]) + if (ext[0]) { - strcat (fname, "."); - strcat (fname, ext); + strcat(fname, "."); + strcat(fname, ext); } - _splitpath (fname, drive, dir, name, ext); - _makepath (fname, drive, dir, name, ext); + _splitpath(fname, drive, dir, name, ext); + _makepath(fname, drive, dir, name, ext); - if ((Settings.StopEmulation = !Memory.LoadROM (fname))) + if ((Settings.StopEmulation = !Memory.LoadROM(fname))) { - fprintf (stderr, _("Error opening: %s\n"), rom_filename); + fprintf(stderr, _("Error opening: %s\n"), rom_filename); loaded = false; } @@ -212,79 +216,77 @@ int S9xOpenROM (const char *rom_filename) if (loaded) { - Memory.LoadSRAM (S9xGetFilename (".srm", SRAM_DIR)); + Memory.LoadSRAM(S9xGetFilename(".srm", SRAM_DIR)); } else { CPU.Flags = flags; Settings.Paused = true; - S9xNoROMLoaded (); - top_level->refresh (); + S9xNoROMLoaded(); + top_level->refresh(); return 1; } CPU.Flags = flags; - if (state_manager.init (gui_config->rewind_buffer_size * 1024 * 1024)) + if (state_manager.init(gui_config->rewind_buffer_size * 1024 * 1024)) { - printf ("Using rewind buffer of %uMB\n", gui_config->rewind_buffer_size); + printf("Using rewind buffer of %uMB\n", gui_config->rewind_buffer_size); } - S9xROMLoaded (); + S9xROMLoaded(); return 0; } -void S9xROMLoaded () +void S9xROMLoaded() { gui_config->rom_loaded = true; - top_level->configure_widgets (); + top_level->configure_widgets(); if (gui_config->full_screen_on_open) { Settings.Paused = false; - top_level->enter_fullscreen_mode (); + top_level->enter_fullscreen_mode(); } - S9xSoundStart (); + S9xSoundStart(); } -void S9xNoROMLoaded () +void S9xNoROMLoaded() { - S9xSoundStop (); + S9xSoundStop(); gui_config->rom_loaded = false; S9xDisplayRefresh(-1, -1); - top_level->configure_widgets (); + top_level->configure_widgets(); } -static gboolean S9xPauseFunc (gpointer data) +static bool S9xPauseFunc() { - S9xProcessEvents (true); + S9xProcessEvents(true); - if (!S9xNetplayPush ()) + if (!S9xNetplayPush()) { - S9xNetplayPop (); + S9xNetplayPop(); } if (!Settings.Paused) /* Coming out of pause */ { /* Clear joystick queues */ - gui_config->flush_joysticks (); + gui_config->flush_joysticks(); - S9xSoundStart (); + S9xSoundStart(); if (Settings.NetPlay && NetPlay.Connected) { - S9xNPSendPause (false); + S9xNPSendPause(false); } /* Resume high-performance callback */ - g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, - S9xIdleFunc, - NULL, - NULL); + Glib::signal_idle().connect(sigc::ptr_fun(S9xIdleFunc)); + return false; } @@ -304,44 +306,44 @@ static gboolean S9xPauseFunc (gpointer data) } } - g_timeout_add(8, S9xPauseFunc, NULL); + Glib::signal_timeout().connect(sigc::ptr_fun(S9xPauseFunc), 8); return false; } -gboolean S9xIdleFunc (gpointer data) +static bool S9xIdleFunc() { if (Settings.Paused && gui_config->rom_loaded) { - S9xSoundStop (); + S9xSoundStop(); - gui_config->flush_joysticks (); + gui_config->flush_joysticks(); if (Settings.NetPlay && NetPlay.Connected) { - S9xNPSendPause (true); + S9xNPSendPause(true); } /* Move to a timer-based function to use less CPU */ - g_timeout_add (8, S9xPauseFunc, NULL); + Glib::signal_timeout().connect(sigc::ptr_fun(S9xPauseFunc), 8); return false; } - S9xCheckPointerTimer (); + S9xCheckPointerTimer(); - S9xProcessEvents (true); + S9xProcessEvents(true); - if (!S9xDisplayDriverIsReady ()) + if (!S9xDisplayDriverIsReady()) { usleep(100); return true; } - S9xThrottle (Settings.SkipFrames); + S9xThrottle(Settings.SkipFrames); - if (!S9xNetplayPush ()) + if (!S9xNetplayPush()) { - if(Settings.Rewinding) + if (Settings.Rewinding) { uint16 joypads[8]; for (int i = 0; i < 8; i++) @@ -350,115 +352,104 @@ gboolean S9xIdleFunc (gpointer data) Settings.Rewinding = state_manager.pop(); for (int i = 0; i < 8; i++) - MovieSetJoypad (i, joypads[i]); + MovieSetJoypad(i, joypads[i]); } - else if(IPPU.TotalEmulatedFrames % gui_config->rewind_granularity == 0) + else if (IPPU.TotalEmulatedFrames % gui_config->rewind_granularity == 0) state_manager.push(); - static int muted_from_turbo = false; - static int mute_saved_state = false; + if ((Settings.TurboMode || Settings.Rewinding) && gui_config->mute_sound_turbo) + Settings.Mute |= 0x80; + else + Settings.Mute &= ~0x80; - if ((Settings.TurboMode || Settings.Rewinding) && !muted_from_turbo && gui_config->mute_sound_turbo) - { - muted_from_turbo = true; - mute_saved_state = Settings.Mute; - S9xSetSoundMute (true); - } + S9xMainLoop(); - if (!(Settings.TurboMode || Settings.Rewinding) && muted_from_turbo) - { - muted_from_turbo = false; - Settings.Mute = mute_saved_state; - } - - S9xMainLoop (); - - S9xNetplayPop (); + S9xNetplayPop(); } return true; } -gboolean S9xScreenSaverCheckFunc (gpointer data) +static bool S9xScreenSaverCheckFunc() { if (!Settings.Paused && (gui_config->screensaver_needs_reset || gui_config->prevent_screensaver)) - top_level->reset_screensaver (); + top_level->reset_screensaver(); return true; } /* Snes9x core hooks */ -void S9xMessage (int type, int number, const char *message) +void S9xMessage(int type, int number, const char *message) { switch (number) { - case S9X_MOVIE_INFO: - S9xSetInfoString (message); + case S9X_MOVIE_INFO: + S9xSetInfoString(message); break; - default: + default: break; } } /* Varies from ParseArgs because this one is for the OS port to handle */ -void S9xParseArg (char **argv, int &i, int argc) +void S9xParseArg(char **argv, int &i, int argc) { - if (!strcasecmp (argv[i], "-filter")) + if (!strcasecmp(argv[i], "-filter")) { if ((++i) < argc) { - if (!strcasecmp (argv[i], "none")) + if (!strcasecmp(argv[i], "none")) { gui_config->scale_method = FILTER_NONE; } - else if (!strcasecmp (argv[i], "supereagle")) + else if (!strcasecmp(argv[i], "supereagle")) { gui_config->scale_method = FILTER_SUPEREAGLE; } - else if (!strcasecmp (argv[i], "2xsai")) + else if (!strcasecmp(argv[i], "2xsai")) { gui_config->scale_method = FILTER_2XSAI; } - else if (!strcasecmp (argv[i], "super2xsai")) + else if (!strcasecmp(argv[i], "super2xsai")) { gui_config->scale_method = FILTER_SUPER2XSAI; } #ifdef USE_HQ2X - else if (!strcasecmp (argv[i], "hq2x")) + else if (!strcasecmp(argv[i], "hq2x")) { gui_config->scale_method = FILTER_HQ2X; } - else if (!strcasecmp (argv[i], "hq3x")) + else if (!strcasecmp(argv[i], "hq3x")) { gui_config->scale_method = FILTER_HQ3X; } - else if (!strcasecmp (argv[i], "hq4x")) + else if (!strcasecmp(argv[i], "hq4x")) { gui_config->scale_method = FILTER_HQ4X; } #endif /* USE_HQ2X */ #ifdef USE_XBRZ - else if (!strcasecmp (argv[i], "2xbrz")) + else if (!strcasecmp(argv[i], "2xbrz")) { gui_config->scale_method = FILTER_2XBRZ; } - else if (!strcasecmp (argv[i], "3xbrz")) + else if (!strcasecmp(argv[i], "3xbrz")) { gui_config->scale_method = FILTER_3XBRZ; } - else if (!strcasecmp (argv[i], "4xbrz")) + else if (!strcasecmp(argv[i], "4xbrz")) { gui_config->scale_method = FILTER_4XBRZ; } #endif /* USE_XBRZ */ - else if (!strcasecmp (argv[i], "epx")) + else if (!strcasecmp(argv[i], "epx")) { gui_config->scale_method = FILTER_EPX; } - else if (!strcasecmp (argv[i], "ntsc")) + else if (!strcasecmp(argv[i], "ntsc")) { gui_config->scale_method = FILTER_NTSC; } @@ -468,20 +459,20 @@ void S9xParseArg (char **argv, int &i, int argc) } } } - else if (!strcasecmp (argv[i], "-mutesound")) + else if (!strcasecmp(argv[i], "-mutesound")) { gui_config->mute_sound = true; } } -static void S9xThrottle (int method) +static void S9xThrottle(int method) { gint64 now; - if (S9xNetplaySyncSpeed ()) + if (S9xNetplaySyncSpeed()) return; - now = g_get_monotonic_time (); + now = g_get_monotonic_time(); if (Settings.HighSpeedSeek > 0) { @@ -496,8 +487,7 @@ static void S9xThrottle (int method) if (Settings.TurboMode) { IPPU.FrameSkip++; - if ((IPPU.FrameSkip >= Settings.TurboSkipFrames) - && !Settings.HighSpeedSeek) + if ((IPPU.FrameSkip >= Settings.TurboSkipFrames) && !Settings.HighSpeedSeek) { IPPU.FrameSkip = 0; IPPU.SkippedFrames = 0; @@ -550,8 +540,8 @@ static void S9xThrottle (int method) while (now - frame_clock < Settings.FrameTime) { - usleep (100); - now = g_get_monotonic_time (); + usleep(100); + now = g_get_monotonic_time(); } frame_clock += Settings.FrameTime; @@ -560,129 +550,47 @@ static void S9xThrottle (int method) } } -void S9xSyncSpeed () +void S9xSyncSpeed() { } -static void S9xCheckPointerTimer () +static void S9xCheckPointerTimer() { if (!gui_config->pointer_is_visible) return; - if (g_get_monotonic_time () - gui_config->pointer_timestamp > 1000000) + if (g_get_monotonic_time() - gui_config->pointer_timestamp > 1000000) { - top_level->hide_mouse_cursor (); + top_level->hide_mouse_cursor(); gui_config->pointer_is_visible = false; } } /* Final exit point, issues exit (0) */ -void S9xExit () +void S9xExit() { - gui_config->save_config_file (); + gui_config->save_config_file(); - top_level->leave_fullscreen_mode (); + top_level->leave_fullscreen_mode(); - S9xPortSoundDeinit (); + S9xPortSoundDeinit(); Settings.StopEmulation = true; if (gui_config->rom_loaded) { - S9xAutoSaveSRAM (); + S9xAutoSaveSRAM(); } - S9xDeinitAPU (); + S9xDeinitAPU(); - S9xDeinitInputDevices (); - S9xDeinitDisplay (); - - gtk_main_quit (); + S9xDeinitInputDevices(); + S9xDeinitDisplay(); delete top_level; delete gui_config; - exit (0); -} - -void -S9xPostRomInit () -{ - if (!strncmp ((const char *) Memory.NSRTHeader + 24, "NSRT", 4)) - { - switch (Memory.NSRTHeader[29]) - { - case 0: //Everything goes - break; - - case 0x10: //Mouse in Port 0 - S9xSetController (0, CTL_MOUSE, 0, 0, 0, 0); - top_level->set_menu_item_selected ("mouse1"); - break; - - case 0x01: //Mouse in Port 1 - S9xSetController (1, CTL_MOUSE, 1, 0, 0, 0); - top_level->set_menu_item_selected ("mouse2"); - break; - - case 0x03: //Super Scope in Port 1 - S9xSetController (1, CTL_SUPERSCOPE, 0, 0, 0, 0); - top_level->set_menu_item_selected ("superscope1"); - break; - - case 0x06: //Multitap in Port 1 - S9xSetController (1, CTL_MP5, 1, 2, 3, 4); - top_level->set_menu_item_selected ("multitap1"); - break; - - case 0x66: //Multitap in Ports 0 and 1 - S9xSetController (0, CTL_MP5, 0, 1, 2, 3); - S9xSetController (1, CTL_MP5, 4, 5, 6, 7); - top_level->set_menu_item_selected ("multitap1"); - top_level->set_menu_item_selected ("multitap2"); - break; - - case 0x08: //Multitap in Port 1, Mouse in new Port 1 - S9xSetController (1, CTL_MOUSE, 1, 0, 0, 0); - //There should be a toggle here for putting in Multitap instead - top_level->set_menu_item_selected ("mouse2"); - break; - - case 0x04: //Pad or Super Scope in Port 1 - S9xSetController (1, CTL_SUPERSCOPE, 0, 0, 0, 0); - top_level->set_menu_item_selected ("superscope2"); - //There should be a toggle here for putting in a pad instead - break; - - case 0x05: //Justifier - Must ask user... - S9xSetController (1, CTL_JUSTIFIER, 1, 0, 0, 0); - //There should be a toggle here for how many justifiers - break; - - case 0x20: //Pad or Mouse in Port 0 - S9xSetController (0, CTL_MOUSE, 0, 0, 0, 0); - //There should be a toggle here for putting in a pad instead - break; - - case 0x22: //Pad or Mouse in Port 0 & 1 - S9xSetController (0, CTL_MOUSE, 0, 0, 0, 0); - S9xSetController (1, CTL_MOUSE, 1, 0, 0, 0); - //There should be a toggles here for putting in pads instead - break; - - case 0x24: //Pad or Mouse in Port 0, Pad or Super Scope in Port 1 - //There should be a toggles here for what to put in, I'm leaving it at gamepad for now - break; - - case 0x27: //Pad or Mouse in Port 0, Pad or Mouse or Super Scope in Port 1 - //There should be a toggles here for what to put in, I'm leaving it at gamepad for now - break; - - //Not Supported yet - case 0x99: break; //Lasabirdie - case 0x0A: break; //Barcode Battler - } - } + exit(0); } const char *S9xStringInput(const char *message) @@ -690,12 +598,12 @@ const char *S9xStringInput(const char *message) return NULL; } -void S9xExtraUsage () +void S9xExtraUsage() { - printf ("GTK port options:\n" - "-filter [option] Use a filter to scale the image.\n" - " [option] is one of: none supereagle 2xsai\n" - " super2xsai hq2x hq3x hq4x 2xbrz 3xbrz 4xbrz epx ntsc\n" - "\n" - "-mutesound Disables sound output.\n"); + printf("GTK port options:\n" + "-filter [option] Use a filter to scale the image.\n" + " [option] is one of: none supereagle 2xsai\n" + " super2xsai hq2x hq3x hq4x 2xbrz 3xbrz 4xbrz epx ntsc\n" + "\n" + "-mutesound Disables sound output.\n"); } diff --git a/gtk/src/gtk_s9x.h b/gtk/src/gtk_s9x.h index 1b3036e5..65121d8d 100644 --- a/gtk/src/gtk_s9x.h +++ b/gtk/src/gtk_s9x.h @@ -8,19 +8,18 @@ #define __GTK_S9X_H #include "gtk_config.h" -#include "gtk_s9xcore.h" #include "gtk_s9xwindow.h" #include -#define SNES9X_GTK_AUTHORS "(c) 2007 - 2019 Brandon Wright (bearoso@gmail.com)" +#define SNES9X_GTK_AUTHORS "(c) 2007 - 2020 Brandon Wright (bearoso@gmail.com)" #define SNES9X_GTK_VERSION "87" extern Snes9xWindow *top_level; extern Snes9xConfig *gui_config; -int S9xOpenROM (const char *filename); -void S9xNoROMLoaded (); -void S9xROMLoaded (); +int S9xOpenROM(const char *filename); +void S9xNoROMLoaded(); +void S9xROMLoaded(); #endif /* __GTK_S9X_H */ diff --git a/gtk/src/gtk_s9xwindow.cpp b/gtk/src/gtk_s9xwindow.cpp index 813292a5..c211f20e 100644 --- a/gtk/src/gtk_s9xwindow.cpp +++ b/gtk/src/gtk_s9xwindow.cpp @@ -4,13 +4,11 @@ For further information, consult the LICENSE file in the root directory. \*****************************************************************************/ -#include "gtk_2_3_compat.h" -#include "gtk_config.h" +#include "gtk_compat.h" + #ifdef GDK_WINDOWING_X11 #include #endif -#include -#include #ifdef USE_XV #include @@ -31,246 +29,255 @@ #include "gtk_control.h" #include "gtk_cheat.h" #include "gtk_netplay.h" +#include "gtk_s9xwindow.h" -static gboolean -event_main_window_delete (GtkWidget *widget, - GdkEvent *event, - gpointer data) +#include "snes9x.h" +#include "controls.h" +#include "movie.h" +#include "display.h" +#include "apu/apu.h" +#include "memmap.h" +#include "cpuexec.h" +#include "snapshot.h" +#include "netplay.h" + +static Glib::RefPtr get_save_states_file_filter() { - S9xExit (); - - return true; + const char *exts[] = { "*.sst", "*.000", "*.001", "*.002", "*.003", "*.004", + "*.005", "*.006", "*.007", "*.008", "*.009", nullptr }; + auto filter = Gtk::FileFilter::create(); + filter->set_name(_("Save States")); + for (int i = 0; exts[i]; i++) + filter->add_pattern(exts[i]); + return filter; } -static gboolean -event_main_window_state_event (GtkWidget *widget, - GdkEventWindowState *event, - gpointer data) +static Glib::RefPtr get_all_files_filter() { - Snes9xWindow *window = (Snes9xWindow *) data; - window->fullscreen_state = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN; - window->maximized_state = event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED; - - return false; + auto filter = Gtk::FileFilter::create(); + filter->set_name(_("All Files")); + filter->add_pattern("*.*"); + filter->add_pattern("*"); + return filter; } -static gboolean -event_continue_item_activate (GtkWidget *widget, gpointer data) +Snes9xWindow::Snes9xWindow(Snes9xConfig *config) + : GtkBuilderWindow("main_window") { - Snes9xWindow *window = (Snes9xWindow *) data; + user_pause = 0; + sys_pause = 0; + last_width = -1; + last_height = -1; + this->config = config; + recent_menu = nullptr; + fullscreen_state = 0; + maximized_state = 0; + focused = true; + paused_from_focus_loss = false; + cr = nullptr; + cairo_owned = false; + mouse_grabbed = false; - window->unpause_from_user (); + if (Gtk::IconTheme::get_default()->has_icon("snes9x")) + { + window->set_default_icon_name("snes9x"); + } + else + { + auto loader = Gdk::PixbufLoader::create(); + loader->write((const guint8 *)app_icon, sizeof(app_icon)); + loader->close(); + window->set_default_icon(loader->get_pixbuf()); + } - return true; -} + drawing_area = get_object("drawingarea").get(); -static gboolean -event_open_cheats (GtkWidget *widget, gpointer data) -{ - Snes9xCheats *cheats; - cheats = new Snes9xCheats (); + gtk_widget_realize(GTK_WIDGET(window->gobj())); + gtk_widget_realize(GTK_WIDGET(drawing_area->gobj())); - cheats->show (); - delete cheats; - - return true; -} - -static gboolean -event_open_multicart (GtkWidget *widget, gpointer data) -{ - ((Snes9xWindow *) data)->open_multicart_dialog (); - - return true; -} - -static gboolean -event_rom_info (GtkWidget *widget, gpointer data) -{ - Snes9xWindow *window = (Snes9xWindow *) data; - - window->show_rom_info (); - - return true; -} - -static gboolean -event_toggle_interface (GtkWidget *widget, gpointer data) -{ - Snes9xWindow *window = (Snes9xWindow *) data; - - window->toggle_ui (); - - return true; -} - -static gboolean -event_sync_clients (GtkWidget *widget, gpointer data) -{ - S9xNetplaySyncClients (); - - return true; -} - -static gboolean -event_pause_item_activate (GtkWidget *widget, gpointer data) -{ - Snes9xWindow *window = (Snes9xWindow *) data; - - window->pause_from_user (); - - return true; -} - -static gboolean -event_open_netplay (GtkWidget *widget, gpointer data) -{ - S9xNetplayDialogOpen (); - - return true; -} - -#if GTK_MAJOR_VERSION >= 3 -static gboolean -event_drawingarea_draw (GtkWidget *widget, - cairo_t *cr, - gpointer data) -{ - - Snes9xWindow *window = (Snes9xWindow *) data; - window->cr = cr; - window->cairo_owned = false; - window->expose (); - window->cr = NULL; - - return true; -} +#ifndef USE_OPENGL + get_object("shader_parameters_separator")->hide(); + get_object("shader_parameters_item")->hide(); #else - -static gboolean -event_drawingarea_expose (GtkWidget *widget, - GdkEventExpose *event, - gpointer data) -{ - ((Snes9xWindow *) data)->expose (); - - return true; -} + enable_widget("shader_parameters_item", false); #endif -static gboolean -event_key (GtkWidget *widget, GdkEventKey *event, gpointer data) -{ - Snes9xWindow *window = (Snes9xWindow *) data; - static unsigned int keyval = 0; - static GdkEventType type = GDK_NOTHING; - Binding b; - s9xcommand_t cmd; + connect_signals(); - /* Ignore multiple identical keypresses to discard repeating keys */ - if (event->keyval == keyval && event->type == type) + if (config->window_width < 100 || config->window_height < 100) { - return true; + config->window_width = 256; + config->window_height = 224; } - /* Provide escape key to get out of fullscreen */ - if (event->keyval == GDK_Escape) - { - if (event->type == GDK_KEY_RELEASE) - { - if (window->config->default_esc_behavior == ESC_EXIT_FULLSCREEN) - window->leave_fullscreen_mode (); - else if (window->config->default_esc_behavior == ESC_EXIT_SNES9X) - S9xExit (); - else - window->toggle_ui (); - } + window->get_window()->set_cursor(); - return true; - } - - keyval = event->keyval; - type = event->type; - - b = Binding (event); - - /* If no mapping for modifier version exists, try non-modifier */ - cmd = S9xGetMapping (b.hex ()); - if (cmd.type == S9xNoMapping) - { - b = Binding (event->keyval, false, false, false); - cmd = S9xGetMapping (b.hex ()); - } - - if (cmd.type != S9xNoMapping) - { - S9xReportButton (b.hex (), (event->type == GDK_KEY_PRESS)); - return true; - } - - return false; /* Pass the key to GTK */ + resize(config->window_width, config->window_height); } -gboolean -event_motion_notify (GtkWidget *widget, - GdkEventMotion *event, - gpointer user_data) +void Snes9xWindow::connect_signals() { - Snes9xWindow *window = (Snes9xWindow *) user_data; - - if (!window->config->rom_loaded || - window->last_width <= 0 || - window->last_height <= 0) - { + drawing_area->signal_draw().connect(sigc::mem_fun(*this, &Snes9xWindow::draw)); + window->signal_delete_event().connect([](GdkEventAny *event) -> bool { + S9xExit(); return false; - } - - if (window->mouse_grabbed) - { - if (event->x_root == window->gdk_mouse_x && - event->y_root == window->gdk_mouse_y) - return false; - - window->snes_mouse_x += (event->x_root - window->gdk_mouse_x); - window->snes_mouse_y += (event->y_root - window->gdk_mouse_y); - window->center_mouse (); + }); + get_object("exit_item")->signal_activate().connect([] { + S9xExit(); + }); + window->signal_window_state_event().connect([&](GdkEventWindowState *state) -> bool { + fullscreen_state = state->new_window_state & GDK_WINDOW_STATE_FULLSCREEN; + maximized_state = state->new_window_state & GDK_WINDOW_STATE_MAXIMIZED; return false; - } + }); -#if GTK_CHECK_VERSION(3,10,0) - int scale_factor = gdk_window_get_scale_factor (gtk_widget_get_window (GTK_WIDGET (window->get_window ()))); -#else - int scale_factor = 1; + window->signal_focus_in_event().connect([&](GdkEventFocus *event) -> bool { + focus_notify(true); + return false; + }); + + window->signal_focus_out_event().connect([&](GdkEventFocus *event) -> bool { + focus_notify(false); + return false; + }); + + last_key_pressed_keyval = 0; + last_key_pressed_type = GDK_NOTHING; + window->signal_key_press_event().connect(sigc::mem_fun(*this, &Snes9xWindow::event_key), false); + window->signal_key_release_event().connect(sigc::mem_fun(*this, &Snes9xWindow::event_key), false); + + drawing_area->signal_button_press_event().connect(sigc::mem_fun(*this, &Snes9xWindow::button_press)); + drawing_area->signal_button_release_event().connect(sigc::mem_fun(*this, &Snes9xWindow::button_release)); + drawing_area->signal_motion_notify_event().connect(sigc::mem_fun(*this, &Snes9xWindow::motion_notify)); + + get_object("continue_item")->signal_activate().connect([&] { + unpause_from_user(); + }); + + get_object("pause_item")->signal_activate().connect([&] { + pause_from_user(); + }); + + get_object("fullscreen_item")->signal_activate().connect([&] { + toggle_fullscreen_mode(); + }); + + get_object("open_rom_item")->signal_activate().connect([&] { + open_rom_dialog(); + }); + + get_object("reset_item")->signal_activate().connect([&] { + S9xSoftReset(); + }); + + get_object("hard_reset_item")->signal_activate().connect([&] { + S9xReset(); + }); + +#ifdef USE_OPENGL + get_object("shader_parameters_item")->signal_activate().connect([&] { + gtk_shader_parameters_dialog(get_window()); + }); #endif - window->snes_mouse_x = (uint16) - ((int) (event->x * scale_factor) - window->mouse_region_x) * 256 / - (window->mouse_region_width <= 0 ? 1 : window->mouse_region_width); - - window->snes_mouse_y = (uint16) - ((int) (event->y * scale_factor) - window->mouse_region_y) * (gui_config->overscan ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT) / - (window->mouse_region_height <= 0 ? 1 : window->mouse_region_height); - - if (!window->config->pointer_is_visible) + const std::vector port_items = { "joypad1", "mouse1", "superscope1", "joypad2", "mouse2", "multitap2", "superscope2", "nothingpluggedin2" }; + for (auto &name : port_items) { - if (!S9xIsMousePluggedIn ()) - window->show_mouse_cursor (); + get_object(name)->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &Snes9xWindow::port_activate), name)); } - window->config->pointer_timestamp = g_get_monotonic_time (); + for (int i = 0; i <= 9; i++) + { + std::string name = "load_state_" + std::to_string(i); + get_object(name.c_str())->signal_activate().connect([i] { + S9xQuickLoadSlot(i); + }); + name = "save_state_" + std::to_string(i); + get_object(name.c_str())->signal_activate().connect([i] { + S9xQuickSaveSlot(i); + }); + } - return false; + get_object("from_file1")->signal_activate().connect([&] { + load_state_dialog(); + }); + + get_object("to_file1")->signal_activate().connect([&] { + save_state_dialog(); + }); + + get_object("load_state_undo")->signal_activate().connect([&] { + S9xUnfreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR)); + }); + + get_object("save_spc_item")->signal_activate().connect([&] { + save_spc_dialog(); + }); + + get_object("open_movie_item")->signal_activate().connect([&] { + if (S9xMovieActive()) + S9xMovieStop(false); + + S9xMovieOpen(S9xChooseMovieFilename(true), false); + }); + + get_object("stop_recording_item")->signal_activate().connect([&] { + if (S9xMovieActive()) + S9xMovieStop(false); + }); + + get_object("jump_to_frame_item")->signal_activate().connect([&] { + movie_seek_dialog(); + }); + + get_object("record_movie_item")->signal_activate().connect([&] { + if (S9xMovieActive()) + S9xMovieStop(false); + + S9xMovieCreate(S9xChooseMovieFilename(false), 0xFF, MOVIE_OPT_FROM_RESET, nullptr, 0); + }); + + get_object("cheats_item")->signal_activate().connect([&] { + open_snes9x_cheats_dialog(); + }); + + get_object("preferences_item")->signal_activate().connect([&] { + snes9x_preferences_open(this, config); + }); + + get_object("open_netplay_item")->signal_activate().connect([&] { + S9xNetplayDialogOpen(); + }); + + get_object("rom_info_item")->signal_activate().connect([&] { + show_rom_info(); + }); + + get_object("sync_clients_item")->signal_activate().connect([&] { + S9xNetplaySyncClients(); + }); + + get_object("hide_ui")->signal_activate().connect([&] { + toggle_ui(); + }); + + for (int i = 1; i <= 5; i++) + { + std::string name = "exact_pixels_" + std::to_string(i) + "x_item"; + get_object(name.c_str())->signal_activate().connect([i, this] { + resize_to_multiple(i); + }); + } + + get_object("open_multicart_item")->signal_activate().connect([&] { + open_multicart_dialog(); + }); } -gboolean -event_button_press (GtkWidget *widget, - GdkEventButton *event, - gpointer user_data) +bool Snes9xWindow::button_press(GdkEventButton *event) { - auto window = (Snes9xWindow *)user_data; - if (S9xIsMousePluggedIn()) { switch (event->button) @@ -288,402 +295,157 @@ event_button_press (GtkWidget *widget, } else if (event->button == 3) { -#if GTK_MAJOR_VERSION >= 3 - gtk_menu_popup_at_pointer(GTK_MENU(window->get_widget("view_menu_menu")), NULL); -#else - gtk_menu_popup(GTK_MENU(window->get_widget("view_menu_menu")), NULL, - NULL, NULL, NULL, 3, event->time); -#endif + get_object("view_menu_menu")->popup_at_pointer(nullptr); } + return false; } -gboolean -event_button_release (GtkWidget *widget, - GdkEventButton *event, - gpointer user_data) +bool Snes9xWindow::button_release(GdkEventButton *event) { switch (event->button) { case 1: - S9xReportButton (BINDING_MOUSE_BUTTON0, 0); + S9xReportButton(BINDING_MOUSE_BUTTON0, 0); break; case 2: - S9xReportButton (BINDING_MOUSE_BUTTON1, 0); + S9xReportButton(BINDING_MOUSE_BUTTON1, 0); break; case 3: - S9xReportButton (BINDING_MOUSE_BUTTON2, 0); + S9xReportButton(BINDING_MOUSE_BUTTON2, 0); break; } return false; } -static void -event_fullscreen (GtkWidget *widget, gpointer data) +bool Snes9xWindow::motion_notify(GdkEventMotion *event) { - Snes9xWindow *window = (Snes9xWindow *) data; + if (!config->rom_loaded || last_width <= 0 || last_height <= 0) + return false; - if (!window->config->fullscreen) - window->enter_fullscreen_mode (); - else - window->leave_fullscreen_mode (); -} + if (mouse_grabbed) + { + if (event->x_root == gdk_mouse_x && event->y_root == gdk_mouse_y) + return false; + snes_mouse_x += (event->x_root - gdk_mouse_x); + snes_mouse_y += (event->y_root - gdk_mouse_y); + center_mouse(); -static void -event_exact_pixels_1x (GtkWidget *widget, gpointer data) -{ - ((Snes9xWindow *) data)->resize_to_multiple (1); -} + return false; + } -static void -event_exact_pixels_2x (GtkWidget *widget, gpointer data) -{ - ((Snes9xWindow *) data)->resize_to_multiple (2); -} + int scale_factor = window->get_scale_factor(); -static void -event_exact_pixels_3x (GtkWidget *widget, gpointer data) -{ - ((Snes9xWindow *) data)->resize_to_multiple (3); -} + snes_mouse_x = (uint16)((int)(event->x * scale_factor) - mouse_region_x) * 256 / + (mouse_region_width <= 0 ? 1 : mouse_region_width); -static void -event_exact_pixels_4x (GtkWidget *widget, gpointer data) -{ - ((Snes9xWindow *) data)->resize_to_multiple (4); -} + snes_mouse_y = (uint16)((int)(event->y * scale_factor) - mouse_region_y) * (gui_config->overscan ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT) / + (mouse_region_height <= 0 ? 1 : mouse_region_height); -static void -event_exact_pixels_5x (GtkWidget *widget, gpointer data) -{ - ((Snes9xWindow *) data)->resize_to_multiple (5); -} + if (!config->pointer_is_visible) + { + if (!S9xIsMousePluggedIn()) + show_mouse_cursor(); + } -static void -event_record_movie (GtkWidget *widget, gpointer data) -{ - if (S9xMovieActive ()) - S9xMovieStop (false); - - S9xMovieCreate (S9xChooseMovieFilename (false), - 0xFF, - MOVIE_OPT_FROM_RESET, - NULL, - 0); -} - -static void -event_open_movie (GtkWidget *widget, gpointer data) -{ - if (S9xMovieActive ()) - S9xMovieStop (false); - - S9xMovieOpen (S9xChooseMovieFilename (true), false); -} - -static void -event_shader_parameters (GtkWidget *widget, gpointer data) -{ -#ifdef USE_OPENGL - Snes9xWindow *window = (Snes9xWindow *) data; - - gtk_shader_parameters_dialog (window->get_window ()); -#endif -} - -static void -event_stop_recording (GtkWidget *widget, gpointer data) -{ - if (S9xMovieActive ()) - S9xMovieStop (false); -} - -static void -event_jump_to_frame (GtkWidget *widget, gpointer data) -{ - Snes9xWindow *window = (Snes9xWindow *) data; - - window->movie_seek_dialog (); -} - -static void -event_reset (GtkWidget *widget, gpointer data) -{ - S9xSoftReset (); -} - -static void -event_hard_reset (GtkWidget *widget, gpointer data) -{ - S9xReset (); -} - -static void -event_save_state (GtkWidget *widget, gpointer data) -{ - int slot; - char *name = (char *) gtk_buildable_get_name (GTK_BUILDABLE (widget)); - - slot = atoi (&(name[11])); - - S9xQuickSaveSlot (slot); -} - -static void -event_save_state_file (GtkWidget *widget, gpointer data) -{ - ((Snes9xWindow *) data)->save_state_dialog (); -} - -static void -event_load_state (GtkWidget *widget, gpointer data) -{ - int slot; - char *name = (char *) gtk_buildable_get_name (GTK_BUILDABLE (widget)); - - slot = atoi (&(name[11])); - - S9xQuickLoadSlot (slot); -} - -static void -event_load_state_undo (GtkWidget *widget, gpointer data) -{ - S9xUnfreezeGame (S9xGetFilename (".undo", SNAPSHOT_DIR)); -} - - -static void -event_load_state_file (GtkWidget *widget, gpointer data) -{ - ((Snes9xWindow *) data)->load_state_dialog (); -} - -static void -event_open_rom (GtkWidget *widget, gpointer data) -{ - ((Snes9xWindow *) data)->open_rom_dialog (); -} - -static void -event_recent_open (GtkRecentChooser *chooser, gpointer data) -{ - Snes9xWindow *window = (Snes9xWindow *) data; - gchar *uri = gtk_recent_chooser_get_current_uri (chooser); - gchar *filename = g_filename_from_uri (uri, NULL, NULL); - - window->try_open_rom (filename); - - g_free (filename); - g_free (uri); -} - -static void -event_save_spc (GtkWidget *widget, gpointer data) -{ - ((Snes9xWindow *) data)->save_spc_dialog (); -} - -static gboolean -event_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer data) -{ - ((Snes9xWindow *) data)->focus_notify (true); + config->pointer_timestamp = g_get_monotonic_time(); return false; } -static gboolean -event_focus_out (GtkWidget *widget, GdkEventFocus *event, gpointer data) +void Snes9xWindow::port_activate(const char *name) { - ((Snes9xWindow *) data)->focus_notify (false); - - return false; -} - -static void -event_port (GtkWidget *widget, gpointer data) -{ - const gchar *name = gtk_buildable_get_name (GTK_BUILDABLE (widget)); - - if (!(gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))) + auto item = get_object(name); + if (!item->get_active()) return; - if (!strcasecmp (name, "joypad1")) + if (!strcasecmp(name, "joypad1")) { - S9xSetController (0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); } - - else if (!strcasecmp (name, "joypad2")) + else if (!strcasecmp(name, "joypad2")) { - S9xSetController (1, CTL_JOYPAD, 1, 0, 0, 0); + S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0); } - - else if (!strcasecmp (name, "mouse1")) + else if (!strcasecmp(name, "mouse1")) { - S9xSetController (0, CTL_MOUSE, 0, 0, 0, 0); + S9xSetController(0, CTL_MOUSE, 0, 0, 0, 0); } - - else if (!strcasecmp (name, "mouse2")) + else if (!strcasecmp(name, "mouse2")) { - S9xSetController (1, CTL_MOUSE, 0, 0, 0, 0); + S9xSetController(1, CTL_MOUSE, 0, 0, 0, 0); } - - else if (!strcasecmp (name, "superscope1")) + else if (!strcasecmp(name, "superscope1")) { - S9xSetController (0, CTL_SUPERSCOPE, 0, 0, 0, 0); + S9xSetController(0, CTL_SUPERSCOPE, 0, 0, 0, 0); } - - else if (!strcasecmp (name, "superscope2")) + else if (!strcasecmp(name, "superscope2")) { - S9xSetController (1, CTL_SUPERSCOPE, 0, 0, 0, 0); + S9xSetController(1, CTL_SUPERSCOPE, 0, 0, 0, 0); } - - else if (!strcasecmp (name, "multitap1")) + else if (!strcasecmp(name, "multitap1")) { - S9xSetController (0, CTL_MP5, 0, 1, 2, 3); + S9xSetController(0, CTL_MP5, 0, 1, 2, 3); } - - else if (!strcasecmp (name, "multitap2")) + else if (!strcasecmp(name, "multitap2")) { - S9xSetController (1, CTL_MP5, 1, 2, 3, 4); + S9xSetController(1, CTL_MP5, 1, 2, 3, 4); } - - else if (!strcasecmp (name, "nothingpluggedin2")) + else if (!strcasecmp(name, "nothingpluggedin2")) { - S9xSetController (1, CTL_NONE, 0, 0, 0, 0); + S9xSetController(1, CTL_NONE, 0, 0, 0, 0); } } -Snes9xWindow::Snes9xWindow (Snes9xConfig *config) : - GtkBuilderWindow ("main_window") +bool Snes9xWindow::event_key(GdkEventKey *event) { - GtkBuilderWindowCallbacks callbacks[] = + Binding b; + s9xcommand_t cmd; + + // Ignore multiple identical keypresses to discard repeating keys + if (event->keyval == last_key_pressed_keyval && event->type == last_key_pressed_type) { - { "main_window_delete_event", G_CALLBACK (event_main_window_delete) }, - { "main_window_state_event", G_CALLBACK (event_main_window_state_event) }, - { "on_continue_item_activate", G_CALLBACK (event_continue_item_activate) }, - { "on_pause_item_activate", G_CALLBACK (event_pause_item_activate) }, - { "main_window_key_press_event", G_CALLBACK (event_key) }, - { "main_window_key_release_event", G_CALLBACK (event_key) }, - { "on_fullscreen_item_activate", G_CALLBACK (event_fullscreen) }, - { "on_open_rom_activate", G_CALLBACK (event_open_rom) }, - { "on_reset_item_activate", G_CALLBACK (event_reset) }, - { "on_shader_parameters_item_activate", G_CALLBACK (event_shader_parameters) }, - { "hard_reset", G_CALLBACK (event_hard_reset) }, - { "on_port_activate", G_CALLBACK (event_port) }, - { "load_save_state", G_CALLBACK (event_load_state) }, - { "load_state_file", G_CALLBACK (event_load_state_file) }, - { "load_state_undo", G_CALLBACK (event_load_state_undo) }, - { "save_save_state", G_CALLBACK (event_save_state) }, - { "save_state_file", G_CALLBACK (event_save_state_file) }, - { "drawingarea_button_press", G_CALLBACK (event_button_press) }, - { "drawingarea_button_release", G_CALLBACK (event_button_release) }, - { "drawingarea_motion_notify", G_CALLBACK (event_motion_notify) }, - { "save_spc", G_CALLBACK (event_save_spc) }, - { "open_movie", G_CALLBACK (event_open_movie) }, - { "stop_recording", G_CALLBACK (event_stop_recording) }, - { "jump_to_frame", G_CALLBACK (event_jump_to_frame) }, - { "record_movie", G_CALLBACK (event_record_movie) }, - { "open_cheats", G_CALLBACK (event_open_cheats) }, - { "on_preferences_item_activate", G_CALLBACK (snes9x_preferences_open) }, - { "focus_in_event", G_CALLBACK (event_focus_in) }, - { "focus_out_event", G_CALLBACK (event_focus_out) }, - { "open_netplay", G_CALLBACK (event_open_netplay) }, - { "rom_info", G_CALLBACK (event_rom_info) }, - { "sync_clients", G_CALLBACK (event_sync_clients) }, - { "toggle_interface", G_CALLBACK (event_toggle_interface) }, - { "exact_1x", G_CALLBACK (event_exact_pixels_1x) }, - { "exact_2x", G_CALLBACK (event_exact_pixels_2x) }, - { "exact_3x", G_CALLBACK (event_exact_pixels_3x) }, - { "exact_4x", G_CALLBACK (event_exact_pixels_4x) }, - { "exact_5x", G_CALLBACK (event_exact_pixels_5x) }, - { "open_multicart", G_CALLBACK (event_open_multicart) }, - - { NULL, NULL } - }; - - user_pause = 0; - sys_pause = 0; - last_width = -1; - last_height = -1; - this->config = config; - empty_cursor = NULL; - default_cursor = NULL; - recent_menu = NULL; - fullscreen_state = 0; - maximized_state = 0; - focused = true; - paused_from_focus_loss = false; - cr = NULL; - cairo_owned = false; - mouse_grabbed = false; - - if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), "snes9x")) - { - gtk_window_set_default_icon_name ("snes9x"); + return true; } - else + + // Provide escape key to get out of fullscreen + if (event->keyval == GDK_Escape) { - GdkPixbufLoader *loader = gdk_pixbuf_loader_new (); - if (gdk_pixbuf_loader_write (loader, (const guchar *)app_icon, sizeof (app_icon), NULL) && - gdk_pixbuf_loader_close (loader, NULL) && - (icon = gdk_pixbuf_loader_get_pixbuf (loader))) + if (event->type == GDK_KEY_RELEASE) { - gtk_window_set_default_icon (icon); + if (config->default_esc_behavior == ESC_EXIT_FULLSCREEN) + leave_fullscreen_mode(); + else if (config->default_esc_behavior == ESC_EXIT_SNES9X) + S9xExit(); + else + toggle_ui(); } - g_object_unref(loader); + + return true; } - drawing_area = GTK_DRAWING_AREA (get_widget ("drawingarea")); -#if GTK_MAJOR_VERSION < 3 - gtk_widget_set_double_buffered (GTK_WIDGET (drawing_area), false); - gtk_widget_set_app_paintable (GTK_WIDGET (drawing_area), true); + last_key_pressed_keyval = event->keyval; + last_key_pressed_type = event->type; -#endif + b = Binding(event); - gtk_widget_realize (window); - gtk_widget_realize (GTK_WIDGET (drawing_area)); -#if GTK_MAJOR_VERSION < 3 - gdk_window_set_back_pixmap (gtk_widget_get_window (window), NULL, false); - gdk_window_set_back_pixmap (gtk_widget_get_window (GTK_WIDGET (drawing_area)), NULL, false); -#endif - -#ifndef USE_OPENGL - gtk_widget_hide (get_widget ("shader_parameters_separator")); - gtk_widget_hide (get_widget ("shader_parameters_item")); -#else - enable_widget ("shader_parameters_item", false); -#endif - -#if GTK_MAJOR_VERSION >= 3 - g_signal_connect_data (drawing_area, - "draw", - G_CALLBACK (event_drawingarea_draw), - this, - NULL, - (GConnectFlags) 0); -#else - g_signal_connect_data (drawing_area, - "expose-event", - G_CALLBACK (event_drawingarea_expose), - this, - NULL, - (GConnectFlags) 0); -#endif - signal_connect (callbacks); - - if (config->window_width < 100 || config->window_height < 100) + // If no mapping for modifier version exists, try non-modifier + cmd = S9xGetMapping(b.hex()); + if (cmd.type == S9xNoMapping) { - config->window_width = 256; - config->window_height = 224; + b = Binding(event->keyval, false, false, false); + cmd = S9xGetMapping(b.hex()); } - default_cursor = gdk_cursor_new_for_display (gdk_display_get_default (),GDK_LEFT_PTR); - gdk_window_set_cursor (gtk_widget_get_window (window), default_cursor); + if (cmd.type != S9xNoMapping) + { + S9xReportButton(b.hex(), (event->type == GDK_KEY_PRESS)); + return true; + } - resize (config->window_width, config->window_height); + return false; // Pass the key to GTK } extern int gtk_splash_smtpe_size; @@ -697,14 +459,14 @@ void Snes9xWindow::setup_splash() { uint16 *screen_ptr = GFX.Screen; - /* Load splash image (RGB24) into Snes9x buffer (RGB15) */ + // Load splash image (RGB24) into Snes9x buffer (RGB15) last_width = 256; last_height = 224; if (config->splash_image == SPLASH_IMAGE_PATTERN || config->splash_image == SPLASH_IMAGE_SMTPE || config->splash_image == SPLASH_IMAGE_COMBO) { - unsigned char *pattern = NULL; + unsigned char *pattern = nullptr; int pattern_size = 0; if (config->splash_image == SPLASH_IMAGE_PATTERN) { @@ -718,9 +480,9 @@ void Snes9xWindow::setup_splash() pattern_size = gtk_splash_combo_size; } - auto pixbuf_loader = gdk_pixbuf_loader_new_with_type("png", NULL); - gdk_pixbuf_loader_write(pixbuf_loader, pattern, pattern_size, NULL); - gdk_pixbuf_loader_close(pixbuf_loader, NULL); + auto pixbuf_loader = gdk_pixbuf_loader_new_with_type("png", nullptr); + gdk_pixbuf_loader_write(pixbuf_loader, pattern, pattern_size, nullptr); + gdk_pixbuf_loader_close(pixbuf_loader, nullptr); auto pixbuf = gdk_pixbuf_loader_get_pixbuf(pixbuf_loader); const unsigned char *splash_ptr = gdk_pixbuf_get_pixels(pixbuf); const int channels = gdk_pixbuf_get_n_channels(pixbuf); @@ -765,9 +527,11 @@ void Snes9xWindow::setup_splash() } } -void -Snes9xWindow::expose () +bool Snes9xWindow::draw(const Cairo::RefPtr &cr) { + this->cr = cr->cobj(); + cairo_owned = false; + if (!(config->fullscreen) && !(maximized_state)) { config->window_width = get_width(); @@ -779,717 +543,493 @@ Snes9xWindow::expose () setup_splash(); } - S9xDisplayRefresh (last_width, last_height); + S9xDisplayRefresh(last_width, last_height); if (!(config->fullscreen)) { - config->window_width = get_width (); - config->window_height = get_height (); + config->window_width = get_width(); + config->window_height = get_height(); } - if ((is_paused () || NetPlay.Paused) && (gui_config->splash_image < SPLASH_IMAGE_STARFIELD || gui_config->rom_loaded)) + if ((is_paused() || NetPlay.Paused) && (gui_config->splash_image < SPLASH_IMAGE_STARFIELD || gui_config->rom_loaded)) { - S9xDeinitUpdate (last_width, last_height); + S9xDeinitUpdate(last_width, last_height); } + + this->cr = nullptr; + + return true; } -void -Snes9xWindow::focus_notify (bool state) +void Snes9xWindow::focus_notify(bool state) { focused = state; if (!state && config->pause_emulation_on_switch) { sys_pause++; - propagate_pause_state (); + propagate_pause_state(); paused_from_focus_loss = true; } if (state && paused_from_focus_loss) { - unpause_from_focus_change (); + unpause_from_focus_change(); paused_from_focus_loss = false; } } -void -Snes9xWindow::open_multicart_dialog () +void Snes9xWindow::open_multicart_dialog() { int result; - GtkBuilderWindow *dialog = new GtkBuilderWindow ("multicart_dialog"); - GtkFileChooser *slota, *slotb; - GtkWidget *multicart_dialog = GTK_WIDGET (dialog->get_window ()); + GtkBuilderWindow dialog_builder("multicart_dialog"); + auto dialog = Glib::RefPtr::cast_static(dialog_builder.window); - gtk_window_set_transient_for (dialog->get_window (), get_window ()); + dialog->set_transient_for(*window.get()); - pause_from_focus_change (); + pause_from_focus_change(); - slota = GTK_FILE_CHOOSER (dialog->get_widget ("multicart_slota")); - slotb = GTK_FILE_CHOOSER (dialog->get_widget ("multicart_slotb")); + auto slota = get_object("multicart_slota"); + auto slotb = get_object("multicart_slotb"); - gtk_file_chooser_set_current_folder (slota, config->last_directory.c_str ()); - gtk_file_chooser_set_current_folder (slotb, config->last_directory.c_str ()); + slota->set_current_folder(config->last_directory); + slotb->set_current_folder(config->last_directory); - result = gtk_dialog_run (GTK_DIALOG (multicart_dialog)); - - gtk_widget_hide (multicart_dialog); + result = dialog->run(); + dialog->hide(); if (result == GTK_RESPONSE_OK) { - const gchar *filename; - - filename = gtk_file_chooser_get_filename (slota); - if (filename) - strncpy (Settings.CartAName, filename, PATH_MAX); + auto filename = slota->get_filename(); + if (!filename.empty()) + strncpy(Settings.CartAName, filename.c_str(), PATH_MAX); else Settings.CartAName[0] = '\0'; - filename = gtk_file_chooser_get_filename (slotb); - if (filename) - strncpy (Settings.CartBName, filename, PATH_MAX); + filename = slotb->get_filename(); + if (!filename.empty()) + strncpy(Settings.CartBName, filename.c_str(), PATH_MAX); else Settings.CartBName[0] = '\0'; Settings.Multi = true; - if (S9xOpenROM (NULL)) + if (S9xOpenROM(nullptr)) { - GtkWidget *msg; - - msg = gtk_message_dialog_new (GTK_WINDOW (this->window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - _("Couldn't load files.")); - gtk_window_set_title (GTK_WINDOW (msg), _("Error")); - gtk_dialog_run (GTK_DIALOG (msg)); - gtk_widget_destroy (msg); + auto msg = Gtk::MessageDialog(*window.get(), + _("Couldn't load files."), + false, + Gtk::MESSAGE_ERROR, + Gtk::BUTTONS_CLOSE, + true); + msg.run(); } } - delete dialog; - - unpause_from_focus_change (); + unpause_from_focus_change(); } -const char * -Snes9xWindow::open_movie_dialog (bool readonly) +std::string Snes9xWindow::open_movie_dialog(bool readonly) { - GtkWidget *dialog; - GtkFileFilter *filter; - char *filename; - gint result; - const char *extensions[] = - { - "*.smv", "*.SMV", - NULL - }; - this->pause_from_focus_change (); + this->pause_from_focus_change(); + + std::string title; + Gtk::FileChooserAction action; if (readonly) { - dialog = gtk_file_chooser_dialog_new (_("Open SNES Movie"), - GTK_WINDOW (this->window), - GTK_FILE_CHOOSER_ACTION_OPEN, - "gtk-cancel", GTK_RESPONSE_CANCEL, - "gtk-open", GTK_RESPONSE_ACCEPT, - NULL); + title = _("Open SNES Movie"); + action = Gtk::FILE_CHOOSER_ACTION_OPEN; } else { - char def[PATH_MAX]; - char default_name[PATH_MAX]; - char drive[_MAX_DRIVE]; - char dir[_MAX_DIR]; - char ext[_MAX_EXT]; + title = _("New SNES Movie"); + action = Gtk::FILE_CHOOSER_ACTION_SAVE; + } - _splitpath (Memory.ROMFilename, drive, dir, def, ext); + Gtk::FileChooserDialog dialog(*window.get(), title, action); + dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); + if (readonly) + dialog.add_button(Gtk::StockID("gtk-open"), Gtk::RESPONSE_ACCEPT); + else + dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_ACCEPT); - snprintf (default_name, PATH_MAX, "%s.smv", def); - - dialog = gtk_file_chooser_dialog_new (_("New SNES Movie"), - GTK_WINDOW (this->window), - GTK_FILE_CHOOSER_ACTION_SAVE, - "gtk-cancel", GTK_RESPONSE_CANCEL, - "gtk-open", GTK_RESPONSE_ACCEPT, - NULL); - - gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), - default_name); + if (!readonly) + { + const char *default_name = S9xGetFilename(".smv", s9x_getdirtype::ROM_DIR); + dialog.set_current_name(default_name); } - filter = gtk_file_filter_new (); - gtk_file_filter_set_name (filter, _("SNES Movies")); + auto filter = Gtk::FileFilter::create(); + filter->set_name(_("SNES Movies")); + filter->add_pattern("*.smv"); + filter->add_pattern("*.SMV"); + dialog.add_filter(filter); + dialog.add_filter(get_all_files_filter()); + + dialog.set_current_folder(S9xGetDirectory(SRAM_DIR)); + auto result = dialog.run(); + dialog.hide(); + this->unpause_from_focus_change(); + + if (result == Gtk::RESPONSE_ACCEPT) + return dialog.get_filename(); + + return std::string{}; +} + +std::string Snes9xWindow::open_rom_dialog(bool run) +{ + const char *extensions[] = { + "*.smc", "*.SMC", "*.fig", "*.FIG", "*.sfc", "*.SFC", + "*.jma", "*.JMA", "*.zip", "*.ZIP", "*.gd3", "*.GD3", + "*.swc", "*.SWC", "*.gz", "*.GZ", "*.bs", "*.BS", + NULL + }; + + pause_from_focus_change(); + + auto dialog = Gtk::FileChooserDialog(*top_level->window.get(), + _("Open SNES ROM Image")); + dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); + dialog.add_button(Gtk::StockID("gtk-open"), Gtk::RESPONSE_ACCEPT); + + auto filter = Gtk::FileFilter::create(); + filter->set_name(_("SNES ROM Images")); for (int i = 0; extensions[i]; i++) + filter->add_pattern(extensions[i]); + dialog.add_filter(filter); + dialog.add_filter(get_all_files_filter()); + + if (!gui_config->last_directory.empty()) + dialog.set_current_folder(config->last_directory); + + auto result = dialog.run(); + dialog.hide(); + + std::string filename; + + if (result == Gtk::RESPONSE_ACCEPT) { - gtk_file_filter_add_pattern (filter, extensions[i]); - } - gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + std::string directory = dialog.get_current_folder(); - filter = gtk_file_filter_new (); - gtk_file_filter_set_name (filter, _("All Files")); - gtk_file_filter_add_pattern (filter, "*.*"); - gtk_file_filter_add_pattern (filter, "*"); - gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + if (!directory.empty()) + gui_config->last_directory = directory; - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), - S9xGetDirectory (SRAM_DIR)); + filename = dialog.get_filename(); - result = gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_hide (dialog); - - if (result == GTK_RESPONSE_ACCEPT) - { - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - } - else - { - filename = strdup (""); + if (!filename.empty()) + { + if (run) + { + Settings.Multi = false; + try_open_rom(filename); + } + } } - gtk_widget_destroy (dialog); - - this->unpause_from_focus_change (); - + unpause_from_focus_change(); return filename; } -void -Snes9xWindow::open_rom_dialog () +bool Snes9xWindow::try_open_rom(std::string filename) { - char *filename; - - pause_from_focus_change (); - - filename = S9xOpenROMDialog (); - - if (filename) - { - Settings.Multi = false; - try_open_rom (filename); - - g_free (filename); - } - - unpause_from_focus_change (); -} - -bool Snes9xWindow::try_open_rom(const char *filename) -{ - pause_from_focus_change (); + pause_from_focus_change(); Settings.Multi = false; - if (S9xOpenROM (filename)) + if (S9xOpenROM(filename.c_str())) { - GtkWidget *msg; - - msg = gtk_message_dialog_new (GTK_WINDOW (this->window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - _("Couldn't load file '%s'"), - filename); - gtk_window_set_title (GTK_WINDOW (msg), _("Error")); - gtk_dialog_run (GTK_DIALOG (msg)); - gtk_widget_destroy (msg); - - unpause_from_focus_change (); - + std::string message = _("Couldn't load file: ") + filename; + Gtk::MessageDialog msg(*window.get(), message, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true); + msg.run(); + unpause_from_focus_change(); return false; } - else - { - const char *groups[] = { "cartridge", NULL }; - GtkRecentData recent_data = - { - NULL, - (gchar *) "SNES ROM", - (gchar *) "application/x-snes-rom", - (gchar *) "Snes9x", - NULL, - (gchar **) groups, - false - }; - gchar *u_filename; + Gtk::RecentManager::Data data; + data.description = "SNES ROM"; + data.mime_type = "application/x-snes-rom"; + data.app_name = "Snes9x"; + data.groups = { "cartridge" }; + data.is_private = false; + data.app_exec = Glib::get_prgname() + " %f"; + Glib::filename_to_uri(filename); + Gtk::RecentManager::get_default()->add_item(filename, data); - u_filename = g_filename_to_uri (filename, NULL, NULL); - - recent_data.app_exec = g_strjoin (" ", - g_get_prgname (), - "%f", - NULL); - - gtk_recent_manager_add_full (gtk_recent_manager_get_default (), - u_filename, - &recent_data); - - g_free (recent_data.app_exec); - g_free (u_filename); - - this->unpause_from_user (); - - } - - this->unpause_from_focus_change (); + unpause_from_user(); + unpause_from_focus_change(); return true; } -void -Snes9xWindow::load_state_dialog () +void Snes9xWindow::load_state_dialog() { - GtkWidget *dialog; - GtkFileFilter *filter; - char *filename; - gint result; + this->pause_from_focus_change(); - this->pause_from_focus_change (); + Gtk::FileChooserDialog dialog(*window.get(), _("Load Saved State")); + dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); + dialog.add_button(Gtk::StockID("gtk-open"), Gtk::RESPONSE_ACCEPT); - dialog = gtk_file_chooser_dialog_new (_("Load Saved State"), - GTK_WINDOW (this->window), - GTK_FILE_CHOOSER_ACTION_OPEN, - "gtk-cancel", GTK_RESPONSE_CANCEL, - "gtk-open", GTK_RESPONSE_ACCEPT, - NULL); + dialog.add_filter(get_save_states_file_filter()); + dialog.add_filter(get_all_files_filter()); + dialog.set_current_folder(S9xGetDirectory(SNAPSHOT_DIR)); - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), - S9xGetDirectory (SNAPSHOT_DIR)); - - filter = gtk_file_filter_new (); - gtk_file_filter_set_name (filter, _("Save States")); - gtk_file_filter_add_pattern (filter, "*.sst"); - gtk_file_filter_add_pattern (filter, "*.zst"); - gtk_file_filter_add_pattern (filter, "*.ZST"); - gtk_file_filter_add_pattern (filter, "*.000"); - gtk_file_filter_add_pattern (filter, "*.001"); - gtk_file_filter_add_pattern (filter, "*.002"); - gtk_file_filter_add_pattern (filter, "*.003"); - gtk_file_filter_add_pattern (filter, "*.004"); - gtk_file_filter_add_pattern (filter, "*.005"); - gtk_file_filter_add_pattern (filter, "*.006"); - gtk_file_filter_add_pattern (filter, "*.007"); - gtk_file_filter_add_pattern (filter, "*.008"); - gtk_file_filter_add_pattern (filter, "*.009"); - gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); - - filter = gtk_file_filter_new (); - gtk_file_filter_set_name (filter, _("All Files")); - gtk_file_filter_add_pattern (filter, "*.*"); - gtk_file_filter_add_pattern (filter, "*"); - gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); - - result = gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_hide (dialog); - - if (result == GTK_RESPONSE_ACCEPT) + auto result = dialog.run(); + dialog.hide(); + if (result == Gtk::RESPONSE_ACCEPT) { - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - - S9xLoadState (filename); - - g_free (filename); + S9xLoadState(dialog.get_filename().c_str()); } - else - { - } - - gtk_widget_destroy (dialog); - - this->unpause_from_focus_change (); + unpause_from_focus_change(); } -void -Snes9xWindow::movie_seek_dialog () +void Snes9xWindow::movie_seek_dialog() { - char str[1024]; - gint result; + char str[1024]; - if (!S9xMovieActive ()) + if (!S9xMovieActive()) return; - GtkBuilderWindow *seek_dialog = new GtkBuilderWindow ("frame_advance_dialog"); - GtkWindow *seek_window = seek_dialog->get_window (); + pause_from_focus_change(); - pause_from_focus_change (); + GtkBuilderWindow seek_dialog("frame_advance_dialog"); - snprintf (str, 1024, _("The current frame in the movie is %d."), S9xMovieGetFrameCounter ()); - gtk_label_set_label (GTK_LABEL (seek_dialog->get_widget ("current_frame_label")), str); + snprintf(str, 1024, _("The current frame in the movie is %d."), S9xMovieGetFrameCounter()); + seek_dialog.get_object("current_frame_label")->set_label(str); - snprintf (str, 1024, "%d", S9xMovieGetFrameCounter ()); - seek_dialog->set_entry_text ("frame_entry", str); + snprintf(str, 1024, "%d", S9xMovieGetFrameCounter()); + seek_dialog.set_entry_text("frame_entry", str); - gtk_window_set_transient_for (seek_window, get_window ()); + auto dialog = Glib::RefPtr::cast_static(seek_dialog.window); - result = gtk_dialog_run (GTK_DIALOG (seek_window)); + dialog->set_transient_for(*window.get()); + auto result = dialog->run(); - int entry_value = seek_dialog->get_entry_value ("frame_entry"); + int entry_value = seek_dialog.get_entry_value("frame_entry"); switch (result) { - case GTK_RESPONSE_OK: + case Gtk::RESPONSE_OK: + if (entry_value > 0 && + entry_value > (int)S9xMovieGetFrameCounter()) + { + Settings.HighSpeedSeek = + entry_value - S9xMovieGetFrameCounter(); + } - if (entry_value > 0 && - entry_value > (int) S9xMovieGetFrameCounter ()) - { - Settings.HighSpeedSeek = - entry_value - S9xMovieGetFrameCounter (); - } - - break; + break; } - delete seek_dialog; - - unpause_from_focus_change (); + unpause_from_focus_change(); } -void -Snes9xWindow::save_state_dialog () +void Snes9xWindow::save_state_dialog() { - GtkWidget *dialog; - GtkFileFilter *filter; - char *filename; - gint result; - char def[PATH_MAX]; - char default_name[PATH_MAX]; - char drive[_MAX_DRIVE]; - char dir[_MAX_DIR]; - char ext[_MAX_EXT]; + pause_from_focus_change(); - this->pause_from_focus_change (); + auto dialog = Gtk::FileChooserDialog(*window.get(), _("Save State"), Gtk::FILE_CHOOSER_ACTION_SAVE); + dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); + dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_ACCEPT); + dialog.set_current_folder(S9xGetDirectory(SNAPSHOT_DIR)); + dialog.set_current_name(S9xGetFilename(".sst", SNAPSHOT_DIR)); + dialog.add_filter(get_save_states_file_filter()); + dialog.add_filter(get_all_files_filter()); - _splitpath (Memory.ROMFilename, drive, dir, def, ext); - - snprintf (default_name, PATH_MAX, "%s.sst", def); - - dialog = gtk_file_chooser_dialog_new (_("Save State"), - GTK_WINDOW (this->window), - GTK_FILE_CHOOSER_ACTION_SAVE, - "gtk-cancel", GTK_RESPONSE_CANCEL, - "gtk-save", GTK_RESPONSE_ACCEPT, - NULL); - - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), - S9xGetDirectory (SNAPSHOT_DIR)); - gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), - default_name); - - filter = gtk_file_filter_new (); - gtk_file_filter_set_name (filter, _("Save States")); - gtk_file_filter_add_pattern (filter, "*.sst"); - gtk_file_filter_add_pattern (filter, "*.zst"); - gtk_file_filter_add_pattern (filter, "*.ZST"); - gtk_file_filter_add_pattern (filter, "*.000"); - gtk_file_filter_add_pattern (filter, "*.001"); - gtk_file_filter_add_pattern (filter, "*.002"); - gtk_file_filter_add_pattern (filter, "*.003"); - gtk_file_filter_add_pattern (filter, "*.004"); - gtk_file_filter_add_pattern (filter, "*.005"); - gtk_file_filter_add_pattern (filter, "*.006"); - gtk_file_filter_add_pattern (filter, "*.007"); - gtk_file_filter_add_pattern (filter, "*.008"); - gtk_file_filter_add_pattern (filter, "*.009"); - gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); - - filter = gtk_file_filter_new (); - gtk_file_filter_set_name (filter, _("All Files")); - gtk_file_filter_add_pattern (filter, "*.*"); - gtk_file_filter_add_pattern (filter, "*"); - gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); - - result = gtk_dialog_run (GTK_DIALOG (dialog)); - - gtk_widget_hide (dialog); + auto result = dialog.run(); + dialog.hide(); if (result == GTK_RESPONSE_ACCEPT) - { - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + S9xSaveState(dialog.get_filename().c_str()); - S9xSaveState (filename); - - g_free (filename); - } - - else - { - } - - gtk_widget_destroy (dialog); - - this->unpause_from_focus_change (); + unpause_from_focus_change(); } -void -Snes9xWindow::save_spc_dialog () +void Snes9xWindow::save_spc_dialog() { - GtkWidget *dialog; - GtkFileFilter *filter; - char *filename; - gint result; - char def[PATH_MAX]; - char default_name[PATH_MAX]; - char drive[_MAX_DRIVE]; - char dir[_MAX_DIR]; - char ext[_MAX_EXT]; + pause_from_focus_change(); - this->pause_from_focus_change (); + auto dialog = Gtk::FileChooserDialog(*window.get(), _("Save SPC file..."), Gtk::FILE_CHOOSER_ACTION_SAVE); + dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); + dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_ACCEPT); + dialog.set_current_folder(S9xGetDirectory(SNAPSHOT_DIR)); + dialog.set_current_name(S9xGetFilename(".spc", SNAPSHOT_DIR)); + auto filter = Gtk::FileFilter::create(); + filter->add_pattern("*.spc"); + filter->add_pattern("*.SPC"); + dialog.add_filter(filter); + dialog.add_filter(get_all_files_filter()); - _splitpath (Memory.ROMFilename, drive, dir, def, ext); + auto result = dialog.run(); + dialog.hide(); - snprintf (default_name, PATH_MAX, "%s.spc", def); - - dialog = gtk_file_chooser_dialog_new (_("Save SPC file..."), - GTK_WINDOW (this->window), - GTK_FILE_CHOOSER_ACTION_SAVE, - "gtk-cancel", GTK_RESPONSE_CANCEL, - "gtk-save", GTK_RESPONSE_ACCEPT, - NULL); - - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), - S9xGetDirectory (SNAPSHOT_DIR)); - gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), - default_name); - - filter = gtk_file_filter_new (); - gtk_file_filter_set_name (filter, _("SPC Files")); - gtk_file_filter_add_pattern (filter, "*.spc"); - gtk_file_filter_add_pattern (filter, "*.SPC"); - gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); - - filter = gtk_file_filter_new (); - gtk_file_filter_set_name (filter, _("All Files")); - gtk_file_filter_add_pattern (filter, "*.*"); - gtk_file_filter_add_pattern (filter, "*"); - gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); - - result = gtk_dialog_run (GTK_DIALOG (dialog)); - - gtk_widget_hide (dialog); - - if (result == GTK_RESPONSE_ACCEPT) + if (result == Gtk::RESPONSE_ACCEPT) { - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - - if (S9xSPCDump (filename)) + if (S9xSPCDump(dialog.get_filename().c_str())) { /* Success ? */ } else { - GtkWidget *msg; - - msg = gtk_message_dialog_new (GTK_WINDOW (this->window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - _("Couldn't save SPC file '%s'"), - filename); - gtk_window_set_title (GTK_WINDOW (msg), _("Error")); - gtk_dialog_run (GTK_DIALOG (msg)); - gtk_widget_destroy (msg); + std::string message = _("Couldn't save SPC file:"); + message += " " + dialog.get_filename(); + Gtk::MessageDialog(*window.get(), message, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true).run(); } - - g_free (filename); } - else - { - } - - gtk_widget_destroy (dialog); - - this->unpause_from_focus_change (); + unpause_from_focus_change(); } -void -Snes9xWindow::set_menu_item_selected (const char *name) +void Snes9xWindow::set_menu_item_selected(const char *name) { - GtkCheckMenuItem *item; - - item = GTK_CHECK_MENU_ITEM (get_widget (name)); - - gtk_check_menu_item_set_active (item, 1); + get_object(name)->set_active(true); } -void -Snes9xWindow::show_rom_info () +void Snes9xWindow::show_rom_info() { - GtkWidget *msg; +const char *markup = _(R"(Information for %s - pause_from_focus_change (); +Name: %s +Speed: %02X/%s +Map: %s +Type: %02x +Contents: %s +ROM Size: %s +Calculated Size: %d +SRAM Size: %s +Header Checksum: %04X +Checksum Compliment: %04X +Actual Checksum: %04X +Video: %s +CRC32: %08X +Revision: %s +%s%s)"); + char output[2048]; - msg = gtk_message_dialog_new_with_markup (GTK_WINDOW (window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_OTHER, - GTK_BUTTONS_CLOSE, - _("Information for %s\n\n" - "Name: %s\n" - "Speed: %02X/%s\n" - "Map: %s\n" - "Type: %02x\n" - "Contents: %s\n" - "ROM Size: %s\n" - "Calculated Size: %d\n" - "SRAM Size: %s\n" - "Header Checksum: %04X\n" - "Checksum Compliment: %04X\n" - "Actual Checksum: %04X\n" - "Video: %s\n" - "CRC32: %08X\n" - "Revision: %s" - "%s%s"), - Memory.ROMFilename, - Memory.ROMName, - Memory.ROMSpeed, - ((Memory.ROMSpeed & 0x10) != 0) ? - "FastROM" : "SlowROM", - (Memory.HiROM) ? - "HiROM" : "LoROM", - Memory.ROMType, - Memory.KartContents (), - Memory.Size (), - Memory.CalculatedSize / 0x20000, - Memory.StaticRAMSize (), - Memory.ROMChecksum, - Memory.ROMComplementChecksum, - Memory.CalculatedChecksum, - (Memory.ROMRegion > 12 || - Memory.ROMRegion < 2) ? - "NTSC 60Hz" : "PAL 50Hz", - Memory.ROMCRC32, - Memory.Revision (), - (Settings.IsPatched) ? _("\n\nThis ROM has been auto-patched with ") : - (Memory.ROMChecksum != - Memory.CalculatedChecksum) ? - _("\n\nThis ROM has been modified or damaged") - : "", - Settings.IsPatched == 1 ? "IPS" : - Settings.IsPatched == 2 ? "BPS" : - Settings.IsPatched == 3 ? "UPS" : - ""); - gtk_window_set_title (GTK_WINDOW (msg), _("File Information")); + snprintf(output, 2048, markup, + Memory.ROMFilename, + Memory.ROMName, + Memory.ROMSpeed, + ((Memory.ROMSpeed & 0x10) != 0) ? "FastROM" : "SlowROM", + (Memory.HiROM) ? "HiROM" : "LoROM", + Memory.ROMType, + Memory.KartContents(), + Memory.Size(), + Memory.CalculatedSize / 0x20000, + Memory.StaticRAMSize(), + Memory.ROMChecksum, + Memory.ROMComplementChecksum, + Memory.CalculatedChecksum, + (Memory.ROMRegion > 12 || Memory.ROMRegion < 2) ? "NTSC 60Hz" : "PAL 50Hz", + Memory.ROMCRC32, + Memory.Revision(), + (Settings.IsPatched) ? _("\n\nThis ROM has been auto-patched with ") : (Memory.ROMChecksum != Memory.CalculatedChecksum) ? _("\n\nThis ROM has been modified or damaged") : "", + Settings.IsPatched == 1 ? "IPS" : Settings.IsPatched == 2 ? "BPS" : Settings.IsPatched == 3 ? "UPS" : ""); - gtk_dialog_run (GTK_DIALOG (msg)); + pause_from_focus_change(); - unpause_from_focus_change (); + auto dialog = Gtk::MessageDialog(*window.get(), output, true, Gtk::MESSAGE_OTHER, Gtk::BUTTONS_CLOSE, true); + dialog.set_title(_("File Information")); + dialog.run(); - gtk_widget_destroy (msg); + unpause_from_focus_change(); } -void -Snes9xWindow::configure_widgets () +void Snes9xWindow::configure_widgets() { - enable_widget ("continue_item", config->rom_loaded); - enable_widget ("pause_item", config->rom_loaded); - enable_widget ("reset_item", config->rom_loaded); - enable_widget ("load_state_item", config->rom_loaded); - enable_widget ("save_state_item", config->rom_loaded); - enable_widget ("save_spc_item", config->rom_loaded); - enable_widget ("hard_reset_item", config->rom_loaded); - enable_widget ("record_movie_item", config->rom_loaded); - enable_widget ("stop_recording_item", config->rom_loaded); - enable_widget ("open_movie_item", config->rom_loaded); - enable_widget ("jump_to_frame_item", config->rom_loaded); - enable_widget ("cheats_item", config->rom_loaded); - enable_widget ("rom_info_item", config->rom_loaded); + enable_widget("continue_item", config->rom_loaded); + enable_widget("pause_item", config->rom_loaded); + enable_widget("reset_item", config->rom_loaded); + enable_widget("load_state_item", config->rom_loaded); + enable_widget("save_state_item", config->rom_loaded); + enable_widget("save_spc_item", config->rom_loaded); + enable_widget("hard_reset_item", config->rom_loaded); + enable_widget("record_movie_item", config->rom_loaded); + enable_widget("stop_recording_item", config->rom_loaded); + enable_widget("open_movie_item", config->rom_loaded); + enable_widget("jump_to_frame_item", config->rom_loaded); + enable_widget("cheats_item", config->rom_loaded); + enable_widget("rom_info_item", config->rom_loaded); - enable_widget ("sync_clients_item", - config->rom_loaded && - Settings.NetPlay && - Settings.NetPlayServer); + enable_widget("sync_clients_item", + config->rom_loaded && + Settings.NetPlay && + Settings.NetPlayServer); if (config->default_esc_behavior != ESC_TOGGLE_MENUBAR) { - enable_widget ("fullscreen_item", config->rom_loaded); + enable_widget("fullscreen_item", config->rom_loaded); config->ui_visible = true; - if (!config->fullscreen) - { - gtk_widget_show (get_widget ("menubar")); - } - else - { - gtk_widget_hide (get_widget ("menubar")); - } - - gtk_widget_hide (get_widget ("hide_ui")); - gtk_widget_hide (get_widget ("hide_ui_separator")); + show_widget("menubar", !config->fullscreen); + show_widget("hide_ui", false); + show_widget("hide_ui_separator", false); } else { - enable_widget ("fullscreen_item", true); + enable_widget("fullscreen_item", true); - gtk_widget_show (get_widget ("hide_ui")); - gtk_widget_show (get_widget ("hide_ui_separator")); - - if (config->ui_visible) - { - gtk_widget_show (get_widget ("menubar")); - } - else - { - gtk_widget_hide (get_widget ("menubar")); - } + show_widget("hide_ui", true); + show_widget("hide_ui_separator", true); + show_widget("menubar", config->ui_visible); } - propagate_pause_state (); + propagate_pause_state(); if (config->rom_loaded && !Settings.Paused) - hide_mouse_cursor (); + hide_mouse_cursor(); else - show_mouse_cursor (); + show_mouse_cursor(); } -void -Snes9xWindow::set_mouseable_area (int x, int y, int width, int height) +void Snes9xWindow::set_mouseable_area(int x, int y, int width, int height) { - mouse_region_x = x; - mouse_region_y = y; - mouse_region_width = width; + mouse_region_x = x; + mouse_region_y = y; + mouse_region_width = width; mouse_region_height = height; } -void -Snes9xWindow::reset_screensaver () +void Snes9xWindow::reset_screensaver() { if (!focused) return; + GdkWindow *gdk_window = window->get_window()->gobj(); + GdkDisplay *gdk_display = window->get_display()->gobj(); + #ifdef GDK_WINDOWING_X11 - if (GDK_IS_X11_WINDOW (gtk_widget_get_window (GTK_WIDGET (window)))) + if (GDK_IS_X11_WINDOW(gdk_window)) { - XResetScreenSaver (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ())); + XResetScreenSaver(GDK_DISPLAY_XDISPLAY(gdk_display)); } #endif #ifdef GDK_WINDOWING_WAYLAND - if (GDK_IS_WAYLAND_WINDOW (gtk_widget_get_window (GTK_WIDGET (window)))) + if (GDK_IS_WAYLAND_WINDOW(gdk_window)) { - // TODO screensaver for wayland + // TODO screensaver for wayland } #endif config->screensaver_needs_reset = false; } -void -Snes9xWindow::toggle_fullscreen_mode () +void Snes9xWindow::toggle_fullscreen_mode() { if (config->fullscreen) - leave_fullscreen_mode (); + leave_fullscreen_mode(); else - enter_fullscreen_mode (); + enter_fullscreen_mode(); } -static double XRRGetExactRefreshRate (Display *dpy, Window window) +static double XRRGetExactRefreshRate(Display *dpy, Window window) { - XRRScreenResources *resources = NULL; - XRRCrtcInfo *crtc_info = NULL; + XRRScreenResources *resources = nullptr; + XRRCrtcInfo *crtc_info = nullptr; int event_base; int error_base; int version_major; @@ -1497,8 +1037,8 @@ static double XRRGetExactRefreshRate (Display *dpy, Window window) double refresh_rate = 0.0; int i; - if (!XRRQueryExtension (dpy, &event_base, &error_base) || - !XRRQueryVersion (dpy, &version_major, &version_minor)) + if (!XRRQueryExtension(dpy, &event_base, &error_base) || + !XRRQueryVersion(dpy, &version_major, &version_minor)) { return refresh_rate; } @@ -1506,8 +1046,8 @@ static double XRRGetExactRefreshRate (Display *dpy, Window window) if (version_minor < 3) return refresh_rate; - resources = XRRGetScreenResourcesCurrent (dpy, window); - crtc_info = XRRGetCrtcInfo (dpy, resources, resources->crtcs[0]); + resources = XRRGetScreenResourcesCurrent(dpy, window); + crtc_info = XRRGetCrtcInfo(dpy, resources, resources->crtcs[0]); for (i = 0; i < resources->nmode; i++) { @@ -1515,60 +1055,59 @@ static double XRRGetExactRefreshRate (Display *dpy, Window window) { XRRModeInfo *m = &resources->modes[i]; - refresh_rate = (double) m->dotClock / m->hTotal / m->vTotal; - refresh_rate /= m->modeFlags & RR_DoubleScan ? 2 : 1; + refresh_rate = (double)m->dotClock / m->hTotal / m->vTotal; + refresh_rate /= m->modeFlags & RR_DoubleScan ? 2 : 1; refresh_rate /= m->modeFlags & RR_ClockDivideBy2 ? 2 : 1; - refresh_rate *= m->modeFlags & RR_DoubleClock ? 2 : 1; + refresh_rate *= m->modeFlags & RR_DoubleClock ? 2 : 1; break; } } - XRRFreeCrtcInfo (crtc_info); - XRRFreeScreenResources (resources); + XRRFreeCrtcInfo(crtc_info); + XRRFreeScreenResources(resources); return refresh_rate; } double -Snes9xWindow::get_refresh_rate () +Snes9xWindow::get_refresh_rate() { double refresh_rate = 0.0; #if defined GDK_WINDOWING_X11 || defined GDK_WINDOWING_WAYLAND - GdkDisplay *display = gtk_widget_get_display (window); + GdkDisplay *gdk_display = window->get_display()->gobj(); + GdkWindow *gdk_window = window->get_window()->gobj(); #endif #ifdef GDK_WINDOWING_X11 - if (GDK_IS_X11_DISPLAY (display)) + if (GDK_IS_X11_DISPLAY(gdk_display)) { - Window xid = gdk_x11_window_get_xid (gtk_widget_get_window (window)); - Display *dpy = gdk_x11_display_get_xdisplay (gtk_widget_get_display (window)); - refresh_rate = XRRGetExactRefreshRate (dpy, xid); + Window xid = gdk_x11_window_get_xid(gdk_window); + Display *dpy = gdk_x11_display_get_xdisplay(gdk_display); + refresh_rate = XRRGetExactRefreshRate(dpy, xid); } #endif #ifdef GDK_WINDOWING_WAYLAND - if (GDK_IS_WAYLAND_DISPLAY (display)) + if (GDK_IS_WAYLAND_DISPLAY(gdk_display)) { - GdkWindow *gdk_window = gtk_widget_get_window (window); - GdkMonitor *monitor = gdk_display_get_monitor_at_window(display, gdk_window); - refresh_rate = (double) gdk_monitor_get_refresh_rate(monitor) / 1000.0; + GdkMonitor *monitor = gdk_display_get_monitor_at_window(gdk_display, gdk_window); + refresh_rate = (double)gdk_monitor_get_refresh_rate(monitor) / 1000.0; } #endif if (refresh_rate < 10.0) { - printf ("Warning: Couldn't read refresh rate.\n"); + printf("Warning: Couldn't read refresh rate.\n"); refresh_rate = 60.0; } return refresh_rate; } -int -Snes9xWindow::get_auto_input_rate () +int Snes9xWindow::get_auto_input_rate() { - double refresh_rate = get_refresh_rate (); + double refresh_rate = get_refresh_rate(); if (refresh_rate == 0.0) return 0; @@ -1590,69 +1129,73 @@ Snes9xWindow::get_auto_input_rate () } #ifdef GDK_WINDOWING_X11 -static void set_bypass_compositor (Display *dpy, Window window, unsigned char bypass) +static void set_bypass_compositor(Display *dpy, Window window, unsigned char bypass) { uint32 value = bypass; - Atom net_wm_bypass_compositor = XInternAtom (dpy, "_NET_WM_BYPASS_COMPOSITOR", False); - XChangeProperty (dpy, window, net_wm_bypass_compositor, XA_CARDINAL, 32, PropModeReplace, (const unsigned char *) &value, 1); + Atom net_wm_bypass_compositor = XInternAtom(dpy, "_NET_WM_BYPASS_COMPOSITOR", False); + XChangeProperty(dpy, window, net_wm_bypass_compositor, XA_CARDINAL, 32, PropModeReplace, (const unsigned char *)&value, 1); } #endif -void -Snes9xWindow::enter_fullscreen_mode () +void Snes9xWindow::enter_fullscreen_mode() { int rom_loaded = config->rom_loaded; if (config->fullscreen) return; + GdkDisplay *gdk_display = window->get_display()->gobj(); + GdkWindow *gdk_window = window->get_window()->gobj(); + config->rom_loaded = 0; nfs_width = config->window_width; nfs_height = config->window_height; + int nfs_x; + int nfs_y; + window->get_position(nfs_x, nfs_y); - gtk_window_get_position (GTK_WINDOW (window), &nfs_x, &nfs_y); - - if (config->change_display_resolution) +#ifdef GDK_WINDOWING_X11 + if (config->change_display_resolution && GDK_IS_X11_WINDOW(gdk_window)) { - GdkDisplay *gdk_display = gtk_widget_get_display (window); - Display *dpy = gdk_x11_display_get_xdisplay (gdk_display); + Display *dpy = gdk_x11_display_get_xdisplay(gdk_display); - gdk_display_sync (gdk_display); - if (XRRSetCrtcConfig (dpy, - config->xrr_screen_resources, - config->xrr_screen_resources->crtcs[0], - CurrentTime, - config->xrr_crtc_info->x, - config->xrr_crtc_info->y, - config->xrr_screen_resources->modes[config->xrr_index].id, - config->xrr_crtc_info->rotation, - &config->xrr_crtc_info->outputs[0], - 1) != 0) + gdk_display_sync(gdk_display); + if (XRRSetCrtcConfig(dpy, + config->xrr_screen_resources, + config->xrr_screen_resources->crtcs[0], + CurrentTime, + config->xrr_crtc_info->x, + config->xrr_crtc_info->y, + config->xrr_screen_resources->modes[config->xrr_index].id, + config->xrr_crtc_info->rotation, + &config->xrr_crtc_info->outputs[0], + 1) != 0) { config->change_display_resolution = 0; } if (gui_config->auto_input_rate) { - Settings.SoundInputRate = top_level->get_auto_input_rate (); - S9xUpdateDynamicRate (1, 2); + Settings.SoundInputRate = top_level->get_auto_input_rate(); + S9xUpdateDynamicRate(1, 2); } } +#endif /* Make sure everything is done synchronously */ - gdk_display_sync (gdk_display_get_default ()); - gtk_window_fullscreen (GTK_WINDOW (window)); + gdk_display_sync(gdk_display); + window->fullscreen(); + gdk_display_sync(gdk_display); + window->present(); - gdk_display_sync (gdk_display_get_default ()); - gtk_window_present (GTK_WINDOW (window)); #ifdef GDK_WINDOWING_X11 - if (GDK_IS_X11_WINDOW (gtk_widget_get_window (GTK_WIDGET (window))) && + if (GDK_IS_X11_WINDOW(window->get_window()->gobj()) && config->default_esc_behavior != ESC_TOGGLE_MENUBAR) { - set_bypass_compositor (gdk_x11_display_get_xdisplay (gtk_widget_get_display (GTK_WIDGET (window))), - gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (window))), - 1); + set_bypass_compositor(gdk_x11_display_get_xdisplay(gdk_display), + gdk_x11_window_get_xid(gdk_window), + 1); } #endif config->fullscreen = 1; @@ -1662,201 +1205,151 @@ Snes9xWindow::enter_fullscreen_mode () if (!Settings.Paused && config->rom_loaded) config->ui_visible = false; - configure_widgets (); + configure_widgets(); } -void -Snes9xWindow::leave_fullscreen_mode () +void Snes9xWindow::leave_fullscreen_mode() { int rom_loaded = config->rom_loaded; if (!config->fullscreen) return; + GdkDisplay *gdk_display = window->get_display()->gobj(); + GdkWindow *gdk_window = window->get_window()->gobj(); + config->rom_loaded = 0; - if (config->change_display_resolution) +#ifdef GDK_WINDOWING_X11 + if (config->change_display_resolution && GDK_IS_X11_WINDOW(gdk_window)) { - GdkDisplay *gdk_display = gtk_widget_get_display (window); - Display *dpy = gdk_x11_display_get_xdisplay (gdk_display); + Display *dpy = gdk_x11_display_get_xdisplay(gdk_display); if (config->xrr_index > config->xrr_screen_resources->nmode) config->xrr_index = 0; - gdk_display_sync (gdk_display); - XRRSetCrtcConfig (dpy, - config->xrr_screen_resources, - config->xrr_screen_resources->crtcs[0], - CurrentTime, - config->xrr_crtc_info->x, - config->xrr_crtc_info->y, - config->xrr_crtc_info->mode, - config->xrr_crtc_info->rotation, - &config->xrr_crtc_info->outputs[0], - 1); + gdk_display_sync(gdk_display); + XRRSetCrtcConfig(dpy, + config->xrr_screen_resources, + config->xrr_screen_resources->crtcs[0], + CurrentTime, + config->xrr_crtc_info->x, + config->xrr_crtc_info->y, + config->xrr_crtc_info->mode, + config->xrr_crtc_info->rotation, + &config->xrr_crtc_info->outputs[0], + 1); if (gui_config->auto_input_rate) { - Settings.SoundInputRate = top_level->get_auto_input_rate (); - S9xUpdateDynamicRate (1, 2); + Settings.SoundInputRate = top_level->get_auto_input_rate(); + S9xUpdateDynamicRate(1, 2); } } - - gtk_window_unfullscreen (GTK_WINDOW (window)); - -#ifdef GDK_WINDOWING_X11 - if (GDK_IS_X11_WINDOW (gtk_widget_get_window (GTK_WIDGET (window)))) - { - set_bypass_compositor (gdk_x11_display_get_xdisplay (gtk_widget_get_display (GTK_WIDGET (window))), - gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (window))), - 0); - } #endif - resize (nfs_width, nfs_height); - gtk_window_move (GTK_WINDOW (window), nfs_x, nfs_y); + window->unfullscreen(); + +#ifdef GDK_WINDOWING_X11 + if (GDK_IS_X11_WINDOW(gdk_window)) + { + set_bypass_compositor(gdk_x11_display_get_xdisplay(gdk_display), + gdk_x11_window_get_xid(gdk_window), + 0); + } +#endif + + resize(nfs_width, nfs_height); + window->move(nfs_x, nfs_y); config->rom_loaded = rom_loaded; - config->fullscreen = 0; - - configure_widgets (); + configure_widgets(); } -void -Snes9xWindow::resize_viewport (int width, int height) +void Snes9xWindow::resize_viewport(int width, int height) { - GtkWidget *item; - GtkAllocation allocation; - int y_padding = 0; + auto menubar = get_object("menubar"); + if (menubar->get_visible()) + height += menubar->get_height(); - item = get_widget ("menubar"); - gtk_widget_get_allocation (item, &allocation); - y_padding += gtk_widget_get_visible (item) ? allocation.height : 0; - - resize (width, height + y_padding); + resize(width, height); } -void -Snes9xWindow::hide_mouse_cursor () +void Snes9xWindow::hide_mouse_cursor() { - if (!empty_cursor) - { - empty_cursor = gdk_cursor_new_for_display (gdk_display_get_default (), GDK_BLANK_CURSOR); - } - - gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (drawing_area)), - empty_cursor); + auto blank = Gdk::Cursor::create(Gdk::BLANK_CURSOR); + drawing_area->get_window()->set_cursor(blank); config->pointer_is_visible = false; } -void -Snes9xWindow::show_mouse_cursor () +void Snes9xWindow::show_mouse_cursor() { - gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (drawing_area)), - NULL); + auto left_ptr = Gdk::Cursor::create(Gdk::LEFT_PTR); + drawing_area->get_window()->set_cursor(left_ptr); config->pointer_is_visible = true; } -void -Snes9xWindow::center_mouse () +void Snes9xWindow::center_mouse() { - GdkWindow *gdk_window = gtk_widget_get_window (window); - GdkDisplay *gdk_display = gdk_window_get_display (gdk_window); - GdkScreen *gdk_screen = gdk_window_get_screen (gdk_window); - int x, y, w, h; + int x; + int y; - gdk_window_get_origin (gdk_window, &x, &y); - w = gdk_window_get_width (gdk_window); - h = gdk_window_get_height (gdk_window); + window->get_window()->get_origin(x, y); + int w = window->get_width(); + int h = window->get_height(); gdk_mouse_x = x + w / 2; gdk_mouse_y = y + h / 2; -#if GTK_MAJOR_VERSION < 3 - gdk_display_warp_pointer (gdk_display, gdk_screen, gdk_mouse_x, - gdk_mouse_y); -#else - GdkSeat *seat = gdk_display_get_default_seat (gdk_display); - GdkDevice *pointer = gdk_seat_get_pointer (seat); - - gdk_device_warp (pointer, gdk_screen, gdk_mouse_x, gdk_mouse_y); -#endif + window->get_display()->get_default_seat()->get_pointer()->warp(window->get_screen(), gdk_mouse_x, gdk_mouse_y); } -void -Snes9xWindow::toggle_grab_mouse () +void Snes9xWindow::toggle_grab_mouse() { - GdkWindow *gdk_window = gtk_widget_get_window (window); - GdkDisplay *gdk_display = gdk_window_get_display (gdk_window); - - if ((!mouse_grabbed && !S9xIsMousePluggedIn ()) || !config->rom_loaded) + if ((!mouse_grabbed && !S9xIsMousePluggedIn()) || !config->rom_loaded) return; -#if GTK_MAJOR_VERSION < 3 + auto seat = window->get_display()->get_default_seat(); if (!mouse_grabbed) - { - gdk_pointer_grab (gdk_window, true, (GdkEventMask) 1020, gdk_window, empty_cursor, GDK_CURRENT_TIME); - center_mouse (); - } + seat->grab(window->get_window(), Gdk::SEAT_CAPABILITY_ALL_POINTING, true, Gdk::Cursor::create(Gdk::BLANK_CURSOR)); else - { - gdk_pointer_ungrab (GDK_CURRENT_TIME); - if (config->pointer_is_visible) - show_mouse_cursor (); - } -#else - GdkSeat *seat = gdk_display_get_default_seat (gdk_display); + seat->ungrab(); - if (!mouse_grabbed) - gdk_seat_grab (seat, gdk_window, GDK_SEAT_CAPABILITY_ALL_POINTING, true, - empty_cursor, NULL, NULL, NULL); - else - gdk_seat_ungrab (seat); -#endif - - S9xReportPointer (BINDING_MOUSE_POINTER, 0, 0); - snes_mouse_x = 0.0; snes_mouse_y = 0.0; + S9xReportPointer(BINDING_MOUSE_POINTER, 0, 0); + snes_mouse_x = 0.0; + snes_mouse_y = 0.0; mouse_grabbed = !mouse_grabbed; if (mouse_grabbed) - center_mouse (); + center_mouse(); } -void -Snes9xWindow::show () +void Snes9xWindow::show() { - gtk_widget_show (window); + window->show(); + configure_widgets(); if (!recent_menu) { - /* Add recent menu after showing window to avoid "No items" bug */ - recent_menu = gtk_recent_chooser_menu_new_for_manager ( - gtk_recent_manager_get_default ()); + auto manager = Gtk::RecentManager::get_default(); + recent_menu = new Gtk::RecentChooserMenu(manager); - GtkRecentFilter *filter = gtk_recent_filter_new (); - GtkRecentChooser *chooser = GTK_RECENT_CHOOSER (recent_menu); + auto filter = Gtk::RecentFilter::create(); + filter->add_group("cartridge"); + recent_menu->add_filter(filter); + recent_menu->set_local_only(); + recent_menu->set_show_icons(false); + recent_menu->set_sort_type(Gtk::RECENT_SORT_MRU); + get_object("open_recent_item")->set_submenu(*recent_menu); + recent_menu->signal_item_activated().connect([&] { + try_open_rom(Glib::filename_from_uri(recent_menu->get_current_uri()).c_str()); + }); - gtk_recent_filter_add_group (filter, "cartridge"); - gtk_recent_chooser_set_local_only (chooser, true); - gtk_recent_chooser_set_show_icons (chooser, false); - gtk_recent_chooser_set_sort_type (chooser, GTK_RECENT_SORT_MRU); - gtk_recent_chooser_add_filter (chooser, filter); - - gtk_menu_item_set_submenu ( - GTK_MENU_ITEM (get_widget ("open_recent_item")), - recent_menu); - - g_signal_connect (G_OBJECT (recent_menu), - "item-activated", - G_CALLBACK (event_recent_open), - (gpointer) this); - - gtk_widget_show (recent_menu); + recent_menu->show(); } } -void -Snes9xWindow::propagate_pause_state () +void Snes9xWindow::propagate_pause_state() { int oldpause = Settings.Paused; @@ -1864,61 +1357,53 @@ Snes9xWindow::propagate_pause_state () if (Settings.Paused != oldpause) { - if (!is_paused ()) + if (!is_paused()) { - S9xSoundStart (); + S9xSoundStart(); if (config->rom_loaded) - enable_widget ("pause_item", true); + enable_widget("pause_item", true); } else { - S9xSoundStop (); - enable_widget ("pause_item", false); - + S9xSoundStop(); + enable_widget("pause_item", false); } - configure_widgets (); + configure_widgets(); } } -void -Snes9xWindow::toggle_ui () +void Snes9xWindow::toggle_ui() { config->ui_visible = !config->ui_visible; - - configure_widgets (); + configure_widgets(); } /* gui_[un]pause Handles when system needs to pause the emulator */ -void -Snes9xWindow::pause_from_focus_change () +void Snes9xWindow::pause_from_focus_change() { sys_pause += config->modal_dialogs; - - propagate_pause_state (); + propagate_pause_state(); } -void -Snes9xWindow::unpause_from_focus_change () +void Snes9xWindow::unpause_from_focus_change() { if (--sys_pause < 0) sys_pause = 0; - propagate_pause_state (); + propagate_pause_state(); } /* client_[un]pause Handles when user manually chooses to pause */ -void -Snes9xWindow::pause_from_user () +void Snes9xWindow::pause_from_user() { user_pause = true; - propagate_pause_state (); + propagate_pause_state(); } -void -Snes9xWindow::unpause_from_user () +void Snes9xWindow::unpause_from_user() { user_pause = false; - propagate_pause_state (); + propagate_pause_state(); } bool Snes9xWindow::is_paused() @@ -1929,149 +1414,112 @@ bool Snes9xWindow::is_paused() return false; } -void -Snes9xWindow::set_menu_item_accel_to_binding (const char *name, - const char *binding) +void Snes9xWindow::set_accelerator_to_binding(const char *name, const char *binding) { Binding bin; - char str[255]; - GtkAccelGroup *accel_group = NULL; - if (!strcmp (binding, "Escape Key")) + if (!strcmp(binding, "Escape Key")) { - bin = Binding (GDK_Escape, false, false, false); + bin = Binding(GDK_Escape, false, false, false); } else { - bin = S9xGetBindingByName (binding); + bin = S9xGetBindingByName(binding); } - snprintf (str, 255, "/%s", name); - if (!(bin.is_key ())) - { - gtk_accel_map_change_entry (str, - 0, - (GdkModifierType) 0, - true); + if (!(bin.is_key())) return; - } - GSList *accel_group_list = gtk_accel_groups_from_object (G_OBJECT (window)); + AcceleratorEntry entry{}; + entry.name = name; + entry.key = bin.get_key(); + entry.modifiers = bin.get_gdk_modifiers(); - if (accel_group_list) - { - accel_group = GTK_ACCEL_GROUP (accel_group_list->data); - } - else - { - accel_group = gtk_accel_group_new (); - gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); - } - - gtk_widget_set_accel_path (get_widget (name), str, accel_group); - - if (!gtk_accel_map_lookup_entry (str, NULL)) - { - gtk_accel_map_add_entry (str, - bin.get_key (), - bin.get_gdk_modifiers ()); - - } - else - { - gtk_accel_map_change_entry (str, - bin.get_key (), - bin.get_gdk_modifiers (), - true); - } + get_object(name)->add_accelerator("activate", accel_group, entry.key, entry.modifiers, Gtk::ACCEL_VISIBLE); + accelerators.push_back(entry); } -void -Snes9xWindow::update_accels () +void Snes9xWindow::update_accelerators() { - set_menu_item_accel_to_binding ("fullscreen_item", "GTK_fullscreen"); - set_menu_item_accel_to_binding ("reset_item", "SoftReset"); - set_menu_item_accel_to_binding ("save_state_0", "QuickSave000"); - set_menu_item_accel_to_binding ("save_state_1", "QuickSave001"); - set_menu_item_accel_to_binding ("save_state_2", "QuickSave002"); - set_menu_item_accel_to_binding ("save_state_3", "QuickSave003"); - set_menu_item_accel_to_binding ("save_state_4", "QuickSave004"); - set_menu_item_accel_to_binding ("save_state_5", "QuickSave005"); - set_menu_item_accel_to_binding ("save_state_6", "QuickSave006"); - set_menu_item_accel_to_binding ("save_state_7", "QuickSave007"); - set_menu_item_accel_to_binding ("save_state_8", "QuickSave008"); - set_menu_item_accel_to_binding ("save_state_9", "QuickSave009"); - set_menu_item_accel_to_binding ("load_state_0", "QuickLoad000"); - set_menu_item_accel_to_binding ("load_state_1", "QuickLoad001"); - set_menu_item_accel_to_binding ("load_state_2", "QuickLoad002"); - set_menu_item_accel_to_binding ("load_state_3", "QuickLoad003"); - set_menu_item_accel_to_binding ("load_state_4", "QuickLoad004"); - set_menu_item_accel_to_binding ("load_state_5", "QuickLoad005"); - set_menu_item_accel_to_binding ("load_state_6", "QuickLoad006"); - set_menu_item_accel_to_binding ("load_state_7", "QuickLoad007"); - set_menu_item_accel_to_binding ("load_state_8", "QuickLoad008"); - set_menu_item_accel_to_binding ("load_state_9", "QuickLoad009"); - set_menu_item_accel_to_binding ("pause_item", "GTK_pause"); - set_menu_item_accel_to_binding ("save_spc_item", "GTK_save_spc"); - set_menu_item_accel_to_binding ("open_rom_item", "GTK_open_rom"); - set_menu_item_accel_to_binding ("record_movie_item", "BeginRecordingMovie"); - set_menu_item_accel_to_binding ("open_movie_item", "LoadMovie"); - set_menu_item_accel_to_binding ("stop_recording_item", "EndRecordingMovie"); - set_menu_item_accel_to_binding ("jump_to_frame_item", "GTK_seek_to_frame"); - set_menu_item_accel_to_binding ("reset_item", "SoftReset"); - set_menu_item_accel_to_binding ("hard_reset_item", "Reset"); - set_menu_item_accel_to_binding ("exit_item", "GTK_quit"); + if (!accel_group) + { + accel_group = Gtk::AccelGroup::create(); + window->add_accel_group(accel_group); + } - /* Special UI assignment */ - set_menu_item_accel_to_binding ("hide_ui", "Escape Key"); + for (auto &entry : accelerators) + { + get_object(entry.name.c_str())->remove_accelerator(accel_group, entry.key, entry.modifiers); + } + accelerators.clear(); + + set_accelerator_to_binding("fullscreen_item", "GTK_fullscreen"); + set_accelerator_to_binding("reset_item", "SoftReset"); + set_accelerator_to_binding("save_state_0", "QuickSave000"); + set_accelerator_to_binding("save_state_1", "QuickSave001"); + set_accelerator_to_binding("save_state_2", "QuickSave002"); + set_accelerator_to_binding("save_state_3", "QuickSave003"); + set_accelerator_to_binding("save_state_4", "QuickSave004"); + set_accelerator_to_binding("save_state_5", "QuickSave005"); + set_accelerator_to_binding("save_state_6", "QuickSave006"); + set_accelerator_to_binding("save_state_7", "QuickSave007"); + set_accelerator_to_binding("save_state_8", "QuickSave008"); + set_accelerator_to_binding("save_state_9", "QuickSave009"); + set_accelerator_to_binding("load_state_0", "QuickLoad000"); + set_accelerator_to_binding("load_state_1", "QuickLoad001"); + set_accelerator_to_binding("load_state_2", "QuickLoad002"); + set_accelerator_to_binding("load_state_3", "QuickLoad003"); + set_accelerator_to_binding("load_state_4", "QuickLoad004"); + set_accelerator_to_binding("load_state_5", "QuickLoad005"); + set_accelerator_to_binding("load_state_6", "QuickLoad006"); + set_accelerator_to_binding("load_state_7", "QuickLoad007"); + set_accelerator_to_binding("load_state_8", "QuickLoad008"); + set_accelerator_to_binding("load_state_9", "QuickLoad009"); + set_accelerator_to_binding("pause_item", "GTK_pause"); + set_accelerator_to_binding("save_spc_item", "GTK_save_spc"); + set_accelerator_to_binding("open_rom_item", "GTK_open_rom"); + set_accelerator_to_binding("record_movie_item", "BeginRecordingMovie"); + set_accelerator_to_binding("open_movie_item", "LoadMovie"); + set_accelerator_to_binding("stop_recording_item", "EndRecordingMovie"); + set_accelerator_to_binding("jump_to_frame_item", "GTK_seek_to_frame"); + set_accelerator_to_binding("reset_item", "SoftReset"); + set_accelerator_to_binding("hard_reset_item", "Reset"); + set_accelerator_to_binding("exit_item", "GTK_quit"); + + // Special UI assignment + set_accelerator_to_binding("hide_ui", "Escape Key"); } -void -Snes9xWindow::resize_to_multiple (int factor) +void Snes9xWindow::resize_to_multiple(int factor) { int h = (config->overscan ? 239 : 224) * factor; - int w = h * S9xGetAspect () + 0.5; + int w = h * S9xGetAspect() + 0.5; - resize_viewport (w, h); + resize_viewport(w, h); } -cairo_t * -Snes9xWindow::get_cairo () +cairo_t *Snes9xWindow::get_cairo() { if (cr) return cr; - GtkWidget *drawing_area = GTK_WIDGET (this->drawing_area); + auto allocation = drawing_area->get_allocation(); -#if GTK_MAJOR_VERSION < 3 - cr = gdk_cairo_create (gtk_widget_get_window (drawing_area)); -#else - GtkAllocation allocation; - gtk_widget_get_allocation (drawing_area, &allocation); - - cairo_rectangle_int_t rect = { 0, 0, allocation.width, allocation.height }; - cairo_region = cairo_region_create_rectangle (&rect); - gdk_drawing_context = gdk_window_begin_draw_frame (gtk_widget_get_window (drawing_area), - cairo_region); - cr = gdk_drawing_context_get_cairo_context (gdk_drawing_context); -#endif + Cairo::RectangleInt rect = { 0, 0, allocation.get_width(), allocation.get_height() }; + gdk_drawing_context = drawing_area->get_window()->begin_draw_frame(Cairo::Region::create(rect)); + cr = gdk_drawing_context->get_cairo_context()->cobj(); cairo_owned = true; return cr; } -void -Snes9xWindow::release_cairo () +void Snes9xWindow::release_cairo() { if (cairo_owned) { -#if GTK_MAJOR_VERSION < 3 - cairo_destroy (cr); -#else - gdk_window_end_draw_frame (gtk_widget_get_window (GTK_WIDGET (drawing_area)), gdk_drawing_context); - cairo_region_destroy (cairo_region); -#endif + drawing_area->get_window()->end_draw_frame(gdk_drawing_context); + gdk_drawing_context.clear(); cairo_owned = false; - cr = NULL; + cr = nullptr; } } diff --git a/gtk/src/gtk_s9xwindow.h b/gtk/src/gtk_s9xwindow.h index 29143a6b..6e656318 100644 --- a/gtk/src/gtk_s9xwindow.h +++ b/gtk/src/gtk_s9xwindow.h @@ -7,7 +7,7 @@ #ifndef __GTK_S9XWINDOW_H #define __GTK_S9XWINDOW_H -#include "gtk_2_3_compat.h" +#include "gtk_compat.h" #include "port.h" #include "gtk_builder_window.h" @@ -15,90 +15,105 @@ class Snes9xWindow : public GtkBuilderWindow { - public: - Snes9xWindow (Snes9xConfig *config); + public: + Snes9xWindow(Snes9xConfig *config); - /* Pause related functions */ - void pause_from_focus_change (); - void unpause_from_focus_change (); - void focus_notify (bool state); - void pause_from_user (); - void unpause_from_user (); - bool is_paused (); - void propagate_pause_state (); + struct AcceleratorEntry + { + std::string name; + unsigned int key; + Gdk::ModifierType modifiers; + }; - /* Fullscreen functions */ - void enter_fullscreen_mode (); - void leave_fullscreen_mode (); - void toggle_fullscreen_mode (); - void finish_fullscreen (); + /* Pause related functions */ + void pause_from_focus_change(); + void unpause_from_focus_change(); + void focus_notify(bool state); + void pause_from_user(); + void unpause_from_user(); + bool is_paused(); + void propagate_pause_state(); - /* Cursor modifying functions */ - void show_mouse_cursor (); - void hide_mouse_cursor (); - void toggle_grab_mouse (); - void center_mouse (); + /* Fullscreen functions */ + void enter_fullscreen_mode(); + void leave_fullscreen_mode(); + void toggle_fullscreen_mode(); + void finish_fullscreen(); - /* Rom-related functions */ - void open_rom_dialog (); - void save_state_dialog (); - void load_state_dialog (); - void configure_widgets (); - void save_spc_dialog (); - bool try_open_rom (const char *filename); - const char *open_movie_dialog (bool readonly); - void movie_seek_dialog (); - void open_multicart_dialog (); - void show_rom_info (); + /* Cursor modifying functions */ + void show_mouse_cursor(); + void hide_mouse_cursor(); + void toggle_grab_mouse(); + void center_mouse(); - /* GTK-base-related functions */ - void show (); - void set_menu_item_selected (const char *name); - void set_mouseable_area (int x, int y, int width, int height); - void set_menu_item_accel_to_binding (const char *name, - const char *binding); - void reset_screensaver (); - void update_accels (); - void toggle_ui (); - void resize_to_multiple (int factor); - void resize_viewport (int width, int height); - void expose (); - void setup_splash(); - double get_refresh_rate (); - int get_auto_input_rate (); + /* Rom-related functions */ + std::string open_rom_dialog(bool run = true); + void save_state_dialog(); + void load_state_dialog(); + void configure_widgets(); + void save_spc_dialog(); + bool try_open_rom(std::string filename); + std::string open_movie_dialog(bool readonly); + void movie_seek_dialog(); + void open_multicart_dialog(); + void show_rom_info(); - cairo_t *get_cairo (); - void release_cairo (); + /* GTK-base-related functions */ + void show(); + void set_menu_item_selected(const char *name); + void set_mouseable_area(int x, int y, int width, int height); + void set_accelerator_to_binding(const char *name, + const char *binding); + void reset_screensaver(); + void update_accelerators(); + void toggle_ui(); + void resize_to_multiple(int factor); + void resize_viewport(int width, int height); + bool draw(const Cairo::RefPtr &cr); + void setup_splash(); + double get_refresh_rate(); + int get_auto_input_rate(); + void connect_signals(); + bool event_key(GdkEventKey *event); + void port_activate(const char *name); + bool button_press(GdkEventButton *event); + bool button_release(GdkEventButton *event); + bool motion_notify(GdkEventMotion *event); - Snes9xConfig *config; - int user_pause, sys_pause; - int last_width, last_height; - int mouse_region_x, mouse_region_y; - int mouse_region_width, mouse_region_height; - int nfs_width, nfs_height, nfs_x, nfs_y; - int fullscreen_state; - int maximized_state; - bool focused; - bool paused_from_focus_loss; - double snes_mouse_x, snes_mouse_y; - double gdk_mouse_x, gdk_mouse_y; - bool mouse_grabbed; - GdkPixbuf *icon, *splash; - GdkCursor *default_cursor, *empty_cursor; - GtkDrawingArea *drawing_area; - GtkWidget *recent_menu; - cairo_t *cr; - bool cairo_owned; -#if GTK_MAJOR_VERSION >= 3 - GdkDrawingContext *gdk_drawing_context; - cairo_region_t *cairo_region; -#endif + cairo_t *get_cairo(); + void release_cairo(); + + Snes9xConfig *config; + int user_pause, sys_pause; + int last_width, last_height; + int mouse_region_x, mouse_region_y; + int mouse_region_width, mouse_region_height; + int nfs_width, nfs_height, nfs_x, nfs_y; + int fullscreen_state; + int maximized_state; + bool focused; + bool paused_from_focus_loss; + double snes_mouse_x, snes_mouse_y; + double gdk_mouse_x, gdk_mouse_y; + bool mouse_grabbed; + GdkPixbuf *icon, *splash; + Gtk::DrawingArea *drawing_area; + Gtk::RecentChooserMenu *recent_menu; + cairo_t *cr; + bool cairo_owned; + Glib::RefPtr gdk_drawing_context; + Glib::RefPtr accel_group; + std::vector accelerators; + + unsigned int last_key_pressed_keyval; + GdkEventType last_key_pressed_type; }; -typedef struct gtk_splash_t { - unsigned int width; - unsigned int height; - unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ +typedef struct gtk_splash_t +{ + unsigned int width; + unsigned int height; + unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ unsigned char pixel_data[256 * 224 * 3 + 1]; } gtk_splash_t; diff --git a/gtk/src/gtk_shader_parameters.cpp b/gtk/src/gtk_shader_parameters.cpp index 25318e2f..7d605741 100644 --- a/gtk/src/gtk_shader_parameters.cpp +++ b/gtk/src/gtk_shader_parameters.cpp @@ -4,7 +4,7 @@ For further information, consult the LICENSE file in the root directory. \*****************************************************************************/ -#include "gtk_2_3_compat.h" +#include "gtk_compat.h" #include #include @@ -13,59 +13,27 @@ #include "gtk_shader_parameters.h" #include "shaders/glsl.h" -static GtkWidget *dialog = NULL; -static std::vector *params = NULL; +#include "gfx.h" + +static Gtk::Dialog *dialog = nullptr; +static std::vector *params = nullptr; static std::vector saved_params; static inline double snap_to_interval(double value, double interval) { + if (interval == 0.0) + return value; return round(value / interval) * interval; } -static void value_changed(GtkRange *range, gpointer user_data) +static void dialog_response(int response_id) { - GLSLParam *p = (GLSLParam *)user_data; - GtkAdjustment *adj = gtk_range_get_adjustment(range); - double interval = gtk_adjustment_get_step_increment(adj); - double value = gtk_range_get_value(range); - - value = snap_to_interval(value, interval); - - gtk_range_set_value(range, value); - - if (p->val != value) - { - p->val = value; - if (Settings.Paused) - S9xDeinitUpdate(top_level->last_width, top_level->last_height); - } -} - -static void toggled(GtkToggleButton *togglebutton, gpointer user_data) -{ - GLSLParam *p = (GLSLParam *)user_data; - double value = (double)gtk_toggle_button_get_active(togglebutton); - - if (p->val != value) - { - p->val = value; - if (Settings.Paused) - S9xDeinitUpdate(top_level->last_width, top_level->last_height); - } -} - -static void dialog_response(GtkDialog *pdialog, gint response_id, gpointer user_data) -{ - std::vector *params = (std::vector *)user_data; - - int width, height; - gtk_window_get_size(GTK_WINDOW(pdialog), &width, &height); - gui_config->shader_parameters_width = width; - gui_config->shader_parameters_height = height; + gui_config->shader_parameters_width = dialog->get_width(); + gui_config->shader_parameters_height = dialog->get_height(); switch (response_id) { - case GTK_RESPONSE_OK: + case Gtk::RESPONSE_OK: { char path[PATH_MAX]; std::string config_file = get_config_dir(); @@ -78,17 +46,17 @@ static void dialog_response(GtkDialog *pdialog, gint response_id, gpointer user_ gui_config->shader_filename = path; if (dialog) - gtk_widget_destroy(GTK_WIDGET(dialog)); - dialog = NULL; + delete dialog; + dialog = nullptr; break; } - case GTK_RESPONSE_CANCEL: - case GTK_RESPONSE_DELETE_EVENT: - case GTK_RESPONSE_NONE: + case Gtk::RESPONSE_CANCEL: + case Gtk::RESPONSE_DELETE_EVENT: + case Gtk::RESPONSE_NONE: if (dialog) - gtk_widget_destroy(GTK_WIDGET(dialog)); - dialog = NULL; + delete dialog; + dialog = nullptr; *params = saved_params; if (Settings.Paused) S9xDeinitUpdate(top_level->last_width, top_level->last_height); @@ -96,17 +64,14 @@ static void dialog_response(GtkDialog *pdialog, gint response_id, gpointer user_ case 15: // Save As { - auto dialog = gtk_file_chooser_dialog_new(_("Export Shader Preset to:"), - top_level->get_window(), - GTK_FILE_CHOOSER_ACTION_SAVE, - "gtk-cancel", GTK_RESPONSE_CANCEL, - "gtk-save", GTK_RESPONSE_ACCEPT, - NULL); + Gtk::FileChooserDialog dialog(_("Export Shader Preset to:"), Gtk::FILE_CHOOSER_ACTION_SAVE); + dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); + dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_ACCEPT); + dialog.set_current_folder(gui_config->last_shader_directory); + + std::string name; + std::string extension; - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), - gui_config->last_shader_directory.c_str()); - const char *name; - const char *extension; if (gui_config->shader_filename.find(".slang") != std::string::npos) { name = "new.slangp"; @@ -117,26 +82,23 @@ static void dialog_response(GtkDialog *pdialog, gint response_id, gpointer user_ name = "new.glslp"; extension = "*.glslp"; } - gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), name); - gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), true); - auto filter = gtk_file_filter_new(); - gtk_file_filter_set_name(filter, _("Shader Preset")); - gtk_file_filter_add_pattern(filter, extension); - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); + dialog.set_current_name(name); + dialog.set_do_overwrite_confirmation(); - auto result = gtk_dialog_run(GTK_DIALOG(dialog)); + auto filter = Gtk::FileFilter::create(); + filter->set_name(_("Shader Preset")); + filter->add_pattern(extension); + dialog.add_filter(filter); + + auto result = dialog.run(); if (result == GTK_RESPONSE_ACCEPT) - { - auto filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - S9xDisplayGetDriver()->save(filename); - g_free(filename); - } + S9xDisplayGetDriver()->save(dialog.get_filename().c_str()); - gtk_widget_destroy(dialog); break; } + default: break; } @@ -147,8 +109,8 @@ void gtk_shader_parameters_dialog_close() if (dialog) { *params = saved_params; - gtk_widget_destroy(GTK_WIDGET(dialog)); - dialog = NULL; + delete dialog; + dialog = nullptr; } } @@ -156,7 +118,7 @@ bool gtk_shader_parameters_dialog(GtkWindow *parent) { if (dialog) { - gtk_window_present(GTK_WINDOW(dialog)); + dialog->present(); return false; } @@ -166,145 +128,85 @@ bool gtk_shader_parameters_dialog(GtkWindow *parent) if (!params || params->size() == 0) return false; - dialog = gtk_dialog_new_with_buttons(_("Shader Parameters"), - parent, - GTK_DIALOG_DESTROY_WITH_PARENT, - "gtk-cancel", - GTK_RESPONSE_CANCEL, - "gtk-save-as", - 15, - "gtk-save", - GTK_RESPONSE_OK, - NULL); + dialog = new Gtk::Dialog(_("Shader Parameters"), Gtk::DIALOG_DESTROY_WITH_PARENT); + dialog->add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); + dialog->add_button(Gtk::StockID("gtk-save-as"), 15); + dialog->add_button(Gtk::StockID("gtk-save"), GTK_RESPONSE_OK); + dialog->signal_response().connect(sigc::ptr_fun(dialog_response)); - g_signal_connect_data(G_OBJECT(dialog), "response", G_CALLBACK(dialog_response), (gpointer)params, NULL, (GConnectFlags)0); - - GtkWidget *scrolled_window; - gtk_widget_set_size_request(dialog, 640, 480); + dialog->set_size_request(640, 480); if (gui_config->shader_parameters_width > 0 && gui_config->shader_parameters_height > 0) - { - gtk_window_resize(GTK_WINDOW(dialog), - gui_config->shader_parameters_width, - gui_config->shader_parameters_height); - } + dialog->resize(gui_config->shader_parameters_width, gui_config->shader_parameters_height); - scrolled_window = gtk_scrolled_window_new(NULL, NULL); - gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), - scrolled_window); + auto scrolled_window = new Gtk::ScrolledWindow; + scrolled_window->set_hexpand(); + scrolled_window->set_vexpand(); + scrolled_window->set_margin_start(5); + scrolled_window->set_margin_end(5); + scrolled_window->set_margin_top(5); + dialog->get_content_area()->add(*scrolled_window); - GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); - -#if GTK_MAJOR_VERSION >= 3 - - gtk_widget_set_hexpand(scrolled_window, true); - gtk_widget_set_vexpand(scrolled_window, true); - gtk_widget_set_margin_start(scrolled_window, 5); - gtk_widget_set_margin_end(scrolled_window, 5); - gtk_widget_set_margin_top(scrolled_window, 5); - gtk_widget_set_margin_bottom(scrolled_window, 5); - - GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - GtkWidget *grid = gtk_grid_new(); - gtk_widget_set_margin_end(grid, 5); - gtk_grid_set_row_homogeneous(GTK_GRID(grid), true); - gtk_grid_set_row_spacing(GTK_GRID(grid), 2); - gtk_grid_set_column_spacing(GTK_GRID(grid), 12); - gtk_container_add(GTK_CONTAINER(vbox), grid); - gtk_container_add(GTK_CONTAINER(scrolled_window), vbox); + auto grid = new Gtk::Grid; + grid->set_margin_end(5); + grid->set_row_homogeneous(); + grid->set_row_spacing(2); + grid->set_column_spacing(12); + auto vbox = new Gtk::VBox; + vbox->pack_start(*grid); + scrolled_window->add(*vbox); + auto sizegroup = Gtk::SizeGroup::create(Gtk::SIZE_GROUP_HORIZONTAL); for (unsigned int i = 0; i < params->size(); i++) { - GLSLParam *p = &(*params)[i]; - GtkWidget *label = gtk_label_new(p->name); - gtk_label_set_xalign(GTK_LABEL(label), 0.0f); - gtk_widget_show(label); + GLSLParam &p = (*params)[i]; + auto label = new Gtk::Label(p.name); + label->set_xalign(0.0f); + label->show(); + grid->attach(*label, 0, i, 1, 1); - gtk_grid_attach(GTK_GRID(grid), label, 0, i, 1, 1); - - if (p->min == 0.0 && p->max == 1.0 && p->step == 1.0) + if (p.min == 0.0 && p.max == 1.0 && p.step == 1.0) { - GtkWidget *check = gtk_check_button_new(); - gtk_grid_attach(GTK_GRID(grid), check, 1, i, 1, 1); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), (int)p->val); - g_signal_connect_data(G_OBJECT(check), "toggled", G_CALLBACK(toggled), (gpointer)p, NULL, (GConnectFlags)0); + auto check = new Gtk::CheckButton; + grid->attach(*check, 1, i, 1, 1); + check->set_active(p.val); + check->signal_toggled().connect([check, ¶m = p.val] { + double new_value = check->get_active(); + if (param != new_value) + { + param = new_value; + if (Settings.Paused) + S9xDeinitUpdate(top_level->last_width, top_level->last_height); + } + }); } else { - GtkWidget *spin = gtk_spin_button_new_with_range(p->min, p->max, p->step); - gtk_entry_set_width_chars(GTK_ENTRY(spin), 5); - gtk_grid_attach(GTK_GRID(grid), spin, 1, i, 1, 1); - gtk_size_group_add_widget(sizegroup, spin); - int digits = gtk_spin_button_get_digits(GTK_SPIN_BUTTON(spin)); - if (digits == 2) - gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), 3); + auto spin = new Gtk::SpinButton(0.0, p.digits); + spin->set_range(p.min, p.max); + spin->get_adjustment()->set_step_increment(p.step); + spin->set_width_chars(6); + grid->attach(*spin, 1, i, 1, 1); + sizegroup->add_widget(*spin); - GtkAdjustment *adjustment = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(spin)); - - GtkWidget *scale = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, adjustment); - gtk_widget_set_hexpand(scale, true); - gtk_grid_attach(GTK_GRID(grid), scale, 2, i, 1, 1); - gtk_scale_set_draw_value(GTK_SCALE(scale), false); - gtk_range_set_value(GTK_RANGE(scale), p->val); - g_signal_connect_data(G_OBJECT(scale), - "value-changed", - G_CALLBACK(value_changed), - (gpointer)p, - NULL, - (GConnectFlags)0); + auto scale = new Gtk::Scale(spin->get_adjustment()); + scale->set_hexpand(); + grid->attach(*scale, 2, i, 1, 1); + scale->set_draw_value(false); + scale->set_value(p.val); + scale->signal_value_changed().connect([spin, ¶m = p.val] { + double new_value = snap_to_interval(spin->get_value(), spin->get_adjustment()->get_step_increment()); + spin->set_value(new_value); + if (param != new_value) + { + param = new_value; + if (Settings.Paused) + S9xDeinitUpdate(top_level->last_width, top_level->last_height); + } + }); } } -#else - GtkWidget *vbox = gtk_vbox_new(false, 5); - GtkWidget *table = gtk_table_new(params->size(), 3, false); - gtk_table_set_row_spacings(GTK_TABLE(table), 5); - gtk_table_set_col_spacings(GTK_TABLE(table), 12); - gtk_container_add(GTK_CONTAINER(vbox), table); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), vbox); - gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 5); - for (unsigned int i = 0; i < params->size(); i++) - { - GLSLParam *p = &(*params)[i]; - GtkWidget *label = gtk_label_new(p->name); - gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); - gtk_widget_show(label); - - gtk_table_attach(GTK_TABLE(table), label, 0, 1, i, i + 1, GTK_FILL, GTK_FILL, 0, 0); - - if (p->min == 0.0 && p->max == 1.0 && p->step == 1.0) - { - GtkWidget *check = gtk_check_button_new(); - gtk_table_attach(GTK_TABLE(table), check, 1, 2, i, i + 1, GTK_FILL, GTK_FILL, 0, 0); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), (int)p->val); - g_signal_connect_data(G_OBJECT(check), "toggled", G_CALLBACK(toggled), (gpointer)p, NULL, (GConnectFlags)0); - } - else - { - GtkWidget *spin = gtk_spin_button_new_with_range(p->min, p->max, p->step); - gtk_table_attach(GTK_TABLE(table), spin, 1, 2, i, i + 1, GTK_FILL, GTK_FILL, 0, 0); - gtk_size_group_add_widget(sizegroup, spin); - int digits = gtk_spin_button_get_digits(GTK_SPIN_BUTTON(spin)); - if (digits == 2) - gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), 3); - - GtkAdjustment *adjustment = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(spin)); - - GtkWidget *scale = gtk_hscale_new(adjustment); - gtk_table_attach(GTK_TABLE(table), scale, 2, 3, i, i + 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), GTK_FILL, 0, 0); - gtk_scale_set_draw_value(GTK_SCALE(scale), false); - gtk_range_set_value(GTK_RANGE(scale), p->val); - g_signal_connect_data(G_OBJECT(scale), - "value-changed", - G_CALLBACK(value_changed), - (gpointer)p, - NULL, - (GConnectFlags)0); - } - } -#endif - - gtk_widget_show_all(dialog); + dialog->show_all(); return true; } diff --git a/gtk/src/gtk_shader_parameters.h b/gtk/src/gtk_shader_parameters.h index d3984804..0919cc7b 100644 --- a/gtk/src/gtk_shader_parameters.h +++ b/gtk/src/gtk_shader_parameters.h @@ -7,9 +7,9 @@ #ifndef __GTK_SHADER_PARAMETERS_H #define __GTK_SHADER_PARAMETERS_H -#include "gtk_2_3_compat.h" +#include "gtk_compat.h" -bool gtk_shader_parameters_dialog (GtkWindow *parent); -void gtk_shader_parameters_dialog_close (); +bool gtk_shader_parameters_dialog(GtkWindow *parent); +void gtk_shader_parameters_dialog_close(); #endif // __GTK_SHADER_PARAMETERS_H diff --git a/gtk/src/gtk_sound.cpp b/gtk/src/gtk_sound.cpp index 28d46a9e..110d4102 100644 --- a/gtk/src/gtk_sound.cpp +++ b/gtk/src/gtk_sound.cpp @@ -10,6 +10,8 @@ #include "gtk_s9x.h" #include "gtk_sound.h" #include "gtk_sound_driver.h" +#include "snes9x.h" +#include "apu/apu.h" #ifdef USE_PORTAUDIO #include "gtk_sound_driver_portaudio.h" @@ -30,10 +32,9 @@ static int playback_rates[8] = 0, 8000, 11025, 16000, 22050, 32000, 44100, 48000 }; -S9xSoundDriver *driver; +static S9xSoundDriver *driver; -int -S9xSoundBase2log (int num) +int S9xSoundBase2log(int num) { int power; @@ -48,14 +49,12 @@ S9xSoundBase2log (int num) return power; } -int -S9xSoundPowerof2 (int num) +int S9xSoundPowerof2(int num) { return (1 << num); } -void -S9xPortSoundInit () +void S9xPortSoundInit() { int pao_driver = 0; int sdl_driver = 0; @@ -103,34 +102,34 @@ S9xPortSoundInit () #ifdef USE_PORTAUDIO if (gui_config->sound_driver == pao_driver) - driver = new S9xPortAudioSoundDriver (); + driver = new S9xPortAudioSoundDriver(); #endif #ifdef USE_OSS if (gui_config->sound_driver == oss_driver) - driver = new S9xOSSSoundDriver (); + driver = new S9xOSSSoundDriver(); #endif if (gui_config->sound_driver == sdl_driver) - driver = new S9xSDLSoundDriver (); + driver = new S9xSDLSoundDriver(); #ifdef USE_ALSA if (gui_config->sound_driver == alsa_driver) - driver = new S9xAlsaSoundDriver (); + driver = new S9xAlsaSoundDriver(); #endif #ifdef USE_PULSEAUDIO if (gui_config->sound_driver == pulse_driver) - driver = new S9xPulseSoundDriver (); + driver = new S9xPulseSoundDriver(); #endif if (driver != NULL) { - driver->init (); + driver->init(); if (gui_config->auto_input_rate) { - Settings.SoundInputRate = top_level->get_auto_input_rate (); + Settings.SoundInputRate = top_level->get_auto_input_rate(); if (Settings.SoundInputRate == 0.0) { Settings.SoundInputRate = 31950; @@ -139,68 +138,65 @@ S9xPortSoundInit () } else { - Settings.SoundInputRate = CLAMP (gui_config->sound_input_rate, 31700, 32300); + Settings.SoundInputRate = CLAMP(gui_config->sound_input_rate, 31700, 32300); } Settings.SoundPlaybackRate = playback_rates[gui_config->sound_playback_rate]; S9xInitSound(0); - S9xSetSoundMute (false); + S9xSetSoundMute(false); } else { - S9xSetSoundMute (gui_config->mute_sound); + S9xSetSoundMute(gui_config->mute_sound); } } -void -S9xPortSoundReinit () +void S9xPortSoundReinit() { - S9xPortSoundDeinit (); + S9xPortSoundDeinit(); /* Ensure the sound device is released before trying to reopen it. */ - sync (); + sync(); - S9xPortSoundInit (); + S9xPortSoundInit(); } -void -S9xPortSoundDeinit () +void S9xPortSoundDeinit() { - S9xSoundStop (); + S9xSoundStop(); - driver->terminate (); + if (driver) + driver->terminate(); delete driver; } -void -S9xSoundStart () +void S9xSoundStart() { - driver->start (); + if (driver) + driver->start(); } -void -S9xSoundStop () +void S9xSoundStop() { - driver->stop (); + if (driver) + driver->stop(); } -bool8 -S9xOpenSoundDevice () +bool8 S9xOpenSoundDevice() { if (gui_config->mute_sound) return false; - gui_config->sound_buffer_size = CLAMP (gui_config->sound_buffer_size, 2, 256); + gui_config->sound_buffer_size = CLAMP(gui_config->sound_buffer_size, 2, 256); - return driver->open_device (); + return driver->open_device(); } /* This really shouldn't be in the port layer */ -void -S9xToggleSoundChannel (int c) +void S9xToggleSoundChannel(int c) { static int sound_switch = 255; @@ -209,5 +205,5 @@ S9xToggleSoundChannel (int c) else sound_switch ^= 1 << c; - S9xSetSoundControl (sound_switch); + S9xSetSoundControl(sound_switch); } diff --git a/gtk/src/gtk_sound_driver_alsa.cpp b/gtk/src/gtk_sound_driver_alsa.cpp index 7fa50967..24e05430 100644 --- a/gtk/src/gtk_sound_driver_alsa.cpp +++ b/gtk/src/gtk_sound_driver_alsa.cpp @@ -6,6 +6,8 @@ #include "gtk_sound_driver_alsa.h" #include "gtk_s9x.h" +#include "snes9x.h" +#include "apu/apu.h" #include #include diff --git a/gtk/src/gtk_sound_driver_oss.cpp b/gtk/src/gtk_sound_driver_oss.cpp index 3eb09533..7f5412a5 100644 --- a/gtk/src/gtk_sound_driver_oss.cpp +++ b/gtk/src/gtk_sound_driver_oss.cpp @@ -6,6 +6,8 @@ #include "gtk_sound_driver_oss.h" #include "gtk_s9x.h" +#include "snes9x.h" +#include "apu/apu.h" #include #include diff --git a/gtk/src/gtk_sound_driver_portaudio.cpp b/gtk/src/gtk_sound_driver_portaudio.cpp index 07e9b94c..cf3699b3 100644 --- a/gtk/src/gtk_sound_driver_portaudio.cpp +++ b/gtk/src/gtk_sound_driver_portaudio.cpp @@ -6,6 +6,8 @@ #include "gtk_sound_driver_portaudio.h" #include "gtk_s9x.h" +#include "apu/apu.h" +#include "snes9x.h" static void port_audio_samples_available_callback(void *data) { diff --git a/gtk/src/gtk_sound_driver_pulse.cpp b/gtk/src/gtk_sound_driver_pulse.cpp index 925f6b0e..e73b56ef 100644 --- a/gtk/src/gtk_sound_driver_pulse.cpp +++ b/gtk/src/gtk_sound_driver_pulse.cpp @@ -6,6 +6,8 @@ #include "gtk_sound_driver_pulse.h" #include "gtk_s9x.h" +#include "snes9x.h" +#include "apu/apu.h" #include #include diff --git a/gtk/src/gtk_sound_driver_sdl.cpp b/gtk/src/gtk_sound_driver_sdl.cpp index c120fa36..cf2e23d0 100644 --- a/gtk/src/gtk_sound_driver_sdl.cpp +++ b/gtk/src/gtk_sound_driver_sdl.cpp @@ -6,6 +6,8 @@ #include "gtk_sound_driver_sdl.h" #include "gtk_s9x.h" +#include "apu/apu.h" +#include "snes9x.h" static void sdl_audio_callback(void *userdata, Uint8 *stream, int len) { diff --git a/gtk/src/gtk_wayland_egl_context.h b/gtk/src/gtk_wayland_egl_context.h index 29d5fb1b..c2ae37d5 100644 --- a/gtk/src/gtk_wayland_egl_context.h +++ b/gtk/src/gtk_wayland_egl_context.h @@ -7,11 +7,11 @@ #ifndef __GTK_WAYLAND_EGL_CONTEXT_H #define __GTK_WAYLAND_EGL_CONTEXT_H -#include -#include -#include - #include "gtk_opengl_context.h" +#include "gtk_compat.h" + +#include +#include class WaylandEGLContext : public OpenGLContext { diff --git a/gtk/src/snes9x.ui b/gtk/src/snes9x.ui index fc0292f7..e1bb91d5 100644 --- a/gtk/src/snes9x.ui +++ b/gtk/src/snes9x.ui @@ -285,7 +285,7 @@ GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK end - + gtk-close True True @@ -351,7 +351,7 @@ 5 5 - + gtk-add True True @@ -369,7 +369,7 @@ - + gtk-remove True True @@ -551,7 +551,7 @@ - button7 + cheats_close @@ -2274,7 +2274,7 @@ - + True True True @@ -2701,7 +2701,7 @@ - + gtk-about True True @@ -5446,7 +5446,7 @@ - + _Reset True True @@ -5502,7 +5502,7 @@ - + _Swap True True @@ -9320,7 +9320,7 @@ cancel_button ok_button button1 - button8 + about_button diff --git a/gtk/src/sourcify.c b/gtk/src/sourcify.c index f1eabb2a..50ee8754 100644 --- a/gtk/src/sourcify.c +++ b/gtk/src/sourcify.c @@ -7,9 +7,7 @@ #include #include -int -main (int argc, - char *argv[]) +int main(int argc, char *argv[]) { FILE *infile, *outfile; unsigned char inchar; @@ -18,49 +16,46 @@ main (int argc, if (argc != 4) { - fprintf (stderr, "Usage: %s infile outfile identifier\n", argv[0]); + fprintf(stderr, "Usage: %s infile outfile identifier\n", argv[0]); return 1; } - stat (argv[1], &file_info); + stat(argv[1], &file_info); - infile = fopen (argv[1], "r"); + infile = fopen(argv[1], "r"); if (!infile) { - fprintf (stderr, "Input file doesn't exist.\n"); + fprintf(stderr, "Input file doesn't exist.\n"); return 2; } - outfile = fopen (argv[2], "w+"); + outfile = fopen(argv[2], "w+"); - fprintf (outfile, - "int %s_size = %d;\n\n", - argv[3], - (int) file_info.st_size); - fprintf (outfile, "unsigned char %s [] = \n{\n ", argv[3]); + fprintf(outfile, "int %s_size = %d;\n\n", argv[3], (int)file_info.st_size); + fprintf(outfile, "unsigned char %s [] = \n{\n ", argv[3]); counter = 0; - while (fread (&inchar, 1, 1, infile)) + while (fread(&inchar, 1, 1, infile)) { if (counter >= 32) { counter = 0; - fprintf (outfile, "\n "); + fprintf(outfile, "\n "); } - fprintf (outfile, "%d,", inchar); + fprintf(outfile, "%d,", inchar); counter++; } /* Erase extra "," */ - fseek (outfile, -1, SEEK_CUR); + fseek(outfile, -1, SEEK_CUR); - fprintf (outfile, "\n};\n"); + fprintf(outfile, "\n};\n"); - fclose (infile); - fclose (outfile); + fclose(infile); + fclose(outfile); return 0; } diff --git a/shaders/glsl.cpp b/shaders/glsl.cpp index 8122cdcd..dc1f1676 100644 --- a/shaders/glsl.cpp +++ b/shaders/glsl.cpp @@ -345,6 +345,14 @@ void GLSLShader::read_shader_file_with_includes(std::string filename, sscanf(line.c_str(), "#pragma parameter %s \"%[^\"]\" %f %f %f %f", par.id, par.name, &par.val, &par.min, &par.max, &par.step); + unsigned int last_decimal = line.rfind(".") + 1; + unsigned int index = last_decimal; + while (isdigit(line[index]) && index < line.length()) + index++; + par.digits = index - last_decimal; + if (line[index - 1] == '0' && line[index - 2] == '.') + par.digits = 0; + if (par.step == 0.0f) par.step = 1.0f; diff --git a/shaders/glsl.h b/shaders/glsl.h index ba364701..ff96958a 100644 --- a/shaders/glsl.h +++ b/shaders/glsl.h @@ -151,6 +151,7 @@ typedef struct float max; float val; float step; + int digits; GLint unif[glsl_max_passes]; } GLSLParam;