Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
87cd3c1
Initial commit for BackgroundTest project
neon-nyan Nov 28, 2025
78e14af
[WIP - Incomplete] Implement NewPipsPager
neon-nyan Nov 30, 2025
e4b429a
[Test Ready] Implement NewPipsPager pt. 2
neon-nyan Nov 30, 2025
5e5f092
Update NewPipsPager
neon-nyan Dec 2, 2025
ae56c01
Fix color for light theme
neon-nyan Dec 5, 2025
f9016e5
Initial property for MediaSlideshow
neon-nyan Dec 5, 2025
8332927
Merge branch 'main' into background-refactor
neon-nyan Dec 6, 2025
8769e4c
Rename MediaSlideshow -> PanelSlideshow + First test
neon-nyan Dec 6, 2025
52c91ed
Fix element animation flies out-of-bound while switching
neon-nyan Dec 7, 2025
4c11f35
Merge branch 'main' into background-refactor
neon-nyan Dec 7, 2025
ccb1dd6
Add buttons for Slideshow
neon-nyan Dec 7, 2025
8f24aae
Add countdown timer for PanelSlideshow
neon-nyan Dec 8, 2025
4fd89b2
Improve NewPipsPager + PanelSlideshow
neon-nyan Dec 11, 2025
5e1f027
Merge branch 'main' into background-refactor
neon-nyan Dec 11, 2025
7d3a1a8
Initial implementation for LayeredBackgroundImage
neon-nyan Dec 11, 2025
78d031b
Implement loader for Image type on LayeredBackgroundImage
neon-nyan Dec 12, 2025
3efdec9
Add Video Background support
neon-nyan Dec 14, 2025
b257e12
Fix video player disposed after foreground load
neon-nyan Dec 14, 2025
c3113f4
Cleanup + Fix element layout state when loaded
neon-nyan Dec 14, 2025
7387499
Fix NewPipsPager button state on selected
neon-nyan Dec 15, 2025
d9b43ee
Use Uri instead of full FileStream for cached local file
neon-nyan Dec 15, 2025
bfd5d7c
Use native ISurfaceImageSourceNativeWithD2D
neon-nyan Dec 15, 2025
79f3845
Update Hi3Helper.Win32
neon-nyan Dec 15, 2025
5a815b9
Perform full MediaPlayer disposal on pause
neon-nyan Dec 16, 2025
46656ea
Use unsafe direct call for video frame drawing's ``EndDraw()``
neon-nyan Dec 16, 2025
4b117c1
Use SwapChainPanelHelper.NativeSurfaceImageSource_BeginDrawUnsafe
neon-nyan Dec 16, 2025
60dc597
Let cache decide stream disposal
neon-nyan Dec 16, 2025
fca7fa2
CodeQA
neon-nyan Dec 16, 2025
a993922
Code migration time!
neon-nyan Dec 16, 2025
d6ec6ae
Merge branch 'main' into background-refactor
neon-nyan Dec 16, 2025
722816d
Fix compile error
neon-nyan Dec 16, 2025
96e7f71
Update LayeredBackgroundImageExtensions.cs
neon-nyan Dec 17, 2025
2caeeb5
Merge branch 'main' into background-refactor
neon-nyan Dec 19, 2025
ab9a096
Fix and use new custom elements for carousel
neon-nyan Dec 20, 2025
ab46ff9
Use UIElementExtensions.CursorType for controls
neon-nyan Dec 20, 2025
5c9d3d4
Run XamlStyler
neon-nyan Dec 20, 2025
4d879a9
Always creates new transition on swipe-based transition
neon-nyan Dec 20, 2025
fecc199
Apply slideshow carousel pause while window is minimized
neon-nyan Dec 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions BackgroundTest/App.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<Application x:Class="BackgroundTest.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<ResourceDictionary Source="ms-appx:///CustomControl/NewPipsPager/NewPipsPager_themeresources.xaml" />
<ResourceDictionary Source="ms-appx:///CustomControl/NewPipsPager/NewPipsPager.xaml" />

<ResourceDictionary Source="ms-appx:///CustomControl/LayeredBackgroundImage/LayeredBackgroundImage.xaml" />

<ResourceDictionary Source="ms-appx:///CustomControl/PanelSlideshow/PanelSlideshow_themeresources.xaml" />
<ResourceDictionary Source="ms-appx:///CustomControl/PanelSlideshow/PanelSlideshow.xaml" />
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<AcrylicBrush x:Key="ContentBackgroundAcrylicBrush"
FallbackColor="#F0222222"
TintColor="#F0222222"
TintLuminosityOpacity="0.7"
TintOpacity="0" />
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<AcrylicBrush x:Key="ContentBackgroundAcrylicBrush"
FallbackColor="#F0FFFFFF"
TintColor="#FFFFFF"
TintLuminosityOpacity="1"
TintOpacity="0.0" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
23 changes: 23 additions & 0 deletions BackgroundTest/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Microsoft.UI.Xaml;

// ReSharper disable SwitchStatementMissingSomeEnumCasesNoDefault
// ReSharper disable CommentTypo
// ReSharper disable StringLiteralTypo

namespace BackgroundTest;

public partial class App
{
private TestWindow? _window;

public App()
{
InitializeComponent();
}

protected override void OnLaunched(LaunchActivatedEventArgs args)
{
_window = new TestWindow();
_window.Activate();
}
}
104 changes: 104 additions & 0 deletions BackgroundTest/BackgroundTest.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- General Properties -->
<OutputType>WinExe</OutputType>
<StartupObject>BackgroundTest.MainEntryPoint</StartupObject>
<Configurations>Debug;Release</Configurations>
<!-- Assembly Info Properties -->
<AssemblyName>BackgroundTest</AssemblyName>
<ProductName>Collapse</ProductName>
<Product>Collapse</Product>
<Description>Collapse</Description>
<AssemblyTitle>Collapse</AssemblyTitle>
<Company>Collapse Launcher Team</Company>
<Authors>$(Company). neon-nyan, Cry0, bagusnl, shatyuka, gablm.</Authors>
<Copyright>Copyright 2022-2025 $(Company)</Copyright>
<!-- Versioning -->
<Version>1.83.12</Version>
<LangVersion>preview</LangVersion>
<Nullable>enable</Nullable>
<!-- Target Settings -->
<Platforms>x64</Platforms>
<TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<CsWinRTAotOptimizerEnabled>true</CsWinRTAotOptimizerEnabled>
<!-- Debug Settings -->
<DebugType>portable</DebugType>
<GitVersion>false</GitVersion>
<!-- WinUI Properties -->
<UseWinUI>true</UseWinUI>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<!-- Analyzers Settings -->
<EnableAOTAnalyzer>true</EnableAOTAnalyzer>
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
<TrimmerSingleWarn>false</TrimmerSingleWarn>
<!-- Other Settings -->
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
<BuiltInComInteropSupport>false</BuiltInComInteropSupport>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<InvariantGlobalization>false</InvariantGlobalization>
<ShouldComputeInputPris>true</ShouldComputeInputPris>
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
<GenerateNeutralResourcesLanguageAttribute>false</GenerateNeutralResourcesLanguageAttribute>
<JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
<WebView2EnableCsWinRTProjection>true</WebView2EnableCsWinRTProjection>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<OutputType>Exe</OutputType>
<!-- !! IMPORTANT !!-->
<!-- DO NOT FORGET TO UPDATE THE DEFINECONSTANTS IN THE PUBLISH PROFILE(S) AS WELL -->
<DefineConstants>DISABLE_XAML_GENERATED_MAIN;ENABLEUSERFEEDBACK;USEVELOPACK;USENEWZIPDECOMPRESS;ENABLEHTTPREPAIR;PREVIEW;DUMPGIJSON;SIMULATEGIHDR;GSPBYPASSGAMERUNNING;MHYPLUGINSUPPORT</DefineConstants>
<TrimMode>full</TrimMode>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<!-- !! IMPORTANT !!-->
<!-- DO NOT FORGET TO UPDATE THE DEFINECONSTANTS IN THE PUBLISH PROFILE(S) AS WELL -->
<DefineConstants>DISABLE_XAML_GENERATED_MAIN;ENABLEUSERFEEDBACK;USEVELOPACK;USENEWZIPDECOMPRESS;ENABLEHTTPREPAIR;PREVIEW;MHYPLUGINSUPPORT</DefineConstants>
<Optimize>True</Optimize>
<GitSkipCache>true</GitSkipCache>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Publish'">
<!-- !! IMPORTANT !!-->
<!-- DO NOT FORGET TO UPDATE THE DEFINECONSTANTS IN THE PUBLISH PROFILE(S) AS WELL -->
<DefineConstants>DISABLE_XAML_GENERATED_MAIN;ENABLEUSERFEEDBACK;USEVELOPACK;USENEWZIPDECOMPRESS;ENABLEHTTPREPAIR;MHYPLUGINSUPPORT</DefineConstants>
<Optimize>true</Optimize>
<GitSkipCache>true</GitSkipCache>
</PropertyGroup>

<ItemGroup>
<Content Include="CustomControl\BGTestImage*">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
<PackageReference Include="CommunityToolkit.Common" Version="8.4.0" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="CommunityToolkit.WinUI.Behaviors" Version="8.2.250402" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.2.250402" />
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" />
<PackageReference Include="CommunityToolkit.WinUI.Converters" Version="8.2.250402" />
<PackageReference Include="CommunityToolkit.WinUI.Extensions" Version="8.2.250402" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.Sizers" Version="8.2.250402" />

<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.3.2" />
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.3.0-prerelease.250720.1" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.6901" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.8.251106002" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="3.0.0" />
<PackageReference Include="PhotoSauce.MagicScaler" Version="0.15.0" />
<PackageReference Include="PhotoSauce.NativeCodecs.Libheif" Version="1.19.5-preview1" />
<PackageReference Include="PhotoSauce.NativeCodecs.Libjxl" Version="0.11.1-preview2" />
<PackageReference Include="PhotoSauce.NativeCodecs.Libwebp" Version="*-*" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Hi3Helper.Win32\Hi3Helper.Win32.csproj" />
<ProjectReference Include="..\Hi3Helper.Win32\WinRT\Hi3Helper.Win32.WinRT.csproj" />
</ItemGroup>

</Project>
Binary file added BackgroundTest/CustomControl/BGTestImage1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added BackgroundTest/CustomControl/BGTestImage2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added BackgroundTest/CustomControl/BGTestImage3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added BackgroundTest/CustomControl/BGTestImage4.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions BackgroundTest/CustomControl/ChangedStructItemArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace BackgroundTest.CustomControl;

public readonly struct ChangedStructItemArgs<TItem>(TItem oldItem, TItem newItem)
where TItem : struct
{
public TItem OldItem { get; private init; } = oldItem;
public TItem NewItem { get; private init; } = newItem;
}

public class ChangedObjectItemArgs<TItem>(TItem? oldItem, TItem? newItem)
where TItem : class
{
public TItem? OldItem { get; private init; } = oldItem;
public TItem? NewItem { get; private init; } = newItem;
}
110 changes: 110 additions & 0 deletions BackgroundTest/CustomControl/Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
using Microsoft.UI.Input;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Data;
using System;
using System.IO;
using System.Runtime.CompilerServices;

namespace BackgroundTest.CustomControl;

public static class Extensions
{
public static readonly DependencyProperty CursorTypeProperty =
DependencyProperty.RegisterAttached("CursorType", typeof(InputSystemCursorShape),
typeof(UIElement), new PropertyMetadata(InputSystemCursorShape.Arrow));

public static InputSystemCursorShape GetCursorType(DependencyObject obj) => (InputSystemCursorShape)obj.GetValue(CursorTypeProperty);

public static void SetCursorType(DependencyObject obj, InputSystemCursorShape value)
{
InputSystemCursor? cursor = InputSystemCursor.Create(value);
if (cursor is null ||
obj is not UIElement asElement)
{
return;
}

asElement.SetCursor(cursor);
asElement.SetValue(CursorTypeProperty, value);
}

extension(Control source)
{
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "GetTemplateChild")]
private extern DependencyObject GetTemplateChildAccessor(string name);

internal T GetTemplateChild<T>(string name)
where T : class
{
DependencyObject obj = source.GetTemplateChildAccessor(name);
if (obj is not T castObj)
{
throw new
InvalidCastException($"Cannot cast type to: {typeof(T).Name} as the object expects type: {obj.GetType().Name}");
}

return castObj;
}
}

/// <param name="element">The <seealso cref="UIElement"/> member of an element</param>
extension(UIElement element)
{
/// <summary>
/// Set the cursor for the element.
/// </summary>
/// <param name="inputCursor">The cursor you want to set. Use <see cref="InputSystemCursor.Create"/> to choose the cursor you want to set.</param>
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "set_ProtectedCursor")]
private extern void SetCursor(InputCursor inputCursor);
}

internal static double TryGetDouble(this object? obj)
{
return obj switch
{
sbyte asSbyte => asSbyte,
byte asByte => asByte,
ushort asUshort => asUshort,
short asShort => asShort,
uint asUint => asUint,
int asInt => asInt,
ulong asUlong => asUlong,
long asLong => asLong,
float asFloat => asFloat,
double asDouble => asDouble,
_ => double.NaN
};
}

internal static void BindProperty(this FrameworkElement element,
FrameworkElement source,
string propertyName,
DependencyProperty dependencyProperty,
BindingMode bindingMode)
{
element.SetBinding(dependencyProperty, new Binding
{
Mode = bindingMode,
Source = source,
Path = new PropertyPath(propertyName)
});
}

internal static Uri GetStringAsUri(this string asStringSource)
{
// Try to create URL with absolute path.
// If not (assume it's a relative local path), then try to get the fully qualified local path.
if (Uri.TryCreate(asStringSource, UriKind.Absolute, out Uri? sourceUri) ||
Path.IsPathFullyQualified(asStringSource))
{
return sourceUri ?? new Uri(asStringSource);
}

string currentWorkingDir = Directory.GetCurrentDirectory();
ReadOnlySpan<char> asStringSourceSpan = asStringSource.Trim("/\\");
asStringSource = Path.Join(currentWorkingDir, asStringSourceSpan);

return sourceUri ?? new Uri(asStringSource);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.IO;
using System.Threading.Tasks;

namespace BackgroundTest.CustomControl.LayeredBackgroundImage;

/// <summary>
/// An interface which implements media cache handler for loading cached media sources.
/// </summary>
public interface IMediaCacheHandler
{
/// <summary>
/// Loads the media source from cached local path or URL or Seekable and Readable <see cref="Stream"/>.
/// </summary>
/// <param name="sourceObject">The input source to be cached.</param>
/// <returns>An instance of <see cref="MediaCacheResult"/> which defines the cached source and its properties.</returns>
Task<MediaCacheResult> LoadCachedSource(object? sourceObject);
}

/// <summary>
/// Contains the result and properties of the cached media source.
/// </summary>
public class MediaCacheResult
{
/// <summary>
/// Indicates whether to force using the WIC (Windows Imaging Component) decoder for image source or not.
/// </summary>
public bool ForceUseInternalDecoder { get; set; }

/// <summary>
/// The source of the media. Only <see cref="string"/> or <see cref="Uri"/> for local path and URL, or Seekable and Readable <see cref="Stream"/> types are supported.
/// </summary>
public object? CachedSource { get; set; }

/// <summary>
/// Whether to perform Dispose if <see cref="CachedSource"/> is a <see cref="Stream"/> type.
/// </summary>
public bool DisposeStream { get; set; }
}
Loading
Loading