* * *

Author Topic: [Solved] How to reparent a Form using GDK2 ?  (Read 1392 times)

BBasile

  • Sr. Member
  • ****
  • Posts: 341
[Solved] How to reparent a Form using GDK2 ?
« 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.
« Last Edit: August 27, 2017, 01:45:02 pm by BBasile »

zeljko

  • Hero Member
  • *****
  • Posts: 938
    • http://wiki.lazarus.freepascal.org/User:Zeljan
Re: How to reparent a Form using GDK2 ?
« Reply #1 on: August 24, 2017, 11:30:43 am »
gdk_window_reparent() will unmap child window, so you have to show it again

Thaddy

  • Hero Member
  • *****
  • Posts: 4798
Re: How to reparent a Form using GDK2 ?
« Reply #2 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.
"Logically, no number of positive outcomes at the level of experimental testing can confirm a scientific theory, but a single counterexample is logically decisive."

BBasile

  • Sr. Member
  • ****
  • Posts: 341
Re: How to reparent a Form using GDK2 ?
« Reply #3 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...).

BBasile

  • Sr. Member
  • ****
  • Posts: 341
Re: How to reparent a Form using GDK2 ?
« Reply #4 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.

zeljko

  • Hero Member
  • *****
  • Posts: 938
    • http://wiki.lazarus.freepascal.org/User:Zeljan
Re: How to reparent a Form using GDK2 ?
« Reply #5 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.

BBasile

  • Sr. Member
  • ****
  • Posts: 341
Re: How to reparent a Form using GDK2 ?
« Reply #6 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.

AmatCoder

  • New member
  • *
  • Posts: 33
    • My site
Re: How to reparent a Form using GDK2 ?
« Reply #7 on: August 24, 2017, 03:31:51 pm »
AFAIK, WindowHandle does not return a GdkWindow but a GtkWidget, is not?

zeljko

  • Hero Member
  • *****
  • Posts: 938
    • http://wiki.lazarus.freepascal.org/User:Zeljan
Re: How to reparent a Form using GDK2 ?
« Reply #8 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.

BBasile

  • Sr. Member
  • ****
  • Posts: 341
Re: How to reparent a Form using GDK2 ?
« Reply #9 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.

BBasile

  • Sr. Member
  • ****
  • Posts: 341
Re: [Solved] How to reparent a Form using GDK2 ?
« Reply #10 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.

dot.not

  • New member
  • *
  • Posts: 22
  • The answer is 42
Re: [Solved] How to reparent a Form using GDK2 ?
« Reply #11 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.
There's 10 kinds of people

BBasile

  • Sr. Member
  • ****
  • Posts: 341
Re: [Solved] How to reparent a Form using GDK2 ?
« Reply #12 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.

AmatCoder

  • New member
  • *
  • Posts: 33
    • My site
Re: [Solved] How to reparent a Form using GDK2 ?
« Reply #13 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 (together with GtkPlug).

In the past I used it (with C language, however) and keyboard events work fine (it uses XEmbed protocol).

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus