The tablet-shell is unmaintained and unused. It is currently dead-weight and a burden when we make changes to weston. Let's drop it for now, we can pull it out of git if we find a need for it later.dev
parent
cae1f0ff2d
commit
873b515aee
@ -1,478 +0,0 @@ |
||||
/*
|
||||
* Copyright © 2011, 2012 Intel Corporation |
||||
* |
||||
* Permission to use, copy, modify, distribute, and sell this software and its |
||||
* documentation for any purpose is hereby granted without fee, provided that |
||||
* the above copyright notice appear in all copies and that both that copyright |
||||
* notice and this permission notice appear in supporting documentation, and |
||||
* that the name of the copyright holders not be used in advertising or |
||||
* publicity pertaining to distribution of the software without specific, |
||||
* written prior permission. The copyright holders make no representations |
||||
* about the suitability of this software for any purpose. It is provided "as |
||||
* is" without express or implied warranty. |
||||
* |
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE |
||||
* OF THIS SOFTWARE. |
||||
*/ |
||||
|
||||
#include <stdint.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <unistd.h> |
||||
#include <sys/wait.h> |
||||
|
||||
#include "window.h" |
||||
#include "../shared/cairo-util.h" |
||||
#include "../shared/config-parser.h" |
||||
|
||||
#include "tablet-shell-client-protocol.h" |
||||
|
||||
struct tablet { |
||||
struct display *display; |
||||
struct tablet_shell *tablet_shell; |
||||
struct rectangle allocation; |
||||
struct window *switcher; |
||||
|
||||
struct homescreen *homescreen; |
||||
struct lockscreen *lockscreen; |
||||
}; |
||||
|
||||
struct homescreen { |
||||
struct window *window; |
||||
struct widget *widget; |
||||
struct wl_list launcher_list; |
||||
}; |
||||
|
||||
struct lockscreen { |
||||
struct window *window; |
||||
struct widget *widget; |
||||
}; |
||||
|
||||
struct launcher { |
||||
struct widget *widget; |
||||
struct homescreen *homescreen; |
||||
cairo_surface_t *icon; |
||||
int focused, pressed; |
||||
char *path; |
||||
struct wl_list link; |
||||
}; |
||||
|
||||
static char *key_lockscreen_icon; |
||||
static char *key_lockscreen_background; |
||||
static char *key_homescreen_background; |
||||
|
||||
static void |
||||
sigchild_handler(int s) |
||||
{ |
||||
int status; |
||||
pid_t pid; |
||||
|
||||
while (pid = waitpid(-1, &status, WNOHANG), pid > 0) |
||||
fprintf(stderr, "child %d exited\n", pid); |
||||
} |
||||
|
||||
static void |
||||
paint_background(cairo_t *cr, const char *path, struct rectangle *allocation) |
||||
{ |
||||
cairo_surface_t *image = NULL; |
||||
cairo_pattern_t *pattern; |
||||
cairo_matrix_t matrix; |
||||
double sx, sy; |
||||
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); |
||||
if (path) |
||||
image = load_cairo_surface(path); |
||||
if (image) { |
||||
pattern = cairo_pattern_create_for_surface(image); |
||||
sx = (double) cairo_image_surface_get_width(image) / |
||||
allocation->width; |
||||
sy = (double) cairo_image_surface_get_height(image) / |
||||
allocation->height; |
||||
cairo_matrix_init_scale(&matrix, sx, sy); |
||||
cairo_pattern_set_matrix(pattern, &matrix); |
||||
cairo_set_source(cr, pattern); |
||||
cairo_pattern_destroy (pattern); |
||||
cairo_surface_destroy(image); |
||||
cairo_paint(cr); |
||||
} else { |
||||
fprintf(stderr, "couldn't load background image: %s\n", path); |
||||
cairo_set_source_rgb(cr, 0.2, 0, 0); |
||||
cairo_paint(cr); |
||||
} |
||||
} |
||||
|
||||
static void |
||||
homescreen_draw(struct widget *widget, void *data) |
||||
{ |
||||
struct homescreen *homescreen = data; |
||||
cairo_surface_t *surface; |
||||
struct rectangle allocation; |
||||
cairo_t *cr; |
||||
struct launcher *launcher; |
||||
const int rows = 4, columns = 5, icon_width = 128, icon_height = 128; |
||||
int x, y, i, width, height, vmargin, hmargin, vpadding, hpadding; |
||||
|
||||
surface = window_get_surface(homescreen->window); |
||||
cr = cairo_create(surface); |
||||
|
||||
widget_get_allocation(widget, &allocation); |
||||
paint_background(cr, key_homescreen_background, &allocation); |
||||
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_OVER); |
||||
|
||||
width = allocation.width - columns * icon_width; |
||||
hpadding = width / (columns + 1); |
||||
hmargin = (width - hpadding * (columns - 1)) / 2; |
||||
|
||||
height = allocation.height - rows * icon_height; |
||||
vpadding = height / (rows + 1); |
||||
vmargin = (height - vpadding * (rows - 1)) / 2; |
||||
|
||||
x = hmargin; |
||||
y = vmargin; |
||||
i = 0; |
||||
|
||||
wl_list_for_each(launcher, &homescreen->launcher_list, link) { |
||||
widget_set_allocation(launcher->widget, |
||||
x, y, icon_width, icon_height); |
||||
x += icon_width + hpadding; |
||||
i++; |
||||
if (i == columns) { |
||||
x = hmargin; |
||||
y += icon_height + vpadding; |
||||
i = 0; |
||||
} |
||||
} |
||||
|
||||
cairo_destroy(cr); |
||||
cairo_surface_destroy(surface); |
||||
} |
||||
|
||||
static void |
||||
lockscreen_draw(struct widget *widget, void *data) |
||||
{ |
||||
struct lockscreen *lockscreen = data; |
||||
cairo_surface_t *surface; |
||||
cairo_surface_t *icon; |
||||
struct rectangle allocation; |
||||
cairo_t *cr; |
||||
int width, height; |
||||
|
||||
surface = window_get_surface(lockscreen->window); |
||||
cr = cairo_create(surface); |
||||
|
||||
widget_get_allocation(widget, &allocation); |
||||
paint_background(cr, key_lockscreen_background, &allocation); |
||||
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_OVER); |
||||
icon = load_cairo_surface(key_lockscreen_icon); |
||||
if (icon) { |
||||
width = cairo_image_surface_get_width(icon); |
||||
height = cairo_image_surface_get_height(icon); |
||||
cairo_set_source_surface(cr, icon, |
||||
allocation.x + (allocation.width - width) / 2, |
||||
allocation.y + (allocation.height - height) / 2); |
||||
} else { |
||||
fprintf(stderr, "couldn't load lockscreen icon: %s\n", |
||||
key_lockscreen_icon); |
||||
cairo_set_source_rgb(cr, 0.2, 0, 0); |
||||
} |
||||
cairo_paint(cr); |
||||
cairo_destroy(cr); |
||||
cairo_surface_destroy(icon); |
||||
cairo_surface_destroy(surface); |
||||
} |
||||
|
||||
static void |
||||
lockscreen_button_handler(struct widget *widget, |
||||
struct input *input, uint32_t time, |
||||
uint32_t button, |
||||
enum wl_pointer_button_state state, void *data) |
||||
{ |
||||
struct lockscreen *lockscreen = data; |
||||
|
||||
if (state == WL_POINTER_BUTTON_STATE_PRESSED && lockscreen->window) { |
||||
window_destroy(lockscreen->window); |
||||
lockscreen->window = NULL; |
||||
} |
||||
} |
||||
|
||||
static struct homescreen * |
||||
homescreen_create(struct tablet *tablet) |
||||
{ |
||||
struct homescreen *homescreen; |
||||
|
||||
homescreen = zalloc (sizeof *homescreen); |
||||
homescreen->window = window_create_custom(tablet->display); |
||||
homescreen->widget = |
||||
window_add_widget(homescreen->window, homescreen); |
||||
window_set_user_data(homescreen->window, homescreen); |
||||
window_set_title(homescreen->window, "homescreen"); |
||||
widget_set_redraw_handler(homescreen->widget, homescreen_draw); |
||||
|
||||
return homescreen; |
||||
} |
||||
|
||||
static struct lockscreen * |
||||
lockscreen_create(struct tablet *tablet) |
||||
{ |
||||
struct lockscreen *lockscreen; |
||||
|
||||
lockscreen = zalloc (sizeof *lockscreen); |
||||
lockscreen->window = window_create_custom(tablet->display); |
||||
lockscreen->widget = |
||||
window_add_widget(lockscreen->window, lockscreen); |
||||
window_set_user_data(lockscreen->window, lockscreen); |
||||
window_set_title(lockscreen->window, "lockscreen"); |
||||
widget_set_redraw_handler(lockscreen->widget, lockscreen_draw); |
||||
widget_set_button_handler(lockscreen->widget, |
||||
lockscreen_button_handler); |
||||
|
||||
return lockscreen; |
||||
} |
||||
|
||||
static void |
||||
show_lockscreen(void *data, struct tablet_shell *tablet_shell) |
||||
{ |
||||
struct tablet *tablet = data; |
||||
|
||||
tablet->lockscreen = lockscreen_create(tablet); |
||||
tablet_shell_set_lockscreen(tablet->tablet_shell, |
||||
window_get_wl_surface(tablet->lockscreen->window)); |
||||
|
||||
widget_schedule_resize(tablet->lockscreen->widget, |
||||
tablet->allocation.width, |
||||
tablet->allocation.height); |
||||
} |
||||
|
||||
static void |
||||
show_switcher(void *data, struct tablet_shell *tablet_shell) |
||||
{ |
||||
struct tablet *tablet = data; |
||||
|
||||
tablet->switcher = window_create_custom(tablet->display); |
||||
window_set_user_data(tablet->switcher, tablet); |
||||
tablet_shell_set_switcher(tablet->tablet_shell, |
||||
window_get_wl_surface(tablet->switcher)); |
||||
} |
||||
|
||||
static void |
||||
hide_switcher(void *data, struct tablet_shell *tablet_shell) |
||||
{ |
||||
} |
||||
|
||||
static const struct tablet_shell_listener tablet_shell_listener = { |
||||
show_lockscreen, |
||||
show_switcher, |
||||
hide_switcher |
||||
}; |
||||
|
||||
static int |
||||
launcher_enter_handler(struct widget *widget, struct input *input, |
||||
float x, float y, void *data) |
||||
{ |
||||
struct launcher *launcher = data; |
||||
|
||||
launcher->focused = 1; |
||||
widget_schedule_redraw(widget); |
||||
|
||||
return CURSOR_LEFT_PTR; |
||||
} |
||||
|
||||
static void |
||||
launcher_leave_handler(struct widget *widget, |
||||
struct input *input, void *data) |
||||
{ |
||||
struct launcher *launcher = data; |
||||
|
||||
launcher->focused = 0; |
||||
widget_schedule_redraw(widget); |
||||
} |
||||
|
||||
static void |
||||
launcher_activate(struct launcher *widget) |
||||
{ |
||||
pid_t pid; |
||||
|
||||
pid = fork(); |
||||
if (pid < 0) { |
||||
fprintf(stderr, "fork failed: %m\n"); |
||||
return; |
||||
} |
||||
|
||||
if (pid) |
||||
return; |
||||
|
||||
if (execl(widget->path, widget->path, NULL) < 0) { |
||||
fprintf(stderr, "execl '%s' failed: %m\n", widget->path); |
||||
exit(1); |
||||
} |
||||
} |
||||
|
||||
static void |
||||
launcher_button_handler(struct widget *widget, |
||||
struct input *input, uint32_t time, |
||||
uint32_t button, |
||||
enum wl_pointer_button_state state, void *data) |
||||
{ |
||||
struct launcher *launcher; |
||||
|
||||
launcher = widget_get_user_data(widget); |
||||
widget_schedule_redraw(widget); |
||||
if (state == WL_POINTER_BUTTON_STATE_RELEASED) { |
||||
launcher_activate(launcher); |
||||
launcher->pressed = 0; |
||||
} else if (state == WL_POINTER_BUTTON_STATE_PRESSED)
|
||||
launcher->pressed = 1; |
||||
} |
||||
|
||||
static void |
||||
launcher_redraw_handler(struct widget *widget, void *data) |
||||
{ |
||||
struct launcher *launcher = data; |
||||
cairo_surface_t *surface; |
||||
struct rectangle allocation; |
||||
cairo_t *cr; |
||||
|
||||
surface = window_get_surface(launcher->homescreen->window); |
||||
cr = cairo_create(surface); |
||||
|
||||
widget_get_allocation(widget, &allocation); |
||||
if (launcher->pressed) { |
||||
allocation.x++; |
||||
allocation.y++; |
||||
} |
||||
|
||||
cairo_set_source_surface(cr, launcher->icon, |
||||
allocation.x, allocation.y); |
||||
cairo_paint(cr); |
||||
|
||||
if (launcher->focused) { |
||||
cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4); |
||||
cairo_mask_surface(cr, launcher->icon, |
||||
allocation.x, allocation.y); |
||||
} |
||||
|
||||
cairo_destroy(cr); |
||||
} |
||||
|
||||
static void |
||||
tablet_shell_add_launcher(struct tablet *tablet, |
||||
const char *icon, const char *path) |
||||
{ |
||||
struct launcher *launcher; |
||||
struct homescreen *homescreen = tablet->homescreen; |
||||
|
||||
launcher = xmalloc(sizeof *launcher); |
||||
launcher->icon = load_cairo_surface(icon); |
||||
if ( !launcher->icon || |
||||
cairo_surface_status (launcher->icon) != CAIRO_STATUS_SUCCESS) { |
||||
fprintf(stderr, "couldn't load %s\n", icon); |
||||
free(launcher); |
||||
return; |
||||
} |
||||
launcher->path = strdup(path); |
||||
|
||||
launcher->homescreen = homescreen; |
||||
launcher->widget = widget_add_widget(homescreen->widget, launcher); |
||||
widget_set_enter_handler(launcher->widget, |
||||
launcher_enter_handler); |
||||
widget_set_leave_handler(launcher->widget, |
||||
launcher_leave_handler); |
||||
widget_set_button_handler(launcher->widget, |
||||
launcher_button_handler); |
||||
widget_set_redraw_handler(launcher->widget, |
||||
launcher_redraw_handler); |
||||
|
||||
wl_list_insert(&homescreen->launcher_list, &launcher->link); |
||||
} |
||||
|
||||
static void |
||||
global_handler(struct display *display, uint32_t name, |
||||
const char *interface, uint32_t version, void *data) |
||||
{ |
||||
struct tablet *tablet = data; |
||||
|
||||
if (!strcmp(interface, "tablet_shell")) { |
||||
tablet->tablet_shell = |
||||
display_bind(display, name, |
||||
&tablet_shell_interface, 1); |
||||
tablet_shell_add_listener(tablet->tablet_shell, |
||||
&tablet_shell_listener, tablet); |
||||
} |
||||
} |
||||
|
||||
int main(int argc, char *argv[]) |
||||
{ |
||||
struct tablet tablet = { 0 }; |
||||
struct display *display; |
||||
struct output *output; |
||||
struct weston_config *config; |
||||
struct weston_config_section *s; |
||||
char *icon, *path; |
||||
const char *name; |
||||
|
||||
display = display_create(&argc, argv); |
||||
if (display == NULL) { |
||||
fprintf(stderr, "failed to create display: %m\n"); |
||||
return -1; |
||||
} |
||||
|
||||
tablet.display = display; |
||||
|
||||
display_set_user_data(tablet.display, &tablet); |
||||
display_set_global_handler(tablet.display, global_handler); |
||||
|
||||
tablet.homescreen = homescreen_create(&tablet); |
||||
tablet_shell_set_homescreen(tablet.tablet_shell, |
||||
window_get_wl_surface(tablet.homescreen->window)); |
||||
|
||||
wl_display_roundtrip (display_get_display(tablet.display)); |
||||
|
||||
wl_list_init(&tablet.homescreen->launcher_list); |
||||
|
||||
config = weston_config_parse("weston.ini"); |
||||
s = weston_config_get_section(config, "shell", NULL, NULL); |
||||
weston_config_section_get_string(s, "lockscreen-icon", |
||||
&key_lockscreen_icon, NULL); |
||||
weston_config_section_get_string(s, "lockscreen", |
||||
&key_lockscreen_background, NULL); |
||||
weston_config_section_get_string(s, "homescreen", |
||||
&key_homescreen_background, NULL); |
||||
|
||||
s = NULL; |
||||
while (weston_config_next_section(config, &s, &name)) { |
||||
if (strcmp(name, "launcher") != 0) |
||||
continue; |
||||
|
||||
weston_config_section_get_string(s, "icon", &icon, NULL); |
||||
weston_config_section_get_string(s, "path", &path, NULL); |
||||
|
||||
if (icon != NULL && path != NULL) |
||||
tablet_shell_add_launcher(&tablet, icon, path); |
||||
else |
||||
fprintf(stderr, "invalid launcher section\n"); |
||||
|
||||
free(icon); |
||||
free(path); |
||||
} |
||||
|
||||
weston_config_destroy(config); |
||||
|
||||
signal(SIGCHLD, sigchild_handler); |
||||
|
||||
output = display_get_output(tablet.display); |
||||
output_get_allocation(output, &tablet.allocation); |
||||
widget_schedule_resize(tablet.homescreen->widget, |
||||
tablet.allocation.width, |
||||
tablet.allocation.height); |
||||
display_run(display); |
||||
|
||||
return 0; |
||||
} |
@ -1,40 +0,0 @@ |
||||
<protocol name="tablet"> |
||||
|
||||
<interface name="tablet_shell" version="1"> |
||||
<request name="set_lockscreen"> |
||||
<arg name="surface" type="object" interface="wl_surface"/> |
||||
</request> |
||||
|
||||
<request name="set_switcher"> |
||||
<arg name="surface" type="object" interface="wl_surface"/> |
||||
</request> |
||||
|
||||
<request name="set_homescreen"> |
||||
<arg name="surface" type="object" interface="wl_surface"/> |
||||
</request> |
||||
|
||||
<request name="show_grid"> |
||||
<arg name="surface" type="object" interface="wl_surface"/> |
||||
</request> |
||||
|
||||
<request name="show_panels"> |
||||
<arg name="surface" type="object" interface="wl_surface"/> |
||||
</request> |
||||
|
||||
<request name="create_client"> |
||||
<arg name="id" type="new_id" interface="tablet_client"/> |
||||
<arg name="name" type="string"/> |
||||
<arg name="fd" type="fd"/> |
||||
</request> |
||||
|
||||
<event name="show_lockscreen"/> |
||||
<event name="show_switcher"/> |
||||
<event name="hide_switcher"/> |
||||
</interface> |
||||
|
||||
<interface name="tablet_client" version="1"> |
||||
<request name="destroy" type="destructor"/> |
||||
<request name="activate"/> |
||||
</interface> |
||||
|
||||
</protocol> |
@ -1,603 +0,0 @@ |
||||
/*
|
||||
* Copyright © 2011 Intel Corporation |
||||
* |
||||
* Permission to use, copy, modify, distribute, and sell this software and |
||||
* its documentation for any purpose is hereby granted without fee, provided |
||||
* that the above copyright notice appear in all copies and that both that |
||||
* copyright notice and this permission notice appear in supporting |
||||
* documentation, and that the name of the copyright holders not be used in |
||||
* advertising or publicity pertaining to distribution of the software |
||||
* without specific, written prior permission. The copyright holders make |
||||
* no representations about the suitability of this software for any |
||||
* purpose. It is provided "as is" without express or implied warranty. |
||||
* |
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS |
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY |
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER |
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF |
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
*/ |
||||
|
||||
#include "config.h" |
||||
|
||||
#include <sys/wait.h> |
||||
#include <unistd.h> |
||||
#include <stdlib.h> |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
#include <linux/input.h> |
||||
#include <assert.h> |
||||
|
||||
#include "compositor.h" |
||||
#include "tablet-shell-server-protocol.h" |
||||
|
||||
/*
|
||||
* TODO: Don't fade back from black until we've received a lockscreen |
||||
* attachment. |
||||
*/ |
||||
|
||||
enum { |
||||
STATE_STARTING, |
||||
STATE_LOCKED, |
||||
STATE_HOME, |
||||
STATE_SWITCHER, |
||||
STATE_TASK |
||||
}; |
||||
|
||||
struct tablet_shell { |
||||
struct wl_resource *resource; |
||||
|
||||
struct wl_listener lock_listener; |
||||
struct wl_listener unlock_listener; |
||||
struct wl_listener destroy_listener; |
||||
|
||||
struct weston_compositor *compositor; |
||||
struct weston_process process; |
||||
struct wl_client *client; |
||||
|
||||
struct weston_surface *surface; |
||||
|
||||
struct weston_surface *lockscreen_surface; |
||||
struct wl_listener lockscreen_listener; |
||||
struct weston_layer lockscreen_layer; |
||||
|
||||
struct weston_layer application_layer; |
||||
|
||||
struct weston_surface *home_surface; |
||||
struct weston_layer homescreen_layer; |
||||
|
||||
struct weston_surface *switcher_surface; |
||||
struct wl_listener switcher_listener; |
||||
|
||||
struct tablet_client *current_client; |
||||
|
||||
int state, previous_state; |
||||
int long_press_active; |
||||
struct wl_event_source *long_press_source; |
||||
}; |
||||
|
||||
struct tablet_client { |
||||
struct wl_resource *resource; |
||||
struct tablet_shell *shell; |
||||
struct wl_client *client; |
||||
struct weston_surface *surface; |
||||
char *name; |
||||
}; |
||||
|
||||
static void |
||||
tablet_shell_destroy(struct wl_listener *listener, void *data); |
||||
|
||||
static struct tablet_shell * |
||||
get_shell(struct weston_compositor *compositor) |
||||
{ |
||||
struct wl_listener *l; |
||||
|
||||
l = wl_signal_get(&compositor->destroy_signal, tablet_shell_destroy); |
||||
if (l) |
||||
return container_of(l, struct tablet_shell, destroy_listener); |
||||
|
||||
return NULL; |
||||
} |
||||
|
||||
static void |
||||
tablet_shell_sigchld(struct weston_process *process, int status) |
||||
{ |
||||
struct tablet_shell *shell = |
||||
container_of(process, struct tablet_shell, process); |
||||
|
||||
shell->process.pid = 0; |
||||
|
||||
weston_log("weston-tablet-shell crashed, exit code %d\n", status); |
||||
} |
||||
|
||||
static void |
||||
tablet_shell_set_state(struct tablet_shell *shell, int state) |
||||
{ |
||||
static const char *states[] = { |
||||
"STARTING", "LOCKED", "HOME", "SWITCHER", "TASK" |
||||
}; |
||||
|
||||
weston_log("switching to state %s (from %s)\n", |
||||
states[state], states[shell->state]); |
||||
shell->previous_state = shell->state; |
||||
shell->state = state; |
||||
} |
||||
|
||||
static struct weston_view * |
||||
get_surface_view(struct weston_surface *surface, int create) |
||||
{ |
||||
if (!surface) |
||||
return NULL; |
||||
|
||||
if (wl_list_empty(&surface->views)) { |
||||
if (create) |
||||
return weston_view_create(surface); |
||||
else |
||||
return NULL; |
||||
} |
||||
|
||||
return container_of(surface->views.next, struct weston_view, surface_link); |
||||
} |
||||
|
||||
static void |
||||
tablet_shell_surface_configure(struct weston_surface *surface, |
||||
int32_t sx, int32_t sy) |
||||
{ |
||||
struct tablet_shell *shell = get_shell(surface->compositor); |
||||
struct weston_view *view = get_surface_view(surface, 0); |
||||
assert(view); |
||||
|
||||
if (weston_surface_is_mapped(surface) || surface->width == 0) |
||||
return; |
||||
|
||||
if (surface == shell->lockscreen_surface) { |
||||
wl_list_insert(&shell->lockscreen_layer.view_list, |
||||
&view->layer_link); |
||||
} else if (surface == shell->switcher_surface) { |
||||
/* */ |
||||
} else if (surface == shell->home_surface) { |
||||
if (shell->state == STATE_STARTING) { |
||||
/* homescreen always visible, at the bottom */ |
||||
wl_list_insert(&shell->homescreen_layer.view_list, |
||||
&view->layer_link); |
||||
|
||||
tablet_shell_set_state(shell, STATE_LOCKED); |
||||
shell->previous_state = STATE_HOME; |
||||
tablet_shell_send_show_lockscreen(shell->resource); |
||||
} |
||||
} else if (shell->current_client && |
||||
shell->current_client->surface != surface && |
||||
shell->current_client->client == wl_resource_get_client(surface->resource)) { |
||||
tablet_shell_set_state(shell, STATE_TASK); |
||||
shell->current_client->surface = surface; |
||||
weston_zoom_run(view, 0.3, 1.0, NULL, NULL); |
||||
wl_list_insert(&shell->application_layer.view_list, |
||||
&view->layer_link); |
||||
} |
||||
|
||||
if (view) { |
||||
weston_view_set_position(view, 0, 0); |
||||
weston_view_update_transform(view); |
||||
} |
||||
} |
||||
|
||||
static void |
||||
handle_lockscreen_surface_destroy(struct wl_listener *listener, void *data) |
||||
{ |
||||
struct tablet_shell *shell = |
||||
container_of(listener, |
||||
struct tablet_shell, lockscreen_listener); |
||||
|
||||
shell->lockscreen_surface = NULL; |
||||
tablet_shell_set_state(shell, shell->previous_state); |
||||
} |
||||
|
||||
static void |
||||
tablet_shell_set_lockscreen(struct wl_client *client, |
||||
struct wl_resource *resource, |
||||
struct wl_resource *surface_resource) |
||||
{ |
||||
struct tablet_shell *shell = wl_resource_get_user_data(resource); |
||||
struct weston_surface *es = wl_resource_get_user_data(surface_resource); |
||||
struct weston_view *view; |
||||
|
||||
view = weston_view_create(es); |
||||
weston_view_set_position(view, 0, 0); |
||||
shell->lockscreen_surface = es; |
||||
es->configure = tablet_shell_surface_configure; |
||||
shell->lockscreen_listener.notify = handle_lockscreen_surface_destroy; |
||||
wl_signal_add(&es->destroy_signal, &shell->lockscreen_listener); |
||||
} |
||||
|
||||
static void |
||||
handle_switcher_surface_destroy(struct wl_listener *listener, void *data) |
||||
{ |
||||
struct tablet_shell *shell = |
||||
container_of(listener, |
||||
struct tablet_shell, switcher_listener); |
||||
|
||||
shell->switcher_surface = NULL; |
||||
if (shell->state != STATE_LOCKED) |
||||
tablet_shell_set_state(shell, shell->previous_state); |
||||
} |
||||
|
||||
static void |
||||
tablet_shell_set_switcher(struct wl_client *client, |
||||
struct wl_resource *resource, |
||||
struct wl_resource *surface_resource) |
||||
{ |
||||
struct tablet_shell *shell = wl_resource_get_user_data(resource); |
||||
struct weston_surface *es = wl_resource_get_user_data(surface_resource); |
||||
struct weston_view *view; |
||||
|
||||
/* FIXME: Switcher should be centered and the compositor
|
||||
* should do the tinting of the background. With the cache |
||||
* layer idea, we should be able to hit the framerate on the |
||||
* fade/zoom in. */ |
||||
view = weston_view_create(es); |
||||
weston_view_set_position(view, 0, 0); |
||||
|
||||
shell->switcher_surface = es; |
||||
shell->switcher_listener.notify = handle_switcher_surface_destroy; |
||||
wl_signal_add(&es->destroy_signal, &shell->switcher_listener); |
||||
} |
||||
|
||||
static void |
||||
tablet_shell_set_homescreen(struct wl_client *client, |
||||
struct wl_resource *resource, |
||||
struct wl_resource *surface_resource) |
||||
{ |
||||
struct tablet_shell *shell = wl_resource_get_user_data(resource); |
||||
struct weston_surface *es = wl_resource_get_user_data(surface_resource); |
||||
struct weston_view *view; |
||||
|
||||
view = weston_view_create(es); |
||||
weston_view_set_position(view, 0, 0); |
||||
|
||||
shell->home_surface = es; |
||||
es->configure = tablet_shell_surface_configure; |
||||
} |
||||
|
||||
static void |
||||
minimize_zoom_done(struct weston_view_animation *zoom, void *data) |
||||
{ |
||||
struct tablet_shell *shell = data; |
||||
struct weston_compositor *compositor = shell->compositor; |
||||
struct weston_seat *seat; |
||||
|
||||
wl_list_for_each(seat, &compositor->seat_list, link) |
||||
weston_surface_activate(shell->home_surface, seat); |
||||
} |
||||
|
||||
static void |
||||
tablet_shell_switch_to(struct tablet_shell *shell, |
||||
struct weston_surface *surface) |
||||
{ |
||||
struct weston_compositor *compositor = shell->compositor; |
||||
struct weston_seat *seat; |
||||
struct weston_surface *current; |
||||
struct weston_view *view = get_surface_view(surface, 1); |
||||
|
||||
if (shell->state == STATE_SWITCHER) { |
||||
wl_list_remove(&shell->switcher_listener.link); |
||||
shell->switcher_surface = NULL; |
||||
}; |
||||
|
||||
if (surface == shell->home_surface) { |
||||
tablet_shell_set_state(shell, STATE_HOME); |
||||
|
||||
if (shell->current_client && shell->current_client->surface) { |
||||
current = shell->current_client->surface; |
||||
weston_zoom_run(get_surface_view(current, 0), 1.0, 0.3, |
||||
minimize_zoom_done, shell); |
||||
} |
||||
} else { |
||||
fprintf(stderr, "switch to %p\n", view); |
||||
wl_list_for_each(seat, &compositor->seat_list, link) |
||||
weston_surface_activate(view->surface, seat); |
||||
tablet_shell_set_state(shell, STATE_TASK); |
||||
weston_zoom_run(view, 0.3, 1.0, NULL, NULL); |
||||
} |
||||
} |
||||
|
||||
static void |
||||
tablet_shell_show_grid(struct wl_client *client, |
||||
struct wl_resource *resource, |
||||
struct wl_resource *surface_resource) |
||||
{ |
||||
struct tablet_shell *shell = wl_resource_get_user_data(resource); |
||||
struct weston_surface *es = wl_resource_get_user_data(surface_resource); |
||||
|
||||
tablet_shell_switch_to(shell, es); |
||||
} |
||||
|
||||
static void |
||||
tablet_shell_show_panels(struct wl_client *client, |
||||
struct wl_resource *resource, |
||||
struct wl_resource *surface_resource) |
||||
{ |
||||
struct tablet_shell *shell = wl_resource_get_user_data(resource); |
||||
struct weston_surface *es = wl_resource_get_user_data(surface_resource); |
||||
|
||||
tablet_shell_switch_to(shell, es); |
||||
} |
||||
|
||||
static void |
||||
destroy_tablet_client(struct wl_resource *resource) |
||||
{ |
||||
struct tablet_client *tablet_client = |
||||
wl_resource_get_user_data(resource); |
||||
|
||||
free(tablet_client->name); |
||||
free(tablet_client); |
||||
} |
||||
|
||||
static void |
||||
tablet_client_destroy(struct wl_client *client, |
||||
struct wl_resource *resource) |
||||
{ |
||||
wl_resource_destroy(resource); |
||||
} |
||||
|
||||
static void |
||||
tablet_client_activate(struct wl_client *client, struct wl_resource *resource) |
||||
{ |
||||
struct tablet_client *tablet_client = wl_resource_get_user_data(resource); |
||||
struct tablet_shell *shell = tablet_client->shell; |
||||
|
||||
shell->current_client = tablet_client; |
||||
if (!tablet_client->surface) |
||||
return; |
||||
|
||||
tablet_shell_switch_to(shell, tablet_client->surface); |
||||
} |
||||
|
||||
static const struct tablet_client_interface tablet_client_implementation = { |
||||
tablet_client_destroy, |
||||
tablet_client_activate |
||||
}; |
||||
|
||||
static void |
||||
tablet_shell_create_client(struct wl_client *client, |
||||
struct wl_resource *resource, |
||||
uint32_t id, const char *name, int fd) |
||||
{ |
||||
struct tablet_shell *shell = wl_resource_get_user_data(resource); |
||||
struct weston_compositor *compositor = shell->compositor; |
||||
struct tablet_client *tablet_client; |
||||
|
||||
tablet_client = malloc(sizeof *tablet_client); |
||||
if (tablet_client == NULL) { |
||||
wl_resource_post_no_memory(resource); |
||||
return; |
||||
} |
||||
|
||||
tablet_client->client = wl_client_create(compositor->wl_display, fd); |
||||
tablet_client->shell = shell; |
||||
tablet_client->name = strdup(name); |
||||
|
||||
tablet_client->resource = |
||||
wl_resource_create(client, &tablet_client_interface, 1, id); |
||||
wl_resource_set_implementation(tablet_client->resource, |
||||
&tablet_client_implementation, |
||||
tablet_client, destroy_tablet_client); |
||||
|
||||
tablet_client->surface = NULL; |
||||
shell->current_client = tablet_client; |
||||
|
||||
weston_log("created client %p, id %d, name %s, fd %d\n", |
||||
tablet_client->client, id, name, fd); |
||||
} |
||||
|
||||
static const struct tablet_shell_interface tablet_shell_implementation = { |
||||
tablet_shell_set_lockscreen, |
||||
tablet_shell_set_switcher, |
||||
tablet_shell_set_homescreen, |
||||
tablet_shell_show_grid, |
||||
tablet_shell_show_panels, |
||||
tablet_shell_create_client |
||||
}; |
||||
|
||||
static void |
||||
launch_ux_daemon(struct tablet_shell *shell) |
||||
{ |
||||
const char *shell_exe = LIBEXECDIR "/weston-tablet-shell"; |
||||
|
||||
shell->client = weston_client_launch(shell->compositor, |
||||
&shell->process, |
||||
shell_exe, tablet_shell_sigchld); |
||||
} |
||||
|
||||
static void |
||||
toggle_switcher(struct tablet_shell *shell) |
||||
{ |
||||
switch (shell->state) { |
||||
case STATE_SWITCHER: |
||||
tablet_shell_send_hide_switcher(shell->resource); |
||||
break; |
||||
default: |
||||
tablet_shell_send_show_switcher(shell->resource); |
||||
tablet_shell_set_state(shell, STATE_SWITCHER); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
static void |
||||
tablet_shell_lock(struct wl_listener *listener, void *data) |
||||
{ |
||||
struct tablet_shell *shell = |
||||
container_of(listener, struct tablet_shell, lock_listener); |
||||
|
||||
if (shell->state == STATE_LOCKED) |
||||
return; |
||||
if (shell->state == STATE_SWITCHER) |
||||
tablet_shell_send_hide_switcher(shell->resource); |
||||
|
||||
tablet_shell_send_show_lockscreen(shell->resource); |
||||
tablet_shell_set_state(shell, STATE_LOCKED); |
||||
} |
||||
|
||||
static void |
||||
tablet_shell_unlock(struct wl_listener *listener, void *data) |
||||
{ |
||||
struct tablet_shell *shell = |
||||
container_of(listener, struct tablet_shell, unlock_listener); |
||||
|
||||
tablet_shell_set_state(shell, STATE_HOME); |
||||
} |
||||
|
||||
static void |
||||
go_home(struct tablet_shell *shell, struct weston_seat *seat) |
||||
{ |
||||
if (shell->state == STATE_SWITCHER) |
||||
tablet_shell_send_hide_switcher(shell->resource); |
||||
|
||||
weston_surface_activate(shell->home_surface, seat); |
||||
|
||||
tablet_shell_set_state(shell, STATE_HOME); |
||||
} |
||||
|
||||
static int |
||||
long_press_handler(void *data) |
||||
{ |
||||
struct tablet_shell *shell = data; |
||||
|
||||
shell->long_press_active = 0; |
||||
toggle_switcher(shell); |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
static void |
||||
menu_key_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data) |
||||
{ |
||||
struct tablet_shell *shell = data; |
||||
|
||||
if (shell->state == STATE_LOCKED) |
||||
return; |
||||
|
||||
toggle_switcher(shell); |
||||
} |
||||
|
||||
static void |
||||
home_key_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data) |
||||
{ |
||||
struct tablet_shell *shell = data; |
||||
|
||||
if (shell->state == STATE_LOCKED) |
||||
return; |
||||
|
||||
if (1) { |
||||
wl_event_source_timer_update(shell->long_press_source, 500); |
||||
shell->long_press_active = 1; |
||||
} else if (shell->long_press_active) { |
||||
/* This code has never been run ... */ |
||||
wl_event_source_timer_update(shell->long_press_source, 0); |
||||
shell->long_press_active = 0; |
||||
|
||||
switch (shell->state) { |
||||
case STATE_HOME: |
||||
case STATE_SWITCHER: |
||||
toggle_switcher(shell); |
||||
break; |
||||
default: |
||||
go_home(shell, (struct weston_seat *) seat); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
static void |
||||
destroy_tablet_shell(struct wl_resource *resource) |
||||
{ |
||||
} |
||||
|
||||
static void |
||||
bind_tablet_shell(struct wl_client *client, void *data, uint32_t version, |
||||
uint32_t id) |
||||
{ |
||||
struct tablet_shell *shell = data; |
||||
|
||||
if (shell->client != client) |
||||
/* Throw an error or just let the client fail when it
|
||||
* tries to access the object?. */ |
||||
return; |
||||
|
||||
shell->resource = |
||||
wl_resource_create(client, &tablet_shell_interface, 1, id); |
||||
wl_resource_set_implementation(shell->resource, |
||||
&tablet_shell_implementation, |
||||
shell, destroy_tablet_shell); |
||||
} |
||||
|
||||
static void |
||||
tablet_shell_destroy(struct wl_listener *listener, void *data) |
||||
{ |
||||
struct tablet_shell *shell = |
||||
container_of(listener, struct tablet_shell, destroy_listener); |
||||
|
||||
if (shell->home_surface) |
||||
shell->home_surface->configure = NULL; |
||||
|
||||
if (shell->lockscreen_surface) |
||||
shell->lockscreen_surface->configure = NULL; |
||||
|
||||
wl_event_source_remove(shell->long_press_source); |
||||
free(shell); |
||||
} |
||||
|
||||
WL_EXPORT int |
||||
module_init(struct weston_compositor *compositor, |
||||
int *argc, char *argv[]) |
||||
{ |
||||
struct tablet_shell *shell; |
||||
struct wl_event_loop *loop; |
||||
|
||||
shell = zalloc(sizeof *shell); |
||||
if (shell == NULL) |
||||
return -1; |
||||
|
||||
shell->compositor = compositor; |
||||
|
||||
shell->destroy_listener.notify = tablet_shell_destroy; |
||||
wl_signal_add(&compositor->destroy_signal, &shell->destroy_listener); |
||||
shell->lock_listener.notify = tablet_shell_lock; |
||||
wl_signal_add(&compositor->idle_signal, &shell->lock_listener); |
||||
shell->unlock_listener.notify = tablet_shell_unlock; |
||||
wl_signal_add(&compositor->wake_signal, &shell->unlock_listener); |
||||
|
||||
/* FIXME: This will make the object available to all clients. */ |
||||
wl_global_create(compositor->wl_display, &tablet_shell_interface, 1, |
||||
shell, bind_tablet_shell); |
||||
|
||||
loop = wl_display_get_event_loop(compositor->wl_display); |
||||
shell->long_press_source = |
||||
wl_event_loop_add_timer(loop, long_press_handler, shell); |
||||
|
||||
weston_compositor_add_key_binding(compositor, KEY_LEFTMETA, 0, |
||||
home_key_binding, shell); |
||||
weston_compositor_add_key_binding(compositor, KEY_RIGHTMETA, 0, |
||||
home_key_binding, shell); |
||||
weston_compositor_add_key_binding(compositor, KEY_LEFTMETA, |
||||
MODIFIER_SUPER, home_key_binding, |
||||
shell); |
||||
weston_compositor_add_key_binding(compositor, KEY_RIGHTMETA, |
||||
MODIFIER_SUPER, home_key_binding, |
||||
shell); |
||||
weston_compositor_add_key_binding(compositor, KEY_COMPOSE, 0, |
||||
menu_key_binding, shell); |
||||
|
||||
weston_layer_init(&shell->homescreen_layer, |
||||
&compositor->cursor_layer.link); |
||||
weston_layer_init(&shell->application_layer, |
||||
&compositor->cursor_layer.link); |
||||
weston_layer_init(&shell->lockscreen_layer, |
||||
&compositor->cursor_layer.link); |
||||
launch_ux_daemon(shell); |
||||
|
||||
tablet_shell_set_state(shell, STATE_STARTING); |
||||
|
||||
return 0; |
||||
} |
Loading…
Reference in new issue