• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41 
42 #include "precomp.hpp"
43 #include "opencv2/imgproc.hpp"
44 
45 #ifndef WIN32
46 
47 #if defined (HAVE_GTK)
48 
49 #include <gtk/gtk.h>
50 #include <gdk/gdkkeysyms.h>
51 #include <gdk-pixbuf/gdk-pixbuf.h>
52 #include <stdio.h>
53 
54 #if (GTK_MAJOR_VERSION == 3)
55   #define GTK_VERSION3
56 #endif //GTK_MAJOR_VERSION >= 3
57 
58 #ifdef HAVE_OPENGL
59     #include <gtk/gtkgl.h>
60     #include <GL/gl.h>
61     #include <GL/glu.h>
62 #endif
63 
64 // TODO Fix the initial window size when flags=0.  Right now the initial window is by default
65 // 320x240 size.  A better default would be actual size of the image.  Problem
66 // is determining desired window size with trackbars while still allowing resizing.
67 //
68 // Gnome Totem source may be of use here, see bacon_video_widget_set_scale_ratio
69 // in totem/src/backend/bacon-video-widget-xine.c
70 
71 ////////////////////////////////////////////////////////////
72 // CvImageWidget GTK Widget Public API
73 ////////////////////////////////////////////////////////////
74 typedef struct _CvImageWidget        CvImageWidget;
75 typedef struct _CvImageWidgetClass   CvImageWidgetClass;
76 
77 struct _CvImageWidget {
78     GtkWidget widget;
79     CvMat * original_image;
80     CvMat * scaled_image;
81     int flags;
82 };
83 
84 struct _CvImageWidgetClass
85 {
86   GtkWidgetClass parent_class;
87 };
88 
89 
90 /** Allocate new image viewer widget */
91 GtkWidget*     cvImageWidgetNew      (int flags);
92 
93 /** Set the image to display in the widget */
94 void           cvImageWidgetSetImage(CvImageWidget * widget, const CvArr *arr);
95 
96 // standard GTK object macros
97 #define CV_IMAGE_WIDGET(obj)          G_TYPE_CHECK_INSTANCE_CAST (obj, cvImageWidget_get_type (), CvImageWidget)
98 #define CV_IMAGE_WIDGET_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, cvImageWidget_get_type (), CvImageWidgetClass)
99 #define CV_IS_IMAGE_WIDGET(obj)       G_TYPE_CHECK_INSTANCE_TYPE (obj, cvImageWidget_get_type ())
100 
101 /////////////////////////////////////////////////////////////////////////////
102 // Private API ////////////////////////////////////////////////////////
103 /////////////////////////////////////////////////////////////////////////////
104 GType        cvImageWidget_get_type (void);
105 
106 static GtkWidgetClass * parent_class = NULL;
107 
108 // flag to help size initial window
109 #define CV_WINDOW_NO_IMAGE 2
110 
cvImageWidgetSetImage(CvImageWidget * widget,const CvArr * arr)111 void cvImageWidgetSetImage(CvImageWidget * widget, const CvArr *arr){
112     CvMat * mat, stub;
113     int origin=0;
114 
115     //printf("cvImageWidgetSetImage\n");
116 
117     if( CV_IS_IMAGE_HDR( arr ))
118         origin = ((IplImage*)arr)->origin;
119 
120     mat = cvGetMat(arr, &stub);
121 
122     if(widget->original_image && !CV_ARE_SIZES_EQ(mat, widget->original_image)){
123         cvReleaseMat( &widget->original_image );
124     }
125     if(!widget->original_image){
126         widget->original_image = cvCreateMat( mat->rows, mat->cols, CV_8UC3 );
127         gtk_widget_queue_resize( GTK_WIDGET( widget ) );
128     }
129     cvConvertImage( mat, widget->original_image,
130                             (origin != 0 ? CV_CVTIMG_FLIP : 0) + CV_CVTIMG_SWAP_RB );
131     if(widget->scaled_image){
132         cvResize( widget->original_image, widget->scaled_image, CV_INTER_AREA );
133     }
134 
135     // window does not refresh without this
136     gtk_widget_queue_draw( GTK_WIDGET(widget) );
137 }
138 
139 GtkWidget*
cvImageWidgetNew(int flags)140 cvImageWidgetNew (int flags)
141 {
142   CvImageWidget *image_widget;
143 
144   image_widget = CV_IMAGE_WIDGET( gtk_widget_new (cvImageWidget_get_type (), NULL) );
145   image_widget->original_image = 0;
146   image_widget->scaled_image = 0;
147   image_widget->flags = flags | CV_WINDOW_NO_IMAGE;
148 
149   return GTK_WIDGET (image_widget);
150 }
151 
152 static void
cvImageWidget_realize(GtkWidget * widget)153 cvImageWidget_realize (GtkWidget *widget)
154 {
155   GdkWindowAttr attributes;
156   gint attributes_mask;
157 
158 #if defined(GTK_VERSION3)
159   GtkAllocation allocation;
160   gtk_widget_get_allocation(widget, &allocation);
161 #endif //GTK_VERSION3
162 
163   //printf("cvImageWidget_realize\n");
164   g_return_if_fail (widget != NULL);
165   g_return_if_fail (CV_IS_IMAGE_WIDGET (widget));
166 
167   gtk_widget_set_realized(widget, TRUE);
168 
169 #if defined(GTK_VERSION3)
170   attributes.x = allocation.x;
171   attributes.y = allocation.y;
172   attributes.width = allocation.width;
173   attributes.height = allocation.height;
174 #else
175   attributes.x = widget->allocation.x;
176   attributes.y = widget->allocation.y;
177   attributes.width = widget->allocation.width;
178   attributes.height = widget->allocation.height;
179 #endif //GTK_VERSION3
180 
181   attributes.wclass = GDK_INPUT_OUTPUT;
182   attributes.window_type = GDK_WINDOW_CHILD;
183   attributes.event_mask = gtk_widget_get_events (widget) |
184     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
185     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK;
186   attributes.visual = gtk_widget_get_visual (widget);
187 
188 #if defined(GTK_VERSION3)
189   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
190   gtk_widget_set_window(
191       widget,
192       gdk_window_new(
193         gtk_widget_get_parent_window(widget),
194         &attributes,
195         attributes_mask
196         )
197       );
198 
199   gtk_widget_set_style(
200       widget,
201       gtk_style_attach(
202         gtk_widget_get_style(widget),
203         gtk_widget_get_window(widget)
204         )
205       );
206 
207   gdk_window_set_user_data (
208       gtk_widget_get_window(widget),
209       widget
210       );
211 
212   gtk_style_set_background (
213       gtk_widget_get_style(widget),
214       gtk_widget_get_window(widget),
215       GTK_STATE_ACTIVE
216       );
217  #else
218   // The following lines are included to prevent breaking
219   // compatibility with older Gtk2 (<gtk+-2.18) libraries.
220   attributes.colormap = gtk_widget_get_colormap (widget);
221   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
222   widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
223 
224   widget->style = gtk_style_attach (widget->style, widget->window);
225   gdk_window_set_user_data (widget->window, widget);
226 
227   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
228 #endif // GTK_VERSION3
229 }
230 
cvImageWidget_calc_size(int im_width,int im_height,int max_width,int max_height)231 static CvSize cvImageWidget_calc_size( int im_width, int im_height, int max_width, int max_height ){
232     float aspect = (float)im_width/(float)im_height;
233     float max_aspect = (float)max_width/(float)max_height;
234     if(aspect > max_aspect){
235         return cvSize( max_width, cvRound(max_width/aspect) );
236     }
237     return cvSize( cvRound(max_height*aspect), max_height );
238 }
239 
240 #if defined (GTK_VERSION3)
241 static void
cvImageWidget_get_preferred_width(GtkWidget * widget,gint * minimal_width,gint * natural_width)242 cvImageWidget_get_preferred_width (GtkWidget *widget, gint *minimal_width, gint *natural_width)
243 {
244   g_return_if_fail (widget != NULL);
245   g_return_if_fail (CV_IS_IMAGE_WIDGET (widget));
246   CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget );
247 
248   if(image_widget->original_image != NULL) {
249     *minimal_width = image_widget->flags & CV_WINDOW_AUTOSIZE ?
250       gdk_window_get_width(gtk_widget_get_window(widget)) : image_widget->original_image->cols;
251   }
252   else {
253     *minimal_width = 320;
254   }
255 
256   if(image_widget->scaled_image != NULL) {
257     *natural_width = *minimal_width < image_widget->scaled_image->cols ?
258       image_widget->scaled_image->cols : *minimal_width;
259   }
260   else {
261     *natural_width = *minimal_width;
262   }
263 }
264 
265 static void
cvImageWidget_get_preferred_height(GtkWidget * widget,gint * minimal_height,gint * natural_height)266 cvImageWidget_get_preferred_height (GtkWidget *widget, gint *minimal_height, gint *natural_height)
267 {
268   g_return_if_fail (widget != NULL);
269   g_return_if_fail (CV_IS_IMAGE_WIDGET (widget));
270   CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget );
271 
272   if(image_widget->original_image != NULL) {
273     *minimal_height = image_widget->flags & CV_WINDOW_AUTOSIZE ?
274       gdk_window_get_height(gtk_widget_get_window(widget)) : image_widget->original_image->rows;
275   }
276   else {
277     *minimal_height = 240;
278   }
279 
280   if(image_widget->scaled_image != NULL) {
281     *natural_height = *minimal_height < image_widget->scaled_image->rows ?
282       image_widget->scaled_image->cols : *minimal_height;
283   }
284   else {
285     *natural_height = *minimal_height;
286   }
287 }
288 
289 #else
290 static void
cvImageWidget_size_request(GtkWidget * widget,GtkRequisition * requisition)291 cvImageWidget_size_request (GtkWidget      *widget,
292                        GtkRequisition *requisition)
293 {
294     CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget );
295 
296     //printf("cvImageWidget_size_request ");
297     // the case the first time cvShowImage called or when AUTOSIZE
298     if( image_widget->original_image &&
299         ((image_widget->flags & CV_WINDOW_AUTOSIZE) ||
300          (image_widget->flags & CV_WINDOW_NO_IMAGE)))
301     {
302         //printf("original ");
303         requisition->width = image_widget->original_image->cols;
304         requisition->height = image_widget->original_image->rows;
305     }
306     // default case
307     else if(image_widget->scaled_image){
308         //printf("scaled ");
309         requisition->width = image_widget->scaled_image->cols;
310         requisition->height = image_widget->scaled_image->rows;
311     }
312     // the case before cvShowImage called
313     else{
314         //printf("default ");
315         requisition->width = 320;
316         requisition->height = 240;
317     }
318     //printf("%d %d\n",requisition->width, requisition->height);
319 }
320 #endif //GTK_VERSION3
321 
cvImageWidget_set_size(GtkWidget * widget,int max_width,int max_height)322 static void cvImageWidget_set_size(GtkWidget * widget, int max_width, int max_height){
323     CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget );
324 
325     //printf("cvImageWidget_set_size %d %d\n", max_width, max_height);
326 
327     // don't allow to set the size
328     if(image_widget->flags & CV_WINDOW_AUTOSIZE) return;
329     if(!image_widget->original_image) return;
330 
331     CvSize scaled_image_size = cvImageWidget_calc_size( image_widget->original_image->cols,
332             image_widget->original_image->rows, max_width, max_height );
333 
334     if( image_widget->scaled_image &&
335             ( image_widget->scaled_image->cols != scaled_image_size.width ||
336               image_widget->scaled_image->rows != scaled_image_size.height ))
337     {
338         cvReleaseMat( &image_widget->scaled_image );
339     }
340     if( !image_widget->scaled_image ){
341         image_widget->scaled_image = cvCreateMat( scaled_image_size.height, scaled_image_size.width, CV_8UC3 );
342 
343 
344     }
345     assert( image_widget->scaled_image );
346 }
347 
348 static void
cvImageWidget_size_allocate(GtkWidget * widget,GtkAllocation * allocation)349 cvImageWidget_size_allocate (GtkWidget     *widget,
350                         GtkAllocation *allocation)
351 {
352   CvImageWidget *image_widget;
353 
354   //printf("cvImageWidget_size_allocate\n");
355   g_return_if_fail (widget != NULL);
356   g_return_if_fail (CV_IS_IMAGE_WIDGET (widget));
357   g_return_if_fail (allocation != NULL);
358 
359 #if defined (GTK_VERSION3)
360   gtk_widget_set_allocation(widget, allocation);
361 #else
362   widget->allocation = *allocation;
363 #endif //GTK_VERSION3
364   image_widget = CV_IMAGE_WIDGET (widget);
365 
366 
367   if( (image_widget->flags & CV_WINDOW_AUTOSIZE)==0 && image_widget->original_image ){
368       // (re) allocated scaled image
369       if( image_widget->flags & CV_WINDOW_NO_IMAGE ){
370           cvImageWidget_set_size( widget, image_widget->original_image->cols,
371                                           image_widget->original_image->rows);
372       }
373       else{
374           cvImageWidget_set_size( widget, allocation->width, allocation->height );
375       }
376       cvResize( image_widget->original_image, image_widget->scaled_image, CV_INTER_AREA );
377   }
378 
379   if (gtk_widget_get_realized (widget))
380     {
381       image_widget = CV_IMAGE_WIDGET (widget);
382 
383       if( image_widget->original_image &&
384               ((image_widget->flags & CV_WINDOW_AUTOSIZE) ||
385                (image_widget->flags & CV_WINDOW_NO_IMAGE)) )
386       {
387 #if defined (GTK_VERSION3)
388           allocation->width = image_widget->original_image->cols;
389           allocation->height = image_widget->original_image->rows;
390           gtk_widget_set_allocation(widget, allocation);
391 #else
392           widget->allocation.width = image_widget->original_image->cols;
393           widget->allocation.height = image_widget->original_image->rows;
394 #endif //GTK_VERSION3
395           gdk_window_move_resize( gtk_widget_get_window(widget),
396               allocation->x, allocation->y,
397               image_widget->original_image->cols, image_widget->original_image->rows );
398           if(image_widget->flags & CV_WINDOW_NO_IMAGE){
399               image_widget->flags &= ~CV_WINDOW_NO_IMAGE;
400               gtk_widget_queue_resize( GTK_WIDGET(widget) );
401           }
402       }
403       else{
404           gdk_window_move_resize (gtk_widget_get_window(widget),
405                   allocation->x, allocation->y,
406                   allocation->width, allocation->height );
407       }
408     }
409 }
410 
411 #if defined (GTK_VERSION3)
412 static void
cvImageWidget_destroy(GtkWidget * object)413 cvImageWidget_destroy (GtkWidget *object)
414 #else
415 static void
416 cvImageWidget_destroy (GtkObject *object)
417 #endif //GTK_VERSION3
418 {
419   CvImageWidget *image_widget;
420 
421   g_return_if_fail (object != NULL);
422   g_return_if_fail (CV_IS_IMAGE_WIDGET (object));
423 
424   image_widget = CV_IMAGE_WIDGET (object);
425 
426   cvReleaseMat( &image_widget->scaled_image );
427   cvReleaseMat( &image_widget->original_image );
428 
429 #if defined (GTK_VERSION3)
430   if (GTK_WIDGET_CLASS (parent_class)->destroy)
431     (* GTK_WIDGET_CLASS (parent_class)->destroy) (object);
432 #else
433   if (GTK_OBJECT_CLASS (parent_class)->destroy)
434     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
435 #endif //GTK_VERSION3
436 }
437 
cvImageWidget_class_init(CvImageWidgetClass * klass)438 static void cvImageWidget_class_init (CvImageWidgetClass * klass)
439 {
440 #if defined (GTK_VERSION3)
441   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
442 #else
443   GtkObjectClass *object_class;
444   GtkWidgetClass *widget_class;
445 
446   object_class = (GtkObjectClass*) klass;
447   widget_class = (GtkWidgetClass*) klass;
448 #endif //GTK_VERSION3
449 
450   parent_class = GTK_WIDGET_CLASS( g_type_class_peek (gtk_widget_get_type ()) );
451 
452 #if defined (GTK_VERSION3)
453   widget_class->destroy = cvImageWidget_destroy;
454   widget_class->get_preferred_width = cvImageWidget_get_preferred_width;
455   widget_class->get_preferred_height = cvImageWidget_get_preferred_height;
456 #else
457   object_class->destroy = cvImageWidget_destroy;
458   widget_class->size_request = cvImageWidget_size_request;
459 #endif //GTK_VERSION3
460 
461   widget_class->realize = cvImageWidget_realize;
462   widget_class->size_allocate = cvImageWidget_size_allocate;
463   widget_class->button_press_event = NULL;
464   widget_class->button_release_event = NULL;
465   widget_class->motion_notify_event = NULL;
466 }
467 
468 static void
cvImageWidget_init(CvImageWidget * image_widget)469 cvImageWidget_init (CvImageWidget *image_widget)
470 {
471     image_widget->original_image=0;
472     image_widget->scaled_image=0;
473     image_widget->flags=0;
474 }
475 
cvImageWidget_get_type(void)476 GType cvImageWidget_get_type (void){
477   static GType image_type = 0;
478 
479   if (!image_type)
480     {
481       image_type = g_type_register_static_simple(
482           GTK_TYPE_WIDGET,
483           (gchar*) "CvImageWidget",
484           sizeof(CvImageWidgetClass),
485           (GClassInitFunc) cvImageWidget_class_init,
486           sizeof(CvImageWidget),
487           (GInstanceInitFunc) cvImageWidget_init,
488           (GTypeFlags)NULL
489           );
490     }
491 
492   return image_type;
493 }
494 /////////////////////////////////////////////////////////////////////////////
495 // End CvImageWidget
496 /////////////////////////////////////////////////////////////////////////////
497 
498 
499 struct CvWindow;
500 
501 typedef struct CvTrackbar
502 {
503     int signature;
504     GtkWidget* widget;
505     char* name;
506     CvTrackbar* next;
507     CvWindow* parent;
508     int* data;
509     int pos;
510     int maxval;
511     CvTrackbarCallback notify;
512     CvTrackbarCallback2 notify2;
513     void* userdata;
514 }
515 CvTrackbar;
516 
517 
518 typedef struct CvWindow
519 {
520     int signature;
521     GtkWidget* widget;
522     GtkWidget* frame;
523     GtkWidget* paned;
524     char* name;
525     CvWindow* prev;
526     CvWindow* next;
527 
528     int last_key;
529     int flags;
530     int status;//0 normal, 1 fullscreen (YV)
531 
532     CvMouseCallback on_mouse;
533     void* on_mouse_param;
534 
535     struct
536     {
537         int pos;
538         int rows;
539         CvTrackbar* first;
540     }
541     toolbar;
542 
543 #ifdef HAVE_OPENGL
544     bool useGl;
545 
546     CvOpenGlDrawCallback glDrawCallback;
547     void* glDrawData;
548 #endif
549 }
550 CvWindow;
551 
552 
553 static gboolean icvOnClose( GtkWidget* widget, GdkEvent* event, gpointer user_data );
554 static gboolean icvOnKeyPress( GtkWidget* widget, GdkEventKey* event, gpointer user_data );
555 static void icvOnTrackbar( GtkWidget* widget, gpointer user_data );
556 static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_data );
557 
558 #ifdef HAVE_GTHREAD
559 int thread_started=0;
560 static gpointer icvWindowThreadLoop();
561 GMutex*				   last_key_mutex;
562 GCond*				   cond_have_key;
563 GMutex*				   window_mutex;
564 GThread*			   window_thread;
565 GtkWidget*             cvTopLevelWidget = 0;
566 #endif
567 
568 static int             last_key = -1;
569 static CvWindow* hg_windows = 0;
570 
cvInitSystem(int argc,char ** argv)571 CV_IMPL int cvInitSystem( int argc, char** argv )
572 {
573     static int wasInitialized = 0;
574 
575     // check initialization status
576     if( !wasInitialized )
577     {
578         hg_windows = 0;
579 
580         gtk_init( &argc, &argv );
581         setlocale(LC_NUMERIC,"C");
582 
583         #ifdef HAVE_OPENGL
584             gtk_gl_init(&argc, &argv);
585         #endif
586 
587         wasInitialized = 1;
588     }
589 
590     return 0;
591 }
592 
cvStartWindowThread()593 CV_IMPL int cvStartWindowThread(){
594 #ifdef HAVE_GTHREAD
595     cvInitSystem(0,NULL);
596     if (!thread_started) {
597     if (!g_thread_supported ()) {
598         /* the GThread system wasn't inited, so init it */
599         g_thread_init(NULL);
600     }
601 
602     // this mutex protects the window resources
603     window_mutex = g_mutex_new();
604 
605     // protects the 'last key pressed' variable
606     last_key_mutex = g_mutex_new();
607 
608     // conditional that indicates a key has been pressed
609     cond_have_key = g_cond_new();
610 
611     // this is the window update thread
612     window_thread = g_thread_create((GThreadFunc) icvWindowThreadLoop,
613                     NULL, TRUE, NULL);
614     }
615     thread_started = window_thread!=NULL;
616     return thread_started;
617 #else
618     return 0;
619 #endif
620 }
621 
622 #ifdef HAVE_GTHREAD
icvWindowThreadLoop()623 gpointer icvWindowThreadLoop(){
624     while(1){
625         g_mutex_lock(window_mutex);
626         gtk_main_iteration_do(FALSE);
627         g_mutex_unlock(window_mutex);
628 
629         // little sleep
630         g_usleep(500);
631 
632         g_thread_yield();
633     }
634     return NULL;
635 }
636 
637 #define CV_LOCK_MUTEX() \
638 if(thread_started && g_thread_self()!=window_thread){ g_mutex_lock( window_mutex ); } else { }
639 
640 #define CV_UNLOCK_MUTEX() \
641 if(thread_started && g_thread_self()!=window_thread){ g_mutex_unlock( window_mutex); } else { }
642 
643 #else
644 #define CV_LOCK_MUTEX()
645 #define CV_UNLOCK_MUTEX()
646 #endif
647 
icvFindWindowByName(const char * name)648 static CvWindow* icvFindWindowByName( const char* name )
649 {
650     CvWindow* window = hg_windows;
651     while( window != 0 && strcmp(name, window->name) != 0 )
652         window = window->next;
653 
654     return window;
655 }
656 
icvWindowByWidget(GtkWidget * widget)657 static CvWindow* icvWindowByWidget( GtkWidget* widget )
658 {
659     CvWindow* window = hg_windows;
660 
661     while( window != 0 && window->widget != widget &&
662            window->frame != widget && window->paned != widget )
663         window = window->next;
664 
665     return window;
666 }
667 
cvGetModeWindow_GTK(const char * name)668 double cvGetModeWindow_GTK(const char* name)//YV
669 {
670     double result = -1;
671 
672     CV_FUNCNAME( "cvGetModeWindow_GTK" );
673 
674     __BEGIN__;
675 
676     CvWindow* window;
677 
678     if (!name)
679         CV_ERROR( CV_StsNullPtr, "NULL name string" );
680 
681     window = icvFindWindowByName( name );
682     if (!window)
683         CV_ERROR( CV_StsNullPtr, "NULL window" );
684 
685     CV_LOCK_MUTEX();
686     result = window->status;
687     CV_UNLOCK_MUTEX();
688 
689     __END__;
690     return result;
691 }
692 
693 
cvSetModeWindow_GTK(const char * name,double prop_value)694 void cvSetModeWindow_GTK( const char* name, double prop_value)//Yannick Verdie
695 {
696 
697     CV_FUNCNAME( "cvSetModeWindow_GTK" );
698 
699     __BEGIN__;
700 
701     CvWindow* window;
702 
703     if(!name)
704         CV_ERROR( CV_StsNullPtr, "NULL name string" );
705 
706     window = icvFindWindowByName( name );
707     if( !window )
708         CV_ERROR( CV_StsNullPtr, "NULL window" );
709 
710     if(window->flags & CV_WINDOW_AUTOSIZE)//if the flag CV_WINDOW_AUTOSIZE is set
711         EXIT;
712 
713     //so easy to do fullscreen here, Linux rocks !
714 
715     if (window->status==CV_WINDOW_FULLSCREEN && prop_value==CV_WINDOW_NORMAL)
716     {
717         CV_LOCK_MUTEX();
718         gtk_window_unfullscreen(GTK_WINDOW(window->frame));
719         window->status=CV_WINDOW_NORMAL;
720         CV_UNLOCK_MUTEX();
721         EXIT;
722     }
723 
724     if (window->status==CV_WINDOW_NORMAL && prop_value==CV_WINDOW_FULLSCREEN)
725     {
726         CV_LOCK_MUTEX();
727         gtk_window_fullscreen(GTK_WINDOW(window->frame));
728         window->status=CV_WINDOW_FULLSCREEN;
729         CV_UNLOCK_MUTEX();
730         EXIT;
731     }
732 
733     __END__;
734 }
735 
setWindowTitle(const String & winname,const String & title)736 void cv::setWindowTitle(const String& winname, const String& title)
737 {
738     CvWindow* window = icvFindWindowByName(winname.c_str());
739 
740     if (!window)
741     {
742         namedWindow(winname);
743         window = icvFindWindowByName(winname.c_str());
744     }
745 
746     if (!window)
747         CV_Error(Error::StsNullPtr, "NULL window");
748 
749     CV_LOCK_MUTEX();
750     gtk_window_set_title(GTK_WINDOW(window->frame), title.c_str());
751     CV_UNLOCK_MUTEX();
752 }
753 
cvGetPropWindowAutoSize_GTK(const char * name)754 double cvGetPropWindowAutoSize_GTK(const char* name)
755 {
756     double result = -1;
757 
758     CV_FUNCNAME( "cvGetPropWindowAutoSize_GTK" );
759 
760     __BEGIN__;
761 
762     CvWindow* window;
763 
764     if (!name)
765         CV_ERROR( CV_StsNullPtr, "NULL name string" );
766 
767     window = icvFindWindowByName( name );
768     if (!window)
769         EXIT; // keep silence here
770 
771     result = window->flags & CV_WINDOW_AUTOSIZE;
772 
773     __END__;
774 
775     return result;
776 }
777 
cvGetRatioWindow_GTK(const char * name)778 double cvGetRatioWindow_GTK(const char* name)
779 {
780     double result = -1;
781 
782     CV_FUNCNAME( "cvGetRatioWindow_GTK" );
783 
784     __BEGIN__;
785 
786     CvWindow* window;
787 
788     if (!name)
789         CV_ERROR( CV_StsNullPtr, "NULL name string" );
790 
791     window = icvFindWindowByName( name );
792     if (!window)
793         EXIT; // keep silence here
794 
795 #if defined (GTK_VERSION3)
796     result = static_cast<double>(
797         gtk_widget_get_allocated_width(window->widget)) / gtk_widget_get_allocated_height(window->widget);
798 #else
799     result = static_cast<double>(window->widget->allocation.width) / window->widget->allocation.height;
800 #endif // GTK_VERSION3
801     __END__;
802 
803     return result;
804 }
805 
cvGetOpenGlProp_GTK(const char * name)806 double cvGetOpenGlProp_GTK(const char* name)
807 {
808     double result = -1;
809 
810 #ifdef HAVE_OPENGL
811     CV_FUNCNAME( "cvGetOpenGlProp_GTK" );
812 
813     __BEGIN__;
814 
815     CvWindow* window;
816 
817     if (!name)
818         CV_ERROR( CV_StsNullPtr, "NULL name string" );
819 
820     window = icvFindWindowByName( name );
821     if (!window)
822         EXIT; // keep silence here
823 
824     result = window->useGl;
825 
826     __END__;
827 #else
828     (void)name;
829 #endif
830 
831     return result;
832 }
833 
834 
835 // OpenGL support
836 
837 #ifdef HAVE_OPENGL
838 
839 namespace
840 {
createGlContext(CvWindow * window)841     void createGlContext(CvWindow* window)
842     {
843         GdkGLConfig* glconfig;
844 
845         CV_FUNCNAME( "createGlContext" );
846 
847         __BEGIN__;
848 
849         // Try double-buffered visual
850         glconfig = gdk_gl_config_new_by_mode((GdkGLConfigMode)(GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE));
851         if (!glconfig)
852             CV_ERROR( CV_OpenGlApiCallError, "Can't Create A GL Device Context" );
853 
854         // Set OpenGL-capability to the widget
855         if (!gtk_widget_set_gl_capability(window->widget, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE))
856             CV_ERROR( CV_OpenGlApiCallError, "Can't Create A GL Device Context" );
857 
858         window->useGl = true;
859 
860         __END__;
861     }
862 
drawGl(CvWindow * window)863     void drawGl(CvWindow* window)
864     {
865         CV_FUNCNAME( "drawGl" );
866 
867         __BEGIN__;
868 
869         GdkGLContext* glcontext = gtk_widget_get_gl_context(window->widget);
870         GdkGLDrawable* gldrawable = gtk_widget_get_gl_drawable(window->widget);
871 
872         if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
873             CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
874 
875         glViewport(0, 0, window->widget->allocation.width, window->widget->allocation.height);
876 
877         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
878 
879         if (window->glDrawCallback)
880             window->glDrawCallback(window->glDrawData);
881 
882         if (gdk_gl_drawable_is_double_buffered (gldrawable))
883             gdk_gl_drawable_swap_buffers(gldrawable);
884         else
885             glFlush();
886 
887         gdk_gl_drawable_gl_end(gldrawable);
888 
889         __END__;
890     }
891 }
892 
893 #endif // HAVE_OPENGL
894 
895 #if defined (GTK_VERSION3)
cvImageWidget_draw(GtkWidget * widget,cairo_t * cr,gpointer data)896 static gboolean cvImageWidget_draw(GtkWidget* widget, cairo_t *cr, gpointer data)
897 {
898 #ifdef HAVE_OPENGL
899     CvWindow* window = (CvWindow*)data;
900 
901     if (window->useGl)
902     {
903         drawGl(window);
904         return TRUE;
905     }
906 #else
907     (void)data;
908 #endif
909 
910   CvImageWidget *image_widget = NULL;
911   GdkPixbuf *pixbuf = NULL;
912 
913   g_return_val_if_fail (widget != NULL, FALSE);
914   g_return_val_if_fail (CV_IS_IMAGE_WIDGET (widget), FALSE);
915 
916   image_widget = CV_IMAGE_WIDGET (widget);
917 
918   if( image_widget->scaled_image ){
919       // center image in available region
920       int x0 = (gtk_widget_get_allocated_width(widget) - image_widget->scaled_image->cols)/2;
921       int y0 = (gtk_widget_get_allocated_height(widget) - image_widget->scaled_image->rows)/2;
922 
923       pixbuf = gdk_pixbuf_new_from_data(image_widget->scaled_image->data.ptr, GDK_COLORSPACE_RGB, false,
924           8, MIN(image_widget->scaled_image->cols, gtk_widget_get_allocated_width(widget)),
925           MIN(image_widget->scaled_image->rows, gtk_widget_get_allocated_height(widget)),
926           image_widget->scaled_image->step, NULL, NULL);
927 
928       gdk_cairo_set_source_pixbuf(cr, pixbuf, x0, y0);
929   }
930   else if( image_widget->original_image ){
931       pixbuf = gdk_pixbuf_new_from_data(image_widget->original_image->data.ptr, GDK_COLORSPACE_RGB, false,
932           8, MIN(image_widget->original_image->cols, gtk_widget_get_allocated_width(widget)),
933           MIN(image_widget->original_image->rows, gtk_widget_get_allocated_height(widget)),
934           image_widget->original_image->step, NULL, NULL);
935       gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
936   }
937 
938   cairo_paint(cr);
939   g_object_unref(pixbuf);
940   return TRUE;
941 }
942 
943 #else
cvImageWidget_expose(GtkWidget * widget,GdkEventExpose * event,gpointer data)944 static gboolean cvImageWidget_expose(GtkWidget* widget, GdkEventExpose* event, gpointer data)
945 {
946 #ifdef HAVE_OPENGL
947     CvWindow* window = (CvWindow*)data;
948 
949     if (window->useGl)
950     {
951         drawGl(window);
952         return TRUE;
953     }
954 #else
955     (void)data;
956 #endif
957 
958   CvImageWidget *image_widget = NULL;
959   cairo_t *cr = NULL;
960   GdkPixbuf *pixbuf = NULL;
961 
962   g_return_val_if_fail (widget != NULL, FALSE);
963   g_return_val_if_fail (CV_IS_IMAGE_WIDGET (widget), FALSE);
964   g_return_val_if_fail (event != NULL, FALSE);
965 
966   if (event->count > 0)
967     return FALSE;
968 
969   cr = gdk_cairo_create(widget->window);
970   image_widget = CV_IMAGE_WIDGET (widget);
971 
972   if( image_widget->scaled_image ){
973       // center image in available region
974       int x0 = (widget->allocation.width - image_widget->scaled_image->cols)/2;
975       int y0 = (widget->allocation.height - image_widget->scaled_image->rows)/2;
976 
977       pixbuf = gdk_pixbuf_new_from_data(image_widget->scaled_image->data.ptr, GDK_COLORSPACE_RGB, false,
978           8, MIN(image_widget->scaled_image->cols, widget->allocation.width),
979           MIN(image_widget->scaled_image->rows, widget->allocation.height),
980           image_widget->scaled_image->step, NULL, NULL);
981 
982       gdk_cairo_set_source_pixbuf(cr, pixbuf, x0, y0);
983   }
984   else if( image_widget->original_image ){
985       pixbuf = gdk_pixbuf_new_from_data(image_widget->original_image->data.ptr, GDK_COLORSPACE_RGB, false,
986           8, MIN(image_widget->original_image->cols, widget->allocation.width),
987           MIN(image_widget->original_image->rows, widget->allocation.height),
988           image_widget->original_image->step, NULL, NULL);
989       gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
990   }
991 
992   cairo_paint(cr);
993   g_object_unref(pixbuf);
994   cairo_destroy(cr);
995   return TRUE;
996 }
997 #endif //GTK_VERSION3
998 
cvNamedWindow(const char * name,int flags)999 CV_IMPL int cvNamedWindow( const char* name, int flags )
1000 {
1001     int result = 0;
1002     CV_FUNCNAME( "cvNamedWindow" );
1003 
1004     __BEGIN__;
1005 
1006     CvWindow* window;
1007     int len;
1008 
1009     cvInitSystem(1,(char**)&name);
1010     if( !name )
1011         CV_ERROR( CV_StsNullPtr, "NULL name string" );
1012 
1013     // Check the name in the storage
1014     if( icvFindWindowByName( name ) != 0 )
1015     {
1016         result = 1;
1017         EXIT;
1018     }
1019 
1020     len = strlen(name);
1021     CV_CALL( window = (CvWindow*)cvAlloc(sizeof(CvWindow) + len + 1));
1022     memset( window, 0, sizeof(*window));
1023     window->name = (char*)(window + 1);
1024     memcpy( window->name, name, len + 1 );
1025     window->flags = flags;
1026     window->signature = CV_WINDOW_MAGIC_VAL;
1027     window->last_key = 0;
1028     window->on_mouse = 0;
1029     window->on_mouse_param = 0;
1030     memset( &window->toolbar, 0, sizeof(window->toolbar));
1031     window->next = hg_windows;
1032     window->prev = 0;
1033     window->status = CV_WINDOW_NORMAL;//YV
1034 
1035     CV_LOCK_MUTEX();
1036 
1037     window->frame = gtk_window_new( GTK_WINDOW_TOPLEVEL );
1038 
1039     window->paned = gtk_vbox_new( FALSE, 0 );
1040     window->widget = cvImageWidgetNew( flags );
1041     gtk_box_pack_end( GTK_BOX(window->paned), window->widget, TRUE, TRUE, 0 );
1042     gtk_widget_show( window->widget );
1043     gtk_container_add( GTK_CONTAINER(window->frame), window->paned );
1044     gtk_widget_show( window->paned );
1045 
1046 #ifndef HAVE_OPENGL
1047     if (flags & CV_WINDOW_OPENGL)
1048         CV_ERROR( CV_OpenGlNotSupported, "Library was built without OpenGL support" );
1049 #else
1050     if (flags & CV_WINDOW_OPENGL)
1051         createGlContext(window);
1052 
1053     window->glDrawCallback = 0;
1054     window->glDrawData = 0;
1055 #endif
1056 
1057     //
1058     // configure event handlers
1059     // TODO -- move this to CvImageWidget ?
1060     g_signal_connect( window->frame, "key-press-event",
1061                         G_CALLBACK(icvOnKeyPress), window );
1062     g_signal_connect( window->widget, "button-press-event",
1063                         G_CALLBACK(icvOnMouse), window );
1064     g_signal_connect( window->widget, "button-release-event",
1065                         G_CALLBACK(icvOnMouse), window );
1066     g_signal_connect( window->widget, "motion-notify-event",
1067                         G_CALLBACK(icvOnMouse), window );
1068     g_signal_connect( window->frame, "delete-event",
1069                         G_CALLBACK(icvOnClose), window );
1070 #if defined(GTK_VERSION3)
1071     g_signal_connect( window->widget, "draw",
1072                         G_CALLBACK(cvImageWidget_draw), window );
1073 #else
1074     g_signal_connect( window->widget, "expose-event",
1075                         G_CALLBACK(cvImageWidget_expose), window );
1076 #endif //GTK_VERSION3
1077 
1078     gtk_widget_add_events (window->widget, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK) ;
1079 
1080     gtk_widget_show( window->frame );
1081     gtk_window_set_title( GTK_WINDOW(window->frame), name );
1082 
1083     if( hg_windows )
1084         hg_windows->prev = window;
1085     hg_windows = window;
1086 
1087     gtk_window_set_resizable( GTK_WINDOW(window->frame), (flags & CV_WINDOW_AUTOSIZE) == 0 );
1088 
1089 
1090     // allow window to be resized
1091     if( (flags & CV_WINDOW_AUTOSIZE)==0 ){
1092         GdkGeometry geometry;
1093         geometry.min_width = 50;
1094         geometry.min_height = 50;
1095         gtk_window_set_geometry_hints( GTK_WINDOW( window->frame ), GTK_WIDGET( window->widget ),
1096             &geometry, (GdkWindowHints) (GDK_HINT_MIN_SIZE));
1097     }
1098 
1099     CV_UNLOCK_MUTEX();
1100 
1101 #ifdef HAVE_OPENGL
1102     if (window->useGl)
1103         cvSetOpenGlContext(name);
1104 #endif
1105 
1106     result = 1;
1107     __END__;
1108 
1109     return result;
1110 }
1111 
1112 
1113 #ifdef HAVE_OPENGL
1114 
cvSetOpenGlContext(const char * name)1115 CV_IMPL void cvSetOpenGlContext(const char* name)
1116 {
1117     CvWindow* window;
1118     GdkGLContext* glcontext;
1119     GdkGLDrawable* gldrawable;
1120 
1121     CV_FUNCNAME( "cvSetOpenGlContext" );
1122 
1123     __BEGIN__;
1124 
1125     if(!name)
1126         CV_ERROR( CV_StsNullPtr, "NULL name string" );
1127 
1128     window = icvFindWindowByName( name );
1129     if (!window)
1130         CV_ERROR( CV_StsNullPtr, "NULL window" );
1131 
1132     if (!window->useGl)
1133         CV_ERROR( CV_OpenGlNotSupported, "Window doesn't support OpenGL" );
1134 
1135     glcontext = gtk_widget_get_gl_context(window->widget);
1136     gldrawable = gtk_widget_get_gl_drawable(window->widget);
1137 
1138     if (!gdk_gl_drawable_make_current(gldrawable, glcontext))
1139         CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
1140 
1141     __END__;
1142 }
1143 
cvUpdateWindow(const char * name)1144 CV_IMPL void cvUpdateWindow(const char* name)
1145 {
1146     CV_FUNCNAME( "cvUpdateWindow" );
1147 
1148     __BEGIN__;
1149 
1150     CvWindow* window;
1151 
1152     if (!name)
1153         CV_ERROR( CV_StsNullPtr, "NULL name string" );
1154 
1155     window = icvFindWindowByName( name );
1156     if (!window)
1157         EXIT;
1158 
1159     // window does not refresh without this
1160     gtk_widget_queue_draw( GTK_WIDGET(window->widget) );
1161 
1162     __END__;
1163 }
1164 
cvSetOpenGlDrawCallback(const char * name,CvOpenGlDrawCallback callback,void * userdata)1165 CV_IMPL void cvSetOpenGlDrawCallback(const char* name, CvOpenGlDrawCallback callback, void* userdata)
1166 {
1167     CvWindow* window;
1168 
1169     CV_FUNCNAME( "cvCreateOpenGLCallback" );
1170 
1171     __BEGIN__;
1172 
1173     if(!name)
1174         CV_ERROR( CV_StsNullPtr, "NULL name string" );
1175 
1176     window = icvFindWindowByName( name );
1177     if( !window )
1178         EXIT;
1179 
1180     if (!window->useGl)
1181         CV_ERROR( CV_OpenGlNotSupported, "Window was created without OpenGL context" );
1182 
1183     window->glDrawCallback = callback;
1184     window->glDrawData = userdata;
1185 
1186     __END__;
1187 }
1188 
1189 #endif // HAVE_OPENGL
1190 
1191 
1192 
1193 
icvDeleteWindow(CvWindow * window)1194 static void icvDeleteWindow( CvWindow* window )
1195 {
1196     CvTrackbar* trackbar;
1197 
1198     if( window->prev )
1199         window->prev->next = window->next;
1200     else
1201         hg_windows = window->next;
1202 
1203     if( window->next )
1204         window->next->prev = window->prev;
1205 
1206     window->prev = window->next = 0;
1207 
1208     gtk_widget_destroy( window->frame );
1209 
1210     for( trackbar = window->toolbar.first; trackbar != 0; )
1211     {
1212         CvTrackbar* next = trackbar->next;
1213         cvFree( &trackbar );
1214         trackbar = next;
1215     }
1216 
1217     cvFree( &window );
1218 #ifdef HAVE_GTHREAD
1219     // if last window, send key press signal
1220     // to jump out of any waiting cvWaitKey's
1221     if(hg_windows==0 && thread_started){
1222         g_cond_broadcast(cond_have_key);
1223     }
1224 #endif
1225 }
1226 
1227 
cvDestroyWindow(const char * name)1228 CV_IMPL void cvDestroyWindow( const char* name )
1229 {
1230     CV_FUNCNAME( "cvDestroyWindow" );
1231 
1232     __BEGIN__;
1233 
1234     CvWindow* window;
1235 
1236     if(!name)
1237         CV_ERROR( CV_StsNullPtr, "NULL name string" );
1238 
1239     window = icvFindWindowByName( name );
1240     if( !window )
1241         EXIT;
1242 
1243     // note that it is possible for the update thread to run this function
1244     // if there is a call to cvShowImage in a mouse callback
1245     // (this would produce a deadlock on window_mutex)
1246     CV_LOCK_MUTEX();
1247 
1248     icvDeleteWindow( window );
1249 
1250     CV_UNLOCK_MUTEX();
1251 
1252     __END__;
1253 }
1254 
1255 
1256 CV_IMPL void
cvDestroyAllWindows(void)1257 cvDestroyAllWindows( void )
1258 {
1259     CV_LOCK_MUTEX();
1260 
1261     while( hg_windows )
1262     {
1263         CvWindow* window = hg_windows;
1264         icvDeleteWindow( window );
1265     }
1266     CV_UNLOCK_MUTEX();
1267 }
1268 
1269 // CvSize icvCalcOptimalWindowSize( CvWindow * window, CvSize new_image_size){
1270 //     CvSize window_size;
1271 //     GtkWidget * toplevel = gtk_widget_get_toplevel( window->frame );
1272 //     gdk_drawable_get_size( GDK_DRAWABLE(toplevel->window),
1273 //             &window_size.width, &window_size.height );
1274 
1275 //     window_size.width = window_size.width + new_image_size.width - window->widget->allocation.width;
1276 //     window_size.height = window_size.height + new_image_size.height - window->widget->allocation.height;
1277 
1278 //     return window_size;
1279 // }
1280 
1281 CV_IMPL void
cvShowImage(const char * name,const CvArr * arr)1282 cvShowImage( const char* name, const CvArr* arr )
1283 {
1284     CV_FUNCNAME( "cvShowImage" );
1285 
1286     __BEGIN__;
1287 
1288     CvWindow* window;
1289 
1290     if( !name )
1291         CV_ERROR( CV_StsNullPtr, "NULL name" );
1292 
1293     CV_LOCK_MUTEX();
1294 
1295     window = icvFindWindowByName(name);
1296     if(!window)
1297     {
1298         cvNamedWindow(name, 1);
1299         window = icvFindWindowByName(name);
1300     }
1301 
1302     if( window && arr )
1303     {
1304     #ifdef HAVE_OPENGL
1305         if (window->useGl)
1306         {
1307             cv::imshow(name, cv::cvarrToMat(arr));
1308             return;
1309         }
1310     #endif
1311 
1312         CvImageWidget * image_widget = CV_IMAGE_WIDGET( window->widget );
1313         cvImageWidgetSetImage( image_widget, arr );
1314     }
1315 
1316     CV_UNLOCK_MUTEX();
1317 
1318     __END__;
1319 }
1320 
cvResizeWindow(const char * name,int width,int height)1321 CV_IMPL void cvResizeWindow(const char* name, int width, int height )
1322 {
1323     CV_FUNCNAME( "cvResizeWindow" );
1324 
1325     __BEGIN__;
1326 
1327     CvWindow* window;
1328     CvImageWidget * image_widget;
1329 
1330     if( !name )
1331         CV_ERROR( CV_StsNullPtr, "NULL name" );
1332 
1333     window = icvFindWindowByName(name);
1334     if(!window)
1335         EXIT;
1336 
1337     image_widget = CV_IMAGE_WIDGET( window->widget );
1338     //if(image_widget->flags & CV_WINDOW_AUTOSIZE)
1339         //EXIT;
1340 
1341     CV_LOCK_MUTEX();
1342 
1343     gtk_window_set_resizable( GTK_WINDOW(window->frame), 1 );
1344     gtk_window_resize( GTK_WINDOW(window->frame), width, height );
1345 
1346     // disable initial resize since presumably user wants to keep
1347     // this window size
1348     image_widget->flags &= ~CV_WINDOW_NO_IMAGE;
1349 
1350     CV_UNLOCK_MUTEX();
1351 
1352     __END__;
1353 }
1354 
1355 
cvMoveWindow(const char * name,int x,int y)1356 CV_IMPL void cvMoveWindow( const char* name, int x, int y )
1357 {
1358     CV_FUNCNAME( "cvMoveWindow" );
1359 
1360     __BEGIN__;
1361 
1362     CvWindow* window;
1363 
1364     if( !name )
1365         CV_ERROR( CV_StsNullPtr, "NULL name" );
1366 
1367     window = icvFindWindowByName(name);
1368     if(!window)
1369         EXIT;
1370 
1371     CV_LOCK_MUTEX();
1372 
1373     gtk_window_move( GTK_WINDOW(window->frame), x, y );
1374 
1375     CV_UNLOCK_MUTEX();
1376 
1377     __END__;
1378 }
1379 
1380 
1381 static CvTrackbar*
icvFindTrackbarByName(const CvWindow * window,const char * name)1382 icvFindTrackbarByName( const CvWindow* window, const char* name )
1383 {
1384     CvTrackbar* trackbar = window->toolbar.first;
1385 
1386     for( ; trackbar != 0 && strcmp( trackbar->name, name ) != 0; trackbar = trackbar->next )
1387         ;
1388 
1389     return trackbar;
1390 }
1391 
1392 static int
icvCreateTrackbar(const char * trackbar_name,const char * window_name,int * val,int count,CvTrackbarCallback on_notify,CvTrackbarCallback2 on_notify2,void * userdata)1393 icvCreateTrackbar( const char* trackbar_name, const char* window_name,
1394                    int* val, int count, CvTrackbarCallback on_notify,
1395                    CvTrackbarCallback2 on_notify2, void* userdata )
1396 {
1397     int result = 0;
1398 
1399     CV_FUNCNAME( "icvCreateTrackbar" );
1400 
1401     __BEGIN__;
1402 
1403     /*char slider_name[32];*/
1404     CvWindow* window = 0;
1405     CvTrackbar* trackbar = 0;
1406 
1407     if( !window_name || !trackbar_name )
1408         CV_ERROR( CV_StsNullPtr, "NULL window or trackbar name" );
1409 
1410     if( count <= 0 )
1411         CV_ERROR( CV_StsOutOfRange, "Bad trackbar maximal value" );
1412 
1413     window = icvFindWindowByName(window_name);
1414     if( !window )
1415         EXIT;
1416 
1417     trackbar = icvFindTrackbarByName(window,trackbar_name);
1418 
1419     CV_LOCK_MUTEX();
1420 
1421     if( !trackbar )
1422     {
1423         int len = strlen(trackbar_name);
1424         trackbar = (CvTrackbar*)cvAlloc(sizeof(CvTrackbar) + len + 1);
1425         memset( trackbar, 0, sizeof(*trackbar));
1426         trackbar->signature = CV_TRACKBAR_MAGIC_VAL;
1427         trackbar->name = (char*)(trackbar+1);
1428         memcpy( trackbar->name, trackbar_name, len + 1 );
1429         trackbar->parent = window;
1430         trackbar->next = window->toolbar.first;
1431         window->toolbar.first = trackbar;
1432 
1433         GtkWidget* hscale_box = gtk_hbox_new( FALSE, 10 );
1434         GtkWidget* hscale_label = gtk_label_new( trackbar_name );
1435         GtkWidget* hscale = gtk_hscale_new_with_range( 0, count, 1 );
1436         gtk_scale_set_digits( GTK_SCALE(hscale), 0 );
1437         //gtk_scale_set_value_pos( hscale, GTK_POS_TOP );
1438         gtk_scale_set_draw_value( GTK_SCALE(hscale), TRUE );
1439 
1440         trackbar->widget = hscale;
1441         gtk_box_pack_start( GTK_BOX(hscale_box), hscale_label, FALSE, FALSE, 5 );
1442         gtk_widget_show( hscale_label );
1443         gtk_box_pack_start( GTK_BOX(hscale_box), hscale, TRUE, TRUE, 5 );
1444         gtk_widget_show( hscale );
1445         gtk_box_pack_start( GTK_BOX(window->paned), hscale_box, FALSE, FALSE, 5 );
1446         gtk_widget_show( hscale_box );
1447 
1448     }
1449 
1450     if( val )
1451     {
1452         int value = *val;
1453         if( value < 0 )
1454             value = 0;
1455         if( value > count )
1456             value = count;
1457         gtk_range_set_value( GTK_RANGE(trackbar->widget), value );
1458         trackbar->pos = value;
1459         trackbar->data = val;
1460     }
1461 
1462     trackbar->maxval = count;
1463     trackbar->notify = on_notify;
1464     trackbar->notify2 = on_notify2;
1465     trackbar->userdata = userdata;
1466     g_signal_connect( trackbar->widget, "value-changed",
1467                         G_CALLBACK(icvOnTrackbar), trackbar );
1468 
1469     // queue a widget resize to trigger a window resize to
1470     // compensate for the addition of trackbars
1471     gtk_widget_queue_resize( GTK_WIDGET(window->widget) );
1472 
1473 
1474     CV_UNLOCK_MUTEX();
1475 
1476     result = 1;
1477 
1478     __END__;
1479 
1480     return result;
1481 }
1482 
1483 
1484 CV_IMPL int
cvCreateTrackbar(const char * trackbar_name,const char * window_name,int * val,int count,CvTrackbarCallback on_notify)1485 cvCreateTrackbar( const char* trackbar_name, const char* window_name,
1486                   int* val, int count, CvTrackbarCallback on_notify )
1487 {
1488     return icvCreateTrackbar(trackbar_name, window_name, val, count,
1489                              on_notify, 0, 0);
1490 }
1491 
1492 
1493 CV_IMPL int
cvCreateTrackbar2(const char * trackbar_name,const char * window_name,int * val,int count,CvTrackbarCallback2 on_notify2,void * userdata)1494 cvCreateTrackbar2( const char* trackbar_name, const char* window_name,
1495                    int* val, int count, CvTrackbarCallback2 on_notify2,
1496                    void* userdata )
1497 {
1498     return icvCreateTrackbar(trackbar_name, window_name, val, count,
1499                              0, on_notify2, userdata);
1500 }
1501 
1502 
1503 CV_IMPL void
cvSetMouseCallback(const char * window_name,CvMouseCallback on_mouse,void * param)1504 cvSetMouseCallback( const char* window_name, CvMouseCallback on_mouse, void* param )
1505 {
1506     CV_FUNCNAME( "cvSetMouseCallback" );
1507 
1508     __BEGIN__;
1509 
1510     CvWindow* window = 0;
1511 
1512     if( !window_name )
1513         CV_ERROR( CV_StsNullPtr, "NULL window name" );
1514 
1515     window = icvFindWindowByName(window_name);
1516     if( !window )
1517         EXIT;
1518 
1519     window->on_mouse = on_mouse;
1520     window->on_mouse_param = param;
1521 
1522     __END__;
1523 }
1524 
1525 
cvGetTrackbarPos(const char * trackbar_name,const char * window_name)1526 CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name )
1527 {
1528     int pos = -1;
1529 
1530     CV_FUNCNAME( "cvGetTrackbarPos" );
1531 
1532     __BEGIN__;
1533 
1534     CvWindow* window;
1535     CvTrackbar* trackbar = 0;
1536 
1537     if( trackbar_name == 0 || window_name == 0 )
1538         CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
1539 
1540     window = icvFindWindowByName( window_name );
1541     if( window )
1542         trackbar = icvFindTrackbarByName( window, trackbar_name );
1543 
1544     if( trackbar )
1545         pos = trackbar->pos;
1546 
1547     __END__;
1548 
1549     return pos;
1550 }
1551 
1552 
cvSetTrackbarPos(const char * trackbar_name,const char * window_name,int pos)1553 CV_IMPL void cvSetTrackbarPos( const char* trackbar_name, const char* window_name, int pos )
1554 {
1555     CV_FUNCNAME( "cvSetTrackbarPos" );
1556 
1557     __BEGIN__;
1558 
1559     CvWindow* window;
1560     CvTrackbar* trackbar = 0;
1561 
1562     if( trackbar_name == 0 || window_name == 0 )
1563         CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
1564 
1565     window = icvFindWindowByName( window_name );
1566     if( window )
1567         trackbar = icvFindTrackbarByName( window, trackbar_name );
1568 
1569     if( trackbar )
1570     {
1571         if( pos < 0 )
1572             pos = 0;
1573 
1574         if( pos > trackbar->maxval )
1575             pos = trackbar->maxval;
1576     }
1577 
1578     CV_LOCK_MUTEX();
1579 
1580     gtk_range_set_value( GTK_RANGE(trackbar->widget), pos );
1581 
1582     CV_UNLOCK_MUTEX();
1583 
1584     __END__;
1585 }
1586 
1587 
cvSetTrackbarMax(const char * trackbar_name,const char * window_name,int maxval)1588 CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval)
1589 {
1590     CV_FUNCNAME("cvSetTrackbarMax");
1591 
1592     __BEGIN__;
1593 
1594     if (maxval >= 0)
1595     {
1596         CvWindow* window = 0;
1597         CvTrackbar* trackbar = 0;
1598 
1599         if (trackbar_name == 0 || window_name == 0)
1600         {
1601             CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name");
1602         }
1603 
1604         window = icvFindWindowByName( window_name );
1605         if (window)
1606         {
1607             trackbar = icvFindTrackbarByName(window, trackbar_name);
1608             if (trackbar)
1609             {
1610                 trackbar->maxval = maxval;
1611 
1612                 CV_LOCK_MUTEX();
1613 
1614                 gtk_range_set_range(GTK_RANGE(trackbar->widget), 0, trackbar->maxval);
1615 
1616                 CV_UNLOCK_MUTEX();
1617             }
1618         }
1619     }
1620 
1621     __END__;
1622 }
1623 
1624 
cvGetWindowHandle(const char * window_name)1625 CV_IMPL void* cvGetWindowHandle( const char* window_name )
1626 {
1627     void* widget = 0;
1628 
1629     CV_FUNCNAME( "cvGetWindowHandle" );
1630 
1631     __BEGIN__;
1632 
1633     CvWindow* window;
1634 
1635     if( window_name == 0 )
1636         CV_ERROR( CV_StsNullPtr, "NULL window name" );
1637 
1638     window = icvFindWindowByName( window_name );
1639     if( window )
1640         widget = (void*)window->widget;
1641 
1642     __END__;
1643 
1644     return widget;
1645 }
1646 
1647 
cvGetWindowName(void * window_handle)1648 CV_IMPL const char* cvGetWindowName( void* window_handle )
1649 {
1650     const char* window_name = "";
1651 
1652     CV_FUNCNAME( "cvGetWindowName" );
1653 
1654     __BEGIN__;
1655 
1656     CvWindow* window;
1657 
1658     if( window_handle == 0 )
1659         CV_ERROR( CV_StsNullPtr, "NULL window" );
1660 
1661     window = icvWindowByWidget( (GtkWidget*)window_handle );
1662     if( window )
1663         window_name = window->name;
1664 
1665     __END__;
1666 
1667     return window_name;
1668 }
1669 
icvMakeGtkFilter(const char * name,const char * patterns,GtkFileFilter * images)1670 static GtkFileFilter* icvMakeGtkFilter(const char* name, const char* patterns, GtkFileFilter* images)
1671 {
1672     GtkFileFilter* filter = gtk_file_filter_new();
1673     gtk_file_filter_set_name(filter, name);
1674 
1675     while(patterns[0])
1676     {
1677         gtk_file_filter_add_pattern(filter, patterns);
1678         gtk_file_filter_add_pattern(images, patterns);
1679         patterns += strlen(patterns) + 1;
1680     }
1681 
1682     return filter;
1683 }
1684 
icvShowSaveAsDialog(GtkWidget * widget,CvWindow * window)1685 static void icvShowSaveAsDialog(GtkWidget* widget, CvWindow* window)
1686 {
1687     if (!window || !widget)
1688         return;
1689 
1690     CvImageWidget* image_widget = CV_IMAGE_WIDGET(window->widget);
1691     if (!image_widget || !image_widget->original_image)
1692         return;
1693 
1694     GtkWidget* dialog = gtk_file_chooser_dialog_new("Save As...",
1695                       GTK_WINDOW(widget),
1696                       GTK_FILE_CHOOSER_ACTION_SAVE,
1697                       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1698                       GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
1699                       NULL);
1700     gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
1701 
1702     cv::String sname = gtk_window_get_title(GTK_WINDOW(window->frame));
1703     sname = sname.substr(sname.find_last_of("\\/") + 1) + ".png";
1704     gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), sname.c_str());
1705 
1706     GtkFileFilter* filter_all = gtk_file_filter_new();
1707     gtk_file_filter_set_name(filter_all, "All Files");
1708     gtk_file_filter_add_pattern(filter_all, "*");
1709 
1710     GtkFileFilter* filter_images = gtk_file_filter_new();
1711     gtk_file_filter_set_name(filter_images, "All Images");
1712 
1713     GtkFileFilter* file_filters[] = {
1714         icvMakeGtkFilter("Portable Network Graphics files (*.png)",               "*.png\0",                             filter_images),
1715         icvMakeGtkFilter("JPEG files (*.jpeg;*.jpg;*.jpe)",                       "*.jpeg\0*.jpg\0*.jpe\0",              filter_images),
1716         icvMakeGtkFilter("Windows bitmap (*.bmp;*.dib)",                          "*.bmp\0*.dib\0",                      filter_images),
1717         icvMakeGtkFilter("TIFF Files (*.tiff;*.tif)",                             "*.tiff\0*.tif\0",                     filter_images),
1718         icvMakeGtkFilter("JPEG-2000 files (*.jp2)",                               "*.jp2\0",                             filter_images),
1719         icvMakeGtkFilter("WebP files (*.webp)",                                   "*.webp\0",                            filter_images),
1720         icvMakeGtkFilter("Portable image format (*.pbm;*.pgm;*.ppm;*.pxm;*.pnm)", "*.pbm\0*.pgm\0*.ppm\0*.pxm\0*.pnm\0", filter_images),
1721         icvMakeGtkFilter("OpenEXR Image files (*.exr)",                           "*.exr\0",                             filter_images),
1722         icvMakeGtkFilter("Radiance HDR (*.hdr;*.pic)",                            "*.hdr\0*.pic\0",                      filter_images),
1723         icvMakeGtkFilter("Sun raster files (*.sr;*.ras)",                         "*.sr\0*.ras\0",                       filter_images),
1724         filter_images,
1725         filter_all
1726     };
1727 
1728     for (size_t idx = 0; idx < sizeof(file_filters)/sizeof(file_filters[0]); ++idx)
1729         gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), file_filters[idx]);
1730     gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter_images);
1731 
1732     cv::String filename;
1733     if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1734     {
1735         char* fname = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
1736         filename = fname;
1737         g_free(fname);
1738     }
1739     gtk_widget_destroy(dialog);
1740 
1741     if (!filename.empty())
1742     {
1743         cv::Mat bgr;
1744         cv::cvtColor(cv::cvarrToMat(image_widget->original_image), bgr, cv::COLOR_RGB2BGR);
1745         cv::imwrite(filename, bgr);
1746     }
1747 }
1748 
1749 #if defined (GTK_VERSION3)
1750 #define GDK_Escape GDK_KEY_Escape
1751 #define GDK_Return GDK_KEY_Return
1752 #define GDK_Linefeed GDK_KEY_Linefeed
1753 #define GDK_Tab GDK_KEY_Tab
1754 #define GDK_s GDK_KEY_s
1755 #define GDK_S GDK_KEY_S
1756 #endif //GTK_VERSION3
1757 
icvOnKeyPress(GtkWidget * widget,GdkEventKey * event,gpointer user_data)1758 static gboolean icvOnKeyPress(GtkWidget* widget, GdkEventKey* event, gpointer user_data)
1759 {
1760     int code = 0;
1761 
1762     if ( (event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK && (event->keyval == GDK_s || event->keyval == GDK_S))
1763     {
1764         try
1765         {
1766             icvShowSaveAsDialog(widget, (CvWindow*)user_data);
1767         }
1768         catch(...)
1769         {
1770             // suppress all exceptions here
1771         }
1772     }
1773 
1774     switch( event->keyval )
1775     {
1776     case GDK_Escape:
1777         code = 27;
1778         break;
1779     case GDK_Return:
1780     case GDK_Linefeed:
1781         code = '\n';
1782         break;
1783     case GDK_Tab:
1784         code = '\t';
1785     break;
1786     default:
1787         code = event->keyval;
1788     }
1789 
1790     code |= event->state << 16;
1791 
1792 #ifdef HAVE_GTHREAD
1793     if(thread_started) g_mutex_lock(last_key_mutex);
1794 #endif
1795 
1796     last_key = code;
1797 
1798 #ifdef HAVE_GTHREAD
1799     if(thread_started){
1800         // signal any waiting threads
1801         g_cond_broadcast(cond_have_key);
1802         g_mutex_unlock(last_key_mutex);
1803     }
1804 #endif
1805 
1806     return FALSE;
1807 }
1808 
1809 
icvOnTrackbar(GtkWidget * widget,gpointer user_data)1810 static void icvOnTrackbar( GtkWidget* widget, gpointer user_data )
1811 {
1812     int pos = cvRound( gtk_range_get_value(GTK_RANGE(widget)));
1813     CvTrackbar* trackbar = (CvTrackbar*)user_data;
1814 
1815     if( trackbar && trackbar->signature == CV_TRACKBAR_MAGIC_VAL &&
1816         trackbar->widget == widget )
1817     {
1818         trackbar->pos = pos;
1819         if( trackbar->data )
1820             *trackbar->data = pos;
1821         if( trackbar->notify2 )
1822             trackbar->notify2(pos, trackbar->userdata);
1823         else if( trackbar->notify )
1824             trackbar->notify(pos);
1825     }
1826 }
1827 
icvOnClose(GtkWidget * widget,GdkEvent *,gpointer user_data)1828 static gboolean icvOnClose( GtkWidget* widget, GdkEvent* /*event*/, gpointer user_data )
1829 {
1830     CvWindow* window = (CvWindow*)user_data;
1831     if( window->signature == CV_WINDOW_MAGIC_VAL &&
1832         window->frame == widget )
1833     {
1834         icvDeleteWindow(window);
1835     }
1836     return TRUE;
1837 }
1838 
1839 
icvOnMouse(GtkWidget * widget,GdkEvent * event,gpointer user_data)1840 static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_data )
1841 {
1842     // TODO move this logic to CvImageWidget
1843     CvWindow* window = (CvWindow*)user_data;
1844     CvPoint2D32f pt32f(-1., -1.);
1845     CvPoint pt(-1,-1);
1846     int cv_event = -1, state = 0;
1847     CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget );
1848 
1849     if( window->signature != CV_WINDOW_MAGIC_VAL ||
1850         window->widget != widget || !window->widget ||
1851         !window->on_mouse /*|| !image_widget->original_image*/)
1852         return FALSE;
1853 
1854     if( event->type == GDK_MOTION_NOTIFY )
1855     {
1856         GdkEventMotion* event_motion = (GdkEventMotion*)event;
1857 
1858         cv_event = CV_EVENT_MOUSEMOVE;
1859         pt32f.x = cvRound(event_motion->x);
1860         pt32f.y = cvRound(event_motion->y);
1861         state = event_motion->state;
1862     }
1863     else if( event->type == GDK_BUTTON_PRESS ||
1864              event->type == GDK_BUTTON_RELEASE ||
1865              event->type == GDK_2BUTTON_PRESS )
1866     {
1867         GdkEventButton* event_button = (GdkEventButton*)event;
1868         pt32f.x = cvRound(event_button->x);
1869         pt32f.y = cvRound(event_button->y);
1870 
1871 
1872         if( event_button->type == GDK_BUTTON_PRESS )
1873         {
1874             cv_event = event_button->button == 1 ? CV_EVENT_LBUTTONDOWN :
1875                        event_button->button == 2 ? CV_EVENT_MBUTTONDOWN :
1876                        event_button->button == 3 ? CV_EVENT_RBUTTONDOWN : 0;
1877         }
1878         else if( event_button->type == GDK_BUTTON_RELEASE )
1879         {
1880             cv_event = event_button->button == 1 ? CV_EVENT_LBUTTONUP :
1881                        event_button->button == 2 ? CV_EVENT_MBUTTONUP :
1882                        event_button->button == 3 ? CV_EVENT_RBUTTONUP : 0;
1883         }
1884         else if( event_button->type == GDK_2BUTTON_PRESS )
1885         {
1886             cv_event = event_button->button == 1 ? CV_EVENT_LBUTTONDBLCLK :
1887                        event_button->button == 2 ? CV_EVENT_MBUTTONDBLCLK :
1888                        event_button->button == 3 ? CV_EVENT_RBUTTONDBLCLK : 0;
1889         }
1890         state = event_button->state;
1891     }
1892 
1893     if( cv_event >= 0 ){
1894         // scale point if image is scaled
1895         if( (image_widget->flags & CV_WINDOW_AUTOSIZE)==0 &&
1896              image_widget->original_image &&
1897              image_widget->scaled_image ){
1898             // image origin is not necessarily at (0,0)
1899 #if defined (GTK_VERSION3)
1900             int x0 = (gtk_widget_get_allocated_width(widget) - image_widget->scaled_image->cols)/2;
1901             int y0 = (gtk_widget_get_allocated_height(widget) - image_widget->scaled_image->rows)/2;
1902 #else
1903             int x0 = (widget->allocation.width - image_widget->scaled_image->cols)/2;
1904             int y0 = (widget->allocation.height - image_widget->scaled_image->rows)/2;
1905 #endif //GTK_VERSION3
1906             pt.x = cvFloor( ((pt32f.x-x0)*image_widget->original_image->cols)/
1907                                             image_widget->scaled_image->cols );
1908             pt.y = cvFloor( ((pt32f.y-y0)*image_widget->original_image->rows)/
1909                                             image_widget->scaled_image->rows );
1910         }
1911         else{
1912             pt = cvPointFrom32f( pt32f );
1913         }
1914 
1915 //        if((unsigned)pt.x < (unsigned)(image_widget->original_image->width) &&
1916 //           (unsigned)pt.y < (unsigned)(image_widget->original_image->height) )
1917         {
1918             int flags = (state & GDK_SHIFT_MASK ? CV_EVENT_FLAG_SHIFTKEY : 0) |
1919                 (state & GDK_CONTROL_MASK ? CV_EVENT_FLAG_CTRLKEY : 0) |
1920                 (state & (GDK_MOD1_MASK|GDK_MOD2_MASK) ? CV_EVENT_FLAG_ALTKEY : 0) |
1921                 (state & GDK_BUTTON1_MASK ? CV_EVENT_FLAG_LBUTTON : 0) |
1922                 (state & GDK_BUTTON2_MASK ? CV_EVENT_FLAG_MBUTTON : 0) |
1923                 (state & GDK_BUTTON3_MASK ? CV_EVENT_FLAG_RBUTTON : 0);
1924             window->on_mouse( cv_event, pt.x, pt.y, flags, window->on_mouse_param );
1925         }
1926     }
1927 
1928         return FALSE;
1929     }
1930 
1931 
icvAlarm(gpointer user_data)1932 static gboolean icvAlarm( gpointer user_data )
1933 {
1934     *(int*)user_data = 1;
1935     return FALSE;
1936 }
1937 
1938 
cvWaitKey(int delay)1939 CV_IMPL int cvWaitKey( int delay )
1940 {
1941 #ifdef HAVE_GTHREAD
1942     if(thread_started && g_thread_self()!=window_thread){
1943         gboolean expired;
1944         int my_last_key;
1945 
1946         // wait for signal or timeout if delay > 0
1947         if(delay>0){
1948             GTimeVal timer;
1949             g_get_current_time(&timer);
1950             g_time_val_add(&timer, delay*1000);
1951             expired = !g_cond_timed_wait(cond_have_key, last_key_mutex, &timer);
1952         }
1953         else{
1954             g_cond_wait(cond_have_key, last_key_mutex);
1955             expired=false;
1956         }
1957         my_last_key = last_key;
1958         g_mutex_unlock(last_key_mutex);
1959         if(expired || hg_windows==0){
1960             return -1;
1961         }
1962         return my_last_key;
1963     }
1964     else{
1965 #endif
1966         int expired = 0;
1967         guint timer = 0;
1968         if( delay > 0 )
1969             timer = g_timeout_add( delay, icvAlarm, &expired );
1970         last_key = -1;
1971         while( gtk_main_iteration_do(TRUE) && last_key < 0 && !expired && hg_windows != 0 )
1972             ;
1973 
1974         if( delay > 0 && !expired )
1975             g_source_remove(timer);
1976 #ifdef HAVE_GTHREAD
1977     }
1978 #endif
1979     return last_key;
1980 }
1981 
1982 
1983 #endif  // HAVE_GTK
1984 #endif  // WIN32
1985 
1986 /* End of file. */
1987