From 28943e130d80c183d40df77bc17c64f4593b6aca Mon Sep 17 00:00:00 2001 From: wangyucheng Date: Sun, 23 Apr 2023 14:29:42 +0800 Subject: [PATCH] feature: add windows capture mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 增加截图时代码捕获的功能 --- .gitignore | 2 + flameshot.pro | 4 + src/core/controller.cpp | 2 +- src/widgets/capture/capturewidget.cpp | 98 +++++++++++++++++++++- src/widgets/capture/capturewidget.h | 6 ++ src/widgets/capture/thicknesswidget.cpp | 1 + src/widgets/capture/toowidget.cpp | 1 + translations/Internationalization_zh_CN.ts | 6 +- 8 files changed, 114 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index e69de29..5acb669 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1,2 @@ +build +.vscode diff --git a/flameshot.pro b/flameshot.pro index 0f368db..cec798d 100644 --- a/flameshot.pro +++ b/flameshot.pro @@ -5,6 +5,7 @@ #------------------------------------------------- win32:LIBS += -luser32 -lshell32 +QMAKE_CXXFLAGS += -Wno-deprecated-declarations TAG_VERSION = $$system(git --git-dir $$PWD/.git --work-tree $$PWD describe --always --tags) isEmpty(TAG_VERSION){ @@ -16,12 +17,15 @@ DEFINES += WNCK_I_KNOW_THIS_IS_UNSTABLE CONFIG += console QT += core gui widgets network svg +QT += x11extras unix:!macx { QT += dbus } CONFIG += c++11 link_pkgconfig + +PKGCONFIG += x11 PKGCONFIG += klog-qt5 PKGCONFIG += kiran-style-helper diff --git a/src/core/controller.cpp b/src/core/controller.cpp index ab46a4b..36abfbf 100644 --- a/src/core/controller.cpp +++ b/src/core/controller.cpp @@ -325,4 +325,4 @@ void Controller::doLater(int msec, QObject *receiver, lambda func) { [timer, func](){ func(); timer->deleteLater(); }); timer->setInterval(msec); timer->start(); -} +} \ No newline at end of file diff --git a/src/widgets/capture/capturewidget.cpp b/src/widgets/capture/capturewidget.cpp index 5985d21..5f05b25 100644 --- a/src/widgets/capture/capturewidget.cpp +++ b/src/widgets/capture/capturewidget.cpp @@ -240,7 +240,6 @@ void CaptureWidget::initOriginUI() m_zoomIndicator = new ZoomIndicator(this); m_zoomIndicator->hide(); - m_isFirstReleaseButton = false; } @@ -406,7 +405,8 @@ void CaptureWidget::paintEvent(QPaintEvent *) { QString helpTxt = tr("Press Enter to capture the screen." "\nUse the Mouse Wheel to change the thickness of your tool." "\nUse ctrl+c to save the picture to the clipboard." - "\nUse ctrl+s to save the picture to the set location."); + "\nUse ctrl+s to save the picture to the set location." + "\nUse ctrl+d open capture window mode."); // We draw the white contrasting background for the text, using the //same text and options to get the boundingRect that the text will have. @@ -566,7 +566,35 @@ void CaptureWidget::mouseMoveEvent(QMouseEvent *e) { //QRect m_backgroundRect = m_selection->geometry(); QPoint topLeft = m_backgroundRect.topLeft() * devicePixelRatioF(); - if(curPos.x() + INDICATOR_WIDTH > m_context.desktop->screenGeometry().width() - 120) + //Active windows select mode + if (activeWindowSelectMode) + { + // new rect for active window + int minWith = INT_MAX; + int minHeight = INT_MAX; + int windowX = 0; + int windowY = 0; + + for (auto win : m_wnds) + { + if (win.contains(curPos)) + { + if (minWith > win.width() && minHeight > win.height()) + { + minWith = win.width(); + minHeight = win.height(); + windowX = win.x(); + windowY = win.y(); + } + //new m_selection + } + m_selection->setVisible(true); + m_selection->setGeometry(QRect(windowX, windowY, minWith, minHeight).normalized()); + update(); + } + } + + if (curPos.x() + INDICATOR_WIDTH > m_context.desktop->screenGeometry().width() - 120) { tmpPos.setX(curPos.x() - INDICATOR_WIDTH); } @@ -971,6 +999,8 @@ void CaptureWidget::initSelection() { }); m_selection->setVisible(false); m_selection->setGeometry(QRect()); + // 初始化要捕获的窗口 + getActiveWindow(); } void CaptureWidget::setState(CaptureButton *b) { @@ -1187,6 +1217,7 @@ void CaptureWidget::initShortcuts() { new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_S), this, SLOT(saveScreenshot())); new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_C), this, SLOT(copyScreenshot())); new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Z), this, SLOT(undo())); + new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_D), this, SLOT(setActiveWindowSelectMode())); new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Z), this, SLOT(redo())); new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Right), this, SLOT(rightResize())); new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Left), this, SLOT(leftResize())); @@ -1419,3 +1450,64 @@ void CaptureWidget::saveFullScreen() { saveScreenshot(); } + +void CaptureWidget::setActiveWindowSelectMode() +{ + activeWindowSelectMode = true; + m_showInitialMsg = false; + update(); +} + +void CaptureWidget::getActiveWindow() +{ + auto display = XOpenDisplay(nullptr); + // todo: 只获取了默认的屏幕,在多屏幕下无法获取到其他屏幕的窗口 + auto root_window = DefaultRootWindow(display); + + Window root_return, parent_return; + Window* child_list = nullptr; + unsigned int child_num = 0; + // 按z-order顺序获取根屏幕的所有子屏幕,也就是所有的窗口 + XQueryTree(display, root_window, &root_return, &parent_return, &child_list, &child_num); + // 绝大部分窗口可以排除,也许可以给出一个常量,比如20(20个需要关注的可见窗口) + m_wnds.reserve(child_num); + for (auto i = child_num; (int)i >= 0; i--) + { + XWindowAttributes attrs; + // 获取窗口相关数据 + XGetWindowAttributes(display, child_list[i], &attrs); + int screenX = 0; + int screenY = 0; + Window childWin; + // 坐标系转换 + XTranslateCoordinates(display, child_list[i], root_window, 0, 0, &screenX, &screenY, &childWin); + // 过滤掉不可见的窗口 + if (attrs.map_state != IsViewable) + { + continue; + } + auto cur_wnd = QRect(screenX, screenY, attrs.width, attrs.height); + auto is_coverd = false; + // 只能判断是否被一个窗口遮挡,如果被两个窗口拼接遮挡则判断不了 + if (m_wnds.isEmpty()) + { + m_wnds.append(cur_wnd); + } + for (auto wnd : m_wnds) + { + if (wnd.contains(cur_wnd, true)) + { + is_coverd = true; + break; + } + } + if (is_coverd) + { + is_coverd = false; + continue; + } + m_wnds.append(cur_wnd); + } + XFree(display); + XFree(child_list); +} \ No newline at end of file diff --git a/src/widgets/capture/capturewidget.h b/src/widgets/capture/capturewidget.h index 79246e4..d08aa4b 100644 --- a/src/widgets/capture/capturewidget.h +++ b/src/widgets/capture/capturewidget.h @@ -123,6 +123,7 @@ private slots: void setDrawThickness(const int &t); void setDrawRectStyle(const int &s); void setDrawLineStyle(const int &l); + void setActiveWindowSelectMode(); protected: void paintEvent(QPaintEvent *); @@ -156,6 +157,10 @@ protected: bool m_adjustmentButtonPressed; bool m_inselection = true; bool m_flag = false; + bool activeWindowSelectMode = false; //select active window + + // save active window + QVector m_wnds; private: void initSecondUI(); @@ -169,6 +174,7 @@ private: void pushToolToStack(); void makeChild(QWidget *w); void updateToolBar(QString toolName); + void getActiveWindow(); QRect extendedSelection() const; QRect extendedRect(QRect *r) const; diff --git a/src/widgets/capture/thicknesswidget.cpp b/src/widgets/capture/thicknesswidget.cpp index 3f6360b..5046201 100644 --- a/src/widgets/capture/thicknesswidget.cpp +++ b/src/widgets/capture/thicknesswidget.cpp @@ -97,6 +97,7 @@ QVector ThicknessWidget::handleMask() const { spacing += i*4; QRect *rect = new QRect(8 + i * 10 + spacing , 13 - i * 2 , (i+1)*4, (i+1)*4); areas.append(*rect); + delete rect; } return areas; } diff --git a/src/widgets/capture/toowidget.cpp b/src/widgets/capture/toowidget.cpp index 96d5fed..33428cf 100644 --- a/src/widgets/capture/toowidget.cpp +++ b/src/widgets/capture/toowidget.cpp @@ -127,6 +127,7 @@ QVector Toowidget::handleMask() const { for (int i = 0; i < m_colorList.size(); ++i) { QRect *rect = new QRect(102 + i * 22, 9, 12, 12); areas.append(*rect); + delete rect; } return areas; } diff --git a/translations/Internationalization_zh_CN.ts b/translations/Internationalization_zh_CN.ts index f8bbbe5..3bfd5d5 100644 --- a/translations/Internationalization_zh_CN.ts +++ b/translations/Internationalization_zh_CN.ts @@ -156,7 +156,8 @@ Press Enter to capture the screen. Use the Mouse Wheel to change the thickness of your tool. Use ctrl+c to save the picture to the clipboard. -Use ctrl+s to save the picture to the set location. +Use ctrl+s to save the picture to the set location. +Use ctrl+d open capture window mode. 按 Enter 键捕捉屏幕。 使用鼠标滚轮来改变绘画工具的宽度。 使用ctrl+c将图片保存到剪贴板。 @@ -164,7 +165,8 @@ Use ctrl+s to save the picture to the set location. 按 Enter 键捕捉屏幕。 使用鼠标滚轮来改变绘画工具的宽度。 使用ctrl+c将图片保存到剪贴板。 -使用ctrl+s将图片保存至设定位置。 +使用ctrl+s将图片保存至设定位置。 +使用ctrl+d打开窗口捕获模式。 -- 2.33.0