Full Code of glzr-io/glazewm for AI

main 6e5242eaecc4 cached
214 files
873.3 KB
224.1k tokens
1202 symbols
1 requests
Download .txt
Showing preview only (935K chars total). Download the full file or copy to clipboard to get everything.
Repository: glzr-io/glazewm
Branch: main
Commit: 6e5242eaecc4
Files: 214
Total size: 873.3 KB

Directory structure:
gitextract_qulwdvhw/

├── .cargo/
│   └── config.toml
├── .editorconfig
├── .gitattributes
├── .github/
│   └── workflows/
│       ├── build.yaml
│       ├── lint-check.yaml
│       ├── package.yaml
│       ├── pr-title-check.yaml
│       ├── release.yaml
│       └── winget-release.yaml
├── .gitignore
├── .vscode/
│   ├── launch.json
│   ├── settings.json
│   └── tasks.json
├── CLAUDE.md
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE.md
├── README.md
├── README_zh.md
├── clippy.toml
├── packages/
│   ├── wm/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   └── src/
│   │       ├── commands/
│   │       │   ├── container/
│   │       │   │   ├── attach_container.rs
│   │       │   │   ├── detach_container.rs
│   │       │   │   ├── flatten_child_split_containers.rs
│   │       │   │   ├── flatten_split_container.rs
│   │       │   │   ├── focus_container_by_id.rs
│   │       │   │   ├── focus_in_direction.rs
│   │       │   │   ├── mod.rs
│   │       │   │   ├── move_container_within_tree.rs
│   │       │   │   ├── replace_container.rs
│   │       │   │   ├── resize_tiling_container.rs
│   │       │   │   ├── set_focused_descendant.rs
│   │       │   │   ├── toggle_tiling_direction.rs
│   │       │   │   └── wrap_in_split_container.rs
│   │       │   ├── general/
│   │       │   │   ├── cycle_focus.rs
│   │       │   │   ├── disable_binding_mode.rs
│   │       │   │   ├── enable_binding_mode.rs
│   │       │   │   ├── mod.rs
│   │       │   │   ├── platform_sync.rs
│   │       │   │   ├── reload_config.rs
│   │       │   │   ├── shell_exec.rs
│   │       │   │   └── toggle_pause.rs
│   │       │   ├── mod.rs
│   │       │   ├── monitor/
│   │       │   │   ├── add_monitor.rs
│   │       │   │   ├── focus_monitor.rs
│   │       │   │   ├── mod.rs
│   │       │   │   ├── remove_monitor.rs
│   │       │   │   ├── sort_monitors.rs
│   │       │   │   └── update_monitor.rs
│   │       │   ├── window/
│   │       │   │   ├── ignore_window.rs
│   │       │   │   ├── manage_window.rs
│   │       │   │   ├── mod.rs
│   │       │   │   ├── move_window_in_direction.rs
│   │       │   │   ├── move_window_to_workspace.rs
│   │       │   │   ├── resize_window.rs
│   │       │   │   ├── run_window_rules.rs
│   │       │   │   ├── set_window_position.rs
│   │       │   │   ├── set_window_size.rs
│   │       │   │   ├── unmanage_window.rs
│   │       │   │   └── update_window_state.rs
│   │       │   └── workspace/
│   │       │       ├── activate_workspace.rs
│   │       │       ├── deactivate_workspace.rs
│   │       │       ├── focus_workspace.rs
│   │       │       ├── mod.rs
│   │       │       ├── move_workspace_in_direction.rs
│   │       │       ├── sort_workspaces.rs
│   │       │       └── update_workspace_config.rs
│   │       ├── events/
│   │       │   ├── handle_display_settings_changed.rs
│   │       │   ├── handle_mouse_move.rs
│   │       │   ├── handle_window_destroyed.rs
│   │       │   ├── handle_window_focused.rs
│   │       │   ├── handle_window_hidden.rs
│   │       │   ├── handle_window_minimize_ended.rs
│   │       │   ├── handle_window_minimized.rs
│   │       │   ├── handle_window_moved_or_resized.rs
│   │       │   ├── handle_window_moved_or_resized_end.rs
│   │       │   ├── handle_window_shown.rs
│   │       │   ├── handle_window_title_changed.rs
│   │       │   └── mod.rs
│   │       ├── ipc_server.rs
│   │       ├── main.rs
│   │       ├── models/
│   │       │   ├── container.rs
│   │       │   ├── insertion_target.rs
│   │       │   ├── mod.rs
│   │       │   ├── monitor.rs
│   │       │   ├── native_monitor_properties.rs
│   │       │   ├── native_window_properties.rs
│   │       │   ├── non_tiling_window.rs
│   │       │   ├── root_container.rs
│   │       │   ├── split_container.rs
│   │       │   ├── tiling_window.rs
│   │       │   ├── workspace.rs
│   │       │   └── workspace_target.rs
│   │       ├── pending_sync.rs
│   │       ├── sys_tray.rs
│   │       ├── traits/
│   │       │   ├── common_getters.rs
│   │       │   ├── mod.rs
│   │       │   ├── position_getters.rs
│   │       │   ├── tiling_direction_getters.rs
│   │       │   ├── tiling_size_getters.rs
│   │       │   └── window_getters.rs
│   │       ├── user_config.rs
│   │       ├── wm.rs
│   │       └── wm_state.rs
│   ├── wm-cli/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   └── src/
│   │       ├── lib.rs
│   │       └── main.rs
│   ├── wm-common/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── active_drag.rs
│   │       ├── app_command.rs
│   │       ├── display_state.rs
│   │       ├── dtos/
│   │       │   ├── container_dto.rs
│   │       │   ├── mod.rs
│   │       │   ├── monitor_dto.rs
│   │       │   ├── root_container_dto.rs
│   │       │   ├── split_container_dto.rs
│   │       │   ├── window_dto.rs
│   │       │   └── workspace_dto.rs
│   │       ├── hide_corner.rs
│   │       ├── ipc.rs
│   │       ├── lib.rs
│   │       ├── parsed_config.rs
│   │       ├── tiling_direction.rs
│   │       ├── utils/
│   │       │   ├── iterator_ext.rs
│   │       │   ├── mod.rs
│   │       │   ├── try_warn.rs
│   │       │   └── vec_deque_ext.rs
│   │       ├── window_state.rs
│   │       └── wm_event.rs
│   ├── wm-ipc-client/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── lib.rs
│   ├── wm-macros/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── common/
│   │       │   ├── attributes.rs
│   │       │   ├── branch.rs
│   │       │   ├── error_handling.rs
│   │       │   ├── mod.rs
│   │       │   ├── named_parameter.rs
│   │       │   ├── parenthesized.rs
│   │       │   ├── peekable.rs
│   │       │   └── spanned_string.rs
│   │       ├── enum_from_inner/
│   │       │   └── mod.rs
│   │       ├── lib.rs
│   │       └── subenum/
│   │           ├── enum_attrs.rs
│   │           ├── mod.rs
│   │           └── variant_attr.rs
│   ├── wm-platform/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   └── src/
│   │       ├── dispatcher.rs
│   │       ├── display.rs
│   │       ├── display_listener.rs
│   │       ├── error.rs
│   │       ├── event_loop.rs
│   │       ├── keybinding_listener.rs
│   │       ├── lib.rs
│   │       ├── models/
│   │       │   ├── color.rs
│   │       │   ├── corner_style.rs
│   │       │   ├── delta.rs
│   │       │   ├── direction.rs
│   │       │   ├── key.rs
│   │       │   ├── key_code.rs
│   │       │   ├── length_value.rs
│   │       │   ├── mod.rs
│   │       │   ├── opacity_value.rs
│   │       │   ├── point.rs
│   │       │   ├── rect.rs
│   │       │   └── rect_delta.rs
│   │       ├── mouse_listener.rs
│   │       ├── native_window.rs
│   │       ├── platform_event.rs
│   │       ├── platform_impl/
│   │       │   ├── macos/
│   │       │   │   ├── application.rs
│   │       │   │   ├── application_observer.rs
│   │       │   │   ├── ax_ui_element.rs
│   │       │   │   ├── ax_value.rs
│   │       │   │   ├── display.rs
│   │       │   │   ├── display_listener.rs
│   │       │   │   ├── event_loop.rs
│   │       │   │   ├── ffi.rs
│   │       │   │   ├── keyboard_hook.rs
│   │       │   │   ├── mod.rs
│   │       │   │   ├── mouse_listener.rs
│   │       │   │   ├── native_window.rs
│   │       │   │   ├── notification_center.rs
│   │       │   │   ├── single_instance.rs
│   │       │   │   └── window_listener.rs
│   │       │   ├── mod.rs
│   │       │   └── windows/
│   │       │       ├── com.rs
│   │       │       ├── display.rs
│   │       │       ├── display_listener.rs
│   │       │       ├── event_loop.rs
│   │       │       ├── keyboard_hook.rs
│   │       │       ├── mod.rs
│   │       │       ├── mouse_listener.rs
│   │       │       ├── native_window.rs
│   │       │       ├── single_instance.rs
│   │       │       └── window_listener.rs
│   │       ├── single_instance.rs
│   │       ├── test.rs
│   │       ├── thread_bound.rs
│   │       └── window_listener.rs
│   └── wm-watcher/
│       ├── Cargo.toml
│       ├── build.rs
│       └── src/
│           └── main.rs
├── resources/
│   ├── Info.plist
│   ├── assets/
│   │   └── sample-config.yaml
│   ├── scripts/
│   │   └── package.ps1
│   └── wix/
│       ├── bundle-theme.wxl
│       ├── bundle-theme.xml
│       ├── bundle.wxs
│       ├── standalone-ui.wxs
│       └── standalone.wxs
├── rust-toolchain.toml
└── rustfmt.toml

================================================
FILE CONTENTS
================================================

================================================
FILE: .cargo/config.toml
================================================
[env]
# Version number shown in CLI and system tray. Override this by setting the
# version number on build/run (i.e. `VERSION_NUMBER="1.0.0" cargo run`).
VERSION_NUMBER = "0.0.0"


================================================
FILE: .editorconfig
================================================
# Editor configuration, see https://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
max_line_length = off


================================================
FILE: .gitattributes
================================================
# Set CRLF as the line ending to use for all files that Git interprets as text files.
* text=auto eol=crlf


================================================
FILE: .github/workflows/build.yaml
================================================
name: Build

on:
  workflow_call:
    inputs:
      enable_ui_access:
        type: boolean
        default: false
        description: (Windows only) Enable UIAccess in the application manifest.
      version_number:
        type: string
        default: 0.0.0
        description: Version number to use for the build.

jobs:
  build:
    strategy:
      fail-fast: false
      matrix:
        include:
          # MacOS (Intel)
          - platform: macos-latest
            target: x86_64-apple-darwin
          # MacOS (Apple Silicon)
          - platform: macos-latest
            target: aarch64-apple-darwin
          # 64-bit Windows (Intel & AMD)
          - platform: windows-latest
            target: x86_64-pc-windows-msvc
          # 64-bit Windows (ARM)
          - platform: windows-latest
            target: aarch64-pc-windows-msvc

    runs-on: ${{ matrix.platform }}
    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@21dc36fb71dd22e3317045c0c31a3f4249868b17
        with:
          targets: ${{ matrix.target }}
          toolchain: nightly

      - uses: swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3
        with:
          shared-key: ${{ matrix.target }}-${{ hashFiles('Cargo.lock') }}

      - name: Build for ${{ matrix.target }}
        env:
          VERSION_NUMBER: ${{ inputs.version_number }}
          # Conditionally enable UIAccess feature for Windows.
          FEATURES: ${{ matrix.platform == 'windows-latest' && inputs.enable_ui_access && '--features ui_access' || '' }}
          # Include `wm-watcher` when building for Windows.
          SCOPE: ${{ matrix.platform == 'windows-latest' && '--workspace' || '' }}
        shell: bash
        run: cargo build --locked --release --target ${{ matrix.target }} $SCOPE $FEATURES

      - name: Create upload directory
        shell: bash
        run: |
          SOURCE_DIR="target/${{ matrix.target }}/release"
          UPLOAD_DIR="temp/$SOURCE_DIR"
          mkdir -p "$UPLOAD_DIR"

          # Move build artifacts. Suppress errors for missing platform-specific binaries.
          mv "$SOURCE_DIR"/glazewm{,-cli} \
            "$SOURCE_DIR"/glazewm{,-cli,-watcher}.exe \
            "$UPLOAD_DIR/" 2>/dev/null || true

      - uses: actions/upload-artifact@v6
        with:
          if-no-files-found: error
          name: build-${{ matrix.target }}
          path: temp


================================================
FILE: .github/workflows/lint-check.yaml
================================================
name: Lint check

on:
  push:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  lint-check:
    strategy:
      fail-fast: false
      matrix:
        include:
          # MacOS (Apple Silicon)
          - platform: macos-latest
            target: aarch64-apple-darwin
          # Windows (x64)
          - platform: windows-latest
            target: x86_64-pc-windows-msvc

    runs-on: ${{ matrix.platform }}
    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@21dc36fb71dd22e3317045c0c31a3f4249868b17
        with:
          components: clippy, rustfmt
          targets: ${{ matrix.target }}
          toolchain: nightly

      - uses: swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3
        with:
          shared-key: ${{ matrix.target }}-${{ hashFiles('Cargo.lock') }}

      - name: Check formatting (rustfmt)
        run: cargo fmt --check

      # Clippy itself runs `cargo check`, so this will also check for compilation errors.
      - name: Check linting (clippy)
        run: cargo clippy --all-targets --all-features -- -D warnings


================================================
FILE: .github/workflows/package.yaml
================================================
name: Package

on:
  workflow_call:
    inputs:
      version_number:
        type: string
        default: 0.0.0
        description: Version number to use for the build (e.g. `1.0.0`).
  workflow_dispatch:
    inputs:
      version_number:
        type: string
        default: 0.0.0
        description: Version number to use for the build (e.g. `1.0.0`).

jobs:
  build:
    uses: ./.github/workflows/build.yaml
    with:
      enable_ui_access: true
      version_number: ${{ inputs.version_number }}

  package-windows:
    needs: build
    runs-on: windows-latest
    env:
      VERSION: ${{ inputs.version_number }}
    steps:
      - uses: actions/checkout@v4

      - name: Download build artifacts
        uses: actions/download-artifact@v8
        with:
          pattern: build-*
          merge-multiple: true

      - name: Install WiX and its extensions
        run: |
          dotnet tool install --global wix --version 5.0.0
          wix extension add WixToolset.UI.wixext/5 WixToolset.Util.wixext/5 WixToolset.BootstrapperApplications.wixext/5

      - name: Install AzureSignTool
        run: |
          dotnet tool install --global AzureSignTool --version 5.0.0

      - name: Run packaging script
        env:
          AZ_VAULT_URL: ${{ secrets.AZ_VAULT_URL }}
          AZ_CERT_NAME: ${{ secrets.AZ_CERT_NAME }}
          AZ_CLIENT_ID: ${{ secrets.AZ_CLIENT_ID }}
          AZ_CLIENT_SECRET: ${{ secrets.AZ_CLIENT_SECRET }}
          AZ_TENANT_ID: ${{ secrets.AZ_TENANT_ID }}
          RFC3161_TIMESTAMP_URL: ${{ vars.RFC3161_TIMESTAMP_URL }}
        run: |
          ./resources/scripts/package.ps1 -VersionNumber $env:VERSION

      - uses: actions/upload-artifact@v6
        with:
          name: package-windows
          if-no-files-found: error
          path: out/installer-*

  package-macos:
    needs: build
    runs-on: macos-latest
    env:
      VERSION: ${{ inputs.version_number }}
    steps:
      - uses: actions/checkout@v4

      - name: Download build artifacts
        uses: actions/download-artifact@v8
        with:
          pattern: build-*
          merge-multiple: true

      - name: Create universal binaries
        run: |
          mkdir temp
          for binary in glazewm glazewm-cli; do
            lipo -create \
              "target/x86_64-apple-darwin/release/$binary" \
              "target/aarch64-apple-darwin/release/$binary" \
              -output "temp/$binary"
            chmod +x "temp/$binary"
          done

      - name: Import signing certificate
        env:
          APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
          APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
        run: |
          # Create a temporary keychain.
          KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
          KEYCHAIN_PASSWORD=$(openssl rand -base64 32)

          security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
          security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
          security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"

          # Import the certificate.
          echo "$APPLE_CERTIFICATE" | base64 --decode > $RUNNER_TEMP/certificate.p12
          security import $RUNNER_TEMP/certificate.p12 \
            -P "$APPLE_CERTIFICATE_PASSWORD" \
            -A \
            -t cert \
            -f pkcs12 \
            -k "$KEYCHAIN_PATH"

          security list-keychain -d user -s "$KEYCHAIN_PATH"

          # Store the keychain path for later steps.
          echo "KEYCHAIN_PATH=$KEYCHAIN_PATH" >> $GITHUB_ENV

      # Make sure to sign the binaries before they're copied into the app bundle.
      - name: Sign universal binaries
        env:
          APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
        run: |
          for binary in glazewm glazewm-cli; do
            codesign --force --options runtime --timestamp \
              --sign "$APPLE_SIGNING_IDENTITY" \
              "temp/$binary"
            codesign --verify --verbose=2 "temp/$binary"
          done

      - name: Convert icon to ICNS
        run: |
          ICONSET_DIR="temp/icon.iconset"
          mkdir -p $ICONSET_DIR
          sips -z 16 16     resources/assets/icon.png --out $ICONSET_DIR/icon_16x16.png
          sips -z 32 32     resources/assets/icon.png --out $ICONSET_DIR/icon_16x16@2x.png
          sips -z 32 32     resources/assets/icon.png --out $ICONSET_DIR/icon_32x32.png
          sips -z 64 64     resources/assets/icon.png --out $ICONSET_DIR/icon_32x32@2x.png
          sips -z 128 128   resources/assets/icon.png --out $ICONSET_DIR/icon_128x128.png
          sips -z 256 256   resources/assets/icon.png --out $ICONSET_DIR/icon_128x128@2x.png
          sips -z 256 256   resources/assets/icon.png --out $ICONSET_DIR/icon_256x256.png
          sips -z 512 512   resources/assets/icon.png --out $ICONSET_DIR/icon_256x256@2x.png
          sips -z 512 512   resources/assets/icon.png --out $ICONSET_DIR/icon_512x512.png
          sips -z 1024 1024 resources/assets/icon.png --out $ICONSET_DIR/icon_512x512@2x.png
          iconutil -c icns $ICONSET_DIR -o temp/icon.icns

      - name: Create app bundle
        run: |
          CONTENTS_DIR="temp/GlazeWM.app/Contents"
          mkdir -p "$CONTENTS_DIR/MacOS" "$CONTENTS_DIR/Resources"

          cp temp/glazewm "$CONTENTS_DIR/MacOS/"
          cp temp/glazewm-cli "$CONTENTS_DIR/MacOS/"
          cp temp/icon.icns "$CONTENTS_DIR/Resources/icon.icns"
          chmod +x "$CONTENTS_DIR/MacOS"/*

          # Substitute version placeholder in Info.plist.
          sed "s/\${VERSION}/$VERSION/g" resources/Info.plist > "$CONTENTS_DIR/Info.plist"

          echo -n "APPL????" > "$CONTENTS_DIR/PkgInfo"

      - name: Sign app bundle
        env:
          APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
        run: |
          codesign --force --options runtime --timestamp \
            --sign "$APPLE_SIGNING_IDENTITY" \
            temp/GlazeWM.app
          codesign --verify --verbose=2 --deep --strict temp/GlazeWM.app

      - name: Create DMG
        run: |
          DMG_DIR="temp/dmg-contents"
          mkdir -p $DMG_DIR
          cp -R temp/GlazeWM.app $DMG_DIR/

          # Create a symbolic link to `/Applications` folder.
          ln -s /Applications $DMG_DIR/Applications

          # Create the DMG.
          hdiutil create -volname GlazeWM \
            -srcfolder $DMG_DIR \
            -ov -format UDZO \
            installer-universal.dmg

      - name: Sign DMG
        env:
          APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
        run: |
          codesign --force --timestamp \
            --sign "$APPLE_SIGNING_IDENTITY" \
            installer-universal.dmg

      - name: Notarize DMG
        env:
          APPLE_ID: ${{ secrets.APPLE_ID }}
          APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
          APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
        run: |
          # Submit for notarization.
          xcrun notarytool submit installer-universal.dmg \
            --apple-id "$APPLE_ID" \
            --password "$APPLE_ID_PASSWORD" \
            --team-id "$APPLE_TEAM_ID" \
            --wait

          # Staple the notarization ticket to the DMG.
          xcrun stapler staple installer-universal.dmg

      - name: Upload DMG
        uses: actions/upload-artifact@v6
        with:
          name: package-macos
          if-no-files-found: error
          path: installer-universal.dmg


================================================
FILE: .github/workflows/pr-title-check.yaml
================================================
name: PR title check

on:
  pull_request:
    types: [opened, edited, synchronize, reopened]

jobs:
  pr-title-check:
    runs-on: ubuntu-latest
    steps:
      - uses: glzr-io/actions/semantic-prs@main
        with:
          gh-token: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .github/workflows/release.yaml
================================================
name: Release

on:
  workflow_dispatch:
    inputs:
      version_number:
        type: string
        description: Version number to use for the build (e.g. `1.0.0`).

permissions:
  contents: write

concurrency:
  group: release

jobs:
  package:
    uses: ./.github/workflows/package.yaml
    secrets: inherit
    with:
      version_number: ${{ inputs.version_number }}

  release:
    needs: package
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Download installers
        uses: actions/download-artifact@v8
        with:
          pattern: package-*
          merge-multiple: true

      - name: Rename installers
        env:
          # Add a `v` prefix to the version number.
          VERSION: v${{ inputs.version_number }}
        run: |
          mv installer-universal.exe "glazewm-$VERSION.exe"
          mv installer-arm64.msi "standalone-glazewm-$VERSION-arm64.msi"
          mv installer-x64.msi "standalone-glazewm-$VERSION-x64.msi"
          mv installer-universal.dmg "glazewm-$VERSION.dmg"

      - name: Create draft release
        env:
          # Add a `v` prefix to the version number.
          VERSION: v${{ inputs.version_number }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh release create "$VERSION" \
            --title "$VERSION" \
            --generate-notes \
            --draft \
            "./glazewm-$VERSION.exe#$VERSION for Windows (standard)" \
            "./standalone-glazewm-$VERSION-arm64.msi#$VERSION for Windows (standalone, arm64)" \
            "./standalone-glazewm-$VERSION-x64.msi#$VERSION for Windows (standalone, x64)" \
            "./glazewm-$VERSION.dmg#$VERSION for macOS"


================================================
FILE: .github/workflows/winget-release.yaml
================================================
name: Winget release

on:
  workflow_dispatch:
  release:
    types: [published]

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: vedantmgoyal9/winget-releaser@19e706d4c9121098010096f9c495a70a7518b30f
        with:
          identifier: glzr-io.glazewm
          installers-regex: 'glazewm-v[0-9.]+\.exe$'
          token: ${{ secrets.WINGET_TOKEN }}


================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# Build outputs
target/
out/

# Misc
.DS_Store
*.pem
*.env
.wix/

# IDE files
.vs/
.idea/


================================================
FILE: .vscode/launch.json
================================================
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch",
      "type": "cppvsdbg",
      "request": "launch",
      "program": "${workspaceRoot}/target/debug/glazewm.exe",
      "preLaunchTask": "rust: cargo build",
      "args": ["start"],
      "stopAtEntry": false,
      "cwd": "${workspaceRoot}",
      "environment": [],
      "console": "integratedTerminal"
      // "externalConsole": true
    }
  ]
}


================================================
FILE: .vscode/settings.json
================================================
{
  "rust-analyzer.check.command": "clippy",
  "editor.insertSpaces": true,
  "editor.tabSize": 2,
  "files.insertFinalNewline": true,
  "files.trimTrailingWhitespace": true,
}


================================================
FILE: .vscode/tasks.json
================================================
{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "cargo",
      "command": "build",
      "problemMatcher": ["$rustc"],
      "group": "build",
      "label": "rust: cargo build"
    }
  ]
}


================================================
FILE: CLAUDE.md
================================================
<project_overview>
GlazeWM is a window manager for macOS and Windows, written in Rust.

Crate structure:

- **wm** (bin): Main application, which implements the core window management logic. Install path on Windows: `C:\Program Files\glzr.io\glazewm.exe`
- **wm-cli** (bin, lib): CLI for interacting with the main application. Added to `$PATH` by default. Install path on Windows: `C:\Program Files\glzr.io\cli\glazewm.exe`
- **wm-common** (lib): Shared types, utilities, and constants used across other crates.
- **wm-ipc-client** (lib): WebSocket client library for IPC with the main application.
- **wm-platform** (lib): Wrappers over platform-specific APIs; other crates do not call Windows/macOS APIs directly.
- **wm-watcher** (Windows-only) (bin): Watchdog process ensuring proper cleanup when the main application exits. Install path on Windows: `C:\Program Files\glzr.io\glazewm-watcher.exe`

</project_overview>

<output_guidelines>

- Be extremely concise. Sacrifice grammar for the sake of conciseness.
- Do not leave partial or simplified implementations.
- The required quality standard is high. Low quality code will be rejected.
- Do not proceed with solutions that are hacky. Solutions must be robust, maintainable, and extendable. Ask guiding questions if uncertain about a solution.

</output_guidelines>

<code_style_guidelines>

- Avoid `.unwrap()` wherever possible.
- For error handling:
  - Use `crate::Error` and `crate::Result` within the `wm-platform` crate.
  - Use `anyhow` in all other crates.
- For logging, use `tracing` macros (e.g. `tracing::info!("...")`).

</code_style_guidelines>

<code_comment_guidelines>

- Functions should always be documented.
- Use punctuation mark at the end of all comments.
- If using unsafe features, include a "SAFETY: ..." comment.
- Wrap type names in backticks (e.g. `NativeMonitor`).

Comment structure:

```rs
/// <Concise summary of the function or type>
///
/// (optional) <Notable caveats for usage (kept brief)>
///
/// (optional) <Describe return value if ambiguous (e.g. "Returns a vector of `NativeMonitor`, sorted by their position from left-to-right.")>
///
/// (optional) # Example usage
///
/// <Code block with example usage>
///
/// (optional) # Platform-specific
///
/// <Bullet-point list of behavioral differences on macOS vs Windows>
pub fn my_function() { ... }
```

</code_comment_guidelines>

<test_guidelines>

- Use `#[cfg(test)]` for test modules.
- Write unit tests for core functionality.

</test_guidelines>


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to GlazeWM

Thanks for your interest in improving GlazeWM 💛

There are fundamentally three ways to contribute:

1. **Opening issues**: If you believe you've found a bug or have a feature request, open an issue to discuss it.

2. **Helping triage issues**: Add supporting details and suggestions to existing issues.

3. **Submitting PRs**: Submit a PR that fixes a bug or implements a feature.

The [#glazewm-dev channel ⚡](https://discord.com/invite/ud6z3qjRvM) is also available for any concerns not covered in this guide, please join us!

## Pull requests & dev workflow

For PRs, a good place to start are the issues marked as [`good first issue`](https://github.com/glzr-io/glazewm/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) or [`help wanted`](https://github.com/glzr-io/glazewm/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22). PR's don't have a requirement to have a corresponding issue, but if there is one already, please drop a comment in the issue and we can assign it to you.

### Setup

First fork, then clone the repo:

```shell
git clone git@github.com:your-username/glazewm.git
```

If not already installed, [install Rust](https://rustup.rs/), then run:

```shell
# `cargo build` will build all binaries and libraries.
# `cargo run` will run the default binary, which is configured to be the wm.
cargo build && cargo run
```

After making your changes, push to your fork and [submit a pull request](https://github.com/glzr-io/zebar/pulls) against the `main` branch. Please try to address only a single feature or fix in the PR so that it's easy to review.

### Tips

If using VSCode, it's recommended to use the [Rust Analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) extension. Get automatic linting by adding this to your VSCode's `settings.json`:

```json
{
  "rust-analyzer.check.command": "clippy"
}
```

## Codebase overview

Knowledge of the entire codebase should never be required to make changes. The following should hopefully help with understanding a particular part of the codebase.

### Crates

GlazeWM is organized into several Rust crates:

- `wm` (bin): Main application, which implements the core window management logic.
  - Gets installed to `C:\Program Files\glzr.io\glazewm.exe`.
- `wm-cli` (bin/lib): CLI for interacting with the main application.
  - Gets installed to `C:\Program Files\glzr.io\cli\glazewm.exe`. This is added to `$PATH` by default.
- `wm-common` (lib): Shared types, utilities, and constants used across other crates.
- `wm-ipc-client` (lib): WebSocket client library for IPC with the main application.
- `wm-platform` (lib): Wrappers over platform-specific API's - other crates don't interact directly with the Windows and macOS API's.
- `wm-watcher` (bin): Watchdog process that ensures proper cleanup when the main application exits.
  - Gets installed to `C:\Program Files\glzr.io\glazewm-watcher.exe`.

### Commands & events

GlazeWM uses a command-event architecture. The state of the WM (stored in [`WmState`](https://github.com/glzr-io/glazewm/blob/main/packages/wm/src/wm_state.rs)) is modified via [commands](https://github.com/glzr-io/glazewm/tree/main/packages/wm/src/commands) and [events](https://github.com/glzr-io/glazewm/tree/main/packages/wm/src/events).

- Commands are run as a result of keybindings, IPC calls, the CLI (which calls IPC internally), or by being called from another command. Most commands are just for internal use and might not have a public-facing API.
- Events arise from the Windows platform (e.g. a window being created, destroyed, focused, etc.). Each of these events have a handler that then modifies the WM state.

Commands and events are processed in a loop in [`start_wm`](https://github.com/glzr-io/glazewm/blob/main/packages/wm/src/main.rs#L68).

## Container tree

Windows in GlazeWM are organized within a tree hierarchy with the following "container" types:

- Root
- Monitors (physical displays)
- Workspaces (virtual groups of windows)
- Split containers (for tiling layouts)
- Windows (application windows)

Here's an example container tree:

```
                                            Root
                                             |
                            +----------------+----------------+
                            |                                 |
                        Monitor 1                         Monitor 2
                            |                                 |
                   +--------+--------+                        |
                   |                 |                        |
               Workspace 1       Workspace 2             Workspace 3
               [horizontal]      [vertical]              [horizontal]
                   |                 |                        |
                   |                 |                        |
              +----+----+      Tiling Window            +-----+-----+
              |         |        (Spotify)              |           |
        Tiling Window   |                       Tiling Window  Floating Window
         (Terminal)     |                         (Discord)       (Slack)
                        |
                        |
                  Split Container
                    [vertical]
                        |
                   +----+----+
                   |         |
           Tiling Window  Tiling Window
             (Chrome)      (VS Code)
```

Windows can be either tiling (nested within split containers) or non-tiling (floating, minimized, maximized, or fullscreen). Non-tiling windows are always direct children of a workspace. Split containers can only have windows as children, and must have at least one child window.


================================================
FILE: Cargo.toml
================================================
[workspace]
resolver = "2"
members = ["packages/*"]
default-members = ["packages/wm", "packages/wm-cli"]

[workspace.dependencies]
anyhow = { version = "1", features = ["backtrace"] }
clap = { version = "4", features = ["derive"] }
futures-util = "0.3"
home = "0.5"
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1", features = ["raw_value"] }
tauri-winres = "0.1"
thiserror = "2"
regex = "1"
tokio = { version = "1", features = ["full"] }
tokio-tungstenite = "0.26"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
uuid = { version = "1", features = ["v4", "serde"] }
wm-macros = { path = "packages/wm-macros" }

[workspace.lints]
clippy.all = { level = "warn", priority = -1 }
clippy.pedantic = { level = "warn", priority = -1 }
clippy.missing_errors_doc = "allow"


================================================
FILE: LICENSE.md
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.


================================================
FILE: README.md
================================================
<div align="center">

> V3 is finally out - check out the changelog [here](https://github.com/glzr-io/GlazeWM/releases) 🔥

  <br>
  <img src="./resources/assets/logo.svg" width="230" alt="GlazeWM logo" />
  <br>

# GlazeWM

**A tiling window manager for Windows inspired by i3wm.**

[![Discord invite][discord-badge]][discord-link]
[![Downloads][downloads-badge]][downloads-link]
[![Good first issues][issues-badge]][issues-link]

GlazeWM lets you easily organize windows and adjust their layout on the fly by using keyboard-driven commands.

[Installation](#installation) •
[Default keybindings](#default-keybindings) •
[Config documentation](#config-documentation) •
[FAQ](#faq) •
[Contributing ↗](https://github.com/glzr-io/glazewm/blob/main/CONTRIBUTING.md)

![Demo video][demo-video]

</div>

### 🌟 Key features

- Simple YAML configuration
- Multi-monitor support
- Customizable rules for specific windows
- Easy one-click installation
- Integration with [Zebar](https://github.com/glzr-io/zebar) as a status bar

## Installation

**The latest version of GlazeWM is downloadable via [releases](https://github.com/glzr-io/GlazeWM/releases).** Zebar can optionally be installed as well via a checkbox during installation.

GlazeWM is also available through several package managers:

**Winget**

```sh
winget install GlazeWM
```

**Chocolatey**

```sh
choco install glazewm
```

**Scoop**

```sh
scoop bucket add extras
scoop install extras/glazewm
```

## Contributing

Help fix something that annoys you, or add a feature you've been wanting for a long time! Contributions are very welcome.

Local development and guidelines are available in the [contributing guide](https://github.com/glzr-io/glazewm/blob/main/CONTRIBUTING.md).

## Default keybindings

On the first launch of GlazeWM, a default configuration can optionally be generated.

Below is a cheat sheet of all available commands and their default keybindings.

![Infographic](/resources/assets/cheatsheet.png)

## Config documentation

The [default config](https://github.com/glzr-io/glazewm/blob/main/resources/assets/sample-config.yaml) file is generated at `%userprofile%\.glzr\glazewm\config.yaml`.

To use a different config file location, you can launch the GlazeWM executable with the CLI argument `--config="..."`, like so:

```sh
./glazewm.exe start --config="C:\<PATH_TO_CONFIG>\config.yaml"
```

Or pass a value for the `GLAZEWM_CONFIG_PATH` environment variable:

```sh
setx GLAZEWM_CONFIG_PATH "C:\<PATH_TO_CONFIG>\config.yaml"
```

With the benefit of using a custom path being that you can choose a different name for the config file, such as `glazewm.yaml`.

### Config: General

```yaml
general:
  # Commands to run when the WM has started (e.g. to run a script or launch
  # another application).
  startup_commands: []

  # Commands to run just before the WM is shutdown.
  shutdown_commands: []

  # Commands to run after the WM config has reloaded.
  config_reload_commands: []

  # Whether to automatically focus windows underneath the cursor.
  focus_follows_cursor: false

  # Whether to switch back and forth between the previously focused
  # workspace when focusing the current workspace.
  toggle_workspace_on_refocus: false

  cursor_jump:
    # Whether to automatically move the cursor on the specified trigger.
    enabled: true

    # Trigger for cursor jump:
    # - 'monitor_focus': Jump when focus changes between monitors.
    # - 'window_focus': Jump when focus changes between windows.
    trigger: "monitor_focus"
```

### Config: Keybindings

The available keyboard shortcuts can be customized via the `keybindings` option. A keybinding consists of one or more key combinations and one or more commands to run when pressed.

It's recommended to use the alt key for keybindings. The Windows key is unfortunately a pain to remap, since the OS reserves certain keybindings (e.g. `lwin+l`).

```yaml
keybindings:
  # Command(s) to run.
  - commands: ["focus --workspace 1"]

    # Key combination(s) to trigger the keybinding.
    bindings: ["alt+1"]

  # Multiple commands can be run in a sequence (e.g. to move a window to a
  # workspace + focus workspace).
  - commands: ["move --workspace 1", "focus --workspace 1"]
    bindings: ["alt+shift+1"]
```

**Full list of keys that can be used for keybindings:**

<details>
<summary>Keys list</summary>

| Key                   | Description                                                               |
| --------------------- | ------------------------------------------------------------------------- |
| `a` - `z`             | Alphabetical letter keys                                                  |
| `0` - `9`             | Number keys                                                               |
| `numpad0` - `numpad9` | Numerical keypad keys                                                     |
| `f1` - `f24`          | Function keys                                                             |
| `shift`               | Either left or right SHIFT key                                            |
| `lshift`              | The left SHIFT key                                                        |
| `rshift`              | The right SHIFT key                                                       |
| `control`             | Either left or right CTRL key                                             |
| `lctrl`               | The left CTRL key                                                         |
| `rctrl`               | The right CTRL key                                                        |
| `alt`                 | Either left or right ALT key                                              |
| `lalt`                | The left ALT key                                                          |
| `ralt`                | The right ALT key                                                         |
| `lwin`                | The left ⊞ Windows logo key                                               |
| `rwin`                | The right ⊞ Windows logo key                                              |
| `space`               | The spacebar key                                                          |
| `escape`              | The ESCAPE key                                                            |
| `back`                | The BACKSPACE key                                                         |
| `tab`                 | The TAB key                                                               |
| `enter`               | The ENTER key                                                             |
| `left`                | The ← arrow key                                                           |
| `right`               | The → arrow key                                                           |
| `up`                  | The ↑ arrow key                                                           |
| `down`                | The ↓ arrow key                                                           |
| `num_lock`            | The NUM LOCK key                                                          |
| `scroll_lock`         | The SCROLL LOCK key                                                       |
| `caps_lock`           | The CAPS LOCK key                                                         |
| `page_up`             | The PAGE UP key                                                           |
| `page_down`           | The PAGE DOWN key                                                         |
| `insert`              | The INSERT key                                                            |
| `delete`              | The DELETE key                                                            |
| `end`                 | The END key                                                               |
| `home`                | The HOME key                                                              |
| `print_screen`        | The PRINT SCREEN key                                                      |
| `multiply`            | The `*` key (only on numpad)                                              |
| `add`                 | The `+` key (only on numpad)                                              |
| `subtract`            | The `-` key (only on numpad)                                              |
| `decimal`             | The DEL key (only on numpad)                                              |
| `divide`              | The `/` key (only on numpad)                                              |
| `volume_up`           | The volume up key                                                         |
| `volume_down`         | The volume down key                                                       |
| `volume_mute`         | The volume mute key                                                       |
| `media_next_track`    | The media next track key                                                  |
| `media_prev_track`    | The media prev track key                                                  |
| `media_stop`          | The media stop key                                                        |
| `media_play_pause`    | The media play/pause key                                                  |
| `oem_semicolon`       | The `;`/`:` key on a US standard keyboard (varies by keyboard)            |
| `oem_question`        | The `/`/`?` key on a US standard keyboard (varies by keyboard)            |
| `oem_tilde`           | The `` ` ``/`~` key on a US standard keyboard (varies by keyboard)        |
| `oem_open_brackets`   | The `[`/`{` key on a US standard keyboard (varies by keyboard)            |
| `oem_pipe`            | The `\`/`\|` key on a US standard keyboard (varies by keyboard)           |
| `oem_close_brackets`  | The `]`/`}` key on a US standard keyboard (varies by keyboard)            |
| `oem_quotes`          | The `'`/`"` key on a US standard keyboard (varies by keyboard)            |
| `oem_8`               | The `` ` ``/`¬` key on a UK keyboard (varies by keyboard)                 |
| `oem_102`             | The `\`/`\|` key next to left Shift on ISO keyboards (varies by keyboard) |
| `oem_plus`            | The `=`/`+` key on a US standard keyboard (varies by keyboard)            |
| `oem_comma`           | The `,`/`<` key on a US standard keyboard (varies by keyboard)            |
| `oem_minus`           | The `-`/`_` key on a US standard keyboard (varies by keyboard)            |
| `oem_period`          | The `.`/`>` key on a US standard keyboard (varies by keyboard)            |
| `muhenkan`            | The 無変換 (non-convert) key for Japanese keyboard layouts                |
| `henkan`              | The 変換 (convert) key for Japanese keyboard layouts                      |

</details>

If a key is not in the list above, it is likely still supported if you use its character in a keybinding (e.g. `alt+å` for the Norwegian Å character).

> German and US international keyboards treat the right-side alt key differently. For these keyboard layouts, use `ralt+ctrl` instead of `ralt` to bind the right-side alt key.

### Config: Gaps

The gaps between windows can be changed via the `gaps` property in the config file. Inner and outer gaps are set separately.

```yaml
gaps:
  # Gap between adjacent windows.
  inner_gap: "20px"

  # Gap between windows and the screen edge.
  outer_gap:
    top: "20px"
    right: "20px"
    bottom: "20px"
    left: "20px"
```

### Config: Workspaces

Workspaces need to be predefined via the `workspaces` property in the config file. A workspace is automatically assigned to each monitor on startup.

```yaml
workspaces:
  # This is the unique ID for the workspace. It's used in keybinding
  # commands, and is also the label shown in 3rd-party apps (e.g. Zebar) if
  # `display_name` is not provided.
  - name: "1"

    # Optional override for the workspace label used in 3rd-party apps.
    # Does not need to be unique.
    display_name: "Work"

    # Optionally force the workspace on a specific monitor if it exists.
    # 0 is your leftmost screen, 1 is the next one to the right, and so on.
    bind_to_monitor: 0

    # Optionally prevent workspace from being deactivated when empty.
    keep_alive: false
```

### Config: Window rules

Commands can be run when a window is first launched. This is useful for adding window-specific behaviors like always starting a window as fullscreen or assigning to a specific workspace.

Windows can be targeted by their process, class, and title. Multiple matching criteria can be used together to target a window more precisely.

```yaml
window_rules:
  - commands: ["move --workspace 1"]
    match:
      # Move browsers to workspace 1.
      - window_process: { regex: "msedge|brave|chrome" }

  - commands: ["ignore"]
    match:
      # Ignores any Zebar windows.
      - window_process: { equals: "zebar" }

      # Ignores picture-in-picture windows for browsers.
      # Note that *both* the title and class must match for the rule to run.
      - window_title: { regex: "[Pp]icture.in.[Pp]icture" }
        window_class: { regex: "Chrome_WidgetWin_1|MozillaDialogClass" }
```

### Config: Window effects

Visual effects can be applied to windows via the `window_effects` option. Currently, colored borders are the only effect available with more to come in the future.

> Note: Window effects are exclusive to Windows 11.

```yaml
window_effects:
  # Visual effects to apply to the focused window.
  focused_window:
    # Highlight the window with a colored border.
    border:
      enabled: true
      color: "#0000ff"

  # Visual effects to apply to non-focused windows.
  other_windows:
    border:
      enabled: false
      color: "#d3d3d3"
```

### Config: Window behavior

The `window_behavior` config option exists to customize the states that a window can be in (`tiling`, `floating`, `minimized`, and `fullscreen`).

```yaml
window_behavior:
  # New windows are created in this state whenever possible.
  # Allowed values: 'tiling', 'floating'.
  initial_state: "tiling"

  # Sets the default options for when a new window is created. This also
  # changes the defaults for when the state change commands, like
  # `set-floating`, are used without any flags.
  state_defaults:
    floating:
      # Whether to center floating windows by default.
      centered: true

      # Whether to show floating windows as always on top.
      shown_on_top: false

    fullscreen:
      # Maximize the window if possible. If the window doesn't have a
      # maximize button, then it'll be made fullscreen normally instead.
      maximized: false
```

### Config: Binding modes

Binding modes are used to modify keybindings while GlazeWM is running.

A binding mode can be enabled with `wm-enable-binding-mode --name <NAME>` and disabled with `wm-disable-binding-mode --name <NAME>`.

```yaml
binding_modes:
  # When enabled, the focused window can be resized via arrow keys or HJKL.
  - name: "resize"
    keybindings:
      - commands: ["resize --width -2%"]
        bindings: ["h", "left"]
      - commands: ["resize --width +2%"]
        bindings: ["l", "right"]
      - commands: ["resize --height +2%"]
        bindings: ["k", "up"]
      - commands: ["resize --height -2%"]
        bindings: ["j", "down"]
      # Press enter/escape to return to default keybindings.
      - commands: ["wm-disable-binding-mode --name resize"]
        bindings: ["escape", "enter"]
```

## FAQ

**Q: How do I run GlazeWM on startup?**

Right-click the GlazeWM icon in the system tray and select "Run on system startup".

**Q: How can I create `<insert layout>`?**

You can create custom layouts by changing the tiling direction with `alt+v`. This changes where the next window is placed _in relation to the current window_. If the current window's direction is horizontal, the new window will be placed to the right of it. If it is vertical, it will be placed below it. This also applies when moving windows; the tiling direction of the stationary window will affect where the moved window will be placed.

Community-made scripts like [Dutch-Raptor/GAT-GWM](https://github.com/Dutch-Raptor/GAT-GWM) and [burgr033/GlazeWM-autotiling-python](https://github.com/burgr033/GlazeWM-autotiling-python) can be used to automatically change the tiling direction. Native support for automatic layouts isn't _currently_ supported.

**Q: How do I create a rule for `<insert application>`?**

To match a specific application, you need a command to execute and either the window's process name, title, or class name. For example, if you use Flow-Launcher and want to make the settings window float, you can do the following:

```yaml
window_rules:
  - commands: ["set-floating"]
    match:
      - window_process: { equals: "Flow.Launcher" }
        window_title: { equals: "Settings" }
```

Programs like Winlister or AutoHotkey's Window Spy can be useful for getting info about a window.

**Q: How can I ignore GlazeWM's keybindings when `<insert application>` is focused?**

This isn't currently supported, however, the keybinding `alt+shift+p` in the default config is used to disable all other keybindings until `alt+shift+p` is pressed again.

[discord-badge]: https://img.shields.io/discord/1041662798196908052.svg?logo=discord&colorB=7289DA
[discord-link]: https://discord.gg/ud6z3qjRvM
[downloads-badge]: https://img.shields.io/github/downloads/glzr-io/glazewm/total?logo=github&logoColor=white
[downloads-link]: https://github.com/glzr-io/glazewm/releases
[issues-badge]: https://img.shields.io/badge/good_first_issues-7057ff
[issues-link]: https://github.com/orgs/glzr-io/projects/4/views/1?sliceBy%5Bvalue%5D=good+first+issue
[demo-video]: resources/assets/demo.webp


================================================
FILE: README_zh.md
================================================
<div align="center">

> V3 终于发布了 - 查看更新日志 [这里](https://github.com/glzr-io/GlazeWM/releases) 🔥

  <br>
  <img src="./resources/assets/logo.svg" width="230" alt="GlazeWM logo" />
  <br>

# GlazeWM

**一个受 i3wm 启发的 Windows 平铺窗口管理器。**

[![Discord invite][discord-badge]][discord-link]
[![Downloads][downloads-badge]][downloads-link]
[![Good first issues][issues-badge]][issues-link]

GlazeWM 让您可以通过键盘驱动的命令轻松组织窗口并即时调整其布局。

[安装](#安装) •
[默认快捷键](#默认快捷键) •
[配置文档](#配置文档) •
[常见问题](#常见问题) •
[贡献 ↗](https://github.com/glzr-io/glazewm/blob/main/CONTRIBUTING.md)

![Demo video][demo-video]

</div>

### 🌟 主要特性

- 简单的 YAML 配置
- 多显示器支持
- 针对特定窗口的可自定义规则
- 简单的一键安装
- 与 [Zebar](https://github.com/glzr-io/zebar) 状态栏集成

## 安装

**GlazeWM 的最新版本可通过 [releases](https://github.com/glzr-io/GlazeWM/releases) 下载。** 在安装过程中可以通过复选框选择性安装 Zebar。

GlazeWM 也可以通过多个包管理器获得:

**Winget**

```sh
winget install GlazeWM
```

**Chocolatey**

```sh
choco install glazewm
```

**Scoop**

```sh
scoop bucket add extras
scoop install extras/glazewm
```

## 贡献

帮助修复困扰您的问题,或添加您一直想要的功能!我们非常欢迎贡献。

本地开发和指南可在 [贡献指南](https://github.com/glzr-io/glazewm/blob/main/CONTRIBUTING.md) 中找到。

## 默认快捷键

在 GlazeWM 首次启动时,可以选择性地生成默认配置。

以下是所有可用命令及其默认快捷键的速查表。

![Infographic](/resources/assets/cheatsheet_cn_ZH.png)

## 配置文档

[默认配置](https://github.com/glzr-io/glazewm/blob/main/resources/assets/sample-config.yaml) 文件生成在 `%userprofile%\.glzr\glazewm\config.yaml`。

要使用不同的配置文件位置,您可以使用 CLI 参数 `--config="..."` 启动 GlazeWM 可执行文件,如下所示:

```sh
./glazewm.exe start --config="C:\<配置文件路径>\config.yaml"
```

或者为 `GLAZEWM_CONFIG_PATH` 环境变量传递一个值:

```sh
setx GLAZEWM_CONFIG_PATH "C:\<配置文件路径>\config.yaml"
```

使用自定义路径的好处是您可以为配置文件选择不同的名称,例如 `glazewm.yaml`。

### 配置:常规

```yaml
general:
  # WM 启动时运行的命令(例如运行脚本或启动另一个应用程序)。
  startup_commands: []

  # WM 关闭前运行的命令。
  shutdown_commands: []

  # WM 配置重新加载后运行的命令。
  config_reload_commands: []

  # 是否自动聚焦光标下方的窗口。
  focus_follows_cursor: false

  # 当聚焦当前工作区时,是否在先前聚焦的工作区之间来回切换。
  toggle_workspace_on_refocus: false

  cursor_jump:
    # 是否在指定触发器上自动移动光标。
    enabled: true

    # 光标跳转的触发器:
    # - 'monitor_focus': 当焦点在显示器之间切换时跳转。
    # - 'window_focus': 当焦点在窗口之间切换时跳转。
    trigger: "monitor_focus"
```

### 配置:快捷键

可用的键盘快捷键可以通过 `keybindings` 选项自定义。快捷键由一个或多个按键组合和按下时运行的一个或多个命令组成。

建议使用 alt 键作为快捷键。不幸的是,Windows 键很难重新映射,因为操作系统保留了某些快捷键(例如 `lwin+l`)。

```yaml
keybindings:
  # 要运行的命令。
  - commands: ["focus --workspace 1"]

    # 触发快捷键的按键组合。
    bindings: ["alt+1"]

  # 可以按顺序运行多个命令(例如将窗口移动到工作区 + 聚焦工作区)。
  - commands: ["move --workspace 1", "focus --workspace 1"]
    bindings: ["alt+shift+1"]
```

**可用于快捷键的完整按键列表:**

<details>
<summary>按键列表</summary>

| 按键                  | 描述                                                           |
| --------------------- | -------------------------------------------------------------- |
| `a` - `z`             | 字母键                                                         |
| `0` - `9`             | 数字键                                                         |
| `numpad0` - `numpad9` | 数字小键盘键                                                   |
| `f1` - `f24`          | 功能键                                                         |
| `shift`               | 左或右 SHIFT 键                                                |
| `lshift`              | 左 SHIFT 键                                                    |
| `rshift`              | 右 SHIFT 键                                                    |
| `control`             | 左或右 CTRL 键                                                 |
| `lctrl`               | 左 CTRL 键                                                     |
| `rctrl`               | 右 CTRL 键                                                     |
| `alt`                 | 左或右 ALT 键                                                  |
| `lalt`                | 左 ALT 键                                                      |
| `ralt`                | 右 ALT 键                                                      |
| `lwin`                | 左 ⊞ Windows 徽标键                                            |
| `rwin`                | 右 ⊞ Windows 徽标键                                            |
| `space`               | 空格键                                                         |
| `escape`              | ESCAPE 键                                                      |
| `back`                | BACKSPACE 键                                                   |
| `tab`                 | TAB 键                                                         |
| `enter`               | ENTER 键                                                       |
| `left`                | ← 方向键                                                       |
| `right`               | → 方向键                                                       |
| `up`                  | ↑ 方向键                                                       |
| `down`                | ↓ 方向键                                                       |
| `num_lock`            | NUM LOCK 键                                                    |
| `scroll_lock`         | SCROLL LOCK 键                                                 |
| `caps_lock`           | CAPS LOCK 键                                                   |
| `page_up`             | PAGE UP 键                                                     |
| `page_down`           | PAGE DOWN 键                                                   |
| `insert`              | INSERT 键                                                      |
| `delete`              | DELETE 键                                                      |
| `end`                 | END 键                                                         |
| `home`                | HOME 键                                                        |
| `print_screen`        | PRINT SCREEN 键                                                |
| `multiply`            | `*` 键(仅限数字小键盘)                                       |
| `add`                 | `+` 键(仅限数字小键盘)                                       |
| `subtract`            | `-` 键(仅限数字小键盘)                                       |
| `decimal`             | DEL 键(仅限数字小键盘)                                       |
| `divide`              | `/` 键(仅限数字小键盘)                                       |
| `volume_up`           | 音量增加键                                                     |
| `volume_down`         | 音量减少键                                                     |
| `volume_mute`         | 静音键                                                         |
| `media_next_track`    | 媒体下一曲键                                                   |
| `media_prev_track`    | 媒体上一曲键                                                   |
| `media_stop`          | 媒体停止键                                                     |
| `media_play_pause`    | 媒体播放/暂停键                                                |
| `oem_semicolon`       | 美式标准键盘上的 `;`/`:` 键(因键盘而异)                      |
| `oem_question`        | 美式标准键盘上的 `/`/`?` 键(因键盘而异)                      |
| `oem_tilde`           | 美式标准键盘上的 `` ` ``/`~` 键(因键盘而异)                  |
| `oem_open_brackets`   | 美式标准键盘上的 `[`/`{` 键(因键盘而异)                      |
| `oem_pipe`            | 美式标准键盘上的 `\`/`\|` 键(因键盘而异)                     |
| `oem_close_brackets`  | 美式标准键盘上的 `]`/`}` 键(因键盘而异)                      |
| `oem_quotes`          | 美式标准键盘上的 `'`/`"` 键(因键盘而异)                      |
| `oem_plus`            | 美式标准键盘上的 `=`/`+` 键(因键盘而异)                      |
| `oem_comma`           | 美式标准键盘上的 `,`/`<` 键(因键盘而异)                      |
| `oem_minus`           | 美式标准键盘上的 `-`/`_` 键(因键盘而异)                      |
| `oem_period`          | 美式标准键盘上的 `.`/`>` 键(因键盘而异)                      |

</details>

如果某个按键不在上述列表中,如果您在快捷键中使用其字符,它很可能仍然受支持(例如挪威语 Å 字符的 `alt+å`)。

> 德语和美式国际键盘对右侧 alt 键的处理不同。对于这些键盘布局,请使用 `ralt+ctrl` 而不是 `ralt` 来绑定右侧 alt 键。

### 配置:间隙

窗口之间的间隙可以通过配置文件中的 `gaps` 属性更改。内部和外部间隙分别设置。

```yaml
gaps:
  # 相邻窗口之间的间隙。
  inner_gap: "20px"

  # 窗口与屏幕边缘之间的间隙。
  outer_gap:
    top: "20px"
    right: "20px"
    bottom: "20px"
    left: "20px"
```

### 配置:工作区

工作区需要通过配置文件中的 `workspaces` 属性预定义。启动时,每个显示器会自动分配一个工作区。

```yaml
workspaces:
  # 这是工作区的唯一 ID。它用于快捷键命令,如果未提供 `display_name`,
  # 它也是第三方应用程序(例如 Zebar)中显示的标签。
  - name: "1"

    # 第三方应用程序中使用的工作区标签的可选覆盖。
    # 不需要是唯一的。
    display_name: "工作"

    # 如果存在,可选择强制工作区在特定显示器上。
    # 0 是您最左边的屏幕,1 是右边的下一个,依此类推。
    bind_to_monitor: 0

    # 可选择防止工作区在空时被停用。
    keep_alive: false
```

### 配置:窗口规则

可以在窗口首次启动时运行命令。这对于添加特定于窗口的行为很有用,比如始终以全屏模式启动窗口或分配到特定工作区。

窗口可以通过其进程、类和标题进行定位。可以一起使用多个匹配条件来更精确地定位窗口。

```yaml
window_rules:
  - commands: ["move --workspace 1"]
    match:
      # 将浏览器移动到工作区 1。
      - window_process: { regex: "msedge|brave|chrome" }

  - commands: ["ignore"]
    match:
      # 忽略任何 Zebar 窗口。
      - window_process: { equals: "zebar" }

      # 忽略浏览器的画中画窗口。
      # 注意标题和类都必须匹配才能运行规则。
      - window_title: { regex: "[Pp]icture.in.[Pp]icture" }
        window_class: { regex: "Chrome_WidgetWin_1|MozillaDialogClass" }
```

### 配置:窗口效果

可以通过 `window_effects` 选项对窗口应用视觉效果。目前,彩色边框是唯一可用的效果,未来会有更多效果。

> 注意:窗口效果仅适用于 Windows 11。

```yaml
window_effects:
  # 应用于聚焦窗口的视觉效果。
  focused_window:
    # 用彩色边框突出显示窗口。
    border:
      enabled: true
      color: "#0000ff"

  # 应用于非聚焦窗口的视觉效果。
  other_windows:
    border:
      enabled: false
      color: "#d3d3d3"
```

### 配置:窗口行为

`window_behavior` 配置选项用于自定义窗口可以处于的状态(`tiling`、`floating`、`minimized` 和 `fullscreen`)。

```yaml
window_behavior:
  # 新窗口在可能的情况下以此状态创建。
  # 允许的值:'tiling'、'floating'。
  initial_state: "tiling"

  # 设置创建新窗口时的默认选项。这也会更改状态更改命令
  # (如 `set-floating`)在不使用任何标志时的默认值。
  state_defaults:
    floating:
      # 是否默认居中浮动窗口。
      centered: true

      # 是否将浮动窗口显示为始终在顶部。
      shown_on_top: false

    fullscreen:
      # 如果可能,最大化窗口。如果窗口没有最大化按钮,
      # 则会正常全屏显示。
      maximized: false
```

### 配置:绑定模式

绑定模式用于在 GlazeWM 运行时修改快捷键。

可以使用 `wm-enable-binding-mode --name <名称>` 启用绑定模式,使用 `wm-disable-binding-mode --name <名称>` 禁用。

```yaml
binding_modes:
  # 启用时,可以通过方向键或 HJKL 调整聚焦窗口的大小。
  - name: "resize"
    keybindings:
      - commands: ["resize --width -2%"]
        bindings: ["h", "left"]
      - commands: ["resize --width +2%"]
        bindings: ["l", "right"]
      - commands: ["resize --height +2%"]
        bindings: ["k", "up"]
      - commands: ["resize --height -2%"]
        bindings: ["j", "down"]
      # 按 enter/escape 返回默认快捷键。
      - commands: ["wm-disable-binding-mode --name resize"]
        bindings: ["escape", "enter"]
```

## 常见问题

**问:如何在启动时运行 GlazeWM?**

通过右键单击 GlazeWM 可执行文件 -> `创建快捷方式` 为可执行文件创建快捷方式。将快捷方式放在启动文件夹中,您可以通过在文件资源管理器的顶部栏中输入 `shell:startup` 来访问该文件夹。

**问:如何创建 `<插入布局>`?**

您可以通过使用 `alt+v` 更改平铺方向来创建自定义布局。这会改变下一个窗口相对于当前窗口的放置位置。如果当前窗口的方向是水平的,新窗口将放置在其右侧。如果是垂直的,将放置在其下方。这也适用于移动窗口;固定窗口的平铺方向将影响移动窗口的放置位置。

社区制作的脚本如 [Dutch-Raptor/GAT-GWM](https://github.com/Dutch-Raptor/GAT-GWM) 和 [burgr033/GlazeWM-autotiling-python](https://github.com/burgr033/GlazeWM-autotiling-python) 可用于自动更改平铺方向。目前不支持自动布局的原生支持。

**问:如何为 `<插入应用程序>` 创建规则?**

要匹配特定应用程序,您需要一个要执行的命令以及窗口的进程名称、标题或类名称。例如,如果您使用 Flow-Launcher 并希望设置窗口浮动,您可以执行以下操作:

```yaml
window_rules:
  - commands: ["set-floating"]
    match:
      - window_process: { equals: "Flow.Launcher" }
        window_title: { equals: "Settings" }
```

像 Winlister 或 AutoHotkey 的 Window Spy 这样的程序对于获取窗口信息很有用。

**问:当 `<插入应用程序>` 聚焦时,如何忽略 GlazeWM 的快捷键?**

目前不支持此功能,但是,默认配置中的快捷键 `alt+shift+p` 用于禁用所有其他快捷键,直到再次按下 `alt+shift+p`。

[discord-badge]: https://img.shields.io/discord/1041662798196908052.svg?logo=discord&colorB=7289DA
[discord-link]: https://discord.gg/ud6z3qjRvM
[downloads-badge]: https://img.shields.io/github/downloads/glzr-io/glazewm/total?logo=github&logoColor=white
[downloads-link]: https://github.com/glzr-io/glazewm/releases
[issues-badge]: https://img.shields.io/badge/good_first_issues-7057ff
[issues-link]: https://github.com/orgs/glzr-io/projects/4/views/1?sliceBy%5Bvalue%5D=good+first+issue
[demo-video]: resources/assets/demo.webp


================================================
FILE: clippy.toml
================================================
# TODO: Would ideally move this to `Cargo.toml`, but it's not supported yet.
# Ref: https://github.com/rust-lang/cargo/issues/12917#issuecomment-1795069197
doc-valid-idents = ["AppKit", "DisplayPort", ".."]


================================================
FILE: packages/wm/Cargo.toml
================================================
[package]
name = "wm"
version = "0.0.0"
description = "GlazeWM is a tiling window manager for Windows inspired by i3 and Polybar."
repository = "https://github.com/glzr-io/glazewm"
license = "GPL-3"
edition = "2021"
default-run = "glazewm"

[[bin]]
name = "glazewm"
path = "src/main.rs"

[features]
ui_access = []

[build-dependencies]
tauri-winres = { workspace = true }

[dependencies]
anyhow = { workspace = true }
auto-launch = "0.5"
ambassador = "0.4"
clap = { workspace = true }
enum-as-inner = "0.6"
futures-util = { workspace = true }
home = { workspace = true }
image = "0.25"
serde = { workspace = true }
serde_json = { workspace = true }
serde_yaml = "0.9"
shell-util = "0.0"
tokio = { workspace = true }
tokio-tungstenite = { workspace = true }
tracing = { workspace = true }
tracing-appender = "0.2"
tracing-subscriber = { workspace = true }
tray-icon = "0.21"
uuid = { workspace = true }
wm-cli = { path = "../wm-cli" }
wm-common = { path = "../wm-common" }
wm-ipc-client = { path = "../wm-ipc-client" }
wm-macros = { workspace = true }
wm-platform = { path = "../wm-platform" }


================================================
FILE: packages/wm/build.rs
================================================
use tauri_winres::VersionInfo;

fn main() {
  println!("cargo:rerun-if-env-changed=VERSION_NUMBER");
  let mut res = tauri_winres::WindowsResource::new();

  // When the `ui_access` feature is enabled, the `uiAccess` attribute is
  // set to `true`. UIAccess is disabled by default because it requires the
  // application to be signed and installed in a secure location.
  let ui_access = {
    #[cfg(feature = "ui_access")]
    {
      "true"
    }
    #[cfg(not(feature = "ui_access"))]
    {
      "false"
    }
  };

  // Conditionally enable UIAccess, which grants privilege to set the
  // foreground window and to set the position of elevated windows.
  //
  // Ref: https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/security-policy-settings/user-account-control-only-elevate-uiaccess-applications-that-are-installed-in-secure-locations
  //
  // Additionally, declare support for per-monitor DPI awareness.
  let manifest_str = format!(
    r#"
<assembly
  xmlns="urn:schemas-microsoft-com:asm.v1"
  manifestVersion="1.0"
  xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"
>
  <asmv3:trustInfo>
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="{ui_access}" />
      </requestedPrivileges>
    </security>
  </asmv3:trustInfo>

  <asmv3:application>
    <windowsSettings
      xmlns:ws2005="http://schemas.microsoft.com/SMI/2005/WindowsSettings"
      xmlns:ws2016="http://schemas.microsoft.com/SMI/2016/WindowsSettings"
    >
      <ws2005:dpiAware>true</ws2005:dpiAware>
      <ws2016:dpiAwareness>PerMonitorV2</ws2016:dpiAwareness>
    </windowsSettings>
  </asmv3:application>
</assembly>
"#
  );

  res.set_manifest(&manifest_str);
  res.set_icon("../../resources/assets/icon.ico");

  // Set language to English (US).
  res.set_language(0x0409);

  res.set("OriginalFilename", "glazewm.exe");
  res.set("ProductName", "GlazeWM");
  res.set("FileDescription", "GlazeWM");

  let version_parts = env!("VERSION_NUMBER")
    .split('.')
    .take(3)
    .map(|part| part.parse().unwrap_or(0))
    .collect::<Vec<u16>>();

  let [major, minor, patch] =
    <[u16; 3]>::try_from(version_parts).unwrap_or([0, 0, 0]);

  let version_str = format!("{major}.{minor}.{patch}.0");
  res.set("FileVersion", &version_str);
  res.set("ProductVersion", &version_str);

  let version_u64 = (u64::from(major) << 48)
    | (u64::from(minor) << 32)
    | (u64::from(patch) << 16);

  res.set_version_info(VersionInfo::FILEVERSION, version_u64);
  res.set_version_info(VersionInfo::PRODUCTVERSION, version_u64);

  res.compile().unwrap();
}


================================================
FILE: packages/wm/src/commands/container/attach_container.rs
================================================
use anyhow::bail;

use super::resize_tiling_container;
use crate::{
  models::Container,
  traits::{CommonGetters, TilingSizeGetters},
};

/// Inserts a child container at the specified index.
///
/// The inserted child will be resized to fit the available space.
pub fn attach_container(
  child: &Container,
  target_parent: &Container,
  target_index: Option<usize>,
) -> anyhow::Result<()> {
  if !child.is_detached() {
    bail!("Cannot attach an already attached container.");
  }

  if let Some(target_index) = target_index {
    // Ensure target index is within the bounds of the parent's children.
    let target_index = target_index.clamp(0, target_parent.child_count());

    // Insert the child at the specified index.
    target_parent
      .borrow_children_mut()
      .insert(target_index, child.clone());
  } else {
    target_parent.borrow_children_mut().push_back(child.clone());
  }

  target_parent
    .borrow_child_focus_order_mut()
    .push_back(child.id());

  *child.borrow_parent_mut() = Some(target_parent.clone());

  // Resize the child and its siblings if it is a tiling container.
  if let Ok(child) = child.as_tiling_container() {
    let tiling_siblings = child.tiling_siblings().collect::<Vec<_>>();

    if tiling_siblings.is_empty() {
      child.set_tiling_size(1.0);
      return Ok(());
    }

    // Set initial tiling size to 0, and then size up the container
    // to the target size.
    #[allow(clippy::cast_precision_loss)]
    let target_size = 1.0 / (tiling_siblings.len() + 1) as f32;
    child.set_tiling_size(0.0);
    resize_tiling_container(&child, target_size);
  }

  Ok(())
}


================================================
FILE: packages/wm/src/commands/container/detach_container.rs
================================================
use anyhow::Context;

use super::flatten_split_container;
use crate::{
  models::Container,
  traits::{CommonGetters, TilingSizeGetters, MIN_TILING_SIZE},
};

/// Removes a container from the tree.
///
/// If the container is a tiling container, the siblings will be resized to
/// fill the freed up space. Will flatten empty parent split containers.
#[allow(clippy::needless_pass_by_value)]
pub fn detach_container(child_to_remove: Container) -> anyhow::Result<()> {
  // Flatten the parent split container if it'll be empty after removing
  // the child.
  if let Some(split_parent) = child_to_remove
    .parent()
    .and_then(|parent| parent.as_split().cloned())
  {
    if split_parent.child_count() == 1 {
      flatten_split_container(split_parent)?;
    }
  }

  let parent = child_to_remove.parent().context("No parent.")?;

  parent
    .borrow_children_mut()
    .retain(|c| c.id() != child_to_remove.id());

  parent
    .borrow_child_focus_order_mut()
    .retain(|id| *id != child_to_remove.id());

  *child_to_remove.borrow_parent_mut() = None;

  // Resize the siblings if it is a tiling container.
  if let Ok(child_to_remove) = child_to_remove.as_tiling_container() {
    let tiling_siblings = parent.tiling_children().collect::<Vec<_>>();

    // TODO: Share logic with `resize_tiling_container`.
    let available_size =
      tiling_siblings.iter().fold(0.0, |sum, container| {
        sum + container.tiling_size() - MIN_TILING_SIZE
      });

    // Adjust size of the siblings based on the freed up space.
    for sibling in &tiling_siblings {
      let resize_factor =
        (sibling.tiling_size() - MIN_TILING_SIZE) / available_size;

      let size_delta = resize_factor * child_to_remove.tiling_size();
      sibling.set_tiling_size(sibling.tiling_size() + size_delta);
    }
  }

  Ok(())
}


================================================
FILE: packages/wm/src/commands/container/flatten_child_split_containers.rs
================================================
use super::flatten_split_container;
use crate::{
  models::Container,
  traits::{CommonGetters, TilingDirectionGetters},
};

/// Flattens any redundant split containers at the top-level of the given
/// parent container.
///
/// For example:
/// ```ignore,compile_fail
/// H[1 H[V[2, 3]]] -> H[1, 2, 3]
/// H[1 H[2, 3]] -> H[1, 2, 3]
/// H[V[1]] -> V[1]
/// ```
pub fn flatten_child_split_containers(
  parent: &Container,
) -> anyhow::Result<()> {
  if let Ok(parent) = parent.as_direction_container() {
    // Get children that are either tiling windows or split containers.
    let tiling_children = parent
      .children()
      .into_iter()
      .filter(|child| child.is_tiling_window() || child.is_split())
      .collect::<Vec<_>>();

    if tiling_children.len() == 1 {
      // Handle case where the parent is a split container and has a
      // single split container child.
      if let Some(split_child) = tiling_children[0].as_split() {
        flatten_split_container(split_child.clone())?;
        parent.set_tiling_direction(parent.tiling_direction().inverse());
      }
    } else {
      let split_children = tiling_children
        .into_iter()
        .filter_map(|child| child.as_split().cloned())
        .collect::<Vec<_>>();

      for split_child in split_children.iter().filter(|split_child| {
        split_child.tiling_direction() == parent.tiling_direction()
      }) {
        // Additionally flatten redundant top-level split containers in
        // the child.
        if split_child.child_count() == 1 {
          if let Some(split_grandchild) =
            split_child.children()[0].as_split()
          {
            flatten_split_container(split_grandchild.clone())?;
          }
        }

        flatten_split_container(split_child.clone())?;
      }
    }
  }

  Ok(())
}


================================================
FILE: packages/wm/src/commands/container/flatten_split_container.rs
================================================
use std::collections::VecDeque;

use anyhow::Context;

use crate::{
  models::SplitContainer,
  traits::{CommonGetters, TilingSizeGetters},
};

/// Removes a split container from the tree and moves its children
/// into the parent container.
///
/// The children will be resized to fit the size of the split container.
#[allow(clippy::needless_pass_by_value)]
pub fn flatten_split_container(
  split_container: SplitContainer,
) -> anyhow::Result<()> {
  let parent = split_container.parent().context("No parent.")?;

  let updated_children =
    split_container.children().into_iter().inspect(|child| {
      *child.borrow_parent_mut() = Some(parent.clone());

      // Resize tiling children to fit the size of the split container.
      if let Ok(tiling_child) = child.as_tiling_container() {
        tiling_child.set_tiling_size(
          split_container.tiling_size() * tiling_child.tiling_size(),
        );
      }
    });

  let index = split_container.index();
  let focus_index = split_container.focus_index();

  // Insert child at its original index in the parent.
  for (child_index, child) in updated_children.enumerate() {
    parent
      .borrow_children_mut()
      .insert(index + child_index, child);
  }

  // Insert child at its original focus index in the parent.
  for (child_focus_index, child_id) in split_container
    .borrow_child_focus_order()
    .iter()
    .enumerate()
  {
    parent
      .borrow_child_focus_order_mut()
      .insert(focus_index + child_focus_index, *child_id);
  }

  // Remove the split container from the tree.
  parent
    .borrow_children_mut()
    .retain(|c| c.id() != split_container.id());

  parent
    .borrow_child_focus_order_mut()
    .retain(|id| *id != split_container.id());

  *split_container.borrow_parent_mut() = None;
  *split_container.borrow_children_mut() = VecDeque::new();

  Ok(())
}


================================================
FILE: packages/wm/src/commands/container/focus_container_by_id.rs
================================================
use anyhow::Context;
use uuid::Uuid;

use super::set_focused_descendant;
use crate::wm_state::WmState;

pub fn focus_container_by_id(
  container_id: &Uuid,
  state: &mut WmState,
) -> anyhow::Result<()> {
  let focus_target = state
    .container_by_id(*container_id)
    .context("No container with given id")?;

  // Set focus to the target container.
  set_focused_descendant(&focus_target, None);
  state.pending_sync.queue_focus_change().queue_cursor_jump();

  Ok(())
}


================================================
FILE: packages/wm/src/commands/container/focus_in_direction.rs
================================================
use anyhow::Context;
use wm_common::{TilingDirection, WindowState};
use wm_platform::Direction;

use super::set_focused_descendant;
use crate::{
  models::{Container, TilingContainer},
  traits::{CommonGetters, TilingDirectionGetters, WindowGetters},
  wm_state::WmState,
};

pub fn focus_in_direction(
  origin_container: &Container,
  direction: &Direction,
  state: &mut WmState,
) -> anyhow::Result<()> {
  let focus_target = match origin_container {
    Container::TilingWindow(_) => {
      // If a suitable focus target isn't found in the current workspace,
      // attempt to find a workspace in the given direction.
      tiling_focus_target(origin_container, direction)?.map_or_else(
        || workspace_focus_target(origin_container, direction, state),
        |container| Ok(Some(container)),
      )?
    }
    Container::NonTilingWindow(ref non_tiling_window) => {
      match non_tiling_window.state() {
        WindowState::Floating(_) => {
          floating_focus_target(origin_container, direction)
        }
        WindowState::Fullscreen(_) => {
          workspace_focus_target(origin_container, direction, state)?
        }
        _ => None,
      }
    }
    Container::Workspace(_) => {
      workspace_focus_target(origin_container, direction, state)?
    }
    _ => None,
  };

  // Set focus to the target container.
  if let Some(focus_target) = focus_target {
    set_focused_descendant(&focus_target, None);
    state.pending_sync.queue_focus_change().queue_cursor_jump();
  }

  Ok(())
}

fn floating_focus_target(
  origin_container: &Container,
  direction: &Direction,
) -> Option<Container> {
  let is_floating = |sibling: &Container| {
    sibling.as_non_tiling_window().is_some_and(|window| {
      matches!(window.state(), WindowState::Floating(_))
    })
  };

  let mut floating_siblings =
    origin_container.siblings().filter(is_floating);

  // Wrap if next/previous floating window is not found.
  match direction {
    Direction::Left => origin_container
      .next_siblings()
      .find(is_floating)
      .or_else(|| floating_siblings.last()),
    Direction::Right => origin_container
      .prev_siblings()
      .find(is_floating)
      .or_else(|| floating_siblings.next()),
    // Cannot focus vertically from a floating window.
    _ => None,
  }
}

/// Gets a focus target within the current workspace. Traverse upwards from
/// the origin container to find an adjacent container that can be focused.
fn tiling_focus_target(
  origin_container: &Container,
  direction: &Direction,
) -> anyhow::Result<Option<Container>> {
  let tiling_direction = TilingDirection::from_direction(direction);
  let mut origin_or_ancestor = origin_container.clone();

  // Traverse upwards from the focused container. Stop searching when a
  // workspace is encountered.
  while !origin_or_ancestor.is_workspace() {
    let parent = origin_or_ancestor
      .parent()
      .and_then(|parent| parent.as_direction_container().ok())
      .context("No direction container.")?;

    // Skip if the tiling direction doesn't match.
    if parent.tiling_direction() != tiling_direction {
      origin_or_ancestor = parent.into();
      continue;
    }

    // Get the next/prev tiling sibling depending on the tiling direction.
    let focus_target = match direction {
      Direction::Up | Direction::Left => origin_or_ancestor
        .prev_siblings()
        .find_map(|c| c.as_tiling_container().ok()),
      _ => origin_or_ancestor
        .next_siblings()
        .find_map(|c| c.as_tiling_container().ok()),
    };

    match focus_target {
      Some(target) => {
        // Return once a suitable focus target is found.
        return Ok(match target {
          TilingContainer::TilingWindow(_) => Some(target.into()),
          TilingContainer::Split(split) => split
            .descendant_in_direction(&direction.inverse())
            .map(Into::into),
        });
      }
      None => origin_or_ancestor = parent.into(),
    }
  }

  Ok(None)
}

/// Gets a focus target outside of the current workspace in the given
/// direction.
///
/// This will descend into the workspace in the given direction, and will
/// always return a tiling container. This makes it different from the
/// `focus_workspace` command with `FocusWorkspaceTarget::Direction`.
fn workspace_focus_target(
  origin_container: &Container,
  direction: &Direction,
  state: &WmState,
) -> anyhow::Result<Option<Container>> {
  let monitor = origin_container.monitor().context("No monitor.")?;

  let target_workspace = state
    .monitor_in_direction(&monitor, direction)?
    .and_then(|monitor| monitor.displayed_workspace());

  let focused_fullscreen = target_workspace
    .as_ref()
    .and_then(|workspace| workspace.descendant_focus_order().next())
    .filter(|focused| match focused {
      Container::NonTilingWindow(window) => {
        matches!(window.state(), WindowState::Fullscreen(_))
      }
      _ => false,
    });

  let focus_target = focused_fullscreen
    .or_else(|| {
      target_workspace.as_ref().and_then(|workspace| {
        workspace
          .descendant_in_direction(&direction.inverse())
          .map(Into::into)
      })
    })
    .or(target_workspace.map(Into::into));

  Ok(focus_target)
}


================================================
FILE: packages/wm/src/commands/container/mod.rs
================================================
mod attach_container;
mod detach_container;
mod flatten_child_split_containers;
mod flatten_split_container;
mod focus_container_by_id;
mod focus_in_direction;
mod move_container_within_tree;
mod replace_container;
mod resize_tiling_container;
mod set_focused_descendant;
mod toggle_tiling_direction;
mod wrap_in_split_container;

pub use attach_container::*;
pub use detach_container::*;
pub use flatten_child_split_containers::*;
pub use flatten_split_container::*;
pub use focus_container_by_id::*;
pub use focus_in_direction::*;
pub use move_container_within_tree::*;
pub use replace_container::*;
pub use resize_tiling_container::*;
pub use set_focused_descendant::*;
pub use toggle_tiling_direction::*;
pub use wrap_in_split_container::*;


================================================
FILE: packages/wm/src/commands/container/move_container_within_tree.rs
================================================
use anyhow::Context;
use wm_common::{VecDequeExt, WmEvent};

use super::{
  attach_container, detach_container, flatten_child_split_containers,
  set_focused_descendant,
};
use crate::{models::Container, traits::CommonGetters, wm_state::WmState};

/// Move a container to a new location in the tree. This detaches the
/// container from its current parent and attaches it to the new parent at
/// the specified index.
///
/// If this container is a tiling container, its siblings are resized on
/// detach, and the container is sized to the default tiling size with its
/// new siblings. No changes to the container's tiling size are made if
/// its parent stays the same.
///
/// This will flatten any redundant split containers after moving the
/// container, which can cause the target parent to become detached. For
/// example, in the layout V[1 H[2]] where container 1 is moved down, the
/// parent gets removed resulting in V[1 2].
pub fn move_container_within_tree(
  container_to_move: &Container,
  target_parent: &Container,
  target_index: usize,
  state: &WmState,
) -> anyhow::Result<()> {
  // Create iterator of parent, grandparent, and great-grandparent.
  let ancestors =
    container_to_move.ancestors().take(3).collect::<Vec<_>>();

  // Get lowest common ancestor (LCA) between `container_to_move` and
  // `target_parent`. This could be the `target_parent` itself.
  let lowest_common_ancestor =
    lowest_common_ancestor(container_to_move, target_parent)
      .context("No common ancestor between containers.")?;

  // If the container is already a child of the target parent, then shift
  // it to the target index.
  if container_to_move.parent().context("No parent.")? == *target_parent {
    target_parent
      .borrow_children_mut()
      .shift_to_index(target_index, container_to_move.clone());

    if container_to_move.has_focus(None) {
      state.emit_event(WmEvent::FocusedContainerMoved {
        focused_container: container_to_move.to_dto()?,
      });
    }

    return Ok(());
  }

  // Handle case where target parent is the LCA. For example, when swapping
  // sibling containers or moving a container to a direct ancestor.
  if *target_parent == lowest_common_ancestor {
    return move_to_lowest_common_ancestor(
      container_to_move,
      &lowest_common_ancestor,
      target_index,
      state,
    );
  }

  // Get ancestor of `container_to_move` that is a direct child of the LCA.
  // This could be the `container_to_move` itself.
  let container_to_move_ancestor = container_to_move
    .self_and_ancestors()
    .find(|ancestor| {
      ancestor.parent() == Some(lowest_common_ancestor.clone())
    })
    .context("Failed to get ancestor of container to move.")?;

  // Likewise, get ancestor of `target_parent` that is a direct child of
  // the LCA.
  let target_parent_ancestor = target_parent
    .self_and_ancestors()
    .find(|ancestor| {
      ancestor.parent() == Some(lowest_common_ancestor.clone())
    })
    .context("Failed to get ancestor of target parent.")?;

  // Get whether the container is the focused descendant in its original
  // subtree from the LCA.
  let is_focused_descendant = *container_to_move
    == container_to_move_ancestor
    || container_to_move
      .has_focus(Some(container_to_move_ancestor.clone()));

  // Get whether the ancestor of `container_to_move` appears before
  // `target_parent`'s ancestor in the child focus order of the LCA.
  let original_focus_index = container_to_move_ancestor.focus_index();
  let is_subtree_focused =
    original_focus_index < target_parent_ancestor.focus_index();

  detach_container(container_to_move.clone())?;
  attach_container(
    &container_to_move.clone(),
    &target_parent.clone(),
    Some(target_index),
  )?;

  // Set `container_to_move` as focused descendant within target subtree if
  // its original subtree had focus more recently (even if the container is
  // not the last focused within that subtree).
  if is_subtree_focused {
    set_focused_descendant(
      container_to_move,
      Some(&target_parent_ancestor),
    );
  }

  // If the focused descendant is moved to the targets subtree, then the
  // target's ancestor should be placed before the original ancestor in
  // LCA's child focus order.
  if is_focused_descendant && is_subtree_focused {
    lowest_common_ancestor
      .borrow_child_focus_order_mut()
      .shift_to_index(original_focus_index, target_parent_ancestor.id());
  }

  // After moving the container, flatten any redundant split containers.
  // For example, in the layout V[1 H[2]] where container 1 is moved down
  // to become V[H[1 2]], this will then need to be flattened to V[1 2].
  for ancestor in ancestors.iter().rev() {
    flatten_child_split_containers(ancestor)?;
  }

  if container_to_move.has_focus(None) {
    state.emit_event(WmEvent::FocusedContainerMoved {
      focused_container: container_to_move.to_dto()?,
    });
  }

  Ok(())
}

fn move_to_lowest_common_ancestor(
  container_to_move: &Container,
  lowest_common_ancestor: &Container,
  target_index: usize,
  state: &WmState,
) -> anyhow::Result<()> {
  // Keep reference to focus index of container's ancestor in LCA's child
  // focus order.
  let original_focus_index = container_to_move
    .self_and_ancestors()
    .find(|ancestor| {
      ancestor.parent() == Some(lowest_common_ancestor.clone())
    })
    .map(|ancestor| ancestor.focus_index())
    .context("Failed to get focus index of container's ancestor.")?;

  detach_container(container_to_move.clone())?;

  attach_container(
    &container_to_move.clone(),
    &lowest_common_ancestor.clone(),
    Some(target_index),
  )?;

  lowest_common_ancestor
    .borrow_child_focus_order_mut()
    .shift_to_index(original_focus_index, container_to_move.id());

  if container_to_move.has_focus(None) {
    state.emit_event(WmEvent::FocusedContainerMoved {
      focused_container: container_to_move.to_dto()?,
    });
  }

  Ok(())
}

/// Gets the lowest container in the tree that has both `container_a` and
/// `container_b` as descendants.
pub fn lowest_common_ancestor(
  container_a: &Container,
  container_b: &Container,
) -> Option<Container> {
  let mut ancestor_a = Some(container_a.clone());

  // Traverse upwards from container A.
  while let Some(current_ancestor_a) = ancestor_a {
    let mut ancestor_b = Some(container_b.clone());

    // Traverse upwards from container B.
    while let Some(current_ancestor_b) = ancestor_b {
      if current_ancestor_a == current_ancestor_b {
        return Some(current_ancestor_a);
      }

      ancestor_b = current_ancestor_b.parent();
    }

    ancestor_a = current_ancestor_a.parent();
  }

  None
}


================================================
FILE: packages/wm/src/commands/container/replace_container.rs
================================================
use anyhow::{bail, Context};
use wm_common::VecDequeExt;

use super::{attach_container, detach_container, resize_tiling_container};
use crate::{
  models::Container,
  traits::{CommonGetters, TilingSizeGetters},
};

/// Replaces a container at the specified index.
///
/// The replaced container will be detached from the tree.
pub fn replace_container(
  replacement_container: &Container,
  target_parent: &Container,
  target_index: usize,
) -> anyhow::Result<()> {
  if !replacement_container.is_detached() {
    bail!(
      "Cannot use an already attached container as replacement container."
    );
  }

  let container_to_replace = target_parent
    .children()
    .get(target_index)
    .cloned()
    .with_context(|| format!("No container at index {target_index}."))?;

  let focus_index = container_to_replace.focus_index();
  let tiling_size = container_to_replace
    .as_tiling_container()
    .map(|c| c.tiling_size());

  // TODO: This will cause issues if the detach causes a wrapping split
  // container to flatten. Currently, that scenario shouldn't be possible.
  // We also can't attach first before detaching, because detaching
  // removes child based on ID and both containers might have the same ID.
  detach_container(container_to_replace)?;

  attach_container(
    replacement_container,
    target_parent,
    Some(target_index),
  )?;

  // Shift to the correct focus index.
  target_parent
    .borrow_child_focus_order_mut()
    .shift_to_index(focus_index, replacement_container.id());

  // Match the tiling size of the replaced container if the replacement
  // is also a tiling container.
  if let Ok(tiling_size) = tiling_size {
    if let Ok(replacement_container) =
      replacement_container.as_tiling_container()
    {
      resize_tiling_container(&replacement_container, tiling_size);
    }
  }

  Ok(())
}


================================================
FILE: packages/wm/src/commands/container/resize_tiling_container.rs
================================================
use crate::{
  models::TilingContainer,
  traits::{CommonGetters, TilingSizeGetters, MIN_TILING_SIZE},
};

pub fn resize_tiling_container(
  container_to_resize: &TilingContainer,
  target_size: f32,
) {
  let tiling_siblings =
    container_to_resize.tiling_siblings().collect::<Vec<_>>();

  // Ignore cases where the container is the only child.
  if tiling_siblings.is_empty() {
    container_to_resize.set_tiling_size(1.);
    return;
  }

  // Prevent the container from being smaller than the minimum size, and
  // larger than the space available from sibling containers.
  #[allow(clippy::cast_precision_loss)]
  let clamped_target_size = target_size.clamp(
    MIN_TILING_SIZE,
    1. - (tiling_siblings.len() as f32 * MIN_TILING_SIZE),
  );

  let size_delta = clamped_target_size - container_to_resize.tiling_size();
  container_to_resize.set_tiling_size(clamped_target_size);

  // Get available tiling size amongst siblings.
  let available_size =
    tiling_siblings.iter().fold(0.0, |sum, container| {
      sum + container.tiling_size() - MIN_TILING_SIZE
    });

  // Distribute the available tiling size amongst its siblings.
  for sibling in &tiling_siblings {
    // Get percentage of resize that affects this container. Siblings are
    // resized in proportion to their current size (i.e. larger containers
    // are shrunk more).
    let resize_factor =
      (sibling.tiling_size() - MIN_TILING_SIZE) / available_size;

    let size_delta = resize_factor * size_delta;

    sibling.set_tiling_size(sibling.tiling_size() - size_delta);
  }
}


================================================
FILE: packages/wm/src/commands/container/set_focused_descendant.rs
================================================
use wm_common::VecDequeExt;

use crate::{models::Container, traits::CommonGetters};

/// Set a given container as the focused container up to and including the
/// end ancestor.
pub fn set_focused_descendant(
  focused_descendant: &Container,
  end_ancestor: Option<&Container>,
) {
  let mut target = focused_descendant.clone();

  // Traverse upwards, shifting the container's ancestors to the front in
  // their focus order.
  while let Some(parent) = target.parent() {
    parent
      .borrow_child_focus_order_mut()
      .shift_to_index(0, target.id());

    // Exit if we've reached the end ancestor.
    if end_ancestor
      .as_ref()
      .is_some_and(|end_ancestor| target.id() == end_ancestor.id())
    {
      break;
    }

    target = parent;
  }
}


================================================
FILE: packages/wm/src/commands/container/toggle_tiling_direction.rs
================================================
use anyhow::Context;
use wm_common::{TilingDirection, WmEvent};

use super::{flatten_split_container, wrap_in_split_container};
use crate::{
  models::{Container, DirectionContainer, SplitContainer, TilingWindow},
  traits::{CommonGetters, TilingDirectionGetters},
  user_config::UserConfig,
  wm_state::WmState,
};

pub fn toggle_tiling_direction(
  container: Container,
  state: &mut WmState,
  config: &UserConfig,
) -> anyhow::Result<()> {
  let direction_container = match container {
    Container::TilingWindow(tiling_window) => {
      toggle_window_direction(tiling_window, config)
    }
    Container::Workspace(workspace) => {
      workspace
        .set_tiling_direction(workspace.tiling_direction().inverse());

      Ok(workspace.into())
    }
    // Can only toggle tiling direction from a tiling window or workspace.
    _ => return Ok(()),
  }?;

  state.emit_event(WmEvent::TilingDirectionChanged {
    direction_container: direction_container.to_dto()?,
    new_tiling_direction: direction_container.tiling_direction(),
  });

  Ok(())
}

fn toggle_window_direction(
  tiling_window: TilingWindow,
  config: &UserConfig,
) -> anyhow::Result<DirectionContainer> {
  let parent = tiling_window
    .direction_container()
    .context("No direction container.")?;

  // If the window is an only child, then either change the tiling
  // direction of its parent workspace or flatten its parent split
  // container.
  if tiling_window.tiling_siblings().count() == 0 {
    return match parent {
      DirectionContainer::Workspace(workspace) => {
        workspace
          .set_tiling_direction(workspace.tiling_direction().inverse());

        Ok(workspace.into())
      }
      DirectionContainer::Split(split_container) => {
        flatten_split_container(split_container.clone())?;

        tiling_window
          .direction_container()
          .context("No direction container.")
      }
    };
  }

  // Create a new split container to wrap the window.
  let split_container = SplitContainer::new(
    parent.tiling_direction().inverse(),
    config.value.gaps.clone(),
  );

  wrap_in_split_container(
    &split_container,
    &parent.into(),
    &[tiling_window.into()],
  )?;

  Ok(split_container.into())
}

pub fn set_tiling_direction(
  container: Container,
  state: &mut WmState,
  config: &UserConfig,
  tiling_direction: &TilingDirection,
) -> anyhow::Result<()> {
  let direction_container = container
    .direction_container()
    .context("No direction container.")?;

  if direction_container.tiling_direction() == *tiling_direction {
    Ok(())
  } else {
    toggle_tiling_direction(container, state, config)
  }
}


================================================
FILE: packages/wm/src/commands/container/wrap_in_split_container.rs
================================================
use std::collections::VecDeque;

use anyhow::Context;

use crate::{
  models::{Container, SplitContainer, TilingContainer},
  traits::{CommonGetters, TilingSizeGetters},
};

pub fn wrap_in_split_container(
  split_container: &SplitContainer,
  target_parent: &Container,
  target_children: &[TilingContainer],
) -> anyhow::Result<()> {
  let starting_index = target_children
    .iter()
    .map(CommonGetters::index)
    .min()
    .context("Failed to get starting index.")?;

  target_parent
    .borrow_children_mut()
    .insert(starting_index, split_container.clone().into());

  let starting_focus_index = target_children
    .iter()
    .map(CommonGetters::focus_index)
    .min()
    .context("Failed to get starting focus index.")?;

  target_parent
    .borrow_child_focus_order_mut()
    .insert(starting_focus_index, split_container.id());

  // Get the total tiling size amongst all children.
  let total_tiling_size = target_children
    .iter()
    .map(TilingSizeGetters::tiling_size)
    .sum::<f32>();

  let target_children_ids = target_children
    .iter()
    .map(CommonGetters::id)
    .collect::<Vec<_>>();

  let sorted_focus_ids = target_parent
    .borrow_child_focus_order()
    .iter()
    .filter(|id| target_children_ids.contains(id))
    .copied()
    .collect::<VecDeque<_>>();

  // Set the split container's parent and tiling size.
  *split_container.borrow_parent_mut() = Some(target_parent.clone());
  split_container.set_tiling_size(total_tiling_size);

  // Move the children from their original parent to the split container.
  for target_child in target_children {
    *target_child.borrow_parent_mut() =
      Some(split_container.clone().into());

    split_container
      .borrow_children_mut()
      .push_back(target_child.clone().into());

    target_parent
      .borrow_children_mut()
      .retain(|child| child != &target_child.clone().into());

    target_parent
      .borrow_child_focus_order_mut()
      .retain(|id| id != &target_child.id());

    // Scale the tiling size to the new split container.
    target_child
      .set_tiling_size(target_child.tiling_size() / total_tiling_size);
  }

  // Add original focus order to split container.
  *split_container.borrow_child_focus_order_mut() = sorted_focus_ids;

  Ok(())
}


================================================
FILE: packages/wm/src/commands/general/cycle_focus.rs
================================================
use anyhow::Context;
use wm_common::WindowState;

use crate::{
  commands::container::set_focused_descendant,
  traits::{CommonGetters, WindowGetters},
  user_config::UserConfig,
  wm_state::WmState,
};

/// Cycles focus through windows of different states. In order, this will
/// change from tiling -> floating -> fullscreen -> minimized, then back to
/// tiling.
///
/// Does nothing if a workspace is focused.
#[allow(clippy::fn_params_excessive_bools)]
pub fn cycle_focus(
  omit_floating: bool,
  omit_fullscreen: bool,
  omit_minimized: bool,
  omit_tiling: bool,
  state: &mut WmState,
  config: &UserConfig,
) -> anyhow::Result<()> {
  let focused_container =
    state.focused_container().context("No focused container.")?;

  if let Ok(window) = focused_container.as_window_container() {
    let workspace = window.workspace().context("No workspace.")?;

    let current = window.state();
    let mut next = next_state(&current, config);

    loop {
      // Break if we have cycled back to the current state.
      if current.is_same_state(&next) {
        break;
      }

      // Skip the next state if it is to be omitted.
      if (omit_floating && matches!(next, WindowState::Floating(_)))
        || omit_fullscreen && matches!(next, WindowState::Fullscreen(_))
        || omit_minimized && matches!(next, WindowState::Minimized)
        || omit_tiling && matches!(next, WindowState::Tiling)
      {
        next = next_state(&next, config);
        continue;
      }

      // Get window that matches the next state.
      let window_of_type = workspace
        .descendant_focus_order()
        .filter_map(|descendant| descendant.as_window_container().ok())
        .find(|descendant| {
          matches!(
            (descendant.state(), &next),
            (WindowState::Floating(_), WindowState::Floating(_))
              | (WindowState::Fullscreen(_), WindowState::Fullscreen(_))
              | (WindowState::Minimized, WindowState::Minimized)
              | (WindowState::Tiling, WindowState::Tiling)
          )
        });

      if let Some(window) = window_of_type {
        set_focused_descendant(&window.into(), None);
        state.pending_sync.queue_focus_change().queue_cursor_jump();
        break;
      }

      next = next_state(&next, config);
    }
  }

  Ok(())
}

fn next_state(
  current_state: &WindowState,
  config: &UserConfig,
) -> WindowState {
  match current_state {
    WindowState::Floating(_) => WindowState::Fullscreen(
      config
        .value
        .window_behavior
        .state_defaults
        .fullscreen
        .clone(),
    ),
    WindowState::Fullscreen(_) => WindowState::Minimized,
    WindowState::Minimized => WindowState::Tiling,
    WindowState::Tiling => WindowState::Floating(
      config.value.window_behavior.state_defaults.floating.clone(),
    ),
  }
}


================================================
FILE: packages/wm/src/commands/general/disable_binding_mode.rs
================================================
use wm_common::WmEvent;

use crate::wm_state::WmState;

pub fn disable_binding_mode(name: &str, state: &mut WmState) {
  state.binding_modes = state
    .binding_modes
    .iter()
    .filter(|config| config.name != name)
    .cloned()
    .collect::<Vec<_>>();

  state.emit_event(WmEvent::BindingModesChanged {
    new_binding_modes: state.binding_modes.clone(),
  });
}


================================================
FILE: packages/wm/src/commands/general/enable_binding_mode.rs
================================================
use anyhow::Context;
use wm_common::WmEvent;

use crate::{user_config::UserConfig, wm_state::WmState};

pub fn enable_binding_mode(
  name: &str,
  state: &mut WmState,
  config: &UserConfig,
) -> anyhow::Result<()> {
  let binding_mode = config
    .value
    .binding_modes
    .iter()
    .find(|config| name == config.name)
    .with_context(|| {
      format!("No binding mode found with the name '{name}'.")
    })?;

  state.binding_modes = vec![binding_mode.clone()];

  state.emit_event(WmEvent::BindingModesChanged {
    new_binding_modes: state.binding_modes.clone(),
  });

  Ok(())
}


================================================
FILE: packages/wm/src/commands/general/mod.rs
================================================
mod cycle_focus;
mod disable_binding_mode;
mod enable_binding_mode;
mod platform_sync;
mod reload_config;
mod shell_exec;
mod toggle_pause;

pub use cycle_focus::*;
pub use disable_binding_mode::*;
pub use enable_binding_mode::*;
pub use platform_sync::*;
pub use reload_config::*;
pub use shell_exec::*;
pub use toggle_pause::*;


================================================
FILE: packages/wm/src/commands/general/platform_sync.rs
================================================
use anyhow::Context;
#[cfg(target_os = "windows")]
use wm_common::WindowEffectConfig;
use wm_common::{
  CursorJumpTrigger, DisplayState, HideCorner, HideMethod, UniqueExt,
  WindowState, WmEvent,
};
#[cfg(target_os = "windows")]
use wm_platform::NativeWindowWindowsExt;
#[cfg(target_os = "windows")]
use wm_platform::{CornerStyle, OpacityValue};
use wm_platform::{Rect, WindowZOrder};

use crate::{
  models::{Container, WindowContainer},
  traits::{CommonGetters, PositionGetters, WindowGetters},
  user_config::UserConfig,
  wm_state::WmState,
};

pub fn platform_sync(
  state: &mut WmState,
  config: &UserConfig,
) -> anyhow::Result<()> {
  let focused_container =
    state.focused_container().context("No focused container.")?;

  if state.pending_sync.needs_focus_update() {
    sync_focus(&focused_container, state)?;
  }

  if !state.pending_sync.containers_to_redraw().is_empty()
    || !state.pending_sync.workspaces_to_reorder().is_empty()
  {
    redraw_containers(&focused_container, state, config)?;
  }

  if state.pending_sync.needs_cursor_jump()
    && config.value.general.cursor_jump.enabled
  {
    jump_cursor(focused_container.clone(), state, config)?;
  }

  if state.pending_sync.needs_focused_effect_update()
    || state.pending_sync.needs_all_effects_update()
  {
    // Keep reference to the previous window that had focus effects
    // applied.
    let prev_effects_window = state.prev_effects_window.clone();

    if let Ok(window) = focused_container.as_window_container() {
      apply_window_effects(&window, true, config);
      state.prev_effects_window = Some(window.clone());
    } else {
      state.prev_effects_window = None;
    }

    // Get windows that should have the unfocused border applied to them.
    // For the sake of performance, we only update the border of the
    // previously focused window. If the `reset_window_effects` flag is
    // passed, the unfocused border is applied to all unfocused windows.
    let unfocused_windows =
      if state.pending_sync.needs_all_effects_update() {
        state.windows()
      } else {
        prev_effects_window.into_iter().collect()
      }
      .into_iter()
      .filter(|window| window.id() != focused_container.id());

    for window in unfocused_windows {
      apply_window_effects(&window, false, config);
    }
  }

  state.pending_sync.clear();

  Ok(())
}

fn sync_focus(
  focused_container: &Container,
  state: &mut WmState,
) -> anyhow::Result<()> {
  let native_window = focused_container.as_window_container().ok();

  // Sets focus to the appropriate target:
  // - If the container is a window, focuses that window.
  // - If the container is a workspace, "resets" focus by focusing the
  //   desktop window.
  //
  // In either case, a `PlatformEvent::WindowFocused` event is subsequently
  // triggered.
  let result = if let Some(window) = native_window {
    tracing::info!("Setting focus to window: {window}");
    window.native().focus()
  } else {
    tracing::info!("Setting focus to the desktop window.");
    state.dispatcher.reset_focus()
  };

  if let Err(err) = result {
    tracing::warn!("Failed to set focus: {}", err);
  }

  state.emit_event(WmEvent::FocusChanged {
    focused_container: focused_container.to_dto()?,
  });

  Ok(())
}

/// Finds windows that should be brought to the top of their workspace's
/// z-order.
///
/// Windows are brought to front if they match the focused window's state
/// (floating/tiling) and any of these conditions are met:
///  * Focus has changed to a different window.
///  * Focused window's state has changed (e.g. tiling -> floating).
///  * Focused window has moved to a different workspace.
fn windows_to_bring_to_front(
  focused_container: &Container,
  state: &WmState,
) -> anyhow::Result<Vec<WindowContainer>> {
  let focused_workspace =
    focused_container.workspace().context("No workspace.")?;

  // Add focused workspace if there's been a focus change.
  let workspaces_to_reorder = state
    .pending_sync
    .workspaces_to_reorder()
    .iter()
    .chain(
      state
        .pending_sync
        .needs_focus_update()
        .then_some(&focused_workspace),
    )
    .unique_by(|workspace| workspace.id());

  // Bring forward windows that match the focused state. Only do this for
  // tiling/floating windows.
  let windows_to_bring_to_front = workspaces_to_reorder
    .flat_map(|workspace| {
      let focused_descendant = workspace
        .descendant_focus_order()
        .next()
        .and_then(|container| container.as_window_container().ok());

      match focused_descendant {
        Some(focused_descendant) => workspace
          .descendants()
          .filter_map(|descendant| descendant.as_window_container().ok())
          .filter(|window| {
            let is_floating_or_tiling = matches!(
              window.state(),
              WindowState::Floating(_) | WindowState::Tiling
            );

            is_floating_or_tiling
              && window.state().is_same_state(&focused_descendant.state())
          })
          .collect(),
        None => vec![],
      }
    })
    .collect::<Vec<_>>();

  Ok(windows_to_bring_to_front)
}

#[allow(clippy::too_many_lines)]
fn redraw_containers(
  focused_container: &Container,
  state: &mut WmState,
  config: &UserConfig,
) -> anyhow::Result<()> {
  let windows_to_redraw = state.windows_to_redraw();
  let windows_to_bring_to_front =
    windows_to_bring_to_front(focused_container, state)?;

  let windows_to_update = {
    let mut windows = windows_to_redraw
      .iter()
      .chain(&windows_to_bring_to_front)
      .unique_by(|window| window.id())
      .collect::<Vec<_>>();

    let descendant_focus_order = state
      .root_container
      .descendant_focus_order()
      .collect::<Vec<_>>();

    // Sort the windows to update by their focus order. The most recently
    // focused window will be updated first.
    // TODO: To reduce flicker, redraw windows that will be shown first,
    // then redraw the ones to be hidden last.
    windows.sort_by_key(|window| {
      descendant_focus_order
        .iter()
        .position(|order| order.id() == window.id())
    });

    windows
  };

  // Get monitors by their optimal hide corner.
  let monitors_by_hide_corner = state.monitors_by_hide_corner();

  for window in windows_to_update.iter().rev() {
    let should_bring_to_front = windows_to_bring_to_front.contains(window);

    let workspace =
      window.workspace().context("Window has no workspace.")?;

    let monitor = window.monitor().context("No monitor.")?;
    let hide_corner = monitors_by_hide_corner
      .iter()
      .find(|(m, _)| m.id() == monitor.id())
      .map(|(_, hide_corner)| hide_corner)
      .context("Monitor not found in hide corner map.")?;

    // Whether the window should be shown above all other windows.
    let z_order = match window.state() {
      WindowState::Floating(config) if config.shown_on_top => {
        WindowZOrder::TopMost
      }
      WindowState::Fullscreen(config) if config.shown_on_top => {
        WindowZOrder::TopMost
      }
      _ if should_bring_to_front => {
        let focused_descendant = workspace
          .descendant_focus_order()
          .next()
          .and_then(|container| container.as_window_container().ok());

        if let Some(focused_descendant) = focused_descendant {
          if window.id() == focused_descendant.id() {
            WindowZOrder::Normal
          } else {
            WindowZOrder::AfterWindow(focused_descendant.native().id())
          }
        } else {
          WindowZOrder::Normal
        }
      }
      _ => WindowZOrder::Normal,
    };

    // Set the z-order of the window.
    //
    // NOTE: macOS doesn't have a robust public API for setting the z-order
    // of a window. See `NativeWindow::raise` for more details.
    #[cfg(target_os = "windows")]
    if should_bring_to_front && !windows_to_redraw.contains(window) {
      tracing::info!("Updating window z-order: {window}");

      if let Err(err) = window.native().set_z_order(&z_order) {
        tracing::warn!("Failed to set window z-order: {}", err);
      }
    }

    // Skip updating the window's position if it only required a z-order
    // change.
    if !windows_to_redraw.contains(window) {
      continue;
    }

    // Transition display state depending on whether window will be
    // shown or hidden.
    window.set_display_state(
      match (window.display_state(), workspace.is_displayed()) {
        (DisplayState::Hidden | DisplayState::Hiding, true) => {
          DisplayState::Showing
        }
        (DisplayState::Shown | DisplayState::Showing, false) => {
          DisplayState::Hiding
        }
        _ => window.display_state(),
      },
    );

    let is_visible = matches!(
      window.display_state(),
      DisplayState::Showing | DisplayState::Shown
    );

    if let Err(err) =
      reposition_window(window, *hide_corner, &z_order, is_visible, config)
    {
      tracing::warn!("Failed to set window position: {}", err);
    }

    // Whether the window is either transitioning to or from fullscreen.
    // TODO: This check can be improved since `prev_state` can be
    // fullscreen without it needing to be marked as not fullscreen.
    #[cfg(target_os = "windows")]
    {
      let is_transitioning_fullscreen =
        match (window.prev_state(), window.state()) {
          (Some(_), WindowState::Fullscreen(s)) if !s.maximized => true,
          (Some(WindowState::Fullscreen(_)), _) => true,
          _ => false,
        };

      if is_transitioning_fullscreen {
        if let Err(err) = window.native().mark_fullscreen(matches!(
          window.state(),
          WindowState::Fullscreen(_)
        )) {
          tracing::warn!("Failed to mark window as fullscreen: {}", err);
        }
      }
    }

    // Skip setting taskbar visibility if the window is hidden (has no
    // effect). Since cloaked windows are normally always visible in the
    // taskbar, we only need to set visibility if `show_all_in_taskbar` is
    // `false`.
    #[cfg(target_os = "windows")]
    if config.value.general.hide_method == HideMethod::Cloak
      && !config.value.general.show_all_in_taskbar
      && matches!(
        window.display_state(),
        DisplayState::Showing | DisplayState::Hiding
      )
    {
      if let Err(err) = window.native().set_taskbar_visibility(is_visible)
      {
        tracing::warn!("Failed to set taskbar visibility: {}", err);
      }
    }
  }

  Ok(())
}

fn reposition_window(
  window: &WindowContainer,
  hide_corner: HideCorner,
  // LINT: `z_order` is only used on Windows.
  #[cfg_attr(not(target_os = "windows"), allow(unused_variables))]
  z_order: &WindowZOrder,
  is_visible: bool,
  config: &UserConfig,
) -> anyhow::Result<()> {
  let rect = window
    .to_rect()?
    .apply_delta(&window.total_border_delta()?, None);

  // For `HideMethod::PlaceInCorner`, we need to reposition hidden windows
  // to the corner of the monitor.
  if config.value.general.hide_method == HideMethod::PlaceInCorner
    && !is_visible
  {
    const VISIBLE_SLIVER: i32 = 1;

    let monitor_rect = window
      .monitor()
      .context("No monitor.")?
      .native_properties()
      .working_area;

    let frame = window.native_properties().frame;

    let position_y = monitor_rect.bottom - VISIBLE_SLIVER;
    let position_x = match hide_corner {
      HideCorner::BottomLeft => {
        monitor_rect.left + VISIBLE_SLIVER - frame.width()
      }
      HideCorner::BottomRight => monitor_rect.right - VISIBLE_SLIVER,
    };

    // Even though the window size is unchanged, `NativeWindow::set_frame`
    // is used instead of `NativeWindow::reposition` because the latter
    // resulted in occasional incorrect positionings on macOS.
    window.native().set_frame(&Rect::from_xy(
      position_x,
      position_y,
      frame.width(),
      frame.height(),
    ))?;

    return Ok(());
  }

  if window.active_drag().is_some() {
    window.native().resize(rect.width(), rect.height())?;
  } else {
    #[cfg(target_os = "macos")]
    window.native().set_frame(&rect)?;

    #[cfg(target_os = "windows")]
    {
      use wm_platform::{
        SWP_ASYNCWINDOWPOS, SWP_FRAMECHANGED, SWP_NOACTIVATE,
        SWP_NOCOPYBITS, SWP_NOSENDCHANGING, WS_MAXIMIZEBOX,
      };

      // Restore window if it's minimized/maximized and shouldn't be. This
      // is needed to be able to move and resize it.
      let should_restore = match &window.state() {
        // Need to restore window if transitioning from maximized
        // fullscreen to non-maximized fullscreen.
        WindowState::Fullscreen(fullscreen) => {
          !fullscreen.maximized && window.native().is_maximized()?
        }
        // No need to restore window if it'll be minimized. Transitioning
        // from maximized to minimized works without having to
        // restore.
        WindowState::Minimized => false,
        _ => {
          window.native().is_minimized()?
            || window.native().is_maximized()?
        }
      };

      if should_restore {
        // Restoring to position has the same effect as `ShowWindow` with
        // `SW_RESTORE`, but doesn't cause a flicker.
        window.native().restore(Some(&rect))?;
      }

      let mut swp_flags = SWP_NOACTIVATE
        | SWP_NOCOPYBITS
        | SWP_NOSENDCHANGING
        | SWP_ASYNCWINDOWPOS;

      match &window.state() {
        WindowState::Minimized => {
          if !window.native().is_minimized()? {
            window.native().minimize()?;
          }
        }
        WindowState::Fullscreen(fullscreen)
          if fullscreen.maximized
            && window.native().has_window_style(WS_MAXIMIZEBOX) =>
        {
          if !window.native().is_maximized()? {
            window.native().maximize()?;
          }

          window.native().set_window_pos(z_order, &rect, swp_flags)?;
        }
        _ => {
          swp_flags |= SWP_FRAMECHANGED;

          window.native().set_window_pos(z_order, &rect, swp_flags)?;

          // When there's a mismatch between the DPI of the monitor and the
          // window, the window might be sized incorrectly after the first
          // move. If we set the position twice, inconsistencies after the
          // first move are resolved.
          if window.has_pending_dpi_adjustment() {
            window.native().set_window_pos(z_order, &rect, swp_flags)?;
          }
        }
      }

      // Set visibility based on the hide method.
      if config.value.general.hide_method == HideMethod::Cloak {
        window.native().set_cloaked(!is_visible)?;
      } else if is_visible {
        window.native().show()?;
      } else {
        window.native().hide()?;
      }
    }
  }

  Ok(())
}

fn jump_cursor(
  focused_container: Container,
  state: &WmState,
  config: &UserConfig,
) -> anyhow::Result<()> {
  let cursor_jump = &config.value.general.cursor_jump;

  let jump_target = match cursor_jump.trigger {
    CursorJumpTrigger::WindowFocus => Some(focused_container),
    CursorJumpTrigger::MonitorFocus => {
      let target_monitor =
        focused_container.monitor().context("No monitor.")?;

      let cursor_monitor = state
        .dispatcher
        .cursor_position()
        .ok()
        .and_then(|pos| state.monitor_at_point(&pos));

      // Jump to the target monitor if the cursor is not already on it.
      cursor_monitor
        .filter(|monitor| monitor.id() != target_monitor.id())
        .map(|_| target_monitor.into())
    }
  };

  if let Some(jump_target) = jump_target {
    let center = jump_target.to_rect()?.center_point();

    if let Err(err) = state.dispatcher.set_cursor_position(&center) {
      tracing::warn!("Failed to set cursor position: {}", err);
    }
  }

  Ok(())
}

fn apply_window_effects(
  // LINT: `window` is only used on Windows.
  #[cfg_attr(not(target_os = "windows"), allow(unused_variables))]
  window: &WindowContainer,
  is_focused: bool,
  config: &UserConfig,
) {
  let window_effects = &config.value.window_effects;

  // LINT: `effect_config` is only used on Windows.
  #[cfg_attr(not(target_os = "windows"), allow(unused_variables))]
  let effect_config = if is_focused {
    &window_effects.focused_window
  } else {
    &window_effects.other_windows
  };

  // Skip if both focused + non-focused window effects are disabled.
  #[cfg(target_os = "windows")]
  if window_effects.focused_window.border.enabled
    || window_effects.other_windows.border.enabled
  {
    apply_border_effect(window, effect_config);
  }

  #[cfg(target_os = "windows")]
  if window_effects.focused_window.hide_title_bar.enabled
    || window_effects.other_windows.hide_title_bar.enabled
  {
    apply_hide_title_bar_effect(window, effect_config);
  }

  #[cfg(target_os = "windows")]
  if window_effects.focused_window.corner_style.enabled
    || window_effects.other_windows.corner_style.enabled
  {
    apply_corner_effect(window, effect_config);
  }

  #[cfg(target_os = "windows")]
  if window_effects.focused_window.transparency.enabled
    || window_effects.other_windows.transparency.enabled
  {
    apply_transparency_effect(window, effect_config);
  }
}

#[cfg(target_os = "windows")]
fn apply_border_effect(
  window: &WindowContainer,
  effect_config: &WindowEffectConfig,
) {
  let border_color = if effect_config.border.enabled {
    Some(&effect_config.border.color)
  } else {
    None
  };

  _ = window.native().set_border_color(border_color);

  let native = window.native().clone();
  let border_color = border_color.cloned();

  // Re-apply border color after a short delay to better handle
  // windows that change it themselves.
  tokio::task::spawn(async move {
    tokio::time::sleep(std::time::Duration::from_millis(50)).await;
    _ = native.set_border_color(border_color.as_ref());
  });
}

#[cfg(target_os = "windows")]
fn apply_hide_title_bar_effect(
  window: &WindowContainer,
  effect_config: &WindowEffectConfig,
) {
  _ = window
    .native()
    .set_title_bar_visibility(!effect_config.hide_title_bar.enabled);
}

#[cfg(target_os = "windows")]
fn apply_corner_effect(
  window: &WindowContainer,
  effect_config: &WindowEffectConfig,
) {
  let corner_style = if effect_config.corner_style.enabled {
    &effect_config.corner_style.style
  } else {
    &CornerStyle::Default
  };

  _ = window.native().set_corner_style(corner_style);
}

#[cfg(target_os = "windows")]
fn apply_transparency_effect(
  window: &WindowContainer,
  effect_config: &WindowEffectConfig,
) {
  let transparency = if effect_config.transparency.enabled {
    &effect_config.transparency.opacity
  } else {
    // Reset the transparency to default.
    &OpacityValue::from_alpha(u8::MAX)
  };

  _ = window.native().set_transparency(transparency);
}


================================================
FILE: packages/wm/src/commands/general/reload_config.rs
================================================
use anyhow::Context;
use tracing::{info, warn};
#[cfg(target_os = "windows")]
use wm_common::{HideMethod, ParsedConfig};
use wm_common::{WindowRuleEvent, WmEvent};
#[cfg(target_os = "windows")]
use wm_platform::NativeWindowWindowsExt;

use crate::{
  commands::{window::run_window_rules, workspace::sort_workspaces},
  traits::{CommonGetters, TilingSizeGetters, WindowGetters},
  user_config::UserConfig,
  wm::WindowManager,
  wm_state::WmState,
};

pub fn reload_config(
  state: &mut WmState,
  config: &mut UserConfig,
) -> anyhow::Result<()> {
  info!("Config reloaded.");

  // Keep reference to old config for comparison.
  #[cfg(target_os = "windows")]
  let old_config = config.value.clone();

  // Re-evaluate user config file and set its values in state.
  config.reload()?;

  // Re-run window rules on all active windows.
  for window in state.windows() {
    window.set_done_window_rules(Vec::new());
    run_window_rules(window, &WindowRuleEvent::Manage, state, config)?;
  }

  update_workspace_configs(state, config)?;

  update_container_gaps(state, config);

  #[cfg(target_os = "windows")]
  update_window_effects(&old_config, state, config)?;

  // Ensure all windows are shown when hide method is changed.
  #[cfg(target_os = "windows")]
  if old_config.general.hide_method != config.value.general.hide_method
    && config.value.general.hide_method == HideMethod::Cloak
  {
    for window in state.windows() {
      let _ = window.native().show();
    }
  }

  // Ensure all windows are shown in taskbar when `show_all_in_taskbar` is
  // changed.
  #[cfg(target_os = "windows")]
  if old_config.general.show_all_in_taskbar
    != config.value.general.show_all_in_taskbar
    && config.value.general.show_all_in_taskbar
  {
    for window in state.windows() {
      let _ = window.native().set_taskbar_visibility(true);
    }
  }

  // Clear active binding modes.
  state.binding_modes = Vec::new();

  // Redraw full container tree.
  state
    .pending_sync
    .queue_container_to_redraw(state.root_container.clone());

  // Emit the updated config.
  state.emit_event(WmEvent::UserConfigChanged {
    config_path: config
      .path
      .to_str()
      .context("Invalid config path.")?
      .to_string(),
    config_string: config.value_str.clone(),
    parsed_config: config.value.clone(),
  });

  // Run config reload commands.
  WindowManager::run_commands(
    &config.value.general.config_reload_commands.clone(),
    state.focused_container().context("No focused container.")?,
    state,
    config,
  )?;

  Ok(())
}

/// Update configs of active workspaces.
fn update_workspace_configs(
  state: &mut WmState,
  config: &UserConfig,
) -> anyhow::Result<()> {
  let workspaces = state.workspaces();

  for workspace in &workspaces {
    let monitor = workspace.monitor().context("No monitor.")?;

    let workspace_config = config
      .value
      .workspaces
      .iter()
      .find(|config| config.name == workspace.config().name)
      .or_else(|| {
        // When the workspace config is not found, the current name of the
        // workspace has been removed. So, we reassign the first suitable
        // workspace config to the workspace.
        config
          .workspace_config_for_monitor(&monitor, &workspaces)
          .or_else(|| config.next_inactive_workspace_config(&workspaces))
      });

    match workspace_config {
      None => {
        warn!(
          "Unable to update workspace config. No available workspace configs."
        );
      }
      Some(workspace_config) => {
        if *workspace_config != workspace.config() {
          workspace.set_config(workspace_config.clone());

          sort_workspaces(&monitor, config)?;

          state.emit_event(WmEvent::WorkspaceUpdated {
            updated_workspace: workspace.to_dto()?,
          });
        }
      }
    }
  }

  Ok(())
}

/// Updates outer gap of workspaces and inner gaps of tiling containers.
fn update_container_gaps(state: &mut WmState, config: &UserConfig) {
  let tiling_containers = state
    .root_container
    .self_and_descendants()
    .filter_map(|container| container.as_tiling_container().ok());

  for container in tiling_containers {
    container.set_gaps_config(config.value.gaps.clone());
  }

  for workspace in state.workspaces() {
    workspace.set_gaps_config(config.value.gaps.clone());
  }
}

#[cfg(target_os = "windows")]
fn update_window_effects(
  old_config: &ParsedConfig,
  state: &mut WmState,
  config: &UserConfig,
) -> anyhow::Result<()> {
  let focused_container =
    state.focused_container().context("No focused container.")?;

  let window_effects = &config.value.window_effects;
  let old_window_effects = &old_config.window_effects;

  // Window border effects are left at system defaults if disabled in the
  // config. However, when transitioning from colored borders to having
  // them disabled, it's best to reset to the system defaults.
  if !window_effects.focused_window.border.enabled
    && old_window_effects.focused_window.border.enabled
  {
    if let Ok(window) = focused_container.as_window_container() {
      _ = window.native().set_border_color(None);
    }
  }

  if !window_effects.other_windows.border.enabled
    && old_window_effects.other_windows.border.enabled
  {
    let unfocused_windows = state
      .windows()
      .into_iter()
      .filter(|window| window.id() != focused_container.id());

    for window in unfocused_windows {
      _ = window.native().set_border_color(None);
    }
  }

  state.pending_sync.queue_all_effects_update();

  Ok(())
}


================================================
FILE: packages/wm/src/commands/general/shell_exec.rs
================================================
use std::path::Path;

#[cfg(target_os = "windows")]
use anyhow::Context;
#[cfg(target_os = "macos")]
use shell_util::{CommandOptions, Shell};
#[cfg(target_os = "windows")]
use wm_platform::DispatcherExtWindows;

use crate::wm_state::WmState;

pub fn shell_exec(
  command: &str,
  // LINT: `hide_window` is only used on Windows.
  #[cfg_attr(not(target_os = "windows"), allow(unused_variables))]
  hide_window: bool,
  state: &WmState,
) -> anyhow::Result<()> {
  let (program, args) = parse_command(command, state)?;
  tracing::info!(
    "Parsed command program: '{}', args: '{}'.",
    program,
    args
  );

  // NOTE: The standard library's `Command::new` is not used because it
  // launches the program as a subprocess. This prevents cleanup of handles
  // held by our process (e.g. the IPC server port) until the subprocess
  // exits.
  let result = {
    #[cfg(target_os = "macos")]
    {
      Shell::spawn(
        &program,
        args.split_whitespace(),
        &CommandOptions::default(),
      )
    }
    #[cfg(target_os = "windows")]
    {
      let home_dir =
        home::home_dir().context("Unable to get home directory.")?;

      // TODO: Use `Shell::spawn` instead. `ShellExecuteExW` is still used
      // to be able to launch programs from the App Paths registry
      // (`HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths`), like
      // `chrome` without it being in $PATH.
      state.dispatcher.shell_execute_ex(
        &program,
        &args,
        &home_dir,
        hide_window,
      )
    }
  };

  result.map_err(|err| {
    anyhow::anyhow!(
      "Shell exec failed for '{command}'. Make sure the program exists and is \
      accessible from your shell. Error: {err}",
    )
  })?;

  Ok(())
}

/// Parses a command string into a program name/path and arguments. This
/// also expands any environment variables found in the command string if
/// they are wrapped in `%` characters. If the command string is a path,
/// a file extension is required.
///
/// This is similar to the `SHEvaluateSystemCommandTemplate` Win32
/// function. It also parses program name/path and arguments, but can't
/// handle `/` as file path delimiters and it errors for certain programs
/// (e.g. `code`).
///
/// Returns a tuple containing the program name/path and arguments.
///
/// # Examples
///
/// ```no_run
/// let (prog, args) = parse_command("code .")?;
/// assert_eq!(prog, "code");
/// assert_eq!(args, ".");
///
/// let (prog, args) = parse_command(
///   r#"C:\Program Files\Git\git-bash --cd=C:\Users\larsb\.glaze-wm"#,
/// )?;
/// assert_eq!(prog, r#"C:\Program Files\Git\git-bash"#);
/// assert_eq!(args, r#"--cd=C:\Users\larsb\.glaze-wm"#);
/// ```
fn parse_command(
  command: &str,
  // LINT: `state` is only used on Windows.
  #[cfg_attr(not(target_os = "windows"), allow(unused_variables))]
  state: &WmState,
) -> anyhow::Result<(String, String)> {
  // Expand environment variables in the command string.
  let expanded_command = {
    #[cfg(target_os = "windows")]
    {
      state.dispatcher.expand_env_strings(command)?
    }
    #[cfg(target_os = "macos")]
    {
      // TODO: Expand env variables on macOS.
      command.to_string()
    }
  };

  let command_parts =
    expanded_command.split_whitespace().collect::<Vec<_>>();

  // If the command starts with double quotes, then the program name/path
  // is wrapped in double quotes (e.g. `"C:\path\to\app.exe" --flag`).
  if expanded_command.starts_with('"') {
    // Find the closing double quote.
    let (closing_index, _) =
      expanded_command.match_indices('"').nth(2).ok_or_else(|| {
        anyhow::anyhow!(
          "Shell exec failed for '{command}': command doesn't have an ending `\"`."
        )
      })?;

    return Ok((
      expanded_command[1..closing_index].to_string(),
      expanded_command[closing_index + 1..].trim().to_string(),
    ));
  }

  // The first part is the program name if it doesn't contain a slash or
  // backslash.
  if let Some(first_part) = command_parts.first() {
    if !first_part.contains(&['/', '\\'][..]) {
      let args = command_parts[1..].join(" ");
      return Ok(((*first_part).to_string(), args));
    }
  }

  let mut cumulative_path = Vec::new();

  // Lastly, iterate over the command until a valid file path is found.
  for (part_index, &part) in command_parts.iter().enumerate() {
    cumulative_path.push(part);

    if Path::new(&cumulative_path.join(" ")).is_file() {
      return Ok((
        cumulative_path.join(" "),
        command_parts[part_index + 1..].join(" "),
      ));
    }
  }

  anyhow::bail!(
    "Shell exec failed for '{command}': program path is not valid."
  )
}


================================================
FILE: packages/wm/src/commands/general/toggle_pause.rs
================================================
use wm_common::WmEvent;

use crate::wm_state::WmState;

/// Pauses or unpauses the WM.
pub fn toggle_pause(state: &mut WmState) {
  let is_paused = !state.is_paused;
  state.is_paused = is_paused;

  // Redraw full container tree on unpause.
  if !is_paused {
    state
      .pending_sync
      .queue_container_to_redraw(state.root_container.clone());
  }

  state.emit_event(WmEvent::PauseChanged { is_paused });
}


================================================
FILE: packages/wm/src/commands/mod.rs
================================================
pub mod container;
pub mod general;
pub mod monitor;
pub mod window;
pub mod workspace;


================================================
FILE: packages/wm/src/commands/monitor/add_monitor.rs
================================================
use anyhow::Context;
use tracing::info;
use wm_common::WmEvent;
use wm_platform::Display;

use crate::{
  commands::{
    container::{attach_container, move_container_within_tree},
    workspace::{activate_workspace, sort_workspaces},
  },
  models::{Monitor, NativeMonitorProperties, Workspace},
  traits::{CommonGetters, PositionGetters, WindowGetters},
  user_config::UserConfig,
  wm_state::WmState,
};

pub fn add_monitor(
  native_display: Display,
  native_properties: NativeMonitorProperties,
  state: &mut WmState,
) -> anyhow::Result<Monitor> {
  // Create `Monitor` instance. This uses the working area of the monitor
  // instead of the bounds of the display. The working area excludes
  // taskbars and other reserved display space.
  let monitor = Monitor::new(native_display, native_properties);

  attach_container(
    &monitor.clone().into(),
    &state.root_container.clone().into(),
    None,
  )?;

  info!("Monitor added: {monitor}");

  state.emit_event(WmEvent::MonitorAdded {
    added_monitor: monitor.to_dto()?,
  });

  Ok(monitor)
}

pub fn move_bounded_workspaces_to_new_monitor(
  monitor: &Monitor,
  state: &mut WmState,
  config: &UserConfig,
) -> anyhow::Result<()> {
  let bound_workspace_configs = config
    .value
    .workspaces
    .iter()
    .filter(|config| {
      config.bind_to_monitor.is_some_and(|monitor_index| {
        monitor.index() == monitor_index as usize
      })
    })
    .collect::<Vec<_>>();

  for workspace_config in bound_workspace_configs {
    let existing_workspace =
      state.workspace_by_name(&workspace_config.name);

    if let Some(existing_workspace) = existing_workspace {
      // Move workspaces that should be bound to the newly added monitor.
      move_workspace_to_monitor(
        &existing_workspace,
        monitor,
        state,
        config,
      )?;
    } else if workspace_config.keep_alive {
      // Activate all `keep_alive` workspaces for this monitor.
      activate_workspace(
        Some(&workspace_config.name),
        Some(monitor.clone()),
        state,
        config,
      )?;
    }
  }

  // Make sure the monitor has at least one workspace. This will
  // automatically prioritize bound workspace configs and fall back to the
  // first available one if needed.
  if monitor.child_count() == 0 {
    activate_workspace(None, Some(monitor.clone()), state, config)?;
  }

  Ok(())
}

// TODO: Move to its own file once `swap-workspace` PR is merged.
// Ref: https://github.com/glzr-io/glazewm/pull/980.
pub fn move_workspace_to_monitor(
  workspace: &Workspace,
  target_monitor: &Monitor,
  state: &mut WmState,
  config: &UserConfig,
) -> anyhow::Result<()> {
  let origin_monitor = workspace.monitor().context("No monitor.")?;

  move_container_within_tree(
    &workspace.clone().into(),
    &target_monitor.clone().into(),
    target_monitor.child_count(),
    state,
  )?;

  let windows = workspace
    .descendants()
    .filter_map(|descendant| descendant.as_window_container().ok());

  for window in windows {
    window.set_has_pending_dpi_adjustment(true);

    window.set_floating_placement(
      window
        .floating_placement()
        .translate_to_center(&workspace.to_rect()?),
    );
  }

  // Get currently displayed workspace on the target monitor.
  let displayed_workspace = target_monitor
    .displayed_workspace()
    .context("No displayed workspace.")?;

  state
    .pending_sync
    .queue_container_to_redraw(workspace.clone())
    .queue_container_to_redraw(displayed_workspace);

  match origin_monitor.child_count() {
    0 => {
      // Prevent origin monitor from having no workspaces.
      activate_workspace(None, Some(origin_monitor), state, config)?;
    }
    _ => {
      // Redraw the workspace on the origin monitor.
      state.pending_sync.queue_container_to_redraw(
        origin_monitor
          .displayed_workspace()
          .context("No displayed workspace.")?,
      );
    }
  }

  sort_workspaces(target_monitor, config)?;

  state.emit_event(WmEvent::WorkspaceUpdated {
    updated_workspace: workspace.to_dto()?,
  });

  Ok(())
}


================================================
FILE: packages/wm/src/commands/monitor/focus_monitor.rs
================================================
use anyhow::Context;

use crate::{
  commands::workspace::focus_workspace, models::WorkspaceTarget,
  user_config::UserConfig, wm_state::WmState,
};

/// Focuses a monitor by a given monitor index.
pub fn focus_monitor(
  monitor_index: usize,
  state: &mut WmState,
  config: &UserConfig,
) -> anyhow::Result<()> {
  let monitors = state.monitors();

  let target_monitor = monitors.get(monitor_index).with_context(|| {
    format!("Monitor at index {monitor_index} was not found.")
  })?;

  let workspace_name = target_monitor
    .displayed_workspace()
    .map(|workspace| workspace.config().name)
    .context("Failed to get target workspace name.")?;

  focus_workspace(WorkspaceTarget::Name(workspace_name), state, config)
}


================================================
FILE: packages/wm/src/commands/monitor/mod.rs
================================================
mod add_monitor;
mod focus_monitor;
mod remove_monitor;
mod sort_monitors;
mod update_monitor;

pub use add_monitor::*;
pub use focus_monitor::*;
pub use remove_monitor::*;
pub use sort_monitors::*;
pub use update_monitor::*;


================================================
FILE: packages/wm/src/commands/monitor/remove_monitor.rs
================================================
use anyhow::Context;
use tracing::info;
use wm_common::WmEvent;

use crate::{
  commands::{
    container::{detach_container, move_container_within_tree},
    workspace::sort_workspaces,
  },
  models::Monitor,
  traits::CommonGetters,
  user_config::UserConfig,
  wm_state::WmState,
};

#[allow(clippy::needless_pass_by_value)]
pub fn remove_monitor(
  monitor: Monitor,
  state: &mut WmState,
  config: &UserConfig,
) -> anyhow::Result<()> {
  info!("Removing monitor: {monitor}");

  let target_monitor = state
    .monitors()
    .into_iter()
    .find(|m| m.id() != monitor.id())
    .context("No target monitor to move workspaces.")?;

  // Avoid moving empty workspaces.
  let workspaces_to_move =
    monitor.workspaces().into_iter().filter(|workspace| {
      workspace.has_children() || workspace.config().keep_alive
    });

  for workspace in workspaces_to_move {
    // Move workspace to target monitor.
    move_container_within_tree(
      &workspace.clone().into(),
      &target_monitor.clone().into(),
      target_monitor.child_count(),
      state,
    )?;

    sort_workspaces(&target_monitor, config)?;

    state.emit_event(WmEvent::WorkspaceUpdated {
      updated_workspace: workspace.to_dto()?,
    });
  }

  detach_container(monitor.clone().into())?;

  state.emit_event(WmEvent::MonitorRemoved {
    removed_id: monitor.id(),
    removed_device_name: monitor.native_properties().device_name,
  });

  Ok(())
}


================================================
FILE: packages/wm/src/commands/monitor/sort_monitors.rs
================================================
use crate::{
  models::RootContainer,
  traits::{CommonGetters, PositionGetters},
};

/// Sorts the root container's monitors from left-to-right and
/// top-to-bottom.
pub fn sort_monitors(root: &RootContainer) -> anyhow::Result<()> {
  let monitors = root.monitors();

  // Create a tuple of monitors and their rects.
  let mut monitors_with_rect = monitors
    .into_iter()
    .map(|monitor| {
      let rect = monitor.to_rect()?.clone();
      anyhow::Ok((monitor, rect))
    })
    .try_collect::<Vec<_>>()?;

  // Sort monitors from left-to-right, top-to-bottom.
  monitors_with_rect.sort_by(|(_, rect_a), (_, rect_b)| {
    if rect_a.x() == rect_b.x() {
      rect_a.y().cmp(&rect_b.y())
    } else {
      rect_a.x().cmp(&rect_b.x())
    }
  });

  *root.borrow_children_mut() = monitors_with_rect
    .into_iter()
    .map(|(monitor, _)| monitor.into())
    .collect();

  Ok(())
}


================================================
FILE: packages/wm/src/commands/monitor/update_monitor.rs
================================================
use tracing::info;
use wm_common::WmEvent;
use wm_platform::Display;

use crate::{
  models::{Monitor, NativeMonitorProperties},
  wm_state::WmState,
};

pub fn update_monitor(
  monitor: &Monitor,
  native_display: &Display,
  native_properties: NativeMonitorProperties,
  state: &mut WmState,
) -> anyhow::Result<()> {
  monitor.set_native(native_display.clone());
  monitor.set_native_properties(native_properties);

  info!("Monitor updated: {monitor}");

  // TODO: Check that a property on the monitor actually changed.
  state.emit_event(WmEvent::MonitorUpdated {
    updated_monitor: monitor.to_dto()?,
  });

  Ok(())
}


================================================
FILE: packages/wm/src/commands/window/ignore_window.rs
================================================
use anyhow::Context;
use wm_common::WindowState;

use crate::{
  commands::container::{
    detach_container, flatten_child_split_containers,
  },
  models::WindowContainer,
  traits::{CommonGetters, WindowGetters},
  wm_state::WmState,
};

#[allow(clippy::needless_pass_by_value)]
pub fn ignore_window(
  window: WindowContainer,
  state: &mut WmState,
) -> anyhow::Result<()> {
  // Create iterator of parent, grandparent, and great-grandparent.
  let ancestors = window.ancestors().take(3).collect::<Vec<_>>();

  state.ignored_windows.push(window.native().clone());
  detach_container(window.clone().into())?;

  // After detaching the container, flatten any redundant split containers.
  // For example, in the layout V[1 H[2]] where container 1 is detached to
  // become V[H[2]], this will then need to be flattened to V[2].
  for ancestor in ancestors.iter().rev() {
    flatten_child_split_containers(ancestor)?;
  }

  // Sibling containers need to be redrawn if the window was tiling.
  if window.state() == WindowState::Tiling {
    let ancestor_to_redraw = ancestors
      .into_iter()
      .find(|ancestor| !ancestor.is_detached())
      .context("No ancestor to redraw.")?;

    state
      .pending_sync
      .queue_containers_to_redraw(ancestor_to_redraw.tiling_children());
  }

  Ok(())
}


================================================
FILE: packages/wm/src/commands/window/manage_window.rs
================================================
use anyhow::Context;
use tracing::info;
use wm_common::{try_warn, WindowRuleEvent, WindowState, WmEvent};
use wm_platform::{NativeWindow, RectDelta};

use crate::{
  commands::{
    container::{attach_container, set_focused_descendant},
    window::run_window_rules,
  },
  models::{
    Container, Monitor, NativeWindowProperties, NonTilingWindow,
    TilingWindow, WindowContainer,
  },
  traits::{CommonGetters, PositionGetters, WindowGetters},
  user_config::UserConfig,
  wm_state::WmState,
};

pub fn manage_window(
  native_window: NativeWindow,
  target_parent: Option<Container>,
  state: &mut WmState,
  config: &mut UserConfig,
) -> anyhow::Result<()> {
  let Some(native_properties) =
    check_is_manageable(&native_window).unwrap_or(None)
  else {
    return Ok(());
  };

  // Create the window instance. This may fail if the window handle has
  // already been destroyed.
  let window = try_warn!(create_window(
    native_window,
    native_properties,
    target_parent,
    state,
    config
  ));

  // Set the newly added window as focus descendant. This means the window
  // rules will be run as if the window is focused.
  set_focused_descendant(&window.clone().into(), None);

  // Window might be detached if `ignore` command has been invoked.
  let updated_window = run_window_rules(
    window.clone(),
    &WindowRuleEvent::Manage,
    state,
    config,
  )?;

  if let Some(window) = updated_window {
    info!("New window managed: {window}");

    state.emit_event(WmEvent::WindowManaged {
      managed_window: window.to_dto()?,
    });

    // OS focus should be set to the newly added window in case it's not
    // already focused.
    state.pending_sync.queue_focus_change();

    // Normally, a `PlatformEvent::WindowFocused` event is what triggers
    // focus effects and workspace reordering to be applied. However, when
    // a window is first launched, this event can come before the
    // window is managed, and so we need to force an update here.
    state.pending_sync.queue_focused_effect_update();
    state.pending_sync.queue_workspace_to_reorder(
      window.workspace().context("No workspace.")?,
    );

    // Sibling containers need to be redrawn if the window is tiling.
    state.pending_sync.queue_container_to_redraw(
      if window.state() == WindowState::Tiling {
        window.parent().context("No parent.")?
      } else {
        window.into()
      },
    );
  }

  Ok(())
}

/// Checks if a window is manageable and retrieves its native properties.
///
/// Returns `Ok(Some(properties))` if the window is manageable and its
/// properties were retrieved successfully.
fn check_is_manageable(
  native_window: &NativeWindow,
) -> anyhow::Result<Option<NativeWindowProperties>> {
  if !native_window.is_visible()? {
    return Ok(None);
  }

  #[cfg(target_os = "macos")]
  {
    use wm_platform::NativeWindowExtMacOs;

    let is_standard_window = native_window.role()? == "AXWindow"
      && native_window.subrole()? == "AXStandardWindow";

    if !is_standard_window {
      return Ok(None);
    }
  }

  // Ensure window has a valid process name, title, etc.
  let native_properties = NativeWindowProperties::try_from(native_window)?;

  #[cfg(target_os = "windows")]
  {
    use wm_platform::{
      NativeWindowWindowsExt, WS_CAPTION, WS_CHILD, WS_EX_NOACTIVATE,
      WS_EX_TOOLWINDOW,
    };

    // TODO: Temporary fix for managing Flow Launcher until a force manage
    // command is added.
    let is_flow_launcher = native_properties.process_name
      == "Flow.Launcher"
      && native_properties.title == "Flow.Launcher";

    if !is_flow_launcher {
      // Ensure window is top-level (i.e. not a child window). Ignore
      // windows that cannot be focused or if they're unavailable in
      // task switcher (alt+tab menu).
      if native_window.has_window_style(WS_CHILD)
        || native_window
          .has_window_style_ex(WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW)
      {
        return Ok(None);
      }

      // Some applications spawn top-level windows for menus that
      // should be ignored. This includes the autocomplete popup in
      // Notepad++ and title bar menu in Keepass. Although not
      // foolproof, these can typically be identified by having an
      // owner window and no title bar.
      if native_window.has_owner_window()
        && !native_window.has_window_style(WS_CAPTION)
      {
        return Ok(None);
      }
    }
  }

  Ok(Some(native_properties))
}

fn create_window(
  native_window: NativeWindow,
  native_properties: NativeWindowProperties,
  target_parent: Option<Container>,
  state: &mut WmState,
  config: &UserConfig,
) -> anyhow::Result<WindowContainer> {
  let nearest_monitor = state
    .nearest_monitor(&native_window)
    .context("No nearest monitor.")?;

  let nearest_workspace = nearest_monitor
    .displayed_workspace()
    .context("No nearest workspace.")?;

  let gaps_config = config.value.gaps.clone();
  let window_state =
    window_state_to_create(&native_properties, &nearest_monitor, config)?;

  // Attach the new window as the first child of the target parent (if
  // provided), otherwise, add as a sibling of the focused container.
  let (target_parent, target_index) = match target_parent {
    Some(parent) => (parent, 0),
    None => insertion_target(&window_state, state)?,
  };

  let target_workspace =
    target_parent.workspace().context("No target workspace.")?;

  let prefers_centered = config
    .value
    .window_behavior
    .state_defaults
    .floating
    .centered;

  // Calculate where window should be placed when floating is enabled. Use
  // the original width/height of the window and optionally position it in
  // the center of the workspace.
  let is_same_workspace = nearest_workspace.id() == target_workspace.id();
  let floating_placement = {
    let placement = if !is_same_workspace || prefers_centered {
      native_properties
        .frame
        .translate_to_center(&target_workspace.to_rect()?)
    } else {
      native_properties.frame.clone()
    };

    // Clamp the window size to be within the workspace's outer gaps. 10px
    // is arbitrary - helps differentiate from tiling windows.
    let max_workspace_rect = target_workspace.max_workspace_rect()?;
    placement.clamp_size(
      max_workspace_rect.width() - 10,
      max_workspace_rect.height() - 10,
    )
  };

  // Window has no border delta unless it's later changed via the
  // `adjust_borders` command.
  let border_delta = RectDelta::zero();

  let window_container: WindowContainer = match window_state {
    WindowState::Tiling => TilingWindow::new(
      None,
      native_window,
      native_properties,
      None,
      border_delta,
      floating_placement,
      false,
      gaps_config,
      Vec::new(),
      None,
    )
    .into(),
    _ => NonTilingWindow::new(
      None,
      native_window,
      native_properties,
      window_state,
      None,
      border_delta,
      None,
      floating_placement,
      !prefers_centered,
      Vec::new(),
      None,
    )
    .into(),
  };

  attach_container(
    &window_container.clone().into(),
    &target_parent,
    Some(target_index),
  )?;

  // The OS might spawn the window on a different monitor to the target
  // parent, so adjustments might need to be made because of DPI.
  if nearest_monitor
    .has_dpi_difference(&window_container.clone().into())?
  {
    window_container.set_has_pending_dpi_adjustment(true);
  }

  Ok(window_container)
}

/// Gets the initial state for a window based on its native state.
///
/// Note that maximized windows are initialized as tiling.
fn window_state_to_create(
  native_properties: &NativeWindowProperties,
  nearest_monitor: &Monitor,
  config: &UserConfig,
) -> anyhow::Result<WindowState> {
  if native_properties.is_minimized {
    return Ok(WindowState::Minimized);
  }

  let nearest_workspace = nearest_monitor
    .displayed_workspace()
    .context("No workspace.")?;

  // Only initialize as fullscreen if the window *exceeds* the workspace
  // bounds (due to the 1px inset).
  //
  // For example, with 0px outer gaps and a window that covers the entire
  // workspace, it would still not be initialized as fullscreen. The window
  // needs to be within the workspace's outer gaps by at least 1px on each
  // side.
  if !native_properties.is_maximized
    && native_properties
      .frame
      .inset(1)
      .contains_rect(&nearest_workspace.max_workspace_rect()?)
  {
    return Ok(WindowState::Fullscreen(
      config
        .value
        .window_behavior
        .state_defaults
        .fullscreen
        .clone(),
    ));
  }

  // Initialize windows that can't be resized as floating.
  if !native_properties.is_resizable {
    return Ok(WindowState::Floating(
      config.value.window_behavior.state_defaults.floating.clone(),
    ));
  }

  Ok(WindowState::default_from_config(&config.value))
}

/// Gets where to insert a new window in the container tree.
///
/// Rules:
/// - For non-tiling windows: Always append to the workspace.
/// - For tiling windows:
///   1. Try to insert after the focused tiling window if one exists.
///   2. If a non-tiling window is focused, try to insert after the first
///      tiling window found.
///   3. If no tiling windows exist, append to the workspace.
///
/// Returns tuple of (parent container, insertion index).
fn insertion_target(
  window_state: &WindowState,
  state: &WmState,
) -> anyhow::Result<(Container, usize)> {
  let focused_container =
    state.focused_container().context("No focused container.")?;

  let focused_workspace =
    focused_container.workspace().context("No workspace.")?;

  // For tiling windows, try to find a suitable tiling window to insert
  // next to.
  if *window_state == WindowState::Tiling {
    let sibling = match focused_container {
      Container::TilingWindow(_) => Some(focused_container),
      _ => focused_workspace
        .descendant_focus_order()
        .find(Container::is_tiling_window),
    };

    if let Some(sibling) = sibling {
      return Ok((
        sibling.parent().context("No parent.")?,
        sibling.index() + 1,
      ));
    }
  }

  // Default to appending to workspace.
  Ok((
    focused_workspace.clone().into(),
    focused_workspace.child_count(),
  ))
}


================================================
FILE: packages/wm/src/commands/window/mod.rs
================================================
mod ignore_window;
mod manage_window;
mod move_window_in_direction;
mod move_window_to_workspace;
mod resize_window;
mod run_window_rules;
mod set_window_position;
mod set_window_size;
mod unmanage_window;
mod update_window_state;

pub use ignore_window::*;
pub use manage_window::*;
pub use move_window_in_direction::*;
pub use move_window_to_workspace::*;
pub use resize_window::*;
pub use run_window_rules::*;
pub use set_window_position::*;
pub use set_window_size::*;
pub use unmanage_window::*;
pub use update_window_state::*;


================================================
FILE: packages/wm/src/commands/window/move_window_in_direction.rs
================================================
use anyhow::Context;
use wm_common::{TilingDirection, WindowState};
use wm_platform::{Direction, Rect};

use crate::{
  commands::container::{
    flatten_child_split_containers, flatten_split_container,
    move_container_within_tree, resize_tiling_container,
    set_focused_descendant, wrap_in_split_container,
  },
  models::{
    DirectionContainer, Monitor, NonTilingWindow, SplitContainer,
    TilingContainer, TilingWindow, WindowContainer,
  },
  traits::{
    CommonGetters, PositionGetters, TilingDirectionGetters, WindowGetters,
  },
  user_config::UserConfig,
  wm_state::WmState,
};

/// The distance in pixels to snap the window to the monitor's edge.
const SNAP_DISTANCE: i32 = 15;

pub fn move_window_in_direction(
  window: WindowContainer,
  direction: &Direction,
  state: &mut WmState,
  config: &UserConfig,
) -> anyhow::Result<()> {
  match window {
    WindowContainer::TilingWindow(window) => {
      move_tiling_window(window, direction, state, config)
    }
    WindowContainer::NonTilingWindow(non_tiling_window) => {
      match non_tiling_window.state() {
        WindowState::Floating(_) => {
          move_floating_window(non_tiling_window, direction, state)
        }
        WindowState::Fullscreen(_) => move_to_workspace_in_direction(
          &non_tiling_window.into(),
          direction,
          state,
        ),
        _ => Ok(()),
      }
    }
  }
}

fn move_tiling_window(
  window_to_move: TilingWindow,
  direction: &Direction,
  state: &mut WmState,
  config: &UserConfig,
) -> anyhow::Result<()> {
  // Flatten the parent split container if it only contains the window.
  if let Some(split_parent) = window_to_move
    .parent()
    .and_then(|parent| parent.as_split().cloned())
  {
    if split_parent.child_count() == 1 {
      flatten_split_container(split_parent)?;
    }
  }

  let parent = window_to_move
    .direction_container()
    .context("No direction container.")?;

  let has_matching_tiling_direction = parent.tiling_direction()
    == TilingDirection::from_direction(direction);

  // Attempt to swap or move the window into a sibling container.
  if has_matching_tiling_direction {
    if let Some(sibling) =
      tiling_sibling_in_direction(&window_to_move, direction)
    {
      return move_to_sibling_container(
        window_to_move,
        sibling,
        direction,
        state,
      );
    }
  }

  // Attempt to move the window to workspace in given direction.
  if (has_matching_tiling_direction
    || window_to_move.tiling_siblings().count() == 0)
    && parent.is_workspace()
  {
    return move_to_workspace_in_direction(
      &window_to_move.into(),
      direction,
      state,
    );
  }

  // The window cannot be moved within the parent container, so traverse
  // upwards to find an ancestor that has the correct tiling direction.
  let target_ancestor = parent.ancestors().find_map(|ancestor| {
    ancestor.as_direction_container().ok().filter(|ancestor| {
      ancestor.tiling_direction()
        == TilingDirection::from_direction(direction)
    })
  });

  match target_ancestor {
    // If there is no suitable ancestor, then change the tiling direction
    // of the workspace.
    None => invert_workspace_tiling_direction(
      window_to_move,
      direction,
      state,
      config,
    ),
    // Otherwise, move the container into the given ancestor. This could
    // simply be the container's direct parent.
    Some(target_ancestor) => insert_into_ancestor(
      &window_to_move,
      &target_ancestor,
      direction,
      state,
    ),
  }
}

/// Gets the next sibling `TilingWindow` or `SplitContainer` in the given
/// direction.
fn tiling_sibling_in_direction(
  window: &TilingWindow,
  direction: &Direction,
) -> Option<TilingContainer> {
  match direction {
    Direction::Up | Direction::Left => window
      .prev_siblings()
      .find_map(|sibling| sibling.as_tiling_container().ok()),
    _ => window
      .next_siblings()
      .find_map(|sibling| sibling.as_tiling_container().ok()),
  }
}

fn move_to_sibling_container(
  window_to_move: TilingWindow,
  target_sibling: TilingContainer,
  direction: &Direction,
  state: &mut WmState,
) -> anyhow::Result<()> {
  let parent = window_to_move.parent().context("No parent.")?;

  match target_sibling {
    TilingContainer::TilingWindow(sibling_window) => {
      // Swap the window with sibling in given direction.
      move_container_within_tree(
        &window_to_move.clone().into(),
        &parent,
        sibling_window.index(),
        state,
      )?;

      state
        .pending_sync
        .queue_container_to_redraw(sibling_window)
        .queue_container_to_redraw(window_to_move);
    }
    TilingContainer::Split(sibling_split) => {
      let sibling_descendant =
        sibling_split.descendant_in_direction(&direction.inverse());

      // Move the window into the sibling split container.
      if let Some(sibling_descendant) = sibling_descendant {
        let target_parent = sibling_descendant
          .direction_container()
          .context("No direction container.")?;

        let has_matching_tiling_direction =
          TilingDirection::from_direction(direction)
            == target_parent.tiling_direction();

        let target_index = match direction {
          Direction::Down | Direction::Right
            if has_matching_tiling_direction =>
          {
            sibling_descendant.index()
          }
          _ => sibling_descendant.index() + 1,
        };

        move_container_within_tree(
          &window_to_move.into(),
          &target_parent.clone().into(),
          target_index,
          state,
        )?;

        state
          .pending_sync
          .queue_container_to_redraw(target_parent)
          .queue_containers_to_redraw(parent.tiling_children());
      }
    }
  }

  Ok(())
}

fn move_to_workspace_in_direction(
  window_to_move: &WindowContainer,
  direction: &Direction,
  state: &mut WmState,
) -> anyhow::Result<()> {
  let parent = window_to_move.parent().context("No parent.")?;
  let workspace = window_to_move.workspace().context("No workspace.")?;
  let monitor = parent.monitor().context("No monitor.")?;

  let target_workspace = state
    .monitor_in_direction(&monitor, direction)?
    .and_then(|monitor| monitor.displayed_workspace());

  if let Some(target_workspace) = target_workspace {
    // Since the window is crossing monitors, adjustments might need to be
    // made because of DPI.
    if monitor.has_dpi_difference(&target_workspace.clone().into())? {
      window_to_move.set_has_pending_dpi_adjustment(true);
    }

    // Update floating placement since the window has to cross monitors.
    window_to_move.set_floating_placement(
      window_to_move
        .floating_placement()
        .translate_to_center(&target_workspace.to_rect()?),
    );

    if let WindowContainer::NonTilingWindow(window_to_move) =
      &window_to_move
    {
      window_to_move.set_insertion_target(None);
    }

    let target_index = match direction {
      Direction::Down | Direction::Right => 0,
      _ => target_workspace.child_count(),
    };

    // Focus should be reassigned within the original workspace after the
    // window is moved out. For example, if the focus order is 1. tiling
    // window and 2. fullscreen window, then we'd want to retain focus on a
    // tiling window on move.
    let focus_target = state.focus_target_after_removal(window_to_move);

    move_container_within_tree(
      &window_to_move.clone().into(),
      &target_workspace.clone().into(),
      target_index,
      state,
    )?;

    if let Some(focus_target) = focus_target {
      set_focused_descendant(
        &focus_target,
        Some(&workspace.clone().into()),
      );
    }

    state
      .pending_sync
      .queue_container_to_redraw(window_to_move.clone())
      .queue_containers_to_redraw(target_workspace.tiling_children())
      .queue_containers_to_redraw(parent.tiling_children())
      .queue_cursor_jump()
      .queue_workspace_to_reorder(target_workspace);
  }

  Ok(())
}

fn invert_workspace_tiling_direction(
  window_to_move: TilingWindow,
  direction: &Direction,
  state: &mut WmState,
  config: &UserConfig,
) -> anyhow::Result<()> {
  let workspace = window_to_move.workspace().context("No workspace.")?;

  // Get top-level tiling children of the workspace.
  let workspace_children = workspace
    .tiling_children()
    .filter(|container| container.id() != window_to_move.id())
    .collect::<Vec<_>>();

  // Create a new split container to wrap the window's siblings. For
  // example, in the layout H[1 V[2 3]] where container 3 is moved down,
  // we create a split container around 1 and 2. This results in
  // H[H[1 V[2 3]]], and V[H[1 V[2]] 3] after the tiling direction change.
  if workspace_children.len() > 1 {
    let split_container = SplitContainer::new(
      workspace.tiling_direction(),
      config.value.gaps.clone(),
    );

    wrap_in_split_container(
      &split_container,
      &workspace.clone().into(),
      &workspace_children,
    )?;
  }

  // Invert the tiling direction of the workspace.
  workspace.set_tiling_direction(workspace.tiling_direction().inverse());

  let target_index = match direction {
    Direction::Left | Direction::Up => 0,
    _ => workspace.child_count(),
  };

  // Depending on the direction, place the window either before or after
  // the split container.
  move_container_within_tree(
    &window_to_move.clone().into(),
    &workspace.clone().into(),
    target_index,
    state,
  )?;

  // Workspace might have redundant split containers after the tiling
  // direction change. For example, V[H[1 2] 3] where container 3 is moved
  // up results in H[3 H[1 2]], and needs to be flattened to H[3 1 2].
  flatten_child_split_containers(&workspace.clone().into())?;

  // Resize the window such that the split container and window are each
  // 0.5.
  resize_tiling_container(&window_to_move.into(), 0.5);

  state
    .pending_sync
    .queue_containers_to_redraw(workspace.tiling_children());

  Ok(())
}

fn insert_into_ancestor(
  window_to_move: &TilingWindow,
  target_ancestor: &DirectionContainer,
  direction: &Direction,
  state: &mut WmState,
) -> anyhow::Result<()> {
  // Traverse upwards to find container whose parent is the target
  // ancestor. Then, depending on the direction, insert before or after
  // that container.
  let window_ancestor = window_to_move
    .ancestors()
    .find(|container| {
      container
        .parent()
        .is_some_and(|parent| parent == target_ancestor.clone().into())
    })
    .context("Window a
Download .txt
gitextract_qulwdvhw/

├── .cargo/
│   └── config.toml
├── .editorconfig
├── .gitattributes
├── .github/
│   └── workflows/
│       ├── build.yaml
│       ├── lint-check.yaml
│       ├── package.yaml
│       ├── pr-title-check.yaml
│       ├── release.yaml
│       └── winget-release.yaml
├── .gitignore
├── .vscode/
│   ├── launch.json
│   ├── settings.json
│   └── tasks.json
├── CLAUDE.md
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE.md
├── README.md
├── README_zh.md
├── clippy.toml
├── packages/
│   ├── wm/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   └── src/
│   │       ├── commands/
│   │       │   ├── container/
│   │       │   │   ├── attach_container.rs
│   │       │   │   ├── detach_container.rs
│   │       │   │   ├── flatten_child_split_containers.rs
│   │       │   │   ├── flatten_split_container.rs
│   │       │   │   ├── focus_container_by_id.rs
│   │       │   │   ├── focus_in_direction.rs
│   │       │   │   ├── mod.rs
│   │       │   │   ├── move_container_within_tree.rs
│   │       │   │   ├── replace_container.rs
│   │       │   │   ├── resize_tiling_container.rs
│   │       │   │   ├── set_focused_descendant.rs
│   │       │   │   ├── toggle_tiling_direction.rs
│   │       │   │   └── wrap_in_split_container.rs
│   │       │   ├── general/
│   │       │   │   ├── cycle_focus.rs
│   │       │   │   ├── disable_binding_mode.rs
│   │       │   │   ├── enable_binding_mode.rs
│   │       │   │   ├── mod.rs
│   │       │   │   ├── platform_sync.rs
│   │       │   │   ├── reload_config.rs
│   │       │   │   ├── shell_exec.rs
│   │       │   │   └── toggle_pause.rs
│   │       │   ├── mod.rs
│   │       │   ├── monitor/
│   │       │   │   ├── add_monitor.rs
│   │       │   │   ├── focus_monitor.rs
│   │       │   │   ├── mod.rs
│   │       │   │   ├── remove_monitor.rs
│   │       │   │   ├── sort_monitors.rs
│   │       │   │   └── update_monitor.rs
│   │       │   ├── window/
│   │       │   │   ├── ignore_window.rs
│   │       │   │   ├── manage_window.rs
│   │       │   │   ├── mod.rs
│   │       │   │   ├── move_window_in_direction.rs
│   │       │   │   ├── move_window_to_workspace.rs
│   │       │   │   ├── resize_window.rs
│   │       │   │   ├── run_window_rules.rs
│   │       │   │   ├── set_window_position.rs
│   │       │   │   ├── set_window_size.rs
│   │       │   │   ├── unmanage_window.rs
│   │       │   │   └── update_window_state.rs
│   │       │   └── workspace/
│   │       │       ├── activate_workspace.rs
│   │       │       ├── deactivate_workspace.rs
│   │       │       ├── focus_workspace.rs
│   │       │       ├── mod.rs
│   │       │       ├── move_workspace_in_direction.rs
│   │       │       ├── sort_workspaces.rs
│   │       │       └── update_workspace_config.rs
│   │       ├── events/
│   │       │   ├── handle_display_settings_changed.rs
│   │       │   ├── handle_mouse_move.rs
│   │       │   ├── handle_window_destroyed.rs
│   │       │   ├── handle_window_focused.rs
│   │       │   ├── handle_window_hidden.rs
│   │       │   ├── handle_window_minimize_ended.rs
│   │       │   ├── handle_window_minimized.rs
│   │       │   ├── handle_window_moved_or_resized.rs
│   │       │   ├── handle_window_moved_or_resized_end.rs
│   │       │   ├── handle_window_shown.rs
│   │       │   ├── handle_window_title_changed.rs
│   │       │   └── mod.rs
│   │       ├── ipc_server.rs
│   │       ├── main.rs
│   │       ├── models/
│   │       │   ├── container.rs
│   │       │   ├── insertion_target.rs
│   │       │   ├── mod.rs
│   │       │   ├── monitor.rs
│   │       │   ├── native_monitor_properties.rs
│   │       │   ├── native_window_properties.rs
│   │       │   ├── non_tiling_window.rs
│   │       │   ├── root_container.rs
│   │       │   ├── split_container.rs
│   │       │   ├── tiling_window.rs
│   │       │   ├── workspace.rs
│   │       │   └── workspace_target.rs
│   │       ├── pending_sync.rs
│   │       ├── sys_tray.rs
│   │       ├── traits/
│   │       │   ├── common_getters.rs
│   │       │   ├── mod.rs
│   │       │   ├── position_getters.rs
│   │       │   ├── tiling_direction_getters.rs
│   │       │   ├── tiling_size_getters.rs
│   │       │   └── window_getters.rs
│   │       ├── user_config.rs
│   │       ├── wm.rs
│   │       └── wm_state.rs
│   ├── wm-cli/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   └── src/
│   │       ├── lib.rs
│   │       └── main.rs
│   ├── wm-common/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── active_drag.rs
│   │       ├── app_command.rs
│   │       ├── display_state.rs
│   │       ├── dtos/
│   │       │   ├── container_dto.rs
│   │       │   ├── mod.rs
│   │       │   ├── monitor_dto.rs
│   │       │   ├── root_container_dto.rs
│   │       │   ├── split_container_dto.rs
│   │       │   ├── window_dto.rs
│   │       │   └── workspace_dto.rs
│   │       ├── hide_corner.rs
│   │       ├── ipc.rs
│   │       ├── lib.rs
│   │       ├── parsed_config.rs
│   │       ├── tiling_direction.rs
│   │       ├── utils/
│   │       │   ├── iterator_ext.rs
│   │       │   ├── mod.rs
│   │       │   ├── try_warn.rs
│   │       │   └── vec_deque_ext.rs
│   │       ├── window_state.rs
│   │       └── wm_event.rs
│   ├── wm-ipc-client/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── lib.rs
│   ├── wm-macros/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── common/
│   │       │   ├── attributes.rs
│   │       │   ├── branch.rs
│   │       │   ├── error_handling.rs
│   │       │   ├── mod.rs
│   │       │   ├── named_parameter.rs
│   │       │   ├── parenthesized.rs
│   │       │   ├── peekable.rs
│   │       │   └── spanned_string.rs
│   │       ├── enum_from_inner/
│   │       │   └── mod.rs
│   │       ├── lib.rs
│   │       └── subenum/
│   │           ├── enum_attrs.rs
│   │           ├── mod.rs
│   │           └── variant_attr.rs
│   ├── wm-platform/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   └── src/
│   │       ├── dispatcher.rs
│   │       ├── display.rs
│   │       ├── display_listener.rs
│   │       ├── error.rs
│   │       ├── event_loop.rs
│   │       ├── keybinding_listener.rs
│   │       ├── lib.rs
│   │       ├── models/
│   │       │   ├── color.rs
│   │       │   ├── corner_style.rs
│   │       │   ├── delta.rs
│   │       │   ├── direction.rs
│   │       │   ├── key.rs
│   │       │   ├── key_code.rs
│   │       │   ├── length_value.rs
│   │       │   ├── mod.rs
│   │       │   ├── opacity_value.rs
│   │       │   ├── point.rs
│   │       │   ├── rect.rs
│   │       │   └── rect_delta.rs
│   │       ├── mouse_listener.rs
│   │       ├── native_window.rs
│   │       ├── platform_event.rs
│   │       ├── platform_impl/
│   │       │   ├── macos/
│   │       │   │   ├── application.rs
│   │       │   │   ├── application_observer.rs
│   │       │   │   ├── ax_ui_element.rs
│   │       │   │   ├── ax_value.rs
│   │       │   │   ├── display.rs
│   │       │   │   ├── display_listener.rs
│   │       │   │   ├── event_loop.rs
│   │       │   │   ├── ffi.rs
│   │       │   │   ├── keyboard_hook.rs
│   │       │   │   ├── mod.rs
│   │       │   │   ├── mouse_listener.rs
│   │       │   │   ├── native_window.rs
│   │       │   │   ├── notification_center.rs
│   │       │   │   ├── single_instance.rs
│   │       │   │   └── window_listener.rs
│   │       │   ├── mod.rs
│   │       │   └── windows/
│   │       │       ├── com.rs
│   │       │       ├── display.rs
│   │       │       ├── display_listener.rs
│   │       │       ├── event_loop.rs
│   │       │       ├── keyboard_hook.rs
│   │       │       ├── mod.rs
│   │       │       ├── mouse_listener.rs
│   │       │       ├── native_window.rs
│   │       │       ├── single_instance.rs
│   │       │       └── window_listener.rs
│   │       ├── single_instance.rs
│   │       ├── test.rs
│   │       ├── thread_bound.rs
│   │       └── window_listener.rs
│   └── wm-watcher/
│       ├── Cargo.toml
│       ├── build.rs
│       └── src/
│           └── main.rs
├── resources/
│   ├── Info.plist
│   ├── assets/
│   │   └── sample-config.yaml
│   ├── scripts/
│   │   └── package.ps1
│   └── wix/
│       ├── bundle-theme.wxl
│       ├── bundle-theme.xml
│       ├── bundle.wxs
│       ├── standalone-ui.wxs
│       └── standalone.wxs
├── rust-toolchain.toml
└── rustfmt.toml
Download .txt
SYMBOL INDEX (1202 symbols across 158 files)

FILE: packages/wm-cli/build.rs
  function main (line 3) | fn main() {

FILE: packages/wm-cli/src/lib.rs
  function start (line 8) | pub async fn start(args: Vec<String>) -> anyhow::Result<()> {

FILE: packages/wm-cli/src/main.rs
  function main (line 8) | async fn main() -> anyhow::Result<()> {

FILE: packages/wm-common/src/active_drag.rs
  type ActiveDrag (line 5) | pub struct ActiveDrag {
  type ActiveDragOperation (line 22) | pub enum ActiveDragOperation {

FILE: packages/wm-common/src/app_command.rs
  constant VERSION (line 11) | const VERSION: &str = env!("VERSION_NUMBER");
  type AppCommand (line 15) | pub enum AppCommand {
    method parse_with_default (line 74) | pub fn parse_with_default(args: &Vec<String>) -> Self {
  type Verbosity (line 92) | pub struct Verbosity {
    method level (line 105) | pub fn level(&self) -> Level {
  type QueryCommand (line 115) | pub enum QueryCommand {
  type SubscribableEvent (line 137) | pub enum SubscribableEvent {
  type InvokeCommand (line 157) | pub enum InvokeCommand {
    method deserialize (line 266) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  type TitleBarVisibility (line 287) | pub enum TitleBarVisibility {
  type InvokeAdjustBordersCommand (line 294) | pub struct InvokeAdjustBordersCommand {
  type InvokeFocusCommand (line 311) | pub struct InvokeFocusCommand {
  type InvokeMoveCommand (line 352) | pub struct InvokeMoveCommand {
  type InvokeResizeCommand (line 389) | pub struct InvokeResizeCommand {
  type SetTransparencyCommand (line 399) | pub struct SetTransparencyCommand {
  type InvokePositionCommand (line 409) | pub struct InvokePositionCommand {
  type InvokeUpdateWorkspaceConfig (line 422) | pub struct InvokeUpdateWorkspaceConfig {

FILE: packages/wm-common/src/display_state.rs
  type DisplayState (line 7) | pub enum DisplayState {

FILE: packages/wm-common/src/dtos/container_dto.rs
  type ContainerDto (line 12) | pub enum ContainerDto {

FILE: packages/wm-common/src/dtos/monitor_dto.rs
  type MonitorDto (line 12) | pub struct MonitorDto {

FILE: packages/wm-common/src/dtos/root_container_dto.rs
  type RootContainerDto (line 11) | pub struct RootContainerDto {

FILE: packages/wm-common/src/dtos/split_container_dto.rs
  type SplitContainerDto (line 12) | pub struct SplitContainerDto {

FILE: packages/wm-common/src/dtos/window_dto.rs
  type WindowDto (line 12) | pub struct WindowDto {

FILE: packages/wm-common/src/dtos/workspace_dto.rs
  type WorkspaceDto (line 12) | pub struct WorkspaceDto {

FILE: packages/wm-common/src/hide_corner.rs
  type HideCorner (line 3) | pub enum HideCorner {

FILE: packages/wm-common/src/ipc.rs
  constant DEFAULT_IPC_PORT (line 6) | pub const DEFAULT_IPC_PORT: u32 = 6123;
  type ServerMessage (line 10) | pub enum ServerMessage {
  type ClientResponseMessage (line 17) | pub struct ClientResponseMessage {
  type ClientResponseData (line 26) | pub enum ClientResponseData {
  type AppMetadataData (line 42) | pub struct AppMetadataData {
  type BindingModesData (line 48) | pub struct BindingModesData {
  type CommandData (line 54) | pub struct CommandData {
  type EventSubscribeData (line 60) | pub struct EventSubscribeData {
  type FocusedData (line 66) | pub struct FocusedData {
  type MonitorsData (line 72) | pub struct MonitorsData {
  type TilingDirectionData (line 78) | pub struct TilingDirectionData {
  type WindowsData (line 85) | pub struct WindowsData {
  type WorkspacesData (line 91) | pub struct WorkspacesData {
  type EventSubscriptionMessage (line 97) | pub struct EventSubscriptionMessage {

FILE: packages/wm-common/src/parsed_config.rs
  type ParsedConfig (line 11) | pub struct ParsedConfig {
  type BindingModeConfig (line 24) | pub struct BindingModeConfig {
  type GapsConfig (line 39) | pub struct GapsConfig {
  method default (line 55) | fn default() -> Self {
  type GeneralConfig (line 72) | pub struct GeneralConfig {
  method default (line 102) | fn default() -> Self {
  type CursorJumpConfig (line 127) | pub struct CursorJumpConfig {
  type CursorJumpTrigger (line 137) | pub enum CursorJumpTrigger {
  type HideMethod (line 145) | pub enum HideMethod {
  type KeybindingConfig (line 154) | pub struct KeybindingConfig {
  type WindowBehaviorConfig (line 168) | pub struct WindowBehaviorConfig {
  type InitialWindowState (line 180) | pub enum InitialWindowState {
  type WindowStateDefaultsConfig (line 188) | pub struct WindowStateDefaultsConfig {
  type FloatingStateConfig (line 195) | pub struct FloatingStateConfig {
  method default (line 204) | fn default() -> Self {
  type FullscreenStateConfig (line 214) | pub struct FullscreenStateConfig {
  method default (line 223) | fn default() -> Self {
  type WindowEffectsConfig (line 233) | pub struct WindowEffectsConfig {
  type WindowEffectConfig (line 243) | pub struct WindowEffectConfig {
  type BorderEffectConfig (line 259) | pub struct BorderEffectConfig {
  method default (line 268) | fn default() -> Self {
  type HideTitleBarEffectConfig (line 283) | pub struct HideTitleBarEffectConfig {
  type CornerEffectConfig (line 290) | pub struct CornerEffectConfig {
  type TransparencyEffectConfig (line 300) | pub struct TransparencyEffectConfig {
  type WindowRuleConfig (line 310) | pub struct WindowRuleConfig {
  type WindowMatchConfig (line 325) | pub struct WindowMatchConfig {
  type MatchType (line 336) | pub enum MatchType {
    method is_match (line 347) | pub fn is_match(&self, value: &str) -> bool {
  type WindowRuleEvent (line 364) | pub enum WindowRuleEvent {
  type WorkspaceConfig (line 377) | pub struct WorkspaceConfig {
  function default_bool (line 391) | const fn default_bool<const V: bool>() -> bool {
  function default_window_rule_on (line 396) | fn default_window_rule_on() -> Vec<WindowRuleEvent> {
  function serialize_bindings (line 403) | fn serialize_bindings<S>(
  function deserialize_bindings (line 428) | fn deserialize_bindings<'de, D>(
  function deserialize_hide_method (line 454) | fn deserialize_hide_method<'de, D>(

FILE: packages/wm-common/src/tiling_direction.rs
  type TilingDirection (line 9) | pub enum TilingDirection {
    method inverse (line 24) | pub fn inverse(&self) -> Self {
    method from_direction (line 41) | pub fn from_direction(direction: &Direction) -> Self {
  type Err (line 50) | type Err = anyhow::Error;
  method from_str (line 64) | fn from_str(unparsed: &str) -> anyhow::Result<Self> {

FILE: packages/wm-common/src/utils/iterator_ext.rs
  type UniqueExt (line 4) | pub trait UniqueExt: Iterator {
    method unique_by (line 9) | fn unique_by<K, F>(self, key_fn: F) -> UniqueBy<Self, K, F>
    method unique_by (line 45) | fn unique_by<K, F>(self, key_fn: F) -> UniqueBy<Self, K, F>
  type UniqueBy (line 16) | pub struct UniqueBy<I: Iterator, K, F> {
  type Item (line 29) | type Item = I::Item;
  method next (line 31) | fn next(&mut self) -> Option<Self::Item> {

FILE: packages/wm-common/src/utils/vec_deque_ext.rs
  type VecDequeExt (line 3) | pub trait VecDequeExt<T>
    method shift_to_index (line 10) | fn shift_to_index(&mut self, target_index: usize, item: T);
  function shift_to_index (line 17) | fn shift_to_index(&mut self, target_index: usize, value: T) {

FILE: packages/wm-common/src/window_state.rs
  type WindowState (line 13) | pub enum WindowState {
    method default_from_config (line 22) | pub fn default_from_config(config: &ParsedConfig) -> Self {
    method is_same_state (line 32) | pub fn is_same_state(&self, other: &Self) -> bool {

FILE: packages/wm-common/src/wm_event.rs
  type WmEvent (line 16) | pub enum WmEvent {

FILE: packages/wm-ipc-client/src/lib.rs
  type IpcClient (line 15) | pub struct IpcClient {
    method connect (line 20) | pub async fn connect() -> anyhow::Result<Self> {
    method send (line 31) | pub async fn send(&mut self, message: &str) -> anyhow::Result<()> {
    method next_message (line 42) | pub async fn next_message(&mut self) -> anyhow::Result<ServerMessage> {
    method client_response (line 56) | pub async fn client_response(
    method event_subscription (line 71) | pub async fn event_subscription(

FILE: packages/wm-macros/src/common/attributes.rs
  type FindAttributes (line 8) | pub trait FindAttributes {
    method find_attrs (line 11) | fn find_attrs(
    method find_list_attrs (line 16) | fn find_list_attrs(
    method find_attrs (line 27) | fn find_attrs(
    method find_attrs (line 38) | fn find_attrs(

FILE: packages/wm-macros/src/common/branch.rs
  type ParseableTuple (line 9) | pub trait ParseableTuple
    method parse_tuple (line 20) | fn parse_tuple<Sep>(
  type PeekableTuple (line 31) | pub trait PeekableTuple
    method peek_parse_tuple (line 41) | fn peek_parse_tuple<Sep>(
  type Ordered (line 160) | pub struct Ordered<T, Sep>
  function parse (line 174) | fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
  function display (line 192) | fn display() -> &'static str {
  function peek (line 196) | fn peek<S>(stream: S) -> bool
  type Target (line 209) | type Target = T;
  function deref (line 211) | fn deref(&self) -> &Self::Target {
  type Unordered (line 243) | pub struct Unordered<T, Sep>
  function parse (line 257) | fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
  type Target (line 271) | type Target = T;
  function deref (line 273) | fn deref(&self) -> &Self::Target {
  type IfElse (line 299) | pub enum IfElse<If, Else>
  function is_if (line 315) | pub fn is_if(&self) -> bool {
  function is_else (line 319) | pub fn is_else(&self) -> bool {
  function parse (line 329) | fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
  type Optional (line 411) | pub enum Optional<T>
  function parse (line 423) | fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
  function display (line 440) | fn display() -> &'static str {
  function peek (line 444) | fn peek<S>(stream: S) -> bool
  function is_some (line 462) | pub fn is_some(&self) -> bool {
  function is_none (line 466) | pub fn is_none(&self) -> bool {
  function to_opt (line 471) | pub fn to_opt(self) -> Option<T> {

FILE: packages/wm-macros/src/common/error_handling.rs
  type ThenError (line 12) | pub trait ThenError<E>
    method then_error (line 25) | fn then_error(self, error: E) -> Result<Self, E>;
  function then_error (line 29) | fn then_error(self, error: E) -> Result<Self, E> {
  type ToError (line 36) | pub trait ToError {
    method error (line 46) | fn error<D: core::fmt::Display>(&self, message: D) -> syn::Error;
    method error (line 53) | fn error<D: core::fmt::Display>(&self, message: D) -> syn::Error {
  type ToSpanError (line 64) | pub trait ToSpanError {
    method serror (line 77) | fn serror<D: core::fmt::Display>(&self, message: D) -> syn::Error;
    method serror (line 84) | fn serror<D: core::fmt::Display>(&self, message: D) -> syn::Error {
  type EmitError (line 92) | pub trait EmitError {
    method emit_warning (line 94) | fn emit_warning<D: Into<String>>(&self, message: D);
    method emit_help (line 96) | fn emit_help<D: Into<String>>(&self, message: D);
    method emit_note (line 98) | fn emit_note<D: Into<String>>(&self, message: D);
    method emit_warning (line 105) | fn emit_warning<D: Into<String>>(&self, message: D) {
    method emit_help (line 109) | fn emit_help<D: Into<String>>(&self, message: D) {
    method emit_note (line 113) | fn emit_note<D: Into<String>>(&self, message: D) {

FILE: packages/wm-macros/src/common/named_parameter.rs
  type NamedParameter (line 24) | pub struct NamedParameter<Name, Param>
  function parse (line 38) | fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
  function peek (line 52) | fn peek<S>(stream: S) -> bool
  function display (line 59) | fn display() -> &'static str {

FILE: packages/wm-macros/src/common/parenthesized.rs
  type Parenthesized (line 23) | pub struct Parenthesized<T>(pub T)
  function parse (line 31) | fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
  type Target (line 42) | type Target = T;
  function deref (line 44) | fn deref(&self) -> &Self::Target {
  function deref_mut (line 53) | fn deref_mut(&mut self) -> &mut Self::Target {

FILE: packages/wm-macros/src/common/peekable.rs
  type PeekableStream (line 15) | pub trait PeekableStream {
    method is_empty (line 16) | fn is_empty(&self) -> bool;
    method peek (line 17) | fn peek<T: syn::parse::Peek>(&self, token: T) -> bool;
    method peek (line 21) | fn peek<T: syn::parse::Peek>(&self, token: T) -> bool {
    method is_empty (line 24) | fn is_empty(&self) -> bool {
    method peek (line 30) | fn peek<T: syn::parse::Peek>(&self, token: T) -> bool {
    method is_empty (line 34) | fn is_empty(&self) -> bool {
    method peek (line 39) | fn peek<T: syn::parse::Peek>(&self, token: T) -> bool {
    method is_empty (line 43) | fn is_empty(&self) -> bool {
    method peek (line 48) | fn peek<T: syn::parse::Peek>(&self, token: T) -> bool {
    method is_empty (line 52) | fn is_empty(&self) -> bool {
    method peek (line 57) | fn peek<T: syn::parse::Peek>(&self, token: T) -> bool {
    method is_empty (line 61) | fn is_empty(&self) -> bool {
  type Peekable (line 67) | pub trait Peekable {
    method peek (line 81) | fn peek<T>(stream: T) -> bool
    method display (line 86) | fn display() -> &'static str;
    method peek (line 101) | fn peek<S>(stream: S) -> bool
    method display (line 108) | fn display() -> &'static str {
  type SynPeek (line 92) | pub trait SynPeek {
    method peekable (line 93) | fn peekable() -> impl syn::parse::Peek;
    method display (line 96) | fn display() -> &'static str;
  function get_peek_display (line 116) | pub fn get_peek_display<T: syn::parse::Peek>(_peek: T) -> &'static str {
  type TPeek (line 132) | pub trait TPeek<'a> {
    method tpeek (line 133) | fn tpeek<T>(&'a self) -> bool
  method tpeek (line 142) | fn tpeek<U>(&'a self) -> bool

FILE: packages/wm-macros/src/common/spanned_string.rs
  type SpannedString (line 6) | pub struct SpannedString {
    method new (line 12) | pub fn new(value: String, span: proc_macro2::Span) -> Self {
    method from_lit_str (line 16) | pub fn from_lit_str(lit_str: syn::LitStr) -> Self {
    method from (line 37) | fn from(lit_str: syn::LitStr) -> Self {
    method parse (line 44) | fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
    method to_tokens (line 52) | fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
  method from (line 25) | fn from(spanned_string: SpannedString) -> Self {
  function from (line 31) | fn from(spanned_string: &SpannedString) -> Self {

FILE: packages/wm-macros/src/enum_from_inner/mod.rs
  function enum_from_inner (line 11) | pub fn enum_from_inner(

FILE: packages/wm-macros/src/lib.rs
  function sub_enum (line 88) | pub fn sub_enum(input: TokenStream) -> TokenStream {
  function enum_from_inner (line 117) | pub fn enum_from_inner(input: TokenStream) -> TokenStream {

FILE: packages/wm-macros/src/subenum/enum_attrs.rs
  function collect_sub_enums (line 9) | pub fn collect_sub_enums<'a>(
  type Subenum (line 19) | pub enum Subenum {
    method parse (line 25) | fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
  type SubenumDeclaration (line 42) | pub struct SubenumDeclaration {
    method parse (line 48) | fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
  type AttrBlock (line 60) | struct AttrBlock {
    method parse (line 65) | fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {

FILE: packages/wm-macros/src/subenum/mod.rs
  constant SUBENUM_ATTR_NAME (line 5) | const SUBENUM_ATTR_NAME: &str = "subenum";
  function sub_enum (line 10) | pub fn sub_enum(
  type SubEnum (line 184) | struct SubEnum<'a> {
  type Variant (line 194) | struct Variant {
    method to_tokens (line 217) | fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
  function to_tokens (line 200) | fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
  function combine_variants (line 227) | fn combine_variants(
  function from_sub_to_main_impl (line 255) | fn from_sub_to_main_impl(
  function try_from_main_to_sub_impl (line 280) | fn try_from_main_to_sub_impl(

FILE: packages/wm-macros/src/subenum/variant_attr.rs
  type SubenumVariant (line 6) | pub struct SubenumVariant {
  function parse_variant (line 13) | pub fn parse_variant(

FILE: packages/wm-platform/build.rs
  function main (line 1) | fn main() {

FILE: packages/wm-platform/src/dispatcher.rs
  type DispatchFn (line 56) | pub type DispatchFn = dyn FnOnce() + Send + 'static;
  type WndProcCallback (line 65) | pub type WndProcCallback =
  type DispatcherExtMacOs (line 70) | pub trait DispatcherExtMacOs {
    method all_applications (line 76) | fn all_applications(&self) -> crate::Result<Vec<Application>>;
    method has_ax_permission (line 86) | fn has_ax_permission(&self, prompt: bool) -> bool;
    method all_applications (line 91) | fn all_applications(&self) -> crate::Result<Vec<Application>> {
    method has_ax_permission (line 95) | fn has_ax_permission(&self, prompt: bool) -> bool {
  type DispatcherExtWindows (line 107) | pub trait DispatcherExtWindows {
    method message_window_handle (line 113) | fn message_window_handle(&self) -> isize;
    method register_wndproc_callback (line 124) | fn register_wndproc_callback(
    method deregister_wndproc_callback (line 134) | fn deregister_wndproc_callback(&self, id: usize) -> crate::Result<()>;
    method window_animations_enabled (line 141) | fn window_animations_enabled(&self) -> crate::Result<bool>;
    method set_window_animations_enabled (line 148) | fn set_window_animations_enabled(
    method expand_env_strings (line 163) | fn expand_env_strings(&self, input: &str) -> crate::Result<String>;
    method shell_execute_ex (line 174) | fn shell_execute_ex(
    method message_window_handle (line 185) | fn message_window_handle(&self) -> isize {
    method register_wndproc_callback (line 189) | fn register_wndproc_callback(
    method deregister_wndproc_callback (line 200) | fn deregister_wndproc_callback(&self, id: usize) -> crate::Result<()> {
    method window_animations_enabled (line 208) | fn window_animations_enabled(&self) -> crate::Result<bool> {
    method set_window_animations_enabled (line 227) | fn set_window_animations_enabled(
    method expand_env_strings (line 249) | fn expand_env_strings(&self, input: &str) -> crate::Result<String> {
    method shell_execute_ex (line 275) | fn shell_execute_ex(
  type Dispatcher (line 338) | pub struct Dispatcher {
    method new (line 346) | pub(crate) fn new(
    method stop_event_loop (line 357) | pub fn stop_event_loop(&self) -> crate::Result<()> {
    method dispatch_async (line 376) | pub fn dispatch_async<F>(&self, dispatch_fn: F) -> crate::Result<()>
    method dispatch_sync (line 410) | pub fn dispatch_sync<F, R>(&self, dispatch_fn: F) -> crate::Result<R>
    method thread_id (line 444) | pub fn thread_id(&self) -> ThreadId {
    method is_event_loop_thread (line 451) | fn is_event_loop_thread(&self) -> bool {
    method displays (line 460) | pub fn displays(&self) -> crate::Result<Vec<Display>> {
    method sorted_displays (line 473) | pub fn sorted_displays(&self) -> crate::Result<Vec<Display>> {
    method display_devices (line 506) | pub fn display_devices(&self) -> crate::Result<Vec<DisplayDevice>> {
    method display_from_point (line 513) | pub fn display_from_point(
    method primary_display (line 521) | pub fn primary_display(&self) -> crate::Result<Display> {
    method nearest_display (line 529) | pub fn nearest_display(
    method visible_windows (line 542) | pub fn visible_windows(&self) -> crate::Result<Vec<NativeWindow>> {
    method focused_window (line 549) | pub fn focused_window(&self) -> crate::Result<NativeWindow> {
    method cursor_position (line 554) | pub fn cursor_position(&self) -> crate::Result<Point> {
    method is_mouse_down (line 580) | pub fn is_mouse_down(&self, button: &MouseButton) -> bool {
    method window_from_point (line 607) | pub fn window_from_point(
    method set_cursor_position (line 615) | pub fn set_cursor_position(&self, point: &Point) -> crate::Result<()> {
    method reset_focus (line 638) | pub fn reset_focus(&self) -> crate::Result<()> {
    method open_file_explorer (line 648) | pub fn open_file_explorer(&self, path: &Path) -> crate::Result<()> {
    method show_error_dialog (line 671) | pub fn show_error_dialog(&self, title: &str, message: &str) {
    method fmt (line 706) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  function dispatch_after_stop_fails (line 718) | fn dispatch_after_stop_fails() {
  function dispatch_sync_executes_in_order (line 735) | fn dispatch_sync_executes_in_order() {
  function dispatch_sync_from_different_threads (line 763) | fn dispatch_sync_from_different_threads() {
  function dispatch_sync_with_nested (line 803) | fn dispatch_sync_with_nested() {

FILE: packages/wm-platform/src/display.rs
  type DisplayId (line 23) | pub struct DisplayId(
  type DisplayDeviceId (line 37) | pub struct DisplayDeviceId(pub String);
  type DisplayExtMacOs (line 41) | pub trait DisplayExtMacOs {
    method cg_display_id (line 43) | fn cg_display_id(&self) -> CGDirectDisplayID;
    method ns_screen (line 50) | fn ns_screen(&self) -> &ThreadBound<Retained<NSScreen>>;
    method cg_display_id (line 55) | fn cg_display_id(&self) -> CGDirectDisplayID {
    method ns_screen (line 59) | fn ns_screen(&self) -> &ThreadBound<Retained<NSScreen>> {
  type DisplayExtWindows (line 66) | pub trait DisplayExtWindows {
    method hmonitor (line 72) | fn hmonitor(&self) -> HMONITOR;
    method hmonitor (line 77) | fn hmonitor(&self) -> HMONITOR {
  type Display (line 90) | pub struct Display {
    method id (line 97) | pub fn id(&self) -> DisplayId {
    method name (line 102) | pub fn name(&self) -> crate::Result<String> {
    method bounds (line 107) | pub fn bounds(&self) -> crate::Result<Rect> {
    method working_area (line 112) | pub fn working_area(&self) -> crate::Result<Rect> {
    method scale_factor (line 117) | pub fn scale_factor(&self) -> crate::Result<f32> {
    method dpi (line 122) | pub fn dpi(&self) -> crate::Result<u32> {
    method is_primary (line 127) | pub fn is_primary(&self) -> crate::Result<bool> {
    method devices (line 136) | pub fn devices(&self) -> crate::Result<Vec<DisplayDevice>> {
    method main_device (line 141) | pub fn main_device(&self) -> crate::Result<DisplayDevice> {
  type ConnectionState (line 148) | pub enum ConnectionState {
  type MirroringState (line 161) | pub enum MirroringState {
  type OutputTechnology (line 171) | pub enum OutputTechnology {
  type DisplayDeviceExtMacOs (line 194) | pub trait DisplayDeviceExtMacOs {
    method cg_display_id (line 200) | fn cg_display_id(&self) -> CGDirectDisplayID;
    method cg_display_id (line 205) | fn cg_display_id(&self) -> CGDirectDisplayID {
  type DisplayDeviceExtWindows (line 212) | pub trait DisplayDeviceExtWindows {
    method device_path (line 220) | fn device_path(&self) -> Option<String>;
    method hardware_id (line 234) | fn hardware_id(&self) -> Option<String>;
    method output_technology (line 241) | fn output_technology(&self) -> crate::Result<Option<OutputTechnology>>;
    method device_path (line 246) | fn device_path(&self) -> Option<String> {
    method hardware_id (line 250) | fn hardware_id(&self) -> Option<String> {
    method output_technology (line 254) | fn output_technology(&self) -> crate::Result<Option<OutputTechnology>> {
  type DisplayDevice (line 264) | pub struct DisplayDevice {
    method id (line 271) | pub fn id(&self) -> DisplayDeviceId {
    method rotation (line 276) | pub fn rotation(&self) -> crate::Result<f32> {
    method refresh_rate (line 281) | pub fn refresh_rate(&self) -> crate::Result<f32> {
    method is_builtin (line 288) | pub fn is_builtin(&self) -> crate::Result<bool> {
    method connection_state (line 293) | pub fn connection_state(&self) -> crate::Result<ConnectionState> {
    method mirroring_state (line 298) | pub fn mirroring_state(&self) -> crate::Result<Option<MirroringState>> {
  function test_nearest_display (line 309) | fn test_nearest_display() {

FILE: packages/wm-platform/src/display_listener.rs
  type DisplayListener (line 9) | pub struct DisplayListener {
    method new (line 18) | pub fn new(dispatcher: &Dispatcher) -> crate::Result<Self> {
    method next_event (line 27) | pub async fn next_event(&mut self) -> Option<()> {
    method terminate (line 32) | pub fn terminate(&mut self) -> crate::Result<()> {

FILE: packages/wm-platform/src/error.rs
  type Error (line 2) | pub enum Error {
  type ParseError (line 80) | pub enum ParseError {
  type Result (line 106) | pub type Result<T> = std::result::Result<T, Error>;

FILE: packages/wm-platform/src/event_loop.rs
  type EventLoop (line 16) | pub struct EventLoop {
    method new (line 24) | pub fn new() -> crate::Result<(Self, Dispatcher)> {
    method run (line 43) | pub fn run(self) -> crate::Result<()> {
  function event_loop_start_stop (line 55) | fn event_loop_start_stop() {

FILE: packages/wm-platform/src/keybinding_listener.rs
  constant MODIFIER_GROUPS (line 19) | const MODIFIER_GROUPS: &[(Key, &[Key])] = &[
  type Keybinding (line 37) | pub struct Keybinding(Vec<Key>);
    method new (line 45) | pub fn new(keys: Vec<Key>) -> crate::Result<Self> {
    method keys (line 55) | pub fn keys(&self) -> &[Key] {
    method trigger_key (line 62) | pub fn trigger_key(&self) -> &Key {
  type KeybindingListener (line 71) | pub struct KeybindingListener {
    method new (line 91) | pub fn new(
    method next_event (line 120) | pub async fn next_event(&mut self) -> Option<KeybindingEvent> {
    method update (line 129) | pub fn update(&self, keybindings: &[Keybinding]) {
    method enable (line 135) | pub fn enable(&mut self, enabled: bool) {
    method terminate (line 140) | pub fn terminate(&mut self) -> crate::Result<()> {
    method create_keyboard_hook (line 145) | fn create_keyboard_hook(
    method create_keybinding_map (line 221) | fn create_keybinding_map(
  method drop (line 238) | fn drop(&mut self) {

FILE: packages/wm-platform/src/models/color.rs
  type Color (line 6) | pub struct Color {
    method to_bgr (line 16) | pub fn to_bgr(&self) -> u32 {
    method deserialize (line 54) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  type Err (line 24) | type Err = crate::ParseError;
  method from_str (line 26) | fn from_str(unparsed: &str) -> Result<Self, crate::ParseError> {

FILE: packages/wm-platform/src/models/corner_style.rs
  type CornerStyle (line 10) | pub enum CornerStyle {

FILE: packages/wm-platform/src/models/delta.rs
  type Delta (line 8) | pub struct Delta<T> {
  type Err (line 14) | type Err = crate::ParseError;
  method from_str (line 16) | fn from_str(unparsed: &str) -> Result<Self, crate::ParseError> {

FILE: packages/wm-platform/src/models/direction.rs
  type Direction (line 7) | pub enum Direction {
    method inverse (line 24) | pub fn inverse(&self) -> Direction {
  type Err (line 35) | type Err = crate::ParseError;
  method from_str (line 46) | fn from_str(unparsed: &str) -> Result<Self, crate::ParseError> {

FILE: packages/wm-platform/src/models/key.rs
  type KeyCode (line 26) | pub struct KeyCode(
    method fmt (line 32) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type KeyParseError (line 38) | pub enum KeyParseError {
  type Key (line 49) | pub enum Key {
    method try_from_literal (line 218) | pub fn try_from_literal(key_str: &str) -> Result<Self, KeyParseError> {
  function test_key_parsing (line 427) | fn test_key_parsing() {
  function test_key_display (line 445) | fn test_key_display() {

FILE: packages/wm-platform/src/models/key_code.rs
  type KeyConversionError (line 25) | pub enum KeyConversionError {
  function test_key_conversion_roundtrip (line 255) | fn test_key_conversion_roundtrip() {
  function test_platform_specific_key_code (line 282) | fn test_platform_specific_key_code() {

FILE: packages/wm-platform/src/models/length_value.rs
  type LengthValue (line 7) | pub struct LengthValue {
    method from_px (line 21) | pub fn from_px(px: i32) -> Self {
    method to_px (line 30) | pub fn to_px(&self, total_px: i32, scale_factor: Option<f32>) -> i32 {
    method to_percentage (line 41) | pub fn to_percentage(&self, total_px: i32) -> f32 {
    method deserialize (line 100) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  type LengthUnit (line 14) | pub enum LengthUnit {
  type Err (line 51) | type Err = crate::ParseError;
  method from_str (line 67) | fn from_str(unparsed: &str) -> Result<Self, crate::ParseError> {

FILE: packages/wm-platform/src/models/opacity_value.rs
  type OpacityValue (line 6) | pub struct OpacityValue(pub f32);
    method to_alpha (line 10) | pub fn to_alpha(&self) -> u8 {
    method from_alpha (line 17) | pub fn from_alpha(alpha: u8) -> Self {
    method deserialize (line 63) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  method default (line 23) | fn default() -> Self {
  type Err (line 29) | type Err = crate::ParseError;
  method from_str (line 42) | fn from_str(unparsed: &str) -> Result<Self, crate::ParseError> {

FILE: packages/wm-platform/src/models/point.rs
  type Point (line 3) | pub struct Point {
    method distance_between (line 12) | pub fn distance_between(&self, other: &Point) -> f32 {

FILE: packages/wm-platform/src/models/rect.rs
  type Corner (line 6) | pub enum Corner {
  type Rect (line 14) | pub struct Rect {
    method from_ltrb (line 32) | pub fn from_ltrb(left: i32, top: i32, right: i32, bottom: i32) -> Self {
    method from_xy (line 43) | pub fn from_xy(x: i32, y: i32, width: i32, height: i32) -> Self {
    method x (line 53) | pub fn x(&self) -> i32 {
    method y (line 58) | pub fn y(&self) -> i32 {
    method width (line 63) | pub fn width(&self) -> i32 {
    method height (line 68) | pub fn height(&self) -> i32 {
    method translate_to_coordinates (line 73) | pub fn translate_to_coordinates(&self, x: i32, y: i32) -> Self {
    method translate_to_center (line 78) | pub fn translate_to_center(&self, outer_rect: &Rect) -> Self {
    method translate_in_direction (line 87) | pub fn translate_in_direction(
    method clamp (line 111) | pub fn clamp(&self, outer_rect: &Rect) -> Self {
    method clamp_size (line 121) | pub fn clamp_size(&self, width: i32, height: i32) -> Self {
    method center_point (line 131) | pub fn center_point(&self) -> Point {
    method corner (line 139) | pub fn corner(&self, corner: &Corner) -> Point {
    method delta (line 162) | pub fn delta(&self, other: &Rect) -> RectDelta {
    method apply_delta (line 172) | pub fn apply_delta(
    method x_overlap (line 187) | pub fn x_overlap(&self, other: &Rect) -> i32 {
    method y_overlap (line 193) | pub fn y_overlap(&self, other: &Rect) -> i32 {
    method intersection_area (line 199) | pub fn intersection_area(&self, other: &Rect) -> i32 {
    method contains_point (line 211) | pub fn contains_point(&self, point: &Point) -> bool {
    method contains_rect (line 219) | pub fn contains_rect(&self, other: &Rect) -> bool {
    method inset (line 232) | pub fn inset(&self, inset_px: i32) -> Self {
    method distance_to_point (line 242) | pub fn distance_to_point(&self, point: &Point) -> f32 {
    method union (line 260) | pub fn union(&self, other: &Rect) -> Self {
  function intersection_area (line 275) | fn intersection_area() {

FILE: packages/wm-platform/src/models/rect_delta.rs
  type RectDelta (line 6) | pub struct RectDelta {
    method new (line 22) | pub fn new(
    method is_significant (line 39) | pub fn is_significant(&self) -> bool {
    method zero (line 48) | pub fn zero() -> Self {
    method inverse (line 61) | pub fn inverse(&self) -> Self {

FILE: packages/wm-platform/src/mouse_listener.rs
  type MouseEventKind (line 7) | pub enum MouseEventKind {
  type MouseListener (line 16) | pub struct MouseListener {
    method new (line 26) | pub fn new(
    method next_event (line 43) | pub async fn next_event(&mut self) -> Option<MouseEvent> {
    method enable (line 48) | pub fn enable(&mut self, enabled: bool) -> crate::Result<()> {
    method set_enabled_events (line 53) | pub fn set_enabled_events(
    method terminate (line 61) | pub fn terminate(&mut self) -> crate::Result<()> {

FILE: packages/wm-platform/src/native_window.rs
  type WindowId (line 28) | pub struct WindowId(
    method from_window_element (line 35) | pub(crate) fn from_window_element(el: &CFRetained<AXUIElement>) -> Self {
  type WindowZOrder (line 50) | pub enum WindowZOrder {
  type NativeWindowExtMacOs (line 59) | pub trait NativeWindowExtMacOs {
    method ax_ui_element (line 65) | fn ax_ui_element(&self) -> &ThreadBound<CFRetained<AXUIElement>>;
    method bundle_id (line 72) | fn bundle_id(&self) -> Option<String>;
    method role (line 79) | fn role(&self) -> crate::Result<String>;
    method subrole (line 86) | fn subrole(&self) -> crate::Result<String>;
    method is_modal (line 93) | fn is_modal(&self) -> crate::Result<bool>;
    method is_main (line 100) | fn is_main(&self) -> crate::Result<bool>;
    method ax_ui_element (line 105) | fn ax_ui_element(&self) -> &ThreadBound<CFRetained<AXUIElement>> {
    method bundle_id (line 109) | fn bundle_id(&self) -> Option<String> {
    method role (line 113) | fn role(&self) -> crate::Result<String> {
    method subrole (line 120) | fn subrole(&self) -> crate::Result<String> {
    method is_modal (line 127) | fn is_modal(&self) -> crate::Result<bool> {
    method is_main (line 134) | fn is_main(&self) -> crate::Result<bool> {
  type NativeWindowWindowsExt (line 144) | pub trait NativeWindowWindowsExt {
    method from_handle (line 150) | fn from_handle(handle: isize) -> NativeWindow;
    method hwnd (line 157) | fn hwnd(&self) -> HWND;
    method class_name (line 164) | fn class_name(&self) -> crate::Result<String>;
    method frame_with_shadows (line 171) | fn frame_with_shadows(&self) -> crate::Result<Rect>;
    method shadow_borders (line 179) | fn shadow_borders(&self) -> crate::Result<RectDelta>;
    method has_owner_window (line 186) | fn has_owner_window(&self) -> bool;
    method has_window_style (line 193) | fn has_window_style(&self, style: WINDOW_STYLE) -> bool;
    method has_window_style_ex (line 200) | fn has_window_style_ex(&self, style: WINDOW_EX_STYLE) -> bool;
    method set_window_pos (line 207) | fn set_window_pos(
    method show (line 221) | fn show(&self) -> crate::Result<()>;
    method hide (line 228) | fn hide(&self) -> crate::Result<()>;
    method restore (line 239) | fn restore(&self, outer_frame: Option<&Rect>) -> crate::Result<()>;
    method set_cloaked (line 246) | fn set_cloaked(&self, cloaked: bool) -> crate::Result<()>;
    method mark_fullscreen (line 256) | fn mark_fullscreen(&self, fullscreen: bool) -> crate::Result<()>;
    method set_taskbar_visibility (line 267) | fn set_taskbar_visibility(&self, visible: bool) -> crate::Result<()>;
    method add_window_style_ex (line 274) | fn add_window_style_ex(&self, style: WINDOW_EX_STYLE);
    method set_z_order (line 281) | fn set_z_order(&self, zorder: &WindowZOrder) -> crate::Result<()>;
    method set_title_bar_visibility (line 288) | fn set_title_bar_visibility(&self, visible: bool) -> crate::Result<()>;
    method set_border_color (line 295) | fn set_border_color(&self, color: Option<&Color>) -> crate::Result<()>;
    method set_corner_style (line 302) | fn set_corner_style(
    method set_transparency (line 312) | fn set_transparency(
    method adjust_transparency (line 322) | fn adjust_transparency(
    method from_handle (line 330) | fn from_handle(handle: isize) -> Self {
    method hwnd (line 334) | fn hwnd(&self) -> HWND {
    method class_name (line 338) | fn class_name(&self) -> crate::Result<String> {
    method frame_with_shadows (line 342) | fn frame_with_shadows(&self) -> crate::Result<Rect> {
    method shadow_borders (line 346) | fn shadow_borders(&self) -> crate::Result<RectDelta> {
    method has_owner_window (line 350) | fn has_owner_window(&self) -> bool {
    method has_window_style (line 354) | fn has_window_style(&self, style: WINDOW_STYLE) -> bool {
    method has_window_style_ex (line 358) | fn has_window_style_ex(&self, style: WINDOW_EX_STYLE) -> bool {
    method set_window_pos (line 362) | fn set_window_pos(
    method show (line 371) | fn show(&self) -> crate::Result<()> {
    method hide (line 375) | fn hide(&self) -> crate::Result<()> {
    method restore (line 379) | fn restore(&self, outer_frame: Option<&Rect>) -> crate::Result<()> {
    method set_cloaked (line 383) | fn set_cloaked(&self, cloaked: bool) -> crate::Result<()> {
    method mark_fullscreen (line 387) | fn mark_fullscreen(&self, fullscreen: bool) -> crate::Result<()> {
    method set_taskbar_visibility (line 391) | fn set_taskbar_visibility(&self, visible: bool) -> crate::Result<()> {
    method add_window_style_ex (line 395) | fn add_window_style_ex(&self, style: WINDOW_EX_STYLE) {
    method set_z_order (line 399) | fn set_z_order(&self, z_order: &WindowZOrder) -> crate::Result<()> {
    method set_title_bar_visibility (line 403) | fn set_title_bar_visibility(&self, visible: bool) -> crate::Result<()> {
    method set_border_color (line 407) | fn set_border_color(&self, color: Option<&Color>) -> crate::Result<()> {
    method set_corner_style (line 411) | fn set_corner_style(
    method set_transparency (line 418) | fn set_transparency(
    method adjust_transparency (line 425) | fn adjust_transparency(
  type NativeWindow (line 434) | pub struct NativeWindow {
    method id (line 441) | pub fn id(&self) -> WindowId {
    method title (line 452) | pub fn title(&self) -> crate::Result<String> {
    method process_name (line 456) | pub fn process_name(&self) -> crate::Result<String> {
    method frame (line 469) | pub fn frame(&self) -> crate::Result<Rect> {
    method position (line 474) | pub fn position(&self) -> crate::Result<(f64, f64)> {
    method size (line 479) | pub fn size(&self) -> crate::Result<(f64, f64)> {
    method is_valid (line 487) | pub fn is_valid(&self) -> bool {
    method is_visible (line 492) | pub fn is_visible(&self) -> crate::Result<bool> {
    method is_minimized (line 497) | pub fn is_minimized(&self) -> crate::Result<bool> {
    method is_maximized (line 502) | pub fn is_maximized(&self) -> crate::Result<bool> {
    method is_resizable (line 507) | pub fn is_resizable(&self) -> crate::Result<bool> {
    method is_desktop_window (line 512) | pub fn is_desktop_window(&self) -> crate::Result<bool> {
    method set_frame (line 523) | pub fn set_frame(&self, rect: &Rect) -> crate::Result<()> {
    method resize (line 528) | pub fn resize(&self, width: i32, height: i32) -> crate::Result<()> {
    method reposition (line 533) | pub fn reposition(&self, x: i32, y: i32) -> crate::Result<()> {
    method minimize (line 537) | pub fn minimize(&self) -> crate::Result<()> {
    method maximize (line 541) | pub fn maximize(&self) -> crate::Result<()> {
    method focus (line 546) | pub fn focus(&self) -> crate::Result<()> {
    method close (line 557) | pub fn close(&self) -> crate::Result<()> {
  method eq (line 563) | fn eq(&self, other: &Self) -> bool {

FILE: packages/wm-platform/src/platform_event.rs
  type PlatformEvent (line 8) | pub enum PlatformEvent {
  type WindowEvent (line 16) | pub enum WindowEvent {
    method window (line 84) | pub fn window(&self) -> Option<&NativeWindow> {
    method notification (line 99) | pub fn notification(&self) -> &WindowEventNotification {
  type WindowEventNotification (line 122) | pub struct WindowEventNotification(
  type KeybindingEvent (line 127) | pub struct KeybindingEvent(pub Keybinding);
  type MouseButton (line 130) | pub enum MouseButton {
  type PressedButtons (line 137) | pub struct PressedButtons {
    method contains (line 145) | pub fn contains(&self, button: &MouseButton) -> bool {
    method update (line 153) | pub(crate) fn update(&mut self, event: MouseEventKind) {
  type MouseEvent (line 165) | pub enum MouseEvent {
    method position (line 200) | pub fn position(&self) -> &Point {
    method pressed_buttons (line 210) | pub fn pressed_buttons(&self) -> &PressedButtons {

FILE: packages/wm-platform/src/platform_impl/macos/application.rs
  type ProcessId (line 16) | pub type ProcessId = i32;
  type Application (line 20) | pub struct Application {
    method new (line 29) | pub(crate) fn new(
    method focused_window (line 50) | pub fn focused_window(
    method windows (line 66) | pub fn windows(&self) -> crate::Result<Vec<crate::NativeWindow>> {
    method psn (line 84) | pub fn psn(&self) -> crate::Result<ffi::ProcessSerialNumber> {
    method bundle_id (line 96) | pub fn bundle_id(&self) -> Option<String> {
    method process_name (line 103) | pub fn process_name(&self) -> Option<String> {
    method is_xpc (line 116) | pub fn is_xpc(&self) -> crate::Result<bool> {
    method activation_policy (line 138) | pub fn activation_policy(&self) -> NSApplicationActivationPolicy {
    method should_observe (line 143) | pub(crate) fn should_observe(&self) -> bool {
    method is_hidden (line 153) | pub(crate) fn is_hidden(&self) -> bool {
  function all_applications (line 158) | pub(crate) fn all_applications(
  function application_for_bundle_id (line 172) | pub(crate) fn application_for_bundle_id(

FILE: packages/wm-platform/src/platform_impl/macos/application_observer.rs
  constant AX_APP_NOTIFICATIONS (line 20) | const AX_APP_NOTIFICATIONS: &[&str] =
  constant AX_WINDOW_NOTIFICATIONS (line 24) | const AX_WINDOW_NOTIFICATIONS: &[&str] = &[
  type ApplicationEventContext (line 35) | struct ApplicationEventContext {
  type ApplicationObserver (line 44) | pub(crate) struct ApplicationObserver {
    method new (line 60) | pub fn new(
    method register_app_notifications (line 145) | fn register_app_notifications(
    method register_window_notifications (line 171) | fn register_window_notifications(
    method emit_all_windows_destroyed (line 199) | pub(crate) fn emit_all_windows_destroyed(&self) {
    method emit_all_windows_hidden (line 214) | pub(crate) fn emit_all_windows_hidden(&self) {
    method emit_all_windows_shown (line 229) | pub(crate) fn emit_all_windows_shown(&self) {
    method window_event_callback (line 246) | unsafe extern "C-unwind" fn window_event_callback(
  method drop (line 381) | fn drop(&mut self) {

FILE: packages/wm-platform/src/platform_impl/macos/ax_ui_element.rs
  type AXUIElementExt (line 9) | pub trait AXUIElementExt {
    method get_attribute (line 17) | fn get_attribute<T: objc2_core_foundation::Type>(
    method set_attribute (line 27) | fn set_attribute<T: objc2_core_foundation::Type + AsRef<CFType>>(
    method get_attribute (line 35) | fn get_attribute<T: objc2_core_foundation::Type>(
    method set_attribute (line 64) | fn set_attribute<T: objc2_core_foundation::Type + AsRef<CFType>>(
  function get_attribute_invalid_attribute_is_err (line 88) | fn get_attribute_invalid_attribute_is_err() {
  function set_attribute_invalid_attribute_is_err (line 99) | fn set_attribute_invalid_attribute_is_err() {

FILE: packages/wm-platform/src/platform_impl/macos/ax_value.rs
  type AXValueTypeMarker (line 9) | pub trait AXValueTypeMarker: Sized + Copy {
    constant AX_TYPE (line 11) | const AX_TYPE: AXValueType;
    constant AX_TYPE (line 15) | const AX_TYPE: AXValueType = AXValueType::CGPoint;
    constant AX_TYPE (line 19) | const AX_TYPE: AXValueType = AXValueType::CGSize;
    constant AX_TYPE (line 23) | const AX_TYPE: AXValueType = AXValueType::CGRect;
    constant AX_TYPE (line 27) | const AX_TYPE: AXValueType = AXValueType::CFRange;
  type AXValueExt (line 31) | pub trait AXValueExt {
    method new_strict (line 39) | fn new_strict<T: AXValueTypeMarker>(
    method value_strict (line 52) | fn value_strict<T: AXValueTypeMarker>(&self) -> crate::Result<T>;
    method new_strict (line 56) | fn new_strict<T: AXValueTypeMarker>(
    method value_strict (line 72) | fn value_strict<T: AXValueTypeMarker>(&self) -> crate::Result<T> {
  function test_ax_value_creation_and_extraction (line 99) | fn test_ax_value_creation_and_extraction() {
  function test_ax_value_wrong_type_extraction (line 113) | fn test_ax_value_wrong_type_extraction() {

FILE: packages/wm-platform/src/platform_impl/macos/display.rs
  type Display (line 20) | pub(crate) struct Display {
    method new (line 27) | pub(crate) fn new(
    method id (line 49) | pub(crate) fn id(&self) -> DisplayId {
    method name (line 54) | pub(crate) fn name(&self) -> crate::Result<String> {
    method bounds (line 63) | pub(crate) fn bounds(&self) -> crate::Result<Rect> {
    method working_area (line 76) | pub(crate) fn working_area(&self) -> crate::Result<Rect> {
    method scale_factor (line 100) | pub(crate) fn scale_factor(&self) -> crate::Result<f32> {
    method dpi (line 108) | pub(crate) fn dpi(&self) -> crate::Result<u32> {
    method is_primary (line 117) | pub(crate) fn is_primary(&self) -> crate::Result<bool> {
    method devices (line 123) | pub(crate) fn devices(
    method main_device (line 136) | pub(crate) fn main_device(&self) -> crate::Result<crate::DisplayDevice> {
    method cg_display_id (line 150) | pub(crate) fn cg_display_id(&self) -> CGDirectDisplayID {
    method ns_screen (line 155) | pub(crate) fn ns_screen(&self) -> &ThreadBound<Retained<NSScreen>> {
  function appkit_rect_to_cg_rect (line 167) | fn appkit_rect_to_cg_rect(
  function from (line 184) | fn from(display: Display) -> Self {
  method eq (line 190) | fn eq(&self, other: &Self) -> bool {
  type DisplayDevice (line 199) | pub(crate) struct DisplayDevice {
    method new (line 207) | pub(crate) fn new(
    method id (line 218) | pub(crate) fn id(&self) -> DisplayDeviceId {
    method rotation (line 230) | pub(crate) fn rotation(&self) -> crate::Result<f32> {
    method refresh_rate (line 236) | pub(crate) fn refresh_rate(&self) -> crate::Result<f32> {
    method is_builtin (line 250) | pub(crate) fn is_builtin(&self) -> crate::Result<bool> {
    method connection_state (line 258) | pub(crate) fn connection_state(&self) -> crate::Result<ConnectionState> {
    method mirroring_state (line 271) | pub(crate) fn mirroring_state(
    method cg_display_id (line 314) | pub(crate) fn cg_display_id(&self) -> CGDirectDisplayID {
  function from (line 320) | fn from(device: DisplayDevice) -> Self {
  function cg_display_uuid (line 328) | fn cg_display_uuid(
  function all_displays (line 342) | pub(crate) fn all_displays(
  function all_display_devices (line 361) | pub(crate) fn all_display_devices(
  function display_from_point (line 394) | pub(crate) fn display_from_point(
  function primary_display (line 411) | pub(crate) fn primary_display(
  function nearest_display (line 433) | pub(crate) fn nearest_display(

FILE: packages/wm-platform/src/platform_impl/macos/display_listener.rs
  type DisplayListener (line 15) | pub(crate) struct DisplayListener {
    method new (line 22) | pub(crate) fn new(
    method terminate (line 38) | pub(crate) fn terminate(&mut self) -> crate::Result<()> {
    method add_observers (line 50) | fn add_observers(
  method drop (line 150) | fn drop(&mut self) {

FILE: packages/wm-platform/src/platform_impl/macos/event_loop.rs
  type EventLoopSource (line 17) | pub(crate) struct EventLoopSource {
    method send_dispatch_async (line 25) | pub(crate) fn send_dispatch_async<F>(
    method send_dispatch_sync (line 53) | pub(crate) fn send_dispatch_sync<F>(
    method send_stop (line 73) | pub(crate) fn send_stop(&self) -> crate::Result<()> {
  type EventLoop (line 102) | pub(crate) struct EventLoop {
    method new (line 109) | pub fn new() -> crate::Result<(Self, Dispatcher)> {
    method run (line 128) | pub fn run(self) -> crate::Result<()> {
    method add_dispatch_source (line 143) | pub(crate) fn add_dispatch_source() -> crate::Result<EventLoopSource> {
    method runloop_signaled_callback (line 194) | extern "C-unwind" fn runloop_signaled_callback(
    method runloop_source_released_callback (line 209) | extern "C-unwind" fn runloop_source_released_callback(
  method drop (line 222) | fn drop(&mut self) {

FILE: packages/wm-platform/src/platform_impl/macos/ffi.rs
  type ProcessSerialNumber (line 13) | pub struct ProcessSerialNumber {
  type ProcessInfo (line 21) | pub(crate) struct ProcessInfo {
  constant CPS_USER_GENERATED (line 37) | pub const CPS_USER_GENERATED: u32 = 0x200;
  function GetProcessForPID (line 42) | pub(crate) fn GetProcessForPID(
  function GetProcessInformation (line 48) | pub(crate) fn GetProcessInformation(
  function CGDisplayCreateUUIDFromDisplayID (line 55) | pub(crate) fn CGDisplayCreateUUIDFromDisplayID(
  function _AXUIElementGetWindow (line 61) | pub(crate) fn _AXUIElementGetWindow(
  function _SLPSSetFrontProcessWithOptions (line 69) | pub(crate) fn _SLPSSetFrontProcessWithOptions(
  function SLPSPostEventRecordTo (line 75) | pub(crate) fn SLPSPostEventRecordTo(

FILE: packages/wm-platform/src/platform_impl/macos/keyboard_hook.rs
  type KeyEvent (line 15) | pub struct KeyEvent {
    method is_key_down (line 32) | pub fn is_key_down(&self, key: Key) -> bool {
  type CallbackData (line 63) | struct CallbackData {
  type KeyboardHook (line 69) | pub struct KeyboardHook {
    method new (line 82) | pub fn new<F>(
    method terminate (line 113) | pub fn terminate(&mut self) -> crate::Result<()> {
    method create_event_tap (line 130) | fn create_event_tap(
    method keyboard_event_callback (line 175) | extern "C-unwind" fn keyboard_event_callback(
  method drop (line 220) | fn drop(&mut self) {

FILE: packages/wm-platform/src/platform_impl/macos/mouse_listener.rs
  type CallbackData (line 23) | struct CallbackData {
    method new (line 34) | fn new(event_tx: mpsc::UnboundedSender<MouseEvent>) -> Self {
  type MouseListener (line 45) | pub(crate) struct MouseListener {
    method new (line 58) | pub(crate) fn new(
    method enable (line 92) | pub(crate) fn enable(&mut self, enabled: bool) -> crate::Result<()> {
    method set_enabled_events (line 101) | pub(crate) fn set_enabled_events(
    method terminate (line 135) | pub(crate) fn terminate(&mut self) -> crate::Result<()> {
    method create_event_tap (line 152) | fn create_event_tap(
    method event_mask_from_enabled (line 194) | fn event_mask_from_enabled(
    method mouse_event_callback (line 228) | extern "C-unwind" fn mouse_event_callback(
  method drop (line 340) | fn drop(&mut self) {

FILE: packages/wm-platform/src/platform_impl/macos/native_window.rs
  type NativeWindow (line 22) | pub(crate) struct NativeWindow {
    method new (line 31) | pub(crate) fn new(
    method id (line 44) | pub(crate) fn id(&self) -> WindowId {
    method title (line 49) | pub(crate) fn title(&self) -> crate::Result<String> {
    method process_name (line 57) | pub(crate) fn process_name(&self) -> crate::Result<String> {
    method frame (line 67) | pub(crate) fn frame(&self) -> crate::Result<Rect> {
    method position (line 82) | pub(crate) fn position(&self) -> crate::Result<(f64, f64)> {
    method size (line 91) | pub(crate) fn size(&self) -> crate::Result<(f64, f64)> {
    method is_valid (line 100) | pub(crate) fn is_valid(&self) -> bool {
    method is_visible (line 135) | pub(crate) fn is_visible(&self) -> crate::Result<bool> {
    method is_minimized (line 140) | pub(crate) fn is_minimized(&self) -> crate::Result<bool> {
    method is_maximized (line 148) | pub(crate) fn is_maximized(&self) -> crate::Result<bool> {
    method is_resizable (line 157) | pub(crate) fn is_resizable(&self) -> crate::Result<bool> {
    method is_desktop_window (line 164) | pub(crate) fn is_desktop_window(&self) -> crate::Result<bool> {
    method set_frame (line 171) | pub(crate) fn set_frame(&self, rect: &Rect) -> crate::Result<()> {
    method resize (line 191) | pub(crate) fn resize(
    method reposition (line 204) | pub(crate) fn reposition(&self, x: i32, y: i32) -> crate::Result<()> {
    method minimize (line 213) | pub(crate) fn minimize(&self) -> crate::Result<()> {
    method maximize (line 221) | pub(crate) fn maximize(&self) -> crate::Result<()> {
    method focus (line 229) | pub(crate) fn focus(&self) -> crate::Result<()> {
    method close (line 237) | pub(crate) fn close(&self) -> crate::Result<()> {
    method with_enhanced_ui_disabled (line 267) | fn with_enhanced_ui_disabled<F, R>(
    method raise (line 306) | fn raise(&self) -> crate::Result<()> {
    method set_front_process (line 334) | fn set_front_process(
    method set_key_window (line 356) | fn set_key_window(
  function from (line 388) | fn from(window: NativeWindow) -> Self {
  function visible_windows (line 394) | pub(crate) fn visible_windows(
  function window_by_id (line 407) | pub(crate) fn window_by_id(
  function window_from_point (line 425) | pub(crate) fn window_from_point(
  function focused_window (line 459) | pub(crate) fn focused_window(
  function reset_focus (line 477) | pub(crate) fn reset_focus(dispatcher: &Dispatcher) -> crate::Result<()> {

FILE: packages/wm-platform/src/platform_impl/macos/notification_center.rs
  type NotificationName (line 24) | pub(crate) enum NotificationName {
    method from (line 37) | fn from(name: &NSNotificationName) -> Self {
  function from (line 74) | fn from(name: NotificationName) -> Self {
  type NotificationEvent (line 109) | pub(crate) enum NotificationEvent {
  type NotificationObserverIvars (line 123) | pub(crate) struct NotificationObserverIvars {
  method new (line 145) | pub fn new(
  method handle_event (line 156) | fn handle_event(&self, notif: &NSNotification) {
  method emit_event (line 224) | fn emit_event(&self, event: NotificationEvent) {
  type NotificationCenter (line 233) | pub(crate) struct NotificationCenter {
    method workspace_center (line 238) | pub fn workspace_center() -> Self {
    method default_center (line 244) | pub fn default_center() -> Self {
    method add_observer (line 250) | pub unsafe fn add_observer(
  function app_from_notification (line 267) | pub unsafe fn app_from_notification(

FILE: packages/wm-platform/src/platform_impl/macos/single_instance.rs
  type SingleInstance (line 7) | pub(crate) struct SingleInstance {
    method new (line 16) | pub(crate) fn new() -> crate::Result<Self> {
    method is_running (line 39) | pub(crate) fn is_running() -> bool {
    method lock_file_path (line 55) | fn lock_file_path() -> crate::Result<PathBuf> {

FILE: packages/wm-platform/src/platform_impl/macos/window_listener.rs
  type WindowEventNotificationInner (line 17) | pub struct WindowEventNotificationInner {
  type WindowListener (line 29) | pub(crate) struct WindowListener {
    method new (line 36) | pub(crate) fn new(
    method terminate (line 49) | pub(crate) fn terminate(&mut self) {
    method init (line 59) | fn init(
    method listen_workspace_events (line 113) | fn listen_workspace_events(
    method create_app_observer (line 210) | fn create_app_observer(
  method drop (line 236) | fn drop(&mut self) {

FILE: packages/wm-platform/src/platform_impl/windows/com.rs
  constant CLSID_IMMERSIVE_SHELL (line 16) | const CLSID_IMMERSIVE_SHELL: GUID =
  type ComInit (line 28) | pub(crate) struct ComInit {
    method new (line 43) | pub(crate) fn new() -> Self {
    method application_view_collection (line 69) | pub(crate) fn application_view_collection(
    method taskbar_list (line 81) | pub(crate) fn taskbar_list(&self) -> crate::Result<&ITaskbarList2> {
    method refresh (line 93) | pub(crate) fn refresh(&mut self) {
    method with_retry (line 116) | pub fn with_retry<T, F>(&mut self, op: F) -> crate::Result<T>
  method default (line 130) | fn default() -> Self {
  method drop (line 136) | fn drop(&mut self) {
  type IApplicationViewCollection (line 150) | pub unsafe trait IApplicationViewCollection: IUnknown {
    method m1 (line 151) | pub unsafe fn m1(&self);
    method m2 (line 152) | pub unsafe fn m2(&self);
    method m3 (line 153) | pub unsafe fn m3(&self);
    method get_view_for_hwnd (line 154) | pub unsafe fn get_view_for_hwnd(
  type IApplicationView (line 165) | pub unsafe trait IApplicationView: IUnknown {
    method m1 (line 166) | pub unsafe fn m1(&self);
    method m2 (line 167) | pub unsafe fn m2(&self);
    method m3 (line 168) | pub unsafe fn m3(&self);
    method m4 (line 169) | pub unsafe fn m4(&self);
    method m5 (line 170) | pub unsafe fn m5(&self);
    method m6 (line 171) | pub unsafe fn m6(&self);
    method m7 (line 172) | pub unsafe fn m7(&self);
    method m8 (line 173) | pub unsafe fn m8(&self);
    method m9 (line 174) | pub unsafe fn m9(&self);
    method set_cloak (line 175) | pub unsafe fn set_cloak(

FILE: packages/wm-platform/src/platform_impl/windows/display.rs
  type Display (line 29) | pub(crate) struct Display {
    method new (line 36) | pub(crate) fn new(monitor_handle: isize) -> Self {
    method id (line 41) | pub(crate) fn id(&self) -> DisplayId {
    method name (line 46) | pub(crate) fn name(&self) -> crate::Result<String> {
    method bounds (line 55) | pub(crate) fn bounds(&self) -> crate::Result<Rect> {
    method working_area (line 61) | pub(crate) fn working_area(&self) -> crate::Result<Rect> {
    method scale_factor (line 67) | pub(crate) fn scale_factor(&self) -> crate::Result<f32> {
    method dpi (line 74) | pub(crate) fn dpi(&self) -> crate::Result<u32> {
    method is_primary (line 92) | pub(crate) fn is_primary(&self) -> crate::Result<bool> {
    method devices (line 98) | pub(crate) fn devices(
    method main_device (line 141) | pub(crate) fn main_device(&self) -> crate::Result<crate::DisplayDevice> {
    method hmonitor (line 155) | pub(crate) fn hmonitor(&self) -> HMONITOR {
    method monitor_info_ex (line 160) | fn monitor_info_ex(&self) -> crate::Result<MONITORINFOEXW> {
  function from (line 183) | fn from(display: Display) -> Self {
  method eq (line 189) | fn eq(&self, other: &Self) -> bool {
  type DisplayDevice (line 198) | pub(crate) struct DisplayDevice {
    method new (line 211) | pub(crate) fn new(adapter_name: String, device_path: &[u16]) -> Self {
    method id (line 228) | pub(crate) fn id(&self) -> DisplayDeviceId {
    method rotation (line 238) | pub(crate) fn rotation(&self) -> crate::Result<f32> {
    method refresh_rate (line 257) | pub(crate) fn refresh_rate(&self) -> crate::Result<f32> {
    method is_builtin (line 264) | pub(crate) fn is_builtin(&self) -> crate::Result<bool> {
    method connection_state (line 272) | pub(crate) fn connection_state(&self) -> crate::Result<ConnectionState> {
    method mirroring_state (line 279) | pub(crate) fn mirroring_state(
    method hardware_id (line 288) | pub(crate) fn hardware_id(&self) -> Option<String> {
    method output_technology (line 299) | pub(crate) fn output_technology(
    method current_device_mode (line 307) | fn current_device_mode(&self) -> crate::Result<DEVMODEW> {
  function from (line 334) | fn from(device: DisplayDevice) -> Self {
  function all_displays (line 340) | pub(crate) fn all_displays(
  function all_display_devices (line 380) | pub(crate) fn all_display_devices(
  function display_from_point (line 392) | pub(crate) fn display_from_point(
  function primary_display (line 411) | pub(crate) fn primary_display(
  function nearest_display (line 423) | pub(crate) fn nearest_display(

FILE: packages/wm-platform/src/platform_impl/windows/display_listener.rs
  type DisplayListener (line 17) | pub(crate) struct DisplayListener {
    method new (line 24) | pub(crate) fn new(
    method terminate (line 95) | pub(crate) fn terminate(&mut self) -> crate::Result<()> {
  method drop (line 105) | fn drop(&mut self) {

FILE: packages/wm-platform/src/platform_impl/windows/event_loop.rs
  type EventLoopSource (line 49) | pub(crate) struct EventLoopSource {
    method send_dispatch_async (line 57) | pub(crate) fn send_dispatch_async<F>(
    method send_dispatch_sync (line 93) | pub(crate) fn send_dispatch_sync<F>(
    method send_stop (line 119) | pub(crate) fn send_stop(&self) -> crate::Result<()> {
    method register_wndproc_callback (line 130) | pub(crate) fn register_wndproc_callback(
    method deregister_wndproc_callback (line 146) | pub(crate) fn deregister_wndproc_callback(
  type EventLoop (line 159) | pub(crate) struct EventLoop {
    method new (line 165) | pub(crate) fn new() -> crate::Result<(Self, Dispatcher)> {
    method run (line 184) | pub(crate) fn run(&self) -> crate::Result<()> {
    method shutdown (line 207) | pub(crate) fn shutdown(&mut self) -> crate::Result<()> {
    method create_message_window (line 217) | fn create_message_window(
    method window_proc (line 256) | unsafe extern "system" fn window_proc(
  method drop (line 292) | fn drop(&mut self) {

FILE: packages/wm-platform/src/platform_impl/windows/keyboard_hook.rs
  type HookCallback (line 20) | type HookCallback = Box<dyn Fn(KeyEvent) -> bool>;
  type KeyEvent (line 32) | pub struct KeyEvent {
    method is_key_down (line 47) | pub fn is_key_down(&self, key: Key) -> bool {
    method is_key_down_raw (line 77) | fn is_key_down_raw(key: u16) -> bool {
  type KeyboardHook (line 84) | pub struct KeyboardHook {
    method new (line 99) | pub fn new<F>(
    method terminate (line 133) | pub fn terminate(&mut self) -> crate::Result<()> {
    method hook_proc (line 150) | extern "system" fn hook_proc(
  method drop (line 199) | fn drop(&mut self) {

FILE: packages/wm-platform/src/platform_impl/windows/mouse_listener.rs
  type CallbackData (line 33) | struct CallbackData {
  type MouseListener (line 44) | pub(crate) struct MouseListener {
    method new (line 52) | pub(crate) fn new(
    method enable (line 77) | pub(crate) fn enable(&mut self, enabled: bool) -> crate::Result<()> {
    method set_enabled_events (line 89) | pub(crate) fn set_enabled_events(
    method terminate (line 107) | pub(crate) fn terminate(&mut self) -> crate::Result<()> {
    method register_callback (line 121) | fn register_callback(
    method handle_wm_input (line 162) | fn handle_wm_input(
    method cursor_pos (line 276) | fn cursor_pos() -> crate::Result<Point> {
    method enable_raw_input (line 286) | fn enable_raw_input(
  method drop (line 321) | fn drop(&mut self) {

FILE: packages/wm-platform/src/platform_impl/windows/native_window.rs
  constant FOREGROUND_INPUT_IDENTIFIER (line 53) | pub(crate) const FOREGROUND_INPUT_IDENTIFIER: u32 = 6379;
  type NativeWindow (line 57) | pub(crate) struct NativeWindow {
    method new (line 64) | pub(crate) fn new(handle: isize) -> Self {
    method id (line 70) | pub(crate) fn id(&self) -> WindowId {
    method title (line 76) | pub(crate) fn title(&self) -> crate::Result<String> {
    method process_name (line 85) | pub(crate) fn process_name(&self) -> crate::Result<String> {
    method frame (line 126) | pub(crate) fn frame(&self) -> crate::Result<Rect> {
    method position (line 153) | pub(crate) fn position(&self) -> crate::Result<(f64, f64)> {
    method size (line 159) | pub(crate) fn size(&self) -> crate::Result<(f64, f64)> {
    method is_valid (line 165) | pub(crate) fn is_valid(&self) -> bool {
    method is_visible (line 170) | pub(crate) fn is_visible(&self) -> crate::Result<bool> {
    method is_minimized (line 178) | pub(crate) fn is_minimized(&self) -> crate::Result<bool> {
    method is_maximized (line 184) | pub(crate) fn is_maximized(&self) -> crate::Result<bool> {
    method is_resizable (line 190) | pub(crate) fn is_resizable(&self) -> crate::Result<bool> {
    method is_desktop_window (line 196) | pub(crate) fn is_desktop_window(&self) -> crate::Result<bool> {
    method set_frame (line 201) | pub(crate) fn set_frame(&self, rect: &Rect) -> crate::Result<()> {
    method resize (line 223) | pub(crate) fn resize(
    method reposition (line 250) | pub(crate) fn reposition(&self, x: i32, y: i32) -> crate::Result<()> {
    method minimize (line 273) | pub(crate) fn minimize(&self) -> crate::Result<()> {
    method maximize (line 279) | pub(crate) fn maximize(&self) -> crate::Result<()> {
    method focus (line 285) | pub(crate) fn focus(&self) -> crate::Result<()> {
    method close (line 310) | pub(crate) fn close(&self) -> crate::Result<()> {
    method hwnd (line 316) | pub(crate) fn hwnd(&self) -> HWND {
    method class_name (line 321) | pub(crate) fn class_name(&self) -> crate::Result<String> {
    method frame_with_shadows (line 335) | pub(crate) fn frame_with_shadows(&self) -> crate::Result<Rect> {
    method shadow_borders (line 353) | pub(crate) fn shadow_borders(&self) -> crate::Result<RectDelta> {
    method has_owner_window (line 366) | pub(crate) fn has_owner_window(&self) -> bool {
    method has_window_style (line 371) | pub(crate) fn has_window_style(&self, style: WINDOW_STYLE) -> bool {
    method has_window_style_ex (line 381) | pub(crate) fn has_window_style_ex(
    method set_window_pos (line 394) | pub(crate) fn set_window_pos(
    method show (line 423) | pub(crate) fn show(&self) -> crate::Result<()> {
    method hide (line 429) | pub(crate) fn hide(&self) -> crate::Result<()> {
    method restore (line 435) | pub(crate) fn restore(
    method set_cloaked (line 466) | pub(crate) fn set_cloaked(&self, cloaked: bool) -> crate::Result<()> {
    method mark_fullscreen (line 494) | pub(crate) fn mark_fullscreen(
    method set_taskbar_visibility (line 512) | pub(crate) fn set_taskbar_visibility(
    method add_window_style_ex (line 532) | pub(crate) fn add_window_style_ex(&self, style: WINDOW_EX_STYLE) {
    method set_z_order (line 545) | pub(crate) fn set_z_order(
    method set_title_bar_visibility (line 578) | pub(crate) fn set_title_bar_visibility(
    method set_border_color (line 618) | pub(crate) fn set_border_color(
    method set_corner_style (line 641) | pub(crate) fn set_corner_style(
    method set_transparency (line 666) | pub(crate) fn set_transparency(
    method adjust_transparency (line 686) | pub(crate) fn adjust_transparency(
    method is_cloaked (line 722) | fn is_cloaked(&self) -> crate::Result<bool> {
  method eq (line 740) | fn eq(&self, other: &Self) -> bool {
  function from (line 748) | fn from(window: NativeWindow) -> Self {
  function visible_windows (line 754) | pub(crate) fn visible_windows(
  function focused_window (line 788) | pub(crate) fn focused_window(
  function window_from_point (line 797) | pub(crate) fn window_from_point(
  function reset_focus (line 820) | pub(crate) fn reset_focus(_dispatcher: &Dispatcher) -> crate::Result<()> {
  function desktop_window (line 830) | fn desktop_window() -> NativeWindow {

FILE: packages/wm-platform/src/platform_impl/windows/single_instance.rs
  constant APP_GUID (line 16) | const APP_GUID: PCWSTR =
  type SingleInstance (line 20) | pub struct SingleInstance {
    method new (line 26) | pub(crate) fn new() -> crate::Result<Self> {
    method is_running (line 44) | pub(crate) fn is_running() -> bool {
  method drop (line 58) | fn drop(&mut self) {

FILE: packages/wm-platform/src/platform_impl/windows/window_listener.rs
  type WindowEventNotificationInner (line 29) | pub struct WindowEventNotificationInner;
  type WindowListener (line 33) | pub(crate) struct WindowListener {
    method new (line 39) | pub(crate) fn new(
    method terminate (line 57) | pub(crate) fn terminate(&mut self) {
    method hook_win_events (line 67) | fn hook_win_events() -> crate::Result<Vec<HWINEVENTHOOK>> {
    method window_event_proc (line 108) | extern "system" fn window_event_proc(
  method drop (line 189) | fn drop(&mut self) {

FILE: packages/wm-platform/src/single_instance.rs
  type SingleInstance (line 9) | pub struct SingleInstance {
    method new (line 21) | pub fn new() -> crate::Result<Self> {
    method is_running (line 29) | pub fn is_running() -> bool {

FILE: packages/wm-platform/src/test.rs
  function main (line 31) | pub fn main() {

FILE: packages/wm-platform/src/thread_bound.rs
  type ThreadBound (line 50) | pub struct ThreadBound<T> {
  function new (line 69) | pub fn new(inner: T, dispatcher: Dispatcher) -> Self {
  function get_ref (line 88) | pub fn get_ref(&self) -> crate::Result<&T> {
  function get_mut (line 102) | pub fn get_mut(&mut self) -> crate::Result<&mut T> {
  function into_inner (line 117) | pub fn into_inner(self) -> crate::Result<T> {
  function with (line 134) | pub fn with<F, R>(&self, f: F) -> crate::Result<R>
  function with_mut (line 151) | pub fn with_mut<F, R>(&mut self, f: F) -> crate::Result<R>
  function is_event_loop_thread (line 170) | pub fn is_event_loop_thread(&self) -> bool {
  function fmt (line 176) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  method drop (line 188) | fn drop(&mut self) {

FILE: packages/wm-platform/src/window_listener.rs
  type WindowListener (line 6) | pub struct WindowListener {
    method new (line 15) | pub fn new(dispatcher: &Dispatcher) -> crate::Result<Self> {
    method next_event (line 25) | pub async fn next_event(&mut self) -> Option<WindowEvent> {
    method terminate (line 30) | pub fn terminate(&mut self) {

FILE: packages/wm-watcher/build.rs
  function main (line 3) | fn main() {

FILE: packages/wm-watcher/src/main.rs
  function main (line 14) | async fn main() -> anyhow::Result<()> {
  function query_initial_windows (line 59) | async fn query_initial_windows(
  function watch_managed_handles (line 89) | async fn watch_managed_handles(

FILE: packages/wm/build.rs
  function main (line 3) | fn main() {

FILE: packages/wm/src/commands/container/attach_container.rs
  function attach_container (line 12) | pub fn attach_container(

FILE: packages/wm/src/commands/container/detach_container.rs
  function detach_container (line 14) | pub fn detach_container(child_to_remove: Container) -> anyhow::Result<()> {

FILE: packages/wm/src/commands/container/flatten_child_split_containers.rs
  function flatten_child_split_containers (line 16) | pub fn flatten_child_split_containers(

FILE: packages/wm/src/commands/container/flatten_split_container.rs
  function flatten_split_container (line 15) | pub fn flatten_split_container(

FILE: packages/wm/src/commands/container/focus_container_by_id.rs
  function focus_container_by_id (line 7) | pub fn focus_container_by_id(

FILE: packages/wm/src/commands/container/focus_in_direction.rs
  function focus_in_direction (line 12) | pub fn focus_in_direction(
  function floating_focus_target (line 52) | fn floating_focus_target(
  function tiling_focus_target (line 82) | fn tiling_focus_target(
  function workspace_focus_target (line 136) | fn workspace_focus_target(

FILE: packages/wm/src/commands/container/move_container_within_tree.rs
  function move_container_within_tree (line 23) | pub fn move_container_within_tree(
  function move_to_lowest_common_ancestor (line 139) | fn move_to_lowest_common_ancestor(
  function lowest_common_ancestor (line 178) | pub fn lowest_common_ancestor(

FILE: packages/wm/src/commands/container/replace_container.rs
  function replace_container (line 13) | pub fn replace_container(

FILE: packages/wm/src/commands/container/resize_tiling_container.rs
  function resize_tiling_container (line 6) | pub fn resize_tiling_container(

FILE: packages/wm/src/commands/container/set_focused_descendant.rs
  function set_focused_descendant (line 7) | pub fn set_focused_descendant(

FILE: packages/wm/src/commands/container/toggle_tiling_direction.rs
  function toggle_tiling_direction (line 12) | pub fn toggle_tiling_direction(
  function toggle_window_direction (line 39) | fn toggle_window_direction(
  function set_tiling_direction (line 83) | pub fn set_tiling_direction(

FILE: packages/wm/src/commands/container/wrap_in_split_container.rs
  function wrap_in_split_container (line 10) | pub fn wrap_in_split_container(

FILE: packages/wm/src/commands/general/cycle_focus.rs
  function cycle_focus (line 17) | pub fn cycle_focus(
  function next_state (line 77) | fn next_state(

FILE: packages/wm/src/commands/general/disable_binding_mode.rs
  function disable_binding_mode (line 5) | pub fn disable_binding_mode(name: &str, state: &mut WmState) {

FILE: packages/wm/src/commands/general/enable_binding_mode.rs
  function enable_binding_mode (line 6) | pub fn enable_binding_mode(

FILE: packages/wm/src/commands/general/platform_sync.rs
  function platform_sync (line 21) | pub fn platform_sync(
  function sync_focus (line 81) | fn sync_focus(
  function windows_to_bring_to_front (line 121) | fn windows_to_bring_to_front(
  function redraw_containers (line 173) | fn redraw_containers(
  function reposition_window (line 338) | fn reposition_window(
  function jump_cursor (line 474) | fn jump_cursor(
  function apply_window_effects (line 511) | fn apply_window_effects(
  function apply_border_effect (line 559) | fn apply_border_effect(
  function apply_hide_title_bar_effect (line 583) | fn apply_hide_title_bar_effect(
  function apply_corner_effect (line 593) | fn apply_corner_effect(
  function apply_transparency_effect (line 607) | fn apply_transparency_effect(

FILE: packages/wm/src/commands/general/reload_config.rs
  function reload_config (line 17) | pub fn reload_config(
  function update_workspace_configs (line 96) | fn update_workspace_configs(
  function update_container_gaps (line 143) | fn update_container_gaps(state: &mut WmState, config: &UserConfig) {
  function update_window_effects (line 159) | fn update_window_effects(

FILE: packages/wm/src/commands/general/shell_exec.rs
  function shell_exec (line 12) | pub fn shell_exec(
  function parse_command (line 92) | fn parse_command(

FILE: packages/wm/src/commands/general/toggle_pause.rs
  function toggle_pause (line 6) | pub fn toggle_pause(state: &mut WmState) {

FILE: packages/wm/src/commands/monitor/add_monitor.rs
  function add_monitor (line 17) | pub fn add_monitor(
  function move_bounded_workspaces_to_new_monitor (line 42) | pub fn move_bounded_workspaces_to_new_monitor(
  function move_workspace_to_monitor (line 93) | pub fn move_workspace_to_monitor(

FILE: packages/wm/src/commands/monitor/focus_monitor.rs
  function focus_monitor (line 9) | pub fn focus_monitor(

FILE: packages/wm/src/commands/monitor/remove_monitor.rs
  function remove_monitor (line 17) | pub fn remove_monitor(

FILE: packages/wm/src/commands/monitor/sort_monitors.rs
  function sort_monitors (line 8) | pub fn sort_monitors(root: &RootContainer) -> anyhow::Result<()> {

FILE: packages/wm/src/commands/monitor/update_monitor.rs
  function update_monitor (line 10) | pub fn update_monitor(

FILE: packages/wm/src/commands/window/ignore_window.rs
  function ignore_window (line 14) | pub fn ignore_window(

FILE: packages/wm/src/commands/window/manage_window.rs
  function manage_window (line 20) | pub fn manage_window(
  function check_is_manageable (line 91) | fn check_is_manageable(
  function create_window (line 153) | fn create_window(
  function window_state_to_create (line 265) | fn window_state_to_create(
  function insertion_target (line 322) | fn insertion_target(

FILE: packages/wm/src/commands/window/move_window_in_direction.rs
  constant SNAP_DISTANCE (line 23) | const SNAP_DISTANCE: i32 = 15;
  function move_window_in_direction (line 25) | pub fn move_window_in_direction(
  function move_tiling_window (line 51) | fn move_tiling_window(
  function tiling_sibling_in_direction (line 131) | fn tiling_sibling_in_direction(
  function move_to_sibling_container (line 145) | fn move_to_sibling_container(
  function move_to_workspace_in_direction (line 209) | fn move_to_workspace_in_direction(
  function invert_workspace_tiling_direction (line 279) | fn invert_workspace_tiling_direction(
  function insert_into_ancestor (line 343) | fn insert_into_ancestor(
  function move_floating_window (line 381) | fn move_floating_window(
  function new_floating_position (line 410) | fn new_floating_position(
  function snap_to_monitor_edge (line 509) | fn snap_to_monitor_edge(

FILE: packages/wm/src/commands/window/move_window_to_workspace.rs
  function move_window_to_workspace (line 16) | pub fn move_window_to_workspace(

FILE: packages/wm/src/commands/window/resize_window.rs
  function resize_window (line 10) | pub fn resize_window(

FILE: packages/wm/src/commands/window/run_window_rules.rs
  function run_window_rules (line 14) | pub fn run_window_rules(

FILE: packages/wm/src/commands/window/set_window_position.rs
  type WindowPositionTarget (line 11) | pub enum WindowPositionTarget {
  function set_window_position (line 16) | pub fn set_window_position(

FILE: packages/wm/src/commands/window/set_window_size.rs
  constant MIN_FLOATING_WIDTH (line 15) | const MIN_FLOATING_WIDTH: i32 = 250;
  constant MIN_FLOATING_HEIGHT (line 16) | const MIN_FLOATING_HEIGHT: i32 = 140;
  function set_window_size (line 18) | pub fn set_window_size(
  function set_tiling_window_size (line 43) | fn set_tiling_window_size(
  function set_tiling_window_length (line 61) | fn set_tiling_window_length(
  function set_floating_window_size (line 101) | fn set_floating_window_size(

FILE: packages/wm/src/commands/window/unmanage_window.rs
  function unmanage_window (line 15) | pub fn unmanage_window(

FILE: packages/wm/src/commands/window/update_window_state.rs
  function update_window_state (line 20) | pub fn update_window_state(
  function set_tiling (line 39) | fn set_tiling(
  function set_non_tiling (line 121) | fn set_non_tiling(

FILE: packages/wm/src/commands/workspace/activate_workspace.rs
  function activate_workspace (line 21) | pub fn activate_workspace(
  function workspace_config (line 85) | fn workspace_config(

FILE: packages/wm/src/commands/workspace/deactivate_workspace.rs
  function deactivate_workspace (line 12) | pub fn deactivate_workspace(

FILE: packages/wm/src/commands/workspace/focus_workspace.rs
  function focus_workspace (line 22) | pub fn focus_workspace(

FILE: packages/wm/src/commands/workspace/move_workspace_in_direction.rs
  function move_workspace_in_direction (line 14) | pub fn move_workspace_in_direction(

FILE: packages/wm/src/commands/workspace/sort_workspaces.rs
  function sort_workspaces (line 9) | pub fn sort_workspaces(

FILE: packages/wm/src/commands/workspace/update_workspace_config.rs
  function update_workspace_config (line 10) | pub fn update_workspace_config(

FILE: packages/wm/src/events/handle_display_settings_changed.rs
  function handle_display_settings_changed (line 15) | pub fn handle_display_settings_changed(
  function find_matching_monitor (line 128) | fn find_matching_monitor<'a>(

FILE: packages/wm/src/events/handle_mouse_move.rs
  function handle_mouse_move (line 15) | pub fn handle_mouse_move(

FILE: packages/wm/src/events/handle_window_destroyed.rs
  function handle_window_destroyed (line 11) | pub fn handle_window_destroyed(

FILE: packages/wm/src/events/handle_window_focused.rs
  function handle_window_focused (line 17) | pub fn handle_window_focused(
  function should_override_focus (line 108) | fn should_override_focus(state: &WmState) -> bool {

FILE: packages/wm/src/events/handle_window_hidden.rs
  function handle_window_hidden (line 10) | pub fn handle_window_hidden(

FILE: packages/wm/src/events/handle_window_minimize_ended.rs
  function handle_window_minimize_ended (line 10) | pub fn handle_window_minimize_ended(

FILE: packages/wm/src/events/handle_window_minimized.rs
  function handle_window_minimized (line 14) | pub fn handle_window_minimized(

FILE: packages/wm/src/events/handle_window_moved_or_resized.rs
  function handle_window_moved_or_resized (line 25) | pub fn handle_window_moved_or_resized(
  function update_floating_window_position (line 362) | pub fn update_floating_window_position(
  function update_drag_state (line 408) | fn update_drag_state(
  function is_in_corner (line 516) | fn is_in_corner(window_frame: &Rect, monitor_rect: &Rect) -> bool {
  function matches_corner_positions (line 549) | fn matches_corner_positions() {
  function does_not_match_non_corner_positions (line 560) | fn does_not_match_non_corner_positions() {

FILE: packages/wm/src/events/handle_window_moved_or_resized_end.rs
  function handle_window_moved_or_resized_end (line 32) | pub fn handle_window_moved_or_resized_end(
  function drop_as_tiling_window (line 152) | fn drop_as_tiling_window(
  type DropPosition (line 289) | enum DropPosition {
  function drop_position (line 300) | fn drop_position(mouse_pos: &Point, rect: &Rect) -> DropPosition {

FILE: packages/wm/src/events/handle_window_shown.rs
  function handle_window_shown (line 10) | pub fn handle_window_shown(

FILE: packages/wm/src/events/handle_window_title_changed.rs
  function handle_window_title_changed (line 10) | pub fn handle_window_title_changed(

FILE: packages/wm/src/ipc_server.rs
  type IpcServer (line 28) | pub struct IpcServer {
    method start (line 42) | pub async fn start() -> anyhow::Result<Self> {
    method handle_connection (line 77) | async fn handle_connection(
    method process_message (line 134) | pub fn process_message(
    method handle_app_command (line 170) | fn handle_app_command(
    method to_client_response_msg (line 323) | fn to_client_response_msg(
    method to_event_subscription_msg (line 341) | fn to_event_subscription_msg(
    method process_event (line 357) | pub fn process_event(&mut self, event: WmEvent) -> anyhow::Result<()> {
    method stop (line 400) | pub fn stop(&self) {
  method drop (line 407) | fn drop(&mut self) {

FILE: packages/wm/src/main.rs
  function main (line 52) | fn main() -> anyhow::Result<()> {
  function start_wm (line 100) | async fn start_wm(
  function setup_logging (line 299) | fn setup_logging(verbosity: &Verbosity) -> anyhow::Result<()> {
  function start_watcher_process (line 336) | fn start_watcher_process() -> anyhow::Result<tokio::process::Child, Error>
  function update_path_env (line 355) | fn update_path_env() {

FILE: packages/wm/src/models/container.rs
  type Container (line 95) | pub enum Container {
  method eq (line 109) | fn eq(&self, other: &Self) -> bool {
  method eq (line 117) | fn eq(&self, other: &Self) -> bool {
  method eq (line 125) | fn eq(&self, other: &Self) -> bool {
  method fmt (line 133) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  method eq (line 172) | fn eq(&self, other: &Self) -> bool {

FILE: packages/wm/src/models/insertion_target.rs
  type InsertionTarget (line 4) | pub struct InsertionTarget {

FILE: packages/wm/src/models/monitor.rs
  type Monitor (line 22) | pub struct Monitor(Rc<RefCell<MonitorInner>>);
    method new (line 34) | pub fn new(
    method native (line 50) | pub fn native(&self) -> Display {
    method set_native (line 54) | pub fn set_native(&self, native: Display) {
    method native_properties (line 58) | pub fn native_properties(&self) -> NativeMonitorProperties {
    method set_native_properties (line 62) | pub fn set_native_properties(
    method displayed_workspace (line 69) | pub fn displayed_workspace(&self) -> Option<Workspace> {
    method workspaces (line 76) | pub fn workspaces(&self) -> Vec<Workspace> {
    method has_dpi_difference (line 86) | pub fn has_dpi_difference(
    method to_dto (line 100) | pub fn to_dto(&self) -> anyhow::Result<ContainerDto> {
    method fmt (line 148) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type MonitorInner (line 24) | struct MonitorInner {
  method to_rect (line 142) | fn to_rect(&self) -> anyhow::Result<Rect> {

FILE: packages/wm/src/models/native_monitor_properties.rs
  type NativeMonitorProperties (line 6) | pub struct NativeMonitorProperties {
    method try_from (line 23) | pub fn try_from(native_display: &Display) -> anyhow::Result<Self> {

FILE: packages/wm/src/models/native_window_properties.rs
  type NativeWindowProperties (line 6) | pub struct NativeWindowProperties {
    type Error (line 20) | type Error = anyhow::Error;
    method try_from (line 22) | fn try_from(native_window: &NativeWindow) -> Result<Self, Self::Error> {

FILE: packages/wm/src/models/non_tiling_window.rs
  type NonTilingWindow (line 26) | pub struct NonTilingWindow(Rc<RefCell<NonTilingWindowInner>>);
    method new (line 49) | pub fn new(
    method insertion_target (line 84) | pub fn insertion_target(&self) -> Option<InsertionTarget> {
    method set_insertion_target (line 88) | pub fn set_insertion_target(
    method to_tiling (line 95) | pub fn to_tiling(&self, gaps_config: GapsConfig) -> TilingWindow {
    method to_dto (line 116) | pub fn to_dto(&self) -> anyhow::Result<ContainerDto> {
  type NonTilingWindowInner (line 28) | struct NonTilingWindowInner {
  method to_rect (line 149) | fn to_rect(&self) -> anyhow::Result<Rect> {

FILE: packages/wm/src/models/root_container.rs
  type RootContainer (line 23) | pub struct RootContainer(Rc<RefCell<RootContainerInner>>);
    method new (line 46) | pub fn new() -> Self {
    method monitors (line 50) | pub fn monitors(&self) -> Vec<Monitor> {
    method to_dto (line 58) | pub fn to_dto(&self) -> anyhow::Result<ContainerDto> {
  type RootContainerInner (line 25) | struct RootContainerInner {
  method default (line 33) | fn default() -> Self {
  method to_rect (line 78) | fn to_rect(&self) -> anyhow::Result<Rect> {

FILE: packages/wm/src/models/split_container.rs
  type SplitContainer (line 28) | pub struct SplitContainer(Rc<RefCell<SplitContainerInner>>);
    method new (line 41) | pub fn new(
    method to_dto (line 58) | pub fn to_dto(&self) -> anyhow::Result<ContainerDto> {
  type SplitContainerInner (line 30) | struct SplitContainerInner {

FILE: packages/wm/src/models/tiling_window.rs
  type TilingWindow (line 31) | pub struct TilingWindow(Rc<RefCell<TilingWindowInner>>);
    method new (line 55) | pub fn new(
    method to_non_tiling (line 90) | pub fn to_non_tiling(
    method to_dto (line 110) | pub fn to_dto(&self) -> anyhow::Result<ContainerDto> {
  type TilingWindowInner (line 33) | struct TilingWindowInner {

FILE: packages/wm/src/models/workspace.rs
  type Workspace (line 24) | pub struct Workspace(Rc<RefCell<WorkspaceInner>>);
    method new (line 38) | pub fn new(
    method config (line 57) | pub fn config(&self) -> WorkspaceConfig {
    method set_config (line 62) | pub fn set_config(&self, config: WorkspaceConfig) {
    method is_displayed (line 67) | pub fn is_displayed(&self) -> bool {
    method set_gaps_config (line 74) | pub fn set_gaps_config(&self, gaps_config: GapsConfig) {
    method outer_gaps (line 82) | pub fn outer_gaps(&self) -> RectDelta {
    method workspace_rect_with_gap_config (line 100) | fn workspace_rect_with_gap_config(
    method max_workspace_rect (line 134) | pub fn max_workspace_rect(&self) -> anyhow::Result<Rect> {
    method to_dto (line 152) | pub fn to_dto(&self) -> anyhow::Result<ContainerDto> {
    method fmt (line 191) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type WorkspaceInner (line 27) | struct WorkspaceInner {
  method to_rect (line 185) | fn to_rect(&self) -> anyhow::Result<Rect> {

FILE: packages/wm/src/models/workspace_target.rs
  type WorkspaceTarget (line 3) | pub enum WorkspaceTarget {

FILE: packages/wm/src/pending_sync.rs
  type PendingSync (line 12) | pub struct PendingSync {
    method has_changes (line 36) | pub fn has_changes(&self) -> bool {
    method clear (line 45) | pub fn clear(&mut self) -> &mut Self {
    method queue_container_to_redraw (line 55) | pub fn queue_container_to_redraw<T>(&mut self, container: T) -> &mut Self
    method queue_containers_to_redraw (line 64) | pub fn queue_containers_to_redraw<I, T>(
    method dequeue_container_from_redraw (line 80) | pub fn dequeue_container_from_redraw<T>(
    method queue_workspace_to_reorder (line 91) | pub fn queue_workspace_to_reorder(
    method queue_focus_change (line 99) | pub fn queue_focus_change(&mut self) -> &mut Self {
    method queue_focused_effect_update (line 104) | pub fn queue_focused_effect_update(&mut self) -> &mut Self {
    method queue_all_effects_update (line 109) | pub fn queue_all_effects_update(&mut self) -> &mut Self {
    method queue_cursor_jump (line 114) | pub fn queue_cursor_jump(&mut self) -> &mut Self {
    method needs_focus_update (line 119) | pub fn needs_focus_update(&self) -> bool {
    method needs_focused_effect_update (line 123) | pub fn needs_focused_effect_update(&self) -> bool {
    method needs_all_effects_update (line 127) | pub fn needs_all_effects_update(&self) -> bool {
    method needs_cursor_jump (line 131) | pub fn needs_cursor_jump(&self) -> bool {
    method containers_to_redraw (line 135) | pub fn containers_to_redraw(&self) -> &HashMap<Uuid, Container> {
    method workspaces_to_reorder (line 139) | pub fn workspaces_to_reorder(&self) -> &Vec<Workspace> {

FILE: packages/wm/src/sys_tray.rs
  type TrayMenuId (line 20) | enum TrayMenuId {
  method fmt (line 30) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Err (line 45) | type Err = anyhow::Error;
  method from_str (line 47) | fn from_str(event: &str) -> Result<Self, Self::Err> {
  type SystemTray (line 59) | pub struct SystemTray {
    method new (line 68) | pub fn new(
    method create_tray_icon (line 133) | fn create_tray_icon(
    method load_icon (line 197) | fn load_icon(bytes: &[u8]) -> anyhow::Result<Icon> {
    method handle_menu_event (line 215) | fn handle_menu_event(
  function auto_launch_instance (line 267) | fn auto_launch_instance() -> anyhow::Result<AutoLaunch> {

FILE: packages/wm/src/traits/common_getters.rs
  type CommonGetters (line 16) | pub trait CommonGetters {
    method id (line 18) | fn id(&self) -> Uuid;
    method as_container (line 20) | fn as_container(&self) -> Container;
    method as_tiling_container (line 22) | fn as_tiling_container(&self) -> anyhow::Result<TilingContainer>;
    method as_window_container (line 24) | fn as_window_container(&self) -> anyhow::Result<WindowContainer>;
    method as_direction_container (line 26) | fn as_direction_container(&self) -> anyhow::Result<DirectionContainer>;
    method to_dto (line 28) | fn to_dto(&self) -> anyhow::Result<ContainerDto>;
    method borrow_parent (line 30) | fn borrow_parent(&self) -> Ref<'_, Option<Container>>;
    method borrow_parent_mut (line 32) | fn borrow_parent_mut(&self) -> RefMut<'_, Option<Container>>;
    method borrow_children (line 34) | fn borrow_children(&self) -> Ref<'_, VecDeque<Container>>;
    method borrow_children_mut (line 36) | fn borrow_children_mut(&self) -> RefMut<'_, VecDeque<Container>>;
    method borrow_child_focus_order (line 38) | fn borrow_child_focus_order(&self) -> Ref<'_, VecDeque<Uuid>>;
    method borrow_child_focus_order_mut (line 40) | fn borrow_child_focus_order_mut(&self) -> RefMut<'_, VecDeque<Uuid>>;
    method parent (line 43) | fn parent(&self) -> Option<Container> {
    method children (line 48) | fn children(&self) -> VecDeque<Container> {
    method child_count (line 53) | fn child_count(&self) -> usize {
    method has_children (line 58) | fn has_children(&self) -> bool {
    method is_detached (line 64) | fn is_detached(&self) -> bool {
    method index (line 71) | fn index(&self) -> usize {
    method child_by_id (line 85) | fn child_by_id(&self, child_id: &Uuid) -> Option<Container> {
    method tiling_children (line 93) | fn tiling_children(
    method descendants (line 104) | fn descendants(&self) -> Descendants {
    method self_and_descendants (line 110) | fn self_and_descendants(&self) -> Descendants {
    method child_focus_order (line 117) | fn child_focus_order(&self) -> Box<dyn Iterator<Item = Container> + '_> {
    method descendant_focus_order (line 132) | fn descendant_focus_order(
    method siblings (line 161) | fn siblings(&self) -> Box<dyn Iterator<Item = Container> + '_> {
    method self_and_siblings (line 171) | fn self_and_siblings(&self) -> Box<dyn Iterator<Item = Container> + '_> {
    method prev_siblings (line 180) | fn prev_siblings(&self) -> Box<dyn Iterator<Item = Container> + '_> {
    method next_siblings (line 191) | fn next_siblings(&self) -> Box<dyn Iterator<Item = Container> + '_> {
    method tiling_siblings (line 201) | fn tiling_siblings(
    method ancestors (line 211) | fn ancestors(&self) -> Ancestors {
    method self_and_ancestors (line 217) | fn self_and_ancestors(&self) -> Ancestors {
    method workspace (line 226) | fn workspace(&self) -> Option<Workspace> {
    method monitor (line 235) | fn monitor(&self) -> Option<Monitor> {
    method direction_container (line 245) | fn direction_container(&self) -> Option<DirectionContainer> {
    method focus_index (line 254) | fn focus_index(&self) -> usize {
    method has_focus (line 270) | fn has_focus(&self, end_ancestor: Option<Container>) -> bool {
  type Ancestors (line 280) | pub struct Ancestors {
  type Item (line 285) | type Item = Container;
  method next (line 287) | fn next(&mut self) -> Option<Container> {
  type Descendants (line 295) | pub struct Descendants {
  type Item (line 300) | type Item = Container;
  method next (line 302) | fn next(&mut self) -> Option<Container> {

FILE: packages/wm/src/traits/position_getters.rs
  type PositionGetters (line 5) | pub trait PositionGetters {
    method to_rect (line 6) | fn to_rect(&self) -> anyhow::Result<Rect>;

FILE: packages/wm/src/traits/tiling_direction_getters.rs
  type TilingDirectionGetters (line 9) | pub trait TilingDirectionGetters: CommonGetters {
    method tiling_direction (line 10) | fn tiling_direction(&self) -> TilingDirection;
    method set_tiling_direction (line 12) | fn set_tiling_direction(&self, tiling_direction: TilingDirection);
    method descendant_in_direction (line 19) | fn descendant_in_direction(
    method child_in_direction (line 34) | fn child_in_direction(

FILE: packages/wm/src/traits/tiling_size_getters.rs
  constant MIN_TILING_SIZE (line 10) | pub const MIN_TILING_SIZE: f32 = 0.01;
  type TilingSizeGetters (line 13) | pub trait TilingSizeGetters: CommonGetters {
    method tiling_size (line 14) | fn tiling_size(&self) -> f32;
    method set_tiling_size (line 16) | fn set_tiling_size(&self, tiling_size: f32);
    method gaps_config (line 18) | fn gaps_config(&self) -> Ref<'_, GapsConfig>;
    method set_gaps_config (line 20) | fn set_gaps_config(&self, gaps_config: GapsConfig);
    method inner_gaps (line 23) | fn inner_gaps(&self) -> anyhow::Result<(i32, i32)> {
    method container_to_resize (line 45) | fn container_to_resize(

FILE: packages/wm/src/traits/window_getters.rs
  type WindowGetters (line 14) | pub trait WindowGetters: CommonGetters {
    method state (line 15) | fn state(&self) -> WindowState;
    method set_state (line 17) | fn set_state(&self, state: WindowState);
    method prev_state (line 19) | fn prev_state(&self) -> Option<WindowState>;
    method set_prev_state (line 21) | fn set_prev_state(&self, state: WindowState);
    method toggled_state (line 32) | fn toggled_state(
    method native (line 61) | fn native(&self) -> Ref<'_, NativeWindow>;
    method border_delta (line 63) | fn border_delta(&self) -> RectDelta;
    method set_border_delta (line 65) | fn set_border_delta(&self, border_delta: RectDelta);
    method total_border_delta (line 67) | fn total_border_delta(&self) -> anyhow::Result<RectDelta> {
    method should_fullscreen (line 102) | fn should_fullscreen(
    method display_state (line 127) | fn display_state(&self) -> DisplayState;
    method set_display_state (line 129) | fn set_display_state(&self, display_state: DisplayState);
    method has_pending_dpi_adjustment (line 133) | fn has_pending_dpi_adjustment(&self) -> bool;
    method set_has_pending_dpi_adjustment (line 135) | fn set_has_pending_dpi_adjustment(
    method floating_placement (line 140) | fn floating_placement(&self) -> Rect;
    method set_floating_placement (line 142) | fn set_floating_placement(&self, floating_placement: Rect);
    method has_custom_floating_placement (line 144) | fn has_custom_floating_placement(&self) -> bool;
    method set_has_custom_floating_placement (line 146) | fn set_has_custom_floating_placement(
    method done_window_rules (line 151) | fn done_window_rules(&self) -> Vec<WindowRuleConfig>;
    method set_done_window_rules (line 153) | fn set_done_window_rules(
    method active_drag (line 158) | fn active_drag(&self) -> Option<ActiveDrag>;
    method set_active_drag (line 160) | fn set_active_drag(&self, active_drag: Option<ActiveDrag>);
    method native_properties (line 163) | fn native_properties(&self) -> NativeWindowProperties;
    method update_native_properties (line 166) | fn update_native_properties<F>(&self, updater: F)

FILE: packages/wm/src/user_config.rs
  constant SAMPLE_CONFIG (line 15) | const SAMPLE_CONFIG: &str =
  type UserConfig (line 19) | pub struct UserConfig {
    method new (line 39) | pub fn new(config_path: Option<PathBuf>) -> anyhow::Result<Self> {
    method read (line 63) | fn read(
    method create_sample (line 81) | fn create_sample(config_path: &PathBuf) -> Result<()> {
    method reload (line 96) | pub fn reload(&mut self) -> anyhow::Result<()> {
    method default_window_rules (line 107) | fn default_window_rules(
    method window_rules_by_event (line 196) | fn window_rules_by_event(
    method pending_window_rules (line 222) | pub fn pending_window_rules(
    method inactive_workspace_configs (line 287) | pub fn inactive_workspace_configs(
    method workspace_config_for_monitor (line 303) | pub fn workspace_config_for_monitor(
    method next_inactive_workspace_config (line 323) | pub fn next_inactive_workspace_config(
    method workspace_config_index (line 337) | pub fn workspace_config_index(
    method sort_workspaces (line 348) | pub fn sort_workspaces(&self, workspaces: &mut [Workspace]) {
    method active_keybinding_configs (line 359) | pub fn active_keybinding_configs(

FILE: packages/wm/src/wm.rs
  type WindowManager (line 52) | pub struct WindowManager {
    method new (line 59) | pub fn new(
    method process_event (line 76) | pub fn process_event(
    method process_commands (line 153) | pub fn process_commands(
    method run_commands (line 185) | pub fn run_commands(
    method run_command (line 218) | pub fn run_command(
    method cleanup (line 783) | pub(crate) fn cleanup(

FILE: packages/wm/src/wm_state.rs
  type WmState (line 30) | pub struct WmState {
    method new (line 81) | pub fn new(
    method populate (line 105) | pub fn populate(
    method monitors (line 169) | pub fn monitors(&self) -> Vec<Monitor> {
    method workspaces (line 173) | pub fn workspaces(&self) -> Vec<Workspace> {
    method sorted_workspaces (line 182) | pub fn sorted_workspaces(&self, config: &UserConfig) -> Vec<Workspace> {
    method windows (line 188) | pub fn windows(&self) -> Vec<WindowContainer> {
    method nearest_monitor (line 200) | pub fn nearest_monitor(
    method monitor_from_native (line 212) | pub fn monitor_from_native(
    method monitor_in_direction (line 225) | pub fn monitor_in_direction(
    method monitors_by_hide_corner (line 276) | pub fn monitors_by_hide_corner(&self) -> Vec<(Monitor, HideCorner)> {
    method window_from_native (line 331) | pub fn window_from_native(
    method workspace_by_name (line 341) | pub fn workspace_by_name(
    method workspace_by_target (line 356) | pub fn workspace_by_target(
    method windows_to_redraw (line 535) | pub fn windows_to_redraw(&self) -> Vec<WindowContainer> {
    method focused_container (line 548) | pub fn focused_container(&self) -> Option<Container> {
    method emit_event (line 558) | pub fn emit_event(&self, event: WmEvent) {
    method emit_exit (line 569) | pub fn emit_exit(&self) -> anyhow::Result<()> {
    method container_by_id (line 574) | pub fn container_by_id(&self, id: Uuid) -> Option<Container> {
    method focus_target_after_removal (line 583) | pub fn focus_target_after_removal(
    method containers_at_point (line 631) | pub fn containers_at_point(
    method monitor_at_point (line 647) | pub fn monitor_at_point(&self, point: &Point) -> Option<Monitor> {
    method cleanup_invalid_windows (line 666) | pub fn cleanup_invalid_windows(&mut self) -> anyhow::Result<()> {
  method drop (line 682) | fn drop(&mut self) {
Condensed preview — 214 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (973K chars).
[
  {
    "path": ".cargo/config.toml",
    "chars": 184,
    "preview": "[env]\r\n# Version number shown in CLI and system tray. Override this by setting the\r\n# version number on build/run (i.e. "
  },
  {
    "path": ".editorconfig",
    "chars": 225,
    "preview": "# Editor configuration, see https://editorconfig.org\r\nroot = true\r\n\r\n[*]\r\ncharset = utf-8\r\nindent_style = space\r\nindent_"
  },
  {
    "path": ".gitattributes",
    "chars": 109,
    "preview": "# Set CRLF as the line ending to use for all files that Git interprets as text files.\r\n* text=auto eol=crlf\r\n"
  },
  {
    "path": ".github/workflows/build.yaml",
    "chars": 2483,
    "preview": "name: Build\r\n\r\non:\r\n  workflow_call:\r\n    inputs:\r\n      enable_ui_access:\r\n        type: boolean\r\n        default: fals"
  },
  {
    "path": ".github/workflows/lint-check.yaml",
    "chars": 1151,
    "preview": "name: Lint check\r\n\r\non:\r\n  push:\r\n  pull_request:\r\n    types: [opened, synchronize, reopened]\r\n\r\njobs:\r\n  lint-check:\r\n "
  },
  {
    "path": ".github/workflows/package.yaml",
    "chars": 7719,
    "preview": "name: Package\r\n\r\non:\r\n  workflow_call:\r\n    inputs:\r\n      version_number:\r\n        type: string\r\n        default: 0.0.0"
  },
  {
    "path": ".github/workflows/pr-title-check.yaml",
    "chars": 279,
    "preview": "name: PR title check\r\n\r\non:\r\n  pull_request:\r\n    types: [opened, edited, synchronize, reopened]\r\n\r\njobs:\r\n  pr-title-ch"
  },
  {
    "path": ".github/workflows/release.yaml",
    "chars": 1772,
    "preview": "name: Release\r\n\r\non:\r\n  workflow_dispatch:\r\n    inputs:\r\n      version_number:\r\n        type: string\r\n        descriptio"
  },
  {
    "path": ".github/workflows/winget-release.yaml",
    "chars": 388,
    "preview": "name: Winget release\r\n\r\non:\r\n  workflow_dispatch:\r\n  release:\r\n    types: [published]\r\n\r\njobs:\r\n  publish:\r\n    runs-on:"
  },
  {
    "path": ".gitignore",
    "chars": 192,
    "preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\r\n\r\n# Build outputs\r\ntarget/\r\nout/\r"
  },
  {
    "path": ".vscode/launch.json",
    "chars": 447,
    "preview": "{\r\n  \"version\": \"0.2.0\",\r\n  \"configurations\": [\r\n    {\r\n      \"name\": \"Launch\",\r\n      \"type\": \"cppvsdbg\",\r\n      \"reque"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 184,
    "preview": "{\r\n  \"rust-analyzer.check.command\": \"clippy\",\r\n  \"editor.insertSpaces\": true,\r\n  \"editor.tabSize\": 2,\r\n  \"files.insertFi"
  },
  {
    "path": ".vscode/tasks.json",
    "chars": 211,
    "preview": "{\r\n  \"version\": \"2.0.0\",\r\n  \"tasks\": [\r\n    {\r\n      \"type\": \"cargo\",\r\n      \"command\": \"build\",\r\n      \"problemMatcher\""
  },
  {
    "path": "CLAUDE.md",
    "chars": 2572,
    "preview": "<project_overview>\r\nGlazeWM is a window manager for macOS and Windows, written in Rust.\r\n\r\nCrate structure:\r\n\r\n- **wm** "
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 5864,
    "preview": "# Contributing to GlazeWM\r\n\r\nThanks for your interest in improving GlazeWM 💛\r\n\r\nThere are fundamentally three ways to co"
  },
  {
    "path": "Cargo.toml",
    "chars": 856,
    "preview": "[workspace]\r\nresolver = \"2\"\r\nmembers = [\"packages/*\"]\r\ndefault-members = [\"packages/wm\", \"packages/wm-cli\"]\r\n\r\n[workspac"
  },
  {
    "path": "LICENSE.md",
    "chars": 35823,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\r\n                       Version 3, 29 June 2007\r\n\r\n Copyright (C) 2007 Fr"
  },
  {
    "path": "README.md",
    "chars": 18139,
    "preview": "<div align=\"center\">\r\n\r\n> V3 is finally out - check out the changelog [here](https://github.com/glzr-io/GlazeWM/releases"
  },
  {
    "path": "README_zh.md",
    "chars": 12265,
    "preview": "<div align=\"center\">\r\n\r\n> V3 终于发布了 - 查看更新日志 [这里](https://github.com/glzr-io/GlazeWM/releases) 🔥\r\n\r\n  <br>\r\n  <img src=\"."
  },
  {
    "path": "clippy.toml",
    "chars": 210,
    "preview": "# TODO: Would ideally move this to `Cargo.toml`, but it's not supported yet.\r\n# Ref: https://github.com/rust-lang/cargo/"
  },
  {
    "path": "packages/wm/Cargo.toml",
    "chars": 1137,
    "preview": "[package]\r\nname = \"wm\"\r\nversion = \"0.0.0\"\r\ndescription = \"GlazeWM is a tiling window manager for Windows inspired by i3 "
  },
  {
    "path": "packages/wm/build.rs",
    "chars": 2728,
    "preview": "use tauri_winres::VersionInfo;\r\n\r\nfn main() {\r\n  println!(\"cargo:rerun-if-env-changed=VERSION_NUMBER\");\r\n  let mut res ="
  },
  {
    "path": "packages/wm/src/commands/container/attach_container.rs",
    "chars": 1691,
    "preview": "use anyhow::bail;\r\n\r\nuse super::resize_tiling_container;\r\nuse crate::{\r\n  models::Container,\r\n  traits::{CommonGetters, "
  },
  {
    "path": "packages/wm/src/commands/container/detach_container.rs",
    "chars": 1882,
    "preview": "use anyhow::Context;\r\n\r\nuse super::flatten_split_container;\r\nuse crate::{\r\n  models::Container,\r\n  traits::{CommonGetter"
  },
  {
    "path": "packages/wm/src/commands/container/flatten_child_split_containers.rs",
    "chars": 1874,
    "preview": "use super::flatten_split_container;\r\nuse crate::{\r\n  models::Container,\r\n  traits::{CommonGetters, TilingDirectionGetter"
  },
  {
    "path": "packages/wm/src/commands/container/flatten_split_container.rs",
    "chars": 1932,
    "preview": "use std::collections::VecDeque;\r\n\r\nuse anyhow::Context;\r\n\r\nuse crate::{\r\n  models::SplitContainer,\r\n  traits::{CommonGet"
  },
  {
    "path": "packages/wm/src/commands/container/focus_container_by_id.rs",
    "chars": 497,
    "preview": "use anyhow::Context;\r\nuse uuid::Uuid;\r\n\r\nuse super::set_focused_descendant;\r\nuse crate::wm_state::WmState;\r\n\r\npub fn foc"
  },
  {
    "path": "packages/wm/src/commands/container/focus_in_direction.rs",
    "chars": 5423,
    "preview": "use anyhow::Context;\r\nuse wm_common::{TilingDirection, WindowState};\r\nuse wm_platform::Direction;\r\n\r\nuse super::set_focu"
  },
  {
    "path": "packages/wm/src/commands/container/mod.rs",
    "chars": 770,
    "preview": "mod attach_container;\r\nmod detach_container;\r\nmod flatten_child_split_containers;\r\nmod flatten_split_container;\r\nmod foc"
  },
  {
    "path": "packages/wm/src/commands/container/move_container_within_tree.rs",
    "chars": 6901,
    "preview": "use anyhow::Context;\r\nuse wm_common::{VecDequeExt, WmEvent};\r\n\r\nuse super::{\r\n  attach_container, detach_container, flat"
  },
  {
    "path": "packages/wm/src/commands/container/replace_container.rs",
    "chars": 1916,
    "preview": "use anyhow::{bail, Context};\r\nuse wm_common::VecDequeExt;\r\n\r\nuse super::{attach_container, detach_container, resize_tili"
  },
  {
    "path": "packages/wm/src/commands/container/resize_tiling_container.rs",
    "chars": 1615,
    "preview": "use crate::{\r\n  models::TilingContainer,\r\n  traits::{CommonGetters, TilingSizeGetters, MIN_TILING_SIZE},\r\n};\r\n\r\npub fn r"
  },
  {
    "path": "packages/wm/src/commands/container/set_focused_descendant.rs",
    "chars": 797,
    "preview": "use wm_common::VecDequeExt;\r\n\r\nuse crate::{models::Container, traits::CommonGetters};\r\n\r\n/// Set a given container as th"
  },
  {
    "path": "packages/wm/src/commands/container/toggle_tiling_direction.rs",
    "chars": 2759,
    "preview": "use anyhow::Context;\r\nuse wm_common::{TilingDirection, WmEvent};\r\n\r\nuse super::{flatten_split_container, wrap_in_split_c"
  },
  {
    "path": "packages/wm/src/commands/container/wrap_in_split_container.rs",
    "chars": 2367,
    "preview": "use std::collections::VecDeque;\r\n\r\nuse anyhow::Context;\r\n\r\nuse crate::{\r\n  models::{Container, SplitContainer, TilingCon"
  },
  {
    "path": "packages/wm/src/commands/general/cycle_focus.rs",
    "chars": 2938,
    "preview": "use anyhow::Context;\r\nuse wm_common::WindowState;\r\n\r\nuse crate::{\r\n  commands::container::set_focused_descendant,\r\n  tra"
  },
  {
    "path": "packages/wm/src/commands/general/disable_binding_mode.rs",
    "chars": 389,
    "preview": "use wm_common::WmEvent;\r\n\r\nuse crate::wm_state::WmState;\r\n\r\npub fn disable_binding_mode(name: &str, state: &mut WmState)"
  },
  {
    "path": "packages/wm/src/commands/general/enable_binding_mode.rs",
    "chars": 624,
    "preview": "use anyhow::Context;\r\nuse wm_common::WmEvent;\r\n\r\nuse crate::{user_config::UserConfig, wm_state::WmState};\r\n\r\npub fn enab"
  },
  {
    "path": "packages/wm/src/commands/general/mod.rs",
    "chars": 345,
    "preview": "mod cycle_focus;\r\nmod disable_binding_mode;\r\nmod enable_binding_mode;\r\nmod platform_sync;\r\nmod reload_config;\r\nmod shell"
  },
  {
    "path": "packages/wm/src/commands/general/platform_sync.rs",
    "chars": 19428,
    "preview": "use anyhow::Context;\r\n#[cfg(target_os = \"windows\")]\r\nuse wm_common::WindowEffectConfig;\r\nuse wm_common::{\r\n  CursorJumpT"
  },
  {
    "path": "packages/wm/src/commands/general/reload_config.rs",
    "chars": 5770,
    "preview": "use anyhow::Context;\r\nuse tracing::{info, warn};\r\n#[cfg(target_os = \"windows\")]\r\nuse wm_common::{HideMethod, ParsedConfi"
  },
  {
    "path": "packages/wm/src/commands/general/shell_exec.rs",
    "chars": 4829,
    "preview": "use std::path::Path;\r\n\r\n#[cfg(target_os = \"windows\")]\r\nuse anyhow::Context;\r\n#[cfg(target_os = \"macos\")]\r\nuse shell_util"
  },
  {
    "path": "packages/wm/src/commands/general/toggle_pause.rs",
    "chars": 436,
    "preview": "use wm_common::WmEvent;\r\n\r\nuse crate::wm_state::WmState;\r\n\r\n/// Pauses or unpauses the WM.\r\npub fn toggle_pause(state: &"
  },
  {
    "path": "packages/wm/src/commands/mod.rs",
    "chars": 93,
    "preview": "pub mod container;\r\npub mod general;\r\npub mod monitor;\r\npub mod window;\r\npub mod workspace;\r\n"
  },
  {
    "path": "packages/wm/src/commands/monitor/add_monitor.rs",
    "chars": 4265,
    "preview": "use anyhow::Context;\r\nuse tracing::info;\r\nuse wm_common::WmEvent;\r\nuse wm_platform::Display;\r\n\r\nuse crate::{\r\n  commands"
  },
  {
    "path": "packages/wm/src/commands/monitor/focus_monitor.rs",
    "chars": 759,
    "preview": "use anyhow::Context;\r\n\r\nuse crate::{\r\n  commands::workspace::focus_workspace, models::WorkspaceTarget,\r\n  user_config::U"
  },
  {
    "path": "packages/wm/src/commands/monitor/mod.rs",
    "chars": 237,
    "preview": "mod add_monitor;\r\nmod focus_monitor;\r\nmod remove_monitor;\r\nmod sort_monitors;\r\nmod update_monitor;\r\n\r\npub use add_monito"
  },
  {
    "path": "packages/wm/src/commands/monitor/remove_monitor.rs",
    "chars": 1499,
    "preview": "use anyhow::Context;\r\nuse tracing::info;\r\nuse wm_common::WmEvent;\r\n\r\nuse crate::{\r\n  commands::{\r\n    container::{detach"
  },
  {
    "path": "packages/wm/src/commands/monitor/sort_monitors.rs",
    "chars": 926,
    "preview": "use crate::{\r\n  models::RootContainer,\r\n  traits::{CommonGetters, PositionGetters},\r\n};\r\n\r\n/// Sorts the root container'"
  },
  {
    "path": "packages/wm/src/commands/monitor/update_monitor.rs",
    "chars": 656,
    "preview": "use tracing::info;\r\nuse wm_common::WmEvent;\r\nuse wm_platform::Display;\r\n\r\nuse crate::{\r\n  models::{Monitor, NativeMonito"
  },
  {
    "path": "packages/wm/src/commands/window/ignore_window.rs",
    "chars": 1354,
    "preview": "use anyhow::Context;\r\nuse wm_common::WindowState;\r\n\r\nuse crate::{\r\n  commands::container::{\r\n    detach_container, flatt"
  },
  {
    "path": "packages/wm/src/commands/window/manage_window.rs",
    "chars": 10675,
    "preview": "use anyhow::Context;\r\nuse tracing::info;\r\nuse wm_common::{try_warn, WindowRuleEvent, WindowState, WmEvent};\r\nuse wm_plat"
  },
  {
    "path": "packages/wm/src/commands/window/mod.rs",
    "chars": 554,
    "preview": "mod ignore_window;\r\nmod manage_window;\r\nmod move_window_in_direction;\r\nmod move_window_to_workspace;\r\nmod resize_window;"
  },
  {
    "path": "packages/wm/src/commands/window/move_window_in_direction.rs",
    "chars": 16444,
    "preview": "use anyhow::Context;\r\nuse wm_common::{TilingDirection, WindowState};\r\nuse wm_platform::{Direction, Rect};\r\n\r\nuse crate::"
  },
  {
    "path": "packages/wm/src/commands/window/move_window_to_workspace.rs",
    "chars": 4644,
    "preview": "use anyhow::Context;\r\nuse tracing::info;\r\nuse wm_common::WindowState;\r\n\r\nuse crate::{\r\n  commands::{\r\n    container::{mo"
  },
  {
    "path": "packages/wm/src/commands/window/resize_window.rs",
    "chars": 2728,
    "preview": "use wm_platform::LengthValue;\r\n\r\nuse super::set_window_size;\r\nuse crate::{\r\n  models::WindowContainer,\r\n  traits::{Commo"
  },
  {
    "path": "packages/wm/src/commands/window/run_window_rules.rs",
    "chars": 1624,
    "preview": "use tracing::info;\r\nuse wm_common::WindowRuleEvent;\r\n\r\nuse crate::{\r\n  models::WindowContainer,\r\n  traits::{CommonGetter"
  },
  {
    "path": "packages/wm/src/commands/window/set_window_position.rs",
    "chars": 1433,
    "preview": "use anyhow::Context;\r\nuse wm_common::WindowState;\r\nuse wm_platform::Rect;\r\n\r\nuse crate::{\r\n  models::WindowContainer,\r\n "
  },
  {
    "path": "packages/wm/src/commands/window/set_window_size.rs",
    "chars": 4529,
    "preview": "use anyhow::Context;\r\nuse wm_common::WindowState;\r\nuse wm_platform::{LengthValue, Rect};\r\n\r\nuse crate::{\r\n  commands::co"
  },
  {
    "path": "packages/wm/src/commands/window/unmanage_window.rs",
    "chars": 1977,
    "preview": "use anyhow::Context;\r\nuse wm_common::{WindowState, WmEvent};\r\n\r\nuse crate::{\r\n  commands::container::{\r\n    detach_conta"
  },
  {
    "path": "packages/wm/src/commands/window/update_window_state.rs",
    "chars": 6516,
    "preview": "use anyhow::Context;\r\nuse tracing::{info, warn};\r\nuse wm_common::WindowState;\r\n\r\nuse crate::{\r\n  commands::container::{\r"
  },
  {
    "path": "packages/wm/src/commands/workspace/activate_workspace.rs",
    "chars": 3159,
    "preview": "use anyhow::Context;\r\nuse tracing::info;\r\nuse wm_common::{TilingDirection, WmEvent, WorkspaceConfig};\r\n\r\nuse super::sort"
  },
  {
    "path": "packages/wm/src/commands/workspace/deactivate_workspace.rs",
    "chars": 711,
    "preview": "use tracing::info;\r\nuse wm_common::WmEvent;\r\n\r\nuse crate::{\r\n  commands::container::detach_container, models::Workspace,"
  },
  {
    "path": "packages/wm/src/commands/workspace/focus_workspace.rs",
    "chars": 3087,
    "preview": "use anyhow::Context;\r\nuse tracing::info;\r\n\r\nuse super::activate_workspace;\r\nuse crate::{\r\n  commands::{\r\n    container::"
  },
  {
    "path": "packages/wm/src/commands/workspace/mod.rs",
    "chars": 364,
    "preview": "mod activate_workspace;\r\nmod deactivate_workspace;\r\nmod focus_workspace;\r\nmod move_workspace_in_direction;\r\nmod sort_wor"
  },
  {
    "path": "packages/wm/src/commands/workspace/move_workspace_in_direction.rs",
    "chars": 2752,
    "preview": "use anyhow::Context;\r\nuse wm_common::WmEvent;\r\nuse wm_platform::Direction;\r\n\r\nuse super::{activate_workspace, deactivate"
  },
  {
    "path": "packages/wm/src/commands/workspace/sort_workspaces.rs",
    "chars": 733,
    "preview": "use anyhow::Context;\r\nuse wm_common::VecDequeExt;\r\n\r\nuse crate::{\r\n  models::Monitor, traits::CommonGetters, user_config"
  },
  {
    "path": "packages/wm/src/commands/workspace/update_workspace_config.rs",
    "chars": 1588,
    "preview": "use anyhow::Context;\r\nuse wm_common::{InvokeUpdateWorkspaceConfig, WmEvent, WorkspaceConfig};\r\n\r\nuse super::sort_workspa"
  },
  {
    "path": "packages/wm/src/events/handle_display_settings_changed.rs",
    "chars": 5618,
    "preview": "use anyhow::Context;\r\nuse wm_common::try_warn;\r\n\r\nuse crate::{\r\n  commands::monitor::{\r\n    add_monitor, move_bounded_wo"
  },
  {
    "path": "packages/wm/src/events/handle_mouse_move.rs",
    "chars": 4198,
    "preview": "use anyhow::Context;\r\n#[cfg(target_os = \"macos\")]\r\nuse wm_common::try_warn;\r\nuse wm_platform::{MouseButton, MouseEvent};"
  },
  {
    "path": "packages/wm/src/events/handle_window_destroyed.rs",
    "chars": 1031,
    "preview": "use anyhow::Context;\r\nuse tracing::info;\r\nuse wm_platform::WindowId;\r\n\r\nuse crate::{\r\n  commands::{window::unmanage_wind"
  },
  {
    "path": "packages/wm/src/events/handle_window_focused.rs",
    "chars": 3866,
    "preview": "use anyhow::Context;\r\nuse tracing::info;\r\nuse wm_common::{DisplayState, WindowRuleEvent, WmEvent};\r\nuse wm_platform::Nat"
  },
  {
    "path": "packages/wm/src/events/handle_window_hidden.rs",
    "chars": 1176,
    "preview": "use tracing::info;\r\nuse wm_common::{DisplayState, HideMethod};\r\nuse wm_platform::NativeWindow;\r\n\r\nuse crate::{\r\n  comman"
  },
  {
    "path": "packages/wm/src/events/handle_window_minimize_ended.rs",
    "chars": 1058,
    "preview": "use tracing::info;\r\nuse wm_common::{try_warn, WindowState};\r\nuse wm_platform::NativeWindow;\r\n\r\nuse crate::{\r\n  commands:"
  },
  {
    "path": "packages/wm/src/events/handle_window_minimized.rs",
    "chars": 1734,
    "preview": "use tracing::info;\r\nuse wm_common::{try_warn, WindowState};\r\nuse wm_platform::NativeWindow;\r\n\r\nuse crate::{\r\n  commands:"
  },
  {
    "path": "packages/wm/src/events/handle_window_moved_or_resized.rs",
    "chars": 19294,
    "preview": "use anyhow::Context;\r\nuse wm_common::{\r\n  try_warn, ActiveDrag, ActiveDragOperation, DisplayState,\r\n  FloatingStateConfi"
  },
  {
    "path": "packages/wm/src/events/handle_window_moved_or_resized_end.rs",
    "chars": 9519,
    "preview": "use anyhow::Context;\r\nuse wm_common::{\r\n  try_warn, FullscreenStateConfig, TilingDirection, WindowState,\r\n};\r\nuse wm_pla"
  },
  {
    "path": "packages/wm/src/events/handle_window_shown.rs",
    "chars": 978,
    "preview": "use tracing::info;\r\nuse wm_common::{DisplayState, HideMethod};\r\nuse wm_platform::NativeWindow;\r\n\r\nuse crate::{\r\n  comman"
  },
  {
    "path": "packages/wm/src/events/handle_window_title_changed.rs",
    "chars": 865,
    "preview": "use tracing::info;\r\nuse wm_common::{try_warn, WindowRuleEvent};\r\nuse wm_platform::NativeWindow;\r\n\r\nuse crate::{\r\n  comma"
  },
  {
    "path": "packages/wm/src/events/mod.rs",
    "chars": 779,
    "preview": "mod handle_display_settings_changed;\r\nmod handle_mouse_move;\r\nmod handle_window_destroyed;\r\nmod handle_window_focused;\r\n"
  },
  {
    "path": "packages/wm/src/ipc_server.rs",
    "chars": 12673,
    "preview": "use std::{iter, net::SocketAddr};\r\n\r\nuse anyhow::{bail, Context};\r\nuse clap::Parser;\r\nuse futures_util::{SinkExt, Stream"
  },
  {
    "path": "packages/wm/src/main.rs",
    "chars": 11722,
    "preview": "// The `windows` or `console` subsystem (default is `console`) determines\r\n// whether a console window is spawned on lau"
  },
  {
    "path": "packages/wm/src/models/container.rs",
    "chars": 5576,
    "preview": "use std::{\r\n  cell::{Ref, RefMut},\r\n  collections::VecDeque,\r\n};\r\n\r\nuse ambassador::Delegate;\r\nuse enum_as_inner::EnumAs"
  },
  {
    "path": "packages/wm/src/models/insertion_target.rs",
    "chars": 216,
    "preview": "use crate::models::Container;\r\n\r\n#[derive(Debug, Clone)]\r\npub struct InsertionTarget {\r\n  pub target_parent: Container,\r"
  },
  {
    "path": "packages/wm/src/models/mod.rs",
    "chars": 563,
    "preview": "mod container;\r\nmod insertion_target;\r\nmod monitor;\r\nmod native_monitor_properties;\r\nmod native_window_properties;\r\nmod "
  },
  {
    "path": "packages/wm/src/models/monitor.rs",
    "chars": 4140,
    "preview": "use std::{\r\n  cell::{Ref, RefCell, RefMut},\r\n  collections::VecDeque,\r\n  rc::Rc,\r\n};\r\n\r\nuse anyhow::Context;\r\nuse uuid::"
  },
  {
    "path": "packages/wm/src/models/native_monitor_properties.rs",
    "chars": 1323,
    "preview": "use wm_platform::{Display, Rect};\r\n#[cfg(target_os = \"windows\")]\r\nuse wm_platform::{DisplayDeviceExtWindows, DisplayExtW"
  },
  {
    "path": "packages/wm/src/models/native_window_properties.rs",
    "chars": 1134,
    "preview": "use wm_platform::{NativeWindow, Rect};\r\n#[cfg(target_os = \"windows\")]\r\nuse wm_platform::{NativeWindowWindowsExt, RectDel"
  },
  {
    "path": "packages/wm/src/models/non_tiling_window.rs",
    "chars": 4830,
    "preview": "use std::{\r\n  cell::{Ref, RefCell, RefMut},\r\n  collections::VecDeque,\r\n  rc::Rc,\r\n};\r\n\r\nuse anyhow::Context;\r\nuse uuid::"
  },
  {
    "path": "packages/wm/src/models/root_container.rs",
    "chars": 1833,
    "preview": "use std::{\r\n  cell::{Ref, RefCell, RefMut},\r\n  collections::VecDeque,\r\n  rc::Rc,\r\n};\r\n\r\nuse anyhow::bail;\r\nuse uuid::Uui"
  },
  {
    "path": "packages/wm/src/models/split_container.rs",
    "chars": 2237,
    "preview": "use std::{\r\n  cell::{Ref, RefCell, RefMut},\r\n  collections::VecDeque,\r\n  rc::Rc,\r\n};\r\n\r\nuse anyhow::Context;\r\nuse uuid::"
  },
  {
    "path": "packages/wm/src/models/tiling_window.rs",
    "chars": 4144,
    "preview": "use std::{\r\n  cell::{Ref, RefCell, RefMut},\r\n  collections::VecDeque,\r\n  rc::Rc,\r\n};\r\n\r\nuse anyhow::Context;\r\nuse uuid::"
  },
  {
    "path": "packages/wm/src/models/workspace.rs",
    "chars": 5774,
    "preview": "use std::{\r\n  cell::{Ref, RefCell, RefMut},\r\n  collections::VecDeque,\r\n  rc::Rc,\r\n};\r\n\r\nuse anyhow::Context;\r\nuse uuid::"
  },
  {
    "path": "packages/wm/src/models/workspace_target.rs",
    "chars": 246,
    "preview": "use wm_platform::Direction;\r\n\r\npub enum WorkspaceTarget {\r\n  Name(String),\r\n  Recent,\r\n  NextActive,\r\n  PreviousActive,\r"
  },
  {
    "path": "packages/wm/src/pending_sync.rs",
    "chars": 3616,
    "preview": "use std::collections::HashMap;\r\n\r\nuse uuid::Uuid;\r\n\r\nuse crate::{\r\n  models::{Container, Workspace},\r\n  traits::CommonGe"
  },
  {
    "path": "packages/wm/src/sys_tray.rs",
    "chars": 8059,
    "preview": "use std::{\r\n  fmt::{self, Display},\r\n  path::Path,\r\n  str::FromStr,\r\n  sync::{Arc, Mutex},\r\n};\r\n\r\nuse anyhow::Context;\r\n"
  },
  {
    "path": "packages/wm/src/traits/common_getters.rs",
    "chars": 10229,
    "preview": "use std::{\r\n  cell::{Ref, RefMut},\r\n  collections::VecDeque,\r\n};\r\n\r\nuse ambassador::delegatable_trait;\r\nuse uuid::Uuid;\r"
  },
  {
    "path": "packages/wm/src/traits/mod.rs",
    "chars": 281,
    "preview": "mod common_getters;\r\nmod position_getters;\r\nmod tiling_direction_getters;\r\nmod tiling_size_getters;\r\nmod window_getters;"
  },
  {
    "path": "packages/wm/src/traits/position_getters.rs",
    "chars": 2877,
    "preview": "use ambassador::delegatable_trait;\r\nuse wm_platform::Rect;\r\n\r\n#[delegatable_trait]\r\npub trait PositionGetters {\r\n  fn to"
  },
  {
    "path": "packages/wm/src/traits/tiling_direction_getters.rs",
    "chars": 2215,
    "preview": "use ambassador::delegatable_trait;\r\nuse wm_common::TilingDirection;\r\nuse wm_platform::Direction;\r\n\r\nuse super::CommonGet"
  },
  {
    "path": "packages/wm/src/traits/tiling_size_getters.rs",
    "chars": 3365,
    "preview": "use std::cell::Ref;\r\n\r\nuse ambassador::delegatable_trait;\r\nuse anyhow::Context;\r\nuse wm_common::{GapsConfig, TilingDirec"
  },
  {
    "path": "packages/wm/src/traits/window_getters.rs",
    "chars": 8779,
    "preview": "use std::cell::Ref;\r\n\r\nuse ambassador::delegatable_trait;\r\nuse wm_common::{ActiveDrag, DisplayState, WindowRuleConfig, W"
  },
  {
    "path": "packages/wm/src/user_config.rs",
    "chars": 11477,
    "preview": "use std::{collections::HashMap, env, fs, path::PathBuf};\r\n\r\nuse anyhow::{Context, Result};\r\nuse wm_common::{\r\n  InvokeCo"
  },
  {
    "path": "packages/wm/src/wm.rs",
    "chars": 23967,
    "preview": "use anyhow::{bail, Context};\r\nuse tokio::sync::mpsc::{self};\r\nuse tracing::warn;\r\nuse uuid::Uuid;\r\n#[cfg(target_os = \"wi"
  },
  {
    "path": "packages/wm/src/wm_state.rs",
    "chars": 22707,
    "preview": "use std::time::Instant;\r\n\r\nuse anyhow::Context;\r\nuse tokio::sync::mpsc::{self};\r\nuse tracing::warn;\r\nuse uuid::Uuid;\r\nus"
  },
  {
    "path": "packages/wm-cli/Cargo.toml",
    "chars": 519,
    "preview": "[package]\r\nname = \"wm-cli\"\r\nversion = \"0.0.0\"\r\nedition = \"2021\"\r\n\r\n[lib]\r\npath = \"src/lib.rs\"\r\n\r\n[[bin]]\r\nname = \"glazew"
  },
  {
    "path": "packages/wm-cli/build.rs",
    "chars": 1090,
    "preview": "use tauri_winres::VersionInfo;\r\n\r\nfn main() {\r\n  println!(\"cargo:rerun-if-env-changed=VERSION_NUMBER\");\r\n  let mut res ="
  },
  {
    "path": "packages/wm-cli/src/lib.rs",
    "chars": 1245,
    "preview": "#![warn(clippy::all, clippy::pedantic)]\r\n#![allow(clippy::missing_errors_doc)]\r\n\r\nuse anyhow::Context;\r\nuse wm_common::C"
  },
  {
    "path": "packages/wm-cli/src/main.rs",
    "chars": 1509,
    "preview": "use std::{env, process::Command};\r\n\r\nuse anyhow::Context;\r\nuse wm_cli::start;\r\nuse wm_common::AppCommand;\r\n\r\n#[tokio::ma"
  },
  {
    "path": "packages/wm-common/Cargo.toml",
    "chars": 342,
    "preview": "[package]\r\nname = \"wm-common\"\r\nversion = \"0.0.0\"\r\nedition = \"2021\"\r\n\r\n[lib]\r\npath = \"src/lib.rs\"\r\n\r\n[dependencies]\r\nanyh"
  },
  {
    "path": "packages/wm-common/src/active_drag.rs",
    "chars": 673,
    "preview": "use serde::{Deserialize, Serialize};\r\nuse wm_platform::Rect;\r\n\r\n#[derive(Debug, Clone, Deserialize, Serialize)]\r\npub str"
  },
  {
    "path": "packages/wm-common/src/app_command.rs",
    "chars": 11610,
    "preview": "use std::{iter, path::PathBuf};\r\n\r\nuse clap::{error::KindFormatter, Args, Parser, ValueEnum};\r\nuse serde::{Deserialize, "
  },
  {
    "path": "packages/wm-common/src/display_state.rs",
    "chars": 295,
    "preview": "use serde::{Deserialize, Serialize};\r\n\r\n/// Represents whether something is shown, hidden, or in an intermediary\r\n/// st"
  },
  {
    "path": "packages/wm-common/src/dtos/container_dto.rs",
    "chars": 487,
    "preview": "use serde::{Deserialize, Serialize};\r\n\r\nuse super::{\r\n  MonitorDto, RootContainerDto, SplitContainerDto, WindowDto, Work"
  },
  {
    "path": "packages/wm-common/src/dtos/mod.rs",
    "chars": 296,
    "preview": "mod container_dto;\r\nmod monitor_dto;\r\nmod root_container_dto;\r\nmod split_container_dto;\r\nmod window_dto;\r\nmod workspace_"
  },
  {
    "path": "packages/wm-common/src/dtos/monitor_dto.rs",
    "chars": 727,
    "preview": "use serde::{Deserialize, Serialize};\r\nuse uuid::Uuid;\r\nuse wm_platform::Rect;\r\n\r\nuse super::ContainerDto;\r\n\r\n/// User-fr"
  },
  {
    "path": "packages/wm-common/src/dtos/root_container_dto.rs",
    "chars": 423,
    "preview": "use serde::{Deserialize, Serialize};\r\nuse uuid::Uuid;\r\n\r\nuse super::ContainerDto;\r\n\r\n/// User-friendly representation of"
  },
  {
    "path": "packages/wm-common/src/dtos/split_container_dto.rs",
    "chars": 614,
    "preview": "use serde::{Deserialize, Serialize};\r\nuse uuid::Uuid;\r\n\r\nuse super::ContainerDto;\r\nuse crate::TilingDirection;\r\n\r\n/// Us"
  },
  {
    "path": "packages/wm-common/src/dtos/window_dto.rs",
    "chars": 887,
    "preview": "use serde::{Deserialize, Serialize};\r\nuse uuid::Uuid;\r\nuse wm_platform::{Rect, RectDelta};\r\n\r\nuse crate::{ActiveDrag, Di"
  },
  {
    "path": "packages/wm-common/src/dtos/workspace_dto.rs",
    "chars": 663,
    "preview": "use serde::{Deserialize, Serialize};\r\nuse uuid::Uuid;\r\n\r\nuse super::ContainerDto;\r\nuse crate::TilingDirection;\r\n\r\n/// Us"
  },
  {
    "path": "packages/wm-common/src/hide_corner.rs",
    "chars": 174,
    "preview": "/// Represents the corner of a monitor that a window should be hidden in.\r\n#[derive(Debug, Clone, Copy, PartialEq)]\r\npub"
  },
  {
    "path": "packages/wm-common/src/ipc.rs",
    "chars": 2746,
    "preview": "use serde::{Deserialize, Serialize};\r\nuse uuid::Uuid;\r\n\r\nuse crate::{BindingModeConfig, ContainerDto, TilingDirection, W"
  },
  {
    "path": "packages/wm-common/src/lib.rs",
    "chars": 529,
    "preview": "#![warn(clippy::all, clippy::pedantic)]\r\n#![allow(clippy::missing_errors_doc)]\r\n\r\nmod active_drag;\r\nmod app_command;\r\nmo"
  },
  {
    "path": "packages/wm-common/src/parsed_config.rs",
    "chars": 13674,
    "preview": "use serde::{Deserialize, Serialize};\r\nuse wm_platform::{\r\n  Color, CornerStyle, Key, Keybinding, LengthValue, OpacityVal"
  },
  {
    "path": "packages/wm-common/src/tiling_direction.rs",
    "chars": 1998,
    "preview": "use std::str::FromStr;\r\n\r\nuse anyhow::bail;\r\nuse serde::{Deserialize, Serialize};\r\nuse wm_platform::Direction;\r\n\r\n#[deri"
  },
  {
    "path": "packages/wm-common/src/utils/iterator_ext.rs",
    "chars": 1290,
    "preview": "use std::{collections::HashSet, hash::Hash};\r\n\r\n/// Extension trait for iterators.\r\npub trait UniqueExt: Iterator {\r\n  /"
  },
  {
    "path": "packages/wm-common/src/utils/mod.rs",
    "chars": 109,
    "preview": "mod iterator_ext;\r\nmod try_warn;\r\nmod vec_deque_ext;\r\n\r\npub use iterator_ext::*;\r\npub use vec_deque_ext::*;\r\n"
  },
  {
    "path": "packages/wm-common/src/utils/try_warn.rs",
    "chars": 330,
    "preview": "/// Utility macro that logs a warning and returns early if the given\r\n/// expression is an error.\r\n#[macro_export]\r\nmacr"
  },
  {
    "path": "packages/wm-common/src/utils/vec_deque_ext.rs",
    "chars": 706,
    "preview": "use std::collections::VecDeque;\r\n\r\npub trait VecDequeExt<T>\r\nwhere\r\n  T: PartialEq,\r\n{\r\n  /// Shifts a value to a specif"
  },
  {
    "path": "packages/wm-common/src/window_state.rs",
    "chars": 952,
    "preview": "use serde::{Deserialize, Serialize};\r\n\r\nuse crate::{\r\n  parsed_config::{\r\n    FloatingStateConfig, FullscreenStateConfig"
  },
  {
    "path": "packages/wm-common/src/wm_event.rs",
    "chars": 1433,
    "preview": "use serde::{Deserialize, Serialize};\r\nuse uuid::Uuid;\r\n\r\nuse crate::{\r\n  dtos::ContainerDto,\r\n  parsed_config::{BindingM"
  },
  {
    "path": "packages/wm-ipc-client/Cargo.toml",
    "chars": 363,
    "preview": "[package]\r\nname = \"wm-ipc-client\"\r\nversion = \"0.0.0\"\r\nedition = \"2021\"\r\n\r\n[lib]\r\npath = \"src/lib.rs\"\r\n\r\n[dependencies]\r\n"
  },
  {
    "path": "packages/wm-ipc-client/src/lib.rs",
    "chars": 2223,
    "preview": "#![allow(clippy::missing_errors_doc)]\r\n\r\nuse anyhow::Context;\r\nuse futures_util::{SinkExt, StreamExt};\r\nuse tokio::net::"
  },
  {
    "path": "packages/wm-macros/Cargo.toml",
    "chars": 167,
    "preview": "[package]\r\nname = \"wm-macros\"\r\nversion = \"0.1.0\"\r\nedition = \"2024\"\r\n\r\n[lib]\r\nproc-macro = true\r\n\r\n[dependencies]\r\nsyn = "
  },
  {
    "path": "packages/wm-macros/src/common/attributes.rs",
    "chars": 1175,
    "preview": "//! Utilities for working with [syn::Attribute]\r\n\r\npub mod prelude {\r\n  pub use super::FindAttributes;\r\n}\r\n\r\n/// Trait f"
  },
  {
    "path": "packages/wm-macros/src/common/branch.rs",
    "chars": 14658,
    "preview": "//! Types and traits for branching and combining parsing operations.\r\n//! Implements functionality similar to `nom`s alt"
  },
  {
    "path": "packages/wm-macros/src/common/error_handling.rs",
    "chars": 3434,
    "preview": "//! Utilities for simplifying error handling and diagnostics.\r\n\r\npub mod prelude {\r\n  // ToSpanError is not used yet, bu"
  },
  {
    "path": "packages/wm-macros/src/common/mod.rs",
    "chars": 580,
    "preview": "/// Utilities for parsing attributes\r\npub mod attributes;\r\n/// Utilities for parsing alternatives and combinators\r\npub m"
  },
  {
    "path": "packages/wm-macros/src/common/named_parameter.rs",
    "chars": 1630,
    "preview": "//! Types for parsing `name = value` patterns.\r\n\r\n/// Type to represent a `name = value` pair, where `name` can be peeke"
  },
  {
    "path": "packages/wm-macros/src/common/parenthesized.rs",
    "chars": 1328,
    "preview": "//! Type wrappers for parsing content that is within delimiters, such as\r\n//! parenthesis or brackets.\r\n\r\n/// Type wrapp"
  },
  {
    "path": "packages/wm-macros/src/common/peekable.rs",
    "chars": 8391,
    "preview": "//! Custom peek implementation to support generics and custom peek\r\n//! functions.\r\n\r\n// Syn has a `Peek` trait, but it "
  },
  {
    "path": "packages/wm-macros/src/common/spanned_string.rs",
    "chars": 1493,
    "preview": "//! Type for a String with an associated source code span.\r\n\r\n/// A String with an associated source code span.\r\n/// An "
  },
  {
    "path": "packages/wm-macros/src/enum_from_inner/mod.rs",
    "chars": 2419,
    "preview": "//! Macro to derive `From` and `TryFrom` implementations for enum variants\r\n\r\nuse quote::ToTokens as _;\r\n\r\nuse crate::pr"
  },
  {
    "path": "packages/wm-macros/src/lib.rs",
    "chars": 3804,
    "preview": "// Enable proc macro diagnostics to allow emitting warnings and errors in\r\n// line\r\n#![feature(proc_macro_diagnostic)]\r\n"
  },
  {
    "path": "packages/wm-macros/src/subenum/enum_attrs.rs",
    "chars": 2134,
    "preview": "use crate::{common::branch::Ordered, prelude::*};\r\n\r\nmod kw {\r\n  crate::common::custom_keyword!(defaults);\r\n}\r\n\r\n/// Col"
  },
  {
    "path": "packages/wm-macros/src/subenum/mod.rs",
    "chars": 7841,
    "preview": "use enum_attrs::{Subenum, SubenumDeclaration};\r\n\r\nuse crate::prelude::*;\r\n\r\nconst SUBENUM_ATTR_NAME: &str = \"subenum\";\r\n"
  },
  {
    "path": "packages/wm-macros/src/subenum/variant_attr.rs",
    "chars": 1358,
    "preview": "use syn::punctuated::Punctuated;\r\n\r\nuse crate::prelude::*;\r\n\r\n/// Holds the parsed data for a single subenum variant.\r\np"
  },
  {
    "path": "packages/wm-platform/Cargo.toml",
    "chars": 1865,
    "preview": "[package]\r\nname = \"wm-platform\"\r\nversion = \"0.0.0\"\r\nedition = \"2021\"\r\n\r\n[lib]\r\npath = \"src/lib.rs\"\r\ntest = false\r\n\r\n[[te"
  },
  {
    "path": "packages/wm-platform/build.rs",
    "chars": 141,
    "preview": "fn main() {\r\n  #[cfg(target_os = \"macos\")]\r\n  println!(\r\n    \"cargo:rustc-link-search=framework=/System/Library/PrivateF"
  },
  {
    "path": "packages/wm-platform/src/dispatcher.rs",
    "chars": 24584,
    "preview": "use std::{\r\n  path::Path,\r\n  sync::{\r\n    atomic::{AtomicBool, Ordering},\r\n    Arc,\r\n  },\r\n  thread::ThreadId,\r\n};\r\n\r\n#["
  },
  {
    "path": "packages/wm-platform/src/display.rs",
    "chars": 8838,
    "preview": "#[cfg(target_os = \"macos\")]\r\nuse objc2::rc::Retained;\r\n#[cfg(target_os = \"macos\")]\r\nuse objc2_app_kit::NSScreen;\r\n#[cfg("
  },
  {
    "path": "packages/wm-platform/src/display_listener.rs",
    "chars": 1101,
    "preview": "use tokio::sync::mpsc;\r\n\r\nuse crate::{platform_impl, Dispatcher};\r\n\r\n/// A listener for system-wide display setting chan"
  },
  {
    "path": "packages/wm-platform/src/error.rs",
    "chars": 2482,
    "preview": "#[derive(Debug, thiserror::Error)]\r\npub enum Error {\r\n  #[error(transparent)]\r\n  Io(#[from] std::io::Error),\r\n\r\n  #[erro"
  },
  {
    "path": "packages/wm-platform/src/event_loop.rs",
    "chars": 1966,
    "preview": "use crate::{platform_impl, Dispatcher};\r\n\r\n/// A cross-platform event loop that allows for remote dispatching via\r\n/// ["
  },
  {
    "path": "packages/wm-platform/src/keybinding_listener.rs",
    "chars": 6872,
    "preview": "use std::{\r\n  collections::HashMap,\r\n  sync::{\r\n    atomic::{AtomicBool, Ordering},\r\n    Arc, Mutex,\r\n  },\r\n};\r\n\r\nuse to"
  },
  {
    "path": "packages/wm-platform/src/lib.rs",
    "chars": 1106,
    "preview": "#![warn(clippy::all, clippy::pedantic)]\r\n#![allow(clippy::missing_errors_doc)]\r\n#![feature(iterator_try_collect)]\r\n\r\nmod"
  },
  {
    "path": "packages/wm-platform/src/models/color.rs",
    "chars": 1884,
    "preview": "use std::str::FromStr;\r\n\r\nuse serde::{Deserialize, Deserializer, Serialize};\r\n\r\n#[derive(Debug, Clone, Serialize)]\r\npub "
  },
  {
    "path": "packages/wm-platform/src/models/corner_style.rs",
    "chars": 356,
    "preview": "use serde::{Deserialize, Serialize};\r\n\r\n/// Corner style of a window's frame.\r\n///\r\n/// # Platform-specific\r\n///\r\n/// On"
  },
  {
    "path": "packages/wm-platform/src/models/delta.rs",
    "chars": 900,
    "preview": "use std::str::FromStr;\r\n\r\nuse serde::Serialize;\r\n\r\n/// A wrapper that indicates a value should be interpreted as a delta"
  },
  {
    "path": "packages/wm-platform/src/models/direction.rs",
    "chars": 1329,
    "preview": "use std::str::FromStr;\r\n\r\nuse serde::Serialize;\r\n\r\n#[derive(Clone, Debug, PartialEq, Serialize)]\r\n#[serde(rename_all = \""
  },
  {
    "path": "packages/wm-platform/src/models/key.rs",
    "chars": 10140,
    "preview": "use std::{fmt, str::FromStr};\r\n\r\nuse serde::{Deserialize, Serialize};\r\n\r\n/// Platform-specific keyboard key code.\r\n///\r\n"
  },
  {
    "path": "packages/wm-platform/src/models/key_code.rs",
    "chars": 11298,
    "preview": "#[cfg(target_os = \"windows\")]\r\nuse windows::Win32::UI::Input::KeyboardAndMouse::{\r\n  VIRTUAL_KEY, VK_0, VK_1, VK_2, VK_3"
  },
  {
    "path": "packages/wm-platform/src/models/length_value.rs",
    "chars": 3294,
    "preview": "use std::str::FromStr;\r\n\r\nuse regex::Regex;\r\nuse serde::{Deserialize, Deserializer, Serialize};\r\n\r\n#[derive(Debug, Clone"
  },
  {
    "path": "packages/wm-platform/src/models/mod.rs",
    "chars": 405,
    "preview": "mod color;\r\nmod corner_style;\r\nmod delta;\r\nmod direction;\r\nmod key;\r\nmod key_code;\r\nmod length_value;\r\nmod opacity_value"
  },
  {
    "path": "packages/wm-platform/src/models/opacity_value.rs",
    "chars": 2107,
    "preview": "use std::str::FromStr;\r\n\r\nuse serde::{Deserialize, Deserializer, Serialize};\r\n\r\n#[derive(Debug, Clone, PartialEq, Serial"
  },
  {
    "path": "packages/wm-platform/src/models/point.rs",
    "chars": 446,
    "preview": "/// Represents an x-y coordinate.\r\n#[derive(Debug, Clone)]\r\npub struct Point {\r\n  pub x: i32,\r\n  pub y: i32,\r\n}\r\n\r\nimpl "
  },
  {
    "path": "packages/wm-platform/src/models/rect.rs",
    "chars": 7840,
    "preview": "use serde::{Deserialize, Serialize};\r\n\r\nuse crate::{Direction, LengthValue, Point, RectDelta};\r\n\r\n#[derive(Debug, Deseri"
  },
  {
    "path": "packages/wm-platform/src/models/rect_delta.rs",
    "chars": 1936,
    "preview": "use serde::{Deserialize, Serialize};\r\n\r\nuse super::LengthValue;\r\n\r\n#[derive(Debug, Deserialize, Clone, Serialize)]\r\npub "
  },
  {
    "path": "packages/wm-platform/src/mouse_listener.rs",
    "chars": 1770,
    "preview": "use tokio::sync::mpsc;\r\n\r\nuse crate::{platform_event::MouseEvent, platform_impl, Dispatcher};\r\n\r\n/// Available mouse eve"
  },
  {
    "path": "packages/wm-platform/src/native_window.rs",
    "chars": 15759,
    "preview": "#[cfg(target_os = \"macos\")]\r\nuse objc2_application_services::AXUIElement;\r\n#[cfg(target_os = \"macos\")]\r\nuse objc2_core_f"
  },
  {
    "path": "packages/wm-platform/src/platform_event.rs",
    "chars": 6038,
    "preview": "use super::NativeWindow;\r\nuse crate::{\r\n  platform_impl::WindowEventNotificationInner, Keybinding, MouseEventKind,\r\n  Po"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/macos/application.rs",
    "chars": 5268,
    "preview": "use std::sync::Arc;\r\n\r\nuse objc2::rc::Retained;\r\nuse objc2_app_kit::{\r\n  NSApplicationActivationPolicy, NSRunningApplica"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/macos/application_observer.rs",
    "chars": 11598,
    "preview": "use std::{\r\n  ptr::NonNull,\r\n  sync::{Arc, Mutex},\r\n};\r\n\r\nuse objc2_application_services::{AXError, AXObserver, AXUIElem"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/macos/ax_ui_element.rs",
    "chars": 3031,
    "preview": "use std::ptr::{self, NonNull};\r\n\r\npub use objc2_application_services::{AXError, AXUIElement};\r\nuse objc2_core_foundation"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/macos/ax_value.rs",
    "chars": 3555,
    "preview": "use std::{ffi::c_void, mem::MaybeUninit, ptr::NonNull};\r\n\r\nuse objc2_application_services::{AXValue, AXValueType};\r\nuse "
  },
  {
    "path": "packages/wm-platform/src/platform_impl/macos/display.rs",
    "chars": 14691,
    "preview": "use std::sync::Arc;\r\n\r\nuse objc2::{rc::Retained, MainThreadMarker};\r\nuse objc2_app_kit::NSScreen;\r\nuse objc2_core_founda"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/macos/display_listener.rs",
    "chars": 4845,
    "preview": "use std::time::{Duration, Instant};\r\n\r\nuse objc2::rc::Retained;\r\nuse tokio::sync::mpsc;\r\n\r\nuse crate::{\r\n  platform_impl"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/macos/event_loop.rs",
    "chars": 7124,
    "preview": "use std::sync::{\r\n  atomic::{AtomicBool, Ordering},\r\n  mpsc, Arc,\r\n};\r\n\r\nuse objc2::MainThreadMarker;\r\nuse objc2_app_kit"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/macos/ffi.rs",
    "chars": 2116,
    "preview": "use std::{ffi::c_void, ptr::NonNull};\r\n\r\nuse objc2_application_services::{AXError, AXUIElement};\r\nuse objc2_core_foundat"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/macos/keyboard_hook.rs",
    "chars": 6575,
    "preview": "use std::{os::raw::c_void, ptr::NonNull};\r\n\r\nuse objc2_core_foundation::{\r\n  kCFRunLoopCommonModes, CFMachPort, CFRetain"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/macos/mod.rs",
    "chars": 735,
    "preview": "mod application;\r\nmod application_observer;\r\nmod ax_ui_element;\r\nmod ax_value;\r\nmod display;\r\nmod display_listener;\r\nmod"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/macos/mouse_listener.rs",
    "chars": 10666,
    "preview": "use std::{\r\n  os::raw::c_void,\r\n  ptr::NonNull,\r\n  time::{Duration, Instant},\r\n};\r\n\r\nuse objc2_core_foundation::{\r\n  kCF"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/macos/native_window.rs",
    "chars": 15633,
    "preview": "use std::sync::Arc;\r\n\r\nuse objc2::MainThreadMarker;\r\nuse objc2_app_kit::{\r\n  NSApplicationActivationOptions, NSWindow, N"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/macos/notification_center.rs",
    "chars": 9243,
    "preview": "use objc2::{\r\n  define_class, msg_send, rc::Retained, runtime::AnyObject, sel,\r\n  AnyThread, DefinedClass,\r\n};\r\nuse objc"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/macos/single_instance.rs",
    "chars": 1830,
    "preview": "use std::{\r\n  fs::{self, File, TryLockError},\r\n  path::PathBuf,\r\n};\r\n\r\n/// Platform-specific implementation of [`SingleI"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/macos/window_listener.rs",
    "chars": 7427,
    "preview": "use std::collections::HashMap;\r\n\r\nuse objc2::rc::Retained;\r\nuse objc2_app_kit::NSWorkspace;\r\nuse tokio::sync::mpsc;\r\n\r\nu"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/mod.rs",
    "chars": 317,
    "preview": "#[cfg(target_os = \"windows\")]\r\n#[path = \"windows/mod.rs\"]\r\nmod platform;\r\n#[cfg(target_os = \"macos\")]\r\n#[path = \"macos/m"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/windows/com.rs",
    "chars": 5532,
    "preview": "use std::cell::RefCell;\r\n\r\nuse windows::{\r\n  core::{ComInterface, IUnknown, IUnknown_Vtbl, GUID, HRESULT},\r\n  Win32::{\r\n"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/windows/display.rs",
    "chars": 12108,
    "preview": "use windows::{\r\n  core::PCWSTR,\r\n  Win32::{\r\n    Foundation::{BOOL, LPARAM, POINT, RECT},\r\n    Graphics::Gdi::{\r\n      E"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/windows/display_listener.rs",
    "chars": 3729,
    "preview": "use std::sync::{\r\n  atomic::{AtomicBool, Ordering},\r\n  Arc,\r\n};\r\n\r\nuse tokio::sync::mpsc;\r\nuse tracing::warn;\r\nuse windo"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/windows/event_loop.rs",
    "chars": 8345,
    "preview": "use std::{\r\n  cell::RefCell,\r\n  collections::HashMap,\r\n  sync::{\r\n    atomic::{AtomicBool, AtomicUsize, Ordering},\r\n    "
  },
  {
    "path": "packages/wm-platform/src/platform_impl/windows/keyboard_hook.rs",
    "chars": 5354,
    "preview": "use std::cell::Cell;\r\n\r\nuse windows::Win32::{\r\n  Foundation::{HINSTANCE, LPARAM, LRESULT, WPARAM},\r\n  UI::{\r\n    Input::"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/windows/mod.rs",
    "chars": 453,
    "preview": "pub(crate) mod com;\r\nmod display;\r\nmod display_listener;\r\nmod event_loop;\r\nmod keyboard_hook;\r\nmod mouse_listener;\r\nmod "
  },
  {
    "path": "packages/wm-platform/src/platform_impl/windows/mouse_listener.rs",
    "chars": 9534,
    "preview": "use std::{\r\n  sync::{Arc, Mutex},\r\n  time::{Duration, Instant},\r\n};\r\n\r\nuse tokio::sync::mpsc;\r\nuse windows::Win32::{\r\n  "
  },
  {
    "path": "packages/wm-platform/src/platform_impl/windows/native_window.rs",
    "chars": 23753,
    "preview": "use std::time::Duration;\r\n\r\nuse tokio::task;\r\nuse tracing::warn;\r\nuse windows::{\r\n  core::PWSTR,\r\n  Win32::{\r\n    Founda"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/windows/single_instance.rs",
    "chars": 1640,
    "preview": "use windows::{\r\n  core::{w, PCWSTR},\r\n  Win32::{\r\n    Foundation::{\r\n      CloseHandle, GetLastError, ERROR_ALREADY_EXIS"
  },
  {
    "path": "packages/wm-platform/src/platform_impl/windows/window_listener.rs",
    "chars": 5996,
    "preview": "use std::sync::OnceLock;\r\n\r\nuse tokio::sync::mpsc;\r\nuse windows::Win32::{\r\n  Foundation::HWND,\r\n  UI::{\r\n    Accessibili"
  },
  {
    "path": "packages/wm-platform/src/single_instance.rs",
    "chars": 926,
    "preview": "use crate::platform_impl;\r\n\r\n/// Ensures only one instance of the application is running at a time.\r\n///\r\n/// # Platform"
  },
  {
    "path": "packages/wm-platform/src/test.rs",
    "chars": 1020,
    "preview": "#![feature(iterator_try_collect)]\r\n\r\n#[macro_use]\r\nextern crate libtest_mimic_collect;\r\n\r\nmod dispatcher;\r\nmod display;\r"
  },
  {
    "path": "packages/wm-platform/src/thread_bound.rs",
    "chars": 6127,
    "preview": "use core::{\r\n  fmt,\r\n  mem::{self, ManuallyDrop},\r\n};\r\nuse std::thread::ThreadId;\r\n\r\nuse crate::Dispatcher;\r\n\r\n/// Binds"
  }
]

// ... and 14 more files (download for full content)

About this extraction

This page contains the full source code of the glzr-io/glazewm GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 214 files (873.3 KB), approximately 224.1k tokens, and a symbol index with 1202 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!