UI: Improvements and fixes for Windows dark mode (#1728)

This commit is contained in:
Crementif 2025-11-22 23:26:27 +01:00 committed by GitHub
parent 1382ee0381
commit 934cc3eb9d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 180 additions and 203 deletions

View file

@ -5,6 +5,7 @@ project(wxwidgets-example)
add_executable(main WIN32 popup.cpp) add_executable(main WIN32 popup.cpp)
find_package(wxWidgets REQUIRED) find_package(wxWidgets REQUIRED)
target_compile_features(main PRIVATE cxx_std_11)
target_compile_definitions(main PRIVATE ${wxWidgets_DEFINITIONS} "$<$<CONFIG:DEBUG>:${wxWidgets_DEFINITIONS_DEBUG}>") target_compile_definitions(main PRIVATE ${wxWidgets_DEFINITIONS} "$<$<CONFIG:DEBUG>:${wxWidgets_DEFINITIONS_DEBUG}>")
target_include_directories(main PRIVATE ${wxWidgets_INCLUDE_DIRS}) target_include_directories(main PRIVATE ${wxWidgets_INCLUDE_DIRS})
target_link_libraries(main PRIVATE ${wxWidgets_LIBRARIES}) target_link_libraries(main PRIVATE ${wxWidgets_LIBRARIES})
@ -13,6 +14,7 @@ add_executable(main2 WIN32 popup.cpp)
find_package(wxWidgets CONFIG REQUIRED) find_package(wxWidgets CONFIG REQUIRED)
target_link_libraries(main2 PRIVATE wx::core wx::base) target_link_libraries(main2 PRIVATE wx::core wx::base)
target_compile_features(main2 PRIVATE cxx_std_11)
option(USE_WXRC "Use the wxrc resource compiler" ON) option(USE_WXRC "Use the wxrc resource compiler" ON)
if(USE_WXRC) if(USE_WXRC)

View file

@ -1,25 +0,0 @@
diff --git a/src/msw/listctrl.cpp b/src/msw/listctrl.cpp
index 2b9e0d7f7e..7eab8b37df 100644
--- a/src/msw/listctrl.cpp
+++ b/src/msw/listctrl.cpp
@@ -3110,6 +3110,11 @@ bool HandleSubItemPrepaint(wxListCtrl* listctrl, LPNMLVCUSTOMDRAW pLVCD, HFONT h
if ( it.iImage != -1 )
{
+ if ( !listctrl->HasCheckBoxes() )
+ {
+ rc.left -= 6;
+ }
+
const int yImage = rc.top + ((rc.bottom - rc.top) / 2 - hImage / 2);
ImageList_Draw(himl, it.iImage, hdc, rc.left, yImage,
nmcd.uItemState & CDIS_SELECTED ? ILD_SELECTED
@@ -3235,7 +3240,7 @@ void HandleItemPaint(wxListCtrl* listctrl, LPNMLVCUSTOMDRAW pLVCD, HFONT hfont)
// do not draw item background colour under the checkbox/image
RECT rcIcon;
wxGetListCtrlItemRect(nmcd.hdr.hwndFrom, nmcd.dwItemSpec, LVIR_ICON, rcIcon);
- if ( !::IsRectEmpty(&rcIcon) )
+ if ( !::IsRectEmpty(&rcIcon) && listctrl->HasCheckBoxes() )
rc.left = rcIcon.right + listctrl->FromDIP(GAP_BETWEEN_CHECKBOX_AND_TEXT);
}

View file

@ -1,39 +1,45 @@
diff --git a/build/cmake/init.cmake b/build/cmake/init.cmake diff --git a/build/cmake/init.cmake b/build/cmake/init.cmake
index f044d22d4d..48fc5ad072 100644 index 4ed7b264ef..195d776aeb 100644
--- a/build/cmake/init.cmake --- a/build/cmake/init.cmake
+++ b/build/cmake/init.cmake +++ b/build/cmake/init.cmake
@@ -198,7 +198,7 @@ if(WIN32) @@ -201,11 +201,11 @@ endif()
endif() wx_get_install_dir(include)
endif() if(WIN32_MSVC_NAMING)
-if(WIN32_MSVC_NAMING)
+if(0)
if(wxBUILD_SHARED) if(wxBUILD_SHARED)
set(lib_suffix "_dll") - set(lib_suffix "_dll")
+ # set(lib_suffix "_dll")
else() else()
- set(lib_suffix "_lib")
+ # set(lib_suffix "_lib")
endif()
- set(wxPLATFORM_LIB_DIR "${wxCOMPILER_PREFIX}${wxARCH_SUFFIX}${lib_suffix}")
+ # set(wxPLATFORM_LIB_DIR "${wxCOMPILER_PREFIX}${wxARCH_SUFFIX}${lib_suffix}")
set(wxINSTALL_INCLUDE_DIR "${include_dir}")
else()
wx_get_flavour(lib_flavour "-")
diff --git a/build/cmake/install.cmake b/build/cmake/install.cmake diff --git a/build/cmake/install.cmake b/build/cmake/install.cmake
index a373983043..2e1ace7bf9 100644 index cbbefdebe9..8f2759d5ad 100644
--- a/build/cmake/install.cmake --- a/build/cmake/install.cmake
+++ b/build/cmake/install.cmake +++ b/build/cmake/install.cmake
@@ -63,7 +63,7 @@ else() @@ -66,7 +66,7 @@ else()
wx_get_install_platform_dir(runtime)
install(DIRECTORY DESTINATION "bin") install(DIRECTORY DESTINATION "${runtime_dir}")
install(CODE "execute_process( \ install(CODE "execute_process( \
- COMMAND ${CMAKE_COMMAND} -E create_symlink \ - COMMAND ${CMAKE_COMMAND} -E create_symlink \
+ COMMAND ${CMAKE_COMMAND} -E copy \ + COMMAND ${CMAKE_COMMAND} -E copy \
\"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/wx/config/${wxBUILD_FILE_ID}\" \ \"${CMAKE_INSTALL_PREFIX}/${library_dir}/wx/config/${wxBUILD_FILE_ID}\" \
\"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/wx-config\" \ \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${runtime_dir}/wx-config\" \
)" )"
diff --git a/build/cmake/utils/CMakeLists.txt b/build/cmake/utils/CMakeLists.txt diff --git a/build/cmake/utils/CMakeLists.txt b/build/cmake/utils/CMakeLists.txt
index 15f4339ef9..f93849e025 100644 index 608351ac42..d8110f9148 100644
--- a/build/cmake/utils/CMakeLists.txt --- a/build/cmake/utils/CMakeLists.txt
+++ b/build/cmake/utils/CMakeLists.txt +++ b/build/cmake/utils/CMakeLists.txt
@@ -39,7 +39,7 @@ if(wxUSE_XRC) @@ -40,7 +40,7 @@ if(wxUSE_XRC)
# Don't use wx_install() here to preserve escaping. # Don't use wx_install() here to preserve escaping.
install(CODE "execute_process( \ install(CODE "execute_process( \
- COMMAND ${CMAKE_COMMAND} -E create_symlink \ - COMMAND ${CMAKE_COMMAND} -E create_symlink \
+ COMMAND ${CMAKE_COMMAND} -E copy \ + COMMAND ${CMAKE_COMMAND} -E copy \
\"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/${wxrc_output_name}${EXE_SUFFIX}\" \ \"${CMAKE_INSTALL_PREFIX}/${runtime_dir}/${wxrc_output_name}${EXE_SUFFIX}\" \
\"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/wxrc${EXE_SUFFIX}\" \ \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${runtime_dir}/wxrc${EXE_SUFFIX}\" \
)" )"

View file

@ -1,13 +1,12 @@
diff --git a/build/cmake/wxWidgetsConfig.cmake.in b/build/cmake/wxWidgetsConfig.cmake.in diff --git a/build/cmake/wxWidgetsConfig.cmake.in b/build/cmake/wxWidgetsConfig.cmake.in
index b251109..60cf762 100644 index 2f3a735d92..c134900764 100644
--- a/build/cmake/wxWidgetsConfig.cmake.in --- a/build/cmake/wxWidgetsConfig.cmake.in
+++ b/build/cmake/wxWidgetsConfig.cmake.in +++ b/build/cmake/wxWidgetsConfig.cmake.in
@@ -1,5 +1,8 @@ @@ -155,6 +155,7 @@ foreach(libname @wxLIB_TARGETS@)
@PACKAGE_INIT@ endforeach()
+include(CMakeFindDependencyMacro) include(CMakeFindDependencyMacro)
+find_dependency(NanoSVG CONFIG) +find_dependency(NanoSVG CONFIG)
+
cmake_policy(PUSH) if(TARGET wx::wxnet AND @wxUSE_WEBREQUEST_CURL@)
# Set policies to prevent warnings # make sure CURL targets are available:
if(POLICY CMP0057)

View file

@ -1,8 +1,8 @@
vcpkg_from_github( vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH OUT_SOURCE_PATH SOURCE_PATH
REPO wxWidgets/wxWidgets REPO wxWidgets/wxWidgets
REF "v${VERSION}" REF "bfd436b"
SHA512 8ad17582c4ba721ffe76ada4bb8bd7bc4b050491220aca335fd0506a51354fb789d5bc3d965f0f459dc81784d6427c88272e2acc2099cddf73730231b5a16f62 SHA512 bd3fd6d0d0db3b6fa34eceae1119e21ffd2f62221dcd249f8b8b82a6e65d83a05101e4e1e4ca9b9c4d7937add73b113bb029b03b05d2c3d87d17c1922d800a24
HEAD_REF master HEAD_REF master
PATCHES PATCHES
install-layout.patch install-layout.patch
@ -12,9 +12,26 @@ vcpkg_from_github(
fix-pcre2.patch fix-pcre2.patch
gtk3-link-libraries.patch gtk3-link-libraries.patch
sdl2.patch sdl2.patch
fix-dark-mode-offset.patch
) )
# Submodule dependencies
vcpkg_from_github(
OUT_SOURCE_PATH lexilla_SOURCE_PATH
REPO wxWidgets/lexilla
REF "27c20a6ae5eebf418debeac0166052ed6fb653bc"
SHA512 7e5de7f664509473b691af8261fca34c2687772faca7260eeba5f2984516e6f8edf88c27192e056c9dda996e2ad2c20f6d1dff1c4bd2f3c0d74852cb50ca424a
HEAD_REF wx
)
file(COPY "${lexilla_SOURCE_PATH}/" DESTINATION "${SOURCE_PATH}/src/stc/lexilla")
vcpkg_from_github(
OUT_SOURCE_PATH scintilla_SOURCE_PATH
REPO wxWidgets/scintilla
REF "0b90f31ced23241054e8088abb50babe9a44ae67"
SHA512 db1f3007f4bd8860fad0817b6cf87980a4b713777025128cf5caea8d6d17b6fafe23fd22ff6886d7d5a420f241d85b7502b85d7e52b4ddb0774edc4b0a0203e7
HEAD_REF wx
)
file(COPY "${scintilla_SOURCE_PATH}/" DESTINATION "${SOURCE_PATH}/src/stc/scintilla")
vcpkg_check_features( vcpkg_check_features(
OUT_FEATURE_OPTIONS FEATURE_OPTIONS OUT_FEATURE_OPTIONS FEATURE_OPTIONS
FEATURES FEATURES
@ -52,14 +69,20 @@ if(VCPKG_TARGET_IS_WINDOWS)
endif() endif()
endif() endif()
if("webview" IN_LIST FEATURES AND VCPKG_LIBRARY_LINKAGE STREQUAL "static")
list(APPEND OPTIONS -DwxUSE_WEBVIEW_EDGE_STATIC=ON)
endif()
vcpkg_find_acquire_program(PKGCONFIG) vcpkg_find_acquire_program(PKGCONFIG)
# This may be set to ON by users in a custom triplet. # This may be set to ON by users in a custom triplet.
# The use of 'wxUSE_STL' and 'WXWIDGETS_USE_STD_CONTAINERS' (ON or OFF) are not API compatible # The use of 'WXWIDGETS_USE_STD_CONTAINERS' (ON or OFF) is not API compatible
# which is why they must be set in a custom triplet rather than a port feature. # which is why it must be set in a custom triplet rather than a port feature.
# For backwards compatibility, we also replace 'wxUSE_STL' (which no longer
# exists) with 'wxUSE_STD_STRING_CONV_IN_WXSTRING' which still exists and was
# set by `wxUSE_STL` previously.
if(NOT DEFINED WXWIDGETS_USE_STL) if(NOT DEFINED WXWIDGETS_USE_STL)
set(WXWIDGETS_USE_STL OFF) set(WXWIDGETS_USE_STL OFF)
set(WXWIDGETS_USE_STD_STRING_CONV_IN_WXSTRING OFF)
endif() endif()
if(NOT DEFINED WXWIDGETS_USE_STD_CONTAINERS) if(NOT DEFINED WXWIDGETS_USE_STD_CONTAINERS)
@ -70,19 +93,18 @@ vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}" SOURCE_PATH "${SOURCE_PATH}"
OPTIONS OPTIONS
${FEATURE_OPTIONS} ${FEATURE_OPTIONS}
-DwxUSE_STC=OFF
-DwxUSE_REGEX=sys -DwxUSE_REGEX=sys
-DwxUSE_ZLIB=sys -DwxUSE_ZLIB=sys
-DwxUSE_EXPAT=sys -DwxUSE_EXPAT=sys
-DwxUSE_LIBJPEG=sys -DwxUSE_LIBJPEG=sys
-DwxUSE_LIBPNG=sys -DwxUSE_LIBPNG=sys
-DwxUSE_LIBTIFF=sys -DwxUSE_LIBTIFF=sys
-DwxUSE_LIBWEBP=sys
-DwxUSE_NANOSVG=sys -DwxUSE_NANOSVG=sys
-DwxUSE_LIBWEBP=sys
-DwxUSE_GLCANVAS=ON -DwxUSE_GLCANVAS=ON
-DwxUSE_LIBGNOMEVFS=OFF -DwxUSE_LIBGNOMEVFS=OFF
-DwxUSE_LIBNOTIFY=OFF -DwxUSE_LIBNOTIFY=OFF
-DwxUSE_STD_STRING_CONV_IN_WXSTRING=${WXWIDGETS_USE_STD_STRING_CONV_IN_WXSTRING} -DwxUSE_STD_STRING_CONV_IN_WXSTRING=${WXWIDGETS_USE_STL}
-DwxUSE_STD_CONTAINERS=${WXWIDGETS_USE_STD_CONTAINERS} -DwxUSE_STD_CONTAINERS=${WXWIDGETS_USE_STD_CONTAINERS}
-DwxUSE_UIACTIONSIMULATOR=OFF -DwxUSE_UIACTIONSIMULATOR=OFF
-DCMAKE_DISABLE_FIND_PACKAGE_GSPELL=ON -DCMAKE_DISABLE_FIND_PACKAGE_GSPELL=ON
@ -101,7 +123,7 @@ vcpkg_cmake_configure(
) )
vcpkg_cmake_install() vcpkg_cmake_install()
vcpkg_cmake_config_fixup(CONFIG_PATH lib/cmake/wxWidgets) vcpkg_cmake_config_fixup(CONFIG_PATH lib/cmake/wxWidgets-3.3)
# The CMake export is not ready for use: It lacks a config file. # The CMake export is not ready for use: It lacks a config file.
file(REMOVE_RECURSE file(REMOVE_RECURSE
@ -126,6 +148,11 @@ vcpkg_copy_pdbs()
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/include/msvc") file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/include/msvc")
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include")
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/lib/mswu")
if(VCPKG_BUILD_TYPE STREQUAL "release")
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/lib/mswud")
endif()
file(GLOB_RECURSE INCLUDES "${CURRENT_PACKAGES_DIR}/include/*.h") file(GLOB_RECURSE INCLUDES "${CURRENT_PACKAGES_DIR}/include/*.h")
if(EXISTS "${CURRENT_PACKAGES_DIR}/lib/mswu/wx/setup.h") if(EXISTS "${CURRENT_PACKAGES_DIR}/lib/mswu/wx/setup.h")
list(APPEND INCLUDES "${CURRENT_PACKAGES_DIR}/lib/mswu/wx/setup.h") list(APPEND INCLUDES "${CURRENT_PACKAGES_DIR}/lib/mswu/wx/setup.h")
@ -191,12 +218,30 @@ endif()
if("example" IN_LIST FEATURES) if("example" IN_LIST FEATURES)
file(INSTALL file(INSTALL
"${CMAKE_CURRENT_LIST_DIR}/example/CMakeLists.txt" "${CMAKE_CURRENT_LIST_DIR}/minimal_example/CMakeLists.txt"
"${SOURCE_PATH}/samples/popup/popup.cpp" "${SOURCE_PATH}/samples/minimal/minimal.cpp"
"${SOURCE_PATH}/samples/sample.xpm" "${SOURCE_PATH}/samples/sample.xpm"
DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}/example" "${SOURCE_PATH}/samples/sample.rc"
DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}/minimal_example"
) )
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/${PORT}/example/popup.cpp" "../sample.xpm" "sample.xpm")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/${PORT}/minimal_example/minimal.cpp" "../sample.xpm" "sample.xpm")
endif()
if("example" IN_LIST FEATURES)
file(INSTALL
"${CMAKE_CURRENT_LIST_DIR}/listctrl_example/CMakeLists.txt"
"${SOURCE_PATH}/samples/listctrl/listtest.cpp"
"${SOURCE_PATH}/samples/listctrl/listtest.h"
"${SOURCE_PATH}/samples/listctrl/listtest.rc"
"${SOURCE_PATH}/samples/sample.xpm"
"${SOURCE_PATH}/samples/sample.rc"
"${SOURCE_PATH}/samples/listctrl/bitmaps"
DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}/listctrl_example"
)
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/${PORT}/listctrl_example/listtest.cpp" "../sample.xpm" "sample.xpm")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/${PORT}/listctrl_example/listtest.rc" "../sample.rc" "sample.rc")
endif() endif()
configure_file("${CMAKE_CURRENT_LIST_DIR}/vcpkg-cmake-wrapper.cmake" "${CURRENT_PACKAGES_DIR}/share/${PORT}/vcpkg-cmake-wrapper.cmake" @ONLY) configure_file("${CMAKE_CURRENT_LIST_DIR}/vcpkg-cmake-wrapper.cmake" "${CURRENT_PACKAGES_DIR}/share/${PORT}/vcpkg-cmake-wrapper.cmake" @ONLY)

View file

@ -1,8 +1,8 @@
diff --git a/build/cmake/init.cmake b/build/cmake/init.cmake diff --git a/build/cmake/init.cmake b/build/cmake/init.cmake
index 5447d33..f5440b4 100644 index 4ed7b264ef..9abf7c9d5d 100644
--- a/build/cmake/init.cmake --- a/build/cmake/init.cmake
+++ b/build/cmake/init.cmake +++ b/build/cmake/init.cmake
@@ -530,7 +530,9 @@ if(wxUSE_GUI) @@ -667,7 +667,9 @@ if(wxUSE_GUI)
endif() endif()
if(wxUSE_SOUND AND wxUSE_LIBSDL AND UNIX AND NOT APPLE) if(wxUSE_SOUND AND wxUSE_LIBSDL AND UNIX AND NOT APPLE)
@ -12,12 +12,12 @@ index 5447d33..f5440b4 100644
+ set(SDL2_LIBRARY SDL2::SDL2 CACHE INTERNAL "") + set(SDL2_LIBRARY SDL2::SDL2 CACHE INTERNAL "")
if(NOT SDL2_FOUND) if(NOT SDL2_FOUND)
find_package(SDL) find_package(SDL)
endif() mark_as_advanced(SDL_INCLUDE_DIR SDLMAIN_LIBRARY)
diff --git a/build/cmake/wxWidgetsConfig.cmake.in b/build/cmake/wxWidgetsConfig.cmake.in diff --git a/build/cmake/wxWidgetsConfig.cmake.in b/build/cmake/wxWidgetsConfig.cmake.in
index 60cf762..202a8c3 100644 index c134900764..7bcb691074 100644
--- a/build/cmake/wxWidgetsConfig.cmake.in --- a/build/cmake/wxWidgetsConfig.cmake.in
+++ b/build/cmake/wxWidgetsConfig.cmake.in +++ b/build/cmake/wxWidgetsConfig.cmake.in
@@ -2,6 +2,9 @@ @@ -156,6 +156,9 @@ endforeach()
include(CMakeFindDependencyMacro) include(CMakeFindDependencyMacro)
find_dependency(NanoSVG CONFIG) find_dependency(NanoSVG CONFIG)
@ -25,5 +25,5 @@ index 60cf762..202a8c3 100644
+ find_dependency(SDL2 CONFIG) + find_dependency(SDL2 CONFIG)
+endif() +endif()
cmake_policy(PUSH) if(TARGET wx::wxnet AND @wxUSE_WEBREQUEST_CURL@)
# Set policies to prevent warnings # make sure CURL targets are available:

View file

@ -9,7 +9,7 @@ set(WX_ROOT_DIR "${_vcpkg_wx_root}" CACHE INTERNAL "")
unset(_vcpkg_wx_root) unset(_vcpkg_wx_root)
if(WIN32) if(WIN32)
# Find all libs with "32" infix which is unknown to FindwxWidgets.cmake # Find all libs with "33" infix which is unknown to FindwxWidgets.cmake
function(z_vcpkg_wxwidgets_find_base_library BASENAME) function(z_vcpkg_wxwidgets_find_base_library BASENAME)
find_library(WX_${BASENAME}d wx${BASENAME}33ud NAMES wx${BASENAME}d PATHS "${wxWidgets_ROOT_DIR}/debug/lib" NO_DEFAULT_PATH) find_library(WX_${BASENAME}d wx${BASENAME}33ud NAMES wx${BASENAME}d PATHS "${wxWidgets_ROOT_DIR}/debug/lib" NO_DEFAULT_PATH)
find_library(WX_${BASENAME} wx${BASENAME}33u NAMES wx${BASENAME} PATHS "${wxWidgets_ROOT_DIR}/lib" NO_DEFAULT_PATH REQUIRED) find_library(WX_${BASENAME} wx${BASENAME}33u NAMES wx${BASENAME} PATHS "${wxWidgets_ROOT_DIR}/lib" NO_DEFAULT_PATH REQUIRED)

View file

@ -590,16 +590,16 @@ void CemuUpdateWindow::OnClose(wxCloseEvent& event)
if (m_restartRequired && !m_restartFile.empty() && fs::exists(m_restartFile)) if (m_restartRequired && !m_restartFile.empty() && fs::exists(m_restartFile))
{ {
PROCESS_INFORMATION pi{}; PROCESS_INFORMATION pi{};
STARTUPINFO si{}; STARTUPINFOW si{};
si.cb = sizeof(si); si.cb = sizeof(si);
std::wstring cmdline = GetCommandLineW(); std::wstring cmdline = GetCommandLineW();
const auto index = cmdline.find('"', 1); const auto index = cmdline.find('"', 1);
cemu_assert_debug(index != std::wstring::npos); cemu_assert_debug(index != std::wstring::npos);
cmdline = L"\"" + m_restartFile.wstring() + L"\"" + cmdline.substr(index + 1); cmdline = L"\"" + boost::nowide::widen(_pathToUtf8(m_restartFile)) + L"\"" + cmdline.substr(index + 1);
HANDLE lock = CreateMutex(nullptr, TRUE, L"Global\\cemu_update_lock"); HANDLE lock = CreateMutexW(nullptr, TRUE, L"Global\\cemu_update_lock");
CreateProcess(nullptr, (wchar_t*)cmdline.c_str(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi); CreateProcessW(nullptr, (wchar_t*)cmdline.c_str(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi);
exit(0); exit(0);
} }

View file

@ -141,17 +141,15 @@ wxGameList::wxGameList(wxWindow* parent, wxWindowID id)
const auto& config = GetWxGUIConfig(); const auto& config = GetWxGUIConfig();
char transparent_bitmap[kIconWidth * kIconWidth * 4] = {}; char transparent_bitmap[kIconWidth * kIconWidth * 4] = {};
memset((void*)transparent_bitmap, wxSystemSettings::GetAppearance().IsDark() ? 0xFF : 0x00, sizeof(transparent_bitmap)); memset(transparent_bitmap, wxSystemSettings::GetAppearance().IsDark() ? 0xFF : 0x00, sizeof(transparent_bitmap));
wxBitmap blank(transparent_bitmap, kIconWidth, kIconWidth); wxBitmap blank(transparent_bitmap, kIconWidth, kIconWidth);
m_image_list_data = {}; m_image_list_data.Add(blank);
m_image_list_data.emplace_back(wxBitmapBundle::FromBitmap(blank)); wxListCtrl::SetImageList(&m_image_list_data, wxIMAGE_LIST_NORMAL);
wxListCtrl::SetNormalImages(m_image_list_data);
m_image_list_small_data = {};
wxBitmap::Rescale(blank, {kListIconWidth, kListIconWidth}); wxBitmap::Rescale(blank, {kListIconWidth, kListIconWidth});
m_image_list_small_data.emplace_back(wxBitmapBundle::FromBitmap(blank)); m_image_list_small_data.Add(blank);
wxListCtrl::SetSmallImages(m_image_list_small_data); wxListCtrl::SetImageList(&m_image_list_small_data, wxIMAGE_LIST_SMALL);
InsertColumn(ColumnHiddenName, "", wxLIST_FORMAT_LEFT, 0); InsertColumn(ColumnHiddenName, "", wxLIST_FORMAT_LEFT, 0);
if(config.show_icon_column) if(config.show_icon_column)
@ -251,13 +249,13 @@ void wxGameList::OnGameListSize(wxSizeEvent &event)
for(int i = GetColumnCount() - 1; i > 0; i--) for(int i = GetColumnCount() - 1; i > 0; i--)
{ {
#ifdef wxHAS_LISTCTRL_COLUMN_ORDER #ifdef wxHAS_LISTCTRL_COLUMN_ORDER
if(GetColumnWidth(GetColumnIndexFromOrder(i)) > 0) if(GetColumnWidth(GetColumnIndexFromOrder(i)) > 0)
{ {
last_col_index = GetColumnIndexFromOrder(i); last_col_index = GetColumnIndexFromOrder(i);
break; break;
} }
#else #else
if(GetColumnWidth(i) > 0) if(GetColumnWidth(i) > 0)
{ {
last_col_index = i; last_col_index = i;
break; break;
@ -302,12 +300,6 @@ int wxGameList::GetColumnDefaultWidth(int column)
switch (column) switch (column)
{ {
case ColumnIcon: case ColumnIcon:
#if __WXMSW__
// note: this is another workaround that could be used to fix the icon offset, but instead of this there's a vcpkg patch for wxWidgets that fixes the icon offset
// wxWidgets offsets the icon in the REPORT view so it's cut off if the column width is set to 64px, see https://github.com/wxWidgets/wxWidgets/blob/09f433faf39aab3f25b3c564b82448bb845fae56/src/msw/listctrl.cpp#L3091
// so add 6px to the column width to compensate, and add another 6px to the right side so that it has equal whitespace on both sides
// return kListIconWidth + 6 + 6;
#endif
return kListIconWidth; return kListIconWidth;
case ColumnName: case ColumnName:
return DefaultColumnSize::name; return DefaultColumnSize::name;
@ -410,11 +402,13 @@ void wxGameList::SetStyle(Style style, bool save)
switch(style) switch(style)
{ {
case Style::kIcons: case Style::kIcons:
wxListCtrl::SetNormalImages(m_image_list_data); wxListCtrl::SetImageList(&m_image_list_data, wxIMAGE_LIST_NORMAL);
break; break;
case Style::kSmallIcons: case Style::kSmallIcons:
wxListCtrl::SetImageList(&m_image_list_small_data, wxIMAGE_LIST_NORMAL);
break;
case Style::kList: case Style::kList:
wxListCtrl::SetSmallImages(m_image_list_small_data); wxListCtrl::SetImageList(&m_image_list_small_data, wxIMAGE_LIST_SMALL);
break; break;
} }
@ -443,7 +437,7 @@ long wxGameList::GetStyleFlags(Style style) const
switch (style) switch (style)
{ {
case Style::kList: case Style::kList:
return (wxLC_SINGLE_SEL | wxLC_REPORT); return (wxLC_SINGLE_SEL | wxLC_VRULES | wxLC_REPORT);
case Style::kIcons: case Style::kIcons:
return (wxLC_SINGLE_SEL | wxLC_ICON); return (wxLC_SINGLE_SEL | wxLC_ICON);
case Style::kSmallIcons: case Style::kSmallIcons:
@ -458,25 +452,22 @@ void wxGameList::UpdateItemColors(sint32 startIndex)
{ {
wxWindowUpdateLocker lock(this); wxWindowUpdateLocker lock(this);
wxColour bgColourPrimary = GetBackgroundColour();
wxColour bgColourSecondary = wxHelper::CalculateAccentColour(bgColourPrimary);
for (int i = startIndex; i < GetItemCount(); ++i) for (int i = startIndex; i < GetItemCount(); ++i)
{ {
const auto titleId = (uint64)GetItemData(i); const uint64 titleId = GetItemData(i);
if (GetConfig().IsGameListFavorite(titleId)) if (GetConfig().IsGameListFavorite(titleId))
{ {
SetItemBackgroundColour(i, kFavoriteColor); SetItemBackgroundColour(i, kFavoriteColor);
SetItemTextColour(i, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); SetItemTextColour(i, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
} }
else if ((i&1) != 0) else if ((i % 2) != 0)
{ {
SetItemBackgroundColour(i, bgColourPrimary); SetItemBackgroundColour(i, kPrimaryColor);
SetItemTextColour(i, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); SetItemTextColour(i, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
} }
else else
{ {
SetItemBackgroundColour(i, bgColourSecondary); SetItemBackgroundColour(i, kAlternateColor);
SetItemTextColour(i, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); SetItemTextColour(i, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
} }
} }
@ -484,7 +475,7 @@ void wxGameList::UpdateItemColors(sint32 startIndex)
static inline int order_to_int(const std::weak_ordering &wo) static inline int order_to_int(const std::weak_ordering &wo)
{ {
// no easy conversion seems to exists in C++20 // no easy conversion seems to exist in C++20
if (wo == std::weak_ordering::less) if (wo == std::weak_ordering::less)
return -1; return -1;
else if (wo == std::weak_ordering::greater) else if (wo == std::weak_ordering::greater)
@ -496,27 +487,24 @@ std::weak_ordering wxGameList::SortComparator(uint64 titleId1, uint64 titleId2,
{ {
auto titleLastPlayed = [](uint64_t id) auto titleLastPlayed = [](uint64_t id)
{ {
iosu::pdm::GameListStat playTimeStat{}; iosu::pdm::GameListStat playTimeStat{};
iosu::pdm::GetStatForGamelist(id, playTimeStat); iosu::pdm::GetStatForGamelist(id, playTimeStat);
return playTimeStat; return playTimeStat;
}; };
auto titlePlayMinutes = [](uint64_t id) auto titlePlayMinutes = [](uint64_t id)
{ {
iosu::pdm::GameListStat playTimeStat; iosu::pdm::GameListStat playTimeStat;
if (!iosu::pdm::GetStatForGamelist(id, playTimeStat)) if (!iosu::pdm::GetStatForGamelist(id, playTimeStat))
return 0u; return 0u;
return playTimeStat.numMinutesPlayed; return playTimeStat.numMinutesPlayed;
}; };
auto titleRegion = [](uint64_t id) auto titleRegion = [](uint64_t id)
{ {
return CafeTitleList::GetGameInfo(id).GetRegion(); return CafeTitleList::GetGameInfo(id).GetRegion();
}; };
if (!sortData->asc)
std::swap(titleId1, titleId2);
switch(sortData->column) switch(sortData->column)
{ {
default: default:
@ -545,7 +533,7 @@ std::weak_ordering wxGameList::SortComparator(uint64 titleId1, uint64 titleId2,
int wxGameList::SortFunction(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData) int wxGameList::SortFunction(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData)
{ {
const auto sort_data = (SortData*)sortData; const auto sort_data = (SortData*)sortData;
return order_to_int(sort_data->thisptr->SortComparator((uint64)item1, (uint64)item2, sort_data)); return sort_data->dir * order_to_int(sort_data->thisptr->SortComparator((uint64)item1, (uint64)item2, sort_data));
} }
void wxGameList::SortEntries(int column) void wxGameList::SortEntries(int column)
@ -569,7 +557,7 @@ void wxGameList::SortEntries(int column)
case ColumnRegion: case ColumnRegion:
case ColumnTitleID: case ColumnTitleID:
{ {
SortData data{this, ItemColumns{column}, ascending}; SortData data{this, ItemColumns{column}, ascending ? 1 : -1};
SortItems(SortFunction, (wxIntPtr)&data); SortItems(SortFunction, (wxIntPtr)&data);
ShowSortIndicator(column, ascending); ShowSortIndicator(column, ascending);
break; break;
@ -840,8 +828,8 @@ void wxGameList::OnContextMenuSelected(wxCommandEvent& event)
int icon_small; int icon_small;
if (!QueryIconForTitle(title_id, icon_large, icon_small)) if (!QueryIconForTitle(title_id, icon_large, icon_small))
break; break;
auto icon = m_image_list_data[icon_large]; auto icon = m_image_list_data.GetIcon(icon_large);
auto newClipboardData = wxBitmapDataObject(icon.GetBitmap(icon.GetDefaultSize())); auto newClipboardData = wxBitmapDataObject(icon);
wxClipboard::Get()->SetData(&newClipboardData); wxClipboard::Get()->SetData(&newClipboardData);
wxClipboard::Get()->Close(); wxClipboard::Get()->Close();
} }
@ -1002,7 +990,7 @@ void wxGameList::ApplyGameListColumnWidths()
const auto& config = GetWxGUIConfig(); const auto& config = GetWxGUIConfig();
wxWindowUpdateLocker lock(this); wxWindowUpdateLocker lock(this);
if(config.show_icon_column) if(config.show_icon_column)
SetColumnWidth(ColumnIcon, GetColumnDefaultWidth(ColumnIcon)); SetColumnWidth(ColumnIcon, kListIconWidth);
else else
SetColumnWidth(ColumnIcon, 0); SetColumnWidth(ColumnIcon, 0);
SetColumnWidth(ColumnName, config.column_width.name); SetColumnWidth(ColumnName, config.column_width.name);
@ -1024,13 +1012,13 @@ void wxGameList::OnColumnBeginResize(wxListEvent& event)
for(int i = GetColumnCount() - 1; i > 0; i--) for(int i = GetColumnCount() - 1; i > 0; i--)
{ {
#ifdef wxHAS_LISTCTRL_COLUMN_ORDER #ifdef wxHAS_LISTCTRL_COLUMN_ORDER
if(GetColumnWidth(GetColumnIndexFromOrder(i)) > 0) if(GetColumnWidth(GetColumnIndexFromOrder(i)) > 0)
{ {
last_col_index = GetColumnIndexFromOrder(i); last_col_index = GetColumnIndexFromOrder(i);
break; break;
} }
#else #else
if(GetColumnWidth(i) > 0) if(GetColumnWidth(i) > 0)
{ {
last_col_index = i; last_col_index = i;
break; break;
@ -1117,19 +1105,6 @@ void wxGameList::OnGameEntryUpdatedByTitleId(wxTitleIdEvent& event)
TitleId baseTitleId = gameInfo.GetBaseTitleId(); TitleId baseTitleId = gameInfo.GetBaseTitleId();
bool isNewEntry = false; bool isNewEntry = false;
if (m_style == Style::kIcons)
{
wxListCtrl::SetNormalImages(m_image_list_data);
}
else if (m_style == Style::kSmallIcons)
{
wxListCtrl::SetSmallImages(m_image_list_small_data);
}
else if (m_style == Style::kList)
{
wxListCtrl::SetSmallImages(m_image_list_small_data);
}
int icon = -1; /* 0 is the default empty icon */ int icon = -1; /* 0 is the default empty icon */
int icon_small = -1; /* 0 is the default empty icon */ int icon_small = -1; /* 0 is the default empty icon */
QueryIconForTitle(baseTitleId, icon, icon_small); QueryIconForTitle(baseTitleId, icon, icon_small);
@ -1175,7 +1150,7 @@ void wxGameList::OnGameEntryUpdatedByTitleId(wxTitleIdEvent& event)
wxString minutesText = formatWxString(wxPLURAL("{} minute", "{} minutes", minutes), minutes); wxString minutesText = formatWxString(wxPLURAL("{} minute", "{} minutes", minutes), minutes);
SetItem(index, ColumnGameTime, hoursText + " " + minutesText); SetItem(index, ColumnGameTime, hoursText + " " + minutesText);
} }
// last played // last played
if (playTimeStat.last_played.year != 0) if (playTimeStat.last_played.year != 0)
{ {
@ -1345,11 +1320,11 @@ void wxGameList::AsyncWorkerThread()
wxMemoryInputStream tmp_stream(tgaData->data(), tgaData->size()); wxMemoryInputStream tmp_stream(tgaData->data(), tgaData->size());
const wxImage image(tmp_stream); const wxImage image(tmp_stream);
// todo - is wxImageList thread safe? // todo - is wxImageList thread safe?
m_image_list_data.emplace_back(image.Scale(kIconWidth, kIconWidth, wxIMAGE_QUALITY_BICUBIC)); int icon = m_image_list_data.Add(image.Scale(kIconWidth, kIconWidth, wxIMAGE_QUALITY_BICUBIC));
m_image_list_small_data.emplace_back(image.Scale(kListIconWidth, kListIconWidth, wxIMAGE_QUALITY_BICUBIC)); int icon_small = m_image_list_small_data.Add(image.Scale(kListIconWidth, kListIconWidth, wxIMAGE_QUALITY_BICUBIC));
// store in cache // store in cache
m_icon_cache_mtx.lock(); m_icon_cache_mtx.lock();
m_icon_cache.try_emplace(titleId, m_image_list_data.size() - 1, m_image_list_small_data.size() - 1); m_icon_cache.try_emplace(titleId, icon, icon_small);
m_icon_cache_mtx.unlock(); m_icon_cache_mtx.unlock();
iconSuccessfullyLoaded = true; iconSuccessfullyLoaded = true;
} }
@ -1390,7 +1365,7 @@ bool wxGameList::QueryIconForTitle(TitleId titleId, int& icon, int& iconSmall)
return true; return true;
} }
void wxGameList::DeleteCachedStrings() void wxGameList::DeleteCachedStrings()
{ {
m_name_cache.clear(); m_name_cache.clear();
} }
@ -1415,9 +1390,9 @@ void wxGameList::CreateShortcut(GameInfo2& gameInfo)
// Obtain and convert icon // Obtain and convert icon
[&]() [&]()
{ {
int iconIndex, smallIconIndex; int iconIdx, smallIconIdx;
if (!QueryIconForTitle(titleId, iconIndex, smallIconIndex)) if (!QueryIconForTitle(titleId, iconIdx, smallIconIdx))
{ {
cemuLog_log(LogType::Force, "Icon hasn't loaded"); cemuLog_log(LogType::Force, "Icon hasn't loaded");
return; return;
@ -1433,8 +1408,8 @@ void wxGameList::CreateShortcut(GameInfo2& gameInfo)
iconPath = outIconDir / fmt::format("{:016x}.png", gameInfo.GetBaseTitleId()); iconPath = outIconDir / fmt::format("{:016x}.png", gameInfo.GetBaseTitleId());
wxFileOutputStream pngFileStream(_pathToUtf8(iconPath.value())); wxFileOutputStream pngFileStream(_pathToUtf8(iconPath.value()));
const auto icon = m_image_list_data[iconIndex]; const auto icon = m_image_list_data.GetIcon(iconIdx);
wxBitmap bitmap{icon.GetBitmap(wxDefaultSize)}; wxBitmap bitmap{icon};
wxImage image = bitmap.ConvertToImage(); wxImage image = bitmap.ConvertToImage();
wxPNGHandler pngHandler; wxPNGHandler pngHandler;
if (!pngHandler.SaveFile(&image, pngFileStream, false)) if (!pngHandler.SaveFile(&image, pngFileStream, false))
@ -1508,9 +1483,9 @@ void wxGameList::CreateShortcut(GameInfo2& gameInfo)
// Obtain and convert icon // Obtain and convert icon
[&]() [&]()
{ {
int iconIndex, smallIconIndex; int iconIdx, smallIconIdx;
if (!QueryIconForTitle(titleId, iconIndex, smallIconIndex)) if (!QueryIconForTitle(titleId, iconIdx, smallIconIdx))
{ {
cemuLog_log(LogType::Force, "Icon hasn't loaded"); cemuLog_log(LogType::Force, "Icon hasn't loaded");
return; return;
@ -1526,8 +1501,8 @@ void wxGameList::CreateShortcut(GameInfo2& gameInfo)
iconPath = outIconDir / fmt::format("{:016x}.png", gameInfo.GetBaseTitleId()); iconPath = outIconDir / fmt::format("{:016x}.png", gameInfo.GetBaseTitleId());
wxFileOutputStream pngFileStream(_pathToUtf8(iconPath.value())); wxFileOutputStream pngFileStream(_pathToUtf8(iconPath.value()));
const auto icon = m_image_list_data[iconIndex]; const auto icon = m_image_list_data.GetIcon(iconIdx);
wxBitmap bitmap{icon.GetBitmap(wxDefaultSize)}; wxBitmap bitmap{icon};
wxImage image = bitmap.ConvertToImage(); wxImage image = bitmap.ConvertToImage();
wxPNGHandler pngHandler; wxPNGHandler pngHandler;
if (!pngHandler.SaveFile(&image, pngFileStream, false)) if (!pngHandler.SaveFile(&image, pngFileStream, false))
@ -1635,14 +1610,14 @@ void wxGameList::CreateShortcut(GameInfo2& gameInfo)
cemuLog_log(LogType::Force, "Icon hasn't loaded"); cemuLog_log(LogType::Force, "Icon hasn't loaded");
return; return;
} }
const auto icon = m_image_list_data[iconIdx]; const auto icon = m_image_list_data.GetIcon(iconIdx);
const auto folder = ActiveSettings::GetUserDataPath("icons"); const auto folder = ActiveSettings::GetUserDataPath("icons");
if (!fs::exists(folder) && !fs::create_directories(folder)) if (!fs::exists(folder) && !fs::create_directories(folder))
{ {
cemuLog_log(LogType::Force, "Failed to create icon directory"); cemuLog_log(LogType::Force, "Failed to create icon directory");
return; return;
} }
wxBitmap bitmap{icon.GetBitmap(wxDefaultSize)}; wxBitmap bitmap{icon};
icon_path = folder / fmt::format("{:016x}.ico", titleId); icon_path = folder / fmt::format("{:016x}.ico", titleId);
auto stream = wxFileOutputStream(icon_path->wstring()); auto stream = wxFileOutputStream(icon_path->wstring());

View file

@ -3,15 +3,15 @@
#include "config/CemuConfig.h" #include "config/CemuConfig.h"
#include "Cafe/TitleList/TitleId.h" #include "Cafe/TitleList/TitleId.h"
#include <future>
#include <mutex> #include <mutex>
#include <optional>
#include <wx/listctrl.h> #include <wx/listctrl.h>
#include <wx/timer.h> #include <wx/timer.h>
#include <wx/panel.h> #include <wx/panel.h>
#include <wx/settings.h> #include <wx/settings.h>
#include <Cafe/TitleList/GameInfo.h> #include <Cafe/TitleList/GameInfo.h>
#include "wxHelper.h"
#include "util/helpers/Semaphore.h" #include "util/helpers/Semaphore.h"
class wxTitleIdEvent : public wxCommandEvent class wxTitleIdEvent : public wxCommandEvent
@ -66,7 +66,8 @@ private:
const wxColour kUpdateColor{ wxSystemSettings::SelectLightDark(wxColour(195, 57, 57), wxColour(84, 29, 29)) }; const wxColour kUpdateColor{ wxSystemSettings::SelectLightDark(wxColour(195, 57, 57), wxColour(84, 29, 29)) };
const wxColour kFavoriteColor{ wxSystemSettings::SelectLightDark(wxColour(253, 246, 211), wxColour(82, 84, 48)) }; const wxColour kFavoriteColor{ wxSystemSettings::SelectLightDark(wxColour(253, 246, 211), wxColour(82, 84, 48)) };
const wxColour kSecondColor{ wxSystemSettings::SelectLightDark(wxColour(242, 249, 253), wxColour(34, 34, 34)) }; const wxColour kPrimaryColor = GetBackgroundColour();
const wxColour kAlternateColor = wxHelper::CalculateAccentColour(kPrimaryColor);
void UpdateItemColors(sint32 startIndex = 0); void UpdateItemColors(sint32 startIndex = 0);
enum ItemColumns : int enum ItemColumns : int
@ -89,7 +90,7 @@ private:
{ {
wxGameList* thisptr; wxGameList* thisptr;
ItemColumns column; ItemColumns column;
bool asc; int dir;
}; };
int FindInsertPosition(TitleId titleId); int FindInsertPosition(TitleId titleId);
@ -109,7 +110,7 @@ private:
std::vector<TitleId> m_icon_load_queue; std::vector<TitleId> m_icon_load_queue;
uint64 m_callbackIdTitleList; uint64 m_callbackIdTitleList;
std::string GetNameByTitleId(uint64 titleId); std::string GetNameByTitleId(uint64 titleId);
void HandleTitleListCallback(struct CafeTitleListCallbackEvent* evt); void HandleTitleListCallback(struct CafeTitleListCallbackEvent* evt);
@ -122,7 +123,8 @@ private:
inline static constexpr int kListIconWidth = 64; inline static constexpr int kListIconWidth = 64;
inline static constexpr int kIconWidth = 128; inline static constexpr int kIconWidth = 128;
wxWithImages::Images m_image_list_data, m_image_list_small_data; wxImageList m_image_list_data = wxImageList(kIconWidth, kIconWidth, false, 1);
wxImageList m_image_list_small_data = wxImageList(kListIconWidth, kListIconWidth, false, 1);
std::mutex m_icon_cache_mtx; std::mutex m_icon_cache_mtx;
std::set<TitleId> m_icon_loaded; std::set<TitleId> m_icon_loaded;

View file

@ -25,10 +25,9 @@ namespace wxHelper
inline wxColour CalculateAccentColour(const wxColour& bgColour) inline wxColour CalculateAccentColour(const wxColour& bgColour)
{ {
wxColour bgColourSecondary;
const uint32 bgLightness = (bgColour.GetRed() + bgColour.GetGreen() + bgColour.GetBlue()) / 3; const uint32 bgLightness = (bgColour.GetRed() + bgColour.GetGreen() + bgColour.GetBlue()) / 3;
const bool isDarkTheme = bgLightness < 128; const bool isDarkTheme = bgLightness < 128;
bgColourSecondary = bgColour.ChangeLightness(isDarkTheme ? 110 : 90); // color for even rows wxColour bgColourSecondary = bgColour.ChangeLightness(isDarkTheme ? 110 : 90); // color for even rows
// for very light themes we'll use a blue tint to match the older Windows Cemu look // for very light themes we'll use a blue tint to match the older Windows Cemu look
if (bgLightness > 250) if (bgLightness > 250)
bgColourSecondary = wxColour(bgColour.Red() - 13, bgColour.Green() - 6, bgColour.Blue() - 2); bgColourSecondary = wxColour(bgColour.Red() - 13, bgColour.Green() - 6, bgColour.Blue() - 2);

View file

@ -22,9 +22,10 @@ DirectInputController::~DirectInputController()
// TODO: test if really needed // TODO: test if really needed
// workaround for gamecube controllers crash on release? // workaround for gamecube controllers crash on release?
bool should_release_device = true; bool should_release_device = true;
if (m_product_guid == GUID{}) { if (m_product_guid == GUID{})
DIDEVICEINSTANCE info{}; {
info.dwSize = sizeof(DIDEVICEINSTANCE); DIDEVICEINSTANCEW info{};
info.dwSize = sizeof(DIDEVICEINSTANCEW);
if (SUCCEEDED(m_device->GetDeviceInfo(&info))) if (SUCCEEDED(m_device->GetDeviceInfo(&info)))
{ {
m_product_guid = info.guidProduct; m_product_guid = info.guidProduct;
@ -90,8 +91,8 @@ bool DirectInputController::connect()
if (FAILED(hr) || m_device == nullptr) if (FAILED(hr) || m_device == nullptr)
return false; return false;
DIDEVICEINSTANCE idi{}; DIDEVICEINSTANCEW idi{};
idi.dwSize = sizeof(DIDEVICEINSTANCE); idi.dwSize = sizeof(DIDEVICEINSTANCEW);
if (SUCCEEDED(m_device->GetDeviceInfo(&idi))) if (SUCCEEDED(m_device->GetDeviceInfo(&idi)))
{ {
// overwrite guid name with "real" display name // overwrite guid name with "real" display name
@ -147,8 +148,8 @@ bool DirectInputController::connect()
} }
} }
DIDEVICEINSTANCE info{}; DIDEVICEINSTANCEW info{};
info.dwSize = sizeof(DIDEVICEINSTANCE); info.dwSize = sizeof(DIDEVICEINSTANCEW);
if (SUCCEEDED(m_device->GetDeviceInfo(&info))) if (SUCCEEDED(m_device->GetDeviceInfo(&info)))
{ {
m_product_guid = info.guidProduct; m_product_guid = info.guidProduct;
@ -157,7 +158,7 @@ bool DirectInputController::connect()
std::fill(m_min_axis.begin(), m_min_axis.end(), 0); std::fill(m_min_axis.begin(), m_min_axis.end(), 0);
std::fill(m_max_axis.begin(), m_max_axis.end(), std::numeric_limits<uint16>::max()); std::fill(m_max_axis.begin(), m_max_axis.end(), std::numeric_limits<uint16>::max());
m_device->EnumObjects( m_device->EnumObjects(
[](LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) -> BOOL [](LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef) -> BOOL
{ {
auto* thisptr = (DirectInputController*)pvRef; auto* thisptr = (DirectInputController*)pvRef;

View file

@ -42,7 +42,7 @@ private:
GUID m_product_guid{}; GUID m_product_guid{};
std::shared_mutex m_mutex; std::shared_mutex m_mutex;
Microsoft::WRL::ComPtr<IDirectInputDevice8> m_device; Microsoft::WRL::ComPtr<IDirectInputDevice8W> m_device;
Microsoft::WRL::ComPtr<IDirectInputEffect> m_effect; Microsoft::WRL::ComPtr<IDirectInputEffect> m_effect;
std::array<LONG, 6> m_min_axis{}; std::array<LONG, 6> m_min_axis{};

View file

@ -4,34 +4,16 @@
DirectInputControllerProvider::DirectInputControllerProvider() DirectInputControllerProvider::DirectInputControllerProvider()
{ {
/*m_module = LoadLibraryA("dinput8.dll"); const auto r = DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8W, (void**)&m_dinput8, nullptr);
if (!m_module)
throw std::runtime_error("can't load any xinput dll");
m_DirectInput8Create = (decltype(&DirectInput8Create))GetProcAddress(m_module, "DirectInput8Create");
m_GetdfDIJoystick = (decltype(&GetdfDIJoystick))GetProcAddress(m_module, "GetdfDIJoystick");
if (!m_DirectInput8Create)
{
FreeLibrary(m_module);
throw std::runtime_error("can't find the DirectInput8Create export");
}*/
const auto r = DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&m_dinput8, nullptr);
if (FAILED(r)) if (FAILED(r))
{ {
const auto error = GetLastError(); const auto error = GetLastError();
//FreeLibrary(m_module);
throw std::runtime_error(fmt::format("can't create direct input object (error: {:#x})", error)); throw std::runtime_error(fmt::format("can't create direct input object (error: {:#x})", error));
} }
} }
DirectInputControllerProvider::~DirectInputControllerProvider() DirectInputControllerProvider::~DirectInputControllerProvider()
{ {
/*if (m_module)
FreeLibrary(m_module);
*/
} }
std::vector<std::shared_ptr<ControllerBase>> DirectInputControllerProvider::get_controllers() std::vector<std::shared_ptr<ControllerBase>> DirectInputControllerProvider::get_controllers()
@ -39,7 +21,7 @@ std::vector<std::shared_ptr<ControllerBase>> DirectInputControllerProvider::get_
std::vector<std::shared_ptr<ControllerBase>> result; std::vector<std::shared_ptr<ControllerBase>> result;
m_dinput8->EnumDevices(DI8DEVCLASS_GAMECTRL, m_dinput8->EnumDevices(DI8DEVCLASS_GAMECTRL,
[](LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) -> BOOL [](LPCDIDEVICEINSTANCEW lpddi, LPVOID pvRef) -> BOOL
{ {
auto* controllers = (decltype(&result))pvRef; auto* controllers = (decltype(&result))pvRef;
@ -55,8 +37,5 @@ std::vector<std::shared_ptr<ControllerBase>> DirectInputControllerProvider::get_
LPCDIDATAFORMAT DirectInputControllerProvider::get_data_format() const LPCDIDATAFORMAT DirectInputControllerProvider::get_data_format() const
{ {
/*if (m_GetdfDIJoystick)
return m_GetdfDIJoystick();*/
return GetdfDIJoystick(); return GetdfDIJoystick();
} }

View file

@ -23,7 +23,7 @@ public:
std::vector<std::shared_ptr<ControllerBase>> get_controllers() override; std::vector<std::shared_ptr<ControllerBase>> get_controllers() override;
IDirectInput8* get_dinput() const { return m_dinput8.Get(); } IDirectInput8W* get_dinput() const { return m_dinput8.Get(); }
LPCDIDATAFORMAT get_data_format() const; LPCDIDATAFORMAT get_data_format() const;
private: private:
@ -32,7 +32,7 @@ private:
decltype(&DirectInput8Create) m_DirectInput8Create; decltype(&DirectInput8Create) m_DirectInput8Create;
decltype(&GetdfDIJoystick) m_GetdfDIJoystick = nullptr; decltype(&GetdfDIJoystick) m_GetdfDIJoystick = nullptr;
Microsoft::WRL::ComPtr<IDirectInput8> m_dinput8; Microsoft::WRL::ComPtr<IDirectInput8W> m_dinput8;
}; };
#endif #endif

View file

@ -96,12 +96,12 @@ void WindowsInitCwd()
{ {
#if BOOST_OS_WINDOWS #if BOOST_OS_WINDOWS
executablePath.resize(4096); executablePath.resize(4096);
int i = GetModuleFileName(NULL, executablePath.data(), executablePath.size()); int i = GetModuleFileNameW(NULL, executablePath.data(), executablePath.size());
if(i >= 0) if(i >= 0)
executablePath.resize(i); executablePath.resize(i);
else else
executablePath.clear(); executablePath.clear();
SetCurrentDirectory(executablePath.c_str()); SetCurrentDirectoryW(executablePath.c_str());
// set high priority // set high priority
SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);
#endif #endif
@ -192,7 +192,7 @@ void HandlePostUpdate()
HANDLE lock; HANDLE lock;
do do
{ {
lock = CreateMutex(nullptr, TRUE, L"Global\\cemu_update_lock"); lock = CreateMutexW(nullptr, TRUE, L"Global\\cemu_update_lock");
std::this_thread::sleep_for(std::chrono::milliseconds(1)); std::this_thread::sleep_for(std::chrono::milliseconds(1));
} while (lock == nullptr); } while (lock == nullptr);
const DWORD wait_result = WaitForSingleObject(lock, 2000); const DWORD wait_result = WaitForSingleObject(lock, 2000);
@ -220,7 +220,7 @@ void ToolShaderCacheMerger();
#if BOOST_OS_WINDOWS #if BOOST_OS_WINDOWS
// entrypoint for release builds // entrypoint for release builds
int wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nShowCmd) int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
{ {
if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE))) if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE)))
cemuLog_log(LogType::Force, "CoInitializeEx() failed"); cemuLog_log(LogType::Force, "CoInitializeEx() failed");

View file

@ -34,13 +34,7 @@
"default-features": false "default-features": false
}, },
"zstd", "zstd",
{ "wxwidgets",
"name": "wxwidgets",
"features": [
"debug-support"
],
"default-features": false
},
"openssl", "openssl",
{ {
"name": "curl", "name": "curl",