xref: /haiku/src/servers/app/decorator/MagneticBorder.cpp (revision 83b1a68c52ba3e0e8796282759f694b7fdddf06d)
1 /*
2  * Copyright 2010-2011, Haiku, Inc.
3  * Distributed under the terms of the MIT license.
4  *
5  * Authors:
6  *		Stephan Aßmus <superstippi@gmx.de>
7  *		Ingo Weinhold <ingo_weinhold@gmx.de>
8  *		Clemens Zeidler <haiku@clemens-zeidler.de>
9  */
10 
11 
12 #include "MagneticBorder.h"
13 
14 #include "Decorator.h"
15 #include "Window.h"
16 #include "Screen.h"
17 
18 
19 MagneticBorder::MagneticBorder()
20 	:
21 	fLastSnapTime(0)
22 {
23 
24 }
25 
26 
27 bool
28 MagneticBorder::AlterDeltaForSnap(Window* window, BPoint& delta, bigtime_t now)
29 {
30 	BRect frame = window->Frame();
31 	Decorator* decorator = window->Decorator();
32 	if (decorator)
33 		frame = decorator->GetFootprint().Frame();
34 
35 	return AlterDeltaForSnap(window->Screen(), frame, delta, now);
36 }
37 
38 
39 bool
40 MagneticBorder::AlterDeltaForSnap(const Screen* screen, BRect& frame,
41 	BPoint& delta, bigtime_t now)
42 {
43 	// Alter the delta (which is a proposed offset used while dragging a
44 	// window) so that the frame of the window 'snaps' to the edges of the
45 	// screen.
46 
47 	const bigtime_t kSnappingDuration = 1500000LL;
48 	const bigtime_t kSnappingPause = 3000000LL;
49 	const float kSnapDistance = 8.0f;
50 
51 	if (now - fLastSnapTime > kSnappingDuration
52 		&& now - fLastSnapTime < kSnappingPause) {
53 		// Maintain a pause between snapping.
54 		return false;
55 	}
56 
57 	// TODO: Perhaps obtain the usable area (not covered by the Deskbar)?
58 	BRect screenFrame = screen->Frame();
59 	BRect originalFrame = frame;
60 	frame.OffsetBy(delta);
61 
62 	float leftDist = fabs(frame.left - screenFrame.left);
63 	float topDist = fabs(frame.top - screenFrame.top);
64 	float rightDist = fabs(frame.right - screenFrame.right);
65 	float bottomDist = fabs(frame.bottom - screenFrame.bottom);
66 
67 	bool snapped = false;
68 	if (leftDist < kSnapDistance || rightDist < kSnapDistance) {
69 		snapped = true;
70 		if (leftDist < rightDist)
71 			delta.x = screenFrame.left - originalFrame.left;
72 		else
73 			delta.x = screenFrame.right - originalFrame.right;
74 	}
75 
76 	if (topDist < kSnapDistance || bottomDist < kSnapDistance) {
77 		snapped = true;
78 		if (topDist < bottomDist)
79 			delta.y = screenFrame.top - originalFrame.top;
80 		else
81 			delta.y = screenFrame.bottom - originalFrame.bottom;
82 	}
83 	if (snapped && now - fLastSnapTime > kSnappingPause)
84 		fLastSnapTime = now;
85 
86 	return snapped;
87 }
88