Skip to content

[Snowcap] Server-side object handle feedback #439

@Ottatop

Description

@Ottatop

With the work in #414, we're going to need to expose handles to server-side objects. The tasklist (and perhaps decorations) will need some form of ForeignToplevelHandle, and workspaces will need ExtWorkspaceHandles, names up for bikeshedding.

Currently, Pinnacle uses a pull-based API for all handles, with signals providing push-based information updates. I am considering a more push-based event stream to implement Snowcap handles with an eye towards maybe moving the Pinnacle API to something similar. This would be similar to event streams implemented in niri and hyprland—a single stream from which all object creation, update, and destruction events flow through. Currently with Pinnacle there are a bunch of different RPCs for single properties and I believe consolidating everything under a single source of truth is better long-term.

To implement this, I propose a single EventStream RPC:

message Event {
    oneof event {
        ForeignToplevelCreated foreign_toplevel_created = 1;
        ForeignToplevelUpdated foreign_toplevel_updated = 2;
        ForeignToplevelDestroyed foreign_toplevel_destroyed = 3;
        // the other stuff
    }
}

message EventStreamRequest {}
message EventStreamResponse {
    repeated Event events = 1;
}

service EventService {
    rpc EventStream(EventStreamRequest) returns (stream EventStreamResponse);
}

Each handle has its own create, update, and destroy messages.

However, there are a few questions that need answering:

  1. What exactly should those messages look like?

    A rough translation of the create, update, and destroy events initially implemented in Snowcap: Add WlrTaskList support #415 is this:

    message ForeignToplevelCreated {
        string identifier = 1;
    
        optional string app_id = 1;
        optional string title = 2;
        bool maximized = 3;
        bool minimized = 4;
        bool activated = 5;
        bool fullscreen = 6;
        repeated string output_names = 7;
        optional string parent_identifier = 8;
    }
    message ForeignToplevelUpdated {
        string identifier = 1;
    
        optional string app_id = 1;
        optional string title = 2;
        optional bool maximized = 3;
        optional bool minimized = 4;
        optional bool activated = 5;
        optional bool fullscreen = 6;
        optional string output_name_entered = 7;
        optional string output_name_left = 8;
        oneof parent {
            string parent_identifier = 9;
            google.protobuf.Empty unset = 10;
        }
    }
    message ForeignToplevelDestroyed {
        string identifier = 1;
    }

    This makes the update message look a little funky, especially when dealing with setting explicit nulls, but this isn't a dealbreaker.

    We could also do a more Wayland-style approach and have Created just supply the identifier and split all of the fields of Update into their own message. I'm not sure how good of an idea that is.

  2. I'm not sure if we should also roll in all the other stream-type RPCs we have like widget events and the recently-merged layer and popup events.

@Ph4ntomas What do you think?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions