1
0
mirror of https://gitlab.com/kelteseth/ScreenPlay.git synced 2024-11-25 20:22:39 +01:00

Add working Godot Wallpaper

This commit is contained in:
Elias Steurer 2023-09-01 13:48:48 +02:00
parent 7ecbd2e8d1
commit c70fa6224a
26 changed files with 627 additions and 772 deletions

View File

@ -4,6 +4,7 @@
"delgan.qml-format", "delgan.qml-format",
"ms-vscode.cpptools-extension-pack", "ms-vscode.cpptools-extension-pack",
"ms-vscode.cmake-tools", "ms-vscode.cmake-tools",
"seanwu.vscode-qt-for-python" "seanwu.vscode-qt-for-python",
"josetr.cmake-language-support-vscode"
] ]
} }

View File

@ -0,0 +1,2 @@
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf

View File

@ -0,0 +1,2 @@
# Godot 4+ specific ignores
.godot/

View File

@ -0,0 +1,16 @@
extends Path3D
# Reference to the PathFollow node
@onready var path_follow = $PathFollow3D
# Speed of the movement along the path
var speed = 0.4
func _process(delta):
# Update the offset to move the object along the path
path_follow.progress += speed * delta
print(path_follow.progress)
# Loop back to the start if we've reached the end of the path
if path_follow.progress > 10:
path_follow.progress = 0.0

View File

@ -0,0 +1,61 @@
[preset.0]
name="Windows Desktop"
platform="Windows Desktop"
runnable=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path=""
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
[preset.0.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=1
binary_format/embed_pck=false
texture_format/bptc=true
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
binary_format/architecture="x86_64"
codesign/enable=false
codesign/timestamp=true
codesign/timestamp_server_url=""
codesign/digest_algorithm=1
codesign/description=""
codesign/custom_options=PackedStringArray()
application/modify_resources=true
application/icon=""
application/console_wrapper_icon=""
application/icon_interpolation=4
application/file_version=""
application/product_version=""
application/company_name=""
application/product_name=""
application/file_description=""
application/copyright=""
application/trademarks=""
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
ssh_remote_deploy/extra_args_ssh=""
ssh_remote_deploy/extra_args_scp=""
ssh_remote_deploy/run_script="Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}'
$action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}'
$trigger = New-ScheduledTaskTrigger -Once -At 00:00
$settings = New-ScheduledTaskSettingsSet
$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings
Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true
Start-ScheduledTask -TaskName godot_remote_debug
while (Get-ScheduledTask -TaskName godot_remote_debug | ? State -eq running) { Start-Sleep -Milliseconds 100 }
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue"
ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue
Remove-Item -Recurse -Force '{temp_dir}'"

View File

@ -0,0 +1 @@
<svg height="128" width="128" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="124" height="124" rx="14" fill="#363d52" stroke="#212532" stroke-width="4"/><g transform="scale(.101) translate(122 122)"><g fill="#fff"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 813 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H447l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c3 34 55 34 58 0v-86c-3-34-55-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></g></svg>

After

Width:  |  Height:  |  Size: 950 B

View File

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://boex5vkldqpl5"
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.svg"
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,20 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[application]
config/name="Fjord"
run/main_scene="res://wallpaper.tscn"
config/features=PackedStringArray("4.1", "Mobile")
config/icon="res://icon.svg"
[rendering]
renderer/rendering_method="mobile"

View File

@ -0,0 +1,36 @@
[gd_scene load_steps=3 format=3 uid="uid://cxlfu6y6b3l5o"]
[ext_resource type="Script" path="res://Path3D.gd" id="1_76sq1"]
[sub_resource type="Curve3D" id="Curve3D_8adw4"]
_data = {
"points": PackedVector3Array(0, 0, 0, 0, 0, 0, -0.820513, 0.281883, 0.141011, 0, 0, 0, 0, 0, 0, -0.1735, 0.399895, -0.280881, 0, 0, 0, 0, 0, 0, 0.510953, 0.524736, -0.727188, 0, 0, 0, 0, 0, 0, 2.26923, 2.38419e-07, -1.10178, 0, 0, 0, 0, 0, 0, 2.53764, -0.832639, -0.471864, 0, 0, 0, 0, 0, 0, 0.836093, -1.07116, 0.572063, 0, 0, 0, 0, 0, 0, -0.416085, -0.732896, 0.871186, 0, 0, 0, 0, 0, 0, -0.809435, -0.0867326, 0.472196),
"tilts": PackedFloat32Array(0, 0, 0, 0, 0, 0, 0, 0)
}
point_count = 8
[node name="Node3D" type="Node3D"]
[node name="Camera3D" type="Camera3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.04825, 4.0185)
[node name="CSGBox3D" type="CSGBox3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.093655, 0)
size = Vector3(5.24075, 0.0764128, 3.72353)
[node name="Path3D" type="Path3D" parent="."]
curve = SubResource("Curve3D_8adw4")
script = ExtResource("1_76sq1")
[node name="PathFollow3D" type="PathFollow3D" parent="Path3D"]
transform = Transform3D(0.546201, -0.126512, -0.828045, 7.45058e-09, 0.988529, -0.151031, 0.837654, 0.0824935, 0.539936, -0.820513, 0.281883, 0.141011)
[node name="OmniLight3D" type="OmniLight3D" parent="Path3D/PathFollow3D"]
light_color = Color(0.921569, 0.52549, 0.32549, 1)
[node name="Label3D" type="Label3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.391226, -1.25994)
shaded = true
text = "GODO WALLPAPER"
font_size = 126
outline_size = 42

View File

@ -38,6 +38,7 @@ set(SOURCES ${SOURCES} main.cpp src/basewindow.cpp)
set(HEADER ${HEADER} src/basewindow.h) set(HEADER ${HEADER} src/basewindow.h)
set(QML set(QML
# cmake-format: sort # cmake-format: sort
qml/GifWallpaper.qml qml/GifWallpaper.qml
qml/MultimediaView.qml qml/MultimediaView.qml
@ -48,6 +49,17 @@ set(QML
set(RESOURCES dot.png qtquickcontrols2.conf index.html) set(RESOURCES dot.png qtquickcontrols2.conf index.html)
set(LIB_SOURCES ${SOURCES} src/basewindow.cpp)
set(LIB_HEADER ${HEADER} src/basewindow.h)
add_library(ScreenPlayWallpaperLib STATIC src/windowshook.cpp src/windowshook.h)
target_include_directories(ScreenPlayWallpaperLib PUBLIC src)
if(WIN32)
# Used for query windows monitor data
target_link_libraries(ScreenPlayWallpaperLib PUBLIC shcore.lib)
endif()
add_executable(${PROJECT_NAME} ${SOURCES} ${HEADER}) add_executable(${PROJECT_NAME} ${SOURCES} ${HEADER})
qt_add_qml_module( qt_add_qml_module(
@ -68,6 +80,7 @@ qt_add_qml_module(
target_link_libraries( target_link_libraries(
${PROJECT_NAME} ${PROJECT_NAME}
PRIVATE ScreenPlaySDK PRIVATE ScreenPlaySDK
ScreenPlayWallpaperLib
ScreenPlayUtil ScreenPlayUtil
ScreenPlayWeatherplugin ScreenPlayWeatherplugin
Qt6::Quick Qt6::Quick
@ -79,6 +92,7 @@ target_link_libraries(
Qt6::Multimedia Qt6::Multimedia
Qt6::WebEngineCore Qt6::WebEngineCore
Qt6::WebEngineQuick) Qt6::WebEngineQuick)
if(WIN32) if(WIN32)
target_link_libraries(${PROJECT_NAME} PRIVATE ScreenPlaySysInfoplugin) target_link_libraries(${PROJECT_NAME} PRIVATE ScreenPlaySysInfoplugin)
elseif(UNIX AND NOT APPLE) elseif(UNIX AND NOT APPLE)
@ -92,6 +106,7 @@ endif()
if(APPLE) if(APPLE)
target_link_libraries(${PROJECT_NAME} PRIVATE "-framework Cocoa") target_link_libraries(${PROJECT_NAME} PRIVATE "-framework Cocoa")
if(NOT OSX_BUNDLE) if(NOT OSX_BUNDLE)
add_custom_command( add_custom_command(
TARGET ${PROJECT_NAME} TARGET ${PROJECT_NAME}

View File

@ -27,11 +27,9 @@ if ( APPLE )
endif() endif()
# Main project information # Main project information
project( GDExtensionTemplate project(ScreenPlayGodotWallpaper
LANGUAGES LANGUAGES
CXX CXX
VERSION
0.1.0
) )
# Create our library # Create our library
@ -45,6 +43,7 @@ target_compile_features( ${PROJECT_NAME}
# LIB_ARCH is the architecture being built. It is set to the build system's architecture. # LIB_ARCH is the architecture being built. It is set to the build system's architecture.
# For macOS, we build a universal library (both arm64 and x86_64). # For macOS, we build a universal library (both arm64 and x86_64).
set(LIB_ARCH ${CMAKE_SYSTEM_PROCESSOR}) set(LIB_ARCH ${CMAKE_SYSTEM_PROCESSOR})
if(APPLE) if(APPLE)
set(LIB_ARCH "universal") set(LIB_ARCH "universal")
endif() endif()
@ -58,13 +57,15 @@ message( STATUS "Building ${PROJECT_NAME} for ${LIB_ARCH} on ${CMAKE_SYSTEM_NAME
# BUILD_OUTPUT_DIR is where we put the resulting library (in the build directory) # BUILD_OUTPUT_DIR is where we put the resulting library (in the build directory)
set(BUILD_OUTPUT_DIR "${PROJECT_BINARY_DIR}/${PROJECT_NAME}/") set(BUILD_OUTPUT_DIR "${PROJECT_BINARY_DIR}/${PROJECT_NAME}/")
set(OUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../ScreenPlayGodot/${PROJECT_NAME}/)
# Compile directly into our Godot project
set_target_properties(${PROJECT_NAME} set_target_properties(${PROJECT_NAME}
PROPERTIES PROPERTIES
CXX_VISIBILITY_PRESET hidden CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN true VISIBILITY_INLINES_HIDDEN true
RUNTIME_OUTPUT_DIRECTORY "${BUILD_OUTPUT_DIR}/${LIB_DIR}" RUNTIME_OUTPUT_DIRECTORY "${OUT_PATH}/${LIB_DIR}"
LIBRARY_OUTPUT_DIRECTORY "${BUILD_OUTPUT_DIR}/${LIB_DIR}" LIBRARY_OUTPUT_DIRECTORY "${OUT_PATH}/${LIB_DIR}"
) )
if(NOT DEFINED CMAKE_DEBUG_POSTFIX) if(NOT DEFINED CMAKE_DEBUG_POSTFIX)
@ -125,4 +126,5 @@ set_target_properties( godot-cpp
target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME}
PRIVATE PRIVATE
godot-cpp godot-cpp
ScreenPlayWallpaperLib
) )

View File

@ -2,10 +2,8 @@
target_sources(${PROJECT_NAME} target_sources(${PROJECT_NAME}
PRIVATE PRIVATE
ScreenPlayWallpaper.h ScreenPlayGodotWallpaper.h
ScreenPlayWallpaper.cpp ScreenPlayGodotWallpaper.cpp
GDExtensionTemplate.h
GDExtensionTemplate.cpp
RegisterExtension.cpp RegisterExtension.cpp
) )

View File

@ -1,32 +0,0 @@
// SPDX-License-Identifier: Unlicense
#include "godot_cpp/core/class_db.hpp"
#include "GDExtensionTemplate.h"
#include "Version.h"
/// @file
/// GDExtensionTemplate example implementation.
/*!
@brief Get the version string for this extension.
@details
The version string is generated by cmake using src/Version.h.in.
It uses the form "<project name> <last tag>-<# commits since last tag>-<short commit hash>".
If there are no commits since the last tag, only the tag is shown.
@return The version string (e.g. "Foo v1.2.3-gdedbd01").
*/
godot::String GDExtensionTemplate::version()
{
return VersionInfo::VERSION_STR.data();
}
/// Bind our methods so GDScript can access them.
void GDExtensionTemplate::_bind_methods()
{
godot::ClassDB::bind_static_method( "GDExtensionTemplate", godot::D_METHOD( "version" ),
&GDExtensionTemplate::version );
}

View File

@ -1,20 +0,0 @@
#pragma once
// SPDX-License-Identifier: Unlicense
#include "godot_cpp/classes/object.hpp"
namespace godot
{
class ClassDB;
};
class GDExtensionTemplate : public godot::Object
{
GDCLASS( GDExtensionTemplate, godot::Object )
public:
static godot::String version();
private:
static void _bind_methods();
};

View File

@ -6,8 +6,7 @@
#include "godot_cpp/core/defs.hpp" #include "godot_cpp/core/defs.hpp"
#include "godot_cpp/godot.hpp" #include "godot_cpp/godot.hpp"
#include "GDExtensionTemplate.h" #include "ScreenPlayGodotWallpaper.h"
#include "ScreenPlayWallpaper.h"
/// @file /// @file
/// Register our classes with Godot. /// Register our classes with Godot.
@ -24,13 +23,7 @@ void initializeExtension(godot::ModuleInitializationLevel p_level)
return; return;
} }
godot::ClassDB::register_class<ScreenPlayWallpaper>(); godot::ClassDB::register_class<ScreenPlayGodotWallpaper>();
godot::ClassDB::register_class<ExampleMin>();
godot::ClassDB::register_class<Example>();
godot::ClassDB::register_class<ExampleVirtual>(true);
godot::ClassDB::register_abstract_class<ExampleAbstract>();
godot::ClassDB::register_class<GDExtensionTemplate>();
} }
/// @brief Called by Godot to let us do any cleanup. /// @brief Called by Godot to let us do any cleanup.

View File

@ -0,0 +1,117 @@
// Copied from godot-cpp/test/src and modified.
#include "ScreenPlayGodotWallpaper.h"
#include "godot_cpp/classes/display_server.hpp"
#include "godot_cpp/classes/global_constants.hpp"
#include "godot_cpp/classes/label.hpp"
#include "godot_cpp/classes/os.hpp"
#include "godot_cpp/core/class_db.hpp"
#include "godot_cpp/variant/utility_functions.hpp"
//// ScreenPlayWallpaper
int ScreenPlayGodotWallpaper::sInstanceCount = 0;
int ScreenPlayGodotWallpaper::sLastID = 0;
ScreenPlayGodotWallpaper::ScreenPlayGodotWallpaper()
{
mID = ++sLastID;
sInstanceCount++;
godot::UtilityFunctions::print(
"ScreenPlayWallpaper ", godot::itos(mID),
" created, current instance count: ", godot::itos(sInstanceCount));
}
ScreenPlayGodotWallpaper::~ScreenPlayGodotWallpaper()
{
sInstanceCount--;
godot::UtilityFunctions::print(
"ScreenPlayWallpaper ", godot::itos(mID),
" destroyed, current instance count: ", godot::itos(sInstanceCount));
// Somehow this gets called at editor startup
// so just return if not initialized
if (!m_hook)
return;
ShowWindow(m_hook->windowHandle, SW_HIDE);
// Force refresh so that we display the regular
// desktop wallpaper again
ShowWindow(m_hook->windowHandleWorker, SW_HIDE);
ShowWindow(m_hook->windowHandleWorker, SW_SHOW);
}
bool ScreenPlayGodotWallpaper::configureWindowGeometry()
{
if (!m_hook->searchWorkerWindowToParentTo()) {
godot::UtilityFunctions::print("No worker window found");
return false;
}
RECT rect {};
if (!GetWindowRect(m_hook->windowHandleWorker, &rect)) {
godot::UtilityFunctions::print("Unable to get WindoeRect from worker");
return false;
}
// Windows coordante system begins at 0x0 at the
// main monitors upper left and not at the most left top monitor.
// This can be easily read from the worker window.
m_hook->zeroPoint = { std::abs(rect.left), std::abs(rect.top) };
// WARNING: Setting Window flags must be called *here*!
SetWindowLongPtr(m_hook->windowHandle, GWL_EXSTYLE, WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT);
SetWindowLongPtr(m_hook->windowHandle, GWL_STYLE, WS_POPUPWINDOW);
return true;
}
bool ScreenPlayGodotWallpaper::init(int activeScreen)
{
auto* displayServer = godot::DisplayServer::get_singleton();
int64_t handle_int = displayServer->window_get_native_handle(godot::DisplayServer::HandleType::WINDOW_HANDLE, activeScreen);
HWND hwnd = reinterpret_cast<HWND>(static_cast<intptr_t>(handle_int));
m_hook = std::make_unique<WindowsHook>();
m_hook->windowHandle = hwnd;
if (!configureWindowGeometry()) {
return false;
}
ShowWindow(m_hook->windowHandle, SW_HIDE);
const int borderWidth = 2;
const float scaling = m_hook->getScaling(activeScreen); // Assuming getScaling is your own function
const int borderOffset = -1;
WinMonitorStats monitors; // Assuming this is your own function
const int width = static_cast<int>(std::abs(monitors.rcMonitors[activeScreen].right - monitors.rcMonitors[activeScreen].left) / scaling) + borderWidth;
const int height = static_cast<int>(std::abs(monitors.rcMonitors[activeScreen].top - monitors.rcMonitors[activeScreen].bottom) / scaling) + borderWidth;
const int x = monitors.rcMonitors[activeScreen].left + m_hook->zeroPoint.x + borderOffset; // Assuming m_zeroPoint is a POINT struct
const int y = monitors.rcMonitors[activeScreen].top + m_hook->zeroPoint.y + borderOffset;
godot::String output = "Setup window activeScreen: " + godot::itos(activeScreen) + " scaling: " + godot::rtos(scaling) + " x: " + godot::itos(x) + " y: " + godot::itos(y) + " width: " + godot::itos(width) + " height: " + godot::itos(height);
godot::UtilityFunctions::print(output);
// Must be called twice for some reason when window has scaling...
if (!SetWindowPos(m_hook->windowHandle, nullptr, x, y, width, height, SWP_HIDEWINDOW)) {
godot::UtilityFunctions::print("Could not set window pos");
return false;
}
if (!SetWindowPos(m_hook->windowHandle, nullptr, x, y, width, height, SWP_HIDEWINDOW)) {
godot::UtilityFunctions::print("Could not set window pos 2");
return false;
}
if (SetParent(m_hook->windowHandle, m_hook->windowHandleWorker) == nullptr) {
godot::UtilityFunctions::print("Could not attach to parent window");
return false;
}
displayServer->window_set_size(godot::Vector2((real_t)width, (real_t)height));
ShowWindow(m_hook->windowHandle, SW_SHOW);
return true;
}
void ScreenPlayGodotWallpaper::_bind_methods()
{
godot::ClassDB::bind_method(godot::D_METHOD("init"), &ScreenPlayGodotWallpaper::init);
}

View File

@ -0,0 +1,35 @@
#pragma once
// Copied from godot-cpp/test/src and modified.
#include "godot_cpp/classes/control.hpp"
#include "godot_cpp/classes/global_constants.hpp"
#include "godot_cpp/classes/viewport.hpp"
#include "godot_cpp/core/binder_common.hpp"
#include <memory>
#include "ScreenPlayGodotWallpaper.h"
#include "windowshook.h"
class ScreenPlayGodotWallpaper : public godot::Node {
GDCLASS(ScreenPlayGodotWallpaper, Node)
public:
ScreenPlayGodotWallpaper();
~ScreenPlayGodotWallpaper() override;
bool init(int activeScreen);
protected:
static void _bind_methods();
private:
bool configureWindowGeometry();
private:
static int sInstanceCount;
static int sLastID;
int mID;
std::unique_ptr<WindowsHook> m_hook;
};

View File

@ -1,475 +0,0 @@
// Copied from godot-cpp/test/src and modified.
#include "godot_cpp/classes/global_constants.hpp"
#include "godot_cpp/classes/label.hpp"
#include "godot_cpp/core/class_db.hpp"
#include "godot_cpp/variant/utility_functions.hpp"
#include "ScreenPlayWallpaper.h"
// Used to mark unused parameters to indicate intent and suppress warnings.
#define UNUSED(expr) (void)(expr)
namespace {
constexpr int MAGIC_NUMBER = 42;
}
//// ScreenPlayWallpaper
int ScreenPlayWallpaper::sInstanceCount = 0;
int ScreenPlayWallpaper::sLastID = 0;
ScreenPlayWallpaper::ScreenPlayWallpaper()
{
mID = ++sLastID;
sInstanceCount++;
godot::UtilityFunctions::print(
"ScreenPlayWallpaper ", godot::itos(mID),
" created, current instance count: ", godot::itos(sInstanceCount));
}
ScreenPlayWallpaper::~ScreenPlayWallpaper()
{
sInstanceCount--;
godot::UtilityFunctions::print(
"ScreenPlayWallpaper ", godot::itos(mID),
" destroyed, current instance count: ", godot::itos(sInstanceCount));
}
int ScreenPlayWallpaper::getID() const
{
return mID;
}
void ScreenPlayWallpaper::_bind_methods()
{
godot::ClassDB::bind_method(godot::D_METHOD("get_id"), &ScreenPlayWallpaper::getID);
}
//// ExampleMin
void ExampleMin::_bind_methods()
{
}
//// Example
Example::Example()
{
godot::UtilityFunctions::print("Constructor.");
}
Example::~Example()
{
godot::UtilityFunctions::print("Destructor.");
}
// Methods.
void Example::simpleFunc()
{
godot::UtilityFunctions::print(" Simple func called.");
}
void Example::simpleConstFunc() const
{
godot::UtilityFunctions::print(" Simple const func called.");
}
godot::String Example::returnSomething(const godot::String& inBase)
{
godot::UtilityFunctions::print(" Return something called.");
return inBase;
}
godot::Viewport* Example::returnSomethingConst() const
{
godot::UtilityFunctions::print(" Return something const called.");
if (is_inside_tree()) {
godot::Viewport* result = get_viewport();
return result;
}
return nullptr;
}
godot::Ref<ScreenPlayWallpaper> Example::returnEmptyRef() const
{
godot::Ref<ScreenPlayWallpaper> ref;
return ref;
}
ScreenPlayWallpaper* Example::returnExtendedRef() const
{
// You can instance and return a refcounted object like this, but keep in mind that refcounting
// starts with the returned object and it will be destroyed when all references are destroyed.
// If you store this pointer you run the risk of having a pointer to a destroyed object.
return memnew(ScreenPlayWallpaper());
}
godot::Ref<ScreenPlayWallpaper> Example::extendedRefChecks(godot::Ref<ScreenPlayWallpaper> inRef) const
{
// This is the preferred way of instancing and returning a refcounted object:
godot::Ref<ScreenPlayWallpaper> ref;
ref.instantiate();
godot::UtilityFunctions::print(
" Example ref checks called with value: ", inRef->get_instance_id(),
", returning value: ", ref->get_instance_id());
return ref;
}
godot::Variant Example::varargsFunc(const godot::Variant** inArgs, GDExtensionInt inArgCount,
GDExtensionCallError& outError)
{
UNUSED(inArgs);
UNUSED(outError);
godot::UtilityFunctions::print(" Varargs (Variant return) called with ",
godot::String::num_int64(inArgCount), " arguments");
return inArgCount;
}
int Example::varargsFuncNonVoidReturn(const godot::Variant** inArgs, GDExtensionInt inArgCount,
GDExtensionCallError& outError)
{
UNUSED(inArgs);
UNUSED(outError);
godot::UtilityFunctions::print(" Varargs (int return) called with ",
godot::String::num_int64(inArgCount), " arguments");
return MAGIC_NUMBER;
}
void Example::varargsFuncVoidReturn(const godot::Variant** inArgs, GDExtensionInt inArgCount,
GDExtensionCallError& outError)
{
UNUSED(inArgs);
UNUSED(outError);
godot::UtilityFunctions::print(" Varargs (no return) called with ",
godot::String::num_int64(inArgCount), " arguments");
}
void Example::emitCustomSignal(const godot::String& inName, int inValue)
{
emit_signal("custom_signal", inName, inValue);
}
int Example::defArgs(int inA, int inB) const
{
return inA + inB;
}
godot::Array Example::testArray() const
{
godot::Array arr;
arr.resize(2);
arr[0] = godot::Variant(1);
arr[1] = godot::Variant(2);
return arr;
}
void Example::testTypedArrayArg(const godot::TypedArray<int64_t>& inArray)
{
for (int i = 0; i < inArray.size(); ++i) {
godot::UtilityFunctions::print(inArray[i]);
}
}
godot::TypedArray<godot::Vector2> Example::testTypedArray() const
{
godot::TypedArray<godot::Vector2> arr;
arr.resize(2);
arr[0] = godot::Vector2(1, 2);
arr[1] = godot::Vector2(2, 3);
return arr;
}
godot::Dictionary Example::testDictionary() const
{
godot::Dictionary dict;
dict["hello"] = "world";
dict["foo"] = "bar";
return dict;
}
Example* Example::testNodeArgument(Example* inNode) const
{
// This should use godot::String::num_uint64(), but it is currently broken:
// https://github.com/godotengine/godot-cpp/issues/1014
godot::UtilityFunctions::print(
" Test node argument called with ",
(inNode != nullptr)
? godot::String::num_int64(static_cast<int64_t>(inNode->get_instance_id()))
: "null");
return inNode;
}
godot::String Example::testStringOps() const
{
godot::String s = godot::String("A");
s += "B";
s += "C";
s += char32_t(0x010E);
s = s + "E";
return s;
}
int Example::testVectorOps() const
{
godot::PackedInt32Array arr;
arr.push_back(10);
arr.push_back(20);
arr.push_back(30);
arr.push_back(45);
int ret = 0;
for (const int32_t& E : arr) {
ret += E;
}
return ret;
}
godot::BitField<Example::Flags> Example::testBitfield(godot::BitField<Flags> inFlags)
{
godot::UtilityFunctions::print(" Got BitField: ", godot::String::num_int64(inFlags));
return inFlags;
}
// Properties.
void Example::setCustomPosition(const godot::Vector2& inPos)
{
mCustomPosition = inPos;
}
godot::Vector2 Example::getCustomPosition() const
{
return mCustomPosition;
}
godot::Vector4 Example::getV4() const
{
return { 1.2f, 3.4f, 5.6f, 7.8f };
}
// Static methods
int Example::testStatic(int inA, int inB)
{
return inA + inB;
}
void Example::testStatic2()
{
godot::UtilityFunctions::print(" void static");
}
// Virtual function override.
bool Example::_has_point(const godot::Vector2& inPoint) const
{
auto* label = godot::Control::get_node<godot::Label>("Label");
label->set_text("Got point: " + godot::Variant(inPoint).stringify());
return false;
}
void Example::_bind_methods()
{
// Methods.
godot::ClassDB::bind_method(godot::D_METHOD("simple_func"), &Example::simpleFunc);
godot::ClassDB::bind_method(godot::D_METHOD("simple_const_func"),
&Example::simpleConstFunc);
godot::ClassDB::bind_method(godot::D_METHOD("return_something"), &Example::returnSomething);
godot::ClassDB::bind_method(godot::D_METHOD("return_something_const"),
&Example::returnSomethingConst);
godot::ClassDB::bind_method(godot::D_METHOD("return_empty_ref"), &Example::returnEmptyRef);
godot::ClassDB::bind_method(godot::D_METHOD("return_extended_ref"),
&Example::returnExtendedRef);
godot::ClassDB::bind_method(godot::D_METHOD("extended_ref_checks", "ref"),
&Example::extendedRefChecks);
godot::ClassDB::bind_method(godot::D_METHOD("test_array"), &Example::testArray);
godot::ClassDB::bind_method(godot::D_METHOD("test_tarray_arg", "array"),
&Example::testTypedArrayArg);
godot::ClassDB::bind_method(godot::D_METHOD("test_tarray"), &Example::testTypedArray);
godot::ClassDB::bind_method(godot::D_METHOD("test_dictionary"), &Example::testDictionary);
godot::ClassDB::bind_method(godot::D_METHOD("test_node_argument"),
&Example::testNodeArgument);
godot::ClassDB::bind_method(godot::D_METHOD("test_string_ops"), &Example::testStringOps);
godot::ClassDB::bind_method(godot::D_METHOD("test_vector_ops"), &Example::testVectorOps);
godot::ClassDB::bind_method(godot::D_METHOD("test_bitfield", "flags"),
&Example::testBitfield);
godot::ClassDB::bind_method(godot::D_METHOD("def_args", "a", "b"), &Example::defArgs,
DEFVAL(100), DEFVAL(200));
godot::ClassDB::bind_static_method("Example", godot::D_METHOD("test_static", "a", "b"),
&Example::testStatic);
godot::ClassDB::bind_static_method("Example", godot::D_METHOD("test_static2"),
&Example::testStatic2);
{
godot::MethodInfo mi;
mi.arguments.emplace_back(godot::Variant::STRING, "some_argument");
mi.name = "varargs_func";
godot::ClassDB::bind_vararg_method(godot::METHOD_FLAGS_DEFAULT, "varargs_func",
&Example::varargsFunc, mi);
}
{
godot::MethodInfo mi;
mi.arguments.emplace_back(godot::Variant::STRING, "some_argument");
mi.name = "varargs_func_nv";
godot::ClassDB::bind_vararg_method(godot::METHOD_FLAGS_DEFAULT, "varargs_func_nv",
&Example::varargsFuncNonVoidReturn, mi);
}
{
godot::MethodInfo mi;
mi.arguments.emplace_back(godot::Variant::STRING, "some_argument");
mi.name = "varargs_func_void";
godot::ClassDB::bind_vararg_method(godot::METHOD_FLAGS_DEFAULT, "varargs_func_void",
&Example::varargsFuncVoidReturn, mi);
}
// Properties.
ADD_GROUP("Test group", "group_");
ADD_SUBGROUP("Test subgroup", "group_subgroup_");
godot::ClassDB::bind_method(godot::D_METHOD("get_custom_position"),
&Example::getCustomPosition);
godot::ClassDB::bind_method(godot::D_METHOD("get_v4"), &Example::getV4);
godot::ClassDB::bind_method(godot::D_METHOD("set_custom_position", "position"),
&Example::setCustomPosition);
ADD_PROPERTY(godot::PropertyInfo(godot::Variant::VECTOR2, "group_subgroup_custom_position"),
"set_custom_position", "get_custom_position");
// Signals.
ADD_SIGNAL(godot::MethodInfo("custom_signal",
godot::PropertyInfo(godot::Variant::STRING, "name"),
godot::PropertyInfo(godot::Variant::INT, "value")));
godot::ClassDB::bind_method(godot::D_METHOD("emit_custom_signal", "name", "value"),
&Example::emitCustomSignal);
// Constants.
BIND_ENUM_CONSTANT(FIRST)
BIND_ENUM_CONSTANT(ANSWER_TO_EVERYTHING)
BIND_BITFIELD_FLAG(FLAG_ONE);
BIND_BITFIELD_FLAG(FLAG_TWO);
BIND_CONSTANT(CONSTANT_WITHOUT_ENUM);
BIND_ENUM_CONSTANT(OUTSIDE_OF_CLASS);
}
void Example::_notification(int inWhat)
{
godot::UtilityFunctions::print("Notification: ", godot::String::num(inWhat));
}
bool Example::_set(const godot::StringName& inName, const godot::Variant& inValue)
{
godot::String name = inName;
if (name.begins_with("dproperty")) {
int64_t index = name.get_slicec('_', 1).to_int();
mDProp[index] = inValue;
return true;
}
if (name == "property_from_list") {
mPropertyFromList = inValue;
return true;
}
return false;
}
bool Example::_get(const godot::StringName& inName, godot::Variant& outReturn) const
{
godot::String name = inName;
if (name.begins_with("dproperty")) {
int64_t index = name.get_slicec('_', 1).to_int();
outReturn = mDProp[index];
return true;
}
if (name == "property_from_list") {
outReturn = mPropertyFromList;
return true;
}
return false;
}
void Example::_get_property_list(godot::List<godot::PropertyInfo>* outList) const
{
outList->push_back(godot::PropertyInfo(godot::Variant::VECTOR3, "property_from_list"));
for (int i = 0; i < 3; ++i) {
outList->push_back(
godot::PropertyInfo(godot::Variant::VECTOR2, "dproperty_" + godot::itos(i)));
}
}
bool Example::_property_can_revert(const godot::StringName& inName) const
{
if (inName == godot::StringName("property_from_list") && mPropertyFromList != godot::Vector3(MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER)) {
return true;
}
return false;
};
bool Example::_property_get_revert(const godot::StringName& inName,
godot::Variant& outProperty) const
{
if (inName == godot::StringName("property_from_list")) {
outProperty = godot::Vector3(MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER);
return true;
}
return false;
};
godot::String Example::_to_string() const
{
return "[ GDExtension::Example <--> Instance ID:" + godot::uitos(get_instance_id()) + " ]";
}
//// ExampleVirtual
void ExampleVirtual::_bind_methods()
{
}
//// ExampleAbstract
void ExampleAbstract::_bind_methods()
{
}

View File

@ -1,135 +0,0 @@
#pragma once
// Copied from godot-cpp/test/src and modified.
#include "godot_cpp/classes/control.hpp"
#include "godot_cpp/classes/global_constants.hpp"
#include "godot_cpp/classes/viewport.hpp"
#include "godot_cpp/core/binder_common.hpp"
class ScreenPlayWallpaper : public godot::RefCounted {
GDCLASS(ScreenPlayWallpaper, RefCounted)
public:
ScreenPlayWallpaper();
~ScreenPlayWallpaper() override;
int getID() const;
protected:
static void _bind_methods();
private:
static int sInstanceCount;
static int sLastID;
int mID;
};
class ExampleMin : public godot::Control {
GDCLASS(ExampleMin, Control)
protected:
static void _bind_methods();
};
class Example : public godot::Control {
GDCLASS(Example, godot::Control)
public:
// Constants.
enum Constants {
FIRST,
ANSWER_TO_EVERYTHING = 42,
};
enum {
CONSTANT_WITHOUT_ENUM = 314,
};
enum Flags {
FLAG_ONE = 1,
FLAG_TWO = 2,
};
Example();
~Example() override;
// Functions.
void simpleFunc();
void simpleConstFunc() const;
godot::String returnSomething(const godot::String& inBase);
godot::Viewport* returnSomethingConst() const;
godot::Ref<ScreenPlayWallpaper> returnEmptyRef() const;
ScreenPlayWallpaper* returnExtendedRef() const;
godot::Ref<ScreenPlayWallpaper> extendedRefChecks(godot::Ref<ScreenPlayWallpaper> inRef) const;
godot::Variant varargsFunc(const godot::Variant** inArgs, GDExtensionInt inArgCount,
GDExtensionCallError& outError);
int varargsFuncNonVoidReturn(const godot::Variant** inArgs, GDExtensionInt inArgCount,
GDExtensionCallError& outError);
void varargsFuncVoidReturn(const godot::Variant** inArgs, GDExtensionInt inArgCount,
GDExtensionCallError& outError);
void emitCustomSignal(const godot::String& inName, int inValue);
int defArgs(int inA = 100, int inB = 200) const;
godot::Array testArray() const;
void testTypedArrayArg(const godot::TypedArray<int64_t>& inArray);
godot::TypedArray<godot::Vector2> testTypedArray() const;
godot::Dictionary testDictionary() const;
Example* testNodeArgument(Example* inNode) const;
godot::String testStringOps() const;
int testVectorOps() const;
godot::BitField<Flags> testBitfield(godot::BitField<Flags> inFlags);
// Property.
void setCustomPosition(const godot::Vector2& inPos);
godot::Vector2 getCustomPosition() const;
godot::Vector4 getV4() const;
// Static method.
static int testStatic(int inA, int inB);
static void testStatic2();
// Virtual function override (no need to bind manually).
virtual bool _has_point(const godot::Vector2& inPoint) const override;
protected:
static void _bind_methods();
void _notification(int inWhat);
bool _set(const godot::StringName& inName, const godot::Variant& inValue);
bool _get(const godot::StringName& inName, godot::Variant& outReturn) const;
void _get_property_list(godot::List<godot::PropertyInfo>* outList) const;
bool _property_can_revert(const godot::StringName& inName) const;
bool _property_get_revert(const godot::StringName& inName, godot::Variant& outProperty) const;
godot::String _to_string() const;
private:
godot::Vector2 mCustomPosition;
godot::Vector3 mPropertyFromList;
godot::Vector2 mDProp[3];
};
VARIANT_ENUM_CAST(Example::Constants);
VARIANT_BITFIELD_CAST(Example::Flags);
enum EnumWithoutClass {
OUTSIDE_OF_CLASS = 512
};
VARIANT_ENUM_CAST(EnumWithoutClass);
class ExampleVirtual : public godot::Object {
GDCLASS(ExampleVirtual, godot::Object)
protected:
static void _bind_methods();
};
class ExampleAbstract : public godot::Object {
GDCLASS(ExampleAbstract, godot::Object)
protected:
static void _bind_methods();
};

View File

@ -11,6 +11,7 @@ add_dependencies( ${PROJECT_NAME} templates )
# We shouldn't be relying on CMAKE_BUILD_TYPE (see https://github.com/asmaloney/GDExtensionTemplate/issues/25) # We shouldn't be relying on CMAKE_BUILD_TYPE (see https://github.com/asmaloney/GDExtensionTemplate/issues/25)
# But until we fix it here and in godot-cpp, ensure it's one we expect. # But until we fix it here and in godot-cpp, ensure it's one we expect.
set(ALLOWED_BUILDS "Debug;Release") set(ALLOWED_BUILDS "Debug;Release")
if(NOT "${CMAKE_BUILD_TYPE}" IN_LIST ALLOWED_BUILDS) if(NOT "${CMAKE_BUILD_TYPE}" IN_LIST ALLOWED_BUILDS)
message(FATAL_ERROR "CMAKE_BUILD_TYPE must be set to Debug or Release") message(FATAL_ERROR "CMAKE_BUILD_TYPE must be set to Debug or Release")
endif() endif()
@ -25,8 +26,9 @@ if ( MINGW )
endif() endif()
# Generate our project's .gdextension file from the template # Generate our project's .gdextension file from the template
set(OUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../ScreenPlayGodot/${PROJECT_NAME}/)
set(GD_EXTENSION_FILE ${PROJECT_NAME}.gdextension) set(GD_EXTENSION_FILE ${PROJECT_NAME}.gdextension)
configure_file( ${GD_EXTENSION_FILE_INPUT} ${PROJECT_BINARY_DIR}/${PROJECT_NAME}/${GD_EXTENSION_FILE} ) configure_file(${GD_EXTENSION_FILE_INPUT} ${OUT_PATH}/${GD_EXTENSION_FILE})
# Install the gdextension file from the build directory # Install the gdextension file from the build directory
install( install(

View File

@ -0,0 +1,10 @@
[configuration]
entry_symbol = "GDExtensionInit"
compatibility_minimum = 4.1
[libraries]
linux.debug.x86_64 = "res://ScreenPlayGodotWallpaper/lib/Linux-x86_64/libScreenPlayGodotWallpaper-d.so"
macos.debug = "res://ScreenPlayGodotWallpaper/lib/Darwin-Universal/libScreenPlayGodotWallpaper-d.dylib"
windows.debug.x86_64 = "res://ScreenPlayGodotWallpaper/lib/Windows-AMD64/ScreenPlayGodotWallpaper-d.dll"

View File

@ -1,13 +1,18 @@
extends Node3D extends Node3D
@onready var screen_play_wallpaper = $ScreenPlayGodotWallpaper
func _ready(): func _ready():
var path = "" # "C:\\Code\\cpp\\ScreenPlay\\ScreenPlay\\Content\\wallpaper_godot_fjord\\fjord.zip"
var path = "C:\\Code\\cpp\\ScreenPlay\\ScreenPlay\\Content\\wallpaper_godot_fjord\\fjord.zip"
var success = ProjectSettings.load_resource_pack (path) var success = ProjectSettings.load_resource_pack (path)
if success: if success:
var scene_resource = load("res://wallpaper.tscn") var scene_resource = load("res://wallpaper.tscn")
if scene_resource: if scene_resource:
var scene_instance = scene_resource.instantiate() var scene_instance = scene_resource.instantiate()
add_child(scene_instance) add_child(scene_instance)
var ok = screen_play_wallpaper.init(0)
print("init ", ok)
else: else:
print("Failed to load the wallpaper.tscn scene.") print("Failed to load the wallpaper.tscn scene.")
else: else:

View File

@ -4,3 +4,5 @@
[node name="Wallpaper" type="Node3D"] [node name="Wallpaper" type="Node3D"]
script = ExtResource("1_ceeuk") script = ExtResource("1_ceeuk")
[node name="ScreenPlayGodotWallpaper" type="ScreenPlayGodotWallpaper" parent="."]

View File

@ -14,8 +14,18 @@ config/name="ScreenPlay"
run/main_scene="res://main.tscn" run/main_scene="res://main.tscn"
config/features=PackedStringArray("4.1", "Mobile") config/features=PackedStringArray("4.1", "Mobile")
boot_splash/show_image=false boot_splash/show_image=false
boot_splash/fullsize=false
config/icon="res://icon.svg" config/icon="res://icon.svg"
[display]
window/size/viewport_width=1
window/size/viewport_height=1
window/size/mode=1
window/size/initial_position_type=0
window/size/initial_position=Vector2i(9999999, 9999999)
window/size/borderless=true
[rendering] [rendering]
renderer/rendering_method="mobile" renderer/rendering_method="mobile"

View File

@ -0,0 +1,111 @@
#include "windowshook.h"
BOOL CALLBACK WinMonitorStats::MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData)
{
WinMonitorStats* pThis = reinterpret_cast<WinMonitorStats*>(pData);
auto scaleFactor = DEVICE_SCALE_FACTOR::DEVICE_SCALE_FACTOR_INVALID;
GetScaleFactorForMonitor(hMon, &scaleFactor);
UINT x = 0;
UINT y = 0;
GetDpiForMonitor(hMon, MONITOR_DPI_TYPE::MDT_RAW_DPI, &x, &y);
pThis->sizes.push_back({ x, y });
pThis->scaleFactor.push_back(scaleFactor);
pThis->hMonitors.push_back(hMon);
pThis->hdcMonitors.push_back(hdc);
pThis->rcMonitors.push_back(*lprcMonitor);
pThis->iMonitors.push_back(static_cast<int>(pThis->hdcMonitors.size()));
// qInfo() << std::abs(lprcMonitor->right - lprcMonitor->left) << std::abs(lprcMonitor->top - lprcMonitor->bottom);
return TRUE;
}
/*!
\brief Searches for the worker window for our window to parent to.
*/
BOOL WINAPI SearchForWorkerWindow(HWND hwnd, LPARAM lparam)
{
// 0xXXXXXXX "" WorkerW
// ...
// 0xXXXXXXX "" SHELLDLL_DefView
// 0xXXXXXXXX "FolderView" SysListView32
// 0xXXXXXXXX "" WorkerW <---- We want this one
// 0xXXXXXXXX "Program Manager" Progman
if (FindWindowExW(hwnd, nullptr, L"SHELLDLL_DefView", nullptr))
*reinterpret_cast<HWND*>(lparam) = FindWindowExW(nullptr, hwnd, L"WorkerW", nullptr);
return TRUE;
}
bool WindowsHook::searchWorkerWindowToParentTo()
{
HWND progman_hwnd = FindWindowW(L"Progman", L"Program Manager");
const DWORD WM_SPAWN_WORKER = 0x052C;
SendMessageTimeoutW(progman_hwnd, WM_SPAWN_WORKER, 0xD, 0x1, SMTO_NORMAL,
10000, nullptr);
return EnumWindows(SearchForWorkerWindow, reinterpret_cast<LPARAM>(&windowHandleWorker));
}
/*!
\brief Returns scaling factor as reported by Windows.
*/
float WindowsHook::getScaling(const int monitorIndex) const
{
// Get all monitors
int monitorCount = GetSystemMetrics(SM_CMONITORS);
if (monitorIndex < 0 || monitorIndex >= monitorCount) {
// Invalid monitor index
return 1.0f;
}
DISPLAY_DEVICE displayDevice;
ZeroMemory(&displayDevice, sizeof(displayDevice));
displayDevice.cb = sizeof(displayDevice);
// Enumerate through monitors until we find the one we're looking for
for (int i = 0; EnumDisplayDevices(NULL, i, &displayDevice, 0); i++) {
if (i == monitorIndex) {
DEVMODE devMode;
ZeroMemory(&devMode, sizeof(devMode));
devMode.dmSize = sizeof(devMode);
// Get settings for selected monitor
if (!EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode)) {
// Unable to get monitor settings
return 1.0f;
}
// Get DPI for selected monitor
HMONITOR hMonitor = MonitorFromPoint({ devMode.dmPosition.x, devMode.dmPosition.y }, MONITOR_DEFAULTTONEAREST);
UINT dpiX = 0, dpiY = 0;
if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) {
return (float)dpiX / 96.0f; // Standard DPI is 96
}
}
}
// If we reach here, it means we couldn't find the monitor with the given index or couldn't get the DPI.
return 1.0f;
}
/*!
\brief Returns true of at least one monitor has active scaling enabled.
*/
bool WindowsHook::hasWindowScaling() const
{
auto enumMonitorCallback = [](HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) -> BOOL {
int scaling = GetDeviceCaps(hdcMonitor, LOGPIXELSX) / 96;
if (scaling != 1) {
*(bool*)dwData = true;
return false; // Stop enumeration
}
return true; // Continue enumeration
};
bool hasScaling = false;
EnumDisplayMonitors(NULL, NULL, enumMonitorCallback, (LPARAM)&hasScaling);
return hasScaling;
}

View File

@ -0,0 +1,41 @@
#pragma once
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <Windows.h>
#include <algorithm>
#include <iostream>
#include <shellscalingapi.h>
#include <vector>
struct WinMonitorStats {
WinMonitorStats()
{
EnumDisplayMonitors(NULL, NULL, MonitorEnum, (LPARAM)this);
}
static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData);
std::vector<int> iMonitors;
std::vector<HMONITOR> hMonitors;
std::vector<HDC> hdcMonitors;
std::vector<RECT> rcMonitors;
std::vector<DEVICE_SCALE_FACTOR> scaleFactor;
std::vector<std::pair<UINT, UINT>> sizes;
int index = 0;
};
struct Point {
int x = 0;
int y = 0;
};
struct WindowsHook {
bool searchWorkerWindowToParentTo();
float getScaling(const int monitorIndex) const;
bool hasWindowScaling() const;
HWND windowHandle {};
HWND windowHandleWorker {};
Point zeroPoint;
};