xshaperectangle.cpp 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #include "xshaperectangle.hpp"
  2. slop::XShapeRectangle::XShapeRectangle( glm::vec2 p1, glm::vec2 p2, float border, float padding, glm::vec4 color, bool highlight ) {
  3. this->color = convertColor( color );
  4. this->border = border;
  5. this->padding = padding;
  6. this->highlight = highlight;
  7. this->alpha = color.a;
  8. // Find each corner of the rectangle
  9. ul = glm::vec2( glm::min( p1.x, p2.x ), glm::max( p1.y, p2.y ) ) ;
  10. bl = glm::vec2( glm::min( p1.x, p2.x ), glm::min( p1.y, p2.y ) ) ;
  11. ur = glm::vec2( glm::max( p1.x, p2.x ), glm::max( p1.y, p2.y ) ) ;
  12. br = glm::vec2( glm::max( p1.x, p2.x ), glm::min( p1.y, p2.y ) ) ;
  13. // Offset the inner corners by the padding.
  14. ul = ul + glm::vec2(-padding,padding);
  15. bl = bl + glm::vec2(-padding,-padding);
  16. ur = ur + glm::vec2(padding,padding);
  17. br = br + glm::vec2(padding,-padding);
  18. // Create the outer corners by offsetting the inner by the bordersize
  19. oul = ul + glm::vec2(-border,border);
  20. obl = bl + glm::vec2(-border,-border);
  21. our = ur + glm::vec2(border,border);
  22. obr = br + glm::vec2(border,-border);
  23. XSetWindowAttributes attributes;
  24. // Set up the window so it's our color
  25. attributes.background_pixel = this->color.pixel;
  26. // Disable window decorations.
  27. attributes.override_redirect = True;
  28. // Make sure we know when we've been successfully destroyed later!
  29. attributes.event_mask = StructureNotifyMask;
  30. unsigned long valueMask = CWBackPixel | CWOverrideRedirect | CWEventMask;
  31. // Create the window
  32. window = XCreateWindow( x11->display, x11->root, 0, 0, WidthOfScreen( x11->screen ), HeightOfScreen( x11->screen ),
  33. 0, CopyFromParent, InputOutput,
  34. CopyFromParent, valueMask, &attributes );
  35. if ( alpha < 1 ) {
  36. // Change the window opacity
  37. unsigned int cardinal_alpha = (unsigned int) (alpha * (unsigned int)-1) ;
  38. XChangeProperty( x11->display, window, XInternAtom( x11->display, "_NET_WM_WINDOW_OPACITY", 0),
  39. XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&cardinal_alpha, 1 );
  40. }
  41. // Set the class hint, and title to "slop"
  42. XClassHint classhints;
  43. char name[] = "slop";
  44. classhints.res_name = name;
  45. classhints.res_class = name;
  46. XSetClassHint( x11->display, window, &classhints );
  47. // Now punch a hole into it so it looks like a selection rectangle, but only if we're not highlighting.
  48. generateHoles();
  49. createdWindow = false;
  50. }
  51. void slop::XShapeRectangle::createWindow() {
  52. if ( createdWindow ) {
  53. return;
  54. }
  55. XMapWindow( x11->display, window );
  56. createdWindow = true;
  57. }
  58. void slop::XShapeRectangle::generateHoles() {
  59. if ( !highlight ) {
  60. XRectangle rects[4];
  61. // Left
  62. rects[0].x = oul.x;
  63. rects[0].y = obl.y;
  64. rects[0].width = border;
  65. rects[0].height = oul.y-obl.y;
  66. // Top
  67. rects[1].x = ul.x;
  68. rects[1].y = obl.y;
  69. rects[1].width = ur.x-ul.x;
  70. rects[1].height = border;
  71. // Right
  72. rects[2].x = ur.x;
  73. rects[2].y = obr.y;
  74. rects[2].width = border;
  75. rects[2].height = our.y - obr.y;
  76. // Bottom
  77. rects[3].x = bl.x;
  78. rects[3].y = ul.y;
  79. rects[3].width = br.x-bl.x;
  80. rects[3].height = border;
  81. XShapeCombineRectangles( x11->display, window, ShapeBounding, 0, 0, rects, 4, ShapeSet, 0);
  82. return;
  83. }
  84. XRectangle rect;
  85. rect.x = oul.x;
  86. rect.y = obl.y;
  87. rect.width = our.x-oul.x;
  88. rect.height = oul.y-obl.y;
  89. XShapeCombineRectangles( x11->display, window, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 0);
  90. }
  91. void slop::XShapeRectangle::setPoints( glm::vec2 p1, glm::vec2 p2 ) {
  92. // Find each corner of the rectangle
  93. ul = glm::vec2( glm::min( p1.x, p2.x ), glm::max( p1.y, p2.y ) ) ;
  94. bl = glm::vec2( glm::min( p1.x, p2.x ), glm::min( p1.y, p2.y ) ) ;
  95. ur = glm::vec2( glm::max( p1.x, p2.x ), glm::max( p1.y, p2.y ) ) ;
  96. br = glm::vec2( glm::max( p1.x, p2.x ), glm::min( p1.y, p2.y ) ) ;
  97. // Offset the inner corners by the padding.
  98. ul = ul + glm::vec2(-padding,padding);
  99. bl = bl + glm::vec2(-padding,-padding);
  100. ur = ur + glm::vec2(padding,padding);
  101. br = br + glm::vec2(padding,-padding);
  102. // Create the outer corners by offsetting the inner by the bordersize
  103. oul = ul + glm::vec2(-border,border);
  104. obl = bl + glm::vec2(-border,-border);
  105. our = ur + glm::vec2(border,border);
  106. obr = br + glm::vec2(border,-border);
  107. generateHoles();
  108. }
  109. slop::XShapeRectangle::~XShapeRectangle() {
  110. XUnmapWindow( x11->display, window );
  111. XDestroyWindow( x11->display, window );
  112. }
  113. void slop::XShapeRectangle::draw( glm::mat4& matrix ) {
  114. // We don't want to be visible until we're asked to draw.
  115. createWindow();
  116. }
  117. glm::vec4 slop::XShapeRectangle::getRect() {
  118. return glm::vec4( bl.x, bl.y, ur.x-ul.x, ul.y-bl.y );
  119. }
  120. XColor slop::XShapeRectangle::convertColor( glm::vec4 color ) {
  121. // Convert float colors to shorts.
  122. short red = short( floor( color.r * 65535.f ) );
  123. short green = short( floor( color.g * 65535.f ) );
  124. short blue = short( floor( color.b * 65535.f ) );
  125. XColor xc;
  126. xc.red = red;
  127. xc.green = green;
  128. xc.blue = blue;
  129. int err = XAllocColor( x11->display, DefaultColormap( x11->display, XScreenNumberOfScreen( x11->screen ) ), &xc );
  130. if ( err == BadColor ) {
  131. throw new std::runtime_error(std::string("Couldn't allocate a color"));
  132. }
  133. return xc;
  134. }