Add multi tab support to the default decorator as discussed on the mailing list. Windows can be stacked on top of one another. All windows using the same decorator instance. This makes it easier to draw the stacked tabs and makes it possible to design more fancy looks for stacked windows. This also helps to fix some issues in S&T, e.g. when activating one window in a stacked group all windows have to be activated to ensure that all tabs are on top. This causes some flickering in tracker.

* Each Window has a reference counted WindowStack class which can be shared between stacked Windows. To keep the Decorator separated from Window there is another tab list in the Decorator now. The index of the stacked Window in the window stack is the same as the index of the tab in the Decorator. Properties like title or window focus are managed on a per tab basis now. This mean when you set the title in the Decorator you also have to specify the tab id which is equal to the window position in the stack.

* When drawing the decorator its important that only the top window is doing the drawing. Also the top window drawing engine should be used.
Actually that is only a problem directly after a window is stacked and the other window has still a none empty dirty region. In this case we clear the dirty region of this window and stop the drawing (the top window will draw everything).

* Track if shifting of a tab is still ongoing, i.e. mouse still down.

* The key event filter called the DesktopListener without holding the window write lock. This probably caused #7801 and #7796.

* Commented out assert's in Window::SetScreen and Window::Screen. Add TODO because I'm not sure about the screen access.

This breaks all existing decorators again, sorry guys! Haven't looked into any other then the default decorator (and the SAT decorator). Will not fix the others in the near future so go for it! Since applications should be able to rely on S&T features the other decorator must be able to handle multiple tabs as well. A simple solution would be to draw all title bars in multiple rows. That probably looks quit poorly. Think the better solution would be to draw a tab interface in the title bar, e.g. like in KDE.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42478 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Clemens Zeidler
2011-07-25 01:09:26 +00:00
parent 5b1742af27
commit bb2e9b06ac
14 changed files with 1666 additions and 660 deletions
+5 -4
View File
@@ -65,15 +65,16 @@ DecorAddOn::AllocateDecorator(Desktop* desktop, DrawingEngine* engine,
DesktopSettings settings(desktop);
Decorator* decorator;
decorator = _AllocateDecorator(settings, rect, look, flags);
desktop->UnlockSingleWindow();
if (!decorator)
return NULL;
decorator->SetDrawingEngine(engine);
decorator->SetTitle(title);
if (decorator->AddTab(title) == false) {
delete decorator;
return NULL;
}
decorator->SetDrawingEngine(engine);
return decorator;
}
+363 -175
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2010, Haiku.
* Copyright 2001-2011, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -22,6 +22,22 @@
#include "DrawingEngine.h"
Decorator::Tab::Tab()
:
zoomRect(),
closeRect(),
minimizeRect(),
closePressed(false),
zoomPressed(false),
minimizePressed(false),
isFocused(false),
title("")
{
}
/*! \brief Constructor
Does general initialization of internal data members and creates a colorset
@@ -41,19 +57,12 @@ Decorator::Decorator(DesktopSettings& settings, BRect rect, window_look look,
fLook(look),
fFlags(flags),
fZoomRect(),
fCloseRect(),
fMinimizeRect(),
fTabRect(),
fTitleBarRect(),
fFrame(rect),
fResizeRect(),
fBorderRect(),
fClosePressed(false),
fZoomPressed(false),
fMinimizePressed(false),
fIsFocused(false),
fTitle(""),
fTopTab(NULL),
fFootprintValid(false)
{
@@ -71,6 +80,89 @@ Decorator::~Decorator()
}
Decorator::Tab*
Decorator::AddTab(const char* title, int32 index, BRegion* updateRegion)
{
Decorator::Tab* tab = _AllocateNewTab();
if (tab == NULL)
return NULL;
tab->title = title;
bool ok = false;
if (index >= 0) {
if (fTabList.AddItem(tab, index) == true)
ok = true;
} else if (fTabList.AddItem(tab) == true)
ok = true;
if (ok == false) {
delete tab;
return NULL;
}
if (_AddTab(index, updateRegion) == false) {
fTabList.RemoveItem(tab);
delete tab;
return NULL;
}
if (fTopTab == NULL)
fTopTab = tab;
_InvalidateFootprint();
return tab;
}
bool
Decorator::RemoveTab(int32 index, BRegion* updateRegion)
{
Decorator::Tab* tab = fTabList.RemoveItemAt(index);
if (tab == NULL)
return false;
_RemoveTab(index, updateRegion);
delete tab;
_InvalidateFootprint();
return true;
}
bool
Decorator::MoveTab(int32 from, int32 to, bool isMoving, BRegion* updateRegion)
{
if (_MoveTab(from, to, isMoving, updateRegion) == false)
return false;
if (fTabList.MoveItem(from, to) == false) {
// move the tab back
_MoveTab(from, to, isMoving, updateRegion);
return false;
}
return true;
}
int32
Decorator::TabAt(const BPoint& where) const
{
for (int32 i = 0; i < fTabList.CountItems(); i++) {
Decorator::Tab* tab = fTabList.ItemAt(i);
if (tab->tabRect.Contains(where))
return i;
}
return -1;
}
void
Decorator::SetTopTap(int32 tab)
{
fTopTab = fTabList.ItemAt(tab);
}
/*! \brief Assigns a display driver to the decorator
\param driver A valid DrawingEngine object
*/
@@ -132,71 +224,6 @@ Decorator::SetLook(DesktopSettings& settings, window_look look,
}
/*! \brief Sets the close button's value.
Note that this does not update the button's look - it just updates the
internal button value
\param is_down Whether the button is down or not
*/
void
Decorator::SetClose(bool pressed)
{
if (pressed != fClosePressed) {
fClosePressed = pressed;
DrawClose();
}
}
/*! \brief Sets the minimize button's value.
Note that this does not update the button's look - it just updates the
internal button value
\param is_down Whether the button is down or not
*/
void
Decorator::SetMinimize(bool pressed)
{
if (pressed != fMinimizePressed) {
fMinimizePressed = pressed;
DrawMinimize();
}
}
/*! \brief Sets the zoom button's value.
Note that this does not update the button's look - it just updates the
internal button value
\param is_down Whether the button is down or not
*/
void
Decorator::SetZoom(bool pressed)
{
if (pressed != fZoomPressed) {
fZoomPressed = pressed;
DrawZoom();
}
}
/*! \brief Updates the value of the decorator title
\param string New title value
*/
void
Decorator::SetTitle(const char* string, BRegion* updateRegion)
{
fTitle.SetTo(string);
_SetTitle(string, updateRegion);
_InvalidateFootprint();
// the border very likely changed
// TODO: redraw?
}
/*! \brief Returns the decorator's window look
\return the decorator's window look
*/
@@ -217,16 +244,6 @@ Decorator::Flags() const
}
/*! \brief Returns the decorator's title
\return the decorator's title
*/
const char*
Decorator::Title() const
{
return fTitle.String();
}
/*! \brief Returns the decorator's border rectangle
\return the decorator's border rectangle
*/
@@ -237,52 +254,149 @@ Decorator::BorderRect() const
}
BRect
Decorator::TitleBarRect() const
{
return fTitleBarRect;
}
/*! \brief Returns the decorator's tab rectangle
\return the decorator's tab rectangle
*/
BRect
Decorator::TabRect() const
Decorator::TabRect(int32 tab) const
{
return fTabRect;
Decorator::Tab* decoratorTab = fTabList.ItemAt(tab);
if (decoratorTab == NULL)
return BRect();
return decoratorTab->tabRect;
}
/*! \brief Returns the value of the close button
\return true if down, false if up
BRect
Decorator::TabRect(Decorator::Tab* tab) const
{
return tab->tabRect;
}
/*! \brief Sets the close button's value.
Note that this does not update the button's look - it just updates the
internal button value
\param is_down Whether the button is down or not
*/
bool
Decorator::GetClose()
{
return fClosePressed;
}
/*! \brief Returns the value of the minimize button
\return true if down, false if up
*/
bool
Decorator::GetMinimize()
{
return fMinimizePressed;
}
/*! \brief Returns the value of the zoom button
\return true if down, false if up
*/
bool
Decorator::GetZoom()
{
return fZoomPressed;
}
void
Decorator::GetSizeLimits(int32* minWidth, int32* minHeight, int32* maxWidth,
int32* maxHeight) const
Decorator::SetClose(int32 tab, bool pressed)
{
Decorator::Tab* decoratorTab = fTabList.ItemAt(tab);
if (decoratorTab == NULL)
return;
if (pressed != decoratorTab->closePressed) {
decoratorTab->closePressed = pressed;
DrawClose(tab);
}
}
/*! \brief Sets the minimize button's value.
Note that this does not update the button's look - it just updates the
internal button value
\param is_down Whether the button is down or not
*/
void
Decorator::SetMinimize(int32 tab, bool pressed)
{
Decorator::Tab* decoratorTab = fTabList.ItemAt(tab);
if (decoratorTab == NULL)
return;
if (pressed != decoratorTab->minimizePressed) {
decoratorTab->minimizePressed = pressed;
DrawMinimize(tab);
}
}
/*! \brief Sets the zoom button's value.
Note that this does not update the button's look - it just updates the
internal button value
\param is_down Whether the button is down or not
*/
void
Decorator::SetZoom(int32 tab, bool pressed)
{
Decorator::Tab* decoratorTab = fTabList.ItemAt(tab);
if (decoratorTab == NULL)
return;
if (pressed != decoratorTab->zoomPressed) {
decoratorTab->zoomPressed = pressed;
DrawZoom(tab);
}
}
/*! \brief Updates the value of the decorator title
\param string New title value
*/
void
Decorator::SetTitle(int32 tab, const char* string, BRegion* updateRegion)
{
Decorator::Tab* decoratorTab = fTabList.ItemAt(tab);
if (decoratorTab == NULL)
return;
decoratorTab->title.SetTo(string);
_SetTitle(decoratorTab, string, updateRegion);
_InvalidateFootprint();
// the border very likely changed
// TODO: redraw?
}
/*! \brief Returns the decorator's title
\return the decorator's title
*/
const char*
Decorator::Title(int32 tab) const
{
Decorator::Tab* decoratorTab = fTabList.ItemAt(tab);
if (decoratorTab == NULL)
return "";
return decoratorTab->title;
}
const char*
Decorator::Title(Decorator::Tab* tab) const
{
return tab->title;
}
bool
Decorator::SetTabLocation(int32 tab, float location, bool isShifting,
BRegion* updateRegion)
{
Decorator::Tab* decoratorTab = fTabList.ItemAt(tab);
if (decoratorTab == NULL)
return false;
if (_SetTabLocation(decoratorTab, location, isShifting, updateRegion)) {
_InvalidateFootprint();
return true;
}
return false;
}
/*! \brief Changes the focus value of the decorator
@@ -292,14 +406,41 @@ Decorator::GetSizeLimits(int32* minWidth, int32* minHeight, int32* maxWidth,
\param active True if active, false if not
*/
void
Decorator::SetFocus(bool active)
Decorator::SetFocus(int32 tab, bool active)
{
fIsFocused = active;
_SetFocus();
Decorator::Tab* decoratorTab = fTabList.ItemAt(tab);
if (decoratorTab == NULL)
return;
decoratorTab->isFocused = active;
_SetFocus(decoratorTab);
// TODO: maybe it would be cleaner to handle the redraw here.
}
bool
Decorator::IsFocus(int32 tab) const
{
Decorator::Tab* decoratorTab = fTabList.ItemAt(tab);
if (decoratorTab == NULL)
return false;
return decoratorTab->isFocused;
};
bool
Decorator::IsFocus(Decorator::Tab* tab) const
{
return tab->isFocused;
}
void
Decorator::GetSizeLimits(int32* minWidth, int32* minHeight, int32* maxWidth,
int32* maxHeight) const
{
}
// #pragma mark - virtual methods
@@ -339,14 +480,25 @@ Decorator::GetFootprint()
- \c REGION_RIGHT_BOTTOM_CORNER The right-bottom corner.
*/
Decorator::Region
Decorator::RegionAt(BPoint where) const
Decorator::RegionAt(BPoint where, int32& tabIndex) const
{
if (fCloseRect.Contains(where))
return REGION_CLOSE_BUTTON;
if (fZoomRect.Contains(where))
return REGION_ZOOM_BUTTON;
if (fTabRect.Contains(where))
return REGION_TAB;
tabIndex = -1;
for (int32 i = 0; i < fTabList.CountItems(); i++) {
Decorator::Tab* tab = fTabList.ItemAt(i);
if (tab->closeRect.Contains(where)) {
tabIndex = i;
return REGION_CLOSE_BUTTON;
}
if (tab->zoomRect.Contains(where)) {
tabIndex = i;
return REGION_ZOOM_BUTTON;
}
if (tab->tabRect.Contains(where)) {
tabIndex = i;
return REGION_TAB;
}
}
return REGION_NONE;
}
@@ -411,17 +563,6 @@ Decorator::ResizeBy(BPoint offset, BRegion* dirty)
}
bool
Decorator::SetTabLocation(float location, BRegion* updateRegion)
{
if (_SetTabLocation(location, updateRegion)) {
_InvalidateFootprint();
return true;
}
return false;
}
/*! \brief Sets a specific highlight for a decorator region.
Can be overridden by derived classes, but the base class version must be
@@ -434,7 +575,8 @@ Decorator::SetTabLocation(float location, BRegion* updateRegion)
\return \c true, if the highlight could be applied.
*/
bool
Decorator::SetRegionHighlight(Region region, uint8 highlight, BRegion* dirty)
Decorator::SetRegionHighlight(Region region, uint8 highlight, BRegion* dirty,
int32 tab)
{
int32 index = (int32)region - 1;
if (index < 0 || index >= REGION_COUNT - 1)
@@ -479,7 +621,7 @@ void
Decorator::Draw(BRect rect)
{
_DrawFrame(rect & fFrame);
_DrawTab(rect & fTabRect);
_DrawTabs(rect & fTitleBarRect);
}
@@ -488,15 +630,7 @@ void
Decorator::Draw()
{
_DrawFrame(fFrame);
_DrawTab(fTabRect);
}
//! Draws the close button
void
Decorator::DrawClose()
{
_DrawClose(fCloseRect);
_DrawTabs(fTitleBarRect);
}
@@ -508,39 +642,63 @@ Decorator::DrawFrame()
}
//! draws the minimize button
//! draws the tab, title, and buttons
void
Decorator::DrawMinimize()
Decorator::DrawTab(int32 tabIndex)
{
_DrawTab(fMinimizeRect);
Decorator::Tab* tab = fTabList.ItemAt(tabIndex);
if (tab == NULL)
return;
_DrawTab(tab, tab->tabRect);
_DrawZoom(tab, tab->zoomRect);
_DrawMinimize(tab, tab->minimizeRect);
_DrawTitle(tab, tab->tabRect);
_DrawClose(tab, tab->closeRect);
}
//! draws the tab, title, and buttons
//! Draws the close button
void
Decorator::DrawTab()
Decorator::DrawClose(int32 tab)
{
_DrawTab(fTabRect);
_DrawZoom(fZoomRect);
_DrawMinimize(fMinimizeRect);
_DrawTitle(fTabRect);
_DrawClose(fCloseRect);
Decorator::Tab* decoratorTab = fTabList.ItemAt(tab);
if (decoratorTab == NULL)
return;
_DrawClose(decoratorTab, decoratorTab->closeRect);
}
//! draws the minimize button
void
Decorator::DrawMinimize(int32 tab)
{
Decorator::Tab* decoratorTab = fTabList.ItemAt(tab);
if (decoratorTab == NULL)
return;
_DrawTab(decoratorTab, decoratorTab->minimizeRect);
}
//! draws the title
void
Decorator::DrawTitle()
Decorator::DrawTitle(int32 tab)
{
_DrawTitle(fTabRect);
Decorator::Tab* decoratorTab = fTabList.ItemAt(tab);
if (decoratorTab == NULL)
return;
_DrawTitle(decoratorTab, decoratorTab->tabRect);
}
//! draws the zoom button
void
Decorator::DrawZoom()
Decorator::DrawZoom(int32 tab)
{
_DrawZoom(fZoomRect);
Decorator::Tab* decoratorTab = fTabList.ItemAt(tab);
if (decoratorTab == NULL)
return;
_DrawZoom(decoratorTab, decoratorTab->zoomRect);
}
@@ -582,6 +740,24 @@ Decorator::_DrawFrame(BRect rect)
}
void
Decorator::_DrawTabs(BRect rect)
{
Decorator::Tab* focusTab = NULL;
for (int32 i = 0; i < fTabList.CountItems(); i++) {
Decorator::Tab* tab = fTabList.ItemAt(i);
if (tab->isFocused) {
focusTab = tab;
continue;
}
_DrawTab(tab, rect);
}
if (focusTab != NULL)
_DrawTab(focusTab, rect);
}
/*! \brief Actually draws the tab
This function is called when the tab itself needs drawn. Other items,
@@ -590,7 +766,7 @@ Decorator::_DrawFrame(BRect rect)
\param rect Area of the tab to update
*/
void
Decorator::_DrawTab(BRect rect)
Decorator::_DrawTab(Decorator::Tab* tab, BRect rect)
{
}
@@ -603,7 +779,7 @@ Decorator::_DrawTab(BRect rect)
\param rect Area of the button to update
*/
void
Decorator::_DrawClose(BRect rect)
Decorator::_DrawClose(Decorator::Tab* tab, BRect rect)
{
}
@@ -618,7 +794,7 @@ Decorator::_DrawClose(BRect rect)
\param rect area of the title to update
*/
void
Decorator::_DrawTitle(BRect rect)
Decorator::_DrawTitle(Decorator::Tab* tab, BRect rect)
{
}
@@ -631,7 +807,7 @@ Decorator::_DrawTitle(BRect rect)
\param rect Area of the button to update
*/
void
Decorator::_DrawZoom(BRect rect)
Decorator::_DrawZoom(Decorator::Tab* tab, BRect rect)
{
}
@@ -644,14 +820,22 @@ Decorator::_DrawZoom(BRect rect)
\param rect Area of the button to update
*/
void
Decorator::_DrawMinimize(BRect rect)
Decorator::_DrawMinimize(Decorator::Tab* tab, BRect rect)
{
}
bool
Decorator::_SetTabLocation(Decorator::Tab* tab, float location, bool isShifting,
BRegion* /*updateRegion*/)
{
return false;
}
//! Hook function called when the decorator changes focus
void
Decorator::_SetFocus()
Decorator::_SetFocus(Decorator::Tab* tab)
{
}
@@ -680,11 +864,15 @@ Decorator::_SetFlags(uint32 flags, BRegion* updateRegion)
void
Decorator::_MoveBy(BPoint offset)
{
fZoomRect.OffsetBy(offset);
fCloseRect.OffsetBy(offset);
fMinimizeRect.OffsetBy(offset);
fMinimizeRect.OffsetBy(offset);
fTabRect.OffsetBy(offset);
for (int32 i = 0; i < fTabList.CountItems(); i++) {
Decorator::Tab* tab = fTabList.ItemAt(i);
tab->zoomRect.OffsetBy(offset);
tab->closeRect.OffsetBy(offset);
tab->minimizeRect.OffsetBy(offset);
tab->tabRect.OffsetBy(offset);
}
fTitleBarRect.OffsetBy(offset);
fFrame.OffsetBy(offset);
fResizeRect.OffsetBy(offset);
fBorderRect.OffsetBy(offset);
+93 -64
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2010, Haiku.
* Copyright 2001-2011, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -27,6 +27,25 @@ class BRegion;
class Decorator {
public:
class Tab {
public:
Tab();
virtual ~Tab() {}
BRect zoomRect;
BRect closeRect;
BRect minimizeRect;
BRect tabRect;
bool closePressed : 1;
bool zoomPressed : 1;
bool minimizePressed : 1;
bool isFocused : 1;
BString title;
};
enum Region {
REGION_NONE,
@@ -61,6 +80,19 @@ public:
window_look look, uint32 flags);
virtual ~Decorator();
virtual Decorator::Tab* AddTab(const char* title, int32 index = -1,
BRegion* updateRegion = NULL);
virtual bool RemoveTab(int32 index,
BRegion* updateRegion = NULL);
virtual bool MoveTab(int32 from, int32 to, bool isMoving,
BRegion* updateRegion = NULL);
virtual int32 TabAt(const BPoint& where) const;
Decorator::Tab* TabAt(int32 index)
{ return fTabList.ItemAt(index); }
int32 CountTabs() const
{ return fTabList.CountItems(); }
void SetTopTap(int32 tab);
void SetDrawingEngine(DrawingEngine *driver);
inline DrawingEngine* GetDrawingEngine() const
{ return fDrawingEngine; }
@@ -72,52 +104,50 @@ public:
void SetFlags(uint32 flags,
BRegion* updateRegion = NULL);
void SetClose(bool pressed);
void SetMinimize(bool pressed);
void SetZoom(bool pressed);
void SetTitle(const char* string,
BRegion* updateRegion = NULL);
window_look Look() const;
uint32 Flags() const;
const char* Title() const;
BRect BorderRect() const;
BRect TabRect() const;
BRect TitleBarRect() const;
BRect TabRect(int32 tab) const;
BRect TabRect(Decorator::Tab* tab) const;
bool GetClose();
bool GetMinimize();
bool GetZoom();
void SetClose(int32 tab, bool pressed);
void SetMinimize(int32 tab, bool pressed);
void SetZoom(int32 tab, bool pressed);
const char* Title(int32 tab) const;
const char* Title(Decorator::Tab* tab) const;
void SetTitle(int32 tab, const char* string,
BRegion* updateRegion = NULL);
void SetFocus(int32 tab, bool focussed);
bool IsFocus(int32 tab) const;
bool IsFocus(Decorator::Tab* tab) const;
/*! \return true if tab location updated, false if out of bounds
or unsupported */
bool SetTabLocation(int32 tab, float location,
bool isShifting, BRegion* updateRegion = NULL);
virtual float TabLocation(int32 tab) const
{ return 0.0; }
virtual Region RegionAt(BPoint where, int32& tab) const;
virtual void GetSizeLimits(int32* minWidth, int32* minHeight,
int32* maxWidth, int32* maxHeight) const;
void SetFocus(bool focussed);
bool IsFocus()
{ return fIsFocused; };
const BRegion& GetFootprint();
virtual Region RegionAt(BPoint where) const;
void MoveBy(float x, float y);
void MoveBy(BPoint offset);
void ResizeBy(float x, float y, BRegion* dirty);
void ResizeBy(BPoint offset, BRegion* dirty);
/*! \return true if tab location updated, false if out of bounds
or unsupported
*/
bool SetTabLocation(float location,
BRegion* /*updateRegion*/ = NULL);
virtual float TabLocation() const
{ return 0.0; }
virtual bool SetRegionHighlight(Region region, uint8 highlight,
BRegion* dirty);
inline uint8 RegionHighlight(Region region) const;
BRegion* dirty, int32 tab = -1);
inline uint8 RegionHighlight(Region region,
int32 tab = -1) const;
bool SetSettings(const BMessage& settings,
BRegion* updateRegion = NULL);
@@ -125,30 +155,39 @@ public:
virtual void Draw(BRect rect);
virtual void Draw();
virtual void DrawClose();
virtual void DrawClose(int32 tab);
virtual void DrawMinimize(int32 tab);
virtual void DrawTab(int32 tab);
virtual void DrawTitle(int32 tab);
virtual void DrawZoom(int32 tab);
virtual void DrawFrame();
virtual void DrawMinimize();
virtual void DrawTab();
virtual void DrawTitle();
virtual void DrawZoom();
rgb_color UIColor(color_which which);
virtual void ExtendDirtyRegion(Region region, BRegion& dirty);
protected:
int32 _TitleWidth() const
{ return fTitle.CountChars(); }
virtual void _DoLayout();
virtual void _DrawFrame(BRect rect);
virtual void _DrawTab(BRect rect);
virtual void _DrawClose(BRect rect);
virtual void _DrawTitle(BRect rect);
virtual void _DrawZoom(BRect rect);
virtual void _DrawMinimize(BRect rect);
virtual void _DrawTabs(BRect rect);
virtual void _DrawTab(Decorator::Tab* tab, BRect rect);
virtual void _DrawClose(Decorator::Tab* tab, BRect rect);
virtual void _DrawTitle(Decorator::Tab* tab, BRect rect);
virtual void _DrawZoom(Decorator::Tab* tab, BRect rect);
virtual void _DrawMinimize(Decorator::Tab* tab, BRect rect);
virtual Decorator::Tab* _AllocateNewTab() = 0;
virtual void _SetTitle(Decorator::Tab* tab, const char* string,
BRegion* updateRegion = NULL) = 0;
int32 _TitleWidth(Decorator::Tab* tab) const
{ return tab->title.CountChars(); }
virtual bool _SetTabLocation(Decorator::Tab* tab, float location,
bool isShifting, BRegion* updateRegion = NULL);
virtual void _SetFocus(Decorator::Tab* tab);
virtual void _FontsChanged(DesktopSettings& settings,
BRegion* updateRegion = NULL);
@@ -157,20 +196,19 @@ protected:
virtual void _SetFlags(uint32 flags,
BRegion* updateRegion = NULL);
virtual void _SetTitle(const char* string,
BRegion* updateRegion = NULL) = 0;
virtual void _SetFocus();
virtual void _MoveBy(BPoint offset);
virtual void _ResizeBy(BPoint offset, BRegion* dirty) = 0;
virtual bool _SetTabLocation(float location,
BRegion* /*updateRegion*/ = NULL)
{ return false; }
virtual bool _SetSettings(const BMessage& settings,
BRegion* updateRegion = NULL);
virtual bool _AddTab(int32 index = -1,
BRegion* updateRegion = NULL) = 0;
virtual bool _RemoveTab(int32 index,
BRegion* updateRegion = NULL) = 0;
virtual bool _MoveTab(int32 from, int32 to, bool isMoving,
BRegion* updateRegion = NULL) = 0;
virtual void _GetFootprint(BRegion *region);
void _InvalidateFootprint();
@@ -180,23 +218,14 @@ protected:
window_look fLook;
uint32 fFlags;
BRect fZoomRect;
BRect fCloseRect;
BRect fMinimizeRect;
BRect fTabRect;
BRect fTitleBarRect;
BRect fFrame;
BRect fResizeRect;
BRect fBorderRect;
Decorator::Tab* fTopTab;
BObjectList<Decorator::Tab> fTabList;
private:
bool fClosePressed : 1;
bool fZoomPressed : 1;
bool fMinimizePressed : 1;
bool fIsFocused : 1;
BString fTitle;
BRegion fFootprint;
bool fFootprintValid : 1;
@@ -205,7 +234,7 @@ private:
uint8
Decorator::RegionHighlight(Region region) const
Decorator::RegionHighlight(Region region, int32 tab) const
{
int32 index = (int32)region - 1;
return index >= 0 && index < REGION_COUNT - 1
File diff suppressed because it is too large Load Diff
+62 -31
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2010, Haiku, Inc.
* Copyright 2001-2011, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -22,13 +22,33 @@ class ServerBitmap;
class DefaultDecorator: public Decorator {
public:
class Tab : public Decorator::Tab {
public:
Tab();
uint32 tabOffset;
float tabLocation;
float textOffset;
BString truncatedTitle;
int32 truncatedTitleLength;
bool buttonFocus : 1;
bool isHighlighted : 1;
ServerBitmap* closeBitmaps[4];
ServerBitmap* zoomBitmaps[4];
float minTabSize;
float maxTabSize;
};
DefaultDecorator(DesktopSettings& settings,
BRect frame, window_look look,
uint32 flags);
virtual ~DefaultDecorator();
virtual float TabLocation() const
{ return (float)fTabOffset; }
virtual float TabLocation(int32 tab) const;
virtual bool GetSettings(BMessage* settings) const;
@@ -38,10 +58,11 @@ public:
virtual void GetSizeLimits(int32* minWidth, int32* minHeight,
int32* maxWidth, int32* maxHeight) const;
virtual Region RegionAt(BPoint where) const;
virtual Region RegionAt(BPoint where, int32& tab) const;
virtual bool SetRegionHighlight(Region region,
uint8 highlight, BRegion* dirty);
uint8 highlight, BRegion* dirty,
int32 tab = -1);
virtual void ExtendDirtyRegion(Region region,
BRegion& dirty);
@@ -83,16 +104,22 @@ protected:
protected:
virtual void _DoLayout();
virtual void _DoTabLayout();
void _DistributeTabSize(float delta);
virtual Decorator::Tab* _AllocateNewTab();
DefaultDecorator::Tab* _TabAt(int32 index) const;
virtual void _DrawFrame(BRect r);
virtual void _DrawTab(BRect r);
virtual void _DrawTab(Decorator::Tab* tab, BRect r);
virtual void _DrawClose(BRect r);
virtual void _DrawTitle(BRect r);
virtual void _DrawZoom(BRect r);
virtual void _DrawClose(Decorator::Tab* tab, BRect r);
virtual void _DrawTitle(Decorator::Tab* tab, BRect r);
virtual void _DrawZoom(Decorator::Tab* tab, BRect r);
virtual void _SetTitle(const char* string,
virtual void _SetTitle(Decorator::Tab* tab, const char* string,
BRegion* updateRegion = NULL);
virtual void _SetFocus(Decorator::Tab* tab);
virtual void _FontsChanged(DesktopSettings& settings,
BRegion* updateRegion);
@@ -102,17 +129,23 @@ protected:
virtual void _SetFlags(uint32 flags,
BRegion* updateRegion = NULL);
virtual void _SetFocus();
virtual void _MoveBy(BPoint offset);
virtual void _ResizeBy(BPoint offset, BRegion* dirty);
virtual bool _SetTabLocation(float location,
virtual bool _SetTabLocation(Decorator::Tab* tab,
float location, bool isShifting,
BRegion* updateRegion = NULL);
virtual bool _SetSettings(const BMessage& settings,
BRegion* updateRegion = NULL);
virtual bool _AddTab(int32 index = -1,
BRegion* updateRegion = NULL);
virtual bool _RemoveTab(int32 index,
BRegion* updateRegion = NULL);
virtual bool _MoveTab(int32 from, int32 to, bool isMoving,
BRegion* updateRegion = NULL);
virtual void _GetFootprint(BRegion *region);
void _GetButtonSizeAndOffset(const BRect& tabRect,
@@ -120,9 +153,11 @@ protected:
float* inset) const;
// DefaultDecorator customization points
virtual void DrawButtons(const BRect& invalid);
virtual void DrawButtons(Decorator::Tab* tab,
const BRect& invalid);
virtual void GetComponentColors(Component component,
uint8 highlight, ComponentColors _colors);
uint8 highlight, ComponentColors _colors,
Decorator::Tab* tab = NULL);
private:
void _UpdateFont(DesktopSettings& settings);
@@ -131,14 +166,20 @@ private:
void _DrawBlendedRect(DrawingEngine *engine,
BRect rect, bool down,
const ComponentColors& colors);
void _LayoutTabItems(const BRect& tabRect);
void _LayoutTabItems(Decorator::Tab* tab,
const BRect& tabRect);
void _InvalidateBitmaps();
ServerBitmap* _GetBitmapForButton(Component item, bool down,
int32 width, int32 height);
ServerBitmap* _GetBitmapForButton(Decorator::Tab* tab,
Component item, bool down, int32 width,
int32 height);
void _GetComponentColors(Component component,
ComponentColors _colors);
ComponentColors _colors,
Decorator::Tab* tab = NULL);
inline float _DefaultTextOffset() const;
void _CalculateTabsRegion();
protected:
static const rgb_color kFrameColors[4];
static const rgb_color kFocusFrameColors[2];
@@ -156,10 +197,6 @@ protected:
const rgb_color kNonFocusTabColorShadow;
const rgb_color kNonFocusTextColor;
bool fButtonFocus;
ServerBitmap* fCloseBitmaps[4];
ServerBitmap* fZoomBitmaps[4];
// Individual rects for handling window frame
// rendering the proper way
BRect fRightBorder;
@@ -169,14 +206,8 @@ protected:
int32 fBorderWidth;
uint32 fTabOffset;
float fTabLocation;
float fTextOffset;
float fMinTabSize;
float fMaxTabSize;
BString fTruncatedTitle;
int32 fTruncatedTitleLength;
BRegion fTabsRegion;
BRect fOldMovingTab;
};
+68 -19
View File
@@ -21,6 +21,7 @@
#include "ClickTarget.h"
#include "Desktop.h"
#include "DefaultDecorator.h"
#include "DrawingEngine.h"
#include "Window.h"
@@ -286,16 +287,58 @@ struct DefaultWindowBehaviour::SlideTabState : MouseTrackingState {
{
}
virtual
~SlideTabState()
{
fDesktop->SetWindowTabLocation(fWindow, fWindow->TabLocation(), false);
}
virtual void MouseMovedAction(BPoint& delta, bigtime_t now)
{
float loc = fWindow->TabLocation();
float location = fWindow->TabLocation();
// TODO: change to [0:1]
loc += delta.x;
if (fDesktop->SetWindowTabLocation(fWindow, loc))
location += delta.x;
AdjustMultiTabLocation(location, true);
if (fDesktop->SetWindowTabLocation(fWindow, location, true))
delta.y = 0;
else
delta = BPoint(0, 0);
}
void AdjustMultiTabLocation(float location, bool isShifting)
{
::Decorator* decorator = fWindow->Decorator();
if (decorator == NULL || decorator->CountTabs() <= 1)
return;
// TODO does not work for none continuous shifts
int32 windowIndex = fWindow->PositionInStack();
DefaultDecorator::Tab* movingTab = static_cast<DefaultDecorator::Tab*>(
decorator->TabAt(windowIndex));
int32 neighbourIndex = windowIndex;
if (movingTab->tabOffset > location)
neighbourIndex--;
else
neighbourIndex++;
DefaultDecorator::Tab* neighbourTab
= static_cast<DefaultDecorator::Tab*>(decorator->TabAt(
neighbourIndex));
if (neighbourTab == NULL)
return;
if (movingTab->tabOffset > location) {
if (location >
neighbourTab->tabOffset + neighbourTab->tabRect.Width() / 2)
return;
} else {
if (location + movingTab->tabRect.Width() <
neighbourTab->tabOffset + neighbourTab->tabRect.Width() / 2)
return;
}
fWindow->MoveToStackPosition(neighbourIndex, isShifting);
}
};
@@ -423,9 +466,10 @@ private:
struct DefaultWindowBehaviour::DecoratorButtonState : State {
DecoratorButtonState(DefaultWindowBehaviour& behavior,
Decorator::Region button)
int32 tab, Decorator::Region button)
:
State(behavior),
fTab(tab),
fButton(button)
{
}
@@ -452,22 +496,23 @@ struct DefaultWindowBehaviour::DecoratorButtonState : State {
engine->LockParallelAccess();
engine->ConstrainClippingRegion(visibleBorder);
int32 tab;
switch (fButton) {
case Decorator::REGION_CLOSE_BUTTON:
decorator->SetClose(false);
if (fBehavior._RegionFor(message) == fButton)
decorator->SetClose(fTab, false);
if (fBehavior._RegionFor(message, tab) == fButton)
fWindow->ServerWindow()->NotifyQuitRequested();
break;
case Decorator::REGION_ZOOM_BUTTON:
decorator->SetZoom(false);
if (fBehavior._RegionFor(message) == fButton)
decorator->SetZoom(fTab, false);
if (fBehavior._RegionFor(message, tab) == fButton)
fWindow->ServerWindow()->NotifyZoom();
break;
case Decorator::REGION_MINIMIZE_BUTTON:
decorator->SetMinimize(false);
if (fBehavior._RegionFor(message) == fButton)
decorator->SetMinimize(fTab, false);
if (fBehavior._RegionFor(message, tab) == fButton)
fWindow->ServerWindow()->NotifyMinimize(true);
break;
@@ -500,20 +545,21 @@ private:
engine->LockParallelAccess();
engine->ConstrainClippingRegion(visibleBorder);
int32 tab;
Decorator::Region hitRegion = message != NULL
? fBehavior._RegionFor(message) : fButton;
? fBehavior._RegionFor(message, tab) : fButton;
switch (fButton) {
case Decorator::REGION_CLOSE_BUTTON:
decorator->SetClose(hitRegion == fButton);
decorator->SetClose(fTab, hitRegion == fButton);
break;
case Decorator::REGION_ZOOM_BUTTON:
decorator->SetZoom(hitRegion == fButton);
decorator->SetZoom(fTab, hitRegion == fButton);
break;
case Decorator::REGION_MINIMIZE_BUTTON:
decorator->SetMinimize(hitRegion == fButton);
decorator->SetMinimize(fTab, hitRegion == fButton);
break;
default:
@@ -526,6 +572,7 @@ private:
}
protected:
int32 fTab;
Decorator::Region fButton;
};
@@ -669,6 +716,7 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where,
Decorator* decorator = fWindow->Decorator();
Decorator::Region hitRegion = Decorator::REGION_NONE;
int32 tab = -1;
Action action = ACTION_NONE;
bool inBorderRegion = false;
@@ -688,7 +736,7 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where,
hitRegion = Decorator::REGION_LEFT_BORDER;
} else {
// click on the decorator -- get the exact region
hitRegion = _RegionFor(message);
hitRegion = _RegionFor(message, tab);
}
// translate the region into an action
@@ -697,7 +745,7 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where,
if ((buttons & B_PRIMARY_MOUSE_BUTTON) != 0) {
// left mouse button
switch (hitRegion) {
case Decorator::REGION_TAB:
case Decorator::REGION_TAB: {
// tab sliding in any case if either shift key is held down
// except sliding up-down by moving mouse left-right would
// look strange
@@ -708,6 +756,7 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where,
}
action = ACTION_DRAG;
break;
}
case Decorator::REGION_LEFT_BORDER:
case Decorator::REGION_RIGHT_BORDER:
@@ -809,7 +858,7 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where,
case ACTION_ZOOM:
case ACTION_MINIMIZE:
_NextState(
new (std::nothrow) DecoratorButtonState(*this, hitRegion));
new (std::nothrow) DecoratorButtonState(*this, tab, hitRegion));
STRACE_CLICK(("===> ACTION_CLOSE/ZOOM/MINIMIZE\n"));
break;
@@ -910,7 +959,7 @@ DefaultWindowBehaviour::_IsWindowModifier(int32 modifiers) const
Decorator::Region
DefaultWindowBehaviour::_RegionFor(const BMessage* message) const
DefaultWindowBehaviour::_RegionFor(const BMessage* message, int32& tab) const
{
Decorator* decorator = fWindow->Decorator();
if (decorator == NULL)
@@ -920,7 +969,7 @@ DefaultWindowBehaviour::_RegionFor(const BMessage* message) const
if (message->FindPoint("where", &where) != B_OK)
return Decorator::REGION_NONE;
return decorator->RegionAt(where);
return decorator->RegionAt(where, tab);
}
+2 -1
View File
@@ -88,7 +88,8 @@ private:
private:
bool _IsWindowModifier(int32 modifiers) const;
Decorator::Region _RegionFor(const BMessage* message) const;
Decorator::Region _RegionFor(const BMessage* message,
int32& tab) const;
void _SetBorderHighlights(int8 horizontal,
int8 vertical, bool active);
+16 -13
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2010, Haiku.
* Copyright 2001-2011, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -581,6 +581,7 @@ Desktop::BroadcastToAllWindows(int32 code)
filter_result
Desktop::KeyEvent(uint32 what, int32 key, int32 modifiers)
{
filter_result result = B_DISPATCH_MESSAGE;
if (LockAllWindows()) {
Window* window = MouseEventWindow();
if (window == NULL)
@@ -591,13 +592,13 @@ Desktop::KeyEvent(uint32 what, int32 key, int32 modifiers)
window->ModifiersChanged(modifiers);
}
if (NotifyKeyPressed(what, key, modifiers))
result = B_SKIP_MESSAGE;
UnlockAllWindows();
}
if (NotifyKeyPressed(what, key, modifiers))
return B_SKIP_MESSAGE;
return B_DISPATCH_MESSAGE;
return result;
}
@@ -1115,15 +1116,12 @@ Desktop::ActivateWindow(Window* window)
}
}
// we don't need to redraw what is currently
// visible of the window
BRegion clean(window->VisibleRegion());
WindowList windows(kWorkingList);
Window* frontmost = window->Frontmost();
CurrentWindows().RemoveWindow(window);
windows.AddWindow(window);
window->MoveToTopStackLayer();
if (frontmost != NULL && frontmost->IsModal()) {
// all modal windows follow their subsets to the front
@@ -1335,6 +1333,10 @@ Desktop::MoveWindowBy(Window* window, float x, float y, int32 workspace)
if (!LockAllWindows())
return;
Window* topWindow = window->TopLayerStackWindow();
if (topWindow)
window = topWindow;
if (workspace == -1)
workspace = fCurrentWorkspace;
if (!window->IsVisible() || workspace != fCurrentWorkspace) {
@@ -1472,16 +1474,16 @@ Desktop::ResizeWindowBy(Window* window, float x, float y)
bool
Desktop::SetWindowTabLocation(Window* window, float location)
Desktop::SetWindowTabLocation(Window* window, float location, bool isShifting)
{
AutoWriteLocker _(fWindowLock);
BRegion dirty;
bool changed = window->SetTabLocation(location, dirty);
bool changed = window->SetTabLocation(location, isShifting, dirty);
if (changed)
RebuildAndRedrawAfterWindowChange(window, dirty);
NotifyWindowTabLocationChanged(window, location);
NotifyWindowTabLocationChanged(window, location, isShifting);
return changed;
}
@@ -1763,7 +1765,7 @@ Desktop::WindowAt(BPoint where)
for (Window* window = CurrentWindows().LastWindow(); window;
window = window->PreviousWindow(fCurrentWorkspace)) {
if (window->IsVisible() && window->VisibleRegion().Contains(where))
return window;
return window->StackedWindowAt(where);
}
return NULL;
@@ -3177,6 +3179,7 @@ void
Desktop::RebuildAndRedrawAfterWindowChange(Window* changedWindow,
BRegion& dirty)
{
ASSERT_MULTI_WRITE_LOCKED(fWindowLock);
if (!changedWindow->IsVisible() || dirty.CountRects() == 0)
return;
+1 -1
View File
@@ -171,7 +171,7 @@ public:
void ResizeWindowBy(Window* window, float x,
float y);
bool SetWindowTabLocation(Window* window,
float location);
float location, bool isShifting);
bool SetWindowDecoratorSettings(Window* window,
const BMessage& settings);
+2 -2
View File
@@ -244,7 +244,7 @@ DesktopObservable::NotifyWindowMinimized(Window* window, bool minimize)
void
DesktopObservable::NotifyWindowTabLocationChanged(Window* window,
float location)
float location, bool isShifting)
{
if (fWeAreInvoking)
return;
@@ -252,7 +252,7 @@ DesktopObservable::NotifyWindowTabLocationChanged(Window* window,
for (DesktopListener* listener = fDesktopListenerList.First();
listener != NULL; listener = fDesktopListenerList.GetNext(listener))
listener->WindowTabLocationChanged(window, location);
listener->WindowTabLocationChanged(window, location, isShifting);
}
+2 -2
View File
@@ -59,7 +59,7 @@ public:
bool minimize) = 0;
virtual void WindowTabLocationChanged(Window* window,
float location) = 0;
float location, bool isShifting) = 0;
virtual void SizeLimitsChanged(Window* window,
int32 minWidth, int32 maxWidth,
int32 minHeight, int32 maxHeight) = 0;
@@ -113,7 +113,7 @@ public:
bool minimize);
void NotifyWindowTabLocationChanged(Window* window,
float location);
float location, bool isShifting);
void NotifySizeLimitsChanged(Window* window,
int32 minWidth, int32 maxWidth,
int32 minHeight, int32 maxHeight);
+413 -81
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2010, Haiku, Inc.
* Copyright 2001-2011, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
@@ -14,6 +14,17 @@
#include "Window.h"
#include <new>
#include <stdio.h>
#include <Debug.h>
#include <DirectWindow.h>
#include <PortLink.h>
#include <View.h>
#include <ViewPrivate.h>
#include <WindowPrivate.h>
#include "ClickTarget.h"
#include "Decorator.h"
#include "DecorManager.h"
@@ -28,17 +39,6 @@
#include "Workspace.h"
#include "WorkspacesView.h"
#include <ViewPrivate.h>
#include <WindowPrivate.h>
#include <Debug.h>
#include <DirectWindow.h>
#include <PortLink.h>
#include <View.h>
#include <new>
#include <stdio.h>
// Toggle debug output
//#define DEBUG_WINDOW
@@ -91,7 +91,6 @@ Window::Window(const BRect& frame, const char *name,
fRegionPool(),
fWindowBehaviour(NULL),
fDecorator(NULL),
fTopView(NULL),
fWindow(window),
fDrawingEngine(drawingEngine),
@@ -120,6 +119,8 @@ Window::Window(const BRect& frame, const char *name,
fWorkspacesViewCount(0)
{
_InitWindowStack();
// make sure our arguments are valid
if (!IsValidLook(fLook))
fLook = B_TITLED_WINDOW_LOOK;
@@ -128,11 +129,12 @@ Window::Window(const BRect& frame, const char *name,
SetFlags(flags, NULL);
if (fLook != B_NO_BORDER_WINDOW_LOOK) {
fDecorator = gDecorManager.AllocateDecorator(this);
if (fDecorator) {
fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight,
&fMaxWidth, &fMaxHeight);
if (fLook != B_NO_BORDER_WINDOW_LOOK && fCurrentStack.Get() != NULL) {
// allocates a decorator
::Decorator* decorator = Decorator();
if (decorator != NULL) {
decorator->GetSizeLimits(&fMinWidth, &fMinHeight, &fMaxWidth,
&fMaxHeight);
}
}
fWindowBehaviour = gDecorManager.AllocateWindowBehaviour(this);
@@ -169,8 +171,9 @@ Window::~Window()
delete fTopView;
}
DetachFromWindowStack(false);
delete fWindowBehaviour;
delete fDecorator;
delete fDrawingEngine;
gDecorManager.CleanupForWindow(this);
@@ -220,8 +223,9 @@ Window::GetBorderRegion(BRegion* region)
// TODO: if someone needs to call this from
// the outside, the clipping needs to be readlocked!
if (fDecorator)
*region = fDecorator->GetFootprint();
::Decorator* decorator = Decorator();
if (decorator)
*region = decorator->GetFootprint();
else
region->MakeEmpty();
}
@@ -272,7 +276,7 @@ Window::_PropagatePosition()
void
Window::MoveBy(int32 x, int32 y)
Window::MoveBy(int32 x, int32 y, bool moveStack)
{
// this function is only called from the desktop thread
@@ -296,14 +300,27 @@ Window::MoveBy(int32 x, int32 y)
fEffectiveDrawingRegionValid = false;
if (fDecorator)
fDecorator->MoveBy(x, y);
if (fTopView != NULL) {
fTopView->MoveBy(x, y, NULL);
fTopView->UpdateOverlay();
}
::Decorator* decorator = Decorator();
if (moveStack && decorator)
decorator->MoveBy(x, y);
WindowStack* stack = GetWindowStack();
if (moveStack && stack) {
for (int32 i = 0; i < stack->CountWindows(); i++) {
Window* window = stack->WindowList().ItemAt(i);
if (window == this)
continue;
window->MoveBy(x, y, false);
//fDesktop->RebuildAndRedrawAfterWindowChange(window, dirty);
}
}
// the desktop will take care of dirty regions
// dispatch a message to the client informing about the changed size
@@ -315,7 +332,7 @@ Window::MoveBy(int32 x, int32 y)
void
Window::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
Window::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion, bool resizeStack)
{
// this function is only called from the desktop thread
@@ -345,19 +362,29 @@ Window::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
fContentRegionValid = false;
fEffectiveDrawingRegionValid = false;
if (fDecorator) {
fDecorator->ResizeBy(x, y, dirtyRegion);
if (fTopView != NULL) {
fTopView->ResizeBy(x, y, dirtyRegion);
fTopView->UpdateOverlay();
}
::Decorator* decorator = Decorator();
if (decorator && resizeStack) {
decorator->ResizeBy(x, y, dirtyRegion);
//if (dirtyRegion) {
//fDrawingEngine->FillRegion(*dirtyRegion, (rgb_color){ 255, 255, 0, 255 });
//snooze(40000);
//}
}
if (fTopView != NULL) {
fTopView->ResizeBy(x, y, dirtyRegion);
fTopView->UpdateOverlay();
WindowStack* stack = GetWindowStack();
if (resizeStack && stack) {
for (int32 i = 0; i < stack->CountWindows(); i++) {
Window* window = stack->WindowList().ItemAt(i);
if (window == this)
continue;
window->ResizeBy(x, y, dirtyRegion, false);
}
}
//if (dirtyRegion)
//fDrawingEngine->FillRegion(*dirtyRegion, (rgb_color){ 0, 255, 255, 255 });
@@ -543,20 +570,32 @@ Window::PreviousWindow(int32 index) const
}
::Decorator*
Window::Decorator() const
{
if (fCurrentStack.Get() == NULL)
return NULL;
return fCurrentStack->Decorator();
}
bool
Window::ReloadDecor()
{
::Decorator* decorator = NULL;
WindowBehaviour* windowBehaviour = NULL;
WindowStack* stack = GetWindowStack();
if (stack == NULL)
return false;
if (fLook != B_NO_BORDER_WINDOW_LOOK) {
// we need a new decorator
decorator = gDecorManager.AllocateDecorator(this);
if (decorator == NULL)
return false;
int32 index = PositionInStack();
if (IsFocus())
decorator->SetFocus(true);
decorator->SetFocus(index, true);
}
windowBehaviour = gDecorManager.AllocateWindowBehaviour(this);
@@ -565,8 +604,7 @@ Window::ReloadDecor()
return false;
}
delete fDecorator;
fDecorator = decorator;
stack->SetDecorator(decorator);
delete fWindowBehaviour;
fWindowBehaviour = windowBehaviour;
@@ -578,7 +616,8 @@ Window::ReloadDecor()
void
Window::SetScreen(const ::Screen* screen)
{
ASSERT_MULTI_WRITE_LOCKED(fDesktop->ScreenLocker());
// TODO this assert fails in Desktop::ShowWindow
//ASSERT_MULTI_WRITE_LOCKED(fDesktop->ScreenLocker());
fScreen = screen;
}
@@ -586,7 +625,8 @@ Window::SetScreen(const ::Screen* screen)
const ::Screen*
Window::Screen() const
{
ASSERT_MULTI_READ_LOCKED(fDesktop->ScreenLocker());
// TODO this assert also fails
//ASSERT_MULTI_READ_LOCKED(fDesktop->ScreenLocker());
return fScreen;
}
@@ -640,7 +680,7 @@ Window::DrawingRegionChanged(View* view) const
void
Window::ProcessDirtyRegion(BRegion& region)
{
// if this is exectuted in the desktop thread,
// if this is executed in the desktop thread,
// it means that the window thread currently
// blocks to get the read lock, if it is
// executed from the window thread, it should
@@ -669,8 +709,13 @@ Window::ProcessDirtyRegion(BRegion& region)
void
Window::RedrawDirtyRegion()
{
// executed from ServerWindow with the read lock held
if (TopLayerStackWindow() != this) {
fDirtyRegion.MakeEmpty();
fDirtyCause = 0;
return;
}
// executed from ServerWindow with the read lock held
if (IsVisible()) {
_DrawBorder();
@@ -961,22 +1006,27 @@ Window::SetTitle(const char* name, BRegion& dirty)
fTitle = name;
if (fDecorator)
fDecorator->SetTitle(name, &dirty);
::Decorator* decorator = Decorator();
if (decorator) {
int32 index = PositionInStack();
decorator->SetTitle(index, name, &dirty);
}
}
void
Window::SetFocus(bool focus)
{
::Decorator* decorator = Decorator();
// executed from Desktop thread
// it holds the clipping write lock,
// so the window thread cannot be
// accessing fIsFocus
BRegion* dirty = NULL;
if (fDecorator)
dirty = fRegionPool.GetRegion(fDecorator->GetFootprint());
if (decorator)
dirty = fRegionPool.GetRegion(decorator->GetFootprint());
if (dirty) {
dirty->IntersectWith(&fVisibleRegion);
fDesktop->MarkDirty(*dirty);
@@ -984,8 +1034,10 @@ Window::SetFocus(bool focus)
}
fIsFocus = focus;
if (fDecorator)
fDecorator->SetFocus(focus);
if (decorator) {
int32 index = PositionInStack();
decorator->SetFocus(index, focus);
}
Activated(focus);
}
@@ -1066,8 +1118,9 @@ Window::SetSizeLimits(int32 minWidth, int32 maxWidth, int32 minHeight,
fMaxHeight = maxHeight;
// give the Decorator a say in this too
if (fDecorator) {
fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight, &fMaxWidth,
::Decorator* decorator = Decorator();
if (decorator) {
decorator->GetSizeLimits(&fMinWidth, &fMinHeight, &fMaxWidth,
&fMaxHeight);
}
@@ -1087,10 +1140,13 @@ Window::GetSizeLimits(int32* minWidth, int32* maxWidth,
bool
Window::SetTabLocation(float location, BRegion& dirty)
Window::SetTabLocation(float location, bool isShifting, BRegion& dirty)
{
if (fDecorator)
return fDecorator->SetTabLocation(location, &dirty);
::Decorator* decorator = Decorator();
if (decorator) {
int32 index = PositionInStack();
return decorator->SetTabLocation(index, location, isShifting, &dirty);
}
return false;
}
@@ -1099,8 +1155,11 @@ Window::SetTabLocation(float location, BRegion& dirty)
float
Window::TabLocation() const
{
if (fDecorator)
return fDecorator->TabLocation();
::Decorator* decorator = Decorator();
if (decorator) {
int32 index = PositionInStack();
return decorator->TabLocation(index);
}
return 0.0;
}
@@ -1116,8 +1175,10 @@ Window::SetDecoratorSettings(const BMessage& settings, BRegion& dirty)
return false;
}
if (fDecorator)
return fDecorator->SetSettings(settings, &dirty);
::Decorator* decorator = Decorator();
if (decorator)
return decorator->SetSettings(settings, &dirty);
return false;
}
@@ -1128,8 +1189,9 @@ Window::GetDecoratorSettings(BMessage* settings)
if (fDesktop)
fDesktop->GetDecoratorSettings(this, *settings);
if (fDecorator)
return fDecorator->GetSettings(settings);
::Decorator* decorator = Decorator();
if (decorator)
return decorator->GetSettings(settings);
return false;
}
@@ -1138,9 +1200,10 @@ Window::GetDecoratorSettings(BMessage* settings)
void
Window::FontsChanged(BRegion* updateRegion)
{
if (fDecorator != NULL) {
::Decorator* decorator = Decorator();
if (decorator != NULL) {
DesktopSettings settings(fDesktop);
fDecorator->FontsChanged(settings, updateRegion);
decorator->FontsChanged(settings, updateRegion);
}
}
@@ -1148,11 +1211,14 @@ Window::FontsChanged(BRegion* updateRegion)
void
Window::SetLook(window_look look, BRegion* updateRegion)
{
if (fDecorator == NULL && look != B_NO_BORDER_WINDOW_LOOK) {
::Decorator* decorator = Decorator();
if (decorator == NULL && look != B_NO_BORDER_WINDOW_LOOK) {
// we need a new decorator
fDecorator = gDecorManager.AllocateDecorator(this);
if (IsFocus())
fDecorator->SetFocus(true);
decorator = gDecorManager.AllocateDecorator(this);
if (IsFocus()) {
int32 index = PositionInStack();
decorator->SetFocus(index, true);
}
}
fLook = look;
@@ -1163,20 +1229,19 @@ Window::SetLook(window_look look, BRegion* updateRegion)
// ...and therefor the drawing region is
// likely not valid anymore either
if (fDecorator != NULL) {
if (decorator != NULL) {
DesktopSettings settings(fDesktop);
fDecorator->SetLook(settings, look, updateRegion);
decorator->SetLook(settings, look, updateRegion);
// we might need to resize the window!
fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight, &fMaxWidth,
decorator->GetSizeLimits(&fMinWidth, &fMinHeight, &fMaxWidth,
&fMaxHeight);
_ObeySizeLimits();
}
if (look == B_NO_BORDER_WINDOW_LOOK) {
if (look == B_NO_BORDER_WINDOW_LOOK && fCurrentStack.Get() != NULL) {
// we don't need a decorator for this window
delete fDecorator;
fDecorator = NULL;
fCurrentStack->SetDecorator(NULL);
}
}
@@ -1216,16 +1281,15 @@ Window::SetFlags(uint32 flags, BRegion* updateRegion)
if ((fFlags & B_SAME_POSITION_IN_ALL_WORKSPACES) != 0)
_PropagatePosition();
if (fDecorator == NULL)
::Decorator* decorator = Decorator();
if (decorator == NULL)
return;
fDecorator->SetFlags(flags, updateRegion);
decorator->SetFlags(flags, updateRegion);
// we might need to resize the window!
if (fDecorator) {
fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight, &fMaxWidth, &fMaxHeight);
_ObeySizeLimits();
}
decorator->GetSizeLimits(&fMinWidth, &fMinHeight, &fMaxWidth, &fMaxHeight);
_ObeySizeLimits();
// TODO: not sure if we want to do this
#if 0
@@ -1672,8 +1736,8 @@ Window::_DrawBorder()
// this is executed in the window thread, but only
// in respond to a REDRAW message having been received, the
// clipping lock is held for reading
if (!fDecorator)
::Decorator* decorator = Decorator();
if (!decorator)
return;
// construct the region of the border that needs redrawing
@@ -1686,13 +1750,13 @@ Window::_DrawBorder()
// intersect with the dirty region
dirtyBorderRegion->IntersectWith(&fDirtyRegion);
DrawingEngine* engine = fDecorator->GetDrawingEngine();
DrawingEngine* engine = decorator->GetDrawingEngine();
if (dirtyBorderRegion->CountRects() > 0 && engine->LockParallelAccess()) {
engine->ConstrainClippingRegion(dirtyBorderRegion);
bool copyToFrontEnabled = engine->CopyToFrontEnabled();
engine->SetCopyToFrontEnabled(true);
fDecorator->Draw(dirtyBorderRegion->Frame());
decorator->Draw(dirtyBorderRegion->Frame());
engine->SetCopyToFrontEnabled(copyToFrontEnabled);
@@ -1887,8 +1951,9 @@ Window::_UpdateContentRegion()
fContentRegion.Set(fFrame);
// resize handle
if (fDecorator)
fContentRegion.Exclude(&fDecorator->GetFootprint());
::Decorator* decorator = Decorator();
if (decorator)
fContentRegion.Exclude(&decorator->GetFootprint());
fContentRegionValid = true;
}
@@ -1991,3 +2056,270 @@ Window::UpdateSession::AddCause(uint8 cause)
{
fCause |= cause;
}
int32
Window::PositionInStack() const
{
if (fCurrentStack.Get() == NULL)
return -1;
return fCurrentStack->WindowList().IndexOf(this);
}
bool
Window::DetachFromWindowStack(bool ownStackNeeded)
{
// The lock must normally be held but is not held when closing the window.
//ASSERT_MULTI_WRITE_LOCKED(fDesktop->WindowLocker());
if (fCurrentStack.Get() == NULL)
return false;
if (fCurrentStack->CountWindows() == 1)
return true;
int32 index = PositionInStack();
if (fCurrentStack->RemoveWindow(this) == false)
return false;
BRegion dirty;
::Decorator* decorator = fCurrentStack->Decorator();
if (decorator != NULL)
decorator->RemoveTab(index, &dirty);
Window* remainingTop = fCurrentStack->TopLayerWindow();
if (remainingTop != NULL) {
decorator->SetDrawingEngine(remainingTop->fDrawingEngine);
// propagate focus to the decorator
remainingTop->SetFocus(remainingTop->IsFocus());
}
fCurrentStack = NULL;
if (ownStackNeeded == true)
_InitWindowStack();
// propagate focus to the new decorator
SetFocus(IsFocus());
fDesktop->RebuildAndRedrawAfterWindowChange(this, dirty);
if (remainingTop != NULL)
fDesktop->MarkDirty(remainingTop->VisibleRegion());
return true;
}
bool
Window::AddWindowToStack(Window* window)
{
ASSERT_MULTI_WRITE_LOCKED(fDesktop->WindowLocker());
WindowStack* stack = GetWindowStack();
if (stack == NULL)
return false;
// first collect dirt from the window to add
BRegion dirty;
::Decorator* otherDecorator = window->Decorator();
if (otherDecorator != NULL)
dirty.Include(otherDecorator->TitleBarRect());
::Decorator* decorator = stack->Decorator();
if (decorator != NULL)
dirty.Include(decorator->TitleBarRect());
int32 position = PositionInStack() + 1;
if (position >= stack->CountWindows())
position = -1;
if (stack->AddWindow(window, position) == false)
return false;
window->DetachFromWindowStack(false);
window->fCurrentStack.SetTo(stack);
if (decorator != NULL)
decorator->AddTab(window->Title(), position, &dirty);
fDesktop->RebuildAndRedrawAfterWindowChange(TopLayerStackWindow(), dirty);
window->SetFocus(window->IsFocus());
return true;
}
Window*
Window::StackedWindowAt(const BPoint& where)
{
::Decorator* decorator = Decorator();
if (decorator == NULL)
return NULL;
int tab = decorator->TabAt(where);
// if we have a decorator we also have a stack
Window* window = fCurrentStack->WindowAt(tab);
if (window != NULL)
return window;
return this;
}
Window*
Window::TopLayerStackWindow()
{
if (fCurrentStack.Get() == NULL)
return this;
return fCurrentStack->TopLayerWindow();
}
WindowStack*
Window::GetWindowStack()
{
if (fCurrentStack.Get() == NULL)
return _InitWindowStack();
return fCurrentStack;
}
bool
Window::MoveToTopStackLayer()
{
::Decorator* decorator = Decorator();
if (decorator == NULL)
return false;
decorator->SetDrawingEngine(fDrawingEngine);
decorator->SetTopTap(PositionInStack());
return fCurrentStack->MoveToTopLayer(this);
}
bool
Window::MoveToStackPosition(int32 to, bool isMoving)
{
if (fCurrentStack.Get() == NULL)
return false;
int32 index = PositionInStack();
if (fCurrentStack->Move(index, to) == false)
return false;
BRegion dirty;
::Decorator* decorator = Decorator();
if (decorator && decorator->MoveTab(index, to, isMoving, &dirty) == false)
return false;
fDesktop->RebuildAndRedrawAfterWindowChange(this, dirty);
return true;
}
WindowStack*
Window::_InitWindowStack()
{
fCurrentStack = NULL;
::Decorator* decorator = NULL;
if (fLook != B_NO_BORDER_WINDOW_LOOK)
decorator = gDecorManager.AllocateDecorator(this);
WindowStack* stack = new(std::nothrow) WindowStack(decorator);
if (stack == NULL)
return NULL;
if (stack->AddWindow(this) != true) {
delete stack;
return NULL;
}
fCurrentStack.SetTo(stack, true);
return stack;
}
WindowStack::WindowStack(::Decorator* decorator)
:
fDecorator(decorator)
{
}
WindowStack::~WindowStack()
{
delete fDecorator;
}
void
WindowStack::SetDecorator(::Decorator* decorator)
{
delete fDecorator;
fDecorator = decorator;
}
::Decorator*
WindowStack::Decorator()
{
return fDecorator;
}
Window*
WindowStack::TopLayerWindow() const
{
return fWindowLayerOrder.ItemAt(fWindowLayerOrder.CountItems() - 1);
}
int32
WindowStack::CountWindows()
{
return fWindowList.CountItems();
}
Window*
WindowStack::WindowAt(int32 index)
{
return fWindowList.ItemAt(index);
}
bool
WindowStack::AddWindow(Window* window, int32 position)
{
if (position >= 0) {
if (fWindowList.AddItem(window, position) == false)
return false;
} else if (fWindowList.AddItem(window) == false)
return false;
if (fWindowLayerOrder.AddItem(window) == false) {
fWindowList.RemoveItem(window);
return false;
}
return true;
}
bool
WindowStack::RemoveWindow(Window* window)
{
if (fWindowList.RemoveItem(window) == false)
return false;
fWindowLayerOrder.RemoveItem(window);
return true;
}
bool
WindowStack::MoveToTopLayer(Window* window)
{
int32 index = fWindowLayerOrder.IndexOf(window);
return fWindowLayerOrder.MoveItem(index,
fWindowLayerOrder.CountItems() - 1);
}
bool
WindowStack::Move(int32 from, int32 to)
{
return fWindowList.MoveItem(from, to);
}
+63 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2010, Haiku, Inc.
* Copyright 2001-2011, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
@@ -20,9 +20,46 @@
#include "WindowList.h"
#include <ObjectList.h>
#include <Referenceable.h>
#include <Region.h>
#include <String.h>
class Window;
typedef BObjectList<Window> StackWindows;
class WindowStack : public BReferenceable {
public:
WindowStack(::Decorator* decorator);
~WindowStack();
void SetDecorator(::Decorator* decorator);
::Decorator* Decorator();
const StackWindows& WindowList() const { return fWindowList; }
const StackWindows& LayerOrder() const { return fWindowLayerOrder; }
Window* TopLayerWindow() const;
int32 CountWindows();
Window* WindowAt(int32 index);
bool AddWindow(Window* window,
int32 position = -1);
bool RemoveWindow(Window* window);
bool MoveToTopLayer(Window* window);
bool Move(int32 from, int32 to);
private:
::Decorator* fDecorator;
StackWindows fWindowList;
StackWindows fWindowLayerOrder;
};
namespace BPrivate {
class PortLink;
};
@@ -65,7 +102,7 @@ public:
Window* PreviousWindow(int32 index) const;
::Desktop* Desktop() const { return fDesktop; }
::Decorator* Decorator() const { return fDecorator; }
::Decorator* Decorator() const;
::ServerWindow* ServerWindow() const { return fWindow; }
::EventTarget& EventTarget() const
{ return fWindow->EventTarget(); }
@@ -88,9 +125,10 @@ public:
void GetBorderRegion(BRegion* region);
void GetContentRegion(BRegion* region);
void MoveBy(int32 x, int32 y);
void MoveBy(int32 x, int32 y, bool moveStack = true);
void ResizeBy(int32 x, int32 y,
BRegion* dirtyRegion);
BRegion* dirtyRegion,
bool resizeStack = true);
void ScrollViewBy(View* view, int32 dx, int32 dy);
@@ -191,7 +229,8 @@ public:
int32* minHeight, int32* maxHeight) const;
// 0.0 -> left .... 1.0 -> right
bool SetTabLocation(float location, BRegion& dirty);
bool SetTabLocation(float location, bool isShifting,
BRegion& dirty);
float TabLocation() const;
bool SetDecoratorSettings(const BMessage& settings,
@@ -254,6 +293,19 @@ public:
static uint32 ValidWindowFlags();
static uint32 ValidWindowFlags(window_feel feel);
// Window stack methods.
WindowStack* GetWindowStack();
bool DetachFromWindowStack(
bool ownStackNeeded = true);
bool AddWindowToStack(Window* window);
Window* StackedWindowAt(const BPoint& where);
Window* TopLayerStackWindow();
int32 PositionInStack() const;
bool MoveToTopStackLayer();
bool MoveToStackPosition(int32 index,
bool isMoving);
protected:
void _ShiftPartOfRegion(BRegion* region,
BRegion* regionToShift, int32 xOffset,
@@ -307,7 +359,6 @@ protected:
BObjectList<Window> fSubsets;
WindowBehaviour* fWindowBehaviour;
::Decorator* fDecorator;
View* fTopView;
::ServerWindow* fWindow;
DrawingEngine* fDrawingEngine;
@@ -377,6 +428,12 @@ protected:
int32 fWorkspacesViewCount;
friend class DecorManager;
private:
WindowStack* _InitWindowStack();
BReference<WindowStack> fCurrentStack;
};
#endif // WINDOW_H
+1 -1
View File
@@ -177,7 +177,7 @@ WorkspacesView::_DrawWindow(DrawingEngine* drawingEngine,
Decorator *decorator = window->Decorator();
BRect tabFrame(0, 0, 0, 0);
if (decorator != NULL)
tabFrame = decorator->TabRect();
tabFrame = decorator->TitleBarRect();
tabFrame = _WindowFrame(workspaceFrame, screenFrame,
tabFrame, tabFrame.LeftTop() - offset);