struct panel {
struct window *window;
- struct wl_list item_list;
- struct panel_item *focus;
};
struct panel_item {
- struct wl_list link;
+ struct item *item;
+ struct panel *panel;
cairo_surface_t *icon;
- int x, y, width, height;
int pressed;
const char *path;
};
}
}
-static struct panel_item *
-panel_find_item(struct panel *panel, int32_t x, int32_t y)
-{
- struct panel_item *item;
-
- wl_list_for_each(item, &panel->item_list, link) {
- if (item->x <= x && x < item->x + item->width &&
- item->y <= y && y < item->y + item->height) {
- return item;
- }
- }
-
- return NULL;
-}
-
static void
-panel_draw_item(struct panel *panel, cairo_t *cr, struct panel_item *item)
+panel_draw_item(struct item *item, void *data)
{
- int x, y;
-
- if (item->pressed) {
- x = item->x + 1;
- y = item->y + 1;
- } else {
- x = item->x;
- y = item->y;
+ cairo_t *cr = data;
+ struct panel_item *pi;
+ int x, y, width, height;
+ double dx, dy;
+
+ pi = item_get_user_data(item);
+ width = cairo_image_surface_get_width(pi->icon);
+ height = cairo_image_surface_get_height(pi->icon);
+ x = 0;
+ y = -height / 2;
+ if (pi->pressed) {
+ x++;
+ y++;
}
- cairo_set_source_surface(cr, item->icon, x, y);
+ dx = x;
+ dy = y;
+ cairo_user_to_device(cr, &dx, &dy);
+ item_set_allocation(item, dx, dy, width, height);
+
+ cairo_set_source_surface(cr, pi->icon, x, y);
cairo_paint(cr);
- if (panel->focus == item) {
+ if (window_get_focus_item(pi->panel->window) == item) {
cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
- cairo_mask_surface(cr, item->icon, x, y);
+ cairo_mask_surface(cr, pi->icon, x, y);
}
+
+ cairo_translate(cr, width + 10, 0);
}
static void
{
cairo_surface_t *surface;
cairo_t *cr;
- struct panel *panel = window_get_user_data(window);
- struct panel_item *item;
window_draw(window);
surface = window_get_surface(window);
cairo_paint(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
- wl_list_for_each(item, &panel->item_list, link)
- panel_draw_item(panel, cr, item);
+ cairo_translate(cr, 10, 32 / 2);
+ window_for_each_item(window, panel_draw_item, cr);
cairo_destroy(cr);
cairo_surface_destroy(surface);
}
static void
-panel_set_focus(struct panel *panel, struct panel_item *focus)
+panel_item_focus_handler(struct window *window,
+ struct item *focus, void *data)
{
- if (focus == panel->focus)
- return;
-
- panel->focus = focus;
- window_schedule_redraw(panel->window);
-}
-
-static int
-panel_enter_handler(struct window *window,
- struct input *input, uint32_t time,
- int32_t x, int32_t y, void *data)
-{
- struct panel *panel = data;
- struct panel_item *item;
-
- item = panel_find_item(panel, x, y);
- panel_set_focus(panel, item);
-
- return POINTER_LEFT_PTR;
-}
-
-static void
-panel_leave_handler(struct window *window,
- struct input *input, uint32_t time, void *data)
-{
- struct panel *panel = data;
-
- panel_set_focus(panel, NULL);
-}
-
-static int
-panel_motion_handler(struct window *window,
- struct input *input, uint32_t time,
- int32_t x, int32_t y,
- int32_t sx, int32_t sy, void *data)
-{
- struct panel *panel = data;
- struct panel_item *item;
-
- if (panel->focus && panel->focus->pressed)
- return POINTER_LEFT_PTR;
-
- item = panel_find_item(panel, sx, sy);
- panel_set_focus(panel, item);
-
- return POINTER_LEFT_PTR;
+ window_schedule_redraw(window);
}
static void
int button, int state, void *data)
{
struct panel *panel = data;
- struct panel_item *item;
- int32_t x, y;
+ struct panel_item *pi;
+ struct item *focus;
- if (panel->focus && button == BTN_LEFT) {
- panel->focus->pressed = state;
+ focus = window_get_focus_item(panel->window);
+ if (focus && button == BTN_LEFT) {
+ pi = item_get_user_data(focus);
window_schedule_redraw(panel->window);
-
- if (state == 0) {
- panel_activate_item(panel, panel->focus);
-
- input_get_position(input, &x, &y);
- item = panel_find_item(panel, x, y);
- panel_set_focus(panel, item);
- }
+ if (state == 0)
+ panel_activate_item(panel, pi);
}
}
panel = malloc(sizeof *panel);
memset(panel, 0, sizeof *panel);
- wl_list_init(&panel->item_list);
panel->window = window_create(display, 0, 0);
window_set_redraw_handler(panel->window, panel_redraw_handler);
window_set_custom(panel->window);
window_set_user_data(panel->window, panel);
- window_set_enter_handler(panel->window, panel_enter_handler);
- window_set_leave_handler(panel->window, panel_leave_handler);
- window_set_motion_handler(panel->window, panel_motion_handler);
window_set_button_handler(panel->window, panel_button_handler);
+ window_set_item_focus_handler(panel->window, panel_item_focus_handler);
return panel;
}
memset(item, 0, sizeof *item);
item->icon = cairo_image_surface_create_from_png(icon);
item->path = strdup(path);
- wl_list_insert(panel->item_list.prev, &item->link);
-
- item->width = cairo_image_surface_get_width(item->icon);
- item->height = cairo_image_surface_get_height(item->icon);
-}
-
-static void
-panel_allocate(struct panel *panel, int width, int height)
-{
- struct panel_item *item;
- int x;
-
- window_set_child_size(panel->window, width, height);
- window_schedule_redraw(panel->window);
-
- x = 10;
- wl_list_for_each(item, &panel->item_list, link) {
- item->x = x;
- item->y = (height - item->height) / 2;
- x += item->width + 10;
- }
+ item->panel = panel;
+ window_add_item(panel->window, item);
}
static void
struct desktop *desktop = data;
if (surface == window_get_wl_surface(desktop->panel->window)) {
- panel_allocate(desktop->panel, width, 32);
+ window_set_child_size(desktop->panel->window, width, 32);
+ window_schedule_redraw(desktop->panel->window);
} else if (surface == window_get_wl_surface(desktop->background)) {
background_draw(desktop->background,
width, height, desktop->background_path);
window_motion_handler_t motion_handler;
window_enter_handler_t enter_handler;
window_leave_handler_t leave_handler;
+ window_item_focus_handler_t item_focus_handler;
+
+ struct wl_list item_list;
+ struct item *focus_item;
+ uint32_t item_grab_button;
void *user_data;
struct wl_list link;
};
+struct item {
+ struct wl_list link;
+ struct rectangle allocation;
+ void *user_data;
+};
+
struct input {
struct display *display;
struct wl_input_device *input_device;
free(window);
}
+static struct item *
+window_find_item(struct window *window, int32_t x, int32_t y)
+{
+ struct item *item;
+
+ wl_list_for_each(item, &window->item_list, link) {
+ if (item->allocation.x <= x &&
+ x < item->allocation.x + item->allocation.width &&
+ item->allocation.y <= y &&
+ y < item->allocation.y + item->allocation.height) {
+ return item;
+ }
+ }
+
+ return NULL;
+}
+
+struct item *
+window_add_item(struct window *window, void *data)
+{
+ struct item *item;
+
+ item = malloc(sizeof *item);
+ memset(item, 0, sizeof *item);
+ item->user_data = data;
+ wl_list_insert(window->item_list.prev, &item->link);
+
+ return item;
+}
+
+void
+window_for_each_item(struct window *window, item_func_t func, void *data)
+{
+ struct item *item;
+
+ wl_list_for_each(item, &window->item_list, link)
+ func(item, data);
+}
+
+struct item *
+window_get_focus_item(struct window *window)
+{
+ return window->focus_item;
+}
+
+void
+item_get_allocation(struct item *item, struct rectangle *allocation)
+{
+ *allocation = item->allocation;
+}
+
+void
+item_set_allocation(struct item *item,
+ int32_t x, int32_t y, int32_t width, int32_t height)
+{
+ item->allocation.x = x;
+ item->allocation.y = y;
+ item->allocation.width = width;
+ item->allocation.height = height;
+}
+
+void *
+item_get_user_data(struct item *item)
+{
+ return item->user_data;
+}
+
void
display_flush_cairo_device(struct display *display)
{
}
static void
+window_set_focus_item(struct window *window, struct item *focus)
+{
+ void *data;
+
+ if (focus == window->focus_item)
+ return;
+
+ window->focus_item = focus;
+ data = focus ? focus->user_data : NULL;
+ if (window->item_focus_handler)
+ window->item_focus_handler(window, focus, data);
+}
+
+static void
window_handle_motion(void *data, struct wl_input_device *input_device,
uint32_t time,
int32_t x, int32_t y, int32_t sx, int32_t sy)
{
struct input *input = data;
struct window *window = input->pointer_focus;
+ struct item *item;
int pointer = POINTER_LEFT_PTR;
input->x = x;
input->sx = sx;
input->sy = sy;
+ if (!window->focus_item || !window->item_grab_button) {
+ item = window_find_item(window, sx, sy);
+ window_set_focus_item(window, item);
+ }
+
if (window->motion_handler)
pointer = (*window->motion_handler)(window, input, time,
x, y, sx, sy,
{
struct input *input = data;
struct window *window = input->pointer_focus;
+ struct item *item;
int location;
+ if (window->focus_item && window->item_grab_button == 0 && state)
+ window->item_grab_button = button;
+
location = get_pointer_location(window, input->sx, input->sy);
if (button == BTN_LEFT && state == 1) {
button, state,
window->user_data);
}
+
+ if (window->focus_item &&
+ window->item_grab_button == button && !state) {
+ window->item_grab_button = 0;
+ item = window_find_item(window, input->sx, input->sy);
+ window_set_focus_item(window, item);
+ }
}
static void
{
struct input *input = data;
struct window *window;
+ struct item *item;
int pointer;
window = input->pointer_focus;
if (window && window->surface != surface) {
+ window_set_focus_item(window, NULL);
+
if (window->leave_handler)
window->leave_handler(window, input,
time, window->user_data);
time, sx, sy,
window->user_data);
- set_pointer_image(input, time, pointer);
+ item = window_find_item(window, x, y);
+ window_set_focus_item(window, item);
+ set_pointer_image(input, time, pointer);
}
}
}
void
+window_set_item_focus_handler(struct window *window,
+ window_item_focus_handler_t handler)
+{
+ window->item_focus_handler = handler;
+}
+
+void
window_set_transparent(struct window *window, int transparent)
{
window->transparent = transparent;
window->margin = 16;
window->decoration = 1;
window->transparent = 1;
+ wl_list_init(&window->item_list);
if (display->dpy)
#ifdef HAVE_CAIRO_EGL
#include <cairo.h>
struct window;
+struct item;
+struct display;
+struct input;
struct task {
void (*run)(struct task *task, uint32_t events);
int32_t height;
};
-struct display;
-struct input;
-
struct display *
display_create(int *argc, char **argv[], const GOptionEntry *option_entries);
int32_t x, int32_t y,
int32_t sx, int32_t sy, void *data);
+typedef void (*window_item_focus_handler_t)(struct window *window,
+ struct item *focus, void *data);
+
struct window *
window_create(struct display *display, int32_t width, int32_t height);
struct window *
void
window_destroy(struct window *window);
+struct item *
+window_add_item(struct window *window, void *data);
+
+typedef void (*item_func_t)(struct item *item, void *data);
+
+void
+window_for_each_item(struct window *window, item_func_t func, void *data);
+
+struct item *
+window_get_focus_item(struct window *window);
+
void
window_move(struct window *window, struct input *input, uint32_t time);
window_keyboard_focus_handler_t handler);
void
+window_set_item_focus_handler(struct window *window,
+ window_item_focus_handler_t handler);
+
+void
window_set_title(struct window *window, const char *title);
const char *
struct input *input, uint32_t time);
void
+item_get_allocation(struct item *item, struct rectangle *allocation);
+
+void
+item_set_allocation(struct item *item,
+ int32_t x, int32_t y, int32_t width, int32_t height);
+
+void *
+item_get_user_data(struct item *item);
+
+void
input_get_position(struct input *input, int32_t *x, int32_t *y);
uint32_t