RemoteDrawingEngine: Reduce RP_READ_BITMAP result timeout.
[haiku.git] / src / preferences / screensaver / ScreenCornerSelector.cpp
blob20b53db35c56b999138e801ed9d7fdea25e63dda
1 /*
2 * Copyright 2003-2013 Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Michael Phipps
7 * Axel Dörfler, axeld@pinc-software.de
8 */
10 #include "ScreenCornerSelector.h"
12 #include <stdio.h>
14 #include <Rect.h>
15 #include <Point.h>
16 #include <Shape.h>
17 #include <Screen.h>
18 #include <Window.h>
20 #include "Constants.h"
21 #include "Utility.h"
24 static const float kAspectRatio = 4.0f / 3.0f;
25 static const float kMonitorBorderSize = 3.0f;
26 static const float kArrowSize = 11.0f;
27 static const float kStopSize = 15.0f;
30 ScreenCornerSelector::ScreenCornerSelector(BRect frame, const char* name,
31 BMessage* message, uint32 resizingMode)
33 BControl(frame, name, NULL, message, resizingMode,
34 B_WILL_DRAW | B_NAVIGABLE | B_FULL_UPDATE_ON_RESIZE),
35 fCurrentCorner(NO_CORNER),
36 fPreviousCorner(-1)
38 SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
42 BRect
43 ScreenCornerSelector::_MonitorFrame() const
45 float width = Bounds().Width();
46 float height = Bounds().Height();
48 if (width / kAspectRatio > height)
49 width = height * kAspectRatio;
50 else if (height * kAspectRatio > width)
51 height = width / kAspectRatio;
53 return BRect((Bounds().Width() - width) / 2,
54 (Bounds().Height() - height) / 2,
55 (Bounds().Width() + width) / 2, (Bounds().Height() + height) / 2);
59 BRect
60 ScreenCornerSelector::_InnerFrame(BRect monitorFrame) const
62 return monitorFrame.InsetByCopy(kMonitorBorderSize + 3,
63 kMonitorBorderSize + 3);
67 BRect
68 ScreenCornerSelector::_CenterFrame(BRect innerFrame) const
70 return innerFrame.InsetByCopy(kArrowSize, kArrowSize);
74 void
75 ScreenCornerSelector::Draw(BRect updateRect)
77 rgb_color darkColor = {160, 160, 160, 255};
78 rgb_color blackColor = {0, 0, 0, 255};
79 rgb_color redColor = {228, 0, 0, 255};
81 BRect outerRect = _MonitorFrame();
82 BRect innerRect(outerRect.InsetByCopy(kMonitorBorderSize + 2,
83 kMonitorBorderSize + 2));
85 SetDrawingMode(B_OP_OVER);
87 if (!_InnerFrame(outerRect).Contains(updateRect)) {
88 // frame & background
90 // if the focus is changing, we don't redraw the whole view, but only
91 // the part that's affected by the change
92 if (!IsFocusChanging()) {
93 SetHighColor(darkColor);
94 FillRoundRect(outerRect, kMonitorBorderSize * 3 / 2,
95 kMonitorBorderSize * 3 / 2);
98 if (IsFocus() && Window()->IsActive())
99 SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
100 else
101 SetHighColor(blackColor);
103 StrokeRoundRect(outerRect, kMonitorBorderSize * 3 / 2,
104 kMonitorBorderSize * 3 / 2);
106 if (IsFocusChanging())
107 return;
109 // power light
111 SetHighColor(redColor);
112 BPoint powerPos(outerRect.left + kMonitorBorderSize * 2, outerRect.bottom
113 - kMonitorBorderSize);
114 StrokeLine(powerPos, BPoint(powerPos.x + 2, powerPos.y));
117 if (!IsFocusChanging()) {
118 SetHighColor(210, 210, 255);
119 FillRoundRect(innerRect, kMonitorBorderSize, kMonitorBorderSize);
122 if (IsFocus() && Window()->IsActive())
123 SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
124 else
125 SetHighColor(blackColor);
126 StrokeRoundRect(innerRect, kMonitorBorderSize, kMonitorBorderSize);
128 innerRect = _InnerFrame(outerRect);
130 if (fCurrentCorner != NO_CORNER)
131 _DrawArrow(innerRect);
132 else
133 _DrawStop(innerRect);
135 SetDrawingMode(B_OP_COPY);
139 int32
140 ScreenCornerSelector::Value()
142 return (int32)fCurrentCorner;
146 void
147 ScreenCornerSelector::SetValue(int32 corner)
149 switch (corner) {
150 case UP_LEFT_CORNER:
151 case UP_RIGHT_CORNER:
152 case DOWN_LEFT_CORNER:
153 case DOWN_RIGHT_CORNER:
154 case NO_CORNER:
155 break;
157 default:
158 corner = NO_CORNER;
160 if ((screen_corner)corner == fCurrentCorner)
161 return;
163 fCurrentCorner = (screen_corner)corner;
164 Invalidate(_InnerFrame(_MonitorFrame()));
165 Invoke();
169 screen_corner
170 ScreenCornerSelector::Corner() const
172 return fCurrentCorner;
176 void
177 ScreenCornerSelector::SetCorner(screen_corner corner)
179 // redirected to SetValue() to make sure only valid values are set
180 SetValue((int32)corner);
184 void
185 ScreenCornerSelector::_DrawStop(BRect innerFrame)
187 BRect centerRect = _CenterFrame(innerFrame);
188 float size = kStopSize;
189 BRect rect;
190 rect.left = centerRect.left + (centerRect.Width() - size) / 2;
191 rect.top = centerRect.top + (centerRect.Height() - size) / 2;
192 if (rect.left < centerRect.left || rect.top < centerRect.top) {
193 size = centerRect.Height();
194 rect.top = centerRect.top;
195 rect.left = centerRect.left + (centerRect.Width() - size) / 2;
197 rect.right = rect.left + size - 1;
198 rect.bottom = rect.top + size - 1;
200 SetHighColor(255, 0, 0);
201 SetPenSize(2);
202 SetFlags(Flags() | B_SUBPIXEL_PRECISE);
204 StrokeEllipse(rect);
206 size -= sin(M_PI / 4) * size + 2;
207 rect.InsetBy(size, size);
208 StrokeLine(rect.RightTop(), rect.LeftBottom());
210 SetFlags(Flags() & ~B_SUBPIXEL_PRECISE);
211 SetPenSize(1);
215 void
216 ScreenCornerSelector::_DrawArrow(BRect innerFrame)
218 float size = kArrowSize;
219 float sizeX = fCurrentCorner == UP_LEFT_CORNER
220 || fCurrentCorner == DOWN_LEFT_CORNER ? size : -size;
221 float sizeY = fCurrentCorner == UP_LEFT_CORNER
222 || fCurrentCorner == UP_RIGHT_CORNER ? size : -size;
224 innerFrame.InsetBy(2, 2);
225 BPoint origin(sizeX < 0 ? innerFrame.right : innerFrame.left,
226 sizeY < 0 ? innerFrame.bottom : innerFrame.top);
228 SetHighColor(kBlack);
229 FillTriangle(BPoint(origin.x, origin.y), BPoint(origin.x, origin.y + sizeY),
230 BPoint(origin.x + sizeX, origin.y));
234 screen_corner
235 ScreenCornerSelector::_ScreenCorner(BPoint point,
236 screen_corner previousCorner) const
238 BRect innerFrame = _InnerFrame(_MonitorFrame());
240 if (!innerFrame.Contains(point))
241 return previousCorner;
243 if (_CenterFrame(innerFrame).Contains(point))
244 return NO_CORNER;
246 float centerX = innerFrame.left + innerFrame.Width() / 2;
247 float centerY = innerFrame.top + innerFrame.Height() / 2;
248 if (point.x < centerX)
249 return point.y < centerY ? UP_LEFT_CORNER : DOWN_LEFT_CORNER;
251 return point.y < centerY ? UP_RIGHT_CORNER : DOWN_RIGHT_CORNER;
255 void
256 ScreenCornerSelector::MouseDown(BPoint where)
258 fPreviousCorner = Value();
260 SetValue(_ScreenCorner(where, (screen_corner)fPreviousCorner));
261 SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
265 void
266 ScreenCornerSelector::MouseUp(BPoint where)
268 fPreviousCorner = -1;
272 void
273 ScreenCornerSelector::MouseMoved(BPoint where, uint32 transit,
274 const BMessage* dragMessage)
276 if (fPreviousCorner == -1)
277 return;
279 SetValue(_ScreenCorner(where, (screen_corner)fPreviousCorner));
283 void
284 ScreenCornerSelector::KeyDown(const char* bytes, int32 numBytes)
286 switch (bytes[0]) {
287 // arrow keys
289 case B_LEFT_ARROW:
290 case '4':
291 if (Corner() == UP_RIGHT_CORNER)
292 SetCorner(UP_LEFT_CORNER);
293 else if (Corner() == DOWN_RIGHT_CORNER)
294 SetCorner(DOWN_LEFT_CORNER);
295 break;
296 case B_RIGHT_ARROW:
297 case '6':
298 if (Corner() == UP_LEFT_CORNER)
299 SetCorner(UP_RIGHT_CORNER);
300 else if (Corner() == DOWN_LEFT_CORNER)
301 SetCorner(DOWN_RIGHT_CORNER);
302 break;
303 case B_UP_ARROW:
304 case '8':
305 if (Corner() == DOWN_LEFT_CORNER)
306 SetCorner(UP_LEFT_CORNER);
307 else if (Corner() == DOWN_RIGHT_CORNER)
308 SetCorner(UP_RIGHT_CORNER);
309 break;
310 case B_DOWN_ARROW:
311 case '2':
312 if (Corner() == UP_LEFT_CORNER)
313 SetCorner(DOWN_LEFT_CORNER);
314 else if (Corner() == UP_RIGHT_CORNER)
315 SetCorner(DOWN_RIGHT_CORNER);
316 break;
318 // numlock keys
320 case B_HOME:
321 case '7':
322 SetCorner(UP_LEFT_CORNER);
323 break;
324 case B_PAGE_UP:
325 case '9':
326 SetCorner(UP_RIGHT_CORNER);
327 break;
328 case B_PAGE_DOWN:
329 case '3':
330 SetCorner(DOWN_RIGHT_CORNER);
331 break;
332 case B_END:
333 case '1':
334 SetCorner(DOWN_LEFT_CORNER);
335 break;
337 default:
338 BControl::KeyDown(bytes, numBytes);