From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 ; 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 ; 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 ; 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 ; Wed, 26 May 2021 10:58:41 +0200 (CEST) From: Dominik Csapak 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 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-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 --- 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