公衆号關注 “五分鐘學算法”
因為日常Linux辦公,經常有截圖順帶簡單編輯的需求。
在Windows上這項工作基本一直是QQ微信代勞,但是在Linux上這兩個都比較拉胯,無奈之下找了幾種Linux下的截圖工具替代
試了幾個比較流行的,感覺下來最好用的算是
flameshot
,功能齊全運作穩定,圖示也挺新潮,操作界面也很簡潔,基本毛病沒得挑。但唯一的缺點就是:「沒有全局熱鍵。」
好在
flameshot
是個開源軟體,下下來源碼瞅了一眼,是我熟悉的Qt寫的,感覺全局熱鍵這部分可以自己整合一下。
源碼中對全局熱鍵的實作隻放開了
windows
,而且從源碼來看好像也隻預留了接口沒實作功能。簡單研究了一下,通過一個名為
qxtglobalshortcut5
的Qt全局熱鍵第三方庫可以輕松實作
使用
先把現成的工具放出來吧,伸手黨福利:https://kdocs.cn/l/sgGCbHx3wSaM [金山文檔] flameshot
- 複制連結到浏覽器直接下載下傳,啟動後工作列會有圖示,點選
即可截圖Take Screenshot
- 點選一次截圖後,全局熱鍵才可以使用。“Ctrl + F5” 即可觸發截圖(ubuntu源内自帶的qt5.5編譯會有這個問題,qt5.7編譯出的程式直接啟動後全局熱鍵就可以用)。
- 自己編譯的話是有翻譯的,這裡單程式沒有翻譯檔案,是以都是英文,不過不影響使用。
- 效果如圖:具體的使用快捷鍵和功能去其他地方查一下吧,我就不搬運了,都是很基本的截圖編輯操作,好用得很:
- 建議在設定裡開機自啟,或者加
啟動,不占用終端。nohup ...... &
- 這個程式我是用的
源内自帶的庫編譯的,是以僅僅适用于ubuntu 16.04。換到其他Linux系統不一定能用。其他Linux平台會因為不自帶qt或者自帶qt庫版本不一樣導緻不能用的問題,最好的辦法是自行下載下傳編譯,方法如下:ubuntu16.04
編譯(Ubuntu 16.04環境)
環境準備
Ubuntu16.04自帶了一些Qt5.5.1的核心庫,但是要編譯的話還需要
qmake
,
lrelease
等工具,還有
x11extras
svg
等qt插件支援,需要安裝:
sudo apt-get install qt5-default
sudo apt-get install qttools5-dev-tools
sudo apt-get install libqt5svg5-dev
sudo apt-get install libqt5x11extras5-dev
sudo apt-get install qtbase5-private-dev
都直接從源裡下,這樣能保證都是配套同一個版本的。
擷取flameshot源碼:
位址:
https://github.com/lupoDharkael/flameshot.git
git clone https://github.com/lupoDharkael/flameshot.git
編譯源碼
cd flameshot
mkdir build
cd build
qmake ../
# 報錯沒有qmake的話,要裝上面的庫
make -j`nproc`
sudo ln -sf `pwd`/flameshot /usr/bin/flameshot
編譯完成後,會生成一個可執行檔案
flameshot
,可以直接放一個軟連接配接到
/usr/bin
下面
增加全局熱鍵功能
一、擷取qxtglobalshortcut5項目到此項目中
# 離開剛才的編譯目錄
cd ../
# pwd: ~/flameshot
git clone https://github.com/ddqd/qxtglobalshortcut5.git
flameshot
項目和
qxtglobalshortcut5
這個項目都是qt的pro管理的,整合起來非常友善 在擷取到
qxtglobalshortcut5
項目後,
flameshot
項目下就有這個玩意兒:
qxtglobalshortcut5
的實作已經相當完善了,引入後一行都不需要改,隻需要改寫
flameshot
項目 在
flameshot.pro
檔案中添加一行:
include(qxtglobalshortcut5/qxt.pri)
QT += core gui widgets network svg
unix:!macx {
QT += dbus
}
CONFIG += c++11 link_pkgconfig
include(qxtglobalshortcut5/qxt.pri) # 這一行是新加的
#CONFIG += packaging # Enables "make install" for packaging paths
TARGET = flameshot
TEMPLATE = app
二、源碼裡注冊全局熱鍵
打開
src/core/controller.cpp
這個檔案,找到Controller的構造函數,在這裡注冊全局熱鍵:
Controller::Controller() : m_captureWindow(nullptr) {
qApp->setQuitOnLastWindowClosed(false);
// init tray icon
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
if (!ConfigHandler().disabledTrayIconValue()) {
enableTrayIcon();
}
/** 注冊全局熱鍵! */
QxtGlobalShortcut* shortcut1 = new QxtGlobalShortcut(QKeySequence("Ctrl+F5"), this);
/** 全局熱鍵觸發的函數! */
connect(shortcut1, SIGNAL(activated()), this, SLOT(shortcutActiveCapture()));
#elif defined(Q_OS_WIN)
enableTrayIcon();
GlobalShortcutFilter *nativeFilter = new GlobalShortcutFilter(this);
qApp->installNativeEventFilter(nativeFilter);
connect(nativeFilter, &GlobalShortcutFilter::printPressed,
this, [this](){
this->requestCapture(CaptureRequest(CaptureRequest::GRAPHICAL_MODE));
});
#endif
QString StyleSheet = CaptureButton::globalStyleSheet();
qApp->setStyleSheet(StyleSheet);
}
這裡除了注釋的兩行是我加的,其他都是原來的代碼,這個庫支援字元串的形式注冊全局熱鍵,
Ctrl+F5
可以換成你自己喜歡的。
因為沒有在
Window
上測試過們這裡隻加給了
Q_OS_LINUX
環境,理論上這個全局熱鍵的庫各平台都是通用的,不過我隻需要Linux。
三、全局熱鍵的處理函數
上面給
shortchut1
注冊了一個槽函數
shortcutActiveCapture
,這個函數還沒有實作,這個函數的功能很簡單,隻需要調用截圖函數就行,可以查一下我們點選截圖觸發的是哪一個函數,我們也調用同一個函數即可:
-
檔案,在頭檔案裡,添加函數聲明:src/core/controller.h
private slots:
void startFullscreenCapture(const uint id = 0);
void startVisualCapture(const uint id = 0,
const QString &forcedSavePath = QString());
void startScreenGrab(const uint id = 0, const int screenNumber = -1);
void handleCaptureTaken(uint id, QPixmap p);
void handleCaptureFailed(uint id);
void shortcutActiveCapture(); //這一句是追加的
-
檔案,在實作檔案裡,添加函數實作:src/core/controller.cpp
void Controller::shortcutActiveCapture()
{
this->startVisualCapture(0,QString());
}
「四、重新編譯運作」
進入到剛才的編譯目錄,重新執行qmake,make編譯就可以了。
cd build
qmake ../
make
編譯好後可以試一下,生成的可執行程式運作後可以通過全局熱鍵
Ctrl+F5
進行截屏編輯操作。
這個改動非常簡單,通篇使用的是Ubuntu源内自帶的工具和庫。即使沒怎麼接觸過qt的人,按照上面的套路也可以把這個工具輕松整出來。
如果是Qt老炮,可以通過本地編譯出來或者本地安裝的其他版本的qt編譯這個程式,目前嘗試qt5.5.1全局熱鍵還是有點問題的,上面也提到了。我本地用的qt5.7沒有這個問題。
存在問題:失去焦點就消失的窗體
理論上可以點選截圖的地方,完全用不到全局熱鍵,隻有一種場景對
全局熱鍵截圖
這個功能有剛需:失去焦點窗體就消失的情況。比如,你在
chorme
浏覽器的某個标簽頁上右鍵彈出一個對話框,你想截圖這個對話框裡的内容,但是一旦你滑鼠去點選截圖的按鈕,這個對話框就會因為失去焦點而消失。這個時候就需要截圖全局熱鍵的功能來實作:
或者對一些滑鼠懸停才會顯示的内容
tooltips
的截圖也是這樣:
但遺憾的是,在Linux平台上,這個全局快捷鍵截圖仍然不能非常完美的解決所有“失焦即焚”窗體的問題
比如說你随便打開一個視窗,滑鼠挪到左上角随便點一個頁籤(檔案、修改、視圖等等的),當他出現菜單時,你想截圖這個菜單的内容,你就會發現全局熱鍵不好使了:
當這個紅框窗體拿到焦點的時候,全局熱鍵就不好使了,為了讓全局熱鍵生效讓他失去焦點,這個窗體又會消失。進入到一種無法截圖的尴尬境地。(我這張是對着虛拟機截出來的)
但這個問題并不是
qxtglobalshortcut5
實作的問題,而是X11本身的限制,一個直覺的證據就是:在這種情況下,你鍵盤上的
PrintScreen
按鍵也會失效。
為了這個問題大概看了下
qxtglobalshortcut5
的Linux部分的實作,确實已經是x11提供的
XGrabKey
所能提供功能的極限了,如果硬要讓自己全局熱鍵的優先級高于視窗管理器,可能得寫驅動級别的程式來搞。