void CIOLIBCALL ciolib_mouse_thread(void *data) { int timedout; int timeout_button=0; int but; int delay; clock_t ttime=0; SetThreadName("Mouse"); init_mouse(); while(1) { timedout=0; if(timeout_button) { delay=state.timeout[timeout_button-1]-MSEC_CLOCK(); if(delay<=0) { timedout=1; } else { timedout=!listSemTryWaitBlock(&state.input,delay); } } else { listSemWait(&state.input); } 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 { struct in_mouse_event *in; in=listShiftNode(&state.input); if(in==NULL) { YIELD(); continue; } but=CIOLIB_BUTTON_NUMBER(in->event); switch(CIOLIB_BUTTON_BASE(in->event)) { case CIOLIB_MOUSE_MOVE: if(in->x==state.curx && in->y==state.cury) break; add_outevent(CIOLIB_MOUSE_MOVE,in->x,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),in->x,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),in->x,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),in->x,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),in->x,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),in->x,in->y); state.button_state[but-1]=MOUSE_DRAGSTARTED; break; case MOUSE_DRAGSTARTED: add_outevent(CIOLIB_BUTTON_DRAG_MOVE(but),in->x,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]=in->x; state.button_y[but-1]=in->y; state.timeout[but-1]=MSEC_CLOCK()+state.click_timeout; if(state.timeout[but-1]==0) state.timeout[but-1]=1; if(state.click_timeout==0) state.timeout[but-1]=0; if(!more_multies(but,0)) { add_outevent(CIOLIB_BUTTON_PRESS(but),state.button_x[but-1],state.button_y[but-1]); state.button_state[but-1]=MOUSE_NOSTATE; state.timeout[but-1]=0; } break; case MOUSE_CLICKED: state.button_state[but-1]=MOUSE_DOUBLEPRESSED; state.timeout[but-1]=MSEC_CLOCK()+state.click_timeout; if(state.timeout[but-1]==0) state.timeout[but-1]=1; if(state.click_timeout==0) state.timeout[but-1]=0; break; case MOUSE_DOUBLECLICKED: state.button_state[but-1]=MOUSE_TRIPLEPRESSED; state.timeout[but-1]=MSEC_CLOCK()+state.click_timeout; if(state.timeout[but-1]==0) state.timeout[but-1]=1; if(state.click_timeout==0) state.timeout[but-1]=0; break; case MOUSE_TRIPLECLICKED: state.button_state[but-1]=MOUSE_QUADPRESSED; state.timeout[but-1]=MSEC_CLOCK()+state.click_timeout; if(state.timeout[but-1]==0) state.timeout[but-1]=1; if(state.click_timeout==0) state.timeout[but-1]=0; 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]=in->x; state.button_y[but-1]=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]=more_multies(but,1)?MSEC_CLOCK()+state.multi_timeout:MSEC_CLOCK(); if(state.timeout[but-1]==0) state.timeout[but-1]=1; break; case MOUSE_DOUBLEPRESSED: state.button_state[but-1]=MOUSE_DOUBLECLICKED; state.timeout[but-1]=more_multies(but,2)?MSEC_CLOCK()+state.multi_timeout:MSEC_CLOCK(); if(state.timeout[but-1]==0) state.timeout[but-1]=1; break; case MOUSE_TRIPLEPRESSED: state.button_state[but-1]=MOUSE_TRIPLECLICKED; state.timeout[but-1]=more_multies(but,3)?MSEC_CLOCK()+state.multi_timeout:MSEC_CLOCK(); if(state.timeout[but-1]==0) state.timeout[but-1]=1; 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; if(state.timeout[but-1]==0) state.timeout[but-1]=1; break; case MOUSE_DRAGSTARTED: add_outevent(CIOLIB_BUTTON_DRAG_END(but),in->x,in->y); state.button_state[but-1]=0; } } state.curx=in->x; state.cury=in->y; free(in); } 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]!=0 && (timeout_button==0 || state.timeout[but-1]<ttime)) { ttime=state.timeout[but-1]; timeout_button=but; } } } }
static int x11_event(XEvent *ev) { switch (ev->type) { /* Graphics related events */ case ConfigureNotify: x11_window_xpos=ev->xconfigure.x; x11_window_ypos=ev->xconfigure.y; x11_window_width=ev->xconfigure.width; x11_window_height=ev->xconfigure.height; handle_resize_event(ev->xconfigure.width, ev->xconfigure.height); break; case NoExpose: break; case GraphicsExpose: expose_rect(ev->xgraphicsexpose.x, ev->xgraphicsexpose.y, ev->xgraphicsexpose.width, ev->xgraphicsexpose.height); break; case Expose: expose_rect(ev->xexpose.x, ev->xexpose.y, ev->xexpose.width, ev->xexpose.height); break; /* Copy/Paste events */ case SelectionClear: { XSelectionClearEvent *req; req=&(ev->xselectionclear); pthread_mutex_lock(©buf_mutex); if(req->selection==CONSOLE_CLIPBOARD) FREE_AND_NULL(copybuf); pthread_mutex_unlock(©buf_mutex); } break; case SelectionNotify: { int format; unsigned long len, bytes_left, dummy; Atom type; if(ev->xselection.selection != CONSOLE_CLIPBOARD) break; if(ev->xselection.requestor!=win) break; if(ev->xselection.property) { x11.XGetWindowProperty(dpy, win, ev->xselection.property, 0, 0, 0, AnyPropertyType, &type, &format, &len, &bytes_left, (unsigned char **)(&pastebuf)); if(bytes_left > 0 && format==8) x11.XGetWindowProperty(dpy, win, ev->xselection.property,0,bytes_left,0,AnyPropertyType,&type,&format,&len,&dummy,(unsigned char **)&pastebuf); else pastebuf=NULL; } else pastebuf=NULL; /* Set paste buffer */ sem_post(&pastebuf_set); sem_wait(&pastebuf_used); x11.XFree(pastebuf); pastebuf=NULL; } break; case SelectionRequest: { XSelectionRequestEvent *req; XEvent respond; req=&(ev->xselectionrequest); pthread_mutex_lock(©buf_mutex); if(copybuf==NULL) { respond.xselection.property=None; } else { if(req->target==XA_STRING) { x11.XChangeProperty(dpy, req->requestor, req->property, XA_STRING, 8, PropModeReplace, (unsigned char *)copybuf, strlen(copybuf)); respond.xselection.property=req->property; } else respond.xselection.property=None; } respond.xselection.type=SelectionNotify; respond.xselection.display=req->display; respond.xselection.requestor=req->requestor; respond.xselection.selection=req->selection; respond.xselection.target=req->target; respond.xselection.time=req->time; x11.XSendEvent(dpy,req->requestor,0,0,&respond); pthread_mutex_unlock(©buf_mutex); } break; /* Mouse Events */ case MotionNotify: { XMotionEvent *me = (XMotionEvent *)ev; me->x/=vstat.scaling; me->x/=vstat.charwidth; me->y/=vstat.scaling; me->y/=vstat.charheight; me->x++; me->y++; if(me->x<1) me->x=1; if(me->y<1) me->y=1; if(me->x>vstat.cols) me->x=vstat.cols; if(me->y>vstat.rows+1) me->y=vstat.rows+1; ciomouse_gotevent(CIOLIB_MOUSE_MOVE,me->x,me->y); } break; case ButtonRelease: { XButtonEvent *be = (XButtonEvent *)ev; be->x/=vstat.scaling; be->x/=vstat.charwidth; be->y/=vstat.scaling; be->y/=vstat.charheight; be->x++; be->y++; if(be->x<1) be->x=1; if(be->y<1) be->y=1; if(be->x>vstat.cols) be->x=vstat.cols; if(be->y>vstat.rows+1) be->y=vstat.rows+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/=vstat.scaling; be->x/=vstat.charwidth; be->y/=vstat.scaling; be->y/=vstat.charheight; be->x++; be->y++; if(be->x<1) be->x=1; if(be->y<1) be->y=1; if(be->x>vstat.cols) be->x=vstat.cols; if(be->y>vstat.rows+1) be->y=vstat.rows+1; if (be->button <= 3) { ciomouse_gotevent(CIOLIB_BUTTON_PRESS(be->button),be->x,be->y); } } break; /* Keyboard Events */ case KeyPress: { static char buf[128]; KeySym ks; int n; int nlock = 0; WORD scan = 0xffff; n = x11.XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0); switch (ks) { case XK_Escape: scan = 1; goto docode; case XK_Tab: case XK_ISO_Left_Tab: scan = 15; goto docode; case XK_Return: case XK_KP_Enter: scan = 28; goto docode; case XK_Print: scan = 55; goto docode; case XK_F1: case XK_F2: case XK_F3: case XK_F4: case XK_F5: case XK_F6: case XK_F7: case XK_F8: case XK_F9: case XK_F10: scan = ks - XK_F1 + 59; goto docode; case XK_KP_7: nlock = 1; case XK_Home: case XK_KP_Home: scan = 71; goto docode; case XK_KP_8: nlock = 1; case XK_Up: case XK_KP_Up: scan = 72; goto docode; case XK_KP_9: nlock = 1; case XK_Prior: case XK_KP_Prior: scan = 73; goto docode; case XK_KP_Subtract: scan = 74; goto docode; case XK_KP_4: nlock = 1; case XK_Left: case XK_KP_Left: scan = 75; goto docode; case XK_KP_5: nlock = 1; case XK_Begin: case XK_KP_Begin: scan = 76; goto docode; case XK_KP_6: nlock = 1; case XK_Right: case XK_KP_Right: scan = 77; goto docode; case XK_KP_Add: scan = 78; goto docode; case XK_KP_1: nlock = 1; case XK_End: case XK_KP_End: scan = 79; goto docode; case XK_KP_2: nlock = 1; case XK_Down: case XK_KP_Down: scan = 80; goto docode; case XK_KP_3: nlock = 1; case XK_Next: case XK_KP_Next: scan = 81; goto docode; case XK_KP_0: nlock = 1; case XK_Insert: case XK_KP_Insert: scan = 82; goto docode; case XK_KP_Decimal: nlock = 1; scan = 83; goto docode; case XK_Delete: case XK_KP_Delete: /* scan = flipdelete ? 14 : 83; */ scan = 83; goto docode; case XK_BackSpace: /* scan = flipdelete ? 83 : 14; */ scan = 14; goto docode; case XK_F11: scan = 87; goto docode; case XK_F12: scan = 88; goto docode; case XK_KP_Divide: scan = Ascii2Scan['/']; goto docode; case XK_KP_Multiply: scan = Ascii2Scan['*']; goto docode; default: if (ks < ' ' || ks > '~') break; scan = Ascii2Scan[ks]; docode: if (nlock) scan |= 0x100; if ((scan & ~0x100) > 88) { scan = 0xffff; break; } if (ev->xkey.state & Mod1Mask) { scan = ScanCodes[scan & 0xff].alt; } else if ((ev->xkey.state & ShiftMask) || (scan & 0x100)) { scan = ScanCodes[scan & 0xff].shift; } else if (ev->xkey.state & ControlMask) { scan = ScanCodes[scan & 0xff].ctrl; } else scan = ScanCodes[scan & 0xff].base; break; } if (scan != 0xffff) { uint16_t key=scan; write(key_pipe[1], &key, (scan&0xff)?1:2); } return(1); } default: break; } return(0); }