123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #include "x.hpp"
  2. is::XEngine* xengine = new is::XEngine();
  3. is::XEngine::XEngine() {
  4. m_display = NULL;
  5. m_visual = NULL;
  6. m_screen = NULL;
  7. m_good = false;
  8. m_mousex = -1;
  9. m_mousey = -1;
  10. }
  11. is::XEngine::~XEngine() {
  12. if ( !m_good ) {
  13. return;
  14. }
  15. for ( unsigned int i=0; i<m_cursors.size(); i++ ) {
  16. if ( m_cursors.at( i ) ) {
  17. XFreeCursor( m_display, m_cursors[i] );
  18. }
  19. }
  20. for ( unsigned int i=0; i<m_rects.size(); i++ ) {
  21. delete m_rects.at( i );
  22. }
  23. XCloseDisplay( m_display );
  24. }
  25. void is::XEngine::addRect( Rectangle* rect ) {
  26. m_rects.push_back( rect );
  27. }
  28. void is::XEngine::removeRect( Rectangle* rect ) {
  29. for ( unsigned int i=0; i<m_rects.size(); i++ ) {
  30. if ( m_rects.at( i ) == rect ) {
  31. m_rects.erase( m_rects.begin() + i );
  32. i--;
  33. delete rect;
  34. return;
  35. }
  36. }
  37. }
  38. bool is::XEngine::mouseDown( unsigned int button ) {
  39. if ( button >= m_mouse.size() ) {
  40. return false;
  41. }
  42. return m_mouse.at( button );
  43. }
  44. int is::XEngine::init( std::string display ) {
  45. // Initialize display
  46. m_display = XOpenDisplay( display.c_str() );
  47. if ( !m_display ) {
  48. printf( "Failed to open X display %s\n", display.c_str() );
  49. return 1;
  50. }
  51. m_screen = ScreenOfDisplay( m_display, DefaultScreen( m_display ) );
  52. m_visual = DefaultVisual ( m_display, XScreenNumberOfScreen( m_screen ) );
  53. m_colormap = DefaultColormap( m_display, XScreenNumberOfScreen( m_screen ) );
  54. m_root = RootWindow ( m_display, XScreenNumberOfScreen( m_screen ) );
  55. m_good = true;
  56. return 0;
  57. }
  58. int is::XEngine::grabCursor( is::CursorType type ) {
  59. if ( !m_good ) {
  60. return 1;
  61. }
  62. int xfontcursor = getCursor( type );
  63. int err = XGrabPointer( m_display, m_root, False,
  64. PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
  65. GrabModeAsync, GrabModeAsync, m_root, xfontcursor, CurrentTime );
  66. if ( err != GrabSuccess ) {
  67. printf( "Failed to grab X cursor\n" );
  68. return 1;
  69. }
  70. return 0;
  71. }
  72. int is::XEngine::releaseCursor() {
  73. if ( !m_good ) {
  74. return 1;
  75. }
  76. XUngrabPointer( m_display, CurrentTime );
  77. return 0;
  78. }
  79. void is::XEngine::tick() {
  80. if ( !m_good ) {
  81. return;
  82. }
  83. XFlush( m_display );
  84. XEvent event;
  85. while ( XPending( m_display ) ) {
  86. XNextEvent( m_display, &event );
  87. switch ( event.type ) {
  88. case MotionNotify: {
  89. m_mousex = event.xmotion.x;
  90. m_mousey = event.xmotion.y;
  91. break;
  92. }
  93. case ButtonPress: {
  94. if ( m_mouse.size() > event.xbutton.button ) {
  95. m_mouse.at( event.xbutton.button ) = true;
  96. } else {
  97. m_mouse.resize( event.xbutton.button+2, false );
  98. m_mouse.at( event.xbutton.button ) = true;
  99. }
  100. break;
  101. }
  102. case ButtonRelease: {
  103. if ( m_mouse.size() > event.xbutton.button ) {
  104. m_mouse.at( event.xbutton.button ) = false;
  105. } else {
  106. m_mouse.resize( event.xbutton.button+2, false );
  107. m_mouse.at( event.xbutton.button ) = false;
  108. }
  109. break;
  110. }
  111. }
  112. }
  113. }
  114. Cursor is::XEngine::getCursor( is::CursorType type ) {
  115. int xfontcursor;
  116. switch ( type ) {
  117. default:
  118. case Left: xfontcursor = XC_left_ptr; break;
  119. case Crosshair: xfontcursor = XC_crosshair; break;
  120. case Cross: xfontcursor = XC_cross; break;
  121. case UpperLeftCorner: xfontcursor = XC_ul_angle; break;
  122. case UpperRightCorner: xfontcursor = XC_ur_angle; break;
  123. case LowerLeftCorner: xfontcursor = XC_ll_angle; break;
  124. case LowerRightCorner: xfontcursor = XC_lr_angle; break;
  125. }
  126. Cursor newcursor = 0;
  127. if ( m_cursors.size() > xfontcursor ) {
  128. newcursor = m_cursors.at( xfontcursor );
  129. }
  130. if ( !newcursor ) {
  131. newcursor = XCreateFontCursor( m_display, xfontcursor );
  132. m_cursors.resize( xfontcursor+2, 0 );
  133. m_cursors.at( xfontcursor ) = newcursor;
  134. }
  135. return newcursor;
  136. }
  137. void is::XEngine::setCursor( is::CursorType type ) {
  138. if ( !m_good ) {
  139. return;
  140. }
  141. Cursor xfontcursor = getCursor( type );
  142. XChangeActivePointerGrab( m_display,
  143. ButtonMotionMask | ButtonPressMask | ButtonReleaseMask,
  144. xfontcursor, CurrentTime );
  145. }
  146. is::Rectangle::~Rectangle() {
  147. //XFreeGC( xengine->m_display, m_gc );
  148. XUnmapWindow( xengine->m_display, m_window );
  149. XDestroyWindow( xengine->m_display, m_window );
  150. }
  151. is::Rectangle::Rectangle( int x, int y, int width, int height, int border, int padding ) {
  152. m_xoffset = 0;
  153. m_yoffset = 0;
  154. m_x = x;
  155. m_y = y;
  156. m_width = width;
  157. m_height = height;
  158. m_border = border;
  159. m_padding = padding;
  160. if ( m_width < 0 ) {
  161. m_xoffset += m_width;
  162. m_width = -m_width;
  163. }
  164. if ( m_height < 0 ) {
  165. m_yoffset += m_height;
  166. m_height = -m_height;
  167. }
  168. if ( m_width == 0 ) {
  169. m_width = 1;
  170. }
  171. if ( m_height == 0 ) {
  172. m_height = 1;
  173. }
  174. XAllocNamedColor( xengine->m_display, xengine->m_colormap, "black", &m_forground, &m_forgroundExact );
  175. XAllocNamedColor( xengine->m_display, xengine->m_colormap, "white", &m_background, &m_backgroundExact );
  176. XSetWindowAttributes attributes;
  177. attributes.background_pixmap = None;
  178. attributes.background_pixel = m_forground.pixel;
  179. attributes.save_under = True;
  180. attributes.override_redirect = True;
  181. attributes.colormap = xengine->m_colormap;
  182. unsigned long valueMask = CWBackPixmap | CWBackPixel |
  183. CWSaveUnder | CWOverrideRedirect |
  184. CWColormap;
  185. m_window = XCreateWindow( xengine->m_display, xengine->m_root, m_x+m_xoffset, m_y+m_yoffset, m_width+m_border*2, m_height+m_border*2,
  186. 0, CopyFromParent, InputOutput,
  187. CopyFromParent, valueMask, &attributes );
  188. XRectangle rect;
  189. rect.x = rect.y = m_border;
  190. rect.width = m_width;
  191. rect.height = m_height;
  192. XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, &rect, 1, ShapeSubtract, 0);
  193. XMapWindow( xengine->m_display, m_window );
  194. draw();
  195. }
  196. void is::Rectangle::setPos( int x, int y ) {
  197. if ( m_x == x && m_y == y ) {
  198. return;
  199. }
  200. m_x = x;
  201. m_y = y;
  202. XMoveWindow( xengine->m_display, m_window, m_x-m_border+m_xoffset, m_y-m_border+m_yoffset );
  203. }
  204. void is::Rectangle::setDim( int w, int h ) {
  205. if ( m_width == w && m_height == h ) {
  206. return;
  207. }
  208. m_xoffset = 0;
  209. m_yoffset = 0;
  210. m_width = w;
  211. m_height = h;
  212. if ( w < 0 ) {
  213. m_xoffset += w;
  214. m_width = -w;
  215. }
  216. if ( h < 0 ) {
  217. m_yoffset += h;
  218. m_height = -h;
  219. }
  220. if ( m_width == 0 ) {
  221. m_width = 1;
  222. }
  223. if ( m_height == 0 ) {
  224. m_height = 1;
  225. }
  226. XResizeWindow( xengine->m_display, m_window, m_width+m_border*2, m_height+m_border*2 );
  227. XMoveWindow( xengine->m_display, m_window, m_x-m_border+m_xoffset, m_y-m_border+m_yoffset );
  228. // Now punch another hole in it.
  229. XRectangle rect;
  230. rect.x = rect.y = 0;
  231. rect.width = m_width+m_border*2;
  232. rect.height = m_height+m_border*2;
  233. XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 0);
  234. rect;
  235. rect.x = rect.y = m_border;
  236. rect.width = m_width;
  237. rect.height = m_height;
  238. XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, &rect, 1, ShapeSubtract, 0);
  239. draw();
  240. }
  241. void is::Rectangle::draw() {
  242. }