From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <d.csapak@proxmox.com>
Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by lists.proxmox.com (Postfix) with ESMTPS id 842F372A4A
 for <pve-devel@lists.proxmox.com>; Wed, 26 May 2021 10:59:20 +0200 (CEST)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
 by firstgate.proxmox.com (Proxmox) with ESMTP id CFC3DE67D
 for <pve-devel@lists.proxmox.com>; Wed, 26 May 2021 10:58:49 +0200 (CEST)
Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com
 [94.136.29.106])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by firstgate.proxmox.com (Proxmox) with ESMTPS id 7C5ECE2E5
 for <pve-devel@lists.proxmox.com>; Wed, 26 May 2021 10:58:41 +0200 (CEST)
Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1])
 by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 5649645A88
 for <pve-devel@lists.proxmox.com>; Wed, 26 May 2021 10:58:41 +0200 (CEST)
From: Dominik Csapak <d.csapak@proxmox.com>
To: pve-devel@lists.proxmox.com
Date: Wed, 26 May 2021 10:58:35 +0200
Message-Id: <20210526085839.9808-8-d.csapak@proxmox.com>
X-Mailer: git-send-email 2.20.1
In-Reply-To: <20210526085839.9808-1-d.csapak@proxmox.com>
References: <20210526085839.9808-1-d.csapak@proxmox.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-SPAM-LEVEL: Spam detection results:  0
 AWL 0.037 Adjusted score from AWL reputation of From: address
 KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment
 SPF_HELO_NONE           0.001 SPF: HELO does not publish an SPF Record
 SPF_PASS               -0.001 SPF: sender matches SPF record
Subject: [pve-devel] [PATCH widget-toolkit 07/11] Toolkit: update focusJump
 override
X-BeenThere: pve-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox VE development discussion <pve-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pve-devel/>
List-Post: <mailto:pve-devel@lists.proxmox.com>
List-Help: <mailto:pve-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=subscribe>
X-List-Received-Date: Wed, 26 May 2021 08:59:20 -0000

upstream code changed a bit, update to current version

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/Toolkit.js | 121 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 84 insertions(+), 37 deletions(-)

diff --git a/src/Toolkit.js b/src/Toolkit.js
index 517f1a1..b85cd32 100644
--- a/src/Toolkit.js
+++ b/src/Toolkit.js
@@ -380,58 +380,105 @@ Ext.define(null, {
     jumpToFocus: false,
 
     saveFocusState: function() {
-	let me = this,
+	var me = this,
 	    store = me.dataSource,
 	    actionableMode = me.actionableMode,
 	    navModel = me.getNavigationModel(),
 	    focusPosition = actionableMode ? me.actionPosition : navModel.getPosition(true),
-	    refocusRow, refocusCol;
-
-	if (focusPosition) {
+	    activeElement = Ext.fly(Ext.Element.getActiveElement()),
+	    focusCell = focusPosition && focusPosition.view === me &&
+	    Ext.fly(focusPosition.getCell(true)),
+	    refocusRow, refocusCol, record;
+
+	// The navModel may return a position that is in a locked partner, so check that
+	// the focusPosition's cell contains the focus before going forward.
+	// The skipSaveFocusState is set by Actionables which actively control
+	// focus destination. See CellEditing#activateCell.
+	if (!me.skipSaveFocusState && focusCell && focusCell.contains(activeElement)) {
 	    // Separate this from the instance that the nav model is using.
 	    focusPosition = focusPosition.clone();
 
-	    // Exit actionable mode.
-	    // We must inform any Actionables that they must relinquish control.
-	    // Tabbability must be reset.
-	    if (actionableMode) {
-		me.ownerGrid.setActionableMode(false);
+	    // While we deactivate the focused element, suspend focus processing on it.
+	    activeElement.suspendFocusEvents();
+
+	    // Suspend actionable mode.
+	    // Each Actionable must silently save its state ready to resume when focus
+	    // can be restored but should only do that if the activeElement is not the cell itself,
+	    // this happens when the grid is refreshed while one of the actionables is being
+	    // deactivated (e.g. Calling  view refresh inside CellEditor 'edit' event listener).
+	    if (actionableMode && focusCell.dom !== activeElement.dom) {
+		me.suspendActionableMode();
+	    } else {
+		// Clear position, otherwise the setPosition on the other side
+		// will be rejected as a no-op if the resumption position is logically
+		// equivalent.
+		actionableMode = false;
+		navModel.setPosition();
 	    }
 
-	    // Blur the focused descendant, but do not trigger focusLeave.
-	    me.el.dom.focus();
+	    // Do not leave the element in tht state in case refresh fails, and restoration
+	    // closure not called.
+	    activeElement.resumeFocusEvents();
 
-	    // Exiting actionable mode navigates to the owning cell, so in either focus mode we must
-	    // clear the navigation position
-	    navModel.setPosition();
+	    // if the store is expanding or collapsing, we should never scroll the view.
+	    if (store.isExpandingOrCollapsing) {
+		return Ext.emptyFn;
+	    }
 
 	    // The following function will attempt to refocus back in the same mode to the same cell
-	    // as it was at before based upon the previous record (if it's still inthe store), or the row index.
+	    // as it was at before based upon the previous record (if it's still in the store),
+	    // or the row index.
 	    return function() {
+		var all;
+
+		// May have changed due to reconfigure
+		store = me.dataSource;
+
 		// If we still have data, attempt to refocus in the same mode.
 		if (store.getCount()) {
-		    // Adjust expectations of where we are able to refocus according to what kind of destruction
-		    // might have been wrought on this view's DOM during focus save.
-		    refocusRow = Math.min(focusPosition.rowIdx, me.all.getCount() - 1);
-		    refocusCol = Math.min(focusPosition.colIdx,
-					  me.getVisibleColumnManager().getColumns().length - 1);
-		    refocusRow = store.contains(focusPosition.record) ? focusPosition.record : refocusRow;
-		    focusPosition = new Ext.grid.CellContext(me).setPosition(refocusRow, refocusCol);
-
-		    if (actionableMode) {
-			me.ownerGrid.setActionableMode(true, focusPosition);
-		    } else {
-			me.cellFocused = true;
-
-			// we sometimes want to scroll back to where we were
-			let x = me.getScrollX();
-			let y = me.getScrollY();
-
-			// Pass "preventNavigation" as true so that that does not cause selection.
-			navModel.setPosition(focusPosition, null, null, null, true);
-
-			if (!me.jumpToFocus) {
-			    me.scrollTo(x, y);
+		    all = me.all;
+
+		    // Adjust expectations of where we are able to refocus according to
+		    // what kind of destruction might have been wrought on this view's DOM
+		    // during focus save.
+		    refocusRow =
+			Math.min(Math.max(focusPosition.rowIdx, all.startIndex), all.endIndex);
+
+		    refocusCol = Math.min(
+			focusPosition.colIdx,
+			me.getVisibleColumnManager().getColumns().length - 1,
+		    );
+
+		    record = focusPosition.record;
+
+		    focusPosition = new Ext.grid.CellContext(me).setPosition(
+			record && store.contains(record) && !record.isCollapsedPlaceholder
+			? record
+			: refocusRow,
+			refocusCol,
+		    );
+
+		    // Maybe there are no cells. eg: all groups collapsed.
+		    if (focusPosition.getCell(true)) {
+			if (actionableMode) {
+			    me.resumeActionableMode(focusPosition);
+			} else {
+			    // we sometimes want to scroll back to where we are
+
+			    let x = me.getScrollX();
+			    let y = me.getScrollY();
+
+			    // Pass "preventNavigation" as true
+			    // so that that does not cause selection.
+			    navModel.setPosition(focusPosition, null, null, null, true);
+
+			    if (!navModel.getPosition()) {
+				focusPosition.column.focus();
+			    }
+
+			    if (!me.jumpToFocus) {
+				me.scrollTo(x, y);
+			    }
 			}
 		    }
 		} else { // No rows - focus associated column header
-- 
2.20.1