Skip to content
Open
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
168 changes: 168 additions & 0 deletions rogii/apply_patches.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
if(NOT COMMAND apply_patches)
function(apply_patches PATCH_DIR)
if(NOT PATCH_DIR)
message(FATAL_ERROR "apply_patches: first argument PATCH_DIR is required")
endif()

# Ensure Git is available
if(NOT GIT_EXECUTABLE)
find_package(Git REQUIRED)
endif()

if(NOT EXISTS "${PATCH_DIR}")
message(STATUS "apply_patches: patch directory not found: ${PATCH_DIR} — skipping")
return()
endif()

# Detect repository root (top-level) using this script's location
execute_process(
COMMAND ${GIT_EXECUTABLE} -C "${CMAKE_CURRENT_LIST_DIR}" rev-parse --show-toplevel
RESULT_VARIABLE _TOPLVL_RES
OUTPUT_VARIABLE _REPO_ROOT
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
if(NOT _TOPLVL_RES EQUAL 0 OR NOT EXISTS "${_REPO_ROOT}")
# Fallback for atypical layouts
set(_REPO_ROOT "${CMAKE_CURRENT_LIST_DIR}/..")
message(WARNING "apply_patches: failed to auto-detect repo root, falling back to: ${_REPO_ROOT}")
endif()

# Gather submodules (paths relative to repo root)
execute_process(
COMMAND ${GIT_EXECUTABLE} -C "${_REPO_ROOT}" submodule status --recursive
RESULT_VARIABLE _SM_RES
OUTPUT_VARIABLE _SM_OUT
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
set(_SUBMODULES "")
if(_SM_RES EQUAL 0 AND _SM_OUT)
string(REPLACE "\n" ";" _SM_LINES "${_SM_OUT}")
foreach(_L IN LISTS _SM_LINES)
string(STRIP "${_L}" _LSTR)
if(_LSTR STREQUAL "")
continue()
endif()
# Format: "<status><sha> <path> (branch)"
string(REGEX REPLACE "^[^ ]+ +([^ ]+).*$" "\\1" _SM_PATH "${_LSTR}")
list(APPEND _SUBMODULES "${_SM_PATH}")
endforeach()
endif()

# Collect patches: top-level and one subdir level (e.g., qtbase/*.patch)
file(GLOB _PATCHES LIST_DIRECTORIES FALSE
"${PATCH_DIR}/*.patch" "${PATCH_DIR}/*.diff"
"${PATCH_DIR}/*/*.patch" "${PATCH_DIR}/*/*.diff"
)
list(SORT _PATCHES)
if(NOT _PATCHES)
message(STATUS "apply_patches: no patches found in ${PATCH_DIR}")
return()
endif()

message(STATUS "apply_patches: applying patches from ${PATCH_DIR}")
foreach(_P IN LISTS _PATCHES)
# Default: apply at repo root with -p0
set(_TARGET_DIR "${_REPO_ROOT}")
set(_STRIP_P 0)
set(_ROUTED_BY_DIR FALSE)

# Heuristic 1: directory-based routing (PATCH_DIR/<submodule>/...)
if(_SUBMODULES)
file(RELATIVE_PATH _REL_UNDER_PATCHDIR "${PATCH_DIR}" "${_P}")
string(REGEX MATCH "^[^/\\]+" _FIRST_COMP "${_REL_UNDER_PATCHDIR}")
foreach(_SM IN LISTS _SUBMODULES)
if(_FIRST_COMP STREQUAL "${_SM}")
set(_TARGET_DIR "${_REPO_ROOT}/${_SM}")
# Usually patch files placed under <submodule>/ are already relative to that submodule (no extra leading '<submodule>/'),
# so -p0 is typically correct. Leave _STRIP_P=0 here.
set(_ROUTED_BY_DIR TRUE)
break()
endif()
endforeach()
endif()

# Heuristic 2: parse patch header to detect submodule and decide strip
if(NOT _ROUTED_BY_DIR AND _SUBMODULES)
file(READ "${_P}" _PATCH_CONTENT LIMIT 8192) # header is small
# Try to capture '+++ b/<top>/' (or '--- a/<top>/')
set(_HDR_MATCH "")
string(REGEX MATCH "^[+-]{3} [ab]/([^/\n\r]+)/" _HDR_MATCH "${_PATCH_CONTENT}")
if(NOT _HDR_MATCH STREQUAL "")
string(REGEX REPLACE "^[+-]{3} [ab]/([^/\n\r]+)/.*$" "\\1" _HDR_TOP "${_HDR_MATCH}")
foreach(_SM IN LISTS _SUBMODULES)
if(_HDR_TOP STREQUAL "${_SM}")
set(_TARGET_DIR "${_REPO_ROOT}/${_SM}")
# Header path starts with '<submodule>/', so when applying *inside* the submodule,
# we need to drop that leading component -> use -p1.
set(_STRIP_P 1)
break()
endif()
endforeach()
endif()
endif()

message(STATUS "→ ${_P} (target: ${_TARGET_DIR}, -p${_STRIP_P})")

# Try two strip levels for robustness: primary then fallback
set(_TRY_P_LIST "${_STRIP_P}")
if(_STRIP_P EQUAL 0)
list(APPEND _TRY_P_LIST 1)
else()
list(APPEND _TRY_P_LIST 0)
endif()

set(_APPLIED FALSE)
foreach(_TRY_P IN LISTS _TRY_P_LIST)
if(_TRY_P GREATER 0)
execute_process(
COMMAND ${GIT_EXECUTABLE} -C "${_TARGET_DIR}" apply -p${_TRY_P} --3way --whitespace=fix --ignore-space-change "${_P}"
RESULT_VARIABLE _APPLY_RES
OUTPUT_VARIABLE _APPLY_OUT
ERROR_VARIABLE _APPLY_ERR
)
else()
execute_process(
COMMAND ${GIT_EXECUTABLE} -C "${_TARGET_DIR}" apply --3way --whitespace=fix --ignore-space-change "${_P}"
RESULT_VARIABLE _APPLY_RES
OUTPUT_VARIABLE _APPLY_OUT
ERROR_VARIABLE _APPLY_ERR
)
endif()

if(_APPLY_RES EQUAL 0)
set(_APPLIED TRUE)
message(STATUS " applied with -p${_TRY_P}")
break()
endif()

# Idempotency check: already applied?
if(_TRY_P GREATER 0)
execute_process(
COMMAND ${GIT_EXECUTABLE} -C "${_TARGET_DIR}" apply -p${_TRY_P} --reverse --check "${_P}"
RESULT_VARIABLE _REV_OK
OUTPUT_QUIET ERROR_QUIET
)
else()
execute_process(
COMMAND ${GIT_EXECUTABLE} -C "${_TARGET_DIR}" apply --reverse --check "${_P}"
RESULT_VARIABLE _REV_OK
OUTPUT_QUIET ERROR_QUIET
)
endif()

if(_REV_OK EQUAL 0)
set(_APPLIED TRUE)
message(STATUS " (already applied) skipping (detected with -p${_TRY_P})")
break()
endif()
endforeach()

if(NOT _APPLIED)
message(FATAL_ERROR
"apply_patches: failed to apply:\n ${_P}\n${_APPLY_ERR}\n(target: ${_TARGET_DIR})")
endif()
endforeach()
endfunction()
endif()
3 changes: 3 additions & 0 deletions rogii/build_common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ if(NOT INIT_REPOSITORY_RESULT EQUAL 0)
)
endif()

include("${CMAKE_CURRENT_LIST_DIR}/../rogii/apply_patches.cmake")
apply_patches("${CMAKE_CURRENT_LIST_DIR}/../rogii/patches")

set(
QT_SUFFIX
"Rogii"
Expand Down
43 changes: 43 additions & 0 deletions rogii/patches/qtbase/0001-QTBUG-120138.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@


diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index ea6dfdac3b0..b0bae35d920 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -1116,22 +1116,23 @@ void QRhiGles2::destroy()
if (!f)
return;

- ensureContext();
- executeDeferredReleases();
+ if (ensureContext()) {
+ executeDeferredReleases();

- if (ofr.tsQueries[0]) {
- f->glDeleteQueries(2, ofr.tsQueries);
- ofr.tsQueries[0] = ofr.tsQueries[1] = 0;
- }
+ if (ofr.tsQueries[0]) {
+ f->glDeleteQueries(2, ofr.tsQueries);
+ ofr.tsQueries[0] = ofr.tsQueries[1] = 0;
+ }

- if (vao) {
- f->glDeleteVertexArrays(1, &vao);
- vao = 0;
- }
+ if (vao) {
+ f->glDeleteVertexArrays(1, &vao);
+ vao = 0;
+ }

- for (uint shader : m_shaderCache)
- f->glDeleteShader(shader);
- m_shaderCache.clear();
+ for (uint shader : m_shaderCache)
+ f->glDeleteShader(shader);
+ m_shaderCache.clear();
+ }

if (!importedContext) {
delete ctx;
25 changes: 25 additions & 0 deletions rogii/patches/qtbase/0002-QTBUG-135337.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@


diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 6c86c47caac..ddc1114485e 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -765,7 +765,8 @@ static void moveToVirtualScreen(QWindow *w, const QScreen *newScreen)
void QWindowsScreenManager::removeScreen(int index)
{
qCDebug(lcQpaScreen) << "Removing Monitor:" << m_screens.at(index)->data();
- QScreen *screen = m_screens.at(index)->screen();
+ QPlatformScreen *platformScreen = m_screens.takeAt(index);
+ QScreen *screen = platformScreen->screen();
QScreen *primaryScreen = QGuiApplication::primaryScreen();
// QTBUG-38650: When a screen is disconnected, Windows will automatically
// move the Window to another screen. This will trigger a geometry change
@@ -791,7 +792,7 @@ void QWindowsScreenManager::removeScreen(int index)
if (movedWindowCount)
QWindowSystemInterface::flushWindowSystemEvents();
}
- QWindowSystemInterface::handleScreenRemoved(m_screens.takeAt(index));
+ QWindowSystemInterface::handleScreenRemoved(platformScreen);
}

/*!
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@


diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index ea6dfdac3b0..826cbe9839b 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -627,6 +627,11 @@ QSurface *QRhiGles2::evaluateFallbackSurface() const

bool QRhiGles2::ensureContext(QSurface *surface) const
{
+ if (!ctx->isValid()) {
+ contextLost = true;
+ return false;
+ }
+
if (!surface) {
// null means any surface is good because not going to render
if (currentSurfaceForCurrentContext(ctx))
64 changes: 64 additions & 0 deletions rogii/patches/qtbase/0004-Fix-iterate-on-destroyed-windows.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 8e14ee09efc..1e83c71284d 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -16,6 +16,8 @@
#include <QtCore/qscopedvaluerollback.h>
#include <QtCore/private/qlocking_p.h>

+#include <vector>
+
#if QT_CONFIG(draganddrop)
#include <qpa/qplatformdrag.h>
#endif
@@ -760,9 +762,16 @@ void QWindowSystemInterface::handleScreenRemoved(QPlatformScreen *platformScreen
&& newPrimaryScreen->handle()->virtualSiblings().contains(platformScreen);

// Move any leftover windows to the primary screen
- const auto allWindows = QGuiApplication::allWindows();
- for (QWindow *window : allWindows) {
- if (!window->isTopLevel() || window->screen() != screen)
+ const auto & allWindowRawPtrs = QGuiApplication::allWindows();
+
+ std::vector<QPointer<QWindow>> allWindowPointers;
+ allWindowPointers.reserve(allWindowRawPtrs.size());
+
+ for (QWindow *rawWindowPtr : allWindowRawPtrs)
+ allWindowPointers.emplace_back(rawWindowPtr);
+
+ for (const auto & window : allWindowPointers) {
+ if (!window || !window->isTopLevel() || window->screen() != screen)
continue;

const bool wasVisible = window->isVisible();
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 277c234e339..fe3767fff62 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -27,6 +27,7 @@

#include <memory>
#include <type_traits>
+#include <vector>

#include <cfgmgr32.h>
#include <setupapi.h>
@@ -778,7 +779,17 @@ void QWindowsScreenManager::removeScreen(int index)
if (screen != primaryScreen) {
unsigned movedWindowCount = 0;
const QWindowList tlws = QGuiApplication::topLevelWindows();
- for (QWindow *w : tlws) {
+
+ std::vector<QPointer<QWindow>> tlwPointers;
+ tlwPointers.reserve(tlws.size());
+
+ for (QWindow *rawWindowPtr : tlws)
+ tlwPointers.emplace_back(rawWindowPtr);
+
+ for (const auto & w : tlwPointers) {
+ if (!w)
+ continue;
+
if (w->screen() == screen && w->handle() && w->type() != Qt::Desktop) {
if (w->isVisible() && w->windowState() != Qt::WindowMinimized
&& (QWindowsWindow::baseWindowOf(w)->exStyle() & WS_EX_TOOLWINDOW)) {