2 * Copyright (c) 1999-2000, Eric Moon.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions, and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include "TipManager.h"
36 #include "TipManagerImpl.h"
37 #include "TipWindow.h"
41 #include <MessageFilter.h>
45 #include "debug_tools.h"
47 __USE_CORTEX_NAMESPACE
49 // -------------------------------------------------------- //
51 // -------------------------------------------------------- //
53 // static instance (created on first call to TipManager::Instance().)
54 TipManager
* TipManager::s_instance
= 0;
55 BLocker
TipManager::s_instanceLock("TipManager::s_instanceLock");
57 // special point value set to highly improbable position
58 const BPoint
TipManager::s_useDefaultOffset(FLT_MIN
, FLT_MIN
);
60 // default tip position
61 const BPoint
TipManager::s_defaultOffset(8.0, 8.0);
63 const bigtime_t
TipManager::s_defIdleTime
= 750000LL;
64 const bigtime_t
TipManager::s_sleepPeriod
= 250000LL;
66 // -------------------------------------------------------- //
68 // -------------------------------------------------------- //
70 filter_result
ignore_quit_key(
73 BMessageFilter
* filter
)
80 if((modifiers() & B_COMMAND_KEY
))
83 message
->FindInt8("byte", &key
);
85 return B_SKIP_MESSAGE
;
90 return B_DISPATCH_MESSAGE
;
93 // -------------------------------------------------------- //
95 // -------------------------------------------------------- //
97 TipManager::~TipManager() {}
99 // -------------------------------------------------------- //
100 // *** singleton access
101 // -------------------------------------------------------- //
104 TipManager
* TipManager::Instance() {
105 BAutolock
_l(s_instanceLock
);
107 s_instance
= new TipManager();
112 // kill current instance if any
114 void TipManager::QuitInstance() {
115 BAutolock
_l(s_instanceLock
);
123 // -------------------------------------------------------- //
124 // hidden constructor (use Instance() to access
125 // a single instance)
126 // -------------------------------------------------------- //
128 TipManager::TipManager() :
131 BRect(-100,-100,-100,-100),
133 B_NO_BORDER_WINDOW_LOOK
,
134 B_FLOATING_ALL_WINDOW_FEEL
,
135 B_ASYNCHRONOUS_CONTROLS
| B_AVOID_FOCUS
),
140 B_PROGRAMMED_DELIVERY
,
144 m_view
= new _TipManagerView(
151 // start the window thread
156 // -------------------------------------------------------- //
157 // add and remove tips
158 // -------------------------------------------------------- //
160 // add or modify a tip:
162 status_t
TipManager::setTip(
166 offset_mode_t offsetMode
/*=LEFT_OFFSET_FROM_RECT*/,
167 BPoint offset
/*=s_useDefaultOffset*/,
168 uint32 flags
/*=NONE*/) {
174 return m_view
->setTip(
175 rect
, text
, view
, offsetMode
, offset
, flags
);
179 status_t
TipManager::setTip(
182 offset_mode_t offsetMode
/*=LEFT_OFFSET_FROM_RECT*/,
183 BPoint offset
/*=s_useDefaultOffset*/,
184 uint32 flags
/*=NONE*/) {
187 BRect(), text
, view
, offsetMode
, offset
, flags
);
190 // Remove all tips matching the given rectangle and/or child
191 // view. Returns the number of tips removed.
193 status_t
TipManager::removeTip(
201 return m_view
->removeTip(rect
, view
);
204 // If more than one tip is mapped to pChild, all are removed:
206 status_t
TipManager::removeAll(
209 return removeTip(BRect(), view
);
212 status_t
TipManager::removeAll(
216 // "### TipManager::removeAll(): %p, %p\n", this, m_view->Looper()));
220 ASSERT(m_view
->Looper() == this); // +++++
223 return m_view
->removeAll(window
);
226 // -------------------------------------------------------- //
227 // *** manual tip arming
228 // -------------------------------------------------------- //
231 // Call when the mouse has entered a particular region of
232 // the screen for which you want a tip to be displayed.
233 // The tip will be displayed if the mouse stops moving
234 // for idleTime microseconds within the rectangle screenRect.
236 status_t
TipManager::showTip(
239 offset_mode_t offsetMode
/*=LEFT_OFFSET_FROM_RECT*/,
240 BPoint offset
/*=s_useDefaultOffset*/,
241 uint32 flags
/*=NONE*/) {
247 return m_view
->armTip(
248 screenRect
, text
, offsetMode
, offset
, flags
);
252 // Call to immediately hide a visible tip. You need to know
253 // the screen rectangle for which the tip was shown (which is easy
254 // if was displayed due to a showTip() call -- pass the same
255 // screenRect argument.)
256 // If the tip was found & hidden, returns B_OK; if there's
257 // no visible tip or it was triggered by a different rectangle,
258 // returns B_BAD_VALUE.
260 status_t
TipManager::hideTip(
266 return m_view
->hideTip(screenRect
);
270 // -------------------------------------------------------- //
272 // -------------------------------------------------------- //
274 // -------------------------------------------------------- //
276 // -------------------------------------------------------- //
278 bool TipManager::QuitRequested() {
279 // ignored, since I receive key events bound for other apps
283 // -------------------------------------------------------- //
285 // -------------------------------------------------------- //
287 void TipManager::MessageReceived(
290 switch(message
->what
) {
292 _inherited::MessageReceived(message
);
296 //// -------------------------------------------------------- //
297 //// BasicThread impl.
298 //// -------------------------------------------------------- //
301 //// 12aug99: a locking bug seems to cause occasional
302 //// crashes on shutdown after the looper's been deleted.
304 //// 23sep99: probably fixed; the TipManager needs to be manually
305 //// killed before the window is deleted.
307 //void TipManager::run() {
309 // BPoint point, lastPoint, screenPoint;
310 // bigtime_t curTime, lastTime;
313 // bool bTipVisible = false;
314 // BRect tipScreenRect;
319 // // [e.moon 27sep99]
320 // // store whether the tip has fired at the current point
321 // bool fired = false;
324 // BView* pOwningView = m_tree->target();
326 // while(!stopping()) {
327 // snooze(s_sleepPeriod);
331 // // wait for the view to show up
332 // if(!pOwningView->Parent() || !pOwningView->Window())
335 // // get current mouse position
336 // pOwningView->LockLooper();
338 // pOwningView->GetMouse(&point, &buttons, false);
339 // screenPoint = pOwningView->ConvertToScreen(point);
341 // pOwningView->UnlockLooper();
343 // // has it been sitting in one place long enough?
344 // bool bMoved = (point != lastPoint);
347 // lastTime = curTime;
351 // // [27sep99 e.moon] the tip has already fired, and
352 // // the mouse hasn't moved; bail out now
356 // curTime = system_time();
357 // bool bIdle = !bMoved && lastTime && (curTime - lastTime) > m_idleTime;
358 // lastPoint = point;
361 // // hide tip once mouse moves outside its rectangle
362 // if(!tipScreenRect.Contains(screenPoint)) {
363 // m_tipWindow->Lock();
364 // if(!m_tipWindow->IsHidden()) // tip may hide itself [7sep99]
365 // m_tipWindow->Hide();
366 // bTipVisible = false;
367 // m_tipWindow->Unlock();
369 // } else if(bIdle) {
371 // // mouse has idled at a given point long enough;
372 // // look for a tip at that position and display one if found:
376 // pOwningView->LockLooper();
378 // // make sure this part of the view is actually visible
379 // if(!pOwningView->Window()->Frame().Contains(screenPoint)) {
380 // pOwningView->UnlockLooper();
384 // // look for a tip under the mouse
385 // m_tipWindow->Lock();
386 // pair<BView*, const tip_entry*> found =
387 // m_tree->match(point, screenPoint);
389 // if(!found.second) {
390 // // none found; move on
391 // pOwningView->UnlockLooper();
392 // m_tipWindow->Unlock();
396 // BView* pTipTarget = found.first;
397 // const tip_entry& entry = *found.second;
399 // // test the screen point against the view's clipping region;
400 // // if no match, the given point is likely covered by another
401 // // window (so stop recursing)
403 // BRegion clipRegion;
404 // pTipTarget->GetClippingRegion(&clipRegion);
405 // if(!clipRegion.Contains(
406 // pTipTarget->ConvertFromScreen(screenPoint))) {
408 // pOwningView->UnlockLooper();
409 // m_tipWindow->Unlock();
413 // // found one; set up the tip window:
414 // BRect entryFrame = pTipTarget->ConvertToScreen(entry.rect);
416 // // set text (this has the side effect of resizing the
419 // ASSERT(m_tipWindow);
420 // m_tipWindow->setText(entry.text.String());
422 // // figure out where to display it:
424 // BPoint offset = (entry.offset == s_useDefaultOffset) ?
429 // switch(entry.offsetMode) {
430 // case LEFT_OFFSET_FROM_RECT:
431 // p = entryFrame.RightTop() + offset;
433 // case LEFT_OFFSET_FROM_POINTER:
434 // p = screenPoint + offset;
436 // case RIGHT_OFFSET_FROM_RECT:
437 // p = entryFrame.LeftTop();
440 // p.x -= m_tipWindow->Frame().Width();
442 // case RIGHT_OFFSET_FROM_POINTER:
446 // p.x -= m_tipWindow->Frame().Width();
449 // ASSERT(!"bad offset mode");
454 // m_tipWindow->MoveTo(p);
455 // m_tipWindow->Show();
457 // bTipVisible = true;
458 // tipScreenRect = entryFrame;
460 // m_tipWindow->Unlock();
461 // pOwningView->UnlockLooper();
464 // } // while(!stopping ...
467 // END -- TipManager.cpp --