Skip to content

feat: WindowRules Workspace Assignment - #137

Open
karlskewes wants to merge 2 commits into
pop-os:masterfrom
karlskewes:workspace-pinning
Open

feat: WindowRules Workspace Assignment#137
karlskewes wants to merge 2 commits into
pop-os:masterfrom
karlskewes:workspace-pinning

Conversation

@karlskewes

@karlskewes karlskewes commented Mar 20, 2026

Copy link
Copy Markdown

Feature

Extend WindowRules enabling launching applications/windows on specific workspaces instead of the current active workspace.

Required for: pop-os/cosmic-comp#2214

How to use

Assign workspace names.

Pin workspaces using UI or via file:

$ cat ~/.config/cosmic/com.system76.CosmicComp/v1/pinned_workspaces 
[
    (
        output: (
            name: "eDP-1",
            edid: None,
        ),
        tiling_enabled: true,
        id: Some("11f90a5"),
        name: Some("terminal"),
    ),
    (
        output: (
            name: "eDP-1",
            edid: None,
        ),
        tiling_enabled: true,
        id: Some("b382cb"),
        name: Some("browser"),
    ),
]

Define Workspace Assignment configuration file with matching name's:

$ cat ~/.config/cosmic/com.system76.CosmicSettings.WindowRules/v1/workspace_assignment_custom
[
  (
    enabled: true,
    appid: "kitty",
    title: ".*",
    workspace_name: "terminal"
  ),
  (
    enabled: true,
    appid: "firefox",
    title: ".*",
    workspace_name: "browser"
  )
]

Disable the window rule by setting enabled: false.

Testing

  1. branch based off flake changes in: refactor: nix flake for build and dev #138
    1. Validate package builds: nix build
    2. Development shell builds: nix develop and then cargo check
  2. cosmic-comp build and execute per feat: WindowRules Workspace Assignment cosmic-comp#2214
  3. NixOS overlay replacing upstream with my fork and this branch.

Note to reviewers

This is my first contribution to Cosmic and I may have misunderstood or completely missed project structure/styling or other conventions. Please let me know and I'll rework accordingly. Thank you!

  • "workspace assignment" naming chosen based off i3wm:
    assign [class="<application_class>"] <workspace_number>
  • separate file path/to/WindowRules/workspace_assignment_custom because it appears to be convention to have a file per feature, rather than a catch all ../WindowRules/window_rules with features: sticky, tiling exceptions, workspace assignment, etc
  • left workspace_assignment_defaults free for implementation if required.

AI Disclosure

No AI generated code in the development of this PR.

  • I have disclosed use of any AI generated code in my commit messages.
    • If you are using an LLM, and do not fully understand the changes it is making to the code base, do not create a PR.
    • In our experience, AI generated code often results in overly complex code that lacks enough context for a proper fix or feature inclusion. This results in considerably longer code reviews. Due to this, AI authored or partially authored PRs may be closed without comment.
  • I understand these changes in full and will be able to respond to review comments.
  • My change is accurately described in the commit message.
  • My contribution is tested and working as described.
  • I have read the Developer Certificate of Origin and certify my contribution under its conditions.

@karlskewes karlskewes changed the title Workspace pinning feat: WindowRules Workspace Assignment Mar 20, 2026
@karlskewes
karlskewes marked this pull request as ready for review March 23, 2026 20:57
@karlskewes
karlskewes force-pushed the workspace-pinning branch 2 times, most recently from 73bcf86 to d96ad98 Compare March 24, 2026 20:33

/// Get the current workspace assignment configuration
pub fn workspace_assignments(context: &cosmic_config::Config) -> Vec<WorkspaceAssignment> {
// Load custom assignments defined by the user.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are ..WindowRules/v1/workspace_assignment_defaults likely?
Wondering if we should use the file workspace_assignment instead or something else if a different naming is preferred.

Some(WorkspaceAssignment {
appid: assignment.appid.clone(),
title: assignment.title.clone(),
enabled: true, // Currently unused.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WorkspaceAssignment.enabled is not used in cosmic-comp.

We could instead have a WorkspaceAssignmentConfig struct { ... enabled: bool } and drop the enabled struct field from WorkspaceAssignment.

return Vec::new();
}
}
if why.is_err()

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clippy lint fix whilst in file, see: pop-os/cosmic-comp#2212

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up updating/fixing all but one here: #142

@karlskewes
karlskewes force-pushed the workspace-pinning branch from ccc11cd to bf74a86 Compare June 2, 2026 20:54
@karlskewes
karlskewes force-pushed the workspace-pinning branch 2 times, most recently from 43f27af to 117942b Compare July 10, 2026 05:17
@karlskewes

Copy link
Copy Markdown
Author

Rebased on 1.2.0.

@karlskewes

karlskewes commented Jul 31, 2026

Copy link
Copy Markdown
Author

Rebased on 1.4.0, 1.5.0, 1.7.0.

Workspace Assignments are a new feature enabling applications to be
consistently launched automatically onto a specific workspace ID.

This commit includes the config structs and getter functions for storing
assignments, e.g:
`com.system76.CosmicSettings.WindowRules/v1/workspace_assignment_custom`

Default (CosmicDE defined) assignments are not currently supported but
code and filenames have been chosen to avoid a conflict with the
standard naming.
@jacobktm

Copy link
Copy Markdown
$ cat ~/.config/cosmic/com.system76.CosmicSettings.WindowRules/v1/workspace_assignment_custom
[
  (
    enabled: true,
    appid: "cosmic-term",
    title: ".*",
    workspace_name: "terminal"
  ),
  (
    enabled: true,
    appid: "firefox",
    title: ".*",
    workspace_name: "browser"
  )
]

I tried this rather than your example above, the only thing I changed was trying to set the terminal to cosmic-term. I set this up in conjunction with pop-os/cosmic-comp#2214. Firefox does open in the expected workspace, but cosmic-term still opens in whatever the active workspace is.

@karlskewes

karlskewes commented Aug 29, 2026

Copy link
Copy Markdown
Author

Stylistically I should make it app_id instead of appid. Other code uses appid.

Hi @jacobktm, can you please try with appid: "com.system76.CosmicTerm".

This is per this:

nix-shell:~/src/github.com/karlskewes/cosmic-protocols]$ nix-shell -p pkg-config openssl wayland

nix-shell:~/src/github.com/karlskewes/cosmic-protocols]$ cargo run --example toplevel-list
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/examples/toplevel-list`
Toplevel ObjectId(zcosmic_toplevel_handle_v1@4278190080)
	Title: Some("~/src/github.com/karlskewes/nixos")
	App ID: Some("kitty")
	States: []
	Outputs: []
	Workspaces: []
Toplevel ObjectId(zcosmic_toplevel_handle_v1@4278190081)
	Title: Some("feat: WindowRules Workspace Assignment by karlskewes · Pull Request #137 · pop-os/cosmic-settings-daemon — Mozilla Firefox")
	App ID: Some("firefox")
	States: []
	Outputs: []
	Workspaces: []
Toplevel ObjectId(zcosmic_toplevel_handle_v1@4278190082)
	Title: Some("~/src/github.com/karlskewes/cosmic-protocols — COSMIC Terminal")
	App ID: Some("com.system76.CosmicTerm")
	States: [Activated]
	Outputs: []
	Workspaces: []

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants