Skip to content

Commit 5370c66

Browse files
committed
Initial release: MaxPane v1.3.0 — Nested docker layouts for REAPER
0 parents  commit 5370c66

48 files changed

Lines changed: 7030 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/FUNDING.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
ko_fi: quickmd
2+
buy_me_a_coffee: bsroczynskh
3+
custom: ["https://paypal.me/b451c"]
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
name: Bug Report
3+
about: Report a bug or unexpected behavior
4+
title: ''
5+
labels: bug
6+
assignees: ''
7+
---
8+
9+
## Description
10+
11+
A clear description of the bug.
12+
13+
## Steps to reproduce
14+
15+
1. Open MaxPane
16+
2. ...
17+
3. ...
18+
19+
## Expected behavior
20+
21+
What you expected to happen.
22+
23+
## Actual behavior
24+
25+
What actually happened.
26+
27+
## Environment
28+
29+
- **REAPER version**:
30+
- **MaxPane version**:
31+
- **OS**: (e.g., macOS 15.3, arm64)
32+
- **Build type**: Release / Debug
33+
34+
## Debug log (if applicable)
35+
36+
If using a Debug build, attach the relevant section from `/tmp/maxpane_debug.log`.
37+
38+
## Screenshots
39+
40+
If applicable, add screenshots to help explain the issue.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
name: Feature Request
3+
about: Suggest a new feature or improvement
4+
title: ''
5+
labels: enhancement
6+
assignees: ''
7+
---
8+
9+
## Description
10+
11+
A clear description of the feature you'd like.
12+
13+
## Use case
14+
15+
Why is this feature important? What workflow does it improve?
16+
17+
## Proposed solution
18+
19+
How you envision this working (if you have ideas).
20+
21+
## Alternatives considered
22+
23+
Any alternative approaches you've thought about.

.github/workflows/build.yml

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
name: Build & Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
jobs:
9+
build:
10+
strategy:
11+
matrix:
12+
include:
13+
- os: macos-14
14+
platform: darwin-arm64
15+
artifact: reaper_maxpane-arm64.dylib
16+
build_file: reaper_maxpane.dylib
17+
- os: macos-13
18+
platform: darwin-x86_64
19+
artifact: reaper_maxpane-x86_64.dylib
20+
build_file: reaper_maxpane.dylib
21+
- os: windows-latest
22+
platform: win-x64
23+
artifact: reaper_maxpane-x64.dll
24+
build_file: Release/reaper_maxpane.dll
25+
- os: ubuntu-latest
26+
platform: linux-x86_64
27+
artifact: reaper_maxpane-x86_64.so
28+
build_file: reaper_maxpane.so
29+
30+
runs-on: ${{ matrix.os }}
31+
name: Build (${{ matrix.platform }})
32+
33+
steps:
34+
- uses: actions/checkout@v4
35+
36+
- name: Clone REAPER SDK
37+
run: git clone --depth 1 https://github.com/justinfrankel/reaper-sdk.git cpp/sdk
38+
39+
- name: Clone WDL
40+
run: git clone --depth 1 https://github.com/cockos/WDL.git cpp/WDL
41+
42+
- name: Create build directory
43+
run: mkdir -p cpp/build
44+
shell: bash
45+
46+
- name: Configure (macOS / Linux)
47+
if: runner.os != 'Windows'
48+
working-directory: cpp/build
49+
run: cmake .. -DCMAKE_BUILD_TYPE=Release
50+
51+
- name: Configure (Windows)
52+
if: runner.os == 'Windows'
53+
working-directory: cpp/build
54+
run: cmake .. -G "Visual Studio 17 2022" -A x64
55+
56+
- name: Build (macOS / Linux)
57+
if: runner.os != 'Windows'
58+
working-directory: cpp/build
59+
run: make -j$(nproc 2>/dev/null || sysctl -n hw.ncpu)
60+
61+
- name: Build (Windows)
62+
if: runner.os == 'Windows'
63+
working-directory: cpp/build
64+
run: cmake --build . --config Release
65+
66+
- name: Rename artifact
67+
working-directory: cpp/build
68+
shell: bash
69+
run: cp "${{ matrix.build_file }}" "${{ matrix.artifact }}"
70+
71+
- name: Upload artifact
72+
uses: actions/upload-artifact@v4
73+
with:
74+
name: ${{ matrix.artifact }}
75+
path: cpp/build/${{ matrix.artifact }}
76+
77+
release:
78+
needs: build
79+
runs-on: ubuntu-latest
80+
permissions:
81+
contents: write
82+
83+
steps:
84+
- name: Download all artifacts
85+
uses: actions/download-artifact@v4
86+
with:
87+
path: artifacts
88+
89+
- name: Create GitHub Release
90+
uses: softprops/action-gh-release@v2
91+
with:
92+
files: artifacts/**/*
93+
generate_release_notes: false
94+
body: |
95+
## MaxPane ${{ github.ref_name }}
96+
97+
Native C++ extension for REAPER — tiling window manager with tabs, workspaces, and drag-and-drop.
98+
99+
### Downloads
100+
101+
| Platform | File |
102+
|----------|------|
103+
| macOS arm64 (Apple Silicon) | `reaper_maxpane-arm64.dylib` |
104+
| macOS x86_64 (Intel) | `reaper_maxpane-x86_64.dylib` |
105+
| Windows x64 | `reaper_maxpane-x64.dll` |
106+
| Linux x86_64 | `reaper_maxpane-x86_64.so` |
107+
108+
### Installation
109+
110+
Copy the binary for your platform to your REAPER UserPlugins folder and restart REAPER.
111+
112+
See the full [CHANGELOG](https://github.com/b451c/MaxPane/blob/main/CHANGELOG.md) for version history.
113+
114+
---
115+
*Support development: [Ko-fi](https://ko-fi.com/quickmd) · [Buy Me a Coffee](https://buymeacoffee.com/bsroczynskh) · [PayPal](https://paypal.me/b451c)*

.gitignore

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Build artifacts
2+
cpp/build/
3+
4+
# External dependencies (cloned separately)
5+
cpp/sdk/
6+
cpp/WDL/
7+
8+
# Compiled binaries
9+
*.dylib
10+
*.dll
11+
*.so
12+
*.o
13+
*.obj
14+
15+
# macOS
16+
.DS_Store
17+
18+
# IDE / Editor
19+
.vscode/
20+
.idea/
21+
*.xcodeproj/
22+
*.swp
23+
*~
24+
25+
# Debug logs
26+
maxpane_debug.log
27+
28+
# Claude Code project files
29+
.claude/

CHANGELOG.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Changelog
2+
3+
All notable changes to MaxPane will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/).
6+
7+
## [1.3.0] - 2026-03-03
8+
9+
### Changed
10+
- **Renamed project**: ReDockIt → **MaxPane** — all source, docs, CMake, actions, ExtState keys, RPP chunk tags updated.
11+
12+
### Added
13+
- **Diagonal grid lines** in empty panes — subtle 45° lines on the pane background, disappear when a window is captured.
14+
15+
### Fixed
16+
- **Pane background color** — captured windows (WS_CHILD) have no own background and inherited the parent's dark color. Fixed by setting `COLOR_PANE_BG = RGB(172,172,172)` as a neutral light gray.
17+
- **DoRelease toggle for Actions window** — closing the Actions tab via [x] left REAPER's toggle state on (checkmark stayed). Root cause: SWELL destroys the NSWindow when a window becomes WS_CHILD, so `g_Main_OnCommand` couldn't find the window and opened a new one. Fix: `SetParent(nullptr)` to restore the NSWindow before toggling.
18+
- **Hint text color** — "Click header to assign a window" was white on light gray after the background color fix. Changed to `RGB(80,80,80)`.
19+
20+
---
21+
22+
## [1.2.0] - 2026-03-02
23+
24+
### Added
25+
- **Pane menu button (▼)** — 16 px button at the right edge of every tab bar. Left-click opens the pane context menu (same as right-click). Hit-test returns `-2`; hover highlights the button.
26+
- `CalcTabBarLayout` shared helper — single source of truth for tab geometry used by `DrawTabBar`, `TabHitTest`, and `IsOnTabCloseButton`.
27+
- `GetTabRect` helper — returns the screen rect for a given tab index; used for targeted invalidation on color change.
28+
- `ExpandRect` static helper (both `container.cpp` and `container_input.cpp`) — in-place RECT union, skips empty src/dst to prevent dirty-rect corruption.
29+
30+
### Changed
31+
- **Targeted `InvalidateRect`** — hover/drag operations now invalidate only the affected rect instead of the full window:
32+
- Splitter hover: union of old + new splitter rect
33+
- Tab/menu-button hover: union of old + new item rect via `GetTabRect` / inline button rect
34+
- Drag highlight change: union of old + new highlight pane rect
35+
- Drag cancel/end: source tab bar + old highlight pane rect
36+
- Tab color change: only that tab's rect via `GetTabRect`
37+
- Timer hover timeout: cached old hover rects only
38+
- Tab area now reserves `PANE_MENU_BTN_WIDTH` (16 px) on the right for the menu button; tabs shrink accordingly.
39+
40+
### Fixed
41+
- **`TabHitTest` x-bounds regression** — the menu-button check (`x >= paneRect.right - 16`) was firing for clicks *outside* the pane's x range (e.g. in the adjacent right-side pane), causing the pane context menu to appear instead of tab interactions. Fix: check `x < paneRect.left || x >= paneRect.right` before the menu-button test.
42+
- `ExpandRect` now guards against empty `src` rect (`{0,0,0,0}`) in both call-sites, preventing the dirty rect from expanding into origin unnecessarily.
43+
44+
### Removed
45+
- Scroll arrows (`<` / `>`) for tab overflow — tabs shrink when a pane is narrow (original behaviour). `m_tabScrollOffset`, `TAB_SCROLL_ARROW_WIDTH`, `TAB_OVERFLOW_THRESHOLD` removed.
46+
47+
---
48+
49+
## [1.1.0] - 2026-03-02
50+
51+
### Added
52+
- Splitter hover highlights (white bar on mouseover)
53+
- Tab hover highlights (lighten effect on mouseover)
54+
- Per-project state persistence via RPP files (`project_config_extension_t`)
55+
- `StateAccessor` abstraction for polymorphic state I/O (global, project, RPP)
56+
57+
### Fixed
58+
- Workspace switch rendering: blank/artifact windows (e.g. Routing Matrix) after switching back
59+
- Frameless floating windows when closing tabs via [x]
60+
- Windows reappearing floating after REAPER restart despite being closed
61+
- Shutdown lifecycle: proper toggle state check, reparent-before-toggle sequence
62+
- Quit interception via hookcommand for reliable state save on macOS/Windows
63+
- RepositionAll repaint: `SWP_FRAMECHANGED` + `InvalidateRect` after pane resize
64+
65+
### Changed
66+
- Simplified to global docker model (removed per-project visibility switching)
67+
- RPP state I/O now uses synchronous `project_config_extension_t` (replaced deferred timer)
68+
- `LoadWorkspace` uses `ReleaseAll(false)` for smoother workspace transitions
69+
- `DoCapture` forces frame recalculation via `SWP_FRAMECHANGED`
70+
71+
## [1.0.1] - 2026-03-01
72+
73+
### Fixed
74+
- **Startup deadlock**: REAPER could hang when loading a project with MaxPane docked. The capture queue now defers `Main_OnCommand` calls during `LoadState()` to avoid calling REAPER APIs while the project is still loading.
75+
76+
### Changed
77+
- Replaced raw `new`/`delete` with `std::unique_ptr` for safer resource management
78+
- Replaced all `strncpy` calls with `safe_strncpy` helper for consistent null-termination
79+
- Extracted magic numbers (colors, geometry, timing) into named constants in `config.h`
80+
- Merged duplicate `FindWindowEnumProc`/`FindChildWindowEnumProc` into single function
81+
- Debug logging is now conditional on `CMAKE_BUILD_TYPE=Debug` (no longer always enabled)
82+
- Added `-Wshadow` and `-Wconversion` compiler warnings
83+
84+
### Removed
85+
- Dead code: unused `BuildLists()` and `IsAnyCaptured()` methods
86+
87+
## [1.0.0] - 2025-03-01
88+
89+
### Added
90+
- Native C++ REAPER extension (no script dependencies)
91+
- Binary split tree layout engine with up to 16 panes
92+
- Tabbed window management with drag-and-drop between panes
93+
- 14 known REAPER windows with one-click capture
94+
- Arbitrary window capture (including ReaImGui scripts)
95+
- Dock frame detection for ReaImGui windows
96+
- Async capture queue with retry logic
97+
- Named workspaces (save/restore complete layouts)
98+
- Favorites system with persistent action command strings
99+
- Tab color palette (8 colors)
100+
- 5 built-in layout presets
101+
- Auto-open on REAPER startup (configurable)
102+
- Full state persistence via REAPER ExtState
103+
- Dockable container (integrates with REAPER's docker system)
104+
- Context menus for panes and tabs
105+
- Capture-by-click mode
106+
- Conditional debug logging (Debug builds only)
107+
- Cross-platform architecture via WDL/SWELL

CODE_OF_CONDUCT.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Code of Conduct
2+
3+
## Our Pledge
4+
5+
We are committed to making participation in MaxPane a welcoming and respectful experience for everyone, regardless of background or experience level.
6+
7+
## Our Standards
8+
9+
**Positive behavior includes:**
10+
- Using welcoming and inclusive language
11+
- Being respectful of differing viewpoints
12+
- Accepting constructive criticism gracefully
13+
- Focusing on what is best for the community
14+
15+
**Unacceptable behavior includes:**
16+
- Personal attacks, insults, or trolling
17+
- Publishing others' private information without permission
18+
- Any conduct that would be considered inappropriate in a professional setting
19+
20+
## Scope
21+
22+
This Code of Conduct applies within all project spaces — issues, pull requests, discussions, and any other communication channels.
23+
24+
## Enforcement
25+
26+
Instances of unacceptable behavior may be reported by opening an issue or contacting the maintainer. All complaints will be reviewed and investigated promptly and fairly.
27+
28+
## Attribution
29+
30+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1.

0 commit comments

Comments
 (0)