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

Commit

Permalink
Merge pull request #54 from justinshannon/feat/keep-on-top
Browse files Browse the repository at this point in the history
Add option to keep window on top
  • Loading branch information
pierr3 authored Jul 15, 2023
2 parents ad6c578 + 7a6e797 commit 393d8ac
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 1 deletion.
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];
}
}

}

0 comments on commit 393d8ac

Please sign in to comment.