[PATCH weston 6/8] clients: desktop-shell: show tooltip for panel items

Tiago Vignatti tiago.vignatti at intel.com
Mon May 7 05:23:12 PDT 2012


A timer is set whenever there's pointer motion inside a panel launcher item;
if the pointer stills inside the item after stopped for 500ms, then tooltip
shows up.

Signed-off-by: Tiago Vignatti <tiago.vignatti at intel.com>
---
 clients/desktop-shell.c |   79 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
index df4494e..6489671 100644
--- a/clients/desktop-shell.c
+++ b/clients/desktop-shell.c
@@ -31,6 +31,8 @@
 #include <cairo.h>
 #include <sys/wait.h>
 #include <linux/input.h>
+#include <sys/timerfd.h>
+#include <sys/epoll.h>
 
 #include <wayland-client.h>
 #include "cairo-util.h"
@@ -82,6 +84,10 @@ struct panel_launcher {
 	int focused, pressed;
 	const char *path;
 	struct wl_list link;
+
+	struct task tooltip_task;
+	int tooltip_fd;
+	int last_x, last_y;
 };
 
 struct unlock_dialog {
@@ -248,7 +254,9 @@ panel_launcher_leave_handler(struct widget *widget,
 			     struct input *input, void *data)
 {
 	struct panel_launcher *launcher = data;
+	struct window *parent = launcher->panel->window;
 
+	window_destroy_tooltip(parent);
 	launcher->focused = 0;
 	widget_schedule_redraw(widget);
 }
@@ -267,6 +275,73 @@ panel_launcher_button_handler(struct widget *widget,
 }
 
 static void
+tooltip_func(struct task *task, uint32_t events)
+{
+	struct panel_launcher *launcher =
+		container_of(task, struct panel_launcher, tooltip_task);
+	uint64_t exp;
+	struct window *parent = launcher->panel->window;
+	const int offset_y = 27;
+
+	read(launcher->tooltip_fd, &exp, sizeof (uint64_t));
+
+	if (launcher->focused)
+		window_create_tooltip(parent, launcher->last_x,
+				launcher->last_y + offset_y, launcher->path);
+}
+
+#define TOOLTIP_TIMEOUT 500
+static int
+tooltip_timer_reset(struct panel_launcher *launcher)
+{
+	struct itimerspec its;
+
+	its.it_interval.tv_sec = 0;
+	its.it_interval.tv_nsec = 0;
+	its.it_value.tv_sec = TOOLTIP_TIMEOUT / 1000;
+	its.it_value.tv_nsec = (TOOLTIP_TIMEOUT % 1000) * 1000 * 1000;
+	if (timerfd_settime(launcher->tooltip_fd, 0, &its, NULL) < 0) {
+		fprintf(stderr, "could not set timerfd\n: %m");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int
+tooltip_timer_create(struct display *display, struct panel_launcher *launcher)
+{
+	/* FIXME: fd here is never closed anywhere; maybe we need a
+	 * panel_launcher_destroy for such. */
+	launcher->tooltip_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
+	if (launcher->tooltip_fd < 0) {
+		fprintf(stderr, "could not create timerfd\n: %m");
+		return -1;
+	}
+
+	launcher->tooltip_task.run = tooltip_func;
+	display_watch_fd(display, launcher->tooltip_fd, EPOLLIN,
+			 &launcher->tooltip_task);
+
+	tooltip_timer_reset(launcher);
+	return 0;
+}
+
+static int
+panel_launcher_motion_handler(struct widget *widget,
+		struct input *input, uint32_t time,
+		int32_t x, int32_t y, void *data)
+{
+	struct panel_launcher *launcher = data;
+
+	tooltip_timer_reset(launcher);
+	launcher->last_x = x;
+	launcher->last_y = y;
+
+	return POINTER_LEFT_PTR;
+}
+
+static void
 panel_button_handler(struct widget *widget,
 		     struct input *input, uint32_t time,
 		     int button, int state, void *data)
@@ -353,6 +428,10 @@ panel_add_launcher(struct panel *panel, const char *icon, const char *path)
 				    panel_launcher_button_handler);
 	widget_set_redraw_handler(launcher->widget,
 				  panel_launcher_redraw_handler);
+	widget_set_motion_handler(launcher->widget,
+				  panel_launcher_motion_handler);
+
+	tooltip_timer_create(window_get_display(panel->window), launcher);
 }
 
 enum {
-- 
1.7.9.5



More information about the wayland-devel mailing list