diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 7f9f40d38..3fb72d829 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -173,6 +173,10 @@ IF(DYNAMIC_OPENSCENEGRAPH) ENDIF() ENDIF() + IF (QT4_FOUND) + ADD_SUBDIRECTORY(osgQtBrowser) + ENDIF() + IF (FLTK_FOUND) ADD_SUBDIRECTORY(osgviewerFLTK) ENDIF(FLTK_FOUND) diff --git a/examples/osgQtBrowser/CMakeLists.txt b/examples/osgQtBrowser/CMakeLists.txt new file mode 100644 index 000000000..17da87e43 --- /dev/null +++ b/examples/osgQtBrowser/CMakeLists.txt @@ -0,0 +1,22 @@ +SET(SOURCES_H + QGraphicsViewAdapter.h +) + +QT4_WRAP_CPP( SOURCES_H_MOC ${SOURCES_H} ) + +INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} "./") + +SET(TARGET_SRC + ${SOURCES_H_MOC} + QGraphicsViewAdapter.cpp + QWebViewImage.cpp + osgQtBrowser.cpp +) + +SET(TARGET_EXTERNAL_LIBRARIES ${QT_QTCORE_LIBRARY_RELEASE} ${QT_QTGUI_LIBRARY_RELEASE} ${QT_QTOPENGL_LIBRARY_RELEASE} ${QT_QTWEBKIT_LIBRARY_RELEASE}) +INCLUDE_DIRECTORIES(${QT_INCLUDE_DIR} ) + +SET(TARGET_ADDED_LIBRARIES osgWidget ) + +#### end var setup ### +SETUP_EXAMPLE(osgQtBrowser) diff --git a/examples/osgQtBrowser/QGraphicsViewAdapter.cpp b/examples/osgQtBrowser/QGraphicsViewAdapter.cpp new file mode 100644 index 000000000..23bff778d --- /dev/null +++ b/examples/osgQtBrowser/QGraphicsViewAdapter.cpp @@ -0,0 +1,458 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ + +#include "QGraphicsViewAdapter.h" +#include "QWebViewImage.h" + +#include + +#include + +#include + +#define MYQKEYEVENT 2000 +#define MYQPOINTEREVENT 2001 + +QCoreApplication* getOrCreateQApplication() +{ + if (QApplication::instance()==0) + { + static char** argv = 0; + static int argc = 0; + static QApplication app(argc,argv); + } + return QApplication::instance(); +} + +class MyQKeyEvent : public QEvent +{ +public: + MyQKeyEvent( int key, bool down ): + QEvent( QEvent::Type(MYQKEYEVENT) ), + _key(key), _down(down) {} + + int _key; + bool _down; +}; + +struct MyQPointerEvent : public QEvent +{ + MyQPointerEvent(int x, int y, unsigned int buttonMask): + QEvent( QEvent::Type(MYQPOINTEREVENT) ), + _x(x), _y(y),_buttonMask(buttonMask) {} + + int _x, _y; + unsigned int _buttonMask; +}; + +QGraphicsViewAdapter::QGraphicsViewAdapter(osg::Image* image, QWidget* widget): + _image(image), + _backgroundColor(255,255,255), + _qtKeyModifiers(Qt::NoModifier) +{ + // make sure we have a valid QApplication before we start creating widgets. + getOrCreateQApplication(); + + + setUpKeyMap(); + + _graphicsScene = new QGraphicsScene(); + _graphicsView = new QGraphicsView; + _graphicsScene->addWidget(widget); + _graphicsView->setScene(_graphicsScene); + _graphicsScene->setStickyFocus(true); + _graphicsView->viewport()->setParent(0); + + int width = _graphicsScene->width(); + int height = _graphicsScene->height(); + + _qimages[0] = QImage(QSize(width, height), QImage::Format_ARGB32); + _qimages[0].fill(_backgroundColor.rgba()); + _qimages[0] = QGLWidget::convertToGLFormat(_qimages[0]); + + _qimages[1] = QImage(QSize(width, height), QImage::Format_ARGB32); + _qimages[1].fill(_backgroundColor.rgba()); + + _qimages[2] = QImage(QSize(width, height), QImage::Format_ARGB32); + _qimages[2].fill(_backgroundColor.rgba()); + + _currentRead = 0; + _currentWrite = 1; + _previousWrite = 2; + _previousFrameNumber = 0; + _newImageAvailable = false; + + connect(_graphicsScene, SIGNAL(changed(const QList &)), + this, SLOT(repaintRequestedSlot(const QList &))); + + assignImage(0); +} + +void QGraphicsViewAdapter::repaintRequestedSlot(const QList&) +{ + // osg::notify(osg::NOTICE)<<"QGraphicsViewAdapter::repaintRequestedSlot"<type()==MYQKEYEVENT) + { + MyQKeyEvent* keyEvent = (MyQKeyEvent*)event; + handleKeyEvent(keyEvent->_key, keyEvent->_down); + } + else if (event->type()==MYQPOINTEREVENT) + { + MyQPointerEvent* pointerEvent = (MyQPointerEvent*)event; + handlePointerEvent(pointerEvent->_x, pointerEvent->_y, pointerEvent->_buttonMask); + } +} + + +void QGraphicsViewAdapter::setUpKeyMap() +{ + _keyMap[osgGA::GUIEventAdapter::KEY_BackSpace] = Qt::Key_Backspace; + _keyMap[osgGA::GUIEventAdapter::KEY_Tab] = Qt::Key_Tab; + _keyMap[osgGA::GUIEventAdapter::KEY_Linefeed] = Qt::Key_Return; // No LineFeed in Qt! + _keyMap[osgGA::GUIEventAdapter::KEY_Clear] = Qt::Key_Clear; + _keyMap[osgGA::GUIEventAdapter::KEY_Return] = Qt::Key_Return; + _keyMap[osgGA::GUIEventAdapter::KEY_Pause] = Qt::Key_Pause; + _keyMap[osgGA::GUIEventAdapter::KEY_Scroll_Lock] = Qt::Key_ScrollLock; + _keyMap[osgGA::GUIEventAdapter::KEY_Sys_Req] = Qt::Key_SysReq; + _keyMap[osgGA::GUIEventAdapter::KEY_Escape] = Qt::Key_Escape; + _keyMap[osgGA::GUIEventAdapter::KEY_Delete] = Qt::Key_Delete; + + _keyMap[osgGA::GUIEventAdapter::KEY_Home] = Qt::Key_Home; + _keyMap[osgGA::GUIEventAdapter::KEY_Left] = Qt::Key_Left; + _keyMap[osgGA::GUIEventAdapter::KEY_Up] = Qt::Key_Up; + _keyMap[osgGA::GUIEventAdapter::KEY_Right] = Qt::Key_Right; + _keyMap[osgGA::GUIEventAdapter::KEY_Down] = Qt::Key_Down; + _keyMap[osgGA::GUIEventAdapter::KEY_Prior] = Qt::Key_Left; // no Prior in Qt + _keyMap[osgGA::GUIEventAdapter::KEY_Page_Up] = Qt::Key_PageUp; + _keyMap[osgGA::GUIEventAdapter::KEY_Next] = Qt::Key_Right; // No Next in Qt + _keyMap[osgGA::GUIEventAdapter::KEY_Page_Down] = Qt::Key_PageDown; + _keyMap[osgGA::GUIEventAdapter::KEY_End] = Qt::Key_End; + _keyMap[osgGA::GUIEventAdapter::KEY_Begin] = Qt::Key_Home; // No Begin in Qt + + _keyMap[osgGA::GUIEventAdapter::KEY_Select] = Qt::Key_Select; + _keyMap[osgGA::GUIEventAdapter::KEY_Print] = Qt::Key_Print; + _keyMap[osgGA::GUIEventAdapter::KEY_Execute] = Qt::Key_Execute; + _keyMap[osgGA::GUIEventAdapter::KEY_Insert] = Qt::Key_Insert; + //_keyMap[osgGA::GUIEventAdapter::KEY_Undo] = Qt::Key_; // no Undo + //_keyMap[osgGA::GUIEventAdapter::KEY_Redo] = Qt::Key_; // no Redo + _keyMap[osgGA::GUIEventAdapter::KEY_Menu] = Qt::Key_Menu; + _keyMap[osgGA::GUIEventAdapter::KEY_Find] = Qt::Key_Search; // no Qt Find + _keyMap[osgGA::GUIEventAdapter::KEY_Cancel] = Qt::Key_Cancel; + _keyMap[osgGA::GUIEventAdapter::KEY_Help] = Qt::Key_Help; + _keyMap[osgGA::GUIEventAdapter::KEY_Break] = Qt::Key_Escape; // no break + _keyMap[osgGA::GUIEventAdapter::KEY_Mode_switch] = Qt::Key_Mode_switch; + _keyMap[osgGA::GUIEventAdapter::KEY_Script_switch] = Qt::Key_Mode_switch; // no Script switch + _keyMap[osgGA::GUIEventAdapter::KEY_Num_Lock] = Qt::Key_NumLock; + + _keyMap[osgGA::GUIEventAdapter::KEY_Shift_L] = Qt::Key_Shift; + _keyMap[osgGA::GUIEventAdapter::KEY_Shift_R] = Qt::Key_Shift; + _keyMap[osgGA::GUIEventAdapter::KEY_Control_L] = Qt::Key_Control; + _keyMap[osgGA::GUIEventAdapter::KEY_Control_R] = Qt::Key_Control; + _keyMap[osgGA::GUIEventAdapter::KEY_Caps_Lock] = Qt::Key_CapsLock; + _keyMap[osgGA::GUIEventAdapter::KEY_Shift_Lock] = Qt::Key_CapsLock; + + _keyMap[osgGA::GUIEventAdapter::KEY_Meta_L] = Qt::Key_Meta; // Qt doesn't have a Meta L + _keyMap[osgGA::GUIEventAdapter::KEY_Meta_R] = Qt::Key_Meta; // Qt doesn't have a Meta R + _keyMap[osgGA::GUIEventAdapter::KEY_Alt_L] = Qt::Key_Alt; // Qt doesn't have a Alt L + _keyMap[osgGA::GUIEventAdapter::KEY_Alt_R] = Qt::Key_Alt; // Qt doesn't have a Alt R + _keyMap[osgGA::GUIEventAdapter::KEY_Super_L] = Qt::Key_Super_L; + _keyMap[osgGA::GUIEventAdapter::KEY_Super_R] = Qt::Key_Super_R; + _keyMap[osgGA::GUIEventAdapter::KEY_Hyper_L] = Qt::Key_Hyper_L; + _keyMap[osgGA::GUIEventAdapter::KEY_Hyper_R] = Qt::Key_Hyper_R; + + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Space] = Qt::Key_Space; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Tab] = Qt::Key_Tab; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Enter] = Qt::Key_Enter; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_F1] = Qt::Key_F1; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_F2] = Qt::Key_F2; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_F3] = Qt::Key_F3; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_F4] = Qt::Key_F4; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Home] = Qt::Key_Home; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Left] = Qt::Key_Left; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Up] = Qt::Key_Up; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Right] = Qt::Key_Right; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Down] = Qt::Key_Down; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Prior] = Qt::Key_Left; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Page_Up] = Qt::Key_PageUp; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Next] = Qt::Key_Right; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Page_Down] = Qt::Key_PageDown; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_End] = Qt::Key_End; + + // _keyMap[osgGA::GUIEventAdapter::KEY_KP_Begin] = Qt::Key_Begin; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Insert] = Qt::Key_Insert; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Delete] = Qt::Key_Delete; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Equal] = Qt::Key_Equal; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Multiply] = Qt::Key_Asterisk; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Add] = Qt::Key_Plus; + //_keyMap[osgGA::GUIEventAdapter::KEY_KP_Separator] = Qt::Key_; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Subtract] = Qt::Key_Minus; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Decimal] = Qt::Key_Period; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Divide] = Qt::Key_division; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_0] = Qt::Key_0; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_1] = Qt::Key_1; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_2] = Qt::Key_2; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_3] = Qt::Key_3; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_4] = Qt::Key_4; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_5] = Qt::Key_5; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_6] = Qt::Key_6; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_7] = Qt::Key_7; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_8] = Qt::Key_8; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_9] = Qt::Key_9; + + _keyMap[osgGA::GUIEventAdapter::KEY_F1] = Qt::Key_F1; + _keyMap[osgGA::GUIEventAdapter::KEY_F2] = Qt::Key_F2; + _keyMap[osgGA::GUIEventAdapter::KEY_F3] = Qt::Key_F3; + _keyMap[osgGA::GUIEventAdapter::KEY_F4] = Qt::Key_F4; + _keyMap[osgGA::GUIEventAdapter::KEY_F5] = Qt::Key_F5; + _keyMap[osgGA::GUIEventAdapter::KEY_F6] = Qt::Key_F6; + _keyMap[osgGA::GUIEventAdapter::KEY_F7] = Qt::Key_F7; + _keyMap[osgGA::GUIEventAdapter::KEY_F8] = Qt::Key_F8; + _keyMap[osgGA::GUIEventAdapter::KEY_F9] = Qt::Key_F9; + _keyMap[osgGA::GUIEventAdapter::KEY_F10] = Qt::Key_F10; + _keyMap[osgGA::GUIEventAdapter::KEY_F11] = Qt::Key_F11; + _keyMap[osgGA::GUIEventAdapter::KEY_F12] = Qt::Key_F12; + _keyMap[osgGA::GUIEventAdapter::KEY_F13] = Qt::Key_F13; + _keyMap[osgGA::GUIEventAdapter::KEY_F14] = Qt::Key_F14; + _keyMap[osgGA::GUIEventAdapter::KEY_F15] = Qt::Key_F15; + _keyMap[osgGA::GUIEventAdapter::KEY_F16] = Qt::Key_F16; + _keyMap[osgGA::GUIEventAdapter::KEY_F17] = Qt::Key_F17; + _keyMap[osgGA::GUIEventAdapter::KEY_F18] = Qt::Key_F18; + _keyMap[osgGA::GUIEventAdapter::KEY_F19] = Qt::Key_F19; + _keyMap[osgGA::GUIEventAdapter::KEY_F20] = Qt::Key_F20; + _keyMap[osgGA::GUIEventAdapter::KEY_F21] = Qt::Key_F21; + _keyMap[osgGA::GUIEventAdapter::KEY_F22] = Qt::Key_F22; + _keyMap[osgGA::GUIEventAdapter::KEY_F23] = Qt::Key_F23; + _keyMap[osgGA::GUIEventAdapter::KEY_F24] = Qt::Key_F24; + _keyMap[osgGA::GUIEventAdapter::KEY_F25] = Qt::Key_F25; + _keyMap[osgGA::GUIEventAdapter::KEY_F26] = Qt::Key_F26; + _keyMap[osgGA::GUIEventAdapter::KEY_F27] = Qt::Key_F27; + _keyMap[osgGA::GUIEventAdapter::KEY_F28] = Qt::Key_F28; + _keyMap[osgGA::GUIEventAdapter::KEY_F29] = Qt::Key_F29; + _keyMap[osgGA::GUIEventAdapter::KEY_F30] = Qt::Key_F30; + _keyMap[osgGA::GUIEventAdapter::KEY_F31] = Qt::Key_F31; + _keyMap[osgGA::GUIEventAdapter::KEY_F32] = Qt::Key_F32; + _keyMap[osgGA::GUIEventAdapter::KEY_F33] = Qt::Key_F33; + _keyMap[osgGA::GUIEventAdapter::KEY_F34] = Qt::Key_F34; + _keyMap[osgGA::GUIEventAdapter::KEY_F35] = Qt::Key_F35; + +} + +bool QGraphicsViewAdapter::sendPointerEvent(int x, int y, int buttonMask) +{ + QCoreApplication::postEvent(this, new MyQPointerEvent(x,y,buttonMask)); + return true; +} + +bool QGraphicsViewAdapter::handlePointerEvent(int x, int y, int buttonMask) +{ + osg::notify(osg::INFO)<<"dispatchPointerEvent("<height()-y; + + bool leftButtonPressed = (buttonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)!=0; + bool middleButtonPressed = (buttonMask & osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON)!=0; + bool rightButtonPressed = (buttonMask & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)!=0; + + bool prev_leftButtonPressed = (_previousButtonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)!=0; + bool prev_middleButtonPressed = (_previousButtonMask & osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON)!=0; + bool prev_rightButtonPressed = (_previousButtonMask & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)!=0; + + osg::notify(osg::INFO)<<"leftButtonPressed "<(_image.get()); + if (qwebViewImage) qwebViewImage->focusBrowser(true); + } + + QMouseEvent event(eventType, QPoint(x, y), qtButton, qtMouseButtons, 0); + QCoreApplication::sendEvent(_graphicsView->viewport(), &event ); + + _previousButtonMask = buttonMask; + } + else if (x != _previousMouseX || y != _previousMouseY) + { + + QMouseEvent event(QEvent::MouseMove, QPoint(x, y), Qt::NoButton, qtMouseButtons, 0); + QCoreApplication::sendEvent(_graphicsView->viewport(), &event); + + _previousMouseX = x; + _previousMouseY = y; + } + + return true; +} + +bool QGraphicsViewAdapter::sendKeyEvent(int key, bool keyDown) +{ + QCoreApplication::postEvent(this, new MyQKeyEvent(key,keyDown)); + return true; +} + +bool QGraphicsViewAdapter::handleKeyEvent(int key, bool keyDown) +{ + QEvent::Type eventType = keyDown ? QEvent::KeyPress : QEvent::KeyRelease; + + osg::notify(osg::INFO)<<"sendKeyEvent("<second; + } + else + { + qtkey = (Qt::Key)key; + input = QChar(key); + } + + QKeyEvent event(eventType, qtkey, _qtKeyModifiers, input); + QCoreApplication::sendEvent(_graphicsScene.data(), &event); + return true; +} + +void QGraphicsViewAdapter::setFrameLastRendered(const osg::FrameStamp* frameStamp) +{ + osg::notify(osg::INFO)<<"setFrameLastRendered("<getFrameNumber()<<")"<getFrameNumber()) + { + { + OpenThreads::ScopedLock lock(_qimagesMutex); + + // make sure that _previousFrameNumber hasn't been updated by another thread since we entered this branch. + if (_previousFrameNumber==frameStamp->getFrameNumber()) return; + _previousFrameNumber = frameStamp->getFrameNumber(); + + std::swap(_currentRead, _previousWrite); + _newImageAvailable = false; + } + + assignImage(_currentRead); + } +} + +void QGraphicsViewAdapter::clearWriteBuffer() +{ + QImage& image = _qimages[_currentWrite]; + image.fill(_backgroundColor.rgba ()); + image = QGLWidget::convertToGLFormat(image); + + // swap the write buffers in a thread safe way + OpenThreads::ScopedLock lock(_qimagesMutex); + std::swap(_currentWrite, _previousWrite); + _newImageAvailable = true; +} + +void QGraphicsViewAdapter::render() +{ + osg::notify(osg::INFO)<<"Current write = "<<_currentWrite<width(), _graphicsScene->height()); + _graphicsView->render(&painter, destinationRect, sourceRect); + painter.end(); +#else + // paint the image with the graphics view + QPixmap pixmap(image.width(), image.height()); + QPainter painter(&pixmap); + QRectF destinationRect(0, 0, image.width(), image.height()); + QRect sourceRect(0, 0, _graphicsScene->width(), _graphicsScene->height()); + _graphicsView->render(&painter, destinationRect, sourceRect); + painter.end(); + + image = pixmap.toImage(); +#endif + + // convert into OpenGL format - flipping around the Y axis and swizzling the pixels + image = QGLWidget::convertToGLFormat(image); + + // swap the write buffers in a thread safe way + OpenThreads::ScopedLock lock(_qimagesMutex); + std::swap(_currentWrite, _previousWrite); + _newImageAvailable = true; +} + +void QGraphicsViewAdapter::assignImage(unsigned int i) +{ + QImage& image = _qimages[i]; + unsigned char* data = image.bits(); + + osg::notify(osg::INFO)<<"assigImage("<settings()->setAttribute(QWebSettings::JavascriptEnabled, true); + _webPage->settings()->setAttribute(QWebSettings::PluginsEnabled, true); + + _webView->setPage(_webPage); + + _adapter = new QGraphicsViewAdapter(this, _webView.data()); +} + +void QWebViewImage::navigateTo(const std::string& url) +{ + _webView->load(QUrl(url.c_str())); +} + +void QWebViewImage::focusBrowser(bool focus) +{ + QFocusEvent event(focus ? QEvent::FocusIn : QEvent::FocusOut, Qt::OtherFocusReason); + QCoreApplication::sendEvent(_webPage, &event); +} + +void QWebViewImage::clearWriteBuffer() +{ + _adapter->clearWriteBuffer(); +} + +void QWebViewImage::render() +{ + _adapter->render(); +} + +void QWebViewImage::setFrameLastRendered(const osg::FrameStamp* frameStamp) +{ + _adapter->setFrameLastRendered(frameStamp); +} + +bool QWebViewImage::sendPointerEvent(int x, int y, int buttonMask) +{ + return _adapter->sendPointerEvent(x,y,buttonMask); +} + +bool QWebViewImage::sendKeyEvent(int key, bool keyDown) +{ + return QWebViewImage::_adapter->sendKeyEvent(key, keyDown); +} + diff --git a/examples/osgQtBrowser/QWebViewImage.h b/examples/osgQtBrowser/QWebViewImage.h new file mode 100644 index 000000000..59710a18e --- /dev/null +++ b/examples/osgQtBrowser/QWebViewImage.h @@ -0,0 +1,51 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ + +#ifndef QWEBVIEWIMAGE +#define QWEBVIEWIMAGE + +#include +#include "QGraphicsViewAdapter.h" + +class QWebViewImage : public osgWidget::BrowserImage +{ + public: + + QWebViewImage(); + + virtual void navigateTo(const std::string& url); + + QWebView* getQWebView() { return _webView; } + QWebPage* getQWebPage() { return _webPage; } + QGraphicsViewAdapter* getQGraphicsViewAdapter() { return _adapter; } + + void focusBrowser(bool focus); + + void clearWriteBuffer(); + + void render(); + + virtual void setFrameLastRendered(const osg::FrameStamp* frameStamp); + + virtual bool sendPointerEvent(int x, int y, int buttonMask); + + virtual bool sendKeyEvent(int key, bool keyDown); + + protected: + + QPointer _adapter; + QPointer _webView; + QPointer _webPage; +}; + +#endif \ No newline at end of file diff --git a/examples/osgQtBrowser/osgQtBrowser.cpp b/examples/osgQtBrowser/osgQtBrowser.cpp new file mode 100644 index 000000000..65a1b31ca --- /dev/null +++ b/examples/osgQtBrowser/osgQtBrowser.cpp @@ -0,0 +1,138 @@ +/* OpenSceneGraph example, osgcompositeviewer. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include + +#include "QGraphicsViewAdapter.h" +#include "QWebViewImage.h" + + +// Thread that runs the viewer's frame loop as we can't run Qt in the background... +class ViewerFrameThread : public OpenThreads::Thread +{ + public: + + ViewerFrameThread(osgViewer::ViewerBase* viewerBase, bool doQApplicationExit): + _viewerBase(viewerBase), + _doQApplicationExit(doQApplicationExit) {} + + ~ViewerFrameThread() + { + cancel(); + while(isRunning()) + { + OpenThreads::Thread::YieldCurrentThread(); + } + } + + int cancel() + { + _viewerBase->setDone(true); + return 0; + } + + void run() + { + int result = _viewerBase->run(); + + if (_doQApplicationExit) QApplication::exit(result); + } + + osg::ref_ptr _viewerBase; + bool _doQApplicationExit; +}; + + +int main(int argc, char **argv) +{ + // Qt requires that we construct the global QApplication before creating any widgets. + QApplication app(argc, argv); + + // use an ArgumentParser object to manage the program arguments. + osg::ArgumentParser arguments(&argc,argv); + + bool useFrameLoopThread = true; + if (arguments.read("--no-frame-thread")) useFrameLoopThread = false; + + osg::ref_ptr image = new QWebViewImage; + + if (arguments.argc()>1) image->navigateTo((arguments[1])); + else image->navigateTo("http://www.youtube.com/"); + + osgWidget::GeometryHints hints(osg::Vec3(0.0f,0.0f,0.0f), + osg::Vec3(1.0f,0.0f,0.0f), + osg::Vec3(0.0f,0.0f,1.0f), + osg::Vec4(1.0f,1.0f,1.0f,1.0f), + osgWidget::GeometryHints::RESIZE_HEIGHT_TO_MAINTAINCE_ASPECT_RATIO); + + + osg::ref_ptr browser = new osgWidget::Browser; + browser->assign(image.get(), hints); + + // image->focusBrowser(true); + + osg::ref_ptr viewer = new osgViewer::Viewer(arguments); + viewer->setSceneData(browser.get()); + viewer->setCameraManipulator(new osgGA::TrackballManipulator()); + viewer->addEventHandler(new osgViewer::StatsHandler); + viewer->addEventHandler(new osgViewer::WindowSizeHandler); + + if (useFrameLoopThread) + { + // create a thread to run the viewer's frame loop + ViewerFrameThread viewerThread(viewer.get(), true); + viewerThread.startThread(); + + // now start the standard Qt event loop, then exists when the viewerThead sends the QApplication::exit() signal. + return QApplication::exec(); + + } + else + { + // run the frame loop, interleaving Qt and the main OSG frame loop + while(!viewer->done()) + { + // process Qt events - this handles both events and paints the browser image + QCoreApplication::processEvents(QEventLoop::AllEvents, 100); + + viewer->frame(); + } + + return 0; + } +}