diff options
Diffstat (limited to 'pjsip-apps/src/vidgui/vidwin.cpp')
-rw-r--r-- | pjsip-apps/src/vidgui/vidwin.cpp | 302 |
1 files changed, 163 insertions, 139 deletions
diff --git a/pjsip-apps/src/vidgui/vidwin.cpp b/pjsip-apps/src/vidgui/vidwin.cpp index 8e207e4e..c8498242 100644 --- a/pjsip-apps/src/vidgui/vidwin.cpp +++ b/pjsip-apps/src/vidgui/vidwin.cpp @@ -1,222 +1,246 @@ #include "vidwin.h" +#include <QEvent> #define THIS_FILE "vidwin.cpp" -#define TIMER_EMBED 1 -#define TIMER_RESIZE 2 +#define TRACE_(...) PJ_LOG(4,(THIS_FILE, __VA_ARGS__)) -void VidWin::timer_cb(pj_timer_heap_t *timer_heap, - struct pj_timer_entry *entry) +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) { - 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); + 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() { - if (timer_entry.id) { - pjsua_cancel_timer(&timer_entry); - timer_entry.id = 0; - } + detach(); + pj_bzero(&hwnd, sizeof(hwnd)); + size_hint = QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + destroy(true, false); } - -void VidWin::resizeEvent(QResizeEvent*) +bool VidWin::event(QEvent *e) { - /* 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); + 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: + break; + } + + 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() { - /* Embed hwnd to widget */ - pj_assert(hwnd.type == PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS); - HWND h = (HWND)hwnd.info.win.hwnd; + 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); +} - //old_parent_hwnd.type = PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS; - //old_parent_hwnd.info.win.hwnd = GetParent(h); +void VidWin::detach() +{ + if (!hwnd.info.win.hwnd) return; - 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)); + 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::resize() +void VidWin::set_size() { - /* Update position and size */ - HWND h = (HWND)hwnd.info.win.hwnd; + if (!hwnd.info.win.hwnd) return; + + HWND w = (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())); + 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()); } -#elif defined(PJ_DARWINOS) +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::embed() +void VidWin::attach() { + if (!hwnd.info.cocoa.window) return; + /* 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)); + TRACE_("%p new parent handle = %p", w, parent); } -void VidWin::resize() +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; 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())); + TRACE_("%p new size = %dx%d", w, qr.width(), qr.height()); } -#elif defined(PJ_LINUX) +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> +#include <X11/Xutil.h> +#include <QX11Info> +#include <stdio.h> -void VidWin::embed() +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(); + int err = XReparentWindow(d, w, parent, 0, 0); + TRACE_("%p new parent handle = %p, err = %d", + (void*)w,(void*)parent, err); +} - 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::detach() +{ } -void VidWin::resize() +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()); } #endif |