|
|
|
@ -37,62 +37,163 @@ struct tablet_shell { |
|
|
|
|
struct window *lockscreen; |
|
|
|
|
struct window *switcher; |
|
|
|
|
struct window *homescreen; |
|
|
|
|
struct wl_list launcher_list; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct launcher { |
|
|
|
|
cairo_surface_t *icon; |
|
|
|
|
char *path; |
|
|
|
|
struct wl_list link; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static char *key_lockscreen_icon; |
|
|
|
|
static char *key_lockscreen_background; |
|
|
|
|
static char *key_homescreen_background; |
|
|
|
|
static char *key_launcher_icon; |
|
|
|
|
static char *key_launcher_path; |
|
|
|
|
static void launcher_section_done(void *data); |
|
|
|
|
|
|
|
|
|
static const struct config_key lockscreen_config_keys[] = { |
|
|
|
|
{ "icon", CONFIG_KEY_STRING, &key_lockscreen_icon }, |
|
|
|
|
{ "background", CONFIG_KEY_STRING, &key_lockscreen_background }, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const struct config_key homescreen_config_keys[] = { |
|
|
|
|
{ "background", CONFIG_KEY_STRING, &key_homescreen_background }, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const struct config_key launcher_config_keys[] = { |
|
|
|
|
{ "icon", CONFIG_KEY_STRING, &key_launcher_icon }, |
|
|
|
|
{ "path", CONFIG_KEY_STRING, &key_launcher_path }, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const struct config_section config_sections[] = { |
|
|
|
|
{ "lockscreen", |
|
|
|
|
lockscreen_config_keys, ARRAY_LENGTH(lockscreen_config_keys) }, |
|
|
|
|
{ "homescreen", |
|
|
|
|
homescreen_config_keys, ARRAY_LENGTH(homescreen_config_keys) }, |
|
|
|
|
{ "launcher", |
|
|
|
|
launcher_config_keys, ARRAY_LENGTH(launcher_config_keys), |
|
|
|
|
launcher_section_done } |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
draw_stub(struct window *window, const char *caption) |
|
|
|
|
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_jpeg(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 backgrond image: %s\n", |
|
|
|
|
key_lockscreen_background); |
|
|
|
|
cairo_set_source_rgb(cr, 0.2, 0, 0); |
|
|
|
|
cairo_paint(cr); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
homescreen_draw(struct tablet_shell *shell) |
|
|
|
|
{ |
|
|
|
|
cairo_surface_t *surface; |
|
|
|
|
struct rectangle allocation; |
|
|
|
|
const int margin = 50, radius = 10; |
|
|
|
|
cairo_text_extents_t extents; |
|
|
|
|
cairo_pattern_t *pattern; |
|
|
|
|
cairo_matrix_t matrix; |
|
|
|
|
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; |
|
|
|
|
|
|
|
|
|
window_draw(window); |
|
|
|
|
window_get_child_allocation(window, &allocation); |
|
|
|
|
surface = window_get_surface(window); |
|
|
|
|
window_draw(shell->homescreen); |
|
|
|
|
window_get_child_allocation(shell->homescreen, &allocation); |
|
|
|
|
surface = window_get_surface(shell->homescreen); |
|
|
|
|
cr = cairo_create(surface); |
|
|
|
|
|
|
|
|
|
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); |
|
|
|
|
cairo_set_source_rgb(cr, 0.0, 0.0, 0.4); |
|
|
|
|
cairo_paint(cr); |
|
|
|
|
paint_background(cr, key_homescreen_background, &allocation); |
|
|
|
|
|
|
|
|
|
cairo_set_operator(cr, CAIRO_OPERATOR_OVER); |
|
|
|
|
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); |
|
|
|
|
rounded_rect(cr, allocation.x + margin, allocation.y + margin, |
|
|
|
|
allocation.x + allocation.width - margin, |
|
|
|
|
allocation.y + allocation.height - margin, radius); |
|
|
|
|
cairo_set_line_width(cr, 6); |
|
|
|
|
cairo_stroke(cr); |
|
|
|
|
|
|
|
|
|
cairo_select_font_face(cr, "Sans", |
|
|
|
|
CAIRO_FONT_SLANT_NORMAL, |
|
|
|
|
CAIRO_FONT_WEIGHT_NORMAL); |
|
|
|
|
cairo_set_font_size(cr, 40); |
|
|
|
|
|
|
|
|
|
cairo_text_extents(cr, caption, &extents); |
|
|
|
|
cairo_move_to(cr, |
|
|
|
|
allocation.x + (allocation.width - extents.width) / 2, |
|
|
|
|
allocation.y + (allocation.height - extents.height) / 2); |
|
|
|
|
cairo_show_text(cr, caption); |
|
|
|
|
|
|
|
|
|
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, &shell->launcher_list, link) { |
|
|
|
|
pattern = cairo_pattern_create_for_surface(launcher->icon); |
|
|
|
|
cairo_matrix_init_scale(&matrix, 2.0, 2.0); |
|
|
|
|
cairo_matrix_translate(&matrix, -x, -y); |
|
|
|
|
cairo_pattern_set_matrix(pattern, &matrix); |
|
|
|
|
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_NONE); |
|
|
|
|
cairo_set_source(cr, pattern); |
|
|
|
|
cairo_pattern_destroy(pattern); |
|
|
|
|
cairo_paint(cr); |
|
|
|
|
x += icon_width + hpadding; |
|
|
|
|
i++; |
|
|
|
|
if (i == columns) { |
|
|
|
|
x = hmargin; |
|
|
|
|
y += icon_height + vpadding; |
|
|
|
|
i = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cairo_surface_flush(surface); |
|
|
|
|
cairo_surface_destroy(surface); |
|
|
|
|
window_flush(window); |
|
|
|
|
window_flush(shell->homescreen); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
homescreen_draw(struct tablet_shell *shell) |
|
|
|
|
lockscreen_draw(struct tablet_shell *shell) |
|
|
|
|
{ |
|
|
|
|
draw_stub(shell->homescreen, "Homescreen Stub"); |
|
|
|
|
} |
|
|
|
|
cairo_surface_t *surface; |
|
|
|
|
cairo_surface_t *icon; |
|
|
|
|
struct rectangle allocation; |
|
|
|
|
cairo_t *cr; |
|
|
|
|
int width, height; |
|
|
|
|
|
|
|
|
|
window_draw(shell->lockscreen); |
|
|
|
|
window_get_child_allocation(shell->lockscreen, &allocation); |
|
|
|
|
surface = window_get_surface(shell->lockscreen); |
|
|
|
|
cr = cairo_create(surface); |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
lockscreen_draw(struct tablet_shell *shell) |
|
|
|
|
{ |
|
|
|
|
draw_stub(shell->lockscreen, "Lockscreen Stub"); |
|
|
|
|
paint_background(cr, key_lockscreen_background, &allocation); |
|
|
|
|
|
|
|
|
|
cairo_set_operator(cr, CAIRO_OPERATOR_OVER); |
|
|
|
|
icon = cairo_image_surface_create_from_png(key_lockscreen_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); |
|
|
|
|
cairo_paint(cr); |
|
|
|
|
cairo_surface_destroy(icon); |
|
|
|
|
|
|
|
|
|
cairo_surface_flush(surface); |
|
|
|
|
cairo_surface_destroy(surface); |
|
|
|
|
window_flush(shell->lockscreen); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int |
|
|
|
@ -187,18 +288,53 @@ tablet_shell_create(struct display *display, uint32_t id) |
|
|
|
|
|
|
|
|
|
tablet_shell_set_homescreen(shell->tablet_shell, |
|
|
|
|
window_get_wl_surface(shell->homescreen)); |
|
|
|
|
|
|
|
|
|
homescreen_draw(shell); |
|
|
|
|
wl_list_init(&shell->launcher_list); |
|
|
|
|
|
|
|
|
|
return shell; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
tablet_shell_add_launcher(struct tablet_shell *shell, |
|
|
|
|
const char *icon, const char *path) |
|
|
|
|
{ |
|
|
|
|
struct launcher *launcher; |
|
|
|
|
|
|
|
|
|
launcher = malloc(sizeof *launcher); |
|
|
|
|
launcher->path = strdup(path); |
|
|
|
|
launcher->icon = cairo_image_surface_create_from_png(icon); |
|
|
|
|
if (cairo_surface_status (launcher->icon) != CAIRO_STATUS_SUCCESS) { |
|
|
|
|
fprintf(stderr, "couldn't load %s\n", icon); |
|
|
|
|
free(launcher); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
wl_list_insert(&shell->launcher_list, &launcher->link); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
launcher_section_done(void *data) |
|
|
|
|
{ |
|
|
|
|
struct tablet_shell *shell = data; |
|
|
|
|
|
|
|
|
|
if (key_launcher_icon == NULL || key_launcher_path == NULL) { |
|
|
|
|
fprintf(stderr, "invalid launcher section\n"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tablet_shell_add_launcher(shell, key_launcher_icon, key_launcher_path); |
|
|
|
|
|
|
|
|
|
free(key_launcher_icon); |
|
|
|
|
key_launcher_icon = NULL; |
|
|
|
|
free(key_launcher_path); |
|
|
|
|
key_launcher_path = NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) |
|
|
|
|
{ |
|
|
|
|
struct display *display; |
|
|
|
|
char *config_file; |
|
|
|
|
uint32_t id; |
|
|
|
|
|
|
|
|
|
fprintf(stderr, "tablet shell client running\n"); |
|
|
|
|
struct tablet_shell *shell; |
|
|
|
|
|
|
|
|
|
display = display_create(&argc, &argv, NULL); |
|
|
|
|
if (display == NULL) { |
|
|
|
@ -209,7 +345,16 @@ int main(int argc, char *argv[]) |
|
|
|
|
wl_display_roundtrip(display_get_display(display)); |
|
|
|
|
id = wl_display_get_global(display_get_display(display), |
|
|
|
|
"tablet_shell", 1); |
|
|
|
|
tablet_shell_create(display, id); |
|
|
|
|
shell = tablet_shell_create(display, id); |
|
|
|
|
|
|
|
|
|
config_file = config_file_path("wayland-tablet-shell.ini"); |
|
|
|
|
parse_config_file(config_file, |
|
|
|
|
config_sections, ARRAY_LENGTH(config_sections), |
|
|
|
|
shell); |
|
|
|
|
free(config_file); |
|
|
|
|
|
|
|
|
|
homescreen_draw(shell); |
|
|
|
|
|
|
|
|
|
display_run(display); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|