Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJanek Bevendorff <janek@jbev.net>2020-01-28 23:42:57 +0300
committerJanek Bevendorff <janek@jbev.net>2020-03-05 11:24:11 +0300
commit6d2ca748787c71eab3adaf2071d5738ba7c28a52 (patch)
tree031a16370418f8abf0c93950b1381dd75ab3622b /src/gui/osutils
parentb9daed20558103e3c8e799f3e0575522bf823df6 (diff)
Add OSUtils for platform-specific functionality.
Moves MacUtils into a separate sub folder and adds WinUtils, NixUtils, and OSUtils for platform-native code on Windows, Unix-like, and generic/all systems.
Diffstat (limited to 'src/gui/osutils')
-rw-r--r--src/gui/osutils/OSUtils.h41
-rw-r--r--src/gui/osutils/OSUtilsBase.cpp27
-rw-r--r--src/gui/osutils/OSUtilsBase.h40
-rw-r--r--src/gui/osutils/macutils/AppKit.h50
-rw-r--r--src/gui/osutils/macutils/AppKitImpl.h42
-rw-r--r--src/gui/osutils/macutils/AppKitImpl.mm217
-rw-r--r--src/gui/osutils/macutils/MacUtils.cpp87
-rw-r--r--src/gui/osutils/macutils/MacUtils.h62
-rw-r--r--src/gui/osutils/nixutils/NixUtils.cpp50
-rw-r--r--src/gui/osutils/nixutils/NixUtils.h48
-rw-r--r--src/gui/osutils/winutils/WinUtils.cpp85
-rw-r--r--src/gui/osutils/winutils/WinUtils.h59
12 files changed, 808 insertions, 0 deletions
diff --git a/src/gui/osutils/OSUtils.h b/src/gui/osutils/OSUtils.h
new file mode 100644
index 000000000..dd1bd8cd1
--- /dev/null
+++ b/src/gui/osutils/OSUtils.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 or (at your option)
+ * version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KEEPASSXC_OSUTILS_H
+#define KEEPASSXC_OSUTILS_H
+
+#include "OSUtilsBase.h"
+#include <QtCore>
+
+#if defined(Q_OS_WIN)
+
+#include "winutils/WinUtils.h"
+#define osUtils static_cast<OSUtilsBase*>(winUtils())
+
+#elif defined(Q_OS_MACOS)
+
+#include "macutils/MacUtils.h"
+#define osUtils static_cast<OSUtilsBase*>(macUtils())
+
+#elif defined(Q_OS_UNIX)
+
+#include "nixutils/NixUtils.h"
+#define osUtils static_cast<OSUtilsBase*>(nixUtils())
+
+#endif
+
+#endif // KEEPASSXC_OSUTILS_H
diff --git a/src/gui/osutils/OSUtilsBase.cpp b/src/gui/osutils/OSUtilsBase.cpp
new file mode 100644
index 000000000..143cb72c1
--- /dev/null
+++ b/src/gui/osutils/OSUtilsBase.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 or (at your option)
+ * version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "OSUtilsBase.h"
+
+OSUtilsBase::OSUtilsBase(QObject* parent)
+ : QObject(parent)
+{
+}
+
+OSUtilsBase::~OSUtilsBase()
+{
+}
diff --git a/src/gui/osutils/OSUtilsBase.h b/src/gui/osutils/OSUtilsBase.h
new file mode 100644
index 000000000..9467fca09
--- /dev/null
+++ b/src/gui/osutils/OSUtilsBase.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 or (at your option)
+ * version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KEEPASSXC_OSUTILSBASE_H
+#define KEEPASSXC_OSUTILSBASE_H
+
+#include <QObject>
+#include <QPointer>
+
+/**
+ * Abstract base class for generic OS-specific functionality
+ * which can be reasonably expected to be available on all platforms.
+ */
+class OSUtilsBase : public QObject
+{
+ Q_OBJECT
+
+public:
+ virtual bool isDarkMode() = 0;
+
+protected:
+ explicit OSUtilsBase(QObject* parent = nullptr);
+ virtual ~OSUtilsBase();
+};
+
+#endif // KEEPASSXC_OSUTILSBASE_H
diff --git a/src/gui/osutils/macutils/AppKit.h b/src/gui/osutils/macutils/AppKit.h
new file mode 100644
index 000000000..2bff8f5b3
--- /dev/null
+++ b/src/gui/osutils/macutils/AppKit.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 Lennart Glauer <mail@lennart-glauer.de>
+ * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 or (at your option)
+ * version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KEEPASSX_APPKIT_H
+#define KEEPASSX_APPKIT_H
+
+#include <QObject>
+#include <unistd.h>
+
+class AppKit : public QObject
+{
+ Q_OBJECT
+
+public:
+ AppKit(QObject* parent = nullptr);
+ ~AppKit();
+
+ pid_t lastActiveProcessId();
+ pid_t activeProcessId();
+ pid_t ownProcessId();
+ bool activateProcess(pid_t pid);
+ bool hideProcess(pid_t pid);
+ bool isHidden(pid_t pid);
+ bool isDarkMode();
+ bool enableAccessibility();
+ bool enableScreenRecording();
+
+signals:
+ void lockDatabases();
+
+private:
+ void* self;
+};
+
+#endif // KEEPASSX_APPKIT_H
diff --git a/src/gui/osutils/macutils/AppKitImpl.h b/src/gui/osutils/macutils/AppKitImpl.h
new file mode 100644
index 000000000..326879766
--- /dev/null
+++ b/src/gui/osutils/macutils/AppKitImpl.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 Lennart Glauer <mail@lennart-glauer.de>
+ * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 or (at your option)
+ * version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#import "AppKit.h"
+
+#import <Foundation/Foundation.h>
+#import <AppKit/NSRunningApplication.h>
+
+@interface AppKitImpl : NSObject
+{
+ AppKit* m_appkit;
+}
+- (id) initWithObject:(AppKit*)appkit;
+
+@property (strong) NSRunningApplication *lastActiveApplication;
+
+- (pid_t) activeProcessId;
+- (pid_t) ownProcessId;
+- (bool) activateProcess:(pid_t) pid;
+- (bool) hideProcess:(pid_t) pid;
+- (bool) isHidden:(pid_t) pid;
+- (bool) isDarkMode;
+- (void) userSwitchHandler:(NSNotification*) notification;
+- (bool) enableAccessibility;
+- (bool) enableScreenRecording;
+
+@end
diff --git a/src/gui/osutils/macutils/AppKitImpl.mm b/src/gui/osutils/macutils/AppKitImpl.mm
new file mode 100644
index 000000000..4a93f963a
--- /dev/null
+++ b/src/gui/osutils/macutils/AppKitImpl.mm
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2016 Lennart Glauer <mail@lennart-glauer.de>
+ * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 or (at your option)
+ * version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#import "AppKitImpl.h"
+
+#import <AppKit/NSWorkspace.h>
+#import <CoreVideo/CVPixelBuffer.h>
+
+@implementation AppKitImpl
+
+- (id) initWithObject:(AppKit*)appkit
+{
+ self = [super init];
+ if (self) {
+ m_appkit = appkit;
+ [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:static_cast<id>(self)
+ selector:@selector(didDeactivateApplicationObserver:)
+ name:NSWorkspaceDidDeactivateApplicationNotification
+ object:nil];
+
+ [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:static_cast<id>(self)
+ selector:@selector(userSwitchHandler:)
+ name:NSWorkspaceSessionDidResignActiveNotification
+ object:nil];
+ }
+ return self;
+}
+
+//
+// Update last active application property
+//
+- (void) didDeactivateApplicationObserver:(NSNotification*) notification
+{
+ NSDictionary* userInfo = notification.userInfo;
+ NSRunningApplication* app = userInfo[NSWorkspaceApplicationKey];
+
+ if (app.processIdentifier != [self ownProcessId]) {
+ self.lastActiveApplication = app;
+ }
+}
+
+//
+// Get process id of frontmost application (-> keyboard input)
+//
+- (pid_t) activeProcessId
+{
+ return [NSWorkspace sharedWorkspace].frontmostApplication.processIdentifier;
+}
+
+//
+// Get process id of own process
+//
+- (pid_t) ownProcessId
+{
+ return [NSProcessInfo processInfo].processIdentifier;
+}
+
+//
+// Activate application by process id
+//
+- (bool) activateProcess:(pid_t) pid
+{
+ NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
+ return [app activateWithOptions:NSApplicationActivateIgnoringOtherApps];
+}
+
+//
+// Hide application by process id
+//
+- (bool) hideProcess:(pid_t) pid
+{
+ NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
+ return [app hide];
+}
+
+//
+// Get application hidden state by process id
+//
+- (bool) isHidden:(pid_t) pid
+{
+ NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
+ return [app isHidden];
+}
+
+//
+// Get state of macOS Dark Mode color scheme
+//
+- (bool) isDarkMode
+{
+ NSDictionary* dict = [[NSUserDefaults standardUserDefaults] persistentDomainForName:NSGlobalDomain];
+ id style = [dict objectForKey:@"AppleInterfaceStyle"];
+ return ( style && [style isKindOfClass:[NSString class]]
+ && NSOrderedSame == [style caseInsensitiveCompare:@"dark"] );
+}
+
+//
+// Notification for user switch
+//
+- (void) userSwitchHandler:(NSNotification*) notification
+{
+ if ([[notification name] isEqualToString:NSWorkspaceSessionDidResignActiveNotification] && m_appkit)
+ {
+ emit m_appkit->lockDatabases();
+ }
+}
+
+//
+// Check if accessibility is enabled, may show an popup asking for permissions
+//
+- (bool) enableAccessibility
+{
+ // Request accessibility permissions for Auto-Type type on behalf of the user
+ NSDictionary* opts = @{static_cast<id>(kAXTrustedCheckOptionPrompt): @YES};
+ return AXIsProcessTrustedWithOptions(static_cast<CFDictionaryRef>(opts));
+}
+
+//
+// Check if screen recording is enabled, may show an popup asking for permissions
+//
+- (bool) enableScreenRecording
+{
+ if (@available(macOS 10.15, *)) {
+ // Request screen recording permission on macOS 10.15+
+ // This is necessary to get the current window title
+ CGDisplayStreamRef stream = CGDisplayStreamCreate(CGMainDisplayID(), 1, 1, kCVPixelFormatType_32BGRA, nil,
+ ^(CGDisplayStreamFrameStatus status, uint64_t displayTime,
+ IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) {
+ Q_UNUSED(status);
+ Q_UNUSED(displayTime);
+ Q_UNUSED(frameSurface);
+ Q_UNUSED(updateRef);
+ });
+ if (stream) {
+ CFRelease(stream);
+ } else {
+ return NO;
+ }
+ }
+ return YES;
+}
+
+@end
+
+//
+// ------------------------- C++ Trampolines -------------------------
+//
+
+AppKit::AppKit(QObject* parent) : QObject(parent)
+{
+ self = [[AppKitImpl alloc] initWithObject:this];
+}
+
+AppKit::~AppKit()
+{
+ [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:static_cast<id>(self)];
+ [static_cast<id>(self) dealloc];
+}
+
+pid_t AppKit::lastActiveProcessId()
+{
+ return [static_cast<id>(self) lastActiveApplication].processIdentifier;
+}
+
+pid_t AppKit::activeProcessId()
+{
+ return [static_cast<id>(self) activeProcessId];
+}
+
+pid_t AppKit::ownProcessId()
+{
+ return [static_cast<id>(self) ownProcessId];
+}
+
+bool AppKit::activateProcess(pid_t pid)
+{
+ return [static_cast<id>(self) activateProcess:pid];
+}
+
+bool AppKit::hideProcess(pid_t pid)
+{
+ return [static_cast<id>(self) hideProcess:pid];
+}
+
+bool AppKit::isHidden(pid_t pid)
+{
+ return [static_cast<id>(self) isHidden:pid];
+}
+
+bool AppKit::isDarkMode()
+{
+ return [static_cast<id>(self) isDarkMode];
+}
+
+bool AppKit::enableAccessibility()
+{
+ return [static_cast<id>(self) enableAccessibility];
+}
+
+bool AppKit::enableScreenRecording()
+{
+ return [static_cast<id>(self) enableScreenRecording];
+}
diff --git a/src/gui/osutils/macutils/MacUtils.cpp b/src/gui/osutils/macutils/MacUtils.cpp
new file mode 100644
index 000000000..498325868
--- /dev/null
+++ b/src/gui/osutils/macutils/MacUtils.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
+ * Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 or (at your option)
+ * version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "MacUtils.h"
+#include <QApplication>
+
+QPointer<MacUtils> MacUtils::m_instance = nullptr;
+
+MacUtils::MacUtils(QObject* parent)
+ : OSUtils(parent)
+ , m_appkit(new AppKit())
+{
+ connect(m_appkit.data(), SIGNAL(lockDatabases()), SIGNAL(lockDatabases()));
+}
+
+MacUtils::~MacUtils()
+{
+}
+
+MacUtils* MacUtils::instance()
+{
+ if (!m_instance) {
+ m_instance = new MacUtils(qApp);
+ }
+
+ return m_instance;
+}
+
+WId MacUtils::activeWindow()
+{
+ return m_appkit->activeProcessId();
+}
+
+bool MacUtils::raiseWindow(WId pid)
+{
+ return m_appkit->activateProcess(pid);
+}
+
+bool MacUtils::raiseOwnWindow()
+{
+ return m_appkit->activateProcess(m_appkit->ownProcessId());
+}
+
+bool MacUtils::raiseLastActiveWindow()
+{
+ return m_appkit->activateProcess(m_appkit->lastActiveProcessId());
+}
+
+bool MacUtils::hideOwnWindow()
+{
+ return m_appkit->hideProcess(m_appkit->ownProcessId());
+}
+
+bool MacUtils::isHidden()
+{
+ return m_appkit->isHidden(m_appkit->ownProcessId());
+}
+
+bool MacUtils::isDarkMode()
+{
+ return m_appkit->isDarkMode();
+}
+
+bool MacUtils::enableAccessibility()
+{
+ return m_appkit->enableAccessibility();
+}
+
+bool MacUtils::enableScreenRecording()
+{
+ return m_appkit->enableScreenRecording();
+}
diff --git a/src/gui/osutils/macutils/MacUtils.h b/src/gui/osutils/macutils/MacUtils.h
new file mode 100644
index 000000000..427c7230a
--- /dev/null
+++ b/src/gui/osutils/macutils/MacUtils.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
+ * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 or (at your option)
+ * version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KEEPASSXC_MACUTILS_H
+#define KEEPASSXC_MACUTILS_H
+
+#include "gui/osutils/OSUtilsBase.h"
+#include "AppKit.h"
+#include <QPointer>
+
+class MacUtils : public OSUtils
+{
+ Q_OBJECT
+
+public:
+ static MacUtils* instance();
+
+ WId activeWindow();
+ bool raiseWindow(WId pid);
+ bool raiseLastActiveWindow();
+ bool raiseOwnWindow();
+ bool hideOwnWindow();
+ bool isHidden();
+ bool isDarkMode() override;
+ bool enableAccessibility();
+ bool enableScreenRecording();
+
+signals:
+ void lockDatabases();
+
+protected:
+ explicit MacUtils(QObject* parent = nullptr);
+ ~MacUtils() override;
+
+private:
+ QScopedPointer<AppKit> m_appkit;
+ static QPointer<MacUtils> m_instance;
+
+ Q_DISABLE_COPY(MacUtils)
+};
+
+inline MacUtils* macUtils()
+{
+ return MacUtils::instance();
+}
+
+#endif // KEEPASSXC_MACUTILS_H
diff --git a/src/gui/osutils/nixutils/NixUtils.cpp b/src/gui/osutils/nixutils/NixUtils.cpp
new file mode 100644
index 000000000..229d6b519
--- /dev/null
+++ b/src/gui/osutils/nixutils/NixUtils.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 or (at your option)
+ * version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "NixUtils.h"
+#include <QApplication>
+#include <QColor>
+#include <QPalette>
+#include <QStyle>
+
+QPointer<NixUtils> NixUtils::m_instance = nullptr;
+
+NixUtils* NixUtils::instance()
+{
+ if (!m_instance) {
+ m_instance = new NixUtils(qApp);
+ }
+
+ return m_instance;
+}
+
+NixUtils::NixUtils(QObject* parent)
+ : OSUtilsBase(parent)
+{
+}
+
+NixUtils::~NixUtils()
+{
+}
+
+bool NixUtils::isDarkMode()
+{
+ if (!qApp || !qApp->style()) {
+ return false;
+ }
+ return qApp->style()->standardPalette().color(QPalette::Window).toHsl().lightness() < 110;
+}
diff --git a/src/gui/osutils/nixutils/NixUtils.h b/src/gui/osutils/nixutils/NixUtils.h
new file mode 100644
index 000000000..bf236cdc3
--- /dev/null
+++ b/src/gui/osutils/nixutils/NixUtils.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 or (at your option)
+ * version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KEEPASSXC_NIXUTILS_H
+#define KEEPASSXC_NIXUTILS_H
+
+#include "gui/osutils/OSUtilsBase.h"
+#include <QPointer>
+
+class NixUtils : public OSUtilsBase
+{
+ Q_OBJECT
+
+public:
+ static NixUtils* instance();
+
+ bool isDarkMode() override;
+
+private:
+ explicit NixUtils(QObject* parent = nullptr);
+ ~NixUtils() override;
+
+private:
+ static QPointer<NixUtils> m_instance;
+
+ Q_DISABLE_COPY(NixUtils)
+};
+
+inline NixUtils* nixUtils()
+{
+ return NixUtils::instance();
+}
+
+#endif // KEEPASSXC_NIXUTILS_H
diff --git a/src/gui/osutils/winutils/WinUtils.cpp b/src/gui/osutils/winutils/WinUtils.cpp
new file mode 100644
index 000000000..f92192f18
--- /dev/null
+++ b/src/gui/osutils/winutils/WinUtils.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 or (at your option)
+ * version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "WinUtils.h"
+#include <QAbstractNativeEventFilter>
+#include <QApplication>
+#include <QSettings>
+
+#include <windows.h>
+
+QPointer<WinUtils> WinUtils::m_instance = nullptr;
+QScopedPointer<WinUtils::DWMEventFilter> WinUtils::m_eventFilter;
+
+WinUtils* WinUtils::instance()
+{
+ if (!m_instance) {
+ m_instance = new WinUtils(qApp);
+ }
+
+ return m_instance;
+}
+
+WinUtils::WinUtils(QObject* parent)
+ : OSUtilsBase(parent)
+{
+}
+
+WinUtils::~WinUtils()
+{
+}
+
+/**
+ * Register event filters to handle native platform events such as theme changes.
+ */
+void WinUtils::registerEventFilters()
+{
+ if (!m_eventFilter) {
+ m_eventFilter.reset(new DWMEventFilter);
+ qApp->installNativeEventFilter(m_eventFilter.data());
+ }
+}
+
+bool WinUtils::DWMEventFilter::nativeEventFilter(const QByteArray& eventType, void* message, long*)
+{
+ if (eventType != "windows_generic_MSG") {
+ return false;
+ }
+
+ auto* msg = static_cast<MSG*>(message);
+ if (!msg->hwnd) {
+ return false;
+ }
+ switch (msg->message) {
+ case WM_CREATE:
+ case WM_INITDIALOG: {
+ if (winUtils()->isDarkMode()) {
+ // TODO: indicate dark mode support for black title bar
+ }
+ break;
+ }
+ }
+
+ return false;
+}
+
+bool WinUtils::isDarkMode()
+{
+ QSettings settings(R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)",
+ QSettings::NativeFormat);
+ return settings.value("AppsUseLightTheme", 1).toInt() == 0;
+}
diff --git a/src/gui/osutils/winutils/WinUtils.h b/src/gui/osutils/winutils/WinUtils.h
new file mode 100644
index 000000000..1a95716e1
--- /dev/null
+++ b/src/gui/osutils/winutils/WinUtils.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 or (at your option)
+ * version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KEEPASSXC_WINUTILS_H
+#define KEEPASSXC_WINUTILS_H
+
+#include "gui/osutils/OSUtilsBase.h"
+
+#include <QAbstractNativeEventFilter>
+#include <QPointer>
+#include <QScopedPointer>
+
+class WinUtils : public OSUtilsBase
+{
+ Q_OBJECT
+
+public:
+ static WinUtils* instance();
+ static void registerEventFilters();
+
+ bool isDarkMode() override;
+
+protected:
+ explicit WinUtils(QObject* parent = nullptr);
+ ~WinUtils() override;
+
+private:
+ class DWMEventFilter : public QAbstractNativeEventFilter
+ {
+ public:
+ bool nativeEventFilter(const QByteArray& eventType, void* message, long*) override;
+ };
+
+ static QPointer<WinUtils> m_instance;
+ static QScopedPointer<DWMEventFilter> m_eventFilter;
+
+ Q_DISABLE_COPY(WinUtils)
+};
+
+inline WinUtils* winUtils()
+{
+ return WinUtils::instance();
+}
+
+#endif // KEEPASSXC_WINUTILS_H