[Galago-commits] r2342 - in trunk/notify-daemon-ng: . src

galago-commits at freedesktop.org galago-commits at freedesktop.org
Tue Nov 22 14:00:24 PST 2005


Author: johnp
Date: 2005-11-22 14:00:12 -0800 (Tue, 22 Nov 2005)
New Revision: 2342

Modified:
   trunk/notify-daemon-ng/ChangeLog
   trunk/notify-daemon-ng/configure.ac
   trunk/notify-daemon-ng/src/eggnotificationbubblewidget.c
   trunk/notify-daemon-ng/src/eggnotificationbubblewidget.h
Log:
* src/eggnotificationbubblewidget.c: Add a more stylized bubble
  and render in both composite and shaped window mode


Modified: trunk/notify-daemon-ng/ChangeLog
===================================================================
--- trunk/notify-daemon-ng/ChangeLog	2005-11-21 09:36:06 UTC (rev 2341)
+++ trunk/notify-daemon-ng/ChangeLog	2005-11-22 22:00:12 UTC (rev 2342)
@@ -1,3 +1,8 @@
+2005-11-22  John (J5) Palmieri  <johnp at redhat.com>
+
+	* src/eggnotificationbubblewidget.c: Add a more stylized bubble
+	and render in both composite and shaped window mode
+
 2005-11-15  John (J5) Palmieri  <johnp at redhat.com>
 	
 	* Change refrences from notification to notify

Modified: trunk/notify-daemon-ng/configure.ac
===================================================================
--- trunk/notify-daemon-ng/configure.ac	2005-11-21 09:36:06 UTC (rev 2341)
+++ trunk/notify-daemon-ng/configure.ac	2005-11-22 22:00:12 UTC (rev 2342)
@@ -3,7 +3,7 @@
 dnl ################################################################
 dnl # Initialize autoconf
 dnl ################################################################
-AC_INIT(notify-daemon, 0.3.0, johnp at redhat.com)
+AC_INIT(notify-daemon, 0.3.1, johnp at redhat.com)
 AC_PREREQ(2.50)
 AC_CONFIG_SRCDIR(config.h.in)
 AC_COPYRIGHT([Copyright 2005 John (J5) Palmieri])
@@ -14,7 +14,7 @@
 dnl ################################################################
 NOTIFY_DAEMON_MAJOR_VERSION=0
 NOTIFY_DAEMON_MINOR_VERSION=3
-NOTIFY_DAEMON_MICRO_VERSION=0
+NOTIFY_DAEMON_MICRO_VERSION=1
 NOTIFY_DAEMON_DEVEL_VERSION=0
 
 NOTIFY_DAEMON_VERSION=$NOTIFY_DAEMON_MAJOR_VERSION.$NOTIFY_DAEMON_MINOR_VERSION.$NOTIFY_DAEMON_MICRO_VERSION

Modified: trunk/notify-daemon-ng/src/eggnotificationbubblewidget.c
===================================================================
--- trunk/notify-daemon-ng/src/eggnotificationbubblewidget.c	2005-11-21 09:36:06 UTC (rev 2341)
+++ trunk/notify-daemon-ng/src/eggnotificationbubblewidget.c	2005-11-22 22:00:12 UTC (rev 2342)
@@ -20,11 +20,16 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
+#include <math.h>
 
 #include <gtk/gtk.h>
 #include "eggnotificationbubblewidget.h"
 
-#define BORDER_SIZE 15
+#define BORDER_SIZE 30 
+#define CURVE_LENGTH 25
+#define TRIANGLE_START 45 
+#define TRIANGLE_WIDTH 60 
+#define TEXT_WIDTH_THRESHOLD 100 
 
 static void egg_notification_bubble_widget_class_init        (EggNotificationBubbleWidgetClass *klass);
 static void egg_notification_bubble_widget_init              (EggNotificationBubbleWidget      *bubble_widget);
@@ -32,9 +37,21 @@
 static void egg_notification_bubble_widget_event_handler     (GtkWidget   *widget,
                                                               GdkEvent    *event,
                                                               gpointer     user_data);
-static gboolean egg_notification_bubble_widget_expose        (GtkWidget *widget, GdkEventExpose *event);
+static gboolean egg_notification_bubble_widget_expose        (GtkWidget *widget, 
+                                                              GdkEventExpose *event);
 
-static void populate_window (EggNotificationBubbleWidget *bubble_widget);
+static gboolean egg_notification_bubble_widget_body_label_expose_handler (GtkWidget *widget, 
+                                                                          GdkEventExpose *event, 
+                                                                          EggNotificationBubbleWidget *bw);
+
+static void egg_notification_bubble_widget_context_changed_handler (EggNotificationBubbleWidget      *bubble_widget);
+
+static void egg_notification_bubble_widget_realize           (GtkWidget *widget);
+
+static void egg_notification_bubble_widget_screen_changed    (GtkWidget *widget,
+                                                              GdkScreen *old_screen);
+
+static void _populate_window (EggNotificationBubbleWidget *bubble_widget);
 static void draw_bubble_widget (EggNotificationBubbleWidget *bubble_widget);
 
 static GtkWindowClass *parent_class;
@@ -103,6 +120,8 @@
 
   object_class->finalize = egg_notification_bubble_widget_finalize;
   widget_class->expose_event = egg_notification_bubble_widget_expose;
+  widget_class->realize = egg_notification_bubble_widget_realize;
+  widget_class->screen_changed = egg_notification_bubble_widget_screen_changed;
 
   egg_notification_bubble_widget_signals[NOTIFICATION_CLICKED] =
     g_signal_new ("clicked",
@@ -116,14 +135,63 @@
 }
 
 static void
+_size_request_handler (GtkWidget *widget, GtkRequisition *requisition, EggNotificationBubbleWidget *bw)
+{
+  #if 0
+  GtkRequisition req;
+  int new_height;
+
+  if (!GTK_WIDGET_VISIBLE (widget) ||
+      GTK_WIDGET (bw)->allocation.width <= 1)
+  return;
+  
+  gtk_widget_set_size_request (GTK_WIDGET (bw), 0, -1);
+  gtk_widget_size_request (GTK_WIDGET (bw), &req);
+  g_print ("req width: %d, req height: %d\n", req.width, req.height);
+
+  new_height = GTK_WIDGET (bw)->allocation.height - widget->allocation.height
+               + req.height;
+
+  if (GTK_WIDGET (bw)->allocation.width > 0 && new_height > 0 && new_height !=
+      widget->allocation.height)
+      {
+
+        g_print ("window req width: %d, req height: %d\n", 
+                       GTK_WIDGET (bw)->allocation.width,
+                       new_height);
+    gtk_window_resize (GTK_WINDOW (bw), 
+                       GTK_WIDGET (bw)->allocation.width,
+                       new_height);
+     }
+     #endif
+
+#if 0
+  if (req.width > MAX_BUBBLE_WIDTH)
+    {
+      g_print ("-");
+    fflush (stdout);
+      gtk_widget_set_size_request (GTK_WIDGET (bubble_widget), MAX_BUBBLE_WIDTH, -1);
+      gtk_widget_size_request (GTK_WIDGET (bubble_widget), &req);
+      gtk_window_resize (GTK_WINDOW (bubble_widget), req.width, req.height);
+    }
+#endif
+}
+
+static void
 egg_notification_bubble_widget_init (EggNotificationBubbleWidget *bubble_widget)
 {
   GtkWindow *win;
-
+  
   win = GTK_WINDOW (bubble_widget);
 
-  populate_window (bubble_widget);
+  bubble_widget->can_composite = FALSE;
 
+  egg_notification_bubble_widget_screen_changed (GTK_WIDGET (bubble_widget),
+                                                 NULL);
+
+ 
+  _populate_window (bubble_widget);
+
 }
 
 static void
@@ -138,52 +206,143 @@
 }
 
 static void
-populate_window (EggNotificationBubbleWidget *bubble_widget)
+_populate_window (EggNotificationBubbleWidget *bubble_widget)
 {
   g_return_if_fail (EGG_IS_NOTIFICATION_BUBBLE_WIDGET (bubble_widget));
 
   GtkWidget *vbox;
   GtkWidget *hbox;
   GtkWidget *widget;
-
+  GdkGeometry geom;
+ 
   widget = GTK_WIDGET (bubble_widget);
 
   gtk_widget_add_events (widget, GDK_BUTTON_PRESS_MASK);
   gtk_widget_set_app_paintable (widget, TRUE);
-  gtk_window_set_resizable (GTK_WINDOW (bubble_widget), FALSE);
-  gtk_widget_set_name (widget, "gtk-tooltips");
+  gtk_window_set_resizable (GTK_WINDOW (bubble_widget), TRUE);
   gtk_container_set_border_width (GTK_CONTAINER (bubble_widget), BORDER_SIZE + 5);
 
   bubble_widget->bubble_widget_header_label = gtk_label_new (NULL);
-  bubble_widget->bubble_widget_body_label = gtk_label_new (NULL);
+
+  //use placeholder so we can use pango/cairo to draw body
+  bubble_widget->bubble_widget_body_label = gtk_frame_new("");
+  gtk_frame_set_shadow_type (bubble_widget->bubble_widget_body_label, GTK_SHADOW_NONE);
   bubble_widget->icon = gtk_image_new_from_stock (GTK_STOCK_INFO, GTK_ICON_SIZE_BUTTON);
+  gtk_widget_ref (bubble_widget->bubble_widget_header_label);
+  gtk_widget_ref (bubble_widget->bubble_widget_body_label);
+  gtk_widget_ref (bubble_widget->icon);
+
   gtk_label_set_line_wrap (GTK_LABEL (bubble_widget->bubble_widget_header_label), TRUE);
-  gtk_label_set_line_wrap (GTK_LABEL (bubble_widget->bubble_widget_body_label), TRUE);
   gtk_misc_set_alignment (GTK_MISC (bubble_widget->bubble_widget_header_label), 0.0, 0.0);
-  gtk_misc_set_alignment (GTK_MISC (bubble_widget->bubble_widget_body_label), 0.0, 0.0);
 
   gtk_misc_set_alignment (GTK_MISC (bubble_widget->icon), 0.0, 0.0);
   gtk_widget_show (bubble_widget->icon);
   gtk_widget_show (bubble_widget->bubble_widget_header_label);
   gtk_widget_show (bubble_widget->bubble_widget_body_label);
 
-  bubble_widget->main_hbox = gtk_hbox_new (FALSE, 10);
-      
-  vbox = gtk_vbox_new (FALSE, 5);
-  hbox = gtk_hbox_new (FALSE, 5);
-  gtk_box_pack_start (GTK_BOX (hbox), bubble_widget->icon, FALSE, FALSE, 0);
-  gtk_container_add (GTK_CONTAINER (vbox), bubble_widget->bubble_widget_header_label);
-  gtk_container_add (GTK_CONTAINER (vbox), bubble_widget->bubble_widget_body_label);
-  gtk_container_add (GTK_CONTAINER (hbox), vbox);
-  gtk_container_add (GTK_CONTAINER (bubble_widget), hbox);
+  bubble_widget->table = gtk_table_new (2, 2, FALSE);
+  gtk_table_set_col_spacings (bubble_widget->table, 5);
+  gtk_table_set_row_spacings (bubble_widget->table, 5);
+ 
+  gtk_table_attach (GTK_TABLE (bubble_widget->table),
+                    bubble_widget->icon,
+                    0, 1, 1, 2,
+                    GTK_FILL, GTK_FILL,
+                    0, 0);
 
+  gtk_table_attach (GTK_TABLE (bubble_widget->table),
+                    bubble_widget->bubble_widget_header_label,
+                    1, 2, 0, 1,
+                    GTK_FILL, GTK_FILL,
+                    0, 0);
+
+  gtk_table_attach (GTK_TABLE (bubble_widget->table),
+                    bubble_widget->bubble_widget_body_label,
+                    1, 2, 1, 2,
+                    GTK_FILL, GTK_FILL,
+                    0, 0);
+  
+  gtk_container_add (GTK_CONTAINER (bubble_widget), bubble_widget->table);
+
+  bubble_widget->body_layout = pango_layout_new (
+                                 gtk_widget_get_pango_context (
+                                   GTK_WIDGET (bubble_widget)));
+
+  g_signal_connect (bubble_widget, "style-set",
+                    G_CALLBACK (egg_notification_bubble_widget_context_changed_handler),
+                    NULL);
+
+  g_signal_connect (bubble_widget, "direction-changed",
+                    G_CALLBACK (egg_notification_bubble_widget_context_changed_handler),
+                    NULL);
+
   g_signal_connect_after (bubble_widget, "event-after",
                           G_CALLBACK (egg_notification_bubble_widget_event_handler),
                           bubble_widget);
    
+  g_signal_connect (bubble_widget->bubble_widget_body_label, "expose-event",
+                    G_CALLBACK (egg_notification_bubble_widget_body_label_expose_handler),
+                    bubble_widget);
 }
 
 static void
+_layout_window (EggNotificationBubbleWidget *bubble_widget,
+                int alignment)
+{
+
+  gtk_container_remove (GTK_CONTAINER (bubble_widget->table), 
+                        bubble_widget->icon);
+
+  gtk_container_remove (GTK_CONTAINER (bubble_widget->table), 
+                        bubble_widget->bubble_widget_header_label);
+
+  gtk_container_remove (GTK_CONTAINER (bubble_widget->table), 
+                        bubble_widget->bubble_widget_body_label);
+
+  if (alignment == TRIANGLE_LEFT)
+    {
+      gtk_table_attach (GTK_TABLE (bubble_widget->table),
+                        bubble_widget->icon,
+                        0, 1, 1, 2,
+                        GTK_FILL, GTK_FILL,
+                        0, 0);
+
+      gtk_table_attach (GTK_TABLE (bubble_widget->table),
+                        bubble_widget->bubble_widget_header_label,
+                        1, 2, 0, 1,
+                        GTK_FILL, GTK_FILL,
+                        0, 0);
+
+      gtk_table_attach (GTK_TABLE (bubble_widget->table),
+                        bubble_widget->bubble_widget_body_label,
+                        1, 2, 1, 2,
+                        GTK_FILL, GTK_FILL,
+                        0, 0);
+    }
+  else
+    {
+      gtk_table_attach (GTK_TABLE (bubble_widget->table),
+                        bubble_widget->icon,
+                        1, 2, 1, 2,
+                        GTK_FILL, GTK_FILL,
+                        0, 0);
+
+      gtk_table_attach (GTK_TABLE (bubble_widget->table),
+                        bubble_widget->bubble_widget_header_label,
+                        0, 1, 0, 1,
+                        GTK_FILL, GTK_FILL,
+                        0, 0);
+
+      gtk_table_attach (GTK_TABLE (bubble_widget->table),
+                        bubble_widget->bubble_widget_body_label,
+                        0, 1, 1, 2,
+                        GTK_FILL, GTK_FILL,
+                        0, 0);
+
+    }
+}
+
+static void
 _destroy_pixmap_data_func (guchar *pixels,
                            gpointer data)
 {
@@ -215,6 +374,32 @@
   gdk_pixbuf_unref (pixbuf);
 }
 
+static void
+_calculate_pango_layout_from_aspect (PangoLayout *layout,
+                                     const char *text, 
+                                     double factor)
+{
+  gint len;
+  gint w, h;
+  double x;
+  
+  len = strlen (text);
+  pango_layout_set_width(layout, -1);
+  pango_layout_set_text (layout, text, len);
+  
+  pango_layout_get_pixel_size (layout, &w, &h);
+
+  if (w > TEXT_WIDTH_THRESHOLD)
+    {
+      pango_layout_get_size (layout, &w, &h);
+
+      x = sqrt (factor * w / h);
+      w = round (w / x);
+
+      pango_layout_set_width(layout, w);
+    }
+}
+
 void
 egg_notification_bubble_widget_set (EggNotificationBubbleWidget *bubble_widget,
 			     const gchar *bubble_widget_header_text,
@@ -223,7 +408,7 @@
 {
   gchar *markupquoted;
   gchar *markuptext;
-  gchar *paddedtext;
+  gint w, h;
 
   g_return_if_fail (EGG_IS_NOTIFICATION_BUBBLE_WIDGET (bubble_widget));
 
@@ -246,321 +431,451 @@
     }
     
   markupquoted = g_markup_escape_text (bubble_widget->bubble_widget_header_text, -1);
-  markuptext = g_strdup_printf ("<b>%s</b>", markupquoted);
+  markuptext = g_strdup_printf ("<span size=\"larger\" weight=\"ultrabold\">%s</span>", markupquoted);
   gtk_label_set_markup (GTK_LABEL (bubble_widget->bubble_widget_header_label), markuptext);
   g_free (markuptext);
   g_free (markupquoted);
 
-  paddedtext = g_strdup_printf ("  %s", bubble_widget->bubble_widget_body_text);
-  gtk_label_set_text (GTK_LABEL (bubble_widget->bubble_widget_body_label), paddedtext);
-  g_free (paddedtext);
+  _calculate_pango_layout_from_aspect (bubble_widget->body_layout,
+                                       bubble_widget->bubble_widget_body_text, 
+                                       0.25);
+
+  pango_layout_get_pixel_size (bubble_widget->body_layout, &w, &h);
+  gtk_widget_set_size_request (bubble_widget->bubble_widget_body_label, w, h);
+  
+  
 }
 
 void
 egg_notification_bubble_widget_set_pos (EggNotificationBubbleWidget   *bubble_widget,
                                  gint x, gint y)
 {
+  GdkScreen *screen;
+  gint monitor_num;
+  GdkRectangle monitor;
+
   bubble_widget->x = x;
   bubble_widget->y = y;
+
+  screen = gtk_window_get_screen (GTK_WINDOW(bubble_widget));
+  monitor_num = gdk_screen_get_monitor_at_point (screen, x, y);
+  gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
+
+  gtk_window_move (GTK_WINDOW (bubble_widget), x, y);
+
+  if (x < (monitor.x + monitor.width) / 2)
+      _layout_window (bubble_widget, TRIANGLE_LEFT);
+  else
+      _layout_window (bubble_widget, TRIANGLE_RIGHT);
 }
 
-static gboolean 
-egg_notification_bubble_widget_expose (GtkWidget *widget, GdkEventExpose *event)
+static void
+egg_notification_bubble_widget_realize (GtkWidget *widget)
 {
-  GtkRequisition req;
   GtkWidgetClass *widget_parent_class;
 
-  gtk_widget_size_request (widget, &req);
-  gtk_paint_flat_box (widget->style, widget->window,
-		      GTK_STATE_NORMAL, GTK_SHADOW_OUT, 
-		      NULL, widget, "notification",
-		      0, 0, req.width, req.height);
+  widget_parent_class = (GtkWidgetClass *)parent_class;
+  if (widget_parent_class->realize)
+    widget_parent_class->realize (widget);
 
   draw_bubble_widget (EGG_NOTIFICATION_BUBBLE_WIDGET(widget));
-
-  widget_parent_class = (GtkWidgetClass *)parent_class;
-  if (widget_parent_class->expose_event)
-    widget_parent_class->expose_event (widget, event);
- 
-  return FALSE;
 }
 
 static void
-subtract_rectangle (GdkRegion *region, GdkRectangle *rectangle)
+egg_notification_bubble_widget_screen_changed (GtkWidget *widget,
+                                               GdkScreen *old_screen)
 {
-  GdkRegion *temp_region;
+  GtkWidgetClass *widget_parent_class;
+  EggNotificationBubbleWidget *bw;
+  GdkScreen *screen;
+  GdkColormap *colormap;
+  gboolean can_composite;
+ 
+  bw = EGG_NOTIFICATION_BUBBLE_WIDGET (widget);
 
-  temp_region = gdk_region_rectangle (rectangle);
-  gdk_region_subtract (region, temp_region);
-  gdk_region_destroy (temp_region);
-}
+  widget_parent_class = (GtkWidgetClass *)parent_class;
+  if (widget_parent_class->screen_changed)
+    widget_parent_class->screen_changed (widget, old_screen);
 
-static GdkRegion *
-add_bevels_to_rectangle (GdkRectangle *rectangle, cairo_t *cairo_context, int orient, int orient_triangle)
-{
-  GdkRectangle temp_rect;
-  GdkRegion *region = gdk_region_rectangle (rectangle);
+  can_composite = TRUE;
   
-  /* Top left */
-  if (!(orient == ORIENT_TOP && orient_triangle == TRIANGLE_LEFT))
+  screen = gtk_widget_get_screen (widget);
+  colormap = gdk_screen_get_rgba_colormap (screen);
+  
+  if (!colormap)
     {
-      temp_rect.width = 5;
-      temp_rect.height = 1;
-      temp_rect.x = rectangle->x;
-      temp_rect.y = rectangle->y;  
-      subtract_rectangle (region, &temp_rect);
+      colormap = gdk_screen_get_rgb_colormap (screen);
+      can_composite = FALSE;
+    }
+    
+  gtk_widget_set_colormap (widget, colormap);
+  
+  bw->can_composite = can_composite;
+}
 
-      temp_rect.y += 1;
-      temp_rect.width -= 2;
-      subtract_rectangle (region, &temp_rect);
 
-      temp_rect.y += 1;
-      temp_rect.width -= 1;
-      subtract_rectangle (region, &temp_rect);
+static gboolean
+egg_notification_bubble_widget_body_label_expose_handler (GtkWidget *widget, 
+                                                          GdkEventExpose *event, 
+                                                          EggNotificationBubbleWidget *bw)
+{
+  cairo_t *cr;
+  cr = gdk_cairo_create (GTK_WIDGET(bw)->window);
 
-      temp_rect.y += 1;
-      temp_rect.width -= 1;
-      temp_rect.height = 2;
-      subtract_rectangle (region, &temp_rect);
+  cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
 
-      temp_rect.x = rectangle->x;
-      temp_rect.y = rectangle->y;
+  cairo_set_source_rgba (cr, bw->body_text_color.red, 
+                             bw->body_text_color.green, 
+                             bw->body_text_color.blue, 
+                             0.60);
+  cairo_move_to (cr, event->area.x, event->area.y);
 
-      cairo_move_to (cairo_context, temp_rect.x + 3, temp_rect.y + 1.5);
-      cairo_line_to (cairo_context, temp_rect.x + 5, temp_rect.y + 1.5);
-      
-      cairo_move_to (cairo_context, temp_rect.x + 2, temp_rect.y + 2.5);
-      cairo_line_to (cairo_context, temp_rect.x + 3, temp_rect.y + 2.5);
+  pango_cairo_layout_path (cr, bw->body_layout);
 
-      cairo_move_to (cairo_context, temp_rect.x + 1, temp_rect.y + 3.5);
-      cairo_line_to (cairo_context, temp_rect.x + 2, temp_rect.y + 3.5);
+  cairo_fill (cr);
+  cairo_destroy (cr);
+}
 
-      cairo_move_to (cairo_context, temp_rect.x + 1, temp_rect.y + 4.5);
-      cairo_line_to (cairo_context, temp_rect.x + 2, temp_rect.y + 4.5);
-      
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_MEDIUM);
-      cairo_stroke (cairo_context);
-      
-      cairo_move_to (cairo_context, temp_rect.x + 3, temp_rect.y + 2.5);
-      cairo_line_to (cairo_context, temp_rect.x + 5, temp_rect.y + 2.5);
+static gboolean 
+egg_notification_bubble_widget_expose (GtkWidget *widget, GdkEventExpose *event)
+{
+  GtkWidgetClass *widget_parent_class;
+  EggNotificationBubbleWidget *bw;
 
-      cairo_move_to (cairo_context, temp_rect.x + 2, temp_rect.y + 3.5);
-      cairo_line_to (cairo_context, temp_rect.x + 3, temp_rect.y + 3.5);
-      
-      cairo_move_to (cairo_context, temp_rect.x + 2, temp_rect.y + 4.5);
-      cairo_line_to (cairo_context, temp_rect.x + 3, temp_rect.y + 4.5);
-      
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-      cairo_stroke (cairo_context);
-    }
+  bw = EGG_NOTIFICATION_BUBBLE_WIDGET (widget);
 
-  /* Top right */
-  if (!(orient == ORIENT_TOP && orient_triangle == TRIANGLE_RIGHT))
-    {
-      temp_rect.width = 5;
-      temp_rect.height = 1;
-      
-      temp_rect.x = (rectangle->x + rectangle->width) - temp_rect.width;
-      temp_rect.y = rectangle->y;
-      subtract_rectangle (region, &temp_rect);
+  draw_bubble_widget (bw);
 
-      temp_rect.y += 1;
-      temp_rect.x += 2;
-      subtract_rectangle (region, &temp_rect);
+  widget_parent_class = (GtkWidgetClass *)parent_class;
+  if (widget_parent_class->expose_event)
+    widget_parent_class->expose_event (widget, event);
+ 
+  return TRUE;
+}
 
-      temp_rect.y += 1;
-      temp_rect.x += 1;
-      subtract_rectangle (region, &temp_rect);
+static GdkPoint 
+_stencil_bubble_top_right (cairo_t *cr,
+                           GdkRectangle *rect,
+			   int pos_x, int pos_y)
+{
+  GdkPoint triangle[3];
+  double d, p1x, p2x, p3x, pdx, pvx, p1y, p2y, p3y, pdy, pvy;
 
-      temp_rect.y += 1;
-      temp_rect.x += 1;
-      temp_rect.height = 2;
-      subtract_rectangle (region, &temp_rect);
+  triangle[2].x = rect->x + rect->width - TRIANGLE_START;
+  triangle[2].y = rect->y;
 
-      temp_rect.x = rectangle->x + rectangle->width;
-      temp_rect.y = rectangle->y;
+  triangle[0].x = triangle[2].x - TRIANGLE_WIDTH;
+  triangle[0].y = rect->y;
+  triangle[1].x = (triangle[2].x - triangle[0].x) / 2 + triangle[0].x;
+  triangle[1].y = rect->y - BORDER_SIZE + 5;
 
-      cairo_move_to (cairo_context, temp_rect.x - 3, temp_rect.y + 1.5);
-      cairo_line_to (cairo_context, temp_rect.x - 5, temp_rect.y + 1.5);
-      
-      cairo_move_to (cairo_context, temp_rect.x - 2, temp_rect.y + 2.5);
-      cairo_line_to (cairo_context, temp_rect.x - 3, temp_rect.y + 2.5);
+#if 0
+  if (triangle[1].x + (BORDER_SIZE - 5) < pos_x)
+    triangle[1].x = pos_x - (BORDER_SIZE + 5);
+#endif 
 
-      cairo_move_to (cairo_context, temp_rect.x - 1, temp_rect.y + 3.5);
-      cairo_line_to (cairo_context, temp_rect.x - 2, temp_rect.y + 3.5);
+  cairo_move_to (cr, triangle[0].x, triangle[0].y);
+  cairo_line_to (cr, triangle[1].x, triangle[1].y);
+  cairo_line_to (cr, triangle[2].x, triangle[2].y);
 
-      cairo_move_to (cairo_context, temp_rect.x - 1, temp_rect.y + 4.5);
-      cairo_line_to (cairo_context, temp_rect.x - 2, temp_rect.y + 4.5);
-      
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_MEDIUM);
-      cairo_stroke (cairo_context);
-      
-      cairo_move_to (cairo_context, temp_rect.x - 3, temp_rect.y + 2.5);
-      cairo_line_to (cairo_context, temp_rect.x - 5, temp_rect.y + 2.5);
+  cairo_line_to (cr, rect->x + rect->width - CURVE_LENGTH, rect->y);
+  cairo_curve_to (cr, 
+                  rect->x + rect->width,
+                  rect->y,
+                  rect->x + rect->width,
+                  rect->y,
+                  rect->x + rect->width, 
+                  rect->y + CURVE_LENGTH);
 
-      cairo_move_to (cairo_context, temp_rect.x - 2, temp_rect.y + 3.5);
-      cairo_line_to (cairo_context, temp_rect.x - 3, temp_rect.y + 3.5);
-      
-      cairo_move_to (cairo_context, temp_rect.x - 2, temp_rect.y + 4.5);
-      cairo_line_to (cairo_context, temp_rect.x - 3, temp_rect.y + 4.5);
-     
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-      cairo_stroke (cairo_context);
+  cairo_line_to (cr, rect->x + rect->width, rect->y + rect->height - CURVE_LENGTH);
 
-    }
+  p1x = rect->x + rect->width;
+  p2x = rect->x;
+  p1y = rect->y + rect->height + (BORDER_SIZE - 5);
+  p2y = rect->y + rect->height;
+  
+  pdx = p1x - p2x;
+  pdy = p1y - p2y;
+  
+  d = sqrt (pdx * pdx + 
+            pdy * pdy);
 
-  /* Bottom right */
-  if (!(orient == ORIENT_BOTTOM && orient_triangle == TRIANGLE_RIGHT))
+  pvx = (pdx / d);
+  pvy = (pdy / d);
+ 
+  p3x = p1x - CURVE_LENGTH * pvx;
+  p3y = p1y - CURVE_LENGTH * pvy;
+
+  cairo_curve_to (cr, 
+                  p1x,
+                  p1y,
+                  p1x,
+                  p1y,
+                  p3x, 
+                  p3y);
+
+  p3x = p2x + CURVE_LENGTH * pvx;
+  p3y = p2y + CURVE_LENGTH * pvy;
+  
+  cairo_line_to (cr, p3x, p3y);
+
+  cairo_curve_to (cr, 
+                  p2x,
+                  p2y,
+                  p2x,
+                  p2y,
+                  p2x, 
+                  p2y - CURVE_LENGTH);
+
+  cairo_line_to (cr, rect->x, rect->y + CURVE_LENGTH);
+  p1x = rect->x + CURVE_LENGTH;
+  if (p1x < triangle[0].x)
     {
-      temp_rect.width = 5;
-      temp_rect.height = 1;
+      cairo_curve_to (cr, 
+                      rect->x,
+                      rect->y,
+                      rect->x,
+                      rect->y,
+                      p1x, 
+                      rect->y);
+      cairo_line_to (cr, triangle[0].x, rect->y);
+    }
+  else
+    {
+      cairo_curve_to (cr, 
+                      rect->x,
+                      rect->y,
+                      rect->x,
+                      rect->y,
+                      triangle[0].x, 
+                      rect->y);
+    }
 
-      temp_rect.x = (rectangle->x + rectangle->width) - temp_rect.width;
-      temp_rect.y = (rectangle->y + rectangle->height) - temp_rect.height;
-      subtract_rectangle (region, &temp_rect);
+  return triangle[1];
+}
 
-      temp_rect.y -= 1;
-      temp_rect.x += 2;
-      subtract_rectangle (region, &temp_rect);
+static GdkPoint
+_stencil_bubble_top_left  (cairo_t *cr,
+                           GdkRectangle *rect, 
+                           int pos_x, int pos_y)
+{
+  GdkPoint triangle[3];
+  double d, p1x, p2x, p3x, pdx, pvx, p1y, p2y, p3y, pdy, pvy;
 
-      temp_rect.y -= 1;
-      temp_rect.x += 1;
-      subtract_rectangle (region, &temp_rect);
+  triangle[0].x = rect->x + TRIANGLE_START;
+  triangle[0].y = rect->y;
+  triangle[2].x = triangle[0].x + TRIANGLE_WIDTH;
+  triangle[2].y = rect->y;
+  triangle[1].x = (triangle[2].x - triangle[0].x) / 2 + triangle[0].x;
+  triangle[1].y = rect->y - BORDER_SIZE + 5;
 
-      temp_rect.y -= 2;
-      temp_rect.x += 1;
-      temp_rect.height = 2;
-      subtract_rectangle (region, &temp_rect);
+  //if (triangle[1].x - (BORDER_SIZE - 5 ) > pos_x)
+  //  triangle[1].x = pos_x + (BORDER_SIZE + 5);
 
-      temp_rect.x = rectangle->x + rectangle->width; 
-      temp_rect.y = rectangle->y + rectangle->height;
+  cairo_move_to (cr, triangle[0].x, triangle[0].y);
+  cairo_line_to (cr, triangle[1].x, triangle[1].y);
+  cairo_line_to (cr, triangle[2].x, triangle[2].y);
 
-      cairo_move_to (cairo_context, temp_rect.x - 3, temp_rect.y - 1.5);
-      cairo_line_to (cairo_context, temp_rect.x - 5, temp_rect.y - 1.5);
-      
-      cairo_move_to (cairo_context, temp_rect.x - 2, temp_rect.y - 2.5);
-      cairo_line_to (cairo_context, temp_rect.x - 3, temp_rect.y - 2.5);
+  cairo_line_to (cr, rect->x + rect->width - CURVE_LENGTH, rect->y);
+  cairo_curve_to (cr, 
+                  rect->x + rect->width,
+                  rect->y,
+                  rect->x + rect->width,
+                  rect->y,
+                  rect->x + rect->width, 
+                  rect->y + CURVE_LENGTH);
 
-      cairo_move_to (cairo_context, temp_rect.x - 1, temp_rect.y - 3.5);
-      cairo_line_to (cairo_context, temp_rect.x - 2, temp_rect.y - 3.5);
+  cairo_line_to (cr, rect->x + rect->width, rect->y + rect->height - CURVE_LENGTH);
 
-      cairo_move_to (cairo_context, temp_rect.x - 1, temp_rect.y - 4.5);
-      cairo_line_to (cairo_context, temp_rect.x - 2, temp_rect.y - 4.5);
-      
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_MEDIUM);
-      cairo_stroke (cairo_context);
-      
-      cairo_move_to (cairo_context, temp_rect.x - 3, temp_rect.y - 2.5);
-      cairo_line_to (cairo_context, temp_rect.x - 5, temp_rect.y - 2.5);
+  p1x = rect->x + rect->width;
+  p2x = rect->x;
+  p1y = rect->y + rect->height;
+  p2y = rect->y + rect->height + (BORDER_SIZE - 5);
+  
+  pdx = p1x - p2x;
+  pdy = p1y - p2y;
+  
+  d = sqrt (pdx * pdx + 
+            pdy * pdy);
 
-      cairo_move_to (cairo_context, temp_rect.x - 2, temp_rect.y - 3.5);
-      cairo_line_to (cairo_context, temp_rect.x - 3, temp_rect.y - 3.5);
-      
-      cairo_move_to (cairo_context, temp_rect.x - 2, temp_rect.y - 4.5);
-      cairo_line_to (cairo_context, temp_rect.x - 3, temp_rect.y - 4.5);
-      
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-      cairo_stroke (cairo_context);
+  pvx = (pdx / d);
+  pvy = (pdy / d);
+ 
+  p3x = p1x - CURVE_LENGTH * pvx;
+  p3y = p1y - CURVE_LENGTH * pvy;
 
-    }
+  cairo_curve_to (cr, 
+                  p1x,
+                  p1y,
+                  p1x,
+                  p1y,
+                  p3x, 
+                  p3y);
 
-  /* Bottom left */
-  if (!(orient == ORIENT_BOTTOM && orient_triangle == TRIANGLE_LEFT))
-    {
-      temp_rect.width = 5;
-      temp_rect.height = 1;
+  p3x = p2x + CURVE_LENGTH * pvx;
+  p3y = p2y + CURVE_LENGTH * pvy;
   
-      temp_rect.x = rectangle->x;
-      temp_rect.y = rectangle->y + rectangle->height - 1;
-      subtract_rectangle (region, &temp_rect);
+  cairo_line_to (cr, p3x, p3y);
 
-      temp_rect.y -= 1;
-      temp_rect.width -= 2;
-      subtract_rectangle (region, &temp_rect);
+  cairo_curve_to (cr, 
+                  p2x,
+                  p2y,
+                  p2x,
+                  p2y,
+                  p2x, 
+                  p2y - CURVE_LENGTH);
 
-      temp_rect.y -= 1;
-      temp_rect.width -= 1;
-      subtract_rectangle (region, &temp_rect);
+  cairo_line_to (cr, rect->x, rect->y + CURVE_LENGTH);
+  p1x = rect->x + CURVE_LENGTH;
+  if (p1x < triangle[0].x)
+    {
+      cairo_curve_to (cr, 
+                      rect->x,
+                      rect->y,
+                      rect->x,
+                      rect->y,
+                      p1x, 
+                      rect->y);
+      cairo_line_to (cr, triangle[0].x, rect->y);
+    }
+  else
+    {
+      cairo_curve_to (cr, 
+                      rect->x,
+                      rect->y,
+                      rect->x,
+                      rect->y,
+                      triangle[0].x, 
+                      rect->y);
+    }
 
-      temp_rect.y -= 2;
-      temp_rect.width -= 1;
-      temp_rect.height = 2;
-      subtract_rectangle (region, &temp_rect);
+  return triangle[1];
+}
 
-      temp_rect.x = rectangle->x;
-      temp_rect.y = rectangle->y + rectangle->height;
+static GdkPoint
+_stencil_bubble_bottom_right (cairo_t *cr,
+                              GdkRectangle *rect,
+			      int pos_x, int pos_y)
+{
 
-      cairo_move_to (cairo_context, temp_rect.x + 3, temp_rect.y - 1.5);
-      cairo_line_to (cairo_context, temp_rect.x + 5, temp_rect.y - 1.5);
-      
-      cairo_move_to (cairo_context, temp_rect.x + 2, temp_rect.y - 2.5);
-      cairo_line_to (cairo_context, temp_rect.x + 3, temp_rect.y - 2.5);
+}
 
-      cairo_move_to (cairo_context, temp_rect.x + 1, temp_rect.y - 3.5);
-      cairo_line_to (cairo_context, temp_rect.x + 2, temp_rect.y - 3.5);
+static GdkPoint 
+_stencil_bubble_bottom_left  (cairo_t *cr,
+                              GdkRectangle *rect,
+			      int pos_x, int pos_y)
+{
 
-      cairo_move_to (cairo_context, temp_rect.x + 1, temp_rect.y - 4.5);
-      cairo_line_to (cairo_context, temp_rect.x + 2, temp_rect.y - 4.5);
-      
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_MEDIUM);
-      cairo_stroke (cairo_context);
-      
-      cairo_move_to (cairo_context, temp_rect.x + 3, temp_rect.y - 2.5);
-      cairo_line_to (cairo_context, temp_rect.x + 5, temp_rect.y - 2.5);
+}
 
-      cairo_move_to (cairo_context, temp_rect.x + 2, temp_rect.y - 3.5);
-      cairo_line_to (cairo_context, temp_rect.x + 3, temp_rect.y - 3.5);
-      
-      cairo_move_to (cairo_context, temp_rect.x + 2, temp_rect.y - 4.5);
-      cairo_line_to (cairo_context, temp_rect.x + 3, temp_rect.y - 4.5);
-      
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-      cairo_stroke (cairo_context);
-    }
+static GdkColor
+_blend_colors (GdkColor color1, GdkColor color2, gdouble factor)
+{
+  GdkColor result;
+  gint channel_intensity;
+  
+  channel_intensity = color1.red * factor + color2.red * (1 - factor);
+  result.red = CLAMP (channel_intensity, 0, 65535);
+  
+  channel_intensity = color1.green * factor + color2.green * (1 - factor);
+  result.green = CLAMP (channel_intensity, 0, 65535);
 
-  return region;
+  channel_intensity = color1.blue * factor + color2.blue * (1 - factor);
+  result.blue = CLAMP (channel_intensity, 0, 65535);
+
+  return result;
 }
 
 static void
+_calculate_colors_from_style (EggNotificationBubbleWidget *bw)
+{
+  GtkStyle *style;
+  GtkWidget *widget;
+  GdkColor header_text_color;
+  GdkColor body_text_color;
+  GdkColor bg_end_gradient;
+  GdkColor border_color;
+  GdkColor bg_start_gradient;
+
+  widget = GTK_WIDGET (bw);
+  
+  gtk_widget_ensure_style (widget);
+  style = widget->style;
+
+  header_text_color = style->text[GTK_STATE_NORMAL];
+  body_text_color = style->text[GTK_STATE_NORMAL];
+  bg_start_gradient = style->base[GTK_STATE_NORMAL];
+  bg_end_gradient = style->bg[GTK_STATE_SELECTED];
+  border_color = style->mid[GTK_STATE_NORMAL];
+  
+  bg_end_gradient = _blend_colors (bg_start_gradient, bg_end_gradient, 0.25);
+ 
+  bw->header_text_color = header_text_color;
+  bw->body_text_color = body_text_color;
+  bw->bg_start_gradient = bg_start_gradient;
+  bw->bg_end_gradient = bg_end_gradient;
+  bw->border_color = border_color;
+}
+
+
+static void
 draw_bubble_widget (EggNotificationBubbleWidget *bubble_widget)
 {
   GtkRequisition requisition;
-  GtkStyle *style;
   gint x, y, w, h;
   GdkScreen *screen;
   gint monitor_num;
   GdkRectangle monitor;
-  GdkPoint triangle_points[3];
   GdkRectangle rectangle;
-  GdkRegion *region;
-  GdkRegion *triangle_region;
-
+  cairo_pattern_t *pat;
+  GdkPixmap *mask;
+  GdkPoint arrow_pos;
+  PangoAttribute *body_text_color;
+  PangoAttrList *attrlist;
+  
   int orient;
   int orient_triangle;  
   guint rectangle_border;
   GtkWidget *widget;
   cairo_t *cairo_context;
+  cairo_t *mask_cr;
+  gboolean can_composite;
 
   widget = GTK_WIDGET(bubble_widget);
   cairo_context = gdk_cairo_create (widget->window);
   
+  can_composite = bubble_widget->can_composite;
+
+  _calculate_colors_from_style (bubble_widget);
  
-  gtk_widget_ensure_style (widget);
-  style = widget->style;
- 
+  x = bubble_widget->x;
+  y = bubble_widget->y;
+
+  screen = gtk_window_get_screen (GTK_WINDOW(widget));
+  monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
+  gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
+
+  if (x < (monitor.x + monitor.width) / 2)
+    {
+      orient_triangle = TRIANGLE_LEFT;
+    }
+  else
+    { 
+      orient_triangle = TRIANGLE_RIGHT;
+    }
+
   gtk_widget_size_request (widget, &requisition);
   w = requisition.width;
   h = requisition.height;
 
-  x = bubble_widget->x;
-  y = bubble_widget->y;
+  if (!can_composite)
+    {
+      mask = gdk_pixmap_new (NULL, w, h, 1);
+      mask_cr = gdk_cairo_create ((GdkDrawable *) mask);
+    }
 
   orient = ORIENT_TOP;
 
-  screen = gtk_window_get_screen (GTK_WINDOW(widget));
-  monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
-  gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
-
   if ((y + h) > monitor.y + monitor.height)
     {
       y -= (h + 5);
@@ -576,232 +891,131 @@
   rectangle.width = w - (rectangle_border * 2);
   rectangle.height = h - (rectangle_border * 2);
 
-  if (x < (monitor.x + monitor.width) / 2)
+  if (orient == ORIENT_TOP)
     {
-      orient_triangle = TRIANGLE_LEFT;
-      triangle_points[0].x = rectangle.x;
+      if (orient_triangle == TRIANGLE_LEFT)
+        {
+          arrow_pos = 
+            _stencil_bubble_top_left (cairo_context, &rectangle, x, y);
+          if (!can_composite)
+            _stencil_bubble_top_left (mask_cr, &rectangle, x, y);
+        }
+      else
+        {
+          arrow_pos = 
+            _stencil_bubble_top_right (cairo_context, &rectangle, x, y);
+          if (!can_composite)
+            _stencil_bubble_top_right (mask_cr, &rectangle, x, y);
+        }
     }
   else
-    { 
-      orient_triangle = TRIANGLE_RIGHT;
-      triangle_points[0].x = rectangle.x + rectangle.width - 10;
-    }
-
-  cairo_set_line_width (cairo_context, 1.0);
-  region = add_bevels_to_rectangle (&rectangle, cairo_context, orient, orient_triangle);
-
-  triangle_points[0].y = orient == ORIENT_TOP ? rectangle.y : rectangle.y + rectangle.height;
-  triangle_points[1].x = triangle_points[0].x + 10;
-  triangle_points[1].y = triangle_points[0].y;
-  triangle_points[2].y = orient == ORIENT_TOP ? 0 : h;
-
-  if (orient_triangle == TRIANGLE_LEFT)
-    triangle_points[2].x = triangle_points[0].x;
-  else
-    triangle_points[2].x = triangle_points[1].x;
-
-  triangle_region = gdk_region_polygon (triangle_points, 3, GDK_WINDING_RULE);
-  gdk_region_union (region, triangle_region);
-  gdk_region_destroy (triangle_region);
-
-  gdk_window_shape_combine_region (widget->window, region, 0, 0);
-
-  if (orient == ORIENT_TOP)
     {
-      /* top from triangle */
       if (orient_triangle == TRIANGLE_LEFT)
         {
-          cairo_move_to (cairo_context, triangle_points[0].x + 0.5, triangle_points[0].y); 
-          cairo_line_to (cairo_context, triangle_points[2].x + 0.5, triangle_points[2].y);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_MEDIUM);
-          
-          cairo_move_to (cairo_context, triangle_points[2].x - 0.5, triangle_points[2].y + 0.5);
-          cairo_line_to (cairo_context, triangle_points[1].x - 0.5, triangle_points[1].y + 0.5);
-          cairo_stroke (cairo_context);
-
-          cairo_move_to (cairo_context, triangle_points[0].x + 1.5, triangle_points[0].y + 5); 
-          cairo_line_to (cairo_context, triangle_points[2].x + 1.5, triangle_points[2].y);
-          cairo_line_to (cairo_context, triangle_points[1].x - 1.5, triangle_points[1].y + 1.5);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-          cairo_stroke (cairo_context);
-
-          cairo_move_to (cairo_context, triangle_points[1].x, triangle_points[1].y + 0.5);
-          cairo_line_to (cairo_context, rectangle.x + rectangle.width, rectangle.y + 0.5);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_MEDIUM);
-          cairo_stroke (cairo_context);
-
-          cairo_move_to (cairo_context, triangle_points[1].x + 1, triangle_points[1].y + 1.5);
-          cairo_line_to (cairo_context, rectangle.x + rectangle.width - 5, rectangle.y + 1.5);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-          cairo_stroke (cairo_context);
+          arrow_pos = 
+            _stencil_bubble_bottom_left (cairo_context, &rectangle, x, y);
+          if (!can_composite)
+            _stencil_bubble_bottom_left (mask_cr, &rectangle, x, y);
         }
-      
-      /* right */
-      cairo_move_to (cairo_context, rectangle.x + rectangle.width - 0.5, rectangle.y + 1.5);
-      cairo_line_to (cairo_context, rectangle.x + rectangle.width - 0.5 , rectangle.y + rectangle.height);
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_DARK);
-      cairo_stroke (cairo_context);
-      
-      cairo_move_to (cairo_context, rectangle.x + rectangle.width - 1.5, rectangle.y + 4.5);
-      cairo_line_to (cairo_context, rectangle.x + rectangle.width - 1.5 , rectangle.y + rectangle.height - 4.5);
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-      cairo_stroke (cairo_context);
- 
-      /* bottom */
-      cairo_move_to (cairo_context, rectangle.x + rectangle.width, rectangle.y + rectangle.height - 0.5);
-      cairo_line_to (cairo_context, rectangle.x, rectangle.y + rectangle.height - 0.5);
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_DARK);
-      cairo_stroke (cairo_context);
-
-      cairo_move_to (cairo_context, rectangle.x + rectangle.width - 5, rectangle.y + rectangle.height - 1.5);
-      cairo_line_to (cairo_context, rectangle.x + 5, rectangle.y + rectangle.height - 1.5);
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-      cairo_stroke (cairo_context);
-
-      /* left */
-      cairo_move_to (cairo_context, rectangle.x + 0.5, rectangle.y + rectangle.height);
-      cairo_line_to (cairo_context, rectangle.x + 0.5, rectangle.y);
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_MEDIUM);
-      cairo_stroke (cairo_context);
-
-      cairo_move_to (cairo_context, rectangle.x + 1.5, rectangle.y + rectangle.height - 5);
-      cairo_line_to (cairo_context, rectangle.x + 1.5, rectangle.y + 5);
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-      cairo_stroke (cairo_context);
-
-      /* top back to triangle */
-      if (orient_triangle == TRIANGLE_RIGHT)
+      else
         {
-
-          cairo_move_to (cairo_context, triangle_points[0].x - 0.5, triangle_points[0].y + 0.5); 
-          cairo_line_to (cairo_context, triangle_points[2].x - 0.5, triangle_points[2].y + 0.5);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_MEDIUM);
-          cairo_stroke (cairo_context);
-          
-          cairo_move_to (cairo_context, triangle_points[2].x - 0.5, triangle_points[2].y);
-          cairo_line_to (cairo_context, triangle_points[1].x - 0.5, triangle_points[1].y + 2);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_DARK);
-          cairo_stroke (cairo_context);
-
-          cairo_move_to (cairo_context, triangle_points[0].x + 1.5, triangle_points[0].y); 
-          cairo_line_to (cairo_context, triangle_points[2].x, triangle_points[2].y);
-          cairo_move_to (cairo_context, triangle_points[1].x - 1.5, triangle_points[2].y);
-          cairo_line_to (cairo_context, triangle_points[1].x - 1.5, triangle_points[1].y + 4.5);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-          cairo_stroke (cairo_context);
-  
-          cairo_move_to (cairo_context, rectangle.x, rectangle.y + 0.5);
-          cairo_line_to (cairo_context, triangle_points[0].x, triangle_points[0].y + 0.5);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_MEDIUM);
-          cairo_stroke (cairo_context);
-
-          cairo_move_to (cairo_context, rectangle.x + 5, rectangle.y + 1.5);
-          cairo_line_to (cairo_context, triangle_points[0].x, triangle_points[0].y + 1.5);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-          cairo_stroke (cairo_context);
-
+          arrow_pos = 
+            _stencil_bubble_bottom_right (cairo_context, &rectangle, x, y);
+          if (!can_composite)
+            _stencil_bubble_bottom_right (mask_cr, &rectangle, x, y);
         }
+    }
 
+  //cairo_set_source_rgba (cairo_context, 0.43, 0.49, 0.55, 1);
 
-    }
+  if (can_composite)
+    cairo_set_source_rgba (cairo_context, 1, 1, 1, 0);
   else
-    {
-      /* bottom from triangle */
-      if (orient_triangle == TRIANGLE_LEFT)
-        {
-          cairo_move_to (cairo_context, triangle_points[0].x + 0.5, triangle_points[0].y); 
-          cairo_line_to (cairo_context, triangle_points[2].x + 0.5, triangle_points[2].y);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_MEDIUM);
-          cairo_stroke (cairo_context);
+    cairo_set_source_rgba (cairo_context, 
+                           bubble_widget->border_color.red / 65535.0, 
+                           bubble_widget->border_color.green / 65535.0,
+                           bubble_widget->border_color.blue / 65535.0, 1);
+                         
+  cairo_set_operator (cairo_context, CAIRO_OPERATOR_SOURCE);
+  cairo_paint (cairo_context);
  
-          cairo_move_to (cairo_context, triangle_points[2].x, triangle_points[2].y);
-          cairo_line_to (cairo_context, triangle_points[1].x, triangle_points[1].y);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_DARK);
-          cairo_stroke (cairo_context);
+  cairo_set_operator (cairo_context, CAIRO_OPERATOR_OVER);
 
-          cairo_move_to (cairo_context, triangle_points[0].x + 1.5, triangle_points[0].y); 
-          cairo_line_to (cairo_context, triangle_points[2].x + 1.5, triangle_points[2].y);
-          cairo_line_to (cairo_context, triangle_points[1].x - 1.5, triangle_points[1].y + 1.5);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-          cairo_stroke (cairo_context);
+#if 0
+  //create shadow
+  if (can_composite)
+    {
+      cairo_path_t *path;
+      cairo_pattern_t *blur;
 
-          cairo_move_to (cairo_context, triangle_points[1].x, triangle_points[1].y - 0.5);
-          cairo_line_to (cairo_context, rectangle.x + rectangle.width, rectangle.y + rectangle.height - 0.5);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_DARK);
-          cairo_stroke (cairo_context);
+      path = cairo_copy_path_flat (cairo_context);
+      cairo_new_path (cairo_context);
       
-          cairo_move_to (cairo_context, triangle_points[1].x, triangle_points[1].y - 1.5);
-          cairo_line_to (cairo_context, rectangle.x + rectangle.width, rectangle.y + rectangle.height - 1.5);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-          cairo_stroke (cairo_context);
-        }
+      cairo_translate (cairo_context, 5, 5);
+      cairo_append_path (cairo_context, path);
+      blur = cairo_pattern_create_rgba (0, 0, 0, .75);
+      cairo_pattern_set_filter (blur, CAIRO_FILTER_GAUSSIAN);
 
-      /* top */
-      cairo_move_to (cairo_context, rectangle.x, rectangle.y + 0.5);
-      cairo_line_to (cairo_context, rectangle.x + rectangle.width, rectangle.y + 0.5);
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_MEDIUM);
-      cairo_stroke (cairo_context);
+      cairo_set_source (cairo_context, blur);
+      cairo_fill (cairo_context);
+     
+      cairo_identity_matrix (cairo_context);
+      cairo_append_path (cairo_context, path);
+     
+      cairo_pattern_destroy (blur);
+      cairo_path_destroy (path);
+    }
 
-      cairo_move_to (cairo_context, rectangle.x, rectangle.y + 1.5);
-      cairo_line_to (cairo_context, rectangle.x + rectangle.width, rectangle.y + 1.5);
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-      cairo_stroke (cairo_context);
+#endif
 
-      /* left */
-      cairo_move_to (cairo_context, rectangle.x + 0.5, rectangle.y + rectangle.height);
-      cairo_line_to (cairo_context, rectangle.x + 0.5, rectangle.y);
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_MEDIUM);
-      cairo_stroke (cairo_context);
+  pat = cairo_pattern_create_linear (0.0, 0.0,  0.0, h);
+  //cairo_pattern_add_color_stop_rgba (pat, 1, 0.59, 0.76, 0.93, 1);
+  cairo_pattern_add_color_stop_rgba (pat, 0, 
+                                     bubble_widget->bg_start_gradient.red /
+                                     65535.0, 
+                                     bubble_widget->bg_start_gradient.green /
+                                     65535.0,
+                                     bubble_widget->bg_start_gradient.blue /
+                                     65535.0, 1);
 
-      cairo_move_to (cairo_context, rectangle.x + 1.5, rectangle.y + rectangle.height);
-      cairo_line_to (cairo_context, rectangle.x + 1.5, rectangle.y);
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-      cairo_stroke (cairo_context);
+  cairo_pattern_add_color_stop_rgba (pat, 1, 
+                                     bubble_widget->bg_end_gradient.red /
+                                     65535.0, 
+                                     bubble_widget->bg_end_gradient.green /
+                                     65535.0,
+                                     bubble_widget->bg_end_gradient.blue /
+                                     65535.0, 1);
 
-      /* right */
-      cairo_move_to (cairo_context, rectangle.x + rectangle.width - 0.5, rectangle.y + 1);
-      cairo_line_to (cairo_context, rectangle.x + rectangle.width - 0.5 , rectangle.y + rectangle.height);
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_DARK);
-      cairo_stroke (cairo_context);
-      
-      cairo_move_to (cairo_context, rectangle.x + rectangle.width - 1.5, rectangle.y + 1);
-      cairo_line_to (cairo_context, rectangle.x + rectangle.width - 1.5 , rectangle.y + rectangle.height);
-      cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-      cairo_stroke (cairo_context);
+  cairo_set_source (cairo_context, pat);
+  cairo_fill_preserve (cairo_context);
+  cairo_pattern_destroy (pat);
+  
+  cairo_set_line_width (cairo_context, 3.5);
+  cairo_set_source_rgba (cairo_context, 0.43, 0.49, 0.55, 1);
+  cairo_stroke (cairo_context);
 
-      /* bottom to triangle */
-      if (orient_triangle == TRIANGLE_RIGHT)
-        {
-          cairo_move_to (cairo_context, triangle_points[0].x + 0.5, triangle_points[0].y); 
-          cairo_line_to (cairo_context, triangle_points[2].x + 0.5, triangle_points[2].y);
- 
-          cairo_move_to (cairo_context, triangle_points[2].x - 0.5, triangle_points[2].y);
-          cairo_line_to (cairo_context, triangle_points[1].x - 0.5, triangle_points[1].y);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_DARK);
-          cairo_stroke (cairo_context);
+  if (!can_composite)
+    {
+      cairo_set_operator (mask_cr, CAIRO_OPERATOR_CLEAR);
+      cairo_paint (mask_cr);
 
-          cairo_move_to (cairo_context, triangle_points[0].x + 1.5, triangle_points[0].y); 
-          cairo_line_to (cairo_context, triangle_points[2].x - 1.5, triangle_points[2].y);
-          cairo_line_to (cairo_context, triangle_points[1].x - 1.5, triangle_points[1].y);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-          cairo_stroke (cairo_context);
- 
-          cairo_move_to (cairo_context, triangle_points[0].x, triangle_points[0].y  - 0.5);
-          cairo_line_to (cairo_context, rectangle.x, rectangle.y + rectangle.height - 0.5);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_DARK);
-          cairo_stroke (cairo_context);
+      cairo_set_operator (mask_cr, CAIRO_OPERATOR_OVER);
+      cairo_set_line_width (mask_cr, 3.5);
+      cairo_set_source_rgba (mask_cr, 1, 1, 1, 1);
+      cairo_fill_preserve (mask_cr);
+      cairo_stroke (mask_cr);
 
-          cairo_move_to (cairo_context, triangle_points[0].x, triangle_points[0].y  - 1.5);
-          cairo_line_to (cairo_context, rectangle.x, rectangle.y + rectangle.height - 1.5);
-          cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, BEVEL_ALPHA_LIGHT);
-          cairo_stroke (cairo_context);
-        }
-
+      gdk_window_shape_combine_mask (widget->window,
+                                     (GdkBitmap *) mask,
+                                     0,
+                                     0);
+      gdk_pixmap_unref (mask);
+      cairo_destroy (mask_cr);
     }
 
-  region = add_bevels_to_rectangle (&rectangle, cairo_context, orient, orient_triangle);
-   
-  gtk_window_move (GTK_WINDOW (widget), x - triangle_points[2].x, y);
+  cairo_destroy (cairo_context);
+ 
+  gtk_window_move (GTK_WINDOW (widget), x - arrow_pos.x, y + 5);
   bubble_widget->active = TRUE;
 }
 
@@ -821,9 +1035,18 @@
 EggNotificationBubbleWidget*
 egg_notification_bubble_widget_new (void)
 {
-  return g_object_new (EGG_TYPE_NOTIFICATION_BUBBLE_WIDGET, "type", GTK_WINDOW_POPUP, NULL);
+  return g_object_new (EGG_TYPE_NOTIFICATION_BUBBLE_WIDGET, 
+                       "type", GTK_WINDOW_POPUP, 
+                       NULL);
 }
 
+static void 
+egg_notification_bubble_widget_context_changed_handler (EggNotificationBubbleWidget *bubble_widget)
+{
+  pango_layout_context_changed (bubble_widget->body_layout);
+}
+
+
 static void
 egg_notification_bubble_widget_event_handler (GtkWidget *widget,
 				       GdkEvent  *event,

Modified: trunk/notify-daemon-ng/src/eggnotificationbubblewidget.h
===================================================================
--- trunk/notify-daemon-ng/src/eggnotificationbubblewidget.h	2005-11-21 09:36:06 UTC (rev 2341)
+++ trunk/notify-daemon-ng/src/eggnotificationbubblewidget.h	2005-11-22 22:00:12 UTC (rev 2342)
@@ -44,11 +44,19 @@
   GtkWidget *icon;
 
   gboolean active;
-  GtkWidget *main_hbox;
+  GtkWidget *table;
   GtkWidget *bubble_widget_header_label;
   GtkWidget *bubble_widget_body_label;
+  PangoLayout *body_layout;
 
   gint x, y;
+  gboolean can_composite;
+
+  GdkColor header_text_color;
+  GdkColor body_text_color;
+  GdkColor bg_start_gradient;
+  GdkColor bg_end_gradient;
+  GdkColor border_color;
 };
 
 struct _EggNotificationBubbleWidgetClass



More information about the galago-commits mailing list