/* * Xpsitouch handles the Psion LCD toolbars. * * Slightly influenced by xbut and XRmouse, thanks! * * Copyright 2002 Tony Lindgren * License: GPL * Warranty: None */ #include "xpsitouch.h" touchpanel *tp; int main(int argc, char *argv[]) { XEvent xev; tp = (touchpanel *)tp_init(argc, argv); for(;;) { XNextEvent(tp->display, &xev); switch (xev.type) { case EnterNotify: TPDEBUG("EnterNotify: x = %d y = %d\n", xev.xmotion.x, xev.xmotion.y); tp_handle_toolbars(tp, xev); break; case MotionNotify: TPDEBUG("MotionNotify: x = %d y = %d\n", xev.xmotion.x, xev.xmotion.y); tp_handle_toolbars(tp, xev); break; case KeyPress: tp_handle_keypress(tp, xev); break; case KeyRelease: tp_handle_keyrelease(tp, xev); break; default: TPDEBUG("Unhandled event: %d\n", xev.type); break; } } tp_exit(tp, 1); } void tp_exec_program(touchpanel *tp, int toolbar, int button) { char *path = TOOLBAR_SYSTEM_SHELL_SCRIPT; int pid, ret = 0; char *argv[4]; char arg1[4]; char arg2[4]; (void)signal(SIGCLD, SIG_IGN); pid = fork(); if (pid < 0) { printf("Could not fork\n"); } else if (pid == 0) { argv[0] = "sh"; argv[1] = arg1; argv[2] = arg2; argv[3] = NULL; sprintf(argv[1], "%d", toolbar); sprintf(argv[2], "%d", button); ret = execvp(path, argv); exit(111); } else { /* Parent */ } } void tp_handle_zoom_buttons(touchpanel *tp, XEvent xev) { int zoom_button; /* Divide the 2 button zoom control area into 3 buttons */ zoom_button = ((xev.xmotion.y - (3 * Y_TOOLB_BUTTON_HEIGHT)) / (2 * Y_TOOLB_BUTTON_HEIGHT / 3)) + 1; TPDEBUG("zoom_button: %d\n", zoom_button); if (tp->queued) { TPDEBUG("Already queued, ignoring press\n"); return; } tp->x_no_buttons = XGetPointerMapping(tp->display, tp->orig_map, NUM_MAX_MOUSEBUTTONS); tp->queued = 1; tp->new_map[0] = (unsigned char)zoom_button; while (XSetPointerMapping(tp->display, tp->new_map, tp->x_no_buttons) == MappingBusy) {}; switch (zoom_button) { case 1: break; case 2: case 3: #ifdef AUTO_RESTORE usleep(AUTO_RESTORE_VAL); break; #endif } while (XSetPointerMapping(tp->display, tp->orig_map, tp->x_no_buttons) == MappingBusy) {}; tp->queued = 0; } void tp_handle_toolbars(touchpanel *tp, XEvent xev) { int button; /* We don't care about coordinates outside the toolbar */ if ((xev.xmotion.y < X_TOOLB_Y_TRIGGER) && (xev.xmotion.x > Y_TOOLB_X_TRIGGER)) { return; } /* Handle bottom "X" LCD toolbar */ if (xev.xmotion.y >= X_TOOLB_Y_TRIGGER) { button = ((xev.xmotion.x + X_TOOLB_CALIBRATION) / X_TOOLB_BUTTON_WIDTH) + 1; tp_exec_program(tp, 1, button); return; } /* Handle left "Y" LCD toolbar */ if (xev.xmotion.x <= Y_TOOLB_X_TRIGGER) { button = ((xev.xmotion.y + Y_TOOLB_CALIBRATION) / Y_TOOLB_BUTTON_HEIGHT) + 1; /* * We use the zoom controller for toggling the * pointer buttons. */ if (button >= 4) { tp_handle_zoom_buttons(tp, xev); return; } tp_exec_program(tp, 2, button); return; } } void tp_handle_keypress(touchpanel *tp, XEvent xev) { int i, j, button; if (tp->queued) { TPDEBUG("Already queued, ignoring press\n"); return; } tp->queued = 1; for (i = 0; i < tp->no_keys; i++) { if (xev.xkey.keycode == tp->keymap_list[i]->keycode) { /* Button is always the index + 1 */ button = i + 1; tp->x_no_buttons = XGetPointerMapping(tp->display, tp->orig_map, NUM_MAX_MOUSEBUTTONS); #ifdef DEBUG printf("Saved to tp->orig_map: "); for (j = 0; j < NUM_MAX_MOUSEBUTTONS; j++) { printf("%d ", tp->orig_map[j]); } printf("\n"); #endif tp->new_map[0] = (unsigned char)button; #ifdef DEBUG printf("Setting tp->new_map: "); for (j = 0; j < NUM_MAX_MOUSEBUTTONS; j++) { printf("%d ", tp->new_map[j]); } printf("\n"); #endif while (XSetPointerMapping(tp->display, tp->new_map, tp->x_no_buttons) == MappingBusy) {}; } } } void tp_handle_keyrelease(touchpanel *tp, XEvent xev) { int j; #ifdef DEBUG printf("Restoring tp->orig_map: "); for (j = 0; j < NUM_MAX_MOUSEBUTTONS; j++) { printf("%d ", tp->orig_map[j]); } printf("\n"); #endif #ifdef AUTO_RESTORE usleep(AUTO_RESTORE_VAL); #endif while (XSetPointerMapping(tp->display, tp->orig_map, tp->x_no_buttons) == MappingBusy) {}; tp->queued = 0; } touch_keymap* tp_new_keymap() { touch_keymap *keymap = NULL; keymap = (touch_keymap *)malloc(sizeof(touch_keymap)); if (keymap == NULL) { printf("Could not allocate memory for a new keymap\n"); } keymap->keycode = 0; keymap->modifier = 0; return keymap; } int tp_init_keylist(touchpanel *tp, int size) { touch_keymap *keymap; touch_keymap **keymap_list; int i; keymap_list = (touch_keymap **)calloc(size, sizeof(touch_keymap *)); tp->keymap_list = keymap_list; if (keymap_list == NULL) { printf("Keymap list memory allocation failed\n"); return 0; } for (i = 0; i < size; i++) { keymap = tp_new_keymap(); if (keymap == NULL) { printf("Keymap memory allocation failed\n"); } keymap_list[i] = keymap; tp->no_keys++; } return 1; } int tp_load_keymaps(touchpanel *tp) { int i; // FIXME: Should be loaded from command line tp->keymap_list[0]->keycode = KEY1; tp->keymap_list[0]->modifier = MOD1; tp->keymap_list[1]->keycode = KEY2; tp->keymap_list[1]->modifier = MOD2; tp->keymap_list[2]->keycode = KEY3; tp->keymap_list[2]->modifier = MOD3; #ifdef DEBUG for (i = 0; i < tp->no_keys; i++) { printf("\tkey: %d\tmodifier: %d\n", tp->keymap_list[i]->keycode, tp->keymap_list[i]->modifier); } #endif return 1; } int tp_listen_keys(touchpanel *tp, int grab) { int i; /* We cannot use XButtonPressMask, it's already taken */ XSelectInput(tp->display, tp->window, (EnterWindowMask | PointerMotionMask)); for (i = 0; i < tp->no_keys; i++) { if (grab) { XGrabKey(tp->display, tp->keymap_list[i]->keycode, tp->keymap_list[i]->modifier, tp->window, False, GrabModeAsync, GrabModeAsync); } else { XUngrabKey(tp->display, tp->keymap_list[i]->keycode, tp->keymap_list[i]->modifier, tp->window); } } } void tp_signal_handler(int sig) { printf("Got signal %d\n", sig); switch (sig) { case SIGINT: tp_exit(tp, 0); break; default: printf("Got unhandled signal\n"); } } int parse_args(touchpanel *tp, int argc, char *argv[]) { int i; for (i = 1; i < argc; i++) { if (!(strcmp(argv[i], "-display")) || !(strcmp(argv[i], "-d"))) { if (i++ < argc) { if (strlen(argv[i]) > 512) return; tp->display_name = argv[i]; } } } } touchpanel * tp_init(int argc, char *argv[]) { touchpanel *tp = NULL; int i, ret; (void)signal(SIGINT, tp_signal_handler); tp = (touchpanel *)malloc(sizeof(touchpanel)); if (tp == NULL) { printf("Could not allocate memory\n"); tp_exit(tp, 10); } parse_args(tp, argc, argv); tp->display = XOpenDisplay(tp->display_name); if (tp->display == NULL) { printf("Could not open display\n"); tp_exit(tp, 11); } tp->screen = DefaultScreen(tp->display); tp->window = RootWindow(tp->display, tp->screen); tp->no_keys = 0; tp->no_buttons = 0; tp->queued = 0; ret = XTestGrabControl(tp->display, True); if (ret != 1) { printf("Could not grab display\n"); tp_exit(tp, 12); } ret = tp_init_keylist(tp, NUM_PSION_MOUSEBUTTONS); if (ret != 1) { printf("Keymap memory allocation failed\n"); } ret = tp_load_keymaps(tp); ret = tp_listen_keys(tp, 1); tp->orig_map = (unsigned char *)calloc(NUM_MAX_MOUSEBUTTONS, sizeof(unsigned char)); tp->new_map = (unsigned char *)calloc(NUM_MAX_MOUSEBUTTONS, sizeof(unsigned char)); for (i = 0; i < NUM_MAX_MOUSEBUTTONS; i++) { tp->new_map[i] = 0; } return tp; } void tp_exit(touchpanel *tp, int code) { int ret; ret = tp_listen_keys(tp, 0); free(tp); exit(code); }