summaryrefslogtreecommitdiffstats
path: root/sway/desktop/render.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop/render.c')
-rw-r--r--sway/desktop/render.c165
1 files changed, 81 insertions, 84 deletions
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 */
48static int scale_length(int length, int offset, float scale) {
49 return round((offset + length) * scale) - round(offset * scale);
50}
51
36static void scale_box(struct wlr_box *box, float scale) { 52static 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
43static void scissor_output(struct wlr_output *wlr_output, 59static 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