Skip to content
This repository has been archived by the owner on May 9, 2024. It is now read-only.

Add option to keep window on top #54

Merged
merged 1 commit into from
Jul 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/include
${NEARGYE_SEMVER_INCLUDE_DIRS})

if (APPLE)
set(APPLE_EXTRA_LIBS src/osx_resources.mm)
set(APPLE_EXTRA_LIBS src/osx_resources.mm src/window_manager.mm)
endif()

if (WIN32)
Expand All @@ -74,6 +74,7 @@ add_executable(vector_audio src/main.cpp
src/application.cpp
src/config.cpp
src/updater.cpp
src/window_manager.cpp
src/data_file_handler.cpp
src/modals/settings.cpp
${CMAKE_SOURCE_DIR}/extern/PlatformFolders/sago/platform_folders.cpp
Expand Down
1 change: 1 addition & 0 deletions include/shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ inline float mPeak = 60.0f;
inline float mVu = 60.0f;
inline int vatsim_cid;
inline std::string vatsim_password;
inline bool keepWindowOnTop = false;

const int kMinVhf = 118000000; // 118.000
const int kMaxVhf = 136975000; // 136.975
Expand Down
7 changes: 7 additions & 0 deletions include/window_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once

#include <SFML/Graphics.hpp>

namespace vector_audio {
void setAlwaysOnTop(sf::RenderWindow& window, bool alwaysOnTop);
}
2 changes: 2 additions & 0 deletions src/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ App::App()
vector_audio::shared::vatsim_password = toml::find_or<std::string>(
cfg::config, "user", "vatsim_password", std::string("password"));

vector_audio::shared::keepWindowOnTop = toml::find_or<bool>(cfg::config, "user", "keepWindowOnTop", false);

vector_audio::shared::ptt = static_cast<sf::Keyboard::Scancode>(
toml::find_or<int>(cfg::config, "user", "ptt", static_cast<int>(sf::Keyboard::Scan::Unknown)));

Expand Down
8 changes: 8 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "spdlog/spdlog.h"
#include "style.h"
#include "updater.h"
#include "window_manager.h"

// Main code
int main(int, char**)
Expand Down Expand Up @@ -93,6 +94,9 @@ int main(int, char**)

auto current_app = std::make_unique<vector_audio::application::App>();

bool alwaysOnTop = vector_audio::shared::keepWindowOnTop;
vector_audio::setAlwaysOnTop(window, alwaysOnTop);

// Main loop
sf::Clock delta_clock;
while (window.isOpen()) {
Expand Down Expand Up @@ -137,7 +141,11 @@ int main(int, char**)
vector_audio::configuration::write_config_async();
vector_audio::shared::capture_ptt_flag = false;
}
}

if (vector_audio::shared::keepWindowOnTop != alwaysOnTop) {
vector_audio::setAlwaysOnTop(window, vector_audio::shared::keepWindowOnTop);
alwaysOnTop = vector_audio::shared::keepWindowOnTop;
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/modals/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ void vector_audio::modals::Settings::render(afv_native::api::atcClient* mClient)
}
vector_audio::style::button_reset_colour();

ImGui::NewLine();

ImGui::Checkbox("Keep Window On Top", &vector_audio::shared::keepWindowOnTop);
ImGui::SameLine();
vector_audio::util::HelpMarker("Enable this option to make the VectorAudio\nwindow stay on top of other windows.");

ImGui::TableNextColumn();

ImGui::Text("Audio configuration");
Expand Down Expand Up @@ -309,6 +315,7 @@ void vector_audio::modals::Settings::render(afv_native::api::atcClient* mClient)
if (ImGui::Button("Save", ImVec2(ImGui::GetContentRegionAvail().x, 0.0F))) {
vector_audio::configuration::config["user"]["vatsim_id"] = vector_audio::shared::vatsim_cid;
vector_audio::configuration::config["user"]["vatsim_password"] = vector_audio::shared::vatsim_password;
vector_audio::configuration::config["user"]["keepWindowOnTop"] = vector_audio::shared::keepWindowOnTop;
vector_audio::configuration::config["audio"]["input_filters"] = vector_audio::shared::mInputFilter;
vector_audio::configuration::config["audio"]["vhf_effects"] = vector_audio::shared::mOutputEffects;
vector_audio::configuration::config["audio"]["hardware_type"] = static_cast<int>(vector_audio::shared::hardware);
Expand Down
62 changes: 62 additions & 0 deletions src/window_manager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "window_manager.h"

#include <iostream>

#ifdef SFML_SYSTEM_WINDOWS
#include <Windows.h>
#elif defined(SFML_SYSTEM_LINUX)
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#endif

namespace vector_audio {

#if !defined(SFML_SYSTEM_MACOS)

void setAlwaysOnTop(sf::RenderWindow& window, bool alwaysOnTop) {
#ifdef SFML_SYSTEM_WINDOWS

HWND hwnd = window.getSystemHandle();
SetWindowPos(hwnd, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

#elif defined(SFML_SYSTEM_LINUX)

XEvent event;
Atom wmStateAbove;
Atom wmNetWmState;

auto display = XOpenDisplay(NULL);
if(!display) {
std::cerr << "WindowManager: failed to open display" << std::endl;
return;
}

auto xwin = static_cast<Window>(window.getSystemHandle());
if(!xwin) {
std::cerr << "WindowManager: getSystemHandle is null" << std::endl;
return;
}

wmStateAbove = XInternAtom(display, "_NET_WM_STATE_ABOVE", False);
wmNetWmState = XInternAtom(display, "_NET_WM_STATE", False);

event.xclient.type = ClientMessage;
event.xclient.display = display;
event.xclient.window = xwin;
event.xclient.message_type = wmNetWmState;
event.xclient.format = 32;
event.xclient.data.l[0] = alwaysOnTop ? 1 : 0; // _NET_WM_STATE_ADD
event.xclient.data.l[1] = wmStateAbove;
event.xclient.data.l[2] = 0; // No second property
event.xclient.data.l[3] = 1; // Normal application window

XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &event);
XSync(display, False);
XCloseDisplay(display);

#endif
}

#endif

}
16 changes: 16 additions & 0 deletions src/window_manager.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "window_manager.h"

#import <Cocoa/Cocoa.h>

namespace vector_audio {

void setAlwaysOnTop(sf::RenderWindow& window, bool alwaysOnTop) {
NSWindow* nsWindow = static_cast<NSWindow*>(window.getSystemHandle());
if (alwaysOnTop) {
[nsWindow setLevel:NSFloatingWindowLevel];
} else {
[nsWindow setLevel:NSNormalWindowLevel];
}
}

}