Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1510)

Unified Diff: chrome/browser/notifications/balloon_win.cc

Issue 208068: Desktop Notifications UI (for windows) (Closed)
Patch Set: Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/notifications/balloon_view_win.cc ('k') | chrome/browser/notifications/balloons.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/notifications/balloon_win.cc
diff --git a/chrome/browser/notifications/balloon_win.cc b/chrome/browser/notifications/balloon_win.cc
new file mode 100755
index 0000000000000000000000000000000000000000..0afacd86c41d8e8ddb0d0935b230ef45cda564b3
--- /dev/null
+++ b/chrome/browser/notifications/balloon_win.cc
@@ -0,0 +1,294 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/balloons.h"
+
+#include "base/logging.h"
+#include "base/gfx/rect.h"
+#include "chrome/browser/notifications/balloon_view_win.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view_win.h"
+#include "chrome/browser/renderer_host/site_instance.h"
+#include "views/window/window_win.h"
+
+namespace {
+// Portion of the screen allotted for notifications.
+// When notification balloons extend over this threshold, no new notifications
+// are shown until some balloons are expired/closed.
+const double kPercentBalloonFillFactor = 0.7;
+
+// Allow at least this number of balloons on the screen.
+const int kMinAllowedBalloonCount = 2;
+
+void GetMainScreenWorkArea(gfx::Rect* bounds) {
+ DCHECK(bounds);
+ RECT work_area = {0};
+ if (::SystemParametersInfo(SPI_GETWORKAREA, 0, &work_area, 0)) {
+ bounds->SetRect(work_area.left,
+ work_area.top,
+ work_area.right,
+ work_area.bottom);
+ } else {
+ // If failed to call SystemParametersInfo for some reason, we simply get the
+ // full screen size as an alternative.
+ bounds->SetRect(0,
+ 0,
+ ::GetSystemMetrics(SM_CXSCREEN) - 1,
+ ::GetSystemMetrics(SM_CYSCREEN) - 1);
+ }
+}
+
+double GetSystemFontScaleFactor() {
+ return 1.0;
+}
+} // namespace
+
+BalloonCollection::BalloonCollection() {
+}
+
+void BalloonCollection::AddObserver(BalloonCollectionObserver* observer) {
+ DCHECK(observer);
+ observers_.push_back(observer);
+ observer->OnBalloonSpaceChanged();
+}
+
+bool BalloonCollection::HasSpace() const {
+ if (count() < kMinAllowedBalloonCount) {
+ return true;
+ }
+
+ int max_balloon_length = 0;
+ int total_length = 0;
+ layout_.GetMaxLengths(&max_balloon_length, &total_length);
+
+ int current_max_length = max_balloon_length * count();
+ int max_allowed_length = static_cast<int>(total_length *
+ kPercentBalloonFillFactor);
+ return current_max_length < max_allowed_length - max_balloon_length;
+}
+
+void BalloonCollection::Add(const Notification& notification,
+ Profile* profile,
+ SiteInstance* site_instance) {
+ Balloon* new_balloon = MakeBalloon(notification, profile, site_instance);
+ gfx::Size size(layout_.min_balloon_width(), layout_.min_balloon_height());
+ new_balloon->SetSize(size);
+ balloons_.push_back(new_balloon);
+ gfx::Point origin = layout_.GetOrigin();
+ for (Balloons::iterator it = balloons_.begin(); it != balloons_.end(); ++it) {
+ gfx::Point upper_left = layout_.NextPosition((*it)->size(), &origin);
+ (*it)->SetPosition(upper_left, false);
+ }
+ new_balloon->Show();
+ notification.display();
+ for (BalloonObservers::iterator it = observers_.begin();
+ it != observers_.end();
+ ++it) {
+ (*it)->OnBalloonSpaceChanged();
+ }
+}
+
+void BalloonCollection::OnBalloonClosed(Balloon* source) {
+ source->notification().close(true);
+
+ for (Balloons::iterator it = balloons_.begin(); it != balloons_.end(); ++it) {
+ if (*it == source) {
+ balloons_.erase(it);
+ break;
+ }
+ }
+
+ gfx::Point origin = layout_.GetOrigin();
+ for (Balloons::iterator it = balloons_.begin(); it != balloons_.end(); ++it) {
+ gfx::Point upper_left = layout_.NextPosition((*it)->size(), &origin);
+ (*it)->SetPosition(upper_left, true);
+ }
+}
+
+void BalloonCollection::ShowAll() {
+}
+
+void BalloonCollection::HideAll() {
+}
+
+Balloon::Balloon(const Notification& notification,
+ Profile* profile,
+ SiteInstance* site_instance,
+ BalloonCloseListener* listener)
+ : profile_(profile),
+ site_instance_(site_instance),
+ notification_(notification),
+ close_listener_(listener) {
+}
+
+Balloon::~Balloon() {
+}
+
+void Balloon::Show() {
+ if (!balloon_view_.get()) {
+ balloon_view_.reset(new BalloonView());
+ balloon_view_->Show(this);
+ }
+}
+
+
+void Balloon::Close() {
+ if (close_listener_) {
+ close_listener_->OnBalloonClosed(this);
+ }
+}
+
+void Balloon::SetPosition(const gfx::Point& upper_left, bool reposition) {
+ position_ = upper_left;
+ if (reposition && balloon_view_.get()) {
+ balloon_view_->RepositionToBalloon();
+ }
+}
+
+void Balloon::SetSize(const gfx::Size& size) {
+ size_ = size;
+}
+
+const gfx::Point& Balloon::position() const {
+ return position_;
+}
+
+const gfx::Size& Balloon::size() const {
+ return size_;
+}
+
+BalloonCollection::Layout::Placement BalloonCollection::Layout::placement_ =
+ BalloonCollection::Layout::VERTICALLY_FROM_BOTTOM_RIGHT;
+
+BalloonCollection::Layout::Layout()
+ : font_scale_factor_(1.0) {
+ RefreshSystemMetrics();
+}
+
+// Scale the size to count in the system font factor
+int BalloonCollection::Layout::ScaleSize(int size) const {
+ return static_cast<int>(size * font_scale_factor_);
+}
+
+int BalloonCollection::Layout::min_balloon_width() const {
+ return ScaleSize(kBalloonMinWidth);
+}
+
+int BalloonCollection::Layout::max_balloon_width() const {
+ return ScaleSize(kBalloonMaxWidth);
+}
+
+int BalloonCollection::Layout::min_balloon_height() const {
+ return ScaleSize(kBalloonMinHeight);
+}
+
+int BalloonCollection::Layout::max_balloon_height() const {
+ return ScaleSize(kBalloonMaxHeight);
+}
+
+gfx::Point BalloonCollection::Layout::GetOrigin() const {
+ int x = 0;
+ int y = 0;
+ switch (placement_) {
+ case HORIZONTALLY_FROM_BOTTOM_LEFT:
+ x = work_area_.x();
+ y = work_area_.bottom();
+ break;
+ case HORIZONTALLY_FROM_BOTTOM_RIGHT:
+ x = work_area_.right();
+ y = work_area_.bottom();
+ break;
+ case VERTICALLY_FROM_TOP_RIGHT:
+ x = work_area_.right();
+ y = work_area_.y();
+ break;
+ case VERTICALLY_FROM_BOTTOM_RIGHT:
+ x = work_area_.right();
+ y = work_area_.bottom();
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ return gfx::Point(x, y);
+}
+
+gfx::Point BalloonCollection::Layout::NextPosition(
+ const gfx::Size& balloon_size,
+ gfx::Point* origin) const {
+ DCHECK(origin);
+
+ int x = 0;
+ int y = 0;
+ switch (placement_) {
+ case HORIZONTALLY_FROM_BOTTOM_LEFT:
+ x = origin->x();
+ y = origin->y() - balloon_size.height();
+ origin->set_x(origin->x() + balloon_size.width());
+ break;
+ case HORIZONTALLY_FROM_BOTTOM_RIGHT:
+ origin->set_x(origin->x() - balloon_size.width());
+ x = origin->x();
+ y = origin->y() - balloon_size.height();
+ break;
+ case VERTICALLY_FROM_TOP_RIGHT:
+ x = origin->x() - balloon_size.width();
+ y = origin->y();
+ origin->set_y(origin->y() + balloon_size.height());
+ break;
+ case VERTICALLY_FROM_BOTTOM_RIGHT:
+ origin->set_y(origin->y() - balloon_size.height());
+ x = origin->x() - balloon_size.width();
+ y = origin->y();
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ return gfx::Point(x, y);
+}
+
+bool BalloonCollection::Layout::RefreshSystemMetrics() {
+ bool changed = false;
+
+ gfx::Rect new_work_area(work_area_.x(), work_area_.y(),
+ work_area_.width(), work_area_.height());
+ GetMainScreenWorkArea(&new_work_area);
+ if (!work_area_.Equals(new_work_area)) {
+ work_area_.SetRect(new_work_area.x(), new_work_area.y(),
+ new_work_area.width(), new_work_area.height());
+ changed = true;
+ }
+
+ double new_font_scale_factor = font_scale_factor_;
+ new_font_scale_factor = GetSystemFontScaleFactor();
+ if (font_scale_factor_ != new_font_scale_factor) {
+ font_scale_factor_ = new_font_scale_factor;
+ changed = true;
+ }
+ return changed;
+}
+
+const void BalloonCollection::Layout::GetMaxLengths(
+ int* max_balloon_length,
+ int* total_length) const {
+ DCHECK(max_balloon_length && total_length);
+
+ switch (placement_) {
+ case HORIZONTALLY_FROM_BOTTOM_LEFT:
+ case HORIZONTALLY_FROM_BOTTOM_RIGHT:
+ *total_length = work_area_.width();
+ *max_balloon_length = max_balloon_width();
+ break;
+ case VERTICALLY_FROM_TOP_RIGHT:
+ case VERTICALLY_FROM_BOTTOM_RIGHT:
+ *total_length = work_area_.height();
+ *max_balloon_length = max_balloon_height();
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
« no previous file with comments | « chrome/browser/notifications/balloon_view_win.cc ('k') | chrome/browser/notifications/balloons.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698