rectangle.cpp 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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. // Free up our color.
  10. XFreeColors( xengine->m_display, xengine->m_colormap, &m_color.pixel, 1, 0 );
  11. XDestroyWindow( xengine->m_display, m_window );
  12. XEvent event;
  13. // Block until the window is actually completely removed.
  14. XIfEvent( xengine->m_display, &event, &isDestroyNotify, (XPointer)&m_window );
  15. }
  16. slop::Rectangle::Rectangle( int x, int y, int width, int height, int border, int padding, int minimumwidth, int minimumheight, float r, float g, float b ) {
  17. m_xoffset = 0;
  18. m_yoffset = 0;
  19. m_x = x;
  20. m_y = y;
  21. m_width = width;
  22. m_height = height;
  23. m_minimumwidth = minimumwidth;
  24. m_minimumheight = minimumheight;
  25. m_border = border;
  26. m_padding = padding;
  27. m_window = None;
  28. // Convert the width, height, x, and y to coordinates that don't have negative values.
  29. // (also adjust for padding and border size.)
  30. constrain( width, height );
  31. // If we don't have a border, we don't exist, so just die.
  32. if ( m_border == 0 ) {
  33. return;
  34. }
  35. // This sets up m_color
  36. int err = convertColor( r, g, b );
  37. if ( err ) {
  38. fprintf( stderr, "Couldn't allocate color of value %f,%f,%f!\n", r, g, b );
  39. }
  40. XSetWindowAttributes attributes;
  41. // Set up the window so it's our color
  42. attributes.background_pixmap = None;
  43. attributes.background_pixel = m_color.pixel;
  44. // Not actually sure what this does, but it keeps the window from bugging out :u.
  45. attributes.override_redirect = True;
  46. // We must use our color map, because that's where our color is allocated.
  47. attributes.colormap = xengine->m_colormap;
  48. // Make sure we know when we've been successfully destroyed later!
  49. attributes.event_mask = StructureNotifyMask;
  50. unsigned long valueMask = CWBackPixmap | CWBackPixel | CWOverrideRedirect | CWColormap | CWEventMask;
  51. // Create the window offset by our generated offsets (see constrain( float, float ))
  52. m_window = XCreateWindow( xengine->m_display, xengine->m_root, m_x+m_xoffset-m_border, m_y+m_yoffset-m_border, m_width+m_border*2, m_height+m_border*2,
  53. 0, CopyFromParent, InputOutput,
  54. CopyFromParent, valueMask, &attributes );
  55. // Now punch a hole into it so it looks like a selection rectangle!
  56. XRectangle rect;
  57. rect.x = rect.y = m_border;
  58. rect.width = m_width;
  59. rect.height = m_height;
  60. XClassHint classhints;
  61. char name[] = "slop";
  62. classhints.res_name = name;
  63. classhints.res_class = name;
  64. XSetClassHint( xengine->m_display, m_window, &classhints );
  65. XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, &rect, 1, ShapeSubtract, 0);
  66. XMapWindow( xengine->m_display, m_window );
  67. }
  68. void slop::Rectangle::setPos( int x, int y ) {
  69. if ( m_x == x && m_y == y ) {
  70. return;
  71. }
  72. m_x = x;
  73. m_y = y;
  74. // If we don't have a border, we don't exist, so just die.
  75. if ( m_border == 0 ) {
  76. return;
  77. }
  78. XMoveWindow( xengine->m_display, m_window, m_x+m_xoffset-m_border, m_y+m_yoffset-m_border );
  79. }
  80. void slop::Rectangle::setDim( int w, int h ) {
  81. if ( m_width == w && m_height == h ) {
  82. return;
  83. }
  84. constrain( w, h );
  85. // If we don't have a border, we don't exist, so just die.
  86. if ( m_border == 0 ) {
  87. return;
  88. }
  89. // Change the window size and location to our generated offsets (see constrain( float, float ))
  90. XResizeWindow( xengine->m_display, m_window, m_width+m_border*2, m_height+m_border*2 );
  91. XMoveWindow( xengine->m_display, m_window, m_x+m_xoffset-m_border, m_y+m_yoffset-m_border );
  92. // Regenerate our hole
  93. XRectangle rect;
  94. rect.x = rect.y = 0;
  95. rect.width = m_width+m_border*2;
  96. rect.height = m_height+m_border*2;
  97. XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 0);
  98. // Then punch out another.
  99. rect.x = rect.y = m_border;
  100. rect.width = m_width;
  101. rect.height = m_height;
  102. XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, &rect, 1, ShapeSubtract, 0);
  103. }
  104. void slop::Rectangle::setGeo( int x, int y, int w, int h ) {
  105. if ( m_x == x && m_y == y && m_width == w && m_height == h ) {
  106. return;
  107. }
  108. m_x = x;
  109. m_y = y;
  110. constrain( w, h );
  111. // If we don't have a border, we don't exist, so just die.
  112. if ( m_border == 0 ) {
  113. return;
  114. }
  115. // Change the window size and location to our generated offsets (see constrain( float, float ))
  116. XResizeWindow( xengine->m_display, m_window, m_width+m_border*2, m_height+m_border*2 );
  117. XMoveWindow( xengine->m_display, m_window, m_x+m_xoffset-m_border, m_y+m_yoffset-m_border );
  118. // Regenerate our hole
  119. XRectangle rect;
  120. rect.x = rect.y = 0;
  121. rect.width = m_width+m_border*2;
  122. rect.height = m_height+m_border*2;
  123. XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 0);
  124. // Then punch out another.
  125. rect.x = rect.y = m_border;
  126. rect.width = m_width;
  127. rect.height = m_height;
  128. XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, &rect, 1, ShapeSubtract, 0);
  129. }
  130. // Keeps our rectangle's sizes all positive, so Xlib doesn't throw an exception.
  131. // It also keeps our values in absolute coordinates which is nice.
  132. void slop::Rectangle::constrain( int w, int h ) {
  133. int pad = m_padding;
  134. if ( pad < 0 && std::abs( w ) < std::abs( pad ) * 2 ) {
  135. pad = 0;
  136. }
  137. if ( w < 0 ) {
  138. m_flippedx = true;
  139. m_xoffset = w - pad;
  140. m_width = -w + pad * 2;
  141. } else {
  142. m_flippedx = false;
  143. m_xoffset = -pad;
  144. m_width = w + pad * 2;
  145. }
  146. pad = m_padding;
  147. if ( pad < 0 && std::abs( h ) < std::abs( pad ) * 2 ) {
  148. pad = 0;
  149. }
  150. if ( h < 0 ) {
  151. m_flippedy = true;
  152. m_yoffset = h - pad;
  153. m_height = -h + pad * 2;
  154. } else {
  155. m_flippedy = false;
  156. m_yoffset = -pad;
  157. m_height = h + pad * 2;
  158. }
  159. if ( m_width < m_minimumwidth ) {
  160. m_width = m_minimumwidth;
  161. }
  162. if ( m_height < m_minimumheight ) {
  163. m_height = m_minimumheight;
  164. }
  165. }
  166. int slop::Rectangle::convertColor( float r, float g, float b ) {
  167. // Convert float colors to shorts.
  168. short red = short( floor( r * 65535.f ) );
  169. short green = short( floor( g * 65535.f ) );
  170. short blue = short( floor( b * 65535.f ) );
  171. XColor color;
  172. color.red = red;
  173. color.green = green;
  174. color.blue = blue;
  175. int err = XAllocColor( xengine->m_display, xengine->m_colormap, &color );
  176. if ( err == BadColor ) {
  177. return err;
  178. }
  179. m_color = color;
  180. return 0;
  181. }