Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add menu option to allow screenshots #8841

Merged
merged 1 commit into from
Feb 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions share/translations/keepassxc_en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5420,6 +5420,10 @@ We recommend you use the AppImage available on our downloads page.</source>
<source>You must restart the application to apply this setting. Would you like to restart now?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Allow Screen Capture</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ManageDatabase</name>
Expand Down Expand Up @@ -7887,10 +7891,6 @@ Kernel: %3 %4</source>
<source>KeePassXC - Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Warning: Failed to prevent screenshots on a top level window!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Database password: </source>
<translation type="unfinished"></translation>
Expand All @@ -7913,6 +7913,10 @@ Kernel: %3 %4</source>
<source>Failed to sign challenge using Windows Hello.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Warning: Failed to block screenshot capture on a top-level window.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Invalid Cipher</source>
<translation type="unfinished"></translation>
Expand Down
22 changes: 20 additions & 2 deletions src/gui/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ MainWindow::MainWindow()
m_showToolbarSeparator = config()->get(Config::GUI_ApplicationTheme).toString() != "classic";

m_ui->actionEntryAutoType->setVisible(autoType()->isAvailable());
m_ui->actionAllowScreenCapture->setVisible(osUtils->canPreventScreenCapture());

m_inactivityTimer = new InactivityTimer(this);
connect(m_inactivityTimer, SIGNAL(inactivityDetected()), this, SLOT(lockDatabasesAfterInactivity()));
Expand Down Expand Up @@ -563,6 +564,7 @@ MainWindow::MainWindow()
connect(m_ui->actionUserGuide, SIGNAL(triggered()), SLOT(openUserGuide()));
connect(m_ui->actionOnlineHelp, SIGNAL(triggered()), SLOT(openOnlineHelp()));
connect(m_ui->actionKeyboardShortcuts, SIGNAL(triggered()), SLOT(openKeyboardShortcuts()));
connect(m_ui->actionAllowScreenCapture, &QAction::toggled, this, &MainWindow::setAllowScreenCapture);

connect(osUtils, &OSUtilsBase::statusbarThemeChanged, this, &MainWindow::updateTrayIcon);

Expand Down Expand Up @@ -1658,11 +1660,27 @@ void MainWindow::applySettingsChanges()
updateTrayIcon();
}

void MainWindow::focusWindowChanged(QWindow* focusWindow)
void MainWindow::setAllowScreenCapture(bool state)
{
if (focusWindow != windowHandle()) {
m_allowScreenCapture = state;
for (auto window : qApp->allWindows()) {
osUtils->setPreventScreenCapture(window, !m_allowScreenCapture);
}
m_ui->actionAllowScreenCapture->blockSignals(true);
m_ui->actionAllowScreenCapture->setChecked(m_allowScreenCapture);
m_ui->actionAllowScreenCapture->blockSignals(false);
}

void MainWindow::focusWindowChanged(QWindow* window)
{
if (window != windowHandle()) {
m_lastFocusOutTime = Clock::currentMilliSecondsSinceEpoch();
}

if (!osUtils->setPreventScreenCapture(window, !m_allowScreenCapture) && !m_allowScreenCapture) {
displayGlobalMessage(QObject::tr("Warning: Failed to block screenshot capture on a top-level window."),
MessageWidget::Error);
}
}

void MainWindow::trayIconTriggered(QSystemTrayIcon::ActivationReason reason)
Expand Down
2 changes: 2 additions & 0 deletions src/gui/MainWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class MainWindow : public QMainWindow

QList<DatabaseWidget*> getOpenDatabases();
void restoreConfigState();
void setAllowScreenCapture(bool state);

enum StackedWidgetIndex
{
Expand Down Expand Up @@ -192,6 +193,7 @@ private slots:
bool m_restartRequested = false;
bool m_contextMenuFocusLock = false;
bool m_showToolbarSeparator = false;
bool m_allowScreenCapture = false;
qint64 m_lastFocusOutTime = 0;
qint64 m_lastShowTime = 0;
QTimer m_updateCheckTimer;
Expand Down
9 changes: 9 additions & 0 deletions src/gui/MainWindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@
<addaction name="menuTheme"/>
<addaction name="actionCompactMode"/>
<addaction name="actionAlwaysOnTop"/>
<addaction name="actionAllowScreenCapture"/>
<addaction name="actionShowPreviewPanel"/>
<addaction name="actionShowToolbar"/>
<addaction name="actionHideUsernames"/>
Expand Down Expand Up @@ -1113,6 +1114,14 @@
<string>XML File…</string>
</property>
</action>
<action name="actionAllowScreenCapture">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Allow Screen Capture</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
Expand Down
2 changes: 1 addition & 1 deletion src/gui/osutils/OSUtilsBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ OSUtilsBase::~OSUtilsBase() = default;
bool OSUtilsBase::setPreventScreenCapture(QWindow*, bool) const
{
// Do nothing by default
return false;
return true;
}
6 changes: 2 additions & 4 deletions src/gui/osutils/macutils/MacUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,9 @@ bool MacUtils::canPreventScreenCapture() const

bool MacUtils::setPreventScreenCapture(QWindow* window, bool prevent) const
{
if (!window) {
return false;
if (window) {
m_appkit->setWindowSecurity(window, prevent);
}

m_appkit->setWindowSecurity(window, prevent);
return true;
}

Expand Down
5 changes: 3 additions & 2 deletions src/gui/osutils/winutils/WinUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,12 @@ bool WinUtils::canPreventScreenCapture() const

bool WinUtils::setPreventScreenCapture(QWindow* window, bool prevent) const
{
bool ret = true;
if (window) {
HWND handle = reinterpret_cast<HWND>(window->winId());
return SetWindowDisplayAffinity(handle, prevent ? WDA_EXCLUDEFROMCAPTURE : WDA_NONE);
ret = SetWindowDisplayAffinity(handle, prevent ? WDA_EXCLUDEFROMCAPTURE : WDA_NONE);
}
return false;
return ret;
}

/**
Expand Down
18 changes: 3 additions & 15 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,21 +183,9 @@ int main(int argc, char** argv)

MainWindow mainWindow;

#ifndef QT_DEBUG
// Disable screen capture if capable and not explicitly allowed
if (osUtils->canPreventScreenCapture() && !parser.isSet(allowScreenCaptureOption)) {
// This ensures any top-level windows (Main Window, Modal Dialogs, etc.) are excluded from screenshots
QObject::connect(&app, &QGuiApplication::focusWindowChanged, &mainWindow, [&](QWindow* window) {
if (window) {
if (!osUtils->setPreventScreenCapture(window, true)) {
mainWindow.displayGlobalMessage(
QObject::tr("Warning: Failed to prevent screenshots on a top level window!"),
MessageWidget::Error);
}
}
});
}
#endif
// Disable screen capture if not explicitly allowed
// This ensures any top-level windows (Main Window, Modal Dialogs, etc.) are excluded from screenshots
mainWindow.setAllowScreenCapture(parser.isSet(allowScreenCaptureOption));

const bool pwstdin = parser.isSet(pwstdinOption);
if (!fileNames.isEmpty() && pwstdin) {
Expand Down