2 * webview.c - webkit webview widget
4 * Copyright (C) 2010 Mason Larobina <mason.larobina@gmail.com>
5 * Copyright (C) 2007-2009 Julien Danjou <julien@danjou.info>
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "widgets/common.h"
24 #include <JavaScriptCore/JavaScript.h>
25 #include <webkit/webkit.h>
26 #include <libsoup/soup.h>
31 SoupCookieJar
*cookiejar
;
32 } Soup
= { NULL
, NULL
};
34 typedef enum { BOOL
, CHAR
, INT
, FLOAT
, DOUBLE
, URI
} property_value_type
;
35 typedef enum { SETTINGS
, WEBKITVIEW
, SOUPSESSION
} property_value_scope
;
43 } property_tmp_values
;
47 property_value_type type
;
48 property_value_scope scope
;
51 { "accept-language", CHAR
, SOUPSESSION
, TRUE
},
52 { "accept-language-auto", BOOL
, SOUPSESSION
, TRUE
},
53 { "auto-load-images", BOOL
, SETTINGS
, TRUE
},
54 { "auto-resize-window", BOOL
, SETTINGS
, TRUE
},
55 { "auto-shrink-images", BOOL
, SETTINGS
, TRUE
},
56 { "cursive-font-family", CHAR
, SETTINGS
, TRUE
},
57 { "custom-encoding", CHAR
, WEBKITVIEW
, TRUE
},
58 { "default-encoding", CHAR
, SETTINGS
, TRUE
},
59 { "default-font-family", CHAR
, SETTINGS
, TRUE
},
60 { "default-font-size", INT
, SETTINGS
, TRUE
},
61 { "default-monospace-font-size", INT
, SETTINGS
, TRUE
},
62 { "editable", BOOL
, WEBKITVIEW
, TRUE
},
63 { "enable-caret-browsing", BOOL
, SETTINGS
, TRUE
},
64 { "enable-default-context-menu", BOOL
, SETTINGS
, TRUE
},
65 { "enable-developer-extras", BOOL
, SETTINGS
, TRUE
},
66 { "enable-dom-paste", BOOL
, SETTINGS
, TRUE
},
67 { "enable-file-access-from-file-uris", BOOL
, SETTINGS
, TRUE
},
68 { "enable-html5-database", BOOL
, SETTINGS
, TRUE
},
69 { "enable-html5-local-storage", BOOL
, SETTINGS
, TRUE
},
70 { "enable-java-applet", BOOL
, SETTINGS
, TRUE
},
71 { "enable-offline-web-application-cache", BOOL
, SETTINGS
, TRUE
},
72 { "enable-page-cache", BOOL
, SETTINGS
, TRUE
},
73 { "enable-plugins", BOOL
, SETTINGS
, TRUE
},
74 { "enable-private-browsing", BOOL
, SETTINGS
, TRUE
},
75 { "enable-scripts", BOOL
, SETTINGS
, TRUE
},
76 { "enable-site-specific-quirks", BOOL
, SETTINGS
, TRUE
},
77 { "enable-spatial-navigation", BOOL
, SETTINGS
, TRUE
},
78 { "enable-spell-checking", BOOL
, SETTINGS
, TRUE
},
79 { "enable-universal-access-from-file-uris", BOOL
, SETTINGS
, TRUE
},
80 { "enable-xss-auditor", BOOL
, SETTINGS
, TRUE
},
81 { "encoding", CHAR
, WEBKITVIEW
, FALSE
},
82 { "enforce-96-dpi", BOOL
, SETTINGS
, TRUE
},
83 { "fantasy-font-family", CHAR
, SETTINGS
, TRUE
},
84 { "full-content-zoom", BOOL
, WEBKITVIEW
, TRUE
},
85 { "idle-timeout", INT
, SOUPSESSION
, TRUE
},
86 { "icon-uri", CHAR
, WEBKITVIEW
, FALSE
},
87 { "javascript-can-access-clipboard", BOOL
, SETTINGS
, TRUE
},
88 { "javascript-can-open-windows-automatically", BOOL
, SETTINGS
, TRUE
},
89 { "max-conns", INT
, SOUPSESSION
, TRUE
},
90 { "max-conns-per-host", INT
, SOUPSESSION
, TRUE
},
91 { "minimum-font-size", INT
, SETTINGS
, TRUE
},
92 { "minimum-logical-font-size", INT
, SETTINGS
, TRUE
},
93 { "monospace-font-family", CHAR
, SETTINGS
, TRUE
},
94 { "print-backgrounds", BOOL
, SETTINGS
, TRUE
},
95 { "progress", DOUBLE
, WEBKITVIEW
, FALSE
},
96 { "proxy-uri", URI
, SOUPSESSION
, TRUE
},
97 { "resizable-text-areas", BOOL
, SETTINGS
, TRUE
},
98 { "sans-serif-font-family", CHAR
, SETTINGS
, TRUE
},
99 { "serif-font-family", CHAR
, SETTINGS
, TRUE
},
100 { "spell-checking-languages", CHAR
, SETTINGS
, TRUE
},
101 { "ssl-ca-file", CHAR
, SOUPSESSION
, TRUE
},
102 { "ssl-strict", BOOL
, SOUPSESSION
, TRUE
},
103 { "tab-key-cycles-through-elements", BOOL
, SETTINGS
, TRUE
},
104 { "timeout", INT
, SOUPSESSION
, TRUE
},
105 { "title", CHAR
, WEBKITVIEW
, FALSE
},
106 { "transparent", BOOL
, WEBKITVIEW
, TRUE
},
107 { "use-ntlm", BOOL
, SOUPSESSION
, TRUE
},
108 { "user-agent", CHAR
, SETTINGS
, TRUE
},
109 { "user-stylesheet-uri", CHAR
, SETTINGS
, TRUE
},
110 { "zoom-level", FLOAT
, WEBKITVIEW
, TRUE
},
111 { "zoom-step", FLOAT
, SETTINGS
, TRUE
},
115 static const struct {
116 WebKitLoadStatus atom
;
118 } load_status_names
[] = {
119 { WEBKIT_LOAD_PROVISIONAL
, "provisional" },
120 { WEBKIT_LOAD_COMMITTED
, "committed", },
121 { WEBKIT_LOAD_FINISHED
, "finished" },
122 { WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT
, "first-visual" },
123 { WEBKIT_LOAD_FAILED
, "failed" },
128 webview_eval_js(WebKitWebView
*view
, const gchar
*script
, const gchar
*file
) {
129 WebKitWebFrame
*frame
;
130 JSGlobalContextRef context
;
131 JSObjectRef globalobject
;
133 JSStringRef js_script
;
134 JSValueRef js_result
;
135 JSValueRef js_exc
= NULL
;
136 JSStringRef js_result_string
;
137 GString
*result
= g_string_new(NULL
);
138 size_t js_result_size
;
140 frame
= webkit_web_view_get_main_frame(WEBKIT_WEB_VIEW(view
));
141 context
= webkit_web_frame_get_global_context(frame
);
142 globalobject
= JSContextGetGlobalObject(context
);
144 /* evaluate the script and get return value*/
145 js_script
= JSStringCreateWithUTF8CString(script
);
146 js_file
= JSStringCreateWithUTF8CString(file
);
147 js_result
= JSEvaluateScript(context
, js_script
, globalobject
, js_file
, 0, &js_exc
);
148 if (js_result
&& !JSValueIsUndefined(context
, js_result
)) {
149 js_result_string
= JSValueToStringCopy(context
, js_result
, NULL
);
150 js_result_size
= JSStringGetMaximumUTF8CStringSize(js_result_string
);
152 if (js_result_size
) {
153 char js_result_utf8
[js_result_size
];
154 JSStringGetUTF8CString(js_result_string
, js_result_utf8
, js_result_size
);
155 g_string_assign(result
, js_result_utf8
);
158 JSStringRelease(js_result_string
);
162 JSStringRef prop
, val
;
163 JSObjectRef exc
= JSValueToObject(context
, js_exc
, NULL
);
165 printf("Exception occured while executing script:\n");
168 prop
= JSStringCreateWithUTF8CString("sourceURL");
169 val
= JSValueToStringCopy(context
, JSObjectGetProperty(context
, exc
, prop
, NULL
), NULL
);
170 size
= JSStringGetMaximumUTF8CStringSize(val
);
173 JSStringGetUTF8CString(val
, cstr
, size
);
174 printf("At %s", cstr
);
176 JSStringRelease(prop
);
177 JSStringRelease(val
);
180 prop
= JSStringCreateWithUTF8CString("line");
181 val
= JSValueToStringCopy(context
, JSObjectGetProperty(context
, exc
, prop
, NULL
), NULL
);
182 size
= JSStringGetMaximumUTF8CStringSize(val
);
185 JSStringGetUTF8CString(val
, cstr
, size
);
186 printf(":%s: ", cstr
);
188 JSStringRelease(prop
);
189 JSStringRelease(val
);
192 val
= JSValueToStringCopy(context
, exc
, NULL
);
193 size
= JSStringGetMaximumUTF8CStringSize(val
);
196 JSStringGetUTF8CString(val
, cstr
, size
);
197 printf("%s\n", cstr
);
199 JSStringRelease(val
);
203 JSStringRelease(js_script
);
204 JSStringRelease(js_file
);
206 return g_string_free(result
, FALSE
);
210 luaH_webview_eval_js(lua_State
*L
)
212 widget_t
*w
= luaH_checkudata(L
, 1, &widget_class
);
213 WebKitWebView
*view
= WEBKIT_WEB_VIEW(g_object_get_data(G_OBJECT(w
->widget
), "webview"));
214 const gchar
*script
= luaL_checkstring(L
, 2);
215 const gchar
*filename
= luaL_checkstring(L
, 3);
217 /* evaluate javascript script and push return result onto lua stack */
218 const gchar
*result
= webview_eval_js(view
, script
, filename
);
219 lua_pushstring(L
, result
);
224 notify_progress_cb(WebKitWebView
*v
, GParamSpec
*s
, widget_t
*w
)
229 lua_State
*L
= globalconf
.L
;
230 luaH_object_push(L
, w
->ref
);
231 luaH_object_emit_signal(L
, -1, "property::progress", 0, 0);
236 title_changed_cb(WebKitWebView
*v
, WebKitWebFrame
*f
, const gchar
*title
, widget_t
*w
)
242 lua_State
*L
= globalconf
.L
;
243 luaH_object_push(L
, w
->ref
);
244 luaH_object_emit_signal(L
, -1, "title-changed", 0, 0);
249 update_uri(GtkWidget
*view
, const gchar
*uri
, widget_t
*w
)
251 /* return if uri has not changed */
252 if (!g_strcmp0(uri
, g_object_get_data(G_OBJECT(view
), "uri")))
255 g_object_set_data_full(G_OBJECT(view
), "uri", g_strdup(uri
), g_free
);
256 lua_State
*L
= globalconf
.L
;
257 luaH_object_push(L
, w
->ref
);
258 luaH_object_emit_signal(L
, -1, "property::uri", 0, 0);
263 notify_load_status_cb(WebKitWebView
*v
, GParamSpec
*s
, widget_t
*w
)
267 update_uri(GTK_WIDGET(v
), webkit_web_view_get_uri(v
), w
);
269 /* Get load status */
270 WebKitLoadStatus status
;
271 g_object_get(G_OBJECT(v
), "load-status", &status
, NULL
);
273 lua_State
*L
= globalconf
.L
;
274 luaH_object_push(L
, w
->ref
);
276 /* get status literal */
277 gboolean found
= FALSE
;
278 for (guint i
= 0; i
< LENGTH(load_status_names
); i
++) {
279 if (load_status_names
[i
].atom
!= status
) continue;
280 lua_pushstring(L
, load_status_names
[i
].name
);
285 lua_pushstring(L
, "unknown");
287 luaH_object_emit_signal(L
, -2, "load-status", 1, 0);
292 mime_type_decision_cb(WebKitWebView
*v
, WebKitWebFrame
*f
,
293 WebKitNetworkRequest
*r
, gchar
*mime
, WebKitWebPolicyDecision
*pd
,
298 lua_State
*L
= globalconf
.L
;
299 const gchar
*uri
= webkit_network_request_get_uri(r
);
302 luaH_object_push(L
, w
->ref
);
303 lua_pushstring(L
, uri
);
304 lua_pushstring(L
, mime
);
305 ret
= luaH_object_emit_signal(L
, -3, "mime-type-decision", 2, 1);
307 if (ret
&& !luaH_checkboolean(L
, -1))
308 /* User responded with false, ignore request */
309 webkit_web_policy_decision_ignore(pd
);
310 else if (!webkit_web_view_can_show_mime_type(v
, mime
))
311 webkit_web_policy_decision_download(pd
);
313 webkit_web_policy_decision_use(pd
);
320 download_request_cb(WebKitWebView
*v
, GObject
*dl
, widget_t
*w
)
323 const gchar
*uri
= webkit_download_get_uri((WebKitDownload
*) dl
);
324 const gchar
*filename
= webkit_download_get_suggested_filename((WebKitDownload
*) dl
);
326 lua_State
*L
= globalconf
.L
;
327 luaH_object_push(L
, w
->ref
);
328 lua_pushstring(L
, uri
);
329 lua_pushstring(L
, filename
);
330 luaH_object_emit_signal(L
, -3, "download-request", 2, 0);
337 link_hover_cb(WebKitWebView
*view
, const char *t
, const gchar
*link
, widget_t
*w
)
340 lua_State
*L
= globalconf
.L
;
341 GObject
*ws
= G_OBJECT(view
);
342 gchar
*last_hover
= g_object_get_data(ws
, "hovered-uri");
344 /* links are identical, do nothing */
345 if (last_hover
&& !g_strcmp0(last_hover
, link
))
348 luaH_object_push(L
, w
->ref
);
351 lua_pushstring(L
, last_hover
);
352 g_object_set_data(ws
, "hovered-uri", NULL
);
353 luaH_object_emit_signal(L
, -2, "link-unhover", 1, 0);
357 lua_pushstring(L
, link
);
358 g_object_set_data_full(ws
, "hovered-uri", g_strdup(link
), g_free
);
359 luaH_object_emit_signal(L
, -2, "link-hover", 1, 0);
362 luaH_object_emit_signal(L
, -1, "property::hovered_uri", 0, 0);
366 /* Raises the "navigation-request" signal on a webkit navigation policy
367 * decision request. The default action is to load the requested uri.
369 * The signal handler is able to:
370 * - return true for the handler execution to stop and the request to continue
371 * - return false for the handler execution to stop and the request to hault
372 * - do nothing and give the navigation decision to the next signal handler
374 * This signal is also where you would attach custom scheme handlers to take
375 * over the navigation request by launching an external application.
378 navigation_decision_cb(WebKitWebView
*v
, WebKitWebFrame
*f
,
379 WebKitNetworkRequest
*r
, WebKitWebNavigationAction
*a
,
380 WebKitWebPolicyDecision
*p
, widget_t
*w
)
386 lua_State
*L
= globalconf
.L
;
387 const gchar
*uri
= webkit_network_request_get_uri(r
);
390 luaH_object_push(L
, w
->ref
);
391 lua_pushstring(L
, uri
);
392 ret
= luaH_object_emit_signal(L
, -2, "navigation-request", 1, 1);
394 if (ret
&& !luaH_checkboolean(L
, -1))
395 /* User responded with false, do not continue navigation request */
396 webkit_web_policy_decision_ignore(p
);
398 webkit_web_policy_decision_use(p
);
405 push_adjustment_values(lua_State
*L
, GtkAdjustment
*adjustment
)
407 gdouble view_size
= gtk_adjustment_get_page_size(adjustment
);
408 gdouble value
= gtk_adjustment_get_value(adjustment
);
409 gdouble max
= gtk_adjustment_get_upper(adjustment
) - view_size
;
410 lua_pushnumber(L
, value
);
411 lua_pushnumber(L
, (max
< 0 ? 0 : max
));
412 lua_pushnumber(L
, view_size
);
417 luaH_webview_get_vscroll(lua_State
*L
)
419 widget_t
*w
= luaH_checkudata(L
, 1, &widget_class
);
420 GtkAdjustment
*adjustment
= gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(w
->widget
));
421 return push_adjustment_values(L
, adjustment
);
425 luaH_webview_get_hscroll(lua_State
*L
)
427 widget_t
*w
= luaH_checkudata(L
, 1, &widget_class
);
428 GtkAdjustment
*adjustment
= gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(w
->widget
));
429 return push_adjustment_values(L
, adjustment
);
433 set_adjustment(GtkAdjustment
*adjustment
, gdouble
new)
435 gdouble view_size
= gtk_adjustment_get_page_size(adjustment
);
436 gdouble max
= gtk_adjustment_get_upper(adjustment
) - view_size
;
437 gtk_adjustment_set_value(adjustment
, ((new < 0 ? 0 : new) > max
? max
: new));
441 luaH_webview_set_scroll_vert(lua_State
*L
)
443 widget_t
*w
= luaH_checkudata(L
, 1, &widget_class
);
444 gdouble value
= (gdouble
) luaL_checknumber(L
, 2);
445 GtkAdjustment
*adjustment
= gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(w
->widget
));
446 set_adjustment(adjustment
, value
);
451 luaH_webview_set_scroll_horiz(lua_State
*L
)
453 widget_t
*w
= luaH_checkudata(L
, 1, &widget_class
);
454 gdouble value
= (gdouble
) luaL_checknumber(L
, 2);
455 GtkAdjustment
*adjustment
= gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(w
->widget
));
456 set_adjustment(adjustment
, value
);
461 luaH_webview_go_back(lua_State
*L
)
463 widget_t
*w
= luaH_checkudata(L
, 1, &widget_class
);
464 gint steps
= (gint
) luaL_checknumber(L
, 2);
465 GtkWidget
*view
= GTK_WIDGET(g_object_get_data(G_OBJECT(w
->widget
), "webview"));
466 webkit_web_view_go_back_or_forward(WEBKIT_WEB_VIEW(view
), steps
* -1);
471 luaH_webview_go_forward(lua_State
*L
)
473 widget_t
*w
= luaH_checkudata(L
, 1, &widget_class
);
474 gint steps
= (gint
) luaL_checknumber(L
, 2);
475 GtkWidget
*view
= GTK_WIDGET(g_object_get_data(G_OBJECT(w
->widget
), "webview"));
476 webkit_web_view_go_back_or_forward(WEBKIT_WEB_VIEW(view
), steps
);
481 luaH_webview_search(lua_State
*L
)
483 widget_t
*w
= luaH_checkudata(L
, 1, &widget_class
);
484 WebKitWebView
*view
= WEBKIT_WEB_VIEW(GTK_WIDGET(g_object_get_data(G_OBJECT(w
->widget
), "webview")));
485 const gchar
*text
= luaL_checkstring(L
, 2);
486 gboolean case_sensitive
= luaH_checkboolean(L
, 3);
487 gboolean forward
= luaH_checkboolean(L
, 4);
488 gboolean wrap
= luaH_checkboolean(L
, 5);
490 webkit_web_view_unmark_text_matches(view
);
491 webkit_web_view_search_text(view
, text
, case_sensitive
, forward
, wrap
);
492 webkit_web_view_mark_text_matches(view
, text
, case_sensitive
, 0);
493 webkit_web_view_set_highlight_text_matches(view
, TRUE
);
498 luaH_webview_clear_search(lua_State
*L
)
500 widget_t
*w
= luaH_checkudata(L
, 1, &widget_class
);
501 WebKitWebView
*view
= WEBKIT_WEB_VIEW(GTK_WIDGET(g_object_get_data(G_OBJECT(w
->widget
), "webview")));
502 webkit_web_view_unmark_text_matches(view
);
506 inline static GObject
*
507 get_settings_object(GtkWidget
*view
, property_value_scope scope
)
511 return G_OBJECT(webkit_web_view_get_settings(WEBKIT_WEB_VIEW(view
)));
513 return G_OBJECT(view
);
515 return G_OBJECT(Soup
.session
);
523 luaH_webview_get_prop(lua_State
*L
)
525 widget_t
*w
= luaH_checkudata(L
, 1, &widget_class
);
526 const gchar
*prop
= luaL_checkstring(L
, 2);
527 GtkWidget
*view
= GTK_WIDGET(g_object_get_data(G_OBJECT(w
->widget
), "webview"));
529 property_tmp_values tmp
;
532 for (guint i
= 0; i
< LENGTH(properties
); i
++) {
533 if (g_strcmp0(properties
[i
].name
, prop
))
536 ws
= get_settings_object(view
, properties
[i
].scope
);
538 switch(properties
[i
].type
) {
540 g_object_get(ws
, prop
, &tmp
.b
, NULL
);
541 lua_pushboolean(L
, tmp
.b
);
545 g_object_get(ws
, prop
, &tmp
.c
, NULL
);
546 lua_pushstring(L
, tmp
.c
);
551 g_object_get(ws
, prop
, &tmp
.i
, NULL
);
552 lua_pushnumber(L
, tmp
.i
);
556 g_object_get(ws
, prop
, &tmp
.f
, NULL
);
557 lua_pushnumber(L
, tmp
.f
);
561 g_object_get(ws
, prop
, &tmp
.d
, NULL
);
562 lua_pushnumber(L
, tmp
.d
);
566 g_object_get(ws
, prop
, &u
, NULL
);
567 tmp
.c
= soup_uri_to_string(u
, 0);
568 lua_pushstring(L
, tmp
.c
);
574 warn("unknown property type for: %s", properties
[i
].name
);
578 warn("unknown property: %s", prop
);
583 luaH_webview_set_prop(lua_State
*L
)
586 widget_t
*w
= luaH_checkudata(L
, 1, &widget_class
);
587 const gchar
*prop
= luaL_checklstring(L
, 2, &len
);
588 GtkWidget
*view
= g_object_get_data(G_OBJECT(w
->widget
), "webview");
590 property_tmp_values tmp
;
593 for (guint i
= 0; i
< LENGTH(properties
); i
++) {
594 if (g_strcmp0(properties
[i
].name
, prop
))
597 if (!properties
[i
].writable
) {
598 warn("attempt to set read-only property: %s", prop
);
602 ws
= get_settings_object(view
, properties
[i
].scope
);
604 switch(properties
[i
].type
) {
606 tmp
.b
= luaH_checkboolean(L
, 3);
607 g_object_set(ws
, prop
, tmp
.b
, NULL
);
611 tmp
.c
= (gchar
*) luaL_checklstring(L
, 3, &len
);
612 g_object_set(ws
, prop
, tmp
.c
, NULL
);
616 tmp
.i
= (gint
) luaL_checknumber(L
, 3);
617 g_object_set(ws
, prop
, tmp
.i
, NULL
);
621 tmp
.f
= (gfloat
) luaL_checknumber(L
, 3);
622 g_object_set(ws
, prop
, tmp
.f
, NULL
);
626 tmp
.d
= (gdouble
) luaL_checknumber(L
, 3);
627 g_object_set(ws
, prop
, tmp
.d
, NULL
);
631 tmp
.c
= (gchar
*) luaL_checkstring(L
, 3);
632 u
= soup_uri_new(tmp
.c
);
633 if (SOUP_URI_VALID_FOR_HTTP(u
))
634 g_object_set(ws
, prop
, u
, NULL
);
636 luaL_error(L
, "cannot parse uri: %s", tmp
.c
);
641 warn("unknown property type for: %s", properties
[i
].name
);
645 warn("unknown property: %s", prop
);
650 luaH_webview_loading(lua_State
*L
)
652 widget_t
*w
= luaH_checkudata(L
, 1, &widget_class
);
653 GtkWidget
*view
= g_object_get_data(G_OBJECT(w
->widget
), "webview");
655 g_object_get(G_OBJECT(view
), "load-status", &s
, NULL
);
657 case WEBKIT_LOAD_PROVISIONAL
:
658 case WEBKIT_LOAD_COMMITTED
:
659 case WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT
:
660 lua_pushboolean(L
, TRUE
);
664 lua_pushboolean(L
, FALSE
);
671 show_scrollbars(widget_t
*w
, gboolean show
)
673 GtkWidget
*view
= g_object_get_data(G_OBJECT(w
->widget
), "webview");
674 WebKitWebFrame
*mf
= webkit_web_view_get_main_frame(WEBKIT_WEB_VIEW(view
));
675 gulong id
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(view
), "hide_handler_id"));
679 g_signal_handler_disconnect((gpointer
) mf
, id
);
680 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(w
->widget
), GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
683 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(w
->widget
), GTK_POLICY_NEVER
, GTK_POLICY_NEVER
);
684 id
= g_signal_connect(G_OBJECT(mf
), "scrollbars-policy-changed", G_CALLBACK(true_cb
), NULL
);
686 g_object_set_data(G_OBJECT(view
), "hide_handler_id", GINT_TO_POINTER(id
));
690 luaH_webview_index(lua_State
*L
, luakit_token_t token
)
692 widget_t
*w
= luaH_checkudata(L
, 1, &widget_class
);
693 GtkWidget
*view
= g_object_get_data(G_OBJECT(w
->widget
), "webview");
698 lua_pushcfunction(L
, luaH_widget_destroy
);
701 case L_TK_GET_SCROLL_VERT
:
702 lua_pushcfunction(L
, luaH_webview_get_vscroll
);
705 case L_TK_GET_SCROLL_HORIZ
:
706 lua_pushcfunction(L
, luaH_webview_get_hscroll
);
709 case L_TK_SET_SCROLL_VERT
:
710 lua_pushcfunction(L
, luaH_webview_set_scroll_vert
);
713 case L_TK_SET_SCROLL_HORIZ
:
714 lua_pushcfunction(L
, luaH_webview_set_scroll_horiz
);
718 lua_pushcfunction(L
, luaH_webview_eval_js
);
722 lua_pushcfunction(L
, luaH_webview_search
);
725 case L_TK_CLEAR_SEARCH
:
726 lua_pushcfunction(L
, luaH_webview_clear_search
);
730 lua_pushcfunction(L
, luaH_webview_set_prop
);
734 lua_pushcfunction(L
, luaH_webview_get_prop
);
737 case L_TK_HOVERED_URI
:
738 lua_pushstring(L
, g_object_get_data(G_OBJECT(view
), "hovered-uri"));
742 lua_pushstring(L
, g_object_get_data(G_OBJECT(view
), "uri"));
746 lua_pushcfunction(L
, luaH_widget_show
);
750 lua_pushcfunction(L
, luaH_widget_hide
);
754 lua_pushcfunction(L
, luaH_widget_focus
);
758 lua_pushcfunction(L
, luaH_webview_loading
);
762 lua_pushcfunction(L
, luaH_webview_go_back
);
765 case L_TK_GO_FORWARD
:
766 lua_pushcfunction(L
, luaH_webview_go_forward
);
770 warn("unknown property: %s", luaL_checkstring(L
, 2));
777 /* The __newindex method for the webview object */
779 luaH_webview_newindex(lua_State
*L
, luakit_token_t token
)
782 widget_t
*w
= luaH_checkudata(L
, 1, &widget_class
);
783 GtkWidget
*view
= g_object_get_data(G_OBJECT(w
->widget
), "webview");
789 uri
= (gchar
*) luaL_checklstring(L
, 3, &len
);
790 if (g_strrstr(uri
, "://") || !g_strcmp0(uri
, "about:blank"))
793 uri
= g_strdup_printf("http://%s", uri
);
794 webkit_web_view_load_uri(WEBKIT_WEB_VIEW(view
), uri
);
795 g_object_set_data_full(G_OBJECT(view
), "uri", uri
, g_free
);
798 case L_TK_SHOW_SCROLLBARS
:
799 show_scrollbars(w
, luaH_checkboolean(L
, 3));
803 warn("unknown property: %s", luaL_checkstring(L
, 2));
807 return luaH_object_emit_property_signal(L
, 1);
811 expose_cb(GtkWidget
*widget
, GdkEventExpose
*e
, widget_t
*w
)
815 lua_State
*L
= globalconf
.L
;
816 luaH_object_push(L
, w
->ref
);
817 luaH_object_emit_signal(L
, -1, "expose", 0, 0);
823 wv_button_press_cb(GtkWidget
*view
, GdkEventButton
*event
, widget_t
*w
)
825 if((event
->type
!= GDK_BUTTON_PRESS
) || (event
->button
!= 1))
828 /* get webview hit context */
829 WebKitHitTestResult
*ht
= webkit_web_view_get_hit_test_result(WEBKIT_WEB_VIEW(view
), event
);
831 g_object_get(ht
, "context", &c
, NULL
);
832 gint context
= (gint
) c
;
834 lua_State
*L
= globalconf
.L
;
835 luaH_object_push(L
, w
->ref
);
836 /* raise "form-active" when a user clicks on a form field and raise
837 * "root-active" when a user clicks elsewhere */
838 if (context
& WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE
)
839 luaH_object_emit_signal(L
, -1, "form-active", 0, 0);
840 else if (context
& WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT
)
841 luaH_object_emit_signal(L
, -1, "root-active", 0, 0);
847 webview_destructor(widget_t
*w
)
849 GtkWidget
*view
= g_object_get_data(G_OBJECT(w
->widget
), "webview");
850 gtk_widget_destroy(GTK_WIDGET(view
));
851 gtk_widget_destroy(GTK_WIDGET(w
->widget
));
855 widget_webview(widget_t
*w
)
857 w
->index
= luaH_webview_index
;
858 w
->newindex
= luaH_webview_newindex
;
859 w
->destructor
= webview_destructor
;
861 /* init soup session & cookies handling */
863 Soup
.session
= webkit_get_default_session();
864 gchar
*cookie_file
= g_build_filename(globalconf
.data_dir
, "cookies.txt", NULL
);
865 Soup
.cookiejar
= soup_cookie_jar_text_new(cookie_file
, FALSE
);
866 soup_session_add_feature(Soup
.session
, (SoupSessionFeature
*) Soup
.cookiejar
);
870 GtkWidget
*view
= webkit_web_view_new();
871 w
->widget
= gtk_scrolled_window_new(NULL
, NULL
);
872 g_object_set_data(G_OBJECT(w
->widget
), "widget", w
);
873 g_object_set_data(G_OBJECT(w
->widget
), "webview", view
);
874 gtk_container_add(GTK_CONTAINER(w
->widget
), view
);
876 show_scrollbars(w
, TRUE
);
878 /* connect webview signals */
879 g_object_connect((GObject
*)view
,
880 "signal::button-press-event", (GCallback
)wv_button_press_cb
, w
,
881 "signal::download-requested", (GCallback
)download_request_cb
, w
,
882 "signal::expose-event", (GCallback
)expose_cb
, w
,
883 "signal::focus-in-event", (GCallback
)focus_cb
, w
,
884 "signal::focus-out-event", (GCallback
)focus_cb
, w
,
885 "signal::hovering-over-link", (GCallback
)link_hover_cb
, w
,
886 "signal::key-press-event", (GCallback
)key_press_cb
, w
,
887 "signal::mime-type-policy-decision-requested", (GCallback
)mime_type_decision_cb
, w
,
888 "signal::navigation-policy-decision-requested", (GCallback
)navigation_decision_cb
, w
,
889 "signal::notify::load-status", (GCallback
)notify_load_status_cb
, w
,
890 "signal::notify::progress", (GCallback
)notify_progress_cb
, w
,
891 "signal::parent-set", (GCallback
)parent_set_cb
, w
,
892 "signal::title-changed", (GCallback
)title_changed_cb
, w
,
896 gtk_widget_show(view
);
897 gtk_widget_show(w
->widget
);
902 // vim: ft=c:et:sw=4:ts=8:sts=4:tw=80