Fix - MacOS - get currentScreen on the edge bottom and right returns nullptr and application crashes

(cherry picked from commit 01ae74fbed34849db485db53ffbdf4a938ebea8e)
This commit is contained in:
Yuriy Puchkov
2021-02-08 19:19:51 +02:00
parent 0425be7a44
commit dc7f62ab8d
12 changed files with 144 additions and 43 deletions

View File

@@ -17,6 +17,7 @@
#include "shortcutswidget.h" #include "shortcutswidget.h"
#include "setshortcutwidget.h" #include "setshortcutwidget.h"
#include "src/core/qguiappcurrentscreen.h"
#include <QHeaderView> #include <QHeaderView>
#include <QIcon> #include <QIcon>
#include <QKeyEvent> #include <QKeyEvent>
@@ -28,7 +29,6 @@
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
#include <QCursor> #include <QCursor>
#include <QGuiApplication>
#include <QRect> #include <QRect>
#include <QScreen> #include <QScreen>
#endif #endif
@@ -42,7 +42,7 @@ ShortcutsWidget::ShortcutsWidget(QWidget* parent)
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
QRect position = frameGeometry(); QRect position = frameGeometry();
QScreen* screen = QGuiApplication::screenAt(QCursor::pos()); QScreen* screen = QGuiAppCurrentScreen().currentScreen();
position.moveCenter(screen->availableGeometry().center()); position.moveCenter(screen->availableGeometry().center());
move(position.topLeft()); move(position.topLeft());
#endif #endif

View File

@@ -1,8 +1,8 @@
# Required to generate MOC # Required to generate MOC
target_sources(flameshot PRIVATE controller.h flameshotdbusadapter.h) target_sources(flameshot PRIVATE controller.h flameshotdbusadapter.h qguiappcurrentscreen.h)
target_sources(flameshot PRIVATE capturerequest.cpp controller.cpp flameshotdbusadapter.cpp) target_sources(flameshot PRIVATE capturerequest.cpp controller.cpp flameshotdbusadapter.cpp qguiappcurrentscreen.cpp)
IF (WIN32) IF (WIN32)
target_sources(flameshot PRIVATE globalshortcutfilter.h globalshortcutfilter.cpp) target_sources(flameshot PRIVATE globalshortcutfilter.h globalshortcutfilter.cpp)

View File

@@ -18,6 +18,7 @@
#include "controller.h" #include "controller.h"
#include "external/QHotkey/QHotkey" #include "external/QHotkey/QHotkey"
#include "src/config/configwindow.h" #include "src/config/configwindow.h"
#include "src/core/qguiappcurrentscreen.h"
#include "src/utils/confighandler.h" #include "src/utils/confighandler.h"
#include "src/utils/history.h" #include "src/utils/history.h"
#include "src/utils/screengrabber.h" #include "src/utils/screengrabber.h"
@@ -99,7 +100,7 @@ Controller::Controller()
// Try to take a test screenshot, MacOS will request a "Screen Recording" // Try to take a test screenshot, MacOS will request a "Screen Recording"
// permissions on the first run. Otherwise it will be hidden under the // permissions on the first run. Otherwise it will be hidden under the
// CaptureWidget // CaptureWidget
QScreen* currentScreen = QGuiApplication::screenAt(QCursor::pos()); QScreen* currentScreen = QGuiAppCurrentScreen().currentScreen();
currentScreen->grabWindow(QApplication::desktop()->winId(), 0, 0, 1, 1); currentScreen->grabWindow(QApplication::desktop()->winId(), 0, 0, 1, 1);
// set global shortcuts for MacOS // set global shortcuts for MacOS
@@ -266,15 +267,16 @@ void Controller::startVisualCapture(const uint id,
if (nullptr == m_captureWindow) { if (nullptr == m_captureWindow) {
int timeout = 5000; // 5 seconds int timeout = 5000; // 5 seconds
for (; timeout >= 0; timeout -= 10) { const int delay = 100;
QWidget* modalWidget = qApp->activeModalWidget(); QWidget* modalWidget = nullptr;
if (modalWidget) { for (; timeout >= 0; timeout -= delay) {
modalWidget->close(); modalWidget = qApp->activeModalWidget();
modalWidget->deleteLater(); if (nullptr == modalWidget) {
} else {
break; break;
} }
QThread::msleep(10); modalWidget->close();
modalWidget->deleteLater();
QThread::msleep(delay);
} }
if (0 == timeout) { if (0 == timeout) {
QMessageBox::warning( QMessageBox::warning(
@@ -492,6 +494,15 @@ void Controller::enableTrayIcon()
#endif #endif
m_trayIcon->show(); m_trayIcon->show();
if (ConfigHandler().showStartupLaunchMessage()) {
m_trayIcon->showMessage(
"Flameshot",
QObject::tr(
"Hello, I'm here! Click icon in the tray to take a screenshot or "
"click with a right button to see more options."),
QSystemTrayIcon::Information,
3000);
}
} }
void Controller::disableTrayIcon() void Controller::disableTrayIcon()

View File

@@ -0,0 +1,65 @@
//
// Created by yuriypuchkov on 09.02.2021.
//
#include "qguiappcurrentscreen.h"
#include <QCursor>
#include <QDesktopWidget>
#include <QGuiApplication>
#include <QPoint>
#include <QScreen>
QGuiAppCurrentScreen::QGuiAppCurrentScreen()
{
m_currentScreen = nullptr;
}
QScreen* QGuiAppCurrentScreen::currentScreen()
{
return currentScreen(QCursor::pos());
}
QScreen* QGuiAppCurrentScreen::currentScreen(const QPoint& pos)
{
m_currentScreen = screenAt(pos);
#if (defined(Q_OS_MAC) || defined(Q_OS_MAC64) || defined(Q_OS_MACOS) || \
defined(Q_OS_MACX))
// On the MacOS if mouse position is at the edge of bottom or right sides
// qGuiApp->screenAt will return nullptr, so we need to try to find current
// screen by moving 1 pixel inside to the current desktop area
if (!m_currentScreen && pos.x() > 0) {
QPoint posCorrected(pos.x() - 1, pos.y());
m_currentScreen = screenAt(posCorrected);
}
if (!m_currentScreen && pos.y() > 0) {
QPoint posCorrected(pos.x(), pos.y() - 1);
m_currentScreen = screenAt(posCorrected);
}
if (!m_currentScreen && pos.x() > 0 && pos.y() > 0) {
QPoint posCorrected(pos.x() - 1, pos.y() - 1);
m_currentScreen = screenAt(posCorrected);
}
#endif
if (!m_currentScreen) {
qCritical("Unable to get current screen, starting to use primary "
"screen. It may be a cause of logical error and working with "
"a wrong screen.");
m_currentScreen = qGuiApp->primaryScreen();
}
return m_currentScreen;
}
QScreen* QGuiAppCurrentScreen::screenAt(const QPoint& pos)
{
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
m_currentScreen = qGuiApp->screenAt(pos);
#else
for (QScreen* const screen : QGuiApplication::screens()) {
m_currentScreen = screen;
if (screen->geometry().contains(pos)) {
break;
}
}
#endif
return m_currentScreen;
}

View File

@@ -0,0 +1,27 @@
//
// Created by yuriypuchkov on 09.02.2021.
//
#ifndef FLAMESHOT_QGUIAPPCURRENTSCREEN_H
#define FLAMESHOT_QGUIAPPCURRENTSCREEN_H
#include <QPoint>
class QScreen;
class QGuiAppCurrentScreen
{
public:
explicit QGuiAppCurrentScreen();
QScreen* currentScreen();
QScreen* currentScreen(const QPoint& pos);
private:
QScreen* screenAt(const QPoint& pos);
// class members
private:
QScreen* m_currentScreen;
};
#endif // FLAMESHOT_QGUIAPPCURRENTSCREEN_H

View File

@@ -17,7 +17,6 @@
#include "abstracttwopointtool.h" #include "abstracttwopointtool.h"
#include <QCursor> #include <QCursor>
#include <QGuiApplication>
#include <QScreen> #include <QScreen>
#include <cmath> #include <cmath>

View File

@@ -16,8 +16,8 @@
// along with Flameshot. If not, see <http://www.gnu.org/licenses/>. // along with Flameshot. If not, see <http://www.gnu.org/licenses/>.
#include "pintool.h" #include "pintool.h"
#include "src/core/qguiappcurrentscreen.h"
#include "src/tools/pin/pinwidget.h" #include "src/tools/pin/pinwidget.h"
#include <QGuiApplication>
#include <QScreen> #include <QScreen>
PinTool::PinTool(QObject* parent) PinTool::PinTool(QObject* parent)
@@ -54,7 +54,7 @@ QWidget* PinTool::widget()
qreal devicePixelRatio = 1; qreal devicePixelRatio = 1;
#if (defined(Q_OS_MAC) || defined(Q_OS_MAC64) || defined(Q_OS_MACOS) || \ #if (defined(Q_OS_MAC) || defined(Q_OS_MAC64) || defined(Q_OS_MACOS) || \
defined(Q_OS_MACX)) defined(Q_OS_MACX))
QScreen* currentScreen = QGuiApplication::screenAt(QCursor::pos()); QScreen* currentScreen = QGuiAppCurrentScreen().currentScreen();
if (currentScreen) { if (currentScreen) {
devicePixelRatio = currentScreen->devicePixelRatio(); devicePixelRatio = currentScreen->devicePixelRatio();
} }

View File

@@ -16,6 +16,7 @@
// along with Flameshot. If not, see <http://www.gnu.org/licenses/>. // along with Flameshot. If not, see <http://www.gnu.org/licenses/>.
#include "screengrabber.h" #include "screengrabber.h"
#include "src/core/qguiappcurrentscreen.h"
#include "src/utils/filenamehandler.h" #include "src/utils/filenamehandler.h"
#include "src/utils/systemnotification.h" #include "src/utils/systemnotification.h"
#include <QApplication> #include <QApplication>
@@ -40,7 +41,7 @@ QPixmap ScreenGrabber::grabEntireDesktop(bool& ok)
ok = true; ok = true;
#if (defined(Q_OS_MAC) || defined(Q_OS_MAC64) || defined(Q_OS_MACOS) || \ #if (defined(Q_OS_MAC) || defined(Q_OS_MAC64) || defined(Q_OS_MACOS) || \
defined(Q_OS_MACX)) defined(Q_OS_MACX))
QScreen* currentScreen = QGuiApplication::screenAt(QCursor::pos()); QScreen* currentScreen = QGuiAppCurrentScreen().currentScreen();
QPixmap screenPixmap( QPixmap screenPixmap(
currentScreen->grabWindow(QApplication::desktop()->winId(), currentScreen->grabWindow(QApplication::desktop()->winId(),
currentScreen->geometry().x(), currentScreen->geometry().x(),

View File

@@ -17,7 +17,6 @@
#include "buttonhandler.h" #include "buttonhandler.h"
#include "src/utils/globalvalues.h" #include "src/utils/globalvalues.h"
#include <QGuiApplication>
#include <QPoint> #include <QPoint>
#include <QScreen> #include <QScreen>

View File

@@ -25,6 +25,7 @@
#include "capturewidget.h" #include "capturewidget.h"
#include "src/core/controller.h" #include "src/core/controller.h"
#include "src/core/qguiappcurrentscreen.h"
#include "src/tools/toolfactory.h" #include "src/tools/toolfactory.h"
#include "src/utils/colorutils.h" #include "src/utils/colorutils.h"
#include "src/utils/screengrabber.h" #include "src/utils/screengrabber.h"
@@ -40,7 +41,6 @@
#include <QApplication> #include <QApplication>
#include <QDateTime> #include <QDateTime>
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QGuiApplication>
#include <QPaintEvent> #include <QPaintEvent>
#include <QPainter> #include <QPainter>
#include <QScreen> #include <QScreen>
@@ -113,12 +113,9 @@ CaptureWidget::CaptureWidget(const uint id,
for (QScreen* const screen : QGuiApplication::screens()) { for (QScreen* const screen : QGuiApplication::screens()) {
QPoint topLeftScreen = screen->geometry().topLeft(); QPoint topLeftScreen = screen->geometry().topLeft();
if (topLeft.x() > topLeftScreen.x() ||
if (topLeftScreen.x() < topLeft.x()) { topLeft.y() > topLeftScreen.y()) {
topLeft.setX(topLeftScreen.x()); topLeft = topLeftScreen;
}
if (topLeftScreen.y() < topLeft.y()) {
topLeft.setY(topLeftScreen.y());
} }
} }
move(topLeft); move(topLeft);
@@ -132,7 +129,7 @@ CaptureWidget::CaptureWidget(const uint id,
// Qt::NoDropShadowWindowHint | Qt::ToolTip | // Qt::NoDropShadowWindowHint | Qt::ToolTip |
// Qt::Popup // Qt::Popup
// ); // );
QScreen* currentScreen = QGuiApplication::screenAt(QCursor::pos()); QScreen* currentScreen = QGuiAppCurrentScreen().currentScreen();
move(currentScreen->geometry().x(), currentScreen->geometry().y()); move(currentScreen->geometry().x(), currentScreen->geometry().y());
resize(currentScreen->size()); resize(currentScreen->size());
#else #else
@@ -153,12 +150,12 @@ CaptureWidget::CaptureWidget(const uint id,
#if (defined(Q_OS_MAC) || defined(Q_OS_MAC64) || defined(Q_OS_MACOS) || \ #if (defined(Q_OS_MAC) || defined(Q_OS_MAC64) || defined(Q_OS_MACOS) || \
defined(Q_OS_MACX)) defined(Q_OS_MACX))
QPoint currentPos = QCursor::pos();
// MacOS works just with one active display, so we need to append // MacOS works just with one active display, so we need to append
// just one current display and keep multiple displays logic for // just one current display and keep multiple displays logic for
// other OS // other OS
QScreen* const screen = qGuiApp->screenAt(currentPos); QRect r;
QRect r = screen->geometry(); QScreen* screen = QGuiAppCurrentScreen().currentScreen();
r = screen->geometry();
// all calculations are processed according to (0, 0) start // all calculations are processed according to (0, 0) start
// point so we need to move current object to (0, 0) // point so we need to move current object to (0, 0)
r.moveTo(0, 0); r.moveTo(0, 0);
@@ -339,16 +336,17 @@ void CaptureWidget::paintEvent(QPaintEvent*)
painter.setClipRect(rect()); painter.setClipRect(rect());
if (m_showInitialMsg) { if (m_showInitialMsg) {
#if (defined(Q_OS_LINUX) && QT_VERSION < QT_VERSION_CHECK(5, 10, 0)) #if (defined(Q_OS_MAC) || defined(Q_OS_MAC64) || defined(Q_OS_MACOS) || \
QRect helpRect = QGuiApplication::primaryScreen()->geometry(); defined(Q_OS_MACX))
#else
QRect helpRect; QRect helpRect;
QScreen* currentScreen = QGuiApplication::screenAt(QCursor::pos()); QScreen* currentScreen = QGuiAppCurrentScreen().currentScreen();
if (currentScreen) { if (currentScreen) {
helpRect = currentScreen->geometry(); helpRect = currentScreen->geometry();
} else { } else {
helpRect = QGuiApplication::primaryScreen()->geometry(); helpRect = QGuiApplication::primaryScreen()->geometry();
} }
#else
QRect helpRect = QGuiApplication::primaryScreen()->geometry();
#endif #endif
helpRect.moveTo(mapFromGlobal(helpRect.topLeft())); helpRect.moveTo(mapFromGlobal(helpRect.topLeft()));
@@ -472,7 +470,6 @@ void CaptureWidget::mouseMoveEvent(QMouseEvent* e)
QPoint newTopLeft = QPoint newTopLeft =
initialRect.topLeft() + (e->pos() - m_dragStartPoint); initialRect.topLeft() + (e->pos() - m_dragStartPoint);
inputRect = QRect(newTopLeft, initialRect.size()); inputRect = QRect(newTopLeft, initialRect.size());
} else { } else {
// Dragging a handle // Dragging a handle
inputRect = m_selection->savedGeometry(); inputRect = m_selection->savedGeometry();
@@ -729,7 +726,8 @@ void CaptureWidget::initPanel()
panelRect.moveTo(panelRect.x() / devicePixelRatio, panelRect.moveTo(panelRect.x() / devicePixelRatio,
panelRect.y() / devicePixelRatio); panelRect.y() / devicePixelRatio);
#else #else
QScreen* currentScreen = QGuiApplication::screenAt(QCursor::pos()); QScreen* currentScreen = QGuiAppCurrentScreen().currentScreen();
if (currentScreen) { if (currentScreen) {
panelRect = currentScreen->geometry(); panelRect = currentScreen->geometry();
auto devicePixelRatio = currentScreen->devicePixelRatio(); auto devicePixelRatio = currentScreen->devicePixelRatio();
@@ -770,7 +768,7 @@ void CaptureWidget::initPanel()
makeChild(m_panel); makeChild(m_panel);
#if (defined(Q_OS_MAC) || defined(Q_OS_MAC64) || defined(Q_OS_MACOS) || \ #if (defined(Q_OS_MAC) || defined(Q_OS_MAC64) || defined(Q_OS_MACOS) || \
defined(Q_OS_MACX)) defined(Q_OS_MACX))
QScreen* currentScreen = QGuiApplication::screenAt(QCursor::pos()); QScreen* currentScreen = QGuiAppCurrentScreen().currentScreen();
panelRect.moveTo(mapFromGlobal(panelRect.topLeft())); panelRect.moveTo(mapFromGlobal(panelRect.topLeft()));
m_panel->setFixedWidth(m_colorPicker->width() * 1.5); m_panel->setFixedWidth(m_colorPicker->width() * 1.5);
m_panel->setFixedHeight(currentScreen->geometry().height()); m_panel->setFixedHeight(currentScreen->geometry().height());
@@ -816,7 +814,10 @@ void CaptureWidget::showAppUpdateNotification(const QString& appLatestVersion,
m_updateNotificationWidget = m_updateNotificationWidget =
new UpdateNotificationWidget(this, appLatestVersion, appLatestUrl); new UpdateNotificationWidget(this, appLatestVersion, appLatestUrl);
} }
#if (defined(Q_OS_LINUX) && QT_VERSION < QT_VERSION_CHECK(5, 10, 0)) #if (defined(Q_OS_MAC) || defined(Q_OS_MAC64) || defined(Q_OS_MACOS) || \
defined(Q_OS_MACX))
int ax = (width() - m_updateNotificationWidget->width()) / 2;
#elif (defined(Q_OS_LINUX) && QT_VERSION < QT_VERSION_CHECK(5, 10, 0))
QRect helpRect = QGuiApplication::primaryScreen()->geometry(); QRect helpRect = QGuiApplication::primaryScreen()->geometry();
#else #else
QRect helpRect; QRect helpRect;
@@ -826,10 +827,9 @@ void CaptureWidget::showAppUpdateNotification(const QString& appLatestVersion,
} else { } else {
helpRect = QGuiApplication::primaryScreen()->geometry(); helpRect = QGuiApplication::primaryScreen()->geometry();
} }
#endif
int ax = helpRect.left() + int ax = helpRect.left() +
((helpRect.width() - m_updateNotificationWidget->width()) / 2); ((helpRect.width() - m_updateNotificationWidget->width()) / 2);
#endif
m_updateNotificationWidget->move(ax, 0); m_updateNotificationWidget->move(ax, 0);
makeChild(m_updateNotificationWidget); makeChild(m_updateNotificationWidget);
m_updateNotificationWidget->show(); m_updateNotificationWidget->show();

View File

@@ -16,6 +16,7 @@
// along with Flameshot. If not, see <http://www.gnu.org/licenses/>. // along with Flameshot. If not, see <http://www.gnu.org/licenses/>.
#include "infowindow.h" #include "infowindow.h"
#include "src/core/qguiappcurrentscreen.h"
#include <QHeaderView> #include <QHeaderView>
#include <QIcon> #include <QIcon>
#include <QKeyEvent> #include <QKeyEvent>
@@ -23,8 +24,6 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
#include <QCursor>
#include <QGuiApplication>
#include <QRect> #include <QRect>
#include <QScreen> #include <QScreen>
#endif #endif
@@ -40,7 +39,7 @@ InfoWindow::InfoWindow(QWidget* parent)
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
QRect position = frameGeometry(); QRect position = frameGeometry();
QScreen* screen = QGuiApplication::screenAt(QCursor::pos()); QScreen* screen = QGuiAppCurrentScreen().currentScreen();
position.moveCenter(screen->availableGeometry().center()); position.moveCenter(screen->availableGeometry().center());
move(position.topLeft()); move(position.topLeft());
#endif #endif

View File

@@ -16,6 +16,7 @@
// along with Flameshot. If not, see <http://www.gnu.org/licenses/>. // along with Flameshot. If not, see <http://www.gnu.org/licenses/>.
#include "sidepanelwidget.h" #include "sidepanelwidget.h"
#include "src/core/qguiappcurrentscreen.h"
#include "src/utils/colorutils.h" #include "src/utils/colorutils.h"
#include "src/utils/pathinfo.h" #include "src/utils/pathinfo.h"
#include <QFormLayout> #include <QFormLayout>
@@ -26,7 +27,6 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#if (defined(Q_OS_MAC) || defined(Q_OS_MAC64) || defined(Q_OS_MACOS) || \ #if (defined(Q_OS_MAC) || defined(Q_OS_MAC64) || defined(Q_OS_MACOS) || \
defined(Q_OS_MACX)) defined(Q_OS_MACX))
#include <QGuiApplication>
#include <QScreen> #include <QScreen>
#endif #endif
@@ -168,7 +168,7 @@ QColor SidePanelWidget::grabPixmapColor(const QPoint& p)
if (m_pixmap) { if (m_pixmap) {
#if (defined(Q_OS_MAC) || defined(Q_OS_MAC64) || defined(Q_OS_MACOS) || \ #if (defined(Q_OS_MAC) || defined(Q_OS_MAC64) || defined(Q_OS_MACOS) || \
defined(Q_OS_MACX)) defined(Q_OS_MACX))
QScreen* currentScreen = QGuiApplication::screenAt(QCursor::pos()); QScreen* currentScreen = QGuiAppCurrentScreen().currentScreen();
QPoint point = p; QPoint point = p;
if (currentScreen) { if (currentScreen) {
point = QPoint((p.x() - currentScreen->geometry().x()) * point = QPoint((p.x() - currentScreen->geometry().x()) *