mirror of
https://github.com/zebrajr/ladybird.git
synced 2025-12-06 00:19:53 +01:00
LibCore+LibWebView+UI/Qt: Support TimeZoneWatcher on Windows
To detect system time zone changes on Windows, the event we need to look for is WM_TIMECHANGE. The problem is how the callback with said message actually gets invoked is very particular. (1) We must have an active message pump (event loop) for the message to ever be processed. (2) We must be a GUI application as WM_TIMECHANGE messages are seemingly sent to top level windows only. It doesn't say that in the docs for the event, but attempts of creating a LibTest-based application with a message pump and a message only window and never receiving the event point to that probably being true. This workaround is built off the fact that Qt's message pump defined internally in QEventDispatcherWin32::processEvents does in fact receive WM_TIMECHANGE events, even though it is not exposed as a QEvent::Type. Given the requirements stated above it makes sense that it works here as the message pump is executing in a QGuiApplication context. So we use a native event filter to hook into the unexposed WM_TIMECHANGE event and forward it along to the on_time_zone_changed() callback. Note that if a Windows GUI framework is done in the future, we'll have to re-add support to ensure the TimeZoneWatcher still gets invoked.
This commit is contained in:
parent
ba9c8b8462
commit
f4c8fd4bef
|
|
@ -90,6 +90,12 @@ elseif (APPLE AND NOT IOS)
|
|||
Platform/ProcessStatisticsMach.cpp
|
||||
TimeZoneWatcherMacOS.mm
|
||||
)
|
||||
elseif (WIN32)
|
||||
list(APPEND SOURCES
|
||||
FileWatcherUnimplemented.cpp
|
||||
Platform/ProcessStatisticsUnimplemented.cpp
|
||||
TimeZoneWatcherWindows.cpp
|
||||
)
|
||||
else()
|
||||
list(APPEND SOURCES
|
||||
FileWatcherUnimplemented.cpp
|
||||
|
|
|
|||
32
Libraries/LibCore/TimeZoneWatcherWindows.cpp
Normal file
32
Libraries/LibCore/TimeZoneWatcherWindows.cpp
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2025, ayeteadoe <ayeteadoe@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Platform.h>
|
||||
#include <LibCore/TimeZoneWatcher.h>
|
||||
|
||||
#if !defined(AK_OS_WINDOWS)
|
||||
static_assert(false, "This file must only be used for Windows");
|
||||
#endif
|
||||
|
||||
namespace Core {
|
||||
|
||||
class TimeZoneWatcherImpl final : public TimeZoneWatcher {
|
||||
public:
|
||||
static ErrorOr<NonnullOwnPtr<TimeZoneWatcherImpl>> create()
|
||||
{
|
||||
return adopt_own(*new TimeZoneWatcherImpl());
|
||||
}
|
||||
|
||||
private:
|
||||
TimeZoneWatcherImpl() = default;
|
||||
};
|
||||
|
||||
ErrorOr<NonnullOwnPtr<TimeZoneWatcher>> TimeZoneWatcher::create()
|
||||
{
|
||||
return TimeZoneWatcherImpl::create();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -362,7 +362,7 @@ ErrorOr<void> Application::launch_services()
|
|||
} else {
|
||||
m_time_zone_watcher = time_zone_watcher.release_value();
|
||||
|
||||
m_time_zone_watcher->on_time_zone_changed = []() {
|
||||
m_time_zone_watcher->on_time_zone_changed = [] {
|
||||
WebContentClient::for_each_client([&](WebView::WebContentClient& client) {
|
||||
client.async_system_time_zone_changed();
|
||||
return IterationDecision::Continue;
|
||||
|
|
@ -874,6 +874,13 @@ void Application::refresh_tab_list()
|
|||
m_devtools->refresh_tab_list();
|
||||
}
|
||||
|
||||
Optional<Core::TimeZoneWatcher&> Application::time_zone_watcher()
|
||||
{
|
||||
if (m_time_zone_watcher != nullptr)
|
||||
return *m_time_zone_watcher;
|
||||
return {};
|
||||
}
|
||||
|
||||
Vector<DevTools::TabDescription> Application::tab_list() const
|
||||
{
|
||||
Vector<DevTools::TabDescription> tabs;
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ public:
|
|||
ErrorOr<void> toggle_devtools_enabled();
|
||||
void refresh_tab_list();
|
||||
|
||||
Optional<Core::TimeZoneWatcher&> time_zone_watcher();
|
||||
|
||||
protected:
|
||||
explicit Application(Optional<ByteString> ladybird_binary_path = {});
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,39 @@
|
|||
#include <QMessageBox>
|
||||
#include <QMimeData>
|
||||
|
||||
#if defined(AK_OS_WINDOWS)
|
||||
# include <AK/Windows.h>
|
||||
# include <LibCore/TimeZoneWatcher.h>
|
||||
# include <QAbstractNativeEventFilter>
|
||||
#endif
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
#if defined(AK_OS_WINDOWS)
|
||||
class NativeWindowsTimeChangeEventFilter : public QAbstractNativeEventFilter {
|
||||
public:
|
||||
NativeWindowsTimeChangeEventFilter(Core::TimeZoneWatcher& time_zone_watcher)
|
||||
: m_time_zone_watcher(time_zone_watcher)
|
||||
{
|
||||
}
|
||||
|
||||
bool nativeEventFilter(QByteArray const& event_type, void* message, qintptr*) override
|
||||
{
|
||||
if (event_type == QByteArrayLiteral("windows_generic_MSG")) {
|
||||
auto msg = static_cast<MSG*>(message);
|
||||
if (msg->message == WM_TIMECHANGE) {
|
||||
m_time_zone_watcher.on_time_zone_changed();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
Core::TimeZoneWatcher& m_time_zone_watcher;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
class LadybirdQApplication : public QApplication {
|
||||
public:
|
||||
explicit LadybirdQApplication(Main::Arguments& arguments)
|
||||
|
|
@ -31,6 +62,14 @@ public:
|
|||
{
|
||||
auto& application = static_cast<Application&>(WebView::Application::the());
|
||||
|
||||
#if defined(AK_OS_WINDOWS)
|
||||
static Optional<NativeWindowsTimeChangeEventFilter> time_change_event_filter {};
|
||||
if (auto time_zone_watcher = application.time_zone_watcher(); !time_change_event_filter.has_value() && time_zone_watcher.has_value()) {
|
||||
time_change_event_filter.emplace(time_zone_watcher.value());
|
||||
installNativeEventFilter(&time_change_event_filter.value());
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::FileOpen: {
|
||||
if (!application.on_open_file)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user