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