Skip to content

Repository files navigation

GridMoveMac

GridMoveMac is a native macOS menu-bar window manager centered on GridMove's middle-mouse workflow.

The default layout is XiperGrid 1. The supplied Windows grid contains 132 groups: 66 unique positions for monitor 1 and the same positions repeated for monitor 2. GridMoveMac stores those 66 unique zones once and applies them independently to every connected Mac display. XiperGrid 2 remains bundled as an alternative with 148 unique positions.

Core interaction

  1. Press and hold the middle mouse button anywhere over a movable window.
  2. Drag the window. GridMoveMac displays XiperGrid's trigger map on the display under the pointer.
  3. Hover a trigger to preview its target rectangle.
  4. Release the middle button to snap and focus the dragged window.
  5. Press Escape during the drag to restore the original frame.

An ordinary middle click is forwarded to the application under the pointer. GridMoveMac activates only after the pointer crosses a four-point drag threshold over a movable window.

Build

Requirements: macOS 14 or newer and Xcode with the Swift toolchain.

For normal development, open Package.swift in Xcode. Xcode understands the Swift package directly, so a generated .xcodeproj file is unnecessary. Select the GridMoveMac executable scheme to build or debug.

From Terminal:

swift test
./scripts/build-app.sh
open GridMoveMac.app

The build script creates and signs GridMoveMac.app. When no signing certificate is configured, it uses an explicit stable designated requirement instead of the changing code hash produced by ordinary ad-hoc signing. After granting Accessibility and Input Monitoring to this stable build once, subsequent rebuilds at the same path retain the same macOS privacy identity.

If you have an Apple Development or other code-signing identity, provide its name when building:

GRIDMOVEMAC_SIGNING_IDENTITY="Apple Development: Your Name (TEAMID)" ./scripts/build-app.sh

Copy the resulting app to /Applications if desired. Keep using one app location and one signing method; changing either may require granting permissions again.

Generated .app bundles, ZIP archives, Swift build caches, and personal Xcode settings are intentionally excluded from Git. Releases should attach a freshly built application archive rather than commit binaries to the source tree.

Permissions

On first launch, grant GridMoveMac these permissions in System Settings → Privacy & Security:

  • Accessibility, so it can move and resize other applications' windows.
  • Input Monitoring, so it can observe the middle mouse button globally.

After changing Input Monitoring permission, quit and reopen the app. GridMoveMac runs as a menu-bar app and does not show a Dock icon.

On first launch, the Settings window opens automatically. On later launches, use the GM item in the menu bar. If GridMoveMac is already running, double-clicking the app again will not create a Dock icon or a second process.

Custom layouts

Open GridMoveMac Settings, then choose Open Custom Layouts Folder. Put layout JSON files in:

~/Library/Application Support/GridMoveMac/Layouts/

Choose Reload after editing. Examples/ThreeColumn.json is a starting point.

Every zone has a trigger and a target. Coordinates are fractions of the current display's usable frame, with (0, 0) at the top-left. A trigger and target may differ, which is how XiperGrid presents a compact trigger map for many overlapping target rectangles.

{
  "id": "my-layout",
  "name": "My Layout",
  "zones": [
    {
      "id": "left",
      "name": "Left half",
      "trigger": { "x": 0, "y": 0, "width": 0.5, "height": 1 },
      "target": { "x": 0, "y": 0, "width": 0.5, "height": 1 }
    }
  ]
}

Rectangles may also contain optional xOffset, yOffset, widthOffset, and heightOffset pixel values. The XiperGrid converter uses these fields to preserve its fixed 50-pixel center trigger strips.

Legacy GridMove conversion

Tools/convert_grid.py converts one monitor's ordinary positional groups from a legacy .grid file:

python3 Tools/convert_grid.py input.grid output.json --monitor 1 --id my-grid --name "My Grid"

The converter accepts arithmetic based on MonitorNTop, Left, Bottom, Right, Width, and Height. Command/plugin groups such as Restore or AlwaysOnTop are intentionally outside the macOS positional layout format.

Secondary controls

  • Control-Option-1 through Control-Option-9 snap the focused window to the first nine zones.

Left-button dragging is never intercepted and never opens the grid overlay. Middle-mouse dragging is the only pointer gesture handled by GridMoveMac.

Repository structure

AppBundle/                 Application Info.plist
Examples/                  Example custom layouts
Sources/GridMoveMac/       AppKit and SwiftUI application source
Tests/GridMoveMacTests/    Layout and conversion tests
Tools/                     Legacy GridMove conversion utility
scripts/                   Reproducible app-bundle build script

GitHub Actions runs swift test on macOS for every push and pull request.

Credits and lineage

GridMoveMac is an independent native macOS implementation of the GridMove interaction model. Its Swift source was written for this project, while its behavior and bundled layouts build on work from the GridMove community:

The XiperGrid definitions were mechanically converted from legacy .grid files into display-independent JSON. GridMoveMac is not affiliated with or endorsed by the original authors.

See NOTICE.md for the full attribution and LICENSE for licensing terms.

About

Native macOS GridMove-style window snapping with middle-mouse dragging

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages