fix: 修复任务栏在智能隐藏模式下窗口拖动到任务栏下方没有隐藏的问题
1.计算窗口的位置和大小的时候,调用的接口获取到的数据不正确,已完善从上游xcb相关的接口获取其他相关的位置等数据,重新计算得到正确的窗口信息 2.松开鼠标的时候没有激活定时器处理,已增加松开鼠标后,对当前活动窗口的处理 Log: Influence: 任务栏设置为智能隐藏,在窗口移动到任务栏下方或者移出来,观察隐藏状态是否正确 Bug: https://pms.uniontech.com/bug-view-154513.html Change-Id: I2bcc4c0d922349a6c98636caab03bdf1a108964c
This commit is contained in:
parent
fc1f9038f0
commit
bb3473e74a
@ -141,21 +141,106 @@ std::string XCBUtils::getAtomName(XCBAtom atom)
|
||||
|
||||
Geometry XCBUtils::getWindowGeometry(XWindow xid)
|
||||
{
|
||||
Geometry ret;
|
||||
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(m_connect, xid);
|
||||
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(m_connect, xcb_drawable_t(xid));
|
||||
xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(m_connect, cookie, nullptr);
|
||||
if (reply) {
|
||||
if (!reply) {
|
||||
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);
|
||||
} else {
|
||||
std::cout << xid << " getWindowGeometry err" << std::endl;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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()
|
||||
@ -437,8 +522,19 @@ bool XCBUtils::isGoodWindow(XWindow xid)
|
||||
// TODO XCB下无_MOTIF_WM_HINTS属性
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -68,6 +68,15 @@ typedef struct {
|
||||
std::vector<BYTE> data; /** Rows, left to right and top to bottom of the CARDINAL ARGB */
|
||||
} 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 加读写锁
|
||||
class AtomCache {
|
||||
public:
|
||||
@ -270,6 +279,9 @@ public:
|
||||
// 注册事件
|
||||
void registerEvents(XWindow xid, uint32_t eventMask);
|
||||
|
||||
private:
|
||||
XWindow getDecorativeWindow(XWindow xid);
|
||||
WindowFrameExtents getWindowFrameExtents(XWindow xid);
|
||||
|
||||
private:
|
||||
xcb_connection_t *m_connect;
|
||||
|
@ -102,28 +102,44 @@ void X11Manager::listenXEventUseXlib()
|
||||
XEvent event;
|
||||
XNextEvent (dpy, &event);
|
||||
|
||||
if (event.type == DestroyNotify) {
|
||||
XDestroyWindowEvent *eD = (XDestroyWindowEvent *) (&event);
|
||||
switch (event.type) {
|
||||
case DestroyNotify: {
|
||||
XDestroyWindowEvent *eD = (XDestroyWindowEvent *)(&event);
|
||||
qDebug() << "DestroyNotify windowId=" << eD->window;
|
||||
|
||||
handleDestroyNotifyEvent(XWindow(eD->window));
|
||||
} else if (event.type == MapNotify) {
|
||||
break;
|
||||
}
|
||||
case MapNotify: {
|
||||
XMapEvent *eM = (XMapEvent *)(&event);
|
||||
qDebug() << "MapNotify windowId=" << eM->window;
|
||||
|
||||
handleMapNotifyEvent(XWindow(eM->window));
|
||||
} else if (event.type == ConfigureNotify ) {
|
||||
XConfigureEvent *eC = (XConfigureEvent *) (&event);
|
||||
break;
|
||||
}
|
||||
case ConfigureNotify: {
|
||||
XConfigureEvent *eC = (XConfigureEvent *)(&event);
|
||||
qDebug() << "ConfigureNotify windowId=" << eC->window;
|
||||
|
||||
handleConfigureNotifyEvent(XWindow(eC->window), eC->x, eC->y, eC->width, eC->height);
|
||||
} else if (event.type == PropertyNotify) {
|
||||
XPropertyEvent *eP = (XPropertyEvent *) (&event);
|
||||
break;
|
||||
}
|
||||
case PropertyNotify: {
|
||||
XPropertyEvent *eP = (XPropertyEvent *)(&event);
|
||||
qDebug() << "PropertyNotify windowId=" << eP->window;
|
||||
|
||||
handlePropertyNotifyEvent(XWindow(eP->window), XCBAtom(eP->atom));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
case UnmapNotify: {
|
||||
// 当松开鼠标的时候会触发该事件,在松开鼠标的时候,需要检测当前窗口是否符合智能隐藏的条件,因此在此处加上该功能
|
||||
// 如果不加上该处理,那么就会出现将窗口从任务栏下方移动到屏幕中央的时候,任务栏不隐藏
|
||||
handleActiveWindowChangedX();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
qDebug() << "Unknown event type " << event.type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user