Recent

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

guest58172

  • Guest
[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.

zeljko

  • Hero Member
  • *****
  • Posts: 1594
    • 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: 14199
  • Probably until I exterminate Putin.
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.
Specialize a type, not a var.

guest58172

  • Guest
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...).

guest58172

  • Guest
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: 1594
    • 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.

guest58172

  • Guest
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

  • Jr. Member
  • **
  • Posts: 55
    • 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: 1594
    • 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.

guest58172

  • Guest
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.

guest58172

  • Guest
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

guest58172

  • Guest
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

  • Jr. Member
  • **
  • Posts: 55
    • 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).

 

TinyPortal © 2005-2018