static void awn_tooltip_set_mask (AwnTooltip *tooltip, gint width, gint height) { GtkWidget *widget = GTK_WIDGET (tooltip); if (gtk_widget_is_composited (widget) == FALSE) { GdkBitmap *shaped_bitmap; shaped_bitmap = (GdkBitmap*) gdk_pixmap_new (NULL, width, height, 1); if (shaped_bitmap) { cairo_t *cr = gdk_cairo_create (shaped_bitmap); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); cairo_translate (cr, 0.5, 0.5); awn_cairo_rounded_rect (cr, 0, 0, width, height, TOOLTIP_ROUND_RADIUS, ROUND_ALL); cairo_fill (cr); cairo_destroy (cr); gtk_widget_shape_combine_mask (widget, NULL, 0, 0); gtk_widget_shape_combine_mask (widget, shaped_bitmap, 0, 0); g_object_unref (shaped_bitmap); } } }
/* GObject Stuff */ static gboolean awn_tooltip_expose_event (GtkWidget *widget, GdkEventExpose *expose) { AwnTooltipPrivate *priv; cairo_t *cr; GtkAllocation alloc; gint width, height; priv = AWN_TOOLTIP (widget)->priv; gtk_widget_get_allocation (widget, &alloc); width = alloc.width; height = alloc.height; cr = gdk_cairo_create (gtk_widget_get_window (widget)); if (!cr) { return FALSE; } /* Clear the background to transparent */ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_set_line_width (cr, 1.0); /* Draw */ awn_cairo_set_source_color (cr, priv->bg); awn_cairo_rounded_rect (cr, 0, 0, width, height, TOOLTIP_ROUND_RADIUS, ROUND_ALL); if (priv->outline_color) { cairo_fill_preserve (cr); awn_cairo_set_source_color (cr, priv->outline_color); cairo_stroke (cr); } else { cairo_fill (cr); } /* Clean up */ cairo_destroy (cr); gtk_container_propagate_expose (GTK_CONTAINER (widget), gtk_bin_get_child (GTK_BIN (widget)), expose); return TRUE; }
static void paint_sad_face (cairo_t *cr) { /* sad face */ const gfloat EYE_SIZE = 0.04; gfloat EYE_POS_X, EYE_POS_Y; awn_cairo_rounded_rect(cr, 0.05, 0.05, 0.9, 0.9, 0.05, ROUND_ALL); cairo_stroke(cr); #define MINI_RECT(cr, x, y) \ cairo_rectangle (cr, x, y, EYE_SIZE, EYE_SIZE); \ cairo_fill (cr); EYE_POS_X = 0.25; EYE_POS_Y = 0.30; /* left eye */ MINI_RECT(cr, EYE_POS_X, EYE_POS_Y); MINI_RECT(cr, EYE_POS_X, EYE_POS_Y + 2*EYE_SIZE); MINI_RECT(cr, EYE_POS_X + EYE_SIZE, EYE_POS_Y + EYE_SIZE); MINI_RECT(cr, EYE_POS_X + 2*EYE_SIZE, EYE_POS_Y); MINI_RECT(cr, EYE_POS_X + 2*EYE_SIZE, EYE_POS_Y + 2*EYE_SIZE); /* right eye */ EYE_POS_X = 0.65; MINI_RECT(cr, EYE_POS_X, EYE_POS_Y); MINI_RECT(cr, EYE_POS_X, EYE_POS_Y + 2*EYE_SIZE); MINI_RECT(cr, EYE_POS_X + EYE_SIZE, EYE_POS_Y + EYE_SIZE); MINI_RECT(cr, EYE_POS_X + 2*EYE_SIZE, EYE_POS_Y); MINI_RECT(cr, EYE_POS_X + 2*EYE_SIZE, EYE_POS_Y + 2*EYE_SIZE); #undef MINI_RECT /* nose */ cairo_curve_to(cr, 0.45, 0.48, 0.5, 0.53, 0.55, 0.48); cairo_stroke(cr); /* mouth */ cairo_curve_to(cr, 0.25, 0.73, 0.5, 0.62, 0.77, 0.77); cairo_stroke(cr); }
/** * awn_cairo_rounded_rect_shadow: * * Draws a shadow for rounded rectangle via cairo. */ void awn_cairo_rounded_rect_shadow(cairo_t *cr, double rx0, double ry0, double width, double height, double radius, AwnCairoRoundCorners state, double shadow_radius, double shadow_alpha) { cairo_pattern_t *pat; const double rx1 = rx0 + width; const double ry1 = ry0 + height; const double xr = rx0 + radius; const double yr = ry0 + radius; cairo_save (cr); cairo_rectangle (cr, rx0 - shadow_radius, ry0 - shadow_radius, width + shadow_radius * 2, height + shadow_radius * 2); awn_cairo_rounded_rect (cr, rx0, ry0, width, height, radius, state); cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD); cairo_clip (cr); /* top left */ pat = cairo_pattern_create_radial (xr, yr, radius, xr, yr, radius + shadow_radius); cairo_pattern_add_color_stop_rgba (pat, 0.0, 0.0, 0.0, 0.0, shadow_alpha); cairo_pattern_add_color_stop_rgba (pat, 1./3, 0.0, 0.0, 0.0, shadow_alpha/2); cairo_pattern_add_color_stop_rgba (pat, 1.0, 0.0, 0.0, 0.0, 0.0); cairo_set_source (cr, pat); cairo_rectangle (cr, rx0 - shadow_radius, ry0 - shadow_radius, radius + shadow_radius, radius + shadow_radius); cairo_fill (cr); cairo_pattern_destroy (pat); /* top */ pat = cairo_pattern_create_linear (0.0, ry0 - shadow_radius, 0.0, ry0); cairo_pattern_add_color_stop_rgba (pat, 0.0, 0.0, 0.0, 0.0, 0.0); cairo_pattern_add_color_stop_rgba (pat, 2./3, 0.0, 0.0, 0.0, shadow_alpha/2); cairo_pattern_add_color_stop_rgba (pat, 1.0, 0.0, 0.0, 0.0, shadow_alpha); cairo_set_source (cr, pat); cairo_rectangle (cr, xr, ry0 - shadow_radius, width - radius * 2, shadow_radius); cairo_fill (cr); cairo_pattern_destroy (pat); /* top right */ pat = cairo_pattern_create_radial (rx1 - radius, yr, radius, rx1 - radius, yr, radius + shadow_radius); cairo_pattern_add_color_stop_rgba (pat, 0.0, 0.0, 0.0, 0.0, shadow_alpha); cairo_pattern_add_color_stop_rgba (pat, 1./3, 0.0, 0.0, 0.0, shadow_alpha/2); cairo_pattern_add_color_stop_rgba (pat, 1.0, 0.0, 0.0, 0.0, 0.0); cairo_set_source (cr, pat); cairo_rectangle (cr, rx1 - radius, ry0 - shadow_radius, radius + shadow_radius, radius + shadow_radius); cairo_fill (cr); cairo_pattern_destroy (pat); /* right */ pat = cairo_pattern_create_linear (rx1, 0.0, rx1 + shadow_radius, 0.0); cairo_pattern_add_color_stop_rgba (pat, 0.0, 0.0, 0.0, 0.0, shadow_alpha); cairo_pattern_add_color_stop_rgba (pat, 1./3, 0.0, 0.0, 0.0, shadow_alpha/2); cairo_pattern_add_color_stop_rgba (pat, 1.0, 0.0, 0.0, 0.0, 0.0); cairo_set_source (cr, pat); cairo_rectangle (cr, rx1, ry0 + radius, shadow_radius, height - radius * 2); cairo_fill (cr); cairo_pattern_destroy (pat); /* bottom right */ pat = cairo_pattern_create_radial (rx1 - radius, ry1 - radius, radius, rx1 - radius, ry1 - radius, radius + shadow_radius); cairo_pattern_add_color_stop_rgba (pat, 0.0, 0.0, 0.0, 0.0, shadow_alpha); cairo_pattern_add_color_stop_rgba (pat, 1./3, 0.0, 0.0, 0.0, shadow_alpha/2); cairo_pattern_add_color_stop_rgba (pat, 1.0, 0.0, 0.0, 0.0, 0.0); cairo_set_source (cr, pat); cairo_rectangle (cr, rx1 - radius, ry1 - radius, radius + shadow_radius, radius + shadow_radius); cairo_fill (cr); cairo_pattern_destroy (pat); /* bottom */ pat = cairo_pattern_create_linear (0.0, ry1, 0.0, ry1 + shadow_radius); cairo_pattern_add_color_stop_rgba (pat, 0.0, 0.0, 0.0, 0.0, shadow_alpha); cairo_pattern_add_color_stop_rgba (pat, 1./3, 0.0, 0.0, 0.0, shadow_alpha/2); cairo_pattern_add_color_stop_rgba (pat, 1.0, 0.0, 0.0, 0.0, 0.0); cairo_set_source (cr, pat); cairo_rectangle (cr, xr, ry1, width - radius * 2, shadow_radius); cairo_fill (cr); cairo_pattern_destroy (pat); /* bottom left */ pat = cairo_pattern_create_radial (xr, ry1 - radius, radius, xr, ry1 - radius, radius + shadow_radius); cairo_pattern_add_color_stop_rgba (pat, 0.0, 0.0, 0.0, 0.0, shadow_alpha); cairo_pattern_add_color_stop_rgba (pat, 1./3, 0.0, 0.0, 0.0, shadow_alpha/2); cairo_pattern_add_color_stop_rgba (pat, 1.0, 0.0, 0.0, 0.0, 0.0); cairo_set_source (cr, pat); cairo_rectangle (cr, rx0 - shadow_radius, ry1 - radius, radius + shadow_radius, radius + shadow_radius); cairo_fill (cr); cairo_pattern_destroy (pat); /* left */ pat = cairo_pattern_create_linear (rx0 - shadow_radius, 0.0, rx0, 0.0); cairo_pattern_add_color_stop_rgba (pat, 0.0, 0.0, 0.0, 0.0, 0.0); cairo_pattern_add_color_stop_rgba (pat, 2./3, 0.0, 0.0, 0.0, shadow_alpha/2); cairo_pattern_add_color_stop_rgba (pat, 1.0, 0.0, 0.0, 0.0, shadow_alpha); cairo_set_source (cr, pat); cairo_rectangle (cr, rx0 - shadow_radius, yr, shadow_radius, height - radius * 2); cairo_fill (cr); cairo_pattern_destroy (pat); cairo_restore (cr); }
static gboolean awn_throbber_expose_event (GtkWidget *widget, GdkEventExpose *event) { AwnThrobberPrivate *priv = AWN_THROBBER (widget)->priv; cairo_t *cr; gint w, h; GtkPositionType pos_type; /* clip the drawing region, nvidia likes it */ AwnEffects *fx = awn_overlayable_get_effects (AWN_OVERLAYABLE (widget)); cr = awn_effects_cairo_create_clipped (fx, event); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); // we'll paint to [0,0] - [1,1], so scale's needed g_object_get (G_OBJECT (widget), "icon-width", &w, "icon-height", &h, NULL); cairo_scale (cr, w, h); switch (priv->type) { case AWN_THROBBER_TYPE_NORMAL: { const gdouble RADIUS = 0.0625; const gdouble DIST = 0.3; const gdouble OTHER = DIST * 0.707106781; /* sqrt(2)/2 */ const gint COUNT = 8; const gint counter = priv->counter; cairo_set_line_width (cr, 1. / priv->size); cairo_translate (cr, 0.5, 0.5); cairo_scale (cr, 1, -1); #define PAINT_CIRCLE(cr, x, y, cnt) \ awn_cairo_set_source_color_with_alpha_multiplier (cr, \ priv->fill_color, ((counter+cnt) % COUNT) / (float)COUNT); \ cairo_arc (cr, x, y, RADIUS, 0, 2*M_PI); \ cairo_fill_preserve (cr); \ awn_cairo_set_source_color_with_alpha_multiplier (cr, \ priv->outline_color, ((counter+cnt) % COUNT) / (float)COUNT); \ cairo_stroke (cr); PAINT_CIRCLE (cr, 0, DIST, 0); PAINT_CIRCLE (cr, OTHER, OTHER, 1); PAINT_CIRCLE (cr, DIST, 0, 2); PAINT_CIRCLE (cr, OTHER, -OTHER, 3); PAINT_CIRCLE (cr, 0, -DIST, 4); PAINT_CIRCLE (cr, -OTHER, -OTHER, 5); PAINT_CIRCLE (cr, -DIST, 0, 6); PAINT_CIRCLE (cr, -OTHER, OTHER, 7); #undef PAINT_CIRCLE break; } case AWN_THROBBER_TYPE_SAD_FACE: { cairo_set_line_width (cr, 0.03); if (priv->fill_color == NULL) { GdkColor c; double r, g, b; c = gtk_widget_get_style (widget)->fg[GTK_STATE_NORMAL]; r = c.red / 65535.0; g = c.green / 65535.0; b = c.blue / 65535.0; cairo_set_source_rgb (cr, r, g, b); } else { awn_cairo_set_source_color_with_alpha_multiplier (cr, priv->fill_color, 0.75); } paint_sad_face (cr); break; } case AWN_THROBBER_TYPE_ARROW_1: cairo_rotate (cr, M_PI); cairo_translate (cr, -1.0, -1.0); // no break case AWN_THROBBER_TYPE_ARROW_2: { pos_type = awn_icon_get_pos_type (AWN_ICON (widget)); if (pos_type == GTK_POS_LEFT || pos_type == GTK_POS_RIGHT) { cairo_rotate (cr, 0.5 * M_PI); cairo_translate (cr, 0.0, -1.0); } if (priv->outline_color) { cairo_set_line_width (cr, 3.5 / priv->size); awn_cairo_set_source_color (cr, priv->outline_color); cairo_move_to (cr, 0.125, 0.375); cairo_line_to (cr, 0.875, 0.5); cairo_line_to (cr, 0.125, 0.625); cairo_stroke (cr); } cairo_set_line_width (cr, 1.75 / priv->size); if (priv->fill_color == NULL) { GdkColor c = gtk_widget_get_style (widget)->fg[GTK_STATE_NORMAL]; double r = c.red / 65535.0; double g = c.green / 65535.0; double b = c.blue / 65535.0; cairo_set_source_rgb (cr, r, g, b); } else { awn_cairo_set_source_color (cr, priv->fill_color); } cairo_move_to (cr, 0.125, 0.375); cairo_line_to (cr, 0.875, 0.5); cairo_line_to (cr, 0.125, 0.625); cairo_stroke (cr); break; } case AWN_THROBBER_TYPE_CLOSE_BUTTON: { cairo_set_line_width (cr, 1. / priv->size); cairo_pattern_t *pat = cairo_pattern_create_linear (0.0, 0.0, 0.5, 1.0); cairo_pattern_add_color_stop_rgb (pat, 0.0, 0.97254, 0.643137, 0.403921); //cairo_pattern_add_color_stop_rgb (pat, 0.0, 0.0, 0.0, 0.0); // test cairo_pattern_add_color_stop_rgb (pat, 0.7, 0.98823, 0.4, 0.0); cairo_pattern_add_color_stop_rgb (pat, 1.0, 0.98823, 0.4, 0.0); cairo_set_source (cr, pat); //cairo_arc (cr, 0.5, 0.5, 0.4, 0.0, 2 * M_PI); awn_cairo_rounded_rect (cr, 0.1, 0.1, 0.8, 0.8, 0.15, ROUND_ALL); cairo_fill_preserve (cr); cairo_pattern_destroy (pat); cairo_set_source_rgba (cr, 0.5, 0.5, 0.5, 0.5); cairo_stroke (cr); cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); cairo_set_line_width (cr, 2./priv->size); /* \ starting with the upper point */ cairo_move_to (cr, 0.3, 0.25); cairo_line_to (cr, 0.7, 0.75); cairo_stroke (cr); /* / starting with the upper point */ cairo_move_to (cr, 0.7, 0.25); cairo_line_to (cr, 0.3, 0.75); cairo_stroke (cr); break; } default: break; } /* let effects know we're finished */ awn_effects_cairo_destroy (fx); return TRUE; }
static gboolean render(GtkWidget ** pwidget, gint interval, Uptime_plug_data **p) { char buf[256]; glibtop_uptime uptime; long tmp; Uptime_plug_data * data = *p; static int width = -1; static int height = -1; cairo_text_extents_t extents; dashboard_cairo_widget c_widge; float mult; data->timer = data->timer - interval; if ((data->timer <= 0) || (data->forceupdate)) { data->forceupdate = FALSE; glibtop_get_uptime(&uptime); tmp = uptime.uptime; data->seconds = tmp % 60; tmp = tmp / 60; //tmp is now minutes data->minutes = tmp % 60; tmp = tmp / 60; //tmp now hours data->hours = tmp % 24; tmp = tmp / 24; data->days = tmp; if (data->show_seconds) { snprintf(buf, sizeof(buf), "Up Time:%d:%02d:%02d:%02d", data->days, data->hours, data->minutes, data->seconds); } else { snprintf(buf, sizeof(buf), "Up Time:%d:%02d:%02d", data->days, data->hours, data->minutes); } if (data->show_seconds) { data->timer = 900; } else { data->timer = 1000 * 55; } /*there is an issue if this widget starts out overly large... the maintable sizes itself too and doesn't properly resize itself downwards... So we start small for the first second and that way give it time to shrink before adjusting to a large scale */ if (width < 0) { snprintf(buf, sizeof(buf), "Up Time:%d:%02d:%02d:%02d", data->days, data->hours, data->minutes, data->seconds); *pwidget = get_cairo_widget(&c_widge, 200, 30); mult = 1; use_bg_rgba_colour(c_widge.cr); cairo_set_operator(c_widge.cr, CAIRO_OPERATOR_SOURCE); cairo_paint(c_widge.cr); data->timer = interval; } else { mult = data->size_mult; *pwidget = get_cairo_widget(&c_widge, width * mult, height * mult); awn_cairo_rounded_rect(c_widge.cr, 0, 0, width*mult, height*mult, height*mult*0.1, ROUND_ALL); cairo_set_source_rgba(c_widge.cr, data->bg.red, data->bg.green, data->bg.blue, data->bg.alpha); cairo_fill(c_widge.cr); } cairo_select_font_face(c_widge.cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(c_widge.cr, dashboard_get_font_size(DASHBOARD_FONT_SMALL)*mult); cairo_set_source_rgba(c_widge.cr, data->fg.red, data->fg.green, data->fg.blue, data->fg.alpha); cairo_move_to(c_widge.cr, 5.0*mult, height*mult*0.7); if (width < 0) { cairo_text_extents(c_widge.cr, buf, &extents); height = extents.height + 2; width = extents.width + 10; return TRUE; } cairo_show_text(c_widge.cr, buf); del_cairo_widget(&c_widge); return TRUE; } else { return FALSE; } }