-
-
Notifications
You must be signed in to change notification settings - Fork 207
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit adds an optional active window border with a user-defined colour. This is achieved by spawning a dedicated "border window" and constantly placing it behind the focused window, or hiding it whenever necessary. Some constraints to note: - The border will only be applied to windows managed by komorebi - This means that if you temporarily float a window, it will lose the active window border - There are some issues where parts of the border will be broken by applications like Zoom, even if Zoom is behind the currently focused window - You probably want to turn off window shadows globally in Advanced System Settings -> Performance for the borders to have a consistent colour all the way around the window - There is some inevitable jank due to trying to reposition both the focused window and the "border window" behind it simultaneously - There are no borders for unfocused windows resolve #182
- Loading branch information
Showing
16 changed files
with
550 additions
and
55 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,5 +4,5 @@ members = [ | |
"derive-ahk", | ||
"komorebi", | ||
"komorebi-core", | ||
"komorebic" | ||
"komorebic", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
use std::sync::atomic::Ordering; | ||
use std::time::Duration; | ||
|
||
use color_eyre::Result; | ||
use komorebi_core::Rect; | ||
use windows::core::PCSTR; | ||
use windows::Win32::Foundation::HWND; | ||
use windows::Win32::UI::WindowsAndMessaging::DispatchMessageA; | ||
use windows::Win32::UI::WindowsAndMessaging::FindWindowA; | ||
use windows::Win32::UI::WindowsAndMessaging::GetMessageA; | ||
use windows::Win32::UI::WindowsAndMessaging::CS_HREDRAW; | ||
use windows::Win32::UI::WindowsAndMessaging::CS_VREDRAW; | ||
use windows::Win32::UI::WindowsAndMessaging::MSG; | ||
use windows::Win32::UI::WindowsAndMessaging::WNDCLASSA; | ||
|
||
use crate::window::Window; | ||
use crate::windows_callbacks; | ||
use crate::WindowsApi; | ||
use crate::BORDER_HWND; | ||
use crate::BORDER_OVERFLOW_IDENTIFIERS; | ||
use crate::WINDOWS_11; | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
pub struct Border { | ||
pub(crate) hwnd: isize, | ||
} | ||
|
||
impl From<isize> for Border { | ||
fn from(hwnd: isize) -> Self { | ||
Self { hwnd } | ||
} | ||
} | ||
|
||
impl Border { | ||
pub const fn hwnd(self) -> HWND { | ||
HWND(self.hwnd) | ||
} | ||
|
||
pub fn create(name: &str) -> Result<()> { | ||
let name = format!("{name}\0"); | ||
let instance = WindowsApi::module_handle_w()?; | ||
let class_name = PCSTR(name.as_ptr()); | ||
let brush = WindowsApi::create_solid_brush(255, 140, 0); | ||
let window_class = WNDCLASSA { | ||
hInstance: instance, | ||
lpszClassName: class_name, | ||
style: CS_HREDRAW | CS_VREDRAW, | ||
lpfnWndProc: Some(windows_callbacks::border_window), | ||
hbrBackground: brush, | ||
..Default::default() | ||
}; | ||
|
||
let _atom = WindowsApi::register_class_a(&window_class)?; | ||
|
||
let name_cl = name.clone(); | ||
std::thread::spawn(move || -> Result<()> { | ||
let hwnd = WindowsApi::create_border_window(PCSTR(name_cl.as_ptr()), instance)?; | ||
let border = Self::from(hwnd); | ||
|
||
let mut message = MSG::default(); | ||
|
||
unsafe { | ||
while GetMessageA(&mut message, border.hwnd(), 0, 0).into() { | ||
DispatchMessageA(&message); | ||
std::thread::sleep(Duration::from_millis(10)); | ||
} | ||
} | ||
|
||
Ok(()) | ||
}); | ||
|
||
let mut hwnd = HWND(0); | ||
while hwnd == HWND(0) { | ||
hwnd = unsafe { FindWindowA(PCSTR(name.as_ptr()), PCSTR::null()) }; | ||
} | ||
|
||
BORDER_HWND.store(hwnd.0, Ordering::SeqCst); | ||
|
||
if *WINDOWS_11 { | ||
WindowsApi::round_corners(hwnd.0)?; | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
pub fn hide(self) -> Result<()> { | ||
WindowsApi::hide_border_window(self.hwnd()) | ||
} | ||
|
||
pub fn set_position( | ||
self, | ||
window: Window, | ||
invisible_borders: &Rect, | ||
activate: bool, | ||
) -> Result<()> { | ||
let mut should_expand_border = false; | ||
|
||
let mut rect = WindowsApi::window_rect(window.hwnd())?; | ||
rect.top -= invisible_borders.bottom; | ||
rect.bottom += invisible_borders.bottom; | ||
|
||
let border_overflows = BORDER_OVERFLOW_IDENTIFIERS.lock(); | ||
if border_overflows.contains(&window.title()?) | ||
|| border_overflows.contains(&window.exe()?) | ||
|| border_overflows.contains(&window.class()?) | ||
{ | ||
should_expand_border = true; | ||
} | ||
|
||
if should_expand_border { | ||
rect.left -= invisible_borders.left; | ||
rect.top -= invisible_borders.top; | ||
rect.right += invisible_borders.right; | ||
rect.bottom += invisible_borders.bottom; | ||
} | ||
|
||
WindowsApi::position_border_window(self.hwnd(), &rect, activate) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.