1c284bb0fSMatt Madia/*
2c284bb0fSMatt Madia * Copyright (c) 1999-2000, Eric Moon.
3c284bb0fSMatt Madia * All rights reserved.
4c284bb0fSMatt Madia *
5c284bb0fSMatt Madia * Redistribution and use in source and binary forms, with or without
6c284bb0fSMatt Madia * modification, are permitted provided that the following conditions
7c284bb0fSMatt Madia * are met:
8c284bb0fSMatt Madia *
9c284bb0fSMatt Madia * 1. Redistributions of source code must retain the above copyright
10c284bb0fSMatt Madia *    notice, this list of conditions, and the following disclaimer.
11c284bb0fSMatt Madia *
12c284bb0fSMatt Madia * 2. Redistributions in binary form must reproduce the above copyright
13c284bb0fSMatt Madia *    notice, this list of conditions, and the following disclaimer in the
14c284bb0fSMatt Madia *    documentation and/or other materials provided with the distribution.
15c284bb0fSMatt Madia *
16c284bb0fSMatt Madia * 3. The name of the author may not be used to endorse or promote products
17c284bb0fSMatt Madia *    derived from this software without specific prior written permission.
18c284bb0fSMatt Madia *
19c284bb0fSMatt Madia * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20c284bb0fSMatt Madia * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21c284bb0fSMatt Madia * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22c284bb0fSMatt Madia * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23c284bb0fSMatt Madia * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24c284bb0fSMatt Madia * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25c284bb0fSMatt Madia * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26c284bb0fSMatt Madia * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27c284bb0fSMatt Madia * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28c284bb0fSMatt Madia * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29c284bb0fSMatt Madia */
30c284bb0fSMatt Madia
31c284bb0fSMatt Madia
32a0795c6fSMarcus Overhagen// TipManager.cpp
33a0795c6fSMarcus Overhagen// e.moon 12may99
34a0795c6fSMarcus Overhagen
35a0795c6fSMarcus Overhagen#include "TipManager.h"
36a0795c6fSMarcus Overhagen#include "TipManagerImpl.h"
37a0795c6fSMarcus Overhagen#include "TipWindow.h"
38a0795c6fSMarcus Overhagen
39a0795c6fSMarcus Overhagen#include <Autolock.h>
40a0795c6fSMarcus Overhagen#include <Message.h>
41a0795c6fSMarcus Overhagen#include <MessageFilter.h>
42a0795c6fSMarcus Overhagen#include <Region.h>
43a0795c6fSMarcus Overhagen#include <float.h>
44a0795c6fSMarcus Overhagen
45a0795c6fSMarcus Overhagen#include "debug_tools.h"
46a0795c6fSMarcus Overhagen
47a0795c6fSMarcus Overhagen__USE_CORTEX_NAMESPACE
48a0795c6fSMarcus Overhagen
49a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
50a0795c6fSMarcus Overhagen// constants
51a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
52a0795c6fSMarcus Overhagen
53a0795c6fSMarcus Overhagen// static instance (created on first call to TipManager::Instance().)
54a0795c6fSMarcus OverhagenTipManager* TipManager::s_instance = 0;
55a0795c6fSMarcus OverhagenBLocker TipManager::s_instanceLock("TipManager::s_instanceLock");
56a0795c6fSMarcus Overhagen
57a0795c6fSMarcus Overhagen// special point value set to highly improbable position
58a0795c6fSMarcus Overhagenconst BPoint TipManager::s_useDefaultOffset(FLT_MIN, FLT_MIN);
59a0795c6fSMarcus Overhagen
60a0795c6fSMarcus Overhagen// default tip position
61a0795c6fSMarcus Overhagenconst BPoint TipManager::s_defaultOffset(8.0, 8.0);
62a0795c6fSMarcus Overhagen
63a0795c6fSMarcus Overhagenconst bigtime_t		TipManager::s_defIdleTime		= 750000LL;
64a0795c6fSMarcus Overhagenconst bigtime_t		TipManager::s_sleepPeriod 	= 250000LL;
65a0795c6fSMarcus Overhagen
66a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
67a0795c6fSMarcus Overhagen// *** message filter
68a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
69a0795c6fSMarcus Overhagen
70a0795c6fSMarcus Overhagenfilter_result ignore_quit_key(
71a0795c6fSMarcus Overhagen	BMessage* message,
72a0795c6fSMarcus Overhagen	BHandler** target,
73a0795c6fSMarcus Overhagen	BMessageFilter* filter)
74a0795c6fSMarcus Overhagen{
75a0795c6fSMarcus Overhagen	switch(message->what)
76a0795c6fSMarcus Overhagen	{
77a0795c6fSMarcus Overhagen		// filter command-Q
78a0795c6fSMarcus Overhagen		case B_KEY_DOWN:
79a0795c6fSMarcus Overhagen		{
80a0795c6fSMarcus Overhagen			if((modifiers() & B_COMMAND_KEY))
81a0795c6fSMarcus Overhagen			{
82a0795c6fSMarcus Overhagen				int8 key;
83a0795c6fSMarcus Overhagen				message->FindInt8("byte", &key);
84a0795c6fSMarcus Overhagen				if(key == 'q')
85a0795c6fSMarcus Overhagen					return B_SKIP_MESSAGE;
86a0795c6fSMarcus Overhagen			}
87a0795c6fSMarcus Overhagen			break;
88a0795c6fSMarcus Overhagen		}
89a0795c6fSMarcus Overhagen	}
90a0795c6fSMarcus Overhagen	return B_DISPATCH_MESSAGE;
91a0795c6fSMarcus Overhagen}
92a0795c6fSMarcus Overhagen
93a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
94a0795c6fSMarcus Overhagen// *** dtor
95a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
96a0795c6fSMarcus Overhagen
97a0795c6fSMarcus OverhagenTipManager::~TipManager() {}
98a0795c6fSMarcus Overhagen
99a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
100a0795c6fSMarcus Overhagen// *** singleton access
101a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
102a0795c6fSMarcus Overhagen
103a0795c6fSMarcus Overhagen/*static*/
104a0795c6fSMarcus OverhagenTipManager* TipManager::Instance() {
105a0795c6fSMarcus Overhagen	BAutolock _l(s_instanceLock);
106a0795c6fSMarcus Overhagen	if(!s_instance)
107a0795c6fSMarcus Overhagen		s_instance = new TipManager();
108a0795c6fSMarcus Overhagen
109a0795c6fSMarcus Overhagen	return s_instance;
110a0795c6fSMarcus Overhagen}
111a0795c6fSMarcus Overhagen
112a0795c6fSMarcus Overhagen// kill current instance if any
113a0795c6fSMarcus Overhagen/*static*/
114a0795c6fSMarcus Overhagenvoid TipManager::QuitInstance() {
115a0795c6fSMarcus Overhagen	BAutolock _l(s_instanceLock);
116a0795c6fSMarcus Overhagen	if(s_instance) {
117a0795c6fSMarcus Overhagen		s_instance->Lock();
118a0795c6fSMarcus Overhagen		s_instance->Quit();
119a0795c6fSMarcus Overhagen		s_instance = 0;
120a0795c6fSMarcus Overhagen	}
121a0795c6fSMarcus Overhagen}
122a0795c6fSMarcus Overhagen
123a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
124a0795c6fSMarcus Overhagen// hidden constructor (use Instance() to access
125a0795c6fSMarcus Overhagen// a single instance)
126a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
127a0795c6fSMarcus Overhagen
128a0795c6fSMarcus OverhagenTipManager::TipManager() :
129a0795c6fSMarcus Overhagen
130a0795c6fSMarcus Overhagen	BWindow(
131a0795c6fSMarcus Overhagen		BRect(-100,-100,-100,-100),
132a0795c6fSMarcus Overhagen		"TipManager",
133a0795c6fSMarcus Overhagen		B_NO_BORDER_WINDOW_LOOK,
134a0795c6fSMarcus Overhagen		B_FLOATING_ALL_WINDOW_FEEL,
135a0795c6fSMarcus Overhagen		B_ASYNCHRONOUS_CONTROLS | B_AVOID_FOCUS),
136a0795c6fSMarcus Overhagen	m_view(0) {
137a0795c6fSMarcus Overhagen
138a0795c6fSMarcus Overhagen	AddCommonFilter(
139a0795c6fSMarcus Overhagen		new BMessageFilter(
140a0795c6fSMarcus Overhagen			B_PROGRAMMED_DELIVERY,
141a0795c6fSMarcus Overhagen			B_ANY_SOURCE,
142a0795c6fSMarcus Overhagen			&ignore_quit_key));
143a0795c6fSMarcus Overhagen
144a0795c6fSMarcus Overhagen	m_view = new _TipManagerView(
145a0795c6fSMarcus Overhagen		new TipWindow(),
146a0795c6fSMarcus Overhagen		this,
147a0795c6fSMarcus Overhagen		s_sleepPeriod,
148a0795c6fSMarcus Overhagen		s_defIdleTime);
149a0795c6fSMarcus Overhagen	AddChild(m_view);
150a0795c6fSMarcus Overhagen
151a0795c6fSMarcus Overhagen	// start the window thread
152a0795c6fSMarcus Overhagen	Show();
153a0795c6fSMarcus Overhagen}
154a0795c6fSMarcus Overhagen
155a0795c6fSMarcus Overhagen
156a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
157a0795c6fSMarcus Overhagen// add and remove tips
158a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
159a0795c6fSMarcus Overhagen
160a0795c6fSMarcus Overhagen// add or modify a tip:
161a0795c6fSMarcus Overhagen
162a0795c6fSMarcus Overhagenstatus_t TipManager::setTip(
163a0795c6fSMarcus Overhagen	const BRect&			rect,
164a0795c6fSMarcus Overhagen	const char*				text,
165a0795c6fSMarcus Overhagen	BView*						view,
166a0795c6fSMarcus Overhagen	offset_mode_t			offsetMode	/*=LEFT_OFFSET_FROM_RECT*/,
167a0795c6fSMarcus Overhagen	BPoint						offset			/*=s_useDefaultOffset*/,
168a0795c6fSMarcus Overhagen	uint32 						flags				/*=NONE*/) {
169a0795c6fSMarcus Overhagen
170a0795c6fSMarcus Overhagen	ASSERT(text);
171a0795c6fSMarcus Overhagen	ASSERT(m_view);
172a0795c6fSMarcus Overhagen
173a0795c6fSMarcus Overhagen	BAutolock _l(this);
174a0795c6fSMarcus Overhagen	return m_view->setTip(
175a0795c6fSMarcus Overhagen		rect, text, view, offsetMode, offset, flags);
176a0795c6fSMarcus Overhagen}
177a0795c6fSMarcus Overhagen
178a0795c6fSMarcus Overhagen
179a0795c6fSMarcus Overhagenstatus_t TipManager::setTip(
180a0795c6fSMarcus Overhagen	const char*				text,
181a0795c6fSMarcus Overhagen	BView*						view,
182a0795c6fSMarcus Overhagen	offset_mode_t			offsetMode	/*=LEFT_OFFSET_FROM_RECT*/,
183a0795c6fSMarcus Overhagen	BPoint						offset			/*=s_useDefaultOffset*/,
184a0795c6fSMarcus Overhagen	uint32 						flags				/*=NONE*/) {
185a0795c6fSMarcus Overhagen
186a0795c6fSMarcus Overhagen	return setTip(
187a0795c6fSMarcus Overhagen		BRect(), text, view, offsetMode, offset, flags);
188a0795c6fSMarcus Overhagen}
189a0795c6fSMarcus Overhagen
190a0795c6fSMarcus Overhagen// Remove all tips matching the given rectangle and/or child
191a0795c6fSMarcus Overhagen// view.  Returns the number of tips removed.
192a0795c6fSMarcus Overhagen
193a0795c6fSMarcus Overhagenstatus_t TipManager::removeTip(
194a0795c6fSMarcus Overhagen	const BRect&		rect,
195a0795c6fSMarcus Overhagen	BView*					view) {
196a0795c6fSMarcus Overhagen
197a0795c6fSMarcus Overhagen	ASSERT(view);
198a0795c6fSMarcus Overhagen	ASSERT(m_view);
199a0795c6fSMarcus Overhagen
200a0795c6fSMarcus Overhagen	BAutolock _l(this);
201a0795c6fSMarcus Overhagen	return m_view->removeTip(rect, view);
202a0795c6fSMarcus Overhagen}
203a0795c6fSMarcus Overhagen
204a0795c6fSMarcus Overhagen// If more than one tip is mapped to pChild, all are removed:
205a0795c6fSMarcus Overhagen
206a0795c6fSMarcus Overhagenstatus_t TipManager::removeAll(
207a0795c6fSMarcus Overhagen	BView*					view) {
208a0795c6fSMarcus Overhagen
209a0795c6fSMarcus Overhagen	return removeTip(BRect(), view);
210a0795c6fSMarcus Overhagen}
211a0795c6fSMarcus Overhagen
212a0795c6fSMarcus Overhagenstatus_t TipManager::removeAll(
213a0795c6fSMarcus Overhagen	BWindow*				window) {
214a0795c6fSMarcus Overhagen
215a0795c6fSMarcus Overhagen//	PRINT((
216a0795c6fSMarcus Overhagen//		"### TipManager::removeAll(): %p, %p\n", this, m_view->Looper()));
217a0795c6fSMarcus Overhagen
218a0795c6fSMarcus Overhagen	ASSERT(window);
219a0795c6fSMarcus Overhagen	ASSERT(m_view);
220a0795c6fSMarcus Overhagen	ASSERT(m_view->Looper() == this); // +++++
221a0795c6fSMarcus Overhagen
222a0795c6fSMarcus Overhagen	BAutolock _l(this);
223a0795c6fSMarcus Overhagen	return m_view->removeAll(window);
224a0795c6fSMarcus Overhagen}
225a0795c6fSMarcus Overhagen
226a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
227a0795c6fSMarcus Overhagen// *** manual tip arming
228a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
229a0795c6fSMarcus Overhagen
230a0795c6fSMarcus Overhagen// [e.moon 19oct99]
231a0795c6fSMarcus Overhagen// Call when the mouse has entered a particular region of
232a0795c6fSMarcus Overhagen// the screen for which you want a tip to be displayed.
233a0795c6fSMarcus Overhagen// The tip will be displayed if the mouse stops moving
234a0795c6fSMarcus Overhagen// for idleTime microseconds within the rectangle screenRect.
235a0795c6fSMarcus Overhagen
236a0795c6fSMarcus Overhagenstatus_t TipManager::showTip(
237a0795c6fSMarcus Overhagen	const char*						text,
238a0795c6fSMarcus Overhagen	BRect									screenRect,
239a0795c6fSMarcus Overhagen	offset_mode_t					offsetMode	/*=LEFT_OFFSET_FROM_RECT*/,
240a0795c6fSMarcus Overhagen	BPoint								offset			/*=s_useDefaultOffset*/,
241a0795c6fSMarcus Overhagen	uint32 								flags				/*=NONE*/) {
242a0795c6fSMarcus Overhagen
243a0795c6fSMarcus Overhagen	ASSERT(text);
244a0795c6fSMarcus Overhagen	ASSERT(m_view);
245a0795c6fSMarcus Overhagen
246a0795c6fSMarcus Overhagen	BAutolock _l(this);
247a0795c6fSMarcus Overhagen	return m_view->armTip(
248a0795c6fSMarcus Overhagen	  screenRect, text, offsetMode, offset, flags);
249a0795c6fSMarcus Overhagen}
250a0795c6fSMarcus Overhagen
251a0795c6fSMarcus Overhagen// [e.moon 22oct99]
252a0795c6fSMarcus Overhagen// Call to immediately hide a visible tip.  You need to know
253a0795c6fSMarcus Overhagen// the screen rectangle for which the tip was shown (which is easy
254a0795c6fSMarcus Overhagen// if was displayed due to a showTip() call -- pass the same
255a0795c6fSMarcus Overhagen// screenRect argument.)
256a0795c6fSMarcus Overhagen// If the tip was found & hidden, returns B_OK; if there's
257a0795c6fSMarcus Overhagen// no visible tip or it was triggered by a different rectangle,
258a0795c6fSMarcus Overhagen// returns B_BAD_VALUE.
259a0795c6fSMarcus Overhagen
260a0795c6fSMarcus Overhagenstatus_t TipManager::hideTip(
261a0795c6fSMarcus Overhagen	BRect									screenRect) {
262a0795c6fSMarcus Overhagen
263a0795c6fSMarcus Overhagen	ASSERT(m_view);
264a0795c6fSMarcus Overhagen
265a0795c6fSMarcus Overhagen	BAutolock _l(this);
266a0795c6fSMarcus Overhagen	return m_view->hideTip(screenRect);
267a0795c6fSMarcus Overhagen}
268a0795c6fSMarcus Overhagen
269a0795c6fSMarcus Overhagen
270a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
271a0795c6fSMarcus Overhagen// *** BWindow
272a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
273a0795c6fSMarcus Overhagen
274a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
275a0795c6fSMarcus Overhagen// *** BLooper
276a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
277a0795c6fSMarcus Overhagen
278a0795c6fSMarcus Overhagenbool TipManager::QuitRequested() {
279a0795c6fSMarcus Overhagen	// ignored, since I receive key events bound for other apps
280a0795c6fSMarcus Overhagen	return false;
281a0795c6fSMarcus Overhagen}
282a0795c6fSMarcus Overhagen
283a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
284a0795c6fSMarcus Overhagen// *** BHandler
285a0795c6fSMarcus Overhagen// -------------------------------------------------------- //
286a0795c6fSMarcus Overhagen
287a0795c6fSMarcus Overhagenvoid TipManager::MessageReceived(
288a0795c6fSMarcus Overhagen	BMessage*							message) {
289a0795c6fSMarcus Overhagen
290a0795c6fSMarcus Overhagen	switch(message->what) {
291a0795c6fSMarcus Overhagen		default:
292a0795c6fSMarcus Overhagen			_inherited::MessageReceived(message);
293a0795c6fSMarcus Overhagen	}
294a0795c6fSMarcus Overhagen}
295a0795c6fSMarcus Overhagen
296a0795c6fSMarcus Overhagen//// -------------------------------------------------------- //
297a0795c6fSMarcus Overhagen//// BasicThread impl.
298a0795c6fSMarcus Overhagen//// -------------------------------------------------------- //
299a0795c6fSMarcus Overhagen//
300a0795c6fSMarcus Overhagen//// +++++
301a0795c6fSMarcus Overhagen//// 12aug99: a locking bug seems to cause occasional
302a0795c6fSMarcus Overhagen////          crashes on shutdown after the looper's been deleted.
303a0795c6fSMarcus Overhagen//// +++++
304a0795c6fSMarcus Overhagen//// 23sep99: probably fixed; the TipManager needs to be manually
305a0795c6fSMarcus Overhagen////          killed before the window is deleted.
306a0795c6fSMarcus Overhagen//
307a0795c6fSMarcus Overhagen//void TipManager::run() {
308a0795c6fSMarcus Overhagen//
309a0795c6fSMarcus Overhagen//	BPoint point, lastPoint, screenPoint;
310a0795c6fSMarcus Overhagen//	bigtime_t curTime, lastTime;
311a0795c6fSMarcus Overhagen//	uint32 buttons;
312a0795c6fSMarcus Overhagen//
313a0795c6fSMarcus Overhagen//	bool bTipVisible = false;
314a0795c6fSMarcus Overhagen//	BRect tipScreenRect;
315a0795c6fSMarcus Overhagen//
316a0795c6fSMarcus Overhagen//	lastTime = 0;
317a0795c6fSMarcus Overhagen//	curTime = 0;
318a0795c6fSMarcus Overhagen//
319a0795c6fSMarcus Overhagen//	// [e.moon 27sep99]
320a0795c6fSMarcus Overhagen//	// store whether the tip has fired at the current point
321a0795c6fSMarcus Overhagen//	bool fired = false;
322a0795c6fSMarcus Overhagen//
323a0795c6fSMarcus Overhagen//	ASSERT(m_tree);
324a0795c6fSMarcus Overhagen//	BView* pOwningView = m_tree->target();
325a0795c6fSMarcus Overhagen//
326a0795c6fSMarcus Overhagen//	while(!stopping()) {
327a0795c6fSMarcus Overhagen//		snooze(s_sleepPeriod);
328a0795c6fSMarcus Overhagen//		if(stopping())
329a0795c6fSMarcus Overhagen//			break;
330a0795c6fSMarcus Overhagen//
331a0795c6fSMarcus Overhagen//		// wait for the view to show up
332a0795c6fSMarcus Overhagen//		if(!pOwningView->Parent() || !pOwningView->Window())
333a0795c6fSMarcus Overhagen//			continue;
334a0795c6fSMarcus Overhagen//
335a0795c6fSMarcus Overhagen//		// get current mouse position
336a0795c6fSMarcus Overhagen//		pOwningView->LockLooper();
337a0795c6fSMarcus Overhagen//
338a0795c6fSMarcus Overhagen//		pOwningView->GetMouse(&point, &buttons, false);
339a0795c6fSMarcus Overhagen//		screenPoint = pOwningView->ConvertToScreen(point);
340a0795c6fSMarcus Overhagen//
341a0795c6fSMarcus Overhagen//		pOwningView->UnlockLooper();
342a0795c6fSMarcus Overhagen//
343a0795c6fSMarcus Overhagen//		// has it been sitting in one place long enough?
344a0795c6fSMarcus Overhagen//		bool bMoved = (point != lastPoint);
345a0795c6fSMarcus Overhagen//
346a0795c6fSMarcus Overhagen//		if(bMoved) {
347a0795c6fSMarcus Overhagen//			lastTime = curTime;
348a0795c6fSMarcus Overhagen//			fired = false;
349a0795c6fSMarcus Overhagen//		}
350a0795c6fSMarcus Overhagen//		else if(fired) {
351a0795c6fSMarcus Overhagen//			// [27sep99 e.moon] the tip has already fired, and
352a0795c6fSMarcus Overhagen//			// the mouse hasn't moved; bail out now
353a0795c6fSMarcus Overhagen//			continue;
354a0795c6fSMarcus Overhagen//		}
355a0795c6fSMarcus Overhagen//
356a0795c6fSMarcus Overhagen//		curTime = system_time();
357a0795c6fSMarcus Overhagen//		bool bIdle = !bMoved && lastTime && (curTime - lastTime) > m_idleTime;
358a0795c6fSMarcus Overhagen//		lastPoint = point;
359a0795c6fSMarcus Overhagen//
360a0795c6fSMarcus Overhagen//		if(bTipVisible) {
361a0795c6fSMarcus Overhagen//			// hide tip once mouse moves outside its rectangle
362a0795c6fSMarcus Overhagen//			if(!tipScreenRect.Contains(screenPoint)) {
363a0795c6fSMarcus Overhagen//				m_tipWindow->Lock();
364a0795c6fSMarcus Overhagen//				if(!m_tipWindow->IsHidden()) // tip may hide itself [7sep99]
365a0795c6fSMarcus Overhagen//					m_tipWindow->Hide();
366a0795c6fSMarcus Overhagen//				bTipVisible = false;
367a0795c6fSMarcus Overhagen//				m_tipWindow->Unlock();
368a0795c6fSMarcus Overhagen//			}
369a0795c6fSMarcus Overhagen//		} else if(bIdle) {
370a0795c6fSMarcus Overhagen//
371a0795c6fSMarcus Overhagen//			// mouse has idled at a given point long enough;
372a0795c6fSMarcus Overhagen//			// look for a tip at that position and display one if found:
373a0795c6fSMarcus Overhagen//
374a0795c6fSMarcus Overhagen//			fired = true;
375a0795c6fSMarcus Overhagen//
376a0795c6fSMarcus Overhagen//			pOwningView->LockLooper();
377a0795c6fSMarcus Overhagen//
378a0795c6fSMarcus Overhagen//			// make sure this part of the view is actually visible
379a0795c6fSMarcus Overhagen//			if(!pOwningView->Window()->Frame().Contains(screenPoint)) {
380a0795c6fSMarcus Overhagen//				pOwningView->UnlockLooper();
381a0795c6fSMarcus Overhagen//				continue;
382a0795c6fSMarcus Overhagen//			}
383a0795c6fSMarcus Overhagen//
384a0795c6fSMarcus Overhagen//			// look for a tip under the mouse
385a0795c6fSMarcus Overhagen//			m_tipWindow->Lock();
386a0795c6fSMarcus Overhagen//			pair<BView*, const tip_entry*> found =
387a0795c6fSMarcus Overhagen//				m_tree->match(point, screenPoint);
388a0795c6fSMarcus Overhagen//
389a0795c6fSMarcus Overhagen//			if(!found.second) {
390a0795c6fSMarcus Overhagen//				// none found; move on
391a0795c6fSMarcus Overhagen//				pOwningView->UnlockLooper();
392a0795c6fSMarcus Overhagen//				m_tipWindow->Unlock();
393a0795c6fSMarcus Overhagen//				continue;
394a0795c6fSMarcus Overhagen//			}
395a0795c6fSMarcus Overhagen//
396a0795c6fSMarcus Overhagen//			BView* pTipTarget = found.first;
397a0795c6fSMarcus Overhagen//			const tip_entry& entry = *found.second;
398a0795c6fSMarcus Overhagen//
399a0795c6fSMarcus Overhagen//			// test the screen point against the view's clipping region;
400a0795c6fSMarcus Overhagen//			// if no match, the given point is likely covered by another
401a0795c6fSMarcus Overhagen//			// window (so stop recursing)
402a0795c6fSMarcus Overhagen//
403a0795c6fSMarcus Overhagen//			BRegion clipRegion;
404a0795c6fSMarcus Overhagen//			pTipTarget->GetClippingRegion(&clipRegion);
405a0795c6fSMarcus Overhagen//			if(!clipRegion.Contains(
406a0795c6fSMarcus Overhagen//				pTipTarget->ConvertFromScreen(screenPoint))) {
407a0795c6fSMarcus Overhagen//				// move on
408a0795c6fSMarcus Overhagen//				pOwningView->UnlockLooper();
409a0795c6fSMarcus Overhagen//				m_tipWindow->Unlock();
410a0795c6fSMarcus Overhagen//				continue;
411a0795c6fSMarcus Overhagen//			}
412a0795c6fSMarcus Overhagen//
413a0795c6fSMarcus Overhagen//			// found one; set up the tip window:
414a0795c6fSMarcus Overhagen//			BRect entryFrame = pTipTarget->ConvertToScreen(entry.rect);
415a0795c6fSMarcus Overhagen//
416a0795c6fSMarcus Overhagen//			// set text (this has the side effect of resizing the
417a0795c6fSMarcus Overhagen//			// window)
418a0795c6fSMarcus Overhagen//
419a0795c6fSMarcus Overhagen//			ASSERT(m_tipWindow);
420a0795c6fSMarcus Overhagen//			m_tipWindow->setText(entry.text.String());
421a0795c6fSMarcus Overhagen//
422a0795c6fSMarcus Overhagen//			// figure out where to display it:
423a0795c6fSMarcus Overhagen//
424a0795c6fSMarcus Overhagen//			BPoint offset = (entry.offset == s_useDefaultOffset) ?
425a0795c6fSMarcus Overhagen//				s_defaultOffset :
426a0795c6fSMarcus Overhagen//				entry.offset;
427a0795c6fSMarcus Overhagen//
428a0795c6fSMarcus Overhagen//			BPoint p;
429a0795c6fSMarcus Overhagen//			switch(entry.offsetMode) {
430a0795c6fSMarcus Overhagen//				case LEFT_OFFSET_FROM_RECT:
431a0795c6fSMarcus Overhagen//					p = entryFrame.RightTop() + offset;
432a0795c6fSMarcus Overhagen//					break;
433a0795c6fSMarcus Overhagen//				case LEFT_OFFSET_FROM_POINTER:
434a0795c6fSMarcus Overhagen//					p = screenPoint + offset;
435a0795c6fSMarcus Overhagen//					break;
436a0795c6fSMarcus Overhagen//				case RIGHT_OFFSET_FROM_RECT:
437a0795c6fSMarcus Overhagen//					p = entryFrame.LeftTop();
438a0795c6fSMarcus Overhagen//					p.x -= offset.x;
439a0795c6fSMarcus Overhagen//					p.y += offset.y;
440a0795c6fSMarcus Overhagen//					p.x -= m_tipWindow->Frame().Width();
441a0795c6fSMarcus Overhagen//					break;
442a0795c6fSMarcus Overhagen//				case RIGHT_OFFSET_FROM_POINTER:
443a0795c6fSMarcus Overhagen//					p = screenPoint;
444a0795c6fSMarcus Overhagen//					p.x -= offset.x;
445a0795c6fSMarcus Overhagen//					p.y += offset.y;
446a0795c6fSMarcus Overhagen//					p.x -= m_tipWindow->Frame().Width();
447a0795c6fSMarcus Overhagen//					break;
448a0795c6fSMarcus Overhagen//				default:
449a0795c6fSMarcus Overhagen//					ASSERT(!"bad offset mode");
450a0795c6fSMarcus Overhagen//			}
451a0795c6fSMarcus Overhagen//
452a0795c6fSMarcus Overhagen//			// do it:
453a0795c6fSMarcus Overhagen//
454a0795c6fSMarcus Overhagen//			m_tipWindow->MoveTo(p);
455a0795c6fSMarcus Overhagen//			m_tipWindow->Show();
456a0795c6fSMarcus Overhagen//
457a0795c6fSMarcus Overhagen//			bTipVisible = true;
458a0795c6fSMarcus Overhagen//			tipScreenRect = entryFrame;
459a0795c6fSMarcus Overhagen//
460a0795c6fSMarcus Overhagen//			m_tipWindow->Unlock();
461a0795c6fSMarcus Overhagen//			pOwningView->UnlockLooper();
462a0795c6fSMarcus Overhagen//
463a0795c6fSMarcus Overhagen//		} // if(bIdle ...
464a0795c6fSMarcus Overhagen//	} // while(!stopping ...
465a0795c6fSMarcus Overhagen//}
466a0795c6fSMarcus Overhagen
467a0795c6fSMarcus Overhagen// END -- TipManager.cpp --
468a0795c6fSMarcus Overhagen
469