Sto cercando di creare un piccolo window manager (solo per divertimento), ma sto avendo problemi nel gestire le finestre create da Firefox (solo con tale domanda, altre applicazioni funziona bene)Xlib e Firefox comportamento
Il problema è che, dopo aver lanciato Firefox e aggiunto la mia decorazione, sembra funzionare bene, ma se per esempio provo a fare clic sul pulsante del menu, la finestra (secondaria) non viene visualizzata.
Quello che sembra accadere è che dopo il clic, un evento ClientMessage è sparato con i seguenti valori:
Data: (null)
Data: _NET_WM_STATE_HIDDEN
Data: (null)
Data: (null)
Data: (null)
Ora il problema è che non so come mostrare la finestra, quale finestra. Ho provato con:
- XRaiseWindow
- XMapWindow
- Ho cercato di ottenere la finestra transitoria e mostrarlo
ma senza successo. Quello che non capisco è che se questo messaggio client è generato dalla sottofinestra del menu o meno.
Come si visualizza una finestra in _NET_WM_STATE_HIDDEN?
Un altro problema strano è che dopo aver ricevuto ClientMessage, ricevo sempre 2 eventi UnMapNotify.
Ho anche un'altra domanda, se voglio mostrare il "File, Modifica" MENU (in Firefox sembra, se non ricordo male, quando si preme il tasto Alt.
Forse Firefox crea un albero di ? finestre
Questo è il ciclo in cui ho gestire gli eventi:
while(1){
XNextEvent(display, &local_event);
switch(local_event.type){
case ConfigureNotify:
configure_notify_handler(local_event, display);
break;
case MotionNotify:
motion_handler(local_event, display);
break;
case CreateNotify:
cur_win = local_event.xcreatewindow.window;
char *window_name;
XFetchName(display, cur_win, &window_name);
printf("Window name: %s\n", window_name);
if(window_name!=NULL){
if(!strcmp(window_name, "Parent")){
printf("Adding borders\n");
XSetWindowBorderWidth(display, cur_win, BORDER_WIDTH);
}
XFree(window_name);
}
break;
case MapNotify:
map_notify_handler(local_event,display, infos);
break;
case UnmapNotify:
printf("UnMapNotify\n");
break;
case DestroyNotify:
printf("Destroy Event\n");
destroy_notify_handler(local_event,display);
break;
case ButtonPress:
printf("Event button pressed\n");
button_handler(local_event, display, infos);
break;
case KeyPress:
printf("Keyboard key pressed\n");
keyboard_handler(local_event, display);
break;
case ClientMessage:
printf("------------ClientMessage\n");
printf("\tMessage: %s\n", XGetAtomName(display,local_event.xclient.message_type));
printf("\tFormat: %d\n", local_event.xclient.format);
Atom *atoms = (Atom *)local_event.xclient.data.l;
int i =0;
for(i=0; i<=5; i++){
printf("\t\tData %d: %s\n", i, XGetAtomName(display, atoms[i]));
}
int nchild;
Window *child_windows;
Window parent_window;
Window root_window;
XQueryTree(display, local_event.xclient.window, &root_window, &parent_window, &child_windows, &nchild);
printf("\tNumber of childs: %d\n", nchild);
break;
}
Ora, nella ClientMessage in realtà sto solo cercando di vedere raccogliere alcune informazioni per capire cosa sta succedendo e quello che posso vedere da. il codice sopra, è che la finestra che ha sollevato th L'evento contiene un figlio (di nuovo: è il menu? o no)
Il codice per l'evento MapNotify, in cui aggiungo la decorazione è il seguente:?
void map_notify_handler(XEvent local_event, Display* display, ScreenInfos infos){
printf("----------Map Notify\n");
XWindowAttributes win_attr;
char *child_name;
XGetWindowAttributes(display, local_event.xmap.window, &win_attr);
XFetchName(display, local_event.xmap.window, &child_name);
printf("\tAttributes: W: %d - H: %d - Name: %s - ID %lu\n", win_attr.width, win_attr.height, child_name, local_event.xmap.window);
Window trans = None;
XGetTransientForHint(display, local_event.xmap.window, &trans);
printf("\tIs transient: %ld\n", trans);
if(child_name!=NULL){
if(strcmp(child_name, "Parent") && local_event.xmap.override_redirect == False){
Window new_win = draw_window_with_name(display, RootWindow(display, infos.screen_num), "Parent", infos.screen_num,
win_attr.x, win_attr.y, win_attr.width, win_attr.height+DECORATION_HEIGHT, 0,
BlackPixel(display, infos.screen_num));
XMapWindow(display, new_win);
XReparentWindow(display,local_event.xmap.window, new_win,0, DECORATION_HEIGHT);
set_window_item(local_event.xmap.window, new_win);
XSelectInput(display, local_event.xmap.window, StructureNotifyMask);
printf("\tParent window id: %lu\n", new_win);
put_text(display, new_win, child_name, "9x15", 10, 10, BlackPixel(display,infos.screen_num), WhitePixel(display, infos.screen_num));
}
}
XFree(child_name);
}
Ora qualcuno mi può aiutare con questi problemi? Purtroppo ho già cercato su Google molte volte, ma senza successo.
Per riassumere, i miei problemi sono due: 1. Come visualizzare i sottofinestre da Firefox 2. Come visualizzare il menu File, Modifica.
UPDATE
ho notato qualcosa di strano test Firefox con xev per capire quali eventi vengono generati al fine di mostrare un'applicazione. Ho visto che usando Firefox in unità e usando Firefox in un altro gestore di finestre, gli eventi sparati sono completamente diversi.In Unity Ho solo:
- ClientMessage
- UnmapNotify
Invece l'utilizzo di Firefox, per esempio con xfce4, i Xevents generati sono di più:
- VisiblityNotify (più di uno)
- Evento di esposizione (più di uno)
Ma se cerco di abilitare VisibilityChangeMask nel mio wm, ricevo i seguenti eventi:
- ConfigureNotify
- ClientMessage
- MapNotify
- 2 UnMapNotify
UPDATE 2
Ho provato a leggere le proprietà XWMhints nella finestra ClientMessage (probabilmente la finestra del menu) ed i valori sono:
Per le bandiere 67 = InputHint, StateHint, WIndowGroupHint
per lo stato iniziale NormalState
UPDATE 3
ho provato a cercare come un nother window manager funziona, e stavo guardando il codice sorgente di calmwm. Quello che capisco è che, quando arriva l'evento ClientMessage, con un messaggio _NET_WM_STATE, aggiorna queste proprietà e, nel caso di _NET_WM_STATE_HIDDEN, cancella questa proprietà, e il risultato sarà che la proprietà verrà cancellata. Così ho provato ad aggiornare il mio codice per eliminare quella proprietà, ma non funziona ancora. In ogni caso il codice aggiornato rilevante in client_message_handler ora assomiglia a questo:
Atom *atoms = (Atom *)local_event.xclient.data.l;
int i =0;
for(i=0; i<=5; i++){
printf("\t\tData %d: %s\n", i, XGetAtomName(display, atoms[i]));
if(i==1){
printf("\t Deleting Property: _NET_WM_STATE_HIDDEN \n");
XDeleteProperty(display, cur_window, atoms[i]);
}
}
E 'solo un test, e sono sicuro che i = 1 nel mio caso è la proprietà _NET_WM_STATE_HIDDEN.
Ecco un link al codice sorgente calmwm: https://github.com/chneukirchen/cwm/blob/linux/xevents.c
Così sto ancora bloccato in quel punto.
AGGIORNAMENTO 4
Davvero non so se aiuta, ma ho cercato di leggere gli attributi di finestra nel MapNotify Event, e la finestra map_state è IsViewable (2).
UPDATE 5
ho trovato un problema simile qui a SO, usando Xlib con python: Xlib python: cannot map firefox menus
La soluzione suggerisce di utilizzare XSetInputFocus, ho provato sul mio gestore XMapNotify:
XSetInputFocus(display, local_event.xmap.window, RevertToParent, CurrentTime);
Ma ancora non aiuta, il menu di Firefox non appare ancora !! E ho lo stesso problema con il tasto destro del mouse.
AGGIORNAMENTO 6
Giocando con xconfigurenotify eventi e unmap evento ho trovato che la: richiesta di Xconfigure dispone di 2 campi della finestra: Finestra e di cui sopra, e quando il il valore xconfigurerequest.window è lo stesso di xunmap Valore finestra.
E anche che xconfigurerequest.above cambia sempre, ma xconfigurerequest.window è sempre lo stesso in tutti gli eventi.
Sembra che xconfigurerequest.above sia correlato al menu che sto tentando di aprire. Per esempio:
- se tasto destro del mouse su una pagina ottengo un id (sempre lo stesso per ogni successivo clic)
- Se destra-clik su una scheda, il valore sopra è un altro
- e lo stesso accade se ho lasciato il menu principale di firefox
Ancora non so se questo aiuti.
Davvero non lo so Qualcuno ha qualche idea?
Il mio amico e io faccio un sacco di x11, gtk, GDK, e altre cose c lib con Firefox. Abbiamo focalizzato una finestra impostando l'hint '_NET_ACTIVE_WINDOW' e anche' XMapRaised': https://gist.github.com/Noitidart/c7be5489fd38f8ecc76b#file-_ff-addon-snippet-x11_focuswindowbynativehandle-js-L280-L283 guarda male di più il tuo problema e anche far sapere al mio amico – yatg
Grazie a @yatg per il tuo commento, ho una domanda sullo snippet di codice che mi hai inviato, il campo l0 è lo stesso campo che in c sarà xclient.data.l0?E perché lo hai impostato su 2? – Ivan
In realtà verifica questo codice molto più pulito: https://github.com/Noitidart/NativeShot/blob/winnt-found-workaround-for-winnt-nondpi-scale/modules/workers/MainWorker.js#L132-L159 fondamentalmente il motivo per cui era 2 è perché questo è il numero magico per '_NET_WM_STATE_TOGGLE' visto qui: https://github.com/Noitidart/NativeShot/blob/winnt-found-workaround-for-winnt-nondpi-scale/modules/ ostypes_x11.jsm # L245 il 'XFlush' è cruciale per l'azione da intraprendere, se' XFlush' non è fatto, non si farà avanti, almeno nel nostro experince, quindi usare 'XFlush' potrebbe essere la tua soluzione fammi sapere come va plz. – yatg