raboof/volare
6
22
Fork
You've already forked volare
2

implement mod+x: unsplit #59

Merged
raboof merged 1 commit from implement-unsplit into main 2023年07月04日 22:05:31 +02:00

fixes #19

still needs a bunch of cleanup, maybe tests.

@edmonds does this look like it'd need any special handling of placeholder containers? I didn't completely follow the expected invariants there.

fixes #19 still needs a bunch of cleanup, maybe tests. @edmonds does this look like it'd need any special handling of placeholder containers? I didn't completely follow the expected invariants there.
raboof force-pushed implement-unsplit from b7b155e68e to cee35c7c92 2023年07月01日 11:52:30 +02:00 Compare
raboof force-pushed implement-unsplit from cee35c7c92 to ab009f50ae 2023年07月01日 14:41:40 +02:00 Compare
raboof force-pushed implement-unsplit from ab009f50ae to b6e38bd4e9 2023年07月03日 09:00:53 +02:00 Compare
raboof changed title from (削除) WIP: implement mod+x: unsplit (削除ここまで) to implement mod+x: unsplit 2023年07月03日 09:01:11 +02:00
@ -39,0 +46,4 @@
for (int i = 0; i < siblings->length; i++) {
if (siblings->items[i] == current) {
if (i == 0) {
return siblings->items[1];
Collaborator
Copy link

Hm, can siblings->length be 1? If so this looks like it accesses one past the end of the siblings list.

Hm, can `siblings->length` be 1? If so this looks like it accesses one past the end of the siblings list.
Author
Owner
Copy link

Good eye, indeed the case where you'd 'unsplit' a workspace that wasn't split wasn't handled yet. Added a check.

Good eye, indeed the case where you'd 'unsplit' a workspace that wasn't split wasn't handled yet. Added a check.
edmonds marked this conversation as resolved
meson.build Outdated
@ -21,2 +21,4 @@
'-Wundef',
'-Wvla',
'-g',
Collaborator
Copy link

Meson has a dedicated flag to enable debugging symbols, but it should be enabled by default already, typically you wouldn't set -g by hand.

Meson has a dedicated flag to enable debugging symbols, but it should be enabled by default already, typically you wouldn't set `-g` by hand.
Author
Owner
Copy link

Oops, didn't mean to commit that :)

Oops, didn't mean to commit that :)
edmonds marked this conversation as resolved
raboof force-pushed implement-unsplit from b6e38bd4e9 to db1f473fce 2023年07月03日 09:15:43 +02:00 Compare
Collaborator
Copy link

@edmonds does this look like it'd need any special handling of placeholder containers? I didn't completely follow the expected invariants there.

Looks like you're using container_insert_child() which already takes care of dealing with the placeholder (aac3fdad17). I'll take a more in-depth look later.

> @edmonds does this look like it'd need any special handling of placeholder containers? I didn't completely follow the expected invariants there. Looks like you're using `container_insert_child()` which already takes care of dealing with the placeholder (aac3fdad179c5c22e15edb79a9d5f644eeb2613c). I'll take a more in-depth look later.
raboof force-pushed implement-unsplit from db1f473fce to d6b283d27b 2023年07月03日 09:25:50 +02:00 Compare
raboof force-pushed implement-unsplit from d6b283d27b to c335e3b94c 2023年07月03日 09:26:29 +02:00 Compare
raboof force-pushed implement-unsplit from c335e3b94c to 865506706d 2023年07月03日 09:27:03 +02:00 Compare
Collaborator
Copy link

Looks like sway uses tabs for indentation but the lines you added to this file are indented with four spaces, can you convert to tabs to keep the code base consistent?

Looks like sway uses tabs for indentation but the lines you added to this file are indented with four spaces, can you convert to tabs to keep the code base consistent?
@ -47,0 +92,4 @@
struct sway_container *parent = con->pending.parent;
struct sway_container *child = parent->pending.children->items[0];
while (parent->pending.children->length) {
container_insert_child(destination, child, destination->pending.children->length);
Collaborator
Copy link

Here you're inserting at the end of the list, which is the same thing as adding (appending), so this can just be:

container_add_child(destination, child);
Here you're inserting at the end of the list, which is the same thing as adding (appending), so this can just be: ```c container_add_child(destination, child); ```
Author
Owner
Copy link

nice

nice
edmonds marked this conversation as resolved
@ -47,0 +91,4 @@
}
struct sway_container *parent = con->pending.parent;
struct sway_container *child = parent->pending.children->items[0];
while (parent->pending.children->length) {
Collaborator
Copy link

If you're unsplitting an empty container you might pick up a placeholder container and put it into the destination container which isn't correct if the destination container already has (non-placeholder) containers in it.

I was able to unsplit this:

Workspace 1
 Output: DP-1
 Layout: splith
 Representation: H[H[V[T[Alacritty] T[<empty>]] T[<empty>]]]

Into this:

Workspace 1
 Output: DP-1
 Layout: splith
 Representation: H[H[T[Alacritty <empty>] T[<empty>]]]

It looks like V[T[Alacritty] T[<empty>]] became T[Alacritty <empty>] after unsplitting.

If a container is an empty tabbed container (no application windows inside it), it must have a placeholder <empty> container as the first and only container in the L_TABBED container. Conversely a non-empty tabbed container (has application windows inside it) must not have any placeholder containers in it.

So e.g. if you're joining (unsplitting) T[Alacritty] and T[<empty>] that should result in T[Alacritty], not T[Alacritty <empty>].

So this loop should probably be something like this:

	while (parent->pending.children->length) {
		if (child->is_placeholder) {
			container_begin_destroy(child);
		} else {
			container_add_child(destination, child);
			child->pending.width = child->pending.height = 0;
			child->width_fraction = child->height_fraction = 0;
		}
		child = parent->pending.children->items[0];
	}

Or maybe:

	if (child->is_placeholder) {
		container_begin_destroy(child);
	} else {
		while (parent->pending.children->length) {
			container_add_child(destination, child);
			child->pending.width = child->pending.height = 0;
			child->width_fraction = child->height_fraction = 0;
			child = parent->pending.children->items[0];
		}
	}
If you're unsplitting an empty container you might pick up a placeholder container and put it into the destination container which isn't correct if the destination container already has (non-placeholder) containers in it. I was able to unsplit this: ``` Workspace 1 Output: DP-1 Layout: splith Representation: H[H[V[T[Alacritty] T[<empty>]] T[<empty>]]] ``` Into this: ``` Workspace 1 Output: DP-1 Layout: splith Representation: H[H[T[Alacritty <empty>] T[<empty>]]] ``` It looks like `V[T[Alacritty] T[<empty>]]` became `T[Alacritty <empty>]` after unsplitting. If a container is an empty tabbed container (no application windows inside it), it must have a placeholder `<empty>` container as the first and only container in the `L_TABBED` container. Conversely a non-empty tabbed container (has application windows inside it) must not have any placeholder containers in it. So e.g. if you're joining (unsplitting) `T[Alacritty]` and `T[<empty>]` that should result in `T[Alacritty]`, not `T[Alacritty <empty>]`. So this loop should probably be something like this: ```c while (parent->pending.children->length) { if (child->is_placeholder) { container_begin_destroy(child); } else { container_add_child(destination, child); child->pending.width = child->pending.height = 0; child->width_fraction = child->height_fraction = 0; } child = parent->pending.children->items[0]; } ``` Or maybe: ```c if (child->is_placeholder) { container_begin_destroy(child); } else { while (parent->pending.children->length) { container_add_child(destination, child); child->pending.width = child->pending.height = 0; child->width_fraction = child->height_fraction = 0; child = parent->pending.children->items[0]; } } ```
edmonds marked this conversation as resolved
Collaborator
Copy link

I gave it some light testing and found/fixed a bug (see in-line comment) and it seems to be working. I was never a big user of the Notion unsplit command, but it seems to be doing what it should be, intuitively.

The TODO that you have marked ("create a target frame if we can find none") doesn't quite make sense to me. When I was able to trigger the "No destination frame found" message it seemed to be in situations where the unsplit command shouldn't do anything, like if you already have a single tabbed container taking up the entire workspace and there's nothing obvious to unsplit it with, or trying to unsplit a floating window. (Maybe unsplitting a floating window should be treated the same as toggling floating mode on that window.) But maybe it also triggers in other situations?

Unsplitting a fullscreen window seems to behave as if the window wasn't fullscreened, i.e. when i exited fullscreen mode the layout had been rearranged as if I hadn't been in fullscreen mode in the first place. Maybe that makes sense, but maybe there's an argument that unsplitting shouldn't occur in fullscreen mode since you can't immediately see the result of the action.

I gave it some light testing and found/fixed a bug (see in-line comment) and it seems to be working. I was never a big user of the Notion unsplit command, but it seems to be doing what it should be, intuitively. The TODO that you have marked ("create a target frame if we can find none") doesn't quite make sense to me. When I was able to trigger the "No destination frame found" message it seemed to be in situations where the unsplit command shouldn't do anything, like if you already have a single tabbed container taking up the entire workspace and there's nothing obvious to unsplit it with, or trying to unsplit a floating window. (Maybe unsplitting a floating window should be treated the same as toggling floating mode on that window.) But maybe it also triggers in other situations? Unsplitting a fullscreen window seems to behave as if the window wasn't fullscreened, i.e. when i exited fullscreen mode the layout had been rearranged as if I hadn't been in fullscreen mode in the first place. Maybe that makes sense, but maybe there's an argument that unsplitting shouldn't occur in fullscreen mode since you can't immediately see the result of the action.
Author
Owner
Copy link

Thanks for the review!

Looks like sway uses tabs for indentation but the lines you added to this file are indented with four spaces, can you convert to tabs to keep the code base consistent?

Yeah, we should add this to PR validation, I bet this won't be the last time I forget :)

found/fixed a bug

Thanks!

maybe there's an argument that unsplitting shouldn't occur in fullscreen mode since you can't immediately see the result of the action

Good idea

Thanks for the review! > Looks like sway uses tabs for indentation but the lines you added to this file are indented with four spaces, can you convert to tabs to keep the code base consistent? Yeah, we should add this to PR validation, I bet this won't be the last time I forget :) > found/fixed a bug Thanks! > maybe there's an argument that unsplitting shouldn't occur in fullscreen mode since you can't immediately see the result of the action Good idea
Author
Owner
Copy link

maybe there's an argument that unsplitting shouldn't occur in fullscreen mode since you can't immediately see the result of the action

Hmm, you can currently 'split' in fullscreen mode, so perhaps it makes sense that you can also 'unsplit'. Maybe let's leave it as is for now and revisit in the future.

> maybe there's an argument that unsplitting shouldn't occur in fullscreen mode since you can't immediately see the result of the action Hmm, you can currently 'split' in fullscreen mode, so perhaps it makes sense that you can also 'unsplit'. Maybe let's leave it as is for now and revisit in the future.
raboof force-pushed implement-unsplit from 865506706d to 2e5ba55fdb
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline failed
2023年07月04日 10:22:59 +02:00
Compare
@ -47,0 +86,4 @@
struct sway_container *destination = find_unsplit_destination(current, ws, ancestor);
if (!destination) {
return cmd_results_new(CMD_FAILURE, "No destination frame found");
Collaborator
Copy link

Not clear to me that this should be a hard failure. Also, should probably use sway terminology here, "container" rather than "frame". Maybe something like:

sway_log(SWAY_DEBUG, "No destination container found for unsplit");
return cmd_results_new(CMD_SUCCESS, NULL);
Not clear to me that this should be a hard failure. Also, should probably use sway terminology here, "container" rather than "frame". Maybe something like: ```c sway_log(SWAY_DEBUG, "No destination container found for unsplit"); return cmd_results_new(CMD_SUCCESS, NULL); ```
edmonds marked this conversation as resolved
@ -47,0 +94,4 @@
if (child->is_placeholder) {
container_begin_destroy(child);
} else {
container_insert_child(destination, child, destination->pending.children->length);
Collaborator
Copy link

Use container_add_child() here

Use `container_add_child()` here
edmonds marked this conversation as resolved
raboof force-pushed implement-unsplit from 2e5ba55fdb
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline failed
to c843ff6f36
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
2023年07月04日 21:54:25 +02:00
Compare
@ -47,0 +87,4 @@
struct sway_container *destination = find_unsplit_destination(current, ws, ancestor);
if (!destination) {
sway_log(SWAY_DEBUG, "No destination container found for unsplit");
return cmd_results_new(CMD_SUCCESS, NULL);
Collaborator
Copy link

Whitespace :-)

Whitespace :-)
edmonds marked this conversation as resolved
raboof force-pushed implement-unsplit from c843ff6f36
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
to 7d0b24756f
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
2023年07月04日 21:59:56 +02:00
Compare
Sign in to join this conversation.
No reviewers
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
raboof/volare!59
Reference in a new issue
raboof/volare
No description provided.
Delete branch "implement-unsplit"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?