1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
//! `rustwlc` is a wrapper for [wlc][], a library for writing a window
//! manager using the [wayland][] protocol. Compositors using rustwlc will
//! not need unsafe code for basic interaction with wayland.
//!
//! # wlc
//!
//! [wlc][] is a library written in C which acts as a wayland compositor. It
//! provides abstractions over wayland via structs such as `WlcView`,
//! `WlcOutput`, `Geometry`, or `KeyboardModifiers`. It provides callbacks
//! (found in the `callback` module) for events such as `view_created`,
//! `mouse_move`, or `view_focused`.
//!
//! # Example
//!
//! For more information on how to use rustwlc, see the `callbacks` module
//! and the `run_wlc()` method.
//!
//! For a more complete example, see [the example program][] on
//! [our GitHub page][].
//!
//! ```rust
//! extern crate rustwlc;
//! use rustwlc::callback;
//! // VIEW_ACTIVATED is a bitflags enum variant, and those must be imported
//! // manually, or using a wildcatd.
//! use rustwlc::{WlcView, VIEW_ACTIVATED};
//!
//! // Callbacks must be labeled extern as they will be called from C
//! extern "C" fn view_created(view: WlcView) -> bool {
//!     view.bring_to_front();
//!     view.focus();
//!     return true;
//! }
//!
//! extern "C" fn view_focus(view: WlcView, focused: bool) {
//!     view.set_state(VIEW_ACTIVATED, focused);
//! }
//!
//! // Entry point for a compositor
//! fn compsoitor_main() {
//!     callback::view_created(view_created);
//!     callback::view_focus(view_focus);
//!
//!     // The default log handler will print wlc logs to stdout
//!     rustwlc::log_set_default_handler();
//!     let run_fn = rustwlc::init().expect("Unable to initialize!");
//!     // This will run wlc's event loop and launch wayland.
//!     run_fn();
//! }
//! # fn main() {}
//! ```
//! For a more full-featured compositor using rustwlc, see [way-cooler][].
//! [wlc]: https://github.com/Cloudef/wlc
//! [wayland]: https://wayland.freedesktop.org/
//! [the example program]: https://github.com/Immington-Industries/rust-wlc/blob/master/example/src/main.rs
//! [our GitHub page]: https://github.com/Immington-Industries/rustwlc
//! [way-cooler]: https://github.com/Immington-Industries/way-cooler

#![warn(missing_docs)]
#![allow(unused_variables)]

extern crate libc;
extern crate wayland_sys;

#[macro_use]
extern crate bitflags;

use std::ffi;

pub mod handle;
pub mod callback;
pub mod types;
pub mod input;
pub mod wayland;
pub mod xkb;
pub mod render;

pub use types::*;
pub use handle::{WlcOutput, WlcView};

/// Query backend wlc is using.
///
/// # Results
/// * None: Unknown backend type
/// * DRM: "Direct Rendering Manager" - running on tty
/// * X11: Running inside an X server
pub fn get_backend_type() -> BackendType {
    BackendType::None
}

/// Initialize wlc's callbacks and logger with a `WlcInterface`.
///
/// # Deprecated
/// wlc has deprecated this callback interface. They offer a new API with a
/// series of methods found in the `callback` module
///
/// To initialize wlc, register your callbacks with the functions described in
/// the `callbacks` module, and the logger using `log_set_handler` or
/// `log_set_default_handler`. Then call `init2()`.
///
/// # Permissions
/// If a compositor is initialized from the tty using suid or logind, it will
/// drop extra permissions after a call to `init()` or `init2()`. It is strongly
/// recommended to delay code which is not registering callbacks until after
/// this call.
///
/// # wlc Example
/// ```no_run
/// use rustwlc;
/// use rustwlc::callback;
/// use rustwlc::WlcView;
///
/// // An example callback function
/// // See the various functions in the callback module for more information
/// extern "C" fn view_focus_callback(view: WlcView, focused: bool) {
///     println!("A view came into focus!");
/// }
///
/// // Set a default log callback
/// rustwlc::log_set_default_handler();
///
/// // Register some callbacks
/// callback::view_focus(view_focus_callback);
/// // ... and additional callbacks
///
/// // The only thing your code should do before init2 is register callbacks
/// // and log handlers.
/// let run_wlc = rustwlc::init()
///     .expect("Unable to initialize wlc!");
///
/// run_wlc();
/// ```
pub fn init() -> Option<fn() -> ()> {
    Some(run_wlc)
}

/// Deprecated alias to init().
///
/// When wlc went to 0.0.1, they added an argumentless init2
/// to replace the old init that took a WlcInterface. Now,
/// init2 has been renamed init and init is removed.
pub fn init2() -> Option<fn() -> ()> {
    init()
}

/// Runs wlc's event loop.
///
/// The initialize functions will return this function in an Option.
/// Only then can it be called to being wlc's main event loop.
fn run_wlc() {
    println!("Attempted to run wlc!");
}

/// Halts execution of wlc.
pub fn terminate() {
}

/// Registers a C callback for wlc logging.
///
/// Note that `rustwlc::log_set_default_handler()` will register a simple callback
/// that will print the type and text to the console.
///
/// # Parameters
/// The `handler` callback has two parameters:
/// * `type`: The `LogType` of the message being printed.
/// * `text`: The text to be logged, currently in C form. One may call `rustwlc::pointer_to_string`
/// to convert it to a Rust String.
///
/// # Safety
/// The callback function (like other callbacks in `rustwlc`) must be marked as extern as it is called
/// from C code.
///
/// In addition, `unsafe` will be required to convert the text into a Rust String.
pub fn log_set_handler(handler: extern "C" fn(type_: LogType, text: *const libc::c_char)) {
}

/// Registers a Rust callback for wlc logging.

/// This is a nice convenience function that should be used in place of
/// `log_set_handler`. That way you can just pass a safe Rust `&str`
/// and not depend on libc`.
pub fn log_set_rust_handler(handler: fn(type_: LogType, text: &str)) {
}

#[allow(dead_code)]
fn default_log_callback(log_type: LogType, text: &str) {
    println!("wlc [{:?}] {}", log_type, text);
}

/// Sets the wlc log callback to a simple function that prints to console.
///
/// Not calling any `log_set_handler` will have no logging, use this or
/// `log_set_handler` with a callback to use wlc logging.
///
/// # Example
/// ```no_run
/// use rustwlc;
///
/// // An example where only the default log handler is registered
/// rustwlc::log_set_default_handler();
///
/// if let Some(run_wlc) = rustwlc::init2() {
///      run_wlc();
/// }
/// else {
///     panic!("Unable to initialize wlc!");
/// }
/// ```
pub fn log_set_default_handler() {
}

/// Unsafe strings conversion function.
///
/// Converts a `*const libc::c_char` to an owned `String`.
/// Useful for log callbacks.
///
/// # Example
/// Standard usage may be for the log callbacks.
/// ```rust
/// extern "C" fn default_log_callback(log_type: LogType, text: *const libc::c_char) {
///     let string = unsafe { pointer_to_string(text) };
///     println!("wlc [{:?}]: {}", log_type, string);
/// }
/// ```
pub unsafe fn pointer_to_string(pointer: *const libc::c_char) -> String {
    if pointer.is_null() {
        return "".to_string();
    }
    let slice = ffi::CStr::from_ptr(pointer);
    slice.to_string_lossy().into_owned()
}