diff options
Diffstat (limited to 'pjsip-apps/src/vidgui/vidwin.cpp')
-rw-r--r-- | pjsip-apps/src/vidgui/vidwin.cpp | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/pjsip-apps/src/vidgui/vidwin.cpp b/pjsip-apps/src/vidgui/vidwin.cpp new file mode 100644 index 00000000..8e207e4e --- /dev/null +++ b/pjsip-apps/src/vidgui/vidwin.cpp @@ -0,0 +1,223 @@ +#include "vidwin.h" + +#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(); + break; + default: + break; + } + + 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); +} + +/* Platform specific code */ + +#if defined(PJ_WIN32) && !defined(PJ_WIN32_WINCE) + +#include <windows.h> + +void VidWin::embed() +{ + /* 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]; + + //[w setStyleMask:NSBorderlessWindowMask]; + + //[w setParentWindow:parent]; + [parent addChildWindow:w ordered:NSWindowAbove]; + PJ_LOG(3, (THIS_FILE, "%p parent handle = %p", w, parent)); +} + + +void VidWin::resize() +{ + /* Update position and size */ + NSWindow *w = (NSWindow*)hwnd.info.cocoa.window; + NSRect r; + + 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) + +#include <X11/Xlib.h> +//#include <QX11Info> + +void VidWin::embed() +{ + /* 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(); + 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() +{ + /* Update position and size */ + Display *d = (Display*)hwnd.info.x11.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); +} + +#endif + |