1

トレイの近くにポップアップする TrayPopupWidget を作成しました。次に、ユーザーがタスクバーの向きや高さを変更すると、間違った場所にポップアップすることに気付きました。そこで、TaskbarDetector クラスを作成しました。

トレイ|タスクバーのウィンドウジオメトリを取得しようとしましたが、間違ったウィンドウプロパティしか取得できません... KDE、LXDEで試しました->同じ悪い動作...

コード: 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 ();
4

2 に答える 2

2

最後に、それを検出する方法を見つけました!

  1. Dock プロパティがあり、表示されているウィンドウを探していて、その上で XGetWindowAttributes(...) を呼び出します。
  2. 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
}

}

于 2012-05-22T20:27:57.923 に答える
0

システム トレイは、必ずしもそれ自体がウィンドウであるとは限りません。KDE では、これはタスクバー内の単なる領域です (_NET_SYSTEM_TRAY_S%i選択の所有者とは関係ありません)。

トレイ アイコンを埋め込んでそのジオメトリを取得してから、そのアイコンの「近く」にウィジェットを表示することをお勧めします (「近く」の妥当な値の場合)。アイコンのジオメトリがわかったら、アイコンを削除できます (ただし、ユーザーがトレイを移動した場合、新しい座標はわかりません)。

これは 100% 信頼できるわけではありません。トレイは、投げることができるすべてのアイコンを表示する義務があるわけではないからです。また、アイコンがちらつくため、視覚的に快適ではありません。しかし、それは何もないよりはましです。

于 2012-05-18T20:41:56.787 に答える