1
/* $Id: filter.c,v 1.2 2001/06/17 08:34:30 cegger Exp $
2
******************************************************************************
4
Filter-mouse - generic mouse event translaator.
6
Copyright (C) 1999 Andreas Beck [becka@ggi-project.org]
8
Permission is hereby granted, free of charge, to any person obtaining a
9
copy of this software and associated documentation files (the "Software"),
10
to deal in the Software without restriction, including without limitation
11
the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
and/or sell copies of the Software, and to permit persons to whom the
13
Software is furnished to do so, subject to the following conditions:
15
The above copyright notice and this permission notice shall be included in
16
all copies or substantial portions of the Software.
18
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21
THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
******************************************************************************
33
#include <ggi/internal/gii-dl.h>
34
#include <ggi/internal/gii_debug.h>
36
static void send_devinfo(gii_input *inp);
43
MAP_TO, /* Dummy entry for parsing */
47
const char *maptypelist[MAP_END]={
63
const char *axislist[AX_END]={
72
double factor,treshold,higher;
75
typedef struct mapping_entry {
77
struct mapping_entry *next;
80
uint32 modifier_mask; /* all modifiers in mask */
81
uint32 modifier_value; /* must match value */
84
uint32 button, label, symbol;
91
struct transform trans;
102
fmouse_send_pbutton(gii_input *inp, uint8 type, uint32 nr)
106
_giiEventBlank(&ev, sizeof(gii_pbutton_event));
107
ev.pbutton.type = type;
108
ev.pbutton.size = sizeof(gii_pbutton_event);
109
ev.pbutton.origin = inp->origin;
110
ev.pbutton.target = GII_EV_TARGET_ALL;
111
ev.pbutton.button = nr;
112
_giiEvQueueAdd(inp, &ev);
116
static sint32 getaxis(gii_pmove_event *move,enum axis axis) {
118
case AX_X: return move->x;
119
case AX_Y: return move->y;
120
case AX_Z: return move->z;
121
case AX_WHEEL: return move->wheel;
124
return 0; /* shouldn't happen. */
127
static void setaxis(gii_pmove_event *move,enum axis axis,sint32 value) {
129
case AX_X: move->x=value;break;
130
case AX_Y: move->y=value;break;
131
case AX_Z: move->z=value;break;
132
case AX_WHEEL: move->wheel=value;break;
137
static sint32 gettrans(struct transform *tf,double invalue) {
138
return invalue*tf->factor+
139
((fabs(invalue)>tf->treshold) ? (invalue > 0.0 ? invalue-tf->treshold : invalue+tf->treshold)*tf->higher : 0) ;
146
GII_fmouse_handler(gii_input *inp, gii_event *event)
148
fmouse_priv *priv = inp->priv;
149
mapping_entry *entry;
153
static int di_sent=0;
154
gii_pmove_event pmrel,pmabs;
156
/* Did we already send the device info record ? Do so, if we didn't. */
162
GIIDPRINT_MISC("filter-mouse: Filt check.\n");
163
if (event->any.origin==inp->origin)
164
return 0; /* avoid recursion ! */
165
GIIDPRINT_MISC("filter-mouse: Real check.\n");
167
/* Track modifiers. This allows to use stuff like shift-clicking */
168
if (event->any.type==evKeyPress ||
169
event->any.type==evKeyRepeat ||
170
event->any.type==evKeyRelease) {
171
priv->modifiers=event->key.modifiers;
174
/* Clear the eventual relative and absolute events that will
175
* get sent after evaluating all rules. We should probably keep the
176
* absolute events between calls.
178
_giiEventBlank((gii_event *)&pmrel, sizeof(gii_pmove_event));
179
pmrel.type = evPtrRelative;
180
pmrel.size = sizeof(gii_pmove_event);
181
pmrel.origin = inp->origin;
182
pmrel.target = GII_EV_TARGET_ALL;
183
pmrel.x = pmrel.y = pmrel.z = pmrel.wheel = 0;
185
_giiEventBlank((gii_event *)&pmabs, sizeof(gii_pmove_event));
186
pmabs.type = evPtrAbsolute;
187
pmabs.size = sizeof(gii_pmove_event);
188
pmabs.origin = inp->origin;
189
pmabs.target = GII_EV_TARGET_ALL;
190
pmabs.x = pmabs.y = pmabs.z = pmabs.wheel = 0;
192
/* Now go through the entries and convert as appropriate.
194
for(entry = priv->entry;entry;entry = entry->next) {
197
GIIDPRINT_MISC("filter-mouse: Checking entry %p.\n",entry);
198
if ((priv->modifiers&entry->modifier_mask)!=
199
entry->modifier_value) continue; /* Modifiers are wrong. Forget it. */
201
switch(entry->from) {
203
if (event->any.type==evKeyPress||
204
event->any.type==evKeyRepeat) invalue=1; /* Key press */
205
else if (event->any.type==evKeyRelease) invalue=0; /* Key release*/
206
else continue; /* Something else - forget it. */
208
/* Continue, if the button/label/symbol doesn't match */
209
if (entry->fromdata.key.button!=GIIK_NIL&&
210
entry->fromdata.key.button!=event->key.button) continue;
211
if (entry->fromdata.key.label!=GIIK_NIL&&
212
entry->fromdata.key.label!=event->key.label) continue;
213
if (entry->fromdata.key.symbol!=GIIK_NIL&&
214
entry->fromdata.key.symbol!=event->key.sym) continue;
217
if (event->any.type==evPtrRelative)
218
invalue=getaxis(&event->pmove,entry->fromdata.axis);
222
if (event->any.type==evPtrAbsolute)
223
invalue=getaxis(&event->pmove,entry->fromdata.axis);
227
if (event->any.type==evPtrButtonPress &&
228
event->pbutton.button==entry->fromdata.button) invalue=1;
229
else if (event->any.type==evPtrButtonRelease &&
230
event->pbutton.button==entry->fromdata.button) invalue=0;
233
default:continue; /* Something is wrong */
237
setaxis(&pmrel,entry->todata.trans.axis,gettrans(&entry->todata.trans,invalue));
241
setaxis(&pmabs,entry->todata.trans.axis,gettrans(&entry->todata.trans,invalue));
245
fmouse_send_pbutton(inp,
246
invalue ? evPtrButtonPress :
248
entry->todata.button);
251
default:continue; /* Something is WRONG here. */
254
GIIDPRINT_MISC("filter-mouse: Checking entry %p.\n",entry);
257
_giiEvQueueAdd(inp, (gii_event *) &pmabs);
260
_giiEvQueueAdd(inp, (gii_event *) &pmrel);
263
if (ret) GIIDPRINT_MISC("filter-mouse: Eating event.\n");
268
static int GII_fmouse_close(gii_input *inp)
270
fmouse_priv *priv = inp->priv;
271
mapping_entry *entry,*next;
273
GIIDPRINT_MISC("GII_fmouse_close(%p) called\n", inp);
287
static gii_cmddata_getdevinfo devinfo =
289
"Mouse filter", /* long device name */
290
"mouf", /* shorthand */
291
emPointer, /* can_generate */
292
4, /* num_buttons (no supported device have more) */
293
0 /* num_axes (only for valuators) */
296
static gii_deviceinfo xdevinfo =
304
static void send_devinfo(gii_input *inp)
307
gii_cmddata_getdevinfo *dinfo;
308
int size = sizeof(gii_cmd_nodata_event)+sizeof(gii_cmddata_getdevinfo);
310
_giiEventBlank(&ev, size);
313
ev.any.type = evCommand;
314
ev.any.origin = inp->origin;
315
ev.cmd.code = GII_CMDCODE_GETDEVINFO;
317
dinfo = (gii_cmddata_getdevinfo *) ev.cmd.data;
320
_giiEvQueueAdd(inp, &ev);
323
static int checkkeyword(char *str,char **endptr,const char *list[],int numlist) {
326
if (endptr) *endptr=str;
327
while(isspace((int)*str)) str++;
329
for(x=0;x<numlist;x++) {
330
if (0==strncasecmp(str, list[x], strlen(list[x]))) {
331
if (endptr) *endptr=str+strlen(list[x]);
338
static int fmouse_doload(const char *filename,fmouse_priv *priv) {
341
char buffer[2048],*parsepoint,*pp2;
342
char *expect="nothing";
349
while(*ptr) ptr=&((*ptr)->next);
351
GIIDPRINT_MISC("filter-keymap opening config \"%s\" called\n",
352
filename ? filename : "(nil)");
353
if ( NULL==(infile=fopen(filename,"r")) ) {
356
while(fgets(buffer,2048,infile)) {
358
/* GIIDPRINT_MISC("filter-mouse should parse %s\n",buffer); - Shouldn't be needed anymore. */
360
parsepoint=pp2=buffer;
361
switch(entry.from=checkkeyword(parsepoint=pp2,&pp2,maptypelist,MAP_TO)) {
363
entry.modifier_mask=strtol(parsepoint=pp2, &pp2, 0);
364
if (pp2==parsepoint) {expect="modmask";goto error;}
365
entry.modifier_value=strtol(parsepoint=pp2, &pp2, 0);
366
if (pp2==parsepoint) {expect="modval";goto error;}
367
entry.fromdata.key.button=strtol(parsepoint=pp2, &pp2, 0);
368
if (pp2==parsepoint) {expect="key-button";goto error;}
369
entry.fromdata.key.label=strtol(parsepoint=pp2, &pp2, 0);
370
if (pp2==parsepoint) {expect="key-label";goto error;}
371
entry.fromdata.key.symbol=strtol(parsepoint=pp2, &pp2, 0);
372
if (pp2==parsepoint) {expect="key-symbol";goto error;}
377
entry.modifier_mask=strtol(parsepoint=pp2, &pp2, 0);
378
if (pp2==parsepoint) {expect="modmask";goto error;}
379
entry.modifier_value=strtol(parsepoint=pp2, &pp2, 0);
380
if (pp2==parsepoint) {expect="modval";goto error;}
381
entry.fromdata.axis=checkkeyword(parsepoint=pp2,&pp2,axislist,AX_END);
382
if (pp2==parsepoint) {expect="axis";goto error;}
385
entry.modifier_mask=strtol(parsepoint=pp2, &pp2, 0);
386
if (pp2==parsepoint) {expect="modmask";goto error;}
387
entry.modifier_value=strtol(parsepoint=pp2, &pp2, 0);
388
if (pp2==parsepoint) {expect="modval";goto error;}
389
entry.fromdata.button=strtol(parsepoint=pp2, &pp2, 0);
390
if (pp2==parsepoint) {expect="butnum";goto error;}
392
default: continue; /* silently ignore all unparseables */
394
if (MAP_TO!=checkkeyword(parsepoint=pp2,&pp2,maptypelist,MAP_END)) {
397
GIIDPRINT_MISC("filter-mouse Parse error at %d:%s (expecting %s)\n",line,parsepoint,expect);
400
switch(entry.to=checkkeyword(parsepoint=pp2,&pp2,maptypelist,MAP_TO)) {
402
expect="no KEY output allowed";
403
goto error; /* Maybe we should add that for mouse->key ? */
406
entry.todata.trans.axis=checkkeyword(parsepoint=pp2,&pp2,axislist,AX_END);
407
if (pp2==parsepoint) {expect="axis";goto error;}
408
entry.todata.trans.factor=strtod(parsepoint=pp2, &pp2);
409
if (pp2==parsepoint) entry.todata.trans.factor=1.0; /* O.k. - the rest will fail as well. So all defaults. */
410
entry.todata.trans.treshold=strtod(parsepoint=pp2, &pp2);
411
if (pp2==parsepoint) entry.todata.trans.treshold=9999.0;
412
entry.todata.trans.higher=strtod(parsepoint=pp2, &pp2);
413
if (pp2==parsepoint) entry.todata.trans.higher=entry.todata.trans.factor;
416
entry.todata.button=strtol(parsepoint=pp2, &pp2, 0);
417
if (pp2==parsepoint) {expect="button";goto error;}
421
*ptr=malloc(sizeof(mapping_entry));
423
memcpy(*ptr,&entry,sizeof(mapping_entry));
434
static int fmouse_loadmap(const char *args,fmouse_priv *priv) {
438
char appendstr[] = "/filter/mouse";
440
if (args&&*args) return fmouse_doload(args,priv);
442
dirname = ggGetUserDir();
443
if (strlen(dirname) + sizeof(appendstr) < 2048) {
444
sprintf(fname, "%s%s", dirname, appendstr);
445
if (fmouse_doload(fname,priv)
451
dirname = giiGetConfDir();
452
if (strlen(dirname) + sizeof(appendstr) < 2048) {
453
sprintf(fname, "%s%s", dirname, appendstr);
454
if (fmouse_doload(fname,priv)
459
return 1; /* Failure */
462
int GIIdlinit(gii_input *inp, const char *args, void *argptr)
466
GIIDPRINT_MISC("filter-mouse init(%p, \"%s\") called\n", inp,
469
priv = malloc(sizeof(fmouse_priv));
470
if (priv == NULL) return GGI_ENOMEM;
474
fmouse_loadmap(args,priv);
477
inp->GIIhandler = GII_fmouse_handler;
478
inp->GIIclose = GII_fmouse_close;
479
inp->devinfo = &xdevinfo;
480
xdevinfo.origin = inp->origin;
482
GIIDPRINT_MISC("filter-mouse fully up\n");