Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

mouse.C

Go to the documentation of this file.
00001 
00002 #include "dev/dev.H"
00003 #include "mlib/points.H"
00004 #include "std/stop_watch.H"
00005 #include "std/config.H"
00006 
00007 #include <GL/glut.h>
00008 #include "glut_winsys.H"
00009 #include "tty_glut.H"
00010 #include "mouse.H"
00011 
00012 #include "kbd.H"
00013 
00014 using mlib::PIXEL;
00015 using mlib::CXYpt;
00016 
00017 #ifdef USE_GLUT_WACOM
00018 #include "glutwacom/glutwacom.h"
00019 
00020 static bool stylus_down = false;
00021 static bool eraser_down = false;
00022 static bool stylus2_down = false;
00023 
00024 static bool debug = Config::get_var_bool("DEBUG_GLUT_WACOM",false);
00025 
00026 inline str_ptr
00027 wacom_device_name(int device)
00028 {
00029    // Convert Wacom device numeric code to string.
00030 
00031    switch(device) {
00032     case GLUT_WACOM_CURSOR:
00033       return "cursor";
00034     case GLUT_WACOM_STYLUS:
00035       return "stylus";
00036     case GLUT_WACOM_ERASER:
00037       return "eraser";
00038     case GLUT_WACOM_MENU:
00039       return "menu";
00040     default:
00041       return "unkown device";
00042    }
00043 }
00044 
00045 inline str_ptr
00046 wacom_button_state(int state)
00047 {
00048    // Convert Wacom button state code to string.
00049 
00050    switch (state) {
00051     case GLUT_WACOM_DOWN:
00052       return "down";
00053     case GLUT_WACOM_UP:
00054       return "up";
00055     default:
00056       return "unknown state";
00057    }
00058 }
00059 
00060 inline str_ptr
00061 wacom_tablet_state(int state)
00062 {
00063    // Convert Wacom tablet state code to string.
00064 
00065    switch (state) {
00066     case GLUT_WACOM_STATE_OFF_TABLET:
00067       return "off tablet";
00068     case GLUT_WACOM_STATE_ON_TABLET:
00069       return "on tablet";
00070     case GLUT_WACOM_NO_STATE_INFO:
00071       return "unknown tablet state";
00072     default:
00073       return "undefined tablet state";
00074    }
00075 }
00076 
00077 extern "C"
00078 void
00079 wacom_button_callback(
00080    int device, int button, int state, int tablet_state,
00081    float x, float y, float pressure, float xtilt, float ytilt,
00082    int proximity
00083    ) 
00084 {
00085    GLUT_MANAGER *mgr = (GLUT_MANAGER *)FD_MANAGER::mgr(); assert(mgr);
00086    // XXX - Just block events to the blocking window, or all windows?
00087    //       Rightnow, we only use one window, so this is academic...
00088    if (mgr->get_blocker() == GLUT_WINSYS::window()) return;
00089 
00090    if (debug || Config::get_var_bool("DEBUG_MOUSE_BUTTON_CALLBACK",false,true)) {
00091       cerr << wacom_device_name(device) << ", "
00092            << "(" << wacom_tablet_state(tablet_state) << "), "
00093            << "button: " << button << ", "
00094            << "(" << wacom_button_state(state) << ")"
00095            << endl;
00096    }
00097 
00098    switch (device) {
00099     case GLUT_WACOM_CURSOR:
00100       // The "puck"
00101       switch (button) {
00102        case GLUT_WACOM_TOP_LEFT_BUTTON:
00103        case GLUT_WACOM_TOP_MIDDLE_BUTTON:
00104        case GLUT_WACOM_TOP_RIGHT_BUTTON:
00105        case GLUT_WACOM_BOTTOM_RIGHT_BUTTON:
00106        case GLUT_WACOM_BOTTOM_LEFT_BUTTON:
00107          err_adv(debug, "wacom_button_callback: cursor button pressed");
00108          break;
00109       }
00110       break;
00111     case GLUT_WACOM_STYLUS:
00112       // The "stylus", or pen
00113       switch (button) {
00114        case GLUT_WACOM_NO_BUTTON:
00115          // Translate stylus events into mouse left button events:
00116          if (tablet_state == GLUT_WACOM_STATE_ON_TABLET) {
00117             stylus_down = true;
00118             GLUT_MOUSE::mouse()->buttons().event(
00119                GLUT_LEFT_BUTTON,  DEVice_buttons::DOWN, Evd::NONE
00120                );
00121          } else {
00122             GLUT_MOUSE::mouse()->buttons().event(
00123                GLUT_LEFT_BUTTON,  DEVice_buttons::UP, Evd::NONE
00124                );
00125          }
00126          break;
00127        case GLUT_WACOM_TOP_BUTTON:
00128          if (state == GLUT_WACOM_DOWN) {
00129             err_adv(debug, "wacom_button_callback: stylus top button pressed");
00130          } else {
00131             err_adv(debug, "wacom_button_callback: stylus top button released");
00132          }
00133          break;
00134        case GLUT_WACOM_BOTTOM_BUTTON:
00135          if (state == GLUT_WACOM_DOWN) {
00136             stylus2_down = true;
00137             GLUT_MOUSE::mouse()->buttons().event(
00138                GLUT_MIDDLE_BUTTON,  DEVice_buttons::DOWN, Evd::NONE
00139                );
00140          } else {
00141             GLUT_MOUSE::mouse()->buttons().event(
00142                GLUT_MIDDLE_BUTTON,  DEVice_buttons::UP, Evd::NONE
00143                );
00144          }
00145          break;
00146       }
00147       break;
00148     case GLUT_WACOM_ERASER:
00149       // Translate eraser events into mouse 3rd button events:
00150       if (tablet_state == GLUT_WACOM_STATE_ON_TABLET) {
00151          eraser_down = true;
00152          GLUT_MOUSE::mouse()->buttons().event(
00153             GLUT_RIGHT_BUTTON,  DEVice_buttons::DOWN, Evd::NONE
00154             );
00155       } else {
00156          eraser_down = false;
00157          GLUT_MOUSE::mouse()->buttons().event(
00158             GLUT_RIGHT_BUTTON,  DEVice_buttons::UP, Evd::NONE
00159             );
00160       }
00161       break;
00162    }
00163 }
00164 
00165 extern "C"
00166 void
00167 wacom_motion_callback(
00168    int device, int tablet_state,
00169    float x, float y, float pressure,
00170    float /* xtilt */, float /* ytilt */,
00171    int /* proximity */
00172    ) 
00173 {
00174 //   GLUT_MANAGER *mgr = (GLUT_MANAGER *)FD_MANAGER::mgr(); assert(mgr);
00175    // XXX - Just block events to the blocking window, or all windows?
00176    //       Rightnow, we only use one window, so this is academic...
00177 //   if (mgr->get_blocker() == GLUT_WINSYS::window()) return;
00178 
00179    GLUT_MOUSE *mouse = GLUT_MOUSE::mouse();
00180 
00181    int w, h;
00182    mouse->winsys()->size(w, h);
00183    CXYpt cur(PIXEL(x, (double) h - y));
00184    mouse->pointer().set_pressure(pressure);
00185    mouse->pointer().event(cur, Evd::NONE);
00186 
00187    // Note: the following lines add significant lag in
00188    //       the tablet response.
00189    if (debug) {
00190       cerr << wacom_device_name(device) << ", "
00191            << "(" << wacom_tablet_state(tablet_state) << "), "
00192            << cur << ", "
00193            << "pressure: " << pressure << endl;
00194    }
00195 }
00196 
00197 #endif
00198 
00199 ARRAY<GLUT_MOUSE *> GLUT_MOUSE::_mice(1);
00200 
00201 extern "C"
00202 void 
00203 mouse_motion_callback(
00204    int x,
00205    int y
00206    )
00207 {
00208    GLUT_MANAGER *mgr = (GLUT_MANAGER *)FD_MANAGER::mgr(); assert(mgr);
00209    // XXX - Just block events to the blocking window, or all windows?
00210    //       Rightnow, we only use one window, so this is academic...
00211    if (mgr->get_blocker() == GLUT_WINSYS::window()) return;
00212 
00213 #ifdef USE_GLUT_WACOM
00214    err_adv(debug, "mouse_motion_callback");
00215    // If the tablet is in use we ignore these duplicate
00216    // "mouse" events that really come from the tablet.
00217    // (the tablet callbacks are generated too.)
00218    if (stylus_down || stylus2_down || eraser_down)
00219       return;
00220 #endif
00221 
00222    GLUT_MOUSE *mouse = GLUT_MOUSE::mouse();
00223    int w, h;
00224    mouse->winsys()->size(w, h);
00225    CXYpt curs(PIXEL(x, (double) h - y));
00226 
00227    // Unfortunately, can't get modifiers in a motion event in glut.
00228    // So, can't have a shift-move event, for example.
00229    mouse->pointer().set_pressure(1.0);
00230    mouse->pointer().event(curs, Evd::NONE);
00231 
00232    // mouse cursor motions turns off window's additional cursor (e.g.,
00233    // the special cursor associated with the tablet)
00234    mouse->winsys()->show_special_cursor(false);
00235 }
00236 
00237 extern "C"
00238 void 
00239 HACK_mouse_right_button_up()
00240 {
00241 #ifdef USE_GLUT_WACOM
00242    err_adv(debug, "HACK_mouse_right_button_up called");
00243 #endif
00244    GLUT_MOUSE::mouse()->buttons().event(
00245       GLUT_RIGHT_BUTTON,  DEVice_buttons::UP, Evd::NONE
00246       );
00247 }
00248 
00249 extern "C"
00250 void 
00251 mouse_button_callback(
00252    int button,
00253    int state,
00254    int /* x */, 
00255    int /* y */
00256    )
00257 {
00258    GLUT_MANAGER *mgr = (GLUT_MANAGER *)FD_MANAGER::mgr(); assert(mgr);
00259    // XXX - Just block events to the blocking window, or all windows?
00260    //       Rightnow, we only use one window, so this is academic...
00261    if (mgr->get_blocker() == GLUT_WINSYS::window()) return;
00262 
00263 #ifdef USE_GLUT_WACOM
00264    // Tablet events get reported redundantly as mouse events too.
00265    // First they are reported as tablet events, then again as mouse events.
00266    // On a "down" event for the tablet, the variable 'stylus_down' is
00267    // set to true. On a mouse up event, we set it back to false.
00268    // In any case we ignore mouse events that are actually tablet events.
00269    if (stylus_down) {
00270       if (state == GLUT_UP)
00271          stylus_down = false;
00272       return;
00273    }
00274    if (stylus2_down) {
00275       if (state == GLUT_UP)
00276          stylus2_down = false;
00277       return;
00278    }
00279    if (eraser_down) {
00280       if (state == GLUT_UP)
00281          eraser_down = false;
00282       return;
00283    }
00284 #endif
00285 
00286    err_adv(Config::get_var_bool("DEBUG_MOUSE_BUTTON_CALLBACK",false,true),
00287       "button: %d, %s",
00288       button,
00289       (state == GLUT_DOWN) ? "down" : "up"
00290       );
00291 
00292    GLUT_MOUSE *mouse = GLUT_MOUSE::mouse();
00293 
00294    const int glut_mods = glutGetModifiers();
00295 
00296    Evd::DEVmod mods = Evd::NONE;
00297 
00298    switch (glut_mods) {
00299     case GLUT_ACTIVE_SHIFT:
00300       mods = Evd::SHIFT;
00301       break;
00302     case GLUT_ACTIVE_CTRL:
00303       mods = Evd::CONTROL;
00304       break;
00305     default:
00306       ;
00307    }
00308 
00309    mouse->buttons().event(
00310       button,
00311       (state == GLUT_DOWN) ? DEVice_buttons::DOWN : DEVice_buttons::UP,
00312       mods);
00313 }
00314 
00315 
00316 GLUT_MOUSE::GLUT_MOUSE(GLUT_WINSYS *winsys) :
00317    _winsys(winsys)
00318 {
00319    while (_mice.num() <= winsys->id()) {
00320       // XXX - Must cast or += ARRAY is used,
00321       // which makes this an infinite loop
00322       _mice += (GLUT_MOUSE *) 0;
00323    }
00324    _mice[winsys->id()] = this;
00325 
00326 #ifdef USE_GLUT_WACOM
00327    if (glutDeviceGet(GLUT_HAS_WACOM_TABLET)) {
00328       glutInitWacom();
00329       glutWacomButtonFunc(wacom_button_callback);
00330       glutWacomMotionFunc(wacom_motion_callback);
00331       err_adv(debug, "Initialized glutwacom");
00332       // return;
00333    } else {
00334       err_msg("GLUT_MOUSE::GLUT_MOUSE: Error: Tablet device not found");
00335    }
00336 #endif
00337 
00338    // Reach here if not using the tablet via the windowing system
00339 
00340    glutMouseFunc(mouse_button_callback);         // Button events
00341    glutMotionFunc(mouse_motion_callback);        // Motion between button events
00342    glutPassiveMotionFunc(mouse_motion_callback); // Other motion
00343 }
00344 
00345 GLUT_MOUSE::~GLUT_MOUSE()
00346 {
00347    cerr << "~GLUT_MOUSE" << endl;
00348    _mice[_winsys->id()] = 0;
00349 }
00350 
00351 GLUT_MOUSE *
00352 GLUT_MOUSE::mouse()
00353 {
00354    return _mice[glutGetWindow()];
00355 }
00356 
00357 void 
00358 GLUT_CURSpush::push( 
00359    CXYpt &pt
00360    ) 
00361 {
00362    if (_win) {
00363       _win->push_cursor(pt);
00364    }
00365 }
00366 
00367 
00368 void 
00369 GLUT_CURSpush::handle_event( 
00370    CEvd &e 
00371    ) 
00372 {
00373   DEVice_2d *ice = (DEVice_2d *)e._d;
00374   push(ice->cur());
00375 }

Generated on Mon Sep 18 11:39:32 2006 for jot by  doxygen 1.4.4