Pregunta

He creado un traypopupwidget que debe aparecer cerca de la bandeja. Luego me di cuenta de que si el usuario cambia la orientación, o la altura de la barra de tareas, aparecerá en el lugar equivocado.Así que creé la clase de tareas de tareas.

Intenté obtener la geometría de una ventana de la barra de tareas de la bandeja, pero solo me equivoco la propiedad de la ventana ... Lo intenté en KDE, LXDE -> MISMO BURDO MALO ...

El código: http://bzfriendsplasm.svn.sourceforge.net/viewvc/bzfriendsplasm/bzfriends/taskbardetector.cpp?revision=156& ;view=markup

   //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 ();

¿Fue útil?

Solución

Finalmente, encontré una manera de detectarlo!

  1. Estoy buscando una ventana, que tiene una propiedad de muelles y visible, y luego llamo a XGetWindowAttributes (...) en él.
  2. Si configuro un método de filtro para la QApplication :: SETEVENTFILTER () También puedo obtener todos los eventos de XEVENT, _NET_WoreaArea (este evento ocurre cuando cambia o mueve la barra de tareas), vuelva a llamar al método de detección de la barra de tareas / bandejas.

    Sin embargo, esto funcionó en KDE4 y GNOME y LXDE, estoy planeando permitir que el usuario establezca la posición emergente solo.

    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
    }
    

    }

Otros consejos

La bandeja del sistema no es necesariamente una ventana per se.En KDE, esto es solo un área en la barra de tareas (y no está relacionada con el propietario de la selección de _NET_SYSTEM_TRAY_S%i).

Es posible que desee intentar incrustar un icono de bandeja y obtener su geometría, luego mostrar su widget "cerca", dicho icono (para un valor razonable de "cerca").Puede eliminar el icono una vez que conozca su geometría (pero luego, si el usuario mueve la bandeja, no sabrá sus nuevas coordenadas).

Esto no es 100% confiable, ya que la bandeja no está de ninguna manera obligada a mostrar todos los iconos que puede tirarlo.Además, no es complaciente visualmente debido al ícono parpadee.Pero es mejor que nada.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top