summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/views/status_icons
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-09 07:35:32 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-09 07:35:32 +0000
commit213dac2f0bff9162502fe325b6ebb85a255efcb2 (patch)
tree3640cb1f19976e38677b8632537d2d41f8444d0f /chrome/browser/ui/views/status_icons
parent6de53d401aa8dc6c7e0a9874c71a95ce88ade50d (diff)
downloadchromium_src-213dac2f0bff9162502fe325b6ebb85a255efcb2.zip
chromium_src-213dac2f0bff9162502fe325b6ebb85a255efcb2.tar.gz
chromium_src-213dac2f0bff9162502fe325b6ebb85a255efcb2.tar.bz2
Move browser/views to browser/ui/views
TBR=brettw BUG=none TEST=none Review URL: http://codereview.chromium.org/4694005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@65508 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/ui/views/status_icons')
-rw-r--r--chrome/browser/ui/views/status_icons/status_icon_win.cc89
-rw-r--r--chrome/browser/ui/views/status_icons/status_icon_win.h65
-rw-r--r--chrome/browser/ui/views/status_icons/status_tray_gtk.cc10
-rw-r--r--chrome/browser/ui/views/status_icons/status_tray_win.cc81
-rw-r--r--chrome/browser/ui/views/status_icons/status_tray_win.h43
-rw-r--r--chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc55
6 files changed, 343 insertions, 0 deletions
diff --git a/chrome/browser/ui/views/status_icons/status_icon_win.cc b/chrome/browser/ui/views/status_icons/status_icon_win.cc
new file mode 100644
index 0000000..5545560
--- /dev/null
+++ b/chrome/browser/ui/views/status_icons/status_icon_win.cc
@@ -0,0 +1,89 @@
+// Copyright (c) 2010 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/views/status_icons/status_icon_win.h"
+
+#include "base/sys_string_conversions.h"
+#include "gfx/icon_util.h"
+#include "gfx/point.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "views/controls/menu/menu_2.h"
+
+StatusIconWin::StatusIconWin(UINT id, HWND window, UINT message)
+ : icon_id_(id),
+ window_(window),
+ message_id_(message) {
+ NOTIFYICONDATA icon_data;
+ InitIconData(&icon_data);
+ icon_data.uFlags = NIF_MESSAGE;
+ icon_data.uCallbackMessage = message_id_;
+ BOOL result = Shell_NotifyIcon(NIM_ADD, &icon_data);
+ DCHECK(result);
+}
+
+StatusIconWin::~StatusIconWin() {
+ // Remove our icon.
+ NOTIFYICONDATA icon_data;
+ InitIconData(&icon_data);
+ Shell_NotifyIcon(NIM_DELETE, &icon_data);
+}
+
+void StatusIconWin::SetImage(const SkBitmap& image) {
+ // Create the icon.
+ NOTIFYICONDATA icon_data;
+ InitIconData(&icon_data);
+ icon_data.uFlags = NIF_ICON;
+ icon_.Set(IconUtil::CreateHICONFromSkBitmap(image));
+ icon_data.hIcon = icon_.Get();
+ BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
+ DCHECK(result);
+}
+
+void StatusIconWin::SetPressedImage(const SkBitmap& image) {
+ // Ignore pressed images, since the standard on Windows is to not highlight
+ // pressed status icons.
+}
+
+void StatusIconWin::SetToolTip(const string16& tool_tip) {
+ // Create the icon.
+ NOTIFYICONDATA icon_data;
+ InitIconData(&icon_data);
+ icon_data.uFlags = NIF_TIP;
+ wcscpy_s(icon_data.szTip, tool_tip.c_str());
+ BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
+ DCHECK(result);
+}
+
+void StatusIconWin::InitIconData(NOTIFYICONDATA* icon_data) {
+ icon_data->cbSize = sizeof(icon_data);
+ icon_data->hWnd = window_;
+ icon_data->uID = icon_id_;
+}
+
+void StatusIconWin::UpdatePlatformContextMenu(menus::MenuModel* menu) {
+ // If no items are passed, blow away our context menu.
+ if (!menu) {
+ context_menu_.reset();
+ return;
+ }
+
+ // Create context menu with the new contents.
+ context_menu_.reset(new views::Menu2(menu));
+}
+
+void StatusIconWin::HandleClickEvent(int x, int y, bool left_mouse_click) {
+ // Pass to the observer if appropriate.
+ if (left_mouse_click && HasObservers()) {
+ DispatchClickEvent();
+ return;
+ }
+
+ // Event not sent to the observer, so display the context menu if one exists.
+ if (context_menu_.get()) {
+ // Set our window as the foreground window, so the context menu closes when
+ // we click away from it.
+ SetForegroundWindow(window_);
+ context_menu_->RunContextMenuAt(gfx::Point(x, y));
+ }
+}
diff --git a/chrome/browser/ui/views/status_icons/status_icon_win.h b/chrome/browser/ui/views/status_icons/status_icon_win.h
new file mode 100644
index 0000000..74c3742
--- /dev/null
+++ b/chrome/browser/ui/views/status_icons/status_icon_win.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_ICON_WIN_H_
+#define CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_ICON_WIN_H_
+#pragma once
+
+#include <windows.h>
+#include <shellapi.h>
+
+#include "base/scoped_handle_win.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/status_icons/status_icon.h"
+
+namespace views {
+class Menu2;
+}
+
+class StatusIconWin : public StatusIcon {
+ public:
+ // Constructor which provides this icon's unique ID and messaging window.
+ StatusIconWin(UINT id, HWND window, UINT message);
+ virtual ~StatusIconWin();
+
+ // Overridden from StatusIcon:
+ virtual void SetImage(const SkBitmap& image);
+ virtual void SetPressedImage(const SkBitmap& image);
+ virtual void SetToolTip(const string16& tool_tip);
+
+ UINT icon_id() const { return icon_id_; }
+
+ UINT message_id() const { return message_id_; }
+
+ // Handles a click event from the user - if |left_button_click| is true and
+ // there is a registered observer, passes the click event to the observer,
+ // otherwise displays the context menu if there is one.
+ void HandleClickEvent(int x, int y, bool left_button_click);
+
+ protected:
+ // Overridden from StatusIcon.
+ virtual void UpdatePlatformContextMenu(menus::MenuModel* menu);
+
+ private:
+ void InitIconData(NOTIFYICONDATA* icon_data);
+
+ // The unique ID corresponding to this icon.
+ UINT icon_id_;
+
+ // Window used for processing messages from this icon.
+ HWND window_;
+
+ // The message identifier used for status icon messages.
+ UINT message_id_;
+
+ // The currently-displayed icon for the window.
+ ScopedHICON icon_;
+
+ // Context menu associated with this icon (if any).
+ scoped_ptr<views::Menu2> context_menu_;
+
+ DISALLOW_COPY_AND_ASSIGN(StatusIconWin);
+};
+
+#endif // CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_ICON_WIN_H_
diff --git a/chrome/browser/ui/views/status_icons/status_tray_gtk.cc b/chrome/browser/ui/views/status_icons/status_tray_gtk.cc
new file mode 100644
index 0000000..7cd0666
--- /dev/null
+++ b/chrome/browser/ui/views/status_icons/status_tray_gtk.cc
@@ -0,0 +1,10 @@
+// Copyright (c) 2010 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/status_icons/status_tray.h"
+
+// Status icons are not currently supported on linux/views.
+StatusTray* StatusTray::Create() {
+ return NULL;
+}
diff --git a/chrome/browser/ui/views/status_icons/status_tray_win.cc b/chrome/browser/ui/views/status_icons/status_tray_win.cc
new file mode 100644
index 0000000..29ed025
--- /dev/null
+++ b/chrome/browser/ui/views/status_icons/status_tray_win.cc
@@ -0,0 +1,81 @@
+// Copyright (c) 2010 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/views/status_icons/status_tray_win.h"
+
+#include "base/win_util.h"
+#include "chrome/browser/views/status_icons/status_icon_win.h"
+#include "chrome/common/chrome_constants.h"
+
+static const UINT kStatusIconMessage = WM_APP + 1;
+
+StatusTrayWin::StatusTrayWin()
+ : next_icon_id_(1) {
+ // Register our window class
+ HINSTANCE hinst = GetModuleHandle(NULL);
+ WNDCLASSEX wc = {0};
+ wc.cbSize = sizeof(wc);
+ wc.lpfnWndProc = StatusTrayWin::WndProcStatic;
+ wc.hInstance = hinst;
+ wc.lpszClassName = chrome::kStatusTrayWindowClass;
+ ATOM clazz = RegisterClassEx(&wc);
+ DCHECK(clazz);
+
+ // Create an offscreen window for handling messages for the status icons.
+ window_ = CreateWindow(chrome::kStatusTrayWindowClass,
+ 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, hinst, 0);
+ win_util::SetWindowUserData(window_, this);
+}
+
+LRESULT CALLBACK StatusTrayWin::WndProcStatic(HWND hwnd,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam) {
+ StatusTrayWin* msg_wnd = reinterpret_cast<StatusTrayWin*>(
+ GetWindowLongPtr(hwnd, GWLP_USERDATA));
+ return msg_wnd->WndProc(hwnd, message, wparam, lparam);
+}
+
+LRESULT CALLBACK StatusTrayWin::WndProc(HWND hwnd,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam) {
+ switch (message) {
+ case kStatusIconMessage:
+ switch (lparam) {
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_CONTEXTMENU:
+ // Walk our icons, find which one was clicked on, and invoke its
+ // HandleClickEvent() method.
+ for (StatusIconList::const_iterator iter = status_icons().begin();
+ iter != status_icons().end();
+ ++iter) {
+ StatusIconWin* win_icon = static_cast<StatusIconWin*>(*iter);
+ if (win_icon->icon_id() == wparam) {
+ POINT p;
+ GetCursorPos(&p);
+ win_icon->HandleClickEvent(p.x, p.y, lparam == WM_LBUTTONDOWN);
+ }
+ }
+ return TRUE;
+ }
+ break;
+ }
+ return ::DefWindowProc(hwnd, message, wparam, lparam);
+}
+
+StatusTrayWin::~StatusTrayWin() {
+ if (window_)
+ DestroyWindow(window_);
+ UnregisterClass(chrome::kStatusTrayWindowClass, GetModuleHandle(NULL));
+}
+
+StatusIcon* StatusTrayWin::CreatePlatformStatusIcon() {
+ return new StatusIconWin(next_icon_id_++, window_, kStatusIconMessage);
+}
+
+StatusTray* StatusTray::Create() {
+ return new StatusTrayWin();
+}
diff --git a/chrome/browser/ui/views/status_icons/status_tray_win.h b/chrome/browser/ui/views/status_icons/status_tray_win.h
new file mode 100644
index 0000000..c6d3c52
--- /dev/null
+++ b/chrome/browser/ui/views/status_icons/status_tray_win.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_TRAY_WIN_H_
+#define CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_TRAY_WIN_H_
+#pragma once
+
+#include <windows.h>
+
+#include "chrome/browser/status_icons/status_tray.h"
+
+class StatusTrayWin : public StatusTray {
+ public:
+ StatusTrayWin();
+ ~StatusTrayWin();
+
+ // Exposed for testing.
+ LRESULT CALLBACK WndProc(HWND hwnd,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam);
+ protected:
+ // Overriden from StatusTray:
+ virtual StatusIcon* CreatePlatformStatusIcon();
+
+ private:
+ // Static callback invoked when a message comes in to our messaging window.
+ static LRESULT CALLBACK WndProcStatic(HWND hwnd,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam);
+
+ // The unique icon ID we will assign to the next icon.
+ UINT next_icon_id_;
+ // The window used for processing events.
+ HWND window_;
+
+ DISALLOW_COPY_AND_ASSIGN(StatusTrayWin);
+};
+
+#endif // CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_TRAY_WIN_H_
+
diff --git a/chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc b/chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc
new file mode 100644
index 0000000..c824755
--- /dev/null
+++ b/chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc
@@ -0,0 +1,55 @@
+// Copyright (c) 2010 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 "app/menus/simple_menu_model.h"
+#include "app/resource_bundle.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/views/status_icons/status_icon_win.h"
+#include "chrome/browser/views/status_icons/status_tray_win.h"
+#include "grit/browser_resources.h"
+#include "grit/theme_resources.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class SkBitmap;
+
+class MockStatusIconObserver : public StatusIcon::Observer {
+ public:
+ MOCK_METHOD0(OnClicked, void());
+};
+
+TEST(StatusTrayWinTest, CreateTray) {
+ // Just tests creation/destruction.
+ StatusTrayWin tray;
+}
+
+TEST(StatusTrayWinTest, CreateIconAndMenu) {
+ // Create an icon, set the images, tooltip, and context menu, then shut it
+ // down.
+ StatusTrayWin tray;
+ StatusIcon* icon = tray.CreateStatusIcon();
+ SkBitmap* bitmap = ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_STATUS_TRAY_ICON);
+ icon->SetImage(*bitmap);
+ icon->SetPressedImage(*bitmap);
+ icon->SetToolTip(ASCIIToUTF16("tool tip"));
+ menus::SimpleMenuModel* menu = new menus::SimpleMenuModel(NULL);
+ menu->AddItem(0, L"foo");
+ icon->SetContextMenu(menu);
+}
+
+TEST(StatusTrayWinTest, ClickOnIcon) {
+ // Create an icon, send a fake click event, make sure observer is called.
+ StatusTrayWin tray;
+ StatusIconWin* icon = static_cast<StatusIconWin*>(tray.CreateStatusIcon());
+ MockStatusIconObserver observer;
+ icon->AddObserver(&observer);
+ EXPECT_CALL(observer, OnClicked());
+ // Mimic a click.
+ tray.WndProc(NULL, icon->message_id(), icon->icon_id(), WM_LBUTTONDOWN);
+ // Mimic a right-click - observer should not be called.
+ tray.WndProc(NULL, icon->message_id(), icon->icon_id(), WM_RBUTTONDOWN);
+ icon->RemoveObserver(&observer);
+}