rearranging source, adding mousebuttonmodifier.
This commit is contained in:
parent
1aa6bd5ebe
commit
81e162dc4b
16
config.def.h
16
config.def.h
@ -20,7 +20,7 @@ static Key keys[] = {
|
||||
{ "-_", XK_minus, 1 },
|
||||
{ "=+", XK_plus, 1 },
|
||||
{ "<-", XK_BackSpace, 2 },
|
||||
{ 0 },
|
||||
{ 0 }, /* New row */
|
||||
{ "->|", XK_Tab, 1 },
|
||||
{ 0, XK_q, 1 },
|
||||
{ 0, XK_w, 1 },
|
||||
@ -35,7 +35,7 @@ static Key keys[] = {
|
||||
{ "[", XK_bracketleft, 1 },
|
||||
{ "]", XK_bracketright, 1 },
|
||||
{ "Return", XK_Return, 3 },
|
||||
{ 0 },
|
||||
{ 0 }, /* New row */
|
||||
{ 0, XK_Caps_Lock, 2 },
|
||||
{ 0, XK_a, 1 },
|
||||
{ 0, XK_s, 1 },
|
||||
@ -49,9 +49,8 @@ static Key keys[] = {
|
||||
{ ":;", XK_semicolon, 1 },
|
||||
{ "'\"", XK_exclam, 1 },
|
||||
{ "\\|", XK_backslash, 1 },
|
||||
{ 0 },
|
||||
{ 0, XK_Shift_L, 2 },
|
||||
{ "<>|", XK_greater, 1 },
|
||||
{ 0 }, /* New row */
|
||||
{ 0, XK_Shift_L, 3 },
|
||||
{ 0, XK_z, 1 },
|
||||
{ 0, XK_x, 1 },
|
||||
{ 0, XK_c, 1 },
|
||||
@ -63,10 +62,15 @@ static Key keys[] = {
|
||||
{ ".", XK_period, 1 },
|
||||
{ "/?", XK_slash, 1 },
|
||||
{ 0, XK_Shift_R, 2 },
|
||||
{ 0 },
|
||||
{ 0 }, /* New row */
|
||||
{ "Ctrl", XK_Control_L, 2 },
|
||||
{ "Alt", XK_Alt_L, 2 },
|
||||
{ "", XK_space, 5 },
|
||||
{ "Alt", XK_Alt_R, 2 },
|
||||
{ "Ctrl", XK_Control_R, 2 },
|
||||
};
|
||||
|
||||
Buttonmod buttonmods[] = {
|
||||
{ XK_Shift_L, Button2 },
|
||||
{ XK_Alt_L, Button3 },
|
||||
};
|
||||
|
8
config.h
8
config.h
@ -50,8 +50,7 @@ static Key keys[] = {
|
||||
{ "'\"", XK_exclam, 1 },
|
||||
{ "\\|", XK_backslash, 1 },
|
||||
{ 0 },
|
||||
{ 0, XK_Shift_L, 2 },
|
||||
{ "<>|", XK_greater, 1 },
|
||||
{ 0, XK_Shift_L, 3 },
|
||||
{ 0, XK_z, 1 },
|
||||
{ 0, XK_x, 1 },
|
||||
{ 0, XK_c, 1 },
|
||||
@ -70,3 +69,8 @@ static Key keys[] = {
|
||||
{ "Alt", XK_Alt_R, 2 },
|
||||
{ "Ctrl", XK_Control_R, 2 },
|
||||
};
|
||||
|
||||
Buttonmod buttonmods[] = {
|
||||
{ XK_Shift_L, Button2 },
|
||||
{ XK_Alt_L, Button3 },
|
||||
};
|
||||
|
154
svkbd.c
154
svkbd.c
@ -1,29 +1,7 @@
|
||||
/* See LICENSE file for copyright and license details.
|
||||
*
|
||||
* dynamic window manager is designed like any other X client as well. It is
|
||||
* driven through handling X events. In contrast to other X clients, a window
|
||||
* manager selects for SubstructureRedirectMask on the root window, to receive
|
||||
* events about window (dis-)appearance. Only one X connection at a time is
|
||||
* allowed to select for this event mask.
|
||||
*
|
||||
* Calls to fetch an X event from the event queue are blocking. Due reading
|
||||
* status text from standard input, a select()-driven main loop has been
|
||||
* implemented which selects for reads on the X connection and STDIN_FILENO to
|
||||
* handle all data smoothly. The event handlers of dwm are organized in an
|
||||
* array which is accessed whenever a new event has been fetched. This allows
|
||||
* event dispatching in O(1) time.
|
||||
*
|
||||
* Each child of the root window is called a client, except windows which have
|
||||
* set the override_redirect flag. Clients are organized in a global
|
||||
* doubly-linked client list, the focus history is remembered through a global
|
||||
* stack list. Each client contains a bit array to indicate the tags of a
|
||||
* client.
|
||||
*
|
||||
* Keys and tagging rules are organized as arrays and defined in config.h.
|
||||
*
|
||||
* To understand everything else, start reading main().
|
||||
* To understand svkbd, start reading main().
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
@ -32,20 +10,13 @@
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
|
||||
/* macros */
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
|
||||
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask))
|
||||
#define LENGTH(x) (sizeof x / sizeof x[0])
|
||||
#define MAXMOD 16
|
||||
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
|
||||
#define TAGMASK ((int)((1LL << LENGTH(tags)) - 1))
|
||||
#define TEXTW(x) (textnw(x, strlen(x)) + dc.font.height)
|
||||
|
||||
/* enums */
|
||||
enum { ColFG, ColBG, ColLast };
|
||||
@ -77,12 +48,17 @@ typedef struct {
|
||||
Bool pressed;
|
||||
} Key;
|
||||
|
||||
typedef struct {
|
||||
KeySym mod;
|
||||
uint button;
|
||||
} Buttonmod;
|
||||
|
||||
/* function declarations */
|
||||
static void buttonpress(XEvent *e);
|
||||
static void buttonrelease(XEvent *e);
|
||||
static void cleanup(void);
|
||||
static void configurenotify(XEvent *e);
|
||||
static void destroynotify(XEvent *e);
|
||||
static void unmapnotify(XEvent *e);
|
||||
static void die(const char *errstr, ...);
|
||||
static void drawkeyboard(void);
|
||||
static void drawkey(Key *k);
|
||||
@ -92,9 +68,11 @@ static ulong getcolor(const char *colstr);
|
||||
static void initfont(const char *fontstr);
|
||||
static void leavenotify(XEvent *e);
|
||||
static void motionnotify(XEvent *e);
|
||||
static void press(Key *k, KeySym mod);
|
||||
static void run(void);
|
||||
static void setup(void);
|
||||
static int textnw(const char *text, uint len);
|
||||
static void unpress();
|
||||
static void updatekeys();
|
||||
|
||||
/* variables */
|
||||
@ -104,7 +82,7 @@ static void (*handler[LASTEvent]) (XEvent *) = {
|
||||
[ButtonPress] = buttonpress,
|
||||
[ButtonRelease] = buttonrelease,
|
||||
[ConfigureNotify] = configurenotify,
|
||||
[DestroyNotify] = destroynotify,
|
||||
[UnmapNotify] = unmapnotify,
|
||||
[Expose] = expose,
|
||||
[LeaveNotify] = leavenotify,
|
||||
[MotionNotify] = motionnotify,
|
||||
@ -113,57 +91,34 @@ static Display *dpy;
|
||||
static DC dc;
|
||||
static Window root, win;
|
||||
static Bool running = True;
|
||||
static Key *hover = NULL, *pressed = NULL;
|
||||
static Key *hover = NULL;
|
||||
static KeySym pressedmod = 0;
|
||||
/* configuration, allows nested code to access above variables */
|
||||
#include "config.h"
|
||||
|
||||
void
|
||||
buttonpress(XEvent *e) {
|
||||
int i;
|
||||
XButtonPressedEvent *ev = &e->xbutton;
|
||||
Key *k;
|
||||
KeySym mod = 0;
|
||||
|
||||
if((k = findkey(ev->x, ev->y))) {
|
||||
if(k->pressed && IsModifierKey(k->keysym)) {
|
||||
XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, k->keysym), False, 0);
|
||||
k->pressed = 0;
|
||||
pressed = NULL;
|
||||
for(i = 0; i < LENGTH(buttonmods); i++)
|
||||
if(ev->button == buttonmods[i].button) {
|
||||
mod = buttonmods[i].mod;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
pressed = k;
|
||||
k->pressed = True;
|
||||
XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, k->keysym), True, 0);
|
||||
}
|
||||
drawkey(k);
|
||||
XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, ww, wh, 0, 0);
|
||||
}
|
||||
if((k = findkey(ev->x, ev->y)))
|
||||
press(k, mod);
|
||||
}
|
||||
|
||||
void
|
||||
buttonrelease(XEvent *e) {
|
||||
int i;
|
||||
XButtonPressedEvent *ev = &e->xbutton;
|
||||
Key *k = findkey(ev->x, ev->y);
|
||||
Key *k;
|
||||
|
||||
if(pressed && k && !IsModifierKey(k->keysym)) {
|
||||
if(k != pressed) {
|
||||
XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, k->keysym), True, 0);
|
||||
k->pressed = 1;
|
||||
}
|
||||
for(i = 0; i < LENGTH(keys); i++) {
|
||||
if(keys[i].pressed && !IsModifierKey(keys[i].keysym)) {
|
||||
XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, keys[i].keysym), False, 0);
|
||||
keys[i].pressed = 0;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < LENGTH(keys); i++) {
|
||||
if(keys[i].pressed) {
|
||||
XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, keys[i].keysym), False, 0);
|
||||
keys[i].pressed = 0;
|
||||
}
|
||||
}
|
||||
pressed = NULL;
|
||||
}
|
||||
drawkeyboard();
|
||||
if((k = findkey(ev->x, ev->y)))
|
||||
unpress(k);
|
||||
}
|
||||
|
||||
void
|
||||
@ -229,8 +184,9 @@ drawkey(Key *k) {
|
||||
col = dc.norm;
|
||||
XSetForeground(dpy, dc.gc, col[ColBG]);
|
||||
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
|
||||
XSetForeground(dpy, dc.gc, col[ColFG]);
|
||||
XSetForeground(dpy, dc.gc, dc.norm[ColFG]);
|
||||
XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
|
||||
XSetForeground(dpy, dc.gc, col[ColFG]);
|
||||
if(k->label)
|
||||
l = k->label;
|
||||
else
|
||||
@ -246,7 +202,7 @@ drawkey(Key *k) {
|
||||
}
|
||||
|
||||
void
|
||||
destroynotify(XEvent *e) {
|
||||
unmapnotify(XEvent *e) {
|
||||
running = False;
|
||||
}
|
||||
|
||||
@ -291,7 +247,7 @@ initfont(const char *fontstr) {
|
||||
dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
|
||||
if(missing) {
|
||||
while(n--)
|
||||
fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]);
|
||||
fprintf(stderr, "svkbd: missing fontset: %s\n", missing[n]);
|
||||
XFreeStringList(missing);
|
||||
}
|
||||
if(dc.font.set) {
|
||||
@ -322,13 +278,11 @@ initfont(const char *fontstr) {
|
||||
|
||||
void
|
||||
leavenotify(XEvent *e) {
|
||||
Key *h = hover;
|
||||
|
||||
unpress(NULL);
|
||||
if(!hover)
|
||||
return;
|
||||
hover = NULL;
|
||||
drawkey(h);
|
||||
XCopyArea(dpy, dc.drawable, win, dc.gc, h->x, h->y, h->w, h->h, h->x, h->y);
|
||||
drawkeyboard();
|
||||
}
|
||||
|
||||
void
|
||||
@ -347,6 +301,24 @@ motionnotify(XEvent *e) {
|
||||
XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, ww, wh, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
press(Key *k, KeySym mod) {
|
||||
int i;
|
||||
k->pressed = !k->pressed;
|
||||
|
||||
if(!IsModifierKey(k->keysym)) {
|
||||
for(i = 0; i < LENGTH(keys); i++)
|
||||
if(keys[i].pressed && IsModifierKey(keys[i].keysym))
|
||||
XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, keys[i].keysym), True, 0);
|
||||
pressedmod = mod;
|
||||
if(pressedmod)
|
||||
XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, mod), True, 0);
|
||||
XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, k->keysym), True, 0);
|
||||
}
|
||||
drawkey(k);
|
||||
XCopyArea(dpy, dc.drawable, win, dc.gc, k->x, k->y, k->w, k->h, k->x, k->y);
|
||||
}
|
||||
|
||||
void
|
||||
run(void) {
|
||||
XEvent ev;
|
||||
@ -413,6 +385,30 @@ textnw(const char *text, uint len) {
|
||||
return XTextWidth(dc.font.xfont, text, len);
|
||||
}
|
||||
|
||||
void
|
||||
unpress() {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < LENGTH(keys); i++)
|
||||
if(keys[i].pressed && !IsModifierKey(keys[i].keysym)) {
|
||||
XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, keys[i].keysym), False, 0);
|
||||
keys[i].pressed = 0;
|
||||
break;
|
||||
}
|
||||
if(i != LENGTH(keys)) {
|
||||
for(i = 0; i < LENGTH(keys); i++) {
|
||||
if(pressedmod)
|
||||
XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, pressedmod), False, 0);
|
||||
pressedmod = 0;
|
||||
if(keys[i].pressed) {
|
||||
XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, keys[i].keysym), False, 0);
|
||||
keys[i].pressed = 0;
|
||||
}
|
||||
}
|
||||
drawkeyboard();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
updatekeys() {
|
||||
int rows, i, j;
|
||||
@ -429,7 +425,7 @@ updatekeys() {
|
||||
keys[i].x = x;
|
||||
keys[i].y = y;
|
||||
keys[i].w = keys[i].width * (ww - 1) / base;
|
||||
if(rows)
|
||||
if(rows != 1)
|
||||
keys[i].h = h;
|
||||
else
|
||||
keys[i].h = (wh - 1) - y;
|
||||
@ -447,17 +443,13 @@ main(int argc, char *argv[]) {
|
||||
die("svkc-"VERSION", © 2006-2008 svkbd engineers, see LICENSE for details\n");
|
||||
else if(argc != 1)
|
||||
die("usage: svkbd [-v]\n");
|
||||
|
||||
if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
|
||||
fprintf(stderr, "warning: no locale support\n");
|
||||
|
||||
if(!(dpy = XOpenDisplay(0)))
|
||||
die("svkbd: cannot open display\n");
|
||||
|
||||
setup();
|
||||
run();
|
||||
cleanup();
|
||||
|
||||
XCloseDisplay(dpy);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user