Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 56 additions & 2 deletions src/cfgfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.

struct cfg cfg, prev_cfg;

#ifdef USE_X11
unsigned long kbemu_keysym(const char *str);
#endif

/* all parsable config options... some of them might map to the same cfg field */
enum {
CFG_REPEAT,
Expand All @@ -57,6 +61,7 @@ enum { RMCFG_ALL, RMCFG_OWN };

static int parse_bnact(const char *s);
static const char *bnact_name(int bnact);
static int parse_kbmap(const char *str, unsigned long *kbmap, int max_keys);
static int add_cfgopt(int opt, int idx, const char *fmt, ...);
static int add_cfgopt_devid(int vid, int pid);
static int rm_cfgopt(const char *name, int mode);
Expand All @@ -76,7 +81,7 @@ static int num_lines;

void default_cfg(struct cfg *cfg)
{
int i;
int i, j;

memset(cfg, 0, sizeof *cfg);

Expand All @@ -99,7 +104,10 @@ void default_cfg(struct cfg *cfg)
for(i=0; i<MAX_BUTTONS; i++) {
cfg->map_button[i] = i;
cfg->kbmap_str[i] = 0;
cfg->kbmap[i] = 0;
cfg->kbmap_count[i] = 0;
for(j=0; j<MAX_KEYS_PER_BUTTON; j++) {
cfg->kbmap[i][j] = 0;
}
}

cfg->repeat_msec = -1;
Expand Down Expand Up @@ -399,6 +407,7 @@ int read_cfg(const char *fname, struct cfg *cfg)
free(cfg->kbmap_str[bnidx]);
}
cfg->kbmap_str[bnidx] = strdup(val_str);
cfg->kbmap_count[bnidx] = parse_kbmap(val_str, cfg->kbmap[bnidx], MAX_KEYS_PER_BUTTON);

} else if(strcmp(key_str, "led") == 0) {
lptr->opt = CFG_LED;
Expand Down Expand Up @@ -726,6 +735,51 @@ static const char *bnact_name(int bnact)
return "none";
}

static int parse_kbmap(const char *str, unsigned long *kbmap, int max_keys)
{
#ifdef USE_X11
char buf[256], *ptr, *start;
int count = 0;

if(!str || !*str) return 0;

strncpy(buf, str, sizeof buf - 1);
buf[sizeof buf - 1] = 0;

start = buf;
while(*start && count < max_keys) {
ptr = strchr(start, '+');
if(ptr) *ptr = 0;

while(*start && isspace(*start)) start++;
if(*start) {
char *end = start + strlen(start) - 1;
while(end > start && isspace(*end)) *end-- = 0;
}

if(*start) {
unsigned long ksym = (unsigned long)kbemu_keysym(start);
if(ksym == 0) {
logmsg(LOG_WARNING, "invalid key name in keyboard mapping: \"%s\"\n", start);
} else {
kbmap[count++] = ksym;
}
}

if(!ptr) break;
start = ptr + 1;
}

if(count >= max_keys && *start) {
logmsg(LOG_WARNING, "keyboard mapping truncated, max %d keys supported\n", max_keys);
}

return count;
#else
return 0;
#endif
}

static struct cfgline *find_cfgopt(int opt, int idx)
{
int i;
Expand Down
4 changes: 3 additions & 1 deletion src/cfgfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MAX_AXES 64
#define MAX_BUTTONS 64
#define MAX_CUSTOM 64
#define MAX_KEYS_PER_BUTTON 8

enum {
LED_OFF = 0,
Expand Down Expand Up @@ -51,7 +52,8 @@ struct cfg {
int map_axis[MAX_AXES];
int map_button[MAX_BUTTONS];
int bnact[MAX_BUTTONS];
int kbmap[MAX_BUTTONS];
unsigned long kbmap[MAX_BUTTONS][MAX_KEYS_PER_BUTTON];
int kbmap_count[MAX_BUTTONS];
char *kbmap_str[MAX_BUTTONS];
int swapyz;
int led, grab_device;
Expand Down
11 changes: 3 additions & 8 deletions src/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,14 +215,9 @@ void process_input(struct device *dev, struct dev_input *inp)
/* check to see if we must emulate a keyboard event instead of a
* retular button event for this button
*/
if(cfg.kbmap_str[inp->idx]) {
if(!cfg.kbmap[inp->idx]) {
cfg.kbmap[inp->idx] = kbemu_keysym(cfg.kbmap_str[inp->idx]);
if(verbose) {
logmsg(LOG_DEBUG, "mapping ``%s'' to keysym %d\n", cfg.kbmap_str[inp->idx], (int)cfg.kbmap[inp->idx]);
}
}
send_kbevent(cfg.kbmap[inp->idx], inp->val);
if(cfg.kbmap_count[inp->idx] > 0) {
KeySym *keys = (KeySym*)cfg.kbmap[inp->idx];
send_kbevent_combo(keys, cfg.kbmap_count[inp->idx], inp->val);
break;
}
#endif
Expand Down
31 changes: 29 additions & 2 deletions src/kbemu.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,18 @@ void send_kbevent(KeySym key, int press)
XEvent xevent;
Window win;
int rev_state;
KeyCode kc;

if(!dpy) return;

if(!(kc = XKeysymToKeycode(dpy, key))) {
logmsg(LOG_WARNING, "failed to convert keysym %lu to keycode\n", key);
return;
}

#ifdef HAVE_XTEST_H
if(use_xtest) {
XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, key), press, 0);
XTestFakeKeyEvent(dpy, kc, press, 0);
XFlush(dpy);
return;
}
Expand All @@ -81,7 +87,7 @@ void send_kbevent(KeySym key, int press)
xevent.xkey.root = DefaultRootWindow(dpy);
xevent.xkey.window = win;
xevent.xkey.subwindow = None;
xevent.xkey.keycode = XKeysymToKeycode(dpy, key);
xevent.xkey.keycode = kc;
xevent.xkey.state = 0;
xevent.xkey.time = CurrentTime;
xevent.xkey.x = xevent.xkey.y = 1;
Expand All @@ -90,6 +96,27 @@ void send_kbevent(KeySym key, int press)
XSendEvent(dpy, win, True, press ? KeyPressMask : KeyReleaseMask, &xevent);
XFlush(dpy);
}

void send_kbevent_combo(KeySym *keys, int count, int press)
{
int i;

if(!dpy || count <= 0) return;

if(press) {
return;
}

/* send press events for all keys */
for(i=0; i<count; i++) {
send_kbevent(keys[i], 1);
}

/* send release events in reverse order */
for(i=0; i<count; i++) {
send_kbevent(keys[count - 1 - i], 0);
}
}
#else
int spacenavd_kbemu_shut_up_empty_source_warning;
#endif /* USE_X11 */
1 change: 1 addition & 0 deletions src/kbemu.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ KeySym kbemu_keysym(const char *str);
const char *kbemu_keyname(KeySym sym);

void send_kbevent(KeySym key, int press);
void send_kbevent_combo(KeySym *keys, int count, int press);

#endif /* KBEMU_H_ */
12 changes: 6 additions & 6 deletions src/proto_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,9 @@ static int handle_request(struct client *c, struct reqresp *req)
sendresp(c, req, -1);
return 0;
}
cfg.kbmap[idx] = req->data[1];
/* TODO handle multi-key sequences in a backwards compatible way */
cfg.kbmap[idx][0] = req->data[1];
cfg.kbmap_count[idx] = req->data[1] > 0 ? 1 : 0;
free(cfg.kbmap_str[idx]);
cfg.kbmap_str[idx] = req->data[1] > 0 ? strdup(str) : 0;
sendresp(c, req, 0);
Expand All @@ -550,11 +552,9 @@ static int handle_request(struct client *c, struct reqresp *req)
sendresp(c, req, -1);
return 0;
}
if(cfg.kbmap_str[idx]) {
if(!cfg.kbmap[idx]) {
cfg.kbmap[idx] = kbemu_keysym(cfg.kbmap_str[idx]);
}
req->data[1] = cfg.kbmap[idx];
/* TODO handle multi-key sequences in a backwards compatible way */
if(cfg.kbmap_count[idx] > 0) {
req->data[1] = cfg.kbmap[idx][0];
} else {
req->data[1] = 0;
}
Expand Down