From fafada28ebc0f2e5423a7d8ece425574ef01ff60 Mon Sep 17 00:00:00 2001 From: Jaime <3794310+AhiyaHiya@users.noreply.github.com> Date: Thu, 5 Sep 2019 06:55:17 -0400 Subject: [PATCH] Merge pull request #14872 from AhiyaHiya:feature/topmost_window * Added mechanism to set/toggle NORMAL window to TOPMOST window. * highgui: remove unnecessary/legacy code --- modules/highgui/include/opencv2/highgui.hpp | 3 +- modules/highgui/src/precomp.hpp | 6 ++ modules/highgui/src/window.cpp | 23 ++++++++ modules/highgui/src/window_cocoa.mm | 62 +++++++++++++++++++++ modules/highgui/src/window_w32.cpp | 45 +++++++++++++++ 5 files changed, 138 insertions(+), 1 deletion(-) diff --git a/modules/highgui/include/opencv2/highgui.hpp b/modules/highgui/include/opencv2/highgui.hpp index 994a1d1efb..628b7fa9ce 100644 --- a/modules/highgui/include/opencv2/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui.hpp @@ -197,7 +197,8 @@ enum WindowPropertyFlags { WND_PROP_AUTOSIZE = 1, //!< autosize property (can be WINDOW_NORMAL or WINDOW_AUTOSIZE). WND_PROP_ASPECT_RATIO = 2, //!< window's aspect ration (can be set to WINDOW_FREERATIO or WINDOW_KEEPRATIO). WND_PROP_OPENGL = 3, //!< opengl support. - WND_PROP_VISIBLE = 4 //!< checks whether the window exists and is visible + WND_PROP_VISIBLE = 4, //!< checks whether the window exists and is visible + WND_PROP_TOPMOST = 5 //!< property to toggle normal window being topmost or not }; //! Mouse Events see cv::MouseCallback diff --git a/modules/highgui/src/precomp.hpp b/modules/highgui/src/precomp.hpp index 1bcc22f610..12e823ba2c 100644 --- a/modules/highgui/src/precomp.hpp +++ b/modules/highgui/src/precomp.hpp @@ -116,6 +116,12 @@ double cvGetOpenGlProp_GTK(const char* name); double cvGetPropVisible_W32(const char* name); +double cvGetPropTopmost_W32(const char* name); +double cvGetPropTopmost_COCOA(const char* name); + +void cvSetPropTopmost_W32(const char* name, const bool topmost); +void cvSetPropTopmost_COCOA(const char* name, const bool topmost); + //for QT #if defined (HAVE_QT) CvRect cvGetWindowRect_QT(const char* name); diff --git a/modules/highgui/src/window.cpp b/modules/highgui/src/window.cpp index 939d3c4eb1..80c449612d 100644 --- a/modules/highgui/src/window.cpp +++ b/modules/highgui/src/window.cpp @@ -42,6 +42,7 @@ #include "precomp.hpp" #include #include "opencv2/core/opengl.hpp" +#include "opencv2/core/utils/logger.hpp" // in later times, use this file as a dispatcher to implementations like cvcap.cpp @@ -83,6 +84,16 @@ CV_IMPL void cvSetWindowProperty(const char* name, int prop_id, double prop_valu #endif break; + case cv::WND_PROP_TOPMOST: + #if defined(HAVE_WIN32UI) + cvSetPropTopmost_W32(name, (prop_value != 0 ? true : false)); + #elif defined(HAVE_COCOA) + cvSetPropTopmost_COCOA(name, (prop_value != 0 ? true : false)); + #else + CV_LOG_WARNING(NULL, "Property WND_PROP_TOPMOST is not supported on current GUI backend"); + #endif + break; + default:; } } @@ -162,6 +173,18 @@ CV_IMPL double cvGetWindowProperty(const char* name, int prop_id) return -1; #endif break; + + case cv::WND_PROP_TOPMOST: + #if defined(HAVE_WIN32UI) + return cvGetPropTopmost_W32(name); + #elif defined(HAVE_COCOA) + return cvGetPropTopmost_COCOA(name); + #else + CV_LOG_WARNING(NULL, "Property WND_PROP_TOPMOST is not supported on current GUI backend"); + return -1; + #endif + break; + default: return -1; } diff --git a/modules/highgui/src/window_cocoa.mm b/modules/highgui/src/window_cocoa.mm index 4041fa1c1e..0c78a070e3 100644 --- a/modules/highgui/src/window_cocoa.mm +++ b/modules/highgui/src/window_cocoa.mm @@ -712,6 +712,68 @@ void cvSetModeWindow_COCOA( const char* name, double prop_value ) __END__; } +double cvGetPropTopmost_COCOA(const char* name) +{ + double result = -1; + CVWindow* window = nil; + + CV_FUNCNAME("cvGetPropTopmost_COCOA"); + + __BEGIN__; + if (name == NULL) + { + CV_ERROR(CV_StsNullPtr, "NULL name string"); + } + + window = cvGetWindow(name); + if (window == NULL) + { + CV_ERROR(CV_StsNullPtr, "NULL window"); + } + + result = (window.level == NSStatusWindowLevel) ? 1 : 0; + + __END__; + return result; +} + +void cvSetPropTopmost_COCOA( const char* name, const bool topmost ) +{ + CVWindow *window = nil; + NSAutoreleasePool* localpool = nil; + CV_FUNCNAME( "cvSetPropTopmost_COCOA" ); + + __BEGIN__; + if( name == NULL ) + { + CV_ERROR( CV_StsNullPtr, "NULL name string" ); + } + + window = cvGetWindow(name); + if ( window == NULL ) + { + CV_ERROR( CV_StsNullPtr, "NULL window" ); + } + + if ([[window contentView] isInFullScreenMode]) + { + EXIT; + } + + localpool = [[NSAutoreleasePool alloc] init]; + if (topmost) + { + [window makeKeyAndOrderFront:window.self]; + [window setLevel:CGWindowLevelForKey(kCGMaximumWindowLevelKey)]; + } + else + { + [window makeKeyAndOrderFront:nil]; + } + [localpool drain]; + __END__; +} + void cv::setWindowTitle(const String& winname, const String& title) { CVWindow *window = cvGetWindow(winname.c_str()); diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index dfb81df4e2..2efee3c947 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -40,6 +40,9 @@ //M*/ #include "precomp.hpp" + +using namespace cv; + #include // required for GET_X_LPARAM() and GET_Y_LPARAM() macros #if defined _WIN32 @@ -538,6 +541,48 @@ void cvSetModeWindow_W32( const char* name, double prop_value)//Yannick Verdie __END__; } +double cvGetPropTopmost_W32(const char* name) +{ + double result = -1; + + CV_Assert(name); + + CvWindow* window = icvFindWindowByName(name); + if (!window) + CV_Error(Error::StsNullPtr, "NULL window"); + + LONG style = GetWindowLongA(window->frame, GWL_EXSTYLE); // -20 + if (!style) + { + std::ostringstream errorMsg; + errorMsg << "window(" << name << "): failed to retrieve extended window style using GetWindowLongA(); error code: " << GetLastError(); + CV_Error(Error::StsError, errorMsg.str().c_str()); + } + + result = (style & WS_EX_TOPMOST) == WS_EX_TOPMOST; + + return result; +} + +void cvSetPropTopmost_W32(const char* name, const bool topmost) +{ + CV_Assert(name); + + CvWindow* window = icvFindWindowByName(name); + if (!window) + CV_Error(Error::StsNullPtr, "NULL window"); + + HWND flag = topmost ? HWND_TOPMOST : HWND_TOP; + BOOL success = SetWindowPos(window->frame, flag, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + + if (!success) + { + std::ostringstream errorMsg; + errorMsg << "window(" << name << "): error reported by SetWindowPos(" << (topmost ? "HWND_TOPMOST" : "HWND_TOP") << "), error code: " << GetLastError(); + CV_Error(Error::StsError, errorMsg.str().c_str()); + } +} + void cv::setWindowTitle(const String& winname, const String& title) { CvWindow* window = icvFindWindowByName(winname.c_str());