├── README.md ├── src ├── main.cpp ├── mlbrowser.pro ├── mleventlistener.cpp ├── mleventlistener.h ├── mlkeyfilter.cpp ├── mlkeyfilter.h ├── mlplayer.cpp ├── mlplayer.h ├── mlpropertychanger.cpp ├── mlpropertychanger.h ├── mlwebkit.cpp └── mlwebkit.h └── start.html /README.md: -------------------------------------------------------------------------------- 1 | 2 | mlbrowser for Rasbian 3 | ===================== 4 | 5 | This fork contains fixes and adjustments so that the browser can be compiled and run on a standard Rasbian installation. 6 | In addition to Raspbian it also needs the prebuilt Qt5 packages from http://twolife.be/raspbian , 7 | 8 | In Addition to the fork from @Topguy this fork does contain some minimal adjustments to allow the the browser to be 9 | displayed rotated for portrait mode displays. Furthermore the Mousecursor can be hidden. 10 | 11 | 12 | HOW-TO: 13 | ------- 14 | 15 | *Start with.* 16 | 17 | Raspbian installed from image or NOOBS. 18 | 19 | *Add the twolife.be repository to you software sources:* 20 | 21 | sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-key 2578B775 22 | sudo bash -c "echo \"deb http://twolife.be/raspbian/ wheezy main backports\" > /etc/apt/sources.list.d/twolife.list" 23 | 24 | (You might still get warnings about non-authenticated packages, havent looked into it.) 25 | 26 | *Update and upgrade:* 27 | 28 | sudo apt-get update 29 | sudo apt-get upgrade 30 | 31 | *Install minimal Qt5 requirements and make Qt5 default Qt environment.* 32 | 33 | sudo apt-get install libqt5webkit5-dev qtdeclarative5-dev qt5-default qt5-qmake 34 | 35 | 36 | *Checkout source:* 37 | 38 | git clone https://github.com/Topguy/mlbrowser.git 39 | cd mlbrowser 40 | 41 | *Configure build* 42 | 43 | mkdir build 44 | cd build 45 | qmake DEFINES+=_BROWSER_ DEFINES+=_MOUSE_ DEFINES+=_PROPERTYCHANGER_ ../src/mlbrowser.pro 46 | 47 | *build* 48 | 49 | make 50 | 51 | _NOTE!!!_ It will now fail to link with a list of libraries it can't find. 52 | It doesnt really need those libraries, so as a hack you replace the line starting with "LIBS" in the Makefile with this line: 53 | 54 | *LIBS* 55 | 56 | LIBS = $(SUBLIBS) -L/opt/vc/lib -lQt5WebKitWidgets -pthread -lrt -L/usr/lib/arm-linux-gnueabihf -lQt5Sql -lQt5Quick -lQt5OpenGL -lQt5PrintSupport -lQt5WebKit -lQt5Qml -lQt5Widgets -lQt5Network -lQt5Gui -lQt5Core -lGLESv2 -lpthread 57 | 58 | *then rerun make* 59 | 60 | make 61 | 62 | _NOTE!!!_ If you get a not found warning for libGLESv2.so.2 and libEGL.so.1, create the following symlinks: 63 | 64 | sudo ln -fs /opt/vc/lib/libEGL.so /usr/lib/arm-linux-gnueabihf/libEGL.so.1 65 | sudo ln -fs /opt/vc/lib/libGLESv2.so /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2 66 | 67 | 68 | And now it should link properly. 69 | 70 | *Test it:* 71 | 72 | ./mlbrowser -platform eglfs http://www.raspberrypi.org 73 | 74 | 75 | *Install it:* 76 | 77 | sudo make install 78 | 79 | *View local html-file:* 80 | 81 | mlbrowser -platform eglfs file:///home/pi/mlbrowser/start.html 82 | 83 | 84 | New program options 85 | ------------------- 86 | -x or -w adjusts horizontal overscan. 87 | 88 | -y or -h adjusts vertical overscan. 89 | 90 | -z adjusts zoom-factor (something like 1.3 to 1.6 looks nice on my TV) 91 | 92 | mlbrowser -platform eglfs -x 92 -y 48 -z 1.3 http://www.google.com 93 | 94 | -r sets rotation mode 95 | 1: rotate 90 degrees clockwise 96 | 2: rotate 180 degrees clockwise 97 | 3: rotate 270 degrees clockwise (aka. 90 degrees counterclockwise) 98 | 99 | -m hide the mouse cursor 100 | 101 | ### TIP No.1: 102 | 103 | If you add mlbrowser to /etc/rc.local it will cause yout Pi to boot directly into the browser on each boot. 104 | But you'll have to use the full path to the binary. 105 | 106 | /usr/local/bin/mlbrowser -platform eglfs http://www.google.com 107 | 108 | 109 | ### TIP No.2: 110 | 111 | Adding this to a script or your .profile file make sure that you dont have to write "-platform eglfs" every time. 112 | 113 | export QT_QPA_PLATFORM=eglfs 114 | 115 | 116 | mlbrowser 117 | ========= 118 | (original readme) 119 | 120 | This is the respository for the mlbrowser that has been developed by Metrological. It can be used with the buildroot fork at https://github.com/albertd/buildroot-rpi or its fork https://github.com/msieben/buildroot-rpi.git. 121 | 122 | You can add this package to your own fork of buildroot by adding the Config.in and mlbrowser.mk files. 123 | 124 | *Config.in* 125 | 126 | config BR2_PACKAGE_MLBROWSER 127 | bool "mlbrowser" 128 | help 129 | Metrological's simple (accellerated) browser implementation 130 | http://www.metrological.com 131 | 132 | *mlbrowser.mk* 133 | 134 | ############################################################# 135 | # 136 | # mlbrowser 137 | # 138 | ############################################################# 139 | 140 | MLBROWSER_VERSION = e7bba1439ff9b38dfd36c6222e4825c5d17e7677 141 | MLBROWSER_SITE_METHOD = git 142 | MLBROWSER_SITE = https://github.com/msieben/mlbrowser.git 143 | 144 | ifeq ($(BR2_PACKAGE_QT5WEBKIT),y) 145 | MLBROWSER_DEPENDENCIES = qt5webkit 146 | endif 147 | 148 | ifeq ($(BR2_PACKAGE_QT_WEBKIT),y) 149 | MLBROWSER_DEPENDENCIES = qt gstreamer 150 | endif 151 | 152 | define MLBROWSER_CONFIGURE_CMDS 153 | (cd $(@D); \ 154 | $(TARGET_MAKE_ENV) \ 155 | $(HOST_DIR)/usr/bin/qmake \ 156 | DEFINES+=_BROWSER_ \ 157 | DEFINES+=_MOUSE_ \ 158 | DEFINES+=_PROPERTYCHANGER_ \ 159 | ./src/mlbrowser.pro \ 160 | ) 161 | endef 162 | 163 | define MLBROWSER_BUILD_CMDS 164 | $(TARGET_MAKE_ENV) $(MAKE) -C $(@D) 165 | endef 166 | 167 | define MLBROWSER_INSTALL_TARGET_CMDS 168 | $(INSTALL) -D -m 0755 $(@D)/mlbrowser $(TARGET_DIR)/usr/bin 169 | endef 170 | 171 | define MLBROWSER_UNINSTALL_TARGET_CMDS 172 | rm -f $(TARGET_DIR)/usr/bin/mlbrowser 173 | endef 174 | 175 | $(eval $(generic-package)) 176 | 177 | Have fun! 178 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #define _BUILD_TIME_ __TIME__ 2 | #define _BUILD_DATE_ __DATE__ 3 | 4 | #include 5 | #include 6 | 7 | #ifdef _KEYFILTER_ 8 | #include 9 | #include 10 | #endif 11 | 12 | #ifdef _EVENTMONITORING_ 13 | #include "mleventlistener.h" 14 | #endif 15 | 16 | #ifdef _VERBOSE_ 17 | #include 18 | #endif 19 | 20 | #ifdef _BROWSER_ 21 | #include "mlwebkit.h" 22 | #endif 23 | 24 | #ifdef _PLAYER_ 25 | #include "mlplayer.h" 26 | #endif 27 | 28 | #ifdef _PROPERTYCHANGER_ 29 | #include "mlpropertychanger.h" 30 | #endif 31 | 32 | #ifdef _KEYFILTER_ 33 | #include "mlkeyfilter.h" 34 | #endif 35 | 36 | #ifdef _VERBOSE_ 37 | void MessageHandler ( QtMsgType type, const QMessageLogContext& context, const QString& message ) 38 | { 39 | /* 40 | black - 30 41 | red - 31 42 | green - 32 43 | brown - 33 44 | blue - 34 45 | magenta - 35 46 | cyan - 36 47 | lightgray - 37 48 | */ 49 | 50 | std::cerr 51 | << QCoreApplication::instance ()->applicationName().toStdString() 52 | // << " : [ version ] " 53 | // << context.version 54 | << " : [ file ] " 55 | << "\033[0;31m" << context.file << "\033[0m" 56 | << " : [ line ] " 57 | << "\033[0;35m" << context.line << "\033[0m" 58 | // << " : [ category ] " 59 | // << context.category 60 | << " : [ type ] " 61 | << "\033[0;36m"; 62 | 63 | switch ( type ) 64 | { 65 | case QtDebugMsg : 66 | std::cerr << "debug"; 67 | break; 68 | case QtWarningMsg : 69 | std::cerr << "warning"; 70 | break; 71 | case QtCriticalMsg : 72 | std::cerr << "critical"; 73 | break; 74 | case QtFatalMsg : 75 | std::cerr << "fatal"; 76 | break; 77 | default : 78 | ; 79 | } 80 | 81 | std::cerr 82 | << "\033[0m" 83 | << " : [ function ] " 84 | << "\033[0;34m" << context.function << "\033[0m" 85 | << " : [ message ] " 86 | << "\033[0;32m" << message.toStdString() << "\033[0m" 87 | << std::endl; 88 | } 89 | #endif 90 | 91 | int main(int argc, char * argv[]) 92 | { 93 | QApplication app(argc, argv); 94 | 95 | #ifdef _VERBOSE_ 96 | qInstallMessageHandler ( MessageHandler ); 97 | #endif 98 | 99 | qDebug () << "browser release (" << _BUILD_DATE_ << _BUILD_TIME_ <<")"; 100 | 101 | #ifdef _PLAYER_ 102 | Player player(NULL); 103 | #endif 104 | 105 | #ifdef _PROPERTYCHANGER_ 106 | PropertyChanger propertychanger(NULL); 107 | #endif 108 | 109 | //REMARK: order of filters is important; last installed -> receives first 110 | #ifdef _EVENTMONITORING_ 111 | qDebug () << "enable event monitoring"; 112 | EventListener eventlistener; 113 | 114 | app.installEventFilter ( &eventlistener ); 115 | #endif 116 | 117 | #ifdef _KEYFILTER_ 118 | qDebug () << "add keyboard filter"; 119 | KeyFilter keyfilter; 120 | 121 | app.installEventFilter ( &keyfilter ); 122 | #endif 123 | 124 | #ifdef _BROWSER_ 125 | QUrl url; 126 | int oscanw=0,oscanh=0; 127 | qreal zoom=1.3; 128 | int a; 129 | 130 | int rotationMode = 0; 131 | bool hiddenCursor = false; 132 | 133 | if (argc > 1) 134 | { 135 | for(a=1; aattach_object(&player, "player"); 178 | #endif 179 | 180 | #ifdef _PROPERTYCHANGER_ 181 | qDebug () << "add propertychanger"; 182 | browser->attach_object(&propertychanger, "propertychanger"); 183 | #endif 184 | 185 | qDebug () << "load and show page"; 186 | 187 | browser->load(url); 188 | browser->show(); 189 | #endif 190 | 191 | return app.exec(); 192 | 193 | #ifdef _BROWSER_ 194 | delete browser; 195 | #endif 196 | } 197 | 198 | -------------------------------------------------------------------------------- /src/mlbrowser.pro: -------------------------------------------------------------------------------- 1 | contains(QT_MAJOR_VERSION, 5) { 2 | QT += \ 3 | webkitwidgets \ 4 | widgets \ 5 | network 6 | } 7 | 8 | contains(QT_MAJOR_VERSION, 4) { 9 | QT += \ 10 | webkit \ 11 | network 12 | } 13 | 14 | TARGET = mlbrowser 15 | target.path = /usr/local/bin 16 | INSTALLS += target 17 | 18 | HEADERS = mlwebkit.h 19 | 20 | SOURCES = \ 21 | mlwebkit.cpp \ 22 | main.cpp 23 | 24 | contains(DEFINES, _EVENTMONITORING_) { 25 | HEADERS += mleventlistener.h 26 | SOURCES += mleventlistener.cpp 27 | } 28 | contains(DEFINES, _KEYFILTER_) { 29 | HEADERS += mlkeyfilter.h 30 | SOURCES += mlkeyfilter.cpp 31 | } 32 | 33 | contains(DEFINES, _PROPERTYCHANGER_) { 34 | HEADERS += mlpropertychanger.h 35 | SOURCES += mlpropertychanger.cpp 36 | } 37 | 38 | 39 | contains(DEFINES, _PLAYER_) { 40 | HEADERS += mlplayer.h 41 | SOURCES += mlplayer.cpp 42 | 43 | unix { 44 | CONFIG += link_pkgconfig 45 | PKGCONFIG += gstreamer-0.10 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/mleventlistener.cpp: -------------------------------------------------------------------------------- 1 | #include "mleventlistener.h" 2 | 3 | #include 4 | #include 5 | 6 | bool EventListener::eventFilter(QObject* pObject, QEvent* pEvent) 7 | { 8 | switch ( pEvent->type() ) 9 | { 10 | case QEvent::KeyPress : 11 | case QEvent::Paint : // 12 Screen update necessary (QPaintEvent). 12 | case QEvent::UpdateLater : // 78 The widget should be queued to be repainted at a later time. 13 | case QEvent::UpdateRequest : // 77 The widget should be repainted. 14 | { 15 | qDebug () << "QObject : " << pObject << " : event type : " << pEvent->type(); 16 | } 17 | default : 18 | ; 19 | } 20 | 21 | return QObject::eventFilter(pObject, pEvent); 22 | } 23 | -------------------------------------------------------------------------------- /src/mleventlistener.h: -------------------------------------------------------------------------------- 1 | #ifndef MLEVENTLISTENER_H 2 | #define MLEVENTLISTENER_H 3 | 4 | #include 5 | 6 | class EventListener : public QObject 7 | { 8 | protected: 9 | bool eventFilter(QObject* pObject, QEvent* pEvent); 10 | }; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/mlkeyfilter.cpp: -------------------------------------------------------------------------------- 1 | #include "mlkeyfilter.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "mlwebkit.h" 9 | 10 | bool KeyFilter::eventFilter(QObject* pObject, QEvent* pEvent) 11 | { 12 | if ( pEvent->type() == QEvent::KeyPress ) 13 | { 14 | //TODO: understand why a stream of keycode = 0 with alternating repeat occurs 15 | 16 | QKeyEvent* pKeyEvent = static_cast< QKeyEvent* >( pEvent ); 17 | 18 | /* 19 | pKeyEvent->count 20 | pKeyEvent->isAutoRepeat 21 | pKeyEvent->key 22 | pKeyEvent->matches 23 | pKeyEvent->modifiers 24 | pKeyEvent->nativeModifiers 25 | pKeyEvent->nativeScanCode 26 | pKeyEvent->nativeVirtualKey 27 | pKeyEvent->text 28 | */ 29 | 30 | if ( pKeyEvent->key() != 0 ) // avoid a (default) stream of output 31 | { 32 | qDebug() << "key code (Qt::Key) : " << QString("%1").arg(pKeyEvent->key(), 0, 16) << " : unicode : " << pKeyEvent->text() << " : modifiers (or of Qt::KeyboardModifier's) : "<< pKeyEvent->modifiers() << " : keypress event (true/false) : " << true << " : key by autorepeat mechanism (true/false) : " << pKeyEvent->isAutoRepeat(); 33 | //TODO: check values 34 | 35 | switch ( pKeyEvent->key() ) 36 | { 37 | case Qt::Key_Select : // 0x1010000 38 | { 39 | QKeyEvent keyevent ( QEvent::KeyPress, Qt::Key_Enter, pKeyEvent->modifiers(), "", pKeyEvent->isAutoRepeat(), 1 ); 40 | qDebug () << "send event : " << QCoreApplication::sendEvent ( reinterpret_cast (QApplication::focusWidget()), &keyevent ); 41 | return true; 42 | } 43 | 44 | case Qt::Key_Menu : // 0x1000055 45 | { 46 | QKeyEvent keyevent ( QEvent::KeyPress, Qt::Key_Backspace, pKeyEvent->modifiers(), "", pKeyEvent->isAutoRepeat(), 1 ); 47 | qDebug () << "send event : " << QCoreApplication::sendEvent ( reinterpret_cast (QApplication::focusWidget()), &keyevent ); 48 | return true; 49 | } 50 | 51 | case Qt::Key_HomePage : // 'Apps', 0x1000090 52 | { 53 | QKeyEvent keyevent ( QEvent::KeyPress, Qt::Key_F8, pKeyEvent->modifiers(), "", pKeyEvent->isAutoRepeat(), 1 ); 54 | qDebug () << "send event : " << QCoreApplication::sendEvent ( reinterpret_cast (QApplication::focusWidget()), &keyevent ); 55 | return true; 56 | } 57 | case Qt::Key_Favorites : // 'FAV1', 0x1000091 58 | { 59 | QKeyEvent keyevent ( QEvent::KeyPress, Qt::Key_F10, pKeyEvent->modifiers(), "", pKeyEvent->isAutoRepeat(), 1 ); 60 | qDebug () << "send event : " << QCoreApplication::sendEvent ( reinterpret_cast (QApplication::focusWidget()), &keyevent ); 61 | return true; 62 | } 63 | #ifdef _INSPECTOR_ 64 | case Qt::Key_Period : // '.' (period), 0x2e 65 | { 66 | //TODO: move to the browser context menu event 67 | 68 | // show / hide webinspector 69 | MLWebKit* pWebKit = MLWebKit::instance(); 70 | 71 | if (pWebKit != NULL ) 72 | pWebKit->inspector(); 73 | 74 | return true; 75 | } 76 | 77 | case Qt::Key_VolumeMute : // 0x1000071 78 | { 79 | QKeyEvent keyevent ( QEvent::KeyPress, Qt::Key_BracketRight, Qt::ControlModifier, "", pKeyEvent->isAutoRepeat(), 1 ); 80 | qDebug () << "send event : " << QCoreApplication::sendEvent ( reinterpret_cast (QApplication::focusWidget()), &keyevent ); 81 | return true; 82 | } 83 | 84 | #endif 85 | default: 86 | ; 87 | } 88 | } 89 | } 90 | 91 | return QObject::eventFilter(pObject, pEvent); 92 | } 93 | -------------------------------------------------------------------------------- /src/mlkeyfilter.h: -------------------------------------------------------------------------------- 1 | #ifndef MLKEYFILETR_H 2 | #define MLKEYFILETR_H 3 | 4 | #include 5 | 6 | class KeyFilter : public QObject 7 | { 8 | protected: 9 | bool eventFilter(QObject* pObject, QEvent* pEvent); 10 | }; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/mlplayer.cpp: -------------------------------------------------------------------------------- 1 | #include "mlplayer.h" 2 | 3 | #include 4 | 5 | Player::Player(QObject* object) 6 | { 7 | Q_UNUSED(object); 8 | 9 | qDebug () << "create player"; 10 | 11 | gst_init ( NULL, NULL ); 12 | // gst_init ( &argc, &argv ); 13 | } 14 | 15 | bool Player::load(QString _url_) 16 | { 17 | qDebug () << "load url : " << _url_; 18 | 19 | url.clear(); 20 | url = _url_; 21 | 22 | //TODO: dynamic allocation 23 | char pdef [500]; 24 | //TODO: verify 25 | sprintf(pdef,"gst-launch-0.10 videotestsrc ! queue ! eglglessink"); 26 | 27 | //sprintf(pdef,"gst-launch-0.10 playbin2c uri=%s ! queue ! eglglessink", url.toLatin1().constData() ); 28 | 29 | pbin = gst_parse_launch ( pdef, NULL ); 30 | 31 | if ( pbin == NULL ) 32 | { 33 | qDebug () << "cannot create pipeline (elements)"; 34 | return false; 35 | } 36 | 37 | //TODO: check return value 38 | gst_element_set_state ( pbin, GST_STATE_READY ); 39 | 40 | gst_element_set_state ( pbin, GST_STATE_PAUSED ); 41 | 42 | return true; 43 | } 44 | 45 | bool Player::start(void) 46 | { 47 | qDebug () << "start playback"; 48 | 49 | if ( pbin == NULL ) 50 | { 51 | qDebug () << "cannot start playback"; 52 | return false; 53 | } 54 | 55 | //TODO: check return value 56 | gst_element_set_state ( pbin, GST_STATE_PLAYING ); 57 | 58 | return true; 59 | } 60 | 61 | bool Player::pause(void) 62 | { 63 | qDebug () << "pause playback"; 64 | 65 | if ( pbin == NULL ) 66 | { 67 | qDebug () << "cannot pause playback"; 68 | return false; 69 | } 70 | 71 | //TODO: check return value 72 | gst_element_set_state ( pbin, GST_STATE_PAUSED ); 73 | 74 | return true; 75 | } 76 | 77 | bool Player::resume(void) 78 | { 79 | qDebug () << "resume playback"; 80 | 81 | if ( pbin == NULL ) 82 | { 83 | qDebug () << "cannot cannot resume playback"; 84 | return false; 85 | } 86 | 87 | //TODO: check return value 88 | gst_element_set_state ( pbin, GST_STATE_PLAYING ); 89 | 90 | return true; 91 | } 92 | 93 | bool Player::stop(void) 94 | { 95 | qDebug () << "stop playback"; 96 | 97 | if ( pbin == NULL ) 98 | qDebug () << "cannot stop playback"; 99 | return false; 100 | 101 | //TODO: check return value 102 | 103 | pause(); 104 | 105 | gst_element_set_state ( pbin, GST_STATE_READY ); 106 | 107 | return true; 108 | } 109 | 110 | bool Player::quit(void) 111 | { 112 | qDebug () << "quit player"; 113 | 114 | stop(); 115 | 116 | //TODO: check return value 117 | gst_element_set_state ( pbin, GST_STATE_NULL ); 118 | 119 | pbin = NULL; 120 | 121 | url.clear(); 122 | 123 | return true; 124 | } 125 | 126 | Player::~Player() 127 | { 128 | quit(); 129 | } 130 | 131 | -------------------------------------------------------------------------------- /src/mlplayer.h: -------------------------------------------------------------------------------- 1 | #ifndef MLPLAYER_H 2 | #define MLPLAYER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Player : public QObject 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | Player(QObject* object); 14 | ~Player(); 15 | 16 | Q_INVOKABLE bool load(QString url); 17 | Q_INVOKABLE bool start(void); 18 | Q_INVOKABLE bool pause(void); 19 | Q_INVOKABLE bool resume(void); 20 | Q_INVOKABLE bool stop(void); 21 | Q_INVOKABLE bool quit(void); 22 | 23 | private: 24 | QString url; 25 | GstElement* pbin; 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/mlpropertychanger.cpp: -------------------------------------------------------------------------------- 1 | #include "mlpropertychanger.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | PropertyChanger::PropertyChanger(QObject* pObject) 8 | { 9 | Q_UNUSED(pObject); 10 | qDebug () << "parent :" << this->parent(); 11 | } 12 | 13 | PropertyChanger::~PropertyChanger() 14 | { 15 | } 16 | 17 | bool PropertyChanger::set_repaint_throttle(QString value) 18 | { 19 | QWebFrame* pFrame = static_cast < QWebFrame* > ( this->parent() ); 20 | QWebPage* pPage = NULL; 21 | 22 | if ( pFrame != NULL ) 23 | pPage = pFrame->page(); 24 | else 25 | return false; 26 | 27 | if ( pPage == NULL ) 28 | return false; 29 | 30 | //TODO: check values 31 | pPage->setProperty("_q_RepaintThrottlingPreset", value); 32 | 33 | return true; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/mlpropertychanger.h: -------------------------------------------------------------------------------- 1 | #ifndef MLPROPERTYCHANGER_H 2 | #define MLPROPERTYCHANGER_H 3 | 4 | #include 5 | 6 | class PropertyChanger : public QObject 7 | { 8 | Q_OBJECT 9 | 10 | public: 11 | PropertyChanger(QObject* object); 12 | ~PropertyChanger(); 13 | 14 | Q_INVOKABLE bool set_repaint_throttle(QString value); // "NoThrottling", "Legacy", "Minimal", "Medium", "Heavy" 15 | private: 16 | //QWebFrame* pFrame; 17 | }; 18 | #endif 19 | -------------------------------------------------------------------------------- /src/mlwebkit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "mlwebkit.h" 9 | 10 | 11 | #include 12 | 13 | 14 | #ifdef _PLAYER_ 15 | #include "mlplayer.h" 16 | #endif 17 | 18 | 19 | #ifdef QT_OPENGL_LIB 20 | #undef QT_OPENGL_LIB 21 | #endif 22 | 23 | class GraphicsWebView : public QGraphicsWebView 24 | { 25 | public: 26 | GraphicsWebView() 27 | { 28 | } 29 | 30 | protected: 31 | void contextMenuEvent(QGraphicsSceneContextMenuEvent* ev) 32 | { 33 | 34 | qDebug () << "received a context event"; 35 | 36 | if ( ev != NULL ) 37 | ev->ignore(); 38 | 39 | /* 40 | QContextMenuEvent::Mouse 41 | QContextMenuEvent::Keyboard 42 | QContextMenuEvent::Other 43 | */ 44 | 45 | } 46 | }; 47 | 48 | class WebPage : public QWebPage 49 | { 50 | public: 51 | 52 | protected: 53 | void javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& source) 54 | { 55 | QString logEntry = source + " [" + QString::number(lineNumber) + "]:" + message.toUtf8().constData(); 56 | qDebug()<mainFrame(); 109 | 110 | pFrame->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff ); 111 | pFrame->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff ); 112 | 113 | QApplication* pApp = (QApplication *)QApplication::instance(); 114 | 115 | QDesktopWidget* pDesktop = QApplication::desktop(); 116 | 117 | if ( pScene == NULL || pView == NULL || pWebview == NULL || pPage == NULL || pFrame == NULL || pApp == NULL || pDesktop == NULL ) 118 | { 119 | qDebug () << "unable to construct browser (elements)"; 120 | return; 121 | } 122 | 123 | // Rotate View according to rotationMode 124 | pView->rotate(90*rotationMode); 125 | 126 | #ifdef QT_OPENGL_LIB 127 | pWidget = NULL; 128 | // pWidget = new QGLWidget(); 129 | // pWidget = new QGLWidget(pView); 130 | #endif 131 | 132 | #ifdef _INSPECTOR_ 133 | pInspector = new QWebInspector; 134 | pInspector->setPage(pPage); 135 | pInspector->resize(QApplication::desktop()->screenGeometry().size()); 136 | #endif 137 | 138 | // Configuration, settings and alike 139 | // pScene->setItemIndexMethod( QGraphicsScene::NoIndex); 140 | // pView->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); 141 | pView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); 142 | // pView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); 143 | // pView->setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate); 144 | 145 | // Disable some 'browser features / elements' 146 | pView->setFrameShape(QFrame::NoFrame); 147 | pView->setHorizontalScrollBarPolicy ( Qt::ScrollBarAlwaysOff ); 148 | pView->setVerticalScrollBarPolicy ( Qt::ScrollBarAlwaysOff ); 149 | 150 | // pView->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); 151 | pView->setWindowFlags(Qt::FramelessWindowHint); 152 | pView->showFullScreen(); 153 | 154 | // Overrule the 'foreground' and 'background' defaults with transparent colors 155 | QPalette palette; 156 | palette.setBrush(QPalette::Active, QPalette::Window, Qt::SolidPattern); 157 | palette.setBrush(QPalette::Active, QPalette::Base, Qt::SolidPattern); 158 | palette.setBrush(QPalette::Inactive, QPalette::Window, Qt::SolidPattern); 159 | palette.setBrush(QPalette::Inactive, QPalette::Base, Qt::SolidPattern); 160 | palette.setColor(QPalette::Active, QPalette::Window, QColor(0, 0, 0x80, 255)); 161 | // Nice light grey default backgroundcolor. Change to bright red if you want to see overscan borders. 162 | palette.setColor(QPalette::Active, QPalette::Base, QColor(0xC0, 0xc0, 0xc0, 255)); 163 | palette.setColor(QPalette::Inactive, QPalette::Window, QColor(0, 0, 0, 255)); 164 | palette.setColor(QPalette::Inactive, QPalette::Base, QColor(0, 0, 0, 255)); 165 | 166 | pApp->setPalette(palette); 167 | 168 | 169 | //TODO: implement check 170 | QSizeF screenSize = pDesktop->screenGeometry().size(); 171 | qDebug () << "screen geometry : " << screenSize; 172 | 173 | QSizeF displaySize; 174 | switch (rotationMode) { 175 | break; 176 | case 1: 177 | case 3: 178 | displaySize = QSizeF( 179 | screenSize.height() - overscanw, 180 | screenSize.width() - overscanh 181 | ); 182 | break; 183 | case 0: 184 | case 2: 185 | default: 186 | displaySize = QSizeF( 187 | screenSize.width() - overscanw, 188 | screenSize.height() - overscanh 189 | ); 190 | } 191 | qDebug () << "display geometry : " << displaySize; 192 | 193 | pWebview->resize(displaySize); 194 | pWebview->setPage(pPage); 195 | 196 | // Set the keyboard and mouse focus 197 | pWebview->setFocus(); 198 | 199 | // Some extra settings 200 | QWebSettings* pSettings = pWebview->settings(); 201 | 202 | #ifdef _INSPECTOR_ 203 | pSettings->setAttribute(QWebSettings::DeveloperExtrasEnabled, true); 204 | #endif 205 | 206 | pSettings->setAttribute(QWebSettings::AcceleratedCompositingEnabled, true); 207 | pSettings->setAttribute(QWebSettings::WebGLEnabled, false); 208 | pSettings->setAttribute(QWebSettings::PluginsEnabled, false); 209 | pSettings->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, true); 210 | pSettings->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true); 211 | pSettings->setAttribute(QWebSettings::LocalContentCanAccessFileUrls, true); 212 | // pSettings->setAttribute(QWebSettings::FrameFlatteningEnabled, true); 213 | pSettings->setAttribute(QWebSettings::LocalStorageEnabled, true); 214 | // pSettings->setAttribute(QWebSettings::WebSecurityEnabled, false); 215 | pSettings->setAttribute(QWebSettings::SpatialNavigationEnabled, false); 216 | 217 | // Overrule the cache settings 218 | /* 219 | pSettings->setMaximumPagesInCache(0); 220 | pSettings->setObjectCacheCapacities(0, 0, 0); 221 | pSettings->QWebSettings::clearMemoryCaches(); 222 | */ 223 | 224 | // Finalize 225 | #ifdef QT_OPENGL_LIB 226 | // pView->setViewport(pWidget); 227 | pView->setViewport(new QGLWidget(QGL::DirectRendering | QGL::DoubleBuffer)); 228 | #endif 229 | 230 | pScene->addItem(pWebview); 231 | 232 | #ifdef _INSPECTOR_ 233 | pProxyWidget = pScene->addWidget(pInspector); 234 | #endif 235 | 236 | // Set visibility 237 | 238 | #ifdef _INSPECTOR_ 239 | // pInspector->hide(); 240 | pProxyWidget->hide(); 241 | #endif 242 | 243 | // Set zoomfactor. (help readability) 244 | pWebview->setZoomFactor(zoom); 245 | //pWebview->setTextSizeMultiplier(zoom); 246 | 247 | pWebview->show(); 248 | } 249 | 250 | MLWebKit::~MLWebKit() 251 | { 252 | qDebug () << "clean up browser (elements)"; 253 | 254 | /* 255 | if (pInspector != NULL) 256 | delete pInspector; 257 | */ 258 | 259 | if (pWebview != NULL) 260 | delete pWebview; 261 | 262 | if (pView != NULL) 263 | delete pView; 264 | 265 | if (pScene != NULL) 266 | delete pScene; 267 | 268 | if (pObject != NULL) 269 | delete pObject; 270 | } 271 | 272 | void MLWebKit::load(QUrl url) 273 | { 274 | qDebug () << "load ( url ) : " << url; 275 | 276 | if (pWebview != NULL) 277 | pWebview->load(url); 278 | } 279 | 280 | void MLWebKit::show() 281 | { 282 | qDebug () << "show ()"; 283 | 284 | if (pView != NULL) 285 | pView->show(); 286 | } 287 | 288 | void MLWebKit::hide() 289 | { 290 | qDebug () << "hide ()"; 291 | 292 | if (pView != NULL) 293 | pView->hide(); 294 | } 295 | 296 | 297 | #if defined (_PLAYER_) || defined (_PROPERTYCHANGER_) 298 | void MLWebKit::attach_object(QObject* _pObject_, QString _name_) 299 | { 300 | qDebug () << "attach_player()"; 301 | 302 | if ( pFrame != NULL) 303 | { 304 | pObject = _pObject_; 305 | 306 | qDebug () << "change (NULL) parent to pFrame"; 307 | pObject->setParent(pFrame); 308 | 309 | qDebug () << "add webkit bridge for object " << pObject; 310 | //TODO: connect to slot to keep the object accessible when page has changed 311 | pFrame->addToJavaScriptWindowObject(_name_, pObject); 312 | 313 | 314 | } 315 | } 316 | #endif 317 | 318 | #ifdef _INSPECTOR_ 319 | void MLWebKit::inspector() 320 | { 321 | qDebug () << "toggle web inspector"; 322 | 323 | if(pInspector != NULL && pWebview != NULL) 324 | { 325 | 326 | if ( pInspector->isVisible() == false ) 327 | { 328 | qDebug () << "show webinspector"; 329 | 330 | pWebview->hide(); 331 | pWebview->setEnabled(false); 332 | pProxyWidget->show(); 333 | pProxyWidget->setEnabled(true); 334 | } 335 | else 336 | { 337 | qDebug () << "hide webinspector"; 338 | 339 | pProxyWidget->hide(); 340 | pProxyWidget->setEnabled(false); 341 | pWebview->show(); 342 | pWebview->setEnabled(true); 343 | } 344 | } 345 | else 346 | qDebug () << "some elements do not exist"; 347 | } 348 | #endif 349 | -------------------------------------------------------------------------------- /src/mlwebkit.h: -------------------------------------------------------------------------------- 1 | #ifndef MLWEBKIT_H 2 | #define MLWEBKIT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #ifdef QT_OPENGL_LIB 11 | #include 12 | #endif 13 | 14 | #ifdef _INSPECTOR_ 15 | #include 16 | #include 17 | #endif 18 | 19 | class MLWebKit 20 | { 21 | public: 22 | MLWebKit(int overscanw=0, int overscanh=0, qreal zoom=1.0, int rotationMode=0); 23 | ~MLWebKit(); 24 | 25 | void load(QUrl url); 26 | void show(); 27 | void hide(); 28 | 29 | #if defined (_PLAYER_) || defined (_PROPERTYCHANGER_) 30 | void attach_object(QObject* pObject, QString _name_); 31 | #endif 32 | 33 | #ifdef _INSPECTOR_ 34 | static MLWebKit* instance(); 35 | void inspector(); 36 | #endif 37 | 38 | private: 39 | QGraphicsView* pView; 40 | QGraphicsScene* pScene; 41 | QGraphicsWebView* pWebview; 42 | QWebPage* pPage; 43 | QWebFrame* pFrame; 44 | 45 | QObject* pObject; 46 | 47 | #ifdef QT_OPENGL_LIB 48 | QGLWidget* pWidget; // viewport 49 | #endif 50 | 51 | #ifdef _INSPECTOR_ 52 | static MLWebKit* pWebKit; 53 | QWebInspector* pInspector; 54 | QGraphicsProxyWidget* pProxyWidget; 55 | #endif 56 | }; 57 | #endif 58 | -------------------------------------------------------------------------------- /start.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

Google

5 |

Raspberry

6 |

BBC

7 |

NRK

8 |

Google Maps (Trondheim)

9 |
10 | 11 | 12 | --------------------------------------------------------------------------------