2009-04-10 4 views
4

So bin ich in einer Situation, wo ich wissen muss, wenn ein Top-Level-Fenster erstellt wird. Ich arbeite auf der Xlib/Xt-Ebene und in einem Window Manager, der die EWMH-Spezifikation nicht unterstützt. Meine Idee ist es, sich in die SubstructionNotify-Events des Root-Fensters einzuklinken. Aber die Dinge sind nicht so einfach wie nur das.Handle "neue Top-Level-Fenster" Ereignisse in Xlib/Xt

Das Problem ist, dass nicht jedes CreateNotify -Ereignis der Erstellung eines [b] Top-Level [/ b] -Fensters entspricht. Also denke ich, dass ich das Fenster, das ich vom Event bekomme, irgendwie testen muss, um zu bestätigen, dass es ein Top-Level-Fenster ist. Ich bin nahe dran, aber ein paar falsche Fenster schaffen es immer noch durch mein Netz. Wenn Sie zum Beispiel in einer GTK-Anwendung eine Dropdown-Box haben und darauf klicken, wird ein neues Fenster erstellt, in dem ich nicht herausfinden kann, wie man fängt und ignoriert. Ein solches Fenster ist von einem typischen Anwendungsfenster der obersten Ebene nicht zu unterscheiden.

Hier ist, was ich bisher:

// I am omiting (tons of) cleanup code and where I set the display and toplevel variables. 

Display* display; 
Widget toplevel; 

bool has_name(Window window) 
{ 
    XTextProperty data = XTextProperty(); 
    return (!XGetWMName (display, window, &data)); 
} 

bool has_client_leader(Window window) 
{ 
    unsigned long nitems = 0; 
    unsigned char* data = 0; 
    Atom actual_type; 
    int actual_format; 
    unsigned long bytes; 
    // WM_CLIENT_LEADER is an interned Atom for the WM_CLIENT_LEADER property 
    int status = XGetWindowProperty (display, window, WM_CLIENT_LEADER, 0L, (~0L), False, 
     AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes, &data); 
    if (status != Success || acutal_type == None) return false; 
    Window* leader = reinterpret_cast<Window*> (data); 
    return (*leader != 0); 
} 

bool has_class(Window window) 
{ 
    XClassHint data = XClassHint(); 
    return (!GetClassHint (display, window, &data)); 
} 

void handle_event(Widget widget, XtPointer, XEvent* event, Boolean*) 
{ 
    if (event->type != CreateNotify) return; 

    Window w = event->xcreatewindow.window; 

    // confirm window has a name 
    if (!has_name (w)) return; 

    // confirm window is a client window 
    Window client = XmuClientWindow (display, w); 
    if (!client || client != w) return; 

    // confirm window has a client leader that is not 0x0 
    if (!has_client_leader (client)) return; 

    // confirm window has a class 
    if (!has_class (client)) return; 

    // The window has passed all our checks! 
    // Go on to do stuff with the window ... 
} 

int main(int argc, char* argv[]) 
{ 
    // ... 

    // Setting up the event handler for SubstructureNotify on root window 
    Window root_window = XDefaultRootWindow (display); 
    Widget dummy = XtCreateWidget ("dummy", coreWidgetClass, toplevel, 0, 0); 
    XtRegisterDrawable (display, root_window, dummy); 
    XSelectInput (display, root_window, SubstructureNotifyMask); 
    XtAddRawEventHandler (dummy, SubstructureNotifyMask, False, handle_event, 0); 

// ... 
} 

Ein langer Schuss, aber hat jemand irgendwelche Ideen, die ich versuchen könnte? Ich kann mir nicht viel mehr vorstellen, was ich hier wirklich tun kann.

+1

An welchem ​​Fenstermanager arbeiten Sie? Warum implementierst du EWMH nicht? – Zifre

Antwort

2

Ich nehme an, Sie sind vertraut mit der ICCCM und seine long-winded discussion.

Haben Sie die WM_TRANSIENT_FOR Eigenschaft überprüft?

+0

+1 für den entsprechenden Link und Hinweis – neuro