*fix* more systray modifications for nice looking icons in real transparency mode *add* added new options to the sample files git-svn-id: http://tint2.googlecode.com/svn/trunk@311 121b4492-b84c-0410-8b4c-0d4edfb3f3cc
jump to
@@ -66,7 +66,7 @@ PKG_CHECK_MODULES([GOBJECT2], [gobject-2.0])
AC_SUBST(GOBJECT2_CFLAGS) AC_SUBST(GOBJECT2_LIBS) -PKG_CHECK_MODULES([X11], [x11]) +PKG_CHECK_MODULES([X11], [x11 xdamage xcomposite]) AC_SUBST(X11_CFLAGS) AC_SUBST(X11_LIBS)
@@ -46,6 +46,9 @@ panel_padding = 0 0 2
font_shadow = 0 panel_background_id = 1 wm_menu = 1 +panel_dock = 0 +real_transparency = 0 +panel_layer = bottom #--------------------------------------------- # TASKBAR
@@ -40,6 +40,9 @@ panel_padding = 7 2 7
font_shadow = 0 panel_background_id = 0 wm_menu = 1 +panel_dock = 0 +real_transparency = 0 +panel_layer = bottom #--------------------------------------------- # TASKBAR@@ -100,6 +103,9 @@ clock_background_id = 1
#clock_lclick_command = xclock clock_rclick_command = orage #clock_tooltip = %A %d %B +#time1_timezone = :US/Hawaii +#time2_timezone = :Europe/Berlin +#clock_tooltip_timezone = :/usr/share/zoneinfo/Europe/Paris #--------------------------------------------- # TOOLTIP
@@ -38,6 +38,9 @@ panel_padding = 5 2 0
font_shadow = 0 panel_background_id = 1 wm_menu = 1 +panel_dock = 0 +real_transparency = 0 +panel_layer = bottom #--------------------------------------------- # TASKBAR@@ -98,6 +101,9 @@ clock_background_id = 0
#clock_lclick_command = xclock clock_rclick_command = orage #clock_tooltip = %A %d %B +#time1_timezone = :US/Hawaii +#time2_timezone = :Europe/Berlin +#clock_tooltip_timezone = :/usr/share/zoneinfo/Europe/Paris #--------------------------------------------- # TOOLTIP
@@ -36,6 +36,9 @@ panel_padding = 10 3 10
font_shadow = 0 panel_background_id = 1 wm_menu = 1 +panel_dock = 0 +real_transparency = 0 +panel_layer = bottom #--------------------------------------------- # TASKBAR
@@ -31,6 +31,9 @@ panel_padding = 7 0
font_shadow = 0 panel_background_id = 1 wm_menu = 0 +panel_dock = 0 +real_transparency = 0 +panel_layer = bottom #--------------------------------------------- # TASKBAR@@ -76,6 +79,9 @@ clock_background_id = 0
#clock_lclick_command = xclock clock_rclick_command = orage #clock_tooltip = %A %d %B +#time1_timezone = :US/Hawaii +#time2_timezone = :Europe/Berlin +#clock_tooltip_timezone = :/usr/share/zoneinfo/Europe/Paris #--------------------------------------------- # BATTERY
@@ -31,6 +31,9 @@ panel_padding = 2 0
font_shadow = 0 panel_background_id = 0 wm_menu = 0 +panel_dock = 0 +real_transparency = 0 +panel_layer = bottom #--------------------------------------------- # TASKBAR@@ -76,6 +79,9 @@ clock_background_id = 1
#clock_lclick_command = xclock #clock_rclick_command = orage #clock_tooltip = %A %d %B +#time1_timezone = :US/Hawaii +#time2_timezone = :Europe/Berlin +#clock_tooltip_timezone = :/usr/share/zoneinfo/Europe/Paris #--------------------------------------------- # BATTERY
@@ -36,6 +36,10 @@ panel_margin = 0 0
panel_padding = 3 3 3 3 font_shadow = 0 panel_background_id = 3 +wm_menu = 1 +panel_dock = 0 +real_transparency = 0 +panel_layer = bottom #---------------------------------------------@@ -82,6 +86,9 @@ #time2_font = Monospace 6
clock_font_color = #151515 60 clock_padding = 4 0 clock_tooltip = %A %d %B +#time1_timezone = :US/Hawaii +#time2_timezone = :Europe/Berlin +#clock_tooltip_timezone = :/usr/share/zoneinfo/Europe/Paris #--------------------------------------------- # BATTERY
@@ -407,7 +407,6 @@
// Unfocusable XWMHints wmhints; if (panel_dock) { - // TODO: Xdnd feature cannot be used in withdrawn state at the moment (at least GTK apps fail, qt seems to work) wmhints.icon_window = wmhints.window_group = p->main_win; wmhints.flags = StateHint | IconWindowHint; wmhints.initial_state = WithdrawnState;
@@ -25,6 +25,9 @@ #include <stdlib.h>
#include <string.h> #include <glib.h> #include <Imlib2.h> +#include <X11/extensions/Xdamage.h> +#include <X11/extensions/Xrender.h> +#include <X11/extensions/Xcomposite.h> #include "systraybar.h" #include "server.h"@@ -163,6 +166,7 @@ posy += (icon_size + systray.area.paddingx);
// position and size the icon window XMoveResizeWindow(server.dsp, traywin->id, traywin->x, traywin->y, icon_size, icon_size); + XResizeWindow(server.dsp, traywin->tray_id, icon_size, icon_size); } }@@ -276,10 +280,10 @@ const TrayWindow * traywin_a = (TrayWindow*)a;
const TrayWindow * traywin_b = (TrayWindow*)b; XTextProperty name_a, name_b; - if(XGetWMName(server.dsp, traywin_a->id, &name_a) == 0) { + if(XGetWMName(server.dsp, traywin_a->tray_id, &name_a) == 0) { return -1; } - else if(XGetWMName(server.dsp, traywin_b->id, &name_b) == 0) { + else if(XGetWMName(server.dsp, traywin_b->tray_id, &name_b) == 0) { XFree(name_a.value); return 1; }@@ -300,17 +304,22 @@ Panel *panel = systray.area.panel;
int hide = 0; error = FALSE; + int wrong_format = 0; old = XSetErrorHandler(window_error_handler); XWindowAttributes attr; XGetWindowAttributes(server.dsp, id, &attr); - if ( attr.depth != server.depth ) { - XSetWindowAttributes a; - a.background_pixmap = None; // set to none, otherwise XReparentWindow fails... - a.background_pixel = 0; // set background pixel to 0. Looks ugly, but at least the icon appears - // TODO: maybe the XShape extension can be used, to clip the icon - XChangeWindowAttributes(server.dsp, id, CWBackPixmap|CWBackPixel, &a); - } - XReparentWindow(server.dsp, id, panel->main_win, 0, 0); + XSetWindowAttributes set_attr; + wrong_format = (attr.depth != server.depth); + set_attr.colormap = attr.colormap; + set_attr.background_pixel = 0; + set_attr.border_pixel = 0; + unsigned long mask = CWColormap|CWBackPixel|CWBorderPixel; + Window parent_window; + if (real_transparency) + parent_window = XCreateWindow(server.dsp, panel->main_win, 0, 0, 30, 30, 0, attr.depth, InputOutput, attr.visual, mask, &set_attr); + else + parent_window = panel->main_win; + XReparentWindow(server.dsp, id, parent_window, 0, 0); XSync(server.dsp, False); XSetErrorHandler(old); if (error != FALSE) {@@ -351,14 +360,19 @@ 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[3] = parent_window; e.xclient.data.l[4] = 0; XSendEvent(server.dsp, id, False, 0xFFFFFF, &e); } traywin = g_new0(TrayWindow, 1); - traywin->id = id; + if (real_transparency) + traywin->id = parent_window; + else + traywin->id = id; + traywin->tray_id = id; traywin->hide = hide; + traywin->wrong_format = wrong_format; if (systray.sort == 3) systray.list_icons = g_slist_prepend(systray.list_icons, traywin);@@ -371,11 +385,17 @@ 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); + XSelectInput(server.dsp, traywin->tray_id, StructureNotifyMask); + if (real_transparency) { + XDamageCreate(server.dsp, traywin->id, XDamageReportRawRectangles); + XCompositeRedirectWindow(server.dsp, traywin->id, CompositeRedirectManual); + } // show the window - if (!traywin->hide) + if (!traywin->hide) { XMapRaised(server.dsp, traywin->id); + XMapRaised(server.dsp, traywin->tray_id); + } // changed in systray force resize on panel panel->area.resize = 1;@@ -394,14 +414,16 @@ systray.area.resize = 1;
systray.area.redraw = 1; //printf("remove_icon id %lx, %d\n", traywin->id); - XSelectInput(server.dsp, traywin->id, NoEventMask); + XSelectInput(server.dsp, traywin->tray_id, NoEventMask); // reparent to root error = FALSE; old = XSetErrorHandler(window_error_handler); if (!traywin->hide) XUnmapWindow(server.dsp, traywin->id); - XReparentWindow(server.dsp, traywin->id, server.root_win, 0, 0); + XReparentWindow(server.dsp, traywin->tray_id, server.root_win, 0, 0); + if (traywin->id != traywin->tray_id) + XDestroyWindow(server.dsp, traywin->id); XSync(server.dsp, False); XSetErrorHandler(old); g_free(traywin);@@ -440,6 +462,50 @@ }
} +void systray_render_icons(TrayWindow* traywin) +{ + // most 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 + + Picture picture_systray, picture_tray, picture_panel; + Drawable mask, tray_pixmap; + Panel* panel = systray.area.panel; + XWindowAttributes attr; + XGetWindowAttributes(server.dsp, traywin->id, &attr); + XRenderPictFormat *format = XRenderFindVisualFormat(server.dsp, attr.visual); + XRenderPictFormat *panel_format = XRenderFindVisualFormat(server.dsp, server.visual); + if (traywin->wrong_format) { + imlib_context_set_drawable(traywin->id); + Imlib_Image image = imlib_create_image_from_drawable(0, 0, 0, traywin->width, traywin->height, 0); + imlib_context_set_image(image); + imlib_image_set_has_alpha(1); + DATA32* data = imlib_image_get_data(); + createHeuristicMask(data, traywin->width, traywin->height); + imlib_image_put_back_data(data); + imlib_render_pixmaps_for_whole_image(&tray_pixmap, &mask); + picture_tray = XRenderCreatePicture( server.dsp, tray_pixmap, panel_format, 0, 0); + Picture mask2 = XRenderCreatePicture( server.dsp, mask, XRenderFindStandardFormat(server.dsp, PictStandardA1), 0, 0); + picture_systray = XRenderCreatePicture( server.dsp, systray.area.pix.pmap, panel_format, 0, 0); + picture_panel = XRenderCreatePicture(server.dsp, panel->main_win, panel_format, 0, 0); + XRenderComposite(server.dsp, PictOpOver, picture_tray, mask2, picture_systray, 0, 0, 0, 0, traywin->x-systray.area.posx, traywin->y-systray.area.posy, traywin->width, traywin->height); + XRenderComposite(server.dsp, PictOpOver, picture_tray, mask2, picture_panel, 0, 0, 0, 0, traywin->x, traywin->y, traywin->width, traywin->height); + imlib_free_pixmap_and_mask(tray_pixmap); + imlib_free_image(); + } + else { + picture_tray = XRenderCreatePicture( server.dsp, traywin->id, format, 0, 0); + picture_systray = XRenderCreatePicture( server.dsp, systray.area.pix.pmap, panel_format, 0, 0); + picture_panel = XRenderCreatePicture(server.dsp, panel->main_win, panel_format, 0, 0); + XRenderComposite(server.dsp, PictOpOver, picture_tray, None, picture_systray, 0, 0, 0, 0, traywin->x-systray.area.posx, traywin->y-systray.area.posy, traywin->width, traywin->height); + XRenderComposite(server.dsp, PictOpOver, picture_tray, None, picture_panel, 0, 0, 0, 0, traywin->x, traywin->y, traywin->width, traywin->height); + } + XRenderFreePicture(server.dsp, picture_systray); + XRenderFreePicture(server.dsp, picture_tray); + XRenderFreePicture(server.dsp, picture_panel); +} + + void refresh_systray_icon() { TrayWindow *traywin;@@ -447,8 +513,9 @@ GSList *l;
for (l = systray.list_icons; l ; l = l->next) { traywin = (TrayWindow*)l->data; if (traywin->hide) continue; - XClearArea(server.dsp, traywin->id, 0, 0, traywin->width, traywin->height, True); + if (real_transparency) systray_render_icons(traywin); + else XClearArea(server.dsp, traywin->id, 0, 0, traywin->width, traywin->height, False); } + if (real_transparency) + XFlush(server.dsp); } - -
@@ -31,10 +31,12 @@
typedef struct { Window id; + Window tray_id; int x, y; int width, height; // TODO: manage icon's show/hide int hide; + int wrong_format; } TrayWindow;
@@ -27,6 +27,7 @@ #include <string.h>
#include <X11/Xutil.h> #include <X11/Xatom.h> #include <X11/Xlocale.h> +#include <X11/extensions/Xdamage.h> #include <Imlib2.h> #include <signal.h>@@ -609,9 +610,10 @@ TrayWindow *traywin;
GSList *l; for (l = systray.list_icons; l ; l = l->next) { traywin = (TrayWindow*)l->data; - if (traywin->id == win) { + if (traywin->tray_id == win) { //printf("move tray %d\n", traywin->x); XMoveResizeWindow(server.dsp, traywin->id, traywin->x, traywin->y, traywin->width, traywin->height); + XResizeWindow(server.dsp, traywin->tray_id, traywin->width, traywin->height); panel_refresh = 1; return; }@@ -701,6 +703,8 @@ cleanup();
exit(0); } + int damage_event, damage_error; + XDamageQueryExtension(server.dsp, &damage_event, &damage_error); x11_fd = ConnectionNumber(server.dsp); XSync(server.dsp, False);@@ -807,7 +811,7 @@ case DestroyNotify:
if (e.xany.window == g_tooltip.window || !systray.area.on_screen) break; for (it = systray.list_icons; it; it = g_slist_next(it)) { - if (((TrayWindow*)it->data)->id == e.xany.window) { + if (((TrayWindow*)it->data)->tray_id == e.xany.window) { remove_icon((TrayWindow*)it->data); break; }@@ -823,6 +827,10 @@ else if (e.xclient.message_type == server.atom.XdndPosition) {
dnd_message(&e.xclient); } break; + + default: + if (e.type == XDamageNotify+damage_event) + systray.area.redraw = 1; } } }
@@ -261,5 +261,4 @@ cairo_set_source_rgba(cr, 1, 1, 1, 0);
cairo_fill(cr); cairo_destroy(cr); cairo_surface_destroy (tmp); - }
@@ -234,3 +234,18 @@ }
} } + +void createHeuristicMask(DATA32* data, int w, int h) +{ + unsigned char* udata = (unsigned char*)data; + int b = udata[0]; + int g = udata[1]; + int r = udata[2]; + int i; + for (i=0; i<h*w; ++i) { + if ( abs(b-*udata)<5 && abs(g-*(udata+1))<5 && abs(r-*(udata+2))<5 ) { + *(udata+3) = 0; + } + udata += 4; + } +}
@@ -64,5 +64,6 @@
// adjust Alpha/Saturation/Brightness on an ARGB icon // alpha from 0 to 100, satur from 0 to 1, bright from 0 to 1. void adjust_asb(DATA32 *data, int w, int h, int alpha, float satur, float bright); +void createHeuristicMask(DATA32* data, int w, int h); #endif