systray: reorder operations to prevent the long icon first show delay that occurs sometimes

This commit is contained in:
o9000 2015-06-14 10:51:30 +02:00
parent 1ba023fc83
commit f5b2de62b6
3 changed files with 75 additions and 64 deletions

View file

@ -466,6 +466,10 @@ gboolean add_icon(Window win)
systray.list_icons = g_slist_sort(systray.list_icons, compare_traywindows);
// printf("add_icon win %lx, %d\n", win, g_slist_length(systray.list_icons));
if (!traywin->hide && !panel->is_hidden)
XMapRaised(server.dsp, traywin->parent);
XSync(server.dsp, False);
// Resize and redraw the systray
systray.area.resize = 1;
systray.area.redraw = 1;
@ -548,8 +552,13 @@ gboolean reparent_icon(TrayWindow *traywin)
if (ret == Success) {
if (data) {
if (nbitem == 2) {
//hide = ((data[1] & XEMBED_MAPPED) == 0);
//printf("hide %d\n", hide);
int hide = ((data[1] & XEMBED_MAPPED) == 0);
if (hide) {
//fprintf(stderr, "tint2: window refused embedding\n");
//remove_icon(traywin);
//XFree(data);
//return FALSE;
}
}
XFree(data);
}
@ -575,7 +584,7 @@ gboolean reparent_icon(TrayWindow *traywin)
XMoveResizeWindow(server.dsp, traywin->parent, traywin->x, traywin->y, traywin->width, traywin->height);
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
XFlush(server.dsp);
XSync(server.dsp, False);
return TRUE;
}
@ -647,28 +656,6 @@ void net_message(XClientMessageEvent *e)
}
}
Display *display = NULL;
XImage *tintXGetImage(Window win)
{
char *display_name = XDisplayName(NULL);
if (!display_name)
return NULL;
if (!display)
display = XOpenDisplay(display_name);
if (!display)
return NULL;
unsigned int border_width;
int xpos, ypos;
unsigned int width, height, depth;
Window root;
if (!XGetGeometry(display, win, &root, &xpos, &ypos, &width, &height, &border_width, &depth)) {
fprintf(stderr, "Couldn't get geometry of window!\n");
return NULL;
}
return XGetImage(display, win, 0, 0, width, height, AllPlanes, XYPixmap);
}
void systray_render_icon_composited(void* t)
{
// we end up in this function only in real transparency mode or if systray_task_asb != 100 0 0
@ -697,44 +684,21 @@ void systray_render_icon_composited(void* t)
traywin->render_timeout = NULL;
}
int empty = 1;
XImage *ximage = tintXGetImage(traywin->win);
if (ximage) {
if (ximage->width != traywin->width ||
ximage->height != traywin->height) {
XFree(ximage);
XCloseDisplay(display);
display = NULL;
{
unsigned int border_width;
int xpos, ypos;
unsigned int width, height, depth;
Window root;
if (!XGetGeometry(server.dsp, traywin->win, &root, &xpos, &ypos, &width, &height, &border_width, &depth)) {
fprintf(stderr, "Couldn't get geometry of window!\n");
return;
}
if (width != traywin->width || height != traywin->height) {
XMoveResizeWindow(server.dsp, traywin->win, 0, 0, traywin->width, traywin->height);
traywin->render_timeout = add_timeout(50, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
return;
}
XColor color;
if (ximage->width > 0 && ximage->height > 0) {
color.pixel = XGetPixel(ximage, ximage->width/2, ximage->height/2);
if (color.pixel != 0)
empty = 0;
int x, y;
for (x = 0; empty && x < ximage->width; x++) {
for (y = 0; empty && y < ximage->height; y++) {
color.pixel = XGetPixel(ximage, x, y);
if (color.pixel != 0)
empty = 0;
}
}
}
XFree(ximage);
XCloseDisplay(display);
display = NULL;
}
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->win, 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
@ -809,6 +773,8 @@ void systray_render_icon_composited(void* t)
if (traywin->depth == 24) {
createHeuristicMask(data, traywin->width, traywin->height);
}
int empty = imageEmpty(data, traywin->width, traywin->height);
if (systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0)
adjust_asb(data, traywin->width, traywin->height, systray.alpha, (float)systray.saturation/100, (float)systray.brightness/100);
imlib_image_put_back_data(data);
@ -822,14 +788,19 @@ void systray_render_icon_composited(void* t)
if (traywin->damage)
XDamageSubtract(server.dsp, traywin->damage, None, None);
XFlush(server.dsp);
XSync(server.dsp, False);
XSetErrorHandler(old);
if (error)
goto on_error;
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);
}
return;
on_error:
@ -847,8 +818,16 @@ on_systray_error:
void systray_render_icon(TrayWindow* traywin)
{
if (!traywin->reparented) {
if (!reparent_icon(traywin))
return;
if (systray_composited) {
// We need to process the events in the main loop first
stop_timeout(traywin->render_timeout);
traywin->render_timeout = add_timeout(50, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
return;
}
}
if (systray_composited) {
if (!traywin->render_timeout)

View file

@ -362,6 +362,37 @@ void createHeuristicMask(DATA32* data, int w, int h)
}
}
int pixelEmpty(DATA32 argb)
{
DATA32 a = (argb >> 24) & 0xff;
if (a == 0)
return 1;
DATA32 rgb = argb & 0xffFFff;
return rgb == 0;
}
int imageEmpty(DATA32* data, int w, int h)
{
unsigned int x, y;
if (w > 0 && h > 0) {
x = w / 2;
y = h / 2;
if (!pixelEmpty(data[y * w + x]))
return 0;
}
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
if (!pixelEmpty(data[y * w + x]))
return 0;
}
}
return 1;
}
void render_image(Drawable d, int x, int y)
{

View file

@ -62,6 +62,7 @@ void extract_values (const char *value, char **value1, char **value2, char **val
// 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);
int imageEmpty(DATA32* data, int w, int h);
void render_image(Drawable d, int x, int y);