123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/remote_cocoa/app_shim/color_panel_bridge.h"
- #import <Cocoa/Cocoa.h>
- #include "skia/ext/skia_utils_mac.h"
- namespace {
- // The currently active bridge, to which the ColorPanelListener will forward
- // its observations.
- remote_cocoa::ColorPanelBridge* g_current_panel_bridge = nullptr;
- } // namespace
- // A singleton listener class to act as a event target for NSColorPanel and
- // send the results to the C++ class, ColorPanelBridge.
- @interface ColorPanelListener : NSObject {
- @protected
- // We don't call DidChooseColor if the change wasn't caused by the user
- // interacting with the panel.
- BOOL _nonUserChange;
- }
- // Called from NSNotificationCenter.
- - (void)windowWillClose:(NSNotification*)notification;
- // Called from NSColorPanel.
- - (void)didChooseColor:(NSColorPanel*)panel;
- // The singleton instance.
- + (ColorPanelListener*)instance;
- // Show the NSColorPanel.
- - (void)showColorPanel;
- // Sets color to the NSColorPanel as a non user change.
- - (void)setColor:(NSColor*)color;
- @end
- @implementation ColorPanelListener
- - (instancetype)init {
- if ((self = [super init])) {
- NSColorPanel* panel = [NSColorPanel sharedColorPanel];
- NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
- [nc addObserver:self
- selector:@selector(windowWillClose:)
- name:NSWindowWillCloseNotification
- object:panel];
- [nc addObserver:self
- selector:@selector(windowDidResignKey:)
- name:NSWindowDidResignKeyNotification
- object:panel];
- }
- return self;
- }
- - (void)dealloc {
- // This object is never freed.
- NOTREACHED();
- [super dealloc];
- }
- - (void)windowWillClose:(NSNotification*)notification {
- if (g_current_panel_bridge)
- g_current_panel_bridge->host()->DidCloseColorPanel();
- _nonUserChange = NO;
- }
- - (void)windowDidResignKey:(NSNotification*)notification {
- // Close the color panel when the user clicks away.
- [self windowWillClose:notification];
- [[NSColorPanel sharedColorPanel] close];
- }
- - (void)didChooseColor:(NSColorPanel*)panel {
- if (_nonUserChange) {
- _nonUserChange = NO;
- return;
- }
- _nonUserChange = NO;
- NSColor* color = [panel color];
- if ([[color colorSpaceName] isEqualToString:NSNamedColorSpace]) {
- color = [color colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]];
- // Some colors in "Developer" palette in "Color Palettes" tab can't be
- // converted to RGB. We just ignore such colors.
- // TODO(tkent): We should notice the rejection to users.
- if (!color)
- return;
- }
- SkColor skColor = 0;
- if ([color colorSpace] == [NSColorSpace genericRGBColorSpace]) {
- // genericRGB -> deviceRGB conversion isn't ignorable. We'd like to use RGB
- // values shown in NSColorPanel UI.
- CGFloat red, green, blue, alpha;
- [color getRed:&red green:&green blue:&blue alpha:&alpha];
- skColor = SkColorSetARGB(
- SkScalarRoundToInt(255.0 * alpha), SkScalarRoundToInt(255.0 * red),
- SkScalarRoundToInt(255.0 * green), SkScalarRoundToInt(255.0 * blue));
- } else {
- skColor = skia::NSDeviceColorToSkColor(
- [[panel color] colorUsingColorSpaceName:NSDeviceRGBColorSpace]);
- }
- if (g_current_panel_bridge)
- g_current_panel_bridge->host()->DidChooseColorInColorPanel(skColor);
- }
- + (ColorPanelListener*)instance {
- static ColorPanelListener* listener = [[ColorPanelListener alloc] init];
- return listener;
- }
- - (void)showColorPanel {
- NSColorPanel* panel = [NSColorPanel sharedColorPanel];
- [panel setShowsAlpha:NO];
- [panel setTarget:self];
- [panel setAction:@selector(didChooseColor:)];
- [panel makeKeyAndOrderFront:nil];
- }
- - (void)setColor:(NSColor*)color {
- _nonUserChange = YES;
- [[NSColorPanel sharedColorPanel] setColor:color];
- }
- @end
- namespace remote_cocoa {
- ColorPanelBridge::ColorPanelBridge(
- mojo::PendingRemote<mojom::ColorPanelHost> host)
- : host_(std::move(host)) {
- g_current_panel_bridge = this;
- }
- ColorPanelBridge::~ColorPanelBridge() {
- if (g_current_panel_bridge == this)
- g_current_panel_bridge = nullptr;
- }
- void ColorPanelBridge::Show(uint32_t initial_color, ShowCallback callback) {
- ColorPanelListener* listener = [ColorPanelListener instance];
- [listener setColor:skia::SkColorToDeviceNSColor(initial_color)];
- [listener showColorPanel];
- std::move(callback).Run();
- }
- void ColorPanelBridge::SetSelectedColor(uint32_t color,
- SetSelectedColorCallback callback) {
- ColorPanelListener* listener = [ColorPanelListener instance];
- [listener setColor:skia::SkColorToDeviceNSColor(color)];
- std::move(callback).Run();
- }
- } // namespace remote_cocoa
|