summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2020-10-21 12:23:57 +0100
committerCaolán McNamara <caolanm@redhat.com>2020-10-22 15:06:48 +0200
commit606c65c90cb3e8abdd74540195b7cb01ba88adc8 (patch)
tree0942df8d5d5357e50fb13c59966c49dd54c0379b /vcl
parenta87af93ff874a55b81e55b46b63798fde4cefc4f (diff)
for DisallowCycleFocusOut forward unused keyevents to InterimItemWindow
for ctrl+q etc Change-Id: Ie0ad94cf0e85693960428ffee5ae4a0ecffb7c6b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104635 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/unx/gtk/gtkframe.hxx2
-rw-r--r--vcl/unx/gtk3/gtk3gtkframe.cxx77
-rw-r--r--vcl/unx/gtk3/gtk3gtkinst.cxx43
3 files changed, 107 insertions, 15 deletions
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
index 27865f2efb12..820d796bf6e5 100644
--- a/vcl/inc/unx/gtk/gtkframe.hxx
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
@@ -530,6 +530,8 @@ public:
static OUString GetPreeditDetails(GtkIMContext* pIMContext, std::vector<ExtTextInputAttr>& rInputFlags, sal_Int32& rCursorPos, sal_uInt8& rCursorFlags);
void DisallowCycleFocusOut();
+ bool IsCycleFocusOutDisallowed() const;
+ void AllowCycleFocusOut();
};
#define OOO_TYPE_FIXED ooo_fixed_get_type()
diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx
index 26c34a09c9d4..eb964a790533 100644
--- a/vcl/unx/gtk3/gtk3gtkframe.cxx
+++ b/vcl/unx/gtk3/gtk3gtkframe.cxx
@@ -1026,6 +1026,26 @@ void GtkSalFrame::DisallowCycleFocusOut()
gtk_widget_set_can_focus(GTK_WIDGET(m_pFixedContainer), false);
}
+bool GtkSalFrame::IsCycleFocusOutDisallowed() const
+{
+ return m_nSetFocusSignalId == 0;
+}
+
+void GtkSalFrame::AllowCycleFocusOut()
+{
+ if (m_nSetFocusSignalId)
+ return;
+ // enable/disable can-focus as control enters and leaves
+ // embedded native gtk widgets
+ m_nSetFocusSignalId = g_signal_connect(G_OBJECT(m_pWindow), "set-focus", G_CALLBACK(signalSetFocus), this);
+
+ // set container without can-focus and focus will tab between
+ // the native embedded widgets using the default gtk handling for
+ // that
+ gtk_widget_set_can_focus(GTK_WIDGET(m_pFixedContainer), true);
+}
+
+
void GtkSalFrame::Init( SalFrame* pParent, SalFrameStyleFlags nStyle )
{
if( nStyle & SalFrameStyleFlags::DEFAULT ) // ensure default style
@@ -3198,6 +3218,8 @@ gboolean GtkSalFrame::signalKey(GtkWidget* pWidget, GdkEventKey* pEvent, gpointe
bool bFocusInAnotherGtkWidget = false;
+ VclPtr<vcl::Window> xTopLevelInterimWindow;
+
if (GTK_IS_WINDOW(pThis->m_pWindow))
{
GtkWidget* pFocusWindow = gtk_window_get_focus(GTK_WINDOW(pThis->m_pWindow));
@@ -3216,6 +3238,24 @@ gboolean GtkSalFrame::signalKey(GtkWidget* pWidget, GdkEventKey* pEvent, gpointe
g_type_class_unref(pClass);
if (bHandled)
return true;
+
+ // Is focus inside a full-app InterimItemWindow? In which case find
+ // that InterimItemWindow and send unconsumed keystrokes to it to
+ // support ctrl-q etc shortcuts
+ if (pThis->IsCycleFocusOutDisallowed())
+ {
+ GtkWidget* pSearch = pFocusWindow;
+ while (pSearch)
+ {
+ void* pData = g_object_get_data(G_OBJECT(pSearch), "InterimWindowGlue");
+ if (pData)
+ {
+ xTopLevelInterimWindow = static_cast<vcl::Window*>(pData);
+ break;
+ }
+ pSearch = gtk_widget_get_parent(pSearch);
+ }
+ }
}
}
@@ -3303,6 +3343,22 @@ gboolean GtkSalFrame::signalKey(GtkWidget* pWidget, GdkEventKey* pEvent, gpointe
}
else
{
+ VclPtr<vcl::Window> xOrigFocusWin;
+ if (xTopLevelInterimWindow)
+ {
+ // Focus is inside a full-app InterimItemWindow send unconsumed
+ // keystrokes to by setting it as the mpFocusWin
+ VclPtr<vcl::Window> xVclWindow = pThis->GetWindow();
+ ImplFrameData* pFrameData = xVclWindow->ImplGetWindowImpl()->mpFrameData;
+ xOrigFocusWin = pFrameData->mpFocusWin;
+ pFrameData->mpFocusWin = xTopLevelInterimWindow;
+ if (pEvent->keyval == GDK_KEY_F6)
+ {
+ // For F6, allow the focus to leave the InterimItemWindow
+ pThis->AllowCycleFocusOut();
+ }
+ }
+
bStopProcessingKey = pThis->doKeyCallback(pEvent->state,
pEvent->keyval,
pEvent->hardware_keycode,
@@ -3310,8 +3366,27 @@ gboolean GtkSalFrame::signalKey(GtkWidget* pWidget, GdkEventKey* pEvent, gpointe
sal_Unicode(gdk_keyval_to_unicode( pEvent->keyval )),
(pEvent->type == GDK_KEY_PRESS),
false);
- if( ! aDel.isDeleted() )
+ if (!aDel.isDeleted())
+ {
pThis->m_nKeyModifiers = ModKeyFlags::NONE;
+
+ if (xTopLevelInterimWindow)
+ {
+ // Focus was inside a full-app InterimItemWindow, restore the original
+ // focus win, unless the focus was changed away from the InterimItemWindow
+ // which should only be possible with F6
+ VclPtr<vcl::Window> xVclWindow = pThis->GetWindow();
+ ImplFrameData* pFrameData = xVclWindow->ImplGetWindowImpl()->mpFrameData;
+ if (pFrameData->mpFocusWin == xTopLevelInterimWindow)
+ pFrameData->mpFocusWin = xOrigFocusWin;
+ if (pEvent->keyval == GDK_KEY_F6)
+ {
+ // undo the above AllowCycleFocusOut for F6
+ pThis->DisallowCycleFocusOut();
+ }
+ }
+ }
+
}
if (!bFocusInAnotherGtkWidget && !aDel.isDeleted() && pThis->m_pIMHandler)
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 6448e3733256..13f97ceb7df9 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -16291,6 +16291,7 @@ private:
std::vector<GtkLabel*> m_aMnemonicLabels;
VclPtr<SystemChildWindow> m_xInterimGlue;
+ bool m_bAllowCycleFocusOut;
void postprocess_widget(GtkWidget* pWidget)
{
@@ -16458,12 +16459,14 @@ private:
pThis->postprocess_widget(GTK_WIDGET(pObject));
}
public:
- GtkInstanceBuilder(GtkWidget* pParent, const OUString& rUIRoot, const OUString& rUIFile, SystemChildWindow* pInterimGlue)
+ GtkInstanceBuilder(GtkWidget* pParent, const OUString& rUIRoot, const OUString& rUIFile,
+ SystemChildWindow* pInterimGlue, bool bAllowCycleFocusOut)
: weld::Builder()
, m_pStringReplace(Translate::GetReadStringHook())
, m_pParentWidget(pParent)
, m_nNotifySignalId(0)
, m_xInterimGlue(pInterimGlue)
+ , m_bAllowCycleFocusOut(bAllowCycleFocusOut)
{
OUString sHelpRoot(rUIFile);
ensure_intercept_drawing_area_accessibility();
@@ -16495,6 +16498,17 @@ public:
{
assert(m_pParentWidget);
g_object_set_data(G_OBJECT(m_pParentWidget), "InterimWindowGlue", m_xInterimGlue.get());
+
+ if (!m_bAllowCycleFocusOut)
+ {
+ GtkWidget* pTopLevel = gtk_widget_get_toplevel(m_pParentWidget);
+ assert(pTopLevel);
+ GtkSalFrame* pFrame = GtkSalFrame::getFromWindow(pTopLevel);
+ assert(pFrame);
+ // unhook handler and let gtk cycle its own way through this widget's
+ // children because it has no non-gtk siblings
+ pFrame->DisallowCycleFocusOut();
+ }
}
}
@@ -16555,6 +16569,18 @@ public:
{
g_slist_free(m_pObjectList);
g_object_unref(m_pBuilder);
+
+ if (m_xInterimGlue && !m_bAllowCycleFocusOut)
+ {
+ GtkWidget* pTopLevel = gtk_widget_get_toplevel(m_pParentWidget);
+ assert(pTopLevel);
+ GtkSalFrame* pFrame = GtkSalFrame::getFromWindow(pTopLevel);
+ assert(pFrame);
+ // rehook handler and let vcl cycle its own way through this widget's
+ // children
+ pFrame->AllowCycleFocusOut();
+ }
+
m_xInterimGlue.disposeAndClear();
}
@@ -17048,7 +17074,7 @@ weld::Builder* GtkInstance::CreateBuilder(weld::Widget* pParent, const OUString&
if (pParent && !pParentWidget) //remove when complete
return SalInstance::CreateBuilder(pParent, rUIRoot, rUIFile);
GtkWidget* pBuilderParent = pParentWidget ? pParentWidget->getWidget() : nullptr;
- return new GtkInstanceBuilder(pBuilderParent, rUIRoot, rUIFile, nullptr);
+ return new GtkInstanceBuilder(pBuilderParent, rUIRoot, rUIFile, nullptr, true);
}
// tdf#135965 for the case of native widgets inside a GtkSalFrame and F1 pressed, run help
@@ -17122,19 +17148,8 @@ weld::Builder* GtkInstance::CreateInterimBuilder(vcl::Window* pParent, const OUS
GtkWidget *pWindow = static_cast<GtkWidget*>(pEnvData->pWidget);
gtk_widget_show_all(pWindow);
- if (!bAllowCycleFocusOut)
- {
- GtkWidget* pTopLevel = gtk_widget_get_toplevel(pWindow);
- assert(pTopLevel);
- GtkSalFrame* pFrame = GtkSalFrame::getFromWindow(pTopLevel);
- assert(pFrame);
- // unhook handler and let gtk cycle its own way through this widget's
- // children because it has no non-gtk siblings
- pFrame->DisallowCycleFocusOut();
- }
-
// build the widget tree as a child of the GtkEventBox GtkGrid parent
- return new GtkInstanceBuilder(pWindow, rUIRoot, rUIFile, xEmbedWindow.get());
+ return new GtkInstanceBuilder(pWindow, rUIRoot, rUIFile, xEmbedWindow.get(), bAllowCycleFocusOut);
}
weld::MessageDialog* GtkInstance::CreateMessageDialog(weld::Widget* pParent, VclMessageType eMessageType, VclButtonsType eButtonsType, const OUString &rPrimaryMessage)