Qt在Linux下实现无边框可缩放的窗口
序
在Linux平台上做desktop应用的还是非常少的。所以基本上网上这部分资料是没有的。Linux平台又不像Win那么多API。这次的实现,本来自己想写xlib的函数的,然后机智的我从deepin的代码里把他们封装好的抠出来了,然后补充了一些x11的封装函数。来完成最终的效果。
本篇文章纯粹抛砖引玉,毕竟只是个demo。简单的说一下遇到的坑。
代码
实现上很简单,重写qt的三个函数就可以。
void FLWidget_Linux::mouseMoveEvent(QMouseEvent *event)
{
#ifdef Q_OS_LINUX
const int x = event->x();
const int y = event->y();
if (resizingCornerEdge == XUtils::CornerEdge::kInvalid)
{
XUtils::UpdateCursorShape(this, x, y, this->layout()->contentsMargins(), ResizeHandleWidth);
}
#endif
return QWidget::mouseMoveEvent(event);
}
void FLWidget_Linux::mousePressEvent(QMouseEvent *event)
{
#ifdef Q_OS_LINUX
const int x = event->x();
const int y = event->y();
if (event->button() == Qt::LeftButton)
{
const XUtils::CornerEdge ce = XUtils::GetCornerEdge(this, x, y, this->layout()->contentsMargins(), ResizeHandleWidth);
if (ce != XUtils::CornerEdge::kInvalid)
{
resizingCornerEdge = ce;
//send x11 move event dont send mouserrelease event
XUtils::SendButtonRelease(this, event->pos(), event->globalPos());
XUtils::StartResizing(this, QCursor::pos(), ce);
}
}
#endif
return QWidget::mousePressEvent(event);
void FLWidget_Linux::mouseReleaseEvent(QMouseEvent *event)
{
#ifdef Q_OS_LINUX
resizingCornerEdge = XUtils::CornerEdge::kInvalid;
#endif
return QWidget::mouseReleaseEvent(event);
}
只重写这三个函数就可以完成对应的功能,当然还得有XUtils。
XUtils是deepin封装的一个功能namespace。封装了常用的xlib操作qt的widget的一些函数。
然后我补充了一个他们的函数
主要是调用的xlib的mousemove之后,Qt接受不到release事件,需要手动再发一个
XUtils::SendButtonRelease(this, event->pos(), event->globalPos());
void SendButtonRelease(const QWidget *widget,
const QPoint &pos, const QPoint &globalPos)
{
const auto display = QX11Info::display();
const auto screen = QX11Info::appScreen();
XEvent xevent;
memset(&xevent, 0, sizeof(XEvent));
xevent.type = ButtonRelease;
xevent.xbutton.button = Button1;
xevent.xbutton.window = widget->effectiveWinId();
xevent.xbutton.x = pos.x();
xevent.xbutton.y = pos.y();
xevent.xbutton.x_root = globalPos.x();
xevent.xbutton.y_root = globalPos.y();
xevent.xbutton.display = display;
XSendEvent(display, widget->effectiveWinId(), False, ButtonReleaseMask, &xevent);
XFlush(display);
}
昨天整理了下文档,发到github上了,欢迎star跟fork
https://github.com/CryFeiFei/FLWidget