rectangle.cpp 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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. // Sleep for 0.1 seconds in hope that the screen actually cleared the window.
  16. usleep( 10000 );
  17. }
  18. slop::Rectangle::Rectangle( int sx, int sy, int ex, int ey, int border, float r, float g, float b, float a ) {
  19. m_x = std::min( sx, ex );
  20. m_y = std::min( sy, ey );
  21. m_width = std::max( sx, ex ) - m_x;
  22. m_height = std::max( sy, ey ) - m_y;
  23. m_border = border;
  24. m_window = None;
  25. // If we don't have a border, we don't exist, so just die.
  26. if ( m_border == 0 ) {
  27. return;
  28. }
  29. // This sets up m_color
  30. int err = convertColor( r, g, b );
  31. if ( err ) {
  32. fprintf( stderr, "Couldn't allocate color of value %f,%f,%f!\n", r, g, b );
  33. }
  34. XSetWindowAttributes attributes;
  35. // Set up the window so it's our color
  36. attributes.background_pixmap = None;
  37. attributes.background_pixel = m_color.pixel;
  38. attributes.border_pixel = m_color.pixel;
  39. // Not actually sure what this does, but it keeps the window from bugging out :u.
  40. attributes.override_redirect = True;
  41. // We must use our color map, because that's where our color is allocated.
  42. attributes.colormap = xengine->m_colormap;
  43. // Make sure we know when we've been successfully destroyed later!
  44. attributes.event_mask = StructureNotifyMask;
  45. unsigned long valueMask = CWBackPixmap | CWBackPixel | CWOverrideRedirect | CWColormap | CWEventMask;
  46. // Create the window
  47. m_window = XCreateWindow( xengine->m_display, xengine->m_root, m_x-m_border, m_y-m_border, m_width+m_border*2, m_height+m_border*2,
  48. 0, CopyFromParent, InputOutput,
  49. CopyFromParent, valueMask, &attributes );
  50. if ( a < 1 ) {
  51. unsigned int cardinal_alpha = (unsigned int) (a * (unsigned int)-1) ;
  52. XChangeProperty( xengine->m_display, m_window, XInternAtom( xengine->m_display, "_NET_WM_WINDOW_OPACITY", 0),
  53. XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&cardinal_alpha, 1 );
  54. }
  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::setGeo( int sx, int sy, int ex, int ey ) {
  69. int x = std::min( sx, ex );
  70. int y = std::min( sy, ey );
  71. int w = std::max( sx, ex ) - x;
  72. int h = std::max( sy, ey ) - y;
  73. if ( m_x == x && m_y == y && m_width == w && m_height == h ) {
  74. return;
  75. }
  76. m_x = x;
  77. m_y = y;
  78. m_width = w;
  79. m_height = h;
  80. // If we don't have a border, we don't exist, so just die.
  81. if ( m_border == 0 ) {
  82. return;
  83. }
  84. // Change the window size
  85. XResizeWindow( xengine->m_display, m_window, m_width+m_border*2, m_height+m_border*2 );
  86. // Fill up our old hole
  87. XRectangle rect;
  88. rect.x = rect.y = 0;
  89. rect.width = m_width+m_border*2;
  90. rect.height = m_height+m_border*2;
  91. XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 0);
  92. // Then punch out another.
  93. rect.x = rect.y = m_border;
  94. rect.width = m_width;
  95. rect.height = m_height;
  96. XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, &rect, 1, ShapeSubtract, 0);
  97. XMoveWindow( xengine->m_display, m_window, m_x-m_border, m_y-m_border );
  98. }
  99. int slop::Rectangle::convertColor( float r, float g, float b ) {
  100. // Convert float colors to shorts.
  101. short red = short( floor( r * 65535.f ) );
  102. short green = short( floor( g * 65535.f ) );
  103. short blue = short( floor( b * 65535.f ) );
  104. XColor color;
  105. color.red = red;
  106. color.green = green;
  107. color.blue = blue;
  108. int err = XAllocColor( xengine->m_display, xengine->m_colormap, &color );
  109. if ( err == BadColor ) {
  110. return err;
  111. }
  112. m_color = color;
  113. return 0;
  114. }