mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-11-07 13:29:55 -05:00
Introduce 'shell' object for moving and resizing surfaces in the compositor
This commit is contained in:
parent
a1f3f60bea
commit
83fc061c9c
8 changed files with 299 additions and 119 deletions
141
clients/window.c
141
clients/window.c
|
|
@ -52,6 +52,7 @@
|
|||
struct display {
|
||||
struct wl_display *display;
|
||||
struct wl_compositor *compositor;
|
||||
struct wl_shell *shell;
|
||||
struct wl_output *output;
|
||||
struct rectangle screen_allocation;
|
||||
EGLDisplay dpy;
|
||||
|
|
@ -71,12 +72,11 @@ struct window {
|
|||
struct display *display;
|
||||
struct wl_surface *surface;
|
||||
const char *title;
|
||||
struct rectangle allocation, saved_allocation, surface_allocation;
|
||||
struct rectangle allocation, saved_allocation, pending_allocation;
|
||||
int resize_edges;
|
||||
int redraw_scheduled;
|
||||
int minimum_width, minimum_height;
|
||||
int margin;
|
||||
int drag_x, drag_y;
|
||||
int state;
|
||||
int fullscreen;
|
||||
int decoration;
|
||||
struct input *grab_device;
|
||||
|
|
@ -195,16 +195,16 @@ window_attach_surface(struct window *window)
|
|||
visual = wl_display_get_premultiplied_argb_visual(window->display->display);
|
||||
wl_surface_attach(window->surface,
|
||||
name,
|
||||
window->surface_allocation.width,
|
||||
window->surface_allocation.height,
|
||||
window->allocation.width,
|
||||
window->allocation.height,
|
||||
stride,
|
||||
visual);
|
||||
|
||||
wl_surface_map(window->surface,
|
||||
window->surface_allocation.x - window->margin,
|
||||
window->surface_allocation.y - window->margin,
|
||||
window->surface_allocation.width,
|
||||
window->surface_allocation.height);
|
||||
window->allocation.x,
|
||||
window->allocation.y,
|
||||
window->allocation.width,
|
||||
window->allocation.height);
|
||||
|
||||
wl_compositor_commit(window->display->compositor, 0);
|
||||
}
|
||||
|
|
@ -229,7 +229,6 @@ window_draw_decorations(struct window *window)
|
|||
|
||||
window->cairo_surface =
|
||||
display_create_surface(window->display, &window->allocation);
|
||||
window->surface_allocation = window->allocation;
|
||||
width = window->allocation.width;
|
||||
height = window->allocation.height;
|
||||
|
||||
|
|
@ -274,7 +273,6 @@ window_draw_fullscreen(struct window *window)
|
|||
{
|
||||
window->cairo_surface =
|
||||
display_create_surface(window->display, &window->allocation);
|
||||
window->surface_allocation = window->allocation;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -315,61 +313,11 @@ window_handle_motion(void *data, struct wl_input_device *input_device,
|
|||
int32_t x, int32_t y, int32_t sx, int32_t sy)
|
||||
{
|
||||
struct input *input = data;
|
||||
struct window *window = input->pointer_focus;
|
||||
|
||||
input->x = x;
|
||||
input->y = y;
|
||||
input->sx = sx;
|
||||
input->sy = sy;
|
||||
|
||||
switch (window->state) {
|
||||
case WINDOW_MOVING:
|
||||
if (window->fullscreen)
|
||||
break;
|
||||
if (window->grab_device != input)
|
||||
break;
|
||||
window->allocation.x = window->drag_x + x;
|
||||
window->allocation.y = window->drag_y + y;
|
||||
wl_surface_map(window->surface,
|
||||
window->allocation.x - window->margin,
|
||||
window->allocation.y - window->margin,
|
||||
window->allocation.width,
|
||||
window->allocation.height);
|
||||
wl_compositor_commit(window->display->compositor, 1);
|
||||
break;
|
||||
|
||||
case WINDOW_RESIZING_TOP:
|
||||
case WINDOW_RESIZING_BOTTOM:
|
||||
case WINDOW_RESIZING_LEFT:
|
||||
case WINDOW_RESIZING_RIGHT:
|
||||
case WINDOW_RESIZING_TOP_LEFT:
|
||||
case WINDOW_RESIZING_TOP_RIGHT:
|
||||
case WINDOW_RESIZING_BOTTOM_LEFT:
|
||||
case WINDOW_RESIZING_BOTTOM_RIGHT:
|
||||
if (window->fullscreen)
|
||||
break;
|
||||
if (window->grab_device != input)
|
||||
break;
|
||||
if (window->state & WINDOW_RESIZING_LEFT) {
|
||||
window->allocation.x = x - window->drag_x + window->saved_allocation.x;
|
||||
window->allocation.width = window->drag_x - x + window->saved_allocation.width;
|
||||
}
|
||||
if (window->state & WINDOW_RESIZING_RIGHT)
|
||||
window->allocation.width = x - window->drag_x + window->saved_allocation.width;
|
||||
if (window->state & WINDOW_RESIZING_TOP) {
|
||||
window->allocation.y = y - window->drag_y + window->saved_allocation.y;
|
||||
window->allocation.height = window->drag_y - y + window->saved_allocation.height;
|
||||
}
|
||||
if (window->state & WINDOW_RESIZING_BOTTOM)
|
||||
window->allocation.height = y - window->drag_y + window->saved_allocation.height;
|
||||
|
||||
if (window->resize_handler)
|
||||
(*window->resize_handler)(window,
|
||||
window->user_data);
|
||||
else if (window->redraw_handler)
|
||||
window_schedule_redraw(window);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void window_handle_button(void *data, struct wl_input_device *input_device,
|
||||
|
|
@ -400,10 +348,8 @@ static void window_handle_button(void *data, struct wl_input_device *input_devic
|
|||
if (button == BTN_LEFT && state == 1) {
|
||||
switch (hlocation | vlocation) {
|
||||
case WINDOW_MOVING:
|
||||
window->drag_x = window->allocation.x - input->x;
|
||||
window->drag_y = window->allocation.y - input->y;
|
||||
window->state = WINDOW_MOVING;
|
||||
window->grab_device = input;
|
||||
wl_shell_move(window->display->shell,
|
||||
window->surface, input_device, time);
|
||||
break;
|
||||
case WINDOW_RESIZING_TOP:
|
||||
case WINDOW_RESIZING_BOTTOM:
|
||||
|
|
@ -413,19 +359,11 @@ static void window_handle_button(void *data, struct wl_input_device *input_devic
|
|||
case WINDOW_RESIZING_TOP_RIGHT:
|
||||
case WINDOW_RESIZING_BOTTOM_LEFT:
|
||||
case WINDOW_RESIZING_BOTTOM_RIGHT:
|
||||
window->drag_x = input->x;
|
||||
window->drag_y = input->y;
|
||||
window->saved_allocation = window->allocation;
|
||||
window->state = hlocation | vlocation;
|
||||
window->grab_device = input;
|
||||
break;
|
||||
default:
|
||||
window->state = WINDOW_STABLE;
|
||||
wl_shell_resize(window->display->shell,
|
||||
window->surface, input_device, time,
|
||||
hlocation | vlocation);
|
||||
break;
|
||||
}
|
||||
} else if (button == BTN_LEFT &&
|
||||
state == 0 && window->grab_device == input) {
|
||||
window->state = WINDOW_STABLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -519,6 +457,34 @@ static const struct wl_input_device_listener input_device_listener = {
|
|||
window_handle_keyboard_focus,
|
||||
};
|
||||
|
||||
static void
|
||||
handle_configure(void *data, struct wl_shell *shell,
|
||||
uint32_t time, uint32_t edges,
|
||||
struct wl_surface *surface,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height)
|
||||
{
|
||||
struct window *window = wl_surface_get_user_data(surface);
|
||||
|
||||
window->resize_edges = edges;
|
||||
window->pending_allocation.x = x;
|
||||
window->pending_allocation.y = y;
|
||||
window->pending_allocation.width = width;
|
||||
window->pending_allocation.height = height;
|
||||
|
||||
if (!(edges & 15))
|
||||
return;
|
||||
|
||||
if (window->resize_handler)
|
||||
(*window->resize_handler)(window,
|
||||
window->user_data);
|
||||
else if (window->redraw_handler)
|
||||
window_schedule_redraw(window);
|
||||
}
|
||||
|
||||
static const struct wl_shell_listener shell_listener = {
|
||||
handle_configure,
|
||||
};
|
||||
|
||||
void
|
||||
window_get_child_rectangle(struct window *window,
|
||||
struct rectangle *rectangle)
|
||||
|
|
@ -542,12 +508,14 @@ window_set_child_size(struct window *window,
|
|||
if (!window->fullscreen) {
|
||||
width = rectangle->width + 20 + window->margin * 2;
|
||||
height = rectangle->height + 60 + window->margin * 2;
|
||||
if (window->state & WINDOW_RESIZING_LEFT)
|
||||
window->allocation.x -=
|
||||
width - window->allocation.width;
|
||||
if (window->state & WINDOW_RESIZING_TOP)
|
||||
window->allocation.y -=
|
||||
height - window->allocation.height;
|
||||
|
||||
if (window->resize_edges & WINDOW_RESIZING_LEFT)
|
||||
window->allocation.x +=
|
||||
window->allocation.width - width;
|
||||
if (window->resize_edges & WINDOW_RESIZING_TOP)
|
||||
window->allocation.y +=
|
||||
window->allocation.height - height;
|
||||
|
||||
window->allocation.width = width;
|
||||
window->allocation.height = height;
|
||||
}
|
||||
|
|
@ -582,8 +550,13 @@ idle_redraw(void *data)
|
|||
{
|
||||
struct window *window = data;
|
||||
|
||||
if (window->resize_edges)
|
||||
window->allocation = window->pending_allocation;
|
||||
|
||||
window->redraw_handler(window, window->user_data);
|
||||
|
||||
window->redraw_scheduled = 0;
|
||||
window->resize_edges = 0;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -696,7 +669,6 @@ window_create(struct display *display, const char *title,
|
|||
window->allocation.height = height;
|
||||
window->saved_allocation = window->allocation;
|
||||
window->margin = 16;
|
||||
window->state = WINDOW_STABLE;
|
||||
window->decoration = 1;
|
||||
|
||||
wl_surface_set_user_data(window->surface, window);
|
||||
|
|
@ -809,6 +781,9 @@ display_handle_global(struct wl_display *display,
|
|||
wl_output_add_listener(d->output, &output_listener, d);
|
||||
} else if (wl_object_implements(object, "input_device", 1)) {
|
||||
display_add_input(d, object);
|
||||
} else if (wl_object_implements(object, "shell", 1)) {
|
||||
d->shell = (struct wl_shell *) object;
|
||||
wl_shell_add_listener(d->shell, &shell_listener, d);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue