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 X (nella sua attuale versione): "libX11.so.6.3.0" , nonché la libreria Xmu (nella sua attuale versione): "libXmu.so.6.2.0"


Mostriamo di seguito un possibile breve codice al riguardo:

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


Library "libX11:6.3.0"

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$ As String) As Pointer

' Window XDefaultRootWindow(Display *display)
' Return the root window for the default screen.
Private Extern XDefaultRootWindow(displayP 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) as pointer
' Returns the name associated with the specified atom.
Private Extern XGetAtomName(display As Pointer, atom As Long)

' XGetWMName(Display *display, Window w, XTextProperty *text_prop_return)
' Calls XGetTextProperty() to obtain the WM_NAME property.
Private Extern XGetWMName(displayP 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(displayP 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(displayP 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(displayP 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(displayP 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(displayP 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(Null)
  If IsNull(dis) 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(8)

  If Not XGetCommand(dis, w, VarPtr(clip), VarPtr(cli)) Then
    If IsNull(mxtp.value) = False Then XFree(mxtp.value)
    Return
  Endif

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

  If XGetWMName(dis, w, nxtp) Then
    Testo(dis, "  Name:  ", nxtp)
    If IsNull(nxtp.value) = False Then XFree(nxtp.value)
  Endif

  If IsNull(mxtp.value) = False Then XFree(mxtp.value)

  If XGetWMIconName(dis, w, xtp) <> 0 Then
    Testo(dis, "  Icon Name:  ", xtp)
    If IsNull(xtp.value) = False 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 IsNull(clh.res_name) = False Then
      s &= String@(clh.res_name)
      XFree(clh.res_name)
    Endif
    s &= "/"
    If IsNull(clh.res_class) = False 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 IsNull(xtp.value) = False 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 IsNull(XGetAtomName(dis, tipo)) = False Then
    s &= XGetAtomName(dis, tipo)
  Else
    Print Null
  Endif

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