Index: pjproject/trunk/pjsip-apps/src/vidgui/vidgui.cpp
===================================================================
--- pjproject/trunk/pjsip-apps/src/vidgui/vidgui.cpp	(revision 3698)
+++ pjproject/trunk/pjsip-apps/src/vidgui/vidgui.cpp	(revision 3699)
@@ -20,4 +20,8 @@
 #include "vidwin.h"
 
+#if defined(PJ_WIN32)
+#   define SDL_MAIN_HANDLED
+#endif
+
 #include <SDL.h>
 #include <assert.h>
@@ -51,4 +55,5 @@
 MainWin::~MainWin()
 {
+    quit();
     theInstance_ = NULL;
 }
@@ -95,5 +100,5 @@
     connect(hangupButton_, SIGNAL(clicked()), this, SLOT(hangup()));
     connect(quitButton_, SIGNAL(clicked()), this, SLOT(quit()));
-    connect(this, SIGNAL(close()), this, SLOT(quit()));
+    //connect(this, SIGNAL(close()), this, SLOT(quit()));
 }
 
@@ -168,7 +173,11 @@
 	pjsua_vid_win_id wid;
 	pjsua_vid_win_info wi;
+	pjsua_vid_preview_param pre_param;
 	pj_status_t status;
 
-	status = pjsua_vid_preview_start(DEFAULT_CAP_DEV, NULL);
+	pj_bzero(&pre_param, sizeof(pre_param));
+	pre_param.rend_id = DEFAULT_REND_DEV;
+
+	status = pjsua_vid_preview_start(DEFAULT_CAP_DEV, &pre_param);
 	if (status != PJ_SUCCESS) {
 	    char errmsg[PJ_ERR_MSG_SIZE];
@@ -180,6 +189,5 @@
 	pjsua_vid_win_get_info(wid, &wi);
 
-	video_prev_= new VidWin(&wi.hwnd);
-	video_prev_->setMinimumSize(320,200);
+	video_prev_ = new VidWin(&wi.hwnd);
 	vbox_left->addWidget(video_prev_, 1);
 
Index: pjproject/trunk/pjsip-apps/src/vidgui/vidgui.pro
===================================================================
--- pjproject/trunk/pjsip-apps/src/vidgui/vidgui.pro	(revision 3698)
+++ pjproject/trunk/pjsip-apps/src/vidgui/vidgui.pro	(revision 3699)
@@ -20,6 +20,9 @@
   LIBS += $$system(make -f pj-pkgconfig.mak ldflags)
   QMAKE_CXXFLAGS += $$system(make -f pj-pkgconfig.mak cflags)
+
+  macx {
+    QMAKE_CXXFLAGS += -ObjC++
+  }
 }
-
 
 TEMPLATE = app
Index: pjproject/trunk/pjsip-apps/src/vidgui/vidwin.cpp
===================================================================
--- pjproject/trunk/pjsip-apps/src/vidgui/vidwin.cpp	(revision 3698)
+++ pjproject/trunk/pjsip-apps/src/vidgui/vidwin.cpp	(revision 3699)
@@ -1,22 +1,66 @@
 #include "vidwin.h"
+#include <QEvent>
 
 #define THIS_FILE	"vidwin.cpp"
-#define TIMER_EMBED	1
-#define TIMER_RESIZE	2
-
-void VidWin::timer_cb(pj_timer_heap_t *timer_heap,
-		      struct pj_timer_entry *entry)
-{
-    VidWin *vw = (VidWin*)entry->user_data;
-    
-    PJ_UNUSED_ARG(timer_heap);
-
-    switch(entry->id) {
-    case TIMER_EMBED:
-	vw->embed();
-	vw->resize();
-	break;
-    case TIMER_RESIZE:
-	vw->resize();
+#define TRACE_(...)	PJ_LOG(4,(THIS_FILE, __VA_ARGS__))
+
+VidWin::VidWin(const pjmedia_vid_dev_hwnd *hwnd_,
+	       QWidget* parent,
+	       Qt::WindowFlags f) :
+    QWidget(parent, f), orig_parent(NULL),
+    size_hint(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)
+{
+    setAttribute(Qt::WA_NativeWindow);
+
+    /* Make this widget a bit "lighter" */
+    setAttribute(Qt::WA_UpdatesDisabled);
+    setAttribute(Qt::WA_PaintOnScreen);
+    setAttribute(Qt::WA_NoSystemBackground);
+    setAttribute(Qt::WA_PaintOutsidePaintEvent);
+    setUpdatesEnabled(false);
+
+    pj_bzero(&hwnd, sizeof(hwnd));
+    if (hwnd_) {
+	hwnd = *hwnd_;
+    }
+}
+
+
+VidWin::~VidWin()
+{
+    detach();
+    pj_bzero(&hwnd, sizeof(hwnd));
+    size_hint = QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+    destroy(true, false);
+}
+
+bool VidWin::event(QEvent *e)
+{
+    switch(e->type()) {
+    case QEvent::Resize:
+	{
+	    // revert to default size hint, make it resizable
+	    setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+	    // resize now
+	    set_size();
+	}
+	break;
+    case QEvent::ParentAboutToChange:
+	get_size();
+	setFixedSize(size_hint);
+	break;
+    case QEvent::ParentChange:
+	{
+	    get_size();
+	    /*
+	    QRect qr = rect();
+	    if (qr.width() > size_hint.width())
+		size_hint.setWidth(qr.width());
+	    if (qr.height() > size_hint.height())
+		size_hint.setWidth(qr.height());
+	    */
+	    setFixedSize(size_hint);
+	    attach();
+	}
 	break;
     default:
@@ -24,128 +68,96 @@
     }
 
-    entry->id = 0;
-}
-
-
-VidWin::VidWin(pjmedia_vid_dev_hwnd *hwnd_, QWidget* parent, Qt::WindowFlags f) :
-    QWidget(parent, f), hwnd(*hwnd_)
-{
-#if 0
-    // A proof that QWidget::create() change window proc!
-    // And that will cause SDL rendering not working.
-    HWND h = (HWND)hwnd->info.win.hwnd;
-    LONG wl;
-
-    wl = GetWindowLong(h, GWL_WNDPROC);
-    printf("%p old proc: %p\n", h, wl);
-
-    create(WId(hwnd->info.win.hwnd), false, true);
-    printf("%p qwidgetwid: %p\n", h, winId());
-
-    wl = GetWindowLong(h, GWL_WNDPROC);
-    printf("%p new proc: %p\n", h, wl);
-#endif
-
-    setAttribute(Qt::WA_NativeWindow);
-    setMinimumSize(320, 200);
-
-    /* Make this widget a bit "lighter" */
-    //setAttribute(Qt::WA_UpdatesDisabled);
-    //setAttribute(Qt::WA_PaintOnScreen);
-    //setAttribute(Qt::WA_NoSystemBackground);
-    //setAttribute(Qt::WA_PaintOutsidePaintEvent);
-    //setUpdatesEnabled(false);
-    
-    /* Schedule embed, as at this point widget initialization is not 
-     * completely done yet (e.g: bad size).
-     */
-    pj_timer_entry_init(&timer_entry, TIMER_EMBED, this, &timer_cb);
-    pj_time_val delay = {0, 100};
-    pjsua_schedule_timer(&timer_entry, &delay);
-}
-
-
-VidWin::~VidWin()
-{
-    if (timer_entry.id) {
-	pjsua_cancel_timer(&timer_entry);
-	timer_entry.id = 0;
-    }
-}
-
-
-void VidWin::resizeEvent(QResizeEvent*)
-{
-    /* Resizing SDL window must be scheduled (via timer),
-     * as on Windows platform, the SDL resizing process
-     * will steal focus (SDL bug?).
-     */
-    if (timer_entry.id && timer_entry.id != TIMER_RESIZE)
-	return;
-
-    if (timer_entry.id == TIMER_RESIZE)
-	pjsua_cancel_timer(&timer_entry);
-
-    timer_entry.id = TIMER_RESIZE;
-    timer_entry.cb = &timer_cb;
-    timer_entry.user_data = this;
-
-    pj_time_val delay = {0, 300};
-    pjsua_schedule_timer(&timer_entry, &delay);
+    return QWidget::event(e);
 }
 
 /* Platform specific code */
 
-#if defined(PJ_WIN32) && !defined(PJ_WIN32_WINCE)
+#if defined(_WIN32) && !defined(_WIN32_WINCE)
 
 #include <windows.h>
 
-void VidWin::embed()
-{
+void VidWin::attach()
+{
+    if (!hwnd.info.win.hwnd) return;
+
+    HWND w = (HWND)hwnd.info.win.hwnd;
+    HWND new_parent = (HWND)winId();
+    orig_parent = GetParent(w);
+
+    SetParent(w, new_parent);
+    SetWindowLong(w, GWL_STYLE, WS_CHILD);
+    ShowWindow(w, SW_SHOWNOACTIVATE);
+    TRACE_("%p new parent handle = %p", w, new_parent);
+}
+
+void VidWin::detach()
+{
+    if (!hwnd.info.win.hwnd) return;
+
+    HWND w = (HWND)hwnd.info.win.hwnd;
+    ShowWindow(w, SW_HIDE);
+    SetParent(w, (HWND)orig_parent);
+    TRACE_("%p revert parent handle to %p", w, orig_parent);
+}
+
+void VidWin::set_size()
+{
+    if (!hwnd.info.win.hwnd) return;
+
+    HWND w = (HWND)hwnd.info.win.hwnd;
+    QRect qr = rect();
+    UINT swp_flag = SWP_NOACTIVATE;
+    SetWindowPos(w, HWND_TOP, 0, 0, qr.width(), qr.height(), swp_flag);
+    TRACE_("%p new size = %dx%d", w, qr.width(), qr.height());
+}
+
+void VidWin::get_size()
+{
+    if (!hwnd.info.win.hwnd) return;
+
+    HWND w = (HWND)hwnd.info.win.hwnd;
+    RECT r;
+    if (GetWindowRect(w, &r))
+	size_hint = QSize(r.right-r.left+1, r.bottom-r.top+1);
+    TRACE_("%p size = %dx%d", w, size_hint.width(), size_hint.height());
+}
+
+#elif defined(__APPLE__)
+
+#import<Cocoa/Cocoa.h>
+
+void VidWin::attach()
+{
+    if (!hwnd.info.cocoa.window) return;
+
     /* Embed hwnd to widget */
-    pj_assert(hwnd.type == PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS);
-    HWND h = (HWND)hwnd.info.win.hwnd;
-    HWND new_parent = (HWND)winId();
-
-    //old_parent_hwnd.type = PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS;
-    //old_parent_hwnd.info.win.hwnd = GetParent(h);
-
-    SetParent(h, new_parent);
-    SetWindowLong(h, GWL_STYLE, WS_CHILD);
-    ShowWindow(h, SW_SHOWNOACTIVATE);
-    PJ_LOG(3, (THIS_FILE, "%p parent handle = %p", h, new_parent));
-}
-
-void VidWin::resize()
-{
-    /* Update position and size */
-    HWND h = (HWND)hwnd.info.win.hwnd;
-    QRect qr = rect();
-    UINT swp_flag = SWP_SHOWWINDOW | SWP_NOACTIVATE;
-    SetWindowPos(h, HWND_TOP, 0, 0, qr.width(), qr.height(), swp_flag);
-    PJ_LOG(3, (THIS_FILE, "%p new size = %d x %d", h, qr.width(), qr.height()));
-}
-
-#elif defined(PJ_DARWINOS)
-
-#import<Cocoa/Cocoa.h>
-
-void VidWin::embed()
-{
-    /* Embed hwnd to widget */
-    pj_assert(hwnd.type != PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS);
     NSWindow *w = (NSWindow*)hwnd.info.cocoa.window;
     NSWindow *parent = [(NSView*)winId() window];
+    orig_parent = [w parentWindow];
 
     //[w setStyleMask:NSBorderlessWindowMask];
 
+    //Can't use this, as sometime the video window may not get reparented.
     //[w setParentWindow:parent];
+
     [parent addChildWindow:w ordered:NSWindowAbove];
-    PJ_LOG(3, (THIS_FILE, "%p parent handle = %p", w, parent));
-}
-
-
-void VidWin::resize()
-{
+    TRACE_("%p new parent handle = %p", w, parent);
+}
+
+
+void VidWin::detach()
+{
+    if (!hwnd.info.cocoa.window) return;
+
+    NSWindow *w = (NSWindow*)hwnd.info.cocoa.window;
+    NSWindow *parent = [(NSView*)winId() window];
+    [parent removeChildWindow:w]; 
+}
+
+
+void VidWin::set_size()
+{
+    if (!hwnd.info.cocoa.window) return;
+
     /* Update position and size */
     NSWindow *w = (NSWindow*)hwnd.info.cocoa.window;
@@ -154,68 +166,80 @@
     NSView* v = (NSView*)winId();
     r = [v bounds];
-    //PJ_LOG(3, (THIS_FILE, "before: (%d,%d) %dx%d", r.origin.x, r.origin.y, r.size.width, r.size.height));
     r = [v convertRectToBase:r];
     r.origin = [[v window] convertBaseToScreen:r.origin];
-    //PJ_LOG(3, (THIS_FILE, "after: (%d,%d) %dx%d", r.origin.x, r.origin.y, r.size.width, r.size.height));
 
     QRect qr = rect();
-/*
-    QPoint p = pos();
-    QPoint pp = parentWidget()->pos();
-    PJ_LOG(3, (THIS_FILE, "this pos: (%d,%d)", p.x(), p.y()));
-    PJ_LOG(3, (THIS_FILE, "parent pos: (%d,%d)", pp.x(), pp.y()));
-    
-    //qr.setTopLeft(mapToGlobal(qr.topLeft()));
-    r.origin.x = qr.x();
-    r.origin.y = qr.y();
-    r.size.width = qr.width();
-    r.size.height = qr.height();
-    //r.origin = [w convertBaseToScreen:r.origin];
-*/
     [w setFrame:r display:NO]; 
 
-    PJ_LOG(3, (THIS_FILE, "%p new size = %d x %d", w, qr.width(), qr.height()));
-}
-
-#elif defined(PJ_LINUX)
+    TRACE_("%p new size = %dx%d", w, qr.width(), qr.height());
+}
+
+void VidWin::get_size()
+{
+    if (!hwnd.info.cocoa.window) return;
+
+    NSWindow *w = (NSWindow*)hwnd.info.cocoa.window;
+
+    size_hint = QSize(300, 200);
+
+    TRACE_("%p size = %dx%d", 0, size_hint.width(), size_hint.height());
+}
+
+
+#elif defined(linux) || defined(__linux)
 
 #include <X11/Xlib.h>
-//#include <QX11Info>
-
-void VidWin::embed()
-{
+#include <X11/Xutil.h>
+#include <QX11Info>
+#include <stdio.h>
+
+void VidWin::attach()
+{
+    if (!hwnd.info.x11.window) return;
+
     /* Embed hwnd to widget */
-    pj_assert(hwnd.type != PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS);
-    Display *d = (Display*)hwnd.info.x11.display;
-    //Display *d = QX11Info::display();
+
+    // Use Qt X11 display here, using window creator X11 display may cause
+    // the window failing to embed to this QWidget.
+    //Display *d = (Display*)hwnd.info.x11.display;
+    Display *d = QX11Info::display();
     Window w = (Window)hwnd.info.x11.window;
     Window parent = (Window)this->winId();
-
-    XSetWindowBorderWidth(d, w, 0);
-
     int err = XReparentWindow(d, w, parent, 0, 0);
-    PJ_LOG(3, (THIS_FILE, "XReparentWindow() err = %d", err));
-    //XRaiseWindow(d, w);
-    //XMapSubwindows(d, parent);
-    //XMapWindow(d, parent);
-    //XMapWindow(d, w);
-    //XSync(d, False);
-    
-    PJ_LOG(3, (THIS_FILE, "[%p,%p] parent handle = %p", d, w, parent));
-}
-
-
-void VidWin::resize()
-{
+    TRACE_("%p new parent handle = %p, err = %d",
+	   (void*)w,(void*)parent, err);
+}
+
+
+void VidWin::detach()
+{
+}
+
+
+void VidWin::set_size()
+{
+    if (!hwnd.info.x11.window) return;
+
     /* Update position and size */
-    Display *d = (Display*)hwnd.info.x11.display;
+    Display *d = QX11Info::display();
     Window w = (Window)hwnd.info.x11.window;
     QRect qr = rect();
-    //XResizeWindow(d, w, qr.width(), qr.height());
-    XMoveResizeWindow(d, w, 0, 0, qr.width(), qr.height());
-
-    PJ_LOG(3, (THIS_FILE, "[%p,%p] new size = %d x %d", d, w, qr.width(), qr.height()));
-    //XSync(d, False);
-    XFlush(d);
+
+    int err = XResizeWindow(d, w, qr.width(), qr.height());
+    TRACE_("[%p,%p] new size = %dx%d, err = %d",
+	   (void*)d, (void*)w, qr.width(), qr.height(), err);
+}
+
+void VidWin::get_size()
+{
+    if (!hwnd.info.x11.window) return;
+
+    Display *d = QX11Info::display();
+    Window w = (Window)hwnd.info.x11.window;
+
+    XWindowAttributes attr;
+    XGetWindowAttributes(d, w, &attr);
+    size_hint = QSize(attr.width, attr.height);
+    TRACE_("%p size = %dx%d", w, size_hint.width(), size_hint.height());
 }
 
Index: pjproject/trunk/pjsip-apps/src/vidgui/vidwin.h
===================================================================
--- pjproject/trunk/pjsip-apps/src/vidgui/vidwin.h	(revision 3698)
+++ pjproject/trunk/pjsip-apps/src/vidgui/vidwin.h	(revision 3699)
@@ -10,24 +10,24 @@
 
 public:
-    // hwnd	    Handle of the video rendering window.
-    VidWin(pjmedia_vid_dev_hwnd *hwnd = NULL, 
+    VidWin(const pjmedia_vid_dev_hwnd *hwnd,
 	   QWidget* parent = 0,
 	   Qt::WindowFlags f = 0);
     virtual ~VidWin();
+    QSize sizeHint() const { return size_hint; }
 
 protected:
-    void resizeEvent(QResizeEvent *e);
+    virtual bool event(QEvent *e);
 
 private:
     pjmedia_vid_dev_hwnd hwnd;
-    //pjmedia_vid_dev_hwnd old_parent_hwnd;
-    pj_timer_entry timer_entry;
+    void *orig_parent;
+    QSize size_hint;
 
-    static void timer_cb(pj_timer_heap_t *timer_heap,
-			 struct pj_timer_entry *entry);
-
-    void embed();
-    void resize();
+    void attach();
+    void detach();
+    void set_size();
+    void get_size();
 };
 
 #endif
+
