Index: evdev.c =================================================================== RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/input/evdev/evdev.c,v retrieving revision 1.3 diff -c -r1.3 evdev.c *** evdev.c 18 Jan 2005 20:18:09 -0000 1.3 --- evdev.c 17 Mar 2005 17:25:40 -0000 *************** *** 70,75 **** --- 70,97 ---- static int wheel_left_button = 6; static int wheel_right_button = 7; + typedef enum { + STATE_NORMAL, /* Normal state, not touching */ + STATE_TOUCHING, /* The touchpad/touchscreen is being touched */ + STATE_TOUCH_LINGER, /* Just tapped, no longer touchng, waiting for tapTime to fill up */ + STATE_DRAGGING /* Dragging */ + } TouchState; + + typedef struct { + int oldabsx, oldabsy; + int touchStart; + TouchState state; + OsTimerPtr upTimer; + + int tapTime; + Bool touchPad; + + int min_x, min_y; + int max_x, max_y; + int screen_width, screen_height; + int screen_num; + } EvdevPrivateRec, *EvdevPrivatePtr; + static void PostButtonClicks(InputInfoPtr pInfo, int button, int count) { *************** *** 81,96 **** --- 103,163 ---- } } + /* Sends the button up event after tapTime has elapsed */ + static CARD32 + TapUpTimeout(OsTimerPtr timer, CARD32 now, pointer arg) + { + InputInfoPtr pInfo = arg; + EvdevPrivatePtr priv = pInfo->private; + int sigstate; + + if(priv->state != STATE_TOUCH_LINGER) + return 0; + + sigstate = xf86BlockSIGIO (); + + xf86PostButtonEvent(pInfo->dev, 0, 1, 0, 0, 0); + priv->state = STATE_NORMAL; + + xf86UnblockSIGIO (sigstate); + + return 0; + } + + static Bool + EvdevConvert(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2, + int v3, int v4, int v5, int *x, int *y) + { + EvdevPrivatePtr priv = pInfo->private; + if (first == 0 && num == 2) { + if(priv->touchPad) { + *x = v0; + *y = v1; + } else { + *x = xf86ScaleAxis(v0, 0, priv->screen_width, priv->min_x, priv->max_x); + *y = xf86ScaleAxis(v1, 0, priv->screen_height, priv->min_y, priv->max_y); + } + return TRUE; + } + else + return FALSE; + } + static void EvdevReadInput(InputInfoPtr pInfo) { struct input_event ev; int len, value; int dx, dy; + int absx, absy; + EvdevPrivatePtr priv = pInfo->private; dx = 0; dy = 0; + absx = priv->oldabsx; + absy = priv->oldabsy; + while (xf86WaitForInput (pInfo->fd, 0) > 0) { len = read(pInfo->fd, &ev, sizeof ev); if (len != sizeof ev) { *************** *** 131,140 **** --- 198,268 ---- break; case EV_ABS: + switch (ev.code) { + case ABS_X: + absx = value; + break; + + case ABS_Y: + absy = value; + break; + } break; case EV_KEY: switch (ev.code) { + case BTN_TOOL_FINGER: + if(value) { + if(priv->touchPad) { + priv->oldabsx = -1; + priv->oldabsy = -1; + } + /* Touch starts */ + switch(priv->state) { + case STATE_NORMAL: + priv->touchStart = GetTimeInMillis(); + priv->state = STATE_TOUCHING; + break; + + case STATE_TOUCH_LINGER: + priv->touchStart = GetTimeInMillis(); + priv->state = STATE_DRAGGING; + break; + + case STATE_TOUCHING: + case STATE_DRAGGING: + xf86Msg(X_WARNING, "spurious BTN_TOOL_FINGER down event\n"); + break; + } + } else { + /* Touch ends */ + if(priv->upTimer) { + TimerFree(priv->upTimer); + priv->upTimer = NULL; + } + switch(priv->state) { + case STATE_DRAGGING: + xf86PostButtonEvent(pInfo->dev, 0, 1, FALSE, 0, 0); + case STATE_TOUCHING: + if(GetTimeInMillis() - priv->touchStart < priv->tapTime) { + priv->state = STATE_TOUCH_LINGER; + xf86PostButtonEvent(pInfo->dev, 0, 1, TRUE, 0, 0); + + priv->upTimer = TimerSet(priv->upTimer, + 0, priv->tapTime, TapUpTimeout, pInfo); + } else { + priv->state = STATE_NORMAL; + } + break; + + case STATE_NORMAL: + case STATE_TOUCH_LINGER: + xf86Msg(X_WARNING, "spurious BTN_TOOL_FINGER up event\n"); + break; + } + } + break; + case BTN_LEFT: case BTN_RIGHT: case BTN_MIDDLE: *************** *** 161,166 **** --- 289,311 ---- } } + if(priv->state == STATE_TOUCHING || priv->state == STATE_DRAGGING) { + if(!priv->touchPad) { + int conv_x, conv_y; + EvdevConvert(pInfo, 0, 2, absx, absy, 0, 0, 0, 0, &conv_x, &conv_y); + xf86XInputSetScreen(pInfo, priv->screen_num, conv_x, conv_y); + + xf86PostMotionEvent(pInfo->dev, TRUE, 0, 2, absx, absy); + } else { + if(priv->oldabsx != -1) + dx = absx - priv->oldabsx; + if(priv->oldabsy != -1) + dy = absy - priv->oldabsy; + } + } + priv->oldabsx = absx; + priv->oldabsy = absy; + if (dx != 0 || dy != 0) xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy); } *************** *** 402,407 **** --- 547,593 ---- } static int + EvdevAddAbsClass(DeviceIntPtr device) + { + InputInfoPtr pInfo; + EvdevPrivatePtr priv; + + pInfo = device->public.devicePrivate; + priv = pInfo->private; + + if (!InitValuatorClassDeviceStruct(device, 2, + miPointerGetMotionEvents, + miPointerGetMotionBufferSize(), Absolute)) + return !Success; + + /* X valuator */ + xf86InitValuatorAxisStruct(device, + 0, /* axis id */ + priv->min_x, + priv->max_x, + 10000, /* resolution, what should we put here? */ + 0, /* min resolution */ + 10000); /* max resolution */ + xf86InitValuatorDefaults(device, 0); + + /* Y valuator */ + xf86InitValuatorAxisStruct(device, + 1, /* axis id */ + priv->min_y, + priv->max_y, + 10000, /* resolution, what should we put here? */ + 0, /* min resolution */ + 10000); /* max resolution */ + xf86InitValuatorDefaults(device, 1); + xf86MotionHistoryAllocate(pInfo); + + if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) + return !Success; + + return Success; + } + + static int EvdevAddRelClass(DeviceIntPtr device) { InputInfoPtr pInfo; *************** *** 410,416 **** if (!InitValuatorClassDeviceStruct(device, 2, miPointerGetMotionEvents, ! miPointerGetMotionBufferSize(), 0)) return !Success; /* X valuator */ --- 596,602 ---- if (!InitValuatorClassDeviceStruct(device, 2, miPointerGetMotionEvents, ! miPointerGetMotionBufferSize(), Relative)) return !Success; /* X valuator */ *************** *** 459,467 **** EvdevInit(DeviceIntPtr device) { InputInfoPtr pInfo; pInfo = device->public.devicePrivate; ! /* FIXME: This doesn't add buttons for keyboards with * scrollwheels. */ --- 645,655 ---- EvdevInit(DeviceIntPtr device) { InputInfoPtr pInfo; + EvdevPrivatePtr priv; pInfo = device->public.devicePrivate; ! priv = pInfo->private; ! /* FIXME: This doesn't add buttons for keyboards with * scrollwheels. */ *************** *** 472,477 **** --- 660,668 ---- if (pInfo->flags & XI86_POINTER_CAPABLE) { EvdevAddButtonClass(device); EvdevAddRelClass(device); + if(!priv->touchPad) { + EvdevAddAbsClass(device); + } } return Success; *************** *** 481,492 **** --- 672,693 ---- EvdevProc(DeviceIntPtr device, int what) { InputInfoPtr pInfo; + EvdevPrivatePtr priv; pInfo = device->public.devicePrivate; + priv = pInfo->private; switch (what) { case DEVICE_INIT: + /* + * these have to be here instead of in the SetupProc, because when the + * SetupProc is run at server startup, screenInfo is not setup yet + */ + priv->screen_width = screenInfo.screens[priv->screen_num]->width; + priv->screen_height = screenInfo.screens[priv->screen_num]->height; + + return EvdevInit(device); case DEVICE_ON: *************** *** 507,530 **** return Success; } - static Bool - EvdevConvert(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2, - int v3, int v4, int v5, int *x, int *y) - { - if (first == 0 && num == 2) { - *x = v0; - *y = v1; - return TRUE; - } - else - return FALSE; - } - static void EvdevProbe(InputInfoPtr pInfo) { char key_bitmask[(KEY_MAX + 7) / 8]; char rel_bitmask[(REL_MAX + 7) / 8]; int i, has_axes, has_buttons, has_keys; if (ioctl(pInfo->fd, --- 708,721 ---- return Success; } static void EvdevProbe(InputInfoPtr pInfo) { + EvdevPrivatePtr priv = pInfo->private; char key_bitmask[(KEY_MAX + 7) / 8]; + char abs_bitmask[(ABS_MAX + 7) / 8]; char rel_bitmask[(REL_MAX + 7) / 8]; + struct input_absinfo absinfo; int i, has_axes, has_buttons, has_keys; if (ioctl(pInfo->fd, *************** *** 534,544 **** --- 725,759 ---- } if (ioctl(pInfo->fd, + EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) < 0) { + xf86Msg(X_ERROR, "ioctl EVIOCGBIT failed: %s\n", strerror(errno)); + return; + } + + if (ioctl(pInfo->fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) < 0) { xf86Msg(X_ERROR, "ioctl EVIOCGBIT failed: %s\n", strerror(errno)); return; } + if(!priv->touchPad) { + if (ioctl(pInfo->fd, + EVIOCGABS(ABS_X), &absinfo) < 0) { + xf86Msg(X_ERROR, "ioctl EVIOCGABS failed: %s\n", strerror(errno)); + return; + } + priv->min_x = absinfo.minimum; + priv->max_x = absinfo.maximum; + + if (ioctl(pInfo->fd, + EVIOCGABS(ABS_Y), &absinfo) < 0) { + xf86Msg(X_ERROR, "ioctl EVIOCGABS failed: %s\n", strerror(errno)); + return; + } + priv->min_y = absinfo.minimum; + priv->max_y = absinfo.maximum; + } + has_axes = FALSE; has_buttons = FALSE; has_keys = FALSE; *************** *** 547,555 **** xf86Msg(X_INFO, "%s: Found x and y relative axes\n", pInfo->name); has_axes = TRUE; } - ! if (TestBit(BTN_LEFT, key_bitmask)) { xf86Msg(X_INFO, "%s: Found mouse buttons\n", pInfo->name); has_buttons = TRUE; } --- 762,775 ---- xf86Msg(X_INFO, "%s: Found x and y relative axes\n", pInfo->name); has_axes = TRUE; } ! if (TestBit(ABS_X, abs_bitmask) && TestBit(ABS_Y, abs_bitmask)) { ! xf86Msg(X_INFO, "%s: Found x and y absolute axes\n", pInfo->name); ! has_axes = TRUE; ! } ! ! if (TestBit(BTN_LEFT, key_bitmask) || ! (TestBit(BTN_TOOL_FINGER, key_bitmask) && priv->tapTime > 0)) { xf86Msg(X_INFO, "%s: Found mouse buttons\n", pInfo->name); has_buttons = TRUE; } *************** *** 590,598 **** InputInfoPtr pInfo; MessageType deviceFrom = X_CONFIG; const char *device; ! if (!(pInfo = xf86AllocateInput(drv, 0))) ! return NULL; /* Initialise the InputInfoRec. */ pInfo->name = dev->identifier; --- 810,825 ---- InputInfoPtr pInfo; MessageType deviceFrom = X_CONFIG; const char *device; + EvdevPrivatePtr priv; ! priv = xalloc(sizeof(EvdevPrivateRec)); ! if(!priv) ! return NULL; ! ! if (!(pInfo = xf86AllocateInput(drv, 0))) { ! xfree(priv); ! return NULL; ! } /* Initialise the InputInfoRec. */ pInfo->name = dev->identifier; *************** *** 611,626 **** pInfo->private_flags = 0; pInfo->always_core_feedback = 0; pInfo->conf_idev = dev; xf86CollectInputOptions(pInfo, NULL, NULL); xf86ProcessCommonOptions(pInfo, pInfo->options); device = xf86CheckStrOption(dev->commonOptions, "Device", NULL); if (!device) { xf86Msg(X_ERROR, "%s: No device specified.\n", pInfo->name); return pInfo; } ! xf86Msg(deviceFrom, "%s: Device: \"%s\"\n", pInfo->name, device); do { pInfo->fd = open(device, O_RDWR, 0); --- 838,864 ---- pInfo->private_flags = 0; pInfo->always_core_feedback = 0; pInfo->conf_idev = dev; + pInfo->private = priv; + + priv->upTimer = NULL; + priv->touchStart = 0; + priv->state = STATE_NORMAL; + priv->tapTime = 200; + priv->touchPad = TRUE; xf86CollectInputOptions(pInfo, NULL, NULL); xf86ProcessCommonOptions(pInfo, pInfo->options); + priv->tapTime = xf86SetIntOption(pInfo->options, "TapTime", priv->tapTime); + priv->touchPad = xf86SetBoolOption(pInfo->options, "TouchPad", priv->touchPad); + priv->screen_num = xf86SetIntOption(pInfo->options, "ScreenNumber", 0); + device = xf86CheckStrOption(dev->commonOptions, "Device", NULL); if (!device) { xf86Msg(X_ERROR, "%s: No device specified.\n", pInfo->name); return pInfo; } ! xf86Msg(deviceFrom, "%s: Device: \"%s\"\n", pInfo->name, device); do { pInfo->fd = open(device, O_RDWR, 0);