Removed misplaced //fixme comment that doesn't belong there.
[WebKit-https.git] / WebKit / gtk / WebCoreSupport / ChromeClientGtk.cpp
1 /*
2  * Copyright (C) 2007 Holger Hans Peter Freyther
3  * Copyright (C) 2007, 2008 Christian Dywan <christian@imendio.com>
4  * Copyright (C) 2008 Nuanti Ltd.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21 #include "config.h"
22 #include "ChromeClientGtk.h"
23
24 #include "FileSystem.h"
25 #include "FileChooser.h"
26 #include "FloatRect.h"
27 #include "IntRect.h"
28 #include "PlatformString.h"
29 #include "CString.h"
30 #include "HitTestResult.h"
31 #include "KURL.h"
32 #include "webkitwebview.h"
33 #include "webkitprivate.h"
34 #include "NotImplemented.h"
35 #include "WindowFeatures.h"
36 #if ENABLE(DATABASE)
37 #include "DatabaseTracker.h"
38 #endif
39
40 #include <glib.h>
41 #include <glib/gi18n.h>
42 #include <gtk/gtk.h>
43
44 using namespace WebCore;
45
46 namespace WebKit {
47
48 ChromeClient::ChromeClient(WebKitWebView* webView)
49     : m_webView(webView)
50 {
51 }
52
53 void ChromeClient::chromeDestroyed()
54 {
55     delete this;
56 }
57
58 FloatRect ChromeClient::windowRect()
59 {
60     if (!m_webView)
61         return FloatRect();
62     GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(m_webView));
63     if (window) {
64         gint left, top, width, height;
65         gtk_window_get_position(GTK_WINDOW(window), &left, &top);
66         gtk_window_get_size(GTK_WINDOW(window), &width, &height);
67         return IntRect(left, top, width, height);
68     }
69     return FloatRect();
70 }
71
72 void ChromeClient::setWindowRect(const FloatRect& r)
73 {
74     notImplemented();
75 }
76
77 FloatRect ChromeClient::pageRect()
78 {
79     if (!m_webView)
80         return FloatRect();
81     GtkAllocation allocation = GTK_WIDGET(m_webView)->allocation;
82     return IntRect(allocation.x, allocation.y, allocation.width, allocation.height);
83 }
84
85 float ChromeClient::scaleFactor()
86 {
87     // Not implementable
88     return 1.0;
89 }
90
91 void ChromeClient::focus()
92 {
93     if (!m_webView)
94         return;
95     gtk_widget_grab_focus(GTK_WIDGET(m_webView));
96 }
97
98 void ChromeClient::unfocus()
99 {
100     if (!m_webView)
101         return;
102     GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(m_webView));
103     if (window)
104         gtk_window_set_focus(GTK_WINDOW(window), NULL);
105 }
106
107 Page* ChromeClient::createWindow(Frame*, const FrameLoadRequest&, const WindowFeatures& features)
108 {
109     if (features.dialog) {
110         notImplemented();
111         return 0;
112     } else {
113         /* TODO: FrameLoadRequest is not used */
114         WebKitWebView* webView = WEBKIT_WEB_VIEW_GET_CLASS(m_webView)->create_web_view(m_webView);
115         if (!webView)
116             return 0;
117
118         WebKitWebViewPrivate* privateData = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
119         return privateData->corePage;
120     }
121 }
122
123 void ChromeClient::show()
124 {
125     notImplemented();
126 }
127
128 bool ChromeClient::canRunModal()
129 {
130     notImplemented();
131     return false;
132 }
133
134 void ChromeClient::runModal()
135 {
136     notImplemented();
137 }
138
139 void ChromeClient::setToolbarsVisible(bool)
140 {
141     notImplemented();
142 }
143
144 bool ChromeClient::toolbarsVisible()
145 {
146     notImplemented();
147     return false;
148 }
149
150 void ChromeClient::setStatusbarVisible(bool)
151 {
152     notImplemented();
153 }
154
155 bool ChromeClient::statusbarVisible()
156 {
157     notImplemented();
158     return false;
159 }
160
161 void ChromeClient::setScrollbarsVisible(bool)
162 {
163     notImplemented();
164 }
165
166 bool ChromeClient::scrollbarsVisible() {
167     notImplemented();
168     return false;
169 }
170
171 void ChromeClient::setMenubarVisible(bool)
172 {
173     notImplemented();
174 }
175
176 bool ChromeClient::menubarVisible()
177 {
178     notImplemented();
179     return false;
180 }
181
182 void ChromeClient::setResizable(bool)
183 {
184     notImplemented();
185 }
186
187 void ChromeClient::closeWindowSoon()
188 {
189     notImplemented();
190 }
191
192 bool ChromeClient::canTakeFocus(FocusDirection)
193 {
194     if (!m_webView)
195         return false;
196     return GTK_WIDGET_CAN_FOCUS(m_webView);
197 }
198
199 void ChromeClient::takeFocus(FocusDirection)
200 {
201     unfocus();
202 }
203
204 bool ChromeClient::canRunBeforeUnloadConfirmPanel()
205 {
206     return true;
207 }
208
209 bool ChromeClient::runBeforeUnloadConfirmPanel(const WebCore::String& message, WebCore::Frame* frame)
210 {
211     return runJavaScriptConfirm(frame, message);
212 }
213
214 void ChromeClient::addMessageToConsole(const WebCore::String& message, unsigned int lineNumber, const WebCore::String& sourceId)
215 {
216     gboolean retval;
217     g_signal_emit_by_name(m_webView, "console-message", message.utf8().data(), lineNumber, sourceId.utf8().data(), &retval);
218 }
219
220 void ChromeClient::runJavaScriptAlert(Frame* frame, const String& message)
221 {
222     gboolean retval;
223     g_signal_emit_by_name(m_webView, "script-alert", kit(frame), message.utf8().data(), &retval);
224 }
225
226 bool ChromeClient::runJavaScriptConfirm(Frame* frame, const String& message)
227 {
228     gboolean retval;
229     gboolean didConfirm;
230     g_signal_emit_by_name(m_webView, "script-confirm", kit(frame), message.utf8().data(), &didConfirm, &retval);
231     return didConfirm == TRUE;
232 }
233
234 bool ChromeClient::runJavaScriptPrompt(Frame* frame, const String& message, const String& defaultValue, String& result)
235 {
236     gboolean retval;
237     gchar* value = 0;
238     g_signal_emit_by_name(m_webView, "script-prompt", kit(frame), message.utf8().data(), defaultValue.utf8().data(), &value, &retval);
239     if (value) {
240         result = String::fromUTF8(value);
241         g_free(value);
242         return true;
243     }
244     return false;
245 }
246
247 void ChromeClient::setStatusbarText(const String& string)
248 {
249     CString stringMessage = string.utf8();
250     g_signal_emit_by_name(m_webView, "status-bar-text-changed", stringMessage.data());
251 }
252
253 bool ChromeClient::shouldInterruptJavaScript()
254 {
255     notImplemented();
256     return false;
257 }
258
259 bool ChromeClient::tabsToLinks() const
260 {
261     return true;
262 }
263
264 IntRect ChromeClient::windowResizerRect() const
265 {
266     notImplemented();
267     return IntRect();
268 }
269
270 void ChromeClient::repaint(const IntRect& windowRect, bool contentChanged, bool immediate, bool repaintContentOnly)
271 {
272     if (!m_webView)
273         return;
274
275     GdkRectangle rect = windowRect;
276     GdkWindow* window = GTK_WIDGET(m_webView)->window;
277
278     if (window) {
279         if (contentChanged)
280             gdk_window_invalidate_rect(window, &rect, FALSE);
281         // We don't currently do immediate updates since they delay other UI elements.
282         //if (immediate)
283         //    gdk_window_process_updates(window, FALSE);
284     }
285 }
286
287 void ChromeClient::scroll(const IntSize& delta, const IntRect& rectToScroll, const IntRect& clipRect)
288 {
289     if (!m_webView)
290         return;
291
292     GdkWindow* window = GTK_WIDGET(m_webView)->window;
293     if (!window)
294         return;
295
296     GdkRectangle area = clipRect;
297     GdkRectangle moveRect;
298
299     GdkRectangle sourceRect = area;
300     sourceRect.x -= delta.width();
301     sourceRect.y -= delta.height();
302
303     GdkRegion* invalidRegion = gdk_region_rectangle(&area);
304
305     if (gdk_rectangle_intersect(&area, &sourceRect, &moveRect)) {
306         GdkRegion* moveRegion = gdk_region_rectangle(&moveRect);
307         gdk_window_move_region(window, moveRegion, delta.width(), delta.height());
308         gdk_region_offset(moveRegion, delta.width(), delta.height());
309         gdk_region_subtract(invalidRegion, moveRegion);
310         gdk_region_destroy(moveRegion);
311     }
312
313     gdk_window_invalidate_region(window, invalidRegion, FALSE);
314     gdk_region_destroy(invalidRegion);
315 }
316
317 IntRect ChromeClient::windowToScreen(const IntRect& rect) const
318 {
319     notImplemented();
320     return rect;
321 }
322
323 IntPoint ChromeClient::screenToWindow(const IntPoint& point) const
324 {
325     notImplemented();
326     return point;
327 }
328
329 PlatformWidget ChromeClient::platformWindow() const
330 {
331     return m_webView ? GTK_WIDGET(m_webView) : 0;
332 }
333
334 void ChromeClient::mouseDidMoveOverElement(const HitTestResult& hit, unsigned modifierFlags)
335 {
336     // check if the element is a link...
337     bool isLink = hit.isLiveLink();
338     if (isLink) {
339         KURL url = hit.absoluteLinkURL();
340         if (!url.isEmpty() && url != m_hoveredLinkURL) {
341             CString titleString = hit.title().utf8();
342             CString urlString = url.prettyURL().utf8();
343             g_signal_emit_by_name(m_webView, "hovering-over-link", titleString.data(), urlString.data());
344             m_hoveredLinkURL = url;
345         }
346     } else if (!isLink && !m_hoveredLinkURL.isEmpty()) {
347         g_signal_emit_by_name(m_webView, "hovering-over-link", 0, 0);
348         m_hoveredLinkURL = KURL();
349     }
350 }
351
352 void ChromeClient::setToolTip(const String& toolTip)
353 {
354 #if GTK_CHECK_VERSION(2,12,0)
355     if (toolTip.isEmpty())
356         g_object_set(G_OBJECT(m_webView), "has-tooltip", FALSE, NULL);
357     else
358         gtk_widget_set_tooltip_text(GTK_WIDGET(m_webView), toolTip.utf8().data());
359 #else
360     // TODO: Support older GTK+ versions
361     // See http://bugs.webkit.org/show_bug.cgi?id=15793
362     notImplemented();
363 #endif
364 }
365
366 void ChromeClient::print(Frame* frame)
367 {
368     webkit_web_frame_print(kit(frame));
369 }
370
371 void ChromeClient::exceededDatabaseQuota(Frame* frame, const String&)
372 {
373 #if ENABLE(DATABASE)
374     // Set to 5M for testing
375     // FIXME: Make this configurable
376     notImplemented();
377     const unsigned long long defaultQuota = 5 * 1024 * 1024;
378     DatabaseTracker::tracker().setQuota(frame->document()->securityOrigin(), defaultQuota);
379 #endif
380 }
381
382 void ChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChooser)
383 {
384     // FIXME: Support multiple files.
385
386     RefPtr<FileChooser> fileChooser = prpFileChooser;
387
388     GtkWidget* dialog = gtk_file_chooser_dialog_new(_("Upload File"),
389                                                     GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(platformWindow()))),
390                                                     GTK_FILE_CHOOSER_ACTION_OPEN,
391                                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
392                                                     GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
393                                                     NULL);
394
395     if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
396         gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
397         if (filename)
398             fileChooser->chooseFile(filenameToString(filename));
399         g_free(filename);
400     }
401     gtk_widget_destroy(dialog);
402 }
403
404 }