Browse Source

add support for getting lock hint from lightdm (for when greeter is started as a lock-screen)

sisyphus
Dustin Falgout 9 years ago
parent
commit
315a20d700
  1. 106
      src/lightdm-webkit2-greeter-ext.c
  2. 102
      src/lightdm-webkit2-greeter.c

106
src/lightdm-webkit2-greeter-ext.c

@ -35,8 +35,7 @@
#include <glib/gi18n.h>
#include <webkit2/webkit-web-extension.h>
#define WEBKIT_DOM_USE_UNSTABLE_API
#include <webkitdom/WebKitDOMDOMWindowUnstable.h>
#include <webkitdom/WebKitDOMCustom.h>
#include <JavaScriptCore/JavaScript.h>
#include <lightdm.h>
@ -53,6 +52,7 @@ static JSClassRef
lightdm_layout_class,
lightdm_session_class;
static JSValueRef
get_user_name_cb(JSContextRef context,
JSObjectRef thisObject,
@ -65,6 +65,7 @@ get_user_name_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_user_real_name_cb(JSContextRef context,
JSObjectRef thisObject,
@ -77,6 +78,7 @@ get_user_real_name_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_user_display_name_cb(JSContextRef context,
JSObjectRef thisObject,
@ -89,6 +91,7 @@ get_user_display_name_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_user_image_cb(JSContextRef context,
JSObjectRef thisObject,
@ -101,6 +104,7 @@ get_user_image_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_user_language_cb(JSContextRef context,
JSObjectRef thisObject,
@ -118,6 +122,7 @@ get_user_language_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_user_layout_cb(JSContextRef context,
JSObjectRef thisObject,
@ -135,6 +140,7 @@ get_user_layout_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_user_session_cb(JSContextRef context,
JSObjectRef thisObject,
@ -152,6 +158,7 @@ get_user_session_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_user_logged_in_cb(JSContextRef context,
JSObjectRef thisObject,
@ -161,6 +168,7 @@ get_user_logged_in_cb(JSContextRef context,
return JSValueMakeBoolean(context, lightdm_user_get_logged_in(user));
}
static JSValueRef
get_language_code_cb(JSContextRef context,
JSObjectRef thisObject,
@ -173,6 +181,7 @@ get_language_code_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_language_name_cb(JSContextRef context,
JSObjectRef thisObject,
@ -185,6 +194,7 @@ get_language_name_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_language_territory_cb(JSContextRef context,
JSObjectRef thisObject,
@ -197,6 +207,7 @@ get_language_territory_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_layout_name_cb(JSContextRef context,
JSObjectRef thisObject,
@ -209,6 +220,7 @@ get_layout_name_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_layout_short_description_cb(JSContextRef context,
JSObjectRef thisObject,
@ -221,6 +233,7 @@ get_layout_short_description_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_layout_description_cb(JSContextRef context,
JSObjectRef thisObject,
@ -233,6 +246,7 @@ get_layout_description_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_session_key_cb(JSContextRef context,
JSObjectRef thisObject,
@ -246,6 +260,7 @@ get_session_key_cb(JSContextRef context,
}
static JSValueRef
get_session_name_cb(JSContextRef context,
JSObjectRef thisObject,
@ -258,6 +273,7 @@ get_session_name_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_session_comment_cb(JSContextRef context,
JSObjectRef thisObject,
@ -270,6 +286,7 @@ get_session_comment_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_hostname_cb(JSContextRef context,
JSObjectRef thisObject,
@ -282,6 +299,7 @@ get_hostname_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_num_users_cb(JSContextRef context,
JSObjectRef thisObject,
@ -293,6 +311,7 @@ get_num_users_cb(JSContextRef context,
return JSValueMakeNumber(context, num_users);
}
static JSValueRef
get_users_cb(JSContextRef context,
JSObjectRef thisObject,
@ -317,6 +336,7 @@ get_users_cb(JSContextRef context,
return array;
}
static JSValueRef
get_languages_cb(JSContextRef context,
JSObjectRef thisObject,
@ -341,6 +361,7 @@ get_languages_cb(JSContextRef context,
return array;
}
static JSValueRef
get_default_language_cb(JSContextRef context,
JSObjectRef thisObject,
@ -353,6 +374,7 @@ get_default_language_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_default_layout_cb(JSContextRef context,
JSObjectRef thisObject,
@ -365,6 +387,7 @@ get_default_layout_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_layouts_cb(JSContextRef context,
JSObjectRef thisObject,
@ -390,6 +413,7 @@ get_layouts_cb(JSContextRef context,
return array;
}
static JSValueRef
get_layout_cb(JSContextRef context,
JSObjectRef thisObject,
@ -403,6 +427,7 @@ get_layout_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static bool
set_layout_cb(JSContextRef context,
JSObjectRef thisObject,
@ -426,6 +451,7 @@ set_layout_cb(JSContextRef context,
return true;
}
static JSValueRef
get_sessions_cb(JSContextRef context,
JSObjectRef thisObject,
@ -450,6 +476,7 @@ get_sessions_cb(JSContextRef context,
return array;
}
static JSValueRef
get_default_session_cb(JSContextRef context,
JSObjectRef thisObject,
@ -463,6 +490,7 @@ get_default_session_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_timed_login_user_cb(JSContextRef context,
JSObjectRef thisObject,
@ -476,6 +504,18 @@ get_timed_login_user_cb(JSContextRef context,
return JSValueMakeString(context, string);
}
static JSValueRef
get_lock_hint_cb(JSContextRef context,
JSObjectRef thisObject,
JSStringRef propertyName,
JSValueRef *exception) {
LightDMGreeter *greeter = JSObjectGetPrivate(thisObject);
return JSValueMakeBoolean(lightdm_greeter_get_lock_hint(greeter));
}
static JSValueRef
get_timed_login_delay_cb(JSContextRef context,
JSObjectRef thisObject,
@ -488,6 +528,7 @@ get_timed_login_delay_cb(JSContextRef context,
return JSValueMakeNumber(context, delay);
}
static JSValueRef
cancel_timed_login_cb(JSContextRef context,
JSObjectRef function,
@ -506,6 +547,7 @@ cancel_timed_login_cb(JSContextRef context,
return JSValueMakeNull(context);
}
static JSValueRef
start_authentication_cb(JSContextRef context,
JSObjectRef function,
@ -530,6 +572,7 @@ start_authentication_cb(JSContextRef context,
return JSValueMakeNull(context);
}
static JSValueRef
provide_secret_cb(JSContextRef context,
JSObjectRef function,
@ -555,6 +598,7 @@ provide_secret_cb(JSContextRef context,
return JSValueMakeNull(context);
}
static JSValueRef
cancel_authentication_cb(JSContextRef context,
JSObjectRef function,
@ -573,6 +617,7 @@ cancel_authentication_cb(JSContextRef context,
return JSValueMakeNull(context);
}
static JSValueRef
get_authentication_user_cb(JSContextRef context,
JSObjectRef thisObject,
@ -582,6 +627,7 @@ get_authentication_user_cb(JSContextRef context,
return JSValueMakeString(context, JSStringCreateWithUTF8CString(lightdm_greeter_get_authentication_user(greeter)));
}
static JSValueRef
get_is_authenticated_cb(JSContextRef context,
JSObjectRef thisObject,
@ -591,6 +637,7 @@ get_is_authenticated_cb(JSContextRef context,
return JSValueMakeBoolean(context, lightdm_greeter_get_is_authenticated(greeter));
}
static JSValueRef
get_can_suspend_cb(JSContextRef context,
JSObjectRef thisObject,
@ -599,6 +646,7 @@ get_can_suspend_cb(JSContextRef context,
return JSValueMakeBoolean(context, lightdm_get_can_suspend());
}
static JSValueRef
suspend_cb(JSContextRef context,
JSObjectRef function,
@ -615,6 +663,7 @@ suspend_cb(JSContextRef context,
return JSValueMakeNull(context);
}
static JSValueRef
get_can_hibernate_cb(JSContextRef context,
JSObjectRef thisObject,
@ -623,6 +672,7 @@ get_can_hibernate_cb(JSContextRef context,
return JSValueMakeBoolean(context, lightdm_get_can_hibernate());
}
static JSValueRef
hibernate_cb(JSContextRef context,
JSObjectRef function,
@ -639,6 +689,7 @@ hibernate_cb(JSContextRef context,
return JSValueMakeNull(context);
}
static JSValueRef
get_can_restart_cb(JSContextRef context,
JSObjectRef thisObject,
@ -647,6 +698,7 @@ get_can_restart_cb(JSContextRef context,
return JSValueMakeBoolean(context, lightdm_get_can_restart());
}
static JSValueRef
restart_cb(JSContextRef context,
JSObjectRef function,
@ -663,6 +715,7 @@ restart_cb(JSContextRef context,
return JSValueMakeNull(context);
}
static JSValueRef
get_can_shutdown_cb(JSContextRef context,
JSObjectRef thisObject,
@ -671,6 +724,7 @@ get_can_shutdown_cb(JSContextRef context,
return JSValueMakeBoolean(context, lightdm_get_can_shutdown());
}
static JSValueRef
shutdown_cb(JSContextRef context,
JSObjectRef function,
@ -687,6 +741,7 @@ shutdown_cb(JSContextRef context,
return JSValueMakeNull(context);
}
static JSValueRef
login_cb(JSContextRef context,
JSObjectRef function,
@ -718,6 +773,7 @@ login_cb(JSContextRef context,
return JSValueMakeNull(context);
}
static JSValueRef
set_language_cb(JSContextRef context,
JSObjectRef function,
@ -740,6 +796,7 @@ set_language_cb(JSContextRef context,
return JSValueMakeNull(context);
}
static JSValueRef
gettext_cb(JSContextRef context,
JSObjectRef function,
@ -763,6 +820,7 @@ gettext_cb(JSContextRef context,
return JSValueMakeString(context, result);
}
static JSValueRef
ngettext_cb(JSContextRef context,
JSObjectRef function,
@ -793,6 +851,7 @@ ngettext_cb(JSContextRef context,
return JSValueMakeString(context, result);
}
static const JSStaticValue lightdm_user_values[] = {
{"name", get_user_name_cb, NULL, kJSPropertyAttributeReadOnly},
{"real_name", get_user_real_name_cb, NULL, kJSPropertyAttributeReadOnly},
@ -841,6 +900,7 @@ static const JSStaticValue lightdm_greeter_values[] = {
{"can_hibernate", get_can_hibernate_cb, NULL, kJSPropertyAttributeReadOnly},
{"can_restart", get_can_restart_cb, NULL, kJSPropertyAttributeReadOnly},
{"can_shutdown", get_can_shutdown_cb, NULL, kJSPropertyAttributeReadOnly},
{"lock_hint", get_lock_hint_cb, NULL, kJSPropertyAttributeReadOnly},
{NULL, NULL, NULL, 0}};
static const JSStaticFunction lightdm_greeter_functions[] = {
@ -910,6 +970,7 @@ static const JSClassDefinition gettext_definition = {
gettext_functions, /* Static functions */
};
static void
web_page_created_callback(WebKitWebExtension *extension, WebKitWebPage *web_page, gpointer user_data) {
/*@formatter:off*/
@ -920,6 +981,7 @@ web_page_created_callback(WebKitWebExtension *extension, WebKitWebPage *web_page
/*@formatter:on*/
}
static void
window_object_cleared_callback(WebKitScriptWorld *world,
WebKitWebPage *web_page,
@ -928,6 +990,8 @@ window_object_cleared_callback(WebKitScriptWorld *world,
JSObjectRef gettext_object, lightdm_greeter_object;
JSGlobalContextRef jsContext;
JSObjectRef globalObject;
WebKitDOMDocument *dom_document;
WebkitDOMDOMWindow *dom_window;
page_id = webkit_web_page_get_id(web_page);
@ -942,16 +1006,32 @@ window_object_cleared_callback(WebKitScriptWorld *world,
lightdm_session_class = JSClassCreate(&lightdm_session_definition);
gettext_object = JSObjectMake(jsContext, gettext_class, NULL);
JSObjectSetProperty(jsContext, globalObject, JSStringCreateWithUTF8CString("gettext"), gettext_object,
kJSPropertyAttributeNone, NULL);
JSObjectSetProperty(jsContext,
globalObject,
JSStringCreateWithUTF8CString("gettext"),
gettext_object,
kJSPropertyAttributeNone,
NULL);
lightdm_greeter_object = JSObjectMake(jsContext, lightdm_greeter_class, greeter);
JSObjectSetProperty(jsContext,
globalObject,
JSStringCreateWithUTF8CString("lightdm"),
lightdm_greeter_object,
kJSPropertyAttributeNone,
NULL);
// If lightdm was started as a lock-screen, send signal to our UI process.
if (lightdm_greeter_get_lock_hint(greeter)) {
dom_document = webkit_web_page_get_dom_document(web_page);
dom_window = webkit_dom_document_get_default_view(dom_document);
webkit_dom_dom_window_webkit_message_handlers_post_message(dom_window, 'Greeter', 'lock_hint_cb');
}
JSObjectSetProperty(jsContext, globalObject, JSStringCreateWithUTF8CString("lightdm"), lightdm_greeter_object,
kJSPropertyAttributeNone, NULL);
}
static void
show_prompt_cb(LightDMGreeter *greeter,
const gchar *text,
@ -982,6 +1062,7 @@ show_prompt_cb(LightDMGreeter *greeter,
}
}
static void
show_message_cb(LightDMGreeter *greeter,
const gchar *text,
@ -1009,6 +1090,7 @@ show_message_cb(LightDMGreeter *greeter,
}
}
static void
authentication_complete_cb(LightDMGreeter *greeter, WebKitWebExtension *extension) {
@ -1033,16 +1115,16 @@ authentication_complete_cb(LightDMGreeter *greeter, WebKitWebExtension *extensio
G_MODULE_EXPORT void
webkit_web_extension_initialize(WebKitWebExtension *extension) {
LightDMGreeter *greeter;
greeter = lightdm_greeter_new();
LightDMGreeter *greeter = lightdm_greeter_new();
g_signal_connect(G_OBJECT(greeter), "authentication-complete", G_CALLBACK(authentication_complete_cb), extension);
g_signal_connect(G_OBJECT(greeter), "show-prompt", G_CALLBACK(show_prompt_cb), extension);
g_signal_connect(G_OBJECT(greeter), "show-message", G_CALLBACK(show_message_cb), extension);
g_signal_connect(webkit_script_world_get_default(), "window-object-cleared",
G_CALLBACK(window_object_cleared_callback), greeter);
g_signal_connect(webkit_script_world_get_default(),
"window-object-cleared",
G_CALLBACK(window_object_cleared_callback),
greeter);
lightdm_greeter_connect_sync(greeter, NULL);
}

102
src/lightdm-webkit2-greeter.c

@ -43,9 +43,10 @@
#include <config.h>
static GtkWidget *web_view;
static GtkWidget *window;
static GtkWidget *web_view;
static GtkWidget *window;
static WebKitSettings *webkit_settings;
static GdkDisplay *default_display;
static GdkFilterReturn
@ -53,8 +54,8 @@ wm_window_filter(GdkXEvent *gxevent, GdkEvent *event, gpointer data) {
XEvent *xevent = (XEvent *) gxevent;
if (xevent->type == MapNotify) {
GdkDisplay *display = gdk_x11_lookup_xdisplay(xevent->xmap.display);
GdkWindow *win = gdk_x11_window_foreign_new_for_display(display, xevent->xmap.window);
GdkDisplay *display = gdk_x11_lookup_xdisplay(xevent->xmap.display);
GdkWindow *win = gdk_x11_window_foreign_new_for_display(display, xevent->xmap.window);
GdkWindowTypeHint win_type = gdk_window_get_type_hint(win);
if (win_type != GDK_WINDOW_TYPE_HINT_COMBO
@ -66,7 +67,7 @@ wm_window_filter(GdkXEvent *gxevent, GdkEvent *event, gpointer data) {
} else if (xevent->type == UnmapNotify) {
Window xwin;
int revert_to = RevertToNone;
int revert_to = RevertToNone;
XGetInputFocus(xevent->xunmap.display, &xwin, &revert_to);
if (revert_to == RevertToNone) {
@ -77,6 +78,7 @@ wm_window_filter(GdkXEvent *gxevent, GdkEvent *event, gpointer data) {
return GDK_FILTER_CONTINUE;
}
static void
initialize_web_extensions_cb(WebKitWebContext *context, gpointer user_data) {
@ -84,6 +86,7 @@ initialize_web_extensions_cb(WebKitWebContext *context, gpointer user_data) {
}
static void
create_new_webkit_settings_object(void) {
webkit_settings = webkit_settings_new_with_settings(
@ -101,15 +104,47 @@ create_new_webkit_settings_object(void) {
);
}
static gboolean
context_menu_cb(WebKitWebView *web_view,
WebKitContextMenu *context_menu,
GdkEvent *event,
WebKitHitTestResult *hit_test_result,
gpointer user_data) {
context_menu_cb(WebKitWebView *view,
WebKitContextMenu *context_menu,
GdkEvent *event,
WebKitHitTestResult *hit_test_result,
gpointer user_data) {
return TRUE;
}
static void
lock_hint_cb(void) {
// Make the greeter behave a bit more like a screensaver if used as un/lock-screen by blanking the screen.
Display *display = gdk_x11_display_get_xdisplay(default_display);
XGetScreenSaver(display, &timeout, &interval, &prefer_blanking, &allow_exposures);
XForceScreenSaver(display, ScreenSaverActive);
XSetScreenSaver(display,
config_get_int(NULL, CONFIG_KEY_SCREENSAVER_TIMEOUT, 60),
0,
ScreenSaverActive,
DefaultExposures);
}
static void
message_received_cb(WebKitUserContentManager *manager,
WebKitJavascriptResult *message,
gpointer user_data) {
char *message_str;
message_str = get_js_result_as_string(message);
/* TODO:
* Abstract this by using JSON for exchanging messages so the handler can be used for more than one task/event.
*/
lock_hint_cb();
}
static gboolean
fade_timer_cb(gpointer data) {
gdouble opacity;
@ -125,54 +160,66 @@ fade_timer_cb(gpointer data) {
return TRUE;
}
static void
quit_cb(void) {
// Fade out the greeter
g_timeout_add(40, (GSourceFunc) fade_timer_cb, NULL);
}
int
main(int argc, char **argv) {
GdkScreen *screen;
GdkWindow *root_window;
GdkRectangle geometry;
GKeyFile *keyfile;
gchar *theme;
GdkRGBA bg_color;
GdkScreen *screen;
GdkWindow *root_window;
GdkRectangle geometry;
GKeyFile *keyfile;
gchar *theme;
GdkRGBA bg_color;
WebKitUserContentManager *manager;
WebKitWebContext *context;
g_unix_signal_add(SIGTERM, (GSourceFunc) quit_cb, /* is_callback */ GINT_TO_POINTER(TRUE));
gtk_init(&argc, &argv);
WebKitWebContext *context = webkit_web_context_get_default();
g_signal_connect(context, "initialize-web-extensions", G_CALLBACK(initialize_web_extensions_cb), NULL);
// Apply greeter settings from conf file
keyfile = g_key_file_new();
g_key_file_load_from_file(keyfile, "/etc/lightdm/lightdm-webkit2-greeter.conf", G_KEY_FILE_NONE, NULL);
theme = g_key_file_get_string(keyfile, "greeter", "webkit-theme", NULL);
// Setup the main window
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
screen = gtk_window_get_screen(GTK_WINDOW(window));
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
screen = gtk_window_get_screen(GTK_WINDOW(window));
root_window = gdk_get_default_root_window();
display = gdk_display_get_default();
gtk_window_set_decorated(GTK_WINDOW(window), FALSE);
gdk_screen_get_monitor_geometry(screen, gdk_screen_get_primary_monitor(screen), &geometry);
gtk_window_set_default_size(GTK_WINDOW(window), geometry.width, geometry.height);
gtk_window_move(GTK_WINDOW(window), geometry.x, geometry.y);
gdk_window_set_cursor(root_window, gdk_cursor_new_for_display(gdk_display_get_default(), GDK_LEFT_PTR));
gdk_window_set_cursor(root_window, gdk_cursor_new_for_display(display, GDK_LEFT_PTR));
// There is no window manager, so we need to implement some of its functionality
gdk_window_set_events(root_window, gdk_window_get_events(root_window) | GDK_SUBSTRUCTURE_MASK);
gdk_window_add_filter(root_window, wm_window_filter, NULL);
// Configure the web_view's settings.
// Register and connect handler for setting the web extensions directory so webkit can find our extension
context = webkit_web_context_get_default();
g_signal_connect(context, "initialize-web-extensions", G_CALLBACK(initialize_web_extensions_cb), NULL);
// Register and connect handler for messages sent from our web extension
manager = webkit_user_content_manager_new();
webkit_user_content_manager_register_script_message_handler(manager, "Greeter");
g_signal_connect(manager, "script-message-received::Greeter", G_CALLBACK(message_received_cb), NULL);
// Create the web_view
web_view = webkit_web_view_new_with_user_content_manager(manager);
// Set the web_view's settings.
create_new_webkit_settings_object();
web_view = webkit_web_view_new_with_settings(webkit_settings);
webkit_web_view_set_settings(web_view, webkit_settings);
// The default background is white which causes a flash effect when the greeter starts. Make it black instead.
gdk_rgba_parse(&bg_color, "#000000");
@ -183,10 +230,9 @@ main(int argc, char **argv) {
gtk_container_add(GTK_CONTAINER(window), web_view);
webkit_web_view_load_uri(WEBKIT_WEB_VIEW(web_view), g_strdup_printf("file://%s/%s/index.html", THEME_DIR, theme));
gtk_widget_show_all(window);
gtk_main();
return 0;

Loading…
Cancel
Save