mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
* chore: bump chromium in DEPS to 142.0.7401.0
* 6911185: Reland "Send touch moves async immediately after scroll starts."
https://chromium-review.googlesource.com/c/chromium/src/+/6911185
* 6906887: mac: click through content area in main window
https://chromium-review.googlesource.com/c/chromium/src/+/6906887
* 6916667: Expose helper to eliminate duplicate recipes.
https://chromium-review.googlesource.com/c/chromium/src/+/6916667
* 6909842: Switch LegacyRenderWidgetHostHWND from atlcrack.h to msg_util.h.
https://chromium-review.googlesource.com/c/chromium/src/+/6909842
* 6884056: Remove the SecKeychain implementation for the Keychain interface
https://chromium-review.googlesource.com/c/chromium/src/+/6884056
* 6904906: Remove `WTF::` in renderer/core/[p-x].*/
https://chromium-review.googlesource.com/c/chromium/src/+/6904906
* 6556585: [persistent_cache]: PersistentCache for CodeCache
https://chromium-review.googlesource.com/c/chromium/src/+/6556585
* 6904864: Layout: Support abort on the text placeholder layout
https://chromium-review.googlesource.com/c/chromium/src/+/6904864
* chore: fixup patch indices
* chore: bump chromium in DEPS to 142.0.7402.0
* fixup! 6556585: [persistent_cache]: PersistentCache for CodeCache
* chore: fixup patch indices
* 6905244: [api] Remove deprecated `GetIsolate`
https://chromium-review.googlesource.com/c/v8/v8/+/6905244
* 6897694: Remove NativeTheme::UserHasContrastPreference().
https://chromium-review.googlesource.com/c/chromium/src/+/6897694
* 6897477: Remove GetPlatformHighContrastColorScheme() and enum.
https://chromium-review.googlesource.com/c/chromium/src/+/6897477
* 6918198: Reland "Rename display::Screen::GetScreen() to display::Screen::Get()"
https://chromium-review.googlesource.com/c/chromium/src/+/6918198
* 6907147: [LNA] add use counter for websocket mixed-content issues
https://chromium-review.googlesource.com/c/chromium/src/+/6907147
* 6914538: Replace WTF::String with blink::String
https://chromium-review.googlesource.com/c/website/+/6914538
* 6892538: [video pip] Allow touchscreen users to toggle live caption
https://chromium-review.googlesource.com/c/chromium/src/+/6892538
* chore: fix patch
* chore: bump chromium in DEPS to 142.0.7403.0
* build: remove ninja logs
* chore: fixup patch indices
* 6920670: [PDF] Change pdf_extension_util to return dictionaries
https://chromium-review.googlesource.com/c/chromium/src/+/6920670
* 6917864: Devirtualize and inline various NativeTheme getters.
https://chromium-review.googlesource.com/c/chromium/src/+/6917864
* 6920873: [PDF] Simplify PDFDocumentHelperClient::OnSaveURL()
https://chromium-review.googlesource.com/c/chromium/src/+/6920873
* build: don't kill blink/web_tests
* 6923655: Roll libc++ from 954086abf121 to b87b2bb112f8 (4 revisions)
https://chromium-review.googlesource.com/c/chromium/src/+/6923655
* 6905242: Reland "[CSP] Clarify report-only console messages."
https://chromium-review.googlesource.com/c/chromium/src/+/6905242
* fixup! 6897694: Remove NativeTheme::UserHasContrastPreference().
* chore: bump chromium in DEPS to 142.0.7405.0
* 6910012: [LNA] Enable LNA enforcement by default
https://chromium-review.googlesource.com/c/chromium/src/+/6910012
* 6929444: Combine GetInstanceForXXX() implementations.
https://chromium-review.googlesource.com/c/chromium/src/+/6929444
* 6927873: Rename native_widget_types.h -> native_ui_types.h
https://chromium-review.googlesource.com/c/chromium/src/+/6927873
* 6853978: Init perfetto really early in WebView
https://chromium-review.googlesource.com/c/chromium/src/+/6853978
* 6874886: Use only one picker observer to avoid getting duplicate notifications
https://chromium-review.googlesource.com/c/chromium/src/+/6874886
* chore: fixup patch indices
* fix: Protocol complex inline dtor
* chore: bump chromium in DEPS to 142.0.7407.0
* chore: bump chromium in DEPS to 142.0.7409.0
* chore: bump chromium in DEPS to 142.0.7411.0
* chore: bump chromium in DEPS to 142.0.7413.0
* fixup! 6905242: Reland "[CSP] Clarify report-only console messages."
* 6927233: Remove NativeTheme "use dark colors" bit.
https://chromium-review.googlesource.com/c/chromium/src/+/6927233
* chore: fixup patch indices
* 6899206: [PermissionOptions] Multi-state permission subscriptions & setting changes
https://chromium-review.googlesource.com/c/chromium/src/+/6899206
* chore: bump chromium in DEPS to 142.0.7415.0
* 6936895: [headless] Remove headless flag from views::Widget class
https://chromium-review.googlesource.com/c/chromium/src/+/6936895
We should probably followup on this to see if there is a way to do this without reverting this CL.
* 6937023: Reland "Use new DBus type system in dbus_xdg::Request"
https://chromium-review.googlesource.com/c/chromium/src/+/6937023
* chore: update patches
* 6944749: Add GN visibility list to //components/os_crypt/sync
https://chromium-review.googlesource.com/c/chromium/src/+/6944749
* Further replace sub_capture_target_version with CaptureVersion
https://chromium-review.googlesource.com/c/chromium/src/+/6935455
* fixup for lint
* chore: update filenames.libcxx.gni
* chore: bump chromium in DEPS to 142.0.7417.0
* 6944136: Reorder NativeTheme headers/.cc files.
Refs https://chromium-review.googlesource.com/c/chromium/src/+/6944136
* 6939701: [DSSC][4] Make FSVCI objects aware of their capture-version-source
Refs https://chromium-review.googlesource.com/c/chromium/src/+/6939701
* 6944404: Remove extraneous callback call
Refs https://chromium-review.googlesource.com/c/chromium/src/+/6944404
* 6936124: [FPF-CI]: Introduce blink::NoiseToken for fingerprinting protection
Refs https://chromium-review.googlesource.com/c/chromium/src/+/6936124
* chore: update patches
* fixup! 6927233: Remove NativeTheme "use dark colors" bit.
Refs https://chromium-review.googlesource.com/c/chromium/src/+/6927233
* fixup! 6917864: Devirtualize and inline various NativeTheme getters.
Refs https://chromium-review.googlesource.com/c/chromium/src/+/6917864
* 6937588: Add initial OsSettingsProvider object, supplying caret blink interval.
Refs https://chromium-review.googlesource.com/c/chromium/src/+/6937588
* fixup! 6905242: Reland "[CSP] Clarify report-only console messages."
Refs https://chromium-review.googlesource.com/c/chromium/src/+/6905242
* 6907515: Replace SingletonHwndObserver with a CallbackList on SingletonHwnd.
Refs https://chromium-review.googlesource.com/c/chromium/src/+/6907515
* 6910482: [Save to Drive] Implement retry functionality
Refs https://chromium-review.googlesource.com/c/chromium/src/+/6910482
* fixup! 6927233: Remove NativeTheme "use dark colors" bit.
Refs https://chromium-review.googlesource.com/c/chromium/src/+/6927233
* Revert "build: remove ninja logs"
This reverts commit 72874740fd.
* test: fix flakey test picked from PR 48205
---------
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
Co-authored-by: Alice Zhao <alicelovescake@anthropic.com>
279 lines
8.6 KiB
C++
279 lines
8.6 KiB
C++
// Copyright (c) 2014 GitHub, Inc.
|
|
// 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"
|
|
|
|
#include <objbase.h>
|
|
|
|
#include "base/containers/span.h"
|
|
#include "base/logging.h"
|
|
#include "base/strings/string_util_win.h"
|
|
#include "base/strings/utf_string_conversions.h"
|
|
#include "shell/browser/ui/win/notify_icon_host.h"
|
|
#include "ui/base/mojom/menu_source_type.mojom.h"
|
|
#include "ui/display/screen.h"
|
|
#include "ui/display/win/screen_win.h"
|
|
#include "ui/gfx/geometry/point.h"
|
|
#include "ui/gfx/geometry/rect.h"
|
|
#include "ui/views/controls/menu/menu_runner.h"
|
|
|
|
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 {
|
|
|
|
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;
|
|
NOTIFYICONDATA icon_data = InitIconData();
|
|
icon_data.uFlags |= NIF_MESSAGE;
|
|
icon_data.uCallbackMessage = message_id_;
|
|
const 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();
|
|
Shell_NotifyIcon(NIM_DELETE, &icon_data);
|
|
}
|
|
|
|
void NotifyIcon::HandleClickEvent(int modifiers,
|
|
bool left_mouse_click,
|
|
bool double_button_click,
|
|
bool middle_button_click) {
|
|
gfx::Rect bounds = GetBounds();
|
|
|
|
if (left_mouse_click) {
|
|
if (double_button_click) // double left click
|
|
NotifyDoubleClicked(bounds, modifiers);
|
|
else // single left click
|
|
NotifyClicked(bounds, display::Screen::Get()->GetCursorScreenPoint(),
|
|
modifiers);
|
|
return;
|
|
} else if (middle_button_click) { // single middle click
|
|
NotifyMiddleClicked(bounds, modifiers);
|
|
} else if (!double_button_click) { // single right click
|
|
if (menu_model_)
|
|
PopUpContextMenu(gfx::Point(), menu_model_->GetWeakPtr());
|
|
else
|
|
NotifyRightClicked(bounds, modifiers);
|
|
}
|
|
}
|
|
|
|
void NotifyIcon::HandleMouseMoveEvent(int modifiers) {
|
|
gfx::Point cursorPos = display::Screen::Get()->GetCursorScreenPoint();
|
|
// Omit event fired when tray icon is created but cursor is outside of it.
|
|
if (GetBounds().Contains(cursorPos))
|
|
NotifyMouseMoved(cursorPos, modifiers);
|
|
}
|
|
|
|
void NotifyIcon::HandleMouseEntered(int modifiers) {
|
|
gfx::Point cursor_pos = display::Screen::Get()->GetCursorScreenPoint();
|
|
NotifyMouseEntered(cursor_pos, modifiers);
|
|
}
|
|
|
|
void NotifyIcon::HandleMouseExited(int modifiers) {
|
|
gfx::Point cursor_pos = display::Screen::Get()->GetCursorScreenPoint();
|
|
NotifyMouseExited(cursor_pos, modifiers);
|
|
}
|
|
|
|
void NotifyIcon::ResetIcon() {
|
|
// Delete any previously existing icon.
|
|
NOTIFYICONDATA icon_data = InitIconData();
|
|
Shell_NotifyIcon(NIM_DELETE, &icon_data);
|
|
|
|
// Update the icon.
|
|
icon_data = InitIconData();
|
|
icon_data.uFlags |= NIF_MESSAGE;
|
|
icon_data.uCallbackMessage = message_id_;
|
|
icon_data.hIcon = icon_.get();
|
|
// 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.";
|
|
}
|
|
|
|
void NotifyIcon::SetImage(HICON image) {
|
|
icon_ = base::win::ScopedGDIObject<HICON>(CopyIcon(image));
|
|
|
|
// Create the icon.
|
|
NOTIFYICONDATA icon_data = InitIconData();
|
|
icon_data.uFlags |= NIF_ICON;
|
|
icon_data.hIcon = image;
|
|
BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
|
|
if (!result)
|
|
LOG(WARNING) << "Error setting status tray icon image";
|
|
}
|
|
|
|
void NotifyIcon::SetPressedImage(HICON image) {
|
|
// Ignore pressed images, since the standard on Windows is to not highlight
|
|
// pressed status icons.
|
|
}
|
|
|
|
template <typename CharT, size_t N>
|
|
static void CopyStringToBuf(CharT (&tgt_buf)[N],
|
|
const std::basic_string<CharT> src_str) {
|
|
if constexpr (N < 1U)
|
|
return;
|
|
|
|
const auto src = base::span{src_str};
|
|
const auto n_chars = std::min(src.size(), N - 1U);
|
|
auto tgt = base::span{tgt_buf};
|
|
tgt.first(n_chars).copy_from(src.first(n_chars));
|
|
tgt[n_chars] = CharT{}; // zero-terminate the string
|
|
}
|
|
|
|
void NotifyIcon::SetToolTip(const std::string& tool_tip) {
|
|
// Create the icon.
|
|
NOTIFYICONDATA icon_data = InitIconData();
|
|
icon_data.uFlags |= NIF_TIP;
|
|
CopyStringToBuf(icon_data.szTip, base::UTF8ToWide(tool_tip));
|
|
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) {
|
|
NOTIFYICONDATA icon_data = InitIconData();
|
|
icon_data.uFlags |= NIF_INFO;
|
|
CopyStringToBuf(icon_data.szInfoTitle, base::AsWString(options.title));
|
|
CopyStringToBuf(icon_data.szInfo, base::AsWString(options.content));
|
|
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;
|
|
|
|
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.uFlags |= NIF_INFO;
|
|
|
|
BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
|
|
if (!result)
|
|
LOG(WARNING) << "Unable to remove status tray balloon.";
|
|
}
|
|
|
|
void NotifyIcon::Focus() {
|
|
NOTIFYICONDATA icon_data = InitIconData();
|
|
|
|
BOOL result = Shell_NotifyIcon(NIM_SETFOCUS, &icon_data);
|
|
if (!result)
|
|
LOG(WARNING) << "Unable to focus tray icon.";
|
|
}
|
|
|
|
void NotifyIcon::PopUpContextMenu(const gfx::Point& pos,
|
|
base::WeakPtr<ElectronMenuModel> menu_model) {
|
|
// Returns if context menu isn't set.
|
|
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();
|
|
|
|
// Show menu at mouse's position by default.
|
|
gfx::Rect rect(pos, gfx::Size());
|
|
if (pos.IsOrigin())
|
|
rect.set_origin(display::Screen::Get()->GetCursorScreenPoint());
|
|
|
|
if (menu_model) {
|
|
menu_runner_ = std::make_unique<views::MenuRunner>(
|
|
menu_model.get(), views::MenuRunner::HAS_MNEMONICS);
|
|
} else {
|
|
menu_runner_ = std::make_unique<views::MenuRunner>(
|
|
menu_model_, views::MenuRunner::HAS_MNEMONICS);
|
|
}
|
|
menu_runner_->RunMenuAt(nullptr, nullptr, rect,
|
|
views::MenuAnchorPosition::kTopLeft,
|
|
ui::mojom::MenuSourceType::kMouse);
|
|
}
|
|
|
|
void NotifyIcon::CloseContextMenu() {
|
|
if (menu_runner_ && menu_runner_->IsRunning()) {
|
|
menu_runner_->Cancel();
|
|
}
|
|
}
|
|
|
|
void NotifyIcon::SetContextMenu(raw_ptr<ElectronMenuModel> menu_model) {
|
|
menu_model_ = menu_model;
|
|
}
|
|
|
|
gfx::Rect NotifyIcon::GetBounds() {
|
|
NOTIFYICONIDENTIFIER icon_id = {};
|
|
icon_id.uID = icon_id_;
|
|
icon_id.hWnd = window_;
|
|
icon_id.cbSize = sizeof(NOTIFYICONIDENTIFIER);
|
|
if (is_using_guid_) {
|
|
icon_id.guidItem = guid_;
|
|
}
|
|
|
|
RECT rect = {0};
|
|
Shell_NotifyIconGetRect(&icon_id, &rect);
|
|
return display::win::GetScreenWin()->ScreenToDIPRect(window_,
|
|
gfx::Rect{rect});
|
|
}
|
|
|
|
NOTIFYICONDATA NotifyIcon::InitIconData() const {
|
|
NOTIFYICONDATA icon_data = {};
|
|
icon_data.cbSize = sizeof(NOTIFYICONDATA);
|
|
icon_data.hWnd = window_;
|
|
icon_data.uID = icon_id_;
|
|
if (is_using_guid_) {
|
|
icon_data.uFlags = NIF_GUID;
|
|
icon_data.guidItem = guid_;
|
|
}
|
|
return icon_data;
|
|
}
|
|
|
|
} // namespace electron
|