Projects
Eulaceura:Mainline:GA
mate-notification-daemon
_service:obs_scm:0002-features-add-new-kiran-th...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:0002-features-add-new-kiran-themes-in-mate-notification.patch of Package mate-notification-daemon
From 507a6bf07ab39523df276a51a8b44ec8f9a235bd Mon Sep 17 00:00:00 2001 From: yuanxing <yuanxing@kylinos.com.cn> Date: Fri, 22 Jan 2021 10:33:30 +0800 Subject: [PATCH 1/9] features: add new kiran themes in mate-notification-properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加新的kiran消息框主题 Realated #33420 --- configure.ac | 1 + po/POTFILES.in | 1 + po/zh_CN.po | 13 + src/capplet/mate-notification-properties.c | 4 + src/daemon/daemon.c | 2 +- src/themes/Makefile.am | 2 +- src/themes/kiran/Makefile.am | 28 + src/themes/kiran/data/icons/close_hover.svg | 16 + src/themes/kiran/data/icons/close_normal.svg | 11 + src/themes/kiran/data/icons/close_press.svg | 16 + src/themes/kiran/data/kiran.css | 91 ++ src/themes/kiran/kiran.c | 934 +++++++++++++++++++ src/themes/kiran/kiran.gresource.xml | 9 + 13 files changed, 1126 insertions(+), 2 deletions(-) create mode 100644 src/themes/kiran/Makefile.am create mode 100644 src/themes/kiran/data/icons/close_hover.svg create mode 100644 src/themes/kiran/data/icons/close_normal.svg create mode 100644 src/themes/kiran/data/icons/close_press.svg create mode 100644 src/themes/kiran/data/kiran.css create mode 100644 src/themes/kiran/kiran.c create mode 100644 src/themes/kiran/kiran.gresource.xml diff --git a/configure.ac b/configure.ac index a43ad19..dea982e 100644 --- a/configure.ac +++ b/configure.ac @@ -249,6 +249,7 @@ src/themes/coco/Makefile src/themes/nodoka/Makefile src/themes/slider/Makefile src/themes/standard/Makefile +src/themes/kiran/Makefile ]) AC_OUTPUT diff --git a/po/POTFILES.in b/po/POTFILES.in index 64a83b1..e3f7c90 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -8,3 +8,4 @@ src/themes/coco/coco-theme.c src/themes/nodoka/nodoka-theme.c src/themes/slider/theme.c src/themes/standard/theme.c +src/themes/kiran/kiran.c diff --git a/po/zh_CN.po b/po/zh_CN.po index 294734f..e2f2551 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -270,2 +270,14 @@ msgid "Closes the notification." msgstr "关闭通知" + +#: ../src/themes/kiran/kiran.c +msgid "Normal Notification" +msgstr "一般信息通知" + +#: ../src/themes/kiran/kiran.c +msgid "Low Notification" +msgstr "低优先级通知" + +#: ../src/themes/kiran/kiran.c +msgid "Critical Notification" +msgstr "重要通知" \ No newline at end of file diff --git a/src/capplet/mate-notification-properties.c b/src/capplet/mate-notification-properties.c index 2f5b103..09b6643 100644 --- a/src/capplet/mate-notification-properties.c +++ b/src/capplet/mate-notification-properties.c @@ -340,6 +340,10 @@ static void notification_properties_dialog_setup_themes(NotificationAppletDialog { theme_label = g_strdup(_("Standard theme")); } + else if (g_str_equal(theme_name, "kiran")) + { + theme_label = g_strdup(_("Kiran")); + } else { theme_label = g_strdup(theme_name); diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index c418809..3ee2266 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c @@ -1352,8 +1352,8 @@ static gboolean notify_daemon_notify_handler(NotifyDaemonNotifications *object, theme_clear_notification_actions (nw); } - theme_set_notification_text (nw, summary, body); theme_set_notification_hints (nw, hints); + theme_set_notification_text (nw, summary, body); /* *XXX This needs to handle file URIs and all that. diff --git a/src/themes/Makefile.am b/src/themes/Makefile.am index 160000b..99df82a 100644 --- a/src/themes/Makefile.am +++ b/src/themes/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS = coco nodoka slider standard +SUBDIRS = coco nodoka slider standard kiran -include $(top_srcdir)/git.mk diff --git a/src/themes/kiran/Makefile.am b/src/themes/kiran/Makefile.am new file mode 100644 index 0000000..fcb1626 --- /dev/null +++ b/src/themes/kiran/Makefile.am @@ -0,0 +1,28 @@ +NULL = + +enginedir = $(libdir)/mate-notification-daemon/engines +engine_LTLIBRARIES = libkiran.la + +RESOURCE_XML=kiran.gresource.xml +GLIB_COMPILE_RESOURCE=glib-compile-resources + +AM_CPPFLAGS = $(THEME_CFLAGS) + +gresource.c: $(RESOURCE_XML) + $(GLIB_COMPILE_RESOURCE) --target $@ $< --generate --c-name kiran + +gresource.h: $(RESOURCE_XML) + $(GLIB_COMPILE_RESOURCE) --target $@ $< --generate --c-name kiran + +libkiran_la_SOURCES = kiran.c gresource.c gresource.h + +libkiran_la_LDFLAGS = -module -avoid-version -no-undefined +libkiran_la_LIBADD = \ + $(THEME_LIBS) \ + $(NULL) + +-include $(top_srcdir)/git.mk + +.PHONY :clean +clean: + rm -f gresource.c gresource.h \ No newline at end of file diff --git a/src/themes/kiran/data/icons/close_hover.svg b/src/themes/kiran/data/icons/close_hover.svg new file mode 100644 index 0000000..1edd094 --- /dev/null +++ b/src/themes/kiran/data/icons/close_hover.svg @@ -0,0 +1,16 @@ +<svg id="close_s" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"> + <defs> + <style> + .cls-1 { + fill: #ea4565; + } + + .cls-2 { + fill: #fff; + fill-rule: evenodd; + } + </style> + </defs> + <rect id="矩形_705" data-name="矩形 705" class="cls-1" width="16" height="16"/> + <path id="关闭" class="cls-2" d="M1181.99,1090.16l-0.83.83-4.16-4.16-4.16,4.16-0.83-.83,4.16-4.16-4.16-4.16,0.83-.83,4.16,4.16,4.16-4.16,0.83,0.83-4.16,4.16Z" transform="translate(-1169 -1078)"/> +</svg> diff --git a/src/themes/kiran/data/icons/close_normal.svg b/src/themes/kiran/data/icons/close_normal.svg new file mode 100644 index 0000000..5b94a31 --- /dev/null +++ b/src/themes/kiran/data/icons/close_normal.svg @@ -0,0 +1,11 @@ +<svg id="close_n" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"> + <defs> + <style> + .cls-1 { + fill: #fff; + fill-rule: evenodd; + } + </style> + </defs> + <path id="关闭" class="cls-1" d="M1181.99,1090.16l-0.83.83-4.16-4.16-4.16,4.16-0.83-.83,4.16-4.16-4.16-4.16,0.83-.83,4.16,4.16,4.16-4.16,0.83,0.83-4.16,4.16Z" transform="translate(-1169 -1078)"/> +</svg> diff --git a/src/themes/kiran/data/icons/close_press.svg b/src/themes/kiran/data/icons/close_press.svg new file mode 100644 index 0000000..7a75734 --- /dev/null +++ b/src/themes/kiran/data/icons/close_press.svg @@ -0,0 +1,16 @@ +<svg id="close_pre" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"> + <defs> + <style> + .cls-1 { + fill: #b8354f; + } + + .cls-2 { + fill: #fff; + fill-rule: evenodd; + } + </style> + </defs> + <rect id="矩形_705" data-name="矩形 705" class="cls-1" width="16" height="16"/> + <path id="关闭" class="cls-2" d="M1181.99,1090.16l-0.83.83-4.16-4.16-4.16,4.16-0.83-.83,4.16-4.16-4.16-4.16,0.83-.83,4.16,4.16,4.16-4.16,0.83,0.83-4.16,4.16Z" transform="translate(-1169 -1078)"/> +</svg> diff --git a/src/themes/kiran/data/kiran.css b/src/themes/kiran/data/kiran.css new file mode 100644 index 0000000..2f9123e --- /dev/null +++ b/src/themes/kiran/data/kiran.css @@ -0,0 +1,91 @@ +/******************Label******************************/ +#summary_label +{ + color:#ffffff; + font-size:14px; + font-family: "Noto Sans CJK SC regular"; + padding-bottom: 8px; +} + +#body_label +{ + color: #919191; + font-size: 12px; + font-family: "Noto Sans CJK SC regular"; + line-height:12px; +} + +#actions_label +{ + color: #3197de; + font-size: 12px; + font-family: "PingFang SC Medium"; +} + + +/*********************Button****************************/ + +#actions_button,#actions_hbox +{ + padding:0px; + box-shadow:none; + margin:0px; +} + +#actions_button:hover +{ + border-bottom:1px solid #3197DE; +} + +#close_button +{ + background-image: url("/kiran/themes/close_normal"); + background-repeat: no-repeat; + background-position: center; + background-color: transparent; + padding: 0px; + border: none; + margin: 0px; + box-shadow: 0px; +} + +#close_button:hover +{ + background-image: url("/kiran/themes/close_hover"); + background-repeat: no-repeat; + background-position: center; +} + +#close_button:active +{ + background-image: url("/kiran/themes/close_press"); + background-repeat: no-repeat; + background-position: center; +} + +/***********************Box***********************/ +#main_hbox , #main_vbox +{ + margin: 0px; + padding: 0px; + box-shadow: 0px; +} + +#main_hbox +{ + /* background-color: yellow; */ + margin-right: 14px; + margin-bottom: 12px; +} + +#icon_box +{ + margin-left: 12px; + margin-top: 12px; + margin-right: 12px; +} + +#text_vbox ,#action_vbox +{ + margin-top: 16px; +} diff --git a/src/themes/kiran/kiran.c b/src/themes/kiran/kiran.c new file mode 100644 index 0000000..9181e20 --- /dev/null +++ b/src/themes/kiran/kiran.c @@ -0,0 +1,934 @@ +/* + * kiran.c + * This file is part of notification-daemon-engine-kiran + * + * Copyright (C) 2012 - Stefano Karapetsas <stefano@karapetsas.com> + * Copyright (C) 2010 - Eduardo Grajeda + * Copyright (C) 2008 - Martin Sourada + * + * notification-daemon-engine-kiran is free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the License, + * or (at your option) any later version. + * + * notification-daemon-engine-kiran is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with notification-daemon-engine-kiran; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include <glib/gi18n.h> +#include <gtk/gtk.h> +#include <gtk/gtkx.h> +#include <gmodule.h> +#include "gresource.h" + +/* Define basic kiran types */ +typedef void (*ActionInvokedCb)(GtkWindow *nw, const char *key); +typedef void (*UrlClickedCb)(GtkWindow *nw, const char *url); + +typedef struct +{ + GtkWidget *win; + GtkWidget *top_spacer; + GtkWidget *bottom_spacer; + GtkWidget *main_hbox; + GtkWidget *iconbox; + GtkWidget *icon; + GtkWidget *close_button; + GtkWidget *summary_label; + GtkWidget *body_label; + GtkWidget *actions_box; + GtkWidget *last_sep; + GtkWidget *stripe_spacer; + GtkWidget *pie_countdown; + + gboolean composited; + gboolean action_icons; + + int width; + int height; + int last_width; + int last_height; + + guchar urgency; + glong timeout; + glong remaining; + + UrlClickedCb url_clicked; + + GtkTextDirection rtl; +} WindowData; + + +enum +{ + URGENCY_LOW, + URGENCY_NORMAL, + URGENCY_CRITICAL +}; + +gboolean theme_check_init(unsigned int major_ver, unsigned int minor_ver, + unsigned int micro_ver); +void get_theme_info(char **theme_name, char **theme_ver, char **author, + char **homepage); +GtkWindow* create_notification(UrlClickedCb url_clicked); +void set_notification_text(GtkWindow *nw, const char *summary, + const char *body); +void set_notification_icon(GtkWindow *nw, GdkPixbuf *pixbuf); +void set_notification_arrow(GtkWidget *nw, gboolean visible, int x, int y); +void add_notification_action(GtkWindow *nw, const char *text, const char *key, + ActionInvokedCb cb); +void clear_notification_actions(GtkWindow *nw); +void move_notification(GtkWidget *nw, int x, int y); +void set_notification_timeout(GtkWindow *nw, glong timeout); +void set_notification_hints(GtkWindow *nw, GVariant *hints); +void notification_tick(GtkWindow *nw, glong remaining); + +#define STRIPE_WIDTH 32 +#define WIDTH 270 +#define IMAGE_SIZE 32 +#define IMAGE_PADDING 10 +#define SPACER_LEFT 30 +#define PIE_RADIUS 7 +#define PIE_WIDTH (2 * PIE_RADIUS) +#define PIE_HEIGHT (2 * PIE_RADIUS) +#define BODY_X_OFFSET (IMAGE_SIZE + 8) +#define DEFAULT_ARROW_OFFSET (SPACER_LEFT + 12) +#define DEFAULT_ARROW_HEIGHT 14 +#define DEFAULT_ARROW_WIDTH 22 +#define DEFAULT_ARROW_SKEW -6 +#define BACKGROUND_OPACITY 1.0 +#define GRADIENT_CENTER 0.7 + +/* Support Nodoka Functions */ + +/* Handle clicking on link */ +static gboolean +activate_link (GtkLabel *label, const char *url, WindowData *windata) +{ + windata->url_clicked (GTK_WINDOW (windata->win), url); + return TRUE; +} + +static void +destroy_windata(WindowData *windata) +{ + g_free(windata); +} + +/* Draw fuctions */ +/* Standard rounded rectangle */ +static void +nodoka_rounded_rectangle (cairo_t * cr, + double x, double y, double w, double h, + int radius) +{ + cairo_move_to (cr, x + radius, y); + cairo_arc (cr, x + w - radius, y + radius, radius, G_PI * 1.5, G_PI * 2); + cairo_arc (cr, x + w - radius, y + h - radius, radius, 0, G_PI * 0.5); + cairo_arc (cr, x + radius, y + h - radius, radius, G_PI * 0.5, G_PI); + cairo_arc (cr, x + radius, y + radius, radius, G_PI, G_PI * 1.5); +} + +/* Fill background */ +static void +fill_background(GtkWidget *widget, WindowData *windata, cairo_t *cr) +{ + float alpha; + if (windata->composited) + alpha = BACKGROUND_OPACITY; + else + alpha = 1.0; + + cairo_pattern_t *pattern; + pattern = cairo_pattern_create_linear (0, 0, 0, windata->height); + cairo_pattern_add_color_stop_rgba (pattern, 0, + 34/255.0, 34/255.0, 34/255.0, alpha); + cairo_pattern_add_color_stop_rgba (pattern, GRADIENT_CENTER, + 34/255.0, 34/255.0, 34/255.0, alpha); + cairo_pattern_add_color_stop_rgba (pattern, 1, + 34/255.0, 34/255.0, 34/255.0, alpha); + cairo_set_source (cr, pattern); + cairo_pattern_destroy (pattern); + + nodoka_rounded_rectangle (cr, 0, 0, windata->width, + windata->height, 6); + + cairo_fill (cr); +} + + +/** + * @brief 当鼠标进入消息框窗体时,重绘背景 + */ +static void +fill_background_when_pointer_enter(GtkWidget *widget, WindowData *windata, cairo_t *cr) +{ + float alpha; + if (windata->composited) + alpha = BACKGROUND_OPACITY; + else + alpha = 1.0; + + cairo_pattern_t *pattern; + pattern = cairo_pattern_create_linear (0, 0, 0, windata->height); + cairo_pattern_add_color_stop_rgba (pattern, 0, + 51/255.0, 51/255.0, 51/255.0, alpha); + cairo_pattern_add_color_stop_rgba (pattern, GRADIENT_CENTER, + 51/255.0, 51/255.0, 51/255.0, alpha); + cairo_pattern_add_color_stop_rgba (pattern, 1, + 51/255.0, 51/255.0, 51/255.0, alpha); + cairo_set_source (cr, pattern); + cairo_pattern_destroy (pattern); + + nodoka_rounded_rectangle (cr, 0, 0, windata->width, + windata->height, 8); + + cairo_fill (cr); +} + +static void +draw_pie(GtkWidget *pie, WindowData *windata, cairo_t *cr) +{ + if (windata->timeout == 0) + return; + + gdouble arc_angle = 1.0 - (gdouble)windata->remaining / (gdouble)windata->timeout; + cairo_set_source_rgba (cr, 92/255.0, 92/255.0, 92/255.0, 1); + cairo_move_to(cr, PIE_RADIUS, PIE_RADIUS); + cairo_arc_negative(cr, PIE_RADIUS, PIE_RADIUS, PIE_RADIUS, + -G_PI/2, (-0.25 + arc_angle)*2*G_PI); + cairo_line_to(cr, PIE_RADIUS, PIE_RADIUS); + + cairo_fill (cr); +} + +static void +update_shape_region (cairo_surface_t *surface, + WindowData *windata) +{ + if (windata->width == windata->last_width && windata->height == windata->last_height) + { + return; + } + + if (windata->width == 0 || windata->height == 0) + { + GtkAllocation allocation; + gtk_widget_get_allocation (windata->win, &allocation); + + windata->width = MAX (allocation.width, 1); + windata->height = MAX (allocation.height, 1); + } + + if (!windata->composited) { + cairo_region_t *region; + + region = gdk_cairo_region_create_from_surface (surface); + gtk_widget_shape_combine_region (windata->win, region); + cairo_region_destroy (region); + } else { + gtk_widget_shape_combine_region (windata->win, NULL); + return; + } + + windata->last_width = windata->width; + windata->last_height = windata->height; +} + +static void +paint_window (GtkWidget *widget, + cairo_t *cr, + WindowData *windata) +{ + cairo_surface_t *surface; + cairo_t *cr2; + + if (windata->width == 0 || windata->height == 0) { + GtkAllocation allocation; + + gtk_widget_get_allocation(windata->win, &allocation); + windata->width = allocation.width; + windata->height = allocation.height; + } + + surface = cairo_surface_create_similar(cairo_get_target(cr), + CAIRO_CONTENT_COLOR_ALPHA, + windata->width, + windata->height); + + cr2 = cairo_create (surface); + fill_background(widget, windata, cr2); + cairo_fill (cr2); + + cairo_destroy (cr2); + + cairo_save (cr); + + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_surface (cr, surface, 0, 0); + cairo_paint (cr); + cairo_restore (cr); + + update_shape_region (surface, windata); + + cairo_surface_destroy (surface); +} + +/** + * @brief 当鼠标进入消息框窗体时,给窗体加上边框 + */ +static void +paint_window_when_pointer_enter(GtkWidget *widget, + cairo_t *cr, + WindowData *windata) +{ + cairo_surface_t *surface; + cairo_t *cr2; + + if (windata->width == 0 || windata->height == 0) { + GtkAllocation allocation; + + gtk_widget_get_allocation(windata->win, &allocation); + windata->width = allocation.width; + windata->height = allocation.height; + } + + surface = cairo_surface_create_similar(cairo_get_target(cr), + CAIRO_CONTENT_COLOR_ALPHA, + windata->width, + windata->height); + + cr2 = cairo_create (surface); + + fill_background_when_pointer_enter(widget, windata, cr2); + cairo_fill (cr2); + + nodoka_rounded_rectangle (cr2, 0, 0, windata->width , windata->height, 8); + cairo_set_source_rgba (cr2, 40/255.0, 144/255.0, 216/255.0, 1.0); + cairo_set_line_width (cr2, 4.0); + cairo_stroke (cr2); + + cairo_destroy (cr2); + + cairo_save (cr); + + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_surface (cr, surface, 0, 0); + cairo_paint (cr); + cairo_restore (cr); + + update_shape_region (surface, windata); + + cairo_surface_destroy (surface); + +} + +/* Event handlers */ +/** + * @brief "draw"回调函数:根据窗体当前状态,判断绘制成鼠标移入样式 + */ +static gboolean +on_draw (GtkWidget *widget, cairo_t *cr, WindowData *windata) +{ + GtkStateFlags flags = gtk_widget_get_state_flags(windata->win); + if (flags & GTK_STATE_FLAG_PRELIGHT) + { + paint_window_when_pointer_enter(widget , cr , windata); + } + else + { + paint_window (widget, cr, windata); + } + return FALSE; +} + +static gboolean +configure_event_cb(GtkWidget *nw, + GdkEventConfigure *event, + WindowData *windata) +{ + windata->width = event->width; + windata->height = event->height; + + gtk_widget_queue_draw(nw); + + return FALSE; +} + +static gboolean +countdown_expose_cb(GtkWidget *pie, + cairo_t *cr, + WindowData *windata) +{ + cairo_t *cr2; + cairo_surface_t *surface; + GtkAllocation alloc; + + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + + gtk_widget_get_allocation (pie, &alloc); + + surface = cairo_surface_create_similar (cairo_get_target (cr), + CAIRO_CONTENT_COLOR_ALPHA, + alloc.width, + alloc.height); + + cr2 = cairo_create (surface); + + cairo_translate (cr2, -alloc.x, -alloc.y); + + GtkStateFlags flags = gtk_widget_get_state_flags(windata->win); + if (flags & GTK_STATE_FLAG_PRELIGHT) + { + fill_background_when_pointer_enter(pie, windata ,cr2); + } + else + { + fill_background (pie, windata, cr2); + } + cairo_translate (cr2, alloc.x, alloc.y); + draw_pie (pie, windata, cr2); + cairo_fill (cr2); + + cairo_destroy (cr2); + + cairo_save (cr); + cairo_set_source_surface (cr, surface, 0, 0); + cairo_paint (cr); + cairo_restore (cr); + + cairo_surface_destroy (surface); + return TRUE; +} + +static gboolean on_configure_event (GtkWidget* widget, GdkEventConfigure* event, WindowData* windata) +{ + windata->width = event->width; + windata->height = event->height; + + gtk_widget_queue_draw (widget); + + return FALSE; +} + +static void on_composited_changed (GtkWidget* window, WindowData* windata) +{ + windata->composited = gdk_screen_is_composited (gtk_widget_get_screen(window)); + + gtk_widget_queue_draw (window); +} + + +/** + * @brief 事件过滤:当鼠标移入或者离开消息框,绘制相应的消息框状态 + */ +GdkFilterReturn event_filter(GdkXEvent *xevent, GdkEvent *event, gpointer userdata) +{ + XEvent *x_event = (XEvent*)xevent; + XGenericEvent *general_event = (XGenericEvent*)x_event; + GtkWidget *window = GTK_WIDGET(userdata); + + switch(x_event->type) { + case EnterNotify: + gtk_widget_set_state_flags(window, GTK_STATE_FLAG_PRELIGHT, FALSE); + gtk_widget_queue_draw(window); + break; + case LeaveNotify: + gtk_widget_set_state_flags(window, gtk_widget_get_state_flags(window) & ~GTK_STATE_FLAG_PRELIGHT, TRUE); + gtk_widget_queue_draw(window); + break; + case GenericEvent: + do + { + if (general_event->evtype == EnterNotify) { + gtk_widget_set_state_flags(window, GTK_STATE_FLAG_PRELIGHT, FALSE); + gtk_widget_queue_draw(window); + } + + if (general_event->evtype == LeaveNotify) { + gtk_widget_set_state_flags(window, gtk_widget_get_state_flags(window) & ~GTK_STATE_FLAG_PRELIGHT, TRUE); + gtk_widget_queue_draw(window); + } + }while(0); + break; + default: + break; + } + return GDK_FILTER_CONTINUE; +} + +static void +on_realize(GtkWidget *widget , gpointer userdata ) +{ + GdkWindow *window = gtk_widget_get_window(widget); + gdk_window_add_filter(window, event_filter, widget); +} + + +static void +action_clicked_cb(GtkWidget *w, GdkEventButton *event, + ActionInvokedCb action_cb) +{ + GtkWindow *nw = g_object_get_data(G_OBJECT(w), "_nw"); + const char *key = g_object_get_data(G_OBJECT(w), "_action_key"); + + action_cb(nw, key); +} + +/* Required functions */ + +/* Checking if we support this notification daemon version */ +gboolean +theme_check_init(unsigned int major_ver, unsigned int minor_ver, + unsigned int micro_ver) +{ + return major_ver == NOTIFICATION_DAEMON_MAJOR_VERSION && minor_ver == NOTIFICATION_DAEMON_MINOR_VERSION && micro_ver == NOTIFICATION_DAEMON_MICRO_VERSION; +} + +/* Sending theme info to the notification daemon */ +void +get_theme_info(char **theme_name, + char **theme_ver, + char **author, + char **homepage) +{ + *theme_name = g_strdup("Kiran"); + *theme_ver = g_strdup_printf("%d.%d.%d", NOTIFICATION_DAEMON_MAJOR_VERSION, + NOTIFICATION_DAEMON_MINOR_VERSION, + NOTIFICATION_DAEMON_MICRO_VERSION); + *author = g_strdup("Eduardo Grajeda"); + *homepage = g_strdup("http://github.com/tatofoo/"); +} + +/* set css*/ +static void +set_css(GtkWidget* widget) +{ + GtkCssProvider *provider = gtk_css_provider_new (); + + gtk_css_provider_load_from_resource (provider, "/kiran/themes/kiran.css"); + gtk_style_context_add_provider_for_screen (gtk_widget_get_screen(widget), + GTK_STYLE_PROVIDER(provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); + gtk_style_context_reset_widgets(gtk_widget_get_screen(widget)); + + g_object_unref (provider); +} + + +/* Create new notification */ +GtkWindow * +create_notification(UrlClickedCb url_clicked) +{ + GtkWidget *win; + GtkWidget *main_vbox; + GtkWidget* close_button; + GtkWidget* action_vbox; + GtkWidget *vbox; + AtkObject *atkobj; + WindowData *windata; + GdkVisual *visual; + GdkScreen *screen; + GResource *resource; + + windata = g_new0(WindowData, 1); + windata->urgency = URGENCY_NORMAL; + windata->url_clicked = url_clicked; + + win = gtk_window_new(GTK_WINDOW_POPUP); + gtk_window_set_resizable(GTK_WINDOW(win), FALSE); + gtk_window_set_decorated (GTK_WINDOW(win), TRUE); + windata->win = win; + + //register resource + resource = kiran_get_resource(); + g_resources_register (resource); + + set_css(windata->win); + gtk_widget_set_name(windata->win , "notification_window"); + windata->rtl = gtk_widget_get_default_direction(); + windata->composited = FALSE; + screen = gtk_window_get_screen(GTK_WINDOW(win)); + visual = gdk_screen_get_rgba_visual(screen); + + if (visual != NULL) + { + gtk_widget_set_visual(win, visual); + if (gdk_screen_is_composited(screen)) + windata->composited = TRUE; + } + gtk_window_set_title(GTK_WINDOW(win), "Notification"); + gtk_window_set_type_hint(GTK_WINDOW(win), GDK_WINDOW_TYPE_HINT_NOTIFICATION); + gtk_widget_add_events(win, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + + g_signal_connect(G_OBJECT(win), "realize" , G_CALLBACK(on_realize) , NULL); + + gtk_widget_realize(win); + + g_object_set_data_full(G_OBJECT(win), "windata", windata, + (GDestroyNotify)destroy_windata); + atk_object_set_role(gtk_widget_get_accessible(win), ATK_ROLE_ALERT); + + g_signal_connect(G_OBJECT(win), "configure_event", + G_CALLBACK(configure_event_cb), windata); + + main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name(main_vbox , "main_vbox"); + gtk_widget_show(main_vbox); + gtk_container_add (GTK_CONTAINER (win), main_vbox); + + g_signal_connect (G_OBJECT (main_vbox), "draw", + G_CALLBACK (on_draw), windata); + + g_signal_connect (G_OBJECT (win), "configure-event", G_CALLBACK (on_configure_event), windata); + + g_signal_connect (G_OBJECT (win), "composited-changed", G_CALLBACK (on_composited_changed), windata); + + windata->main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_name(windata->main_hbox , "main_hbox"); + gtk_widget_set_halign (windata->main_hbox, GTK_ALIGN_START); + gtk_widget_set_valign (windata->main_hbox, GTK_ALIGN_START); + gtk_widget_show (windata->main_hbox); + gtk_box_pack_start (GTK_BOX(main_vbox), windata->main_hbox, FALSE, FALSE, 0); + + /* The icon goes at the left */ + windata->iconbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name(windata->iconbox , "icon_box"); + gtk_widget_show(windata->iconbox); + gtk_box_pack_start(GTK_BOX(windata->main_hbox), windata->iconbox, + FALSE, FALSE, 0); + gtk_widget_set_valign (GTK_WIDGET(windata->iconbox),GTK_ALIGN_START); + + windata->icon = gtk_image_new(); + gtk_box_pack_start(GTK_BOX(windata->iconbox), windata->icon, + FALSE, FALSE, 0); + + /* The title and the text at the right */ + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name(vbox , "text_vbox"); + gtk_widget_set_halign (vbox, GTK_ALIGN_START); + gtk_widget_show (vbox); + gtk_box_pack_start (GTK_BOX (windata->main_hbox), vbox, FALSE, FALSE, 0); + + + /* Add action_vbox*/ + action_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL , 0); + gtk_widget_set_name(action_vbox , "action_vbox"); + gtk_widget_show(action_vbox); + gtk_box_pack_end(GTK_BOX(windata->main_hbox), action_vbox , FALSE , FALSE ,0); + gtk_widget_set_halign (action_vbox, GTK_ALIGN_END); + + /* Add the close button */ + close_button = gtk_button_new(); + gtk_widget_set_name(GTK_WIDGET(close_button) ,"close_button" ); + gtk_widget_set_size_request(GTK_WIDGET(close_button) , 16 , 16); + gtk_widget_set_valign (close_button, GTK_ALIGN_START); + gtk_widget_set_halign (close_button, GTK_ALIGN_END); + gtk_widget_set_vexpand (close_button,FALSE); + gtk_widget_set_hexpand(close_button , FALSE); + gtk_widget_show(close_button); + + windata->close_button = close_button; + gtk_box_pack_start (GTK_BOX (action_vbox), + windata->close_button, + FALSE, FALSE, 0); + + gtk_button_set_relief(GTK_BUTTON(close_button), GTK_RELIEF_NONE); + gtk_container_set_border_width(GTK_CONTAINER(close_button), 0); + g_signal_connect_swapped(G_OBJECT(close_button), "clicked", G_CALLBACK(gtk_widget_destroy), win); + + atkobj = gtk_widget_get_accessible(close_button); + atk_action_set_description(ATK_ACTION(atkobj), 0, + _("Closes the notification.")); + atk_object_set_name(atkobj, ""); + atk_object_set_description (atkobj, _("Closes the notification.")); + + windata->actions_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,10); + gtk_widget_set_name(windata->actions_box , "actions_box"); + gtk_widget_set_halign(windata->actions_box, GTK_ALIGN_END); + gtk_widget_show(windata->actions_box); + gtk_box_pack_end(GTK_BOX(action_vbox), windata->actions_box, FALSE, FALSE, 0); + gtk_widget_set_vexpand (windata->actions_box,FALSE); + gtk_widget_set_hexpand (windata->actions_box,FALSE); + + windata->summary_label = gtk_label_new(NULL); + gtk_widget_set_name(windata->summary_label, "summary_label"); + gtk_widget_show(windata->summary_label); + gtk_box_pack_start(GTK_BOX(vbox), windata->summary_label, FALSE, FALSE, 0); + gtk_label_set_xalign (GTK_LABEL (windata->summary_label), 0.0); + gtk_label_set_yalign (GTK_LABEL (windata->summary_label), 0.0); + gtk_label_set_line_wrap(GTK_LABEL(windata->summary_label), TRUE); + gtk_label_set_line_wrap_mode (GTK_LABEL (windata->summary_label), PANGO_WRAP_WORD_CHAR); + + atkobj = gtk_widget_get_accessible(windata->summary_label); + atk_object_set_description (atkobj, _("Notification summary text.")); + + windata->body_label = gtk_label_new(NULL); + gtk_widget_set_name(windata->body_label , "body_label"); + gtk_box_pack_start(GTK_BOX(vbox), windata->body_label, FALSE, FALSE, 0); + gtk_label_set_xalign (GTK_LABEL (windata->body_label), 0.0); + gtk_label_set_yalign (GTK_LABEL (windata->body_label), 0.0); + gtk_label_set_line_wrap(GTK_LABEL(windata->body_label), TRUE); + gtk_label_set_line_wrap_mode (GTK_LABEL (windata->body_label), PANGO_WRAP_WORD_CHAR); + gtk_label_set_max_width_chars (GTK_LABEL (windata->body_label), 50); + gtk_widget_set_vexpand (windata->body_label, FALSE); + + g_signal_connect(G_OBJECT(windata->body_label), "activate-link", + G_CALLBACK(activate_link), windata); + + atkobj = gtk_widget_get_accessible(windata->body_label); + atk_object_set_description (atkobj, _("Notification body text.")); + + g_resources_unregister (resource); + return GTK_WINDOW(win); +} + +/* Set the notification text */ +void +set_notification_text(GtkWindow *nw, const char *summary, const char *body) +{ + WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata"); + g_assert(windata != NULL); + + if(summary == NULL || *summary == '\0') + { + if(windata->urgency == URGENCY_CRITICAL) + { + summary = _("Normal Notification"); + } + else if(windata->urgency == URGENCY_LOW) + { + summary = _("Low Notification"); + } + else if(windata->urgency == URGENCY_CRITICAL) + { + summary = _("Critical Notification"); + } + } + + gtk_label_set_text(GTK_LABEL(windata->summary_label) , summary); + gtk_label_set_text (GTK_LABEL (windata->body_label), body); + + if (body == NULL || *body == '\0') + gtk_widget_hide(windata->body_label); + else + gtk_widget_show(windata->body_label); + + gtk_widget_set_size_request( + ((body != NULL && *body != '\0') + ? windata->body_label : windata->summary_label), + WIDTH - (IMAGE_SIZE + IMAGE_PADDING) - 10, + -1); +} + +/* Set notification icon */ +void +set_notification_icon(GtkWindow *nw, GdkPixbuf *pixbuf) +{ + WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata"); + g_assert(windata != NULL); + gtk_image_set_from_pixbuf(GTK_IMAGE(windata->icon), pixbuf); + + if (pixbuf != NULL) + { + int pixbuf_width = gdk_pixbuf_get_width(pixbuf); + + gtk_widget_show(windata->icon); + gtk_widget_set_size_request(windata->iconbox, + MAX(BODY_X_OFFSET, pixbuf_width), -1); + } + else + { + gtk_widget_hide(windata->icon); + gtk_widget_set_size_request(windata->iconbox, BODY_X_OFFSET, -1); + } +} + +/* Set notification arrow */ +void +set_notification_arrow(GtkWidget *nw, gboolean visible, int x, int y) +{ + /* nothing */ +} + +/* Add notification action */ +void +add_notification_action(GtkWindow *nw, const char *text, const char *key, + ActionInvokedCb cb) +{ + WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata"); + GtkWidget *label; + GtkWidget *button; + GtkWidget *hbox; + GdkPixbuf *pixbuf; + char *buf; + + g_assert(windata != NULL); + + if (gtk_widget_get_visible(windata->actions_box)) + { + gtk_widget_show(windata->actions_box); + /* Don't try to re-add a pie_countdown */ + if (!windata->pie_countdown) { + windata->pie_countdown = gtk_drawing_area_new(); + gtk_widget_set_halign (windata->pie_countdown, GTK_ALIGN_END); + gtk_widget_set_valign (windata->pie_countdown, GTK_ALIGN_END); + gtk_widget_show(windata->pie_countdown); + + gtk_box_pack_end (GTK_BOX (windata->actions_box), windata->pie_countdown, FALSE, FALSE, 0); + gtk_widget_set_size_request(windata->pie_countdown, + PIE_WIDTH, PIE_HEIGHT); + g_signal_connect(G_OBJECT(windata->pie_countdown), "draw", + G_CALLBACK(countdown_expose_cb), windata); + } + } + + if (windata->action_icons) { + button = gtk_button_new_from_icon_name(key, GTK_ICON_SIZE_BUTTON); + goto add_button; + } + + button = gtk_button_new(); + gtk_widget_show(button); + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6); + gtk_widget_set_name(GTK_WIDGET(hbox) , "actions_hbox"); + gtk_widget_set_valign(GTK_WIDGET(hbox), GTK_ALIGN_END); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 0); + gtk_widget_show(hbox); + gtk_container_add(GTK_CONTAINER(button), hbox); + + /* Try to be smart and find a suitable icon. */ + buf = g_strdup_printf("stock_%s", key); + pixbuf = gtk_icon_theme_load_icon( + gtk_icon_theme_get_for_screen( + gdk_window_get_screen(gtk_widget_get_window(GTK_WIDGET(nw)))), + buf, 16, GTK_ICON_LOOKUP_USE_BUILTIN, NULL); + g_free(buf); + + if (pixbuf != NULL) + { + GtkWidget *image = gtk_image_new_from_pixbuf(pixbuf); + gtk_widget_show(image); + gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); + gtk_widget_set_halign (image, GTK_ALIGN_END); + gtk_widget_set_valign (image, GTK_ALIGN_END); + } + + label = gtk_label_new(NULL); + gtk_widget_set_name(GTK_WIDGET(label) , "actions_label"); + gtk_widget_show(label); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_label_set_yalign (GTK_LABEL (label), 1.0); + gtk_widget_set_valign(GTK_WIDGET(label), GTK_ALIGN_END); + gtk_label_set_text(GTK_LABEL(label) , text); + +add_button: + gtk_widget_set_valign(GTK_WIDGET(button), GTK_ALIGN_END); + gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); + + gtk_widget_set_name(GTK_WIDGET(button) , "actions_button"); + gtk_box_pack_start(GTK_BOX(windata->actions_box), button, FALSE, FALSE, 0); + + g_object_set_data(G_OBJECT(button), "_nw", nw); + g_object_set_data_full(G_OBJECT(button), + "_action_key", g_strdup(key), g_free); + g_signal_connect(G_OBJECT(button), "button-release-event", + G_CALLBACK(action_clicked_cb), cb); + + gtk_widget_show_all(windata->actions_box); +} + +/* Clear notification actions */ +void +clear_notification_actions(GtkWindow *nw) +{ + WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata"); + + windata->pie_countdown = NULL; + + gtk_widget_hide(windata->actions_box); + gtk_container_foreach(GTK_CONTAINER(windata->actions_box), + (GtkCallback)gtk_widget_destroy, NULL); +} + +/* Move notification window */ +void +move_notification(GtkWidget *nw, int x, int y) +{ + WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata"); + g_assert(windata != NULL); + + gtk_window_move(GTK_WINDOW(nw), x, y); +} + + +/* Optional Functions */ + +/* Destroy notification */ + +/* Show notification */ + +/* Hide notification */ + +/* Set notification timeout */ +void +set_notification_timeout(GtkWindow *nw, glong timeout) +{ + WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata"); + g_assert(windata != NULL); + + windata->timeout = timeout; +} + +/* Set notification hints */ +void set_notification_hints(GtkWindow *nw, GVariant *hints) +{ + WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata"); + GVariant *value = NULL, *icon_value = NULL; + + g_assert(windata != NULL); + + g_variant_lookup(hints, "urgency", "v", &value); + g_variant_lookup(hints, "action-icons", "v", &icon_value); + + if (value != NULL && g_variant_get_type(value) == G_VARIANT_TYPE_BYTE) + { + windata->urgency = g_variant_get_byte(value); + + if (windata->urgency == URGENCY_CRITICAL) { + gtk_window_set_title(GTK_WINDOW(nw), "Critical Notification"); + } else { + gtk_window_set_title(GTK_WINDOW(nw), "Notification"); + } + } + + /* Determine if action-icons have been requested */ + if (icon_value != NULL && g_variant_get_type(icon_value) == G_VARIANT_TYPE_BOOLEAN) + { + windata->action_icons = g_variant_get_boolean(icon_value); + } +} + +/* Notification tick */ +void +notification_tick(GtkWindow *nw, glong remaining) +{ + WindowData *windata = g_object_get_data(G_OBJECT(nw), "windata"); + windata->remaining = remaining; + + if (windata->pie_countdown != NULL) + { + gtk_widget_queue_draw_area(windata->pie_countdown, 0, 0, + PIE_WIDTH, PIE_HEIGHT); + } +} diff --git a/src/themes/kiran/kiran.gresource.xml b/src/themes/kiran/kiran.gresource.xml new file mode 100644 index 0000000..d177863 --- /dev/null +++ b/src/themes/kiran/kiran.gresource.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<gresources> + <gresource prefix="/kiran/themes"> + <file alias="kiran.css">data/kiran.css</file> + <file alias="close_hover">data/icons/close_hover.svg</file> + <file alias="close_normal">data/icons/close_normal.svg</file> + <file alias="close_press">data/icons/close_press.svg</file> + </gresource> +</gresources> -- 2.27.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2