Bug#276734: GDK icon window trouble

Brad Jorsch Brad Jorsch <anomie@users.sourceforge.net>, 276734@bugs.debian.org
Sat, 16 Oct 2004 11:35:52 -0400


--/9DWx/yDrRhgMJTb
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Here's the test program. This is the compilation command I used, GTK
requires many libraries:
gcc -Wall wmgtktest.c -o wmgtktest -I/usr/include/atk-1.0 \
-I/usr/lib/gtk-2.0/include -I/usr/include/pango-1.0 \
-I/usr/lib/glib-2.0/include -I/usr/include/glib-2.0 \
-I/usr/include/gtk-2.0 -lSM -lICE -L/usr/X11R6/lib -lXpm -lX11 -lXext \
-Wl,--export-dynamic -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 \
-lgdk_pixbuf-2.0 -lm -lpangoxft-1.0 -lpangox-1.0 -lpango-1.0 \
-lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0

You can execute it as "./wmgtktest", or as "./wmgtktest -hack" to see
the version with the hack I mentioned active. The warning about "XID
already known" is harmless, it has to do with getting the leader window
so we can correctly reparent the icon window.

This is all under Windowmaker, BTW (package wmaker). I do not know what
might happen under other window managers.

--/9DWx/yDrRhgMJTb
Content-Type: text/x-csrc; charset=us-ascii
Content-Disposition: attachment; filename="wmgtktest.c"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <gtk/gtk.h>
#include <gdk/gdkx.h>

/* XPM */
static char * xpm[] = {
"64 64 4 1",
" 	c None",
".	c #000000",
"+	c #FFFF00",
"@	c #050500",
"                          .+++++++++.                           ",
"                      .....+++++++++.....                       ",
"                   ....+++++++++++++++++....                    ",
"                 ...+++++++++++++++++++++++...                  ",
"               ...+++++++++++++++++++++++++++...                ",
"              ..+++++++++++++++++++++++++++++++..               ",
"            ...+++++++++++++++++++++++++++++++++...             ",
"           ..+++++++++++++++++++++++++++++++++++++..            ",
"          ..+++++++++++++++++++++++++++++++++++++++..           ",
"         ..+++++++++++++++++++++++++++++++++++++++++..          ",
"        ..+++++++++++++++++++++++++++++++++++++++++++..         ",
"       ..+++++++++++++++++++++++++++++++++++++++++++++..        ",
"      ..+++++++++++++++++++++++++++++++++++++++++++++++..       ",
"      .+++++++++++++++++++++++++++++++++++++++++++++++++.       ",
"     ..+++++++++++++++++++++++++++++++++++++++++++++++++..      ",
"    ..+++++++++@@@@@@@++++++++++++++++++@@@@@@@++++++++++..     ",
"    .+++++++++@@@@@@@@@++++++++++++++++@@@@@@@@@++++++++++.     ",
"   ..++++++++@@@@@@@@@@@++++++++++++++@@@@@@@@@@@+++++++++..    ",
"   .+++++++++@@@@@@@@@@@++++++++++++++@@@@@@@@@@@++++++++++.    ",
"  ..+++++++++@@@@@@@@@@@++++++++++++++@@@@@@@@@@@++++++++++..   ",
"  .++++++++++@@@@@@@@@@@++++++++++++++@@@@@@@@@@@+++++++++++.   ",
"  .++++++++++@@@@@@@@@@@++++++++++++++@@@@@@@@@@@+++++++++++.   ",
" ..++++++++++@@@@@@@@@@@++++++++++++++@@@@@@@@@@@+++++++++++..  ",
" .+++++++++++@@@@@@@@@@@++++++++++++++@@@@@@@@@@@++++++++++++.  ",
" .++++++++++++@@@@@@@@@++++++++++++++++@@@@@@@@@+++++++++++++.  ",
" .+++++++++++++@@@@@@@++++++++++++++++++@@@@@@@++++++++++++++.  ",
"..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.. ",
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++. ",
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++. ",
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++. ",
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++. ",
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++. ",
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++. ",
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++. ",
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++. ",
"+++++++++@@@@@++++++++++++++++++++++++++++++++++++++++++++++++. ",
"..+++++++@@@@@@++++++++++++++++++++++++++++++++++++++++++++++.. ",
" .+++++++@@@@@@@++++++++++++++++++++++++++++++++@@@@@++++++++.  ",
" .+++++++@@@@@@@+++++++++++++++++++++++++++++++@@@@@@++++++++.  ",
" .+++++++@@@@@@@@+++++++++++++++++++++++++++++@@@@@@@++++++++.  ",
" ..+++++++@@@@@@@++++++++++++++++++++++++++++@@@@@@@@+++++++..  ",
"  .++++++++@@@@@@@++++++++++++++++++++++++++@@@@@@@@@+++++++.   ",
"  .++++++++@@@@@@@@+++++++++++++++++++++++@@@@@@@@@@++++++++.   ",
"  ..++++++++@@@@@@@@+++++++++++++++++++++@@@@@@@@@@++++++++..   ",
"   .++++++++@@@@@@@@@@@++++++++++++++++@@@@@@@@@@@+++++++++.    ",
"   ..++++++++@@@@@@@@@@@++++++++++++++@@@@@@@@@@@+++++++++..    ",
"    .+++++++++@@@@@@@@@@@@++++++++++@@@@@@@@@@@@++++++++++.     ",
"    ..+++++++++@@@@@@@@@@@@@@+++@@@@@@@@@@@@@@+++++++++++..     ",
"     ..+++++++++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+++++++++++..      ",
"      .++++++++++++@@@@@@@@@@@@@@@@@@@@@@@@+++++++++++++.       ",
"      ..++++++++++++@@@@@@@@@@@@@@@@@@@@@@+++++++++++++..       ",
"       ..+++++++++++++@@@@@@@@@@@@@@@@@@++++++++++++++..        ",
"        ..+++++++++++++++@@@@@@@@@@@@++++++++++++++++..         ",
"         ..+++++++++++++++++++++++++++++++++++++++++..          ",
"          ..+++++++++++++++++++++++++++++++++++++++..           ",
"           ..+++++++++++++++++++++++++++++++++++++..            ",
"            ...+++++++++++++++++++++++++++++++++...             ",
"              ..+++++++++++++++++++++++++++++++..               ",
"               ...+++++++++++++++++++++++++++...                ",
"                 ...+++++++++++++++++++++++...                  ",
"                   ....+++++++++++++++++....                    ",
"                      .....+++++++++.....                       ",
"                          ...........                           ",
"                                                                "};

static GtkWidget *dockwin, *iconwin;
static GdkPixmap *pixmap;
static GdkGC *pixmap_gc;

void RedrawWindow(void) {
    gdk_draw_drawable(dockwin->window, pixmap_gc, pixmap, 0, 0, 0, 0, 64, 64);
    gdk_draw_drawable(iconwin->window, pixmap_gc, pixmap, 0, 0, 0, 0, 64, 64);
}

static gint redraw_dock(gpointer d){
    RedrawWindow();
    return 0;
}

static GdkWindow *get_gdk_leader(GdkWindow *win){
    GdkAtom atom, type;
    gint len;
    guchar *data;
    GdkWindow *leader=NULL;

    atom=gdk_atom_intern("WM_CLIENT_LEADER", TRUE);
    type=gdk_atom_intern("WINDOW", TRUE);
    if(atom==GDK_NONE || type==GDK_NONE) return NULL;
    if(!gdk_property_get(win, atom, type, 0, 4, FALSE, NULL, NULL, &len, &data)) return NULL;                                                                       if(len==4) leader=gdk_window_foreign_new(*(GdkNativeWindow *)data);
    g_free(data);
    return leader;
}

#define die(args...) { fprintf(stderr, args); exit(1); }

void openDockWindow(int argc, char *argv[], char *pixmap_bytes[]){
    GdkColormap *cmap;
    GdkColor white, black;
    GdkWindow *leader;
    XWMHints hints;

    if((dockwin=gtk_window_new(GTK_WINDOW_TOPLEVEL))==NULL) die("Couldn't create window");
    if((iconwin=gtk_window_new(GTK_WINDOW_TOPLEVEL))==NULL) die("Couldn't create window");
    gtk_widget_set_size_request(dockwin, 64, 64);
    gtk_widget_set_size_request(iconwin, 64, 64);
    gtk_widget_set_app_paintable(dockwin, TRUE);
    gtk_widget_set_app_paintable(iconwin, TRUE);
    gtk_widget_add_events(dockwin, GDK_EXPOSURE_MASK);
    gtk_widget_add_events(iconwin, GDK_EXPOSURE_MASK);
    g_signal_connect(G_OBJECT(dockwin), "expose-event", G_CALLBACK(redraw_dock), NULL);
    g_signal_connect(G_OBJECT(iconwin), "expose-event", G_CALLBACK(redraw_dock), NULL);
    g_signal_connect(G_OBJECT(dockwin), "destroy", G_CALLBACK(exit), NULL);
    g_signal_connect(G_OBJECT(iconwin), "destroy", G_CALLBACK(exit), NULL);
    gtk_widget_realize(dockwin);
    gtk_widget_realize(iconwin);
    if((leader=get_gdk_leader(dockwin->window))==NULL) die("Couldn't obtain Gdk leader window");
    gdk_window_reparent(iconwin->window, leader, 0, 0);
    gdk_window_set_icon(leader, iconwin->window, NULL, NULL);
    if(argc>1 && !strcmp(argv[1], "-hack")){
        fprintf(stderr, "Enabling hack for gdk_window_set_icon() bug\n");
        // XXX: Start hack for libgtk bug
        hints.icon_window = GDK_WINDOW_XWINDOW(iconwin->window);
        hints.flags = IconWindowHint;
        XSetWMHints(GDK_DISPLAY(), GDK_WINDOW_XWINDOW(leader), &hints);
        // XXX: End hack for libgtk bug
    }
    gdk_window_unref(leader);

    hints.initial_state = WithdrawnState;
    hints.flags = StateHint;
    XSetWMHints(GDK_DISPLAY(), GDK_WINDOW_XWINDOW(dockwin->window), &hints);

    cmap=gdk_colormap_get_system();
    white.red=65535;
    white.green=65535;
    white.blue=65535;
    black.red=0;
    black.green=0;
    black.blue=0;
    gdk_color_alloc(cmap, &white);
    gdk_color_alloc(cmap, &black);
    pixmap=gdk_pixmap_colormap_create_from_xpm_d(NULL, cmap, NULL, NULL, pixmap_bytes);

    pixmap_gc=gdk_gc_new(iconwin->window);

    RedrawWindow();

    gtk_widget_show(iconwin);
    gtk_widget_show(dockwin);
    gdk_window_withdraw(dockwin->window);
}

int main(int argc, char **argv){
    if(argc>2 || (argc==2 && strcmp(argv[1],"-hack"))){
        fprintf(stderr, "USAGE: %s [-nohack]\n", argv[0]);
        exit(1);
    }
    
    gtk_init(&argc, &argv);
    openDockWindow(argc, argv, xpm);
    gtk_main();

    return 0;
}

--/9DWx/yDrRhgMJTb--