GtkStatusicon/trayicon transparency support



hi,

i wrote some code for the trayicon to support transparency/colored gnome and kde panel. see attached file. At the moment it only works under KDE. Gnome notification area needs to be motified first. (already done private).

If you like the code i will make a clean patch. But how ? Should i just put the stuff in the file gtktrayicon-x11.c <http://cvs.gnome.org/viewcvs/gtk%2B/gtk/gtktrayicon-x11.c?rev=1.2&view=log> or libegg for the moment ? If you want a GObject/Custom widget you must do it yourself ;)

thanks for help, Jochen

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

typedef struct tray_struct * trayicon;

static gboolean debug=TRUE;
void create_tray_and_dock (trayicon tray);

#define SYSTEM_TRAY_REQUEST_DOCK 0


struct tray_struct {
  Window manager_window;
  GdkWindow *manager_window_gdk;
  gint screen_height;
  GdkWindow *root_gdk;
  GdkWindow *plug_gdk;
  Window plug_xlib;
  GdkPixbuf *icon_pixbuf;
  Atom system_tray_opcode_atom;
  Atom manager_atom;
};

Window get_manager_window (void)
{

  static gboolean first_call=TRUE;
  static Atom selection_atom;
  Window manager_window=None;

  if (first_call) {
    gchar *tmp=g_strdup_printf ("_NET_SYSTEM_TRAY_S%i", 
      XScreenNumberOfScreen(XDefaultScreenOfDisplay(GDK_DISPLAY())));
    selection_atom = XInternAtom(GDK_DISPLAY(), tmp, False);
    g_free (tmp);
    first_call=FALSE;
  }

  gdk_error_trap_push();
  XGrabServer (GDK_DISPLAY());
  manager_window = XGetSelectionOwner (GDK_DISPLAY(), selection_atom);
  XUngrabServer (GDK_DISPLAY());
  XFlush (GDK_DISPLAY());

  if (gdk_error_trap_pop())
    return None;
  
  printf ("get manager window: %d\n", manager_window);
    
  return manager_window;
}

void dock_window(trayicon tray)
{

  XClientMessageEvent ev;
  
  ev.type = ClientMessage;
  ev.window =tray->manager_window;
  ev.message_type =tray->system_tray_opcode_atom;
  ev.format = 32;
  ev.data.l[0] = CurrentTime;
  ev.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
  ev.data.l[2] = tray->plug_xlib;
  ev.data.l[3] =0;
  ev.data.l[4] = 0;

  gdk_error_trap_push ();
    XSendEvent (GDK_DISPLAY(), tray->manager_window, False, NoEventMask, (XEvent *)&ev);
    XSync (GDK_DISPLAY(), False);
  gdk_error_trap_pop ();

}

void reparent_notify  (trayicon tray)
{

   XSetWindowBackgroundPixmap(GDK_DISPLAY(), tray->plug_xlib, ParentRelative);
   XClearWindow (GDK_DISPLAY(), tray->plug_xlib);
   XFlush (GDK_DISPLAY());

}

void expose (trayicon tray)
{
    GdkGC *gc =gdk_gc_new (tray->plug_gdk);

    XClearWindow (GDK_DISPLAY(), tray->plug_xlib);
    XFlush (GDK_DISPLAY());
    
    gdk_draw_pixbuf (tray->plug_gdk, gc, tray->icon_pixbuf,
        0, 0, 0, 0, 24, 24, GDK_RGB_DITHER_NONE, 0, 0);

}

static GdkFilterReturn filter (GdkXEvent *xevent, 
    GdkEvent *event, gpointer user_data)
{
  XEvent *xev = (XEvent *)xevent;

  trayicon tray = (trayicon) user_data;

   
  if (xev->xany.type == ReparentNotify) {
    printf ("reparen notify\n");
    reparent_notify(tray);
  }

  if (xev->xany.type == Expose) {
    printf ("expose notify\n");
    expose(tray);
  }
  
  return GDK_FILTER_CONTINUE;
}

void create_tray_and_dock (trayicon tray)
{

  if (tray->manager_window==None)
    tray->manager_window=get_manager_window();
  
  if (tray->manager_window==None)
    return;

  tray->manager_window_gdk=NULL;
  tray->manager_window_gdk=gdk_window_foreign_new(tray->manager_window);

  tray->plug_xlib= XCreateSimpleWindow(GDK_DISPLAY(), GDK_ROOT_WINDOW(), 0, 
      0, 24, 24, 0, 0, 0);

  XSelectInput(GDK_DISPLAY(), tray->plug_xlib, StructureNotifyMask | ExposureMask);
      tray->plug_gdk=gdk_window_foreign_new (tray->plug_xlib);
  
  gdk_window_add_filter (tray->plug_gdk, filter, (gpointer) tray);

  dock_window (tray);

}

void trayicon_show (trayicon tray)
{

  g_assert (tray != NULL);

  tray->screen_height=gdk_screen_get_height (gdk_screen_get_default());
  tray->root_gdk =gdk_screen_get_root_window (gdk_screen_get_default());

  tray->manager_window = get_manager_window ();
  tray->manager_window_gdk =NULL;

  create_tray_and_dock(tray);

}

trayicon trayicon_new(GdkPixbuf *default_icon)
{

  g_assert (default_icon != NULL);

  trayicon tray;

  printf ("trayicon_new\n");

  tray =(trayicon)g_malloc(sizeof(struct tray_struct));

  tray->manager_atom = XInternAtom (GDK_DISPLAY(), "MANAGER", False);
  tray->system_tray_opcode_atom = XInternAtom (GDK_DISPLAY(), 
      "_NET_SYSTEM_TRAY_OPCODE", False);
   tray->icon_pixbuf=g_object_ref (default_icon);
  
  return tray;

}

int
main (int argc, char *argv[])
{

  gtk_init (&argc, &argv);

  trayicon tray;

 
  GdkPixbuf *pixbuf=gdk_pixbuf_new_from_file ("/home/pulp/gaim.png", NULL);

  tray=trayicon_new(pixbuf);
  g_object_unref (pixbuf);

  trayicon_show (tray);

  gtk_main ();
  return 0;
}


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