2018-11-07 01:04:10 +01:00
|
|
|
#include "gtk_2_3_compat.h"
|
2018-05-09 23:25:09 +02:00
|
|
|
#ifdef GDK_WINDOWING_X11
|
2018-11-07 01:04:10 +01:00
|
|
|
#include <X11/Xatom.h>
|
2018-05-09 23:25:09 +02:00
|
|
|
#endif
|
2010-09-25 17:46:12 +02:00
|
|
|
#include <gdk/gdkkeysyms.h>
|
2010-09-26 11:19:15 +02:00
|
|
|
#include <cairo.h>
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
#ifdef USE_XV
|
|
|
|
#include <X11/extensions/XShm.h>
|
|
|
|
#include <X11/extensions/Xv.h>
|
|
|
|
#include <X11/extensions/Xvlib.h>
|
|
|
|
#endif
|
|
|
|
|
2018-05-24 19:18:59 +02:00
|
|
|
#ifdef USE_OPENGL
|
|
|
|
#include "gtk_shader_parameters.h"
|
|
|
|
#endif
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
#include "gtk_s9x.h"
|
|
|
|
#include "gtk_preferences.h"
|
|
|
|
#include "gtk_icon.h"
|
|
|
|
#include "gtk_display.h"
|
|
|
|
#include "gtk_file.h"
|
|
|
|
#include "gtk_sound.h"
|
|
|
|
#include "gtk_control.h"
|
|
|
|
#include "gtk_cheat.h"
|
|
|
|
#ifdef NETPLAY_SUPPORT
|
|
|
|
#include "gtk_netplay.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
event_main_window_delete (GtkWidget *widget,
|
|
|
|
GdkEvent *event,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
S9xExit ();
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
event_main_window_state_event (GtkWidget *widget,
|
|
|
|
GdkEventWindowState *event,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
event_continue_item_activate (GtkWidget *widget, gpointer data)
|
|
|
|
{
|
|
|
|
Snes9xWindow *window = (Snes9xWindow *) data;
|
|
|
|
|
|
|
|
window->unpause_from_user ();
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
event_open_cheats (GtkWidget *widget, gpointer data)
|
|
|
|
{
|
|
|
|
Snes9xCheats *cheats;
|
|
|
|
cheats = new Snes9xCheats ();
|
|
|
|
|
|
|
|
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_show_statusbar (GtkWidget *widget, gpointer data)
|
|
|
|
{
|
2014-03-30 05:15:04 +02:00
|
|
|
((Snes9xWindow *) data)->toggle_statusbar ();
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
event_sync_clients (GtkWidget *widget, gpointer data)
|
|
|
|
{
|
|
|
|
#ifdef NETPLAY_SUPPORT
|
|
|
|
S9xNetplaySyncClients ();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
#ifdef NETPLAY_SUPPORT
|
|
|
|
S9xNetplayDialogOpen ();
|
|
|
|
#endif
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2018-04-28 18:59:17 +02:00
|
|
|
#if GTK_MAJOR_VERSION >= 3
|
2011-02-06 02:42:26 +01:00
|
|
|
static gboolean
|
|
|
|
event_drawingarea_draw (GtkWidget *widget,
|
|
|
|
cairo_t *cr,
|
|
|
|
gpointer data)
|
|
|
|
{
|
2018-10-29 22:02:45 +01:00
|
|
|
|
2017-12-07 19:24:29 +01:00
|
|
|
Snes9xWindow *window = (Snes9xWindow *) data;
|
|
|
|
window->cr = cr;
|
|
|
|
window->cairo_owned = FALSE;
|
|
|
|
window->expose ();
|
|
|
|
window->cr = NULL;
|
2011-02-06 02:42:26 +01:00
|
|
|
|
2018-10-29 22:02:45 +01:00
|
|
|
return TRUE;
|
2011-02-06 02:42:26 +01:00
|
|
|
}
|
|
|
|
|
2018-04-28 18:59:17 +02:00
|
|
|
#else
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
static gboolean
|
2011-02-06 02:42:26 +01:00
|
|
|
event_drawingarea_expose (GtkWidget *widget,
|
|
|
|
GdkEventExpose *event,
|
|
|
|
gpointer data)
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2015-08-16 12:36:56 +02:00
|
|
|
((Snes9xWindow *) data)->expose ();
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2018-10-29 22:02:45 +01:00
|
|
|
return TRUE;
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
2011-02-06 02:42:26 +01:00
|
|
|
#endif
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
/* Ignore multiple identical keypresses to discard repeating keys */
|
|
|
|
if (event->keyval == keyval && event->type == type)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Provide escape key to get out of fullscreen */
|
2010-09-26 11:19:15 +02:00
|
|
|
if (event->keyval == GDK_Escape)
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2010-09-26 11:19:15 +02:00
|
|
|
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 ();
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
2010-09-26 11:19:15 +02:00
|
|
|
{
|
2010-09-25 17:46:12 +02:00
|
|
|
b = Binding (event->keyval, false, false, false);
|
2010-09-26 11:19:15 +02:00
|
|
|
cmd = S9xGetMapping (b.hex ());
|
|
|
|
}
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2010-09-26 11:19:15 +02:00
|
|
|
if (cmd.type != S9xNoMapping)
|
|
|
|
{
|
|
|
|
S9xReportButton (b.hex (), (event->type == GDK_KEY_PRESS));
|
|
|
|
return TRUE;
|
|
|
|
}
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
return FALSE; /* Pass the key to GTK */
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
event_motion_notify (GtkWidget *widget,
|
|
|
|
GdkEventMotion *event,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
Snes9xWindow *window = (Snes9xWindow *) user_data;
|
|
|
|
|
|
|
|
if (!window->config->rom_loaded ||
|
|
|
|
window->last_width <= 0 ||
|
|
|
|
window->last_height <= 0)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2018-11-08 21:23:37 +01:00
|
|
|
if (window->mouse_grabbed)
|
|
|
|
{
|
|
|
|
if (event->x_root == window->mouse_reported_x &&
|
|
|
|
event->y_root == window->mouse_reported_y)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
window->mouse_loc_x += (event->x_root - window->mouse_reported_x);
|
|
|
|
window->mouse_loc_y += (event->y_root - window->mouse_reported_y);
|
|
|
|
window->center_mouse ();
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2018-05-23 22:50:57 +02:00
|
|
|
#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;
|
|
|
|
#endif
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
window->mouse_loc_x = (uint16)
|
2018-05-23 22:50:57 +02:00
|
|
|
((int) (event->x * scale_factor) - window->mouse_region_x) * 256 /
|
2010-09-25 17:46:12 +02:00
|
|
|
(window->mouse_region_width <= 0 ? 1 : window->mouse_region_width);
|
|
|
|
|
|
|
|
window->mouse_loc_y = (uint16)
|
2018-05-23 22:50:57 +02:00
|
|
|
((int) (event->y * scale_factor) - window->mouse_region_y) * (gui_config->overscan ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT) /
|
2010-09-25 17:46:12 +02:00
|
|
|
(window->mouse_region_height <= 0 ? 1 : window->mouse_region_height);
|
|
|
|
|
2010-09-26 11:19:15 +02:00
|
|
|
if (!window->config->pointer_is_visible)
|
|
|
|
{
|
|
|
|
if (!S9xIsMousePluggedIn ())
|
|
|
|
window->show_mouse_cursor ();
|
|
|
|
}
|
|
|
|
|
2018-10-28 22:55:33 +01:00
|
|
|
window->config->pointer_timestamp = g_get_monotonic_time ();
|
2010-09-26 11:19:15 +02:00
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
event_button_press (GtkWidget *widget,
|
|
|
|
GdkEventButton *event,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
switch (event->button)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
S9xReportButton (BINDING_MOUSE_BUTTON0, 1);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
S9xReportButton (BINDING_MOUSE_BUTTON1, 1);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
S9xReportButton (BINDING_MOUSE_BUTTON2, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
event_button_release (GtkWidget *widget,
|
|
|
|
GdkEventButton *event,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
switch (event->button)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
S9xReportButton (BINDING_MOUSE_BUTTON0, 0);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
S9xReportButton (BINDING_MOUSE_BUTTON1, 0);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
S9xReportButton (BINDING_MOUSE_BUTTON2, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
event_fullscreen (GtkWidget *widget, gpointer data)
|
|
|
|
{
|
|
|
|
Snes9xWindow *window = (Snes9xWindow *) data;
|
|
|
|
|
|
|
|
if (!window->config->fullscreen)
|
|
|
|
window->enter_fullscreen_mode ();
|
|
|
|
else
|
|
|
|
window->leave_fullscreen_mode ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
event_exact_pixels_1x (GtkWidget *widget, gpointer data)
|
|
|
|
{
|
2014-03-29 11:48:35 +01:00
|
|
|
((Snes9xWindow *) data)->resize_to_multiple (1);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
event_exact_pixels_2x (GtkWidget *widget, gpointer data)
|
|
|
|
{
|
2014-03-29 11:48:35 +01:00
|
|
|
((Snes9xWindow *) data)->resize_to_multiple (2);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
event_exact_pixels_3x (GtkWidget *widget, gpointer data)
|
|
|
|
{
|
2014-03-29 11:48:35 +01:00
|
|
|
((Snes9xWindow *) data)->resize_to_multiple (3);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
event_exact_pixels_4x (GtkWidget *widget, gpointer data)
|
|
|
|
{
|
2014-03-29 11:48:35 +01:00
|
|
|
((Snes9xWindow *) data)->resize_to_multiple (4);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
event_exact_pixels_5x (GtkWidget *widget, gpointer data)
|
|
|
|
{
|
2014-03-29 11:48:35 +01:00
|
|
|
((Snes9xWindow *) data)->resize_to_multiple (5);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-05-24 19:18:59 +02:00
|
|
|
static void
|
|
|
|
event_shader_parameters (GtkWidget *widget, gpointer data)
|
|
|
|
{
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
Snes9xWindow *window = (Snes9xWindow *) data;
|
|
|
|
|
|
|
|
gtk_shader_parameters_dialog (window->get_window ());
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
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;
|
2010-09-26 11:19:15 +02:00
|
|
|
char *name = (char *) gtk_buildable_get_name (GTK_BUILDABLE (widget));
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
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;
|
2010-09-26 11:19:15 +02:00
|
|
|
char *name = (char *) gtk_buildable_get_name (GTK_BUILDABLE (widget));
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
slot = atoi (&(name[11]));
|
|
|
|
|
|
|
|
S9xQuickLoadSlot (slot);
|
|
|
|
}
|
|
|
|
|
2018-06-09 17:23:26 +02:00
|
|
|
static void
|
|
|
|
event_load_state_undo (GtkWidget *widget, gpointer data)
|
|
|
|
{
|
2018-06-21 20:46:29 +02:00
|
|
|
S9xUnfreezeGame (S9xGetFilename (".undo", SNAPSHOT_DIR));
|
2018-06-09 17:23:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
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);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
event_focus_out (GtkWidget *widget, GdkEventFocus *event, gpointer data)
|
|
|
|
{
|
|
|
|
((Snes9xWindow *) data)->focus_notify (FALSE);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
event_port (GtkWidget *widget, gpointer data)
|
|
|
|
{
|
2010-09-26 11:19:15 +02:00
|
|
|
const gchar *name = gtk_buildable_get_name (GTK_BUILDABLE (widget));
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
if (!(gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!strcasecmp (name, "joypad1"))
|
|
|
|
{
|
|
|
|
S9xSetController (0, CTL_JOYPAD, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcasecmp (name, "joypad2"))
|
|
|
|
{
|
|
|
|
S9xSetController (1, CTL_JOYPAD, 1, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcasecmp (name, "mouse1"))
|
|
|
|
{
|
|
|
|
S9xSetController (0, CTL_MOUSE, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcasecmp (name, "mouse2"))
|
|
|
|
{
|
|
|
|
S9xSetController (1, CTL_MOUSE, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcasecmp (name, "superscope1"))
|
|
|
|
{
|
|
|
|
S9xSetController (0, CTL_SUPERSCOPE, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcasecmp (name, "superscope2"))
|
|
|
|
{
|
|
|
|
S9xSetController (1, CTL_SUPERSCOPE, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
2018-10-03 23:58:40 +02:00
|
|
|
else if (!strcasecmp (name, "multitap1"))
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
S9xSetController (0, CTL_MP5, 0, 1, 2, 3);
|
2018-10-03 23:58:40 +02:00
|
|
|
}
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
else if (!strcasecmp (name, "multitap2"))
|
|
|
|
{
|
|
|
|
S9xSetController (1, CTL_MP5, 1, 2, 3, 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Snes9xWindow::Snes9xWindow (Snes9xConfig *config) :
|
2010-09-26 11:19:15 +02:00
|
|
|
GtkBuilderWindow ("main_window")
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2010-09-26 11:19:15 +02:00
|
|
|
GtkBuilderWindowCallbacks callbacks[] =
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
{ "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) },
|
2018-05-24 19:18:59 +02:00
|
|
|
{ "on_shader_parameters_item_activate", G_CALLBACK (event_shader_parameters) },
|
2010-09-25 17:46:12 +02:00
|
|
|
{ "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) },
|
2018-06-09 17:23:26 +02:00
|
|
|
{ "load_state_undo", G_CALLBACK (event_load_state_undo) },
|
2010-09-25 17:46:12 +02:00
|
|
|
{ "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) },
|
|
|
|
{ "show_statusbar", G_CALLBACK (event_show_statusbar) },
|
|
|
|
{ "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;
|
2010-09-26 11:19:15 +02:00
|
|
|
empty_cursor = NULL;
|
|
|
|
default_cursor = NULL;
|
2010-09-25 17:46:12 +02:00
|
|
|
recent_menu = NULL;
|
|
|
|
fullscreen_state = 0;
|
|
|
|
maximized_state = 0;
|
|
|
|
focused = 1;
|
|
|
|
paused_from_focus_loss = 0;
|
2017-12-07 19:24:29 +01:00
|
|
|
cr = NULL;
|
|
|
|
cairo_owned = 0;
|
2018-11-08 21:23:37 +01:00
|
|
|
mouse_grabbed = 0;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), "snes9x"))
|
|
|
|
{
|
|
|
|
gtk_window_set_default_icon_name ("snes9x");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-09-12 02:32:10 +02:00
|
|
|
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)))
|
|
|
|
{
|
|
|
|
gtk_window_set_default_icon (icon);
|
|
|
|
}
|
|
|
|
g_object_unref(loader);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
drawing_area = GTK_DRAWING_AREA (get_widget ("drawingarea"));
|
2018-04-28 18:59:17 +02:00
|
|
|
#if GTK_MAJOR_VERSION < 3
|
2010-09-25 17:46:12 +02:00
|
|
|
gtk_widget_set_double_buffered (GTK_WIDGET (drawing_area), FALSE);
|
2018-10-29 22:14:40 +01:00
|
|
|
gtk_widget_set_app_paintable (GTK_WIDGET (drawing_area), TRUE);
|
2018-11-07 01:04:10 +01:00
|
|
|
|
2017-12-07 03:30:27 +01:00
|
|
|
#endif
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
gtk_widget_realize (window);
|
|
|
|
gtk_widget_realize (GTK_WIDGET (drawing_area));
|
2018-04-28 18:59:17 +02:00
|
|
|
#if GTK_MAJOR_VERSION < 3
|
2010-09-26 11:19:15 +02:00
|
|
|
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);
|
2011-02-05 13:36:27 +01:00
|
|
|
#endif
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
gtk_check_menu_item_set_active (
|
|
|
|
GTK_CHECK_MENU_ITEM (get_widget ("show_statusbar_item")),
|
|
|
|
config->statusbar_visible ? 1 : 0);
|
|
|
|
|
|
|
|
#ifdef NETPLAY_SUPPORT
|
|
|
|
#else
|
|
|
|
gtk_widget_hide (get_widget ("open_netplay_item"));
|
|
|
|
gtk_widget_hide (get_widget ("netplay_separator"));
|
|
|
|
gtk_widget_hide (get_widget ("sync_clients_item"));
|
|
|
|
gtk_widget_hide (get_widget ("sync_clients_separator"));
|
|
|
|
#endif
|
|
|
|
|
2018-05-24 19:18:59 +02:00
|
|
|
#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
|
|
|
|
|
2018-04-28 18:59:17 +02:00
|
|
|
#if GTK_MAJOR_VERSION >= 3
|
2011-02-06 02:42:26 +01:00
|
|
|
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
|
2010-09-25 17:46:12 +02:00
|
|
|
signal_connect (callbacks);
|
|
|
|
|
|
|
|
if (config->window_width < 100 || config->window_height < 100)
|
|
|
|
{
|
|
|
|
config->window_width = 256;
|
|
|
|
config->window_height = 224;
|
|
|
|
}
|
|
|
|
|
2017-12-07 03:30:27 +01:00
|
|
|
default_cursor = gdk_cursor_new_for_display (gdk_display_get_default (),GDK_LEFT_PTR);
|
2010-09-26 11:19:15 +02:00
|
|
|
gdk_window_set_cursor (gtk_widget_get_window (window), default_cursor);
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
resize (config->window_width, config->window_height);
|
|
|
|
}
|
|
|
|
|
2015-08-16 12:36:56 +02:00
|
|
|
extern const gtk_splash_t gtk_splash;
|
|
|
|
|
2010-09-26 11:19:15 +02:00
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::expose ()
|
2010-09-26 11:19:15 +02:00
|
|
|
{
|
2016-10-02 02:23:21 +02:00
|
|
|
if (last_width < 0)
|
2010-09-26 11:19:15 +02:00
|
|
|
{
|
|
|
|
if (!(config->fullscreen) && !(maximized_state))
|
|
|
|
{
|
|
|
|
config->window_width = get_width ();
|
|
|
|
config->window_height = get_height ();
|
|
|
|
}
|
|
|
|
|
2015-08-16 12:36:56 +02:00
|
|
|
/* Load splash image (RGB24) into Snes9x buffer (RGB15) */
|
|
|
|
last_width = 256;
|
|
|
|
last_height = 224;
|
|
|
|
|
|
|
|
uint16 *screen_ptr = GFX.Screen;
|
|
|
|
const unsigned char *splash_ptr = gtk_splash.pixel_data;
|
|
|
|
|
|
|
|
for (int y = 0; y < 224; y++, screen_ptr += (GFX.Pitch / 2))
|
|
|
|
{
|
|
|
|
for (int x = 0; x < 256; x++)
|
|
|
|
{
|
2018-05-04 21:28:50 +02:00
|
|
|
unsigned int red = *splash_ptr++;
|
2015-08-16 12:36:56 +02:00
|
|
|
unsigned int green = *splash_ptr++;
|
2018-05-04 21:28:50 +02:00
|
|
|
unsigned int blue = *splash_ptr++;
|
2015-08-16 12:36:56 +02:00
|
|
|
|
2018-05-04 21:28:50 +02:00
|
|
|
screen_ptr[x] = ((red & 0xF8) << 8) +
|
|
|
|
((green & 0xFC) << 3) +
|
2015-08-16 12:36:56 +02:00
|
|
|
((blue & 0xF8) >> 3);
|
|
|
|
}
|
|
|
|
}
|
2016-10-02 02:23:21 +02:00
|
|
|
}
|
2015-08-16 12:36:56 +02:00
|
|
|
|
2016-10-02 02:23:21 +02:00
|
|
|
S9xDisplayRefresh (last_width, last_height);
|
2010-09-26 11:19:15 +02:00
|
|
|
|
2016-10-02 02:23:21 +02:00
|
|
|
if (!(config->fullscreen))
|
|
|
|
{
|
|
|
|
config->window_width = get_width ();
|
|
|
|
config->window_height = get_height ();
|
|
|
|
}
|
2010-09-26 11:19:15 +02:00
|
|
|
|
2018-11-07 01:04:10 +01:00
|
|
|
if (is_paused ()
|
2010-09-26 11:19:15 +02:00
|
|
|
#ifdef NETPLAY_SUPPORT
|
2016-10-02 02:23:21 +02:00
|
|
|
|| NetPlay.Paused
|
2010-09-26 11:19:15 +02:00
|
|
|
#endif
|
2018-10-17 00:26:24 +02:00
|
|
|
)
|
2018-10-29 22:02:45 +01:00
|
|
|
{
|
2018-11-07 01:04:10 +01:00
|
|
|
S9xDeinitUpdate (last_width, last_height);
|
2018-10-29 22:02:45 +01:00
|
|
|
}
|
2010-09-26 11:19:15 +02:00
|
|
|
}
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
void
|
|
|
|
Snes9xWindow::focus_notify (int state)
|
|
|
|
{
|
|
|
|
focused = state ? 1 : 0;
|
|
|
|
|
|
|
|
if (!state && config->pause_emulation_on_switch)
|
|
|
|
{
|
|
|
|
sys_pause++;
|
|
|
|
propagate_pause_state ();
|
|
|
|
paused_from_focus_loss = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state && paused_from_focus_loss)
|
|
|
|
{
|
|
|
|
unpause_from_focus_change ();
|
|
|
|
paused_from_focus_loss = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::open_multicart_dialog ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
int result;
|
2010-09-26 11:19:15 +02:00
|
|
|
GtkBuilderWindow *dialog = new GtkBuilderWindow ("multicart_dialog");
|
2010-09-25 17:46:12 +02:00
|
|
|
GtkFileChooser *slota, *slotb;
|
|
|
|
GtkWidget *multicart_dialog = GTK_WIDGET (dialog->get_window ());
|
|
|
|
|
|
|
|
gtk_window_set_transient_for (dialog->get_window (), get_window ());
|
|
|
|
|
|
|
|
pause_from_focus_change ();
|
|
|
|
|
|
|
|
slota = GTK_FILE_CHOOSER (dialog->get_widget ("multicart_slota"));
|
|
|
|
slotb = GTK_FILE_CHOOSER (dialog->get_widget ("multicart_slotb"));
|
|
|
|
|
|
|
|
gtk_file_chooser_set_current_folder (slota, config->last_directory);
|
|
|
|
gtk_file_chooser_set_current_folder (slotb, config->last_directory);
|
|
|
|
|
|
|
|
result = gtk_dialog_run (GTK_DIALOG (multicart_dialog));
|
|
|
|
|
|
|
|
gtk_widget_hide (multicart_dialog);
|
|
|
|
|
|
|
|
if (result == GTK_RESPONSE_OK)
|
|
|
|
{
|
|
|
|
const gchar *filename;
|
|
|
|
|
|
|
|
filename = gtk_file_chooser_get_filename (slota);
|
|
|
|
if (filename)
|
|
|
|
strncpy (Settings.CartAName, filename, PATH_MAX);
|
|
|
|
else
|
|
|
|
Settings.CartAName[0] = '\0';
|
|
|
|
|
|
|
|
filename = gtk_file_chooser_get_filename (slotb);
|
|
|
|
if (filename)
|
|
|
|
strncpy (Settings.CartBName, filename, PATH_MAX);
|
|
|
|
else
|
|
|
|
Settings.CartBName[0] = '\0';
|
|
|
|
|
|
|
|
Settings.Multi = TRUE;
|
|
|
|
|
|
|
|
if (S9xOpenROM (NULL))
|
|
|
|
{
|
|
|
|
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."));
|
2010-09-26 11:19:15 +02:00
|
|
|
gtk_window_set_title (GTK_WINDOW (msg), _("Error"));
|
2010-09-25 17:46:12 +02:00
|
|
|
gtk_dialog_run (GTK_DIALOG (msg));
|
|
|
|
gtk_widget_destroy (msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-26 11:19:15 +02:00
|
|
|
delete dialog;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
unpause_from_focus_change ();
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
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 ();
|
|
|
|
|
|
|
|
if (readonly)
|
|
|
|
{
|
|
|
|
dialog = gtk_file_chooser_dialog_new (_("Open SNES Movie"),
|
|
|
|
GTK_WINDOW (this->window),
|
|
|
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
2017-12-07 03:30:27 +01:00
|
|
|
"gtk-cancel", GTK_RESPONSE_CANCEL,
|
|
|
|
"gtk-open", GTK_RESPONSE_ACCEPT,
|
2010-09-25 17:46:12 +02:00
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char def[PATH_MAX];
|
|
|
|
char default_name[PATH_MAX];
|
|
|
|
char drive[_MAX_DRIVE];
|
|
|
|
char dir[_MAX_DIR];
|
|
|
|
char ext[_MAX_EXT];
|
|
|
|
|
|
|
|
_splitpath (Memory.ROMFilename, drive, dir, def, ext);
|
|
|
|
|
2018-05-14 03:17:02 +02:00
|
|
|
snprintf (default_name, PATH_MAX, "%s.smv", def);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
dialog = gtk_file_chooser_dialog_new (_("New SNES Movie"),
|
|
|
|
GTK_WINDOW (this->window),
|
|
|
|
GTK_FILE_CHOOSER_ACTION_SAVE,
|
2017-12-07 03:30:27 +01:00
|
|
|
"gtk-cancel", GTK_RESPONSE_CANCEL,
|
|
|
|
"gtk-open", GTK_RESPONSE_ACCEPT,
|
2010-09-25 17:46:12 +02:00
|
|
|
NULL);
|
|
|
|
|
|
|
|
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog),
|
|
|
|
default_name);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
filter = gtk_file_filter_new ();
|
|
|
|
gtk_file_filter_set_name (filter, _("SNES Movies"));
|
|
|
|
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);
|
|
|
|
|
|
|
|
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
|
|
|
|
S9xGetDirectory (SRAM_DIR));
|
|
|
|
|
|
|
|
result = gtk_dialog_run (GTK_DIALOG (dialog));
|
2011-02-05 13:36:27 +01:00
|
|
|
gtk_widget_hide (dialog);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
if (result == GTK_RESPONSE_ACCEPT)
|
|
|
|
{
|
|
|
|
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
filename = strdup ("");
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_widget_destroy (dialog);
|
|
|
|
|
|
|
|
this->unpause_from_focus_change ();
|
|
|
|
|
|
|
|
return filename;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Snes9xWindow::open_rom_dialog ()
|
|
|
|
{
|
|
|
|
char *filename;
|
|
|
|
|
|
|
|
pause_from_focus_change ();
|
|
|
|
|
|
|
|
filename = S9xOpenROMDialog ();
|
|
|
|
|
|
|
|
if (filename)
|
|
|
|
{
|
|
|
|
Settings.Multi = FALSE;
|
|
|
|
try_open_rom (filename);
|
|
|
|
|
|
|
|
g_free (filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
unpause_from_focus_change ();
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
Snes9xWindow::try_open_rom (const char *filename)
|
|
|
|
{
|
|
|
|
pause_from_focus_change ();
|
|
|
|
|
|
|
|
Settings.Multi = FALSE;
|
|
|
|
|
|
|
|
if (S9xOpenROM (filename))
|
|
|
|
{
|
|
|
|
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);
|
2010-09-26 11:19:15 +02:00
|
|
|
gtk_window_set_title (GTK_WINDOW (msg), _("Error"));
|
2010-09-25 17:46:12 +02:00
|
|
|
gtk_dialog_run (GTK_DIALOG (msg));
|
|
|
|
gtk_widget_destroy (msg);
|
|
|
|
|
|
|
|
unpause_from_focus_change ();
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-04-07 23:43:34 +02:00
|
|
|
const char *groups[] = { "cartridge", NULL };
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
GtkRecentData recent_data =
|
|
|
|
{
|
|
|
|
NULL,
|
|
|
|
(gchar *) "SNES ROM",
|
|
|
|
(gchar *) "application/x-snes-rom",
|
|
|
|
(gchar *) "Snes9x",
|
|
|
|
NULL,
|
2012-04-07 23:43:34 +02:00
|
|
|
(gchar **) groups,
|
2010-09-25 17:46:12 +02:00
|
|
|
FALSE
|
|
|
|
};
|
|
|
|
gchar *u_filename;
|
|
|
|
|
|
|
|
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 ();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Snes9xWindow::load_state_dialog ()
|
|
|
|
{
|
|
|
|
GtkWidget *dialog;
|
|
|
|
GtkFileFilter *filter;
|
|
|
|
char *filename;
|
|
|
|
gint result;
|
|
|
|
|
|
|
|
this->pause_from_focus_change ();
|
|
|
|
|
|
|
|
dialog = gtk_file_chooser_dialog_new (_("Load Saved State"),
|
|
|
|
GTK_WINDOW (this->window),
|
|
|
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
2017-12-07 03:30:27 +01:00
|
|
|
"gtk-cancel", GTK_RESPONSE_CANCEL,
|
|
|
|
"gtk-open", GTK_RESPONSE_ACCEPT,
|
2010-09-25 17:46:12 +02:00
|
|
|
NULL);
|
|
|
|
|
|
|
|
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");
|
2017-04-25 21:45:30 +02:00
|
|
|
gtk_file_filter_add_pattern (filter, "*.009");
|
2010-09-25 17:46:12 +02:00
|
|
|
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));
|
2011-02-05 13:36:27 +01:00
|
|
|
gtk_widget_hide (dialog);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
if (result == GTK_RESPONSE_ACCEPT)
|
|
|
|
{
|
|
|
|
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
|
|
|
|
|
|
|
S9xLoadState (filename);
|
|
|
|
|
|
|
|
g_free (filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_widget_destroy (dialog);
|
|
|
|
|
|
|
|
this->unpause_from_focus_change ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::movie_seek_dialog ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
char str[1024];
|
|
|
|
gint result;
|
|
|
|
|
|
|
|
if (!S9xMovieActive ())
|
|
|
|
return;
|
|
|
|
|
2010-09-26 11:19:15 +02:00
|
|
|
GtkBuilderWindow *seek_dialog = new GtkBuilderWindow ("frame_advance_dialog");
|
|
|
|
GtkWindow *seek_window = seek_dialog->get_window ();
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
pause_from_focus_change ();
|
|
|
|
|
2010-09-26 11:19:15 +02:00
|
|
|
snprintf (str, 1024, _("The current frame in the movie is <b>%d</b>."), S9xMovieGetFrameCounter ());
|
|
|
|
gtk_label_set_label (GTK_LABEL (seek_dialog->get_widget ("current_frame_label")), str);
|
|
|
|
|
|
|
|
snprintf (str, 1024, "%d", S9xMovieGetFrameCounter ());
|
|
|
|
seek_dialog->set_entry_text ("frame_entry", str);
|
|
|
|
|
|
|
|
gtk_window_set_transient_for (seek_window, get_window ());
|
|
|
|
|
|
|
|
result = gtk_dialog_run (GTK_DIALOG (seek_window));
|
|
|
|
|
|
|
|
int entry_value = seek_dialog->get_entry_value ("frame_entry");
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
switch (result)
|
|
|
|
{
|
|
|
|
case GTK_RESPONSE_OK:
|
|
|
|
|
|
|
|
if (entry_value > 0 &&
|
|
|
|
entry_value > (int) S9xMovieGetFrameCounter ())
|
|
|
|
{
|
|
|
|
Settings.HighSpeedSeek =
|
|
|
|
entry_value - S9xMovieGetFrameCounter ();
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-09-26 11:19:15 +02:00
|
|
|
delete seek_dialog;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
unpause_from_focus_change ();
|
|
|
|
}
|
|
|
|
|
|
|
|
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];
|
|
|
|
|
|
|
|
this->pause_from_focus_change ();
|
|
|
|
|
|
|
|
_splitpath (Memory.ROMFilename, drive, dir, def, ext);
|
|
|
|
|
2018-05-14 03:17:02 +02:00
|
|
|
snprintf (default_name, PATH_MAX, "%s.sst", def);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
dialog = gtk_file_chooser_dialog_new (_("Save State"),
|
|
|
|
GTK_WINDOW (this->window),
|
|
|
|
GTK_FILE_CHOOSER_ACTION_SAVE,
|
2017-12-07 03:30:27 +01:00
|
|
|
"gtk-cancel", GTK_RESPONSE_CANCEL,
|
|
|
|
"gtk-save", GTK_RESPONSE_ACCEPT,
|
2010-09-25 17:46:12 +02:00
|
|
|
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");
|
2017-04-25 21:45:30 +02:00
|
|
|
gtk_file_filter_add_pattern (filter, "*.009");
|
2010-09-25 17:46:12 +02:00
|
|
|
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));
|
|
|
|
|
2011-02-05 13:36:27 +01:00
|
|
|
gtk_widget_hide (dialog);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
if (result == GTK_RESPONSE_ACCEPT)
|
|
|
|
{
|
|
|
|
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
|
|
|
|
|
|
|
S9xSaveState (filename);
|
|
|
|
|
|
|
|
g_free (filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_widget_destroy (dialog);
|
|
|
|
|
|
|
|
this->unpause_from_focus_change ();
|
|
|
|
}
|
|
|
|
|
|
|
|
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];
|
|
|
|
|
|
|
|
this->pause_from_focus_change ();
|
|
|
|
|
|
|
|
_splitpath (Memory.ROMFilename, drive, dir, def, ext);
|
|
|
|
|
2018-05-14 03:17:02 +02:00
|
|
|
snprintf (default_name, PATH_MAX, "%s.spc", def);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
dialog = gtk_file_chooser_dialog_new (_("Save SPC file..."),
|
|
|
|
GTK_WINDOW (this->window),
|
|
|
|
GTK_FILE_CHOOSER_ACTION_SAVE,
|
2017-12-07 03:30:27 +01:00
|
|
|
"gtk-cancel", GTK_RESPONSE_CANCEL,
|
|
|
|
"gtk-save", GTK_RESPONSE_ACCEPT,
|
2010-09-25 17:46:12 +02:00
|
|
|
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));
|
|
|
|
|
2011-02-05 13:36:27 +01:00
|
|
|
gtk_widget_hide (dialog);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
if (result == GTK_RESPONSE_ACCEPT)
|
|
|
|
{
|
|
|
|
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
|
|
|
|
|
|
|
if (S9xSPCDump (filename))
|
|
|
|
{
|
|
|
|
/* 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);
|
2010-09-26 11:19:15 +02:00
|
|
|
gtk_window_set_title (GTK_WINDOW (msg), _("Error"));
|
2010-09-25 17:46:12 +02:00
|
|
|
gtk_dialog_run (GTK_DIALOG (msg));
|
|
|
|
gtk_widget_destroy (msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_widget_destroy (dialog);
|
|
|
|
|
|
|
|
this->unpause_from_focus_change ();
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
statusbar_timeout (gpointer data)
|
|
|
|
{
|
|
|
|
gtk_statusbar_pop (GTK_STATUSBAR (data),
|
|
|
|
gtk_statusbar_get_context_id (GTK_STATUSBAR (data),
|
|
|
|
"info"));
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Snes9xWindow::show_status_message (const char *message)
|
|
|
|
{
|
|
|
|
GtkStatusbar *statusbar = GTK_STATUSBAR (get_widget ("statusbar"));
|
|
|
|
|
|
|
|
gtk_statusbar_pop (statusbar, gtk_statusbar_get_context_id (statusbar, "info"));
|
|
|
|
gtk_statusbar_push (statusbar, gtk_statusbar_get_context_id (statusbar, "info"), message);
|
|
|
|
|
2010-09-26 11:19:15 +02:00
|
|
|
g_timeout_add (2000, statusbar_timeout, statusbar);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::update_statusbar ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
GtkStatusbar *bar = GTK_STATUSBAR (get_widget ("statusbar"));
|
|
|
|
char status_string[256];
|
|
|
|
char title_string[1024];
|
|
|
|
|
|
|
|
if (!config->rom_loaded)
|
|
|
|
{
|
|
|
|
snprintf (title_string, 1024, "Snes9x");
|
|
|
|
status_string[0] = '\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#ifdef NETPLAY_SUPPORT
|
|
|
|
if (config->netplay_activated)
|
|
|
|
{
|
|
|
|
if (config->netplay_server_up)
|
|
|
|
{
|
|
|
|
snprintf (status_string,
|
|
|
|
256,
|
|
|
|
_("%sHosting NetPlay - %s"),
|
|
|
|
is_paused () || NetPlay.Paused ? _("Paused - ") : "",
|
|
|
|
S9xBasenameNoExt (Memory.ROMFilename));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
snprintf (status_string,
|
|
|
|
256,
|
|
|
|
_("%s%s on NetPlay %s:%d - Player %d"),
|
|
|
|
is_paused () || NetPlay.Paused ? _("Paused - ") : "",
|
|
|
|
S9xBasenameNoExt (Memory.ROMFilename),
|
|
|
|
NetPlay.ServerHostName,
|
|
|
|
NetPlay.Port,
|
|
|
|
NetPlay.Player);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
snprintf (status_string,
|
|
|
|
256,
|
|
|
|
"%s%s",
|
|
|
|
is_paused () ? _("Paused - ") : "",
|
|
|
|
S9xBasenameNoExt (Memory.ROMFilename));
|
|
|
|
}
|
|
|
|
|
2018-11-06 01:17:48 +01:00
|
|
|
snprintf (title_string, 1024, "%s", S9xBasenameNoExt (Memory.ROMFilename));
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
gtk_window_set_title (GTK_WINDOW (window), title_string);
|
|
|
|
gtk_statusbar_pop (bar, gtk_statusbar_get_context_id (bar, "none"));
|
|
|
|
gtk_statusbar_push (bar, gtk_statusbar_get_context_id (bar, "none"), status_string);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::show_rom_info ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
GtkWidget *msg;
|
|
|
|
|
|
|
|
pause_from_focus_change ();
|
|
|
|
|
|
|
|
msg = gtk_message_dialog_new_with_markup (GTK_WINDOW (window),
|
|
|
|
GTK_DIALOG_DESTROY_WITH_PARENT,
|
2010-09-26 11:19:15 +02:00
|
|
|
GTK_MESSAGE_OTHER,
|
2010-09-25 17:46:12 +02:00
|
|
|
GTK_BUTTONS_CLOSE,
|
|
|
|
_("<b>Information for %s</b>\n\n"
|
|
|
|
"<i>Name:</i> %s\n"
|
|
|
|
"<i>Speed:</i> %02X/%s\n"
|
|
|
|
"<i>Map:</i> %s\n"
|
|
|
|
"<i>Type:</i> %02x\n"
|
|
|
|
"<i>Contents:</i> %s\n"
|
|
|
|
"<i>ROM Size:</i> %s\n"
|
|
|
|
"<i>Calculated Size:</i> %d\n"
|
|
|
|
"<i>SRAM Size:</i> %s\n"
|
|
|
|
"<i>Header Checksum:</i> %04X\n"
|
|
|
|
"<i>Checksum Compliment:</i> %04X\n"
|
|
|
|
"<i>Actual Checksum:</i> %04X\n"
|
|
|
|
"<i>Video:</i> %s\n"
|
|
|
|
"<i>CRC32:</i> %08X\n"
|
|
|
|
"<i>Revision:</i> %s"
|
|
|
|
"<b><i>%s</i></b>"),
|
|
|
|
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 (),
|
|
|
|
(Memory.ROMChecksum !=
|
|
|
|
Memory.CalculatedChecksum) ?
|
|
|
|
_("\n\nThis ROM has been modified or damaged")
|
|
|
|
: "");
|
2010-09-26 11:19:15 +02:00
|
|
|
gtk_window_set_title (GTK_WINDOW (msg), _("File Information"));
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
gtk_dialog_run (GTK_DIALOG (msg));
|
|
|
|
|
|
|
|
unpause_from_focus_change ();
|
|
|
|
|
|
|
|
gtk_widget_destroy (msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::configure_widgets ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
|
|
|
#ifdef NETPLAY_SUPPORT
|
|
|
|
enable_widget ("sync_clients_item",
|
|
|
|
config->rom_loaded &&
|
|
|
|
Settings.NetPlay &&
|
|
|
|
Settings.NetPlayServer);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (config->default_esc_behavior != ESC_TOGGLE_MENUBAR)
|
|
|
|
{
|
|
|
|
enable_widget ("fullscreen_item", config->rom_loaded);
|
|
|
|
|
|
|
|
config->ui_visible = TRUE;
|
|
|
|
|
|
|
|
if (!config->fullscreen)
|
|
|
|
{
|
|
|
|
gtk_widget_show (get_widget ("menubar"));
|
|
|
|
|
|
|
|
if (config->statusbar_visible)
|
|
|
|
gtk_widget_show (get_widget ("statusbar"));
|
|
|
|
else
|
|
|
|
gtk_widget_hide (get_widget ("statusbar"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gtk_widget_hide (get_widget ("menubar"));
|
|
|
|
gtk_widget_hide (get_widget ("statusbar"));
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_widget_hide (get_widget ("hide_ui"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
enable_widget ("fullscreen_item", TRUE);
|
|
|
|
|
|
|
|
gtk_widget_show (get_widget ("hide_ui"));
|
|
|
|
|
|
|
|
if (config->ui_visible)
|
|
|
|
{
|
|
|
|
gtk_widget_show (get_widget ("menubar"));
|
|
|
|
if (config->statusbar_visible)
|
|
|
|
gtk_widget_show (get_widget ("statusbar"));
|
|
|
|
else
|
|
|
|
gtk_widget_hide (get_widget ("statusbar"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gtk_widget_hide (get_widget ("menubar"));
|
|
|
|
gtk_widget_hide (get_widget ("statusbar"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-26 11:19:15 +02:00
|
|
|
propagate_pause_state ();
|
|
|
|
|
|
|
|
if (config->rom_loaded && !Settings.Paused)
|
2010-09-25 17:46:12 +02:00
|
|
|
hide_mouse_cursor ();
|
|
|
|
else
|
|
|
|
show_mouse_cursor ();
|
|
|
|
}
|
|
|
|
|
|
|
|
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_height = height;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::reset_screensaver ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
if (!focused)
|
|
|
|
return;
|
|
|
|
|
2018-05-09 23:43:10 +02:00
|
|
|
#ifdef GDK_WINDOWING_X11
|
|
|
|
if (GDK_IS_X11_WINDOW (gtk_widget_get_window (GTK_WIDGET (window))))
|
|
|
|
{
|
|
|
|
XResetScreenSaver (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef GDK_WINDOWING_WAYLAND
|
|
|
|
if (GDK_IS_WAYLAND_WINDOW (gtk_widget_get_window (GTK_WIDGET (window))))
|
|
|
|
{
|
|
|
|
// TODO screensaver for wayland
|
|
|
|
}
|
|
|
|
#endif
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
config->screensaver_needs_reset = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::toggle_fullscreen_mode ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
if (config->fullscreen)
|
|
|
|
leave_fullscreen_mode ();
|
|
|
|
else
|
|
|
|
enter_fullscreen_mode ();
|
|
|
|
}
|
|
|
|
|
2018-05-03 00:43:32 +02:00
|
|
|
static double XRRGetExactRefreshRate (Display *dpy, Window window)
|
|
|
|
{
|
|
|
|
XRRScreenResources *resources = NULL;
|
|
|
|
XRRCrtcInfo *crtc_info = NULL;
|
|
|
|
int event_base;
|
|
|
|
int error_base;
|
|
|
|
int version_major;
|
|
|
|
int version_minor;
|
|
|
|
double refresh_rate = 0.0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!XRRQueryExtension (dpy, &event_base, &error_base) ||
|
|
|
|
!XRRQueryVersion (dpy, &version_major, &version_minor))
|
|
|
|
{
|
|
|
|
return refresh_rate;
|
|
|
|
}
|
|
|
|
|
2018-05-05 00:52:29 +02:00
|
|
|
if (version_minor < 3)
|
|
|
|
return refresh_rate;
|
|
|
|
|
|
|
|
resources = XRRGetScreenResourcesCurrent (dpy, window);
|
|
|
|
crtc_info = XRRGetCrtcInfo (dpy, resources, resources->crtcs[0]);
|
2018-05-03 00:43:32 +02:00
|
|
|
|
|
|
|
for (i = 0; i < resources->nmode; i++)
|
|
|
|
{
|
|
|
|
if (resources->modes[i].id == crtc_info->mode)
|
|
|
|
{
|
|
|
|
XRRModeInfo *m = &resources->modes[i];
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
XRRFreeCrtcInfo (crtc_info);
|
|
|
|
XRRFreeScreenResources (resources);
|
|
|
|
|
|
|
|
return refresh_rate;
|
|
|
|
}
|
|
|
|
|
|
|
|
double
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::get_refresh_rate ()
|
2018-05-03 00:43:32 +02:00
|
|
|
{
|
2018-05-09 23:29:59 +02:00
|
|
|
double refresh_rate = 0.0;
|
|
|
|
GdkDisplay *display = gtk_widget_get_display (window);
|
|
|
|
GdkWindow *gdk_window = gtk_widget_get_window (window);
|
2018-10-15 21:18:21 +02:00
|
|
|
|
2018-05-09 23:29:59 +02:00
|
|
|
#ifdef GDK_WINDOWING_X11
|
|
|
|
if (GDK_IS_X11_DISPLAY (display))
|
|
|
|
{
|
2018-11-07 01:46:44 +01:00
|
|
|
Window xid = gdk_x11_window_get_xid (gtk_widget_get_window (window));
|
2018-10-15 21:18:21 +02:00
|
|
|
Display *dpy = gdk_x11_display_get_xdisplay (gtk_widget_get_display (window));
|
|
|
|
refresh_rate = XRRGetExactRefreshRate (dpy, xid);
|
|
|
|
}
|
2018-05-09 23:29:59 +02:00
|
|
|
#endif
|
2018-10-15 21:18:21 +02:00
|
|
|
|
2018-05-09 23:29:59 +02:00
|
|
|
#ifdef GDK_WINDOWING_WAYLAND
|
|
|
|
if (GDK_IS_WAYLAND_DISPLAY (display))
|
|
|
|
{
|
|
|
|
GdkMonitor *monitor = gdk_display_get_monitor_at_window(display, gdk_window);
|
|
|
|
refresh_rate = (double) gdk_monitor_get_refresh_rate(monitor) / 1000.0;
|
|
|
|
}
|
|
|
|
#endif
|
2018-10-15 21:18:21 +02:00
|
|
|
|
2018-05-03 00:43:32 +02:00
|
|
|
if (refresh_rate < 10.0)
|
|
|
|
{
|
|
|
|
printf ("Warning: Couldn't read refresh rate.\n");
|
|
|
|
refresh_rate = 60.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return refresh_rate;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::get_auto_input_rate ()
|
2018-05-03 00:43:32 +02:00
|
|
|
{
|
2018-06-07 22:49:41 +02:00
|
|
|
double refresh_rate = get_refresh_rate ();
|
2018-06-07 16:42:25 +02:00
|
|
|
|
2018-06-07 22:49:41 +02:00
|
|
|
if (refresh_rate == 0.0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Try for a close multiple of 60hz
|
|
|
|
if (refresh_rate > 119.0 && refresh_rate < 121.0)
|
|
|
|
refresh_rate /= 2.0;
|
|
|
|
if (refresh_rate > 179.0 && refresh_rate < 181.0)
|
|
|
|
refresh_rate /= 3.0;
|
|
|
|
if (refresh_rate > 239.0 && refresh_rate < 241.0)
|
|
|
|
refresh_rate /= 4.0;
|
|
|
|
|
|
|
|
double new_input_rate = refresh_rate * 32040.0 / 60.09881389744051 + 0.5;
|
|
|
|
|
|
|
|
if (new_input_rate > 32040.0 * 1.05 || new_input_rate < 32040.0 * 0.95)
|
|
|
|
new_input_rate = 0.0;
|
2018-06-07 16:42:25 +02:00
|
|
|
|
|
|
|
return new_input_rate;
|
2018-05-03 00:43:32 +02:00
|
|
|
}
|
|
|
|
|
2018-10-15 21:31:42 +02:00
|
|
|
#ifdef GDK_WINDOWING_X11
|
2018-04-28 19:49:36 +02:00
|
|
|
static void set_bypass_compositor (Display *dpy, Window window, unsigned char bypass)
|
|
|
|
{
|
2018-05-05 01:31:25 +02:00
|
|
|
uint32 value = bypass;
|
2018-04-28 19:49:36 +02:00
|
|
|
Atom net_wm_bypass_compositor = XInternAtom (dpy, "_NET_WM_BYPASS_COMPOSITOR", False);
|
2018-05-05 01:31:25 +02:00
|
|
|
XChangeProperty (dpy, window, net_wm_bypass_compositor, XA_CARDINAL, 32, PropModeReplace, (const unsigned char *) &value, 1);
|
2018-04-28 19:49:36 +02:00
|
|
|
}
|
2018-10-15 21:31:42 +02:00
|
|
|
#endif
|
2018-04-28 19:49:36 +02:00
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::enter_fullscreen_mode ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
int rom_loaded = config->rom_loaded;
|
|
|
|
|
|
|
|
if (config->fullscreen)
|
|
|
|
return;
|
|
|
|
|
|
|
|
config->rom_loaded = 0;
|
|
|
|
|
|
|
|
nfs_width = config->window_width;
|
|
|
|
nfs_height = config->window_height;
|
|
|
|
|
|
|
|
gtk_window_get_position (GTK_WINDOW (window), &nfs_x, &nfs_y);
|
|
|
|
|
|
|
|
if (config->change_display_resolution)
|
|
|
|
{
|
2018-04-29 01:36:40 +02:00
|
|
|
GdkDisplay *gdk_display = gtk_widget_get_display (window);
|
|
|
|
Display *dpy = gdk_x11_display_get_xdisplay (gdk_display);
|
|
|
|
|
|
|
|
gdk_display_sync (gdk_display);
|
|
|
|
if (XRRSetCrtcConfig (dpy,
|
|
|
|
config->xrr_screen_resources,
|
2018-05-05 00:52:29 +02:00
|
|
|
config->xrr_screen_resources->crtcs[0],
|
2018-04-29 01:36:40 +02:00
|
|
|
CurrentTime,
|
|
|
|
config->xrr_crtc_info->x,
|
|
|
|
config->xrr_crtc_info->y,
|
2018-05-05 00:52:29 +02:00
|
|
|
config->xrr_screen_resources->modes[config->xrr_index].id,
|
2018-04-29 01:36:40 +02:00
|
|
|
config->xrr_crtc_info->rotation,
|
2018-05-05 00:52:29 +02:00
|
|
|
&config->xrr_crtc_info->outputs[0],
|
2018-04-29 01:36:40 +02:00
|
|
|
1) != 0)
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
config->change_display_resolution = 0;
|
|
|
|
}
|
2018-05-03 00:43:32 +02:00
|
|
|
|
|
|
|
if (gui_config->auto_input_rate)
|
|
|
|
{
|
|
|
|
Settings.SoundInputRate = top_level->get_auto_input_rate ();
|
2018-05-03 00:51:58 +02:00
|
|
|
S9xUpdateDynamicRate (1, 2);
|
2018-05-03 00:43:32 +02:00
|
|
|
}
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
2018-04-29 01:36:40 +02:00
|
|
|
/* Make sure everything is done synchronously */
|
|
|
|
gdk_display_sync (gdk_display_get_default ());
|
|
|
|
gtk_window_fullscreen (GTK_WINDOW (window));
|
2018-04-28 19:49:36 +02:00
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
gdk_display_sync (gdk_display_get_default ());
|
2010-09-26 11:19:15 +02:00
|
|
|
gtk_window_present (GTK_WINDOW (window));
|
2018-05-10 18:36:54 +02:00
|
|
|
#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))),
|
2018-11-07 01:46:44 +01:00
|
|
|
gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (window))),
|
2018-05-10 18:36:54 +02:00
|
|
|
1);
|
|
|
|
}
|
|
|
|
#endif
|
2010-09-25 17:46:12 +02:00
|
|
|
config->fullscreen = 1;
|
|
|
|
config->rom_loaded = rom_loaded;
|
|
|
|
|
|
|
|
/* If we're running a game, disable ui when entering fullscreen */
|
|
|
|
if (!Settings.Paused && config->rom_loaded)
|
|
|
|
config->ui_visible = FALSE;
|
|
|
|
|
|
|
|
configure_widgets ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::leave_fullscreen_mode ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
int rom_loaded = config->rom_loaded;
|
|
|
|
|
|
|
|
if (!config->fullscreen)
|
|
|
|
return;
|
|
|
|
|
|
|
|
config->rom_loaded = 0;
|
|
|
|
|
|
|
|
if (config->change_display_resolution)
|
|
|
|
{
|
2011-02-11 10:44:47 +01:00
|
|
|
GdkDisplay *gdk_display = gtk_widget_get_display (window);
|
2018-04-29 01:36:40 +02:00
|
|
|
Display *dpy = gdk_x11_display_get_xdisplay (gdk_display);
|
|
|
|
|
2018-05-05 00:52:29 +02:00
|
|
|
if (config->xrr_index > config->xrr_screen_resources->nmode)
|
2018-04-29 01:36:40 +02:00
|
|
|
config->xrr_index = 0;
|
|
|
|
|
|
|
|
gdk_display_sync (gdk_display);
|
|
|
|
XRRSetCrtcConfig (dpy,
|
|
|
|
config->xrr_screen_resources,
|
2018-05-05 00:52:29 +02:00
|
|
|
config->xrr_screen_resources->crtcs[0],
|
2018-04-29 01:36:40 +02:00
|
|
|
CurrentTime,
|
|
|
|
config->xrr_crtc_info->x,
|
|
|
|
config->xrr_crtc_info->y,
|
|
|
|
config->xrr_crtc_info->mode,
|
|
|
|
config->xrr_crtc_info->rotation,
|
2018-05-05 00:52:29 +02:00
|
|
|
&config->xrr_crtc_info->outputs[0],
|
2018-04-29 01:36:40 +02:00
|
|
|
1);
|
2018-05-03 00:43:32 +02:00
|
|
|
|
|
|
|
if (gui_config->auto_input_rate)
|
|
|
|
{
|
|
|
|
Settings.SoundInputRate = top_level->get_auto_input_rate ();
|
2018-05-03 00:51:58 +02:00
|
|
|
S9xUpdateDynamicRate (1, 2);
|
2018-05-03 00:43:32 +02:00
|
|
|
}
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
gtk_window_unfullscreen (GTK_WINDOW (window));
|
|
|
|
|
2018-05-10 18:36:54 +02:00
|
|
|
#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))),
|
2018-11-07 01:46:44 +01:00
|
|
|
gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (window))),
|
2018-05-10 18:36:54 +02:00
|
|
|
0);
|
|
|
|
}
|
|
|
|
#endif
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
resize (nfs_width, nfs_height);
|
|
|
|
gtk_window_move (GTK_WINDOW (window), nfs_x, nfs_y);
|
|
|
|
|
|
|
|
config->rom_loaded = rom_loaded;
|
|
|
|
|
|
|
|
config->fullscreen = 0;
|
|
|
|
|
|
|
|
configure_widgets ();
|
|
|
|
}
|
|
|
|
|
2014-03-30 05:15:04 +02:00
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::toggle_statusbar ()
|
2014-03-30 05:15:04 +02:00
|
|
|
{
|
|
|
|
GtkWidget *item;
|
|
|
|
GtkAllocation allocation;
|
|
|
|
int width = 0;
|
|
|
|
int height = 0;
|
|
|
|
|
2018-11-07 22:09:27 +01:00
|
|
|
item = get_widget ("menubar");
|
|
|
|
gtk_widget_get_allocation (item, &allocation);
|
|
|
|
height += gtk_widget_get_visible (item) ? allocation.height : 0;
|
2014-03-30 05:15:04 +02:00
|
|
|
|
|
|
|
item = get_widget ("drawingarea");
|
|
|
|
gtk_widget_get_allocation (item, &allocation);
|
|
|
|
height += allocation.height;
|
|
|
|
width = allocation.width;
|
|
|
|
|
|
|
|
config->statusbar_visible = !config->statusbar_visible;
|
|
|
|
configure_widgets ();
|
|
|
|
|
|
|
|
item = get_widget ("statusbar");
|
|
|
|
gtk_widget_get_allocation (item, &allocation);
|
|
|
|
height += gtk_widget_get_visible (item) ? allocation.height : 0;
|
|
|
|
|
|
|
|
resize (width, height);
|
|
|
|
}
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
void
|
|
|
|
Snes9xWindow::resize_viewport (int width, int height)
|
|
|
|
{
|
2010-09-26 11:19:15 +02:00
|
|
|
GtkWidget *item;
|
|
|
|
GtkAllocation allocation;
|
|
|
|
int y_padding = 0;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2018-11-07 22:09:27 +01:00
|
|
|
item = get_widget ("menubar");
|
|
|
|
gtk_widget_get_allocation (item, &allocation);
|
|
|
|
y_padding += gtk_widget_get_visible (item) ? allocation.height : 0;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
item = get_widget ("statusbar");
|
2010-09-26 11:19:15 +02:00
|
|
|
gtk_widget_get_allocation (item, &allocation);
|
|
|
|
y_padding += gtk_widget_get_visible (item) ? allocation.height : 0;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
resize (width, height + y_padding);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::hide_mouse_cursor ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2010-09-26 11:19:15 +02:00
|
|
|
if (!empty_cursor)
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2017-12-07 03:30:27 +01:00
|
|
|
empty_cursor = gdk_cursor_new_for_display (gdk_display_get_default (), GDK_BLANK_CURSOR);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
2010-09-26 11:19:15 +02:00
|
|
|
gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (drawing_area)),
|
|
|
|
empty_cursor);
|
|
|
|
config->pointer_is_visible = FALSE;
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::show_mouse_cursor ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2010-09-26 11:19:15 +02:00
|
|
|
gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (drawing_area)),
|
|
|
|
NULL);
|
|
|
|
config->pointer_is_visible = TRUE;
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
2018-11-08 21:23:37 +01:00
|
|
|
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;
|
|
|
|
|
|
|
|
gdk_window_get_origin (gdk_window, &x, &y);
|
|
|
|
w = gdk_window_get_width (gdk_window);
|
|
|
|
h = gdk_window_get_height (gdk_window);
|
|
|
|
|
|
|
|
mouse_reported_x = x + w / 2;
|
|
|
|
mouse_reported_y = y + h / 2;
|
|
|
|
|
|
|
|
#if GTK_MAJOR_VERSION < 3
|
|
|
|
gdk_display_warp_pointer (gdk_display, gdk_screen, mouse_reported_x,
|
|
|
|
mouse_reported_y);
|
|
|
|
#elif GTK_MINOR_VERSION < 20
|
|
|
|
GdkDeviceManager *manager = gdk_display_get_device_manager (gdk_display);
|
|
|
|
GdkDevice *pointer = gdk_device_manager_get_client_pointer (manager);
|
|
|
|
|
|
|
|
gdk_device_warp (pointer, gdk_screen, mouse_reported_x, mouse_reported_y);
|
|
|
|
#else
|
|
|
|
GdkSeat *seat = gdk_display_get_default_seat (gdk_display);
|
|
|
|
GdkDevice *pointer = gdk_seat_get_pointer (seat);
|
|
|
|
|
|
|
|
gdk_device_warp (pointer, gdk_screen, mouse_reported_x, mouse_reported_y);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
return;
|
|
|
|
|
|
|
|
#if GTK_MAJOR_VERSION < 3
|
|
|
|
if (!mouse_grabbed)
|
|
|
|
{
|
|
|
|
gdk_pointer_grab (gdk_window, TRUE, (GdkEventMask) 1020, gdk_window, empty_cursor, GDK_CURRENT_TIME);
|
|
|
|
center_mouse ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gdk_pointer_ungrab (GDK_CURRENT_TIME);
|
|
|
|
if (config->pointer_is_visible)
|
|
|
|
show_mouse_cursor ();
|
|
|
|
}
|
|
|
|
#elif GTK_MINOR_VERSION < 20
|
|
|
|
GdkDeviceManager *manager = gdk_display_get_device_manager (gdk_display);
|
|
|
|
GdkDevice *pointer = gdk_device_manager_get_client_pointer (manager);
|
|
|
|
|
|
|
|
if (!mouse_grabbed)
|
|
|
|
gdk_device_grab (pointer, gdk_window, GDK_OWNERSHIP_NONE, TRUE,
|
|
|
|
(GdkEventMask) 1020, empty_cursor, GDK_CURRENT_TIME);
|
|
|
|
else
|
|
|
|
gdk_device_ungrab (pointer, GDK_CURRENT_TIME);
|
|
|
|
#else
|
|
|
|
GdkSeat *seat = gdk_display_get_default_seat (gdk_display);
|
|
|
|
|
|
|
|
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);
|
|
|
|
mouse_loc_x = 0; mouse_loc_y = 0;
|
|
|
|
mouse_grabbed ^= 1;
|
|
|
|
if (mouse_grabbed)
|
|
|
|
center_mouse ();
|
|
|
|
}
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::show ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
gtk_widget_show (window);
|
|
|
|
|
|
|
|
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 ());
|
|
|
|
|
|
|
|
GtkRecentFilter *filter = gtk_recent_filter_new ();
|
|
|
|
GtkRecentChooser *chooser = GTK_RECENT_CHOOSER (recent_menu);
|
|
|
|
|
2012-04-07 23:43:34 +02:00
|
|
|
gtk_recent_filter_add_group (filter, "cartridge");
|
2010-09-25 17:46:12 +02:00
|
|
|
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);
|
2010-09-26 11:19:15 +02:00
|
|
|
|
|
|
|
gtk_widget_show (recent_menu);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::propagate_pause_state ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
int oldpause = Settings.Paused;
|
|
|
|
|
|
|
|
Settings.Paused = (sys_pause || user_pause || !(config->rom_loaded));
|
|
|
|
|
|
|
|
if (Settings.Paused != oldpause)
|
|
|
|
{
|
|
|
|
if (!is_paused ())
|
|
|
|
{
|
|
|
|
S9xSoundStart ();
|
|
|
|
if (config->rom_loaded)
|
|
|
|
enable_widget ("pause_item", TRUE);
|
|
|
|
|
|
|
|
S9xDisplayClearBuffers ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
S9xSoundStop ();
|
|
|
|
enable_widget ("pause_item", FALSE);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-09-26 11:19:15 +02:00
|
|
|
configure_widgets ();
|
2010-09-25 17:46:12 +02:00
|
|
|
update_statusbar ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::toggle_ui ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
config->ui_visible = !config->ui_visible;
|
|
|
|
|
|
|
|
configure_widgets ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* gui_[un]pause Handles when system needs to pause the emulator */
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::pause_from_focus_change ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2010-10-30 16:21:26 +02:00
|
|
|
sys_pause += config->modal_dialogs;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
propagate_pause_state ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::unpause_from_focus_change ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2010-10-30 16:21:26 +02:00
|
|
|
if (--sys_pause < 0)
|
|
|
|
sys_pause = 0;
|
2010-09-25 17:46:12 +02:00
|
|
|
propagate_pause_state ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* client_[un]pause Handles when user manually chooses to pause */
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::pause_from_user ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
user_pause = TRUE;
|
|
|
|
propagate_pause_state ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::unpause_from_user ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
user_pause = FALSE;
|
|
|
|
propagate_pause_state ();
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned char
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::is_paused ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
if (user_pause || sys_pause || Settings.Paused || !(config->rom_loaded))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Snes9xWindow::set_menu_item_accel_to_binding (const char *name,
|
|
|
|
const char *binding)
|
|
|
|
{
|
|
|
|
Binding bin;
|
|
|
|
char str[255];
|
2010-09-26 11:19:15 +02:00
|
|
|
GtkAccelGroup *accel_group = NULL;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
if (!strcmp (binding, "Escape Key"))
|
|
|
|
{
|
|
|
|
bin = Binding (GDK_Escape, false, false, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bin = S9xGetBindingByName (binding);
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf (str, 255, "<Snes9x>/%s", name);
|
|
|
|
if (!(bin.is_key ()))
|
|
|
|
{
|
|
|
|
gtk_accel_map_change_entry (str,
|
|
|
|
0,
|
|
|
|
(GdkModifierType) 0,
|
|
|
|
TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-09-26 11:19:15 +02:00
|
|
|
GSList *accel_group_list = gtk_accel_groups_from_object (G_OBJECT (window));
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2010-09-26 11:19:15 +02:00
|
|
|
gtk_widget_set_accel_path (get_widget (name), str, accel_group);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::update_accels ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
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");
|
2017-04-25 21:45:30 +02:00
|
|
|
set_menu_item_accel_to_binding ("save_state_9", "QuickSave009");
|
2010-09-25 17:46:12 +02:00
|
|
|
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");
|
2017-04-25 21:45:30 +02:00
|
|
|
set_menu_item_accel_to_binding ("load_state_9", "QuickLoad009");
|
2010-09-25 17:46:12 +02:00
|
|
|
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");
|
|
|
|
|
|
|
|
/* Special UI assignment */
|
|
|
|
set_menu_item_accel_to_binding ("hide_ui", "Escape Key");
|
|
|
|
}
|
2014-03-29 11:48:35 +01:00
|
|
|
|
|
|
|
void
|
|
|
|
Snes9xWindow::resize_to_multiple (int factor)
|
|
|
|
{
|
2014-03-30 05:15:04 +02:00
|
|
|
int h = (config->overscan ? 239 : 224) * factor;
|
2014-04-01 19:06:21 +02:00
|
|
|
int w = h * S9xGetAspect () + 0.5;
|
2014-03-29 11:48:35 +01:00
|
|
|
|
|
|
|
resize_viewport (w, h);
|
|
|
|
}
|
2017-12-07 19:24:29 +01:00
|
|
|
|
|
|
|
cairo_t *
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::get_cairo ()
|
2017-12-07 19:24:29 +01:00
|
|
|
{
|
|
|
|
if (cr)
|
|
|
|
return cr;
|
|
|
|
|
|
|
|
GtkWidget *drawing_area = GTK_WIDGET (this->drawing_area);
|
|
|
|
|
2018-04-28 18:59:17 +02:00
|
|
|
#if GTK_MAJOR_VERSION < 3
|
2017-12-07 19:24:29 +01:00
|
|
|
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_owned = TRUE;
|
|
|
|
return cr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
Snes9xWindow::release_cairo ()
|
2017-12-07 19:24:29 +01:00
|
|
|
{
|
|
|
|
if (cairo_owned)
|
|
|
|
{
|
2018-04-28 18:59:17 +02:00
|
|
|
#if GTK_MAJOR_VERSION < 3
|
2017-12-07 19:24:29 +01:00
|
|
|
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
|
|
|
|
cairo_owned = FALSE;
|
|
|
|
cr = NULL;
|
|
|
|
}
|
|
|
|
}
|