WinRT apps check if the Windows theme is set to dark mode through IUISettings3::GetColorValue().
An option needs to be added to Winecfg to enable dark mode support, which just sets the registry key AppsUseLightTheme to 0 for dark mode and 1 for light mode. It will have to be in a separate merge request. Also, not sure if a dark mode checkbox should be added or if dark mode should be automatically set based on the loaded theme in Wine. Though, for the latter there needs to be a property that returns the mode of the theme. Name alone might not be sufficient.
-- v4: windows.ui: Implement IUISettings3::GetColorValue(). windows.ui/tests: Add IUISettings3::GetColorValue() tests. windows.ui: Add IUISettings3 stub interface. windows.ui: Add stub DLL. include: Add windows.ui.viewmanagement.idl file.
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- include/Makefile.in | 1 + include/windows.ui.viewmanagement.idl | 167 ++++++++++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 include/windows.ui.viewmanagement.idl
diff --git a/include/Makefile.in b/include/Makefile.in index 8602dd51e42..b9a357ef366 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -824,6 +824,7 @@ SOURCES = \ windows.system.threading.idl \ windows.system.userprofile.idl \ windows.ui.idl \ + windows.ui.viewmanagement.idl \ windowscontracts.idl \ windowsx.h \ wine/afd.h \ diff --git a/include/windows.ui.viewmanagement.idl b/include/windows.ui.viewmanagement.idl new file mode 100644 index 00000000000..e7a90646338 --- /dev/null +++ b/include/windows.ui.viewmanagement.idl @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2023 Mohamad Al-Jaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef __WIDL__ +#pragma winrt ns_prefix +#endif + +import "inspectable.idl"; +import "asyncinfo.idl"; +import "eventtoken.idl"; +import "windowscontracts.idl"; +import "windows.foundation.idl"; +import "windows.devices.enumeration.idl"; +/* import "windows.phone.idl"; */ +import "windows.ui.idl"; +/* import "windows.ui.core.idl"; */ +/* import "windows.ui.popups.idl"; */ +/* import "windows.ui.windowmanagement.idl"; */ + +namespace Windows.UI.ViewManagement +{ + typedef enum HandPreference HandPreference; + typedef enum UIColorType UIColorType; + typedef enum UIElementType UIElementType; + + interface IUISettings; + interface IUISettings3; + + runtimeclass UISettings; + + declare { + interface Windows.Foundation.TypedEventHandler<Windows.UI.ViewManagement.UISettings *, IInspectable *>; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0) + ] + enum HandPreference + { + LeftHanded = 0, + RightHanded = 1, + }; + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0) + ] + enum UIColorType + { + Background = 0, + Foreground = 1, + AccentDark3 = 2, + AccentDark2 = 3, + AccentDark1 = 4, + Accent = 5, + AccentLight1 = 6, + AccentLight2 = 7, + AccentLight3 = 8, + Complement = 9, + }; + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0) + ] + enum UIElementType + { + ActiveCaption = 0, + Background = 1, + ButtonFace = 2, + ButtonText = 3, + CaptionText = 4, + GrayText = 5, + Highlight = 6, + HighlightText = 7, + Hotlight = 8, + InactiveCaption = 9, + InactiveCaptionText = 10, + Window = 11, + WindowText = 12, + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + AccentColor = 1000, + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + TextHigh = 1001, + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + TextMedium = 1002, + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + TextLow = 1003, + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + TextContrastWithHigh = 1004, + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + NonTextHigh = 1005, + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + NonTextMediumHigh = 1006, + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + NonTextMedium = 1007, + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + NonTextMediumLow = 1008, + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + NonTextLow = 1009, + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + PageBackground = 1010, + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + PopupBackground = 1011, + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + OverlayOutsidePopup = 1012, + }; + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.UI.ViewManagement.UISettings), + uuid(85361600-1c63-4627-bcb1-3a89e0bc9c55) + ] + interface IUISettings : IInspectable + { + [propget] HRESULT HandPreference([out, retval] Windows.UI.ViewManagement.HandPreference *value); + [propget] HRESULT CursorSize([out, retval] Windows.Foundation.Size *value); + [propget] HRESULT ScrollBarSize([out, retval] Windows.Foundation.Size *value); + [propget] HRESULT ScrollBarArrowSize([out, retval] Windows.Foundation.Size *value); + [propget] HRESULT ScrollBarThumbBoxSize([out, retval] Windows.Foundation.Size *value); + [propget] HRESULT MessageDuration([out, retval] UINT32 *value); + [propget] HRESULT AnimationsEnabled([out, retval] boolean *value); + [propget] HRESULT CaretBrowsingEnabled([out, retval] boolean *value); + [propget] HRESULT CaretBlinkRate([out, retval] UINT32 *value); + [propget] HRESULT CaretWidth([out, retval] UINT32 *value); + [propget] HRESULT DoubleClickTime([out, retval] UINT32 *value); + [propget] HRESULT MouseHoverTime([out, retval] UINT32 *value); + HRESULT UIElementColor([in] Windows.UI.ViewManagement.UIElementType element, [out, retval] Windows.UI.Color *value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.UI.ViewManagement.UISettings), + uuid(03021be4-5254-4781-8194-5168f7d06d7b) + ] + interface IUISettings3 : IInspectable + { + HRESULT GetColorValue([in] Windows.UI.ViewManagement.UIColorType color, [out, retval] Windows.UI.Color *value); + [eventadd] HRESULT ColorValuesChanged([in] Windows.Foundation.TypedEventHandler<Windows.UI.ViewManagement.UISettings *, IInspectable *> *handler, + [out, retval] EventRegistrationToken *cookie); + [eventremove] HRESULT ColorValuesChanged([in] EventRegistrationToken cookie); + } + + [ + activatable(Windows.Foundation.UniversalApiContract, 1.0), + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile) + ] + runtimeclass UISettings + { + [default] interface Windows.UI.ViewManagement.IUISettings; + [contract(Windows.Foundation.UniversalApiContract, 1.0)] interface Windows.UI.ViewManagement.IUISettings3; + } +}
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- configure.ac | 2 + dlls/windows.ui/Makefile.in | 9 +++ dlls/windows.ui/classes.idl | 23 ++++++ dlls/windows.ui/main.c | 55 ++++++++++++++ dlls/windows.ui/private.h | 41 ++++++++++ dlls/windows.ui/tests/Makefile.in | 5 ++ dlls/windows.ui/tests/uisettings.c | 90 ++++++++++++++++++++++ dlls/windows.ui/uisettings.c | 116 +++++++++++++++++++++++++++++ dlls/windows.ui/windows.ui.spec | 7 ++ 9 files changed, 348 insertions(+) create mode 100644 dlls/windows.ui/Makefile.in create mode 100644 dlls/windows.ui/classes.idl create mode 100644 dlls/windows.ui/main.c create mode 100644 dlls/windows.ui/private.h create mode 100644 dlls/windows.ui/tests/Makefile.in create mode 100644 dlls/windows.ui/tests/uisettings.c create mode 100644 dlls/windows.ui/uisettings.c create mode 100644 dlls/windows.ui/windows.ui.spec
diff --git a/configure.ac b/configure.ac index 9ff7c5e8914..2581e115a79 100644 --- a/configure.ac +++ b/configure.ac @@ -3127,6 +3127,8 @@ WINE_CONFIG_MAKEFILE(dlls/windows.media/tests) WINE_CONFIG_MAKEFILE(dlls/windows.networking) WINE_CONFIG_MAKEFILE(dlls/windows.system.profile.systemmanufacturers) WINE_CONFIG_MAKEFILE(dlls/windows.system.profile.systemmanufacturers/tests) +WINE_CONFIG_MAKEFILE(dlls/windows.ui) +WINE_CONFIG_MAKEFILE(dlls/windows.ui/tests) WINE_CONFIG_MAKEFILE(dlls/windowscodecs) WINE_CONFIG_MAKEFILE(dlls/windowscodecs/tests) WINE_CONFIG_MAKEFILE(dlls/windowscodecsext) diff --git a/dlls/windows.ui/Makefile.in b/dlls/windows.ui/Makefile.in new file mode 100644 index 00000000000..cb9b48a664b --- /dev/null +++ b/dlls/windows.ui/Makefile.in @@ -0,0 +1,9 @@ +MODULE = windows.ui.dll +IMPORTS = combase + +C_SRCS = \ + main.c \ + uisettings.c + +IDL_SRCS = \ + classes.idl diff --git a/dlls/windows.ui/classes.idl b/dlls/windows.ui/classes.idl new file mode 100644 index 00000000000..e6680b2e550 --- /dev/null +++ b/dlls/windows.ui/classes.idl @@ -0,0 +1,23 @@ +/* + * Runtime Classes for windows.ui.dll + * + * Copyright (C) 2023 Mohamad Al-Jaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma makedep register + +#include "windows.ui.viewmanagement.idl" diff --git a/dlls/windows.ui/main.c b/dlls/windows.ui/main.c new file mode 100644 index 00000000000..8896e0d1e71 --- /dev/null +++ b/dlls/windows.ui/main.c @@ -0,0 +1,55 @@ +/* WinRT Windows.UI Implementation + * + * Copyright (C) 2023 Mohamad Al-Jaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "initguid.h" +#include "private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ui); + +static const char *debugstr_hstring( HSTRING hstr ) +{ + const WCHAR *str; + UINT32 len; + if (hstr && !((ULONG_PTR)hstr >> 16)) return "(invalid)"; + str = WindowsGetStringRawBuffer( hstr, &len ); + return wine_dbgstr_wn( str, len ); +} + +HRESULT WINAPI DllGetClassObject( REFCLSID clsid, REFIID riid, void **out ) +{ + FIXME( "clsid %s, riid %s, out %p stub!\n", debugstr_guid(clsid), debugstr_guid(riid), out ); + return CLASS_E_CLASSNOTAVAILABLE; +} + +HRESULT WINAPI DllGetActivationFactory( HSTRING classid, IActivationFactory **factory ) +{ + const WCHAR *buffer = WindowsGetStringRawBuffer( classid, NULL ); + + TRACE( "class %s, factory %p.\n", debugstr_hstring(classid), factory ); + + *factory = NULL; + + if (!wcscmp( buffer, RuntimeClass_Windows_UI_ViewManagement_UISettings )) + IActivationFactory_QueryInterface( uisettings_factory, &IID_IActivationFactory, (void **)factory ); + + if (*factory) return S_OK; + return CLASS_E_CLASSNOTAVAILABLE; +} diff --git a/dlls/windows.ui/private.h b/dlls/windows.ui/private.h new file mode 100644 index 00000000000..1af5faf152b --- /dev/null +++ b/dlls/windows.ui/private.h @@ -0,0 +1,41 @@ +/* WinRT Windows.UI Implementation + * + * Copyright (C) 2023 Mohamad Al-Jaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_WINDOWS_UI_PRIVATE_H +#define __WINE_WINDOWS_UI_PRIVATE_H + +#include <stdarg.h> + +#define COBJMACROS +#include "windef.h" +#include "winbase.h" +#include "winstring.h" + +#include "activation.h" + +#define WIDL_using_Windows_Foundation +#include "windows.foundation.h" +#define WIDL_using_Windows_UI +#include "windows.ui.h" +#define WIDL_using_Windows_UI_ViewManagement +#include "windows.ui.viewmanagement.h" + +extern IActivationFactory *uisettings_factory; + +#endif diff --git a/dlls/windows.ui/tests/Makefile.in b/dlls/windows.ui/tests/Makefile.in new file mode 100644 index 00000000000..4c587f17f23 --- /dev/null +++ b/dlls/windows.ui/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = windows.ui.dll +IMPORTS = combase + +C_SRCS = \ + uisettings.c diff --git a/dlls/windows.ui/tests/uisettings.c b/dlls/windows.ui/tests/uisettings.c new file mode 100644 index 00000000000..d9e10aee177 --- /dev/null +++ b/dlls/windows.ui/tests/uisettings.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2023 Mohamad Al-Jaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#define COBJMACROS +#include "initguid.h" +#include <stdarg.h> + +#include "windef.h" +#include "winbase.h" +#include "winstring.h" + +#include "roapi.h" + +#define WIDL_using_Windows_Foundation +#include "windows.foundation.h" +#define WIDL_using_Windows_UI +#include "windows.ui.h" +#define WIDL_using_Windows_UI_ViewManagement +#include "windows.ui.viewmanagement.h" + +#include "wine/test.h" + +#define check_interface( obj, iid, exp ) check_interface_( __LINE__, obj, iid, exp ) +static void check_interface_( unsigned int line, void *obj, const IID *iid, BOOL supported ) +{ + IUnknown *iface = obj; + IUnknown *unk; + HRESULT hr, expected_hr; + + expected_hr = supported ? S_OK : E_NOINTERFACE; + + hr = IUnknown_QueryInterface( iface, iid, (void **)&unk ); + ok_( __FILE__, line )( hr == expected_hr, "Got hr %#lx, expected %#lx.\n", hr, expected_hr ); + if (SUCCEEDED(hr)) + IUnknown_Release( unk ); +} + +static void test_UISettings(void) +{ + static const WCHAR *uisettings_name = L"Windows.UI.ViewManagement.UISettings"; + IActivationFactory *factory; + HSTRING str; + HRESULT hr; + LONG ref; + + hr = WindowsCreateString( uisettings_name, wcslen( uisettings_name ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = RoGetActivationFactory( str, &IID_IActivationFactory, (void **)&factory ); + WindowsDeleteString( str ); + ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "got hr %#lx.\n", hr ); + if (hr == REGDB_E_CLASSNOTREG) + { + win_skip( "%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w( uisettings_name ) ); + return; + } + + check_interface( factory, &IID_IUnknown, TRUE ); + check_interface( factory, &IID_IInspectable, TRUE ); + check_interface( factory, &IID_IAgileObject, FALSE ); + + ref = IActivationFactory_Release( factory ); + ok( ref == 1, "got ref %ld.\n", ref ); +} + +START_TEST(uisettings) +{ + HRESULT hr; + + hr = RoInitialize( RO_INIT_MULTITHREADED ); + ok( hr == S_OK, "RoInitialize failed, hr %#lx\n", hr ); + + test_UISettings(); + + RoUninitialize(); +} diff --git a/dlls/windows.ui/uisettings.c b/dlls/windows.ui/uisettings.c new file mode 100644 index 00000000000..1ce1096d708 --- /dev/null +++ b/dlls/windows.ui/uisettings.c @@ -0,0 +1,116 @@ +/* WinRT Windows.UI Implementation + * + * Copyright (C) 2023 Mohamad Al-Jaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ui); + +struct uisettings_statics +{ + IActivationFactory IActivationFactory_iface; + LONG ref; +}; + +static inline struct uisettings_statics *impl_from_IActivationFactory( IActivationFactory *iface ) +{ + return CONTAINING_RECORD( iface, struct uisettings_statics, IActivationFactory_iface ); +} + +static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out ) +{ + struct uisettings_statics *impl = impl_from_IActivationFactory( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IActivationFactory )) + { + *out = &impl->IActivationFactory_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI factory_AddRef( IActivationFactory *iface ) +{ + struct uisettings_statics *impl = impl_from_IActivationFactory( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p, ref %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI factory_Release( IActivationFactory *iface ) +{ + struct uisettings_statics *impl = impl_from_IActivationFactory( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + TRACE( "iface %p, ref %lu.\n", iface, ref ); + return ref; +} + +static HRESULT WINAPI factory_GetIids( IActivationFactory *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_GetRuntimeClassName( IActivationFactory *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_GetTrustLevel( IActivationFactory *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_ActivateInstance( IActivationFactory *iface, IInspectable **instance ) +{ + FIXME( "iface %p, instance %p stub!\n", iface, instance ); + return E_NOTIMPL; +} + +static const struct IActivationFactoryVtbl factory_vtbl = +{ + factory_QueryInterface, + factory_AddRef, + factory_Release, + /* IInspectable methods */ + factory_GetIids, + factory_GetRuntimeClassName, + factory_GetTrustLevel, + /* IActivationFactory methods */ + factory_ActivateInstance, +}; + +static struct uisettings_statics uisettings_statics = +{ + {&factory_vtbl}, + 1, +}; + +IActivationFactory *uisettings_factory = &uisettings_statics.IActivationFactory_iface; diff --git a/dlls/windows.ui/windows.ui.spec b/dlls/windows.ui/windows.ui.spec new file mode 100644 index 00000000000..7801fb70dcc --- /dev/null +++ b/dlls/windows.ui/windows.ui.spec @@ -0,0 +1,7 @@ +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetActivationFactory(ptr ptr) +@ stdcall -private DllGetClassObject(ptr ptr ptr) +@ stdcall -private DllRegisterServer() +@ stdcall -private DllUnregisterServer() +@ stub CreateControlInput +@ stub CreateControlInputEx
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/windows.ui/tests/uisettings.c | 22 +++++- dlls/windows.ui/uisettings.c | 119 ++++++++++++++++++++++++++++- 2 files changed, 138 insertions(+), 3 deletions(-)
diff --git a/dlls/windows.ui/tests/uisettings.c b/dlls/windows.ui/tests/uisettings.c index d9e10aee177..a54b581dfd0 100644 --- a/dlls/windows.ui/tests/uisettings.c +++ b/dlls/windows.ui/tests/uisettings.c @@ -53,6 +53,8 @@ static void test_UISettings(void) { static const WCHAR *uisettings_name = L"Windows.UI.ViewManagement.UISettings"; IActivationFactory *factory; + IUISettings3 *uisettings3; + IInspectable *inspectable; HSTRING str; HRESULT hr; LONG ref; @@ -61,7 +63,6 @@ static void test_UISettings(void) ok( hr == S_OK, "got hr %#lx.\n", hr );
hr = RoGetActivationFactory( str, &IID_IActivationFactory, (void **)&factory ); - WindowsDeleteString( str ); ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "got hr %#lx.\n", hr ); if (hr == REGDB_E_CLASSNOTREG) { @@ -72,7 +73,26 @@ static void test_UISettings(void) check_interface( factory, &IID_IUnknown, TRUE ); check_interface( factory, &IID_IInspectable, TRUE ); check_interface( factory, &IID_IAgileObject, FALSE ); + check_interface( factory, &IID_IUISettings3, FALSE ); + + hr = RoActivateInstance( str, &inspectable ); + ok( hr == S_OK, "Got unexpected hr %#lx.\n", hr ); + WindowsDeleteString( str ); + + hr = IInspectable_QueryInterface( inspectable, &IID_IUISettings3, (void **)&uisettings3 ); + ok( hr == S_OK || broken( hr == E_NOINTERFACE ), "Got unexpected hr %#lx.\n", hr ); + if (FAILED(hr)) + { + win_skip( "IUISettings3 not supported.\n" ); + goto skip_uisettings3; + } + + check_interface( inspectable, &IID_IAgileObject, TRUE ); + + IUISettings3_Release( uisettings3 );
+skip_uisettings3: + IInspectable_Release( inspectable ); ref = IActivationFactory_Release( factory ); ok( ref == 1, "got ref %ld.\n", ref ); } diff --git a/dlls/windows.ui/uisettings.c b/dlls/windows.ui/uisettings.c index 1ce1096d708..983a9b9f0cf 100644 --- a/dlls/windows.ui/uisettings.c +++ b/dlls/windows.ui/uisettings.c @@ -23,6 +23,108 @@
WINE_DEFAULT_DEBUG_CHANNEL(ui);
+struct uisettings +{ + IUISettings3 IUISettings3_iface; + LONG ref; +}; + +static inline struct uisettings *impl_from_IUISettings3( IUISettings3 *iface ) +{ + return CONTAINING_RECORD( iface, struct uisettings, IUISettings3_iface ); +} + +static HRESULT WINAPI uisettings3_QueryInterface( IUISettings3 *iface, REFIID iid, void **out ) +{ + struct uisettings *impl = impl_from_IUISettings3( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_IUISettings3 )) + { + *out = &impl->IUISettings3_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI uisettings3_AddRef( IUISettings3 *iface ) +{ + struct uisettings *impl = impl_from_IUISettings3( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p, ref %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI uisettings3_Release( IUISettings3 *iface ) +{ + struct uisettings *impl = impl_from_IUISettings3( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p, ref %lu.\n", iface, ref ); + + if (!ref) free( impl ); + return ref; +} + +static HRESULT WINAPI uisettings3_GetIids( IUISettings3 *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI uisettings3_GetRuntimeClassName( IUISettings3 *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI uisettings3_GetTrustLevel( IUISettings3 *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI uisettings3_GetColorValue( IUISettings3 *iface, UIColorType type, Color *value ) +{ + FIXME( "iface %p, type %d, color %p stub!\n", iface, type, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI uisettings3_add_ColorValuesChanged( IUISettings3 *iface, ITypedEventHandler_UISettings_IInspectable *handler, EventRegistrationToken *cookie ) +{ + FIXME( "iface %p, handler %p, cookie %p stub!\n", iface, handler, cookie ); + return E_NOTIMPL; +} + +static HRESULT WINAPI uisettings3_remove_ColorValuesChanged( IUISettings3 *iface, EventRegistrationToken cookie ) +{ + FIXME( "iface %p, cookie %#I64x stub!\n", iface, cookie.value ); + return E_NOTIMPL; +} + +static const struct IUISettings3Vtbl uisettings3_vtbl = +{ + uisettings3_QueryInterface, + uisettings3_AddRef, + uisettings3_Release, + /* IInspectable methods */ + uisettings3_GetIids, + uisettings3_GetRuntimeClassName, + uisettings3_GetTrustLevel, + /* IUISettings3 methods */ + uisettings3_GetColorValue, + uisettings3_add_ColorValuesChanged, + uisettings3_remove_ColorValuesChanged, +}; + struct uisettings_statics { IActivationFactory IActivationFactory_iface; @@ -90,8 +192,21 @@ static HRESULT WINAPI factory_GetTrustLevel( IActivationFactory *iface, TrustLev
static HRESULT WINAPI factory_ActivateInstance( IActivationFactory *iface, IInspectable **instance ) { - FIXME( "iface %p, instance %p stub!\n", iface, instance ); - return E_NOTIMPL; + struct uisettings *impl; + + TRACE( "iface %p, instance %p.\n", iface, instance ); + + if (!(impl = calloc( 1, sizeof(*impl) ))) + { + *instance = NULL; + return E_OUTOFMEMORY; + } + + impl->IUISettings3_iface.lpVtbl = &uisettings3_vtbl; + impl->ref = 1; + + *instance = (IInspectable *)&impl->IUISettings3_iface; + return S_OK; }
static const struct IActivationFactoryVtbl factory_vtbl =
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/windows.ui/tests/Makefile.in | 2 +- dlls/windows.ui/tests/uisettings.c | 75 ++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-)
diff --git a/dlls/windows.ui/tests/Makefile.in b/dlls/windows.ui/tests/Makefile.in index 4c587f17f23..76dbfb1677c 100644 --- a/dlls/windows.ui/tests/Makefile.in +++ b/dlls/windows.ui/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = windows.ui.dll -IMPORTS = combase +IMPORTS = combase advapi32
C_SRCS = \ uisettings.c diff --git a/dlls/windows.ui/tests/uisettings.c b/dlls/windows.ui/tests/uisettings.c index a54b581dfd0..133173c528c 100644 --- a/dlls/windows.ui/tests/uisettings.c +++ b/dlls/windows.ui/tests/uisettings.c @@ -34,6 +34,10 @@
#include "wine/test.h"
+static const WCHAR *subkey = L"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"; +static const WCHAR *name = L"AppsUseLightTheme"; +static const HKEY root = HKEY_CURRENT_USER; + #define check_interface( obj, iid, exp ) check_interface_( __LINE__, obj, iid, exp ) static void check_interface_( unsigned int line, void *obj, const IID *iid, BOOL supported ) { @@ -49,12 +53,45 @@ static void check_interface_( unsigned int line, void *obj, const IID *iid, BOOL IUnknown_Release( unk ); }
+static DWORD get_app_theme(void) +{ + DWORD ret = 0, len = sizeof(ret), type; + HKEY hkey; + + if (RegOpenKeyExW( root, subkey, 0, KEY_QUERY_VALUE, &hkey )) return 1; + if (RegQueryValueExW( hkey, name, NULL, &type, (BYTE *)&ret, &len ) || type != REG_DWORD) ret = 1; + RegCloseKey( hkey ); + return ret; +} + +static DWORD set_app_theme( DWORD mode ) +{ + DWORD ret = 1, len = sizeof(ret); + HKEY hkey; + + if (RegOpenKeyExW( root, subkey, 0, KEY_SET_VALUE, &hkey )) return 0; + if (RegSetValueExW( hkey, name, 0, REG_DWORD, (const BYTE *)&mode, len )) ret = 0; + RegCloseKey( hkey ); + return ret; +} + +static void reset_color( Color *value ) +{ + value->A = 1; + value->R = 1; + value->G = 1; + value->B = 1; +} + static void test_UISettings(void) { static const WCHAR *uisettings_name = L"Windows.UI.ViewManagement.UISettings"; IActivationFactory *factory; IUISettings3 *uisettings3; IInspectable *inspectable; + DWORD default_theme; + UIColorType type; + Color value; HSTRING str; HRESULT hr; LONG ref; @@ -89,6 +126,44 @@ static void test_UISettings(void)
check_interface( inspectable, &IID_IAgileObject, TRUE );
+ default_theme = get_app_theme(); + + /* Light Theme */ + if (!set_app_theme( 1 )) goto done; + + reset_color( &value ); + type = UIColorType_Foreground; + hr = IUISettings3_GetColorValue( uisettings3, type, &value ); + todo_wine ok( hr == S_OK, "GetColorValue returned %#lx\n", hr ); + todo_wine ok( value.A == 255 && value.R == 0 && value.G == 0 && value.B == 0, + "got unexpected value.A == %d value.R == %d value.G == %d value.B == %d\n", value.A, value.R, value.G, value.B ); + + reset_color( &value ); + type = UIColorType_Background; + hr = IUISettings3_GetColorValue( uisettings3, type, &value ); + todo_wine ok( hr == S_OK, "GetColorValue returned %#lx\n", hr ); + todo_wine ok( value.A == 255 && value.R == 255 && value.G == 255 && value.B == 255, + "got unexpected value.A == %d value.R == %d value.G == %d value.B == %d\n", value.A, value.R, value.G, value.B ); + + /* Dark Theme */ + if (!set_app_theme( 0 )) goto done; + + reset_color( &value ); + type = UIColorType_Foreground; + hr = IUISettings3_GetColorValue( uisettings3, type, &value ); + todo_wine ok( hr == S_OK, "GetColorValue returned %#lx\n", hr ); + todo_wine ok( value.A == 255 && value.R == 255 && value.G == 255 && value.B == 255, + "got unexpected value.A == %d value.R == %d value.G == %d value.B == %d\n", value.A, value.R, value.G, value.B ); + + reset_color( &value ); + type = UIColorType_Background; + hr = IUISettings3_GetColorValue( uisettings3, type, &value ); + todo_wine ok( hr == S_OK, "GetColorValue returned %#lx\n", hr ); + todo_wine ok( value.A == 255 && value.R == 0 && value.G == 0 && value.B == 0, + "got unexpected value.A == %d value.R == %d value.G == %d value.B == %d\n", value.A, value.R, value.G, value.B ); + +done: + set_app_theme( default_theme ); IUISettings3_Release( uisettings3 );
skip_uisettings3:
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/windows.ui/Makefile.in | 2 +- dlls/windows.ui/tests/uisettings.c | 12 ++++---- dlls/windows.ui/uisettings.c | 46 ++++++++++++++++++++++++++++-- 3 files changed, 51 insertions(+), 9 deletions(-)
diff --git a/dlls/windows.ui/Makefile.in b/dlls/windows.ui/Makefile.in index cb9b48a664b..592d023f353 100644 --- a/dlls/windows.ui/Makefile.in +++ b/dlls/windows.ui/Makefile.in @@ -1,5 +1,5 @@ MODULE = windows.ui.dll -IMPORTS = combase +IMPORTS = combase advapi32
C_SRCS = \ main.c \ diff --git a/dlls/windows.ui/tests/uisettings.c b/dlls/windows.ui/tests/uisettings.c index 133173c528c..bd1e7a02d20 100644 --- a/dlls/windows.ui/tests/uisettings.c +++ b/dlls/windows.ui/tests/uisettings.c @@ -134,15 +134,15 @@ static void test_UISettings(void) reset_color( &value ); type = UIColorType_Foreground; hr = IUISettings3_GetColorValue( uisettings3, type, &value ); - todo_wine ok( hr == S_OK, "GetColorValue returned %#lx\n", hr ); - todo_wine ok( value.A == 255 && value.R == 0 && value.G == 0 && value.B == 0, + ok( hr == S_OK, "GetColorValue returned %#lx\n", hr ); + ok( value.A == 255 && value.R == 0 && value.G == 0 && value.B == 0, "got unexpected value.A == %d value.R == %d value.G == %d value.B == %d\n", value.A, value.R, value.G, value.B );
reset_color( &value ); type = UIColorType_Background; hr = IUISettings3_GetColorValue( uisettings3, type, &value ); - todo_wine ok( hr == S_OK, "GetColorValue returned %#lx\n", hr ); - todo_wine ok( value.A == 255 && value.R == 255 && value.G == 255 && value.B == 255, + ok( hr == S_OK, "GetColorValue returned %#lx\n", hr ); + ok( value.A == 255 && value.R == 255 && value.G == 255 && value.B == 255, "got unexpected value.A == %d value.R == %d value.G == %d value.B == %d\n", value.A, value.R, value.G, value.B );
/* Dark Theme */ @@ -151,14 +151,14 @@ static void test_UISettings(void) reset_color( &value ); type = UIColorType_Foreground; hr = IUISettings3_GetColorValue( uisettings3, type, &value ); - todo_wine ok( hr == S_OK, "GetColorValue returned %#lx\n", hr ); + ok( hr == S_OK, "GetColorValue returned %#lx\n", hr ); todo_wine ok( value.A == 255 && value.R == 255 && value.G == 255 && value.B == 255, "got unexpected value.A == %d value.R == %d value.G == %d value.B == %d\n", value.A, value.R, value.G, value.B );
reset_color( &value ); type = UIColorType_Background; hr = IUISettings3_GetColorValue( uisettings3, type, &value ); - todo_wine ok( hr == S_OK, "GetColorValue returned %#lx\n", hr ); + ok( hr == S_OK, "GetColorValue returned %#lx\n", hr ); todo_wine ok( value.A == 255 && value.R == 0 && value.G == 0 && value.B == 0, "got unexpected value.A == %d value.R == %d value.G == %d value.B == %d\n", value.A, value.R, value.G, value.B );
diff --git a/dlls/windows.ui/uisettings.c b/dlls/windows.ui/uisettings.c index 983a9b9f0cf..943fbb6a37e 100644 --- a/dlls/windows.ui/uisettings.c +++ b/dlls/windows.ui/uisettings.c @@ -92,10 +92,52 @@ static HRESULT WINAPI uisettings3_GetTrustLevel( IUISettings3 *iface, TrustLevel return E_NOTIMPL; }
+static DWORD get_app_theme(void) +{ + static const WCHAR *subkey = L"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"; + static const WCHAR *name = L"AppsUseLightTheme"; + static const HKEY root = HKEY_CURRENT_USER; + DWORD ret = 0, len = sizeof(ret), type; + HKEY hkey; + + if (RegOpenKeyExW( root, subkey, 0, KEY_QUERY_VALUE, &hkey )) return 1; + if (RegQueryValueExW( hkey, name, NULL, &type, (BYTE *)&ret, &len ) || type != REG_DWORD) ret = 1; + RegCloseKey( hkey ); + return ret; +} + +static void set_color_value( BYTE a, BYTE r, BYTE g, BYTE b, Color *out ) +{ + out->A = a; + out->R = r; + out->G = g; + out->B = b; +} + static HRESULT WINAPI uisettings3_GetColorValue( IUISettings3 *iface, UIColorType type, Color *value ) { - FIXME( "iface %p, type %d, color %p stub!\n", iface, type, value ); - return E_NOTIMPL; + DWORD theme; + + TRACE( "iface %p, type %d, value %p.\n", iface, type, value ); + + switch (type) + { + case UIColorType_Foreground: + case UIColorType_Background: + theme = get_app_theme(); + break; + default: + FIXME( "type %d not implemented.\n", type ); + return E_NOTIMPL; + } + + if (type == UIColorType_Foreground) + set_color_value( 255, theme ? 0 : 255, theme ? 0 : 255, theme ? 0 : 255, value ); + else + set_color_value( 255, theme ? 255 : 0, theme ? 255 : 0, theme ? 255 : 0, value ); + + TRACE( "Returning value.A = %d, value.R = %d, value.G = %d, value.B = %d\n", value->A, value->R, value->G, value->B ); + return S_OK; }
static HRESULT WINAPI uisettings3_add_ColorValuesChanged( IUISettings3 *iface, ITypedEventHandler_UISettings_IInspectable *handler, EventRegistrationToken *cookie )
**v4** - Remove unknown entry points - Remove unneeded interfaces and classes - Amend whitespace - Add `IAgileObject` to uisettings3_QueryInterface - Add tests prior to implementing `IUISettings3::GetColorValue`
On Thu Feb 9 04:16:33 2023 +0000, Mohamad Al-Jaf wrote:
changed this line in [version 4 of the diff](/wine/wine/-/merge_requests/2103/diffs?diff_id=31671&start_sha=f64b50840c2aa2464f8869ad22b65fe9c8c613df#11182fdead11787061af0e1b24c36ecbdd887b52_171_144)
I also dropped the declarations since they're not being used.
On Thu Feb 9 04:16:31 2023 +0000, Mohamad Al-Jaf wrote:
changed this line in [version 4 of the diff](/wine/wine/-/merge_requests/2103/diffs?diff_id=31671&start_sha=f64b50840c2aa2464f8869ad22b65fe9c8c613df#6b66c0a00a782bc4eb89000b40a04c672a35d7a4_115_113)
Indeed, this was leftover from when I was amending the tests.
On Thu Feb 9 04:16:30 2023 +0000, Mohamad Al-Jaf wrote:
changed this line in [version 4 of the diff](/wine/wine/-/merge_requests/2103/diffs?diff_id=31671&start_sha=f64b50840c2aa2464f8869ad22b65fe9c8c613df#8ba20b10e9c7c0f0b3158887f044e690681f6762_12_8)
Yeah, it looks like they're internal to Windows anyway.
On Tue Feb 7 10:40:45 2023 +0000, Rémi Bernon wrote:
Not sure if it's fine to add IUISettings3 by itself without
IUISettings first. IUISettings3 doesn't seem to be inherited. Yes, WinRT doesn't use inheritance. So I think it's fine to skip some interfaces unless some app queries them. Haven't looked at the registry problems, though ofc they need to be addressed if there's any.
It looks like Chromium queries IUISettings and IUISettings2. But it's not relevant to this MR so no reason to add them.
I think the registry issue should be fixed after creating the key AppsUseLightTheme. Though, it's still unclear why RegSetValueExW creates the key locally but not in the testbot.
This merge request was approved by Rémi Bernon.