Deskbar: Use hvif window icons & scale with font

Add vector rdefs for shown, hidden, shown switch
and hidden switch icons. Remove unused bitmap
resources. Add window switch vector icons to
artwork.

Create window icon cache in TBarApp and cache the
window icons based on font size.
Fixes memory leak in #18357.

Don't draw off-workspace lines in Switcher, use
switch icon for that instead. Fixes crash reported
in #18359. Position icon and window name better in
Switcher.

Put BarTeamInfo icon parameter last and make it
optional, the icon gets set by caching.

Enable team icon cache and window icon cache.

Fixes #14694

Deskbar: Scale Twitcher icons based on font size

Remove the point ctor parameter and deprecate the
switcherLoc setting by not using or setting it and
leaving it at its default value.

Center window on screen resolution change and
workspace change (as resolution may not match).

Fixes #17924

Change-Id: Ib63cc307f14cda397ffb66ea74091be59e6e5535
Reviewed-on: https://review.haiku-os.org/c/haiku/+/6335
Reviewed-by: John Scipione <jscipione@gmail.com>
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk>
This commit is contained in:
John Scipione 2023-05-05 01:49:21 -04:00 committed by waddlesplash
parent 217bbbf423
commit fb885767b6
9 changed files with 621 additions and 434 deletions

View File

@ -49,6 +49,7 @@ All rights reserved.
#include <Dragger.h>
#include <File.h>
#include <FindDirectory.h>
#include <IconUtils.h>
#include <Locale.h>
#include <Message.h>
#include <Messenger.h>
@ -74,14 +75,13 @@ All rights reserved.
BLocker TBarApp::sSubscriberLock;
BList TBarApp::sBarTeamInfoList;
BList TBarApp::sWindowIconCache;
BList TBarApp::sSubscribers;
const uint32 kShowDeskbarMenu = 'BeMn';
const uint32 kShowTeamMenu = 'TmMn';
static const color_space kIconColorSpace = B_RGBA32;
int
main()
@ -127,8 +127,18 @@ TBarApp::TBarApp()
}
}
sWindowIconCache.MakeEmpty();
for (int32 id = R_WindowShownIcon; id <= R_WindowHiddenSwitchIcon; id++) {
if (id == R_ResizeIcon)
continue;
WindowIconCache* winCache = new WindowIconCache(id);
_CacheWindowIcon(winCache);
sWindowIconCache.AddItem(winCache);
}
sSubscribers.MakeEmpty();
fSwitcherMessenger = BMessenger(new TSwitchManager(fSettings.switcherLoc));
fSwitcherMessenger = BMessenger(new TSwitchManager());
fBarWindow->Show();
fBarWindow->Lock();
@ -635,11 +645,12 @@ TBarApp::MessageReceived(BMessage* message)
case kResizeTeamIcons:
{
int32 oldIconSize = fSettings.iconSize;
int32 iconSize;
if (message->FindInt32("be:value", &iconSize) != B_OK)
int32 value;
if (message->FindInt32("be:value", &value) != B_OK)
break;
fSettings.iconSize = iconSize * kIconSizeInterval;
int32 iconSize = value * kIconSizeInterval;
fSettings.iconSize = iconSize;
// pin icon size between min and max values
if (fSettings.iconSize < kMinimumIconSize)
@ -792,6 +803,69 @@ TBarApp::Unsubscribe(const BMessenger &subscriber)
}
BBitmap*
TBarApp::FetchTeamIcon(team_id team, int32 size)
{
int32 teamCount = sBarTeamInfoList.CountItems();
for (int32 i = 0; i < teamCount; i++) {
BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
if (barInfo->teams->HasItem((void*)(addr_t)team)) {
_CacheTeamIcon(barInfo, size);
BBitmap* icon = barInfo->icon;
// restore icon pointer back to setting
if (size != fSettings.iconSize) {
int32 index = (fSettings.iconSize - kMinimumIconSize)
/ kIconSizeInterval;
barInfo->icon = barInfo->iconCache[index];
}
return icon;
}
}
return NULL;
}
BBitmap*
TBarApp::FetchWindowIcon(bool local, bool minimized)
{
int32 id = R_WindowShownIcon;
int32 index = 0;
if (local) {
if (!minimized) {
id = R_WindowShownIcon;
index = 0;
}
else {
id = R_WindowHiddenIcon;
index = 1;
}
} else {
if (!minimized) {
id = R_WindowShownSwitchIcon;
index = 2;
}
else {
id = R_WindowHiddenSwitchIcon;
index = 3;
}
}
// create a new cache entry if not found
WindowIconCache* winCache
= (WindowIconCache*)sWindowIconCache.ItemAt(index);
if (winCache == NULL)
winCache = new WindowIconCache(id);
_CacheWindowIcon(winCache);
return winCache->icon;
}
void
TBarApp::AddTeam(team_id team, uint32 flags, const char* sig, entry_ref* ref)
{
@ -832,9 +906,6 @@ TBarApp::AddTeam(team_id team, uint32 flags, const char* sig, entry_ref* ref)
return;
}
BFile file(ref, B_READ_ONLY);
BAppFileInfo appMime(&file);
BString name;
if (!gLocalizedNamePreferred
|| BLocaleRoster::Default()->GetLocalizedFileName(name, *ref)
@ -843,8 +914,8 @@ TBarApp::AddTeam(team_id team, uint32 flags, const char* sig, entry_ref* ref)
}
BarTeamInfo* barInfo = new BarTeamInfo(new BList(), flags, strdup(sig),
NULL, strdup(name.String()));
FetchAppIcon(barInfo);
strdup(name.String()));
_CacheTeamIcon(barInfo);
barInfo->teams->AddItem((void*)(addr_t)team);
sBarTeamInfoList.AddItem(barInfo);
@ -912,7 +983,7 @@ TBarApp::ResizeTeamIcons()
BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
if ((barInfo->flags & B_BACKGROUND_APP) == 0
&& strcasecmp(barInfo->sig, kDeskbarSignature) != 0) {
FetchAppIcon(barInfo);
_CacheTeamIcon(barInfo);
}
}
}
@ -921,14 +992,14 @@ TBarApp::ResizeTeamIcons()
int32
TBarApp::TeamIconSize()
{
static int32 iconSize = 0, composedIconSize = 0;
if (iconSize != fSettings.iconSize) {
composedIconSize = be_control_look->ComposeIconSize(fSettings.iconSize)
.IntegerWidth() + 1;
iconSize = fSettings.iconSize;
static int32 iconSize = 0, composed = 0;
int32 saved = fSettings.iconSize;
if (iconSize != saved) {
composed = be_control_look->ComposeIconSize(saved).IntegerWidth() + 1;
iconSize = saved;
}
return composedIconSize;
return composed;
}
@ -963,29 +1034,44 @@ TBarApp::QuitPreferencesWindow()
}
void
TBarApp::FetchAppIcon(BarTeamInfo* barInfo)
status_t
TBarApp::_CacheTeamIcon(BarTeamInfo* barInfo)
{
const int32 width = TeamIconSize();
const int32 index = (fSettings.iconSize - kMinimumIconSize) / kIconSizeInterval;
if (barInfo == NULL)
return B_BAD_VALUE;
return _CacheTeamIcon(barInfo, fSettings.iconSize);
}
status_t
TBarApp::_CacheTeamIcon(BarTeamInfo* barInfo, int32 size)
{
if (barInfo == NULL || size < kMinimumIconSize)
return B_BAD_VALUE;
// icon index based on icon size
const int32 index = (size - kMinimumIconSize) / kIconSizeInterval;
// first look in the icon cache
barInfo->icon = barInfo->iconCache[index];
if (barInfo->icon != NULL)
return;
return B_OK;
int32 composed = be_control_look->ComposeIconSize(size).IntegerWidth() + 1;
BRect iconRect = BRect(0, 0, composed - 1, composed - 1);
BBitmap* icon = new BBitmap(iconRect, B_RGBA32);
// icon wasn't in cache, get it from be_roster and cache it
app_info appInfo;
icon_size size = width >= 31 ? B_LARGE_ICON : B_MINI_ICON;
BBitmap* icon = new BBitmap(IconRect(), kIconColorSpace);
if (be_roster->GetAppInfo(barInfo->sig, &appInfo) == B_OK) {
// fetch the app icon
BFile file(&appInfo.ref, B_READ_ONLY);
BAppFileInfo appMime(&file);
if (appMime.GetIcon(icon, size) == B_OK) {
delete barInfo->iconCache[index];
if (appMime.GetIcon(icon, (icon_size)size) == B_OK) {
barInfo->iconCache[index] = barInfo->icon = icon;
return;
return B_OK;
}
}
@ -993,10 +1079,10 @@ TBarApp::FetchAppIcon(BarTeamInfo* barInfo)
// fetch the generic 3 boxes icon and cache it
BMimeType defaultAppMime;
defaultAppMime.SetTo(B_APP_MIME_TYPE);
if (defaultAppMime.GetIcon(icon, size) == B_OK) {
delete barInfo->iconCache[index];
if (defaultAppMime.GetIcon(icon, (icon_size)size) == B_OK) {
barInfo->iconCache[index] = barInfo->icon = icon;
return;
return B_OK;
}
// couldn't find generic 3 boxes icon
@ -1016,30 +1102,75 @@ TBarApp::FetchAppIcon(BarTeamInfo* barInfo)
iconBits[i] = B_TRANSPARENT_MAGIC_CMAP8;
}
delete barInfo->iconCache[index];
barInfo->iconCache[index] = barInfo->icon = icon;
return B_OK;
}
BRect
TBarApp::IconRect()
status_t
TBarApp::_CacheWindowIcon(WindowIconCache* winCache)
{
int32 iconSize = TeamIconSize();
return BRect(0, 0, iconSize - 1, iconSize - 1);
if (winCache == NULL)
return B_BAD_VALUE;
// clip font size
int32 fontSize = (int32)floorf(be_plain_font->Size());
if (fontSize < kMinimumFontSize)
fontSize = kMinimumFontSize;
if (fontSize > kMaximumFontSize)
fontSize = kMaximumFontSize;
// icon index based on font size
const int32 index = (fontSize - kMinimumFontSize) / kFontSizeInterval;
// first look in the icon cache
winCache->icon = winCache->iconCache[index];
if (winCache->icon != NULL)
return B_OK;
int32 id = winCache->id;
uint8* data;
size_t size;
// icon wasn't in cache, get vector icon from resource and cache it
data = (uint8*)AppResSet()->FindResource(B_VECTOR_ICON_TYPE, id, &size);
if (data != NULL && size > 0) {
// seems valid, scale bitmap according to font size
BBitmap* icon = new(std::nothrow) BBitmap(
BRect(B_ORIGIN, be_control_look->ComposeIconSize(B_MINI_ICON)),
B_RGBA32);
if (icon != NULL && icon->InitCheck() == B_OK
&& BIconUtils::GetVectorIcon(const_cast<const uint8*>(data),
size, icon) == B_OK) {
winCache->iconCache[index] = winCache->icon = icon;
return B_OK;
} else if (icon != NULL) {
// ran out of memory allocating bitmap, this should never happen
delete icon;
delete winCache->iconCache[index];
winCache->iconCache[index] = winCache->icon = NULL;
return B_NO_MEMORY;
}
}
return B_ERROR;
}
// #pragma mark - BarTeamInfo
BarTeamInfo::BarTeamInfo(BList* teams, uint32 flags, char* sig, BBitmap* icon,
char* name)
BarTeamInfo::BarTeamInfo(BList* teams, uint32 flags, char* sig, char* name,
BBitmap* icon)
:
teams(teams),
flags(flags),
sig(sig),
icon(icon),
name(name)
name(name),
icon(icon)
{
_Init();
}
@ -1050,8 +1181,8 @@ BarTeamInfo::BarTeamInfo(const BarTeamInfo &info)
teams(new BList(*info.teams)),
flags(info.flags),
sig(strdup(info.sig)),
icon(new BBitmap(*info.icon)),
name(strdup(info.name))
name(strdup(info.name)),
icon(new BBitmap(*info.icon))
{
_Init();
}
@ -1073,3 +1204,39 @@ BarTeamInfo::_Init()
for (int32 i = 0; i < kIconCacheCount; i++)
iconCache[i] = NULL;
}
// #pragma mark - WindowIconCache
WindowIconCache::WindowIconCache(int32 id, BBitmap* icon)
:
id(id),
icon(icon)
{
_Init();
}
WindowIconCache::WindowIconCache(const WindowIconCache &cache)
:
id(cache.id),
icon(new BBitmap(*cache.icon))
{
_Init();
}
WindowIconCache::~WindowIconCache()
{
for (int32 i = 0; i < kWindowIconCacheCount; i++)
delete iconCache[i];
}
void
WindowIconCache::_Init()
{
for (int32 i = 0; i < kWindowIconCacheCount; i++)
iconCache[i] = NULL;
}

View File

@ -74,6 +74,13 @@ const int32 kIconSizeInterval = 8;
const int32 kIconCacheCount = (kMaximumIconSize - kMinimumIconSize)
/ kIconSizeInterval + 1;
// font size constants
const int32 kMinimumFontSize = 8;
const int32 kMaximumFontSize = 72;
const int32 kFontSizeInterval = 1;
const int32 kWindowIconCacheCount = (kMaximumFontSize - kMinimumFontSize)
/ kFontSizeInterval + 1;
// update preferences message constant
const uint32 kUpdatePreferences = 'Pref';
@ -93,7 +100,7 @@ class TBarWindow;
class BarTeamInfo {
public:
BarTeamInfo(BList* teams, uint32 flags,
char* sig, BBitmap* icon, char* name);
char* sig, char* name, BBitmap* icon = NULL);
BarTeamInfo(const BarTeamInfo &info);
~BarTeamInfo();
@ -104,11 +111,28 @@ public:
BList* teams;
uint32 flags;
char* sig;
BBitmap* icon;
char* name;
BBitmap* icon;
BBitmap* iconCache[kIconCacheCount];
};
class WindowIconCache {
public:
WindowIconCache(int32 id, BBitmap* icon = NULL);
WindowIconCache(const WindowIconCache &cache);
~WindowIconCache();
private:
void _Init();
public:
int32 id;
BBitmap* icon;
BBitmap* iconCache[kWindowIconCacheCount];
};
class TBarApp : public BServer {
public:
TBarApp();
@ -132,6 +156,10 @@ public:
int32 TeamIconSize();
BBitmap* FetchTeamIcon(team_id team, int32 size);
BBitmap* FetchWindowIcon(bool local = true,
bool minimized = false);
private:
void AddTeam(team_id team, uint32 flags,
const char* sig, entry_ref*);
@ -144,9 +172,9 @@ private:
void QuitPreferencesWindow();
void ResizeTeamIcons();
void FetchAppIcon(BarTeamInfo* barInfo);
BRect IconRect();
status_t _CacheTeamIcon(BarTeamInfo* barInfo);
status_t _CacheTeamIcon(BarTeamInfo* barInfo, int32 size);
status_t _CacheWindowIcon(WindowIconCache* winCache);
private:
TBarWindow* fBarWindow;
@ -162,6 +190,7 @@ private:
static BLocker sSubscriberLock;
static BList sBarTeamInfoList;
static BList sWindowIconCache;
static BList sSubscribers;
};

View File

@ -338,7 +338,7 @@ TBarMenuBar::FetchTeamIcon()
if (fTeamIconData == NULL || fTeamIconSize == 0) {
// we haven't fetched vector icon data yet, fetch it
fTeamIconData = (const uint8*)AppResSet()->FindResource(
B_VECTOR_ICON_TYPE, R_TeamIconVector, &fTeamIconSize);
B_VECTOR_ICON_TYPE, R_TeamIcon, &fTeamIconSize);
}
if (fTeamIconData != NULL && fTeamIconSize > 0) {
@ -349,11 +349,13 @@ TBarMenuBar::FetchTeamIcon()
iconRect.InsetBy(-1, -1);
// grow icon by 1px so that it renders nicely at 12pt font size
BBitmap* icon = new(std::nothrow) BBitmap(iconRect, B_RGBA32);
if (icon != NULL && BIconUtils::GetVectorIcon(fTeamIconData,
fTeamIconSize, icon) == B_OK) {
if (icon != NULL && icon->InitCheck() == B_OK
&& BIconUtils::GetVectorIcon(fTeamIconData, fTeamIconSize, icon)
== B_OK) {
// rasterize vector icon into a bitmap at the scaled size
teamIcon = icon;
}
} else if (icon != NULL)
delete icon;
}
return teamIcon;

View File

@ -41,8 +41,10 @@ All rights reserved.
#include <strings.h>
#include <Bitmap.h>
#include <ControlLook.h>
#include <Debug.h>
#include <Font.h>
#include <LayoutUtils.h>
#include <Mime.h>
#include <Node.h>
#include <NodeInfo.h>
@ -62,9 +64,6 @@ All rights reserved.
// allows you to press 's' to keep the switcher window on screen
static const color_space kIconFormat = B_RGBA32;
class TTeamGroup {
public:
TTeamGroup();
@ -82,10 +81,11 @@ public:
{ return fSignature; }
uint32 Flags() const
{ return fFlags; }
const BBitmap* SmallIcon() const
{ return fSmallIcon; }
const BBitmap* LargeIcon() const
{ return fLargeIcon; }
const BBitmap* SmallIcon() const { return fSmallIcon; }
const BBitmap* LargeIcon() const { return fLargeIcon; }
void CacheTeamIcons(int32 small, int32 large);
private:
BList* fTeams;
@ -105,9 +105,11 @@ public:
virtual bool QuitRequested();
virtual void MessageReceived(BMessage* message);
virtual void ScreenChanged(BRect screenFrame, color_space);
virtual void Show();
virtual void Hide();
virtual void WindowActivated(bool state);
virtual void WorkspaceActivated(int32, bool active);
void DoKey(uint32 key, uint32 modifiers);
TIconView* IconView();
@ -120,6 +122,9 @@ public:
int32 SlotOf(int32);
void Redraw(int32 index);
protected:
void CenterWindow(BRect screenFrame, BSize);
private:
TSwitchManager* fManager;
TIconView* fIconView;
@ -171,14 +176,14 @@ public:
virtual void Draw(BRect updateRect);
void ScrollTo(float x, float y)
{
ScrollTo(BPoint(x, y));
}
virtual void ScrollTo(BPoint where);
{ ScrollTo(BPoint(x, y)); }
virtual void ScrollTo(BPoint where);
void Update(int32 previous, int32 current,
int32 previousSlot, int32 currentSlot,
bool forward);
void DrawTeams(BRect update);
int32 SlotOf(int32) const;
BRect FrameOf(int32) const;
int32 ItemAtPoint(BPoint) const;
@ -186,16 +191,13 @@ public:
void CenterOn(int32 index);
private:
void CacheIcons(TTeamGroup* group);
void AnimateIcon(BBitmap* startIcon, BBitmap* endIcon);
void AnimateIcon(const BBitmap* start, const BBitmap* end);
bool fAutoScrolling;
TSwitcherWindow* fSwitcher;
TSwitchManager* fManager;
BBitmap* fOffBitmap;
BView* fOffView;
BBitmap* fCurrentSmall;
BBitmap* fCurrentLarge;
};
class TBox : public BBox {
@ -221,18 +223,13 @@ private:
};
const int32 kHorizontalMargin = 11;
const int32 kVerticalMargin = 10;
static const int32 kHorizontalMargin = 11;
static const int32 kVerticalMargin = 10;
// SLOT_SIZE must be divisible by 4. That's because of the scrolling
// animation. If this needs to change then look at TIconView::Update()
static const int32 kTeamIconSize = 32;
const int32 kSlotSize = 36;
const int32 kScrollStep = kSlotSize / 2;
const int32 kNumSlots = 7;
const int32 kCenterSlot = 3;
static const int32 kWindowScrollSteps = 3;
const int32 kWindowScrollSteps = 3;
// #pragma mark -
@ -358,21 +355,6 @@ TTeamGroup::TTeamGroup(BList* teams, uint32 flags, char* name,
fLargeIcon(NULL)
{
strlcpy(fSignature, signature, sizeof(fSignature));
fSmallIcon = new BBitmap(BRect(0, 0, 15, 15), kIconFormat);
fLargeIcon = new BBitmap(BRect(0, 0, 31, 31), kIconFormat);
app_info appInfo;
if (be_roster->GetAppInfo(signature, &appInfo) == B_OK) {
BNode node(&(appInfo.ref));
if (node.InitCheck() == B_OK) {
BNodeInfo nodeInfo(&node);
if (nodeInfo.InitCheck() == B_OK) {
nodeInfo.GetTrackerIcon(fSmallIcon, B_MINI_ICON);
nodeInfo.GetTrackerIcon(fLargeIcon, B_LARGE_ICON);
}
}
}
}
@ -380,33 +362,47 @@ TTeamGroup::~TTeamGroup()
{
delete fTeams;
free(fName);
delete fSmallIcon;
delete fLargeIcon;
}
void
TTeamGroup::Draw(BView* view, BRect bounds, bool main)
{
BRect rect;
if (main) {
rect = fLargeIcon->Bounds();
rect.OffsetTo(bounds.LeftTop());
rect.OffsetBy(2, 2);
view->DrawBitmap(fLargeIcon, rect);
} else {
rect = fSmallIcon->Bounds();
rect.OffsetTo(bounds.LeftTop());
rect.OffsetBy(10, 10);
view->DrawBitmap(fSmallIcon, rect);
BRect largeRect = fLargeIcon->Bounds();
largeRect.OffsetTo(bounds.LeftTop());
int32 offset = (bounds.IntegerWidth()
- largeRect.IntegerWidth()) / 2;
largeRect.OffsetBy(offset, offset);
if (main)
view->DrawBitmap(fLargeIcon, largeRect);
else {
BRect smallRect = fSmallIcon->Bounds();
smallRect.OffsetTo(largeRect.LeftTop());
int32 offset = (largeRect.IntegerWidth()
- smallRect.IntegerWidth()) / 2;
smallRect.OffsetBy(BPoint(offset, offset));
view->DrawBitmap(fSmallIcon, smallRect);
}
}
// #pragma mark -
void
TTeamGroup::CacheTeamIcons(int32 smallIconSize, int32 largeIconSize)
{
TBarApp* app = static_cast<TBarApp*>(be_app);
int32 teamCount = TeamList()->CountItems();
for (int32 index = 0; index < teamCount; index++) {
team_id team = (addr_t)TeamList()->ItemAt(index);
fSmallIcon = app->FetchTeamIcon(team, smallIconSize);
fLargeIcon = app->FetchTeamIcon(team, largeIconSize);
}
}
TSwitchManager::TSwitchManager(BPoint point)
// #pragma mark - TSwitchManager
TSwitchManager::TSwitchManager()
: BHandler("SwitchManager"),
fMainMonitor(create_sem(1, "main_monitor")),
fBlock(false),
@ -419,9 +415,29 @@ TSwitchManager::TSwitchManager(BPoint point)
fCurrentSlot(0),
fWindowID(-1)
{
BRect rect(point.x, point.y,
point.x + (kSlotSize * kNumSlots) - 1 + (2 * kHorizontalMargin),
point.y + 82);
fLargeIconSize = kTeamIconSize;
fSmallIconSize = kTeamIconSize / 2;
// get the composed icon size for slot calculation but don't set it
int32 composed = be_control_look->ComposeIconSize(kTeamIconSize)
.IntegerWidth() + 1;
// SLOT_SIZE must be divisible by 4. That's because of the scrolling
// animation. If this needs to change then look at TIconView::Update()
fSlotSize = (composed + composed / 4) & ~3u;
fScrollStep = fSlotSize / 2;
// TODO set these based on screen width
fSlotCount = 7;
fCenterSlot = 3;
font_height plainFontHeight;
be_plain_font->GetHeight(&plainFontHeight);
float plainHeight = plainFontHeight.ascent + plainFontHeight.descent;
BRect rect(0, 0,
(fSlotSize * fSlotCount) - 1 + (2 * kHorizontalMargin),
fSlotSize + (4 * kVerticalMargin) + plainHeight);
fWindow = new TSwitcherWindow(rect, this);
fWindow->AddHandler(this);
@ -436,9 +452,10 @@ TSwitchManager::TSwitchManager(BPoint point)
if (!barTeamInfo)
break;
TTeamGroup* tinfo = new TTeamGroup(barTeamInfo->teams,
TTeamGroup* group = new TTeamGroup(barTeamInfo->teams,
barTeamInfo->flags, barTeamInfo->name, barTeamInfo->sig);
fGroupList.AddItem(tinfo);
group->CacheTeamIcons(fSmallIconSize, fLargeIconSize);
fGroupList.AddItem(group);
barTeamInfo->teams = NULL;
barTeamInfo->name = NULL;
@ -489,59 +506,46 @@ TSwitchManager::MessageReceived(BMessage* message)
case B_SOME_APP_LAUNCHED:
{
BList* teams;
const char* name;
BBitmap* smallIcon;
uint32 flags;
const char* signature;
BList* teams;
if (message->FindString("sig", &signature) != B_OK)
break;
if (message->FindInt32("flags", (int32*)&flags) != B_OK)
break;
if (message->FindString("name", &name) != B_OK)
break;
if (message->FindPointer("teams", (void**)&teams) != B_OK)
break;
if (message->FindPointer("icon", (void**)&smallIcon) != B_OK) {
delete teams;
break;
}
delete smallIcon;
if (message->FindString("sig", &signature) != B_OK) {
delete teams;
break;
}
if (message->FindInt32("flags", (int32*)&flags) != B_OK) {
delete teams;
break;
}
if (message->FindString("name", &name) != B_OK) {
delete teams;
break;
}
TTeamGroup* tinfo = new TTeamGroup(teams, flags, strdup(name),
TTeamGroup* group = new TTeamGroup(teams, flags, strdup(name),
signature);
fGroupList.AddItem(tinfo);
group->CacheTeamIcons(fSmallIconSize, fLargeIconSize);
fGroupList.AddItem(group);
fWindow->Redraw(fGroupList.CountItems() - 1);
break;
}
case kAddTeam:
{
const char* signature = message->FindString("sig");
team_id team = message->FindInt32("team");
int32 count = fGroupList.CountItems();
const char* signature = message->FindString("sig");
for (int32 i = 0; i < count; i++) {
TTeamGroup* tinfo = (TTeamGroup*)fGroupList.ItemAt(i);
if (strcasecmp(tinfo->Signature(), signature) == 0) {
if (!(tinfo->TeamList()->HasItem((void*)(addr_t)team)))
tinfo->TeamList()->AddItem((void*)(addr_t)team);
break;
int32 teamCount = fGroupList.CountItems();
for (int32 index = 0; index < teamCount; index++) {
TTeamGroup* group = (TTeamGroup*)fGroupList.ItemAt(index);
ASSERT(group);
if (strcasecmp(group->Signature(), signature) == 0
&& !group->TeamList()->HasItem((void*)(addr_t)team)) {
group->CacheTeamIcons(fSmallIconSize, fLargeIconSize);
group->TeamList()->AddItem((void*)(addr_t)team);
}
break;
}
break;
}
@ -549,12 +553,12 @@ TSwitchManager::MessageReceived(BMessage* message)
case kRemoveTeam:
{
team_id team = message->FindInt32("team");
int32 count = fGroupList.CountItems();
for (int32 i = 0; i < count; i++) {
TTeamGroup* tinfo = (TTeamGroup*)fGroupList.ItemAt(i);
if (tinfo->TeamList()->HasItem((void*)(addr_t)team)) {
tinfo->TeamList()->RemoveItem((void*)(addr_t)team);
int32 teamCount = fGroupList.CountItems();
for (int32 index = 0; index < teamCount; index++) {
TTeamGroup* group = (TTeamGroup*)fGroupList.ItemAt(index);
ASSERT(group);
if (group->TeamList()->HasItem((void*)(addr_t)team)) {
group->TeamList()->RemoveItem((void*)(addr_t)team);
break;
}
}
@ -739,7 +743,7 @@ TSwitchManager::Process(bool forward, bool byWindow)
fBlock = true;
if (fWindow->Lock()) {
BRect screenFrame = BScreen().Frame();
BRect screenFrame = BScreen(B_MAIN_SCREEN_ID).Frame();
BRect windowFrame = fWindow->Frame();
if (!screenFrame.Contains(windowFrame)) {
@ -861,15 +865,15 @@ TSwitchManager::_FindNextValidApp(bool forward)
void
TSwitchManager::SwitchToApp(int32 previousIndex, int32 newIndex, bool forward)
TSwitchManager::SwitchToApp(int32 previous, int32 current, bool forward)
{
int32 previousSlot = fCurrentSlot;
fCurrentIndex = newIndex;
fCurrentIndex = current;
fCurrentSlot = fWindow->SlotOf(fCurrentIndex);
fCurrentWindow = 0;
fWindow->Update(previousIndex, fCurrentIndex, previousSlot, fCurrentSlot,
fWindow->Update(previous, fCurrentIndex, previousSlot, fCurrentSlot,
forward);
}
@ -968,8 +972,10 @@ TSwitchManager::ActivateApp(bool forceShow, bool allowWorkspaceSwitch)
break;
}
if (matchWindowInfo->server_token != windowInfo->server_token
&& teamGroup->TeamList()->HasItem((void*)(addr_t)matchWindowInfo->team))
windowsToActivate.AddItem((void*)(addr_t)matchWindowInfo->server_token);
&& teamGroup->TeamList()->HasItem(
(void*)(addr_t)matchWindowInfo->team))
windowsToActivate.AddItem(
(void*)(addr_t)matchWindowInfo->server_token);
free(matchWindowInfo);
}
@ -1075,8 +1081,8 @@ TSwitchManager::WindowInfo(int32 groupIndex, int32 windowIndex)
client_window_info* windowInfo = get_window_info(tokens[i]);
if (windowInfo) {
// skip hidden/special windows
if (IsWindowOK(windowInfo)
&& (teamGroup->TeamList()->HasItem((void*)(addr_t)windowInfo->team))) {
if (IsWindowOK(windowInfo) && (teamGroup->TeamList()->HasItem(
(void*)(addr_t)windowInfo->team))) {
// this window belongs to the team!
if (matches == windowIndex) {
// we found it!
@ -1210,6 +1216,14 @@ TSwitchManager::GroupList()
}
BRect
TSwitchManager::CenterRect()
{
return BRect(fCenterSlot * fSlotSize, 0,
(fCenterSlot + 1) * fSlotSize - 1, fSlotSize - 1);
}
// #pragma mark - TBox
@ -1231,8 +1245,7 @@ TBox::TBox(BRect bounds, TSwitchManager* manager, TSwitcherWindow* window,
void
TBox::AllAttached()
{
BRect centerRect(kCenterSlot * kSlotSize, 0,
(kCenterSlot + 1) * kSlotSize - 1, kSlotSize - 1);
BRect centerRect(fManager->CenterRect());
BRect frame = fIconView->Frame();
// scroll the centerRect to correct location
@ -1260,7 +1273,7 @@ TBox::MouseDown(BPoint where)
// Want to scroll by NUMSLOTS - 1 slots
int32 previousIndex = fManager->CurrentIndex();
int32 previousSlot = fManager->CurrentSlot();
int32 newSlot = previousSlot - (kNumSlots - 1);
int32 newSlot = previousSlot - (fManager->SlotCount() - 1);
if (newSlot < 0)
newSlot = 0;
@ -1275,7 +1288,7 @@ TBox::MouseDown(BPoint where)
// Want to scroll by NUMSLOTS - 1 slots
int32 previousIndex = fManager->CurrentIndex();
int32 previousSlot = fManager->CurrentSlot();
int32 newSlot = previousSlot + (kNumSlots - 1);
int32 newSlot = previousSlot + (fManager->SlotCount() - 1);
int32 newIndex = fIconView->IndexAt(newSlot);
if (newIndex < 0) {
@ -1434,7 +1447,7 @@ TBox::DrawIconScrollers(bool force)
bool updateRight = false;
BRect rect = fIconView->Bounds();
if (rect.left > (kSlotSize * kCenterSlot)) {
if (rect.left > (fManager->SlotSize() * fManager->CenterSlot())) {
updateLeft = true;
fLeftScroller = true;
} else {
@ -1610,7 +1623,7 @@ TSwitcherWindow::TSwitcherWindow(BRect frame, TSwitchManager* manager)
rect.OffsetTo(B_ORIGIN);
rect.InsetBy(kHorizontalMargin, 0);
rect.top = kVerticalMargin;
rect.bottom = rect.top + kSlotSize - 1;
rect.bottom = rect.top + fManager->SlotSize() + 1;
fIconView = new TIconView(rect, manager, this);
@ -1634,6 +1647,8 @@ TSwitcherWindow::TSwitcherWindow(BRect frame, TSwitchManager* manager)
float sizeDelta = be_plain_font->Size() - 12;
ResizeBy(0, sizeDelta);
}
CenterWindow(BScreen(B_MAIN_SCREEN_ID).Frame(), frame.Size());
}
@ -1671,6 +1686,33 @@ TSwitcherWindow::MessageReceived(BMessage* message)
}
void
TSwitcherWindow::ScreenChanged(BRect screenFrame, color_space)
{
CenterWindow(screenFrame | BScreen(B_MAIN_SCREEN_ID).Frame(),
Frame().Size());
}
void
TSwitcherWindow::WorkspaceActivated(int32, bool active)
{
if (active)
CenterWindow(BScreen(B_MAIN_SCREEN_ID).Frame(), Frame().Size());
}
void
TSwitcherWindow::CenterWindow(BRect screenFrame, BSize windowSize)
{
BPoint centered = BLayoutUtils::AlignInFrame(screenFrame, windowSize,
BAlignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_VERTICAL_CENTER))
.LeftTop();
MoveTo(centered);
}
void
TSwitcherWindow::Redraw(int32 index)
{
@ -1745,7 +1787,6 @@ TSwitcherWindow::DoKey(uint32 key, uint32 modifiers)
bool
TSwitcherWindow::QuitRequested()
{
((TBarApp*)be_app)->Settings()->switcherLoc = Frame().LeftTop();
fManager->Stop(false, 0);
return false;
}
@ -1760,12 +1801,13 @@ TSwitcherWindow::WindowActivated(bool state)
void
TSwitcherWindow::Update(int32 prev, int32 current, int32 previousSlot,
int32 currentSlot, bool forward)
TSwitcherWindow::Update(int32 previous, int32 current,
int32 previousSlot, int32 currentSlot, bool forward)
{
if (!IsHidden())
fIconView->Update(prev, current, previousSlot, currentSlot, forward);
else
if (!IsHidden()) {
fIconView->Update(previous, current, previousSlot, currentSlot,
forward);
} else
fIconView->CenterOn(current);
fWindowView->UpdateGroup(current, 0);
@ -1836,24 +1878,20 @@ TIconView::TIconView(BRect frame, TSwitchManager* manager,
: BView(frame, "main_view", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED),
fAutoScrolling(false),
fSwitcher(switcherWindow),
fManager(manager)
fManager(manager),
fOffBitmap(NULL),
fOffView(NULL)
{
BRect rect(0, 0, kSlotSize - 1, kSlotSize - 1);
BRect slot(0, 0, fManager->SlotSize() - 1, fManager->SlotSize() - 1);
fOffView = new BView(rect, "off_view", B_FOLLOW_NONE, B_WILL_DRAW);
fOffBitmap = new BBitmap(rect, B_RGB32, true);
fOffView = new BView(slot, "off_view", B_FOLLOW_NONE, B_WILL_DRAW);
fOffBitmap = new BBitmap(slot, B_RGBA32, true);
fOffBitmap->AddChild(fOffView);
fCurrentSmall = new BBitmap(BRect(0, 0, 15, 15), kIconFormat);
fCurrentLarge = new BBitmap(BRect(0, 0, 31, 31), kIconFormat);
}
TIconView::~TIconView()
{
delete fCurrentSmall;
delete fCurrentLarge;
delete fOffBitmap;
}
@ -1864,85 +1902,104 @@ TIconView::KeyDown(const char* /*bytes*/, int32 /*numBytes*/)
void
TIconView::CacheIcons(TTeamGroup* teamGroup)
TIconView::AnimateIcon(const BBitmap* start, const BBitmap* end)
{
const BBitmap* bitmap = teamGroup->SmallIcon();
ASSERT(bitmap);
fCurrentSmall->SetBits(bitmap->Bits(), bitmap->BitsLength(), 0,
bitmap->ColorSpace());
bitmap = teamGroup->LargeIcon();
ASSERT(bitmap);
fCurrentLarge->SetBits(bitmap->Bits(), bitmap->BitsLength(), 0,
bitmap->ColorSpace());
}
void
TIconView::AnimateIcon(BBitmap* startIcon, BBitmap* endIcon)
{
BRect centerRect(kCenterSlot * kSlotSize, 0,
(kCenterSlot + 1) * kSlotSize - 1, kSlotSize - 1);
BRect startIconBounds = startIcon->Bounds();
BRect centerRect(fManager->CenterRect());
BRect bounds = Bounds();
float width = startIconBounds.Width();
int32 amount = (width < 20) ? -2 : 2;
float off = 0;
// center the starting icon inside of centerRect
float off = (centerRect.Width() - width) / 2;
startIconBounds.OffsetTo(BPoint(off, off));
BRect startRect = start->Bounds();
BRect endRect = end->Bounds();
BRect rect = startRect;
int32 small = fManager->SmallIconSize();
bool out = startRect.Width() <= small;
int32 insetValue = small / 8;
int32 inset = out ? -insetValue : insetValue;
// scroll the centerRect to correct location
// center start rect in center rect
off = roundf((centerRect.Width() - rect.Width()) / 2);
startRect.OffsetTo(off, off);
rect.OffsetTo(off, off);
// center end rect in center rect
off = roundf((centerRect.Width() - endRect.Width()) / 2);
endRect.OffsetTo(off, off);
// scroll center rect to the draw slot
centerRect.OffsetBy(bounds.left, 0);
// scroll dest rect to draw slow
BRect destRect = fOffBitmap->Bounds();
// scroll to the centerRect location
destRect.OffsetTo(centerRect.left, 0);
// center the destRect inside of centerRect.
off = (centerRect.Width() - destRect.Width()) / 2;
destRect.OffsetBy(BPoint(off, off));
// center dest rect in center rect
off = roundf((centerRect.Width() - destRect.Width()) / 2);
destRect.OffsetBy(off, off);
fOffBitmap->Lock();
rgb_color backgroundColor = ui_color(B_PANEL_BACKGROUND_COLOR);
if (backgroundColor.Brightness() > 100)
fOffView->SetHighColor(tint_color(backgroundColor, B_DARKEN_1_TINT));
else
fOffView->SetHighColor(tint_color(backgroundColor, 0.85));
rgb_color bg = ui_color(B_PANEL_BACKGROUND_COLOR);
fOffView->SetHighColor(tint_color(bg, bg.Brightness() > 100
? B_DARKEN_1_TINT : 0.85));
// animate start icon
for (int i = 0; i < 2; i++) {
startIconBounds.InsetBy(amount, amount);
rect.InsetBy(inset, inset);
snooze(20000);
fOffView->SetDrawingMode(B_OP_COPY);
fOffView->FillRect(fOffView->Bounds());
fOffView->SetDrawingMode(B_OP_ALPHA);
fOffView->DrawBitmap(startIcon, startIconBounds);
fOffView->DrawBitmap(start, rect);
fOffView->Sync();
DrawBitmap(fOffBitmap, destRect);
}
// draw cached start icon again to clear composed icon rounding errors
fOffView->SetDrawingMode(B_OP_COPY);
fOffView->FillRect(fOffView->Bounds());
fOffView->SetDrawingMode(B_OP_ALPHA);
fOffView->DrawBitmap(start, startRect);
fOffView->Sync();
DrawBitmap(fOffBitmap, destRect);
// animate end icon
for (int i = 0; i < 2; i++) {
startIconBounds.InsetBy(amount, amount);
rect.InsetBy(inset, inset);
snooze(20000);
fOffView->SetDrawingMode(B_OP_COPY);
fOffView->FillRect(fOffView->Bounds());
fOffView->SetDrawingMode(B_OP_ALPHA);
fOffView->DrawBitmap(endIcon, startIconBounds);
fOffView->DrawBitmap(end, rect);
fOffView->Sync();
DrawBitmap(fOffBitmap, destRect);
}
// draw cached end icon again
fOffView->SetDrawingMode(B_OP_COPY);
fOffView->FillRect(fOffView->Bounds());
fOffView->SetDrawingMode(B_OP_ALPHA);
fOffView->DrawBitmap(end, endRect);
fOffView->Sync();
DrawBitmap(fOffBitmap, destRect);
fOffBitmap->Unlock();
}
void
TIconView::Update(int32, int32 current, int32 previousSlot, int32 currentSlot,
bool forward)
TIconView::Update(int32 previous, int32 current,
int32 previousSlot, int32 currentSlot, bool forward)
{
// Animate the shrinking of the currently centered icon.
AnimateIcon(fCurrentLarge, fCurrentSmall);
BList* groupList = fManager->GroupList();
ASSERT(groupList);
// animate shrinking previously centered icon
TTeamGroup* previousGroup = (TTeamGroup*)groupList->ItemAt(previous);
ASSERT(previousGroup);
AnimateIcon(previousGroup->LargeIcon(), previousGroup->SmallIcon());
int32 nslots = abs(previousSlot - currentSlot);
int32 stepSize = kScrollStep;
int32 stepSize = fManager->ScrollStep();
if (forward && (currentSlot < previousSlot)) {
// we were at the end of the list and we just moved to the start
@ -1961,7 +2018,7 @@ TIconView::Update(int32, int32 current, int32 previousSlot, int32 currentSlot,
int32 total = 0;
fAutoScrolling = true;
while (total < (nslots * kSlotSize)) {
while (total < (nslots * fManager->SlotSize())) {
ScrollBy(scrollValue, 0);
snooze(1000);
total += stepSize;
@ -1969,12 +2026,10 @@ TIconView::Update(int32, int32 current, int32 previousSlot, int32 currentSlot,
}
fAutoScrolling = false;
TTeamGroup* teamGroup = (TTeamGroup*)fManager->GroupList()->ItemAt(current);
ASSERT(teamGroup);
CacheIcons(teamGroup);
// Animate the expansion of the currently centered icon
AnimateIcon(fCurrentSmall, fCurrentLarge);
// animate expanding currently centered icon
TTeamGroup* currentGroup = (TTeamGroup*)groupList->ItemAt(current);
ASSERT(group);
AnimateIcon(currentGroup->SmallIcon(), currentGroup->LargeIcon());
}
@ -1982,14 +2037,14 @@ void
TIconView::CenterOn(int32 index)
{
BRect rect = FrameOf(index);
ScrollTo(rect.left - (kCenterSlot * kSlotSize), 0);
ScrollTo(rect.left - (fManager->CenterSlot() * fManager->SlotSize()), 0);
}
int32
TIconView::ItemAtPoint(BPoint point) const
{
return IndexAt((int32)(point.x / kSlotSize) - kCenterSlot);
return IndexAt((int32)(point.x / fManager->SlotSize()) - fManager->CenterSlot());
}
@ -2016,18 +2071,18 @@ TIconView::SlotOf(int32 index) const
{
BRect rect = FrameOf(index);
return (int32)(rect.left / kSlotSize) - kCenterSlot;
return (int32)(rect.left / fManager->SlotSize()) - fManager->CenterSlot();
}
BRect
TIconView::FrameOf(int32 index) const
{
int32 visible = index + kCenterSlot;
int32 visible = index + fManager->CenterSlot();
// first few slots in view are empty
return BRect(visible * kSlotSize, 0, (visible + 1) * kSlotSize - 1,
kSlotSize - 1);
return BRect(visible * fManager->SlotSize(), 0,
(visible + 1) * fManager->SlotSize() - 1, fManager->SlotSize() - 1);
}
@ -2047,26 +2102,24 @@ TIconView::DrawTeams(BRect update)
FillRect(update);
int32 mainIndex = fManager->CurrentIndex();
BList* list = fManager->GroupList();
int32 count = list->CountItems();
BList* groupList = fManager->GroupList();
int32 teamCount = groupList->CountItems();
BRect rect(kCenterSlot * kSlotSize, 0,
(kCenterSlot + 1) * kSlotSize - 1, kSlotSize - 1);
BRect rect(fManager->CenterSlot() * fManager->SlotSize(), 0,
(fManager->CenterSlot() + 1) * fManager->SlotSize() - 1,
fManager->SlotSize() - 1);
for (int32 i = 0; i < count; i++) {
TTeamGroup* teamGroup = (TTeamGroup*)list->ItemAt(i);
if (rect.Intersects(update) && teamGroup) {
for (int32 i = 0; i < teamCount; i++) {
TTeamGroup* group = (TTeamGroup*)groupList->ItemAt(i);
if (rect.Intersects(update) && group != NULL) {
SetDrawingMode(B_OP_ALPHA);
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
teamGroup->Draw(this, rect, !fAutoScrolling && (i == mainIndex));
if (i == mainIndex)
CacheIcons(teamGroup);
group->Draw(this, rect, !fAutoScrolling && (i == mainIndex));
SetDrawingMode(B_OP_COPY);
}
rect.OffsetBy(kSlotSize, 0);
rect.OffsetBy(fManager->SlotSize(), 0);
}
}
@ -2172,7 +2225,8 @@ TWindowView::GetPreferredSize(float* _width, float* _height)
fItemHeight = (int32) fh.ascent + fh.descent;
// top & bottom margin
fItemHeight = fItemHeight + 3 + 3;
float margin = be_control_look->DefaultLabelSpacing();
fItemHeight = fItemHeight + margin * 2;
// want fItemHeight to be divisible by kWindowScrollSteps.
fItemHeight = ((((int)fItemHeight) + kWindowScrollSteps)
@ -2274,8 +2328,19 @@ TWindowView::Draw(BRect update)
if (!title.Length())
return;
float iconWidth = 0;
// get the (cached) window icon bitmap
TBarApp* app = static_cast<TBarApp*>(be_app);
const BBitmap* bitmap = app->FetchWindowIcon(local, minimized);
if (bitmap != NULL)
iconWidth = bitmap->Bounds().Width();
float spacing = be_control_look->DefaultLabelSpacing();
float stringWidth = StringWidth(title.String());
float maxWidth = bounds.Width() - (14 + 5);
float maxWidth = bounds.Width();
if (bitmap != NULL)
maxWidth -= (iconWidth + spacing);
if (stringWidth > maxWidth) {
// window title is too long, need to truncate
@ -2283,35 +2348,33 @@ TWindowView::Draw(BRect update)
stringWidth = maxWidth;
}
BPoint point((bounds.Width() - (stringWidth + 14 + 5)) / 2,
windowRect.bottom - 4);
BPoint p(point.x, (windowRect.top + windowRect.bottom) / 2);
SetDrawingMode(B_OP_OVER);
const BBitmap* bitmap = AppResSet()->FindBitmap(B_MESSAGE_TYPE,
minimized ? R_WindowHiddenIcon : R_WindowShownIcon);
p.y -= (bitmap->Bounds().bottom - bitmap->Bounds().top) / 2;
DrawBitmap(bitmap, p);
if (!local) {
rgb_color color = ui_color(B_PANEL_BACKGROUND_COLOR);
if (color.Brightness() > 100)
SetHighColor(tint_color(color, B_DARKEN_4_TINT));
else
SetHighColor(tint_color(color, B_LIGHTEN_1_TINT));
p.x -= 8;
p.y += 4;
StrokeLine(p + BPoint(2, 2), p + BPoint(2, 2));
StrokeLine(p + BPoint(4, 2), p + BPoint(6, 2));
StrokeLine(p + BPoint(0, 5), p + BPoint(0, 5));
StrokeLine(p + BPoint(2, 5), p + BPoint(6, 5));
StrokeLine(p + BPoint(1, 8), p + BPoint(1, 8));
StrokeLine(p + BPoint(3, 8), p + BPoint(6, 8));
BPoint point((bounds.Width() - stringWidth) / 2, windowRect.bottom);
if (bitmap != NULL) {
point.x = (bounds.Width()
- (stringWidth + iconWidth + spacing)) / 2;
}
BPoint p(point.x, (windowRect.top + windowRect.bottom) / 2);
SetDrawingMode(B_OP_OVER);
// center bitmap horizontally and move text past icon
if (bitmap != NULL) {
p.y -= (bitmap->Bounds().bottom - bitmap->Bounds().top) / 2;
DrawBitmap(bitmap, p);
point.x += bitmap->Bounds().Width() + spacing;
}
// center text vertically
font_height fontHeight;
GetFontHeight(&fontHeight);
float textHeight = fontHeight.ascent + fontHeight.descent;
point.y -= (textHeight / 2) + (spacing / 2);
if (bitmap != NULL) {
// center in middle of window icon
point.y += ((textHeight - bitmap->Bounds().Height()) / 2);
}
point.x += 21;
MovePenTo(point);
SetHighUIColor(B_PANEL_TEXT_COLOR);

View File

@ -52,7 +52,7 @@ struct client_window_info;
class TSwitchManager : public BHandler {
public:
TSwitchManager(BPoint where);
TSwitchManager();
virtual ~TSwitchManager();
virtual void MessageReceived(BMessage* message);
@ -76,6 +76,14 @@ public:
bool inCurrentWorkspace = false);
TTeamGroup* FindTeam(team_id, int32* index);
int32 LargeIconSize() { return fLargeIconSize; }
int32 SmallIconSize() { return fSmallIconSize; }
int32 SlotSize() { return fSlotSize; }
int32 ScrollStep() { return fScrollStep; }
int32 SlotCount() { return fSlotCount; }
int32 CenterSlot() { return fCenterSlot; }
BRect CenterRect();
private:
void MainEntry(BMessage* message);
void Process(bool forward, bool byWindow = false);
@ -101,6 +109,13 @@ private:
int32 fCurrentWindow;
int32 fCurrentSlot;
int32 fWindowID;
int32 fLargeIconSize;
int32 fSmallIconSize;
int32 fSlotSize;
int32 fScrollStep;
int32 fSlotCount;
int32 fCenterSlot;
};

View File

@ -58,17 +58,18 @@ static float sHPad, sVPad, sLabelOffset = 0.0f;
// #pragma mark - TWindowMenuItem
TWindowMenuItem::TWindowMenuItem(const char* name, int32 id, bool mini,
bool currentWorkspace, bool dragging)
TWindowMenuItem::TWindowMenuItem(const char* name, int32 id, bool minimized,
bool local, bool dragging)
:
TTruncatableMenuItem(name, NULL),
fBitmap(NULL),
fID(id),
fMini(mini),
fCurrentWorkSpace(currentWorkspace),
fIsModified(false),
fIsMinimized(minimized),
fIsLocal(local),
fDragging(dragging),
fExpanded(false),
fRequireUpdate(false),
fModified(false)
fRequireUpdate(false)
{
_Init(name);
}
@ -213,8 +214,8 @@ TWindowMenuItem::Invoke(BMessage* /*message*/)
if (item->Menu()->Window() != NULL) {
zoomRect = item->Menu()->ConvertToScreen(item->Frame());
doZoom = (fMini && action == B_BRING_TO_FRONT)
|| (!fMini && action == B_MINIMIZE_WINDOW);
doZoom = (fIsMinimized && action == B_BRING_TO_FRONT)
|| (!fIsMinimized && action == B_MINIMIZE_WINDOW);
}
do_window_action(fID, action, zoomRect, doZoom);
@ -225,14 +226,14 @@ TWindowMenuItem::Invoke(BMessage* /*message*/)
void
TWindowMenuItem::SetTo(const char* name, int32 id, bool mini,
bool currentWorkspace, bool dragging)
TWindowMenuItem::SetTo(const char* name, int32 id, bool minimized,
bool local, bool dragging)
{
fModified = fCurrentWorkSpace != currentWorkspace || fMini != mini;
fIsModified = fIsLocal != local || fIsMinimized != minimized;
fID = id;
fMini = mini;
fCurrentWorkSpace = currentWorkspace;
fIsMinimized = minimized;
fIsLocal = local;
fDragging = dragging;
fRequireUpdate = false;
@ -268,15 +269,8 @@ TWindowMenuItem::_Init(const char* name)
sLabelOffset = ceilf((be_control_look->DefaultLabelSpacing() / 3.0f) * 4.0f);
}
if (fMini) {
fBitmap = fCurrentWorkSpace
? AppResSet()->FindBitmap(B_MESSAGE_TYPE, R_WindowHiddenIcon)
: AppResSet()->FindBitmap(B_MESSAGE_TYPE, R_WindowHiddenSwitchIcon);
} else {
fBitmap = fCurrentWorkSpace
? AppResSet()->FindBitmap(B_MESSAGE_TYPE, R_WindowShownIcon)
: AppResSet()->FindBitmap(B_MESSAGE_TYPE, R_WindowShownSwitchIcon);
}
TBarApp* app = static_cast<TBarApp*>(be_app);
fBitmap = app->FetchWindowIcon(fIsLocal, fIsMinimized);
BFont font(be_plain_font);
fLabelWidth = ceilf(font.StringWidth(name));

View File

@ -51,15 +51,14 @@ public:
bool mini, bool currentWorkSpace,
bool dragging = false);
void SetTo(const char* name, int32 id, bool mini,
bool currentWorkSpace,
bool dragging = false);
void SetTo(const char* name, int32 id, bool minimized,
bool local, bool dragging = false);
bool Expanded() const { return fExpanded; };
void SetExpanded(bool expand) { fExpanded = expand; };
int32 ID() const { return fID; };
bool Modified() const { return fModified; };
bool Modified() const { return fIsModified; };
bool RequiresUpdate() { return fRequireUpdate; };
void SetRequireUpdate(bool update)
@ -77,17 +76,21 @@ protected:
private:
void _Init(const char* name);
int32 fID;
bool fMini;
bool fCurrentWorkSpace;
private:
const BBitmap* fBitmap;
int32 fID;
float fLabelWidth;
float fLabelAscent;
float fLabelDescent;
bool fDragging;
bool fExpanded;
bool fRequireUpdate;
bool fModified;
bool fIsModified : 1;
bool fIsMinimized : 1;
bool fIsLocal : 1;
bool fDragging : 1;
bool fExpanded : 1;
bool fRequireUpdate : 1;
};

View File

@ -8,6 +8,5 @@ enum {
R_WindowHiddenIcon = 21,
R_ResizeIcon = 22,
R_WindowShownSwitchIcon = 23,
R_WindowHiddenSwitchIcon = 24,
R_TeamIconVector = 25
R_WindowHiddenSwitchIcon = 24
};

View File

@ -1,7 +1,7 @@
#include "icons.h"
resource(R_LeafLogoBitmap) #'VICN' array {
resource(R_LeafLogoBitmap) vector_icon {
$"6E6369660102010602438798C0E5A13DF937406BAE4D330E4CA0420000AAFFFF"
$"00337F010216C676C7BCC676C7BCCDE4CEECDD2DCFB2D596D105DBF0CEC5DAD9"
$"CCB5DB59CDA2E352D196EA2CC98EE790CB83E947C8D3E65EC72EE82DC964E8B0"
@ -81,32 +81,7 @@ resource(R_SmallNewGroupIcon) archive(, 0x00000000) BBitmap {
}
};
resource(R_TeamIcon) archive(, 0x00000000) BBitmap {
"_frame" = rect { 0.0, 0.0, 19.0, 15.0 },
"_cspace" = 4,
"_bmflags" = 1,
"_rowbytes" = 20,
"_data" = array {
$"FFFF0000000000000000000000000000FFFFFFFF"
$"FFFF008F8F8F8F8F8F8F8F8F8F00000000FFFFFF"
$"FFFF008F8F8F8F8F0000000000D9D90000FFFFFF"
$"FFFF008F8F3F8F3F00D9001B00D9D9AA01FFFFFF"
$"FFFF008F3F3F3F3F8F8F00001500000A0016FFFF"
$"FFFF008F8F3F8F3F3F8F8F8F001B151C1C00FFFF"
$"FFFF008F8F3F8F3F8F8F8F8F0015150B1B00FFFF"
$"FFFF008F8F8F8F8F8F8F8F8F8F0100001C00FFFF"
$"FFFF008F8F8F8F8F8F8F8F8F8F0166001C00FFFF"
$"FFFF00000000000000000000000066660000FFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFF0066660000FFFF"
$"FFFFFFFFFFFFFFFFFF000000000000000000FFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFF0066668D00FFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFF0066668D00FFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFF0000AAAA0011FFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFF000000000011FFFF"
}
};
resource(R_TeamIconVector) #'VICN' array {
resource(R_TeamIcon) vector_icon {
$"6E6369661905FF03000001020006023F900F3DA311BDA3113F900F49E579C426"
$"607B77AD779F66986605F905F905F9020006023D81E73ACACFBCF5653FB7664A"
$"22313F685CA6A4D0FFB781C0FF036697CB020006023C194E3ADC9FBE40D23F4E"
@ -178,54 +153,20 @@ resource(R_GenericAppIcon) archive(, 0x00000000) BBitmap {
}
};
resource(R_WindowShownIcon) archive(, 0x00000000) BBitmap {
"_frame" = rect { 0.0, 0.0, 15.0, 15.0 },
"_cspace" = 4,
"_bmflags" = 1,
"_rowbytes" = 16,
"_data" = array {
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FF0F0F0F0F0F0F0F0F0FFFFFFFFFFFFF"
$"FF0FFCFCFCFCFCFCFC00FFFFFFFFFFFF"
$"FF0FBDBDBDBDBDBDBD0F0F0F0F0FFFFF"
$"FF0F191919191919191919191900FFFF"
$"FF0F193F3F3F3F3F3F3F3F3F1900FFFF"
$"FF0F193F3F3F3F3F3F3F3F3F1900FFFF"
$"FF0F193F3F3F3F3F3F3F3F3F1900FFFF"
$"FF0F193F3F3F3F3F3F3F3F3F1900FFFF"
$"FF0F193F3F3F3F3F3F3F3F3F1900FFFF"
$"FF0F193F3F3F3F3F3F3F3F3F1900FFFF"
$"FF0F193F3F3F3F3F3F3F3F3F1900FFFF"
$"FF0F193F3F3F3F3F3F3F3F3F1900FFFF"
$"FF0F191919191919191919191900FFFF"
$"FF00000000000000000000000000FFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
}
resource(R_WindowShownIcon) vector_icon {
$"6E63696605050005FF0578020006020000003A0000C000000000004BFFFF43FF"
$"FF9AFFFF65FFFFAF1205C8050A0620585458542C502C505420540A0A24542424"
$"4024402C542C542844284420202020540A042020202C402C40200A04202C2058"
$"5458542C0A044024402844284424060A030102202C240A040103202C240A0101"
$"03023EC4EC0000000000003EE8BA48800046D1740A020101202C240A00010020"
$"2C240A000104202C24"
};
resource(R_WindowHiddenIcon) archive(, 0x00000000) BBitmap {
"_frame" = rect { 0.0, 0.0, 15.0, 15.0 },
"_cspace" = 4,
"_bmflags" = 1,
"_rowbytes" = 16,
"_data" = array {
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FF0F0F0F0F0F0F0F0F0FFFFFFFFFFFFF"
$"FF0F1313131313131300FFFFFFFFFFFF"
$"FF0F131313131313130F0F0F0F0FFFFF"
$"FF0F191919191919191919191900FFFF"
$"FF0F191919191919191919191900FFFF"
$"FF0F191919191919191919191900FFFF"
$"FF0F191919191919191919191900FFFF"
$"FF0F191919191919191919191900FFFF"
$"FF0F191919191919191919191900FFFF"
$"FF0F191919191919191919191900FFFF"
$"FF0F191919191919191919191900FFFF"
$"FF0F191919191919191919191900FFFF"
$"FF0F191919191919191919191900FFFF"
$"FF00000000000000000000000000FFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
}
resource(R_WindowHiddenIcon) vector_icon {
$"6E6369660405000578059805C8050A0620585458542C502C505420540A0A2454"
$"24244024402C542C542844284420202020540A042020202C402C40200A04202C"
$"20585458542C0A044024402844284424050A020102202C240A030103202C240A"
$"010101202C240A000100202C240A000104202C24"
};
resource(R_ResizeIcon) archive(, 0x00000000) BBitmap {
@ -245,52 +186,26 @@ resource(R_ResizeIcon) archive(, 0x00000000) BBitmap {
}
};
resource(R_WindowShownSwitchIcon) archive(, 0x00000000) BBitmap {
"_frame" = rect { 0.0, 0.0, 23.0, 15.0 },
"_cspace" = 4,
"_bmflags" = 1,
"_rowbytes" = 24,
"_data" = array {
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFF0C0C0C0C0C0C0C0C0CFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFF0CFAFAFAFAFAFAFA00FFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFF0CF9F9F9F9F9F9F90C0C0C0C0CFFFF"
$"FFFFFFFFFFFFFFFFFF0C191919191919191919191900FFFF"
$"FFFFFFFFFFFFFFFFFF0C193F3F3F3F3F3F3F3F3F1900FFFF"
$"FFFF0CFF0C0C0CFFFF0C193F3F3F3F3F3F3F3F3F1900FFFF"
$"FFFFFFFFFFFFFFFFFF0C193F3F3F3F3F3F3F3F3F1900FFFF"
$"FFFFFFFFFFFFFFFFFF0C193F3F3F3F3F3F3F3F3F1900FFFF"
$"0CFF0C0C0C0C0CFFFF0C193F3F3F3F3F3F3F3F3F1900FFFF"
$"FFFFFFFFFFFFFFFFFF0C193F3F3F3F3F3F3F3F3F1900FFFF"
$"FFFFFFFFFFFFFFFFFF0C193F3F3F3F3F3F3F3F3F1900FFFF"
$"FF0CFF0C0C0C0CFFFF0C193F3F3F3F3F3F3F3F3F1900FFFF"
$"FFFFFFFFFFFFFFFFFF0C191919191919191919191900FFFF"
$"FFFFFFFFFFFFFFFFFF00000000000000000000000000FFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
}
resource(R_WindowShownSwitchIcon) vector_icon {
$"6E63696605050005FF0578020006020000003A0000C000000000004BFFFF43FF"
$"FF9AFFFF65FFFFAF1205C8060A0620585458542C502C505420540A0A24542424"
$"4024402C542C542844284420202020540A042020202C402C40200A04202C2058"
$"5458542C0A0440244028442844240A0450305050305030300C0A030102202C24"
$"0A040103202C240A010103023EC4EC0000000000003EE8BA48800046D1740A02"
$"0101202C240A000100202C240A000104202C240A020105023C00000000000000"
$"003800008D6DB64900000A020105023A00000000000000003800004500004A00"
$"000A02010502380000000000000000380000C000004900000A0201050237FFFF"
$"0000000000003800004300004A00000A0201050237FFFF000000000000380000"
$"4000004A80000A020105023B000000000000000038000042FFFF4A8000"
};
resource(R_WindowHiddenSwitchIcon) archive(, 0x00000000) BBitmap {
"_frame" = rect { 0.0, 0.0, 23.0, 15.0 },
"_cspace" = 4,
"_bmflags" = 1,
"_rowbytes" = 24,
"_data" = array {
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFF0C0C0C0C0C0C0C0C0CFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFF0C1010101010101000FFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFF0C101010101010100C0C0C0C0CFFFF"
$"FFFFFFFFFFFFFFFFFF0C191919191919191919191900FFFF"
$"FFFFFFFFFFFFFFFFFF0C191919191919191919191900FFFF"
$"FFFF0CFF0C0C0CFFFF0C191919191919191919191900FFFF"
$"FFFFFFFFFFFFFFFFFF0C191919191919191919191900FFFF"
$"FFFFFFFFFFFFFFFFFF0C191919191919191919191900FFFF"
$"0CFF0C0C0C0C0CFFFF0C191919191919191919191900FFFF"
$"FFFFFFFFFFFFFFFFFF0C191919191919191919191900FFFF"
$"FFFFFFFFFFFFFFFFFF0C191919191919191919191900FFFF"
$"FF0CFF0C0C0C0CFFFF0C191919191919191919191900FFFF"
$"FFFFFFFFFFFFFFFFFF0C191919191919191919191900FFFF"
$"FFFFFFFFFFFFFFFFFF00000000000000000000000000FFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
}
resource(R_WindowHiddenSwitchIcon) vector_icon {
$"6E6369660405000578059805C8050A0620585458542C502C505420540A0A2454"
$"24244024402C542C542844284420202020540A042020202C402C40200A04202C"
$"20585458542C0A0440244028442844240B0A020102202C240A030103202C240A"
$"010101202C240A000100202C240A000104202C240A0101040242000000000000"
$"00003E0000CBC00048E0000A010104023E00000000000000003E0000C8000048"
$"E0000A010104023DFFFF0000000000003E0000C6FFFF49E0000A010104023DFF"
$"FF0000000000003E0000C77FFF4A70000A010104024000000000000000003E00"
$"00C8FFFF49E0000A010104024100000000000000003E0000CAA0004A7000"
};