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
19MagneticBorder::MagneticBorder()
20	:
21	fLastSnapTime(0)
22{
23
24}
25
26
27bool
28MagneticBorder::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
39bool
40MagneticBorder::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