diff --git a/src/conio/Common.gmake b/src/conio/Common.gmake index f4b3a303e228b7835106b79c993293aeb91ef08e..373053b4a8d37dd04556948b776b0e9076662832 100644 --- a/src/conio/Common.gmake +++ b/src/conio/Common.gmake @@ -23,6 +23,8 @@ CIOLIB_LDFLAGS += ${PTHREAD_LDFLAGS} CIOLIB_CFLAGS += $(PTHREAD_CFLAGS) CIOLIB_OBJS += $(LIBODIR)/ansi_cio.o $(LIBODIR)/threadwrap.o CIOLIB_OBJS += $(LIBODIR)/curs_cio.o $(LIBODIR)/ciolib.o +CIOLIB_OBJS += $(LIBODIR)/mouse.o $(LIBODIR)/semwrap.o +CIOLIB_OBJS += $(LIBODIR)/genwrap.o $(PTHREAD_OBJS) CIOLIB_CFLAGS += -I$(UIFC_SRC) # Curses Stuff diff --git a/src/conio/ciolib.c b/src/conio/ciolib.c index 02e6facebe1faecc4e6b463bab796c7d5e3ae691..9407887b899874be852b796631079423ef5f5236 100644 --- a/src/conio/ciolib.c +++ b/src/conio/ciolib.c @@ -68,7 +68,7 @@ int try_x_init(int mode) { if(!console_init()) { cio_api.mode=CIOLIB_MODE_X; - cio_api.mouse=0; + cio_api.mouse=1; cio_api.puttext=x_puttext; cio_api.gettext=x_gettext; cio_api.textattr=x_textattr; @@ -83,7 +83,6 @@ int try_x_init(int mode) cio_api.getch=x_getch; cio_api.getche=x_getche; cio_api.textmode=x_textmode; - cio_api.getmouse=NULL; cio_api.showmouse=NULL; cio_api.hidemouse=NULL; cio_api.settitle=x_settitle; @@ -112,7 +111,6 @@ int try_curses_init(int mode) cio_api.getch=curs_getch; cio_api.getche=curs_getche; cio_api.textmode=curs_textmode; - cio_api.getmouse=curs_getmouse; cio_api.showmouse=curs_showmouse; cio_api.hidemouse=curs_hidemouse; cio_api.settitle=NULL; @@ -142,7 +140,6 @@ int try_ansi_init(int mode) cio_api.getch=ansi_getch; cio_api.getche=ansi_getche; cio_api.textmode=ansi_textmode; - cio_api.getmouse=NULL; cio_api.showmouse=NULL; cio_api.hidemouse=NULL; cio_api.settitle=NULL; @@ -175,7 +172,6 @@ int try_conio_init(int mode) cio_api.getch=win32_getch; cio_api.getche=win32_getche; cio_api.textmode=win32_textmode; - cio_api.getmouse=win32_getmouse; cio_api.showmouse=win32_showmouse; cio_api.hidemouse=win32_hidemouse; cio_api.settitle=win32_settitle; @@ -232,6 +228,7 @@ int initciolib(int mode) cio_textinfo.winright=cio_textinfo.screenwidth; cio_textinfo.winbottom=cio_textinfo.screenheight; cio_textinfo.normattr=7; + _beginthread(ciolib_mouse_thread,0,NULL); return(0); } @@ -240,6 +237,8 @@ int ciolib_kbhit(void) CIOLIB_INIT(); if(ungotch) return(1); + if(mouse_pending()) + return(1); return(cio_api.kbhit()); } @@ -754,14 +753,6 @@ void ciolib_setcursortype(int a) cio_api.setcursortype(a); } -int ciolib_getmouse(struct cio_mouse_event *mevent) { - CIOLIB_INIT(); - - if(cio_api.getmouse!=NULL) - return(cio_api.getmouse(mevent)); - return(-1); -} - int ciolib_showmouse(void) { CIOLIB_INIT(); diff --git a/src/conio/ciolib.h b/src/conio/ciolib.h index 3af19e08e4edd7bb09c33398c1a3503e88437e0d..f639724d13cddd5e926721401b50643fe2515c7a 100644 --- a/src/conio/ciolib.h +++ b/src/conio/ciolib.h @@ -3,6 +3,8 @@ #ifndef _CIOLIB_H_ #define _CIOLIB_H_ +#include <mouse.h> + enum { CIOLIB_MODE_AUTO ,CIOLIB_MODE_CURSES @@ -81,12 +83,6 @@ struct text_info { unsigned char cury; /* y-coordinate in current window */ }; -struct cio_mouse_event { - int x; - int y; - int button; -}; - typedef struct { int mode; int mouse; @@ -123,7 +119,7 @@ typedef struct { int (*cputs) (char *); void (*textbackground) (int); void (*textcolor) (int); - int (*getmouse) (struct cio_mouse_event *mevent); + int (*getmouse) (struct mouse_event *mevent); int (*hidemouse) (void); int (*showmouse) (void); void (*settitle) (const char *); diff --git a/src/conio/console.c b/src/conio/console.c index 19ec879bc3eaf2135bc2b7d31c427ad5cd3d8e96..293155d603ea9711b18b52ad8501ccfa0a0a9d0b 100644 --- a/src/conio/console.c +++ b/src/conio/console.c @@ -47,6 +47,9 @@ #include "console.h" #include "vparams.h" +#include "keys.h" +#include "mouse.h" + /* Console definition variables */ BYTE VideoMode; int FW, FH, FD; @@ -561,58 +564,67 @@ static int video_event(XEvent *ev) { switch (ev->type) { - case MotionNotify: { - XMotionEvent *me = (XMotionEvent *)ev; - me->x -= 2; - me->y -= 2; - - mouse_status.x = (me->x < mouse_status.range.x) - ? mouse_status.range.x - : (me->x > mouse_status.range.w) - ? mouse_status.range.w : me->x; - mouse_status.y = (me->y < mouse_status.range.y) - ? mouse_status.range.y - : (me->y > mouse_status.range.h) - ? mouse_status.range.h : me->y; - break; - } - case ButtonRelease: { - XButtonEvent *be = (XButtonEvent *)ev; - be->x -= 2; - be->y -= 2; - - if (be->button < 3) - mouse_status.ups[be->button]++; - - mouse_status.x = (be->x < mouse_status.range.x) - ? mouse_status.range.x - : (be->x > mouse_status.range.w) - ? mouse_status.range.w : be->x; - mouse_status.y = (be->y < mouse_status.range.y) - ? mouse_status.range.y - : (be->y > mouse_status.range.h) - ? mouse_status.range.h : be->y; - break; - } - case ButtonPress: { - XButtonEvent *be = (XButtonEvent *)ev; - be->x -= 2; - be->y -= 2; - - if (be->button < 3) - mouse_status.downs[be->button]++; - - mouse_status.x = (be->x < mouse_status.range.x) - ? mouse_status.range.x - : (be->x > mouse_status.range.w) - ? mouse_status.range.w : be->x; - mouse_status.y = (be->y < mouse_status.range.y) - ? mouse_status.range.y - : (be->y > mouse_status.range.h) - ? mouse_status.range.h : be->y; - - break; - } + case MotionNotify: { + XMotionEvent *me = (XMotionEvent *)ev; + me->x -= 2; + me->y -= 8; + me->x/=FW; + me->y/=FH; + me->x++; + me->y++; + if(me->x<1) + me->x=1; + if(me->y<1) + me->y=1; + if(me->x>DpyCols) + me->x=DpyCols; + if(me->y>DpyRows+1) + me->y=DpyRows+1; + ciomouse_gotevent(CIOLIB_MOUSE_MOVE,me->x,me->y); + break; + } + case ButtonRelease: { + XButtonEvent *be = (XButtonEvent *)ev; + be->x -= 2; + be->y -= 8; + be->x/=FW; + be->y/=FH; + be->x++; + be->y++; + if(be->x<1) + be->x=1; + if(be->y<1) + be->y=1; + if(be->x>DpyCols) + be->x=DpyCols; + if(be->y>DpyRows+1) + be->y=DpyRows+1; + if (be->button <= 3) { + ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(be->button),be->x,be->y); + } + break; + } + case ButtonPress: { + XButtonEvent *be = (XButtonEvent *)ev; + be->x -= 2; + be->y -= 8; + be->x/=FW; + be->y/=FH; + be->x++; + be->y++; + if(be->x<1) + be->x=1; + if(be->y<1) + be->y=1; + if(be->x>DpyCols) + be->x=DpyCols; + if(be->y>DpyRows+1) + be->y=DpyRows+1; + if (be->button <= 3) { + ciomouse_gotevent(CIOLIB_BUTTON_PRESS(be->button),be->x,be->y); + } + break; + } case NoExpose: break; case GraphicsExpose: @@ -1334,20 +1346,26 @@ tty_read(int flag) return(r & 0xff); } - if (KbdEmpty()) { + if (KbdEmpty() && !mouse_pending()) { if (flag & TTYF_BLOCK) { - while (KbdEmpty()) + while (KbdEmpty() && !mouse_pending()) tty_pause(); } else { return(-1); } } - r = KbdRead(); - if ((r & 0xff) == 0) - x_nextchar = r >> 8; - r &= 0xff; - return(r & 0xff); + if(mouse_pending()) { + x_nextchar=CIO_KEY_MOUSE>>8; + return(CIO_KEY_MOUSE&0xff); + } + else { + r = KbdRead(); + if ((r & 0xff) == 0) + x_nextchar = r >> 8; + r &= 0xff; + return(r & 0xff); + } } int diff --git a/src/conio/curs_cio.c b/src/conio/curs_cio.c index bc78666c00147d5ea21017e9922f94a108f79b22..04a41410a3836f03bc0ff4fe89d0e012e8cbe892 100644 --- a/src/conio/curs_cio.c +++ b/src/conio/curs_cio.c @@ -8,6 +8,7 @@ #include "ciolib.h" #include "curs_cio.h" #include "keys.h" +#include "mouse.h" static unsigned char curs_nextgetch=0; const int curs_tabs[10]={9,17,25,33,41,49,57,65,73,80}; @@ -401,6 +402,8 @@ int curs_kbhit(void) if(curs_nextgetch) return(1); + if(mouse_pending()) + return(1); timeout.tv_sec=0; timeout.tv_usec=0; FD_ZERO(&rfds); @@ -639,6 +642,7 @@ int curs_initciolib(long inmode) keypad(stdscr, TRUE); scrollok(stdscr,FALSE); raw(); + halfdelay(1); atexit(call_endwin); /* Set up color pairs */ @@ -649,8 +653,10 @@ int curs_initciolib(long inmode) } mode = inmode; #ifdef NCURSES_VERSION_MAJOR - if(mousemask(BUTTON1_CLICKED|BUTTON3_CLICKED,NULL)==BUTTON1_CLICKED|BUTTON3_CLICKED) + if(mousemask(BUTTON1_PRESSED|BUTTON1_RELEASED|BUTTON2_PRESSED|BUTTON2_RELEASED|BUTTON3_PRESSED|BUTTON3_RELEASED|REPORT_MOUSE_POSITION,NULL)==BUTTON1_PRESSED|BUTTON1_RELEASED|BUTTON2_PRESSED|BUTTON2_RELEASED|BUTTON3_PRESSED|BUTTON3_RELEASED|REPORT_MOUSE_POSITION) { + mouseinterval(0); cio_api.mouse=1; + } else mousemask(0,NULL); #endif @@ -761,190 +767,220 @@ int curs_putch(int c) int curs_getch(void) { int ch; + MEVENT mevnt; if(curs_nextgetch) { ch=curs_nextgetch; curs_nextgetch=0; } else { - while((ch=getch())==ERR) { - delay(1); + while((ch=getch())==ERR && !mouse_pending()); + if(mouse_pending()) { + curs_nextgetch=CIO_KEY_MOUSE>>8; + ch=CIO_KEY_MOUSE & 0xff; } - if(ch > 255) { - switch(ch) { - case KEY_DOWN: /* Down-arrow */ - curs_nextgetch=0x50; - ch=0; - break; - - case KEY_UP: /* Up-arrow */ - curs_nextgetch=0x48; - ch=0; - break; - - case KEY_LEFT: /* Left-arrow */ - curs_nextgetch=0x4b; - ch=0; - break; - - case KEY_RIGHT: /* Right-arrow */ - curs_nextgetch=0x4d; - ch=0; - break; - - case KEY_HOME: /* Home key (upward+left arrow) */ - curs_nextgetch=0x47; - ch=0; - break; - - case KEY_BACKSPACE: /* Backspace (unreliable) */ - ch=8; - break; - - case KEY_F(1): /* Function Key */ - curs_nextgetch=0x3b; - ch=0; - break; - - case KEY_F(2): /* Function Key */ - curs_nextgetch=0x3c; - ch=0; - break; - - case KEY_F(3): /* Function Key */ - curs_nextgetch=0x3d; - ch=0; - break; - - case KEY_F(4): /* Function Key */ - curs_nextgetch=0x3e; - ch=0; - break; - - case KEY_F(5): /* Function Key */ - curs_nextgetch=0x3f; - ch=0; - break; - - case KEY_F(6): /* Function Key */ - curs_nextgetch=0x40; - ch=0; - break; - - case KEY_F(7): /* Function Key */ - curs_nextgetch=0x41; - ch=0; - break; - - case KEY_F(8): /* Function Key */ - curs_nextgetch=0x42; - ch=0; - break; - - case KEY_F(9): /* Function Key */ - curs_nextgetch=0x43; - ch=0; - break; - - case KEY_F(10): /* Function Key */ - curs_nextgetch=0x44; - ch=0; - break; - - case KEY_F(11): /* Function Key */ - curs_nextgetch=0x57; - ch=0; - break; - - case KEY_F(12): /* Function Key */ - curs_nextgetch=0x58; - ch=0; - break; - - case KEY_DC: /* Delete character */ - curs_nextgetch=0x53; - ch=0; - break; - - case KEY_IC: /* Insert char or enter insert mode */ - curs_nextgetch=0x52; - ch=0; - break; - - case KEY_EIC: /* Exit insert char mode */ - curs_nextgetch=0x52; - ch=0; - break; - - case KEY_NPAGE: /* Next page */ - curs_nextgetch=0x51; - ch=0; - break; - - case KEY_PPAGE: /* Previous page */ - curs_nextgetch=0x49; - ch=0; - break; - - case KEY_ENTER: /* Enter or send (unreliable) */ - curs_nextgetch=0x0d; - ch=0; - break; - - case KEY_A1: /* Upper left of keypad */ - curs_nextgetch=0x47; - ch=0; - break; - - case KEY_A3: /* Upper right of keypad */ - curs_nextgetch=0x49; - ch=0; - break; - - case KEY_B2: /* Center of keypad */ - curs_nextgetch=0x4c; - ch=0; - break; - - case KEY_C1: /* Lower left of keypad */ - curs_nextgetch=0x4f; - ch=0; - break; - - case KEY_C3: /* Lower right of keypad */ - curs_nextgetch=0x51; - ch=0; - break; - - case KEY_BEG: /* Beg (beginning) */ - curs_nextgetch=0x47; - ch=0; - break; - - case KEY_CANCEL: /* Cancel */ - curs_nextgetch=0x03; - ch=0; - break; - - case KEY_END: /* End */ - curs_nextgetch=0x4f; - ch=0; - break; - - case KEY_SELECT: /* Select - Is "End" in X */ - curs_nextgetch=0x4f; - ch=0; - break; - - case KEY_MOUSE: /* Mouse stuff */ - ch=CIO_KEY_MOUSE>>8; - curs_nextgetch=CIO_KEY_MOUSE&0xff; - break; - - default: - curs_nextgetch=0xff; - ch=0; - break; + else { + if(ch > 255) { + switch(ch) { + case KEY_DOWN: /* Down-arrow */ + curs_nextgetch=0x50; + ch=0; + break; + + case KEY_UP: /* Up-arrow */ + curs_nextgetch=0x48; + ch=0; + break; + + case KEY_LEFT: /* Left-arrow */ + curs_nextgetch=0x4b; + ch=0; + break; + + case KEY_RIGHT: /* Right-arrow */ + curs_nextgetch=0x4d; + ch=0; + break; + + case KEY_HOME: /* Home key (upward+left arrow) */ + curs_nextgetch=0x47; + ch=0; + break; + + case KEY_BACKSPACE: /* Backspace (unreliable) */ + ch=8; + break; + + case KEY_F(1): /* Function Key */ + curs_nextgetch=0x3b; + ch=0; + break; + + case KEY_F(2): /* Function Key */ + curs_nextgetch=0x3c; + ch=0; + break; + + case KEY_F(3): /* Function Key */ + curs_nextgetch=0x3d; + ch=0; + break; + + case KEY_F(4): /* Function Key */ + curs_nextgetch=0x3e; + ch=0; + break; + + case KEY_F(5): /* Function Key */ + curs_nextgetch=0x3f; + ch=0; + break; + + case KEY_F(6): /* Function Key */ + curs_nextgetch=0x40; + ch=0; + break; + + case KEY_F(7): /* Function Key */ + curs_nextgetch=0x41; + ch=0; + break; + + case KEY_F(8): /* Function Key */ + curs_nextgetch=0x42; + ch=0; + break; + + case KEY_F(9): /* Function Key */ + curs_nextgetch=0x43; + ch=0; + break; + + case KEY_F(10): /* Function Key */ + curs_nextgetch=0x44; + ch=0; + break; + + case KEY_F(11): /* Function Key */ + curs_nextgetch=0x57; + ch=0; + break; + + case KEY_F(12): /* Function Key */ + curs_nextgetch=0x58; + ch=0; + break; + + case KEY_DC: /* Delete character */ + curs_nextgetch=0x53; + ch=0; + break; + + case KEY_IC: /* Insert char or enter insert mode */ + curs_nextgetch=0x52; + ch=0; + break; + + case KEY_EIC: /* Exit insert char mode */ + curs_nextgetch=0x52; + ch=0; + break; + + case KEY_NPAGE: /* Next page */ + curs_nextgetch=0x51; + ch=0; + break; + + case KEY_PPAGE: /* Previous page */ + curs_nextgetch=0x49; + ch=0; + break; + + case KEY_ENTER: /* Enter or send (unreliable) */ + curs_nextgetch=0x0d; + ch=0; + break; + + case KEY_A1: /* Upper left of keypad */ + curs_nextgetch=0x47; + ch=0; + break; + + case KEY_A3: /* Upper right of keypad */ + curs_nextgetch=0x49; + ch=0; + break; + + case KEY_B2: /* Center of keypad */ + curs_nextgetch=0x4c; + ch=0; + break; + + case KEY_C1: /* Lower left of keypad */ + curs_nextgetch=0x4f; + ch=0; + break; + + case KEY_C3: /* Lower right of keypad */ + curs_nextgetch=0x51; + ch=0; + break; + + case KEY_BEG: /* Beg (beginning) */ + curs_nextgetch=0x47; + ch=0; + break; + + case KEY_CANCEL: /* Cancel */ + curs_nextgetch=0x03; + ch=0; + break; + + case KEY_END: /* End */ + curs_nextgetch=0x4f; + ch=0; + break; + + case KEY_SELECT: /* Select - Is "End" in X */ + curs_nextgetch=0x4f; + ch=0; + break; + + case KEY_MOUSE: /* Mouse stuff */ + if(getmouse(&mevnt)==OK) { + int evnt=0; + switch(mevnt.bstate) { + case BUTTON1_PRESSED: + evnt=CIOLIB_BUTTON_1_PRESS; + break; + case BUTTON1_RELEASED: + evnt=CIOLIB_BUTTON_1_RELEASE; + break; + case BUTTON2_PRESSED: + evnt=CIOLIB_BUTTON_2_PRESS; + break; + case BUTTON2_RELEASED: + evnt=CIOLIB_BUTTON_2_RELEASE; + break; + case BUTTON3_PRESSED: + evnt=CIOLIB_BUTTON_3_PRESS; + break; + case BUTTON3_RELEASED: + evnt=CIOLIB_BUTTON_3_RELEASE; + break; + case REPORT_MOUSE_POSITION: + evnt=CIOLIB_MOUSE_MOVE; + break; + } + ciomouse_gotevent(evnt, mevnt.x+1, mevnt.y+1); + } + break; + + default: + curs_nextgetch=0xff; + ch=0; + break; + } } } } @@ -980,34 +1016,8 @@ int curs_hidemouse(void) int curs_showmouse(void) { #ifdef NCURSES_VERSION_MAJOR - if(mousemask(BUTTON1_CLICKED|BUTTON3_CLICKED,NULL)==BUTTON1_CLICKED|BUTTON3_CLICKED) + if(mousemask(BUTTON1_PRESSED|BUTTON1_RELEASED|BUTTON2_PRESSED|BUTTON2_RELEASED|BUTTON3_PRESSED|BUTTON3_RELEASED|REPORT_MOUSE_POSITION,NULL)==BUTTON1_PRESSED|BUTTON1_RELEASED|BUTTON2_PRESSED|BUTTON2_RELEASED|BUTTON3_PRESSED|BUTTON3_RELEASED|REPORT_MOUSE_POSITION) return(0); #endif return(-1); } - -/* cio_get_mouse() */ -int curs_getmouse(struct cio_mouse_event *mevent) -{ - #ifdef NCURSES_VERSION_MAJOR - MEVENT mevnt; - - if(getmouse(&mevnt)==OK) { - mevent->x=mevnt.x; - mevent->y=mevnt.y; - switch(mevnt.bstate) { - case BUTTON1_CLICKED: - mevent->button=1; - break; - case BUTTON3_CLICKED: - mevent->button=2; - break; - } - } - else - return(-1); - return(0); - #else - return(-1); - #endif -} diff --git a/src/conio/curs_cio.h b/src/conio/curs_cio.h index b2126f62d1d5ebe5b7acc8289941937ed8edaafc..6420def416fe924756358896477f070735677486 100644 --- a/src/conio/curs_cio.h +++ b/src/conio/curs_cio.h @@ -27,7 +27,6 @@ void curs_setcursortype(int type); int curs_getch(void); int curs_getche(void); void curs_textmode(int mode); -int curs_getmouse(struct cio_mouse_event *mevent); int curs_showmouse(void); int curs_hidemouse(void); #ifdef __cplusplus diff --git a/src/conio/mouse.c b/src/conio/mouse.c index 324567151aca01a850dcf5dbb94e13f3c17ea92f..4f8ad0e7f6ffb7607f04cd1399a05c6fae265e2c 100644 --- a/src/conio/mouse.c +++ b/src/conio/mouse.c @@ -1,5 +1,6 @@ #include <genwrap.h> #include <semwrap.h> +#include <threadwrap.h> #include "mouse.h" @@ -13,10 +14,11 @@ enum { ,MOUSE_TRIPLECLICKED ,MOUSE_QUADPRESSED ,MOUSE_QUADCLICKED + ,MOUSE_DRAGSTARTED }; -static pthread_mutex_t in_mutex; -static pthread_mutex_t out_mutex; +pthread_mutex_t in_mutex; +pthread_mutex_t out_mutex; sem_t in_sem; struct in_mouse_event { @@ -38,25 +40,15 @@ struct out_mouse_event { void *nextevent; }; -struct curr_event { - int event; /* Current event (if successfull) - * ie: If you're already clicked, and not moved, a double-click - * is the "Current Event" */ - int sx; /* Current event start x */ - int sy; /* Current event start y */ - clock_t ts; /* msclock() time this event will finish - * ie: When double-click is current, release+timeout or - * press+timeout */ -} - struct mouse_state { int buttonstate; /* Current state of all buttons - bitmap */ int knownbuttonstatemask; /* Mask of buttons that have done something since * We started watching... the rest are actually in * an unknown state */ - int button_states[3]; /* Expanded state of each button */ - int button_x[3]; /* Start X/Y position of the current state */ - int button_y[3]; + int button_state[3]; /* Expanded state of each button */ + int button_x[3]; /* Start X/Y position of the current state */ + int button_y[3]; + clock_t timeout[3]; /* Button event timeouts (timespecs ie: time of expiry) */ int curx; /* Current X position */ int cury; /* Current Y position */ int events; /* Currently enabled events */ @@ -68,14 +60,11 @@ struct mouse_state { }; struct mouse_state state; +int mouse_events=0; void init_mouse(void) { - state.buttonstate=0; - state.knownbuttonstatemask=0; - state.curx=0; - state.cury=0; - state.events=0; + memset(&state,0,sizeof(state)); state.click_timeout=200; state.multi_timeout=300; state.events_in=(struct in_mouse_event *)NULL; @@ -87,32 +76,27 @@ void init_mouse(void) int ciomouse_setevents(int events) { - state.events=events; - return state.events; + mouse_events=events; + return mouse_events; } int ciomouse_addevents(int events) { - state.events |= events; - return state.events; + mouse_events |= events; + return mouse_events; } int ciomouse_delevents(int events) { - state.events &= ~events; - return state.events; + mouse_events &= ~events; + return mouse_events; } -static void ciomouse_gotevent(int event, int x, int y) +void ciomouse_gotevent(int event, int x, int y) { struct in_mouse_event *ime; struct in_mouse_event **lastevent; - /* If you're not handling any mouse events, it doesn't matter what happens */ - /* though this COULD be used to build up correct current mouse state data */ - if(!state.events) - return; - ime=(struct in_mouse_event *)malloc(sizeof(struct in_mouse_event)); ime->ts=msclock(); ime->event=event; @@ -122,61 +106,263 @@ static void ciomouse_gotevent(int event, int x, int y) pthread_mutex_lock(&in_mutex); - for(lastevent=&state.events_in;*lastevent != NULL;lastevnet=&(lastevent->nextevent)); + for(lastevent=&state.events_in;*lastevent != NULL;lastevent=&(*lastevent)->nextevent); *lastevent=ime; pthread_mutex_unlock(&in_mutex); sem_post(&in_sem); } -static void add_outevent(int event, int bstate, int kbsm, sx, sy, ex, ey) +void add_outevent(int event, int x, int y) { struct out_mouse_event *ome; struct out_mouse_event **lastevent; + int but=0; - ome=(struct out_mouse_event *)malloc(sizeof(out_mouse_ecent)); + if(!(mouse_events & 1<<event)) + return; + ome=(struct out_mouse_event *)malloc(sizeof(struct out_mouse_event)); + but=CIOLIB_BUTTON_NUMBER(event); ome->event=event; - ome->bstate=bstate; - ome->kbsm=kbsm; - ome->startx=sx; - ome->starty=sy; - ome->endx=ex; - ome->endy=ey; + ome->bstate=state.buttonstate; + ome->kbsm=state.knownbuttonstatemask; + ome->startx=but?state.button_x[but-1]:state.curx; + ome->starty=but?state.button_y[but-1]:state.cury; + ome->endx=x; + ome->endy=y; ome->nextevent=(struct out_mouse_event *)NULL; pthread_mutex_lock(&out_mutex); - for(lastevent=&state.events_out;*lastevent != NULL;lastevent=&(lastevent->nextevent)); + for(lastevent=&state.events_out;*lastevent != NULL;lastevent=&(*lastevent)->nextevent); *lastevent=ome; - pthread_mutex_unlock(&in_mutex); + pthread_mutex_unlock(&out_mutex); } -static void ciolib_mouse_thread(void *data) +void ciolib_mouse_thread(void *data) { - int use_timeout=0; struct timespec timeout; - init_mouse(); struct in_mouse_event *old_in_event; + int timedout; + int timeout_button=0; + int but; + int delay; + clock_t ttime=0; + init_mouse(); while(1) { - if(use_timeout) - sem_timedwait(&in_sem,&timeout); + timedout=0; + if(timeout_button) { + delay=state.timeout[timeout_button-1]-msclock(); + if(delay<=0) { + timedout=1; + } + else { + timedout=sem_trywait_block(&in_sem,delay); + } + } else sem_wait(&in_sem); + if(timedout) { + state.timeout[timeout_button-1]=0; + switch(state.button_state[timeout_button-1]) { + case MOUSE_SINGLEPRESSED: + /* Press event */ + add_outevent(CIOLIB_BUTTON_PRESS(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]); + break; + case MOUSE_CLICKED: + /* Click Event */ + add_outevent(CIOLIB_BUTTON_CLICK(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]); + break; + case MOUSE_DOUBLEPRESSED: + /* Click event, then press event */ + add_outevent(CIOLIB_BUTTON_CLICK(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]); + add_outevent(CIOLIB_BUTTON_PRESS(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]); + break; + case MOUSE_DOUBLECLICKED: + /* Double-click event */ + add_outevent(CIOLIB_BUTTON_DBL_CLICK(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]); + break; + case MOUSE_TRIPLEPRESSED: + /* Double-click event, then press event */ + add_outevent(CIOLIB_BUTTON_DBL_CLICK(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]); + add_outevent(CIOLIB_BUTTON_PRESS(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]); + break; + case MOUSE_TRIPLECLICKED: + /* Triple-click event */ + add_outevent(CIOLIB_BUTTON_TRPL_CLICK(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]); + break; + case MOUSE_QUADPRESSED: + /* Triple-click evetn then press event */ + add_outevent(CIOLIB_BUTTON_TRPL_CLICK(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]); + add_outevent(CIOLIB_BUTTON_PRESS(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]); + break; + case MOUSE_QUADCLICKED: + add_outevent(CIOLIB_BUTTON_QUAD_CLICK(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]); + /* Quad click event (This doesn't need a timeout does it? */ + break; + } + state.button_state[timeout_button-1]=MOUSE_NOSTATE; + } + else { + but=CIOLIB_BUTTON_NUMBER(state.events_in->event); + switch(CIOLIB_BUTTON_BASE(state.events_in->event)) { + case CIOLIB_MOUSE_MOVE: + add_outevent(CIOLIB_MOUSE_MOVE,state.events_in->x,state.events_in->y); + for(but=1;but<=3;but++) { + switch(state.button_state[but-1]) { + case MOUSE_NOSTATE: + if(state.buttonstate & CIOLIB_BUTTON(but)) { + add_outevent(CIOLIB_BUTTON_DRAG_START(but),state.button_x[but-1],state.button_y[but-1]); + add_outevent(CIOLIB_BUTTON_DRAG_MOVE(but),state.events_in->x,state.events_in->y); + state.button_state[but-1]=MOUSE_DRAGSTARTED; + } + break; + case MOUSE_SINGLEPRESSED: + add_outevent(CIOLIB_BUTTON_DRAG_START(but),state.button_x[but-1],state.button_y[but-1]); + add_outevent(CIOLIB_BUTTON_DRAG_MOVE(but),state.events_in->x,state.events_in->y); + state.button_state[but-1]=MOUSE_DRAGSTARTED; + break; + case MOUSE_CLICKED: + add_outevent(CIOLIB_BUTTON_CLICK(but),state.button_x[but-1],state.button_y[but-1]); + state.button_state[but-1]=MOUSE_NOSTATE; + break; + case MOUSE_DOUBLEPRESSED: + add_outevent(CIOLIB_BUTTON_CLICK(but),state.button_x[but-1],state.button_y[but-1]); + add_outevent(CIOLIB_BUTTON_DRAG_START(but),state.button_x[but-1],state.button_y[but-1]); + add_outevent(CIOLIB_BUTTON_DRAG_MOVE(but),state.events_in->x,state.events_in->y); + state.button_state[but-1]=MOUSE_DRAGSTARTED; + break; + case MOUSE_DOUBLECLICKED: + add_outevent(CIOLIB_BUTTON_DBL_CLICK(but),state.button_x[but-1],state.button_y[but-1]); + state.button_state[but-1]=MOUSE_NOSTATE; + break; + case MOUSE_TRIPLEPRESSED: + add_outevent(CIOLIB_BUTTON_DBL_CLICK(but),state.button_x[but-1],state.button_y[but-1]); + add_outevent(CIOLIB_BUTTON_DRAG_START(but),state.button_x[but-1],state.button_y[but-1]); + add_outevent(CIOLIB_BUTTON_DRAG_MOVE(but),state.events_in->x,state.events_in->y); + state.button_state[but-1]=MOUSE_DRAGSTARTED; + break; + case MOUSE_TRIPLECLICKED: + add_outevent(CIOLIB_BUTTON_TRPL_CLICK(but),state.button_x[but-1],state.button_y[but-1]); + state.button_state[but-1]=MOUSE_NOSTATE; + break; + case MOUSE_QUADPRESSED: + add_outevent(CIOLIB_BUTTON_TRPL_CLICK(but),state.button_x[but-1],state.button_y[but-1]); + add_outevent(CIOLIB_BUTTON_DRAG_START(but),state.button_x[but-1],state.button_y[but-1]); + add_outevent(CIOLIB_BUTTON_DRAG_MOVE(but),state.events_in->x,state.events_in->y); + state.button_state[but-1]=MOUSE_DRAGSTARTED; + break; + case MOUSE_DRAGSTARTED: + add_outevent(CIOLIB_BUTTON_DRAG_MOVE(but),state.events_in->x,state.events_in->y); + break; + } + } + break; + case CIOLIB_BUTTON_1_PRESS: + state.buttonstate|=1<<(but-1); + state.knownbuttonstatemask|=1<<(but-1); + switch(state.button_state[but-1]) { + case MOUSE_NOSTATE: + state.button_state[but-1]=MOUSE_SINGLEPRESSED; + state.button_x[but-1]=state.events_in->x; + state.button_y[but-1]=state.events_in->y; + state.timeout[but-1]=msclock()+(state.click_timeout*MSCLOCKS_PER_SEC)/1000; + break; + case MOUSE_CLICKED: + state.button_state[but-1]=MOUSE_DOUBLEPRESSED; + state.timeout[but-1]=msclock()+(state.click_timeout*MSCLOCKS_PER_SEC)/1000; + break; + case MOUSE_DOUBLECLICKED: + state.button_state[but-1]=MOUSE_TRIPLEPRESSED; + state.timeout[but-1]=msclock()+(state.click_timeout*MSCLOCKS_PER_SEC)/1000; + break; + case MOUSE_TRIPLECLICKED: + state.button_state[but-1]=MOUSE_QUADPRESSED; + state.timeout[but-1]=msclock()+(state.click_timeout*MSCLOCKS_PER_SEC)/1000; + break; + } + break; + case CIOLIB_BUTTON_1_RELEASE: + state.buttonstate&= ~(1<<(but-1)); + state.knownbuttonstatemask|=1<<(but-1); + switch(state.button_state[but-1]) { + case MOUSE_NOSTATE: + state.button_x[but-1]=state.events_in->x; + state.button_y[but-1]=state.events_in->y; + add_outevent(CIOLIB_BUTTON_RELEASE(but),state.button_x[but-1],state.button_y[but-1]); + break; + case MOUSE_SINGLEPRESSED: + state.button_state[but-1]=MOUSE_CLICKED; + state.timeout[but-1]=msclock()+(state.multi_timeout*MSCLOCKS_PER_SEC)/1000; + break; + case MOUSE_DOUBLEPRESSED: + state.button_state[but-1]=MOUSE_DOUBLECLICKED; + state.timeout[but-1]=msclock()+(state.multi_timeout*MSCLOCKS_PER_SEC)/1000; + break; + case MOUSE_TRIPLEPRESSED: + state.button_state[but-1]=MOUSE_TRIPLECLICKED; + state.timeout[but-1]=msclock()+(state.multi_timeout*MSCLOCKS_PER_SEC)/1000; + break; + case MOUSE_QUADPRESSED: + state.button_state[but-1]=MOUSE_NOSTATE; + add_outevent(CIOLIB_BUTTON_QUAD_CLICK(but),state.button_x[but-1],state.button_y[but-1]); + state.timeout[but-1]=0; + break; + case MOUSE_DRAGSTARTED: + add_outevent(CIOLIB_BUTTON_DRAG_END(but),state.events_in->x,state.events_in->y); + state.button_state[but-1]=0; + } + } + state.curx=state.events_in->x; + state.cury=state.events_in->y; - /* Check for a timeout rather than a sem_post() */ - - if(!validate_pending(state.events_in->event)) { - add_eventsfor(state.events_in->event); + pthread_mutex_lock(&in_mutex); + old_in_event=state.events_in; + state.events_in=state.events_in->nextevent; + free(old_in_event); + pthread_mutex_unlock(&in_mutex); } - use_timeout=get_timeout(&timeout); - pthread_mutex_lock(&in_mutex); - old_in_event=state.events_in; - state.events_in=state.events_in->nextevent; - free(old_in_event); - pthread_mutes_unlock(&in_mutex); + ttime=-1; + timeout_button=0; + for(but=1;but<=3;but++) { + if(state.button_state[but-1]!=MOUSE_NOSTATE && state.button_state[but-1]!=MOUSE_DRAGSTARTED && state.timeout[but-1]<ttime) { + ttime=state.timeout[but-1]; + timeout_button=but; + } + } + } +} + +int mouse_pending(void) +{ + return(state.events_out!=NULL); +} + +int ciolib_getmouse(struct mouse_event *mevent) +{ + int retval=0; + struct out_mouse_event *old_out_event; + + pthread_mutex_lock(&out_mutex); + + if(state.events_out!=NULL) { + mevent->event=state.events_out->event; + mevent->bstate=state.events_out->bstate; + mevent->kbsm=state.events_out->kbsm; + mevent->startx=state.events_out->startx; + mevent->starty=state.events_out->starty; + mevent->endx=state.events_out->endx; + mevent->endy=state.events_out->endy; + old_out_event=state.events_out; + state.events_out=state.events_out->nextevent; + free(old_out_event); } + else + retval=-1; + pthread_mutex_unlock(&out_mutex); + return(retval); } diff --git a/src/conio/mouse.h b/src/conio/mouse.h index 6fcf4cb7c83c452e88642a8236e1bfc2a3218348..ef9f7086b7c008c7088d54942cb85dc5dc987b4e 100644 --- a/src/conio/mouse.h +++ b/src/conio/mouse.h @@ -53,13 +53,27 @@ enum { #define CIOLIB_BUTTON_CLICK(x) ((x-1)*9+3) #define CIOLIB_BUTTON_DBL_CLICK(x) ((x-1)*9+4) #define CIOLIB_BUTTON_TRPL_CLICK(x) ((x-1)*9+5) -#define CIOLIB_BUTTON_QUAD_CLOCK(x) ((x-1)*9+6) +#define CIOLIB_BUTTON_QUAD_CLICK(x) ((x-1)*9+6) #define CIOLIB_BUTTON_DRAG_START(x) ((x-1)*9+7) #define CIOLIB_BUTTON_DRAG_MOVE(x) ((x-1)*9+8) #define CIOLIB_BUTTON_DRAG_END(x) ((x-1)*9+9) -#define CIOLIB_BUTTON_NUMBER(x) ((x-1)/9+1) +#define CIOLIB_BUTTON_NUMBER(x) ((x+8)/9) -#define CIOLIB_BUTTON_BASE(x) (x-9*CIOLIB_BUTTON_NUMBER(x)) +#define CIOLIB_BUTTON_BASE(x) (x!=CIOLIB_MOUSE_MOVE?x-9*(CIOLIB_BUTTON_NUMBER(x)-1):CIOLIB_MOUSE_MOVE) + +#ifdef __cplusplus +extern "C" { +#endif +void ciomouse_gotevent(int event, int x, int y); +int mouse_pending(void); +int ciolib_getmouse(struct mouse_event *mevent); +void ciolib_mouse_thread(void *data); +int ciomouse_setevents(int events); +int ciomouse_addevents(int events); +int ciomouse_delevents(int events); +#ifdef __cplusplus +} +#endif #endif diff --git a/src/conio/win32cio.c b/src/conio/win32cio.c index e1ac43d80913a81907b7d2667db63f5433cd45fc..e1bcb024efb0f07fc883a3c147db9004cdff01e7 100644 --- a/src/conio/win32cio.c +++ b/src/conio/win32cio.c @@ -84,6 +84,7 @@ unsigned char WintoDOSAttr(WORD newattr) int win32_kbhit(void) { + static DWORD last_state=0; INPUT_RECORD input; DWORD num=0; @@ -97,11 +98,32 @@ int win32_kbhit(void) return(1); if(domouse) { if(input.EventType==MOUSE_EVENT) { - if(!input.Event.MouseEvent.dwEventFlags - && (!input.Event.MouseEvent.dwButtonState - || input.Event.MouseEvent.dwButtonState==FROM_LEFT_1ST_BUTTON_PRESSED - || input.Event.MouseEvent.dwButtonState==RIGHTMOST_BUTTON_PRESSED)) - return(1); + if(input.Event.MouseEvent.dwEventFlags==MOUSE_MOVED) { + ciomouse_gotevent(CIOLIB_MOUSE_MOVE,dwMousePosition.X+1,dwMousePosition.Y+1); + } + if(!input.Event.MouseEvent.dwEventFlags) { + switch(input.Event.MouseEvent.dwButtonState ^ last_state) { + case FROM_LEFT_1ST_BUTTON_PRESSED: + if(input.Event.MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) + ciomouse_gotevent(CIOLIB_BUTTON_1_PRESS,dwMousePosition.X+1,dwMousePosition.Y+1); + else + ciomouse_gotevent(CIOLIB_BUTTON_1_RELEASE,dwMousePosition.X+1,dwMousePosition.Y+1); + break; + case FROM_LEFT_2ND_BUTTON_PRESSED: + if(input.Event.MouseEvent.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) + ciomouse_gotevent(CIOLIB_BUTTON_2_PRESS,dwMousePosition.X+1,dwMousePosition.Y+1); + else + ciomouse_gotevent(CIOLIB_BUTTON_2_RELEASE,dwMousePosition.X+1,dwMousePosition.Y+1); + break; + case RIGHTMOST_BUTTON_PRESSED: + if(input.Event.MouseEvent.dwButtonState & RIGHTMOST_BUTTON_PRESSED) + ciomouse_gotevent(CIOLIB_BUTTON_3_PRESS,dwMousePosition.X+1,dwMousePosition.Y+1); + else + ciomouse_gotevent(CIOLIB_BUTTON_3_RELEASE,dwMousePosition.X+1,dwMousePosition.Y+1); + break; + } + last_state=input.Event.MouseEvent.dwButtonState; + } } } if(ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &input, 1, &num) @@ -109,6 +131,8 @@ int win32_kbhit(void) continue; } } + if(mouse_pending()) + return(1); return(0); } @@ -125,6 +149,8 @@ int win32_getch(void) lastch>>=8; return(ch); } + if(mousepending()) + lastch=CIO_KEY_MOUSE; if(!ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &input, 1, &num) || !num || (input.EventType!=KEY_EVENT && input.EventType!=MOUSE_EVENT)) continue; @@ -155,34 +181,32 @@ int win32_getch(void) break; case MOUSE_EVENT: if(domouse) { - if(input.Event.MouseEvent.dwEventFlags!=0) - continue; - if(input.Event.MouseEvent.dwButtonState==0) { - if(cio_last_button_press.button - && cio_last_button_press.x==input.Event.MouseEvent.dwMousePosition.X - && cio_last_button_press.y==input.Event.MouseEvent.dwMousePosition.Y) { - memcpy(&last_mouse_click,&cio_last_button_press,sizeof(last_mouse_click)); - memset(&cio_last_button_press,0,sizeof(cio_last_button_press)); - lastch=CIO_KEY_MOUSE; - break; + if(input.EventType==MOUSE_EVENT) { + if(input.Event.MouseEvent.dwEventFlags==MOUSE_MOVED) { + ciomouse_gotevent(CIOLIB_MOUSE_MOVE,dwMousePosition.X+1,dwMousePosition.Y+1); } - else { - memset(&cio_last_button_press,0,sizeof(cio_last_button_press)); - } - } - else { - memset(&cio_last_button_press,0,sizeof(cio_last_button_press)); - switch(input.Event.MouseEvent.dwButtonState) { - case FROM_LEFT_1ST_BUTTON_PRESSED: - cio_last_button_press.x=input.Event.MouseEvent.dwMousePosition.X; - cio_last_button_press.y=input.Event.MouseEvent.dwMousePosition.Y; - cio_last_button_press.button=1; - break; - case RIGHTMOST_BUTTON_PRESSED: - cio_last_button_press.x=input.Event.MouseEvent.dwMousePosition.X; - cio_last_button_press.y=input.Event.MouseEvent.dwMousePosition.Y; - cio_last_button_press.button=2; - break; + if(!input.Event.MouseEvent.dwEventFlags) { + switch(input.Event.MouseEvent.dwButtonState ^ last_state) { + case FROM_LEFT_1ST_BUTTON_PRESSED: + if(input.Event.MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) + ciomouse_gotevent(CIOLIB_BUTTON_1_PRESS,dwMousePosition.X+1,dwMousePosition.Y+1); + else + ciomouse_gotevent(CIOLIB_BUTTON_1_RELEASE,dwMousePosition.X+1,dwMousePosition.Y+1); + break; + case FROM_LEFT_2ND_BUTTON_PRESSED: + if(input.Event.MouseEvent.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) + ciomouse_gotevent(CIOLIB_BUTTON_2_PRESS,dwMousePosition.X+1,dwMousePosition.Y+1); + else + ciomouse_gotevent(CIOLIB_BUTTON_2_RELEASE,dwMousePosition.X+1,dwMousePosition.Y+1); + break; + case RIGHTMOST_BUTTON_PRESSED: + if(input.Event.MouseEvent.dwButtonState & RIGHTMOST_BUTTON_PRESSED) + ciomouse_gotevent(CIOLIB_BUTTON_3_PRESS,dwMousePosition.X+1,dwMousePosition.Y+1); + else + ciomouse_gotevent(CIOLIB_BUTTON_3_RELEASE,dwMousePosition.X+1,dwMousePosition.Y+1); + break; + } + last_state=input.Event.MouseEvent.dwButtonState; } } }