X Window System core protocol

L'X Window System core protocol (protocollo principale di X Window System) [1][2][3] è il protocollo base dell'X Window System, che è un sistema (che lavora in rete) di gestione delle finestre per bitmap display usato per creare interfacce grafiche utente in sistemi Unix, Unix-like e altri sistemi operativi. L'X Window System è basato su un modello client-server: un singolo server controlla l'hardware diinput/output, come lo schermo, la tastiera e il mouse; ogni applicazione (programma) agisce come un client, interagendo con l'utente e con gli altri client attraverso il server. Questa interazione è regolata dal X Window System core protocol. Esistono altri protocolli relativi all'X Window System, sia costruiti sopra l'X Window System core protocol sia come protocolli separati.

Il logo di X Window System

Nell'X Window System core protocol si possono inviare solo quattro tipi di pacchetti, in maniera asincrona, attraverso la rete: richieste, risposte, eventi ed errori. Le Richieste vengono inviate da un client ad un server per chiedere ti eseguire alcune operazioni (per esempio, creare una nuova finestra) e ritornare indietro i dati che contiene. Le Risposte sono inviate dal server per fornire tali dati. Gli Eventi vengono inviati dal server per notificare ai client dell'attività dell'utente o di altre occorrenze che sono interessati a conoscere. Gli Errori sono pacchetti inviati dal server per notificare ad un client di errori accaduti durante l'elaborazione delle sue richieste. Le richieste possono generare risposte, eventi ed errori; a parte questo, il protocollo non regola l'ordine specifico in cui i pacchetti sono inviati in rete. Esistono alcune estensioni al core protocol, ognuna delle quali aventi le proprie richieste, risposte, eventi ed errori.

L'X Window System fu concepito al MIT nel 1984 (la sua pubblicazione corrente X11 comparve nel settembre 1987). I suoi progettisti Bob Scheifler e Jim Gettys stabilirono come primi principi che il suo core protocol doveva "creare meccanismi e non politiche". Come risultato di ciò, il procollo principale non specifica l'interazione fra i client e tra client e utente. Queste interazioni sono l'oggetto di specifiche separate [4] come le specifiche ICCCM e freedesktop.org e sono tipicamente definite automaticamente dall'uso di un dato insieme di widget.

Panoramica

La comunicazione fra server e i client avviene mediante lo scambio di pacchetti attraverso un canale. La connessione viene stabilita dal client (nel protocollo non viene specificato come il client viene avviato). Il client invia anche il primo pacchetto, contenente l'ordine dei byte da usare e informazioni sulla versione del protocollo e il tipo di autenticazione che il client si aspetta che il server usi. Il server risponde con un pacchetto che stabilisce l'accettazione o il rifiuto della connessione, oppure con una richiesta di ulteriore autenticazione. Se la connessione viene accettata, il pacchetto di accettazione contiene dati per il client da usare nella seguente interazione con il server.

Un esempio di interazione tra un client e un server.

Dopo che la connessione viene stabilita, possono venire scambiati quattro tipi di pacchetto fra client e server nel canale:

  1. Request: Il client richiede informazioni dal server o gli chiede di eseguire un'azione.
  2. Reply: Il server risponde alla richiesta. Non tutte le richieste generano una risposta.
  3. Event: Il server invia un evento al client, per esempio un input da mouse o tastiera o una finestra che è stata mossa, ridimensionata o esposta.
  4. Error: Il server invia un pacchetto di errore se una richiesta non è valida. Dato che le richieste vengono accodate, i pacchetti di errore generati da una richiesta potrebbero non essere inviati immediatamente.

I pacchetti di richiesta e di risposta hanno lunghezza variabile, mentre pacchetti di errore ed evento hanno una lunghezza fissata di 32 byte.

I pacchetti di richiesta sono numerati sequenzialmente dal server non appena vengono ricevuti: la prima richiesta da un client viene numerata 1, la seconda 2, ecc. I 16 bit meno significativi del numero di sequenza di una richiesta vengono inclusi negli eventuali pacchetti di risposta ed errore generati dalla richiesta. Sono inclusi anche nei pacchetti di evento per indicare il numero di sequenza della richiesta che il server sta processando attualmente o ha appena finito di processare.

Finestre

Quella che di solito in altre interfacce grafiche utente viene chiamata una finestra, è una finestra top-level (di primo piano) nell'X Window System. Il termine finestra è anche usato per finestre che stanno dentro un'altra finestra, in altre parole, sotto finestre di una finestra padre. Gli elementi grafici tipo bottoni, menu, icone, ecc. sono tutti realizzati usando finestre.

Un possibile posizionamento di alcune finestre: 1 è la finestra radice, che copre l'intero schermo; 2 e 3 sono finestre top-level; 4 e 5 sono sotto finestre di 2. Le parti di finestra che sono fuori dalla propria finestra genitore non sono visibili.

Un client può richiedere la creazione di una finestra. Più precisamente può richiedere la creazione di una sotto finestra di una finestra esistente. Le finestre create dai client sono strutturate in un albero (una gerarchia). La radice di quest'albero è la root window (finestra radice), che è una finestra speciale creata automaticamente dal server all'avvio. Tutte le altre finestre sono direttamente o indirettamente sotto finestre della finestra radice. Visivamente la finestra radice è larga come tutto lo schermo (anche se potrebbe essere più larga, nel qual caso l'utente può muoversi sull'area visibile), e sta dietro a tutte le altre finestre.

Non è sempre garantito che il contenuto di una finestra venga preservato nel tempo. In particolare, il contenuto di una finestra può essere distrutto quando una finestra viene spostata, ridimensionata, coperta da altre finestre, e in generale resa totalmente o parzialmente non visibile. In particolare, il contenuto viene perso se l'X server non mantiene una backing store (memoria del passato) del contenuto della finestra. Il client può richiedere alla backing store che una finestra venga mantenuta, ma non c'e l'obbligo da parte del server di farlo. Perciò, i client non possono assumere che la backing store venga mantenuta. Se una parte visibile di una finestra ha un contenuto non specificato, viene inviato un evento per notificare che il contenuto della finestra deve essere ridisegnato.

Ogni finestra ha un insieme di attributi associato, tipo la geometria della finestra (dimensione e posizione), l'immagine di sfondo, se è stata fatta una richiesta alla backing store per essa, ecc. Il protocollo comprende richieste da parte dei client per ispezionare e cambiare gli attributi di una finestra.

Le finestre possono essere di InputOutput o InputOnly. Le finestre che possono essere mostrate sullo schermo e usate per disegnare sono del primo tipo. Quelle del secondo tipo non vengono mai mostrate nello schermo; sono utilizzate solo per ricevere input.

Anatomia di una finestra FVWM. L'area bianca è la finestra come viene creata e vista dall'applicazione client.

La cornice decorativa e la barra del titolo (che include eventualmente bottoni) che viene vista di solito attorno alle finestre sono create dal window manager, non dal client che crea la finestra. Il window manager gestisce anche gli input relativi a questi elementi, tipo il ridimensionamento della finestra quando l'utente clicca e trascina il bordo della finestra. I client di solito operano all'interno della finestra che hanno creato, a prescindere dai cambiamenti attuati dal window manager. Un cambiamento che un client deve tenere in considerazione è che i re-parenting window manager (window manager che adottano tutte le finestre, ovvero le rendono loro figlie), quali sono quasi tutti i window manager moderni, cambiano le finestre top-level in finestre che non sono la radice. Dal punto di vista del core protocol, il window manager è un client, con nessuna differenza rispetto alle altre applicazioni.

I dati su una finestra possono essere ottenuti eseguendo il programma xwininfo. Passandogli l'argomento -tree, questo programma mostra l'albero delle sotto finestre di una finestra, assieme ai loro identificatori e dati sulla geometria.

Pixmap (mappe di pixel) e drawable (oggetti disegnabili)

Una pixmap è una regione di memoria che può essere usata per disegnare. A differenza delle finestre, le pixmap non sono automaticamente disegnate sullo schermo. Comunque, il contenuto di una pixmap (o una parte di essa) può essere trasferito ad una finestra o viceversa. Questo permette l'uso di tecniche tipo il double buffering. La maggioranza delle operazioni grafiche che può essere eseguita su una finestra può anche essere fatta su una pixmap.

Le finestre e le pixmap sono entrambe chiamate drawables (oggetti disegnabili), e i loro contenuti risiedono nel server. Un client può comunque richiedere che il contenuto di un drawable venga trasferito dal server al client o viceversa.

Contesti grafici e fonts

Il client può richiedere un certo numero di operazioni grafiche, come pulire un'area, copiare un'area in un'altra, disegnare punti, linee, rettangoli e testo. A parte la pulizia, tutte le altre operazioni sono fattibili su tutti gli oggetti, sia finestre che pixmap.

La maggioranza di richieste di operazioni grafiche comprende un graphic context (contesto grafico), che è una struttura che contiene i parametri delle operazioni grafiche. Un contesto grafico include un colore di primo piano (foreground), un colore di sfondo (background), il font del testo e altri parametri grafici. Quando richiede un'operazione grafica, il client include un contesto grafico. Non tutti i parametri del contesto grafico sono necessari per l'operazione: per esempio, il font non ha alcun effetto nel disegnare una linea.

Il core protocol specifica l'uso di font lato-server[5]. Tali font sono salvati su file e il server vi accede o direttamente tramite il file system locale oppure via rete tramite un altro programma chiamato font server. I client possono fare richiesta della lista di font utilizzabili al server e possono richiedere che un font venga caricato (se non lo è già) o scaricato (se non usato da altri client) dal server. Un client può richiedere informazioni generali sul font (per esempio l'ascent del font) e lo spazio che una data stringa può occupare quando disegnata con un font specifico.

Il programma xfontsel permette all'utente di vedere i glifi di un font.

Il nome dei font sono stringhe arbitrarie a livello del X Window core protocol. Le convenzioni X logical font description [6] specificano come i font dovrebbero essere nominati in accordo con i loro attributi. Queste convenzioni specificano anche i valori delle proprietà opzionali che possono essere assegnate ai font.

Il programma xlsfonts stampa la lista dei font immagazzinati nel server. Il programma xfontsel mostra i glifi dei font e permette all'utente di selezionare il nome di un font per usarlo in un'altra finestra.

L'uso di font lato-server è attualmente deprecato in favore dei font lato-client.[7] Tali font sono renderizzati dal client, non dal server, con il supporto delle librerie grafiche Xft o cairo e l'estensione XRender. Nessuna specifica è data sui font lato-client nel core protocol.

Risorse e identificatori

Tutti i dati relativi alle finestre, pixmaps, font, ecc. sono salvati nel server. Il client conosce gli identificatori di questi oggetti che usa come nomi quando interagisce con il server. Per esempio, se un client desidera che venga creata una finestra, richiede al server di creare una finestra con un dato identificatore. L'identificatore può essere usato in seguito dal client per le richieste, per esempio, che venga disegnata una stringa nella finestra. Gli oggetti seguenti risiedono nel server sono noti al client attraverso identificatori numerici:

  • Window
  • Pixmap
  • Font
  • Colormap (una tavola dei colori, descritta sopra)
  • Graphic context (Contesto grafico)

Questi oggetti sono chiamati risorse. Quando un client richiede la creazione di una tale risorsa, specifica anche un identificatore per essa. Per esempio, per creare una nuova finestra, il client specifica sia gli attributi della finestra (genitore, larghezza, altezza, ecc.) sia l'identificatore associato alla finestra.

Gli identificatori sono interi a 32-bit con i 3 bit più significativi uguali a 0. Ogni client ha il proprio insieme di identificatori che può utilizzare per creare nuove risorse. Questo insieme è specificato dal server con due interi inclusi nel pacchetto di accettazione (il pacchetto che il server invia al client per informare che la connessione è stata accettata). I client scelgono gli identificatori che sono in questo insieme in modo tale da non avere sovrapposizioni: due oggetti fra finestre, pixmap, font, colormaps e graphic context non possono avere lo stesso identificatore.

Una volta che una risorsa è stata creata, il suo identificatore viene usato dal client per richiedere l'esecuzione di operazioni su di esso al server. Alcune operazioni interessano date risorse (per esempio, le richieste per muovere una finestra); altre richiedono dei dati delle risorse memorizzate dal server (per esempio, richieste di attributi di finestre).

Gli identificatori sono unici anche nel server, non solo nel client; per esempio, due finestre non possono avere lo stesso identificatore anche se create da due client diversi. Un client può accedere ad ogni oggetto noto l'identificatore. In particolare, può anche accedere alle risorse create da un altro client, anche se i loro identificatori sono al di fuori dell'insieme di identificatori che loro (i client) possono creare.

Come risultato di ciò, due client connessi allo stesso server possono usare lo stesso identificatore per riferirsi alla stessa risorsa. Per esempio, se un client crea una finestra con identificatore 0x1e00021 e passa questo numero 0x1e00021 ad un'altra applicazione (attraverso qualsiasi mezzo utilizzabile, per esempio salvando questo numero in un file che è accessibile anche all'altra applicazione), questa altra applicazione ha la possibilità di operare proprio nella stessa finestra. Quest'possibilità viene sfruttata per esempio dalla versione X Window di Ghostviwe: questo programma crea una sotto finestra, salvando il suo identificatore in una variabile d'ambiente e chiama Ghostscript; questo programma disegna il contenuto del file PostScript da mostrare in questa finestra.[8]

Le risorse sono normalmente distrutte quando il client che le ha create chiude la connessione col server. Comunque, prima di chiudere la connessione, un client può richiedere al server di non distruggerle.

Eventi

Gli eventi sono pacchetti inviati dal server al client per comunicare che qualcosa di cui il client potrebbe essere interessato a sapere è accaduto. Per esempio, un evento viene inviato quando l'utente preme un tasto o fa un click su un bottone del mouse. Gli eventi non sono solo usati per gli input; per esempio, eventi sono inviati per indicare la creazione di una nuova sotto finestra di una data finestra.

Ogni evento è relativo alla finestra. Per esempio, se l'utente clicca quando il puntatore è in una finestra, l'evento sarà relativo a quella finestra, Il pacchetto evento contiene l'identificatore di quella finestra.

Un client può richiedere al server di inviare un evento ad un altro client; questo viene usato per le comunicazioni fra client. Un tale evento viene generato per esempio quando un client richiede il testo che è attualmente selezionato: questo evento viene inviato al client che gestisce in quel momento la finestra che detiene la selezione.

L'evento Expose viene inviato quando un'area di una finestra dal contenuto non visibile diventa visibile. Il contenuto di una finestra potrebbe venir distrutto in alcune condizioni, per esempio, se la finestra è coperta e il server non sta mantenendo la backing store. Il server genera un evento Expose per notificare al client che una parte della finestra deve essere disegnata.

Un esempio di evento: quando viene premuto un tasto in una finestra, viene generato un evento e inviato al client a seconda della sua window event mask (maschera degli eventi della finestra) che il client può cambiare.

La maggior parte di tipi di eventi vengono inviati solo se il client ha mostrato interesse in loro in precedenza. Questo perché i client potrebbero essere interessati solo ad alcuni tipi di eventi. Per esempio, un client potrebbe essere interessato ad eventi relativi alla tastiera ma non a quelli relativi al mouse. Alcuni tipi di eventi sono comunque inviati ai client anche se non ne hanno fatto specificatamente richiesta.

I client specificano quali tipi di eventi vogliono che vengano inviati settando un attributo di una finestra. Per esempio, per fare in modo di ridisegnare una finestra quando il suo contenuto è stato distrutto, un client deve ricevere gli eventi Expose, che lo informano che quella finestra ha bisogno di essere ridisegnata nuovamente. Comunque al client verranno inviati eventi Expose solo se avrà stabilito precedentemente il suo interesse per questi eventi, e questo viene fatto impostando in modo appropriato l'attributo della maschera degli eventi della finestra.

Client differenti possono richiedere eventi nella stessa finestra. Possono anche impostare maschere degli eventi differenti nella stessa finestra. Per esempio, un client può richiedere solo eventi della tastiera in una finestra mentre un altro client può richiedere solo eventi del mouse nella stessa finestra. Questo è possibile perché il server, per ogni finestra, mantiene una maschera degli eventi separata per ogni client. Comunque, ci sono alcuni tipi di eventi che possono essere selezionati solo da un client alla volta per ogni finestra. In particolare questi eventi riportano il click dei bottoni del mouse e alcuni cambiamenti relativi alla gestione della finestra.

Il programma xev mostra gli eventi relativi ad una finestra. In particolare, xev -id WID richiede tutti i possibili eventi relativi alla finestra con identificatore WID e li stampa.

Esempio

Quello che segue è un possibile esempio di interazione tra un server e un programma che crea una finestra con una scatola nera dentro e appare alla pressione di un tasto. In questo esempio il server non invia nessuna risposta perché le richieste del client non generano risposte, ma potrebbero generare errori.

  1. Il client apre la connessione con il server e invia il pacchetto iniziale specificando il byte order da usare.
  2. Il server accetta la connessione (nessuna autorizzazione è richiesta in questo esempio) inviando un appropriato pacchetto che contiene altre informazioni tipo l'identificatore della finestra radice (per esempio 0x0000002b) e quali identificatori il client può creare.
  3. Il client richiede la creazione di un contesto grafico di default con identificatore 0x00200000 (questa richiesta, come le altre richieste in questo esempio, non genera risposte dal server).
  4. Il client richiede al server di creare una finestra top-level (cioè specifica che il genitore deve essere la root window 0x0000002b) con identificatore 0x00200001, di dimensione 200x200. posizione (10,10), ecc.
  5. Il client richiede un cambiamento di attributi della finestra 0x00200001, specificando l'interesse a ricevere i relativi eventi Expose e KeyPress
  6. Il client richiede che la finestra 0x00200001 venga mappata (mostrata sullo schermo).
  7. Quando la finestra viene resa visibile e il suo contenuto deve essere disegnato, il server invia al client un evento Expose.
  8. In risposta a questo evento, il client richiede che venga disegnata una scatola (un'area rettangolare) inviando una richiesta FillRectangle con identificatore di finestra 0x00200001 e contesto grafico 0x00200000.

Se la finestra era coperta da un'altra finestra e viene scoperta di nuovo, assumendo che la backing store non sia mantenuta, allora:

  1. Il server invia un altro evento Expose per dire al client che quella finestra deve essere ridisegnata.
  2. Il client ridisegna la finestra inviando una richiesta PolyFillRectangle.

Se viene premuto un tasto:

  1. Il server invia un evento KeyPress al client per notificargli che l'utente ha premuto un tasto.
  2. Il client reagisce di conseguenza (in questo caso termina).

Colori

A livello di protocollo, un colore è rappresentato da un intero senza segno a 32-bit chiamato pixel value. I seguenti elementi influenzano la rappresentazione dei colori:

  1. la color depth (profondità del colore)
  2. la color map (mappa dei colori), che è una tabella che contiene i valori di intensità
  3. la visual type (tipo di visuale). che specifica come viene usata la tabella per rappresentare i colori

In un codice più semplice possibile, la colormap è una tabella contenente una tripla RGB in ogni riga. Un pixelvalue x rappresenta il colore contenuto nell'x-esima riga della tabella. Se il client può cambiare le voci nella colormap, questa rappresentazione viene identificata dalla PseudoColor visual class. La StaticColor visual class è simile ma il client non può cambiare le voci nella colormap.

Ci sono in totale 6 possibili visual class, ognuna delle quali identifica un modo differente per rappresentare un pixelvalue con una tripla RGB. PseudoColor e StaticColor sono due. GrayScale e StaticGray sono altre due che differiscono dalle prime dal fatto che vengono usate solo scale di grigi.

Le due visual class che rimangono differiscono dalle precedenti perché scorporano i pixelvalue in tre parti e usano tre tabelle separate l'intensità di rosso, verde, e blu. In accordo con questa rappresentazione del colore, un pixelvalue viene convertito in una tripla RGB come segue.

  1. il pixelvalue è visto come una sequenza di bit
  2. la sequenza è scomposta in tre parti
  3. ognuna di queste tre sequenze di bit è vista come un intero e usata come un indice per trovare un valore in ognuna di queste 3 tabelle separate

Questo meccanismo richiede che la colormap venga composta da tre tabelle separate, una per ogni colore primario. Il risultato della conversione è ancora una tripla di valori di intensità. Le visual class che usa questa rappresentazione sono DirectColor e TrueColor, che differiscono nel lasciar cambiare o meno le colormap all'utente.

Questi sei meccanismi per la rappresentazione dei colori con i pixelvalue richiedono tutti per funzionare qualche paramentro addizionale. Questi parametri sono collezionati in una visual type, che contiene una visual class e altri parametri della rapparesentazione dei colori. Ogni server ha un insieme fisso di visual type, ognuna associata ad un identificatore numerico. Questi identificatori sono interi senza segno a 32-bit ma non sono necessariamente diversi dagli identificatori di risorse o atomi.

Quando la connessione da un client viene accettata, il pacchetto di accettazione inviato dal server contiene una sequenza di blocchi, ognuno contenente informazioni su un singolo schermo. Per ogni schermo, il blocco relativo contiene una lista di altri blocchi, ognuno dei quali relativo ad una specifica color depth (profondità del colore) supportata dallo schermo. Per ogni profondità, questa lista contiene una lista di visual type. Come risultato di ciò, ogni schermo è associato ad un numero di possibili profondità, e ogni profondità di ogni schermo è associato a un numero di possibili visual types. Una data visual type può essere usata per più di uno schermo e per profondità differenti.

Per ogni visual type, il pacchetto di accettazione contiene sia gli identificatori che i parametri attuali relativi contenuti (visual class, ecc.) Il client salva queste informazioni, dato che non può richiederle in seguito. In più, i client non possono cambiare o creare nuove visual type. Le richieste per la creazione di una nuova finestra comprendono la profondità e l'identificatore della visual type da usare per rappresentare i colori della finestra stessa.

Le colormap sono usate a prescindere dal fatto che l'hardware che controlla lo schermo (ad esempio una scheda grafica) usa una palette, che è una tavola che viene anche usata per rappresentare i colori. I server usano colormap anche se l'hardware non sta usando una palette. Ogni volta che l'hardware usa una palette, può essere installato solo un numero limitato colormap. In particolare, una colormap viene installata quando l'hardware può mostrare i colori in accordo con essa. Un client può richiedere al server di installare una colormap. Comunque, questo potrebbe richiedere la rimozione di un'altra colormap: l'effetto è che le finestre che usano una colormap rimossa non sono mostrate con i colori corretti, un effetto chiamato color flashing o technicolor. Questo problema può essere risolto usando colormap standard che sono colormap con una associazione predicibile fra pixelvalue e colori. Grazie a questa proprietà, le colormap standard possono essere usate da applicazioni differenti.

La creazione di colori è regolata dalla convenzione ICCCM. Le colormap standard sono regolate dal ICCCM e dalle specifiche Xlib.

Una parte del sistema dei colori di X è la X Color Management System (xcms) (sistema di gestione del colore di X). Questo fu introdotto con X11R6 Release 5 nel 1991. Questo sistema consiste di diverse funzionalità addizionali in xlib, che si trova nella serie di funzioni di Xcms*. Questo sistema definisce schemi di colore device independent (indipendenti dal dispositivo) che possono essere convertiti in sistemi RGB dipendenti dal dispositivo. Il sistema consiste di funzioni di xlib Xcms* e, come nella X Device Color Characterization Convention (XDCCC) che descrive come convertire i vari sistemi di colori indipendenti dal dispositivo in sistemi di colore RGB dipendenti dal dispositivo. Questo sistema supporta CIE XYZ, xyY, L *u*v e L *a*b così come il TekHVC colour systems.[9],[10]

Atomi

Gli Atomi sono interi a 32-bit che rappresentano stringhe. I progettisti del protocollo introdussero gli atomi al fine di rappresentare stringhe con una dimensione fissa e corta:[11] mentre una stringa potrebbe essere arbitrariamente lunga, un atomo è sempre un intero a 32-bit. Le ridotte dimensioni di un atomo vennero sfruttate nei tipi di pacchetti che devono essere tendenzialmente inviati molte volte con le stesse stringhe; da questo deriva un uso più efficiente della rete. La dimensione fissa di un atomo venne sfruttata specificando una dimensione fissata per ogni evento in 32 byte: pacchetti di dimensione fissa possono contenere atomi, mentre non possono contenere stringhe.

Precisamente, gli atomi sono identificatori di stringhe salvate nel server. Sono simili agli identificatori di risorse (finestre, pixmap, ecc.) ma differiscono da questi per due motivi. Quando un client richiede la creazione di un nuovo atomo, invia solamente al server la stringa da salvare, non il suo identificatore; questo identificatore è scelto dal server e restituito come risposta al client. La seconda differenza importante fra risorse e atomi è che gli atomi non sono associati ai client. Una volta creati, un atomo sopravvive finché il server si spegne o si riavvia (questo non il comportamento di default delle risorse).

Gli atomi sono identificatori e sono perciò unici. Comunque, un identificatore di atomo e uno di risorsa possono coincidere. La stringa associata ad un atomo è chiamata atom name (nome dell'atomo). Il nome di un atomo non può essere cambiato dopo la creazione e due atomi non possono avere lo stesso nome. A conseguenza di questo, il nome di un atomo è comunemente usato per indicare l'atomo stesso: “l'atomo ABCD” significa, precisamente, "l'atomo al quale la stringa ABCD è associata" o "l'atomo con nome ABCD". Un client può richiedere la creazione di un nuovo atomo ma anche l'identificatore di un atomo di una data stringa. Alcuni atomi sono "predefiniti" (creati dal server con un dato identificatore e una data stringa).

Gli atomi vengono usati per un certo numero di scopi, la maggior parte relativi alla comunicazione fra diversi client connessi allo stesso server. In particolare, sono usati nell'associare le proprietà delle finestre, descritte in precedenza.

La lista di tutti gli atomi residenti in un server possono essere stampati usando il programma xlsatoms. In particolare, questo programma stampa ogni atomo (il suo identificatore, ossia un numero) con il suo nome (la sua stringa associata).

Proprietà

Ogni finestra ha un insieme predefinito di attributi e un insieme di proprietà, tutte salvate nel server e accessibili ai client tramite richieste appropriate. Gli attributi sono dati sulle finestre, come la loro dimensione, posizione, colore di sfondo, ecc. Le proprietà sono pezzi arbitrari di dati associati alla finestra. Al contrario degli attributi, le proprietà non hanno significato a livello del X Window core protocol. Un client può memorizzare dati arbitrari in un proprietà di una finestra. Le proprietà sono usate per la maggior parte per la comunicazione da client a client.

Una proprietà è caratterizzata da un nome, un tipo e un valore. Una proprietà è simile ad una variabili in un linguaggio imperativo, dove l'applicazione può creare una nuova proprietà con un dato nome e di un certo tipo e salvarci un valore. Le proprietà sono associate alle finestre: due proprietà con lo stesso nome, aventi tipi e valori differenti possono esistere in due finestre differenti.

Il nome, tipo e valore di una proprietà sono stringhe, più precisamente, sono atomi, ovvero strighe salvate nel server e accessibli ai client tramite identificatori. Una applicazione client può accedere a una data proprietà usando l'identificatore dell'atomo contenente il nome della proprietà.

Le proprietà sono usate principalmente per la comunicazione fra client. Per esempio, la proprietà chiamata WM_NAME (la proprietà nominata dall'atomo a cui è associata la stringa "WM_NAME") è usata per salvare il nome per la finestra; i gestori di finestre di solito leggono questa proprietà e visualizzano il nome della finestra nella barra del titolo.

Alcuni tipi di comunicazione inter-client usano proprietà della finestra radice. Per esempio, in accordo con la specifica freedesktop window manager [12], i gestori di finestre dovrebbero salvare l'identificatore della finestra correntemente attiva nella proprietà di nome _NET_ACTIVE_WINDOW della finestra radice. Le X resources, che contengono i parametri dei programmi, sono anch'esse salvate in proprietà della finestra radice; In questo modo, tutti i client possono accedere ad esse, anche se girano in computer differenti.

Il programma xprop stampa le proprietà di una data finestra; xprop -root stampa il nome, tipo e valore di ogni proprietà della finestra radice.

Mappings (Mappature)

Questa chiave genera sempre lo stesso keycode, ma i simboli /, 7 e { sono associati a tre differenti keysyms.

In X Window System, ogni singolo tasto è associata ad un numero nell'intervallo 8-255 chiamato keycode (codice tasto). Un keycode identifica solo un tasto, non un particolare carattere o termine (ad esempio "Page Up") fra quelli che potrebbero essere raffigurati nel tasto. Ognuno di questi caratteri o termini viene invece identificato da un keysym. Mentre un keycode dipende solo dal tasto appena premuto, un keysym potrebbe dipendere, per esempio, dalla pressione o meno del tasto Shift o qualche altro modificatore (Ctrl, Alt, ecc.).

Quando un tasto viene premuto o pubblicato, il server invia eventi del tipo KeyPress o KeyRelease al client appropriato. Questo evento contiene:

  1. il keycode del tasto premuto
  2. lo stato corrente dei modificatori (Shift, Control, ecc.) e dei bottoni del mouse
Come viene tradotto un keycode in un keysym.

Il server invia quindi un keycode e lo stato dei modificatori senza cercare di tradurlo in uno specifico carattere. È responsabilità del client fare questa conversione. Per esempio, un client potrebbe ricevere un evento che stabilisce che un dato tasto è stato premuto mentre il modificatore Shift era premuto. Se questo tasto normalmente genererebbe il carattere "a", il client (e non il server) associa questo evento al carattere "A".

Mentre la traduzione dei keycode in keysym viene fatta dal client, la tabella che rappresenta le associazioni viene mantenuta nel server. Salvare questa tabella in un posto centralizzato la rende accessibile a tutti i client. I tipici client richiedono solo questa mappatura e la usano per decodificare il keycode e i modificatori di un evento relativo a un tasto in un keysym. Comunque, i client possono anche cambiare questa mappatura a proprio piacere.

Il server X lavora con al più otto modificatori. Comunque, ogni modificatore può essere associato a più di un tasto. Questo è necessario perché molte tastiere hanno tasti duplicati per gli stessi modificatori. Per esempio, molte tastiere hanno due tasti "Shift" (uno a destra e una sinistra). Questi tasti producono due keycode differenti quando premuti, ma il server X li associa entrambi al modificatore "Shift".

Per ognuno degli otto modificatori, il server X mantiene una lista di keycode, che lui considera essere modificatori. Ad esempio, se la lista del primo modificatore ("Shift") contiene il keycode 0x37 allora il tasto che produce il keycode 0x37 è considerato un tasto modificatore "di tipo shift" dal server X.

La lista che mappa i modificatori è mantenuta dal server X ma può essere cambiata da ogni client. Per esempio, un client può richiedere che il tasto "F1" venga aggiunto alla lista dei modificatori di tipo "Shift". Da qui in avanti, questo tasto si comporta come un altro modificatore di tipo Shift. Comunque, il keycode corrispondente a F1 viene comunque generato quando questo tasto viene premuto. Come risultato di ciò, F1 opera come faceva prima (ad esempio, potrebbe venire aperta una finestra di help), ma opera anche come il tasto Shift (premendo "a" in un editor di testo e assieme F1, verrebbe stampato il carattere "A").

Il server X mantiene e usa una mappatura dei modificatori per i bottoni del mouse. Comunque, i bottoni possono essere solo permutati. Questo è maggiormente utile per scambiare il tasto destro con quello sinistro per gli utenti mancini.

Il programma xmodmap mostra e cambia mappature di tasti, modificatori e bottoni del mouse.

Grabs (Catture)

Una grab è una condizione nella quale tutti gli eventi di mouse o tastiera sono inviati ad un singolo client. Un client può richiedere la cattura di mouse, tastiera o di entrambi: se la richiesta è approvata dal server, tutti gli eventi di mouse/tastiera sono inviati al client che ha richiesto la cattura finché la cattura viene pubblicata. Gli altri client non riceveranno questi eventi.

Quando richiede una grab, un client specifica una grab window (finestra di cattura): tutti gli eventi sono inviati al client come se fossero relativi alla grab window. Comunque, gli altri client non ricevono gli eventi anche se li hanno selezionati nella grub window. Ci sono due tipi di catture:

attiva
la cattura ha luogo immediatamente
passiva
la cattura ha luogo solo quando un viene premuto un tasto o un bottone del mouse specificato in precedenza e termina quando questo viene pubblicato.
Se il puntatore (del mouse) o la tastiera sono frozen (bloccati, congelati), gli eventi che generano sono bloccati in una coda. Se sono catturati, i loro eventi sono instradati al client che detiene la cattura invece che alla finestra a cui erano destinati. Gli eventi del puntatore possono essere scartati in base alla event mask (maschera degli eventi).

Una richiesta di cattura può includere una richiesta di freezing (congelamento) di tastiera o puntatore. La differenza tra cattura e congelamento è che la cattura cambia il destinatario degli eventi, mentre il congelamento ferma proprio la loro consegna. Quando una periferica è congelata, gli eventi che genera sono salvati in una coda da cui essere consegnati normalmente una volta finito il congelamento.

Per eventi del puntatore, c'è un parametro addizionale che influenza la consegna degli eventi: una event mask (maschera degli eventi), che specifica quali tipi di eventi sono da consegnare e quali devono essere scartati.

La richiesta di cattura include un campo per specificare cosa succede agli eventi che verrebbero inviati al client che detiene la cattura anche se non hanno stabilito la cattura. In particolare, il client può richiedere che questi vengano inviati normalmente in accordo con la cattura. Queste due condizioni non sono la stessa cosa come potrebbe sembrare. Per esempio, un client che normalmente riceverebbe gli eventi della tastiera nella prima finestra potrebbe richiedere che la tastiera venga catturata da una seconda finestra. Gli eventi che normalmente vengono inviati alla prima finestra potrebbero o no essere rediretti alla finestra di cattura in base al parametro nella richiesta di cattura.

Un client può anche richiedere la cattura di un intero server. In questo caso, nessuna richiesta sarà processata dal server eccetto quelle provenienti dal client che ha richiesto la cattura.

Altro

Nel core protocol esistono altri tipi di eventi e richieste. Un primo tipo di richieste sono relative alla relazione di parentela tra finestre: un client può richiedere di cambiare il padre di una finestra o può richiedere informazioni sulla parentela delle finestre. Altre richieste sono relative alla selezione, che comunque è governata per la maggior parte da altri protocolli. Altre richieste sono quelle sul focus e la forma del cursore. Un client può richiedere che il proprietario di una risorsa (finestra, pixmap, ecc.) venga ucciso, il che causa la terminazione della connessione con il server. Infine, un client può richiedere di inviare una richiesta no-operation al server.

Estensioni

La shape extension permette a un oclock di creare una finestra circolare.

Il X Window core protocol fu progettato per essere estensibile. Esso specifica un meccanismo per interrogare le estensioni disponibili e come sono fatti gli eventi, le estensioni, i pacchetti di errore dell'estensione.

In particolare, un client può richiedere i dati relativi a una estensione specifica dalla lista delle estensioni disponibili. I pacchetti delle estensioni sono simili a quelli del core protocol. Il core protocol specifica che richieste, eventi e pacchetti di errore contengono un intero che indica il tipo (per esempio la richiesta di creazione di una nuova finestra è indicata dal numero 1). Un intervallo di questi interi è riservato per le estensioni.

Autorizzazioni

Lo stesso argomento in dettaglio: Autorizzazioni X Window.

Quando il client inizialmente stabilisce una connessione con il server, il server può replicare o accettando la connessione o rifiutandola o richiedendo un'autorizzazione. Il core protocol non specifica il processo di autenticazione, che dipende dal tipo di autenticazione usata, a parte che deve finire con l'invio o di un'accettazione o di un rifiuto da parte del server.

Durante la regolare interazione tra client e un server, solo le richieste relative all'autenticazione riguardano il metodo di accesso host-based. In particolare, un client può richiedere che questo metodo sia abilitato e può richiedere la lettura e la modifica della lista di client che sono autorizzati a connettersi. Le applicazioni tipiche non usano queste richieste; queste sono usate dal programma xhost per dare all'utente o uno script l'accesso alla lista di accesso. Il metodo di accesso host-based è considerato insicuro.

Xlib e altre librerie client

Lo stesso argomento in dettaglio: Xlib.

La maggior parte dei programmi client comunicano con il server attraverso la libreria Xlib client. In particolare, la maggior parte di client usa librerie tipo Xaw, Motif, GTK+, o Qt le quali a loro volta usano Xlib per interagire con il server. L'uso di Xlib ha i seguenti effetti:

  1. Xlib rende i client sincroni per quanto riguarda eventi e risposte:
    1. le funzioni Xlib che inviano richieste si bloccano finché non ricevono le appropriate risposte, se ne aspettano qualcuna; in altre parole, un client X Window che non usa Xlib può inviare una richiesta al server e dopo fare altre operazioni mentre sta aspettando la risposta, ma un client che usa Xlib può solamente chiamare una funzione Xlib che invia la richiesta e aspetta la risposta, perciò bloccando il client mentre aspetta (a meno che un client non faccia partire un nuovo thread prima di chiamare la funzione);
    2. mentre il server invia gli eventi in maniera asincrona, Xlib salva gli eventi ricevuti dal client in una coda; il programma client può accedervi solo chiamando esplicitamente funzioni della libreria di X11; in altre parole, il client è forzato a bloccarsi o stare in busy waiting (attesa attiva) se sta aspettando un evento.
  1. Xlib non invia richieste al server immediatamente, ma le salva in una coda, chiamata output buffer; le richieste nell'output buffer sono effettivamente inviate quando:
    1. il programma ne richiede esplicitamente l'invio chiamando una funzione di libreria tipo XFlush;
    2. il programma chiama una funzione che fa come risultato qualcosa che coinvolge una richiesta dal server, tipo XGetWindowAttributes;
    3. il programma chiede di un evento nella coda degli eventi (per esempio chiamando XNextEvent) e la chiamata si blocca (ad esempio, XNextEvent si blocca se la coda è vuota).

Librerie di più alto livello tipo Xt (che è a volte usato da Xaw e Motif) permettono al programma client di specificare le funzioni di callback associate ad alcuni eventi; la libreria si cura di interrogare la coda degli eventi chiamando la funzione appropriata quando richiesta; alcuni eventi tipo quelli che indicano la necessità di ridisegnare una finestra sono gestiti internamente da Xt.

Librerie a basso livello, tipo XCB, forniscono accesso asincrono al protocollo, permettendo un miglior occultamento della latenza.

Quello che il procollo principale di X Window System non specifica

Il procollo principale di X Window non regola la comunicazione inter-client a non specifica come le finestre sono usate per formare gli elementi visuali comuni in un'interfaccia grafica utente (bottoni, menu, ecc.) Gli elementi dell'interfaccia grafica utente sono definiti dalle librerie client che realizzano Widget (informatica)s toolkit. La comunicazione inter-client è considerata da altri standard tipo le specifiche ICCCM e freedesktop.[12]

La comunicazione inter-client è centrale nelle selezioni, cut buffers r nel trascinamento, che sono metodi usati da un utente per trasferire dati fra una finestra all'altra. Dato che le finestre potrebbero essere controllate da programmi diversi, un protocollo per scambiare questi dati è necessario. La comunicazione inter client è rilevante anche per i Window manager che sono programmi che controllano la visualizzazione delle finestre e il "look-and-feel" generale di una GUI. Un'altra questione ancora dove la comunicazione inter-client è per certi versi rilevante è quella del session manager.

Come un utente fa partire una sessione è un'altra questione non coperta dal core protocol. Di solito, questo avviene automaticamente tramite il display manager. L'utente può comunque far partire una sessione manualmente facendo girare il programma xinit o startx.

Note

Voci correlate

Collegamenti esterni