Skip to content

Commit 0ef3988

Browse files
committed
swaynag: fix hidpi
1 parent e01acb6 commit 0ef3988

File tree

4 files changed

+95
-62
lines changed

4 files changed

+95
-62
lines changed

include/swaynag/swaynag.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
#define SWAYNAG_MAX_HEIGHT 500
1111

12+
struct swaynag;
13+
1214
enum swaynag_action_type {
1315
SWAYNAG_ACTION_DISMISS,
1416
SWAYNAG_ACTION_EXPAND,
@@ -28,6 +30,9 @@ struct swaynag_output {
2830
char *name;
2931
struct wl_output *wl_output;
3032
uint32_t wl_name;
33+
uint32_t scale;
34+
struct swaynag *swaynag;
35+
struct wl_list link;
3136
};
3237

3338
struct swaynag_button {
@@ -67,7 +72,8 @@ struct swaynag {
6772
struct wl_shm *shm;
6873
struct swaynag_pointer pointer;
6974
struct zxdg_output_manager_v1 *xdg_output_manager;
70-
struct swaynag_output output;
75+
struct wl_list outputs; // struct swaynag_output
76+
struct swaynag_output *output;
7177
struct zwlr_layer_shell_v1 *layer_shell;
7278
struct zwlr_layer_surface_v1 *layer_surface;
7379
struct wl_surface *surface;

swaynag/main.c

+1-4
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,6 @@ int main(int argc, char **argv) {
9494
swaynag_type_merge(type, swaynag_type_get(types, "<config>"));
9595
swaynag_type_merge(type, swaynag_type_get(types, "<defaults>"));
9696
swaynag.type = type;
97-
if (swaynag.type->output) {
98-
swaynag.output.name = strdup(swaynag.type->output);
99-
}
10097

10198
swaynag_types_free(types);
10299

@@ -106,7 +103,7 @@ int main(int argc, char **argv) {
106103
free(swaynag.details.button_details.text);
107104
}
108105

109-
wlr_log(WLR_DEBUG, "Output: %s", swaynag.output.name);
106+
wlr_log(WLR_DEBUG, "Output: %s", swaynag.type->output);
110107
wlr_log(WLR_DEBUG, "Anchors: %d", swaynag.type->anchors);
111108
wlr_log(WLR_DEBUG, "Type: %s", swaynag.type->name);
112109
wlr_log(WLR_DEBUG, "Message: %s", swaynag.message);

swaynag/render.c

+14-10
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ static uint32_t render_message(cairo_t *cairo, struct swaynag *swaynag) {
2525

2626
cairo_set_source_u32(cairo, swaynag->type->text);
2727
cairo_move_to(cairo, padding, (int)(ideal_height - text_height) / 2);
28-
pango_printf(cairo, swaynag->type->font, swaynag->scale, false, "%s",
29-
swaynag->message);
28+
pango_printf(cairo, swaynag->type->font, swaynag->scale, false,
29+
"%s", swaynag->message);
3030

31-
return ideal_height;
31+
return ideal_surface_height;
3232
}
3333

3434
static void render_details_scroll_button(cairo_t *cairo,
@@ -61,9 +61,11 @@ static int get_detailed_scroll_button_width(cairo_t *cairo,
6161
struct swaynag *swaynag) {
6262
int up_width, down_width, temp_height;
6363
get_text_size(cairo, swaynag->type->font, &up_width, &temp_height,
64-
swaynag->scale, true, "%s", swaynag->details.button_up.text);
64+
swaynag->scale, true,
65+
"%s", swaynag->details.button_up.text);
6566
get_text_size(cairo, swaynag->type->font, &down_width, &temp_height,
66-
swaynag->scale, true, "%s", swaynag->details.button_down.text);
67+
swaynag->scale, true,
68+
"%s", swaynag->details.button_down.text);
6769

6870
int text_width = up_width > down_width ? up_width : down_width;
6971
int border = swaynag->type->button_border_thickness * swaynag->scale;
@@ -83,7 +85,7 @@ static uint32_t render_detailed(cairo_t *cairo, struct swaynag *swaynag,
8385
int decor = padding + border;
8486

8587
swaynag->details.x = decor;
86-
swaynag->details.y = y + decor;
88+
swaynag->details.y = y * swaynag->scale + decor;
8789
swaynag->details.width = width - decor * 2;
8890

8991
PangoLayout *layout = get_pango_layout(cairo, swaynag->type->font,
@@ -167,7 +169,7 @@ static uint32_t render_detailed(cairo_t *cairo, struct swaynag *swaynag,
167169
pango_cairo_show_layout(cairo, layout);
168170
g_object_unref(layout);
169171

170-
return ideal_height;
172+
return ideal_height / swaynag->scale;
171173
}
172174

173175
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,
211213

212214
*x = button->x - border;
213215

214-
return ideal_height;
216+
return ideal_surface_height;
215217
}
216218

217219
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) {
245247
max_height += border;
246248
}
247249
cairo_set_source_u32(cairo, swaynag->type->border_bottom);
248-
cairo_rectangle(cairo, 0, swaynag->height * swaynag->scale - border,
249-
swaynag->width * swaynag->scale, border);
250+
cairo_rectangle(cairo, 0,
251+
swaynag->height * swaynag->scale - border,
252+
swaynag->width * swaynag->scale,
253+
border);
250254
cairo_fill(cairo);
251255

252256
return max_height;

swaynag/swaynag.c

+73-47
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,34 @@ static struct zwlr_layer_surface_v1_listener layer_surface_listener = {
8585
.closed = layer_surface_closed,
8686
};
8787

88+
static void surface_enter(void *data, struct wl_surface *surface,
89+
struct wl_output *output) {
90+
struct swaynag *swaynag = data;
91+
struct swaynag_output *swaynag_output;
92+
wl_list_for_each(swaynag_output, &swaynag->outputs, link) {
93+
if (swaynag_output->wl_output == output) {
94+
wlr_log(WLR_DEBUG, "Surface enter on output %s",
95+
swaynag_output->name);
96+
swaynag->output = swaynag_output;
97+
swaynag->scale = swaynag->output->scale;
98+
render_frame(swaynag);
99+
break;
100+
}
101+
};
102+
}
103+
104+
static struct wl_surface_listener surface_listener = {
105+
.enter = surface_enter,
106+
.leave = nop,
107+
};
108+
88109
static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer,
89110
uint32_t serial, struct wl_surface *surface,
90111
wl_fixed_t surface_x, wl_fixed_t surface_y) {
91112
struct swaynag *swaynag = data;
92113
struct swaynag_pointer *pointer = &swaynag->pointer;
93-
wl_surface_set_buffer_scale(pointer->cursor_surface, swaynag->scale);
114+
wl_surface_set_buffer_scale(pointer->cursor_surface,
115+
swaynag->scale);
94116
wl_surface_attach(pointer->cursor_surface,
95117
wl_cursor_image_get_buffer(pointer->cursor_image), 0, 0);
96118
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,
141163
}
142164

143165
struct swaynag_button button_down = swaynag->details.button_down;
144-
int bot = swaynag->details.total_lines - swaynag->details.visible_lines;
166+
int bot = swaynag->details.total_lines;
167+
bot -= swaynag->details.visible_lines;
145168
if (x >= button_down.x
146169
&& y >= button_down.y
147170
&& x < button_down.x + button_down.width
@@ -206,9 +229,12 @@ const struct wl_seat_listener seat_listener = {
206229

207230
static void output_scale(void *data, struct wl_output *output,
208231
int32_t factor) {
209-
struct swaynag *swaynag = data;
210-
swaynag->scale = factor;
211-
render_frame(swaynag);
232+
struct swaynag_output *swaynag_output = data;
233+
swaynag_output->scale = factor;
234+
if (swaynag_output->swaynag->output == swaynag_output) {
235+
swaynag_output->swaynag->scale = swaynag_output->scale;
236+
render_frame(swaynag_output->swaynag);
237+
}
212238
}
213239

214240
static struct wl_output_listener output_listener = {
@@ -218,33 +244,19 @@ static struct wl_output_listener output_listener = {
218244
.scale = output_scale,
219245
};
220246

221-
struct output_state {
222-
struct wl_output *wl_output;
223-
uint32_t wl_name;
224-
struct zxdg_output_v1 *xdg_output;
225-
struct swaynag *swaynag;
226-
};
227-
228247
static void xdg_output_handle_name(void *data,
229248
struct zxdg_output_v1 *xdg_output, const char *name) {
230-
struct output_state *state = data;
231-
char *outname = state->swaynag->output.name;
249+
struct swaynag_output *swaynag_output = data;
250+
char *outname = swaynag_output->swaynag->type->output;
232251
wlr_log(WLR_DEBUG, "Checking against output %s for %s", name, outname);
233-
if (!state->swaynag->output.wl_output && outname && name
252+
if (!swaynag_output->swaynag->output && outname && name
234253
&& strcmp(outname, name) == 0) {
235254
wlr_log(WLR_DEBUG, "Using output %s", name);
236-
state->swaynag->output.wl_output = state->wl_output;
237-
state->swaynag->output.wl_name = state->wl_name;
238-
wl_output_add_listener(state->swaynag->output.wl_output,
239-
&output_listener, state->swaynag);
240-
wl_display_roundtrip(state->swaynag->display);
241-
zxdg_output_v1_destroy(state->xdg_output);
242-
} else {
243-
zxdg_output_v1_destroy(state->xdg_output);
244-
wl_output_destroy(state->wl_output);
255+
swaynag_output->swaynag->output = swaynag_output;
245256
}
246-
state->swaynag->querying_outputs--;
247-
free(state);
257+
swaynag_output->name = strdup(name);
258+
zxdg_output_v1_destroy(xdg_output);
259+
swaynag_output->swaynag->querying_outputs--;
248260
}
249261

250262
static struct zxdg_output_v1_listener xdg_output_listener = {
@@ -267,18 +279,24 @@ static void handle_global(void *data, struct wl_registry *registry,
267279
} else if (strcmp(interface, wl_shm_interface.name) == 0) {
268280
swaynag->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
269281
} else if (strcmp(interface, wl_output_interface.name) == 0) {
270-
if (!swaynag->output.wl_output && swaynag->xdg_output_manager) {
282+
if (!swaynag->output && swaynag->xdg_output_manager) {
271283
swaynag->querying_outputs++;
272-
struct output_state *state =
273-
calloc(1, sizeof(struct output_state));
274-
state->swaynag = swaynag;
275-
state->wl_output = wl_registry_bind(registry, name,
284+
struct swaynag_output *output =
285+
calloc(1, sizeof(struct swaynag_output));
286+
output->wl_output = wl_registry_bind(registry, name,
276287
&wl_output_interface, 3);
277-
state->wl_name = name;
278-
state->xdg_output = zxdg_output_manager_v1_get_xdg_output(
279-
swaynag->xdg_output_manager, state->wl_output);
280-
zxdg_output_v1_add_listener(state->xdg_output,
281-
&xdg_output_listener, state);
288+
output->wl_name = name;
289+
output->scale = 1;
290+
output->swaynag = swaynag;
291+
wl_list_insert(&swaynag->outputs, &output->link);
292+
wl_output_add_listener(output->wl_output,
293+
&output_listener, output);
294+
295+
struct zxdg_output_v1 *xdg_output;
296+
xdg_output = zxdg_output_manager_v1_get_xdg_output(
297+
swaynag->xdg_output_manager, output->wl_output);
298+
zxdg_output_v1_add_listener(xdg_output,
299+
&xdg_output_listener, output);
282300
}
283301
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
284302
swaynag->layer_shell = wl_registry_bind(
@@ -294,7 +312,7 @@ static void handle_global(void *data, struct wl_registry *registry,
294312
static void handle_global_remove(void *data, struct wl_registry *registry,
295313
uint32_t name) {
296314
struct swaynag *swaynag = data;
297-
if (swaynag->output.wl_name == name) {
315+
if (swaynag->output->wl_name == name) {
298316
swaynag->run_display = false;
299317
}
300318
}
@@ -309,6 +327,7 @@ void swaynag_setup(struct swaynag *swaynag) {
309327
assert(swaynag->display);
310328

311329
swaynag->scale = 1;
330+
wl_list_init(&swaynag->outputs);
312331

313332
struct wl_registry *registry = wl_display_get_registry(swaynag->display);
314333
wl_registry_add_listener(registry, &registry_listener, swaynag);
@@ -319,16 +338,16 @@ void swaynag_setup(struct swaynag *swaynag) {
319338
wl_display_roundtrip(swaynag->display);
320339
}
321340

322-
if (!swaynag->output.wl_output && swaynag->output.name) {
323-
wlr_log(WLR_ERROR, "Output '%s' not found", swaynag->output.name);
341+
if (!swaynag->output && swaynag->type->output) {
342+
wlr_log(WLR_ERROR, "Output '%s' not found", swaynag->type->output);
324343
swaynag_destroy(swaynag);
325344
exit(EXIT_FAILURE);
326345
}
327346

328347
struct swaynag_pointer *pointer = &swaynag->pointer;
329-
int scale = swaynag->scale < 1 ? 1 : swaynag->scale;
330-
pointer->cursor_theme = wl_cursor_theme_load(
331-
NULL, 24 * scale, swaynag->shm);
348+
int scale = swaynag->output ? swaynag->scale : 1;
349+
pointer->cursor_theme = wl_cursor_theme_load(NULL, 24 * scale,
350+
swaynag->shm);
332351
assert(pointer->cursor_theme);
333352
struct wl_cursor *cursor =
334353
wl_cursor_theme_get_cursor(pointer->cursor_theme, "left_ptr");
@@ -339,8 +358,11 @@ void swaynag_setup(struct swaynag *swaynag) {
339358

340359
swaynag->surface = wl_compositor_create_surface(swaynag->compositor);
341360
assert(swaynag->surface);
361+
wl_surface_add_listener(swaynag->surface, &surface_listener, swaynag);
362+
342363
swaynag->layer_surface = zwlr_layer_shell_v1_get_layer_surface(
343-
swaynag->layer_shell, swaynag->surface, swaynag->output.wl_output,
364+
swaynag->layer_shell, swaynag->surface,
365+
swaynag->output ? swaynag->output->wl_output : NULL,
344366
ZWLR_LAYER_SHELL_V1_LAYER_TOP, "swaynag");
345367
assert(swaynag->layer_surface);
346368
zwlr_layer_surface_v1_add_listener(swaynag->layer_surface,
@@ -388,10 +410,6 @@ void swaynag_destroy(struct swaynag *swaynag) {
388410
wl_surface_destroy(swaynag->surface);
389411
}
390412

391-
if (swaynag->output.wl_output) {
392-
wl_output_destroy(swaynag->output.wl_output);
393-
}
394-
395413
if (&swaynag->buffers[0]) {
396414
destroy_buffer(&swaynag->buffers[0]);
397415
}
@@ -400,6 +418,14 @@ void swaynag_destroy(struct swaynag *swaynag) {
400418
destroy_buffer(&swaynag->buffers[1]);
401419
}
402420

421+
struct swaynag_output *output, *temp;
422+
wl_list_for_each_safe(output, temp, &swaynag->outputs, link) {
423+
wl_output_destroy(output->wl_output);
424+
free(output->name);
425+
wl_list_remove(&output->link);
426+
free(output);
427+
};
428+
403429
if (swaynag->compositor) {
404430
wl_compositor_destroy(swaynag->compositor);
405431
}

0 commit comments

Comments
 (0)