1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
42 #include "precomp.hpp"
49 #include "gdk/gdkkeysyms.h"
53 #include <gtk/gtkgl.h>
58 /*#if _MSC_VER >= 1200
59 #pragma warning( disable: 4505 )
60 #pragma comment(lib,"gtk-win32-2.0.lib")
61 #pragma comment(lib,"glib-2.0.lib")
62 #pragma comment(lib,"gobject-2.0.lib")
63 #pragma comment(lib,"gdk-win32-2.0.lib")
64 #pragma comment(lib,"gdk_pixbuf-2.0.lib")
68 // TODO Fix the initial window size when flags=0. Right now the initial window is by default
69 // 320x240 size. A better default would be actual size of the image. Problem
70 // is determining desired window size with trackbars while still allowing resizing.
72 // Gnome Totem source may be of use here, see bacon_video_widget_set_scale_ratio
73 // in totem/src/backend/bacon-video-widget-xine.c
75 ////////////////////////////////////////////////////////////
76 // CvImageWidget GTK Widget Public API
77 ////////////////////////////////////////////////////////////
78 typedef struct _CvImageWidget CvImageWidget;
79 typedef struct _CvImageWidgetClass CvImageWidgetClass;
81 struct _CvImageWidget {
83 CvMat * original_image;
88 struct _CvImageWidgetClass
90 GtkWidgetClass parent_class;
94 /** Allocate new image viewer widget */
95 GtkWidget* cvImageWidgetNew (int flags);
97 /** Set the image to display in the widget */
98 void cvImageWidgetSetImage(CvImageWidget * widget, const CvArr *arr);
100 // standard GTK object macros
101 #define CV_IMAGE_WIDGET(obj) GTK_CHECK_CAST (obj, cvImageWidget_get_type (), CvImageWidget)
102 #define CV_IMAGE_WIDGET_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, cvImageWidget_get_type (), CvImageWidgetClass)
103 #define CV_IS_IMAGE_WIDGET(obj) GTK_CHECK_TYPE (obj, cvImageWidget_get_type ())
105 /////////////////////////////////////////////////////////////////////////////
106 // Private API ////////////////////////////////////////////////////////
107 /////////////////////////////////////////////////////////////////////////////
108 GtkType cvImageWidget_get_type (void);
110 static GtkWidgetClass * parent_class = NULL;
112 // flag to help size initial window
113 #define CV_WINDOW_NO_IMAGE 2
115 void cvImageWidgetSetImage(CvImageWidget * widget, const CvArr *arr){
119 //printf("cvImageWidgetSetImage\n");
121 if( CV_IS_IMAGE_HDR( arr ))
122 origin = ((IplImage*)arr)->origin;
124 mat = cvGetMat(arr, &stub);
126 if(widget->original_image && !CV_ARE_SIZES_EQ(mat, widget->original_image)){
127 cvReleaseMat( &widget->original_image );
129 if(!widget->original_image){
130 widget->original_image = cvCreateMat( mat->rows, mat->cols, CV_8UC3 );
131 gtk_widget_queue_resize( GTK_WIDGET( widget ) );
133 cvConvertImage( mat, widget->original_image,
134 (origin != 0 ? CV_CVTIMG_FLIP : 0) + CV_CVTIMG_SWAP_RB );
135 if(widget->scaled_image){
136 cvResize( widget->original_image, widget->scaled_image, CV_INTER_AREA );
139 // window does not refresh without this
140 gtk_widget_queue_draw( GTK_WIDGET(widget) );
144 cvImageWidgetNew (int flags)
146 CvImageWidget *image_widget;
148 image_widget = CV_IMAGE_WIDGET( gtk_type_new (cvImageWidget_get_type ()) );
149 image_widget->original_image = 0;
150 image_widget->scaled_image = 0;
151 image_widget->flags = flags | CV_WINDOW_NO_IMAGE;
153 return GTK_WIDGET (image_widget);
157 cvImageWidget_realize (GtkWidget *widget)
159 GdkWindowAttr attributes;
160 gint attributes_mask;
162 //printf("cvImageWidget_realize\n");
163 g_return_if_fail (widget != NULL);
164 g_return_if_fail (CV_IS_IMAGE_WIDGET (widget));
166 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
168 attributes.x = widget->allocation.x;
169 attributes.y = widget->allocation.y;
170 attributes.width = widget->allocation.width;
171 attributes.height = widget->allocation.height;
172 attributes.wclass = GDK_INPUT_OUTPUT;
173 attributes.window_type = GDK_WINDOW_CHILD;
174 attributes.event_mask = gtk_widget_get_events (widget) |
175 GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
176 GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK;
177 attributes.visual = gtk_widget_get_visual (widget);
178 attributes.colormap = gtk_widget_get_colormap (widget);
180 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
181 widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
183 widget->style = gtk_style_attach (widget->style, widget->window);
185 gdk_window_set_user_data (widget->window, widget);
187 gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
190 static CvSize cvImageWidget_calc_size( int im_width, int im_height, int max_width, int max_height ){
191 float aspect = (float)im_width/(float)im_height;
192 float max_aspect = (float)max_width/(float)max_height;
193 if(aspect > max_aspect){
194 return cvSize( max_width, cvRound(max_width/aspect) );
196 return cvSize( cvRound(max_height*aspect), max_height );
200 cvImageWidget_size_request (GtkWidget *widget,
201 GtkRequisition *requisition)
203 CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget );
205 //printf("cvImageWidget_size_request ");
206 // the case the first time cvShowImage called or when AUTOSIZE
207 if( image_widget->original_image &&
208 ((image_widget->flags & CV_WINDOW_AUTOSIZE) ||
209 (image_widget->flags & CV_WINDOW_NO_IMAGE)))
211 //printf("original ");
212 requisition->width = image_widget->original_image->cols;
213 requisition->height = image_widget->original_image->rows;
216 else if(image_widget->scaled_image){
218 requisition->width = image_widget->scaled_image->cols;
219 requisition->height = image_widget->scaled_image->rows;
221 // the case before cvShowImage called
223 //printf("default ");
224 requisition->width = 320;
225 requisition->height = 240;
227 //printf("%d %d\n",requisition->width, requisition->height);
230 static void cvImageWidget_set_size(GtkWidget * widget, int max_width, int max_height){
231 CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget );
233 //printf("cvImageWidget_set_size %d %d\n", max_width, max_height);
235 // don't allow to set the size
236 if(image_widget->flags & CV_WINDOW_AUTOSIZE) return;
237 if(!image_widget->original_image) return;
239 CvSize scaled_image_size = cvImageWidget_calc_size( image_widget->original_image->cols,
240 image_widget->original_image->rows, max_width, max_height );
242 if( image_widget->scaled_image &&
243 ( image_widget->scaled_image->cols != scaled_image_size.width ||
244 image_widget->scaled_image->rows != scaled_image_size.height ))
246 cvReleaseMat( &image_widget->scaled_image );
248 if( !image_widget->scaled_image ){
249 image_widget->scaled_image = cvCreateMat( scaled_image_size.height, scaled_image_size.width, CV_8UC3 );
253 assert( image_widget->scaled_image );
257 cvImageWidget_size_allocate (GtkWidget *widget,
258 GtkAllocation *allocation)
260 CvImageWidget *image_widget;
262 //printf("cvImageWidget_size_allocate\n");
263 g_return_if_fail (widget != NULL);
264 g_return_if_fail (CV_IS_IMAGE_WIDGET (widget));
265 g_return_if_fail (allocation != NULL);
267 widget->allocation = *allocation;
268 image_widget = CV_IMAGE_WIDGET (widget);
271 if( (image_widget->flags & CV_WINDOW_AUTOSIZE)==0 && image_widget->original_image ){
272 // (re) allocated scaled image
273 if( image_widget->flags & CV_WINDOW_NO_IMAGE ){
274 cvImageWidget_set_size( widget, image_widget->original_image->cols,
275 image_widget->original_image->rows);
278 cvImageWidget_set_size( widget, allocation->width, allocation->height );
280 cvResize( image_widget->original_image, image_widget->scaled_image, CV_INTER_AREA );
283 if (GTK_WIDGET_REALIZED (widget))
285 image_widget = CV_IMAGE_WIDGET (widget);
287 if( image_widget->original_image &&
288 ((image_widget->flags & CV_WINDOW_AUTOSIZE) ||
289 (image_widget->flags & CV_WINDOW_NO_IMAGE)) )
291 widget->allocation.width = image_widget->original_image->cols;
292 widget->allocation.height = image_widget->original_image->rows;
293 gdk_window_move_resize( widget->window, allocation->x, allocation->y,
294 image_widget->original_image->cols, image_widget->original_image->rows );
295 if(image_widget->flags & CV_WINDOW_NO_IMAGE){
296 image_widget->flags &= ~CV_WINDOW_NO_IMAGE;
297 gtk_widget_queue_resize( GTK_WIDGET(widget) );
301 gdk_window_move_resize (widget->window,
302 allocation->x, allocation->y,
303 allocation->width, allocation->height );
310 cvImageWidget_destroy (GtkObject *object)
312 CvImageWidget *image_widget;
314 g_return_if_fail (object != NULL);
315 g_return_if_fail (CV_IS_IMAGE_WIDGET (object));
317 image_widget = CV_IMAGE_WIDGET (object);
319 cvReleaseMat( &image_widget->scaled_image );
320 cvReleaseMat( &image_widget->original_image );
322 if (GTK_OBJECT_CLASS (parent_class)->destroy)
323 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
326 static void cvImageWidget_class_init (CvImageWidgetClass * klass)
328 GtkObjectClass *object_class;
329 GtkWidgetClass *widget_class;
331 object_class = (GtkObjectClass*) klass;
332 widget_class = (GtkWidgetClass*) klass;
334 parent_class = GTK_WIDGET_CLASS( gtk_type_class (gtk_widget_get_type ()) );
336 object_class->destroy = cvImageWidget_destroy;
338 widget_class->realize = cvImageWidget_realize;
339 widget_class->size_request = cvImageWidget_size_request;
340 widget_class->size_allocate = cvImageWidget_size_allocate;
341 widget_class->button_press_event = NULL;
342 widget_class->button_release_event = NULL;
343 widget_class->motion_notify_event = NULL;
347 cvImageWidget_init (CvImageWidget *image_widget)
349 image_widget->original_image=0;
350 image_widget->scaled_image=0;
351 image_widget->flags=0;
354 GtkType cvImageWidget_get_type (void){
355 static GtkType image_type = 0;
359 static const GtkTypeInfo image_info =
361 (gchar*)"CvImageWidget",
362 sizeof (CvImageWidget),
363 sizeof (CvImageWidgetClass),
364 (GtkClassInitFunc) cvImageWidget_class_init,
365 (GtkObjectInitFunc) cvImageWidget_init,
366 /* reserved_1 */ NULL,
367 /* reserved_1 */ NULL,
368 (GtkClassInitFunc) NULL
371 image_type = gtk_type_unique (GTK_TYPE_WIDGET, &image_info);
376 /////////////////////////////////////////////////////////////////////////////
378 /////////////////////////////////////////////////////////////////////////////
383 typedef struct CvTrackbar
393 CvTrackbarCallback notify;
394 CvTrackbarCallback2 notify2;
400 typedef struct CvWindow
412 int status;//0 normal, 1 fullscreen (YV)
414 CvMouseCallback on_mouse;
415 void* on_mouse_param;
428 CvOpenGlDrawCallback glDrawCallback;
431 CvOpenGlCleanCallback glCleanCallback;
438 static gboolean icvOnClose( GtkWidget* widget, GdkEvent* event, gpointer user_data );
439 static gboolean icvOnKeyPress( GtkWidget* widget, GdkEventKey* event, gpointer user_data );
440 static void icvOnTrackbar( GtkWidget* widget, gpointer user_data );
441 static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_data );
444 int thread_started=0;
445 static gpointer icvWindowThreadLoop();
446 GMutex* last_key_mutex;
447 GCond* cond_have_key;
448 GMutex* window_mutex;
449 GThread* window_thread;
450 GtkWidget* cvTopLevelWidget = 0;
453 static int last_key = -1;
454 static CvWindow* hg_windows = 0;
456 CV_IMPL int cvInitSystem( int argc, char** argv )
458 static int wasInitialized = 0;
460 // check initialization status
461 if( !wasInitialized )
465 gtk_disable_setlocale();
466 gtk_init( &argc, &argv );
469 gtk_gl_init(&argc, &argv);
478 CV_IMPL int cvStartWindowThread(){
480 cvInitSystem(0,NULL);
481 if (!thread_started) {
482 if (!g_thread_supported ()) {
483 /* the GThread system wasn't inited, so init it */
487 // this mutex protects the window resources
488 window_mutex = g_mutex_new();
490 // protects the 'last key pressed' variable
491 last_key_mutex = g_mutex_new();
493 // conditional that indicates a key has been pressed
494 cond_have_key = g_cond_new();
496 // this is the window update thread
497 window_thread = g_thread_create((GThreadFunc) icvWindowThreadLoop,
500 thread_started = window_thread!=NULL;
501 return thread_started;
508 gpointer icvWindowThreadLoop(){
510 g_mutex_lock(window_mutex);
511 gtk_main_iteration_do(FALSE);
512 g_mutex_unlock(window_mutex);
522 #define CV_LOCK_MUTEX() \
523 if(thread_started && g_thread_self()!=window_thread){ g_mutex_lock( window_mutex ); } else { }
525 #define CV_UNLOCK_MUTEX() \
526 if(thread_started && g_thread_self()!=window_thread){ g_mutex_unlock( window_mutex); } else { }
529 #define CV_LOCK_MUTEX()
530 #define CV_UNLOCK_MUTEX()
533 static CvWindow* icvFindWindowByName( const char* name )
535 CvWindow* window = hg_windows;
536 while( window != 0 && strcmp(name, window->name) != 0 )
537 window = window->next;
542 static CvWindow* icvWindowByWidget( GtkWidget* widget )
544 CvWindow* window = hg_windows;
546 while( window != 0 && window->widget != widget &&
547 window->frame != widget && window->paned != widget )
548 window = window->next;
553 double cvGetModeWindow_GTK(const char* name)//YV
557 CV_FUNCNAME( "cvGetModeWindow_GTK" );
564 CV_ERROR( CV_StsNullPtr, "NULL name string" );
566 window = icvFindWindowByName( name );
568 CV_ERROR( CV_StsNullPtr, "NULL window" );
571 result = window->status;
579 void cvSetModeWindow_GTK( const char* name, double prop_value)//Yannick Verdie
582 CV_FUNCNAME( "cvSetModeWindow_GTK" );
589 CV_ERROR( CV_StsNullPtr, "NULL name string" );
591 window = icvFindWindowByName( name );
593 CV_ERROR( CV_StsNullPtr, "NULL window" );
595 if(window->flags & CV_WINDOW_AUTOSIZE)//if the flag CV_WINDOW_AUTOSIZE is set
598 //so easy to do fullscreen here, Linux rocks !
600 if (window->status==CV_WINDOW_FULLSCREEN && prop_value==CV_WINDOW_NORMAL)
603 gtk_window_unfullscreen(GTK_WINDOW(window->frame));
604 window->status=CV_WINDOW_NORMAL;
609 if (window->status==CV_WINDOW_NORMAL && prop_value==CV_WINDOW_FULLSCREEN)
612 gtk_window_fullscreen(GTK_WINDOW(window->frame));
613 window->status=CV_WINDOW_FULLSCREEN;
622 double cvGetPropWindowAutoSize_GTK(const char* name)
626 CV_FUNCNAME( "cvGetPropWindowAutoSize_GTK" );
633 CV_ERROR( CV_StsNullPtr, "NULL name string" );
635 window = icvFindWindowByName( name );
637 EXIT; // keep silence here
639 result = window->flags & CV_WINDOW_AUTOSIZE;
646 double cvGetRatioWindow_GTK(const char* name)
650 CV_FUNCNAME( "cvGetRatioWindow_GTK" );
657 CV_ERROR( CV_StsNullPtr, "NULL name string" );
659 window = icvFindWindowByName( name );
661 EXIT; // keep silence here
663 result = static_cast<double>(window->widget->allocation.width) / window->widget->allocation.height;
670 double cvGetOpenGlProp_GTK(const char* name)
675 CV_FUNCNAME( "cvGetOpenGlProp_GTK" );
682 CV_ERROR( CV_StsNullPtr, "NULL name string" );
684 window = icvFindWindowByName( name );
686 EXIT; // keep silence here
688 result = window->useGl;
703 class GlFuncTab_GTK : public CvOpenGlFuncTab
708 void genBuffers(int n, unsigned int* buffers) const;
709 void deleteBuffers(int n, const unsigned int* buffers) const;
711 void bufferData(unsigned int target, ptrdiff_t size, const void* data, unsigned int usage) const;
712 void bufferSubData(unsigned int target, ptrdiff_t offset, ptrdiff_t size, const void* data) const;
714 void bindBuffer(unsigned int target, unsigned int buffer) const;
716 void* mapBuffer(unsigned int target, unsigned int access) const;
717 void unmapBuffer(unsigned int target) const;
719 void generateBitmapFont(const std::string& family, int height, int weight, bool italic, bool underline, int start, int count, int base) const;
721 bool isGlContextInitialized() const;
723 PFNGLGENBUFFERSPROC glGenBuffersExt;
724 PFNGLDELETEBUFFERSPROC glDeleteBuffersExt;
726 PFNGLBUFFERDATAPROC glBufferDataExt;
727 PFNGLBUFFERSUBDATAPROC glBufferSubDataExt;
729 PFNGLBINDBUFFERPROC glBindBufferExt;
731 PFNGLMAPBUFFERPROC glMapBufferExt;
732 PFNGLUNMAPBUFFERPROC glUnmapBufferExt;
737 GlFuncTab_GTK::GlFuncTab_GTK()
740 glDeleteBuffersExt = 0;
743 glBufferSubDataExt = 0;
748 glUnmapBufferExt = 0;
753 void GlFuncTab_GTK::genBuffers(int n, unsigned int* buffers) const
755 CV_FUNCNAME( "GlFuncTab_GTK::genBuffers" );
759 if (!glGenBuffersExt)
760 CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension");
762 glGenBuffersExt(n, buffers);
768 void GlFuncTab_GTK::deleteBuffers(int n, const unsigned int* buffers) const
770 CV_FUNCNAME( "GlFuncTab_GTK::deleteBuffers" );
774 if (!glDeleteBuffersExt)
775 CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension");
777 glDeleteBuffersExt(n, buffers);
783 void GlFuncTab_GTK::bufferData(unsigned int target, ptrdiff_t size, const void* data, unsigned int usage) const
785 CV_FUNCNAME( "GlFuncTab_GTK::bufferData" );
789 if (!glBufferDataExt)
790 CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension");
792 glBufferDataExt(target, size, data, usage);
798 void GlFuncTab_GTK::bufferSubData(unsigned int target, ptrdiff_t offset, ptrdiff_t size, const void* data) const
800 CV_FUNCNAME( "GlFuncTab_GTK::bufferSubData" );
804 if (!glBufferSubDataExt)
805 CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension");
807 glBufferSubDataExt(target, offset, size, data);
813 void GlFuncTab_GTK::bindBuffer(unsigned int target, unsigned int buffer) const
815 CV_FUNCNAME( "GlFuncTab_GTK::bindBuffer" );
819 if (!glBindBufferExt)
820 CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension");
822 glBindBufferExt(target, buffer);
828 void* GlFuncTab_GTK::mapBuffer(unsigned int target, unsigned int access) const
830 CV_FUNCNAME( "GlFuncTab_GTK::mapBuffer" );
837 CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension");
839 res = glMapBufferExt(target, access);
847 void GlFuncTab_GTK::unmapBuffer(unsigned int target) const
849 CV_FUNCNAME( "GlFuncTab_GTK::unmapBuffer" );
853 if (!glUnmapBufferExt)
854 CV_ERROR(CV_OpenGlApiCallError, "Current OpenGL implementation doesn't support required extension");
856 glUnmapBufferExt(target);
862 void GlFuncTab_GTK::generateBitmapFont(const std::string& family, int height, int weight, bool italic, bool underline, int start, int count, int base) const
864 PangoFontDescription* fontDecr;
865 PangoFont* pangoFont;
867 CV_FUNCNAME( "GlFuncTab_GTK::generateBitmapFont" );
871 fontDecr = pango_font_description_new();
873 pango_font_description_set_size(fontDecr, height);
875 pango_font_description_set_family_static(fontDecr, family.c_str());
877 pango_font_description_set_weight(fontDecr, static_cast<PangoWeight>(weight));
879 pango_font_description_set_style(fontDecr, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
881 pangoFont = gdk_gl_font_use_pango_font(fontDecr, start, count, base);
883 pango_font_description_free(fontDecr);
886 CV_ERROR(CV_OpenGlApiCallError, "Can't create font");
891 bool GlFuncTab_GTK::isGlContextInitialized() const
898 static GlFuncTab_GTK glFuncTab;
899 static bool first = true;
906 func = gdk_gl_get_proc_address("glGenBuffers");
907 glFuncTab.glGenBuffersExt = (PFNGLGENBUFFERSPROC)func;
909 func = gdk_gl_get_proc_address("glDeleteBuffers");
910 glFuncTab.glDeleteBuffersExt = (PFNGLDELETEBUFFERSPROC)func;
912 func = gdk_gl_get_proc_address("glBufferData");
913 glFuncTab.glBufferDataExt = (PFNGLBUFFERDATAPROC)func;
915 func = gdk_gl_get_proc_address("glBufferSubData");
916 glFuncTab.glBufferSubDataExt = (PFNGLBUFFERSUBDATAPROC)func;
918 func = gdk_gl_get_proc_address("glBindBuffer");
919 glFuncTab.glBindBufferExt = (PFNGLBINDBUFFERPROC)func;
921 func = gdk_gl_get_proc_address("glMapBuffer");
922 glFuncTab.glMapBufferExt = (PFNGLMAPBUFFERPROC)func;
924 func = gdk_gl_get_proc_address("glUnmapBuffer");
925 glFuncTab.glUnmapBufferExt = (PFNGLUNMAPBUFFERPROC)func;
927 glFuncTab.initialized = true;
929 icvSetOpenGlFuncTab(&glFuncTab);
935 void createGlContext(CvWindow* window)
937 GdkGLConfig* glconfig;
939 CV_FUNCNAME( "createGlContext" );
943 window->useGl = false;
945 // Try double-buffered visual
946 glconfig = gdk_gl_config_new_by_mode((GdkGLConfigMode)(GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE));
948 CV_ERROR( CV_OpenGlApiCallError, "Can't Create A GL Device Context" );
950 // Set OpenGL-capability to the widget
951 if (!gtk_widget_set_gl_capability(window->widget, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE))
952 CV_ERROR( CV_OpenGlApiCallError, "Can't Create A GL Device Context" );
956 window->useGl = true;
961 void releaseGlContext(CvWindow* window)
963 CV_FUNCNAME( "releaseGlContext" );
967 window->useGl = false;
972 void drawGl(CvWindow* window)
974 CV_FUNCNAME( "drawGl" );
978 GdkGLContext* glcontext = gtk_widget_get_gl_context(window->widget);
979 GdkGLDrawable* gldrawable = gtk_widget_get_gl_drawable(window->widget);
981 if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
982 CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
984 glViewport(0, 0, window->widget->allocation.width, window->widget->allocation.height);
986 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
988 if (window->glDrawCallback)
989 window->glDrawCallback(window->glDrawData);
993 if (gdk_gl_drawable_is_double_buffered (gldrawable))
994 gdk_gl_drawable_swap_buffers(gldrawable);
998 gdk_gl_drawable_gl_end(gldrawable);
1004 #endif // HAVE_OPENGL
1007 static gboolean cvImageWidget_expose(GtkWidget* widget, GdkEventExpose* event, gpointer data)
1010 CvWindow* window = (CvWindow*)data;
1019 CvImageWidget *image_widget;
1021 g_return_val_if_fail (widget != NULL, FALSE);
1022 g_return_val_if_fail (CV_IS_IMAGE_WIDGET (widget), FALSE);
1023 g_return_val_if_fail (event != NULL, FALSE);
1025 if (event->count > 0)
1028 image_widget = CV_IMAGE_WIDGET (widget);
1030 gdk_window_clear_area (widget->window,
1032 widget->allocation.width,
1033 widget->allocation.height);
1034 if( image_widget->scaled_image ){
1035 // center image in available region
1036 int x0 = (widget->allocation.width - image_widget->scaled_image->cols)/2;
1037 int y0 = (widget->allocation.height - image_widget->scaled_image->rows)/2;
1039 gdk_draw_rgb_image( widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
1040 x0, y0, MIN(image_widget->scaled_image->cols, widget->allocation.width),
1041 MIN(image_widget->scaled_image->rows, widget->allocation.height),
1042 GDK_RGB_DITHER_MAX, image_widget->scaled_image->data.ptr, image_widget->scaled_image->step );
1044 else if( image_widget->original_image ){
1045 gdk_draw_rgb_image( widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
1047 MIN(image_widget->original_image->cols, widget->allocation.width),
1048 MIN(image_widget->original_image->rows, widget->allocation.height),
1049 GDK_RGB_DITHER_MAX, image_widget->original_image->data.ptr, image_widget->original_image->step );
1054 CV_IMPL int cvNamedWindow( const char* name, int flags )
1057 CV_FUNCNAME( "cvNamedWindow" );
1064 cvInitSystem(1,(char**)&name);
1066 CV_ERROR( CV_StsNullPtr, "NULL name string" );
1068 // Check the name in the storage
1069 if( icvFindWindowByName( name ) != 0 )
1076 CV_CALL( window = (CvWindow*)cvAlloc(sizeof(CvWindow) + len + 1));
1077 memset( window, 0, sizeof(*window));
1078 window->name = (char*)(window + 1);
1079 memcpy( window->name, name, len + 1 );
1080 window->flags = flags;
1081 window->signature = CV_WINDOW_MAGIC_VAL;
1082 window->last_key = 0;
1083 window->on_mouse = 0;
1084 window->on_mouse_param = 0;
1085 memset( &window->toolbar, 0, sizeof(window->toolbar));
1086 window->next = hg_windows;
1088 window->status = CV_WINDOW_NORMAL;//YV
1092 window->frame = gtk_window_new( GTK_WINDOW_TOPLEVEL );
1094 window->paned = gtk_vbox_new( FALSE, 0 );
1095 window->widget = cvImageWidgetNew( flags );
1096 gtk_box_pack_end( GTK_BOX(window->paned), window->widget, TRUE, TRUE, 0 );
1097 gtk_widget_show( window->widget );
1098 gtk_container_add( GTK_CONTAINER(window->frame), window->paned );
1099 gtk_widget_show( window->paned );
1102 if (flags & CV_WINDOW_OPENGL)
1103 CV_ERROR( CV_OpenGlNotSupported, "Library was built without OpenGL support" );
1105 if (flags & CV_WINDOW_OPENGL)
1106 createGlContext(window);
1108 window->glDrawCallback = 0;
1109 window->glDrawData = 0;
1111 window->glCleanCallback = 0;
1112 window->glCleanData = 0;
1116 // configure event handlers
1117 // TODO -- move this to CvImageWidget ?
1118 gtk_signal_connect( GTK_OBJECT(window->frame), "key-press-event",
1119 GTK_SIGNAL_FUNC(icvOnKeyPress), window );
1120 gtk_signal_connect( GTK_OBJECT(window->widget), "button-press-event",
1121 GTK_SIGNAL_FUNC(icvOnMouse), window );
1122 gtk_signal_connect( GTK_OBJECT(window->widget), "button-release-event",
1123 GTK_SIGNAL_FUNC(icvOnMouse), window );
1124 gtk_signal_connect( GTK_OBJECT(window->widget), "motion-notify-event",
1125 GTK_SIGNAL_FUNC(icvOnMouse), window );
1126 gtk_signal_connect( GTK_OBJECT(window->frame), "delete-event",
1127 GTK_SIGNAL_FUNC(icvOnClose), window );
1128 gtk_signal_connect( GTK_OBJECT(window->widget), "expose-event",
1129 GTK_SIGNAL_FUNC(cvImageWidget_expose), window );
1131 gtk_widget_add_events (window->widget, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK) ;
1133 gtk_widget_show( window->frame );
1134 gtk_window_set_title( GTK_WINDOW(window->frame), name );
1137 hg_windows->prev = window;
1138 hg_windows = window;
1140 gtk_window_set_resizable( GTK_WINDOW(window->frame), (flags & CV_WINDOW_AUTOSIZE) == 0 );
1143 // allow window to be resized
1144 if( (flags & CV_WINDOW_AUTOSIZE)==0 ){
1145 GdkGeometry geometry;
1146 geometry.min_width = 50;
1147 geometry.min_height = 50;
1148 gtk_window_set_geometry_hints( GTK_WINDOW( window->frame ), GTK_WIDGET( window->widget ),
1149 &geometry, (GdkWindowHints) (GDK_HINT_MIN_SIZE));
1156 cvSetOpenGlContext(name);
1168 CV_IMPL void cvSetOpenGlContext(const char* name)
1171 GdkGLContext* glcontext;
1172 GdkGLDrawable* gldrawable;
1174 CV_FUNCNAME( "cvSetOpenGlContext" );
1179 CV_ERROR( CV_StsNullPtr, "NULL name string" );
1181 window = icvFindWindowByName( name );
1183 CV_ERROR( CV_StsNullPtr, "NULL window" );
1186 CV_ERROR( CV_OpenGlNotSupported, "Window doesn't support OpenGL" );
1188 glcontext = gtk_widget_get_gl_context(window->widget);
1189 gldrawable = gtk_widget_get_gl_drawable(window->widget);
1191 if (!gdk_gl_drawable_make_current(gldrawable, glcontext))
1192 CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
1197 CV_IMPL void cvUpdateWindow(const char* name)
1199 CV_FUNCNAME( "cvUpdateWindow" );
1206 CV_ERROR( CV_StsNullPtr, "NULL name string" );
1208 window = icvFindWindowByName( name );
1212 // window does not refresh without this
1213 gtk_widget_queue_draw( GTK_WIDGET(window->widget) );
1218 CV_IMPL void cvSetOpenGlDrawCallback(const char* name, CvOpenGlDrawCallback callback, void* userdata)
1222 CV_FUNCNAME( "cvCreateOpenGLCallback" );
1227 CV_ERROR( CV_StsNullPtr, "NULL name string" );
1229 window = icvFindWindowByName( name );
1234 CV_ERROR( CV_OpenGlNotSupported, "Window was created without OpenGL context" );
1236 window->glDrawCallback = callback;
1237 window->glDrawData = userdata;
1242 void icvSetOpenGlCleanCallback(const char* name, CvOpenGlCleanCallback callback, void* userdata)
1245 GdkGLContext* glcontext;
1246 GdkGLDrawable* gldrawable;
1248 CV_FUNCNAME( "icvSetOpenGlCleanCallback" );
1253 CV_ERROR(CV_StsNullPtr, "NULL name string");
1255 window = icvFindWindowByName(name);
1260 CV_ERROR( CV_OpenGlNotSupported, "Window doesn't support OpenGL" );
1262 glcontext = gtk_widget_get_gl_context(window->widget);
1263 gldrawable = gtk_widget_get_gl_drawable(window->widget);
1265 gdk_gl_drawable_make_current(gldrawable, glcontext);
1267 if (window->glCleanCallback)
1268 window->glCleanCallback(window->glCleanData);
1270 window->glCleanCallback = callback;
1271 window->glCleanData = userdata;
1276 #endif // HAVE_OPENGL
1281 static void icvDeleteWindow( CvWindow* window )
1283 CvTrackbar* trackbar;
1288 GdkGLContext* glcontext = gtk_widget_get_gl_context(window->widget);
1289 GdkGLDrawable* gldrawable = gtk_widget_get_gl_drawable(window->widget);
1291 gdk_gl_drawable_make_current(gldrawable, glcontext);
1293 if (window->glCleanCallback)
1295 window->glCleanCallback(window->glCleanData);
1296 window->glCleanCallback = 0;
1297 window->glCleanData = 0;
1300 releaseGlContext(window);
1305 window->prev->next = window->next;
1307 hg_windows = window->next;
1310 window->next->prev = window->prev;
1312 window->prev = window->next = 0;
1314 gtk_widget_destroy( window->frame );
1316 for( trackbar = window->toolbar.first; trackbar != 0; )
1318 CvTrackbar* next = trackbar->next;
1319 cvFree( &trackbar );
1325 // if last window, send key press signal
1326 // to jump out of any waiting cvWaitKey's
1327 if(hg_windows==0 && thread_started){
1328 g_cond_broadcast(cond_have_key);
1334 CV_IMPL void cvDestroyWindow( const char* name )
1336 CV_FUNCNAME( "cvDestroyWindow" );
1343 CV_ERROR( CV_StsNullPtr, "NULL name string" );
1345 window = icvFindWindowByName( name );
1349 // note that it is possible for the update thread to run this function
1350 // if there is a call to cvShowImage in a mouse callback
1351 // (this would produce a deadlock on window_mutex)
1354 icvDeleteWindow( window );
1363 cvDestroyAllWindows( void )
1369 CvWindow* window = hg_windows;
1370 icvDeleteWindow( window );
1375 CvSize icvCalcOptimalWindowSize( CvWindow * window, CvSize new_image_size){
1377 GtkWidget * toplevel = gtk_widget_get_toplevel( window->frame );
1378 gdk_drawable_get_size( GDK_DRAWABLE(toplevel->window),
1379 &window_size.width, &window_size.height );
1381 window_size.width = window_size.width + new_image_size.width - window->widget->allocation.width;
1382 window_size.height = window_size.height + new_image_size.height - window->widget->allocation.height;
1388 cvShowImage( const char* name, const CvArr* arr )
1390 CV_FUNCNAME( "cvShowImage" );
1397 CV_ERROR( CV_StsNullPtr, "NULL name" );
1401 window = icvFindWindowByName(name);
1404 cvNamedWindow(name, 1);
1405 window = icvFindWindowByName(name);
1414 CvMat* mat = cvGetMat(arr, &stub);
1416 cv::imshow(name, im);
1421 CvImageWidget * image_widget = CV_IMAGE_WIDGET( window->widget );
1422 cvImageWidgetSetImage( image_widget, arr );
1430 CV_IMPL void cvResizeWindow(const char* name, int width, int height )
1432 CV_FUNCNAME( "cvResizeWindow" );
1437 CvImageWidget * image_widget;
1440 CV_ERROR( CV_StsNullPtr, "NULL name" );
1442 window = icvFindWindowByName(name);
1446 image_widget = CV_IMAGE_WIDGET( window->widget );
1447 //if(image_widget->flags & CV_WINDOW_AUTOSIZE)
1452 gtk_window_set_resizable( GTK_WINDOW(window->frame), 1 );
1453 gtk_window_resize( GTK_WINDOW(window->frame), width, height );
1455 // disable initial resize since presumably user wants to keep
1457 image_widget->flags &= ~CV_WINDOW_NO_IMAGE;
1465 CV_IMPL void cvMoveWindow( const char* name, int x, int y )
1467 CV_FUNCNAME( "cvMoveWindow" );
1474 CV_ERROR( CV_StsNullPtr, "NULL name" );
1476 window = icvFindWindowByName(name);
1482 gtk_window_move( GTK_WINDOW(window->frame), x, y );
1491 icvFindTrackbarByName( const CvWindow* window, const char* name )
1493 CvTrackbar* trackbar = window->toolbar.first;
1495 for( ; trackbar != 0 && strcmp( trackbar->name, name ) != 0; trackbar = trackbar->next )
1502 icvCreateTrackbar( const char* trackbar_name, const char* window_name,
1503 int* val, int count, CvTrackbarCallback on_notify,
1504 CvTrackbarCallback2 on_notify2, void* userdata )
1508 CV_FUNCNAME( "icvCreateTrackbar" );
1512 /*char slider_name[32];*/
1513 CvWindow* window = 0;
1514 CvTrackbar* trackbar = 0;
1516 if( !window_name || !trackbar_name )
1517 CV_ERROR( CV_StsNullPtr, "NULL window or trackbar name" );
1520 CV_ERROR( CV_StsOutOfRange, "Bad trackbar maximal value" );
1522 window = icvFindWindowByName(window_name);
1526 trackbar = icvFindTrackbarByName(window,trackbar_name);
1532 int len = strlen(trackbar_name);
1533 trackbar = (CvTrackbar*)cvAlloc(sizeof(CvTrackbar) + len + 1);
1534 memset( trackbar, 0, sizeof(*trackbar));
1535 trackbar->signature = CV_TRACKBAR_MAGIC_VAL;
1536 trackbar->name = (char*)(trackbar+1);
1537 memcpy( trackbar->name, trackbar_name, len + 1 );
1538 trackbar->parent = window;
1539 trackbar->next = window->toolbar.first;
1540 window->toolbar.first = trackbar;
1542 GtkWidget* hscale_box = gtk_hbox_new( FALSE, 10 );
1543 GtkWidget* hscale_label = gtk_label_new( trackbar_name );
1544 GtkWidget* hscale = gtk_hscale_new_with_range( 0, count, 1 );
1545 gtk_range_set_update_policy( GTK_RANGE(hscale), GTK_UPDATE_CONTINUOUS );
1546 gtk_scale_set_digits( GTK_SCALE(hscale), 0 );
1547 //gtk_scale_set_value_pos( hscale, GTK_POS_TOP );
1548 gtk_scale_set_draw_value( GTK_SCALE(hscale), TRUE );
1550 trackbar->widget = hscale;
1551 gtk_box_pack_start( GTK_BOX(hscale_box), hscale_label, FALSE, FALSE, 5 );
1552 gtk_widget_show( hscale_label );
1553 gtk_box_pack_start( GTK_BOX(hscale_box), hscale, TRUE, TRUE, 5 );
1554 gtk_widget_show( hscale );
1555 gtk_box_pack_start( GTK_BOX(window->paned), hscale_box, FALSE, FALSE, 5 );
1556 gtk_widget_show( hscale_box );
1567 gtk_range_set_value( GTK_RANGE(trackbar->widget), value );
1568 trackbar->pos = value;
1569 trackbar->data = val;
1572 trackbar->maxval = count;
1573 trackbar->notify = on_notify;
1574 trackbar->notify2 = on_notify2;
1575 trackbar->userdata = userdata;
1576 gtk_signal_connect( GTK_OBJECT(trackbar->widget), "value-changed",
1577 GTK_SIGNAL_FUNC(icvOnTrackbar), trackbar );
1579 // queue a widget resize to trigger a window resize to
1580 // compensate for the addition of trackbars
1581 gtk_widget_queue_resize( GTK_WIDGET(window->widget) );
1595 cvCreateTrackbar( const char* trackbar_name, const char* window_name,
1596 int* val, int count, CvTrackbarCallback on_notify )
1598 return icvCreateTrackbar(trackbar_name, window_name, val, count,
1604 cvCreateTrackbar2( const char* trackbar_name, const char* window_name,
1605 int* val, int count, CvTrackbarCallback2 on_notify2,
1608 return icvCreateTrackbar(trackbar_name, window_name, val, count,
1609 0, on_notify2, userdata);
1614 cvSetMouseCallback( const char* window_name, CvMouseCallback on_mouse, void* param )
1616 CV_FUNCNAME( "cvSetMouseCallback" );
1620 CvWindow* window = 0;
1623 CV_ERROR( CV_StsNullPtr, "NULL window name" );
1625 window = icvFindWindowByName(window_name);
1629 window->on_mouse = on_mouse;
1630 window->on_mouse_param = param;
1636 CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name )
1640 CV_FUNCNAME( "cvGetTrackbarPos" );
1645 CvTrackbar* trackbar = 0;
1647 if( trackbar_name == 0 || window_name == 0 )
1648 CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
1650 window = icvFindWindowByName( window_name );
1652 trackbar = icvFindTrackbarByName( window, trackbar_name );
1655 pos = trackbar->pos;
1663 CV_IMPL void cvSetTrackbarPos( const char* trackbar_name, const char* window_name, int pos )
1665 CV_FUNCNAME( "cvSetTrackbarPos" );
1670 CvTrackbar* trackbar = 0;
1672 if( trackbar_name == 0 || window_name == 0 )
1673 CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
1675 window = icvFindWindowByName( window_name );
1677 trackbar = icvFindTrackbarByName( window, trackbar_name );
1684 if( pos > trackbar->maxval )
1685 pos = trackbar->maxval;
1690 gtk_range_set_value( GTK_RANGE(trackbar->widget), pos );
1698 CV_IMPL void* cvGetWindowHandle( const char* window_name )
1702 CV_FUNCNAME( "cvGetWindowHandle" );
1708 if( window_name == 0 )
1709 CV_ERROR( CV_StsNullPtr, "NULL window name" );
1711 window = icvFindWindowByName( window_name );
1713 widget = (void*)window->widget;
1721 CV_IMPL const char* cvGetWindowName( void* window_handle )
1723 const char* window_name = "";
1725 CV_FUNCNAME( "cvGetWindowName" );
1731 if( window_handle == 0 )
1732 CV_ERROR( CV_StsNullPtr, "NULL window" );
1734 window = icvWindowByWidget( (GtkWidget*)window_handle );
1736 window_name = window->name;
1743 static gboolean icvOnKeyPress( GtkWidget * /*widget*/,
1744 GdkEventKey* event, gpointer /*user_data*/ )
1748 switch( event->keyval )
1761 code = event->keyval;
1764 code |= event->state << 16;
1767 if(thread_started) g_mutex_lock(last_key_mutex);
1774 // signal any waiting threads
1775 g_cond_broadcast(cond_have_key);
1776 g_mutex_unlock(last_key_mutex);
1784 static void icvOnTrackbar( GtkWidget* widget, gpointer user_data )
1786 int pos = cvRound( gtk_range_get_value(GTK_RANGE(widget)));
1787 CvTrackbar* trackbar = (CvTrackbar*)user_data;
1789 if( trackbar && trackbar->signature == CV_TRACKBAR_MAGIC_VAL &&
1790 trackbar->widget == widget )
1792 trackbar->pos = pos;
1793 if( trackbar->data )
1794 *trackbar->data = pos;
1795 if( trackbar->notify2 )
1796 trackbar->notify2(pos, trackbar->userdata);
1797 else if( trackbar->notify )
1798 trackbar->notify(pos);
1802 static gboolean icvOnClose( GtkWidget* widget, GdkEvent* /*event*/, gpointer user_data )
1804 CvWindow* window = (CvWindow*)user_data;
1805 if( window->signature == CV_WINDOW_MAGIC_VAL &&
1806 window->frame == widget )
1808 icvDeleteWindow(window);
1814 static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_data )
1816 // TODO move this logic to CvImageWidget
1817 CvWindow* window = (CvWindow*)user_data;
1818 CvPoint2D32f pt32f = {-1., -1.};
1819 CvPoint pt = {-1,-1};
1820 int cv_event = -1, state = 0;
1821 CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget );
1823 if( window->signature != CV_WINDOW_MAGIC_VAL ||
1824 window->widget != widget || !window->widget ||
1825 !window->on_mouse /*|| !image_widget->original_image*/)
1828 if( event->type == GDK_MOTION_NOTIFY )
1830 GdkEventMotion* event_motion = (GdkEventMotion*)event;
1832 cv_event = CV_EVENT_MOUSEMOVE;
1833 pt32f.x = cvRound(event_motion->x);
1834 pt32f.y = cvRound(event_motion->y);
1835 state = event_motion->state;
1837 else if( event->type == GDK_BUTTON_PRESS ||
1838 event->type == GDK_BUTTON_RELEASE ||
1839 event->type == GDK_2BUTTON_PRESS )
1841 GdkEventButton* event_button = (GdkEventButton*)event;
1842 pt32f.x = cvRound(event_button->x);
1843 pt32f.y = cvRound(event_button->y);
1846 if( event_button->type == GDK_BUTTON_PRESS )
1848 cv_event = event_button->button == 1 ? CV_EVENT_LBUTTONDOWN :
1849 event_button->button == 2 ? CV_EVENT_MBUTTONDOWN :
1850 event_button->button == 3 ? CV_EVENT_RBUTTONDOWN : 0;
1852 else if( event_button->type == GDK_BUTTON_RELEASE )
1854 cv_event = event_button->button == 1 ? CV_EVENT_LBUTTONUP :
1855 event_button->button == 2 ? CV_EVENT_MBUTTONUP :
1856 event_button->button == 3 ? CV_EVENT_RBUTTONUP : 0;
1858 else if( event_button->type == GDK_2BUTTON_PRESS )
1860 cv_event = event_button->button == 1 ? CV_EVENT_LBUTTONDBLCLK :
1861 event_button->button == 2 ? CV_EVENT_MBUTTONDBLCLK :
1862 event_button->button == 3 ? CV_EVENT_RBUTTONDBLCLK : 0;
1864 state = event_button->state;
1867 if( cv_event >= 0 ){
1868 // scale point if image is scaled
1869 if( (image_widget->flags & CV_WINDOW_AUTOSIZE)==0 &&
1870 image_widget->original_image &&
1871 image_widget->scaled_image ){
1872 // image origin is not necessarily at (0,0)
1873 int x0 = (widget->allocation.width - image_widget->scaled_image->cols)/2;
1874 int y0 = (widget->allocation.height - image_widget->scaled_image->rows)/2;
1875 pt.x = cvRound( ((pt32f.x-x0)*image_widget->original_image->cols)/
1876 image_widget->scaled_image->cols );
1877 pt.y = cvRound( ((pt32f.y-y0)*image_widget->original_image->rows)/
1878 image_widget->scaled_image->rows );
1881 pt = cvPointFrom32f( pt32f );
1884 // if((unsigned)pt.x < (unsigned)(image_widget->original_image->width) &&
1885 // (unsigned)pt.y < (unsigned)(image_widget->original_image->height) )
1887 int flags = (state & GDK_SHIFT_MASK ? CV_EVENT_FLAG_SHIFTKEY : 0) |
1888 (state & GDK_CONTROL_MASK ? CV_EVENT_FLAG_CTRLKEY : 0) |
1889 (state & (GDK_MOD1_MASK|GDK_MOD2_MASK) ? CV_EVENT_FLAG_ALTKEY : 0) |
1890 (state & GDK_BUTTON1_MASK ? CV_EVENT_FLAG_LBUTTON : 0) |
1891 (state & GDK_BUTTON2_MASK ? CV_EVENT_FLAG_MBUTTON : 0) |
1892 (state & GDK_BUTTON3_MASK ? CV_EVENT_FLAG_RBUTTON : 0);
1893 window->on_mouse( cv_event, pt.x, pt.y, flags, window->on_mouse_param );
1901 static gboolean icvAlarm( gpointer user_data )
1903 *(int*)user_data = 1;
1908 CV_IMPL int cvWaitKey( int delay )
1911 if(thread_started && g_thread_self()!=window_thread){
1915 // wait for signal or timeout if delay > 0
1918 g_get_current_time(&timer);
1919 g_time_val_add(&timer, delay*1000);
1920 expired = !g_cond_timed_wait(cond_have_key, last_key_mutex, &timer);
1923 g_cond_wait(cond_have_key, last_key_mutex);
1926 my_last_key = last_key;
1927 g_mutex_unlock(last_key_mutex);
1928 if(expired || hg_windows==0){
1938 timer = g_timeout_add( delay, icvAlarm, &expired );
1940 while( gtk_main_iteration_do(TRUE) && last_key < 0 && !expired && hg_windows != 0 )
1943 if( delay > 0 && !expired )
1944 g_source_remove(timer);