summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-07-15 15:20:21 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-07-15 22:08:26 +1000
commita120d4c79f9406a2f7cc38c60069d3183c98ea87 (patch)
tree87a568ff97fc94ca82b9ceb4abacb02ea86a9f71
parentMerge pull request #2272 from RyanDwyer/simplify-transactions (diff)
downloadsway-a120d4c79f9406a2f7cc38c60069d3183c98ea87.tar.gz
sway-a120d4c79f9406a2f7cc38c60069d3183c98ea87.tar.zst
sway-a120d4c79f9406a2f7cc38c60069d3183c98ea87.zip
Make focus part of transactions
Rather than maintain copies of the entire focus stack, this PR transactionises the focus by introducing two new properties to the container state and using those when rendering. * `bool focused` means this container has actual focus. Only one container should have this equalling true in its current state. * `struct sway_container *focus_inactive_child` points to the immediate child that was most recently focused (eg. for tabbed and stacked containers).
-rw-r--r--include/sway/input/seat.h11
-rw-r--r--include/sway/tree/container.h3
-rw-r--r--sway/commands.c2
-rw-r--r--sway/desktop/render.c61
-rw-r--r--sway/desktop/transaction.c18
-rw-r--r--sway/input/cursor.c3
-rw-r--r--sway/input/keyboard.c2
-rw-r--r--sway/input/seat.c24
-rw-r--r--sway/ipc-server.c2
-rw-r--r--sway/main.c2
10 files changed, 55 insertions, 73 deletions
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h
index 0e440701..1f7792ba 100644
--- a/include/sway/input/seat.h
+++ b/include/sway/input/seat.h
@@ -119,17 +119,6 @@ struct sway_container *seat_get_active_child(struct sway_seat *seat,
119 struct sway_container *container); 119 struct sway_container *container);
120 120
121/** 121/**
122 * Return the immediate child of container which was most recently focused, with
123 * fallback to selecting the child in the parent's `current` (rendered) children
124 * list.
125 *
126 * This is useful for when a tabbed container and its children are destroyed but
127 * still being rendered, and we have to render an appropriate child.
128 */
129struct sway_container *seat_get_active_current_child(struct sway_seat *seat,
130 struct sway_container *container);
131
132/**
133 * Iterate over the focus-inactive children of the container calling the 122 * Iterate over the focus-inactive children of the container calling the
134 * function on each. 123 * function on each.
135 */ 124 */
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
index 11780916..04e50fc6 100644
--- a/include/sway/tree/container.h
+++ b/include/sway/tree/container.h
@@ -68,6 +68,9 @@ struct sway_container_state {
68 struct sway_container *parent; 68 struct sway_container *parent;
69 list_t *children; 69 list_t *children;
70 70
71 struct sway_container *focused_inactive_child;
72 bool focused;
73
71 // View properties 74 // View properties
72 double view_x, view_y; 75 double view_x, view_y;
73 double view_width, view_height; 76 double view_width, view_height;
diff --git a/sway/commands.c b/sway/commands.c
index 50d949d4..addd64a6 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -9,7 +9,6 @@
9#include "sway/commands.h" 9#include "sway/commands.h"
10#include "sway/config.h" 10#include "sway/config.h"
11#include "sway/criteria.h" 11#include "sway/criteria.h"
12#include "sway/desktop/transaction.h"
13#include "sway/security.h" 12#include "sway/security.h"
14#include "sway/input/input-manager.h" 13#include "sway/input/input-manager.h"
15#include "sway/input/seat.h" 14#include "sway/input/seat.h"
@@ -323,7 +322,6 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
323cleanup: 322cleanup:
324 free(exec); 323 free(exec);
325 free(views); 324 free(views);
326 transaction_commit_dirty();
327 if (!results) { 325 if (!results) {
328 results = cmd_results_new(CMD_SUCCESS, NULL, NULL); 326 results = cmd_results_new(CMD_SUCCESS, NULL, NULL);
329 } 327 }
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index 4bfc573b..17fe823a 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -543,9 +543,6 @@ static void render_container(struct sway_output *output,
543static void render_container_simple(struct sway_output *output, 543static void render_container_simple(struct sway_output *output,
544 pixman_region32_t *damage, struct sway_container *con, 544 pixman_region32_t *damage, struct sway_container *con,
545 bool parent_focused) { 545 bool parent_focused) {
546 struct sway_seat *seat = input_manager_current_seat(input_manager);
547 struct sway_container *focus = seat_get_focus(seat);
548
549 for (int i = 0; i < con->current.children->length; ++i) { 546 for (int i = 0; i < con->current.children->length; ++i) {
550 struct sway_container *child = con->current.children->items[i]; 547 struct sway_container *child = con->current.children->items[i];
551 548
@@ -556,11 +553,11 @@ static void render_container_simple(struct sway_output *output,
556 struct wlr_texture *marks_texture; 553 struct wlr_texture *marks_texture;
557 struct sway_container_state *state = &child->current; 554 struct sway_container_state *state = &child->current;
558 555
559 if (focus == child || parent_focused) { 556 if (state->focused || parent_focused) {
560 colors = &config->border_colors.focused; 557 colors = &config->border_colors.focused;
561 title_texture = child->title_focused; 558 title_texture = child->title_focused;
562 marks_texture = view->marks_focused; 559 marks_texture = view->marks_focused;
563 } else if (seat_get_focus_inactive(seat, con) == child) { 560 } else if (con->current.focused_inactive_child == child) {
564 colors = &config->border_colors.focused_inactive; 561 colors = &config->border_colors.focused_inactive;
565 title_texture = child->title_focused_inactive; 562 title_texture = child->title_focused_inactive;
566 marks_texture = view->marks_focused_inactive; 563 marks_texture = view->marks_focused_inactive;
@@ -580,7 +577,7 @@ static void render_container_simple(struct sway_output *output,
580 render_view(output, damage, child, colors); 577 render_view(output, damage, child, colors);
581 } else { 578 } else {
582 render_container(output, damage, child, 579 render_container(output, damage, child,
583 parent_focused || focus == child); 580 parent_focused || child->current.focused);
584 } 581 }
585 } 582 }
586} 583}
@@ -594,11 +591,9 @@ static void render_container_tabbed(struct sway_output *output,
594 if (!con->current.children->length) { 591 if (!con->current.children->length) {
595 return; 592 return;
596 } 593 }
597 struct sway_seat *seat = input_manager_current_seat(input_manager);
598 struct sway_container *focus = seat_get_focus(seat);
599 struct sway_container *current = seat_get_active_current_child(seat, con);
600 struct border_colors *current_colors = &config->border_colors.unfocused;
601 struct sway_container_state *pstate = &con->current; 594 struct sway_container_state *pstate = &con->current;
595 struct sway_container *current = pstate->focused_inactive_child;
596 struct border_colors *current_colors = &config->border_colors.unfocused;
602 597
603 double width_gap_adjustment = 2 * pstate->current_gaps; 598 double width_gap_adjustment = 2 * pstate->current_gaps;
604 int tab_width = 599 int tab_width =
@@ -613,11 +608,11 @@ static void render_container_tabbed(struct sway_output *output,
613 struct wlr_texture *title_texture; 608 struct wlr_texture *title_texture;
614 struct wlr_texture *marks_texture; 609 struct wlr_texture *marks_texture;
615 610
616 if (focus == child || parent_focused) { 611 if (cstate->focused || parent_focused) {
617 colors = &config->border_colors.focused; 612 colors = &config->border_colors.focused;
618 title_texture = child->title_focused; 613 title_texture = child->title_focused;
619 marks_texture = view ? view->marks_focused : NULL; 614 marks_texture = view ? view->marks_focused : NULL;
620 } else if (child == current) { 615 } else if (child == pstate->focused_inactive_child) {
621 colors = &config->border_colors.focused_inactive; 616 colors = &config->border_colors.focused_inactive;
622 title_texture = child->title_focused_inactive; 617 title_texture = child->title_focused_inactive;
623 marks_texture = view ? view->marks_focused_inactive : NULL; 618 marks_texture = view ? view->marks_focused_inactive : NULL;
@@ -644,13 +639,11 @@ static void render_container_tabbed(struct sway_output *output,
644 } 639 }
645 640
646 // Render surface and left/right/bottom borders 641 // Render surface and left/right/bottom borders
647 if (current) { 642 if (current->type == C_VIEW) {
648 if (current->type == C_VIEW) { 643 render_view(output, damage, current, current_colors);
649 render_view(output, damage, current, current_colors); 644 } else {
650 } else { 645 render_container(output, damage, current,
651 render_container(output, damage, current, 646 parent_focused || current->current.focused);
652 parent_focused || current == focus);
653 }
654 } 647 }
655} 648}
656 649
@@ -663,11 +656,9 @@ static void render_container_stacked(struct sway_output *output,
663 if (!con->current.children->length) { 656 if (!con->current.children->length) {
664 return; 657 return;
665 } 658 }
666 struct sway_seat *seat = input_manager_current_seat(input_manager);
667 struct sway_container *focus = seat_get_focus(seat);
668 struct sway_container *current = seat_get_active_current_child(seat, con);
669 struct border_colors *current_colors = &config->border_colors.unfocused;
670 struct sway_container_state *pstate = &con->current; 659 struct sway_container_state *pstate = &con->current;
660 struct sway_container *current = pstate->focused_inactive_child;
661 struct border_colors *current_colors = &config->border_colors.unfocused;
671 662
672 size_t titlebar_height = container_titlebar_height(); 663 size_t titlebar_height = container_titlebar_height();
673 664
@@ -680,11 +671,11 @@ static void render_container_stacked(struct sway_output *output,
680 struct wlr_texture *title_texture; 671 struct wlr_texture *title_texture;
681 struct wlr_texture *marks_texture; 672 struct wlr_texture *marks_texture;
682 673
683 if (focus == child || parent_focused) { 674 if (cstate->focused || parent_focused) {
684 colors = &config->border_colors.focused; 675 colors = &config->border_colors.focused;
685 title_texture = child->title_focused; 676 title_texture = child->title_focused;
686 marks_texture = view ? view->marks_focused : NULL; 677 marks_texture = view ? view->marks_focused : NULL;
687 } else if (child == current) { 678 } else if (child == pstate->focused_inactive_child) {
688 colors = &config->border_colors.focused_inactive; 679 colors = &config->border_colors.focused_inactive;
689 title_texture = child->title_focused_inactive; 680 title_texture = child->title_focused_inactive;
690 marks_texture = view ? view->marks_focused_inactive : NULL; 681 marks_texture = view ? view->marks_focused_inactive : NULL;
@@ -704,13 +695,11 @@ static void render_container_stacked(struct sway_output *output,
704 } 695 }
705 696
706 // Render surface and left/right/bottom borders 697 // Render surface and left/right/bottom borders
707 if (current) { 698 if (current->type == C_VIEW) {
708 if (current->type == C_VIEW) { 699 render_view(output, damage, current, current_colors);
709 render_view(output, damage, current, current_colors); 700 } else {
710 } else { 701 render_container(output, damage, current,
711 render_container(output, damage, current, 702 parent_focused || current->current.focused);
712 parent_focused || current == focus);
713 }
714 } 703 }
715} 704}
716 705
@@ -738,13 +727,11 @@ static void render_floating_container(struct sway_output *soutput,
738 pixman_region32_t *damage, struct sway_container *con) { 727 pixman_region32_t *damage, struct sway_container *con) {
739 if (con->type == C_VIEW) { 728 if (con->type == C_VIEW) {
740 struct sway_view *view = con->sway_view; 729 struct sway_view *view = con->sway_view;
741 struct sway_seat *seat = input_manager_current_seat(input_manager);
742 struct sway_container *focus = seat_get_focus(seat);
743 struct border_colors *colors; 730 struct border_colors *colors;
744 struct wlr_texture *title_texture; 731 struct wlr_texture *title_texture;
745 struct wlr_texture *marks_texture; 732 struct wlr_texture *marks_texture;
746 733
747 if (focus == con) { 734 if (con->current.focused) {
748 colors = &config->border_colors.focused; 735 colors = &config->border_colors.focused;
749 title_texture = con->title_focused; 736 title_texture = con->title_focused;
750 marks_texture = view->marks_focused; 737 marks_texture = view->marks_focused;
@@ -871,9 +858,7 @@ void output_render(struct sway_output *output, struct timespec *when,
871 render_layer(output, damage, 858 render_layer(output, damage,
872 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); 859 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);
873 860
874 struct sway_seat *seat = input_manager_current_seat(input_manager); 861 render_container(output, damage, workspace, workspace->current.focused);
875 struct sway_container *focus = seat_get_focus(seat);
876 render_container(output, damage, workspace, focus == workspace);
877 render_floating(output, damage); 862 render_floating(output, damage);
878 863
879 render_unmanaged(output, damage, 864 render_unmanaged(output, damage,
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c
index 0ae042db..fcfb0b51 100644
--- a/sway/desktop/transaction.c
+++ b/sway/desktop/transaction.c
@@ -139,6 +139,14 @@ static void copy_pending_state(struct sway_container *container,
139 state->children = create_list(); 139 state->children = create_list();
140 list_cat(state->children, container->children); 140 list_cat(state->children, container->children);
141 } 141 }
142
143 struct sway_seat *seat = input_manager_current_seat(input_manager);
144 state->focused = seat_get_focus(seat) == container;
145
146 if (container->type != C_VIEW) {
147 state->focused_inactive_child =
148 seat_get_active_child(seat, container);
149 }
142} 150}
143 151
144static void transaction_add_container(struct sway_transaction *transaction, 152static void transaction_add_container(struct sway_transaction *transaction,
@@ -195,10 +203,12 @@ static void transaction_apply(struct sway_transaction *transaction) {
195 .width = instruction->state.swayc_width, 203 .width = instruction->state.swayc_width,
196 .height = instruction->state.swayc_height, 204 .height = instruction->state.swayc_height,
197 }; 205 };
198 for (int j = 0; j < root_container.children->length; ++j) { 206 for (int j = 0; j < root_container.current.children->length; ++j) {
199 struct sway_container *output = root_container.children->items[j]; 207 struct sway_container *output = root_container.current.children->items[j];
200 output_damage_box(output->sway_output, &old_box); 208 if (output->sway_output) {
201 output_damage_box(output->sway_output, &new_box); 209 output_damage_box(output->sway_output, &old_box);
210 output_damage_box(output->sway_output, &new_box);
211 }
202 } 212 }
203 213
204 // There are separate children lists for each instruction state, the 214 // There are separate children lists for each instruction state, the
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 307eedd4..7a9f3ed7 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -10,6 +10,7 @@
10#include <wlr/types/wlr_idle.h> 10#include <wlr/types/wlr_idle.h>
11#include "list.h" 11#include "list.h"
12#include "log.h" 12#include "log.h"
13#include "sway/desktop/transaction.h"
13#include "sway/input/cursor.h" 14#include "sway/input/cursor.h"
14#include "sway/layers.h" 15#include "sway/layers.h"
15#include "sway/output.h" 16#include "sway/output.h"
@@ -219,6 +220,7 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
219 struct sway_drag_icon *drag_icon = wlr_drag_icon->data; 220 struct sway_drag_icon *drag_icon = wlr_drag_icon->data;
220 drag_icon_update_position(drag_icon); 221 drag_icon_update_position(drag_icon);
221 } 222 }
223 transaction_commit_dirty();
222} 224}
223 225
224static void handle_cursor_motion(struct wl_listener *listener, void *data) { 226static void handle_cursor_motion(struct wl_listener *listener, void *data) {
@@ -278,6 +280,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
278 280
279 wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, 281 wlr_seat_pointer_notify_button(cursor->seat->wlr_seat,
280 time_msec, button, state); 282 time_msec, button, state);
283 transaction_commit_dirty();
281} 284}
282 285
283static void handle_cursor_button(struct wl_listener *listener, void *data) { 286static void handle_cursor_button(struct wl_listener *listener, void *data) {
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c
index 580c0d4b..ede38519 100644
--- a/sway/input/keyboard.c
+++ b/sway/input/keyboard.c
@@ -3,6 +3,7 @@
3#include <wlr/backend/multi.h> 3#include <wlr/backend/multi.h>
4#include <wlr/backend/session.h> 4#include <wlr/backend/session.h>
5#include <wlr/types/wlr_idle.h> 5#include <wlr/types/wlr_idle.h>
6#include "sway/desktop/transaction.h"
6#include "sway/input/seat.h" 7#include "sway/input/seat.h"
7#include "sway/input/keyboard.h" 8#include "sway/input/keyboard.h"
8#include "sway/input/input-manager.h" 9#include "sway/input/input-manager.h"
@@ -126,6 +127,7 @@ static void keyboard_execute_command(struct sway_keyboard *keyboard,
126 binding->command); 127 binding->command);
127 config->handler_context.seat = keyboard->seat_device->sway_seat; 128 config->handler_context.seat = keyboard->seat_device->sway_seat;
128 struct cmd_results *results = execute_command(binding->command, NULL); 129 struct cmd_results *results = execute_command(binding->command, NULL);
130 transaction_commit_dirty();
129 if (results->status != CMD_SUCCESS) { 131 if (results->status != CMD_SUCCESS) {
130 wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)", 132 wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)",
131 binding->command, results->error); 133 binding->command, results->error);
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 5e65ca70..74f1375e 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -661,9 +661,13 @@ void seat_set_focus_warp(struct sway_seat *seat,
661 if (last_focus) { 661 if (last_focus) {
662 seat_send_unfocus(last_focus, seat); 662 seat_send_unfocus(last_focus, seat);
663 } 663 }
664
665 seat_send_focus(container, seat); 664 seat_send_focus(container, seat);
666 container_damage_whole(container->parent); 665
666 container_set_dirty(container);
667 container_set_dirty(container->parent); // for focused_inactive_child
668 if (last_focus) {
669 container_set_dirty(last_focus);
670 }
667 } 671 }
668 672
669 // If we've focused a floating container, bring it to the front. 673 // If we've focused a floating container, bring it to the front.
@@ -717,10 +721,6 @@ void seat_set_focus_warp(struct sway_seat *seat,
717 } 721 }
718 } 722 }
719 723
720 if (last_focus) {
721 container_damage_whole(last_focus);
722 }
723
724 if (last_workspace && last_workspace != new_workspace) { 724 if (last_workspace && last_workspace != new_workspace) {
725 cursor_send_pointer_motion(seat->cursor, 0, true); 725 cursor_send_pointer_motion(seat->cursor, 0, true);
726 } 726 }
@@ -840,18 +840,6 @@ struct sway_container *seat_get_active_child(struct sway_seat *seat,
840 return NULL; 840 return NULL;
841} 841}
842 842
843struct sway_container *seat_get_active_current_child(struct sway_seat *seat,
844 struct sway_container *container) {
845 struct sway_seat_container *current = NULL;
846 wl_list_for_each(current, &seat->focus_stack, link) {
847 if (current->container->current.parent == container &&
848 current->container->current.layout != L_FLOATING) {
849 return current->container;
850 }
851 }
852 return NULL;
853}
854
855struct sway_container *seat_get_focus(struct sway_seat *seat) { 843struct sway_container *seat_get_focus(struct sway_seat *seat) {
856 if (!seat->has_focus) { 844 if (!seat->has_focus) {
857 return NULL; 845 return NULL;
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index c5161a6b..be703915 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -18,6 +18,7 @@
18#include <wayland-server.h> 18#include <wayland-server.h>
19#include "sway/commands.h" 19#include "sway/commands.h"
20#include "sway/config.h" 20#include "sway/config.h"
21#include "sway/desktop/transaction.h"
21#include "sway/ipc-json.h" 22#include "sway/ipc-json.h"
22#include "sway/ipc-server.h" 23#include "sway/ipc-server.h"
23#include "sway/output.h" 24#include "sway/output.h"
@@ -484,6 +485,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
484 case IPC_COMMAND: 485 case IPC_COMMAND:
485 { 486 {
486 struct cmd_results *results = execute_command(buf, NULL); 487 struct cmd_results *results = execute_command(buf, NULL);
488 transaction_commit_dirty();
487 char *json = cmd_results_to_json(results); 489 char *json = cmd_results_to_json(results);
488 int length = strlen(json); 490 int length = strlen(json);
489 client_valid = ipc_send_reply(client, json, (uint32_t)length); 491 client_valid = ipc_send_reply(client, json, (uint32_t)length);
diff --git a/sway/main.c b/sway/main.c
index 1d772b48..1a55b519 100644
--- a/sway/main.c
+++ b/sway/main.c
@@ -20,6 +20,7 @@
20#include "sway/commands.h" 20#include "sway/commands.h"
21#include "sway/config.h" 21#include "sway/config.h"
22#include "sway/debug.h" 22#include "sway/debug.h"
23#include "sway/desktop/transaction.h"
23#include "sway/server.h" 24#include "sway/server.h"
24#include "sway/tree/layout.h" 25#include "sway/tree/layout.h"
25#include "sway/ipc-server.h" 26#include "sway/ipc-server.h"
@@ -441,6 +442,7 @@ int main(int argc, char **argv) {
441 free(line); 442 free(line);
442 list_del(config->cmd_queue, 0); 443 list_del(config->cmd_queue, 0);
443 } 444 }
445 transaction_commit_dirty();
444 446
445 if (!terminate_request) { 447 if (!terminate_request) {
446 server_run(&server); 448 server_run(&server);