use super::{DisplayReference, DroppableObject, FlutterbugError};
use std::{
fmt,
ptr::NonNull,
sync::{Arc, Weak},
};
use x11::xlib::{self, _XIC, _XIM};
pub struct InputMethod {
inner: NonNull<_XIM>,
}
impl fmt::Debug for InputMethod {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "X11 Input Method")
}
}
impl InputMethod {
#[inline]
pub(crate) fn from_raw(_dpy: DisplayReference, inner: NonNull<_XIM>) -> Self {
Self { inner }
}
#[inline]
pub unsafe fn raw(&self) -> NonNull<_XIM> {
self.inner
}
}
impl Drop for InputMethod {
fn drop(&mut self) {
unsafe { xlib::XCloseIM(self.inner.as_mut()) };
}
}
pub struct InputContext {
inner: Arc<NonNull<_XIC>>,
dpy: DisplayReference,
win: xlib::Window,
}
impl fmt::Debug for InputContext {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "X11 Input Context for window {}", self.win)
}
}
impl Drop for InputContext {
fn drop(&mut self) {
unsafe { xlib::XDestroyIC(self.inner.as_ptr()) };
}
}
impl InputContext {
#[inline]
pub(crate) fn from_raw(
dpy: DisplayReference,
inner: Arc<NonNull<_XIC>>,
win: xlib::Window,
) -> Self {
Self { dpy, inner, win }
}
}
pub struct InputContextReference {
inner: Weak<NonNull<_XIC>>,
dpy: DisplayReference,
win: xlib::Window,
}
impl fmt::Debug for InputContextReference {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "X11 Input Context Reference for window {}", self.win)
}
}
impl Clone for InputContextReference {
fn clone(&self) -> InputContextReference {
Self::from_raw(self.dpy.clone(), self.inner.clone(), self.win)
}
}
impl InputContextReference {
#[inline]
pub(crate) fn from_raw(
dpy: DisplayReference,
inner: Weak<NonNull<_XIC>>,
win: xlib::Window,
) -> Self {
Self { dpy, inner, win }
}
}
pub trait GenericInputContext: fmt::Debug {
fn raw(&self) -> Result<NonNull<_XIC>, FlutterbugError>;
fn reference(&self) -> InputContextReference;
fn set_focus(&self) -> Result<(), FlutterbugError> {
unsafe { xlib::XSetICFocus(self.raw()?.as_mut()) };
Ok(())
}
}
impl GenericInputContext for InputContext {
#[inline]
fn raw(&self) -> Result<NonNull<_XIC>, FlutterbugError> {
Ok(*self.inner)
}
#[inline]
fn reference(&self) -> InputContextReference {
InputContextReference::from_raw(self.dpy.clone(), Arc::downgrade(&self.inner), self.win)
}
}
impl GenericInputContext for InputContextReference {
#[inline]
fn raw(&self) -> Result<NonNull<_XIC>, FlutterbugError> {
Ok(*self
.inner
.upgrade()
.ok_or_else(|| FlutterbugError::PointerWasDropped(DroppableObject::IC))?)
}
#[inline]
fn reference(&self) -> InputContextReference {
self.clone()
}
}