diff --git a/include/config.h b/include/config.h index 87e231877..5e1c123ec 100644 --- a/include/config.h +++ b/include/config.h @@ -81,6 +81,7 @@ struct output_config { int enabled; int width, height; int x, y; + int scale; char *background; char *background_option; }; diff --git a/include/output.h b/include/output.h index 10c5bb533..e8afd5ed6 100644 --- a/include/output.h +++ b/include/output.h @@ -19,4 +19,6 @@ void get_absolute_center_position(swayc_t *container, struct wlc_point *point); // stable sort workspaces on this output void sort_workspaces(swayc_t *output); +void output_get_scaled_size(wlc_handle handle, struct wlc_size *size); + #endif diff --git a/sway/commands.c b/sway/commands.c index d572afa08..053b57927 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -1585,6 +1585,7 @@ static struct cmd_results *cmd_output(int argc, char **argv) { output->x = output->y = output->width = output->height = -1; output->name = strdup(name); output->enabled = -1; + output->scale = 1; // TODO: atoi doesn't handle invalid numbers @@ -1642,6 +1643,11 @@ static struct cmd_results *cmd_output(int argc, char **argv) { } output->x = x; output->y = y; + } else if (strcasecmp(command, "scale") == 0) { + if (++i >= argc) { + return cmd_results_new(CMD_INVALID, "output", "Missing scale parameter."); + } + output->scale = atoi(argv[i]); } else if (strcasecmp(command, "background") == 0 || strcasecmp(command, "bg") == 0) { wordexp_t p; if (++i >= argc) { @@ -1700,10 +1706,10 @@ static struct cmd_results *cmd_output(int argc, char **argv) { list_add(config->output_configs, output); } - sway_log(L_DEBUG, "Config stored for output %s (enabled:%d) (%d x %d @ %d, %d) (bg %s %s)", + sway_log(L_DEBUG, "Config stored for output %s (enabled:%d) (%d x %d @ %d, %d scale %d) (bg %s %s)", output->name, output->enabled, output->width, - output->height, output->x, output->y, output->background, - output->background_option); + output->height, output->x, output->y, output->scale, + output->background, output->background_option); if (output->name) { // Try to find the output container and apply configuration now. If diff --git a/sway/config.c b/sway/config.c index 5e1887a68..25566213a 100644 --- a/sway/config.c +++ b/sway/config.c @@ -863,9 +863,12 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { output->width = oc->width; output->height = oc->height; - sway_log(L_DEBUG, "Set %s size to %ix%i", oc->name, oc->width, oc->height); + sway_log(L_DEBUG, "Set %s size to %ix%i (%d)", oc->name, oc->width, oc->height, oc->scale); struct wlc_size new_size = { .w = oc->width, .h = oc->height }; - wlc_output_set_resolution(output->handle, &new_size); + wlc_output_set_resolution(output->handle, &new_size, (uint32_t)oc->scale); + } else if (oc && oc->scale != 1) { + const struct wlc_size *new_size = wlc_output_get_resolution(output->handle); + wlc_output_set_resolution(output->handle, new_size, (uint32_t)oc->scale); } // Find position for it diff --git a/sway/container.c b/sway/container.c index 67aa68514..c922bac3b 100644 --- a/sway/container.c +++ b/sway/container.c @@ -102,7 +102,8 @@ static void update_root_geometry() { // New containers swayc_t *new_output(wlc_handle handle) { - const struct wlc_size *size = wlc_output_get_resolution(handle); + struct wlc_size size; + output_get_scaled_size(handle, &size); const char *name = wlc_output_get_name(handle); // Find current outputs to see if this already exists { @@ -148,8 +149,8 @@ swayc_t *new_output(wlc_handle handle) { swayc_t *output = new_swayc(C_OUTPUT); output->handle = handle; output->name = name ? strdup(name) : NULL; - output->width = size->w; - output->height = size->h; + output->width = size.w; + output->height = size.h; output->unmanaged = create_list(); output->bg_pid = 0; diff --git a/sway/handlers.c b/sway/handlers.c index 405df1c81..cb608bec0 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -56,7 +56,8 @@ static struct background_config *if_background_find_config(struct wl_client *cli } static struct wlc_geometry compute_panel_geometry(struct panel_config *config) { - const struct wlc_size resolution = *wlc_output_get_resolution(config->output); + struct wlc_size resolution; + output_get_scaled_size(config->output, &resolution); const struct wlc_geometry *old = wlc_view_get_geometry(config->handle); struct wlc_geometry new; diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 4e5ea896c..228e551dc 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -11,8 +11,17 @@ static json_object *ipc_json_create_rect(swayc_t *c) { json_object_object_add(rect, "x", json_object_new_int((int32_t)c->x)); json_object_object_add(rect, "y", json_object_new_int((int32_t)c->y)); - json_object_object_add(rect, "width", json_object_new_int((int32_t)c->width)); - json_object_object_add(rect, "height", json_object_new_int((int32_t)c->height)); + + struct wlc_size size; + if (c->type == C_OUTPUT) { + size = *wlc_output_get_resolution(c->handle); + } else { + size.w = c->width; + size.h = c->height; + } + + json_object_object_add(rect, "width", json_object_new_int((int32_t)size.w)); + json_object_object_add(rect, "height", json_object_new_int((int32_t)size.h)); return rect; } @@ -111,12 +120,14 @@ static float ipc_json_child_percentage(swayc_t *c) { } static void ipc_json_describe_output(swayc_t *output, json_object *object) { + uint32_t scale = wlc_output_get_scale(output->handle); json_object_object_add(object, "active", json_object_new_boolean(true)); json_object_object_add(object, "primary", json_object_new_boolean(false)); json_object_object_add(object, "layout", json_object_new_string("output")); json_object_object_add(object, "type", json_object_new_string("output")); json_object_object_add(object, "current_workspace", (output->focused) ? json_object_new_string(output->focused->name) : NULL); + json_object_object_add(object, "scale", json_object_new_int(scale)); } static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) { diff --git a/sway/layout.c b/sway/layout.c index fc7a31b41..db9787f3f 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -406,20 +406,21 @@ static void update_border_geometry_floating(swayc_t *c, struct wlc_geometry *geo c->actual_geometry = g; swayc_t *output = swayc_parent_by_type(c, C_OUTPUT); - const struct wlc_size *res = wlc_output_get_resolution(output->handle); + struct wlc_size res; + output_get_scaled_size(output->handle, &res); switch (c->border_type) { case B_NONE: break; case B_PIXEL: - adjust_border_geometry(c, &g, res, c->border_thickness, + adjust_border_geometry(c, &g, &res, c->border_thickness, c->border_thickness, c->border_thickness, c->border_thickness); break; case B_NORMAL: { int title_bar_height = config->font_height + 4; // borders + padding - adjust_border_geometry(c, &g, res, c->border_thickness, + adjust_border_geometry(c, &g, &res, c->border_thickness, c->border_thickness, title_bar_height, c->border_thickness); struct wlc_geometry title_bar = { @@ -545,13 +546,15 @@ void update_geometry(swayc_t *container) { gap = update_gap_geometry(container, &geometry); } + swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); + struct wlc_size size; + output_get_scaled_size(output->handle, &size); + if (swayc_is_fullscreen(container)) { - swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); - const struct wlc_size *size = wlc_output_get_resolution(output->handle); geometry.origin.x = 0; geometry.origin.y = 0; - geometry.size.w = size->w; - geometry.size.h = size->h; + geometry.size.w = size.w; + geometry.size.h = size.h; if (op->focused == workspace) { wlc_view_bring_to_front(container->handle); } @@ -576,7 +579,9 @@ void update_geometry(swayc_t *container) { border_left = 0; } - if (geometry.origin.x + geometry.size.w == workspace->x + workspace->width) { + if (geometry.origin.x + geometry.size.w == size.w || + geometry.size.w == container->x + container->width) { + // should work for swaybar at right border_right = 0; } } @@ -586,7 +591,9 @@ void update_geometry(swayc_t *container) { border_top = 0; } - if (geometry.origin.y + geometry.size.h == workspace->y + workspace->height) { + if (geometry.origin.y + geometry.size.h == size.h || + geometry.size.h == container->y + container->height) { + // this works for swaybar at bottom border_bottom = 0; } } @@ -721,7 +728,8 @@ static void arrange_windows_r(swayc_t *container, double width, double height) { return; case C_OUTPUT: { - struct wlc_size resolution = *wlc_output_get_resolution(container->handle); + struct wlc_size resolution; + output_get_scaled_size(container->handle, &resolution); width = resolution.w; height = resolution.h; // output must have correct size due to e.g. seamless mouse, // but a workspace might be smaller depending on panels. diff --git a/sway/output.c b/sway/output.c index d56a2f308..97b8a4a6d 100644 --- a/sway/output.c +++ b/sway/output.c @@ -5,6 +5,13 @@ #include "log.h" #include "list.h" +void output_get_scaled_size(wlc_handle handle, struct wlc_size *size) { + *size = *wlc_output_get_resolution(handle); + uint32_t scale = wlc_output_get_scale(handle); + size->w /= scale; + size->h /= scale; +} + swayc_t *output_by_name(const char* name, const struct wlc_point *abs_pos) { if (strcasecmp(name, "left") == 0) { return swayc_adjacent_output(NULL, MOVE_LEFT, abs_pos, true);