Switch to gir

This commit is contained in:
Julian Ospald 2017-07-10 23:21:16 +02:00 committed by Ospald, Julian
parent 965a64aa55
commit 13850652a7
17 changed files with 663 additions and 378 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

View File

@ -10,7 +10,7 @@ before_script:
script:
- |
travis-cargo build &&
travis-cargo test &&
# travis-cargo test &&
travis-cargo --only stable doc
after_success:
- travis-cargo --only stable doc-upload

View File

@ -1,7 +1,6 @@
[package]
name = "libnotify"
version = "0.5.0"
version = "1.0.0"
authors = ["Mika Attila <radiantstatue@gmail.com>", "Julian Ospald <hasufell@posteo.de>"]
license = "MIT"
description = "Rust bindings to libnotify"
@ -11,10 +10,10 @@ documentation = "http://crumblingstatue.github.io/doc/libnotify/libnotify/"
keywords = ["libnotify", "notification"]
[dependencies]
error-chain = "0.10.0"
libnotify-sys = "^0.5.0"
gdk-pixbuf = "^0.1.3"
gdk-pixbuf-sys = "^0.3.4"
glib-sys = "^0.3.4"
gobject-sys = "^0.3.4"
glib = "^0.1.3"
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

@ -2,11 +2,10 @@ extern crate libnotify;
fn main() {
// Init libnotify
libnotify::init("myapp").unwrap();
libnotify::init("myapp");
// Create a new notification and show it
let n =
libnotify::Notification::new("Summary", Some("Optional Body"), None)
.unwrap();
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

1
gir Submodule

@ -0,0 +1 @@
Subproject commit 89daf8f60096fb80b7a1eff67feb0bf1bf165ec4

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

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),
}
}
}

View File

@ -1,33 +0,0 @@
use std;
/// Error variants for Libnotify.
error_chain! {
foreign_links {
Utf8(std::str::Utf8Error);
Nul(std::ffi::NulError);
}
errors {
UnknownError {
description("Unknown Error")
display("Unknown Error")
}
InvalidParameter {
description("Invalid parameter")
display("Invalid parameter")
}
NotificationShowError(t: String) {
description("Failed to show notification")
display("Failed to show notification: {}", t)
}
NotifyAlreadyInitialized {
description("Notify system already initialized")
display("Notify system already initialized")
}
NotifyInitError {
description("Notify system initialization error")
display("Notify system initialization error")
}
}
}

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

@ -9,7 +9,7 @@
//! // Create a new notification and show it
//! let n = libnotify::Notification::new("Summary",
//! Some("Optional Body"),
//! None).unwrap();
//! None);
//! // Show the notification
//! n.show().unwrap();
//! // You can also use the .show() convenience method on the context
@ -24,27 +24,22 @@
#![warn(missing_docs)]
#[macro_use]
extern crate error_chain;
extern crate gobject_sys;
extern crate gdk_pixbuf;
extern crate gdk_pixbuf_sys;
#[macro_use]
extern crate glib;
extern crate glib_sys;
extern crate libnotify_sys as sys;
pub mod errors;
use errors::*;
use gdk_pixbuf_sys::GdkPixbuf;
use glib::translate::ToGlibPtr;
use std::ffi::{CStr, CString};
use std::os::raw::c_int;
use std::os::raw::c_char;
extern crate glib_sys as glib_ffi;
extern crate gobject_sys as gobject_ffi;
extern crate libnotify_sys as ffi;
macro_rules! init_panic {
pub use enums::*;
pub use functions::*;
pub use notification::*;
macro_rules! assert_initialized_libnotify {
() => {
use functions::*;
if !is_initted() {
panic!("Notify system not initialized, invalid call of function");
}
@ -52,318 +47,6 @@ macro_rules! init_panic {
}
/// 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,
}
}
}
/// A passive pop-up notification
pub struct Notification {
handle: *mut sys::NotifyNotification,
}
impl Drop for Notification {
fn drop(&mut self) {
unsafe {
if gobject_sys::g_type_check_instance_is_a(
self.handle as *mut gobject_sys::GTypeInstance,
gobject_sys::G_TYPE_OBJECT,
) == glib_sys::GFALSE
{
panic!("Not a GObject!");
}
let gobject = self.handle as
*mut gobject_sys::GObject;
gobject_sys::g_object_unref(gobject);
}
}
}
impl Notification {
/// Creates a new Notification.
///
/// Arguments:
///
/// - summary: Required summary text
/// - body: Optional body text
/// - icon: Optional icon theme icon name or filename
pub fn new(summary: &str,
body: Option<&str>,
icon: Option<&str>)
-> Result<Notification> {
init_panic!();
let summary = CString::new(summary)?;
let body = match body {
Some(body) => Some(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(CString::new(icon)?),
None => None,
};
let icon_ptr = match icon {
Some(ref 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() {
bail!(ErrorKind::UnknownError);
}
Ok(Notification { handle: n })
}
}
/// Tells the notification server to display the notification
/// on the screen.
pub fn show(&self) -> Result<()> {
init_panic!();
unsafe {
let mut err: *mut glib_sys::GError = std::ptr::null_mut();
sys::notify_notification_show(self.handle, &mut err);
if !err.is_null() {
let msg = CStr::from_ptr((*err).message)
.to_string_lossy()
.into_owned();
glib_sys::g_error_free(err);
bail!(ErrorKind::NotificationShowError(msg));
}
Ok(())
}
}
/// Set the notification timeout. Note that the server might ignore
/// the timeout.
pub fn set_notification_timeout(&self, timeout: i32) {
init_panic!();
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<()> {
init_panic!();
let summary = CString::new(summary)?;
let body = match body {
Some(body) => Some(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(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 == glib_sys::GFALSE {
bail!(ErrorKind::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<()> {
init_panic!();
let key = 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<()> {
init_panic!();
let category = 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) {
init_panic!();
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) {
init_panic!();
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) {
init_panic!();
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<()> {
init_panic!();
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 msg = CStr::from_ptr((*err).message)
.to_string_lossy()
.into_owned();
glib_sys::g_error_free(err);
bail!(ErrorKind::NotificationShowError(msg));
}
}
return Ok(());
}
}
/// Initialized libnotify. This must be called before any other functions.
pub fn init(app_name: &str) -> Result<()> {
let app_name = CString::new(app_name)?;
unsafe {
if sys::notify_is_initted() == glib_sys::GTRUE {
bail!(ErrorKind::NotifyAlreadyInitialized);
}
let app_name = CString::new(app_name)?;
if sys::notify_init(app_name.as_ptr()) == glib_sys::GFALSE {
bail!(ErrorKind::NotifyInitError);
}
}
return Ok(());
}
/// 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() {
init_panic!();
unsafe {
sys::notify_uninit();
}
}
/// Gets whether or not libnotify is initialized.
pub fn is_initted() -> bool {
unsafe {
if sys::notify_is_initted() == glib_sys::GTRUE {
return true;
} else {
return false;
}
}
}
/// Sets the application name.
pub fn set_app_name(app_name: &str) -> Result<()> {
init_panic!();
let app_name = CString::new(app_name)?;
unsafe {
sys::notify_set_app_name(app_name.as_ptr());
}
return Ok(());
}
/// Gets the application name registered.
pub fn get_app_name() -> Result<String> {
init_panic!();
unsafe {
let c_name: *const c_char = sys::notify_get_app_name();
let c_str = CStr::from_ptr(c_name);
let string = c_str.to_str()?;
return Ok(String::from(string));
}
}
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")
}
}
}