diff options
Diffstat (limited to 'src/gs-window-x11.c.orig')
-rw-r--r-- | src/gs-window-x11.c.orig | 2647 |
1 files changed, 0 insertions, 2647 deletions
diff --git a/src/gs-window-x11.c.orig b/src/gs-window-x11.c.orig deleted file mode 100644 index f7c3c70..0000000 --- a/src/gs-window-x11.c.orig +++ /dev/null @@ -1,2647 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2004-2008 William Jon McCann <[email protected]> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Authors: William Jon McCann <[email protected]> - * - */ - -#include "config.h" - -#include <sys/types.h> -#include <errno.h> -#include <sys/wait.h> -#include <string.h> - -#include <gdk/gdkx.h> -#include <gdk/gdkkeysyms.h> -#include <gtk/gtk.h> - -#include "gs-window.h" -#include "gs-marshal.h" -#include "subprocs.h" -#include "gs-debug.h" - -#ifdef HAVE_SHAPE_EXT -#include <X11/extensions/shape.h> -#endif - -static void gs_window_class_init (GSWindowClass *klass); -static void gs_window_init (GSWindow *window); -static void gs_window_finalize (GObject *object); - -static gboolean popup_dialog_idle (GSWindow *window); -static void gs_window_dialog_finish (GSWindow *window); -static void remove_command_watches (GSWindow *window); - -enum -{ - DIALOG_RESPONSE_CANCEL, - DIALOG_RESPONSE_OK -}; - -#define MAX_QUEUED_EVENTS 16 -#define INFO_BAR_SECONDS 30 - -#define GS_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GS_TYPE_WINDOW, GSWindowPrivate)) - -struct GSWindowPrivate -{ - int monitor; - - GdkRectangle geometry; - guint obscured : 1; - guint dialog_up : 1; - - guint lock_enabled : 1; - guint user_switch_enabled : 1; - guint logout_enabled : 1; - guint keyboard_enabled : 1; - - guint64 logout_timeout; - char *logout_command; - char *keyboard_command; - char *status_message; - - GtkWidget *vbox; - GtkWidget *drawing_area; - GtkWidget *lock_box; - GtkWidget *lock_socket; - GtkWidget *keyboard_socket; - GtkWidget *info_bar; - GtkWidget *info_content; - - GdkPixmap *background_pixmap; - - guint popup_dialog_idle_id; - - guint dialog_map_signal_id; - guint dialog_unmap_signal_id; - guint dialog_response_signal_id; - - guint watchdog_timer_id; - guint info_bar_timer_id; - - gint lock_pid; - gint lock_watch_id; - gint dialog_response; - gboolean dialog_quit_requested; - gboolean dialog_shake_in_progress; - - gint keyboard_pid; - gint keyboard_watch_id; - - GList *key_events; - - gdouble last_x; - gdouble last_y; - - GTimer *timer; - -#ifdef HAVE_SHAPE_EXT - int shape_event_base; -#endif -}; - -enum -{ - ACTIVITY, - DEACTIVATED, - LAST_SIGNAL -}; - -enum -{ - PROP_0, - PROP_OBSCURED, - PROP_DIALOG_UP, - PROP_LOCK_ENABLED, - PROP_LOGOUT_ENABLED, - PROP_KEYBOARD_ENABLED, - PROP_KEYBOARD_COMMAND, - PROP_LOGOUT_COMMAND, - PROP_LOGOUT_TIMEOUT, - PROP_MONITOR, - PROP_STATUS_MESSAGE -}; - -static guint signals [LAST_SIGNAL] = { 0, }; - -G_DEFINE_TYPE (GSWindow, gs_window, GTK_TYPE_WINDOW) - -static void -set_invisible_cursor (GdkWindow *window, - gboolean invisible) -{ - GdkBitmap *empty_bitmap; - GdkCursor *cursor = NULL; - GdkColor useless; - char invisible_cursor_bits [] = { 0x0 }; - - if (invisible) - { - useless.red = useless.green = useless.blue = 0; - useless.pixel = 0; - - empty_bitmap = gdk_bitmap_create_from_data (window, - invisible_cursor_bits, - 1, 1); - - cursor = gdk_cursor_new_from_pixmap (empty_bitmap, - empty_bitmap, - &useless, - &useless, 0, 0); - - g_object_unref (empty_bitmap); - } - - gdk_window_set_cursor (window, cursor); - - if (cursor) - { - gdk_cursor_unref (cursor); - } -} - -/* derived from tomboy */ -static void -gs_window_override_user_time (GSWindow *window) -{ - guint32 ev_time = gtk_get_current_event_time (); - - if (ev_time == 0) - { - gint ev_mask = gtk_widget_get_events (GTK_WIDGET (window)); - if (!(ev_mask & GDK_PROPERTY_CHANGE_MASK)) - { - gtk_widget_add_events (GTK_WIDGET (window), - GDK_PROPERTY_CHANGE_MASK); - } - - /* - * NOTE: Last resort for D-BUS or other non-interactive - * openings. Causes roundtrip to server. Lame. - */ - ev_time = gdk_x11_get_server_time (GTK_WIDGET (window)->window); - } - - gdk_x11_window_set_user_time (GTK_WIDGET (window)->window, ev_time); -} - -static void -force_no_pixmap_background (GtkWidget *widget) -{ - static gboolean first_time = TRUE; - - if (first_time) - { - gtk_rc_parse_string ("\n" - " style \"gs-theme-engine-style\"\n" - " {\n" - " bg_pixmap[NORMAL] = \"<none>\"\n" - " bg_pixmap[INSENSITIVE] = \"<none>\"\n" - " bg_pixmap[ACTIVE] = \"<none>\"\n" - " bg_pixmap[PRELIGHT] = \"<none>\"\n" - " bg[NORMAL] = { 0.0, 0.0, 0.0 }\n" - " bg[INSENSITIVE] = { 0.0, 0.0, 0.0 }\n" - " bg[ACTIVE] = { 0.0, 0.0, 0.0 }\n" - " bg[PRELIGHT] = { 0.0, 0.0, 0.0 }\n" - " }\n" - " widget \"gs-window-drawing-area*\" style : highest \"gs-theme-engine-style\"\n" - "\n"); - first_time = FALSE; - } - - gtk_widget_set_name (widget, "gs-window-drawing-area"); -} - -static void -clear_children (Window window) -{ - Window root; - Window parent; - Window *children; - unsigned int n_children; - int status; - - children = NULL; - status = XQueryTree (GDK_DISPLAY (), window, &root, &parent, &children, &n_children); - - if (status == 0) - { - if (children) - { - XFree (children); - } - return; - } - - if (children) - { - while (n_children) - { - Window child; - - child = children [--n_children]; - - XClearWindow (GDK_DISPLAY (), child); - clear_children (child); - } - - XFree (children); - } -} - -static void -widget_clear_all_children (GtkWidget *widget) -{ - GdkWindow *w; - - gs_debug ("Clearing all child windows"); - - gdk_error_trap_push (); - - w = widget->window; - - clear_children (GDK_WINDOW_XID (w)); - - gdk_display_sync (gtk_widget_get_display (widget)); - gdk_error_trap_pop (); -} - -void -gs_window_set_background_pixmap (GSWindow *window, - GdkPixmap *pixmap) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - if (window->priv->background_pixmap != NULL) - { - g_object_unref (window->priv->background_pixmap); - } - - if (pixmap != NULL) - { - window->priv->background_pixmap = g_object_ref (pixmap); - gdk_window_set_back_pixmap (GTK_WIDGET (window)->window, - pixmap, - FALSE); - } -} - -static void -gs_window_clear_to_background_pixmap (GSWindow *window) -{ - GtkStateType state; - GtkStyle *style; - - g_return_if_fail (GS_IS_WINDOW (window)); - - if (! GTK_WIDGET_VISIBLE (GTK_WIDGET (window))) - { - return; - } - - if (window->priv->background_pixmap == NULL) - { - /* don't allow null pixmaps */ - return; - } - - gs_debug ("Clearing window to background pixmap"); - - style = gtk_style_copy (GTK_WIDGET (window)->style); - - state = (GtkStateType) 0; - while (state < (GtkStateType) G_N_ELEMENTS (GTK_WIDGET (window)->style->bg_pixmap)) - { - - if (style->bg_pixmap[state] != NULL) - { - g_object_unref (style->bg_pixmap[state]); - } - - style->bg_pixmap[state] = g_object_ref (window->priv->background_pixmap); - state++; - } - - gtk_widget_set_style (GTK_WIDGET (window), style); - g_object_unref (style); - - if (window->priv->background_pixmap != NULL) - { - gdk_window_set_back_pixmap (GTK_WIDGET (window)->window, - window->priv->background_pixmap, - FALSE); - } - - gdk_window_clear (GTK_WIDGET (window)->window); - - gdk_flush (); -} - -static void -clear_widget (GtkWidget *widget) -{ - GdkColor color = { 0, 0x0000, 0x0000, 0x0000 }; - GdkColormap *colormap; - GtkStateType state; - GtkStyle *style; - - if (! GTK_WIDGET_VISIBLE (widget)) - { - return; - } - - gs_debug ("Clearing widget"); - - state = (GtkStateType) 0; - while (state < (GtkStateType) G_N_ELEMENTS (widget->style->bg)) - { - gtk_widget_modify_bg (widget, state, &color); - state++; - } - - style = gtk_style_copy (widget->style); - - state = (GtkStateType) 0; - while (state < (GtkStateType) G_N_ELEMENTS (widget->style->bg_pixmap)) - { - - if (style->bg_pixmap[state] != NULL) - { - g_object_unref (style->bg_pixmap[state]); - } - - style->bg_pixmap[state] = NULL; - state++; - } - - colormap = gdk_drawable_get_colormap (widget->window); - gdk_colormap_alloc_color (colormap, &color, FALSE, TRUE); - gdk_window_set_background (widget->window, &color); - - gtk_widget_set_style (widget, style); - g_object_unref (style); - - gdk_window_clear (widget->window); - - /* If a screensaver theme adds child windows we need to clear them too */ - widget_clear_all_children (widget); - - gdk_flush (); -} - -void -gs_window_clear (GSWindow *window) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - clear_widget (GTK_WIDGET (window)); - clear_widget (window->priv->drawing_area); -} - -static GdkRegion * -get_outside_region (GSWindow *window) -{ - int i; - GdkRegion *region; - - region = gdk_region_new (); - for (i = 0; i < window->priv->monitor; i++) - { - GdkRectangle geometry; - - gdk_screen_get_monitor_geometry (GTK_WINDOW (window)->screen, - i, &geometry); - gdk_region_union_with_rect (region, &geometry); - } - - return region; -} - -static void -update_geometry (GSWindow *window) -{ - GdkRectangle geometry; - GdkRegion *outside_region; - GdkRegion *monitor_region; - - outside_region = get_outside_region (window); - - gdk_screen_get_monitor_geometry (GTK_WINDOW (window)->screen, - window->priv->monitor, - &geometry); - gs_debug ("got geometry for monitor %d: x=%d y=%d w=%d h=%d", - window->priv->monitor, - geometry.x, - geometry.y, - geometry.width, - geometry.height); - monitor_region = gdk_region_rectangle (&geometry); - gdk_region_subtract (monitor_region, outside_region); - gdk_region_destroy (outside_region); - - gdk_region_get_clipbox (monitor_region, &geometry); - gdk_region_destroy (monitor_region); - - gs_debug ("using geometry for monitor %d: x=%d y=%d w=%d h=%d", - window->priv->monitor, - geometry.x, - geometry.y, - geometry.width, - geometry.height); - - window->priv->geometry.x = geometry.x; - window->priv->geometry.y = geometry.y; - window->priv->geometry.width = geometry.width; - window->priv->geometry.height = geometry.height; -} - -static void -screen_size_changed (GdkScreen *screen, - GSWindow *window) -{ - gs_debug ("Got screen size changed signal"); - gtk_widget_queue_resize (GTK_WIDGET (window)); -} - -/* copied from panel-toplevel.c */ -static void -gs_window_move_resize_window (GSWindow *window, - gboolean move, - gboolean resize) -{ - GtkWidget *widget; - - widget = GTK_WIDGET (window); - - g_assert (GTK_WIDGET_REALIZED (widget)); - - gs_debug ("Move and/or resize window on monitor %d: x=%d y=%d w=%d h=%d", - window->priv->monitor, - window->priv->geometry.x, - window->priv->geometry.y, - window->priv->geometry.width, - window->priv->geometry.height); - - if (move && resize) - { - gdk_window_move_resize (widget->window, - window->priv->geometry.x, - window->priv->geometry.y, - window->priv->geometry.width, - window->priv->geometry.height); - } - else if (move) - { - gdk_window_move (widget->window, - window->priv->geometry.x, - window->priv->geometry.y); - } - else if (resize) - { - gdk_window_resize (widget->window, - window->priv->geometry.width, - window->priv->geometry.height); - } -} - -static void -gs_window_real_unrealize (GtkWidget *widget) -{ - g_signal_handlers_disconnect_by_func (gtk_window_get_screen (GTK_WINDOW (widget)), - screen_size_changed, - widget); - - if (GTK_WIDGET_CLASS (gs_window_parent_class)->unrealize) - { - GTK_WIDGET_CLASS (gs_window_parent_class)->unrealize (widget); - } -} - -/* copied from gdk */ -extern char **environ; - -static gchar ** -spawn_make_environment_for_screen (GdkScreen *screen, - gchar **envp) -{ - gchar **retval = NULL; - gchar *display_name; - gint display_index = -1; - gint i, env_len; - - g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); - - if (envp == NULL) - envp = environ; - - for (env_len = 0; envp[env_len]; env_len++) - if (strncmp (envp[env_len], "DISPLAY", strlen ("DISPLAY")) == 0) - display_index = env_len; - - retval = g_new (char *, env_len + 1); - retval[env_len] = NULL; - - display_name = gdk_screen_make_display_name (screen); - - for (i = 0; i < env_len; i++) - if (i == display_index) - retval[i] = g_strconcat ("DISPLAY=", display_name, NULL); - else - retval[i] = g_strdup (envp[i]); - - g_assert (i == env_len); - - g_free (display_name); - - return retval; -} - -static gboolean -spawn_command_line_on_screen_sync (GdkScreen *screen, - const gchar *command_line, - char **standard_output, - char **standard_error, - int *exit_status, - GError **error) -{ - char **argv = NULL; - char **envp = NULL; - gboolean retval; - - g_return_val_if_fail (command_line != NULL, FALSE); - - if (! g_shell_parse_argv (command_line, NULL, &argv, error)) - { - return FALSE; - } - - envp = spawn_make_environment_for_screen (screen, NULL); - - retval = g_spawn_sync (NULL, - argv, - envp, - G_SPAWN_SEARCH_PATH, - NULL, - NULL, - standard_output, - standard_error, - exit_status, - error); - - g_strfreev (argv); - g_strfreev (envp); - - return retval; -} - -static GdkVisual * -get_best_visual_for_screen (GdkScreen *screen) -{ - char *command; - char *std_output; - int exit_status; - GError *error; - unsigned long v; - char c; - GdkVisual *visual; - gboolean res; - - visual = NULL; - - command = g_build_filename (LIBEXECDIR, "mate-screensaver-gl-helper", NULL); - - error = NULL; - std_output = NULL; - res = spawn_command_line_on_screen_sync (screen, - command, - &std_output, - NULL, - &exit_status, - &error); - if (! res) - { - gs_debug ("Could not run command '%s': %s", command, error->message); - g_error_free (error); - goto out; - } - - if (1 == sscanf (std_output, "0x%lx %c", &v, &c)) - { - if (v != 0) - { - VisualID visual_id; - - visual_id = (VisualID) v; - visual = gdkx_visual_get (visual_id); - - gs_debug ("Found best GL visual for screen %d: 0x%x", - gdk_screen_get_number (screen), - (unsigned int) visual_id); - } - } -out: - g_free (std_output); - g_free (command); - - return visual; -} - -static GdkColormap * -get_best_colormap_for_screen (GdkScreen *screen) -{ - GdkColormap *colormap; - GdkVisual *visual; - - g_return_val_if_fail (screen != NULL, NULL); - - visual = get_best_visual_for_screen (screen); - - colormap = NULL; - if (visual != NULL) - { - colormap = gdk_colormap_new (visual, FALSE); - } - - return colormap; -} - -static void -widget_set_best_colormap (GtkWidget *widget) -{ - GdkColormap *colormap; - - g_return_if_fail (widget != NULL); - - colormap = get_best_colormap_for_screen (gtk_widget_get_screen (widget)); - if (colormap != NULL) - { - gtk_widget_set_colormap (widget, colormap); - g_object_unref (colormap); - } -} - -static void -gs_window_real_realize (GtkWidget *widget) -{ - widget_set_best_colormap (widget); - - if (GTK_WIDGET_CLASS (gs_window_parent_class)->realize) - { - GTK_WIDGET_CLASS (gs_window_parent_class)->realize (widget); - } - - gs_window_override_user_time (GS_WINDOW (widget)); - - gs_window_move_resize_window (GS_WINDOW (widget), TRUE, TRUE); - - g_signal_connect (gtk_window_get_screen (GTK_WINDOW (widget)), - "size_changed", - G_CALLBACK (screen_size_changed), - widget); -} - -/* every so often we should raise the window in case - another window has somehow gotten on top */ -static gboolean -watchdog_timer (GSWindow *window) -{ - GtkWidget *widget = GTK_WIDGET (window); - - gdk_window_focus (widget->window, GDK_CURRENT_TIME); - - return TRUE; -} - -static void -remove_watchdog_timer (GSWindow *window) -{ - if (window->priv->watchdog_timer_id != 0) - { - g_source_remove (window->priv->watchdog_timer_id); - window->priv->watchdog_timer_id = 0; - } -} - -static void -add_watchdog_timer (GSWindow *window, - glong timeout) -{ - window->priv->watchdog_timer_id = g_timeout_add (timeout, - (GSourceFunc)watchdog_timer, - window); -} - -static void -remove_popup_dialog_idle (GSWindow *window) -{ - if (window->priv->popup_dialog_idle_id != 0) - { - g_source_remove (window->priv->popup_dialog_idle_id); - window->priv->popup_dialog_idle_id = 0; - } -} - -static void -add_popup_dialog_idle (GSWindow *window) -{ - window->priv->popup_dialog_idle_id = g_idle_add ((GSourceFunc)popup_dialog_idle, window); -} - -static gboolean -emit_deactivated_idle (GSWindow *window) -{ - g_signal_emit (window, signals [DEACTIVATED], 0); - - return FALSE; -} - -static void -add_emit_deactivated_idle (GSWindow *window) -{ - g_idle_add ((GSourceFunc)emit_deactivated_idle, window); -} - -static void -gs_window_raise (GSWindow *window) -{ - GdkWindow *win; - - g_return_if_fail (GS_IS_WINDOW (window)); - - gs_debug ("Raising screensaver window"); - - win = GTK_WIDGET (window)->window; - - gdk_window_raise (win); -} - -static gboolean -x11_window_is_ours (Window window) -{ - GdkWindow *gwindow; - gboolean ret; - - ret = FALSE; - - gwindow = gdk_window_lookup (window); - if (gwindow && (window != GDK_ROOT_WINDOW ())) - { - ret = TRUE; - } - - return ret; -} - -#ifdef HAVE_SHAPE_EXT -static void -unshape_window (GSWindow *window) -{ - gdk_window_shape_combine_region (GTK_WIDGET (window)->window, - NULL, - 0, - 0); -} -#endif - -static void -gs_window_xevent (GSWindow *window, - GdkXEvent *xevent) -{ - XEvent *ev; - - ev = xevent; - - /* MapNotify is used to tell us when new windows are mapped. - ConfigureNofify is used to tell us when windows are raised. */ - switch (ev->xany.type) - { - case MapNotify: - { - XMapEvent *xme = &ev->xmap; - - if (! x11_window_is_ours (xme->window)) - { - gs_window_raise (window); - } - else - { - gs_debug ("not raising our windows"); - } - - break; - } - case ConfigureNotify: - { - XConfigureEvent *xce = &ev->xconfigure; - - if (! x11_window_is_ours (xce->window)) - { - gs_window_raise (window); - } - else - { - gs_debug ("not raising our windows"); - } - - break; - } - default: - /* extension events */ -#ifdef HAVE_SHAPE_EXT - if (ev->xany.type == (window->priv->shape_event_base + ShapeNotify)) - { - /*XShapeEvent *xse = (XShapeEvent *) ev;*/ - unshape_window (window); - gs_debug ("Window was reshaped!"); - } -#endif - - break; - } - -} - -static GdkFilterReturn -xevent_filter (GdkXEvent *xevent, - GdkEvent *event, - GSWindow *window) -{ - gs_window_xevent (window, xevent); - - return GDK_FILTER_CONTINUE; -} - -static void -select_popup_events (void) -{ - XWindowAttributes attr; - unsigned long events; - - gdk_error_trap_push (); - - memset (&attr, 0, sizeof (attr)); - XGetWindowAttributes (GDK_DISPLAY (), GDK_ROOT_WINDOW (), &attr); - - events = SubstructureNotifyMask | attr.your_event_mask; - XSelectInput (GDK_DISPLAY (), GDK_ROOT_WINDOW (), events); - - gdk_display_sync (gdk_display_get_default ()); - gdk_error_trap_pop (); -} - -static void -window_select_shape_events (GSWindow *window) -{ -#ifdef HAVE_SHAPE_EXT - unsigned long events; - int shape_error_base; - - gdk_error_trap_push (); - - if (XShapeQueryExtension (GDK_DISPLAY (), &window->priv->shape_event_base, &shape_error_base)) - { - events = ShapeNotifyMask; - XShapeSelectInput (GDK_DISPLAY (), GDK_WINDOW_XID (GTK_WIDGET (window)->window), events); - } - - gdk_display_sync (gdk_display_get_default ()); - gdk_error_trap_pop (); -#endif -} - -static void -gs_window_real_show (GtkWidget *widget) -{ - GSWindow *window; - - if (GTK_WIDGET_CLASS (gs_window_parent_class)->show) - { - GTK_WIDGET_CLASS (gs_window_parent_class)->show (widget); - } - - gs_window_clear (GS_WINDOW (widget)); - - set_invisible_cursor (widget->window, TRUE); - - window = GS_WINDOW (widget); - if (window->priv->timer) - { - g_timer_destroy (window->priv->timer); - } - window->priv->timer = g_timer_new (); - - remove_watchdog_timer (window); - add_watchdog_timer (window, 30000); - - select_popup_events (); - window_select_shape_events (window); - gdk_window_add_filter (NULL, (GdkFilterFunc)xevent_filter, window); -} - -static void -set_info_text_and_icon (GSWindow *window, - const char *icon_stock_id, - const char *primary_text, - const char *secondary_text) -{ - GtkWidget *content_area; - GtkWidget *hbox_content; - GtkWidget *image; - GtkWidget *vbox; - gchar *primary_markup; - gchar *secondary_markup; - GtkWidget *primary_label; - GtkWidget *secondary_label; - - hbox_content = gtk_hbox_new (FALSE, 8); - gtk_widget_show (hbox_content); - - image = gtk_image_new_from_stock (icon_stock_id, GTK_ICON_SIZE_DIALOG); - gtk_widget_show (image); - gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0); - gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0); - - vbox = gtk_vbox_new (FALSE, 6); - gtk_widget_show (vbox); - gtk_box_pack_start (GTK_BOX (hbox_content), vbox, FALSE, FALSE, 0); - - primary_markup = g_strdup_printf ("<b>%s</b>", primary_text); - primary_label = gtk_label_new (primary_markup); - g_free (primary_markup); - gtk_widget_show (primary_label); - gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0); - gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE); - gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE); - gtk_misc_set_alignment (GTK_MISC (primary_label), 0, 0.5); - - if (secondary_text != NULL) - { - secondary_markup = g_strdup_printf ("<small>%s</small>", - secondary_text); - secondary_label = gtk_label_new (secondary_markup); - g_free (secondary_markup); - gtk_widget_show (secondary_label); - gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0); - gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE); - gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE); - gtk_misc_set_alignment (GTK_MISC (secondary_label), 0, 0.5); - } - - /* remove old content */ - content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (window->priv->info_bar)); - if (window->priv->info_content != NULL) - { - gtk_container_remove (GTK_CONTAINER (content_area), window->priv->info_content); - } - gtk_box_pack_start (GTK_BOX (content_area), - hbox_content, - TRUE, FALSE, 0); - window->priv->info_content = hbox_content; -} - -static gboolean -info_bar_timeout (GSWindow *window) -{ - window->priv->info_bar_timer_id = 0; - gtk_widget_hide (window->priv->info_bar); - return FALSE; -} - -void -gs_window_show_message (GSWindow *window, - const char *summary, - const char *body, - const char *icon) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - set_info_text_and_icon (window, - icon, - summary, - body); - gtk_widget_show (window->priv->info_bar); - - if (window->priv->info_bar_timer_id > 0) - { - g_source_remove (window->priv->info_bar_timer_id); - } - - window->priv->info_bar_timer_id = g_timeout_add_seconds (INFO_BAR_SECONDS, - (GSourceFunc)info_bar_timeout, - window); -} - -void -gs_window_show (GSWindow *window) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - gtk_widget_show (GTK_WIDGET (window)); -} - -static void -gs_window_real_hide (GtkWidget *widget) -{ - GSWindow *window; - - window = GS_WINDOW (widget); - - gdk_window_remove_filter (NULL, (GdkFilterFunc)xevent_filter, window); - - remove_watchdog_timer (window); - - if (GTK_WIDGET_CLASS (gs_window_parent_class)->hide) - { - GTK_WIDGET_CLASS (gs_window_parent_class)->hide (widget); - } -} - -void -gs_window_destroy (GSWindow *window) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - gs_window_cancel_unlock_request (window); - - gtk_widget_destroy (GTK_WIDGET (window)); -} - -GdkWindow * -gs_window_get_gdk_window (GSWindow *window) -{ - g_return_val_if_fail (GS_IS_WINDOW (window), NULL); - - return GTK_WIDGET (window)->window; -} - -GtkWidget * -gs_window_get_drawing_area (GSWindow *window) -{ - g_return_val_if_fail (GS_IS_WINDOW (window), NULL); - - return window->priv->drawing_area; -} - -/* just for debugging */ -static gboolean -error_watch (GIOChannel *source, - GIOCondition condition, - gpointer data) -{ - gboolean finished = FALSE; - - if (condition & G_IO_IN) - { - GIOStatus status; - GError *error = NULL; - char *line; - - line = NULL; - status = g_io_channel_read_line (source, &line, NULL, NULL, &error); - - switch (status) - { - case G_IO_STATUS_NORMAL: - gs_debug ("command error output: %s", line); - break; - case G_IO_STATUS_EOF: - finished = TRUE; - break; - case G_IO_STATUS_ERROR: - finished = TRUE; - gs_debug ("Error reading from child: %s\n", error->message); - g_error_free (error); - return FALSE; - case G_IO_STATUS_AGAIN: - default: - break; - } - g_free (line); - } - else if (condition & G_IO_HUP) - { - finished = TRUE; - } - - if (finished) - { - return FALSE; - } - - return TRUE; -} - -static gboolean -spawn_on_window (GSWindow *window, - char *command, - int *pid, - GIOFunc watch_func, - gpointer user_data, - gint *watch_id) -{ - int argc; - char **argv; - GError *error; - gboolean result; - GIOChannel *channel; - int standard_output; - int standard_error; - int child_pid; - int id; - - error = NULL; - if (! g_shell_parse_argv (command, &argc, &argv, &error)) - { - gs_debug ("Could not parse command: %s", error->message); - g_error_free (error); - return FALSE; - } - - error = NULL; - result = gdk_spawn_on_screen_with_pipes (GTK_WINDOW (window)->screen, - NULL, - argv, - NULL, - G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, - NULL, - NULL, - &child_pid, - NULL, - &standard_output, - &standard_error, - &error); - - if (! result) - { - gs_debug ("Could not start command '%s': %s", command, error->message); - g_error_free (error); - g_strfreev (argv); - return FALSE; - } - - if (pid != NULL) - { - *pid = child_pid; - } - else - { - g_spawn_close_pid (child_pid); - } - - /* output channel */ - channel = g_io_channel_unix_new (standard_output); - g_io_channel_set_close_on_unref (channel, TRUE); - g_io_channel_set_flags (channel, - g_io_channel_get_flags (channel) | G_IO_FLAG_NONBLOCK, - NULL); - id = g_io_add_watch (channel, - G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - watch_func, - user_data); - if (watch_id != NULL) - { - *watch_id = id; - } - g_io_channel_unref (channel); - - /* error channel */ - channel = g_io_channel_unix_new (standard_error); - g_io_channel_set_close_on_unref (channel, TRUE); - g_io_channel_set_flags (channel, - g_io_channel_get_flags (channel) | G_IO_FLAG_NONBLOCK, - NULL); - id = g_io_add_watch (channel, - G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - error_watch, - NULL); - g_io_channel_unref (channel); - - g_strfreev (argv); - - return result; -} - -static void -lock_plug_added (GtkWidget *widget, - GSWindow *window) -{ - gtk_widget_show (widget); -} - -static gboolean -lock_plug_removed (GtkWidget *widget, - GSWindow *window) -{ - gtk_widget_hide (widget); - gtk_container_remove (GTK_CONTAINER (window->priv->vbox), GTK_WIDGET (window->priv->lock_box)); - window->priv->lock_box = NULL; - - return TRUE; -} - -static void -keyboard_plug_added (GtkWidget *widget, - GSWindow *window) -{ - gtk_widget_show (widget); -} - -static gboolean -keyboard_plug_removed (GtkWidget *widget, - GSWindow *window) -{ - gtk_widget_hide (widget); - gtk_container_remove (GTK_CONTAINER (window->priv->vbox), GTK_WIDGET (window->priv->keyboard_socket)); - - return TRUE; -} - -static void -keyboard_socket_destroyed (GtkWidget *widget, - GSWindow *window) -{ - g_signal_handlers_disconnect_by_func (widget, keyboard_socket_destroyed, window); - g_signal_handlers_disconnect_by_func (widget, keyboard_plug_added, window); - g_signal_handlers_disconnect_by_func (widget, keyboard_plug_removed, window); - - window->priv->keyboard_socket = NULL; -} - -static void -forward_key_events (GSWindow *window) -{ - window->priv->key_events = g_list_reverse (window->priv->key_events); - - while (window->priv->key_events != NULL) - { - GdkEventKey *event = window->priv->key_events->data; - - gtk_window_propagate_key_event (GTK_WINDOW (window), event); - - gdk_event_free ((GdkEvent *)event); - window->priv->key_events = g_list_delete_link (window->priv->key_events, - window->priv->key_events); - } -} - -static void -remove_key_events (GSWindow *window) -{ - window->priv->key_events = g_list_reverse (window->priv->key_events); - - while (window->priv->key_events) - { - GdkEventKey *event = window->priv->key_events->data; - - gdk_event_free ((GdkEvent *)event); - window->priv->key_events = g_list_delete_link (window->priv->key_events, - window->priv->key_events); - } -} - -static void -lock_socket_show (GtkWidget *widget, - GSWindow *window) -{ - gtk_widget_child_focus (window->priv->lock_socket, GTK_DIR_TAB_FORWARD); - - /* send queued events to the dialog */ - forward_key_events (window); -} - -static void -lock_socket_destroyed (GtkWidget *widget, - GSWindow *window) -{ - g_signal_handlers_disconnect_by_func (widget, lock_socket_show, window); - g_signal_handlers_disconnect_by_func (widget, lock_socket_destroyed, window); - g_signal_handlers_disconnect_by_func (widget, lock_plug_added, window); - g_signal_handlers_disconnect_by_func (widget, lock_plug_removed, window); - - window->priv->lock_socket = NULL; -} - -static void -create_keyboard_socket (GSWindow *window, - guint32 id) -{ - int height; - - height = (gdk_screen_get_height (gtk_widget_get_screen (GTK_WIDGET (window)))) / 4; - - window->priv->keyboard_socket = gtk_socket_new (); - gtk_widget_set_size_request (window->priv->keyboard_socket, -1, height); - - g_signal_connect (window->priv->keyboard_socket, "destroy", - G_CALLBACK (keyboard_socket_destroyed), window); - g_signal_connect (window->priv->keyboard_socket, "plug_added", - G_CALLBACK (keyboard_plug_added), window); - g_signal_connect (window->priv->keyboard_socket, "plug_removed", - G_CALLBACK (keyboard_plug_removed), window); - gtk_box_pack_start (GTK_BOX (window->priv->vbox), window->priv->keyboard_socket, FALSE, FALSE, 0); - gtk_socket_add_id (GTK_SOCKET (window->priv->keyboard_socket), id); -} - -/* adapted from gspawn.c */ -static int -wait_on_child (int pid) -{ - int status; - -wait_again: - if (waitpid (pid, &status, 0) < 0) - { - if (errno == EINTR) - { - goto wait_again; - } - else if (errno == ECHILD) - { - ; /* do nothing, child already reaped */ - } - else - { - gs_debug ("waitpid () should not fail in 'GSWindow'"); - } - } - - return status; -} - -static void -kill_keyboard_command (GSWindow *window) -{ - if (window->priv->keyboard_pid > 0) - { - signal_pid (window->priv->keyboard_pid, SIGTERM); - } -} - -static void -kill_dialog_command (GSWindow *window) -{ - /* If a dialog is up we need to signal it - and wait on it */ - if (window->priv->lock_pid > 0) - { - signal_pid (window->priv->lock_pid, SIGTERM); - } -} - -static void -keyboard_command_finish (GSWindow *window) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - /* send a signal just in case */ - kill_keyboard_command (window); - - gs_debug ("Keyboard finished"); - - if (window->priv->keyboard_pid > 0) - { - int exit_status; - - exit_status = wait_on_child (window->priv->keyboard_pid); - - g_spawn_close_pid (window->priv->keyboard_pid); - window->priv->keyboard_pid = 0; - } -} - -static gboolean -keyboard_command_watch (GIOChannel *source, - GIOCondition condition, - GSWindow *window) -{ - gboolean finished = FALSE; - - g_return_val_if_fail (GS_IS_WINDOW (window), FALSE); - - if (condition & G_IO_IN) - { - GIOStatus status; - GError *error = NULL; - char *line; - - line = NULL; - status = g_io_channel_read_line (source, &line, NULL, NULL, &error); - - switch (status) - { - case G_IO_STATUS_NORMAL: - { - guint32 id; - char c; - gs_debug ("keyboard command output: %s", line); - if (1 == sscanf (line, " %" G_GUINT32_FORMAT " %c", &id, &c)) - { - create_keyboard_socket (window, id); - } - } - break; - case G_IO_STATUS_EOF: - finished = TRUE; - break; - case G_IO_STATUS_ERROR: - finished = TRUE; - gs_debug ("Error reading from child: %s\n", error->message); - g_error_free (error); - return FALSE; - case G_IO_STATUS_AGAIN: - default: - break; - } - - g_free (line); - } - else if (condition & G_IO_HUP) - { - finished = TRUE; - } - - if (finished) - { - window->priv->keyboard_watch_id = 0; - keyboard_command_finish (window); - return FALSE; - } - - return TRUE; -} - -static void -embed_keyboard (GSWindow *window) -{ - gboolean res; - - if (! window->priv->keyboard_enabled - || window->priv->keyboard_command == NULL) - return; - - gs_debug ("Adding embedded keyboard widget"); - - /* FIXME: verify command is safe */ - - gs_debug ("Running command: %s", window->priv->keyboard_command); - - res = spawn_on_window (window, - window->priv->keyboard_command, - &window->priv->keyboard_pid, - (GIOFunc)keyboard_command_watch, - window, - &window->priv->keyboard_watch_id); - if (! res) - { - gs_debug ("Could not start command: %s", window->priv->keyboard_command); - } -} - -static void -create_lock_socket (GSWindow *window, - guint32 id) -{ - window->priv->lock_socket = gtk_socket_new (); - window->priv->lock_box = gtk_alignment_new (0.5, 0.5, 0, 0); - gtk_widget_show (window->priv->lock_box); - gtk_box_pack_start (GTK_BOX (window->priv->vbox), window->priv->lock_box, TRUE, TRUE, 0); - - gtk_container_add (GTK_CONTAINER (window->priv->lock_box), window->priv->lock_socket); - - g_signal_connect (window->priv->lock_socket, "show", - G_CALLBACK (lock_socket_show), window); - g_signal_connect (window->priv->lock_socket, "destroy", - G_CALLBACK (lock_socket_destroyed), window); - g_signal_connect (window->priv->lock_socket, "plug_added", - G_CALLBACK (lock_plug_added), window); - g_signal_connect (window->priv->lock_socket, "plug_removed", - G_CALLBACK (lock_plug_removed), window); - - gtk_socket_add_id (GTK_SOCKET (window->priv->lock_socket), id); - - if (window->priv->keyboard_enabled) - { - embed_keyboard (window); - } -} - -static void -gs_window_dialog_finish (GSWindow *window) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - gs_debug ("Dialog finished"); - - /* make sure we finish the keyboard thing too */ - keyboard_command_finish (window); - - /* send a signal just in case */ - kill_dialog_command (window); - - if (window->priv->lock_pid > 0) - { - int exit_status; - - exit_status = wait_on_child (window->priv->lock_pid); - - g_spawn_close_pid (window->priv->lock_pid); - window->priv->lock_pid = 0; - } - - /* remove events for the case were we failed to show socket */ - remove_key_events (window); -} - -static void -maybe_kill_dialog (GSWindow *window) -{ - if (!window->priv->dialog_shake_in_progress - && window->priv->dialog_quit_requested - && window->priv->lock_pid > 0) - { - kill (window->priv->lock_pid, SIGTERM); - } -} - -/* very rudimentary animation for indicating an auth failure */ -static void -shake_dialog (GSWindow *window) -{ - int i; - guint left; - guint right; - - window->priv->dialog_shake_in_progress = TRUE; - - for (i = 0; i < 9; i++) - { - if (i % 2 == 0) - { - left = 30; - right = 0; - } - else - { - left = 0; - right = 30; - } - - if (! window->priv->lock_box) - { - break; - } - - gtk_alignment_set_padding (GTK_ALIGNMENT (window->priv->lock_box), - 0, 0, - left, - right); - - while (gtk_events_pending ()) - { - gtk_main_iteration (); - } - - g_usleep (10000); - } - - window->priv->dialog_shake_in_progress = FALSE; - maybe_kill_dialog (window); -} - -static void -window_set_dialog_up (GSWindow *window, - gboolean dialog_up) -{ - if (window->priv->dialog_up == dialog_up) - { - return; - } - - window->priv->dialog_up = dialog_up; - g_object_notify (G_OBJECT (window), "dialog-up"); -} - -static void -popdown_dialog (GSWindow *window) -{ - gs_window_dialog_finish (window); - - gtk_widget_show (window->priv->drawing_area); - - gs_window_clear (window); - set_invisible_cursor (GTK_WIDGET (window)->window, TRUE); - - window_set_dialog_up (window, FALSE); - - /* reset the pointer positions */ - window->priv->last_x = -1; - window->priv->last_y = -1; - - if (window->priv->lock_box != NULL) - { - gtk_container_remove (GTK_CONTAINER (window->priv->vbox), GTK_WIDGET (window->priv->lock_box)); - window->priv->lock_box = NULL; - } - - remove_popup_dialog_idle (window); - remove_command_watches (window); -} - -static gboolean -lock_command_watch (GIOChannel *source, - GIOCondition condition, - GSWindow *window) -{ - gboolean finished = FALSE; - - g_return_val_if_fail (GS_IS_WINDOW (window), FALSE); - - if (condition & G_IO_IN) - { - GIOStatus status; - GError *error = NULL; - char *line; - - line = NULL; - status = g_io_channel_read_line (source, &line, NULL, NULL, &error); - - switch (status) - { - case G_IO_STATUS_NORMAL: - gs_debug ("command output: %s", line); - - if (strstr (line, "WINDOW ID=") != NULL) - { - guint32 id; - char c; - if (1 == sscanf (line, " WINDOW ID= %" G_GUINT32_FORMAT " %c", &id, &c)) - { - create_lock_socket (window, id); - } - } - else if (strstr (line, "NOTICE=") != NULL) - { - if (strstr (line, "NOTICE=AUTH FAILED") != NULL) - { - shake_dialog (window); - } - } - else if (strstr (line, "RESPONSE=") != NULL) - { - if (strstr (line, "RESPONSE=OK") != NULL) - { - gs_debug ("Got OK response"); - window->priv->dialog_response = DIALOG_RESPONSE_OK; - } - else - { - gs_debug ("Got CANCEL response"); - window->priv->dialog_response = DIALOG_RESPONSE_CANCEL; - } - finished = TRUE; - } - else if (strstr (line, "REQUEST QUIT") != NULL) - { - gs_debug ("Got request for quit"); - window->priv->dialog_quit_requested = TRUE; - maybe_kill_dialog (window); - } - break; - case G_IO_STATUS_EOF: - finished = TRUE; - break; - case G_IO_STATUS_ERROR: - finished = TRUE; - gs_debug ("Error reading from child: %s\n", error->message); - g_error_free (error); - return FALSE; - case G_IO_STATUS_AGAIN: - default: - break; - } - - g_free (line); - } - else if (condition & G_IO_HUP) - { - finished = TRUE; - } - - if (finished) - { - popdown_dialog (window); - - if (window->priv->dialog_response == DIALOG_RESPONSE_OK) - { - add_emit_deactivated_idle (window); - } - - window->priv->lock_watch_id = 0; - - return FALSE; - } - - return TRUE; -} - -static gboolean -is_logout_enabled (GSWindow *window) -{ - double elapsed; - - if (! window->priv->logout_enabled) - { - return FALSE; - } - - if (! window->priv->logout_command) - { - return FALSE; - } - - elapsed = g_timer_elapsed (window->priv->timer, NULL); - - if (window->priv->logout_timeout < (elapsed * 1000)) - { - return TRUE; - } - - return FALSE; -} - -static gboolean -is_user_switch_enabled (GSWindow *window) -{ - return window->priv->user_switch_enabled; -} - -static void -popup_dialog (GSWindow *window) -{ - gboolean result; - char *tmp; - GString *command; - - gs_debug ("Popping up dialog"); - - tmp = g_build_filename (LIBEXECDIR, "mate-screensaver-dialog", NULL); - command = g_string_new (tmp); - g_free (tmp); - - if (is_logout_enabled (window)) - { - command = g_string_append (command, " --enable-logout"); - g_string_append_printf (command, " --logout-command='%s'", window->priv->logout_command); - } - - if (window->priv->status_message) - { - char *quoted; - - quoted = g_shell_quote (window->priv->status_message); - g_string_append_printf (command, " --status-message=%s", quoted); - g_free (quoted); - } - - if (is_user_switch_enabled (window)) - { - command = g_string_append (command, " --enable-switch"); - } - - if (gs_debug_enabled ()) - { - command = g_string_append (command, " --verbose"); - } - - gtk_widget_hide (window->priv->drawing_area); - - gs_window_clear_to_background_pixmap (window); - - set_invisible_cursor (GTK_WIDGET (window)->window, FALSE); - - window->priv->dialog_quit_requested = FALSE; - window->priv->dialog_shake_in_progress = FALSE; - - result = spawn_on_window (window, - command->str, - &window->priv->lock_pid, - (GIOFunc)lock_command_watch, - window, - &window->priv->lock_watch_id); - if (! result) - { - gs_debug ("Could not start command: %s", command->str); - } - - g_string_free (command, TRUE); -} - -static gboolean -popup_dialog_idle (GSWindow *window) -{ - popup_dialog (window); - - window->priv->popup_dialog_idle_id = 0; - - return FALSE; -} - -void -gs_window_request_unlock (GSWindow *window) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - gs_debug ("Requesting unlock"); - - if (! GTK_WIDGET_VISIBLE (GTK_WIDGET (window))) - { - gs_debug ("Request unlock but window is not visible!"); - return; - } - - if (window->priv->lock_watch_id > 0) - { - return; - } - - if (! window->priv->lock_enabled) - { - add_emit_deactivated_idle (window); - - return; - } - - if (window->priv->popup_dialog_idle_id == 0) - { - add_popup_dialog_idle (window); - } - - window_set_dialog_up (window, TRUE); -} - -void -gs_window_cancel_unlock_request (GSWindow *window) -{ - /* FIXME: This is a bit of a hammer approach... - * Maybe we should send a delete-event to - * the plug? - */ - g_return_if_fail (GS_IS_WINDOW (window)); - - popdown_dialog (window); -} - -void -gs_window_set_lock_enabled (GSWindow *window, - gboolean lock_enabled) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - if (window->priv->lock_enabled == lock_enabled) - { - return; - } - - window->priv->lock_enabled = lock_enabled; - g_object_notify (G_OBJECT (window), "lock-enabled"); -} - -void -gs_window_set_screen (GSWindow *window, - GdkScreen *screen) -{ - - g_return_if_fail (GS_IS_WINDOW (window)); - g_return_if_fail (GDK_IS_SCREEN (screen)); - - gtk_window_set_screen (GTK_WINDOW (window), screen); -} - -GdkScreen * -gs_window_get_screen (GSWindow *window) -{ - g_return_val_if_fail (GS_IS_WINDOW (window), NULL); - - return GTK_WINDOW (window)->screen; -} - -void -gs_window_set_keyboard_enabled (GSWindow *window, - gboolean enabled) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - window->priv->keyboard_enabled = enabled; -} - -void -gs_window_set_keyboard_command (GSWindow *window, - const char *command) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - g_free (window->priv->keyboard_command); - - if (command != NULL) - { - window->priv->keyboard_command = g_strdup (command); - } - else - { - window->priv->keyboard_command = NULL; - } -} - -void -gs_window_set_logout_enabled (GSWindow *window, - gboolean logout_enabled) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - window->priv->logout_enabled = logout_enabled; -} - -void -gs_window_set_user_switch_enabled (GSWindow *window, - gboolean user_switch_enabled) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - window->priv->user_switch_enabled = user_switch_enabled; -} - -void -gs_window_set_logout_timeout (GSWindow *window, - glong logout_timeout) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - if (logout_timeout < 0) - { - window->priv->logout_timeout = 0; - } - else - { - window->priv->logout_timeout = logout_timeout; - } -} - -void -gs_window_set_logout_command (GSWindow *window, - const char *command) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - g_free (window->priv->logout_command); - - if (command) - { - window->priv->logout_command = g_strdup (command); - } - else - { - window->priv->logout_command = NULL; - } -} - -void -gs_window_set_status_message (GSWindow *window, - const char *status_message) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - g_free (window->priv->status_message); - window->priv->status_message = g_strdup (status_message); -} - -void -gs_window_set_monitor (GSWindow *window, - int monitor) -{ - g_return_if_fail (GS_IS_WINDOW (window)); - - if (window->priv->monitor == monitor) - { - return; - } - - window->priv->monitor = monitor; - - gtk_widget_queue_resize (GTK_WIDGET (window)); - - g_object_notify (G_OBJECT (window), "monitor"); -} - -int -gs_window_get_monitor (GSWindow *window) -{ - g_return_val_if_fail (GS_IS_WINDOW (window), -1); - - return window->priv->monitor; -} - -static void -gs_window_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GSWindow *self; - - self = GS_WINDOW (object); - - switch (prop_id) - { - case PROP_LOCK_ENABLED: - gs_window_set_lock_enabled (self, g_value_get_boolean (value)); - break; - case PROP_KEYBOARD_ENABLED: - gs_window_set_keyboard_enabled (self, g_value_get_boolean (value)); - break; - case PROP_KEYBOARD_COMMAND: - gs_window_set_keyboard_command (self, g_value_get_string (value)); - break; - case PROP_LOGOUT_ENABLED: - gs_window_set_logout_enabled (self, g_value_get_boolean (value)); - break; - case PROP_LOGOUT_COMMAND: - gs_window_set_logout_command (self, g_value_get_string (value)); - break; - case PROP_STATUS_MESSAGE: - gs_window_set_status_message (self, g_value_get_string (value)); - break; - case PROP_LOGOUT_TIMEOUT: - gs_window_set_logout_timeout (self, g_value_get_long (value)); - break; - case PROP_MONITOR: - gs_window_set_monitor (self, g_value_get_int (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gs_window_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GSWindow *self; - - self = GS_WINDOW (object); - - switch (prop_id) - { - case PROP_LOCK_ENABLED: - g_value_set_boolean (value, self->priv->lock_enabled); - break; - case PROP_KEYBOARD_ENABLED: - g_value_set_boolean (value, self->priv->keyboard_enabled); - break; - case PROP_KEYBOARD_COMMAND: - g_value_set_string (value, self->priv->keyboard_command); - break; - case PROP_LOGOUT_ENABLED: - g_value_set_boolean (value, self->priv->logout_enabled); - break; - case PROP_LOGOUT_COMMAND: - g_value_set_string (value, self->priv->logout_command); - break; - case PROP_STATUS_MESSAGE: - g_value_set_string (value, self->priv->status_message); - break; - case PROP_LOGOUT_TIMEOUT: - g_value_set_long (value, self->priv->logout_timeout); - break; - case PROP_MONITOR: - g_value_set_int (value, self->priv->monitor); - break; - case PROP_OBSCURED: - g_value_set_boolean (value, self->priv->obscured); - break; - case PROP_DIALOG_UP: - g_value_set_boolean (value, self->priv->dialog_up); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -queue_key_event (GSWindow *window, - GdkEventKey *event) -{ - /* Eat the first return, enter, escape, or space */ - if (window->priv->key_events == NULL - && (event->keyval == GDK_Return - || event->keyval == GDK_KP_Enter - || event->keyval == GDK_Escape - || event->keyval == GDK_space)) - { - return; - } - - /* Only cache MAX_QUEUED_EVENTS key events. If there are any more than this then - something is wrong */ - /* Don't queue keys that may cause focus navigation in the dialog */ - if (g_list_length (window->priv->key_events) < MAX_QUEUED_EVENTS - && event->keyval != GDK_Tab - && event->keyval != GDK_Up - && event->keyval != GDK_Down) - { - window->priv->key_events = g_list_prepend (window->priv->key_events, - gdk_event_copy ((GdkEvent *)event)); - } -} - -static gboolean -maybe_handle_activity (GSWindow *window) -{ - gboolean handled; - - handled = FALSE; - - /* if we already have a socket then don't bother */ - if (! window->priv->lock_socket - && GTK_WIDGET_IS_SENSITIVE (GTK_WIDGET (window))) - { - g_signal_emit (window, signals [ACTIVITY], 0, &handled); - } - - return handled; -} - -static gboolean -gs_window_real_key_press_event (GtkWidget *widget, - GdkEventKey *event) -{ - /*g_message ("KEY PRESS state: %u keyval %u", event->state, event->keyval);*/ - - /* Ignore brightness keys */ - if (event->hardware_keycode == 101 || event->hardware_keycode == 212) - { - gs_debug ("Ignoring brightness keys"); - return TRUE; - } - - maybe_handle_activity (GS_WINDOW (widget)); - - queue_key_event (GS_WINDOW (widget), event); - - if (GTK_WIDGET_CLASS (gs_window_parent_class)->key_press_event) - { - GTK_WIDGET_CLASS (gs_window_parent_class)->key_press_event (widget, event); - } - - return TRUE; -} - -static gboolean -gs_window_real_motion_notify_event (GtkWidget *widget, - GdkEventMotion *event) -{ - GSWindow *window; - gdouble distance; - gdouble min_distance; - gdouble min_percentage = 0.1; - GdkScreen *screen; - - window = GS_WINDOW (widget); - - screen = gs_window_get_screen (window); - min_distance = gdk_screen_get_width (screen) * min_percentage; - - /* if the last position was not set then don't detect motion */ - if (window->priv->last_x < 0 || window->priv->last_y < 0) - { - window->priv->last_x = event->x; - window->priv->last_y = event->y; - - return FALSE; - } - - /* just an approximate distance */ - distance = MAX (ABS (window->priv->last_x - event->x), - ABS (window->priv->last_y - event->y)); - - if (distance > min_distance) - { - maybe_handle_activity (window); - - window->priv->last_x = -1; - window->priv->last_y = -1; - } - - return FALSE; -} - -static gboolean -gs_window_real_button_press_event (GtkWidget *widget, - GdkEventButton *event) -{ - GSWindow *window; - - window = GS_WINDOW (widget); - maybe_handle_activity (window); - - return FALSE; -} - -static gboolean -gs_window_real_scroll_event (GtkWidget *widget, - GdkEventScroll *event) -{ - GSWindow *window; - - window = GS_WINDOW (widget); - maybe_handle_activity (window); - - return FALSE; -} - -static void -gs_window_real_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - GSWindow *window; - GtkBin *bin; - GdkRectangle old_geometry; - int position_changed = FALSE; - int size_changed = FALSE; - - window = GS_WINDOW (widget); - bin = GTK_BIN (widget); - - if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) - { - gtk_widget_size_request (bin->child, requisition); - } - - old_geometry = window->priv->geometry; - - update_geometry (window); - - requisition->width = window->priv->geometry.width; - requisition->height = window->priv->geometry.height; - - if (! GTK_WIDGET_REALIZED (widget)) - { - return; - } - - if (old_geometry.width != window->priv->geometry.width || - old_geometry.height != window->priv->geometry.height) - { - size_changed = TRUE; - } - - if (old_geometry.x != window->priv->geometry.x || - old_geometry.y != window->priv->geometry.y) - { - position_changed = TRUE; - } - - gs_window_move_resize_window (window, position_changed, size_changed); -} - -static gboolean -gs_window_real_grab_broken (GtkWidget *widget, - GdkEventGrabBroken *event) -{ - if (event->grab_window != NULL) - { - gs_debug ("Grab broken on window %X %s, new grab on window %X", - (guint32) GDK_WINDOW_XID (event->window), - event->keyboard ? "keyboard" : "pointer", - (guint32) GDK_WINDOW_XID (event->grab_window)); - } - else - { - gs_debug ("Grab broken on window %X %s, new grab is outside application", - (guint32) GDK_WINDOW_XID (event->window), - event->keyboard ? "keyboard" : "pointer"); - } - - return FALSE; -} - -gboolean -gs_window_is_obscured (GSWindow *window) -{ - g_return_val_if_fail (GS_IS_WINDOW (window), FALSE); - - return window->priv->obscured; -} - -gboolean -gs_window_is_dialog_up (GSWindow *window) -{ - g_return_val_if_fail (GS_IS_WINDOW (window), FALSE); - - return window->priv->dialog_up; -} - -static void -window_set_obscured (GSWindow *window, - gboolean obscured) -{ - if (window->priv->obscured == obscured) - { - return; - } - - window->priv->obscured = obscured; - g_object_notify (G_OBJECT (window), "obscured"); -} - -static gboolean -gs_window_real_visibility_notify_event (GtkWidget *widget, - GdkEventVisibility *event) -{ - switch (event->state) - { - case GDK_VISIBILITY_FULLY_OBSCURED: - window_set_obscured (GS_WINDOW (widget), TRUE); - break; - case GDK_VISIBILITY_PARTIAL: - break; - case GDK_VISIBILITY_UNOBSCURED: - window_set_obscured (GS_WINDOW (widget), FALSE); - break; - default: - break; - } - - return FALSE; -} - -static void -gs_window_class_init (GSWindowClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - - object_class->finalize = gs_window_finalize; - object_class->get_property = gs_window_get_property; - object_class->set_property = gs_window_set_property; - - widget_class->show = gs_window_real_show; - widget_class->hide = gs_window_real_hide; - widget_class->realize = gs_window_real_realize; - widget_class->unrealize = gs_window_real_unrealize; - widget_class->key_press_event = gs_window_real_key_press_event; - widget_class->motion_notify_event = gs_window_real_motion_notify_event; - widget_class->button_press_event = gs_window_real_button_press_event; - widget_class->scroll_event = gs_window_real_scroll_event; - widget_class->size_request = gs_window_real_size_request; - widget_class->grab_broken_event = gs_window_real_grab_broken; - widget_class->visibility_notify_event = gs_window_real_visibility_notify_event; - - g_type_class_add_private (klass, sizeof (GSWindowPrivate)); - - signals [ACTIVITY] = - g_signal_new ("activity", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GSWindowClass, activity), - NULL, - NULL, - gs_marshal_BOOLEAN__VOID, - G_TYPE_BOOLEAN, - 0); - signals [DEACTIVATED] = - g_signal_new ("deactivated", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GSWindowClass, deactivated), - NULL, - NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, - 0); - - g_object_class_install_property (object_class, - PROP_OBSCURED, - g_param_spec_boolean ("obscured", - NULL, - NULL, - FALSE, - G_PARAM_READABLE)); - g_object_class_install_property (object_class, - PROP_DIALOG_UP, - g_param_spec_boolean ("dialog-up", - NULL, - NULL, - FALSE, - G_PARAM_READABLE)); - g_object_class_install_property (object_class, - PROP_LOCK_ENABLED, - g_param_spec_boolean ("lock-enabled", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_LOGOUT_ENABLED, - g_param_spec_boolean ("logout-enabled", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_LOGOUT_TIMEOUT, - g_param_spec_long ("logout-timeout", - NULL, - NULL, - -1, - G_MAXLONG, - 0, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_LOGOUT_COMMAND, - g_param_spec_string ("logout-command", - NULL, - NULL, - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_STATUS_MESSAGE, - g_param_spec_string ("status-message", - NULL, - NULL, - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_KEYBOARD_ENABLED, - g_param_spec_boolean ("keyboard-enabled", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_KEYBOARD_COMMAND, - g_param_spec_string ("keyboard-command", - NULL, - NULL, - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, - PROP_MONITOR, - g_param_spec_int ("monitor", - "Xinerama monitor", - "The monitor (in terms of Xinerama) which the window is on", - 0, - G_MAXINT, - 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - -} - -static void -create_info_bar (GSWindow *window) -{ - window->priv->info_bar = gtk_info_bar_new (); - gtk_widget_set_no_show_all (window->priv->info_bar, TRUE); - gtk_box_pack_end (GTK_BOX (window->priv->vbox), window->priv->info_bar, FALSE, FALSE, 0); -} - -static void -gs_window_init (GSWindow *window) -{ - window->priv = GS_WINDOW_GET_PRIVATE (window); - - window->priv->geometry.x = -1; - window->priv->geometry.y = -1; - window->priv->geometry.width = -1; - window->priv->geometry.height = -1; - - window->priv->last_x = -1; - window->priv->last_y = -1; - - gtk_window_set_decorated (GTK_WINDOW (window), FALSE); - - gtk_window_set_skip_taskbar_hint (GTK_WINDOW (window), TRUE); - gtk_window_set_skip_pager_hint (GTK_WINDOW (window), TRUE); - - gtk_window_set_keep_above (GTK_WINDOW (window), TRUE); - - gtk_window_fullscreen (GTK_WINDOW (window)); - - gtk_widget_set_events (GTK_WIDGET (window), - gtk_widget_get_events (GTK_WIDGET (window)) - | GDK_POINTER_MOTION_MASK - | GDK_BUTTON_PRESS_MASK - | GDK_BUTTON_RELEASE_MASK - | GDK_KEY_PRESS_MASK - | GDK_KEY_RELEASE_MASK - | GDK_EXPOSURE_MASK - | GDK_VISIBILITY_NOTIFY_MASK - | GDK_ENTER_NOTIFY_MASK - | GDK_LEAVE_NOTIFY_MASK); - - window->priv->vbox = gtk_vbox_new (FALSE, 12); - gtk_widget_show (window->priv->vbox); - gtk_container_add (GTK_CONTAINER (window), window->priv->vbox); - - window->priv->drawing_area = gtk_drawing_area_new (); - gtk_widget_show (window->priv->drawing_area); - gtk_box_pack_start (GTK_BOX (window->priv->vbox), window->priv->drawing_area, TRUE, TRUE, 0); - create_info_bar (window); - - force_no_pixmap_background (window->priv->drawing_area); -} - -static void -remove_command_watches (GSWindow *window) -{ - if (window->priv->lock_watch_id != 0) - { - g_source_remove (window->priv->lock_watch_id); - window->priv->lock_watch_id = 0; - } - if (window->priv->keyboard_watch_id != 0) - { - g_source_remove (window->priv->keyboard_watch_id); - window->priv->keyboard_watch_id = 0; - } -} - -static void -gs_window_finalize (GObject *object) -{ - GSWindow *window; - - g_return_if_fail (object != NULL); - g_return_if_fail (GS_IS_WINDOW (object)); - - window = GS_WINDOW (object); - - g_return_if_fail (window->priv != NULL); - - g_free (window->priv->logout_command); - g_free (window->priv->keyboard_command); - - if (window->priv->info_bar_timer_id > 0) - { - g_source_remove (window->priv->info_bar_timer_id); - } - - remove_watchdog_timer (window); - remove_popup_dialog_idle (window); - - if (window->priv->timer) - { - g_timer_destroy (window->priv->timer); - } - - remove_key_events (window); - - remove_command_watches (window); - - gs_window_dialog_finish (window); - - if (window->priv->background_pixmap) - { - g_object_unref (window->priv->background_pixmap); - } - - G_OBJECT_CLASS (gs_window_parent_class)->finalize (object); -} - -GSWindow * -gs_window_new (GdkScreen *screen, - int monitor, - gboolean lock_enabled) -{ - GObject *result; - - result = g_object_new (GS_TYPE_WINDOW, - "type", GTK_WINDOW_POPUP, - "screen", screen, - "monitor", monitor, - "lock-enabled", lock_enabled, - NULL); - - return GS_WINDOW (result); -} |