Resolves: tdf#156751 add "Special Character..." to GtkEntry context menus
translation exists so doesn't require additional translation
Change-Id: Ibc5df15b9b8442307195d79c862c69e0506c4057
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155733
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
diff --git a/solenv/sanitizers/ui/vcl.suppr b/solenv/sanitizers/ui/vcl.suppr
index a07c257..52e3b4d 100644
--- a/solenv/sanitizers/ui/vcl.suppr
+++ b/solenv/sanitizers/ui/vcl.suppr
@@ -7,6 +7,7 @@ vcl/uiconfig/ui/combobox.ui://GtkEntry[@id='entry'] no-labelled-by
vcl/uiconfig/ui/combobox.ui://GtkToggleButton[@id='button'] button-no-label
vcl/uiconfig/ui/combobox.ui://GtkMenuButton[@id='overlaybutton'] button-no-label
vcl/uiconfig/ui/cupspassworddialog.ui://GtkLabel[@id='text'] orphan-label
vcl/uiconfig/ui/editmenu.ui://GtkMenuItem[@id='specialchar'] button-no-label
vcl/uiconfig/ui/menutogglebutton3.ui://GtkToggleButton[@id='togglebutton'] button-no-label
vcl/uiconfig/ui/menutogglebutton3.ui://GtkButton[@id='menubutton'] button-no-label
vcl/uiconfig/ui/menutogglebutton4.ui://GtkToggleButton[@id='togglebutton'] button-no-label
diff --git a/vcl/inc/strings.hrc b/vcl/inc/strings.hrc
index c2e95f2..7f5699a 100644
--- a/vcl/inc/strings.hrc
+++ b/vcl/inc/strings.hrc
@@ -125,6 +125,8 @@
#define STR_UNSAVED_DOCUMENTS NC_("STR_UNSAVED_DOCUMENTS", "There are unsaved documents")
#define STR_SPECIAL_CHARACTER_MENU_ENTRY NC_("editmenu|specialchar", "_Special Character...")
#endif // INCLUDED_VCL_INC_STRINGS_HRC
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/control/edit.cxx b/vcl/source/control/edit.cxx
index 0db27e8..92c0311 100644
--- a/vcl/source/control/edit.cxx
+++ b/vcl/source/control/edit.cxx
@@ -1978,6 +1978,8 @@ void Edit::Command( const CommandEvent& rCEvt )
pPopup->EnableItem(pPopup->GetItemId(u"copy"), bEnableCopy);
pPopup->EnableItem(pPopup->GetItemId(u"delete"), bEnableDelete);
pPopup->EnableItem(pPopup->GetItemId(u"paste"), bEnablePaste);
pPopup->SetItemText(pPopup->GetItemId(u"specialchar"),
BuilderUtils::convertMnemonicMarkup(VclResId(STR_SPECIAL_CHARACTER_MENU_ENTRY)));
pPopup->EnableItem(pPopup->GetItemId(u"specialchar"), bEnableSpecialChar);
pPopup->EnableItem(
pPopup->GetItemId(u"undo"),
diff --git a/vcl/source/edit/vclmedit.cxx b/vcl/source/edit/vclmedit.cxx
index 541d6bf..d519735 100644
--- a/vcl/source/edit/vclmedit.cxx
+++ b/vcl/source/edit/vclmedit.cxx
@@ -41,6 +41,8 @@
#include <vcl/weld.hxx>
#include <osl/diagnose.h>
#include <tools/json_writer.hxx>
#include <strings.hrc>
#include <svdata.hxx>
class ImpVclMEdit : public SfxListener
{
@@ -789,6 +791,8 @@ void TextWindow::Command( const CommandEvent& rCEvt )
pPopup->EnableItem(pPopup->GetItemId(u"copy"), bEnableCopy);
pPopup->EnableItem(pPopup->GetItemId(u"delete"), bEnableDelete);
pPopup->EnableItem(pPopup->GetItemId(u"paste"), bEnablePaste);
pPopup->SetItemText(pPopup->GetItemId(u"specialchar"),
BuilderUtils::convertMnemonicMarkup(VclResId(STR_SPECIAL_CHARACTER_MENU_ENTRY)));
pPopup->EnableItem(pPopup->GetItemId(u"specialchar"), bEnableSpecialChar);
pPopup->EnableItem(pPopup->GetItemId(u"undo"), bEnableUndo);
pPopup->ShowItem(pPopup->GetItemId(u"specialchar"), !vcl::GetGetSpecialCharsFunction());
diff --git a/vcl/uiconfig/ui/editmenu.ui b/vcl/uiconfig/ui/editmenu.ui
index 8c025d4..e0d55fb 100644
--- a/vcl/uiconfig/ui/editmenu.ui
+++ b/vcl/uiconfig/ui/editmenu.ui
@@ -69,7 +69,6 @@
<object class="GtkMenuItem" id="specialchar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes" context="editmenu|specialchar">_Special Character...</property>
<property name="use_underline">True</property>
</object>
</child>
diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx
index 2cfd0d6..141039d 100644
--- a/vcl/unx/gtk3/gtkinst.cxx
+++ b/vcl/unx/gtk3/gtkinst.cxx
@@ -19024,41 +19024,67 @@ void GtkInstanceDrawingArea::im_context_set_cursor_location(const tools::Rectang
}
#if !GTK_CHECK_VERSION(4, 0, 0)
static void InsertSpecialChar(GtkEntry *pEntry)
{
if (auto pImplFncGetSpecialChars = vcl::GetGetSpecialCharsFunction())
{
weld::Window* pDialogParent = nullptr;
GtkWidget* pTopLevel = widget_get_toplevel(GTK_WIDGET(pEntry));
if (GtkSalFrame* pFrame = pTopLevel ? GtkSalFrame::getFromWindow(pTopLevel) : nullptr)
pDialogParent = pFrame->GetFrameWeld();
std::unique_ptr<GtkInstanceWindow> xFrameWeld;
if (!pDialogParent && pTopLevel)
{
xFrameWeld.reset(new GtkInstanceWindow(GTK_WINDOW(pTopLevel), nullptr, false));
pDialogParent = xFrameWeld.get();
}
OUString aChars = pImplFncGetSpecialChars(pDialogParent, ::get_font(GTK_WIDGET(pEntry)));
if (!aChars.isEmpty())
{
gtk_editable_delete_selection(GTK_EDITABLE(pEntry));
gint position = gtk_editable_get_position(GTK_EDITABLE(pEntry));
OString sText(OUStringToOString(aChars, RTL_TEXTENCODING_UTF8));
gtk_editable_insert_text(GTK_EDITABLE(pEntry), sText.getStr(), sText.getLength(),
&position);
gtk_editable_set_position(GTK_EDITABLE(pEntry), position);
}
}
}
static gboolean signalEntryInsertSpecialCharKeyPress(GtkEntry* pEntry, GdkEventKey* pEvent, gpointer)
{
if ((pEvent->keyval == GDK_KEY_S || pEvent->keyval == GDK_KEY_s) &&
(pEvent->state & GDK_MODIFIER_MASK) == static_cast<GdkModifierType>(GDK_SHIFT_MASK|GDK_CONTROL_MASK))
{
if (auto pImplFncGetSpecialChars = vcl::GetGetSpecialCharsFunction())
{
weld::Window* pDialogParent = nullptr;
GtkWidget* pTopLevel = widget_get_toplevel(GTK_WIDGET(pEntry));
if (GtkSalFrame* pFrame = pTopLevel ? GtkSalFrame::getFromWindow(pTopLevel) : nullptr)
pDialogParent = pFrame->GetFrameWeld();
std::unique_ptr<GtkInstanceWindow> xFrameWeld;
if (!pDialogParent && pTopLevel)
{
xFrameWeld.reset(new GtkInstanceWindow(GTK_WINDOW(pTopLevel), nullptr, false));
pDialogParent = xFrameWeld.get();
}
OUString aChars = pImplFncGetSpecialChars(pDialogParent, ::get_font(GTK_WIDGET(pEntry)));
if (!aChars.isEmpty())
{
gtk_editable_delete_selection(GTK_EDITABLE(pEntry));
gint position = gtk_editable_get_position(GTK_EDITABLE(pEntry));
OString sText(OUStringToOString(aChars, RTL_TEXTENCODING_UTF8));
gtk_editable_insert_text(GTK_EDITABLE(pEntry), sText.getStr(), sText.getLength(),
&position);
gtk_editable_set_position(GTK_EDITABLE(pEntry), position);
}
}
InsertSpecialChar(pEntry);
return true;
}
return false;
}
static void signalActivateEntryInsertSpecialChar(GtkEntry *pEntry)
{
InsertSpecialChar(pEntry);
}
static void signalEntryPopulatePopup(GtkEntry* pEntry, GtkWidget* pMenu, gpointer)
{
if (!GTK_IS_MENU(pMenu))
return;
if (!vcl::GetGetSpecialCharsFunction())
return;
GtkWidget *item = gtk_menu_item_new_with_mnemonic(MapToGtkAccelerator(VclResId(STR_SPECIAL_CHARACTER_MENU_ENTRY)).getStr());
gtk_widget_show(item);
g_signal_connect_swapped(item, "activate", G_CALLBACK(signalActivateEntryInsertSpecialChar), pEntry);
gtk_menu_shell_append(GTK_MENU_SHELL(pMenu), item);
}
#endif
namespace {
@@ -20970,6 +20996,7 @@ private:
gulong m_nEntryFocusInSignalId;
gulong m_nEntryFocusOutSignalId;
gulong m_nEntryKeyPressEventSignalId;
gulong m_nEntryPopulatePopupMenuSignalId;
guint m_nAutoCompleteIdleId;
gint m_nNonCustomLineHeight;
gint m_nPrePopupCursorPos;
@@ -22071,6 +22098,7 @@ public:
m_nEntryFocusInSignalId = g_signal_connect(m_pEntry, "focus-in-event", G_CALLBACK(signalEntryFocusIn), this);
m_nEntryFocusOutSignalId = g_signal_connect(m_pEntry, "focus-out-event", G_CALLBACK(signalEntryFocusOut), this);
m_nEntryKeyPressEventSignalId = g_signal_connect(m_pEntry, "key-press-event", G_CALLBACK(signalEntryKeyPress), this);
m_nEntryPopulatePopupMenuSignalId = g_signal_connect(m_pEntry, "populate-popup", G_CALLBACK(signalEntryPopulatePopup), nullptr);
m_nKeyPressEventSignalId = 0;
}
else
@@ -22116,6 +22144,7 @@ public:
m_nEntryFocusInSignalId = 0;
m_nEntryFocusOutSignalId = 0;
m_nEntryKeyPressEventSignalId = 0;
m_nEntryPopulatePopupMenuSignalId = 0;
m_nKeyPressEventSignalId = g_signal_connect(m_pToggleButton, "key-press-event", G_CALLBACK(signalKeyPress), this);
}
@@ -22711,6 +22740,7 @@ public:
g_signal_handler_disconnect(m_pEntry, m_nEntryFocusInSignalId);
g_signal_handler_disconnect(m_pEntry, m_nEntryFocusOutSignalId);
g_signal_handler_disconnect(m_pEntry, m_nEntryKeyPressEventSignalId);
g_signal_handler_disconnect(m_pEntry, m_nEntryPopulatePopupMenuSignalId);
}
else
g_signal_handler_disconnect(m_pToggleButton, m_nKeyPressEventSignalId);
@@ -23835,6 +23865,7 @@ private:
else if (GTK_IS_ENTRY(pWidget))
{
g_signal_connect(pWidget, "key-press-event", G_CALLBACK(signalEntryInsertSpecialCharKeyPress), nullptr);
g_signal_connect(pWidget, "populate-popup", G_CALLBACK(signalEntryPopulatePopup), nullptr);
}
#endif
else if (GTK_IS_WINDOW(pWidget))