commit
62e8b043c7
102
src/dbus.c
102
src/dbus.c
@ -61,20 +61,21 @@ static const char *introspection_xml =
|
||||
"</node>";
|
||||
|
||||
static void on_get_capabilities(GDBusConnection *connection,
|
||||
const gchar *sender,
|
||||
const GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation);
|
||||
static void on_notify(GDBusConnection *connection,
|
||||
const gchar *sender,
|
||||
GVariant *parameters, GDBusMethodInvocation *invocation);
|
||||
static void on_close_notification(GDBusConnection *connection,
|
||||
const gchar *sender,
|
||||
GVariant *parameters,
|
||||
const GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation);
|
||||
static void on_notify(GDBusConnection *connection,
|
||||
const gchar *sender,
|
||||
GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation);
|
||||
static void on_close_notification(GDBusConnection *connection,
|
||||
const gchar *sender,
|
||||
GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation);
|
||||
static void on_get_server_information(GDBusConnection *connection,
|
||||
const gchar *sender,
|
||||
const GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation);
|
||||
const gchar *sender,
|
||||
const GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation);
|
||||
static RawImage *get_raw_image_from_data_hint(GVariant *icon_data);
|
||||
|
||||
void handle_method_call(GDBusConnection *connection,
|
||||
@ -83,7 +84,8 @@ void handle_method_call(GDBusConnection *connection,
|
||||
const gchar *interface_name,
|
||||
const gchar *method_name,
|
||||
GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation, gpointer user_data)
|
||||
GDBusMethodInvocation *invocation,
|
||||
gpointer user_data)
|
||||
{
|
||||
if (g_strcmp0(method_name, "GetCapabilities") == 0) {
|
||||
on_get_capabilities(connection, sender, parameters, invocation);
|
||||
@ -92,8 +94,7 @@ void handle_method_call(GDBusConnection *connection,
|
||||
} else if (g_strcmp0(method_name, "CloseNotification") == 0) {
|
||||
on_close_notification(connection, sender, parameters, invocation);
|
||||
} else if (g_strcmp0(method_name, "GetServerInformation") == 0) {
|
||||
on_get_server_information(connection, sender, parameters,
|
||||
invocation);
|
||||
on_get_server_information(connection, sender, parameters, invocation);
|
||||
} else {
|
||||
fprintf(stderr, "WARNING: sender: %s; unknown method_name: %s\n", sender,
|
||||
method_name);
|
||||
@ -101,9 +102,9 @@ void handle_method_call(GDBusConnection *connection,
|
||||
}
|
||||
|
||||
static void on_get_capabilities(GDBusConnection *connection,
|
||||
const gchar *sender,
|
||||
const GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation)
|
||||
const gchar *sender,
|
||||
const GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
GVariantBuilder *builder;
|
||||
GVariant *value;
|
||||
@ -113,7 +114,7 @@ static void on_get_capabilities(GDBusConnection *connection,
|
||||
g_variant_builder_add(builder, "s", "body");
|
||||
g_variant_builder_add(builder, "s", "body-hyperlinks");
|
||||
|
||||
if(settings.markup != MARKUP_NO)
|
||||
if (settings.markup != MARKUP_NO)
|
||||
g_variant_builder_add(builder, "s", "body-markup");
|
||||
|
||||
value = g_variant_new("(as)", builder);
|
||||
@ -124,8 +125,9 @@ static void on_get_capabilities(GDBusConnection *connection,
|
||||
}
|
||||
|
||||
static void on_notify(GDBusConnection *connection,
|
||||
const gchar *sender,
|
||||
GVariant *parameters, GDBusMethodInvocation *invocation)
|
||||
const gchar *sender,
|
||||
GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
|
||||
gchar *appname = NULL;
|
||||
@ -297,9 +299,9 @@ static void on_notify(GDBusConnection *connection,
|
||||
}
|
||||
|
||||
static void on_close_notification(GDBusConnection *connection,
|
||||
const gchar *sender,
|
||||
GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation)
|
||||
const gchar *sender,
|
||||
GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
guint32 id;
|
||||
g_variant_get(parameters, "(u)", &id);
|
||||
@ -310,9 +312,9 @@ static void on_close_notification(GDBusConnection *connection,
|
||||
}
|
||||
|
||||
static void on_get_server_information(GDBusConnection *connection,
|
||||
const gchar *sender,
|
||||
const GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation)
|
||||
const gchar *sender,
|
||||
const GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
GVariant *value;
|
||||
|
||||
@ -342,7 +344,9 @@ void notification_closed(notification *n, enum reason reason)
|
||||
n->dbus_client,
|
||||
"/org/freedesktop/Notifications",
|
||||
"org.freedesktop.Notifications",
|
||||
"NotificationClosed", body, &err);
|
||||
"NotificationClosed",
|
||||
body,
|
||||
&err);
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "Unable to close notification: %s\n", err->message);
|
||||
@ -360,7 +364,9 @@ void action_invoked(notification *n, const char *identifier)
|
||||
n->dbus_client,
|
||||
"/org/freedesktop/Notifications",
|
||||
"org.freedesktop.Notifications",
|
||||
"ActionInvoked", body, &err);
|
||||
"ActionInvoked",
|
||||
body,
|
||||
&err);
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "Unable to invoke action: %s\n", err->message);
|
||||
@ -373,7 +379,8 @@ static const GDBusInterfaceVTable interface_vtable = {
|
||||
};
|
||||
|
||||
static void on_bus_acquired(GDBusConnection *connection,
|
||||
const gchar *name, gpointer user_data)
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
guint registration_id;
|
||||
|
||||
@ -383,7 +390,9 @@ static void on_bus_acquired(GDBusConnection *connection,
|
||||
"/org/freedesktop/Notifications",
|
||||
introspection_data->interfaces[0],
|
||||
&interface_vtable,
|
||||
NULL, NULL, &err);
|
||||
NULL,
|
||||
NULL,
|
||||
&err);
|
||||
|
||||
if (registration_id == 0) {
|
||||
fprintf(stderr, "Unable to register dbus connection: %s\n", err->message);
|
||||
@ -392,13 +401,15 @@ static void on_bus_acquired(GDBusConnection *connection,
|
||||
}
|
||||
|
||||
static void on_name_acquired(GDBusConnection *connection,
|
||||
const gchar *name, gpointer user_data)
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
dbus_conn = connection;
|
||||
}
|
||||
|
||||
static void on_name_lost(GDBusConnection *connection,
|
||||
const gchar *name, gpointer user_data)
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
fprintf(stderr, "Name Lost. Is Another notification daemon running?\n");
|
||||
exit(1);
|
||||
@ -410,15 +421,15 @@ static RawImage *get_raw_image_from_data_hint(GVariant *icon_data)
|
||||
GVariant *data_variant;
|
||||
gsize expected_len;
|
||||
|
||||
g_variant_get (icon_data,
|
||||
"(iiibii@ay)",
|
||||
&image->width,
|
||||
&image->height,
|
||||
&image->rowstride,
|
||||
&image->has_alpha,
|
||||
&image->bits_per_sample,
|
||||
&image->n_channels,
|
||||
&data_variant);
|
||||
g_variant_get(icon_data,
|
||||
"(iiibii@ay)",
|
||||
&image->width,
|
||||
&image->height,
|
||||
&image->rowstride,
|
||||
&image->has_alpha,
|
||||
&image->bits_per_sample,
|
||||
&image->n_channels,
|
||||
&data_variant);
|
||||
|
||||
expected_len = (image->height - 1) * image->rowstride + image->width
|
||||
* ((image->n_channels * image->bits_per_sample + 7) / 8);
|
||||
@ -433,8 +444,8 @@ static RawImage *get_raw_image_from_data_hint(GVariant *icon_data)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image->data = (guchar *) g_memdup (g_variant_get_data (data_variant),
|
||||
g_variant_get_size (data_variant));
|
||||
image->data = (guchar *) g_memdup(g_variant_get_data(data_variant),
|
||||
g_variant_get_size(data_variant));
|
||||
g_variant_unref(data_variant);
|
||||
|
||||
return image;
|
||||
@ -455,7 +466,10 @@ int initdbus(void)
|
||||
"org.freedesktop.Notifications",
|
||||
G_BUS_NAME_OWNER_FLAGS_NONE,
|
||||
on_bus_acquired,
|
||||
on_name_acquired, on_name_lost, NULL, NULL);
|
||||
on_name_acquired,
|
||||
on_name_lost,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
return owner_id;
|
||||
}
|
||||
|
@ -18,8 +18,8 @@
|
||||
#include "option_parser.h"
|
||||
#include "queues.h"
|
||||
#include "settings.h"
|
||||
#include "x11/x.h"
|
||||
#include "x11/screen.h"
|
||||
#include "x11/x.h"
|
||||
|
||||
#ifndef VERSION
|
||||
#define VERSION "version info needed"
|
||||
|
@ -4,8 +4,8 @@
|
||||
#define DUNST_DUNST_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "notification.h"
|
||||
|
||||
|
@ -14,9 +14,9 @@
|
||||
|
||||
#include "dbus.h"
|
||||
#include "dunst.h"
|
||||
#include "settings.h"
|
||||
#include "notification.h"
|
||||
#include "queues.h"
|
||||
#include "settings.h"
|
||||
#include "utils.h"
|
||||
|
||||
static bool is_initialized = false;
|
||||
@ -43,8 +43,7 @@ static int regex_init(void)
|
||||
|
||||
void regex_teardown(void)
|
||||
{
|
||||
if (is_initialized)
|
||||
{
|
||||
if (is_initialized) {
|
||||
regfree(&cregex);
|
||||
is_initialized = false;
|
||||
}
|
||||
@ -94,7 +93,8 @@ char *extract_urls(const char *to_match)
|
||||
* Open url in browser.
|
||||
*
|
||||
*/
|
||||
void open_browser(const char *in) {
|
||||
void open_browser(const char *in)
|
||||
{
|
||||
// remove prefix and test url
|
||||
char *url = extract_urls(in);
|
||||
if (!url)
|
||||
|
@ -5,25 +5,24 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <glib.h>
|
||||
#include <libgen.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include "dbus.h"
|
||||
#include "dunst.h"
|
||||
#include "markup.h"
|
||||
#include "menu.h"
|
||||
#include "queues.h"
|
||||
#include "rules.h"
|
||||
#include "settings.h"
|
||||
#include "queues.h"
|
||||
#include "utils.h"
|
||||
#include "x11/x.h"
|
||||
|
||||
|
||||
/*
|
||||
* print a human readable representation
|
||||
* of the given notification to stdout.
|
||||
@ -92,7 +91,8 @@ void notification_run_script(notification *n)
|
||||
if (pid2) {
|
||||
exit(0);
|
||||
} else {
|
||||
int ret = execlp(n->script, n->script,
|
||||
int ret = execlp(n->script,
|
||||
n->script,
|
||||
appname,
|
||||
summary,
|
||||
body,
|
||||
@ -225,8 +225,11 @@ void notification_free(notification *n)
|
||||
* to point to the first char, which occurs after replacement.
|
||||
*
|
||||
*/
|
||||
void notification_replace_single_field(char **haystack, char **needle,
|
||||
const char *replacement, enum markup_mode markup_mode) {
|
||||
void notification_replace_single_field(char **haystack,
|
||||
char **needle,
|
||||
const char *replacement,
|
||||
enum markup_mode markup_mode)
|
||||
{
|
||||
|
||||
assert(*needle[0] == '%');
|
||||
// needle has to point into haystack (but not on the last char)
|
||||
@ -245,7 +248,8 @@ void notification_replace_single_field(char **haystack, char **needle,
|
||||
g_free(input);
|
||||
}
|
||||
|
||||
char *notification_extract_markup_urls(char **str_ptr) {
|
||||
char *notification_extract_markup_urls(char **str_ptr)
|
||||
{
|
||||
char *start, *end, *replace_buf, *str, *urls = NULL, *url, *index_buf;
|
||||
int linkno = 1;
|
||||
|
||||
@ -339,87 +343,87 @@ void notification_init(notification *n)
|
||||
/* replace all formatter */
|
||||
for(char *substr = strchr(n->msg, '%');
|
||||
substr;
|
||||
substr = strchr(substr, '%')){
|
||||
substr = strchr(substr, '%')) {
|
||||
|
||||
char pg[16];
|
||||
char *icon_tmp;
|
||||
|
||||
switch(substr[1]){
|
||||
case 'a':
|
||||
notification_replace_single_field(
|
||||
&n->msg,
|
||||
&substr,
|
||||
n->appname,
|
||||
MARKUP_NO);
|
||||
break;
|
||||
case 's':
|
||||
notification_replace_single_field(
|
||||
&n->msg,
|
||||
&substr,
|
||||
n->summary,
|
||||
n->markup);
|
||||
break;
|
||||
case 'b':
|
||||
notification_replace_single_field(
|
||||
&n->msg,
|
||||
&substr,
|
||||
n->body,
|
||||
n->markup);
|
||||
break;
|
||||
case 'I':
|
||||
icon_tmp = g_strdup(n->icon);
|
||||
notification_replace_single_field(
|
||||
&n->msg,
|
||||
&substr,
|
||||
icon_tmp ? basename(icon_tmp) : "",
|
||||
MARKUP_NO);
|
||||
g_free(icon_tmp);
|
||||
break;
|
||||
case 'i':
|
||||
notification_replace_single_field(
|
||||
&n->msg,
|
||||
&substr,
|
||||
n->icon ? n->icon : "",
|
||||
MARKUP_NO);
|
||||
break;
|
||||
case 'p':
|
||||
if (n->progress != -1)
|
||||
sprintf(pg, "[%3d%%]", n->progress);
|
||||
switch(substr[1]) {
|
||||
case 'a':
|
||||
notification_replace_single_field(
|
||||
&n->msg,
|
||||
&substr,
|
||||
n->appname,
|
||||
MARKUP_NO);
|
||||
break;
|
||||
case 's':
|
||||
notification_replace_single_field(
|
||||
&n->msg,
|
||||
&substr,
|
||||
n->summary,
|
||||
n->markup);
|
||||
break;
|
||||
case 'b':
|
||||
notification_replace_single_field(
|
||||
&n->msg,
|
||||
&substr,
|
||||
n->body,
|
||||
n->markup);
|
||||
break;
|
||||
case 'I':
|
||||
icon_tmp = g_strdup(n->icon);
|
||||
notification_replace_single_field(
|
||||
&n->msg,
|
||||
&substr,
|
||||
icon_tmp ? basename(icon_tmp) : "",
|
||||
MARKUP_NO);
|
||||
g_free(icon_tmp);
|
||||
break;
|
||||
case 'i':
|
||||
notification_replace_single_field(
|
||||
&n->msg,
|
||||
&substr,
|
||||
n->icon ? n->icon : "",
|
||||
MARKUP_NO);
|
||||
break;
|
||||
case 'p':
|
||||
if (n->progress != -1)
|
||||
sprintf(pg, "[%3d%%]", n->progress);
|
||||
|
||||
notification_replace_single_field(
|
||||
&n->msg,
|
||||
&substr,
|
||||
n->progress != -1 ? pg : "",
|
||||
MARKUP_NO);
|
||||
break;
|
||||
case 'n':
|
||||
if (n->progress != -1)
|
||||
sprintf(pg, "%d", n->progress);
|
||||
notification_replace_single_field(
|
||||
&n->msg,
|
||||
&substr,
|
||||
n->progress != -1 ? pg : "",
|
||||
MARKUP_NO);
|
||||
break;
|
||||
case 'n':
|
||||
if (n->progress != -1)
|
||||
sprintf(pg, "%d", n->progress);
|
||||
|
||||
notification_replace_single_field(
|
||||
&n->msg,
|
||||
&substr,
|
||||
n->progress != -1 ? pg : "",
|
||||
MARKUP_NO);
|
||||
break;
|
||||
case '%':
|
||||
notification_replace_single_field(
|
||||
&n->msg,
|
||||
&substr,
|
||||
"%",
|
||||
MARKUP_NO);
|
||||
break;
|
||||
case '\0':
|
||||
fprintf(stderr, "WARNING: format_string has trailing %% character."
|
||||
"To escape it use %%%%.");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "WARNING: format_string %%%c"
|
||||
" is unknown\n", substr[1]);
|
||||
// shift substr pointer forward,
|
||||
// as we can't interpret the format string
|
||||
substr++;
|
||||
break;
|
||||
notification_replace_single_field(
|
||||
&n->msg,
|
||||
&substr,
|
||||
n->progress != -1 ? pg : "",
|
||||
MARKUP_NO);
|
||||
break;
|
||||
case '%':
|
||||
notification_replace_single_field(
|
||||
&n->msg,
|
||||
&substr,
|
||||
"%",
|
||||
MARKUP_NO);
|
||||
break;
|
||||
case '\0':
|
||||
fprintf(stderr, "WARNING: format_string has trailing %% character."
|
||||
"To escape it use %%%%.");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "WARNING: format_string %%%c"
|
||||
" is unknown\n", substr[1]);
|
||||
// shift substr pointer forward,
|
||||
// as we can't interpret the format string
|
||||
substr++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -550,7 +554,8 @@ void notification_update_text_to_render(notification *n)
|
||||
* invoke it. If there are multiple and no default, open the context menu. If
|
||||
* there are no actions, proceed similarly with urls.
|
||||
*/
|
||||
void notification_do_action(notification *n) {
|
||||
void notification_do_action(notification *n)
|
||||
{
|
||||
if (n->actions) {
|
||||
if (n->actions->count == 2) {
|
||||
action_invoked(n, n->actions->actions[0]);
|
||||
|
@ -75,7 +75,10 @@ int notification_cmp_data(const void *a, const void *b, void *data);
|
||||
int notification_is_duplicate(const notification *a, const notification *b);
|
||||
void notification_run_script(notification *n);
|
||||
void notification_print(notification *n);
|
||||
void notification_replace_single_field(char **haystack, char **needle, const char *replacement, enum markup_mode markup_mode);
|
||||
void notification_replace_single_field(char **haystack,
|
||||
char **needle,
|
||||
const char *replacement,
|
||||
enum markup_mode markup_mode);
|
||||
void notification_update_text_to_render(notification *n);
|
||||
void notification_do_action(notification *n);
|
||||
|
||||
|
@ -41,7 +41,7 @@ static int cmdline_find_option(const char *key);
|
||||
section_t *new_section(const char *name)
|
||||
{
|
||||
for (int i = 0; i < section_count; i++) {
|
||||
if(!strcmp(name, sections[i].name)) {
|
||||
if (!strcmp(name, sections[i].name)) {
|
||||
die("Duplicated section in dunstrc detected.\n", -1);
|
||||
}
|
||||
}
|
||||
@ -215,7 +215,6 @@ char *clean_value(const char *value)
|
||||
s[strlen(s) - 1] = '\0';
|
||||
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
int load_ini_file(FILE *fp)
|
||||
@ -443,13 +442,11 @@ char *option_get_path(const char *ini_section,
|
||||
val = cmdline_get_path(cmdline_key, NULL, description);
|
||||
}
|
||||
|
||||
|
||||
if (val) {
|
||||
return val;
|
||||
} else {
|
||||
return ini_get_path(ini_section, ini_key, def);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
char *option_get_string(const char *ini_section,
|
||||
@ -464,13 +461,11 @@ char *option_get_string(const char *ini_section,
|
||||
val = cmdline_get_string(cmdline_key, NULL, description);
|
||||
}
|
||||
|
||||
|
||||
if (val) {
|
||||
return val;
|
||||
} else {
|
||||
return ini_get_string(ini_section, ini_key, def);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
gint64 option_get_time(const char *ini_section,
|
||||
|
@ -3,8 +3,8 @@
|
||||
#ifndef DUNST_QUEUE_H
|
||||
#define DUNST_QUEUE_H
|
||||
|
||||
#include "notification.h"
|
||||
#include "dbus.h"
|
||||
#include "notification.h"
|
||||
|
||||
/*
|
||||
* Initialise neccessary queues
|
||||
|
@ -139,7 +139,7 @@ void load_settings(char *cmdline_config_path)
|
||||
//Use markup if set
|
||||
//Use default if settings.markup not set yet
|
||||
// (=>c empty&&!allow_markup)
|
||||
if(c){
|
||||
if (c) {
|
||||
settings.markup = parse_markup_mode(c);
|
||||
} else if (!settings.markup) {
|
||||
settings.markup = defaults.markup;
|
||||
|
27
src/utils.c
27
src/utils.c
@ -2,15 +2,16 @@
|
||||
#include "utils.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <glib.h>
|
||||
#include <errno.h>
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
char *string_replace_char(char needle, char replacement, char *haystack) {
|
||||
char *string_replace_char(char needle, char replacement, char *haystack)
|
||||
{
|
||||
char *current = haystack;
|
||||
while ((current = strchr (current, needle)) != NULL)
|
||||
while ((current = strchr(current, needle)) != NULL)
|
||||
*current++ = replacement;
|
||||
return haystack;
|
||||
}
|
||||
@ -34,7 +35,7 @@ char *string_replace_at(char *buf, int pos, int len, const char *repl)
|
||||
memcpy(tmp + pos, repl, repl_len);
|
||||
memmove(tmp + pos + repl_len, buf + pos + len, buf_len - (pos + len) + 1);
|
||||
|
||||
if(tmp != buf) {
|
||||
if (tmp != buf) {
|
||||
g_free(buf);
|
||||
}
|
||||
|
||||
@ -52,8 +53,7 @@ char *string_replace(const char *needle, const char *replacement, char *haystack
|
||||
return string_replace_at(haystack, (start - haystack), strlen(needle), replacement);
|
||||
}
|
||||
|
||||
char *string_replace_all(const char *needle, const char *replacement,
|
||||
char *haystack)
|
||||
char *string_replace_all(const char *needle, const char *replacement, char *haystack)
|
||||
{
|
||||
char *start;
|
||||
int needle_pos;
|
||||
@ -110,7 +110,8 @@ void string_strip_delimited(char *str, char a, char b)
|
||||
str[iwrite] = 0;
|
||||
}
|
||||
|
||||
char *string_to_path(char *string) {
|
||||
char *string_to_path(char *string)
|
||||
{
|
||||
|
||||
if (string && 0 == strncmp(string, "~/", 2)) {
|
||||
char *home = g_strconcat(getenv("HOME"), "/", NULL);
|
||||
@ -123,7 +124,8 @@ char *string_to_path(char *string) {
|
||||
return string;
|
||||
}
|
||||
|
||||
gint64 string_to_time(const char *string) {
|
||||
gint64 string_to_time(const char *string)
|
||||
{
|
||||
|
||||
assert(string);
|
||||
|
||||
@ -134,16 +136,13 @@ gint64 string_to_time(const char *string) {
|
||||
if (errno != 0) {
|
||||
fprintf(stderr, "ERROR: Time: '%s': %s.\n", string, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
else if (string == endptr) {
|
||||
} else if (string == endptr) {
|
||||
fprintf(stderr, "ERROR: Time: No digits found.\n");
|
||||
return 0;
|
||||
}
|
||||
else if (errno != 0 && val == 0) {
|
||||
} else if (errno != 0 && val == 0) {
|
||||
fprintf(stderr, "ERROR: Time: '%s' unknown error.\n", string);
|
||||
return 0;
|
||||
}
|
||||
else if (errno == 0 && !*endptr) {
|
||||
} else if (errno == 0 && !*endptr) {
|
||||
return val * G_USEC_PER_SEC;
|
||||
}
|
||||
|
||||
|
@ -8,15 +8,13 @@
|
||||
char *string_replace_char(char needle, char replacement, char *haystack);
|
||||
|
||||
/* replace all occurrences of needle with replacement in haystack */
|
||||
char *string_replace_all(const char *needle, const char *replacement,
|
||||
char *haystack);
|
||||
char *string_replace_all(const char *needle, const char *replacement, char *haystack);
|
||||
|
||||
/* replace <len> characters with <repl> at position <pos> of the string <buf> */
|
||||
char *string_replace_at(char *buf, int pos, int len, const char *repl);
|
||||
|
||||
/* replace needle with replacement in haystack */
|
||||
char *string_replace(const char *needle, const char *replacement,
|
||||
char *haystack);
|
||||
char *string_replace(const char *needle, const char *replacement, char *haystack);
|
||||
|
||||
char *string_append(char *a, const char *b, const char *sep);
|
||||
|
||||
|
@ -4,9 +4,9 @@
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xresource.h>
|
||||
#include <X11/extensions/randr.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <X11/extensions/randr.h>
|
||||
#include <assert.h>
|
||||
#include <glib.h>
|
||||
#include <locale.h>
|
||||
@ -64,7 +64,8 @@ static double get_xft_dpi_value()
|
||||
return dpi;
|
||||
}
|
||||
|
||||
void init_screens() {
|
||||
void init_screens()
|
||||
{
|
||||
if (!settings.force_xinerama) {
|
||||
randr_init();
|
||||
randr_update();
|
||||
@ -164,7 +165,6 @@ void xinerama_update()
|
||||
XFree(info);
|
||||
}
|
||||
|
||||
|
||||
void screen_update_fallback()
|
||||
{
|
||||
alloc_screen_ar(1);
|
||||
@ -177,7 +177,6 @@ void screen_update_fallback()
|
||||
|
||||
screens[0].dim.w = DisplayWidth(xctx.dpy, screen);
|
||||
screens[0].dim.h = DisplayHeight(xctx.dpy, screen);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -210,9 +209,15 @@ screen_info *get_active_screen()
|
||||
unsigned int dummy_ui;
|
||||
Window dummy_win;
|
||||
|
||||
XQueryPointer(xctx.dpy, root, &dummy_win,
|
||||
&dummy_win, &x, &y, &dummy,
|
||||
&dummy, &dummy_ui);
|
||||
XQueryPointer(xctx.dpy,
|
||||
root,
|
||||
&dummy_win,
|
||||
&dummy_win,
|
||||
&x,
|
||||
&y,
|
||||
&dummy,
|
||||
&dummy,
|
||||
&dummy_ui);
|
||||
}
|
||||
|
||||
if (settings.f_mode == FOLLOW_KEYBOARD) {
|
||||
@ -278,11 +283,20 @@ static Window get_focused_window(void)
|
||||
Atom netactivewindow =
|
||||
XInternAtom(xctx.dpy, "_NET_ACTIVE_WINDOW", false);
|
||||
|
||||
XGetWindowProperty(xctx.dpy, root, netactivewindow, 0L,
|
||||
sizeof(Window), false, XA_WINDOW,
|
||||
&type, &format, &nitems, &bytes_after, &prop_return);
|
||||
XGetWindowProperty(xctx.dpy,
|
||||
root,
|
||||
netactivewindow,
|
||||
0L,
|
||||
sizeof(Window),
|
||||
false,
|
||||
XA_WINDOW,
|
||||
&type,
|
||||
&format,
|
||||
&nitems,
|
||||
&bytes_after,
|
||||
&prop_return);
|
||||
if (prop_return) {
|
||||
focused = *(Window *) prop_return;
|
||||
focused = *(Window *)prop_return;
|
||||
XFree(prop_return);
|
||||
}
|
||||
|
||||
|
238
src/x11/x.c
238
src/x11/x.c
@ -7,18 +7,18 @@
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <assert.h>
|
||||
#include <cairo.h>
|
||||
#include <cairo-xlib.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <cairo.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <glib-object.h>
|
||||
#include <locale.h>
|
||||
#include <math.h>
|
||||
#include <pango/pangocairo.h>
|
||||
#include <pango/pango-attributes.h>
|
||||
#include <pango/pango-font.h>
|
||||
#include <pango/pango-layout.h>
|
||||
#include <pango/pango-types.h>
|
||||
#include <pango/pangocairo.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -29,8 +29,8 @@
|
||||
#include "src/dunst.h"
|
||||
#include "src/markup.h"
|
||||
#include "src/notification.h"
|
||||
#include "src/settings.h"
|
||||
#include "src/queues.h"
|
||||
#include "src/settings.h"
|
||||
#include "src/utils.h"
|
||||
|
||||
#include "screen.h"
|
||||
@ -111,31 +111,30 @@ static color_t calculate_foreground_color(color_t bg)
|
||||
|
||||
int signedness = darken ? -1 : 1;
|
||||
|
||||
color.r = _apply_delta(color.r, c_delta *signedness);
|
||||
color.g = _apply_delta(color.g, c_delta *signedness);
|
||||
color.b = _apply_delta(color.b, c_delta *signedness);
|
||||
color.r = _apply_delta(color.r, c_delta * signedness);
|
||||
color.g = _apply_delta(color.g, c_delta * signedness);
|
||||
color.b = _apply_delta(color.b, c_delta * signedness);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
static color_t x_get_separator_color(colored_layout *cl, colored_layout *cl_next)
|
||||
{
|
||||
switch (settings.sep_color) {
|
||||
case FRAME:
|
||||
if (cl_next->n->urgency > cl->n->urgency)
|
||||
return cl_next->frame;
|
||||
else
|
||||
return cl->frame;
|
||||
case CUSTOM:
|
||||
return x_string_to_color_t(settings.sep_custom_color_str);
|
||||
case FOREGROUND:
|
||||
return cl->fg;
|
||||
case AUTO:
|
||||
return calculate_foreground_color(cl->bg);
|
||||
default:
|
||||
printf("Unknown separator color type. Please file a Bugreport.\n");
|
||||
return cl->fg;
|
||||
case FRAME:
|
||||
if (cl_next->n->urgency > cl->n->urgency)
|
||||
return cl_next->frame;
|
||||
else
|
||||
return cl->frame;
|
||||
case CUSTOM:
|
||||
return x_string_to_color_t(settings.sep_custom_color_str);
|
||||
case FOREGROUND:
|
||||
return cl->fg;
|
||||
case AUTO:
|
||||
return calculate_foreground_color(cl->bg);
|
||||
default:
|
||||
printf("Unknown separator color type. Please file a Bugreport.\n");
|
||||
return cl->fg;
|
||||
|
||||
}
|
||||
}
|
||||
@ -159,16 +158,16 @@ static void r_setup_pango_layout(PangoLayout *layout, int width)
|
||||
|
||||
PangoAlignment align;
|
||||
switch (settings.align) {
|
||||
case left:
|
||||
default:
|
||||
align = PANGO_ALIGN_LEFT;
|
||||
break;
|
||||
case center:
|
||||
align = PANGO_ALIGN_CENTER;
|
||||
break;
|
||||
case right:
|
||||
align = PANGO_ALIGN_RIGHT;
|
||||
break;
|
||||
case left:
|
||||
default:
|
||||
align = PANGO_ALIGN_LEFT;
|
||||
break;
|
||||
case center:
|
||||
align = PANGO_ALIGN_CENTER;
|
||||
break;
|
||||
case right:
|
||||
align = PANGO_ALIGN_RIGHT;
|
||||
break;
|
||||
}
|
||||
pango_layout_set_alignment(layout, align);
|
||||
|
||||
@ -189,7 +188,8 @@ static bool have_dynamic_width(void)
|
||||
return (xctx.geometry.mask & WidthValue && xctx.geometry.w == 0);
|
||||
}
|
||||
|
||||
static bool does_file_exist(const char *filename){
|
||||
static bool does_file_exist(const char *filename)
|
||||
{
|
||||
return (access(filename, F_OK) != -1);
|
||||
}
|
||||
|
||||
@ -198,9 +198,10 @@ static bool is_readable_file(const char *filename)
|
||||
return (access(filename, R_OK) != -1);
|
||||
}
|
||||
|
||||
const char *get_filename_ext(const char *filename) {
|
||||
const char *get_filename_ext(const char *filename)
|
||||
{
|
||||
const char *dot = strrchr(filename, '.');
|
||||
if(!dot || dot == filename) return "";
|
||||
if (!dot || dot == filename) return "";
|
||||
return dot + 1;
|
||||
}
|
||||
|
||||
@ -409,17 +410,17 @@ static colored_layout *r_init_shared(cairo_t *c, notification *n)
|
||||
if (!settings.word_wrap) {
|
||||
PangoEllipsizeMode ellipsize;
|
||||
switch (settings.ellipsize) {
|
||||
case start:
|
||||
ellipsize = PANGO_ELLIPSIZE_START;
|
||||
break;
|
||||
case middle:
|
||||
ellipsize = PANGO_ELLIPSIZE_MIDDLE;
|
||||
break;
|
||||
case end:
|
||||
ellipsize = PANGO_ELLIPSIZE_END;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
case start:
|
||||
ellipsize = PANGO_ELLIPSIZE_START;
|
||||
break;
|
||||
case middle:
|
||||
ellipsize = PANGO_ELLIPSIZE_MIDDLE;
|
||||
break;
|
||||
case end:
|
||||
ellipsize = PANGO_ELLIPSIZE_END;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
pango_layout_set_ellipsize(cl->l, ellipsize);
|
||||
}
|
||||
@ -630,7 +631,7 @@ static dimension_t x_render_layout(cairo_t *c, colored_layout *cl, colored_layou
|
||||
if (use_padding)
|
||||
dim.y += h + settings.padding;
|
||||
else
|
||||
dim.y += (int) (floor(bg_half_height) + pango_offset);
|
||||
dim.y += (int)(floor(bg_half_height) + pango_offset);
|
||||
|
||||
if (settings.separator_height > 0 && !last) {
|
||||
color_t sep_color = x_get_separator_color(cl, cl_next);
|
||||
@ -648,7 +649,7 @@ static dimension_t x_render_layout(cairo_t *c, colored_layout *cl, colored_layou
|
||||
}
|
||||
cairo_move_to(c, settings.h_padding, dim.y);
|
||||
|
||||
if (cl->icon) {
|
||||
if (cl->icon) {
|
||||
unsigned int image_width = cairo_image_surface_get_width(cl->icon),
|
||||
image_height = cairo_image_surface_get_height(cl->icon),
|
||||
image_x,
|
||||
@ -660,9 +661,9 @@ static dimension_t x_render_layout(cairo_t *c, colored_layout *cl, colored_layou
|
||||
image_x = bg_width - settings.h_padding - image_width + settings.frame_width;
|
||||
}
|
||||
|
||||
cairo_set_source_surface (c, cl->icon, image_x, image_y);
|
||||
cairo_rectangle (c, image_x, image_y, image_width, image_height);
|
||||
cairo_fill (c);
|
||||
cairo_set_source_surface(c, cl->icon, image_x, image_y);
|
||||
cairo_rectangle(c, image_x, image_y, image_width, image_height);
|
||||
cairo_fill(c);
|
||||
}
|
||||
|
||||
return dim;
|
||||
@ -703,7 +704,6 @@ void x_win_draw(void)
|
||||
cairo_destroy(c);
|
||||
cairo_surface_destroy(image_surface);
|
||||
r_free_layouts(layouts);
|
||||
|
||||
}
|
||||
|
||||
static void x_win_move(int width, int height)
|
||||
@ -732,7 +732,6 @@ static void x_win_move(int width, int height)
|
||||
XResizeWindow(xctx.dpy, xctx.win, width, height);
|
||||
}
|
||||
|
||||
|
||||
xctx.window_dim.x = x;
|
||||
xctx.window_dim.y = y;
|
||||
xctx.window_dim.h = height;
|
||||
@ -743,8 +742,14 @@ static void setopacity(Window win, unsigned long opacity)
|
||||
{
|
||||
Atom _NET_WM_WINDOW_OPACITY =
|
||||
XInternAtom(xctx.dpy, "_NET_WM_WINDOW_OPACITY", false);
|
||||
XChangeProperty(xctx.dpy, win, _NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32,
|
||||
PropModeReplace, (unsigned char *)&opacity, 1L);
|
||||
XChangeProperty(xctx.dpy,
|
||||
win,
|
||||
_NET_WM_WINDOW_OPACITY,
|
||||
XA_CARDINAL,
|
||||
32,
|
||||
PropModeReplace,
|
||||
(unsigned char *)&opacity,
|
||||
1L);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -766,30 +771,30 @@ static KeySym x_numlock_mod()
|
||||
* could count as 'using implementation details',
|
||||
* so use this large switch. */
|
||||
switch (mod) {
|
||||
case ShiftMapIndex:
|
||||
sym = ShiftMask;
|
||||
goto end;
|
||||
case LockMapIndex:
|
||||
sym = LockMask;
|
||||
goto end;
|
||||
case ControlMapIndex:
|
||||
sym = ControlMask;
|
||||
goto end;
|
||||
case Mod1MapIndex:
|
||||
sym = Mod1Mask;
|
||||
goto end;
|
||||
case Mod2MapIndex:
|
||||
sym = Mod2Mask;
|
||||
goto end;
|
||||
case Mod3MapIndex:
|
||||
sym = Mod3Mask;
|
||||
goto end;
|
||||
case Mod4MapIndex:
|
||||
sym = Mod4Mask;
|
||||
goto end;
|
||||
case Mod5MapIndex:
|
||||
sym = Mod5Mask;
|
||||
goto end;
|
||||
case ShiftMapIndex:
|
||||
sym = ShiftMask;
|
||||
goto end;
|
||||
case LockMapIndex:
|
||||
sym = LockMask;
|
||||
goto end;
|
||||
case ControlMapIndex:
|
||||
sym = ControlMask;
|
||||
goto end;
|
||||
case Mod1MapIndex:
|
||||
sym = Mod1Mask;
|
||||
goto end;
|
||||
case Mod2MapIndex:
|
||||
sym = Mod2Mask;
|
||||
goto end;
|
||||
case Mod3MapIndex:
|
||||
sym = Mod3Mask;
|
||||
goto end;
|
||||
case Mod4MapIndex:
|
||||
sym = Mod4Mask;
|
||||
goto end;
|
||||
case Mod5MapIndex:
|
||||
sym = Mod5Mask;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -825,8 +830,7 @@ gboolean x_mainloop_fd_check(GSource *source)
|
||||
/*
|
||||
* Main Dispatcher for XEvents
|
||||
*/
|
||||
gboolean x_mainloop_fd_dispatch(GSource *source, GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
gboolean x_mainloop_fd_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
|
||||
{
|
||||
XEvent ev;
|
||||
unsigned int state;
|
||||
@ -1031,7 +1035,6 @@ void x_setup(void)
|
||||
x_win_setup();
|
||||
x_cairo_setup();
|
||||
x_shortcut_grab(&settings.history_ks);
|
||||
|
||||
}
|
||||
|
||||
static void x_set_wm(Window win)
|
||||
@ -1045,9 +1048,14 @@ static void x_set_wm(Window win)
|
||||
XInternAtom(xctx.dpy, "_NET_WM_NAME", false);
|
||||
|
||||
XStoreName(xctx.dpy, win, title);
|
||||
XChangeProperty(xctx.dpy, win, _net_wm_title,
|
||||
XInternAtom(xctx.dpy, "UTF8_STRING", false), 8,
|
||||
PropModeReplace, (unsigned char *) title, strlen(title));
|
||||
XChangeProperty(xctx.dpy,
|
||||
win,
|
||||
_net_wm_title,
|
||||
XInternAtom(xctx.dpy, "UTF8_STRING", false),
|
||||
8,
|
||||
PropModeReplace,
|
||||
(unsigned char *)title,
|
||||
strlen(title));
|
||||
|
||||
/* set window class */
|
||||
char *class = settings.class != NULL ? settings.class : "Dunst";
|
||||
@ -1062,8 +1070,14 @@ static void x_set_wm(Window win)
|
||||
data[0] = XInternAtom(xctx.dpy, "_NET_WM_WINDOW_TYPE_NOTIFICATION", false);
|
||||
data[1] = XInternAtom(xctx.dpy, "_NET_WM_WINDOW_TYPE_UTILITY", false);
|
||||
|
||||
XChangeProperty(xctx.dpy, win, net_wm_window_type, XA_ATOM, 32,
|
||||
PropModeReplace, (unsigned char *) data, 2L);
|
||||
XChangeProperty(xctx.dpy,
|
||||
win,
|
||||
net_wm_window_type,
|
||||
XA_ATOM,
|
||||
32,
|
||||
PropModeReplace,
|
||||
(unsigned char *)data,
|
||||
2L);
|
||||
|
||||
/* set state above */
|
||||
Atom net_wm_state =
|
||||
@ -1099,13 +1113,18 @@ static void x_win_setup(void)
|
||||
ButtonReleaseMask | FocusChangeMask| StructureNotifyMask;
|
||||
|
||||
screen_info *scr = get_active_screen();
|
||||
xctx.win =
|
||||
XCreateWindow(xctx.dpy, root, scr->dim.x, scr->dim.y, scr->dim.w,
|
||||
1, 0, DefaultDepth(xctx.dpy,
|
||||
DefaultScreen(xctx.dpy)),
|
||||
CopyFromParent, DefaultVisual(xctx.dpy,
|
||||
DefaultScreen(xctx.dpy)),
|
||||
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
|
||||
xctx.win = XCreateWindow(xctx.dpy,
|
||||
root,
|
||||
scr->dim.x,
|
||||
scr->dim.y,
|
||||
scr->dim.w,
|
||||
1,
|
||||
0,
|
||||
DefaultDepth(xctx.dpy, DefaultScreen(xctx.dpy)),
|
||||
CopyFromParent,
|
||||
DefaultVisual(xctx.dpy, DefaultScreen(xctx.dpy)),
|
||||
CWOverrideRedirect | CWBackPixmap | CWEventMask,
|
||||
&wa);
|
||||
|
||||
x_set_wm(xctx.win);
|
||||
settings.transparency =
|
||||
@ -1135,8 +1154,16 @@ void x_win_show(void)
|
||||
x_shortcut_grab(&settings.context_ks);
|
||||
|
||||
x_shortcut_setup_error_handler();
|
||||
XGrabButton(xctx.dpy, AnyButton, AnyModifier, xctx.win, false,
|
||||
BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
|
||||
XGrabButton(xctx.dpy,
|
||||
AnyButton,
|
||||
AnyModifier,
|
||||
xctx.win,
|
||||
false,
|
||||
BUTTONMASK,
|
||||
GrabModeAsync,
|
||||
GrabModeSync,
|
||||
None,
|
||||
None);
|
||||
if (x_shortcut_tear_down_error_handler()) {
|
||||
fprintf(stderr, "Unable to grab mouse button(s)\n");
|
||||
}
|
||||
@ -1181,7 +1208,6 @@ KeySym x_shortcut_string_to_mask(const char *str)
|
||||
fprintf(stderr, "Warning: Unknown Modifier: %s\n", str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1237,10 +1263,20 @@ int x_shortcut_grab(keyboard_shortcut *ks)
|
||||
x_shortcut_setup_error_handler();
|
||||
|
||||
if (ks->is_valid) {
|
||||
XGrabKey(xctx.dpy, ks->code, ks->mask, root,
|
||||
true, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(xctx.dpy, ks->code, ks->mask | x_numlock_mod() , root,
|
||||
true, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(xctx.dpy,
|
||||
ks->code,
|
||||
ks->mask,
|
||||
root,
|
||||
true,
|
||||
GrabModeAsync,
|
||||
GrabModeAsync);
|
||||
XGrabKey(xctx.dpy,
|
||||
ks->code,
|
||||
ks->mask | x_numlock_mod(),
|
||||
root,
|
||||
true,
|
||||
GrabModeAsync,
|
||||
GrabModeAsync);
|
||||
}
|
||||
|
||||
if (x_shortcut_tear_down_error_handler()) {
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
|
||||
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
|
||||
#define FONT_HEIGHT_BORDER 2
|
||||
#define DEFFONT "Monospace-11"
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user