-
Notifications
You must be signed in to change notification settings - Fork 0
既存のプロファイルを適用する機能を実装 #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,7 +9,7 @@ | |
| 2. 任意のフォルダに展開 | ||
| 3. `WindowController.exe` を実行 | ||
|
|
||
| > .NET ランタイムは同梱済み(自己完結型)のため、別途インストール不要です。 | ||
| > .NET ランタイムは同梱済み(自己完結型)のため、別途インストール不要です。 | ||
| > 二重起動は自動でブロックされます。 | ||
|
|
||
| ## 動作環境 | ||
|
|
@@ -22,24 +22,24 @@ | |
|
|
||
| GUI で起動中のウィンドウを一覧表示し、チェックしたウィンドウの配置を「プロファイル」として保存します。 | ||
|
|
||
| - 各ウィンドウの位置・サイズ・状態(最小化/最大化/通常)を記録 | ||
| - スナップ位置(左半分、右半分など)を自動検出 → モニタ構成が変わっても再計算 | ||
| - ブラウザの URL を UI Automation で取得(クリップボードやフォーカスに一切触れません) | ||
| - 各ウィンドウの位置・サイズ・状態(最小化/最大化/通常)を記録 | ||
| - スナップ位置(左半分、右半分など)を自動検出 → モニタ構成が変わっても再計算 | ||
| - ブラウザの URL を UI Automation で取得(クリップボードやフォーカスに一切触れません) | ||
|
|
||
| ### プロファイル適用(配置のみ) | ||
| ### プロファイル適用(配置のみ) | ||
|
|
||
| 保存済みプロファイルを選んで「適用」すると、対応ウィンドウを検索して配置を復元します。 | ||
|
|
||
| ### 一括起動 + 配置 | ||
|
|
||
| 見つからないウィンドウはアプリを起動した上で配置します(最大 12 秒待機)。 | ||
| 見つからないウィンドウはアプリを起動した上で配置します(最大 12 秒待機)。 | ||
|
|
||
| ### 最小化 / 最大化の連動 | ||
|
|
||
| プロファイル内のウィンドウを「グループ」として扱い、1 つを最小化・復元すると他も追従させます。 | ||
|
|
||
| - 全体 ON/OFF + プロファイル個別 ON/OFF | ||
| - 曖昧なマッチは連動対象から自動除外(誤爆防止) | ||
| - 曖昧なマッチは連動対象から自動除外(誤爆防止) | ||
|
|
||
| ## 使い方 | ||
|
|
||
|
|
@@ -49,45 +49,72 @@ GUI で起動中のウィンドウを一覧表示し、チェックしたウィ | |
|
|
||
| | メニュー | 動作 | | ||
| |---|---| | ||
| | **GUI を開く** | 設定画面を表示 | | ||
| | **プロファイルを適用 (配置のみ)** | GUI を表示 | | ||
| | **GUI を開く** | メイン画面を表示 | | ||
| | **設定…** | 設定画面を表示 | | ||
| | **既定のプロファイルを適用** | 既定のプロファイルを適用(設定で指定したプロファイルを順に適用) | | ||
| | **終了** | アプリを終了 | | ||
|
|
||
| ### ホットキー | ||
|
|
||
| | キー | 動作 | | ||
| |---|---| | ||
| | **Ctrl + Alt + W** | GUI を開く | | ||
| | **Ctrl + Alt + W** | メイン画面を表示(既定。設定で変更/無効化可) | | ||
| | (任意) | プロファイル適用ホットキー(プロファイルごとに設定。配置のみ適用) | | ||
|
|
||
| ### GUI | ||
|
|
||
| | 領域 | 説明 | | ||
| |---|---| | ||
| | 上段 | 起動中ウィンドウ一覧(チェックして保存対象を選択) | | ||
| | 中段 | プロファイル名入力 → 「チェックを保存」 | | ||
| | 下段 | 保存済みプロファイル一覧(チェック=連動 ON/OFF、名前ダブルクリックでリネーム) | | ||
| | ボタン | 適用(配置のみ)/ 一括起動+配置 / 削除 | | ||
| | 設定 | 連動機能全体 ON/OFF、起動時 GUI 表示、profiles.json 保存先変更 | | ||
| | 起動中ウィンドウ | チェックしたウィンドウをプロファイルに保存(Title/Exe/Class/URL/Browser Profile を表示) | | ||
| | プロファイル保存 | プロファイル名入力 → 「プロファイル保存」 | | ||
| | 保存済みプロファイル | チェック=最小化/最大化を常時連動、名前編集(競合時は自動で連番付与) | | ||
| | ボタン | 適用(配置のみ)/ 一括起動+配置 / 削除 | | ||
| | 右クリック | 「モニターを選択して配置」(配置前に警告が出ることがあります) | | ||
| | 設定画面 | 連動機能全体 ON/OFF、起動時 GUI 表示、profiles.json 保存先、ホットキー(GUI表示/プロファイル適用) | | ||
|
|
||
| ## データの保存場所 | ||
|
|
||
| | ファイル | パス | | ||
| |---|---| | ||
| | 設定 | `%LOCALAPPDATA%\WindowController\appsettings.json` | | ||
| | プロファイル | `%LOCALAPPDATA%\WindowController\profiles.json` (GUI で変更可能) | | ||
| | プロファイル | `%LOCALAPPDATA%\WindowController\profiles.json` (GUI で変更可能) | | ||
| | ログ | `%LOCALAPPDATA%\WindowController\window-controller.log` | | ||
|
|
||
| > `profiles.json` の保存先は GUI 下部の「変更…」ボタンで任意のフォルダに変更できます。 | ||
| > 「既定に戻す」で上記デフォルトに戻ります。 | ||
|
|
||
| ### appsettings.json について | ||
|
|
||
| `appsettings.json` はアプリ全体の設定(`profiles.json` の保存先・ホットキー設定など)を保持します。 | ||
|
|
||
| ```json | ||
| { | ||
| "profilesPath": "C:\\Path\\To\\profiles.json", | ||
| "defaultProfileIds": [ | ||
| "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", | ||
| "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy" | ||
| ], | ||
| "hotkeys": { | ||
| "showGui": { "key": "W", "ctrl": true, "alt": true, "shift": false, "win": false }, | ||
| "profiles": { | ||
| "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx": { "key": "1", "ctrl": true, "alt": false, "shift": false, "win": false } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
Comment on lines
+86
to
+104
|
||
|
|
||
| ### profiles.json スキーマ | ||
|
|
||
| ```json | ||
| { | ||
| "version": 1, | ||
| "settings": { | ||
| "syncMinMax": 0, | ||
| "showGuiOnStartup": 1 | ||
| "showGuiOnStartup": 1, | ||
| "aspectRatioWarnThreshold": 0.02, | ||
| "warnOnResolutionMismatch": true, | ||
| "warnOnMonitorMismatch": true, | ||
| "allowCrossDesktopApply": true | ||
| }, | ||
| "profiles": [ | ||
| { | ||
|
|
@@ -96,38 +123,55 @@ GUI で起動中のウィンドウを一覧表示し、チェックしたウィ | |
| "syncMinMax": 0, | ||
| "createdAt": "2026-01-01T20:20:20", | ||
| "updatedAt": "2026-01-01T20:20:20", | ||
| "targetDesktopId": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy", | ||
| "windows": [ | ||
| { | ||
| "match": { | ||
| "exe": "Code - Insiders.exe", | ||
| "class": "Chrome_WidgetWin_1", | ||
| "title": "Window Title", | ||
| "url": "", | ||
| "urlKey": "", | ||
| "browser": null | ||
| "url": "https://example.com/", | ||
| "urlKey": "https://example.com/", | ||
| "browser": { | ||
| "kind": "chromium", | ||
| "userDataDir": "C:\\Users\\you\\AppData\\Local\\Google\\Chrome\\User Data", | ||
| "profileDirectory": "Default" | ||
| } | ||
| }, | ||
| "path": "C:\\Users\\you\\AppData\\Local\\Programs\\...\\Code - Insiders.exe", | ||
| "rect": { "x": 0, "y": 0, "w": 960, "h": 1040 }, | ||
| "rectNormalized": { "xN": 0.0, "yN": 0.0, "wN": 0.5, "hN": 1.0 }, | ||
| "minMax": 0, | ||
| "snap": { "type": "left" }, | ||
| "monitor": { "index": 1, "name": "\\\\.\\DISPLAY1" } | ||
| "monitor": { | ||
| "index": 1, | ||
| "name": "\\\\.\\DISPLAY1", | ||
| "devicePath": "\\\\?\\DISPLAY#...", | ||
| "pixelWidth": 3840, | ||
| "pixelHeight": 2160 | ||
| }, | ||
| "desktopId": "zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ``` | ||
|
|
||
| > `id` はプロファイルの内部識別子(UUID)です。旧バージョンで作成された `profiles.json` に `id` がない場合、起動時に自動で付与されます。 | ||
| > `id` はプロファイルの内部識別子(UUID)です。旧バージョンで作成された `profiles.json` に `id` がない場合や、`id` が重複している場合は起動時に自動で再付与されます。 | ||
|
|
||
| > JSON は `null` の項目を出力しません(例: `browser` / `snap` / `monitor` / `rectNormalized` / `desktopId` / `targetDesktopId` は状況により省略されます)。また `monitor.pixelWidth` / `monitor.pixelHeight` は 0 の場合は省略されます。 | ||
|
|
||
| > `desktopId` / `targetDesktopId` / `allowCrossDesktopApply` など仮想デスクトップ関連は将来拡張向けのフィールドで、GUI 上に「※整備中」と表示される機能は現状動作しない場合があります。 | ||
|
|
||
| ## ブラウザ URL 取得 | ||
|
|
||
| | ブラウザ | 方式 | 備考 | | ||
| |---|---|---| | ||
| | Chrome / Edge / Brave / Vivaldi | UI Automation (ValuePattern) | 非侵襲 | | ||
| | Firefox / Floorp | UI Automation | 取得不可時は空(誤マッチ防止) | | ||
| | Firefox / Floorp | UI Automation | 取得不可時は空(誤マッチ防止) | | ||
|
|
||
| ## ビルド(開発者向け) | ||
| ## ビルド(開発者向け) | ||
|
|
||
| ```bash | ||
| # ビルド | ||
|
|
@@ -137,21 +181,21 @@ dotnet build | |
| # 実行 | ||
| dotnet run --project WindowController.App | ||
|
|
||
| # 公開用ビルド(単一ファイル・自己完結型) | ||
| # 公開用ビルド(単一ファイル・自己完結型) | ||
| dotnet publish WindowController.App -c Release | ||
| # 出力先: src/WindowController.App/bin/Release/net8.0-windows/win-x64/publish/ | ||
| ``` | ||
|
|
||
| ## 配布用ZIPの生成 | ||
|
|
||
| 配布用のZIP(中身は `WindowController.exe` のみ)をリポジトリ直下の `dist/` に出力します。 | ||
| 配布用のZIP(中身は `WindowController.exe` のみ)をリポジトリ直下の `dist/` に出力します。 | ||
|
|
||
| ```powershell | ||
| pwsh scripts/package.ps1 | ||
| ``` | ||
|
|
||
| - 出力: `dist/WindowController-v<version>-win-x64.zip` | ||
| - publish出力(確認用): `dist/publish/WindowController.exe` | ||
| - publish出力(確認用): `dist/publish/WindowController.exe` | ||
|
|
||
| ### 必要環境 | ||
|
|
||
|
|
@@ -166,7 +210,7 @@ src/ | |
| WindowController.Core/ モデル、URL正規化、マッチングロジック | ||
| WindowController.Win32/ P/Invoke、ウィンドウ列挙/配置、WinEventHook | ||
| WindowController.Browser/ FlaUI.UIA3 による URL 取得 | ||
| WindowController.App/ WPF アプリ(トレイ、GUI、ViewModel) | ||
| WindowController.App/ WPF アプリ(トレイ、GUI、ViewModel) | ||
| ``` | ||
|
|
||
| ### 技術スタック | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
src/WindowController.App/DefaultProfilesMissingDialog.xaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| <ui:FluentWindow x:Class="WindowController.App.DefaultProfilesMissingDialog" | ||
| xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
| xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
| xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml" | ||
| Title="既定のプロファイル" | ||
| Width="520" SizeToContent="Height" | ||
| MinHeight="0" | ||
| WindowStartupLocation="CenterOwner" | ||
| ResizeMode="NoResize" | ||
| Topmost="True" | ||
| ShowInTaskbar="False" | ||
| ExtendsContentIntoTitleBar="True" | ||
| WindowBackdropType="Mica"> | ||
| <Grid> | ||
| <Grid.RowDefinitions> | ||
| <RowDefinition Height="Auto"/> | ||
| <RowDefinition Height="Auto"/> | ||
| </Grid.RowDefinitions> | ||
|
|
||
| <ui:TitleBar Grid.Row="0" Title="既定のプロファイル" | ||
| ShowMaximize="False" ShowMinimize="False"/> | ||
|
|
||
| <StackPanel Grid.Row="1" Margin="24,0,24,24"> | ||
| <StackPanel Orientation="Horizontal" Margin="0,0,0,8"> | ||
| <ui:SymbolIcon Symbol="Info24" FontSize="22" Margin="0,0,8,0" | ||
| Foreground="{DynamicResource TextFillColorPrimaryBrush}"/> | ||
| <TextBlock Text="既定のプロファイルが設定されていません" | ||
| Style="{StaticResource SectionHeader}" Margin="0"/> | ||
| </StackPanel> | ||
|
|
||
| <TextBlock Text="設定画面の「既定のプロファイル」から適用するプロファイルを選択してください。" | ||
| Style="{StaticResource SectionDescription}" | ||
| TextWrapping="Wrap" | ||
| Margin="0,0,0,16"/> | ||
|
|
||
| <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,8,0,0"> | ||
| <ui:Button Click="OpenSettings_Click" Appearance="Info" | ||
| Margin="0,0,8,0" Padding="16,8"> | ||
| <ui:Button.Icon> | ||
| <ui:SymbolIcon Symbol="Settings24"/> | ||
| </ui:Button.Icon> | ||
| <ui:Button.Content> | ||
| <TextBlock Text="設定を開く"/> | ||
| </ui:Button.Content> | ||
| </ui:Button> | ||
|
|
||
| <ui:Button Click="Close_Click" Appearance="Secondary" | ||
| Padding="16,8"> | ||
| <ui:Button.Icon> | ||
| <ui:SymbolIcon Symbol="Dismiss24"/> | ||
| </ui:Button.Icon> | ||
| <ui:Button.Content> | ||
| <TextBlock Text="閉じる"/> | ||
| </ui:Button.Content> | ||
| </ui:Button> | ||
| </StackPanel> | ||
| </StackPanel> | ||
| </Grid> | ||
| </ui:FluentWindow> |
26 changes: 26 additions & 0 deletions
26
src/WindowController.App/DefaultProfilesMissingDialog.xaml.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| using System.Windows; | ||
| using Wpf.Ui.Controls; | ||
|
|
||
| namespace WindowController.App; | ||
|
|
||
| /// <summary> | ||
| /// Dialog shown when no default profiles are configured. | ||
| /// Returns <c>true</c> via DialogResult when the user chooses to open settings. | ||
| /// </summary> | ||
| public partial class DefaultProfilesMissingDialog : FluentWindow | ||
| { | ||
| public DefaultProfilesMissingDialog() | ||
| { | ||
| InitializeComponent(); | ||
| } | ||
|
|
||
| private void OpenSettings_Click(object sender, RoutedEventArgs e) | ||
| { | ||
| DialogResult = true; | ||
| } | ||
|
|
||
| private void Close_Click(object sender, RoutedEventArgs e) | ||
| { | ||
| DialogResult = false; | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
README のトレイメニュー説明が実装と不一致です。実装では「既定のプロファイルを適用」ですが、README では「プロファイルを適用(配置のみ)」になっています。実際のメニュー名と動作(既定プロファイルを適用する)に合わせて更新してください。