Merge pull request #11903 from alalek:issue_9002

pull/11925/head^2
Alexander Alekhin 6 years ago
commit 924ff903ad
  1. 119
      modules/highgui/src/window_gtk.cpp

@ -40,9 +40,6 @@
//M*/ //M*/
#include "precomp.hpp" #include "precomp.hpp"
#include "opencv2/imgproc.hpp"
using namespace cv;
#ifndef _WIN32 #ifndef _WIN32
@ -66,6 +63,11 @@ using namespace cv;
#include <GL/glu.h> #include <GL/glu.h>
#endif #endif
#include <opencv2/core/utils/logger.hpp>
#include "opencv2/imgproc.hpp"
using namespace cv;
#ifndef BIT_ALLIN #ifndef BIT_ALLIN
#define BIT_ALLIN(x,y) ( ((x)&(y)) == (y) ) #define BIT_ALLIN(x,y) ( ((x)&(y)) == (y) )
#endif #endif
@ -595,10 +597,15 @@ int thread_started=0;
static gpointer icvWindowThreadLoop(gpointer data); static gpointer icvWindowThreadLoop(gpointer data);
GMutex* last_key_mutex = NULL; GMutex* last_key_mutex = NULL;
GCond* cond_have_key = NULL; GCond* cond_have_key = NULL;
GMutex* window_mutex = NULL;
GThread* window_thread = NULL; GThread* window_thread = NULL;
#endif #endif
static cv::Mutex& getWindowMutex()
{
static cv::Mutex* g_window_mutex = new cv::Mutex();
return *g_window_mutex;
}
static int last_key = -1; static int last_key = -1;
static std::vector< Ptr<CvWindow> > g_windows; static std::vector< Ptr<CvWindow> > g_windows;
@ -625,28 +632,28 @@ CV_IMPL int cvInitSystem( int argc, char** argv )
CV_IMPL int cvStartWindowThread(){ CV_IMPL int cvStartWindowThread(){
#ifdef HAVE_GTHREAD #ifdef HAVE_GTHREAD
cvInitSystem(0,NULL); cvInitSystem(0,NULL);
if (!thread_started) { if (!thread_started)
if (!g_thread_supported ()) { {
/* the GThread system wasn't inited, so init it */ if (!g_thread_supported ()) {
g_thread_init(NULL); /* the GThread system wasn't inited, so init it */
} g_thread_init(NULL);
}
// this mutex protects the window resources
window_mutex = g_mutex_new(); (void)getWindowMutex(); // force mutex initialization
// protects the 'last key pressed' variable // protects the 'last key pressed' variable
last_key_mutex = g_mutex_new(); last_key_mutex = g_mutex_new();
// conditional that indicates a key has been pressed // conditional that indicates a key has been pressed
cond_have_key = g_cond_new(); cond_have_key = g_cond_new();
#if !GLIB_CHECK_VERSION(2, 32, 0) #if !GLIB_CHECK_VERSION(2, 32, 0)
// this is the window update thread // this is the window update thread
window_thread = g_thread_create(icvWindowThreadLoop, window_thread = g_thread_create(icvWindowThreadLoop,
NULL, TRUE, NULL); NULL, TRUE, NULL);
#else #else
window_thread = g_thread_new("OpenCV window update", icvWindowThreadLoop, NULL); window_thread = g_thread_new("OpenCV window update", icvWindowThreadLoop, NULL);
#endif #endif
} }
thread_started = window_thread!=NULL; thread_started = window_thread!=NULL;
return thread_started; return thread_started;
@ -659,9 +666,10 @@ CV_IMPL int cvStartWindowThread(){
gpointer icvWindowThreadLoop(gpointer /*data*/) gpointer icvWindowThreadLoop(gpointer /*data*/)
{ {
while(1){ while(1){
g_mutex_lock(window_mutex); {
gtk_main_iteration_do(FALSE); cv::AutoLock lock(getWindowMutex());
g_mutex_unlock(window_mutex); gtk_main_iteration_do(FALSE);
}
// little sleep // little sleep
g_usleep(500); g_usleep(500);
@ -671,20 +679,10 @@ gpointer icvWindowThreadLoop(gpointer /*data*/)
return NULL; return NULL;
} }
class GMutexLock {
GMutex* mutex_;
public:
GMutexLock(GMutex* mutex) : mutex_(mutex) { if (mutex_) g_mutex_lock(mutex_); }
~GMutexLock() { if (mutex_) g_mutex_unlock(mutex_); mutex_ = NULL; }
};
#define CV_LOCK_MUTEX() GMutexLock lock(window_mutex);
#else
#define CV_LOCK_MUTEX()
#endif #endif
#define CV_LOCK_MUTEX() cv::AutoLock lock(getWindowMutex())
static CvWindow* icvFindWindowByName( const char* name ) static CvWindow* icvFindWindowByName( const char* name )
{ {
for(size_t i = 0; i < g_windows.size(); ++i) for(size_t i = 0; i < g_windows.size(); ++i)
@ -1705,18 +1703,19 @@ static gboolean icvOnKeyPress(GtkWidget* widget, GdkEventKey* event, gpointer us
code |= event->state << 16; code |= event->state << 16;
#ifdef HAVE_GTHREAD #ifdef HAVE_GTHREAD
if(thread_started) g_mutex_lock(last_key_mutex); if(thread_started)
#endif {
g_mutex_lock(last_key_mutex);
last_key = code; last_key = code;
#ifdef HAVE_GTHREAD
if(thread_started){
// signal any waiting threads // signal any waiting threads
g_cond_broadcast(cond_have_key); g_cond_broadcast(cond_have_key);
g_mutex_unlock(last_key_mutex); g_mutex_unlock(last_key_mutex);
} }
else
#endif #endif
{
last_key = code;
}
return FALSE; return FALSE;
} }
@ -1886,10 +1885,12 @@ static gboolean icvAlarm( gpointer user_data )
CV_IMPL int cvWaitKey( int delay ) CV_IMPL int cvWaitKey( int delay )
{ {
#ifdef HAVE_GTHREAD #ifdef HAVE_GTHREAD
if(thread_started && g_thread_self()!=window_thread){ if (thread_started && g_thread_self() != window_thread)
gboolean expired; {
gboolean expired = true;
int my_last_key; int my_last_key;
g_mutex_lock(last_key_mutex);
// wait for signal or timeout if delay > 0 // wait for signal or timeout if delay > 0
if(delay>0){ if(delay>0){
GTimeVal timer; GTimeVal timer;
@ -1898,8 +1899,15 @@ CV_IMPL int cvWaitKey( int delay )
expired = !g_cond_timed_wait(cond_have_key, last_key_mutex, &timer); expired = !g_cond_timed_wait(cond_have_key, last_key_mutex, &timer);
} }
else{ else{
g_cond_wait(cond_have_key, last_key_mutex); if (g_windows.empty())
expired=false; {
CV_LOG_WARNING(NULL, "cv::waitKey() is called without timeout and missing active windows. Ignoring");
}
else
{
g_cond_wait(cond_have_key, last_key_mutex);
expired=false;
}
} }
my_last_key = last_key; my_last_key = last_key;
g_mutex_unlock(last_key_mutex); g_mutex_unlock(last_key_mutex);
@ -1908,21 +1916,20 @@ CV_IMPL int cvWaitKey( int delay )
} }
return my_last_key; return my_last_key;
} }
else{ else
#endif #endif
{
int expired = 0; int expired = 0;
guint timer = 0; guint timer = 0;
if( delay > 0 ) if( delay > 0 )
timer = g_timeout_add( delay, icvAlarm, &expired ); timer = g_timeout_add( delay, icvAlarm, &expired );
last_key = -1; last_key = -1;
while( gtk_main_iteration_do(TRUE) && last_key < 0 && !expired && !g_windows.empty()) while( gtk_main_iteration_do(TRUE) && last_key < 0 && !expired && (delay > 0 || !g_windows.empty()))
; ;
if( delay > 0 && !expired ) if( delay > 0 && !expired )
g_source_remove(timer); g_source_remove(timer);
#ifdef HAVE_GTHREAD
} }
#endif
return last_key; return last_key;
} }

Loading…
Cancel
Save