swaynag: fix hidpi

This commit is contained in:
Brian Ashworth 2018-07-30 01:02:50 -04:00
parent e01acb6097
commit 0ef3988438
4 changed files with 95 additions and 62 deletions

View file

@ -9,6 +9,8 @@
#define SWAYNAG_MAX_HEIGHT 500 #define SWAYNAG_MAX_HEIGHT 500
struct swaynag;
enum swaynag_action_type { enum swaynag_action_type {
SWAYNAG_ACTION_DISMISS, SWAYNAG_ACTION_DISMISS,
SWAYNAG_ACTION_EXPAND, SWAYNAG_ACTION_EXPAND,
@ -28,6 +30,9 @@ struct swaynag_output {
char *name; char *name;
struct wl_output *wl_output; struct wl_output *wl_output;
uint32_t wl_name; uint32_t wl_name;
uint32_t scale;
struct swaynag *swaynag;
struct wl_list link;
}; };
struct swaynag_button { struct swaynag_button {
@ -67,7 +72,8 @@ struct swaynag {
struct wl_shm *shm; struct wl_shm *shm;
struct swaynag_pointer pointer; struct swaynag_pointer pointer;
struct zxdg_output_manager_v1 *xdg_output_manager; struct zxdg_output_manager_v1 *xdg_output_manager;
struct swaynag_output output; struct wl_list outputs; // struct swaynag_output
struct swaynag_output *output;
struct zwlr_layer_shell_v1 *layer_shell; struct zwlr_layer_shell_v1 *layer_shell;
struct zwlr_layer_surface_v1 *layer_surface; struct zwlr_layer_surface_v1 *layer_surface;
struct wl_surface *surface; struct wl_surface *surface;

View file

@ -94,9 +94,6 @@ int main(int argc, char **argv) {
swaynag_type_merge(type, swaynag_type_get(types, "<config>")); swaynag_type_merge(type, swaynag_type_get(types, "<config>"));
swaynag_type_merge(type, swaynag_type_get(types, "<defaults>")); swaynag_type_merge(type, swaynag_type_get(types, "<defaults>"));
swaynag.type = type; swaynag.type = type;
if (swaynag.type->output) {
swaynag.output.name = strdup(swaynag.type->output);
}
swaynag_types_free(types); swaynag_types_free(types);
@ -106,7 +103,7 @@ int main(int argc, char **argv) {
free(swaynag.details.button_details.text); free(swaynag.details.button_details.text);
} }
wlr_log(WLR_DEBUG, "Output: %s", swaynag.output.name); wlr_log(WLR_DEBUG, "Output: %s", swaynag.type->output);
wlr_log(WLR_DEBUG, "Anchors: %d", swaynag.type->anchors); wlr_log(WLR_DEBUG, "Anchors: %d", swaynag.type->anchors);
wlr_log(WLR_DEBUG, "Type: %s", swaynag.type->name); wlr_log(WLR_DEBUG, "Type: %s", swaynag.type->name);
wlr_log(WLR_DEBUG, "Message: %s", swaynag.message); wlr_log(WLR_DEBUG, "Message: %s", swaynag.message);

View file

@ -25,10 +25,10 @@ static uint32_t render_message(cairo_t *cairo, struct swaynag *swaynag) {
cairo_set_source_u32(cairo, swaynag->type->text); cairo_set_source_u32(cairo, swaynag->type->text);
cairo_move_to(cairo, padding, (int)(ideal_height - text_height) / 2); cairo_move_to(cairo, padding, (int)(ideal_height - text_height) / 2);
pango_printf(cairo, swaynag->type->font, swaynag->scale, false, "%s", pango_printf(cairo, swaynag->type->font, swaynag->scale, false,
swaynag->message); "%s", swaynag->message);
return ideal_height; return ideal_surface_height;
} }
static void render_details_scroll_button(cairo_t *cairo, static void render_details_scroll_button(cairo_t *cairo,
@ -61,9 +61,11 @@ static int get_detailed_scroll_button_width(cairo_t *cairo,
struct swaynag *swaynag) { struct swaynag *swaynag) {
int up_width, down_width, temp_height; int up_width, down_width, temp_height;
get_text_size(cairo, swaynag->type->font, &up_width, &temp_height, get_text_size(cairo, swaynag->type->font, &up_width, &temp_height,
swaynag->scale, true, "%s", swaynag->details.button_up.text); swaynag->scale, true,
"%s", swaynag->details.button_up.text);
get_text_size(cairo, swaynag->type->font, &down_width, &temp_height, get_text_size(cairo, swaynag->type->font, &down_width, &temp_height,
swaynag->scale, true, "%s", swaynag->details.button_down.text); swaynag->scale, true,
"%s", swaynag->details.button_down.text);
int text_width = up_width > down_width ? up_width : down_width; int text_width = up_width > down_width ? up_width : down_width;
int border = swaynag->type->button_border_thickness * swaynag->scale; int border = swaynag->type->button_border_thickness * swaynag->scale;
@ -83,7 +85,7 @@ static uint32_t render_detailed(cairo_t *cairo, struct swaynag *swaynag,
int decor = padding + border; int decor = padding + border;
swaynag->details.x = decor; swaynag->details.x = decor;
swaynag->details.y = y + decor; swaynag->details.y = y * swaynag->scale + decor;
swaynag->details.width = width - decor * 2; swaynag->details.width = width - decor * 2;
PangoLayout *layout = get_pango_layout(cairo, swaynag->type->font, PangoLayout *layout = get_pango_layout(cairo, swaynag->type->font,
@ -167,7 +169,7 @@ static uint32_t render_detailed(cairo_t *cairo, struct swaynag *swaynag,
pango_cairo_show_layout(cairo, layout); pango_cairo_show_layout(cairo, layout);
g_object_unref(layout); g_object_unref(layout);
return ideal_height; return ideal_height / swaynag->scale;
} }
static uint32_t render_button(cairo_t *cairo, struct swaynag *swaynag, static uint32_t render_button(cairo_t *cairo, struct swaynag *swaynag,
@ -211,7 +213,7 @@ static uint32_t render_button(cairo_t *cairo, struct swaynag *swaynag,
*x = button->x - border; *x = button->x - border;
return ideal_height; return ideal_surface_height;
} }
static uint32_t render_to_cairo(cairo_t *cairo, struct swaynag *swaynag) { static uint32_t render_to_cairo(cairo_t *cairo, struct swaynag *swaynag) {
@ -245,8 +247,10 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct swaynag *swaynag) {
max_height += border; max_height += border;
} }
cairo_set_source_u32(cairo, swaynag->type->border_bottom); cairo_set_source_u32(cairo, swaynag->type->border_bottom);
cairo_rectangle(cairo, 0, swaynag->height * swaynag->scale - border, cairo_rectangle(cairo, 0,
swaynag->width * swaynag->scale, border); swaynag->height * swaynag->scale - border,
swaynag->width * swaynag->scale,
border);
cairo_fill(cairo); cairo_fill(cairo);
return max_height; return max_height;

View file

@ -85,12 +85,34 @@ static struct zwlr_layer_surface_v1_listener layer_surface_listener = {
.closed = layer_surface_closed, .closed = layer_surface_closed,
}; };
static void surface_enter(void *data, struct wl_surface *surface,
struct wl_output *output) {
struct swaynag *swaynag = data;
struct swaynag_output *swaynag_output;
wl_list_for_each(swaynag_output, &swaynag->outputs, link) {
if (swaynag_output->wl_output == output) {
wlr_log(WLR_DEBUG, "Surface enter on output %s",
swaynag_output->name);
swaynag->output = swaynag_output;
swaynag->scale = swaynag->output->scale;
render_frame(swaynag);
break;
}
};
}
static struct wl_surface_listener surface_listener = {
.enter = surface_enter,
.leave = nop,
};
static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer,
uint32_t serial, struct wl_surface *surface, uint32_t serial, struct wl_surface *surface,
wl_fixed_t surface_x, wl_fixed_t surface_y) { wl_fixed_t surface_x, wl_fixed_t surface_y) {
struct swaynag *swaynag = data; struct swaynag *swaynag = data;
struct swaynag_pointer *pointer = &swaynag->pointer; struct swaynag_pointer *pointer = &swaynag->pointer;
wl_surface_set_buffer_scale(pointer->cursor_surface, swaynag->scale); wl_surface_set_buffer_scale(pointer->cursor_surface,
swaynag->scale);
wl_surface_attach(pointer->cursor_surface, wl_surface_attach(pointer->cursor_surface,
wl_cursor_image_get_buffer(pointer->cursor_image), 0, 0); wl_cursor_image_get_buffer(pointer->cursor_image), 0, 0);
wl_pointer_set_cursor(wl_pointer, serial, pointer->cursor_surface, wl_pointer_set_cursor(wl_pointer, serial, pointer->cursor_surface,
@ -141,7 +163,8 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
} }
struct swaynag_button button_down = swaynag->details.button_down; struct swaynag_button button_down = swaynag->details.button_down;
int bot = swaynag->details.total_lines - swaynag->details.visible_lines; int bot = swaynag->details.total_lines;
bot -= swaynag->details.visible_lines;
if (x >= button_down.x if (x >= button_down.x
&& y >= button_down.y && y >= button_down.y
&& x < button_down.x + button_down.width && x < button_down.x + button_down.width
@ -206,9 +229,12 @@ const struct wl_seat_listener seat_listener = {
static void output_scale(void *data, struct wl_output *output, static void output_scale(void *data, struct wl_output *output,
int32_t factor) { int32_t factor) {
struct swaynag *swaynag = data; struct swaynag_output *swaynag_output = data;
swaynag->scale = factor; swaynag_output->scale = factor;
render_frame(swaynag); if (swaynag_output->swaynag->output == swaynag_output) {
swaynag_output->swaynag->scale = swaynag_output->scale;
render_frame(swaynag_output->swaynag);
}
} }
static struct wl_output_listener output_listener = { static struct wl_output_listener output_listener = {
@ -218,33 +244,19 @@ static struct wl_output_listener output_listener = {
.scale = output_scale, .scale = output_scale,
}; };
struct output_state {
struct wl_output *wl_output;
uint32_t wl_name;
struct zxdg_output_v1 *xdg_output;
struct swaynag *swaynag;
};
static void xdg_output_handle_name(void *data, static void xdg_output_handle_name(void *data,
struct zxdg_output_v1 *xdg_output, const char *name) { struct zxdg_output_v1 *xdg_output, const char *name) {
struct output_state *state = data; struct swaynag_output *swaynag_output = data;
char *outname = state->swaynag->output.name; char *outname = swaynag_output->swaynag->type->output;
wlr_log(WLR_DEBUG, "Checking against output %s for %s", name, outname); wlr_log(WLR_DEBUG, "Checking against output %s for %s", name, outname);
if (!state->swaynag->output.wl_output && outname && name if (!swaynag_output->swaynag->output && outname && name
&& strcmp(outname, name) == 0) { && strcmp(outname, name) == 0) {
wlr_log(WLR_DEBUG, "Using output %s", name); wlr_log(WLR_DEBUG, "Using output %s", name);
state->swaynag->output.wl_output = state->wl_output; swaynag_output->swaynag->output = swaynag_output;
state->swaynag->output.wl_name = state->wl_name;
wl_output_add_listener(state->swaynag->output.wl_output,
&output_listener, state->swaynag);
wl_display_roundtrip(state->swaynag->display);
zxdg_output_v1_destroy(state->xdg_output);
} else {
zxdg_output_v1_destroy(state->xdg_output);
wl_output_destroy(state->wl_output);
} }
state->swaynag->querying_outputs--; swaynag_output->name = strdup(name);
free(state); zxdg_output_v1_destroy(xdg_output);
swaynag_output->swaynag->querying_outputs--;
} }
static struct zxdg_output_v1_listener xdg_output_listener = { static struct zxdg_output_v1_listener xdg_output_listener = {
@ -267,18 +279,24 @@ static void handle_global(void *data, struct wl_registry *registry,
} else if (strcmp(interface, wl_shm_interface.name) == 0) { } else if (strcmp(interface, wl_shm_interface.name) == 0) {
swaynag->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); swaynag->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
} else if (strcmp(interface, wl_output_interface.name) == 0) { } else if (strcmp(interface, wl_output_interface.name) == 0) {
if (!swaynag->output.wl_output && swaynag->xdg_output_manager) { if (!swaynag->output && swaynag->xdg_output_manager) {
swaynag->querying_outputs++; swaynag->querying_outputs++;
struct output_state *state = struct swaynag_output *output =
calloc(1, sizeof(struct output_state)); calloc(1, sizeof(struct swaynag_output));
state->swaynag = swaynag; output->wl_output = wl_registry_bind(registry, name,
state->wl_output = wl_registry_bind(registry, name,
&wl_output_interface, 3); &wl_output_interface, 3);
state->wl_name = name; output->wl_name = name;
state->xdg_output = zxdg_output_manager_v1_get_xdg_output( output->scale = 1;
swaynag->xdg_output_manager, state->wl_output); output->swaynag = swaynag;
zxdg_output_v1_add_listener(state->xdg_output, wl_list_insert(&swaynag->outputs, &output->link);
&xdg_output_listener, state); wl_output_add_listener(output->wl_output,
&output_listener, output);
struct zxdg_output_v1 *xdg_output;
xdg_output = zxdg_output_manager_v1_get_xdg_output(
swaynag->xdg_output_manager, output->wl_output);
zxdg_output_v1_add_listener(xdg_output,
&xdg_output_listener, output);
} }
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
swaynag->layer_shell = wl_registry_bind( swaynag->layer_shell = wl_registry_bind(
@ -294,7 +312,7 @@ static void handle_global(void *data, struct wl_registry *registry,
static void handle_global_remove(void *data, struct wl_registry *registry, static void handle_global_remove(void *data, struct wl_registry *registry,
uint32_t name) { uint32_t name) {
struct swaynag *swaynag = data; struct swaynag *swaynag = data;
if (swaynag->output.wl_name == name) { if (swaynag->output->wl_name == name) {
swaynag->run_display = false; swaynag->run_display = false;
} }
} }
@ -309,6 +327,7 @@ void swaynag_setup(struct swaynag *swaynag) {
assert(swaynag->display); assert(swaynag->display);
swaynag->scale = 1; swaynag->scale = 1;
wl_list_init(&swaynag->outputs);
struct wl_registry *registry = wl_display_get_registry(swaynag->display); struct wl_registry *registry = wl_display_get_registry(swaynag->display);
wl_registry_add_listener(registry, &registry_listener, swaynag); wl_registry_add_listener(registry, &registry_listener, swaynag);
@ -319,16 +338,16 @@ void swaynag_setup(struct swaynag *swaynag) {
wl_display_roundtrip(swaynag->display); wl_display_roundtrip(swaynag->display);
} }
if (!swaynag->output.wl_output && swaynag->output.name) { if (!swaynag->output && swaynag->type->output) {
wlr_log(WLR_ERROR, "Output '%s' not found", swaynag->output.name); wlr_log(WLR_ERROR, "Output '%s' not found", swaynag->type->output);
swaynag_destroy(swaynag); swaynag_destroy(swaynag);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
struct swaynag_pointer *pointer = &swaynag->pointer; struct swaynag_pointer *pointer = &swaynag->pointer;
int scale = swaynag->scale < 1 ? 1 : swaynag->scale; int scale = swaynag->output ? swaynag->scale : 1;
pointer->cursor_theme = wl_cursor_theme_load( pointer->cursor_theme = wl_cursor_theme_load(NULL, 24 * scale,
NULL, 24 * scale, swaynag->shm); swaynag->shm);
assert(pointer->cursor_theme); assert(pointer->cursor_theme);
struct wl_cursor *cursor = struct wl_cursor *cursor =
wl_cursor_theme_get_cursor(pointer->cursor_theme, "left_ptr"); wl_cursor_theme_get_cursor(pointer->cursor_theme, "left_ptr");
@ -339,8 +358,11 @@ void swaynag_setup(struct swaynag *swaynag) {
swaynag->surface = wl_compositor_create_surface(swaynag->compositor); swaynag->surface = wl_compositor_create_surface(swaynag->compositor);
assert(swaynag->surface); assert(swaynag->surface);
wl_surface_add_listener(swaynag->surface, &surface_listener, swaynag);
swaynag->layer_surface = zwlr_layer_shell_v1_get_layer_surface( swaynag->layer_surface = zwlr_layer_shell_v1_get_layer_surface(
swaynag->layer_shell, swaynag->surface, swaynag->output.wl_output, swaynag->layer_shell, swaynag->surface,
swaynag->output ? swaynag->output->wl_output : NULL,
ZWLR_LAYER_SHELL_V1_LAYER_TOP, "swaynag"); ZWLR_LAYER_SHELL_V1_LAYER_TOP, "swaynag");
assert(swaynag->layer_surface); assert(swaynag->layer_surface);
zwlr_layer_surface_v1_add_listener(swaynag->layer_surface, zwlr_layer_surface_v1_add_listener(swaynag->layer_surface,
@ -388,10 +410,6 @@ void swaynag_destroy(struct swaynag *swaynag) {
wl_surface_destroy(swaynag->surface); wl_surface_destroy(swaynag->surface);
} }
if (swaynag->output.wl_output) {
wl_output_destroy(swaynag->output.wl_output);
}
if (&swaynag->buffers[0]) { if (&swaynag->buffers[0]) {
destroy_buffer(&swaynag->buffers[0]); destroy_buffer(&swaynag->buffers[0]);
} }
@ -400,6 +418,14 @@ void swaynag_destroy(struct swaynag *swaynag) {
destroy_buffer(&swaynag->buffers[1]); destroy_buffer(&swaynag->buffers[1]);
} }
struct swaynag_output *output, *temp;
wl_list_for_each_safe(output, temp, &swaynag->outputs, link) {
wl_output_destroy(output->wl_output);
free(output->name);
wl_list_remove(&output->link);
free(output);
};
if (swaynag->compositor) { if (swaynag->compositor) {
wl_compositor_destroy(swaynag->compositor); wl_compositor_destroy(swaynag->compositor);
} }