Skip to content

Commit

Permalink
Add support for icon_variants and variants in menus and action APIs f…
Browse files Browse the repository at this point in the history
…or Web Extensions.

https://webkit.org/b/279135
rdar://problem/134885372

Reviewed by NOBODY (OOPS!).

Add support for the `icons_variants` key in `menus.create()` and `menus.update()`.
Also add support for `variants` key in `action.setIcon()`.

Proposal: https://github.com/w3c/webextensions/blob/main/proposals/dark_mode_extension_icons.md
WECG issue: w3c/webextensions#229

* Source/WebKit/Shared/Extensions/WebExtensionMenuItem.serialization.in:
* Source/WebKit/Shared/Extensions/WebExtensionMenuItemParameters.h:
* Source/WebKit/UIProcess/Extensions/Cocoa/API/WebExtensionContextAPIActionCocoa.mm:
(WebKit::WebExtensionContext::actionSetIcon):
* Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionActionCocoa.mm:
(WebKit::WebExtensionAction::clearCustomizations):
(WebKit::WebExtensionAction::icon):
(WebKit::WebExtensionAction::setIcons):
(WebKit::WebExtensionAction::setIconVariants):
(WebKit::WebExtensionAction::clearIconCache):
(WebKit::WebExtensionAction::setIconsDictionary): Deleted.
* Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionMenuItemCocoa.mm:
(WebKit::WebExtensionMenuItem::WebExtensionMenuItem):
(WebKit::WebExtensionMenuItem::minimalParameters const):
(WebKit::WebExtensionMenuItem::update):
(WebKit::WebExtensionMenuItem::icon const):
(WebKit::WebExtensionMenuItem::clearIconCache const):
* Source/WebKit/UIProcess/Extensions/WebExtensionAction.h:
* Source/WebKit/UIProcess/Extensions/WebExtensionContext.h:
* Source/WebKit/UIProcess/Extensions/WebExtensionContext.messages.in:
* Source/WebKit/UIProcess/Extensions/WebExtensionMenuItem.h:
* Source/WebKit/WebProcess/Extensions/API/Cocoa/WebExtensionAPIActionCocoa.mm:
(WebKit::WebExtensionAPIAction::isValidDimensionKey):
(WebKit::WebExtensionAPIAction::parseIconPath):
(WebKit::WebExtensionAPIAction::parseIconPathsDictionary):
(WebKit::WebExtensionAPIAction::parseIconImageDataDictionary):
(WebKit::WebExtensionAPIAction::parseIconVariants):
(WebKit::WebExtensionAPIAction::setIcon):
* Source/WebKit/WebProcess/Extensions/API/Cocoa/WebExtensionAPIMenusCocoa.mm:
(WebKit::WebExtensionAPIMenus::parseCreateAndUpdateProperties):
(WebKit::WebExtensionAPIMenus::createMenu):
(WebKit::WebExtensionAPIMenus::update):
* Source/WebKit/WebProcess/Extensions/API/WebExtensionAPIAction.h:
* Source/WebKit/WebProcess/Extensions/API/WebExtensionAPIMenus.h:
* Source/WebKit/WebProcess/Extensions/Bindings/Scripts/CodeGeneratorExtensions.pm:
(_generateImplementationFile):
* Source/WebKit/WebProcess/Extensions/Interfaces/WebExtensionAPIMenus.idl:
* Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionAPIAction.mm:
(TestWebKitAPI::TEST(WKWebExtensionAPIAction, SetIconWithDataURL)): Renamed.
(TestWebKitAPI::TEST(WKWebExtensionAPIAction, SetIconWithVariants)): Added.
(TestWebKitAPI::TEST(WKWebExtensionAPIAction, SetIconWithImageDataAndVariants)): Added.
(TestWebKitAPI::TEST(WKWebExtensionAPIAction, SetIconThrowsWithNoValidVariants)): Added.
(TestWebKitAPI::TEST(WKWebExtensionAPIAction, SetIconWithMixedValidAndInvalidVariants)): Added.
(TestWebKitAPI::TEST(WKWebExtensionAPIAction, SetIconWithAnySizeVariantAndSVGDataURL)): Added.
(TestWebKitAPI::TEST(WKWebExtensionAPIAction, SetIconWithSVGDataURL)): Deleted.
* Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionAPIMenus.mm:
(TestWebKitAPI::TEST(WKWebExtensionAPIMenus, Errors)): Fixed expectations.
(TestWebKitAPI::TEST(WKWebExtensionAPIMenus, MenuItemWithIconVariants)): Added.
(TestWebKitAPI::TEST(WKWebExtensionAPIMenus, MenuItemWithImageDataVariants)): Added.
(TestWebKitAPI::TEST(WKWebExtensionAPIMenus, MenuItemWithWithNoValidVariants)): Added.
(TestWebKitAPI::TEST(WKWebExtensionAPIMenus, MenuItemWithMixedValidAndInvalidIconVariants)): Added.
(TestWebKitAPI::TEST(WKWebExtensionAPIMenus, MenuItemWithAnySizeVariantAndSVGDataURL)): Added.
(TestWebKitAPI::TEST(WKWebExtensionAPIMenus, UpdateMenuItemWithIconVariants)): Added.
(TestWebKitAPI::TEST(WKWebExtensionAPIMenus, ClearMenuItemIconVariantsWithNull)): Added.
(TestWebKitAPI::TEST(WKWebExtensionAPIMenus, ClearMenuItemIconVariantsWithEmpty)): Added.
  • Loading branch information
xeenon committed Sep 4, 2024
1 parent 56a9103 commit 3c878d8
Show file tree
Hide file tree
Showing 17 changed files with 1,194 additions and 95 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ struct WebKit::WebExtensionMenuItemParameters {
String title;
String command;

String iconDictionaryJSON;
String iconsJSON;

std::optional<bool> checked;
std::optional<bool> enabled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ struct WebExtensionMenuItemParameters {
String title;
String command;

String iconDictionaryJSON;
String iconsJSON;

std::optional<bool> checked;
std::optional<bool> enabled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
completionHandler({ });
}

void WebExtensionContext::actionSetIcon(std::optional<WebExtensionWindowIdentifier> windowIdentifier, std::optional<WebExtensionTabIdentifier> tabIdentifier, const String& iconDictionaryJSON, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&& completionHandler)
void WebExtensionContext::actionSetIcon(std::optional<WebExtensionWindowIdentifier> windowIdentifier, std::optional<WebExtensionTabIdentifier> tabIdentifier, const String& iconsJSON, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&& completionHandler)
{
static NSString * const apiName = @"action.setIcon()";

Expand All @@ -124,7 +124,19 @@
return;
}

action.value()->setIconsDictionary(parseJSON(iconDictionaryJSON));
id parsedIcons = parseJSON(iconsJSON, JSONOptions::FragmentsAllowed);
if (auto *dictionary = dynamic_objc_cast<NSDictionary>(parsedIcons))
action.value()->setIcons(dictionary);
#if ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
else if (auto *array = dynamic_objc_cast<NSArray>(parsedIcons))
action.value()->setIconVariants(array);
#endif
else {
action.value()->setIcons(nil);
#if ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
action.value()->setIconVariants(nil);
#endif
}

completionHandler({ });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,10 +591,17 @@ - (void)_otherPopoverWillShow:(NSNotification *)notification

void WebExtensionAction::clearCustomizations()
{
#if ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
if (!m_customIcons && !m_customIconVariants && m_customPopupPath.isNull() && m_customLabel.isNull() && m_customBadgeText.isNull() && !m_customEnabled && !m_blockedResourceCount)
#else
if (!m_customIcons && m_customPopupPath.isNull() && m_customLabel.isNull() && m_customBadgeText.isNull() && !m_customEnabled && !m_blockedResourceCount)
#endif
return;

m_customIcons = nil;
#if ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
m_customIconVariants = nil;
#endif
m_customPopupPath = nullString();
m_customLabel = nullString();
m_customBadgeText = nullString();
Expand All @@ -606,6 +613,7 @@ - (void)_otherPopoverWillShow:(NSNotification *)notification
m_popoverAppearance = Appearance::Default;
#endif

clearIconCache();
propertiesDidChange();
}

Expand Down Expand Up @@ -645,15 +653,46 @@ - (void)_otherPopoverWillShow:(NSNotification *)notification
if (!extensionContext())
return nil;

if (m_customIcons) {
auto *result = extensionContext()->extension().bestImageInIconsDictionary(m_customIcons.get(), idealSize, [&](auto *error) {
extensionContext()->recordError(error);
});
#if ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
if (m_customIconVariants || m_customIcons)
#else
if (m_customIcons)
#endif
{
// Clear the cache if the display scales change (connecting display, etc.)
auto *currentScales = availableScreenScales();
if (![currentScales isEqualToSet:m_cachedIconScales.get()])
clearIconCache();

if (m_cachedIcon && CGSizeEqualToSize(idealSize, m_cachedIconIdealSize))
return m_cachedIcon.get();

CocoaImage *result;

#if ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
if (m_customIconVariants) {
result = extensionContext()->extension().bestImageForIconVariants(m_customIconVariants.get(), idealSize, [&](auto *error) {
extensionContext()->recordError(error);
});
} else
#endif // ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
if (m_customIcons) {
result = extensionContext()->extension().bestImageInIconsDictionary(m_customIcons.get(), idealSize, [&](auto *error) {
extensionContext()->recordError(error);
});
}

if (result) {
m_cachedIcon = result;
m_cachedIconScales = currentScales;
m_cachedIconIdealSize = idealSize;

if (result)
return result;
}

clearIconCache();

// If custom icons fail, fallback to the default icons.
// If custom icons fail, fallback.
}

if (RefPtr fallback = fallbackAction())
Expand All @@ -663,16 +702,41 @@ - (void)_otherPopoverWillShow:(NSNotification *)notification
return extensionContext()->extension().actionIcon(idealSize);
}

void WebExtensionAction::setIconsDictionary(NSDictionary *icons)
void WebExtensionAction::setIcons(NSDictionary *icons)
{
if ([(m_customIcons ?: @{ }) isEqualToDictionary:(icons ?: @{ })])
return;

m_customIcons = icons.count ? icons : nil;
#if ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
m_customIconVariants = nil;
#endif

clearIconCache();
propertiesDidChange();
}

#if ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
void WebExtensionAction::setIconVariants(NSArray *iconVariants)
{
if ([(m_customIconVariants ?: @[ ]) isEqualToArray:(iconVariants ?: @[ ])])
return;

m_customIconVariants = iconVariants.count ? iconVariants : nil;
m_customIcons = nil;

clearIconCache();
propertiesDidChange();
}
#endif // ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)

void WebExtensionAction::clearIconCache()
{
m_cachedIcon = nil;
m_cachedIconScales = nil;
m_cachedIconIdealSize = CGSizeZero;
}

String WebExtensionAction::popupPath() const
{
if (!extensionContext())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,14 @@ - (IBAction)_performAction:(id)sender
else
m_contexts = WebExtensionMenuItemContextType::Page;

if (!parameters.iconDictionaryJSON.isEmpty())
m_icons = parseJSON(parameters.iconDictionaryJSON);
if (!parameters.iconsJSON.isEmpty()) {
id parsedIcons = parseJSON(parameters.iconsJSON, JSONOptions::FragmentsAllowed);
m_icons = dynamic_objc_cast<NSDictionary>(parsedIcons);
#if ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
m_iconVariants = dynamic_objc_cast<NSArray>(parsedIcons);
#endif
clearIconCache();
}

if (parameters.documentURLPatterns) {
for (auto& patternString : parameters.documentURLPatterns.value()) {
Expand All @@ -135,7 +141,7 @@ - (IBAction)_performAction:(id)sender

nullString(), // title
nullString(), // command
nullString(), // iconDictionaryJSON
nullString(), // iconsJSON

isChecked(),
isEnabled(),
Expand Down Expand Up @@ -175,8 +181,14 @@ - (IBAction)_performAction:(id)sender
if (!parameters.command.isNull())
m_command = extensionContext()->command(parameters.command);

if (!parameters.iconDictionaryJSON.isNull())
m_icons = parseJSON(parameters.iconDictionaryJSON);
if (!parameters.iconsJSON.isNull()) {
id parsedIcons = parseJSON(parameters.iconsJSON, JSONOptions::FragmentsAllowed);
m_icons = dynamic_objc_cast<NSDictionary>(parsedIcons);
#if ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
m_iconVariants = dynamic_objc_cast<NSArray>(parsedIcons);
#endif
clearIconCache();
}

if (parameters.checked)
m_checked = parameters.checked.value();
Expand Down Expand Up @@ -331,9 +343,54 @@ - (IBAction)_performAction:(id)sender
{
ASSERT(extensionContext());

return extensionContext()->extension().bestImageInIconsDictionary(m_icons.get(), idealSize, [&](auto *error) {
extensionContext()->recordError(error);
});
#if ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
if (!m_iconVariants && !m_icons)
#else
if (!m_icons)
#endif
return nil;

// Clear the cache if the display scales change (connecting display, etc.)
auto *currentScales = availableScreenScales();
if (![currentScales isEqualToSet:m_cachedIconScales.get()])
clearIconCache();

if (m_cachedIcon && CGSizeEqualToSize(idealSize, m_cachedIconIdealSize))
return m_cachedIcon.get();

CocoaImage *result;

#if ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
if (m_iconVariants) {
result = extensionContext()->extension().bestImageForIconVariants(m_iconVariants.get(), idealSize, [&](auto *error) {
extensionContext()->recordError(error);
});
} else
#endif // ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
if (m_icons) {
result = extensionContext()->extension().bestImageInIconsDictionary(m_icons.get(), idealSize, [&](auto *error) {
extensionContext()->recordError(error);
});
}

if (result) {
m_cachedIcon = result;
m_cachedIconIdealSize = idealSize;
m_cachedIconScales = currentScales;

return result;
}

clearIconCache();

return nil;
}

void WebExtensionMenuItem::clearIconCache() const
{
m_cachedIcon = nil;
m_cachedIconScales = nil;
m_cachedIconIdealSize = CGSizeZero;
}

} // namespace WebKit
Expand Down
14 changes: 13 additions & 1 deletion Source/WebKit/UIProcess/Extensions/WebExtensionAction.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ class WebExtensionAction : public API::ObjectImpl<API::Object::Type::WebExtensio
void propertiesDidChange();

CocoaImage *icon(CGSize);
void setIconsDictionary(NSDictionary *);
void setIcons(NSDictionary *);
#if ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
void setIconVariants(NSArray *);
#endif

String label(FallbackWhenEmpty = FallbackWhenEmpty::Yes) const;
void setLabel(String);
Expand Down Expand Up @@ -144,6 +147,8 @@ class WebExtensionAction : public API::ObjectImpl<API::Object::Type::WebExtensio
private:
WebExtensionAction* fallbackAction() const;

void clearIconCache();

#if PLATFORM(MAC)
void detectPopoverColorScheme();
#endif
Expand All @@ -166,7 +171,14 @@ class WebExtensionAction : public API::ObjectImpl<API::Object::Type::WebExtensio
String m_customPopupPath;
String m_popupWebViewInspectionName;

RetainPtr<CocoaImage> m_cachedIcon;
RetainPtr<NSSet> m_cachedIconScales;
CGSize m_cachedIconIdealSize { CGSizeZero };

RetainPtr<NSDictionary> m_customIcons;
#if ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
RetainPtr<NSArray> m_customIconVariants;
#endif
String m_customLabel;
String m_customBadgeText;
ssize_t m_blockedResourceCount { 0 };
Expand Down
2 changes: 1 addition & 1 deletion Source/WebKit/UIProcess/Extensions/WebExtensionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ class WebExtensionContext : public API::ObjectImpl<API::Object::Type::WebExtensi
bool isActionMessageAllowed();
void actionGetTitle(std::optional<WebExtensionWindowIdentifier>, std::optional<WebExtensionTabIdentifier>, CompletionHandler<void(Expected<String, WebExtensionError>&&)>&&);
void actionSetTitle(std::optional<WebExtensionWindowIdentifier>, std::optional<WebExtensionTabIdentifier>, const String& title, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&&);
void actionSetIcon(std::optional<WebExtensionWindowIdentifier>, std::optional<WebExtensionTabIdentifier>, const String& iconDictionaryJSON, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&&);
void actionSetIcon(std::optional<WebExtensionWindowIdentifier>, std::optional<WebExtensionTabIdentifier>, const String& iconsJSON, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&&);
void actionGetPopup(std::optional<WebExtensionWindowIdentifier>, std::optional<WebExtensionTabIdentifier>, CompletionHandler<void(Expected<String, WebExtensionError>&&)>&&);
void actionSetPopup(std::optional<WebExtensionWindowIdentifier>, std::optional<WebExtensionTabIdentifier>, const String& popupPath, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&&);
void actionOpenPopup(WebPageProxyIdentifier, std::optional<WebExtensionWindowIdentifier>, std::optional<WebExtensionTabIdentifier>, CompletionHandler<void(Expected<void, WebExtensionError>&&)>&&);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ messages -> WebExtensionContext {
// Action APIs
[EnabledIf='isActionMessageAllowed()'] ActionGetTitle(std::optional<WebKit::WebExtensionWindowIdentifier> windowIdentifier, std::optional<WebKit::WebExtensionTabIdentifier> tabIdentifier) -> (Expected<String, WebKit::WebExtensionError> result)
[EnabledIf='isActionMessageAllowed()'] ActionSetTitle(std::optional<WebKit::WebExtensionWindowIdentifier> windowIdentifier, std::optional<WebKit::WebExtensionTabIdentifier> tabIdentifier, String title) -> (Expected<void, WebKit::WebExtensionError> result)
[EnabledIf='isActionMessageAllowed()'] ActionSetIcon(std::optional<WebKit::WebExtensionWindowIdentifier> windowIdentifier, std::optional<WebKit::WebExtensionTabIdentifier> tabIdentifier, String iconDictionaryJSON) -> (Expected<void, WebKit::WebExtensionError> result)
[EnabledIf='isActionMessageAllowed()'] ActionSetIcon(std::optional<WebKit::WebExtensionWindowIdentifier> windowIdentifier, std::optional<WebKit::WebExtensionTabIdentifier> tabIdentifier, String iconsJSON) -> (Expected<void, WebKit::WebExtensionError> result)
[EnabledIf='isActionMessageAllowed()'] ActionGetPopup(std::optional<WebKit::WebExtensionWindowIdentifier> windowIdentifier, std::optional<WebKit::WebExtensionTabIdentifier> tabIdentifier) -> (Expected<String, WebKit::WebExtensionError> result)
[EnabledIf='isActionMessageAllowed()'] ActionSetPopup(std::optional<WebKit::WebExtensionWindowIdentifier> windowIdentifier, std::optional<WebKit::WebExtensionTabIdentifier> tabIdentifier, String popupPath) -> (Expected<void, WebKit::WebExtensionError> result)
[EnabledIf='isActionMessageAllowed()'] ActionOpenPopup(WebKit::WebPageProxyIdentifier identifier, std::optional<WebKit::WebExtensionWindowIdentifier> windowIdentifier, std::optional<WebKit::WebExtensionTabIdentifier> tabIdentifier) -> (Expected<void, WebKit::WebExtensionError> result)
Expand Down Expand Up @@ -126,7 +126,7 @@ messages -> WebExtensionContext {
[EnabledIf='isSidebarMessageAllowed()'] SidebarSetOptions(std::optional<WebKit::WebExtensionWindowIdentifier> windowIdentifier, std::optional<WebKit::WebExtensionTabIdentifier> tabIdentifier, std::optional<String> panelSourcePath, std::optional<bool> enabled) -> (Expected<void, WebKit::WebExtensionError> result)
[EnabledIf='isSidebarMessageAllowed()'] SidebarGetTitle(std::optional<WebKit::WebExtensionWindowIdentifier> windowIdentifier, std::optional<WebKit::WebExtensionTabIdentifier> tabIdentifier) -> (Expected<String, WebKit::WebExtensionError> result)
[EnabledIf='isSidebarMessageAllowed()'] SidebarSetTitle(std::optional<WebKit::WebExtensionWindowIdentifier> windowIdentifier, std::optional<WebKit::WebExtensionTabIdentifier> tabIdentifier, std::optional<String> title) -> (Expected<void, WebKit::WebExtensionError> result)
[EnabledIf='isSidebarMessageAllowed()'] SidebarSetIcon(std::optional<WebKit::WebExtensionWindowIdentifier> windowIdentifier, std::optional<WebKit::WebExtensionTabIdentifier> tabIdentifier, String iconDictionaryJSON) -> (Expected<void, WebKit::WebExtensionError> result)
[EnabledIf='isSidebarMessageAllowed()'] SidebarSetIcon(std::optional<WebKit::WebExtensionWindowIdentifier> windowIdentifier, std::optional<WebKit::WebExtensionTabIdentifier> tabIdentifier, String iconsJSON) -> (Expected<void, WebKit::WebExtensionError> result)
#endif // ENABLE(WK_WEB_EXTENSIONS_SIDEBAR)

// Storage APIs
Expand Down
10 changes: 10 additions & 0 deletions Source/WebKit/UIProcess/Extensions/WebExtensionMenuItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ class WebExtensionMenuItem : public RefCounted<WebExtensionMenuItem>, public Can

static String removeAmpersands(const String&);

void clearIconCache() const;

enum class ForceUnchecked : bool { No, Yes };
CocoaMenuItem *platformMenuItem(const WebExtensionMenuItemContextParameters&, ForceUnchecked = ForceUnchecked::No) const;

Expand All @@ -132,7 +134,15 @@ class WebExtensionMenuItem : public RefCounted<WebExtensionMenuItem>, public Can
String m_title;

RefPtr<WebExtensionCommand> m_command;

mutable RetainPtr<CocoaImage> m_cachedIcon;
mutable RetainPtr<NSSet> m_cachedIconScales;
mutable CGSize m_cachedIconIdealSize { CGSizeZero };

RetainPtr<NSDictionary> m_icons;
#if ENABLE(WK_WEB_EXTENSIONS_ICON_VARIANTS)
RetainPtr<NSArray> m_iconVariants;
#endif

bool m_checked : 1 { false };
bool m_enabled : 1 { true };
Expand Down
Loading

0 comments on commit 3c878d8

Please sign in to comment.