attribute c x11 xlib

c - html title attribute



Comportamiento de Xlib y Firefox (1)

Estoy tratando de crear un pequeño administrador de ventanas (solo por diversión), pero tengo problemas para manejar las ventanas creadas por Firefox (solo con esa aplicación, otras aplicaciones funcionan bien)

El problema es que después de iniciar Firefox y agregar mi decoración, parece funcionar bien, pero si, por ejemplo, trato de hacer clic en el botón de menú, no aparece la (sub) ventana.

Lo que parece suceder es que después del clic, se desencadena un evento ClientMessage con los siguientes valores:

Data: (null) Data: _NET_WM_STATE_HIDDEN Data: (null) Data: (null) Data: (null)

Ahora el problema es que no sé cómo mostrar la ventana, qué ventana. Lo intenté con:

  • XRaiseWindow
  • XMapWindow
  • Traté de obtener la ventana transitoria y mostrarla

Pero sin éxito. Lo que no entiendo es que si este mensaje de cliente es generado por la subventana del menú o no.

¿Cómo debo mostrar una ventana que está en _NET_WM_STATE_HIDDEN?

Otro problema extraño es que después de recibir ClientMessage, siempre recibo 2 eventos UnMapNotify.

También tengo otra pregunta, si quiero mostrar el menú "Archivo, Editar" (en Firefox aparece, si no recuerdo mal, cuando presionas el botón Alt.

¿Quizás Firefox crea un árbol de ventanas?

Este es el ciclo donde manejo los eventos:

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; }

Ahora, en el mensaje del cliente, en realidad solo estoy tratando de recopilar información para comprender lo que está sucediendo. Y lo que puedo ver en el código anterior es que la ventana que generó el evento contiene un elemento secundario (de nuevo: ¿es ese el menú o no?)

El código para el evento MapNotify, donde agrego la decoración es el siguiente:

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); }

Ahora, ¿alguien puede ayudarme con estos problemas? Lamentablemente ya busqué en Google muchas veces, pero sin éxito.

En resumen, mis problemas son dos: 1. Cómo mostrar subventanas de Firefox 2. Cómo mostrar el menú Archivo, Editar.

ACTUALIZAR

Noté algo extraño probando Firefox con xev para comprender qué eventos se activan para mostrar una aplicación. Vi que usando Firefox en la unidad, y usando Firefox en otro administrador de ventanas, los eventos disparados son completamente diferentes. En Unity solo tengo:

  1. ClientMessage
  2. UnmapNotify

En lugar de usar Firefox, por ejemplo con xfce4, los eventos x generados son más:

  1. VisiblityNotify (más de uno)
  2. Exponer evento (más de uno)

Pero si trato de habilitar VisibilityChangeMask en mi wm, recibo los siguientes eventos:

  • ConfigureNotify
  • ClientMessage
  • MapNotify
  • 2 UnMapNotify

ACTUALIZACIÓN 2

Intenté leer las propiedades de XWMhints en la ventana ClientMessage (probablemente la ventana de menú) y los valores son:

  • Para las banderas 67 = InputHint, StateHint, WIndowGroupHint

  • Para el estado inicial NormalState

ACTUALIZACIÓN 3

Traté de ver cómo funciona otro administrador de ventanas, y estaba mirando el código fuente de calmwm. Entiendo que, cuando llega el evento ClientMessage, con un mensaje _NET_WM_STATE, actualiza estas propiedades y, en el caso de _NET_WM_STATE_HIDDEN, borra esta propiedad y el resultado será que la propiedad se eliminará. Así que intenté actualizar mi código para eliminar esa propiedad, pero todavía no funciona. De todos modos, el código actualizado relevante en client_message_handler ahora se ve así:

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]); } }

Es solo una prueba, y estoy seguro de que i = 1 en mi caso es la propiedad _NET_WM_STATE_HIDDEN.

Aquí un enlace al código fuente de calmwm: https://github.com/chneukirchen/cwm/blob/linux/xevents.c

Entonces todavía estoy atrapado en ese punto.

ACTUALIZACIÓN 4

Realmente no sé si ayuda, pero intenté leer los atributos de la ventana en el evento MapNotify, y la ventana map_state es IsViewable (2).

ACTUALIZACIÓN 5

Encontré un problema similar aquí en SO, usando xlib con python: Xlib python: no se pueden asignar menús de Firefox

La solución sugiere usar XSetInputFocus, lo intenté en mi controlador XMapNotify:

XSetInputFocus(display, local_event.xmap.window, RevertToParent, CurrentTime);

¡Pero todavía no ayuda, el menú de Firefox todavía no aparece! Y tengo el mismo problema con el clic derecho.

ACTUALIZACIÓN 6

Jugando con el evento xconfigurenotify y el evento unmap descubrí que: la solicitud Xconfigure tiene 2 campos de ventana: ventana y superior, y cuando el valor xconfigurerequest.window es el mismo que el valor xunmap.window.

Y también que xconfigurerequest.above siempre está cambiando, pero xconfigurerequest.window es siempre el mismo en todos los eventos.

Parece que xconfigurerequest.above está relacionado con el menú que intento abrir. Por ejemplo:

  • si hago clic derecho en una página, obtengo una identificación (siempre la misma para cada clic posterior)
  • si hago clic derecho en una pestaña, el valor anterior es otro
  • y lo mismo sucede si hago clic izquierdo en el menú principal de Firefox

Todavía no sé si eso ayuda.

Realmente no sé ¿Alguien tiene alguna idea?


Use xtruss : un programa de rastreo de protocolo X fácil de usar

Visión general

Cualquier programador acostumbrado a escribir programas en Linux o System Unixes de tipo V habrá encontrado el programa conocido como strace o truss, que monitorea otro programa y produce un registro detallado de cada llamada al sistema que realiza, en otras palabras, todos los programas interacciones con el núcleo del sistema operativo. Esta es a menudo una herramienta de depuración invaluable, y casi tan buena como educativa.

Sin embargo, cuando se trata de un programa GUI (o más bien, el comportamiento relacionado con la GUI de un programa) que desea comprender o depurar, el nivel de interacción con el núcleo del sistema operativo rara vez es el más útil. Más útil, uno quisiera registrar todas las interacciones del programa con el servidor X de la misma manera.

Ya existen programas que harán esto. Soy consciente de Xmon y Xtrace. Pero tienden a requerir mucho esfuerzo para configurar: debe ejecutar el programa para establecer un servidor de escucha, luego organizar manualmente para que el programa de destino se ponga en contacto con eso en lugar del servidor real, incluido un trabajo complicado con xauth. Idealmente, le gustaría rastrear las operaciones X de un programa para que sea tan fácil como rastrear sus llamadas al sistema kernel: le gustaría escribir un comando tan simple como argumentos de nombre de programa, y ​​tener todo manejado automáticamente por usted.

Además, la salida de esos programas es menos fácil de leer de lo que me hubiera gustado, lo que significa en gran medida que es menos parecida de lo que me gustaría que fuera. strace tiene la buena propiedad de poner cada llamada del sistema y su valor de retorno en la misma línea de salida, para que pueda ver de un vistazo a qué fue respondida cada respuesta. Los monitores de protocolo X, sin embargo, tienden a seguir fielmente la estructura del protocolo X, lo que significa que cada solicitud y respuesta se imprime con un número de secuencia, y debe hacer coincidir los dos a simple vista.

Entonces, esta página presenta xtruss, mi propia contribución al campo de los registradores de protocolo X. Tiene una sintaxis de línea de comandos similar a strace: en su modo predeterminado, simplemente prefijas "xtruss" a la misma línea de comando que hubieras ejecutado de todos modos, y su formato de salida también es más parecido a strace, colocando solicitudes y respuestas en el mismo línea de salida donde sea razonablemente posible.

strace también admite la función de adjuntar a un proceso que ya se está ejecutando y rastrearlo desde la mitad de su ejecución, útil cuando algo sale mal con un proceso de larga ejecución que no sabía de antemano que iba a necesitar rastrear. xtruss admite esta misma función, por medio de la extensión X RECORD (siempre que su servidor X lo admita, como lo hacen los modernos X.Org); entonces, en ese modo, puede identificar una ventana con el mouse (de manera similar a los programas estándar como xwininfo y xkill), y xtruss se conectará al programa cliente X que posee la ventana que especificó, y comenzará a rastrearla.

Descripción

xtruss es una utilidad que registra todo lo que pasa entre el servidor X y uno o más programas de cliente X. En esto es similar a xmon (1), pero pretende combinar la funcionalidad básica de xmon con una interfaz mucho más similar a strace (1).

Al igual que xmon, xtruss en su modo predeterminado funciona configurando un servidor proxy X, esperando conexiones a eso y reenviándolos al servidor X real. Sin embargo, a diferencia de xmon, no tiene que lidiar con nada de eso a mano: no es necesario iniciar la utilidad de rastreo en un terminal y adjuntar procesos manualmente desde otro, a menos que realmente desee (en cuyo caso, el - La opción P hará eso). El modo principal de uso es simplemente escribir xtruss seguido de la línea de comando de su programa X; xtruss se encargará automáticamente de ajustar el entorno del nuevo programa para que apunte a su servidor proxy, y (también a diferencia de xmon) también se encargará de la autorización X automáticamente.

Como modo de uso alternativo, también puede adjuntar xtruss a una aplicación X que ya se está ejecutando, si no se dio cuenta de que querría rastrearla hasta que ya se haya iniciado. Este modo requiere la cooperación del servidor X, específicamente, no puede funcionar a menos que el servidor admita la extensión de protocolo RECORD, pero como los servidores X.Org modernos sí lo proporcionan, a menudo es útil.