Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 检测系统托盘\任务栏方向(X11)_C++_Qt_X11_Taskbar_Tray - Fatal编程技术网

C++ 检测系统托盘\任务栏方向(X11)

C++ 检测系统托盘\任务栏方向(X11),c++,qt,x11,taskbar,tray,C++,Qt,X11,Taskbar,Tray,我创建了一个TrayPopupWidget,应该会在托盘附近弹出。 然后我意识到,如果用户更改任务栏的方向或高度,它将在错误的位置弹出。所以我创建了TaskbarDetector类 我试图获得任务栏的窗口几何图形,但我只得到了错误的窗口属性。。。 我试过KDE,LXDE->同样的坏行为 守则: //获取屏幕分辨率 整数大小; 旋转-原始旋转; Display*Display=XOpenDisplay(空); 窗口根=根窗口(显示,0); XRRScreenSize*xrrs=XRRSizes(

我创建了一个TrayPopupWidget,应该会在托盘附近弹出。 然后我意识到,如果用户更改任务栏的方向或高度,它将在错误的位置弹出。所以我创建了TaskbarDetector类

我试图获得任务栏的窗口几何图形,但我只得到了错误的窗口属性。。。 我试过KDE,LXDE->同样的坏行为

守则:

//获取屏幕分辨率
整数大小;
旋转-原始旋转;
Display*Display=XOpenDisplay(空);
窗口根=根窗口(显示,0);
XRRScreenSize*xrrs=XRRSizes(显示、0和数量大小);
XRRScreenConfiguration*conf=XRRGetScreenInfo(显示,根目录);
XRRConfigCurrentRate(配置);
SizeID原始大小id=XRRConfigCurrentConfiguration(配置和原始旋转);
p_screenWidth=xrrs[原始大小\u id]。宽度;
p_screenHeight=xrrs[原始尺寸\u id]。高度;
//获取托盘位置
无符号长系统选择=0;
Screen*Screen=xDefaultScreen显示(显示);
//修正我!!!
QString*net\u系统托盘=新的QString(“\u net\u系统托盘%i”);
(*净系统托盘)=净系统托盘->替换(“%i”,QString::number(XScreenNumber of screen(screen));
sysTraySelection=XInternAtom(显示,网络系统托盘->本地8bit(),False);
如果(sysTraySelection==无)
返回未知;
trayWindow=XGetSelectionOwner(显示、系统选择);
XWindowAttributes w_attr;
unsigned long status=XGetWindowAttributes(显示、trayWindow和w_属性);
如果(状态==0)
返回未知;
p_taskBarLeft=w_attr.y;
p_taskBarTop=w_attr.x;
p_taskBarBottom=w_attr.x+w_attr.height;
p_taskBarRight=w_属性y+w_属性宽度;

qDebug()系统托盘本身不一定是一个窗口。在KDE中,这只是任务栏中的一个区域(它与
\u NET\u SYSTEM\u TRAY\u S%i
选择所有者无关)

您可能希望尝试嵌入一个托盘图标并获取其几何图形,然后显示您的小部件“near”所述图标(对于一些合理的“near”值)。一旦知道图标的几何图形,就可以删除它(但是如果用户移动托盘,就不会知道它的新坐标)


这不是100%可靠的,因为托盘没有义务显示您可以扔给它的所有图标。此外,由于图标闪烁,视觉效果不佳。但总比什么都没有好。

最后,我找到了一种检测它的方法

  • 我正在搜索一个具有dock属性且可见的窗口,然后对其调用XGetWindowAttributes(…)
  • 如果我将筛选方法设置为QApplication::setEventFilter(),我可以获取每个XEvent、\u NET\u 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
    }
    
    bool TaskBarDetector::lookUpDockWindow(无符号长和根窗口,bool检查)
    {
    Display*Display=QX11Info::Display();
    窗口父对象;
    窗口*儿童;
    未签名的非整数儿童;
    智力状态;
    if(检查和检查dockProperty(rootWindow))
    {
    trayWindow=根窗口;
    返回true;
    }
    状态=XQueryTree(显示、根窗口、根窗口、父级、子级和noOfChildren);
    如果(状态==0)
    {
    qDebug()消息==WM\u设置更改和分段->wParam==SPI\u设置工作区)
    {
    检测器->过程检测事件();
    返回false;
    }
    返回false;
    #恩迪夫
    #ifdef Q_WS_X11
    XEvent*XEvent=static_cast(msg);
    如果(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(原子名称=“\u网络\u工作区”)
    {
    检测器->处理检测器事件();
    返回false;
    }
    }
    返回false;
    #恩迪夫
    }
    

    }

    1。使用xwininfo-tree-all命令,我可以得到我想要的东西,因此它必须是一个窗口。
    2.我可以通过捕获x11属性更改事件来检测更改,并通过窗口识别它(但这部分代码没有发布在此处(链接),我有KDE,
    xwininfo-tree-all
    完全没有提到系统托盘。
    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
    }