Archive for the 'Trucos' Category

Tablet con systemd

miércoles, septiembre 24th, 2014

Hace un par de días actualicé el sistema Debian que le había instalado a mi tablet, y me encontré con la desagradable sorpresa de que mi gestor de ventanas y mi driver táctil dejaron de funcionar. El motivo es que, recientemente, Debian se ha cambiado a systemd, por lo que tuve que hacer algunos cambios para adaptarlo.

El primer y más fundamental cambio fue reemplazar los scripts en bash por ficheros de configuración de systemd. Este es el fichero para lanzar el driver táctil:

[Unit]
Description=GSLx680 user-space driver launcher for systemd

[Service]
Type=simple
ExecStart=/bin/gslx680 -new_scroll /dev/i2c-1 /etc/gslx680/firmware.cfg
ExecStop=killall gslx680

[Install]
WantedBy=multi-user.target

Este fichero lanza durante el arranque el driver, y durante el apagado del sistema lo mata.

El fichero para lanzar las X es similar:

[Unit]
Description=Launch X11

[Service]
Type=simple
User=debian
ExecStart=/usr/bin/startx
ExecStop=killall xinit

[Install]
WantedBy=multi-user.target

El único cambio es que especificamos con qué usuario queremos lanzar el comando: en este caso el usuario es debian.

Otro cambio que tuve que hacer fue eliminar, en el fichero .xinitrc, el que se lance ck-launch-session, el gestor de sesiones de ConsoleKit. Este ya no es necesario porque de ello se encarga systemd.

Por último, para apagar el sistema el gestor de ventanas ya no ejecuta halt, sino systemctl poweroff, con lo que ya no es necesario que haya un comando para ello con el bit suid activo.

Un último detalle: tuve que desinstalar el demonio pulseaudio para conseguir que reprodujese vídeos. Todavía no se el motivo de que con él lanzado no funcione (el audio queda bloqueado y tanto mplayer como vlc se quedan congelados esperando a que se libere).

Tamaño constante en GTK

sábado, septiembre 6th, 2014

Hace unos días envié un parche para Slingshot, el lanzador de aplicaciones de Elementary OS. El problema que tenía es que tenía fijados al pixel los tamaños de todos los elementos. Esto se adapta bien si se utiliza el tema de Elementary y, además, en lengua inglesa. Sin embargo, en el momento en que se utiliza otro tema, o bien una lengua en la que alguna categoría de programas sea mucho más larga que en inglés, nos encontraremos con que el conjunto de iconos queda recortado por la derecha:

Se supone que esto no debería ocurrir porque Gtk permite crear interfaces que se redimensionen de manera automática, sin embargo en slingshot esto no ocurría. El motivo es que los iconos no están hechos con un Gtk.IconView, sino con botones dentro de un Gtk.Grid. Pero los autores querían, además, que dichos botones tuviesen un tamaño fijo de 130×130 pixels exactamente, por lo que la única idea que se les ocurrió fue fijar el tamaño exacto de la ventana que contiene todo el lanzador, incluyendo la lista de categorías, el buscador, etc. El motivo de hacerlo así es que dentro de cada botón hay, además del icono, una etiqueta con el nombre de la aplicación, y salvo que el contenedor tenga un tamaño determinado, la etiqueta intentará expandirse todo lo que pueda, y ni siquiera sirve de nada pedir un tamaño deseado, porque si el texto en la etiqueta es más largo, la etiqueta se expandirá todo lo que pueda para contener todo el texto.

La primera idea que se me ocurrió fue engancharme a la señal size_allocate del botón. Esta señal se emite cada vez que un widget cambia de tamaño por el motivo que sea, y recibe como parámetro sus nuevas medidas. Con ella y la propiedad max_width_chars intenté limitar el tamaño de la etiqueta para que el botón tuviese el tamaño máximo deseado; por desgracia era un proceso relativamente lento y que, además, provocaba un parpadeo en la ventana, pues ésta primero tomaba el valor máximo y se reducía progresivamente hasta el tamaño correcto, a medida que las distintas etiquetas iban reduciendo su número de caracteres.

La segunda idea, sugerida por la gente de la lista de desarrollo de Gtk, fue encapsular la etiqueta dentro de un Gtk.Fixed, pues permite ajustar manualmente el tamaño de cualquier widget situado en su interior. Esta solución casi funcionó, pues aunque la etiqueta se mantenía en el ancho deseado, el Gtk.Fixed contenedor se redimensionaba hasta ocupar el mismo espacio que ocuparía la etiqueta si estaba sola.

Ante esto me di cuenta de que la solución iba a necesitar de algo más de investigación y, sobre todo, de meterme en los entresijos del renderizado de Gtk, así que empecé a investigar, y descubrí que todo widget tiene dos métodos que participan de manera especial en la asignación de tamaño: get_preferred_width y get_preferred_height. Estos dos métodos devuelven dos valores: el primero es el tamaño mínimo que necesita dicho widget en el eje correspondiente para mostrar su contenido, y el segundo el tamaño deseado. En el caso de una etiqueta, el tamaño deseado será el ancho que ocupe la totalidad del texto puesto en una única línea, mientras que el tamaño mínimo dependerá de varias opciones: si no hay elipsis de texto coincidirá con el tamaño deseado, pero si no, será menor, de lo necesario para pintar el borde y unos puntos suspensivos.

Cuando un contenedor tiene en su interior otro widget, llama a estos dos métodos para saber cuanto espacio debe reservar. Lo interesante es que dichos valores son, realmente, orientativos, pues el contenedor puede asignar otros tamaños si así lo considera oportuno. Así, si una etiqueta pide 100 pixels pero está en una ventana que mide 200 y tiene activo el flag de expandirse, el tamaño final de la etiqueta será de 200. De igual forma, si una etiqueta pide un tamaño deseado de 100 pixels de ancho pero la ventana mide 50, recibirá 50 y el texto tendrá que ocupar varias líneas.

Ante esto se me ocurrió probar qué ocurriría si creo una nueva clase que herede de Gtk.Label, en la que redefino (override) el método get_preferred_width para que devuelva 120 como ancho mínimo y deseado (porque cada botón tiene un margen de 5 pixels por cada lado). El resultado es justo el deseado: la etiqueta mide exactamente el ancho que se le indica, y aplica las reglas para pasar a nuevas líneas o para añadir elipsis.

Por supuesto esto es fácil de hacer en Vala; en C es posible hacerlo también, pero obliga a meterse en el interior de GObject, una tarea que, sinceramente, no me llama demasiado en este momento.

Cagándola con un bug grave

domingo, agosto 10th, 2014

A veces a uno se le escapan pequeños bug que, en principio, no tienen la menor importancia, hasta que resulta que sí la tienen. Eso me ha ocurrido con la nueva versión en desarrollo de DevedeNG.

El bug ni siquiera era tal, sino más bien una combinación de valores por defecto poco adecuados, mensajes poco claros, y código que hacía demasiadas cosas. Básicamente, DevedeNG necesita una carpeta vacía donde crear el proyecto, así que le pide al usuario que le indique una. Si dicha carpeta ya existe le indica que va a proceder a borrarla, dejándole escoger si quiere continuar o cancelar antes de hacerlo.

Hasta aquí todo parece normal. El problema es que la carpeta por defecto era la carpeta personal del usuario, y el mensaje de aviso decía simplemente: “La carpeta seleccionada ya existe. Si continúa, será borrada. ¿Continuar?”. Este mensaje no es lo suficientemente claro porque en ninguna parte aparece qué carpeta se va a borrar. Ante esto, un usuario que se limite a pulsar Siguiente->Siguiente->Siguiente se encontrará con su carpeta personal borrada.

El código ya está corregido, para lo que he aplicado las siguientes lecciones aprendidas:

  • Debe evitarse utilizar la carpeta de usuario ($HOME) como destino por defecto cuando haya que realizar alguna acción que borre una carpeta. En el caso de DevedeNG, el primer cambio fue que la carpeta destino se componga de la carpeta escogida por el usuario más el nombre del proyecto, por lo que, por defecto, nunca será la carpeta de usuario sola la escogida para ser borrada.
  • Siempre que se le pida al usuario confirmación para borrar una carpeta debe mostrarse claramente en el texto qué carpeta se va a borrar. Nunca se debe dar por supuesto que el usuario lo sabe.
  • En la medida de lo posible no debe borrarse la carpeta al completo, sino buscar qué ficheros y directorios son los que pueden interferir con el proceso que se quiere realizar, borrando exclusivamente esos y ninguno más.

Afortunadamente, el usuario que se tropezó con este problema tenía copia de seguridad, por lo que todo quedó en un susto.

XCB y Cairo

sábado, septiembre 28th, 2013

Actualizado: Por fin he terminado la primera versión usable de TabletWM y TabletLauncher. Con ellos y el driver para la pantalla táctil he conseguido el gran objetivo de poder utilizar aplicaciones GNU/Linux nativas en una tablet sin teclado ni ratón.

Crear TabletWM fue, sin duda, la parte más compleja, porque supuso trabajar con un API completamente nuevo, como es XCB. Tenía claro que no quería utilizar XLib, así que me lié la manta a la cabeza, pero partiendo de un gestor de ventanas muy, pero que muy básico hecho por Cinolt a finales de 2011.

Lo primero que aprendí es que el protocolo X es lento, por lo que en un dispositivo como una tablet, con capacidades limitadas, no es recomendable pedir al servidor X las propiedades de una ventana cada vez que se quiere mostrar en pantalla o cambiar sus dimensiones o posición. Sin embargo no parece existir una manera de que el servidor avise al gestor de ventanas de que una propiedad ha cambiado, y dado que estas propiedades contienen información importante necesaria a la hora de mapear una ventana, la mejor solución que encontré fue hacer una caché de datos que relleno en el momento de hacer visible una ventana (en ese momento las propiedades ya tienen que estar definidas), aunque antes puedo haber almacenado otras operaciones que se hayan hecho en la ventana, como un cambio de tamaño o de posición.

Otra cosa que aprendí es que hay dos grupos de eventos de interés para un gestor de ventanas: request y notification. El primero se emite cuando una aplicación pide realizar alguna operación sobre una ventana suya, y la segunda si el resultado de dicha operación cambia algo realmente en la ventana. Así, si una aplicación pide cambiar el tamaño de una ventana, ejecutará un comando xcb_configure_window(). Si no existe un gestor de ventanas, dicho comando se ejecuta normalmente; pero si lo hay, se genera un evento xcb_configure_request en el gestor. Este puede decidir si ignorarlo, ejecutarlo tal cual o modificarlo. Si decide ejecutarlo y el tamaño de la ventana cambia realmente, se emite un evento xcb_configure_notification, que llegará a la aplicación.

Y aquí encontré otro de los problemas que tuve: mi intención es que las ventanas estén maximizadas siempre, por lo que cada vez que recibía un evento xcb_configure_request, emitía un comando xcb_configure_window() con el tamaño máximo de la pantalla. El problema ocurría con algunas ventanas que pedían ser más grandes que la pantalla, por ejemplo la ventana de configuración de Firefox. En este caso, se mostraba la ventana en la primera pestaña, y la pantalla es lo suficientemente grande como para contener todo; al recibir el evento, TabletWM modifica los valores pedidos por el navegador, ajustándolos al tamaño de la pantalla, y cambia las dimensiones de la ventana. Se emite el evento xcb_configure_notification y todo sigue perfectamente.

Pero cuando se escoge la pestaña de Seguridad, el nuevo contenido no entra en la pantalla, por lo que Firefox pide un tamaño más grande. El gestor de ventanas recibe el evento y cambia los parámetros por las dimensiones de la pantalla (que es el mismo tamaño que ya tiene la ventana), y da la orden de cambiar el tamaño. Pero como es el mismo, nunca se genera un evento xcb_configure_notification, pero Firefox espera que le llegue. El resultado es que la ventana queda sin refrescar.

La solución que apliqué fue ejecutar primero el comando de cambio de tamaño tal cual llega, y ejecutar luego un segundo comando con el tamaño que el gestor de ventanas desea. De esa manera la aplicación siempre recibe el evento que espera, y todos felices.

Otra curiosidad fue a la hora de leer ciertas cadenas de texto en las propiedades. En algunos casos, una propiedad (como por ejemplo _XKB_RULES_NAMES) contiene varias cadenas separadas por NUL (o sea, un byte a cero). Si pedimos el tamaño de ésta en la cookie (cookie->length) nos devolverá la longitud de la primera cadena exclusivamente. Si queremos obtener todas tenemos que utilizar xcb_get_property_value_length(), que sí nos dará el tamaño total. Por si fuera poco, no se garantiza que al final de la cadena haya un NUL, por lo que debemos tener en cuenta el tamaño para no pasarnos, en lugar de usar strcpy().

El teclado fue otro de los problemas serios que tuve: el método normal de entrada por teclado de X es relativamente rudimentario, por lo que hoy en día se utiliza la extensión XKB. Por desgracia esta extensión no está portada tal cual a XCB, sino que existe un proyecto separado, XCB-COMMON, que contiene aquellas partes no dependientes de un servidor X. Por si fuera poco, no puedo emular la pulsación de un carácter concreto, sino sólo la pulsación de una tecla en sí. Esto significa que los códigos que tengo que enviar a las X dependerán del idioma del teclado escogido por el usuario, además de tener que emular pulsaciones múltiples como la tecla mayúsculas, AltGR, etc.

Encima, esta biblioteca está orientada a obtener un carácter a partir de una pulsación, cuando yo necesitaba el proceso inverso. Aunque parte del trabajo lo hace (dado un carácter devuelve el código de la tecla), no devuelve el código de los modificadores necesarios. Así, si pido la arroba, me devuelve el código de la tecla ‘2’, pero no me dice si necesito pulsar también las mayúsculas (caso del teclado norteamericano) o AtlGR (caso del teclado español). Esto me obligó a realizar una pequeña chapuza, consistente en probar todas las posibles combinaciones de teclas normales y teclas modificadoras (shift, control, etc) para ver qué caracteres produce cada una.

Y para rizar el rizo, no es posible siempre obtener la combinación correcta, por lo que en algunos casos no queda más remedio que redefinir un código de tecla que no se utilice con un carácter determinado (por ejemplo, la letra Ñ). Esto hay que hacerlo con las funciones de entrada clásicas, no con las de XKB, por lo que el resultado final es algo caótico, pero funciona, y permite definir un teclado cualquiera en pantalla a partir de los caracteres que se quieren mostrar en lugar de las teclas físicas que se deben pulsar.

Pasando a Cairo, decidí utilizar esta biblioteca para los elementos gráficos (como el teclado o la ventana de apagado) en lugar de las funciones de X por varios motivos:

  • Cairo ofrece antialiasing, tanto en fuentes como en primitivas gráficas.
  • Cairo es una biblioteca moderna con un API sencillo y potente.
  • Ya conozco Cairo, pero no las funciones gráficas de X.
  • No supone una carga extra porque el lanzador de aplicaciones utiliza GTK, que por debajo trabaja también con Cairo.

Trabajar con Cairo directamente desde XCB no es muy complicado. Para ello, primero se debe crear una ventana, y a continuación una superficie Cairo con cairo_xcb_surface_create(). La principal complicación es conocer el visual_type de la ventana, para poder pasárselo a la función. Esto lo podemos saber mediante el siguiente código (la variable conn es el handler de la conexión con el servidor X):

    xcb_screen_t *scr=xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
    xcb_visualtype_t *visual_type = NULL;
    xcb_depth_iterator_t depth_iter;

    for (depth_iter = xcb_screen_allowed_depths_iterator (scr); depth_iter.rem; xcb_depth_next (&depth_iter)) {
        xcb_visualtype_iterator_t visual_iter;

        visual_iter = xcb_depth_visuals_iterator (depth_iter.data);
        for (; visual_iter.rem; xcb_visualtype_next (&visual_iter)) {
            if (scr->root_visual == visual_iter.data->visual_id) {
                visual_type = visual_iter.data;
                break;
            }
        }
    }

Luego no tenemos más que engancharnos al evento expose de la ventana (XCB_EVENT_MASK_EXPOSURE) y, cada vez que se reciba, generar un contexto Cairo y repintar la ventana. Un detalle extra a tener en cuenta es que cada vez que se redimensione la ventana es necesario llamar a cairo_xcb_surface_set_size(), para cambiar el tamaño de la superficie Cairo.

Ah, y no olvidar hacer un xcb_flush() al terminar de pintar algo, para que efectivamente lo pinte en la ventana.

Gestion de energia

viernes, agosto 16th, 2013

Nuevos cambios en la configuración del núcleo. Para que la gestión de energía funcione y la tablet se apague realmente al utilizar shutdown -h now o halt, y que apm -v devuelva el nivel actual de batería, es necesario activar las siguientes opciones:

    Power management options --->
        Run-time PM core functionality=Y
        Advanced Power Management Emulation=y
    Device Drivers --->
        Power supply class support=Y --->
            AXP Power drivers=Y --->
                AXP PMU type=AXP20 driver
                AXP initial charging environment set=Y
                AXP charging current set when suspendresumeshutdown=Y
            APM emulation for class batteries=Y
        Voltage and Current Regulator Support=Y --->

La última es necesaria para que aparezcan las de AXP Power drivers.

Teclados Logitech

jueves, agosto 15th, 2013

Para trabajar con más comodidad con la tablet decidí utilizar un teclado con touchpad integrado. En casa tenía un modelo Logitech, así que lo conecté; sin embargo, no funcionó. Lo curioso es que desde Android sí funcionaba, así como en mi PC, así que decidí hacer algunas pruebas extra. Al final descubrí que para que estos dispositivos, que utilizan el Logitech Unifying Receiver, funcionen, es necesario activar no sólo el soporte HID completo en el núcleo, sino también las opciones siguientes opciones:

    Device Drivers --->
        HID devices=Y --->
            Generic HID support=Y
                /dev/hidraw raw HID device support=Y
            USB Human Interface Device (full HID) support=Y
            /dev/hiddev raw HID device support=Y

Viajando al espacio

sábado, junio 22nd, 2013

Me he enganchado al juego Kerbal Space Program. Para los que no lo conozcan, es un simulador espacial de corte humorístico, aunque muy realista. El objetivo es construir un cohete para llevar a los Kerbals, (los habitantes del planeta Kerbal) hasta su luna Mun. Se pueden poner en órbita satélites, y muchas cosas más.

Lo más interesante es que hay versión para Linux, y además, comprado en la propia página cuesta sólo 23 dolares (unos 16 euros, al cambio). Aún está en desarrollo, pero se puede comprar la versión actual, que es muy completa, y con ese pago ya se tiene acceso a las distintas actualizaciones, hasta que el juego esté completo.

Solo tiene un defectillo: la falta de un instalador que permita disponer de un icono en los menús. Por eso he escrito yo uno, que se puede bajar aquí: instalador de Kerbal Space Program para Linux. Basta con descomprimirlo en la misma carpeta que el juego y ejecutar el fichero ksp_installer.

Un par de detalles, por si acaso:

  • No utilizar el ejecutable de 64 bits, porque falla más que una escopeta de feria (es un problema conocido). El ejecutable de 32 bits funciona perfectamente en Linux de 64 bits.
  • Si se quiere lanzar desde una línea de comandos, debe utilizarse el comando LC_ALL=C ./KSP.x86 para que el juego funcione bien (mi instalador ya lo tiene en cuenta)
  • La última versión de pago, la 0.20.2, no funciona con el driver libre para tarjetas AMD/ATI; es necesario utilizar el privativo, o bajarse la versión 0.19, que también está disponible (espero que lo corrijan pronto)

 

Hackeando cuelgatazas

lunes, junio 17th, 2013

Mi cocina es algo pequeña, así que cualquier cosa que ayude a tener más espacio siempre es bienvenida. Una idea que tuve hace tiempo fue aprovechar que los muebles tienen una moldura por debajo, que deja un hueco de unos tres centímetros, para añadir unos cuelgatazas disimulados en la base, y así tenerlas más a mano y aprovechar el hueco liberado para otras cosas.

Por desgracia, no encontré en ninguna parte un modelo que me convenciese. El más parecido fue éste de CASA, diseñado para enganchar en la balda de un estante. Pese a todo, es más un cuelgapocillos, porque el metal de la zona curva, que es la que sostiene el peso, se dobla demasiado si pongo una taza de desayuno (pulsar en las imágenes para verlas a tamaño completo):

IMG_20130616_192040

Sin embargo, si sujetaba el colgador de manera adecuada todavía podría utilizarlo, así que me puse manos a la obra. Lo primero fue buscar un trozo de tablero (en mi caso, de 15×75 cm) donde fijar los colgadores, y marcar en él los puntos en donde se cruzan las barras que lo forman:

IMG_20130616_164828 IMG_20130616_164847 IMG_20130616_165024

El siguiente paso fue fijar cada uno de los tres cuelgatazas al tablero mediante unas alcayatas, montadas de tal manera que impidan que se mueva en cualquier sentido:

IMG_20130616_165846 IMG_20130616_165904

A continuación había que fijarlo al mueble, debajo de la rejilla de los platos. Para ello puse dos pequeñas escuadras en uno de los laterales; en el otro, como hay un mueble “normal”, decidí atornillarlo directamente a su base:

IMG_20130616_170102

Una vez colocado el tablero sobre las escuadras y atornillado a éstas, hay que recortar lo que sobresalga de los tornillos, obviamente:

IMG_20130616_171132

¡Y listo! Ya puedo colgar hasta 18 tazas cómodamente.

IMG_20130616_192103

Para jugar bien

sábado, noviembre 10th, 2012

En la entrada anterior explicaba el problema que supone jugar cuando se utiliza un gestor de ventanas por composición. Este problema se describe con más detalle en los artículos The Cost Of Running CompizMutter Can Cause A Gaming/OpenGL Performance Hit Too. El principal motivo es que los programas no pintan directamente sobre la pantalla, sino sobre un buffer oculto, y es el gestor de ventanas el que, de manera periódica, copia dicho buffer a la zona visible.

La solución que proponía era aumentar la prioridad del gestor de ventanas y del servidor X, pero dado que es una operación algo liosa para alguien que no tenga unos mínimos conocimientos, decidí hacer un pequeño programa que lo automatizase. Ese programa se llama GAMEd. La esencia es muy sencilla: tenemos una lista de ejecutables almacenada en /etc/gamed.conf. Cada vez que se lanza el gestor de ventanas y el entorno de escritorio, se llama mediante DBus al demonio GAMEd (y si no estaba lanzado, el propio DBus lo lanza como root). Este demonio recorre la lista de procesos actuales, y cambia su prioridad a cada uno que coincida con alguno de la lista. De esta manera es posible asignar prioridades altas desde el espacio de usuario sin abrir un agujero de seguridad, porque sólo se cambiarán aquellos programas autorizados.

El sistema está diseñado para ser completamente transparente: por defecto asigna prioridad -15, pero se puede utilizar el comando renice_gamed para escoger cualquier otra (podría llegarse hasta -20, pero en el código de un programa similar, AutoNICEd, recomienda no hacerlo, así que GAMEd simplemente redondea a -15 si se pone una prioridad mayor). Dicha prioridad se almacena y se utiliza todas las veces que se llame al demonio, hasta que el usuario la vuelva a cambiar si quiere.

Por otro lado se añade un pequeño script en el arranque del escritorio, que llama al demonio. Esto hace que cada vez que se arranque el ordenador y se entre en la sesión, se ajustará de nuevo automáticamente la prioridad de las X y del gestor de ventanas.

Yo lo he probado en Gala y en Compiz y se nota la diferencia, pero no he podido probarlo en Gnome-Shell por ciertos problemas de compatibilidad de paquetes entre éste y Elementary OS.

Así pues, si jugáis regularmente en vuestro equipo Linux y notáis pérdida de rendimiento y de FPS en vuestros juegos, probad a instalar GAMEd y contadme qué tal os ha ido.

Juego elemental

lunes, noviembre 5th, 2012

Llevo una temporadita probando Elementary OS, y tengo que decir que me encanta. Es un concepto de escritorio y sistema operativo que, salvo un par de detalles, encaja como un guante en lo que busco. Tanto es así que estoy asegurándome de que Cronopete esté perfectamente integrado en él.

Por otro lado, hace poco descubrí Limbo, un juego con una ambientación sencillamente impresionante.

Sin embargo, me encontré con que la mezcla de ambos no funcionaba muy bien: había “saltos” entre fotogramas, se conseguían muy pocos FPS y había un retardo brutal (casi un segundo) entre la pulsación de una tecla y que el personaje ejecutase la acción correspondiente. Al principio lo achaqué a Wine (es un juego para windows), pero buscando información encontré que al resto de gente le funcionaba perfectamente.

Lo primero que hice fue cambiar del driver privativo de AMD/ATI (FGLRX) al libre (Radeon), y los saltos desaparecieron, pero los bajos FPS y el retardo seguían allí.

Recordé que había una crítica general contra los gestores de ventanas por composición como Compiz, Mutter y KWin, porque tienen que renderizar el contenido de cada ventana cada vez que la aplicación lo cambia. Ante esto, probé a arrancar una sesión de gnome-fallback-session, y allí funcionaba perfectamente, lo que confirmó que el problema estaba en Gala (el gestor de ventanas de Elementary).

Sin embargo, pensando, llegué a la conclusión de que perfectamente podía deberse al retardo en la conmutación entre tareas, así que decidí probar a asignarle máxima prioridad (-19) tanto al servidor X como a Gala. Para ello usé el comando renice (como root, porque si no, no permite asignar valores negativos, correspondientes a la máxima prioridad). Con eso el problema se resolvió, y el juego funcionó con una suavidad total, igual que si no estuviese utilizando un gestor de ventanas por composición.


Utilizamos cookies para garantizar que tenga la mejor experiencia en nuestro sitio web.