#include "../include/xcv_license.h" //PCH namespace Widgets95 {//-. //<-' //TODO: XGrabPointer can offer better control, and maybe not interfere. #if XCV_GLX #define WIDGETS_95_NOCAPTURE //freeglut's XWarpPointer isn't quite cutting it. #endif /********************** WIDGETS_95_Mouse_Interaction::mouse_down_handler() ******/ static int xcv_mouse_iaction_warp_x; static int xcv_mouse_iaction_warp_y; static bool xcv_mouse_iaction_special = false; bool mouse_interface::_mouse_stage(int stage, _iaction_iii mf, int local_x, int local_y, bool inside) { if(!e.init_inside) { e.curr_inside = false; return true; } else e.curr_inside = true; if(1==stage) { if(local_y>ui_mouse_iaction_span) { assert(top&_placement); e.init_inside = e.curr_inside = false; return false; } xcv_mouse_iaction_warp_x = local_x-x_center(); xcv_mouse_iaction_warp_y = local_y-y_center(); (this->*mf)(1,xcv_mouse_iaction_warp_x,xcv_mouse_iaction_warp_y); //NEW: I think rotate::needs_idle was putting the ui in constant //idle. if(needs_idle()) e::xcv_setIdleFuncIfNecessary(); //redraw(); //Enable click to select, maybe double-click to reset? } else if(2==stage) { int wx = 0, wy = 0; //EXPERIMENTAL bool shift = true; #ifndef WIDGETS_95_NOCAPTURE shift = e.curr_modifiers&GLUT_ACTIVE_SHIFT; #endif if(shift) { xcv_mouse_iaction_warp_x = local_x-x_center(); xcv_mouse_iaction_warp_y = local_y-y_center(); } else { xcv_mouse_iaction_warp_x+=wx=local_x-e.down_x; xcv_mouse_iaction_warp_y+=wy=local_y-e.down_y; if(!xcv_mouse_iaction_special) { glutSetCursor(GLUT_CURSOR_NONE); //2019: No spraycan cursor glutWarpPointer(e.down_x,e.down_y); } else wx = wy = 0; } (this->*mf)(2,xcv_mouse_iaction_warp_x,xcv_mouse_iaction_warp_y); //freeglut uses XWarpPointer that generates mouse events, which it //doesn't suppress. #if XCV_GLX //NOTE: This works, but it jams up after a while... I think events //just stop coming. //Maybe XGrabPointer (https://stackoverflow.com/questions/2792954) //can do it? xcv_mouse_iaction_warp_x+=wx; xcv_mouse_iaction_warp_y+=wy; #endif output_live(); execute_callback(); } else if(3==stage) { (this->*mf)(3,xcv_mouse_iaction_warp_x,xcv_mouse_iaction_warp_y); #ifndef WIDGETS_95_NOCAPTURE if(!xcv_mouse_iaction_special) { if(~e.curr_modifiers&GLUT_ACTIVE_SHIFT) { glutWarpPointer(e.down_x,e.down_y); } } #endif redraw(); } return false; } /****************************** WIDGETS_95_Mouse_Interaction::draw() **********/ void mouse_interface::_draw(_iaction_i mf, int vpw, int vph) { bool draw_inactive_area = !vpw; if(vpw<=0) if(!_ui) { vpw = glutGet(GLUT_WINDOW_WIDTH); vph = glutGet(GLUT_WINDOW_HEIGHT); } else _ui->find_dims(&vpw,&vph); if(draw_inactive_area) { int x1 = _w/2-name_span()/2-1; draw_name(x1,ui_mouse_iaction_span+5,this==e::get_active()); } //draw_active_area(); { int text_drop = ui_mouse_iaction_head; /* kludge */ int viewport_size = _h-text_drop; /* std::min(w,h); */ gl::glMatrixMode(GL_MODELVIEW); gl::glPushMatrix(); gl::glLoadIdentity(); //-1,-1 is just to center rotate's ball. gl::glTranslated(_x_abs+_w/2-1,_y_abs+viewport_size/2-1,0); /*** Draw the interaction control's orthographic elements ***/ (this->*mf)(0); //iaction_draw(0); /*** Setup and draw the interaction control's perspective elements ***/ ////TODO? ui::translate doesn't require this step //// int vpx = _x_abs+(_w-viewport_size)/2; int vpy = vph-_y_abs-_h+text_drop; gl::glViewport(vpx,vpy,viewport_size,viewport_size); gl::glMatrixMode(GL_PROJECTION); gl::glPushMatrix(); gl::glLoadIdentity(); double xy = 1, zc = 50; /* X-Y size, and Z origin */ gl::glFrustum(-xy,+xy,-xy,+xy,zc*0.7,zc*1.3); gl::glMatrixMode(GL_MODELVIEW); gl::glLoadIdentity(); gl::glTranslated(0,0,-zc); (this->*mf)(1); //iaction_draw(1); gl::glMatrixMode(GL_PROJECTION); gl::glPopMatrix(); gl::glViewport(0,0,vpw,vph); gl::glMatrixMode(GL_MODELVIEW); gl::glPopMatrix(); } } /************************************ WIDGETS_95_Mouse_Interaction::update_area() **********/ void mouse_interface::_update_area() { int name_packed = _name_span(true); _w = std::max(_w,name_packed+4); _w = std::max(_w,_h-ui_mouse_iaction_head); //i.e. UI_MOUSE_IACTION_RADIUS //iaction_update_size(); } /****************************** WIDGETS_95_Mouse_Interaction::special_handler() **********/ bool mouse_interface::_special_handler(int key, int modifiers) { int drag_x = 0, drag_y = 0; switch(key) { case GLUT_KEY_LEFT: drag_x = -6; break; case GLUT_KEY_RIGHT: drag_x = 6; break; case GLUT_KEY_UP: drag_y = -6; break; case GLUT_KEY_DOWN: drag_y = 6; break; default: return true; //signal keycode unprocessed } if(drag_x||drag_y) { //HACK: Visualize arrow key? if(!e.wheel_event) e.spacebar_is_down = true; xcv_mouse_iaction_special = true; e::Click iaction(this,x_center(),y_center()); iaction.drag(drag_x,drag_y); bool ret = iaction.finish(); xcv_mouse_iaction_special = false; if(ret) return true; } return false; } //---. }//<-'