Skip to content

Improve Theme.cs#4302

Closed
Jack251970 wants to merge 21 commits intodevfrom
copilot/fix-cast-exception-bug
Closed

Improve Theme.cs#4302
Jack251970 wants to merge 21 commits intodevfrom
copilot/fix-cast-exception-bug

Conversation

@Jack251970
Copy link
Member

@Jack251970 Jack251970 commented Feb 27, 2026

This pull request makes several improvements and bug fixes to the theme and window styling logic in Theme.cs. The main focus is on making theme resource management more robust, improving drop shadow effect handling, ensuring safe brush usage, and enhancing dispatcher/thread safety for UI updates.

Theme resource management and robustness:

  • Refactored how theme resources are updated by wrapping resource addition in a try/catch block to handle InvalidCastException, preventing crashes when resource dictionaries contain unexpected types. (UpdateResourceDictionary, Flow.Launcher.Core/Resource/Theme.csL103-R124)
  • Improved dispatcher usage in async UI update methods (RefreshFrameAsync, SetBlurForWindowAsync) to ensure thread safety and avoid exceptions when called from non-UI threads. (RefreshFrameAsync, [1]; SetBlurForWindowAsync, [2]

Drop shadow and style application:

  • Reworked the logic for adding and removing drop shadow effects to create new unsealed styles, copy relevant setters, and correctly adjust margins, ensuring that effects are applied and removed cleanly without modifying the original style in place. (AddDropShadowEffectToCurrentTheme, RemoveDropShadowEffectFromCurrentTheme, Flow.Launcher.Core/Resource/Theme.csL480-R632)
  • Improved the handling of drop shadow and blur effects so that they interact correctly depending on the theme and system capabilities, and ensured corner preferences and effects are set and removed in the correct order. (AutoDropShadow, [1] [2]

Brush and resource safety:

Resource dictionary and style retrieval improvements:

Minor refactors and cleanups:

  • Cleaned up and clarified variable names and comments throughout the file for better readability. (Multiple locations)

Most important changes:

Theme resource management and thread safety:

  • Wrapped resource dictionary updates in a try/catch to handle InvalidCastException, preventing crashes when adding new theme resources.
  • Ensured all UI updates via dispatcher are thread-safe and only run on the UI thread, adding checks and proper invocation for RefreshFrameAsync and SetBlurForWindowAsync. [1] [2]

Drop shadow and style handling:

  • Refactored drop shadow effect logic to create new, unsealed styles and correctly adjust margins and effects, ensuring clean application and removal of visual effects.
  • Improved the interaction between blur and drop shadow effects, ensuring correct order and conditions for applying/removing effects and setting window corner preferences. [1] [2]

Brush and resource safety:

  • Added a helper to safely create caret brush values, avoiding shared mutable brushes and ensuring brushes are frozen when possible.

Resource dictionary and style retrieval:

  • Improved robustness when retrieving styles and resource dictionary entries, checking for existence before casting to prevent null reference exceptions. [1] [2]

Copilot AI and others added 2 commits February 27, 2026 14:39
…validation on Windows theme change

Co-authored-by: Jack251970 <53996452+Jack251970@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 27, 2026 14:48
@prlabeler prlabeler bot added the bug Something isn't working label Feb 27, 2026
@github-actions github-actions bot added this to the 2.2.0 milestone Feb 27, 2026
@gitstream-cm
Copy link

gitstream-cm bot commented Feb 27, 2026

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

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 2 files

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 27, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Wraps resource dictionary updates in defensive checks, adds a private helper to derive CaretBrush values from Foreground safely, freezes newly created brushes for immutability, makes CopyStyle static, hardens dispatcher usage in theme refresh/blur async flows, and limits frame refresh on theme change to the System color scheme. (≈33 words)

Changes

Cohort / File(s) Summary
Theme resource and brush handling
Flow.Launcher.Core/Resource/Theme.cs
Add GetNewCaretValue(object) to map Foreground → CaretBrush (handles DynamicResourceExtension, SolidColorBrush, other types). Wrap resource-dictionary additions in try/catch for InvalidCastException. Replace direct CaretBrush additions with guarded helper usage. Create new SolidColorBrush instances and call Freeze() before assigning. Make CopyStyle(Style, Style) static and adapt usages. Refactor async dispatcher checks in RefreshFrameAsync / SetBlurForWindowAsync.
Main window theme refresh
Flow.Launcher/MainWindow.xaml.cs
ActualApplicationThemeChanged now calls RefreshFrameAsync only when the color scheme is System (conditional refresh).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI as MainWindow
  participant Theme as Theme
  participant Disp as Dispatcher
  participant Win as Window

  UI->>Theme: ActualApplicationThemeChanged(event)
  alt ColorScheme == System
    Theme->>Disp: RefreshFrameAsync()
    Disp-->>Theme: Ensure on UI thread (reinvoke if needed)
    Theme->>Theme: Resolve Foreground (including DynamicResource)
    Theme->>Theme: GetNewCaretValue(foreground)
    Theme->>Theme: Create new SolidColorBrush & Freeze()
    Theme->>Win: Apply brush/setters (CopyStyle called statically)
    Theme->>Disp: SetBlurForWindowAsync() (dispatcher guard)
  else
    UI-->>Theme: Skip RefreshFrameAsync
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • onesounds
  • taooceros
  • jjw24
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Improve Theme.cs' is vague and generic, using non-descriptive language that does not convey meaningful information about the changeset. Use a more specific title that reflects the main fix, such as 'Fix InvalidCastException in Theme resource updates' or 'Add defensive handling for brush and resource assignments in Theme.cs'.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR implements defensive handling for InvalidCastException [#4298], adds try-catch around resource dictionary updates, introduces GetNewCaretValue for safer resource mapping, and freezes brushes for immutability, addressing core exception prevention requirements.
Out of Scope Changes check ✅ Passed All changes focus on Theme.cs brush/resource handling and MainWindow.xaml.cs theme refresh logic directly related to fixing the casting exception and resource handling [#4298].
Description check ✅ Passed The PR description is comprehensive, directly related to the changeset, and clearly documents improvements to theme and window styling logic with specific focus areas.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch copilot/fix-cast-exception-bug

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request suppresses a spurious error dialog that appears when users change Windows themes or accent colors. The error is caused by a WPF framework bug where SystemResources.InvalidateTreeResources incorrectly attempts to clone Color structs as if they were Freezable or Expression objects, resulting in an InvalidCastException that the application cannot prevent.

Changes:

  • Added IsRecoverableSystemResourceException method to detect the specific WPF system resource invalidation exception
  • Integrated the new exception check into ErrorReporting.Report to suppress the error dialog while still logging the exception
  • Added comprehensive documentation explaining the WPF framework issue

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
Flow.Launcher/Helper/ExceptionHelper.cs Added new method to detect InvalidCastException from WPF's SystemResources.InvalidateTreeResources
Flow.Launcher/Helper/ErrorReporting.cs Integrated the new exception check to prevent error dialog from being shown

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…ource invalidation on Windows theme change"

This reverts commit 372f142.
Refactored caret and background brush assignment to avoid sharing mutable instances and ensure proper resource referencing. Added GetNewCaretValue helper for safe caret brush creation. Brushes for backgrounds are now frozen for performance. Improved foreground value retrieval and dynamic resource key extraction. Made some methods static for clarity and consistency. Enhances resource management and reliability in theme handling.
@prlabeler prlabeler bot added Code Refactor enhancement New feature or request labels Feb 28, 2026
@coderabbitai coderabbitai bot removed bug Something isn't working enhancement New feature or request labels Feb 28, 2026
@Jack251970 Jack251970 changed the title Suppress spurious error dialog on Windows theme/accent color change Fix cast object of type 'System.Windows.Media.Color' to type 'System.Windows.Expression' exception Feb 28, 2026
@Jack251970 Jack251970 requested a review from Copilot February 28, 2026 07:17
@prlabeler prlabeler bot added the bug Something isn't working label Feb 28, 2026
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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Flow.Launcher.Core/Resource/Theme.cs (1)

814-819: ⚠️ Potential issue | 🟡 Minor

Remove ToString() when looking up DynamicResource keys in ResourceDictionary.

At line 814, converting dynamicResource.ResourceKey to string via ToString() violates WPF resource lookup semantics. ResourceDictionary requires matching the actual key object (e.g., ComponentResourceKey), not its string representation. This inconsistency is evident at line 260, where the code correctly preserves ResourceKey object identity.

Proposed fix
- var resourceKey = dynamicResource.ResourceKey.ToString();
+ var resourceKey = dynamicResource.ResourceKey;

- if (Resources.Contains(resourceKey))
+ if (resourceKey != null && Resources.Contains(resourceKey))
{
    var colorResource = Resources[resourceKey];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Flow.Launcher.Core/Resource/Theme.cs` around lines 814 - 819, The code is
converting dynamicResource.ResourceKey to a string before lookup which breaks
WPF resource key identity; in the Theme.cs block around the dynamicResource
handling, stop calling ToString() and use the ResourceKey object directly when
checking and retrieving from the ResourceDictionary (i.e., replace the use of
var resourceKey = dynamicResource.ResourceKey.ToString() and subsequent
Resources.Contains(resourceKey)/Resources[resourceKey] calls with checks that
use dynamicResource.ResourceKey itself so ComponentResourceKey and other
non-string keys resolve correctly).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@Flow.Launcher.Core/Resource/Theme.cs`:
- Around line 814-819: The code is converting dynamicResource.ResourceKey to a
string before lookup which breaks WPF resource key identity; in the Theme.cs
block around the dynamicResource handling, stop calling ToString() and use the
ResourceKey object directly when checking and retrieving from the
ResourceDictionary (i.e., replace the use of var resourceKey =
dynamicResource.ResourceKey.ToString() and subsequent
Resources.Contains(resourceKey)/Resources[resourceKey] calls with checks that
use dynamicResource.ResourceKey itself so ComponentResourceKey and other
non-string keys resolve correctly).

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 372f142 and 60b92c5.

📒 Files selected for processing (1)
  • Flow.Launcher.Core/Resource/Theme.cs

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Jack251970 Jack251970 enabled auto-merge February 28, 2026 07:29
Previously, the theme was refreshed on every theme change event.
Now, `_theme.RefreshFrameAsync()` is only called if the color
scheme setting is set to "System", preventing unnecessary
refreshes in other scenarios.
@gitstream-cm
Copy link

gitstream-cm bot commented Feb 28, 2026

🥷 Code experts: jjw24

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

See details

Flow.Launcher.Core/Resource/Theme.cs

Activity based on git-commit:

jjw24 Jack251970
FEB
JAN
DEC
NOV
OCT 12 additions & 2 deletions
SEP 2 additions & 2 deletions

Knowledge based on git-blame:
jjw24: 99%
Jack251970: 1%

Flow.Launcher/MainWindow.xaml.cs

Activity based on git-commit:

jjw24 Jack251970
FEB
JAN
DEC
NOV 1 additions & 1 deletions
OCT 8 additions & 7 deletions
SEP 1547 additions & 49 deletions

Knowledge based on git-blame:
Jack251970: 100%

✨ Comment /gs review for LinearB AI review. Learn how to automate it here.

@coderabbitai coderabbitai bot removed the bug Something isn't working label Feb 28, 2026
Refactored RefreshFrameAsync and SetBlurForWindowAsync to check Dispatcher access before invoking UI updates, ensuring thread safety and reducing unnecessary Dispatcher calls. Also removed redundant code and unused using directive.
@coderabbitai coderabbitai bot added the bug Something isn't working label Feb 28, 2026
@Jack251970 Jack251970 marked this pull request as draft March 1, 2026 04:16
auto-merge was automatically disabled March 1, 2026 04:16

Pull request was converted to draft

Jack251970 and others added 12 commits March 1, 2026 12:19
Improve IsBlurTheme to check blur support directly in the
current theme's resource dictionary, ensuring precise and
context-specific detection. Updated related logic and comments
for clarity.
Renamed the variable themeName to theme in the UpdateFonts method
to improve naming consistency. No functional changes were made.
Reworked how drop shadow effects are added and removed by creating new unsealed Style instances instead of modifying sealed ones. Resources, triggers, and setters are copied, with margin adjustments and effect setter management to ensure reliability. Introduced GetNewWindowBorderStyle helper for style copying.
Explicitly set DispatcherPriority.Render when invoking RefreshFrameAsync and SetBlurForWindowAsync on the application's dispatcher. This ensures theme-related UI changes are processed with rendering priority, improving responsiveness and visual consistency. Also added System.Windows.Threading import for access to DispatcherPriority.
Refactored theme resource dictionary lookups to safely check for "WindowBorderStyle" before accessing, preventing potential exceptions. Updated three methods to handle missing styles gracefully and standardized resource key checks. GetWindowBorderStyleBackground now returns transparent if style is missing.
Renamed IsBlurTheme to IsThemeBlurEnabled and moved system
backdrop support checks out of the helper function. Blur
availability is now determined by combining theme settings
and system capability in the calling code. Updated all
usages to reflect the new logic for improved clarity.
Refactored dark mode logic to first use user's ColorScheme
preference when "SystemBG" is set to "Auto". Only falls back
to system dark mode setting if ColorScheme is not explicitly
set to "Dark" or "Light". This ensures user preferences take
precedence over system defaults.
Freeze SolidColorBrush instances before assigning them to mainWindow.Background to improve performance and immutability. Applied to both transparent and selected background scenarios.
Replaces GetNewWindowBorderStyle with direct instantiation of a new Style for Border and uses CopyStyle to transfer properties. Removes the old helper method and moves style copying logic inline for improved clarity and maintainability.
Changed assignment of WindowBorderStyle to use Application.Current.Resources for global effect, replacing previous use of _oldResource. This ensures theme changes are applied consistently across the application.
@Jack251970 Jack251970 mentioned this pull request Mar 2, 2026
@prlabeler prlabeler bot added Code Refactor enhancement New feature or request labels Mar 2, 2026
@Jack251970 Jack251970 changed the title Fix cast object of type 'System.Windows.Media.Color' to type 'System.Windows.Expression' exception Improve Theme.cs Mar 2, 2026
@Jack251970 Jack251970 removed bug Something isn't working enhancement New feature or request Code Refactor 10 min review labels Mar 4, 2026
@Jack251970 Jack251970 removed this from the 2.2.0 milestone Mar 4, 2026
@Jack251970 Jack251970 closed this Mar 9, 2026
@Jack251970 Jack251970 deleted the copilot/fix-cast-exception-bug branch March 9, 2026 10:37
@Jack251970
Copy link
Member Author

This PR has been decomposed into #4318, #4319, #4330 and #4331

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants