File: xrecord.rs

package info (click to toggle)
rust-x11 2.18.1-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 528 kB
  • sloc: makefile: 2
file content (127 lines) | stat: -rw-r--r-- 3,267 bytes parent folder | download | duplicates (8)
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
// Example for X Record Extension

#![cfg_attr(not(feature = "xlib"), allow(dead_code))]
#![cfg_attr(not(feature = "xlib"), allow(unused_imports))]

extern crate libc;
extern crate x11;

use std::ffi::CString;
use std::ptr::{
  null,
  null_mut,
};

use std::os::raw::{
    c_int
};
use x11::xlib;
use x11::xrecord;

static mut EVENT_COUNT:u32 = 0;

#[cfg(not(all(feature = "xlib", feature = "xrecord")))]
fn main () {
    panic!("this example requires `--features 'xlib xrecord'`");
}

#[cfg(all(feature = "xlib", feature = "xrecord"))]
fn main () {
    unsafe {
        // Open displays
        let dpy_control = xlib::XOpenDisplay(null());
        let dpy_data = xlib::XOpenDisplay(null());
        if dpy_control == null_mut() || dpy_data == null_mut() {
            panic!("can't open display");
        }
        // Enable synchronization
        xlib::XSynchronize(dpy_control, 1);

        let extension_name = CString::new("RECORD").unwrap();

        let extension = xlib::XInitExtension(
            dpy_control,
            extension_name.as_ptr());
        if extension.is_null() {
            panic!("Error init X Record Extension");
        }

        // Get version
        let mut version_major: c_int = 0;
        let mut version_minor: c_int = 0;
        xrecord::XRecordQueryVersion(
            dpy_control,
            &mut version_major,
            &mut version_minor
        );
        println!(
            "RECORD extension version {}.{}",
            version_major,
            version_minor
        );

        // Prepare record range
        let mut record_range: xrecord::XRecordRange = *xrecord::XRecordAllocRange();
        record_range.device_events.first = xlib::KeyPress as u8;
        record_range.device_events.last = xlib::MotionNotify as u8;

        // Create context
        let context = xrecord::XRecordCreateContext(
            dpy_control,
            0,
            &mut xrecord::XRecordAllClients,
            1,
            std::mem::transmute(&mut &mut record_range),
            1
        );

        if context == 0 {
            panic!("Fail create Record context\n");
        }

        // Run
        let result = xrecord::XRecordEnableContext(
            dpy_data,
            context,
            Some(record_callback),
            &mut 0
        );
        if result == 0 {
            panic!("Cound not enable the Record context!\n");
        }
    }
}

unsafe extern "C" fn record_callback(_:*mut i8, raw_data: *mut xrecord::XRecordInterceptData) {
    EVENT_COUNT += 1;
    let data = &*raw_data;

    // Skip server events
    if data.category != xrecord::XRecordFromServer {
        return;
    }

    // Cast binary data
    let xdatum = &*(data.data as *mut XRecordDatum);

    let event_type = match xdatum.xtype  as i32 {
        xlib::KeyPress      => "KeyPress",
        xlib::KeyRelease    => "KeyRelease",
        xlib::ButtonPress   => "ButtonPress",
        xlib::ButtonRelease => "ButtonRelease",
        xlib::MotionNotify  => "MotionNotify",
        _                   => "Other"
    };

    println!("Event recieve\t{:?}\tevent.", event_type);

    xrecord::XRecordFreeData(raw_data);
}

#[repr(C)]
struct XRecordDatum {
    xtype: u8,
    code: u8,
    unknown1: u8,
    unknown2: u8
}