From: Andreas Fink Date: Sun, 3 Jan 2010 00:33:07 +0000 (+0000) Subject: *fix* more systray modifications for nice looking icons in real transparency mode X-Git-Url: https://git.brokenzipper.com/gitweb?a=commitdiff_plain;h=e8ee3c40c5d9f7f66a033e8492c34e282002e51d;p=chaz%2Ftint2 *fix* more systray modifications for nice looking icons in real transparency mode *add* added new options to the sample files --- diff --git a/configure.ac b/configure.ac index 369010a..3488887 100644 --- a/configure.ac +++ b/configure.ac @@ -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) diff --git a/sample/black_single_desktop.tint2rc b/sample/black_single_desktop.tint2rc index 82e55f5..7b5208c 100644 --- a/sample/black_single_desktop.tint2rc +++ b/sample/black_single_desktop.tint2rc @@ -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 diff --git a/sample/default.tint2rc b/sample/default.tint2rc index dddd2a7..07f3f2a 100644 --- a/sample/default.tint2rc +++ b/sample/default.tint2rc @@ -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 diff --git a/sample/horizontal_icon_only.tint2rc b/sample/horizontal_icon_only.tint2rc index e0af81b..3a7a69c 100644 --- a/sample/horizontal_icon_only.tint2rc +++ b/sample/horizontal_icon_only.tint2rc @@ -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 diff --git a/sample/rounded_multi_desktop.tint2rc b/sample/rounded_multi_desktop.tint2rc index 30584c4..bc50885 100644 --- a/sample/rounded_multi_desktop.tint2rc +++ b/sample/rounded_multi_desktop.tint2rc @@ -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 diff --git a/sample/tint2rc b/sample/tint2rc index 1c321b5..6a9e86f 100644 --- a/sample/tint2rc +++ b/sample/tint2rc @@ -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 diff --git a/sample/vertical_icon_only.tint2rc b/sample/vertical_icon_only.tint2rc index ca9547e..9ed5fd7 100644 --- a/sample/vertical_icon_only.tint2rc +++ b/sample/vertical_icon_only.tint2rc @@ -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 diff --git a/sample/white_single_desktop.tint2rc b/sample/white_single_desktop.tint2rc index 79cb39d..713bc0a 100644 --- a/sample/white_single_desktop.tint2rc +++ b/sample/white_single_desktop.tint2rc @@ -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 @@ time1_font = AvantGardeLTMedium 9 bold 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 diff --git a/src/panel.c b/src/panel.c index 34954f7..8bb9f14 100644 --- a/src/panel.c +++ b/src/panel.c @@ -407,7 +407,6 @@ void set_panel_properties(Panel *p) // 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; diff --git a/src/systray/systraybar.c b/src/systray/systraybar.c index 02ed1b4..38acd62 100644 --- a/src/systray/systraybar.c +++ b/src/systray/systraybar.c @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include #include "systraybar.h" #include "server.h" @@ -163,6 +166,7 @@ void resize_systray(void *obj) // 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 @@ static gint compare_traywindows(gconstpointer a, gconstpointer b) 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 @@ gboolean add_icon(Window id) 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 @@ gboolean add_icon(Window id) 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 @@ gboolean add_icon(Window id) //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 @@ void remove_icon(TrayWindow *traywin) 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 net_message(XClientMessageEvent *e) } +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 @@ void refresh_systray_icon() 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); } - - diff --git a/src/systray/systraybar.h b/src/systray/systraybar.h index 9e3b990..a2dbaba 100644 --- a/src/systray/systraybar.h +++ b/src/systray/systraybar.h @@ -31,10 +31,12 @@ typedef struct { 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; diff --git a/src/tint.c b/src/tint.c index 27458b8..8f17653 100644 --- a/src/tint.c +++ b/src/tint.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -609,9 +610,10 @@ void event_configure_notify (Window win) 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 @@ int main (int argc, char *argv[]) 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 @@ int main (int argc, char *argv[]) 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 @@ int main (int argc, char *argv[]) dnd_message(&e.xclient); } break; + + default: + if (e.type == XDamageNotify+damage_event) + systray.area.redraw = 1; } } } diff --git a/src/util/area.c b/src/util/area.c index 62bb2f2..ae9c541 100644 --- a/src/util/area.c +++ b/src/util/area.c @@ -261,5 +261,4 @@ void clear_pixmap(Pixmap p, int x, int y, int w, int h) cairo_fill(cr); cairo_destroy(cr); cairo_surface_destroy (tmp); - } diff --git a/src/util/common.c b/src/util/common.c index c0ca6c3..c186d42 100644 --- a/src/util/common.c +++ b/src/util/common.c @@ -234,3 +234,18 @@ void adjust_asb(DATA32 *data, int w, int h, int alpha, float satur, float bright } } + +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