LINUX.ORG.RU

Еще один вопросик про X11 - как отлавливать нажатие на кнопку Close (крестик справа вверху окна)?...


0

0

Я так понимаю, что такое нажатие прибивает процесс, породивший окно,
с сообщением "X connection to :4.0 broken (explicit kill or server
shutdown)." А вот как бы такую ситуацию обработать?
У меня используются только базовые функции X11 типа XCreateWindow и
такого вот:

.....................
 while (done == 0) {
      /* read the next event */
      XNextEvent (mydisplay, &myevent);
      switch (myevent.type) {
          /* repaint window on expose events */
          case Expose: 
              XSetForeground(mydisplay, mygc, myforeground);
          ..............
      }
 }
.....................

Видимо, нужно обрабатывать какое-то событие, только вот как и
какое - непонятно :(

anonymous

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

Я тут поразбирался и обнаружил вот что. Если в gdb поставить брейкпоинт на exit(), то по нажатию на крестик получается такой стек вызовов в exit():

(gdb) bt #0 0x4202ac26 in exit () from /lib/i686/libc.so.6 #1 0x402f6f49 in _XDefaultIOError () from /usr/X11R6/lib/libX11.so.6 #2 0x402f790f in _XIOError () from /usr/X11R6/lib/libX11.so.6 #3 0x402f504c in _XRead () from /usr/X11R6/lib/libX11.so.6 #4 0x402f4ccb in _XReadEvents () from /usr/X11R6/lib/libX11.so.6 #5 0x402e61c8 in XNextEvent () from /usr/X11R6/lib/libX11.so.6 #6 0x08048da0 in main (argc=1, argv=0xbfffedf4) at my_x11_2.c:157 #7 0x420158f7 in __libc_start_main () from /lib/i686/libc.so.6 (gdb)

Т.е. как бы получается, что нажатие на эту терминальную кнопку убило функцию XNextEvent. Что же може быть не так?

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

Сорри, форматирование поехало....
Я тут поразбирался и обнаружил вот что. Если в gdb поставить
брейкпоинт на exit(), то по нажатию на крестик получается такой
стек вызовов в exit():

(gdb) bt
#0 0x4202ac26 in exit () from /lib/i686/libc.so.6
#1 0x402f6f49 in _XDefaultIOError () from /usr/X11R6/lib/libX11.so.6
#2 0x402f790f in _XIOError () from /usr/X11R6/lib/libX11.so.6
#3 0x402f504c in _XRead () from /usr/X11R6/lib/libX11.so.6
#4 0x402f4ccb in _XReadEvents () from /usr/X11R6/lib/libX11.so.6
#5 0x402e61c8 in XNextEvent () from /usr/X11R6/lib/libX11.so.6
#6 0x08048da0 in main (argc=1, argv=0xbfffedf4) at my_x11_2.c:157
#7 0x420158f7 in __libc_start_main () from /lib/i686/libc.so.6
(gdb)

Т.е. как бы получается, что нажатие на эту терминальную кнопку
убило функцию XNextEvent. Что же може быть не так?

anonymous
()

тебе нужно отрабатывать DestroyNotify евент и закрывать соединение с сервером если тебе без окно не жизнь ..

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

Вы знаете, я пытался обрабатывать DestroyNotify, но у меня ничего не
получалось, пока я не добавил вот это (это код из одного исходника,
который мне попался на глаза):

Перед циклом обработки:

    Atom  atom1, atom2;
    atom1 = XInternAtom(mydisplay, "WM_PROTOCOLS", 0);
    atom2 = XInternAtom(mydisplay, "WM_DELETE_WINDOW", 0);
    XSetWMProtocols(mydisplay, mywindow, &atom2, 1);

И в самом цикле:

 case ClientMessage:
      if(myevent.xclient.message_type == atom1 &&
         myevent.xclient.data.l[0] == atom2)
      {
          XDestroyWindow(mydisplay, mywindow);
      }

      break;

 case DestroyNotify:
      printf("Window has been destroyed\n");
      XCloseDisplay (mydisplay);
      return 0;

После этого все стало прекрасно работать....
Всем спасибо за советы, но все же я не совсем понял, в чем тут дело.

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

дело в том что в соответствии с icccm если у окна стоит WM_DELETE_WINDOW в протоколах, то перед убитием окна WM должен послать client-message чтобы клиент мог завершиться сам .. это например удобно когда ты жмешь [x] на апликухи у которой есть несохраненные файлы .. она получает WM_DELETE_WINDOW и выбрасывает диалог с вопросом нужно ли сохранять файлы перед выходом ..

в твоей ситуации это лишнее

проверь event-mask у своего окна - убедись что у тебя есть StructureNotify в ней

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

Да, есть:

    /* input event selection */
    XSelectInput (mydisplay,
                  mywindow,
                  ExposureMask|StructureNotifyMask);

В цикле обработки сообщений есть строки

              case DestroyNotify:
                   printf("Window has been destroyed\n");
                   XCloseDisplay (mydisplay);
                   return 0;

но до них управление никогда не доходит.

anonymous
()
Ответ на: комментарий от lg

> тебе нужно отрабатывать DestroyNotify евент

При чем здесь оно? Оконный манагер просто отрубает клиента от сервера, если top level окно клиента не имеет WM_DELETE_WINDOW. Оконный манагер вызывает XKillClient, и сервер просто закрывает свой конец сокета, безо всяких предупреждений.

А если клиент не хочет, чтобы с ним так поступали, он должен поиметь атомы WM_PROTOCOLS и WM_DELETE_WINDOW. Затем указать их менеджеру окон для каждого своего окна верхнего уровня. Тогда WM будет посылать окну ClientMessage на попытку его закрытия. Задача клиента -- проверить атомы в сообщении на равенство WM_PROTOCOLS и WM_DELETE_WINDOW, и если это они -- закрыться самому.

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

> При чем здесь оно? Оконный манагер просто отрубает клиента от сервера, если top level окно клиента не имеет WM_DELETE_WINDOW. Оконный манагер вызывает XKillClient, и сервер просто закрывает свой конец сокета, безо всяких предупреждений.

Да ладно, а что если у тебя нет сокета и коннект к X серверу происходит через shared memory или у тебя на одном дисплее два клиента? Ты хочешь сказать что убивая одного, закроется сокет и второй автоматом тоже сдохнет? Это не так, но DestroyNotify действительно на KillClient не генериться, только на DestroyWindow

lg ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.