├── .gitignore ├── .gitmodules ├── .travis.yml ├── Cargo.toml ├── Gir.toml ├── LICENSE ├── Makefile ├── README.md ├── examples └── show.rs ├── gir-libnotify.toml ├── libnotify-sys ├── Cargo.toml ├── LICENSE ├── README.md ├── build.rs └── src │ └── lib.rs └── src ├── enums.rs ├── functions.rs ├── lib.rs └── notification.rs /.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target/ 3 | .cargo/ 4 | docs.md 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "gir"] 2 | path = gir 3 | url = https://github.com/gtk-rs/gir.git 4 | [submodule "gir-files"] 5 | path = gir-files 6 | url = https://github.com/hasufell/gir-files.git 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: false 3 | language: rust 4 | rust: 5 | - nightly 6 | - beta 7 | - stable 8 | addons: 9 | apt: 10 | packages: 11 | - libgdk-pixbuf2.0-common 12 | - libgdk-pixbuf2.0-dev 13 | - libglib2.0-data 14 | - libglib2.0-dev 15 | - libnotify-dev 16 | before_script: 17 | - | 18 | pip install 'travis-cargo<0.2' --user && 19 | export PATH=$HOME/.local/bin:$PATH 20 | script: 21 | - | 22 | travis-cargo build && 23 | # travis-cargo test && 24 | travis-cargo --only stable doc 25 | after_success: 26 | - travis-cargo --only stable doc-upload 27 | env: 28 | global: 29 | - TRAVIS_CARGO_NIGHTLY_FEATURE="" 30 | - secure: B9+n+ikrYqSxK1SYOHIvjtYi58IvdVC0HYJxyDiJnzIcEtos/aDiGbMZU1pIvC+qIAibdltIqzZ1afVC1msfsxeaov2e4VPKfTJV0gwLLq6tzuuaOeujtM9YUUWrdr8QQXk3LEPIl8HD5jm6VTLcl2TqPeiiyn96rk67nA5jeS8= 31 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = [ 3 | "Mika Attila ", 4 | "Julian Ospald ", 5 | ] 6 | description = "Rust bindings to libnotify" 7 | documentation = "https://hasufell.github.io/rust-libnotify/libnotify/" 8 | keywords = [ 9 | "libnotify", 10 | "notification", 11 | ] 12 | license = "MIT" 13 | name = "libnotify" 14 | readme = "README.md" 15 | repository = "https://github.com/hasufell/rust-libnotify" 16 | version = "1.0.2" 17 | 18 | [dependencies] 19 | gdk-pixbuf = "^0.2.0" 20 | gdk-pixbuf-sys = "^0.4.0" 21 | glib = "^0.3.1" 22 | glib-sys = "^0.4.0" 23 | gobject-sys = "^0.4.0" 24 | libnotify-sys = "^1.0.1" 25 | -------------------------------------------------------------------------------- /Gir.toml: -------------------------------------------------------------------------------- 1 | [options] 2 | girs_dir = "gir-files" 3 | library = "Notify" 4 | version = "0.7" 5 | min_cfg_version = "0.7.7" 6 | target_path = "." 7 | work_mode = "normal" 8 | generate_safety_asserts = true 9 | deprecate_by_min_version = true 10 | 11 | generate = [ 12 | "Notify.Urgency", 13 | ] 14 | 15 | 16 | 17 | [[object]] 18 | name = "Notify.Notification" 19 | status = "generate" 20 | [[object.function]] 21 | name = "get_closed_reason" 22 | ignore = true 23 | [[object.function]] 24 | name = "add_action" 25 | ignore = true 26 | [[object.function]] 27 | name = "clear_actions" 28 | ignore = true 29 | [[object.function]] 30 | name = "close" 31 | # manual 32 | ignore = true 33 | [[object.function]] 34 | name = "set_hint" 35 | # manual 36 | ignore = true 37 | [[object.function]] 38 | name = "set_icon_from_pixbuf" 39 | # deprecated 40 | ignore = true 41 | [[object.function]] 42 | name = "set_image_from_pixbuf" 43 | # manual 44 | ignore = true 45 | [[object.function]] 46 | name = "show" 47 | # manual 48 | ignore = true 49 | [[object.function]] 50 | name = "update" 51 | [object.function.return] 52 | bool_return_is_error = "Invalid parameter passed" 53 | [[object.function]] 54 | name = "set_app_name" 55 | [[object.function.parameter]] 56 | name = "app_name" 57 | nullable = true 58 | 59 | [[object]] 60 | name = "Notify.*" 61 | status = "generate" 62 | [[object.function]] 63 | name = "is_initted" 64 | # manual assert_initialized_main_thread 65 | ignore = true 66 | [[object.function]] 67 | name = "init" 68 | # manual assert_initialized_main_thread 69 | ignore = true 70 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Mika Attila 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GIR = gir/target/bin/gir 2 | GIR_SRC = gir/Cargo.toml gir/Cargo.lock gir/build.rs $(shell find gir/src -name '*.rs') 3 | GIR_FILES = gir-files/Notify-0.7.gir 4 | 5 | # Run `gir` generating the bindings 6 | gir : src/auto/mod.rs 7 | 8 | src/auto/mod.rs : Gir.toml $(GIR) $(GIR_FILES) 9 | $(GIR) -c Gir.toml 10 | $(GIR) -m doc -c Gir.toml 11 | rustdoc-stripper -g -o docs.md 12 | 13 | $(GIR) : $(GIR_SRC) 14 | rm -f gir/target/bin/gir 15 | cargo install --path gir --root gir/target 16 | rm -f gir/target/.crates.toml 17 | 18 | $(GIR_SRC) $(GIR_FILES) : 19 | git submodule update --init 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Latest Version](https://img.shields.io/crates/v/libnotify.svg)](https://crates.io/crates/libnotify) 2 | [![License](https://img.shields.io/github/license/hasufell/rust-libnotify.svg)](LICENSE) 3 | [![Crate download count](https://img.shields.io/crates/d/libnotify.svg)](https://crates.io/crates/libnotify) 4 | 5 | [![Documentation (crates.io)](https://img.shields.io/badge/documentation-docs.rs-df3600.svg)](https://docs.rs/libnotify) 6 | [![Documentation (master)](https://img.shields.io/badge/documentation-master-yellow.svg)](https://hasufell.github.io/rust-libnotify/) 7 | 8 | [![Build Status](https://travis-ci.org/hasufell/rust-libnotify.svg)](https://travis-ci.org/hasufell/rust-libnotify) 9 | [![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) 10 | 11 | # rust-libnotify 12 | Rust binding to libnotify. 13 | -------------------------------------------------------------------------------- /examples/show.rs: -------------------------------------------------------------------------------- 1 | extern crate libnotify; 2 | 3 | fn main() { 4 | // Init libnotify 5 | libnotify::init("myapp"); 6 | // Create a new notification (doesn't show it yet) 7 | let n = 8 | libnotify::Notification::new("Summary", Some("Optional Body"), None); 9 | // Show the notification 10 | n.show().unwrap(); 11 | // Update the existent notification 12 | n.update("I am another notification", None, None).unwrap(); 13 | // Show the updated notification 14 | n.show().unwrap(); 15 | // We are done, deinit 16 | libnotify::uninit(); 17 | } 18 | -------------------------------------------------------------------------------- /gir-libnotify.toml: -------------------------------------------------------------------------------- 1 | [options] 2 | work_mode = "sys" 3 | library = "Notify" 4 | version = "0.7" 5 | min_cfg_version = "0.7.6" 6 | external_libraries = [ 7 | "GLib", 8 | "GObject", 9 | "GdkPixbuf", 10 | ] 11 | 12 | -------------------------------------------------------------------------------- /libnotify-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = [ 3 | "Mika Attila ", 4 | "Julian Ospald ", 5 | ] 6 | build = "build.rs" 7 | description = "FFI bindings to libnotify" 8 | keywords = [ 9 | "libnotify", 10 | "notification", 11 | ] 12 | license = "MIT" 13 | links = "libnotify" 14 | name = "libnotify-sys" 15 | readme = "README.md" 16 | repository = "https://github.com/hasufell/rust-libnotify" 17 | version = "1.0.1" 18 | 19 | [build-dependencies] 20 | pkg-config = ">=0.3.9" 21 | 22 | [dependencies] 23 | bitflags = "^0.9.1" 24 | gdk-pixbuf-sys = "^0.4.0" 25 | glib-sys = "^0.4.0" 26 | gobject-sys = "^0.4.0" 27 | libc = "^0.2.30" 28 | 29 | [lib] 30 | name = "libnotify_sys" 31 | -------------------------------------------------------------------------------- /libnotify-sys/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Mika Attila 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /libnotify-sys/README.md: -------------------------------------------------------------------------------- 1 | [![Latest Version](https://img.shields.io/crates/v/libnotify-sys.svg)](https://crates.io/crates/libnotify-sys) 2 | [![License](https://img.shields.io/github/license/hasufell/rust-libnotify.svg)](LICENSE) 3 | [![Crate download count](https://img.shields.io/crates/d/libnotify-sys.svg)](https://crates.io/crates/libnotify-sys) 4 | 5 | # rust-libnotify-sys 6 | 7 | Rust FFI declarations for libnotify 8 | -------------------------------------------------------------------------------- /libnotify-sys/build.rs: -------------------------------------------------------------------------------- 1 | extern crate pkg_config; 2 | 3 | use pkg_config::{Config, Error}; 4 | use std::env; 5 | use std::io::prelude::*; 6 | use std::io; 7 | use std::process; 8 | 9 | fn main() { 10 | if let Err(s) = find() { 11 | let _ = writeln!(io::stderr(), "{}", s); 12 | process::exit(1); 13 | } 14 | } 15 | 16 | fn find() -> Result<(), Error> { 17 | let package_name = "libnotify"; 18 | let shared_libs = ["notify"]; 19 | let version = { 20 | "0.7.6" 21 | }; 22 | 23 | if let Ok(lib_dir) = env::var("GTK_LIB_DIR") { 24 | for lib_ in shared_libs.iter() { 25 | println!("cargo:rustc-link-lib=dylib={}", lib_); 26 | } 27 | println!("cargo:rustc-link-search=native={}", lib_dir); 28 | return Ok(()) 29 | } 30 | 31 | let target = env::var("TARGET").expect("TARGET environment variable doesn't exist"); 32 | let hardcode_shared_libs = target.contains("windows"); 33 | 34 | let mut config = Config::new(); 35 | config.atleast_version(version); 36 | if hardcode_shared_libs { 37 | config.cargo_metadata(false); 38 | } 39 | match config.probe(package_name) { 40 | Ok(library) => { 41 | if hardcode_shared_libs { 42 | for lib_ in shared_libs.iter() { 43 | println!("cargo:rustc-link-lib=dylib={}", lib_); 44 | } 45 | for path in library.link_paths.iter() { 46 | println!("cargo:rustc-link-search=native={}", 47 | path.to_str().expect("library path doesn't exist")); 48 | } 49 | } 50 | Ok(()) 51 | } 52 | Err(Error::EnvNoPkgConfig(_)) | Err(Error::Command { .. }) => { 53 | for lib_ in shared_libs.iter() { 54 | println!("cargo:rustc-link-lib=dylib={}", lib_); 55 | } 56 | Ok(()) 57 | } 58 | Err(err) => Err(err), 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /libnotify-sys/src/lib.rs: -------------------------------------------------------------------------------- 1 | // This file was generated by gir (89daf8f) from gir-files (1f01de0) 2 | // DO NOT EDIT 3 | 4 | #![allow(non_camel_case_types, non_upper_case_globals)] 5 | 6 | extern crate libc; 7 | extern crate bitflags; 8 | extern crate glib_sys as glib; 9 | extern crate gobject_sys as gobject; 10 | extern crate gdk_pixbuf_sys as gdk_pixbuf; 11 | 12 | #[allow(unused_imports)] 13 | use libc::{c_int, c_char, c_uchar, c_float, c_uint, c_double, 14 | c_short, c_ushort, c_long, c_ulong, 15 | c_void, size_t, ssize_t, intptr_t, uintptr_t, time_t, FILE}; 16 | 17 | #[allow(unused_imports)] 18 | use glib::{gboolean, gconstpointer, gpointer, GType, Volatile}; 19 | 20 | // Enums 21 | #[derive(Clone, Copy, Debug, Eq, PartialEq)] 22 | #[repr(C)] 23 | pub enum NotifyUrgency { 24 | Low = 0, 25 | Normal = 1, 26 | Critical = 2, 27 | } 28 | pub const NOTIFY_URGENCY_LOW: NotifyUrgency = NotifyUrgency::Low; 29 | pub const NOTIFY_URGENCY_NORMAL: NotifyUrgency = NotifyUrgency::Normal; 30 | pub const NOTIFY_URGENCY_CRITICAL: NotifyUrgency = NotifyUrgency::Critical; 31 | 32 | // Constants 33 | pub const NOTIFY_EXPIRES_DEFAULT: c_int = -1; 34 | pub const NOTIFY_EXPIRES_NEVER: c_int = 0; 35 | pub const NOTIFY_VERSION_MAJOR: c_int = 0; 36 | pub const NOTIFY_VERSION_MICRO: c_int = 7; 37 | pub const NOTIFY_VERSION_MINOR: c_int = 7; 38 | 39 | // Callbacks 40 | pub type NotifyActionCallback = Option; 41 | 42 | // Records 43 | #[repr(C)] 44 | pub struct NotifyNotificationClass { 45 | pub parent_class: gobject::GObjectClass, 46 | pub closed: Option, 47 | } 48 | 49 | #[repr(C)] 50 | pub struct NotifyNotificationPrivate(c_void); 51 | 52 | // Classes 53 | #[repr(C)] 54 | pub struct NotifyNotification { 55 | pub parent_object: gobject::GObject, 56 | pub priv_: *mut NotifyNotificationPrivate, 57 | } 58 | 59 | extern "C" { 60 | 61 | //========================================================================= 62 | // NotifyNotification 63 | //========================================================================= 64 | pub fn notify_notification_get_type() -> GType; 65 | pub fn notify_notification_new(summary: *const c_char, body: *const c_char, icon: *const c_char) -> *mut NotifyNotification; 66 | //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`]); 67 | pub fn notify_notification_clear_actions(notification: *mut NotifyNotification); 68 | pub fn notify_notification_clear_hints(notification: *mut NotifyNotification); 69 | pub fn notify_notification_close(notification: *mut NotifyNotification, error: *mut *mut glib::GError) -> gboolean; 70 | pub fn notify_notification_get_closed_reason(notification: *const NotifyNotification) -> c_int; 71 | pub fn notify_notification_set_app_name(notification: *mut NotifyNotification, app_name: *const c_char); 72 | pub fn notify_notification_set_category(notification: *mut NotifyNotification, category: *const c_char); 73 | pub fn notify_notification_set_hint(notification: *mut NotifyNotification, key: *const c_char, value: *mut glib::GVariant); 74 | pub fn notify_notification_set_hint_byte(notification: *mut NotifyNotification, key: *const c_char, value: c_uchar); 75 | pub fn notify_notification_set_hint_byte_array(notification: *mut NotifyNotification, key: *const c_char, value: *mut u8, len: size_t); 76 | pub fn notify_notification_set_hint_double(notification: *mut NotifyNotification, key: *const c_char, value: c_double); 77 | pub fn notify_notification_set_hint_int32(notification: *mut NotifyNotification, key: *const c_char, value: c_int); 78 | pub fn notify_notification_set_hint_string(notification: *mut NotifyNotification, key: *const c_char, value: *const c_char); 79 | pub fn notify_notification_set_hint_uint32(notification: *mut NotifyNotification, key: *const c_char, value: c_uint); 80 | pub fn notify_notification_set_icon_from_pixbuf(notification: *mut NotifyNotification, icon: *mut gdk_pixbuf::GdkPixbuf); 81 | pub fn notify_notification_set_image_from_pixbuf(notification: *mut NotifyNotification, pixbuf: *mut gdk_pixbuf::GdkPixbuf); 82 | pub fn notify_notification_set_timeout(notification: *mut NotifyNotification, timeout: c_int); 83 | pub fn notify_notification_set_urgency(notification: *mut NotifyNotification, urgency: NotifyUrgency); 84 | pub fn notify_notification_show(notification: *mut NotifyNotification, error: *mut *mut glib::GError) -> gboolean; 85 | pub fn notify_notification_update(notification: *mut NotifyNotification, summary: *const c_char, body: *const c_char, icon: *const c_char) -> gboolean; 86 | 87 | //========================================================================= 88 | // Other functions 89 | //========================================================================= 90 | pub fn notify_get_app_name() -> *const c_char; 91 | pub fn notify_get_server_caps() -> *mut glib::GList; 92 | 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; 93 | pub fn notify_init(app_name: *const c_char) -> gboolean; 94 | pub fn notify_is_initted() -> gboolean; 95 | pub fn notify_set_app_name(app_name: *const c_char); 96 | pub fn notify_uninit(); 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/enums.rs: -------------------------------------------------------------------------------- 1 | // This file was generated by gir (89daf8f) from gir-files (1f01de0) 2 | // DO NOT EDIT 3 | 4 | use ffi; 5 | use glib::translate::*; 6 | use std; 7 | 8 | /// The urgency level of the notification. 9 | #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] 10 | pub enum Urgency { 11 | /// Low urgency. Used for unimportant notifications. 12 | Low, 13 | /// Normal urgency. Used for most standard notifications. 14 | Normal, 15 | /// Critical urgency. Used for very important notifications. 16 | Critical, 17 | #[doc(hidden)] 18 | __Unknown(i32), 19 | } 20 | 21 | #[doc(hidden)] 22 | impl ToGlib for Urgency { 23 | type GlibType = ffi::NotifyUrgency; 24 | 25 | fn to_glib(&self) -> ffi::NotifyUrgency { 26 | match *self { 27 | Urgency::Low => ffi::NOTIFY_URGENCY_LOW, 28 | Urgency::Normal => ffi::NOTIFY_URGENCY_NORMAL, 29 | Urgency::Critical => ffi::NOTIFY_URGENCY_CRITICAL, 30 | Urgency::__Unknown(value) => unsafe { std::mem::transmute(value) }, 31 | } 32 | } 33 | } 34 | 35 | #[doc(hidden)] 36 | impl FromGlib for Urgency { 37 | fn from_glib(value: ffi::NotifyUrgency) -> Self { 38 | match value as i32 { 39 | 0 => Urgency::Low, 40 | 1 => Urgency::Normal, 41 | 2 => Urgency::Critical, 42 | value => Urgency::__Unknown(value), 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/functions.rs: -------------------------------------------------------------------------------- 1 | use ffi; 2 | use glib::translate::*; 3 | use glib_ffi; 4 | use std::ptr; 5 | 6 | 7 | 8 | /// Gets whether or not libnotify is initialized. 9 | /// 10 | /// # Returns 11 | /// 12 | /// `true` if libnotify is initialized, or `false` otherwise. 13 | pub fn is_initted() -> bool { 14 | unsafe { from_glib(ffi::notify_is_initted()) } 15 | } 16 | 17 | /// Initialized libnotify. This must be called before any other functions. 18 | /// 19 | /// # Returns 20 | /// 21 | /// `Ok(())` if successful, `Err(str)` on error. 22 | // TODO: switch back to BoolError when it hits stable glib 23 | pub fn init(app_name: &str) -> Result<(), String> { 24 | unsafe { 25 | let b = ffi::notify_init(app_name.to_glib_none().0); 26 | 27 | match b { 28 | glib_ffi::GFALSE => Err( 29 | String::from("Failed to initialize libnotify"), 30 | ), 31 | _ => Ok(()), 32 | } 33 | } 34 | } 35 | 36 | /// Gets the application name registered. 37 | /// 38 | /// # Returns 39 | /// 40 | /// The registered application name, passed to `init()`. 41 | pub fn get_app_name() -> Option { 42 | assert_initialized_libnotify!(); 43 | unsafe { from_glib_none(ffi::notify_get_app_name()) } 44 | } 45 | 46 | /// Synchronously queries the server for its capabilities and returns them as 47 | /// a Vector. 48 | /// 49 | /// # Returns 50 | /// 51 | /// A Vector of server capability Strings. 52 | pub fn get_server_caps() -> Vec { 53 | assert_initialized_libnotify!(); 54 | unsafe { 55 | FromGlibPtrContainer::from_glib_full(ffi::notify_get_server_caps()) 56 | } 57 | } 58 | 59 | /// Synchronously queries the server for its information, specifically, 60 | /// the name, vendor, server version, and the version of the notifications 61 | /// specification that it is compliant with. 62 | /// 63 | /// # Returns 64 | /// 65 | /// `Some(ret_name, ret_vendor, ret_version, ret_spec_version)` on 66 | /// success, otherwise `None` on error. 67 | pub fn get_server_info() -> Option<(String, String, String, String)> { 68 | assert_initialized_libnotify!(); 69 | unsafe { 70 | let mut ret_name = ptr::null_mut(); 71 | let mut ret_vendor = ptr::null_mut(); 72 | let mut ret_version = ptr::null_mut(); 73 | let mut ret_spec_version = ptr::null_mut(); 74 | let ret = from_glib(ffi::notify_get_server_info( 75 | &mut ret_name, 76 | &mut ret_vendor, 77 | &mut ret_version, 78 | &mut ret_spec_version, 79 | )); 80 | if ret { 81 | Some(( 82 | from_glib_full(ret_name), 83 | from_glib_full(ret_vendor), 84 | from_glib_full(ret_version), 85 | from_glib_full(ret_spec_version), 86 | )) 87 | } else { 88 | None 89 | } 90 | } 91 | } 92 | 93 | /// Sets the application name. 94 | /// ## `app_name` 95 | /// The name of the application. 96 | pub fn set_app_name(app_name: &str) { 97 | assert_initialized_libnotify!(); 98 | unsafe { 99 | ffi::notify_set_app_name(app_name.to_glib_none().0); 100 | } 101 | } 102 | 103 | /// Uninitialized libnotify. 104 | /// 105 | /// This should be called when the program no longer needs libnotify for 106 | /// the rest of its lifecycle, typically just before exitting. 107 | pub fn uninit() { 108 | assert_initialized_libnotify!(); 109 | unsafe { 110 | ffi::notify_uninit(); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Rustic bindings to [libnotify](https://developer.gnome.org/libnotify/) 2 | //! 3 | //! ```rust 4 | //! extern crate libnotify; 5 | //! 6 | //! fn main() { 7 | //! // Init libnotify 8 | //! libnotify::init("myapp").unwrap(); 9 | //! // Create a new notification (doesn't show it yet) 10 | //! let n = libnotify::Notification::new("Summary", 11 | //! Some("Optional Body"), 12 | //! None); 13 | //! // Show the notification 14 | //! n.show().unwrap(); 15 | //! // Update the existent notification 16 | //! n.update("I am another notification", None, None).unwrap(); 17 | //! // Show the updated notification 18 | //! n.show().unwrap(); 19 | //! // We are done, deinit 20 | //! libnotify::uninit(); 21 | //! } 22 | //! 23 | //! ``` 24 | 25 | #![warn(missing_docs)] 26 | 27 | extern crate gdk_pixbuf; 28 | #[macro_use] 29 | extern crate glib; 30 | extern crate glib_sys as glib_ffi; 31 | extern crate gobject_sys as gobject_ffi; 32 | extern crate libnotify_sys as ffi; 33 | 34 | 35 | pub use enums::*; 36 | pub use functions::*; 37 | pub use notification::*; 38 | 39 | 40 | macro_rules! assert_initialized_libnotify { 41 | () => { 42 | use functions::*; 43 | if !is_initted() { 44 | panic!("Notify system not initialized, invalid call of function"); 45 | } 46 | } 47 | } 48 | 49 | 50 | mod enums; 51 | mod functions; 52 | mod notification; 53 | -------------------------------------------------------------------------------- /src/notification.rs: -------------------------------------------------------------------------------- 1 | use Urgency; 2 | use ffi; 3 | use gdk_pixbuf; 4 | use glib::translate::*; 5 | use glib; 6 | use glib_ffi; 7 | use gobject_ffi; 8 | use std::mem; 9 | use std::ptr; 10 | use std; 11 | 12 | 13 | glib_wrapper! { 14 | /// `Notification` represents a passive pop-up notification. It can contain 15 | /// summary text, body text, and an icon, as well as hints specifying how 16 | /// the notification should be presented. The notification is rendered by 17 | /// a notification daemon, and may present the notification in any number 18 | /// of ways. As such, there is a clear separation of content and 19 | /// presentation, and this API enforces that. 20 | pub struct Notification(Object); 21 | 22 | match fn { 23 | get_type => || ffi::notify_notification_get_type(), 24 | } 25 | } 26 | 27 | 28 | 29 | impl Notification { 30 | /// Creates a new `Notification`. The summary text is required, but 31 | /// all other parameters are optional. 32 | /// ## `summary` 33 | /// The required summary text. 34 | /// ## `body` 35 | /// The optional body text. 36 | /// ## `icon` 37 | /// The optional icon theme icon name or filename. 38 | /// 39 | /// # Returns 40 | /// 41 | /// The new `Notification`. 42 | pub fn new<'a, 'b, P: Into>, Q: Into>>( 43 | summary: &str, 44 | body: P, 45 | icon: Q, 46 | ) -> Notification { 47 | assert_initialized_libnotify!(); 48 | let body = body.into(); 49 | let body = body.to_glib_none(); 50 | let icon = icon.into(); 51 | let icon = icon.to_glib_none(); 52 | unsafe { 53 | from_glib_full(ffi::notify_notification_new( 54 | summary.to_glib_none().0, 55 | body.0, 56 | icon.0, 57 | )) 58 | } 59 | } 60 | 61 | /// Synchronously tells the notification server to hide the notification on the screen. 62 | /// 63 | /// # Returns 64 | /// 65 | /// `Ok(())` on success, or `Err(err)` on error 66 | pub fn close(&self) -> Result<(), glib::error::Error> { 67 | assert_initialized_libnotify!(); 68 | unsafe { 69 | let mut err: *mut glib_ffi::GError = std::ptr::null_mut(); 70 | ffi::notify_notification_close(self.to_glib_none().0, &mut err); 71 | 72 | if !err.is_null() { 73 | return Err(glib::error::Error::wrap(err)); 74 | } else { 75 | return Ok(()); 76 | } 77 | } 78 | } 79 | 80 | /// Tells the notification server to display the notification on the screen. 81 | /// 82 | /// # Returns 83 | /// 84 | /// `Ok(())` on success, or `Err(err)` on error 85 | // TODO: test if Error leaks memory 86 | pub fn show(&self) -> Result<(), glib::error::Error> { 87 | assert_initialized_libnotify!(); 88 | unsafe { 89 | let mut err: *mut glib_ffi::GError = std::ptr::null_mut(); 90 | ffi::notify_notification_show(self.to_glib_none().0, &mut err); 91 | 92 | if !err.is_null() { 93 | return Err(glib::error::Error::wrap(err)); 94 | } else { 95 | return Ok(()); 96 | } 97 | } 98 | } 99 | 100 | /// Sets a hint for `key` with value `value`. If `value` is `None`, 101 | /// a previously set hint for `key` is unset. 102 | /// 103 | /// If `value` is floating, it is consumed. 104 | /// ## `key` 105 | /// the hint key 106 | /// ## `value` 107 | pub fn set_hint(&self, key: &str, value: Option) { 108 | assert_initialized_libnotify!(); 109 | 110 | let gvalue: *mut glib_ffi::GVariant = { 111 | match value { 112 | Some(ref value) => value.to_glib_none().0, 113 | None => std::ptr::null_mut(), 114 | } 115 | }; 116 | 117 | unsafe { 118 | ffi::notify_notification_set_hint( 119 | self.to_glib_none().0, 120 | key.to_glib_none().0, 121 | gvalue, 122 | ) 123 | } 124 | } 125 | 126 | /// Sets the image in the notification from a `gdk_pixbuf::Pixbuf`. 127 | /// ## `pixbuf` 128 | /// The image. 129 | pub fn set_image_from_pixbuf(&self, pixbuf: &gdk_pixbuf::Pixbuf) { 130 | assert_initialized_libnotify!(); 131 | 132 | unsafe { 133 | ffi::notify_notification_set_image_from_pixbuf( 134 | self.to_glib_none().0, 135 | pixbuf.to_glib_none().0, 136 | ); 137 | } 138 | } 139 | 140 | /// Clears all hints from the notification. 141 | pub fn clear_hints(&self) { 142 | unsafe { 143 | ffi::notify_notification_clear_hints(self.to_glib_none().0); 144 | } 145 | } 146 | 147 | /// Sets the application name for the notification. If this function is 148 | /// not called or if `app_name` is `None`, the application name will be 149 | /// set from the value used in `notify_init` or overridden with 150 | /// `notify_set_app_name`. 151 | /// ## `app_name` 152 | /// the localised application name 153 | pub fn set_app_name<'a, P: Into>>(&self, app_name: P) { 154 | let app_name = app_name.into(); 155 | let app_name = app_name.to_glib_none(); 156 | unsafe { 157 | ffi::notify_notification_set_app_name( 158 | self.to_glib_none().0, 159 | app_name.0, 160 | ); 161 | } 162 | } 163 | 164 | /// Sets the category of this notification. This can be used by the 165 | /// notification server to filter or display the data in a certain way. 166 | /// ## `category` 167 | /// The category. 168 | pub fn set_category(&self, category: &str) { 169 | unsafe { 170 | ffi::notify_notification_set_category( 171 | self.to_glib_none().0, 172 | category.to_glib_none().0, 173 | ); 174 | } 175 | } 176 | 177 | /// Sets the timeout of the notification. To set the default time, pass 178 | /// `NOTIFY_EXPIRES_DEFAULT` as `timeout`. To set the notification to never 179 | /// expire, pass `NOTIFY_EXPIRES_NEVER`. 180 | /// 181 | /// Note that the timeout may be ignored by the server. 182 | /// ## `timeout` 183 | /// The timeout in milliseconds. 184 | pub fn set_timeout(&self, timeout: i32) { 185 | unsafe { 186 | ffi::notify_notification_set_timeout( 187 | self.to_glib_none().0, 188 | timeout, 189 | ); 190 | } 191 | } 192 | 193 | /// Sets the urgency level of this notification. 194 | /// 195 | /// See: `Urgency` 196 | /// ## `urgency` 197 | /// The urgency level. 198 | pub fn set_urgency(&self, urgency: Urgency) { 199 | unsafe { 200 | ffi::notify_notification_set_urgency( 201 | self.to_glib_none().0, 202 | urgency.to_glib(), 203 | ); 204 | } 205 | } 206 | 207 | /// Updates the notification text and icon. This won't send the update out 208 | /// and display it on the screen. For that, you will need to call 209 | /// `Notification::show`. 210 | /// ## `summary` 211 | /// The new required summary text. 212 | /// ## `body` 213 | /// The optional body text. 214 | /// ## `icon` 215 | /// The optional icon theme icon name or filename. 216 | /// 217 | /// # Returns 218 | /// 219 | /// `Ok(())` on success, or `Err(str)` if an invalid parameter was passed 220 | // TODO: switch back to BoolError when it hits stable glib 221 | pub fn update< 222 | 'a, 223 | 'b, 224 | P: Into>, 225 | Q: Into>, 226 | >( 227 | &self, 228 | summary: &str, 229 | body: P, 230 | icon: Q, 231 | ) -> Result<(), String> { 232 | let body = body.into(); 233 | let body = body.to_glib_none(); 234 | let icon = icon.into(); 235 | let icon = icon.to_glib_none(); 236 | unsafe { 237 | let b = ffi::notify_notification_update( 238 | self.to_glib_none().0, 239 | summary.to_glib_none().0, 240 | body.0, 241 | icon.0, 242 | ); 243 | match b { 244 | glib_ffi::GFALSE => Err( 245 | String::from("Invalid parameter passed"), 246 | ), 247 | _ => Ok(()), 248 | } 249 | } 250 | } 251 | } 252 | --------------------------------------------------------------------------------