Example #1
0
void add_timeout_intern(int value_msec, int interval_msec, void (*_callback)(),
                        void* arg, timeout* t) {
  t->interval_msec = interval_msec;
  t->_callback = _callback;
  t->arg = arg;
  struct timespec cur_time;
  clock_gettime(CLOCK_MONOTONIC, &cur_time);
  t->timeout_expires = add_msec_to_timespec(cur_time, value_msec);

  int can_align = 0;
  if (interval_msec > 0 && !t->multi_timeout)
    can_align = align_with_existing_timeouts(t);
  if (!can_align)
    timeout_list = g_slist_insert_sorted(timeout_list, t, compare_timeouts);
}
Example #2
0
void callback_multi_timeout(void* arg) {
  multi_timeout_handler* mth = arg;
  struct timespec cur_time;
  clock_gettime(CLOCK_MONOTONIC, &cur_time);
  GSList* it = mth->timeout_list;
  while (it) {
    timeout* t = it->data;
    if (++t->multi_timeout->current_count >=
        t->multi_timeout->count_to_expiration) {
      t->_callback(t->arg);
      t->multi_timeout->current_count = 0;
      t->timeout_expires = add_msec_to_timespec(cur_time, t->interval_msec);
    }
    it = it->next;
  }
}
Example #3
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;
}
Example #4
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;
}