diff options
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | gui/simple-greeter/gdm-greeter-background.c | 332 | ||||
-rw-r--r-- | gui/simple-greeter/gdm-greeter-panel.c | 7 | ||||
-rw-r--r-- | gui/simple-greeter/gdm-simple-greeter.c | 2 |
4 files changed, 307 insertions, 53 deletions
@@ -1,3 +1,20 @@ +2007-10-05 William Jon McCann <mccann@jhu.edu> + + * gui/simple-greeter/gdm-greeter-background.c: + (cairo_surface_get_width), (cairo_surface_get_height), + (update_surface), (load_image), (update_background), + (gdm_greeter_background_move_resize_window), (get_outside_region), + (get_monitor_geometry), (update_geometry), + (gdm_greeter_background_real_size_request), + (gdm_greeter_background_real_expose), + (gdm_greeter_background_real_configure), + (gdm_greeter_background_class_init): + * gui/simple-greeter/gdm-greeter-panel.c: (gdm_greeter_panel_init): + * gui/simple-greeter/gdm-simple-greeter.c: (create_greeter): + Make the background window sizing more robust. And a little + more efficient. Also add some tranparency to the windows + when running under a compositor. + 2007-10-04 William Jon McCann <mccann@jhu.edu> * daemon/main.c: (set_effective_user), (set_effective_group), @@ -6,8 +23,6 @@ 2007-10-04 William Jon McCann <mccann@jhu.edu> - reviewed by: <delete if not using a buddy> - * AUTHORS: Add myself. diff --git a/gui/simple-greeter/gdm-greeter-background.c b/gui/simple-greeter/gdm-greeter-background.c index 4da8fd14..3ca3fbd3 100644 --- a/gui/simple-greeter/gdm-greeter-background.c +++ b/gui/simple-greeter/gdm-greeter-background.c @@ -30,6 +30,11 @@ #include <glib-object.h> #include <gtk/gtk.h> +#include <cairo.h> +#if CAIRO_HAS_XLIB_SURFACE +#include <cairo-xlib.h> +#endif + #include <gconf/gconf-client.h> #include "gdm-greeter-background.h" @@ -53,8 +58,8 @@ typedef enum { struct GdmGreeterBackgroundPrivate { - int window_width; - int window_height; + int monitor; + GdkRectangle geometry; gboolean background_enabled; char *image_filename; @@ -309,6 +314,96 @@ scale_pixbuf (GdkPixbuf *pixbuf, } } +static int +cairo_surface_get_width (cairo_surface_t *surface) +{ + cairo_surface_type_t surf_type; + int w; + + surf_type = cairo_surface_get_type (surface); + + w = 0; + + switch (surf_type) { +#if CAIRO_HAS_XLIB_SURFACE + case CAIRO_SURFACE_TYPE_XLIB: + w = cairo_xlib_surface_get_width (surface); + break; +#endif + case CAIRO_SURFACE_TYPE_IMAGE: + w = cairo_image_surface_get_width (surface); + break; + default: + g_warning ("Unknown surface type: %d", surf_type); + break; + } + + return w; +} + +static int +cairo_surface_get_height (cairo_surface_t *surface) +{ + cairo_surface_type_t surf_type; + int w; + + surf_type = cairo_surface_get_type (surface); + + w = 0; + + g_debug ("Surface type %d", surf_type); + switch (surf_type) { +#if CAIRO_HAS_XLIB_SURFACE + case CAIRO_SURFACE_TYPE_XLIB: + w = cairo_xlib_surface_get_height (surface); + break; +#endif + case CAIRO_SURFACE_TYPE_IMAGE: + w = cairo_image_surface_get_height (surface); + break; + default: + g_warning ("Unknown surface type: %d", surf_type); + break; + } + + return w; +} + +static void +update_surface (GdmGreeterBackground *background) +{ + + g_assert (GTK_WIDGET_REALIZED (GTK_WIDGET (background))); + + if (background->priv->surf == NULL + || cairo_surface_get_width (background->priv->surf) != background->priv->geometry.width + || cairo_surface_get_height (background->priv->surf) != background->priv->geometry.height) { + cairo_t *cr; + + if (background->priv->surf != NULL) { + g_debug ("Destroying existing surface w:%d h:%d", + cairo_image_surface_get_width (background->priv->surf), + cairo_image_surface_get_height (background->priv->surf)); + cairo_surface_destroy (background->priv->surf); + } + + g_debug ("Creating a new surface for the background w:%d h:%d", + background->priv->geometry.width, + background->priv->geometry.height); + + cr = gdk_cairo_create (GTK_WIDGET (background)->window); + background->priv->surf = cairo_surface_create_similar (cairo_get_target (cr), + CAIRO_CONTENT_COLOR, + background->priv->geometry.width, + background->priv->geometry.height); + g_debug ("Created surface w:%d h:%d", + cairo_surface_get_width (background->priv->surf), + cairo_surface_get_height (background->priv->surf)); + cairo_destroy (cr); + } + +} + static void load_image (GdmGreeterBackground *background) { @@ -316,14 +411,21 @@ load_image (GdmGreeterBackground *background) GdkPixbuf *scaled; cairo_t *cr; int pw, ph; - cairo_surface_t *image; + GError *error; - pixbuf = gdk_pixbuf_new_from_file (background->priv->image_filename, NULL); + g_debug ("Loading background from %s", background->priv->image_filename); + error = NULL; + pixbuf = gdk_pixbuf_new_from_file (background->priv->image_filename, &error); if (pixbuf == NULL) { + g_warning ("Unable to load image: %s", error->message); + g_error_free (error); return; } - scaled = scale_pixbuf (pixbuf, background->priv->window_width, background->priv->window_height, TRUE); + scaled = scale_pixbuf (pixbuf, + background->priv->geometry.width, + background->priv->geometry.height, + TRUE); if (scaled != NULL) { g_object_unref (pixbuf); pixbuf = scaled; @@ -336,14 +438,15 @@ load_image (GdmGreeterBackground *background) cairo_pattern_destroy (background->priv->pat); } - image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - pw, - ph); + update_surface (background); + + g_assert (background->priv->surf != NULL); cr = cairo_create (background->priv->surf); /* XXX Handle out of memory? */ gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); + background->priv->pat = cairo_pattern_reference (cairo_get_source (cr)); background->priv->pat_width = pw; background->priv->pat_height = ph; @@ -357,17 +460,19 @@ update_background (GdmGreeterBackground *background) { cairo_t *cr; - if (background->priv->window_width <= 0 - || background->priv->window_height <= 0) { + if (background->priv->geometry.width <= 0 + || background->priv->geometry.height <= 0) { /* we haven't gotten a configure yet - so don't bother */ return; } cr = gdk_cairo_create (GTK_WIDGET (background)->window); + g_debug ("Clearing background"); + /* always clear to black */ cairo_set_source_rgb (cr, 0, 0, 0); - cairo_rectangle (cr, 0, 0, background->priv->window_width, background->priv->window_height); + cairo_rectangle (cr, 0, 0, background->priv->geometry.width, background->priv->geometry.height); cairo_fill (cr); if (background->priv->image_filename != NULL @@ -381,18 +486,23 @@ update_background (GdmGreeterBackground *background) if (background->priv->image_placement == BACKGROUND_SCALED) { double sx, sy; - sx = (double)background->priv->window_width / background->priv->pat_width; - sy = (double)background->priv->window_height / background->priv->pat_height; + sx = (double)background->priv->geometry.width / background->priv->pat_width; + sy = (double)background->priv->geometry.height / background->priv->pat_height; cairo_scale (cr, sx, sy); - g_debug ("scaling w:%d sx:%f sy:%f", background->priv->window_width, sx, sy); + if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) { + g_warning ("couldn't scale background: %s", cairo_status_to_string (cairo_status (cr))); + } + + g_debug ("scaling w:%d sx:%f sy:%f", background->priv->geometry.width, sx, sy); cairo_pattern_set_extend (background->priv->pat, CAIRO_EXTEND_NONE); + } else if (background->priv->image_placement == BACKGROUND_SCALED_ASPECT) { double sx, sy, s; double dx, dy; - sx = (double)background->priv->window_width / background->priv->pat_width; - sy = (double)background->priv->window_height / background->priv->pat_height; + sx = (double)background->priv->geometry.width / background->priv->pat_width; + sy = (double)background->priv->geometry.height / background->priv->pat_height; /* scale up long dimension */ s = MIN (sx, sy); @@ -401,12 +511,12 @@ update_background (GdmGreeterBackground *background) dx = dy = 0; /* now center short dimension */ if (sy > sx) { - dy = (double)background->priv->window_height - background->priv->pat_height * s; + dy = (double)background->priv->geometry.height - background->priv->pat_height * s; } else { - dx = (double)background->priv->window_width - background->priv->pat_width * s; + dx = (double)background->priv->geometry.width - background->priv->pat_width * s; } cairo_translate (cr, dx / 2, dy / 2); - g_debug ("aspect scaling w:%d scale:%f dx:%f dy:%f", background->priv->window_width, s, dx, dy); + g_debug ("aspect scaling w:%d scale:%f dx:%f dy:%f", background->priv->geometry.width, s, dx, dy); cairo_pattern_set_extend (background->priv->pat, CAIRO_EXTEND_NONE); } else if (background->priv->image_placement == BACKGROUND_TILED) { @@ -415,25 +525,32 @@ update_background (GdmGreeterBackground *background) /* centered */ double dx, dy; - dx = (double)background->priv->window_width - background->priv->pat_width; - dy = (double)background->priv->window_height - background->priv->pat_height; + dx = (double)background->priv->geometry.width - background->priv->pat_width; + dy = (double)background->priv->geometry.height - background->priv->pat_height; cairo_translate (cr, dx / 2, dy / 2); g_debug ("centering dx:%f dy:%f", dx, dy); cairo_pattern_set_extend (background->priv->pat, CAIRO_EXTEND_NONE); } + g_debug ("Painting background with alpha %f", background->priv->image_alpha); cairo_set_source (cr, background->priv->pat); + if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) { + g_warning ("couldn't set pattern source: %s", cairo_status_to_string (cairo_status (cr))); + } cairo_paint_with_alpha (cr, background->priv->image_alpha); + if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) { + g_warning ("couldn't paint background: %s", cairo_status_to_string (cairo_status (cr))); + } } else if (background->priv->color_shading != COLOR_SHADING_SOLID) { cairo_pattern_t *pat; g_debug ("color gradient"); if (background->priv->color_shading == COLOR_SHADING_VERTICAL) { - pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, background->priv->window_height); + pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, background->priv->geometry.height); } else { - pat = cairo_pattern_create_linear (0.0, 0.0, background->priv->window_width, 0.0); + pat = cairo_pattern_create_linear (0.0, 0.0, background->priv->geometry.width, 0.0); } cairo_pattern_add_color_stop_rgba (pat, @@ -451,7 +568,7 @@ update_background (GdmGreeterBackground *background) cairo_set_source (cr, pat); - cairo_rectangle (cr, 0, 0, background->priv->window_width, background->priv->window_height); + cairo_rectangle (cr, 0, 0, background->priv->geometry.width, background->priv->geometry.height); cairo_fill (cr); cairo_pattern_destroy (pat); } else { @@ -461,7 +578,7 @@ update_background (GdmGreeterBackground *background) background->priv->color1.green / 65535.0, background->priv->color1.blue / 65535.0, 1.0); - cairo_rectangle (cr, 0, 0, background->priv->window_width, background->priv->window_height); + cairo_rectangle (cr, 0, 0, background->priv->geometry.width, background->priv->geometry.height); cairo_fill (cr); } @@ -538,38 +655,138 @@ gdm_greeter_background_real_unrealize (GtkWidget *widget) GTK_WIDGET_CLASS (gdm_greeter_background_parent_class)->unrealize (widget); } } -static gboolean -gdm_greeter_background_real_configure (GtkWidget *widget, - GdkEventConfigure *event) + +/* copied from panel-toplevel.c */ +static void +gdm_greeter_background_move_resize_window (GdmGreeterBackground *background, + gboolean move, + gboolean resize) { - gboolean handled = FALSE; - GdmGreeterBackground *background = GDM_GREETER_BACKGROUND (widget); - cairo_t *cr; + GtkWidget *widget; + + widget = GTK_WIDGET (background); + + g_assert (GTK_WIDGET_REALIZED (widget)); + + if (move && resize) { + gdk_window_move_resize (widget->window, + background->priv->geometry.x, + background->priv->geometry.y, + background->priv->geometry.width, + background->priv->geometry.height); + } else if (move) { + gdk_window_move (widget->window, + background->priv->geometry.x, + background->priv->geometry.y); + } else if (resize) { + gdk_window_resize (widget->window, + background->priv->geometry.width, + background->priv->geometry.height); + } +} + +static GdkRegion * +get_outside_region (GdmGreeterBackground *background) +{ + int i; + GdkRegion *region; - g_debug ("configure w: %d h: %d", event->width, event->height); - background->priv->window_width = event->width; - background->priv->window_height = event->height; + region = gdk_region_new (); + for (i = 0; i < background->priv->monitor; i++) { + GdkRectangle geometry; - if (background->priv->surf != NULL) { - cairo_surface_destroy (background->priv->surf); + gdk_screen_get_monitor_geometry (GTK_WINDOW (background)->screen, + i, + &geometry); + gdk_region_union_with_rect (region, &geometry); } - cr = gdk_cairo_create (widget->window); - background->priv->surf = cairo_surface_create_similar (cairo_get_target (cr), - CAIRO_CONTENT_COLOR, - background->priv->window_width, - background->priv->window_height); - cairo_destroy (cr); + return region; +} +static void +get_monitor_geometry (GdmGreeterBackground *background, + GdkRectangle *geometry) +{ + GdkRegion *outside_region; + GdkRegion *monitor_region; + GdkRectangle geom; - /* schedule a redraw */ - gtk_widget_queue_draw (widget); + outside_region = get_outside_region (background); - if (GTK_WIDGET_CLASS (gdm_greeter_background_parent_class)->configure_event) { - handled = GTK_WIDGET_CLASS (gdm_greeter_background_parent_class)->configure_event (widget, event); + gdk_screen_get_monitor_geometry (GTK_WINDOW (background)->screen, + background->priv->monitor, + &geom); + monitor_region = gdk_region_rectangle (&geom); + gdk_region_subtract (monitor_region, outside_region); + gdk_region_destroy (outside_region); + + gdk_region_get_clipbox (monitor_region, geometry); + gdk_region_destroy (monitor_region); +} + +static void +update_geometry (GdmGreeterBackground *background, + GtkRequisition *requisition) +{ + GdkRectangle geometry; + int height; + + get_monitor_geometry (background, &geometry); + + height = requisition->height; + background->priv->geometry.width = geometry.width; + background->priv->geometry.height = geometry.height; + + background->priv->geometry.x = geometry.x; + background->priv->geometry.y = geometry.y; + + g_debug ("Setting background geometry x:%d y:%d w:%d h:%d", + background->priv->geometry.x, + background->priv->geometry.y, + background->priv->geometry.width, + background->priv->geometry.height); +} + +static void +gdm_greeter_background_real_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + GdmGreeterBackground *background; + GtkBin *bin; + GdkRectangle old_geometry; + int position_changed = FALSE; + int size_changed = FALSE; + + background = GDM_GREETER_BACKGROUND (widget); + bin = GTK_BIN (widget); + + if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) { + gtk_widget_size_request (bin->child, requisition); } - return handled; + old_geometry = background->priv->geometry; + + update_geometry (background, requisition); + + requisition->width = background->priv->geometry.width; + requisition->height = background->priv->geometry.height; + + if (! GTK_WIDGET_REALIZED (widget)) { + return; + } + + if (old_geometry.width != background->priv->geometry.width || + old_geometry.height != background->priv->geometry.height) { + size_changed = TRUE; + } + + if (old_geometry.x != background->priv->geometry.x || + old_geometry.y != background->priv->geometry.y) { + position_changed = TRUE; + } + + gdm_greeter_background_move_resize_window (background, position_changed, size_changed); } static gboolean @@ -578,12 +795,30 @@ gdm_greeter_background_real_expose (GtkWidget *widget, { gboolean handled = FALSE; - update_background (GDM_GREETER_BACKGROUND (widget)); + g_debug ("Exposing the background"); if (GTK_WIDGET_CLASS (gdm_greeter_background_parent_class)->expose_event) { handled = GTK_WIDGET_CLASS (gdm_greeter_background_parent_class)->expose_event (widget, event); } + update_background (GDM_GREETER_BACKGROUND (widget)); + + return handled; +} + +static gboolean +gdm_greeter_background_real_configure (GtkWidget *widget, + GdkEventConfigure *event) +{ + gboolean handled; + + handled = FALSE; + + g_debug ("Background configure w: %d h: %d", event->width, event->height); + if (GTK_WIDGET_CLASS (gdm_greeter_background_parent_class)->configure_event) { + handled = GTK_WIDGET_CLASS (gdm_greeter_background_parent_class)->configure_event (widget, event); + } + return handled; } @@ -604,6 +839,7 @@ gdm_greeter_background_class_init (GdmGreeterBackgroundClass *klass) widget_class->unrealize = gdm_greeter_background_real_unrealize; widget_class->expose_event = gdm_greeter_background_real_expose; widget_class->configure_event = gdm_greeter_background_real_configure; + widget_class->size_request = gdm_greeter_background_real_size_request; g_type_class_add_private (klass, sizeof (GdmGreeterBackgroundPrivate)); } diff --git a/gui/simple-greeter/gdm-greeter-panel.c b/gui/simple-greeter/gdm-greeter-panel.c index a96b4095..a41ec172 100644 --- a/gui/simple-greeter/gdm-greeter-panel.c +++ b/gui/simple-greeter/gdm-greeter-panel.c @@ -376,7 +376,7 @@ static void gdm_greeter_panel_init (GdmGreeterPanel *panel) { GtkWidget *label; - GtkWidget *tray; + NaTray *tray; panel->priv = GDM_GREETER_PANEL_GET_PRIVATE (panel); @@ -392,6 +392,7 @@ gdm_greeter_panel_init (GdmGreeterPanel *panel) gtk_window_set_keep_above (GTK_WINDOW (panel), TRUE); gtk_window_set_type_hint (GTK_WINDOW (panel), GDK_WINDOW_TYPE_HINT_DOCK); + gtk_window_set_opacity (GTK_WINDOW (panel), 0.75); panel->priv->hbox = gtk_hbox_new (FALSE, 12); gtk_widget_show (panel->priv->hbox); @@ -403,8 +404,8 @@ gdm_greeter_panel_init (GdmGreeterPanel *panel) tray = na_tray_new_for_screen (gtk_window_get_screen (GTK_WINDOW (panel)), GTK_ORIENTATION_HORIZONTAL); - gtk_box_pack_end (GTK_BOX (panel->priv->hbox), tray, FALSE, FALSE, 6); - gtk_widget_show (tray); + gtk_box_pack_end (GTK_BOX (panel->priv->hbox), GTK_WIDGET (tray), FALSE, FALSE, 6); + gtk_widget_show (GTK_WIDGET (tray)); } diff --git a/gui/simple-greeter/gdm-simple-greeter.c b/gui/simple-greeter/gdm-simple-greeter.c index e19f78a9..2db76623 100644 --- a/gui/simple-greeter/gdm-simple-greeter.c +++ b/gui/simple-greeter/gdm-simple-greeter.c @@ -532,6 +532,8 @@ create_greeter (GdmSimpleGreeter *greeter) gtk_entry_set_invisible_char (GTK_ENTRY (entry), invisible_char); } + gtk_window_set_opacity (GTK_WINDOW (dialog), 0.75); + gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ALWAYS); gtk_window_set_deletable (GTK_WINDOW (dialog), FALSE); gtk_window_set_decorated (GTK_WINDOW (dialog), FALSE); |