Update to 2.0.0 tree from current Fremantle build
[opencv] / src / highgui / window_carbon.cpp
diff --git a/src/highgui/window_carbon.cpp b/src/highgui/window_carbon.cpp
new file mode 100644 (file)
index 0000000..df32585
--- /dev/null
@@ -0,0 +1,970 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                        Intel License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000, Intel Corporation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of Intel Corporation may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "_highgui.h"
+
+#include <Carbon/Carbon.h>
+
+#include <unistd.h>
+#include <cstdio>
+#include <cmath>
+
+//#define MS_TO_TICKS(a) a*3/50
+
+#define LABELWIDTH 64
+#define INTERWIDGETSPACE 16
+#define WIDGETHEIGHT 32
+#define NO_KEY -1
+
+struct CvWindow;
+
+typedef struct CvTrackbar
+{
+    int signature;
+    
+    ControlRef trackbar;
+    ControlRef label;
+    
+    char* name;
+    CvTrackbar* next;
+    CvWindow* parent;
+    int* data;
+    int pos;
+    int maxval;
+    CvTrackbarCallback notify;
+    CvTrackbarCallback2 notify2;
+    void* userdata;
+}
+CvTrackbar;
+
+
+typedef struct CvWindow
+{
+    int signature;
+    
+    char* name;
+    CvWindow* prev;
+    CvWindow* next;
+    
+    WindowRef window;
+    CGImageRef imageRef;
+    int imageWidth;//FD
+    int imageHeight;//FD
+        
+    CvMat* image;
+    CvMat* dst_image;
+    int converted;
+    int last_key;
+    int flags;
+    
+    CvMouseCallback on_mouse;
+    void* on_mouse_param;
+    
+    struct {
+        int pos;
+        int rows;
+        CvTrackbar* first;
+    }
+    toolbar;
+    int trackbarheight;
+}
+CvWindow;
+
+static CvWindow* hg_windows = 0;
+
+#define Assert(exp)                                             \
+if( !(exp) )                                                    \
+{                                                               \
+    printf("Assertion: %s  %s: %d\n", #exp, __FILE__, __LINE__);\
+    assert(exp);                                                \
+}
+
+static int wasInitialized = 0;    
+static char lastKey = NO_KEY;
+OSStatus keyHandler(EventHandlerCallRef hcr, EventRef theEvent, void* inUserData);
+static pascal OSStatus windowEventHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *inUserData);
+
+static const EventTypeSpec applicationKeyboardEvents[] = 
+{
+    { kEventClassKeyboard, kEventRawKeyDown },
+};
+
+CV_IMPL int cvInitSystem( int argc, char** argv )
+{
+    OSErr err = noErr;
+    if( !wasInitialized ) 
+    {
+    
+        hg_windows = 0;
+        err = InstallApplicationEventHandler(NewEventHandlerUPP( keyHandler),GetEventTypeCount(applicationKeyboardEvents),applicationKeyboardEvents,NULL,NULL);
+        if (err != noErr)
+        {
+             fprintf(stderr,"InstallApplicationEventHandler was not ok\n");
+        }
+        wasInitialized = 1;
+    }
+    
+    return 0;
+}
+
+// TODO: implement missing functionality
+CV_IMPL int cvStartWindowThread()
+{
+    return 0;
+}
+
+static int icvCountTrackbarInWindow( const CvWindow* window)
+{
+    CvTrackbar* trackbar = window->toolbar.first;
+    int count = 0;
+    while (trackbar != 0) {
+        count++;
+        trackbar = trackbar->next;
+    }
+    return count;
+}
+
+static CvTrackbar* icvTrackbarByHandle( void * handle )
+{
+    CvWindow* window = hg_windows;
+    CvTrackbar* trackbar = NULL;
+    while( window != 0 && window->window != handle) {
+        trackbar = window->toolbar.first;
+        while (trackbar != 0 && trackbar->trackbar != handle)
+            trackbar = trackbar->next;
+        if (trackbar != 0 && trackbar->trackbar == handle)
+            break;
+        window = window->next;
+    }
+    return trackbar;
+}
+
+static CvWindow* icvWindowByHandle( void * handle )
+{
+    CvWindow* window = hg_windows;
+    
+    while( window != 0 && window->window != handle)
+        window = window->next;
+    
+    return window;
+}
+
+CV_IMPL CvWindow * icvFindWindowByName( const char* name)
+{
+    CvWindow* window = hg_windows;
+    while( window != 0 && strcmp(name, window->name) != 0 ) 
+               window = window->next;
+       
+    return window;
+}
+
+static CvTrackbar* icvFindTrackbarByName( const CvWindow* window, const char* name )
+{
+    CvTrackbar* trackbar = window->toolbar.first;
+    
+    while (trackbar != 0 && strcmp( trackbar->name, name ) != 0)
+        trackbar = trackbar->next;
+    
+    return trackbar;
+}
+
+//FD
+/* draw image to frame */
+static void icvDrawImage( CvWindow* window )
+{
+    Assert( window != 0 );
+    if( window->imageRef == 0 ) return;
+    
+    CGContextRef myContext;
+    CGRect rect;
+    Rect portrect;
+    int width = window->imageWidth;
+    int height = window->imageHeight;
+    
+        GetWindowPortBounds(window->window, &portrect);
+    
+    if( window->flags & CV_WINDOW_AUTOSIZE ) 
+       { 
+        CGPoint origin = {0,0}; 
+        CGSize size = {portrect.right-portrect.left, portrect.bottom-portrect.top-window->trackbarheight};
+        rect.origin = origin; rect.size = size;
+    } 
+       else 
+       {
+        CGPoint origin = {0, portrect.bottom - height - window->trackbarheight};
+        CGSize size = {width, height};
+        rect.origin = origin; rect.size = size;
+    }
+    
+    /* 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*/
+    SetPortWindowPort (window->window);
+    QDBeginCGContext (GetWindowPort (window->window), &myContext);
+    CGContextSetInterpolationQuality (myContext, kCGInterpolationLow); 
+    CGContextDrawImage(myContext,rect,window->imageRef);
+    CGContextFlush(myContext);// 4
+    QDEndCGContext (GetWindowPort(window->window), &myContext);// 5
+}
+
+//FD
+/* update imageRef */
+static void icvPutImage( CvWindow* window )
+{
+    Assert( window != 0 );
+    if( window->image == 0 ) return;
+    
+    CGColorSpaceRef colorspace = NULL;
+    CGDataProviderRef provider = NULL;
+    int width = window->imageWidth = window->image->cols;
+    int height = window->imageHeight = window->image->rows;
+    
+    colorspace = CGColorSpaceCreateDeviceRGB();
+    
+    int size = 8;
+    int nbChannels = 3;
+    
+    provider = CGDataProviderCreateWithData(NULL, window->image->data.ptr, width * height , NULL );
+    
+    if (window->imageRef != NULL){
+        CGImageRelease(window->imageRef);
+        window->imageRef = NULL;
+    }
+    
+    window->imageRef = CGImageCreate( width, height, size , size*nbChannels , window->image->step, colorspace,  kCGImageAlphaNone , provider, NULL, true, kCGRenderingIntentDefault );
+    icvDrawImage( window );
+
+    /* release the provider's memory */
+    CGDataProviderRelease( provider );
+}
+
+static void icvUpdateWindowSize( const CvWindow* window )
+{
+    int width = 0, height = 240; /* init à al taille de base de l'image*/
+    Rect globalBounds;
+    
+    GetWindowBounds(window->window, kWindowContentRgn, &globalBounds);
+    
+    int minWidth = 320;
+    
+    if( window->image ) {
+        width = MAX(MAX(window->image->width, width), minWidth);
+        height = window->image->height;
+    } else
+        width = minWidth;
+    
+    height += window->trackbarheight;
+    
+    //height +=WIDGETHEIGHT; /* 32 pixels are spearating tracbars from the video display */
+    
+    globalBounds.right = globalBounds.left + width;
+    globalBounds.bottom = globalBounds.top + height;
+    SetWindowBounds(window->window, kWindowContentRgn, &globalBounds);
+}
+
+static void icvDeleteWindow( CvWindow* window )
+{
+    CvTrackbar* trackbar;
+    
+    if( window->prev )
+        window->prev->next = window->next;
+    else
+        hg_windows = window->next;
+    
+    if( window->next )
+        window->next->prev = window->prev;
+    
+    window->prev = window->next = 0;
+    
+    cvReleaseMat( &window->image );
+    cvReleaseMat( &window->dst_image );
+    
+    for( trackbar = window->toolbar.first; trackbar != 0; ) 
+       {
+        CvTrackbar* next = trackbar->next;
+        cvFree( (void**)&trackbar );
+        trackbar = next;
+    }
+    
+       if (window->imageRef != NULL)
+        CGImageRelease(window->imageRef);
+    
+    cvFree( (void**)&window );
+}
+
+
+CV_IMPL void cvDestroyWindow( const char* name)
+{
+    CV_FUNCNAME( "cvDestroyWindow" );
+    
+    __BEGIN__;
+    
+    CvWindow* window;
+    
+    if(!name)
+        CV_ERROR( CV_StsNullPtr, "NULL name string" );
+    
+    window = icvFindWindowByName( name );
+    if( !window )
+        EXIT;
+    
+    icvDeleteWindow( window );
+    
+    __END__;
+}
+
+
+CV_IMPL void cvDestroyAllWindows( void )
+{
+    while( hg_windows ) 
+       {
+        CvWindow* window = hg_windows;
+        icvDeleteWindow( window );
+    }
+}
+
+
+CV_IMPL void cvShowImage( const char* name, const CvArr* arr)
+{
+    CV_FUNCNAME( "cvShowImage" );
+    
+    __BEGIN__;
+    
+    CvWindow* window;
+    int origin = 0;
+    int resize = 0;
+    CvMat stub, *image;
+    
+    if( !name )
+        CV_ERROR( CV_StsNullPtr, "NULL name" );
+    
+    window = icvFindWindowByName(name);
+       if(!window)
+       {
+               cvNamedWindow(name, 1);
+               window = icvFindWindowByName(name);
+       }
+
+    if( !window || !arr )
+        EXIT; // keep silence here.
+    
+    if( CV_IS_IMAGE_HDR( arr ))
+        origin = ((IplImage*)arr)->origin;
+    
+    CV_CALL( image = cvGetMat( arr, &stub ));
+    
+    /*
+     if( !window->image )
+     cvResizeWindow( name, image->cols, image->rows );
+     */
+    
+    if( window->image &&
+        !CV_ARE_SIZES_EQ(window->image, image) ) {
+        if ( ! (window->flags & CV_WINDOW_AUTOSIZE) )//FD
+            resize = 1;
+        cvReleaseMat( &window->image );
+    }
+    
+    if( !window->image ) {
+        resize = 1;//FD
+        window->image = cvCreateMat( image->rows, image->cols, CV_8UC3 );
+    }
+    
+    cvConvertImage( image, window->image, (origin != 0 ? CV_CVTIMG_FLIP : 0) + CV_CVTIMG_SWAP_RB );
+    icvPutImage( window );
+    if ( resize )//FD
+        icvUpdateWindowSize( window );
+    
+    __END__;
+}
+
+CV_IMPL void cvResizeWindow( const char* name, int width, int height)
+{
+    CV_FUNCNAME( "cvResizeWindow" );
+    
+    __BEGIN__;
+    
+    CvWindow* window;
+    //CvTrackbar* trackbar;
+    
+    if( !name )
+        CV_ERROR( CV_StsNullPtr, "NULL name" );
+    
+    window = icvFindWindowByName(name);
+    if(!window)
+        EXIT;
+    
+    SizeWindow(window->window, width, height, true);
+    
+    __END__;
+}
+
+CV_IMPL void cvMoveWindow( const char* name, int x, int y)
+{
+    CV_FUNCNAME( "cvMoveWindow" );
+    
+    __BEGIN__;
+    
+    CvWindow* window;
+    //CvTrackbar* trackbar;
+    
+    if( !name )
+        CV_ERROR( CV_StsNullPtr, "NULL name" );
+    
+    window = icvFindWindowByName(name);
+    if(!window)
+        EXIT;
+    
+    MoveWindow(window->window, x, y, true);
+    
+    __END__;
+}
+
+void TrackbarActionProcPtr (ControlRef theControl, ControlPartCode partCode)
+{
+    CvTrackbar * trackbar = icvTrackbarByHandle (theControl);
+    
+       if (trackbar == NULL)
+       {
+        fprintf(stderr,"Error getting trackbar\n");
+        return;
+    }
+       else 
+       {
+        int pos = GetControl32BitValue (theControl);
+        if ( trackbar->data )
+            *trackbar->data = pos;
+        if ( trackbar->notify )
+            trackbar->notify(pos);
+        else if ( trackbar->notify2 )
+            trackbar->notify2(pos, trackbar->userdata);
+    }
+}
+
+
+static int icvCreateTrackbar (const char* trackbar_name,
+                              const char* window_name,
+                              int* val, int count,
+                              CvTrackbarCallback on_notify,
+                              CvTrackbarCallback2 on_notify2,
+                              void* userdata)
+{
+    int result = 0;
+    
+    CV_FUNCNAME( "icvCreateTrackbar" );
+    __BEGIN__;
+    
+    /*char slider_name[32];*/
+    CvWindow* window = 0;
+    CvTrackbar* trackbar = 0;
+    Rect  stboundsRect;
+    ControlRef outControl;
+    ControlRef stoutControl;
+    Rect bounds;
+    
+    if( !window_name || !trackbar_name )
+        CV_ERROR( CV_StsNullPtr, "NULL window or trackbar name" );
+    
+    if( count <= 0 )
+        CV_ERROR( CV_StsOutOfRange, "Bad trackbar maximal value" );
+    
+    window = icvFindWindowByName(window_name);
+    if( !window )
+        EXIT;
+    
+    trackbar = icvFindTrackbarByName(window,trackbar_name);
+    if( !trackbar ) 
+       {
+        int len = strlen(trackbar_name);
+        trackbar = (CvTrackbar*)cvAlloc(sizeof(CvTrackbar) + len + 1);
+        memset( trackbar, 0, sizeof(*trackbar));
+        trackbar->signature = CV_TRACKBAR_MAGIC_VAL;
+        trackbar->name = (char*)(trackbar+1);
+        memcpy( trackbar->name, trackbar_name, len + 1 );
+        trackbar->parent = window;
+        trackbar->next = window->toolbar.first;
+        window->toolbar.first = trackbar;
+        
+        if( val ) 
+               {
+            int value = *val;
+            if( value < 0 )
+                value = 0;
+            if( value > count )
+                value = count;
+            trackbar->pos = value;
+            trackbar->data = val;
+        }
+        
+        trackbar->maxval = count;
+        
+        int c = icvCountTrackbarInWindow(window);              
+        
+        GetWindowBounds(window->window,kWindowContentRgn,&bounds);
+        
+        stboundsRect.top = (INTERWIDGETSPACE +WIDGETHEIGHT)* (c-1)+INTERWIDGETSPACE;
+        stboundsRect.left = INTERWIDGETSPACE;
+        stboundsRect.bottom = stboundsRect.top + WIDGETHEIGHT;
+        stboundsRect.right = stboundsRect.left+LABELWIDTH;
+        
+        //fprintf(stdout,"create trackabar bounds (%d %d %d %d)\n",stboundsRect.top,stboundsRect.left,stboundsRect.bottom,stboundsRect.right);
+        CreateStaticTextControl (window->window,&stboundsRect,CFStringCreateWithCString(NULL,trackbar_name,kCFStringEncodingASCII),NULL,&stoutControl);
+        
+        stboundsRect.top = (INTERWIDGETSPACE +WIDGETHEIGHT)* (c-1)+INTERWIDGETSPACE;
+        stboundsRect.left = INTERWIDGETSPACE*2+LABELWIDTH;
+        stboundsRect.bottom = stboundsRect.top + WIDGETHEIGHT;
+        stboundsRect.right =  bounds.right-INTERWIDGETSPACE;
+        
+        CreateSliderControl (window->window,&stboundsRect, trackbar->pos,0,trackbar->maxval,kControlSliderLiveFeedback,0,true,NewControlActionUPP(TrackbarActionProcPtr),&outControl);
+        
+        bounds.bottom += INTERWIDGETSPACE + WIDGETHEIGHT;
+        SetControlVisibility (outControl,true,true);
+        SetControlVisibility (stoutControl,true,true);
+        
+        trackbar->trackbar = outControl;
+        trackbar->label = stoutControl;
+        if (c == 1)
+            window->trackbarheight = INTERWIDGETSPACE*2 + WIDGETHEIGHT;
+        else
+            window->trackbarheight += INTERWIDGETSPACE + WIDGETHEIGHT;
+        icvUpdateWindowSize( window );
+    }
+
+    trackbar->notify = on_notify;
+    trackbar->notify2 = on_notify2;
+    trackbar->userdata = userdata;
+
+    result = 1;
+
+    __END__;
+    return result;
+}
+
+
+CV_IMPL int cvCreateTrackbar (const char* trackbar_name,
+                              const char* window_name,
+                              int* val, int count,
+                              CvTrackbarCallback on_notify)
+{
+    return icvCreateTrackbar(trackbar_name, window_name, val, count, on_notify, 0, 0);
+}
+
+
+CV_IMPL int cvCreateTrackbar2(const char* trackbar_name,
+                              const char* window_name,
+                              int* val, int count,
+                              CvTrackbarCallback2 on_notify2,
+                              void* userdata)
+{
+    return icvCreateTrackbar(trackbar_name, window_name, val,
+                             count, 0, on_notify2, userdata);
+}
+
+
+CV_IMPL void
+cvSetMouseCallback( const char* name, CvMouseCallback function, void* info)
+{
+    CvWindow* window = icvFindWindowByName( name );
+    if (window != NULL)
+       {
+        window->on_mouse = function;
+        window->on_mouse_param = info;
+    } 
+       else
+       {
+        fprintf(stdout,"Error with cvSetMouseCallback. Window not found : %s\n",name);
+       }
+}
+
+ CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name )
+{
+    int pos = -1;
+    
+    CV_FUNCNAME( "cvGetTrackbarPos" );
+
+    __BEGIN__;
+
+    CvWindow* window;
+    CvTrackbar* trackbar = 0;
+
+    if( trackbar_name == 0 || window_name == 0 )
+        CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
+
+    window = icvFindWindowByName( window_name );
+    if( window )
+        trackbar = icvFindTrackbarByName( window, trackbar_name );
+
+    if( trackbar )
+        pos = trackbar->pos;
+
+    __END__;
+
+    return pos;
+}
+
+CV_IMPL void cvSetTrackbarPos(const char* trackbar_name, const char* window_name, int pos)
+{
+   CV_FUNCNAME( "cvSetTrackbarPos" );
+
+    __BEGIN__;
+
+    CvWindow* window;
+    CvTrackbar* trackbar = 0;
+
+    if( trackbar_name == 0 || window_name == 0 )
+        CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
+
+    window = icvFindWindowByName( window_name );
+    if( window )
+        trackbar = icvFindTrackbarByName( window, trackbar_name );
+
+    if( trackbar )
+    {
+        if( pos < 0 )
+            pos = 0;
+
+        if( pos > trackbar->maxval )
+            pos = trackbar->maxval;
+
+       // Set new value and redraw the trackbar
+       SetControlValue( trackbar->trackbar, pos );
+       Draw1Control( trackbar->trackbar );     
+    }
+
+    __END__;
+    return ;
+}
+
+CV_IMPL void* cvGetWindowHandle( const char* name )
+{
+    WindowRef result = 0;
+    
+    __BEGIN__;
+    
+    CvWindow* window;
+    window = icvFindWindowByName( name );
+    if (window != NULL)
+        result = window->window;
+    else
+        result = NULL;
+    
+    __END__;
+    
+    return result;
+}
+
+
+CV_IMPL const char* cvGetWindowName( void* window_handle )
+{      
+    const char* window_name = "";
+    
+    CV_FUNCNAME( "cvGetWindowName" );
+    
+    __BEGIN__;
+    
+    CvWindow* window;
+    
+    if( window_handle == 0 )
+        CV_ERROR( CV_StsNullPtr, "NULL window" );
+    window = icvWindowByHandle(window_handle );
+    if( window )
+        window_name = window->name;
+    
+    __END__;
+    
+    return window_name;
+}
+
+
+CV_IMPL int cvNamedWindow( const char* name, int flags )
+{
+    int result = 0;
+    CV_FUNCNAME( "cvNamedWindow" );
+    if (!wasInitialized)
+        cvInitSystem(0, NULL);
+    
+    // to be able to display a window, we need to be a 'faceful' application
+    // http://lists.apple.com/archives/carbon-dev/2005/Jun/msg01414.html
+    static bool switched_to_faceful = false;
+    if (! switched_to_faceful)
+    {
+        ProcessSerialNumber psn = { 0, kCurrentProcess };
+        OSStatus ret = TransformProcessType (&psn, kProcessTransformToForegroundApplication );
+
+        if (ret == noErr) 
+        {
+            SetFrontProcess( &psn );
+            switched_to_faceful = true;
+        }
+        else
+        {
+            fprintf(stderr, "Failed to tranform process type: %d\n", (int) ret);
+            fflush (stderr);
+        }
+    }
+    
+    __BEGIN__;
+    
+    WindowRef       outWindow = NULL;
+    OSStatus              err = noErr;
+    Rect        contentBounds = {100,100,320,440};
+    
+    CvWindow* window;
+    UInt wAttributes = 0;
+    
+    int len;
+    
+    const EventTypeSpec genericWindowEventHandler[] = { 
+        { kEventClassMouse, kEventMouseMoved},
+        { kEventClassMouse, kEventMouseDragged},
+        { kEventClassMouse, kEventMouseUp},
+        { kEventClassMouse, kEventMouseDown},
+        { kEventClassWindow, kEventWindowClose },
+        { kEventClassWindow, kEventWindowBoundsChanged }//FD
+    };
+    
+    if( !name )
+        CV_ERROR( CV_StsNullPtr, "NULL name string" );
+    
+    if( icvFindWindowByName( name ) != 0 ){
+        result = 1;
+        EXIT;
+    }
+    len = strlen(name);
+    CV_CALL( window = (CvWindow*)cvAlloc(sizeof(CvWindow) + len + 1));
+    memset( window, 0, sizeof(*window));
+    window->name = (char*)(window + 1);
+    memcpy( window->name, name, len + 1 );
+    window->flags = flags;
+    window->signature = CV_WINDOW_MAGIC_VAL;
+    window->image = 0;
+    window->last_key = 0;
+    window->on_mouse = 0;
+    window->on_mouse_param = 0;
+    
+    window->next = hg_windows;
+    window->prev = 0;
+    if( hg_windows )
+        hg_windows->prev = window;
+    hg_windows = window;
+    wAttributes =  kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute | kWindowLiveResizeAttribute;
+    
+    err = CreateNewWindow ( kDocumentWindowClass,wAttributes,&contentBounds,&outWindow);
+    if (err != noErr)
+        fprintf(stderr,"Error while creating the window\n");
+    
+    SetWindowTitleWithCFString(outWindow,CFStringCreateWithCString(NULL,name,kCFStringEncodingASCII));
+    if (err != noErr)
+        fprintf(stdout,"Error SetWindowTitleWithCFString\n");
+    
+    window->window = outWindow;
+    
+    err = InstallWindowEventHandler(outWindow, NewEventHandlerUPP(windowEventHandler), GetEventTypeCount(genericWindowEventHandler), genericWindowEventHandler, outWindow, NULL);
+    
+    ShowWindow( outWindow );
+    result = 1;
+       
+    __END__;
+    return result;
+}
+
+static pascal OSStatus windowEventHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *inUserData)
+{
+    CvWindow* window = NULL;
+    UInt32 eventKind, eventClass;
+    OSErr err = noErr;
+    int event = 0;
+    UInt32 count = 0;
+    HIPoint point = {0,0};
+    EventMouseButton eventMouseButton = 0;//FD
+    UInt32 modifiers;//FD
+    
+    WindowRef theWindow = (WindowRef)inUserData;
+    if (theWindow == NULL)
+        return eventNotHandledErr;
+    window = icvWindowByHandle(theWindow);
+    if ( window == NULL)
+        return eventNotHandledErr;
+    
+    eventKind = GetEventKind(theEvent);
+    eventClass = GetEventClass(theEvent);
+        
+    switch (eventClass) {
+    case kEventClassMouse : {
+        switch (eventKind){
+        case kEventMouseUp :
+        case kEventMouseDown : 
+        case kEventMouseMoved :
+        case kEventMouseDragged : {
+            err = CallNextEventHandler(nextHandler, theEvent);
+            if (err != eventNotHandledErr)
+                return err;
+            err = GetEventParameter(theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(eventMouseButton), NULL, &eventMouseButton);
+            err = GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers);
+            err = GetEventParameter(theEvent,kEventParamClickCount,typeUInt32,NULL,sizeof(UInt32),NULL,&count);
+            if (err == noErr){
+                if (count >1) event += 6;
+            } else {
+                event = CV_EVENT_MOUSEMOVE;
+            }
+            
+            if (eventKind == kEventMouseUp)
+                event +=4;
+            if (eventKind == kEventMouseDown)
+                event +=1;
+            
+            unsigned int flags = 0;
+
+            err = GetEventParameter(theEvent, kEventParamWindowMouseLocation, typeHIPoint, NULL, sizeof(point), NULL, &point);
+            if (eventKind != kEventMouseMoved){
+                switch(eventMouseButton){
+                    case kEventMouseButtonPrimary:
+                        if (modifiers & controlKey){
+                            flags += CV_EVENT_FLAG_RBUTTON;
+                            event += 1;
+                        } else {
+                            flags += CV_EVENT_FLAG_LBUTTON;
+                        }
+                        break;
+                    case kEventMouseButtonSecondary:
+                        flags += CV_EVENT_FLAG_RBUTTON;
+                        event += 1;
+                        break;
+                    case kEventMouseButtonTertiary:
+                        flags += CV_EVENT_FLAG_MBUTTON;
+                        event += 2;
+                        break;
+                }
+            }
+
+            if (modifiers&controlKey) flags += CV_EVENT_FLAG_CTRLKEY;
+            if (modifiers&shiftKey)   flags += CV_EVENT_FLAG_SHIFTKEY;
+            if (modifiers& cmdKey )   flags += CV_EVENT_FLAG_ALTKEY;
+
+            if (window->on_mouse != NULL){
+                int lx,ly;
+                Rect structure, content;
+                GetWindowBounds(theWindow, kWindowStructureRgn, &structure);
+                GetWindowBounds(theWindow, kWindowContentRgn, &content);
+                lx = (int)point.x - content.left + structure.left;
+                ly = (int)point.y - window->trackbarheight  - content.top + structure.top; /* minus la taille des trackbars */
+                if (window->flags & CV_WINDOW_AUTOSIZE) {//FD
+                                                         //printf("was %d,%d\n", lx, ly);
+                    /* scale the mouse coordinates */
+                    lx = lx * window->imageWidth / (content.right - content.left);
+                    ly = ly * window->imageHeight / (content.bottom - content.top - window->trackbarheight);
+                }
+
+                if (lx>0 && ly >0){ /* a remettre dans les coordonnées locale */
+                    window->on_mouse (event, lx, ly, flags, window->on_mouse_param);
+                    return noErr;
+                }
+            }
+        }
+        default : return eventNotHandledErr;
+        }
+    }
+    case kEventClassWindow : {//FD
+        switch (eventKind){
+        case kEventWindowBoundsChanged :
+        {
+            /* resize the trackbars */
+            CvTrackbar *t;
+            Rect bounds;
+            GetWindowBounds(window->window,kWindowContentRgn,&bounds);
+            for ( t = window->toolbar.first; t != 0; t = t->next )
+                SizeControl(t->trackbar,bounds.right - bounds.left - INTERWIDGETSPACE*3 - LABELWIDTH , WIDGETHEIGHT); 
+        }
+            /* redraw the image */
+            icvDrawImage(window);
+            break;
+        default :
+            return eventNotHandledErr;
+        }
+    }
+    default:
+        return eventNotHandledErr;
+    }
+
+    return eventNotHandledErr;
+}
+
+OSStatus keyHandler(EventHandlerCallRef hcr, EventRef theEvent, void* inUserData) 
+{
+    UInt32 eventKind;
+    UInt32 eventClass;
+    OSErr  err        = noErr;
+
+    eventKind  = GetEventKind     (theEvent);
+    eventClass = GetEventClass    (theEvent);
+    err        = GetEventParameter(theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(lastKey), NULL, &lastKey);
+    if (err != noErr)
+        lastKey = NO_KEY;
+               
+    return noErr;
+}
+
+CV_IMPL int cvWaitKey (int maxWait)
+{
+    EventRecord theEvent;
+       
+       // wait at least for one event (to allow mouse, etc. processing), exit if maxWait milliseconds passed (nullEvent)
+       UInt32 start = TickCount();
+    int iters=0;
+       do
+       {
+               // remaining time until maxWait is over
+               UInt32 wait = EventTimeToTicks (maxWait / 1000.0) - (TickCount() - start);
+               if ((int)wait <= 0)
+        {
+            if( maxWait > 0 && iters > 0 )
+                break;
+            wait = 1;
+        }
+        iters++;
+        WaitNextEvent (everyEvent, &theEvent, maxWait > 0 ? wait : kDurationForever, NULL);
+       }
+       while (lastKey == NO_KEY  &&  theEvent.what != nullEvent);
+       
+    int key = lastKey;
+    lastKey = NO_KEY;
+    return key;
+}
+
+/* End of file. */