The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/misc/syscons/scmouse.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer as
   10  *    the first lines of this file unmodified.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  *
   26  * $FreeBSD: src/sys/dev/syscons/scmouse.c,v 1.12.2.3 2001/07/28 12:51:47 yokota Exp $
   27  */
   28 
   29 #include "opt_syscons.h"
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/kernel.h>
   34 #include <sys/conf.h>
   35 #include <sys/signalvar.h>
   36 #include <sys/proc.h>
   37 #include <sys/tty.h>
   38 #include <sys/thread2.h>
   39 #include <sys/mplock2.h>
   40 
   41 #include <machine/console.h>
   42 #include <sys/mouse.h>
   43 
   44 #include "syscons.h"
   45 
   46 #ifdef SC_TWOBUTTON_MOUSE
   47 #define SC_MOUSE_PASTEBUTTON    MOUSE_BUTTON3DOWN       /* right button */
   48 #define SC_MOUSE_EXTENDBUTTON   MOUSE_BUTTON2DOWN       /* not really used */
   49 #else
   50 #define SC_MOUSE_PASTEBUTTON    MOUSE_BUTTON2DOWN       /* middle button */
   51 #define SC_MOUSE_EXTENDBUTTON   MOUSE_BUTTON3DOWN       /* right button */
   52 #endif /* SC_TWOBUTTON_MOUSE */
   53 
   54 #define SC_WAKEUP_DELTA         20
   55 
   56 #ifndef SC_NO_SYSMOUSE
   57 
   58 static int              cut_buffer_size;
   59 static u_char           *cut_buffer;
   60 
   61 /* local functions */
   62 static void sc_mouse_init(void *);
   63 static void sc_mouse_uninit(void *);
   64 
   65 static void set_mouse_pos(scr_stat *scp);
   66 #ifndef SC_NO_CUTPASTE
   67 static int skip_spc_right(scr_stat *scp, int p);
   68 static int skip_spc_left(scr_stat *scp, int p);
   69 static void mouse_cut(scr_stat *scp);
   70 static void mouse_cut_start(scr_stat *scp);
   71 static void mouse_cut_end(scr_stat *scp);
   72 static void mouse_cut_word(scr_stat *scp);
   73 static void mouse_cut_line(scr_stat *scp);
   74 static void mouse_cut_extend(scr_stat *scp);
   75 static void mouse_paste(scr_stat *scp);
   76 #endif /* SC_NO_CUTPASTE */
   77 
   78 #ifndef SC_NO_CUTPASTE
   79 /* allocate a cut buffer */
   80 void
   81 sc_alloc_cut_buffer(scr_stat *scp, int wait)
   82 {
   83     u_char *p;
   84 
   85     if ((cut_buffer == NULL)
   86         || (cut_buffer_size < scp->xsize * scp->ysize + 1)) {
   87         p = cut_buffer;
   88         cut_buffer = NULL;
   89         if (p != NULL)
   90             kfree(p, M_SYSCONS);
   91         cut_buffer_size = scp->xsize * scp->ysize + 1;
   92         p = kmalloc(cut_buffer_size, M_SYSCONS, (wait) ? M_WAITOK : M_NOWAIT);
   93         if (p != NULL)
   94             p[0] = '\0';
   95         cut_buffer = p;
   96     }
   97 }
   98 #endif /* SC_NO_CUTPASTE */
   99 
  100 /* move mouse */
  101 void
  102 sc_mouse_move(scr_stat *scp, int x, int y)
  103 {
  104     crit_enter();
  105     scp->mouse_xpos = scp->mouse_oldxpos = x;
  106     scp->mouse_ypos = scp->mouse_oldypos = y;
  107     if (scp->font_size <= 0)
  108         scp->mouse_pos = scp->mouse_oldpos = 0;
  109     else
  110         scp->mouse_pos = scp->mouse_oldpos = 
  111             (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
  112     scp->status |= MOUSE_MOVED;
  113     crit_exit();
  114 }
  115 
  116 /* adjust mouse position */
  117 static void
  118 set_mouse_pos(scr_stat *scp)
  119 {
  120     if (scp->mouse_xpos < scp->xoff*8)
  121         scp->mouse_xpos = scp->xoff*8;
  122     if (scp->mouse_ypos < scp->yoff*scp->font_size)
  123         scp->mouse_ypos = scp->yoff*scp->font_size;
  124     if (ISGRAPHSC(scp)) {
  125         if (scp->mouse_xpos > scp->xpixel-1)
  126             scp->mouse_xpos = scp->xpixel-1;
  127         if (scp->mouse_ypos > scp->ypixel-1)
  128             scp->mouse_ypos = scp->ypixel-1;
  129         return;
  130     } else {
  131         if (scp->mouse_xpos > (scp->xsize + scp->xoff)*8 - 1)
  132             scp->mouse_xpos = (scp->xsize + scp->xoff)*8 - 1;
  133         if (scp->mouse_ypos > (scp->ysize + scp->yoff)*scp->font_size - 1)
  134             scp->mouse_ypos = (scp->ysize + scp->yoff)*scp->font_size - 1;
  135     }
  136 
  137     if (scp->mouse_xpos != scp->mouse_oldxpos || scp->mouse_ypos != scp->mouse_oldypos) {
  138         scp->status |= MOUSE_MOVED;
  139         scp->mouse_pos =
  140             (scp->mouse_ypos/scp->font_size - scp->yoff)*scp->xsize 
  141                 + scp->mouse_xpos/8 - scp->xoff;
  142 #ifndef SC_NO_CUTPASTE
  143         if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING))
  144             mouse_cut(scp);
  145 #endif
  146     }
  147 }
  148 
  149 #ifndef SC_NO_CUTPASTE
  150 
  151 void
  152 sc_draw_mouse_image(scr_stat *scp)
  153 {
  154     if (ISGRAPHSC(scp))
  155         return;
  156 
  157     ++scp->sc->videoio_in_progress;
  158     (*scp->rndr->draw_mouse)(scp, scp->mouse_xpos, scp->mouse_ypos, TRUE);
  159     scp->mouse_oldpos = scp->mouse_pos;
  160     scp->mouse_oldxpos = scp->mouse_xpos;
  161     scp->mouse_oldypos = scp->mouse_ypos;
  162     scp->status |= MOUSE_VISIBLE;
  163     --scp->sc->videoio_in_progress;
  164 }
  165 
  166 void
  167 sc_remove_mouse_image(scr_stat *scp)
  168 {
  169     int size;
  170     int i;
  171 
  172     if (ISGRAPHSC(scp))
  173         return;
  174 
  175     ++scp->sc->videoio_in_progress;
  176     (*scp->rndr->draw_mouse)(scp,
  177                              (scp->mouse_oldpos%scp->xsize + scp->xoff)*8,
  178                              (scp->mouse_oldpos/scp->xsize + scp->yoff)
  179                                  * scp->font_size,
  180                              FALSE);
  181     size = scp->xsize*scp->ysize;
  182     i = scp->mouse_oldpos;
  183     mark_for_update(scp, i);
  184     mark_for_update(scp, i);
  185     if (i + scp->xsize + 1 < size) {
  186         mark_for_update(scp, i + scp->xsize + 1);
  187     } else if (i + scp->xsize < size) {
  188         mark_for_update(scp, i + scp->xsize);
  189     } else if (i + 1 < size) {
  190         mark_for_update(scp, i + 1);
  191     }
  192     scp->status &= ~MOUSE_VISIBLE;
  193     --scp->sc->videoio_in_progress;
  194 }
  195 
  196 int
  197 sc_inside_cutmark(scr_stat *scp, int pos)
  198 {
  199     int start;
  200     int end;
  201 
  202     if (scp->mouse_cut_end < 0)
  203         return FALSE;
  204     if (scp->mouse_cut_start <= scp->mouse_cut_end) {
  205         start = scp->mouse_cut_start;
  206         end = scp->mouse_cut_end;
  207     } else {
  208         start = scp->mouse_cut_end;
  209         end = scp->mouse_cut_start - 1;
  210     }
  211     return ((start <= pos) && (pos <= end));
  212 }
  213 
  214 void
  215 sc_remove_cutmarking(scr_stat *scp)
  216 {
  217     crit_enter();
  218     if (scp->mouse_cut_end >= 0) {
  219         mark_for_update(scp, scp->mouse_cut_start);
  220         mark_for_update(scp, scp->mouse_cut_end);
  221     }
  222     scp->mouse_cut_start = scp->xsize*scp->ysize;
  223     scp->mouse_cut_end = -1;
  224     crit_exit();
  225     scp->status &= ~MOUSE_CUTTING;
  226 }
  227 
  228 void
  229 sc_remove_all_cutmarkings(sc_softc_t *sc)
  230 {
  231     scr_stat *scp;
  232     int i;
  233 
  234     /* delete cut markings in all vtys */
  235     for (i = 0; i < sc->vtys; ++i) {
  236         scp = SC_STAT(sc->dev[i]);
  237         if (scp == NULL)
  238             continue;
  239         sc_remove_cutmarking(scp);
  240     }
  241 }
  242 
  243 void
  244 sc_remove_all_mouse(sc_softc_t *sc)
  245 {
  246     scr_stat *scp;
  247     int i;
  248 
  249     for (i = 0; i < sc->vtys; ++i) {
  250         scp = SC_STAT(sc->dev[i]);
  251         if (scp == NULL)
  252             continue;
  253         if (scp->status & MOUSE_VISIBLE) {
  254             scp->status &= ~MOUSE_VISIBLE;
  255             mark_all(scp);
  256         }
  257     }
  258 }
  259 
  260 #define IS_SPACE_CHAR(c)        (((c) & 0xff) == ' ')
  261 
  262 /* skip spaces to right */
  263 static int
  264 skip_spc_right(scr_stat *scp, int p)
  265 {
  266     int c;
  267     int i;
  268 
  269     for (i = p % scp->xsize; i < scp->xsize; ++i) {
  270         c = sc_vtb_getc(&scp->vtb, p);
  271         if (!IS_SPACE_CHAR(c))
  272             break;
  273         ++p;
  274     }
  275     return i;
  276 }
  277 
  278 /* skip spaces to left */
  279 static int
  280 skip_spc_left(scr_stat *scp, int p)
  281 {
  282     int c;
  283     int i;
  284 
  285     for (i = p-- % scp->xsize - 1; i >= 0; --i) {
  286         c = sc_vtb_getc(&scp->vtb, p);
  287         if (!IS_SPACE_CHAR(c))
  288             break;
  289         --p;
  290     }
  291     return i;
  292 }
  293 
  294 /* copy marked region to the cut buffer */
  295 static void
  296 mouse_cut(scr_stat *scp)
  297 {
  298     int start;
  299     int end;
  300     int from;
  301     int to;
  302     int blank;
  303     int c;
  304     int p;
  305     int i;
  306 
  307     start = scp->mouse_cut_start;
  308     if (scp->mouse_pos >= start) {
  309         from = start;
  310         to = end = scp->mouse_pos;
  311     } else {
  312         from = end = scp->mouse_pos;
  313         to = start - 1;
  314     }
  315     for (p = from, i = blank = 0; p <= to; ++p) {
  316         cut_buffer[i] = sc_vtb_getc(&scp->vtb, p);
  317         /* remember the position of the last non-space char */
  318         if (!IS_SPACE_CHAR(cut_buffer[i++]))
  319             blank = i;          /* the first space after the last non-space */
  320         /* trim trailing blank when crossing lines */
  321         if ((p % scp->xsize) == (scp->xsize - 1)) {
  322             cut_buffer[blank] = '\r';
  323             i = blank + 1;
  324         }
  325     }
  326     cut_buffer[i] = '\0';
  327 
  328     /* scan towards the end of the last line */
  329     --p;
  330     for (i = p % scp->xsize; i < scp->xsize; ++i) {
  331         c = sc_vtb_getc(&scp->vtb, p);
  332         if (!IS_SPACE_CHAR(c))
  333             break;
  334         ++p;
  335     }
  336     /* if there is nothing but blank chars, trim them, but mark towards eol */
  337     if (i >= scp->xsize) {
  338         if (end >= start)
  339             to = end = p - 1;
  340         else
  341             to = start = p;
  342         cut_buffer[blank++] = '\r';
  343         cut_buffer[blank] = '\0';
  344     }
  345 
  346     /* remove the current marking */
  347     crit_enter();
  348     if (scp->mouse_cut_start <= scp->mouse_cut_end) {
  349         mark_for_update(scp, scp->mouse_cut_start);
  350         mark_for_update(scp, scp->mouse_cut_end);
  351     } else if (scp->mouse_cut_end >= 0) {
  352         mark_for_update(scp, scp->mouse_cut_end);
  353         mark_for_update(scp, scp->mouse_cut_start);
  354     }
  355 
  356     /* mark the new region */
  357     scp->mouse_cut_start = start;
  358     scp->mouse_cut_end = end;
  359     mark_for_update(scp, from);
  360     mark_for_update(scp, to);
  361     crit_exit();
  362 }
  363 
  364 /* a mouse button is pressed, start cut operation */
  365 static void
  366 mouse_cut_start(scr_stat *scp) 
  367 {
  368     int i;
  369     int j;
  370 
  371     if (scp->status & MOUSE_VISIBLE) {
  372         i = scp->mouse_cut_start;
  373         j = scp->mouse_cut_end;
  374         sc_remove_all_cutmarkings(scp->sc);
  375         if (scp->mouse_pos == i && i == j) {
  376             cut_buffer[0] = '\0';
  377         } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) {
  378             /* if the pointer is on trailing blank chars, mark towards eol */
  379             i = skip_spc_left(scp, scp->mouse_pos) + 1;
  380             crit_enter();
  381             scp->mouse_cut_start =
  382                 (scp->mouse_pos / scp->xsize) * scp->xsize + i;
  383             scp->mouse_cut_end =
  384                 (scp->mouse_pos / scp->xsize + 1) * scp->xsize - 1;
  385             crit_exit();
  386             cut_buffer[0] = '\r';
  387             cut_buffer[1] = '\0';
  388             scp->status |= MOUSE_CUTTING;
  389         } else {
  390             crit_enter();
  391             scp->mouse_cut_start = scp->mouse_pos;
  392             scp->mouse_cut_end = scp->mouse_cut_start;
  393             crit_exit();
  394             cut_buffer[0] = sc_vtb_getc(&scp->vtb, scp->mouse_cut_start);
  395             cut_buffer[1] = '\0';
  396             scp->status |= MOUSE_CUTTING;
  397         }
  398         mark_all(scp);  /* this is probably overkill XXX */
  399     }
  400 }
  401 
  402 /* end of cut operation */
  403 static void
  404 mouse_cut_end(scr_stat *scp) 
  405 {
  406     if (scp->status & MOUSE_VISIBLE)
  407         scp->status &= ~MOUSE_CUTTING;
  408 }
  409 
  410 /* copy a word under the mouse pointer */
  411 static void
  412 mouse_cut_word(scr_stat *scp)
  413 {
  414     int start;
  415     int end;
  416     int sol;
  417     int eol;
  418     int c;
  419     int i;
  420     int j;
  421 
  422     /*
  423      * Because we don't have locale information in the kernel,
  424      * we only distinguish space char and non-space chars.  Punctuation
  425      * chars, symbols and other regular chars are all treated alike.
  426      */
  427     if (scp->status & MOUSE_VISIBLE) {
  428         /* remove the current cut mark */
  429         crit_enter();
  430         if (scp->mouse_cut_start <= scp->mouse_cut_end) {
  431             mark_for_update(scp, scp->mouse_cut_start);
  432             mark_for_update(scp, scp->mouse_cut_end);
  433         } else if (scp->mouse_cut_end >= 0) {
  434             mark_for_update(scp, scp->mouse_cut_end);
  435             mark_for_update(scp, scp->mouse_cut_start);
  436         }
  437         scp->mouse_cut_start = scp->xsize*scp->ysize;
  438         scp->mouse_cut_end = -1;
  439         crit_exit();
  440 
  441         sol = (scp->mouse_pos / scp->xsize) * scp->xsize;
  442         eol = sol + scp->xsize;
  443         c = sc_vtb_getc(&scp->vtb, scp->mouse_pos);
  444         if (IS_SPACE_CHAR(c)) {
  445             /* blank space */
  446             for (j = scp->mouse_pos; j >= sol; --j) {
  447                 c = sc_vtb_getc(&scp->vtb, j);
  448                 if (!IS_SPACE_CHAR(c))
  449                     break;
  450             }
  451             start = ++j;
  452             for (j = scp->mouse_pos; j < eol; ++j) {
  453                 c = sc_vtb_getc(&scp->vtb, j);
  454                 if (!IS_SPACE_CHAR(c))
  455                     break;
  456             }
  457             end = j - 1;
  458         } else {
  459             /* non-space word */
  460             for (j = scp->mouse_pos; j >= sol; --j) {
  461                 c = sc_vtb_getc(&scp->vtb, j);
  462                 if (IS_SPACE_CHAR(c))
  463                     break;
  464             }
  465             start = ++j;
  466             for (j = scp->mouse_pos; j < eol; ++j) {
  467                 c = sc_vtb_getc(&scp->vtb, j);
  468                 if (IS_SPACE_CHAR(c))
  469                     break;
  470             }
  471             end = j - 1;
  472         }
  473 
  474         /* copy the found word */
  475         for (i = 0, j = start; j <= end; ++j)
  476             cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j);
  477         cut_buffer[i] = '\0';
  478         scp->status |= MOUSE_CUTTING;
  479 
  480         /* mark the region */
  481         crit_enter();
  482         scp->mouse_cut_start = start;
  483         scp->mouse_cut_end = end;
  484         mark_for_update(scp, start);
  485         mark_for_update(scp, end);
  486         crit_exit();
  487     }
  488 }
  489 
  490 /* copy a line under the mouse pointer */
  491 static void
  492 mouse_cut_line(scr_stat *scp)
  493 {
  494     int i;
  495     int j;
  496 
  497     if (scp->status & MOUSE_VISIBLE) {
  498         /* remove the current cut mark */
  499         crit_enter();
  500         if (scp->mouse_cut_start <= scp->mouse_cut_end) {
  501             mark_for_update(scp, scp->mouse_cut_start);
  502             mark_for_update(scp, scp->mouse_cut_end);
  503         } else if (scp->mouse_cut_end >= 0) {
  504             mark_for_update(scp, scp->mouse_cut_end);
  505             mark_for_update(scp, scp->mouse_cut_start);
  506         }
  507 
  508         /* mark the entire line */
  509         scp->mouse_cut_start =
  510             (scp->mouse_pos / scp->xsize) * scp->xsize;
  511         scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize - 1;
  512         mark_for_update(scp, scp->mouse_cut_start);
  513         mark_for_update(scp, scp->mouse_cut_end);
  514         crit_exit();
  515 
  516         /* copy the line into the cut buffer */
  517         for (i = 0, j = scp->mouse_cut_start; j <= scp->mouse_cut_end; ++j)
  518             cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j);
  519         cut_buffer[i++] = '\r';
  520         cut_buffer[i] = '\0';
  521         scp->status |= MOUSE_CUTTING;
  522     }
  523 }
  524 
  525 /* extend the marked region to the mouse pointer position */
  526 static void
  527 mouse_cut_extend(scr_stat *scp) 
  528 {
  529     int start;
  530     int end;
  531 
  532     if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING)
  533         && (scp->mouse_cut_end >= 0)) {
  534         if (scp->mouse_cut_start <= scp->mouse_cut_end) {
  535             start = scp->mouse_cut_start;
  536             end = scp->mouse_cut_end;
  537         } else {
  538             start = scp->mouse_cut_end;
  539             end = scp->mouse_cut_start - 1;
  540         }
  541         crit_enter();
  542         if (scp->mouse_pos > end) {
  543             scp->mouse_cut_start = start;
  544             scp->mouse_cut_end = end;
  545         } else if (scp->mouse_pos < start) {
  546             scp->mouse_cut_start = end + 1;
  547             scp->mouse_cut_end = start;
  548         } else {
  549             if (scp->mouse_pos - start > end + 1 - scp->mouse_pos) {
  550                 scp->mouse_cut_start = start;
  551                 scp->mouse_cut_end = end;
  552             } else {
  553                 scp->mouse_cut_start = end + 1;
  554                 scp->mouse_cut_end = start;
  555             }
  556         }
  557         crit_exit();
  558         mouse_cut(scp);
  559         scp->status |= MOUSE_CUTTING;
  560     }
  561 }
  562 
  563 /* paste cut buffer contents into the current vty */
  564 static void
  565 mouse_paste(scr_stat *scp) 
  566 {
  567     if (scp->status & MOUSE_VISIBLE)
  568         sc_paste(scp, cut_buffer, strlen(cut_buffer));
  569 }
  570 
  571 #endif /* SC_NO_CUTPASTE */
  572 
  573 static void
  574 sc_mouse_exit1_proc(struct proc *p)
  575 {
  576     scr_stat *scp;
  577 
  578     scp = p->p_drv_priv;
  579     KKASSERT(scp != NULL);
  580 
  581     get_mplock();
  582     KKASSERT(scp->mouse_proc == p);
  583     KKASSERT(scp->mouse_pid == p->p_pid);
  584 
  585     scp->mouse_signal = 0;
  586     scp->mouse_proc = NULL;
  587     scp->mouse_pid = 0;
  588     rel_mplock();
  589 
  590     PRELE(p);
  591     p->p_flags &= ~P_SCMOUSE;
  592     p->p_drv_priv = NULL;
  593 }
  594 
  595 /*
  596  * sc_mouse_exit1:
  597  *
  598  *      Handle exit1 for processes registered as MOUSE_MODE handlers.
  599  *      We must remove a process hold, established when MOUSE_MODE
  600  *      was enabled.
  601  */
  602 static void
  603 sc_mouse_exit1(struct thread *td)
  604 {
  605     struct proc *p;
  606 
  607     p = td->td_proc;
  608     KKASSERT(p != NULL);
  609 
  610     if ((p->p_flags & P_SCMOUSE) == 0)
  611         return;
  612 
  613 
  614     sc_mouse_exit1_proc(p);
  615 }
  616 
  617 int
  618 sc_mouse_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag)
  619 {
  620     mouse_info_t *mouse;
  621     scr_stat *cur_scp;
  622     scr_stat *scp;
  623     int f;
  624 
  625     scp = SC_STAT(tp->t_dev);
  626 
  627     switch (cmd) {
  628 
  629     case CONS_MOUSECTL:         /* control mouse arrow */
  630         mouse = (mouse_info_t*) data;
  631         cur_scp = scp->sc->cur_scp;
  632 
  633         switch (mouse->operation) {
  634         /*
  635          * Setup a process to receive signals on mouse events.
  636          */
  637         case MOUSE_MODE:
  638             get_mplock();
  639 
  640             if (!ISSIGVALID(mouse->u.mode.signal)) {
  641                 /* Setting MOUSE_MODE w/ an invalid signal is used to disarm */
  642                 if (scp->mouse_proc == curproc) {
  643                     sc_mouse_exit1_proc(curproc);
  644                     rel_mplock();
  645                     return 0;
  646                 } else {
  647                     rel_mplock();
  648                     return EINVAL;
  649                 }
  650             } else {
  651                 /* Only one mouse process per syscons */
  652                 if (scp->mouse_proc) {
  653                     rel_mplock();
  654                     return EINVAL;
  655                 }
  656 
  657                 /* Only one syscons signal source per process */
  658                 if (curproc->p_flags & P_SCMOUSE) {
  659                     rel_mplock();
  660                     return EINVAL;
  661                 }
  662 
  663                 /*
  664                  * Process is stabilized by a hold, which is removed from
  665                  * sc_mouse_exit1. scp's mouse_{signal,proc,pid} fields
  666                  * are synchronized by the MP Lock.
  667                  */
  668                 scp->mouse_signal = mouse->u.mode.signal;
  669                 scp->mouse_proc = curproc;
  670                 scp->mouse_pid = curproc->p_pid;
  671                 curproc->p_flags |= P_SCMOUSE;
  672                 KKASSERT(curproc->p_drv_priv == NULL);
  673                 curproc->p_drv_priv = scp;
  674                 PHOLD(curproc);
  675 
  676                 rel_mplock();
  677                 return 0;
  678             }
  679             /*NOTREACHED*/
  680             break;
  681 
  682         case MOUSE_SHOW:
  683             crit_enter();
  684             if (!(scp->sc->flags & SC_MOUSE_ENABLED)) {
  685                 scp->sc->flags |= SC_MOUSE_ENABLED;
  686                 cur_scp->status &= ~MOUSE_HIDDEN;
  687                 if (!ISGRAPHSC(cur_scp))
  688                     mark_all(cur_scp);
  689                 crit_exit();
  690                 return 0;
  691             } else {
  692                 crit_exit();
  693                 return EINVAL;
  694             }
  695             break;
  696 
  697         case MOUSE_HIDE:
  698             crit_enter();
  699             if (scp->sc->flags & SC_MOUSE_ENABLED) {
  700                 scp->sc->flags &= ~SC_MOUSE_ENABLED;
  701                 sc_remove_all_mouse(scp->sc);
  702                 crit_exit();
  703                 return 0;
  704             } else {
  705                 crit_exit();
  706                 return EINVAL;
  707             }
  708             break;
  709 
  710         case MOUSE_MOVEABS:
  711             crit_enter();
  712             scp->mouse_xpos = mouse->u.data.x;
  713             scp->mouse_ypos = mouse->u.data.y;
  714             set_mouse_pos(scp);
  715             crit_exit();
  716             break;
  717 
  718         case MOUSE_MOVEREL:
  719             crit_enter();
  720             scp->mouse_xpos += mouse->u.data.x;
  721             scp->mouse_ypos += mouse->u.data.y;
  722             set_mouse_pos(scp);
  723             crit_exit();
  724             break;
  725 
  726         case MOUSE_GETINFO:
  727             mouse->u.data.x = scp->mouse_xpos;
  728             mouse->u.data.y = scp->mouse_ypos;
  729             mouse->u.data.z = 0;
  730             mouse->u.data.buttons = scp->mouse_buttons;
  731             return 0;
  732 
  733         case MOUSE_ACTION:
  734         case MOUSE_MOTION_EVENT:
  735             /* send out mouse event on /dev/sysmouse */
  736 #if 0
  737             /* this should maybe only be settable from /dev/consolectl SOS */
  738             if (SC_VTY(tp->t_dev) != SC_CONSOLECTL)
  739                 return ENOTTY;
  740 #endif
  741             crit_enter();
  742             if (mouse->u.data.x != 0 || mouse->u.data.y != 0) {
  743                 cur_scp->mouse_xpos += mouse->u.data.x;
  744                 cur_scp->mouse_ypos += mouse->u.data.y;
  745                 set_mouse_pos(cur_scp);
  746             }
  747             f = 0;
  748             if (mouse->operation == MOUSE_ACTION) {
  749                 f = cur_scp->mouse_buttons ^ mouse->u.data.buttons;
  750                 cur_scp->mouse_buttons = mouse->u.data.buttons;
  751             }
  752             crit_exit();
  753 
  754             if (sysmouse_event(mouse) == 0)
  755                 return 0;
  756 
  757             /* 
  758              * If any buttons are down or the mouse has moved a lot, 
  759              * stop the screen saver.
  760              */
  761             if (((mouse->operation == MOUSE_ACTION) && mouse->u.data.buttons)
  762                 || (mouse->u.data.x*mouse->u.data.x
  763                         + mouse->u.data.y*mouse->u.data.y
  764                         >= SC_WAKEUP_DELTA*SC_WAKEUP_DELTA)) {
  765                 sc_touch_scrn_saver();
  766             }
  767 
  768             cur_scp->status &= ~MOUSE_HIDDEN;
  769 
  770             get_mplock();
  771             if (cur_scp->mouse_signal) {
  772                 KKASSERT(cur_scp->mouse_proc != NULL);
  773                 ksignal(cur_scp->mouse_proc, cur_scp->mouse_signal);
  774                 rel_mplock();
  775                 break;
  776             }
  777             rel_mplock();
  778 
  779             if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL))
  780                 break;
  781 
  782 #ifndef SC_NO_CUTPASTE
  783             if ((mouse->operation == MOUSE_ACTION) && f) {
  784                 /* process button presses */
  785                 if (cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN)
  786                     mouse_cut_start(cur_scp);
  787                 else
  788                     mouse_cut_end(cur_scp);
  789                 if (cur_scp->mouse_buttons & MOUSE_BUTTON2DOWN ||
  790                     cur_scp->mouse_buttons & MOUSE_BUTTON3DOWN)
  791                     mouse_paste(cur_scp);
  792             }
  793 #endif /* SC_NO_CUTPASTE */
  794             break;
  795 
  796         case MOUSE_BUTTON_EVENT:
  797             if ((mouse->u.event.id & MOUSE_BUTTONS) == 0)
  798                 return EINVAL;
  799             if (mouse->u.event.value < 0)
  800                 return EINVAL;
  801 #if 0
  802             /* this should maybe only be settable from /dev/consolectl SOS */
  803             if (SC_VTY(tp->t_dev) != SC_CONSOLECTL)
  804                 return ENOTTY;
  805 #endif
  806             if (mouse->u.event.value > 0)
  807                 cur_scp->mouse_buttons |= mouse->u.event.id;
  808             else
  809                 cur_scp->mouse_buttons &= ~mouse->u.event.id;
  810 
  811             if (sysmouse_event(mouse) == 0)
  812                 return 0;
  813 
  814             /* if a button is held down, stop the screen saver */
  815             if (mouse->u.event.value > 0)
  816                 sc_touch_scrn_saver();
  817 
  818             cur_scp->status &= ~MOUSE_HIDDEN;
  819 
  820             get_mplock();
  821             if (cur_scp->mouse_signal) {
  822                 KKASSERT(cur_scp->mouse_proc != NULL);
  823                 ksignal(cur_scp->mouse_proc, cur_scp->mouse_signal);
  824                 rel_mplock();
  825                 break;
  826             }
  827             rel_mplock();
  828 
  829             if (ISGRAPHSC(cur_scp) || (cut_buffer == NULL))
  830                 break;
  831 
  832 #ifndef SC_NO_CUTPASTE
  833             switch (mouse->u.event.id) {
  834             case MOUSE_BUTTON1DOWN:
  835                 switch (mouse->u.event.value % 4) {
  836                 case 0: /* up */
  837                     mouse_cut_end(cur_scp);
  838                     break;
  839                 case 1: /* single click: start cut operation */
  840                     mouse_cut_start(cur_scp);
  841                     break;
  842                 case 2: /* double click: cut a word */
  843                     mouse_cut_word(cur_scp);
  844                     mouse_cut_end(cur_scp);
  845                     break;
  846                 case 3: /* triple click: cut a line */
  847                     mouse_cut_line(cur_scp);
  848                     mouse_cut_end(cur_scp);
  849                     break;
  850                 }
  851                 break;
  852             case SC_MOUSE_PASTEBUTTON:
  853                 switch (mouse->u.event.value) {
  854                 case 0: /* up */
  855                     break;
  856                 default:
  857                     mouse_paste(cur_scp);
  858                     break;
  859                 }
  860                 break;
  861             case SC_MOUSE_EXTENDBUTTON:
  862                 switch (mouse->u.event.value) {
  863                 case 0: /* up */
  864                     if (!(cur_scp->mouse_buttons & MOUSE_BUTTON1DOWN))
  865                         mouse_cut_end(cur_scp);
  866                     break;
  867                 default:
  868                     mouse_cut_extend(cur_scp);
  869                     break;
  870                 }
  871                 break;
  872             }
  873 #endif /* SC_NO_CUTPASTE */
  874             break;
  875 
  876         case MOUSE_MOUSECHAR:
  877             if (mouse->u.mouse_char < 0) {
  878                 mouse->u.mouse_char = scp->sc->mouse_char;
  879             } else {
  880                 if (mouse->u.mouse_char >= (unsigned char)-1 - 4)
  881                     return EINVAL;
  882                 crit_enter();
  883                 sc_remove_all_mouse(scp->sc);
  884 #ifndef SC_NO_FONT_LOADING
  885                 if (ISTEXTSC(cur_scp) && (cur_scp->font != NULL))
  886                     sc_load_font(cur_scp, 0, cur_scp->font_size, cur_scp->font,
  887                                  cur_scp->sc->mouse_char, 4);
  888 #endif
  889                 scp->sc->mouse_char = mouse->u.mouse_char;
  890                 crit_exit();
  891             }
  892             break;
  893 
  894         default:
  895             return EINVAL;
  896         }
  897 
  898         return 0;
  899     }
  900 
  901     return ENOIOCTL;
  902 }
  903 
  904 void
  905 sc_mouse_init(void *unused)
  906 {
  907     at_exit(sc_mouse_exit1);
  908 }
  909 
  910 void
  911 sc_mouse_uninit(void *unused)
  912 {
  913 }
  914 
  915 SYSINIT(sc_mouse_init, SI_SUB_DRIVERS, SI_ORDER_ANY, sc_mouse_init, NULL);
  916 SYSUNINIT(sc_mouse_uninit, SI_SUB_DRIVERS, SI_ORDER_ANY, sc_mouse_uninit, NULL);
  917 
  918 #endif /* SC_NO_SYSMOUSE */

Cache object: a6cbd126e73d5c30cd9299ad4a727a51


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.