use crate::graphics::GraphicsSettings;
use super::{
window_width,
window_height,
window_center,
mouse_cursor,
WindowEvent,
KeyboardButton,
InnerWindowEvent,
Window,
WindowBase,
PagedWindow,
DynamicWindow,
WindowSettings,
GeneralSettings,
};
use glium::backend::glutin::DisplayCreationError;
use glium::glutin::{
ContextBuilder,
NotCurrent,
monitor::MonitorHandle,
event_loop::{ControlFlow,EventLoop},
event::{
Event,
WindowEvent as GWindowEvent,
ElementState,
},
window::WindowBuilder,
platform::desktop::EventLoopExtDesktop,
};
use std::collections::VecDeque;
pub struct DefaultWindow{
pub (crate) base:WindowBase,
pub (crate) events:VecDeque<WindowEvent>,
#[cfg(feature="auto_hide")]
pub (crate) events_handler:fn(&mut Self),
}
use WindowEvent::*;
impl DefaultWindow{
pub fn new<F>(setting:F)->Result<DefaultWindow,DisplayCreationError>
where F:FnOnce(Vec<MonitorHandle>,&mut WindowSettings){
Window::new::<F>(setting)
}
pub fn next_event(&mut self)->Option<WindowEvent>{
while self.events.is_empty(){
#[cfg(feature="auto_hide")]
(self.events_handler)(self);
#[cfg(not(feature="auto_hide"))]
self.event_listener(); }
self.events.pop_front()
}
pub fn into_paged_window(self)->PagedWindow{
#[cfg(feature="auto_hide")]
let minimized=if self.events_handler
as *const fn(&mut DefaultWindow)
==
DefaultWindow::event_listener
as *const fn(&mut DefaultWindow)
{
true
}
else{
false
};
PagedWindow{
base:self.base,
#[cfg(feature="auto_hide")]
minimized,
}
}
pub fn into_dynamic_window<'a,O:PartialEq>(self)->DynamicWindow<'a,O>{
DynamicWindow{
base:self.base,
page_ref:std::ptr::null_mut(),
last_page:None,
}
}
}
impl DefaultWindow{
pub (crate) fn event_listener(&mut self){
let el=&mut self.base.event_loop as *mut EventLoop<InnerWindowEvent>;
let event_loop=unsafe{&mut *el};
event_loop.run_return(|event,_,control_flow|{
#[cfg(not(feature="lazy"))]
self.base.update_check();
*control_flow=ControlFlow::Exit;
let next_event=match event{
Event::UserEvent(event)=>match event{
#[cfg(not(feature="lazy"))]
InnerWindowEvent::Update=>{
self.base.next_update+=self.base.update_interval;
WindowEvent::Update
}
_=>return
}
Event::WindowEvent{event,..}=>match event{
GWindowEvent::CloseRequested=>CloseRequested,
GWindowEvent::Resized(size)=>window_resized!(size,self),
GWindowEvent::Moved(pos)=>Moved([pos.x,pos.y]),
GWindowEvent::CursorMoved{position,..}=>cursor_moved!(position),
GWindowEvent::MouseWheel{delta,..}=>MouseWheelScroll(delta),
GWindowEvent::MouseInput{button,state,..}=>mouse_input!(button,state,self),
GWindowEvent::KeyboardInput{input,..}=>keyboard_input!(input),
GWindowEvent::ReceivedCharacter(character)
if !character.is_ascii_control()=>CharacterInput(character),
#[cfg(feature="auto_hide")]
GWindowEvent::Focused(f) if !f=>self.lost_focus(),
#[cfg(not(feature="auto_hide"))]
GWindowEvent::Focused(f)=>Focused(f),
GWindowEvent::ModifiersChanged(modifier)=>ModifiersChanged(modifier),
#[cfg(feature="file_drop")]
GWindowEvent::DroppedFile(path)=>DroppedFile(path),
#[cfg(feature="file_drop")]
GWindowEvent::HoveredFile(path)=>HoveredFile(path),
#[cfg(feature="file_drop")]
GWindowEvent::HoveredFileCancelled=>HoveredFileCancelled,
_=>return }
Event::Suspended=>Suspended,
Event::Resumed=>Resumed,
Event::MainEventsCleared=>{
self.base.display.gl_window().window().request_redraw();
return
}
Event::RedrawRequested(_)=>{
#[cfg(feature="fps_counter")]
self.base.count_fps();
RedrawRequested
}
_=>return };
self.events.push_back(next_event)
});
}
#[cfg(feature="auto_hide")]
pub (crate) fn wait_until_focused(&mut self){
let el=&mut self.base.event_loop as *mut EventLoop<InnerWindowEvent>;
let event_loop=unsafe{&mut *el};
event_loop.run_return(|event,_,control_flow|{
*control_flow=ControlFlow::Wait;
let event=match event{
Event::WindowEvent{event,..}=>{
match event{
GWindowEvent::CloseRequested=>{ *control_flow=ControlFlow::Exit;
CloseRequested
}
GWindowEvent::Resized(size)=>{
*control_flow=ControlFlow::Exit;
window_resized!(size,self)
}
GWindowEvent::Focused(_)=>{
*control_flow=ControlFlow::Exit;
self.gained_focus()
}
_=>return
}
}
Event::Suspended=>{
*control_flow=ControlFlow::Exit;
Suspended
}
Event::Resumed=>{
*control_flow=ControlFlow::Exit;
Resumed
}
_=>return
};
self.events.push_back(event);
})
}
}
impl DefaultWindow{
#[cfg(feature="auto_hide")]
fn lost_focus(&mut self)->WindowEvent{
self.base.display.gl_window().window().set_minimized(true); self.events_handler=DefaultWindow::wait_until_focused;
Focused(false)
}
#[cfg(feature="auto_hide")]
fn gained_focus(&mut self)->WindowEvent{
self.events_handler=DefaultWindow::event_listener;
self.base.display.gl_window().window().set_minimized(false);
Focused(true)
}
}
impl Window for DefaultWindow{
fn window_base(&self)->&WindowBase{
&self.base
}
fn window_base_mut(&mut self)->&mut WindowBase{
&mut self.base
}
fn raw(
window_builder:WindowBuilder,
context_builder:ContextBuilder<NotCurrent>,
graphics_settings:GraphicsSettings,
event_loop:EventLoop<InnerWindowEvent>,
general_settings:GeneralSettings,
)->Result<DefaultWindow,DisplayCreationError>{
let base=WindowBase::raw(window_builder,
context_builder,
graphics_settings,
event_loop,
general_settings,
);
match base{
Ok(w)=>Ok(Self{
base:w,
events:VecDeque::with_capacity(32),
#[cfg(feature="auto_hide")]
events_handler:DefaultWindow::event_listener,
}),
Err(e)=>Err(e)
}
}
}