* Copyright 2011, Axel DΓΆrfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#include "CaptureWindow.h"
#include <stdio.h>
#include <Roster.h>
#include <Screen.h>
#include "Switcher.h"
static const bigtime_t kUpdateDelay = 50000;
class CaptureView : public BView {
public:
CaptureView();
virtual ~CaptureView();
void AddMoveOutNotification(BMessage* message);
virtual void MouseMoved(BPoint point, uint32 transit,
const BMessage* dragMessage);
virtual void KeyDown(const char* bytes, int32 numBytes);
private:
void _UpdateLast(const BPoint& point);
void _Notify(uint32 location, team_id team);
void _SendMovedOutNotification();
static team_id _CurrentTeam();
private:
uint32 fModifierMask;
BPoint fLastPoint;
team_id fLastTeam;
bigtime_t fLastEvent;
uint32 fMovedOutWhat;
BMessenger fMovedOutMessenger;
BRect fMovedOutFrame;
};
CaptureView::CaptureView()
:
BView("main", 0),
fModifierMask(B_CONTROL_KEY),
fMovedOutWhat(0)
{
SetEventMask(B_POINTER_EVENTS | B_KEYBOARD_EVENTS, B_NO_POINTER_HISTORY);
_UpdateLast(BPoint(-1, -1));
}
CaptureView::~CaptureView()
{
}
void
CaptureView::AddMoveOutNotification(BMessage* message)
{
if (fMovedOutWhat != 0)
_SendMovedOutNotification();
if (message->FindMessenger("target", &fMovedOutMessenger) == B_OK
&& message->FindRect("frame", &fMovedOutFrame) == B_OK)
fMovedOutWhat = (uint32)message->FindInt32("what");
}
void
CaptureView::MouseMoved(BPoint point, uint32 transit,
const BMessage* dragMessage)
{
ConvertToScreen(&point);
if (fMovedOutWhat != 0 && !fMovedOutFrame.Contains(point))
_SendMovedOutNotification();
uint32 modifiers = ::modifiers();
if ((modifiers & fModifierMask) == 0) {
_UpdateLast(point);
return;
}
BScreen screen;
BRect screenFrame = screen.Frame();
uint32 location = kNowhere;
if (point.x <= screenFrame.left && fLastPoint.x > screenFrame.left)
location = kLeftEdge;
else if (point.x >= screenFrame.right && fLastPoint.x < screenFrame.right)
location = kRightEdge;
else if (point.y <= screenFrame.top && fLastPoint.y > screenFrame.top)
location = kTopEdge;
else if (point.y >= screenFrame.bottom && fLastPoint.y < screenFrame.bottom)
location = kBottomEdge;
if (location != kNowhere)
_Notify(location, fLastTeam);
_UpdateLast(point);
}
void
CaptureView::KeyDown(const char* bytes, int32 numBytes)
{
if ((::modifiers() & (B_CONTROL_KEY | B_SHIFT_KEY | B_OPTION_KEY
| B_COMMAND_KEY)) != (B_COMMAND_KEY | B_CONTROL_KEY))
return;
uint32 location = kNowhere;
switch (bytes[0]) {
case '1':
location = kLeftEdge;
break;
case '2':
location = kRightEdge;
break;
case '3':
location = kTopEdge;
break;
case '4':
location = kBottomEdge;
break;
}
if (location != kNowhere)
_Notify(location, _CurrentTeam());
}
void
CaptureView::_UpdateLast(const BPoint& point)
{
fLastPoint = point;
bigtime_t now = system_time();
if (now > fLastEvent + kUpdateDelay)
fLastTeam = _CurrentTeam();
fLastEvent = now;
}
void
CaptureView::_Notify(uint32 location, team_id team)
{
if (location == kNowhere)
return;
BMessage message(kMsgLocationTrigger);
message.AddInt32("location", location);
message.AddInt32("team", team);
be_app->PostMessage(&message);
}
void
CaptureView::_SendMovedOutNotification()
{
BMessage movedOut(fMovedOutWhat);
fMovedOutMessenger.SendMessage(&movedOut);
fMovedOutWhat = 0;
}
team_id
CaptureView::_CurrentTeam()
{
app_info appInfo;
status_t status = be_roster->GetActiveAppInfo(&appInfo);
if (status == B_OK)
return appInfo.team;
return status;
}
CaptureWindow::CaptureWindow()
:
BWindow(BRect(0, 0, 100, 100), "mouse capture", B_NO_BORDER_WINDOW_LOOK,
B_NORMAL_WINDOW_FEEL, B_ASYNCHRONOUS_CONTROLS, B_ALL_WORKSPACES)
{
fCaptureView = new CaptureView();
AddChild(fCaptureView);
}
CaptureWindow::~CaptureWindow()
{
}
void
CaptureWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgHideWhenMouseMovedOut:
fCaptureView->AddMoveOutNotification(message);
break;
default:
BWindow::MessageReceived(message);
break;
}
}