我创建了一个 TrayPopupWidget,它应该在托盘附近弹出。 然后我意识到,如果用户更改任务栏的方向或高度,它会在错误的位置弹出。所以我创建了 TaskbarDetector 类。
我试图获取托盘|任务栏的窗口几何形状,但我只得到错误的窗口属性...... 我尝试过 KDE、LXDE -> 同样的不良行为...
//Getting screen resolutoin
int num_sizes;
Rotation original_rotation;
Display *display = XOpenDisplay(NULL);
Window root = RootWindow(display, 0);
XRRScreenSize *xrrs = XRRSizes(display, 0, &num_sizes);
XRRScreenConfiguration *conf = XRRGetScreenInfo(display, root);
XRRConfigCurrentRate(conf);
SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation);
p_screenWidth = xrrs[original_size_id].width;
p_screenHeight = xrrs[original_size_id].height;
//Getting tray position
unsigned long sysTraySelection = 0;
Screen *screen = XDefaultScreenOfDisplay(display);
//FIXME !!!
QString *net_sys_tray = new QString("_NET_SYSTEM_TRAY_S%i");
(*net_sys_tray) = net_sys_tray->replace ("%i",QString::number (XScreenNumberOfScreen(screen)));
sysTraySelection = XInternAtom(display, net_sys_tray->toLocal8Bit (), False);
if ( sysTraySelection == None)
return Unknown;
trayWindow = XGetSelectionOwner(display, sysTraySelection);
XWindowAttributes w_attr;
unsigned long status = XGetWindowAttributes (display,trayWindow,&w_attr);
if ( status == 0)
return Unknown;
p_taskBarLeft = w_attr.y;
p_taskBarTop = w_attr.x;
p_taskBarBottom = w_attr.x + w_attr.height;
p_taskBarRight = w_attr.y + w_attr.width;
qDebug () << QString("Window id: " ) + QString::number (trayWindow);
qDebug() << QString("SysTraySelection: ") + QString::number (sysTraySelection );
qDebug() << QString("Top ") + QString::number (p_taskBarTop);
qDebug() << QString("Left ") + QString::number (p_taskBarLeft);
qDebug() << QString("Bottom ") + QString::number (p_taskBarBottom);
qDebug() << QString("Right " ) + QString::number (p_taskBarRight);
XCloseDisplay(display);
delete net_sys_tray;
return decideOrientation ();
最佳答案
终于,我找到了检测它的方法!
- 我正在搜索一个具有停靠属性且可见的窗口,然后我对其调用 XGetWindowAttributes(...)。
- 如果我为 QApplication::setEventFilter() 设置过滤方法,我也可以获得每个 XEvent、_NET_WORKAREA 事件(当您调整大小或移动任务栏时会发生此事件),然后我重新调用任务栏/托盘检测方法。
但是,这在 KDE4 和 GNOME 和 LXDE 上都有效,我计划允许用户自己设置弹出位置。
bool TaskBarDetector::lookUpDockWindow ( unsigned long &rootWindow, bool check)
{
Display *display = QX11Info::display ();
Window parent;
Window *children;
unsigned int noOfChildren;
int status;
if ( check && checkDockProperty(rootWindow) )
{
trayWindow = rootWindow;
return true;
}
status = XQueryTree (display, rootWindow, &rootWindow, &parent, &children, &noOfChildren);
if (status == 0)
{
qDebug() << "ERROR - Could not query the window tree. Aborting.";
trayWindow = 0;
return false;
}
if (noOfChildren == 0)
{
trayWindow = 0;
return false;
}
for (unsigned int ind = 0 ; ind < noOfChildren; ++ind )
{
if ( lookUpDockWindow ( children[ind] ,true) )
return true;
}
XFree ((char*) children);
trayWindow = 0;
return false;
}
bool TaskBarDetector::checkDockProperty(unsigned long window)
{
Display *x11display = QX11Info::display ();
Atom *atoms;
int numberAtoms = 0;
char *atomName;
XTextProperty prop;
XWindowAttributes windowattr;
atoms = XListProperties (x11display, window, &numberAtoms);
for (int ind = 0; ind < numberAtoms; ++ind )
{
atomName = XGetAtomName(x11display, atoms[ind]);
if (QString(atomName).compare ("_NET_WM_WINDOW_TYPE" ) != 0 )
continue;
unsigned long status = XGetTextProperty (x11display,window,&prop,atoms[ind]);
if ( status == 0 )
continue;
int value = (int) (*prop.value);
if (value != 151 )
continue;
if (XGetWindowAttributes(x11display,window,&windowattr) == 0)
continue;
return windowattr.map_state == 2;
}
return false;
}
void TaskBarDetector::saveWindowAttr(unsigned long root)
{
XWindowAttributes windowattr;
Display *x11display =QX11Info::display ();
if (XGetWindowAttributes(x11display,trayWindow,&windowattr) == 0)
{
trayWindow = 0;
return;
}
int x = 0;
int y = 0;
Window *w = &trayWindow;
if( XTranslateCoordinates(x11display,trayWindow,root,windowattr.x,windowattr.y,&x,&y,w) == True)
{
p_taskBarTop = y;
p_taskBarLeft = x;
p_taskBarRight = p_taskBarLeft + windowattr.width;
p_taskBarBottom = p_taskBarTop + windowattr.height;
p_taskBarHeight = windowattr.height;
p_taskBarWidth = windowattr.width;
} else
{
p_orientation = Unknown;
p_taskBarTop = 0;
p_taskBarLeft = 0;
p_taskBarRight = 0;
p_taskBarBottom = 0;
p_taskBarHeight = 0;
p_taskBarWidth = 0;
}
bool TaskBarDetector::appEventFilter(void *msg, long *result)
{
Q_UNUSED(result);
if ( !TaskBarDetector::hasInstance() )
return false;
TaskBarDetector *detector = TaskBarDetector::getInstance();
#ifdef Q_WS_WIN
MSG *seged = static_cast<MSG*>(msg);
if ( seged->message == WM_SETTINGCHANGE && seged->wParam == SPI_SETWORKAREA )
{
detector->processDetectEvent();
return false;
}
return false;
#endif
#ifdef Q_WS_X11
XEvent *xevent = static_cast<XEvent*> (msg);
if ( xevent->type == PropertyNotify )
{
XPropertyEvent xpe = xevent->xproperty;
char * ch_atom_name = XGetAtomName(QX11Info::display(),xpe.atom);
QString atom_name = QString(ch_atom_name).trimmed ();
if ( atom_name == "_NET_WORKAREA" )
{
detector->processDetectEvent ();
return false;
}
}
return false;
#endif
}
}
关于c++ - 检测系统托盘\任务栏方向(X11),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10658463/