← bitàcola

La pàgina respon

Qui és l'amo de la pulsació

La regla amb què rumb s'ha quedat és que la pàgina és el destinatari per defecte del teclat i la barra d'adreces és l'excepció.

Això capgira el que feia el shell abans. La barra d'adreces havia estat l'única cosa que havia demanat mai cap pulsació, així que les rebia totes, i un camp de text d'una pàgina era decoració. Ara url_focused és un sol booleà, fals a l'arrencada. Es posa a cert amb Cmd/Ctrl+L o amb un clic a la barra, i torna a fals amb Enter, que navega, o Escape, que abandona l'edició. A tota la resta, les tecles van a Servo.

Fins i tot fer que s'activés el comportament antic va demanar un arranjament que val la pena recordar, perquè el símptoma mentia. El bug es va reportar com a «backspace no esborra la URL». La realitat era que cap pulsació no feia absolutament res: GPUI només entrega esdeveniments de teclat a un element que sigui a la cadena de focus, i això exigeix dues coses alhora, track_focus(&FocusHandle) sobre un element enfocable i que la finestra hagi enfocat aquell handle de debò. La callback on_key_down no s'invocava mai. Ara el shell manté un handle de focus, el registra a l'arrel i torna a enfocar a cada render si el focus ha marxat — perquè la finestra l'ha perdut, perquè un element fill se l'ha quedat, pel que sigui.

a key is pressed shell shortcuts Cmd/Ctrl+L, tab switching… consumed otherwise URL bar, if focused url_focused consumed otherwise the page map_key → Servo never reaches Servo the page cannot see a key the shell claimed

De pulsació de GPUI a pulsació de Servo

map_key fa la traducció. Una llista curta de tecles amb nom — entre altres, les fletxes, enter, escape, backspace, home i end — passa directament d'un costat a l'altre. Tota la resta es converteix en un caràcter tret del key_char de GPUI, que ja ha resolt shift i AltGr, així que shift+a arriba com a «A» i option+s com a «ß». Quan no hi ha key_char — GPUI el suprimeix en les combinacions amb Ctrl —, s'utilitza en el seu lloc un nom de tecla d'un sol caràcter, i és així com Ctrl+C sobreviu com el caràcter «c». Qualsevol altra cosa no torna res i es descarta: els modificadors sols i totes les tecles de funció.

Una segona funció auxiliar mapeja els quatre booleans de modificador de GPUI als bitflags de Servo, i el modificador platform de GPUI — Cmd a macOS, Super a Linux — passa a ser META.

Després l'esdeveniment es construeix amb KeyboardEvent::new_without_event, i dos dels seus arguments són confessions. GPUI no dona al shell cap codi d'escaneig físic, així que code sempre és Unidentified i location sempre és estàndard. Servo governa l'entrada de text a partir del valor de la tecla més els modificadors, de manera que escriure funciona — però una pàgina que llegeixi event.code, un joc que lligui WASD per posició física o una drecera pensada per sobreviure a una disposició Dvorak, no en treu res d'aprofitable, de rumb. Els dos últims arguments són repeat i is_composing, tots dos fixats a fals al codi, perquè el shell no en fa el seguiment de cap dels dos.

El key-up també es reenvia, per a les pàgines que l'escolten, i se salta mentre la barra d'adreces té el focus, ja que la barra només actua amb el key-down.

On és realment el punter

Els esdeveniments de punter arriben de GPUI en píxels lògics relatius a la finestra. Servo vol un punt en l'espai propi del WebView, en píxels de dispositiu. Entre les dues coses hi ha dues correccions.

La primera és el desplaçament: el contingut web no comença a dalt de tot de la finestra; qui hi comença és la interfície del navegador. Abans que això es tractés, el mapeig passava la y relativa a la finestra tal qual, i desplaçava cada esdeveniment de punter cap avall exactament l'alçada de la barra d'eines. El que ho feia confus és que l'error no era uniforme — com que l'escala vertical feia servir l'alçada sencera de la finestra en comptes de l'alçada de l'àrea de contingut, l'error creixia linealment amb la y. Els clics a prop de dalt d'una pàgina queien més o menys on apuntaves. Els clics a prop del final d'una pàgina llarga es desviaven uns quants per cent.

WINDOW tab strip URL bar content rect click − chrome × rescale content SERVO RENDER TARGET same point skip the rescale and the error grows the further down you click

L'arranjament són dues funcions. content_metrics torna el rectangle de contingut de la disposició actual — la barra d'adreces sempre és una franja d'amplada completa a dalt, i la barra de pestanyes ocupa o bé una franja horitzontal o bé una columna vertical segons on l'hagi posada l'usuari, així que els desplaçaments canvien amb cada disposició. pointer_to_webview resta aquest desplaçament, retalla dins del rectangle i reescala per la mida de render de Servo dividida per la mida del contingut.

El reescalat no és redundant. El quad que GPUI mostra a pantalla i el destí de render de Servo poden no coincidir — un WM de mosaic que imposa una mida, l'escalat fraccionari — i, quan coincideixen, es redueix a una multiplicació per la identitat. L'alçada de la barra d'eines viu en una constant amb nom al costat de la disposició que la defineix, i aquesta és l'única raó per la qual va continuar sent correcta quan després es va afegir una barra de pestanyes damunt de la barra d'adreces i el desplaçament va canviar.

Cursors, i les formes que GPUI no té

Servo diu a qui l'incrusta quin punter vol mitjançant notify_cursor_changed al WebViewDelegate. El shell el desa en una cel·la i — aquesta és la part que és fàcil que se t'escapi — activa el flag de brut quan el valor ha canviat, de manera que es programa un fotograma de GPUI per aplicar-lo. Sense això, passar per sobre d'un enllaç en una pàgina altrament estàtica establiria el cursor i no es repintaria res per ensenyar-lo.

cursor_to_gpui mapeja les paraules clau de CSS al CursorStyle de GPUI: pointer a una mà que assenyala, text a un cursor en I, i les vuit direccions de redimensionament als seus equivalents. Dues notes d'aquesta funció. GPUI no té equivalent per a wait, progress, help, zoom-in, zoom-out ni all-scroll, així que aquests cauen a la fletxa — una pàgina que mostri un cursor d'ocupat no mostra res de res a rumb. I les direccions diagonals de redimensionament s'aparellen per geometria, pel que volen dir els noms de les variants, i no pas pels comentaris de documentació que GPUI hi té, que estan mal etiquetats.

La pantalla completa va entrar en el mateix commit, amb F11 i un botó de la barra d'eines — pantalla completa i no pas maximitzar perquè tots els compositors la respecten, _NET_WM_STATE_FULLSCREEN a X11 i xdg_toplevel.set_fullscreen a Wayland, inclosos els gestors de finestres de mosaic que ignoren de ple una petició de maximitzar. El botó hi és perquè alguns compositors s'empassen F11 abans.

Què encara no està connectat

Sense composició d'IME: is_composing està fixat a fals al codi i no hi ha cap camí de preedició, així que qui escrigui en japonès, xinès o coreà no pot fer servir aquest navegador. Sense arrossegar i deixar anar cap a la pàgina, sense tàctil, sense comandament.

Els botons del ratolí s'acaben a l'esquerre, el dret i el central; els botons de navegació de GPUI — els botons laterals que volen dir enrere i endavant — es reconeixen i tot seguit es descarten, a l'espera de decidir si són de la pàgina o del shell. Els esdeveniments de roda s'envien en mode píxel, i quan GPUI informa d'un scroll en línies, el shell multiplica per 16 com a substitut d'una alçada de línia que no llegeix d'enlloc.

I cada drecera que el shell reclama, la pàgina no la veurà mai. Cmd/Ctrl+T, W, L i R, Ctrl+Tab, Ctrl+Shift+D, F11 i F12 tornen abans que s'executi el codi de reenviament, i totes les altres tecles de funció les descarta map_key per falta de mapeig. Una aplicació web que vulgui F1 per a l'ajuda, o Ctrl+W com a drecera pròpia, ho porta clar i no té cap manera de demanar-ho.

La barra d'adreces tampoc no és un camp de text de debò. Clicar-hi posa el cursor al final i enlloc més: no pots clicar al mig d'una URL, ni arrossegar per seleccionar-ne un tros.

pointer keys scroll GPUI window owns the drawable Servo WebView owns the page notify_input_event notify_cursor_changed element-relative physical pixels → webview coordinates
Els esdeveniments viatgen en un sentit cap al WebView, i la forma del cursor torna per l'altre.