diff --git a/src/Application.cpp b/src/Application.cpp --- a/src/Application.cpp +++ b/src/Application.cpp @@ -175,18 +175,21 @@ void Application::createWindow(Profile::Ptr profile, const QString &directory) { MainWindow *window = newMainWindow(); - window->createSession(profile, directory); + ViewManager *viewManager = window->viewManager(); + window->createSession(viewManager->activeContainer(), profile, directory); finalizeNewMainWindow(window); } void Application::detachView(Session *session) { MainWindow *window = newMainWindow(); - window->viewManager()->createView(session); + ViewManager *manager = window->viewManager(); + + manager->createView(manager->activeContainer(), session); // When detaching a view, the size of the new window should equal the // size of the source window - Session *newsession = window->viewManager()->activeViewController()->session(); + Session *newsession = manager->activeViewController()->session(); newsession->setSize(session->size()); window->adjustSize(); // Since user is dragging and dropping, move dnd window to where @@ -227,7 +230,8 @@ Profile::Ptr newProfile = processProfileChangeArgs(baseProfile); // create new session - Session *session = window->createSession(newProfile, QString()); + ViewManager *viewManager = window->viewManager(); + Session *session = window->createSession(viewManager->activeContainer(), newProfile, QString()); if (m_parser->isSet(QStringLiteral("noclose"))) { session->setAutoClose(false); @@ -374,7 +378,8 @@ // Create the new session Profile::Ptr theProfile = shouldUseNewProfile ? newProfile : baseProfile; - Session *session = window->createSession(theProfile, QString()); + ViewManager *viewManager = window->viewManager(); + Session *session = window->createSession(viewManager->activeContainer(), theProfile, QString()); if (m_parser->isSet(QStringLiteral("noclose"))) { session->setAutoClose(false); diff --git a/src/MainWindow.h b/src/MainWindow.h --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -42,6 +42,7 @@ class SessionController; class ProfileList; class BookmarkHandler; +class TabbedViewContainer; /** * The main window. This contains the menus and an area which contains the terminal displays. @@ -73,19 +74,21 @@ /** * Create a new session. * + * @param tabWidget where the new widget should be added. * @param profile The profile to use to create the new session. * @param directory Initial working directory for the new session or empty * if the default working directory associated with the profile should be used. */ - Session *createSession(Profile::Ptr profile, const QString &directory); + Session *createSession(TabbedViewContainer *tabWidget, Profile::Ptr profile, const QString &directory); /** * create a new SSH session. * + * @param tabWidget where the new widget should be added. * @param profile The profile to use to create the new session. * @param url the URL representing the new SSH connection */ - Session *createSSHSession(Profile::Ptr profile, const QUrl &url); + Session *createSSHSession(TabbedViewContainer *tabWidget, Profile::Ptr profile, const QUrl &url); /** * Helper method to make this window get input focus @@ -132,14 +135,14 @@ bool focusNextPrevChild(bool next) Q_DECL_OVERRIDE; private Q_SLOTS: - void newTab(); + void newTab(TabbedViewContainer *tabWidget); void cloneTab(); void newWindow(); void showManageProfilesDialog(); void activateMenuBar(); void showSettingsDialog(const bool showProfilePage = false); void showShortcutsDialog(); - void newFromProfile(Profile::Ptr profile); + void newFromProfile(TabbedViewContainer *tabWidget, Profile::Ptr profile); void activeViewChanged(SessionController *controller); void disconnectController(SessionController *controller); void activeViewTitleChanged(ViewProperties *); diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -50,6 +50,7 @@ #include "SessionController.h" #include "ProfileList.h" #include "Session.h" +#include "ViewContainer.h" #include "ViewManager.h" #include "SessionManager.h" #include "ProfileManager.h" @@ -109,13 +110,10 @@ connect(_viewManager, &Konsole::ViewManager::updateWindowIcon, this, &Konsole::MainWindow::updateWindowIcon); - connect(_viewManager, - static_cast(&Konsole::ViewManager::newViewRequest), - this, - &Konsole::MainWindow::newFromProfile); - connect(_viewManager, - static_cast(&Konsole::ViewManager::newViewRequest), this, - &Konsole::MainWindow::newTab); + connect(_viewManager, &Konsole::ViewManager::newViewWithProfileRequest, + this, &Konsole::MainWindow::newFromProfile); + connect(_viewManager, &Konsole::ViewManager::newViewRequest, + this, &Konsole::MainWindow::newTab); connect(_viewManager, &Konsole::ViewManager::viewDetached, this, &Konsole::MainWindow::viewDetached); @@ -316,7 +314,8 @@ collection->setDefaultShortcut(_newTabMenuAction, Konsole::ACCEL + Qt::SHIFT + Qt::Key_T); collection->setShortcutsConfigurable(_newTabMenuAction, true); _newTabMenuAction->setAutoRepeat(false); - connect(_newTabMenuAction, &KActionMenu::triggered, this, &Konsole::MainWindow::newTab); + connect(_newTabMenuAction, &KActionMenu::triggered, + this, [this] { newTab(_viewManager->activeContainer());}); collection->addAction(QStringLiteral("new-tab"), _newTabMenuAction); collection->setShortcutsConfigurable(_newTabMenuAction, true); @@ -390,7 +389,7 @@ profileListChanged(list->actions()); connect(list, &Konsole::ProfileList::profileSelected, this, - &Konsole::MainWindow::newFromProfile); + [this](Profile::Ptr profile) { newFromProfile(_viewManager->activeContainer(), profile);}); connect(list, &Konsole::ProfileList::actionsChanged, this, &Konsole::MainWindow::profileListChanged); @@ -459,17 +458,17 @@ Q_FOREACH (const auto &url, urls) { if (url.isLocalFile()) { - createSession(defaultProfile, url.path()); + createSession(_viewManager->activeContainer(), defaultProfile, url.path()); } else if (url.scheme() == QLatin1String("ssh")) { - createSSHSession(defaultProfile, url); + createSSHSession(_viewManager->activeContainer(), defaultProfile, url); } } } -void MainWindow::newTab() +void MainWindow::newTab(TabbedViewContainer *tabWidget) { Profile::Ptr defaultProfile = ProfileManager::instance()->defaultProfile(); - createSession(defaultProfile, activeSessionDir()); + createSession(tabWidget, defaultProfile, activeSessionDir()); } void MainWindow::cloneTab() @@ -479,15 +478,15 @@ Session *session = _pluggedController->session(); Profile::Ptr profile = SessionManager::instance()->sessionProfile(session); if (profile) { - createSession(profile, activeSessionDir()); + createSession(_viewManager->activeContainer(), profile, activeSessionDir()); } else { // something must be wrong: every session should be associated with profile Q_ASSERT(false); - newTab(); + newTab(_viewManager->activeContainer()); } } -Session *MainWindow::createSession(Profile::Ptr profile, const QString &directory) +Session *MainWindow::createSession(TabbedViewContainer *tabWidget, Profile::Ptr profile, const QString &directory) { if (!profile) { profile = ProfileManager::instance()->defaultProfile(); @@ -505,12 +504,12 @@ // doesn't suffer a change in terminal size right after the session // starts. Some applications such as GNU Screen and Midnight Commander // don't like this happening - _viewManager->createView(session); + _viewManager->createView(tabWidget, session); return session; } -Session *MainWindow::createSSHSession(Profile::Ptr profile, const QUrl &url) +Session *MainWindow::createSSHSession(TabbedViewContainer *tabWidget, Profile::Ptr profile, const QUrl &url) { if (!profile) { profile = ProfileManager::instance()->defaultProfile(); @@ -535,7 +534,7 @@ // doesn't suffer a change in terminal size right after the session // starts. some applications such as GNU Screen and Midnight Commander // don't like this happening - _viewManager->createView(session); + _viewManager->createView(tabWidget, session); return session; } @@ -709,9 +708,9 @@ } } -void MainWindow::newFromProfile(Profile::Ptr profile) +void MainWindow::newFromProfile(TabbedViewContainer *tabWidget, Profile::Ptr profile) { - createSession(profile, activeSessionDir()); + createSession(tabWidget, profile, activeSessionDir()); } void MainWindow::showManageProfilesDialog() diff --git a/src/Part.cpp b/src/Part.cpp --- a/src/Part.cpp +++ b/src/Part.cpp @@ -42,6 +42,7 @@ #include "ProfileManager.h" #include "TerminalDisplay.h" #include "ViewManager.h" +#include "ViewContainer.h" #include "KonsoleSettings.h" #include "settings/PartInfo.h" #include "settings/ProfileSettings.h" @@ -64,9 +65,7 @@ connect(_viewManager, &Konsole::ViewManager::activeViewChanged, this, &Konsole::Part::activeViewChanged); connect(_viewManager, &Konsole::ViewManager::empty, this, &Konsole::Part::terminalExited); - connect(_viewManager, - static_cast(&Konsole::ViewManager::newViewRequest), this, - &Konsole::Part::newTab); + connect(_viewManager, &Konsole::ViewManager::newViewRequest, this, &Konsole::Part::newTab); _viewManager->widget()->setParent(parentWidget); @@ -214,7 +213,7 @@ session->setInitialWorkingDirectory(directory); } - _viewManager->createView(session); + _viewManager->createView(_viewManager->activeContainer(), session); } void Part::activeViewChanged(SessionController *controller) diff --git a/src/TerminalDisplay.cpp b/src/TerminalDisplay.cpp --- a/src/TerminalDisplay.cpp +++ b/src/TerminalDisplay.cpp @@ -3687,6 +3687,12 @@ break; case QEvent::FocusOut: case QEvent::FocusIn: + if(_screenWindow) { + // force a redraw on focusIn, fixes the + // black screen bug when the view is focused + // but doesn't redraws. + _screenWindow->notifyOutputChanged(); + } update(); break; default: diff --git a/src/ViewContainer.h b/src/ViewContainer.h --- a/src/ViewContainer.h +++ b/src/ViewContainer.h @@ -57,7 +57,7 @@ * to actually add or remove view widgets from the container widget, as well * as updating any navigation aids. */ -class TabbedViewContainer : public QTabWidget +class KONSOLEPRIVATE_EXPORT TabbedViewContainer : public QTabWidget { Q_OBJECT @@ -145,10 +145,10 @@ void empty(TabbedViewContainer *container); /** Emitted when the user requests to open a new view */ - void newViewRequest(); + void newViewRequest(TabbedViewContainer *thisContainer); /** Requests creation of a new view, with the selected profile. */ - void newViewRequest(Profile::Ptr); + void newViewWithProfileRequest(TabbedViewContainer *thisContainer, Profile::Ptr); /** * Emitted when the user requests to move a view from another container @@ -159,9 +159,8 @@ * to append it. This index should be passed to addView() when the new view * has been created. * @param id The identifier of the view. - * @param sourceContainer Initial move event Tabbed view container. */ - void moveViewRequest(int index, int id, TabbedViewContainer *sourceContainer); + void moveViewRequest(int index, int sessionControllerId); /** Emitted when the active view changes */ void activeViewChanged(QWidget *view); diff --git a/src/ViewContainer.cpp b/src/ViewContainer.cpp --- a/src/ViewContainer.cpp +++ b/src/ViewContainer.cpp @@ -72,7 +72,7 @@ _newTabButton->setIcon(QIcon::fromTheme(QStringLiteral("document-new"))); _newTabButton->setAutoRaise(true); connect(_newTabButton, &QToolButton::clicked, this, [this]{ - emit newViewRequest(); + emit newViewRequest(this); }); _closeTabButton->setIcon(QIcon::fromTheme(QStringLiteral("tab-close"))); @@ -88,15 +88,7 @@ connect(tabBarWidget, &DetachableTabBar::detachTab, this, [this](int idx) { emit detachTab(this, widget(idx)); }); - connect(this, &TabbedViewContainer::currentChanged, this, [this](int index) { - if (index != -1) { - QWidget *view = widget(index); - view->setFocus(); - updateTabHistory(view); - } else { - deleteLater(); - } - }); + connect(this, &TabbedViewContainer::currentChanged, this, &TabbedViewContainer::currentTabChanged); // The context menu of tab bar _contextPopupMenu = new QMenu(tabBar()); @@ -137,7 +129,7 @@ auto profileList = new ProfileList(false, profileMenu); profileList->syncWidgetActions(profileMenu, true); connect(profileList, &Konsole::ProfileList::profileSelected, this, - static_cast(&Konsole::TabbedViewContainer::newViewRequest)); + [this](Profile::Ptr profile) { newViewWithProfileRequest(this, profile); }); _newTabButton->setMenu(profileMenu); konsoleConfigChanged(); @@ -161,7 +153,7 @@ const auto currentPos = QCursor::pos(); for(const auto dropWidget : widgets) { if (dropWidget->rect().contains(dropWidget->mapFromGlobal(currentPos))) { - emit dropWidget->moveViewRequest(-1, id, this); + emit dropWidget->moveViewRequest(-1, id); removeView(widget(index)); } } @@ -387,7 +379,7 @@ if (index >= 0) { renameTab(index); } else { - emit newViewRequest(); + emit newViewRequest(this); } } @@ -445,13 +437,15 @@ void TabbedViewContainer::currentTabChanged(int index) { - setCurrentIndex(index); - if (widget(index) != nullptr) { - emit activeViewChanged(widget(index)); + if (index != -1) { + QWidget *view = widget(index); + view->setFocus(); + updateTabHistory(view); + emit activeViewChanged(view); + setTabActivity(index, false); + } else { + deleteLater(); } - - // clear activity indicators - setTabActivity(index, false); } void TabbedViewContainer::wheelScrolled(int delta) diff --git a/src/ViewManager.h b/src/ViewManager.h --- a/src/ViewManager.h +++ b/src/ViewManager.h @@ -39,6 +39,7 @@ class SessionController; class ViewProperties; class ViewSplitter; +class TabbedViewContainer; /** * Manages the terminal display widgets in a Konsole window or part. @@ -77,7 +78,7 @@ * Creates a new view to display the output from and deliver input to @p session. * Constructs a new container to hold the views if no container has yet been created. */ - void createView(Session *session); + void createView(TabbedViewContainer *tabWidget, Session *session); /** * Applies the view-specific settings associated with specified @p profile @@ -193,6 +194,10 @@ */ static bool profileHasBlurEnabled(const Profile::Ptr profile); + /** returns the active tab from the view + */ + TabbedViewContainer *activeContainer(); + Q_SIGNALS: /** Emitted when the last view is removed from the view manager */ void empty(); @@ -239,9 +244,9 @@ void blurSettingChanged(bool); /** Requests creation of a new view with the default profile. */ - void newViewRequest(); + void newViewRequest(TabbedViewContainer *tabWidget); /** Requests creation of a new view, with the selected profile. */ - void newViewRequest(Profile::Ptr); + void newViewWithProfileRequest(TabbedViewContainer *tabWidget, Profile::Ptr); public Q_SLOTS: /** DBus slot that returns the number of sessions in the current view. */ @@ -375,8 +380,7 @@ // called when a ViewContainer requests a view be // moved - void containerMoveViewRequest(int index, int id, - TabbedViewContainer *sourceTabbedContainer); + void containerMoveViewRequest(int index, int sessionControllerId); void detachView(TabbedViewContainer *container, QWidget *view); diff --git a/src/ViewManager.cpp b/src/ViewManager.cpp --- a/src/ViewManager.cpp +++ b/src/ViewManager.cpp @@ -95,6 +95,8 @@ _managerId = ++lastManagerId; QDBusConnection::sessionBus().registerObject(QLatin1String("/Windows/") + QString::number(_managerId), this); + + _viewSplitter->addContainer(createContainer(), Qt::Vertical); } ViewManager::~ViewManager() = default; @@ -465,20 +467,17 @@ { TabbedViewContainer *container = createContainer(); - // iterate over each session which has a view in the current active - // container and create a new view for that session in a new container - for(int i = 0, end = _viewSplitter->activeContainer()->count(); i < end; i++) { - auto view = _viewSplitter->activeContainer()->widget(i); - Session *session = _sessionMap[qobject_cast(view)]; - TerminalDisplay *display = createTerminalDisplay(session); - const Profile::Ptr profile = SessionManager::instance()->sessionProfile(session); - applyProfileToView(display, profile); - ViewProperties *properties = createController(session, display); + if (_viewSplitter->activeContainer()->count()) { + // get the currently applied profile and use it to create the new tab. + auto *activeContainer= _viewSplitter->activeContainer(); + auto *currentDisplay = qobject_cast(activeContainer->currentWidget()); + auto profile = SessionManager::instance()->sessionProfile(_sessionMap[currentDisplay]); - _sessionMap[display] = session; + // Create a new session with the selected profile. + auto *session = SessionManager::instance()->createSession(profile); + session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); - container->addView(display, properties); - session->addView(display); + createView(session, container, 0); } _viewSplitter->addContainer(container, orientation); @@ -622,28 +621,12 @@ updateDetachViewState(); } -void ViewManager::createView(Session *session) +void ViewManager::createView(TabbedViewContainer *tabWidget, Session *session) { - // create the default container - if (_viewSplitter->containers().count() == 0) { - TabbedViewContainer *container = createContainer(); - _viewSplitter->addContainer(container, Qt::Vertical); - emit splitViewToggle(false); - } - - // new tab will be put at the end by default. - int index = -1; + const int index = _newTabBehavior == PutNewTabAfterCurrentTab ? + _viewSplitter->activeContainer()->currentIndex() + 1 : -1; - if (_newTabBehavior == PutNewTabAfterCurrentTab) { - index = _viewSplitter->activeContainer()->currentIndex() + 1; - } - - // iterate over the view containers owned by this view manager - // and create a new terminal display for the session in each of them, along with - // a controller for the session/display pair - foreach (TabbedViewContainer *container, _viewSplitter->containers()) { - createView(session, container, index); - } + createView(session, tabWidget, index); } TabbedViewContainer *ViewManager::createContainer() @@ -665,13 +648,10 @@ containerViewsChanged(container); }); - connect(container, - static_cast(&Konsole::TabbedViewContainer::newViewRequest), this, - static_cast(&Konsole::ViewManager::newViewRequest)); - connect(container, - static_cast(&Konsole::TabbedViewContainer::newViewRequest), - this, - static_cast(&Konsole::ViewManager::newViewRequest)); + connect(container, &TabbedViewContainer::newViewRequest, + this, &ViewManager::newViewRequest); + connect(container, &Konsole::TabbedViewContainer::newViewWithProfileRequest, + this, &Konsole::ViewManager::newViewWithProfileRequest); connect(container, &Konsole::TabbedViewContainer::moveViewRequest, this, &Konsole::ViewManager::containerMoveViewRequest); connect(container, &Konsole::TabbedViewContainer::viewRemoved, this, @@ -682,34 +662,16 @@ return container; } -void ViewManager::containerMoveViewRequest(int index, int id, - TabbedViewContainer *sourceTabbedContainer) +void ViewManager::containerMoveViewRequest(int index, int id) { auto *container = qobject_cast(sender()); auto *controller = qobject_cast(ViewProperties::propertiesById(id)); - - if (controller == nullptr) { - return; - } - - // do not move the last tab in a split view. - if (sourceTabbedContainer != nullptr) { - QPointer sourceContainer = qobject_cast(sourceTabbedContainer); - - if (_viewSplitter->containers().contains(sourceContainer)) { - return; - } else { - ViewManager *sourceViewManager = sourceTabbedContainer->connectedViewManager(); - - // do not remove the last tab on the window - if (qobject_cast(sourceViewManager->widget())->containers().size() > 1) { - return; - } - } - } + Q_ASSERT(container); + Q_ASSERT(controller); createView(controller->session(), container, index); controller->session()->refresh(); + container->currentWidget()->setFocus(); } void ViewManager::setNavigationMethod(NavigationMethod method) @@ -974,6 +936,11 @@ group.writeEntry("Sessions", ids); } +TabbedViewContainer *ViewManager::activeContainer() +{ + return _viewSplitter->activeContainer(); +} + void ViewManager::restoreSessions(const KConfigGroup &group) { QList ids = group.readEntry("Sessions", QList()); @@ -991,7 +958,7 @@ break; } - createView(session); + createView(activeContainer(), session); if (!session->isRunning()) { session->run(); } @@ -1008,7 +975,7 @@ if (ids.isEmpty()) { // Session file is unusable, start default Profile Profile::Ptr profile = ProfileManager::instance()->defaultProfile(); Session *session = SessionManager::instance()->createSession(profile); - createView(session); + createView(activeContainer(), session); if (!session->isRunning()) { session->run(); } @@ -1063,7 +1030,7 @@ session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); - createView(session); + createView(activeContainer(), session); session->run(); return session->sessionId(); @@ -1085,7 +1052,7 @@ session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); - createView(session); + createView(activeContainer(), session); session->run(); return session->sessionId(); @@ -1108,7 +1075,7 @@ session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); - createView(session); + createView(activeContainer(), session); session->run(); return session->sessionId();