45 Commits

Author SHA1 Message Date
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
Mika Attila
d23eabffea Version bump 2015-09-19 09:42:31 +02:00
Mika Attila
ffd99b67e2 Depend on gtypes 2015-09-19 09:42:17 +02:00
Mika Attila
72df2c0adb Version bump 2015-03-27 08:34:00 +01:00
Mika Attila
dac1075025 Update to new crate naming rules 2015-03-25 19:04:43 +01:00
Mika Attila
d3ad5323fb Update doc example 2015-03-10 19:18:44 +01:00
Mika Attila
445f0b6d13 Implement std::fmt::Display for the error types 2015-03-10 19:14:18 +01:00
Mika Attila
a0955acabd Add example to the documentation 2015-03-10 08:46:54 +01:00
5 changed files with 356 additions and 56 deletions

21
.travis.yml Normal file
View File

@@ -0,0 +1,21 @@
language: rust
rust:
- nightly
- beta
- stable
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: IjahTjjwmuvig/wTDMwxpk1F3Ywi2d0r17+JmOXHPdbfSfhi4puiTzsOgMjBhFtosTwcvlBeFwwFeTtl9KFNG165xm9Fqbhcez9sx+hS+EWZR/MBPFhKorJlgva0nuH8L1cxDUP+mDkcV/BdXCDeT7ml+y/FqEDAI4N0lwEsVMk=
- secure: B8QPcNgwOmbJ8dNJn/p/tE1cLeUOLTo/Oj7nOBkK1tatMgS6yfQFa5pyNEqeTyZAyNptssqSH1BpRC3RxTJ/b+kFzdy8Kq1nkJfp9R9zTY34w5gWukfmmTH4Qe2lyWY/DKL1lGVjb+8mroV9sPaS5Y4DqYHbeYtpWF8Gi27vIL4=

View File

@@ -1,8 +1,8 @@
[package]
name = "libnotify"
version = "0.0.2"
authors = ["Mika Attila <radiantstatue@gmail.com>"]
version = "0.5.0"
authors = ["Mika Attila <radiantstatue@gmail.com>", "Julian Ospald <hasufell@posteo.de>"]
license = "MIT"
description = "Rust bindings to libnotify"
readme = "README.md"
@@ -11,5 +11,9 @@ documentation = "http://crumblingstatue.github.io/doc/libnotify/libnotify/"
keywords = ["libnotify", "notification"]
[dependencies]
libnotify-sys = "*"
glib-2_0-sys = "*"
libnotify-sys = "^0.5.0"
gdk-pixbuf = "^0.1.3"
gdk-pixbuf-sys = "^0.3.4"
glib-sys = "^0.3.4"
gtypes = "^0.2.0"
glib = "^0.1.3"

View File

@@ -1,2 +1,4 @@
[![Build Status](https://travis-ci.org/crumblingstatue/rust-libnotify.svg)](https://travis-ci.org/crumblingstatue/rust-libnotify)
# libnotify-rs
Rust binding to libnotify

View File

@@ -1,9 +1,12 @@
extern crate libnotify;
fn main() {
let notify = libnotify::Context::new("hello").unwrap();
let n = notify.new_notification("This is the summary.",
Some("This is the optional body text."),
None).unwrap();
// Create a libnotify context
let notify = libnotify::Context::new("myapp").unwrap();
// Create a new notification and show it
let n = notify.new_notification("Summary", Some("Optional Body"), None)
.unwrap();
n.show().unwrap();
// You can also use the .show() convenience method on the context
notify.show("I am another notification", None, None).unwrap();
}

View File

@@ -1,29 +1,136 @@
extern crate "libnotify-sys" as sys;
extern crate "glib-2_0-sys" as glib;
//! Rustic bindings to [libnotify](https://developer.gnome.org/libnotify/)
//!
//! ```rust
//! extern crate libnotify;
//!
//! fn main() {
//! // Create a libnotify context
//! let notify = libnotify::Context::new("myapp").unwrap();
//! // Create a new notification and show it
//! let n = notify.new_notification("Summary",
//! Some("Optional Body"),
//! None).unwrap();
//! n.show().unwrap();
//! // You can also use the .show() convenience method on the context
//! notify.show("I am another notification", None, None).unwrap();
//! }
//!
//! ```
use std::ffi::CString;
#![warn(missing_docs)]
extern crate gdk_pixbuf;
extern crate gdk_pixbuf_sys;
extern crate glib;
extern crate glib_sys;
extern crate gtypes;
extern crate libnotify_sys as sys;
use gdk_pixbuf_sys::GdkPixbuf;
use glib::translate::*;
use gtypes::{TRUE, FALSE};
use std::error::Error;
use std::ffi::{self, CStr, CString};
use std::fmt;
use std::marker::PhantomData;
use std::os::raw::c_int;
/// The urgency level of the notification.
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,
}
impl From<sys::NotifyUrgency> for Urgency {
fn from(urgency: sys::NotifyUrgency) -> Urgency {
match urgency {
sys::NotifyUrgency::NotifyUrgencyLow => Urgency::Low,
sys::NotifyUrgency::NotifyUrgencyNormal => Urgency::Normal,
sys::NotifyUrgency::NotifyUrgencyCritical => Urgency::Critical,
}
}
}
impl From<Urgency> for sys::NotifyUrgency {
fn from(urgency: Urgency) -> sys::NotifyUrgency {
match urgency {
Urgency::Low => sys::NotifyUrgency::NotifyUrgencyLow,
Urgency::Normal => sys::NotifyUrgency::NotifyUrgencyNormal,
Urgency::Critical => sys::NotifyUrgency::NotifyUrgencyCritical,
}
}
}
use glib::types::{
TRUE,
FALSE
};
/// Error that can happen on context creation
#[derive(Debug)]
pub enum ContextCreationError {
/// Context already exists
/// Context already exists.
AlreadyExists,
InitFailure,
NulError
/// Failed to initialize libnotify.
InitError,
/// A nul byte was found in the provided string.
NulError(ffi::NulError),
}
#[derive(Debug)]
pub enum NotificationCreationError {
NulError,
Unknown
impl fmt::Display for ContextCreationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use ContextCreationError::*;
match *self {
AlreadyExists => write!(f, "A Libnotify context already exists."),
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)]
/// An error that can happen when attempting to create a notification.
pub enum NotificationCreationError {
/// A nul byte was found in the provided string.
NulError(ffi::NulError),
/// An unknown error happened.
Unknown,
/// Invalid parameter passed to a glib function
InvalidParameter,
}
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"),
InvalidParameter => write!(f, "An invalid parameter was passed"),
}
}
}
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.
@@ -40,16 +147,14 @@ impl Context {
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)
};
let app_name = try!(CString::new(app_name));
if sys::notify_init(app_name.as_ptr()) == FALSE {
return Err(ContextCreationError::InitFailure);
return Err(ContextCreationError::InitError);
}
}
Ok(Context)
}
/// Creates a new Notification.
///
/// Arguments:
@@ -57,36 +162,30 @@ impl Context {
/// - 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)
};
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) => match CString::new(body) {
Ok(cstr) => Some(cstr),
Err(_) => return Err(NotificationCreationError::NulError)
},
None => None
Some(body) => Some(try!(CString::new(body))),
None => None,
};
let body_ptr = match body {
Some(body) => body.as_ptr(),
None => std::ptr::null()
Some(ref 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
Some(icon) => Some(try!(CString::new(icon))),
None => None,
};
let icon_ptr = match icon {
Some(icon) => icon.as_ptr(),
None => std::ptr::null()
Some(ref icon) => icon.as_ptr(),
None => std::ptr::null(),
};
unsafe {
let n = sys::notify_notification_new(summary.as_ptr(),
body_ptr,
@@ -95,9 +194,26 @@ impl Context {
return Err(NotificationCreationError::Unknown);
}
Ok(Notification{handle: n, _phantom: PhantomData})
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 {
@@ -108,24 +224,178 @@ impl Drop for Context {
}
}
/// A passive pop-up notification
pub struct Notification<'a> {
handle: *mut sys::NotifyNotification,
_phantom: PhantomData<&'a Context>
_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<(), ()> {
pub fn show(&'a self) -> Result<(), NotificationShowError> {
unsafe {
let mut err: *mut glib::GError = std::ptr::null_mut();
let mut err: *mut glib_sys::GError = std::ptr::null_mut();
sys::notify_notification_show(self.handle, &mut err);
if !err.is_null() {
glib::g_error_free(err);
return Err(())
let result = Err(NotificationShowError {
message: CStr::from_ptr((*err).message)
.to_string_lossy()
.into_owned(),
});
glib_sys::g_error_free(err);
return result;
}
return Ok(())
Ok(())
}
}
/// Set the notification timeout. Note that the server might ignore
/// the timeout.
pub fn set_notification_timeout(&self, timeout: i32) {
let _timeout: c_int = From::from(timeout);
unsafe { sys::notify_notification_set_timeout(self.handle, _timeout) }
}
/// 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 `.show()`.
pub fn update(&self,
summary: &str,
body: Option<&str>,
icon: Option<&str>)
-> Result<(), 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(ref 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(ref icon) => icon.as_ptr(),
None => std::ptr::null(),
};
unsafe {
let b = sys::notify_notification_update(self.handle,
summary.as_ptr(),
body_ptr,
icon_ptr);
if b == FALSE {
return Err(NotificationCreationError::InvalidParameter);
}
}
return Ok(());
}
/// Sets a hint for `key` with value `value`. If value is `None`,
/// then key is unset.
pub fn set_hint(&self,
key: &str,
value: Option<glib::variant::Variant>)
-> Result<(), NotificationCreationError> {
let key = try!(CString::new(key));
let gvalue: *mut glib_sys::GVariant = {
match value {
Some(ref value) => value.to_glib_none().0,
None => std::ptr::null_mut(),
}
};
unsafe {
sys::notify_notification_set_hint(self.handle, key.as_ptr(), gvalue)
}
return Ok(());
}
/// Sets the category of this notification. This can be used by the
/// notification server to filter or display the data in a certain way.
pub fn set_category(&self, category: &str) -> Result<(), NotificationCreationError> {
let category = try!(CString::new(category));
unsafe {
sys::notify_notification_set_category(self.handle,
category.as_ptr());
}
return Ok(());
}
/// Sets the urgency level of this notification.
pub fn set_urgency(&self, urgency: Urgency) {
let urgency: sys::NotifyUrgency = From::from(urgency);
unsafe {
sys::notify_notification_set_urgency(self.handle,
urgency);
}
}
/// Sets the image in the notification from a Pixbuf.
pub fn set_image_from_pixbuf(&self, pixbuf: &gdk_pixbuf::Pixbuf) {
let pixbuf: *mut GdkPixbuf = pixbuf.to_glib_none().0;
unsafe {
sys::notify_notification_set_image_from_pixbuf(self.handle,
pixbuf);
}
}
/// Clears all hints from the notification.
pub fn clear_hints(&self) {
unsafe {
sys::notify_notification_clear_hints(self.handle);
}
}
/// Synchronously tells the notification server to hide the
/// notification on the screen.
pub fn close(&self) -> Result<(), NotificationShowError> {
unsafe {
let mut err: *mut glib_sys::GError = std::ptr::null_mut();
sys::notify_notification_close(self.handle,
&mut err);
if !err.is_null() {
let result = Err(NotificationShowError {
message: CStr::from_ptr((*err).message)
.to_string_lossy()
.into_owned(),
});
glib_sys::g_error_free(err);
return result;
}
}
return 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"
}
}