building a gtk sdl widget
- From: Derethor <derethor thepentagon com>
- To: gtk-app-devel-list gnome org
- Subject: building a gtk sdl widget
- Date: Thu, 12 Apr 2001 13:44:09 +0200
hI gtk hackers!
I'm trying to create a gtksdl widget, based on my previus code for SDL
under gnome... but I have some questions O:)
In general terms, I got a crash when I realize the SDL surface. The
reason is that I update the surface that it isnt visible.
My parent class is the GTKWidget, using the code from the
GtkDrawingArea. On my previus code, I attached the SDL Surface to a GTK
Drawing area, but all functions from it was useless (it was just the
base widget for the surface). So, I choosed building the widget from
scratch. Also, I notice some problems with the realize and the expose
events (sometimes, I update the surface BEFORE expose it, causing
segmentation faults)
So, I traced the basic loop for the widget, and seems to be like this
(calling it from my test program with gtk_sdl_new):
-> gtk_sdl_new
-> gtk_sdl_class_init (I set the realize,
size_allocate, and expose functions)
-> gtk_sdl_init (I set the can_focus flag,
and set the key press event)
-> gtk_sdl_size (queue a resize)
<-
-> gtk_sdl_size_allocate (if widget_realized -> resize and
send_configure)
<-
-> gtk_sdl_realize (set attributes, create the gdk_window, and
send_configure)
-> gtk_sdl_send_configure (call the configure event)
<-
-> gtk_sdl_expose (if there is a surface, update it,
else attach a new surface to the widget window)
-> gtl_sdl_surface_attach (set the SDL window to the widget
window)
NOTE: at this point, the surface is not
visible, but the widget with correct size
<-
-> gtk_sdl_expose (this is called when I refresh the widget)
-> gtk_sdl_surface_update (call SDL_UpdateRect)
CRASH!
I guess that the problem is that I attach the surface when the widget
gdk window is not visible yet.
So, my question are:
what is exactly the difference between realize and expose?
On which event can I be sure that the window is visible on the screen?
after configure maybe?
what is the meaning of configure, exactly?
how can I set the expose_event, called after the event? (like with
gtk_signal_connect_after)
any idea why I get my crash?
Thanks in advance.
pd. I attached the code below... As soon as I have the widget working, I
will release it under GPL, 'cause I think that somebody else will use
it. So, If you like to help me or contribute, please, send me an email
--
signed
derethor of centolos
#include "gtksdl.h"
static void gtk_sdl_class_init (GtkSDLClass *klass);
static void gtk_sdl_init (GtkSDL *sdl);
static void gtk_sdl_realize (GtkWidget *widget);
static void gtk_sdl_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static void gtk_sdl_send_configure (GtkSDL *sdl);
static void gtk_sdl_surface_attach (GtkSDL *sdl);
static gint gtk_sdl_expose (GtkWidget *widget, GdkEventExpose *event);
static void gtk_sdl_display_update (GtkSDL *sdl);
static GtkWidgetClass *parent_class = NULL;
GtkType gtk_sdl_get_type (void)
{
static GtkType sdl_type = 0;
if (!sdl_type)
{
static const GtkTypeInfo sdl_info =
{
"GtkSDL",
sizeof (GtkSDL),
sizeof (GtkSDLClass),
(GtkClassInitFunc) gtk_sdl_class_init,
(GtkObjectInitFunc) gtk_sdl_init,
/* reserved_1 */ NULL,
/* reserved_2 */ NULL,
(GtkClassInitFunc) NULL,
};
sdl_type = gtk_type_unique (GTK_TYPE_WIDGET, &sdl_info);
}
return sdl_type;
}
static void gtk_sdl_class_init (GtkSDLClass *class)
{
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
puts ("before class init");
widget_class = GTK_WIDGET_CLASS (class);
widget_class->realize = gtk_sdl_realize;
widget_class->size_allocate = gtk_sdl_size_allocate;
widget_class->expose_event = gtk_sdl_expose;
parent_class = gtk_type_class (gtk_widget_get_type ());
object_class = GTK_OBJECT_CLASS (class);
/*
object_class->destroy = gtk_dial_destroy;
*/
/*
widget_class->size_request = gtk_dial_size_request;
widget_class->size_allocate = gtk_dial_size_allocate;
*/
puts ("after class init");
}
static void gtk_sdl_init (GtkSDL *sdl)
{
puts ("before sdl init");
GTK_WIDGET_SET_FLAGS (sdl, GTK_CAN_FOCUS);
if ( GTK_WIDGET_CAN_FOCUS(sdl) )
{
gtk_widget_grab_focus ( GTK_WIDGET (sdl) );
}
gtk_widget_set_events ( GTK_WIDGET (sdl), GDK_KEY_PRESS_MASK );
puts ("after sdl init");
}
GtkWidget *gtk_sdl_new (gint width, gint height, gint bpp, Uint32 flags)
{
GtkSDL *sdl;
puts ("before sdl new");
sdl = gtk_type_new (gtk_sdl_get_type ());
sdl->width = width;
sdl->height = height;
sdl->bpp = bpp;
sdl->flags = flags;
gtk_sdl_size ( GTK_SDL (sdl), width, height);
/*
timeout_id = gtk_timeout_add ( (33*10)/10 , cbDrawAreaUpdate, (gpointer )darea);
gtk_object_set_data ( GTK_OBJECT (sdl), "timeout_id", (gpointer )timeout_id );
*/
puts ("after sdl new");
return GTK_WIDGET (sdl);
}
void gtk_sdl_size (GtkSDL *sdl, gint width, gint height)
{
puts ("before sdl size");
g_return_if_fail (GTK_IS_SDL (sdl));
GTK_WIDGET (sdl)->requisition.width = width;
GTK_WIDGET (sdl)->requisition.height = height;
gtk_widget_queue_resize (GTK_WIDGET (sdl));
puts ("after sdl size");
}
static void gtk_sdl_realize (GtkWidget *widget)
{
GtkSDL *sdl;
GdkWindowAttr attributes;
gint attributes_mask;
puts ("before sdl realize");
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_SDL (widget));
sdl = GTK_SDL (widget);
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
attributes.window_type = GDK_WINDOW_CHILD;
attributes.x = widget->allocation.x;
attributes.y = widget->allocation.y;
attributes.width = widget->allocation.width;
attributes.height = widget->allocation.height;
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.visual = gtk_widget_get_visual (widget);
attributes.colormap = gtk_widget_get_colormap (widget);
attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
gdk_window_set_user_data (widget->window, sdl);
widget->style = gtk_style_attach (widget->style, widget->window);
gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
gtk_sdl_send_configure (GTK_SDL (widget));
puts ("after sdl realize");
}
static void gtk_sdl_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
{
puts ("before sdl size allocate");
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_SDL (widget));
g_return_if_fail (allocation != NULL);
widget->allocation = *allocation;
/* FIXME, TODO-1.3: back out the MAX() statements */
widget->allocation.width = MAX (1, widget->allocation.width);
widget->allocation.height = MAX (1, widget->allocation.height);
if (GTK_WIDGET_REALIZED (widget))
{
gdk_window_move_resize (widget->window,
allocation->x, allocation->y,
allocation->width, allocation->height);
gtk_sdl_send_configure (GTK_SDL (widget));
}
puts ("after sdl size allocate");
}
static void gtk_sdl_send_configure (GtkSDL *sdl)
{
GtkWidget *widget;
GdkEventConfigure event;
puts ("before sdl send configure");
widget = GTK_WIDGET (sdl);
event.type = GDK_CONFIGURE;
event.window = widget->window;
event.send_event = TRUE;
event.x = widget->allocation.x;
event.y = widget->allocation.y;
event.width = widget->allocation.width;
event.height = widget->allocation.height;
gtk_widget_event (widget, (GdkEvent*) &event);
puts ("after sdl send configure");
}
static void gtk_sdl_surface_attach (GtkSDL *sdl)
{
gchar SDL_windowhack[32];
puts ("before sdl surface attach");
/* Attach the SDL_Surface */
puts ("attaching the surface");
sprintf (SDL_windowhack, "SDL_WINDOWID=%ld",
GDK_WINDOW_XWINDOW ( GTK_WIDGET(sdl)->window ) );
/* putenv (SDL_windowhack);*/
SDL_QuitSubSystem (SDL_INIT_VIDEO);
if ( SDL_InitSubSystem ( SDL_INIT_VIDEO ) < 0)
{
fprintf (stderr, "unable to init SDL: %s", SDL_GetError() );
return;
}
if (sdl->flags &= (SDL_OPENGLBLIT | SDL_DOUBLEBUF))
{
SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
}
if (sdl->surface)
{
puts ("TODO: deallocate previus surface");
}
sdl->surface = SDL_SetVideoMode( sdl->width, sdl->height, sdl->bpp, sdl->flags);
if (!sdl->surface)
{
fprintf (stderr, "Unable to set the video mode: %s", SDL_GetError() );
return;
}
/*
puts ("update rect");
SDL_UpdateRect (sdl->surface, 0, 0, 0, 0);
puts ("display update");
gtk_sdl_display_update (sdl);
puts ("end attach surface");
*/
puts ("after sdl surface attach");
}
static gint gtk_sdl_expose (GtkWidget *widget, GdkEventExpose *event)
{
SDL_Surface *surface;
SDL_Rect dest;
puts ("before sdl expose");
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_SDL (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
if (event->count > 0) return FALSE;
surface = SDL_GetVideoSurface ();
if (surface)
{
puts ("update rects from expose");
dest.x = event->area.x;
dest.y = event->area.y;
dest.w = event->area.width;
dest.h = event->area.height;
SDL_UpdateRect (surface, 0, 0, 0, 0);
/* SDL_UpdateRects (surface, 1, &dest);
gtk_sdl_display_update ( GTK_SDL(widget) );*/
}
else
{
gtk_sdl_surface_attach (GTK_SDL (widget));
}
puts ("after sdl expose");
return FALSE;
}
static void gtk_sdl_display_update (GtkSDL *sdl)
{
SDL_Surface *surface;
puts ("before sdl display update");
g_return_if_fail (sdl != NULL);
g_return_if_fail (GTK_IS_SDL (sdl));
g_return_if_fail (sdl->surface);
if ( (sdl->flags &=SDL_OPENGL) || (sdl->flags &= SDL_OPENGLBLIT) )
{
/*
if (dkActiveUpdaterGL) (*dkActiveUpdaterGL)();
*/
SDL_GL_SwapBuffers ();
}
else
{
/*
if (dkActiveUpdater) (*dkActiveUpdater)();
*/
puts ("get video surface");
surface = SDL_GetVideoSurface ();
puts ("flip video surface");
SDL_Flip (surface);
}
puts ("after display update");
}
# ifndef __GTK_SDL_H__
# define __GTK_SDL_H__
# include <stdlib.h>
# include <gdk/gdk.h>
# include <gtk/gtkwidget.h>
# include <gdk/gdkx.h>
# include <SDL/SDL.h>
# ifdef __cplusplus
extern "C" {
# endif /* __cplusplus */
# define GTK_TYPE_SDL (gtk_sdl_get_type ())
# define GTK_SDL(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_SDL, GtkSDL))
# define GTK_SDL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_SDL, GtkSDLClass))
# define GTK_IS_SDL(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_SDL))
# define GTK_IS_SDL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SDL))
typedef struct _GtkSDL GtkSDL;
typedef struct _GtkSDLClass GtkSDLClass;
struct _GtkSDL
{
GtkWidget widget;
SDL_Surface *surface;
gint width, height, bpp;
Uint16 flags;
};
struct _GtkSDLClass
{
GtkWidgetClass parent_class;
};
GtkType gtk_sdl_get_type (void);
GtkWidget *gtk_sdl_new (gint width, gint height, gint bpp, Uint32 flags);
void gtk_sdl_size (GtkSDL *sdl,
gint width,
gint height);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_SDL_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]