use ::{_API};
use capi::scdef::{GFX_LAYER};
use capi::scdom::HELEMENT;
use capi::sctypes::{HWINDOW, POINT, UINT, BOOL, RECT, LPCBYTE, LPVOID, INT};
use capi::scmsg::*;
pub use capi::scmsg::key_codes;
pub use capi::scbehavior::{MOUSE_BUTTONS, MOUSE_EVENTS, KEYBOARD_STATES, KEY_EVENTS};
#[derive(Debug)]
pub enum Message {
Create {
backend: GFX_LAYER,
transparent: bool,
},
Destroy,
Size {
width: u32,
height: u32,
},
Resolution {
ppi: u32,
},
Focus {
enter: bool,
},
Heartbit {
milliseconds: u32,
},
Redraw,
Paint(PaintLayer),
RenderTo(RenderEvent),
Mouse(MouseEvent),
Keyboard(KeyboardEvent),
}
#[derive(Debug)]
pub struct MouseEvent {
pub event: MOUSE_EVENTS,
pub button: MOUSE_BUTTONS,
pub modifiers: KEYBOARD_STATES,
pub pos: POINT,
}
#[derive(Debug)]
pub struct KeyboardEvent {
pub event: KEY_EVENTS,
pub code: UINT,
pub modifiers: KEYBOARD_STATES,
}
#[derive(Debug)]
pub struct PaintLayer {
pub element: HELEMENT,
pub is_foreground: bool,
}
pub struct RenderEvent
{
pub layer: Option<PaintLayer>,
pub callback: Box<dyn Fn(&RECT, &[u8])>,
}
impl std::fmt::Debug for RenderEvent {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt
.debug_struct("RenderEvent")
.field("layer", &self.layer)
.field("callback", &"Box<dyn Fn>")
.finish()
}
}
pub fn handle_message(wnd: HWINDOW, event: Message) -> bool
{
let ok = match event {
Message::Create { backend, transparent } => {
let msg = SCITER_X_MSG_CREATE {
header: SCITER_X_MSG_CODE::SXM_CREATE.into(),
backend,
transparent: transparent as BOOL,
};
(_API.SciterProcX)(wnd, &msg.header as *const _)
},
Message::Destroy => {
let msg = SCITER_X_MSG_DESTROY {
header: SCITER_X_MSG_CODE::SXM_DESTROY.into(),
};
(_API.SciterProcX)(wnd, &msg.header as *const _)
},
Message::Size { width, height} => {
let msg = SCITER_X_MSG_SIZE {
header: SCITER_X_MSG_CODE::SXM_SIZE.into(),
width,
height,
};
(_API.SciterProcX)(wnd, &msg.header as *const _)
},
Message::Resolution { ppi } => {
let msg = SCITER_X_MSG_RESOLUTION {
header: SCITER_X_MSG_CODE::SXM_RESOLUTION.into(),
ppi,
};
(_API.SciterProcX)(wnd, &msg.header as *const _)
},
Message::Focus { enter } => {
let msg = SCITER_X_MSG_FOCUS {
header: SCITER_X_MSG_CODE::SXM_FOCUS.into(),
enter: enter as BOOL,
};
(_API.SciterProcX)(wnd, &msg.header as *const _)
},
Message::Heartbit { milliseconds } => {
let msg = SCITER_X_MSG_HEARTBIT {
header: SCITER_X_MSG_CODE::SXM_HEARTBIT.into(),
time: milliseconds,
};
(_API.SciterProcX)(wnd, &msg.header as *const _)
},
Message::Mouse(params) => {
let msg = SCITER_X_MSG_MOUSE {
header: SCITER_X_MSG_CODE::SXM_MOUSE.into(),
event: params.event,
button: params.button,
modifiers: params.modifiers as u32,
pos: params.pos,
};
(_API.SciterProcX)(wnd, &msg.header as *const _)
},
Message::Keyboard(params) => {
let msg = SCITER_X_MSG_KEY {
header: SCITER_X_MSG_CODE::SXM_KEY.into(),
event: params.event,
code: params.code,
modifiers: params.modifiers as u32,
};
(_API.SciterProcX)(wnd, &msg.header as *const _)
},
Message::Redraw => {
use std::ptr;
let msg = SCITER_X_MSG_PAINT {
header: SCITER_X_MSG_CODE::SXM_PAINT.into(),
element: ptr::null_mut(),
isFore: true as BOOL,
targetType: SCITER_PAINT_TARGET_TYPE::SPT_DEFAULT,
param: ptr::null_mut(),
callback: None,
};
(_API.SciterProcX)(wnd, &msg.header as *const _)
},
Message::Paint(paint) => {
use std::ptr;
let msg = SCITER_X_MSG_PAINT {
header: SCITER_X_MSG_CODE::SXM_PAINT.into(),
element: paint.element,
isFore: paint.is_foreground as BOOL,
targetType: SCITER_PAINT_TARGET_TYPE::SPT_DEFAULT,
param: ptr::null_mut(),
callback: None,
};
(_API.SciterProcX)(wnd, &msg.header as *const _)
},
Message::RenderTo(paint) => {
struct Callback {
callback: Box<dyn Fn(&RECT, &[u8])>,
}
extern "system" fn inner(rgba: LPCBYTE, x: INT, y: INT, width: UINT, height: UINT, param: LPVOID)
{
assert!(!param.is_null());
assert!(!rgba.is_null());
if param.is_null() || rgba.is_null() { return; }
let bitmap_area = RECT {
left: x,
top: y,
right: x + width as INT,
bottom: y + height as INT,
};
let bitmap_size = width * height * 4;
let bitmap_data = unsafe { std::slice::from_raw_parts(rgba, bitmap_size as usize) };
let param = param as *const Callback;
let wrapper = unsafe { &*param };
(wrapper.callback)(&bitmap_area, bitmap_data);
}
let wrapper = Callback {
callback: paint.callback,
};
let param = &wrapper as *const _ as LPVOID;
let element = paint.layer.unwrap_or(PaintLayer {
element: std::ptr::null_mut(),
is_foreground: false,
});
let msg = SCITER_X_MSG_PAINT {
header: SCITER_X_MSG_CODE::SXM_PAINT.into(),
element: element.element,
isFore: element.is_foreground as BOOL,
targetType: SCITER_PAINT_TARGET_TYPE::SPT_RECEIVER,
param: param,
callback: Some(inner),
};
(_API.SciterProcX)(wnd, &msg.header as *const _)
},
};
ok != 0
}