Beispiel #1
0
void callback_timeout_expired()
{
	struct timespec cur_time;
	timeout* t;
	while (timeout_list) {
		clock_gettime(CLOCK_MONOTONIC, &cur_time);
		t = timeout_list->data;
		if (compare_timespecs(&t->timeout_expires, &cur_time) <= 0) {
			// it's time for the callback function
			t->_callback(t->arg);
			// If _callback() calls stop_timeout(t) the timer 't' was freed and is not in the timeout_list
			if (g_slist_find(timeout_list, t)) {
				// Timer still exists
				timeout_list = g_slist_remove(timeout_list, t);
				if (t->interval_msec > 0) {
					add_timeout_intern(t->interval_msec, t->interval_msec, t->_callback, t->arg, t);
				} else {
					// Destroy single-shot timer
					if (t->self)
						*t->self = NULL;
					free(t);
				}
			}
		} else {
			return;
		}
	}
}
Beispiel #2
0
void callback_timeout_expired() {
  struct timespec cur_time;
  timeout* t;
  while (timeout_list) {
    clock_gettime(CLOCK_MONOTONIC, &cur_time);
    t = timeout_list->data;
    if (compare_timespecs(&t->timeout_expires, &cur_time) <= 0) {
      // it's time for the callback function
      t->_callback(t->arg);
      if (g_slist_find(timeout_list, t)) {
        // if _callback() calls stop_timeout(t) the timeout 't' was freed and is
        // not in the timeout_list
        timeout_list = g_slist_remove(timeout_list, t);
        if (t->interval_msec > 0)
          add_timeout_intern(t->interval_msec, t->interval_msec, t->_callback,
                             t->arg, t);
        else
          free(t);
      }
    } else
      return;
  }
}
Beispiel #3
0
gint compare_timeouts(gconstpointer t1, gconstpointer t2) {
  return compare_timespecs(&((timeout*)t1)->timeout_expires,
                           &((timeout*)t2)->timeout_expires);
}
Beispiel #4
0
void systray_reconfigure_event(TrayWindow *traywin, XEvent *e)
{
	if (systray_profile)
		fprintf(stderr,
		        "XConfigure event: win = %lu (%s), x = %d, y = %d, w = %d, h = %d\n",
		        traywin->win,
		        traywin->name,
		        e->xconfigure.x,
		        e->xconfigure.y,
		        e->xconfigure.width,
		        e->xconfigure.height);

	if (!traywin->reparented)
		return;

	if (e->xconfigure.width != traywin->width || e->xconfigure.height != traywin->height || e->xconfigure.x != 0 ||
	    e->xconfigure.y != 0) {
		if (traywin->bad_size_counter < max_bad_resize_events) {
			struct timespec now;
			clock_gettime(CLOCK_MONOTONIC, &now);
			struct timespec earliest_resize = add_msec_to_timespec(traywin->time_last_resize, resize_period_threshold);
			if (compare_timespecs(&earliest_resize, &now) > 0) {
				// Fast resize, but below the threshold
				traywin->bad_size_counter++;
			} else {
				// Slow resize, reset counter
				traywin->time_last_resize.tv_sec = now.tv_sec;
				traywin->time_last_resize.tv_nsec = now.tv_nsec;
				traywin->bad_size_counter = 0;
			}
			if (traywin->bad_size_counter < min_bad_resize_events) {
				systray_resize_icon(traywin);
			} else {
				if (!traywin->resize_timeout)
					traywin->resize_timeout =
					    add_timeout(fast_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);
			}
		} else {
			if (traywin->bad_size_counter == max_bad_resize_events) {
				traywin->bad_size_counter++;
				fprintf(stderr,
				        RED "Detected resize loop for tray icon %lu (%s), throttling resize events" RESET "\n",
				        traywin->win,
				        traywin->name);
			}
			// Delayed resize
			// FIXME Normally we should force the icon to resize fill_color to the size we resized it to when we
			// embedded it.
			// However this triggers a resize loop in new versions of GTK, which we must avoid.
			if (!traywin->resize_timeout)
				traywin->resize_timeout =
				    add_timeout(slow_resize_period, 0, systray_resize_icon, traywin, &traywin->resize_timeout);
			return;
		}
	} else {
		// Correct size
		stop_timeout(traywin->resize_timeout);
	}

	// Resize and redraw the systray
	if (systray_profile)
		fprintf(stderr,
				BLUE "[%f] %s:%d trigger resize & redraw" RESET "\n",
				profiling_get_time(),
				__FUNCTION__,
				__LINE__);
	panel_refresh = TRUE;
	refresh_systray = TRUE;
}
Beispiel #5
0
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
	// 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;

	if (systray_profile)
		fprintf(stderr,
		        "[%f] %s:%d win = %lu (%s)\n",
		        profiling_get_time(),
		        __FUNCTION__,
		        __LINE__,
		        traywin->win,
		        traywin->name);

	// wine tray icons update whenever mouse is over them, so we limit the updates to 50 ms
	struct timespec now;
	clock_gettime(CLOCK_MONOTONIC, &now);
	struct timespec earliest_render = add_msec_to_timespec(traywin->time_last_render, min_refresh_period);
	if (compare_timespecs(&earliest_render, &now) > 0) {
		traywin->num_fast_renders++;
		if (traywin->num_fast_renders > max_fast_refreshes) {
			traywin->render_timeout =
			    add_timeout(min_refresh_period, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
			if (systray_profile)
				fprintf(stderr,
				        YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
				        profiling_get_time(),
				        __FUNCTION__,
				        __LINE__,
				        traywin->win,
				        traywin->name);
			return;
		}
	} else {
		traywin->time_last_render.tv_sec = now.tv_sec;
		traywin->time_last_render.tv_nsec = now.tv_nsec;
		traywin->num_fast_renders = 0;
	}

	if (traywin->width == 0 || traywin->height == 0) {
		// reschedule rendering since the geometry information has not yet been processed (can happen on slow cpu)
		traywin->render_timeout =
		    add_timeout(min_refresh_period, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
		if (systray_profile)
			fprintf(stderr,
			        YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
			        profiling_get_time(),
			        __FUNCTION__,
			        __LINE__,
			        traywin->win,
			        traywin->name);
		return;
	}

	if (traywin->render_timeout) {
		stop_timeout(traywin->render_timeout);
		traywin->render_timeout = NULL;
	}

	// 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

	// Very ugly hack, but somehow imlib2 is not able to get the image from the traywindow itself,
	// so we first render the tray window onto a pixmap, and then we tell imlib2 to use this pixmap as
	// drawable. If someone knows why it does not work with the traywindow itself, please tell me ;)
	Pixmap tmp_pmap = XCreatePixmap(server.display, traywin->win, traywin->width, traywin->height, 32);
	if (!tmp_pmap) {
		goto on_systray_error;
	}
	XRenderPictFormat *f;
	if (traywin->depth == 24) {
		f = XRenderFindStandardFormat(server.display, PictStandardRGB24);
	} else if (traywin->depth == 32) {
		f = XRenderFindStandardFormat(server.display, PictStandardARGB32);
	} else {
		fprintf(stderr, RED "Strange tray icon found with depth: %d" RESET "\n", traywin->depth);
		XFreePixmap(server.display, tmp_pmap);
		return;
	}
	XRenderPictFormat *f32 = XRenderFindVisualFormat(server.display, server.visual32);
	if (!f || !f32) {
		XFreePixmap(server.display, tmp_pmap);
		goto on_systray_error;
	}

	XSync(server.display, False);
	error = FALSE;
	XErrorHandler old = XSetErrorHandler(window_error_handler);

	// if (server.real_transparency)
	// Picture pict_image = XRenderCreatePicture(server.display, traywin->parent, f, 0, 0);
	// reverted Rev 407 because here it's breaking alls icon with systray + xcompmgr
	Picture pict_image = XRenderCreatePicture(server.display, traywin->win, f, 0, 0);
	if (!pict_image) {
		XFreePixmap(server.display, tmp_pmap);
		XSetErrorHandler(old);
		goto on_error;
	}
	Picture pict_drawable =
		XRenderCreatePicture(server.display, tmp_pmap, XRenderFindVisualFormat(server.display, server.visual32), 0, 0);
	if (!pict_drawable) {
		XRenderFreePicture(server.display, pict_image);
		XFreePixmap(server.display, tmp_pmap);
		XSetErrorHandler(old);
		goto on_error;
	}
	XRenderComposite(server.display,
	                 PictOpSrc,
	                 pict_image,
	                 None,
	                 pict_drawable,
	                 0,
	                 0,
	                 0,
	                 0,
	                 0,
	                 0,
	                 traywin->width,
	                 traywin->height);
	XRenderFreePicture(server.display, pict_image);
	XRenderFreePicture(server.display, pict_drawable);
	// end of the ugly hack and we can continue as before

	imlib_context_set_visual(server.visual32);
	imlib_context_set_colormap(server.colormap32);
	imlib_context_set_drawable(tmp_pmap);
	Imlib_Image image = imlib_create_image_from_drawable(0, 0, 0, traywin->width, traywin->height, 1);
	imlib_context_set_visual(server.visual);
	imlib_context_set_colormap(server.colormap);
	XFreePixmap(server.display, tmp_pmap);
	if (!image) {
		imlib_context_set_visual(server.visual);
		imlib_context_set_colormap(server.colormap);
		XSetErrorHandler(old);
		goto on_error;
	} else {
		if (traywin->image) {
			imlib_context_set_image(traywin->image);
			imlib_free_image_and_decache();
		}
		traywin->image = image;
	}

	imlib_context_set_image(traywin->image);
	// if (traywin->depth == 24)
	// imlib_save_image("/home/thil77/test.jpg");
	imlib_image_set_has_alpha(1);
	DATA32 *data = imlib_image_get_data();
	if (traywin->depth == 24) {
		create_heuristic_mask(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);

	systray_render_icon_from_image(traywin);

	if (traywin->damage)
		XDamageSubtract(server.display, traywin->damage, None, None);
	XSync(server.display, False);
	XSetErrorHandler(old);

	if (error)
		goto on_error;

	panel_refresh = TRUE;

	if (systray_profile)
		fprintf(stderr,
		        "[%f] %s:%d win = %lu (%s)\n",
		        profiling_get_time(),
		        __FUNCTION__,
		        __LINE__,
		        traywin->win,
		        traywin->name);

	return;

on_error:
	fprintf(stderr,
	        RED "systray %d: rendering error for icon %lu (%s) pid %d" RESET "\n",
	        __LINE__,
	        traywin->win,
	        traywin->name,
	        traywin->pid);
	return;

on_systray_error:
	fprintf(stderr,
	        RED "systray %d: rendering error for icon %lu (%s) pid %d. "
	            "Disabling compositing and restarting systray..." RESET "\n",
	        __LINE__,
	        traywin->win,
	        traywin->name,
	        traywin->pid);
	systray_composited = 0;
	stop_net();
	start_net();
	return;
}