Exemple #1
0
void
eventd_nd_notification_draw(EventdNdNotification *self, cairo_surface_t *surface)
{
    gint padding;
    gint offset_y = 0;
    gdouble value = -1;

    padding = eventd_nd_style_get_bubble_padding(self->style);

    switch ( eventd_nd_style_get_text_valign(self->style) )
    {
    case EVENTD_ND_VANCHOR_BOTTOM:
        offset_y = self->content_size.height - self->text.height;
    break;
    case EVENTD_ND_VANCHOR_CENTER:
        offset_y = self->content_size.height / 2 - self->text.height / 2;
    break;
    case EVENTD_ND_VANCHOR_TOP:
    break;
    }

    if ( self->event != NULL )
    {
        GVariant *val;

        val = eventd_event_get_data(self->event, eventd_nd_style_get_template_progress(self->style));
        if ( val != NULL )
            value = g_variant_get_double(val);
        if ( eventd_nd_style_get_progress_reversed(self->style) )
            value = 1.0 - value;
    }

    cairo_t *cr;
    cr = cairo_create(surface);

    eventd_nd_draw_bubble_draw(cr, self->style, self->bubble_size.width, self->bubble_size.height, self->context->shaping, value);
    cairo_translate(cr, padding, padding);
    eventd_nd_draw_image_and_icon_draw(cr, self->image, self->icon, self->style, self->content_size.width, self->content_size.height, value);
    eventd_nd_draw_text_draw(cr, self->style, self->text.text, self->text.x, offset_y);

    cairo_destroy(cr);
    cairo_surface_flush(surface);
}
Exemple #2
0
const gchar *
_eventd_config_get_best_match(GList *list, EventdEvent *event, GQuark *current_flags)
{
    GList *match_;
    for ( match_ = list ; match_ != NULL ; match_ = g_list_next(match_) )
    {
        EventdConfigMatch *match = match_->data;
        gboolean skip = FALSE;

        if ( match->if_data != NULL )
        {
            gchar **data;
            for ( data = match->if_data ; ( *data != NULL ) && ( ! skip )  ; ++data )
            {
                if ( ! eventd_event_has_data(event, *data) )
                    skip = TRUE;
            }
            if ( skip )
                continue;
        }

        if ( match->if_data_matches != NULL )
        {
            GList *data_match_;
            const gchar *data;
            for ( data_match_ = match->if_data_matches ; ( data_match_ != NULL ) && ( ! skip ) ; data_match_ = g_list_next(data_match_) )
            {
                EventdConfigDataMatch *data_match = data_match_->data;
                if ( ( data = eventd_event_get_data(event, data_match->data) ) == NULL )
                    continue;
                if ( ! g_regex_match(data_match->regex, data, 0, NULL) )
                    skip = TRUE;
            }
            if ( skip )
                continue;
        }

        if ( current_flags != NULL )
        {
            GQuark *flag;
            if ( match->flags_whitelist != NULL )
            {
                GQuark *wflag;
                for ( wflag = match->flags_whitelist ; ( *wflag != 0 ) && ( ! skip ) ; ++wflag )
                {
                    for ( flag = current_flags ; ( *flag != 0 ) && ( ! skip ) ; ++flag )
                    {
                        if ( *flag != *wflag )
                            skip = TRUE;
                    }
                }
                if ( skip )
                    continue;
            }

            if ( match->flags_blacklist != NULL )
            {
                GQuark *bflag;
                for ( bflag = match->flags_blacklist ; ( *bflag != 0 ) && ( ! skip ) ; ++bflag )
                {
                    for ( flag = current_flags ; ( *flag != 0 ) && ( ! skip ) ; ++flag )
                    {
                        if ( *flag == *bflag )
                            skip = TRUE;
                    }
                }
                if ( skip )
                    continue;
            }
        }

        return match->id;
    }

    return NULL;
}
Exemple #3
0
EVENTD_EXPORT
FilenameProcessResult
evhelpers_filename_process(const Filename *filename, EventdEvent *event, const gchar *subdir, gchar **ret_uri, GVariant **ret_data)
{
    g_return_val_if_fail(filename != NULL, FILENAME_PROCESS_RESULT_NONE);
    g_return_val_if_fail(event != NULL, FILENAME_PROCESS_RESULT_NONE);
    g_return_val_if_fail(subdir != NULL, FILENAME_PROCESS_RESULT_NONE);
    g_return_val_if_fail(ret_uri != NULL, FILENAME_PROCESS_RESULT_NONE);
    g_return_val_if_fail(ret_data != NULL, FILENAME_PROCESS_RESULT_NONE);

    gchar *uri = NULL;

    if ( filename->data_name != NULL )
    {
        GVariant *data;
        data = eventd_event_get_data(event, filename->data_name);
        if ( data == NULL )
            return FILENAME_PROCESS_RESULT_NONE;
        if ( g_variant_is_of_type(data, G_VARIANT_TYPE_STRING) )
            uri = g_variant_dup_string(data, NULL);
        else if ( g_variant_is_of_type(data, G_VARIANT_TYPE("(msmsv)")) )
        {
            *ret_data = g_variant_ref(data);
            return FILENAME_PROCESS_RESULT_DATA;
        }
        else
            return FILENAME_PROCESS_RESULT_NONE;
    }
    else if ( filename->file_uri != NULL )
        uri = evhelpers_format_string_get_string(filename->file_uri, event, NULL, NULL);
    else
        g_return_val_if_reached(FILENAME_PROCESS_RESULT_NONE);

    if ( uri == NULL )
        return FILENAME_PROCESS_RESULT_NONE;
    if ( *uri == '\0' )
    {
        g_free(uri);
        return FILENAME_PROCESS_RESULT_NONE;
    }

    if ( g_str_has_prefix(uri, "data:") )
    {
        gchar *mime_type = uri + strlen("data:");
        if ( _evhelpers_filename_check_data_base64_prefix(mime_type) )
        {
            gchar *c;
            guchar *data;
            gsize length;

            /* We checked for ";base64," already */
            c = g_utf8_strchr(mime_type, -1, ',');
            *c = '\0';

            data = g_base64_decode(c + 1, &length);

            c = g_utf8_strchr(mime_type, c - mime_type, ';');
            *c++ = '\0';

            if ( *mime_type == '\0' )
                mime_type = NULL;

            if ( *c == '\0' )
                c = NULL;

            *ret_data = g_variant_new("(msmsv)", mime_type, c, g_variant_new_from_data(G_VARIANT_TYPE_BYTESTRING, data, length, FALSE, g_free, data));
            g_free(uri);
            return FILENAME_PROCESS_RESULT_DATA;
        }
    }
    else if ( g_str_has_prefix(uri, "file://") )
    {
        const gchar *p = uri + strlen("file://");
        if ( ! g_path_is_absolute(p) )
        {
            gchar *tmp = uri;
            if ( g_path_is_absolute(subdir) )
                uri = g_strconcat("file://", subdir, G_DIR_SEPARATOR_S, p, NULL);
            else
                uri = g_strconcat("file://", g_get_user_data_dir(), G_DIR_SEPARATOR_S PACKAGE_NAME G_DIR_SEPARATOR_S, subdir, G_DIR_SEPARATOR_S, p, NULL);
            g_free(tmp);
            p = uri + strlen("file://");
        }
        if ( g_file_test(p, G_FILE_TEST_IS_REGULAR) )
        {
            *ret_uri = uri;
            return FILENAME_PROCESS_RESULT_URI;
        }
    }
    else if ( g_str_has_prefix(uri, "theme:") )
    {
        *ret_uri = uri;
        return FILENAME_PROCESS_RESULT_THEME;
    }

    g_free(uri);

    return FILENAME_PROCESS_RESULT_NONE;
}
Exemple #4
0
static const gchar *
_evhelpers_token_list_callback(const gchar *token, guint64 value, gpointer user_data)
{
    FormatStringReplaceData *data = user_data;

    if ( data->callback != NULL )
        return data->callback(token, data->event, data->user_data);

    g_free(data->to_free);
    data->to_free = NULL;

    GVariant *content;
    content = eventd_event_get_data(data->event, token);
    if ( content == NULL )
        return NULL;

    if ( g_variant_is_of_type(content, G_VARIANT_TYPE_STRING) )
        return g_variant_get_string(content, NULL);

    if ( g_variant_is_of_type(content, G_VARIANT_TYPE_BOOLEAN) )
        return g_variant_get_boolean(content) ? "true" : NULL;

#define _evhelpers_check_type_with_format(l, U, GFormat) G_STMT_START { \
        if ( g_variant_is_of_type(content, G_VARIANT_TYPE_##U) ) \
        { \
            g_snprintf(data->number, sizeof(data->number), "%" GFormat, g_variant_get_##l(content)); \
            return data->number; \
        } \
    } G_STMT_END
#define _evhelpers_check_type(l, U) _evhelpers_check_type_with_format(l, U, G_G##U##_FORMAT)

    _evhelpers_check_type(int16, INT16);
    _evhelpers_check_type(int32, INT32);
    _evhelpers_check_type(int64, INT64);
    _evhelpers_check_type_with_format(byte, BYTE, "hhu");
    _evhelpers_check_type(uint16, UINT16);
    _evhelpers_check_type(uint32, UINT32);
    _evhelpers_check_type(uint64, UINT64);
    _evhelpers_check_type_with_format(double, DOUBLE, "lf");

#undef _evhelpers_check_type
#undef _evhelpers_check_type_with_format

    if ( g_variant_is_of_type(content, G_VARIANT_TYPE_STRING_ARRAY) )
    {
        const gchar **strv;
        gsize length;
        GString *ret;
        strv = g_variant_get_strv(content, &length);
        if ( length > 0 )
        {
            ret = g_string_sized_new(length * strlen(strv[0]));
            for ( ; *strv != NULL ; ++strv )
                g_string_append_c(g_string_append(ret, *strv), ' ');
            g_string_truncate(ret, ret->len - 1);
            data->to_free = g_string_free(ret, FALSE);
        }
    }
    else
        data->to_free = g_variant_print(content, FALSE);

    return data->to_free;
}
Exemple #5
0
static gboolean
_eventd_events_event_matches(EventdEventsEvent *self, EventdEvent *event, GQuark *current_flags)
{
    if ( self->if_data != NULL )
    {
        gchar **data;
        for ( data = self->if_data ; *data != NULL ; ++data )
        {
            if ( ! eventd_event_has_data(event, *data) )
                return FALSE;
        }
    }

    if ( self->if_data_matches != NULL )
    {
        EventdEventsEventDataMatch *match;
        GVariant *data;
        for ( match = self->if_data_matches ; match->data != NULL ; ++match )
        {
            if ( ! eventd_event_has_data(event, match->data) )
                continue;
            if ( ( data = eventd_event_get_data(event, match->data) ) == NULL )
                return FALSE;

            if ( match->key != NULL )
            {
                if ( ! g_variant_is_of_type(data, G_VARIANT_TYPE_VARDICT) )
                    return FALSE;

                data = g_variant_lookup_value(data, match->key, g_variant_get_type(match->value));
                if ( data == NULL )
                    return FALSE;
            }
            else if ( ! g_variant_type_equal(g_variant_get_type(data), g_variant_get_type(match->value)) )
                return FALSE;

            gint ret;
            ret = g_variant_compare(data, match->value);
            ret = CLAMP(ret, -1, 1);
            if ( ( ret != match->accepted[0] ) && ( ret != match->accepted[1] ) )
                return FALSE;
        }
    }

    if ( self->if_data_regexes != NULL )
    {
        EventdEventsEventDataRegex *match;
        const gchar *data;
        for ( match = self->if_data_regexes ; match->data != NULL ; ++match )
        {
            if ( ! eventd_event_has_data(event, match->data) )
                continue;
            if ( ( data = eventd_event_get_data_string(event, match->data) ) == NULL )
                return FALSE;
            if ( ! g_regex_match(match->regex, data, 0, NULL) )
                return FALSE;
        }
    }

    if ( current_flags != NULL )
    {
        GQuark *flag;
        if ( self->flags_whitelist != NULL )
        {
            GQuark *wflag;
            for ( wflag = self->flags_whitelist ; *wflag != 0 ; ++wflag )
            {
                gboolean has = FALSE;
                for ( flag = current_flags ; ( *flag != 0 ) && ( ! has ) ; ++flag )
                {
                    if ( *flag == *wflag )
                        has = TRUE;
                }
                if ( ! has )
                    return FALSE;
            }
        }

        if ( self->flags_blacklist != NULL )
        {
            GQuark *bflag;
            for ( bflag = self->flags_blacklist ; *bflag != 0 ; ++bflag )
            {
                for ( flag = current_flags ; *flag != 0 ; ++flag )
                {
                    if ( *flag == *bflag )
                        return FALSE;
                }
            }
        }
    }

    return TRUE;
}
Exemple #6
0
static void
_eventd_nd_notification_process(EventdNdNotification *self, EventdEvent *event)
{
    _eventd_nd_notification_clean(self);
    if ( event != NULL )
        self->event = eventd_event_ref(event);

    gint border, padding;
    gint progress_bar_width = 0;
    gint min_width, max_width;

    gint text_width = 0, text_max_width;
    gint image_width = 0, image_height = 0;


    switch ( self->context->shaping )
    {
    case EVENTD_ND_SHAPING_NONE:
    case EVENTD_ND_SHAPING_SHAPE:
        self->offset.x = 0;
        self->offset.y = 0;
        self->surface_size.width = 0;
        self->surface_size.height = 0;
    break;
    case EVENTD_ND_SHAPING_COMPOSITING:
    {
        gint blur, offset_x, offset_y;
        blur = eventd_nd_style_get_bubble_border_blur(self->style) * 2; /* We must reserve enough space to avoid clipping */
        offset_x = eventd_nd_style_get_bubble_border_blur_offset_x(self->style);
        offset_y = eventd_nd_style_get_bubble_border_blur_offset_y(self->style);

        self->offset.x = MAX(0, blur - offset_x);
        self->offset.y = MAX(0, blur - offset_y);
        self->surface_size.width = 2 * blur + MAX(0, ABS(offset_x) - blur);
        self->surface_size.height = 2 * blur + MAX(0, ABS(offset_y) - blur);
    }
    break;
    }
    border = eventd_nd_style_get_bubble_border(self->style);
    padding = eventd_nd_style_get_bubble_padding(self->style);
    min_width = eventd_nd_style_get_bubble_min_width(self->style);
    max_width = eventd_nd_style_get_bubble_max_width(self->style);

    switch ( eventd_nd_style_get_progress_placement(self->style) )
    {
    case EVENTD_ND_STYLE_PROGRESS_PLACEMENT_BAR_BOTTOM:
        if ( self->event != NULL )
        {
            GVariant *val;

            val = eventd_event_get_data(self->event, eventd_nd_style_get_template_progress(self->style));
            if ( val != NULL )
                progress_bar_width = eventd_nd_style_get_progress_bar_width(self->style);
        }
    break;
    case EVENTD_ND_STYLE_PROGRESS_PLACEMENT_IMAGE_BOTTOM_TOP:
    case EVENTD_ND_STYLE_PROGRESS_PLACEMENT_IMAGE_TOP_BOTTOM:
    case EVENTD_ND_STYLE_PROGRESS_PLACEMENT_IMAGE_LEFT_RIGHT:
    case EVENTD_ND_STYLE_PROGRESS_PLACEMENT_IMAGE_RIGHT_LEFT:
    case EVENTD_ND_STYLE_PROGRESS_PLACEMENT_IMAGE_CIRCULAR:
    break;
    }

    if ( max_width < 0 )
        max_width = self->context->geometry.w - 2 * ( self->queue->margin_x + border );
    max_width -= 2 * padding;
    min_width += 2 * padding;
    if ( min_width > max_width )
        min_width = max_width;

    /* proccess data and compute the bubble size */
    text_max_width = eventd_nd_style_get_text_max_width(self->style);
    if ( text_max_width < 0 )
        text_max_width = max_width;
    else
        text_max_width = MIN(text_max_width, max_width);
    self->text.text = eventd_nd_draw_text_process(self->style, self->event, text_max_width, g_queue_get_length(self->queue->wait_queue), &text_width);

    self->content_size.width = text_width;

    if ( self->content_size.width < max_width )
    {
        if ( self->event != NULL )
            eventd_nd_draw_image_and_icon_process(self->context->theme_context, self->style, self->event, max_width - self->content_size.width, self->context->geometry.s, &self->image, &self->icon, &self->text.x, &image_width, &image_height);
        self->content_size.width += image_width;
    }

    /* We are sure that min_width <= max_width */
    if ( min_width > self->content_size.width )
    {
        self->content_size.width = min_width;
        /* Let the text take the remaining space if needed (e.g. Right-to-Left) */
        text_width = self->content_size.width - image_width;
    }
    pango_layout_set_width(self->text.text, text_width * PANGO_SCALE);
    pango_layout_get_pixel_size(self->text.text, NULL, &self->text.height);

    self->content_size.height = MAX(image_height, self->text.height);

    self->bubble_size.width = self->content_size.width + 2 * padding;
    self->bubble_size.height = self->content_size.height + 2 * padding + progress_bar_width;
    self->border_size.width = self->bubble_size.width + 2 * border;
    self->border_size.height = self->bubble_size.height + 2 * border;
    self->surface_size.width += self->border_size.width;
    self->surface_size.height += self->border_size.height;

    if ( self->timeout > 0 )
    {
        g_source_remove(self->timeout);
        self->timeout = g_timeout_add_full(G_PRIORITY_DEFAULT, eventd_nd_style_get_bubble_timeout(self->style), _eventd_nd_event_timedout, self, NULL);
    }
}