af435c165e64ae55e987fe39c822d64a9bd0d20d
[WebKit-https.git] / Source / WebKit / UIProcess / win / WebContextMenuProxyWin.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2017 Sony Interactive Entertainment Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "WebContextMenuProxyWin.h"
29
30 #if ENABLE(CONTEXT_MENUS)
31
32 #include "APIContextMenuClient.h"
33 #include "WebContextMenuItem.h"
34 #include "WebContextMenuItemData.h"
35 #include "WebPageProxy.h"
36 #include "WebProcessProxy.h"
37
38 namespace WebKit {
39 using namespace WebCore;
40
41 void WebContextMenuProxyWin::show()
42 {
43     Vector<Ref<WebContextMenuItem>> proposedAPIItems;
44     for (auto& item : m_context.menuItems())
45         proposedAPIItems.append(WebContextMenuItem::create(item));
46     m_contextMenuListener = WebContextMenuListenerProxy::create(this);
47     m_page.contextMenuClient().getContextMenuFromProposedMenu(m_page, WTFMove(proposedAPIItems), *m_contextMenuListener, m_context.webHitTestResultData(), m_page.process().transformHandlesToObjects(m_userData.object()).get());
48 }
49
50 static HMENU createMenu(const ContextMenuContextData &context)
51 {
52     HMENU menu = ::CreatePopupMenu();
53     MENUINFO menuInfo;
54     menuInfo.cbSize = sizeof(menuInfo);
55     menuInfo.fMask = MIM_STYLE;
56     menuInfo.dwStyle = MNS_NOTIFYBYPOS;
57     menuInfo.dwMenuData = (ULONG_PTR)&context;
58     ::SetMenuInfo(menu, &menuInfo);
59     return menu;
60 }
61
62 static void populate(const ContextMenuContextData &, HMENU, const Vector<WebContextMenuItemData>&);
63
64 static void createMenuItem(const ContextMenuContextData &context, HMENU menu, const WebContextMenuItemData &data)
65 {
66     UINT flags = 0;
67
68     flags |= data.enabled() ? MF_ENABLED : MF_DISABLED;
69     flags |= data.checked() ? MF_CHECKED : MF_UNCHECKED;
70
71     switch (data.type()) {
72     case ActionType:
73     case CheckableActionType:
74         ::AppendMenu(menu, flags | MF_STRING, data.action(), data.title().charactersWithNullTermination().data());
75         break;
76     case SeparatorType:
77         ::AppendMenu(menu, flags | MF_SEPARATOR, data.action(), nullptr);
78         break;
79     case SubmenuType:
80         HMENU submenu = createMenu(context);
81         populate(context, submenu, data.submenu());
82         ::AppendMenu(menu, flags | MF_POPUP, (UINT_PTR)submenu, data.title().charactersWithNullTermination().data());
83         break;
84     }
85 }
86
87 static void populate(const ContextMenuContextData &context, HMENU menu, const Vector<WebContextMenuItemData>& items)
88 {
89     for (auto& data : items)
90         createMenuItem(context, menu, data);
91 }
92
93 static void populate(const ContextMenuContextData &context, HMENU menu, const Vector<Ref<WebContextMenuItem>>& items)
94 {
95     for (auto& item : items) {
96         auto data = item->data();
97         createMenuItem(context, menu, data);
98     }
99 }
100
101 void WebContextMenuProxyWin::showContextMenuWithItems(Vector<Ref<WebContextMenuItem>>&& items)
102 {
103     populate(m_context, m_menu, items);
104
105     UINT flags = TPM_RIGHTBUTTON | TPM_TOPALIGN | TPM_VERPOSANIMATION | TPM_HORIZONTAL | TPM_LEFTALIGN | TPM_HORPOSANIMATION;
106     POINT pt { m_context.menuLocation().x(), m_context.menuLocation().y() };
107     HWND wnd = m_page.viewWidget();
108     ::ClientToScreen(wnd, &pt);
109     ::TrackPopupMenuEx(m_menu, flags, pt.x, pt.y, m_page.viewWidget(), nullptr);
110 }
111
112 WebContextMenuProxyWin::WebContextMenuProxyWin(WebPageProxy& page, ContextMenuContextData&& context, const UserData& userData)
113     : WebContextMenuProxy(WTFMove(context), userData)
114     , m_page(page)
115 {
116     m_menu = createMenu(m_context);
117 }
118
119 WebContextMenuProxyWin::~WebContextMenuProxyWin()
120 {
121     if (m_menu)
122         ::DestroyMenu(m_menu);
123 }
124
125 } // namespace WebKit
126 #endif // ENABLE(CONTEXT_MENUS)