Commit bc3a0717 authored by Stefano Crocco's avatar Stefano Crocco Committed by David Faure
Browse files

Add support for full screen web pages

Konqueror already has a full screen mode where the menu bar and the
title bar are hidden and the window takes all the space in the screen.
However, this isn't enough as some web pages (for example when those
playing a video) now expect a full screen mode (which I call complete
full screen) where an element of the page, and not just the window,
takes all the screen.

To achieve this kind of full screen, it's necessary to hide not only the
menu bar and the title bar, but also the status bar, the tab bar and the
tool bars. In theory, also the side bar and the terminal emulator should
be hidden, but this commit doesn't to that.

When switching to a different tab, the complete full screen mode is
automatically exited (because it's strictly related to the contents
of the page). Complete full screen mode is NOT entered again
automatically when switching back to the previous page. This is
consistent with the behavior of other browsers such as Chrome or
FireFox.

If Konqueror ...
parent 1a62207c
......@@ -83,6 +83,7 @@ set(konqueror_KDEINIT_SRCS
konqhistorydialog.cpp
konqstatusbarmessagelabel.cpp
konqurl.cpp
konqbrowserinterface.cpp
)
kconfig_add_kcfg_files(konqueror_KDEINIT_SRCS konqsettingsxt.kcfgc)
......
/*
* This file is part of the KDE project.
*
* Copyright 2020 Stefano Crocco <stefano.crocco@alice.it>
*
* 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) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#include <KParts/ReadOnlyPart>
#include "konqbrowserinterface.h"
#include "konqmainwindow.h"
KonqBrowserInterface::KonqBrowserInterface(KonqMainWindow *mainWindow, KParts::ReadOnlyPart *part):
KParts::BrowserInterface(mainWindow), m_mainWindow(mainWindow), m_part(part)
{
}
void KonqBrowserInterface::toggleCompleteFullScreen(bool on)
{
m_mainWindow->toggleCompleteFullScreen(on);
}
/*
* This file is part of the KDE project.
*
* Copyright 2020 Stefano Crocco <stefano.crocco@alice.it>
*
* 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) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef KONQBROWSERINTERFACE_H
#define KONQBROWSERINTERFACE_H
#include <KParts/BrowserInterface>
class KonqMainWindow;
namespace KParts {
class ReadOnlyPart;
}
/**
* Implementation of KParts::BrowserInterface which redirects calls to KonqMainWindow
*/
class KonqBrowserInterface : public KParts::BrowserInterface
{
Q_OBJECT
public:
/**
* Default constructor
*/
KonqBrowserInterface(KonqMainWindow *mainWindow, KParts::ReadOnlyPart *part);
~KonqBrowserInterface(){}
public slots:
void toggleCompleteFullScreen(bool on);
private:
KonqMainWindow *m_mainWindow;
KParts::ReadOnlyPart *m_part;
};
#endif // KONQBROWSERINTERFACE_H
......@@ -189,7 +189,7 @@ KonqMainWindow::KonqMainWindow(const QUrl &initialURL)
, m_bLocationBarConnected(false)
, m_bURLEnterLock(false)
, m_urlCompletionStarted(false)
, m_prevMenuBarVisible(true)
, m_fullScreenData{FullScreenState::NoFullScreen, FullScreenState::NoFullScreen, true, true, false}
, m_goBuffer(0)
, m_pBookmarkMenu(nullptr)
, m_configureDialog(nullptr)
......@@ -1974,6 +1974,15 @@ void KonqMainWindow::slotPartActivated(KParts::Part *part)
KonqView *newView = nullptr;
KonqView *oldView = m_currentView;
//Exit full screen when a new part is activated
if (m_fullScreenData.currentState == FullScreenState::CompleteFullScreen) {
if (oldView && oldView->part()) {
QMetaObject::invokeMethod(oldView->part(), "exitFullScreen");
} else { //This should never happen
toggleCompleteFullScreen(false);
}
}
if (part) {
newView = m_mapViews.value(static_cast<KParts::ReadOnlyPart *>(part));
Q_ASSERT(newView);
......@@ -3293,6 +3302,13 @@ void KonqMainWindow::slotShowStatusBar()
void KonqMainWindow::slotUpdateFullScreen(bool set)
{
if (m_fullScreenData.currentState == FullScreenState::CompleteFullScreen) {
if (m_currentView && m_currentView->part()) {
QMetaObject::invokeMethod(m_currentView->part(), "exitFullScreen");
}
return;
}
KToggleFullScreenAction::setFullScreen(this, set);
if (set) {
// Create toolbar button for exiting from full-screen mode
......@@ -3316,17 +3332,18 @@ void KonqMainWindow::slotUpdateFullScreen(bool set)
plugActionList(QStringLiteral("fullscreen"), lst);
}
m_prevMenuBarVisible = menuBar()->isVisible();
m_fullScreenData.wasMenuBarVisible = menuBar()->isVisible();
menuBar()->hide();
m_paShowMenuBar->setChecked(false);
} else {
unplugActionList(QStringLiteral("fullscreen"));
if (m_prevMenuBarVisible) {
if (m_fullScreenData.wasMenuBarVisible) {
menuBar()->show();
m_paShowMenuBar->setChecked(true);
}
}
m_fullScreenData.switchToState(set ? FullScreenState::OrdinaryFullScreen : FullScreenState::NoFullScreen);
}
void KonqMainWindow::setLocationBarURL(const QUrl &url)
......@@ -5577,3 +5594,84 @@ void KonqMainWindow::updateProxyForWebEngine(bool updateProtocolManager)
QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, url.host(), url.port(), url.userName(), url.password()));
}
}
void KonqMainWindow::toggleCompleteFullScreen(bool on)
{
//Do nothing if already in complete full screen mode and on is true or not in complete full screen mode and on is false
if (on == (m_fullScreenData.currentState == FullScreenState::CompleteFullScreen)) {
return;
}
if (on) {
slotForceSaveMainWindowSettings();
resetAutoSaveSettings();
//Hide the menu bar
menuBar()->setVisible(false);
//Hide the side bar
QAction *a = m_toggleViewGUIClient->action(QStringLiteral("konq_sidebartng"));
if (a) {
KToggleAction *ta = static_cast<KToggleAction*>(a);
if (ta){
m_fullScreenData.wasSidebarVisible = ta->isChecked();
a->setChecked(false);
}
}
//Hide the tool bars
const QList<QAction*> actions = toolBarMenuAction()->menu()->actions();
for (QAction *a : actions) {
a->setChecked(false);
}
} else {
setAutoSaveSettings();
}
//Status bar and side bar are not managed by autoSaveSettings
//Hide or show the sidebar
QAction *a = m_toggleViewGUIClient->action(QStringLiteral("konq_sidebartng"));
KToggleAction *sideBarAction = qobject_cast<KToggleAction*>(a);
if (sideBarAction) {
if (on) {
m_fullScreenData.wasSidebarVisible = sideBarAction ->isChecked();
sideBarAction ->setChecked(false);
} else if (m_fullScreenData.wasSidebarVisible) {
sideBarAction->setChecked(true);
}
}
//Hide or show the status bar
if (m_currentView) {
QStatusBar *statusBar = m_currentView->frame()->statusbar();
if (on) {
m_fullScreenData.wasStatusBarVisible = statusBar->isVisible();
statusBar->setVisible(false);
} else if (m_fullScreenData.wasStatusBarVisible) {
statusBar->setVisible(true);
}
}
if (on || m_fullScreenData.previousState == FullScreenState::NoFullScreen) {
disconnect(m_ptaFullScreen, &KToggleAction::toggled, this, &KonqMainWindow::slotUpdateFullScreen);
KToggleFullScreenAction::setFullScreen(this, on);
connect(m_ptaFullScreen, &KToggleAction::toggled, this, &KonqMainWindow::slotUpdateFullScreen);
}
m_pViewManager->forceHideTabBar(on);
if (on) {
QString msg = i18n("You have entered Complete Full Screen mode (the user interface is completely hidden)."
" You can exit it by pressing the keyboard shortcut for Full Screen Mode (%1)", m_ptaFullScreen->shortcut().toString());
KMessageBox::information(this, msg, QString(), "Complete Full Screen Warning");
}
m_fullScreenData.switchToState(on ? FullScreenState::CompleteFullScreen : m_fullScreenData.previousState);
}
void KonqMainWindow::FullScreenData::switchToState(KonqMainWindow::FullScreenState newState)
{
if (newState != currentState) {
previousState = currentState;
currentState = newState;
}
}
......@@ -509,6 +509,25 @@ protected:
void closeEvent(QCloseEvent *) override;
bool askForTarget(const KLocalizedString &text, QUrl &url);
private:
enum class FullScreenState {
NoFullScreen,
OrdinaryFullScreen,
CompleteFullScreen
};
struct FullScreenData {
FullScreenState previousState;
FullScreenState currentState;
bool wasMenuBarVisible;
bool wasStatusBarVisible;
bool wasSidebarVisible;
void switchToState(FullScreenState newState);
};
private Q_SLOTS:
void slotUndoTextChanged(const QString &newText);
......@@ -526,7 +545,9 @@ private Q_SLOTS:
void initBookmarkBar();
void showPageSecurity();
void toggleCompleteFullScreen(bool on);
private:
void updateWindowIcon();
......@@ -576,7 +597,7 @@ private:
QObject *lastFrame(KonqView *view);
QLineEdit *comboEdit();
private: // members
KonqUndoManager *m_pUndoManager;
......@@ -645,8 +666,9 @@ private: // members
// Set in constructor, used in slotRunFinished
bool m_bNeedApplyKonqMainWindowSettings: 1;
bool m_urlCompletionStarted: 1;
bool m_prevMenuBarVisible: 1;
FullScreenData m_fullScreenData;
int m_goBuffer;
Qt::MouseButtons m_goMouseState;
Qt::KeyboardModifiers m_goKeyboardState;
......@@ -709,6 +731,8 @@ private: // members
*/
bool m_isPopupWithProxyWindow;
QPointer<KonqMainWindow> m_popupProxyWindow;
friend class KonqBrowserInterface;
};
#endif // KONQMAINWINDOW_H
......@@ -54,7 +54,7 @@ KonqFrameTabs::KonqFrameTabs(QWidget *parent, KonqFrameContainerBase *parentCont
: KTabWidget(parent),
m_pPopupMenu(nullptr),
m_pSubPopupMenuTab(nullptr),
m_rightWidget(nullptr), m_leftWidget(nullptr), m_alwaysTabBar(false)
m_rightWidget(nullptr), m_leftWidget(nullptr), m_alwaysTabBar(false), m_forceHideTabBar(false)
{
// Set an object name so the widget style can identify this widget.
setObjectName(QStringLiteral("kde_konq_tabwidget"));
......@@ -436,7 +436,9 @@ void KonqFrameTabs::slotInitiateDrag(QWidget *w)
void KonqFrameTabs::updateTabBarVisibility()
{
if (m_alwaysTabBar) {
if (m_forceHideTabBar) {
tabBar()->hide();
} else if (m_alwaysTabBar) {
tabBar()->show();
} else {
tabBar()->setVisible(count() > 1);
......@@ -452,6 +454,15 @@ void KonqFrameTabs::setAlwaysTabbedMode(bool enable)
}
}
void KonqFrameTabs::forceHideTabBar(bool force)
{
if (m_forceHideTabBar != force) {
m_forceHideTabBar = force;
updateTabBarVisibility();
}
}
void KonqFrameTabs::initPopupMenu()
{
m_pPopupMenu = new QMenu(this);
......
......@@ -119,6 +119,7 @@ public:
public Q_SLOTS:
void slotCurrentChanged(int index);
void setAlwaysTabbedMode(bool);
void forceHideTabBar(bool force);
Q_SIGNALS:
void removeTabPopup();
......@@ -159,6 +160,7 @@ private:
NewTabToolButton *m_leftWidget;
bool m_permanentCloseButtons;
bool m_alwaysTabBar;
bool m_forceHideTabBar;
QMap<QString, QAction *> m_popupActions;
};
......
<?xml version="1.0"?>
<!DOCTYPE gui SYSTEM "kpartgui.dtd">
<gui name="Konqueror" version="70">
<gui name="Konqueror" version="71">
<MenuBar>
<Menu name="file" noMerge="1"><text>&amp;File</text>
<Action name="new_window"/>
......@@ -97,6 +97,7 @@
<Action name="reload"/>
<Action name="stop"/>
<Action name="go_home_popup"/>
<ActionList name="fullscreen"/>
<WeakSeparator/>
<Merge/>
</ToolBar>
......
......@@ -29,6 +29,7 @@
#include "konqtabs.h"
#include "konqhistorymanager.h"
#include "konqpixmapprovider.h"
#include "konqbrowserinterface.h"
#include <kio/job.h>
#include <kio/jobuidelegate.h>
......@@ -251,6 +252,7 @@ void KonqView::switchView(KonqViewFactory &viewFactory)
if (!part) {
return;
}
m_pPart = part;
// Set the statusbar in the BE asap to avoid a KMainWindow statusbar being created.
......@@ -386,6 +388,10 @@ void KonqView::connectPart()
KParts::BrowserExtension *ext = browserExtension();
if (ext) {
KonqBrowserInterface *bi = new KonqBrowserInterface(mainWindow(), m_pPart);
ext->setBrowserInterface(bi);
connect(ext, SIGNAL(openUrlRequestDelayed(QUrl,KParts::OpenUrlArguments,KParts::BrowserArguments)),
m_pMainWindow, SLOT(slotOpenURLRequest(QUrl,KParts::OpenUrlArguments,KParts::BrowserArguments)));
......@@ -1235,7 +1241,7 @@ bool KonqView::prepareReload(KParts::OpenUrlArguments &args, KParts::BrowserArgu
KParts::BrowserExtension *KonqView::browserExtension() const
{
return KParts::BrowserExtension::childObject(m_pPart);
return m_pPart ? KParts::BrowserExtension::childObject(m_pPart) : nullptr;
}
KParts::StatusBarExtension *KonqView::statusBarExtension() const
......
......@@ -1416,6 +1416,14 @@ bool KonqViewManager::isTabBarVisible() const
return !m_tabContainer->tabBar()->isHidden();
}
void KonqViewManager::forceHideTabBar(bool force)
{
if (m_tabContainer) {
m_tabContainer->forceHideTabBar(force);
}
}
void KonqViewManager::createTabContainer(QWidget *parent, KonqFrameContainerBase *parentContainer)
{
#ifdef DEBUG_VIEWMGR
......
......@@ -162,6 +162,13 @@ public:
* Returns true if the tabwidget exists and the tabbar is visible
*/
bool isTabBarVisible() const;
/**
* Forces hiding the tab bar, regardless of settings or number of tabs
*
* This is used to provide movie full screen
*/
void forceHideTabBar(bool force);
// Apply configuration that applies to us, like alwaysTabbedMode.
void applyConfiguration();
......
......@@ -720,6 +720,8 @@ void WebEngineSettings::init( KConfig * config, bool reset )
QWebEngineSettings::defaultSettings()->setAttribute(QWebEngineSettings::PdfViewerEnabled, internalPdfViewer());
#endif
QWebEngineSettings::defaultSettings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
// These numbers should be calculated from real "logical" DPI/72, using a default dpi of 96 for now
computeFontSizes(96);
}
......
......@@ -50,6 +50,7 @@
#include <KParts/HtmlExtension>
#include <KUserTimestamp>
#include <KPasswdServerClient>
#include <KParts/BrowserInterface>
#include <QStandardPaths>
#include <QDesktopWidget>
......@@ -64,6 +65,7 @@
#include <QWebEngineDownloadItem>
#include <QUrlQuery>
#include <KConfigGroup>
#include <KToggleFullScreenAction>
//#include <QWebSecurityOrigin>
#include "utils.h"
......@@ -91,6 +93,7 @@ WebEnginePage::WebEnginePage(WebEnginePart *part, QWidget *parent)
this, &WebEnginePage::slotLoadFinished);
connect(this, &QWebEnginePage::authenticationRequired,
this, &WebEnginePage::slotAuthenticationRequired);
connect(this, &QWebEnginePage::fullScreenRequested, this, &WebEnginePage::changeFullScreenMode);
if(!this->profile()->httpUserAgent().contains(QLatin1String("Konqueror")))
{
this->profile()->setHttpUserAgent(this->profile()->httpUserAgent() + " Konqueror (WebEnginePart)");
......@@ -729,6 +732,18 @@ void WebEnginePage::slotAuthenticationRequired(const QUrl &requestUrl, QAuthenti
}
}
void WebEnginePage::changeFullScreenMode(QWebEngineFullScreenRequest req)
{
KParts::BrowserInterface *iface = part()->browserExtension()->browserInterface();
if (iface) {
req.accept();
iface->callMethod("toggleCompleteFullScreen", req.toggleOn());
} else {
req.reject();
}
}
/************************************* Begin NewWindowPage ******************************************/
......
......@@ -32,6 +32,7 @@
#include <QMultiHash>
#include <QPointer>
#include <QScopedPointer>
#include <QWebEngineFullScreenRequest>
class QAuthenticator;
class QUrl;
......@@ -40,6 +41,7 @@ class WebEnginePart;
class QWebEngineDownloadItem;
class KPasswdServerClient;
class WebEngineWallet;
class QWebEngineFullScreenRequest;
class WebEnginePage : public QWebEnginePage
{
......@@ -136,6 +138,7 @@ protected Q_SLOTS:
virtual void slotGeometryChangeRequested(const QRect& rect);
void slotFeaturePermissionRequested(const QUrl& url, QWebEnginePage::Feature feature);
void slotAuthenticationRequired(const QUrl &requestUrl, QAuthenticator *auth);
void changeFullScreenMode(QWebEngineFullScreenRequest req);
private:
bool checkLinkSecurity(const QNetworkRequest& req, NavigationType type) const;
......
......@@ -69,6 +69,8 @@
#include <KSslInfoDialog>
#include <KProtocolManager>
#include <KProtocolInfo>
#include <KParts/PartActivateEvent>
#include <KParts/BrowserInterface>
#include <QUrl>
#include <QFile>
......@@ -432,7 +434,7 @@ bool WebEnginePart::openUrl(const QUrl &_u)
p->setSslInfo(sslInfo);
}
}
attemptInstallKIOSchemeHandler(u);
// Set URL in KParts before emitting started; konq plugins rely on that.
......@@ -526,7 +528,7 @@ void WebEnginePart::slotLoadFinished (bool ok)
m_hasCachedFormData = false;
if (WebEngineSettings::self()->isNonPasswordStorableSite(url().host())) {
addWalletStatusBarIcon();
}
}
else {
// Attempt to fill the web form...
WebEngineWallet *wallet = page() ? page()->wallet() : nullptr;
......@@ -993,3 +995,8 @@ void WebEnginePart::slotFillFormRequestCompleted (bool ok)
addWalletStatusBarIcon();
}
void WebEnginePart::exitFullScreen()
{
page()->triggerAction(QWebEnginePage::ExitFullScreen);
}
......@@ -103,6 +103,9 @@ public:
void setWallet(WebEngineWallet* wallet);
public Q_SLOTS:
void exitFullScreen();
protected:
/**
* Re-implemented for internal reasons. API remains unaffected.
......@@ -152,9 +155,9 @@ private:
WebEnginePage* page();
const WebEnginePage* page() const;
static void initWebEngineUrlSchemes();
void attemptInstallKIOSchemeHandler(const QUrl &url);
void initActions();
void updateActions();
void addWalletStatusBarIcon();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment