📄 lib_mouse.c
字号:
} else { found = TRUE; } } } /* * The gpm_fd file-descriptor may be negative (xterm). So we have to * maintain our notion of whether the mouse connection is active * without testing the file-descriptor. */ if (found && enable_gpm_mouse(TRUE)) { SP->_mouse_type = M_GPM; SP->_mouse_fd = *my_gpm_fd; T(("GPM mouse_fd %d", SP->_mouse_fd)); returnVoid; } }#endif /* USE_GPM_SUPPORT */ /* OS/2 VIO */#if USE_EMX_MOUSE if (!mouse_thread && strstr(cur_term->type.term_names, "xterm") == 0 && key_mouse) { int handles[2]; if (pipe(handles) < 0) { perror("mouse pipe error"); returnVoid; } else { int rc; if (!mouse_buttons[0]) { char *s = getenv("MOUSE_BUTTONS_123"); mouse_buttons[0] = 1; if (s && strlen(s) >= 3) { mouse_buttons[1] = s[0] - '0'; mouse_buttons[2] = s[1] - '0'; mouse_buttons[3] = s[2] - '0'; } } mouse_wfd = handles[1]; M_FD(SP) = handles[0]; /* Needed? */ setmode(handles[0], O_BINARY); setmode(handles[1], O_BINARY); /* Do not use CRT functions, we may single-threaded. */ rc = DosCreateThread((unsigned long *) &mouse_thread, mouse_server, 0, 0, 8192); if (rc) { printf("mouse thread error %d=%#x", rc, rc); } else { SP->_mouse_type = M_XTERM; } returnVoid; } }#endif /* USE_EMX_MOUSE */#if USE_SYSMOUSE { struct mouse_info the_mouse; char *the_device = 0; if (isatty(SP->_ifd)) the_device = ttyname(SP->_ifd); if (the_device == 0) the_device = "/dev/tty"; SP->_mouse_fd = open(the_device, O_RDWR); if (SP->_mouse_fd >= 0) { /* * sysmouse does not have a usable user interface for obtaining * mouse events. The logical way to proceed (reading data on a * stream) only works if one opens the device as root. Even in * that mode, careful examination shows we lose events * occasionally. The interface provided for user programs is to * establish a signal handler. really. * * Take over SIGUSR2 for this purpose since SIGUSR1 is more * likely to be used by an application. getch() will have to * handle the misleading EINTR's. */ signal(SIGUSR2, SIG_IGN); the_mouse.operation = MOUSE_MODE; the_mouse.u.mode.mode = 0; the_mouse.u.mode.signal = SIGUSR2; if (ioctl(SP->_mouse_fd, CONS_MOUSECTL, &the_mouse) != -1) { signal(SIGUSR2, handle_sysmouse); the_mouse.operation = MOUSE_SHOW; ioctl(SP->_mouse_fd, CONS_MOUSECTL, &the_mouse);#if defined(FBIO_MODEINFO) || defined(CONS_MODEINFO) /* FreeBSD > 2.x */ {#ifndef FBIO_GETMODE /* FreeBSD 3.x */#define FBIO_GETMODE CONS_GET#define FBIO_MODEINFO CONS_MODEINFO#endif /* FBIO_GETMODE */ video_info_t the_video; if (ioctl(SP->_mouse_fd, FBIO_GETMODE, &the_video.vi_mode) != -1 && ioctl(SP->_mouse_fd, FBIO_MODEINFO, &the_video) != -1) { SP->_sysmouse_char_width = the_video.vi_cwidth; SP->_sysmouse_char_height = the_video.vi_cheight; } }#endif /* defined(FBIO_MODEINFO) || defined(CONS_MODEINFO) */ if (SP->_sysmouse_char_width <= 0) SP->_sysmouse_char_width = 8; if (SP->_sysmouse_char_height <= 0) SP->_sysmouse_char_height = 16; SP->_mouse_type = M_SYSMOUSE; returnVoid; } } }#endif /* USE_SYSMOUSE */ /* we know how to recognize mouse events under "xterm" */ if (key_mouse != 0) { if (!strcmp(key_mouse, xterm_kmous)) { init_xterm_mouse(); } } else if (strstr(cur_term->type.term_names, "xterm") != 0) { (void) _nc_add_to_try(&(SP->_keytry), xterm_kmous, KEY_MOUSE); init_xterm_mouse(); } returnVoid;}static bool_nc_mouse_init(void)/* initialize the mouse */{ int i; if (!initialized && (SP != 0)) { initialized = TRUE; TR(MY_TRACE, ("_nc_mouse_init() called")); for (i = 0; i < EV_MAX; i++) events[i].id = INVALID_EVENT; initialize_mousetype(); T(("_nc_mouse_init() set mousetype to %d", SP->_mouse_type)); } return initialized;}/* * Query to see if there is a pending mouse event. This is called from * fifo_push() in lib_getch.c */static bool_nc_mouse_event(SCREEN *sp GCC_UNUSED){ bool result = FALSE; switch (SP->_mouse_type) { case M_XTERM: /* xterm: never have to query, mouse events are in the keyboard stream */#if USE_EMX_MOUSE { char kbuf[3]; int i, res = read(M_FD(sp), &kbuf, 3); /* Eat the prefix */ if (res != 3) printf("Got %d chars instead of 3 for prefix.\n", res); for (i = 0; i < res; i++) { if (kbuf[i] != key_mouse[i]) printf("Got char %d instead of %d for prefix.\n", (int) kbuf[i], (int) key_mouse[i]); } result = TRUE; }#endif /* USE_EMX_MOUSE */ break;#if USE_GPM_SUPPORT case M_GPM: { /* query server for event, return TRUE if we find one */ Gpm_Event ev; if (my_Gpm_GetEvent(&ev) == 1) { /* there's only one mouse... */ eventp->id = NORMAL_EVENT; eventp->bstate = 0; switch (ev.type & 0x0f) { case (GPM_DOWN): if (ev.buttons & GPM_B_LEFT) eventp->bstate |= BUTTON1_PRESSED; if (ev.buttons & GPM_B_MIDDLE) eventp->bstate |= BUTTON2_PRESSED; if (ev.buttons & GPM_B_RIGHT) eventp->bstate |= BUTTON3_PRESSED; break; case (GPM_UP): if (ev.buttons & GPM_B_LEFT) eventp->bstate |= BUTTON1_RELEASED; if (ev.buttons & GPM_B_MIDDLE) eventp->bstate |= BUTTON2_RELEASED; if (ev.buttons & GPM_B_RIGHT) eventp->bstate |= BUTTON3_RELEASED; break; default: break; } eventp->x = ev.x - 1; eventp->y = ev.y - 1; eventp->z = 0; /* bump the next-free pointer into the circular list */ eventp = NEXT(eventp); result = TRUE; } } break;#endif#if USE_SYSMOUSE case M_SYSMOUSE: if (SP->_sysmouse_head < SP->_sysmouse_tail) { *eventp = SP->_sysmouse_fifo[SP->_sysmouse_head]; /* * Point the fifo-head to the next possible location. If there * are none, reset the indices. This may be interrupted by the * signal handler, doing essentially the same reset. */ SP->_sysmouse_head += 1; if (SP->_sysmouse_head == SP->_sysmouse_tail) { SP->_sysmouse_tail = 0; SP->_sysmouse_head = 0; } /* bump the next-free pointer into the circular list */ eventp = NEXT(eventp); result = TRUE; } break;#endif /* USE_SYSMOUSE */ case M_NONE: break; } return result; /* true if we found an event */}static bool_nc_mouse_inline(SCREEN *sp)/* mouse report received in the keyboard stream -- parse its info */{ int b; bool result = FALSE; TR(MY_TRACE, ("_nc_mouse_inline() called")); if (SP->_mouse_type == M_XTERM) { unsigned char kbuf[4]; mmask_t prev; size_t grabbed; int res; /* This code requires that your xterm entry contain the kmous * capability and that it be set to the \E[M documented in the * Xterm Control Sequences reference. This is how we * arrange for mouse events to be reported via a KEY_MOUSE * return value from wgetch(). After this value is received, * _nc_mouse_inline() gets called and is immediately * responsible for parsing the mouse status information * following the prefix. * * The following quotes from the ctrlseqs.ms document in the * X distribution, describing the X mouse tracking feature: * * Parameters for all mouse tracking escape sequences * generated by xterm encode numeric parameters in a single * character as value+040. For example, ! is 1. * * On button press or release, xterm sends ESC [ M CbCxCy. * The low two bits of Cb encode button information: 0=MB1 * pressed, 1=MB2 pressed, 2=MB3 pressed, 3=release. The * upper bits encode what modifiers were down when the * button was pressed and are added together. 4=Shift, * 8=Meta, 16=Control. Cx and Cy are the x and y coordinates * of the mouse event. The upper left corner is (1,1). * * (End quote) By the time we get here, we've eaten the * key prefix. FYI, the loop below is necessary because * mouse click info isn't guaranteed to present as a * single clist item. * * Wheel mice may return buttons 4 and 5 when the wheel is turned. * We encode those as button presses. */ for (grabbed = 0; grabbed < 3; grabbed += res) { /* For VIO mouse we add extra bit 64 to disambiguate button-up. */#if USE_EMX_MOUSE res = read(M_FD(sp) >= 0 ? M_FD(sp) : sp->_ifd, &kbuf, 3);#else res = read(sp->_ifd, kbuf + grabbed, 3 - grabbed);#endif if (res == -1) break; } kbuf[3] = '\0'; TR(TRACE_IEVENT, ("_nc_mouse_inline sees the following xterm data: '%s'", kbuf)); /* there's only one mouse... */ eventp->id = NORMAL_EVENT; /* processing code goes here */ eventp->bstate = 0; prev = PREV(eventp)->bstate;#if USE_EMX_MOUSE#define PRESS_POSITION(n) \ eventp->bstate = MASK_PRESS(n); \ if (kbuf[0] & 0x40) \ eventp->bstate = MASK_RELEASE(n)#else#define PRESS_POSITION(n) \ eventp->bstate = (prev & MASK_PRESS(n) \ ? REPORT_MOUSE_POSITION \ : MASK_PRESS(n))#endif switch (kbuf[0] & 0x3) { case 0x0: if (kbuf[0] & 64) eventp->bstate = MASK_PRESS(4); else PRESS_POSITION(1); break; case 0x1:#if NCURSES_MOUSE_VERSION == 2 if (kbuf[0] & 64) eventp->bstate = MASK_PRESS(5); else#endif PRESS_POSITION(2); break; case 0x2: PRESS_POSITION(3); break; case 0x3: /* * Release events aren't reported for individual buttons, just for * the button set as a whole. However, because there are normally * no mouse events under xterm that intervene between press and * release, we can infer the button actually released by looking at * the previous event. */ if (prev & (BUTTON_PRESSED | BUTTON_RELEASED)) { eventp->bstate = BUTTON_RELEASED; for (b = 1; b <= MAX_BUTTONS; ++b) { if (!(prev & MASK_PRESS(b))) eventp->bstate &= ~MASK_RELEASE(b); } } else { /* * XFree86 xterm will return a stream of release-events to * let the application know where the mouse is going, if the * private mode 1002 or 1003 is enabled. */ eventp->bstate = REPORT_MOUSE_POSITION; } break; } result = (eventp->bstate & REPORT_MOUSE_POSITION) ? TRUE : FALSE; if (kbuf[0] & 4) { eventp->bstate |= BUTTON_SHIFT; } if (kbuf[0] & 8) { eventp->bstate |= BUTTON_ALT; } if (kbuf[0] & 16) { eventp->bstate |= BUTTON_CTRL; } eventp->x = (kbuf[1] - ' ') - 1; eventp->y = (kbuf[2] - ' ') - 1; TR(MY_TRACE, ("_nc_mouse_inline: primitive mouse-event %s has slot %ld", _tracemouse(eventp), (long) (eventp - events))); /* bump the next-free pointer into the circular list */ eventp = NEXT(eventp);#if 0 /* this return would be needed for QNX's mods to lib_getch.c */ return (TRUE);#endif } return (result);}static voidmouse_activate(bool on){ if (!on && !initialized) return; if (!_nc_mouse_init()) return; if (on) { switch (SP->_mouse_type) { case M_XTERM:#if NCURSES_EXT_FUNCS keyok(KEY_MOUSE, on);#endif TPUTS_TRACE("xterm mouse initialization"); enable_xterm_mouse(1); break;#if USE_GPM_SUPPORT case M_GPM: if (enable_gpm_mouse(1)) { SP->_mouse_fd = *my_gpm_fd; T(("GPM mouse_fd %d", SP->_mouse_fd)); } break;#endif#if USE_SYSMOUSE case M_SYSMOUSE: signal(SIGUSR2, handle_sysmouse); SP->_mouse_active = TRUE; break;#endif case M_NONE: return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -