wmfs2 core

This commit is contained in:
Martin Duquesnoy 2011-08-05 15:04:39 +02:00
parent dab775db74
commit 1f3ae53e9d
14 changed files with 898 additions and 14 deletions

View File

@ -35,7 +35,7 @@
#define DISP_PAYLOAD(p, l) \
do { \
int i = 0; \
for(; i < (l) && (p); ++i, ++p) \
for(; i < (l) && (p); ++i, ++(p)) \
if(isprint(*(p))) \
putchar((char)*(p)); \
} while(/* CONSTCOND */ 0);
@ -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
wmfs2/src/client.c Executable file
View File

@ -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
wmfs2/src/client.h Executable file
View File

@ -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
wmfs2/src/event.c Executable file
View File

@ -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
wmfs2/src/event.h Executable file
View File

@ -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
wmfs2/src/screen.c Executable file
View File

@ -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
wmfs2/src/screen.h Executable file
View File

@ -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
wmfs2/src/tag.c Executable file
View File

@ -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
wmfs2/src/tag.h Executable file
View File

@ -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
wmfs2/src/util.c Executable file
View File

@ -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
wmfs2/src/util.h Executable file
View File

@ -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
wmfs2/src/wmfs.c Executable file
View File

@ -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
wmfs2/src/wmfs.h Executable file
View File

@ -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
wmfs2/wmfs.c Normal file
View File

@ -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;
}