| /* $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 |
| |