diff --git a/strafe-client/src/app.rs b/strafe-client/src/app.rs
new file mode 100644
index 000000000..23d28e40e
--- /dev/null
+++ b/strafe-client/src/app.rs
@@ -0,0 +1,68 @@
+use crate::window::Instruction;
+use strafesnet_common::integer;
+use strafesnet_common::instruction::TimedInstruction;
+use strafesnet_common::session::TimeInner as SessionTimeInner;
+
+pub struct App<'a>{
+	root_time:std::time::Instant,
+	window_thread:crate::compat_worker::QNWorker<'a,TimedInstruction<Instruction,SessionTimeInner>>,
+}
+impl<'a> App<'a>{
+	pub fn new(
+		root_time:std::time::Instant,
+		window_thread:crate::compat_worker::QNWorker<'a,TimedInstruction<Instruction,SessionTimeInner>>,
+	)->App<'a>{
+		Self{
+			root_time,
+			window_thread,
+		}
+	}
+	fn send_timed_instruction(&mut self,instruction:Instruction){
+		let time=integer::Time::from_nanos(self.root_time.elapsed().as_nanos() as i64);
+		self.window_thread.send(TimedInstruction{time,instruction}).unwrap();
+	}
+}
+impl winit::application::ApplicationHandler for App<'_>{
+	fn resumed(&mut self,_event_loop:&winit::event_loop::ActiveEventLoop){
+		//
+	}
+
+	fn window_event(
+		&mut self,
+		event_loop:&winit::event_loop::ActiveEventLoop,
+		_window_id:winit::window::WindowId,
+		event:winit::event::WindowEvent,
+	){
+		match event{
+			winit::event::WindowEvent::KeyboardInput{
+				event:winit::event::KeyEvent{
+					logical_key:winit::keyboard::Key::Named(winit::keyboard::NamedKey::Escape),
+					state:winit::event::ElementState::Pressed,
+					..
+				},
+				..
+			}
+			|winit::event::WindowEvent::CloseRequested=>{
+				event_loop.exit();
+			},
+			_=>(),
+		}
+		self.send_timed_instruction(Instruction::WindowEvent(event));
+	}
+
+	fn device_event(
+		&mut self,
+		_event_loop:&winit::event_loop::ActiveEventLoop,
+		_device_id:winit::event::DeviceId,
+		event:winit::event::DeviceEvent,
+	){
+		self.send_timed_instruction(Instruction::DeviceEvent(event));
+	}
+
+	fn about_to_wait(
+		&mut self,
+		_event_loop:&winit::event_loop::ActiveEventLoop
+	){
+		self.send_timed_instruction(Instruction::WindowEvent(winit::event::WindowEvent::RedrawRequested));
+	}
+}
diff --git a/strafe-client/src/main.rs b/strafe-client/src/main.rs
index 65beb0f05..20fb19e49 100644
--- a/strafe-client/src/main.rs
+++ b/strafe-client/src/main.rs
@@ -1,3 +1,4 @@
+mod app;
 mod file;
 mod setup;
 mod window;
diff --git a/strafe-client/src/setup.rs b/strafe-client/src/setup.rs
index e54f41b02..f9ef207ce 100644
--- a/strafe-client/src/setup.rs
+++ b/strafe-client/src/setup.rs
@@ -1,8 +1,3 @@
-use crate::window::Instruction;
-use strafesnet_common::instruction::TimedInstruction;
-use strafesnet_common::integer;
-use strafesnet_common::session::TimeInner as SessionTimeInner;
-
 fn optional_features()->wgpu::Features{
 	wgpu::Features::TEXTURE_COMPRESSION_ASTC
 	|wgpu::Features::TEXTURE_COMPRESSION_ETC2
@@ -213,73 +208,16 @@ pub fn setup_and_start(title:&str){
 	);
 
 	for arg in std::env::args().skip(1){
-		let path=std::path::PathBuf::from(arg);
-		window_thread.send(TimedInstruction{
-			time:integer::Time::ZERO,
-			instruction:Instruction::WindowEvent(winit::event::WindowEvent::DroppedFile(path)),
+		window_thread.send(strafesnet_common::instruction::TimedInstruction{
+			time:strafesnet_common::integer::Time::ZERO,
+			instruction:crate::window::Instruction::WindowEvent(winit::event::WindowEvent::DroppedFile(arg.into())),
 		}).unwrap();
 	};
 
 	println!("Entering event loop...");
-	let root_time=std::time::Instant::now();
-	run_event_loop(event_loop,window_thread,root_time).unwrap();
-}
-
-fn run_event_loop(
-	event_loop:winit::event_loop::EventLoop<()>,
-	mut window_thread:crate::compat_worker::QNWorker<TimedInstruction<Instruction,SessionTimeInner>>,
-	root_time:std::time::Instant
-	)->Result<(),winit::error::EventLoopError>{
-		event_loop.run(move |event,elwt|{
-			let time=integer::Time::from_nanos(root_time.elapsed().as_nanos() as i64);
-			// *control_flow=if cfg!(feature="metal-auto-capture"){
-			// 	winit::event_loop::ControlFlow::Exit
-			// }else{
-			// 	winit::event_loop::ControlFlow::Poll
-			// };
-			match event{
-				winit::event::Event::AboutToWait=>{
-					window_thread.send(TimedInstruction{time,instruction:Instruction::RequestRedraw}).unwrap();
-				}
-				winit::event::Event::WindowEvent {
-					event:
-						// WindowEvent::Resized(size)
-						// | WindowEvent::ScaleFactorChanged {
-						// 	new_inner_size: &mut size,
-						// 	..
-						// },
-						winit::event::WindowEvent::Resized(size),//ignoring scale factor changed for now because mutex bruh
-					window_id:_,
-				} => {
-					window_thread.send(TimedInstruction{time,instruction:Instruction::Resize(size)}).unwrap();
-				}
-				winit::event::Event::WindowEvent{event,..}=>match event{
-					winit::event::WindowEvent::KeyboardInput{
-						event:
-							winit::event::KeyEvent {
-							logical_key: winit::keyboard::Key::Named(winit::keyboard::NamedKey::Escape),
-								state: winit::event::ElementState::Pressed,
-								..
-							},
-						..
-					}
-					|winit::event::WindowEvent::CloseRequested=>{
-						elwt.exit();
-					}
-					winit::event::WindowEvent::RedrawRequested=>{
-						window_thread.send(TimedInstruction{time,instruction:Instruction::Render}).unwrap();
-					}
-					_=>{
-						window_thread.send(TimedInstruction{time,instruction:Instruction::WindowEvent(event)}).unwrap();
-					}
-				},
-				winit::event::Event::DeviceEvent{
-					event,
-					..
-				} => {
-					window_thread.send(TimedInstruction{time,instruction:Instruction::DeviceEvent(event)}).unwrap();
-				},
-				_=>{}
-			}
-		})
+	let mut app=crate::app::App::new(
+		std::time::Instant::now(),
+		window_thread
+	);
+	event_loop.run_app(&mut app).unwrap();
 }
diff --git a/strafe-client/src/window.rs b/strafe-client/src/window.rs
index b2139cde2..d22685dfd 100644
--- a/strafe-client/src/window.rs
+++ b/strafe-client/src/window.rs
@@ -7,11 +7,8 @@ use strafesnet_session::session::{self,SessionInputInstruction,SessionControlIns
 use strafesnet_settings::directories::Directories;
 
 pub enum Instruction{
-	Resize(winit::dpi::PhysicalSize<u32>),
 	WindowEvent(winit::event::WindowEvent),
 	DeviceEvent(winit::event::DeviceEvent),
-	RequestRedraw,
-	Render,
 }
 
 //holds thread handles to dispatch to
@@ -170,6 +167,23 @@ impl WindowContext<'_>{
 					},
 				}
 			},
+			winit::event::WindowEvent::Resized(size)=>{
+				self.physics_thread.send(
+					TimedInstruction{
+						time,
+						instruction:PhysicsWorkerInstruction::Resize(size)
+					}
+				).unwrap();
+			},
+			winit::event::WindowEvent::RedrawRequested=>{
+				self.window.request_redraw();
+				self.physics_thread.send(
+					TimedInstruction{
+						time,
+						instruction:PhysicsWorkerInstruction::Render
+					}
+				).unwrap();
+			},
 			_=>(),
 		}
 	}
@@ -240,31 +254,12 @@ pub fn worker<'a>(
 	//WindowContextSetup::into_worker
 	crate::compat_worker::QNWorker::new(move |ins:TimedInstruction<Instruction,SessionTimeInner>|{
 		match ins.instruction{
-			Instruction::RequestRedraw=>{
-				window_context.window.request_redraw();
-			}
 			Instruction::WindowEvent(window_event)=>{
 				window_context.window_event(ins.time,window_event);
 			},
 			Instruction::DeviceEvent(device_event)=>{
 				window_context.device_event(ins.time,device_event);
 			},
-			Instruction::Resize(size)=>{
-				window_context.physics_thread.send(
-					TimedInstruction{
-						time:ins.time,
-						instruction:PhysicsWorkerInstruction::Resize(size)
-					}
-				).unwrap();
-			}
-			Instruction::Render=>{
-				window_context.physics_thread.send(
-					TimedInstruction{
-						time:ins.time,
-						instruction:PhysicsWorkerInstruction::Render
-					}
-				).unwrap();
-			}
 		}
 	})
 }