Przechwycić WM_DELETE_WINDOW na X11?


Chciałbym przechwycić wiadomość
WM_DELETE_WINDOW
wysyłaną do określonego wyboru systemu Windows, który piszę (

AllTray
http://alltray.trausch.us/), abym mógł działać na jej podstawie, zamiast otrzymywać ją od wniosku. Obecnie rozważam wypróbowanie tego na poziomie GDK

przez
gdk_display_add_client_message_filter
http://library.gnome.org/devel ... ilter
jeśli to możliwe, ale byłbym zadowolony z rozwiązania Xlib, gdyby takie też istniało; wydaje się
jest to możliwe, ale po prostu nie rozumiem, jak mogę to zrobić z powodzeniem.
Obecnie mam dwa programy (napisane w C), których próbuję użyć do rozwiązania tego problemu: pierwszy nie robi nic poza utworzeniem okna i zarejestrowaniem, że wie o
WM_DELETE_WINDOW
, a drugi próbuje złapać ta wiadomość, ale wydaje się, że tego nie robi; wydaje się, że nic nie robi. Czy dobrze rozumiem dokumentację dotyczącą tego problemu, czy jest jeszcze coś, co muszę zrobić (lub czy muszę całkowicie unikać korzystania z GDK w tym celu)?
Tło jest takie: zanim przepisałem AllTray, najwyraźniej próbował przechwycić kliknięcie myszą samego przycisku X. W przypadku niektórych menedżerów okien działało to dobrze, dla innych w ogóle nie działało, a dla innych użytkownik musiał to skonfigurować ręcznie i powiedz AllTray, gdzie znajduje się przycisk zamykania okna. To, czego szukam, to rozwiązanie, które nie zawiera
LD_LIBRARY_PRELOAD
i będzie działać dla dowolnej kombinacji menedżera okien/aplikacji, która spełnia aktualne standardy i wysyła
WM_DELETE_WINDOW
ClientMessage., Gdy okno zamknięte.

UPDATE
: Nadal szukam odpowiedzi. Trasa, którą obecnie wybieram, polega na próbie zmiany koloru okna i samodzielnego kontrolowania go, ale po prostu nie mogę go uruchomić. Po odrodzeniu wydaje mi się, że nie jestem w stanie go odzyskać. Być może brakuje mi czegoś bardzo podstawowego, ale nie mogę dowiedzieć się, jak sprawić, by pojawiło się ponownie w moim własnym oknie, aby przywrócić je na ekranie.

UPDATE 2

OK, więc natknąłem się na kolejną ceglaną ścianę. Dokumentacja serwera X mówi, aby ustawić StructureNotifyMask w masce zdarzeń okna, aby odbierać zdarzenia MapNotify i ReparentNotify. Byłbym zainteresowany, aby uzyskać oba. Moim obecnym zamysłem było stworzenie okna, które służyłoby po prostu jako odbiornik wydarzeń, a kiedy otrzymuję zdarzenia dla interesujących rzeczy, działam na nich, tworząc i przerysowując. Jednak to po prostu nie działa. Jedyne zdarzenia, które faktycznie otrzymuję, to zdarzenia PropertyNotify. Więc ta trasa też nie wydaje się zbyt przydatna.
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Nie znam X11, ale googlowałem używając

„Hooking
WM_DELETE_WINDOW
X11”
http://www.google.com/search%3 ... UTF-8
jako słowa kluczowe. Znaleziony

17k-MarkMail
http://markmail.org/download.x ... r%3D3
i

mplayer-commits r154-trunk/libvo
https://garage.maemo.org/piper ... ml... W obu przypadkach robią to samo.
/* This is used to intercept window closing requests. */
static Atom wm_delete_window;

wewnątrz
static void x11_init ()
,
XMapWindow(display, win);
wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, win, &wm_delete_window, 1);

następnie w ramach
static int x11_check_events ()
,
XEvent Event;
while (XPending(display)) {
XNextEvent(display, &Event);
if (Event.type == ClientMessage) {
if ((Atom)Event.xclient.data.l[0] == wm_delete_window) {
/* your code here */
}
}
}

Widzieć

XInternAtom
http://tronche.com/gui/x/xlib/ ... .html
,

XSetWMProtocols
http://tronche.com/gui/x/xlib/ ... .html
i

XNextEvent
http://tronche.com/gui/x/xlib/ ... .html
.
Po tym, jak napisałem powyżej, znalazłem to

okno przetwarzania zamknij w aplikacji
http://linuxsoftware.co.nz/blo ... indow
X11 :

Chcemy, aby użytkownik kliknął przycisk Zamknij
[x]
w naszej aplikacji X11
otworzył okno dialogowe z pytaniem „czy ty?
naprawdę chcesz rzucić? ”. To proste
Dodatek X. Brak wyszukanych widżetów GTK lub
QT tu nie ma. Jak więc złapać komunikat „okno jest
being closed”?
Odpowiedź brzmi: powiedz oknu
Manager nas tym interesuje
zdarzenie, wywołując
XSetWMProtocols
i
rejestrując w nim wiadomość
WM_DELETE_WINDOW
. Wtedy będziemy mieć klienta
wiadomość od menedżera okien, jeśli
ktoś spróbuje zamknąć okno i
nie zamknie się, zostawi to sobie ... Oto przykład ....

// example.cpp
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <iostream>int main()
{
Display* display = XOpenDisplay(NULL);
Window window = XCreateSimpleWindow(display,
DefaultRootWindow(display),
0, 0,
500, 400,
0,
0, 0);// register interest in the delete window message
Atom wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, window, &wmDeleteMessage, 1); std::cout << "Starting up..." << std::endl;
XMapWindow(display, window); while (true) {
XEvent event;
XNextEvent(display, &event); if (event.type == ClientMessage &&
event.xclient.data.l[0] == wmDeleteMessage) {
std::cout << "Shutting down now!!!" << std::endl;
break;
}
} XCloseDisplay(display);
return 0;
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Niestety najlepszą odpowiedzią na to pytanie jest seria braków odpowiedzi; istnieją techniczne sposoby na osiągnięcie tego celu, ale wszystkie mają wady, które czynią je niezwykle niepraktycznymi:
  • Utwórz serwer proxy X11 dla aplikacji, przekazując wszystkie komunikaty protokołu X11 między aplikacją a serwerem X. Serwer proxy odfiltruje wtedy wszystkie interesujące wiadomości. Wadą tego jest to, że jest to bardzo duże obciążenie dla jednej małej funkcji, a protokół X11 jest skomplikowany. Mogą też wystąpić niezamierzone konsekwencje, co czyni tę opcję jeszcze mniej atrakcyjną.
  • Działa jako standardowa aplikacja, która działa jako pośrednik między menedżerem okien a „interesującymi” aplikacjami klienckimi. To psuje niektóre rzeczy, takie jak XDnD. Zasadniczo nie różni się od pierwszej opcji, z wyjątkiem tego, że proxy znajduje się na poziomie okna, a nie na poziomie protokołu X11.
  • Użyj nieprzenośnej sztuczki bibliotecznej
    LD_PRELOAD
    . To ma trochę niedogodności: [list][*]Nie jest przenośny dla dynamicznych konsolidatorów: nie wszystkie dynamiczne konsolidatory obsługują
    LD_PRELOAD
    , nawet w systemach typu UNIX.
  • Nie można go przenosić między systemami operacyjnymi: nie wszystkie systemy operacyjne obsługują funkcjonalne konsolidatory dynamiczne.
  • Narusza to przejrzystość sieci: obiekt współdzielony/biblioteka dołączana dynamicznie musi znajdować się na hoście jako działający proces potomny.
  • Nie wszystkie aplikacje X11 używają Xlib; należałoby napisać jeden moduł
    LD_PRELOAD
    dla każdej z bibliotek, których aplikacja może używać do komunikacji z X11.
  • Oprócz ostatniego punktu, nie wszystkie aplikacje będą podatne na
    LD_PRELOAD
    , nawet jeśli działają pod konsolidatorem, który go obsługuje, ponieważ nie mogą używać współdzielonego obiektu lub biblioteki DLL do komunikacji z X; Weźmy na przykład aplikację Java, która używa biblioteki protokołu X11 napisanej w samej Javie.
  • W niektórych systemach operacyjnych, takich jak UNIX, biblioteki
    LD_PRELOAD
    muszą być ustawione na setuid/setgid, jeśli mają być używane z programami setuid/setgid. Jest to oczywiście potencjalna luka w zabezpieczeniach.
  • Jestem prawie pewien, że są inne wady, o których nie mogę pomyśleć.

[/*]
[*]
Zaimplementuj rozszerzenie do X Window System. Nie do przenoszenia wśród implementacji X11, skomplikowane i zawiłe i całkowicie wykluczone.
[/*]
[*]
Wstaw rozszerzenia lub wtyczki do menedżerów okien. Jest tyle menedżerów okien, ilu jest opinii na temat menedżerów okien, a zatem jest to całkowicie niemożliwe.
[/*]
[/list]
Ostatecznie udało mi się w końcu osiągnąć swój cel za pomocą zupełnie odrębnego mechanizmu; wszyscy zainteresowani powinni zapoznać się z obsługą Close-to-Tray w AllTray 0.7.5.1dev i nowszych, w tym

gałąź git master dostępna na github
https://github.com/mbt/alltray/
.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Powinieneś przeczytać ICCCM, który mówi ci, jak menedżer okien współdziała z klientem. Większość WM utworzy okno z ramką, aby pomieścić okno najwyższego poziomu, przez ponowne malowanie. W ten sposób, jeśli twój rodzic może zerwać relacje znane WM i twojemu klientowi.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Ok, aby rozwinąć moją poprzednią sugestię, możesz zechcieć zbadać

XEmbed
http://standards.freedesktop.o ... ml... Przynajmniej może dać ci kilka pomysłów do wypróbowania.
W przeciwnym razie przyjrzałbym się, jak inne podobne oprogramowanie (takie jak wmdock lub sposób implementacji GtkPlug/GtkSocket) może działać, chociaż uważam, że oba te przypadki wymagają wyraźnego wsparcia w aplikacjach.
Mam nadzieję, że to będzie bardziej pomocne.

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się