fix: honor win.setEnabled(false) and modal parents under Wayland (#54427)

On Linux, disabling a window (setEnabled(false), or opening a modal child)
only took effect under X11; under Wayland the window kept receiving input
and isEnabled() always returned true.

Replace the X11-only EventDisabler rewriter with the window tree host's
DisableEventListening(), which blocks event dispatch the same way on both
X11 and Wayland, and run the disabling specs on Wayland too.
This commit is contained in:
Shelley Vohr authored and GitHub committed 2026-09-26 20:17:17 +09:00
1 parent 783bf56ab7
commit ff6681b1ff
6 files changed
+11 -88

No files matched your search

-2
View File
@@ -63,8 +63,6 @@ filenames = {
"shell/browser/ui/views/global_menu_bar_registrar_x11.h",
"shell/browser/ui/views/global_menu_bar_x11.cc",
"shell/browser/ui/views/global_menu_bar_x11.h",
"shell/browser/ui/x/event_disabler.cc",
"shell/browser/ui/x/event_disabler.h",
"shell/browser/ui/x/x_window_utils.cc",
"shell/browser/ui/x/x_window_utils.h",
]
+7 -16
View File
@@ -76,7 +76,6 @@
#if BUILDFLAG(SUPPORTS_OZONE_X11)
#include "shell/browser/ui/views/global_menu_bar_x11.h"
#include "shell/browser/ui/x/event_disabler.h"
#include "shell/browser/ui/x/x_window_utils.h"
#include "ui/gfx/x/atom_cache.h"
#include "ui/gfx/x/connection.h"
@@ -691,10 +690,7 @@ bool NativeWindowViews::IsEnabled() const {
#if BUILDFLAG(IS_WIN)
return ::IsWindowEnabled(GetAcceleratedWidget());
#elif BUILDFLAG(IS_LINUX)
if (x11_util::IsX11())
return !event_disabler_.get();
NOTIMPLEMENTED();
return true;
return !enable_event_listening_;
#endif
}
@@ -728,17 +724,12 @@ void NativeWindowViews::SetEnabledInternal(bool enable) {
#if BUILDFLAG(IS_WIN)
::EnableWindow(GetAcceleratedWidget(), enable);
#else
if (x11_util::IsX11()) {
views::DesktopWindowTreeHostPlatform* tree_host =
views::DesktopWindowTreeHostLinux::GetHostForWidget(
GetAcceleratedWidget());
if (enable) {
tree_host->RemoveEventRewriter(event_disabler_.get());
event_disabler_.reset();
} else {
event_disabler_ = std::make_unique<EventDisabler>();
tree_host->AddEventRewriter(event_disabler_.get());
}
if (enable) {
enable_event_listening_.RunAndReset();
} else {
auto* tree_host = static_cast<views::DesktopWindowTreeHostLinux*>(
GetNativeWindow()->GetHost());
enable_event_listening_.ReplaceClosure(tree_host->DisableEventListening());
}
#endif
}
+3 -8
View File
@@ -11,6 +11,7 @@
#include <optional>
#include <string>
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/no_destructor.h"
#include "shell/browser/ui/views/root_view.h"
@@ -43,10 +44,6 @@ namespace electron {
class GlobalMenuBarX11;
#endif
#if BUILDFLAG(SUPPORTS_OZONE_X11)
class EventDisabler;
#endif
#if BUILDFLAG(IS_WIN)
gfx::Rect ScreenToDIPRect(HWND hwnd, const gfx::Rect& pixel_bounds);
#endif
@@ -297,11 +294,9 @@ class NativeWindowViews : public NativeWindow,
#if BUILDFLAG(IS_LINUX)
std::unique_ptr<GlobalMenuBarX11> global_menu_bar_;
#endif
#if BUILDFLAG(SUPPORTS_OZONE_X11)
// To disable the mouse events.
std::unique_ptr<EventDisabler> event_disabler_;
// Set while the window is disabled; running it re-enables event dispatch.
base::ScopedClosureRunner enable_event_listening_;
#endif
// The color to use as the theme and symbol colors respectively for WCO.
-27
View File
@@ -1,27 +0,0 @@
// Copyright (c) 2016 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/x/event_disabler.h"
#include <memory>
namespace electron {
EventDisabler::EventDisabler() = default;
EventDisabler::~EventDisabler() = default;
ui::EventRewriteStatus EventDisabler::RewriteEvent(
const ui::Event& event,
std::unique_ptr<ui::Event>* rewritten_event) {
return ui::EVENT_REWRITE_DISCARD;
}
ui::EventRewriteStatus EventDisabler::NextDispatchEvent(
const ui::Event& last_event,
std::unique_ptr<ui::Event>* new_event) {
return ui::EVENT_REWRITE_CONTINUE;
}
} // namespace electron
-34
View File
@@ -1,34 +0,0 @@
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ELECTRON_SHELL_BROWSER_UI_X_EVENT_DISABLER_H_
#define ELECTRON_SHELL_BROWSER_UI_X_EVENT_DISABLER_H_
#include <memory>
#include "ui/events/event_rewriter.h"
namespace electron {
class EventDisabler : public ui::EventRewriter {
public:
EventDisabler();
~EventDisabler() override;
// disable copy
EventDisabler(const EventDisabler&) = delete;
EventDisabler& operator=(const EventDisabler&) = delete;
// ui::EventRewriter:
ui::EventRewriteStatus RewriteEvent(
const ui::Event& event,
std::unique_ptr<ui::Event>* rewritten_event) override;
ui::EventRewriteStatus NextDispatchEvent(
const ui::Event& last_event,
std::unique_ptr<ui::Event>* new_event) override;
};
} // namespace electron
#endif // ELECTRON_SHELL_BROWSER_UI_X_EVENT_DISABLER_H_
+1 -1
View File
@@ -6509,7 +6509,7 @@ describe('BrowserWindow module', () => {
}
});
ifdescribe(process.platform !== 'darwin' && !isWayland)('disabling parent windows', () => {
ifdescribe(process.platform !== 'darwin')('disabling parent windows', () => {
it('can disable and enable a window', () => {
const w = new BrowserWindow({ show: false });
w.setEnabled(false);