Keys pressed while holding down mouse are repeated using AntTweakBar

Alec Jacobson

December 10, 2012

weblog/

I found a strange bug in AntTweakBar, that causes key press events to be repeated when holding the mouse down. Here's a tiny self-compiling cpp program to reproduce the error:
#!/bin/bash
/*/../bin/ls > /dev/null
# BEGIN BASH SCRIPT
printf "//" | cat - $0 | g++ -g -I/opt/local/igl/igl_lib/include -Wall -Wextra -O3 -o .main -x c++ - -L/opt/local/igl/igl_lib/external/AntTweakBar/lib -lAntTweakBar -framework AppKit -framework GLUT -framework OpenGL && ./.main $@
rm -f .main
# END BASH SCRIPT
exit
*/

#include <AntTweakBar.h>

#ifdef __APPLE__
#  include <OpenGL/gl.h>
#  include <GLUT/glut.h>
#elif defined(_WIN32)
#  include <GL/freeglut.h>
#  define NOMINMAX
#  include <Windows.h>
#  undef NOMINMAX
#else
#  define GL_GLEXT_PROTOTYPES
#  include <GL/gl.h>
#  include <GL/glext.h>
#  include <GL/glut.h>
#endif

#include <iostream>

using namespace std;
bool bool_var = true;

void reshape(int width, int height)
{
  TwWindowSize(width,height);
}

void display()
{
  if(bool_var)
  {
    glClearColor(0,0,0,0);
  }else
  {
    glClearColor(1,1,1,0);
  }
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  TwDraw();
  glutSwapBuffers();
  glutPostRedisplay();
}

int main(int argc, char * argv[])
{
  using namespace std;
  cout<<"1) Click+hold the mouse button in the window but do not drag."<<endl;
  cout<<"2) Press and release 'a'."<<endl;

  glutInit(&argc,argv);
  TwInit(TW_OPENGL, NULL);
  TwBar * bar = TwNewBar("bar");
  TwDefine("bar label='bar' size='200 200' text=light alpha='200' color='68 68 68'");
  TwAddVarRW(bar,"bool_var",TW_TYPE_BOOLCPP,&bool_var,"key=a");
  glutInitWindowSize(500,250);
  glutCreateWindow(__FILE__);
  glutDisplayFunc(display);
  glutReshapeFunc(reshape);
  glutMouseFunc((GLUTmousebuttonfun)TwEventMouseButtonGLUT);
  glutMotionFunc((GLUTmousemotionfun)TwEventMouseMotionGLUT);
  glutPassiveMotionFunc((GLUTmousemotionfun)TwEventMouseMotionGLUT); // same as MouseMotion
  glutKeyboardFunc((GLUTkeyboardfun)TwEventKeyboardGLUT);
  glutSpecialFunc((GLUTspecialfun)TwEventSpecialGLUT);
  glutMainLoop();
  TwTerminate();
  return 0;
}
To reproduce the problem, run the code and do the following:
  1. Click the left mouse button in the middle of the window and hold it without moving the cursor
  2. Press and release 'a'
You should see the background change just once, but instead it flashes because the key press event is being repeatedly sent. I dug around in the AntTweakBar source code and found that it's not exactly that the key press event is being repeated. It's that when you click and hold the mouse in the same position, AntTweakbar is simulating a repeated mouse click every time the bar is drawn (TwDraw()). Now, when you press a key AntTweakBar processes the key event and then highlights the appropriate bar item. This highlighting is then used by the repeated mouse clicks as if the highlighted item were under the mouse. To fix this bug you can replace line ~2058 in TwMgr.cpp:
TwMouseButton(TW_MOUSE_PRESSED, g_TwMgr->m_LastMousePressedButtonID);
with:
TwMouseMotion(g_TwMgr->m_LastMouseX,g_TwMgr->m_LastMouseY);
TwMouseButton(TW_MOUSE_PRESSED, g_TwMgr->m_LastMousePressedButtonID);
This just tells AntTweakBar to first consider the mouse position before simulating a click.