mirror of
https://github.com/swaywm/sway.git
synced 2024-12-27 23:47:21 +01:00
Merge pull request #743 from deklov/panel-as-shell-03
Set panels/backgrounds' geometries correctly and don't render them ex…
This commit is contained in:
commit
6abbe04e75
12 changed files with 157 additions and 74 deletions
|
@ -32,6 +32,9 @@ struct workspace {
|
|||
bool urgent;
|
||||
};
|
||||
|
||||
/** Global bar state */
|
||||
extern struct bar swaybar;
|
||||
|
||||
/**
|
||||
* Setup bar.
|
||||
*/
|
||||
|
|
|
@ -13,5 +13,11 @@ void ipc_bar_init(struct bar *bar, const char *bar_id);
|
|||
*/
|
||||
bool handle_ipc_event(struct bar *bar);
|
||||
|
||||
|
||||
/**
|
||||
* Send workspace command to sway
|
||||
*/
|
||||
void ipc_send_workspace_command(const char *workspace_name);
|
||||
|
||||
#endif /* _SWAYBAR_IPC_H */
|
||||
|
||||
|
|
|
@ -14,4 +14,9 @@ void render(struct output *output, struct config *config, struct status_line *li
|
|||
*/
|
||||
void set_window_height(struct window *window, int height);
|
||||
|
||||
/**
|
||||
* Compute the size of a workspace name
|
||||
*/
|
||||
void workspace_button_size(struct window *window, const char *workspace_name, int *width, int *height);
|
||||
|
||||
#endif /* _SWAYBAR_RENDER_H */
|
||||
|
|
|
@ -28,10 +28,10 @@ struct cursor {
|
|||
};
|
||||
|
||||
struct pointer_input {
|
||||
wl_fixed_t last_x;
|
||||
wl_fixed_t last_y;
|
||||
int last_x;
|
||||
int last_y;
|
||||
|
||||
void (*notify)(struct window *window, wl_fixed_t x, wl_fixed_t y, uint32_t button);
|
||||
void (*notify)(struct window *window, int x, int y, uint32_t button);
|
||||
};
|
||||
|
||||
struct window {
|
||||
|
|
|
@ -11,8 +11,6 @@ struct background_config {
|
|||
wlc_resource surface;
|
||||
// we need the wl_resource of the surface in the destructor
|
||||
struct wl_resource *wl_surface_res;
|
||||
// used to determine if client is a background
|
||||
struct wl_client *client;
|
||||
};
|
||||
|
||||
struct panel_config {
|
||||
|
@ -25,6 +23,8 @@ struct panel_config {
|
|||
enum desktop_shell_panel_position panel_position;
|
||||
// used to determine if client is a panel
|
||||
struct wl_client *client;
|
||||
// wlc handle for this panel's surface, not set until panel is created
|
||||
wlc_handle handle;
|
||||
};
|
||||
|
||||
struct desktop_shell_state {
|
||||
|
|
|
@ -73,7 +73,6 @@ static void set_background(struct wl_client *client, struct wl_resource *resourc
|
|||
}
|
||||
sway_log(L_DEBUG, "Setting surface %p as background for output %d", surface, (int)output);
|
||||
struct background_config *config = malloc(sizeof(struct background_config));
|
||||
config->client = client;
|
||||
config->output = output;
|
||||
config->surface = wlc_resource_from_wl_surface_resource(surface);
|
||||
config->wl_surface_res = surface;
|
||||
|
|
124
sway/handlers.c
124
sway/handlers.c
|
@ -33,6 +33,66 @@
|
|||
// Event handled by sway and should not be sent to client
|
||||
#define EVENT_HANDLED true
|
||||
|
||||
static struct panel_config *if_panel_find_config(struct wl_client *client) {
|
||||
int i;
|
||||
for (i = 0; i < desktop_shell.panels->length; i++) {
|
||||
struct panel_config *config = desktop_shell.panels->items[i];
|
||||
if (config->client == client) {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct wlc_geometry compute_panel_geometry(struct panel_config *config) {
|
||||
const struct wlc_size resolution = *wlc_output_get_resolution(config->output);
|
||||
const struct wlc_geometry *old = wlc_view_get_geometry(config->handle);
|
||||
struct wlc_geometry new;
|
||||
|
||||
switch (config->panel_position) {
|
||||
case DESKTOP_SHELL_PANEL_POSITION_TOP:
|
||||
new.origin.x = 0;
|
||||
new.origin.y = 0;
|
||||
new.size.w = resolution.w;
|
||||
new.size.h = old->size.h;
|
||||
break;
|
||||
case DESKTOP_SHELL_PANEL_POSITION_BOTTOM:
|
||||
new.origin.x = 0;
|
||||
new.origin.y = resolution.h - old->size.h;
|
||||
new.size.w = resolution.w;
|
||||
new.size.h = old->size.h;
|
||||
break;
|
||||
case DESKTOP_SHELL_PANEL_POSITION_LEFT:
|
||||
new.origin.x = 0;
|
||||
new.origin.y = 0;
|
||||
new.size.w = old->size.w;
|
||||
new.size.h = resolution.h;
|
||||
break;
|
||||
case DESKTOP_SHELL_PANEL_POSITION_RIGHT:
|
||||
new.origin.x = resolution.w - old->size.w;
|
||||
new.origin.y = 0;
|
||||
new.size.w = old->size.w;
|
||||
new.size.h = resolution.h;
|
||||
break;
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
static void update_panel_geometry(struct panel_config *config) {
|
||||
struct wlc_geometry geometry = compute_panel_geometry(config);
|
||||
wlc_view_set_geometry(config->handle, 0, &geometry);
|
||||
}
|
||||
|
||||
static void update_panel_geometries(wlc_handle output) {
|
||||
for (int i = 0; i < desktop_shell.panels->length; i++) {
|
||||
struct panel_config *config = desktop_shell.panels->items[i];
|
||||
if (config->output == output) {
|
||||
update_panel_geometry(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Handles */
|
||||
|
||||
static bool handle_input_created(struct libinput_device *device) {
|
||||
|
@ -119,32 +179,6 @@ static void handle_output_pre_render(wlc_handle output) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < desktop_shell.panels->length; ++i) {
|
||||
struct panel_config *config = desktop_shell.panels->items[i];
|
||||
if (config->output == output) {
|
||||
struct wlc_size size = *wlc_surface_get_size(config->surface);
|
||||
struct wlc_geometry geo = {
|
||||
.size = size
|
||||
};
|
||||
switch (config->panel_position) {
|
||||
case DESKTOP_SHELL_PANEL_POSITION_TOP:
|
||||
geo.origin = (struct wlc_point){ 0, 0 };
|
||||
break;
|
||||
case DESKTOP_SHELL_PANEL_POSITION_BOTTOM:
|
||||
geo.origin = (struct wlc_point){ 0, resolution.h - size.h };
|
||||
break;
|
||||
case DESKTOP_SHELL_PANEL_POSITION_LEFT:
|
||||
geo.origin = (struct wlc_point){ 0, 0 };
|
||||
break;
|
||||
case DESKTOP_SHELL_PANEL_POSITION_RIGHT:
|
||||
geo.origin = (struct wlc_point){ resolution.w - size.w, 0 };
|
||||
break;
|
||||
}
|
||||
wlc_surface_render(config->surface, &geo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_output_post_render(wlc_handle output) {
|
||||
|
@ -158,10 +192,16 @@ static void handle_view_pre_render(wlc_handle view) {
|
|||
|
||||
static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) {
|
||||
sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h);
|
||||
|
||||
swayc_t *c = swayc_by_handle(output);
|
||||
if (!c) return;
|
||||
if (!c) {
|
||||
return;
|
||||
}
|
||||
c->width = to->w;
|
||||
c->height = to->h;
|
||||
|
||||
update_panel_geometries(output);
|
||||
|
||||
arrange_windows(&root_container, -1, -1);
|
||||
}
|
||||
|
||||
|
@ -176,28 +216,6 @@ static void handle_output_focused(wlc_handle output, bool focus) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool client_is_background(struct wl_client *client) {
|
||||
int i;
|
||||
for (i = 0; i < desktop_shell.backgrounds->length; i++) {
|
||||
struct background_config *config = desktop_shell.backgrounds->items[i];
|
||||
if (config->client == client) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool client_is_panel(struct wl_client *client) {
|
||||
int i;
|
||||
for (i = 0; i < desktop_shell.panels->length; i++) {
|
||||
struct panel_config *config = desktop_shell.panels->items[i];
|
||||
if (config->client == client) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ws_cleanup() {
|
||||
swayc_t *op, *ws;
|
||||
int i = 0, j;
|
||||
|
@ -228,8 +246,14 @@ static bool handle_view_created(wlc_handle handle) {
|
|||
bool return_to_workspace = false;
|
||||
struct wl_client *client = wlc_view_get_wl_client(handle);
|
||||
pid_t pid;
|
||||
struct panel_config *panel_config = NULL;
|
||||
|
||||
if (client_is_background(client) || client_is_panel(client)) {
|
||||
panel_config = if_panel_find_config(client);
|
||||
if (panel_config) {
|
||||
panel_config->handle = handle;
|
||||
update_panel_geometry(panel_config);
|
||||
wlc_view_set_mask(handle, VISIBLE);
|
||||
wlc_view_set_output(handle, panel_config->output);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,37 @@ struct output *new_output(const char *name) {
|
|||
return output;
|
||||
}
|
||||
|
||||
static void mouse_button_notify(struct window *window, int x, int y, uint32_t button) {
|
||||
sway_log(L_DEBUG, "Mouse button %d clicked at %d %d\n", button, x, y);
|
||||
|
||||
struct output *clicked_output = NULL;
|
||||
for (int i = 0; i < swaybar.outputs->length; i++) {
|
||||
struct output *output = swaybar.outputs->items[i];
|
||||
if (window == output->window) {
|
||||
clicked_output = output;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sway_assert(clicked_output != NULL, "Got pointer event for non-existing output")) {
|
||||
return;
|
||||
}
|
||||
|
||||
double button_x = 0.5;
|
||||
for (int i = 0; i < clicked_output->workspaces->length; i++) {
|
||||
struct workspace *workspace = clicked_output->workspaces->items[i];
|
||||
int button_width, button_height;
|
||||
|
||||
workspace_button_size(window, workspace->name, &button_width, &button_height);
|
||||
|
||||
button_x += button_width;
|
||||
if (x <= button_x) {
|
||||
ipc_send_workspace_command(workspace->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id) {
|
||||
/* initialize bar with default values */
|
||||
bar_init(bar);
|
||||
|
@ -92,6 +123,9 @@ void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id) {
|
|||
/* set font */
|
||||
bar_output->window->font = bar->config->font;
|
||||
|
||||
/* set font */
|
||||
bar_output->window->pointer_input.notify = mouse_button_notify;
|
||||
|
||||
/* set window height */
|
||||
set_window_height(bar_output->window, bar->config->height);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,15 @@
|
|||
#include "bar/config.h"
|
||||
#include "bar/ipc.h"
|
||||
|
||||
void ipc_send_workspace_command(const char *workspace_name) {
|
||||
uint32_t size = strlen("workspace ") + strlen(workspace_name) + 1;
|
||||
|
||||
char command[size];
|
||||
sprintf(command, "workspace %s", workspace_name);
|
||||
|
||||
ipc_single_command(swaybar.ipc_socketfd, IPC_COMMAND, command, &size);
|
||||
}
|
||||
|
||||
static void ipc_parse_config(struct config *config, const char *payload) {
|
||||
json_object *bar_config = json_tokener_parse(payload);
|
||||
json_object *tray_output, *mode, *hidden_bar, *position, *status_command;
|
||||
|
|
|
@ -172,7 +172,7 @@ static void render_block(struct window *window, struct config *config, struct st
|
|||
|
||||
}
|
||||
|
||||
static char *handle_workspace_number(bool strip_num, const char *ws_name) {
|
||||
static const char *strip_workspace_name(bool strip_num, const char *ws_name) {
|
||||
bool strip = false;
|
||||
int i;
|
||||
|
||||
|
@ -190,18 +190,23 @@ static char *handle_workspace_number(bool strip_num, const char *ws_name) {
|
|||
}
|
||||
|
||||
if (strip) {
|
||||
return strdup(ws_name + i);
|
||||
return ws_name + i;
|
||||
}
|
||||
|
||||
return strdup(ws_name);
|
||||
return ws_name;
|
||||
}
|
||||
|
||||
void workspace_button_size(struct window *window, const char *workspace_name, int *width, int *height) {
|
||||
const char *stripped_name = strip_workspace_name(swaybar.config->strip_workspace_numbers, workspace_name);
|
||||
|
||||
get_text_size(window->cairo, window->font, width, height, false, "%s", stripped_name);
|
||||
*width += 2 * ws_horizontal_padding;
|
||||
*height += 2 * ws_vertical_padding;
|
||||
}
|
||||
|
||||
static void render_workspace_button(struct window *window, struct config *config, struct workspace *ws, double *x) {
|
||||
// strip workspace numbers if required
|
||||
char *name = handle_workspace_number(config->strip_workspace_numbers, ws->name);
|
||||
const char *stripped_name = strip_workspace_name(config->strip_workspace_numbers, ws->name);
|
||||
|
||||
int width, height;
|
||||
get_text_size(window->cairo, window->font, &width, &height, false, "%s", name);
|
||||
struct box_colors box_colors;
|
||||
if (ws->urgent) {
|
||||
box_colors = config->colors.urgent_workspace;
|
||||
|
@ -213,26 +218,25 @@ static void render_workspace_button(struct window *window, struct config *config
|
|||
box_colors = config->colors.inactive_workspace;
|
||||
}
|
||||
|
||||
int width, height;
|
||||
workspace_button_size(window, stripped_name, &width, &height);
|
||||
|
||||
// background
|
||||
cairo_set_source_u32(window->cairo, box_colors.background);
|
||||
cairo_rectangle(window->cairo, *x, 1.5, width + ws_horizontal_padding * 2 - 1,
|
||||
height + ws_vertical_padding * 2);
|
||||
cairo_rectangle(window->cairo, *x, 1.5, width - 1, height);
|
||||
cairo_fill(window->cairo);
|
||||
|
||||
// border
|
||||
cairo_set_source_u32(window->cairo, box_colors.border);
|
||||
cairo_rectangle(window->cairo, *x, 1.5, width + ws_horizontal_padding * 2 - 1,
|
||||
height + ws_vertical_padding * 2);
|
||||
cairo_rectangle(window->cairo, *x, 1.5, width - 1, height);
|
||||
cairo_stroke(window->cairo);
|
||||
|
||||
// text
|
||||
cairo_set_source_u32(window->cairo, box_colors.text);
|
||||
cairo_move_to(window->cairo, (int)*x + ws_horizontal_padding, margin);
|
||||
pango_printf(window->cairo, window->font, false, "%s", name);
|
||||
pango_printf(window->cairo, window->font, false, "%s", stripped_name);
|
||||
|
||||
*x += width + ws_horizontal_padding * 2 + ws_spacing;
|
||||
|
||||
free(name);
|
||||
*x += width + ws_spacing;
|
||||
}
|
||||
|
||||
static void render_binding_mode_indicator(struct window *window, struct config *config, double pos) {
|
||||
|
|
|
@ -54,7 +54,6 @@ int main(int argc, const char **argv) {
|
|||
sway_abort("Failed to create surfaces.");
|
||||
}
|
||||
desktop_shell_set_background(registry->desktop_shell, output->output, window->surface);
|
||||
window_make_shell(window);
|
||||
list_add(surfaces, window);
|
||||
|
||||
#ifdef WITH_GDK_PIXBUF
|
||||
|
|
|
@ -32,8 +32,8 @@ static void pointer_handle_motion(void *data, struct wl_pointer *pointer,
|
|||
uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) {
|
||||
struct window *window = data;
|
||||
|
||||
window->pointer_input.last_x = sx_w;
|
||||
window->pointer_input.last_y = sy_w;
|
||||
window->pointer_input.last_x = wl_fixed_to_int(sx_w);
|
||||
window->pointer_input.last_y = wl_fixed_to_int(sy_w);
|
||||
}
|
||||
|
||||
static void pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
|
||||
|
|
Loading…
Reference in a new issue