Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2007-11

Linux : Using SDL with GTK2 ?

6 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Andrew Haines
to Tom
Tom wrote 12 lines
Hi, I'm desperately trying to build a application mixing GTK with SDL for *Linux*. I know that's not always recommended as it involves 2 listening loops but it should work. I found some *C* snippets/applications (eg making window hacks) but I'm unable to translate them into Pascal. My goal is to display Joystick events into a GTK2 window. Ideally I would like to use Jedi-SDL with GTK2. Of course either GTK2 or SDL used alone works fine. Does anyone have some example to achieve this ?
uses sdl, gtk, gdk, X;
var
  SDLWindowHack: String
  X11Window: X.TWindow;
begin
...
  // this is for gtk1 only. gtk2 is similar but different
  X11Window :=
GDK_WINDOW_XWINDOW(PGdkWindowPrivate(GTK_WIDGET(APanel.Handle)^.window ) );
  SDLWindowHack := 'SDL_WINDOWID='+ IntToStr(PtrUint(X11Window));
  putenv (PChar(SDLWindowhack));
end;

You have to for sure set the environment variable SDL_WINDOWID before you create the window with sdl and maybe before sdl_init.

IIRC using this method somehow makes sdl not listen for keyboard/mouse events because it is using a window you have made and expects you to already be processing those events in some way.

The other way to embed a window is to create the window normally with sdl without setting SDL_WINDOWID and then accessing the PSurface record get the X11 window ID and use XReparentWindow to embed it into your app. unfortunatly the window is created outside your app and is briefly visible before you have stuck it inside your app. Sdl will behave as if the window is not embedded in your app. Setting keyboard focus and mouse focus in the window may have quirks.

Overall I think the first method is best.

Setting the SDL_WINDOWID works on windows too if you set it to the (hwnd)TWinControl.Handle of whatever component you want sdl to draw to.

Andrew

T.Guilleminot
to Andrew Haines

Thanks for your answer. I'm a newbie so I still have a few questions :o) :

1. I'm unsure of chronology of things to do in the program body. Is the following correct :
a) Create GTK stuff
b) SDL Hack/SDL_WINDOWID
c) SDL_INIT
d) Show GTK widgets

2. You mentioned "this is for gtk1 only. gtk2 is similar but different". What to do for GTK2 ?

3. Which kind of GTK Object "APanel" can be ?

4. FPC complains on "handle". What's wrong ?

Free Pascal Compiler version 2.2.0 [2007/08/30] for i386 Target OS: Linux for i386
Compiling test.pas
test.pas(45,77) Error: Illegal qualifier
test.pas(45,77) Fatal: Syntax error, ")" expected but "identifier HANDLE" found
Fatal: Compilation aborted
Error: /usr/bin/ppc386 returned an error exitcode (normal if you did not specify a source file to be compiled)

Thanks Again.
Tom

Andrew Haines wrote 56 lines
Tom wrote: > Hi, > > I'm desperately trying to build a application mixing GTK with SDL for *Linux*. > > I know that's not always recommended as it involves 2 listening loops but it > should work. I found some *C* snippets/applications (eg making window hacks) but > I'm unable to translate them into Pascal. > My goal is to display Joystick events into a GTK2 window. Ideally I would like > to use Jedi-SDL with GTK2. Of course either GTK2 or SDL used alone works fine. > Does anyone have some example to achieve this ? > > > uses sdl, gtk, gdk, X; var SDLWindowHack: String X11Window: X.TWindow; begin ... // this is for gtk1 only. gtk2 is similar but different X11Window := GDK_WINDOW_XWINDOW(PGdkWindowPrivate(GTK_WIDGET(APanel.Handle)^.window ) ); SDLWindowHack := 'SDL_WINDOWID='+ IntToStr(PtrUint(X11Window)); putenv (PChar(SDLWindowhack)); end; You have to for sure set the environment variable SDL_WINDOWID before you create the window with sdl and maybe before sdl_init. IIRC using this method somehow makes sdl not listen for keyboard/mouse events because it is using a window you have made and expects you to already be processing those events in some way. The other way to embed a window is to create the window normally with sdl without setting SDL_WINDOWID and then accessing the PSurface record get the X11 window ID and use XReparentWindow to embed it into your app. unfortunatly the window is created outside your app and is briefly visible before you have stuck it inside your app. Sdl will behave as if the window is not embedded in your app. Setting keyboard focus and mouse focus in the window may have quirks. Overall I think the first method is best. Setting the SDL_WINDOWID works on windows too if you set it to the (hwnd)TWinControl.Handle of whatever component you want sdl to draw to. Andrew
Andrew Haines
to T.Guilleminot
T.Guilleminot wrote 7 lines
1. I'm unsure of chronology of things to do in the program body. Is the following correct : a) Create GTK stuff b) SDL Hack/SDL_WINDOWID c) SDL_INIT d) Show GTK widgets

Yes that's right. With the only exception being that you have to use gtk_widget_realize on whatever gtk widget you are using for sdl so that the x11 window will be allocated.

2. You mentioned "this is for gtk1 only. gtk2 is similar but different". What to do for GTK2 ?

I've attached a simple program that will compile for gtk1 or gtk2. you can change a define at the top of the source to switch between gtk 1 or 2.

3. Which kind of GTK Object "APanel" can be ? 4. FPC complains on "handle". What's wrong ?

Sorry I thought you were using the LCL and so my example was for that. I attached an example program that doesn't use the LCL.

Thanks Again. Tom

It's worth noting that you cannot have more than one sdl window per application. It's a limitation of sdl.

Andrew

Darius Blaszyk
to Andrew Haines: Yes that's right. With the only exception being that you have to use gtk_widget_realize…

Hi Andrew,

I found this mail from you regarding attaching SDL to the used widgetset. But whatever I do I cannot get it to work. The example you attached in the email below works fine, so it has to be possible. So why not when using the LCL?

I hope you don;t mind me bugging you about this, but I've been staring at the code for two days now, and you're my last resort...

The code I've been using is pasted below. If you don't feel like fixing my mess (or simply don't have the time to) just let me know and I'll understand.

function GetX11Window(AWidget: PGtkWidget): X.TWindow;
begin
  // first make sure the x11 window is created for the gtk widget
  if GTK_WIDGET_REALIZED(AWidget) = False then
    gtk_widget_realize(AWidget);
  // now retrieve the X window
{$IFDEF GTK2}
  Result := GDK_WINDOW_XWINDOW(PGdkDrawAble(AWidget^.window));
{$ENDIF}
{$IFDEF GTK1}
  Result := GDK_WINDOW_XWINDOW(PGdkWindowPrivate(AWidget^.window));
{$ENDIF}
end;
procedure SetSDLWidget(AWidget: PGtkWidget);
var
  X11Window:    QWord;
  SDL_WINDOWID: string;
begin
  X11Window    := GetX11Window(AWidget);
  SDL_WINDOWID := 'SDL_WINDOWID=' + IntToStr(PtrUint(X11Window));
  _putenv(PChar(SDL_WINDOWID));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
  SetSDLWidget(PGtkWidget(Panel));
end;
In a Button1Click handler SDL is initialized like so;

if SDL_Init(SDL_INIT_VIDEO or SDL_INIT_AUDIO or SDL_INIT_TIMER) 0 then
raise Exception.CreateFmt('Could not initialize SDL - %s', [SDL_GetError]);

Regards, Darius

Andrew Haines wrote 167 lines
T.Guilleminot wrote: > 1. I'm unsure of chronology of things to do in the program body. Is the > following correct : > a) Create GTK stuff > b) SDL Hack/SDL_WINDOWID > c) SDL_INIT > d) Show GTK widgets > Yes that's right. With the only exception being that you have to use gtk_widget_realize on whatever gtk widget you are using for sdl so that the x11 window will be allocated. > 2. You mentioned "this is for gtk1 only. gtk2 is similar but different". > What to do for GTK2 ? > I've attached a simple program that will compile for gtk1 or gtk2. you can change a define at the top of the source to switch between gtk 1 or 2. > 3. Which kind of GTK Object "APanel" can be ? > > 4. FPC complains on "handle". What's wrong ? > Sorry I thought you were using the LCL and so my example was for that. I attached an example program that doesn't use the LCL. > Thanks Again. > Tom > > It's worth noting that you cannot have more than one sdl window per application. It's a limitation of sdl. Andrew plain text document attachment (project1.lpr) program Project1; {$mode objfpc}{$H+} {$DEFINE GTK1} uses Classes, SysUtils, {$IFDEF GTK2} Gtk2, Gdk2, Gdk2x, Glib2, {$ENDIF} {$IFDEF GTK1} Gtk, Gdk, Glib,{$ENDIF} X, sdl, sdlutils; var MainWindow, Drawable: PGtkWidget; SDLSurface: PSDL_Surface = nil; procedure InitGtk; begin gtk_init(@argc, @argv); MainWindow := gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(PGtkWindow(MainWindow), 'Hey there''s SDL in this window!'); Drawable := gtk_drawing_area_new; gtk_widget_set_app_paintable(Drawable, False); {$IFDEF GTK2} gtk_widget_set_double_buffered(Drawable, False); {$ENDIF} gtk_container_add(PGtkContainer(MainWindow), Drawable); {$IFDEF GTK1} gtk_widget_show(MainWindow); {$ENDIF} end; procedure ResizeSDL(AWidget: PGtkWidget; Allocation: PGtkAllocation; userdata: pointer); cdecl; begin SDLSurface := SDL_SetVideoMode(Allocation^.width, Allocation^.height, 0, SDL_HWSURFACE); end; procedure ExposeSDL(widget: PGtkWidget; event: PGdkEventExpose; Data: Pointer); cdecl; var Col1, Col2: TSDL_Color; ARect: TSDL_Rect; begin Col1.r := 255; Col1.b := 0; Col1.g := 0; Col2.r := 0; Col2.b := 255; Col2.g := 0; ARect := SDLRect(0,0,Drawable^.allocation.width, Drawable^.allocation.height); SDL_FillRect(SDLSurface, @ARect, $FFFF0000); SDL_Flip(SDLSurface); end; procedure SetGtkCallbacks; begin gtk_signal_connect(GTK_OBJECT(Drawable), 'expose-event', TGtkSignalFunc(@ExposeSDL), nil); gtk_signal_connect(GTK_OBJECT(Drawable), 'size-allocate', TGtkSignalFunc(@ResizeSDL), nil); gtk_signal_connect(GTK_OBJECT(MainWindow), 'destroy', TGtkSignalFunc(@gtk_main_quit), nil) end; function GetX11Window(AWidget: PGtkWidget): X.TWindow; begin // first make sure the x11 window is created for the gtk widget if GTK_WIDGET_REALIZED(AWidget) = False then gtk_widget_realize(AWidget); // now retrieve the X window {$IFDEF GTK2} Result := GDK_WINDOW_XWINDOW(PGdkDrawAble(AWidget^.window)); {$ENDIF} {$IFDEF GTK1} Result := GDK_WINDOW_XWINDOW(PGdkWindowPrivate(AWidget^.window)); {$ENDIF} end; procedure SetSDLWidget(AWidget: PGtkWidget); var X11Window: QWord; SDL_WINDOWID: String; begin X11Window := GetX11Window(AWidget); SDL_WINDOWID := 'SDL_WINDOWID='+IntToStr(PtrUint(X11Window)); _putenv(PChar(SDL_WINDOWID)); end; procedure SyncGtk; begin gtk_main_iteration_do(True); end; procedure InitSDL; begin SDL_Init(SDL_INIT_VIDEO or SDL_INIT_JOYSTICK); SDLSurface := SDL_SetVideoMode(Drawable^.allocation.width, Drawable^.allocation.height, 0, SDL_HWSURFACE); end; procedure Run; begin gtk_widget_show_all(MainWindow); gtk_main; end; begin InitGtk; SetGtkCallbacks; SetSDLWidget(Drawable); SyncGtk; InitSDL; Run; end. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal No virus found in this incoming message. Checked by AVG Free Edition. Version: 7.5.503 / Virus Database: 269.16.0/1136 - Release Date: 11/17/2007 2:55 PM