LINUX.ORG.RU

Проблема с XOpenDisplay (c QX11Info::display() все работает)

 ,


0

1

Задача: убрать заданное окно qt приложения с панели задач.

Решение:

hideFromTaskBar(QWidget* widget)
{
  Display* display = QX11Info::display();

  const int n_elements = 2;
  Atom state[n_elements];

  state[0] = XInternAtom(display, "_NET_WM_STATE_SKIP_PAGER"  , true);
  state[1] = XInternAtom(display, "_NET_WM_STATE_SKIP_TASKBAR", true);

  XChangeProperty(display, widget->winId(),
                  XInternAtom(display, "_NET_WM_STATE", true),
                  XA_ATOM,
                  32,
                  PropModeReplace,
                  (unsigned char*)state,
                  n_elements);
}

Проблема: если заменить

QX11Info::display()
на
XOpenDisplay(0)
окно не убирается с панели задач.

Приложение замечательно работает используя QX11Info::display(), но мне интересно, что я делаю неправльно при использовании XOpenDisplay?

Другие фунции(например XQueryTree) нормально работают с объектом получаемым через XOpenDisplay.

Тестовое приложение: pro:

QT += gui
TARGET = test_hide_from_taskbar
SOURCES += main.cpp
LIBS += -lX11

main.cpp:

#include <QApplication>
#include <QPushButton>
#include <QX11Info>

#include <X11/Xatom.h>
#include <X11/Xlib.h>

class Widget : public QPushButton
{
    Q_OBJECT

  public:
    Widget(QWidget* parent = 0);

    void hideFromTaskBar(QWidget *widget);

  public slots:
    void on_click();
};


Widget::Widget(QWidget *parent)
  : QPushButton(parent)
{
  resize(200, 200);
  connect(this, SIGNAL(clicked()), SLOT(on_click()));
}

void Widget::hideFromTaskBar(QWidget* widget)
{
  Display* display = XOpenDisplay(0);
  Display* qdisplay = QX11Info::display();
//  display = qdisplay;

  const int n_elements = 2;
  Atom state[n_elements];

  Q_ASSERT(RootWindow(display, 0) ==
           RootWindow(qdisplay, 0));

  state[0] = XInternAtom(display, "_NET_WM_STATE_SKIP_PAGER"  , true);
  state[1] = XInternAtom(display, "_NET_WM_STATE_SKIP_TASKBAR", true);

  XChangeProperty(display, widget->winId(),
                  XInternAtom(display, "_NET_WM_STATE", true),
                  XA_ATOM,
                  32,
                  PropModeReplace,
                  (unsigned char*)state,
                  n_elements);
}

void Widget::on_click()
{
  QWidget* wgt = new QWidget();
  wgt->resize(500, 500);
  wgt->show();
  hideFromTaskBar(wgt);
}

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  Widget w;
  w.show();
  
  return a.exec();
}

#include "main.moc"


Ответ на: комментарий от Zubok

Из документации:

if the display_name is NULL, it defaults to the value of the DISPLAY environment variable

то есть NULL передавать можно и результат

XOpenDisplay(0) 
не отличается от
XOpenDisplay(getenv("DISPLAY")) // в исходниках qt так
(где getenv(«DISPLAY») возвращает волне валидное название ":0")

Я же писал, что вполне успешно отрабатывает поиск окон, через XQueryTree, а XChangeProperty почему-то не работает.

Ower
() автор топика
Ответ на: комментарий от Ower

Странно, что результат одинаковый. Дело в том, что при помощи XOpenDisplay ты открываешь (внимание!) второе соединение к серверу X, а не существущее используешь.

Zubok ★★★★★
()
Ответ на: комментарий от Ower

Поэтому ты получаешь другой диапазон идентификаторов ресурсов. И поэтому обращение к ресурсу widget->winId() из диапазона уже существующего соединения ни к чему не приводит. То есть display у тебя новый и XID не его.

Zubok ★★★★★
()

Расскажи, какая вообще изначально задача, а то не ясно, что ты делаешь. У каких окон ты пытаешься Property менять.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Расскажи, какая вообще изначально задача, а то не ясно, что ты делаешь. У каких окон ты пытаешься Property менять.

С панели задач приложение должно убирать свои собственные окна.

Поэтому ты получаешь другой диапазон идентификаторов ресурсов. И поэтому обращение к ресурсу widget->winId() из диапазона уже существующего соединения ни к чему не приводит. То есть display у тебя новый и XID не его.

насчет диапазонов не понял. например я делаю

m_display = XOpenDisplay(0)
после чего вот это работает:
XSetTransientForHint(m_display, widget->winId(), target_window)

а XChangeProperty c тем же m_display и widget->winId() не работает. при этом если заменить m_display на QX11Info::display(), то работает.

Ower
() автор топика
Ответ на: комментарий от Ower

насчет диапазонов не понял. например я делаю

Диапазон действительно новый у нового соединения, но это при создании своих ресурсов. К другим ресурсам это не должно перекрывать доступ по идее. Мое предположение по поводу ресурсов, скорее всего, ошибочно.

Но в любом случае, тебе не следует создавать второе соединение к серверу. У тебя уже есть соединение и Qt его тебе предоставляет в распоряжение. То есть сама идея вызывать XOPenDisplay из Qt плоха.

а XChangeProperty c тем же m_display и widget->winId() не работает. при этом если заменить m_display на QX11Info::display(), то работает.

А XGetWindowProperty к этому окну работает? Если изменить свойство через дисплей из QX11Info, а прочитать его через дисплей XOpenDisplay.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

XGetWindowProperty для _NET_WM_STATE через какой дисплей установил свойство - через тот и читается.

При этом другие свойства читаются для обоих дисплеев нормально нормально, например WM_CLASS.

Ower
() автор топика
Ответ на: комментарий от Ower

Не совсем понял. А те свойства, которые ты устанавливаешь, они устанавливаются и читаются хотя бы?

И еще. Проанализируй результат XChangeProperty. Если 0, то какая-то ошибка. Надо посмотреть, что он напишет. XChangeProperty() can generate BadAlloc, BadAtom, BadMatch, BadValue, and BadWindow errors.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Когда устанавливаю _NET_WM_STATE, то читается оно через тот дисплей, через который устанавливал, через другой - пусто. И, естественно, XChangeProperty всегда 1 возвращает.

Ower
() автор топика
Ответ на: комментарий от Ower

Загадочные дела. А вот если XFlush(display) сделать после XChangeProperty? Это что-то меняет?

Zubok ★★★★★
()
Ответ на: комментарий от Zubok
XChangeProperty(display); XFlush(QX11Info::display()); XFlush(display) - работает
XChangeProperty(display); XFlush(QX11Info::display()); XGetWindowProperty(display) - работает
XChangeProperty(display); XFlush(QX11Info::display()); - не работает
XChangeProperty(display); XFlush(display); - не работает

при XFlush перед XChangeProperty результаты такие же

Ower
() автор топика
Ответ на: комментарий от Ower

Хм, что-то я в этой жизни не понимаю. Надо будет скомпилить примерчик и разобраться. Не у одного у тебя такое:

http://www.qtcentre.org/threads/13097-XOpenDisplay-!-X11Info-display()

Хотя тут еще не проблема, а просто констатация факта, что display разные. Но это понятно.

XChangeProperty(display); XFlush(QX11Info::display()); XFlush(display) - работает

То есть сработало изменение свойства через другой display, но только если вот эти два Flush сделаны? А если либо один Flush, либо другой, то не работает, получается. Хм.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.