1268 lines
37 KiB
Diff
1268 lines
37 KiB
Diff
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
|
||
@@ -187,3 +187,16 @@ msgstr "通知主体文本"
|
||
#: ../src/themes/standard/theme.c:752
|
||
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
|
||
|