fix: 修复任务栏在智能隐藏模式下窗口拖动到任务栏下方没有隐藏的问题

1.计算窗口的位置和大小的时候,调用的接口获取到的数据不正确,已完善从上游xcb相关的接口获取其他相关的位置等数据,重新计算得到正确的窗口信息
2.松开鼠标的时候没有激活定时器处理,已增加松开鼠标后,对当前活动窗口的处理

Log:
Influence: 任务栏设置为智能隐藏,在窗口移动到任务栏下方或者移出来,观察隐藏状态是否正确
Bug: https://pms.uniontech.com/bug-view-154513.html
Change-Id: I2bcc4c0d922349a6c98636caab03bdf1a108964c
This commit is contained in:
donghualin 2022-10-13 05:36:33 +00:00
parent fc1f9038f0
commit bb3473e74a
3 changed files with 143 additions and 19 deletions

View File

@ -141,23 +141,108 @@ std::string XCBUtils::getAtomName(XCBAtom atom)
Geometry XCBUtils::getWindowGeometry(XWindow xid) Geometry XCBUtils::getWindowGeometry(XWindow xid)
{ {
Geometry ret; xcb_get_geometry_cookie_t cookie = xcb_get_geometry(m_connect, xcb_drawable_t(xid));
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(m_connect, xid);
xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(m_connect, cookie, nullptr); xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(m_connect, cookie, nullptr);
if (reply) { if (!reply) {
ret.x = reply->x;
ret.y = reply->y;
ret.width = reply->width;
ret.height = reply->height;
free(reply);
} else {
std::cout << xid << " getWindowGeometry err" << std::endl; std::cout << xid << " getWindowGeometry err" << std::endl;
return Geometry();
} }
Geometry ret;
ret.x = reply->x;
ret.y = reply->y;
ret.width = reply->width;
ret.height = reply->height;
free(reply);
const xcb_setup_t *xcbSetup = xcb_get_setup(m_connect);
if (!xcbSetup)
return Geometry();
xcb_screen_iterator_t xcbScreenIterator = xcb_setup_roots_iterator(xcbSetup);
xcb_translate_coordinates_reply_t *translateReply =
xcb_translate_coordinates_reply(m_connect,
xcb_translate_coordinates(m_connect, xid, xcbScreenIterator.data->root, 0, 0),
nullptr);
if (translateReply) {
ret.x = translateReply->dst_x;
ret.y = translateReply->dst_y;
free(translateReply);
}
XWindow dWin = getDecorativeWindow(xid);
reply = xcb_get_geometry_reply(m_connect, xcb_get_geometry(m_connect, xcb_drawable_t(dWin)), nullptr);
if (!reply)
return ret;
if (reply->x == ret.x && reply->y == ret.y) {
// 无标题的窗口比如deepin-editor, dconf-editor等
WindowFrameExtents windowFrameRect = getWindowFrameExtents(xid);
if (!windowFrameRect.isNull()) {
int x = ret.x + windowFrameRect.Left;
int y = ret.y + windowFrameRect.Top;
int width = ret.width - (windowFrameRect.Left + windowFrameRect.Right);
int height = ret.height - (windowFrameRect.Top + windowFrameRect.Bottom);
ret.x = x;
ret.y = y;
ret.width = width;
ret.height = height;
}
}
free(reply);
return ret; return ret;
} }
XWindow XCBUtils::getDecorativeWindow(XWindow xid)
{
XWindow winId = xid;
for (int i = 0; i < 10; i++) {
xcb_query_tree_cookie_t cookie = xcb_query_tree(m_connect, winId);
xcb_query_tree_reply_t *reply = xcb_query_tree_reply(m_connect, cookie, nullptr);
if (!reply)
return 0;
if (reply->root == reply->parent)
return winId;
winId = reply->parent;
}
return 0;
}
WindowFrameExtents XCBUtils::getWindowFrameExtents(XWindow xid)
{
xcb_atom_t perp = getAtom("_NET_FRAME_EXTENTS");
xcb_get_property_cookie_t cookie = xcb_get_property(m_connect, false, xid, perp, XCB_ATOM_CARDINAL, 0, 4);
xcb_get_property_reply_t *reply = xcb_get_property_reply(m_connect, cookie, nullptr);
if (!reply || reply->format == 0) {
if (reply)
free(reply);
perp = getAtom("_GTK_FRAME_EXTENTS");
cookie = xcb_get_property(m_connect, false, xid, perp, XCB_ATOM_CARDINAL, 0, 4);
reply = xcb_get_property_reply(m_connect, cookie, nullptr);
if (!reply)
return WindowFrameExtents();
}
if (reply->format != 32 || reply->value_len != 4) {
free(reply);
return WindowFrameExtents();
}
uint32_t *data = static_cast<uint32_t *>(xcb_get_property_value(reply));
free(reply);
if (!data)
return WindowFrameExtents();
WindowFrameExtents winFrame(data[0], data[1], data[2], data[3]);
return winFrame;
}
XWindow XCBUtils::getActiveWindow() XWindow XCBUtils::getActiveWindow()
{ {
XWindow ret; XWindow ret;
@ -437,8 +522,19 @@ bool XCBUtils::isGoodWindow(XWindow xid)
// TODO XCB下无_MOTIF_WM_HINTS属性 // TODO XCB下无_MOTIF_WM_HINTS属性
MotifWMHints XCBUtils::getWindowMotifWMHints(XWindow xid) MotifWMHints XCBUtils::getWindowMotifWMHints(XWindow xid)
{ {
MotifWMHints ret; XCBAtom atomWmHints = getAtom("_MOTIF_WM_HINTS");
xcb_get_property_cookie_t cookie = xcb_get_property(m_connect, false, xid, atomWmHints, atomWmHints, 0, 5);
xcb_get_property_reply_t *reply = xcb_get_property_reply(m_connect, cookie, nullptr);
if (!reply || reply->format != 32 || reply->value_len != 5)
return MotifWMHints{0, 0, 0, 0, 0};
uint32_t *data = static_cast<uint32_t *>(xcb_get_property_value(reply));
MotifWMHints ret;
ret.flags = data[0];
ret.functions = data[1];
ret.decorations = data[2];
ret.inputMode = data[3];
ret.status = data[4];
return ret; return ret;
} }

View File

@ -68,6 +68,15 @@ typedef struct {
std::vector<BYTE> data; /** Rows, left to right and top to bottom of the CARDINAL ARGB */ std::vector<BYTE> data; /** Rows, left to right and top to bottom of the CARDINAL ARGB */
} WMIcon; } WMIcon;
typedef struct WindowFrameExtents {
uint32_t Left;
uint32_t Right;
uint32_t Top;
uint32_t Bottom;
WindowFrameExtents(int left = 0, int right = 0, int top = 0, int bottom = 0): Left(left), Right(right), Top(top), Bottom(bottom) {}
bool isNull() { return Left == 0 && Right == 0 && Top == 0 && Bottom == 0;}
} WindowFrameExtents;
// 缓存atom减少X访问 TODO 加读写锁 // 缓存atom减少X访问 TODO 加读写锁
class AtomCache { class AtomCache {
public: public:
@ -270,6 +279,9 @@ public:
// 注册事件 // 注册事件
void registerEvents(XWindow xid, uint32_t eventMask); void registerEvents(XWindow xid, uint32_t eventMask);
private:
XWindow getDecorativeWindow(XWindow xid);
WindowFrameExtents getWindowFrameExtents(XWindow xid);
private: private:
xcb_connection_t *m_connect; xcb_connection_t *m_connect;

View File

@ -102,28 +102,44 @@ void X11Manager::listenXEventUseXlib()
XEvent event; XEvent event;
XNextEvent (dpy, &event); XNextEvent (dpy, &event);
if (event.type == DestroyNotify) { switch (event.type) {
XDestroyWindowEvent *eD = (XDestroyWindowEvent *) (&event); case DestroyNotify: {
XDestroyWindowEvent *eD = (XDestroyWindowEvent *)(&event);
qDebug() << "DestroyNotify windowId=" << eD->window; qDebug() << "DestroyNotify windowId=" << eD->window;
handleDestroyNotifyEvent(XWindow(eD->window)); handleDestroyNotifyEvent(XWindow(eD->window));
} else if (event.type == MapNotify) { break;
}
case MapNotify: {
XMapEvent *eM = (XMapEvent *)(&event); XMapEvent *eM = (XMapEvent *)(&event);
qDebug() << "MapNotify windowId=" << eM->window; qDebug() << "MapNotify windowId=" << eM->window;
handleMapNotifyEvent(XWindow(eM->window)); handleMapNotifyEvent(XWindow(eM->window));
} else if (event.type == ConfigureNotify ) { break;
XConfigureEvent *eC = (XConfigureEvent *) (&event); }
case ConfigureNotify: {
XConfigureEvent *eC = (XConfigureEvent *)(&event);
qDebug() << "ConfigureNotify windowId=" << eC->window; qDebug() << "ConfigureNotify windowId=" << eC->window;
handleConfigureNotifyEvent(XWindow(eC->window), eC->x, eC->y, eC->width, eC->height); handleConfigureNotifyEvent(XWindow(eC->window), eC->x, eC->y, eC->width, eC->height);
} else if (event.type == PropertyNotify) { break;
XPropertyEvent *eP = (XPropertyEvent *) (&event); }
case PropertyNotify: {
XPropertyEvent *eP = (XPropertyEvent *)(&event);
qDebug() << "PropertyNotify windowId=" << eP->window; qDebug() << "PropertyNotify windowId=" << eP->window;
handlePropertyNotifyEvent(XWindow(eP->window), XCBAtom(eP->atom)); handlePropertyNotifyEvent(XWindow(eP->window), XCBAtom(eP->atom));
} else { break;
}
case UnmapNotify: {
// 当松开鼠标的时候会触发该事件,在松开鼠标的时候,需要检测当前窗口是否符合智能隐藏的条件,因此在此处加上该功能
// 如果不加上该处理,那么就会出现将窗口从任务栏下方移动到屏幕中央的时候,任务栏不隐藏
handleActiveWindowChangedX();
break;
}
default:
qDebug() << "Unknown event type " << event.type; qDebug() << "Unknown event type " << event.type;
break;
} }
} }