GtkSocket bug ? and patch



Hi,

Let me describe the problem first.  I wrote a simple test program,
gdk_socket_add_id.c, and try to steal a legacy X app., xeyes.

I'm using Fedora Core 2 (with gtk+-2.4.14).  The procedure is as
following:

> xeyes & <CR>
> xwininfo <CR> ..... then click on xeyes, I get WID, eg 0x2c00007.
> gdk_socket_add_id 0x2c00007 <CR>

The result is two windows instead of one (xeyes embedded in embedder),
but xeyes will resize if I resize the embedder.  Looks like xeyes
does been controlled by embedder ... but reparent is not working.

I then trace gtk's source code (and also look at the source code of
a Tcl/Tk package called TkSteal).  I found the problem could be the
gdk_window_reparent() defined in gtk+-2.4.14/gdk/x11/gdkwindows-x11.c.

In TkSteal (TkSteal4.0c.tar.gz), the author said:

file: TkSteal/libTkSteal/tkXAccess.c
...
...
/*
  I do not know why, but several window managers require multiple
  reparent events. Right now a value of 25 should be enough.
  */
#define REPARENT_LOOPS 25
...
...
for (counter1 = 0; counter1 < REPARENT_LOOPS; counter1++) {
        XReparentWindow(Tk_Display(tkrootwin), window, parent, 0, 0);
        XSync(Tk_Display(tkrootwin), False);
}
...
...


Accounding to this info, I modify gtk+-2.4.14/gdk/x11/gdkwindows-x11.c
but only use REPARENT_LOOPS = 5 (check patch-gtk+-2.4.14 at the end of this
email) and it do solve the problem.

Any comment ?

Regards
KC

/* file: gdk_socket_add_id.c */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>

int main (int argc, char *argv[])
{
        int exWID;
        GtkWidget *win = NULL;
        GtkWidget *vbox = NULL;
        GtkWidget *label = NULL;
        GtkWidget *socket = NULL;

        switch (argc) {
        case 2:
                exWID = strtol(argv[1], NULL, 0);
                break;
        default:
                fprintf(stderr, "usage: %s exWID\n", argv[0]);
                exit(1);
        }

        gtk_init(&argc, &argv);

        win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        g_signal_connect(G_OBJECT(win), "delete_event",
                G_CALLBACK(gtk_main_quit), NULL);
        g_signal_connect(G_OBJECT(win), "destroy",
                G_CALLBACK(gtk_main_quit), NULL);
        gtk_container_set_border_width(GTK_CONTAINER(win), 2);
        gtk_window_set_title(GTK_WINDOW(win), "HELLO RE-PARENT");
        gtk_window_set_default_size(GTK_WINDOW(win), 640, 480);
        gtk_widget_set_size_request(GTK_WIDGET(win), 100, 100);

        vbox = gtk_vbox_new (FALSE, 0);
        gtk_container_add(GTK_CONTAINER (win), vbox);

        label = gtk_label_new ("Xlib window");
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

        socket = gtk_socket_new();

        gtk_box_pack_start (GTK_BOX (vbox), socket, TRUE, TRUE, 0);
        gtk_widget_show (socket);

        gtk_socket_add_id(GTK_SOCKET(socket), exWID);

        gtk_widget_show (socket);

        gtk_widget_show_all(win);
        gtk_main();
        exit(0);
}




--------------------------------------------------------- begin of
patch-gtk+-2.4.14
--- gtk+-2.4.14/gdk/x11/gdkwindow-x11.c 2004-10-19 04:55:17.000000000 +0800
+++ gtk+-2.4.14.kc/gdk/x11/gdkwindow-x11.c      2005-03-24
18:35:28.348561144 +0800
@@ -1534,6 +1534,7 @@
                     gint       x,
                     gint       y)
 {
+  int i, max_reparent_count = 5;
   GdkDisplay *display;
   GdkWindowObject *window_private;
   GdkWindowObject *parent_private;
@@ -1561,11 +1562,25 @@
   old_parent_private = (GdkWindowObject*)window_private->parent;
   parent_private = (GdkWindowObject*) new_parent;
   impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
-
-  XReparentWindow (GDK_WINDOW_XDISPLAY (window),
-                  GDK_WINDOW_XID (window),
-                  GDK_WINDOW_XID (new_parent),
-                  x, y);
+
+  /* 2005/03/24 Kuang-Chun Cheng <kccheng linuxdaq-labs org>
+   *
+   * According to the comment of source code of package TkSteal (by
Sven Delmas)
+   * some window managers require multiple reparent events.  I do
found this problem
+   * when I try to use gtk_socket_add_id() to kidnap a legacy X app.,
xeyes, under
+   * Fedora Core 2.
+   * The xeyes will remain a separate toplevel windows instead of a
child of embedder.
+   *
+   * The following loop do fix the problem:
+   */
+  for (i=0; i<max_reparent_count; ++i) {
+       XSync(GDK_WINDOW_XDISPLAY (window), False);
+       XReparentWindow (GDK_WINDOW_XDISPLAY (window),
+                        GDK_WINDOW_XID (window),
+                        GDK_WINDOW_XID (new_parent),
+                        x, y);
+       usleep(100);
+  }

   window_private->x = x;
   window_private->y = y;
--------------------------------------------------------- end of
patch-gtk+-2.4.14






-- 

       /\__/\       OpenATE INC
    . /`    '\      http://www.openate.com/
    === 0  0 ===    TEL: 886-2-27607832 FAX: 886-2-27694542
      \  __  /
     /        \     Kuang-Chun Cheng
    /          \    http://www.openate.com/~kccheng
   |            |   kccheng openate com, MSN: kcc1967 gmail com
    \  ||  ||  /
    #\_oo__oo_/#######o...



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]