* Early work in progress of toying around with the idea to show some useful
panels when touching the screen border with the mouse while holding down the CTRL key. * Right now, a simple running applications list is shown on the top/bottom, and a list of the windows of the current app on the left/right edge which you can click to front. * Imagine you could configure this to show various panels like a shelf, a query window, workspaces, recent files, favourite files, folder contents, have a clipboard for files, ... * Just wanted to have it in SVN even if it's only barely useful right now - I would be glad to hear your opinions on this, and if it's worthwhile to continue working on this. -alpha git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41754 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -55,6 +55,7 @@ HaikuSubInclude showimage ;
|
||||
HaikuSubInclude soundrecorder ;
|
||||
HaikuSubInclude stylededit ;
|
||||
HaikuSubInclude sudoku ;
|
||||
HaikuSubInclude switcher ;
|
||||
HaikuSubInclude terminal ;
|
||||
HaikuSubInclude text_search ;
|
||||
HaikuSubInclude tracker ;
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "ApplicationsView.h"
|
||||
|
||||
#include "LaunchButton.h"
|
||||
#include "Switcher.h"
|
||||
|
||||
|
||||
static const uint32 kMsgActivateApp = 'AcAp';
|
||||
|
||||
|
||||
ApplicationsView::ApplicationsView(uint32 location)
|
||||
:
|
||||
BGroupView((location & (kTopEdge | kBottomEdge)) != 0
|
||||
? B_HORIZONTAL : B_VERTICAL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ApplicationsView::~ApplicationsView()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ApplicationsView::AttachedToWindow()
|
||||
{
|
||||
// TODO: make this dynamic!
|
||||
|
||||
BList teamList;
|
||||
be_roster->GetAppList(&teamList);
|
||||
|
||||
for (int32 i = 0; i < teamList.CountItems(); i++) {
|
||||
app_info appInfo;
|
||||
team_id team = (team_id)teamList.ItemAt(i);
|
||||
if (be_roster->GetRunningAppInfo(team, &appInfo) == B_OK)
|
||||
_AddTeam(appInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ApplicationsView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case kMsgActivateApp:
|
||||
be_roster->ActivateApp(message->FindInt32("team"));
|
||||
break;
|
||||
|
||||
default:
|
||||
BGroupView::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ApplicationsView::_AddTeam(app_info& info)
|
||||
{
|
||||
if ((info.flags & B_BACKGROUND_APP) != 0)
|
||||
return;
|
||||
|
||||
BMessage* message = new BMessage(kMsgActivateApp);
|
||||
message->AddInt32("team", info.team);
|
||||
|
||||
LaunchButton* button = new LaunchButton(info.signature, NULL, message,
|
||||
this);
|
||||
button->SetTo(&info.ref);
|
||||
AddChild(button);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef APPLICATIONS_VIEW_H
|
||||
#define APPLICATIONS_VIEW_H
|
||||
|
||||
|
||||
#include <GroupView.h>
|
||||
#include <Roster.h>
|
||||
|
||||
|
||||
class ApplicationsView : public BGroupView {
|
||||
public:
|
||||
ApplicationsView(uint32 location);
|
||||
virtual ~ApplicationsView();
|
||||
|
||||
virtual void AttachedToWindow();
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
private:
|
||||
void _AddTeam(app_info& info);
|
||||
};
|
||||
|
||||
|
||||
#endif // APPLICATIONS_VIEW_H
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, [email protected].
|
||||
* 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;
|
||||
// 50 ms
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// TODO: we will need to iterate over all existing screens to find the
|
||||
// right one!
|
||||
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();
|
||||
|
||||
// We update the currently active application only, if the mouse did
|
||||
// not move over it for a certain time - this is necessary only for
|
||||
// focus follow mouse.
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ team_id
|
||||
CaptureView::_CurrentTeam()
|
||||
{
|
||||
app_info appInfo;
|
||||
status_t status = be_roster->GetActiveAppInfo(&appInfo);
|
||||
if (status == B_OK)
|
||||
return appInfo.team;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef CAPTURE_WINDOW_H
|
||||
#define CAPTURE_WINDOW_H
|
||||
|
||||
|
||||
#include <Window.h>
|
||||
|
||||
|
||||
class CaptureView;
|
||||
|
||||
|
||||
class CaptureWindow : public BWindow {
|
||||
public:
|
||||
CaptureWindow();
|
||||
virtual ~CaptureWindow();
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
private:
|
||||
CaptureView* fCaptureView;
|
||||
};
|
||||
|
||||
|
||||
#endif // CAPTURE_WINDOW_H
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "GroupListView.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <Window.h>
|
||||
|
||||
|
||||
class RendererLayoutItem : public BAbstractLayout {
|
||||
public:
|
||||
RendererLayoutItem(BView* owner, int32 index, void* item,
|
||||
ListItemRenderer*& renderer)
|
||||
:
|
||||
fOwner(owner),
|
||||
fIndex(index),
|
||||
fItem(item),
|
||||
fRenderer(renderer)
|
||||
{
|
||||
}
|
||||
|
||||
ListItemRenderer* Renderer() const
|
||||
{
|
||||
fRenderer->SetTo(fOwner, fItem);
|
||||
return fRenderer;
|
||||
}
|
||||
|
||||
int32 Index() const
|
||||
{
|
||||
return fIndex;
|
||||
}
|
||||
|
||||
void* Item() const
|
||||
{
|
||||
return fItem;
|
||||
}
|
||||
|
||||
virtual BSize BaseMinSize()
|
||||
{
|
||||
fRenderer->SetTo(fOwner, fItem);
|
||||
return fRenderer->MinSize();
|
||||
}
|
||||
|
||||
virtual BSize BasePreferredSize()
|
||||
{
|
||||
fRenderer->SetTo(fOwner, fItem);
|
||||
return fRenderer->PreferredSize();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void DerivedLayoutItems()
|
||||
{
|
||||
// shouldn't ever be called?
|
||||
}
|
||||
|
||||
private:
|
||||
BView* fOwner;
|
||||
int32 fIndex;
|
||||
void* fItem;
|
||||
ListItemRenderer*& fRenderer;
|
||||
};
|
||||
|
||||
|
||||
GroupListView::GroupListView(const char* name, GroupListModel* model,
|
||||
enum orientation orientation, float spacing)
|
||||
:
|
||||
BView(NULL, B_WILL_DRAW, new BGroupLayout(orientation, spacing)),
|
||||
fModel(NULL),
|
||||
fItemRenderer(NULL),
|
||||
fGroupRenderer(NULL),
|
||||
fSelectionMessage(NULL)
|
||||
{
|
||||
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
SetModel(model);
|
||||
}
|
||||
|
||||
|
||||
GroupListView::~GroupListView()
|
||||
{
|
||||
delete fModel;
|
||||
delete fItemRenderer;
|
||||
delete fGroupRenderer;
|
||||
delete fSelectionMessage;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GroupListView::SetModel(GroupListModel* model)
|
||||
{
|
||||
// TODO: remove all previous
|
||||
// TODO: add change mechanism
|
||||
// TODO: use a "virtual" BGroupLayout (ie. one that create its layout items
|
||||
// on the fly).
|
||||
fModel = model;
|
||||
|
||||
std::map<addr_t, BGroupLayout*> groupMap;
|
||||
|
||||
int32 groupCount = model->CountGroups();
|
||||
for (int groupIndex = 0; groupIndex < groupCount; groupIndex++) {
|
||||
BGroupLayout* groupItem = new BGroupLayout(B_VERTICAL, 0);
|
||||
groupItem->SetVisible(false);
|
||||
AddChild(groupItem);
|
||||
|
||||
void* group = model->GroupAt(groupIndex);
|
||||
groupMap[(addr_t)group] = groupItem;
|
||||
groupItem->AddItem(new RendererLayoutItem(this, groupIndex, group,
|
||||
fGroupRenderer));
|
||||
}
|
||||
|
||||
int32 itemCount = model->CountItems();
|
||||
for (int itemIndex = 0; itemIndex < itemCount; itemIndex++) {
|
||||
void* group = model->GroupForItemAt(itemIndex);
|
||||
if (group == NULL)
|
||||
continue;
|
||||
|
||||
BGroupLayout* groupItem = groupMap[(addr_t)group];
|
||||
if (groupItem == NULL)
|
||||
continue;
|
||||
|
||||
groupItem->SetVisible(true);
|
||||
|
||||
RendererLayoutItem* rendererItem = new RendererLayoutItem(this,
|
||||
itemIndex, model->ItemAt(itemIndex), fItemRenderer);
|
||||
groupItem->AddItem(rendererItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GroupListView::SetItemRenderer(ListItemRenderer* renderer)
|
||||
{
|
||||
fItemRenderer = renderer;
|
||||
InvalidateLayout();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GroupListView::SetGroupRenderer(ListItemRenderer* renderer)
|
||||
{
|
||||
fGroupRenderer = renderer;
|
||||
InvalidateLayout();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GroupListView::SetSelectionMessage(BMessage* message, BMessenger target)
|
||||
{
|
||||
fSelectionMessage = message;
|
||||
fSelectionTarget = target;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GroupListView::AttachedToWindow()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GroupListView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
default:
|
||||
BView::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GroupListView::MouseDown(BPoint point)
|
||||
{
|
||||
if (fSelectionMessage == NULL)
|
||||
return;
|
||||
|
||||
BLayoutItem* item = _ItemAt(GetLayout(), point);
|
||||
|
||||
if (RendererLayoutItem* rendererItem
|
||||
= dynamic_cast<RendererLayoutItem*>(item)) {
|
||||
BMessage message(*fSelectionMessage);
|
||||
|
||||
int32 buttons = 0;
|
||||
if (Window()->CurrentMessage() != NULL)
|
||||
buttons = Window()->CurrentMessage()->FindInt32("buttons");
|
||||
if (buttons != 0)
|
||||
message.AddInt32("buttons", buttons);
|
||||
message.AddInt32("index", rendererItem->Index());
|
||||
message.AddPointer(rendererItem->Renderer() == fGroupRenderer
|
||||
? "group" : "item", rendererItem->Item());
|
||||
|
||||
fSelectionTarget.SendMessage(&message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GroupListView::Draw(BRect updateRect)
|
||||
{
|
||||
_Draw(GetLayout(), updateRect);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GroupListView::_Draw(BLayoutItem* item, BRect updateRect)
|
||||
{
|
||||
if (RendererLayoutItem* rendererItem
|
||||
= dynamic_cast<RendererLayoutItem*>(item)) {
|
||||
ListItemRenderer* renderer = rendererItem->Renderer();
|
||||
renderer->Draw(this, rendererItem->Frame(), rendererItem->Index(),
|
||||
false);
|
||||
} else if (BLayout* layout = dynamic_cast<BLayout*>(item)) {
|
||||
for (int i = 0; i < layout->CountItems(); i++) {
|
||||
item = layout->ItemAt(i);
|
||||
if (!item->IsVisible() || !item->Frame().Intersects(updateRect))
|
||||
continue;
|
||||
|
||||
_Draw(item, updateRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BLayoutItem*
|
||||
GroupListView::_ItemAt(BLayoutItem* item, BPoint point)
|
||||
{
|
||||
if (RendererLayoutItem* rendererItem
|
||||
= dynamic_cast<RendererLayoutItem*>(item))
|
||||
return rendererItem;
|
||||
|
||||
if (BLayout* layout = dynamic_cast<BLayout*>(item)) {
|
||||
for (int i = 0; i < layout->CountItems(); i++) {
|
||||
item = layout->ItemAt(i);
|
||||
if (!item->IsVisible() || !item->Frame().Contains(point))
|
||||
continue;
|
||||
|
||||
return _ItemAt(item, point);
|
||||
}
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef GROUP_LIST_VIEW_H
|
||||
#define GROUP_LIST_VIEW_H
|
||||
|
||||
|
||||
#include <GroupView.h>
|
||||
#include <Roster.h>
|
||||
|
||||
|
||||
class GroupListModel {
|
||||
public:
|
||||
virtual int32 CountItems() = 0;
|
||||
virtual void* ItemAt(int32 index) = 0;
|
||||
|
||||
virtual int32 CountGroups() = 0;
|
||||
virtual void* GroupAt(int32 index) = 0;
|
||||
virtual void* GroupForItemAt(int32 index) = 0;
|
||||
};
|
||||
|
||||
|
||||
template<typename ItemType, typename GroupType>
|
||||
class TypedGroupListModel : public GroupListModel {
|
||||
public:
|
||||
virtual ItemType* ItemAt(int32 index) = 0;
|
||||
|
||||
virtual GroupType* GroupAt(int32 index) = 0;
|
||||
virtual GroupType* GroupForItemAt(int32 index) = 0;
|
||||
};
|
||||
|
||||
|
||||
class ListItemRenderer {
|
||||
public:
|
||||
virtual void SetTo(BView* owner, void* item) = 0;
|
||||
|
||||
virtual BSize MinSize() = 0;
|
||||
virtual BSize MaxSize() = 0;
|
||||
virtual BSize PreferredSize() = 0;
|
||||
|
||||
virtual void Draw(BView* owner, BRect frame, int32 index,
|
||||
bool selected) = 0;
|
||||
};
|
||||
|
||||
|
||||
class GroupListView : public BView {
|
||||
public:
|
||||
GroupListView(const char* name,
|
||||
GroupListModel* model = NULL,
|
||||
enum orientation orientation = B_VERTICAL,
|
||||
float spacing = 0);
|
||||
virtual ~GroupListView();
|
||||
|
||||
GroupListModel* Model() const
|
||||
{ return fModel; }
|
||||
virtual void SetModel(GroupListModel* model);
|
||||
|
||||
ListItemRenderer* ItemRenderer() const
|
||||
{ return fItemRenderer; }
|
||||
virtual void SetItemRenderer(ListItemRenderer* renderer);
|
||||
ListItemRenderer* GroupRenderer() const
|
||||
{ return fGroupRenderer; }
|
||||
virtual void SetGroupRenderer(ListItemRenderer* renderer);
|
||||
|
||||
BMessage* SelectionMessage() const
|
||||
{ return fSelectionMessage; }
|
||||
virtual void SetSelectionMessage(BMessage* message,
|
||||
BMessenger target);
|
||||
|
||||
virtual void AttachedToWindow();
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual void MouseDown(BPoint point);
|
||||
virtual void Draw(BRect updateRect);
|
||||
|
||||
private:
|
||||
void _Draw(BLayoutItem* item, BRect updateRect);
|
||||
BLayoutItem* _ItemAt(BLayoutItem* item, BPoint point);
|
||||
|
||||
private:
|
||||
GroupListModel* fModel;
|
||||
ListItemRenderer* fItemRenderer;
|
||||
ListItemRenderer* fGroupRenderer;
|
||||
|
||||
BMessage* fSelectionMessage;
|
||||
BMessenger fSelectionTarget;
|
||||
};
|
||||
|
||||
|
||||
#endif // GROUP_LIST_VIEW_H
|
||||
@@ -0,0 +1,16 @@
|
||||
SubDir HAIKU_TOP src apps switcher ;
|
||||
|
||||
UsePrivateHeaders app interface shared ;
|
||||
|
||||
Application Switcher :
|
||||
ApplicationsView.cpp
|
||||
CaptureWindow.cpp
|
||||
GroupListView.cpp
|
||||
LaunchButton.cpp
|
||||
PanelWindow.cpp
|
||||
Switcher.cpp
|
||||
WindowsView.cpp
|
||||
|
||||
: be translation $(TARGET_LIBSUPC++) $(HAIKU_LOCALE_LIBS) libshared.a
|
||||
: Switcher.rdef
|
||||
;
|
||||
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
* Copyright 2006-2009, Stephan Aßmus <[email protected]>
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "LaunchButton.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <AppDefs.h>
|
||||
#include <AppFileInfo.h>
|
||||
#include <Application.h>
|
||||
#include <Bitmap.h>
|
||||
#include <Catalog.h>
|
||||
#include <File.h>
|
||||
#include <Node.h>
|
||||
#include <NodeInfo.h>
|
||||
#include <Region.h>
|
||||
#include <Roster.h>
|
||||
#include <Window.h>
|
||||
|
||||
|
||||
#define DEFAULT_ICON_SIZE 64
|
||||
|
||||
#undef B_TRANSLATE_CONTEXT
|
||||
#define B_TRANSLATE_CONTEXT "LaunchBox"
|
||||
|
||||
|
||||
static const float kDragStartDist = 10.0;
|
||||
static const float kDragBitmapAlphaScale = 0.6;
|
||||
|
||||
|
||||
bigtime_t LaunchButton::sClickSpeed = 0;
|
||||
bool LaunchButton::sIgnoreDoubleClick = true;
|
||||
|
||||
|
||||
LaunchButton::LaunchButton(const char* name, const char* label,
|
||||
BMessage* message, BHandler* target)
|
||||
:
|
||||
BIconButton(name, label, message, target),
|
||||
fRef(NULL),
|
||||
fAppSig(NULL),
|
||||
fDescription(""),
|
||||
fAnticipatingDrop(false),
|
||||
fLastClickTime(0),
|
||||
fIconSize(DEFAULT_ICON_SIZE)
|
||||
{
|
||||
if (sClickSpeed == 0 || get_click_speed(&sClickSpeed) != B_OK)
|
||||
sClickSpeed = 500000;
|
||||
}
|
||||
|
||||
|
||||
LaunchButton::~LaunchButton()
|
||||
{
|
||||
delete fRef;
|
||||
free(fAppSig);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LaunchButton::AttachedToWindow()
|
||||
{
|
||||
BIconButton::AttachedToWindow();
|
||||
_UpdateToolTip();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LaunchButton::Draw(BRect updateRect)
|
||||
{
|
||||
if (fAnticipatingDrop) {
|
||||
rgb_color color = fRef ? ui_color(B_KEYBOARD_NAVIGATION_COLOR)
|
||||
: (rgb_color){ 0, 130, 60, 255 };
|
||||
SetHighColor(color);
|
||||
// limit clipping region to exclude the blue rect we just drew
|
||||
BRect r(Bounds());
|
||||
StrokeRect(r);
|
||||
r.InsetBy(1.0, 1.0);
|
||||
BRegion region(r);
|
||||
ConstrainClippingRegion(®ion);
|
||||
}
|
||||
if (IsValid()) {
|
||||
BIconButton::Draw(updateRect);
|
||||
} else {
|
||||
rgb_color background = LowColor();
|
||||
rgb_color lightShadow = tint_color(background,
|
||||
(B_NO_TINT + B_DARKEN_1_TINT) / 2.0);
|
||||
rgb_color shadow = tint_color(background, B_DARKEN_1_TINT);
|
||||
rgb_color light = tint_color(background, B_LIGHTEN_1_TINT);
|
||||
BRect r(Bounds());
|
||||
_DrawFrame(r, shadow, light, lightShadow, lightShadow);
|
||||
r.InsetBy(2.0, 2.0);
|
||||
SetHighColor(lightShadow);
|
||||
FillRect(r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LaunchButton::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case B_SIMPLE_DATA:
|
||||
case B_REFS_RECEIVED: {
|
||||
entry_ref ref;
|
||||
if (message->FindRef("refs", &ref) == B_OK) {
|
||||
if (fRef) {
|
||||
if (ref != *fRef) {
|
||||
BEntry entry(fRef, true);
|
||||
if (entry.IsDirectory()) {
|
||||
message->PrintToStream();
|
||||
// copy stuff into the directory
|
||||
} else {
|
||||
message->what = B_REFS_RECEIVED;
|
||||
team_id team;
|
||||
if (fAppSig)
|
||||
team = be_roster->TeamFor(fAppSig);
|
||||
else
|
||||
team = be_roster->TeamFor(fRef);
|
||||
if (team < 0) {
|
||||
if (fAppSig)
|
||||
be_roster->Launch(fAppSig, message, &team);
|
||||
else
|
||||
be_roster->Launch(fRef, message, &team);
|
||||
} else {
|
||||
app_info appInfo;
|
||||
if (team >= 0
|
||||
&& be_roster->GetRunningAppInfo(team,
|
||||
&appInfo) == B_OK) {
|
||||
BMessenger messenger(appInfo.signature,
|
||||
team);
|
||||
if (messenger.IsValid())
|
||||
messenger.SendMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SetTo(&ref);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case B_PASTE:
|
||||
case B_MODIFIERS_CHANGED:
|
||||
default:
|
||||
BIconButton::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LaunchButton::MouseDown(BPoint where)
|
||||
{
|
||||
bigtime_t now = system_time();
|
||||
bool callInherited = true;
|
||||
if (sIgnoreDoubleClick && now - fLastClickTime < sClickSpeed)
|
||||
callInherited = false;
|
||||
fLastClickTime = now;
|
||||
if (BMessage* message = Window()->CurrentMessage()) {
|
||||
uint32 buttons;
|
||||
message->FindInt32("buttons", (int32*)&buttons);
|
||||
if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0 && IsInside()) {
|
||||
// context menu?
|
||||
} else
|
||||
fDragStart = where;
|
||||
}
|
||||
if (callInherited)
|
||||
BIconButton::MouseDown(where);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LaunchButton::MouseUp(BPoint where)
|
||||
{
|
||||
if (fAnticipatingDrop) {
|
||||
fAnticipatingDrop = false;
|
||||
Invalidate();
|
||||
}
|
||||
BIconButton::MouseUp(where);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LaunchButton::MouseMoved(BPoint where, uint32 transit,
|
||||
const BMessage* dragMessage)
|
||||
{
|
||||
if ((dragMessage && (transit == B_ENTERED_VIEW || transit == B_INSIDE_VIEW))
|
||||
&& ((dragMessage->what == B_SIMPLE_DATA
|
||||
|| dragMessage->what == B_REFS_RECEIVED) || fRef)) {
|
||||
if (!fAnticipatingDrop) {
|
||||
fAnticipatingDrop = true;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
if (!dragMessage || (transit == B_EXITED_VIEW || transit == B_OUTSIDE_VIEW)) {
|
||||
if (fAnticipatingDrop) {
|
||||
fAnticipatingDrop = false;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
BIconButton::MouseMoved(where, transit, dragMessage);
|
||||
}
|
||||
|
||||
|
||||
BSize
|
||||
LaunchButton::MinSize()
|
||||
{
|
||||
return PreferredSize();
|
||||
}
|
||||
|
||||
|
||||
BSize
|
||||
LaunchButton::PreferredSize()
|
||||
{
|
||||
float minWidth = fIconSize;
|
||||
float minHeight = fIconSize;
|
||||
|
||||
float hPadding = max_c(6.0, ceilf(minHeight / 3.0));
|
||||
float vPadding = max_c(6.0, ceilf(minWidth / 3.0));
|
||||
|
||||
if (Label() != NULL && Label()[0] != '\0') {
|
||||
font_height fh;
|
||||
GetFontHeight(&fh);
|
||||
minHeight += ceilf(fh.ascent + fh.descent) + vPadding;
|
||||
minWidth += StringWidth(Label()) + vPadding;
|
||||
}
|
||||
|
||||
return BSize(minWidth + hPadding, minHeight + vPadding);
|
||||
}
|
||||
|
||||
|
||||
BSize
|
||||
LaunchButton::MaxSize()
|
||||
{
|
||||
return PreferredSize();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
LaunchButton::SetTo(const entry_ref* ref)
|
||||
{
|
||||
free(fAppSig);
|
||||
fAppSig = NULL;
|
||||
|
||||
delete fRef;
|
||||
if (ref) {
|
||||
fRef = new entry_ref(*ref);
|
||||
// follow links
|
||||
BEntry entry(fRef, true);
|
||||
entry.GetRef(fRef);
|
||||
|
||||
_UpdateIcon(fRef);
|
||||
// see if this is an application
|
||||
BFile file(ref, B_READ_ONLY);
|
||||
BAppFileInfo info;
|
||||
if (info.SetTo(&file) == B_OK) {
|
||||
char mimeSig[B_MIME_TYPE_LENGTH];
|
||||
if (info.GetSignature(mimeSig) == B_OK) {
|
||||
SetTo(mimeSig, false);
|
||||
} else {
|
||||
fprintf(stderr, "no MIME signature for '%s'\n", fRef->name);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "no BAppFileInfo for '%s'\n", fRef->name);
|
||||
}
|
||||
} else {
|
||||
fRef = NULL;
|
||||
ClearIcon();
|
||||
}
|
||||
_UpdateToolTip();
|
||||
}
|
||||
|
||||
|
||||
entry_ref*
|
||||
LaunchButton::Ref() const
|
||||
{
|
||||
return fRef;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LaunchButton::SetTo(const char* appSig, bool updateIcon)
|
||||
{
|
||||
if (appSig) {
|
||||
free(fAppSig);
|
||||
fAppSig = strdup(appSig);
|
||||
if (updateIcon) {
|
||||
entry_ref ref;
|
||||
if (be_roster->FindApp(fAppSig, &ref) == B_OK)
|
||||
SetTo(&ref);
|
||||
}
|
||||
}
|
||||
_UpdateToolTip();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LaunchButton::SetDescription(const char* text)
|
||||
{
|
||||
fDescription.SetTo(text);
|
||||
_UpdateToolTip();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LaunchButton::SetIconSize(uint32 size)
|
||||
{
|
||||
if (fIconSize == size)
|
||||
return;
|
||||
|
||||
fIconSize = size;
|
||||
_UpdateIcon(fRef);
|
||||
|
||||
InvalidateLayout();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LaunchButton::SetIgnoreDoubleClick(bool refuse)
|
||||
{
|
||||
sIgnoreDoubleClick = refuse;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
LaunchButton::_UpdateToolTip()
|
||||
{
|
||||
// TODO: This works around a bug in the tool tip management.
|
||||
// Remove when fixed (although no harm done...)
|
||||
HideToolTip();
|
||||
SetToolTip(static_cast<BToolTip*>(NULL));
|
||||
|
||||
if (fRef) {
|
||||
BString helper(fRef->name);
|
||||
if (fDescription.CountChars() > 0) {
|
||||
if (fDescription != helper)
|
||||
helper << "\n\n" << fDescription.String();
|
||||
} else {
|
||||
BFile file(fRef, B_READ_ONLY);
|
||||
BAppFileInfo appFileInfo;
|
||||
version_info info;
|
||||
if (appFileInfo.SetTo(&file) == B_OK
|
||||
&& appFileInfo.GetVersionInfo(&info,
|
||||
B_APP_VERSION_KIND) == B_OK
|
||||
&& strlen(info.short_info) > 0
|
||||
&& helper.Compare(info.short_info) != 0) {
|
||||
helper << "\n\n" << info.short_info;
|
||||
}
|
||||
}
|
||||
SetToolTip(helper.String());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LaunchButton::_UpdateIcon(const entry_ref* ref)
|
||||
{
|
||||
BBitmap* icon = new BBitmap(BRect(0.0, 0.0, fIconSize - 1,
|
||||
fIconSize - 1), B_RGBA32);
|
||||
// NOTE: passing an invalid/unknown icon_size argument will cause
|
||||
// the BNodeInfo to ignore it and just use the bitmap bounds.
|
||||
if (BNodeInfo::GetTrackerIcon(ref, icon, (icon_size)fIconSize) == B_OK)
|
||||
SetIcon(icon);
|
||||
|
||||
delete icon;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LaunchButton::_DrawFrame(BRect r, rgb_color col1, rgb_color col2,
|
||||
rgb_color col3, rgb_color col4)
|
||||
{
|
||||
BeginLineArray(8);
|
||||
AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), col1);
|
||||
AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), col1);
|
||||
AddLine(BPoint(r.right, r.top + 1.0), BPoint(r.right, r.bottom), col2);
|
||||
AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), col2);
|
||||
r.InsetBy(1.0, 1.0);
|
||||
AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), col3);
|
||||
AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), col3);
|
||||
AddLine(BPoint(r.right, r.top + 1.0), BPoint(r.right, r.bottom), col4);
|
||||
AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), col4);
|
||||
EndLineArray();
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2006-2011, Stephan Aßmus <[email protected]>
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef LAUNCH_BUTTON_H
|
||||
#define LAUNCH_BUTTON_H
|
||||
|
||||
|
||||
#include <IconButton.h>
|
||||
#include <List.h>
|
||||
#include <String.h>
|
||||
|
||||
|
||||
enum {
|
||||
MSG_ADD_SLOT = 'adsl',
|
||||
MSG_CLEAR_SLOT = 'clsl',
|
||||
MSG_REMOVE_SLOT = 'rmsl',
|
||||
MSG_LAUNCH = 'lnch',
|
||||
};
|
||||
|
||||
|
||||
class LaunchButton : public BIconButton {
|
||||
public:
|
||||
LaunchButton(const char* name,
|
||||
const char* label = NULL,
|
||||
BMessage* message = NULL,
|
||||
BHandler* target = NULL);
|
||||
virtual ~LaunchButton();
|
||||
|
||||
// BIconButton interface
|
||||
virtual void AttachedToWindow();
|
||||
virtual void Draw(BRect updateRect);
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual void MouseDown(BPoint where);
|
||||
virtual void MouseUp(BPoint where);
|
||||
virtual void MouseMoved(BPoint where, uint32 transit,
|
||||
const BMessage* dragMessage);
|
||||
|
||||
virtual BSize MinSize();
|
||||
virtual BSize PreferredSize();
|
||||
virtual BSize MaxSize();
|
||||
|
||||
// LaunchButton
|
||||
void SetTo(const entry_ref* ref);
|
||||
entry_ref* Ref() const;
|
||||
|
||||
void SetTo(const char* appSig, bool updateIcon);
|
||||
const char* AppSignature() const
|
||||
{ return fAppSig; }
|
||||
|
||||
void SetDescription(const char* text);
|
||||
const char* Description() const
|
||||
{ return fDescription.String(); }
|
||||
|
||||
void SetIconSize(uint32 size);
|
||||
uint32 IconSize() const
|
||||
{ return fIconSize; }
|
||||
|
||||
static void SetIgnoreDoubleClick(bool refuse);
|
||||
static bool IgnoreDoubleClick()
|
||||
{ return sIgnoreDoubleClick; }
|
||||
|
||||
private:
|
||||
void _UpdateToolTip();
|
||||
void _UpdateIcon(const entry_ref* ref);
|
||||
|
||||
void _DrawFrame(BRect frame,
|
||||
rgb_color left, rgb_color top,
|
||||
rgb_color right, rgb_color bottom);
|
||||
|
||||
private:
|
||||
entry_ref* fRef;
|
||||
char* fAppSig;
|
||||
BString fDescription;
|
||||
|
||||
bool fAnticipatingDrop;
|
||||
bigtime_t fLastClickTime;
|
||||
BPoint fDragStart;
|
||||
|
||||
uint32 fIconSize;
|
||||
|
||||
static bigtime_t sClickSpeed;
|
||||
static bool sIgnoreDoubleClick;
|
||||
};
|
||||
|
||||
#endif // LAUNCH_BUTTON_H
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "PanelWindow.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <GroupLayout.h>
|
||||
#include <MessageRunner.h>
|
||||
#include <Screen.h>
|
||||
|
||||
#include "ApplicationsView.h"
|
||||
#include "GroupListView.h"
|
||||
#include "Switcher.h"
|
||||
#include "WindowsView.h"
|
||||
|
||||
|
||||
static const uint32 kMsgShow = 'SHOW';
|
||||
static const uint32 kMsgHide = 'HIDE';
|
||||
|
||||
static const int32 kMinShowState = 0;
|
||||
static const int32 kMaxShowState = 4;
|
||||
static const bigtime_t kMoveDelay = 15000;
|
||||
// 25 ms
|
||||
|
||||
|
||||
PanelWindow::PanelWindow(uint32 location, uint32 which, team_id team)
|
||||
:
|
||||
BWindow(BRect(-16000, -16000, -15900, -15900), "panel",
|
||||
B_BORDERED_WINDOW_LOOK, B_FLOATING_ALL_WINDOW_FEEL,
|
||||
B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS | B_AVOID_FOCUS,
|
||||
B_ALL_WORKSPACES),
|
||||
fLocation(location),
|
||||
fShowState(kMinShowState)
|
||||
{
|
||||
SetLayout(new BGroupLayout(B_HORIZONTAL));
|
||||
|
||||
BView* child = _ViewFor(location, which, team);
|
||||
if (child != NULL)
|
||||
AddChild(child);
|
||||
|
||||
Run();
|
||||
PostMessage(kMsgShow);
|
||||
}
|
||||
|
||||
|
||||
PanelWindow::~PanelWindow()
|
||||
{
|
||||
BMessage message(kMsgLocationFree);
|
||||
message.AddInt32("location", fLocation);
|
||||
be_app->PostMessage(&message);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PanelWindow::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case kMsgShow:
|
||||
case kMsgHide:
|
||||
_UpdateShowState(message->what);
|
||||
break;
|
||||
|
||||
default:
|
||||
BWindow::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BView*
|
||||
PanelWindow::_ViewFor(uint32 location, uint32 which, team_id team) const
|
||||
{
|
||||
switch (which) {
|
||||
case kShowApplications:
|
||||
return new ApplicationsView(location);
|
||||
case kShowApplicationWindows:
|
||||
return new WindowsView(team, location);
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PanelWindow::_UpdateShowState(uint32 how)
|
||||
{
|
||||
if ((how == kMsgShow && fShowState >= kMaxShowState)
|
||||
|| (how == kMsgHide && fShowState <= kMinShowState))
|
||||
return;
|
||||
|
||||
fShowState += how == kMsgShow ? 1 : -1;
|
||||
|
||||
// Compute start and end position depending on the location
|
||||
// TODO: multi-screen support
|
||||
BScreen screen;
|
||||
BRect screenFrame = screen.Frame();
|
||||
BPoint from;
|
||||
BPoint to;
|
||||
|
||||
switch (fLocation) {
|
||||
case kLeftEdge:
|
||||
case kRightEdge:
|
||||
from.y = screenFrame.top
|
||||
+ (screenFrame.Height() - Bounds().Height()) / 2.f;
|
||||
to.y = from.y;
|
||||
break;
|
||||
case kTopEdge:
|
||||
case kBottomEdge:
|
||||
from.x = screenFrame.left
|
||||
+ (screenFrame.Width() - Bounds().Width()) / 2.f;
|
||||
to.x = from.x;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (fLocation) {
|
||||
case kLeftEdge:
|
||||
from.x = screenFrame.left - Bounds().Width();
|
||||
to.x = screenFrame.left;
|
||||
break;
|
||||
case kRightEdge:
|
||||
from.x = screenFrame.right;
|
||||
to.x = screenFrame.right - Bounds().Width();
|
||||
break;
|
||||
case kTopEdge:
|
||||
from.y = screenFrame.top - Bounds().Height();
|
||||
to.y = screenFrame.top;
|
||||
break;
|
||||
case kBottomEdge:
|
||||
from.y = screenFrame.bottom;
|
||||
to.y = screenFrame.bottom - Bounds().Height();
|
||||
break;
|
||||
}
|
||||
|
||||
MoveTo(from.x + _Factor() * (to.x - from.x),
|
||||
from.y + _Factor() * (to.y - from.y));
|
||||
|
||||
if (kMsgShow && IsHidden())
|
||||
Show();
|
||||
else if (fShowState == 0 && kMsgHide && !IsHidden())
|
||||
Quit();
|
||||
|
||||
if ((how == kMsgShow && fShowState < kMaxShowState)
|
||||
|| (how == kMsgHide && fShowState > kMinShowState)) {
|
||||
BMessage move(how);
|
||||
BMessageRunner::StartSending(this, &move, kMoveDelay, 1);
|
||||
} else if (how == kMsgShow) {
|
||||
// Hide the window once the mouse left its frame
|
||||
BMessage hide(kMsgHideWhenMouseMovedOut);
|
||||
hide.AddMessenger("target", this);
|
||||
hide.AddInt32("what", kMsgHide);
|
||||
|
||||
// The window might not span over the whole screen, but one dimension
|
||||
// should be ignored for the cursor movements
|
||||
BRect frame = Frame();
|
||||
switch (fLocation) {
|
||||
case kLeftEdge:
|
||||
case kRightEdge:
|
||||
frame.top = screenFrame.top;
|
||||
frame.bottom = screenFrame.bottom;
|
||||
break;
|
||||
case kTopEdge:
|
||||
case kBottomEdge:
|
||||
frame.left = screenFrame.left;
|
||||
frame.right = screenFrame.right;
|
||||
break;
|
||||
}
|
||||
hide.AddRect("frame", frame);
|
||||
be_app->PostMessage(&hide);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
PanelWindow::_Factor()
|
||||
{
|
||||
float factor = 1.f * fShowState / kMaxShowState;
|
||||
return 1 - (factor - 1) * (factor - 1);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef PANEL_WINDOW_H
|
||||
#define PANEL_WINDOW_H
|
||||
|
||||
|
||||
#include <Window.h>
|
||||
|
||||
|
||||
class PanelWindow : public BWindow {
|
||||
public:
|
||||
PanelWindow(uint32 location, uint32 which,
|
||||
team_id team);
|
||||
virtual ~PanelWindow();
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
private:
|
||||
BView* _ViewFor(uint32 location, uint32 which,
|
||||
team_id team) const;
|
||||
void _UpdateShowState(uint32 how);
|
||||
float _Factor();
|
||||
|
||||
private:
|
||||
uint32 fLocation;
|
||||
int32 fShowState;
|
||||
};
|
||||
|
||||
|
||||
#endif // PANEL_WINDOW_H
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "Switcher.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <Application.h>
|
||||
#include <Catalog.h>
|
||||
|
||||
#include "CaptureWindow.h"
|
||||
#include "PanelWindow.h"
|
||||
|
||||
|
||||
#undef B_TRANSLATE_CONTEXT
|
||||
#define B_TRANSLATE_CONTEXT "Switcher"
|
||||
|
||||
|
||||
const char* kSignature = "application/x-vnd.Haiku-Switcher";
|
||||
|
||||
|
||||
Switcher::Switcher()
|
||||
:
|
||||
BApplication(kSignature),
|
||||
fOccupiedLocations(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Switcher::~Switcher()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Switcher::ReadyToRun()
|
||||
{
|
||||
CaptureWindow* window = new CaptureWindow();
|
||||
window->Run();
|
||||
|
||||
fCaptureMessenger = window;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Switcher::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case kMsgLocationTrigger:
|
||||
{
|
||||
uint32 location = (uint32)message->FindInt32("location");
|
||||
if ((location & fOccupiedLocations) == 0) {
|
||||
// TODO: make function configurable
|
||||
uint32 which = kShowApplicationWindows;
|
||||
if ((location & (kTopEdge | kBottomEdge)) != 0)
|
||||
which = kShowApplications;
|
||||
|
||||
new PanelWindow(location, which,
|
||||
(team_id)message->FindInt32("team"));
|
||||
fOccupiedLocations |= location;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgLocationFree:
|
||||
{
|
||||
uint32 location;
|
||||
if (message->FindInt32("location", (int32*)&location) == B_OK)
|
||||
fOccupiedLocations &= ~location;
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgHideWhenMouseMovedOut:
|
||||
fCaptureMessenger.SendMessage(message);
|
||||
break;
|
||||
|
||||
default:
|
||||
BApplication::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
int
|
||||
main(int /*argc*/, char** /*argv*/)
|
||||
{
|
||||
Switcher app;
|
||||
app.Run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef SWITCHER_H
|
||||
#define SWITCHER_H
|
||||
|
||||
|
||||
#include <Application.h>
|
||||
|
||||
|
||||
class BMessage;
|
||||
|
||||
|
||||
enum {
|
||||
kNowhere = 0,
|
||||
kTopEdge = 0x01,
|
||||
kBottomEdge = 0x02,
|
||||
kLeftEdge = 0x04,
|
||||
kRightEdge = 0x08,
|
||||
// TODO: not yet supported
|
||||
kTopLeftCorner = 0x10,
|
||||
kTopRightCorner = 0x20,
|
||||
kBottomLeftCorner = 0x40,
|
||||
kBottomRightCorner = 0x80
|
||||
};
|
||||
|
||||
enum {
|
||||
kShowApplications,
|
||||
kShowApplicationWindows,
|
||||
kShowWorkspaceWindows,
|
||||
kShowAllWindows,
|
||||
kShowWorkspaces,
|
||||
kShowShelf,
|
||||
kShowFavorites,
|
||||
kShowRecentFiles,
|
||||
kShowFilesClipboard,
|
||||
kShowFolder,
|
||||
kShowQuery
|
||||
};
|
||||
|
||||
|
||||
static const uint32 kMsgLocationTrigger = 'LoTr';
|
||||
static const uint32 kMsgLocationFree = 'LoFr';
|
||||
static const uint32 kMsgHideWhenMouseMovedOut = 'HwMo';
|
||||
|
||||
|
||||
class Switcher : public BApplication {
|
||||
public:
|
||||
Switcher();
|
||||
virtual ~Switcher();
|
||||
|
||||
virtual void ReadyToRun();
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
private:
|
||||
BMessenger fCaptureMessenger;
|
||||
uint32 fOccupiedLocations;
|
||||
};
|
||||
|
||||
|
||||
extern const char* kSignature;
|
||||
|
||||
|
||||
#endif // SWITCHER_H
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
resource app_signature "application/x-vnd.Haiku-Switcher";
|
||||
|
||||
//resource app_name_catalog_entry "x-vnd.Haiku-Switcher:System name:Switcher";
|
||||
|
||||
resource app_version {
|
||||
major = 1,
|
||||
middle = 0,
|
||||
minor = 0,
|
||||
|
||||
variety = B_APPV_BETA,
|
||||
internal = 0,
|
||||
|
||||
short_info = "Switcher",
|
||||
long_info = "Switcher ©2011 Haiku, Inc."
|
||||
};
|
||||
|
||||
resource app_flags B_SINGLE_LAUNCH | B_BACKGROUND_APP;
|
||||
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "WindowsView.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <LayoutBuilder.h>
|
||||
#include <ObjectList.h>
|
||||
#include <StringView.h>
|
||||
|
||||
#include <MessengerPrivate.h>
|
||||
#include <WindowInfo.h>
|
||||
#include <WindowPrivate.h>
|
||||
|
||||
#include "GroupListView.h"
|
||||
#include "LaunchButton.h"
|
||||
#include "Switcher.h"
|
||||
|
||||
|
||||
static const uint32 kMsgActivateWindow = 'AcWn';
|
||||
|
||||
|
||||
class WindowModel : public TypedGroupListModel<client_window_info, void> {
|
||||
public:
|
||||
WindowModel(team_id team)
|
||||
:
|
||||
fWindows(true),
|
||||
fWorkspaces(0),
|
||||
fWorkspaceCount(0)
|
||||
{
|
||||
// TODO: more than one team via signature!
|
||||
int32 count;
|
||||
int32* tokens = get_token_list(team, &count);
|
||||
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
client_window_info* info = get_window_info(tokens[i]);
|
||||
if (!_WindowShouldBeListed(info)) {
|
||||
free(info);
|
||||
continue;
|
||||
}
|
||||
|
||||
fWorkspaces |= info->workspaces;
|
||||
fWindows.AddItem(info);
|
||||
}
|
||||
free(tokens);
|
||||
|
||||
for (uint32 i = 0; i < 32; i++) {
|
||||
if ((fWorkspaces & (1UL << i)) != 0)
|
||||
fWorkspaceCount++;
|
||||
}
|
||||
|
||||
fWindows.SortItems(&_CompareWindowInfo);
|
||||
}
|
||||
|
||||
virtual ~WindowModel()
|
||||
{
|
||||
}
|
||||
|
||||
void BringToFront(int32 index)
|
||||
{
|
||||
client_window_info* info = fWindows.ItemAt(index);
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
do_window_action(info->server_token, B_BRING_TO_FRONT, BRect(), false);
|
||||
}
|
||||
|
||||
void Close(int32 index)
|
||||
{
|
||||
client_window_info* info = fWindows.ItemAt(index);
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
BMessenger window;
|
||||
BMessenger::Private(window).SetTo(info->team, info->client_port,
|
||||
info->client_token);
|
||||
window.SendMessage(B_QUIT_REQUESTED);
|
||||
}
|
||||
|
||||
virtual int32 CountItems()
|
||||
{
|
||||
return fWindows.CountItems();
|
||||
}
|
||||
|
||||
virtual client_window_info* ItemAt(int32 index)
|
||||
{
|
||||
return fWindows.ItemAt(index);
|
||||
}
|
||||
|
||||
virtual int32 CountGroups()
|
||||
{
|
||||
return fWorkspaceCount;
|
||||
}
|
||||
|
||||
virtual void* GroupAt(int32 index)
|
||||
{
|
||||
return (void*)(_NthSetBit(index, fWorkspaces) + 1);
|
||||
}
|
||||
|
||||
virtual void* GroupForItemAt(int32 index)
|
||||
{
|
||||
client_window_info* info = ItemAt(index);
|
||||
return (void*)(_NthSetBit(0, info->workspaces) + 1);
|
||||
}
|
||||
|
||||
private:
|
||||
bool _WindowShouldBeListed(client_window_info* info)
|
||||
{
|
||||
return info != NULL
|
||||
&& (info->feel == B_NORMAL_WINDOW_FEEL
|
||||
|| info->feel == kWindowScreenFeel)
|
||||
&& (info->show_hide_level <= 0 || info->is_mini);
|
||||
}
|
||||
|
||||
int32 _NthSetBit(int32 index, uint32 mask)
|
||||
{
|
||||
for (uint32 i = 0; i < 32; i++) {
|
||||
if ((mask & (1UL << i)) != 0) {
|
||||
if (index-- == 0)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _CompareWindowInfo(const client_window_info* a,
|
||||
const client_window_info* b)
|
||||
{
|
||||
return strcasecmp(a->name, b->name);
|
||||
}
|
||||
|
||||
private:
|
||||
BObjectList<client_window_info> fWindows;
|
||||
uint32 fWorkspaces;
|
||||
int32 fWorkspaceCount;
|
||||
};
|
||||
|
||||
|
||||
class StringItemRenderer : public ListItemRenderer {
|
||||
public:
|
||||
StringItemRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~StringItemRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
void SetText(BView* owner, const BString& text)
|
||||
{
|
||||
fText = text;
|
||||
owner->TruncateString(&fText, B_TRUNCATE_MIDDLE, 200);
|
||||
SetWidth((int32)ceilf(owner->StringWidth(fText.String())));
|
||||
|
||||
font_height fontHeight;
|
||||
owner->GetFontHeight(&fontHeight);
|
||||
|
||||
SetBaselineOffset(
|
||||
2 + (int32)ceilf(fontHeight.ascent + fontHeight.leading / 2));
|
||||
|
||||
SetHeight((int32)ceilf(fontHeight.ascent)
|
||||
+ (int32)ceilf(fontHeight.descent)
|
||||
+ (int32)ceilf(fontHeight.leading) + 4);
|
||||
}
|
||||
|
||||
virtual void SetWidth(int32 width)
|
||||
{
|
||||
fWidth = width;
|
||||
}
|
||||
|
||||
virtual void SetHeight(int32 height)
|
||||
{
|
||||
fHeight = height;
|
||||
}
|
||||
|
||||
virtual void SetBaselineOffset(int32 offset)
|
||||
{
|
||||
fBaselineOffset = offset;
|
||||
}
|
||||
|
||||
const BString& Text() const
|
||||
{
|
||||
return fText;
|
||||
}
|
||||
|
||||
virtual BSize MinSize()
|
||||
{
|
||||
return BSize(fWidth, fHeight);
|
||||
}
|
||||
|
||||
virtual BSize MaxSize()
|
||||
{
|
||||
return BSize(B_SIZE_UNLIMITED, fHeight);
|
||||
}
|
||||
|
||||
virtual BSize PreferredSize()
|
||||
{
|
||||
return BSize(fWidth, fHeight);
|
||||
}
|
||||
|
||||
virtual void Draw(BView* owner, BRect frame, int32 index, bool selected)
|
||||
{
|
||||
owner->SetLowColor(owner->ViewColor());
|
||||
owner->MovePenTo(frame.left, frame.top + fBaselineOffset);
|
||||
owner->DrawString(fText);
|
||||
}
|
||||
|
||||
private:
|
||||
BString fText;
|
||||
int32 fWidth;
|
||||
int32 fHeight;
|
||||
int32 fBaselineOffset;
|
||||
};
|
||||
|
||||
|
||||
class WorkspaceRenderer : public StringItemRenderer {
|
||||
public:
|
||||
virtual void SetTo(BView* owner, void* item)
|
||||
{
|
||||
fWorkspace = (uint32)item;
|
||||
|
||||
if ((uint32)current_workspace() == fWorkspace - 1)
|
||||
SetText(owner, "Current workspace");
|
||||
else {
|
||||
BString text("Workspace ");
|
||||
text << fWorkspace;
|
||||
SetText(owner, text);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Draw(BView* owner, BRect frame, int32 index, bool selected)
|
||||
{
|
||||
owner->SetHighColor(tint_color(owner->ViewColor(), B_DARKEN_2_TINT));
|
||||
StringItemRenderer::Draw(owner, frame, index, false);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 fWorkspace;
|
||||
};
|
||||
|
||||
|
||||
class WindowRenderer : public StringItemRenderer {
|
||||
public:
|
||||
virtual void SetTo(BView* owner, void* item)
|
||||
{
|
||||
fInfo = (client_window_info*)item;
|
||||
SetText(owner, fInfo->name);
|
||||
}
|
||||
|
||||
virtual void SetWidth(int32 width)
|
||||
{
|
||||
StringItemRenderer::SetWidth(width + 20);
|
||||
}
|
||||
|
||||
virtual void Draw(BView* owner, BRect frame, int32 index, bool selected)
|
||||
{
|
||||
owner->SetHighColor(0, 0, 0);
|
||||
frame.left += 20;
|
||||
StringItemRenderer::Draw(owner, frame, index, selected);
|
||||
}
|
||||
|
||||
private:
|
||||
client_window_info* fInfo;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
WindowsView::WindowsView(team_id team, uint32 location)
|
||||
:
|
||||
BGridView("windows")
|
||||
{
|
||||
app_info info;
|
||||
be_roster->GetRunningAppInfo(team, &info);
|
||||
|
||||
LaunchButton* launchButton = new LaunchButton(info.signature, NULL, NULL,
|
||||
this);
|
||||
launchButton->SetTo(&info.ref);
|
||||
|
||||
BStringView* nameView = new BStringView("name", info.ref.name);
|
||||
BFont font(be_plain_font);
|
||||
font.SetSize(font.Size() * 2);
|
||||
font.SetFace(B_BOLD_FACE);
|
||||
nameView->SetFont(&font);
|
||||
|
||||
fListView = new GroupListView("list", new WindowModel(team),
|
||||
_Orientation(location));
|
||||
fListView->SetItemRenderer(new WindowRenderer());
|
||||
fListView->SetGroupRenderer(new WorkspaceRenderer());
|
||||
|
||||
GridLayout()->SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING,
|
||||
B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING);
|
||||
|
||||
if (_Orientation(location) == B_HORIZONTAL) {
|
||||
BLayoutBuilder::Grid<>(this)
|
||||
.Add(launchButton, 0, 0)
|
||||
.Add(nameView, 1, 0)
|
||||
.Add(fListView, 2, 0);
|
||||
} else {
|
||||
BLayoutBuilder::Grid<>(this)
|
||||
.Add(launchButton, 0, 0)
|
||||
.Add(nameView, 1, 0)
|
||||
.Add(fListView, 0, 1, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WindowsView::~WindowsView()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WindowsView::AttachedToWindow()
|
||||
{
|
||||
fListView->SetSelectionMessage(new BMessage(kMsgActivateWindow), this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WindowsView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case kMsgActivateWindow:
|
||||
{
|
||||
int32 index;
|
||||
if (message->FindInt32("index", &index) == B_OK
|
||||
&& message->HasPointer("item")) {
|
||||
WindowModel* model = (WindowModel*)fListView->Model();
|
||||
|
||||
if (message->FindInt32("buttons") == B_SECONDARY_MOUSE_BUTTON)
|
||||
model->Close(index);
|
||||
else
|
||||
model->BringToFront(index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
BGridView::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
orientation
|
||||
WindowsView::_Orientation(uint32 location)
|
||||
{
|
||||
return (location & (kTopEdge | kBottomEdge)) != 0
|
||||
? B_HORIZONTAL : B_VERTICAL;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef WINDOWS_VIEW_H
|
||||
#define WINDOWS_VIEW_H
|
||||
|
||||
|
||||
#include <GridView.h>
|
||||
|
||||
|
||||
class GroupListView;
|
||||
|
||||
|
||||
class WindowsView : public BGridView {
|
||||
public:
|
||||
WindowsView(team_id team, uint32 location);
|
||||
virtual ~WindowsView();
|
||||
|
||||
protected:
|
||||
virtual void AttachedToWindow();
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
private:
|
||||
orientation _Orientation(uint32 location);
|
||||
|
||||
private:
|
||||
GroupListView* fListView;
|
||||
};
|
||||
|
||||
|
||||
#endif // WINDOWS_VIEW_H
|
||||
Reference in New Issue
Block a user