Lazarus

Programming => Widgetset => GTK => Topic started by: guest58172 on August 23, 2017, 12:58:27 pm

Title: [Solved] How to reparent a Form using GDK2 ?
Post by: guest58172 on August 23, 2017, 12:58:27 pm
How can i reparent a window using the low level widgetset API, so gtk, under linux ?

So far i try this:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, gdk2,
  6.   LCLIntf, LCLType;
  7. type
  8.   TForm2 = class(TForm)
  9.   end;
  10.   TForm1 = class(TForm)
  11.     procedure FormClick(Sender: TObject);
  12.   end;
  13. var
  14.   Form1: TForm1;
  15. implementation
  16. {$R *.lfm}
  17.  
  18. procedure TForm1.FormClick(Sender: TObject);
  19. var
  20.   hst: PGdkWindow;
  21.   win: PGdkWindow;
  22.   frm: TForm2;
  23. begin
  24.   frm := TForm2.CreateNew(self);
  25.   frm.ShowOnTop;
  26.   frm.Color:= clBlue;
  27.   frm.Width:= 200;
  28.   frm.Height:= 200;
  29.   hst := GDK_WINDOW(Pointer(WindowHandle));
  30.   win := GDK_WINDOW(Pointer(frm.WindowHandle));
  31.   gdk_window_reparent(win,  hst, 10, 10);
  32. end;
  33.  
  34. end.

But it doesn't work. hst and win seems valid tho.
I need this because eventually this could be used to embed external x11 applications.
Title: Re: How to reparent a Form using GDK2 ?
Post by: zeljko on August 24, 2017, 11:30:43 am
gdk_window_reparent() will unmap child window, so you have to show it again
Title: Re: How to reparent a Form using GDK2 ?
Post by: Thaddy on August 24, 2017, 11:48:11 am
gdk_window_reparent() will unmap child window, so you have to show it again
Absolutely correct, but @BBasile: why low-level? the widget set abstraction takes care of that if you re-assign the parent? And it does so pretty efficient, see sourcecode.
There should not be any need for it. And there is no performance to be gained.
Title: Re: How to reparent a Form using GDK2 ?
Post by: guest58172 on August 24, 2017, 12:08:39 pm
gdk_window_reparent() will unmap child window, so you have to show it again
Absolutely correct, but @BBasile: why low-level? the widget set abstraction takes care of that if you re-assign the parent? And it does so pretty efficient, see sourcecode.
There should not be any need for it. And there is no performance to be gained.

I need this because eventually this could be used to embed external x11 applications. So in a first time i try with a second form. When this will work i'll start doing the same with an external application, which requires more low level things, especially under linux (under windows this is much easier, this is the kind of things you do the first year you started programming...).
Title: Re: How to reparent a Form using GDK2 ?
Post by: guest58172 on August 24, 2017, 12:17:23 pm
gdk_window_reparent() will unmap child window, so you have to show it again

No this doesn't work. Neither with gdk_window_show() nor TForm.show().
I bet that the handles are not valid. What i see in the debugger must be garbage that look valid after cast.
Title: Re: How to reparent a Form using GDK2 ?
Post by: zeljko on August 24, 2017, 02:44:57 pm
First check gdk_is_window(handle), if that's correct and both are visible that should work.
Title: Re: How to reparent a Form using GDK2 ?
Post by: guest58172 on August 24, 2017, 03:16:56 pm
Yeah, GDK_IS_WINDOW is false for both. debugger showed garbages. This happens sometimes that random data look like valid after cast.
Title: Re: How to reparent a Form using GDK2 ?
Post by: AmatCoder on August 24, 2017, 03:31:51 pm
AFAIK, WindowHandle does not return a GdkWindow but a GtkWidget, is not?
Title: Re: How to reparent a Form using GDK2 ?
Post by: zeljko on August 26, 2017, 11:47:36 am
AFAIK, WindowHandle does not return a GdkWindow but a GtkWidget, is not?

Yes, I've missed that part. It returns GtkWindow, and then you should ask GtkWindow for it's window (GdkWindow), so then it should be correct.
Title: Re: How to reparent a Form using GDK2 ?
Post by: guest58172 on August 27, 2017, 01:44:36 pm
AFAIK, WindowHandle does not return a GdkWindow but a GtkWidget, is not?

Indeed that works. Once cast to PGtkWidget i have a valid PGdkWindow as member.
Title: Re: [Solved] How to reparent a Form using GDK2 ?
Post by: guest58172 on August 27, 2017, 02:08:16 pm
Hosting an external window now works with gdk_window_foreign_new(), that's really awesome. There are problems with the alignment and the keyboard input (and strangely not the mouse) but this looks very usable.
Title: Re: [Solved] How to reparent a Form using GDK2 ?
Post by: dot.not on August 27, 2017, 02:19:46 pm

There are problems with the alignment and the keyboard input (and strangely not the mouse) but this looks very usable.


Possibly because keyboard tries to act on the focused control (and perhaps by re-parenting the form the active control has changed/ been lost?) whereas the mouse clicks sets the focus.
Title: Re: [Solved] How to reparent a Form using GDK2 ?
Post by: guest58172 on August 27, 2017, 03:50:54 pm
I find no useful info about how to fix the keyboard issue.

The current code is:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
  6.   gdk2, gtk2, gdk2x;
  7. type
  8.   TForm1 = class(TForm)
  9.     procedure FormClick(Sender: TObject);
  10.   end;
  11. var
  12.   Form1: TForm1;
  13.  
  14. implementation
  15. {$R *.lfm}
  16.  
  17. procedure TForm1.FormClick(Sender: TObject);
  18. var
  19.   hst1: PGtkWidget;
  20.   hst2: PGdkWindow;
  21.   winx: PGdkWindow;
  22. begin
  23.  
  24.   hst1 := PGtkWidget(WindowHandle);
  25.   hst2 := hst1^.window;
  26.  
  27.   // l- launch a console
  28.   // - use xwininfo to find the right "Window id" for the console...
  29.   // - then replace the hex nbr and run this app and click.
  30.   winx := gdk_window_foreign_new($4c00005);
  31.  
  32.   if GDK_IS_WINDOW((hst2)) and GDK_IS_WINDOW((winx)) then
  33.   begin
  34.     gdk_window_reparent(winx, hst2, 0, 0);
  35.   end;
  36. end;
  37. end.

I think this would be worth a component. As said previously under Windows this will be much simpler but w/ gtk i'm in a deep fog.
Title: Re: [Solved] How to reparent a Form using GDK2 ?
Post by: AmatCoder on August 27, 2017, 10:36:19 pm
Just for the record, the correct way to embed a X11 window with GTK+ is to use GtkSocket (https://developer.gnome.org/gtk3/stable/GtkSocket.html) (together with GtkPlug (https://developer.gnome.org/gtk3/stable/GtkPlug.html)).

In the past I used it (with C language, however) and keyboard events work fine (it uses XEmbed (https://specifications.freedesktop.org/xembed-spec/xembed-spec-0.5.html) protocol).
TinyPortal © 2005-2018