electron/shell/browser/ui/win/notify_icon.cc

257 lines
7.7 KiB
C++
Raw Normal View History

// Copyright (c) 2014 GitHub, Inc.
2014-06-03 03:25:09 +00:00
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/browser/ui/win/notify_icon.h"
2014-06-03 03:25:09 +00:00
#include <objbase.h>
chore: bump chromium to 6d130075d378a64187360ba4e7820 (master) (#24256) * chore: bump chromium in DEPS to 7fb9778894d73378bff51087ce869ea5aa6e5d5d * chore: bump chromium in DEPS to 83da426e53d423f0530fc23433b6d2c4d0548442 * update patches * remove chromeos-only TtsControllerDelegate Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2255314 * SharedUserScriptMaster -> SharedUserScriptManager Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2258357 * avoid deprecated DISALLOW_COPY_AND_ASSIGN https://groups.google.com/a/chromium.org/forum/#!msg/cxx/qwH2hxaEjac/TUKq6eqfCwAJ * chore: bump chromium in DEPS to b2eaf9ff4e6b03267bf279583ea20ceb2b25e9d0 * update patches * rename GetHighContrastColorScheme -> GetPlatformHighContrastColorScheme Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2250224 * remove vulkan info collection Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2252818 * add max_xcode_version build var Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2264867 * add missing headers * chore: bump chromium in DEPS to cded18ca1138f7e8efc904f077ddcca34f0135cf * update patches * add empty floc blocklist to BrowserProcessImpl Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2240873 * chore: bump chromium in DEPS to f06602226cd80bf677b2ce013a94a2fb7f6ac58d * chore: bump chromium in DEPS to 747aa4bfc74fc6cf7f08ee72624cd69ae41ae28d * chore: bump chromium in DEPS to 31c0105e50fcc4e94de33e5c8602c755ace4a32b * chore: update patches * Reland "[base] Stop including check.h, notreached.h, etc. in logging.h" https://chromium-review.googlesource.com/c/chromium/src/+/2264297 * X11 and Ozone: make sure gfx::AcceleratedWidget to be uint32_t https://chromium-review.googlesource.com/c/chromium/src/+/2260554 * Move zygote from //services/service_manager back to //content https://chromium-review.googlesource.com/c/chromium/src/+/2252466 * chore: update v8 patches * [XProto] Remove usage of Shape extension https://chromium-review.googlesource.com/c/chromium/src/+/2262113 * fixup! add empty floc blocklist to BrowserProcessImpl * Require macOS 10.15.1 sdk https://chromium-review.googlesource.com/c/chromium/src/+/2238504 * Use newer Xcode version 11.5.0 * update src cache * chore: bump chromium in DEPS to 60a9883e35db3f6f91916f0878e88e1849c17b11 * chore: update patches * Reland "Reland "New toolchain for Windows 10 19041 SDK"" https://chromium-review.googlesource.com/c/chromium/src/+/2255527 * update patches * Convert raw NonClientFrameViews to unique_ptrs https://chromium-review.googlesource.com/c/chromium/src/+/2240417 * [printing] Move PrintHostMsg_DidPreviewDocument_Params to print.mojom https://chromium-review.googlesource.com/c/chromium/src/+/2257035 * chore: bump chromium in DEPS to 12c233c2a85bfa28fb279f390121ba681e52a71b * chore: update patches * Removing oppressive language for the directory chrome/browser/apps https://chromium-review.googlesource.com/c/chromium/src/+/2269822 * Inclusion: rename SpellcheckLanguageBlacklistPolicyHandler https://chromium-review.googlesource.com/c/chromium/src/+/2267646 * Clean up duplicate WebContents "is fullscreen" functions https://chromium-review.googlesource.com/c/chromium/src/+/2275148 * Adds icon loading service with sandbox for Windows. https://chromium-review.googlesource.com/c/chromium/src/+/1987273 * No more Vulkan info collection for UMA on Windows https://chromium-review.googlesource.com/c/chromium/src/+/2252818 * fix lint * chore: update buildflag conditions * chore: bump chromium in DEPS to a837d4c4230ace4f10b2768728f4044b7995dfa5 * update hunspell files * chore: update patches * Make content::FileSelectListener a RefCounted https://chromium-review.googlesource.com/c/chromium/src/+/2275338 * fix build failures on MAS * update patches * fixup! Reland "[base] Stop including check.h, notreached.h, etc. in logging.h" * fix build on windows * Check for GDI exhaustion if window creation fails https://chromium-review.googlesource.com/c/chromium/src/+/2244124 * chore: bump chromium in DEPS to 2c9b2a73be4ef9ec22d8b6da8e174cb80753f125 * chore: update patches * Network Service: Move DeleteCookiePredicate into public folder https://chromium-review.googlesource.com/c/chromium/src/+/2264186 * chore: bump chromium in DEPS to fa2606299bcc02c362528d26b5dcf8c8a0db0735 * chore: bump chromium in DEPS to d9c235d1227204dbae3708daae851573a3566b94 * chore: bump chromium in DEPS to 2f82c284243c035f49a747fd1ead6c44b4b31093 * chore: update patches * Move creating the LayerTreeSettings into blink. https://chromium-review.googlesource.com/c/chromium/src/+/2267720 * chore: bump chromium in DEPS to 914112f1d9af9e4974059dc403da62699a55550f * update patches * chore: bump chromium in DEPS to e0bc1ffae6393fc543a2da94c88167df75859b36 * refactor: match upstream print preview handling (#24452) * update patches * chore: bump chromium in DEPS to 0881423156abe084164b51ab58ce93a8bd380524 * update patches * update patches * give a type to pendingPromise * chore: bump chromium in DEPS to 11a8c1534b16d130075d378a64187360ba4e7820 * update patches * 2272609: Move //services/service_manager/sandbox to //sandbox/policy. https://chromium-review.googlesource.com/c/chromium/src/+/2272609 * update patches * fixup! 2272609: Move //services/service_manager/sandbox to //sandbox/policy. * fixup! 2272609: Move //services/service_manager/sandbox to //sandbox/policy. * 2264511: Cookies: Update SetCanonicalCookie to return CookieAccessResult https://chromium-review.googlesource.com/c/chromium/src/+/2264511 * chore: fix setAlwaysOnTop test The window must be visible for state to be updated properly. * Revert "Migrate modules/desktop_capture and modules/video_capture to webrtc::Mutex." https://webrtc-review.googlesource.com/c/src/+/179080 * update patches Co-authored-by: Andy Locascio <andy@slack-corp.com> Co-authored-by: deepak1556 <hop2deep@gmail.com> Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com> Co-authored-by: John Kleinschmidt <jkleinsc@github.com> Co-authored-by: Electron Bot <anonymous@electronjs.org> Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> Co-authored-by: Jeremy Rose <nornagon@nornagon.net> Co-authored-by: Samuel Attard <marshallofsound@electronjs.org>
2020-07-14 01:13:34 +00:00
#include "base/logging.h"
2014-06-03 03:25:09 +00:00
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util_win.h"
2014-06-03 03:25:09 +00:00
#include "base/strings/utf_string_conversions.h"
#include "base/win/windows_version.h"
#include "shell/browser/ui/win/notify_icon_host.h"
2014-06-03 03:25:09 +00:00
#include "third_party/skia/include/core/SkBitmap.h"
2016-07-04 06:08:55 +00:00
#include "ui/display/screen.h"
2016-07-05 00:31:29 +00:00
#include "ui/display/win/screen_win.h"
2016-08-26 22:30:02 +00:00
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/image/image.h"
2014-07-11 11:42:53 +00:00
#include "ui/views/controls/menu/menu_runner.h"
2014-06-03 03:25:09 +00:00
namespace {
UINT ConvertIconType(electron::TrayIcon::IconType type) {
using IconType = electron::TrayIcon::IconType;
switch (type) {
case IconType::kNone:
return NIIF_NONE;
case IconType::kInfo:
return NIIF_INFO;
case IconType::kWarning:
return NIIF_WARNING;
case IconType::kError:
return NIIF_ERROR;
case IconType::kCustom:
return NIIF_USER;
default:
NOTREACHED() << "Invalid icon type";
}
}
} // namespace
namespace electron {
2014-06-03 03:25:09 +00:00
NotifyIcon::NotifyIcon(NotifyIconHost* host,
UINT id,
HWND window,
UINT message,
GUID guid)
: host_(host), icon_id_(id), window_(window), message_id_(message) {
guid_ = guid;
is_using_guid_ = guid != GUID_DEFAULT;
2014-06-03 03:25:09 +00:00
NOTIFYICONDATA icon_data;
InitIconData(&icon_data);
2015-07-24 15:02:14 +00:00
icon_data.uFlags |= NIF_MESSAGE;
2014-06-03 03:25:09 +00:00
icon_data.uCallbackMessage = message_id_;
BOOL result = Shell_NotifyIcon(NIM_ADD, &icon_data);
// This can happen if the explorer process isn't running when we try to
// create the icon for some reason (for example, at startup).
if (!result)
LOG(WARNING) << "Unable to create status tray icon.";
}
NotifyIcon::~NotifyIcon() {
// Remove our icon.
host_->Remove(this);
NOTIFYICONDATA icon_data;
InitIconData(&icon_data);
Shell_NotifyIcon(NIM_DELETE, &icon_data);
}
2015-12-02 11:58:10 +00:00
void NotifyIcon::HandleClickEvent(int modifiers,
2015-07-29 04:36:01 +00:00
bool left_mouse_click,
bool double_button_click) {
2016-06-21 06:49:22 +00:00
gfx::Rect bounds = GetBounds();
2014-06-03 03:25:09 +00:00
if (left_mouse_click) {
2015-07-29 04:36:01 +00:00
if (double_button_click) // double left click
2016-06-21 06:49:22 +00:00
NotifyDoubleClicked(bounds, modifiers);
2015-07-29 04:36:01 +00:00
else // single left click
2017-10-05 02:51:41 +00:00
NotifyClicked(bounds,
display::Screen::GetScreen()->GetCursorScreenPoint(),
modifiers);
2014-06-03 03:25:09 +00:00
return;
2015-07-29 04:36:01 +00:00
} else if (!double_button_click) { // single right click
if (menu_model_)
2015-12-02 11:58:10 +00:00
PopUpContextMenu(gfx::Point(), menu_model_);
else
2016-06-21 06:49:22 +00:00
NotifyRightClicked(bounds, modifiers);
2014-06-03 03:25:09 +00:00
}
}
void NotifyIcon::HandleMouseMoveEvent(int modifiers) {
gfx::Point cursorPos = display::Screen::GetScreen()->GetCursorScreenPoint();
// Omit event fired when tray icon is created but cursor is outside of it.
if (GetBounds().Contains(cursorPos))
NotifyMouseMoved(cursorPos, modifiers);
}
2014-06-03 03:25:09 +00:00
void NotifyIcon::ResetIcon() {
NOTIFYICONDATA icon_data;
InitIconData(&icon_data);
// Delete any previously existing icon.
Shell_NotifyIcon(NIM_DELETE, &icon_data);
InitIconData(&icon_data);
2015-07-24 15:02:14 +00:00
icon_data.uFlags |= NIF_MESSAGE;
2014-06-03 03:25:09 +00:00
icon_data.uCallbackMessage = message_id_;
2016-05-20 13:28:07 +00:00
icon_data.hIcon = icon_.get();
2014-06-03 03:25:09 +00:00
// If we have an image, then set the NIF_ICON flag, which tells
// Shell_NotifyIcon() to set the image for the status icon it creates.
if (icon_data.hIcon)
icon_data.uFlags |= NIF_ICON;
// Re-add our icon.
BOOL result = Shell_NotifyIcon(NIM_ADD, &icon_data);
if (!result)
LOG(WARNING) << "Unable to re-create status tray icon.";
}
2016-05-20 07:55:22 +00:00
void NotifyIcon::SetImage(HICON image) {
2016-05-20 13:28:07 +00:00
icon_ = base::win::ScopedHICON(CopyIcon(image));
2014-06-03 03:25:09 +00:00
// Create the icon.
NOTIFYICONDATA icon_data;
InitIconData(&icon_data);
2015-07-24 15:02:14 +00:00
icon_data.uFlags |= NIF_ICON;
2016-05-20 07:55:22 +00:00
icon_data.hIcon = image;
2014-06-03 03:25:09 +00:00
BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
if (!result)
LOG(WARNING) << "Error setting status tray icon image";
}
2016-05-20 07:55:22 +00:00
void NotifyIcon::SetPressedImage(HICON image) {
2014-06-03 03:25:09 +00:00
// Ignore pressed images, since the standard on Windows is to not highlight
// pressed status icons.
}
void NotifyIcon::SetToolTip(const std::string& tool_tip) {
// Create the icon.
NOTIFYICONDATA icon_data;
InitIconData(&icon_data);
2015-07-24 15:02:14 +00:00
icon_data.uFlags |= NIF_TIP;
wcsncpy_s(icon_data.szTip, base::UTF8ToWide(tool_tip).c_str(), _TRUNCATE);
2014-06-03 03:25:09 +00:00
BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
if (!result)
LOG(WARNING) << "Unable to set tooltip for status tray icon";
}
void NotifyIcon::DisplayBalloon(const BalloonOptions& options) {
2014-11-28 10:30:43 +00:00
NOTIFYICONDATA icon_data;
InitIconData(&icon_data);
2015-07-24 15:02:14 +00:00
icon_data.uFlags |= NIF_INFO;
wcsncpy_s(icon_data.szInfoTitle, base::as_wcstr(options.title), _TRUNCATE);
wcsncpy_s(icon_data.szInfo, base::as_wcstr(options.content), _TRUNCATE);
2014-11-28 10:30:43 +00:00
icon_data.uTimeout = 0;
icon_data.hBalloonIcon = options.icon;
icon_data.dwInfoFlags = ConvertIconType(options.icon_type);
if (options.large_icon)
icon_data.dwInfoFlags |= NIIF_LARGE_ICON;
if (options.no_sound)
icon_data.dwInfoFlags |= NIIF_NOSOUND;
if (options.respect_quiet_time)
icon_data.dwInfoFlags |= NIIF_RESPECT_QUIET_TIME;
2014-11-28 10:30:43 +00:00
BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
if (!result)
LOG(WARNING) << "Unable to create status tray balloon.";
}
void NotifyIcon::RemoveBalloon() {
NOTIFYICONDATA icon_data;
InitIconData(&icon_data);
icon_data.uFlags |= NIF_INFO;
BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
if (!result)
LOG(WARNING) << "Unable to remove status tray balloon.";
}
2019-08-09 14:43:48 +00:00
void NotifyIcon::Focus() {
NOTIFYICONDATA icon_data;
InitIconData(&icon_data);
BOOL result = Shell_NotifyIcon(NIM_SETFOCUS, &icon_data);
if (!result)
LOG(WARNING) << "Unable to focus tray icon.";
}
void NotifyIcon::PopUpContextMenu(const gfx::Point& pos,
ElectronMenuModel* menu_model) {
// Returns if context menu isn't set.
2016-06-28 22:28:27 +00:00
if (menu_model == nullptr && menu_model_ == nullptr)
return;
// Set our window as the foreground window, so the context menu closes when
// we click away from it.
if (!SetForegroundWindow(window_))
return;
// Cancel current menu if there is one.
CloseContextMenu();
2015-12-02 11:58:10 +00:00
// Show menu at mouse's position by default.
gfx::Rect rect(pos, gfx::Size());
if (pos.IsOrigin())
2016-07-04 06:08:55 +00:00
rect.set_origin(display::Screen::GetScreen()->GetCursorScreenPoint());
2015-12-02 11:58:10 +00:00
menu_runner_ = std::make_unique<views::MenuRunner>(
menu_model != nullptr ? menu_model : menu_model_,
views::MenuRunner::HAS_MNEMONICS);
menu_runner_->RunMenuAt(nullptr, nullptr, rect,
chore: bump chromium to 1e9f9a24aa12 (master) (#17880) * chore: bump chromium in DEPS to 1e9f9a24aa12bea9cf194a82a7e249bd1242ec4f * chore: update patches * Make WebContents' theme color a base::Optional<SkColor> https://chromium-review.googlesource.com/c/chromium/src/+/1540022 * update autofill patch for incorrect header includes * Move Shell messages to web_test and rename to BlinkTest. https://chromium-review.googlesource.com/c/chromium/src/+/1525181 * Make PlatformNotificationServiceImpl a KeyedService. https://chromium-review.googlesource.com/c/chromium/src/+/1336150 * Move MediaPlayerId to its own file. https://chromium-review.googlesource.com/c/chromium/src/+/1547057 * Remove net/base/completion_callback.h, which is no longer used https://chromium-review.googlesource.com/c/chromium/src/+/1552821 * AW NS: support file scheme cookies https://chromium-review.googlesource.com/c/chromium/src/+/1533486 * Remove SecurityInfo and adapt remaining consumers https://chromium-review.googlesource.com/c/chromium/src/+/1509455 * Remove deprecated type-specific number to string conversion functions https://chromium-review.googlesource.com/c/chromium/src/+/1545881 * DevTools: Adding new performance histograms for launch of top 4 tools https://chromium-review.googlesource.com/c/chromium/src/+/1506388 * Update include paths for //base/hash/hash.h https://chromium-review.googlesource.com/c/chromium/src/+/1544630 * build: Disable ensure_gn_version gclient hook for mac CI checkout * update patches * use maybe version of v8::String::NewFromTwoByte * bump appveyor image version * fix mac ci hopefully * Convert enum to enum class for MenuAnchorPosition https://chromium-review.googlesource.com/c/chromium/src/+/1530508 * use maybe version of ToObject * RenderViewHost::GetProcess is no longer const * Unrefcount AuthChallengeInfo https://chromium-review.googlesource.com/c/chromium/src/+/1550631 * MenuButtonController takes Button rather than MenuButton https://chromium-review.googlesource.com/c/chromium/src/+/1500935 * add //ui/views_bridge_mac to deps to fix link error * forward declare views::Button in atom::MenuDelegate * more v8 patches * base/{=> hash}/md5.h https://chromium-review.googlesource.com/c/chromium/src/+/1535124 * gfx::{PlatformFontWin => win}::* https://chromium-review.googlesource.com/c/chromium/src/+/1534178 * fix v8 patches * [base] Rename TaskScheduler to ThreadPool https://chromium-review.googlesource.com/c/chromium/src/+/1561552 * use internal_config_base for bytecode_builtins_list_generator avoids windows link errors * FIXME: temporarily disable v8/breakpad integration * FIXME: temporarily disable prevent-will-redirect test * FIXME: disable neon on aarch64 pending crbug.com/953815 * update to account for WebCursor refactor https://chromium-review.googlesource.com/c/chromium/src/+/1562755 * enable stack dumping on appveyor * Revert "FIXME: disable neon on aarch64 pending crbug.com/953815" This reverts commit 57f082026be3d83069f2a2814684abf4dc9e7b53. * fix: remove const qualifiers to match upstream * fix: remove const qualifiers to match upstream in cc files as well * don't throw an error when testing if an object is an object * use non-deprecated Buffer constructor * Remove net::CookieSameSite::DEFAULT_MODE enum value https://chromium-review.googlesource.com/c/chromium/src/+/1567955 * depend on modded dbus-native to work around buffer deprecation https://github.com/sidorares/dbus-native/pull/262 * revert clang roll to fix arm build on linux * fixup! depend on modded dbus-native to work around buffer deprecation need more coffee * update coffee-script * robustify verify-mksnapshot w.r.t. command-line parameters * Revert "robustify verify-mksnapshot w.r.t. command-line parameters" This reverts commit a49af01411f684f6025528d604895c3696e0bc57. * fix mksnapshot by matching args * update patches * TMP: enable rdp on appveyor * Changed ContentBrowserClient::CreateQuotaPermissionContext() to return scoped_refptr. https://chromium-review.googlesource.com/c/chromium/src/+/1569376 * Make content::ResourceType an enum class. https://chromium-review.googlesource.com/c/chromium/src/+/1569345 * fixup! Make content::ResourceType an enum class. * turn off rdp * use net::CompletionRepeatingCallback instead of base::Callback<void(int)> * remove disable_ensure_gn_version_gclient_hook.patch * copy repeating callback instead of std::move * fix lint * add completion_repeating_callback.h include
2019-04-20 17:20:37 +00:00
views::MenuAnchorPosition::kTopLeft,
2018-04-18 01:55:30 +00:00
ui::MENU_SOURCE_MOUSE);
}
void NotifyIcon::CloseContextMenu() {
if (menu_runner_ && menu_runner_->IsRunning()) {
menu_runner_->Cancel();
}
}
void NotifyIcon::SetContextMenu(ElectronMenuModel* menu_model) {
menu_model_ = menu_model;
2014-06-03 03:25:09 +00:00
}
2016-06-21 06:49:22 +00:00
gfx::Rect NotifyIcon::GetBounds() {
NOTIFYICONIDENTIFIER icon_id;
memset(&icon_id, 0, sizeof(NOTIFYICONIDENTIFIER));
icon_id.uID = icon_id_;
icon_id.hWnd = window_;
icon_id.cbSize = sizeof(NOTIFYICONIDENTIFIER);
if (is_using_guid_) {
icon_id.guidItem = guid_;
}
2016-06-21 06:49:22 +00:00
2018-04-18 01:55:30 +00:00
RECT rect = {0};
2016-06-21 06:49:22 +00:00
Shell_NotifyIconGetRect(&icon_id, &rect);
2016-07-05 00:31:29 +00:00
return display::win::ScreenWin::ScreenToDIPRect(window_, gfx::Rect(rect));
2016-06-21 06:49:22 +00:00
}
2014-06-03 03:25:09 +00:00
void NotifyIcon::InitIconData(NOTIFYICONDATA* icon_data) {
2014-11-28 10:59:51 +00:00
memset(icon_data, 0, sizeof(NOTIFYICONDATA));
icon_data->cbSize = sizeof(NOTIFYICONDATA);
2014-06-03 03:25:09 +00:00
icon_data->hWnd = window_;
icon_data->uID = icon_id_;
if (is_using_guid_) {
icon_data->uFlags = NIF_GUID;
icon_data->guidItem = guid_;
}
2014-06-03 03:25:09 +00:00
}
} // namespace electron