diff --git a/Canopy.Core/Canopy.Core.csproj b/Canopy.Core/Canopy.Core.csproj
index 6480354..c9a1159 100644
--- a/Canopy.Core/Canopy.Core.csproj
+++ b/Canopy.Core/Canopy.Core.csproj
@@ -12,11 +12,19 @@
+
+
-
+
+
+
+
+
+
+
diff --git a/Canopy.Core/Canopy.cs b/Canopy.Core/Canopy.cs
new file mode 100644
index 0000000..9486991
--- /dev/null
+++ b/Canopy.Core/Canopy.cs
@@ -0,0 +1,259 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using Canopy.Configuration;
+using Canopy.Providers;
+using Canopy.Server;
+using Canopy.Server.Messages;
+using Serilog;
+using Synesthesia.Utils.Extensions;
+using SynesthesiaDev.Synx;
+using SynesthesiaDev.Synx.Codon;
+
+namespace Canopy;
+
+public class Canopy(ICanopyPlatform platform)
+{
+ public readonly ICanopyPlatform Platform = platform;
+
+ public static Config CurrentConfig = null!;
+
+ public static readonly GeopositionProvider GEOPOSITION_PROVIDER = new GeopositionProvider();
+ public static readonly WeatherProvider WEATHER_PROVIDER = new WeatherProvider();
+ public static readonly TimeOfDayProvider TIME_OF_DAY_PROVIDER = new TimeOfDayProvider();
+ public static readonly SeasonProvider SEASON_PROVIDER = new SeasonProvider();
+ public static readonly HolidayProvider HOLIDAY_PROVIDER = new HolidayProvider();
+
+ private CanopyState? lastState;
+
+#if DEBUG
+ public static readonly string CANOPY_FOLDER_PATH = Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
+ ".canopy-development"
+ );
+#else
+ public static readonly string CANOPY_FOLDER_PATH = Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
+ ".canopy"
+ );
+#endif
+
+ public static bool ConfigMigrated = false;
+ public static readonly string CONFIG_FILE_PATH = Path.Combine(CANOPY_FOLDER_PATH, "config.synx");
+
+ public CanopyWebsocketServer? WebsocketServer;
+
+ public void Initialize()
+ {
+ Log.Verbose("Initializing Canopy..");
+
+ LoadRefreshable();
+
+ var task = Task.Run(async () =>
+ {
+ using var timer = new PeriodicTimer(TimeSpan.FromMilliseconds(CurrentConfig.General.RefreshPeriod));
+ while (await timer.WaitForNextTickAsync())
+ Refresh();
+ });
+
+ Platform.InitializeTray(this);
+
+ Console.ReadLine();
+ }
+
+ public void LoadRefreshable()
+ {
+ loadConfig();
+ lastState = null;
+ GEOPOSITION_PROVIDER.InvalidateCache();
+
+ WebsocketServer?.Stop();
+ if (CurrentConfig.Websocket.Enabled)
+ {
+ WebsocketServer = new CanopyWebsocketServer();
+ WebsocketServer.Initialize();
+ }
+
+ Refresh();
+ }
+
+ private void loadConfig()
+ {
+ Log.Verbose("Loading config..");
+ if (!Directory.Exists(CANOPY_FOLDER_PATH))
+ {
+ Directory.CreateDirectory(CANOPY_FOLDER_PATH);
+ }
+
+ if (!File.Exists(CONFIG_FILE_PATH))
+ {
+ Log.Verbose("Config file doesn't exist.. creating new one");
+
+ File.Create(CONFIG_FILE_PATH).Close();
+ var encodedText = Config.VERSIONED_CODEC.Encode(SynxTranscoder.INSTANCE, Config.DEFAULT).Object().EncodeToString();
+ File.WriteAllText(CONFIG_FILE_PATH, encodedText);
+
+ CurrentConfig = Config.DEFAULT;
+ }
+ else
+ {
+ var decoded = Config.VERSIONED_CODEC.Decode(SynxTranscoder.INSTANCE, File.ReadAllText(CONFIG_FILE_PATH).ToSynxObject());
+ CurrentConfig = decoded;
+ if (ConfigMigrated)
+ {
+ var encoded = Config.VERSIONED_CODEC.Encode(SynxTranscoder.INSTANCE, CurrentConfig).Object().EncodeToString();
+ File.WriteAllText(CONFIG_FILE_PATH, encoded);
+ Log.Information("A migration was applied to your config and it was re-written");
+ }
+ }
+
+ Log.Information("Loaded {wallpapers} wallpapers", CurrentConfig.Wallpapers.Count);
+ validateConfig();
+ }
+
+ public void Refresh()
+ {
+ Log.Debug("Refreshing state..");
+ var time = TIME_OF_DAY_PROVIDER.Get();
+ var weather = WEATHER_PROVIDER.Get();
+ var season = SEASON_PROVIDER.Get();
+ var holiday = HOLIDAY_PROVIDER.Get();
+
+ var state = new CanopyState(time, weather, season, holiday);
+
+ if (CurrentConfig.System.ChangeSystemThemesDependingOnTime && time != lastState?.Time)
+ {
+ var theme = getThemeForTimeOfDay(time);
+ Log.Information("Changing system theme to {theme}", theme);
+ Platform.SetTheme(theme);
+ }
+
+ if (lastState == state)
+ {
+ Log.Debug("State is same, no updates");
+ return;
+ }
+
+ lastState = state;
+
+ var next = PickNextWallpaper(time, weather, season, holiday);
+ if (next == null)
+ {
+ Log.Error("No wallpapers found for current state ({state})", state);
+ return;
+ }
+
+ Log.Information("Picked new wallpaper: {pick}!", next.Path);
+ Log.Verbose("Setting wallpaper via {type}", Platform.GetType().Name);
+ Platform.SetDesktop(ResolveWallpaperPath(next.Path));
+
+ var message = new NewWallpaperMessage(DateTimeOffset.Now.ToUnixTimeMilliseconds(), next);
+ WebsocketServer?.Send(message);
+ }
+
+ private record CanopyState(TimeOfDay Time, WeatherType Weather, SeasonType Season, Holiday? Holiday);
+
+ public Wallpaper? PickNextWallpaper(TimeOfDay time, WeatherType weather, SeasonType season, Holiday? holiday)
+ {
+ if (holiday != null)
+ {
+ var holidayWallpapers = CurrentConfig.Wallpapers.Filter(w => w.Holiday.Value == holiday);
+ if (holidayWallpapers.IsNotEmpty())
+ {
+ var wallpaper = holidayWallpapers.Random();
+ return wallpaper;
+ }
+ }
+
+
+ var eligible = CurrentConfig.Wallpapers.Filter(w =>
+ containsOrEmpty(w.Season, season) &&
+ containsOrEmpty(w.Time, time) &&
+ containsOrEmpty(w.Weather, weather) &&
+ w.Holiday.IsMissing
+ );
+
+
+ if (eligible.IsEmpty()) return null;
+
+ var scored = eligible
+ .Select(w => (Wallpaper: w, Score: scoreWallpaper(w, time, weather, season)))
+ .ToList();
+
+ var topScore = scored.Max(s => s.Score);
+
+ Log.Verbose(" ");
+ Log.Verbose("Scorer:");
+ foreach (var (wallpaper, score) in scored)
+ {
+ Log.Verbose("{paper} - {score}", wallpaper.Path, score);
+ }
+
+ Log.Verbose(" ");
+
+ var topMatches = scored.Where(s => s.Score == topScore).Select(s => s.Wallpaper).ToList();
+
+ return topMatches.IsEmpty() ? null : topMatches.Random();
+ }
+
+ private ICanopyPlatform.Theme getThemeForTimeOfDay(TimeOfDay time) =>
+ time switch
+ {
+ TimeOfDay.Sunset or TimeOfDay.Morning or TimeOfDay.Afternoon => ICanopyPlatform.Theme.Light,
+ TimeOfDay.Sunrise or TimeOfDay.Night or TimeOfDay.DeepNight => ICanopyPlatform.Theme.Dark,
+ _ => ICanopyPlatform.Theme.Light
+ };
+
+ private static int scoreWallpaper(Wallpaper w, TimeOfDay time, WeatherType weather, SeasonType season)
+ {
+ int score = 0;
+ if (w.Time.Contains(time)) score++;
+ if (w.Weather.Contains(weather))
+ {
+ score++;
+ if (weather is WeatherType.Rainy or WeatherType.Stormy)
+ score++;
+ }
+
+ if (w.Season.Contains(season)) score++;
+ return score;
+ }
+
+ private static bool containsOrEmpty(List list, T item)
+ {
+ if (list.IsEmpty()) return true;
+ return list.Contains(item);
+ }
+
+ private void validateConfig()
+ {
+ string? error = null;
+ foreach (var wallpaper in CurrentConfig.Wallpapers)
+ {
+ if (!File.Exists(ResolveWallpaperPath(wallpaper.Path)))
+ {
+ error = $"Wallpaper with path {ResolveWallpaperPath(wallpaper.Path)} doesn't exist";
+ }
+
+ if (wallpaper.Accent != null)
+ {
+ if (wallpaper.Accent.Length != 7 || !wallpaper.Accent.StartsWith('#'))
+ error = $"Invalid accent format. Must be hex color like #ff00ff (Wallpaper {wallpaper.Path})";
+ }
+ }
+
+ if (error != null)
+ {
+ Log.Error(error);
+ Environment.Exit(0);
+ }
+ }
+
+ public static string ResolveWallpaperPath(string rawPath)
+ {
+ if (Path.IsPathRooted(rawPath))
+ return rawPath;
+
+ return Path.GetFullPath(Path.Combine(CANOPY_FOLDER_PATH, rawPath));
+ }
+}
diff --git a/Canopy.Core/Configuration/Config.cs b/Canopy.Core/Configuration/Config.cs
new file mode 100644
index 0000000..1618ff7
--- /dev/null
+++ b/Canopy.Core/Configuration/Config.cs
@@ -0,0 +1,61 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using Codon.Codec;
+using Codon.Codec.Versioned;
+using SynesthesiaDev.Synx.Types;
+
+namespace Canopy.Configuration;
+
+public record Config(
+ // ReSharper disable once InconsistentNaming
+ string _schema,
+ GeneralConfig General,
+ SystemConfig System,
+ UpdaterConfig Updater,
+ WeatherConfig Weather,
+ WebsocketConfig Websocket,
+ List Wallpapers
+)
+{
+ public static readonly Config DEFAULT = new Config
+ (
+ _schema: "https://github.com/SynesthesiaDev/Canopy/blob/main/schema.md",
+ General: GeneralConfig.DEFAULT,
+ System: SystemConfig.DEFAULT,
+ Updater: UpdaterConfig.DEFAULT,
+ Weather: WeatherConfig.DEFAULT,
+ Websocket: WebsocketConfig.DEFAULT,
+ Wallpapers: Wallpaper.DEFAULT_WALLPAPERS
+ );
+
+ public static readonly StructCodec CODEC = StructCodec.For()
+ .Field("_schema", Codecs.STRING, c => c._schema)
+ .Field("General", GeneralConfig.CODEC, c => c.General)
+ .Field("System", SystemConfig.CODEC, c => c.System)
+ .Field("Updater", UpdaterConfig.CODEC, c => c.Updater)
+ .Field("Weather", WeatherConfig.CODEC, c => c.Weather)
+ .Field("Websocket", WebsocketConfig.CODEC, c => c.Websocket)
+ .Field("Wallpapers", Wallpaper.CODEC.List(), c => c.Wallpapers)
+ .Build((s, config, arg3, arg4, arg5, arg6, arg7) => new Config(s, config, arg3, arg4, arg5, arg6, arg7));
+
+ public static readonly VersionedStructCodec VERSIONED_CODEC = new VersionedStructCodec
+ {
+ CurrentSchemaVersion = 2,
+ InnerCodec = CODEC,
+ SchemaMigrationRegistry = SchemaMigrationRegistry.Builder().For(builder =>
+ {
+ builder.Add(1, (transcoder, _, output) =>
+ {
+ output.Put(transcoder.EncodeString("_schema"), transcoder.EncodeString(DEFAULT._schema));
+ Canopy.ConfigMigrated = true;
+ });
+ builder.Add(2, (transcoder, _, output) =>
+ {
+ output.Put(transcoder.EncodeString("ChangeSystemThemesDependingOnTime"), transcoder.EncodeBool(DEFAULT.System.ChangeSystemThemesDependingOnTime));
+ Canopy.ConfigMigrated = true;
+ });
+ })
+ };
+
+}
diff --git a/Canopy.Core/Configuration/ConfigurationScript.cs b/Canopy.Core/Configuration/ConfigurationScript.cs
deleted file mode 100644
index 76062a2..0000000
--- a/Canopy.Core/Configuration/ConfigurationScript.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using Canopy.Graphics;
-using Canopy.Rendering;
-using Canopy.Utils;
-using Synesthesia.Utils;
-
-namespace Canopy.Configuration;
-
-public class CanopyUserlandScope
-{
- public required RuntimeInfo.Platform Platform;
- public required string Version;
- public required bool IsDevelopmentBuild;
- public required string OpenGLVersion;
- public required string ShaderVersion;
-
- /*
- * Registers a clock with specified interval. Can be listened to via
- */
- public void RegisterClock(TimeSpan interval)
- {
- // internals later, just api layer now
- }
-
- /*
- * You should only really do this if you know what you are doing.
- * Calling this will disable built-in frame optimizations (running at 0fps until needed)
- * And leave this up to you
- */
- public void RegisterDrawHook()
- {
- }
-
- public class Configuration
- {
- /*
- * Set the underlying windows wallpaper to any newly pushed wallpaper
- * In case the program crashes, and before it start up (windows can be slow on startup when running auto-run programs)
- */
- public bool SetUnderlyingWindowsWallpaper = true;
-
- /*
- * Initializes OpenGL with 8 stencil bits.
- * Not needed for normal use, but if you run custom shaders or
- * more complex rendering logic with masking, you may need this.
- */
- public bool UseStencil = false;
-
- /*
- * Show the default wallpaper if no user-selected one is currently showing.
- * This is mainly for first-run wizard kinda thing since the default wallpaper has config instructions in it (im too lazy to render text)
- */
- public bool ShowDefaultWallpaper = true;
-
- /*
- * Release stream for an automatic update to pull from.
- * WARNING: Development release stream may be unstable and introduce breaking api changes often
- */
- public ReleaseStream ReleaseStream = ReleaseStream.Release;
-
- /*
- * Done on startup using Velopack
- */
- public bool AutoUpdate = true;
-
- /*
- * for development purposes only
- */
- public bool DebugRenderVisualizer = false;
-
- /*
- * For video wallpapers
- */
- public HardwareDecoder HardwareVideoDecoder = HardwareDecoder.NVDEC;
- }
-}
-
-// Entry main Lua file
-public interface IConfigurationScriptApi
-{
- string Author { get; }
- string Name { get; }
-
- void OnInitialize(CanopyUserlandScope scope);
- void OnClockTick();
- void OnFrame(OpenGLRenderer renderer);
-
- void PushWallpaper(Wallpaper wallpaper, Transition transition);
-
- record Transition(long Time, Easing Easing, Action? Callback = null)
- {
- public static readonly Transition DEFAULT = new Transition(5000, Easing.In);
- }
-}
diff --git a/Canopy.Core/Configuration/GeneralConfig.cs b/Canopy.Core/Configuration/GeneralConfig.cs
new file mode 100644
index 0000000..b7e3305
--- /dev/null
+++ b/Canopy.Core/Configuration/GeneralConfig.cs
@@ -0,0 +1,23 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using Codon.Codec;
+
+namespace Canopy.Configuration;
+
+public record GeneralConfig(
+ bool AutoStartOnStartup,
+ int RefreshPeriod,
+ Wallpaper.FitMode FitMode,
+ bool UseSolarNoonAsMidday
+)
+{
+ public static readonly GeneralConfig DEFAULT = new GeneralConfig(true, 60_000, Wallpaper.FitMode.Fill, true);
+
+ public static readonly StructCodec CODEC = StructCodec.For()
+ .Field("AutoStartOnStartup", Codecs.BOOLEAN, g => g.AutoStartOnStartup)
+ .Field("RefreshPeriod", Codecs.INT, g => g.RefreshPeriod)
+ .Field("FitMode", Codecs.Enum(), g => g.FitMode)
+ .Field("UseSolarNoonAsMidday", Codecs.BOOLEAN, g => g.UseSolarNoonAsMidday)
+ .Build((autoStart, refresh, fitMode, noon) => new GeneralConfig(autoStart, refresh, fitMode, noon));
+}
diff --git a/Canopy.Core/Rendering/INativeContext.cs b/Canopy.Core/Configuration/Holiday.cs
similarity index 61%
rename from Canopy.Core/Rendering/INativeContext.cs
rename to Canopy.Core/Configuration/Holiday.cs
index de7d671..e73bb04 100644
--- a/Canopy.Core/Rendering/INativeContext.cs
+++ b/Canopy.Core/Configuration/Holiday.cs
@@ -1,9 +1,13 @@
// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-namespace Canopy.Rendering;
+namespace Canopy.Configuration;
-public interface INativeContext
+public enum Holiday
{
- IntPtr GetProcAddress(string procName);
+ Christmas,
+ NewYear,
+ Easter,
+ Halloween,
+
}
diff --git a/Canopy.Core/Graphics/TextureFillMode.cs b/Canopy.Core/Configuration/SeasonType.cs
similarity index 63%
rename from Canopy.Core/Graphics/TextureFillMode.cs
rename to Canopy.Core/Configuration/SeasonType.cs
index 6175526..850be2e 100644
--- a/Canopy.Core/Graphics/TextureFillMode.cs
+++ b/Canopy.Core/Configuration/SeasonType.cs
@@ -1,11 +1,12 @@
// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-namespace Canopy.Graphics;
+namespace Canopy.Configuration;
-public enum TextureFillMode
+public enum SeasonType
{
- Stretch,
- Fit,
- Fill,
+ Spring,
+ Summer,
+ Autumn,
+ Winter
}
diff --git a/Canopy.Core/Configuration/SystemConfig.cs b/Canopy.Core/Configuration/SystemConfig.cs
new file mode 100644
index 0000000..95631ae
--- /dev/null
+++ b/Canopy.Core/Configuration/SystemConfig.cs
@@ -0,0 +1,31 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using Codon.Codec;
+
+namespace Canopy.Configuration;
+
+public record SystemConfig(
+ bool UseLegacyWindowsApi,
+ bool ApplyToAllMacOsSpaces,
+ bool UpdateLockScreen,
+ bool DontUpdateWhenBatteryLow,
+ bool ChangeSystemThemesDependingOnTime
+)
+{
+ public static readonly SystemConfig DEFAULT = new SystemConfig(
+ UseLegacyWindowsApi: false,
+ ApplyToAllMacOsSpaces: true,
+ UpdateLockScreen: false,
+ DontUpdateWhenBatteryLow: true,
+ ChangeSystemThemesDependingOnTime: false
+ );
+
+ public static readonly StructCodec CODEC = StructCodec.For()
+ .Field("UseLegacyWindowsApi", Codecs.BOOLEAN, s => s.UseLegacyWindowsApi)
+ .Field("ApplyToAllMacOsSpaces", Codecs.BOOLEAN, s => s.ApplyToAllMacOsSpaces)
+ .Field("UpdateLockScreen", Codecs.BOOLEAN, s => s.UpdateLockScreen)
+ .Field("DontUpdateWhenBatteryLow", Codecs.BOOLEAN, s => s.DontUpdateWhenBatteryLow)
+ .Field("ChangeSystemThemesDependingOnTime", Codecs.BOOLEAN, s => s.ChangeSystemThemesDependingOnTime)
+ .Build((b, b1, arg3, arg4, arg5) => new SystemConfig(b, b1, arg3, arg4, arg5));
+}
diff --git a/Canopy.Core/Rendering/OpenGLException.cs b/Canopy.Core/Configuration/TimeOfDay.cs
similarity index 56%
rename from Canopy.Core/Rendering/OpenGLException.cs
rename to Canopy.Core/Configuration/TimeOfDay.cs
index ad19208..30b61bd 100644
--- a/Canopy.Core/Rendering/OpenGLException.cs
+++ b/Canopy.Core/Configuration/TimeOfDay.cs
@@ -1,9 +1,14 @@
// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-namespace Canopy.Rendering;
+namespace Canopy.Configuration;
-public class OpenGLException(string message) : Exception
+public enum TimeOfDay
{
- public override string Message => message;
+ Sunrise,
+ Morning,
+ Afternoon,
+ Sunset,
+ Night,
+ DeepNight,
}
diff --git a/Canopy.Core/Configuration/UpdaterConfig.cs b/Canopy.Core/Configuration/UpdaterConfig.cs
new file mode 100644
index 0000000..7ef92cf
--- /dev/null
+++ b/Canopy.Core/Configuration/UpdaterConfig.cs
@@ -0,0 +1,25 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using Codon.Codec;
+
+namespace Canopy.Configuration;
+
+public record UpdaterConfig(UpdaterConfig.Release ReleaseStream, bool AutoUpdate, string Source)
+{
+
+ public static readonly UpdaterConfig DEFAULT = new UpdaterConfig(Release.Release, true, "https://github.com/SynesthesiaDev/Canopy/releases");
+
+ public static readonly StructCodec CODEC = StructCodec.For()
+ .Field("ReleaseStream", Codecs.Enum(), u => u.ReleaseStream)
+ .Field("AutoUpdate", Codecs.BOOLEAN, u => u.AutoUpdate)
+ .Field("Source", Codecs.STRING, u => u.Source)
+ .Build((release, b, arg3) => new UpdaterConfig(release, b, arg3));
+
+ public enum Release
+ {
+ Release,
+ PreRelease
+ }
+
+}
diff --git a/Canopy.Core/Configuration/Wallpaper.cs b/Canopy.Core/Configuration/Wallpaper.cs
new file mode 100644
index 0000000..f24f6fd
--- /dev/null
+++ b/Canopy.Core/Configuration/Wallpaper.cs
@@ -0,0 +1,206 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using Codon.Codec;
+using Codon.Optionals;
+using Synesthesia.Utils.Extensions;
+
+namespace Canopy.Configuration;
+
+public record Wallpaper(
+ string Path,
+ List Time,
+ List Weather,
+ List Season,
+ Optional Holiday,
+ string? Accent = null
+)
+{
+
+ public static readonly List DEFAULT_WALLPAPERS =
+ [
+ new Wallpaper
+ (
+ Path: "./default/cloudy-quasar.png",
+ Time: [TimeOfDay.Night, TimeOfDay.DeepNight],
+ Weather: [WeatherType.Cloudy],
+ Season: [],
+ Holiday: Optional.Empty(),
+ Accent: "#c5d9d7"
+ ),
+
+ new Wallpaper
+ (
+ Path: "./default/beach.jpg",
+ Time: [TimeOfDay.Afternoon],
+ Weather: [WeatherType.Clear],
+ Season: [SeasonType.Summer],
+ Holiday: Optional.Empty(),
+ Accent: "#207ad9"
+ ),
+
+ new Wallpaper
+ (
+ Path: "./default/halloween.jpg",
+ Time: [],
+ Weather: [],
+ Season: [],
+ Holiday: Optional.Of(Configuration.Holiday.Halloween),
+ Accent: "#f56b3d"
+ ),
+
+ new Wallpaper
+ (
+ Path: "./default/eclipse.jpg",
+ Time: [TimeOfDay.Sunset],
+ Weather: [WeatherType.Cloudy, WeatherType.Clear],
+ Season: [],
+ Holiday: Optional.Empty(),
+ Accent: "#f4545e"
+ ),
+
+ new Wallpaper
+ (
+ Path: "./default/flower-field.jpg",
+ Time: [TimeOfDay.Morning, TimeOfDay.Afternoon],
+ Weather: [WeatherType.Clear],
+ Season: [SeasonType.Spring],
+ Holiday: Optional.Empty(),
+ Accent: "#9ca15e"
+ ),
+
+ new Wallpaper
+ (
+ Path: "./default/i-touch-this.jpg",
+ Time: [TimeOfDay.Morning],
+ Weather: [WeatherType.Clear],
+ Season: [],
+ Holiday: Optional.Empty(),
+ Accent: "#89b238"
+ ),
+ new Wallpaper
+ (
+ Path: "./default/pink-clouds.jpg",
+ Time: [TimeOfDay.Sunset, TimeOfDay.Sunrise],
+ Weather: [WeatherType.Clear, WeatherType.Cloudy],
+ Season: [],
+ Holiday: Optional.Empty(),
+ Accent: "#e69c94"
+ ),
+ new Wallpaper
+ (
+ Path: "./default/snowflakes.jpg",
+ Time: [TimeOfDay.Night, TimeOfDay.DeepNight],
+ Weather: [WeatherType.Rainy, WeatherType.Clear],
+ Season: [SeasonType.Winter],
+ Holiday: Optional.Empty(),
+ Accent: "#c2e6ff"
+ ),
+ new Wallpaper
+ (
+ Path: "./default/swirly-painting.jpg",
+ Time: [TimeOfDay.Sunset, TimeOfDay.Sunrise],
+ Weather: [WeatherType.Clear, WeatherType.Cloudy],
+ Season: [],
+ Holiday: Optional.Empty(),
+ Accent: "#df7488"
+ ),
+ new Wallpaper
+ (
+ Path: "./default/flowering-rain.png",
+ Time: [TimeOfDay.Morning, TimeOfDay.Afternoon],
+ Weather: [WeatherType.Rainy, WeatherType.Stormy],
+ Season: [],
+ Holiday: Optional.Empty(),
+ Accent: "#598fb1"
+ ),
+
+ // Fallback Wallpapers per each time
+
+ new Wallpaper
+ (
+ Path: "./default/fallback/Sunrise.jpg",
+ Time: [TimeOfDay.Sunrise],
+ Weather: [],
+ Season: [],
+ Holiday: Optional.Empty(),
+ Accent: "#1a4a4a"
+ ),
+ new Wallpaper
+ (
+ Path: "./default/fallback/Morning.jpg",
+ Time: [TimeOfDay.Morning],
+ Weather: [],
+ Season: [],
+ Holiday: Optional.Empty(),
+ Accent: "#1b4a40"
+ ),
+ new Wallpaper
+ (
+ Path: "./default/fallback/Afternoon.jpg",
+ Time: [TimeOfDay.Afternoon],
+ Weather: [],
+ Season: [],
+ Holiday: Optional.Empty(),
+ Accent: "#3d76a1"
+ ),
+ new Wallpaper
+ (
+ Path: "./default/fallback/Sunset.jpg",
+ Time: [TimeOfDay.Sunset],
+ Weather: [],
+ Season: [],
+ Holiday: Optional.Empty(),
+ Accent: "#e56f32"
+ ),
+ new Wallpaper
+ (
+ Path: "./default/fallback/Night.jpg",
+ Time: [TimeOfDay.Night],
+ Weather: [],
+ Season: [],
+ Holiday: Optional.Empty(),
+ Accent: "#314d3f"
+ ),
+ new Wallpaper
+ (
+ Path: "./default/fallback/DeepNight.jpg",
+ Time: [TimeOfDay.DeepNight],
+ Weather: [],
+ Season: [],
+ Holiday: Optional.Empty(),
+ Accent: "#1b2836"
+ ),
+ ];
+
+ public static readonly StructCodec CODEC = StructCodec.For()
+ .Field("Path", Codecs.STRING, w => w.Path)
+ .Field("Time", Codecs.Enum().List().Default([]), w => w.Time)
+ .Field("Weather", Codecs.Enum().List().Default([]), w => w.Weather)
+ .Field("Season", Codecs.Enum().List().Default([]), w => w.Season)
+ .Field("Holiday", Codecs.Enum().Optional(), w => w.Holiday)
+ .Field("Accent", Codecs.STRING.Optional(), w => w.Accent.ToOptional())
+ .Build((s, days, arg3, arg4, arg5, acc) => new Wallpaper(s, days, arg3, arg4, arg5, acc.Value));
+
+ public enum FitMode
+ {
+ Fill,
+ Fit,
+ Stretch,
+ Tile,
+ Center,
+ Span
+ }
+
+ public override string ToString() => $"Wallpaper(Path={Path}, Time={Time.ToListString()}, Weather={Weather.ToListString()}, Season={Season.ToListString()}, Holiday={Holiday}, Accent={Accent})";
+}
+
+
+// public record Wallpaper(
+// string Path,
+// List Time,
+// List Weather,
+// List Season,
+// Holiday? Holiday = null,
+// string? Accent = null
+// )
diff --git a/Canopy.Core/Configuration/WeatherConfig.cs b/Canopy.Core/Configuration/WeatherConfig.cs
new file mode 100644
index 0000000..00f0c11
--- /dev/null
+++ b/Canopy.Core/Configuration/WeatherConfig.cs
@@ -0,0 +1,37 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using Codon.Codec;
+
+namespace Canopy.Configuration;
+
+public record WeatherConfig(
+ bool UseAutoLocation,
+ int RefreshInterval,
+ WeatherConfig.OfflineMode OfflineFallback,
+ WeatherConfig.ManualCoordinates? Coordinates
+)
+{
+ public static readonly WeatherConfig DEFAULT = new WeatherConfig(true, 60_000, OfflineMode.UseLastKnownState, new ManualCoordinates(Latitude: 50.087555, Longitude: 14.421194));
+
+ public static readonly StructCodec CODEC = StructCodec.For()
+ .Field("UseAutoLocation", Codecs.BOOLEAN, w => w.UseAutoLocation)
+ .Field("RefreshInterval", Codecs.INT, w => w.RefreshInterval)
+ .Field("OfflineFallback", Codecs.Enum(), w => w.OfflineFallback)
+ .Field("Coordinates", ManualCoordinates.CODEC.Optional(), w => w.Coordinates.ToOptional())
+ .Build((b, i, arg3, arg4) => new WeatherConfig(b, i, arg3, arg4.Value));
+
+ public enum OfflineMode
+ {
+ UseLastKnownState,
+ IgnoreWeather
+ }
+
+ public record ManualCoordinates(double Longitude, double Latitude)
+ {
+ public static readonly StructCodec CODEC = StructCodec.For()
+ .Field("Longitude", Codecs.DOUBLE, m => m.Longitude)
+ .Field("Latitude", Codecs.DOUBLE, m => m.Latitude)
+ .Build((lon, lat) => new ManualCoordinates(lon, lat));
+ }
+}
diff --git a/Canopy.Core/Utils/IEasingFunction.cs b/Canopy.Core/Configuration/WeatherType.cs
similarity index 63%
rename from Canopy.Core/Utils/IEasingFunction.cs
rename to Canopy.Core/Configuration/WeatherType.cs
index f9bb0b5..88b96d2 100644
--- a/Canopy.Core/Utils/IEasingFunction.cs
+++ b/Canopy.Core/Configuration/WeatherType.cs
@@ -1,10 +1,12 @@
// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-namespace Canopy.Utils;
+namespace Canopy.Configuration;
-
-public interface IEasingFunction
+public enum WeatherType
{
- double ApplyEasing(double time);
+ Clear,
+ Cloudy,
+ Rainy,
+ Stormy,
}
diff --git a/Canopy.Core/Configuration/WebsocketConfig.cs b/Canopy.Core/Configuration/WebsocketConfig.cs
new file mode 100644
index 0000000..c8e6680
--- /dev/null
+++ b/Canopy.Core/Configuration/WebsocketConfig.cs
@@ -0,0 +1,16 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using Codon.Codec;
+
+namespace Canopy.Configuration;
+
+public record WebsocketConfig(bool Enabled, string Url)
+{
+ public static readonly WebsocketConfig DEFAULT = new WebsocketConfig(false, "http://localhost:5808/");
+
+ public static readonly StructCodec CODEC = StructCodec.For()
+ .Field("Enabled", Codecs.BOOLEAN, s => s.Enabled)
+ .Field("Url", Codecs.STRING, s => s.Url)
+ .Build((b, s) => new WebsocketConfig(b, s));
+}
diff --git a/Canopy.Core/Extensions/GLExtensions.cs b/Canopy.Core/Extensions/GLExtensions.cs
deleted file mode 100644
index 25fee47..0000000
--- a/Canopy.Core/Extensions/GLExtensions.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using System.Diagnostics;
-using Serilog;
-using Silk.NET.OpenGL;
-
-namespace Canopy.Extensions;
-
-public static class GLExtensions
-{
- [Conditional("DEBUG")]
- public static void CheckError(this GL gl, string location)
- {
- var error = gl.GetError();
- if (error != GLEnum.NoError)
- {
- Log.Error("OpenGL Error at {Location}: {GLEnum}", location, error);
- }
- }
-}
diff --git a/Canopy.Core/Graphics/DrawableContainer.cs b/Canopy.Core/Graphics/DrawableContainer.cs
deleted file mode 100644
index 0ff6063..0000000
--- a/Canopy.Core/Graphics/DrawableContainer.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using Canopy.Rendering;
-
-namespace Canopy.Graphics;
-
-public class DrawableContainer : IDrawable
-{
-
-
- public void Dispose()
- {
- throw new NotImplementedException();
- }
-
- public void Draw(OpenGLRenderer gl)
- {
- throw new NotImplementedException();
- }
-}
diff --git a/Canopy.Core/Graphics/Wallpaper.cs b/Canopy.Core/Graphics/Wallpaper.cs
deleted file mode 100644
index a2859d1..0000000
--- a/Canopy.Core/Graphics/Wallpaper.cs
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using System.Drawing;
-using System.Numerics;
-using Canopy.Rendering;
-using Canopy.Rendering.Shaders;
-using Canopy.Rendering.Textures;
-using Canopy.Storage;
-using Canopy.Utils.Future;
-using Synesthesia.Utils.Extensions;
-
-namespace Canopy.Graphics;
-
-public class Wallpaper : IDrawable
-{
- // null means it uses default texture shader
- public Shader? Shader { get; private set; }
-
- // null means not ready for rendering yet, probably uploading.
- // transitions should wait until loaded and swapped
- public Texture? Texture { get; private set; }
-
- public TextureFillMode TextureFillMode { get; set; } = TextureFillMode.Fill;
-
- public string TextureResourceName { get; }
-
- public float Alpha { get; set; } = 1f;
-
- public float CornerRadius { get; set; } = 1f;
-
- private RectangleF uvCoords = new(0, 0, 1, 1);
- private Vector2 drawSize = Vector2.One;
- private Vector2 drawOffset = Vector2.Zero;
-
- public Vector2 Size { get; private set; }
-
- public AssetStorage AssetStorage { get; }
-
- public Wallpaper(string textureResourceName, AssetStorage assetStorage, string? sharedResourceName = null)
- {
- TextureResourceName = textureResourceName;
- AssetStorage = assetStorage;
-
- Tasks.RunAsync(() => assetStorage.GetResolved(textureResourceName, DataParsers.LoadTexture)).Then(tex =>
- {
- Texture = tex;
- if (Size != Vector2.Zero) updateAxis(Size);
- });
-
- if (sharedResourceName != null)
- {
- Tasks.RunAsync(() =>
- {
- var normalizedShaderName = sharedResourceName.RemoveSuffix(".vert").RemoveSuffix(".frag");
- var vert = assetStorage.GetResolved($"{normalizedShaderName}.vert", DataParsers.LoadString);
- var frag = assetStorage.GetResolved($"{normalizedShaderName}.frag", DataParsers.LoadString);
-
- return new Shader(vert, frag, true);
- }).Then(shader =>
- {
- Shader = shader;
- });
- }
- }
-
- public void Draw(OpenGLRenderer gl)
- {
- var currentSize = new Vector2(gl.BackBufferWidth, gl.BackBufferHeight);
-
- // Dont recalc every frame
- if (Size != currentSize)
- {
- Size = currentSize;
- updateAxis(currentSize);
- }
-
- var shaderReady = Shader is { IsCompiled: true };
- if (shaderReady) gl.BindShader(Shader!);
-
- gl.DrawQuad(drawOffset, drawSize, 0xFFFFFFFF, Alpha, CornerRadius, Texture, uvCoords);
-
- if (shaderReady) gl.UnbindShader();
- }
-
- public void Dispose()
- {
- Shader?.Dispose();
- Texture?.Dispose();
- }
-
- private void updateAxis(Vector2 size)
- {
- if (Texture == null || TextureFillMode == TextureFillMode.Stretch) return;
-
- var textureRatio = (float)Texture.Width / Texture.Height;
- var boxRatio = size.X / size.Y;
-
- drawSize = size;
- drawOffset = Vector2.Zero;
- uvCoords = new RectangleF(0, 0, 1, 1);
-
- switch (TextureFillMode)
- {
- case TextureFillMode.Fit:
- if (textureRatio > boxRatio)
- {
- drawSize = new Vector2(size.X, size.X / textureRatio);
- drawOffset = new Vector2(0, (size.Y - drawSize.Y) / 2f);
- }
- else
- {
- drawSize = new Vector2(size.Y * textureRatio, size.Y);
- drawOffset = new Vector2((size.X - drawSize.X) / 2f, 0);
- }
-
- break;
- case TextureFillMode.Fill:
- var scaleX = 1f;
- var scaleY = 1f;
-
- if (textureRatio > boxRatio)
- {
- scaleX = boxRatio / textureRatio;
- }
- else
- {
- scaleY = textureRatio / boxRatio;
- }
-
- uvCoords = new RectangleF((1f - scaleX) / 2f, (1f - scaleY) / 2f, scaleX, scaleY);
- break;
- }
- }
-}
diff --git a/Canopy.Core/ICanopyPlatform.cs b/Canopy.Core/ICanopyPlatform.cs
index fb03965..ed40900 100644
--- a/Canopy.Core/ICanopyPlatform.cs
+++ b/Canopy.Core/ICanopyPlatform.cs
@@ -1,18 +1,25 @@
-using Canopy.Graphics;
-using Synesthesia.Utils;
+using Synesthesia.Utils;
namespace Canopy;
public interface ICanopyPlatform
{
RuntimeInfo.Platform Platform { get; }
+ void SetDesktop(string path);
+ void SetTheme(Theme theme);
+ void InitializeTray(Canopy canopy);
+ void ShowNotification(string title, string message, NotificationLevel level = NotificationLevel.Info);
- void Initialize();
+ enum Theme
+ {
+ Light,
+ Dark
+ }
- void InjectIntoDesktop(IntPtr chibiWindowHandle);
-
- void HideWindow();
- void ShowWindow();
-
- void PushWallpaper(Wallpaper wallpaper);
+ enum NotificationLevel
+ {
+ Info,
+ Warning,
+ Error
+ }
}
diff --git a/Canopy.Core/IWindowSurface.cs b/Canopy.Core/IWindowSurface.cs
deleted file mode 100644
index 891ba31..0000000
--- a/Canopy.Core/IWindowSurface.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using System.Numerics;
-using Canopy.Rendering;
-
-namespace Canopy;
-
-public interface IWindowSurface : IDisposable
-{
- IntPtr Handle { get; }
-
- INativeContext NativeContext { get; }
-
- Vector2 GetScreenSize();
- void SwapBuffers();
-
- void InitializeGraphicsContext();
-}
diff --git a/Canopy.Core/Nothing.cs b/Canopy.Core/Nothing.cs
deleted file mode 100644
index 161fabd..0000000
--- a/Canopy.Core/Nothing.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Canopy;
-
-public sealed class Nothing
-{
- public static readonly Nothing INSTANCE = new();
-}
\ No newline at end of file
diff --git a/Canopy.Core/Providers/GeopositionProvider.cs b/Canopy.Core/Providers/GeopositionProvider.cs
new file mode 100644
index 0000000..4b02e14
--- /dev/null
+++ b/Canopy.Core/Providers/GeopositionProvider.cs
@@ -0,0 +1,50 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using Codon.Codec;
+using Codon.Codec.Json;
+
+namespace Canopy.Providers;
+
+public class GeopositionProvider : IProvider
+{
+ private const string geo_location_endpoint = "http://ip-api.com/json/?fields=lat,lon";
+
+ private static readonly HttpClient http_client = new();
+ private GeoPosition? cached;
+
+ public void InvalidateCache()
+ {
+ cached = null;
+ }
+
+ public GeoPosition Get()
+ {
+ if (cached != null) return cached;
+
+ var weatherConfig = Canopy.CurrentConfig.Weather;
+ if (weatherConfig.UseAutoLocation)
+ {
+ if (weatherConfig.Coordinates == null)
+ throw new InvalidOperationException("Cannot have 'UseAutoLocation' disabled and have no coordinates specified");
+
+ cached = new GeoPosition(weatherConfig.Coordinates.Latitude, weatherConfig.Coordinates.Longitude);
+ return cached;
+ }
+
+ var request = new HttpRequestMessage(HttpMethod.Get, geo_location_endpoint);
+ var res = http_client.Send(request);
+ var body = res.Content.ReadAsStringAsync().GetAwaiter().GetResult();
+ var geoPosition = GeoPosition.CODEC.Decode(JsonTranscoder.INSTANCE, body.ToJson());
+ cached = geoPosition;
+ return geoPosition;
+ }
+
+ public record GeoPosition(double Lat, double Lon)
+ {
+ public static readonly StructCodec CODEC = StructCodec.For()
+ .Field("lat", Codecs.DOUBLE, r => r.Lat)
+ .Field("Lon", Codecs.DOUBLE, r => r.Lon)
+ .Build((lat, lon) => new GeoPosition(lat, lon));
+ }
+}
diff --git a/Canopy.Core/Providers/HolidayProvider.cs b/Canopy.Core/Providers/HolidayProvider.cs
new file mode 100644
index 0000000..df6e3ce
--- /dev/null
+++ b/Canopy.Core/Providers/HolidayProvider.cs
@@ -0,0 +1,91 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using Canopy.Configuration;
+using Serilog;
+
+namespace Canopy.Providers;
+
+public class HolidayProvider : IProvider
+{
+ public Holiday? Get()
+ {
+ var now = DateTimeOffset.Now;
+ Holiday? activeHoliday = null;
+ foreach (var holiday in Enum.GetValues())
+ {
+ if (IsActive(holiday, now.DateTime))
+ {
+ activeHoliday = holiday;
+ break;
+ }
+ }
+ Log.Verbose(" ");
+ Log.Verbose("Holiday: {h}", activeHoliday);
+ Log.Verbose(" ");
+ return activeHoliday;
+ }
+
+ public static bool IsActive(Holiday holiday, DateTime targetDate)
+ {
+ var (start, end) = GetWindow(holiday, targetDate.Year);
+ return targetDate >= start && targetDate <= end;
+ }
+
+ public static (DateTime Start, DateTime End) GetWindow(Holiday holiday, int year)
+ {
+ return holiday switch
+ {
+ //All of December to 27th
+ Holiday.Christmas => (
+ new DateTime(year, 12, 1),
+ new DateTime(year, 12, 27, 23, 59, 59)
+ ),
+
+ // New Year: Dec 30 to Jan 3
+ Holiday.NewYear => (new DateTime(year - 1, 12, 28), new DateTime(year, 1, 7, 23, 59, 59)),
+
+ // Halloween: Oct 15 to Nov 3
+ Holiday.Halloween => (new DateTime(year, 10, 15), new DateTime(year, 11, 3, 23, 59, 59)),
+
+ Holiday.Easter => getEasterWindow(year, daysBefore: 7, daysAfter: 7),
+
+ _ => throw new ArgumentOutOfRangeException(nameof(holiday), holiday, null)
+ };
+ }
+
+ private static (DateTime Start, DateTime End) getEasterWindow(int year, int daysBefore, int daysAfter)
+ {
+ DateTime easterSunday = getEasterSunday(year);
+ DateTime start = easterSunday.AddDays(-daysBefore);
+ DateTime end = easterSunday.AddDays(daysAfter).Add(new TimeSpan(23, 59, 59));
+ return (start, end);
+ }
+
+ private static DateTime getEasterSunday(int year)
+ {
+ int metonicCycleIndex = year % 19;
+
+ int century = year / 100;
+ int yearInCentury = year % 100;
+
+ int leapCenturies = century / 4;
+ int nonLeapCenturies = century % 4;
+
+ int lunarCorrection = (century + 8) / 25;
+ int solarCorrection = (century - lunarCorrection + 1) / 3;
+
+ int epact = (19 * metonicCycleIndex + century - leapCenturies - solarCorrection + 15) % 30;
+
+ int leapYearsInCentury = yearInCentury / 4;
+ int nonLeapYearsInCentury = yearInCentury % 4;
+ int dayOfWeekOffset = (32 + 2 * nonLeapCenturies + 2 * leapYearsInCentury - epact - nonLeapYearsInCentury) % 7;
+
+ int cycleCorrection = (metonicCycleIndex + 11 * epact + 22 * dayOfWeekOffset) / 451;
+
+ int monthIndex = (epact + dayOfWeekOffset - 7 * cycleCorrection + 114) / 31;
+ int dayOfMonth = ((epact + dayOfWeekOffset - 7 * cycleCorrection + 114) % 31) + 1;
+
+ return new DateTime(year, monthIndex, dayOfMonth);
+ }
+}
diff --git a/Canopy.Core/Utils/ReleaseStream.cs b/Canopy.Core/Providers/IProvider.cs
similarity index 69%
rename from Canopy.Core/Utils/ReleaseStream.cs
rename to Canopy.Core/Providers/IProvider.cs
index 3ffd08f..80a9992 100644
--- a/Canopy.Core/Utils/ReleaseStream.cs
+++ b/Canopy.Core/Providers/IProvider.cs
@@ -1,10 +1,9 @@
// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-namespace Canopy.Utils;
+namespace Canopy.Providers;
-public enum ReleaseStream
+public interface IProvider
{
- Release,
- Development
+ T Get();
}
diff --git a/Canopy.Core/Providers/SeasonProvider.cs b/Canopy.Core/Providers/SeasonProvider.cs
new file mode 100644
index 0000000..b58a613
--- /dev/null
+++ b/Canopy.Core/Providers/SeasonProvider.cs
@@ -0,0 +1,24 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using Canopy.Configuration;
+
+namespace Canopy.Providers;
+
+public class SeasonProvider : IProvider
+{
+ public SeasonType Get()
+ {
+ var now = DateTimeOffset.Now;
+ float value = now.Month + (now.Day / 100f);
+
+ if (value is < 3.21f or >= 12.22f)
+ return SeasonType.Winter;
+ if (value < 6.21f)
+ return SeasonType.Spring;
+ if (value < 9.23f)
+ return SeasonType.Summer;
+
+ return SeasonType.Autumn;
+ }
+}
diff --git a/Canopy.Core/Providers/TimeOfDayProvider.cs b/Canopy.Core/Providers/TimeOfDayProvider.cs
new file mode 100644
index 0000000..ef8483f
--- /dev/null
+++ b/Canopy.Core/Providers/TimeOfDayProvider.cs
@@ -0,0 +1,61 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using Canopy.Configuration;
+using Innovative.Geometry;
+using Innovative.SolarCalculator;
+using Serilog;
+
+namespace Canopy.Providers;
+
+public class TimeOfDayProvider : IProvider
+{
+ private const int sunrise_offset_minutes = 60;
+ private const int sunset_offset_minutes = -100;
+ private const int event_duration_minutes = 60;
+
+ public TimeOfDay Get()
+ {
+ var now = DateTimeOffset.Now;
+ var geo = Canopy.GEOPOSITION_PROVIDER.Get();
+ var solarTimes = new SolarTimes(now, new Angle(geo.Lat), new Angle(geo.Lon));
+
+ var baseSunrise = solarTimes.Sunrise;
+ var baseSunset = solarTimes.Sunset;
+
+ var sunriseStart = baseSunrise.AddMinutes(sunrise_offset_minutes);
+ var sunsetStart = baseSunset.AddMinutes(sunset_offset_minutes);
+
+ Log.Verbose(" ");
+ Log.Verbose("Solar Noon: {sun}", solarTimes.SolarNoon);
+ Log.Verbose("Sunrise: {sun}", sunriseStart);
+ Log.Verbose("Sunset: {sun}", sunsetStart);
+
+ var eventDuration = TimeSpan.FromMinutes(event_duration_minutes);
+ var sunriseEnd = sunriseStart + eventDuration;
+ var sunsetEnd = sunsetStart + eventDuration;
+
+ if (now >= sunriseStart && now < sunriseEnd)
+ return TimeOfDay.Sunrise;
+
+ if (now >= sunsetStart && now < sunsetEnd)
+ return TimeOfDay.Sunset;
+
+ if (now >= sunriseEnd && now < sunsetStart)
+ {
+ DateTimeOffset midday;
+
+ if (Canopy.CurrentConfig.General.UseSolarNoonAsMidday)
+ midday = baseSunrise + (baseSunset - baseSunrise) / 2;
+ else
+ midday = DateTime.Today.AddHours(12);
+
+ return now < midday ? TimeOfDay.Morning : TimeOfDay.Afternoon;
+ }
+
+ if ((now >= sunsetEnd && now.Hour < 22) || (now.Hour >= 4 && now < sunriseStart))
+ return TimeOfDay.Night;
+
+ return TimeOfDay.DeepNight;
+ }
+}
diff --git a/Canopy.Core/Providers/WeatherProvider.cs b/Canopy.Core/Providers/WeatherProvider.cs
new file mode 100644
index 0000000..0c76a03
--- /dev/null
+++ b/Canopy.Core/Providers/WeatherProvider.cs
@@ -0,0 +1,92 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using Canopy.Configuration;
+using OpenMeteoApi;
+using Serilog;
+
+namespace Canopy.Providers;
+
+public class WeatherProvider : IProvider
+{
+ private static readonly OpenMeteoClient open_meteo_client = new OpenMeteoClient();
+
+ public WeatherType Get()
+ {
+ var geo = Canopy.GEOPOSITION_PROVIDER.Get();
+ var weather = open_meteo_client.GetCurrentWeather(geo.Lat, geo.Lon).GetAwaiter().GetResult();
+
+ var condition = ToWeatherCondition(weather.WeatherCode!.Value);
+
+ var weatherType = condition switch
+ {
+ WeatherCondition.ClearSky or
+ WeatherCondition.MainlyClear or
+ WeatherCondition.Unknown => WeatherType.Clear,
+
+ WeatherCondition.PartlyCloudy or
+ WeatherCondition.Overcast or
+ WeatherCondition.Fog => WeatherType.Cloudy,
+
+ WeatherCondition.DrizzleLight or
+ WeatherCondition.DrizzleModerate or
+ WeatherCondition.DrizzleDense or
+ WeatherCondition.RainSlight or
+ WeatherCondition.RainModerate or
+ WeatherCondition.RainHeavy or
+ WeatherCondition.SnowSlight or
+ WeatherCondition.SnowModerate or
+ WeatherCondition.SnowHeavy => WeatherType.Rainy,
+
+ WeatherCondition.Thunderstorm => WeatherType.Stormy,
+
+ _ => throw new ArgumentOutOfRangeException()
+ };
+
+ Log.Verbose(" ");
+ Log.Verbose("Weather: {w}", weatherType);
+ Log.Verbose("Underlying: {w}", condition);
+ return weatherType;
+ }
+
+ public enum WeatherCondition
+ {
+ ClearSky,
+ MainlyClear,
+ PartlyCloudy,
+ Overcast,
+ Fog,
+ DrizzleLight,
+ DrizzleModerate,
+ DrizzleDense,
+ RainSlight,
+ RainModerate,
+ RainHeavy,
+ SnowSlight,
+ SnowModerate,
+ SnowHeavy,
+ Thunderstorm,
+ Unknown
+ }
+
+ public static WeatherCondition ToWeatherCondition(int code) =>
+ code switch
+ {
+ 0 => WeatherCondition.ClearSky,
+ 1 => WeatherCondition.MainlyClear,
+ 2 => WeatherCondition.PartlyCloudy,
+ 3 => WeatherCondition.Overcast,
+ 45 or 48 => WeatherCondition.Fog,
+ 51 => WeatherCondition.DrizzleLight,
+ 53 => WeatherCondition.DrizzleModerate,
+ 55 => WeatherCondition.DrizzleDense,
+ 61 => WeatherCondition.RainSlight,
+ 63 => WeatherCondition.RainModerate,
+ 65 => WeatherCondition.RainHeavy,
+ 71 => WeatherCondition.SnowSlight,
+ 73 => WeatherCondition.SnowModerate,
+ 75 => WeatherCondition.SnowHeavy,
+ 95 or 96 or 99 => WeatherCondition.Thunderstorm,
+ _ => WeatherCondition.Unknown
+ };
+}
diff --git a/Canopy.Core/Rendering/OpenGLRenderer.cs b/Canopy.Core/Rendering/OpenGLRenderer.cs
deleted file mode 100644
index 4d43004..0000000
--- a/Canopy.Core/Rendering/OpenGLRenderer.cs
+++ /dev/null
@@ -1,289 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using System.Collections.Concurrent;
-using System.Drawing;
-using System.Numerics;
-using System.Runtime.CompilerServices;
-using Canopy.Rendering.Shaders;
-using Serilog;
-using Silk.NET.OpenGL;
-using Synesthesia.Utils.Profiler;
-using Shader = Canopy.Rendering.Shaders.Shader;
-using Texture = Canopy.Rendering.Textures.Texture;
-
-namespace Canopy.Rendering;
-
-public class OpenGLRenderer : IDisposable
-{
- // Cache so we don't query with string every frame. That's expensive on gc allocations!!
- private int textureShaderLocation;
-
- private uint vao, vbo, ebo;
- private int projectionUniformLocation;
- private int colorUniformLocation;
- private int alphaUniformLocation;
- private int useTextureUniformLocation;
-
- private bool openGlInitialized;
-
- public Shader DefaultShader { get; private set; } = null!;
-
- public required IWindowSurface Surface { get; init; }
-
- public GL OpenGL
- {
- get
- {
- EnsureInitialized();
- return field;
- }
-
- private set;
- } = null!;
-
- public int BackBufferWidth { get; private set; }
- public int BackBufferHeight { get; private set; }
- public Texture? CurrentTexture { get; private set; }
- public Shader? CurrentShader { get; private set; }
-
- public static readonly ConcurrentQueue TEXTURE_UPLOAD_QUEUE = new ConcurrentQueue();
- public static readonly ConcurrentQueue SHADER_COMPILE_QUEUE = new ConcurrentQueue();
-
- public void Initialize()
- {
- if (openGlInitialized) throw new InvalidOperationException("OpenGL is already initialized");
- Log.Verbose(" ");
- Log.Verbose("Initializing OpenGL Renderer..");
-
- var gl = GL.GetApi(name =>
- {
- var ptr = Surface.NativeContext.GetProcAddress(name);
- return ptr;
- });
-
- OpenGL = gl ?? throw new InvalidOperationException("Silk.NET could not bind to OpenGL");
-
- BackBufferWidth = (int)Surface.GetScreenSize().X;
- BackBufferHeight = (int)Surface.GetScreenSize().Y;
-
- openGlInitialized = true;
- Resize(BackBufferWidth, BackBufferHeight);
-
- initQuadGeometry();
- compileDefaultShaders();
- updateProjection();
-
- var version = OpenGL.GetStringS(GLEnum.Version);
- var shadingLanguageVersion = OpenGL.GetStringS(GLEnum.ShadingLanguageVersion);
- var vendor = OpenGL.GetStringS(GLEnum.Vendor);
- var renderer = OpenGL.GetStringS(GLEnum.Renderer);
-
- Console.WriteLine(" ");
- Log.Debug("OpenGL Initialized");
- Log.Debug($"- Version: {version}");
- Log.Debug($"- Vendor: {vendor}");
- Log.Debug($"- Renderer {renderer}");
- Log.Debug($"- GLSL: {shadingLanguageVersion}");
- Log.Debug(" ");
- }
-
- private void initQuadGeometry()
- {
- unsafe
- {
- uint[] indices = [0u, 1u, 2u, 0u, 2u, 3u];
-
- vao = OpenGL.GenVertexArray();
- vbo = OpenGL.GenBuffer();
- ebo = OpenGL.GenBuffer();
-
- OpenGL.BindVertexArray(vao);
-
- OpenGL.BindBuffer(BufferTargetARB.ArrayBuffer, vbo);
- OpenGL.BufferData(BufferTargetARB.ArrayBuffer, 64, null, BufferUsageARB.DynamicDraw);
-
- OpenGL.BindBuffer(BufferTargetARB.ElementArrayBuffer, ebo);
- OpenGL.BufferData(BufferTargetARB.ElementArrayBuffer, indices, BufferUsageARB.StaticDraw);
-
- const uint stride = 4 * sizeof(float);
-
- OpenGL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, stride, 0);
- OpenGL.EnableVertexAttribArray(0);
-
- OpenGL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, stride, 2 * sizeof(float));
- OpenGL.EnableVertexAttribArray(1);
-
- OpenGL.BindVertexArray(0);
- }
- }
-
- // Still need position and size because if you have multiple monitors, the window will span across ALL of them, so
- // you need to draw multiple wallpapers at different positions that match the monitors
- public void DrawQuad(Vector2 position, Vector2 size, uint packedColor, float alpha, float cornerRadius, Texture? texture, RectangleF? textureCoord)
- {
- EnsureInitialized();
- if (texture is { IsUploaded: false }) return;
- if (texture != CurrentTexture) BindTexture(texture);
-
- var tex = textureCoord ?? new RectangleF(0, 0, 1, 1);
- float x = position.X, y = position.Y, w = size.X, h = size.Y;
-
- // Interleaved: x, y, u, v per vertex
- ReadOnlySpan vertices =
- [
- x, y, tex.Left, tex.Top,
- x, y + h, tex.Left, tex.Bottom,
- x + w, y + h, tex.Right, tex.Bottom,
- x + w, y, tex.Right, tex.Top,
- ];
-
- OpenGL.BindVertexArray(vao);
- OpenGL.BindBuffer(BufferTargetARB.ArrayBuffer, vbo);
- OpenGL.BufferSubData(BufferTargetARB.ArrayBuffer, 0, vertices);
-
- CurrentShader?.SetVector4(colorUniformLocation, new Vector4(
- (packedColor & 0xFF) / 255f,
- (packedColor >> 8 & 0xFF) / 255f,
- (packedColor >> 16 & 0xFF) / 255f,
- (packedColor >> 24 & 0xFF) / 255f));
- CurrentShader?.SetFloat(alphaUniformLocation, alpha);
- CurrentShader?.SetBool(useTextureUniformLocation, texture != null);
-
- unsafe
- {
- OpenGL.DrawElements(PrimitiveType.Triangles, 6, DrawElementsType.UnsignedInt, null);
- }
-
- OpenGL.BindVertexArray(0);
- }
-
- public void BindTexture(Texture? texture)
- {
- if (CurrentTexture == texture) return;
-
- CurrentTexture = texture;
- if (texture != null && texture.Bind(OpenGL))
- {
- CurrentShader?.SetInt(textureShaderLocation, 0);
- }
- else
- {
- OpenGL.BindTexture(TextureTarget.Texture2D, 0);
- }
- }
-
- public void Resize(int width, int height)
- {
- BackBufferWidth = width;
- BackBufferHeight = height;
-
- EnsureInitialized();
- pushViewport();
- }
-
- public void BindShader(Shader shader)
- {
- // ThreadSafety.AssertRunningOnRenderThread();
- if (CurrentShader == shader) return;
-
- CurrentShader = shader;
- shader.Use();
- cacheShaderUniformLocations();
- }
-
- public void UnbindShader()
- {
- BindShader(DefaultShader);
- }
-
- public void BeginDrawing()
- {
- EnsureInitialized();
-
-#if DEBUG
- OpenGL.ClearColor(1f, 0f, 1f, 1f);
-#else
- OpenGL.ClearColor(0f, 0f, 0f, 1f);
-#endif
-
- OpenGL.Clear(ClearBufferMask.ColorBufferBit);
-
- while (!TEXTURE_UPLOAD_QUEUE.IsEmpty)
- {
- TEXTURE_UPLOAD_QUEUE.TryDequeue(out var texture);
- texture?.Upload(OpenGL);
- }
-
- while (!SHADER_COMPILE_QUEUE.IsEmpty)
- {
- SHADER_COMPILE_QUEUE.TryDequeue(out var shader);
- shader?.Compile(OpenGL);
- }
-
- pushViewport();
- }
-
- public void EndDrawing()
- {
- EnsureInitialized();
-
- Surface.SwapBuffers();
- BindTexture(null);
- }
-
- private void pushViewport()
- {
- OpenGL.Viewport(0, 0, (uint)BackBufferWidth, (uint)BackBufferHeight);
- if(CurrentShader != null) updateProjection();
- }
-
- private void updateProjection()
- {
- var proj = Matrix4x4.CreateOrthographicOffCenter(
- left: 0,
- right: BackBufferWidth,
- bottom: BackBufferHeight,
- top: 0,
- zNearPlane: -1,
- zFarPlane: 1
- );
-
- CurrentShader?.SetMatrix4(projectionUniformLocation, proj);
- }
-
- private void compileDefaultShaders()
- {
- var profiler = Timings.RentAndPush();
- DefaultShader = new Shader(ShaderSources.DEFAULT_VERTEX, ShaderSources.DEFAULT_FRAGMENT, false);
- DefaultShader.Compile(OpenGL);
- var time = profiler.PopAndReturn();
-
- Log.Verbose("Took {ms}ms to compile default shader", time);
- BindShader(DefaultShader);
- }
-
- private void cacheShaderUniformLocations()
- {
- textureShaderLocation = CurrentShader!.GetUniformLocation("u_texture");
- projectionUniformLocation = CurrentShader!.GetUniformLocation("u_projection");
- colorUniformLocation = CurrentShader!.GetUniformLocation("u_color");
- alphaUniformLocation = CurrentShader!.GetUniformLocation("u_alpha");
- useTextureUniformLocation = CurrentShader!.GetUniformLocation("u_use_texture");
- }
-
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void EnsureInitialized()
- {
- if (!openGlInitialized) throw new InvalidOperationException("OpenGL is not initialized yet");
- }
-
- public void Dispose()
- {
- Log.Verbose("Disposing OpenGLRenderer");
- openGlInitialized = false;
-
- OpenGL.Dispose();
- }
-}
diff --git a/Canopy.Core/Rendering/Shaders/Shader.cs b/Canopy.Core/Rendering/Shaders/Shader.cs
deleted file mode 100644
index 6eb0929..0000000
--- a/Canopy.Core/Rendering/Shaders/Shader.cs
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using System.Numerics;
-using Faster.Map.Core;
-using Serilog;
-using Silk.NET.OpenGL;
-using Synesthesia.Utils.Extensions;
-
-namespace Canopy.Rendering.Shaders;
-
-public class Shader : IDisposable
-{
- public uint Program { get; private set; }
-
- private readonly DenseMap uniformCache = new();
-
- public bool IsCompiled { get; private set; }
-
- public bool CompileQueued { get; private set; }
-
- public bool UploadImmediately { get; }
-
- public readonly string? Vertex;
- public readonly string? Fragment;
-
- private GL? gl;
-
- public Shader(string? vertexCode, string? fragmentCode, bool uploadImmediately)
- {
- if (vertexCode == null && fragmentCode == null) throw new OpenGLException("Cannot have both Vertex and Fragment shaders empty");
-
- Vertex = vertexCode;
- Fragment = fragmentCode;
- UploadImmediately = uploadImmediately;
-
- if(UploadImmediately) EnqueueCompile();
- }
-
-
- public void EnqueueCompile()
- {
- Log.Verbose("Shader upload enqueued");
- OpenGLRenderer.SHADER_COMPILE_QUEUE.Enqueue(this);
- CompileQueued = true;
- }
-
- public void Compile(GL opengl)
- {
- gl = opengl;
- CompileQueued = false;
-
- uint? vertexShader = null;
- uint? fragmentShader = null;
-
- if (Vertex != null) vertexShader = compileShader(ShaderType.VertexShader, Vertex);
- if (Fragment != null) fragmentShader = compileShader(ShaderType.FragmentShader, Fragment);
-
- Program = gl.CreateProgram();
-
- if (vertexShader != null) gl.AttachShader(Program, vertexShader.Value);
- if (fragmentShader != null) gl.AttachShader(Program, fragmentShader.Value);
- gl.LinkProgram(Program);
-
- gl.GetProgram(Program, ProgramPropertyARB.LinkStatus, out int success);
-
- if (success == 0) throw new OpenGLException($"Shader linking failed: {gl.GetProgramInfoLog(Program)}");
-
- if (vertexShader != null) gl.DeleteShader(vertexShader.Value);
- if (fragmentShader != null) gl.DeleteShader(fragmentShader.Value);
-
- IsCompiled = true;
-
- Log.Verbose("Compiled shader {this}", this);
- }
-
- private void assertGlInitialized()
- {
- if (gl == null) throw new InvalidOperationException("Shader is not compiled/being compiled");
- }
-
- public int GetUniformLocation(string uniform)
- {
- assertGlInitialized();
-
- if (uniformCache.Get(uniform, out int cached))
- return cached;
-
- var location = gl!.GetUniformLocation(Program, uniform);
- return location != -1 ? location : throw new OpenGLException($"Failed to get shader uniform '{uniform}'");
- }
-
- private uint compileShader(ShaderType shaderType, string code)
- {
- assertGlInitialized();
-
- uint shader = gl!.CreateShader(shaderType);
- gl.ShaderSource(shader, code);
- gl.CompileShader(shader);
-
- gl.GetShader(shader, ShaderParameterName.CompileStatus, out int success);
-
- var shaderId = success == 0 ? throw new OpenGLException($"Shader compilation failed: ({shaderType}): {gl.GetShaderInfoLog(shader)}") : shader;
- Log.Verbose("Compiled {Replace} shader with id {ShaderId}", shaderType.ToString().Replace("Shader", string.Empty), shaderId);
- return shaderId;
- }
-
- public void SetMatrix4(int location, Matrix4x4 matrix)
- {
- assertGlInitialized();
-
- unsafe
- {
- gl!.UniformMatrix4(location, 1, false, (float*)&matrix);
- }
- }
-
- public void SetMatrix4(string name, Matrix4x4 matrix)
- {
- int location = GetUniformLocation(name);
- SetMatrix4(location, matrix);
- }
-
- public void SetFloat(int location, float value)
- {
- assertGlInitialized();
- gl!.Uniform1(location, value);
- }
-
- public void SetFloat(string name, float value)
- {
- var location = GetUniformLocation(name);
- SetFloat(location, value);
- }
-
- public void SetDouble(int location, double value)
- {
- assertGlInitialized();
- gl!.Uniform1(location, value);
- }
-
- public void SetDouble(string name, double value)
- {
- var location = GetUniformLocation(name);
- SetDouble(location, value);
- }
-
- public void SetInt(int location, int value)
- {
- assertGlInitialized();
- gl!.Uniform1(location, value);
- }
-
- public void SetInt(string name, int value)
- {
- var location = GetUniformLocation(name);
- SetInt(location, value);
- }
-
- public void SetBool(int location, bool value) => SetInt(location, value.ToInt());
-
- public void SetBool(string name, bool value) => SetInt(name, value.ToInt());
-
- public void SetVector2(int location, Vector2 value)
- {
- assertGlInitialized();
- gl!.Uniform2(location, value);
- }
-
- public void SetVector2(string name, Vector2 value)
- {
- var location = GetUniformLocation(name);
- SetVector2(location, value);
- }
-
- public void SetVector3(int location, Vector3 value)
- {
- assertGlInitialized();
- gl!.Uniform3(location, value);
- }
-
- public void SetVector3(string name, Vector3 value)
- {
- var location = GetUniformLocation(name);
- SetVector3(location, value);
- }
-
- public void SetVector4(int location, Vector4 value)
- {
- assertGlInitialized();
- gl!.Uniform4(location, value);
- }
-
- public void SetVector4(string name, Vector4 value)
- {
- var location = GetUniformLocation(name);
- SetVector4(location, value);
- }
-
- public void Use()
- {
- assertGlInitialized();
-
- gl!.UseProgram(Program);
- Log.Verbose("Bound shader program {id}", Program);
- }
-
- public override string ToString() => $"Shader(Handle={Program}, Vertex={Vertex != null}, Fragment={Fragment != null}, IsCompiled={IsCompiled}, CompileQueued={CompileQueued})";
-
- public void Dispose()
- {
- Log.Verbose("Disposed shader program {h}", Program);
- gl?.DeleteProgram(Program);
- uniformCache.Clear();
- }
-}
diff --git a/Canopy.Core/Rendering/Shaders/ShaderSources.cs b/Canopy.Core/Rendering/Shaders/ShaderSources.cs
deleted file mode 100644
index 241c206..0000000
--- a/Canopy.Core/Rendering/Shaders/ShaderSources.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-namespace Canopy.Rendering.Shaders;
-
-public sealed class ShaderSources
-{
- public const string DEFAULT_VERTEX = @"
- #version 330 core
- layout(location = 0) in vec2 a_pos;
- layout(location = 1) in vec2 a_texCoord;
-
- out vec2 v_texCoord;
- uniform mat4 u_projection;
-
- void main()
- {
- v_texCoord = a_texCoord;
- gl_Position = u_projection * vec4(a_pos, 0.0, 1.0);
- }
- ";
-
- public const string DEFAULT_FRAGMENT = @"
- #version 330 core
- in vec2 v_texCoord;
- out vec4 FragColor;
-
- uniform sampler2D u_texture;
- uniform bool u_use_texture;
- uniform vec4 u_color;
- uniform float u_alpha;
-
- void main()
- {
- vec4 color = u_use_texture
- ? texture(u_texture, v_texCoord) * u_color
- : u_color;
-
- FragColor = vec4(color.rgb, color.a * u_alpha);
- }
- ";
-}
diff --git a/Canopy.Core/Rendering/Textures/Texture.cs b/Canopy.Core/Rendering/Textures/Texture.cs
deleted file mode 100644
index 65c5490..0000000
--- a/Canopy.Core/Rendering/Textures/Texture.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using Serilog;
-using Silk.NET.OpenGL;
-
-namespace Canopy.Rendering.Textures;
-
-public class Texture : IDisposable
-{
- public uint Handle { get; private set; }
-
- public TextureData TextureData { get; private set; }
-
- public int Width => TextureData.Width;
- public int Height => TextureData.Height;
- public PixelFormat PixelFormat => TextureData.PixelFormat;
-
- public bool IsUploaded { get; private set; }
-
- public bool UploadQueued { get; private set; }
-
- public bool UploadImmediately { get; }
-
- private GL? gl;
-
- public Texture(TextureData textureData, bool uploadImmediately)
- {
- UploadImmediately = uploadImmediately;
- TextureData = textureData;
- IsUploaded = false;
-
- if (UploadImmediately) EnqueueUpload();
- }
-
- public void EnqueueUpload()
- {
- Log.Verbose("Texture upload enqueued");
- OpenGLRenderer.TEXTURE_UPLOAD_QUEUE.Enqueue(this);
- UploadQueued = true;
- }
-
- public void Upload(GL opengl)
- {
- // ThreadSafety.AssertRunningOnRenderThread();
-
- if (IsUploaded) return;
- if (TextureData.Data.Length == 0) throw new OpenGLException("No pixel data");
-
- gl = opengl;
- Handle = gl.GenTexture();
- opengl.BindTexture(TextureTarget.Texture2D, Handle);
-
- gl.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
- gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
- gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMinFilter.Linear);
- gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
- gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
-
- unsafe
- {
- fixed (void* ptr = TextureData.Data)
- {
- gl.TexImage2D(TextureTarget.Texture2D, 0, InternalFormat.Rgba, (uint)Width, (uint)Height, 0, TextureData.PixelFormat, PixelType.UnsignedByte, ptr);
- }
- }
-
- IsUploaded = true;
- UploadQueued = false;
- Log.Verbose("Uploaded texture {this}", ToString());
- }
-
- public bool Bind(GL opengl, TextureUnit unit = TextureUnit.Texture0)
- {
- // ThreadSafety.AssertRunningOnRenderThread();
-
- switch (IsUploaded)
- {
- case false when !UploadQueued:
- EnqueueUpload();
- return false;
- case false:
- return false;
- }
-
- gl!.ActiveTexture(unit);
- gl.BindTexture(TextureTarget.Texture2D, Handle);
- return true;
- }
-
- public override string ToString() => $"Texture(Handle={Handle}, TextureData={TextureData}, IsUploaded={IsUploaded}, UploadQueued={UploadQueued})";
-
- public void Dispose()
- {
- }
-}
diff --git a/Canopy.Core/Rendering/Textures/TextureData.cs b/Canopy.Core/Rendering/Textures/TextureData.cs
deleted file mode 100644
index a0d4c91..0000000
--- a/Canopy.Core/Rendering/Textures/TextureData.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using Silk.NET.OpenGL;
-
-namespace Canopy.Rendering.Textures;
-
-public class TextureData(int width, int height, byte[] data, PixelFormat pixelFormat)
-{
- public int Width { get; set; } = width;
- public int Height { get; set; } = height;
- public byte[] Data { get; set; } = data;
- public PixelFormat PixelFormat { get; set; } = pixelFormat;
-
- public override string ToString() => $"TextureData(Width={Width}, Height={Height}, Data={Data.Length} PixelFormat={PixelFormat})";
-}
diff --git a/Canopy.Core/Rendering/WallpaperManager.cs b/Canopy.Core/Rendering/WallpaperManager.cs
deleted file mode 100644
index 7697d15..0000000
--- a/Canopy.Core/Rendering/WallpaperManager.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using Canopy.Graphics;
-
-namespace Canopy.Rendering;
-
-public class WallpaperManager(ICanopyPlatform platform) : IDrawable
-{
- public ICanopyPlatform Platform => platform;
-
- protected Wallpaper? CurrentWallpaper;
- protected Wallpaper? NextWallpaper;
-
- private bool firstSwap = true;
-
- public void Dispose()
- {
- CurrentWallpaper?.Dispose();
- NextWallpaper?.Dispose();
- }
-
- public void PushWallpaper(Wallpaper wallpaper)
- {
- NextWallpaper = wallpaper;
- }
-
- public void Draw(OpenGLRenderer gl)
- {
- var currentWallpaperCanDraw = CurrentWallpaper is { Texture.IsUploaded: true };
- if(currentWallpaperCanDraw) CurrentWallpaper!.Draw(gl);
-
- if (NextWallpaper is { Texture.IsUploaded: true })
- {
- if (currentWallpaperCanDraw)
- {
- //TODO CurrentWallpaper.FadeAlpha(5000, 1f, Easings.OutSine).Then(() => //swap wallpapers)
- CurrentWallpaper!.Alpha = 0f;
- var old = CurrentWallpaper;
-
- CurrentWallpaper = NextWallpaper;
- NextWallpaper = null;
- old.Dispose();
- }
- else
- {
- CurrentWallpaper = NextWallpaper;
- NextWallpaper = null;
- }
- }
-
- if (firstSwap && currentWallpaperCanDraw)
- {
- firstSwap = false;
- Platform.ShowWindow();
- }
- }
-}
diff --git a/Canopy.Core/Server/CanopyWebsocketServer.cs b/Canopy.Core/Server/CanopyWebsocketServer.cs
new file mode 100644
index 0000000..5d269e6
--- /dev/null
+++ b/Canopy.Core/Server/CanopyWebsocketServer.cs
@@ -0,0 +1,36 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using Canopy.Server.Messages;
+using Serilog;
+
+namespace Canopy.Server;
+
+public class CanopyWebsocketServer
+{
+ private readonly WebsocketServer websocketServer = new WebsocketServer("/update", Canopy.CurrentConfig.Websocket.Url);
+ private ISocketMessage? lastMessage;
+
+ public void Initialize()
+ {
+ websocketServer.Start();
+
+ websocketServer.ClientConnected.Subscribe(_ =>
+ {
+ if (lastMessage != null)
+ Send(lastMessage);
+ });
+ }
+
+ public void Send(ISocketMessage message)
+ {
+ lastMessage = message;
+ Task.Run(() => websocketServer.Send(message.Encode()));
+ Log.Information("(WebSocket) -> Sent message {message} to websocket", message.GetType().Name);
+ }
+
+ public void Stop()
+ {
+ websocketServer.Stop();
+ }
+}
diff --git a/Canopy.Core/Graphics/IDrawable.cs b/Canopy.Core/Server/Messages/ISocketMessage.cs
similarity index 57%
rename from Canopy.Core/Graphics/IDrawable.cs
rename to Canopy.Core/Server/Messages/ISocketMessage.cs
index 08b19fc..c723256 100644
--- a/Canopy.Core/Graphics/IDrawable.cs
+++ b/Canopy.Core/Server/Messages/ISocketMessage.cs
@@ -1,11 +1,11 @@
// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-using Canopy.Rendering;
+namespace Canopy.Server.Messages;
-namespace Canopy.Graphics;
-
-public interface IDrawable : IDisposable
+public interface ISocketMessage
{
- void Draw(OpenGLRenderer gl);
+ string Encode();
+
+ ISocketMessage Decode(string message);
}
diff --git a/Canopy.Core/Server/Messages/NewWallpaperMessage.cs b/Canopy.Core/Server/Messages/NewWallpaperMessage.cs
new file mode 100644
index 0000000..999d732
--- /dev/null
+++ b/Canopy.Core/Server/Messages/NewWallpaperMessage.cs
@@ -0,0 +1,23 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using Canopy.Configuration;
+using Codon.Codec;
+using Codon.Codec.Json;
+
+namespace Canopy.Server.Messages;
+
+public record NewWallpaperMessage(long Timestamp, Wallpaper Wallpaper) : ISocketMessage
+{
+ public static readonly StructCodec CODEC = StructCodec.For()
+ .Field("Timestamp", Codecs.LONG, w => w.Timestamp)
+ .Field("Wallpaper", Wallpaper.CODEC, w => w.Wallpaper)
+ .Build((time, wallpaper) => new NewWallpaperMessage(time, wallpaper));
+
+ public string Encode() => CODEC.Encode(JsonTranscoder.INSTANCE, this).ToStringPretty();
+
+ public ISocketMessage Decode(string message)
+ {
+ throw new NotImplementedException();
+ }
+}
diff --git a/Canopy.Core/Server/WebsocketServer.cs b/Canopy.Core/Server/WebsocketServer.cs
new file mode 100644
index 0000000..41c4204
--- /dev/null
+++ b/Canopy.Core/Server/WebsocketServer.cs
@@ -0,0 +1,142 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Net;
+using System.Net.WebSockets;
+using System.Text;
+using Serilog;
+using Synesthesia.Utils.Events;
+
+namespace Canopy.Server;
+
+public class WebsocketServer
+{
+ private readonly HttpListener listener = new();
+ private readonly string path;
+ private readonly HashSet sockets = new();
+ private readonly Lock @lock = new();
+ private CancellationTokenSource? cts;
+
+ public readonly EventDispatcher ClientConnected = new EventDispatcher();
+
+ public WebsocketServer(string path, string url)
+ {
+ this.path = path;
+ listener.Prefixes.Add(url.EndsWith('/') ? url : url + "/");
+ }
+
+ public void Start()
+ {
+ cts = new CancellationTokenSource();
+ listener.Start();
+ Log.Information("(Websocket) Server listening on {prefix}", string.Join(", ", listener.Prefixes));
+ _ = Task.Run(() => acceptLoopAsync(cts.Token));
+ }
+
+ public void Stop()
+ {
+ cts?.Cancel();
+ listener.Stop();
+ }
+
+ private async Task acceptLoopAsync(CancellationToken ct)
+ {
+ while (!ct.IsCancellationRequested)
+ {
+ HttpListenerContext ctx;
+ try
+ {
+ ctx = await listener.GetContextAsync();
+ }
+ catch (HttpListenerException)
+ {
+ break;
+ }
+ catch (ObjectDisposedException)
+ {
+ break;
+ }
+
+ if (ctx.Request.Url?.AbsolutePath != path || !ctx.Request.IsWebSocketRequest)
+ {
+ ctx.Response.StatusCode = 400;
+ ctx.Response.Close();
+ continue;
+ }
+
+ _ = handleClientAsync(ctx, ct);
+ }
+ }
+
+ private async Task handleClientAsync(HttpListenerContext ctx, CancellationToken ct)
+ {
+ WebSocketContext wsCtx;
+ try
+ {
+ wsCtx = await ctx.AcceptWebSocketAsync(null);
+ }
+ catch (Exception ex)
+ {
+ Log.Warning(ex, "(Websocket) WebSocket handshake failed");
+ ctx.Response.StatusCode = 500;
+ ctx.Response.Close();
+ return;
+ }
+
+ var socket = wsCtx.WebSocket;
+ lock (@lock) { sockets.Add(socket); }
+ Log.Debug("(Websocket) <-> Client connected on {path}", path);
+ ClientConnected.Dispatch(socket);
+
+ var buffer = new byte[1024];
+ try
+ {
+ while (socket.State == WebSocketState.Open && !ct.IsCancellationRequested)
+ {
+ var result = await socket.ReceiveAsync(buffer, ct);
+ if (result.MessageType == WebSocketMessageType.Close)
+ {
+ await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, null, ct);
+ break;
+ }
+ }
+ }
+ catch (OperationCanceledException) { }
+ catch (WebSocketException ex)
+ {
+ Log.Error(ex, "(Websocket) <-!-> Client disconnected due to error");
+ }
+ finally
+ {
+ lock (@lock) { sockets.Remove(socket); }
+ socket.Dispose();
+ Log.Debug("(Websocket) <-!-> Client disconnected safely");
+ }
+ }
+
+ public async Task Send(string text)
+ {
+ WebSocket[] activeSockets;
+ lock (@lock)
+ {
+ activeSockets = sockets.Where(s => s.State == WebSocketState.Open).ToArray();
+ }
+
+ if (activeSockets.Length == 0) return;
+
+ var bytes = Encoding.UTF8.GetBytes(text);
+ var sendTasks = activeSockets.Select(socket => Task.Run(async () =>
+ {
+ try
+ {
+ await socket.SendAsync(bytes, WebSocketMessageType.Text, true, CancellationToken.None);
+ }
+ catch (WebSocketException ex)
+ {
+ Log.Warning(ex, "(Websocket) -> Send failed, client likely disconnected");
+ }
+ }));
+
+ await Task.WhenAll(sendTasks);
+ }
+}
diff --git a/Canopy.Core/ShellUtils.cs b/Canopy.Core/ShellUtils.cs
new file mode 100644
index 0000000..52c0cb6
--- /dev/null
+++ b/Canopy.Core/ShellUtils.cs
@@ -0,0 +1,33 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace Canopy;
+
+public static class ShellUtils
+{
+ public static void OpenFolder(string folderPath)
+ {
+ if (!Directory.Exists(folderPath))
+ return;
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ Process.Start(new ProcessStartInfo
+ {
+ FileName = folderPath,
+ UseShellExecute = true
+ });
+ }
+ else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ {
+ Process.Start("open", $"\"{folderPath}\"");
+ }
+ else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+ {
+ Process.Start("xdg-open", $"\"{folderPath}\"");
+ }
+ }
+}
diff --git a/Canopy.Core/Storage/AssemblyAssetStorage.cs b/Canopy.Core/Storage/AssemblyAssetStorage.cs
deleted file mode 100644
index 6155752..0000000
--- a/Canopy.Core/Storage/AssemblyAssetStorage.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using System.Reflection;
-
-namespace Canopy.Storage;
-
-public class AssemblyAssetStorage(Assembly assembly) : AssetStorage
-{
- public override string[] GetAllFiles() => assembly.GetManifestResourceNames();
-
- public override bool FileExists(string path) => assembly.GetManifestResourceNames().Contains(path);
-
- public override byte[]? GetOrNull(string path)
- {
- using var stream = assembly.GetManifestResourceStream(path);
- return stream == null ? null : ReadFully(stream);
- }
-
- public static byte[] ReadFully(Stream input)
- {
- byte[] buffer = new byte[16*1024];
- using MemoryStream ms = new MemoryStream();
-
- int read;
- while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
- {
- ms.Write(buffer, 0, read);
- }
- return ms.ToArray();
- }
-}
diff --git a/Canopy.Core/Storage/AssetStorage.cs b/Canopy.Core/Storage/AssetStorage.cs
deleted file mode 100644
index ca4a620..0000000
--- a/Canopy.Core/Storage/AssetStorage.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-namespace Canopy.Storage;
-
-public abstract class AssetStorage
-{
- private readonly Dictionary cacheTyped = new();
-
- public abstract string[] GetAllFiles();
-
- public abstract bool FileExists(string path);
-
- public abstract byte[]? GetOrNull(string path);
-
- public byte[] Get(string path, string exception = "File with that path was not found")
- {
- return GetOrNull(path) ?? throw new FileNotFoundException(exception, path);
- }
-
- public T? GetResolvedOrNull(string path, Func dataParser) where T: class
- {
- if (cacheTyped.TryGetValue(path, out var cachedObj) && cachedObj is T typed)
- return typed;
-
- var item = GetOrNull(path);
- if (item == null) return null;
-
- var resolved = dataParser.Invoke(item, path);
- cacheTyped.TryAdd(path, resolved);
-
- return resolved;
- }
-
- public T GetResolved(string path, Func dataParser, string exception = "File with that path was not found") where T: class
- {
- return GetResolvedOrNull(path, dataParser) ?? throw new FileNotFoundException(exception, path);
- }
-}
diff --git a/Canopy.Core/Storage/DataParsers.cs b/Canopy.Core/Storage/DataParsers.cs
deleted file mode 100644
index c3446be..0000000
--- a/Canopy.Core/Storage/DataParsers.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using System.Text;
-using Canopy.Rendering.Textures;
-using Silk.NET.OpenGL;
-using StbImageSharp;
-using Texture = Canopy.Rendering.Textures.Texture;
-
-namespace Canopy.Storage;
-
-public static class DataParsers
-{
-
- public static Texture LoadTexture(byte[] data, bool uploadImmediately = false)
- {
- var image = ImageResult.FromMemory(data, ColorComponents.RedGreenBlueAlpha);
- var textureData = new TextureData(image.Width, image.Height, image.Data, PixelFormat.Rgba);
- return new Texture(textureData, uploadImmediately);
- }
-
- public static Texture LoadTexture(byte[] data, string _)
- {
- return LoadTexture(data, true);
- }
-
- public static string LoadString(byte[] data, string _)
- {
- return Encoding.UTF8.GetString(data);
- }
-}
diff --git a/Canopy.Core/Storage/DirectoryAssetStorage.cs b/Canopy.Core/Storage/DirectoryAssetStorage.cs
deleted file mode 100644
index 76020dc..0000000
--- a/Canopy.Core/Storage/DirectoryAssetStorage.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using Serilog;
-
-namespace Canopy.Storage;
-
-public class DirectoryAssetStorage(string dirPath) : AssetStorage
-{
- private readonly string rootFullPath = Path.GetFullPath(dirPath);
-
- public override string[] GetAllFiles()
- {
- return Directory.EnumerateFiles(rootFullPath, "*", SearchOption.AllDirectories)
- .Select(p => Path.GetRelativePath(rootFullPath, p))
- .ToArray();
- }
-
- public override bool FileExists(string path)
- {
- var fullPath = getSafeFullPath(path);
- return fullPath != null && File.Exists(fullPath);
- }
-
- public override byte[]? GetOrNull(string path)
- {
- var fullPath = getSafeFullPath(path);
- if (fullPath == null || !File.Exists(fullPath)) return null;
-
- try
- {
- return File.ReadAllBytes(fullPath);
- }
- catch (Exception)
- {
- Log.Warning("file {path} exists but couldn't be read", path);
- return null;
- }
- }
-
- /// combines the root path with the relative path and normalizes separators
- /// and ensures the file doesn't escape the root directory (../../../).
- private string? getSafeFullPath(string relativePath)
- {
- if (string.IsNullOrWhiteSpace(relativePath)) return null;
-
- string combinedPath = Path.Combine(rootFullPath, relativePath);
- string fullPath = Path.GetFullPath(combinedPath);
-
- return !fullPath.StartsWith(rootFullPath, StringComparison.OrdinalIgnoreCase) ? null : fullPath;
- }
-}
diff --git a/Canopy.Core/Utils/Easing.cs b/Canopy.Core/Utils/Easing.cs
deleted file mode 100644
index 90a5237..0000000
--- a/Canopy.Core/Utils/Easing.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-namespace Canopy.Utils;
-
-public enum Easing
-{
- Linear,
- Out,
- In,
- InQuad,
- OutQuad,
- InOutQuad,
- InCubic,
- OutCubic,
- InOutCubic,
- InQuart,
- OutQuart,
- InOutQuart,
- InQuint,
- OutQuint,
- InOutQuint,
- InSine,
- OutSine,
- InOutSine,
- InExpo,
- OutExpo,
- InOutExpo,
- InCirc,
- OutCirc,
- InOutCirc,
- InElastic,
- OutElastic,
- OutElasticHalf,
- OutElasticQuarter,
- InOutElastic,
- InBack,
- OutBack,
- InOutBack,
- InBounce,
- OutBounce,
- InOutBounce,
- OutPow10,
-}
-
diff --git a/Canopy.Core/Utils/EasingFunction.cs b/Canopy.Core/Utils/EasingFunction.cs
deleted file mode 100644
index 073841c..0000000
--- a/Canopy.Core/Utils/EasingFunction.cs
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-namespace Canopy.Utils
-{
- public readonly struct EasingFunction(Easing easing) : IEasingFunction
- {
- private const double elastic_const = 2 * Math.PI / .3;
- private const double elastic_const2 = .3 / 4;
-
- private const double back_const = 1.70158;
- private const double back_const2 = back_const * 1.525;
-
- private const double bounce_const = 1 / 2.75;
-
- private static readonly double expo_offset = Math.Pow(2, -10);
- private static readonly double elastic_offset_full = Math.Pow(2, -11);
- private static readonly double elastic_offset_half = Math.Pow(2, -10) * Math.Sin((.5 - elastic_const2) * elastic_const);
- private static readonly double elastic_offset_quarter = Math.Pow(2, -10) * Math.Sin((.25 - elastic_const2) * elastic_const);
- private static readonly double in_out_elastic_offset = Math.Pow(2, -10) * Math.Sin((1 - elastic_const2 * 1.5) * elastic_const / 1.5);
-
- public double ApplyEasing(double time)
- {
- switch (easing)
- {
- case Easing.Linear:
- default:
- return time;
-
- case Easing.In:
- case Easing.InQuad:
- return time * time;
-
- case Easing.Out:
- case Easing.OutQuad:
- return time * (2 - time);
-
- case Easing.InOutQuad:
- if (time < .5) return time * time * 2;
-
- return --time * time * -2 + 1;
-
- case Easing.InCubic:
- return time * time * time;
-
- case Easing.OutCubic:
- return --time * time * time + 1;
-
- case Easing.InOutCubic:
- if (time < .5) return time * time * time * 4;
-
- return --time * time * time * 4 + 1;
-
- case Easing.InQuart:
- return time * time * time * time;
-
- case Easing.OutQuart:
- return 1 - --time * time * time * time;
-
- case Easing.InOutQuart:
- if (time < .5) return time * time * time * time * 8;
-
- return --time * time * time * time * -8 + 1;
-
- case Easing.InQuint:
- return time * time * time * time * time;
-
- case Easing.OutQuint:
- return --time * time * time * time * time + 1;
-
- case Easing.InOutQuint:
- if (time < .5) return time * time * time * time * time * 16;
-
- return --time * time * time * time * time * 16 + 1;
-
- case Easing.InSine:
- return 1 - Math.Cos(time * Math.PI * .5);
-
- case Easing.OutSine:
- return Math.Sin(time * Math.PI * .5);
-
- case Easing.InOutSine:
- return .5 - .5 * Math.Cos(Math.PI * time);
-
- case Easing.InExpo:
- return Math.Pow(2, 10 * (time - 1) + expo_offset * (time - 1));
-
- case Easing.OutExpo:
- return -Math.Pow(2, -10 * time) + 1 + expo_offset * time;
-
- case Easing.InOutExpo:
- if (time < .5) return .5 * (Math.Pow(2, 20 * time - 10) + expo_offset * (2 * time - 1));
-
- return 1 - .5 * (Math.Pow(2, -20 * time + 10) + expo_offset * (-2 * time + 1));
-
- case Easing.InCirc:
- return 1 - Math.Sqrt(1 - time * time);
-
- case Easing.OutCirc:
- return Math.Sqrt(1 - --time * time);
-
- case Easing.InOutCirc:
- if ((time *= 2) < 1) return .5 - .5 * Math.Sqrt(1 - time * time);
-
- return .5 * Math.Sqrt(1 - (time -= 2) * time) + .5;
-
- case Easing.InElastic:
- return -Math.Pow(2, -10 + 10 * time) * Math.Sin((1 - elastic_const2 - time) * elastic_const) + elastic_offset_full * (1 - time);
-
- case Easing.OutElastic:
- return Math.Pow(2, -10 * time) * Math.Sin((time - elastic_const2) * elastic_const) + 1 - elastic_offset_full * time;
-
- case Easing.OutElasticHalf:
- return Math.Pow(2, -10 * time) * Math.Sin((.5 * time - elastic_const2) * elastic_const) + 1 - elastic_offset_half * time;
-
- case Easing.OutElasticQuarter:
- return Math.Pow(2, -10 * time) * Math.Sin((.25 * time - elastic_const2) * elastic_const) + 1 - elastic_offset_quarter * time;
-
- case Easing.InOutElastic:
- if ((time *= 2) < 1)
- {
- return -.5 * (Math.Pow(2, -10 + 10 * time) * Math.Sin((1 - elastic_const2 * 1.5 - time) * elastic_const / 1.5)
- - in_out_elastic_offset * (1 - time));
- }
-
- return .5 * (Math.Pow(2, -10 * --time) * Math.Sin((time - elastic_const2 * 1.5) * elastic_const / 1.5)
- - in_out_elastic_offset * time) + 1;
-
- case Easing.InBack:
- return time * time * ((back_const + 1) * time - back_const);
-
- case Easing.OutBack:
- return --time * time * ((back_const + 1) * time + back_const) + 1;
-
- case Easing.InOutBack:
- if ((time *= 2) < 1) return .5 * time * time * ((back_const2 + 1) * time - back_const2);
-
- return .5 * ((time -= 2) * time * ((back_const2 + 1) * time + back_const2) + 2);
-
- case Easing.InBounce:
- time = 1 - time;
- if (time < bounce_const)
- return 1 - 7.5625 * time * time;
- if (time < 2 * bounce_const)
- return 1 - (7.5625 * (time -= 1.5 * bounce_const) * time + .75);
- if (time < 2.5 * bounce_const)
- return 1 - (7.5625 * (time -= 2.25 * bounce_const) * time + .9375);
-
- return 1 - (7.5625 * (time -= 2.625 * bounce_const) * time + .984375);
-
- case Easing.OutBounce:
- if (time < bounce_const)
- return 7.5625 * time * time;
- if (time < 2 * bounce_const)
- return 7.5625 * (time -= 1.5 * bounce_const) * time + .75;
- if (time < 2.5 * bounce_const)
- return 7.5625 * (time -= 2.25 * bounce_const) * time + .9375;
-
- return 7.5625 * (time -= 2.625 * bounce_const) * time + .984375;
-
- case Easing.InOutBounce:
- if (time < .5) return .5 - .5 * new EasingFunction(Easing.OutBounce).ApplyEasing(1 - time * 2);
-
- return new EasingFunction(Easing.OutBounce).ApplyEasing((time - .5) * 2) * .5 + .5;
-
- case Easing.OutPow10:
- return --time * Math.Pow(time, 10) + 1;
- }
- }
- }
-}
diff --git a/Canopy.Core/Utils/Future/ITask.cs b/Canopy.Core/Utils/Future/ITask.cs
deleted file mode 100644
index c683bba..0000000
--- a/Canopy.Core/Utils/Future/ITask.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Canopy.Utils.Future;
-
-public interface ITask
-{
- bool IsComplete { get; }
- void OnCompleted(Action callback);
-}
diff --git a/Canopy.Core/Utils/Future/Nothing.cs b/Canopy.Core/Utils/Future/Nothing.cs
deleted file mode 100644
index 8867250..0000000
--- a/Canopy.Core/Utils/Future/Nothing.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Canopy.Utils.Future;
-
-public sealed class Nothing
-{
- public static readonly Nothing INSTANCE = new();
-}
diff --git a/Canopy.Core/Utils/Future/Tasks.cs b/Canopy.Core/Utils/Future/Tasks.cs
deleted file mode 100644
index a2d9732..0000000
--- a/Canopy.Core/Utils/Future/Tasks.cs
+++ /dev/null
@@ -1,128 +0,0 @@
-namespace Canopy.Utils.Future;
-
-public class TaskTask : ITask
-{
- private T? result;
- private Exception? exception;
-
- private readonly List> successCallbacks = [];
- private readonly List> failCallbacks = [];
- private readonly List anyCompletionCallbacks = [];
-
- public bool IsComplete { get; private set; }
-
- public TaskTask Then(Action then)
- {
- if (IsComplete && exception == null)
- {
- then.Invoke(result!);
- }
- else
- {
- successCallbacks.Add(then);
- }
-
- return this;
- }
-
- public void Complete(T value)
- {
- if (IsComplete) return;
-
- result = value;
- IsComplete = true;
- successCallbacks.ForEach(a => a.Invoke(value));
- anyCompletionCallbacks.ForEach(a => a.Invoke());
- }
-
- public void Fail(Exception ex)
- {
- if (IsComplete) return;
- exception = ex;
- IsComplete = true;
- failCallbacks.ForEach(a => a.Invoke(ex));
- anyCompletionCallbacks.ForEach(a => a.Invoke());
- }
-
-
- public void OnCompleted(Action callback)
- {
- if (IsComplete) callback();
- else anyCompletionCallbacks.Add(callback);
- }
-
- public void OnSuccess(Action callback)
- {
- if (IsComplete && exception == null && result != null) callback.Invoke(result!);
- else successCallbacks.Add(callback);
- }
-
- public void OnFail(Action callback)
- {
- if (IsComplete && exception != null) callback.Invoke(exception);
- else failCallbacks.Add(callback);
- }
-}
-
-public static class Tasks
-{
- public static TaskTask RunAsync(Func action)
- {
- var future = new TaskTask();
-
- Task.Run(() =>
- {
- try
- {
- var result = action();
- future.Complete(result);
- }
- catch (Exception ex)
- {
- future.Fail(ex);
- }
- });
-
- return future;
- }
-
- public static TaskTask RunAsync(Action action)
- {
- return RunAsync(() =>
- {
- action();
- return Nothing.INSTANCE;
- });
- }
-
- public static TaskTask Completed(T value)
- {
- var future = new TaskTask();
- future.Complete(value);
- return future;
- }
-
- public static TaskTask All(params ITask[] futures)
- {
- var returnedPromise = new TaskTask();
- if (futures.Length == 0)
- {
- returnedPromise.Complete(Nothing.INSTANCE);
- return returnedPromise;
- }
-
- var remaining = futures.Length;
- foreach (var future in futures)
- {
- future.OnCompleted(() =>
- {
- if (Interlocked.Decrement(ref remaining) == 0)
- {
- returnedPromise.Complete(Nothing.INSTANCE);
- }
- });
- }
-
- return returnedPromise;
- }
-}
diff --git a/Canopy.Core/Utils/HardwareDecoder.cs b/Canopy.Core/Utils/HardwareDecoder.cs
deleted file mode 100644
index 658f7bd..0000000
--- a/Canopy.Core/Utils/HardwareDecoder.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-// ReSharper disable InconsistentNaming
-namespace Canopy.Utils;
-
-public enum HardwareDecoder
-{
- None,
- NVDEC,
- AMD_VCN,
- INTEL_QSV,
- FFMPEG
-}
diff --git a/Canopy.Core/Utils/MathUtil.cs b/Canopy.Core/Utils/MathUtil.cs
deleted file mode 100644
index 71f50b9..0000000
--- a/Canopy.Core/Utils/MathUtil.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-namespace Canopy.Utils;
-
-public static class MathUtil
-{
- public static float ToRads(this float deg)
- {
- return deg * (MathF.PI / 180f);
- }
-}
diff --git a/Canopy.Core/Utils/Precision.cs b/Canopy.Core/Utils/Precision.cs
deleted file mode 100644
index 3a377f0..0000000
--- a/Canopy.Core/Utils/Precision.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-namespace Canopy.Utils;
-
-public static class Precision
-{
- public static bool IsSame(float value1, float value2, float precision = 0.00001f)
- {
- return Math.Abs(value1 - value2) < precision;
- }
-
- public static bool IsSame(double value1, double value2, double precision = 0.00001)
- {
- return Math.Abs(value1 - value2) < precision;
- }
-}
diff --git a/Canopy.Core/Utils/Timing/IAdjustableClock.cs b/Canopy.Core/Utils/Timing/IAdjustableClock.cs
deleted file mode 100644
index 8c1a672..0000000
--- a/Canopy.Core/Utils/Timing/IAdjustableClock.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace Canopy.Utils.Timing;
-
-public interface IAdjustableClock
-{
- void Reset();
-
- void Start();
-
- void Stop();
-
- bool Seek(double position);
-
- double Rate { get; set; }
-
- void ResetSpeedAdjustments();
-}
diff --git a/Canopy.Core/Utils/Timing/StopwatchClock.cs b/Canopy.Core/Utils/Timing/StopwatchClock.cs
deleted file mode 100644
index 4178bca..0000000
--- a/Canopy.Core/Utils/Timing/StopwatchClock.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using System.Diagnostics;
-
-namespace Canopy.Utils.Timing;
-
-public sealed class StopwatchClock : Stopwatch, IAdjustableClock
-{
- private double seekOffset;
-
- private double rateChangeUsed;
-
- private double rateChangeAccumulated;
-
- private double stopwatchMilliseconds => (double)ElapsedTicks / Frequency * 1000;
-
- private double stopwatchCurrentTime => (stopwatchMilliseconds - rateChangeUsed) * rate + rateChangeAccumulated;
-
- public double CurrentTime => stopwatchCurrentTime + seekOffset;
-
- private double rate = 1;
-
- public double Rate
- {
- get => rate;
- set
- {
- if (rate == value) return;
-
- rateChangeAccumulated += (stopwatchMilliseconds - rateChangeUsed) * rate;
- rateChangeUsed = stopwatchMilliseconds;
-
- rate = value;
- }
- }
-
- public StopwatchClock(bool start)
- {
- if (start) Start();
- }
-
- public new void Reset()
- {
- resetAccumulatedRate();
- base.Reset();
- }
-
- public new void Restart()
- {
- resetAccumulatedRate();
- base.Restart();
- }
-
- public bool Seek(double position)
- {
- seekOffset = position - stopwatchCurrentTime;
- return true;
- }
-
- public void ResetSpeedAdjustments() => Rate = 1;
-
- private void resetAccumulatedRate()
- {
- rateChangeAccumulated = 0;
- rateChangeUsed = 0;
- }
-}
diff --git a/Canopy.Core/Utils/UserLand.cs b/Canopy.Core/Utils/UserLand.cs
deleted file mode 100644
index 57195ea..0000000
--- a/Canopy.Core/Utils/UserLand.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using Canopy.Graphics;
-using Canopy.Storage;
-
-namespace Canopy.Utils;
-
-public static class UserLand
-{
- public static void EntryPoint(ICanopyPlatform platform)
- {
- var storage = new DirectoryAssetStorage(@"C:\Users\Synesthesia\RiderProjects\Canopy\resources");
- var wallpaper = new Wallpaper("furina.png", storage);
-
- platform.PushWallpaper(wallpaper);
- }
-
-
-}
diff --git a/Canopy.Windows/BackgroundTrayService.cs b/Canopy.Windows/BackgroundTrayService.cs
new file mode 100644
index 0000000..00efc16
--- /dev/null
+++ b/Canopy.Windows/BackgroundTrayService.cs
@@ -0,0 +1,81 @@
+// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Collections.Concurrent;
+using System.Drawing;
+using System.Reflection;
+using H.NotifyIcon.Core;
+using Serilog;
+using Vanara.PInvoke;
+using static Vanara.PInvoke.User32;
+
+namespace Canopy.Windows;
+
+public class BackgroundTrayService(Canopy canopy)
+{
+ private Thread? trayThread;
+ private TrayIconWithContextMenu trayIcon = null!;
+ private readonly ConcurrentQueue queue = new ConcurrentQueue();
+
+ public void Start()
+ {
+
+ trayThread = new Thread(() =>
+ {
+ trayIcon = new TrayIconWithContextMenu();
+ trayIcon.ToolTip = "🌿 Canopy";
+
+ var assembly = Assembly.GetExecutingAssembly();
+ using var stream = assembly.GetManifestResourceStream("Canopy.Windows.canopy.ico");
+
+ if (stream != null)
+ {
+ var icon = new Icon(stream);
+ trayIcon.UpdateIcon(icon.Handle);
+ }
+ else
+ {
+ Log.Warning("Icon not found");
+ }
+
+ var menu = new PopupMenu();
+ menu.Items.Add(new PopupMenuItem("Open Config Folder", (_, _) => ShellUtils.OpenFolder(Canopy.CANOPY_FOLDER_PATH)));
+ menu.Items.Add(new PopupMenuItem("Reload Config", (_, _) => canopy.LoadRefreshable()));
+ // menu.Items.Add(new PopupMenuItem("Test popup", (_, _) => canopy.Platform.ShowNotification("fuccckkk", "my peniiiiiiiiiis", ICanopyPlatform.NotificationLevel.Warning)));
+ menu.Items.Add(new PopupMenuItem("Dark Theme", (_, _) => canopy.Platform.SetTheme(ICanopyPlatform.Theme.Dark)));
+ menu.Items.Add(new PopupMenuItem("Light Theme", (_, _) => canopy.Platform.SetTheme(ICanopyPlatform.Theme.Light)));
+ menu.Items.Add(new PopupMenuItem("Exit", (_, _) => Environment.Exit(0)));
+ trayIcon.ContextMenu = menu;
+
+ trayIcon.Create();
+
+ while (GetMessage(out MSG msg, IntPtr.Zero) == 1)
+ {
+ while (queue.TryDequeue(out var task))
+ {
+ Log.Information("dequeued");
+ task.Invoke();
+ }
+ TranslateMessage(in msg);
+ DispatchMessage(in msg);
+ }
+ });
+
+ trayThread.SetApartmentState(ApartmentState.STA);
+ trayThread.IsBackground = true;
+ trayThread.Start();
+ }
+
+ public void ShowBalloon(string title, string message, NotificationIcon icon)
+ {
+ queue.Enqueue(() =>
+ {
+ Log.Warning("{title}, {message}, {icon}", title, message, icon);
+ trayIcon.ShowNotification(
+ title: title,
+ message: message,
+ icon: icon
+ );
+ });
+ }
+}
diff --git a/Canopy.Windows/Canopy.Windows.csproj b/Canopy.Windows/Canopy.Windows.csproj
index 179099e..0c80ffb 100644
--- a/Canopy.Windows/Canopy.Windows.csproj
+++ b/Canopy.Windows/Canopy.Windows.csproj
@@ -1,19 +1,31 @@
-
- Exe
- net10.0
- enable
- enable
-
+
+ Exe
+ net10.0
+ enable
+ enable
+ true
-
-
-
+ true
+ true
+ false
+ true
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Canopy.Windows/CanopyPlatformWindows.cs b/Canopy.Windows/CanopyPlatformWindows.cs
index 1170591..592e747 100644
--- a/Canopy.Windows/CanopyPlatformWindows.cs
+++ b/Canopy.Windows/CanopyPlatformWindows.cs
@@ -1,277 +1,133 @@
// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-using Canopy.Graphics;
-using Canopy.Rendering;
-using Canopy.Utils;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Runtime.InteropServices;
+using H.NotifyIcon.Core;
+using Microsoft.Win32;
using Serilog;
using Synesthesia.Utils;
-using SynesthesiaDev.Chibi.Core;
-using SynesthesiaDev.Chibi.Core.Enums;
+using Synesthesia.Utils.Extensions;
using Vanara.PInvoke;
-using WinEventHook;
+using static Vanara.PInvoke.User32;
namespace Canopy.Windows;
public class CanopyPlatformWindows : ICanopyPlatform
{
- public RuntimeInfo.Platform Platform => RuntimeInfo.Platform.Windows;
+ RuntimeInfo.Platform ICanopyPlatform.Platform => RuntimeInfo.Platform.Windows;
+ private const string registry_key_path = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";
- private IntPtr workerW, progman, shellDllDefView, originalWorkerW;
- private bool layeredShellView;
- private WindowEventHook workerWHook = null!;
+ private BackgroundTrayService backgroundTrayService = null!;
- public OpenGLRenderer? OpenGL;
- public ChibiWindow Window = null!;
-
- public readonly WallpaperManager WallpaperManager;
-
- public CanopyPlatformWindows()
- {
- WallpaperManager = new WallpaperManager(this);
- }
-
- public void Initialize()
+ public void SetDesktop(string path)
{
- Window = new ChibiWindow();
+ var useLegacyMethod = Canopy.CurrentConfig.System.UseLegacyWindowsApi;
- Window.OnWindowCreated.Subscribe(_ =>
+ if (useLegacyMethod)
{
- var surface = new Gdi32Surface
+ var tempPath = Path.Combine(Path.GetTempPath(), $"canopy-wallpaper-{Guid.NewGuid().ToString()}.bpm");
+ File.WriteAllBytes(tempPath, convertToBmp(File.ReadAllBytes(path)));
+
+ var result = SystemParametersInfo
+ (
+ SPI.SPI_SETDESKWALLPAPER,
+ 0,
+ tempPath,
+ SPIF.SPIF_UPDATEINIFILE | SPIF.SPIF_SENDWININICHANGE
+ );
+
+ if (!result)
{
- Window = Window,
- Handle = Window.WindowHandle,
- NativeContext = new WindowsGLContext()
- };
-
- surface.InitializeGraphicsContext();
-
- OpenGL = new OpenGLRenderer
- {
- Surface = surface
- };
+ Log.Error("Failed to set wallpaper via legacy windows SystemParametersInfo api");
+ }
- OpenGL.Initialize();
+ File.Delete(tempPath);
- UserLand.EntryPoint(this);
- });
+ return;
+ }
- Window.OnWindowResized.Subscribe(e =>
+ var wallpaper = new Shell32.IDesktopWallpaper();
+ try
{
- OpenGL?.Resize((int)e.Now.X, (int)e.Now.Y);
- });
-
- Window.OnFrame += () =>
+ wallpaper.SetWallpaper(null, path);
+ wallpaper.SetPosition(Shell32.DESKTOP_WALLPAPER_POSITION.DWPOS_FILL);
+ }
+ finally
{
- if (OpenGL == null) return;
-
- OpenGL.BeginDrawing();
- WallpaperManager.Draw(OpenGL);
- OpenGL.EndDrawing();
- };
-
- // Start window hidden and unhide it after the first swap to prevent white flash
- Window.Run(952, 520, WindowFlags.Resizable | WindowFlags.HighPixelDensity | WindowFlags.Hidden);
- }
-
- public void HideWindow() => Window.WindowVisible = false;
- public void ShowWindow() => Window.WindowVisible = true;
-
- public void PushWallpaper(Wallpaper wallpaper)
- {
- WallpaperManager.PushWallpaper(wallpaper);
- // WallpaperManager.Wallpapers.Add(wallpaper);
+ Marshal.ReleaseComObject(wallpaper);
+ }
}
- // !! This is not AI-made, I am just leaving comments here
- // for whoever wants to do this in the future and wants to learn from this source code
- // <3
-
- public void InjectIntoDesktop(IntPtr chibiWindowHandle)
+ public void SetTheme(ICanopyPlatform.Theme theme)
{
- WindowDiagnostics.DumpTree(progman, "BEFORE injection");
-
- Log.Verbose("Creating WorkerW..");
-
- // Find progman
- progman = NativeUtils.GetProgman();
-
- // win 11 has changed how desktop rendering works to allow HDR and stuff like that. Read more below
- // https://github.com/rocksdanister/lively/issues/2074#issuecomment-2030662089
- layeredShellView = NativeUtils.HasExtendedStyle(progman, Native.WindowStyles.WS_EX_NOREDIRECTIONBITMAP);
- if (layeredShellView)
- Log.Information("Detected raised desktop with layered shell view");
-
- // Send timeout with 0x052C to progman. This tells progman to create a new
- // WorkerW window behind the desktop icons
- Native.SendMessageTimeout(
- progman,
- 0x052C,
- new IntPtr(0xD),
- new IntPtr(0x1),
- Native.SendMessageTimeoutFlags.SMTO_NORMAL,
- 1000,
- out _
- );
-
- Native.EnumWindows((handle, _) =>
+ var useLightTheme = (theme == ICanopyPlatform.Theme.Light).ToInt();
+ using (RegistryKey? key = Registry.CurrentUser.OpenSubKey(registry_key_path, true))
{
- var pointer = Native.FindWindowEx(handle, IntPtr.Zero, "SHELLDLL_DefView", IntPtr.Zero);
-
- if (pointer != IntPtr.Zero)
+ if (key != null)
{
- workerW = Native.FindWindowEx(IntPtr.Zero, handle, "WorkerW", IntPtr.Zero);
- shellDllDefView = pointer;
+ key.SetValue("AppsUseLightTheme", useLightTheme, RegistryValueKind.DWord);
+ key.SetValue("SystemUsesLightTheme", useLightTheme, RegistryValueKind.DWord);
}
-
- return true;
- }, IntPtr.Zero);
-
- if (workerW == IntPtr.Zero)
- {
- Log.Error("WorkerW not found after EnumWindows — SHELLDLL_DefView may still be in Progman");
- // Fallback: check directly inside Progman
- shellDllDefView = Native.FindWindowEx(progman, IntPtr.Zero, "SHELLDLL_DefView", IntPtr.Zero);
- workerW = progman; // parent to Progman itself as fallback
}
- if (layeredShellView)
+ unsafe
{
- shellDllDefView = Native.FindWindowEx(progman, IntPtr.Zero, "SHELLDLL_DefView", IntPtr.Zero);
- workerW = Native.FindWindowEx(progman, IntPtr.Zero, "WorkerW", IntPtr.Zero);
- Log.Information("LayeredShell: shellDllDefView={defView}, workerW={workerW}", shellDllDefView, workerW);
- }
-
- originalWorkerW = NativeUtils.GetDesktopWorkerW();
-
- Log.Information("WorkerW created ({workerW})", workerW);
-
- attachWindowToWorkerW(chibiWindowHandle);
-
- WindowDiagnostics.DumpTree(progman, "AFTER injection");
-
- WindowDiagnostics.DumpWindow(chibiWindowHandle, "Chibi Window");
+ nint result = 0;
+ fixed (char* pString = "ImmersiveColorSet")
+ {
+ SendMessageTimeout(
+ HWND.HWND_BROADCAST,
+ (uint)WindowMessage.WM_SETTINGCHANGE,
+ IntPtr.Zero,
+ (IntPtr)pString,
+ SMTO.SMTO_ABORTIFHUNG,
+ 5000,
+ ref result
+ );
+ }
- try
- {
- if (workerW != IntPtr.Zero)
+ fixed (char* pPolicy = "Policy")
{
- Log.Information("Listening to WorkerW events..");
- var dwThreadId = Native.GetWindowThreadProcessId(workerW, out int dwProcess);
- workerWHook = new WindowEventHook(WindowEvent.EVENT_OBJECT_DESTROY);
- workerWHook.HookToThread(dwThreadId);
- workerWHook.EventReceived += WorkerWHook_EventReceived;
+ SendMessageTimeout(
+ HWND.HWND_BROADCAST,
+ (uint)WindowMessage.WM_SETTINGCHANGE,
+ IntPtr.Zero,
+ (IntPtr)pPolicy,
+ SMTO.SMTO_ABORTIFHUNG,
+ 5000,
+ ref result
+ );
}
}
- catch (Exception e)
- {
- Console.WriteLine(e);
- throw;
- }
}
-
- private async void WorkerWHook_EventReceived(object? _, WinEventHookEventArgs e)
+ public void InitializeTray(Canopy canopy)
{
- if (e.WindowHandle != workerW || e.EventType != WindowEvent.EVENT_OBJECT_DESTROY)
- return;
-
- Log.Error("WorkerW died");
-
- if (layeredShellView)
- {
- InjectIntoDesktop(Window.WindowHandle);
-
- // var windowFlags = (int)(Native.SetWindowPosFlags.SWP_NOMOVE |
- // Native.SetWindowPosFlags.SWP_NOSIZE |
- // Native.SetWindowPosFlags.SWP_NOACTIVATE);
-
- // foreach (var item in wallpapers) //only have one, later
- // {
- // NativeMethods.SetWindowPos(item.Handle,
- // (int)shellDLL_DefView,
- // 0,
- // 0,
- // 0,
- // 0,
- // windowFlags);
- // }
-
- ensureWorkerWzOrder();
- }
- else
- {
- //reset wallpaper?
- // what does that mean in lively? creating the window again? Is each wallpaper different window? thats janky
- }
+ backgroundTrayService = new BackgroundTrayService(canopy);
+ backgroundTrayService.Start();
}
- private void attachWindowToWorkerW(IntPtr sdlWindowHandle)
-{
- var styleFlags = User32.GetWindowLong(sdlWindowHandle, User32.WindowLongFlags.GWL_STYLE);
-
- styleFlags &= (int)~(User32.WindowStyles.WS_POPUP | User32.WindowStyles.WS_CAPTION | User32.WindowStyles.WS_THICKFRAME | User32.WindowStyles.WS_MINIMIZEBOX | User32.WindowStyles.WS_MAXIMIZEBOX);
- styleFlags |= (int)(User32.WindowStyles.WS_CHILD |
- User32.WindowStyles.WS_CLIPSIBLINGS |
- User32.WindowStyles.WS_CLIPCHILDREN);
-
- User32.SetWindowLong(sdlWindowHandle, User32.WindowLongFlags.GWL_STYLE, styleFlags);
-
- User32.SetWindowPos(sdlWindowHandle, 0, 0, 0, 0, 0,
- User32.SetWindowPosFlags.SWP_NOMOVE | User32.SetWindowPosFlags.SWP_NOSIZE |
- User32.SetWindowPosFlags.SWP_NOZORDER | User32.SetWindowPosFlags.SWP_FRAMECHANGED);
-
- var parent = layeredShellView ? progman : workerW;
- Native.SetParent(sdlWindowHandle, parent);
-
- Native.GetWindowRect(parent, out Native.RECT prct);
-
- var windowFlags = (int)(
- Native.SetWindowPosFlags.SWP_NOACTIVATE |
- Native.SetWindowPosFlags.SWP_SHOWWINDOW
- );
-
- if (layeredShellView && shellDllDefView != IntPtr.Zero)
- {
- // put window below the icon layer in Z-order (siblings under Progman)
- Native.SetWindowPos(
- sdlWindowHandle,
- (int)shellDllDefView, // insert AFTER
- 0, 0,
- prct.Right - prct.Left,
- prct.Bottom - prct.Top,
- windowFlags
- );
- }
- else
+ public void ShowNotification(string title, string message, ICanopyPlatform.NotificationLevel level = ICanopyPlatform.NotificationLevel.Info)
{
- Native.SetWindowPos(
- sdlWindowHandle,
- (int)Native.HWNDInsertAfter.HWND_TOP,
- 0, 0,
- prct.Right - prct.Left,
- prct.Bottom - prct.Top,
- windowFlags
- );
- }
+ var icon = level switch
+ {
+ ICanopyPlatform.NotificationLevel.Info => NotificationIcon.Info,
+ ICanopyPlatform.NotificationLevel.Warning => NotificationIcon.Warning,
+ ICanopyPlatform.NotificationLevel.Error => NotificationIcon.Error,
+ _ => throw new ArgumentOutOfRangeException(nameof(level), level, null)
+ };
- ensureWorkerWzOrder();
- Log.Information("Wallpaper attached (parent={parent}, layered={layered})", parent, layeredShellView);
-}
+ backgroundTrayService.ShowBalloon(title, message, icon);
+ }
- private void ensureWorkerWzOrder()
+ private static byte[] convertToBmp(byte[] sourceImageBytes)
{
- if (!layeredShellView) return;
- if (shellDllDefView == IntPtr.Zero || Window.WindowHandle == IntPtr.Zero) return;
-
- var windowFlags = (int)(Native.SetWindowPosFlags.SWP_NOMOVE
- | Native.SetWindowPosFlags.SWP_NOSIZE
- | Native.SetWindowPosFlags.SWP_NOACTIVATE);
-
- //window below icons, as a sibling under Progman
- Native.SetWindowPos(Window.WindowHandle, (int)shellDllDefView, 0, 0, 0, 0, windowFlags);
- Log.Information("Z-order re-asserted: SDL window below shellDllDefView");
+ using var inputStream = new MemoryStream(sourceImageBytes);
+ using var bitmap = new Bitmap(inputStream);
+ using var outputStream = new MemoryStream();
+ bitmap.Save(outputStream, ImageFormat.Bmp);
+ return outputStream.ToArray();
}
-
- // FUCKKK
}
diff --git a/Canopy.Windows/Gdi32Surface.cs b/Canopy.Windows/Gdi32Surface.cs
deleted file mode 100644
index ec17d08..0000000
--- a/Canopy.Windows/Gdi32Surface.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using System.Numerics;
-using System.Runtime.InteropServices;
-using Canopy.Rendering;
-using SynesthesiaDev.Chibi.Core;
-using Vanara.PInvoke;
-using static Vanara.PInvoke.Gdi32;
-using static Vanara.PInvoke.User32;
-
-namespace Canopy.Windows;
-
-public class Gdi32Surface : IWindowSurface
-{
- public required ChibiWindow Window { get; init; }
- public required IntPtr Handle { get; init; }
- public required INativeContext NativeContext { get; init; }
-
- private IntPtr hglrc = IntPtr.Zero;
- private SafeReleaseHDC hdc = SafeReleaseHDC.Null;
-
- public Vector2 GetScreenSize() => Window.ScreenResolution;
-
- public void SwapBuffers()
- {
- if (!hdc.IsInvalid)
- {
- Gdi32.SwapBuffers(hdc);
- }
- }
-
- public void InitializeGraphicsContext()
- {
- hdc = GetDC(Handle);
- if (hdc == IntPtr.Zero) throw new InvalidOperationException("Failed to get Device Context (HDC)");
-
- var pfd = new PIXELFORMATDESCRIPTOR();
- pfd.nSize = (ushort)Marshal.SizeOf(pfd);
- pfd.nVersion = 1;
- pfd.dwFlags = PFD_FLAGS.PFD_DRAW_TO_WINDOW | PFD_FLAGS.PFD_SUPPORT_OPENGL | PFD_FLAGS.PFD_DOUBLEBUFFER;
- pfd.iPixelType = PFD_TYPE.PFD_TYPE_RGBA;
- pfd.cColorBits = 32;
- pfd.cDepthBits = 24;
- pfd.cStencilBits = 8;
-
- var pixelFormat = ChoosePixelFormat(hdc, in pfd);
- if (pixelFormat == 0) throw new InvalidOperationException("Failed to choose suitable pixel format");
-
- if (!SetPixelFormat(hdc, pixelFormat, in pfd))
- throw new InvalidOperationException("Failed to set pixel format on HDC");
-
- hglrc = wglCreateContext(hdc.DangerousGetHandle());
- if (hglrc == IntPtr.Zero) throw new InvalidOperationException("Failed to create wgl context");
-
- if (!wglMakeCurrent(hdc.DangerousGetHandle(), hglrc))
- throw new InvalidOperationException("Failed to make WGL context current");
-
- }
-
- [DllImport("opengl32.dll")]
- private static extern IntPtr wglCreateContext(IntPtr hdc);
-
- [DllImport("opengl32.dll")]
- private static extern bool wglMakeCurrent(IntPtr hdc, IntPtr hglrc);
-
- [DllImport("opengl32.dll")]
- private static extern bool wglDeleteContext(IntPtr hglrc);
-
- public void Dispose()
- {
- wglMakeCurrent(IntPtr.Zero, IntPtr.Zero);
-
- if (hglrc != IntPtr.Zero)
- {
- wglDeleteContext(hglrc);
- hglrc = IntPtr.Zero;
- }
-
- if (!hdc.IsInvalid)
- {
- ReleaseDC(Handle, hdc);
- hdc.Dispose();
- }
- }
-}
diff --git a/Canopy.Windows/Native.cs b/Canopy.Windows/Native.cs
deleted file mode 100644
index 14ef189..0000000
--- a/Canopy.Windows/Native.cs
+++ /dev/null
@@ -1,4584 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-namespace Canopy.Windows;
-
-using Microsoft.Win32.SafeHandles;
-using System;
-using System.ComponentModel;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using System.Text;
-
-#pragma warning disable CA1707, CA1401, CA1712
-public static class Native
-{
- [DllImport("shell32.dll", CharSet = CharSet.Auto)]
- public static extern uint ExtractIconEx(string szFileName, int nIconIndex, IntPtr[] phiconLarge, IntPtr[] phiconSmall, uint nIcons);
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern bool DestroyIcon(IntPtr hIcon);
-
- [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
- public static extern int GetCurrentPackageFullName(ref int packageFullNameLength, StringBuilder packageFullName);
-
- [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- public static extern uint GetFinalPathNameByHandle(
- SafeFileHandle hFile,
- StringBuilder lpszFilePath,
- uint cchFilePath,
- uint dwFlags);
-
- [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- public static extern SafeFileHandle CreateFile(
- string lpFileName,
- uint dwDesiredAccess,
- uint dwShareMode,
- IntPtr lpSecurityAttributes,
- uint dwCreationDisposition,
- uint dwFlagsAndAttributes,
- IntPtr hTemplateFile);
-
- [DllImport("user32.dll")]
- public static extern IntPtr GetThreadDpiAwarenessContext();
-
- [DllImport("user32.dll")]
- public static extern DPI_AWARENESS GetAwarenessFromDpiAwarenessContext(IntPtr dpiContext);
-
- public enum DPI_AWARENESS
- {
- DPI_UNAWARE = 0,
- SYSTEM_AWARE = 1,
- PER_MONITOR_AWARE = 2
- }
-
- public enum MonitorDpiType
- {
- MDT_Effective_DPI = 0,
- MDT_Angular_DPI = 1,
- MDT_Raw_DPI = 2,
- MDT_Default = MDT_Effective_DPI
- }
-
- [DllImport("Shcore.dll")]
- public static extern int GetDpiForMonitor(IntPtr hmonitor, MonitorDpiType dpiType, out uint dpiX, out uint dpiY);
-
- public enum GetAncestorFlags
- {
- ///
- /// Retrieves the parent window. This does not include the owner, as it does with the GetParent function.
- ///
- GetParent = 1,
-
- ///
- /// Retrieves the root window by walking the chain of parent windows.
- ///
- GetRoot = 2,
-
- ///
- /// Retrieves the owned root window by walking the chain of parent and owner windows returned by GetParent.
- ///
- GetRootOwner = 3
- }
-
- [DllImport("user32.dll", ExactSpelling = true)]
- public static extern IntPtr GetAncestor(IntPtr hwnd, GetAncestorFlags flags);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern bool QueryFullProcessImageName([In] IntPtr hProcess, [In] int dwFlags, [Out] StringBuilder lpExeName, ref int lpdwSize);
-
- [DllImport("dwmapi.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
- public static extern void DwmSetWindowAttribute(IntPtr hwnd,
- DWMWINDOWATTRIBUTE attribute,
- ref DWM_WINDOW_CORNER_PREFERENCE pvAttribute,
- uint cbAttribute);
-
- [DllImport("dwmapi.dll")]
- public static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out int pvAttribute, int cbAttribute);
-
- public enum DWMWINDOWATTRIBUTE
- {
- NCRenderingEnabled = 1,
- NCRenderingPolicy,
- TransitionsForceDisabled,
- AllowNCPaint,
- CaptionButtonBounds,
- NonClientRtlLayout,
- ForceIconicRepresentation,
- Flip3DPolicy,
- ExtendedFrameBounds,
- HasIconicBitmap,
- DisallowPeek,
- ExcludedFromPeek,
- Cloak,
- Cloaked,
- FreezeRepresentation,
- PassiveUpdateMode,
- UseHostBackdropBrush,
- UseImmersiveDarkMode = 20,
- WindowCornerPreference = 33,
- BorderColor,
- CaptionColor,
- TextColor,
- VisibleFrameBorderThickness,
- Last
- }
-
- public enum DWM_WINDOW_CORNER_PREFERENCE
- {
- DWMWCP_DEFAULT = 0,
- DWMWCP_DONOTROUND = 1,
- DWMWCP_ROUND = 2,
- DWMWCP_ROUNDSMALL = 3
- }
-
- [DllImport("dwmapi.dll")]
- public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
-
- public const int DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19;
- public const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
-
- [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- public static extern IntPtr LoadImage(IntPtr hinst, string lpszName, uint uType,
- int cxDesired, int cyDesired, uint fuLoad);
-
- [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);
-
- [DllImport("User32")]
- public static extern int GetDpiForWindow(IntPtr hwnd);
-
- #region screensaver
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern bool LockWorkStation();
-
-
- [DllImport("User32.dll")]
- public static extern bool SetCursorPos(int X, int Y);
-
- [DllImport("user32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool GetCursorPos(out POINT lpPoint);
-
- public enum QUERY_USER_NOTIFICATION_STATE
- {
- QUNS_NOT_PRESENT = 1,
- QUNS_BUSY = 2,
- QUNS_RUNNING_D3D_FULL_SCREEN = 3,
- QUNS_PRESENTATION_MODE = 4,
- QUNS_ACCEPTS_NOTIFICATIONS = 5,
- QUNS_QUIET_TIME = 6
- };
-
- [DllImport("shell32.dll")]
- public static extern int SHQueryUserNotificationState(out QUERY_USER_NOTIFICATION_STATE pquns);
-
- #endregion //screensaver
-
- #region undocumented
-
- //undocumented, may get removed/changed in the future.
-
- [DllImport("ntdll.dll", PreserveSig = false)]
- public static extern void NtSuspendProcess(IntPtr processHandle);
-
- [DllImport("ntdll.dll", PreserveSig = false, SetLastError = true)]
- public static extern void NtResumeProcess(IntPtr processHandle);
-
- #endregion //undocumented
-
- #region gdi
-
- ///
- /// Specifies a raster-operation code. These codes define how the color data for the
- /// source rectangle is to be combined with the color data for the destination
- /// rectangle to achieve the final color.
- ///
- public enum TernaryRasterOperations : uint
- {
- /// dest = source
- SRCCOPY = 0x00CC0020,
-
- /// dest = source OR dest
- SRCPAINT = 0x00EE0086,
-
- /// dest = source AND dest
- SRCAND = 0x008800C6,
-
- /// dest = source XOR dest
- SRCINVERT = 0x00660046,
-
- /// dest = source AND (NOT dest)
- SRCERASE = 0x00440328,
-
- /// dest = (NOT source)
- NOTSRCCOPY = 0x00330008,
-
- /// dest = (NOT src) AND (NOT dest)
- NOTSRCERASE = 0x001100A6,
-
- /// dest = (source AND pattern)
- MERGECOPY = 0x00C000CA,
-
- /// dest = (NOT source) OR dest
- MERGEPAINT = 0x00BB0226,
-
- /// dest = pattern
- PATCOPY = 0x00F00021,
-
- /// dest = DPSnoo
- PATPAINT = 0x00FB0A09,
-
- /// dest = pattern XOR dest
- PATINVERT = 0x005A0049,
-
- /// dest = (NOT dest)
- DSTINVERT = 0x00550009,
-
- /// dest = BLACK
- BLACKNESS = 0x00000042,
-
- /// dest = WHITE
- WHITENESS = 0x00FF0062,
-
- ///
- /// Capture window as seen on screen. This includes layered windows
- /// such as WPF windows with AllowsTransparency="true"
- ///
- CAPTUREBLT = 0x40000000
- }
-
- ///
- /// Performs a bit-block transfer of the color data corresponding to a
- /// rectangle of pixels from the specified source device context into
- /// a destination device context.
- ///
- /// Handle to the destination device context.
- /// The leftmost x-coordinate of the destination rectangle (in pixels).
- /// The topmost y-coordinate of the destination rectangle (in pixels).
- /// The width of the source and destination rectangles (in pixels).
- /// The height of the source and the destination rectangles (in pixels).
- /// Handle to the source device context.
- /// The leftmost x-coordinate of the source rectangle (in pixels).
- /// The topmost y-coordinate of the source rectangle (in pixels).
- /// A raster-operation code.
- ///
- /// true if the operation succeedes, false otherwise. To get extended error information, call .
- ///
- [DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool BitBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, [In] IntPtr hdcSrc, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
-
- ///
- /// Creates a bitmap compatible with the device that is associated with the specified device context.
- ///
- /// A handle to a device context.
- /// The bitmap width, in pixels.
- /// The bitmap height, in pixels.
- /// If the function succeeds, the return value is a handle to the compatible bitmap (DDB). If the function fails, the return value is .
- [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleBitmap")]
- public static extern IntPtr CreateCompatibleBitmap([In] IntPtr hdc, int nWidth, int nHeight);
-
- /// Deletes the specified device context (DC).
- /// A handle to the device context.
- /// If the function succeeds, the return value is nonzero.If the function fails, the return value is zero.
- /// An application must not delete a DC whose handle was obtained by calling the GetDC function. Instead, it must call the ReleaseDC function to free the DC.
- [DllImport("gdi32.dll", EntryPoint = "DeleteDC")]
- public static extern bool DeleteDC([In] IntPtr hdc);
-
- /// Selects an object into the specified device context (DC). The new object replaces the previous object of the same type.
- /// A handle to the DC.
- /// A handle to the object to be selected.
- ///
- /// If the selected object is not a region and the function succeeds, the return value is a handle to the object being replaced. If the selected object is a region and the function succeeds, the return value is one of the following values.
- /// SIMPLEREGION - Region consists of a single rectangle.
- /// COMPLEXREGION - Region consists of more than one rectangle.
- /// NULLREGION - Region is empty.
- /// If an error occurs and the selected object is not a region, the return value is NULL. Otherwise, it is HGDI_ERROR.
- ///
- ///
- /// This function returns the previously selected object of the specified type. An application should always replace a new object with the original, default object after it has finished drawing with the new object.
- /// An application cannot select a single bitmap into more than one DC at a time.
- /// ICM: If the object being selected is a brush or a pen, color management is performed.
- ///
- [DllImport("gdi32.dll", EntryPoint = "SelectObject")]
- public static extern IntPtr SelectObject([In] IntPtr hdc, [In] IntPtr hgdiobj);
-
- ///
- /// Creates a memory device context (DC) compatible with the specified device.
- ///
- /// A handle to an existing DC. If this handle is NULL,
- /// the function creates a memory DC compatible with the application's current screen.
- ///
- /// If the function succeeds, the return value is the handle to a memory DC.
- /// If the function fails, the return value is .
- ///
- [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleDC", SetLastError = true)]
- public static extern IntPtr CreateCompatibleDC([In] IntPtr hdc);
-
- [DllImport("gdi32.dll")]
- public static extern bool DeleteObject(IntPtr hObject);
-
- [DllImport("gdi32.dll")]
- public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
-
- [DllImport("gdi32.dll", SetLastError = true)]
- public static extern uint GetPixel(IntPtr dc, int x, int y);
-
- #endregion //gdi
-
- #region life cycle
-
- public const int HWND_BROADCAST = 0xffff;
-
- [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
- public static extern System.IntPtr GetCommandLine();
-
- [DllImport("user32")]
- public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
-
- [DllImport("user32")]
- public static extern int RegisterWindowMessage(string message);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern int RegisterApplicationRestart([MarshalAs(UnmanagedType.LPWStr)] string commandLineArgs, int Flags);
-
- [Flags]
- public enum RestartFlags
- {
- ///
- /// No restart restrictions
- ///
- NONE = 0,
-
- ///
- /// Do not restart if process terminates due to unhandled exception
- ///
- RESTART_NO_CRASH = 1,
-
- ///
- /// Do not restart if process terminates due to application not responding
- ///
- RESTART_NO_HANG = 2,
-
- ///
- /// Do not restart if process terminates due to installation of update
- ///
- RESTART_NO_PATCH = 4,
-
- ///
- /// Do not restart if process terminates due to computer restart as result of an update
- ///
- RESTART_NO_REBOOT = 8
- }
-
- #endregion // life cycle
-
- public delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam);
-
- [DllImport("user32")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);
-
- [DllImport("user32.dll")]
- public static extern IntPtr GetWindowDC(IntPtr hWnd);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern bool DebugActiveProcess(uint dwProcessId);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern bool DebugActiveProcessStop(uint dwProcessId);
-
- public const int BM_CLICK = 0x00F5; //left-click
-
- [DllImport("user32.dll")]
- public static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
-
- [StructLayout(LayoutKind.Sequential)]
- public struct LASTINPUTINFO
- {
- public static readonly int SizeOf = Marshal.SizeOf(typeof(LASTINPUTINFO));
-
- [MarshalAs(UnmanagedType.U4)]
- public UInt32 cbSize;
-
- [MarshalAs(UnmanagedType.U4)]
- public UInt32 dwTime;
- }
-
- [DllImport("user32.dll")]
- public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
-
- [DllImport("user32.dll")]
- public static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
-
-
- [DllImport("user32.dll")]
- public static extern int GetClassName(int hWnd, StringBuilder lpClassName, int nMaxCount);
-
- #region windows message
-
- public enum SHOWWINDOW : uint
- {
- SW_HIDE = 0,
- SW_SHOWNORMAL = 1,
- SW_NORMAL = 1,
- SW_SHOWMINIMIZED = 2,
- SW_SHOWMAXIMIZED = 3,
- SW_MAXIMIZE = 3,
- SW_SHOWNOACTIVATE = 4,
- SW_SHOW = 5,
- SW_MINIMIZE = 6,
- SW_SHOWMINNOACTIVE = 7,
- SW_SHOWNA = 8,
- SW_RESTORE = 9,
- SW_SHOWDEFAULT = 10,
- SW_FORCEMINIMIZE = 11,
- SW_MAX = 11,
- }
-
- [return: MarshalAs(UnmanagedType.Bool)]
- [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- public static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
-
- [DllImport("User32.dll", EntryPoint = "PostMessageW", CallingConvention = CallingConvention.Winapi
- , CharSet = CharSet.Unicode)]
- public extern static IntPtr PostMessageW(IntPtr hWnd, Int32 Msg, IntPtr wParam, IntPtr lParam);
-
- [DllImport("User32.dll", EntryPoint = "PostMessageW", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode)]
- public extern static IntPtr PostMessageW(IntPtr hWnd, Int32 Msg, IntPtr wParam, UIntPtr lParam);
-
- ///
- /// Windows Messages
- /// Defined in winuser.h from Windows SDK v6.1
- /// Documentation pulled from MSDN.
- ///
- public enum WM : uint
- {
- ///
- /// The WM_NULL message performs no operation. An application sends the WM_NULL message if it wants to post a message that the recipient window will ignore.
- ///
- NULL = 0x0000,
-
- ///
- /// The WM_CREATE message is sent when an application requests that a window be created by calling the CreateWindowEx or CreateWindow function. (The message is sent before the function returns.) The window procedure of the new window receives this message after the window is created, but before the window becomes visible.
- ///
- CREATE = 0x0001,
-
- ///
- /// The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window procedure of the window being destroyed after the window is removed from the screen.
- /// This message is sent first to the window being destroyed and then to the child windows (if any) as they are destroyed. During the processing of the message, it can be assumed that all child windows still exist.
- /// ///
- DESTROY = 0x0002,
-
- ///
- /// The WM_MOVE message is sent after a window has been moved.
- ///
- MOVE = 0x0003,
-
- ///
- /// The WM_SIZE message is sent to a window after its size has changed.
- ///
- SIZE = 0x0005,
-
- ///
- /// The WM_ACTIVATE message is sent to both the window being activated and the window being deactivated. If the windows use the same input queue, the message is sent synchronously, first to the window procedure of the top-level window being deactivated, then to the window procedure of the top-level window being activated. If the windows use different input queues, the message is sent asynchronously, so the window is activated immediately.
- ///
- ACTIVATE = 0x0006,
-
- ///
- /// The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus.
- ///
- SETFOCUS = 0x0007,
-
- ///
- /// The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus.
- ///
- KILLFOCUS = 0x0008,
-
- ///
- /// The WM_ENABLE message is sent when an application changes the enabled state of a window. It is sent to the window whose enabled state is changing. This message is sent before the EnableWindow function returns, but after the enabled state (WS_DISABLED style bit) of the window has changed.
- ///
- ENABLE = 0x000A,
-
- ///
- /// An application sends the WM_SETREDRAW message to a window to allow changes in that window to be redrawn or to prevent changes in that window from being redrawn.
- ///
- SETREDRAW = 0x000B,
-
- ///
- /// An application sends a WM_SETTEXT message to set the text of a window.
- ///
- SETTEXT = 0x000C,
-
- ///
- /// An application sends a WM_GETTEXT message to copy the text that corresponds to a window into a buffer provided by the caller.
- ///
- GETTEXT = 0x000D,
-
- ///
- /// An application sends a WM_GETTEXTLENGTH message to determine the length, in characters, of the text associated with a window.
- ///
- GETTEXTLENGTH = 0x000E,
-
- ///
- /// The WM_PAINT message is sent when the system or another application makes a request to paint a portion of an application's window. The message is sent when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage function when the application obtains a WM_PAINT message by using the GetMessage or PeekMessage function.
- ///
- PAINT = 0x000F,
-
- ///
- /// The WM_CLOSE message is sent as a signal that a window or an application should terminate.
- ///
- CLOSE = 0x0010,
-
- ///
- /// The WM_QUERYENDSESSION message is sent when the user chooses to end the session or when an application calls one of the system shutdown functions. If any application returns zero, the session is not ended. The system stops sending WM_QUERYENDSESSION messages as soon as one application returns zero.
- /// After processing this message, the system sends the WM_ENDSESSION message with the wParam parameter set to the results of the WM_QUERYENDSESSION message.
- ///
- QUERYENDSESSION = 0x0011,
-
- ///
- /// The WM_QUERYOPEN message is sent to an icon when the user requests that the window be restored to its previous size and position.
- ///
- QUERYOPEN = 0x0013,
-
- ///
- /// The WM_ENDSESSION message is sent to an application after the system processes the results of the WM_QUERYENDSESSION message. The WM_ENDSESSION message informs the application whether the session is ending.
- ///
- ENDSESSION = 0x0016,
-
- ///
- /// The WM_QUIT message indicates a request to terminate an application and is generated when the application calls the PostQuitMessage function. It causes the GetMessage function to return zero.
- ///
- QUIT = 0x0012,
-
- ///
- /// The WM_ERASEBKGND message is sent when the window background must be erased (for example, when a window is resized). The message is sent to prepare an invalidated portion of a window for painting.
- ///
- ERASEBKGND = 0x0014,
-
- ///
- /// This message is sent to all top-level windows when a change is made to a system color setting.
- ///
- SYSCOLORCHANGE = 0x0015,
-
- ///
- /// The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown.
- ///
- SHOWWINDOW = 0x0018,
-
- ///
- /// An application sends the WM_WININICHANGE message to all top-level windows after making a change to the WIN.INI file. The SystemParametersInfo function sends this message after an application uses the function to change a setting in WIN.INI.
- /// Note The WM_WININICHANGE message is provided only for compatibility with earlier versions of the system. Applications should use the WM_SETTINGCHANGE message.
- ///
- WININICHANGE = 0x001A,
-
- ///
- /// An application sends the WM_WININICHANGE message to all top-level windows after making a change to the WIN.INI file. The SystemParametersInfo function sends this message after an application uses the function to change a setting in WIN.INI.
- /// Note The WM_WININICHANGE message is provided only for compatibility with earlier versions of the system. Applications should use the WM_SETTINGCHANGE message.
- ///
- SETTINGCHANGE = WININICHANGE,
-
- ///
- /// The WM_DEVMODECHANGE message is sent to all top-level windows whenever the user changes device-mode settings.
- ///
- DEVMODECHANGE = 0x001B,
-
- ///
- /// The WM_ACTIVATEAPP message is sent when a window belonging to a different application than the active window is about to be activated. The message is sent to the application whose window is being activated and to the application whose window is being deactivated.
- ///
- ACTIVATEAPP = 0x001C,
-
- ///
- /// An application sends the WM_FONTCHANGE message to all top-level windows in the system after changing the pool of font resources.
- ///
- FONTCHANGE = 0x001D,
-
- ///
- /// A message that is sent whenever there is a change in the system time.
- ///
- TIMECHANGE = 0x001E,
-
- ///
- /// The WM_CANCELMODE message is sent to cancel certain modes, such as mouse capture. For example, the system sends this message to the active window when a dialog box or message box is displayed. Certain functions also send this message explicitly to the specified window regardless of whether it is the active window. For example, the EnableWindow function sends this message when disabling the specified window.
- ///
- CANCELMODE = 0x001F,
-
- ///
- /// The WM_SETCURSOR message is sent to a window if the mouse causes the cursor to move within a window and mouse input is not captured.
- ///
- SETCURSOR = 0x0020,
-
- ///
- /// The WM_MOUSEACTIVATE message is sent when the cursor is in an inactive window and the user presses a mouse button. The parent window receives this message only if the child window passes it to the DefWindowProc function.
- ///
- MOUSEACTIVATE = 0x0021,
-
- ///
- /// The WM_CHILDACTIVATE message is sent to a child window when the user clicks the window's title bar or when the window is activated, moved, or sized.
- ///
- CHILDACTIVATE = 0x0022,
-
- ///
- /// The WM_QUEUESYNC message is sent by a computer-based training (CBT) application to separate user-input messages from other messages sent through the WH_JOURNALPLAYBACK Hook procedure.
- ///
- QUEUESYNC = 0x0023,
-
- ///
- /// The WM_GETMINMAXINFO message is sent to a window when the size or position of the window is about to change. An application can use this message to override the window's default maximized size and position, or its default minimum or maximum tracking size.
- ///
- GETMINMAXINFO = 0x0024,
-
- ///
- /// Windows NT 3.51 and earlier: The WM_PAINTICON message is sent to a minimized window when the icon is to be painted. This message is not sent by newer versions of Microsoft Windows, except in unusual circumstances explained in the Remarks.
- ///
- PAINTICON = 0x0026,
-
- ///
- /// Windows NT 3.51 and earlier: The WM_ICONERASEBKGND message is sent to a minimized window when the background of the icon must be filled before painting the icon. A window receives this message only if a class icon is defined for the window; otherwise, WM_ERASEBKGND is sent. This message is not sent by newer versions of Windows.
- ///
- ICONERASEBKGND = 0x0027,
-
- ///
- /// The WM_NEXTDLGCTL message is sent to a dialog box procedure to set the keyboard focus to a different control in the dialog box.
- ///
- NEXTDLGCTL = 0x0028,
-
- ///
- /// The WM_SPOOLERSTATUS message is sent from Print Manager whenever a job is added to or removed from the Print Manager queue.
- ///
- SPOOLERSTATUS = 0x002A,
-
- ///
- /// The WM_DRAWITEM message is sent to the parent window of an owner-drawn button, combo box, list box, or menu when a visual aspect of the button, combo box, list box, or menu has changed.
- ///
- DRAWITEM = 0x002B,
-
- ///
- /// The WM_MEASUREITEM message is sent to the owner window of a combo box, list box, list view control, or menu item when the control or menu is created.
- ///
- MEASUREITEM = 0x002C,
-
- ///
- /// Sent to the owner of a list box or combo box when the list box or combo box is destroyed or when items are removed by the LB_DELETESTRING, LB_RESETCONTENT, CB_DELETESTRING, or CB_RESETCONTENT message. The system sends a WM_DELETEITEM message for each deleted item. The system sends the WM_DELETEITEM message for any deleted list box or combo box item with nonzero item data.
- ///
- DELETEITEM = 0x002D,
-
- ///
- /// Sent by a list box with the LBS_WANTKEYBOARDINPUT style to its owner in response to a WM_KEYDOWN message.
- ///
- VKEYTOITEM = 0x002E,
-
- ///
- /// Sent by a list box with the LBS_WANTKEYBOARDINPUT style to its owner in response to a WM_CHAR message.
- ///
- CHARTOITEM = 0x002F,
-
- ///
- /// An application sends a WM_SETFONT message to specify the font that a control is to use when drawing text.
- ///
- SETFONT = 0x0030,
-
- ///
- /// An application sends a WM_GETFONT message to a control to retrieve the font with which the control is currently drawing its text.
- ///
- GETFONT = 0x0031,
-
- ///
- /// An application sends a WM_SETHOTKEY message to a window to associate a hot key with the window. When the user presses the hot key, the system activates the window.
- ///
- SETHOTKEY = 0x0032,
-
- ///
- /// An application sends a WM_GETHOTKEY message to determine the hot key associated with a window.
- ///
- GETHOTKEY = 0x0033,
-
- ///
- /// The WM_QUERYDRAGICON message is sent to a minimized (iconic) window. The window is about to be dragged by the user but does not have an icon defined for its class. An application can return a handle to an icon or cursor. The system displays this cursor or icon while the user drags the icon.
- ///
- QUERYDRAGICON = 0x0037,
-
- ///
- /// The system sends the WM_COMPAREITEM message to determine the relative position of a new item in the sorted list of an owner-drawn combo box or list box. Whenever the application adds a new item, the system sends this message to the owner of a combo box or list box created with the CBS_SORT or LBS_SORT style.
- ///
- COMPAREITEM = 0x0039,
-
- ///
- /// Active Accessibility sends the WM_GETOBJECT message to obtain information about an accessible object contained in a server application.
- /// Applications never send this message directly. It is sent only by Active Accessibility in response to calls to AccessibleObjectFromPoint, AccessibleObjectFromEvent, or AccessibleObjectFromWindow. However, server applications handle this message.
- ///
- GETOBJECT = 0x003D,
-
- ///
- /// The WM_COMPACTING message is sent to all top-level windows when the system detects more than 12.5 percent of system time over a 30- to 60-second interval is being spent compacting memory. This indicates that system memory is low.
- ///
- COMPACTING = 0x0041,
-
- ///
- /// WM_COMMNOTIFY is Obsolete for Win32-Based Applications
- ///
- [Obsolete]
- COMMNOTIFY = 0x0044,
-
- ///
- /// The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in the Z order is about to change as a result of a call to the SetWindowPos function or another window-management function.
- ///
- WINDOWPOSCHANGING = 0x0046,
-
- ///
- /// The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place in the Z order has changed as a result of a call to the SetWindowPos function or another window-management function.
- ///
- WINDOWPOSCHANGED = 0x0047,
-
- ///
- /// Notifies applications that the system, typically a battery-powered personal computer, is about to enter a suspended mode.
- /// Use: POWERBROADCAST
- ///
- [Obsolete]
- POWER = 0x0048,
-
- ///
- /// An application sends the WM_COPYDATA message to pass data to another application.
- ///
- COPYDATA = 0x004A,
-
- ///
- /// The WM_CANCELJOURNAL message is posted to an application when a user cancels the application's journaling activities. The message is posted with a NULL window handle.
- ///
- CANCELJOURNAL = 0x004B,
-
- ///
- /// Sent by a common control to its parent window when an event has occurred or the control requires some information.
- ///
- NOTIFY = 0x004E,
-
- ///
- /// The WM_INPUTLANGCHANGEREQUEST message is posted to the window with the focus when the user chooses a new input language, either with the hotkey (specified in the Keyboard control panel application) or from the indicator on the system taskbar. An application can accept the change by passing the message to the DefWindowProc function or reject the change (and prevent it from taking place) by returning immediately.
- ///
- INPUTLANGCHANGEREQUEST = 0x0050,
-
- ///
- /// The WM_INPUTLANGCHANGE message is sent to the topmost affected window after an application's input language has been changed. You should make any application-specific settings and pass the message to the DefWindowProc function, which passes the message to all first-level child windows. These child windows can pass the message to DefWindowProc to have it pass the message to their child windows, and so on.
- ///
- INPUTLANGCHANGE = 0x0051,
-
- ///
- /// Sent to an application that has initiated a training card with Microsoft Windows Help. The message informs the application when the user clicks an authorable button. An application initiates a training card by specifying the HELP_TCARD command in a call to the WinHelp function.
- ///
- TCARD = 0x0052,
-
- ///
- /// Indicates that the user pressed the F1 key. If a menu is active when F1 is pressed, WM_HELP is sent to the window associated with the menu; otherwise, WM_HELP is sent to the window that has the keyboard focus. If no window has the keyboard focus, WM_HELP is sent to the currently active window.
- ///
- HELP = 0x0053,
-
- ///
- /// The WM_USERCHANGED message is sent to all windows after the user has logged on or off. When the user logs on or off, the system updates the user-specific settings. The system sends this message immediately after updating the settings.
- ///
- USERCHANGED = 0x0054,
-
- ///
- /// Determines if a window accepts ANSI or Unicode structures in the WM_NOTIFY notification message. WM_NOTIFYFORMAT messages are sent from a common control to its parent window and from the parent window to the common control.
- ///
- NOTIFYFORMAT = 0x0055,
-
- ///
- /// The WM_CONTEXTMENU message notifies a window that the user clicked the right mouse button (right-clicked) in the window.
- ///
- CONTEXTMENU = 0x007B,
-
- ///
- /// The WM_STYLECHANGING message is sent to a window when the SetWindowLong function is about to change one or more of the window's styles.
- ///
- STYLECHANGING = 0x007C,
-
- ///
- /// The WM_STYLECHANGED message is sent to a window after the SetWindowLong function has changed one or more of the window's styles
- ///
- STYLECHANGED = 0x007D,
-
- ///
- /// The WM_DISPLAYCHANGE message is sent to all windows when the display resolution has changed.
- ///
- DISPLAYCHANGE = 0x007E,
-
- ///
- /// The WM_GETICON message is sent to a window to retrieve a handle to the large or small icon associated with a window. The system displays the large icon in the ALT+TAB dialog, and the small icon in the window caption.
- ///
- GETICON = 0x007F,
-
- ///
- /// An application sends the WM_SETICON message to associate a new large or small icon with a window. The system displays the large icon in the ALT+TAB dialog box, and the small icon in the window caption.
- ///
- SETICON = 0x0080,
-
- ///
- /// The WM_NCCREATE message is sent prior to the WM_CREATE message when a window is first created.
- ///
- NCCREATE = 0x0081,
-
- ///
- /// The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY message. WM_DESTROY is used to free the allocated memory object associated with the window.
- /// The WM_NCDESTROY message is sent after the child windows have been destroyed. In contrast, WM_DESTROY is sent before the child windows are destroyed.
- ///
- NCDESTROY = 0x0082,
-
- ///
- /// The WM_NCCALCSIZE message is sent when the size and position of a window's client area must be calculated. By processing this message, an application can control the content of the window's client area when the size or position of the window changes.
- ///
- NCCALCSIZE = 0x0083,
-
- ///
- /// The WM_NCHITTEST message is sent to a window when the cursor moves, or when a mouse button is pressed or released. If the mouse is not captured, the message is sent to the window beneath the cursor. Otherwise, the message is sent to the window that has captured the mouse.
- ///
- NCHITTEST = 0x0084,
-
- ///
- /// The WM_NCPAINT message is sent to a window when its frame must be painted.
- ///
- NCPAINT = 0x0085,
-
- ///
- /// The WM_NCACTIVATE message is sent to a window when its nonclient area needs to be changed to indicate an active or inactive state.
- ///
- NCACTIVATE = 0x0086,
-
- ///
- /// The WM_GETDLGCODE message is sent to the window procedure associated with a control. By default, the system handles all keyboard input to the control; the system interprets certain types of keyboard input as dialog box navigation keys. To override this default behavior, the control can respond to the WM_GETDLGCODE message to indicate the types of input it wants to process itself.
- ///
- GETDLGCODE = 0x0087,
-
- ///
- /// The WM_SYNCPAINT message is used to synchronize painting while avoiding linking independent GUI threads.
- ///
- SYNCPAINT = 0x0088,
-
- ///
- /// The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved within the nonclient area of the window. This message is posted to the window that contains the cursor. If a window has captured the mouse, this message is not posted.
- ///
- NCMOUSEMOVE = 0x00A0,
-
- ///
- /// The WM_NCLBUTTONDOWN message is posted when the user presses the left mouse button while the cursor is within the nonclient area of a window. This message is posted to the window that contains the cursor. If a window has captured the mouse, this message is not posted.
- ///
- NCLBUTTONDOWN = 0x00A1,
-
- ///
- /// The WM_NCLBUTTONUP message is posted when the user releases the left mouse button while the cursor is within the nonclient area of a window. This message is posted to the window that contains the cursor. If a window has captured the mouse, this message is not posted.
- ///
- NCLBUTTONUP = 0x00A2,
-
- ///
- /// The WM_NCLBUTTONDBLCLK message is posted when the user double-clicks the left mouse button while the cursor is within the nonclient area of a window. This message is posted to the window that contains the cursor. If a window has captured the mouse, this message is not posted.
- ///
- NCLBUTTONDBLCLK = 0x00A3,
-
- ///
- /// The WM_NCRBUTTONDOWN message is posted when the user presses the right mouse button while the cursor is within the nonclient area of a window. This message is posted to the window that contains the cursor. If a window has captured the mouse, this message is not posted.
- ///
- NCRBUTTONDOWN = 0x00A4,
-
- ///
- /// The WM_NCRBUTTONUP message is posted when the user releases the right mouse button while the cursor is within the nonclient area of a window. This message is posted to the window that contains the cursor. If a window has captured the mouse, this message is not posted.
- ///
- NCRBUTTONUP = 0x00A5,
-
- ///
- /// The WM_NCRBUTTONDBLCLK message is posted when the user double-clicks the right mouse button while the cursor is within the nonclient area of a window. This message is posted to the window that contains the cursor. If a window has captured the mouse, this message is not posted.
- ///
- NCRBUTTONDBLCLK = 0x00A6,
-
- ///
- /// The WM_NCMBUTTONDOWN message is posted when the user presses the middle mouse button while the cursor is within the nonclient area of a window. This message is posted to the window that contains the cursor. If a window has captured the mouse, this message is not posted.
- ///
- NCMBUTTONDOWN = 0x00A7,
-
- ///
- /// The WM_NCMBUTTONUP message is posted when the user releases the middle mouse button while the cursor is within the nonclient area of a window. This message is posted to the window that contains the cursor. If a window has captured the mouse, this message is not posted.
- ///
- NCMBUTTONUP = 0x00A8,
-
- ///
- /// The WM_NCMBUTTONDBLCLK message is posted when the user double-clicks the middle mouse button while the cursor is within the nonclient area of a window. This message is posted to the window that contains the cursor. If a window has captured the mouse, this message is not posted.
- ///
- NCMBUTTONDBLCLK = 0x00A9,
-
- ///
- /// The WM_NCXBUTTONDOWN message is posted when the user presses the first or second X button while the cursor is in the nonclient area of a window. This message is posted to the window that contains the cursor. If a window has captured the mouse, this message is not posted.
- ///
- NCXBUTTONDOWN = 0x00AB,
-
- ///
- /// The WM_NCXBUTTONUP message is posted when the user releases the first or second X button while the cursor is in the nonclient area of a window. This message is posted to the window that contains the cursor. If a window has captured the mouse, this message is not posted.
- ///
- NCXBUTTONUP = 0x00AC,
-
- ///
- /// The WM_NCXBUTTONDBLCLK message is posted when the user double-clicks the first or second X button while the cursor is in the nonclient area of a window. This message is posted to the window that contains the cursor. If a window has captured the mouse, this message is not posted.
- ///
- NCXBUTTONDBLCLK = 0x00AD,
-
- ///
- /// The WM_INPUT_DEVICE_CHANGE message is sent to the window that registered to receive raw input. A window receives this message through its WindowProc function.
- ///
- INPUT_DEVICE_CHANGE = 0x00FE,
-
- ///
- /// The WM_INPUT message is sent to the window that is getting raw input.
- ///
- INPUT = 0x00FF,
-
- ///
- /// This message filters for keyboard messages.
- ///
- KEYFIRST = 0x0100,
-
- ///
- /// The WM_KEYDOWN message is posted to the window with the keyboard focus when a nonsystem key is pressed. A nonsystem key is a key that is pressed when the ALT key is not pressed.
- ///
- KEYDOWN = 0x0100,
-
- ///
- /// The WM_KEYUP message is posted to the window with the keyboard focus when a nonsystem key is released. A nonsystem key is a key that is pressed when the ALT key is not pressed, or a keyboard key that is pressed when a window has the keyboard focus.
- ///
- KEYUP = 0x0101,
-
- ///
- /// The WM_CHAR message is posted to the window with the keyboard focus when a WM_KEYDOWN message is translated by the TranslateMessage function. The WM_CHAR message contains the character code of the key that was pressed.
- ///
- CHAR = 0x0102,
-
- ///
- /// The WM_DEADCHAR message is posted to the window with the keyboard focus when a WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR specifies a character code generated by a dead key. A dead key is a key that generates a character, such as the umlaut (double-dot), that is combined with another character to form a composite character. For example, the umlaut-O character (Ö) is generated by typing the dead key for the umlaut character, and then typing the O key.
- ///
- DEADCHAR = 0x0103,
-
- ///
- /// The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when the user presses the F10 key (which activates the menu bar) or holds down the ALT key and then presses another key. It also occurs when no window currently has the keyboard focus; in this case, the WM_SYSKEYDOWN message is sent to the active window. The window that receives the message can distinguish between these two contexts by checking the context code in the lParam parameter.
- ///
- SYSKEYDOWN = 0x0104,
-
- ///
- /// The WM_SYSKEYUP message is posted to the window with the keyboard focus when the user releases a key that was pressed while the ALT key was held down. It also occurs when no window currently has the keyboard focus; in this case, the WM_SYSKEYUP message is sent to the active window. The window that receives the message can distinguish between these two contexts by checking the context code in the lParam parameter.
- ///
- SYSKEYUP = 0x0105,
-
- ///
- /// The WM_SYSCHAR message is posted to the window with the keyboard focus when a WM_SYSKEYDOWN message is translated by the TranslateMessage function. It specifies the character code of a system character key — that is, a character key that is pressed while the ALT key is down.
- ///
- SYSCHAR = 0x0106,
-
- ///
- /// The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when a WM_SYSKEYDOWN message is translated by the TranslateMessage function. WM_SYSDEADCHAR specifies the character code of a system dead key — that is, a dead key that is pressed while holding down the ALT key.
- ///
- SYSDEADCHAR = 0x0107,
-
- ///
- /// The WM_UNICHAR message is posted to the window with the keyboard focus when a WM_KEYDOWN message is translated by the TranslateMessage function. The WM_UNICHAR message contains the character code of the key that was pressed.
- /// The WM_UNICHAR message is equivalent to WM_CHAR, but it uses Unicode Transformation Format (UTF)-32, whereas WM_CHAR uses UTF-16. It is designed to send or post Unicode characters to ANSI windows and it can can handle Unicode Supplementary Plane characters.
- ///
- UNICHAR = 0x0109,
-
- ///
- /// This message filters for keyboard messages.
- ///
- KEYLAST = 0x0108,
-
- ///
- /// Sent immediately before the IME generates the composition string as a result of a keystroke. A window receives this message through its WindowProc function.
- ///
- IME_STARTCOMPOSITION = 0x010D,
-
- ///
- /// Sent to an application when the IME ends composition. A window receives this message through its WindowProc function.
- ///
- IME_ENDCOMPOSITION = 0x010E,
-
- ///
- /// Sent to an application when the IME changes composition status as a result of a keystroke. A window receives this message through its WindowProc function.
- ///
- IME_COMPOSITION = 0x010F,
- IME_KEYLAST = 0x010F,
-
- ///
- /// The WM_INITDIALOG message is sent to the dialog box procedure immediately before a dialog box is displayed. Dialog box procedures typically use this message to initialize controls and carry out any other initialization tasks that affect the appearance of the dialog box.
- ///
- INITDIALOG = 0x0110,
-
- ///
- /// The WM_COMMAND message is sent when the user selects a command item from a menu, when a control sends a notification message to its parent window, or when an accelerator keystroke is translated.
- ///
- COMMAND = 0x0111,
-
- ///
- /// A window receives this message when the user chooses a command from the Window menu, clicks the maximize button, minimize button, restore button, close button, or moves the form. You can stop the form from moving by filtering this out.
- ///
- SYSCOMMAND = 0x0112,
-
- ///
- /// The WM_TIMER message is posted to the installing thread's message queue when a timer expires. The message is posted by the GetMessage or PeekMessage function.
- ///
- TIMER = 0x0113,
-
- ///
- /// The WM_HSCROLL message is sent to a window when a scroll event occurs in the window's standard horizontal scroll bar. This message is also sent to the owner of a horizontal scroll bar control when a scroll event occurs in the control.
- ///
- HSCROLL = 0x0114,
-
- ///
- /// The WM_VSCROLL message is sent to a window when a scroll event occurs in the window's standard vertical scroll bar. This message is also sent to the owner of a vertical scroll bar control when a scroll event occurs in the control.
- ///
- VSCROLL = 0x0115,
-
- ///
- /// The WM_INITMENU message is sent when a menu is about to become active. It occurs when the user clicks an item on the menu bar or presses a menu key. This allows the application to modify the menu before it is displayed.
- ///
- INITMENU = 0x0116,
-
- ///
- /// The WM_INITMENUPOPUP message is sent when a drop-down menu or submenu is about to become active. This allows an application to modify the menu before it is displayed, without changing the entire menu.
- ///
- INITMENUPOPUP = 0x0117,
-
- ///
- /// The WM_MENUSELECT message is sent to a menu's owner window when the user selects a menu item.
- ///
- MENUSELECT = 0x011F,
-
- ///
- /// The WM_MENUCHAR message is sent when a menu is active and the user presses a key that does not correspond to any mnemonic or accelerator key. This message is sent to the window that owns the menu.
- ///
- MENUCHAR = 0x0120,
-
- ///
- /// The WM_ENTERIDLE message is sent to the owner window of a modal dialog box or menu that is entering an idle state. A modal dialog box or menu enters an idle state when no messages are waiting in its queue after it has processed one or more previous messages.
- ///
- ENTERIDLE = 0x0121,
-
- ///
- /// The WM_MENURBUTTONUP message is sent when the user releases the right mouse button while the cursor is on a menu item.
- ///
- MENURBUTTONUP = 0x0122,
-
- ///
- /// The WM_MENUDRAG message is sent to the owner of a drag-and-drop menu when the user drags a menu item.
- ///
- MENUDRAG = 0x0123,
-
- ///
- /// The WM_MENUGETOBJECT message is sent to the owner of a drag-and-drop menu when the mouse cursor enters a menu item or moves from the center of the item to the top or bottom of the item.
- ///
- MENUGETOBJECT = 0x0124,
-
- ///
- /// The WM_UNINITMENUPOPUP message is sent when a drop-down menu or submenu has been destroyed.
- ///
- UNINITMENUPOPUP = 0x0125,
-
- ///
- /// The WM_MENUCOMMAND message is sent when the user makes a selection from a menu.
- ///
- MENUCOMMAND = 0x0126,
-
- ///
- /// An application sends the WM_CHANGEUISTATE message to indicate that the user interface (UI) state should be changed.
- ///
- CHANGEUISTATE = 0x0127,
-
- ///
- /// An application sends the WM_UPDATEUISTATE message to change the user interface (UI) state for the specified window and all its child windows.
- ///
- UPDATEUISTATE = 0x0128,
-
- ///
- /// An application sends the WM_QUERYUISTATE message to retrieve the user interface (UI) state for a window.
- ///
- QUERYUISTATE = 0x0129,
-
- ///
- /// The WM_CTLCOLORMSGBOX message is sent to the owner window of a message box before Windows draws the message box. By responding to this message, the owner window can set the text and background colors of the message box by using the given display device context handle.
- ///
- CTLCOLORMSGBOX = 0x0132,
-
- ///
- /// An edit control that is not read-only or disabled sends the WM_CTLCOLOREDIT message to its parent window when the control is about to be drawn. By responding to this message, the parent window can use the specified device context handle to set the text and background colors of the edit control.
- ///
- CTLCOLOREDIT = 0x0133,
-
- ///
- /// Sent to the parent window of a list box before the system draws the list box. By responding to this message, the parent window can set the text and background colors of the list box by using the specified display device context handle.
- ///
- CTLCOLORLISTBOX = 0x0134,
-
- ///
- /// The WM_CTLCOLORBTN message is sent to the parent window of a button before drawing the button. The parent window can change the button's text and background colors. However, only owner-drawn buttons respond to the parent window processing this message.
- ///
- CTLCOLORBTN = 0x0135,
-
- ///
- /// The WM_CTLCOLORDLG message is sent to a dialog box before the system draws the dialog box. By responding to this message, the dialog box can set its text and background colors using the specified display device context handle.
- ///
- CTLCOLORDLG = 0x0136,
-
- ///
- /// The WM_CTLCOLORSCROLLBAR message is sent to the parent window of a scroll bar control when the control is about to be drawn. By responding to this message, the parent window can use the display context handle to set the background color of the scroll bar control.
- ///
- CTLCOLORSCROLLBAR = 0x0137,
-
- ///
- /// A static control, or an edit control that is read-only or disabled, sends the WM_CTLCOLORSTATIC message to its parent window when the control is about to be drawn. By responding to this message, the parent window can use the specified device context handle to set the text and background colors of the static control.
- ///
- CTLCOLORSTATIC = 0x0138,
-
- ///
- /// Use WM_MOUSEFIRST to specify the first mouse message. Use the PeekMessage() Function.
- ///
- MOUSEFIRST = 0x0200,
-
- ///
- /// The WM_MOUSEMOVE message is posted to a window when the cursor moves. If the mouse is not captured, the message is posted to the window that contains the cursor. Otherwise, the message is posted to the window that has captured the mouse.
- ///
- MOUSEMOVE = 0x0200,
-
- ///
- /// The WM_LBUTTONDOWN message is posted when the user presses the left mouse button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.
- ///
- LBUTTONDOWN = 0x0201,
-
- ///
- /// The WM_LBUTTONUP message is posted when the user releases the left mouse button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.
- ///
- LBUTTONUP = 0x0202,
-
- ///
- /// The WM_LBUTTONDBLCLK message is posted when the user double-clicks the left mouse button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.
- ///
- LBUTTONDBLCLK = 0x0203,
-
- ///
- /// The WM_RBUTTONDOWN message is posted when the user presses the right mouse button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.
- ///
- RBUTTONDOWN = 0x0204,
-
- ///
- /// The WM_RBUTTONUP message is posted when the user releases the right mouse button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.
- ///
- RBUTTONUP = 0x0205,
-
- ///
- /// The WM_RBUTTONDBLCLK message is posted when the user double-clicks the right mouse button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.
- ///
- RBUTTONDBLCLK = 0x0206,
-
- ///
- /// The WM_MBUTTONDOWN message is posted when the user presses the middle mouse button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.
- ///
- MBUTTONDOWN = 0x0207,
-
- ///
- /// The WM_MBUTTONUP message is posted when the user releases the middle mouse button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.
- ///
- MBUTTONUP = 0x0208,
-
- ///
- /// The WM_MBUTTONDBLCLK message is posted when the user double-clicks the middle mouse button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.
- ///
- MBUTTONDBLCLK = 0x0209,
-
- ///
- /// The WM_MOUSEWHEEL message is sent to the focus window when the mouse wheel is rotated. The DefWindowProc function propagates the message to the window's parent. There should be no internal forwarding of the message, since DefWindowProc propagates it up the parent chain until it finds a window that processes it.
- ///
- MOUSEWHEEL = 0x020A,
-
- ///
- /// The WM_XBUTTONDOWN message is posted when the user presses the first or second X button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.
- ///
- XBUTTONDOWN = 0x020B,
-
- ///
- /// The WM_XBUTTONUP message is posted when the user releases the first or second X button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.
- ///
- XBUTTONUP = 0x020C,
-
- ///
- /// The WM_XBUTTONDBLCLK message is posted when the user double-clicks the first or second X button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.
- ///
- XBUTTONDBLCLK = 0x020D,
-
- ///
- /// The WM_MOUSEHWHEEL message is sent to the focus window when the mouse's horizontal scroll wheel is tilted or rotated. The DefWindowProc function propagates the message to the window's parent. There should be no internal forwarding of the message, since DefWindowProc propagates it up the parent chain until it finds a window that processes it.
- ///
- MOUSEHWHEEL = 0x020E,
-
- ///
- /// Use WM_MOUSELAST to specify the last mouse message. Used with PeekMessage() Function.
- ///
- MOUSELAST = 0x020E,
-
- ///
- /// The WM_PARENTNOTIFY message is sent to the parent of a child window when the child window is created or destroyed, or when the user clicks a mouse button while the cursor is over the child window. When the child window is being created, the system sends WM_PARENTNOTIFY just before the CreateWindow or CreateWindowEx function that creates the window returns. When the child window is being destroyed, the system sends the message before any processing to destroy the window takes place.
- ///
- PARENTNOTIFY = 0x0210,
-
- ///
- /// The WM_ENTERMENULOOP message informs an application's main window procedure that a menu modal loop has been entered.
- ///
- ENTERMENULOOP = 0x0211,
-
- ///
- /// The WM_EXITMENULOOP message informs an application's main window procedure that a menu modal loop has been exited.
- ///
- EXITMENULOOP = 0x0212,
-
- ///
- /// The WM_NEXTMENU message is sent to an application when the right or left arrow key is used to switch between the menu bar and the system menu.
- ///
- NEXTMENU = 0x0213,
-
- ///
- /// The WM_SIZING message is sent to a window that the user is resizing. By processing this message, an application can monitor the size and position of the drag rectangle and, if needed, change its size or position.
- ///
- SIZING = 0x0214,
-
- ///
- /// The WM_CAPTURECHANGED message is sent to the window that is losing the mouse capture.
- ///
- CAPTURECHANGED = 0x0215,
-
- ///
- /// The WM_MOVING message is sent to a window that the user is moving. By processing this message, an application can monitor the position of the drag rectangle and, if needed, change its position.
- ///
- MOVING = 0x0216,
-
- ///
- /// Notifies applications that a power-management event has occurred.
- ///
- POWERBROADCAST = 0x0218,
-
- ///
- /// Notifies an application of a change to the hardware configuration of a device or the computer.
- ///
- DEVICECHANGE = 0x0219,
-
- ///
- /// An application sends the WM_MDICREATE message to a multiple-document interface (MDI) client window to create an MDI child window.
- ///
- MDICREATE = 0x0220,
-
- ///
- /// An application sends the WM_MDIDESTROY message to a multiple-document interface (MDI) client window to close an MDI child window.
- ///
- MDIDESTROY = 0x0221,
-
- ///
- /// An application sends the WM_MDIACTIVATE message to a multiple-document interface (MDI) client window to instruct the client window to activate a different MDI child window.
- ///
- MDIACTIVATE = 0x0222,
-
- ///
- /// An application sends the WM_MDIRESTORE message to a multiple-document interface (MDI) client window to restore an MDI child window from maximized or minimized size.
- ///
- MDIRESTORE = 0x0223,
-
- ///
- /// An application sends the WM_MDINEXT message to a multiple-document interface (MDI) client window to activate the next or previous child window.
- ///
- MDINEXT = 0x0224,
-
- ///
- /// An application sends the WM_MDIMAXIMIZE message to a multiple-document interface (MDI) client window to maximize an MDI child window. The system resizes the child window to make its client area fill the client window. The system places the child window's window menu icon in the rightmost position of the frame window's menu bar, and places the child window's restore icon in the leftmost position. The system also appends the title bar text of the child window to that of the frame window.
- ///
- MDIMAXIMIZE = 0x0225,
-
- ///
- /// An application sends the WM_MDITILE message to a multiple-document interface (MDI) client window to arrange all of its MDI child windows in a tile format.
- ///
- MDITILE = 0x0226,
-
- ///
- /// An application sends the WM_MDICASCADE message to a multiple-document interface (MDI) client window to arrange all its child windows in a cascade format.
- ///
- MDICASCADE = 0x0227,
-
- ///
- /// An application sends the WM_MDIICONARRANGE message to a multiple-document interface (MDI) client window to arrange all minimized MDI child windows. It does not affect child windows that are not minimized.
- ///
- MDIICONARRANGE = 0x0228,
-
- ///
- /// An application sends the WM_MDIGETACTIVE message to a multiple-document interface (MDI) client window to retrieve the handle to the active MDI child window.
- ///
- MDIGETACTIVE = 0x0229,
-
- ///
- /// An application sends the WM_MDISETMENU message to a multiple-document interface (MDI) client window to replace the entire menu of an MDI frame window, to replace the window menu of the frame window, or both.
- ///
- MDISETMENU = 0x0230,
-
- ///
- /// The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving or sizing modal loop. The window enters the moving or sizing modal loop when the user clicks the window's title bar or sizing border, or when the window passes the WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the message specifies the SC_MOVE or SC_SIZE value. The operation is complete when DefWindowProc returns.
- /// The system sends the WM_ENTERSIZEMOVE message regardless of whether the dragging of full windows is enabled.
- ///
- ENTERSIZEMOVE = 0x0231,
-
- ///
- /// The WM_EXITSIZEMOVE message is sent one time to a window, after it has exited the moving or sizing modal loop. The window enters the moving or sizing modal loop when the user clicks the window's title bar or sizing border, or when the window passes the WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the message specifies the SC_MOVE or SC_SIZE value. The operation is complete when DefWindowProc returns.
- ///
- EXITSIZEMOVE = 0x0232,
-
- ///
- /// Sent when the user drops a file on the window of an application that has registered itself as a recipient of dropped files.
- ///
- DROPFILES = 0x0233,
-
- ///
- /// An application sends the WM_MDIREFRESHMENU message to a multiple-document interface (MDI) client window to refresh the window menu of the MDI frame window.
- ///
- MDIREFRESHMENU = 0x0234,
-
- ///
- /// Sent to an application when a window is activated. A window receives this message through its WindowProc function.
- ///
- IME_SETCONTEXT = 0x0281,
-
- ///
- /// Sent to an application to notify it of changes to the IME window. A window receives this message through its WindowProc function.
- ///
- IME_NOTIFY = 0x0282,
-
- ///
- /// Sent by an application to direct the IME window to carry out the requested command. The application uses this message to control the IME window that it has created. To send this message, the application calls the SendMessage function with the following parameters.
- ///
- IME_CONTROL = 0x0283,
-
- ///
- /// Sent to an application when the IME window finds no space to extend the area for the composition window. A window receives this message through its WindowProc function.
- ///
- IME_COMPOSITIONFULL = 0x0284,
-
- ///
- /// Sent to an application when the operating system is about to change the current IME. A window receives this message through its WindowProc function.
- ///
- IME_SELECT = 0x0285,
-
- ///
- /// Sent to an application when the IME gets a character of the conversion result. A window receives this message through its WindowProc function.
- ///
- IME_CHAR = 0x0286,
-
- ///
- /// Sent to an application to provide commands and request information. A window receives this message through its WindowProc function.
- ///
- IME_REQUEST = 0x0288,
-
- ///
- /// Sent to an application by the IME to notify the application of a key press and to keep message order. A window receives this message through its WindowProc function.
- ///
- IME_KEYDOWN = 0x0290,
-
- ///
- /// Sent to an application by the IME to notify the application of a key release and to keep message order. A window receives this message through its WindowProc function.
- ///
- IME_KEYUP = 0x0291,
-
- ///
- /// The WM_MOUSEHOVER message is posted to a window when the cursor hovers over the client area of the window for the period of time specified in a prior call to TrackMouseEvent.
- ///
- MOUSEHOVER = 0x02A1,
-
- ///
- /// The WM_MOUSELEAVE message is posted to a window when the cursor leaves the client area of the window specified in a prior call to TrackMouseEvent.
- ///
- MOUSELEAVE = 0x02A3,
-
- ///
- /// The WM_NCMOUSEHOVER message is posted to a window when the cursor hovers over the nonclient area of the window for the period of time specified in a prior call to TrackMouseEvent.
- ///
- NCMOUSEHOVER = 0x02A0,
-
- ///
- /// The WM_NCMOUSELEAVE message is posted to a window when the cursor leaves the nonclient area of the window specified in a prior call to TrackMouseEvent.
- ///
- NCMOUSELEAVE = 0x02A2,
-
- ///
- /// The WM_WTSSESSION_CHANGE message notifies applications of changes in session state.
- ///
- WTSSESSION_CHANGE = 0x02B1,
- TABLET_FIRST = 0x02c0,
- TABLET_LAST = 0x02df,
-
- ///
- /// An application sends a WM_CUT message to an edit control or combo box to delete (cut) the current selection, if any, in the edit control and copy the deleted text to the clipboard in CF_TEXT format.
- ///
- CUT = 0x0300,
-
- ///
- /// An application sends the WM_COPY message to an edit control or combo box to copy the current selection to the clipboard in CF_TEXT format.
- ///
- COPY = 0x0301,
-
- ///
- /// An application sends a WM_PASTE message to an edit control or combo box to copy the current content of the clipboard to the edit control at the current caret position. Data is inserted only if the clipboard contains data in CF_TEXT format.
- ///
- PASTE = 0x0302,
-
- ///
- /// An application sends a WM_CLEAR message to an edit control or combo box to delete (clear) the current selection, if any, from the edit control.
- ///
- CLEAR = 0x0303,
-
- ///
- /// An application sends a WM_UNDO message to an edit control to undo the last operation. When this message is sent to an edit control, the previously deleted text is restored or the previously added text is deleted.
- ///
- UNDO = 0x0304,
-
- ///
- /// The WM_RENDERFORMAT message is sent to the clipboard owner if it has delayed rendering a specific clipboard format and if an application has requested data in that format. The clipboard owner must render data in the specified format and place it on the clipboard by calling the SetClipboardData function.
- ///
- RENDERFORMAT = 0x0305,
-
- ///
- /// The WM_RENDERALLFORMATS message is sent to the clipboard owner before it is destroyed, if the clipboard owner has delayed rendering one or more clipboard formats. For the content of the clipboard to remain available to other applications, the clipboard owner must render data in all the formats it is capable of generating, and place the data on the clipboard by calling the SetClipboardData function.
- ///
- RENDERALLFORMATS = 0x0306,
-
- ///
- /// The WM_DESTROYCLIPBOARD message is sent to the clipboard owner when a call to the EmptyClipboard function empties the clipboard.
- ///
- DESTROYCLIPBOARD = 0x0307,
-
- ///
- /// The WM_DRAWCLIPBOARD message is sent to the first window in the clipboard viewer chain when the content of the clipboard changes. This enables a clipboard viewer window to display the new content of the clipboard.
- ///
- DRAWCLIPBOARD = 0x0308,
-
- ///
- /// The WM_PAINTCLIPBOARD message is sent to the clipboard owner by a clipboard viewer window when the clipboard contains data in the CF_OWNERDISPLAY format and the clipboard viewer's client area needs repainting.
- ///
- PAINTCLIPBOARD = 0x0309,
-
- ///
- /// The WM_VSCROLLCLIPBOARD message is sent to the clipboard owner by a clipboard viewer window when the clipboard contains data in the CF_OWNERDISPLAY format and an event occurs in the clipboard viewer's vertical scroll bar. The owner should scroll the clipboard image and update the scroll bar values.
- ///
- VSCROLLCLIPBOARD = 0x030A,
-
- ///
- /// The WM_SIZECLIPBOARD message is sent to the clipboard owner by a clipboard viewer window when the clipboard contains data in the CF_OWNERDISPLAY format and the clipboard viewer's client area has changed size.
- ///
- SIZECLIPBOARD = 0x030B,
-
- ///
- /// The WM_ASKCBFORMATNAME message is sent to the clipboard owner by a clipboard viewer window to request the name of a CF_OWNERDISPLAY clipboard format.
- ///
- ASKCBFORMATNAME = 0x030C,
-
- ///
- /// The WM_CHANGECBCHAIN message is sent to the first window in the clipboard viewer chain when a window is being removed from the chain.
- ///
- CHANGECBCHAIN = 0x030D,
-
- ///
- /// The WM_HSCROLLCLIPBOARD message is sent to the clipboard owner by a clipboard viewer window. This occurs when the clipboard contains data in the CF_OWNERDISPLAY format and an event occurs in the clipboard viewer's horizontal scroll bar. The owner should scroll the clipboard image and update the scroll bar values.
- ///
- HSCROLLCLIPBOARD = 0x030E,
-
- ///
- /// This message informs a window that it is about to receive the keyboard focus, giving the window the opportunity to realize its logical palette when it receives the focus.
- ///
- QUERYNEWPALETTE = 0x030F,
-
- ///
- /// The WM_PALETTEISCHANGING message informs applications that an application is going to realize its logical palette.
- ///
- PALETTEISCHANGING = 0x0310,
-
- ///
- /// This message is sent by the OS to all top-level and overlapped windows after the window with the keyboard focus realizes its logical palette.
- /// This message enables windows that do not have the keyboard focus to realize their logical palettes and update their client areas.
- ///
- PALETTECHANGED = 0x0311,
-
- ///
- /// The WM_HOTKEY message is posted when the user presses a hot key registered by the RegisterHotKey function. The message is placed at the top of the message queue associated with the thread that registered the hot key.
- ///
- HOTKEY = 0x0312,
-
- ///
- /// The WM_PRINT message is sent to a window to request that it draw itself in the specified device context, most commonly in a printer device context.
- ///
- PRINT = 0x0317,
-
- ///
- /// The WM_PRINTCLIENT message is sent to a window to request that it draw its client area in the specified device context, most commonly in a printer device context.
- ///
- PRINTCLIENT = 0x0318,
-
- ///
- /// The WM_APPCOMMAND message notifies a window that the user generated an application command event, for example, by clicking an application command button using the mouse or typing an application command key on the keyboard.
- ///
- APPCOMMAND = 0x0319,
-
- ///
- /// The WM_THEMECHANGED message is broadcast to every window following a theme change event. Examples of theme change events are the activation of a theme, the deactivation of a theme, or a transition from one theme to another.
- ///
- THEMECHANGED = 0x031A,
-
- ///
- /// Sent when the contents of the clipboard have changed.
- ///
- CLIPBOARDUPDATE = 0x031D,
-
- ///
- /// The system will send a window the WM_DWMCOMPOSITIONCHANGED message to indicate that the availability of desktop composition has changed.
- ///
- DWMCOMPOSITIONCHANGED = 0x031E,
-
- ///
- /// WM_DWMNCRENDERINGCHANGED is called when the non-client area rendering status of a window has changed. Only windows that have set the flag DWM_BLURBEHIND.fTransitionOnMaximized to true will get this message.
- ///
- DWMNCRENDERINGCHANGED = 0x031F,
-
- ///
- /// Sent to all top-level windows when the colorization color has changed.
- ///
- DWMCOLORIZATIONCOLORCHANGED = 0x0320,
-
- ///
- /// WM_DWMWINDOWMAXIMIZEDCHANGE will let you know when a DWM composed window is maximized. You also have to register for this message as well. You'd have other windowd go opaque when this message is sent.
- ///
- DWMWINDOWMAXIMIZEDCHANGE = 0x0321,
-
- ///
- /// Sent to request extended title bar information. A window receives this message through its WindowProc function.
- ///
- GETTITLEBARINFOEX = 0x033F,
- HANDHELDFIRST = 0x0358,
- HANDHELDLAST = 0x035F,
- AFXFIRST = 0x0360,
- AFXLAST = 0x037F,
- PENWINFIRST = 0x0380,
- PENWINLAST = 0x038F,
-
- ///
- /// The WM_APP constant is used by applications to help define private messages, usually of the form WM_APP+X, where X is an integer value.
- ///
- APP = 0x8000,
-
- ///
- /// The WM_USER constant is used by applications to help define private messages for use by private window classes, usually of the form WM_USER+X, where X is an integer value.
- ///
- USER = 0x0400,
-
- ///
- /// An application sends the WM_CPL_LAUNCH message to Windows Control Panel to request that a Control Panel application be started.
- ///
- CPL_LAUNCH = USER + 0x1000,
-
- ///
- /// The WM_CPL_LAUNCHED message is sent when a Control Panel application, started by the WM_CPL_LAUNCH message, has closed. The WM_CPL_LAUNCHED message is sent to the window identified by the wParam parameter of the WM_CPL_LAUNCH message that started the application.
- ///
- CPL_LAUNCHED = USER + 0x1001,
-
- ///
- /// WM_SYSTIMER is a well-known yet still undocumented message. Windows uses WM_SYSTIMER for internal actions like scrolling.
- ///
- SYSTIMER = 0x118,
-
- ///
- /// The accessibility state has changed.
- ///
- HSHELL_ACCESSIBILITYSTATE = 11,
-
- ///
- /// The shell should activate its main window.
- ///
- HSHELL_ACTIVATESHELLWINDOW = 3,
-
- ///
- /// The user completed an input event (for example, pressed an application command button on the mouse or an application command key on the keyboard), and the application did not handle the WM_APPCOMMAND message generated by that input.
- /// If the Shell procedure handles the WM_COMMAND message, it should not call CallNextHookEx. See the Return Value section for more information.
- ///
- HSHELL_APPCOMMAND = 12,
-
- ///
- /// A window is being minimized or maximized. The system needs the coordinates of the minimized rectangle for the window.
- ///
- HSHELL_GETMINRECT = 5,
-
- ///
- /// Keyboard language was changed or a new keyboard layout was loaded.
- ///
- HSHELL_LANGUAGE = 8,
-
- ///
- /// The title of a window in the task bar has been redrawn.
- ///
- HSHELL_REDRAW = 6,
-
- ///
- /// The user has selected the task list. A shell application that provides a task list should return TRUE to prevent Windows from starting its task list.
- ///
- HSHELL_TASKMAN = 7,
-
- ///
- /// A top-level, unowned window has been created. The window exists when the system calls this hook.
- ///
- HSHELL_WINDOWCREATED = 1,
-
- ///
- /// A top-level, unowned window is about to be destroyed. The window still exists when the system calls this hook.
- ///
- HSHELL_WINDOWDESTROYED = 2,
-
- ///
- /// The activation has changed to a different top-level, unowned window.
- ///
- HSHELL_WINDOWACTIVATED = 4,
-
- ///
- /// A top-level window is being replaced. The window exists when the system calls this hook.
- ///
- HSHELL_WINDOWREPLACED = 13
- }
-
- #endregion
-
- [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
-
- [DllImport("user32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool IsWindow(IntPtr hWnd);
-
- [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- public static extern int GetWindowTextLength(IntPtr hWnd);
-
- [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
- public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
-
- [DllImport("kernel32.dll")]
- public static extern bool SetProcessWorkingSetSize(IntPtr hProcess, int
- dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize);
-
- #region Window_Style
-
- [DllImport("user32.dll")]
- public static extern IntPtr GetMenu(IntPtr hWnd);
-
- [DllImport("user32.dll")]
- public static extern int GetMenuItemCount(IntPtr hMenu);
-
- [DllImport("user32.dll")]
- public static extern bool RemoveMenu(IntPtr hMenu, uint uPosition, uint uFlags);
-
- [DllImport("user32.dll")]
- public static extern bool DrawMenuBar(IntPtr hWnd);
-
- public static uint MF_BYPOSITION = 0x400;
- public static uint MF_REMOVE = 0x1000;
-
- // This helper static method is required because the 32-bit version of user32.dll does not contain this API
- // (on any versions of Windows), so linking the method will fail at run-time. The bridge dispatches the request
- // to the correct function (GetWindowLong in 32-bit mode and GetWindowLongPtr in 64-bit mode)
- public static IntPtr SetWindowLongPtr(HandleRef hWnd, int nIndex, IntPtr dwNewLong)
- {
- if (IntPtr.Size == 8)
- return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
- else
- return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32()));
- }
-
- [DllImport("user32.dll", EntryPoint = "SetWindowLong", SetLastError = true)]
- public static extern int SetWindowLong32(HandleRef hWnd, int nIndex, int dwNewLong);
-
- [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", SetLastError = true)]
- public static extern IntPtr SetWindowLongPtr64(HandleRef hWnd, int nIndex, IntPtr dwNewLong);
-
- #endregion
-
- //ref: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.getlastwin32error?view=netframework-4.8
- //[DllImportAttribute("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- //public static extern int MessageBox(IntPtr hwnd, String text, String caption, uint type);
-
- #region WinDesktopCore
-
- [Flags]
- public enum SendMessageTimeoutFlags : uint
- {
- SMTO_NORMAL = 0x0,
- SMTO_BLOCK = 0x1,
- SMTO_ABORTIFHUNG = 0x2,
- SMTO_NOTIMEOUTIFNOTHUNG = 0x8,
- SMTO_ERRORONEXIT = 0x20
- }
-
- public enum AnimateWindowFlags : uint
- {
- AW_HOR_POSITIVE = 0x00000001,
- AW_HOR_NEGATIVE = 0x00000002,
- AW_VER_POSITIVE = 0x00000004,
- AW_VER_NEGATIVE = 0x00000008,
- AW_CENTER = 0x00000010,
- AW_HIDE = 0x00010000,
- AW_ACTIVATE = 0x00020000,
- AW_SLIDE = 0x00040000,
- AW_BLEND = 0x00080000
- }
-
- [DllImport("user32")]
- public static extern bool AnimateWindow(IntPtr hwnd, int time, AnimateWindowFlags flags);
-
- [DllImport("user32.dll")]
- public static extern IntPtr GetShellWindow();
-
- [DllImport("user32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern IntPtr FindWindow(string lpWindowClass, string lpWindowName);
-
- [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam, SendMessageTimeoutFlags fuFlags, uint uTimeout, out IntPtr lpdwResult);
-
- [DllImport("user32.dll")]
- public static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
-
- public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);
-
- [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
- public static extern IntPtr FindWindowByCaption(IntPtr zeroOnly, string lpWindowName);
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern IntPtr SetParent(IntPtr child, IntPtr parent);
-
- #region sendmsg
-
- [DllImport("User32.dll", EntryPoint = "SendMessage")]
- public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
-
- public const int WM_KEYDOWN = 0x0100;
- public const int WM_KEYUP = 0x0101;
-
- [return: MarshalAs(UnmanagedType.Bool)]
- [DllImport("user32.dll", SetLastError = true)]
- public static extern bool PostMessage(int hWnd, uint Msg, int wParam, int lParam);
-
- #endregion
-
- [DllImport("kernel32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
-
- /*
- [DllImport("user32.dll")]
- public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
- [DllImport("user32.dll")]
- public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, long dwNewLong);
- */
-
- [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
- public static extern IntPtr GetWindowLongPtr32(IntPtr hWnd, int nIndex);
-
- [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
- private static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex);
-
- // This static method is required because Win32 does not support
- // GetWindowLongPtr directly
- public static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex)
- {
- if (IntPtr.Size == 8)
- return GetWindowLongPtr64(hWnd, nIndex);
- else
- return GetWindowLongPtr32(hWnd, nIndex);
- }
-
- public enum GWL
- {
- GWL_WNDPROC = (-4),
- GWL_HINSTANCE = (-6),
- GWL_HWNDPARENT = (-8),
- GWL_STYLE = (-16),
- GWL_EXSTYLE = (-20),
- GWL_USERDATA = (-21),
- GWL_ID = (-12)
- }
-
- public abstract class WindowStyles
- {
- public const uint WS_EX_NOREDIRECTIONBITMAP = 0x00200000;
- public const uint WS_OVERLAPPED = 0x00000000;
- public const uint WS_POPUP = 0x80000000;
- public const uint WS_CHILD = 0x40000000;
- public const uint WS_MINIMIZE = 0x20000000;
- public const uint WS_VISIBLE = 0x10000000;
- public const uint WS_DISABLED = 0x08000000;
- public const uint WS_CLIPSIBLINGS = 0x04000000;
- public const uint WS_CLIPCHILDREN = 0x02000000;
- public const uint WS_MAXIMIZE = 0x01000000;
- public const uint WS_CAPTION = 0x00C00000; /* WS_BORDER | WS_DLGFRAME */
- public const uint WS_BORDER = 0x00800000;
- public const uint WS_DLGFRAME = 0x00400000;
- public const uint WS_VSCROLL = 0x00200000;
- public const uint WS_HSCROLL = 0x00100000;
- public const uint WS_SYSMENU = 0x00080000;
- public const uint WS_THICKFRAME = 0x00040000;
- public const uint WS_GROUP = 0x00020000;
- public const uint WS_TABSTOP = 0x00010000;
-
- public const uint WS_MINIMIZEBOX = 0x00020000;
- public const uint WS_MAXIMIZEBOX = 0x00010000;
-
- public const uint WS_TILED = WS_OVERLAPPED;
- public const uint WS_ICONIC = WS_MINIMIZE;
- public const uint WS_SIZEBOX = WS_THICKFRAME;
- public const uint WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW;
-
- // Common Window Styles
-
- public const uint WS_OVERLAPPEDWINDOW =
- (WS_OVERLAPPED |
- WS_CAPTION |
- WS_SYSMENU |
- WS_THICKFRAME |
- WS_MINIMIZEBOX |
- WS_MAXIMIZEBOX);
-
- public const uint WS_POPUPWINDOW =
- (WS_POPUP |
- WS_BORDER |
- WS_SYSMENU);
-
- public const uint WS_CHILDWINDOW = WS_CHILD;
-
- //Extended Window Styles
-
- public const uint WS_EX_DLGMODALFRAME = 0x00000001;
- public const uint WS_EX_NOPARENTNOTIFY = 0x00000004;
- public const uint WS_EX_TOPMOST = 0x00000008;
- public const uint WS_EX_ACCEPTFILES = 0x00000010;
- public const uint WS_EX_TRANSPARENT = 0x00000020;
-
- //#if(WINVER >= 0x0400)
- public const uint WS_EX_MDICHILD = 0x00000040;
- public const uint WS_EX_TOOLWINDOW = 0x00000080;
- public const uint WS_EX_WINDOWEDGE = 0x00000100;
- public const uint WS_EX_CLIENTEDGE = 0x00000200;
- public const uint WS_EX_CONTEXTHELP = 0x00000400;
-
- public const uint WS_EX_RIGHT = 0x00001000;
- public const uint WS_EX_LEFT = 0x00000000;
- public const uint WS_EX_RTLREADING = 0x00002000;
- public const uint WS_EX_LTRREADING = 0x00000000;
- public const uint WS_EX_LEFTSCROLLBAR = 0x00004000;
- public const uint WS_EX_RIGHTSCROLLBAR = 0x00000000;
-
- public const uint WS_EX_CONTROLPARENT = 0x00010000;
- public const uint WS_EX_STATICEDGE = 0x00020000;
- public const uint WS_EX_APPWINDOW = 0x00040000;
-
- public const uint WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE);
- public const uint WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST);
- //#endif /* WINVER >= 0x0400 */
-
- //#if(_WIN32_WINNT >= 0x0500)
- public const uint WS_EX_LAYERED = 0x00080000;
- //#endif /* _WIN32_WINNT >= 0x0500 */
-
- //#if(WINVER >= 0x0500)
- public const uint WS_EX_NOINHERITLAYOUT = 0x00100000; // Disable inheritence of mirroring by children
- public const uint WS_EX_LAYOUTRTL = 0x00400000; // Right to left mirroring
- //#endif /* WINVER >= 0x0500 */
-
- //#if(_WIN32_WINNT >= 0x0500)
- public const uint WS_EX_COMPOSITED = 0x02000000;
-
- public const uint WS_EX_NOACTIVATE = 0x08000000;
- //#endif /* _WIN32_WINNT >= 0x0500 */
- }
-
-
- [DllImport("user32.dll", EntryPoint = "SetWindowPos", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool SetWindowPos(IntPtr hwnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
-
- [DllImport("user32.dll")]
- public static extern IntPtr GetDesktopWindow();
-
- [DllImport("Shell32.dll")]
- public static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
-
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- [return: MarshalAs(UnmanagedType.I4)]
- public static extern Int32 SystemParametersInfo(UInt32 uiAction, UInt32 uiParam, String pvParam, UInt32 fWinIni);
-
-
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- public static extern bool SystemParametersInfo(
- int uAction, int uParam, [MarshalAs(UnmanagedType.I1)] bool lpvParam,
- int flags);
-
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- public static extern bool SystemParametersInfo(
- int uAction, int uParam, ref int lpvParam,
- int flags);
-
-
- public static UInt32 SPIF_SENDWININICHANGE = 0x02;
- public static UInt32 SPI_SETDESKWALLPAPER = 20;
- public static UInt32 SPIF_UPDATEINIFILE = 0x1;
- public static UInt32 SPI_SETCLIENTAREAANIMATION = 0x1043;
-
- #endregion //WinDesktopCore
-
- #region keyboard
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern IntPtr SetFocus(IntPtr hWnd);
-
- [DllImport("User32.dll")]
- public static extern int SetForegroundWindow(IntPtr point);
-
- #endregion keyboard
-
- #region Pause
-
- [DllImport("USER32.DLL")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool IsWindowVisible(IntPtr hWnd);
-
- //..Pause.c
- [Flags]
- public enum ThreadAccess : int
- {
- TERMINATE = (0x0001),
- SUSPEND_RESUME = (0x0002),
- GET_CONTEXT = (0x0008),
- SET_CONTEXT = (0x0010),
- SET_INFORMATION = (0x0020),
- QUERY_INFORMATION = (0x0040),
- SET_THREAD_TOKEN = (0x0080),
- IMPERSONATE = (0x0100),
- DIRECT_IMPERSONATION = (0x0200)
- }
-
- [DllImport("kernel32.dll")]
- public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
-
- [DllImport("kernel32.dll")]
- public static extern uint SuspendThread(IntPtr hThread);
-
- [DllImport("kernel32.dll")]
- public static extern int ResumeThread(IntPtr hThread);
-
- //..pause logic
- [StructLayout(LayoutKind.Sequential)]
- public struct RECT
- {
- public int Left;
- public int Top;
- public int Right;
- public int Bottom;
- }
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
-
- [DllImport("user32.dll")]
- public static extern IntPtr GetForegroundWindow();
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
-
- [DllImport("coredll.dll", SetLastError = true)]
- static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
-
- [DllImport("coredll.dll", SetLastError = true)]
- public static extern int GetModuleFileName(UIntPtr hModule, StringBuilder lpFilename, int nSize);
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern int GetWindowRect(IntPtr hwnd, out RECT rc);
-
- [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
- public static extern bool CloseHandle(IntPtr handle);
-
- public const int APPCOMMAND_VOLUME_MUTE = 0x80000;
- public const int WM_APPCOMMAND = 0x319;
-
- [DllImport("user32.dll")]
- public static extern IntPtr SendMessageW(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
-
- #endregion pause
-
- #region ScreenResolution
-
- [StructLayout(LayoutKind.Sequential)]
- public struct WINDOWPOS
- {
- public IntPtr hwnd;
- public IntPtr hwndInsertAfter;
- public int x;
- public int y;
- public int cx;
- public int cy;
- public int flags;
- }
-
- public const int MONITOR_DEFAULTTONULL = 0;
- public const int MONITOR_DEFAULTTOPRIMARY = 1;
- public const int MONITOR_DEFAULTTONEAREST = 2;
-
- [DllImport("user32.dll")]
- public static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);
-
- [StructLayout(LayoutKind.Sequential)]
- public struct POINT
- {
- public int X;
- public int Y;
-
- public POINT(int x, int y)
- {
- this.X = x;
- this.Y = y;
- }
-
- public static implicit operator System.Drawing.Point(POINT p)
- {
- return new System.Drawing.Point(p.X, p.Y);
- }
-
- public static implicit operator POINT(System.Drawing.Point p)
- {
- return new POINT(p.X, p.Y);
- }
- }
-
- [DllImport("user32.dll")]
- public static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);
-
- [DllImport("user32", ExactSpelling = true, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.I4)]
- public static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] ref RECT rect, [MarshalAs(UnmanagedType.U4)] int cPoints);
-
- [DllImport("user32", ExactSpelling = true, SetLastError = true)]
- public static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] ref System.Drawing.Point pt, [MarshalAs(UnmanagedType.U4)] int cPoints);
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
-
- [DllImport("User32.dll")]
- public static extern IntPtr GetDC(IntPtr hwnd);
-
- [DllImport("User32.dll")]
- public static extern int ReleaseDC(IntPtr hwnd, IntPtr dc);
-
- //..IsIconic = minimized. IsZoomed = maximixed
- [DllImport("user32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool IsIconic(IntPtr hWnd);
-
- [DllImport("user32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool IsZoomed(IntPtr hWnd);
-
- public enum HWNDInsertAfter : int
- {
- HWND_TOP = 0,
- HWND_BOTTOM = 1,
- HWND_TOPMOST = -1,
- HWND_NOTOPMOST = -2
- }
-
- [Flags]
- public enum SetWindowPosFlags : int
- {
- // ReSharper disable InconsistentNaming
-
- ///
- /// If the calling thread and the thread that owns the window are attached to different input queues, the system posts the request to the thread that owns the window. This prevents the calling thread from blocking its execution while other threads process the request.
- ///
- SWP_ASYNCWINDOWPOS = 0x4000,
-
- ///
- /// Prevents generation of the WM_SYNCPAINT message.
- ///
- SWP_DEFERERASE = 0x2000,
-
- ///
- /// Draws a frame (defined in the window's class description) around the window.
- ///
- SWP_DRAWFRAME = 0x0020,
-
- ///
- /// Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE is sent only when the window's size is being changed.
- ///
- SWP_FRAMECHANGED = 0x0020,
-
- ///
- /// Hides the window.
- ///
- SWP_HIDEWINDOW = 0x0080,
-
- ///
- /// Does not activate the window. If this flag is not set, the window is activated and moved to the top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter parameter).
- ///
- SWP_NOACTIVATE = 0x0010,
-
- ///
- /// Discards the entire contents of the client area. If this flag is not specified, the valid contents of the client area are saved and copied back into the client area after the window is sized or repositioned.
- ///
- SWP_NOCOPYBITS = 0x0100,
-
- ///
- /// Retains the current position (ignores X and Y parameters).
- ///
- SWP_NOMOVE = 0x0002,
-
- ///
- /// Does not change the owner window's position in the Z order.
- ///
- SWP_NOOWNERZORDER = 0x0200,
-
- ///
- /// Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent window uncovered as a result of the window being moved. When this flag is set, the application must explicitly invalidate or redraw any parts of the window and parent window that need redrawing.
- ///
- SWP_NOREDRAW = 0x0008,
-
- ///
- /// Same as the SWP_NOOWNERZORDER flag.
- ///
- SWP_NOREPOSITION = 0x0200,
-
- ///
- /// Prevents the window from receiving the WM_WINDOWPOSCHANGING message.
- ///
- SWP_NOSENDCHANGING = 0x0400,
-
- ///
- /// Retains the current size (ignores the cx and cy parameters).
- ///
- SWP_NOSIZE = 0x0001,
-
- ///
- /// Retains the current Z order (ignores the hWndInsertAfter parameter).
- ///
- SWP_NOZORDER = 0x0004,
-
- ///
- /// Displays the window.
- ///
- SWP_SHOWWINDOW = 0x0040,
-
- // ReSharper restore InconsistentNaming
- }
-
- #endregion ScreenResolution
-
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- public static extern bool GetMonitorInfo(IntPtr hMonitor, ref MonitorInfoEx lpmi);
-
- // size of a device name string
- public const int CCHDEVICENAME = 32;
-
- ///
- /// The MONITORINFOEX structure contains information about a display monitor.
- /// The GetMonitorInfo function stores information into a MONITORINFOEX structure or a MONITORINFO structure.
- /// The MONITORINFOEX structure is a superset of the MONITORINFO structure. The MONITORINFOEX structure adds a string member to contain a name
- /// for the display monitor.
- ///
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
- public struct MonitorInfoEx
- {
- ///
- /// The size, in bytes, of the structure. Set this member to sizeof(MONITORINFOEX) (72) before calling the GetMonitorInfo function.
- /// Doing so lets the function determine the type of structure you are passing to it.
- ///
- public int Size;
-
- ///
- /// A RECT structure that specifies the display monitor rectangle, expressed in virtual-screen coordinates.
- /// Note that if the monitor is not the primary display monitor, some of the rectangle's coordinates may be negative values.
- ///
- public RectStruct Monitor;
-
- ///
- /// A RECT structure that specifies the work area rectangle of the display monitor that can be used by applications,
- /// expressed in virtual-screen coordinates. Windows uses this rectangle to maximize an application on the monitor.
- /// The rest of the area in rcMonitor contains system windows such as the task bar and side bars.
- /// Note that if the monitor is not the primary display monitor, some of the rectangle's coordinates may be negative values.
- ///
- public RectStruct WorkArea;
-
- ///
- /// The attributes of the display monitor.
- ///
- /// This member can be the following value:
- /// 1 : MONITORINFOF_PRIMARY
- ///
- public uint Flags;
-
- ///
- /// A string that specifies the device name of the monitor being used. Most applications have no use for a display monitor name,
- /// and so can save some bytes by using a MONITORINFO structure.
- ///
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
- public string DeviceName;
-
- public void Init()
- {
- this.Size = 40 + 2 * CCHDEVICENAME;
- this.DeviceName = string.Empty;
- }
- }
-
- ///
- /// The RECT structure defines the coordinates of the upper-left and lower-right corners of a rectangle.
- ///
- ///
- ///
- /// By convention, the right and bottom edges of the rectangle are normally considered exclusive.
- /// In other words, the pixel whose coordinates are ( right, bottom ) lies immediately outside of the the rectangle.
- /// For example, when RECT is passed to the FillRect function, the rectangle is filled up to, but not including,
- /// the right column and bottom row of pixels. This structure is identical to the RECTL structure.
- ///
- [StructLayout(LayoutKind.Sequential)]
- public struct RectStruct
- {
- ///
- /// The x-coordinate of the upper-left corner of the rectangle.
- ///
- public int Left;
-
- ///
- /// The y-coordinate of the upper-left corner of the rectangle.
- ///
- public int Top;
-
- ///
- /// The x-coordinate of the lower-right corner of the rectangle.
- ///
- public int Right;
-
- ///
- /// The y-coordinate of the lower-right corner of the rectangle.
- ///
- public int Bottom;
- }
-
- #region parent process
-
- ///
- /// A utility class to determine a process parent.
- ///
- [StructLayout(LayoutKind.Sequential)]
- public struct ParentProcessUtilities
- {
- // These members must match PROCESS_BASIC_INFORMATION
- internal IntPtr Reserved1;
- internal IntPtr PebBaseAddress;
- internal IntPtr Reserved2_0;
- internal IntPtr Reserved2_1;
- internal IntPtr UniqueProcessId;
- internal IntPtr InheritedFromUniqueProcessId;
-
- [DllImport("ntdll.dll")]
- private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtilities processInformation, int processInformationLength, out int returnLength);
-
- ///
- /// Gets the parent process of the current process.
- ///
- /// An instance of the Process class.
- public static Process GetParentProcess()
- {
- return GetParentProcess(Process.GetCurrentProcess().Handle);
- }
-
- ///
- /// Gets the parent process of specified process.
- ///
- /// The process id.
- /// An instance of the Process class.
- public static Process GetParentProcess(int id)
- {
- Process process = Process.GetProcessById(id);
- return GetParentProcess(process.Handle);
- }
-
- ///
- /// Gets the parent process of a specified process.
- ///
- /// The process handle.
- /// An instance of the Process class.
- public static Process GetParentProcess(IntPtr handle)
- {
- ParentProcessUtilities pbi = new ParentProcessUtilities();
- int returnLength;
- int status = NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength);
- if (status != 0)
- throw new Win32Exception(status);
-
- try
- {
- return Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32());
- }
- catch (ArgumentException)
- {
- // not found
- return null;
- }
- }
- }
-
- #endregion //parent process
-
- [DllImport("user32.dll")]
- public static extern IntPtr GetTopWindow(IntPtr hWnd);
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern IntPtr GetWindow(IntPtr hWnd, GetWindowType uCmd);
-
- public enum GetWindowType : uint
- {
- ///
- /// The retrieved handle identifies the window of the same type that is highest in the Z order.
- ///
- /// If the specified window is a topmost window, the handle identifies a topmost window.
- /// If the specified window is a top-level window, the handle identifies a top-level window.
- /// If the specified window is a child window, the handle identifies a sibling window.
- ///
- GW_HWNDFIRST = 0,
-
- ///
- /// The retrieved handle identifies the window of the same type that is lowest in the Z order.
- ///
- /// If the specified window is a topmost window, the handle identifies a topmost window.
- /// If the specified window is a top-level window, the handle identifies a top-level window.
- /// If the specified window is a child window, the handle identifies a sibling window.
- ///
- GW_HWNDLAST = 1,
-
- ///
- /// The retrieved handle identifies the window below the specified window in the Z order.
- ///
- /// If the specified window is a topmost window, the handle identifies a topmost window.
- /// If the specified window is a top-level window, the handle identifies a top-level window.
- /// If the specified window is a child window, the handle identifies a sibling window.
- ///
- GW_HWNDNEXT = 2,
-
- ///
- /// The retrieved handle identifies the window above the specified window in the Z order.
- ///
- /// If the specified window is a topmost window, the handle identifies a topmost window.
- /// If the specified window is a top-level window, the handle identifies a top-level window.
- /// If the specified window is a child window, the handle identifies a sibling window.
- ///
- GW_HWNDPREV = 3,
-
- ///
- /// The retrieved handle identifies the specified window's owner window, if any.
- ///
- GW_OWNER = 4,
-
- ///
- /// The retrieved handle identifies the child window at the top of the Z order,
- /// if the specified window is a parent window; otherwise, the retrieved handle is NULL.
- /// The function examines only child windows of the specified window. It does not examine descendant windows.
- ///
- GW_CHILD = 5,
-
- ///
- /// The retrieved handle identifies the enabled popup window owned by the specified window (the
- /// search uses the first such window found using GW_HWNDNEXT); otherwise, if there are no enabled
- /// popup windows, the retrieved handle is that of the specified window.
- ///
- GW_ENABLEDPOPUP = 6
- }
-
- #region shell
-
- [DllImport("shell32.dll")]
- public static extern void SHGetSetSettings(ref SHELLSTATE lpss, SSF dwMask, bool bSet);
-
- [StructLayout(LayoutKind.Sequential)]
- public struct SHELLSTATE
- {
- public uint flags_1;
- public uint dwWin95Unused;
- public uint uWin95Unused;
- public int lParamSort;
- public int iSortDirection;
- public uint version;
- public uint uNotUsed;
- public uint flags_2;
-
- public bool fShowAllObjects
- {
- get { return (flags_1 & 0x00000001u) == 0x00000001u; }
- set
- {
- if (value) { flags_1 |= 0x00000001u; }
- else { flags_1 &= ~0x00000001u; }
- }
- }
-
- public bool fShowExtensions
- {
- get { return (flags_1 & 0x00000002u) == 0x00000002u; }
- set
- {
- if (value) { flags_1 |= 0x00000002u; }
- else { flags_1 &= ~0x00000002u; }
- }
- }
-
- public bool fNoConfirmRecycle
- {
- get { return (flags_1 & 0x00000004u) == 0x00000004u; }
- set
- {
- if (value) { flags_1 |= 0x00000004u; }
- else { flags_1 &= ~0x00000004u; }
- }
- }
-
- public bool fShowSysFiles
- {
- get { return (flags_1 & 0x00000008u) == 0x00000008u; }
- set
- {
- if (value) { flags_1 |= 0x00000008u; }
- else { flags_1 &= ~0x00000008u; }
- }
- }
-
- public bool fShowCompColor
- {
- get { return (flags_1 & 0x00000010u) == 0x00000010u; }
- set
- {
- if (value) { flags_1 |= 0x00000010u; }
- else { flags_1 &= ~0x00000010u; }
- }
- }
-
- public bool fDoubleClickInWebView
- {
- get { return (flags_1 & 0x00000020u) == 0x00000020u; }
- set
- {
- if (value) { flags_1 |= 0x00000020u; }
- else { flags_1 &= ~0x00000020u; }
- }
- }
-
- public bool fDesktopHTML
- {
- get { return (flags_1 & 0x00000040u) == 0x00000040u; }
- set
- {
- if (value) { flags_1 |= 0x00000040u; }
- else { flags_1 &= ~0x00000040u; }
- }
- }
-
- public bool fWin95Classic
- {
- get { return (flags_1 & 0x00000080u) == 0x00000080u; }
- set
- {
- if (value) { flags_1 |= 0x00000080u; }
- else { flags_1 &= ~0x00000080u; }
- }
- }
-
- public bool fDontPrettyPath
- {
- get { return (flags_1 & 0x00000100u) == 0x00000100u; }
- set
- {
- if (value) { flags_1 |= 0x00000100u; }
- else { flags_1 &= ~0x00000100u; }
- }
- }
-
- public bool fShowAttribCol
- {
- get { return (flags_1 & 0x00000200u) == 0x00000200u; }
- set
- {
- if (value) { flags_1 |= 0x00000200u; }
- else { flags_1 &= ~0x00000200u; }
- }
- }
-
- public bool fMapNetDrvBtn
- {
- get { return (flags_1 & 0x00000400u) == 0x00000400u; }
- set
- {
- if (value) { flags_1 |= 0x00000400u; }
- else { flags_1 &= ~0x00000400u; }
- }
- }
-
- public bool fShowInfoTip
- {
- get { return (flags_1 & 0x00000800u) == 0x00000800u; }
- set
- {
- if (value) { flags_1 |= 0x00000800u; }
- else { flags_1 &= ~0x00000800u; }
- }
- }
-
- public bool fHideIcons
- {
- get { return (flags_1 & 0x00001000u) == 0x00001000u; }
- set
- {
- if (value) { flags_1 |= 0x00001000u; }
- else { flags_1 &= ~0x00001000u; }
- }
- }
-
- public bool fWebView
- {
- get { return (flags_1 & 0x00002000u) == 0x00002000u; }
- set
- {
- if (value) { flags_1 |= 0x00002000u; }
- else { flags_1 &= ~0x00002000u; }
- }
- }
-
- public bool fFilter
- {
- get { return (flags_1 & 0x00004000u) == 0x00004000u; }
- set
- {
- if (value) { flags_1 |= 0x00004000u; }
- else { flags_1 &= ~0x00004000u; }
- }
- }
-
- public bool fShowSuperHidden
- {
- get { return (flags_1 & 0x00008000u) == 0x00008000u; }
- set
- {
- if (value) { flags_1 |= 0x00008000u; }
- else { flags_1 &= ~0x00008000u; }
- }
- }
-
- public bool fNoNetCrawling
- {
- get { return (flags_1 & 0x00010000u) == 0x00010000u; }
- set
- {
- if (value) { flags_1 |= 0x00010000u; }
- else { flags_1 &= ~0x00010000u; }
- }
- }
-
- public bool fSepProcess
- {
- get { return (flags_2 & 0x00000001u) == 0x00000001u; }
- set
- {
- if (value) { flags_2 |= 0x00000001u; }
- else { flags_2 &= ~0x00000001u; }
- }
- }
-
- public bool fStartPanelOn
- {
- get { return (flags_2 & 0x00000002u) == 0x00000002u; }
- set
- {
- if (value) { flags_2 |= 0x00000002u; }
- else { flags_2 &= ~0x00000002u; }
- }
- }
-
- public bool fShowStartPage
- {
- get { return (flags_2 & 0x00000004u) == 0x00000004u; }
- set
- {
- if (value) { flags_2 |= 0x00000004u; }
- else { flags_2 &= ~0x00000004u; }
- }
- }
-
- public bool fAutoCheckSelect
- {
- get { return (flags_2 & 0x00000008u) == 0x00000008u; }
- set
- {
- if (value) { flags_2 |= 0x00000008u; }
- else { flags_2 &= ~0x00000008u; }
- }
- }
-
- public bool fIconsOnly
- {
- get { return (flags_2 & 0x00000010u) == 0x00000010u; }
- set
- {
- if (value) { flags_2 |= 0x00000010u; }
- else { flags_2 &= ~0x00000010u; }
- }
- }
-
- public bool fShowTypeOverlay
- {
- get { return (flags_2 & 0x00000020u) == 0x00000020u; }
- set
- {
- if (value) { flags_2 |= 0x00000020u; }
- else { flags_2 &= ~0x00000020u; }
- }
- }
-
- public bool fShowStatusBar
- {
- get { return (flags_2 & 0x00000040u) == 0x00000040u; }
- set
- {
- if (value) { flags_2 |= 0x00000040u; }
- else { flags_2 &= ~0x00000040u; }
- }
- }
- }
-
- [Flags]
- public enum SSF : uint
- {
- SSF_SHOWALLOBJECTS = 0x00000001,
- SSF_SHOWEXTENSIONS = 0x00000002,
- SSF_HIDDENFILEEXTS = 0x00000004,
- SSF_SERVERADMINUI = 0x00000004,
- SSF_SHOWCOMPCOLOR = 0x00000008,
- SSF_SORTCOLUMNS = 0x00000010,
- SSF_SHOWSYSFILES = 0x00000020,
- SSF_DOUBLECLICKINWEBVIEW = 0x00000080,
- SSF_SHOWATTRIBCOL = 0x00000100,
- SSF_DESKTOPHTML = 0x00000200,
- SSF_WIN95CLASSIC = 0x00000400,
- SSF_DONTPRETTYPATH = 0x00000800,
- SSF_MAPNETDRVBUTTON = 0x00001000,
- SSF_SHOWINFOTIP = 0x00002000,
- SSF_HIDEICONS = 0x00004000,
- SSF_NOCONFIRMRECYCLE = 0x00008000,
- SSF_FILTER = 0x00010000,
- SSF_WEBVIEW = 0x00020000,
- SSF_SHOWSUPERHIDDEN = 0x00040000,
- SSF_SEPPROCESS = 0x00080000,
- SSF_NONETCRAWLING = 0x00100000,
- SSF_STARTPANELON = 0x00200000,
- SSF_SHOWSTARTPAGE = 0x00400000,
- SSF_AUTOCHECKSELECT = 0x00800000,
- SSF_ICONSONLY = 0x01000000,
- SSF_SHOWTYPEOVERLAY = 0x02000000,
- SSF_SHOWSTATUSBAR = 0x04000000
- }
-
- #endregion //shell
-
- #region display mgr
-
- #region SPI
-
- ///
- /// SPI_ System-wide parameter - Used in SystemParametersInfo function
- ///
- [Description("SPI_(System-wide parameter - Used in SystemParametersInfo function )")]
- public enum SPI : uint
- {
- ///
- /// Determines whether the warning beeper is on.
- /// The pvParam parameter must point to a BOOL variable that receives TRUE if the beeper is on, or FALSE if it is off.
- ///
- SPI_GETBEEP = 0x0001,
-
- ///
- /// Turns the warning beeper on or off. The uiParam parameter specifies TRUE for on, or FALSE for off.
- ///
- SPI_SETBEEP = 0x0002,
-
- ///
- /// Retrieves the two mouse threshold values and the mouse speed.
- ///
- SPI_GETMOUSE = 0x0003,
-
- ///
- /// Sets the two mouse threshold values and the mouse speed.
- ///
- SPI_SETMOUSE = 0x0004,
-
- ///
- /// Retrieves the border multiplier factor that determines the width of a window's sizing border.
- /// The pvParam parameter must point to an integer variable that receives this value.
- ///
- SPI_GETBORDER = 0x0005,
-
- ///
- /// Sets the border multiplier factor that determines the width of a window's sizing border.
- /// The uiParam parameter specifies the new value.
- ///
- SPI_SETBORDER = 0x0006,
-
- ///
- /// Retrieves the keyboard repeat-speed setting, which is a value in the range from 0 (approximately 2.5 repetitions per second)
- /// through 31 (approximately 30 repetitions per second). The actual repeat rates are hardware-dependent and may vary from
- /// a linear scale by as much as 20%. The pvParam parameter must point to a DWORD variable that receives the setting
- ///
- SPI_GETKEYBOARDSPEED = 0x000A,
-
- ///
- /// Sets the keyboard repeat-speed setting. The uiParam parameter must specify a value in the range from 0
- /// (approximately 2.5 repetitions per second) through 31 (approximately 30 repetitions per second).
- /// The actual repeat rates are hardware-dependent and may vary from a linear scale by as much as 20%.
- /// If uiParam is greater than 31, the parameter is set to 31.
- ///
- SPI_SETKEYBOARDSPEED = 0x000B,
-
- ///
- /// Not implemented.
- ///
- SPI_LANGDRIVER = 0x000C,
-
- ///
- /// Sets or retrieves the width, in pixels, of an icon cell. The system uses this rectangle to arrange icons in large icon view.
- /// To set this value, set uiParam to the new value and set pvParam to null. You cannot set this value to less than SM_CXICON.
- /// To retrieve this value, pvParam must point to an integer that receives the current value.
- ///
- SPI_ICONHORIZONTALSPACING = 0x000D,
-
- ///
- /// Retrieves the screen saver time-out value, in seconds. The pvParam parameter must point to an integer variable that receives the value.
- ///
- SPI_GETSCREENSAVETIMEOUT = 0x000E,
-
- ///
- /// Sets the screen saver time-out value to the value of the uiParam parameter. This value is the amount of time, in seconds,
- /// that the system must be idle before the screen saver activates.
- ///
- SPI_SETSCREENSAVETIMEOUT = 0x000F,
-
- ///
- /// Determines whether screen saving is enabled. The pvParam parameter must point to a bool variable that receives TRUE
- /// if screen saving is enabled, or FALSE otherwise.
- /// Does not work for Windows 7: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724947(v=vs.85).aspx
- ///
- SPI_GETSCREENSAVEACTIVE = 0x0010,
-
- ///
- /// Sets the state of the screen saver. The uiParam parameter specifies TRUE to activate screen saving, or FALSE to deactivate it.
- ///
- SPI_SETSCREENSAVEACTIVE = 0x0011,
-
- ///
- /// Retrieves the current granularity value of the desktop sizing grid. The pvParam parameter must point to an integer variable
- /// that receives the granularity.
- ///
- SPI_GETGRIDGRANULARITY = 0x0012,
-
- ///
- /// Sets the granularity of the desktop sizing grid to the value of the uiParam parameter.
- ///
- SPI_SETGRIDGRANULARITY = 0x0013,
-
- ///
- /// Sets the desktop wallpaper. The value of the pvParam parameter determines the new wallpaper. To specify a wallpaper bitmap,
- /// set pvParam to point to a null-terminated string containing the name of a bitmap file. Setting pvParam to "" removes the wallpaper.
- /// Setting pvParam to SETWALLPAPER_DEFAULT or null reverts to the default wallpaper.
- ///
- SPI_SETDESKWALLPAPER = 0x0014,
-
- ///
- /// Sets the current desktop pattern by causing Windows to read the Pattern= setting from the WIN.INI file.
- ///
- SPI_SETDESKPATTERN = 0x0015,
-
- ///
- /// Retrieves the keyboard repeat-delay setting, which is a value in the range from 0 (approximately 250 ms delay) through 3
- /// (approximately 1 second delay). The actual delay associated with each value may vary depending on the hardware. The pvParam parameter must point to an integer variable that receives the setting.
- ///
- SPI_GETKEYBOARDDELAY = 0x0016,
-
- ///
- /// Sets the keyboard repeat-delay setting. The uiParam parameter must specify 0, 1, 2, or 3, where zero sets the shortest delay
- /// (approximately 250 ms) and 3 sets the longest delay (approximately 1 second). The actual delay associated with each value may
- /// vary depending on the hardware.
- ///
- SPI_SETKEYBOARDDELAY = 0x0017,
-
- ///
- /// Sets or retrieves the height, in pixels, of an icon cell.
- /// To set this value, set uiParam to the new value and set pvParam to null. You cannot set this value to less than SM_CYICON.
- /// To retrieve this value, pvParam must point to an integer that receives the current value.
- ///
- SPI_ICONVERTICALSPACING = 0x0018,
-
- ///
- /// Determines whether icon-title wrapping is enabled. The pvParam parameter must point to a bool variable that receives TRUE
- /// if enabled, or FALSE otherwise.
- ///
- SPI_GETICONTITLEWRAP = 0x0019,
-
- ///
- /// Turns icon-title wrapping on or off. The uiParam parameter specifies TRUE for on, or FALSE for off.
- ///
- SPI_SETICONTITLEWRAP = 0x001A,
-
- ///
- /// Determines whether pop-up menus are left-aligned or right-aligned, relative to the corresponding menu-bar item.
- /// The pvParam parameter must point to a bool variable that receives TRUE if left-aligned, or FALSE otherwise.
- ///
- SPI_GETMENUDROPALIGNMENT = 0x001B,
-
- ///
- /// Sets the alignment value of pop-up menus. The uiParam parameter specifies TRUE for right alignment, or FALSE for left alignment.
- ///
- SPI_SETMENUDROPALIGNMENT = 0x001C,
-
- ///
- /// Sets the width of the double-click rectangle to the value of the uiParam parameter.
- /// The double-click rectangle is the rectangle within which the second click of a double-click must fall for it to be registered
- /// as a double-click.
- /// To retrieve the width of the double-click rectangle, call GetSystemMetrics with the SM_CXDOUBLECLK flag.
- ///
- SPI_SETDOUBLECLKWIDTH = 0x001D,
-
- ///
- /// Sets the height of the double-click rectangle to the value of the uiParam parameter.
- /// The double-click rectangle is the rectangle within which the second click of a double-click must fall for it to be registered
- /// as a double-click.
- /// To retrieve the height of the double-click rectangle, call GetSystemMetrics with the SM_CYDOUBLECLK flag.
- ///
- SPI_SETDOUBLECLKHEIGHT = 0x001E,
-
- ///
- /// Retrieves the logical font information for the current icon-title font. The uiParam parameter specifies the size of a LOGFONT structure,
- /// and the pvParam parameter must point to the LOGFONT structure to fill in.
- ///
- SPI_GETICONTITLELOGFONT = 0x001F,
-
- ///
- /// Sets the double-click time for the mouse to the value of the uiParam parameter. The double-click time is the maximum number
- /// of milliseconds that can occur between the first and second clicks of a double-click. You can also call the SetDoubleClickTime
- /// function to set the double-click time. To get the current double-click time, call the GetDoubleClickTime function.
- ///
- SPI_SETDOUBLECLICKTIME = 0x0020,
-
- ///
- /// Swaps or restores the meaning of the left and right mouse buttons. The uiParam parameter specifies TRUE to swap the meanings
- /// of the buttons, or FALSE to restore their original meanings.
- ///
- SPI_SETMOUSEBUTTONSWAP = 0x0021,
-
- ///
- /// Sets the font that is used for icon titles. The uiParam parameter specifies the size of a LOGFONT structure,
- /// and the pvParam parameter must point to a LOGFONT structure.
- ///
- SPI_SETICONTITLELOGFONT = 0x0022,
-
- ///
- /// This flag is obsolete. Previous versions of the system use this flag to determine whether ALT+TAB fast task switching is enabled.
- /// For Windows 95, Windows 98, and Windows NT version 4.0 and later, fast task switching is always enabled.
- ///
- SPI_GETFASTTASKSWITCH = 0x0023,
-
- ///
- /// This flag is obsolete. Previous versions of the system use this flag to enable or disable ALT+TAB fast task switching.
- /// For Windows 95, Windows 98, and Windows NT version 4.0 and later, fast task switching is always enabled.
- ///
- SPI_SETFASTTASKSWITCH = 0x0024,
-
- //#if(WINVER >= 0x0400)
- ///
- /// Sets dragging of full windows either on or off. The uiParam parameter specifies TRUE for on, or FALSE for off.
- /// Windows 95: This flag is supported only if Windows Plus! is installed. See SPI_GETWINDOWSEXTENSION.
- ///
- SPI_SETDRAGFULLWINDOWS = 0x0025,
-
- ///
- /// Determines whether dragging of full windows is enabled. The pvParam parameter must point to a BOOL variable that receives TRUE
- /// if enabled, or FALSE otherwise.
- /// Windows 95: This flag is supported only if Windows Plus! is installed. See SPI_GETWINDOWSEXTENSION.
- ///
- SPI_GETDRAGFULLWINDOWS = 0x0026,
-
- ///
- /// Retrieves the metrics associated with the nonclient area of nonminimized windows. The pvParam parameter must point
- /// to a NONCLIENTMETRICS structure that receives the information. Set the cbSize member of this structure and the uiParam parameter
- /// to sizeof(NONCLIENTMETRICS).
- ///
- SPI_GETNONCLIENTMETRICS = 0x0029,
-
- ///
- /// Sets the metrics associated with the nonclient area of nonminimized windows. The pvParam parameter must point
- /// to a NONCLIENTMETRICS structure that contains the new parameters. Set the cbSize member of this structure
- /// and the uiParam parameter to sizeof(NONCLIENTMETRICS). Also, the lfHeight member of the LOGFONT structure must be a negative value.
- ///
- SPI_SETNONCLIENTMETRICS = 0x002A,
-
- ///
- /// Retrieves the metrics associated with minimized windows. The pvParam parameter must point to a MINIMIZEDMETRICS structure
- /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to sizeof(MINIMIZEDMETRICS).
- ///
- SPI_GETMINIMIZEDMETRICS = 0x002B,
-
- ///
- /// Sets the metrics associated with minimized windows. The pvParam parameter must point to a MINIMIZEDMETRICS structure
- /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to sizeof(MINIMIZEDMETRICS).
- ///
- SPI_SETMINIMIZEDMETRICS = 0x002C,
-
- ///
- /// Retrieves the metrics associated with icons. The pvParam parameter must point to an ICONMETRICS structure that receives
- /// the information. Set the cbSize member of this structure and the uiParam parameter to sizeof(ICONMETRICS).
- ///
- SPI_GETICONMETRICS = 0x002D,
-
- ///
- /// Sets the metrics associated with icons. The pvParam parameter must point to an ICONMETRICS structure that contains
- /// the new parameters. Set the cbSize member of this structure and the uiParam parameter to sizeof(ICONMETRICS).
- ///
- SPI_SETICONMETRICS = 0x002E,
-
- ///
- /// Sets the size of the work area. The work area is the portion of the screen not obscured by the system taskbar
- /// or by application desktop toolbars. The pvParam parameter is a pointer to a RECT structure that specifies the new work area rectangle,
- /// expressed in virtual screen coordinates. In a system with multiple display monitors, the function sets the work area
- /// of the monitor that contains the specified rectangle.
- ///
- SPI_SETWORKAREA = 0x002F,
-
- ///
- /// Retrieves the size of the work area on the primary display monitor. The work area is the portion of the screen not obscured
- /// by the system taskbar or by application desktop toolbars. The pvParam parameter must point to a RECT structure that receives
- /// the coordinates of the work area, expressed in virtual screen coordinates.
- /// To get the work area of a monitor other than the primary display monitor, call the GetMonitorInfo function.
- ///
- SPI_GETWORKAREA = 0x0030,
-
- ///
- /// Windows Me/98/95: Pen windows is being loaded or unloaded. The uiParam parameter is TRUE when loading and FALSE
- /// when unloading pen windows. The pvParam parameter is null.
- ///
- SPI_SETPENWINDOWS = 0x0031,
-
- ///
- /// Retrieves information about the HighContrast accessibility feature. The pvParam parameter must point to a HIGHCONTRAST structure
- /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to sizeof(HIGHCONTRAST).
- /// For a general discussion, see remarks.
- /// Windows NT: This value is not supported.
- ///
- ///
- /// There is a difference between the High Contrast color scheme and the High Contrast Mode. The High Contrast color scheme changes
- /// the system colors to colors that have obvious contrast; you switch to this color scheme by using the Display Options in the control panel.
- /// The High Contrast Mode, which uses SPI_GETHIGHCONTRAST and SPI_SETHIGHCONTRAST, advises applications to modify their appearance
- /// for visually-impaired users. It involves such things as audible warning to users and customized color scheme
- /// (using the Accessibility Options in the control panel). For more information, see HIGHCONTRAST on MSDN.
- /// For more information on general accessibility features, see Accessibility on MSDN.
- ///
- SPI_GETHIGHCONTRAST = 0x0042,
-
- ///
- /// Sets the parameters of the HighContrast accessibility feature. The pvParam parameter must point to a HIGHCONTRAST structure
- /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to sizeof(HIGHCONTRAST).
- /// Windows NT: This value is not supported.
- ///
- SPI_SETHIGHCONTRAST = 0x0043,
-
- ///
- /// Determines whether the user relies on the keyboard instead of the mouse, and wants applications to display keyboard interfaces
- /// that would otherwise be hidden. The pvParam parameter must point to a BOOL variable that receives TRUE
- /// if the user relies on the keyboard; or FALSE otherwise.
- /// Windows NT: This value is not supported.
- ///
- SPI_GETKEYBOARDPREF = 0x0044,
-
- ///
- /// Sets the keyboard preference. The uiParam parameter specifies TRUE if the user relies on the keyboard instead of the mouse,
- /// and wants applications to display keyboard interfaces that would otherwise be hidden; uiParam is FALSE otherwise.
- /// Windows NT: This value is not supported.
- ///
- SPI_SETKEYBOARDPREF = 0x0045,
-
- ///
- /// Determines whether a screen reviewer utility is running. A screen reviewer utility directs textual information to an output device,
- /// such as a speech synthesizer or Braille display. When this flag is set, an application should provide textual information
- /// in situations where it would otherwise present the information graphically.
- /// The pvParam parameter is a pointer to a BOOL variable that receives TRUE if a screen reviewer utility is running, or FALSE otherwise.
- /// Windows NT: This value is not supported.
- ///
- SPI_GETSCREENREADER = 0x0046,
-
- ///
- /// Determines whether a screen review utility is running. The uiParam parameter specifies TRUE for on, or FALSE for off.
- /// Windows NT: This value is not supported.
- ///
- SPI_SETSCREENREADER = 0x0047,
-
- ///
- /// Retrieves the animation effects associated with user actions. The pvParam parameter must point to an ANIMATIONINFO structure
- /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to sizeof(ANIMATIONINFO).
- ///
- SPI_GETANIMATION = 0x0048,
-
- ///
- /// Sets the animation effects associated with user actions. The pvParam parameter must point to an ANIMATIONINFO structure
- /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to sizeof(ANIMATIONINFO).
- ///
- SPI_SETANIMATION = 0x0049,
-
- ///
- /// Determines whether the font smoothing feature is enabled. This feature uses font antialiasing to make font curves appear smoother
- /// by painting pixels at different gray levels.
- /// The pvParam parameter must point to a BOOL variable that receives TRUE if the feature is enabled, or FALSE if it is not.
- /// Windows 95: This flag is supported only if Windows Plus! is installed. See SPI_GETWINDOWSEXTENSION.
- ///
- SPI_GETFONTSMOOTHING = 0x004A,
-
- ///
- /// Enables or disables the font smoothing feature, which uses font antialiasing to make font curves appear smoother
- /// by painting pixels at different gray levels.
- /// To enable the feature, set the uiParam parameter to TRUE. To disable the feature, set uiParam to FALSE.
- /// Windows 95: This flag is supported only if Windows Plus! is installed. See SPI_GETWINDOWSEXTENSION.
- ///
- SPI_SETFONTSMOOTHING = 0x004B,
-
- ///
- /// Sets the width, in pixels, of the rectangle used to detect the start of a drag operation. Set uiParam to the new value.
- /// To retrieve the drag width, call GetSystemMetrics with the SM_CXDRAG flag.
- ///
- SPI_SETDRAGWIDTH = 0x004C,
-
- ///
- /// Sets the height, in pixels, of the rectangle used to detect the start of a drag operation. Set uiParam to the new value.
- /// To retrieve the drag height, call GetSystemMetrics with the SM_CYDRAG flag.
- ///
- SPI_SETDRAGHEIGHT = 0x004D,
-
- ///
- /// Used internally; applications should not use this value.
- ///
- SPI_SETHANDHELD = 0x004E,
-
- ///
- /// Retrieves the time-out value for the low-power phase of screen saving. The pvParam parameter must point to an integer variable
- /// that receives the value. This flag is supported for 32-bit applications only.
- /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications.
- /// Windows 95: This flag is supported for 16-bit applications only.
- ///
- SPI_GETLOWPOWERTIMEOUT = 0x004F,
-
- ///
- /// Retrieves the time-out value for the power-off phase of screen saving. The pvParam parameter must point to an integer variable
- /// that receives the value. This flag is supported for 32-bit applications only.
- /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications.
- /// Windows 95: This flag is supported for 16-bit applications only.
- ///
- SPI_GETPOWEROFFTIMEOUT = 0x0050,
-
- ///
- /// Sets the time-out value, in seconds, for the low-power phase of screen saving. The uiParam parameter specifies the new value.
- /// The pvParam parameter must be null. This flag is supported for 32-bit applications only.
- /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications.
- /// Windows 95: This flag is supported for 16-bit applications only.
- ///
- SPI_SETLOWPOWERTIMEOUT = 0x0051,
-
- ///
- /// Sets the time-out value, in seconds, for the power-off phase of screen saving. The uiParam parameter specifies the new value.
- /// The pvParam parameter must be null. This flag is supported for 32-bit applications only.
- /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications.
- /// Windows 95: This flag is supported for 16-bit applications only.
- ///
- SPI_SETPOWEROFFTIMEOUT = 0x0052,
-
- ///
- /// Determines whether the low-power phase of screen saving is enabled. The pvParam parameter must point to a BOOL variable
- /// that receives TRUE if enabled, or FALSE if disabled. This flag is supported for 32-bit applications only.
- /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications.
- /// Windows 95: This flag is supported for 16-bit applications only.
- ///
- SPI_GETLOWPOWERACTIVE = 0x0053,
-
- ///
- /// Determines whether the power-off phase of screen saving is enabled. The pvParam parameter must point to a BOOL variable
- /// that receives TRUE if enabled, or FALSE if disabled. This flag is supported for 32-bit applications only.
- /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications.
- /// Windows 95: This flag is supported for 16-bit applications only.
- ///
- SPI_GETPOWEROFFACTIVE = 0x0054,
-
- ///
- /// Activates or deactivates the low-power phase of screen saving. Set uiParam to 1 to activate, or zero to deactivate.
- /// The pvParam parameter must be null. This flag is supported for 32-bit applications only.
- /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications.
- /// Windows 95: This flag is supported for 16-bit applications only.
- ///
- SPI_SETLOWPOWERACTIVE = 0x0055,
-
- ///
- /// Activates or deactivates the power-off phase of screen saving. Set uiParam to 1 to activate, or zero to deactivate.
- /// The pvParam parameter must be null. This flag is supported for 32-bit applications only.
- /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications.
- /// Windows 95: This flag is supported for 16-bit applications only.
- ///
- SPI_SETPOWEROFFACTIVE = 0x0056,
-
- ///
- /// Reloads the system cursors. Set the uiParam parameter to zero and the pvParam parameter to null.
- ///
- SPI_SETCURSORS = 0x0057,
-
- ///
- /// Reloads the system icons. Set the uiParam parameter to zero and the pvParam parameter to null.
- ///
- SPI_SETICONS = 0x0058,
-
- ///
- /// Retrieves the input locale identifier for the system default input language. The pvParam parameter must point
- /// to an HKL variable that receives this value. For more information, see Languages, Locales, and Keyboard Layouts on MSDN.
- ///
- SPI_GETDEFAULTINPUTLANG = 0x0059,
-
- ///
- /// Sets the default input language for the system shell and applications. The specified language must be displayable
- /// using the current system character set. The pvParam parameter must point to an HKL variable that contains
- /// the input locale identifier for the default language. For more information, see Languages, Locales, and Keyboard Layouts on MSDN.
- ///
- SPI_SETDEFAULTINPUTLANG = 0x005A,
-
- ///
- /// Sets the hot key set for switching between input languages. The uiParam and pvParam parameters are not used.
- /// The value sets the shortcut keys in the keyboard property sheets by reading the registry again. The registry must be set before this flag is used. the path in the registry is \HKEY_CURRENT_USER\keyboard layout\toggle. Valid values are "1" = ALT+SHIFT, "2" = CTRL+SHIFT, and "3" = none.
- ///
- SPI_SETLANGTOGGLE = 0x005B,
-
- ///
- /// Windows 95: Determines whether the Windows extension, Windows Plus!, is installed. Set the uiParam parameter to 1.
- /// The pvParam parameter is not used. The function returns TRUE if the extension is installed, or FALSE if it is not.
- ///
- SPI_GETWINDOWSEXTENSION = 0x005C,
-
- ///
- /// Enables or disables the Mouse Trails feature, which improves the visibility of mouse cursor movements by briefly showing
- /// a trail of cursors and quickly erasing them.
- /// To disable the feature, set the uiParam parameter to zero or 1. To enable the feature, set uiParam to a value greater than 1
- /// to indicate the number of cursors drawn in the trail.
- /// Windows 2000/NT: This value is not supported.
- ///
- SPI_SETMOUSETRAILS = 0x005D,
-
- ///
- /// Determines whether the Mouse Trails feature is enabled. This feature improves the visibility of mouse cursor movements
- /// by briefly showing a trail of cursors and quickly erasing them.
- /// The pvParam parameter must point to an integer variable that receives a value. If the value is zero or 1, the feature is disabled.
- /// If the value is greater than 1, the feature is enabled and the value indicates the number of cursors drawn in the trail.
- /// The uiParam parameter is not used.
- /// Windows 2000/NT: This value is not supported.
- ///
- SPI_GETMOUSETRAILS = 0x005E,
-
- ///
- /// Windows Me/98: Used internally; applications should not use this flag.
- ///
- SPI_SETSCREENSAVERRUNNING = 0x0061,
-
- ///
- /// Same as SPI_SETSCREENSAVERRUNNING.
- ///
- SPI_SCREENSAVERRUNNING = SPI_SETSCREENSAVERRUNNING,
- //#endif /* WINVER >= 0x0400 */
-
- ///
- /// Retrieves information about the FilterKeys accessibility feature. The pvParam parameter must point to a FILTERKEYS structure
- /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to sizeof(FILTERKEYS).
- ///
- SPI_GETFILTERKEYS = 0x0032,
-
- ///
- /// Sets the parameters of the FilterKeys accessibility feature. The pvParam parameter must point to a FILTERKEYS structure
- /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to sizeof(FILTERKEYS).
- ///
- SPI_SETFILTERKEYS = 0x0033,
-
- ///
- /// Retrieves information about the ToggleKeys accessibility feature. The pvParam parameter must point to a TOGGLEKEYS structure
- /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to sizeof(TOGGLEKEYS).
- ///
- SPI_GETTOGGLEKEYS = 0x0034,
-
- ///
- /// Sets the parameters of the ToggleKeys accessibility feature. The pvParam parameter must point to a TOGGLEKEYS structure
- /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to sizeof(TOGGLEKEYS).
- ///
- SPI_SETTOGGLEKEYS = 0x0035,
-
- ///
- /// Retrieves information about the MouseKeys accessibility feature. The pvParam parameter must point to a MOUSEKEYS structure
- /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to sizeof(MOUSEKEYS).
- ///
- SPI_GETMOUSEKEYS = 0x0036,
-
- ///
- /// Sets the parameters of the MouseKeys accessibility feature. The pvParam parameter must point to a MOUSEKEYS structure
- /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to sizeof(MOUSEKEYS).
- ///
- SPI_SETMOUSEKEYS = 0x0037,
-
- ///
- /// Determines whether the Show Sounds accessibility flag is on or off. If it is on, the user requires an application
- /// to present information visually in situations where it would otherwise present the information only in audible form.
- /// The pvParam parameter must point to a BOOL variable that receives TRUE if the feature is on, or FALSE if it is off.
- /// Using this value is equivalent to calling GetSystemMetrics (SM_SHOWSOUNDS). That is the recommended call.
- ///
- SPI_GETSHOWSOUNDS = 0x0038,
-
- ///
- /// Sets the parameters of the SoundSentry accessibility feature. The pvParam parameter must point to a SOUNDSENTRY structure
- /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to sizeof(SOUNDSENTRY).
- ///
- SPI_SETSHOWSOUNDS = 0x0039,
-
- ///
- /// Retrieves information about the StickyKeys accessibility feature. The pvParam parameter must point to a STICKYKEYS structure
- /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to sizeof(STICKYKEYS).
- ///
- SPI_GETSTICKYKEYS = 0x003A,
-
- ///
- /// Sets the parameters of the StickyKeys accessibility feature. The pvParam parameter must point to a STICKYKEYS structure
- /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to sizeof(STICKYKEYS).
- ///
- SPI_SETSTICKYKEYS = 0x003B,
-
- ///
- /// Retrieves information about the time-out period associated with the accessibility features. The pvParam parameter must point
- /// to an ACCESSTIMEOUT structure that receives the information. Set the cbSize member of this structure and the uiParam parameter
- /// to sizeof(ACCESSTIMEOUT).
- ///
- SPI_GETACCESSTIMEOUT = 0x003C,
-
- ///
- /// Sets the time-out period associated with the accessibility features. The pvParam parameter must point to an ACCESSTIMEOUT
- /// structure that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to sizeof(ACCESSTIMEOUT).
- ///
- SPI_SETACCESSTIMEOUT = 0x003D,
-
- //#if(WINVER >= 0x0400)
- ///
- /// Windows Me/98/95: Retrieves information about the SerialKeys accessibility feature. The pvParam parameter must point
- /// to a SERIALKEYS structure that receives the information. Set the cbSize member of this structure and the uiParam parameter
- /// to sizeof(SERIALKEYS).
- /// Windows Server 2003, Windows XP/2000/NT: Not supported. The user controls this feature through the control panel.
- ///
- SPI_GETSERIALKEYS = 0x003E,
-
- ///
- /// Windows Me/98/95: Sets the parameters of the SerialKeys accessibility feature. The pvParam parameter must point
- /// to a SERIALKEYS structure that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter
- /// to sizeof(SERIALKEYS).
- /// Windows Server 2003, Windows XP/2000/NT: Not supported. The user controls this feature through the control panel.
- ///
- SPI_SETSERIALKEYS = 0x003F,
- //#endif /* WINVER >= 0x0400 */
-
- ///
- /// Retrieves information about the SoundSentry accessibility feature. The pvParam parameter must point to a SOUNDSENTRY structure
- /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to sizeof(SOUNDSENTRY).
- ///
- SPI_GETSOUNDSENTRY = 0x0040,
-
- ///
- /// Sets the parameters of the SoundSentry accessibility feature. The pvParam parameter must point to a SOUNDSENTRY structure
- /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to sizeof(SOUNDSENTRY).
- ///
- SPI_SETSOUNDSENTRY = 0x0041,
-
- //#if(_WIN32_WINNT >= 0x0400)
- ///
- /// Determines whether the snap-to-default-button feature is enabled. If enabled, the mouse cursor automatically moves
- /// to the default button, such as OK or Apply, of a dialog box. The pvParam parameter must point to a BOOL variable
- /// that receives TRUE if the feature is on, or FALSE if it is off.
- /// Windows 95: Not supported.
- ///
- SPI_GETSNAPTODEFBUTTON = 0x005F,
-
- ///
- /// Enables or disables the snap-to-default-button feature. If enabled, the mouse cursor automatically moves to the default button,
- /// such as OK or Apply, of a dialog box. Set the uiParam parameter to TRUE to enable the feature, or FALSE to disable it.
- /// Applications should use the ShowWindow function when displaying a dialog box so the dialog manager can position the mouse cursor.
- /// Windows 95: Not supported.
- ///
- SPI_SETSNAPTODEFBUTTON = 0x0060,
- //#endif /* _WIN32_WINNT >= 0x0400 */
-
- //#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
- ///
- /// Retrieves the width, in pixels, of the rectangle within which the mouse pointer has to stay for TrackMouseEvent
- /// to generate a WM_MOUSEHOVER message. The pvParam parameter must point to a UINT variable that receives the width.
- /// Windows 95: Not supported.
- ///
- SPI_GETMOUSEHOVERWIDTH = 0x0062,
-
- ///
- /// Retrieves the width, in pixels, of the rectangle within which the mouse pointer has to stay for TrackMouseEvent
- /// to generate a WM_MOUSEHOVER message. The pvParam parameter must point to a UINT variable that receives the width.
- /// Windows 95: Not supported.
- ///
- SPI_SETMOUSEHOVERWIDTH = 0x0063,
-
- ///
- /// Retrieves the height, in pixels, of the rectangle within which the mouse pointer has to stay for TrackMouseEvent
- /// to generate a WM_MOUSEHOVER message. The pvParam parameter must point to a UINT variable that receives the height.
- /// Windows 95: Not supported.
- ///
- SPI_GETMOUSEHOVERHEIGHT = 0x0064,
-
- ///
- /// Sets the height, in pixels, of the rectangle within which the mouse pointer has to stay for TrackMouseEvent
- /// to generate a WM_MOUSEHOVER message. Set the uiParam parameter to the new height.
- /// Windows 95: Not supported.
- ///
- SPI_SETMOUSEHOVERHEIGHT = 0x0065,
-
- ///
- /// Retrieves the time, in milliseconds, that the mouse pointer has to stay in the hover rectangle for TrackMouseEvent
- /// to generate a WM_MOUSEHOVER message. The pvParam parameter must point to a UINT variable that receives the time.
- /// Windows 95: Not supported.
- ///
- SPI_GETMOUSEHOVERTIME = 0x0066,
-
- ///
- /// Sets the time, in milliseconds, that the mouse pointer has to stay in the hover rectangle for TrackMouseEvent
- /// to generate a WM_MOUSEHOVER message. This is used only if you pass HOVER_DEFAULT in the dwHoverTime parameter in the call to TrackMouseEvent. Set the uiParam parameter to the new time.
- /// Windows 95: Not supported.
- ///
- SPI_SETMOUSEHOVERTIME = 0x0067,
-
- ///
- /// Retrieves the number of lines to scroll when the mouse wheel is rotated. The pvParam parameter must point
- /// to a UINT variable that receives the number of lines. The default value is 3.
- /// Windows 95: Not supported.
- ///
- SPI_GETWHEELSCROLLLINES = 0x0068,
-
- ///
- /// Sets the number of lines to scroll when the mouse wheel is rotated. The number of lines is set from the uiParam parameter.
- /// The number of lines is the suggested number of lines to scroll when the mouse wheel is rolled without using modifier keys.
- /// If the number is 0, then no scrolling should occur. If the number of lines to scroll is greater than the number of lines viewable,
- /// and in particular if it is WHEEL_PAGESCROLL (#defined as UINT_MAX), the scroll operation should be interpreted
- /// as clicking once in the page down or page up regions of the scroll bar.
- /// Windows 95: Not supported.
- ///
- SPI_SETWHEELSCROLLLINES = 0x0069,
-
- ///
- /// Retrieves the time, in milliseconds, that the system waits before displaying a shortcut menu when the mouse cursor is
- /// over a submenu item. The pvParam parameter must point to a DWORD variable that receives the time of the delay.
- /// Windows 95: Not supported.
- ///
- SPI_GETMENUSHOWDELAY = 0x006A,
-
- ///
- /// Sets uiParam to the time, in milliseconds, that the system waits before displaying a shortcut menu when the mouse cursor is
- /// over a submenu item.
- /// Windows 95: Not supported.
- ///
- SPI_SETMENUSHOWDELAY = 0x006B,
-
- ///
- /// Determines whether the IME status window is visible (on a per-user basis). The pvParam parameter must point to a BOOL variable
- /// that receives TRUE if the status window is visible, or FALSE if it is not.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_GETSHOWIMEUI = 0x006E,
-
- ///
- /// Sets whether the IME status window is visible or not on a per-user basis. The uiParam parameter specifies TRUE for on or FALSE for off.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_SETSHOWIMEUI = 0x006F,
- //#endif
-
- //#if(WINVER >= 0x0500)
- ///
- /// Retrieves the current mouse speed. The mouse speed determines how far the pointer will move based on the distance the mouse moves.
- /// The pvParam parameter must point to an integer that receives a value which ranges between 1 (slowest) and 20 (fastest).
- /// A value of 10 is the default. The value can be set by an end user using the mouse control panel application or
- /// by an application using SPI_SETMOUSESPEED.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_GETMOUSESPEED = 0x0070,
-
- ///
- /// Sets the current mouse speed. The pvParam parameter is an integer between 1 (slowest) and 20 (fastest). A value of 10 is the default.
- /// This value is typically set using the mouse control panel application.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_SETMOUSESPEED = 0x0071,
-
- ///
- /// Determines whether a screen saver is currently running on the window station of the calling process.
- /// The pvParam parameter must point to a BOOL variable that receives TRUE if a screen saver is currently running, or FALSE otherwise.
- /// Note that only the interactive window station, "WinSta0", can have a screen saver running.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_GETSCREENSAVERRUNNING = 0x0072,
-
- ///
- /// Retrieves the full path of the bitmap file for the desktop wallpaper. The pvParam parameter must point to a buffer
- /// that receives a null-terminated path string. Set the uiParam parameter to the size, in characters, of the pvParam buffer. The returned string will not exceed MAX_PATH characters. If there is no desktop wallpaper, the returned string is empty.
- /// Windows NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_GETDESKWALLPAPER = 0x0073,
- //#endif /* WINVER >= 0x0500 */
-
- //#if(WINVER >= 0x0500)
- ///
- /// Determines whether active window tracking (activating the window the mouse is on) is on or off. The pvParam parameter must point
- /// to a BOOL variable that receives TRUE for on, or FALSE for off.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_GETACTIVEWINDOWTRACKING = 0x1000,
-
- ///
- /// Sets active window tracking (activating the window the mouse is on) either on or off. Set pvParam to TRUE for on or FALSE for off.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_SETACTIVEWINDOWTRACKING = 0x1001,
-
- ///
- /// Determines whether the menu animation feature is enabled. This master switch must be on to enable menu animation effects.
- /// The pvParam parameter must point to a BOOL variable that receives TRUE if animation is enabled and FALSE if it is disabled.
- /// If animation is enabled, SPI_GETMENUFADE indicates whether menus use fade or slide animation.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_GETMENUANIMATION = 0x1002,
-
- ///
- /// Enables or disables menu animation. This master switch must be on for any menu animation to occur.
- /// The pvParam parameter is a BOOL variable; set pvParam to TRUE to enable animation and FALSE to disable animation.
- /// If animation is enabled, SPI_GETMENUFADE indicates whether menus use fade or slide animation.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_SETMENUANIMATION = 0x1003,
-
- ///
- /// Determines whether the slide-open effect for combo boxes is enabled. The pvParam parameter must point to a BOOL variable
- /// that receives TRUE for enabled, or FALSE for disabled.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_GETCOMBOBOXANIMATION = 0x1004,
-
- ///
- /// Enables or disables the slide-open effect for combo boxes. Set the pvParam parameter to TRUE to enable the gradient effect,
- /// or FALSE to disable it.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_SETCOMBOBOXANIMATION = 0x1005,
-
- ///
- /// Determines whether the smooth-scrolling effect for list boxes is enabled. The pvParam parameter must point to a BOOL variable
- /// that receives TRUE for enabled, or FALSE for disabled.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_GETLISTBOXSMOOTHSCROLLING = 0x1006,
-
- ///
- /// Enables or disables the smooth-scrolling effect for list boxes. Set the pvParam parameter to TRUE to enable the smooth-scrolling effect,
- /// or FALSE to disable it.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_SETLISTBOXSMOOTHSCROLLING = 0x1007,
-
- ///
- /// Determines whether the gradient effect for window title bars is enabled. The pvParam parameter must point to a BOOL variable
- /// that receives TRUE for enabled, or FALSE for disabled. For more information about the gradient effect, see the GetSysColor function.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_GETGRADIENTCAPTIONS = 0x1008,
-
- ///
- /// Enables or disables the gradient effect for window title bars. Set the pvParam parameter to TRUE to enable it, or FALSE to disable it.
- /// The gradient effect is possible only if the system has a color depth of more than 256 colors. For more information about
- /// the gradient effect, see the GetSysColor function.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_SETGRADIENTCAPTIONS = 0x1009,
-
- ///
- /// Determines whether menu access keys are always underlined. The pvParam parameter must point to a BOOL variable that receives TRUE
- /// if menu access keys are always underlined, and FALSE if they are underlined only when the menu is activated by the keyboard.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_GETKEYBOARDCUES = 0x100A,
-
- ///
- /// Sets the underlining of menu access key letters. The pvParam parameter is a BOOL variable. Set pvParam to TRUE to always underline menu
- /// access keys, or FALSE to underline menu access keys only when the menu is activated from the keyboard.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_SETKEYBOARDCUES = 0x100B,
-
- ///
- /// Same as SPI_GETKEYBOARDCUES.
- ///
- SPI_GETMENUUNDERLINES = SPI_GETKEYBOARDCUES,
-
- ///
- /// Same as SPI_SETKEYBOARDCUES.
- ///
- SPI_SETMENUUNDERLINES = SPI_SETKEYBOARDCUES,
-
- ///
- /// Determines whether windows activated through active window tracking will be brought to the top. The pvParam parameter must point
- /// to a BOOL variable that receives TRUE for on, or FALSE for off.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_GETACTIVEWNDTRKZORDER = 0x100C,
-
- ///
- /// Determines whether or not windows activated through active window tracking should be brought to the top. Set pvParam to TRUE
- /// for on or FALSE for off.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_SETACTIVEWNDTRKZORDER = 0x100D,
-
- ///
- /// Determines whether hot tracking of user-interface elements, such as menu names on menu bars, is enabled. The pvParam parameter
- /// must point to a BOOL variable that receives TRUE for enabled, or FALSE for disabled.
- /// Hot tracking means that when the cursor moves over an item, it is highlighted but not selected. You can query this value to decide
- /// whether to use hot tracking in the user interface of your application.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_GETHOTTRACKING = 0x100E,
-
- ///
- /// Enables or disables hot tracking of user-interface elements such as menu names on menu bars. Set the pvParam parameter to TRUE
- /// to enable it, or FALSE to disable it.
- /// Hot-tracking means that when the cursor moves over an item, it is highlighted but not selected.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_SETHOTTRACKING = 0x100F,
-
- ///
- /// Determines whether menu fade animation is enabled. The pvParam parameter must point to a BOOL variable that receives TRUE
- /// when fade animation is enabled and FALSE when it is disabled. If fade animation is disabled, menus use slide animation.
- /// This flag is ignored unless menu animation is enabled, which you can do using the SPI_SETMENUANIMATION flag.
- /// For more information, see AnimateWindow.
- /// Windows NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_GETMENUFADE = 0x1012,
-
- ///
- /// Enables or disables menu fade animation. Set pvParam to TRUE to enable the menu fade effect or FALSE to disable it.
- /// If fade animation is disabled, menus use slide animation. he The menu fade effect is possible only if the system
- /// has a color depth of more than 256 colors. This flag is ignored unless SPI_MENUANIMATION is also set. For more information,
- /// see AnimateWindow.
- /// Windows NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_SETMENUFADE = 0x1013,
-
- ///
- /// Determines whether the selection fade effect is enabled. The pvParam parameter must point to a BOOL variable that receives TRUE
- /// if enabled or FALSE if disabled.
- /// The selection fade effect causes the menu item selected by the user to remain on the screen briefly while fading out
- /// after the menu is dismissed.
- /// Windows NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_GETSELECTIONFADE = 0x1014,
-
- ///
- /// Set pvParam to TRUE to enable the selection fade effect or FALSE to disable it.
- /// The selection fade effect causes the menu item selected by the user to remain on the screen briefly while fading out
- /// after the menu is dismissed. The selection fade effect is possible only if the system has a color depth of more than 256 colors.
- /// Windows NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_SETSELECTIONFADE = 0x1015,
-
- ///
- /// Determines whether ToolTip animation is enabled. The pvParam parameter must point to a BOOL variable that receives TRUE
- /// if enabled or FALSE if disabled. If ToolTip animation is enabled, SPI_GETTOOLTIPFADE indicates whether ToolTips use fade or slide animation.
- /// Windows NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_GETTOOLTIPANIMATION = 0x1016,
-
- ///
- /// Set pvParam to TRUE to enable ToolTip animation or FALSE to disable it. If enabled, you can use SPI_SETTOOLTIPFADE
- /// to specify fade or slide animation.
- /// Windows NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_SETTOOLTIPANIMATION = 0x1017,
-
- ///
- /// If SPI_SETTOOLTIPANIMATION is enabled, SPI_GETTOOLTIPFADE indicates whether ToolTip animation uses a fade effect or a slide effect.
- /// The pvParam parameter must point to a BOOL variable that receives TRUE for fade animation or FALSE for slide animation.
- /// For more information on slide and fade effects, see AnimateWindow.
- /// Windows NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_GETTOOLTIPFADE = 0x1018,
-
- ///
- /// If the SPI_SETTOOLTIPANIMATION flag is enabled, use SPI_SETTOOLTIPFADE to indicate whether ToolTip animation uses a fade effect
- /// or a slide effect. Set pvParam to TRUE for fade animation or FALSE for slide animation. The tooltip fade effect is possible only
- /// if the system has a color depth of more than 256 colors. For more information on the slide and fade effects,
- /// see the AnimateWindow function.
- /// Windows NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_SETTOOLTIPFADE = 0x1019,
-
- ///
- /// Determines whether the cursor has a shadow around it. The pvParam parameter must point to a BOOL variable that receives TRUE
- /// if the shadow is enabled, FALSE if it is disabled. This effect appears only if the system has a color depth of more than 256 colors.
- /// Windows NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_GETCURSORSHADOW = 0x101A,
-
- ///
- /// Enables or disables a shadow around the cursor. The pvParam parameter is a BOOL variable. Set pvParam to TRUE to enable the shadow
- /// or FALSE to disable the shadow. This effect appears only if the system has a color depth of more than 256 colors.
- /// Windows NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_SETCURSORSHADOW = 0x101B,
-
- //#if(_WIN32_WINNT >= 0x0501)
- ///
- /// Retrieves the state of the Mouse Sonar feature. The pvParam parameter must point to a BOOL variable that receives TRUE
- /// if enabled or FALSE otherwise. For more information, see About Mouse Input on MSDN.
- /// Windows 2000/NT, Windows 98/95: This value is not supported.
- ///
- SPI_GETMOUSESONAR = 0x101C,
-
- ///
- /// Turns the Sonar accessibility feature on or off. This feature briefly shows several concentric circles around the mouse pointer
- /// when the user presses and releases the CTRL key. The pvParam parameter specifies TRUE for on and FALSE for off. The default is off.
- /// For more information, see About Mouse Input.
- /// Windows 2000/NT, Windows 98/95: This value is not supported.
- ///
- SPI_SETMOUSESONAR = 0x101D,
-
- ///
- /// Retrieves the state of the Mouse ClickLock feature. The pvParam parameter must point to a BOOL variable that receives TRUE
- /// if enabled, or FALSE otherwise. For more information, see About Mouse Input.
- /// Windows 2000/NT, Windows 98/95: This value is not supported.
- ///
- SPI_GETMOUSECLICKLOCK = 0x101E,
-
- ///
- /// Turns the Mouse ClickLock accessibility feature on or off. This feature temporarily locks down the primary mouse button
- /// when that button is clicked and held down for the time specified by SPI_SETMOUSECLICKLOCKTIME. The uiParam parameter specifies
- /// TRUE for on,
- /// or FALSE for off. The default is off. For more information, see Remarks and About Mouse Input on MSDN.
- /// Windows 2000/NT, Windows 98/95: This value is not supported.
- ///
- SPI_SETMOUSECLICKLOCK = 0x101F,
-
- ///
- /// Retrieves the state of the Mouse Vanish feature. The pvParam parameter must point to a BOOL variable that receives TRUE
- /// if enabled or FALSE otherwise. For more information, see About Mouse Input on MSDN.
- /// Windows 2000/NT, Windows 98/95: This value is not supported.
- ///
- SPI_GETMOUSEVANISH = 0x1020,
-
- ///
- /// Turns the Vanish feature on or off. This feature hides the mouse pointer when the user types; the pointer reappears
- /// when the user moves the mouse. The pvParam parameter specifies TRUE for on and FALSE for off. The default is off.
- /// For more information, see About Mouse Input on MSDN.
- /// Windows 2000/NT, Windows 98/95: This value is not supported.
- ///
- SPI_SETMOUSEVANISH = 0x1021,
-
- ///
- /// Determines whether native User menus have flat menu appearance. The pvParam parameter must point to a BOOL variable
- /// that returns TRUE if the flat menu appearance is set, or FALSE otherwise.
- /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_GETFLATMENU = 0x1022,
-
- ///
- /// Enables or disables flat menu appearance for native User menus. Set pvParam to TRUE to enable flat menu appearance
- /// or FALSE to disable it.
- /// When enabled, the menu bar uses COLOR_MENUBAR for the menubar background, COLOR_MENU for the menu-popup background, COLOR_MENUHILIGHT
- /// for the fill of the current menu selection, and COLOR_HILIGHT for the outline of the current menu selection.
- /// If disabled, menus are drawn using the same metrics and colors as in Windows 2000 and earlier.
- /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_SETFLATMENU = 0x1023,
-
- ///
- /// Determines whether the drop shadow effect is enabled. The pvParam parameter must point to a BOOL variable that returns TRUE
- /// if enabled or FALSE if disabled.
- /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_GETDROPSHADOW = 0x1024,
-
- ///
- /// Enables or disables the drop shadow effect. Set pvParam to TRUE to enable the drop shadow effect or FALSE to disable it.
- /// You must also have CS_DROPSHADOW in the window class style.
- /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_SETDROPSHADOW = 0x1025,
-
- ///
- /// Retrieves a BOOL indicating whether an application can reset the screensaver's timer by calling the SendInput function
- /// to simulate keyboard or mouse input. The pvParam parameter must point to a BOOL variable that receives TRUE
- /// if the simulated input will be blocked, or FALSE otherwise.
- ///
- SPI_GETBLOCKSENDINPUTRESETS = 0x1026,
-
- ///
- /// Determines whether an application can reset the screensaver's timer by calling the SendInput function to simulate keyboard
- /// or mouse input. The uiParam parameter specifies TRUE if the screensaver will not be deactivated by simulated input,
- /// or FALSE if the screensaver will be deactivated by simulated input.
- ///
- SPI_SETBLOCKSENDINPUTRESETS = 0x1027,
- //#endif /* _WIN32_WINNT >= 0x0501 */
-
- ///
- /// Determines whether UI effects are enabled or disabled. The pvParam parameter must point to a BOOL variable that receives TRUE
- /// if all UI effects are enabled, or FALSE if they are disabled.
- /// Windows NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_GETUIEFFECTS = 0x103E,
-
- ///
- /// Enables or disables UI effects. Set the pvParam parameter to TRUE to enable all UI effects or FALSE to disable all UI effects.
- /// Windows NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_SETUIEFFECTS = 0x103F,
-
- ///
- /// Retrieves the amount of time following user input, in milliseconds, during which the system will not allow applications
- /// to force themselves into the foreground. The pvParam parameter must point to a DWORD variable that receives the time.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_GETFOREGROUNDLOCKTIMEOUT = 0x2000,
-
- ///
- /// Sets the amount of time following user input, in milliseconds, during which the system does not allow applications
- /// to force themselves into the foreground. Set pvParam to the new timeout value.
- /// The calling thread must be able to change the foreground window, otherwise the call fails.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_SETFOREGROUNDLOCKTIMEOUT = 0x2001,
-
- ///
- /// Retrieves the active window tracking delay, in milliseconds. The pvParam parameter must point to a DWORD variable
- /// that receives the time.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_GETACTIVEWNDTRKTIMEOUT = 0x2002,
-
- ///
- /// Sets the active window tracking delay. Set pvParam to the number of milliseconds to delay before activating the window
- /// under the mouse pointer.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_SETACTIVEWNDTRKTIMEOUT = 0x2003,
-
- ///
- /// Retrieves the number of times SetForegroundWindow will flash the taskbar button when rejecting a foreground switch request.
- /// The pvParam parameter must point to a DWORD variable that receives the value.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_GETFOREGROUNDFLASHCOUNT = 0x2004,
-
- ///
- /// Sets the number of times SetForegroundWindow will flash the taskbar button when rejecting a foreground switch request.
- /// Set pvParam to the number of times to flash.
- /// Windows NT, Windows 95: This value is not supported.
- ///
- SPI_SETFOREGROUNDFLASHCOUNT = 0x2005,
-
- ///
- /// Retrieves the caret width in edit controls, in pixels. The pvParam parameter must point to a DWORD that receives this value.
- /// Windows NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_GETCARETWIDTH = 0x2006,
-
- ///
- /// Sets the caret width in edit controls. Set pvParam to the desired width, in pixels. The default and minimum value is 1.
- /// Windows NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_SETCARETWIDTH = 0x2007,
-
- //#if(_WIN32_WINNT >= 0x0501)
- ///
- /// Retrieves the time delay before the primary mouse button is locked. The pvParam parameter must point to DWORD that receives
- /// the time delay. This is only enabled if SPI_SETMOUSECLICKLOCK is set to TRUE. For more information, see About Mouse Input on MSDN.
- /// Windows 2000/NT, Windows 98/95: This value is not supported.
- ///
- SPI_GETMOUSECLICKLOCKTIME = 0x2008,
-
- ///
- /// Turns the Mouse ClickLock accessibility feature on or off. This feature temporarily locks down the primary mouse button
- /// when that button is clicked and held down for the time specified by SPI_SETMOUSECLICKLOCKTIME. The uiParam parameter
- /// specifies TRUE for on, or FALSE for off. The default is off. For more information, see Remarks and About Mouse Input on MSDN.
- /// Windows 2000/NT, Windows 98/95: This value is not supported.
- ///
- SPI_SETMOUSECLICKLOCKTIME = 0x2009,
-
- ///
- /// Retrieves the type of font smoothing. The pvParam parameter must point to a UINT that receives the information.
- /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_GETFONTSMOOTHINGTYPE = 0x200A,
-
- ///
- /// Sets the font smoothing type. The pvParam parameter points to a UINT that contains either FE_FONTSMOOTHINGSTANDARD,
- /// if standard anti-aliasing is used, or FE_FONTSMOOTHINGCLEARTYPE, if ClearType is used. The default is FE_FONTSMOOTHINGSTANDARD.
- /// When using this option, the fWinIni parameter must be set to SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE; otherwise,
- /// SystemParametersInfo fails.
- ///
- SPI_SETFONTSMOOTHINGTYPE = 0x200B,
-
- ///
- /// Retrieves a contrast value that is used in ClearType™ smoothing. The pvParam parameter must point to a UINT
- /// that receives the information.
- /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_GETFONTSMOOTHINGCONTRAST = 0x200C,
-
- ///
- /// Sets the contrast value used in ClearType smoothing. The pvParam parameter points to a UINT that holds the contrast value.
- /// Valid contrast values are from 1000 to 2200. The default value is 1400.
- /// When using this option, the fWinIni parameter must be set to SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE; otherwise,
- /// SystemParametersInfo fails.
- /// SPI_SETFONTSMOOTHINGTYPE must also be set to FE_FONTSMOOTHINGCLEARTYPE.
- /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_SETFONTSMOOTHINGCONTRAST = 0x200D,
-
- ///
- /// Retrieves the width, in pixels, of the left and right edges of the focus rectangle drawn with DrawFocusRect.
- /// The pvParam parameter must point to a UINT.
- /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_GETFOCUSBORDERWIDTH = 0x200E,
-
- ///
- /// Sets the height of the left and right edges of the focus rectangle drawn with DrawFocusRect to the value of the pvParam parameter.
- /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_SETFOCUSBORDERWIDTH = 0x200F,
-
- ///
- /// Retrieves the height, in pixels, of the top and bottom edges of the focus rectangle drawn with DrawFocusRect.
- /// The pvParam parameter must point to a UINT.
- /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_GETFOCUSBORDERHEIGHT = 0x2010,
-
- ///
- /// Sets the height of the top and bottom edges of the focus rectangle drawn with DrawFocusRect to the value of the pvParam parameter.
- /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
- ///
- SPI_SETFOCUSBORDERHEIGHT = 0x2011,
-
- ///
- /// Not implemented.
- ///
- SPI_GETFONTSMOOTHINGORIENTATION = 0x2012,
-
- ///
- /// Not implemented.
- ///
- SPI_SETFONTSMOOTHINGORIENTATION = 0x2013,
- }
-
- #endregion // SPI
-
- [DllImport("user32.dll")]
- static extern int GetSystemMetrics(SystemMetric smIndex);
-
- ///
- /// Flags used with the Windows API (User32.dll):GetSystemMetrics(SystemMetric smIndex)
- ///
- /// This Enum and declaration signature was written by Gabriel T. Sharp
- /// ai_productions@verizon.net or osirisgothra@hotmail.com
- /// Obtained on pinvoke.net, please contribute your code to support the wiki!
- ///
- public enum SystemMetric : int
- {
- ///
- /// The flags that specify how the system arranged minimized windows. For more information, see the Remarks section in this topic.
- ///
- SM_ARRANGE = 56,
-
- ///
- /// The value that specifies how the system is started:
- /// 0 Normal boot
- /// 1 Fail-safe boot
- /// 2 Fail-safe with network boot
- /// A fail-safe boot (also called SafeBoot, Safe Mode, or Clean Boot) bypasses the user startup files.
- ///
- SM_CLEANBOOT = 67,
-
- ///
- /// The number of display monitors on a desktop. For more information, see the Remarks section in this topic.
- ///
- SM_CMONITORS = 80,
-
- ///
- /// The number of buttons on a mouse, or zero if no mouse is installed.
- ///
- SM_CMOUSEBUTTONS = 43,
-
- ///
- /// The width of a window border, in pixels. This is equivalent to the SM_CXEDGE value for windows with the 3-D look.
- ///
- SM_CXBORDER = 5,
-
- ///
- /// The width of a cursor, in pixels. The system cannot create cursors of other sizes.
- ///
- SM_CXCURSOR = 13,
-
- ///
- /// This value is the same as SM_CXFIXEDFRAME.
- ///
- SM_CXDLGFRAME = 7,
-
- ///
- /// The width of the rectangle around the location of a first click in a double-click sequence, in pixels. ,
- /// The second click must occur within the rectangle that is defined by SM_CXDOUBLECLK and SM_CYDOUBLECLK for the system
- /// to consider the two clicks a double-click. The two clicks must also occur within a specified time.
- /// To set the width of the double-click rectangle, call SystemParametersInfo with SPI_SETDOUBLECLKWIDTH.
- ///
- SM_CXDOUBLECLK = 36,
-
- ///
- /// The number of pixels on either side of a mouse-down point that the mouse pointer can move before a drag operation begins.
- /// This allows the user to click and release the mouse button easily without unintentionally starting a drag operation.
- /// If this value is negative, it is subtracted from the left of the mouse-down point and added to the right of it.
- ///
- SM_CXDRAG = 68,
-
- ///
- /// The width of a 3-D border, in pixels. This metric is the 3-D counterpart of SM_CXBORDER.
- ///
- SM_CXEDGE = 45,
-
- ///
- /// The thickness of the frame around the perimeter of a window that has a caption but is not sizable, in pixels.
- /// SM_CXFIXEDFRAME is the height of the horizontal border, and SM_CYFIXEDFRAME is the width of the vertical border.
- /// This value is the same as SM_CXDLGFRAME.
- ///
- SM_CXFIXEDFRAME = 7,
-
- ///
- /// The width of the left and right edges of the focus rectangle that the DrawFocusRectdraws.
- /// This value is in pixels.
- /// Windows 2000: This value is not supported.
- ///
- SM_CXFOCUSBORDER = 83,
-
- ///
- /// This value is the same as SM_CXSIZEFRAME.
- ///
- SM_CXFRAME = 32,
-
- ///
- /// The width of the client area for a full-screen window on the primary display monitor, in pixels.
- /// To get the coordinates of the portion of the screen that is not obscured by the system taskbar or by application desktop toolbars,
- /// call the SystemParametersInfofunction with the SPI_GETWORKAREA value.
- ///
- SM_CXFULLSCREEN = 16,
-
- ///
- /// The width of the arrow bitmap on a horizontal scroll bar, in pixels.
- ///
- SM_CXHSCROLL = 21,
-
- ///
- /// The width of the thumb box in a horizontal scroll bar, in pixels.
- ///
- SM_CXHTHUMB = 10,
-
- ///
- /// The default width of an icon, in pixels. The LoadIcon function can load only icons with the dimensions
- /// that SM_CXICON and SM_CYICON specifies.
- ///
- SM_CXICON = 11,
-
- ///
- /// The width of a grid cell for items in large icon view, in pixels. Each item fits into a rectangle of size
- /// SM_CXICONSPACING by SM_CYICONSPACING when arranged. This value is always greater than or equal to SM_CXICON.
- ///
- SM_CXICONSPACING = 38,
-
- ///
- /// The default width, in pixels, of a maximized top-level window on the primary display monitor.
- ///
- SM_CXMAXIMIZED = 61,
-
- ///
- /// The default maximum width of a window that has a caption and sizing borders, in pixels.
- /// This metric refers to the entire desktop. The user cannot drag the window frame to a size larger than these dimensions.
- /// A window can override this value by processing the WM_GETMINMAXINFO message.
- ///
- SM_CXMAXTRACK = 59,
-
- ///
- /// The width of the default menu check-mark bitmap, in pixels.
- ///
- SM_CXMENUCHECK = 71,
-
- ///
- /// The width of menu bar buttons, such as the child window close button that is used in the multiple document interface, in pixels.
- ///
- SM_CXMENUSIZE = 54,
-
- ///
- /// The minimum width of a window, in pixels.
- ///
- SM_CXMIN = 28,
-
- ///
- /// The width of a minimized window, in pixels.
- ///
- SM_CXMINIMIZED = 57,
-
- ///
- /// The width of a grid cell for a minimized window, in pixels. Each minimized window fits into a rectangle this size when arranged.
- /// This value is always greater than or equal to SM_CXMINIMIZED.
- ///
- SM_CXMINSPACING = 47,
-
- ///
- /// The minimum tracking width of a window, in pixels. The user cannot drag the window frame to a size smaller than these dimensions.
- /// A window can override this value by processing the WM_GETMINMAXINFO message.
- ///
- SM_CXMINTRACK = 34,
-
- ///
- /// The amount of border padding for captioned windows, in pixels. Windows XP/2000: This value is not supported.
- ///
- SM_CXPADDEDBORDER = 92,
-
- ///
- /// The width of the screen of the primary display monitor, in pixels. This is the same value obtained by calling
- /// GetDeviceCaps as follows: GetDeviceCaps( hdcPrimaryMonitor, HORZRES).
- ///
- SM_CXSCREEN = 0,
-
- ///
- /// The width of a button in a window caption or title bar, in pixels.
- ///
- SM_CXSIZE = 30,
-
- ///
- /// The thickness of the sizing border around the perimeter of a window that can be resized, in pixels.
- /// SM_CXSIZEFRAME is the width of the horizontal border, and SM_CYSIZEFRAME is the height of the vertical border.
- /// This value is the same as SM_CXFRAME.
- ///
- SM_CXSIZEFRAME = 32,
-
- ///
- /// The recommended width of a small icon, in pixels. Small icons typically appear in window captions and in small icon view.
- ///
- SM_CXSMICON = 49,
-
- ///
- /// The width of small caption buttons, in pixels.
- ///
- SM_CXSMSIZE = 52,
-
- ///
- /// The width of the virtual screen, in pixels. The virtual screen is the bounding rectangle of all display monitors.
- /// The SM_XVIRTUALSCREEN metric is the coordinates for the left side of the virtual screen.
- ///
- SM_CXVIRTUALSCREEN = 78,
-
- ///
- /// The width of a vertical scroll bar, in pixels.
- ///
- SM_CXVSCROLL = 2,
-
- ///
- /// The height of a window border, in pixels. This is equivalent to the SM_CYEDGE value for windows with the 3-D look.
- ///
- SM_CYBORDER = 6,
-
- ///
- /// The height of a caption area, in pixels.
- ///
- SM_CYCAPTION = 4,
-
- ///
- /// The height of a cursor, in pixels. The system cannot create cursors of other sizes.
- ///
- SM_CYCURSOR = 14,
-
- ///
- /// This value is the same as SM_CYFIXEDFRAME.
- ///
- SM_CYDLGFRAME = 8,
-
- ///
- /// The height of the rectangle around the location of a first click in a double-click sequence, in pixels.
- /// The second click must occur within the rectangle defined by SM_CXDOUBLECLK and SM_CYDOUBLECLK for the system to consider
- /// the two clicks a double-click. The two clicks must also occur within a specified time. To set the height of the double-click
- /// rectangle, call SystemParametersInfo with SPI_SETDOUBLECLKHEIGHT.
- ///
- SM_CYDOUBLECLK = 37,
-
- ///
- /// The number of pixels above and below a mouse-down point that the mouse pointer can move before a drag operation begins.
- /// This allows the user to click and release the mouse button easily without unintentionally starting a drag operation.
- /// If this value is negative, it is subtracted from above the mouse-down point and added below it.
- ///
- SM_CYDRAG = 69,
-
- ///
- /// The height of a 3-D border, in pixels. This is the 3-D counterpart of SM_CYBORDER.
- ///
- SM_CYEDGE = 46,
-
- ///
- /// The thickness of the frame around the perimeter of a window that has a caption but is not sizable, in pixels.
- /// SM_CXFIXEDFRAME is the height of the horizontal border, and SM_CYFIXEDFRAME is the width of the vertical border.
- /// This value is the same as SM_CYDLGFRAME.
- ///
- SM_CYFIXEDFRAME = 8,
-
- ///
- /// The height of the top and bottom edges of the focus rectangle drawn byDrawFocusRect.
- /// This value is in pixels.
- /// Windows 2000: This value is not supported.
- ///
- SM_CYFOCUSBORDER = 84,
-
- ///
- /// This value is the same as SM_CYSIZEFRAME.
- ///
- SM_CYFRAME = 33,
-
- ///
- /// The height of the client area for a full-screen window on the primary display monitor, in pixels.
- /// To get the coordinates of the portion of the screen not obscured by the system taskbar or by application desktop toolbars,
- /// call the SystemParametersInfo function with the SPI_GETWORKAREA value.
- ///
- SM_CYFULLSCREEN = 17,
-
- ///
- /// The height of a horizontal scroll bar, in pixels.
- ///
- SM_CYHSCROLL = 3,
-
- ///
- /// The default height of an icon, in pixels. The LoadIcon function can load only icons with the dimensions SM_CXICON and SM_CYICON.
- ///
- SM_CYICON = 12,
-
- ///
- /// The height of a grid cell for items in large icon view, in pixels. Each item fits into a rectangle of size
- /// SM_CXICONSPACING by SM_CYICONSPACING when arranged. This value is always greater than or equal to SM_CYICON.
- ///
- SM_CYICONSPACING = 39,
-
- ///
- /// For double byte character set versions of the system, this is the height of the Kanji window at the bottom of the screen, in pixels.
- ///
- SM_CYKANJIWINDOW = 18,
-
- ///
- /// The default height, in pixels, of a maximized top-level window on the primary display monitor.
- ///
- SM_CYMAXIMIZED = 62,
-
- ///
- /// The default maximum height of a window that has a caption and sizing borders, in pixels. This metric refers to the entire desktop.
- /// The user cannot drag the window frame to a size larger than these dimensions. A window can override this value by processing
- /// the WM_GETMINMAXINFO message.
- ///
- SM_CYMAXTRACK = 60,
-
- ///
- /// The height of a single-line menu bar, in pixels.
- ///
- SM_CYMENU = 15,
-
- ///
- /// The height of the default menu check-mark bitmap, in pixels.
- ///
- SM_CYMENUCHECK = 72,
-
- ///
- /// The height of menu bar buttons, such as the child window close button that is used in the multiple document interface, in pixels.
- ///
- SM_CYMENUSIZE = 55,
-
- ///
- /// The minimum height of a window, in pixels.
- ///
- SM_CYMIN = 29,
-
- ///
- /// The height of a minimized window, in pixels.
- ///
- SM_CYMINIMIZED = 58,
-
- ///
- /// The height of a grid cell for a minimized window, in pixels. Each minimized window fits into a rectangle this size when arranged.
- /// This value is always greater than or equal to SM_CYMINIMIZED.
- ///
- SM_CYMINSPACING = 48,
-
- ///
- /// The minimum tracking height of a window, in pixels. The user cannot drag the window frame to a size smaller than these dimensions.
- /// A window can override this value by processing the WM_GETMINMAXINFO message.
- ///
- SM_CYMINTRACK = 35,
-
- ///
- /// The height of the screen of the primary display monitor, in pixels. This is the same value obtained by calling
- /// GetDeviceCaps as follows: GetDeviceCaps( hdcPrimaryMonitor, VERTRES).
- ///
- SM_CYSCREEN = 1,
-
- ///
- /// The height of a button in a window caption or title bar, in pixels.
- ///
- SM_CYSIZE = 31,
-
- ///
- /// The thickness of the sizing border around the perimeter of a window that can be resized, in pixels.
- /// SM_CXSIZEFRAME is the width of the horizontal border, and SM_CYSIZEFRAME is the height of the vertical border.
- /// This value is the same as SM_CYFRAME.
- ///
- SM_CYSIZEFRAME = 33,
-
- ///
- /// The height of a small caption, in pixels.
- ///
- SM_CYSMCAPTION = 51,
-
- ///
- /// The recommended height of a small icon, in pixels. Small icons typically appear in window captions and in small icon view.
- ///
- SM_CYSMICON = 50,
-
- ///
- /// The height of small caption buttons, in pixels.
- ///
- SM_CYSMSIZE = 53,
-
- ///
- /// The height of the virtual screen, in pixels. The virtual screen is the bounding rectangle of all display monitors.
- /// The SM_YVIRTUALSCREEN metric is the coordinates for the top of the virtual screen.
- ///
- SM_CYVIRTUALSCREEN = 79,
-
- ///
- /// The height of the arrow bitmap on a vertical scroll bar, in pixels.
- ///
- SM_CYVSCROLL = 20,
-
- ///
- /// The height of the thumb box in a vertical scroll bar, in pixels.
- ///
- SM_CYVTHUMB = 9,
-
- ///
- /// Nonzero if User32.dll supports DBCS; otherwise, 0.
- ///
- SM_DBCSENABLED = 42,
-
- ///
- /// Nonzero if the debug version of User.exe is installed; otherwise, 0.
- ///
- SM_DEBUG = 22,
-
- ///
- /// Nonzero if the current operating system is Windows 7 or Windows Server 2008 R2 and the Tablet PC Input
- /// service is started; otherwise, 0. The return value is a bitmask that specifies the type of digitizer input supported by the device.
- /// For more information, see Remarks.
- /// Windows Server 2008, Windows Vista, and Windows XP/2000: This value is not supported.
- ///
- SM_DIGITIZER = 94,
-
- ///
- /// Nonzero if Input Method Manager/Input Method Editor features are enabled; otherwise, 0.
- /// SM_IMMENABLED indicates whether the system is ready to use a Unicode-based IME on a Unicode application.
- /// To ensure that a language-dependent IME works, check SM_DBCSENABLED and the system ANSI code page.
- /// Otherwise the ANSI-to-Unicode conversion may not be performed correctly, or some components like fonts
- /// or registry settings may not be present.
- ///
- SM_IMMENABLED = 82,
-
- ///
- /// Nonzero if there are digitizers in the system; otherwise, 0. SM_MAXIMUMTOUCHES returns the aggregate maximum of the
- /// maximum number of contacts supported by every digitizer in the system. If the system has only single-touch digitizers,
- /// the return value is 1. If the system has multi-touch digitizers, the return value is the number of simultaneous contacts
- /// the hardware can provide. Windows Server 2008, Windows Vista, and Windows XP/2000: This value is not supported.
- ///
- SM_MAXIMUMTOUCHES = 95,
-
- ///
- /// Nonzero if the current operating system is the Windows XP, Media Center Edition, 0 if not.
- ///
- SM_MEDIACENTER = 87,
-
- ///
- /// Nonzero if drop-down menus are right-aligned with the corresponding menu-bar item; 0 if the menus are left-aligned.
- ///
- SM_MENUDROPALIGNMENT = 40,
-
- ///
- /// Nonzero if the system is enabled for Hebrew and Arabic languages, 0 if not.
- ///
- SM_MIDEASTENABLED = 74,
-
- ///
- /// Nonzero if a mouse is installed; otherwise, 0. This value is rarely zero, because of support for virtual mice and because
- /// some systems detect the presence of the port instead of the presence of a mouse.
- ///
- SM_MOUSEPRESENT = 19,
-
- ///
- /// Nonzero if a mouse with a horizontal scroll wheel is installed; otherwise 0.
- ///
- SM_MOUSEHORIZONTALWHEELPRESENT = 91,
-
- ///
- /// Nonzero if a mouse with a vertical scroll wheel is installed; otherwise 0.
- ///
- SM_MOUSEWHEELPRESENT = 75,
-
- ///
- /// The least significant bit is set if a network is present; otherwise, it is cleared. The other bits are reserved for future use.
- ///
- SM_NETWORK = 63,
-
- ///
- /// Nonzero if the Microsoft Windows for Pen computing extensions are installed; zero otherwise.
- ///
- SM_PENWINDOWS = 41,
-
- ///
- /// This system metric is used in a Terminal Services environment to determine if the current Terminal Server session is
- /// being remotely controlled. Its value is nonzero if the current session is remotely controlled; otherwise, 0.
- /// You can use terminal services management tools such as Terminal Services Manager (tsadmin.msc) and shadow.exe to
- /// control a remote session. When a session is being remotely controlled, another user can view the contents of that session
- /// and potentially interact with it.
- ///
- SM_REMOTECONTROL = 0x2001,
-
- ///
- /// This system metric is used in a Terminal Services environment. If the calling process is associated with a Terminal Services
- /// client session, the return value is nonzero. If the calling process is associated with the Terminal Services console session,
- /// the return value is 0.
- /// Windows Server 2003 and Windows XP: The console session is not necessarily the physical console.
- /// For more information, seeWTSGetActiveConsoleSessionId.
- ///
- SM_REMOTESESSION = 0x1000,
-
- ///
- /// Nonzero if all the display monitors have the same color format, otherwise, 0. Two displays can have the same bit depth,
- /// but different color formats. For example, the red, green, and blue pixels can be encoded with different numbers of bits,
- /// or those bits can be located in different places in a pixel color value.
- ///
- SM_SAMEDISPLAYFORMAT = 81,
-
- ///
- /// This system metric should be ignored; it always returns 0.
- ///
- SM_SECURE = 44,
-
- ///
- /// The build number if the system is Windows Server 2003 R2; otherwise, 0.
- ///
- SM_SERVERR2 = 89,
-
- ///
- /// Nonzero if the user requires an application to present information visually in situations where it would otherwise present
- /// the information only in audible form; otherwise, 0.
- ///
- SM_SHOWSOUNDS = 70,
-
- ///
- /// Nonzero if the current session is shutting down; otherwise, 0. Windows 2000: This value is not supported.
- ///
- SM_SHUTTINGDOWN = 0x2000,
-
- ///
- /// Nonzero if the computer has a low-end (slow) processor; otherwise, 0.
- ///
- SM_SLOWMACHINE = 73,
-
- ///
- /// Nonzero if the current operating system is Windows 7 Starter Edition, Windows Vista Starter, or Windows XP Starter Edition; otherwise, 0.
- ///
- SM_STARTER = 88,
-
- ///
- /// Nonzero if the meanings of the left and right mouse buttons are swapped; otherwise, 0.
- ///
- SM_SWAPBUTTON = 23,
-
- ///
- /// Nonzero if the current operating system is the Windows XP Tablet PC edition or if the current operating system is Windows Vista
- /// or Windows 7 and the Tablet PC Input service is started; otherwise, 0. The SM_DIGITIZER setting indicates the type of digitizer
- /// input supported by a device running Windows 7 or Windows Server 2008 R2. For more information, see Remarks.
- ///
- SM_TABLETPC = 86,
-
- ///
- /// The coordinates for the left side of the virtual screen. The virtual screen is the bounding rectangle of all display monitors.
- /// The SM_CXVIRTUALSCREEN metric is the width of the virtual screen.
- ///
- SM_XVIRTUALSCREEN = 76,
-
- ///
- /// The coordinates for the top of the virtual screen. The virtual screen is the bounding rectangle of all display monitors.
- /// The SM_CYVIRTUALSCREEN metric is the height of the virtual screen.
- ///
- SM_YVIRTUALSCREEN = 77,
- }
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
- public class MONITORINFOEX
- {
- public int cbSize = Marshal.SizeOf(typeof(MONITORINFOEX));
- public RECT rcMonitor = new RECT();
- public RECT rcWork = new RECT();
- public int dwFlags = 0;
-
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
- public char[] szDevice = new char[32];
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public class COMRECT
- {
- public int left;
- public int top;
- public int right;
- public int bottom;
-
- public COMRECT()
- {
- }
-
- public COMRECT(System.Drawing.Rectangle r)
- {
- left = (int)r.X;
- top = (int)r.Y;
- right = (int)r.Right;
- bottom = (int)r.Bottom;
- }
-
- public COMRECT(int left, int top, int right, int bottom)
- {
- this.left = left;
- this.top = top;
- this.right = right;
- this.bottom = bottom;
- }
- }
-
- [Flags]
- public enum DisplayDeviceStateFlags : int
- {
- /// The device is part of the desktop.
- AttachedToDesktop = 0x1,
-
- MultiDriver = 0x2,
-
- /// The device is part of the desktop.
- PrimaryDevice = 0x4,
-
- ///
- /// Represents a pseudo device used to mirror application drawing for remoting or other purposes.
- ///
- MirroringDriver = 0x8,
-
- /// The device is VGA compatible.
- VGACompatible = 0x10,
-
- ///
- /// The device is removable; it cannot be the primary display.
- ///
- Removable = 0x20,
-
- ///
- /// The device has more display modes than its output devices support.
- ///
- ModesPruned = 0x8000000,
-
- Remote = 0x4000000,
- Disconnect = 0x2000000
- }
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct DISPLAY_DEVICE
- {
- [MarshalAs(UnmanagedType.U4)]
- public int cb;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
- public string DeviceName;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
- public string DeviceString;
-
- [MarshalAs(UnmanagedType.U4)]
- public DisplayDeviceStateFlags StateFlags;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
- public string DeviceID;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
- public string DeviceKey;
- }
-
- [DllImport("user32.dll", ExactSpelling = true)]
- public static extern IntPtr MonitorFromWindow(HandleRef handle, int flags);
-
- [DllImport("user32.dll", ExactSpelling = true)]
- public static extern IntPtr MonitorFromPoint(POINT pt, int flags);
-
- [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
- public static extern int GetSystemMetrics(int nIndex);
-
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- public static extern bool GetMonitorInfo(HandleRef hmonitor, [In, Out] MONITORINFOEX info);
-
- public delegate bool MonitorEnumProc(IntPtr monitor, IntPtr hdc, IntPtr lprcMonitor, IntPtr lParam);
-
- [DllImport("user32.dll", ExactSpelling = true)]
- public static extern bool EnumDisplayMonitors(HandleRef hdc, COMRECT rcClip, MonitorEnumProc lpfnEnum, IntPtr dwData);
-
-
- [DllImport("user32.dll", CharSet = CharSet.Unicode)]
- public static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags);
-
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- public static extern bool SystemParametersInfo(int nAction, int nParam, ref RECT rc, int nUpdate);
-
- public const int EDD_GET_DEVICE_INTERFACE_NAME = 0x00000001;
-
- #endregion //display mgr
-}
-#pragma warning restore CA1707, CA1401, CA1712
diff --git a/Canopy.Windows/NativeUtils.cs b/Canopy.Windows/NativeUtils.cs
deleted file mode 100644
index 32b92fd..0000000
--- a/Canopy.Windows/NativeUtils.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-namespace Canopy.Windows;
-
-public static class NativeUtils
-{
- public static bool HasExtendedStyle(IntPtr hwnd, uint style)
- {
- if (hwnd == IntPtr.Zero)
- return false;
-
- IntPtr exStylePtr = Native.GetWindowLongPtr(hwnd, (int)Native.GWL.GWL_EXSTYLE);
- if (exStylePtr == IntPtr.Zero)
- return false;
-
- return (exStylePtr.ToInt64() & style) != 0;
- }
-
- public static IntPtr GetProgman() => Native.FindWindow("Progman", null!);
-
- public static IntPtr GetDesktopWorkerW()
- {
- var progman = GetProgman();
- var workerWOrig = IntPtr.Zero;
- var folderView = Native.FindWindowEx(progman, IntPtr.Zero, "SHELLDLL_DefView", null!);
- if (folderView != IntPtr.Zero)
- return workerWOrig != IntPtr.Zero ? workerWOrig : progman;
-
- //If the desktop isn't under Progman, cycle through the WorkerW handles and find the correct one
- do
- {
- workerWOrig = Native.FindWindowEx(Native.GetDesktopWindow(), workerWOrig, "WorkerW", null!);
- folderView = Native.FindWindowEx(workerWOrig, IntPtr.Zero, "SHELLDLL_DefView", null!);
- } while (folderView == IntPtr.Zero && workerWOrig != IntPtr.Zero);
-
- // Win 11
- return workerWOrig != IntPtr.Zero ? workerWOrig : progman;
- }
-
- public static IntPtr GetLastChildWindow(IntPtr parent)
- {
- IntPtr lastChild = IntPtr.Zero;
-
- Native.EnumChildWindows(parent, (hWnd, lParam) =>
- {
- lastChild = hWnd;
- return true;
- }, IntPtr.Zero);
-
- return lastChild;
- }
-}
diff --git a/Canopy.Windows/Program.cs b/Canopy.Windows/Program.cs
index b16f4f6..ec009a4 100644
--- a/Canopy.Windows/Program.cs
+++ b/Canopy.Windows/Program.cs
@@ -6,6 +6,7 @@ namespace Canopy.Windows;
internal class Program
{
+ [STAThread]
private static void Main(string[] args)
{
using var log = new LoggerConfiguration()
@@ -15,7 +16,9 @@ private static void Main(string[] args)
Log.Logger = log;
- var canopy = new CanopyPlatformWindows();
+ var canopy = new Canopy(new CanopyPlatformWindows());
canopy.Initialize();
+
+
}
}
diff --git a/Canopy.Windows/WindowsDiagnostics.cs b/Canopy.Windows/WindowsDiagnostics.cs
deleted file mode 100644
index b6fc3a0..0000000
--- a/Canopy.Windows/WindowsDiagnostics.cs
+++ /dev/null
@@ -1,105 +0,0 @@
-using System.Runtime.InteropServices;
-using System.Text;
-using Serilog;
-
-namespace Canopy.Windows;
-
-public static class WindowDiagnostics
-{
- // Raw P/Invoke to avoid any Vanara wrapper uncertainty
- [DllImport("user32.dll")] private static extern bool GetWindowRect(IntPtr h, out RECT r);
- [DllImport("user32.dll")] private static extern int GetWindowLong(IntPtr h, int idx);
- [DllImport("user32.dll")] private static extern bool IsWindowVisible(IntPtr h);
- [DllImport("user32.dll")] private static extern IntPtr GetWindow(IntPtr h, uint cmd);
- [DllImport("user32.dll")] private static extern IntPtr GetTopWindow(IntPtr h);
- [DllImport("user32.dll")] private static extern IntPtr GetParent(IntPtr h);
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- private static extern int GetClassName(IntPtr h, StringBuilder sb, int max);
-
- [StructLayout(LayoutKind.Sequential)]
- private struct RECT { public int L, T, R, B; }
-
- private const int GWL_STYLE = -16;
- private const int GWL_EXSTYLE = -20;
- private const uint GW_HWNDNEXT = 2;
-
- private const uint WS_CHILD = 0x40000000;
- private const uint WS_VISIBLE = 0x10000000;
- private const uint WS_EX_LAYERED = 0x00080000;
- private const uint WS_EX_NOREDIRBITMAP = 0x00200000; // Win11 HDR / layered shell flag
- private const uint WS_EX_TRANSPARENT = 0x00000020;
-
- ///
- /// Dumps the full window subtree rooted at .
- /// Pass your SDL handle as to mark it in the output.
- ///
- public static void DumpTree(IntPtr root, string label, IntPtr highlight = default)
- {
- Log.Information("┌── {Label} ──────────────────────────────────────────", label);
- Walk(root, 0, highlight);
- Log.Information("└─────────────────────────────────────────────────────");
- }
-
- ///
- /// Quick one-liner about a single window — useful for spot-checks.
- ///
- public static void DumpWindow(IntPtr hwnd, string label)
- {
- Log.Information("[Diag:{Label}] {Info}", label, Describe(hwnd, false));
- }
-
- // ─── internals ────────────────────────────────────────────────────────────
-
- private static void Walk(IntPtr hwnd, int depth, IntPtr highlight)
- {
- if (hwnd == IntPtr.Zero) return;
-
- var isSdl = hwnd == highlight;
- var indent = new string(' ', depth * 3);
- var arrow = isSdl ? " ◄◄◄ SDL WINDOW" : "";
-
- Log.Information("{Indent}{Info}{Arrow}", indent, Describe(hwnd, isSdl), arrow);
-
- var child = GetTopWindow(hwnd);
- while (child != IntPtr.Zero)
- {
- Walk(child, depth + 1, highlight);
- child = GetWindow(child, GW_HWNDNEXT);
- }
- }
-
- private static string Describe(IntPtr hwnd, bool isSdl)
- {
- var sb = new StringBuilder(256);
- GetClassName(hwnd, sb, sb.Capacity);
- var cls = sb.ToString();
-
- GetWindowRect(hwnd, out var r);
- var w = r.R - r.L;
- var h = r.B - r.T;
-
- var style = unchecked((uint)GetWindowLong(hwnd, GWL_STYLE));
- var exStyle = unchecked((uint)GetWindowLong(hwnd, GWL_EXSTYLE));
-
- var vis = IsWindowVisible(hwnd);
- var isChild = (style & WS_CHILD) != 0;
- var noRedir = (exStyle & WS_EX_NOREDIRBITMAP) != 0; // critical on Win11
- var layered = (exStyle & WS_EX_LAYERED) != 0;
- var transp = (exStyle & WS_EX_TRANSPARENT) != 0;
-
- var parent = GetParent(hwnd);
-
- // Highlight any suspicious flags in the output
- var flags = new List();
- if (!vis) flags.Add("!HIDDEN");
- if (!isChild) flags.Add("TOP-LEVEL");
- if (noRedir) flags.Add("NO-REDIR"); // present on Progman on Win11
- if (layered) flags.Add("LAYERED");
- if (transp) flags.Add("TRANSPARENT");
- if (w == 0 || h == 0) flags.Add("ZERO-SIZE");
-
- var flagStr = flags.Count > 0 ? $" [{string.Join(' ', flags)}]" : "";
-
- return $"[{hwnd:X8}] {cls} | {w}x{h} @{r.L},{r.T} | parent={parent:X8} | style=0x{style:X8}{flagStr}";
- }
-}
diff --git a/Canopy.Windows/WindowsGLContext.cs b/Canopy.Windows/WindowsGLContext.cs
deleted file mode 100644
index cf2687d..0000000
--- a/Canopy.Windows/WindowsGLContext.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2026 SynesthesiaDev . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using System.Runtime.InteropServices;
-using Canopy.Rendering;
-
-namespace Canopy.Windows;
-
-public class WindowsGLContext : INativeContext
-{
- public IntPtr GetProcAddress(string procName)
- {
- IntPtr addr = wglGetProcAddress(procName);
-
- // wglGetProcAddress returns 0, 1, 2, 3, or -1 if it fails or if the function is a core 1.1 function.
- if (addr == IntPtr.Zero || addr == 1 || addr == 2 || addr == 3 || addr == -1)
- {
- // fallback look inside opengl32.dll directly
- IntPtr module = GetModuleHandle("opengl32.dll");
- addr = GetProcAddress(module, procName);
- }
-
- return addr;
- }
-
- [DllImport("opengl32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
- private static extern IntPtr wglGetProcAddress(string lpszProc);
-
- [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
- private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
-
- [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
- private static extern IntPtr GetModuleHandle(string lpModuleName);
-
- public bool TryGetProcAddress(string procName, out IntPtr addr)
- {
- addr = GetProcAddress(procName);
- return addr != IntPtr.Zero;
- }
-}
diff --git a/Canopy.Windows/canopy.ico b/Canopy.Windows/canopy.ico
new file mode 100644
index 0000000..84fd9e0
Binary files /dev/null and b/Canopy.Windows/canopy.ico differ
diff --git a/Canopy.sln.DotSettings.user b/Canopy.sln.DotSettings.user
index 534fa6d..85749bc 100644
--- a/Canopy.sln.DotSettings.user
+++ b/Canopy.sln.DotSettings.user
@@ -1,2 +1,9 @@
- ForceIncluded
\ No newline at end of file
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
\ No newline at end of file
diff --git a/README.md b/README.md
index 944fe5a..c4cdb7e 100644
--- a/README.md
+++ b/README.md
@@ -6,20 +6,18 @@


-**A lightweight, highly customizable dynamic and animated wallpaper engine for Windows.**
-
-*(Maybe on Linux and Mac too in the future)*
+A lightweight wallpaper engine that automatically switches your desktop based on real-world conditions like time of day, weather, season, and holidays.
---
### ⚡ Features
-- **☀️ Dynamic Environments**
- - Automatically switch wallpapers based on real-time conditions like time of day, current weather, or any custom conditions
-- **🎨 Custom Shader Support:**
- - Attach and render custom glsl shaders directly onto your desktop
-- **🌙 Lua Scripting:**
- - Highly extensible and easily configurable. Write simple or complex Luau scripts to automate transitions and logic
+- **☀️ Condition-Based Wallpapers**
+ - Automatically switch wallpapers based on time of day, current weather, season, and holidays
+- **🔌 WebSocket Support:**
+ - Canopy can broadcast the current wallpaper along with info like it's accent color over a local WebSocket, so other apps (e.g. zebar) can theme themselves to match automatically
+- **🖥️ System Theme Sync**
+ - Optionally switch your system's light/dark theme alongside the wallpaper based on time of day
- 🚫 **No AI Slop**
- Purely written by passionete single-brain-celled autistic individual
@@ -35,6 +33,19 @@
### 🛠️ Configuration
-Canopy is configured via [Luau](https://luau.org/), making configuration incredibly flexible
+Canopy is configured via a `config.synx` file, written in [Synx](https://github.com/SynesthesiaDev/Synx). A default config with a starter wallpaper set is generated automatically on first launch:
+
+```synx
+Wallpapers = [
+ {
+ Path = "./default/beach.jpg"
+ Time = ["Afternoon"]
+ Weather = ["Clear"]
+ Season = ["Summer"]
+ Holiday = null
+ Accent = "#207ad9"
+ }
+
+```
-//todo example
\ No newline at end of file
+See the [full config schema](https://github.com/SynesthesiaDev/Canopy/blob/main/schema.md) for every available option.
diff --git a/schema.md b/schema.md
new file mode 100644
index 0000000..a3adb10
--- /dev/null
+++ b/schema.md
@@ -0,0 +1,312 @@
+# Config Schema
+
+Config is written in the [Synx](https://github.com/SynesthesiaDev/Synx) language which is very easy to understand and write even without any knowledge of it but **the TLDR is:**
+- Types with `?` after them are nullable, you can specify `null` directly or just don't define them at all
+- Enums are defined as string so with "string quotes"
+
+Below are all schemas related to the config file.
+
+## Config
+
+- `_schemaVersion` - Automatic variable inserted by a codec, don't touch or stuff breaky!!!
+- `_schema` - Link to this! Does nothing other than that
+- `General` - General section
+- `System` - System section
+- `Updater` - Updater section
+- `Weather` - Weather section
+- `Websocket` - Websocket section
+- `Wallpapers` - Wallpapers section
+
+## General
+
+- `AutoStartOnStartup`
+ - Automatically start Canopy when system starts up
+ - Type: `Boolean`
+
+- `RefreshPeriod`
+ - Interval at which Canopy will check current conditions and potentially apply new wallpaper _(Keep in mind, the API limit for weather api is 10,000 requests a day!)_
+ - Type: `Int`
+
+- `FitMode`
+ - How the wallpaper will be applied
+ - Type: `Enum` [`Fill`, `Stretch`, `Tile`, `Center` or `Span`]
+
+## System
+
+- `UseLegacyWindowsApi`
+ - Uses legacy windows api for compatibility
+ - Type: `Boolean`
+
+- `ApplyToAllMacOsSpaces`
+ - Apply wallpapers to all MacOS spaces
+ - Type: `Boolean`
+
+- `UpdateLockScreen`
+ - Update the lock screen with the wallpaper as well
+ - Type: `Boolean`
+
+- `DontUpdateWhenBatteryLow`
+ - Don't run new checks when device battery is low
+ - Type: `Boolean`
+
+- `ChangeSystemThemesDependingOnTime`
+ - Change to dark theme when `Night` is selected and light mode when `Morning` is selected
+ - Type: `Boolean`
+
+## Updater
+
+- `ReleaseStream`
+ - What release stream the auto updater uses
+ - Type: `Enum` [`Release`, `PreRelease`]
+
+- `AutoUpdate`
+ - Should new updates be automatically downloaded when Canopy launches
+ - Type: `Boolean`
+
+- `Source`
+ - Source for the release stream (must be github releases)
+ - Type: `String`
+
+## Weather
+
+- `UseAutoLocation`
+ - Automatically detects your location from your IP Address _(Not sent anywhere.. what are we.. microslop?)_
+ - Type: `Boolean`
+
+- `OfflineFallback`
+ - What should happen if you are offline and requests cannot be made
+ - Type: `Enum` [`UseLastKnownState`, `IgnoreWeather`]
+
+- `Coordinates`
+ - Manual coordinates
+ - Type: `Coordinates?`
+
+## Coordinates
+
+- `Latitude`
+ - Your latitude
+ - Type: `Double`
+
+- `Longitude`
+ - Your longitude
+ - Type: `Double`
+
+## Websocket
+
+- `Enabled`
+ - Should Canopy start a websocket server on startup
+ - Type: `Boolean`
+
+- `Url`
+ - URL of the websocket. Must include `http://` at the beginning and `:port` at the end _(example: `http://localhost:5808/`)_
+ - Type: `String`
+
+
+### Websocket Message Schemas
+
+Following are the schemas for messages Canopy sends over the websocket as JSON:
+
+#### `/update` - NewWallpaperMessage
+
+- `Timestamp`
+ - Timestamp of wallpaper change
+ - Type: `Long`
+
+- `Wallpaper`
+ - the new Wallpaper object
+ - Type: `Wallpaper`
+
+## Wallpaper
+
+- `Path`
+ - Path to the image relative to the `.canopy` folder in user folder
+ - Type: `String`
+
+- `Time`
+ - List of Time enum, indicating at what time of day should the wallpaper appear
+ - Type: `List of Time` [`Sunrise`, `Morning`, `Afternoon`, `Sunset`, `Night`, `DeepNight`]
+
+- `Weather`
+ - List of Weather enum, indicating at what weather should the wallpaper appear
+ - Type: `List of Weather` [`Clear`, `Cloudy`, `Rainy`, `Stormy`]
+
+- `Season`
+ - List of Season enum, indicating during what season should the wallpaper appear
+ - Type: `List of Season` [`Spring`, `Summer`, `Autumn`, `Winter`]
+
+- `Holiday`
+ - Indicating during what holiday this wallpaper should appear. **Note that `Holiday` overrides any other condition and is always picked**. Can be null or missing
+ - Type: `Holiday?` [`Christmas`, `NewYear`, `Easter`, `Halloween`]
+
+- `Accent`
+ - Hex color for accent color, not used internally, but is sent in websocket messages so other programs may use it
+ - Type: `String?`
+
+**(Note that you may leave any of the lists empty or not define them to mark them as wildcard, meaning it will be allowed in any time/weather/season)**
+
+# Default Config File
+
+```hocon
+_schemaVersion = 1
+_schema = "https://github.com/SynesthesiaDev/Canopy/blob/main/schema.md"
+General = {
+ AutoStartOnStartup = true
+ RefreshPeriod = 60000
+ FitMode = "Fill"
+}
+System = {
+ UseLegacyWindowsApi = false
+ ApplyToAllMacOsSpaces = true
+ UpdateLockScreen = false
+ DontUpdateWhenBatteryLow = true
+}
+Updater = {
+ ReleaseStream = "Release"
+ AutoUpdate = true
+ Source = "https://github.com/SynesthesiaDev/Canopy/releases"
+}
+Weather = {
+ UseAutoLocation = true
+ RefreshInterval = 60000
+ OfflineFallback = "UseLastKnownState"
+ Coordinates = {
+ Longitude = 14.421194
+ Latitude = 50.087555
+ }
+}
+Websocket = {
+ Enabled = false
+ Url = "http://localhost:5808/"
+}
+Wallpapers = [
+ {
+ Path = "./default/cloudy-quasar.png"
+ Time = ["Night", "DeepNight"]
+ Weather = ["Cloudy"]
+ Season = []
+ Holiday = null
+ Accent = "#c5d9d7"
+ },
+ {
+ Path = "./default/beach.jpg"
+ Time = ["Afternoon"]
+ Weather = ["Clear"]
+ Season = ["Summer"]
+ Holiday = null
+ Accent = "#207ad9"
+ },
+ {
+ Path = "./default/halloween.jpg"
+ Time = []
+ Weather = []
+ Season = []
+ Holiday = "Halloween"
+ Accent = "#f56b3d"
+ },
+ {
+ Path = "./default/eclipse.jpg"
+ Time = ["Sunset"]
+ Weather = ["Cloudy", "Clear"]
+ Season = []
+ Holiday = null
+ Accent = "#f4545e"
+ },
+ {
+ Path = "./default/flower-field.jpg"
+ Time = ["Morning", "Afternoon"]
+ Weather = ["Clear"]
+ Season = ["Spring"]
+ Holiday = null
+ Accent = "#9ca15e"
+ },
+ {
+ Path = "./default/i-touch-this.jpg"
+ Time = ["Morning"]
+ Weather = ["Clear"]
+ Season = []
+ Holiday = null
+ Accent = "#89b238"
+ },
+ {
+ Path = "./default/pink-clouds.jpg"
+ Time = ["Sunset", "Sunrise"]
+ Weather = ["Clear", "Cloudy"]
+ Season = []
+ Holiday = null
+ Accent = "#e69c94"
+ },
+ {
+ Path = "./default/snowflakes.jpg"
+ Time = ["Night", "DeepNight"]
+ Weather = ["Rainy", "Clear"]
+ Season = ["Winter"]
+ Holiday = null
+ Accent = "#c2e6ff"
+ },
+ {
+ Path = "./default/swirly-painting.jpg"
+ Time = ["Sunset", "Sunrise"]
+ Weather = ["Clear", "Cloudy"]
+ Season = []
+ Holiday = null
+ Accent = "#df7488"
+ },
+ {
+ Path = "./default/flowering-rain.png"
+ Time = ["Morning", "Afternoon"]
+ Weather = ["Rainy", "Stormy"]
+ Season = []
+ Holiday = null
+ Accent = "#598fb1"
+ },
+ {
+ Path = "./default/fallback/Sunrise.jpg"
+ Time = ["Sunrise"]
+ Weather = []
+ Season = []
+ Holiday = null
+ Accent = "#1a4a4a"
+ },
+ {
+ Path = "./default/fallback/Morning.jpg"
+ Time = ["Morning"]
+ Weather = []
+ Season = []
+ Holiday = null
+ Accent = "#1b4a40"
+ },
+ {
+ Path = "./default/fallback/Afternoon.jpg"
+ Time = ["Afternoon"]
+ Weather = []
+ Season = []
+ Holiday = null
+ Accent = "#3d76a1"
+ },
+ {
+ Path = "./default/fallback/Sunset.jpg"
+ Time = ["Sunset"]
+ Weather = []
+ Season = []
+ Holiday = null
+ Accent = "#e56f32"
+ },
+ {
+ Path = "./default/fallback/Night.jpg"
+ Time = ["Night"]
+ Weather = []
+ Season = []
+ Holiday = null
+ Accent = "#314d3f"
+ },
+ {
+ Path = "./default/fallback/DeepNight.jpg"
+ Time = ["DeepNight"]
+ Weather = []
+ Season = []
+ Holiday = null
+ Accent = "#1b2836"
+ }
+]
+
+```
\ No newline at end of file