93d9e4f7aaa92dda91a8c6f38ad8fee0ebab7ae5
[platform/upstream/opencv.git] / modules / highgui / src / window_carbon.cpp
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
44 #include <Carbon/Carbon.h>
45 #include <Quicktime/Quicktime.h>//YV
46
47 #include <unistd.h>
48 #include <cstdio>
49 #include <cmath>
50
51 //#define MS_TO_TICKS(a) a*3/50
52
53 #define LABELWIDTH 64
54 #define INTERWIDGETSPACE 16
55 #define WIDGETHEIGHT 32
56 #define NO_KEY -1
57
58 struct CvWindow;
59
60 typedef struct CvTrackbar
61 {
62     int signature;
63
64     ControlRef trackbar;
65     ControlRef label;
66
67     char* name;
68     CvTrackbar* next;
69     CvWindow* parent;
70     int* data;
71     int pos;
72     int maxval;
73     int labelSize;//Yannick Verdie
74     CvTrackbarCallback notify;
75     CvTrackbarCallback2 notify2;
76     void* userdata;
77 }
78 CvTrackbar;
79
80
81 typedef struct CvWindow
82 {
83     int signature;
84
85     char* name;
86     CvWindow* prev;
87     CvWindow* next;
88
89     WindowRef window;
90     WindowRef oldwindow;//YV
91     CGImageRef imageRef;
92     int imageWidth;//FD
93     int imageHeight;//FD
94
95     CvMat* image;
96     CvMat* dst_image;
97     int converted;
98     int last_key;
99     int flags;
100     int status;//YV
101     Ptr restoreState;//YV
102
103     CvMouseCallback on_mouse;
104     void* on_mouse_param;
105
106     struct {
107         int pos;
108         int rows;
109         CvTrackbar* first;
110     }
111     toolbar;
112     int trackbarheight;
113 }
114 CvWindow;
115
116 static CvWindow* hg_windows = 0;
117
118 #define Assert(exp)                                             \
119 if( !(exp) )                                                    \
120 {                                                               \
121     printf("Assertion: %s  %s: %d\n", #exp, __FILE__, __LINE__);\
122     assert(exp);                                                \
123 }
124
125 static int wasInitialized = 0;
126 static char lastKey = NO_KEY;
127 OSStatus keyHandler(EventHandlerCallRef hcr, EventRef theEvent, void* inUserData);
128 static pascal OSStatus windowEventHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *inUserData);
129
130 static const EventTypeSpec applicationKeyboardEvents[] =
131 {
132     { kEventClassKeyboard, kEventRawKeyDown },
133 };
134
135 CV_IMPL int cvInitSystem( int argc, char** argv )
136 {
137     OSErr err = noErr;
138     if( !wasInitialized )
139     {
140
141         hg_windows = 0;
142         err = InstallApplicationEventHandler(NewEventHandlerUPP( keyHandler),GetEventTypeCount(applicationKeyboardEvents),applicationKeyboardEvents,NULL,NULL);
143         if (err != noErr)
144         {
145              fprintf(stderr,"InstallApplicationEventHandler was not ok\n");
146         }
147         wasInitialized = 1;
148     }
149
150     return 0;
151 }
152
153 // TODO: implement missing functionality
154 CV_IMPL int cvStartWindowThread()
155 {
156     return 0;
157 }
158
159 static int icvCountTrackbarInWindow( const CvWindow* window)
160 {
161     CvTrackbar* trackbar = window->toolbar.first;
162     int count = 0;
163     while (trackbar != 0) {
164         count++;
165         trackbar = trackbar->next;
166     }
167     return count;
168 }
169
170 static CvTrackbar* icvTrackbarByHandle( void * handle )
171 {
172     CvWindow* window = hg_windows;
173     CvTrackbar* trackbar = NULL;
174     while( window != 0 && window->window != handle) {
175         trackbar = window->toolbar.first;
176         while (trackbar != 0 && trackbar->trackbar != handle)
177             trackbar = trackbar->next;
178         if (trackbar != 0 && trackbar->trackbar == handle)
179             break;
180         window = window->next;
181     }
182     return trackbar;
183 }
184
185 static CvWindow* icvWindowByHandle( void * handle )
186 {
187     CvWindow* window = hg_windows;
188
189     while( window != 0 && window->window != handle)
190         window = window->next;
191
192     return window;
193 }
194
195 CV_IMPL CvWindow * icvFindWindowByName( const char* name)
196 {
197     CvWindow* window = hg_windows;
198     while( window != 0 && strcmp(name, window->name) != 0 )
199         window = window->next;
200
201     return window;
202 }
203
204 static CvTrackbar* icvFindTrackbarByName( const CvWindow* window, const char* name )
205 {
206     CvTrackbar* trackbar = window->toolbar.first;
207
208     while (trackbar != 0 && strcmp( trackbar->name, name ) != 0)
209         trackbar = trackbar->next;
210
211     return trackbar;
212 }
213
214 //FD
215 /* draw image to frame */
216 static void icvDrawImage( CvWindow* window )
217 {
218     Assert( window != 0 );
219     if( window->imageRef == 0 ) return;
220
221     CGContextRef myContext;
222     CGRect rect;
223     Rect portrect;
224     int width = window->imageWidth;
225     int height = window->imageHeight;
226
227         GetWindowPortBounds(window->window, &portrect);
228
229     if(!( window->flags & CV_WINDOW_AUTOSIZE) ) //YV
230     {
231         CGPoint origin = {0,0};
232         CGSize size = {portrect.right-portrect.left, portrect.bottom-portrect.top-window->trackbarheight};
233         rect.origin = origin; rect.size = size;
234     }
235     else
236     {
237         CGPoint origin = {0, portrect.bottom - height - window->trackbarheight};
238         CGSize size = {width, height};
239         rect.origin = origin; rect.size = size;
240     }
241
242     /* To be sybnchronous we are using this, better would be to susbcribe to the draw event and process whenever requested, we might save SOME CPU cycles*/
243     SetPortWindowPort (window->window);
244     QDBeginCGContext (GetWindowPort (window->window), &myContext);
245     CGContextSetInterpolationQuality (myContext, kCGInterpolationLow);
246     CGContextDrawImage(myContext,rect,window->imageRef);
247     CGContextFlush(myContext);// 4
248     QDEndCGContext (GetWindowPort(window->window), &myContext);// 5
249 }
250
251 //FD
252 /* update imageRef */
253 static void icvPutImage( CvWindow* window )
254 {
255     Assert( window != 0 );
256     if( window->image == 0 ) return;
257
258     CGColorSpaceRef colorspace = NULL;
259     CGDataProviderRef provider = NULL;
260     int width = window->imageWidth = window->image->cols;
261     int height = window->imageHeight = window->image->rows;
262
263     colorspace = CGColorSpaceCreateDeviceRGB();
264
265     int size = 8;
266     int nbChannels = 3;
267
268     provider = CGDataProviderCreateWithData(NULL, window->image->data.ptr, width * height , NULL );
269
270     if (window->imageRef != NULL){
271         CGImageRelease(window->imageRef);
272         window->imageRef = NULL;
273     }
274
275     window->imageRef = CGImageCreate( width, height, size , size*nbChannels , window->image->step, colorspace,  kCGImageAlphaNone , provider, NULL, true, kCGRenderingIntentDefault );
276     icvDrawImage( window );
277
278     /* release the provider's memory */
279     CGDataProviderRelease( provider );
280 }
281
282 static void icvUpdateWindowSize( const CvWindow* window )
283 {
284     int width = 0, height = 240; /* init Ã  al taille de base de l'image*/
285     Rect globalBounds;
286
287     GetWindowBounds(window->window, kWindowContentRgn, &globalBounds);
288
289     int minWidth = 320;
290
291     if( window->image ) {
292         width = MAX(MAX(window->image->width, width), minWidth);
293         height = window->image->height;
294     } else
295         width = minWidth;
296
297     height += window->trackbarheight;
298
299     //height +=WIDGETHEIGHT; /* 32 pixels are spearating tracbars from the video display */
300
301     globalBounds.right = globalBounds.left + width;
302     globalBounds.bottom = globalBounds.top + height;
303     SetWindowBounds(window->window, kWindowContentRgn, &globalBounds);
304 }
305
306 static void icvDeleteWindow( CvWindow* window )
307 {
308     CvTrackbar* trackbar;
309
310     if( window->prev )
311         window->prev->next = window->next;
312     else
313         hg_windows = window->next;
314
315     if( window->next )
316         window->next->prev = window->prev;
317
318     window->prev = window->next = 0;
319
320     cvReleaseMat( &window->image );
321     cvReleaseMat( &window->dst_image );
322
323     for( trackbar = window->toolbar.first; trackbar != 0; )
324     {
325         CvTrackbar* next = trackbar->next;
326         cvFree( (void**)&trackbar );
327         trackbar = next;
328     }
329
330     if (window->imageRef != NULL)
331         CGImageRelease(window->imageRef);
332
333     DisposeWindow (window->window);//YV
334
335     cvFree( (void**)&window );
336 }
337
338
339 CV_IMPL void cvDestroyWindow( const char* name)
340 {
341     CV_FUNCNAME( "cvDestroyWindow" );
342
343     __BEGIN__;
344
345     CvWindow* window;
346
347     if(!name)
348         CV_ERROR( CV_StsNullPtr, "NULL name string" );
349
350     window = icvFindWindowByName( name );
351     if( !window )
352         EXIT;
353
354     icvDeleteWindow( window );
355
356     __END__;
357 }
358
359
360 CV_IMPL void cvDestroyAllWindows( void )
361 {
362     while( hg_windows )
363     {
364         CvWindow* window = hg_windows;
365         icvDeleteWindow( window );
366     }
367 }
368
369
370 CV_IMPL void cvShowImage( const char* name, const CvArr* arr)
371 {
372     CV_FUNCNAME( "cvShowImage" );
373
374     __BEGIN__;
375
376     CvWindow* window;
377     int origin = 0;
378     int resize = 0;
379     CvMat stub, *image;
380
381     if( !name )
382         CV_ERROR( CV_StsNullPtr, "NULL name" );
383
384     window = icvFindWindowByName(name);
385     if(!window)
386     {
387         cvNamedWindow(name, 1);
388         window = icvFindWindowByName(name);
389     }
390
391     if( !window || !arr )
392         EXIT; // keep silence here.
393
394     if( CV_IS_IMAGE_HDR( arr ))
395         origin = ((IplImage*)arr)->origin;
396
397     CV_CALL( image = cvGetMat( arr, &stub ));
398
399     /*
400      if( !window->image )
401      cvResizeWindow( name, image->cols, image->rows );
402      */
403
404     if( window->image &&
405         !CV_ARE_SIZES_EQ(window->image, image) ) {
406         if ( ! (window->flags & CV_WINDOW_AUTOSIZE) )//FD
407             resize = 1;
408         cvReleaseMat( &window->image );
409     }
410
411     if( !window->image ) {
412         resize = 1;//FD
413         window->image = cvCreateMat( image->rows, image->cols, CV_8UC3 );
414     }
415
416     cvConvertImage( image, window->image, (origin != 0 ? CV_CVTIMG_FLIP : 0) + CV_CVTIMG_SWAP_RB );
417     icvPutImage( window );
418     if ( resize )//FD
419         icvUpdateWindowSize( window );
420
421     __END__;
422 }
423
424 CV_IMPL void cvResizeWindow( const char* name, int width, int height)
425 {
426     CV_FUNCNAME( "cvResizeWindow" );
427
428     __BEGIN__;
429
430     CvWindow* window;
431     //CvTrackbar* trackbar;
432
433     if( !name )
434         CV_ERROR( CV_StsNullPtr, "NULL name" );
435
436     window = icvFindWindowByName(name);
437     if(!window)
438         EXIT;
439
440     SizeWindow(window->window, width, height, true);
441
442     __END__;
443 }
444
445 CV_IMPL void cvMoveWindow( const char* name, int x, int y)
446 {
447     CV_FUNCNAME( "cvMoveWindow" );
448
449     __BEGIN__;
450
451     CvWindow* window;
452     //CvTrackbar* trackbar;
453
454     if( !name )
455         CV_ERROR( CV_StsNullPtr, "NULL name" );
456
457     window = icvFindWindowByName(name);
458     if(!window)
459         EXIT;
460
461     MoveWindow(window->window, x, y, true);
462
463     __END__;
464 }
465
466 void TrackbarActionProcPtr (ControlRef theControl, ControlPartCode partCode)
467 {
468     CvTrackbar * trackbar = icvTrackbarByHandle (theControl);
469
470     if (trackbar == NULL)
471     {
472         fprintf(stderr,"Error getting trackbar\n");
473         return;
474     }
475     else
476     {
477         int pos = GetControl32BitValue (theControl);
478         if ( trackbar->data )
479             *trackbar->data = pos;
480         if ( trackbar->notify )
481             trackbar->notify(pos);
482         else if ( trackbar->notify2 )
483             trackbar->notify2(pos, trackbar->userdata);
484
485         //--------YV---------------------------
486         CFStringEncoding encoding = kCFStringEncodingASCII;
487         CFAllocatorRef alloc_default = kCFAllocatorDefault;  // = NULL;
488
489         char valueinchar[20];
490         sprintf(valueinchar, " (%d)",  *trackbar->data);
491
492         // create an empty CFMutableString
493         CFIndex maxLength = 256;
494         CFMutableStringRef cfstring = CFStringCreateMutable(alloc_default,maxLength);
495
496         // append some c strings into it.
497         CFStringAppendCString(cfstring,trackbar->name,encoding);
498         CFStringAppendCString(cfstring,valueinchar,encoding);
499
500         SetControlData(trackbar->label, kControlEntireControl,kControlStaticTextCFStringTag, sizeof(cfstring), &cfstring);
501         DrawControls(trackbar->parent->window);
502         //-----------------------------------------
503     }
504 }
505
506
507 static int icvCreateTrackbar (const char* trackbar_name,
508                               const char* window_name,
509                               int* val, int count,
510                               CvTrackbarCallback on_notify,
511                               CvTrackbarCallback2 on_notify2,
512                               void* userdata)
513 {
514     int result = 0;
515
516     CV_FUNCNAME( "icvCreateTrackbar" );
517     __BEGIN__;
518
519     /*char slider_name[32];*/
520     CvWindow* window = 0;
521     CvTrackbar* trackbar = 0;
522     Rect  stboundsRect;
523     ControlRef outControl;
524     ControlRef stoutControl;
525     Rect bounds;
526
527     if( !window_name || !trackbar_name )
528         CV_ERROR( CV_StsNullPtr, "NULL window or trackbar name" );
529
530     if( count <= 0 )
531         CV_ERROR( CV_StsOutOfRange, "Bad trackbar maximal value" );
532
533     window = icvFindWindowByName(window_name);
534     if( !window )
535         EXIT;
536
537     trackbar = icvFindTrackbarByName(window,trackbar_name);
538     if( !trackbar )
539     {
540         int len = strlen(trackbar_name);
541         trackbar = (CvTrackbar*)cvAlloc(sizeof(CvTrackbar) + len + 1);
542         memset( trackbar, 0, sizeof(*trackbar));
543         trackbar->signature = CV_TRACKBAR_MAGIC_VAL;
544         trackbar->name = (char*)(trackbar+1);
545         memcpy( trackbar->name, trackbar_name, len + 1 );
546         trackbar->parent = window;
547         trackbar->next = window->toolbar.first;
548         window->toolbar.first = trackbar;
549
550         if( val )
551         {
552             int value = *val;
553             if( value < 0 )
554                 value = 0;
555             if( value > count )
556                 value = count;
557             trackbar->pos = value;
558             trackbar->data = val;
559         }
560
561         trackbar->maxval = count;
562
563         //----------- YV ----------------------
564         //get nb of digits
565         int nbDigit = 0;
566         while((count/=10)>10){
567             nbDigit++;
568         }
569
570         //pad size maxvalue in pixel
571         Point   qdSize;
572         char valueinchar[strlen(trackbar_name)+1 +1 +1+nbDigit+1];//length+\n +space +(+nbDigit+)
573         sprintf(valueinchar, "%s (%d)",trackbar_name, trackbar->maxval);
574         SInt16  baseline;
575         CFStringRef text = CFStringCreateWithCString(NULL,valueinchar,kCFStringEncodingASCII);
576         GetThemeTextDimensions( text, kThemeCurrentPortFont, kThemeStateActive, false, &qdSize, &baseline );
577         trackbar->labelSize = qdSize.h;
578         //--------------------------------------
579
580         int c = icvCountTrackbarInWindow(window);
581
582         GetWindowBounds(window->window,kWindowContentRgn,&bounds);
583
584         stboundsRect.top = (INTERWIDGETSPACE +WIDGETHEIGHT)* (c-1)+INTERWIDGETSPACE;
585         stboundsRect.left = INTERWIDGETSPACE;
586         stboundsRect.bottom = stboundsRect.top + WIDGETHEIGHT;
587         stboundsRect.right = stboundsRect.left+LABELWIDTH;
588
589         //fprintf(stdout,"create trackabar bounds (%d %d %d %d)\n",stboundsRect.top,stboundsRect.left,stboundsRect.bottom,stboundsRect.right);
590      //----------- YV ----------------------
591      sprintf(valueinchar, "%s (%d)",trackbar_name, trackbar->pos);
592         CreateStaticTextControl (window->window,&stboundsRect,CFStringCreateWithCString(NULL,valueinchar,kCFStringEncodingASCII),NULL,&stoutControl);
593         //--------------------------------------
594
595         stboundsRect.top = (INTERWIDGETSPACE +WIDGETHEIGHT)* (c-1)+INTERWIDGETSPACE;
596         stboundsRect.left = INTERWIDGETSPACE*2+LABELWIDTH;
597         stboundsRect.bottom = stboundsRect.top + WIDGETHEIGHT;
598         stboundsRect.right =  bounds.right-INTERWIDGETSPACE;
599
600         CreateSliderControl (window->window,&stboundsRect, trackbar->pos,0,trackbar->maxval,kControlSliderLiveFeedback,0,true,NewControlActionUPP(TrackbarActionProcPtr),&outControl);
601
602         bounds.bottom += INTERWIDGETSPACE + WIDGETHEIGHT;
603         SetControlVisibility (outControl,true,true);
604         SetControlVisibility (stoutControl,true,true);
605
606         trackbar->trackbar = outControl;
607         trackbar->label = stoutControl;
608         if (c == 1)
609             window->trackbarheight = INTERWIDGETSPACE*2 + WIDGETHEIGHT;
610         else
611             window->trackbarheight += INTERWIDGETSPACE + WIDGETHEIGHT;
612         icvUpdateWindowSize( window );
613     }
614
615     trackbar->notify = on_notify;
616     trackbar->notify2 = on_notify2;
617     trackbar->userdata = userdata;
618
619     result = 1;
620
621     __END__;
622     return result;
623 }
624
625
626 CV_IMPL int cvCreateTrackbar (const char* trackbar_name,
627                               const char* window_name,
628                               int* val, int count,
629                               CvTrackbarCallback on_notify)
630 {
631     return icvCreateTrackbar(trackbar_name, window_name, val, count, on_notify, 0, 0);
632 }
633
634
635 CV_IMPL int cvCreateTrackbar2(const char* trackbar_name,
636                               const char* window_name,
637                               int* val, int count,
638                               CvTrackbarCallback2 on_notify2,
639                               void* userdata)
640 {
641     return icvCreateTrackbar(trackbar_name, window_name, val,
642                              count, 0, on_notify2, userdata);
643 }
644
645
646 CV_IMPL void
647 cvSetMouseCallback( const char* name, CvMouseCallback function, void* info)
648 {
649     CvWindow* window = icvFindWindowByName( name );
650     if (window != NULL)
651     {
652         window->on_mouse = function;
653         window->on_mouse_param = info;
654     }
655     else
656     {
657         fprintf(stdout,"Error with cvSetMouseCallback. Window not found : %s\n",name);
658     }
659 }
660
661  CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name )
662 {
663     int pos = -1;
664
665     CV_FUNCNAME( "cvGetTrackbarPos" );
666
667     __BEGIN__;
668
669     CvWindow* window;
670     CvTrackbar* trackbar = 0;
671
672     if( trackbar_name == 0 || window_name == 0 )
673         CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
674
675     window = icvFindWindowByName( window_name );
676     if( window )
677         trackbar = icvFindTrackbarByName( window, trackbar_name );
678
679     if( trackbar )
680         pos = trackbar->pos;
681
682     __END__;
683
684     return pos;
685 }
686
687 CV_IMPL void cvSetTrackbarPos(const char* trackbar_name, const char* window_name, int pos)
688 {
689    CV_FUNCNAME( "cvSetTrackbarPos" );
690
691     __BEGIN__;
692
693     CvWindow* window;
694     CvTrackbar* trackbar = 0;
695
696     if( trackbar_name == 0 || window_name == 0 )
697         CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
698
699     window = icvFindWindowByName( window_name );
700     if( window )
701         trackbar = icvFindTrackbarByName( window, trackbar_name );
702
703     if( trackbar )
704     {
705         if( pos < 0 )
706             pos = 0;
707
708         if( pos > trackbar->maxval )
709             pos = trackbar->maxval;
710
711     // Set new value and redraw the trackbar
712     SetControlValue( trackbar->trackbar, pos );
713     Draw1Control( trackbar->trackbar );
714     }
715
716     __END__;
717     return ;
718 }
719
720 CV_IMPL void* cvGetWindowHandle( const char* name )
721 {
722     WindowRef result = 0;
723
724     __BEGIN__;
725
726     CvWindow* window;
727     window = icvFindWindowByName( name );
728     if (window != NULL)
729         result = window->window;
730     else
731         result = NULL;
732
733     __END__;
734
735     return result;
736 }
737
738
739 CV_IMPL const char* cvGetWindowName( void* window_handle )
740 {
741     const char* window_name = "";
742
743     CV_FUNCNAME( "cvGetWindowName" );
744
745     __BEGIN__;
746
747     CvWindow* window;
748
749     if( window_handle == 0 )
750         CV_ERROR( CV_StsNullPtr, "NULL window" );
751     window = icvWindowByHandle(window_handle );
752     if( window )
753         window_name = window->name;
754
755     __END__;
756
757     return window_name;
758 }
759
760 double cvGetModeWindow_CARBON(const char* name)//YV
761 {
762     double result = -1;
763
764     CV_FUNCNAME( "cvGetModeWindow_QT" );
765
766     __BEGIN__;
767
768     CvWindow* window;
769
770     if(!name)
771         CV_ERROR( CV_StsNullPtr, "NULL name string" );
772
773     window = icvFindWindowByName( name );
774     if( !window )
775         CV_ERROR( CV_StsNullPtr, "NULL window" );
776
777     result = window->status;
778
779     __END__;
780     return result;
781 }
782
783 void cvSetModeWindow_CARBON( const char* name, double prop_value)//Yannick Verdie
784 {
785     OSStatus err = noErr;
786
787
788     CV_FUNCNAME( "cvSetModeWindow_QT" );
789
790     __BEGIN__;
791
792     CvWindow* window;
793
794     if(!name)
795         CV_ERROR( CV_StsNullPtr, "NULL name string" );
796
797     window = icvFindWindowByName( name );
798     if( !window )
799         CV_ERROR( CV_StsNullPtr, "NULL window" );
800
801     if(window->flags & CV_WINDOW_AUTOSIZE)//if the flag CV_WINDOW_AUTOSIZE is set
802         EXIT;
803
804     if (window->status==CV_WINDOW_FULLSCREEN && prop_value==CV_WINDOW_NORMAL)
805     {
806         err = EndFullScreen(window->restoreState,0);
807         if (err != noErr)
808             fprintf(stdout,"Error EndFullScreen\n");
809         window->window = window->oldwindow;
810         ShowWindow( window->window );
811
812         window->status=CV_WINDOW_NORMAL;
813         EXIT;
814     }
815
816     if (window->status==CV_WINDOW_NORMAL && prop_value==CV_WINDOW_FULLSCREEN)
817     {
818         GDHandle device;
819         err = GetWindowGreatestAreaDevice(window->window, kWindowTitleBarRgn, &device, NULL);
820         if (err != noErr)
821             fprintf(stdout,"Error GetWindowGreatestAreaDevice\n");
822
823         HideWindow(window->window);
824         window->oldwindow = window->window;
825         err = BeginFullScreen(&(window->restoreState), device, 0, 0, &window->window, 0, fullScreenAllowEvents | fullScreenDontSwitchMonitorResolution);
826         if (err != noErr)
827             fprintf(stdout,"Error BeginFullScreen\n");
828
829         window->status=CV_WINDOW_FULLSCREEN;
830         EXIT;
831     }
832
833     __END__;
834 }
835
836 void cv::setWindowTitle(const String& winname, const String& title)
837 {
838     CvWindow* window = icvFindWindowByName(winname.c_str());
839
840     if (!window)
841     {
842         namedWindow(winname);
843         window = icvFindWindowByName(winname.c_str());
844     }
845
846     if (!window)
847         CV_Error(Error::StsNullPtr, "NULL window");
848
849     if (noErr != SetWindowTitleWithCFString(window->window, CFStringCreateWithCString(NULL, title.c_str(), kCFStringEncodingASCII)))
850         CV_Error_(Error::StsError, ("Failed to set \"%s\" window title to \"%s\"", winname.c_str(), title.c_str()));
851 }
852
853 CV_IMPL int cvNamedWindow( const char* name, int flags )
854 {
855     int result = 0;
856     CV_FUNCNAME( "cvNamedWindow" );
857     if (!wasInitialized)
858         cvInitSystem(0, NULL);
859
860     // to be able to display a window, we need to be a 'faceful' application
861     // http://lists.apple.com/archives/carbon-dev/2005/Jun/msg01414.html
862     static bool switched_to_faceful = false;
863     if (! switched_to_faceful)
864     {
865         ProcessSerialNumber psn = { 0, kCurrentProcess };
866         OSStatus ret = TransformProcessType (&psn, kProcessTransformToForegroundApplication );
867
868         if (ret == noErr)
869         {
870             SetFrontProcess( &psn );
871             switched_to_faceful = true;
872         }
873         else
874         {
875             fprintf(stderr, "Failed to tranform process type: %d\n", (int) ret);
876             fflush (stderr);
877         }
878     }
879
880     __BEGIN__;
881
882     WindowRef       outWindow = NULL;
883     OSStatus              err = noErr;
884     Rect        contentBounds = {100,100,320,440};
885
886     CvWindow* window;
887     UInt wAttributes = 0;
888
889     int len;
890
891     const EventTypeSpec genericWindowEventHandler[] = {
892         { kEventClassMouse, kEventMouseMoved},
893         { kEventClassMouse, kEventMouseDragged},
894         { kEventClassMouse, kEventMouseUp},
895         { kEventClassMouse, kEventMouseDown},
896         { kEventClassWindow, kEventWindowClose },
897         { kEventClassWindow, kEventWindowBoundsChanged }//FD
898     };
899
900     if( !name )
901         CV_ERROR( CV_StsNullPtr, "NULL name string" );
902
903     if( icvFindWindowByName( name ) != 0 ){
904         result = 1;
905         EXIT;
906     }
907     len = strlen(name);
908     CV_CALL( window = (CvWindow*)cvAlloc(sizeof(CvWindow) + len + 1));
909     memset( window, 0, sizeof(*window));
910     window->name = (char*)(window + 1);
911     memcpy( window->name, name, len + 1 );
912     window->flags = flags;
913     window->status = CV_WINDOW_NORMAL;//YV
914     window->signature = CV_WINDOW_MAGIC_VAL;
915     window->image = 0;
916     window->last_key = 0;
917     window->on_mouse = 0;
918     window->on_mouse_param = 0;
919
920     window->next = hg_windows;
921     window->prev = 0;
922     if( hg_windows )
923         hg_windows->prev = window;
924     hg_windows = window;
925     wAttributes =  kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute | kWindowLiveResizeAttribute;
926
927
928     if (window->flags & CV_WINDOW_AUTOSIZE)//Yannick verdie, remove the handler at the bottom-right position of the window in AUTORESIZE mode
929     {
930     wAttributes = 0;
931     wAttributes = kWindowCloseBoxAttribute | kWindowFullZoomAttribute | kWindowCollapseBoxAttribute | kWindowStandardHandlerAttribute  |  kWindowLiveResizeAttribute;
932     }
933
934     err = CreateNewWindow ( kDocumentWindowClass,wAttributes,&contentBounds,&outWindow);
935     if (err != noErr)
936         fprintf(stderr,"Error while creating the window\n");
937
938     SetWindowTitleWithCFString(outWindow,CFStringCreateWithCString(NULL,name,kCFStringEncodingASCII));
939     if (err != noErr)
940         fprintf(stdout,"Error SetWindowTitleWithCFString\n");
941
942     window->window = outWindow;
943     window->oldwindow = 0;//YV
944
945     err = InstallWindowEventHandler(outWindow, NewEventHandlerUPP(windowEventHandler), GetEventTypeCount(genericWindowEventHandler), genericWindowEventHandler, outWindow, NULL);
946
947     ShowWindow( outWindow );
948     result = 1;
949
950     __END__;
951     return result;
952 }
953
954 static pascal OSStatus windowEventHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *inUserData)
955 {
956     CvWindow* window = NULL;
957     UInt32 eventKind, eventClass;
958     OSErr err = noErr;
959     int event = 0;
960     UInt32 count = 0;
961     HIPoint point = {0,0};
962     EventMouseButton eventMouseButton = 0;//FD
963     UInt32 modifiers;//FD
964
965     WindowRef theWindow = (WindowRef)inUserData;
966     if (theWindow == NULL)
967         return eventNotHandledErr;
968     window = icvWindowByHandle(theWindow);
969     if ( window == NULL)
970         return eventNotHandledErr;
971
972     eventKind = GetEventKind(theEvent);
973     eventClass = GetEventClass(theEvent);
974
975     switch (eventClass) {
976     case kEventClassMouse : {
977         switch (eventKind){
978         case kEventMouseUp :
979         case kEventMouseDown :
980         case kEventMouseMoved :
981         case kEventMouseDragged : {
982             err = CallNextEventHandler(nextHandler, theEvent);
983             if (err != eventNotHandledErr)
984                 return err;
985             err = GetEventParameter(theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(eventMouseButton), NULL, &eventMouseButton);
986             err = GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers);
987             err = GetEventParameter(theEvent,kEventParamClickCount,typeUInt32,NULL,sizeof(UInt32),NULL,&count);
988             if (err == noErr){
989                 if (count >1) event += 6;
990             } else {
991                 event = CV_EVENT_MOUSEMOVE;
992             }
993
994             if (eventKind == kEventMouseUp)
995                 event +=4;
996             if (eventKind == kEventMouseDown)
997                 event +=1;
998
999             unsigned int flags = 0;
1000
1001             err = GetEventParameter(theEvent, kEventParamWindowMouseLocation, typeHIPoint, NULL, sizeof(point), NULL, &point);
1002             if (eventKind != kEventMouseMoved){
1003                 switch(eventMouseButton){
1004                     case kEventMouseButtonPrimary:
1005                         if (modifiers & controlKey){
1006                             flags += CV_EVENT_FLAG_RBUTTON;
1007                             event += 1;
1008                         } else {
1009                             flags += CV_EVENT_FLAG_LBUTTON;
1010                         }
1011                         break;
1012                     case kEventMouseButtonSecondary:
1013                         flags += CV_EVENT_FLAG_RBUTTON;
1014                         event += 1;
1015                         break;
1016                     case kEventMouseButtonTertiary:
1017                         flags += CV_EVENT_FLAG_MBUTTON;
1018                         event += 2;
1019                         break;
1020                 }
1021             }
1022
1023             if (modifiers&controlKey) flags += CV_EVENT_FLAG_CTRLKEY;
1024             if (modifiers&shiftKey)   flags += CV_EVENT_FLAG_SHIFTKEY;
1025             if (modifiers& cmdKey )   flags += CV_EVENT_FLAG_ALTKEY;
1026
1027             if (window->on_mouse != NULL){
1028                 int lx,ly;
1029                 Rect structure, content;
1030                 GetWindowBounds(theWindow, kWindowStructureRgn, &structure);
1031                 GetWindowBounds(theWindow, kWindowContentRgn, &content);
1032                 lx = (int)point.x - content.left + structure.left;
1033                 ly = (int)point.y - window->trackbarheight  - content.top + structure.top; /* minus la taille des trackbars */
1034                 if (window->flags & CV_WINDOW_AUTOSIZE) {//FD
1035                                                          //printf("was %d,%d\n", lx, ly);
1036                     /* scale the mouse coordinates */
1037                     lx = lx * window->imageWidth / (content.right - content.left);
1038                     ly = ly * window->imageHeight / (content.bottom - content.top - window->trackbarheight);
1039                 }
1040
1041                 if (lx>0 && ly >0){ /* a remettre dans les coordonnées locale */
1042                     window->on_mouse (event, lx, ly, flags, window->on_mouse_param);
1043                     return noErr;
1044                 }
1045             }
1046         }
1047         default : return eventNotHandledErr;
1048         }
1049     }
1050     case kEventClassWindow : {//FD
1051         switch (eventKind){
1052         case kEventWindowBoundsChanged :
1053         {
1054             /* resize the trackbars */
1055             CvTrackbar *t;
1056             Rect bounds;
1057             GetWindowBounds(window->window,kWindowContentRgn,&bounds);
1058             for ( t = window->toolbar.first; t != 0; t = t->next )
1059                 SizeControl(t->trackbar,bounds.right - bounds.left - INTERWIDGETSPACE*3 - LABELWIDTH , WIDGETHEIGHT);
1060         }
1061             /* redraw the image */
1062             icvDrawImage(window);
1063             break;
1064         default :
1065             return eventNotHandledErr;
1066         }
1067     }
1068     default:
1069         return eventNotHandledErr;
1070     }
1071
1072     return eventNotHandledErr;
1073 }
1074
1075 OSStatus keyHandler(EventHandlerCallRef hcr, EventRef theEvent, void* inUserData)
1076 {
1077     UInt32 eventKind;
1078     UInt32 eventClass;
1079     OSErr  err        = noErr;
1080
1081     eventKind  = GetEventKind     (theEvent);
1082     eventClass = GetEventClass    (theEvent);
1083     err        = GetEventParameter(theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(lastKey), NULL, &lastKey);
1084     if (err != noErr)
1085         lastKey = NO_KEY;
1086
1087     return noErr;
1088 }
1089
1090 CV_IMPL int cvWaitKey (int maxWait)
1091 {
1092     EventRecord theEvent;
1093
1094     // wait at least for one event (to allow mouse, etc. processing), exit if maxWait milliseconds passed (nullEvent)
1095     UInt32 start = TickCount();
1096     int iters=0;
1097     do
1098     {
1099         // remaining time until maxWait is over
1100         UInt32 wait = EventTimeToTicks (maxWait / 1000.0) - (TickCount() - start);
1101         if ((int)wait <= 0)
1102         {
1103             if( maxWait > 0 && iters > 0 )
1104                 break;
1105             wait = 1;
1106         }
1107         iters++;
1108         WaitNextEvent (everyEvent, &theEvent, maxWait > 0 ? wait : kDurationForever, NULL);
1109     }
1110     while (lastKey == NO_KEY  &&  theEvent.what != nullEvent);
1111
1112     int key = lastKey;
1113     lastKey = NO_KEY;
1114     return key;
1115 }
1116
1117 /* End of file. */