46 Commits
v0.0.4 ... gir

Author SHA1 Message Date
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
Mika Attila
a74f4c9888 Add convenience method to context for showing a notification 2015-11-03 10:06:33 +01:00
Mika Attila
69a2d18218 Version bump 2015-11-03 09:19:13 +01:00
Mika Attila
c698097ffd Remove unnecessary return statement 2015-11-03 09:17:20 +01:00
Mika Attila
8daef60a03 Implement From<ffi::NulError> for error types that have this variant 2015-11-03 09:15:16 +01:00
Mika Attila
d282d2cd50 Add remaining missing documentation 2015-11-03 01:04:22 +01:00
Mika Attila
6251e0ad5c Expose ffi::NulError in nul errors 2015-11-03 01:01:49 +01:00
Mika Attila
db2578ea92 Use fmt::Result 2015-11-03 00:55:09 +01:00
Mika Attila
ba947a35f8 Rename InitFailure to InitError and add documentation 2015-11-03 00:54:03 +01:00
Mika Attila
503eee4441 Warn about missing documentation 2015-11-03 00:51:20 +01:00
Mika Attila
4b0aaab709 Update doc example 2015-11-03 00:50:27 +01:00
Mika Attila
94bb46164f Add NotificationShowError 2015-11-03 00:49:12 +01:00
Mika Attila
3dfc03aebd Format source code with rustfmt 2015-11-02 23:55:35 +01:00
Mika Attila
7bc56e4974 Let's try this again, shall we? 2015-11-01 22:07:39 +01:00
Mika Attila
d42152428f Remove some unnecessary stuff from .travis.yml 2015-11-01 22:05:12 +01:00
Mika Attila
619409ffc4 Add travis badge 2015-11-01 22:03:36 +01:00
Mika Attila
8e7b939a78 Add .travis.yml 2015-11-01 22:01:07 +01:00
Mika Attila
d19aadb4d2 Version bump 2015-10-24 14:55:05 +02:00
Mika Attila
7556615e78 Specify exact versions of dependencies 2015-10-24 14:54:47 +02:00
Mika Attila
1636812abc Merge pull request #1 from mzabaluev/rename-glib-sys
Renaming of glib packages
2015-10-23 22:51:28 +02:00
Mikhail Zabaluev
d979d8a2d1 Renamed glib packages
I'm going to normalize the package names in gi-rust, while also switching
to generated code that provides nearly all of the library API. This
package is one of the few that depends on the current name.
2015-10-23 23:34:09 +03:00
17 changed files with 730 additions and 170 deletions

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

30
.travis.yml Normal file
View File

@@ -0,0 +1,30 @@
dist: trusty
sudo: false
language: rust
rust:
- nightly
- beta
- stable
addons:
apt:
packages:
- libgdk-pixbuf2.0-common
- libgdk-pixbuf2.0-dev
- libglib2.0-data
- libglib2.0-dev
- libnotify-dev
before_script:
- |
pip install 'travis-cargo<0.2' --user &&
export PATH=$HOME/.local/bin:$PATH
script:
- |
travis-cargo build &&
# travis-cargo test &&
travis-cargo --only stable doc
after_success:
- travis-cargo --only stable doc-upload
env:
global:
- TRAVIS_CARGO_NIGHTLY_FEATURE=""
- secure: B8QPcNgwOmbJ8dNJn/p/tE1cLeUOLTo/Oj7nOBkK1tatMgS6yfQFa5pyNEqeTyZAyNptssqSH1BpRC3RxTJ/b+kFzdy8Kq1nkJfp9R9zTY34w5gWukfmmTH4Qe2lyWY/DKL1lGVjb+8mroV9sPaS5Y4DqYHbeYtpWF8Gi27vIL4=

View File

@@ -1,8 +1,7 @@
[package]
name = "libnotify"
version = "0.0.4"
authors = ["Mika Attila <radiantstatue@gmail.com>"]
version = "1.0.0"
authors = ["Mika Attila <radiantstatue@gmail.com>", "Julian Ospald <hasufell@posteo.de>"]
license = "MIT"
description = "Rust bindings to libnotify"
readme = "README.md"
@@ -11,6 +10,10 @@ documentation = "http://crumblingstatue.github.io/doc/libnotify/libnotify/"
keywords = ["libnotify", "notification"]
[dependencies]
libnotify-sys = "*"
glib-2_0-sys = "*"
gtypes = "*"
error-chain = ">=0.10.0"
gdk-pixbuf = { git = "https://github.com/gtk-rs/gdk-pixbuf.git" }
gdk-pixbuf-sys = { git = "https://github.com/gtk-rs/sys" }
glib = { git = "https://github.com/gtk-rs/glib.git" }
glib-sys = { git = "https://github.com/gtk-rs/sys" }
gobject-sys = { git = "https://github.com/gtk-rs/sys" }
libnotify-sys = { path = "libnotify-sys" }

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,2 +1,8 @@
[![Build Status](https://travis-ci.org/hasufell/rust-libnotify.svg)](https://travis-ci.org/hasufell/rust-libnotify)
[![Latest Version](https://img.shields.io/crates/v/libnotify.svg)](https://crates.io/crates/libnotify)
# libnotify-rs
Rust binding to libnotify
Rust binding to libnotify.
* [Online documentation](https://hasufell.github.io/rust-libnotify/)

View File

@@ -1,12 +1,17 @@
extern crate libnotify;
fn main() {
let notify = libnotify::Context::new("hello").unwrap_or_else(|e| {
panic!("{}", e);
});
let body_text = Some("This is the optional body text.");
let n = notify.new_notification("This is the summary.",
body_text,
None).unwrap_or_else(|e| panic!("{}", e));
n.show().ok().expect("Failed to show notification");
// Init libnotify
libnotify::init("myapp");
// Create a new notification and show it
let n =
libnotify::Notification::new("Summary", Some("Optional Body"), None);
// Show the notification
n.show().unwrap();
// You can also use the .show() convenience method on the context
n.update("I am another notification", None, None).unwrap();
// Show the update notification
n.show().unwrap();
// We are done, deinit
libnotify::uninit();
}

1
gir Submodule

Submodule gir added at 89daf8f600

1
gir-files Submodule

Submodule gir-files added at 1f01de0ff0

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",
]

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

@@ -0,0 +1,25 @@
[build-dependencies]
pkg-config = ">=0.3.7"
[dependencies]
bitflags = "^0.9.0"
libc = "^0.2.0"
[dependencies.gdk-pixbuf-sys]
git = "https://github.com/gtk-rs/sys"
[dependencies.glib-sys]
git = "https://github.com/gtk-rs/sys"
[dependencies.gobject-sys]
git = "https://github.com/gtk-rs/sys"
[lib]
name = "libnotify_sys"
[package]
build = "build.rs"
links = "libnotify"
name = "libnotify-sys"
version = "1.0.0"

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;
#[macro_use] 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();
}

46
src/enums.rs Normal file
View File

@@ -0,0 +1,46 @@
// 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),
}
}
}

95
src/functions.rs Normal file
View File

@@ -0,0 +1,95 @@
use ffi;
use glib::translate::*;
use glib;
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(err)` on error.
pub fn init(app_name: &str) -> Result<(), glib::error::BoolError> {
unsafe {
glib::error::BoolError::from_glib(ffi::notify_init(app_name.to_glib_none().0), "Failed to initialize libnotify")
}
}
/// 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,170 +4,49 @@
//! extern crate libnotify;
//!
//! fn main() {
//! let notify = libnotify::Context::new("hello").unwrap_or_else(|e| {
//! panic!("{}", e);
//! });
//! let body_text = Some("This is the optional body text.");
//! let n = notify.new_notification("This is the summary.",
//! body_text,
//! None).unwrap_or_else(|e| {
//! panic!("{}", e);
//! });
//! n.show().ok().expect("Failed to show notification");
//! // Init libnotify
//! libnotify::init("myapp").unwrap();
//! // Create a new notification and show it
//! let n = libnotify::Notification::new("Summary",
//! Some("Optional Body"),
//! None);
//! // Show the notification
//! n.show().unwrap();
//! // You can also use the .show() convenience method on the context
//! n.update("I am another notification", None, None).unwrap();
//! // Show the update notification
//! n.show().unwrap();
//! // We are done, deinit
//! libnotify::uninit();
//! }
//!
//! ```
extern crate libnotify_sys as sys;
extern crate glib_2_0_sys as glib;
extern crate gtypes;
#![warn(missing_docs)]
use std::ffi::CString;
use std::marker::PhantomData;
use std::fmt;
extern crate gdk_pixbuf;
#[macro_use]
extern crate glib;
extern crate glib_sys as glib_ffi;
extern crate gobject_sys as gobject_ffi;
extern crate libnotify_sys as ffi;
use gtypes::{
TRUE,
FALSE
};
/// Error that can happen on context creation
#[derive(Debug)]
pub enum ContextCreationError {
/// Context already exists
AlreadyExists,
InitFailure,
NulError
}
pub use enums::*;
pub use functions::*;
pub use notification::*;
impl fmt::Display for ContextCreationError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use ContextCreationError::*;
match *self {
AlreadyExists => write!(f, "A Libnotify context already exists."),
InitFailure => write!(f, "Failed to initialize libnotify."),
NulError => write!(f, "Argument contains a nul character.")
macro_rules! assert_initialized_libnotify {
() => {
use functions::*;
if !is_initted() {
panic!("Notify system not initialized, invalid call of function");
}
}
}
#[derive(Debug)]
pub enum NotificationCreationError {
NulError,
Unknown
}
impl fmt::Display for NotificationCreationError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use NotificationCreationError::*;
match *self {
NulError => write!(f, "Argument contains a nul character."),
Unknown => write!(f, "Unknown 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 = match CString::new(app_name) {
Ok(name) => name,
Err(_) => return Err(ContextCreationError::NulError)
};
if sys::notify_init(app_name.as_ptr()) == FALSE {
return Err(ContextCreationError::InitFailure);
}
}
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 = match CString::new(summary) {
Ok(cstr) => cstr,
Err(_) => return Err(NotificationCreationError::NulError)
};
let body = match body {
Some(body) => match CString::new(body) {
Ok(cstr) => Some(cstr),
Err(_) => return Err(NotificationCreationError::NulError)
},
None => None
};
let body_ptr = match body {
Some(body) => body.as_ptr(),
None => std::ptr::null()
};
let icon = match icon {
Some(icon) => match CString::new(icon) {
Ok(cstr) => Some(cstr),
Err(_) => return Err(NotificationCreationError::NulError)
},
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})
}
}
}
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<(), ()> {
unsafe {
let mut err: *mut glib::GError = std::ptr::null_mut();
sys::notify_notification_show(self.handle, &mut err);
if !err.is_null() {
glib::g_error_free(err);
return Err(())
}
return Ok(())
}
}
}
mod enums;
mod functions;
mod notification;

205
src/notification.rs Normal file
View File

@@ -0,0 +1,205 @@
use Urgency;
use ffi;
use gdk_pixbuf;
use glib::translate::*;
use glib;
use glib_ffi;
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
///
/// `true` on success, or `false` on error with `error` filled in
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
///
/// `true` if successful. On error, this will return `false` and set
/// `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
///
/// `true`, unless an invalid parameter was passed.
pub fn update<'a, 'b, P: Into<Option<&'a str>>, Q: Into<Option<&'b str>>>(&self, summary: &str, body: P, icon: Q) -> Result<(), glib::error::BoolError> {
let body = body.into();
let body = body.to_glib_none();
let icon = icon.into();
let icon = icon.to_glib_none();
unsafe {
glib::error::BoolError::from_glib(ffi::notify_notification_update(self.to_glib_none().0, summary.to_glib_none().0, body.0, icon.0), "Invalid parameter passed")
}
}
}