Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
b7fbf5e
Move (some) menu command handling to NotifyIcon
res2k Jun 23, 2024
6e4449f
Internally rename 'autostart' to 'login startup'
res2k Jun 23, 2024
3623444
Move 'login startup' config into separate class
res2k Jun 23, 2024
5ab1e34
HDRCmd: Add ability to change 'startup when logging in'
res2k Jun 23, 2024
b305490
Add docs for new 'status' HDRCmd command
res2k Jun 23, 2024
5f2db54
Rename hdr::Display to hdr::DisplayInfo
res2k Jun 23, 2024
2fc7cb6
Add & use hdr::DisplayID internal type
res2k Jun 30, 2024
9afc39f
Make hdr::DisplayID public
res2k Jun 30, 2024
93556a4
Change hdr::DisplayInfo to lazily return status, name
res2k Jun 30, 2024
b5b5481
Implement hdr::GetWindowsHDRStatus() using GetDisplays()
res2k Jun 30, 2024
6aac538
Add hdr::DisplayInfo::GetID()
res2k Jun 30, 2024
1033a5d
Implement hdr::SetWindowsHDRStatus() using GetDisplays()
res2k Jun 30, 2024
9eacaf3
Change HDR functions to take explicit displays list
res2k Jun 30, 2024
f00e630
Store DisplayInfo errors as HRESULT
res2k Jun 30, 2024
24cdedd
Add DisplayInfo::GetStableID()
res2k Jun 30, 2024
01f09ad
Statically allocate LoginStartupConfig
res2k Jul 7, 2024
77cb561
Add RegistryKey move ctors, assignment
res2k Jul 7, 2024
e80390d
Add RegistryKey::GetValue()
res2k Jul 7, 2024
21e9dcd
Add DisplayConfig class
res2k Jul 7, 2024
06c7db3
HDRCmd: Move some status functions to separate source
res2k Jul 7, 2024
4eec988
Print whether a display is 'selected' or not in long status
res2k Jul 7, 2024
dcc82be
Add 'index' to DisplayInfo
res2k Jul 7, 2024
2991c98
HDRCmd: Implement 'select' subcommand to toggle which displays to inc…
res2k Jul 7, 2024
371c600
Add hdr::GetEnabledDisplays()
res2k Aug 11, 2024
f12b285
HDRCmd: Add subcommand base class for those involving displays
res2k Aug 11, 2024
3c584b6
Add DisplayID::operator==
res2k Aug 11, 2024
6b4806f
HDRCmd: Add displays argument to on, off commands
res2k Aug 11, 2024
9ce4c7c
HDRCmd: Only consider selected displays for short, exitcode status
res2k Aug 11, 2024
1ba9dca
HDRTray: Only consider selected displays for notification icon
res2k Aug 11, 2024
6aab115
common: Expose registry path used by DisplayConfig
res2k Aug 11, 2024
aeedb2c
HDRTray: Add watcher for display config changes
res2k Aug 11, 2024
a65052a
common: Add RegistryKey::Open()
res2k Aug 11, 2024
fe259bf
common: Only 'open' registry key when querying enabled flag
res2k Aug 11, 2024
c7a8eb6
Add documentation on display selection
res2k Aug 11, 2024
6434659
Bump minimum required Windows to 10 1809
res2k Aug 11, 2024
59d9e49
Add winui3_cmake as a submodule
res2k Dec 14, 2024
567ef04
Add mock-up HDRTrayConfig
res2k Dec 14, 2024
edd4b06
Move version.h to common
res2k Dec 20, 2024
3ea35ee
Add some more fields to version.h
res2k Dec 20, 2024
4cd3d28
Add actual version number to HDRTrayConfig About
res2k Dec 20, 2024
3531ba8
Add IsOn property to ToggleCard
res2k Dec 20, 2024
10f0838
Expose Toggled event from ToggleCard
res2k Dec 21, 2024
f2cf0a6
Use generated winrt headers for common
res2k Dec 21, 2024
3aa3d18
Fix warning when using 'common' in HDRTrayConfig
res2k Dec 21, 2024
45164b9
Add HDRViewModel class, use as member of App
res2k Dec 21, 2024
3f3487f
Update HDR status on display change
res2k Dec 21, 2024
c9b06eb
Hook up HDR toggling to HDRPage
res2k Dec 22, 2024
c9855ce
Programmatically get list of displays
res2k Dec 24, 2024
fe66c12
Add & use HDRViewModel::IsHDRAvailable()
res2k Dec 25, 2024
1346116
Move DisplayConfigWatcher to common
res2k Dec 25, 2024
0583d0a
Update HDRViewModel on display config change
res2k Dec 25, 2024
c8f25c5
Add spaceship operator to DisplayID
res2k Dec 25, 2024
76fd123
Reuse HDRDisplay objects
res2k Dec 25, 2024
a4911a6
Add more fields to HDRDisplay
res2k Dec 25, 2024
d135e5b
Always store use display config from wow64_64 keys
res2k Dec 25, 2024
9ad97c2
Hook up display selection toggling
res2k Dec 25, 2024
20df324
Factor out RegistryWatcher
res2k Dec 26, 2024
9160925
Add LoginStartupConfigWatcher
res2k Dec 26, 2024
5829eb0
Provide plumbing to make 'Start when logging in' toggle do something
res2k Dec 26, 2024
731f714
Switch to two-way HDRViewModel::IsHDREnabled property
res2k Dec 26, 2024
7e258fa
Switch to two-way HDRDisplay::IsSelected property
res2k Dec 27, 2024
a280f2d
Switch to two-way SettingsViewModel::IsLoginStartupEnabled
res2k Dec 27, 2024
8948fcc
Launch HDRTrayConfig from notification icon context menu
res2k Dec 27, 2024
11a1542
Add resource file to HDRTrayConfig
res2k Dec 27, 2024
bf3443d
Add window icon to HDRTrayConfig
res2k Dec 27, 2024
3ddbd47
Add custom title bar to HDRTrayConfig
res2k Dec 27, 2024
ddf59fc
Make AboutPage links work
res2k Dec 28, 2024
0aa8977
Tweak MainWindow navigation behavior
res2k Dec 28, 2024
3aaec1d
Also install HDRTrayConfig
res2k Dec 28, 2024
40053ee
Add resource_common.h
res2k Dec 31, 2024
fc71ab2
Customize 'App Runtime not found' dialog
res2k Jan 1, 2025
4317abb
Update copyright
res2k Jan 1, 2025
18ba7d6
Handle display changes in HDRTrayConfig
res2k Jan 1, 2025
b233ce4
Always update HDR status after displays changed
res2k Jan 1, 2025
76977fc
Fix show argument for HDRTrayConfig
res2k Mar 25, 2025
71b974a
Update to stable WinUI3 1.7
res2k Mar 25, 2025
fe56d8d
Add function to get description string for error code
res2k Jul 3, 2025
32b7c01
Move NotifyIcon balloon tip to separate method
res2k Jul 3, 2025
998bfb6
Show a balloon tip when toggling 'Start when logging in' failed
res2k Jul 3, 2025
b68a56c
Also add periodic HDR status re-check to HDRTrayConfig
res2k Aug 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
[submodule "ext/CLI11"]
path = ext/CLI11
url = https://github.com/CLIUtils/CLI11
[submodule "ext/winui3_cmake"]
path = ext/winui3_cmake
url = https://github.com/res2k/winui3_cmake
27 changes: 25 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ set(VERSION_MINOR ${GITVERSIONDETECT_VERSION_MINOR})
set(VERSION_REVISION ${GITVERSIONDETECT_VERSION_PATCH})
set(VERSION_BUILD ${GITVERSIONDETECT_VERSION_COMMIT_NUM})
set(VERSION_FULL ${GITVERSIONDETECT_VERSION})
set(VERSION_COMMIT ${GITVERSIONDETECT_VERSION_COMMIT_SHA})
set(COPYRIGHT_STR "Copyright (c) 2022-2025 Frank Richter")

set(CMAKE_CXX_STANDARD 23)
Expand Down Expand Up @@ -62,11 +63,29 @@ endif()
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)

add_subdirectory(ext)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/ext/winui3_cmake/cmake")

# We need to use the same CppWinRT version for common and HDRTrayConfig,
# so generate headers from the nuget packages
include(nuget)
nuget_install()

set(WINSDK_VERSION 10.0.17763.0)

include(find_platform_winmds)
include(run_cppwinrt)
find_platform_winmds(PATHS_VAR PLATFORM_WINMD_PATHS WINSDK_VERSION ${WINSDK_VERSION})
run_cppwinrt(TARGET platform_cppwinrt
OUT "${CMAKE_CURRENT_BINARY_DIR}/generated"
IN ${PLATFORM_WINMD_PATHS})
include_directories("${CMAKE_CURRENT_BINARY_DIR}/generated")

add_subdirectory(common)
add_dependencies(common platform_cppwinrt)

add_subdirectory(HDRTray)
add_subdirectory(HDRCmd)
add_subdirectory(HDRTray)
add_subdirectory(HDRTrayConfig)

if(MARKO_AVAILABLE)
set(MD2HTML "${CMAKE_CURRENT_SOURCE_DIR}/build/md2html.py")
Expand All @@ -85,9 +104,13 @@ if(MARKO_AVAILABLE)
add_custom_target(ConvertMD ALL DEPENDS ${GENERATED_HTML_FILES})
endif()

install(TARGETS HDRTray HDRCmd
install(TARGETS HDRTray HDRCmd HDRTrayConfig
RUNTIME
DESTINATION ".")
install(FILES
"$<TARGET_FILE_DIR:HDRTrayConfig>/Microsoft.WindowsAppRuntime.Bootstrap.dll"
"$<TARGET_FILE_DIR:HDRTrayConfig>/HDRTrayConfig.pri"
DESTINATION ".")
if(MARKO_AVAILABLE)
foreach(md_file LICENSE README)
install(FILES "${MD_OUTPUT_DIR}/${md_file}.html"
Expand Down
11 changes: 10 additions & 1 deletion HDRCmd/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
configure_file(version.h.in "${CMAKE_CURRENT_BINARY_DIR}/generated/version.h")
configure_file(version.rc.in "${CMAKE_CURRENT_BINARY_DIR}/generated/version.rc")

add_executable(HDRCmd)
target_sources(HDRCmd PRIVATE
"HDRCmd.cpp"
"HDRCmd.manifest"
"HDRCmd.rc"
"subcommand/display_status.hpp"
"subcommand/display_status.cpp"
"subcommand/resolve_display.hpp"
"subcommand/resolve_display.cpp"
"subcommand/Base.hpp"
"subcommand/Disable.hpp"
"subcommand/Disable.cpp"
"subcommand/DisplayUsing.hpp"
"subcommand/DisplayUsing.cpp"
"subcommand/Enable.hpp"
"subcommand/Enable.cpp"
"subcommand/LoginStartup.hpp"
"subcommand/LoginStartup.cpp"
"subcommand/Select.hpp"
"subcommand/Select.cpp"
"subcommand/Status.hpp"
"subcommand/Status.cpp"
)
Expand Down
16 changes: 13 additions & 3 deletions HDRCmd/HDRCmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@

#include "subcommand/Disable.hpp"
#include "subcommand/Enable.hpp"
#include "subcommand/LoginStartup.hpp"
#include "subcommand/Select.hpp"
#include "subcommand/Status.hpp"
#include "version.h"
#include "WinVerCheck.hpp"

#include <format>

#include <winrt/Windows.Foundation.h>

static std::string failure_message(const CLI::App *app, const CLI::Error &e) {
return std::format("Invalid command line arguments: {}\n\n{}", e.what(), app->help());
}
Expand All @@ -34,12 +38,16 @@ int wmain(int argc, const wchar_t* const argv[])
{
CLI::App app{"HDRCmd " VERSION_FULL " - turn \"Use HDR\" on or off from command line"};

// if Windows 10 < version 1803 refuse to start
if (!IsWindows10_1803OrGreater()) {
std::cerr << "Sorry, HDRCmd only works on Windows 10, version 1803 and above" << std::endl;
// if Windows 10 < version 1809 refuse to start
if (!IsWindows10_1809OrGreater()) {
std::cerr << "Sorry, HDRCmd only works on Windows 10, version 1809 and above" << std::endl;
return -2;
}

// Init WinRT. For monitor stable ID.
// FIXME: Obtain lazily?
winrt::init_apartment();

app.allow_windows_style_options();
app.ignore_case();
app.require_subcommand(1);
Expand All @@ -48,6 +56,8 @@ int wmain(int argc, const wchar_t* const argv[])
subcommand::Status::add(app);
subcommand::Enable::add(app);
subcommand::Disable::add(app);
subcommand::Select::add(app);
subcommand::LoginStartup::add(app);

CLI11_PARSE(app, argc, argv);
const auto* subcmd = app.get_subcommands()[0];
Expand Down
7 changes: 5 additions & 2 deletions HDRCmd/subcommand/Disable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@

namespace subcommand {

Disable::Disable(CLI::App* parent) : Base("Turn HDR off", "off", parent) { }
Disable::Disable(CLI::App* parent) : DisplayUsing("Turn HDR off", "off", parent)
{
add_displays_option(this, default_displays_option_name, "Displays to consider");
}

int Disable::run() const
{
auto result = hdr::SetWindowsHDRStatus(false);
auto result = hdr::SetWindowsHDRStatus(GetSelectedDisplays(), false);
if (!result)
return -1;
return *result == hdr::Status::Off ? 0 : 1;
Expand Down
4 changes: 2 additions & 2 deletions HDRCmd/subcommand/Disable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
#ifndef SUBCOMMAND_DISABLE_HPP_
#define SUBCOMMAND_DISABLE_HPP_

#include "Base.hpp"
#include "DisplayUsing.hpp"

namespace subcommand {
class Disable : public Base
class Disable : public DisplayUsing
{
protected:
Disable(CLI::App* parent);
Expand Down
52 changes: 52 additions & 0 deletions HDRCmd/subcommand/DisplayUsing.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
HDRCmd - enable/disable "Use HDR" from command line
Copyright (C) 2024 Frank Richter

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#include "DisplayUsing.hpp"

#include "resolve_display.hpp"

namespace subcommand {

const char* DisplayUsing::default_displays_option_name = "-d,--displays";

CLI::Option* DisplayUsing::add_displays_option(CLI::App* app, std::string option_name, std::string option_description)
{
return app->add_option(option_name, display_ids, option_description)->type_name("# or NAME");
}

hdr::DisplayInfo_vec DisplayUsing::GetSelectedDisplays() const
{
if (display_ids.empty())
return hdr::GetEnabledDisplays();

auto all_displays = hdr::GetDisplays();
hdr::DisplayInfo_vec selected_displays;
for(const auto& disp_id : display_ids) {
if (const auto* disp = resolve_display(all_displays, disp_id)) {
if (std::find_if(selected_displays.begin(), selected_displays.end(),
[disp](const hdr::DisplayInfo& already_selected) {
return already_selected.GetID() == disp->GetID();
}) != selected_displays.end())
continue;
selected_displays.push_back(*disp);
}
}
return selected_displays;
}

}
50 changes: 50 additions & 0 deletions HDRCmd/subcommand/DisplayUsing.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
HDRCmd - enable/disable "Use HDR" from command line
Copyright (C) 2024 Frank Richter

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#ifndef SUBCOMMAND_DISPLAYUSING_HPP_
#define SUBCOMMAND_DISPLAYUSING_HPP_

#include "Base.hpp"

#include "HDR.h"

namespace subcommand {

class DisplayUsing : public Base
{
protected:
/// Default name for "optional" display specification
static const char* default_displays_option_name;
/// Display IDs given on command line
std::vector<std::string> display_ids;

/// Add an option for explicit display selection. Fills display_ids
CLI::Option* add_displays_option(CLI::App* app, std::string option_name, std::string option_description);

/// Return selected displays, from command line, if explicitly given, or configuration by default
hdr::DisplayInfo_vec GetSelectedDisplays() const;

template<typename... Arg>
DisplayUsing(Arg&&... arg) : Base(std::forward<Arg>(arg)...)
{
}
};

} // namespace subcommand

#endif // SUBCOMMAND_DISPLAYUSING_HPP_
7 changes: 5 additions & 2 deletions HDRCmd/subcommand/Enable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@

namespace subcommand {

Enable::Enable(CLI::App* parent) : Base("Turn HDR on", "on", parent) { }
Enable::Enable(CLI::App* parent) : DisplayUsing("Turn HDR on", "on", parent)
{
add_displays_option(this, default_displays_option_name, "Displays to consider");
}

int Enable::run() const
{
auto result = hdr::SetWindowsHDRStatus(true);
auto result = hdr::SetWindowsHDRStatus(GetSelectedDisplays(), true);
if (!result)
return -1;
return *result == hdr::Status::On ? 0 : 1;
Expand Down
4 changes: 2 additions & 2 deletions HDRCmd/subcommand/Enable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
#ifndef SUBCOMMAND_ENABLE_HPP_
#define SUBCOMMAND_ENABLE_HPP_

#include "Base.hpp"
#include "DisplayUsing.hpp"

namespace subcommand {
class Enable : public Base
class Enable : public DisplayUsing
{
protected:
Enable(CLI::App* parent);
Expand Down
78 changes: 78 additions & 0 deletions HDRCmd/subcommand/LoginStartup.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
HDRCmd - enable/disable "Use HDR" from command line
Copyright (C) 2024 Frank Richter

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#include "LoginStartup.hpp"

#include "LoginStartupConfig.hpp"

#include <array>
#include <format>
#include <print>

namespace subcommand {

LoginStartup::LoginStartup(CLI::App* parent) : Base("Change 'Start when logging in'", "startup", parent)
{
add_subcommand("status", "Print current status of option");
add_subcommand("on", "Turn 'Start when logging in' on");
add_subcommand("off", "Turn 'Start when logging in' off");
}

int LoginStartup::print_status(bool active)
{
auto status_result = LoginStartupConfig::instance().IsEnabled();
if (!status_result) {
std::println("Could not get login startup state, error {}", status_result.error());
return status_result.error();
}

auto status_str = *status_result ? "ON" : "OFF";
if (active)
std::println("'Start when logging in' is now {}", status_str);
else
std::println("'Start when logging in' is {}", status_str);
return 0;
}

int LoginStartup::run() const
{
bool has_status = got_subcommand("status");
bool has_on = got_subcommand("on");
bool has_off = got_subcommand("off");

if (has_on || has_off) {
auto enable_result = LoginStartupConfig::instance().SetEnabled(has_on);
if (!enable_result) {
std::println("Could not change login startup state, error {}", enable_result.error());
return enable_result.error();
}
}

if (!has_status && !has_on && !has_off) {
// No explicit command given: also include help text
std::cout << help() << std::endl;
}
return print_status(has_on || has_off);
}

CLI::App* LoginStartup::add(CLI::App& app)
{
return app.add_subcommand(std::shared_ptr<LoginStartup>(new LoginStartup(&app)));
}

} // namespace subcommand
Loading
Loading