Skip to content

Fix issues related to search window maximization and Snap behavior #3606

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
merged 7 commits into from
Jun 5, 2025

Conversation

onesounds
Copy link
Contributor

@onesounds onesounds commented Jun 2, 2025

What's the PR

  • Fix BUG: FL Window Height Stuck After Double-Click with Resize Cursor #2806
  • Prevent window from being maximized or resized by double-clicking the title bar or window borders.
  • Improve behavior when the window is maximized via the Snap feature.
  • Improve behavior when the window is snapped to the left or right or restored from a snapped state.
  • Fix window border issues when the window is snapped to the screen edges.
  • Disable the ability to minimize the window.

Details

Issue #2806 was resolved by preventing double-clicking on the window border. But when using the Snap feature with Win+Arrow keys (automatically resizing the window by dragging it to the top or sides of the monitor), several issues were identified with Flow’s behavior. The explanation is a bit complicated, but trying out various Snap scenarios easily reveals many problematic cases. No one will probably read all of this, but here’s a rough breakdown anyway:

Issue: When snapping, the window border is forcibly turned into a rectangle. This results in visible rounded corners and shadows being removed. The behavior differs between Blur and non-Blur themes.
Solution: Adjusted the border rendering logic to display correctly. This was not something that could be handled by application code alone. The window still appears as a rectangle, but we've ensured there are no remaining rounded corners or visual artifacts. Since becoming a rectangle is standard Windows behavior, we are keeping this behavior as is.

Issue: Pressing Win+Down Arrow minimizes the window, but there is no way to restore it except with Win+Up Arrow.
Solution: Prevented the window from being minimized.

Issue: While normal maximizing is blocked, OS-level forced maximization via Snap cannot be blocked.
Solution: The only way to exit this state is by dragging the title bar, but in Flow, the title area is hidden, making it non-intuitive for users. To address this, dragging from the title area while maximized now automatically restores the window to normal and allows a smooth drag transition.

Issue: When a window is unsnapped from left/right Snap, the OS automatically reduces its height. Flow interpreted this as a SizeChanged event and responded by updating the result count, often reducing it to 2.
Solution: If the window height shrinks to below the size needed to show even a single result, the result count is now preserved and not recalculated.

Test Cases

  • Flow should not be minimized using the Windows + Down Arrow key.
  • When Flow's window is snapped using Win + Left/Right Arrow or by dragging, the rounded border should not be visible inside the rectangular window.
  • When a Flow window snapped to the left or right is restored to normal state by dragging, the MaxResult count should remain unchanged.
  • When Flow's window is maximized by dragging it to the top of the monitor, the transition back to the normal window state via dragging should behave naturally.
  • Even if the window border is double-clicked, the result panel height should still display correctly on the next query.

ETC

  • Since the maximized state can now be exited more naturally (though it might feel slightly off if the result window is already visible, it's not too distracting), allowing the WIN+Up shortcut seems acceptable. However, just in case, I’ve decided to block all maximize behaviors except those triggered by Snap.

  • I remember it was possible to adjust the slightly oversized window that appears when maximized, but I didn’t bother implementing that due to the hassle.

  • There doesn’t seem to be a reliable way to detect snap events. I initially considered estimating snap status by calculating window size, but dropped that idea because Windows 11 supports various snap layouts (such as 1:1:1 splits instead of just halves), and there may also be interactions with tools like PowerToys FancyZones.

@prlabeler prlabeler bot added bug Something isn't working enhancement New feature or request labels Jun 2, 2025
@onesounds onesounds self-assigned this Jun 2, 2025

This comment has been minimized.

Copy link

gitstream-cm bot commented Jun 2, 2025

🥷 Code experts: Jack251970

Jack251970, onesounds have most 👩‍💻 activity in the files.
Jack251970, onesounds have most 🧠 knowledge in the files.

See details

Flow.Launcher.Core/Resource/Theme.cs

Activity based on git-commit:

Jack251970 onesounds
JUN
MAY 10 additions & 10 deletions
APR 29 additions & 27 deletions 25 additions & 12 deletions
MAR 881 additions & 954 deletions 1159 additions & 895 deletions
FEB 64 additions & 28 deletions 333 additions & 17 deletions
JAN 7 additions & 4 deletions

Knowledge based on git-blame:
Jack251970: 65%
onesounds: 23%

Flow.Launcher.Infrastructure/Win32Helper.cs

Activity based on git-commit:

Jack251970 onesounds
JUN
MAY 107 additions & 0 deletions
APR 202 additions & 33 deletions 4 additions & 0 deletions
MAR 581 additions & 226 deletions
FEB 13 additions & 16 deletions 22 additions & 0 deletions
JAN 0 additions & 138 deletions

Knowledge based on git-blame:
Jack251970: 95%

Flow.Launcher/MainWindow.xaml.cs

Activity based on git-commit:

Jack251970 onesounds
JUN 1 additions & 1 deletions
MAY 140 additions & 43 deletions 5 additions & 1 deletions
APR 69 additions & 45 deletions 5 additions & 1 deletions
MAR 1141 additions & 1076 deletions 327 additions & 141 deletions
FEB 1 additions & 1 deletions 8 additions & 4 deletions
JAN

Knowledge based on git-blame:
Jack251970: 68%
onesounds: 13%

To learn more about /:\ gitStream - Visit our Docs

Copy link

gitstream-cm bot commented Jun 2, 2025

Be a legend 🏆 by adding a before and after screenshot of the changes you made, especially if they are around UI/UX.

Copy link
Contributor

coderabbitai bot commented Jun 2, 2025

📝 Walkthrough

"""

Walkthrough

The changes refine window behavior by setting the window border corner radius to zero when blur effects are applied, and by enhancing mouse and window message handling in the main window to correctly manage resizing, maximizing, and double-click interactions, preventing window height from getting stuck.

Changes

Files/Paths Change Summary
Flow.Launcher.Core/Resource/Theme.cs Sets Border.CornerRadius to zero for Acrylic or Mica blur backdrops to ensure rectangular window borders.
Flow.Launcher.Infrastructure/Win32Helper.cs Adds trailing whitespace only; no functional changes.
Flow.Launcher/MainWindow.xaml.cs Modifies mouse down and window procedure to handle dragging, resizing, maximizing, and double-click events properly, including height and width updates.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant MainWindow

    User->>MainWindow: MouseDown (left button)
    alt Window is maximized
        MainWindow->>MainWindow: Calculate mouse position ratios relative to window
        MainWindow->>MainWindow: Restore window to normal state
        MainWindow->>MainWindow: Adjust window position to maintain cursor relative location
        MainWindow->>MainWindow: Initiate DragMove if mouse still pressed
    else Window is not maximized
        MainWindow->>MainWindow: DragMove immediately
    end

    User->>MainWindow: Window messages (WM_ENTERSIZEMOVE, WM_EXITSIZEMOVE, WM_NCLBUTTONDBLCLK, WM_SYSCOMMAND)
    MainWindow->>MainWindow: Update window size, layout, and handle maximize/minimize commands accordingly
Loading

Assessment against linked issues

Objective Addressed Explanation
Fix window height stuck after double-click with resize cursor (#2806)
Ensure window resizes and maximizes/minimizes correctly with user interactions (#2806)
Restore window height and layout after double-click or maximize/minimize actions (#2806)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes found.

Suggested reviewers

  • jjw24

Poem

A window’s dance from tall to wide,
With double-clicks, it will decide.
Borders squared, and blur applied,
No more heights that get denied!
The launcher leaps with nimble grace—
Bugs are gone, let’s celebrate this case!
🐇✨
"""


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 556a4c8 and 0ecc01d.

📒 Files selected for processing (1)
  • Flow.Launcher.Infrastructure/Win32Helper.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Flow.Launcher.Infrastructure/Win32Helper.cs
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: gitStream.cm
  • GitHub Check: gitStream.cm
  • GitHub Check: gitStream.cm
  • GitHub Check: gitStream.cm
  • GitHub Check: gitStream.cm
  • GitHub Check: build
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🔭 Outside diff range comments (1)
Flow.Launcher/MainWindow.xaml.cs (1)

538-616: 🛠️ Refactor suggestion

Translate Korean comments and improve code clarity.

The window message handling is well-implemented, but Korean comments should be translated.

 else if (msg == Win32Helper.WM_EXITSIZEMOVE)
 {
-    //Prevent updating the number of results when the window height is below the height of a single result item.
-    //This situation occurs not only when the user manually resizes the window, but also when the window is released from a side snap, as the OS automatically adjusts the window height.
-    //(Without this check, releasing from a snap can cause the window height to hit the minimum, resulting in only 2 results being shown.)
+    // Prevent updating the number of results when the window height is below the height of a single result item.
+    // This situation occurs not only when the user manually resizes the window, but also when the window is released from a side snap, 
+    // as the OS automatically adjusts the window height. Without this check, releasing from a snap can cause the window height 
+    // to hit the minimum, resulting in only 2 results being shown.
     if (_initialHeight != (int)Height && Height > (_settings.WindowHeightSize + _settings.ItemHeightSize))
     {

Also consider extracting the magic number:

+private const int WM_COMMAND_MASK = 0xFFF0;
+
 else if (msg == WM_SYSCOMMAND)
 {
-    int command = wParam.ToInt32() & 0xFFF0;
+    int command = wParam.ToInt32() & WM_COMMAND_MASK;
🧹 Nitpick comments (1)
Flow.Launcher.Core/Resource/Theme.cs (1)

674-682: Replace Korean comments with English for consistency.

The implementation logic is correct, but the comments should be in English to maintain consistency with the rest of the codebase.

-// For themes with blur enabled, the window border is rendered by the system, so it's treated as a simple rectangle regardless of thickness.
-//(This is to avoid issues when the window is forcibly changed to a rectangular shape during snap scenarios.)
+// For themes with blur enabled, the window border is rendered by the system, so it's treated as a simple rectangle.
+// This prevents shape distortion issues when the window is snapped to screen edges.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a06cb43 and 08038de.

📒 Files selected for processing (3)
  • Flow.Launcher.Core/Resource/Theme.cs (1 hunks)
  • Flow.Launcher.Infrastructure/Win32Helper.cs (1 hunks)
  • Flow.Launcher/MainWindow.xaml.cs (4 hunks)
🧰 Additional context used
🪛 GitHub Actions: Check Spelling
Flow.Launcher/MainWindow.xaml.cs

[warning] 83-83: Ioc is not a recognized word. (unrecognized-spelling)


[warning] 84-84: Ioc is not a recognized word. (unrecognized-spelling)


[warning] 460-460: VSTHRD is not a recognized word. (unrecognized-spelling)


[warning] 520-520: VSTHRD is not a recognized word. (unrecognized-spelling)


[warning] 532-532: VSTHRD is not a recognized word. (unrecognized-spelling)


[warning] 634-634: WMP is not a recognized word. (unrecognized-spelling)


[warning] 636-636: WMP is not a recognized word. (unrecognized-spelling)


[warning] 637-637: WMP is not a recognized word. (unrecognized-spelling)


[warning] 638-638: WMP is not a recognized word. (unrecognized-spelling)


[warning] 718-718: gamemode is not a recognized word. (unrecognized-spelling)


[warning] 719-719: gamemode is not a recognized word. (unrecognized-spelling)


[warning] 722-722: gamemode is not a recognized word. (unrecognized-spelling)


[warning] 725-725: positionreset is not a recognized word. (unrecognized-spelling)


[warning] 728-728: positionreset is not a recognized word. (unrecognized-spelling)


[warning] 744-744: gamemode is not a recognized word. (unrecognized-spelling)


[warning] 745-745: positionreset is not a recognized word. (unrecognized-spelling)


[warning] 750-750: positionreset is not a recognized word. (unrecognized-spelling)


[warning] 860-860: XRatio is not a recognized word. (unrecognized-spelling)


[warning] 861-861: YRatio is not a recognized word. (unrecognized-spelling)


[warning] 1075-1075: clocksb is not a recognized word. (unrecognized-spelling)


[warning] 1076-1076: clocksb is not a recognized word. (unrecognized-spelling)


[warning] 1077-1077: iconsb is not a recognized word. (unrecognized-spelling)


[warning] 1078-1078: iconsb is not a recognized word. (unrecognized-spelling)


[warning] 1083-1083: clocksb is not a recognized word. (unrecognized-spelling)


[warning] 1084-1084: iconsb is not a recognized word. (unrecognized-spelling)

Flow.Launcher.Infrastructure/Win32Helper.cs

[warning] 43-43: Dwm is not a recognized word. (unrecognized-spelling)


[warning] 45-45: DWMWA is not a recognized word. (unrecognized-spelling)


[warning] 45-45: DWMWINDOWATTRIBUTE is not a recognized word. (unrecognized-spelling)


[warning] 55-55: DWMSBT is not a recognized word. (unrecognized-spelling)


[warning] 55-55: SYSTEMBACKDROP is not a recognized word. (unrecognized-spelling)


[warning] 56-56: DWMSBT is not a recognized word. (unrecognized-spelling)


[warning] 56-56: SYSTEMBACKDROP is not a recognized word. (unrecognized-spelling)


[warning] 57-57: DWMSBT is not a recognized word. (unrecognized-spelling)


[warning] 57-57: SYSTEMBACKDROP is not a recognized word. (unrecognized-spelling)


[warning] 60-60: Dwm is not a recognized word. (unrecognized-spelling)


[warning] 60-60: PInvoke is not a recognized word. (unrecognized-spelling)


[warning] 62-62: DWMWA is not a recognized word. (unrecognized-spelling)


[warning] 62-62: DWMWINDOWATTRIBUTE is not a recognized word. (unrecognized-spelling)


[warning] 62-62: SYSTEMBACKDROP is not a recognized word. (unrecognized-spelling)


[warning] 71-71: Dwm is not a recognized word. (unrecognized-spelling)


[warning] 71-71: PInvoke is not a recognized word. (unrecognized-spelling)


[warning] 73-73: DWMWA is not a recognized word. (unrecognized-spelling)


[warning] 73-73: DWMWINDOWATTRIBUTE is not a recognized word. (unrecognized-spelling)


[warning] 89-89: DWMWCP is not a recognized word. (unrecognized-spelling)


[warning] 90-90: DWMWCP is not a recognized word. (unrecognized-spelling)


[warning] 91-91: DWMWCP is not a recognized word. (unrecognized-spelling)


[warning] 95-95: Dwm is not a recognized word. (unrecognized-spelling)


[warning] 95-95: PInvoke is not a recognized word. (unrecognized-spelling)


[warning] 97-97: DWMWA is not a recognized word. (unrecognized-spelling)


[warning] 97-97: DWMWINDOWATTRIBUTE is not a recognized word. (unrecognized-spelling)


[warning] 108-108: PInvoke is not a recognized word. (unrecognized-spelling)


[warning] 163-163: GWL is not a recognized word. (unrecognized-spelling)


[warning] 181-181: GWL is not a recognized word. (unrecognized-spelling)


[warning] 186-186: GWL is not a recognized word. (unrecognized-spelling)


[warning] 197-197: GWL is not a recognized word. (unrecognized-spelling)


[warning] 204-204: Wnd is not a recognized word. (unrecognized-spelling)


[warning] 206-206: Wnd is not a recognized word. (unrecognized-spelling)


[warning] 214-214: Wnd is not a recognized word. (unrecognized-spelling)


[warning] 218-218: Wnd is not a recognized word. (unrecognized-spelling)


[warning] 271-271: WINTAB is not a recognized word. (unrecognized-spelling)


[warning] 284-284: Progman is not a recognized word. (unrecognized-spelling)


[warning] 285-285: WORKERW is not a recognized word. (unrecognized-spelling)


[warning] 525-525: hkl is not a recognized word. (unrecognized-spelling)


[warning] 531-531: hkl is not a recognized word. (unrecognized-spelling)


[warning] 557-557: nqo is not a recognized word. (unrecognized-spelling)


[warning] 630-630: tsf is not a recognized word. (unrecognized-spelling)


[warning] 653-653: tsf is not a recognized word. (unrecognized-spelling)


[warning] 653-653: tsf is not a recognized word. (unrecognized-spelling)


[warning] 654-654: Tsf is not a recognized word. (unrecognized-spelling)


[warning] 690-690: Noto is not a recognized word. (unrecognized-spelling)


[warning] 691-691: Noto is not a recognized word. (unrecognized-spelling)


[warning] 692-692: Noto is not a recognized word. (unrecognized-spelling)


[warning] 693-693: Noto is not a recognized word. (unrecognized-spelling)


[warning] 734-734: noto is not a recognized word. (unrecognized-spelling)


[warning] 737-737: noto is not a recognized word. (unrecognized-spelling)


[warning] 739-739: noto is not a recognized word. (unrecognized-spelling)


[warning] 759-759: noto is not a recognized word. (unrecognized-spelling)

⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: gitStream.cm
  • GitHub Check: gitStream.cm
  • GitHub Check: gitStream.cm
  • GitHub Check: build

This comment has been minimized.

This comment has been minimized.

SizeToContent = SizeToContent.Height;
handled = true;
}
else if (msg == WM_SYSCOMMAND)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Block Maximize/Minimize by Win+Up and Win+Down Arrow

@@ -541,7 +598,20 @@ private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref b

handled = true;
}

if (msg == WM_NCLBUTTONDBLCLK)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Block the double click in frame

@@ -465,7 +465,52 @@ private void OnPreviewMouseMove(object sender, MouseEventArgs e)

private void OnMouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left) DragMove();
if (e.ChangedButton == MouseButton.Left)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

When the window is maximized via Snap, dragging attempts will first switch the window from Maximized to Normal state, and adjust the drag position accordingly.

@@ -671,7 +671,15 @@ private void SetBlurForWindow(string theme, BackdropTypes backdropType)
windowBorderStyle.Setters.Remove(windowBorderStyle.Setters.OfType<Setter>().FirstOrDefault(x => x.Property.Name == "Background"));
windowBorderStyle.Setters.Add(new Setter(Border.BackgroundProperty, new SolidColorBrush(Colors.Transparent)));
}


Copy link
Contributor Author

Choose a reason for hiding this comment

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

Eliminated the issue where internal border values remained visible when the window border was forcibly set to a rectangle via Snap. This behavior only applies when blur is enabled; non-blur themes are unaffected.

@onesounds
Copy link
Contributor Author

@coderabbitai Review again please, lady.

Copy link
Contributor

coderabbitai bot commented Jun 2, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

@onesounds, I'll provide a fresh comprehensive review of your window management fixes.


🏁 Script executed:

#!/bin/bash
# Let's examine the key changes in detail
echo "=== Reviewing Theme.cs changes ==="
cat "Flow.Launcher.Core/Resource/Theme.cs"
echo -e "\n=== Reviewing MainWindow.xaml.cs changes ==="
cat "Flow.Launcher/MainWindow.xaml.cs"
echo -e "\n=== Checking Win32Helper.cs ==="
cat "Flow.Launcher.Infrastructure/Win32Helper.cs"

Length of output: 91477


Excellent work on this comprehensive window management fix! I can see you've put significant thought into handling the complex edge cases around window snapping and maximization. Here's my detailed review:

🎯 Strengths of the Implementation

1. Theme.cs - Corner Radius Fix

// For themes with blur enabled, the window border is rendered by the system, so it's treated as a simple rectangle regardless of thickness.
//(This is to avoid issues when the window is forcibly changed to a rectangular shape during snap scenarios.)
var cornerRadiusSetter = windowBorderStyle.Setters.OfType<Setter>().FirstOrDefault(x => x.Property == Border.CornerRadiusProperty);
if (cornerRadiusSetter != null)
    cornerRadiusSetter.Value = new CornerRadius(0);
else
    windowBorderStyle.Setters.Add(new Setter(Border.CornerRadiusProperty, new CornerRadius(0)));

Smart approach: Setting corner radius to 0 for blur themes prevents visual artifacts when Windows forces rectangular shapes during snapping.

Proper setter handling: The code correctly checks for existing setters before adding new ones.

2. MainWindow.xaml.cs - Enhanced Mouse Handling

if (WindowState == WindowState.Maximized)
{
    // Calculate ratio based on maximized window dimensions
    double maxWidth = this.ActualWidth;
    double maxHeight = this.ActualHeight;
    var mousePos = e.GetPosition(this);
    double xRatio = mousePos.X / maxWidth;
    double yRatio = mousePos.Y / maxHeight;
    
    // Current monitor information
    var screen = Screen.FromHandle(new WindowInteropHelper(this).Handle);
    var workingArea = screen.WorkingArea;
    var screenLeftTop = Win32Helper.TransformPixelsToDIP(this, workingArea.X, workingArea.Y);
    
    // Switch to Normal state
    WindowState = WindowState.Normal;

Excellent ratio calculation: Maintaining relative mouse position when dragging from maximized state creates a natural user experience.

Multi-monitor awareness: Properly handles different monitor configurations with DPI scaling.

3. Window Message Handling

//Prevent updating the number of results when the window height is below the height of a single result item.
//This situation occurs not only when the user manually resizes the window, but also when the window is released from a side snap, as the OS automatically adjusts the window height.
//(Without this check, releasing from a snap can cause the window height to hit the minimum, resulting in only 2 results being shown.)
if (_initialHeight != (int)Height && Height> (_settings.WindowHeightSize + _settings.ItemHeightSize))

Thoughtful safeguard: The height threshold check prevents unwanted result count recalculations during snap operations.

Clear documentation: Excellent comments explaining the edge case this addresses.

🔍 Potential Improvements & Considerations

1. Error Handling Enhancement

try
{
    // ... existing drag logic
}
catch (InvalidOperationException)
{
    // Ignored - can occur if drag operation is already in progress
}

Consider adding logging for debugging purposes:

catch (InvalidOperationException ex)
{
    // Log for debugging but don't show to user as this is expected in some scenarios
    _api.LogDebug(ClassName, $"Drag operation exception (expected): {ex.Message}");
}

2. Magic Number Constants

The hardcoded values could be extracted to constants:

private const int SHADOW_MARGIN = 32;
private const int WINDOW_BORDER_ADJUSTMENT = 14;

3. Async Pattern Consideration

The Dispatcher.BeginInvoke in the drag handling could potentially be improved:

Dispatcher.BeginInvoke(new Action(() =>
{
    // ... position calculation
}), DispatcherPriority.ApplicationIdle);

Consider using Dispatcher.InvokeAsync for better async/await patterns if this becomes more complex.

🏗️ Architecture Assessment

Separation of Concerns: Theme-related changes in Theme.cs, window behavior in MainWindow.xaml.cs - clean separation.

Defensive Programming: Multiple safeguards against edge cases (height thresholds, exception handling, etc.).

Performance Conscious: Only updates when necessary (height/width change detection).

🎯 Addresses Original Issues

Based on the PR objectives, this implementation successfully addresses:

  • Window height stuck after double-click: SizeToContent = SizeToContent.Height resolves this
  • Border rendering issues during snap: Corner radius fix handles this
  • Maximized window dragging: Sophisticated ratio-based restoration
  • Result count preservation: Height threshold prevents unwanted recalculations

📝 Minor Suggestions

  1. Consider extracting window message constants to a shared location if used elsewhere
  2. Add unit tests for the ratio calculation logic if possible
  3. Consider adding telemetry to track how often these edge cases occur in production

Overall, this is a well-engineered solution that demonstrates deep understanding of Windows window management complexities. The fix is comprehensive and should resolve the reported issues effectively! 🎉

Copy link

github-actions bot commented Jun 2, 2025

@check-spelling-bot Report

🔴 Please review

See the 📂 files view, the 📜action log, or 📝 job summary for details.

❌ Errors and Warnings Count
❌ forbidden-pattern 24
⚠️ non-alpha-in-dictionary 13

See ❌ Event descriptions for more information.

Forbidden patterns 🙅 (1)

In order to address this, you could change the content to not match the forbidden patterns (comments before forbidden patterns may help explain why they're forbidden), add patterns for acceptable instances, or adjust the forbidden patterns themselves.

These forbidden patterns matched content:

s.b. workaround(s)

\bwork[- ]arounds?\b
If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

@Jack251970 Jack251970 added this to the Future milestone Jun 3, 2025
@onesounds
Copy link
Contributor Author

Note: When the fixed size option is enabled, the snap feature doesn't work at all. Might be worth trying to enable it only while dragging.

@Jack251970 Jack251970 modified the milestones: Future, 1.20.1 Jun 4, 2025
@jjw24 jjw24 enabled auto-merge June 5, 2025 03:09
@jjw24 jjw24 removed enhancement New feature or request 10 min review labels Jun 5, 2025
@jjw24 jjw24 merged commit 9be5938 into Flow-Launcher:dev Jun 5, 2025
5 checks passed
@jjw24 jjw24 changed the title Fix issues related to window maximization and Snap behavior Fix issues related to search window maximization and Snap behavior Jun 5, 2025
@prlabeler prlabeler bot added the enhancement New feature or request label Jun 5, 2025
@jjw24 jjw24 removed the enhancement New feature or request label Jun 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BUG: FL Window Height Stuck After Double-Click with Resize Cursor
3 participants