Switch browser integration to use native raising of windows

This commit is contained in:
varjolintu 2018-01-25 14:21:05 +02:00 committed by Jonathan White
parent c630214915
commit 5488f1bfc3
16 changed files with 229 additions and 34 deletions

View File

@ -174,7 +174,9 @@ if(APPLE)
set(keepassx_SOURCES set(keepassx_SOURCES
${keepassx_SOURCES} ${keepassx_SOURCES}
core/ScreenLockListenerMac.cpp core/ScreenLockListenerMac.cpp
core/MacPasteboard.cpp) core/MacPasteboard.cpp
gui/macutils/MacUtils.cpp
gui/macutils/AppKitImpl.mm)
endif() endif()
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
set(keepassx_SOURCES set(keepassx_SOURCES
@ -272,7 +274,7 @@ target_link_libraries(keepassx_core
${ZXCVBN_LIBRARIES}) ${ZXCVBN_LIBRARIES})
if(APPLE) if(APPLE)
target_link_libraries(keepassx_core "-framework Foundation") target_link_libraries(keepassx_core "-framework Foundation -framework AppKit")
if(Qt5MacExtras_FOUND) if(Qt5MacExtras_FOUND)
target_link_libraries(keepassx_core Qt5::MacExtras) target_link_libraries(keepassx_core Qt5::MacExtras)
endif() endif()

View File

@ -17,6 +17,7 @@
*/ */
#include "AutoTypeMac.h" #include "AutoTypeMac.h"
#include "gui/macutils/MacUtils.h"
#include <ApplicationServices/ApplicationServices.h> #include <ApplicationServices/ApplicationServices.h>
@ -25,8 +26,7 @@
#define INVALID_KEYCODE 0xFFFF #define INVALID_KEYCODE 0xFFFF
AutoTypePlatformMac::AutoTypePlatformMac() AutoTypePlatformMac::AutoTypePlatformMac()
: m_appkit(new AppKit()) : m_hotkeyRef(nullptr)
, m_hotkeyRef(nullptr)
, m_hotkeyId({ 'kpx2', HOTKEY_ID }) , m_hotkeyId({ 'kpx2', HOTKEY_ID })
{ {
EventTypeSpec eventSpec; EventTypeSpec eventSpec;
@ -79,7 +79,7 @@ QStringList AutoTypePlatformMac::windowTitles()
// //
WId AutoTypePlatformMac::activeWindow() WId AutoTypePlatformMac::activeWindow()
{ {
return m_appkit->activeProcessId(); return macUtils()->activeWindow();
} }
// //
@ -159,7 +159,7 @@ AutoTypeExecutor* AutoTypePlatformMac::createExecutor()
// //
bool AutoTypePlatformMac::raiseWindow(WId pid) bool AutoTypePlatformMac::raiseWindow(WId pid)
{ {
return m_appkit->activateProcess(pid); return macUtils()->raiseWindow(pid);
} }
// //
@ -167,7 +167,7 @@ bool AutoTypePlatformMac::raiseWindow(WId pid)
// //
bool AutoTypePlatformMac::raiseLastActiveWindow() bool AutoTypePlatformMac::raiseLastActiveWindow()
{ {
return m_appkit->activateProcess(m_appkit->lastActiveProcessId()); return macUtils()->raiseLastActiveWindow();
} }
// //
@ -175,7 +175,7 @@ bool AutoTypePlatformMac::raiseLastActiveWindow()
// //
bool AutoTypePlatformMac::raiseOwnWindow() bool AutoTypePlatformMac::raiseOwnWindow()
{ {
return m_appkit->activateProcess(m_appkit->ownProcessId()); return macUtils()->raiseOwnWindow();
} }
// //

View File

@ -23,7 +23,6 @@
#include <QtPlugin> #include <QtPlugin>
#include <memory> #include <memory>
#include "AppKit.h"
#include "autotype/AutoTypePlatformPlugin.h" #include "autotype/AutoTypePlatformPlugin.h"
#include "autotype/AutoTypeAction.h" #include "autotype/AutoTypeAction.h"
@ -55,7 +54,6 @@ signals:
void globalShortcutTriggered(); void globalShortcutTriggered();
private: private:
std::unique_ptr<AppKit> m_appkit;
EventHotKeyRef m_hotkeyRef; EventHotKeyRef m_hotkeyRef;
EventHotKeyID m_hotkeyId; EventHotKeyID m_hotkeyId;

View File

@ -1,6 +1,8 @@
set(autotype_mac_SOURCES AutoTypeMac.cpp) set(autotype_mac_SOURCES AutoTypeMac.cpp)
set(autotype_mac_mm_SOURCES AppKitImpl.mm) set(autotype_mac_mm_SOURCES
${CMAKE_SOURCE_DIR}/src/gui/macutils/AppKitImpl.mm
${CMAKE_SOURCE_DIR}/src/gui/macutils/MacUtils.cpp)
add_library(keepassx-autotype-cocoa MODULE ${autotype_mac_SOURCES} ${autotype_mac_mm_SOURCES}) add_library(keepassx-autotype-cocoa MODULE ${autotype_mac_SOURCES} ${autotype_mac_mm_SOURCES})
set_target_properties(keepassx-autotype-cocoa PROPERTIES LINK_FLAGS "-framework Foundation -framework AppKit -framework Carbon") set_target_properties(keepassx-autotype-cocoa PROPERTIES LINK_FLAGS "-framework Foundation -framework AppKit -framework Carbon")

View File

@ -33,8 +33,12 @@
#include "core/Group.h" #include "core/Group.h"
#include "core/Metadata.h" #include "core/Metadata.h"
#include "core/PasswordGenerator.h" #include "core/PasswordGenerator.h"
#include "core/Tools.h"
#include "gui/MainWindow.h" #include "gui/MainWindow.h"
#include "gui/MessageBox.h" #include "gui/MessageBox.h"
#ifdef Q_OS_MACOS
#include "gui/macutils/MacUtils.h"
#endif
const char BrowserService::KEEPASSXCBROWSER_NAME[] = "KeePassXC-Browser Settings"; const char BrowserService::KEEPASSXCBROWSER_NAME[] = "KeePassXC-Browser Settings";
const char BrowserService::KEEPASSXCBROWSER_OLD_NAME[] = "keepassxc-browser Settings"; const char BrowserService::KEEPASSXCBROWSER_OLD_NAME[] = "keepassxc-browser Settings";
@ -50,6 +54,7 @@ BrowserService::BrowserService(DatabaseTabWidget* parent)
: m_dbTabWidget(parent) : m_dbTabWidget(parent)
, m_dialogActive(false) , m_dialogActive(false)
, m_bringToFrontRequested(false) , m_bringToFrontRequested(false)
, m_wasMinimized(false)
, m_keepassBrowserUUID(QUuid::fromRfc4122(QByteArray::fromHex("de887cc3036343b8974b5911b8816224"))) , m_keepassBrowserUUID(QUuid::fromRfc4122(QByteArray::fromHex("de887cc3036343b8974b5911b8816224")))
{ {
// Don't connect the signals when used from DatabaseSettingsWidgetBrowser (parent is nullptr) // Don't connect the signals when used from DatabaseSettingsWidgetBrowser (parent is nullptr)
@ -90,8 +95,9 @@ bool BrowserService::openDatabase(bool triggerUnlock)
} }
if (triggerUnlock) { if (triggerUnlock) {
getMainWindow()->bringToFront();
m_bringToFrontRequested = true; m_bringToFrontRequested = true;
m_wasMinimized = getMainWindow()->isMinimized();
raiseWindow(true);
} }
return false; return false;
@ -168,6 +174,7 @@ QString BrowserService::storeKey(const QString& key)
"give it a unique name to identify and accept it.")); "give it a unique name to identify and accept it."));
keyDialog.setOkButtonText(tr("Save and allow access")); keyDialog.setOkButtonText(tr("Save and allow access"));
keyDialog.setWindowFlags(keyDialog.windowFlags() | Qt::WindowStaysOnTopHint); keyDialog.setWindowFlags(keyDialog.windowFlags() | Qt::WindowStaysOnTopHint);
raiseWindow();
keyDialog.show(); keyDialog.show();
keyDialog.activateWindow(); keyDialog.activateWindow();
keyDialog.raise(); keyDialog.raise();
@ -176,6 +183,7 @@ QString BrowserService::storeKey(const QString& key)
id = keyDialog.textValue(); id = keyDialog.textValue();
if (ok != QDialog::Accepted || id.isEmpty()) { if (ok != QDialog::Accepted || id.isEmpty()) {
hideWindow();
return {}; return {};
} }
@ -191,6 +199,7 @@ QString BrowserService::storeKey(const QString& key)
} }
} while (contains && dialogResult == MessageBox::Cancel); } while (contains && dialogResult == MessageBox::Cancel);
hideWindow();
db->metadata()->customData()->set(QLatin1String(ASSOCIATE_KEY_PREFIX) + id, key); db->metadata()->customData()->set(QLatin1String(ASSOCIATE_KEY_PREFIX) + id, key);
return id; return id;
} }
@ -371,12 +380,13 @@ void BrowserService::updateEntry(const QString& id,
|| entry->password().compare(password, Qt::CaseSensitive) != 0) { || entry->password().compare(password, Qt::CaseSensitive) != 0) {
MessageBox::Button dialogResult = MessageBox::No; MessageBox::Button dialogResult = MessageBox::No;
if (!browserSettings()->alwaysAllowUpdate()) { if (!browserSettings()->alwaysAllowUpdate()) {
raiseWindow();
dialogResult = MessageBox::question(nullptr, dialogResult = MessageBox::question(nullptr,
tr("KeePassXC: Update Entry"), tr("KeePassXC: Update Entry"),
tr("Do you want to update the information in %1 - %2?") tr("Do you want to update the information in %1 - %2?")
.arg(QUrl(url).host(), username), .arg(QUrl(url).host(), username),
MessageBox::Save | MessageBox::Cancel, MessageBox::Save | MessageBox::Cancel,
MessageBox::Cancel); MessageBox::Cancel, MessageBox::Raise);
} }
if (browserSettings()->alwaysAllowUpdate() || dialogResult == MessageBox::Save) { if (browserSettings()->alwaysAllowUpdate() || dialogResult == MessageBox::Save) {
@ -385,6 +395,8 @@ void BrowserService::updateEntry(const QString& id,
entry->setPassword(password); entry->setPassword(password);
entry->endUpdate(); entry->endUpdate();
} }
hideWindow();
} }
} }
@ -591,6 +603,11 @@ bool BrowserService::confirmEntries(QList<Entry*>& pwEntriesToConfirm,
accessControlDialog.setUrl(url); accessControlDialog.setUrl(url);
accessControlDialog.setItems(pwEntriesToConfirm); accessControlDialog.setItems(pwEntriesToConfirm);
raiseWindow();
accessControlDialog.show();
accessControlDialog.activateWindow();
accessControlDialog.raise();
int res = accessControlDialog.exec(); int res = accessControlDialog.exec();
if (accessControlDialog.remember()) { if (accessControlDialog.remember()) {
for (Entry* entry : pwEntriesToConfirm) { for (Entry* entry : pwEntriesToConfirm) {
@ -614,6 +631,7 @@ bool BrowserService::confirmEntries(QList<Entry*>& pwEntriesToConfirm,
} }
m_dialogActive = false; m_dialogActive = false;
hideWindow();
if (res == QDialog::Accepted) { if (res == QDialog::Accepted) {
return true; return true;
} }
@ -909,6 +927,32 @@ bool BrowserService::checkLegacySettings()
return dialogResult == MessageBox::Yes; return dialogResult == MessageBox::Yes;
} }
void BrowserService::hideWindow() const
{
if (m_wasMinimized) {
getMainWindow()->showMinimized();
} else {
#ifdef Q_OS_MACOS
macUtils()->raiseLastActiveWindow();
#else
getMainWindow()->lower();
#endif
}
}
void BrowserService::raiseWindow(const bool force)
{
m_wasMinimized = getMainWindow()->isMinimized();
#ifdef Q_OS_MACOS
macUtils()->raiseOwnWindow();
Tools::wait(500);
#else
if (force) {
getMainWindow()->bringToFront();
}
#endif
}
void BrowserService::databaseLocked(DatabaseWidget* dbWidget) void BrowserService::databaseLocked(DatabaseWidget* dbWidget)
{ {
if (dbWidget) { if (dbWidget) {
@ -920,7 +964,7 @@ void BrowserService::databaseUnlocked(DatabaseWidget* dbWidget)
{ {
if (dbWidget) { if (dbWidget) {
if (m_bringToFrontRequested) { if (m_bringToFrontRequested) {
getMainWindow()->lower(); hideWindow();
m_bringToFrontRequested = false; m_bringToFrontRequested = false;
} }
emit databaseUnlocked(); emit databaseUnlocked();

View File

@ -117,11 +117,14 @@ private:
bool moveSettingsToCustomData(Entry* entry, const QString& name) const; bool moveSettingsToCustomData(Entry* entry, const QString& name) const;
int moveKeysToCustomData(Entry* entry, QSharedPointer<Database> db) const; int moveKeysToCustomData(Entry* entry, QSharedPointer<Database> db) const;
bool checkLegacySettings(); bool checkLegacySettings();
void hideWindow() const;
void raiseWindow(const bool force = false);
private: private:
DatabaseTabWidget* const m_dbTabWidget; DatabaseTabWidget* const m_dbTabWidget;
bool m_dialogActive; bool m_dialogActive;
bool m_bringToFrontRequested; bool m_bringToFrontRequested;
bool m_wasMinimized;
QUuid m_keepassBrowserUUID; QUuid m_keepassBrowserUUID;
}; };

View File

@ -25,7 +25,11 @@ DatabaseOpenDialog::DatabaseOpenDialog(QWidget* parent)
, m_view(new DatabaseOpenWidget(this)) , m_view(new DatabaseOpenWidget(this))
{ {
setWindowTitle(tr("Unlock Database - KeePassXC")); setWindowTitle(tr("Unlock Database - KeePassXC"));
#ifdef Q_OS_MACOS
setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
#else
setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint | Qt::ForeignWindow); setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint | Qt::ForeignWindow);
#endif
connect(m_view, SIGNAL(dialogFinished(bool)), this, SLOT(complete(bool))); connect(m_view, SIGNAL(dialogFinished(bool)), this, SLOT(complete(bool)));
} }

View File

@ -15,8 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef KEEPASSX_AUTOTYPEUNLOCKDIALOG_H #ifndef KEEPASSX_UNLOCKDATABASEDIALOG_H
#define KEEPASSX_AUTOTYPEUNLOCKDIALOG_H #define KEEPASSX_UNLOCKDATABASEDIALOG_H
#include "core/Global.h" #include "core/Global.h"
@ -37,7 +37,8 @@ public:
{ {
None, None,
AutoType, AutoType,
Merge Merge,
Browser
}; };
explicit DatabaseOpenDialog(QWidget* parent = nullptr); explicit DatabaseOpenDialog(QWidget* parent = nullptr);
@ -61,4 +62,4 @@ private:
Intent m_intent = Intent::None; Intent m_intent = Intent::None;
}; };
#endif // KEEPASSX_AUTOTYPEUNLOCKDIALOG_H #endif // KEEPASSX_UNLOCKDATABASEDIALOG_H

View File

@ -39,6 +39,9 @@
#include "gui/DatabaseOpenDialog.h" #include "gui/DatabaseOpenDialog.h"
#include "gui/entry/EntryView.h" #include "gui/entry/EntryView.h"
#include "gui/group/GroupView.h" #include "gui/group/GroupView.h"
#ifdef Q_OS_MACOS
#include "gui/macutils/MacUtils.h"
#endif
#include "gui/wizard/NewDatabaseWizard.h" #include "gui/wizard/NewDatabaseWizard.h"
DatabaseTabWidget::DatabaseTabWidget(QWidget* parent) DatabaseTabWidget::DatabaseTabWidget(QWidget* parent)
@ -544,8 +547,8 @@ void DatabaseTabWidget::unlockDatabaseInDialog(DatabaseWidget* dbWidget, Databas
m_databaseOpenDialog->setFilePath(filePath); m_databaseOpenDialog->setFilePath(filePath);
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
if (intent == DatabaseOpenDialog::Intent::AutoType) { if (intent == DatabaseOpenDialog::Intent::AutoType || intent == DatabaseOpenDialog::Intent::Browser) {
autoType()->raiseWindow(); macUtils()->raiseOwnWindow();
Tools::wait(500); Tools::wait(500);
} }
#endif #endif

View File

@ -76,7 +76,8 @@ MessageBox::Button MessageBox::messageBox(QWidget* parent,
const QString& title, const QString& title,
const QString& text, const QString& text,
MessageBox::Buttons buttons, MessageBox::Buttons buttons,
MessageBox::Button defaultButton) MessageBox::Button defaultButton,
MessageBox::Action action)
{ {
if (m_nextAnswer == MessageBox::NoButton) { if (m_nextAnswer == MessageBox::NoButton) {
QMessageBox msgBox(parent); QMessageBox msgBox(parent);
@ -101,6 +102,11 @@ MessageBox::Button MessageBox::messageBox(QWidget* parent,
} }
} }
if (action == MessageBox::Raise) {
msgBox.setWindowFlags(Qt::WindowStaysOnTopHint);
msgBox.activateWindow();
msgBox.raise();
}
msgBox.exec(); msgBox.exec();
Button returnButton = m_addedButtonLookup[msgBox.clickedButton()]; Button returnButton = m_addedButtonLookup[msgBox.clickedButton()];
@ -118,36 +124,40 @@ MessageBox::Button MessageBox::critical(QWidget* parent,
const QString& title, const QString& title,
const QString& text, const QString& text,
MessageBox::Buttons buttons, MessageBox::Buttons buttons,
MessageBox::Button defaultButton) MessageBox::Button defaultButton,
MessageBox::Action action)
{ {
return messageBox(parent, QMessageBox::Critical, title, text, buttons, defaultButton); return messageBox(parent, QMessageBox::Critical, title, text, buttons, defaultButton, action);
} }
MessageBox::Button MessageBox::information(QWidget* parent, MessageBox::Button MessageBox::information(QWidget* parent,
const QString& title, const QString& title,
const QString& text, const QString& text,
MessageBox::Buttons buttons, MessageBox::Buttons buttons,
MessageBox::Button defaultButton) MessageBox::Button defaultButton,
MessageBox::Action action)
{ {
return messageBox(parent, QMessageBox::Information, title, text, buttons, defaultButton); return messageBox(parent, QMessageBox::Information, title, text, buttons, defaultButton, action);
} }
MessageBox::Button MessageBox::question(QWidget* parent, MessageBox::Button MessageBox::question(QWidget* parent,
const QString& title, const QString& title,
const QString& text, const QString& text,
MessageBox::Buttons buttons, MessageBox::Buttons buttons,
MessageBox::Button defaultButton) MessageBox::Button defaultButton,
MessageBox::Action action)
{ {
return messageBox(parent, QMessageBox::Question, title, text, buttons, defaultButton); return messageBox(parent, QMessageBox::Question, title, text, buttons, defaultButton, action);
} }
MessageBox::Button MessageBox::warning(QWidget* parent, MessageBox::Button MessageBox::warning(QWidget* parent,
const QString& title, const QString& title,
const QString& text, const QString& text,
MessageBox::Buttons buttons, MessageBox::Buttons buttons,
MessageBox::Button defaultButton) MessageBox::Button defaultButton,
MessageBox::Action action)
{ {
return messageBox(parent, QMessageBox::Warning, title, text, buttons, defaultButton); return messageBox(parent, QMessageBox::Warning, title, text, buttons, defaultButton, action);
} }
void MessageBox::setNextAnswer(MessageBox::Button button) void MessageBox::setNextAnswer(MessageBox::Button button)

View File

@ -63,6 +63,11 @@ public:
Last = Merge, Last = Merge,
}; };
enum Action {
None = 0,
Raise = 1,
};
typedef uint64_t Buttons; typedef uint64_t Buttons;
static void initializeButtonDefs(); static void initializeButtonDefs();
@ -72,22 +77,26 @@ public:
const QString& title, const QString& title,
const QString& text, const QString& text,
Buttons buttons = MessageBox::Ok, Buttons buttons = MessageBox::Ok,
Button defaultButton = MessageBox::NoButton); Button defaultButton = MessageBox::NoButton,
Action action = MessageBox::None);
static Button information(QWidget* parent, static Button information(QWidget* parent,
const QString& title, const QString& title,
const QString& text, const QString& text,
Buttons buttons = MessageBox::Ok, Buttons buttons = MessageBox::Ok,
Button defaultButton = MessageBox::NoButton); Button defaultButton = MessageBox::NoButton,
Action action = MessageBox::None);
static Button question(QWidget* parent, static Button question(QWidget* parent,
const QString& title, const QString& title,
const QString& text, const QString& text,
Buttons buttons = MessageBox::Ok, Buttons buttons = MessageBox::Ok,
Button defaultButton = MessageBox::NoButton); Button defaultButton = MessageBox::NoButton,
Action action = MessageBox::None);
static Button warning(QWidget* parent, static Button warning(QWidget* parent,
const QString& title, const QString& title,
const QString& text, const QString& text,
Buttons buttons = MessageBox::Ok, Buttons buttons = MessageBox::Ok,
Button defaultButton = MessageBox::NoButton); Button defaultButton = MessageBox::NoButton,
Action action = MessageBox::None);
private: private:
static Button m_nextAnswer; static Button m_nextAnswer;
@ -99,7 +108,8 @@ private:
const QString& title, const QString& title,
const QString& text, const QString& text,
Buttons buttons = MessageBox::Ok, Buttons buttons = MessageBox::Ok,
Button defaultButton = MessageBox::NoButton); Button defaultButton = MessageBox::NoButton,
Action action = MessageBox::None);
static QString stdButtonText(QMessageBox::StandardButton button); static QString stdButtonText(QMessageBox::StandardButton button);

View File

@ -0,0 +1,62 @@
/*
* 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>
MacUtils* MacUtils::m_instance = nullptr;
MacUtils::MacUtils(QObject* parent) : QObject(parent)
, m_appkit(new AppKit())
{
}
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());
}

View File

@ -0,0 +1,56 @@
/*
* 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 <QObject>
#include <QWidget>
#include "AppKit.h"
class MacUtils : public QObject
{
Q_OBJECT
public:
static MacUtils* instance();
static void createTestInstance();
WId activeWindow();
bool raiseWindow(WId pid);
bool raiseLastActiveWindow();
bool raiseOwnWindow();
private:
explicit MacUtils(QObject* parent = nullptr);
~MacUtils();
private:
std::unique_ptr<AppKit> m_appkit;
static MacUtils* m_instance;
void* self;
Q_DISABLE_COPY(MacUtils)
};
inline MacUtils* macUtils()
{
return MacUtils::instance();
}
#endif // KEEPASSXC_MACUTILS_H