diff options
| author | Marco Trevisan (Treviño) <mail@3v1n0.net> | 2013-12-13 11:27:55 +0100 |
|---|---|---|
| committer | Marco Trevisan (Treviño) <mail@3v1n0.net> | 2013-12-13 11:27:55 +0100 |
| commit | 0ed17457477d5374f481ccb7a02778ba214d447d (patch) | |
| tree | 06392d2fdceef2e7228f72e4abe729561b841af2 /plugins | |
| parent | 7a378f3c012fd8ae2e9334b911c82d235749397c (diff) | |
DecorationsWidgets: add a simple basic implementation of compiz-textures based widget system
(bzr r3566.5.51)
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/unityshell/src/DecorationsWidgets.cpp | 257 | ||||
| -rw-r--r-- | plugins/unityshell/src/DecorationsWidgets.h | 109 |
2 files changed, 366 insertions, 0 deletions
diff --git a/plugins/unityshell/src/DecorationsWidgets.cpp b/plugins/unityshell/src/DecorationsWidgets.cpp new file mode 100644 index 000000000..954018206 --- /dev/null +++ b/plugins/unityshell/src/DecorationsWidgets.cpp @@ -0,0 +1,257 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright (C) 2013 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> + */ + +#include <composite/composite.h> +#include "DecorationsWidgets.h" + +namespace unity +{ +namespace decoration +{ +namespace +{ +CompositeScreen* cscreen_ = CompositeScreen::get(screen); +} + +Item::Item() + : max_width_(std::numeric_limits<int>::max()) +{} + +bool Item::SetMaximumWidth(int max_width) +{ + int clamped = std::max(0, max_width); + + if (max_width_ == clamped) + return false; + + max_width_ = clamped; + return true; +} + +void Item::Damage() +{ + cscreen_->damageRegion(Geometry()); +} + +// void Item::SetSize(int width, int height) +// { +// SetMaximumWidth(width); +// } + +// + +TexturedItem::TexturedItem() +{ + visible = true; +} + +void TexturedItem::Draw(GLWindow* ctx, GLMatrix const& transformation, GLWindowPaintAttrib const& attrib, + CompRegion const& clip, unsigned mask) +{ + if (!visible) + return; + + if (!static_cast<GLTexture*>(texture_)) + UpdateTexture(); + + ctx->vertexBuffer()->begin(); + ctx->glAddGeometry({texture_.quad.matrix}, texture_.quad.box, clip); + + if (ctx->vertexBuffer()->end()) + ctx->glDrawTexture(texture_, transformation, attrib, mask); +} + +CompRect const& TexturedItem::Geometry() const +{ + return texture_.quad.box; +} + +void TexturedItem::SetCoords(int x, int y) +{ + texture_.SetCoords(x, y); +} + +void TexturedItem::SetX(int x) +{ + texture_.SetX(x); +} + +void TexturedItem::SetY(int y) +{ + texture_.SetY(y); +} + +bool TexturedItem::SetMaximumWidth(int max_width) +{ + if (!Item::SetMaximumWidth(max_width)) + return false; + + if (!resizable() && texture_.st && max_width > texture_.st->width()) + max_width = texture_.st->width(); + + texture_.quad.box.setWidth(max_width); + + return true; +} + +// + +Layout::Layout() + : inner_padding_(0) +{} + +void Layout::Append(Item::Ptr const& item) +{ + if (!item || std::find(items_.begin(), items_.end(), item) != items_.end()) + return; + + items_.push_back(item); + auto relayout_cb = sigc::hide(sigc::mem_fun(this, &Layout::Relayout)); + item->visible.changed.connect(relayout_cb); + item->resizable.changed.connect(relayout_cb); + Relayout(); +} + +CompRect const& Layout::Geometry() const +{ + return rect_; +} + +bool Layout::SetMaximumWidth(int max_width) +{ + if (!Item::SetMaximumWidth(max_width)) + return false; + + Relayout(); + return true; +} + +void Layout::SetCoords(int x, int y) +{ + if (x == rect_.x() && y == rect_.y()) + return; + + rect_.setX(x); + rect_.setY(y); + Relayout(); +} + +void Layout::Relayout() +{ + bool first_loop = true; + + do + { + rect_.setWidth(0); + rect_.setHeight(0); + size_t resizable_items = 0; + + for (auto const& item : items_) + { + if (!item->visible()) + continue; + + if (first_loop) + item->SetMaximumWidth(max_width_); + + auto const& item_geo = item->Geometry(); + item->SetX(rect_.x2()); + rect_.setHeight(std::max(rect_.height(), item_geo.height())); + + if (item_geo.width() > 0) + { + rect_.setWidth(rect_.width() + item_geo.width() + inner_padding_); + + if (item->resizable()) + ++resizable_items; + } + } + + if (!items_.empty()) + rect_.setWidth(std::max(0, rect_.width() - inner_padding_)); + + bool too_big = (rect_.width() > max_width_); + bool has_resizables = (resizable_items > 0); + int exceeding_width = rect_.width() - max_width_; + + if (first_loop) + { + for (auto const& item : items_) + { + if (!item->visible()) + continue; + + auto const& item_geo = item->Geometry(); + item->SetY(rect_.y1() + (rect_.height() - item_geo.height()) / 2); + + if (too_big && has_resizables) + { + if (item->resizable() && item_geo.width() > 0 && resizable_items > 0) + { + int max_item_width = std::max<int>(0, (exceeding_width - item_geo.width()) / resizable_items); + item->SetMaximumWidth(max_item_width); + exceeding_width -= item_geo.width(); + --resizable_items; + } + } + } + } + + if (too_big && (!first_loop || !has_resizables)) + { + exceeding_width = rect_.width() - max_width_; + + for (auto it = items_.rbegin(); it != items_.rend(); ++it) + { + auto const& item = *it; + if (!item->visible()) + continue; + + int old_width = item->Geometry().width(); + int max_item_width = std::max<int>(0, old_width - exceeding_width); + item->SetMaximumWidth(max_item_width); + exceeding_width -= (old_width - max_item_width); + + if (exceeding_width <= 0) + break; + } + } + + first_loop = false; + } + while (rect_.width() > max_width_); +} + +void Layout::Draw(GLWindow* ctx, GLMatrix const& transformation, GLWindowPaintAttrib const& attrib, + CompRegion const& clip, unsigned mask) +{ + for (auto const& item : items_) + { + if (item->visible()) + item->Draw(ctx, transformation, attrib, clip, mask); + } +} + +std::list<Item::Ptr> const& Layout::Items() const +{ + return items_; +} + +} // decoration namespace +} // unity namespace diff --git a/plugins/unityshell/src/DecorationsWidgets.h b/plugins/unityshell/src/DecorationsWidgets.h new file mode 100644 index 000000000..18cbcdaf5 --- /dev/null +++ b/plugins/unityshell/src/DecorationsWidgets.h @@ -0,0 +1,109 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright (C) 2013 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> + */ + +#ifndef UNITY_DECORATION_WIDGETS +#define UNITY_DECORATION_WIDGETS + +#include <list> +#include "CompizUtils.h" + +namespace unity +{ +namespace decoration +{ +namespace cu = compiz_utils; + +class Item : public sigc::trackable +{ +public: + typedef std::shared_ptr<Item> Ptr; + + Item(); + virtual ~Item() = default; + + nux::Property<bool> visible; + nux::Property<bool> resizable; + // sigc::signal<void> geo_changed; + + virtual CompRect const& Geometry() const = 0; + virtual void SetCoords(int x, int y) = 0; + virtual void SetX(int x) { SetCoords(x, Geometry().y()); } + virtual void SetY(int y) { SetCoords(Geometry().x(), y); } + // virtual void SetSize(int width, int height); + // virtual void SetWidth(int width) { SetSize(width, Geometry().height()); } + // virtual void SetHeight(int height) { SetSize(Geometry().width(), height); }; + virtual bool SetMaximumWidth(int max_width); + + void Damage(); + virtual void Draw(GLWindow*, GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask) {} + +protected: + int max_width_; +}; + + +class TexturedItem : public Item +{ +public: + typedef std::shared_ptr<TexturedItem> Ptr; + + TexturedItem(); + virtual void UpdateTexture() = 0; + + void Draw(GLWindow*, GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask); + CompRect const& Geometry() const; + void SetCoords(int x, int y); + void SetX(int x); + void SetY(int y); + bool SetMaximumWidth(int max_width); + void SetSize(int width, int height); + +protected: + cu::SimpleTextureQuad texture_; +}; + + +class Layout : public Item +{ +public: + typedef std::shared_ptr<Layout> Ptr; + + Layout(); + + void Append(Item::Ptr const&); + + CompRect const& Geometry() const; + bool SetMaximumWidth(int max_width); + + void SetCoords(int x, int y); + void Relayout(); + void Draw(GLWindow*, GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask); + + std::list<Item::Ptr> const& Items() const; + +private: + int inner_padding_; + CompRect rect_; + std::list<Item::Ptr> items_; +}; + +} // decoration namespace +} // unity namespace + +#endif |
