Exemple #1
0
/* Perform several periodic tasks */
void perform_periodic_tasks(int mask)
{
	struct TrayIcon *ti;
	/* 1. Remove all invalid icons */
	while ((ti = icon_list_forall(&find_invalid_icons)) != NULL) {
		LOG_TRACE(("icon 0x%x is invalid; removing\n", ti->wid));
		remove_icon(ti->wid);
	}
	/* 2. Print tray status if asked to */
	if (tray_status_requested) dump_tray_status();
	/* 3. KLUDGE to fix window size on (buggy?) WMs */
	if (settings.kludge_flags & KLUDGE_FIX_WND_SIZE) {
		/* KLUDGE TODO: resolve */
		XWindowAttributes xwa;
		XGetWindowAttributes(tray_data.dpy, tray_data.tray, &xwa);
		if (!tray_data.is_reparented && 
				(xwa.width != tray_data.xsh.width || xwa.height != tray_data.xsh.height)) 
		{
			LOG_TRACE(("KLUDGE: fixing tray window size (current: %dx%d, required: %dx%d)\n",
						xwa.width, xwa.height,
						tray_data.xsh.width, tray_data.xsh.height));
			tray_update_window_props();
		} 
	}
	/* 4. run scrollbars periodic tasks */
	if (mask & PT_MASK_SB) scrollbars_periodic_tasks();
}
Exemple #2
0
/* Track icon visibility state changes */
void icon_track_visibility_changes(Window w)
{
	struct TrayIcon *ti;
	int mapped;
	/* Ignore false alarms */
	if ((ti = icon_list_find(w)) == NULL || !ti->is_xembed_supported) return;
	mapped = xembed_get_mapped_state(ti);
	LOG_TRACE(("xembed_is_mapped(0x%x) = %u\n", w, mapped));
	LOG_TRACE(("is_visible = %u\n", ti->is_visible));
#ifdef DEBUG
	x11_dump_win_info(tray_data.dpy, ti->wid);
#endif
	/* Nothing has changed */
	if (mapped == ti->is_visible) return;
	ti->is_visible = mapped;
	LOG_INFO(("%s icon 0x%x\n", mapped ? "showing" : "hiding", w));
	if (mapped) { /* Icon has become mapped and is listed as hidden. Show this icon. */
		embedder_reset_size(ti);
		if (!layout_add(ti)) {
			xembed_set_mapped_state(ti, False);
			return;
		}
		embedder_show(ti);
	} else { /* Icon has become unmapped and is listed as visible. Hide this icon. */
		layout_remove(ti);
		embedder_hide(ti);
	}
	embedder_update_positions(False);
	tray_update_window_props();
}
Exemple #3
0
static void refresh_icons()
{
	embedder_update_positions(_refresh_forced);
	tray_update_window_props();
	_refresh = FALSE;
	_refresh_forced = FALSE;
}
Exemple #4
0
void configure_notify(XConfigureEvent ev)
{
	struct TrayIcon *ti;
	struct Point sz;
	XWindowAttributes xwa;
	if (ev.window == tray_data.tray) {
		/* Tray window was resized */
		/* TODO: distinguish between synthetic and real configure notifies */
		/* TODO: catch rejected configure requests */
		/* XXX: Geometry stuff is a mess. Geometry
		 * is specified in slots, but almost always is 
		 * stored in pixels... */
		LOG_TRACE(("tray window geometry from event: %ux%u+%d+%d\n", ev.width, ev.height, ev.x, ev.y));
		/* Sometimes, configure notifies come too late, so we fetch real geometry ourselves */
		XGetWindowAttributes(tray_data.dpy, tray_data.tray, &xwa);
		x11_get_window_abs_coords(tray_data.dpy, tray_data.tray, &tray_data.xsh.x, &tray_data.xsh.y);
		LOG_TRACE(("tray window geometry from X11 calls: %dx%d+%d+%d\n", xwa.width, xwa.height, tray_data.xsh.x, tray_data.xsh.y));
		tray_data.xsh.width = xwa.width;
		tray_data.xsh.height = xwa.height;
		/* Update icons positions */
		/* XXX: internal API is bad. example below */
		icon_list_forall(&layout_translate_to_window);
		embedder_update_positions(True);
		/* Adjust window background if necessary */
		tray_update_bg(False);
		tray_refresh_window(True);
		tray_update_window_strut();
		scrollbars_update();
	} else if ((ti = icon_list_find(ev.window)) != NULL) { /* Some icon has resized its window */
		/* KDE icons are not allowed to change their size. Reset icon size. */
		if (ti->cmode == CM_KDE || settings.kludge_flags & KLUDGE_FORCE_ICONS_SIZE) {
			embedder_reset_size(ti);
			return;
		}
		if (settings.kludge_flags & KLUDGE_FORCE_ICONS_SIZE) return;
		/* Get new window size */
		if (!x11_get_window_size(tray_data.dpy, ti->wid, &sz.x, &sz.y)) {
			embedder_unembed(ti);
			return;
		}
		LOG_TRACE(("icon 0x%x was resized, new size: %ux%u, old size: %ux%u\n", ev.window, 
					sz.x, sz.y, ti->l.wnd_sz.x, ti->l.wnd_sz.y));
		/* Check if the size has really changed */
		if (sz.x == ti->l.wnd_sz.x && sz.y == ti->l.wnd_sz.y) return;
		ti->l.wnd_sz = sz;
		ti->is_resized = True;
		/* Do the job */
		layout_handle_icon_resize(ti);
		embedder_refresh(ti);
#ifdef DEBUG
		print_icon_data(ti);
#endif
		embedder_update_positions(False);
		tray_update_window_props();
#ifdef DEBUG
		dump_tray_status();
#endif
	}
}
Exemple #5
0
/* Add icon to the tray */
void add_icon(Window w, int cmode)
{
	struct TrayIcon *ti;
	/* Aviod adding duplicates */
	if ((ti = icon_list_find(w)) != NULL) {
		LOG_TRACE(("ignoring second request to embed 0x%x"
					"(requested cmode=%d, current cmode=%d\n",
					w, cmode, ti->cmode));
		return;
	}
	/* Dear Edsger W. Dijkstra, I see you behind my back =( */
	if ((ti = icon_list_new(w, cmode)) == NULL) goto failed0;
	LOG_TRACE(("starting embedding for icon 0x%x, cmode=%d\n", w, cmode));
	x11_dump_win_info(tray_data.dpy, w);
	/* Start embedding cycle */
	if (!xembed_check_support(ti)) goto failed1;
	if (ti->is_xembed_supported)
		ti->is_visible = xembed_get_mapped_state(ti);
	else
		ti->is_visible = True;
	if (ti->is_visible) {
		if (!embedder_reset_size(ti)) goto failed1;
		if (!layout_add(ti)) goto failed1;
	}
	if (!xembed_embed(ti)) goto failed1;
	if (!embedder_embed(ti)) goto failed2;
	embedder_update_positions(False);
	tray_update_window_props();
	/* Report success */
	LOG_INFO(("added icon %s (wid 0x%x) as %s\n", 
			x11_get_window_name(tray_data.dpy, ti->wid, "<unknown>"),
			ti->wid, 
			ti->is_visible ? "visible" : "hidden"));
	goto ok;
failed2:
	layout_remove(ti);
failed1:
	icon_list_free(ti);
failed0:
	LOG_INFO(("failed to add icon %s (wid 0x%x)\n", 
			x11_get_window_name(tray_data.dpy, ti->wid, "<unknown>"),
			ti->wid));
ok:
	if (settings.log_level >= LOG_LEVEL_TRACE) dump_tray_status();
	return;
}
Exemple #6
0
/* Remove icon from the tray */
void remove_icon(Window w)
{
	struct TrayIcon *ti;
	char *name;
	/* Ignore false alarms */
	if ((ti = icon_list_find(w)) == NULL) return;
	dump_tray_status();
	embedder_unembed(ti);
	xembed_unembed(ti);
	layout_remove(ti);
	icon_list_free(ti);
	LOG_INFO(("removed icon %s (wid 0x%x)\n",
				x11_get_window_name(tray_data.dpy, ti->wid, "<unknown>"), 
				w));
	/* no need to call embedde_update_positions(), as
	 * scrollbars_click(SB_WND_MAX) will call it */
	/* XXX: maybe we need a different name for this
	 * routine instad of passing cryptinc constant? */
	scrollbars_click(SB_WND_MAX);
	tray_update_window_props();
	dump_tray_status();
}
Exemple #7
0
void client_message(XClientMessageEvent ev)
{
	int cmode = CM_FDO;
	struct TrayIcon *ti;
#ifdef DEBUG
	/* Print neat message(s) about this event to aid debugging */
	char *msg_type_name;
	msg_type_name = XGetAtomName(tray_data.dpy, ev.message_type);
	if (msg_type_name != NULL) {
		LOG_TRACE(("message \"%s\"\n", msg_type_name));
		XFree(msg_type_name);
	}
	if (ev.message_type == tray_data.xa_wm_protocols) {
		msg_type_name = XGetAtomName(tray_data.dpy, ev.data.l[0]);
		if (msg_type_name != NULL) {
			LOG_TRACE(("WM_PROTOCOLS message type: %s\n", msg_type_name));
			XFree(msg_type_name);
		}
	}
#endif
	/* Graceful exit */
	if (ev.message_type == tray_data.xa_wm_protocols &&
		ev.data.l[0] == tray_data.xa_wm_delete_window && 
		ev.window == tray_data.tray)
	{
		LOG_TRACE(("got WM_DELETE message, will now exit\n"));
		exit(0); // atexit will call cleanup()
	} 
	/* Handle _NET_SYSTEM_TRAY_* messages */
	if (ev.message_type == tray_data.xa_tray_opcode && tray_data.is_active) {
		LOG_TRACE(("this is the _NET_SYSTEM_TRAY_OPCODE(%lu) message\n", ev.data.l[1]));
		switch (ev.data.l[1]) {
			/* This is the starting point of NET SYSTEM TRAY protocol */
			case SYSTEM_TRAY_REQUEST_DOCK:
				LOG_TRACE(("dockin' requested by window 0x%x, serving in a moment\n", ev.data.l[2]));
#ifndef NO_NATIVE_KDE
				if (kde_tray_check_for_icon(tray_data.dpy, ev.data.l[2])) cmode = CM_KDE;
				if (kde_tray_is_old_icon(ev.data.l[2])) kde_tray_old_icons_remove(ev.data.l[2]);
#endif
				add_icon(ev.data.l[2], cmode);
				break;
			/* We ignore these messages, since we do not show
			 * any baloons anyways */
			case SYSTEM_TRAY_BEGIN_MESSAGE:
			case SYSTEM_TRAY_CANCEL_MESSAGE:
				break;
			/* Below are special cases added by this implementation */
			/* STALONETRAY_TRAY_DOCK_CONFIRMED is sent by stalonetray 
			 * to itself. (see embed.c) */
			case STALONE_TRAY_DOCK_CONFIRMED:
				ti = icon_list_find(ev.data.l[2]);
				if (ti != NULL && !ti->is_embedded) {
					ti->is_embedded = True;
					LOG_TRACE(("embedding confirmed for icon 0x%x\n", ti->wid));
#ifdef DEBUG
					dump_tray_status();
#endif
				}
				tray_update_window_props();
				break;
			/* Dump tray status on request */
			case STALONE_TRAY_STATUS_REQUESTED:
				dump_tray_status();
				break;
			/* Find icon and scroll to it if necessary */
			case STALONE_TRAY_REMOTE_CONTROL:
				ti = icon_list_find(ev.window);
				if (ti == NULL) break;
				scrollbars_scroll_to(ti);
#if 0
				/* Quick hack */
				{
					Window icon = ev.window;
					int rc;
					int x = ev.data.l[3], y = ev.data.l[4], depth = 0, idummy, i;
					int btn = ev.data.l[2];
					Window win, root;
					unsigned int udummy, w, h;
					XGetGeometry(tray_data.dpy, icon, &root, 
							&idummy, &idummy, 
							&w, &h, &udummy, &udummy);
					LOG_TRACE(("wid=0x%x w=%d h=%d\n", icon, w, h));
					x = (x == REMOTE_CLICK_POS_DEFAULT) ? w / 2 : x;
					y = (y == REMOTE_CLICK_POS_DEFAULT) ? h / 2 : y;
					/* 3.2. Find subwindow to execute click on */
					win = x11_find_subwindow_at(tray_data.dpy, icon, &x, &y, depth);
					/* 3.3. Send mouse click(s) to target */
					LOG_TRACE(("wid=0x%x btn=%d x=%d y=%d\n", 
								win, btn, x, y));
#define SEND_BTN_EVENT(press, time) do { \
					x11_send_button(tray_data.dpy, /* dispslay */ \
							press, /* event type */ \
							win, /* target window */ \
							root, /* root window */ \
							time, /* time */ \
							btn, /* button */ \
							Button1Mask << (btn - 1), /* state mask */ \
							x, /* x coord (relative) */ \
							y); /* y coord (relative) */ \
				} while (0)
					for (i = 0; i < ev.data.l[0]; i++) {
						SEND_BTN_EVENT(1, x11_get_server_timestamp(tray_data.dpy, tray_data.tray));
						my_usleep(250);
						SEND_BTN_EVENT(0, x11_get_server_timestamp(tray_data.dpy, tray_data.tray));
					}
#undef SEND_BTN_EVENT
				}
#endif
				break;
			default:
				break;
		}
	}
#ifdef DEBUG
	if (ev.message_type == tray_data.xa_tray_opcode && !tray_data.is_active)
		LOG_TRACE(("ignoring _NET_SYSTEM_TRAY_OPCODE(%lu) message because tray is not active\n", tray_data.is_active));
#endif
}