2020/05/01

xzoom mejorado

Me había quedado muy incómodo con el hack de arrastrar la carpeta para que se viera en la ventana magnificada el cursor, así que me puse a investigar. A diferencia de lo que suelo hacer que es ir mostrando todos los caminos equivocados que tomé y lo que aprendí, voy a mostrar sólo el camino feliz.

Entre la m y la p, hay una región en negativo


Tras algunos intentos fallidos aprendí a bajar el código fuente, tan fácil como:

$> mkdir sources
$> cd sources
$> apt source xzoom


Conviene crear la carpeta contenedora por que te tira todo donde estés. Para crear el Makefile:

$> xmkmf

Si no existe lo arreglás con el sudo apt get que te sugiere. Luego compilás con:

$> make


Yo quería apoyarme en lo existente y hacer un fork para luego proponer un pull request, me puse a buscar y hallé:


Le mandé mail al creador original, parece ser un proyecto que ha muerto en su origen, si me constesta, actualizaré.



Me quedé entonces en investigar y se me ocurrió mirar la versión de mbarakatt, ¡bingo! tiene casi todo el código necesario, sólo tuve que acomodarlo y ver como dibujar el cursor.

Para que le sirva a mbarakatt incorporé primero la funcionalidad de prender y apagar el follow mouse y luego seguí construyendo encima.

Lo que voy a hacer para que le sirva a mbarakatt es primero incorporar la funcionalidad de prender y apagar follow mouse, así me queda el código incorporado, luego agregaré lo que quería.


Proceso definitivo




$> mkdir xzoom
$> cd xzoom/
$> apt source xzoom
$> rm *
$> mv xzoom-0.3/* .
$> rmdir xzoom-0.3/
$> git init .
$> git add .
$> git commit -m "Initial commit ..."

Hice un branch follow_mouse y en master dejé lo del cursor.

Finalmente, para actualizar el binario:

$> which xzoom 
/usr/bin/xzoom
$> sudo chown root.root xzoom
$> sudo cp xzoom /usr/bin/xzoom


El código está en https://github.com/cpantel/xzoom.

El código aportado


Para procesar las nuevas opciones de linea de comando:


if(!strcmp(argv[0], "-follow")) {
  follow_mouse = True;
  continue;

}

if(!strcmp(argv[0], "-no-follow")) {
  follow_mouse = False;
  continue;
}

if(!strcmp(argv[0], "-cursor")) {
  show_cursor = True;
  continue;
}
 

if(!strcmp(argv[0], "-no-cursor")) {
  show_cursor = False;
  continue;
}



El cambio de las opciones en tiempo de ejecución:


case 'c':
  show_cursor = ! show_cursor;
  break;
 

case 'f':
  follow_mouse = ! follow_mouse;
  break;




Le agregué los condicionales a seguir el mouse:

if (follow_mouse || show_cursor ) {
  for (i = 0; i < number_of_screens; i++) {
    result = XQueryPointer(display, root_windows[i], 

               &window_returned, &window_returned,
               &root_x, &root_y, &win_x, &win_y,
               &mask_return

             );
    if (result == True) {
      break;
    }
  }
  if (result != True) {
    fprintf(stderr, "No mouse found.\n");
    return -1;
  }
  if (follow_mouse) {
    xgrab = root_x - width[SRC]/2;
    ygrab = root_y - height[SRC]/2;
  }

}


Y el corazón, que fué medio tiro al arco zen, por puro instinto, inspirándome en una pregunta que encontré por ahí:


if (show_cursor) {
  long pixel = 0;
  int cursor2x = ( root_x - xgrab ) * magx;
  int cursor2y = ( root_y - ygrab ) * magy;
 

  if (cursor2x < CURSOR_RADIUS)
    cursor2x = CURSOR_RADIUS;
  if (cursor2y < CURSOR_RADIUS)

    cursor2y = CURSOR_RADIUS;

  if (cursor2x > ximage[DST]->width)

    cursor2x = ximage[DST]->width - CURSOR_RADIUS;
  if (cursor2y > ximage[DST]->width)
    cursor2y = ximage[DST]->height - CURSOR_RADIUS;

  for (int x = cursor2x - CURSOR_RADIUS;

       x < cursor2x + CURSOR_RADIUS 
         && x < ximage[DST]->width;
       x++
      ) {
    for (int y = cursor2y - CURSOR_RADIUS;

         y < cursor2y + CURSOR_RADIUS
           && y < ximage[DST]->height;
         y++
        ) {
      // Invert the color of each pixel
      pixel = XGetPixel(ximage[DST], x, y);
      XPutPixel(ximage[DST], x, y, ~pixel);
    }
  }
}



Los limitantes entre 0 y width y height estan para que el cursor se detenga en el borde y te dé un indicio de dónde está. El de 0 tambien está por que si no crashea.

El código es horrible, son mil lineas, todo en main, variables globales. Si fuera a completar lo faltante que es que funcione correctamente mostrar cursor cuando hay rotación, lo refactorizaría todo, pero difícil que ocurra.

No hay comentarios:

Publicar un comentario