852 lines
23 KiB
Diff
852 lines
23 KiB
Diff
From e577b6143c140983d31e527b39045cb58451a59e Mon Sep 17 00:00:00 2001
|
|
From: Jeffy Chen <jeffy.chen@rock-chips.com>
|
|
Date: Fri, 28 Jul 2023 14:54:30 +0800
|
|
Subject: [PATCH 66/95] desktop-shell: Support desktop launchers
|
|
|
|
Tested on RK3588 EVB with:
|
|
1/ sed -i "s/\[\(launcher\)/[desktop-\1/" /etc/xdg/weston/weston.ini.d/*
|
|
2/ killall weston; weston&
|
|
|
|
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
|
|
---
|
|
clients/desktop-shell.c | 700 +++++++++++++++++++++++++++++++++++++++-
|
|
1 file changed, 688 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
|
|
index f88f63e..fb32632 100644
|
|
--- a/clients/desktop-shell.c
|
|
+++ b/clients/desktop-shell.c
|
|
@@ -128,6 +128,8 @@ struct background {
|
|
char *image;
|
|
int type;
|
|
uint32_t color;
|
|
+
|
|
+ struct wl_list launcher_group_list;
|
|
};
|
|
|
|
struct output {
|
|
@@ -135,6 +137,8 @@ struct output {
|
|
uint32_t server_output_id;
|
|
struct wl_list link;
|
|
|
|
+ char *name;
|
|
+
|
|
int x;
|
|
int y;
|
|
struct panel *panel;
|
|
@@ -164,6 +168,72 @@ struct panel_clock {
|
|
time_t refresh_timer;
|
|
};
|
|
|
|
+enum gravity {
|
|
+ CENTER,
|
|
+ LEFT_TOP,
|
|
+ LEFT_BOTTOM,
|
|
+ RIGHT_TOP,
|
|
+ RIGHT_BOTTOM,
|
|
+};
|
|
+
|
|
+struct desktop_launcher_group {
|
|
+ struct widget *widget;
|
|
+ struct background *background;
|
|
+ struct wl_list link;
|
|
+ struct wl_list launcher_list;
|
|
+
|
|
+ char *name;
|
|
+ uint32_t row;
|
|
+ uint32_t column;
|
|
+
|
|
+ struct desktop_launcher_group *left_of;
|
|
+ struct desktop_launcher_group *right_of;
|
|
+ struct desktop_launcher_group *top_of;
|
|
+ struct desktop_launcher_group *bottom_of;
|
|
+
|
|
+ double padding_left;
|
|
+ double padding_right;
|
|
+ double padding_top;
|
|
+ double padding_bottom;
|
|
+
|
|
+ double max_width;
|
|
+ double max_height;
|
|
+
|
|
+ enum gravity gravity;
|
|
+
|
|
+ bool fit_size;
|
|
+
|
|
+ double launcher_ratio;
|
|
+ double launcher_width;
|
|
+ double launcher_height;
|
|
+
|
|
+ double spacing_x;
|
|
+ double spacing_y;
|
|
+
|
|
+ uint32_t color;
|
|
+
|
|
+ bool show_text;
|
|
+ uint32_t text_color;
|
|
+ double text_scale;
|
|
+ double text_alpha;
|
|
+
|
|
+ double icon_alpha;
|
|
+ uint32_t highlight_color;
|
|
+};
|
|
+
|
|
+struct desktop_launcher {
|
|
+ struct widget *widget;
|
|
+ struct desktop_launcher_group *group;
|
|
+ cairo_surface_t *icon;
|
|
+ int focused;
|
|
+ char *path;
|
|
+ char *displayname;
|
|
+ struct wl_list link;
|
|
+ struct custom_env env;
|
|
+ char * const *argp;
|
|
+ char * const *envp;
|
|
+};
|
|
+
|
|
struct unlock_dialog {
|
|
struct window *window;
|
|
struct widget *widget;
|
|
@@ -248,7 +318,7 @@ check_desktop_ready(struct window *window)
|
|
}
|
|
|
|
static void
|
|
-panel_launcher_activate(struct panel_launcher *widget)
|
|
+launcher_activate(char * const *argp, char * const *envp)
|
|
{
|
|
pid_t pid;
|
|
|
|
@@ -264,8 +334,8 @@ panel_launcher_activate(struct panel_launcher *widget)
|
|
if (setsid() == -1)
|
|
exit(EXIT_FAILURE);
|
|
|
|
- if (execve(widget->argp[0], widget->argp, widget->envp) < 0) {
|
|
- fprintf(stderr, "execl '%s' failed: %s\n", widget->argp[0],
|
|
+ if (execve(argp[0], argp, envp) < 0) {
|
|
+ fprintf(stderr, "execl '%s' failed: %s\n", argp[0],
|
|
strerror(errno));
|
|
exit(1);
|
|
}
|
|
@@ -383,8 +453,7 @@ panel_launcher_button_handler(struct widget *widget,
|
|
launcher = widget_get_user_data(widget);
|
|
widget_schedule_redraw(widget);
|
|
if (state == WL_POINTER_BUTTON_STATE_RELEASED)
|
|
- panel_launcher_activate(launcher);
|
|
-
|
|
+ launcher_activate(launcher->argp, launcher->envp);
|
|
}
|
|
|
|
static void
|
|
@@ -409,7 +478,7 @@ panel_launcher_touch_up_handler(struct widget *widget, struct input *input,
|
|
launcher = widget_get_user_data(widget);
|
|
launcher->focused = 0;
|
|
widget_schedule_redraw(widget);
|
|
- panel_launcher_activate(launcher);
|
|
+ launcher_activate(launcher->argp, launcher->envp);
|
|
}
|
|
|
|
static void
|
|
@@ -443,7 +512,7 @@ panel_launcher_tablet_tool_up_handler(struct widget *widget,
|
|
struct panel_launcher *launcher;
|
|
|
|
launcher = widget_get_user_data(widget);
|
|
- panel_launcher_activate(launcher);
|
|
+ launcher_activate(launcher->argp, launcher->envp);
|
|
}
|
|
|
|
static void
|
|
@@ -459,7 +528,7 @@ panel_launcher_tablet_tool_button_handler(struct widget *widget,
|
|
launcher = widget_get_user_data(widget);
|
|
|
|
if (state == ZWP_TABLET_TOOL_V2_BUTTON_STATE_RELEASED)
|
|
- panel_launcher_activate(launcher);
|
|
+ launcher_activate(launcher->argp, launcher->envp);
|
|
}
|
|
|
|
static int clock_timer_reset(struct panel_clock *clock);
|
|
@@ -907,6 +976,194 @@ background_draw(struct widget *widget, void *data)
|
|
check_desktop_ready(background->window);
|
|
}
|
|
|
|
+#define PERCENT_VALUE(v, size) ((int)((v) >= 1 ? (v) : (v) * (size)))
|
|
+
|
|
+static void
|
|
+desktop_group_resize(struct desktop_launcher_group *group)
|
|
+{
|
|
+ struct desktop_launcher *launcher;
|
|
+ struct rectangle allocation;
|
|
+ int row, column, width, height, spacing_x, spacing_y, count;
|
|
+
|
|
+ widget_get_allocation(group->widget, &allocation);
|
|
+
|
|
+ width = PERCENT_VALUE(group->launcher_width, allocation.width);
|
|
+ height = PERCENT_VALUE(group->launcher_height, allocation.height);
|
|
+
|
|
+ row = group->row;
|
|
+ column = group->column;
|
|
+
|
|
+ if (!width) {
|
|
+ if (group->launcher_ratio && height)
|
|
+ width = height * group->launcher_ratio;
|
|
+ else if (!row)
|
|
+ width = 200;
|
|
+ else if (group->spacing_x >= 1)
|
|
+ width = allocation.width / row - group->spacing_x;
|
|
+ else
|
|
+ width = allocation.width / row / (1 + group->spacing_x);
|
|
+ }
|
|
+ spacing_x = PERCENT_VALUE(group->spacing_x ? group->spacing_x : 0.1,
|
|
+ width);
|
|
+ row = MAX(row ? row : allocation.width / (width + spacing_x), 1);
|
|
+
|
|
+ if (!height) {
|
|
+ if (group->launcher_ratio)
|
|
+ height = width / group->launcher_ratio;
|
|
+ else if (!column)
|
|
+ height = width / (group->show_text ? 0.8 : 1);
|
|
+ else if (group->spacing_y >= 1)
|
|
+ height = allocation.height / column - group->spacing_y;
|
|
+ else
|
|
+ height = allocation.height / column / (1 + group->spacing_y);
|
|
+ }
|
|
+ spacing_y = PERCENT_VALUE(group->spacing_y ? group->spacing_y : 0.1,
|
|
+ height);
|
|
+ column = MAX(column ? column : allocation.height / (height + spacing_y), 1);
|
|
+
|
|
+ /* Auto spacing */
|
|
+ if (!group->spacing_x)
|
|
+ spacing_x = allocation.width / row - width;
|
|
+ if (!group->spacing_y)
|
|
+ spacing_y = allocation.height / column - height;
|
|
+
|
|
+ /* Fit group size */
|
|
+ count = wl_list_length(&group->launcher_list);
|
|
+ if (count < row)
|
|
+ row = count;
|
|
+ if ((count + row - 1) / row < column)
|
|
+ column = (count + row - 1) / row;
|
|
+ allocation.width = (width + spacing_x) * row;
|
|
+ allocation.height = (height + spacing_y) * column;
|
|
+
|
|
+ count = 0;
|
|
+ wl_list_for_each(launcher, &group->launcher_list, link) {
|
|
+ int x, y;
|
|
+
|
|
+ x = allocation.x + spacing_x / 2 +
|
|
+ allocation.width * (count % row) / row;
|
|
+ y = allocation.y + spacing_y / 2 +
|
|
+ allocation.height * (count / row) / column;
|
|
+
|
|
+ widget_set_allocation(launcher->widget, x, y, width, height);
|
|
+
|
|
+ count++;
|
|
+ if (count >= row * column)
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* Apply fit size */
|
|
+ if (group->fit_size)
|
|
+ widget_set_allocation(group->widget,
|
|
+ allocation.x, allocation.y,
|
|
+ allocation.width, allocation.height);
|
|
+}
|
|
+
|
|
+static void
|
|
+background_resize(struct widget *widget,
|
|
+ int32_t width, int32_t height, void *data)
|
|
+{
|
|
+ struct desktop_launcher_group *group;
|
|
+ struct background *background = data;
|
|
+ struct panel *panel = background->owner->panel;
|
|
+ int start_x, start_y;
|
|
+
|
|
+ /* Background is always at (0,0) */
|
|
+ start_x = start_y = 0;
|
|
+
|
|
+ /* Remove panel area */
|
|
+ if (panel) {
|
|
+ struct desktop *desktop = background->owner->desktop;
|
|
+ struct rectangle allocation;
|
|
+
|
|
+ widget_get_allocation(panel->widget, &allocation);
|
|
+
|
|
+ switch (desktop->panel_position) {
|
|
+ case WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP:
|
|
+ start_y += allocation.height;
|
|
+ /* fallthrough */
|
|
+ case WESTON_DESKTOP_SHELL_PANEL_POSITION_BOTTOM:
|
|
+ height -= allocation.height;
|
|
+ break;
|
|
+ case WESTON_DESKTOP_SHELL_PANEL_POSITION_LEFT:
|
|
+ start_x += allocation.width;
|
|
+ /* fallthrough */
|
|
+ case WESTON_DESKTOP_SHELL_PANEL_POSITION_RIGHT:
|
|
+ width -= allocation.width;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ wl_list_for_each(group, &background->launcher_group_list, link) {
|
|
+ struct rectangle allocation;
|
|
+ int left, right, top, bottom, x, y, w, h;
|
|
+ int max_width, max_height;
|
|
+
|
|
+ left = top = 0;
|
|
+ right = width;
|
|
+ bottom = height;
|
|
+
|
|
+ if (group->left_of) {
|
|
+ widget_get_allocation(group->left_of->widget,
|
|
+ &allocation);
|
|
+ right = allocation.x - start_x;
|
|
+ }
|
|
+ if (group->right_of) {
|
|
+ widget_get_allocation(group->right_of->widget,
|
|
+ &allocation);
|
|
+ left = allocation.x + allocation.width - start_x;
|
|
+ }
|
|
+ if (group->top_of) {
|
|
+ widget_get_allocation(group->top_of->widget,
|
|
+ &allocation);
|
|
+ bottom = allocation.y - start_y;
|
|
+ }
|
|
+ if (group->bottom_of) {
|
|
+ widget_get_allocation(group->bottom_of->widget,
|
|
+ &allocation);
|
|
+ top = allocation.y + allocation.height - start_y;
|
|
+ }
|
|
+
|
|
+ left += PERCENT_VALUE(group->padding_left, width);
|
|
+ right -= PERCENT_VALUE(group->padding_right, width);
|
|
+ top += PERCENT_VALUE(group->padding_top, height);
|
|
+ bottom -= PERCENT_VALUE(group->padding_bottom, height);
|
|
+
|
|
+ max_width = PERCENT_VALUE(group->max_width, width);
|
|
+ max_height = PERCENT_VALUE(group->max_height, height);
|
|
+
|
|
+ w = MAX(MIN(max_width ? max_width : width, right - left),0);
|
|
+ h = MAX(MIN(max_height ? max_height : height, bottom - top),0);
|
|
+
|
|
+ switch (group->gravity) {
|
|
+ case LEFT_TOP:
|
|
+ x = left;
|
|
+ y = top;
|
|
+ break;
|
|
+ case LEFT_BOTTOM:
|
|
+ x = left;
|
|
+ y = bottom - h;
|
|
+ break;
|
|
+ case RIGHT_TOP:
|
|
+ x = right - w;
|
|
+ y = top;
|
|
+ break;
|
|
+ case RIGHT_BOTTOM:
|
|
+ x = right - w;
|
|
+ y = bottom - h;
|
|
+ break;
|
|
+ default:
|
|
+ x = left + (right - left - w) / 2;
|
|
+ y = top + (bottom - top - h) / 2;
|
|
+ break;
|
|
+ };
|
|
+
|
|
+ widget_set_allocation(group->widget,
|
|
+ x + start_x, y + start_y, w, h);
|
|
+ desktop_group_resize(group);
|
|
+ }
|
|
+}
|
|
+
|
|
static void
|
|
background_destroy(struct background *background);
|
|
|
|
@@ -1195,6 +1452,400 @@ static const struct weston_desktop_shell_listener listener = {
|
|
desktop_shell_grab_cursor
|
|
};
|
|
|
|
+static int
|
|
+desktop_launcher_enter_handler(struct widget *widget, struct input *input,
|
|
+ float x, float y, void *data)
|
|
+{
|
|
+ struct desktop_launcher *launcher = data;
|
|
+
|
|
+ launcher->focused = 1;
|
|
+ widget_schedule_redraw(widget);
|
|
+
|
|
+ return CURSOR_LEFT_PTR;
|
|
+}
|
|
+
|
|
+static void
|
|
+desktop_launcher_leave_handler(struct widget *widget,
|
|
+ struct input *input, void *data)
|
|
+{
|
|
+ struct desktop_launcher *launcher = data;
|
|
+
|
|
+ launcher->focused = 0;
|
|
+ widget_schedule_redraw(widget);
|
|
+}
|
|
+
|
|
+static void
|
|
+desktop_launcher_button_handler(struct widget *widget,
|
|
+ struct input *input, uint32_t time,
|
|
+ uint32_t button,
|
|
+ enum wl_pointer_button_state state, void *data)
|
|
+{
|
|
+ struct desktop_launcher *launcher;
|
|
+
|
|
+ launcher = widget_get_user_data(widget);
|
|
+ widget_schedule_redraw(widget);
|
|
+ if (state == WL_POINTER_BUTTON_STATE_RELEASED)
|
|
+ launcher_activate(launcher->argp, launcher->envp);
|
|
+
|
|
+}
|
|
+
|
|
+static void
|
|
+desktop_launcher_touch_down_handler(struct widget *widget, struct input *input,
|
|
+ uint32_t serial, uint32_t time, int32_t id,
|
|
+ float x, float y, void *data)
|
|
+{
|
|
+ struct desktop_launcher *launcher;
|
|
+
|
|
+ launcher = widget_get_user_data(widget);
|
|
+ launcher->focused = 1;
|
|
+ widget_schedule_redraw(widget);
|
|
+}
|
|
+
|
|
+static void
|
|
+desktop_launcher_touch_up_handler(struct widget *widget, struct input *input,
|
|
+ uint32_t serial, uint32_t time, int32_t id,
|
|
+ void *data)
|
|
+{
|
|
+ struct desktop_launcher *launcher;
|
|
+
|
|
+ launcher = widget_get_user_data(widget);
|
|
+ launcher->focused = 0;
|
|
+ widget_schedule_redraw(widget);
|
|
+ launcher_activate(launcher->argp, launcher->envp);
|
|
+}
|
|
+
|
|
+static void
|
|
+desktop_launcher_redraw_handler(struct widget *widget, void *data)
|
|
+{
|
|
+ struct desktop_launcher *launcher = data;
|
|
+ struct desktop_launcher_group *group = launcher->group;
|
|
+ struct rectangle allocation;
|
|
+ cairo_t *cr;
|
|
+ int x, y, icon_w, icon_h;
|
|
+ double scale;
|
|
+
|
|
+ widget_get_allocation(widget, &allocation);
|
|
+
|
|
+ /* Draw text */
|
|
+ if (group->show_text) {
|
|
+ cairo_text_extents_t extents;
|
|
+ double text_alpha = (group->text_color >> 24) / 255.0;
|
|
+ int spacing, text_height, text_offset;
|
|
+
|
|
+ if (group->spacing_y > 1)
|
|
+ spacing = group->spacing_y / 2;
|
|
+ else if (group->spacing_y)
|
|
+ spacing = group->spacing_y * allocation.height / 2;
|
|
+ else
|
|
+ spacing = allocation.height * 0.05;
|
|
+
|
|
+ cr = widget_cairo_create(group->widget);
|
|
+ cairo_rectangle(cr, allocation.x, allocation.y,
|
|
+ allocation.width, allocation.height);
|
|
+ cairo_clip(cr);
|
|
+
|
|
+ cairo_set_font_size(cr, 40 * group->text_scale);
|
|
+
|
|
+ cairo_text_extents(cr, "j", &extents);
|
|
+ text_height = extents.height;
|
|
+ text_offset = extents.height + extents.y_bearing;
|
|
+
|
|
+ cairo_text_extents(cr, launcher->displayname, &extents);
|
|
+
|
|
+ x = allocation.x +
|
|
+ MAX((allocation.width - extents.width) / 2, 0);
|
|
+ y = allocation.y + MAX(allocation.height - text_height, 0) +
|
|
+ text_height - text_offset;
|
|
+
|
|
+ cairo_move_to(cr, x + 1, y + 1);
|
|
+ cairo_set_source_rgba(cr, 0, 0, 0, text_alpha);
|
|
+ cairo_show_text(cr, launcher->displayname);
|
|
+ cairo_move_to(cr, x, y);
|
|
+ set_hex_color(cr, group->text_color);
|
|
+
|
|
+ cairo_show_text(cr, launcher->displayname);
|
|
+ cairo_destroy(cr);
|
|
+
|
|
+ allocation.height -= text_height + spacing;
|
|
+ }
|
|
+
|
|
+ /* Draw icon */
|
|
+ cr = widget_cairo_create(group->widget);
|
|
+
|
|
+ icon_w = cairo_image_surface_get_width(launcher->icon);
|
|
+ icon_h = cairo_image_surface_get_height(launcher->icon);
|
|
+
|
|
+ scale = MIN(1.0 * allocation.width / icon_w,
|
|
+ 1.0 * allocation.height / icon_h);
|
|
+
|
|
+ x = allocation.x + (allocation.width - icon_w * scale) / 2;
|
|
+ y = allocation.y + (allocation.height - icon_h * scale) / 2;
|
|
+
|
|
+ x = round(x / scale);
|
|
+ y = round(y / scale);
|
|
+ cairo_scale(cr, scale, scale);
|
|
+
|
|
+ cairo_set_source_surface(cr, launcher->icon, x, y);
|
|
+ cairo_paint_with_alpha(cr, group->icon_alpha);
|
|
+
|
|
+ if (launcher->focused) {
|
|
+ set_hex_color(cr, group->highlight_color);
|
|
+ cairo_mask_surface(cr, launcher->icon, x, y);
|
|
+ }
|
|
+
|
|
+ cairo_destroy(cr);
|
|
+}
|
|
+
|
|
+static void
|
|
+desktop_group_redraw(struct widget *widget, void *data)
|
|
+{
|
|
+ cairo_t *cr;
|
|
+ struct desktop_launcher_group *group = data;
|
|
+ struct rectangle allocation;
|
|
+
|
|
+ if (wl_list_empty(&group->launcher_list))
|
|
+ return;
|
|
+
|
|
+ widget_get_allocation(widget, &allocation);
|
|
+
|
|
+ cr = widget_cairo_create(group->widget);
|
|
+ cairo_rectangle(cr, allocation.x, allocation.y,
|
|
+ allocation.width, allocation.height);
|
|
+ set_hex_color(cr, group->color);
|
|
+ cairo_fill(cr);
|
|
+ cairo_destroy(cr);
|
|
+}
|
|
+
|
|
+static void
|
|
+desktop_add_launcher(struct desktop_launcher_group *group,
|
|
+ const char *icon, const char *path, const char *displayname)
|
|
+{
|
|
+ struct desktop_launcher *launcher;
|
|
+
|
|
+ launcher = xzalloc(sizeof *launcher);
|
|
+ launcher->icon = load_icon_or_fallback(icon);
|
|
+ launcher->path = xstrdup(path);
|
|
+ launcher->displayname = xstrdup(displayname);
|
|
+
|
|
+ custom_env_init_from_environ(&launcher->env);
|
|
+ custom_env_add_from_exec_string(&launcher->env, launcher->path);
|
|
+ launcher->envp = custom_env_get_envp(&launcher->env);
|
|
+ launcher->argp = custom_env_get_argp(&launcher->env);
|
|
+
|
|
+ launcher->group = group;
|
|
+ wl_list_insert(group->launcher_list.prev, &launcher->link);
|
|
+
|
|
+ launcher->widget = widget_add_widget(group->widget, launcher);
|
|
+ widget_set_enter_handler(launcher->widget,
|
|
+ desktop_launcher_enter_handler);
|
|
+ widget_set_leave_handler(launcher->widget,
|
|
+ desktop_launcher_leave_handler);
|
|
+ widget_set_button_handler(launcher->widget,
|
|
+ desktop_launcher_button_handler);
|
|
+ widget_set_touch_down_handler(launcher->widget,
|
|
+ desktop_launcher_touch_down_handler);
|
|
+ widget_set_touch_up_handler(launcher->widget,
|
|
+ desktop_launcher_touch_up_handler);
|
|
+ widget_set_redraw_handler(launcher->widget,
|
|
+ desktop_launcher_redraw_handler);
|
|
+}
|
|
+
|
|
+static void
|
|
+desktop_add_launchers(struct desktop_launcher_group *group,
|
|
+ struct desktop *desktop)
|
|
+{
|
|
+ struct weston_config_section *s;
|
|
+ char *name, *icon, *path, *displayname;
|
|
+ const char *section;
|
|
+
|
|
+ s = NULL;
|
|
+ while (weston_config_next_section(desktop->config, &s, §ion)) {
|
|
+ if (strcmp(section, "desktop-launcher") != 0)
|
|
+ continue;
|
|
+
|
|
+ weston_config_section_get_string(s, "group", &name, NULL);
|
|
+ if ((!group->name != !name) ||
|
|
+ (name && group->name && strcmp(name, group->name))) {
|
|
+ free(name);
|
|
+ continue;
|
|
+ }
|
|
+ free(name);
|
|
+
|
|
+ weston_config_section_get_string(s, "icon", &icon, NULL);
|
|
+ weston_config_section_get_string(s, "path", &path, NULL);
|
|
+ weston_config_section_get_string(s, "displayname", &displayname, NULL);
|
|
+ if (displayname == NULL)
|
|
+ displayname = xstrdup(basename(path));
|
|
+
|
|
+ if (icon != NULL && path != NULL) {
|
|
+ desktop_add_launcher(group, icon, path, displayname);
|
|
+ } else {
|
|
+ fprintf(stderr, "invalid desktop-launcher section\n");
|
|
+ }
|
|
+
|
|
+ free(icon);
|
|
+ free(path);
|
|
+ free(displayname);
|
|
+ }
|
|
+}
|
|
+
|
|
+static struct desktop_launcher_group *
|
|
+background_find_group(struct background *background, const char *name)
|
|
+{
|
|
+ struct desktop_launcher_group *group;
|
|
+
|
|
+ if (!name)
|
|
+ return NULL;
|
|
+
|
|
+ wl_list_for_each(group, &background->launcher_group_list, link) {
|
|
+ if (group->name && !strcmp(group->name, name))
|
|
+ return group;
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static void
|
|
+background_add_group(struct background *background,
|
|
+ struct weston_config_section *s, struct desktop *desktop)
|
|
+{
|
|
+ struct desktop_launcher_group *group;
|
|
+ char *gravity, *name;
|
|
+
|
|
+ group = xzalloc(sizeof *group);
|
|
+ group->background = background;
|
|
+
|
|
+ weston_config_section_get_string(s, "name", &group->name, NULL);
|
|
+
|
|
+ /* Auto calculated by default */
|
|
+ weston_config_section_get_uint(s, "row", &group->row, 0);
|
|
+ weston_config_section_get_uint(s, "column", &group->column, 0);
|
|
+
|
|
+ weston_config_section_get_string(s, "left-to", &name, NULL);
|
|
+ group->left_of = background_find_group(background, name);
|
|
+ if (name && !group->left_of) {
|
|
+ fprintf(stderr, "unknown left-of: %s\n", name);
|
|
+ free(group);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ weston_config_section_get_string(s, "right-of", &name, NULL);
|
|
+ group->right_of = background_find_group(background, name);
|
|
+ if (name && !group->right_of) {
|
|
+ fprintf(stderr, "unknown right-of: %s\n", name);
|
|
+ free(group);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ weston_config_section_get_string(s, "top-of", &name, NULL);
|
|
+ group->top_of = background_find_group(background, name);
|
|
+ if (name && !group->top_of) {
|
|
+ fprintf(stderr, "unknown top-of: %s\n", name);
|
|
+ free(group);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ weston_config_section_get_string(s, "bottom-of", &name, NULL);
|
|
+ group->bottom_of = background_find_group(background, name);
|
|
+ if (name && !group->bottom_of) {
|
|
+ fprintf(stderr, "unknown bottom-of: %s\n", name);
|
|
+ free(group);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ weston_config_section_get_double(s, "padding-left",
|
|
+ &group->padding_left, 0.05);
|
|
+ weston_config_section_get_double(s, "padding-right",
|
|
+ &group->padding_right, 0.05);
|
|
+ weston_config_section_get_double(s, "padding-top",
|
|
+ &group->padding_top, 0.05);
|
|
+ weston_config_section_get_double(s, "padding-bottom",
|
|
+ &group->padding_bottom, 0.05);
|
|
+
|
|
+ weston_config_section_get_double(s, "max-width", &group->max_width, 0);
|
|
+ weston_config_section_get_double(s, "max-height",
|
|
+ &group->max_height, 0);
|
|
+
|
|
+ weston_config_section_get_string(s, "gravity", &gravity, NULL);
|
|
+ if (gravity) {
|
|
+ if (!strcmp(gravity, "left-top"))
|
|
+ group->gravity = LEFT_TOP;
|
|
+ else if (!strcmp(gravity, "left-bottom"))
|
|
+ group->gravity = LEFT_BOTTOM;
|
|
+ else if (!strcmp(gravity, "right-top"))
|
|
+ group->gravity = RIGHT_TOP;
|
|
+ else if (!strcmp(gravity, "right-bottom"))
|
|
+ group->gravity = RIGHT_BOTTOM;
|
|
+ else
|
|
+ group->gravity = CENTER;
|
|
+ }
|
|
+
|
|
+ weston_config_section_get_bool(s, "fit-size", &group->fit_size, false);
|
|
+
|
|
+ weston_config_section_get_double(s, "launcher-ratio",
|
|
+ &group->launcher_ratio, 0);
|
|
+ weston_config_section_get_double(s, "launcher-width",
|
|
+ &group->launcher_width, 0);
|
|
+ weston_config_section_get_double(s, "launcher-height",
|
|
+ &group->launcher_height, 0);
|
|
+
|
|
+ /* Auto spacing by default */
|
|
+ weston_config_section_get_double(s, "spacing-x", &group->spacing_x, 0);
|
|
+ weston_config_section_get_double(s, "spacing-y", &group->spacing_y, 0);
|
|
+
|
|
+ weston_config_section_get_color(s, "color", &group->color, 0x11FFFFFF);
|
|
+
|
|
+ weston_config_section_get_bool(s, "show-text",
|
|
+ &group->show_text, true);
|
|
+ weston_config_section_get_color(s, "text-color",
|
|
+ &group->text_color, 0xDDFFFFFF);
|
|
+ weston_config_section_get_double(s, "text-scale",
|
|
+ &group->text_scale, 1);
|
|
+
|
|
+ weston_config_section_get_double(s, "icon-alpha",
|
|
+ &group->icon_alpha, 1);
|
|
+ weston_config_section_get_color(s, "highlight-color",
|
|
+ &group->highlight_color, 0x66FFFFFF);
|
|
+
|
|
+ group->widget = widget_add_widget(background->widget, group);
|
|
+ widget_set_redraw_handler(group->widget, desktop_group_redraw);
|
|
+
|
|
+ wl_list_init(&group->launcher_list);
|
|
+ desktop_add_launchers(group, desktop);
|
|
+
|
|
+ wl_list_insert(background->launcher_group_list.prev, &group->link);
|
|
+}
|
|
+
|
|
+static void
|
|
+background_add_groups(struct background *background, struct desktop *desktop)
|
|
+{
|
|
+ struct weston_config_section *s;
|
|
+ const char *section;
|
|
+ char *name;
|
|
+ int count;
|
|
+
|
|
+ count = 0;
|
|
+ s = NULL;
|
|
+ while (weston_config_next_section(desktop->config, &s, §ion)) {
|
|
+ if (strcmp(section, "desktop-launcher-group") != 0)
|
|
+ continue;
|
|
+
|
|
+ weston_config_section_get_string(s, "output", &name, NULL);
|
|
+ if (name && background->owner->name &&
|
|
+ strcmp(name, background->owner->name)) {
|
|
+ free(name);
|
|
+ continue;
|
|
+ }
|
|
+ free(name);
|
|
+
|
|
+ background_add_group(background, s, desktop);
|
|
+ count++;
|
|
+ }
|
|
+
|
|
+ /* add default launcher group */
|
|
+ if (!count)
|
|
+ background_add_group(background, NULL, desktop);
|
|
+}
|
|
+
|
|
static void
|
|
background_destroy(struct background *background)
|
|
{
|
|
@@ -1219,6 +1870,7 @@ background_create(struct desktop *desktop, struct output *output)
|
|
background->widget = window_add_widget(background->window, background);
|
|
window_set_user_data(background->window, background);
|
|
widget_set_redraw_handler(background->widget, background_draw);
|
|
+ widget_set_resize_handler(background->widget, background_resize);
|
|
widget_set_transparent(background->widget, 0);
|
|
|
|
s = weston_config_get_section(desktop->config, "shell", NULL, NULL);
|
|
@@ -1250,6 +1902,9 @@ background_create(struct desktop *desktop, struct output *output)
|
|
|
|
free(type);
|
|
|
|
+ wl_list_init(&background->launcher_group_list);
|
|
+ background_add_groups(background, desktop);
|
|
+
|
|
return background;
|
|
}
|
|
|
|
@@ -1300,6 +1955,7 @@ output_destroy(struct output *output)
|
|
wl_output_destroy(output->output);
|
|
wl_list_remove(&output->link);
|
|
|
|
+ free(output->name);
|
|
free(output);
|
|
}
|
|
|
|
@@ -1381,11 +2037,30 @@ output_handle_scale(void *data,
|
|
window_set_buffer_scale(output->background->window, scale);
|
|
}
|
|
|
|
+static void
|
|
+output_handle_name(void *data,
|
|
+ struct wl_output *wl_output,
|
|
+ const char *name)
|
|
+{
|
|
+ struct output *output = data;
|
|
+
|
|
+ output->name = strdup(name);
|
|
+}
|
|
+
|
|
+static void
|
|
+output_handle_description(void *data,
|
|
+ struct wl_output *wl_output,
|
|
+ const char *description)
|
|
+{
|
|
+}
|
|
+
|
|
static const struct wl_output_listener output_listener = {
|
|
output_handle_geometry,
|
|
output_handle_mode,
|
|
output_handle_done,
|
|
- output_handle_scale
|
|
+ output_handle_scale,
|
|
+ output_handle_name,
|
|
+ output_handle_description,
|
|
};
|
|
|
|
static void
|
|
@@ -1407,7 +2082,7 @@ output_init(struct output *output, struct desktop *desktop)
|
|
}
|
|
|
|
static void
|
|
-create_output(struct desktop *desktop, uint32_t id)
|
|
+create_output(struct desktop *desktop, uint32_t id, uint32_t version)
|
|
{
|
|
struct output *output;
|
|
|
|
@@ -1417,7 +2092,8 @@ create_output(struct desktop *desktop, uint32_t id)
|
|
|
|
output->desktop = desktop;
|
|
output->output =
|
|
- display_bind(desktop->display, id, &wl_output_interface, 2);
|
|
+ display_bind(desktop->display, id, &wl_output_interface,
|
|
+ MIN(version, 4));
|
|
output->server_output_id = id;
|
|
|
|
wl_output_add_listener(output->output, &output_listener, output);
|
|
@@ -1499,7 +2175,7 @@ global_handler(struct display *display, uint32_t id,
|
|
&listener,
|
|
desktop);
|
|
} else if (!strcmp(interface, "wl_output")) {
|
|
- create_output(desktop, id);
|
|
+ create_output(desktop, id, version);
|
|
}
|
|
}
|
|
|
|
--
|
|
2.20.1
|
|
|