Skip to content

Commit

Permalink
feat(wm): reintroduce remove-title-bar cmds
Browse files Browse the repository at this point in the history
This commit reintroduces some old code from the feature/remove-titlebars
branch. This feature is very unstable and it is strongly advised that
nobody actually uses it. Wherever possible, please use the "remove
titlebar" functionality provided directly within an application.
  • Loading branch information
LGUG2Z committed May 15, 2023
1 parent d0c081f commit c37ba42
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 11 deletions.
2 changes: 2 additions & 0 deletions komorebi-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ pub enum SocketMessage {
ToggleFocusFollowsMouse(FocusFollowsMouseImplementation),
MouseFollowsFocus(bool),
ToggleMouseFollowsFocus,
RemoveTitleBar(ApplicationIdentifier, String),
ToggleTitleBars,
AddSubscriber(String),
RemoveSubscriber(String),
NotificationSchema,
Expand Down
7 changes: 6 additions & 1 deletion komorebi/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ lazy_static! {

static ref BORDER_OFFSET: Arc<Mutex<Option<Rect>>> =
Arc::new(Mutex::new(None));

// Use app-specific titlebar removal options where possible
// eg. Windows Terminal, IntelliJ IDEA, Firefox
static ref NO_TITLEBAR: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![]));
}

pub static INITIAL_CONFIGURATION_LOADED: AtomicBool = AtomicBool::new(false);
Expand All @@ -168,6 +172,7 @@ pub static BORDER_COLOUR_CURRENT: AtomicU32 = AtomicU32::new(0);
pub static BORDER_WIDTH: AtomicI32 = AtomicI32::new(20);
// 0 0 0 aka pure black, I doubt anyone will want this as a border colour
pub const TRANSPARENCY_COLOUR: u32 = 0;
pub static REMOVE_TITLEBARS: AtomicBool = AtomicBool::new(false);

pub static HIDDEN_HWND: AtomicIsize = AtomicIsize::new(0);

Expand Down Expand Up @@ -511,7 +516,7 @@ fn main() -> Result<()> {

tracing::error!("received ctrl-c, restoring all hidden windows and terminating process");

wm.lock().restore_all_windows();
wm.lock().restore_all_windows()?;

if WindowsApi::focus_follows_mouse()? {
WindowsApi::disable_focus_follows_mouse()?;
Expand Down
15 changes: 14 additions & 1 deletion komorebi/src/process_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ use crate::INITIAL_CONFIGURATION_LOADED;
use crate::LAYERED_WHITELIST;
use crate::MANAGE_IDENTIFIERS;
use crate::MONITOR_INDEX_PREFERENCES;
use crate::NO_TITLEBAR;
use crate::OBJECT_NAME_CHANGE_ON_LAUNCH;
use crate::REMOVE_TITLEBARS;
use crate::SUBSCRIPTION_PIPES;
use crate::TCP_CONNECTIONS;
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
Expand Down Expand Up @@ -575,7 +577,7 @@ impl WindowManager {
tracing::info!(
"received stop command, restoring all hidden windows and terminating process"
);
self.restore_all_windows();
self.restore_all_windows()?;

if WindowsApi::focus_follows_mouse()? {
WindowsApi::disable_focus_follows_mouse()?;
Expand Down Expand Up @@ -1076,6 +1078,17 @@ impl WindowManager {
let mut stream = UnixStream::connect(socket)?;
stream.write_all(schema.as_bytes())?;
}
SocketMessage::RemoveTitleBar(_, ref id) => {
let mut identifiers = NO_TITLEBAR.lock();
if !identifiers.contains(id) {
identifiers.push(id.clone());
}
}
SocketMessage::ToggleTitleBars => {
let current = REMOVE_TITLEBARS.load(Ordering::SeqCst);
REMOVE_TITLEBARS.store(!current, Ordering::SeqCst);
self.update_focused_workspace(false)?;
}
};

match message {
Expand Down
36 changes: 28 additions & 8 deletions komorebi/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use crate::HIDDEN_HWNDS;
use crate::HIDING_BEHAVIOUR;
use crate::LAYERED_WHITELIST;
use crate::MANAGE_IDENTIFIERS;
use crate::NO_TITLEBAR;
use crate::WSL2_UI_PROCESSES;

#[derive(Debug, Clone, Copy, JsonSchema)]
Expand Down Expand Up @@ -346,23 +347,23 @@ impl Window {
pub fn transparent(self) -> Result<()> {
let mut ex_style = self.ex_style()?;
ex_style.insert(ExtendedWindowStyle::LAYERED);
self.update_ex_style(ex_style)?;
self.update_ex_style(&ex_style)?;
WindowsApi::set_transparent(self.hwnd());
Ok(())
}

pub fn opaque(self) -> Result<()> {
let mut ex_style = self.ex_style()?;
ex_style.remove(ExtendedWindowStyle::LAYERED);
self.update_ex_style(ex_style)
self.update_ex_style(&ex_style)
}

#[allow(dead_code)]
pub fn update_style(self, style: WindowStyle) -> Result<()> {
pub fn update_style(self, style: &WindowStyle) -> Result<()> {
WindowsApi::update_style(self.hwnd(), isize::try_from(style.bits())?)
}

pub fn update_ex_style(self, style: ExtendedWindowStyle) -> Result<()> {
pub fn update_ex_style(self, style: &ExtendedWindowStyle) -> Result<()> {
WindowsApi::update_ex_style(self.hwnd(), isize::try_from(style.bits())?)
}

Expand Down Expand Up @@ -397,6 +398,20 @@ impl Window {
WindowsApi::is_window(self.hwnd())
}

pub fn remove_title_bar(self) -> Result<()> {
let mut style = self.style()?;
style.remove(WindowStyle::CAPTION);
style.remove(WindowStyle::THICKFRAME);
self.update_style(&style)
}

pub fn add_title_bar(self) -> Result<()> {
let mut style = self.style()?;
style.insert(WindowStyle::CAPTION);
style.insert(WindowStyle::THICKFRAME);
self.update_style(&style)
}

#[tracing::instrument(fields(exe, title))]
pub fn should_manage(self, event: Option<WindowManagerEvent>) -> Result<bool> {
if let Some(WindowManagerEvent::DisplayChange(_)) = event {
Expand Down Expand Up @@ -427,7 +442,7 @@ impl Window {
// If not allowing cloaked windows, we need to ensure the window is not cloaked
(false, false) => {
if let (Ok(title), Ok(exe_name), Ok(class)) = (self.title(), self.exe(), self.class()) {
return Ok(window_is_eligible(&title, &exe_name, &class, self.style()?, self.ex_style()?, event));
return Ok(window_is_eligible(&title, &exe_name, &class, &self.style()?, &self.ex_style()?, event));
}
}
_ => {}
Expand All @@ -441,8 +456,8 @@ fn window_is_eligible(
title: &String,
exe_name: &String,
class: &String,
style: WindowStyle,
ex_style: ExtendedWindowStyle,
style: &WindowStyle,
ex_style: &ExtendedWindowStyle,
event: Option<WindowManagerEvent>,
) -> bool {
let mut should_float = false;
Expand Down Expand Up @@ -503,7 +518,12 @@ fn window_is_eligible(
wsl2_ui_processes.contains(exe_name)
};

if (allow_wsl2_gui || style.contains(WindowStyle::CAPTION) && ex_style.contains(ExtendedWindowStyle::WINDOWEDGE))
let allow_titlebar_removed = {
let titlebars_removed = NO_TITLEBAR.lock();
titlebars_removed.contains(exe_name)
};

if (allow_wsl2_gui || allow_titlebar_removed || style.contains(WindowStyle::CAPTION) && ex_style.contains(ExtendedWindowStyle::WINDOWEDGE))
&& !ex_style.contains(ExtendedWindowStyle::DLGMODALFRAME)
// Get a lot of dupe events coming through that make the redrawing go crazy
// on FocusChange events if I don't filter out this one. But, if we are
Expand Down
16 changes: 15 additions & 1 deletion komorebi/src/window_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ use crate::FLOAT_IDENTIFIERS;
use crate::HOME_DIR;
use crate::LAYERED_WHITELIST;
use crate::MANAGE_IDENTIFIERS;
use crate::NO_TITLEBAR;
use crate::OBJECT_NAME_CHANGE_ON_LAUNCH;
use crate::REMOVE_TITLEBARS;
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
use crate::WORKSPACE_RULES;

Expand All @@ -75,6 +77,7 @@ pub struct WindowManager {
pub already_moved_window_handles: Arc<Mutex<HashSet<isize>>>,
}

#[allow(clippy::struct_excessive_bools)]
#[derive(Debug, Serialize, JsonSchema)]
pub struct State {
pub monitors: Ring<Monitor>,
Expand All @@ -87,6 +90,7 @@ pub struct State {
pub focus_follows_mouse: Option<FocusFollowsMouseImplementation>,
pub mouse_follows_focus: bool,
pub has_pending_raise_op: bool,
pub remove_titlebars: bool,
pub float_identifiers: Vec<String>,
pub manage_identifiers: Vec<String>,
pub layered_whitelist: Vec<String>,
Expand Down Expand Up @@ -114,6 +118,7 @@ impl From<&WindowManager> for State {
focus_follows_mouse: wm.focus_follows_mouse,
mouse_follows_focus: wm.mouse_follows_focus,
has_pending_raise_op: wm.has_pending_raise_op,
remove_titlebars: REMOVE_TITLEBARS.load(Ordering::SeqCst),
float_identifiers: FLOAT_IDENTIFIERS.lock().clone(),
manage_identifiers: MANAGE_IDENTIFIERS.lock().clone(),
layered_whitelist: LAYERED_WHITELIST.lock().clone(),
Expand Down Expand Up @@ -480,6 +485,7 @@ impl WindowManager {
Ok(())
}

#[allow(clippy::too_many_arguments)]
#[tracing::instrument(skip(self))]
fn add_window_handle_to_move_based_on_workspace_rule(
&self,
Expand Down Expand Up @@ -954,18 +960,26 @@ impl WindowManager {
}

#[tracing::instrument(skip(self))]
pub fn restore_all_windows(&mut self) {
pub fn restore_all_windows(&mut self) -> Result<()> {
tracing::info!("restoring all hidden windows");

let no_titlebar = NO_TITLEBAR.lock();

for monitor in self.monitors_mut() {
for workspace in monitor.workspaces_mut() {
for containers in workspace.containers_mut() {
for window in containers.windows_mut() {
if no_titlebar.contains(&window.exe()?) {
window.add_title_bar()?;
}

window.restore();
}
}
}
}

Ok(())
}

#[tracing::instrument(skip(self))]
Expand Down
2 changes: 2 additions & 0 deletions komorebi/src/windows_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,8 @@ impl WindowsApi {
}

fn window_long_ptr_w(hwnd: HWND, index: WINDOW_LONG_PTR_INDEX) -> Result<isize> {
// Can return 0, which does not always mean that an error has occurred
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongptrw
Result::from(WindowsResult::from(unsafe {
GetWindowLongPtrW(hwnd, index)
}))
Expand Down
11 changes: 11 additions & 0 deletions komorebi/src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ use crate::ring::Ring;
use crate::window::Window;
use crate::windows_api::WindowsApi;
use crate::INITIAL_CONFIGURATION_LOADED;
use crate::NO_TITLEBAR;
use crate::REMOVE_TITLEBARS;

#[derive(Debug, Clone, Serialize, Getters, CopyGetters, MutGetters, Setters, JsonSchema)]
pub struct Workspace {
Expand Down Expand Up @@ -212,9 +214,18 @@ impl Workspace {
self.resize_dimensions(),
);

let should_remove_titlebars = REMOVE_TITLEBARS.load(Ordering::SeqCst);
let no_titlebar = NO_TITLEBAR.lock().clone();

let windows = self.visible_windows_mut();
for (i, window) in windows.into_iter().enumerate() {
if let (Some(window), Some(layout)) = (window, layouts.get(i)) {
if should_remove_titlebars && no_titlebar.contains(&window.exe()?) {
window.remove_title_bar()?;
} else if no_titlebar.contains(&window.exe()?) {
window.add_title_bar()?;
}

window.set_position(layout, invisible_borders, false)?;
}
}
Expand Down
21 changes: 21 additions & 0 deletions komorebic/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,7 @@ gen_application_target_subcommand_args! {
IdentifyLayeredApplication,
IdentifyObjectNameChangeApplication,
IdentifyBorderOverflowApplication,
RemoveTitleBar,
}

#[derive(Parser, AhkFunction)]
Expand Down Expand Up @@ -964,6 +965,11 @@ enum SubCommand {
/// Identify an application that has WS_EX_LAYERED, but should still be managed
#[clap(arg_required_else_help = true)]
IdentifyLayeredApplication(IdentifyLayeredApplication),
/// Whitelist an application for title bar removal
#[clap(arg_required_else_help = true)]
RemoveTitleBar(RemoveTitleBar),
/// Toggle title bars for whitelisted applications
ToggleTitleBars,
/// Identify an application that has overflowing borders
#[clap(arg_required_else_help = true)]
#[clap(alias = "identify-border-overflow")]
Expand Down Expand Up @@ -1710,6 +1716,21 @@ fn main() -> Result<()> {
.as_bytes()?,
)?;
}
SubCommand::RemoveTitleBar(target) => {
match target.identifier {
ApplicationIdentifier::Exe => {}
_ => {
return Err(anyhow!(
"this command requires applications to be identified by their exe"
))
}
}

send_message(&SocketMessage::RemoveTitleBar(target.identifier, target.id).as_bytes()?)?;
}
SubCommand::ToggleTitleBars => {
send_message(&SocketMessage::ToggleTitleBars.as_bytes()?)?;
}
SubCommand::Manage => {
send_message(&SocketMessage::ManageFocusedWindow.as_bytes()?)?;
}
Expand Down

0 comments on commit c37ba42

Please sign in to comment.