int sc_mouse_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag) { mouse_info_t *mouse; scr_stat *cur_scp; scr_stat *scp; struct proc *oproc; int f; scp = SC_STAT(tp->t_dev); switch (cmd) { case CONS_MOUSECTL: /* control mouse arrow */ mouse = (mouse_info_t*)data; cur_scp = scp->sc->cur_scp; switch (mouse->operation) { case MOUSE_MODE: if (ISSIGVALID(mouse->u.mode.signal)) { oproc = scp->mouse_proc; scp->mouse_signal = mouse->u.mode.signal; scp->mouse_proc = curproc; scp->mouse_pid = curproc->p_pid; PHOLD(curproc); } else { oproc = scp->mouse_proc; scp->mouse_signal = 0; scp->mouse_proc = NULL; scp->mouse_pid = 0; } if (oproc) { PRELE(oproc); oproc = NULL; } return 0; case MOUSE_SHOW: crit_enter(); if (!(scp->sc->flags & SC_MOUSE_ENABLED)) { scp->sc->flags |= SC_MOUSE_ENABLED; cur_scp->status &= ~MOUSE_HIDDEN; if (!ISGRAPHSC(cur_scp)) mark_all(cur_scp); crit_exit(); return 0; } else { crit_exit(); return EINVAL; } break; case MOUSE_HIDE: crit_enter(); if (scp->sc->flags & SC_MOUSE_ENABLED) { scp->sc->flags &= ~SC_MOUSE_ENABLED; sc_remove_all_mouse(scp->sc); crit_exit(); return 0; } else { crit_exit(); return EINVAL; } break; case MOUSE_MOVEABS: crit_enter(); scp->mouse_xpos = mouse->u.data.x; scp->mouse_ypos = mouse->u.data.y; set_mouse_pos(scp); crit_exit(); break; case MOUSE_MOVEREL: crit_enter(); scp->mouse_xpos += mouse->u.data.x; scp->mouse_ypos += mouse->u.data.y; set_mouse_pos(scp); crit_exit(); break; case MOUSE_GETINFO: mouse->u.data.x = scp->mouse_xpos; mouse->u.data.y = scp->mouse_ypos; mouse->u.data.z = 0; mouse->u.data.buttons = scp->mouse_buttons; return 0; case MOUSE_ACTION: case MOUSE_MOTION_EVENT: /* send out mouse event on /dev/sysmouse */ #if 0 /* this should maybe only be settable from /dev/consolectl SOS */ if (SC_VTY(tp->t_dev) != SC_CONSOLECTL) return ENOTTY; #endif crit_enter(); if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { cur_scp->mouse_xpos += mouse->u.data.x; cur_scp->mouse_ypos += mouse->u.data.y; set_mouse_pos(cur_scp); } f = 0; if (mouse->operation == MOUSE_ACTION) { f = cur_scp->mouse_buttons ^ mouse->u.data.buttons; cur_scp->mouse_buttons = mouse->u.data.buttons; } crit_exit(); if (sysmouse_event(mouse) == 0) return 0; /* * If any buttons are down or the mouse has moved a lot, * stop the screen saver. */ if (((mouse->operation == MOUSE_ACTION) && mouse->u.data.buttons) || (mouse->u.data.x*mouse->u.data.x + mouse->u.data.y*mouse->u.data.y >= SC_WAKEUP_DELTA*SC_WAKEUP_DELTA)) { sc_touch_scrn_saver(); } cur_scp->status &= ~MOUSE_HIDDEN; if (cur_scp->mouse_signal) { /* has controlling process died? */ if (cur_scp->mouse_proc && (cur_scp->mouse_proc != pfindn(cur_scp->mouse_pid))){ oproc = cur_scp->mouse_proc; cur_scp->mouse_signal = 0; cur_scp->mouse_proc = NULL; cur_scp->mouse_pid = 0; if (oproc) PRELE(oproc); } else { ksignal(cur_scp->mouse_proc, cur_scp->mouse_signal); break; } } if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL)) break; #ifndef SC_NO_CUTPASTE if ((mouse->operation == MOUSE_ACTION) && f) { /* process button presses */ if (cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN) mouse_cut_start(cur_scp); else mouse_cut_end(cur_scp); if (cur_scp->mouse_buttons & MOUSE_BUTTON2DOWN || cur_scp->mouse_buttons & MOUSE_BUTTON3DOWN) mouse_paste(cur_scp); } #endif /* SC_NO_CUTPASTE */ break; case MOUSE_BUTTON_EVENT: if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) return EINVAL; if (mouse->u.event.value < 0) return EINVAL; #if 0 /* this should maybe only be settable from /dev/consolectl SOS */ if (SC_VTY(tp->t_dev) != SC_CONSOLECTL) return ENOTTY; #endif if (mouse->u.event.value > 0) cur_scp->mouse_buttons |= mouse->u.event.id; else cur_scp->mouse_buttons &= ~mouse->u.event.id; if (sysmouse_event(mouse) == 0) return 0; /* if a button is held down, stop the screen saver */ if (mouse->u.event.value > 0) sc_touch_scrn_saver(); cur_scp->status &= ~MOUSE_HIDDEN; if (cur_scp->mouse_signal) { if (cur_scp->mouse_proc && (cur_scp->mouse_proc != pfindn(cur_scp->mouse_pid))){ oproc = cur_scp->mouse_proc; cur_scp->mouse_signal = 0; cur_scp->mouse_proc = NULL; cur_scp->mouse_pid = 0; if (oproc) PRELE(oproc); } else { ksignal(cur_scp->mouse_proc, cur_scp->mouse_signal); break; } } if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL)) break; #ifndef SC_NO_CUTPASTE switch (mouse->u.event.id) { case MOUSE_BUTTON1DOWN: switch (mouse->u.event.value % 4) { case 0: /* up */ mouse_cut_end(cur_scp); break; case 1: /* single click: start cut operation */ mouse_cut_start(cur_scp); break; case 2: /* double click: cut a word */ mouse_cut_word(cur_scp); mouse_cut_end(cur_scp); break; case 3: /* triple click: cut a line */ mouse_cut_line(cur_scp); mouse_cut_end(cur_scp); break; } break; case SC_MOUSE_PASTEBUTTON: switch (mouse->u.event.value) { case 0: /* up */ break; default: mouse_paste(cur_scp); break; } break; case SC_MOUSE_EXTENDBUTTON: switch (mouse->u.event.value) { case 0: /* up */ if (!(cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN)) mouse_cut_end(cur_scp); break; default: mouse_cut_extend(cur_scp); break; } break; } #endif /* SC_NO_CUTPASTE */ break; case MOUSE_MOUSECHAR: if (mouse->u.mouse_char < 0) { mouse->u.mouse_char = scp->sc->mouse_char; } else { if (mouse->u.mouse_char >= (unsigned char)-1 - 4) return EINVAL; crit_enter(); sc_remove_all_mouse(scp->sc); #ifndef SC_NO_FONT_LOADING if (ISTEXTSC(cur_scp) && (cur_scp->font != NULL)) sc_load_font(cur_scp, 0, cur_scp->font_size, cur_scp->font, cur_scp->sc->mouse_char, 4); #endif scp->sc->mouse_char = mouse->u.mouse_char; crit_exit(); } break; default: return EINVAL; } return 0; } return ENOIOCTL; }
int sc_mouse_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) { mouse_info_t *mouse; mouse_info_t buf; scr_stat *cur_scp; scr_stat *scp; struct proc *p1; int s; int f; scp = SC_STAT(tp); switch (cmd) { case CONS_MOUSECTL: /* control mouse arrow */ case OLD_CONS_MOUSECTL: mouse = (mouse_info_t*)data; random_harvest_queue(mouse, sizeof(mouse_info_t), 2, RANDOM_MOUSE); if (cmd == OLD_CONS_MOUSECTL) { static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; old_mouse_info_t *old_mouse = (old_mouse_info_t *)data; mouse = &buf; mouse->operation = old_mouse->operation; switch (mouse->operation) { case MOUSE_MODE: mouse->u.mode = old_mouse->u.mode; break; case MOUSE_SHOW: case MOUSE_HIDE: break; case MOUSE_MOVEABS: case MOUSE_MOVEREL: case MOUSE_ACTION: mouse->u.data.x = old_mouse->u.data.x; mouse->u.data.y = old_mouse->u.data.y; mouse->u.data.z = 0; mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7]; break; case MOUSE_GETINFO: old_mouse->u.data.x = scp->mouse_xpos; old_mouse->u.data.y = scp->mouse_ypos; old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7]; return 0; default: return EINVAL; } } cur_scp = scp->sc->cur_scp; switch (mouse->operation) { case MOUSE_MODE: if (ISSIGVALID(mouse->u.mode.signal)) { scp->mouse_signal = mouse->u.mode.signal; scp->mouse_proc = td->td_proc; scp->mouse_pid = td->td_proc->p_pid; } else { scp->mouse_signal = 0; scp->mouse_proc = NULL; scp->mouse_pid = 0; } return 0; case MOUSE_SHOW: s = spltty(); if (!(scp->sc->flags & SC_MOUSE_ENABLED)) { scp->sc->flags |= SC_MOUSE_ENABLED; cur_scp->status &= ~MOUSE_HIDDEN; if (!ISGRAPHSC(cur_scp)) mark_all(cur_scp); } splx(s); return 0; /* NOTREACHED */ case MOUSE_HIDE: s = spltty(); if (scp->sc->flags & SC_MOUSE_ENABLED) { scp->sc->flags &= ~SC_MOUSE_ENABLED; sc_remove_all_mouse(scp->sc); } splx(s); return 0; /* NOTREACHED */ case MOUSE_MOVEABS: s = spltty(); scp->mouse_xpos = mouse->u.data.x; scp->mouse_ypos = mouse->u.data.y; set_mouse_pos(scp); splx(s); break; case MOUSE_MOVEREL: s = spltty(); scp->mouse_xpos += mouse->u.data.x; scp->mouse_ypos += mouse->u.data.y; set_mouse_pos(scp); splx(s); break; case MOUSE_GETINFO: mouse->u.data.x = scp->mouse_xpos; mouse->u.data.y = scp->mouse_ypos; mouse->u.data.z = 0; mouse->u.data.buttons = scp->mouse_buttons; return 0; case MOUSE_ACTION: case MOUSE_MOTION_EVENT: /* send out mouse event on /dev/sysmouse */ #if 0 /* this should maybe only be settable from /dev/consolectl SOS */ if (SC_VTY(tp->t_dev) != SC_CONSOLECTL) return ENOTTY; #endif s = spltty(); if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { cur_scp->mouse_xpos += mouse->u.data.x; cur_scp->mouse_ypos += mouse->u.data.y; set_mouse_pos(cur_scp); } f = 0; if (mouse->operation == MOUSE_ACTION) { f = cur_scp->mouse_buttons ^ mouse->u.data.buttons; cur_scp->mouse_buttons = mouse->u.data.buttons; } splx(s); if (sysmouse_event(mouse) == 0) return 0; /* * If any buttons are down or the mouse has moved a lot, * stop the screen saver. */ if (((mouse->operation == MOUSE_ACTION) && mouse->u.data.buttons) || (mouse->u.data.x*mouse->u.data.x + mouse->u.data.y*mouse->u.data.y >= SC_WAKEUP_DELTA*SC_WAKEUP_DELTA)) { sc_touch_scrn_saver(); } cur_scp->status &= ~MOUSE_HIDDEN; if (cur_scp->mouse_level > 0) { sc_mouse_input(scp, mouse); break; } if (cur_scp->mouse_signal && cur_scp->mouse_proc) { /* has controlling process died? */ if (cur_scp->mouse_proc != (p1 = pfind(cur_scp->mouse_pid))) { cur_scp->mouse_signal = 0; cur_scp->mouse_proc = NULL; cur_scp->mouse_pid = 0; if (p1) PROC_UNLOCK(p1); } else { kern_psignal(cur_scp->mouse_proc, cur_scp->mouse_signal); PROC_UNLOCK(cur_scp->mouse_proc); break; } } #ifndef SC_NO_CUTPASTE if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL)) break; if ((mouse->operation == MOUSE_ACTION) && f) { /* process button presses */ if (cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN) mouse_cut_start(cur_scp); else mouse_cut_end(cur_scp); if (cur_scp->mouse_buttons & MOUSE_BUTTON2DOWN || cur_scp->mouse_buttons & MOUSE_BUTTON3DOWN) sc_mouse_paste(cur_scp); } #endif /* SC_NO_CUTPASTE */ break; case MOUSE_BUTTON_EVENT: if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) return EINVAL; if (mouse->u.event.value < 0) return EINVAL; #if 0 /* this should maybe only be settable from /dev/consolectl SOS */ if (SC_VTY(tp->t_dev) != SC_CONSOLECTL) return ENOTTY; #endif if (mouse->u.event.value > 0) cur_scp->mouse_buttons |= mouse->u.event.id; else cur_scp->mouse_buttons &= ~mouse->u.event.id; if (sysmouse_event(mouse) == 0) return 0; /* if a button is held down, stop the screen saver */ if (mouse->u.event.value > 0) sc_touch_scrn_saver(); cur_scp->status &= ~MOUSE_HIDDEN; if (cur_scp->mouse_level > 0) { sc_mouse_input(scp, mouse); break; } if (cur_scp->mouse_signal && cur_scp->mouse_proc) { if (cur_scp->mouse_proc != (p1 = pfind(cur_scp->mouse_pid))){ cur_scp->mouse_signal = 0; cur_scp->mouse_proc = NULL; cur_scp->mouse_pid = 0; if (p1) PROC_UNLOCK(p1); } else { kern_psignal(cur_scp->mouse_proc, cur_scp->mouse_signal); PROC_UNLOCK(cur_scp->mouse_proc); break; } } #ifndef SC_NO_CUTPASTE if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL)) break; switch (mouse->u.event.id) { case MOUSE_BUTTON1DOWN: switch (mouse->u.event.value % 4) { case 0: /* up */ mouse_cut_end(cur_scp); break; case 1: /* single click: start cut operation */ mouse_cut_start(cur_scp); break; case 2: /* double click: cut a word */ mouse_cut_word(cur_scp); mouse_cut_end(cur_scp); break; case 3: /* triple click: cut a line */ mouse_cut_line(cur_scp); mouse_cut_end(cur_scp); break; } break; case SC_MOUSE_PASTEBUTTON: switch (mouse->u.event.value) { case 0: /* up */ break; default: sc_mouse_paste(cur_scp); break; } break; case SC_MOUSE_EXTENDBUTTON: switch (mouse->u.event.value) { case 0: /* up */ if (!(cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN)) mouse_cut_end(cur_scp); break; default: mouse_cut_extend(cur_scp); break; } break; } #endif /* SC_NO_CUTPASTE */ break; case MOUSE_MOUSECHAR: if (mouse->u.mouse_char < 0) { mouse->u.mouse_char = scp->sc->mouse_char; } else { if (mouse->u.mouse_char > UCHAR_MAX - 3) return EINVAL; s = spltty(); sc_remove_all_mouse(scp->sc); #ifndef SC_NO_FONT_LOADING if (ISTEXTSC(cur_scp) && (cur_scp->font != NULL)) sc_load_font(cur_scp, 0, cur_scp->font_size, cur_scp->font_width, cur_scp->font + cur_scp->font_size * cur_scp->sc->mouse_char, cur_scp->sc->mouse_char, 4); #endif scp->sc->mouse_char = mouse->u.mouse_char; splx(s); } break; default: return EINVAL; } return 0; } return ENOIOCTL; }