diff options
Diffstat (limited to 'pjsip-apps/src/vidgui/vidwin.cpp')
-rw-r--r-- | pjsip-apps/src/vidgui/vidwin.cpp | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/pjsip-apps/src/vidgui/vidwin.cpp b/pjsip-apps/src/vidgui/vidwin.cpp new file mode 100644 index 0000000..1caee89 --- /dev/null +++ b/pjsip-apps/src/vidgui/vidwin.cpp @@ -0,0 +1,309 @@ +/* $Id: vidwin.cpp 4060 2012-04-17 09:55:30Z ming $ */ +/* + * Copyright (C) 2011 Teluu Inc. (http://www.teluu.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "vidwin.h" +#include <QEvent> + +#define THIS_FILE "vidwin.cpp" +#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() +{ + show_sdl(false); + detach(); +} + +void VidWin::putIntoLayout(QBoxLayout *box) +{ + box->addWidget(this, 1); + show(); + activateWindow(); +} + +bool VidWin::event(QEvent *e) +{ + switch(e->type()) { + + case QEvent::Resize: + set_size(); + break; + + case QEvent::ParentChange: + get_size(); + if (0) { + 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; + + case QEvent::Show: + show_sdl(true); + // revert to default size hint, make it resizable + setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + break; + + case QEvent::Hide: + show_sdl(false); + break; + + default: + break; + } + + return QWidget::event(e); +} + +/* Platform specific code */ + +#if defined(_WIN32) && !defined(_WIN32_WINCE) + +#include <windows.h> + +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); + + //SetWindowLong(w, GWL_STYLE, WS_CHILD); + SetParent(w, new_parent); + 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; + 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()); +} + +void VidWin::show_sdl(bool visible) +{ + if (!hwnd.info.win.hwnd) return; + + HWND w = (HWND)hwnd.info.win.hwnd; + ShowWindow(w, visible ? SW_SHOW : SW_HIDE); +} + +#elif defined(__APPLE__) + +#import<Cocoa/Cocoa.h> + +void VidWin::attach() +{ + if (!hwnd.info.cocoa.window) return; + + /* Embed hwnd to widget */ + 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]; + 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; + NSRect r; + + NSView* v = (NSView*)winId(); + r = [v bounds]; + r = [v convertRectToBase:r]; + r.origin = [[v window] convertBaseToScreen:r.origin]; + + QRect qr = rect(); + [w setFrame:r display:NO]; + + 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()); +} + +void VidWin::show_sdl(bool visible) +{ + if (!hwnd.info.cocoa.window) return; + + NSWindow *w = (NSWindow*)hwnd.info.cocoa.window; + + if (visible) { + [[w contentView]setHidden:NO]; + } else { + [[w contentView]setHidden:YES]; + } +} + +#elif defined(linux) || defined(__linux) + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <QX11Info> +#include <stdio.h> + +#define GET_DISPLAY() QX11Info::display() +//#define GET_DISPLAY() (Display*)hwnd.info.x11.display + +void VidWin::attach() +{ + if (!hwnd.info.x11.window) return; + + /* Embed hwnd to widget */ + + // 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 = GET_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); +} + + +void VidWin::detach() +{ +} + + +void VidWin::set_size() +{ + if (!hwnd.info.x11.window) return; + + /* Update position and size */ + Display *d = GET_DISPLAY(); + Window w = (Window)hwnd.info.x11.window; + QRect qr = rect(); + + 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 = GET_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()); +} + +void VidWin::show_sdl(bool visible) +{ + if (!hwnd.info.x11.window) return; + + Display *d = GET_DISPLAY(); + Window w = (Window)hwnd.info.x11.window; + + if (visible) { + XMapRaised(d, w); + } else { + XUnmapWindow(d, w); + } + + XFlush(d); +} + +#endif + |