For add auto-hide animation for GTK desktop panel, the key word is gdk_window_move() and set widget as GDK_WINDOW_TYPE_HINT_DOCK(or use Xlib to set Atom). For fix the panel icon filcker we have to use gdk_window_set_back_pixmap().
gdk-move.c:
/** * gcc -g -o gdk-move gdk-move.c `pkg-config gtk+-2.0 --cflags --libs gthread-2.0` */ #include <gtk/gtk.h> guint animation_hidden = 0; guint animation_show = 0; gboolean hidden = FALSE; gboolean processing = FALSE; int y_pos = 0; gboolean panel_toplevel_animation_show (GtkWidget *toplevel) { y_pos += 1; if (y_pos <= 0) { processing = TRUE; gdk_window_move (toplevel->window, toplevel->allocation.x, y_pos); } else { y_pos = 0; processing = FALSE; hidden = FALSE; return FALSE; } //g_message ("show %d", y_pos); return TRUE; } gboolean panel_toplevel_animation_hidden (GtkWidget *toplevel) { y_pos -= 1; if (toplevel->allocation.height + y_pos > 1) { processing = TRUE; gdk_window_move (toplevel->window, toplevel->allocation.x, y_pos); } else { processing = FALSE; hidden = TRUE; return FALSE; } //g_message ("hidden %d", y_pos); return TRUE; } void panel_hidden (GtkWidget *widget) { animation_hidden = g_timeout_add (20, (GSourceFunc) panel_toplevel_animation_hidden, widget); } void panel_show (GtkWidget *widget) { animation_show = g_timeout_add (20, (GSourceFunc) panel_toplevel_animation_show, widget); } gboolean enter_event (GtkWidget *widget, GdkEventCrossing *event, gpointer data) { if (!processing && hidden && event->detail != GDK_NOTIFY_INFERIOR) { g_message ("show"); panel_show (widget); } return FALSE; } gboolean leave_event (GtkWidget *widget, GdkEventCrossing *event, gpointer data) { if (!processing && !hidden && event->detail != GDK_NOTIFY_INFERIOR){ g_message ("hidden"); panel_hidden (widget); } return FALSE; } void size_allocate (GtkWidget *widget, GtkAllocation *allocation, gpointer user_data) { g_message ("size_allocate"); } void size_request (GtkWidget *widget, GtkRequisition *requisition, gpointer user_data) { g_message ("size_request"); } gboolean expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { g_message ("expose_event"); return FALSE; } int main( int argc, char *argv[] ) { GtkWidget *window; GtkWidget *box; gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DOCK); gtk_window_set_default_size (GTK_WINDOW (window), gdk_screen_get_width (gdk_screen_get_default ()), 100); box = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (window), box); GtkWidget *image = gtk_image_new_from_file ("/home/john/Pictures/test.png"); gtk_box_pack_start (GTK_BOX(box), image, TRUE, TRUE, 0); gtk_widget_set_double_buffered (window, FALSE); g_signal_connect (G_OBJECT (window), "size_allocate", G_CALLBACK (size_allocate), NULL); g_signal_connect (G_OBJECT (window), "size-request", G_CALLBACK (size_request), NULL); g_signal_connect (G_OBJECT (window), "expose-event", G_CALLBACK (expose_event), NULL); g_signal_connect (G_OBJECT (window), "enter_notify_event", G_CALLBACK (enter_event), NULL); g_signal_connect (G_OBJECT (window), "leave_notify_event", G_CALLBACK (leave_event), NULL); gtk_widget_show_all (window); gdk_window_set_back_pixmap(window->window,NULL,FALSE); gtk_main (); return 0; }
use Xlib to set window as DOCK(from gnome-panel-2.30.0):
static Atom net_wm_window_type = None; static Atom net_wm_window_type_dock = None; static Atom net_wm_window_type_normal = None; void panel_xutils_set_window_type (GdkWindow *gdk_window, PanelXUtilsWindowType type) { Display *display; Window window; Atom atoms [2]; int i = 0; g_return_if_fail (GDK_IS_WINDOW (gdk_window)); display = GDK_WINDOW_XDISPLAY (gdk_window); window = GDK_WINDOW_XWINDOW (gdk_window); if (net_wm_window_type == None) net_wm_window_type = XInternAtom (display, "_NET_WM_WINDOW_TYPE", False); switch (type) { case PANEL_XUTILS_TYPE_DOCK: if (net_wm_window_type_dock == None) net_wm_window_type_dock = XInternAtom (display, "_NET_WM_WINDOW_TYPE_DOCK", False); atoms [i++] = net_wm_window_type_dock; break; case PANEL_XUTILS_TYPE_NORMAL: if (net_wm_window_type_normal == None) net_wm_window_type_normal = XInternAtom (display, "_NET_WM_WINDOW_TYPE_NORMAL", False); atoms [i++] = net_wm_window_type_normal; break; default: g_assert_not_reached (); break; } gdk_error_trap_push (); XChangeProperty (display, window, net_wm_window_type, XA_ATOM, 32, PropModeReplace, (guchar *) &atoms, i); gdk_error_trap_pop (); }