#include <assert.h>
#include <signal.h>
#include <math.h>
+#include <sys/types.h>
#include <wayland-server.h>
#include "compositor.h"
#include "desktop-shell-server-protocol.h"
#include "../shared/config-parser.h"
+#include "log.h"
-struct shell_surface;
+enum animation_type {
+ ANIMATION_NONE,
-struct wl_shell {
+ ANIMATION_ZOOM,
+ ANIMATION_FADE
+};
+
+struct desktop_shell {
struct weston_compositor *compositor;
- struct weston_shell shell;
+
+ struct wl_listener lock_listener;
+ struct wl_listener unlock_listener;
+ struct wl_listener destroy_listener;
struct weston_layer fullscreen_layer;
struct weston_layer panel_layer;
struct weston_layer background_layer;
struct weston_layer lock_layer;
+ struct wl_listener pointer_focus_listener;
+ struct weston_surface *busy_surface;
+
struct {
struct weston_process process;
struct wl_client *client;
struct weston_process process;
} screensaver;
+ uint32_t binding_modifier;
+ enum animation_type win_animation_type;
struct weston_surface *debug_repaint_surface;
};
SHELL_SURFACE_POPUP
};
+struct ping_timer {
+ struct wl_event_source *source;
+ uint32_t serial;
+};
+
struct shell_surface {
struct wl_resource resource;
struct weston_surface *surface;
struct wl_listener surface_destroy_listener;
struct shell_surface *parent;
+ struct desktop_shell *shell;
- enum shell_surface_type type;
+ enum shell_surface_type type, next_type;
+ char *title, *class;
int32_t saved_x, saved_y;
bool saved_position_valid;
+ bool saved_rotation_valid;
+ int unresponsive;
struct {
struct weston_transform transform;
struct {
struct wl_pointer_grab grab;
- uint32_t time;
int32_t x, y;
struct weston_transform parent_transform;
int32_t initial_up;
+ struct wl_seat *seat;
+ uint32_t serial;
} popup;
struct {
+ int32_t x, y;
+ uint32_t flags;
+ } transient;
+
+ struct {
enum wl_shell_surface_fullscreen_method type;
struct weston_transform transform; /* matrix from x, y */
uint32_t framerate;
struct weston_surface *black_surface;
} fullscreen;
+ struct ping_timer *ping_timer;
+
struct weston_output *fullscreen_output;
struct weston_output *output;
struct wl_list link;
+
+ const struct weston_shell_client *client;
};
-struct weston_move_grab {
+struct shell_grab {
struct wl_pointer_grab grab;
- struct weston_surface *surface;
- int32_t dx, dy;
+ struct shell_surface *shsurf;
+ struct wl_listener shsurf_destroy_listener;
+};
+
+struct weston_move_grab {
+ struct shell_grab base;
+ wl_fixed_t dx, dy;
};
struct rotate_grab {
- struct wl_pointer_grab grab;
- struct shell_surface *surface;
+ struct shell_grab base;
struct weston_matrix rotation;
struct {
- int32_t x;
- int32_t y;
+ GLfloat x;
+ GLfloat y;
} center;
};
+static struct shell_surface *
+get_shell_surface(struct weston_surface *surface);
+
+static struct desktop_shell *
+shell_surface_get_shell(struct shell_surface *shsurf);
+
+static bool
+shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
+{
+ struct desktop_shell *shell;
+ struct weston_surface *top_fs_es;
+
+ shell = shell_surface_get_shell(shsurf);
+
+ if (wl_list_empty(&shell->fullscreen_layer.surface_list))
+ return false;
+
+ top_fs_es = container_of(shell->fullscreen_layer.surface_list.next,
+ struct weston_surface,
+ layer_link);
+ return (shsurf == get_shell_surface(top_fs_es));
+}
+
+static void
+destroy_shell_grab_shsurf(struct wl_listener *listener, void *data)
+{
+ struct shell_grab *grab;
+
+ grab = container_of(listener, struct shell_grab,
+ shsurf_destroy_listener);
+
+ grab->shsurf = NULL;
+}
+
+static void
+shell_grab_init(struct shell_grab *grab,
+ const struct wl_pointer_grab_interface *interface,
+ struct shell_surface *shsurf)
+{
+ grab->grab.interface = interface;
+ grab->shsurf = shsurf;
+ grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
+ wl_signal_add(&shsurf->resource.destroy_signal,
+ &grab->shsurf_destroy_listener);
+
+}
+
+static void
+shell_grab_finish(struct shell_grab *grab)
+{
+ if (grab->shsurf)
+ wl_list_remove(&grab->shsurf_destroy_listener.link);
+}
+
static void
center_on_output(struct weston_surface *surface,
struct weston_output *output);
+static enum weston_keyboard_modifier
+get_modifier(char *modifier)
+{
+ if (!modifier)
+ return MODIFIER_SUPER;
+
+ if (!strcmp("ctrl", modifier))
+ return MODIFIER_CTRL;
+ else if (!strcmp("alt", modifier))
+ return MODIFIER_ALT;
+ else if (!strcmp("super", modifier))
+ return MODIFIER_SUPER;
+ else
+ return MODIFIER_SUPER;
+}
+
+static enum animation_type
+get_animation_type(char *animation)
+{
+ if (!animation)
+ return ANIMATION_NONE;
+
+ if (!strcmp("zoom", animation))
+ return ANIMATION_ZOOM;
+ else if (!strcmp("fade", animation))
+ return ANIMATION_FADE;
+ else
+ return ANIMATION_NONE;
+}
+
static void
-shell_configuration(struct wl_shell *shell)
+shell_configuration(struct desktop_shell *shell)
{
char *config_file;
char *path = NULL;
int duration = 60;
+ char *modifier = NULL;
+ char *win_animation = NULL;
+
+ struct config_key shell_keys[] = {
+ { "binding-modifier", CONFIG_KEY_STRING, &modifier },
+ { "animation", CONFIG_KEY_STRING, &win_animation},
+ };
struct config_key saver_keys[] = {
{ "path", CONFIG_KEY_STRING, &path },
};
struct config_section cs[] = {
+ { "shell", shell_keys, ARRAY_LENGTH(shell_keys), NULL },
{ "screensaver", saver_keys, ARRAY_LENGTH(saver_keys), NULL },
};
- config_file = config_file_path("weston-desktop-shell.ini");
+ config_file = config_file_path("weston.ini");
parse_config_file(config_file, cs, ARRAY_LENGTH(cs), shell);
free(config_file);
shell->screensaver.path = path;
shell->screensaver.duration = duration;
+ shell->binding_modifier = get_modifier(modifier);
+ shell->win_animation_type = get_animation_type(win_animation);
}
static void
-noop_grab_focus(struct wl_pointer_grab *grab, uint32_t time,
- struct wl_surface *surface, int32_t x, int32_t y)
+noop_grab_focus(struct wl_pointer_grab *grab,
+ struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
{
grab->focus = NULL;
}
static void
move_grab_motion(struct wl_pointer_grab *grab,
- uint32_t time, int32_t x, int32_t y)
+ uint32_t time, wl_fixed_t x, wl_fixed_t y)
{
struct weston_move_grab *move = (struct weston_move_grab *) grab;
- struct wl_input_device *device = grab->input_device;
- struct weston_surface *es = move->surface;
+ struct wl_pointer *pointer = grab->pointer;
+ struct shell_surface *shsurf = move->base.shsurf;
+ struct weston_surface *es;
+ int dx = wl_fixed_to_int(pointer->x + move->dx);
+ int dy = wl_fixed_to_int(pointer->y + move->dy);
- weston_surface_configure(es,
- device->x + move->dx,
- device->y + move->dy,
+ if (!shsurf)
+ return;
+
+ es = shsurf->surface;
+
+ weston_surface_configure(es, dx, dy,
es->geometry.width, es->geometry.height);
}
static void
move_grab_button(struct wl_pointer_grab *grab,
- uint32_t time, int32_t button, int32_t state)
+ uint32_t time, uint32_t button, uint32_t state_w)
{
- struct wl_input_device *device = grab->input_device;
+ struct shell_grab *shell_grab = container_of(grab, struct shell_grab,
+ grab);
+ struct wl_pointer *pointer = grab->pointer;
+ enum wl_pointer_button_state state = state_w;
- if (device->button_count == 0 && state == 0) {
- wl_input_device_end_pointer_grab(device, time);
+ if (pointer->button_count == 0 &&
+ state == WL_POINTER_BUTTON_STATE_RELEASED) {
+ shell_grab_finish(shell_grab);
+ wl_pointer_end_grab(pointer);
free(grab);
}
}
move_grab_button,
};
+static void
+busy_cursor_grab_focus(struct wl_pointer_grab *base,
+ struct wl_surface *surface, int32_t x, int32_t y)
+{
+ struct shell_grab *grab = (struct shell_grab *) base;
+ struct wl_pointer *pointer = base->pointer;
+
+ if (grab->grab.focus != surface) {
+ shell_grab_finish(grab);
+ wl_pointer_end_grab(pointer);
+ free(grab);
+ }
+}
+
+static void
+busy_cursor_grab_motion(struct wl_pointer_grab *grab,
+ uint32_t time, int32_t x, int32_t y)
+{
+}
+
+static void
+busy_cursor_grab_button(struct wl_pointer_grab *grab,
+ uint32_t time, uint32_t button, uint32_t state)
+{
+}
+
+static const struct wl_pointer_grab_interface busy_cursor_grab_interface = {
+ busy_cursor_grab_focus,
+ busy_cursor_grab_motion,
+ busy_cursor_grab_button,
+};
+
+static void
+set_busy_cursor(struct shell_surface *shsurf, struct wl_pointer *pointer)
+{
+ struct shell_grab *grab;
+ struct desktop_shell *shell = shsurf->shell;
+ struct weston_seat *seat = (struct weston_seat *) pointer->seat;
+ struct weston_surface *sprite;
+
+ grab = malloc(sizeof *grab);
+ if (!grab)
+ return;
+
+ shell_grab_init(grab, &busy_cursor_grab_interface, shsurf);
+ grab->grab.focus = &shsurf->surface->surface;
+ wl_pointer_start_grab(pointer, &grab->grab);
+ wl_pointer_set_focus(pointer, &shell->busy_surface->surface, 0, 0);
+
+ sprite = (struct weston_surface *) seat->sprite;
+ shell->busy_surface->output = sprite->output;
+}
+
+static void
+end_busy_cursor(struct shell_surface *shsurf, struct wl_pointer *pointer)
+{
+ struct shell_grab *grab = (struct shell_grab *) pointer->grab;
+
+ if (grab->grab.interface == &busy_cursor_grab_interface) {
+ shell_grab_finish(grab);
+ wl_pointer_end_grab(pointer);
+ free(grab);
+ }
+}
+
+static void
+ping_timer_destroy(struct shell_surface *shsurf)
+{
+ if (!shsurf || !shsurf->ping_timer)
+ return;
+
+ if (shsurf->ping_timer->source)
+ wl_event_source_remove(shsurf->ping_timer->source);
+
+ free(shsurf->ping_timer);
+ shsurf->ping_timer = NULL;
+}
+
static int
-weston_surface_move(struct weston_surface *es,
- struct weston_input_device *wd, uint32_t time)
+ping_timeout_handler(void *data)
+{
+ struct shell_surface *shsurf = data;
+ struct weston_seat *seat;
+
+ /* Client is not responding */
+ shsurf->unresponsive = 1;
+
+ wl_list_for_each(seat, &shsurf->surface->compositor->seat_list, link)
+ if (seat->seat.pointer->focus == &shsurf->surface->surface)
+ set_busy_cursor(shsurf, seat->seat.pointer);
+
+ return 1;
+}
+
+static void
+ping_handler(struct weston_surface *surface, uint32_t serial)
+{
+ struct shell_surface *shsurf = get_shell_surface(surface);
+ struct wl_event_loop *loop;
+ int ping_timeout = 200;
+
+ if (!shsurf)
+ return;
+ if (!shsurf->resource.client)
+ return;
+
+ if (!shsurf->ping_timer) {
+ shsurf->ping_timer = malloc(sizeof *shsurf->ping_timer);
+ if (!shsurf->ping_timer)
+ return;
+
+ shsurf->ping_timer->serial = serial;
+ loop = wl_display_get_event_loop(surface->compositor->wl_display);
+ shsurf->ping_timer->source =
+ wl_event_loop_add_timer(loop, ping_timeout_handler, shsurf);
+ wl_event_source_timer_update(shsurf->ping_timer->source, ping_timeout);
+
+ wl_shell_surface_send_ping(&shsurf->resource, serial);
+ }
+}
+
+static void
+handle_pointer_focus(struct wl_listener *listener, void *data)
+{
+ struct wl_pointer *pointer = data;
+ struct weston_surface *surface =
+ (struct weston_surface *) pointer->focus;
+ struct weston_compositor *compositor;
+ struct shell_surface *shsurf;
+ uint32_t serial;
+
+ if (!surface)
+ return;
+
+ compositor = surface->compositor;
+ shsurf = get_shell_surface(surface);
+
+ if (shsurf && shsurf->unresponsive) {
+ set_busy_cursor(shsurf, pointer);
+ } else {
+ serial = wl_display_next_serial(compositor->wl_display);
+ ping_handler(surface, serial);
+ }
+}
+
+static void
+shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
+ uint32_t serial)
+{
+ struct shell_surface *shsurf = resource->data;
+ struct desktop_shell *shell = shsurf->shell;
+ struct weston_seat *seat;
+ struct weston_compositor *ec = shsurf->surface->compositor;
+ struct wl_pointer *pointer;
+ int was_unresponsive;
+
+ if (shsurf->ping_timer->serial == serial) {
+ was_unresponsive = shsurf->unresponsive;
+ shsurf->unresponsive = 0;
+ if (was_unresponsive) {
+ /* Received pong from previously unresponsive client */
+ wl_list_for_each(seat, &ec->seat_list, link) {
+ pointer = seat->seat.pointer;
+ if (pointer->focus ==
+ &shell->busy_surface->surface &&
+ pointer->current ==
+ &shsurf->surface->surface)
+ end_busy_cursor(shsurf, pointer);
+ }
+ }
+ ping_timer_destroy(shsurf);
+ }
+}
+
+static void
+shell_surface_set_title(struct wl_client *client,
+ struct wl_resource *resource, const char *title)
+{
+ struct shell_surface *shsurf = resource->data;
+
+ free(shsurf->title);
+ shsurf->title = strdup(title);
+}
+
+static void
+shell_surface_set_class(struct wl_client *client,
+ struct wl_resource *resource, const char *class)
+{
+ struct shell_surface *shsurf = resource->data;
+
+ free(shsurf->class);
+ shsurf->class = strdup(class);
+}
+
+static int
+surface_move(struct shell_surface *shsurf, struct weston_seat *ws)
{
struct weston_move_grab *move;
+ if (!shsurf)
+ return -1;
+
move = malloc(sizeof *move);
if (!move)
return -1;
- move->grab.interface = &move_grab_interface;
- move->dx = es->geometry.x - wd->input_device.grab_x;
- move->dy = es->geometry.y - wd->input_device.grab_y;
- move->surface = es;
+ shell_grab_init(&move->base, &move_grab_interface, shsurf);
- wl_input_device_start_pointer_grab(&wd->input_device, &move->grab, time);
+ move->dx = wl_fixed_from_double(shsurf->surface->geometry.x) -
+ ws->seat.pointer->grab_x;
+ move->dy = wl_fixed_from_double(shsurf->surface->geometry.y) -
+ ws->seat.pointer->grab_y;
- wl_input_device_set_pointer_focus(&wd->input_device, NULL, time, 0, 0);
+ wl_pointer_start_grab(ws->seat.pointer, &move->base.grab);
+
+ wl_pointer_set_focus(ws->seat.pointer, NULL,
+ wl_fixed_from_int(0),
+ wl_fixed_from_int(0));
return 0;
}
static void
shell_surface_move(struct wl_client *client, struct wl_resource *resource,
- struct wl_resource *input_resource, uint32_t time)
+ struct wl_resource *seat_resource, uint32_t serial)
{
- struct weston_input_device *wd = input_resource->data;
+ struct weston_seat *ws = seat_resource->data;
struct shell_surface *shsurf = resource->data;
- if (wd->input_device.button_count == 0 ||
- wd->input_device.grab_time != time ||
- wd->input_device.pointer_focus != &shsurf->surface->surface)
+ if (ws->seat.pointer->button_count == 0 ||
+ ws->seat.pointer->grab_serial != serial ||
+ ws->seat.pointer->focus != &shsurf->surface->surface)
return;
- if (weston_surface_move(shsurf->surface, wd, time) < 0)
+ if (surface_move(shsurf, ws) < 0)
wl_resource_post_no_memory(resource);
}
struct weston_resize_grab {
- struct wl_pointer_grab grab;
+ struct shell_grab base;
uint32_t edges;
int32_t width, height;
- struct shell_surface *shsurf;
};
static void
resize_grab_motion(struct wl_pointer_grab *grab,
- uint32_t time, int32_t x, int32_t y)
+ uint32_t time, wl_fixed_t x, wl_fixed_t y)
{
struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
- struct wl_input_device *device = grab->input_device;
+ struct wl_pointer *pointer = grab->pointer;
+ struct shell_surface *shsurf = resize->base.shsurf;
int32_t width, height;
- int32_t from_x, from_y;
- int32_t to_x, to_y;
+ wl_fixed_t from_x, from_y;
+ wl_fixed_t to_x, to_y;
+
+ if (!shsurf)
+ return;
- weston_surface_from_global(resize->shsurf->surface,
- device->grab_x, device->grab_y,
- &from_x, &from_y);
- weston_surface_from_global(resize->shsurf->surface,
- device->x, device->y, &to_x, &to_y);
+ weston_surface_from_global_fixed(shsurf->surface,
+ pointer->grab_x, pointer->grab_y,
+ &from_x, &from_y);
+ weston_surface_from_global_fixed(shsurf->surface,
+ pointer->x, pointer->y, &to_x, &to_y);
+ width = resize->width;
if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
- width = resize->width + from_x - to_x;
+ width += wl_fixed_to_int(from_x - to_x);
} else if (resize->edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
- width = resize->width + to_x - from_x;
- } else {
- width = resize->width;
+ width += wl_fixed_to_int(to_x - from_x);
}
+ height = resize->height;
if (resize->edges & WL_SHELL_SURFACE_RESIZE_TOP) {
- height = resize->height + from_y - to_y;
+ height += wl_fixed_to_int(from_y - to_y);
} else if (resize->edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
- height = resize->height + to_y - from_y;
- } else {
- height = resize->height;
+ height += wl_fixed_to_int(to_y - from_y);
}
- wl_shell_surface_send_configure(&resize->shsurf->resource,
- time, resize->edges, width, height);
+ shsurf->client->send_configure(shsurf->surface,
+ resize->edges, width, height);
}
static void
+send_configure(struct weston_surface *surface,
+ uint32_t edges, int32_t width, int32_t height)
+{
+ struct shell_surface *shsurf = get_shell_surface(surface);
+
+ wl_shell_surface_send_configure(&shsurf->resource,
+ edges, width, height);
+}
+
+static const struct weston_shell_client shell_client = {
+ send_configure
+};
+
+static void
resize_grab_button(struct wl_pointer_grab *grab,
- uint32_t time, int32_t button, int32_t state)
+ uint32_t time, uint32_t button, uint32_t state_w)
{
- struct wl_input_device *device = grab->input_device;
+ struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
+ struct wl_pointer *pointer = grab->pointer;
+ enum wl_pointer_button_state state = state_w;
- if (device->button_count == 0 && state == 0) {
- wl_input_device_end_pointer_grab(device, time);
+ if (pointer->button_count == 0 &&
+ state == WL_POINTER_BUTTON_STATE_RELEASED) {
+ shell_grab_finish(&resize->base);
+ wl_pointer_end_grab(pointer);
free(grab);
}
}
};
static int
-weston_surface_resize(struct shell_surface *shsurf,
- struct weston_input_device *wd,
- uint32_t time, uint32_t edges)
+surface_resize(struct shell_surface *shsurf,
+ struct weston_seat *ws, uint32_t edges)
{
struct weston_resize_grab *resize;
if (!resize)
return -1;
- resize->grab.interface = &resize_grab_interface;
+ shell_grab_init(&resize->base, &resize_grab_interface, shsurf);
+
resize->edges = edges;
resize->width = shsurf->surface->geometry.width;
resize->height = shsurf->surface->geometry.height;
- resize->shsurf = shsurf;
- wl_input_device_start_pointer_grab(&wd->input_device, &resize->grab, time);
+ wl_pointer_start_grab(ws->seat.pointer, &resize->base.grab);
- wl_input_device_set_pointer_focus(&wd->input_device, NULL, time, 0, 0);
+ wl_pointer_set_focus(ws->seat.pointer, NULL,
+ wl_fixed_from_int(0),
+ wl_fixed_from_int(0));
return 0;
}
static void
shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
- struct wl_resource *input_resource, uint32_t time,
+ struct wl_resource *seat_resource, uint32_t serial,
uint32_t edges)
{
- struct weston_input_device *wd = input_resource->data;
+ struct weston_seat *ws = seat_resource->data;
struct shell_surface *shsurf = resource->data;
if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
return;
- if (wd->input_device.button_count == 0 ||
- wd->input_device.grab_time != time ||
- wd->input_device.pointer_focus != &shsurf->surface->surface)
+ if (ws->seat.pointer->button_count == 0 ||
+ ws->seat.pointer->grab_serial != serial ||
+ ws->seat.pointer->focus != &shsurf->surface->surface)
return;
- if (weston_surface_resize(shsurf, wd, time, edges) < 0)
+ if (surface_resize(shsurf, ws, edges) < 0)
wl_resource_post_no_memory(resource);
}
shell_unset_fullscreen(struct shell_surface *shsurf)
{
/* undo all fullscreen things here */
+ if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
+ shell_surface_is_top_fullscreen(shsurf)) {
+ weston_output_switch_mode(shsurf->fullscreen_output,
+ shsurf->fullscreen_output->origin);
+ }
shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
shsurf->fullscreen.framerate = 0;
wl_list_remove(&shsurf->fullscreen.transform.link);
wl_list_init(&shsurf->fullscreen.transform.link);
- weston_surface_destroy(shsurf->fullscreen.black_surface);
+ if (shsurf->fullscreen.black_surface)
+ weston_surface_destroy(shsurf->fullscreen.black_surface);
shsurf->fullscreen.black_surface = NULL;
shsurf->fullscreen_output = NULL;
- shsurf->surface->force_configure = 1;
weston_surface_set_position(shsurf->surface,
shsurf->saved_x, shsurf->saved_y);
+ if (shsurf->saved_rotation_valid) {
+ wl_list_insert(&shsurf->surface->geometry.transformation_list,
+ &shsurf->rotation.transform.link);
+ shsurf->saved_rotation_valid = false;
+ }
}
static int
}
static void
+set_surface_type(struct shell_surface *shsurf)
+{
+ struct weston_surface *surface = shsurf->surface;
+ struct shell_surface *pshsurf = shsurf->parent;
+ struct weston_surface *pes;
+ struct shell_surface *priv;
+ struct desktop_shell *shell = shsurf->shell;
+
+ reset_shell_surface_type(shsurf);
+
+ shsurf->type = shsurf->next_type;
+ shsurf->next_type = SHELL_SURFACE_NONE;
+
+ switch (shsurf->type) {
+ case SHELL_SURFACE_TOPLEVEL:
+ break;
+ case SHELL_SURFACE_TRANSIENT:
+ pes = pshsurf->surface;
+ weston_surface_set_position(surface,
+ pes->geometry.x + shsurf->transient.x,
+ pes->geometry.y + shsurf->transient.y);
+ break;
+
+ case SHELL_SURFACE_MAXIMIZED:
+ shsurf->saved_x = surface->geometry.x;
+ shsurf->saved_y = surface->geometry.y;
+ shsurf->saved_position_valid = true;
+ break;
+
+ case SHELL_SURFACE_FULLSCREEN:
+ shsurf->saved_x = surface->geometry.x;
+ shsurf->saved_y = surface->geometry.y;
+ shsurf->saved_position_valid = true;
+
+ if (!wl_list_empty(&shsurf->rotation.transform.link)) {
+ wl_list_remove(&shsurf->rotation.transform.link);
+ wl_list_init(&shsurf->rotation.transform.link);
+ shsurf->surface->geometry.dirty = 1;
+ shsurf->saved_rotation_valid = true;
+ }
+ break;
+
+ case SHELL_SURFACE_BACKGROUND:
+ wl_list_for_each(priv, &shell->backgrounds, link) {
+ if (priv->output == shsurf->output) {
+ priv->surface->output = NULL;
+ wl_list_remove(&priv->surface->layer_link);
+ wl_list_remove(&priv->link);
+ break;
+ }
+ }
+
+ wl_list_insert(&shell->backgrounds, &shsurf->link);
+
+ weston_surface_set_position(surface, shsurf->output->x,
+ shsurf->output->y);
+ break;
+
+ case SHELL_SURFACE_PANEL:
+ wl_list_for_each(priv, &shell->panels, link) {
+ if (priv->output == shsurf->output) {
+ priv->surface->output = NULL;
+ wl_list_remove(&priv->surface->layer_link);
+ wl_list_remove(&priv->link);
+ break;
+ }
+ }
+
+ wl_list_insert(&shell->panels, &shsurf->link);
+
+ weston_surface_set_position(surface, shsurf->output->x,
+ shsurf->output->y);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+set_toplevel(struct shell_surface *shsurf)
+{
+ shsurf->next_type = SHELL_SURFACE_TOPLEVEL;
+}
+
+static void
shell_surface_set_toplevel(struct wl_client *client,
struct wl_resource *resource)
-
{
struct shell_surface *surface = resource->data;
- if (reset_shell_surface_type(surface))
- return;
+ set_toplevel(surface);
+}
- surface->type = SHELL_SURFACE_TOPLEVEL;
+static void
+set_transient(struct shell_surface *shsurf,
+ struct shell_surface *pshsurf, int x, int y, uint32_t flags)
+{
+ /* assign to parents output */
+ shsurf->parent = pshsurf;
+ shsurf->transient.x = x;
+ shsurf->transient.y = y;
+ shsurf->transient.flags = flags;
+ shsurf->next_type = SHELL_SURFACE_TRANSIENT;
}
static void
int x, int y, uint32_t flags)
{
struct shell_surface *shsurf = resource->data;
- struct weston_surface *es = shsurf->surface;
struct shell_surface *pshsurf = parent_resource->data;
- struct weston_surface *pes = pshsurf->surface;
-
- if (reset_shell_surface_type(shsurf))
- return;
-
- /* assign to parents output */
- shsurf->output = pes->output;
- weston_surface_set_position(es, pes->geometry.x + x,
- pes->geometry.y + y);
- shsurf->type = SHELL_SURFACE_TRANSIENT;
+ set_transient(shsurf, pshsurf, x, y, flags);
}
-static struct wl_shell *
+static struct desktop_shell *
shell_surface_get_shell(struct shell_surface *shsurf)
{
- struct weston_surface *es = shsurf->surface;
- struct weston_shell *shell = es->compositor->shell;
-
- return (struct wl_shell *)container_of(shell, struct wl_shell, shell);
+ return shsurf->shell;
}
static int
-get_output_panel_height(struct wl_shell *wlshell,struct weston_output *output)
+get_output_panel_height(struct desktop_shell *shell,
+ struct weston_output *output)
{
struct shell_surface *priv;
int panel_height = 0;
if (!output)
return 0;
- wl_list_for_each(priv, &wlshell->panels, link) {
+ wl_list_for_each(priv, &shell->panels, link) {
if (priv->output == output) {
panel_height = priv->surface->geometry.height;
break;
{
struct shell_surface *shsurf = resource->data;
struct weston_surface *es = shsurf->surface;
- struct wl_shell *wlshell = NULL;
+ struct desktop_shell *shell = NULL;
uint32_t edges = 0, panel_height = 0;
/* get the default output, if the client set it as NULL
else
shsurf->output = get_default_output(es->compositor);
- if (reset_shell_surface_type(shsurf))
- return;
-
- shsurf->saved_x = es->geometry.x;
- shsurf->saved_y = es->geometry.y;
- shsurf->saved_position_valid = true;
-
- wlshell = shell_surface_get_shell(shsurf);
- panel_height = get_output_panel_height(wlshell, es->output);
+ shell = shell_surface_get_shell(shsurf);
+ panel_height = get_output_panel_height(shell, es->output);
edges = WL_SHELL_SURFACE_RESIZE_TOP|WL_SHELL_SURFACE_RESIZE_LEFT;
- wl_shell_surface_send_configure(&shsurf->resource,
- weston_compositor_get_time(), edges,
- es->output->current->width,
- es->output->current->height - panel_height);
+ shsurf->client->send_configure(shsurf->surface, edges,
+ es->output->current->width,
+ es->output->current->height - panel_height);
- shsurf->type = SHELL_SURFACE_MAXIMIZED;
+ shsurf->next_type = SHELL_SURFACE_MAXIMIZED;
}
+static void
+black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy);
+
static struct weston_surface *
create_black_surface(struct weston_compositor *ec,
+ struct weston_surface *fs_surface,
GLfloat x, GLfloat y, int w, int h)
{
struct weston_surface *surface = NULL;
surface = weston_surface_create(ec);
if (surface == NULL) {
- fprintf(stderr, "no memory\n");
+ weston_log("no memory\n");
return NULL;
}
+ surface->configure = black_surface_configure;
+ surface->private = fs_surface;
weston_surface_configure(surface, x, y, w, h);
weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
return surface;
if (!shsurf->fullscreen.black_surface)
shsurf->fullscreen.black_surface =
create_black_surface(surface->compositor,
+ surface,
output->x, output->y,
output->current->width,
output->current->height);
weston_surface_set_position(surface, output->x, output->y);
break;
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
+ if (shell_surface_is_top_fullscreen(shsurf)) {
+ struct weston_mode mode = {0,
+ surface->geometry.width,
+ surface->geometry.height,
+ shsurf->fullscreen.framerate};
+
+ if (weston_output_switch_mode(output, &mode) == 0) {
+ weston_surface_configure(shsurf->fullscreen.black_surface,
+ output->x, output->y,
+ output->current->width,
+ output->current->height);
+ weston_surface_set_position(surface, output->x, output->y);
+ break;
+ }
+ }
break;
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
break;
static void
shell_stack_fullscreen(struct shell_surface *shsurf)
{
+ struct weston_output *output = shsurf->fullscreen_output;
struct weston_surface *surface = shsurf->surface;
- struct wl_shell *shell = shell_surface_get_shell(shsurf);
+ struct desktop_shell *shell = shell_surface_get_shell(shsurf);
wl_list_remove(&surface->layer_link);
- wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
-
wl_list_insert(&shell->fullscreen_layer.surface_list,
&surface->layer_link);
+ weston_surface_damage(surface);
+
+ if (!shsurf->fullscreen.black_surface)
+ shsurf->fullscreen.black_surface =
+ create_black_surface(surface->compositor,
+ surface,
+ output->x, output->y,
+ output->current->width,
+ output->current->height);
+
+ wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
wl_list_insert(&surface->layer_link,
&shsurf->fullscreen.black_surface->layer_link);
-
- weston_surface_damage(surface);
weston_surface_damage(shsurf->fullscreen.black_surface);
}
static void
shell_map_fullscreen(struct shell_surface *shsurf)
{
- shell_configure_fullscreen(shsurf);
shell_stack_fullscreen(shsurf);
+ shell_configure_fullscreen(shsurf);
}
static void
else
shsurf->output = get_default_output(es->compositor);
- if (reset_shell_surface_type(shsurf))
- return;
-
shsurf->fullscreen_output = shsurf->output;
shsurf->fullscreen.type = method;
shsurf->fullscreen.framerate = framerate;
- shsurf->type = SHELL_SURFACE_FULLSCREEN;
-
- shsurf->saved_x = es->geometry.x;
- shsurf->saved_y = es->geometry.y;
- shsurf->saved_position_valid = true;
+ shsurf->next_type = SHELL_SURFACE_FULLSCREEN;
- if (es->output)
- shsurf->surface->force_configure = 1;
-
- wl_shell_surface_send_configure(&shsurf->resource,
- weston_compositor_get_time(), 0,
- shsurf->output->current->width,
- shsurf->output->current->height);
+ shsurf->client->send_configure(shsurf->surface, 0,
+ shsurf->output->current->width,
+ shsurf->output->current->height);
}
static void
-popup_grab_focus(struct wl_pointer_grab *grab, uint32_t time,
- struct wl_surface *surface, int32_t x, int32_t y)
+popup_grab_focus(struct wl_pointer_grab *grab,
+ struct wl_surface *surface,
+ wl_fixed_t x,
+ wl_fixed_t y)
{
- struct wl_input_device *device = grab->input_device;
+ struct wl_pointer *pointer = grab->pointer;
struct shell_surface *priv =
container_of(grab, struct shell_surface, popup.grab);
struct wl_client *client = priv->surface->surface.resource.client;
if (surface && surface->resource.client == client) {
- wl_input_device_set_pointer_focus(device, surface, time, x, y);
+ wl_pointer_set_focus(pointer, surface, x, y);
grab->focus = surface;
} else {
- wl_input_device_set_pointer_focus(device, NULL, time, 0, 0);
+ wl_pointer_set_focus(pointer, NULL,
+ wl_fixed_from_int(0),
+ wl_fixed_from_int(0));
grab->focus = NULL;
}
}
static void
popup_grab_motion(struct wl_pointer_grab *grab,
- uint32_t time, int32_t sx, int32_t sy)
+ uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
{
struct wl_resource *resource;
- resource = grab->input_device->pointer_focus_resource;
+ resource = grab->pointer->focus_resource;
if (resource)
- wl_input_device_send_motion(resource, time, sx, sy);
+ wl_pointer_send_motion(resource, time, sx, sy);
}
static void
popup_grab_button(struct wl_pointer_grab *grab,
- uint32_t time, int32_t button, int32_t state)
+ uint32_t time, uint32_t button, uint32_t state_w)
{
struct wl_resource *resource;
struct shell_surface *shsurf =
container_of(grab, struct shell_surface, popup.grab);
+ struct wl_display *display;
+ enum wl_pointer_button_state state = state_w;
+ uint32_t serial;
- resource = grab->input_device->pointer_focus_resource;
+ resource = grab->pointer->focus_resource;
if (resource) {
- wl_input_device_send_button(resource, time, button, state);
- } else if (state == 0 &&
+ display = wl_client_get_display(resource->client);
+ serial = wl_display_get_serial(display);
+ wl_pointer_send_button(resource, serial, time, button, state);
+ } else if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
(shsurf->popup.initial_up ||
- time - shsurf->popup.time > 500)) {
+ time - shsurf->popup.seat->pointer->grab_time > 500)) {
wl_shell_surface_send_popup_done(&shsurf->resource);
- wl_input_device_end_pointer_grab(grab->input_device, time);
- shsurf->popup.grab.input_device = NULL;
+ wl_pointer_end_grab(grab->pointer);
+ shsurf->popup.grab.pointer = NULL;
}
- if (state == 0)
+ if (state == WL_POINTER_BUTTON_STATE_RELEASED)
shsurf->popup.initial_up = 1;
}
};
static void
-shell_map_popup(struct shell_surface *shsurf, uint32_t time)
+shell_map_popup(struct shell_surface *shsurf)
{
- struct wl_input_device *device;
+ struct wl_seat *seat = shsurf->popup.seat;
struct weston_surface *es = shsurf->surface;
struct weston_surface *parent = shsurf->parent->surface;
es->output = parent->output;
-
shsurf->popup.grab.interface = &popup_grab_interface;
- device = es->compositor->input_device;
weston_surface_update_transform(parent);
if (parent->transform.enabled) {
&shsurf->popup.parent_transform.link);
weston_surface_set_position(es, shsurf->popup.x, shsurf->popup.y);
- shsurf->popup.grab.input_device = device;
- shsurf->popup.time = device->grab_time;
shsurf->popup.initial_up = 0;
- wl_input_device_start_pointer_grab(shsurf->popup.grab.input_device,
- &shsurf->popup.grab, shsurf->popup.time);
+ /* We don't require the grab to still be active, but if another
+ * grab has started in the meantime, we end the popup now. */
+ if (seat->pointer->grab_serial == shsurf->popup.serial) {
+ wl_pointer_start_grab(seat->pointer, &shsurf->popup.grab);
+ } else {
+ wl_shell_surface_send_popup_done(&shsurf->resource);
+ }
}
static void
shell_surface_set_popup(struct wl_client *client,
struct wl_resource *resource,
- struct wl_resource *input_device_resource,
- uint32_t time,
+ struct wl_resource *seat_resource,
+ uint32_t serial,
struct wl_resource *parent_resource,
int32_t x, int32_t y, uint32_t flags)
{
shsurf->type = SHELL_SURFACE_POPUP;
shsurf->parent = parent_resource->data;
+ shsurf->popup.seat = seat_resource->data;
+ shsurf->popup.serial = serial;
shsurf->popup.x = x;
shsurf->popup.y = y;
}
static const struct wl_shell_surface_interface shell_surface_implementation = {
+ shell_surface_pong,
shell_surface_move,
shell_surface_resize,
shell_surface_set_toplevel,
shell_surface_set_transient,
shell_surface_set_fullscreen,
shell_surface_set_popup,
- shell_surface_set_maximized
+ shell_surface_set_maximized,
+ shell_surface_set_title,
+ shell_surface_set_class
};
static void
-destroy_shell_surface(struct wl_resource *resource)
+destroy_shell_surface(struct shell_surface *shsurf)
{
- struct shell_surface *shsurf = resource->data;
-
- if (shsurf->popup.grab.input_device)
- wl_input_device_end_pointer_grab(shsurf->popup.grab.input_device, 0);
+ if (shsurf->popup.grab.pointer)
+ wl_pointer_end_grab(shsurf->popup.grab.pointer);
- /* in case cleaning up a dead client destroys shell_surface first */
- if (shsurf->surface)
- wl_list_remove(&shsurf->surface_destroy_listener.link);
+ if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
+ shell_surface_is_top_fullscreen(shsurf)) {
+ weston_output_switch_mode(shsurf->fullscreen_output,
+ shsurf->fullscreen_output->origin);
+ }
if (shsurf->fullscreen.black_surface)
weston_surface_destroy(shsurf->fullscreen.black_surface);
+ /* As destroy_resource() use wl_list_for_each_safe(),
+ * we can always remove the listener.
+ */
+ wl_list_remove(&shsurf->surface_destroy_listener.link);
+ shsurf->surface->configure = NULL;
+ ping_timer_destroy(shsurf);
+
wl_list_remove(&shsurf->link);
free(shsurf);
}
static void
-shell_handle_surface_destroy(struct wl_listener *listener,
- struct wl_resource *resource, uint32_t time)
+shell_destroy_shell_surface(struct wl_resource *resource)
+{
+ struct shell_surface *shsurf = resource->data;
+
+ destroy_shell_surface(shsurf);
+}
+
+static void
+shell_handle_surface_destroy(struct wl_listener *listener, void *data)
{
struct shell_surface *shsurf = container_of(listener,
struct shell_surface,
surface_destroy_listener);
- shsurf->surface = NULL;
- wl_resource_destroy(&shsurf->resource, time);
+ if (shsurf->resource.client) {
+ wl_resource_destroy(&shsurf->resource);
+ } else {
+ wl_signal_emit(&shsurf->resource.destroy_signal,
+ &shsurf->resource);
+ destroy_shell_surface(shsurf);
+ }
}
static struct shell_surface *
get_shell_surface(struct weston_surface *surface)
{
- struct wl_list *lst = &surface->surface.resource.destroy_listener_list;
struct wl_listener *listener;
- /* search the destroy listener list for our callback */
- wl_list_for_each(listener, lst, link) {
- if (listener->func == shell_handle_surface_destroy) {
- return container_of(listener, struct shell_surface,
- surface_destroy_listener);
- }
- }
+ listener = wl_signal_get(&surface->surface.resource.destroy_signal,
+ shell_handle_surface_destroy);
+ if (listener)
+ return container_of(listener, struct shell_surface,
+ surface_destroy_listener);
return NULL;
}
static void
-shell_get_shell_surface(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t id,
- struct wl_resource *surface_resource)
+shell_surface_configure(struct weston_surface *, int32_t, int32_t);
+
+static struct shell_surface *
+create_shell_surface(void *shell, struct weston_surface *surface,
+ const struct weston_shell_client *client)
{
- struct weston_surface *surface = surface_resource->data;
struct shell_surface *shsurf;
- if (get_shell_surface(surface)) {
- wl_resource_post_error(surface_resource,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "wl_shell::get_shell_surface already requested");
- return;
+ if (surface->configure) {
+ weston_log("surface->configure already set\n");
+ return NULL;
}
shsurf = calloc(1, sizeof *shsurf);
if (!shsurf) {
- wl_resource_post_no_memory(resource);
- return;
+ weston_log("no memory to allocate shell surface\n");
+ return NULL;
}
- shsurf->resource.destroy = destroy_shell_surface;
- shsurf->resource.object.id = id;
- shsurf->resource.object.interface = &wl_shell_surface_interface;
- shsurf->resource.object.implementation =
- (void (**)(void)) &shell_surface_implementation;
- shsurf->resource.data = shsurf;
+ surface->configure = shell_surface_configure;
+ surface->compositor->shell_interface.shell = shell;
+ shsurf->shell = (struct desktop_shell *) shell;
+ shsurf->unresponsive = 0;
shsurf->saved_position_valid = false;
+ shsurf->saved_rotation_valid = false;
shsurf->surface = surface;
shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
shsurf->fullscreen.framerate = 0;
shsurf->fullscreen.black_surface = NULL;
+ shsurf->ping_timer = NULL;
wl_list_init(&shsurf->fullscreen.transform.link);
- shsurf->surface_destroy_listener.func = shell_handle_surface_destroy;
- wl_list_insert(surface->surface.resource.destroy_listener_list.prev,
- &shsurf->surface_destroy_listener.link);
+ wl_signal_init(&shsurf->resource.destroy_signal);
+ shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
+ wl_signal_add(&surface->surface.resource.destroy_signal,
+ &shsurf->surface_destroy_listener);
/* init link so its safe to always remove it in destroy_shell_surface */
wl_list_init(&shsurf->link);
weston_matrix_init(&shsurf->rotation.rotation);
shsurf->type = SHELL_SURFACE_NONE;
+ shsurf->next_type = SHELL_SURFACE_NONE;
+
+ shsurf->client = client;
+
+ return shsurf;
+}
+
+static void
+shell_get_shell_surface(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id,
+ struct wl_resource *surface_resource)
+{
+ struct weston_surface *surface = surface_resource->data;
+ struct desktop_shell *shell = resource->data;
+ struct shell_surface *shsurf;
+
+ if (get_shell_surface(surface)) {
+ wl_resource_post_error(surface_resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "desktop_shell::get_shell_surface already requested");
+ return;
+ }
+
+ shsurf = create_shell_surface(shell, surface, &shell_client);
+ if (!shsurf) {
+ wl_resource_post_error(surface_resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "surface->configure already set");
+ return;
+ }
+
+ shsurf->resource.destroy = shell_destroy_shell_surface;
+ shsurf->resource.object.id = id;
+ shsurf->resource.object.interface = &wl_shell_surface_interface;
+ shsurf->resource.object.implementation =
+ (void (**)(void)) &shell_surface_implementation;
+ shsurf->resource.data = shsurf;
wl_client_add_resource(client, &shsurf->resource);
}
}
static void
-launch_screensaver(struct wl_shell *shell)
+launch_screensaver(struct desktop_shell *shell)
{
if (shell->screensaver.binding)
return;
return;
if (shell->screensaver.process.pid != 0) {
- fprintf(stderr, "old screensaver still running\n");
+ weston_log("old screensaver still running\n");
return;
}
}
static void
-terminate_screensaver(struct wl_shell *shell)
+terminate_screensaver(struct desktop_shell *shell)
{
if (shell->screensaver.process.pid == 0)
return;
}
static void
-show_screensaver(struct wl_shell *shell, struct shell_surface *surface)
+show_screensaver(struct desktop_shell *shell, struct shell_surface *surface)
{
struct wl_list *list;
}
static void
-hide_screensaver(struct wl_shell *shell, struct shell_surface *surface)
+hide_screensaver(struct desktop_shell *shell, struct shell_surface *surface)
{
wl_list_remove(&surface->surface->layer_link);
wl_list_init(&surface->surface->layer_link);
struct wl_resource *output_resource,
struct wl_resource *surface_resource)
{
- struct wl_shell *shell = resource->data;
struct shell_surface *shsurf = surface_resource->data;
- struct weston_surface *surface = shsurf->surface;
- struct shell_surface *priv;
- if (reset_shell_surface_type(shsurf))
- return;
-
- wl_list_for_each(priv, &shell->backgrounds, link) {
- if (priv->output == output_resource->data) {
- priv->surface->output = NULL;
- wl_list_remove(&priv->surface->layer_link);
- wl_list_remove(&priv->link);
- break;
- }
- }
-
- shsurf->type = SHELL_SURFACE_BACKGROUND;
+ shsurf->next_type = SHELL_SURFACE_BACKGROUND;
shsurf->output = output_resource->data;
- wl_list_insert(&shell->backgrounds, &shsurf->link);
-
- weston_surface_set_position(surface, shsurf->output->x,
- shsurf->output->y);
-
- desktop_shell_send_configure(resource,
- weston_compositor_get_time(), 0,
+ desktop_shell_send_configure(resource, 0,
surface_resource,
shsurf->output->current->width,
shsurf->output->current->height);
struct wl_resource *output_resource,
struct wl_resource *surface_resource)
{
- struct wl_shell *shell = resource->data;
struct shell_surface *shsurf = surface_resource->data;
- struct weston_surface *surface = shsurf->surface;
- struct shell_surface *priv;
-
- if (reset_shell_surface_type(shsurf))
- return;
- wl_list_for_each(priv, &shell->panels, link) {
- if (priv->output == output_resource->data) {
- priv->surface->output = NULL;
- wl_list_remove(&priv->surface->layer_link);
- wl_list_remove(&priv->link);
- break;
- }
- }
-
- shsurf->type = SHELL_SURFACE_PANEL;
+ shsurf->next_type = SHELL_SURFACE_PANEL;
shsurf->output = output_resource->data;
- wl_list_insert(&shell->panels, &shsurf->link);
-
- weston_surface_set_position(surface, shsurf->output->x,
- shsurf->output->y);
-
- desktop_shell_send_configure(resource,
- weston_compositor_get_time(), 0,
+ desktop_shell_send_configure(resource, 0,
surface_resource,
shsurf->output->current->width,
shsurf->output->current->height);
}
static void
-handle_lock_surface_destroy(struct wl_listener *listener,
- struct wl_resource *resource, uint32_t time)
+handle_lock_surface_destroy(struct wl_listener *listener, void *data)
{
- struct wl_shell *shell =
- container_of(listener, struct wl_shell, lock_surface_listener);
+ struct desktop_shell *shell =
+ container_of(listener, struct desktop_shell, lock_surface_listener);
- fprintf(stderr, "lock surface gone\n");
+ weston_log("lock surface gone\n");
shell->lock_surface = NULL;
}
struct wl_resource *resource,
struct wl_resource *surface_resource)
{
- struct wl_shell *shell = resource->data;
+ struct desktop_shell *shell = resource->data;
struct shell_surface *surface = surface_resource->data;
- if (reset_shell_surface_type(surface))
- return;
-
shell->prepare_event_sent = false;
if (!shell->locked)
shell->lock_surface = surface;
- shell->lock_surface_listener.func = handle_lock_surface_destroy;
- wl_list_insert(&surface_resource->destroy_listener_list,
- &shell->lock_surface_listener.link);
+ shell->lock_surface_listener.notify = handle_lock_surface_destroy;
+ wl_signal_add(&surface_resource->destroy_signal,
+ &shell->lock_surface_listener);
- shell->lock_surface->type = SHELL_SURFACE_LOCK;
+ shell->lock_surface->next_type = SHELL_SURFACE_LOCK;
}
static void
-resume_desktop(struct wl_shell *shell)
+resume_desktop(struct desktop_shell *shell)
{
struct shell_surface *tmp;
desktop_shell_unlock(struct wl_client *client,
struct wl_resource *resource)
{
- struct wl_shell *shell = resource->data;
+ struct desktop_shell *shell = resource->data;
shell->prepare_event_sent = false;
resume_desktop(shell);
}
+static void
+desktop_shell_set_busy_surface(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *surface_resource)
+{
+ struct desktop_shell *shell = resource->data;
+
+ shell->busy_surface = surface_resource->data;
+}
+
static const struct desktop_shell_interface desktop_shell_implementation = {
desktop_shell_set_background,
desktop_shell_set_panel,
desktop_shell_set_lock_surface,
- desktop_shell_unlock
+ desktop_shell_unlock,
+ desktop_shell_set_busy_surface
};
static enum shell_surface_type
}
static void
-move_binding(struct wl_input_device *device, uint32_t time,
- uint32_t key, uint32_t button, uint32_t state, void *data)
+move_binding(struct wl_seat *seat, uint32_t time, uint32_t button, void *data)
{
struct weston_surface *surface =
- (struct weston_surface *) device->pointer_focus;
+ (struct weston_surface *) seat->pointer->focus;
+ struct shell_surface *shsurf;
if (surface == NULL)
return;
- switch (get_shell_surface_type(surface)) {
+ shsurf = get_shell_surface(surface);
+ if (shsurf == NULL)
+ return;
+
+ switch (shsurf->type) {
case SHELL_SURFACE_PANEL:
case SHELL_SURFACE_BACKGROUND:
case SHELL_SURFACE_FULLSCREEN:
break;
}
- weston_surface_move(surface, (struct weston_input_device *) device, time);
+ surface_move(shsurf, (struct weston_seat *) seat);
}
static void
-resize_binding(struct wl_input_device *device, uint32_t time,
- uint32_t key, uint32_t button, uint32_t state, void *data)
+resize_binding(struct wl_seat *seat, uint32_t time, uint32_t button, void *data)
{
struct weston_surface *surface =
- (struct weston_surface *) device->pointer_focus;
+ (struct weston_surface *) seat->pointer->focus;
uint32_t edges = 0;
int32_t x, y;
struct shell_surface *shsurf;
}
weston_surface_from_global(surface,
- device->grab_x, device->grab_y, &x, &y);
+ wl_fixed_to_int(seat->pointer->grab_x),
+ wl_fixed_to_int(seat->pointer->grab_y),
+ &x, &y);
if (x < surface->geometry.width / 3)
edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
else
edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
- weston_surface_resize(shsurf, (struct weston_input_device *) device,
- time, edges);
+ surface_resize(shsurf, (struct weston_seat *) seat, edges);
+}
+
+static void
+surface_opacity_binding(struct wl_seat *seat, uint32_t time, uint32_t axis,
+ wl_fixed_t value, void *data)
+{
+ float step = 0.05;
+ struct shell_surface *shsurf;
+ struct weston_surface *surface =
+ (struct weston_surface *) seat->pointer->focus;
+
+ if (surface == NULL)
+ return;
+
+ shsurf = get_shell_surface(surface);
+ if (!shsurf)
+ return;
+
+ switch (shsurf->type) {
+ case SHELL_SURFACE_BACKGROUND:
+ case SHELL_SURFACE_SCREENSAVER:
+ return;
+ default:
+ break;
+ }
+
+ surface->alpha += wl_fixed_to_double(value) * step;
+
+ if (surface->alpha > 1.0)
+ surface->alpha = 1.0;
+ if (surface->alpha < step)
+ surface->alpha = step;
+
+ surface->geometry.dirty = 1;
+ weston_surface_damage(surface);
}
static void
-zoom_binding(struct wl_input_device *device, uint32_t time,
- uint32_t key, uint32_t button, uint32_t state, void *data)
+do_zoom(struct wl_seat *seat, uint32_t time, uint32_t key, uint32_t axis,
+ wl_fixed_t value)
{
- struct weston_input_device *wd = (struct weston_input_device *) device;
- struct weston_compositor *compositor = wd->compositor;
+ struct weston_seat *ws = (struct weston_seat *) seat;
+ struct weston_compositor *compositor = ws->compositor;
struct weston_output *output;
+ float maximum_level, increment;
wl_list_for_each(output, &compositor->output_list, link) {
if (pixman_region32_contains_point(&output->region,
- device->x, device->y, NULL)) {
- if (state && key == KEY_UP) {
- output->zoom.active = 1;
- output->zoom.level -= output->zoom.increment;
- }
- if (state && key == KEY_DOWN)
- output->zoom.level += output->zoom.increment;
-
- if (output->zoom.level >= 1.0) {
+ wl_fixed_to_double(seat->pointer->x),
+ wl_fixed_to_double(seat->pointer->y),
+ NULL)) {
+ if (key == KEY_PAGEUP)
+ increment = output->zoom.increment;
+ else if (key == KEY_PAGEDOWN)
+ increment = -output->zoom.increment;
+ else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
+ increment = output->zoom.increment *
+ wl_fixed_to_double(value);
+ else
+ increment = 0;
+
+ output->zoom.active = 1;
+ output->zoom.level += increment;
+
+ if (output->zoom.level <= 0.0) {
output->zoom.active = 0;
- output->zoom.level = 1.0;
+ output->zoom.level = 0.0;
}
- if (output->zoom.level < output->zoom.increment)
- output->zoom.level = output->zoom.increment;
+ maximum_level = 1 - output->zoom.increment;
+
+ if (output->zoom.level > maximum_level)
+ output->zoom.level = maximum_level;
- weston_output_update_zoom(output, device->x, device->y);
+ weston_output_update_zoom(output,
+ seat->pointer->x,
+ seat->pointer->y,
+ ZOOM_POINTER);
}
}
}
static void
-terminate_binding(struct wl_input_device *device, uint32_t time,
- uint32_t key, uint32_t button, uint32_t state, void *data)
+zoom_axis_binding(struct wl_seat *seat, uint32_t time, uint32_t axis,
+ wl_fixed_t value, void *data)
+{
+ do_zoom(seat, time, 0, axis, value);
+}
+
+static void
+zoom_key_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
+ void *data)
+{
+ do_zoom(seat, time, key, 0, 0);
+}
+
+static void
+terminate_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
+ void *data)
{
struct weston_compositor *compositor = data;
- if (state)
- wl_display_terminate(compositor->wl_display);
+ wl_display_terminate(compositor->wl_display);
}
static void
rotate_grab_motion(struct wl_pointer_grab *grab,
- uint32_t time, int32_t x, int32_t y)
+ uint32_t time, wl_fixed_t x, wl_fixed_t y)
{
struct rotate_grab *rotate =
- container_of(grab, struct rotate_grab, grab);
- struct wl_input_device *device = grab->input_device;
- struct shell_surface *surface = rotate->surface;
- GLfloat cx = 0.5f * surface->surface->geometry.width;
- GLfloat cy = 0.5f * surface->surface->geometry.height;
- GLfloat dx, dy;
- GLfloat r;
+ container_of(grab, struct rotate_grab, base.grab);
+ struct wl_pointer *pointer = grab->pointer;
+ struct shell_surface *shsurf = rotate->base.shsurf;
+ struct weston_surface *surface;
+ GLfloat cx, cy, dx, dy, cposx, cposy, dposx, dposy, r;
+
+ if (!shsurf)
+ return;
+
+ surface = shsurf->surface;
- dx = device->x - rotate->center.x;
- dy = device->y - rotate->center.y;
+ cx = 0.5f * surface->geometry.width;
+ cy = 0.5f * surface->geometry.height;
+
+ dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
+ dy = wl_fixed_to_double(pointer->y) - rotate->center.y;
r = sqrtf(dx * dx + dy * dy);
- wl_list_remove(&surface->rotation.transform.link);
- surface->surface->geometry.dirty = 1;
+ wl_list_remove(&shsurf->rotation.transform.link);
+ shsurf->surface->geometry.dirty = 1;
if (r > 20.0f) {
struct weston_matrix *matrix =
- &surface->rotation.transform.matrix;
+ &shsurf->rotation.transform.matrix;
weston_matrix_init(&rotate->rotation);
rotate->rotation.d[0] = dx / r;
weston_matrix_init(matrix);
weston_matrix_translate(matrix, -cx, -cy, 0.0f);
- weston_matrix_multiply(matrix, &surface->rotation.rotation);
+ weston_matrix_multiply(matrix, &shsurf->rotation.rotation);
weston_matrix_multiply(matrix, &rotate->rotation);
weston_matrix_translate(matrix, cx, cy, 0.0f);
wl_list_insert(
- &surface->surface->geometry.transformation_list,
- &surface->rotation.transform.link);
+ &shsurf->surface->geometry.transformation_list,
+ &shsurf->rotation.transform.link);
} else {
- wl_list_init(&surface->rotation.transform.link);
- weston_matrix_init(&surface->rotation.rotation);
+ wl_list_init(&shsurf->rotation.transform.link);
+ weston_matrix_init(&shsurf->rotation.rotation);
weston_matrix_init(&rotate->rotation);
}
+ /* We need to adjust the position of the surface
+ * in case it was resized in a rotated state before */
+ cposx = surface->geometry.x + cx;
+ cposy = surface->geometry.y + cy;
+ dposx = rotate->center.x - cposx;
+ dposy = rotate->center.y - cposy;
+ if (dposx != 0.0f || dposy != 0.0f) {
+ weston_surface_set_position(surface,
+ surface->geometry.x + dposx,
+ surface->geometry.y + dposy);
+ }
+
/* Repaint implies weston_surface_update_transform(), which
* lazily applies the damage due to rotation update.
*/
- weston_compositor_schedule_repaint(surface->surface->compositor);
+ weston_compositor_schedule_repaint(shsurf->surface->compositor);
}
static void
rotate_grab_button(struct wl_pointer_grab *grab,
- uint32_t time, int32_t button, int32_t state)
+ uint32_t time, uint32_t button, uint32_t state_w)
{
struct rotate_grab *rotate =
- container_of(grab, struct rotate_grab, grab);
- struct wl_input_device *device = grab->input_device;
- struct shell_surface *surface = rotate->surface;
-
- if (device->button_count == 0 && state == 0) {
- weston_matrix_multiply(&surface->rotation.rotation,
- &rotate->rotation);
- wl_input_device_end_pointer_grab(device, time);
+ container_of(grab, struct rotate_grab, base.grab);
+ struct wl_pointer *pointer = grab->pointer;
+ struct shell_surface *shsurf = rotate->base.shsurf;
+ enum wl_pointer_button_state state = state_w;
+
+ if (pointer->button_count == 0 &&
+ state == WL_POINTER_BUTTON_STATE_RELEASED) {
+ if (shsurf)
+ weston_matrix_multiply(&shsurf->rotation.rotation,
+ &rotate->rotation);
+ shell_grab_finish(&rotate->base);
+ wl_pointer_end_grab(pointer);
free(rotate);
}
}
};
static void
-rotate_binding(struct wl_input_device *device, uint32_t time,
- uint32_t key, uint32_t button, uint32_t state, void *data)
+rotate_binding(struct wl_seat *seat, uint32_t time, uint32_t button,
+ void *data)
{
struct weston_surface *base_surface =
- (struct weston_surface *) device->pointer_focus;
+ (struct weston_surface *) seat->pointer->focus;
struct shell_surface *surface;
struct rotate_grab *rotate;
GLfloat dx, dy;
if (!rotate)
return;
- rotate->grab.interface = &rotate_grab_interface;
- rotate->surface = surface;
+ shell_grab_init(&rotate->base, &rotate_grab_interface, surface);
- weston_surface_to_global(surface->surface,
- surface->surface->geometry.width / 2,
- surface->surface->geometry.height / 2,
- &rotate->center.x, &rotate->center.y);
+ weston_surface_to_global_float(surface->surface,
+ surface->surface->geometry.width / 2,
+ surface->surface->geometry.height / 2,
+ &rotate->center.x, &rotate->center.y);
- wl_input_device_start_pointer_grab(device, &rotate->grab, time);
+ wl_pointer_start_grab(seat->pointer, &rotate->base.grab);
- dx = device->x - rotate->center.x;
- dy = device->y - rotate->center.y;
+ dx = wl_fixed_to_double(seat->pointer->x) - rotate->center.x;
+ dy = wl_fixed_to_double(seat->pointer->y) - rotate->center.y;
r = sqrtf(dx * dx + dy * dy);
if (r > 20.0f) {
struct weston_matrix inverse;
inverse.d[1] = -inverse.d[4];
inverse.d[5] = inverse.d[0];
weston_matrix_multiply(&surface->rotation.rotation, &inverse);
+
+ weston_matrix_init(&rotate->rotation);
+ rotate->rotation.d[0] = dx / r;
+ rotate->rotation.d[4] = -dy / r;
+ rotate->rotation.d[1] = -rotate->rotation.d[4];
+ rotate->rotation.d[5] = rotate->rotation.d[0];
} else {
weston_matrix_init(&surface->rotation.rotation);
weston_matrix_init(&rotate->rotation);
}
- wl_input_device_set_pointer_focus(device, NULL, time, 0, 0);
+ wl_pointer_set_focus(seat->pointer, NULL,
+ wl_fixed_from_int(0),
+ wl_fixed_from_int(0));
}
static void
-activate(struct weston_shell *base, struct weston_surface *es,
- struct weston_input_device *device, uint32_t time)
+activate(struct desktop_shell *shell, struct weston_surface *es,
+ struct weston_seat *seat)
{
- struct wl_shell *shell = container_of(base, struct wl_shell, shell);
- struct weston_compositor *compositor = shell->compositor;
+ struct weston_surface *surf, *prev;
- weston_surface_activate(es, device, time);
-
- if (compositor->wxs)
- weston_xserver_surface_activate(es);
+ weston_surface_activate(es, seat);
switch (get_shell_surface_type(es)) {
case SHELL_SURFACE_BACKGROUND:
break;
case SHELL_SURFACE_FULLSCREEN:
/* should on top of panels */
+ shell_stack_fullscreen(get_shell_surface(es));
+ shell_configure_fullscreen(get_shell_surface(es));
break;
default:
+ /* move the fullscreen surfaces down into the toplevel layer */
+ if (!wl_list_empty(&shell->fullscreen_layer.surface_list)) {
+ wl_list_for_each_reverse_safe(surf,
+ prev,
+ &shell->fullscreen_layer.surface_list,
+ layer_link)
+ weston_surface_restack(surf,
+ &shell->toplevel_layer.surface_list);
+ }
+
weston_surface_restack(es,
&shell->toplevel_layer.surface_list);
break;
}
}
+/* no-op func for checking black surface */
static void
-click_to_activate_binding(struct wl_input_device *device,
- uint32_t time, uint32_t key,
- uint32_t button, uint32_t state, void *data)
+black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
{
- struct weston_input_device *wd = (struct weston_input_device *) device;
- struct weston_compositor *compositor = data;
+}
+
+static bool
+is_black_surface (struct weston_surface *es, struct weston_surface **fs_surface)
+{
+ if (es->configure == black_surface_configure) {
+ if (fs_surface)
+ *fs_surface = (struct weston_surface *)es->private;
+ return true;
+ }
+ return false;
+}
+
+static void
+click_to_activate_binding(struct wl_seat *seat, uint32_t time, uint32_t button,
+ void *data)
+{
+ struct weston_seat *ws = (struct weston_seat *) seat;
+ struct desktop_shell *shell = data;
struct weston_surface *focus;
struct weston_surface *upper;
- focus = (struct weston_surface *) device->pointer_focus;
+ focus = (struct weston_surface *) seat->pointer->focus;
if (!focus)
return;
- upper = container_of(focus->link.prev, struct weston_surface, link);
- if (focus->link.prev != &compositor->surface_list &&
- get_shell_surface_type(upper) == SHELL_SURFACE_FULLSCREEN) {
- printf("%s: focus is black surface, raise its fullscreen surface\n", __func__);
- shell_stack_fullscreen(get_shell_surface(upper));
+ if (is_black_surface(focus, &upper))
focus = upper;
- }
- if (state && device->pointer_grab == &device->default_pointer_grab)
- activate(compositor->shell, focus, wd, time);
+ if (seat->pointer->grab == &seat->pointer->default_grab)
+ activate(shell, focus, ws);
}
static void
-lock(struct weston_shell *base)
+lock(struct wl_listener *listener, void *data)
{
- struct wl_shell *shell = container_of(base, struct wl_shell, shell);
- struct weston_input_device *device;
+ struct desktop_shell *shell =
+ container_of(listener, struct desktop_shell, lock_listener);
+ struct weston_seat *seat;
struct shell_surface *shsurf;
struct weston_output *output;
- uint32_t time;
if (shell->locked) {
wl_list_for_each(output, &shell->compositor->output_list, link)
weston_compositor_schedule_repaint(shell->compositor);
/* reset keyboard foci */
- time = weston_compositor_get_time();
- wl_list_for_each(device, &shell->compositor->input_device_list, link) {
- wl_input_device_set_keyboard_focus(&device->input_device,
- NULL, time);
+ wl_list_for_each(seat, &shell->compositor->seat_list, link) {
+ wl_keyboard_set_focus(seat->seat.keyboard, NULL);
}
/* TODO: disable bindings that should not work while locked. */
}
static void
-unlock(struct weston_shell *base)
+unlock(struct wl_listener *listener, void *data)
{
- struct wl_shell *shell = container_of(base, struct wl_shell, shell);
+ struct desktop_shell *shell =
+ container_of(listener, struct desktop_shell, unlock_listener);
if (!shell->locked || shell->lock_surface) {
weston_compositor_wake(shell->compositor);
}
static void
-map(struct weston_shell *base, struct weston_surface *surface,
+map(struct desktop_shell *shell, struct weston_surface *surface,
int32_t width, int32_t height, int32_t sx, int32_t sy)
{
- struct wl_shell *shell = container_of(base, struct wl_shell, shell);
struct weston_compositor *compositor = shell->compositor;
struct shell_surface *shsurf;
enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
struct weston_surface *parent;
+ struct weston_seat *seat;
int panel_height = 0;
shsurf = get_shell_surface(surface);
surface->geometry.height = height;
surface->geometry.dirty = 1;
- weston_compositor_update_drag_surfaces(compositor);
-
/* initial positioning, see also configure() */
switch (surface_type) {
case SHELL_SURFACE_TOPLEVEL:
center_on_output(surface, get_default_output(compositor));
break;
case SHELL_SURFACE_POPUP:
- shell_map_popup(shsurf, shsurf->popup.time);
+ shell_map_popup(shsurf);
case SHELL_SURFACE_NONE:
weston_surface_set_position(surface,
surface->geometry.x + sx,
}
switch (surface_type) {
- case SHELL_SURFACE_TOPLEVEL:
case SHELL_SURFACE_TRANSIENT:
+ if (shsurf->transient.flags ==
+ WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
+ break;
+ case SHELL_SURFACE_TOPLEVEL:
case SHELL_SURFACE_FULLSCREEN:
case SHELL_SURFACE_MAXIMIZED:
- if (!shell->locked)
- activate(base, surface,
- (struct weston_input_device *)
- compositor->input_device,
- weston_compositor_get_time());
+ if (!shell->locked) {
+ wl_list_for_each(seat, &compositor->seat_list, link)
+ activate(shell, surface, seat);
+ }
break;
default:
break;
}
if (surface_type == SHELL_SURFACE_TOPLEVEL)
- weston_zoom_run(surface, 0.8, 1.0, NULL, NULL);
+ {
+ switch (shell->win_animation_type) {
+ case ANIMATION_FADE:
+ weston_fade_run(surface, NULL, NULL);
+ break;
+ case ANIMATION_ZOOM:
+ weston_zoom_run(surface, 0.8, 1.0, NULL, NULL);
+ break;
+ default:
+ break;
+ }
+ }
}
static void
-configure(struct weston_shell *base, struct weston_surface *surface,
+configure(struct desktop_shell *shell, struct weston_surface *surface,
GLfloat x, GLfloat y, int32_t width, int32_t height)
{
- struct wl_shell *shell = container_of(base, struct wl_shell, shell);
enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
- enum shell_surface_type prev_surface_type = SHELL_SURFACE_NONE;
struct shell_surface *shsurf;
shsurf = get_shell_surface(surface);
center_on_output(surface, shsurf->fullscreen_output);
break;
case SHELL_SURFACE_FULLSCREEN:
+ shell_stack_fullscreen(shsurf);
shell_configure_fullscreen(shsurf);
- if (prev_surface_type != SHELL_SURFACE_FULLSCREEN)
- shell_stack_fullscreen(shsurf);
break;
case SHELL_SURFACE_MAXIMIZED:
/* setting x, y and using configure to change that geometry */
}
}
-static int launch_desktop_shell_process(struct wl_shell *shell);
+static void
+shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
+{
+ struct shell_surface *shsurf = get_shell_surface(es);
+ struct desktop_shell *shell = shsurf->shell;
+ int type_changed = 0;
+
+ if (shsurf->next_type != SHELL_SURFACE_NONE &&
+ shsurf->type != shsurf->next_type) {
+ set_surface_type(shsurf);
+ type_changed = 1;
+ }
+
+ if (!weston_surface_is_mapped(es)) {
+ map(shell, es, es->buffer->width, es->buffer->height, sx, sy);
+ } else if (type_changed || sx != 0 || sy != 0 ||
+ es->geometry.width != es->buffer->width ||
+ es->geometry.height != es->buffer->height) {
+ GLfloat from_x, from_y;
+ GLfloat to_x, to_y;
+
+ weston_surface_to_global_float(es, 0, 0, &from_x, &from_y);
+ weston_surface_to_global_float(es, sx, sy, &to_x, &to_y);
+ configure(shell, es,
+ es->geometry.x + to_x - from_x,
+ es->geometry.y + to_y - from_y,
+ es->buffer->width, es->buffer->height);
+ }
+}
+
+static int launch_desktop_shell_process(struct desktop_shell *shell);
static void
desktop_shell_sigchld(struct weston_process *process, int status)
{
uint32_t time;
- struct wl_shell *shell =
- container_of(process, struct wl_shell, child.process);
+ struct desktop_shell *shell =
+ container_of(process, struct desktop_shell, child.process);
shell->child.process.pid = 0;
shell->child.client = NULL; /* already destroyed by wayland */
shell->child.deathcount++;
if (shell->child.deathcount > 5) {
- fprintf(stderr, "weston-desktop-shell died, giving up.\n");
+ weston_log("weston-desktop-shell died, giving up.\n");
return;
}
- fprintf(stderr, "weston-desktop-shell died, respawning...\n");
+ weston_log("weston-desktop-shell died, respawning...\n");
launch_desktop_shell_process(shell);
}
static int
-launch_desktop_shell_process(struct wl_shell *shell)
+launch_desktop_shell_process(struct desktop_shell *shell)
{
const char *shell_exe = LIBEXECDIR "/weston-desktop-shell";
static void
bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
{
- struct wl_shell *shell = data;
+ struct desktop_shell *shell = data;
wl_client_add_object(client, &wl_shell_interface,
&shell_implementation, id, shell);
static void
unbind_desktop_shell(struct wl_resource *resource)
{
- struct wl_shell *shell = resource->data;
+ struct desktop_shell *shell = resource->data;
if (shell->locked)
resume_desktop(shell);
bind_desktop_shell(struct wl_client *client,
void *data, uint32_t version, uint32_t id)
{
- struct wl_shell *shell = data;
+ struct desktop_shell *shell = data;
struct wl_resource *resource;
resource = wl_client_add_object(client, &desktop_shell_interface,
wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
"permission to bind desktop_shell denied");
- wl_resource_destroy(resource, 0);
+ wl_resource_destroy(resource);
}
static void
struct wl_resource *shell_surface_resource,
struct wl_resource *output_resource)
{
- struct wl_shell *shell = resource->data;
+ struct desktop_shell *shell = resource->data;
struct shell_surface *surface = shell_surface_resource->data;
struct weston_output *output = output_resource->data;
- if (reset_shell_surface_type(surface))
- return;
-
- surface->type = SHELL_SURFACE_SCREENSAVER;
+ surface->next_type = SHELL_SURFACE_SCREENSAVER;
surface->fullscreen_output = output;
surface->output = output;
static void
unbind_screensaver(struct wl_resource *resource)
{
- struct wl_shell *shell = resource->data;
+ struct desktop_shell *shell = resource->data;
shell->screensaver.binding = NULL;
free(resource);
bind_screensaver(struct wl_client *client,
void *data, uint32_t version, uint32_t id)
{
- struct wl_shell *shell = data;
+ struct desktop_shell *shell = data;
struct wl_resource *resource;
resource = wl_client_add_object(client, &screensaver_interface,
wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
"interface object already bound");
- wl_resource_destroy(resource, 0);
+ wl_resource_destroy(resource);
}
struct switcher {
- struct weston_compositor *compositor;
+ struct desktop_shell *shell;
struct weston_surface *current;
struct wl_listener listener;
struct wl_keyboard_grab grab;
static void
switcher_next(struct switcher *switcher)
{
- struct weston_compositor *compositor = switcher->compositor;
+ struct weston_compositor *compositor = switcher->shell->compositor;
struct weston_surface *surface;
struct weston_surface *first = NULL, *prev = NULL, *next = NULL;
+ struct shell_surface *shsurf;
wl_list_for_each(surface, &compositor->surface_list, link) {
- /* Workaround for cursor surfaces. */
- if (surface->surface.resource.destroy_listener_list.next == NULL)
- continue;
-
switch (get_shell_surface_type(surface)) {
case SHELL_SURFACE_TOPLEVEL:
case SHELL_SURFACE_FULLSCREEN:
if (prev == switcher->current)
next = surface;
prev = surface;
- surface->alpha = 64;
+ surface->alpha = 0.25;
surface->geometry.dirty = 1;
weston_surface_damage(surface);
break;
default:
break;
}
+
+ if (is_black_surface(surface, NULL)) {
+ surface->alpha = 0.25;
+ surface->geometry.dirty = 1;
+ weston_surface_damage(surface);
+ }
}
if (next == NULL)
next = first;
+ if (next == NULL)
+ return;
+
wl_list_remove(&switcher->listener.link);
- wl_list_insert(next->surface.resource.destroy_listener_list.prev,
- &switcher->listener.link);
+ wl_signal_add(&next->surface.resource.destroy_signal,
+ &switcher->listener);
switcher->current = next;
- next->alpha = 255;
+ next->alpha = 1.0;
+
+ shsurf = get_shell_surface(switcher->current);
+ if (shsurf && shsurf->type ==SHELL_SURFACE_FULLSCREEN)
+ shsurf->fullscreen.black_surface->alpha = 1.0;
}
static void
-switcher_handle_surface_destroy(struct wl_listener *listener,
- struct wl_resource *resource, uint32_t time)
+switcher_handle_surface_destroy(struct wl_listener *listener, void *data)
{
struct switcher *switcher =
container_of(listener, struct switcher, listener);
}
static void
-switcher_destroy(struct switcher *switcher, uint32_t time)
+switcher_destroy(struct switcher *switcher)
{
- struct weston_compositor *compositor = switcher->compositor;
+ struct weston_compositor *compositor = switcher->shell->compositor;
struct weston_surface *surface;
- struct weston_input_device *device =
- (struct weston_input_device *) switcher->grab.input_device;
+ struct wl_keyboard *keyboard = switcher->grab.keyboard;
wl_list_for_each(surface, &compositor->surface_list, link) {
- surface->alpha = 255;
+ surface->alpha = 1.0;
weston_surface_damage(surface);
}
- activate(compositor->shell, switcher->current, device, time);
+ if (switcher->current)
+ activate(switcher->shell, switcher->current,
+ (struct weston_seat *) keyboard->seat);
wl_list_remove(&switcher->listener.link);
- wl_input_device_end_keyboard_grab(&device->input_device, time);
+ wl_keyboard_end_grab(keyboard);
free(switcher);
}
static void
switcher_key(struct wl_keyboard_grab *grab,
- uint32_t time, uint32_t key, int32_t state)
+ uint32_t time, uint32_t key, uint32_t state_w)
{
struct switcher *switcher = container_of(grab, struct switcher, grab);
- struct weston_input_device *device =
- (struct weston_input_device *) grab->input_device;
+ enum wl_keyboard_key_state state = state_w;
- if ((device->modifier_state & MODIFIER_SUPER) == 0) {
- switcher_destroy(switcher, time);
- } else if (key == KEY_TAB && state) {
+ if (key == KEY_TAB && state == WL_KEYBOARD_KEY_STATE_PRESSED)
switcher_next(switcher);
- }
-};
+}
+
+static void
+switcher_modifier(struct wl_keyboard_grab *grab, uint32_t serial,
+ uint32_t mods_depressed, uint32_t mods_latched,
+ uint32_t mods_locked, uint32_t group)
+{
+ struct switcher *switcher = container_of(grab, struct switcher, grab);
+ struct weston_seat *seat = (struct weston_seat *) grab->keyboard->seat;
+
+ if ((seat->modifier_state & switcher->shell->binding_modifier) == 0)
+ switcher_destroy(switcher);
+}
static const struct wl_keyboard_grab_interface switcher_grab = {
- switcher_key
+ switcher_key,
+ switcher_modifier,
};
static void
-switcher_binding(struct wl_input_device *device, uint32_t time,
- uint32_t key, uint32_t button,
- uint32_t state, void *data)
+switcher_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
+ void *data)
{
- struct weston_compositor *compositor = data;
+ struct desktop_shell *shell = data;
struct switcher *switcher;
switcher = malloc(sizeof *switcher);
- switcher->compositor = compositor;
+ switcher->shell = shell;
switcher->current = NULL;
- switcher->listener.func = switcher_handle_surface_destroy;
+ switcher->listener.notify = switcher_handle_surface_destroy;
wl_list_init(&switcher->listener.link);
switcher->grab.interface = &switcher_grab;
- wl_input_device_start_keyboard_grab(device, &switcher->grab, time);
- wl_input_device_set_keyboard_focus(device, NULL,
- weston_compositor_get_time());
+ wl_keyboard_start_grab(seat->keyboard, &switcher->grab);
+ wl_keyboard_set_focus(seat->keyboard, NULL);
switcher_next(switcher);
}
static void
-backlight_binding(struct wl_input_device *device, uint32_t time,
- uint32_t key, uint32_t button, uint32_t state, void *data)
+backlight_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
+ void *data)
{
struct weston_compositor *compositor = data;
struct weston_output *output;
+ long backlight_new = 0;
/* TODO: we're limiting to simple use cases, where we assume just
* control on the primary display. We'd have to extend later if we
if (!output->set_backlight)
return;
- if ((key == KEY_F9 || key == KEY_BRIGHTNESSDOWN) &&
- output->backlight_current > 1)
- output->backlight_current--;
- else if ((key == KEY_F10 || key == KEY_BRIGHTNESSUP) &&
- output->backlight_current < 10)
- output->backlight_current++;
+ if (key == KEY_F9 || key == KEY_BRIGHTNESSDOWN)
+ backlight_new = output->backlight_current - 25;
+ else if (key == KEY_F10 || key == KEY_BRIGHTNESSUP)
+ backlight_new = output->backlight_current + 25;
+ if (backlight_new < 5)
+ backlight_new = 5;
+ if (backlight_new > 255)
+ backlight_new = 255;
+
+ output->backlight_current = backlight_new;
output->set_backlight(output, output->backlight_current);
}
static void
-debug_repaint_binding(struct wl_input_device *device, uint32_t time,
- uint32_t key, uint32_t button, uint32_t state, void *data)
+debug_repaint_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
+ void *data)
{
- struct weston_compositor *compositor = data;
- struct wl_shell *shell =
- container_of(compositor->shell, struct wl_shell, shell);
+ struct desktop_shell *shell = data;
+ struct weston_compositor *compositor = shell->compositor;
struct weston_surface *surface;
if (shell->debug_repaint_surface) {
}
static void
-shell_destroy(struct weston_shell *base)
+force_kill_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
+ void *data)
{
- struct wl_shell *shell = container_of(base, struct wl_shell, shell);
+ struct wl_client *client;
+ pid_t pid;
+ uid_t uid;
+ gid_t gid;
+
+ client = seat->keyboard->focus->resource.client;
+ wl_client_get_credentials(client, &pid, &uid, &gid);
+
+ kill(pid, SIGKILL);
+}
+
+static void
+shell_destroy(struct wl_listener *listener, void *data)
+{
+ struct desktop_shell *shell =
+ container_of(listener, struct desktop_shell, destroy_listener);
if (shell->child.client)
wl_client_destroy(shell->child.client);
+ wl_list_remove(&shell->lock_listener.link);
+ wl_list_remove(&shell->unlock_listener.link);
+
free(shell->screensaver.path);
free(shell);
}
+static void
+shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
+{
+ uint32_t mod;
+
+ /* fixed bindings */
+ weston_compositor_add_key_binding(ec, KEY_BACKSPACE,
+ MODIFIER_CTRL | MODIFIER_ALT,
+ terminate_binding, ec);
+ weston_compositor_add_button_binding(ec, BTN_LEFT, 0,
+ click_to_activate_binding,
+ shell);
+ weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
+ MODIFIER_SUPER | MODIFIER_ALT,
+ surface_opacity_binding, NULL);
+ weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
+ MODIFIER_SUPER, zoom_axis_binding,
+ NULL);
+
+ /* configurable bindings */
+ mod = shell->binding_modifier;
+ weston_compositor_add_key_binding(ec, KEY_PAGEUP, mod,
+ zoom_key_binding, NULL);
+ weston_compositor_add_key_binding(ec, KEY_PAGEDOWN, mod,
+ zoom_key_binding, NULL);
+ weston_compositor_add_button_binding(ec, BTN_LEFT, mod, move_binding,
+ shell);
+ weston_compositor_add_button_binding(ec, BTN_MIDDLE, mod,
+ resize_binding, shell);
+ weston_compositor_add_button_binding(ec, BTN_RIGHT, mod,
+ rotate_binding, NULL);
+ weston_compositor_add_key_binding(ec, KEY_TAB, mod, switcher_binding,
+ shell);
+ weston_compositor_add_key_binding(ec, KEY_F9, mod, backlight_binding,
+ ec);
+ weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSDOWN, 0,
+ backlight_binding, ec);
+ weston_compositor_add_key_binding(ec, KEY_F10, mod, backlight_binding,
+ ec);
+ weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSUP, 0,
+ backlight_binding, ec);
+ weston_compositor_add_key_binding(ec, KEY_SPACE, mod,
+ debug_repaint_binding, shell);
+ weston_compositor_add_key_binding(ec, KEY_K, mod,
+ force_kill_binding, shell);
+}
+
int
shell_init(struct weston_compositor *ec);
WL_EXPORT int
shell_init(struct weston_compositor *ec)
{
- struct wl_shell *shell;
+ struct desktop_shell *shell;
shell = malloc(sizeof *shell);
if (shell == NULL)
memset(shell, 0, sizeof *shell);
shell->compositor = ec;
- shell->shell.lock = lock;
- shell->shell.unlock = unlock;
- shell->shell.map = map;
- shell->shell.configure = configure;
- shell->shell.destroy = shell_destroy;
+
+ shell->destroy_listener.notify = shell_destroy;
+ wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
+ shell->lock_listener.notify = lock;
+ wl_signal_add(&ec->lock_signal, &shell->lock_listener);
+ shell->unlock_listener.notify = unlock;
+ wl_signal_add(&ec->unlock_signal, &shell->unlock_listener);
+ ec->ping_handler = ping_handler;
+ ec->shell_interface.create_shell_surface = create_shell_surface;
+ ec->shell_interface.set_toplevel = set_toplevel;
+ ec->shell_interface.set_transient = set_transient;
+ ec->shell_interface.move = surface_move;
+ ec->shell_interface.resize = surface_resize;
wl_list_init(&shell->backgrounds);
wl_list_init(&shell->panels);
if (launch_desktop_shell_process(shell) != 0)
return -1;
- weston_compositor_add_binding(ec, 0, BTN_LEFT, MODIFIER_SUPER,
- move_binding, shell);
- weston_compositor_add_binding(ec, 0, BTN_MIDDLE, MODIFIER_SUPER,
- resize_binding, shell);
- weston_compositor_add_binding(ec, KEY_BACKSPACE, 0,
- MODIFIER_CTRL | MODIFIER_ALT,
- terminate_binding, ec);
- weston_compositor_add_binding(ec, 0, BTN_LEFT, 0,
- click_to_activate_binding, ec);
- weston_compositor_add_binding(ec, KEY_UP, 0, MODIFIER_SUPER,
- zoom_binding, shell);
- weston_compositor_add_binding(ec, KEY_DOWN, 0, MODIFIER_SUPER,
- zoom_binding, shell);
- weston_compositor_add_binding(ec, 0, BTN_LEFT,
- MODIFIER_SUPER | MODIFIER_ALT,
- rotate_binding, NULL);
- weston_compositor_add_binding(ec, KEY_TAB, 0, MODIFIER_SUPER,
- switcher_binding, ec);
-
- /* brightness */
- weston_compositor_add_binding(ec, KEY_F9, 0, MODIFIER_CTRL,
- backlight_binding, ec);
- weston_compositor_add_binding(ec, KEY_BRIGHTNESSDOWN, 0, 0,
- backlight_binding, ec);
- weston_compositor_add_binding(ec, KEY_F10, 0, MODIFIER_CTRL,
- backlight_binding, ec);
- weston_compositor_add_binding(ec, KEY_BRIGHTNESSUP, 0, 0,
- backlight_binding, ec);
-
- weston_compositor_add_binding(ec, KEY_SPACE, 0, MODIFIER_SUPER,
- debug_repaint_binding, ec);
-
- ec->shell = &shell->shell;
+ shell->pointer_focus_listener.notify = handle_pointer_focus;
+ if (ec->seat->seat.pointer)
+ wl_signal_add(&ec->seat->seat.pointer->focus_signal,
+ &shell->pointer_focus_listener);
+
+ shell_add_bindings(ec, shell);
return 0;
}