Skip to content

Commit

Permalink
working termination
Browse files Browse the repository at this point in the history
  • Loading branch information
jhideki committed Mar 21, 2024
1 parent 25ec607 commit ef0eb18
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 100 deletions.
17 changes: 13 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ version = "0.1.0"
edition = "2021"

[dependencies]
lazy_static = "1.4.0"
crossbeam-channel = "0.5"

[dependencies.windows]
version = "0.54"
features = ["Win32_UI_WindowsAndMessaging","Win32_Foundation","Win32_Graphics_Gdi","Win32_UI_Accessibility","Win32_UI_Input_KeyboardAndMouse"]
features = ["Win32_UI_WindowsAndMessaging","Win32_Foundation","Win32_Graphics_Gdi","Win32_UI_Accessibility","Win32_UI_Input_KeyboardAndMouse", "Win32_System_Threading"]

6 changes: 1 addition & 5 deletions src/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use windows::Win32::UI::WindowsAndMessaging::{
GetWindowTextW, IsWindowVisible, PostMessageW, EVENT_SYSTEM_FOREGROUND,
};

//Checks if leader is pressed and signals window manager to re enumerate windows
//Used to update window_manager when user does not use whirlwin
pub unsafe extern "system" fn win_event_proc(
_: HWINEVENTHOOK,
event: u32,
Expand All @@ -18,14 +18,10 @@ pub unsafe extern "system" fn win_event_proc(
_: u32,
_: u32,
) {
println!("callback called");
let leader_pressed = LEADER_PRESSED.load(Ordering::Acquire);
if event == EVENT_SYSTEM_FOREGROUND && !leader_pressed {
let _ = PostMessageW(None, NEW_FOREGROUND_SET, None, None);
println!("leader in callback {}", leader_pressed);
}

println!("callback finisehd");
}

pub unsafe extern "system" fn enum_windows_proc(hwnd: HWND, lparam: LPARAM) -> BOOL {
Expand Down
26 changes: 11 additions & 15 deletions src/keybinds.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use crate::window_manager::{Direction, WindowManagerMessage};
use crate::EXIT_PROGRAM;

use std::io::Error;
use std::process;
use std::sync::mpsc::Sender;
use std::sync::Arc;

use windows::Win32::UI::Input::KeyboardAndMouse::{
RegisterHotKey, UnregisterHotKey, HOT_KEY_MODIFIERS,
};
use windows::Win32::UI::WindowsAndMessaging::PostMessageW;

//Hotkey indentifies
const EXIT: i32 = 1;
Expand Down Expand Up @@ -45,9 +44,6 @@ pub fn handle_hotkey(
if leader_pressed {
match wparam {
EXIT => {
if let Err(_err) = unsafe { PostMessageW(None, EXIT_PROGRAM, None, None) } {
process::exit(0);
}
if let Err(err) = sender.send(WindowManagerMessage::EndListener) {
return Err(format!("Failed to send message: {}", err));
}
Expand Down Expand Up @@ -116,7 +112,7 @@ pub fn register_leader() -> Result<(), Error> {

pub fn unregister_leader() {
unsafe {
UnregisterHotKey(None, LEADER);
let _ = UnregisterHotKey(None, LEADER);
}
}
fn register_hotkeys() -> Result<(), Error> {
Expand Down Expand Up @@ -158,14 +154,14 @@ fn register_hotkeys() -> Result<(), Error> {

pub fn unregister_hotkeys() {
unsafe {
UnregisterHotKey(None, EXIT);
UnregisterHotKey(None, SWITCH_LEFT);
UnregisterHotKey(None, SWITCH_RIGHT);
UnregisterHotKey(None, SWITCH_ABOVE);
UnregisterHotKey(None, SWITCH_BELOW);
UnregisterHotKey(None, SWITCH_NEXT);
UnregisterHotKey(None, CLOSE_WINDOW);
UnregisterHotKey(None, SWITCH_PREVIOUS);
let _ = UnregisterHotKey(None, EXIT);
let _ = UnregisterHotKey(None, SWITCH_LEFT);
let _ = UnregisterHotKey(None, SWITCH_RIGHT);
let _ = UnregisterHotKey(None, SWITCH_ABOVE);
let _ = UnregisterHotKey(None, SWITCH_BELOW);
let _ = UnregisterHotKey(None, SWITCH_NEXT);
let _ = UnregisterHotKey(None, CLOSE_WINDOW);
let _ = UnregisterHotKey(None, SWITCH_PREVIOUS);
}
}

53 changes: 38 additions & 15 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,23 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{channel, Sender};
use std::sync::Arc;
use std::thread;

use crossbeam_channel;
use windows::Win32::System::Threading::GetCurrentThreadId;
use windows::Win32::UI::Accessibility::SetWinEventHook;
use windows::Win32::UI::WindowsAndMessaging::{
DispatchMessageW, GetMessageW, TranslateMessage, EVENT_SYSTEM_FOREGROUND, MSG,
WINEVENT_OUTOFCONTEXT, WM_HOTKEY, WM_USER,
DispatchMessageW, GetMessageW, PostThreadMessageW, TranslateMessage, EVENT_SYSTEM_FOREGROUND,
MSG, WINEVENT_OUTOFCONTEXT, WM_HOTKEY, WM_USER,
};

static LEADER_PRESSED: AtomicBool = AtomicBool::new(false);
const NEW_FOREGROUND_SET: u32 = WM_USER + 1;
const EXIT_PROGRAM: u32 = WM_USER + 2;

fn spawn_hook(sender: Arc<Sender<WindowManagerMessage>>) {
fn spawn_hook(
sender: Arc<Sender<WindowManagerMessage>>,
thread_id_sender: crossbeam_channel::Sender<u32>,
) {
unsafe {
SetWinEventHook(
EVENT_SYSTEM_FOREGROUND,
Expand All @@ -33,18 +40,28 @@ fn spawn_hook(sender: Arc<Sender<WindowManagerMessage>>) {
WINEVENT_OUTOFCONTEXT,
);
}
let thread_id = unsafe { GetCurrentThreadId() };
if let Err(e) = thread_id_sender.send(thread_id) {
println!("Error sending thread id {}", e);
}

let mut msg: MSG = MSG::default();
unsafe {
loop {
loop {
unsafe {
if GetMessageW(&mut msg, None, 0, 0).into() {
if msg.message == NEW_FOREGROUND_SET {
println!("new foreground set in handle_callback");
if let Err(err) = sender.send(WindowManagerMessage::ClearWindows) {
println!("{}", err);
}
if let Err(err) = sender.send(WindowManagerMessage::SetCurrent) {
println!("{}", err);
}
if let Err(err) = sender.send(WindowManagerMessage::SetWindows) {
println!("{}", err);
}
} else if msg.message == EXIT_PROGRAM {
break;
}
}
TranslateMessage(&msg);
Expand All @@ -53,7 +70,7 @@ fn spawn_hook(sender: Arc<Sender<WindowManagerMessage>>) {
}
}

fn key_listener(sender: Arc<Sender<WindowManagerMessage>>) {
fn key_listener(sender: Arc<Sender<WindowManagerMessage>>, callback_thread_id: u32) {
unsafe {
let mut msg: MSG = MSG::default();
while GetMessageW(&mut msg, None, 0, 0).into() {
Expand All @@ -62,11 +79,14 @@ fn key_listener(sender: Arc<Sender<WindowManagerMessage>>) {
let wparam = msg.wParam.0 as i32;
match handle_hotkey(wparam, &sender, leader_pressed) {
Ok(leader) => {
println!("leader after hotkey {}", leader);
LEADER_PRESSED.store(leader, Ordering::Relaxed);
println!("leader pressed updated");
}
Err(e) => {
if let Err(e) =
PostThreadMessageW(callback_thread_id, EXIT_PROGRAM, None, None)
{
println!("error sending thread message {}", e);
}
println!("Error {}", e);
break;
}
Expand All @@ -83,21 +103,24 @@ fn main() -> Result<(), Error> {
let mut window_manager = WindowManager::new(receiver);
window_manager.set_windows();
let window_manger_listener = thread::spawn(move || window_manager.start());
let callback_listener = {
let sender = Arc::clone(&sender_arc);
thread::spawn(move || spawn_hook(sender))
};

unregister_leader();
match register_leader() {
Ok(()) => println!("Leader Registered"),
Err(e) => println!("Failed to registrer leader: {}", e),
}

key_listener(Arc::clone(&sender_arc));
//Channel used for retreiving thread id of callback listener
let (callback_sender, callback_receiver) = crossbeam_channel::unbounded();
let callback_listener = {
let thread_id_sender = callback_sender.clone();
let sender = Arc::clone(&sender_arc);
thread::spawn(move || spawn_hook(sender, thread_id_sender))
};
let callback_thread_id = callback_receiver.recv().unwrap();

key_listener(Arc::clone(&sender_arc), callback_thread_id);

window_manger_listener.join().unwrap();
println!("callback listenern joined");
callback_listener.join().unwrap();
unregister_leader();
Ok(())
Expand Down
6 changes: 3 additions & 3 deletions src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ impl Window {
let mut placement: WINDOWPLACEMENT = WINDOWPLACEMENT::default();
let mut info: WINDOWINFO = WINDOWINFO::default();
unsafe {
GetWindowPlacement(hwnd, &mut placement);
GetWindowInfo(hwnd, &mut info);
let _ = GetWindowPlacement(hwnd, &mut placement);
let _ = GetWindowInfo(hwnd, &mut info);
}
Self {
hwnd,
Expand All @@ -43,7 +43,7 @@ impl Window {
fn set_rect(hwnd: HWND, info: WINDOWINFO) -> Rect {
let mut rect: RECT = RECT::default();
unsafe {
GetWindowRect(hwnd, &mut rect);
let _ = GetWindowRect(hwnd, &mut rect);
}
Rect {
right: rect.right - info.cxWindowBorders as i32,
Expand Down
76 changes: 20 additions & 56 deletions src/window_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use crate::callbacks::enum_windows_proc;
use crate::window::Window;

use std::sync::mpsc::Receiver;
use windows::Win32::Foundation::{HWND, LPARAM, WPARAM};
use windows::Win32::Foundation::{HWND, LPARAM};
use windows::Win32::UI::WindowsAndMessaging::{
CloseWindow, EnumWindows, GetForegroundWindow, SendMessageW, SetForegroundWindow, SetWindowPos,
HWND_BOTTOM, SWP_NOMOVE, SWP_NOSIZE, WM_CLOSE,
CloseWindow, EnumWindows, GetForegroundWindow, SetForegroundWindow, SetWindowPos, HWND_BOTTOM,
SWP_NOMOVE, SWP_NOSIZE,
};
pub enum Direction {
Left,
Expand Down Expand Up @@ -55,7 +55,6 @@ impl WindowManager {

pub fn start(mut self) {
while let Ok(message) = self.receiver.recv() {
println!("message received in window_manager");
match message {
WindowManagerMessage::SetWindows => self.set_windows(),
WindowManagerMessage::CloseWindow => self.close_window(),
Expand Down Expand Up @@ -90,23 +89,14 @@ impl WindowManager {
}

fn switch_to_direction(&mut self, direction: Direction) {
let mut option = None;
match direction {
Direction::Left => {
option = Some(self.left.take());
}
Direction::Right => {
option = Some(self.right.take());
}
Direction::Below => {
option = Some(self.below.take());
}
Direction::Above => {
option = Some(self.above.take());
}
}
let window = match direction {
Direction::Left => self.left.take(),
Direction::Right => self.right.take(),
Direction::Below => self.below.take(),
Direction::Above => self.above.take(),
};

if let Some(window) = option.unwrap() {
if let Some(window) = window {
unsafe {
if !SetForegroundWindow(window.hwnd).as_bool() {
println!("Failed to switch windows");
Expand All @@ -120,8 +110,9 @@ impl WindowManager {

pub fn close_window(&mut self) {
unsafe {
//CloseWindow(self.current.hwnd);
SendMessageW(self.current.hwnd, WM_CLOSE, WPARAM(0), LPARAM(0));
if let Err(e) = CloseWindow(self.current.hwnd) {
println!("Failed to close window {}", e);
}
}
if let Some(window) = &self.next {
self.current = window.to_owned();
Expand All @@ -130,24 +121,10 @@ impl WindowManager {
}
}

/*fn print_window_info(window: &Window) {
println!("order: {}", window.order);
println!("flags {}", window.placement.flags);
println!("dwStyle {}", window.info.dwStyle);
println!("creator version{}", window.info.wCreatorVersion);
println!("atom {}", window.info.atomWindowType);
println!("visibility {}", unsafe { IsWindowVisible(window.hwnd) });
println!("border width {}", window.info.cxWindowBorders);
println!("cmd {}", window.placement.showCmd);
println!("left {}", window.rect.left);
println!("right {}", window.rect.right);
println!("bottom {}", window.rect.bottom);
println!("top {}", window.rect.top);
println!("");
}*/
#[allow(dead_code)]
pub fn print_windows(&mut self) {
println!("current");
&self.current.print_title();
let _ = &self.current.print_title();
println!("");

print!("left");
Expand Down Expand Up @@ -188,7 +165,7 @@ impl WindowManager {

pub fn set_windows(&mut self) {
unsafe {
EnumWindows(
let _ = EnumWindows(
Some(enum_windows_proc),
LPARAM(self as *mut WindowManager as isize),
);
Expand Down Expand Up @@ -222,15 +199,17 @@ impl WindowManager {
window.print_title();
unsafe {
SetForegroundWindow(window.hwnd);
SetWindowPos(
if let Err(e) = SetWindowPos(
self.current.hwnd,
HWND_BOTTOM,
0,
0,
0,
0,
SWP_NOMOVE | SWP_NOSIZE,
);
) {
println!("Switch to next {}: ", e);
}
}
if let Some(hwnd) = self.stack_bottom {
if hwnd == window.hwnd {
Expand All @@ -250,18 +229,3 @@ impl WindowManager {
}
}

#[macro_export]
macro_rules! switch_to_direction {
($window_manager:expr, $direction:ident) => {
if let Some(window) = $window_manager.$direction.take() {
if SetForegroundWindow(window.hwnd) == 0 {
println!("Failed to switch windows");
}
$window_manager.clear_windows();
$window_manager.current = window;
$window_manager.set_windows();
println!("Switch to window {}", stringify!($direction));
}
};
}

0 comments on commit ef0eb18

Please sign in to comment.