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