HACKING 120% {Hacking, programmazione, computer & molto altro}

TinyWM

« Older   Newer »
  Share  
vogy
view post Posted on 24/8/2014, 12:21     +1   -1




Per chi non lo sapesse TinyWM è il più piccolo window manager esistente (e lo sarà per sempre).
Sono circa 50 righe di C su XLib per implementare tre funzioni:
- alt + tasto_sx: muove la finestra
- alt + tasto_dx: allarga/stringe la finestra
- alt + F1: sposta il focus tra le finestre [abbinamento osceno anche a detta dell'autore]

Ogni modifica va fatta ricompilando il sorgente, quindi se qualcuno volesse divertirsi posto qui il codice (preso dal pacchetto debian-src, l'originale è un 2005, credo sia identico ma per sicurezza...)
CODICE
/* TinyWM is written by Nick Welch <mack@incise.org>, 2005.
*
* This software is in the public domain
* and is provided AS IS, with NO WARRANTY. */

#include <X11/Xlib.h>

#define MAX(a, b) ((a) > (b) ? (a) : (b))

int main()
{
   Display * dpy;
   Window root;
   XWindowAttributes attr;
   XButtonEvent start;
   XEvent ev;

   if(!(dpy = XOpenDisplay(0x0))) return 1;

   root = DefaultRootWindow(dpy);

   XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("F1")), Mod1Mask, root,
           True, GrabModeAsync, GrabModeAsync);
   XGrabButton(dpy, 1, Mod1Mask, root, True, ButtonPressMask, GrabModeAsync,
           GrabModeAsync, None, None);
   XGrabButton(dpy, 3, Mod1Mask, root, True, ButtonPressMask, GrabModeAsync,
           GrabModeAsync, None, None);

   for(;;)
   {
       XNextEvent(dpy, &ev);
       if(ev.type == KeyPress && ev.xkey.subwindow != None)
           XRaiseWindow(dpy, ev.xkey.subwindow);
       else if(ev.type == ButtonPress && ev.xbutton.subwindow != None)
       {
           XGrabPointer(dpy, ev.xbutton.subwindow, True,
                   PointerMotionMask|ButtonReleaseMask, GrabModeAsync,
                   GrabModeAsync, None, None, CurrentTime);
           XGetWindowAttributes(dpy, ev.xbutton.subwindow, &attr);
           start = ev.xbutton;
       }
       else if(ev.type == MotionNotify)
       {
           int xdiff, ydiff;
           while(XCheckTypedEvent(dpy, MotionNotify, &ev));
           xdiff = ev.xbutton.x_root - start.x_root;
           ydiff = ev.xbutton.y_root - start.y_root;
           XMoveResizeWindow(dpy, ev.xmotion.window,
               attr.x + (start.button==1 ? xdiff : 0),
               attr.y + (start.button==1 ? ydiff : 0),
               MAX(1, attr.width + (start.button==3 ? xdiff : 0)),
               MAX(1, attr.height + (start.button==3 ? ydiff : 0)));
       }
       else if(ev.type == ButtonRelease)
           XUngrabPointer(dpy, CurrentTime);
   }
}

io ho il file tinywm.c in /usr/bin in modo da ricompilarlo direttamente:
CODICE
# cd /usr/bin
# gcc tinywm.c -o tinywm -lX11

se a qualcuno serve anche un /usr/share/xsessions/tinywm.desktop:
CODICE
[Desktop Entry]
Encoding=UTF-8
Name=Tinywm
Comment=u r gay
Exec=/usr/bin/tinywm
Terminal=False
TryExec=/usr/bin/tinywm
Type=Application

[Window Manager]
SessionManaged=true

se non usate .xinitrc vi create uno script di avvio xinitrcoso (in chmod 755) e lo sostituite a /usr/bin/tinywm

Siccome ho visto che qui dentro Python va forte, c'è anche la versione in python-xlib:
CODICE
# TinyWM is written by Nick Welch <mack@incise.org>, 2005.
#
# This software is in the public domain
# and is provided AS IS, with NO WARRANTY.

from Xlib.display import Display
from Xlib import X, XK

dpy = Display()
root = dpy.screen().root

root.grab_key(XK.string_to_keysym("F1"), X.Mod1Mask, 1,
       X.GrabModeAsync, X.GrabModeAsync)
root.grab_button(1, X.Mod1Mask, 1, X.ButtonPressMask,
       X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)
root.grab_button(3, X.Mod1Mask, 1, X.ButtonPressMask,
       X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)

while 1:
   ev = root.display.next_event()

   if ev.type == X.KeyPress and ev.child != X.NONE:
       ev.window.circulate(X.RaiseLowest)
   elif ev.type == X.ButtonPress and ev.child != X.NONE:
       ev.child.grab_pointer(1, X.PointerMotionMask|X.ButtonReleaseMask,
               X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE, X.CurrentTime)
       attr = ev.child.get_geometry()
       start = ev
   elif ev.type == X.MotionNotify:
       #while(XCheckTypedEvent(dpy, MotionNotify, &ev));
       xdiff = ev.root_x - start.root_x
       ydiff = ev.root_y - start.root_y
       ev.window.configure(
           x = attr.x + (start.detail == 1 and xdiff or 0),
           y = attr.y + (start.detail == 1 and ydiff or 0),
           width = max(1, attr.width + (start.detail == 3 and xdiff or 0)),
           height = max(1, attr.height + (start.detail == 3 and ydiff or 0)))
   elif ev.type == X.ButtonRelease:
       dpy.ungrab_pointer(X.CurrentTime)

ovviamente questa non si compila ma va resa eseguibile.

Caricate qualcosa in avvio perché quando si dice 'minimale' a volte si intende veramente quello. Tipo che...
CODICE
#!/bin/sh
/usr/bin/xterm &
exec /usr/bin/tinywm

...vi produce questo

con un minimo di .xinitrc (o il vostro file):
CODICE
#!/bin/sh
# feh per impostare un wallpaper
feh --bg-scale /home/vogy/.tinywm/cattivissimo.jpg &
# Conky
conky &
# urxvt/screen
/usr/bin/urxvt -T "Screen" -e /usr/bin/screen &
exec /usr/bin/tinywm

si arriva ad uno stadio `umano`

Se qualcuno fosse attizzato:
XLib C: www.x.org/releases/X11R7.7/doc/libX11/libX11/libX11.html
Python XLib: http://python-xlib.sourceforge.net/doc/html/index.html
Non so ancora bene cosa andrò a farci sopra, comunque scriverò le modifiche in questa discussione...
 
Top
vogy
view post Posted on 25/8/2014, 11:20     +1   -1




Prime modifiche:

1. tolto quel bruttissimo alt+F1 suddiviso in due diversi comandi:
alt+enter --> porta in primo piano
alt+backspace --> porta al livello più basso
Prima era un po' un casino perché avendo una finestra che copriva le altre era obbligo spostarla.
Tra l'altro nel mio ultimo laptop ho i tasti f1-f12 sotto seconda funzione...se lo fa HP non saranno gli unici.

2. aggiunto un alt+q (quit) per chiudere le finestre; molte applicazioni hanno già un ctrl+q per la chiusura però mi pareva giusto farne uno di sistema

Il codice adesso ha un annidamento piuttodto brutto, alla prossima modifica tolgo quelli 'else if'...
CODICE
/* TinyWM is written by Nick Welch <mack@incise.org>, 2005.
* [changed by vogy]
* This software is in the public domain
* and is provided AS IS, with NO WARRANTY. */

#include <X11/Xlib.h>

#define MAX(a, b) ((a) > (b) ? (a) : (b))

int main()
{
       Display * dpy;
       Window root;
       XWindowAttributes attr;
       XButtonEvent start;
       XEvent ev;

       if(!(dpy = XOpenDisplay(0x0))) return 1;

       root = DefaultRootWindow(dpy);

       XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("Return")), Mod1Mask, root, True, GrabModeAsync, GrabModeAsync);
       XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("BackSpace")), Mod1Mask, root, True, GrabModeAsync, GrabModeAsync);
       XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("q")), Mod1Mask, root, True, GrabModeAsync, GrabModeAsync);
       XGrabButton(dpy, 1, Mod1Mask, root, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
       XGrabButton(dpy, 3, Mod1Mask, root, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);

       for(;;)
       {
         XNextEvent(dpy, &ev);
         if(ev.type == KeyPress && ev.xkey.keycode == XKeysymToKeycode(dpy, XStringToKeysym("Return"))) {
                       XRaiseWindow(dpy, ev.xkey.subwindow);
         }
         else if(ev.type == KeyPress && ev.xkey.keycode == XKeysymToKeycode(dpy, XStringToKeysym("BackSpace"))) {
                       XLowerWindow(dpy, ev.xkey.subwindow);
         }
         else if(ev.type == KeyPress && ev.xkey.keycode == XKeysymToKeycode(dpy, XStringToKeysym("q"))) {
                       XDestroyWindow(dpy, ev.xkey.subwindow);
         }
         else if(ev.type == ButtonPress && ev.xbutton.subwindow != None) {
                       XGrabPointer(dpy, ev.xbutton.subwindow, True, PointerMotionMask|ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
                       XGetWindowAttributes(dpy, ev.xbutton.subwindow, &attr);
                       start = ev.xbutton;
         }
         else if(ev.type == MotionNotify) {
                       int xdiff, ydiff;
                       while(XCheckTypedEvent(dpy, MotionNotify, &ev));
                       xdiff = ev.xbutton.x_root - start.x_root;
                       ydiff = ev.xbutton.y_root - start.y_root;
                       XMoveResizeWindow(dpy, ev.xmotion.window, attr.x + (start.button==1 ? xdiff : 0), attr.y + (start.button==1 ? ydiff : 0), MAX(1, attr.width + (start.button==3 ? xdiff : 0)), MAX(1, attr.height + (start.button==3 ? ydiff : 0)));
         }
         else if(ev.type == ButtonRelease)
                       XUngrabPointer(dpy, CurrentTime);
       }
}
 
Top
vogy
view post Posted on 7/9/2014, 09:03     +1   -1




Nuova versione aggiustata ad un livello di fiqettosità adeguato per sfiqettare in giro :)

Il WM è strutturato per quadranti di schermo (tipo RatPoison per capirsi); tasto di funzione 'alt':
CODICE
alt + tasto_dx  ---> sposta la finestra sotto il puntatore
alt + tasto_sx  ---> allarga/riduce la finestra

alt + m         ---> massimizza la finestra
alt + q         ---> chiude la finestra
                   (con applicazioni Gtk meglio il suo ctrl+q, meno drastico)

alt + invio     ---> porta la finestra in primo piano
alt + backspace ---> porta la finestra in ultimo piano (mostra quelle coperte)

[parte fiqa]
alt + frecce    ---> allarga/muove le finestre rendendo possibile una disposizione
                    per quadranti. Del tipo...
                    finestra centrale?
                    - alt+sx allarga la finestra fino al lato sinistro dello schermo
                    - alt+sx stringe la finestra che ora va da metà schermo al lato
                      sinistro
                    - alt+up allarga fino al bordo superiore
                    - alt+up stringe sul primo quadrante

esempio di un modello finale di uso:

sorgente:
CODICE
/* TinyWM is written by Nick Welch <mack@incise.org>, 2005.
*
* This software is in the public domain
* and is provided AS IS, with NO WARRANTY.
*
* This Is vogy Version Implemented, 2014
* $ gcc thisfile.c -o filename -lX11
*
* PleaseRemember: The State Is An Unnecessary Evil
*/

#include <X11/Xlib.h>

#define MAX(a, b) ((a) > (b) ? (a) : (b))

int main()
{
  Display * dpy;
  Window root;
  XWindowAttributes attr;
  XButtonEvent start;
  XEvent ev;
  unsigned int keycode[8];
  unsigned int MWidth, MHeight, QWidth, QHeight;

  if(!(dpy = XOpenDisplay(0x0))) return 1;

  root = DefaultRootWindow(dpy);
 
  keycode[0] = XKeysymToKeycode(dpy, XStringToKeysym("Return"));
  keycode[1] = XKeysymToKeycode(dpy, XStringToKeysym("BackSpace"));
  keycode[2] = XKeysymToKeycode(dpy, XStringToKeysym("q"));
  keycode[3] = XKeysymToKeycode(dpy, XStringToKeysym("m"));
  keycode[4] = XKeysymToKeycode(dpy, XStringToKeysym("Left"));
  keycode[5] = XKeysymToKeycode(dpy, XStringToKeysym("Up"));
  keycode[6] = XKeysymToKeycode(dpy, XStringToKeysym("Right"));
  keycode[7] = XKeysymToKeycode(dpy, XStringToKeysym("Down"));

  MWidth = XDisplayWidth(dpy, 0x0);
  MHeight = XDisplayHeight(dpy, 0x0);
  QWidth = MWidth / 2;
  QHeight = MHeight / 2;

  XGrabKey(dpy, keycode[0], Mod1Mask, root, True, GrabModeAsync, GrabModeAsync);
  XGrabKey(dpy, keycode[1], Mod1Mask, root, True, GrabModeAsync, GrabModeAsync);
  XGrabKey(dpy, keycode[2], Mod1Mask, root, True, GrabModeAsync, GrabModeAsync);
  XGrabKey(dpy, keycode[3], Mod1Mask, root, True, GrabModeAsync, GrabModeAsync);
  XGrabKey(dpy, keycode[4], Mod1Mask, root, True, GrabModeAsync, GrabModeAsync);
  XGrabKey(dpy, keycode[5], Mod1Mask, root, True, GrabModeAsync, GrabModeAsync);
  XGrabKey(dpy, keycode[6], Mod1Mask, root, True, GrabModeAsync, GrabModeAsync);
  XGrabKey(dpy, keycode[7], Mod1Mask, root, True, GrabModeAsync, GrabModeAsync);
  XGrabButton(dpy, 1, Mod1Mask, root, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
  XGrabButton(dpy, 3, Mod1Mask, root, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);

  for(;;)
  {
    XNextEvent(dpy, &ev);
    if(ev.type == KeyPress && ev.xkey.keycode == keycode[0]) {
        XRaiseWindow(dpy, ev.xkey.subwindow);
    }
    else if(ev.type == KeyPress && ev.xbutton.subwindow != None && ev.xkey.keycode == keycode[1]) {
        XLowerWindow(dpy, ev.xkey.subwindow);
    }
    else if(ev.type == KeyPress && ev.xbutton.subwindow != None && ev.xkey.keycode == keycode[2]) {
        XDestroyWindow(dpy, ev.xkey.subwindow);
    }
    else if(ev.type == KeyPress && ev.xbutton.subwindow != None && ev.xkey.keycode == keycode[3]) {
        XMoveResizeWindow(dpy, ev.xkey.subwindow, 0, 0, MWidth, MHeight);
    }
    else if(ev.type == KeyPress && ev.xbutton.subwindow != None && ev.xkey.keycode == keycode[4]) {
        XGetWindowAttributes(dpy, ev.xbutton.subwindow, &attr);
        if(attr.x == 0 && attr.width > QWidth) {
           XMoveResizeWindow(dpy, ev.xkey.subwindow, 0, attr.y, QWidth, attr.height);
        } else {
           XMoveResizeWindow(dpy, ev.xkey.subwindow, 0, attr.y, attr.x + attr.width, attr.height);
        }
    }
    else if(ev.type == KeyPress && ev.xbutton.subwindow != None && ev.xkey.keycode == keycode[6]) {
        XGetWindowAttributes(dpy, ev.xbutton.subwindow, &attr);
        if(attr.x + attr.width == MWidth && attr.width > QWidth) {
           XMoveResizeWindow(dpy, ev.xkey.subwindow, QWidth, attr.y, QWidth, attr.height);
        } else {
           XMoveResizeWindow(dpy, ev.xkey.subwindow, attr.x, attr.y, MWidth - attr.x, attr.height);
        }
    }
    else if(ev.type == KeyPress && ev.xbutton.subwindow != None && ev.xkey.keycode == keycode[5]) {
        XGetWindowAttributes(dpy, ev.xbutton.subwindow, &attr);
        if(attr.height > QHeight) {
           XMoveResizeWindow(dpy, ev.xkey.subwindow, attr.x, 0, attr.width, QHeight);
        } else {
           XMoveResizeWindow(dpy, ev.xkey.subwindow, attr.x, 0, attr.width, attr.y + attr.height);
        }
    }
    else if(ev.type == KeyPress && ev.xbutton.subwindow != None && ev.xkey.keycode == keycode[7]) {
        XGetWindowAttributes(dpy, ev.xbutton.subwindow, &attr);
        if(attr.height > QHeight) {
           XMoveResizeWindow(dpy, ev.xkey.subwindow, attr.x, QHeight, attr.width, QHeight);
        } else {
           XMoveResizeWindow(dpy, ev.xkey.subwindow, attr.x, attr.y, attr.width, MHeight - attr.y);
        }
    }
    else if(ev.type == ButtonPress && ev.xbutton.subwindow != None) {
        XGrabPointer(dpy, ev.xbutton.subwindow, True, PointerMotionMask|ButtonReleaseMask,
                     GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
        XGetWindowAttributes(dpy, ev.xbutton.subwindow, &attr);
        start = ev.xbutton;
    }
    else if(ev.type == MotionNotify) {
        int xdiff, ydiff;
        while(XCheckTypedEvent(dpy, MotionNotify, &ev));
        xdiff = ev.xbutton.x_root - start.x_root;
        ydiff = ev.xbutton.y_root - start.y_root;
        XMoveResizeWindow(dpy, ev.xmotion.window, attr.x + (start.button==1 ? xdiff : 0),
                          attr.y + (start.button==1 ? ydiff : 0),
                          MAX(1, attr.width + (start.button==3 ? xdiff : 0)),
                          MAX(1, attr.height + (start.button==3 ? ydiff : 0)));
    }
    else if(ev.type == ButtonRelease)
        XUngrabPointer(dpy, CurrentTime);
  }
}
 
Top
2 replies since 24/8/2014, 12:21   110 views
  Share