Browse Source

wmfs2 core

Martin Duquesnoy 13 years ago
parent
commit
1f3ae53e9d
14 changed files with 898 additions and 14 deletions
  1. 15 14
      hftsniff.c
  2. 138 0
      wmfs2/src/client.c
  3. 31 0
      wmfs2/src/client.h
  4. 25 0
      wmfs2/src/event.c
  5. 17 0
      wmfs2/src/event.h
  6. 45 0
      wmfs2/src/screen.c
  7. 23 0
      wmfs2/src/screen.h
  8. 38 0
      wmfs2/src/tag.c
  9. 22 0
      wmfs2/src/tag.h
  10. 82 0
      wmfs2/src/util.c
  11. 24 0
      wmfs2/src/util.h
  12. 174 0
      wmfs2/src/wmfs.c
  13. 76 0
      wmfs2/src/wmfs.h
  14. 188 0
      wmfs2/wmfs.c

+ 15 - 14
hftsniff.c

@@ -32,12 +32,12 @@
           printf("( \e[1m%s\e[0m ) ", s); \
      } while(/* CONSTCOND */ 0);
 
-#define DISP_PAYLOAD(p, l)                \
-     do {                                 \
-          int i = 0;                      \
-          for(; i < (l) && (p); ++i, ++p) \
-               if(isprint(*(p)))          \
-                    putchar((char)*(p));  \
+#define DISP_PAYLOAD(p, l)                  \
+     do {                                   \
+          int i = 0;                        \
+          for(; i < (l) && (p); ++i, ++(p)) \
+               if(isprint(*(p)))            \
+                    putchar((char)*(p));    \
      } while(/* CONSTCOND */ 0);
 
 #define BYE(s, er)                           \
@@ -233,21 +233,21 @@ main(int argc, char **argv)
      pcap_t             *descr;
      struct bpf_program  bpf;
 
-     /* Find device */
-       if(!(dev = pcap_lookupdev(errbuf)))
-          BYE("Can't find device", errbuf);
-
-     printf("Device ( %s )\n", dev);
+     if(argc < 2)
+     {
+          fprintf(stderr, "%s usage: %s <interface>\n", argv[0], argv[0]);
+          exit(EXIT_FAILURE);
+     }
 
      /* Find adress & mask */
-     if(pcap_lookupnet(dev, &netip, &mask, errbuf) < 0)
+     if(pcap_lookupnet(argv[1], &netip, &mask, errbuf) < 0)
      {
-          fprintf(stderr, "Can't find Adress or Mask: (%s)", errbuf);
+          fprintf(stderr, "Can't find Adress or Mask: (%s)\n", errbuf);
           netip = mask = 0;
      }
 
      /* Open device and reaaad */
-     if(!(descr = pcap_open_live(dev, SNAPLEN, true,  TIMEOUT, errbuf)))
+     if(!(descr = pcap_open_live(argv[1], SNAPLEN, true,  TIMEOUT, errbuf)))
           BYE("Fail at opening and reading device", errbuf);
 
      /* Check if packet is from ethernet device */
@@ -261,6 +261,7 @@ main(int argc, char **argv)
      if(pcap_setfilter(descr, &bpf) < 0)
           BYE("Can't use option", pcap_geterr(descr));
 
+     printf("%d\n", 1<<1);
      pcap_loop(descr, 10, pkt_handle, NULL);
 
      pcap_freecode(&bpf);

+ 138 - 0
wmfs2/src/client.c

@@ -0,0 +1,138 @@
+/*
+ *  wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
+ *  For license, see COPYING.
+ */
+
+#include "client.h"
+#include "util.h"
+
+/** Send a ConfigureRequest event to the Client
+ * \param c Client pointer
+*/
+void
+client_configure(Client *c)
+{
+     XConfigureEvent ev;
+
+     ev.type              = ConfigureNotify;
+     ev.event             = c->win;
+     ev.window            = c->win;
+     ev.x                 = c->geo.x;
+     ev.y                 = c->geo.y;
+     ev.width             = c->geo.w;
+     ev.height            = c->geo.h;
+     ev.above             = None;
+     ev.border_width      = 0;
+     ev.override_redirect = 0;
+
+     XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ev);
+}
+
+/** Map a client
+ * \param c Client pointer
+ */
+void
+client_map(Client *c)
+{
+     XMapWindow(W->dpy, c->win);
+}
+
+/** Unmap a client
+ * \param c Client pointer
+ */
+void
+client_unmap(Client *c)
+{
+     XUnmapWindow(W->dpy, c->win);
+}
+
+/** Close a client
+ * \param c Client pointer
+*/
+void
+client_close(Client *c)
+{
+     XEvent ev;
+     Atom *atom = NULL;
+     int proto;
+
+     /* Event will call client_remove */
+     if(XGetWMProtocols(W->dpy, c->win, &atom, &proto) && atom)
+     {
+          while(proto--)
+               if(atom[proto] == ATOM("WM_DELETE_WINDOW"))
+               {
+                    ev.type = ClientMessage;
+                    ev.xclient.window = c->win;
+                    ev.xclient.message_type = ATOM("WM_PROTOCOLS");
+                    ev.xclient.format = 32;
+                    ev.xclient.data.l[0] = ATOM("WM_DELETE_WINDOW");
+                    ev.xclient.data.l[1] = CurrentTime;
+                    ev.xclient.data.l[2] = 0;
+                    ev.xclient.data.l[3] = 0;
+                    ev.xclient.data.l[4] = 0;
+
+                    XSendEvent(W->dpy, c->win, False, NoEventMask, &ev);
+
+                    XFree(atom);
+
+                    return;
+               }
+
+          XKillClient(W->dpy, c->win);
+     }
+     else
+          XKillClient(W->dpy, c->win);
+}
+
+Client*
+client_new(Window w, XWindowAttributes *wa)
+{
+     Client *c;
+     XSetWindowAttributes at;
+
+     c = xcalloc(1, sizeof(Client));
+
+     /* C attributes */
+     c->win    = w;
+     c->screen = W->screen;
+     c->tag    = W->screen->seltag;
+     c->flags  = 0;
+
+     /* Geometry */
+     c->geo.x = wa->x;
+     c->geo.y = wa->y;
+     c->geo.w = wa->width;
+     c->geo.h = wa->height;
+
+     /* X window attributes */
+     at.event_mask = PropertyChangeMask;
+     XChangeWindowAttributes(dpy, w, CWEventMask, &at);
+
+     /* Attach */
+     SLIST_INSERT(&W->h.client, c, Client, next);
+
+     return c;
+}
+
+void
+client_remove(Client *c)
+{
+     XGrabServer(W->dpy);
+     XSetErrorHandler(wmfs_error_handler_dummy);
+
+     XReparentWindow(W->dpy, c->win, W->root, c->geo.x, c->geo.y);
+
+     SLIST_REMOVE(&W->h.client, c, Client, next);
+
+     XUngrabServer(W->dpy);
+     XSetErrorHandler(wmfs_error_handler);
+
+     free(c);
+}
+
+void
+client_free(void)
+{
+     FREE_LIST(W->client);
+}

+ 31 - 0
wmfs2/src/client.h

@@ -0,0 +1,31 @@
+/*
+ *  wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
+ *  For license, see COPYING.
+ */
+
+#ifndef CLIENT_H
+#define CLIENT_H
+
+#include "wmfs.h"
+#include "tag.h"
+#include "screen.h"
+
+typedef struct Client
+{
+     Tag *tag;
+     Screen *screen;
+     Geo *geo;
+     Flags flags;
+     Window win;
+     SLIST_ENTRY(Client) next;
+} Client;
+
+void client_configure(Client *c);
+void client_map(Client *c);
+void client_unmap(Client *c);
+void client_close(Client *c);
+Client *client_new(Window w, XWindowAttributes *wa);
+void client_remove(Client *c);
+void client_free(void);
+
+#endif /* CLIENT_H */

+ 25 - 0
wmfs2/src/event.c

@@ -0,0 +1,25 @@
+/*
+ *  wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
+ *  For license, see COPYING.
+ */
+
+#include "event.h"
+#include "util.h"
+#include "wmfs.h"
+
+static void
+event_dummy(XEvent *e)
+{
+     (void)e;
+}
+
+void
+event_init(void)
+{
+     int i = MAX_EV;
+
+     while(i--)
+          event_handle[i] = event_dummy;
+
+}
+

+ 17 - 0
wmfs2/src/event.h

@@ -0,0 +1,17 @@
+/*
+ *  wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
+ *  For license, see COPYING.
+ */
+
+#ifndef EVENT_H
+#define EVENT_H
+
+#define MAX_EV 256
+
+#define HANDLE_EVENT(e) event_handle[(e)->type](e);
+
+void event_init(void);
+
+void (*event_handle)(XEvent*)[MAX_EV];
+
+#endif /* EVENT_H */

+ 45 - 0
wmfs2/src/screen.c

@@ -0,0 +1,45 @@
+/*
+ *  wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
+ *  For license, see COPYING.
+ */
+
+#include "screen.h"
+#include "util.h"
+
+static Screen*
+screen_new(Geo g)
+{
+     Screen *s = xcalloc(1, sizeof(Screen));
+
+     s->geo = g;
+     s->seltag = NULL;
+
+     SLIST_INIT(&s->tags);
+
+     SLIST_INSERT_HEAD(s, &W->h.screen, Screen, next);
+
+     W->screen = s;
+
+     return s;
+}
+
+void
+screen_init(void)
+{
+     Geo g;
+
+     g.x = 0;
+     g.y = 0;
+     g.w = DisplayWidth(W->dpy, W->xscreen);
+     g.h = DisplayHeight(W->dpy, W->xscreen);
+
+     SLIST_INIT(&W->h.screen);
+
+     screen_new(g);
+}
+
+void
+screen_free(void)
+{
+     FREE_LIST(Screen, W->h.screen);
+}

+ 23 - 0
wmfs2/src/screen.h

@@ -0,0 +1,23 @@
+/*
+ *  wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
+ *  For license, see COPYING.
+ */
+
+#include "wmfs.h"
+#include "tag.h"
+
+#ifndef SCREEN_H
+#define SCREEN_H
+
+typedef struct Screen
+{
+     Geo geo;
+     Tag *seltag;
+     SLIST_HEAD(, Tag) tags;
+     SLIST_ENTRY(Screen) next;
+} Screen;
+
+void screen_init(void);
+void screen_free(void);
+
+#endif /* SCREEN_H */

+ 38 - 0
wmfs2/src/tag.c

@@ -0,0 +1,38 @@
+/*
+ *  wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
+ *  For license, see COPYING.
+ */
+
+#include "tag.h"
+#include "util.h"
+
+Tag*
+tag_new(Screen *s, const char *name)
+{
+     Tag *t;
+
+     t = xcalloc(1, sizeof(Tag));
+
+     t->screen = s;
+     t->name   = name;
+     t->flags  = 0;
+     t->sel    = NULL;
+
+     SLIST_INSERT_HEAD(t, &s->tags, Tag, next);
+
+     return t;
+}
+
+void
+tag_screen(Screen *s, Tag *t)
+{
+     s->seltag = t;
+
+}
+
+
+void
+tag_free(Screen *s)
+{
+     LIST_FREE(s->tags);
+}

+ 22 - 0
wmfs2/src/tag.h

@@ -0,0 +1,22 @@
+/*
+ *  wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
+ *  For license, see COPYING.
+ */
+
+#ifndef TAG_H
+#define TAG_H
+
+#include "wmfs.h"
+#include "screen.h"
+#include "client.h"
+
+typedef struct Tag
+{
+     char *name;
+     Screen *screen;
+     Flags flags;
+     Client *sel;
+     SLIST_ENTRY(Tag) next;
+} Tag;
+
+#endif /* TAG_H */

+ 82 - 0
wmfs2/src/util.c

@@ -0,0 +1,82 @@
+/*
+ *  wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
+ *  For license, see COPYING.
+ */
+
+#include "wmfs.h"
+#include "util.h"
+
+/** malloc with error support and size_t overflow protection
+ * \param nmemb number of objects
+ * \param size size of single object
+ * \return non null void pointer
+ */
+void*
+xmalloc(size_t nmemb, size_t size)
+{
+     void *ret;
+
+     if(SIZE_MAX / nmemb < size)
+          err(EXIT_FAILURE, "xmalloc(%zu, %zu), "
+                    "size_t overflow detected", nmemb, size);
+
+     if((ret = malloc(nmemb * size)) == NULL)
+          err(EXIT_FAILURE, "malloc(%zu)", nmemb * size);
+
+     return ret;
+}
+
+/** calloc with error support
+ * \param nmemb Number of objects
+ * \param size size of single object
+ * \return non null void pointer
+*/
+void*
+xcalloc(size_t nmemb, size_t size)
+{
+     void *ret;
+
+     if((ret = calloc(nmemb, size)) == NULL)
+          err(EXIT_FAILURE, "calloc(%zu * %zu)", nmemb, size);
+
+     return ret;
+}
+
+/** Execute a system command
+ * \param cmd Command
+ * \return child pid
+*/
+pid_t
+spawn(const char *format, ...)
+{
+     char *sh = NULL;
+     char cmd[512];
+     va_list ap;
+     pid_t pid;
+     size_t len;
+
+     va_start(ap, format);
+     len = vsnprintf(cmd, sizeof(cmd), format, ap);
+     va_end(ap);
+
+     if (len >= sizeof(cmd))
+     {
+          warnx("command too long (> 512 bytes)");
+          return -1;
+     }
+
+     if(!(sh = getenv("SHELL")))
+          sh = "/bin/sh";
+
+     if((pid = fork()) == 0)
+     {
+          setsid();
+          if (execl(sh, sh, "-c", cmd, (char*)NULL) == -1)
+               warn("execl(sh -c %s)", cmd);
+          exit(EXIT_FAILURE);
+     }
+     else if (pid == -1)
+          warn("fork");
+
+     return pid;
+}

+ 24 - 0
wmfs2/src/util.h

@@ -0,0 +1,24 @@
+/*
+ *  wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
+ *  For license, see COPYING.
+ */
+
+#ifndef UTIL_H
+#define UTIL_H
+
+/* Todo FREE_LIST(type, head, function_remove) */
+#define FREE_LIST(type, head)                   \
+     do {                                       \
+          type *t;                              \
+          while(!SLIST_EMPTY(&head)) {          \
+               t = SLIST_FIRST(&head);          \
+               SLIST_REMOVE_HEAD(&head, next);  \
+               free(t); /* function_remove(t)*/ \
+          }                                     \
+     } while(/* CONSTCOND */ 0);
+
+void *xmalloc(size_t nmemb, size_t size);
+void *xcalloc(size_t nmemb, size_t size);
+pid_t spawn(const char *format, ...);
+
+#endif /* UTIL_H */

+ 174 - 0
wmfs2/src/wmfs.c

@@ -0,0 +1,174 @@
+/*
+ *  wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
+ *  For license, see COPYING.
+ */
+
+#include "wmfs.h"
+#include "event.h"
+
+int
+wmfs_error_handler(Display *d, XErrorEvent *event)
+{
+      char mess[256];
+
+      /* Check if there is another WM running */
+      if(event->error_code == BadAccess
+                && W->root == event->resourceid)
+           errx(EXIT_FAILURE, "Another Window Manager is already running.");
+
+      /* Ignore focus change error for unmapped client
+       * 42 = X_SetInputFocus
+       * 28 = X_GrabButton
+       */
+     if(client_gb_win(event->resourceid))
+          if(event->error_code == BadWindow
+                    || event->request_code == 42
+                    || event->request_code == 28)
+               return 0;
+
+
+     XGetErrorText(d, event->error_code, mess, 128);
+     warnx("%s(%d) opcodes %d/%d\n  resource #%lx\n",
+               mess,
+               event->error_code,
+               event->request_code,
+               event->minor_code,
+               event->resourceid);
+
+     return 1;
+}
+
+int
+wmfs_error_handler_dummy(Display *d, XErrorEvent *event)
+{
+     (void)d;
+     (void)event;
+
+     return 0;
+}
+
+static void
+wmfs_xinit(void)
+{
+     char **misschar, **names, *defstring;
+     int d, i = 0, j = 0;
+     XModifierKeymap *mm;
+     XFontStruct **xfs = NULL;
+     XSetWindowAttributes at;
+
+     /*
+      * X Error handler
+      */
+     XSetErrorHandler(wmfs_error_handler);
+
+     /*
+      * X var
+      */
+     W->xscreen = DefaultScreen(W->dpy);
+     W->gc = DefaultGC(W->dpy, W->xscreen);
+
+     /*
+      * Root window
+      */
+     W->root = RootWindow(dpy, W->xscreen);
+     at.event_mask = KeyMask | ButtonMask | MouseMask | PropertyChangeMask
+          | SubstructureRedirectMask | SubstructureNotifyMask | StructureNotifyMask;
+     XChangeWindowAttributes(W->dpy, W->root, CWEventMask | CWCursor, &at);
+
+     /*
+      * Font
+      */
+     setlocale(LC_CTYPE, "");
+
+     W->font.fontset = XCreateFontSet(W->dpy, "fixed", &misschar, &d, &defstring);
+
+     XExtentsOfFontSet(W->font.fontset);
+     XFontsOfFontSet(W->font.fontset, &xfs, &names);
+
+     font.as    = xfs[0]->max_bounds.ascent;
+     font.de    = xfs[0]->max_bounds.descent;
+     font.width = xfs[0]->max_bounds.width;
+
+     W->font.height = W->font.as + W->font.de;
+
+     if(misschar)
+          XFreeStringList(misschar);
+
+     /*
+      * Keys
+      */
+     mm = XGetModifierMapping(W->dpy);
+
+     for(; i < 8; i++)
+          for(; j < mm->max_keypermod; ++j)
+               if(mm->modifiermap[i * mm->max_keypermod + j]
+                         == XKeysymToKeycode(W->dpy, XK_Num_Lock))
+                    W->numlockmask = (1 << i);
+     XFreeModifiermap(mm);
+
+}
+
+static void
+wmfs_loop(void)
+{
+     XEvent ev;
+
+     W->running = true;
+
+     while(W->running)
+          while(XPending(W->dpy))
+          {
+               XNextEvent(W->dpy, &ev);
+               HANDLE_EVENT(&e);
+          }
+}
+
+static void
+wmfs_init(void)
+{
+     /* X init */
+     wmfs_xinit();
+
+     /* Screen init */
+     screen_init();
+
+}
+
+void
+wmfs_quit(void)
+{
+     W->running = false;
+
+     /* X stuffs */
+     XCloseDisplay(W->dpy);
+     XFreeGC(W->gc);
+     XFreeFontSet(dpy, W->font.fontset);
+
+     screen_free();
+
+     free(W);
+}
+
+
+int
+main(int argc, char **argv)
+{
+     W = xcalloc(1, sizeof(Wmfs));
+
+     /* Get X display */
+     if(!(W->dpy = XOpenDisplay(NULL)))
+     {
+          fprintf(stderr, "%s: Can't open X server\n", argv[0]);
+          exit(EXIT_FAILURE);
+     }
+
+     /* Opt */
+
+     wmfs_init();
+
+     wmfs_loop();
+
+     wmfs_quit();
+
+     return 1;
+}

+ 76 - 0
wmfs2/src/wmfs.h

@@ -0,0 +1,76 @@
+/*
+ *  wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
+ *  For license, see COPYING.
+ */
+
+#ifndef WMFS_H
+#define WMFS_H
+
+/* Standard */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <unistd.h>
+#include <locale.h>
+#include <err.h>
+#include <sys/queue.h>
+
+/* Xlib */
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+/* Local */
+#include "screen.h"
+#include "client.h"
+
+#define ButtonMask   (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask)
+#define MouseMask    (ButtonMask | PointerMotionMask)
+#define KeyMask      (KeyPressMask | KeyReleaseMask)
+
+typedef struct
+{
+     int x, y, w, h;
+} Geo;
+
+typedef struct
+{
+     /* X11 stuffs */
+     bool running;
+     Display *dpy;
+     Window root;
+     int xscreen;
+     Flags numlockmask;
+     GC gc;
+
+     struct
+     {
+          int as, de, width, height;
+          XFontSet fontset;
+     } font;
+
+     /* Lists heads */
+     struct
+     {
+          SLIST_HEAD(, Screen) screen;
+          SLIST_HEAD(, Client) client;
+     } h;
+
+     /*
+      * Selected screen, from what you go everywhere; selected tag,
+      * and then selected client.
+      */
+     Screen *screen;
+
+} Wmfs;
+
+
+int wmfs_error_handler(Display *d, XErrorEvent *event);
+int wmfs_error_handler_dummy(Display *d, XErrorEvent *event);
+void wmfs_quit(void);
+
+/* Single global variable */
+Wmfs *W;
+
+#endif /* WMFS_H */

+ 188 - 0
wmfs2/wmfs.c

@@ -0,0 +1,188 @@
+/*
+ *  wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
+ *
+ */
+
+/* Standard */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <signal.h>
+#include <unistd.h>
+#include <locale.h>
+#include <sys/queue.h>
+
+/* Xlib */
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/cursorfont.h>
+
+/* Macro */
+#define FREE_LIST(type, head)                  \
+     do {                                      \
+          type *t;                             \
+          while(!SLIST_EMPTY(&head)) {         \
+               t = SLIST_FIRST(&head);         \
+               SLIST_REMOVE_HEAD(&head, next); \
+               free(t);                        \
+          }                                    \
+     } while(/* CONSTCOND */ 0);               \
+
+/* Structure */
+typedef unsigned int Flags;
+
+typedef struct
+{
+     int x, y, w, h;
+} Geo;
+
+typedef struct Tag
+{
+     char *name;
+     Screen *screen;
+     Flags flags;
+     Client *sel;
+     SLIST_ENTRY(Tag) next;
+} Tag;
+
+typedef struct Screen
+{
+     Geo geo;
+     Tag *seltag;
+     SLIST_HEAD(, Tag) tags;
+     SLIST_ENTRY(Screen) next;
+} Screen;
+
+typedef struct Client
+{
+     Tag *tag;
+     Screen *screen;
+     Geo *geo;
+     Flags flags;
+     SLIST_ENTRY(Client) next;
+} Client;
+
+typedef struct
+{
+     /* X11 stuffs */
+     Display *dpy;
+     Window root;
+     int xscreen;
+     GC gc;
+
+     struct
+     {
+          int as, de, width, height;
+          XFontSet fontset;
+     } font;
+
+     /* Lists heads */
+     struct
+     {
+          SLIST_HEAD(, Screen) screen;
+          SLIST_HEAD(, Client) client;
+     } h;
+
+     /*
+      * Selected screen, from what you go everywhere; selected tag,
+      * and then selected client.
+      */
+     Screen *screen;
+
+} Wmfs;
+
+/* Only global variable */
+Wmfs *W;
+
+/*
+ * SCREEN
+ */
+void
+screen_init(void)
+{
+     Geo g;
+
+     g.x = 0;
+     g.y = 0;
+     g.w = DisplayWidth(W->dpy, W->xscreen);
+     g.h = DisplayHeight(W->dpy, W->xscreen);
+
+     SLIST_INIT(&W->h.screen);
+
+     screen_new(g);
+}
+
+Screen*
+screen_new(Geo g)
+{
+     Screen *s = calloc(sizeof(Screen));
+
+     s->geo = g;
+     s->seltag = NULL;
+
+     SLIST_INIT(&s->tags);
+
+     SLIST_INSERT_HEAD(s, &W->h.screen, next);
+
+     W->screen = s;
+
+     return s;
+}
+
+void
+screen_free(void)
+{
+     FREE_LIST(Screen, W->h.screen);
+}
+
+/*
+ * INIT
+ */
+void
+init(void)
+{
+     /* X init */
+     W->xscreen = DefaultScreen(W->dpy);
+     W->gc      = DefaultGC(W->dpy, W->xscreen);
+     W->root    = RootWindow(dpy, W->xscreen);
+
+     /* Screen init */
+     screen_init();
+
+     return;
+}
+
+void
+quit(void)
+{
+     /* X stuffs */
+     XCloseDisplay(W->dpy);
+     XFreeGC(W->gc);
+     XFreeFontSet(dpy, W->font.fontset);
+
+     screen_free();
+
+     free(W);
+}
+
+int
+main(int argc, char **argv)
+{
+
+     W = calloc(sizeof(Wmfs));
+
+
+     /* Get X display */
+     if(!(W->dpy = XOpenDisplay(NULL)))
+     {
+          fprintf(stderr, "%s: Can't open X server\n", argv[0]);
+          exit(EXIT_FAILURE);
+     }
+
+     init();
+
+     quit();
+
+     return 1;
+}
+