diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 0b2c8c9ece79..6ff1dfc00628 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -18,14 +18,20 @@ #include "native_mate/dictionary.h" #include "ui/gfx/geometry/rect.h" +#if defined(OS_WIN) +#include "atom/browser/native_window_views.h" +#include "atom/browser/ui/win/taskbar_host.h" +#endif + #include "atom/common/node_includes.h" +#if defined(OS_WIN) namespace mate { template<> -struct Converter { +struct Converter { static bool FromV8(v8::Isolate* isolate, v8::Handle val, - atom::NativeWindow::ThumbarButton* out) { + atom::TaskbarHost::ThumbarButton* out) { mate::Dictionary dict; if (!ConvertFromV8(isolate, val, &dict)) return false; @@ -37,6 +43,7 @@ struct Converter { }; } // namespace mate +#endif namespace atom { @@ -431,9 +438,19 @@ void Window::SetOverlayIcon(const gfx::Image& overlay, window_->SetOverlayIcon(overlay, description); } -void Window::SetThumbarButtons( - const std::vector& buttons) { - window_->SetThumbarButtons(buttons); +bool Window::SetThumbarButtons(mate::Arguments* args) { +#if defined(OS_WIN) + std::vector buttons; + if (!args->GetNext(&buttons)) { + args->ThrowError(); + return false; + } + auto window = static_cast(window_.get()); + return window->taskbar_host().SetThumbarButtons( + window->GetAcceleratedWidget(), buttons); +#else + return false; +#endif } void Window::SetMenu(v8::Isolate* isolate, v8::Local value) { diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 7742c8a9fa9b..de2f093ea3e1 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -130,8 +130,7 @@ class Window : public mate::TrackableObject, void SetProgressBar(double progress); void SetOverlayIcon(const gfx::Image& overlay, const std::string& description); - void SetThumbarButtons( - const std::vector& buttons); + bool SetThumbarButtons(mate::Arguments* args); void SetMenu(v8::Isolate* isolate, v8::Local menu); void SetAutoHideMenuBar(bool auto_hide); bool IsMenuBarAutoHide(); diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 91770af316e3..96085846bca8 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -277,11 +277,6 @@ bool NativeWindow::HasModalDialog() { return has_dialog_attached_; } -bool NativeWindow::SetThumbarButtons( - const std::vector& buttons) { - return false; -} - void NativeWindow::FocusOnWebView() { web_contents()->GetRenderViewHost()->Focus(); } diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index d461215222d6..b9294d38c931 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -60,14 +60,6 @@ class NativeWindow : public content::WebContentsObserver, public brightray::InspectableWebContentsViewDelegate { public: using CapturePageCallback = base::Callback; - using ThumbarButtonClickedCallback = base::Closure; - - struct ThumbarButton { - std::string tooltip; - gfx::Image icon; - std::vector flags; - ThumbarButtonClickedCallback clicked_callback; - }; class DialogScope { public: @@ -103,6 +95,7 @@ class NativeWindow : public content::WebContentsObserver, virtual void Close() = 0; virtual void CloseImmediately() = 0; + virtual bool IsClosed() const { return is_closed_; } virtual void Focus(bool focus) = 0; virtual bool IsFocused() = 0; virtual void Show() = 0; @@ -147,16 +140,17 @@ class NativeWindow : public content::WebContentsObserver, virtual void SetMenu(ui::MenuModel* menu); virtual bool HasModalDialog(); virtual gfx::NativeWindow GetNativeWindow() = 0; + + // Taskbar/Dock APIs. virtual void SetProgressBar(double progress) = 0; virtual void SetOverlayIcon(const gfx::Image& overlay, const std::string& description) = 0; + + // Workspace APIs. virtual void SetVisibleOnAllWorkspaces(bool visible) = 0; virtual bool IsVisibleOnAllWorkspaces() = 0; - virtual bool SetThumbarButtons( - const std::vector& buttons); - - virtual bool IsClosed() const { return is_closed_; } + // Webview APIs. virtual void FocusOnWebView(); virtual void BlurWebView(); virtual bool IsWebViewFocused(); diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index acb7de33f4d6..45697c96683c 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -4,10 +4,6 @@ #include "atom/browser/native_window_views.h" -#if defined(OS_WIN) -#include -#endif - #include #include @@ -46,13 +42,9 @@ #elif defined(OS_WIN) #include "atom/browser/ui/views/win_frame_view.h" #include "atom/browser/ui/win/atom_desktop_window_tree_host_win.h" -#include "base/win/scoped_comptr.h" -#include "base/win/windows_version.h" #include "ui/base/win/shell.h" -#include "ui/gfx/icon_util.h" #include "ui/gfx/win/dpi.h" #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" -#include "ui/views/win/hwnd_util.h" #endif namespace atom { @@ -221,11 +213,11 @@ NativeWindowViews::NativeWindowViews( params.native_widget = new views::DesktopNativeWidgetAura(window_.get()); atom_desktop_window_tree_host_win_ = new AtomDesktopWindowTreeHostWin( + this, window_.get(), static_cast(params.native_widget)); params.desktop_window_tree_host = atom_desktop_window_tree_host_win_; -#endif -#if defined(USE_X11) +#elif defined(USE_X11) std::string name = Browser::Get()->GetName(); // Set WM_WINDOW_ROLE. params.wm_role_name = "browser-window"; @@ -621,24 +613,7 @@ gfx::NativeWindow NativeWindowViews::GetNativeWindow() { void NativeWindowViews::SetProgressBar(double progress) { #if defined(OS_WIN) - if (base::win::GetVersion() < base::win::VERSION_WIN7) - return; - base::win::ScopedComPtr taskbar; - if (FAILED(taskbar.CreateInstance(CLSID_TaskbarList, NULL, - CLSCTX_INPROC_SERVER) || - FAILED(taskbar->HrInit()))) { - return; - } - HWND frame = views::HWNDForNativeWindow(GetNativeWindow()); - if (progress > 1.0) { - taskbar->SetProgressState(frame, TBPF_INDETERMINATE); - } else if (progress < 0) { - taskbar->SetProgressState(frame, TBPF_NOPROGRESS); - } else if (progress >= 0) { - taskbar->SetProgressValue(frame, - static_cast(progress * 100), - 100); - } + taskbar_host_.SetProgressBar(GetAcceleratedWidget(), progress); #elif defined(USE_X11) if (unity::IsRunning()) { unity::SetProgressFraction(progress); @@ -649,22 +624,7 @@ void NativeWindowViews::SetProgressBar(double progress) { void NativeWindowViews::SetOverlayIcon(const gfx::Image& overlay, const std::string& description) { #if defined(OS_WIN) - if (base::win::GetVersion() < base::win::VERSION_WIN7) - return; - - base::win::ScopedComPtr taskbar; - if (FAILED(taskbar.CreateInstance(CLSID_TaskbarList, NULL, - CLSCTX_INPROC_SERVER) || - FAILED(taskbar->HrInit()))) { - return; - } - - HWND frame = views::HWNDForNativeWindow(GetNativeWindow()); - - std::wstring wstr = std::wstring(description.begin(), description.end()); - taskbar->SetOverlayIcon(frame, - IconUtil::CreateHICONFromSkBitmap(overlay.AsBitmap()), - wstr.c_str()); + taskbar_host_.SetOverlayIcon(GetAcceleratedWidget(), overlay, description); #endif } @@ -717,18 +677,6 @@ bool NativeWindowViews::IsVisibleOnAllWorkspaces() { return false; } -bool NativeWindowViews::SetThumbarButtons( - const std::vector& buttons) { -#if defined(OS_WIN) - if (atom_desktop_window_tree_host_win_) { - return atom_desktop_window_tree_host_win_->SetThumbarButtons( - views::HWNDForNativeWindow(window_->GetNativeWindow()), - buttons); - } -#endif - return false; -} - gfx::AcceleratedWidget NativeWindowViews::GetAcceleratedWidget() { return GetNativeWindow()->GetHost()->GetAcceleratedWidget(); } @@ -890,6 +838,17 @@ void NativeWindowViews::GetDevToolsWindowWMClass( } #endif +#if defined(OS_WIN) +bool NativeWindowViews::PreHandleMSG( + UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) { + // Handle thumbar button click message. + if (message == WM_COMMAND && HIWORD(w_param) == THBN_CLICKED) + return taskbar_host_.HandleThumbarButtonEvent(LOWORD(w_param)); + else + return false; +} +#endif + void NativeWindowViews::HandleKeyboardEvent( content::WebContents*, const content::NativeWebKeyboardEvent& event) { diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 792a72c75624..355f5bd38ef3 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -14,6 +14,11 @@ #include "ui/views/widget/widget_delegate.h" #include "ui/views/widget/widget_observer.h" +#if defined(OS_WIN) +#include "atom/browser/ui/win/message_handler_delegate.h" +#include "atom/browser/ui/win/taskbar_host.h" +#endif + namespace views { class UnhandledKeyboardEventHandler; } @@ -23,11 +28,15 @@ namespace atom { class GlobalMenuBarX11; class MenuBar; class WindowStateWatcher; + #if defined(OS_WIN) class AtomDesktopWindowTreeHostWin; #endif class NativeWindowViews : public NativeWindow, +#if defined(OS_WIN) + public MessageHandlerDelegate, +#endif public views::WidgetDelegateView, public views::WidgetObserver { public: @@ -82,13 +91,15 @@ class NativeWindowViews : public NativeWindow, bool IsMenuBarVisible() override; void SetVisibleOnAllWorkspaces(bool visible) override; bool IsVisibleOnAllWorkspaces() override; - bool SetThumbarButtons( - const std::vector& buttons) override; gfx::AcceleratedWidget GetAcceleratedWidget(); views::Widget* widget() const { return window_.get(); } +#if defined(OS_WIN) + TaskbarHost& taskbar_host() { return taskbar_host_; } +#endif + private: // views::WidgetObserver: void OnWidgetActivationChanged( @@ -127,6 +138,12 @@ class NativeWindowViews : public NativeWindow, std::string* name, std::string* class_name) override; #endif +#if defined(OS_WIN) + // MessageHandlerDelegate: + bool PreHandleMSG( + UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) override; +#endif + // NativeWindow: void HandleKeyboardEvent( content::WebContents*, @@ -164,6 +181,8 @@ class NativeWindowViews : public NativeWindow, // Records window was whether restored from minimized state or maximized // state. bool is_minimized_; + // In charge of running taskbar related APIs. + TaskbarHost taskbar_host_; #endif // Handles unhandled keyboard messages coming back from the renderer process. diff --git a/atom/browser/ui/win/atom_desktop_window_tree_host_win.cc b/atom/browser/ui/win/atom_desktop_window_tree_host_win.cc index 157cb610fb3a..84a6d9aa3e50 100644 --- a/atom/browser/ui/win/atom_desktop_window_tree_host_win.cc +++ b/atom/browser/ui/win/atom_desktop_window_tree_host_win.cc @@ -4,48 +4,25 @@ #include "atom/browser/ui/win/atom_desktop_window_tree_host_win.h" -#include - -#include "atom/browser/native_window.h" -#include "atom/browser/ui/win/thumbar_host.h" +#include "atom/browser/ui/win/message_handler_delegate.h" namespace atom { AtomDesktopWindowTreeHostWin::AtomDesktopWindowTreeHostWin( + MessageHandlerDelegate* delegate, views::internal::NativeWidgetDelegate* native_widget_delegate, views::DesktopNativeWidgetAura* desktop_native_widget_aura) : views::DesktopWindowTreeHostWin(native_widget_delegate, - desktop_native_widget_aura) { + desktop_native_widget_aura), + delegate_(delegate) { } AtomDesktopWindowTreeHostWin::~AtomDesktopWindowTreeHostWin() { } -bool AtomDesktopWindowTreeHostWin::SetThumbarButtons( - HWND window, - const std::vector& buttons) { - if (!thumbar_host_.get()) { - thumbar_host_.reset(new ThumbarHost(window)); - } - return thumbar_host_->SetThumbarButtons(buttons); -} - -bool AtomDesktopWindowTreeHostWin::PreHandleMSG(UINT message, - WPARAM w_param, - LPARAM l_param, - LRESULT* result) { - switch (message) { - case WM_COMMAND: { - // Handle thumbar button click message. - int id = LOWORD(w_param); - int thbn_message = HIWORD(w_param); - if (thbn_message == THBN_CLICKED && thumbar_host_ && - thumbar_host_->HandleThumbarButtonEvent(id)) - return true; - } - } - - return false; +bool AtomDesktopWindowTreeHostWin::PreHandleMSG( + UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) { + return delegate_->PreHandleMSG(message, w_param, l_param, result); } } // namespace atom diff --git a/atom/browser/ui/win/atom_desktop_window_tree_host_win.h b/atom/browser/ui/win/atom_desktop_window_tree_host_win.h index fc09b6503b80..47e4cb6aed2a 100644 --- a/atom/browser/ui/win/atom_desktop_window_tree_host_win.h +++ b/atom/browser/ui/win/atom_desktop_window_tree_host_win.h @@ -10,31 +10,28 @@ #include #include "atom/browser/native_window.h" -#include "atom/browser/ui/win/thumbar_host.h" -#include "base/memory/scoped_ptr.h" #include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h" namespace atom { +class MessageHandlerDelegate; + class AtomDesktopWindowTreeHostWin : public views::DesktopWindowTreeHostWin { public: AtomDesktopWindowTreeHostWin( + MessageHandlerDelegate* delegate, views::internal::NativeWidgetDelegate* native_widget_delegate, views::DesktopNativeWidgetAura* desktop_native_widget_aura); - ~AtomDesktopWindowTreeHostWin(); - - bool SetThumbarButtons( - HWND window, - const std::vector& buttons); + ~AtomDesktopWindowTreeHostWin() override; protected: - bool PreHandleMSG(UINT message, - WPARAM w_param, - LPARAM l_param, - LRESULT* result) override; + bool PreHandleMSG( + UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) override; private: - scoped_ptr thumbar_host_; + MessageHandlerDelegate* delegate_; // weak ref + + DISALLOW_COPY_AND_ASSIGN(AtomDesktopWindowTreeHostWin); }; } // namespace atom diff --git a/atom/browser/ui/win/message_handler_delegate.cc b/atom/browser/ui/win/message_handler_delegate.cc new file mode 100644 index 000000000000..791d1fd816d9 --- /dev/null +++ b/atom/browser/ui/win/message_handler_delegate.cc @@ -0,0 +1,14 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/ui/win/message_handler_delegate.h" + +namespace atom { + +bool MessageHandlerDelegate::PreHandleMSG( + UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) { + return false; +} + +} // namespace atom diff --git a/atom/browser/ui/win/message_handler_delegate.h b/atom/browser/ui/win/message_handler_delegate.h new file mode 100644 index 000000000000..d8cfcf7fc43b --- /dev/null +++ b/atom/browser/ui/win/message_handler_delegate.h @@ -0,0 +1,26 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_UI_WIN_MESSAGE_HANDLER_DELEGATE_H_ +#define ATOM_BROWSER_UI_WIN_MESSAGE_HANDLER_DELEGATE_H_ + +#include + +namespace atom { + +class MessageHandlerDelegate { + public: + // Catch-all message handling and filtering. Called before + // HWNDMessageHandler's built-in handling, which may pre-empt some + // expectations in Views/Aura if messages are consumed. Returns true if the + // message was consumed by the delegate and should not be processed further + // by the HWNDMessageHandler. In this case, |result| is returned. |result| is + // not modified otherwise. + virtual bool PreHandleMSG( + UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_UI_WIN_MESSAGE_HANDLER_DELEGATE_H_ diff --git a/atom/browser/ui/win/taskbar_host.cc b/atom/browser/ui/win/taskbar_host.cc new file mode 100644 index 000000000000..c728e4664c3a --- /dev/null +++ b/atom/browser/ui/win/taskbar_host.cc @@ -0,0 +1,165 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/ui/win/taskbar_host.h" + +#include + +#include "base/stl_util.h" +#include "base/win/scoped_gdi_object.h" +#include "base/strings/utf_string_conversions.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/icon_util.h" + +namespace atom { + +namespace { + +// From MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#thumbbars +// The thumbnail toolbar has a maximum of seven buttons due to the limited room. +const size_t kMaxButtonsCount = 7; + +// The base id of Thumbar button. +const int kButtonIdBase = 40001; + +bool GetThumbarButtonFlags(const std::vector& flags, + THUMBBUTTONFLAGS* out) { + THUMBBUTTONFLAGS result = THBF_ENABLED; // THBF_ENABLED == 0 + for (const auto& flag : flags) { + if (flag == "disabled") + result |= THBF_DISABLED; + else if (flag == "dismissonclick") + result |= THBF_DISMISSONCLICK; + else if (flag == "nobackground") + result |= THBF_NOBACKGROUND; + else if (flag == "hidden") + result |= THBF_HIDDEN; + else if (flag == "noninteractive") + result |= THBF_NONINTERACTIVE; + else + return false; + } + *out = result; + return true; +} + +} // namespace + +TaskbarHost::TaskbarHost() : thumbar_buttons_added_(false) { +} + +TaskbarHost::~TaskbarHost() { +} + +bool TaskbarHost::SetThumbarButtons( + HWND window, const std::vector& buttons) { + if (!InitailizeTaskbar()) + return false; + + callback_map_.clear(); + + // The number of buttons in thumbar can not be changed once it is created, + // so we have to claim kMaxButtonsCount buttons initialy in case users add + // more buttons later. + base::win::ScopedHICON icons[kMaxButtonsCount] = {}; + THUMBBUTTON thumb_buttons[kMaxButtonsCount] = {}; + + for (size_t i = 0; i < kMaxButtonsCount; ++i) { + THUMBBUTTON& thumb_button = thumb_buttons[i]; + + // Set ID. + thumb_button.iId = kButtonIdBase + i; + thumb_button.dwMask = THB_FLAGS; + + if (i >= buttons.size()) { + // This button is used to occupy the place in toolbar, and it does not + // show. + thumb_button.dwFlags = THBF_HIDDEN; + continue; + } + + // This button is user's button. + const ThumbarButton& button = buttons[i]; + + // Generate flags. + thumb_button.dwFlags = THBF_ENABLED; + if (!GetThumbarButtonFlags(button.flags, &thumb_button.dwFlags)) + return false; + + // Set icon. + if (!button.icon.IsEmpty()) { + thumb_button.dwMask |= THB_ICON; + icons[i] = IconUtil::CreateHICONFromSkBitmap(button.icon.AsBitmap()); + thumb_button.hIcon = icons[i].Get(); + } + + // Set tooltip. + if (!button.tooltip.empty()) { + thumb_button.dwMask |= THB_TOOLTIP; + wcscpy_s(thumb_button.szTip, base::UTF8ToUTF16(button.tooltip).c_str()); + } + + // Save callback. + callback_map_[thumb_button.iId] = button.clicked_callback; + } + + // Finally add them to taskbar. + HRESULT r; + if (thumbar_buttons_added_) + r = taskbar_->ThumbBarUpdateButtons(window, kMaxButtonsCount, + thumb_buttons); + else + r = taskbar_->ThumbBarAddButtons(window, kMaxButtonsCount, thumb_buttons); + + thumbar_buttons_added_ = true; + return SUCCEEDED(r); +} + +bool TaskbarHost::SetProgressBar(HWND window, double value) { + if (!InitailizeTaskbar()) + return false; + + HRESULT r; + if (value > 1.0) + r = taskbar_->SetProgressState(window, TBPF_INDETERMINATE); + else if (value < 0) + r = taskbar_->SetProgressState(window, TBPF_NOPROGRESS); + else + r = taskbar_->SetProgressValue(window, static_cast(value * 100), 100); + return SUCCEEDED(r); +} + +bool TaskbarHost::SetOverlayIcon( + HWND window, const gfx::Image& overlay, const std::string& text) { + if (!InitailizeTaskbar()) + return false; + + base::win::ScopedHICON icon( + IconUtil::CreateHICONFromSkBitmap(overlay.AsBitmap())); + return SUCCEEDED( + taskbar_->SetOverlayIcon(window, icon, base::UTF8ToUTF16(text).c_str())); +} + +bool TaskbarHost::HandleThumbarButtonEvent(int button_id) { + if (ContainsKey(callback_map_, button_id)) { + auto callback = callback_map_[button_id]; + if (!callback.is_null()) + callback.Run(); + return true; + } + return false; +} + +bool TaskbarHost::InitailizeTaskbar() { + if (FAILED(taskbar_.CreateInstance(CLSID_TaskbarList, + nullptr, + CLSCTX_INPROC_SERVER)) || + FAILED(taskbar_->HrInit())) { + return false; + } else { + return true; + } +} + +} // namespace atom diff --git a/atom/browser/ui/win/taskbar_host.h b/atom/browser/ui/win/taskbar_host.h new file mode 100644 index 000000000000..185b88a6b5b6 --- /dev/null +++ b/atom/browser/ui/win/taskbar_host.h @@ -0,0 +1,64 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_UI_WIN_TASKBAR_HOST_H_ +#define ATOM_BROWSER_UI_WIN_TASKBAR_HOST_H_ + +#include + +#include +#include +#include + +#include "base/callback.h" +#include "base/win/scoped_comptr.h" +#include "ui/gfx/image/image.h" + +namespace atom { + +class TaskbarHost { + public: + struct ThumbarButton { + std::string tooltip; + gfx::Image icon; + std::vector flags; + base::Closure clicked_callback; + }; + + TaskbarHost(); + virtual ~TaskbarHost(); + + // Add or update the buttons in thumbar. + bool SetThumbarButtons( + HWND window, const std::vector& buttons); + + // Set the progress state in taskbar. + bool SetProgressBar(HWND window, double value); + + // Set the overlay icon in taskbar. + bool SetOverlayIcon( + HWND window, const gfx::Image& overlay, const std::string& text); + + // Called by the window that there is a button in thumbar clicked. + bool HandleThumbarButtonEvent(int button_id); + + private: + // Initailize the taskbar object. + bool InitailizeTaskbar(); + + using CallbackMap = std::map; + CallbackMap callback_map_; + + // The COM object of taskbar. + base::win::ScopedComPtr taskbar_; + + // Whether we have already added the buttons to thumbar. + bool thumbar_buttons_added_; + + DISALLOW_COPY_AND_ASSIGN(TaskbarHost); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_UI_WIN_TASKBAR_HOST_H_ diff --git a/atom/browser/ui/win/thumbar_host.cc b/atom/browser/ui/win/thumbar_host.cc deleted file mode 100644 index af57ef4e5c64..000000000000 --- a/atom/browser/ui/win/thumbar_host.cc +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) 2015 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "atom/browser/ui/win/thumbar_host.h" - -#include - -#include - -#include "base/win/scoped_comptr.h" -#include "base/win/win_util.h" -#include "base/win/wrapped_window_proc.h" -#include "base/strings/utf_string_conversions.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/gfx/icon_util.h" -#include "ui/gfx/win/hwnd_util.h" - -namespace atom { - -namespace { - -// From MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/ -// dd378460(v=vs.85).aspx#thumbbars -// The thumbnail toolbar has a maximum of seven buttons due to the limited room. -const int kMaxButtonsCount = 7; - -// The base id of Thumbar button. -const int kButtonIdBase = 40001; - -bool GetThumbarButtonFlags(const std::vector& flags, - THUMBBUTTONFLAGS* out) { - if (flags.empty()) { - *out = THBF_ENABLED; - return true; - } - THUMBBUTTONFLAGS result = static_cast(0); - for (const auto& flag : flags) { - if (flag == "enabled") { - result |= THBF_ENABLED; - } else if (flag == "disabled") { - result |= THBF_DISABLED; - } else if (flag == "dismissonclick") { - result |= THBF_DISMISSONCLICK; - } else if (flag == "nobackground") { - result |= THBF_NOBACKGROUND; - } else if (flag == "hidden") { - result |= THBF_HIDDEN; - } else if (flag == "noninteractive") { - result |= THBF_NONINTERACTIVE; - } else { - return false; - } - } - *out = result; - return true; -} - -} // namespace - -ThumbarHost::ThumbarHost(HWND window) : is_initialized_(false), - window_(window) { -} - -ThumbarHost::~ThumbarHost() { -} - -bool ThumbarHost::SetThumbarButtons( - const std::vector& buttons) { - if (buttons.size() > kMaxButtonsCount) - return false; - - base::win::ScopedComPtr taskbar; - if (FAILED(taskbar.CreateInstance(CLSID_TaskbarList, - nullptr, - CLSCTX_INPROC_SERVER)) || - FAILED(taskbar->HrInit())) { - return false; - } - - THUMBBUTTON thumb_buttons[kMaxButtonsCount] = {}; - thumbar_button_clicked_callback_map_.clear(); - - // Once a toolbar with a set of buttons is added to thumbnail, there is no way - // to remove it without re-creating the window. - // To achieve to re-set thumbar buttons, we initialize the buttons with - // HIDDEN state and only updated the caller's specified buttons. - // - // Initialize all thumb buttons with HIDDEN state. - for (int i = 0; i < kMaxButtonsCount; ++i) { - thumb_buttons[i].iId = kButtonIdBase + i; - thumb_buttons[i].dwMask = THB_FLAGS; // dwFlags is valid. - thumb_buttons[i].dwFlags = THBF_HIDDEN; - } - - // Update the callers' specified buttons. - for (size_t i = 0; i < buttons.size(); ++i) { - if (!GetThumbarButtonFlags(buttons[i].flags, &thumb_buttons[i].dwFlags)) - return false; - thumb_buttons[i].dwMask = THB_ICON | THB_FLAGS; - thumb_buttons[i].hIcon = IconUtil::CreateHICONFromSkBitmap( - buttons[i].icon.AsBitmap()); - if (!buttons[i].tooltip.empty()) { - thumb_buttons[i].dwMask |= THB_TOOLTIP; - wcscpy_s(thumb_buttons[i].szTip, - base::UTF8ToUTF16(buttons[i].tooltip).c_str()); - } - - thumbar_button_clicked_callback_map_[thumb_buttons[i].iId] = - buttons[i].clicked_callback; - } - - bool is_success = false; - if (!is_initialized_) { - is_initialized_ = true; - is_success = taskbar->ThumbBarAddButtons( - window_, buttons.size(), thumb_buttons) == S_OK; - } else { - is_success = taskbar->ThumbBarUpdateButtons( - window_, kMaxButtonsCount, thumb_buttons) == S_OK; - } - - // Release thumb_buttons' icons, the taskbar makes its own copy. - for (size_t i = 0; i < buttons.size(); ++i) { - ::DestroyIcon(thumb_buttons[i].hIcon); - } - return is_success; -} - -bool ThumbarHost::HandleThumbarButtonEvent(int button_id) { - if (thumbar_button_clicked_callback_map_.find(button_id) != - thumbar_button_clicked_callback_map_.end()) { - auto callback = thumbar_button_clicked_callback_map_[button_id]; - if (!callback.is_null()) - callback.Run(); - return true; - } - return false; -} - -} // namespace atom diff --git a/atom/browser/ui/win/thumbar_host.h b/atom/browser/ui/win/thumbar_host.h deleted file mode 100644 index d14bbaeda305..000000000000 --- a/atom/browser/ui/win/thumbar_host.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2015 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#ifndef ATOM_BROWSER_UI_WIN_THUMBAR_HOST_H_ -#define ATOM_BROWSER_UI_WIN_THUMBAR_HOST_H_ - -#include - -#include -#include - -#include "atom/browser/native_window.h" - -namespace atom { - -class ThumbarHost { - public: - explicit ThumbarHost(HWND window); - ~ThumbarHost(); - - bool SetThumbarButtons( - const std::vector& buttons); - bool HandleThumbarButtonEvent(int button_id); - - private: - using ThumbarButtonClickedCallbackMap = std::map< - int, NativeWindow::ThumbarButtonClickedCallback>; - ThumbarButtonClickedCallbackMap thumbar_button_clicked_callback_map_; - - bool is_initialized_; - - HWND window_; - - DISALLOW_COPY_AND_ASSIGN(ThumbarHost); -}; - -} // namespace atom - -#endif // ATOM_BROWSER_UI_WIN_THUMBAR_HOST_H_ diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 60b9b84735d0..612b3ce4f3f0 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -646,23 +646,24 @@ __Note:__ This API is only available on Windows (Windows 7 and above) ### BrowserWindow.setThumbarButtons(buttons) -* `buttons` Array of `button` objects +* `buttons` Array * `button` Object * `icon` [NativeImage](native-image.md) - The icon showing in thumbnail toolbar. - * `tooltip` String - (Option) - The text of the button's tooltip. - * `flags` Array of Strings - (Option) Control specific states and behaviors - of the button. By default, it uses `enabled`. - * `enabled` - The button is active and available to the user. - * `disabled` - The button is disabled. It is present, but has a visual - state that indicates that it will not respond to user action. - * `dismissonclick` - When the button is clicked, the taskbar button's - flyout closes immediately. - * `nobackground` - Do not draw a button border, use only the image. - * `hidden` - The button is not shown to the user. - * `noninteractive` - The button is enabled but not interactive; no - pressed button state is drawn. This value is intended for instances - where the button is used in a notification. + * `tooltip` String (optional) - The text of the button's tooltip. + * `flags` Array (optional) - Control specific states and behaviors + of the button. By default, it uses `enabled`. It can include following + Strings: + * `enabled` - The button is active and available to the user. + * `disabled` - The button is disabled. It is present, but has a visual + state that indicates that it will not respond to user action. + * `dismissonclick` - When the button is clicked, the taskbar button's + flyout closes immediately. + * `nobackground` - Do not draw a button border, use only the image. + * `hidden` - The button is not shown to the user. + * `noninteractive` - The button is enabled but not interactive; no + pressed button state is drawn. This value is intended for instances + where the button is used in a notification. * `click` - Function Add a thumbnail toolbar with a specified set of buttons to the thumbnail image diff --git a/filenames.gypi b/filenames.gypi index 45aaac7c2778..f7b9fca5e717 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -202,14 +202,16 @@ 'atom/browser/ui/views/submenu_button.h', 'atom/browser/ui/views/win_frame_view.cc', 'atom/browser/ui/views/win_frame_view.h', - "atom/browser/ui/win/atom_desktop_window_tree_host_win.cc", - "atom/browser/ui/win/atom_desktop_window_tree_host_win.h", + 'atom/browser/ui/win/atom_desktop_window_tree_host_win.cc', + 'atom/browser/ui/win/atom_desktop_window_tree_host_win.h', + 'atom/browser/ui/win/message_handler_delegate.cc', + 'atom/browser/ui/win/message_handler_delegate.h', 'atom/browser/ui/win/notify_icon_host.cc', 'atom/browser/ui/win/notify_icon_host.h', 'atom/browser/ui/win/notify_icon.cc', 'atom/browser/ui/win/notify_icon.h', - 'atom/browser/ui/win/thumbar_host.cc', - 'atom/browser/ui/win/thumbar_host.h', + 'atom/browser/ui/win/taskbar_host.cc', + 'atom/browser/ui/win/taskbar_host.h', 'atom/browser/ui/x/window_state_watcher.cc', 'atom/browser/ui/x/window_state_watcher.h', 'atom/browser/ui/x/x_window_utils.cc',