Compare commits

..

52 Commits

Author SHA1 Message Date
a951e61a6c
Update libnotify deps 2017-09-02 01:00:43 +02:00
d830a339e1
Update libnotify-sys deps 2017-09-02 00:59:43 +02:00
843fb0c731
Fix build against latest glib 2017-07-19 19:47:08 +02:00
afcf7a7581
Fix build against latest gtk-rs 2017-07-14 00:47:21 +02:00
831b761b02 Explicitly add LICENSE to libnotify-sys subdir
So we also make sure it ends up in the cargo crate.
2017-07-13 11:41:45 +02:00
8e955a6e08 Add badges to libnotify-sys 2017-07-13 11:35:04 +02:00
a3d579d750 Fix LICENSE link 2017-07-13 11:24:15 +02:00
6536667a4d Reorder bagdes, add download count badge 2017-07-13 11:20:23 +02:00
f954a77778 Add documentation badges 2017-07-13 11:12:44 +02:00
Ospald, Julian
fc8ca1af63 Fix documentation 2017-07-11 16:33:31 +02:00
Ospald, Julian
f28b8bc052 Bump to 1.0.1 2017-07-11 15:59:55 +02:00
Ospald, Julian
49f09df64a Remove obsolete dependency 2017-07-11 15:59:24 +02:00
Ospald, Julian
a8b22fa6ef Cosmetic README fix 2017-07-11 15:53:01 +02:00
Ospald, Julian
5f551cf664 Add README.md to libnotify-sys 2017-07-11 15:53:01 +02:00
Ospald, Julian
08d77ee4ff Update metadata 2017-07-11 15:53:01 +02:00
Ospald, Julian
03059f79c6 Remove git dependencies 2017-07-11 15:53:01 +02:00
Ospald, Julian
091ee97b70 Remove BoolError occurences
Because currently depends on unpublished glib binding.
2017-07-11 15:53:01 +02:00
Ospald, Julian
d939bee7ea Cargo fmt 2017-07-11 15:24:10 +02:00
Ospald, Julian
557ebbc93f Fix examples 2017-07-11 15:18:40 +02:00
Ospald, Julian
b50ff703ad Update README 2017-07-11 15:06:27 +02:00
Ospald, Julian
a75ae6a1fe Fix documentation 2017-07-11 14:48:23 +02:00
Ospald, Julian
d2a17eba0b Fix compiler warnings 2017-07-11 14:48:17 +02:00
Ospald, Julian
e789326c83 Update .gitignore 2017-07-11 14:36:45 +02:00
Ospald, Julian
6a96044a68 Fix examples 2017-07-11 14:36:21 +02:00
Ospald, Julian
cee315cf36 Fix travis secret 2017-07-11 14:11:04 +02:00
Ospald, Julian
ac0502b16c Merge branch 'gir' 2017-07-11 13:58:52 +02:00
Ospald, Julian
fb42397f55 Fix README 2017-07-11 13:58:06 +02:00
Ospald, Julian
69f5fe66f1 Fix travis 2017-07-11 13:58:06 +02:00
13850652a7 Switch to gir 2017-07-11 13:58:06 +02:00
Ospald, Julian
965a64aa55 Drop use of gtypes 2017-07-10 11:57:41 +02:00
Ospald, Julian
9f6e3f5d31 Add Drop impl for Notification
The notification is now unrefed via the GObject system.
2017-07-10 11:53:22 +02:00
437f2cc756
Rename new_notification() to new() 2017-07-10 01:09:21 +02:00
fe4d803efe
Small rewrite:
* Use error-chain for errors and expose them
* Don't use Context object, since the lifetimes get us in trouble
  when used with gtk-rs, which has callback closures with static
  lifetime. Instead we just expose notify_init()/notify_uninit() and
  panic when functions are called before notify_init().
2017-07-10 01:01:36 +02:00
172cbd5143
Add lifetime specifiers to &self 2017-07-09 21:46:44 +02:00
8c16ab53b5
Update travis secret 2017-07-09 19:52:57 +02:00
f351cc15e2
Add Notification::close() 2017-07-09 19:33:53 +02:00
b77584e0a0
Add Notification::clear_hints() 2017-07-09 19:33:32 +02:00
c3897b7c0e
Add Notification::set_image_from_pixbuf() 2017-07-09 19:33:13 +02:00
6166c861e4
Add Notification::set_urgency() 2017-07-09 19:31:25 +02:00
c2efdd0842
Add Notification::set_category() 2017-07-09 19:30:49 +02:00
a52c50a318
Add Author 2017-07-09 14:38:55 +02:00
34880d2117
Bump version to 0.5.0 2017-07-09 14:34:45 +02:00
73eb0cc68d
Cosmetics 2017-07-09 14:25:30 +02:00
95263c33f8
Add Notification::set_hint() 2017-07-09 14:23:37 +02:00
cdc4af3be1
Add Notification::update() 2017-07-09 14:22:36 +02:00
8c66220a4e
Add Notification::set_notification_timeout() 2017-07-09 14:22:06 +02:00
923c801814
Fix gtypes version constraint 2017-07-09 14:20:11 +02:00
6e5a9ab5d4
Switch to using glib-sys
We need GVariant and to_glib_none() later,
which must be from the crate glib_sys.
2017-07-09 14:19:48 +02:00
bf90bccef8
Undeprecate 2017-07-09 13:52:54 +02:00
7d80600657
Fix body/icon pointing to garbage
The pattern matching moves 'body' and drops it after
creation of the pointer. We must avoid the move, by using 'ref'.
2017-07-09 12:51:55 +02:00
Mika Attila
5ab8f64e88 Deprecate in favor of notify-rust 2017-04-01 17:55:11 +02:00
Mika Attila
a61230b012 Update dependencies 2016-01-27 23:11:38 +01:00
20 changed files with 817 additions and 220 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
Cargo.lock Cargo.lock
target/ target/
.cargo/ .cargo/
docs.md

6
.gitmodules vendored Normal file
View File

@ -0,0 +1,6 @@
[submodule "gir"]
path = gir
url = https://github.com/gtk-rs/gir.git
[submodule "gir-files"]
path = gir-files
url = https://github.com/hasufell/gir-files.git

View File

@ -1,8 +1,18 @@
dist: trusty
sudo: false
language: rust language: rust
rust: rust:
- nightly - nightly
- beta - beta
- stable - stable
addons:
apt:
packages:
- libgdk-pixbuf2.0-common
- libgdk-pixbuf2.0-dev
- libglib2.0-data
- libglib2.0-dev
- libnotify-dev
before_script: before_script:
- | - |
pip install 'travis-cargo<0.2' --user && pip install 'travis-cargo<0.2' --user &&
@ -10,11 +20,11 @@ before_script:
script: script:
- | - |
travis-cargo build && travis-cargo build &&
travis-cargo test && # travis-cargo test &&
travis-cargo --only stable doc travis-cargo --only stable doc
after_success: after_success:
- travis-cargo --only stable doc-upload - travis-cargo --only stable doc-upload
env: env:
global: global:
- TRAVIS_CARGO_NIGHTLY_FEATURE="" - TRAVIS_CARGO_NIGHTLY_FEATURE=""
- secure: IjahTjjwmuvig/wTDMwxpk1F3Ywi2d0r17+JmOXHPdbfSfhi4puiTzsOgMjBhFtosTwcvlBeFwwFeTtl9KFNG165xm9Fqbhcez9sx+hS+EWZR/MBPFhKorJlgva0nuH8L1cxDUP+mDkcV/BdXCDeT7ml+y/FqEDAI4N0lwEsVMk= - secure: B9+n+ikrYqSxK1SYOHIvjtYi58IvdVC0HYJxyDiJnzIcEtos/aDiGbMZU1pIvC+qIAibdltIqzZ1afVC1msfsxeaov2e4VPKfTJV0gwLLq6tzuuaOeujtM9YUUWrdr8QQXk3LEPIl8HD5jm6VTLcl2TqPeiiyn96rk67nA5jeS8=

View File

@ -1,16 +1,24 @@
[package] [package]
authors = [
name = "libnotify" "Mika Attila <radiantstatue@gmail.com>",
version = "0.2.0" "Julian Ospald <hasufell@posteo.de>",
authors = ["Mika Attila <radiantstatue@gmail.com>"] ]
license = "MIT"
description = "Rust bindings to libnotify" description = "Rust bindings to libnotify"
documentation = "https://hasufell.github.io/rust-libnotify/libnotify/"
keywords = [
"libnotify",
"notification",
]
license = "MIT"
name = "libnotify"
readme = "README.md" readme = "README.md"
repository = "https://github.com/crumblingstatue/rust-libnotify" repository = "https://github.com/hasufell/rust-libnotify"
documentation = "http://crumblingstatue.github.io/doc/libnotify/libnotify/" version = "1.0.2"
keywords = ["libnotify", "notification"]
[dependencies] [dependencies]
libnotify-sys = "0.2.0" gdk-pixbuf = "^0.2.0"
glib-2-0-sys = "0.46.0" gdk-pixbuf-sys = "^0.4.0"
gtypes = "0.1.2" glib = "^0.3.1"
glib-sys = "^0.4.0"
gobject-sys = "^0.4.0"
libnotify-sys = "^1.0.1"

69
Gir.toml Normal file
View File

@ -0,0 +1,69 @@
[options]
girs_dir = "gir-files"
library = "Notify"
version = "0.7"
min_cfg_version = "0.7.7"
target_path = "."
work_mode = "normal"
generate_safety_asserts = true
deprecate_by_min_version = true
generate = [
"Notify.Urgency",
]
[[object]]
name = "Notify.Notification"
status = "generate"
[[object.function]]
name = "get_closed_reason"
ignore = true
[[object.function]]
name = "add_action"
ignore = true
[[object.function]]
name = "clear_actions"
ignore = true
[[object.function]]
name = "close"
# manual
ignore = true
[[object.function]]
name = "set_hint"
# manual
ignore = true
[[object.function]]
name = "set_icon_from_pixbuf"
# deprecated
ignore = true
[[object.function]]
name = "set_image_from_pixbuf"
# manual
ignore = true
[[object.function]]
name = "show"
# manual
ignore = true
[[object.function]]
name = "update"
[object.function.return]
bool_return_is_error = "Invalid parameter passed"
[[object.function]]
name = "set_app_name"
[[object.function.parameter]]
name = "app_name"
nullable = true
[[object]]
name = "Notify.*"
status = "generate"
[[object.function]]
name = "is_initted"
# manual assert_initialized_main_thread
ignore = true
[[object.function]]
name = "init"
# manual assert_initialized_main_thread
ignore = true

19
Makefile Normal file
View File

@ -0,0 +1,19 @@
GIR = gir/target/bin/gir
GIR_SRC = gir/Cargo.toml gir/Cargo.lock gir/build.rs $(shell find gir/src -name '*.rs')
GIR_FILES = gir-files/Notify-0.7.gir
# Run `gir` generating the bindings
gir : src/auto/mod.rs
src/auto/mod.rs : Gir.toml $(GIR) $(GIR_FILES)
$(GIR) -c Gir.toml
$(GIR) -m doc -c Gir.toml
rustdoc-stripper -g -o docs.md
$(GIR) : $(GIR_SRC)
rm -f gir/target/bin/gir
cargo install --path gir --root gir/target
rm -f gir/target/.crates.toml
$(GIR_SRC) $(GIR_FILES) :
git submodule update --init

View File

@ -1,4 +1,12 @@
[![Build Status](https://travis-ci.org/crumblingstatue/rust-libnotify.svg)](https://travis-ci.org/crumblingstatue/rust-libnotify) [![Latest Version](https://img.shields.io/crates/v/libnotify.svg)](https://crates.io/crates/libnotify)
[![License](https://img.shields.io/github/license/hasufell/rust-libnotify.svg)](LICENSE)
[![Crate download count](https://img.shields.io/crates/d/libnotify.svg)](https://crates.io/crates/libnotify)
# libnotify-rs [![Documentation (crates.io)](https://img.shields.io/badge/documentation-docs.rs-df3600.svg)](https://docs.rs/libnotify)
Rust binding to libnotify [![Documentation (master)](https://img.shields.io/badge/documentation-master-yellow.svg)](https://hasufell.github.io/rust-libnotify/)
[![Build Status](https://travis-ci.org/hasufell/rust-libnotify.svg)](https://travis-ci.org/hasufell/rust-libnotify)
[![Join the chat at https://gitter.im/hasufell/rust-libnotify](https://badges.gitter.im/hasufell/rust-libnotify.svg)](https://gitter.im/hasufell/rust-libnotify?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
# rust-libnotify
Rust binding to libnotify.

View File

@ -1,11 +1,17 @@
extern crate libnotify; extern crate libnotify;
fn main() { fn main() {
// Create a libnotify context // Init libnotify
let notify = libnotify::Context::new("myapp").unwrap(); libnotify::init("myapp");
// Create a new notification and show it // Create a new notification (doesn't show it yet)
let n = notify.new_notification("Summary", Some("Optional Body"), None).unwrap(); let n =
libnotify::Notification::new("Summary", Some("Optional Body"), None);
// Show the notification
n.show().unwrap(); n.show().unwrap();
// You can also use the .show() convenience method on the context // Update the existent notification
notify.show("I am another notification", None, None).unwrap(); n.update("I am another notification", None, None).unwrap();
// Show the updated notification
n.show().unwrap();
// We are done, deinit
libnotify::uninit();
} }

1
gir Submodule

@ -0,0 +1 @@
Subproject commit ac9a8dadb62d003af9f0c6ed46e82ff0971125e5

1
gir-files Submodule

@ -0,0 +1 @@
Subproject commit 1f01de0ff05a22bdb5de4b1a330c46bdafdea300

11
gir-libnotify.toml Normal file
View File

@ -0,0 +1,11 @@
[options]
work_mode = "sys"
library = "Notify"
version = "0.7"
min_cfg_version = "0.7.6"
external_libraries = [
"GLib",
"GObject",
"GdkPixbuf",
]

30
libnotify-sys/Cargo.toml Normal file
View File

@ -0,0 +1,30 @@
[package]
authors = [
"Mika Attila <radiantstatue@gmail.com>",
"Julian Ospald <hasufell@posteo.de>",
]
build = "build.rs"
description = "FFI bindings to libnotify"
keywords = [
"libnotify",
"notification",
]
license = "MIT"
links = "libnotify"
name = "libnotify-sys"
readme = "README.md"
repository = "https://github.com/hasufell/rust-libnotify"
version = "1.0.1"
[build-dependencies]
pkg-config = ">=0.3.9"
[dependencies]
bitflags = "^0.9.1"
gdk-pixbuf-sys = "^0.4.0"
glib-sys = "^0.4.0"
gobject-sys = "^0.4.0"
libc = "^0.2.30"
[lib]
name = "libnotify_sys"

21
libnotify-sys/LICENSE Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Mika Attila
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

7
libnotify-sys/README.md Normal file
View File

@ -0,0 +1,7 @@
[![Latest Version](https://img.shields.io/crates/v/libnotify-sys.svg)](https://crates.io/crates/libnotify-sys)
[![License](https://img.shields.io/github/license/hasufell/rust-libnotify.svg)](LICENSE)
[![Crate download count](https://img.shields.io/crates/d/libnotify-sys.svg)](https://crates.io/crates/libnotify-sys)
# rust-libnotify-sys
Rust FFI declarations for libnotify

61
libnotify-sys/build.rs Normal file
View File

@ -0,0 +1,61 @@
extern crate pkg_config;
use pkg_config::{Config, Error};
use std::env;
use std::io::prelude::*;
use std::io;
use std::process;
fn main() {
if let Err(s) = find() {
let _ = writeln!(io::stderr(), "{}", s);
process::exit(1);
}
}
fn find() -> Result<(), Error> {
let package_name = "libnotify";
let shared_libs = ["notify"];
let version = {
"0.7.6"
};
if let Ok(lib_dir) = env::var("GTK_LIB_DIR") {
for lib_ in shared_libs.iter() {
println!("cargo:rustc-link-lib=dylib={}", lib_);
}
println!("cargo:rustc-link-search=native={}", lib_dir);
return Ok(())
}
let target = env::var("TARGET").expect("TARGET environment variable doesn't exist");
let hardcode_shared_libs = target.contains("windows");
let mut config = Config::new();
config.atleast_version(version);
if hardcode_shared_libs {
config.cargo_metadata(false);
}
match config.probe(package_name) {
Ok(library) => {
if hardcode_shared_libs {
for lib_ in shared_libs.iter() {
println!("cargo:rustc-link-lib=dylib={}", lib_);
}
for path in library.link_paths.iter() {
println!("cargo:rustc-link-search=native={}",
path.to_str().expect("library path doesn't exist"));
}
}
Ok(())
}
Err(Error::EnvNoPkgConfig(_)) | Err(Error::Command { .. }) => {
for lib_ in shared_libs.iter() {
println!("cargo:rustc-link-lib=dylib={}", lib_);
}
Ok(())
}
Err(err) => Err(err),
}
}

98
libnotify-sys/src/lib.rs Normal file
View File

@ -0,0 +1,98 @@
// This file was generated by gir (89daf8f) from gir-files (1f01de0)
// DO NOT EDIT
#![allow(non_camel_case_types, non_upper_case_globals)]
extern crate libc;
extern crate bitflags;
extern crate glib_sys as glib;
extern crate gobject_sys as gobject;
extern crate gdk_pixbuf_sys as gdk_pixbuf;
#[allow(unused_imports)]
use libc::{c_int, c_char, c_uchar, c_float, c_uint, c_double,
c_short, c_ushort, c_long, c_ulong,
c_void, size_t, ssize_t, intptr_t, uintptr_t, time_t, FILE};
#[allow(unused_imports)]
use glib::{gboolean, gconstpointer, gpointer, GType, Volatile};
// Enums
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(C)]
pub enum NotifyUrgency {
Low = 0,
Normal = 1,
Critical = 2,
}
pub const NOTIFY_URGENCY_LOW: NotifyUrgency = NotifyUrgency::Low;
pub const NOTIFY_URGENCY_NORMAL: NotifyUrgency = NotifyUrgency::Normal;
pub const NOTIFY_URGENCY_CRITICAL: NotifyUrgency = NotifyUrgency::Critical;
// Constants
pub const NOTIFY_EXPIRES_DEFAULT: c_int = -1;
pub const NOTIFY_EXPIRES_NEVER: c_int = 0;
pub const NOTIFY_VERSION_MAJOR: c_int = 0;
pub const NOTIFY_VERSION_MICRO: c_int = 7;
pub const NOTIFY_VERSION_MINOR: c_int = 7;
// Callbacks
pub type NotifyActionCallback = Option<unsafe extern "C" fn(*mut NotifyNotification, *mut c_char, gpointer)>;
// Records
#[repr(C)]
pub struct NotifyNotificationClass {
pub parent_class: gobject::GObjectClass,
pub closed: Option<unsafe extern "C" fn(*mut NotifyNotification)>,
}
#[repr(C)]
pub struct NotifyNotificationPrivate(c_void);
// Classes
#[repr(C)]
pub struct NotifyNotification {
pub parent_object: gobject::GObject,
pub priv_: *mut NotifyNotificationPrivate,
}
extern "C" {
//=========================================================================
// NotifyNotification
//=========================================================================
pub fn notify_notification_get_type() -> GType;
pub fn notify_notification_new(summary: *const c_char, body: *const c_char, icon: *const c_char) -> *mut NotifyNotification;
//pub fn notify_notification_add_action(notification: *mut NotifyNotification, action: *const c_char, label: *const c_char, callback: NotifyActionCallback, user_data: gpointer, free_func: /*Metadata mismatch*/[c:type mismatch `GFreeFunc` != `GDestroyNotify` of `DestroyNotify`]);
pub fn notify_notification_clear_actions(notification: *mut NotifyNotification);
pub fn notify_notification_clear_hints(notification: *mut NotifyNotification);
pub fn notify_notification_close(notification: *mut NotifyNotification, error: *mut *mut glib::GError) -> gboolean;
pub fn notify_notification_get_closed_reason(notification: *const NotifyNotification) -> c_int;
pub fn notify_notification_set_app_name(notification: *mut NotifyNotification, app_name: *const c_char);
pub fn notify_notification_set_category(notification: *mut NotifyNotification, category: *const c_char);
pub fn notify_notification_set_hint(notification: *mut NotifyNotification, key: *const c_char, value: *mut glib::GVariant);
pub fn notify_notification_set_hint_byte(notification: *mut NotifyNotification, key: *const c_char, value: c_uchar);
pub fn notify_notification_set_hint_byte_array(notification: *mut NotifyNotification, key: *const c_char, value: *mut u8, len: size_t);
pub fn notify_notification_set_hint_double(notification: *mut NotifyNotification, key: *const c_char, value: c_double);
pub fn notify_notification_set_hint_int32(notification: *mut NotifyNotification, key: *const c_char, value: c_int);
pub fn notify_notification_set_hint_string(notification: *mut NotifyNotification, key: *const c_char, value: *const c_char);
pub fn notify_notification_set_hint_uint32(notification: *mut NotifyNotification, key: *const c_char, value: c_uint);
pub fn notify_notification_set_icon_from_pixbuf(notification: *mut NotifyNotification, icon: *mut gdk_pixbuf::GdkPixbuf);
pub fn notify_notification_set_image_from_pixbuf(notification: *mut NotifyNotification, pixbuf: *mut gdk_pixbuf::GdkPixbuf);
pub fn notify_notification_set_timeout(notification: *mut NotifyNotification, timeout: c_int);
pub fn notify_notification_set_urgency(notification: *mut NotifyNotification, urgency: NotifyUrgency);
pub fn notify_notification_show(notification: *mut NotifyNotification, error: *mut *mut glib::GError) -> gboolean;
pub fn notify_notification_update(notification: *mut NotifyNotification, summary: *const c_char, body: *const c_char, icon: *const c_char) -> gboolean;
//=========================================================================
// Other functions
//=========================================================================
pub fn notify_get_app_name() -> *const c_char;
pub fn notify_get_server_caps() -> *mut glib::GList;
pub fn notify_get_server_info(ret_name: *mut *mut c_char, ret_vendor: *mut *mut c_char, ret_version: *mut *mut c_char, ret_spec_version: *mut *mut c_char) -> gboolean;
pub fn notify_init(app_name: *const c_char) -> gboolean;
pub fn notify_is_initted() -> gboolean;
pub fn notify_set_app_name(app_name: *const c_char);
pub fn notify_uninit();
}

45
src/enums.rs Normal file
View File

@ -0,0 +1,45 @@
// This file was generated by gir (89daf8f) from gir-files (1f01de0)
// DO NOT EDIT
use ffi;
use glib::translate::*;
use std;
/// The urgency level of the notification.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum Urgency {
/// Low urgency. Used for unimportant notifications.
Low,
/// Normal urgency. Used for most standard notifications.
Normal,
/// Critical urgency. Used for very important notifications.
Critical,
#[doc(hidden)]
__Unknown(i32),
}
#[doc(hidden)]
impl ToGlib for Urgency {
type GlibType = ffi::NotifyUrgency;
fn to_glib(&self) -> ffi::NotifyUrgency {
match *self {
Urgency::Low => ffi::NOTIFY_URGENCY_LOW,
Urgency::Normal => ffi::NOTIFY_URGENCY_NORMAL,
Urgency::Critical => ffi::NOTIFY_URGENCY_CRITICAL,
Urgency::__Unknown(value) => unsafe { std::mem::transmute(value) },
}
}
}
#[doc(hidden)]
impl FromGlib<ffi::NotifyUrgency> for Urgency {
fn from_glib(value: ffi::NotifyUrgency) -> Self {
match value as i32 {
0 => Urgency::Low,
1 => Urgency::Normal,
2 => Urgency::Critical,
value => Urgency::__Unknown(value),
}
}
}

112
src/functions.rs Normal file
View File

@ -0,0 +1,112 @@
use ffi;
use glib::translate::*;
use glib_ffi;
use std::ptr;
/// Gets whether or not libnotify is initialized.
///
/// # Returns
///
/// `true` if libnotify is initialized, or `false` otherwise.
pub fn is_initted() -> bool {
unsafe { from_glib(ffi::notify_is_initted()) }
}
/// Initialized libnotify. This must be called before any other functions.
///
/// # Returns
///
/// `Ok(())` if successful, `Err(str)` on error.
// TODO: switch back to BoolError when it hits stable glib
pub fn init(app_name: &str) -> Result<(), String> {
unsafe {
let b = ffi::notify_init(app_name.to_glib_none().0);
match b {
glib_ffi::GFALSE => Err(
String::from("Failed to initialize libnotify"),
),
_ => Ok(()),
}
}
}
/// Gets the application name registered.
///
/// # Returns
///
/// The registered application name, passed to `init()`.
pub fn get_app_name() -> Option<String> {
assert_initialized_libnotify!();
unsafe { from_glib_none(ffi::notify_get_app_name()) }
}
/// Synchronously queries the server for its capabilities and returns them as
/// a Vector.
///
/// # Returns
///
/// A Vector of server capability Strings.
pub fn get_server_caps() -> Vec<String> {
assert_initialized_libnotify!();
unsafe {
FromGlibPtrContainer::from_glib_full(ffi::notify_get_server_caps())
}
}
/// Synchronously queries the server for its information, specifically,
/// the name, vendor, server version, and the version of the notifications
/// specification that it is compliant with.
///
/// # Returns
///
/// `Some(ret_name, ret_vendor, ret_version, ret_spec_version)` on
/// success, otherwise `None` on error.
pub fn get_server_info() -> Option<(String, String, String, String)> {
assert_initialized_libnotify!();
unsafe {
let mut ret_name = ptr::null_mut();
let mut ret_vendor = ptr::null_mut();
let mut ret_version = ptr::null_mut();
let mut ret_spec_version = ptr::null_mut();
let ret = from_glib(ffi::notify_get_server_info(
&mut ret_name,
&mut ret_vendor,
&mut ret_version,
&mut ret_spec_version,
));
if ret {
Some((
from_glib_full(ret_name),
from_glib_full(ret_vendor),
from_glib_full(ret_version),
from_glib_full(ret_spec_version),
))
} else {
None
}
}
}
/// Sets the application name.
/// ## `app_name`
/// The name of the application.
pub fn set_app_name(app_name: &str) {
assert_initialized_libnotify!();
unsafe {
ffi::notify_set_app_name(app_name.to_glib_none().0);
}
}
/// Uninitialized libnotify.
///
/// This should be called when the program no longer needs libnotify for
/// the rest of its lifecycle, typically just before exitting.
pub fn uninit() {
assert_initialized_libnotify!();
unsafe {
ffi::notify_uninit();
}
}

View File

@ -4,217 +4,49 @@
//! extern crate libnotify; //! extern crate libnotify;
//! //!
//! fn main() { //! fn main() {
//! // Create a libnotify context //! // Init libnotify
//! let notify = libnotify::Context::new("myapp").unwrap(); //! libnotify::init("myapp").unwrap();
//! // Create a new notification and show it //! // Create a new notification (doesn't show it yet)
//! let n = notify.new_notification("Summary", //! let n = libnotify::Notification::new("Summary",
//! Some("Optional Body"), //! Some("Optional Body"),
//! None).unwrap(); //! None);
//! // Show the notification
//! n.show().unwrap(); //! n.show().unwrap();
//! // You can also use the .show() convenience method on the context //! // Update the existent notification
//! notify.show("I am another notification", None, None).unwrap(); //! n.update("I am another notification", None, None).unwrap();
//! // Show the updated notification
//! n.show().unwrap();
//! // We are done, deinit
//! libnotify::uninit();
//! } //! }
//! //!
//! ``` //! ```
#![warn(missing_docs)] #![warn(missing_docs)]
extern crate libnotify_sys as sys; extern crate gdk_pixbuf;
extern crate glib_2_0_sys as glib; #[macro_use]
extern crate gtypes; extern crate glib;
extern crate glib_sys as glib_ffi;
extern crate gobject_sys as gobject_ffi;
extern crate libnotify_sys as ffi;
use std::ffi::{self, CStr, CString};
use std::marker::PhantomData;
use std::fmt;
use std::error::Error;
use gtypes::{TRUE, FALSE}; pub use enums::*;
pub use functions::*;
pub use notification::*;
/// Error that can happen on context creation
#[derive(Debug)]
pub enum ContextCreationError {
/// Context already exists.
AlreadyExists,
/// Failed to initialize libnotify.
InitError,
/// A nul byte was found in the provided string.
NulError(ffi::NulError),
}
impl fmt::Display for ContextCreationError { macro_rules! assert_initialized_libnotify {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { () => {
use ContextCreationError::*; use functions::*;
match *self { if !is_initted() {
AlreadyExists => write!(f, "A Libnotify context already exists."), panic!("Notify system not initialized, invalid call of function");
InitError => write!(f, "Failed to initialize libnotify."),
NulError(ref e) => write!(f, "{}", e),
} }
} }
} }
impl From<ffi::NulError> for ContextCreationError {
fn from(src: ffi::NulError) -> Self {
ContextCreationError::NulError(src)
}
}
#[derive(Debug)] mod enums;
/// An error that can happen when attempting to create a notification. mod functions;
pub enum NotificationCreationError { mod notification;
/// A nul byte was found in the provided string.
NulError(ffi::NulError),
/// An unknown error happened.
Unknown,
}
impl fmt::Display for NotificationCreationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use NotificationCreationError::*;
match *self {
NulError(ref e) => write!(f, "{}", e),
Unknown => write!(f, "Unknown error"),
}
}
}
impl From<ffi::NulError> for NotificationCreationError {
fn from(src: ffi::NulError) -> Self {
NotificationCreationError::NulError(src)
}
}
impl Error for NotificationCreationError {
fn description(&self) -> &str {
"notification creation error"
}
}
/// The context which within libnotify operates.
///
/// Only one context can exist at a time.
pub struct Context;
impl Context {
/// Create a new context
///
/// Arguments:
///
/// - app_name: The name of the application using the context
pub fn new(app_name: &str) -> Result<Context, ContextCreationError> {
unsafe {
if sys::notify_is_initted() == TRUE {
return Err(ContextCreationError::AlreadyExists);
}
let app_name = try!(CString::new(app_name));
if sys::notify_init(app_name.as_ptr()) == FALSE {
return Err(ContextCreationError::InitError);
}
}
Ok(Context)
}
/// Creates a new Notification.
///
/// Arguments:
///
/// - summary: Required summary text
/// - body: Optional body text
/// - icon: Optional icon theme icon name or filename
pub fn new_notification(&self,
summary: &str,
body: Option<&str>,
icon: Option<&str>)
-> Result<Notification, NotificationCreationError> {
let summary = try!(CString::new(summary));
let body = match body {
Some(body) => Some(try!(CString::new(body))),
None => None,
};
let body_ptr = match body {
Some(body) => body.as_ptr(),
None => std::ptr::null(),
};
let icon = match icon {
Some(icon) => Some(try!(CString::new(icon))),
None => None,
};
let icon_ptr = match icon {
Some(icon) => icon.as_ptr(),
None => std::ptr::null(),
};
unsafe {
let n = sys::notify_notification_new(summary.as_ptr(), body_ptr, icon_ptr);
if n.is_null() {
return Err(NotificationCreationError::Unknown);
}
Ok(Notification {
handle: n,
_phantom: PhantomData,
})
}
}
/// Show a notification.
///
/// This is a convenience method that creates a new notification,
/// and shows it in one step.
pub fn show(&self,
summary: &str,
body: Option<&str>,
icon: Option<&str>)
-> Result<(), Box<Error>> {
let notif = try!(self.new_notification(summary, body, icon));
try!(notif.show());
Ok(())
}
}
impl Drop for Context {
fn drop(&mut self) {
unsafe {
sys::notify_uninit();
}
}
}
/// A passive pop-up notification
pub struct Notification<'a> {
handle: *mut sys::NotifyNotification,
_phantom: PhantomData<&'a Context>,
}
impl<'a> Notification<'a> {
/// Tells the notification server to display the notification
/// on the screen.
pub fn show(&'a self) -> Result<(), NotificationShowError> {
unsafe {
let mut err: *mut glib::GError = std::ptr::null_mut();
sys::notify_notification_show(self.handle, &mut err);
if !err.is_null() {
let result = Err(NotificationShowError {
message: CStr::from_ptr((*err).message).to_string_lossy().into_owned(),
});
glib::g_error_free(err);
return result;
}
Ok(())
}
}
}
/// An error that can happen when attempting to show a notification.
#[derive(Debug)]
pub struct NotificationShowError {
message: String,
}
impl fmt::Display for NotificationShowError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Error showing notification: {}", self.message)
}
}
impl Error for NotificationShowError {
fn description(&self) -> &str {
"notification show error"
}
}

251
src/notification.rs Normal file
View File

@ -0,0 +1,251 @@
use Urgency;
use ffi;
use gdk_pixbuf;
use glib::translate::*;
use glib;
use glib_ffi;
use gobject_ffi;
use std::mem;
use std::ptr;
use std;
glib_wrapper! {
/// `Notification` represents a passive pop-up notification. It can contain
/// summary text, body text, and an icon, as well as hints specifying how
/// the notification should be presented. The notification is rendered by
/// a notification daemon, and may present the notification in any number
/// of ways. As such, there is a clear separation of content and
/// presentation, and this API enforces that.
pub struct Notification(Object<ffi::NotifyNotification>);
match fn {
get_type => || ffi::notify_notification_get_type(),
}
}
impl Notification {
/// Creates a new `Notification`. The summary text is required, but
/// all other parameters are optional.
/// ## `summary`
/// The required summary text.
/// ## `body`
/// The optional body text.
/// ## `icon`
/// The optional icon theme icon name or filename.
///
/// # Returns
///
/// The new `Notification`.
pub fn new<'a, 'b, P: Into<Option<&'a str>>, Q: Into<Option<&'b str>>>(
summary: &str,
body: P,
icon: Q,
) -> Notification {
assert_initialized_libnotify!();
let body = body.into();
let body = body.to_glib_none();
let icon = icon.into();
let icon = icon.to_glib_none();
unsafe {
from_glib_full(ffi::notify_notification_new(
summary.to_glib_none().0,
body.0,
icon.0,
))
}
}
/// Synchronously tells the notification server to hide the notification on the screen.
///
/// # Returns
///
/// `Ok(())` on success, or `Err(err)` on error
pub fn close(&self) -> Result<(), glib::error::Error> {
assert_initialized_libnotify!();
unsafe {
let mut err: *mut glib_ffi::GError = std::ptr::null_mut();
ffi::notify_notification_close(self.to_glib_none().0, &mut err);
if !err.is_null() {
return Err(glib::error::Error::wrap(err));
} else {
return Ok(());
}
}
}
/// Tells the notification server to display the notification on the screen.
///
/// # Returns
///
/// `Ok(())` on success, or `Err(err)` on error
// TODO: test if Error leaks memory
pub fn show(&self) -> Result<(), glib::error::Error> {
assert_initialized_libnotify!();
unsafe {
let mut err: *mut glib_ffi::GError = std::ptr::null_mut();
ffi::notify_notification_show(self.to_glib_none().0, &mut err);
if !err.is_null() {
return Err(glib::error::Error::wrap(err));
} else {
return Ok(());
}
}
}
/// Sets a hint for `key` with value `value`. If `value` is `None`,
/// a previously set hint for `key` is unset.
///
/// If `value` is floating, it is consumed.
/// ## `key`
/// the hint key
/// ## `value`
pub fn set_hint(&self, key: &str, value: Option<glib::variant::Variant>) {
assert_initialized_libnotify!();
let gvalue: *mut glib_ffi::GVariant = {
match value {
Some(ref value) => value.to_glib_none().0,
None => std::ptr::null_mut(),
}
};
unsafe {
ffi::notify_notification_set_hint(
self.to_glib_none().0,
key.to_glib_none().0,
gvalue,
)
}
}
/// Sets the image in the notification from a `gdk_pixbuf::Pixbuf`.
/// ## `pixbuf`
/// The image.
pub fn set_image_from_pixbuf(&self, pixbuf: &gdk_pixbuf::Pixbuf) {
assert_initialized_libnotify!();
unsafe {
ffi::notify_notification_set_image_from_pixbuf(
self.to_glib_none().0,
pixbuf.to_glib_none().0,
);
}
}
/// Clears all hints from the notification.
pub fn clear_hints(&self) {
unsafe {
ffi::notify_notification_clear_hints(self.to_glib_none().0);
}
}
/// Sets the application name for the notification. If this function is
/// not called or if `app_name` is `None`, the application name will be
/// set from the value used in `notify_init` or overridden with
/// `notify_set_app_name`.
/// ## `app_name`
/// the localised application name
pub fn set_app_name<'a, P: Into<Option<&'a str>>>(&self, app_name: P) {
let app_name = app_name.into();
let app_name = app_name.to_glib_none();
unsafe {
ffi::notify_notification_set_app_name(
self.to_glib_none().0,
app_name.0,
);
}
}
/// Sets the category of this notification. This can be used by the
/// notification server to filter or display the data in a certain way.
/// ## `category`
/// The category.
pub fn set_category(&self, category: &str) {
unsafe {
ffi::notify_notification_set_category(
self.to_glib_none().0,
category.to_glib_none().0,
);
}
}
/// Sets the timeout of the notification. To set the default time, pass
/// `NOTIFY_EXPIRES_DEFAULT` as `timeout`. To set the notification to never
/// expire, pass `NOTIFY_EXPIRES_NEVER`.
///
/// Note that the timeout may be ignored by the server.
/// ## `timeout`
/// The timeout in milliseconds.
pub fn set_timeout(&self, timeout: i32) {
unsafe {
ffi::notify_notification_set_timeout(
self.to_glib_none().0,
timeout,
);
}
}
/// Sets the urgency level of this notification.
///
/// See: `Urgency`
/// ## `urgency`
/// The urgency level.
pub fn set_urgency(&self, urgency: Urgency) {
unsafe {
ffi::notify_notification_set_urgency(
self.to_glib_none().0,
urgency.to_glib(),
);
}
}
/// Updates the notification text and icon. This won't send the update out
/// and display it on the screen. For that, you will need to call
/// `Notification::show`.
/// ## `summary`
/// The new required summary text.
/// ## `body`
/// The optional body text.
/// ## `icon`
/// The optional icon theme icon name or filename.
///
/// # Returns
///
/// `Ok(())` on success, or `Err(str)` if an invalid parameter was passed
// TODO: switch back to BoolError when it hits stable glib
pub fn update<
'a,
'b,
P: Into<Option<&'a str>>,
Q: Into<Option<&'b str>>,
>(
&self,
summary: &str,
body: P,
icon: Q,
) -> Result<(), String> {
let body = body.into();
let body = body.to_glib_none();
let icon = icon.into();
let icon = icon.to_glib_none();
unsafe {
let b = ffi::notify_notification_update(
self.to_glib_none().0,
summary.to_glib_none().0,
body.0,
icon.0,
);
match b {
glib_ffi::GFALSE => Err(
String::from("Invalid parameter passed"),
),
_ => Ok(()),
}
}
}
}