198 lines
4.3 KiB
C
198 lines
4.3 KiB
C
/*
|
|
* fookb.c
|
|
*
|
|
* (c) 1998-2004 Alexey Vyskubov <alexey@mawhrin.net>
|
|
*/
|
|
|
|
#include <stdlib.h> /* malloc() */
|
|
#include <stdio.h> /* puts() */
|
|
|
|
/* X Window headers */
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
|
|
/* Command line parsing and X resource manager */
|
|
#include <X11/Xresource.h>
|
|
|
|
/* XKB fun */
|
|
#include <X11/XKBlib.h>
|
|
|
|
/* My own fun */
|
|
#include "fookb.h"
|
|
#include "images.h"
|
|
#include "opts.h"
|
|
#include "params.h"
|
|
|
|
#define sterror(x) (void)printf("Strange error, please report! %s:%d, %s\n",\
|
|
__FILE__, __LINE__, x)
|
|
|
|
|
|
static void getGC(Window win, GC *gc, Display *dpy)
|
|
{
|
|
*gc = XCreateGC(dpy, win, 0, NULL);
|
|
//XSetBackground(dpy, *gc, 0L);
|
|
}
|
|
|
|
|
|
int main(int argc, register char *argv[])
|
|
{
|
|
Display *dpy;
|
|
int scr;
|
|
Window root;
|
|
|
|
int err;
|
|
|
|
int event_rtrn; /* for XkbOpenDisplay */
|
|
int error_rtrn;
|
|
int reason_rtrn;
|
|
|
|
XkbEvent labuda; /* Xkb event. X event will be labuda.core */
|
|
|
|
Window billy; /* _The_ Window */
|
|
|
|
int border = 0; /* _The_ Window parameters */
|
|
|
|
XWMHints *wm_hints;
|
|
XClassHint class_hints;
|
|
XColor col;
|
|
|
|
GC gc; /* Graphic context */
|
|
|
|
char resn[] = "fookb";
|
|
char resc[] = "Fookb";
|
|
|
|
|
|
int state = 0; /* We suppose that latin keyboard is the
|
|
primal state FIXME */
|
|
|
|
XrmInitialize(); /* We should initialize X resource
|
|
manager before doing something else
|
|
*/
|
|
|
|
ParseOptions(&argc, argv); /* We should parse command line
|
|
options and try to find '-display'
|
|
before opening X display */
|
|
|
|
/* Go, fighters, go! */
|
|
dpy = XkbOpenDisplay(mydispname,
|
|
&event_rtrn,
|
|
&error_rtrn, NULL, NULL, &reason_rtrn);
|
|
|
|
/* Oops. */
|
|
if (dpy == NULL) {
|
|
(void)puts("Cannot open display.");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
scr = DefaultScreen(dpy);
|
|
root = RootWindow(dpy, scr);
|
|
|
|
/* We would like receive the only Xkb event: XkbStateNotify. And only
|
|
* when XkbLockGroup happens. */
|
|
|
|
if (False == XkbSelectEvents(dpy,
|
|
XkbUseCoreKbd,
|
|
XkbAllEventsMask,
|
|
0)) {
|
|
sterror("Cannot XkbSelectEvents. It's your problem -- not mine.");
|
|
exit(EXIT_FAILURE);
|
|
} /* Deselect all events */
|
|
|
|
if (False == XkbSelectEventDetails(dpy,
|
|
XkbUseCoreKbd,
|
|
XkbStateNotify,
|
|
XkbAllEventsMask,
|
|
XkbGroupLockMask)) {
|
|
sterror("Cannot XkbSelectEventDetails. It's your problem -- not mine.");
|
|
exit(EXIT_FAILURE);
|
|
} /* Select XkbStateNotify/XkbgroupLock */
|
|
|
|
read_images(dpy); /* Let's read icon images */
|
|
|
|
/* Run out! */
|
|
billy = XCreateWindow(dpy,
|
|
root,
|
|
0, 0,
|
|
get_width(), get_height(),
|
|
border,
|
|
CopyFromParent, CopyFromParent,
|
|
CopyFromParent, 0, 0);
|
|
XParseColor(dpy, DefaultColormap(dpy, scr), read_param("Bg"), &col);
|
|
XAllocColor(dpy, DefaultColormap(dpy, scr), &col);
|
|
XSetWindowBackground(dpy, billy, col.pixel);
|
|
XStoreName(dpy, billy, "fookb");
|
|
|
|
class_hints.res_name = resn;
|
|
class_hints.res_class = resc;
|
|
|
|
err = XSetClassHint(dpy, billy, &class_hints);
|
|
switch(err) {
|
|
case BadAlloc:
|
|
sterror("BadAlloc");
|
|
exit(EXIT_FAILURE);
|
|
case BadWindow:
|
|
sterror("BadWindow");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
wm_hints = XAllocWMHints();
|
|
wm_hints->window_group = billy;
|
|
|
|
wm_hints->input = False;
|
|
wm_hints->flags = InputHint | WindowGroupHint;
|
|
|
|
err = XSetWMHints(dpy, billy, wm_hints);
|
|
switch(err) {
|
|
case BadAlloc:
|
|
sterror("BadAlloc");
|
|
exit(EXIT_FAILURE);
|
|
case BadWindow:
|
|
sterror("BadWindow");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
/* The only thing we would like to do - update our billy */
|
|
XSelectInput(dpy, billy, ExposureMask | ButtonPressMask);
|
|
|
|
XSetCommand(dpy, billy, argv, argc);
|
|
|
|
/* Programmer supplied functions */
|
|
getGC(billy, &gc, dpy);
|
|
|
|
|
|
/* Let's look */
|
|
XMapWindow(dpy, billy); /* We would like to see the window. */
|
|
|
|
/* HELLO! HELLO! HELLO! Is that our GOOD FRIEND main loop here? */
|
|
while (1) {
|
|
XNextEvent(dpy, &labuda.core);
|
|
switch (labuda.core.type) {
|
|
|
|
case Expose: /* We should update our window. */
|
|
if (labuda.core.xexpose.count != 0)
|
|
/* Well, I knew what does it mean,
|
|
but I forgot :) */
|
|
break;
|
|
update_window(billy, gc, state, dpy);
|
|
break;
|
|
default: /* XkbLockGroup happens : FIXME */
|
|
state = labuda.state.group;
|
|
#ifdef DEBUG
|
|
printf("%u\n", state);
|
|
#endif
|
|
if ((state < 0) || (state > 1))
|
|
state = 1;
|
|
update_window(billy, gc, state, dpy);
|
|
|
|
#ifdef DEBUG
|
|
puts("."); /* XkbLockGroup happens */
|
|
#endif
|
|
}
|
|
}
|
|
|
|
XFreeGC(dpy, gc);
|
|
XDestroyWindow(dpy, billy);
|
|
XCloseDisplay(dpy);
|
|
exit(0);
|
|
}
|