diff --git a/clients/dnd.c b/clients/dnd.c index 3b54dec5..42233af0 100644 --- a/clients/dnd.c +++ b/clients/dnd.c @@ -628,7 +628,6 @@ static struct dnd * dnd_create(struct display *display) { struct dnd *dnd; - gchar *title; int i, x, y; int32_t width, height; @@ -637,9 +636,9 @@ dnd_create(struct display *display) return dnd; memset(dnd, 0, sizeof *dnd); - title = g_strdup_printf("Wayland Drag and Drop Demo"); + dnd->window = window_create(display, 400, 400); + window_set_title(dnd->window, "Wayland Drag and Drop Demo"); - dnd->window = window_create(display, title, 500, 400); dnd->display = display; dnd->key = 100; diff --git a/clients/flower.c b/clients/flower.c index de7c1d42..b5caa324 100644 --- a/clients/flower.c +++ b/clients/flower.c @@ -141,9 +141,9 @@ int main(int argc, char *argv[]) flower.width = 200; flower.height = 200; flower.display = d; - flower.window = window_create(d, "flower", - flower.width, flower.height); + flower.window = window_create(d, flower.width, flower.height); + window_set_title(flower.window, "flower"); window_set_decoration(flower.window, 0); window_draw(flower.window); s = window_get_surface(flower.window); diff --git a/clients/gears.c b/clients/gears.c index f2eae9c9..25e1fcbc 100644 --- a/clients/gears.c +++ b/clients/gears.c @@ -358,7 +358,8 @@ gears_create(struct display *display) gears = malloc(sizeof *gears); memset(gears, 0, sizeof *gears); gears->d = display; - gears->window = window_create(display, "Wayland Gears", width, height); + gears->window = window_create(display, width, height); + window_set_title(gears->window, "Wayland Gears"); gears->display = display_get_egl_display(gears->d); if (gears->display == NULL) diff --git a/clients/image.c b/clients/image.c index 891bd8a7..b528ed69 100644 --- a/clients/image.c +++ b/clients/image.c @@ -216,7 +216,8 @@ image_create(struct display *display, uint32_t key, const char *filename) image->filename = g_strdup(filename); - image->window = window_create(display, title, 500, 400); + image->window = window_create(display, 500, 400); + window_set_title(image->window, title); image->display = display; /* FIXME: Window uses key 1 for moves, need some kind of diff --git a/clients/resizor.c b/clients/resizor.c index 46d9cbf7..dbd07528 100644 --- a/clients/resizor.c +++ b/clients/resizor.c @@ -38,6 +38,7 @@ struct resizor { struct display *display; struct window *window; + struct window *menu; int32_t width; struct { @@ -148,6 +149,38 @@ key_handler(struct window *window, struct input *input, uint32_t time, } } +static void +show_menu(struct resizor *resizor, struct input *input) +{ + cairo_surface_t *surface; + int32_t x, y, width = 200, height = 200; + + input_get_position(input, &x, &y); + resizor->menu = window_create_transient(resizor->display, + resizor->window, + x - 10, y - 10, width, height); + + window_draw(resizor->menu); + window_flush(resizor->menu); +} + +static void +button_handler(struct window *window, + struct input *input, uint32_t time, + int button, int state, void *data) +{ + struct resizor *resizor = data; + + switch (button) { + case 274: + if (state) + show_menu(resizor, input); + else + window_destroy(resizor->menu); + break; + } +} + static struct resizor * resizor_create(struct display *display) { @@ -159,7 +192,8 @@ resizor_create(struct display *display) return resizor; memset(resizor, 0, sizeof *resizor); - resizor->window = window_create(display, "Wayland Resizor", 500, 400); + resizor->window = window_create(display, 500, 400); + window_set_title(resizor->window, "Wayland Resizor"); resizor->display = display; window_set_key_handler(resizor->window, key_handler); @@ -175,6 +209,7 @@ resizor_create(struct display *display) height = resizor->height.current + 0.5; window_set_child_size(resizor->window, resizor->width, height); + window_set_button_handler(resizor->window, button_handler); resizor_draw(resizor); diff --git a/clients/smoke.c b/clients/smoke.c index 7052cb44..c3e81319 100644 --- a/clients/smoke.c +++ b/clients/smoke.c @@ -277,7 +277,8 @@ int main(int argc, char *argv[]) smoke.width = 200; smoke.height = 200; smoke.display = d; - smoke.window = window_create(d, "smoke", smoke.width, smoke.height); + smoke.window = window_create(d, smoke.width, smoke.height); + window_set_title(smoke.window, "smoke"); window_set_buffer_type(smoke.window, WINDOW_BUFFER_TYPE_SHM); clock_gettime(CLOCK_MONOTONIC, &ts); diff --git a/clients/terminal.c b/clients/terminal.c index 92549071..1e015c15 100644 --- a/clients/terminal.c +++ b/clients/terminal.c @@ -2213,8 +2213,8 @@ terminal_create(struct display *display, int fullscreen) terminal_init(terminal); terminal->margin_top = 0; terminal->margin_bottom = -1; - terminal->window = window_create(display, "Wayland Terminal", - 500, 400); + terminal->window = window_create(display, 500, 400); + window_set_title(terminal->window, "Wayland Terminal"); init_state_machine(&terminal->state_machine); init_color_table(terminal); diff --git a/clients/view.c b/clients/view.c index db94dcaf..9512dc49 100644 --- a/clients/view.c +++ b/clients/view.c @@ -171,7 +171,8 @@ view_create(struct display *display, uint32_t key, const char *filename) view->filename = g_strdup(filename); - view->window = window_create(display, title, 500, 400); + view->window = window_create(display, 500, 400); + window_set_title(view->window, title); view->display = display; /* FIXME: Window uses key 1 for moves, need some kind of diff --git a/clients/window.c b/clients/window.c index e2e59d10..a42ade0c 100644 --- a/clients/window.c +++ b/clients/window.c @@ -84,9 +84,11 @@ struct display { struct window { struct display *display; + struct window *parent; struct wl_surface *surface; const char *title; struct rectangle allocation, saved_allocation, server_allocation; + int x, y; int resize_edges; int redraw_scheduled; int minimum_width, minimum_height; @@ -598,7 +600,12 @@ window_attach_surface(struct window *window) wl_display_sync_callback(display->display, free_surface, window); if (!window->mapped) { - wl_surface_map_toplevel(window->surface); + if (!window->parent) + wl_surface_map_toplevel(window->surface); + else + wl_surface_map_transient(window->surface, + window->parent->surface, + window->x, window->y, 0); window->mapped = 1; } @@ -650,6 +657,28 @@ window_create_surface(struct window *window) cairo_surface_destroy(surface); } +static void +window_draw_menu(struct window *window) +{ + cairo_t *cr; + int width, height, r = 5; + + window_create_surface(window); + + cr = cairo_create(window->cairo_surface); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); + cairo_paint(cr); + + width = window->allocation.width; + height = window->allocation.height; + rounded_rect(cr, r, r, width - r, height - r, r); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_rgba(cr, 1.0, 1.0, 0.0, 0.5); + cairo_fill(cr); + cairo_destroy(cr); +} + static void window_draw_decorations(struct window *window) { @@ -706,6 +735,14 @@ window_draw_decorations(struct window *window) cairo_device_flush (window->display->device); } +void +window_destroy(struct window *window) +{ + wl_surface_destroy(window->surface); + wl_list_remove(&window->link); + free(window); +} + void display_flush_cairo_device(struct display *display) { @@ -715,7 +752,9 @@ display_flush_cairo_device(struct display *display) void window_draw(struct window *window) { - if (window->fullscreen || !window->decoration) + if (window->parent) + window_draw_menu(window); + else if (window->fullscreen || !window->decoration) window_create_surface(window); else window_draw_decorations(window); @@ -1202,9 +1241,9 @@ window_damage(struct window *window, int32_t x, int32_t y, wl_surface_damage(window->surface, x, y, width, height); } -struct window * -window_create(struct display *display, const char *title, - int32_t width, int32_t height) +static struct window * +window_create_internal(struct display *display, struct window *parent, + int32_t width, int32_t height) { struct window *window; @@ -1214,7 +1253,7 @@ window_create(struct display *display, const char *title, memset(window, 0, sizeof *window); window->display = display; - window->title = strdup(title); + window->parent = parent; window->surface = wl_compositor_create_surface(display->compositor); window->allocation.x = 0; window->allocation.y = 0; @@ -1235,6 +1274,41 @@ window_create(struct display *display, const char *title, return window; } +void +window_set_title(struct window *window, const char *title) +{ + window->title = strdup(title); +} + +struct window * +window_create(struct display *display, int32_t width, int32_t height) +{ + struct window *window; + + window = window_create_internal(display, NULL, width, height); + if (!window) + return NULL; + + return window; +} + +struct window * +window_create_transient(struct display *display, struct window *parent, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + struct window *window; + + window = window_create_internal(parent->display, + parent, width, height); + if (!window) + return NULL; + + window->x = x; + window->y = y; + + return window; +} + void window_set_buffer_type(struct window *window, enum window_buffer_type type) { diff --git a/clients/window.h b/clients/window.h index 27811f3f..14aeab45 100644 --- a/clients/window.h +++ b/clients/window.h @@ -127,8 +127,16 @@ typedef void (*display_global_handler_t)(struct display *display, uint32_t version); struct window * -window_create(struct display *display, const char *title, - int32_t width, int32_t height); +window_create(struct display *display, int32_t width, int32_t height); +struct window * +window_create_transient(struct display *display, struct window *parent, + int32_t x, int32_t y, int32_t width, int32_t height); + +void +window_destroy(struct window *window); + +void +window_set_title(struct window *window, const char *title); void window_move(struct window *window, struct input *input, uint32_t time);