*ID: 3165057 - Embed SDL window in GTK window patch applied

Big thanks to Bryan Cain!
*fixed issues with xscale/yscale options "not sticking" in gtk gui
*set gtk window to resize to xscale/yscale options

introduced known bug:  alt-tab won't currently go into fullscreen
This commit is contained in:
punkrockguy318 2011-01-25 03:26:09 +00:00
parent 8d1bcc9bea
commit be15c0cfec
5 changed files with 263 additions and 68 deletions

View File

@ -71,7 +71,7 @@ Debugger additions
Shinydoofy - sf:shinydoofy
SDL maintenence
Lukas Sabota - ltsmooth42 at comcast.net (sf:punkrockguy318)
Lukas Sabota - ltsmooth42 at gmail dot com (sf:punkrockguy318)
Head SDL developer
Soules - gimmedonutnow at gmail dot com (sf:gimmedonutnow)
@ -80,6 +80,10 @@ Linux SDL driver maintenance
radsaq - radsaq at gmail dot com (sf:radsaq)
Build system, testing, and random cleanups
bryan cain -
sdl in gtk gui patch
-----------------------------------------
Included components:

View File

@ -1,9 +1,9 @@
TODO-SVN:
* DONE! Working!Test and work on unix-netplay
*** Auto-resize game window
*** Add alt-enter for fullscreen in GTK
* DONE! Get to compile with SDL 1.3
* segfaults when opening a second game
* segfaults on fullscreen entry
* DONE! Fix sound stuttering/lag (fixed in SDL 1.1.14)
* Flesh out GTK GUI
* Sound config
* DONE! Individual volume mixers
@ -25,7 +25,7 @@ TODO-SVN:
* OpenGLip
* Scanline end/start
* DONE! pallete
* Integrate SDL window into GTK GUI
* THANKS BRYAN CAIN! Integrate SDL window into GTK GUI
* DONE! Fix opening compressed ROMs
* DONE! Fix Famicom Disk System
* DONE!(PAUSE) Add a key to resume normal playback when finished frameskipping

View File

@ -33,6 +33,7 @@ void loadGame ();
extern Config *g_config;
GtkWidget* MainWindow = NULL;
GtkWidget* socket = NULL;
GtkWidget* padNoCombo;
// This function configures a single button on a gamepad
@ -670,8 +671,8 @@ void openVideoConfig()
gtk_box_pack_start(GTK_BOX(yscaleHbox), yscaleLbl, FALSE, FALSE, 2);
gtk_box_pack_start(GTK_BOX(yscaleHbox), yscaleSpin, FALSE, FALSE, 2);
g_signal_connect(xscaleSpin, "button-release-event", G_CALLBACK(setXscale), NULL);
g_signal_connect(yscaleSpin, "button-release-event", G_CALLBACK(setYscale), NULL);
g_signal_connect(xscaleSpin, "value-changed", G_CALLBACK(setXscale), NULL);
g_signal_connect(yscaleSpin, "value-changed", G_CALLBACK(setYscale), NULL);
double f;
// sync with config
@ -1277,16 +1278,11 @@ void loadGame ()
gtk_widget_destroy (fileChooser);
}
void closeGame() { CloseGame(); }
// this is not used currently; it is used in rendering sdl in
// the gtk window which is broken
gint configureEvent (GtkWidget* widget, GdkEventConfigure* event)
void closeGame()
{
//neccessary for SDL rendering on gtk win (i think?)
//s_screen = SDL_SetVideoMode(event->width, event->height, 0, 0);
return TRUE;
GdkColor bg = {0, 0, 0, 0};
gtk_widget_modify_bg(socket, GTK_STATE_NORMAL, &bg);
CloseGame();
}
void saveStateAs()
@ -1359,6 +1355,197 @@ void loadStateFrom()
}
// Adapted from Gens/GS. Converts a GDK key value into an SDL key value.
unsigned short GDKToSDLKeyval(int gdk_key)
{
if (!(gdk_key & 0xFF00))
{
// ASCII symbol.
// SDL and GDK use the same values for these keys.
// Make sure the key value is lowercase.
gdk_key = tolower(gdk_key);
// Return the key value.
return gdk_key;
}
if (gdk_key & 0xFFFF0000)
{
// Extended X11 key. Not supported by SDL.
#ifdef GDK_WINDOWING_X11
fprintf(stderr, "Unhandled extended X11 key: 0x%08X (%s)", gdk_key, XKeysymToString(gdk_key));
#else
fprintf(stderr, "Unhandled extended key: 0x%08X\n", gdk_key);
#endif
return 0;
}
// Non-ASCII symbol.
static const uint16_t gdk_to_sdl_table[0x100] =
{
// 0x00 - 0x0F
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
SDLK_BACKSPACE, SDLK_TAB, SDLK_RETURN, SDLK_CLEAR,
0x0000, SDLK_RETURN, 0x0000, 0x0000,
// 0x10 - 0x1F
0x0000, 0x0000, 0x0000, SDLK_PAUSE,
SDLK_SCROLLOCK, SDLK_SYSREQ, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, SDLK_ESCAPE,
0x0000, 0x0000, 0x0000, 0x0000,
// 0x20 - 0x2F
SDLK_COMPOSE, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
// 0x30 - 0x3F [Japanese keys]
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
// 0x40 - 0x4F [unused]
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
// 0x50 - 0x5F
SDLK_HOME, SDLK_LEFT, SDLK_UP, SDLK_RIGHT,
SDLK_DOWN, SDLK_PAGEUP, SDLK_PAGEDOWN, SDLK_END,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
// 0x60 - 0x6F
0x0000, SDLK_PRINT, 0x0000, SDLK_INSERT,
SDLK_UNDO, 0x0000, 0x0000, SDLK_MENU,
0x0000, SDLK_HELP, SDLK_BREAK, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
// 0x70 - 0x7F [mostly unused, except for Alt Gr and Num Lock]
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, SDLK_MODE, SDLK_NUMLOCK,
// 0x80 - 0x8F [mostly unused, except for some numeric keypad keys]
SDLK_KP5, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, SDLK_KP_ENTER, 0x0000, 0x0000,
// 0x90 - 0x9F
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, SDLK_KP7, SDLK_KP4, SDLK_KP8,
SDLK_KP6, SDLK_KP2, SDLK_KP9, SDLK_KP3,
SDLK_KP1, SDLK_KP5, SDLK_KP0, SDLK_KP_PERIOD,
// 0xA0 - 0xAF
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, SDLK_KP_MULTIPLY, SDLK_KP_PLUS,
0x0000, SDLK_KP_MINUS, SDLK_KP_PERIOD, SDLK_KP_DIVIDE,
// 0xB0 - 0xBF
SDLK_KP0, SDLK_KP1, SDLK_KP2, SDLK_KP3,
SDLK_KP4, SDLK_KP5, SDLK_KP6, SDLK_KP7,
SDLK_KP8, SDLK_KP9, 0x0000, 0x0000,
0x0000, SDLK_KP_EQUALS, SDLK_F1, SDLK_F2,
// 0xC0 - 0xCF
SDLK_F3, SDLK_F4, SDLK_F5, SDLK_F6,
SDLK_F7, SDLK_F8, SDLK_F9, SDLK_F10,
SDLK_F11, SDLK_F12, SDLK_F13, SDLK_F14,
SDLK_F15, 0x0000, 0x0000, 0x0000,
// 0xD0 - 0xDF [L* and R* function keys]
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
// 0xE0 - 0xEF
0x0000, SDLK_LSHIFT, SDLK_RSHIFT, SDLK_LCTRL,
SDLK_RCTRL, SDLK_CAPSLOCK, 0x0000, SDLK_LMETA,
SDLK_RMETA, SDLK_LALT, SDLK_RALT, SDLK_LSUPER,
SDLK_RSUPER, 0x0000, 0x0000, 0x0000,
// 0xF0 - 0xFF [mostly unused, except for Delete]
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, SDLK_DELETE,
};
unsigned short sdl_key = gdk_to_sdl_table[gdk_key & 0xFF];
if (sdl_key == 0)
{
// Unhandled GDK key.
fprintf(stderr, "Unhandled GDK key: 0x%04X (%s)", gdk_key, gdk_keyval_name(gdk_key));
return 0;
}
return sdl_key;
}
// Function adapted from Gens/GS (source/gens/input/input_sdl.c)
gint convertKeypress(GtkWidget *grab, GdkEventKey *event, gpointer user_data)
{
SDL_Event sdlev;
SDLKey sdlkey;
int keystate;
// Only grab keys from the main window.
if (grab != MainWindow)
{
// Don't push this key onto the SDL event stack.
return FALSE;
}
switch (event->type)
{
case GDK_KEY_PRESS:
sdlev.type = SDL_KEYDOWN;
sdlev.key.state = SDL_PRESSED;
keystate = 1;
break;
case GDK_KEY_RELEASE:
sdlev.type = SDL_KEYUP;
sdlev.key.state = SDL_RELEASED;
keystate = 0;
break;
default:
fprintf(stderr, "Unhandled GDK event type: %d", event->type);
return FALSE;
}
// Convert this keypress from GDK to SDL.
sdlkey = (SDLKey)GDKToSDLKeyval(event->keyval);
// Create an SDL event from the keypress.
sdlev.key.keysym.sym = sdlkey;
if (sdlkey != 0)
{
SDL_PushEvent(&sdlev);
#if SDL_VERSION_ATLEAST(1, 3, 0)
SDL_GetKeyboardState(NULL)[SDL_GetScancodeFromKey(sdlkey)] = keystate;
#else
SDL_GetKeyState(NULL)[sdlkey] = keystate;
#endif
}
// Allow GTK+ to process this key.
return FALSE;
}
/* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
static GtkItemFactoryEntry menu_items[] = {
{ "/_File", NULL, NULL, 0, "<Branch>" },
@ -1469,79 +1656,55 @@ int InitGTKSubsystem(int argc, char** argv)
gtk_window_set_title(GTK_WINDOW(MainWindow), FCEU_NAME_AND_VERSION);
gtk_window_set_default_size(GTK_WINDOW(MainWindow), 359, 200);
vbox = gtk_vbox_new(FALSE, 3);
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(MainWindow), vbox);
Menubar = CreateMenubar(MainWindow);
//consoleOutput = gtk_text_view_new_with_buffer(gtkConsoleBuf);
//gtk_text_view_set_editable(GTK_TEXT_VIEW(consoleOutput), FALSE);
//gtkConsoleBuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(consoleOutput));
//gtk_text_buffer_get_iter_at_offset(gtkConsoleBuf, &iter, 0);
//gtk_text_buffer_insert(gtkConsoleBuf, &iter, "FceuX GUI Started.\n", -1);
// = vte_terminal_new();
//vte_terminal_feed(VTE_TERMINAL(term), "FceuX GUI Started", -1);
//gtk_container_add(GTK_CONTAINER(vbox), Menubar);
gtk_box_pack_start (GTK_BOX(vbox), Menubar, FALSE, TRUE, 0);
//gtk_box_pack_start (GTK_BOX(vbox), term, TRUE, TRUE, 0);
// broken SDL embedding code
//gtk_widget_set_usize(MainWindow, xres, yres);
//gtk_widget_realize(MainWindow);
// event handlers
//gtk_widget_add_events(MainWindow, GDK_BUTTON_PRESS_MASK);
//gtk_signal_connect(GTK_OBJECT(MainWindow), "configure_event",
// GTK_SIGNAL_FUNC(configureEvent), 0);
// PRG: this code here is the the windowID "hack" to render SDL
// in a GTK window. however, I can't get it to work right now
// so i'm commenting it out and haivng a seperate GTK2 window with
// controls
// 12/21/09
/*
GtkWidget* socket = gtk_socket_new();
gtk_widget_show (socket) ;
gtk_container_add (GTK_CONTAINER(MainWindow), socket);
// ---
// uncommented and fixed by Bryan Cain
// 1/24/11
//
// prg - Bryan Cain, you are the man!
GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
gtk_widget_show(hbox);
gtk_box_pack_end (GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
socket = gtk_event_box_new();
gtk_box_pack_start (GTK_BOX(hbox), socket, TRUE, FALSE, 0);
double xscale, yscale;
printf("%f %f", xscale, yscale);
g_config->getOption("SDL.XScale", &xscale);
g_config->getOption("SDL.YScale", &yscale);
gtk_widget_set_size_request(socket, 256*xscale, 224*yscale);
gtk_widget_realize(socket);
gtk_widget_show(socket);
char SDL_windowhack[24];
sprintf(SDL_windowhack, "SDL_WINDOWID=%ld", (long int)gtk_socket_get_id (GTK_SOCKET(socket)));
putenv(SDL_windowhack);
GdkColor bg = {0, 0, 0, 0};
gtk_widget_modify_bg(socket, GTK_STATE_NORMAL, &bg);
// set up keypress "snooper" to convert GDK keypress events into SDL keypresses
gtk_key_snooper_install(convertKeypress, NULL);
// init SDL
if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
{
fprintf(stderr, "Couldn't init SDL: %s\n", SDL_GetError());
gtk_main_quit();
}
// test rendering
//screen = SDL_SetVideoMode(xres, yres, 0, 0);
//hello = SDL_LoadBMP( "hello.bmp" );
*/
g_signal_connect(MainWindow, "destroy-event", quit, NULL);
//gtk_idle_add(mainLoop, MainWindow);
// signal handlers
g_signal_connect(MainWindow, "delete-event", quit, NULL);
gtk_widget_show_all(MainWindow);
GtkRequisition req;
gtk_widget_size_request(GTK_WIDGET(MainWindow), &req);
gtk_window_resize(GTK_WINDOW(MainWindow), req.width, req.height);
return 0;
}

View File

@ -20,6 +20,9 @@
#ifndef FCEUX_GUI_H
#define FCEUX_GUI_H
#define GTK_LITE
#include <gtk/gtk.h>
extern GtkWidget* MainWindow;
extern GtkWidget* socket;
int InitGTKSubsystem(int argc, char** argv);
void pushOutputToGTK(const char* str);
void showGui(bool b);

View File

@ -45,6 +45,7 @@
#ifdef _GTK
#include "gui.h"
#include <gdk/gdkx.h>
#endif
// GLOBALS
@ -358,6 +359,24 @@ InitVideo(FCEUGI *gi)
}
#endif
#ifdef _GTK
while (gtk_events_pending())
gtk_main_iteration_do(FALSE);
char SDL_windowhack[128];
sprintf(SDL_windowhack, "SDL_WINDOWID=%u", (unsigned int)GDK_WINDOW_XWINDOW(gtk_widget_get_window(socket)));
SDL_putenv(SDL_windowhack);
// init SDL video
if (SDL_WasInit(SDL_INIT_VIDEO))
SDL_QuitSubSystem(SDL_INIT_VIDEO);
if ( SDL_InitSubSystem(SDL_INIT_VIDEO) < 0 )
{
fprintf(stderr, "Couldn't init SDL video: %s\n", SDL_GetError());
gtk_main_quit();
}
#endif
s_screen = SDL_SetVideoMode((int)(NWIDTH * s_exs),
(int)(s_tlines * s_eys),
desbpp, flags);
@ -365,6 +384,12 @@ InitVideo(FCEUGI *gi)
FCEUD_PrintError(SDL_GetError());
return -1;
}
#ifdef _GTK
GtkRequisition req;
gtk_widget_size_request(GTK_WIDGET(MainWindow), &req);
gtk_window_resize(GTK_WINDOW(MainWindow), req.width, req.height);
#endif
}
s_curbpp = s_screen->format->BitsPerPixel;
if(!s_screen) {