rectangle.cpp 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #include "rectangle.hpp"
  2. static Bool isDestroyNotify( Display* dpy, XEvent* ev, XPointer win ) {
  3. return ev->type == DestroyNotify && ev->xdestroywindow.window == *((Window*)win);
  4. }
  5. slop::Rectangle::~Rectangle() {
  6. if ( m_window == None ) {
  7. return;
  8. }
  9. // Try to erase the window before destroying it.
  10. XRectangle rect;
  11. rect.x = 0;
  12. rect.y = 0;
  13. rect.width = 0;
  14. rect.height = 0;
  15. XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 0);
  16. // Sleep for 0.1 seconds in hope that the rectangle was erased.
  17. usleep( 10000 );
  18. // Free up our color.
  19. XFreeColors( xengine->m_display, xengine->m_colormap, &m_color.pixel, 1, 0 );
  20. XDestroyWindow( xengine->m_display, m_window );
  21. XEvent event;
  22. // Block until the window is actually completely removed.
  23. XIfEvent( xengine->m_display, &event, &isDestroyNotify, (XPointer)&m_window );
  24. // Sleep for 0.1 seconds in hope that the screen actually cleared the window.
  25. usleep( 10000 );
  26. }
  27. slop::Rectangle::Rectangle( int sx, int sy, int ex, int ey, int border, bool highlight, float r, float g, float b, float a ) {
  28. m_x = std::min( sx, ex );
  29. m_y = std::min( sy, ey );
  30. m_width = std::max( sx, ex ) - m_x;
  31. m_height = std::max( sy, ey ) - m_y;
  32. m_border = border;
  33. m_window = None;
  34. m_highlight = highlight;
  35. // If we don't have a border, we don't exist, so just die.
  36. if ( m_border == 0 ) {
  37. return;
  38. }
  39. if ( m_highlight ) {
  40. m_border = 0;
  41. }
  42. m_color = convertColor( r, g, b );
  43. XSetWindowAttributes attributes;
  44. // Set up the window so it's our color
  45. attributes.background_pixel = m_color.pixel;
  46. // Disable window decorations.
  47. attributes.override_redirect = True;
  48. // Make sure we know when we've been successfully destroyed later!
  49. attributes.event_mask = StructureNotifyMask;
  50. unsigned long valueMask = CWBackPixel | CWOverrideRedirect | CWEventMask;
  51. // Create the window
  52. m_window = XCreateWindow( xengine->m_display, xengine->m_root, 0, 0, WidthOfScreen( xengine->m_screen ), HeightOfScreen( xengine->m_screen ),
  53. 0, CopyFromParent, InputOutput,
  54. CopyFromParent, valueMask, &attributes );
  55. if ( a < 1 ) {
  56. // Change the window opacity
  57. unsigned int cardinal_alpha = (unsigned int) (a * (unsigned int)-1) ;
  58. XChangeProperty( xengine->m_display, m_window, XInternAtom( xengine->m_display, "_NET_WM_WINDOW_OPACITY", 0),
  59. XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&cardinal_alpha, 1 );
  60. }
  61. XClassHint classhints;
  62. char name[] = "slop";
  63. classhints.res_name = name;
  64. classhints.res_class = name;
  65. XSetClassHint( xengine->m_display, m_window, &classhints );
  66. // Now punch a hole into it so it looks like a selection rectangle, but only if we're not highlighting.
  67. if ( !m_highlight ) {
  68. XRectangle rects[4];
  69. // Left
  70. rects[0].x = m_x-m_border;
  71. rects[0].y = m_y-m_border;
  72. rects[0].width = m_border;
  73. rects[0].height = m_height+m_border*2;
  74. // Top
  75. rects[1].x = m_x;
  76. rects[1].y = m_y-m_border;
  77. rects[1].width = m_width+m_border;
  78. rects[1].height = m_border;
  79. // Right
  80. rects[2].x = m_x+m_width;
  81. rects[2].y = m_y-m_border;
  82. rects[2].width = m_border;
  83. rects[2].height = m_height+m_border*2;
  84. // Bottom
  85. rects[3].x = m_x;
  86. rects[3].y = m_y+m_height;
  87. rects[3].width = m_width+m_border;
  88. rects[3].height = m_border;
  89. XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, rects, 4, ShapeSet, 0);
  90. } else {
  91. XRectangle rect;
  92. rect.x = m_x;
  93. rect.y = m_y;
  94. rect.width = m_width;
  95. rect.height = m_height;
  96. XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 0);
  97. }
  98. // Make it so all input falls through
  99. XRectangle rect;
  100. rect.x = rect.y = rect.width = rect.height = 0;
  101. XShapeCombineRectangles( xengine->m_display, m_window, ShapeInput, 0, 0, &rect, 1, ShapeSet, 0);
  102. XMapWindow( xengine->m_display, m_window );
  103. }
  104. void slop::Rectangle::setGeo( int sx, int sy, int ex, int ey ) {
  105. int x = std::min( sx, ex );
  106. int y = std::min( sy, ey );
  107. int w = std::max( sx, ex ) - x;
  108. int h = std::max( sy, ey ) - y;
  109. // Only resize or move if we have to, because they're oddly expensive.
  110. m_x = x;
  111. m_y = y;
  112. m_width = w;
  113. m_height = h;
  114. if ( m_border > 0 ) {
  115. XRectangle rects[4];
  116. // Left
  117. rects[0].x = m_x-m_border;
  118. rects[0].y = m_y-m_border;
  119. rects[0].width = m_border;
  120. rects[0].height = m_height+m_border*2;
  121. // Top
  122. rects[1].x = m_x;
  123. rects[1].y = m_y-m_border;
  124. rects[1].width = m_width+m_border;
  125. rects[1].height = m_border;
  126. // Right
  127. rects[2].x = m_x+m_width;
  128. rects[2].y = m_y-m_border;
  129. rects[2].width = m_border;
  130. rects[2].height = m_height+m_border*2;
  131. // Bottom
  132. rects[3].x = m_x;
  133. rects[3].y = m_y+m_height;
  134. rects[3].width = m_width+m_border;
  135. rects[3].height = m_border;
  136. XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, rects, 4, ShapeSet, 0);
  137. } else {
  138. XRectangle rect;
  139. rect.x = m_x;
  140. rect.y = m_y;
  141. rect.width = m_width;
  142. rect.height = m_height;
  143. XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 0);
  144. }
  145. }
  146. XColor slop::Rectangle::convertColor( float r, float g, float b ) {
  147. // Convert float colors to shorts.
  148. short red = short( floor( r * 65535.f ) );
  149. short green = short( floor( g * 65535.f ) );
  150. short blue = short( floor( b * 65535.f ) );
  151. XColor color;
  152. color.red = red;
  153. color.green = green;
  154. color.blue = blue;
  155. int err = XAllocColor( xengine->m_display, xengine->m_colormap, &color );
  156. if ( err == BadColor ) {
  157. fprintf( stderr, "Couldn't allocate color of value %f,%f,%f!\n", r, g, b );
  158. }
  159. return color;
  160. }