因为日常Linux办公,经常有截图顺带简单编辑的需求。
在Windows上这项工作基本一直是QQ微信代劳,但是在Linux上这两个都比较拉胯,无奈之下找了几种Linux下的截图工具替代
试了几个比较流行的,感觉下来最好用的算是flameshot
,功能齐全运行稳定,图标也挺新潮,操作界面也很简洁,基本毛病没得挑。但唯一的缺点就是:没有全局热键。
好在flameshot
是个开源软件,下下来源码瞅了一眼,是我熟悉的Qt写的,感觉全局热键这部分可以自己整合一下。
源码中对全局热键的实现只放开了windows
,而且从源码来看好像也只预留了接口没实现功能。简单研究了一下,通过一个名为qxtglobalshortcut5
的Qt全局热键第三方库可以轻松实现
先把现成的工具放出来吧,伸手党福利:
https://kdocs.cn/l/sgGCbHx3wSaM
[金山文档] flameshot
Take Screenshot
即可截图nohup ...... &
启动,不占用终端。ubuntu16.04
源内自带的库编译的,所以仅仅适用于ubuntu 16.04。换到其他Linux系统不一定能用。其他Linux平台会因为不自带qt或者自带qt库版本不一样导致不能用的问题,最好的办法是自行下载编译,方法如下: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
都直接从源里下,这样能保证都是配套同一个版本的。
地址: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
五、中文输入法支持
在Linux下Qt编译出来的程序默认都不支持切换输入法,导致截图编辑的时候无法输入中文。
解决方案很简单:sudo apt-get install fcitx-frontend-qt5
安装这个库之后,再重新编译flameshot
程序就可以了。
这个解决方案的原理,实质上是安装了
/usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.so
这个库,有了这个库,再使用系统的Qt编译出的程序就都可以使用fcitx类型的中文输入法(搜狗就是这种)
如果你是用的是自己安装的其他版本的Qt,那么你需要:
- 下载
fcitx-qt5
的源码- 用自己的Qt编译源码生成
libfcitxplatforminputcontextplugin.so
库- 把这个库放到你qt安装目录的:
qt/5.7/gcc_64/plugins/platforminputcontexts/
目录下 (我这里是5.7)- 重新编译程序就可以了
- 此处参考:https://www.cnblogs.com/fox-Benjiaming/p/11738092.html:
编译好后可以试一下,生成的可执行程序运行后可以通过全局热键Ctrl+F5
进行截屏编辑操作。
这个改动非常简单,通篇使用的是Ubuntu源内自带的工具和库。即使没怎么接触过qt的人,按照上面的套路也可以把这个工具轻松整出来。
如果是Qt老炮,可以通过本地编译出来或者本地安装的其他版本的qt编译这个程序,目前尝试qt5.5.1全局热键还是有点问题的,上面也提到了。我本地用的qt5.7没有这个问题。
理论上可以点击截图的地方,完全用不到全局热键,只对一种场景对全局热键截图
这个功能有刚需:失去焦点窗体就消失的情况。比如,你在chorme
浏览器的某个标签页上右键弹出一个对话框,你想截图这个对话框里的内容,但是一旦你鼠标去点击截图的按钮,这个对话框就会因为失去焦点而消失。这个时候就需要截图全局热键的功能来实现:
或者对一些tooltips
的截图也是这样:
但遗憾的是,在Linux平台上它不能非常完美的解决所有“失焦即焚”窗体的问题,比如说你随便打开一个窗口,鼠标挪到左上角随便点一个选项卡(文件、修改、视图等等的),当他出现菜单时,你想截图这个菜单的内容,你就会发现全局热键不好使了:
当这个红框窗体拿到焦点的时候,全局热键就不好使了,为了让全局热键生效让他失去焦点,这个窗体又会消失。进入到一种无法截图的尴尬境地。(我这张是对着虚拟机截出来的)
但这个问题并不是qxtglobalshortcut5
实现的问题,而是X11本身的限制,一个直观的证据就是:在这种情况下,你键盘上的PrintScreen
按键也会失效。
为了这个问题大概看了下qxtglobalshortcut5
的Linux部分的实现,确实已经是x11提供的XGrabKey
所能提供功能的极限了,如果硬要让自己全局热键的优先级高于窗口管理器,可能得写驱动级别的程序来搞。