blob: 3e38b6cdc5933e48cb8fe98db2d3b46ba88d54d5 [file] [log] [blame]
/* $Id$ */
/*
* 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