Ottenere informazioni sulle applicazioni client in esecuzione su un display con le funzioni del API di X11

Da Gambas-it.org - Wikipedia.

La libreria X11 ci consente anche di ottenere alcune informazioni generiche sulle applicazioni client in esecuzione su un display.

Sarà necessario richiamare la libreria del sistema X11: "libX11.so.6.4.0 " , nonché la libreria Xmu: "libXmu.so.6.2.0 ".

Mostriamo di seguito un possibile breve codice al riguardo:

Library "libX11:6.4.0"

Public Struct XTextProperty
  value As Pointer
  encoding As Long
  formatI As Integer
  nitems As Long
End Struct

Public Struct XClassHint
  res_name As Pointer
  res_class As Pointer
End Struct

Private Const XA_STRING As Integer = 31

' Display *XOpenDisplay(char *display_name)
' Opens a connection to the X server that controls a display.
Private Extern XOpenDisplay(display_name As Pointer) As Pointer

' Window XDefaultRootWindow(Display *display)
' Return the root window for the default screen.
Private Extern XDefaultRootWindow(display As Pointer) As Integer

' Status XGetWMClientMachine(Display *display, Window w, XTextProperty *text_prop_return)
' Performs an XGetTextProperty() on the WM_CLIENT_MACHINE property.
Private Extern XGetWMClientMachine(display As Pointer, w As Long, text_prop_return As XTextProperty) As Integer

' Status XGetCommand(Display *display, Window w, char ***argv_return, int *argc_return)
' Reads the WM_COMMAND property from the specified window and returns a string list.
Private Extern XGetCommand(display As Pointer, w As Long, argv_return As Pointer, argc_return As Pointer) As Integer

' int XFree(void *)
' It's a general-purpose Xlib routine that frees the specified data.
Private Extern XFree(po As Pointer) As Integer

' char * XGetAtomName(Display *display, Atom atom)
' Returns the name associated with the specified atom.
Private Extern XGetAtomName(display As Pointer, atom As Long) As Pointer

' XGetWMName(Display *display, Window w, XTextProperty *text_prop_return)
' Calls XGetTextProperty() to obtain the WM_NAME property.
Private Extern XGetWMName(display As Pointer, w As Long, text_prop_return As XTextProperty) As Integer

' Status XGetWMIconName(Display *display, Window w, XTextProperty *text_prop_return)
' Calls XGetTextProperty() to obtain the WM_ICON_NAME property.
Private Extern XGetWMIconName(display As Pointer, w As Long, text_prop_return As XTextProperty) As Integer

' Status XQueryTree(Display *display, Window w, Window *root_return, Window *parent_return, Window **children_return, unsigned int *nchildren_return)
' Returns the root ID, the parent window ID, a pointer to the list of children windows (NULL when there are no children), and the number of children in the list for the specified window.
Private Extern XQueryTree(display As Pointer, w As Long, root_return As Pointer, parent_return As Pointer, children_return As Pointer, nchildren_return As Pointer) As Integer

' Status XGetClassHint(Display *display, Window w, XClassHint *class_hints_return)
' Returns the class hint of the specified window to the members of the supplied structure.
Private Extern XGetClassHint(display As Pointer, w As Long, class_hints_return As XClassHint) As Integer

' XCloseDisplay (Display *display)
' Closes a display or disconnect from the X server.
Private Extern XCloseDisplay(display As Pointer)


' Window XmuClientWindow(Display *dpy, Window win)
' Finds a window at or below the specified window which has a WM_STATE property.
Private Extern XmuClientWindow(display As Pointer, w As Long) As Long In "libXmu:6.2.0"


' void exit(int status)
' Terminates the calling process immediately.Any Open file descriptors belonging To the process are closed And any children Of the process are inherited.
Private Extern exitus(status As Integer) In "libc:6" Exec "exit"


Public Sub Main()

 Dim i, nc As Integer
 Dim dis, figli As Pointer
 Dim dm, root, client, l As Long
 Dim st As Stream
   
 dis = XOpenDisplay(0)
 If dis == 0 Then Error.Raise("Impossibile aprire lo schermo !")
   
 root = XDefaultRootWindow(dis)
 Proprieta_Clienti(dis, root)

 If Not XQueryTree(dis, root, VarPtr(dm), VarPtr(dm), VarPtr(figli), VarPtr(nc)) Then Return

 st = Memory figli For Read
 For i = 0 To nc - 1
   Read #st, l
   client = XmuClientWindow(dis, l)
   If client <> 0 Then Proprieta_Clienti(dis, client)
 Next
 st.Close
   
' Va in chiusura:
 XCloseDisplay(dis)
 exitus(0)
   
End
 
Private Procedure Proprieta_Clienti(dis As Pointer, w As Long)

 Dim mxtp, nxtp, xtp As New XTextproperty
 Dim clh As New XClassHint
 Dim cli, i As Integer
 Dim clip, p As Pointer
 Dim st As Stream
 Dim s As String
 
 If Not XGetWMClientMachine(dis, w, mxtp) Then
   mxtp.value = 0
   mxtp.encoding = 0
 Endif

 clip = Alloc(Sizeof(gb.Integer), 2)

 If Not XGetCommand(dis, w, VarPtr(clip), VarPtr(cli)) Then
   If mxtp.value > 0 Then XFree(mxtp.value)
   Return
 Endif

' Scrive l'informazione d'intestazione dell'applicazione:
 Print "\nFinestra &"; Hex(w); ":"
 If mxtp.value == 0 Then Print "nullo", Hex(w)
 Testo(dis, "  Machine:  ", mxtp)

 If XGetWMName(dis, w, nxtp) Then
   Testo(dis, "  Name:  ", nxtp)
   If nxtp.value > 0 Then XFree(nxtp.value)
 Endif

 If mxtp.value > 0 Then XFree(mxtp.value)

 If XGetWMIconName(dis, w, xtp) <> 0 Then
   Testo(dis, "  Icon Name:  ", xtp)
   If xtp.value > 0 Then XFree(xtp.value)
 Endif

' Scrive il comando dell'applicazione:
 st = Memory clip For Read
 While i < cli
   Read #st, p
   Print "  Command:  "; String@(p)
   Inc i
 Wend
 st.Close

 s = "  Instance/Class:  "
 If XGetClassHint(dis, w, clh) Then
   If clh.res_name > 0 Then
     s &= String@(clh.res_name)
     XFree(clh.res_name)
   Endif
   s &= "/"
   If clh.res_class > 0 Then
     s &= String@(clh.res_class)
     XFree(clh.res_class)
   Endif
 Endif
 Print s
   
End

Private Procedure Testo(dis As Pointer, s As String, xtp As XTextproperty)
 
 If (xtp.encoding == 0) Or (xtp.formatI == 0) Then
   Print ""
   Return
  Endif

 If (xtp.encoding = XA_STRING) And (xtp.formatI == 8) Then
   If xtp.value > 0 Then
     s &= String@(xtp.value)
     Print s
   Endif
 Else
   s &= Sconosciuto(dis, xtp.encoding, xtp.formatI)
 Endif

End

Private Function Sconosciuto(dis As Pointer, tipo As Long, formato As Integer) As String
  
 Dim s As String
 
 s = "<Tipo sconosciuto "
   
 If tipo == 0 Then
   s &= "Nessuno"
 Else If XGetAtomName(dis, tipo) > 0 Then
   s &= XGetAtomName(dis, tipo)
 Else
   Print Null
 Endif

 s &= CStr(tipo) & " o formato " & CLong(formato) & ">"
   
 Return s
 
End