X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2Fsystray%2Fsystraybar.c;h=9842384443b7653b02e9c768a68374709f81b65a;hb=e177e2a5f09e5037eb4b16fd6d6a1dbfa22b9558;hp=0a728e73c552ea721c14ca80d3ad3f2d7dacbfd8;hpb=950baafde9286fcff4d2c3bdbf66ee3ddb1a2433;p=chaz%2Ftint2 diff --git a/src/systray/systraybar.c b/src/systray/systraybar.c index 0a728e7..9842384 100644 --- a/src/systray/systraybar.c +++ b/src/systray/systraybar.c @@ -2,6 +2,7 @@ * Tint2 : systraybar * * Copyright (C) 2009 thierry lorthiois (lorthiois@bbsoft.fr) +* based on 'docker-1.5' from Ben Jansens. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -41,15 +42,12 @@ Window net_sel_win = None, hint_win = None; // freedesktop specification doesn't allow multi systray Systraybar systray; +int refresh_systray; void init_systray() { Panel *panel = &panel1[0]; - systray.area.parent = panel; - systray.area.panel = panel; - systray.area._draw_foreground = draw_systray; - systray.area._resize = resize_systray; if (systray.area.on_screen) systray.area.on_screen = init_net(); @@ -57,19 +55,24 @@ void init_systray() if (!systray.area.on_screen) return; + systray.area.parent = panel; + systray.area.panel = panel; + systray.area._draw_foreground = draw_systray; + systray.area._resize = resize_systray; + systray.area.resize = 1; + systray.area.redraw = 1; + refresh_systray = 0; + // configure systray // draw only one systray (even with multi panel) - systray.area.posy = panel->area.pix.border.width + panel->area.paddingy; - systray.area.height = panel->area.height - (2 * systray.area.posy); - systray.area.width = 0; - - systray.area.posx = panel->area.width - panel->area.paddingxlr - panel->area.pix.border.width - systray.area.width; - if (panel->clock.area.on_screen) - systray.area.posx -= (panel->clock.area.width + panel->area.paddingx); - if (panel->battery.area.on_screen) - systray.area.posx -= (panel->battery.area.width + panel->area.paddingx); - - systray.area.redraw = 1; + if (panel_horizontal) { + systray.area.posy = panel->area.pix.border.width + panel->area.paddingy; + systray.area.height = panel->area.height - (2 * systray.area.posy); + } + else { + systray.area.posx = panel->area.pix.border.width + panel->area.paddingy; + systray.area.width = panel->area.width - (2 * panel->area.pix.border.width) - (2 * panel->area.paddingy); + } } @@ -86,43 +89,14 @@ void cleanup_systray() } free_area(&systray.area); - cleanup_net(); } void draw_systray(void *obj, cairo_t *c, int active) { - Systraybar *sysbar = obj; - Panel *panel = sysbar->area.panel; - TrayWindow *traywin; - GSList *l; - int icon_size; - - //printf("draw_systray %d %d\n", systray.area.posx, systray.area.width); - icon_size = sysbar->area.height - (2 * sysbar->area.pix.border.width) - (2 * sysbar->area.paddingy); - for (l = systray.list_icons; l ; l = l->next) { - traywin = (TrayWindow*)l->data; - - // watch for the icon trying to resize itself! - XSelectInput(server.dsp, traywin->id, StructureNotifyMask|ResizeRedirectMask); - - // position and size the icon window - XMoveResizeWindow(server.dsp, traywin->id, traywin->x, traywin->y, icon_size, icon_size); - XSetWindowBackgroundPixmap (server.dsp, panel->main_win, systray.area.pix.pmap); - - // resize our window so that the new window can fit in it - //fix_geometry(); - - // flush before clearing, otherwise the clear isn't effective. - XFlush(server.dsp); - // make sure the new child will get the right stuff in its background - // for ParentRelative. - XClearWindow(server.dsp, panel->main_win); - - // show the window - XMapRaised(server.dsp, traywin->id); - } + // tint2 don't draw systray icons. just the background. + refresh_systray = 1; } @@ -135,71 +109,80 @@ void resize_systray(void *obj) int count, posx, posy; int icon_size; - icon_size = sysbar->area.height - (2 * sysbar->area.pix.border.width) - (2 * sysbar->area.paddingy); + if (panel_horizontal) + icon_size = sysbar->area.height; + else + icon_size = sysbar->area.width; + icon_size = icon_size - (2 * sysbar->area.pix.border.width) - (2 * sysbar->area.paddingy); count = g_slist_length(systray.list_icons); - if (!count) systray.area.width = 0; - else systray.area.width = (2 * systray.area.pix.border.width) + (2 * systray.area.paddingxlr) + (icon_size * count) + ((count-1) * systray.area.paddingx); - - systray.area.posx = panel->area.width - panel->area.pix.border.width - panel->area.paddingxlr - systray.area.width; - if (panel->clock.area.on_screen) - systray.area.posx -= (panel->clock.area.width + panel->area.paddingx); - if (panel->battery.area.on_screen) - systray.area.posx -= (panel->battery.area.width + panel->area.paddingx); - - systray.area.redraw = 1; + if (panel_horizontal) { + if (!count) systray.area.width = 0; + else systray.area.width = (2 * systray.area.pix.border.width) + (2 * systray.area.paddingxlr) + (icon_size * count) + ((count-1) * systray.area.paddingx); + + systray.area.posx = panel->area.width - panel->area.pix.border.width - panel->area.paddingxlr - systray.area.width; + if (panel->clock.area.on_screen) + systray.area.posx -= (panel->clock.area.width + panel->area.paddingx); +#ifdef ENABLE_BATTERY + if (panel->battery.area.on_screen) + systray.area.posx -= (panel->battery.area.width + panel->area.paddingx); +#endif + } + else { + if (!count) systray.area.height = 0; + else systray.area.height = (2 * systray.area.pix.border.width) + (2 * systray.area.paddingxlr) + (icon_size * count) + ((count-1) * systray.area.paddingx); + + systray.area.posy = panel->area.pix.border.width + panel->area.paddingxlr; + if (panel->clock.area.on_screen) + systray.area.posy += (panel->clock.area.height + panel->area.paddingx); +#ifdef ENABLE_BATTERY + if (panel->battery.area.on_screen) + systray.area.posy += (panel->battery.area.height + panel->area.paddingx); +#endif + } - posy = panel->area.pix.border.width + panel->area.paddingy + systray.area.pix.border.width + systray.area.paddingy; - posx = systray.area.posx + systray.area.pix.border.width + systray.area.paddingxlr; + if (panel_horizontal) { + posy = panel->area.pix.border.width + panel->area.paddingy + systray.area.pix.border.width + systray.area.paddingy; + posx = systray.area.posx + systray.area.pix.border.width + systray.area.paddingxlr; + } + else { + posx = panel->area.pix.border.width + panel->area.paddingy + systray.area.pix.border.width + systray.area.paddingy; + posy = systray.area.posy + systray.area.pix.border.width + systray.area.paddingxlr; + } for (l = systray.list_icons; l ; l = l->next) { traywin = (TrayWindow*)l->data; traywin->y = posy; traywin->x = posx; - posx += (icon_size + systray.area.paddingx); - } + traywin->width = icon_size; + traywin->height = icon_size; + if (panel_horizontal) + posx += (icon_size + systray.area.paddingx); + else + posy += (icon_size + systray.area.paddingx); - // resize other objects on panel - printf("resize_systray %d %d\n", systray.area.posx, systray.area.width); + // position and size the icon window + XMoveResizeWindow(server.dsp, traywin->id, traywin->x, traywin->y, icon_size, icon_size); + } } -/* -void create_hint_win() -{ - XWMHints hints; - XClassHint classhints; - Panel *panel = systray.area.panel; - - hint_win = XCreateSimpleWindow(server.dsp, server.root_win, 0, 0, 1, 1, 0, 0, 0); - hints.flags = StateHint | WindowGroupHint | IconWindowHint; - hints.initial_state = WithdrawnState; - hints.window_group = hint_win; - hints.icon_window = panel->main_win; - - classhints.res_name = "docker"; - classhints.res_class = "Docker"; - - XSetWMProperties(server.dsp, hint_win, NULL, NULL, NULL, 0, - NULL, &hints, &classhints); - - XMapWindow(server.dsp, hint_win); -} -*/ +// *********************************************** +// systray protocol int init_net() { + // freedesktop systray specification if (XGetSelectionOwner(server.dsp, server.atom._NET_SYSTEM_TRAY_SCREEN) != None) { fprintf(stderr, "tint2 : another systray is running\n"); return 0; } - //create_hint_win(); - // init systray protocol net_sel_win = XCreateSimpleWindow(server.dsp, server.root_win, -1, -1, 1, 1, 0, 0, 0); // v0.2 trayer specification. tint2 always orizontal. + // TODO : vertical panel ?? int orient = 0; XChangeProperty(server.dsp, net_sel_win, server.atom._NET_SYSTEM_TRAY_ORIENTATION, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &orient, 1); @@ -220,7 +203,6 @@ int init_net() ev.data.l[3] = 0; ev.data.l[4] = 0; XSendEvent(server.dsp, server.root_win, False, StructureNotifyMask, (XEvent*)&ev); - return 1; } @@ -234,88 +216,81 @@ void cleanup_net() } -/* -void fix_geometry() -{ - GSList *it; - Panel *panel = systray.area.panel; - - // find the proper width and height - width = 0; - height = icon_size; - for (it = icons; it != NULL; it = g_slist_next(it)) { - width += icon_size; - } - - XResizeWindow(server.dsp, panel->main_win, width + border * 2, height + border * 2); -} -*/ - gboolean error; int window_error_handler(Display *d, XErrorEvent *e) { - d=d;e=e; - if (e->error_code == BadWindow) { - error = TRUE; - } else { - //g_printerr("X ERROR NOT BAD WINDOW!\n"); - abort(); - } - return 0; -} - - -gboolean icon_swallow(Window id) -{ - XErrorHandler old; - Panel *panel = systray.area.panel; - - error = FALSE; - old = XSetErrorHandler(window_error_handler); - XReparentWindow(server.dsp, id, panel->main_win, 0, 0); - XSync(server.dsp, False); - XSetErrorHandler(old); - - return !error; + d=d;e=e; + error = TRUE; + if (e->error_code != BadWindow) { + printf("error_handler %d\n", e->error_code); + } + return 0; } -// The traywin must have its id and type set. gboolean add_icon(Window id) { TrayWindow *traywin; + XErrorHandler old; + Panel *panel = systray.area.panel; - if (!icon_swallow(id)) { + error = FALSE; + old = XSetErrorHandler(window_error_handler); + XReparentWindow(server.dsp, id, panel->main_win, 0, 0); + XSync(server.dsp, False); + XSetErrorHandler(old); + if (error != FALSE) { fprintf(stderr, "tint2 : not icon_swallow\n"); return FALSE; } + { + Atom acttype; + int actfmt; + unsigned long nbitem, bytes; + unsigned char *data = 0; + int ret; + + ret = XGetWindowProperty(server.dsp, id, server.atom._XEMBED_INFO, 0, 2, False, server.atom._XEMBED_INFO, &acttype, &actfmt, &nbitem, &bytes, &data); + if (data) XFree(data); + if (ret != Success) { + fprintf(stderr, "tint2 : xembed error\n"); + return FALSE; + } + } + { + XEvent e; + e.xclient.type = ClientMessage; + e.xclient.serial = 0; + e.xclient.send_event = True; + e.xclient.message_type = server.atom._XEMBED; + e.xclient.window = id; + e.xclient.format = 32; + e.xclient.data.l[0] = CurrentTime; + e.xclient.data.l[1] = XEMBED_EMBEDDED_NOTIFY; + e.xclient.data.l[2] = 0; + e.xclient.data.l[3] = panel->main_win; + e.xclient.data.l[4] = 0; + XSendEvent(server.dsp, id, False, 0xFFFFFF, &e); + } + traywin = g_new0(TrayWindow, 1); traywin->id = id; systray.list_icons = g_slist_prepend(systray.list_icons, traywin); - printf("ajout d'un icone %d (%lx)\n", g_slist_length(systray.list_icons), id); systray.area.resize = 1; - systray.area.redraw = 1; + systray.area.redraw = 1; + //printf("add_icon id %lx, %d\n", id, g_slist_length(systray.list_icons)); + + // watch for the icon trying to resize itself! + XSelectInput(server.dsp, traywin->id, StructureNotifyMask); + + // show the window + XMapRaised(server.dsp, traywin->id); // changed in systray force resize on panel - Panel *panel = systray.area.panel; panel->area.resize = 1; panel_refresh = 1; - -// => calcul x, y, width, height dans resize -/* - // find the positon for the systray app window - int count = g_slist_length(icons); - traywin->x = border + ((width % icon_size) / 2) + - (count % (width / icon_size)) * icon_size; - traywin->y = border + ((height % icon_size) / 2) + - (count / (height / icon_size)) * icon_size; - - // add the new icon to the list - icons = g_slist_append(icons, traywin); -*/ - return TRUE; } @@ -323,27 +298,29 @@ gboolean add_icon(Window id) void remove_icon(TrayWindow *traywin) { XErrorHandler old; + Window id = traywin->id; - XSelectInput(server.dsp, traywin->id, NoEventMask); + // remove from our list + systray.list_icons = g_slist_remove(systray.list_icons, traywin); + g_free(traywin); + systray.area.resize = 1; + systray.area.redraw = 1; + //printf("remove_icon id %lx, %d\n", traywin->id); + + XSelectInput(server.dsp, id, NoEventMask); // reparent to root error = FALSE; old = XSetErrorHandler(window_error_handler); - XReparentWindow(server.dsp, traywin->id, server.root_win, 0, 0); + XUnmapWindow(server.dsp, id); + XReparentWindow(server.dsp, id, server.root_win, 0, 0); XSync(server.dsp, False); XSetErrorHandler(old); - // remove from our list - systray.list_icons = g_slist_remove(systray.list_icons, traywin); - g_free(traywin); - printf("suppression d'un icone %d\n", g_slist_length(systray.list_icons)); - systray.area.resize = 1; - // changed in systray force resize on panel Panel *panel = systray.area.panel; panel->area.resize = 1; panel_refresh = 1; - } @@ -353,7 +330,6 @@ void net_message(XClientMessageEvent *e) Window id; opcode = e->data.l[1]; - switch (opcode) { case SYSTEM_TRAY_REQUEST_DOCK: id = e->data.l[2]; @@ -361,24 +337,28 @@ void net_message(XClientMessageEvent *e) break; case SYSTEM_TRAY_BEGIN_MESSAGE: - printf("message from dockapp\n"); - id = e->window; - break; - case SYSTEM_TRAY_CANCEL_MESSAGE: - printf("message cancelled\n"); - id = e->window; + // we don't show baloons messages. break; default: - if (opcode == server.atom._NET_SYSTEM_TRAY_MESSAGE_DATA) { - printf("message from dockapp:\n %s\n", e->data.b); - id = e->window; - } - // unknown message type. not in the spec + if (opcode == server.atom._NET_SYSTEM_TRAY_MESSAGE_DATA) + printf("message from dockapp: %s\n", e->data.b); + else + fprintf(stderr, "SYSTEM_TRAY : unknown message type\n"); break; } } +void refresh_systray_icon() +{ + TrayWindow *traywin; + GSList *l; + for (l = systray.list_icons; l ; l = l->next) { + traywin = (TrayWindow*)l->data; + XClearArea(server.dsp, traywin->id, 0, 0, traywin->width, traywin->height, True); + } +} +