Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Embed/Swallow an external X11 prog in Tk

16 views
Skip to first unread message

kenTk

unread,
Jul 31, 2018, 2:56:54 PM7/31/18
to
I am looking to embed a separate program that is written in c using X11/Xlib etc in to a Tk Frame.
I started with this rather old posting.
https://www.perlmonks.org/?node_id=83360
which works partially using xterm as the external program.
Both xterm and my prog suffer the same problem so I will leave it with the xterm example for the sake of this posting.
The only change that I made to the above script was to change "color_xterm" to "xterm".
If you call it with a command line argument of 1 it fails to embed.
With more than 1 it will embed n-1 times. The last iteration fails and you are left with a separate, non-embedded xterm pane.
It seems that reparent always needs a following call of itself to complete the reparent process. Simply calling it twice each time does not fix it.

I worked on it for many hours and eventually left it with a band-aid: I made an n+1 iteration using a separate, target Tk parent pane ( which it never reaches)and then killed the n+1 instance of xterm.

I appreciate that xterm has its own "-into" function for doing this as posted on
https://www.perlmonks.org/bare/?node_id=359764
But "-into" is built in. To do something similar I would have to re-write my prog using something like the X Toolkit and XtOpenDisplay instead of XopenDisplay but that is another learning curve.

Any suggestions would be appreciated.

kenTk

unread,
Aug 10, 2018, 2:37:40 PM8/10/18
to
An update after more investigations and tests:
I have created this, smallest possible X program that, when called from perl enables ReparentWindow to work.
// smallX.c
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

Display *theDisplay;
int main(int argc, char ** argv)
{
// Connect to the display server
theDisplay = XOpenDisplay(NULL);
if (!theDisplay) {fprintf(stderr, "unable to connect to display\n");return 7;}
XCloseDisplay(NULL); // Only for tidyness
return 0;
}

The simplified and modified Tk that I am using for the test:
#!/usr/bin/perl
# $Id: ptk_steal.pl,v 1.1 1999/07/01 19:56:31 eserte Exp $
# Author: Slaven Rezic
# Copyright (C) 1999 Slaven Rezic. All rights reserved.
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
# Mail:
# WWW: http://user.cs.tu-berlin.de/~eserte/
# Modified by KVS Aug 2018

use strict;
use Tk;
use X11::Protocol;

my $x = X11::Protocol->new();
my $top = MainWindow->new(-width=>850,-height=>525);
my $pid;
my $wid;

$top->Label( -text => "A xterm:" )->place(-x=>200,-y=>1);
$top->Button(-text => 'Exit',
-command => sub{
kill(9,$pid);
$top->destroy})->place(-x=>4,-y=>5);

my $f = $top->Frame( -width => 600, -height => 500,'-container' => 1,-background=>'blue' )->place(-x=>200,-y=>20);
$f->update;

unless($pid = fork)
{
exec("/usr/bin/xterm -name WindowToSteal");
}


my $check = $top->repeat(50,sub { $wid = get_window_by_name("WindowToSteal");});

while ( !defined $wid )
{
$top->waitVariable( \$wid );
}
$check->cancel;

$x->ReparentWindow( $wid, oct( $f->id ), 100, 100 );

# THE FOLLOWING LINE MAKES ReparentWindow WORK. WITHOUT IT xterm WONT GO IN THE # FRAME.
system("./smallX");

MainLoop();

sub get_window_by_name
{
_get_window_by_name( $x->{'root'}, $_[0] );
}

sub _get_window_by_name
{
my ( $root, $searchname ) = @_;
my ( $dummy, $dummy2, @new_kids ) = $x->QueryTree($root);
foreach my $k (@new_kids) {
my $atomnr;

foreach my $atom ( $x->ListProperties($k) )
{
if ( $x->GetAtomName($atom) eq "WM_CLASS" )
{
$atomnr = $atom;
last;
}
}
if ( defined $atomnr )
{
my ($classprop) =
$x->GetProperty( $k, $atomnr, "AnyPropertyType", 0, 256, 0);

my ( $class, $name ) = split( /\0/, $classprop );
if ( $class eq $searchname )
{
return $k;
}
}
my $ret = _get_window_by_name( $k, $searchname );
if ( defined $ret )
{
return $ret;
}
}
undef;
}

__END__

It looks like there is a pipeline which needs to be flushed.
0 new messages