diff options
-rw-r--r-- | sway/desktop/output.c | 12 | ||||
-rw-r--r-- | sway/desktop/render.c | 165 |
2 files changed, 89 insertions, 88 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index adc1ee10..fc52dd28 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -223,11 +223,15 @@ void output_drag_icons_for_each_surface(struct sway_output *output, | |||
223 | } | 223 | } |
224 | } | 224 | } |
225 | 225 | ||
226 | static int scale_length(int length, int offset, float scale) { | ||
227 | return round((offset + length) * scale) - round(offset * scale); | ||
228 | } | ||
229 | |||
226 | static void scale_box(struct wlr_box *box, float scale) { | 230 | static void scale_box(struct wlr_box *box, float scale) { |
227 | box->x *= scale; | 231 | box->width = scale_length(box->width, box->x, scale); |
228 | box->y *= scale; | 232 | box->height = scale_length(box->height, box->y, scale); |
229 | box->width *= scale; | 233 | box->x = round(box->x * scale); |
230 | box->height *= scale; | 234 | box->y = round(box->y * scale); |
231 | } | 235 | } |
232 | 236 | ||
233 | struct sway_workspace *output_get_active_workspace(struct sway_output *output) { | 237 | struct sway_workspace *output_get_active_workspace(struct sway_output *output) { |
diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 3617da87..9b26c560 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c | |||
@@ -33,11 +33,27 @@ struct render_data { | |||
33 | float alpha; | 33 | float alpha; |
34 | }; | 34 | }; |
35 | 35 | ||
36 | /** | ||
37 | * Apply scale to a width or height. | ||
38 | * | ||
39 | * One does not simply multiply the width by the scale. We allow fractional | ||
40 | * scaling, which means the resulting scaled width might be a decimal. | ||
41 | * So we round it. | ||
42 | * | ||
43 | * But even this can produce undesirable results depending on the X or Y offset | ||
44 | * of the box. For example, with a scale of 1.5, a box with width=1 should not | ||
45 | * scale to 2px if its X coordinate is 1, because the X coordinate would have | ||
46 | * scaled to 2px. | ||
47 | */ | ||
48 | static int scale_length(int length, int offset, float scale) { | ||
49 | return round((offset + length) * scale) - round(offset * scale); | ||
50 | } | ||
51 | |||
36 | static void scale_box(struct wlr_box *box, float scale) { | 52 | static void scale_box(struct wlr_box *box, float scale) { |
37 | box->x *= scale; | 53 | box->width = scale_length(box->width, box->x, scale); |
38 | box->y *= scale; | 54 | box->height = scale_length(box->height, box->y, scale); |
39 | box->width *= scale; | 55 | box->x = round(box->x * scale); |
40 | box->height *= scale; | 56 | box->y = round(box->y * scale); |
41 | } | 57 | } |
42 | 58 | ||
43 | static void scissor_output(struct wlr_output *wlr_output, | 59 | static void scissor_output(struct wlr_output *wlr_output, |
@@ -392,14 +408,23 @@ static void render_titlebar(struct sway_output *output, | |||
392 | render_rect(output->wlr_output, output_damage, &box, color); | 408 | render_rect(output->wlr_output, output_damage, &box, color); |
393 | 409 | ||
394 | // Single pixel right edge | 410 | // Single pixel right edge |
395 | box.x = (x + width - TITLEBAR_BORDER_THICKNESS) * output_scale; | 411 | box.x = x + width - TITLEBAR_BORDER_THICKNESS; |
412 | box.y = y + TITLEBAR_BORDER_THICKNESS; | ||
413 | box.width = TITLEBAR_BORDER_THICKNESS; | ||
414 | box.height = | ||
415 | container_titlebar_height() - TITLEBAR_BORDER_THICKNESS * 2; | ||
416 | scale_box(&box, output_scale); | ||
396 | render_rect(output->wlr_output, output_damage, &box, color); | 417 | render_rect(output->wlr_output, output_damage, &box, color); |
397 | } | 418 | } |
398 | 419 | ||
399 | size_t inner_width = width - TITLEBAR_H_PADDING * 2; | 420 | size_t inner_width = width - TITLEBAR_H_PADDING * 2; |
421 | int bg_y = y + TITLEBAR_BORDER_THICKNESS; | ||
422 | int ob_bg_height = scale_length( | ||
423 | (TITLEBAR_V_PADDING - TITLEBAR_BORDER_THICKNESS) * 2 + | ||
424 | config->font_height, bg_y, output_scale); | ||
400 | 425 | ||
401 | // Marks | 426 | // Marks |
402 | size_t marks_ob_width = 0; // output-buffer-local | 427 | int marks_ob_width = 0; // output-buffer-local |
403 | if (config->show_marks && marks_texture) { | 428 | if (config->show_marks && marks_texture) { |
404 | struct wlr_box texture_box; | 429 | struct wlr_box texture_box; |
405 | wlr_texture_get_size(marks_texture, | 430 | wlr_texture_get_size(marks_texture, |
@@ -408,15 +433,14 @@ static void render_titlebar(struct sway_output *output, | |||
408 | 433 | ||
409 | // The marks texture might be shorter than the config->font_height, in | 434 | // The marks texture might be shorter than the config->font_height, in |
410 | // which case we need to pad it as evenly as possible above and below. | 435 | // which case we need to pad it as evenly as possible above and below. |
411 | int ob_padding_total = config->font_height * output_scale - | 436 | int ob_padding_total = ob_bg_height - texture_box.height; |
412 | texture_box.height; | 437 | int ob_padding_above = floor(ob_padding_total / 2.0); |
413 | int ob_padding_above = floor(ob_padding_total / 2); | 438 | int ob_padding_below = ceil(ob_padding_total / 2.0); |
414 | int ob_padding_below = ceil(ob_padding_total / 2); | ||
415 | 439 | ||
416 | // Render texture | 440 | // Render texture |
417 | texture_box.x = (x - output_x + width - TITLEBAR_H_PADDING) | 441 | texture_box.x = round((x - output_x + width - TITLEBAR_H_PADDING) |
418 | * output_scale - texture_box.width; | 442 | * output_scale) - texture_box.width; |
419 | texture_box.y = (y - output_y + TITLEBAR_V_PADDING) * output_scale + | 443 | texture_box.y = round((bg_y - output_y) * output_scale) + |
420 | ob_padding_above; | 444 | ob_padding_above; |
421 | 445 | ||
422 | float matrix[9]; | 446 | float matrix[9]; |
@@ -431,29 +455,18 @@ static void render_titlebar(struct sway_output *output, | |||
431 | &texture_box, matrix, con->alpha); | 455 | &texture_box, matrix, con->alpha); |
432 | 456 | ||
433 | // Padding above | 457 | // Padding above |
434 | if (ob_padding_above > 0) { | 458 | memcpy(&color, colors->background, sizeof(float) * 4); |
435 | memcpy(&color, colors->background, sizeof(float) * 4); | 459 | premultiply_alpha(color, con->alpha); |
436 | premultiply_alpha(color, con->alpha); | 460 | box.x = texture_box.x + round(output_x * output_scale); |
437 | box.x = (x + width - TITLEBAR_H_PADDING) * output_scale - | 461 | box.y = round((y + TITLEBAR_BORDER_THICKNESS) * output_scale); |
438 | texture_box.width; | 462 | box.width = texture_box.width; |
439 | box.y = (y + TITLEBAR_V_PADDING) * output_scale; | 463 | box.height = ob_padding_above; |
440 | box.width = texture_box.width; | 464 | render_rect(output->wlr_output, output_damage, &box, color); |
441 | box.height = ob_padding_above; | ||
442 | render_rect(output->wlr_output, output_damage, &box, color); | ||
443 | } | ||
444 | 465 | ||
445 | // Padding below | 466 | // Padding below |
446 | if (ob_padding_below > 0) { | 467 | box.y += ob_padding_above + texture_box.height; |
447 | memcpy(&color, colors->background, sizeof(float) * 4); | 468 | box.height = ob_padding_below; |
448 | premultiply_alpha(color, con->alpha); | 469 | render_rect(output->wlr_output, output_damage, &box, color); |
449 | box.x = (x + width - TITLEBAR_H_PADDING) * output_scale - | ||
450 | texture_box.width; | ||
451 | box.y = (y + TITLEBAR_V_PADDING) * output_scale + | ||
452 | ob_padding_above + texture_box.height; | ||
453 | box.width = texture_box.width; | ||
454 | box.height = ob_padding_below; | ||
455 | render_rect(output->wlr_output, output_damage, &box, color); | ||
456 | } | ||
457 | } | 470 | } |
458 | 471 | ||
459 | // Title text | 472 | // Title text |
@@ -466,89 +479,73 @@ static void render_titlebar(struct sway_output *output, | |||
466 | 479 | ||
467 | // The title texture might be shorter than the config->font_height, | 480 | // The title texture might be shorter than the config->font_height, |
468 | // in which case we need to pad it above and below. | 481 | // in which case we need to pad it above and below. |
469 | int ob_padding_above = (config->font_baseline - con->title_baseline) | 482 | int ob_padding_above = round((config->font_baseline - |
470 | * output_scale; | 483 | con->title_baseline + TITLEBAR_V_PADDING - |
471 | int ob_padding_below = (config->font_height - con->title_height) | 484 | TITLEBAR_BORDER_THICKNESS) * output_scale); |
472 | * output_scale - ob_padding_above; | 485 | int ob_padding_below = ob_bg_height - ob_padding_above - |
486 | texture_box.height; | ||
473 | 487 | ||
474 | // Render texture | 488 | // Render texture |
475 | texture_box.x = (x - output_x + TITLEBAR_H_PADDING) * output_scale; | 489 | texture_box.x = |
476 | texture_box.y = (y - output_y + TITLEBAR_V_PADDING) * output_scale + | 490 | round((x - output_x + TITLEBAR_H_PADDING) * output_scale); |
477 | ob_padding_above; | 491 | texture_box.y = |
492 | round((bg_y - output_y) * output_scale) + ob_padding_above; | ||
478 | 493 | ||
479 | float matrix[9]; | 494 | float matrix[9]; |
480 | wlr_matrix_project_box(matrix, &texture_box, | 495 | wlr_matrix_project_box(matrix, &texture_box, |
481 | WL_OUTPUT_TRANSFORM_NORMAL, | 496 | WL_OUTPUT_TRANSFORM_NORMAL, |
482 | 0.0, output->wlr_output->transform_matrix); | 497 | 0.0, output->wlr_output->transform_matrix); |
483 | 498 | ||
484 | if (inner_width * output_scale - marks_ob_width < texture_box.width) { | 499 | int inner_x = x - output_x + TITLEBAR_H_PADDING; |
485 | texture_box.width = inner_width * output_scale - marks_ob_width; | 500 | int ob_inner_width = scale_length(inner_width, inner_x, output_scale); |
501 | if (ob_inner_width - marks_ob_width < texture_box.width) { | ||
502 | texture_box.width = ob_inner_width - marks_ob_width; | ||
486 | } | 503 | } |
487 | render_texture(output->wlr_output, output_damage, title_texture, | 504 | render_texture(output->wlr_output, output_damage, title_texture, |
488 | &texture_box, matrix, con->alpha); | 505 | &texture_box, matrix, con->alpha); |
489 | 506 | ||
490 | // Padding above | 507 | // Padding above |
491 | if (ob_padding_above > 0) { | 508 | memcpy(&color, colors->background, sizeof(float) * 4); |
492 | memcpy(&color, colors->background, sizeof(float) * 4); | 509 | premultiply_alpha(color, con->alpha); |
493 | premultiply_alpha(color, con->alpha); | 510 | box.x = texture_box.x + round(output_x * output_scale); |
494 | box.x = (x + TITLEBAR_H_PADDING) * output_scale; | 511 | box.y = round((y + TITLEBAR_BORDER_THICKNESS) * output_scale); |
495 | box.y = (y + TITLEBAR_V_PADDING) * output_scale; | 512 | box.width = texture_box.width; |
496 | box.width = texture_box.width; | 513 | box.height = ob_padding_above; |
497 | box.height = ob_padding_above; | 514 | render_rect(output->wlr_output, output_damage, &box, color); |
498 | render_rect(output->wlr_output, output_damage, &box, color); | ||
499 | } | ||
500 | 515 | ||
501 | // Padding below | 516 | // Padding below |
502 | if (ob_padding_below > 0) { | 517 | box.y += ob_padding_above + texture_box.height; |
503 | memcpy(&color, colors->background, sizeof(float) * 4); | 518 | box.height = ob_padding_below; |
504 | premultiply_alpha(color, con->alpha); | 519 | render_rect(output->wlr_output, output_damage, &box, color); |
505 | box.x = (x + TITLEBAR_H_PADDING) * output_scale; | ||
506 | box.y = (y + TITLEBAR_V_PADDING) * output_scale + | ||
507 | ob_padding_above + texture_box.height; | ||
508 | box.width = texture_box.width; | ||
509 | box.height = ob_padding_below; | ||
510 | render_rect(output->wlr_output, output_damage, &box, color); | ||
511 | } | ||
512 | } | 520 | } |
513 | 521 | ||
514 | // Padding above title | ||
515 | memcpy(&color, colors->background, sizeof(float) * 4); | ||
516 | premultiply_alpha(color, con->alpha); | ||
517 | box.x = x + (layout == L_TABBED) * TITLEBAR_BORDER_THICKNESS; | ||
518 | box.y = y + TITLEBAR_BORDER_THICKNESS; | ||
519 | box.width = width - (layout == L_TABBED) * TITLEBAR_BORDER_THICKNESS * 2; | ||
520 | box.height = TITLEBAR_V_PADDING - TITLEBAR_BORDER_THICKNESS; | ||
521 | scale_box(&box, output_scale); | ||
522 | render_rect(output->wlr_output, output_damage, &box, color); | ||
523 | |||
524 | // Padding below title | ||
525 | box.y = (y + TITLEBAR_V_PADDING + config->font_height) * output_scale; | ||
526 | render_rect(output->wlr_output, output_damage, &box, color); | ||
527 | |||
528 | // Filler between title and marks | 522 | // Filler between title and marks |
529 | box.width = inner_width * output_scale - title_ob_width - marks_ob_width; | 523 | box.width = |
524 | round(inner_width * output_scale) - title_ob_width - marks_ob_width; | ||
530 | if (box.width > 0) { | 525 | if (box.width > 0) { |
531 | box.x = (x + TITLEBAR_H_PADDING) * output_scale + title_ob_width; | 526 | box.x = round((x + TITLEBAR_H_PADDING) * output_scale) + title_ob_width; |
532 | box.y = (y + TITLEBAR_V_PADDING) * output_scale; | 527 | box.y = round(bg_y * output_scale); |
533 | box.height = config->font_height * output_scale; | 528 | box.height = ob_bg_height; |
534 | render_rect(output->wlr_output, output_damage, &box, color); | 529 | render_rect(output->wlr_output, output_damage, &box, color); |
535 | } | 530 | } |
536 | 531 | ||
537 | // Padding left of title | 532 | // Padding left of title |
538 | left_offset = (layout == L_TABBED) * TITLEBAR_BORDER_THICKNESS; | 533 | left_offset = (layout == L_TABBED) * TITLEBAR_BORDER_THICKNESS; |
539 | box.x = x + left_offset; | 534 | box.x = x + left_offset; |
540 | box.y = y + TITLEBAR_V_PADDING; | 535 | box.y = y + TITLEBAR_BORDER_THICKNESS; |
541 | box.width = TITLEBAR_H_PADDING - left_offset; | 536 | box.width = TITLEBAR_H_PADDING - left_offset; |
542 | box.height = config->font_height; | 537 | box.height = (TITLEBAR_V_PADDING - TITLEBAR_BORDER_THICKNESS) * 2 + |
538 | config->font_height; | ||
543 | scale_box(&box, output_scale); | 539 | scale_box(&box, output_scale); |
544 | render_rect(output->wlr_output, output_damage, &box, color); | 540 | render_rect(output->wlr_output, output_damage, &box, color); |
545 | 541 | ||
546 | // Padding right of marks | 542 | // Padding right of marks |
547 | right_offset = (layout == L_TABBED) * TITLEBAR_BORDER_THICKNESS; | 543 | right_offset = (layout == L_TABBED) * TITLEBAR_BORDER_THICKNESS; |
548 | box.x = x + width - TITLEBAR_H_PADDING; | 544 | box.x = x + width - TITLEBAR_H_PADDING; |
549 | box.y = y + TITLEBAR_V_PADDING; | 545 | box.y = y + TITLEBAR_BORDER_THICKNESS; |
550 | box.width = TITLEBAR_H_PADDING - right_offset; | 546 | box.width = TITLEBAR_H_PADDING - right_offset; |
551 | box.height = config->font_height; | 547 | box.height = (TITLEBAR_V_PADDING - TITLEBAR_BORDER_THICKNESS) * 2 + |
548 | config->font_height; | ||
552 | scale_box(&box, output_scale); | 549 | scale_box(&box, output_scale); |
553 | render_rect(output->wlr_output, output_damage, &box, color); | 550 | render_rect(output->wlr_output, output_damage, &box, color); |
554 | 551 | ||