all repos — tint2 @ 3ab42f9b726a02474e073af3f179264180c25af7

fork of the tint2 desktop panel for my custom setup - only minimized windows across all desktops for the taskbar

Workaround for empty systray icon in Google Chrome (misbehaving)
o9000 o9000
commit

3ab42f9b726a02474e073af3f179264180c25af7

parent

7bce19452ee1c9ce1274f5a72950205f1873568a

4 files changed, 82 insertions(+), 10 deletions(-)

jump to
M src/server.csrc/server.c

@@ -98,6 +98,7 @@ server.atom._NET_SYSTEM_TRAY_MESSAGE_DATA = XInternAtom(server.dsp, "_NET_SYSTEM_TRAY_MESSAGE_DATA", False);

server.atom._NET_SYSTEM_TRAY_ORIENTATION = XInternAtom(server.dsp, "_NET_SYSTEM_TRAY_ORIENTATION", False); server.atom._XEMBED = XInternAtom(server.dsp, "_XEMBED", False); server.atom._XEMBED_INFO = XInternAtom(server.dsp, "_XEMBED_INFO", False); + server.atom._NET_WM_PID = XInternAtom(server.dsp, "_NET_WM_PID", True); // drag 'n' drop server.atom.XdndAware = XInternAtom(server.dsp, "XdndAware", False);
M src/server.hsrc/server.h

@@ -74,6 +74,7 @@ Atom _NET_SYSTEM_TRAY_MESSAGE_DATA;

Atom _NET_SYSTEM_TRAY_ORIENTATION; Atom _XEMBED; Atom _XEMBED_INFO; + Atom _NET_WM_PID; Atom _XSETTINGS_SCREEN; Atom _XSETTINGS_SETTINGS; Atom XdndAware;
M src/systray/systraybar.csrc/systray/systraybar.c

@@ -108,8 +108,9 @@

GSList *l; int count = 0; for (l = systray.list_icons; l ; l = l->next) { - if (!((TrayWindow*)l->data)->hide) - count++; + if (((TrayWindow*)l->data)->hide) + continue; + count++; } if (count == 0) hide(&systray.area);

@@ -146,8 +147,9 @@ if (systray_max_icon_size > 0 && sysbar->icon_size > systray_max_icon_size)

sysbar->icon_size = systray_max_icon_size; count = 0; for (l = systray.list_icons; l ; l = l->next) { - if (!((TrayWindow*)l->data)->hide) - count++; + if (((TrayWindow*)l->data)->hide || ((TrayWindow*)l->data)->empty) + continue; + count++; } //printf("count %d\n", count);

@@ -194,11 +196,12 @@ TrayWindow *traywin;

GSList *l; for (i=1, l = systray.list_icons; l ; i++, l = l->next) { traywin = (TrayWindow*)l->data; - if (traywin->hide) continue; + if (traywin->hide) + continue; traywin->y = posy; traywin->x = posx; - //printf("systray %d : %d,%d\n", i, posx, posy); + // printf("systray %d : pos %d, %d\n", traywin->tray_id, posx, posy); traywin->width = sysbar->icon_size; traywin->height = sysbar->icon_size; if (panel_horizontal) {

@@ -336,6 +339,15 @@ static gint compare_traywindows(gconstpointer a, gconstpointer b)

{ const TrayWindow * traywin_a = (TrayWindow*)a; const TrayWindow * traywin_b = (TrayWindow*)b; + + if (traywin_a->empty && !traywin_b->empty) + return 1; + if (!traywin_a->empty && traywin_b->empty) + return -1; + + if (systray.sort < 2) + return 0; + XTextProperty name_a, name_b; if(XGetWMName(server.dsp, traywin_a->tray_id, &name_a) == 0) {

@@ -361,12 +373,42 @@ XErrorHandler old;

Panel *panel = systray.area.panel; int hide = 0; + int pid = 0; + { + Atom actual_type; + int actual_format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *prop = 0; + int ret = XGetWindowProperty(server.dsp, id, server.atom._NET_WM_PID, 0, 1024, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop); + if (ret == Success && prop) { + pid = prop[1] * 256; + pid += prop[0]; + } + } + GSList *l; + int num_empty_same_pid = 0; for (l = systray.list_icons; l; l = l->next) { if (((TrayWindow*)l->data)->tray_id == id) return FALSE; + if (pid && ((TrayWindow*)l->data)->pid == pid && ((TrayWindow*)l->data)->empty) + num_empty_same_pid++; } + const int max_num_empty_same_pid = 0; + if (num_empty_same_pid > max_num_empty_same_pid) { + for (l = systray.list_icons; l; l = l->next) { + if (pid && ((TrayWindow*)l->data)->pid == pid && ((TrayWindow*)l->data)->empty) { + num_empty_same_pid++; + fprintf(stderr, "Removing tray icon %lu from misbehaving application with pid=%d\n", ((TrayWindow*)l->data)->tray_id, pid); + remove_icon((TrayWindow*)l->data); + break; + } + } + } + //printf("add_icon: %d, pid %d, %d\n", id, pid, num_empty_same_pid); + error = FALSE; XWindowAttributes attr; if ( XGetWindowAttributes(server.dsp, id, &attr) == False ) return FALSE;

@@ -445,6 +487,8 @@ traywin->tray_id = id;

traywin->hide = hide; traywin->depth = attr.depth; traywin->damage = 0; + traywin->empty = 0; + traywin->pid = pid; if (systray.area.on_screen == 0) show(&systray.area);

@@ -481,7 +525,7 @@ XErrorHandler old;

// remove from our list systray.list_icons = g_slist_remove(systray.list_icons, traywin); - //printf("remove_icon id %lx, %d\n", traywin->id); + //printf("remove_icon: %d\n", traywin->tray_id); XSelectInput(server.dsp, traywin->tray_id, NoEventMask); if (traywin->damage)

@@ -503,8 +547,9 @@ // check empty systray

int count = 0; GSList *l; for (l = systray.list_icons; l; l = l->next) { - if (!((TrayWindow*)l->data)->hide) - count++; + if (((TrayWindow*)l->data)->hide || ((TrayWindow*)l->data)->empty) + continue; + count++; } if (count == 0) hide(&systray.area);

@@ -546,6 +591,7 @@ {

// we end up in this function only in real transparency mode or if systray_task_asb != 100 0 0 // we made also sure, that we always have a 32 bit visual, i.e. we can safely create 32 bit pixmaps here TrayWindow* traywin = t; + traywin->render_timeout = 0; if ( traywin->width == 0 || traywin->height == 0 ) { // reschedule rendering since the geometry information has not yet been processed (can happen on slow cpu)

@@ -553,6 +599,27 @@ systray_render_icon(traywin);

return; } + XImage *ximage = XGetImage(server.dsp, traywin->tray_id, 0, 0, traywin->width, traywin->height, AllPlanes, XYPixmap); + XColor color; + int x, y, empty = 1; + for (x = 0; empty && x < traywin->width; x++) { + for (y = 0; empty && y < traywin->height; y++) { + color.pixel = XGetPixel(ximage, x, y); + if (color.pixel != 0) + empty = 0; + } + } + XFree(ximage); + if (traywin->empty != empty) { + traywin->empty = empty; + systray.area.resize = 1; + panel_refresh = 1; + systray.list_icons = g_slist_sort(systray.list_icons, compare_traywindows); + } + //printf("systray_render_icon_now: %d empty %d\n", traywin->tray_id, empty); + if (empty) + return; + // good systray icons support 32 bit depth, but some icons are still 24 bit. // We create a heuristic mask for these icons, i.e. we get the rgb value in the top left corner, and // mask out all pixel with the same rgb value

@@ -636,7 +703,8 @@ TrayWindow *traywin;

GSList *l; for (l = systray.list_icons; l ; l = l->next) { traywin = (TrayWindow*)l->data; - if (traywin->hide) continue; + if (traywin->hide) + continue; systray_render_icon(traywin); } }
M src/systray/systraybar.hsrc/systray/systraybar.h

@@ -43,6 +43,8 @@ int hide;

int depth; Damage damage; timeout* render_timeout; + int empty; + int pid; } TrayWindow;