~paparazzi-uav/paparazzi/v5.0-manual

« back to all changes in this revision

Viewing changes to sw/ext/opencv_bebop/opencv/modules/highgui/src/window_gtk.cpp

  • Committer: Paparazzi buildbot
  • Date: 2016-05-18 15:00:29 UTC
  • Revision ID: felix.ruess+docbot@gmail.com-20160518150029-e8lgzi5kvb4p7un9
Manual import commit 4b8bbb730080dac23cf816b98908dacfabe2a8ec from v5.0 branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
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*
 
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
 
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
 
 
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
 
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) != 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
 
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) != 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
 
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
 
 
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
 
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
 
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
 
 
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
 
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
 
 
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
    int minval;
 
512
    CvTrackbarCallback notify;
 
513
    CvTrackbarCallback2 notify2;
 
514
    void* userdata;
 
515
}
 
516
CvTrackbar;
 
517
 
 
518
 
 
519
typedef struct CvWindow
 
520
{
 
521
    int signature;
 
522
    GtkWidget* widget;
 
523
    GtkWidget* frame;
 
524
    GtkWidget* paned;
 
525
    char* name;
 
526
    CvWindow* prev;
 
527
    CvWindow* next;
 
528
 
 
529
    int last_key;
 
530
    int flags;
 
531
    int status;//0 normal, 1 fullscreen (YV)
 
532
 
 
533
    CvMouseCallback on_mouse;
 
534
    void* on_mouse_param;
 
535
 
 
536
    struct
 
537
    {
 
538
        int pos;
 
539
        int rows;
 
540
        CvTrackbar* first;
 
541
    }
 
542
    toolbar;
 
543
 
 
544
#ifdef HAVE_OPENGL
 
545
    bool useGl;
 
546
 
 
547
    CvOpenGlDrawCallback glDrawCallback;
 
548
    void* glDrawData;
 
549
#endif
 
550
}
 
551
CvWindow;
 
552
 
 
553
 
 
554
static gboolean icvOnClose( GtkWidget* widget, GdkEvent* event, gpointer user_data );
 
555
static gboolean icvOnKeyPress( GtkWidget* widget, GdkEventKey* event, gpointer user_data );
 
556
static void icvOnTrackbar( GtkWidget* widget, gpointer user_data );
 
557
static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_data );
 
558
 
 
559
#ifdef HAVE_GTHREAD
 
560
int thread_started=0;
 
561
static gpointer icvWindowThreadLoop();
 
562
GMutex*                            last_key_mutex;
 
563
GCond*                             cond_have_key;
 
564
GMutex*                            window_mutex;
 
565
GThread*                           window_thread;
 
566
GtkWidget*             cvTopLevelWidget = 0;
 
567
#endif
 
568
 
 
569
static int             last_key = -1;
 
570
static CvWindow* hg_windows = 0;
 
571
 
 
572
CV_IMPL int cvInitSystem( int argc, char** argv )
 
573
{
 
574
    static int wasInitialized = 0;
 
575
 
 
576
    // check initialization status
 
577
    if( !wasInitialized )
 
578
    {
 
579
        hg_windows = 0;
 
580
 
 
581
        gtk_init( &argc, &argv );
 
582
        setlocale(LC_NUMERIC,"C");
 
583
 
 
584
        #ifdef HAVE_OPENGL
 
585
            gtk_gl_init(&argc, &argv);
 
586
        #endif
 
587
 
 
588
        wasInitialized = 1;
 
589
    }
 
590
 
 
591
    return 0;
 
592
}
 
593
 
 
594
CV_IMPL int cvStartWindowThread(){
 
595
#ifdef HAVE_GTHREAD
 
596
    cvInitSystem(0,NULL);
 
597
    if (!thread_started) {
 
598
    if (!g_thread_supported ()) {
 
599
        /* the GThread system wasn't inited, so init it */
 
600
        g_thread_init(NULL);
 
601
    }
 
602
 
 
603
    // this mutex protects the window resources
 
604
    window_mutex = g_mutex_new();
 
605
 
 
606
    // protects the 'last key pressed' variable
 
607
    last_key_mutex = g_mutex_new();
 
608
 
 
609
    // conditional that indicates a key has been pressed
 
610
    cond_have_key = g_cond_new();
 
611
 
 
612
    // this is the window update thread
 
613
    window_thread = g_thread_create((GThreadFunc) icvWindowThreadLoop,
 
614
                    NULL, TRUE, NULL);
 
615
    }
 
616
    thread_started = window_thread!=NULL;
 
617
    return thread_started;
 
618
#else
 
619
    return 0;
 
620
#endif
 
621
}
 
622
 
 
623
#ifdef HAVE_GTHREAD
 
624
gpointer icvWindowThreadLoop(){
 
625
    while(1){
 
626
        g_mutex_lock(window_mutex);
 
627
        gtk_main_iteration_do(FALSE);
 
628
        g_mutex_unlock(window_mutex);
 
629
 
 
630
        // little sleep
 
631
        g_usleep(500);
 
632
 
 
633
        g_thread_yield();
 
634
    }
 
635
    return NULL;
 
636
}
 
637
 
 
638
#define CV_LOCK_MUTEX() \
 
639
if(thread_started && g_thread_self()!=window_thread){ g_mutex_lock( window_mutex ); } else { }
 
640
 
 
641
#define CV_UNLOCK_MUTEX() \
 
642
if(thread_started && g_thread_self()!=window_thread){ g_mutex_unlock( window_mutex); } else { }
 
643
 
 
644
#else
 
645
#define CV_LOCK_MUTEX()
 
646
#define CV_UNLOCK_MUTEX()
 
647
#endif
 
648
 
 
649
static CvWindow* icvFindWindowByName( const char* name )
 
650
{
 
651
    CvWindow* window = hg_windows;
 
652
    while( window != 0 && strcmp(name, window->name) != 0 )
 
653
        window = window->next;
 
654
 
 
655
    return window;
 
656
}
 
657
 
 
658
static CvWindow* icvWindowByWidget( GtkWidget* widget )
 
659
{
 
660
    CvWindow* window = hg_windows;
 
661
 
 
662
    while( window != 0 && window->widget != widget &&
 
663
           window->frame != widget && window->paned != widget )
 
664
        window = window->next;
 
665
 
 
666
    return window;
 
667
}
 
668
 
 
669
double cvGetModeWindow_GTK(const char* name)//YV
 
670
{
 
671
    double result = -1;
 
672
 
 
673
    CV_FUNCNAME( "cvGetModeWindow_GTK" );
 
674
 
 
675
    __BEGIN__;
 
676
 
 
677
    CvWindow* window;
 
678
 
 
679
    if (!name)
 
680
        CV_ERROR( CV_StsNullPtr, "NULL name string" );
 
681
 
 
682
    window = icvFindWindowByName( name );
 
683
    if (!window)
 
684
        CV_ERROR( CV_StsNullPtr, "NULL window" );
 
685
 
 
686
    CV_LOCK_MUTEX();
 
687
    result = window->status;
 
688
    CV_UNLOCK_MUTEX();
 
689
 
 
690
    __END__;
 
691
    return result;
 
692
}
 
693
 
 
694
 
 
695
void cvSetModeWindow_GTK( const char* name, double prop_value)//Yannick Verdie
 
696
{
 
697
 
 
698
    CV_FUNCNAME( "cvSetModeWindow_GTK" );
 
699
 
 
700
    __BEGIN__;
 
701
 
 
702
    CvWindow* window;
 
703
 
 
704
    if(!name)
 
705
        CV_ERROR( CV_StsNullPtr, "NULL name string" );
 
706
 
 
707
    window = icvFindWindowByName( name );
 
708
    if( !window )
 
709
        CV_ERROR( CV_StsNullPtr, "NULL window" );
 
710
 
 
711
    if(window->flags & CV_WINDOW_AUTOSIZE)//if the flag CV_WINDOW_AUTOSIZE is set
 
712
        EXIT;
 
713
 
 
714
    //so easy to do fullscreen here, Linux rocks !
 
715
 
 
716
    if (window->status==CV_WINDOW_FULLSCREEN && prop_value==CV_WINDOW_NORMAL)
 
717
    {
 
718
        CV_LOCK_MUTEX();
 
719
        gtk_window_unfullscreen(GTK_WINDOW(window->frame));
 
720
        window->status=CV_WINDOW_NORMAL;
 
721
        CV_UNLOCK_MUTEX();
 
722
        EXIT;
 
723
    }
 
724
 
 
725
    if (window->status==CV_WINDOW_NORMAL && prop_value==CV_WINDOW_FULLSCREEN)
 
726
    {
 
727
        CV_LOCK_MUTEX();
 
728
        gtk_window_fullscreen(GTK_WINDOW(window->frame));
 
729
        window->status=CV_WINDOW_FULLSCREEN;
 
730
        CV_UNLOCK_MUTEX();
 
731
        EXIT;
 
732
    }
 
733
 
 
734
    __END__;
 
735
}
 
736
 
 
737
void cv::setWindowTitle(const String& winname, const String& title)
 
738
{
 
739
    CvWindow* window = icvFindWindowByName(winname.c_str());
 
740
 
 
741
    if (!window)
 
742
    {
 
743
        namedWindow(winname);
 
744
        window = icvFindWindowByName(winname.c_str());
 
745
    }
 
746
 
 
747
    if (!window)
 
748
        CV_Error(Error::StsNullPtr, "NULL window");
 
749
 
 
750
    CV_LOCK_MUTEX();
 
751
    gtk_window_set_title(GTK_WINDOW(window->frame), title.c_str());
 
752
    CV_UNLOCK_MUTEX();
 
753
}
 
754
 
 
755
double cvGetPropWindowAutoSize_GTK(const char* name)
 
756
{
 
757
    double result = -1;
 
758
 
 
759
    CV_FUNCNAME( "cvGetPropWindowAutoSize_GTK" );
 
760
 
 
761
    __BEGIN__;
 
762
 
 
763
    CvWindow* window;
 
764
 
 
765
    if (!name)
 
766
        CV_ERROR( CV_StsNullPtr, "NULL name string" );
 
767
 
 
768
    window = icvFindWindowByName( name );
 
769
    if (!window)
 
770
        EXIT; // keep silence here
 
771
 
 
772
    result = window->flags & CV_WINDOW_AUTOSIZE;
 
773
 
 
774
    __END__;
 
775
 
 
776
    return result;
 
777
}
 
778
 
 
779
double cvGetRatioWindow_GTK(const char* name)
 
780
{
 
781
    double result = -1;
 
782
 
 
783
    CV_FUNCNAME( "cvGetRatioWindow_GTK" );
 
784
 
 
785
    __BEGIN__;
 
786
 
 
787
    CvWindow* window;
 
788
 
 
789
    if (!name)
 
790
        CV_ERROR( CV_StsNullPtr, "NULL name string" );
 
791
 
 
792
    window = icvFindWindowByName( name );
 
793
    if (!window)
 
794
        EXIT; // keep silence here
 
795
 
 
796
#if defined (GTK_VERSION3)
 
797
    result = static_cast<double>(
 
798
        gtk_widget_get_allocated_width(window->widget)) / gtk_widget_get_allocated_height(window->widget);
 
799
#else
 
800
    result = static_cast<double>(window->widget->allocation.width) / window->widget->allocation.height;
 
801
#endif // GTK_VERSION3
 
802
    __END__;
 
803
 
 
804
    return result;
 
805
}
 
806
 
 
807
double cvGetOpenGlProp_GTK(const char* name)
 
808
{
 
809
    double result = -1;
 
810
 
 
811
#ifdef HAVE_OPENGL
 
812
    CV_FUNCNAME( "cvGetOpenGlProp_GTK" );
 
813
 
 
814
    __BEGIN__;
 
815
 
 
816
    CvWindow* window;
 
817
 
 
818
    if (!name)
 
819
        CV_ERROR( CV_StsNullPtr, "NULL name string" );
 
820
 
 
821
    window = icvFindWindowByName( name );
 
822
    if (!window)
 
823
        EXIT; // keep silence here
 
824
 
 
825
    result = window->useGl;
 
826
 
 
827
    __END__;
 
828
#else
 
829
    (void)name;
 
830
#endif
 
831
 
 
832
    return result;
 
833
}
 
834
 
 
835
 
 
836
// OpenGL support
 
837
 
 
838
#ifdef HAVE_OPENGL
 
839
 
 
840
namespace
 
841
{
 
842
    void createGlContext(CvWindow* window)
 
843
    {
 
844
        GdkGLConfig* glconfig;
 
845
 
 
846
        CV_FUNCNAME( "createGlContext" );
 
847
 
 
848
        __BEGIN__;
 
849
 
 
850
        // Try double-buffered visual
 
851
        glconfig = gdk_gl_config_new_by_mode((GdkGLConfigMode)(GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE));
 
852
        if (!glconfig)
 
853
            CV_ERROR( CV_OpenGlApiCallError, "Can't Create A GL Device Context" );
 
854
 
 
855
        // Set OpenGL-capability to the widget
 
856
        if (!gtk_widget_set_gl_capability(window->widget, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE))
 
857
            CV_ERROR( CV_OpenGlApiCallError, "Can't Create A GL Device Context" );
 
858
 
 
859
        window->useGl = true;
 
860
 
 
861
        __END__;
 
862
    }
 
863
 
 
864
    void drawGl(CvWindow* window)
 
865
    {
 
866
        CV_FUNCNAME( "drawGl" );
 
867
 
 
868
        __BEGIN__;
 
869
 
 
870
        GdkGLContext* glcontext = gtk_widget_get_gl_context(window->widget);
 
871
        GdkGLDrawable* gldrawable = gtk_widget_get_gl_drawable(window->widget);
 
872
 
 
873
        if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
 
874
            CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
 
875
 
 
876
        glViewport(0, 0, window->widget->allocation.width, window->widget->allocation.height);
 
877
 
 
878
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
879
 
 
880
        if (window->glDrawCallback)
 
881
            window->glDrawCallback(window->glDrawData);
 
882
 
 
883
        if (gdk_gl_drawable_is_double_buffered (gldrawable))
 
884
            gdk_gl_drawable_swap_buffers(gldrawable);
 
885
        else
 
886
            glFlush();
 
887
 
 
888
        gdk_gl_drawable_gl_end(gldrawable);
 
889
 
 
890
        __END__;
 
891
    }
 
892
}
 
893
 
 
894
#endif // HAVE_OPENGL
 
895
 
 
896
#if defined (GTK_VERSION3)
 
897
static gboolean cvImageWidget_draw(GtkWidget* widget, cairo_t *cr, gpointer data)
 
898
{
 
899
#ifdef HAVE_OPENGL
 
900
    CvWindow* window = (CvWindow*)data;
 
901
 
 
902
    if (window->useGl)
 
903
    {
 
904
        drawGl(window);
 
905
        return TRUE;
 
906
    }
 
907
#else
 
908
    (void)data;
 
909
#endif
 
910
 
 
911
  CvImageWidget *image_widget = NULL;
 
912
  GdkPixbuf *pixbuf = NULL;
 
913
 
 
914
  g_return_val_if_fail (widget != NULL, FALSE);
 
915
  g_return_val_if_fail (CV_IS_IMAGE_WIDGET (widget), FALSE);
 
916
 
 
917
  image_widget = CV_IMAGE_WIDGET (widget);
 
918
 
 
919
  if( image_widget->scaled_image ){
 
920
      // center image in available region
 
921
      int x0 = (gtk_widget_get_allocated_width(widget) - image_widget->scaled_image->cols)/2;
 
922
      int y0 = (gtk_widget_get_allocated_height(widget) - image_widget->scaled_image->rows)/2;
 
923
 
 
924
      pixbuf = gdk_pixbuf_new_from_data(image_widget->scaled_image->data.ptr, GDK_COLORSPACE_RGB, false,
 
925
          8, MIN(image_widget->scaled_image->cols, gtk_widget_get_allocated_width(widget)),
 
926
          MIN(image_widget->scaled_image->rows, gtk_widget_get_allocated_height(widget)),
 
927
          image_widget->scaled_image->step, NULL, NULL);
 
928
 
 
929
      gdk_cairo_set_source_pixbuf(cr, pixbuf, x0, y0);
 
930
  }
 
931
  else if( image_widget->original_image ){
 
932
      pixbuf = gdk_pixbuf_new_from_data(image_widget->original_image->data.ptr, GDK_COLORSPACE_RGB, false,
 
933
          8, MIN(image_widget->original_image->cols, gtk_widget_get_allocated_width(widget)),
 
934
          MIN(image_widget->original_image->rows, gtk_widget_get_allocated_height(widget)),
 
935
          image_widget->original_image->step, NULL, NULL);
 
936
      gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
 
937
  }
 
938
 
 
939
  cairo_paint(cr);
 
940
  g_object_unref(pixbuf);
 
941
  return TRUE;
 
942
}
 
943
 
 
944
#else
 
945
static gboolean cvImageWidget_expose(GtkWidget* widget, GdkEventExpose* event, gpointer data)
 
946
{
 
947
#ifdef HAVE_OPENGL
 
948
    CvWindow* window = (CvWindow*)data;
 
949
 
 
950
    if (window->useGl)
 
951
    {
 
952
        drawGl(window);
 
953
        return TRUE;
 
954
    }
 
955
#else
 
956
    (void)data;
 
957
#endif
 
958
 
 
959
  CvImageWidget *image_widget = NULL;
 
960
  cairo_t *cr = NULL;
 
961
  GdkPixbuf *pixbuf = NULL;
 
962
 
 
963
  g_return_val_if_fail (widget != NULL, FALSE);
 
964
  g_return_val_if_fail (CV_IS_IMAGE_WIDGET (widget), FALSE);
 
965
  g_return_val_if_fail (event != NULL, FALSE);
 
966
 
 
967
  if (event->count > 0)
 
968
    return FALSE;
 
969
 
 
970
  cr = gdk_cairo_create(widget->window);
 
971
  image_widget = CV_IMAGE_WIDGET (widget);
 
972
 
 
973
  if( image_widget->scaled_image ){
 
974
      // center image in available region
 
975
      int x0 = (widget->allocation.width - image_widget->scaled_image->cols)/2;
 
976
      int y0 = (widget->allocation.height - image_widget->scaled_image->rows)/2;
 
977
 
 
978
      pixbuf = gdk_pixbuf_new_from_data(image_widget->scaled_image->data.ptr, GDK_COLORSPACE_RGB, false,
 
979
          8, MIN(image_widget->scaled_image->cols, widget->allocation.width),
 
980
          MIN(image_widget->scaled_image->rows, widget->allocation.height),
 
981
          image_widget->scaled_image->step, NULL, NULL);
 
982
 
 
983
      gdk_cairo_set_source_pixbuf(cr, pixbuf, x0, y0);
 
984
  }
 
985
  else if( image_widget->original_image ){
 
986
      pixbuf = gdk_pixbuf_new_from_data(image_widget->original_image->data.ptr, GDK_COLORSPACE_RGB, false,
 
987
          8, MIN(image_widget->original_image->cols, widget->allocation.width),
 
988
          MIN(image_widget->original_image->rows, widget->allocation.height),
 
989
          image_widget->original_image->step, NULL, NULL);
 
990
      gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
 
991
  }
 
992
 
 
993
  cairo_paint(cr);
 
994
  g_object_unref(pixbuf);
 
995
  cairo_destroy(cr);
 
996
  return TRUE;
 
997
}
 
998
#endif //GTK_VERSION3
 
999
 
 
1000
CV_IMPL int cvNamedWindow( const char* name, int flags )
 
1001
{
 
1002
    int result = 0;
 
1003
    CV_FUNCNAME( "cvNamedWindow" );
 
1004
 
 
1005
    __BEGIN__;
 
1006
 
 
1007
    CvWindow* window;
 
1008
    int len;
 
1009
 
 
1010
    cvInitSystem(1,(char**)&name);
 
1011
    if( !name )
 
1012
        CV_ERROR( CV_StsNullPtr, "NULL name string" );
 
1013
 
 
1014
    // Check the name in the storage
 
1015
    if( icvFindWindowByName( name ) != 0 )
 
1016
    {
 
1017
        result = 1;
 
1018
        EXIT;
 
1019
    }
 
1020
 
 
1021
    len = strlen(name);
 
1022
    CV_CALL( window = (CvWindow*)cvAlloc(sizeof(CvWindow) + len + 1));
 
1023
    memset( window, 0, sizeof(*window));
 
1024
    window->name = (char*)(window + 1);
 
1025
    memcpy( window->name, name, len + 1 );
 
1026
    window->flags = flags;
 
1027
    window->signature = CV_WINDOW_MAGIC_VAL;
 
1028
    window->last_key = 0;
 
1029
    window->on_mouse = 0;
 
1030
    window->on_mouse_param = 0;
 
1031
    memset( &window->toolbar, 0, sizeof(window->toolbar));
 
1032
    window->next = hg_windows;
 
1033
    window->prev = 0;
 
1034
    window->status = CV_WINDOW_NORMAL;//YV
 
1035
 
 
1036
    CV_LOCK_MUTEX();
 
1037
 
 
1038
    window->frame = gtk_window_new( GTK_WINDOW_TOPLEVEL );
 
1039
 
 
1040
    window->paned = gtk_vbox_new( FALSE, 0 );
 
1041
    window->widget = cvImageWidgetNew( flags );
 
1042
    gtk_box_pack_end( GTK_BOX(window->paned), window->widget, TRUE, TRUE, 0 );
 
1043
    gtk_widget_show( window->widget );
 
1044
    gtk_container_add( GTK_CONTAINER(window->frame), window->paned );
 
1045
    gtk_widget_show( window->paned );
 
1046
 
 
1047
#ifndef HAVE_OPENGL
 
1048
    if (flags & CV_WINDOW_OPENGL)
 
1049
        CV_ERROR( CV_OpenGlNotSupported, "Library was built without OpenGL support" );
 
1050
#else
 
1051
    if (flags & CV_WINDOW_OPENGL)
 
1052
        createGlContext(window);
 
1053
 
 
1054
    window->glDrawCallback = 0;
 
1055
    window->glDrawData = 0;
 
1056
#endif
 
1057
 
 
1058
    //
 
1059
    // configure event handlers
 
1060
    // TODO -- move this to CvImageWidget ?
 
1061
    g_signal_connect( window->frame, "key-press-event",
 
1062
                        G_CALLBACK(icvOnKeyPress), window );
 
1063
    g_signal_connect( window->widget, "button-press-event",
 
1064
                        G_CALLBACK(icvOnMouse), window );
 
1065
    g_signal_connect( window->widget, "button-release-event",
 
1066
                        G_CALLBACK(icvOnMouse), window );
 
1067
    g_signal_connect( window->widget, "motion-notify-event",
 
1068
                        G_CALLBACK(icvOnMouse), window );
 
1069
    g_signal_connect( window->frame, "delete-event",
 
1070
                        G_CALLBACK(icvOnClose), window );
 
1071
#if defined(GTK_VERSION3)
 
1072
    g_signal_connect( window->widget, "draw",
 
1073
                        G_CALLBACK(cvImageWidget_draw), window );
 
1074
#else
 
1075
    g_signal_connect( window->widget, "expose-event",
 
1076
                        G_CALLBACK(cvImageWidget_expose), window );
 
1077
#endif //GTK_VERSION3
 
1078
 
 
1079
    gtk_widget_add_events (window->widget, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK) ;
 
1080
 
 
1081
    gtk_widget_show( window->frame );
 
1082
    gtk_window_set_title( GTK_WINDOW(window->frame), name );
 
1083
 
 
1084
    if( hg_windows )
 
1085
        hg_windows->prev = window;
 
1086
    hg_windows = window;
 
1087
 
 
1088
    gtk_window_set_resizable( GTK_WINDOW(window->frame), (flags & CV_WINDOW_AUTOSIZE) == 0 );
 
1089
 
 
1090
 
 
1091
    // allow window to be resized
 
1092
    if( (flags & CV_WINDOW_AUTOSIZE)==0 ){
 
1093
        GdkGeometry geometry;
 
1094
        geometry.min_width = 50;
 
1095
        geometry.min_height = 50;
 
1096
        gtk_window_set_geometry_hints( GTK_WINDOW( window->frame ), GTK_WIDGET( window->widget ),
 
1097
            &geometry, (GdkWindowHints) (GDK_HINT_MIN_SIZE));
 
1098
    }
 
1099
 
 
1100
    CV_UNLOCK_MUTEX();
 
1101
 
 
1102
#ifdef HAVE_OPENGL
 
1103
    if (window->useGl)
 
1104
        cvSetOpenGlContext(name);
 
1105
#endif
 
1106
 
 
1107
    result = 1;
 
1108
    __END__;
 
1109
 
 
1110
    return result;
 
1111
}
 
1112
 
 
1113
 
 
1114
#ifdef HAVE_OPENGL
 
1115
 
 
1116
CV_IMPL void cvSetOpenGlContext(const char* name)
 
1117
{
 
1118
    CvWindow* window;
 
1119
    GdkGLContext* glcontext;
 
1120
    GdkGLDrawable* gldrawable;
 
1121
 
 
1122
    CV_FUNCNAME( "cvSetOpenGlContext" );
 
1123
 
 
1124
    __BEGIN__;
 
1125
 
 
1126
    if(!name)
 
1127
        CV_ERROR( CV_StsNullPtr, "NULL name string" );
 
1128
 
 
1129
    window = icvFindWindowByName( name );
 
1130
    if (!window)
 
1131
        CV_ERROR( CV_StsNullPtr, "NULL window" );
 
1132
 
 
1133
    if (!window->useGl)
 
1134
        CV_ERROR( CV_OpenGlNotSupported, "Window doesn't support OpenGL" );
 
1135
 
 
1136
    glcontext = gtk_widget_get_gl_context(window->widget);
 
1137
    gldrawable = gtk_widget_get_gl_drawable(window->widget);
 
1138
 
 
1139
    if (!gdk_gl_drawable_make_current(gldrawable, glcontext))
 
1140
        CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
 
1141
 
 
1142
    __END__;
 
1143
}
 
1144
 
 
1145
CV_IMPL void cvUpdateWindow(const char* name)
 
1146
{
 
1147
    CV_FUNCNAME( "cvUpdateWindow" );
 
1148
 
 
1149
    __BEGIN__;
 
1150
 
 
1151
    CvWindow* window;
 
1152
 
 
1153
    if (!name)
 
1154
        CV_ERROR( CV_StsNullPtr, "NULL name string" );
 
1155
 
 
1156
    window = icvFindWindowByName( name );
 
1157
    if (!window)
 
1158
        EXIT;
 
1159
 
 
1160
    // window does not refresh without this
 
1161
    gtk_widget_queue_draw( GTK_WIDGET(window->widget) );
 
1162
 
 
1163
    __END__;
 
1164
}
 
1165
 
 
1166
CV_IMPL void cvSetOpenGlDrawCallback(const char* name, CvOpenGlDrawCallback callback, void* userdata)
 
1167
{
 
1168
    CvWindow* window;
 
1169
 
 
1170
    CV_FUNCNAME( "cvCreateOpenGLCallback" );
 
1171
 
 
1172
    __BEGIN__;
 
1173
 
 
1174
    if(!name)
 
1175
        CV_ERROR( CV_StsNullPtr, "NULL name string" );
 
1176
 
 
1177
    window = icvFindWindowByName( name );
 
1178
    if( !window )
 
1179
        EXIT;
 
1180
 
 
1181
    if (!window->useGl)
 
1182
        CV_ERROR( CV_OpenGlNotSupported, "Window was created without OpenGL context" );
 
1183
 
 
1184
    window->glDrawCallback = callback;
 
1185
    window->glDrawData = userdata;
 
1186
 
 
1187
    __END__;
 
1188
}
 
1189
 
 
1190
#endif // HAVE_OPENGL
 
1191
 
 
1192
 
 
1193
 
 
1194
 
 
1195
static void icvDeleteWindow( CvWindow* window )
 
1196
{
 
1197
    CvTrackbar* trackbar;
 
1198
 
 
1199
    if( window->prev )
 
1200
        window->prev->next = window->next;
 
1201
    else
 
1202
        hg_windows = window->next;
 
1203
 
 
1204
    if( window->next )
 
1205
        window->next->prev = window->prev;
 
1206
 
 
1207
    window->prev = window->next = 0;
 
1208
 
 
1209
    gtk_widget_destroy( window->frame );
 
1210
 
 
1211
    for( trackbar = window->toolbar.first; trackbar != 0; )
 
1212
    {
 
1213
        CvTrackbar* next = trackbar->next;
 
1214
        cvFree( &trackbar );
 
1215
        trackbar = next;
 
1216
    }
 
1217
 
 
1218
    cvFree( &window );
 
1219
#ifdef HAVE_GTHREAD
 
1220
    // if last window, send key press signal
 
1221
    // to jump out of any waiting cvWaitKey's
 
1222
    if(hg_windows==0 && thread_started){
 
1223
        g_cond_broadcast(cond_have_key);
 
1224
    }
 
1225
#endif
 
1226
}
 
1227
 
 
1228
 
 
1229
CV_IMPL void cvDestroyWindow( const char* name )
 
1230
{
 
1231
    CV_FUNCNAME( "cvDestroyWindow" );
 
1232
 
 
1233
    __BEGIN__;
 
1234
 
 
1235
    CvWindow* window;
 
1236
 
 
1237
    if(!name)
 
1238
        CV_ERROR( CV_StsNullPtr, "NULL name string" );
 
1239
 
 
1240
    window = icvFindWindowByName( name );
 
1241
    if( !window )
 
1242
        EXIT;
 
1243
 
 
1244
    // note that it is possible for the update thread to run this function
 
1245
    // if there is a call to cvShowImage in a mouse callback
 
1246
    // (this would produce a deadlock on window_mutex)
 
1247
    CV_LOCK_MUTEX();
 
1248
 
 
1249
    icvDeleteWindow( window );
 
1250
 
 
1251
    CV_UNLOCK_MUTEX();
 
1252
 
 
1253
    __END__;
 
1254
}
 
1255
 
 
1256
 
 
1257
CV_IMPL void
 
1258
cvDestroyAllWindows( void )
 
1259
{
 
1260
    CV_LOCK_MUTEX();
 
1261
 
 
1262
    while( hg_windows )
 
1263
    {
 
1264
        CvWindow* window = hg_windows;
 
1265
        icvDeleteWindow( window );
 
1266
    }
 
1267
    CV_UNLOCK_MUTEX();
 
1268
}
 
1269
 
 
1270
// CvSize icvCalcOptimalWindowSize( CvWindow * window, CvSize new_image_size){
 
1271
//     CvSize window_size;
 
1272
//     GtkWidget * toplevel = gtk_widget_get_toplevel( window->frame );
 
1273
//     gdk_drawable_get_size( GDK_DRAWABLE(toplevel->window),
 
1274
//             &window_size.width, &window_size.height );
 
1275
 
 
1276
//     window_size.width = window_size.width + new_image_size.width - window->widget->allocation.width;
 
1277
//     window_size.height = window_size.height + new_image_size.height - window->widget->allocation.height;
 
1278
 
 
1279
//     return window_size;
 
1280
// }
 
1281
 
 
1282
CV_IMPL void
 
1283
cvShowImage( const char* name, const CvArr* arr )
 
1284
{
 
1285
    CV_FUNCNAME( "cvShowImage" );
 
1286
 
 
1287
    __BEGIN__;
 
1288
 
 
1289
    CvWindow* window;
 
1290
 
 
1291
    if( !name )
 
1292
        CV_ERROR( CV_StsNullPtr, "NULL name" );
 
1293
 
 
1294
    CV_LOCK_MUTEX();
 
1295
 
 
1296
    window = icvFindWindowByName(name);
 
1297
    if(!window)
 
1298
    {
 
1299
        cvNamedWindow(name, 1);
 
1300
        window = icvFindWindowByName(name);
 
1301
    }
 
1302
 
 
1303
    if( window && arr )
 
1304
    {
 
1305
    #ifdef HAVE_OPENGL
 
1306
        if (window->useGl)
 
1307
        {
 
1308
            cv::imshow(name, cv::cvarrToMat(arr));
 
1309
            return;
 
1310
        }
 
1311
    #endif
 
1312
 
 
1313
        CvImageWidget * image_widget = CV_IMAGE_WIDGET( window->widget );
 
1314
        cvImageWidgetSetImage( image_widget, arr );
 
1315
    }
 
1316
 
 
1317
    CV_UNLOCK_MUTEX();
 
1318
 
 
1319
    __END__;
 
1320
}
 
1321
 
 
1322
CV_IMPL void cvResizeWindow(const char* name, int width, int height )
 
1323
{
 
1324
    CV_FUNCNAME( "cvResizeWindow" );
 
1325
 
 
1326
    __BEGIN__;
 
1327
 
 
1328
    CvWindow* window;
 
1329
    CvImageWidget * image_widget;
 
1330
 
 
1331
    if( !name )
 
1332
        CV_ERROR( CV_StsNullPtr, "NULL name" );
 
1333
 
 
1334
    window = icvFindWindowByName(name);
 
1335
    if(!window)
 
1336
        EXIT;
 
1337
 
 
1338
    image_widget = CV_IMAGE_WIDGET( window->widget );
 
1339
    //if(image_widget->flags & CV_WINDOW_AUTOSIZE)
 
1340
        //EXIT;
 
1341
 
 
1342
    CV_LOCK_MUTEX();
 
1343
 
 
1344
    gtk_window_set_resizable( GTK_WINDOW(window->frame), 1 );
 
1345
    gtk_window_resize( GTK_WINDOW(window->frame), width, height );
 
1346
 
 
1347
    // disable initial resize since presumably user wants to keep
 
1348
    // this window size
 
1349
    image_widget->flags &= ~CV_WINDOW_NO_IMAGE;
 
1350
 
 
1351
    CV_UNLOCK_MUTEX();
 
1352
 
 
1353
    __END__;
 
1354
}
 
1355
 
 
1356
 
 
1357
CV_IMPL void cvMoveWindow( const char* name, int x, int y )
 
1358
{
 
1359
    CV_FUNCNAME( "cvMoveWindow" );
 
1360
 
 
1361
    __BEGIN__;
 
1362
 
 
1363
    CvWindow* window;
 
1364
 
 
1365
    if( !name )
 
1366
        CV_ERROR( CV_StsNullPtr, "NULL name" );
 
1367
 
 
1368
    window = icvFindWindowByName(name);
 
1369
    if(!window)
 
1370
        EXIT;
 
1371
 
 
1372
    CV_LOCK_MUTEX();
 
1373
 
 
1374
    gtk_window_move( GTK_WINDOW(window->frame), x, y );
 
1375
 
 
1376
    CV_UNLOCK_MUTEX();
 
1377
 
 
1378
    __END__;
 
1379
}
 
1380
 
 
1381
 
 
1382
static CvTrackbar*
 
1383
icvFindTrackbarByName( const CvWindow* window, const char* name )
 
1384
{
 
1385
    CvTrackbar* trackbar = window->toolbar.first;
 
1386
 
 
1387
    for( ; trackbar != 0 && strcmp( trackbar->name, name ) != 0; trackbar = trackbar->next )
 
1388
        ;
 
1389
 
 
1390
    return trackbar;
 
1391
}
 
1392
 
 
1393
static int
 
1394
icvCreateTrackbar( const char* trackbar_name, const char* window_name,
 
1395
                   int* val, int count, CvTrackbarCallback on_notify,
 
1396
                   CvTrackbarCallback2 on_notify2, void* userdata )
 
1397
{
 
1398
    int result = 0;
 
1399
 
 
1400
    CV_FUNCNAME( "icvCreateTrackbar" );
 
1401
 
 
1402
    __BEGIN__;
 
1403
 
 
1404
    /*char slider_name[32];*/
 
1405
    CvWindow* window = 0;
 
1406
    CvTrackbar* trackbar = 0;
 
1407
 
 
1408
    if( !window_name || !trackbar_name )
 
1409
        CV_ERROR( CV_StsNullPtr, "NULL window or trackbar name" );
 
1410
 
 
1411
    if( count <= 0 )
 
1412
        CV_ERROR( CV_StsOutOfRange, "Bad trackbar maximal value" );
 
1413
 
 
1414
    window = icvFindWindowByName(window_name);
 
1415
    if( !window )
 
1416
        EXIT;
 
1417
 
 
1418
    trackbar = icvFindTrackbarByName(window,trackbar_name);
 
1419
 
 
1420
    CV_LOCK_MUTEX();
 
1421
 
 
1422
    if( !trackbar )
 
1423
    {
 
1424
        int len = strlen(trackbar_name);
 
1425
        trackbar = (CvTrackbar*)cvAlloc(sizeof(CvTrackbar) + len + 1);
 
1426
        memset( trackbar, 0, sizeof(*trackbar));
 
1427
        trackbar->signature = CV_TRACKBAR_MAGIC_VAL;
 
1428
        trackbar->name = (char*)(trackbar+1);
 
1429
        memcpy( trackbar->name, trackbar_name, len + 1 );
 
1430
        trackbar->parent = window;
 
1431
        trackbar->next = window->toolbar.first;
 
1432
        window->toolbar.first = trackbar;
 
1433
 
 
1434
        GtkWidget* hscale_box = gtk_hbox_new( FALSE, 10 );
 
1435
        GtkWidget* hscale_label = gtk_label_new( trackbar_name );
 
1436
        GtkWidget* hscale = gtk_hscale_new_with_range( 0, count, 1 );
 
1437
        gtk_scale_set_digits( GTK_SCALE(hscale), 0 );
 
1438
        //gtk_scale_set_value_pos( hscale, GTK_POS_TOP );
 
1439
        gtk_scale_set_draw_value( GTK_SCALE(hscale), TRUE );
 
1440
 
 
1441
        trackbar->widget = hscale;
 
1442
        gtk_box_pack_start( GTK_BOX(hscale_box), hscale_label, FALSE, FALSE, 5 );
 
1443
        gtk_widget_show( hscale_label );
 
1444
        gtk_box_pack_start( GTK_BOX(hscale_box), hscale, TRUE, TRUE, 5 );
 
1445
        gtk_widget_show( hscale );
 
1446
        gtk_box_pack_start( GTK_BOX(window->paned), hscale_box, FALSE, FALSE, 5 );
 
1447
        gtk_widget_show( hscale_box );
 
1448
 
 
1449
    }
 
1450
 
 
1451
    if( val )
 
1452
    {
 
1453
        int value = *val;
 
1454
        if( value < 0 )
 
1455
            value = 0;
 
1456
        if( value > count )
 
1457
            value = count;
 
1458
        gtk_range_set_value( GTK_RANGE(trackbar->widget), value );
 
1459
        trackbar->pos = value;
 
1460
        trackbar->data = val;
 
1461
    }
 
1462
 
 
1463
    trackbar->maxval = count;
 
1464
    trackbar->notify = on_notify;
 
1465
    trackbar->notify2 = on_notify2;
 
1466
    trackbar->userdata = userdata;
 
1467
    g_signal_connect( trackbar->widget, "value-changed",
 
1468
                        G_CALLBACK(icvOnTrackbar), trackbar );
 
1469
 
 
1470
    // queue a widget resize to trigger a window resize to
 
1471
    // compensate for the addition of trackbars
 
1472
    gtk_widget_queue_resize( GTK_WIDGET(window->widget) );
 
1473
 
 
1474
 
 
1475
    CV_UNLOCK_MUTEX();
 
1476
 
 
1477
    result = 1;
 
1478
 
 
1479
    __END__;
 
1480
 
 
1481
    return result;
 
1482
}
 
1483
 
 
1484
 
 
1485
CV_IMPL int
 
1486
cvCreateTrackbar( const char* trackbar_name, const char* window_name,
 
1487
                  int* val, int count, CvTrackbarCallback on_notify )
 
1488
{
 
1489
    return icvCreateTrackbar(trackbar_name, window_name, val, count,
 
1490
                             on_notify, 0, 0);
 
1491
}
 
1492
 
 
1493
 
 
1494
CV_IMPL int
 
1495
cvCreateTrackbar2( const char* trackbar_name, const char* window_name,
 
1496
                   int* val, int count, CvTrackbarCallback2 on_notify2,
 
1497
                   void* userdata )
 
1498
{
 
1499
    return icvCreateTrackbar(trackbar_name, window_name, val, count,
 
1500
                             0, on_notify2, userdata);
 
1501
}
 
1502
 
 
1503
 
 
1504
CV_IMPL void
 
1505
cvSetMouseCallback( const char* window_name, CvMouseCallback on_mouse, void* param )
 
1506
{
 
1507
    CV_FUNCNAME( "cvSetMouseCallback" );
 
1508
 
 
1509
    __BEGIN__;
 
1510
 
 
1511
    CvWindow* window = 0;
 
1512
 
 
1513
    if( !window_name )
 
1514
        CV_ERROR( CV_StsNullPtr, "NULL window name" );
 
1515
 
 
1516
    window = icvFindWindowByName(window_name);
 
1517
    if( !window )
 
1518
        EXIT;
 
1519
 
 
1520
    window->on_mouse = on_mouse;
 
1521
    window->on_mouse_param = param;
 
1522
 
 
1523
    __END__;
 
1524
}
 
1525
 
 
1526
 
 
1527
CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name )
 
1528
{
 
1529
    int pos = -1;
 
1530
 
 
1531
    CV_FUNCNAME( "cvGetTrackbarPos" );
 
1532
 
 
1533
    __BEGIN__;
 
1534
 
 
1535
    CvWindow* window;
 
1536
    CvTrackbar* trackbar = 0;
 
1537
 
 
1538
    if( trackbar_name == 0 || window_name == 0 )
 
1539
        CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
 
1540
 
 
1541
    window = icvFindWindowByName( window_name );
 
1542
    if( window )
 
1543
        trackbar = icvFindTrackbarByName( window, trackbar_name );
 
1544
 
 
1545
    if( trackbar )
 
1546
        pos = trackbar->pos;
 
1547
 
 
1548
    __END__;
 
1549
 
 
1550
    return pos;
 
1551
}
 
1552
 
 
1553
 
 
1554
CV_IMPL void cvSetTrackbarPos( const char* trackbar_name, const char* window_name, int pos )
 
1555
{
 
1556
    CV_FUNCNAME( "cvSetTrackbarPos" );
 
1557
 
 
1558
    __BEGIN__;
 
1559
 
 
1560
    CvWindow* window;
 
1561
    CvTrackbar* trackbar = 0;
 
1562
 
 
1563
    if( trackbar_name == 0 || window_name == 0 )
 
1564
        CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
 
1565
 
 
1566
    window = icvFindWindowByName( window_name );
 
1567
    if( window )
 
1568
        trackbar = icvFindTrackbarByName( window, trackbar_name );
 
1569
 
 
1570
    if( trackbar )
 
1571
    {
 
1572
        if( pos < 0 )
 
1573
            pos = 0;
 
1574
 
 
1575
        if( pos > trackbar->maxval )
 
1576
            pos = trackbar->maxval;
 
1577
    }
 
1578
 
 
1579
    CV_LOCK_MUTEX();
 
1580
 
 
1581
    gtk_range_set_value( GTK_RANGE(trackbar->widget), pos );
 
1582
 
 
1583
    CV_UNLOCK_MUTEX();
 
1584
 
 
1585
    __END__;
 
1586
}
 
1587
 
 
1588
 
 
1589
CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval)
 
1590
{
 
1591
    CV_FUNCNAME("cvSetTrackbarMax");
 
1592
 
 
1593
    __BEGIN__;
 
1594
 
 
1595
    if (maxval >= 0)
 
1596
    {
 
1597
        CvWindow* window = 0;
 
1598
        CvTrackbar* trackbar = 0;
 
1599
 
 
1600
        if (trackbar_name == 0 || window_name == 0)
 
1601
        {
 
1602
            CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name");
 
1603
        }
 
1604
 
 
1605
        window = icvFindWindowByName( window_name );
 
1606
        if (window)
 
1607
        {
 
1608
            trackbar = icvFindTrackbarByName(window, trackbar_name);
 
1609
            if (trackbar)
 
1610
            {
 
1611
                trackbar->maxval = (trackbar->minval>maxval)?trackbar->minval:maxval;
 
1612
 
 
1613
                CV_LOCK_MUTEX();
 
1614
 
 
1615
                gtk_range_set_range(GTK_RANGE(trackbar->widget), 0, trackbar->maxval);
 
1616
 
 
1617
                CV_UNLOCK_MUTEX();
 
1618
            }
 
1619
        }
 
1620
    }
 
1621
 
 
1622
    __END__;
 
1623
}
 
1624
 
 
1625
 
 
1626
CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval)
 
1627
{
 
1628
    CV_FUNCNAME("cvSetTrackbarMin");
 
1629
 
 
1630
    __BEGIN__;
 
1631
 
 
1632
    if (minval >= 0)
 
1633
    {
 
1634
        CvWindow* window = 0;
 
1635
        CvTrackbar* trackbar = 0;
 
1636
 
 
1637
        if (trackbar_name == 0 || window_name == 0)
 
1638
        {
 
1639
            CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name");
 
1640
        }
 
1641
 
 
1642
        window = icvFindWindowByName( window_name );
 
1643
        if (window)
 
1644
        {
 
1645
            trackbar = icvFindTrackbarByName(window, trackbar_name);
 
1646
            if (trackbar)
 
1647
            {
 
1648
                trackbar->minval = (minval<trackbar->maxval)?minval:trackbar->maxval;
 
1649
 
 
1650
                CV_LOCK_MUTEX();
 
1651
 
 
1652
                gtk_range_set_range(GTK_RANGE(trackbar->widget), minval, trackbar->maxval);
 
1653
 
 
1654
                CV_UNLOCK_MUTEX();
 
1655
            }
 
1656
        }
 
1657
    }
 
1658
 
 
1659
    __END__;
 
1660
}
 
1661
 
 
1662
 
 
1663
CV_IMPL void* cvGetWindowHandle( const char* window_name )
 
1664
{
 
1665
    void* widget = 0;
 
1666
 
 
1667
    CV_FUNCNAME( "cvGetWindowHandle" );
 
1668
 
 
1669
    __BEGIN__;
 
1670
 
 
1671
    CvWindow* window;
 
1672
 
 
1673
    if( window_name == 0 )
 
1674
        CV_ERROR( CV_StsNullPtr, "NULL window name" );
 
1675
 
 
1676
    window = icvFindWindowByName( window_name );
 
1677
    if( window )
 
1678
        widget = (void*)window->widget;
 
1679
 
 
1680
    __END__;
 
1681
 
 
1682
    return widget;
 
1683
}
 
1684
 
 
1685
 
 
1686
CV_IMPL const char* cvGetWindowName( void* window_handle )
 
1687
{
 
1688
    const char* window_name = "";
 
1689
 
 
1690
    CV_FUNCNAME( "cvGetWindowName" );
 
1691
 
 
1692
    __BEGIN__;
 
1693
 
 
1694
    CvWindow* window;
 
1695
 
 
1696
    if( window_handle == 0 )
 
1697
        CV_ERROR( CV_StsNullPtr, "NULL window" );
 
1698
 
 
1699
    window = icvWindowByWidget( (GtkWidget*)window_handle );
 
1700
    if( window )
 
1701
        window_name = window->name;
 
1702
 
 
1703
    __END__;
 
1704
 
 
1705
    return window_name;
 
1706
}
 
1707
 
 
1708
static GtkFileFilter* icvMakeGtkFilter(const char* name, const char* patterns, GtkFileFilter* images)
 
1709
{
 
1710
    GtkFileFilter* filter = gtk_file_filter_new();
 
1711
    gtk_file_filter_set_name(filter, name);
 
1712
 
 
1713
    while(patterns[0])
 
1714
    {
 
1715
        gtk_file_filter_add_pattern(filter, patterns);
 
1716
        gtk_file_filter_add_pattern(images, patterns);
 
1717
        patterns += strlen(patterns) + 1;
 
1718
    }
 
1719
 
 
1720
    return filter;
 
1721
}
 
1722
 
 
1723
static void icvShowSaveAsDialog(GtkWidget* widget, CvWindow* window)
 
1724
{
 
1725
    if (!window || !widget)
 
1726
        return;
 
1727
 
 
1728
    CvImageWidget* image_widget = CV_IMAGE_WIDGET(window->widget);
 
1729
    if (!image_widget || !image_widget->original_image)
 
1730
        return;
 
1731
 
 
1732
    GtkWidget* dialog = gtk_file_chooser_dialog_new("Save As...",
 
1733
                      GTK_WINDOW(widget),
 
1734
                      GTK_FILE_CHOOSER_ACTION_SAVE,
 
1735
                      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
1736
                      GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
 
1737
                      NULL);
 
1738
    gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
 
1739
 
 
1740
    cv::String sname = gtk_window_get_title(GTK_WINDOW(window->frame));
 
1741
    sname = sname.substr(sname.find_last_of("\\/") + 1) + ".png";
 
1742
    gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), sname.c_str());
 
1743
 
 
1744
    GtkFileFilter* filter_all = gtk_file_filter_new();
 
1745
    gtk_file_filter_set_name(filter_all, "All Files");
 
1746
    gtk_file_filter_add_pattern(filter_all, "*");
 
1747
 
 
1748
    GtkFileFilter* filter_images = gtk_file_filter_new();
 
1749
    gtk_file_filter_set_name(filter_images, "All Images");
 
1750
 
 
1751
    GtkFileFilter* file_filters[] = {
 
1752
        icvMakeGtkFilter("Portable Network Graphics files (*.png)",               "*.png\0",                             filter_images),
 
1753
        icvMakeGtkFilter("JPEG files (*.jpeg;*.jpg;*.jpe)",                       "*.jpeg\0*.jpg\0*.jpe\0",              filter_images),
 
1754
        icvMakeGtkFilter("Windows bitmap (*.bmp;*.dib)",                          "*.bmp\0*.dib\0",                      filter_images),
 
1755
        icvMakeGtkFilter("TIFF Files (*.tiff;*.tif)",                             "*.tiff\0*.tif\0",                     filter_images),
 
1756
        icvMakeGtkFilter("JPEG-2000 files (*.jp2)",                               "*.jp2\0",                             filter_images),
 
1757
        icvMakeGtkFilter("WebP files (*.webp)",                                   "*.webp\0",                            filter_images),
 
1758
        icvMakeGtkFilter("Portable image format (*.pbm;*.pgm;*.ppm;*.pxm;*.pnm)", "*.pbm\0*.pgm\0*.ppm\0*.pxm\0*.pnm\0", filter_images),
 
1759
        icvMakeGtkFilter("OpenEXR Image files (*.exr)",                           "*.exr\0",                             filter_images),
 
1760
        icvMakeGtkFilter("Radiance HDR (*.hdr;*.pic)",                            "*.hdr\0*.pic\0",                      filter_images),
 
1761
        icvMakeGtkFilter("Sun raster files (*.sr;*.ras)",                         "*.sr\0*.ras\0",                       filter_images),
 
1762
        filter_images,
 
1763
        filter_all
 
1764
    };
 
1765
 
 
1766
    for (size_t idx = 0; idx < sizeof(file_filters)/sizeof(file_filters[0]); ++idx)
 
1767
        gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), file_filters[idx]);
 
1768
    gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter_images);
 
1769
 
 
1770
    cv::String filename;
 
1771
    if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
 
1772
    {
 
1773
        char* fname = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
 
1774
        filename = fname;
 
1775
        g_free(fname);
 
1776
    }
 
1777
    gtk_widget_destroy(dialog);
 
1778
 
 
1779
    if (!filename.empty())
 
1780
    {
 
1781
        cv::Mat bgr;
 
1782
        cv::cvtColor(cv::cvarrToMat(image_widget->original_image), bgr, cv::COLOR_RGB2BGR);
 
1783
        cv::imwrite(filename, bgr);
 
1784
    }
 
1785
}
 
1786
 
 
1787
#if defined (GTK_VERSION3)
 
1788
#define GDK_Escape GDK_KEY_Escape
 
1789
#define GDK_Return GDK_KEY_Return
 
1790
#define GDK_Linefeed GDK_KEY_Linefeed
 
1791
#define GDK_Tab GDK_KEY_Tab
 
1792
#define GDK_s GDK_KEY_s
 
1793
#define GDK_S GDK_KEY_S
 
1794
#endif //GTK_VERSION3
 
1795
 
 
1796
static gboolean icvOnKeyPress(GtkWidget* widget, GdkEventKey* event, gpointer user_data)
 
1797
{
 
1798
    int code = 0;
 
1799
 
 
1800
    if ( (event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK && (event->keyval == GDK_s || event->keyval == GDK_S))
 
1801
    {
 
1802
        try
 
1803
        {
 
1804
            icvShowSaveAsDialog(widget, (CvWindow*)user_data);
 
1805
        }
 
1806
        catch(...)
 
1807
        {
 
1808
            // suppress all exceptions here
 
1809
        }
 
1810
    }
 
1811
 
 
1812
    switch( event->keyval )
 
1813
    {
 
1814
    case GDK_Escape:
 
1815
        code = 27;
 
1816
        break;
 
1817
    case GDK_Return:
 
1818
    case GDK_Linefeed:
 
1819
        code = '\n';
 
1820
        break;
 
1821
    case GDK_Tab:
 
1822
        code = '\t';
 
1823
    break;
 
1824
    default:
 
1825
        code = event->keyval;
 
1826
    }
 
1827
 
 
1828
    code |= event->state << 16;
 
1829
 
 
1830
#ifdef HAVE_GTHREAD
 
1831
    if(thread_started) g_mutex_lock(last_key_mutex);
 
1832
#endif
 
1833
 
 
1834
    last_key = code;
 
1835
 
 
1836
#ifdef HAVE_GTHREAD
 
1837
    if(thread_started){
 
1838
        // signal any waiting threads
 
1839
        g_cond_broadcast(cond_have_key);
 
1840
        g_mutex_unlock(last_key_mutex);
 
1841
    }
 
1842
#endif
 
1843
 
 
1844
    return FALSE;
 
1845
}
 
1846
 
 
1847
 
 
1848
static void icvOnTrackbar( GtkWidget* widget, gpointer user_data )
 
1849
{
 
1850
    int pos = cvRound( gtk_range_get_value(GTK_RANGE(widget)));
 
1851
    CvTrackbar* trackbar = (CvTrackbar*)user_data;
 
1852
 
 
1853
    if( trackbar && trackbar->signature == CV_TRACKBAR_MAGIC_VAL &&
 
1854
        trackbar->widget == widget )
 
1855
    {
 
1856
        trackbar->pos = pos;
 
1857
        if( trackbar->data )
 
1858
            *trackbar->data = pos;
 
1859
        if( trackbar->notify2 )
 
1860
            trackbar->notify2(pos, trackbar->userdata);
 
1861
        else if( trackbar->notify )
 
1862
            trackbar->notify(pos);
 
1863
    }
 
1864
}
 
1865
 
 
1866
static gboolean icvOnClose( GtkWidget* widget, GdkEvent* /*event*/, gpointer user_data )
 
1867
{
 
1868
    CvWindow* window = (CvWindow*)user_data;
 
1869
    if( window->signature == CV_WINDOW_MAGIC_VAL &&
 
1870
        window->frame == widget )
 
1871
    {
 
1872
        icvDeleteWindow(window);
 
1873
    }
 
1874
    return TRUE;
 
1875
}
 
1876
 
 
1877
 
 
1878
static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_data )
 
1879
{
 
1880
    // TODO move this logic to CvImageWidget
 
1881
    CvWindow* window = (CvWindow*)user_data;
 
1882
    CvPoint2D32f pt32f(-1., -1.);
 
1883
    CvPoint pt(-1,-1);
 
1884
    int cv_event = -1, state = 0;
 
1885
    CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget );
 
1886
 
 
1887
    if( window->signature != CV_WINDOW_MAGIC_VAL ||
 
1888
        window->widget != widget || !window->widget ||
 
1889
        !window->on_mouse /*|| !image_widget->original_image*/)
 
1890
        return FALSE;
 
1891
 
 
1892
    if( event->type == GDK_MOTION_NOTIFY )
 
1893
    {
 
1894
        GdkEventMotion* event_motion = (GdkEventMotion*)event;
 
1895
 
 
1896
        cv_event = CV_EVENT_MOUSEMOVE;
 
1897
        pt32f.x = cvRound(event_motion->x);
 
1898
        pt32f.y = cvRound(event_motion->y);
 
1899
        state = event_motion->state;
 
1900
    }
 
1901
    else if( event->type == GDK_BUTTON_PRESS ||
 
1902
             event->type == GDK_BUTTON_RELEASE ||
 
1903
             event->type == GDK_2BUTTON_PRESS )
 
1904
    {
 
1905
        GdkEventButton* event_button = (GdkEventButton*)event;
 
1906
        pt32f.x = cvRound(event_button->x);
 
1907
        pt32f.y = cvRound(event_button->y);
 
1908
 
 
1909
 
 
1910
        if( event_button->type == GDK_BUTTON_PRESS )
 
1911
        {
 
1912
            cv_event = event_button->button == 1 ? CV_EVENT_LBUTTONDOWN :
 
1913
                       event_button->button == 2 ? CV_EVENT_MBUTTONDOWN :
 
1914
                       event_button->button == 3 ? CV_EVENT_RBUTTONDOWN : 0;
 
1915
        }
 
1916
        else if( event_button->type == GDK_BUTTON_RELEASE )
 
1917
        {
 
1918
            cv_event = event_button->button == 1 ? CV_EVENT_LBUTTONUP :
 
1919
                       event_button->button == 2 ? CV_EVENT_MBUTTONUP :
 
1920
                       event_button->button == 3 ? CV_EVENT_RBUTTONUP : 0;
 
1921
        }
 
1922
        else if( event_button->type == GDK_2BUTTON_PRESS )
 
1923
        {
 
1924
            cv_event = event_button->button == 1 ? CV_EVENT_LBUTTONDBLCLK :
 
1925
                       event_button->button == 2 ? CV_EVENT_MBUTTONDBLCLK :
 
1926
                       event_button->button == 3 ? CV_EVENT_RBUTTONDBLCLK : 0;
 
1927
        }
 
1928
        state = event_button->state;
 
1929
    }
 
1930
 
 
1931
    if( cv_event >= 0 ){
 
1932
        // scale point if image is scaled
 
1933
        if( (image_widget->flags & CV_WINDOW_AUTOSIZE)==0 &&
 
1934
             image_widget->original_image &&
 
1935
             image_widget->scaled_image ){
 
1936
            // image origin is not necessarily at (0,0)
 
1937
#if defined (GTK_VERSION3)
 
1938
            int x0 = (gtk_widget_get_allocated_width(widget) - image_widget->scaled_image->cols)/2;
 
1939
            int y0 = (gtk_widget_get_allocated_height(widget) - image_widget->scaled_image->rows)/2;
 
1940
#else
 
1941
            int x0 = (widget->allocation.width - image_widget->scaled_image->cols)/2;
 
1942
            int y0 = (widget->allocation.height - image_widget->scaled_image->rows)/2;
 
1943
#endif //GTK_VERSION3
 
1944
            pt.x = cvFloor( ((pt32f.x-x0)*image_widget->original_image->cols)/
 
1945
                                            image_widget->scaled_image->cols );
 
1946
            pt.y = cvFloor( ((pt32f.y-y0)*image_widget->original_image->rows)/
 
1947
                                            image_widget->scaled_image->rows );
 
1948
        }
 
1949
        else{
 
1950
            pt = cvPointFrom32f( pt32f );
 
1951
        }
 
1952
 
 
1953
//        if((unsigned)pt.x < (unsigned)(image_widget->original_image->width) &&
 
1954
//           (unsigned)pt.y < (unsigned)(image_widget->original_image->height) )
 
1955
        {
 
1956
            int flags = (state & GDK_SHIFT_MASK ? CV_EVENT_FLAG_SHIFTKEY : 0) |
 
1957
                (state & GDK_CONTROL_MASK ? CV_EVENT_FLAG_CTRLKEY : 0) |
 
1958
                (state & (GDK_MOD1_MASK|GDK_MOD2_MASK) ? CV_EVENT_FLAG_ALTKEY : 0) |
 
1959
                (state & GDK_BUTTON1_MASK ? CV_EVENT_FLAG_LBUTTON : 0) |
 
1960
                (state & GDK_BUTTON2_MASK ? CV_EVENT_FLAG_MBUTTON : 0) |
 
1961
                (state & GDK_BUTTON3_MASK ? CV_EVENT_FLAG_RBUTTON : 0);
 
1962
            window->on_mouse( cv_event, pt.x, pt.y, flags, window->on_mouse_param );
 
1963
        }
 
1964
    }
 
1965
 
 
1966
        return FALSE;
 
1967
    }
 
1968
 
 
1969
 
 
1970
static gboolean icvAlarm( gpointer user_data )
 
1971
{
 
1972
    *(int*)user_data = 1;
 
1973
    return FALSE;
 
1974
}
 
1975
 
 
1976
 
 
1977
CV_IMPL int cvWaitKey( int delay )
 
1978
{
 
1979
#ifdef HAVE_GTHREAD
 
1980
    if(thread_started && g_thread_self()!=window_thread){
 
1981
        gboolean expired;
 
1982
        int my_last_key;
 
1983
 
 
1984
        // wait for signal or timeout if delay > 0
 
1985
        if(delay>0){
 
1986
            GTimeVal timer;
 
1987
            g_get_current_time(&timer);
 
1988
            g_time_val_add(&timer, delay*1000);
 
1989
            expired = !g_cond_timed_wait(cond_have_key, last_key_mutex, &timer);
 
1990
        }
 
1991
        else{
 
1992
            g_cond_wait(cond_have_key, last_key_mutex);
 
1993
            expired=false;
 
1994
        }
 
1995
        my_last_key = last_key;
 
1996
        g_mutex_unlock(last_key_mutex);
 
1997
        if(expired || hg_windows==0){
 
1998
            return -1;
 
1999
        }
 
2000
        return my_last_key;
 
2001
    }
 
2002
    else{
 
2003
#endif
 
2004
        int expired = 0;
 
2005
        guint timer = 0;
 
2006
        if( delay > 0 )
 
2007
            timer = g_timeout_add( delay, icvAlarm, &expired );
 
2008
        last_key = -1;
 
2009
        while( gtk_main_iteration_do(TRUE) && last_key < 0 && !expired && hg_windows != 0 )
 
2010
            ;
 
2011
 
 
2012
        if( delay > 0 && !expired )
 
2013
            g_source_remove(timer);
 
2014
#ifdef HAVE_GTHREAD
 
2015
    }
 
2016
#endif
 
2017
    return last_key;
 
2018
}
 
2019
 
 
2020
 
 
2021
#endif  // HAVE_GTK
 
2022
#endif  // WIN32
 
2023
 
 
2024
/* End of file. */