1 | /* |
2 | * Copyright (C) 2012 Igalia S.L. |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Library General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2 of the License, or (at your option) any later version. |
8 | * |
9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Library General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Library General Public License |
15 | * along with this library; see the file COPYING.LIB. If not, write to |
16 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 | * Boston, MA 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "config.h" |
21 | #include "WebKitContextMenu.h" |
22 | |
23 | #include "APIArray.h" |
24 | #include "WebContextMenuItem.h" |
25 | #include "WebKitContextMenuItemPrivate.h" |
26 | #include "WebKitContextMenuPrivate.h" |
27 | #include <wtf/glib/GRefPtr.h> |
28 | #include <wtf/glib/WTFGType.h> |
29 | |
30 | using namespace WebKit; |
31 | using namespace WebCore; |
32 | |
33 | /** |
34 | * SECTION: WebKitContextMenu |
35 | * @Short_description: Represents the context menu in a #WebKitWebView |
36 | * @Title: WebKitContextMenu |
37 | * |
38 | * #WebKitContextMenu represents a context menu containing |
39 | * #WebKitContextMenuItem<!-- -->s in a #WebKitWebView. |
40 | * |
41 | * When a #WebKitWebView is about to display the context menu, it |
42 | * emits the #WebKitWebView::context-menu signal, which has the |
43 | * #WebKitContextMenu as an argument. You can modify it, adding new |
44 | * submenus that you can create with webkit_context_menu_new(), adding |
45 | * new #WebKitContextMenuItem<!-- -->s with |
46 | * webkit_context_menu_prepend(), webkit_context_menu_append() or |
47 | * webkit_context_menu_insert(), maybe after having removed the |
48 | * existing ones with webkit_context_menu_remove_all(). |
49 | * |
50 | */ |
51 | |
52 | struct { |
53 | GList* ; |
54 | WebKitContextMenuItem* ; |
55 | GRefPtr<GVariant> ; |
56 | }; |
57 | |
58 | WEBKIT_DEFINE_TYPE(WebKitContextMenu, webkit_context_menu, G_TYPE_OBJECT) |
59 | |
60 | static void (GObject* object) |
61 | { |
62 | webkit_context_menu_remove_all(WEBKIT_CONTEXT_MENU(object)); |
63 | G_OBJECT_CLASS(webkit_context_menu_parent_class)->dispose(object); |
64 | } |
65 | |
66 | static void (WebKitContextMenuClass* listClass) |
67 | { |
68 | GObjectClass* gObjectClass = G_OBJECT_CLASS(listClass); |
69 | gObjectClass->dispose = webkitContextMenuDispose; |
70 | } |
71 | |
72 | void (WebKitContextMenu* , Vector<WebContextMenuItemData>& ) |
73 | { |
74 | for (GList* item = menu->priv->items; item; item = g_list_next(item)) { |
75 | WebKitContextMenuItem* = WEBKIT_CONTEXT_MENU_ITEM(item->data); |
76 | contextMenuItems.append(webkitContextMenuItemToWebContextMenuItemData(menuItem)); |
77 | } |
78 | } |
79 | |
80 | void (WebKitContextMenu* , Vector<WebContextMenuItemGlib>& ) |
81 | { |
82 | for (GList* item = menu->priv->items; item; item = g_list_next(item)) { |
83 | WebKitContextMenuItem* = WEBKIT_CONTEXT_MENU_ITEM(item->data); |
84 | contextMenuItems.append(webkitContextMenuItemToWebContextMenuItemGlib(menuItem)); |
85 | } |
86 | } |
87 | |
88 | WebKitContextMenu* (const Vector<WebContextMenuItemData>& items) |
89 | { |
90 | WebKitContextMenu* = webkit_context_menu_new(); |
91 | for (const auto& item : items) |
92 | webkit_context_menu_prepend(menu, webkitContextMenuItemCreate(item)); |
93 | menu->priv->items = g_list_reverse(menu->priv->items); |
94 | |
95 | return menu; |
96 | } |
97 | |
98 | void (WebKitContextMenu* , WebKitContextMenuItem* item) |
99 | { |
100 | menu->priv->parentItem = item; |
101 | } |
102 | |
103 | WebKitContextMenuItem* (WebKitContextMenu* ) |
104 | { |
105 | return menu->priv->parentItem; |
106 | } |
107 | |
108 | /** |
109 | * webkit_context_menu_new: |
110 | * |
111 | * Creates a new #WebKitContextMenu object to be used as a submenu of an existing |
112 | * #WebKitContextMenu. The context menu of a #WebKitWebView is created by the view |
113 | * and passed as an argument of #WebKitWebView::context-menu signal. |
114 | * To add items to the menu use webkit_context_menu_prepend(), |
115 | * webkit_context_menu_append() or webkit_context_menu_insert(). |
116 | * See also webkit_context_menu_new_with_items() to create a #WebKitContextMenu with |
117 | * a list of initial items. |
118 | * |
119 | * Returns: The newly created #WebKitContextMenu object |
120 | */ |
121 | WebKitContextMenu* () |
122 | { |
123 | return WEBKIT_CONTEXT_MENU(g_object_new(WEBKIT_TYPE_CONTEXT_MENU, NULL)); |
124 | } |
125 | |
126 | /** |
127 | * webkit_context_menu_new_with_items: |
128 | * @items: (element-type WebKitContextMenuItem): a #GList of #WebKitContextMenuItem |
129 | * |
130 | * Creates a new #WebKitContextMenu object to be used as a submenu of an existing |
131 | * #WebKitContextMenu with the given initial items. |
132 | * See also webkit_context_menu_new() |
133 | * |
134 | * Returns: The newly created #WebKitContextMenu object |
135 | */ |
136 | WebKitContextMenu* (GList* items) |
137 | { |
138 | WebKitContextMenu* = webkit_context_menu_new(); |
139 | g_list_foreach(items, reinterpret_cast<GFunc>(reinterpret_cast<GCallback>(g_object_ref_sink)), 0); |
140 | menu->priv->items = g_list_copy(items); |
141 | |
142 | return menu; |
143 | } |
144 | |
145 | /** |
146 | * webkit_context_menu_prepend: |
147 | * @menu: a #WebKitContextMenu |
148 | * @item: the #WebKitContextMenuItem to add |
149 | * |
150 | * Adds @item at the beginning of the @menu. |
151 | */ |
152 | void (WebKitContextMenu* , WebKitContextMenuItem* item) |
153 | { |
154 | webkit_context_menu_insert(menu, item, 0); |
155 | } |
156 | |
157 | /** |
158 | * webkit_context_menu_append: |
159 | * @menu: a #WebKitContextMenu |
160 | * @item: the #WebKitContextMenuItem to add |
161 | * |
162 | * Adds @item at the end of the @menu. |
163 | */ |
164 | void (WebKitContextMenu* , WebKitContextMenuItem* item) |
165 | { |
166 | webkit_context_menu_insert(menu, item, -1); |
167 | } |
168 | |
169 | /** |
170 | * webkit_context_menu_insert: |
171 | * @menu: a #WebKitContextMenu |
172 | * @item: the #WebKitContextMenuItem to add |
173 | * @position: the position to insert the item |
174 | * |
175 | * Inserts @item into the @menu at the given position. |
176 | * If @position is negative, or is larger than the number of items |
177 | * in the #WebKitContextMenu, the item is added on to the end of |
178 | * the @menu. The first position is 0. |
179 | */ |
180 | void (WebKitContextMenu* , WebKitContextMenuItem* item, int position) |
181 | { |
182 | g_return_if_fail(WEBKIT_IS_CONTEXT_MENU(menu)); |
183 | g_return_if_fail(WEBKIT_IS_CONTEXT_MENU_ITEM(item)); |
184 | |
185 | g_object_ref_sink(item); |
186 | menu->priv->items = g_list_insert(menu->priv->items, item, position); |
187 | } |
188 | |
189 | /** |
190 | * webkit_context_menu_move_item: |
191 | * @menu: a #WebKitContextMenu |
192 | * @item: the #WebKitContextMenuItem to add |
193 | * @position: the new position to move the item |
194 | * |
195 | * Moves @item to the given position in the @menu. |
196 | * If @position is negative, or is larger than the number of items |
197 | * in the #WebKitContextMenu, the item is added on to the end of |
198 | * the @menu. |
199 | * The first position is 0. |
200 | */ |
201 | void (WebKitContextMenu* , WebKitContextMenuItem* item, int position) |
202 | { |
203 | g_return_if_fail(WEBKIT_IS_CONTEXT_MENU(menu)); |
204 | g_return_if_fail(WEBKIT_IS_CONTEXT_MENU_ITEM(item)); |
205 | |
206 | if (!g_list_find(menu->priv->items, item)) |
207 | return; |
208 | |
209 | menu->priv->items = g_list_remove(menu->priv->items, item); |
210 | menu->priv->items = g_list_insert(menu->priv->items, item, position); |
211 | } |
212 | |
213 | /** |
214 | * webkit_context_menu_get_items: |
215 | * @menu: a #WebKitContextMenu |
216 | * |
217 | * Returns the item list of @menu. |
218 | * |
219 | * Returns: (element-type WebKitContextMenuItem) (transfer none): a #GList of |
220 | * #WebKitContextMenuItem<!-- -->s |
221 | */ |
222 | GList* (WebKitContextMenu* ) |
223 | { |
224 | g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU(menu), 0); |
225 | |
226 | return menu->priv->items; |
227 | } |
228 | |
229 | /** |
230 | * webkit_context_menu_get_n_items: |
231 | * @menu: a #WebKitContextMenu |
232 | * |
233 | * Gets the length of the @menu. |
234 | * |
235 | * Returns: the number of #WebKitContextMenuItem<!-- -->s in @menu |
236 | */ |
237 | guint (WebKitContextMenu* ) |
238 | { |
239 | g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU(menu), 0); |
240 | |
241 | return g_list_length(menu->priv->items); |
242 | } |
243 | |
244 | /** |
245 | * webkit_context_menu_first: |
246 | * @menu: a #WebKitContextMenu |
247 | * |
248 | * Gets the first item in the @menu. |
249 | * |
250 | * Returns: (transfer none): the first #WebKitContextMenuItem of @menu, |
251 | * or %NULL if the #WebKitContextMenu is empty. |
252 | */ |
253 | WebKitContextMenuItem* (WebKitContextMenu* ) |
254 | { |
255 | g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU(menu), 0); |
256 | |
257 | return menu->priv->items ? WEBKIT_CONTEXT_MENU_ITEM(menu->priv->items->data) : 0; |
258 | } |
259 | |
260 | /** |
261 | * webkit_context_menu_last: |
262 | * @menu: a #WebKitContextMenu |
263 | * |
264 | * Gets the last item in the @menu. |
265 | * |
266 | * Returns: (transfer none): the last #WebKitContextMenuItem of @menu, |
267 | * or %NULL if the #WebKitContextMenu is empty. |
268 | */ |
269 | WebKitContextMenuItem* (WebKitContextMenu* ) |
270 | { |
271 | g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU(menu), 0); |
272 | |
273 | GList* last = g_list_last(menu->priv->items); |
274 | return last ? WEBKIT_CONTEXT_MENU_ITEM(last->data) : 0; |
275 | } |
276 | |
277 | /** |
278 | * webkit_context_menu_get_item_at_position: |
279 | * @menu: a #WebKitContextMenu |
280 | * @position: the position of the item, counting from 0 |
281 | * |
282 | * Gets the item at the given position in the @menu. |
283 | * |
284 | * Returns: (transfer none): the #WebKitContextMenuItem at position @position in @menu, |
285 | * or %NULL if the position is off the end of the @menu. |
286 | */ |
287 | WebKitContextMenuItem* (WebKitContextMenu* , unsigned position) |
288 | { |
289 | g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU(menu), 0); |
290 | |
291 | gpointer item = g_list_nth_data(menu->priv->items, position); |
292 | return item ? WEBKIT_CONTEXT_MENU_ITEM(item) : 0; |
293 | } |
294 | |
295 | /** |
296 | * webkit_context_menu_remove: |
297 | * @menu: a #WebKitContextMenu |
298 | * @item: the #WebKitContextMenuItem to remove |
299 | * |
300 | * Removes @item from the @menu. |
301 | * See also webkit_context_menu_remove_all() to remove all items. |
302 | */ |
303 | void (WebKitContextMenu* , WebKitContextMenuItem* item) |
304 | { |
305 | g_return_if_fail(WEBKIT_IS_CONTEXT_MENU(menu)); |
306 | g_return_if_fail(WEBKIT_IS_CONTEXT_MENU_ITEM(item)); |
307 | |
308 | if (!g_list_find(menu->priv->items, item)) |
309 | return; |
310 | |
311 | menu->priv->items = g_list_remove(menu->priv->items, item); |
312 | g_object_unref(item); |
313 | } |
314 | |
315 | /** |
316 | * webkit_context_menu_remove_all: |
317 | * @menu: a #WebKitContextMenu |
318 | * |
319 | * Removes all items of the @menu. |
320 | */ |
321 | void (WebKitContextMenu* ) |
322 | { |
323 | g_return_if_fail(WEBKIT_IS_CONTEXT_MENU(menu)); |
324 | |
325 | g_list_free_full(menu->priv->items, reinterpret_cast<GDestroyNotify>(g_object_unref)); |
326 | menu->priv->items = 0; |
327 | } |
328 | |
329 | /** |
330 | * webkit_context_menu_set_user_data: |
331 | * @menu: a #WebKitContextMenu |
332 | * @user_data: a #GVariant |
333 | * |
334 | * Sets user data to @menu. |
335 | * This function can be used from a Web Process extension to set user data |
336 | * that can be retrieved from the UI Process using webkit_context_menu_get_user_data(). |
337 | * If the @user_data #GVariant is floating, it is consumed. |
338 | * |
339 | * Since: 2.8 |
340 | */ |
341 | void (WebKitContextMenu* , GVariant* userData) |
342 | { |
343 | g_return_if_fail(WEBKIT_IS_CONTEXT_MENU(menu)); |
344 | g_return_if_fail(userData); |
345 | |
346 | menu->priv->userData = userData; |
347 | } |
348 | |
349 | /** |
350 | * webkit_context_menu_get_user_data: |
351 | * @menu: a #WebKitContextMenu |
352 | * |
353 | * Gets the user data of @menu. |
354 | * This function can be used from the UI Process to get user data previously set |
355 | * from the Web Process with webkit_context_menu_set_user_data(). |
356 | * |
357 | * Returns: (transfer none): the user data of @menu, or %NULL if @menu doesn't have user data |
358 | * |
359 | * Since: 2.8 |
360 | */ |
361 | GVariant* (WebKitContextMenu* ) |
362 | { |
363 | g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU(menu), nullptr); |
364 | |
365 | return menu->priv->userData.get(); |
366 | } |
367 | |