diff -Naur old_src/bubble.c src/bubble.c --- old_src/bubble.c 2012-03-23 10:49:59.000000000 -0400 +++ src/bubble.c 2012-11-10 08:44:21.000000000 -0500 @@ -119,6 +119,14 @@ A }; +typedef struct _NotifyHSVColor NotifyHSVColor; + +struct _NotifyHSVColor { + gdouble hue; + gdouble saturation; + gdouble value; +}; + #define TEMPORARY_ICON_PREFIX_WORKAROUND 1 #ifdef TEMPORARY_ICON_PREFIX_WORKAROUND #warning "--== Using the icon-name-substitution! This is a temp. workaround not going to be maintained for long! ==--" @@ -128,25 +136,25 @@ // FIXME: this is in class Defaults already, but not yet hooked up so for the // moment we use the macros here, these values reflect the visual-guideline // for jaunty notifications -#define TEXT_TITLE_COLOR_R 1.0f -#define TEXT_TITLE_COLOR_G 1.0f -#define TEXT_TITLE_COLOR_B 1.0f -#define TEXT_TITLE_COLOR_A 1.0f - -#define TEXT_BODY_COLOR_R 0.91f -#define TEXT_BODY_COLOR_G 0.91f -#define TEXT_BODY_COLOR_B 0.91f -#define TEXT_BODY_COLOR_A 1.0f +float TEXT_TITLE_COLOR_R = 1.0f; +float TEXT_TITLE_COLOR_G = 1.0f; +float TEXT_TITLE_COLOR_B = 1.0f; +float TEXT_TITLE_COLOR_A = 1.0f; + +float TEXT_BODY_COLOR_R = 0.91f; +float TEXT_BODY_COLOR_G = 0.91f; +float TEXT_BODY_COLOR_B = 0.91f; +float TEXT_BODY_COLOR_A = 1.0f; #define TEXT_SHADOW_COLOR_R 0.0f #define TEXT_SHADOW_COLOR_G 0.0f #define TEXT_SHADOW_COLOR_B 0.0f -#define TEXT_SHADOW_COLOR_A 1.0f +float TEXT_SHADOW_COLOR_A = 1.0f; -#define BUBBLE_BG_COLOR_R 0.15f -#define BUBBLE_BG_COLOR_G 0.15f -#define BUBBLE_BG_COLOR_B 0.15f -#define BUBBLE_BG_COLOR_A 0.9f +float BUBBLE_BG_COLOR_R = 0.07f; +float BUBBLE_BG_COLOR_G = 0.07f; +float BUBBLE_BG_COLOR_B = 0.07f; +float BUBBLE_BG_COLOR_A = 0.9f; #define INDICATOR_UNLIT_R 1.0f #define INDICATOR_UNLIT_G 1.0f @@ -167,6 +175,10 @@ #define BUBBLE_CONTENT_BLUR_RADIUS 4 #define TEXT_DROP_SHADOW_SIZE 2 +gboolean BUBBLE_PREVENT_FADE = TRUE; +gboolean BUBBLE_CLOSE_ON_CLICK = FALSE; +gboolean BUBBLE_AS_DESKTOP_BG = FALSE; + //-- private functions --------------------------------------------------------- static guint g_bubble_signals[LAST_SIGNAL] = { 0 }; @@ -487,6 +499,22 @@ cairo_surface_destroy (new_surface); } +static gdouble +get_shadow_size (Bubble *bubble) +{ + BubblePrivate* priv = GET_PRIVATE (bubble); + Defaults* d = bubble->defaults; + return defaults_get_bubble_shadow_size (d, priv->composited); +} + +static gdouble +get_corner_radius (Bubble *bubble) +{ + BubblePrivate* priv = GET_PRIVATE (bubble); + Defaults* d = bubble->defaults; + return defaults_get_bubble_corner_radius (d, priv->composited); +} + static void _draw_layout_grid (cairo_t* cr, Bubble* bubble) @@ -501,112 +529,112 @@ // all vertical grid lines cairo_move_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d), - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + 0.5f + EM2PIXELS (get_shadow_size (bubble), d), + 0.5f + EM2PIXELS (get_shadow_size (bubble), d)); cairo_line_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d), + 0.5f + EM2PIXELS (get_shadow_size (bubble), d), 0.5f + (gdouble) bubble_get_height (bubble) - - EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + EM2PIXELS (get_shadow_size (bubble), d)); cairo_move_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_margin_size (d), d), - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + 0.5f + EM2PIXELS (get_shadow_size (bubble), d)); cairo_line_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_margin_size (d), d), 0.5f + (gdouble) bubble_get_height (bubble) - - EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + EM2PIXELS (get_shadow_size (bubble), d)); cairo_move_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_margin_size (d), d) + EM2PIXELS (defaults_get_icon_size (d), d), - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + 0.5f + EM2PIXELS (get_shadow_size (bubble), d)); cairo_line_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_margin_size (d), d) + EM2PIXELS (defaults_get_icon_size (d), d), 0.5f + (gdouble) bubble_get_height (bubble) - - EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + EM2PIXELS (get_shadow_size (bubble), d)); cairo_move_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (2 * defaults_get_margin_size (d), d) + EM2PIXELS (defaults_get_icon_size (d), d), - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + 0.5f + EM2PIXELS (get_shadow_size (bubble), d)); cairo_line_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (2 * defaults_get_margin_size (d), d) + EM2PIXELS (defaults_get_icon_size (d), d), 0.5f + (gdouble) bubble_get_height (bubble) - - EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + EM2PIXELS (get_shadow_size (bubble), d)); cairo_move_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_bubble_width (d), d) - EM2PIXELS (defaults_get_margin_size (d), d), - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + 0.5f + EM2PIXELS (get_shadow_size (bubble), d)); cairo_line_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_bubble_width (d), d) - EM2PIXELS (defaults_get_margin_size (d), d), 0.5f + (gdouble) bubble_get_height (bubble) - - EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + EM2PIXELS (get_shadow_size (bubble), d)); cairo_move_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_bubble_width (d), d), - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + 0.5f + EM2PIXELS (get_shadow_size (bubble), d)); cairo_line_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_bubble_width (d), d), 0.5f + (gdouble) bubble_get_height (bubble) - - EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + EM2PIXELS (get_shadow_size (bubble), d)); // all horizontal grid lines cairo_move_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d), - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + 0.5f + EM2PIXELS (get_shadow_size (bubble), d), + 0.5f + EM2PIXELS (get_shadow_size (bubble), d)); cairo_line_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_bubble_width (d), d), - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + 0.5f + EM2PIXELS (get_shadow_size (bubble), d)); cairo_move_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d), - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d), + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_margin_size (d), d)); cairo_line_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_bubble_width (d), d), - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_margin_size (d), d)); cairo_move_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d), - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d), + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_margin_size (d), d) + EM2PIXELS (defaults_get_icon_size (d), d)); cairo_line_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_bubble_width (d), d), - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_margin_size (d), d) + EM2PIXELS (defaults_get_icon_size (d), d)); cairo_move_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d), + 0.5f + EM2PIXELS (get_shadow_size (bubble), d), 0.5f + (gdouble) bubble_get_height (bubble) - - EM2PIXELS (defaults_get_bubble_shadow_size (d), d) - + EM2PIXELS (get_shadow_size (bubble), d) - EM2PIXELS (defaults_get_margin_size (d), d)); cairo_line_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_bubble_width (d), d), 0.5f + (gdouble) bubble_get_height (bubble) - - EM2PIXELS (defaults_get_bubble_shadow_size (d), d) - + EM2PIXELS (get_shadow_size (bubble), d) - EM2PIXELS (defaults_get_margin_size (d), d)); cairo_move_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d), + 0.5f + EM2PIXELS (get_shadow_size (bubble), d), 0.5f + (gdouble) bubble_get_height (bubble) - - EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + EM2PIXELS (get_shadow_size (bubble), d)); cairo_line_to (cr, - 0.5f + EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + 0.5f + EM2PIXELS (get_shadow_size (bubble), d) + EM2PIXELS (defaults_get_bubble_width (d), d), 0.5f + (gdouble) bubble_get_height (bubble) - - EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + EM2PIXELS (get_shadow_size (bubble), d)); cairo_stroke (cr); } @@ -625,20 +653,28 @@ raico_blur_t* blur = NULL; gint width; gint height; + gint scratch_shadow_size; bubble_get_size (self, &width, &height); // create temp. scratch surface for top-left shadow/background part if (priv->composited) + { + scratch_shadow_size = EM2PIXELS (get_shadow_size (self), d); scratch = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, - 3 * EM2PIXELS (defaults_get_bubble_shadow_size (d), d), - 3 * EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + 3 * scratch_shadow_size, + 3 * scratch_shadow_size); + } else + { + // We must have at least some width to this scratch surface. + scratch_shadow_size = 1; scratch = cairo_image_surface_create ( CAIRO_FORMAT_RGB24, - 3 * EM2PIXELS (defaults_get_bubble_shadow_size (d), d), - 3 * EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + 3 * scratch_shadow_size, + 3 * scratch_shadow_size); + } g_return_if_fail (scratch); @@ -673,48 +709,72 @@ color_string = defaults_get_bubble_bg_color (d); gdk_rgba_parse (&color, color_string); g_free (color_string); - + + // Apply color tweaks + NotifyHSVColor hsv_color; + gtk_rgb_to_hsv (color.red, color.green, color.blue, + &hsv_color.hue, &hsv_color.saturation, &hsv_color.value); + hsv_color.saturation *= (2.0f - hsv_color.saturation); + hsv_color.value = MIN (hsv_color.value, 0.4f); + gtk_hsv_to_rgb (hsv_color.hue, hsv_color.saturation, hsv_color.value, + &color.red, &color.green, &color.blue); + if (priv->composited) { _draw_shadow ( cr, width, height, - EM2PIXELS (defaults_get_bubble_shadow_size (d), d), - EM2PIXELS (defaults_get_bubble_corner_radius (d), d)); + EM2PIXELS (get_shadow_size (self), d), + EM2PIXELS (get_corner_radius (self), d)); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); draw_round_rect ( cr, 1.0f, - EM2PIXELS (defaults_get_bubble_shadow_size (d), d), - EM2PIXELS (defaults_get_bubble_shadow_size (d), d), - EM2PIXELS (defaults_get_bubble_corner_radius (d), d), + EM2PIXELS (get_shadow_size (self), d), + EM2PIXELS (get_shadow_size (self), d), + EM2PIXELS (get_corner_radius (self), d), EM2PIXELS (defaults_get_bubble_width (d), d), (gdouble) bubble_get_height (self) - - 2.0f * EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + 2.0f * EM2PIXELS (get_shadow_size (self), d)); cairo_fill (cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); - cairo_set_source_rgba (cr, - 0.75 * color.red, - 0.75 * color.green, - 0.75 * color.blue, - BUBBLE_BG_COLOR_A); + if (BUBBLE_AS_DESKTOP_BG) { + cairo_set_source_rgba (cr, + color.red, + color.green, + color.blue, + BUBBLE_BG_COLOR_A); + } else { + cairo_set_source_rgba (cr, + BUBBLE_BG_COLOR_R, + BUBBLE_BG_COLOR_G, + BUBBLE_BG_COLOR_B, + BUBBLE_BG_COLOR_A); + } } else - cairo_set_source_rgb (cr, - 0.75 * color.red, - 0.75 * color.green, - 0.75 * color.blue); + if (BUBBLE_AS_DESKTOP_BG) { + cairo_set_source_rgb (cr, + color.red, + color.green, + color.blue); + } else { + cairo_set_source_rgb (cr, + BUBBLE_BG_COLOR_R, + BUBBLE_BG_COLOR_G, + BUBBLE_BG_COLOR_B); + } draw_round_rect ( cr, 1.0f, - EM2PIXELS (defaults_get_bubble_shadow_size (d), d), - EM2PIXELS (defaults_get_bubble_shadow_size (d), d), - EM2PIXELS (defaults_get_bubble_corner_radius (d), d), + EM2PIXELS (get_shadow_size (self), d), + EM2PIXELS (get_shadow_size (self), d), + EM2PIXELS (get_corner_radius (self), d), EM2PIXELS (defaults_get_bubble_width (d), d), (gdouble) bubble_get_height (self) - - 2.0f * EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + 2.0f * EM2PIXELS (get_shadow_size (self), d)); cairo_fill (cr); cairo_destroy (cr); @@ -722,8 +782,8 @@ dummy = cairo_image_surface_create_for_data ( cairo_image_surface_get_data (scratch), cairo_image_surface_get_format (scratch), - 3 * EM2PIXELS (defaults_get_bubble_shadow_size (d), d), - 3 * EM2PIXELS (defaults_get_bubble_shadow_size (d), d), + 3 * scratch_shadow_size, + 3 * scratch_shadow_size, cairo_image_surface_get_stride (scratch)); clone = copy_surface (dummy); cairo_surface_destroy (dummy); @@ -732,8 +792,8 @@ dummy = cairo_image_surface_create_for_data ( cairo_image_surface_get_data (clone), cairo_image_surface_get_format (clone), - 2 * EM2PIXELS (defaults_get_bubble_shadow_size (d), d), - 2 * EM2PIXELS (defaults_get_bubble_shadow_size (d), d), + 2 * scratch_shadow_size, + 2 * scratch_shadow_size, cairo_image_surface_get_stride (clone)); normal = copy_surface (dummy); cairo_surface_destroy (dummy); @@ -748,8 +808,8 @@ dummy = cairo_image_surface_create_for_data ( cairo_image_surface_get_data (clone), cairo_image_surface_get_format (clone), - 2 * EM2PIXELS (defaults_get_bubble_shadow_size (d), d), - 2 * EM2PIXELS (defaults_get_bubble_shadow_size (d), d), + 2 * scratch_shadow_size, + 2 * scratch_shadow_size, cairo_image_surface_get_stride (clone)); blurred = copy_surface (dummy); cairo_surface_destroy (dummy); @@ -1265,11 +1325,11 @@ draw_round_rect ( cr, 1.0f, - EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + 2.0f, - EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + 2.0f, - EM2PIXELS (defaults_get_bubble_corner_radius (d), d) - 2.0f, + EM2PIXELS (get_shadow_size (self), d) + 2.0f, + EM2PIXELS (get_shadow_size (self), d) + 2.0f, + EM2PIXELS (get_corner_radius (self), d) - 2.0f, EM2PIXELS (defaults_get_bubble_width (d), d) - 4.0f, - 2.0f * EM2PIXELS (defaults_get_bubble_shadow_size (d), d) - 2.0f); + 2.0f * EM2PIXELS (get_shadow_size (self), d) - 2.0f); cairo_fill (cr); cairo_set_source_rgb (cr, 0.0f, 0.0f, 0.0f); @@ -1279,12 +1339,12 @@ cairo_move_to ( cr, EM2PIXELS (defaults_get_text_body_size (d), d) + - EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + EM2PIXELS (get_shadow_size (self), d) + 2.0f, EM2PIXELS (defaults_get_text_body_size (d), d) + - EM2PIXELS (defaults_get_bubble_shadow_size (d), d) + + EM2PIXELS (get_shadow_size (self), d) + 2.0f + - ((2.0f * EM2PIXELS (defaults_get_bubble_shadow_size (d), d) - 2.0f) - + ((2.0f * EM2PIXELS (get_shadow_size (self), d) - 2.0f) - EM2PIXELS (defaults_get_text_body_size (d), d)) / 2); switch (bubble_get_urgency (self)) @@ -1428,7 +1488,7 @@ gdouble alpha_blur) { Defaults* d = self->defaults; - gint shadow = EM2PIXELS (defaults_get_bubble_shadow_size (d), d); + gint shadow = EM2PIXELS (get_shadow_size (self), d); gint icon_half = EM2PIXELS (defaults_get_icon_size (d), d) / 2; gint width_half = EM2PIXELS (defaults_get_bubble_width (d), d) / 2; gint height_half = EM2PIXELS (defaults_get_bubble_min_height (d), d) / 2; @@ -1605,15 +1665,23 @@ // sanity check if (!window) return; - - // set an 1x1 input-region to allow click-through - region = cairo_region_create_rectangle (&rect); - if (cairo_region_status (region) == CAIRO_STATUS_SUCCESS) + + if (!BUBBLE_CLOSE_ON_CLICK) { - gtk_widget_input_shape_combine_region (window, NULL); - gtk_widget_input_shape_combine_region (window, region); + // set an 1x1 input-region to allow click-through + region = cairo_region_create_rectangle (&rect); + if (cairo_region_status (region) == CAIRO_STATUS_SUCCESS) + { + gtk_widget_input_shape_combine_region (window, NULL); + gtk_widget_input_shape_combine_region (window, region); + } + cairo_region_destroy (region); + } + else + { + GdkWindow *window_ = gtk_widget_get_window (window); + gdk_window_set_events (window_, gdk_window_get_events (window_) | GDK_BUTTON_PRESS); } - cairo_region_destroy (region); } static void @@ -1703,7 +1771,7 @@ cairo_paint (cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); - if (priv->prevent_fade || !priv->composited) + if (!BUBBLE_PREVENT_FADE || priv->prevent_fade || !priv->composited) { // render drop-shadow and bubble-background _render_background (bubble, cr, 1.0f, 0.0f); @@ -1730,12 +1798,35 @@ _set_bg_blur (window, TRUE, - EM2PIXELS (defaults_get_bubble_shadow_size (d), d)); + EM2PIXELS (get_shadow_size (bubble), d)); return TRUE; } static gboolean +button_press_event_handler (GtkWidget* window G_GNUC_UNUSED, + GdkEventButton* event, + Bubble* bubble) +{ + BubblePrivate *priv = GET_PRIVATE (bubble); + + if (priv->mouse_over && event->button == 1) + { + bubble_hide (bubble); + + dbus_send_close_signal (bubble_get_sender (bubble), + bubble_get_id (bubble), + 1); + + g_signal_emit (bubble, g_bubble_signals[TIMED_OUT], 0); + + return TRUE; + } + + return FALSE; +} + +static gboolean redraw_handler (Bubble* bubble) { GtkWindow* window; @@ -1759,7 +1850,7 @@ if (priv->alpha == NULL) { - if (priv->distance < 1.0f && !priv->prevent_fade) + if (priv->distance < 1.0f && !priv->prevent_fade && BUBBLE_PREVENT_FADE) { gtk_window_set_opacity (window, WINDOW_MIN_OPACITY + @@ -1914,7 +2005,7 @@ // mark mouse-pointer having left bubble and proximity-area // after inital show-up of bubble - if (priv->prevent_fade && priv->distance > 1.0f) + if (BUBBLE_PREVENT_FADE && priv->prevent_fade && priv->distance > 1.0f) priv->prevent_fade = FALSE; } @@ -2210,6 +2301,14 @@ G_CALLBACK (expose_handler), this); + if (BUBBLE_CLOSE_ON_CLICK) + { + g_signal_connect (window, + "button-press-event", + G_CALLBACK (button_press_event_handler), + this); + } + // "clear" input-mask, set title/icon/attributes gtk_widget_set_app_paintable (window, TRUE); gtk_window_set_title (GTK_WINDOW (window), "notify-osd"); @@ -2689,7 +2788,7 @@ priv = GET_PRIVATE (self); - if (priv->prevent_fade) + if (BUBBLE_PREVENT_FADE && priv->prevent_fade) return FALSE; return priv->mouse_over; @@ -2793,7 +2892,7 @@ // check if mouse-pointer is over bubble (and proximity-area) initially pointer_update (self); - if (priv->distance <= 1.0f) + if (priv->distance <= 1.0f || !BUBBLE_PREVENT_FADE) priv->prevent_fade = TRUE; else priv->prevent_fade = FALSE; @@ -3351,6 +3450,8 @@ gint old_bubble_height = 0; gint new_bubble_width = 0; gint new_bubble_height = 0; + gint x; + gint y; Defaults* d; BubblePrivate* priv; @@ -3379,7 +3480,7 @@ new_bubble_width = EM2PIXELS (defaults_get_bubble_width (d), d) + - 2 * EM2PIXELS (defaults_get_bubble_shadow_size (d), d); + 2 * EM2PIXELS (get_shadow_size (self), d); switch (priv->layout) { @@ -3397,7 +3498,7 @@ new_bubble_height = EM2PIXELS (defaults_get_bubble_min_height (d), d) + - 2.0f * EM2PIXELS (defaults_get_bubble_shadow_size (d), d); + 2.0f * EM2PIXELS (get_shadow_size (self), d); break; case LAYOUT_ICON_TITLE_BODY: @@ -3446,7 +3547,7 @@ new_bubble_height = EM2PIXELS (defaults_get_icon_size (d), d) + 2.0f * EM2PIXELS (defaults_get_margin_size (d), d) + - 2.0f * EM2PIXELS (defaults_get_bubble_shadow_size (d), d); + 2.0f * EM2PIXELS (get_shadow_size (self), d); } else { @@ -3454,7 +3555,7 @@ priv->body_height + priv->title_height + 2.0f * EM2PIXELS (defaults_get_margin_size (d), d) + - 2.0f * EM2PIXELS (defaults_get_bubble_shadow_size (d), d); + 2.0f * EM2PIXELS (get_shadow_size (self), d); } } } @@ -3501,7 +3602,7 @@ priv->body_height + priv->title_height + 2.0f * EM2PIXELS (defaults_get_margin_size (d), d) + - 2.0f * EM2PIXELS (defaults_get_bubble_shadow_size (d), d); + 2.0f * EM2PIXELS (get_shadow_size (self), d); } } break; @@ -3518,7 +3619,7 @@ new_bubble_height = priv->title_height + 2.0f * EM2PIXELS (defaults_get_margin_size (d), d) + - 2.0f * EM2PIXELS (defaults_get_bubble_shadow_size (d), d); + 2.0f * EM2PIXELS (get_shadow_size (self), d); } break; @@ -3545,6 +3646,13 @@ _refresh_body (self); update_shape (self); + + if (defaults_get_gravity (d) == GRAVITY_SOUTH_EAST) + { + bubble_get_position(self, &x, &y); + bubble_move(self, x, y - (new_bubble_height - old_bubble_height)); + } + } void diff -Naur old_src/defaults.c src/defaults.c --- old_src/defaults.c 2012-03-23 10:49:59.000000000 -0400 +++ src/defaults.c 2012-11-10 08:44:21.000000000 -0500 @@ -110,40 +110,41 @@ /* these values are interpreted as em-measurements and do comply to the * visual guide for jaunty-notifications */ #define DEFAULT_DESKTOP_BOTTOM_GAP 6.0f -#define DEFAULT_BUBBLE_WIDTH 24.0f -#define DEFAULT_BUBBLE_MIN_HEIGHT 5.0f -#define DEFAULT_BUBBLE_MAX_HEIGHT 12.2f -#define DEFAULT_BUBBLE_VERT_GAP 0.5f -#define DEFAULT_BUBBLE_HORZ_GAP 0.5f +float DEFAULT_BUBBLE_WIDTH = 24.0f; +float DEFAULT_BUBBLE_MIN_HEIGHT = 5.0f; +float DEFAULT_BUBBLE_MAX_HEIGHT = 12.2f; +float DEFAULT_BUBBLE_VERT_GAP = 0.5f; +float DEFAULT_BUBBLE_HORZ_GAP = 0.5f; #define DEFAULT_BUBBLE_SHADOW_SIZE 0.7f #define DEFAULT_BUBBLE_SHADOW_COLOR "#000000" #define DEFAULT_BUBBLE_BG_COLOR "#131313" #define DEFAULT_BUBBLE_BG_OPACITY "#cc" #define DEFAULT_BUBBLE_HOVER_OPACITY "#66" -#define DEFAULT_BUBBLE_CORNER_RADIUS 0.375f +float DEFAULT_BUBBLE_CORNER_RADIUS = 0.375f; #define DEFAULT_CONTENT_SHADOW_SIZE 0.125f #define DEFAULT_CONTENT_SHADOW_COLOR "#000000" -#define DEFAULT_MARGIN_SIZE 1.0f -#define DEFAULT_ICON_SIZE 3.0f -#define DEFAULT_GAUGE_SIZE 0.625f -#define DEFAULT_GAUGE_OUTLINE_WIDTH 0.125f +float DEFAULT_MARGIN_SIZE = 1.0f; +float DEFAULT_ICON_SIZE = 3.0f; +float DEFAULT_GAUGE_SIZE = 0.625f; +#define DEFAULT_GAUGE_OUTLINE_WIDTH 0.125f #define DEFAULT_TEXT_FONT_FACE "Sans" #define DEFAULT_TEXT_TITLE_COLOR "#ffffff" -#define DEFAULT_TEXT_TITLE_WEIGHT TEXT_WEIGHT_BOLD -#define DEFAULT_TEXT_TITLE_SIZE 1.0f +short DEFAULT_TEXT_TITLE_WEIGHT = TEXT_WEIGHT_BOLD; +float DEFAULT_TEXT_TITLE_SIZE = 1.0f; #define DEFAULT_TEXT_BODY_COLOR "#eaeaea" -#define DEFAULT_TEXT_BODY_WEIGHT TEXT_WEIGHT_NORMAL -#define DEFAULT_TEXT_BODY_SIZE 0.9f +short DEFAULT_TEXT_BODY_WEIGHT = TEXT_WEIGHT_NORMAL; +float DEFAULT_TEXT_BODY_SIZE = 0.9f; #define DEFAULT_PIXELS_PER_EM 10.0f #define DEFAULT_SYSTEM_FONT_SIZE 10.0f #define DEFAULT_SCREEN_DPI 96.0f #define DEFAULT_GRAVITY GRAVITY_NORTH_EAST +short SLOT_ALLOCATION = SLOT_ALLOCATION_DYNAMIC; /* these values are interpreted as milliseconds-measurements and do comply to * the visual guide for jaunty-notifications */ -#define DEFAULT_FADE_IN_TIMEOUT 250 -#define DEFAULT_FADE_OUT_TIMEOUT 1000 -#define DEFAULT_ON_SCREEN_TIMEOUT 10000 +float DEFAULT_FADE_IN_TIMEOUT = 250; +float DEFAULT_FADE_OUT_TIMEOUT = 1000; +float DEFAULT_ON_SCREEN_TIMEOUT = 10000; /* notify-osd settings */ #define NOTIFY_OSD_SCHEMA "com.canonical.notify-osd" @@ -242,7 +243,7 @@ gravity = g_settings_get_int (self->nosd_settings, GSETTINGS_GRAVITY_KEY); // protect against out-of-bounds values for gravity - if (gravity != GRAVITY_EAST && gravity != GRAVITY_NORTH_EAST) + if (gravity != GRAVITY_EAST && gravity != GRAVITY_NORTH_EAST && gravity != GRAVITY_WEST && gravity != GRAVITY_NORTH_WEST && gravity != GRAVITY_SOUTH_EAST && gravity != GRAVITY_SOUTH_WEST) gravity = DEFAULT_GRAVITY; // update stored DPI-value @@ -546,7 +547,7 @@ self); // use fixed slot-allocation for async. and sync. bubbles - self->slot_allocation = SLOT_ALLOCATION_FIXED; + self->slot_allocation = SLOT_ALLOCATION; } static void @@ -1546,7 +1547,7 @@ "gravity", "Positional hint for placing bubbles", 0, - 2, + 6, DEFAULT_GRAVITY, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | @@ -1762,11 +1763,11 @@ } gdouble -defaults_get_bubble_shadow_size (Defaults* self) +defaults_get_bubble_shadow_size (Defaults* self, gboolean is_composited) { gdouble bubble_shadow_size; - if (!self || !IS_DEFAULTS (self)) + if (!self || !IS_DEFAULTS (self) || !is_composited) return 0.0f; g_object_get (self, "bubble-shadow-size", &bubble_shadow_size, NULL); @@ -1841,11 +1842,11 @@ } gdouble -defaults_get_bubble_corner_radius (Defaults* self) +defaults_get_bubble_corner_radius (Defaults* self, gboolean is_composited) { gdouble bubble_corner_radius; - if (!self || !IS_DEFAULTS (self)) + if (!self || !IS_DEFAULTS (self) || !is_composited) return 0.0f; g_object_get (self, @@ -2205,11 +2206,10 @@ } void -defaults_get_top_corner (Defaults *self, gint *x, gint *y) +defaults_get_top_corner (Defaults *self, GdkScreen **screen, gint *x, gint *y) { GdkRectangle rect; GdkRectangle panel_rect = {0, 0, 0, 0}; - GdkScreen* screen = NULL; GdkWindow* active_window = NULL; GdkWindow* panel_window = NULL; gint mx; @@ -2219,21 +2219,23 @@ gint aw_monitor; gboolean has_panel_window = FALSE; gboolean follow_focus = defaults_multihead_does_focus_follow (self); + gboolean is_composited = FALSE; g_return_if_fail (self != NULL && IS_DEFAULTS (self)); gdk_display_get_pointer (gdk_display_get_default (), - &screen, + screen, &mx, &my, NULL); + is_composited = gdk_screen_is_composited (*screen); panel_window = get_panel_window (); if (panel_window != NULL) { gdk_window_get_frame_extents (panel_window, &panel_rect); - panel_monitor = gdk_screen_get_monitor_at_window (screen, + panel_monitor = gdk_screen_get_monitor_at_window (*screen, panel_window); monitor = panel_monitor; g_debug ("found panel (%d,%d) - %dx%d on monitor %d", @@ -2249,12 +2251,12 @@ if (follow_focus) { g_debug ("multi_head_focus_follow mode"); - monitor = gdk_screen_get_monitor_at_point (screen, mx, my); - active_window = gdk_screen_get_active_window (screen); + monitor = gdk_screen_get_monitor_at_point (*screen, mx, my); + active_window = gdk_screen_get_active_window (*screen); if (active_window != NULL) { aw_monitor = gdk_screen_get_monitor_at_window ( - screen, + *screen, active_window); if (monitor != aw_monitor) @@ -2270,7 +2272,7 @@ } } - gdk_screen_get_monitor_geometry (screen, monitor, &rect); + gdk_screen_get_monitor_geometry (*screen, monitor, &rect); g_debug ("selecting monitor %d at (%d,%d) - %dx%d", monitor, rect.x, @@ -2299,7 +2301,7 @@ *y = rect.y; *y += EM2PIXELS (defaults_get_bubble_vert_gap (self), self) - - EM2PIXELS (defaults_get_bubble_shadow_size (self), self); + - EM2PIXELS (defaults_get_bubble_shadow_size (self, is_composited), self); /* correct potential offset in multi-monitor setups with two (or more) * monitors side by side, all having different vertical resolutions and @@ -2307,9 +2309,9 @@ * the top edge of the monitor with the lowest vertical resolution, * LP: #716458 */ GdkRectangle cur_geo = {0, 0, 0, 0}; - int num_monitors = gdk_screen_get_n_monitors (screen); - int screen_width = gdk_screen_get_width (screen); - int screen_height = gdk_screen_get_height (screen); + int num_monitors = gdk_screen_get_n_monitors (*screen); + int screen_width = gdk_screen_get_width (*screen); + int screen_height = gdk_screen_get_height (*screen); if (!follow_focus && num_monitors > 1) { @@ -2319,10 +2321,10 @@ { int right_most_monitor = 0; - right_most_monitor = gdk_screen_get_monitor_at_point (screen, + right_most_monitor = gdk_screen_get_monitor_at_point (*screen, screen_width, screen_height / 2); - gdk_screen_get_monitor_geometry (screen, + gdk_screen_get_monitor_geometry (*screen, right_most_monitor, &cur_geo); if (cur_geo.y != 0) @@ -2332,10 +2334,10 @@ { int left_most_monitor = 0; - left_most_monitor = gdk_screen_get_monitor_at_point (screen, + left_most_monitor = gdk_screen_get_monitor_at_point (*screen, 0, screen_height / 2); - gdk_screen_get_monitor_geometry (screen, + gdk_screen_get_monitor_geometry (*screen, left_most_monitor, &cur_geo); if (cur_geo.y != 0) @@ -2348,12 +2350,12 @@ if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_LTR) { *x = rect.x + rect.width; - *x -= EM2PIXELS (defaults_get_bubble_shadow_size (self), self) + *x -= EM2PIXELS (defaults_get_bubble_shadow_size (self, is_composited), self) + EM2PIXELS (defaults_get_bubble_horz_gap (self), self) + EM2PIXELS (defaults_get_bubble_width (self), self); } else { *x = rect.x - - EM2PIXELS (defaults_get_bubble_shadow_size (self), self) + - EM2PIXELS (defaults_get_bubble_shadow_size (self, is_composited), self) + EM2PIXELS (defaults_get_bubble_horz_gap (self), self); } diff -Naur old_src/defaults.h src/defaults.h --- old_src/defaults.h 2012-03-23 10:49:59.000000000 -0400 +++ src/defaults.h 2012-11-10 08:44:21.000000000 -0500 @@ -31,6 +31,7 @@ #include #include +#include G_BEGIN_DECLS @@ -58,7 +59,13 @@ { GRAVITY_NONE = 0, GRAVITY_NORTH_EAST, // top-right of screen - GRAVITY_EAST // vertically centered at right of screen + GRAVITY_EAST, // vertically centered at right of screen + GRAVITY_SOUTH_EAST, // bottom-right of screen + GRAVITY_SOUTH_WEST, // bottom-left of screen + GRAVITY_WEST, // vertically centered at left of screen + GRAVITY_NORTH_WEST // top-left of screen + + } Gravity; typedef enum @@ -177,7 +184,7 @@ defaults_get_bubble_horz_gap (Defaults* self); gdouble -defaults_get_bubble_shadow_size (Defaults* self); +defaults_get_bubble_shadow_size (Defaults* self, gboolean is_composited); gchar* defaults_get_bubble_shadow_color (Defaults* self); @@ -192,7 +199,7 @@ defaults_get_bubble_hover_opacity (Defaults* self); gdouble -defaults_get_bubble_corner_radius (Defaults* self); +defaults_get_bubble_corner_radius (Defaults* self, gboolean is_composited); gdouble defaults_get_content_shadow_size (Defaults* self); @@ -258,7 +265,7 @@ defaults_refresh_screen_dimension_properties (Defaults *self); void -defaults_get_top_corner (Defaults *self, gint *x, gint *y); +defaults_get_top_corner (Defaults *self, GdkScreen **screen, gint *x, gint *y); Gravity defaults_get_gravity (Defaults *self); diff -Naur old_src/display.c src/display.c --- old_src/display.c 2012-03-23 10:49:59.000000000 -0400 +++ src/display.c 2012-11-10 08:44:21.000000000 -0500 @@ -60,12 +60,13 @@ static gboolean stack_is_at_top_corner (Stack *self, Bubble *bubble) { + GdkScreen* screen; gint x, y1, y2; g_assert (IS_STACK (self)); g_assert (IS_BUBBLE (bubble)); - defaults_get_top_corner (self->defaults, &x, &y1); + defaults_get_top_corner (self->defaults, &screen, &x, &y1); bubble_get_position (bubble, &x, &y2); return y1 == y2; @@ -74,11 +75,12 @@ static void stack_display_position_sync_bubble (Stack *self, Bubble *bubble) { - Defaults* d = self->defaults; - gint y = 0; - gint x = 0; + Defaults* d = self->defaults; + GdkScreen* screen; + gint y = 0; + gint x = 0; - defaults_get_top_corner (d, &x, &y); + defaults_get_top_corner (d, &screen, &x, &y); // TODO: with multi-head, in focus follow mode, there may be enough // space left on the top monitor @@ -279,10 +281,11 @@ static void stack_layout (Stack* self) { - Bubble* bubble = NULL; - Defaults* d; - gint y = 0; - gint x = 0; + Bubble* bubble = NULL; + Defaults* d; + GdkScreen* screen; + gint y = 0; + gint x = 0; g_return_if_fail (self != NULL); @@ -310,10 +313,12 @@ return; } + /* bubble_set_timeout (bubble, defaults_get_on_screen_timeout (self->defaults)); + */ - defaults_get_top_corner (self->defaults, &x, &y); + defaults_get_top_corner (self->defaults, &screen, &x, &y); d = self->defaults; diff -Naur old_src/main.c src/main.c --- old_src/main.c 2012-03-23 10:49:59.000000000 -0400 +++ src/main.c 2012-11-10 08:44:21.000000000 -0500 @@ -25,6 +25,10 @@ ** with this program. If not, see . ** *******************************************************************************/ +#define _GNU_SOURCE /* getline */ +#include /* getuid */ +#include /* getpwuid */ +#include #include #include @@ -39,6 +43,213 @@ #define ICONS_DIR (DATADIR G_DIR_SEPARATOR_S "notify-osd" G_DIR_SEPARATOR_S "icons") +/* begin hack */ +extern float TEXT_TITLE_COLOR_R; +extern float TEXT_TITLE_COLOR_G; +extern float TEXT_TITLE_COLOR_B; +extern float TEXT_TITLE_COLOR_A; + +extern float TEXT_BODY_COLOR_R; +extern float TEXT_BODY_COLOR_G; +extern float TEXT_BODY_COLOR_B; +extern float TEXT_BODY_COLOR_A; + +extern float TEXT_SHADOW_COLOR_A; + +extern float BUBBLE_BG_COLOR_R; +extern float BUBBLE_BG_COLOR_G; +extern float BUBBLE_BG_COLOR_B; +extern float BUBBLE_BG_COLOR_A; + +extern float DEFAULT_TEXT_TITLE_SIZE; +extern float DEFAULT_TEXT_BODY_SIZE; +extern float DEFAULT_ON_SCREEN_TIMEOUT; + +extern short DEFAULT_TEXT_TITLE_WEIGHT; +extern short DEFAULT_TEXT_BODY_WEIGHT; +extern short SLOT_ALLOCATION; + +extern float DEFAULT_MARGIN_SIZE; +extern float DEFAULT_BUBBLE_CORNER_RADIUS; +extern float DEFAULT_BUBBLE_WIDTH; +extern float DEFAULT_BUBBLE_VERT_GAP; +extern float DEFAULT_BUBBLE_HORZ_GAP; +extern float DEFAULT_ICON_SIZE; +extern float DEFAULT_GAUGE_SIZE; + +extern gboolean BUBBLE_PREVENT_FADE; +extern gboolean BUBBLE_CLOSE_ON_CLICK; +extern gboolean BUBBLE_AS_DESKTOP_BG; + +void parse_color(unsigned int c, float* r, float* g, float* b) +{ + *b = (float)(c & 0xFF) / (float)(0xFF); + c >>= 8; + *g = (float)(c & 0xFF) / (float)(0xFF); + c >>= 8; + *r = (float)(c & 0xFF) / (float)(0xFF); +} + + +void load_settings(void) +{ + char file[PATH_MAX]; + uid_t uid = getuid(); + const char* settings_file_name = ".notify-osd"; + + struct passwd* pw = getpwuid(uid); + if (!pw) { + fprintf(stderr, + "failed to retrieve home directory. using default settings.\n"); + return; + } + /* $HOME/.notify-osd */ + snprintf(file, sizeof(file), "%s%s%s", pw->pw_dir, + G_DIR_SEPARATOR_S, settings_file_name); + + FILE* fp = fopen(file, "r"); + + if (!fp) { + fprintf(stderr, "could not open '%s'. using default settings.\n", file); + return; + + } + printf("reading settings from '%s'\n", file); + + char* buf = NULL; + size_t size = 0; + char key[32], value[32]; + float fvalue; + unsigned int ivalue; + + while(getline(&buf, &size, fp) != -1) { + if (sscanf(buf, "%31s = %31s", key, value) != 2) + continue; + if (!strcmp(key, "bubble-background-color") && + sscanf(value, "%x", &ivalue)) { + + parse_color(ivalue, &BUBBLE_BG_COLOR_R, &BUBBLE_BG_COLOR_G, + &BUBBLE_BG_COLOR_B); + + + } else if (!strcmp(key, "bubble-background-opacity") && + sscanf(value, "%f", &fvalue)) { + + BUBBLE_BG_COLOR_A = fvalue*0.01; + + } else if (!strcmp(key, "text-title-color") && + sscanf(value, "%x", &ivalue) ) { + + parse_color(ivalue, &TEXT_TITLE_COLOR_R, &TEXT_TITLE_COLOR_G, + &TEXT_TITLE_COLOR_B); + + } else if (!strcmp(key, "text-title-opacity") && + sscanf(value, "%f", &fvalue) ) { + + TEXT_TITLE_COLOR_A = fvalue*0.01; + + } else if (!strcmp(key, "text-body-color") && + sscanf(value, "%x", &ivalue) ) { + + parse_color(ivalue, &TEXT_BODY_COLOR_R, &TEXT_BODY_COLOR_G, + &TEXT_BODY_COLOR_B); + + } else if (!strcmp(key, "text-body-opacity") && + sscanf(value, "%f", &fvalue) ) { + + TEXT_BODY_COLOR_A = fvalue*0.01; + + } else if (!strcmp(key, "text-shadow-opacity") && + sscanf(value, "%f", &fvalue) ) { + + TEXT_SHADOW_COLOR_A = fvalue*0.01; + + } else if (!strcmp(key, "text-title-size") && + sscanf(value, "%f", &fvalue) ) { + DEFAULT_TEXT_TITLE_SIZE = fvalue*0.01; + + } else if (!strcmp(key, "text-body-size") && + sscanf(value, "%f", &fvalue) ) { + DEFAULT_TEXT_BODY_SIZE = fvalue*0.01; + + } else if (!strcmp(key, "bubble-expire-timeout") && + sscanf(value, "%f", &fvalue) ) { + DEFAULT_ON_SCREEN_TIMEOUT = fvalue*1000; + + } else if (!strcmp(key, "text-title-weight")) { + if (!strcmp(value, "bold")) { + DEFAULT_TEXT_TITLE_WEIGHT = 700; + } else if (!strcmp(value, "normal")) { + DEFAULT_TEXT_TITLE_WEIGHT = 400; + } else if (!strcmp(value, "light")) { + DEFAULT_TEXT_TITLE_WEIGHT = 300; + } + } else if (!strcmp(key, "text-body-weight")) { + if (!strcmp(value, "bold")) { + DEFAULT_TEXT_BODY_WEIGHT = 700; + } else if (!strcmp(value, "normal")) { + DEFAULT_TEXT_BODY_WEIGHT = 400; + } else if (!strcmp(value, "light")) { + DEFAULT_TEXT_BODY_WEIGHT = 300; + } + } else if (!strcmp(key, "text-margin-size") && + sscanf(value, "%f", &fvalue) ) { + DEFAULT_MARGIN_SIZE = fvalue*0.1; + + } else if (!strcmp(key, "bubble-corner-radius") && + sscanf(value, "%f", &fvalue) ) { + DEFAULT_BUBBLE_CORNER_RADIUS = fvalue*0.01; + + } else if (!strcmp(key, "bubble-width") && + sscanf(value, "%f", &fvalue) ) { + DEFAULT_BUBBLE_WIDTH = fvalue*0.1; + + } else if (!strcmp(key, "slot-allocation")) { + if (!strcmp(value, "dynamic")) { + SLOT_ALLOCATION = SLOT_ALLOCATION_DYNAMIC; + } else if (!strcmp(value, "fixed")) { + SLOT_ALLOCATION = SLOT_ALLOCATION_FIXED; + } + } else if (!strcmp(key, "bubble-vertical-gap") && + sscanf(value, "%f", &fvalue) ) { + DEFAULT_BUBBLE_VERT_GAP = fvalue*0.1; + + } else if (!strcmp(key, "bubble-horizontal-gap") && + sscanf(value, "%f", &fvalue) ) { + DEFAULT_BUBBLE_HORZ_GAP = fvalue*0.1; + + } else if (!strcmp(key, "bubble-icon-size") && + sscanf(value, "%f", &fvalue) ) { + DEFAULT_ICON_SIZE = fvalue*0.1; + + } else if (!strcmp(key, "bubble-gauge-size") && + sscanf(value, "%f", &fvalue) ) { + DEFAULT_GAUGE_SIZE = fvalue*0.1; + + } else if (!strcmp(key, "bubble-prevent-fade") && + sscanf(value, "%d", &ivalue) ) { + BUBBLE_PREVENT_FADE = ivalue; + + } else if (!strcmp(key, "bubble-close-on-click") && + sscanf(value, "%d", &ivalue) ) { + BUBBLE_CLOSE_ON_CLICK = ivalue; + + } else if (!strcmp(key, "bubble-as-desktop-bg") && + sscanf(value, "%d", &ivalue) ) { + BUBBLE_AS_DESKTOP_BG = ivalue; + + } + + } + + if (buf) { + free(buf); + } + + fclose(fp); +} +/* end hack */ + int main (int argc, char** argv) @@ -58,6 +269,8 @@ gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), ICONS_DIR); + load_settings(); + defaults = defaults_new (); observer = observer_new (); stack = stack_new (defaults, observer); diff -Naur old_src/send-test-notification.sh src/send-test-notification.sh --- old_src/send-test-notification.sh 1969-12-31 19:00:00.000000000 -0500 +++ src/send-test-notification.sh 2012-11-10 08:44:09.000000000 -0500 @@ -0,0 +1,63 @@ +#!/bin/sh + +notify-send "Take note" "The next example will test the icon-only layout-case" -i dialog-info +sleep 2 +notify-send "Eject" -i notification-device-eject -h string:x-canonical-private-icon-only: +sleep 2 +notify-send "WiFi signal found" -i notification-network-wireless-medium +sleep 2 +notify-send "WiFi signal lost" -i notification-network-wireless-disconnected +sleep 2 +notify-send "Volume" -i notification-audio-volume-medium -h int:value:75 -h string:x-canonical-private-synchronous: +sleep 2 +notify-send "Volume" -i notification-audio-volume-low -h int:value:30 -h string:x-canonical-private-synchronous: +sleep 2 +notify-send "Brightness" -i notification-display-brightness-high -h int:value:101 -h string:x-canonical-private-synchronous: +sleep 2 +notify-send "Brightness" -i notification-keyboard-brightness-medium -h int:value:45 -h string:x-canonical-private-synchronous: +sleep 2 +notify-send "Testing markup" "Some bold, underlined, italic text. Note, you should not see any marked up text." +sleep 2 +notify-send "Jamshed Kakar" "Hey, what about this restaurant? http://www.blafasel.org + +Would you go from your place by train or should I pick you up from work? What do you think?" +sleep 2 +notify-send "English bubble" "The quick brown fox jumps over the lazy dog." -i network +sleep 2 +notify-send "Bubble from Germany" "Polyfon zwitschernd aßen Mäxchens Vögel Rüben, Joghurt und Quark." -i gnome-system +sleep 2 +notify-send "Very russian" "Съешь ещё этих мягких французских булок, да выпей чаю." -i dialog-info +sleep 2 +notify-send "More from Germany" "Oje, Qualm verwölkt Dix zig Farbtriptychons." -i gnome-globe +sleep 2 +notify-send "Filter the world 1/3" "Ubuntu +Don't rock the boat +Kick him while he's down +\"Film spectators are quiet vampires.\" +Peace & Love +War & Peace +Law & Order +Love & War +7 > 3 +7 > 3" +sleep 2 +notify-send "Filter the world 2/3" "7 > 3 +7 > 3 +14 < 42 +14 < 42 +14 < 42 +14 < 42 +>< +<> +< this is not a tag > +Not italic" +sleep 2 +notify-send "Filter the world 3/3" "So broken +Nothing to see +Test +Bold +Span +E-flat +Sandwich +Fry +Testing tag" diff -Naur old_src/stack.c src/stack.c --- old_src/stack.c 2012-03-23 10:49:59.000000000 -0400 +++ src/stack.c 2012-11-10 08:44:21.000000000 -0500 @@ -44,6 +44,7 @@ G_DEFINE_TYPE (Stack, stack, G_TYPE_OBJECT); #define FORCED_SHUTDOWN_THRESHOLD 500 +#define NOTIFY_EXPIRES_DEFAULT -1 /* fwd declaration */ void close_handler (GObject* n, Stack* stack); @@ -646,6 +647,15 @@ if (body) bubble_set_message_body (bubble, body); + if (timeout == NOTIFY_EXPIRES_DEFAULT) { + bubble_set_timeout (bubble, + defaults_get_on_screen_timeout (self->defaults)); + } + else { + bubble_set_timeout (bubble, timeout); + } + + if (new_bubble && bubble_is_append_allowed(bubble)) { app_bubble = find_bubble_for_append(self, bubble); @@ -885,6 +895,9 @@ gint* x, gint* y) { + GdkScreen* screen = NULL; + gboolean is_composited = FALSE; + // sanity checks if (!x && !y) return; @@ -904,7 +917,9 @@ } // initialize x and y - defaults_get_top_corner (self->defaults, x, y); + defaults_get_top_corner (self->defaults, &screen, x, y); + + is_composited = gdk_screen_is_composited (screen); // differentiate returned top-left corner for top and bottom slot // depending on the placement @@ -920,12 +935,12 @@ *y += defaults_get_desktop_height (d) / 2 - EM2PIXELS (defaults_get_bubble_vert_gap (d) / 2.0f, d) - bubble_height + - EM2PIXELS (defaults_get_bubble_shadow_size (d), d); + EM2PIXELS (defaults_get_bubble_shadow_size (d, is_composited), d); // the position for the async. bubble else if (slot == SLOT_BOTTOM) *y += defaults_get_desktop_height (d) / 2 + EM2PIXELS (defaults_get_bubble_vert_gap (d) / 2.0f, d) - - EM2PIXELS (defaults_get_bubble_shadow_size (d), d); + EM2PIXELS (defaults_get_bubble_shadow_size (d, is_composited), d); break; case GRAVITY_NORTH_EAST: @@ -944,15 +959,61 @@ case SLOT_ALLOCATION_FIXED: *y += EM2PIXELS (defaults_get_icon_size (d), d) + 2 * EM2PIXELS (defaults_get_margin_size (d), d) + - EM2PIXELS (defaults_get_bubble_vert_gap (d), d); /* + - 2 * EM2PIXELS (defaults_get_bubble_shadow_size (d), d);*/ + EM2PIXELS (defaults_get_bubble_vert_gap (d), d) + 2; + break; + + case SLOT_ALLOCATION_DYNAMIC: + g_assert (stack_is_slot_vacant (self, SLOT_TOP) == OCCUPIED); + *y += bubble_get_height (self->slots[SLOT_TOP]) + + EM2PIXELS (defaults_get_bubble_vert_gap (d), d) - + 2 * EM2PIXELS (defaults_get_bubble_shadow_size (d, is_composited), d); + break; + + default: + break; + } + + } + break; + + case GRAVITY_WEST: + d = self->defaults; + + *x = defaults_get_desktop_left (d); + + // the position for the sync./feedback bubble + if (slot == SLOT_TOP) + *y += defaults_get_desktop_height (d) / 2 - + EM2PIXELS (defaults_get_bubble_vert_gap (d) / 2.0f, d) - + bubble_height + + EM2PIXELS (defaults_get_bubble_shadow_size (d, is_composited), d); + // the position for the async. bubble + else if (slot == SLOT_BOTTOM) + *y += defaults_get_desktop_height (d) / 2 + + EM2PIXELS (defaults_get_bubble_vert_gap (d) / 2.0f, d) - + EM2PIXELS (defaults_get_bubble_shadow_size (d, is_composited), d); + break; + + case GRAVITY_NORTH_WEST: + d = self->defaults; + + *x = defaults_get_desktop_left (d); + + if (slot == SLOT_BOTTOM) + { + switch (defaults_get_slot_allocation (d)) + { + case SLOT_ALLOCATION_FIXED: + *y += EM2PIXELS (defaults_get_icon_size (d), d) + + 2 * EM2PIXELS (defaults_get_margin_size (d), d) + + EM2PIXELS (defaults_get_bubble_vert_gap (d), d) + 2; break; case SLOT_ALLOCATION_DYNAMIC: g_assert (stack_is_slot_vacant (self, SLOT_TOP) == OCCUPIED); *y += bubble_get_height (self->slots[SLOT_TOP]) + EM2PIXELS (defaults_get_bubble_vert_gap (d), d) - - 2 * EM2PIXELS (defaults_get_bubble_shadow_size (d), d); + 2 * EM2PIXELS (defaults_get_bubble_shadow_size (d, is_composited), d); break; default: @@ -961,6 +1022,114 @@ } break; + + case GRAVITY_SOUTH_EAST: + d = self->defaults; + + switch (defaults_get_slot_allocation (d)) + { + case SLOT_ALLOCATION_FIXED: + if (slot == SLOT_TOP) + { + *y += defaults_get_desktop_height (d) - + 2 * EM2PIXELS (defaults_get_bubble_vert_gap (d), d) - + bubble_height + + 2 * EM2PIXELS (defaults_get_bubble_shadow_size (d, is_composited), d); + + } + + if (slot == SLOT_BOTTOM) + { + *y += defaults_get_desktop_height (d) - + bubble_height - + EM2PIXELS (defaults_get_icon_size (d), d) - + 2 * EM2PIXELS (defaults_get_margin_size (d), d) - + 3 * EM2PIXELS (defaults_get_bubble_vert_gap (d), d) + + 2 * EM2PIXELS (defaults_get_bubble_shadow_size (d, is_composited), d) - 2; + + } + break; + + case SLOT_ALLOCATION_DYNAMIC: + if (slot == SLOT_TOP) + { + *y += defaults_get_desktop_height (d) - + 2 * EM2PIXELS (defaults_get_bubble_vert_gap (d), d) - + bubble_height + + 2 * EM2PIXELS (defaults_get_bubble_shadow_size (d, is_composited), d); + } + + if (slot == SLOT_BOTTOM) + { + g_assert (stack_is_slot_vacant (self, SLOT_TOP) == OCCUPIED); + *y += defaults_get_desktop_height (d) - + 3 * EM2PIXELS (defaults_get_bubble_vert_gap (d), d) - + bubble_height + + 4 * EM2PIXELS (defaults_get_bubble_shadow_size (d, is_composited), d) - + bubble_get_height (self->slots[SLOT_TOP]); + } + break; + + default: + break; + } + + break; + + case GRAVITY_SOUTH_WEST: + d = self->defaults; + + *x = defaults_get_desktop_left (d); + + switch (defaults_get_slot_allocation (d)) + { + case SLOT_ALLOCATION_FIXED: + if (slot == SLOT_TOP) + { + *y += defaults_get_desktop_height (d) - + 2 * EM2PIXELS (defaults_get_bubble_vert_gap (d), d) - + bubble_height + + 2 * EM2PIXELS (defaults_get_bubble_shadow_size (d, is_composited), d); + + } + + if (slot == SLOT_BOTTOM) + { + *y += defaults_get_desktop_height (d) - + bubble_height - + EM2PIXELS (defaults_get_icon_size (d), d) - + 2 * EM2PIXELS (defaults_get_margin_size (d), d) - + 3 * EM2PIXELS (defaults_get_bubble_vert_gap (d), d) + + 2 * EM2PIXELS (defaults_get_bubble_shadow_size (d, is_composited), d) - 2; + + } + break; + + case SLOT_ALLOCATION_DYNAMIC: + if (slot == SLOT_TOP) + { + *y += defaults_get_desktop_height (d) - + 2 * EM2PIXELS (defaults_get_bubble_vert_gap (d), d) - + bubble_height + + 2 * EM2PIXELS (defaults_get_bubble_shadow_size (d, is_composited), d); + } + + if (slot == SLOT_BOTTOM) + { + g_assert (stack_is_slot_vacant (self, SLOT_TOP) == OCCUPIED); + *y += defaults_get_desktop_height (d) - + 3 * EM2PIXELS (defaults_get_bubble_vert_gap (d), d) - + bubble_height + + 4 * EM2PIXELS (defaults_get_bubble_shadow_size (d, is_composited), d) - + bubble_get_height (self->slots[SLOT_TOP]); + } + break; + + default: + break; + } + + break; default: g_warning ("Unhandled placement!\n"); .