summaryrefslogtreecommitdiff
path: root/vcl/unx/gtk3/gtkframe.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/unx/gtk3/gtkframe.cxx')
-rw-r--r--vcl/unx/gtk3/gtkframe.cxx180
1 files changed, 154 insertions, 26 deletions
diff --git a/vcl/unx/gtk3/gtkframe.cxx b/vcl/unx/gtk3/gtkframe.cxx
index 66fa98d08cb5..7108f9206380 100644
--- a/vcl/unx/gtk3/gtkframe.cxx
+++ b/vcl/unx/gtk3/gtkframe.cxx
@@ -76,6 +76,12 @@ int GtkSalFrame::m_nFloats = 0;
static GDBusConnection* pSessionBus = nullptr;
+static void EnsureSessionBus()
+{
+ if (!pSessionBus)
+ pSessionBus = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr);
+}
+
sal_uInt16 GtkSalFrame::GetKeyModCode( guint state )
{
sal_uInt16 nCode = 0;
@@ -541,8 +547,7 @@ static void attach_menu_model(GtkSalFrame* pSalFrame)
#if !GTK_CHECK_VERSION(4,0,0)
// Get a DBus session connection.
- if (!pSessionBus)
- pSessionBus = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, nullptr);
+ EnsureSessionBus();
if (!pSessionBus)
return;
@@ -629,13 +634,9 @@ void GtkSalFrame::EnsureAppMenuWatch()
return;
// Get a DBus session connection.
- if ( pSessionBus == nullptr )
- {
- pSessionBus = g_bus_get_sync( G_BUS_TYPE_SESSION, nullptr, nullptr );
-
- if ( pSessionBus == nullptr )
- return;
- }
+ EnsureSessionBus();
+ if (!pSessionBus)
+ return;
// Publish the menu only if AppMenu registrar is available.
m_nWatcherId = g_bus_watch_name_on_connection( pSessionBus,
@@ -698,8 +699,14 @@ GtkSalFrame::~GtkSalFrame()
{
SolarMutexGuard aGuard;
- if(m_nWatcherId)
+ if (m_nWatcherId)
g_bus_unwatch_name(m_nWatcherId);
+
+ if (m_nPortalSettingChangedSignalId)
+ g_signal_handler_disconnect(m_pSettingsPortal, m_nPortalSettingChangedSignalId);
+
+ if (m_pSettingsPortal)
+ g_object_unref(m_pSettingsPortal);
}
GtkWidget *pEventWidget = getMouseEventWidget();
@@ -900,6 +907,8 @@ void GtkSalFrame::InitCommon()
m_pSurface = nullptr;
m_nGrabLevel = 0;
m_bSalObjectSetPosSize = false;
+ m_nPortalSettingChangedSignalId = 0;
+ m_pSettingsPortal = nullptr;
m_aDamageHandler.handle = this;
m_aDamageHandler.damaged = ::damaged;
@@ -1243,6 +1252,91 @@ void GtkSalFrame::AllowCycleFocusOut()
#endif
}
+namespace
+{
+ enum ColorScheme
+ {
+ DEFAULT,
+ PREFER_DARK,
+ PREFER_LIGHT
+ };
+
+ bool ReadColorScheme(GDBusProxy* proxy, GVariant** out)
+ {
+ g_autoptr (GVariant) ret =
+ g_dbus_proxy_call_sync(proxy, "Read",
+ g_variant_new ("(ss)", "org.freedesktop.appearance", "color-scheme"),
+ G_DBUS_CALL_FLAGS_NONE, G_MAXINT, nullptr, nullptr);
+ if (!ret)
+ return false;
+
+ g_autoptr (GVariant) child = nullptr;
+ g_variant_get(ret, "(v)", &child);
+ g_variant_get(child, "v", out);
+
+ return true;
+ }
+}
+
+void GtkSalFrame::SetColorScheme(GVariant* variant)
+{
+ if (!m_pWindow)
+ return;
+
+ guint32 color_scheme = g_variant_get_uint32(variant);
+ if (color_scheme > PREFER_LIGHT)
+ color_scheme = DEFAULT;
+
+ bool bDarkIconTheme(color_scheme == PREFER_DARK);
+ GtkSettings* pSettings = gtk_widget_get_settings(m_pWindow);
+ g_object_set(pSettings, "gtk-application-prefer-dark-theme", bDarkIconTheme, nullptr);
+}
+
+static void settings_portal_changed_cb(GDBusProxy*, const char*, const char* signal_name,
+ GVariant* parameters, gpointer frame)
+{
+ if (g_strcmp0(signal_name, "SettingChanged"))
+ return;
+
+ g_autoptr (GVariant) value = nullptr;
+ const char *name_space;
+ const char *name;
+ g_variant_get(parameters, "(&s&sv)", &name_space, &name, &value);
+
+ if (g_strcmp0(name_space, "org.freedesktop.appearance") ||
+ g_strcmp0(name, "color-scheme"))
+ return;
+
+ GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
+ pThis->SetColorScheme(value);
+}
+
+void GtkSalFrame::ListenPortalSettings()
+{
+ EnsureSessionBus();
+
+ if (!pSessionBus)
+ return;
+
+ m_pSettingsPortal = g_dbus_proxy_new_sync(pSessionBus,
+ G_DBUS_PROXY_FLAGS_NONE,
+ nullptr,
+ "org.freedesktop.portal.Desktop",
+ "/org/freedesktop/portal/desktop",
+ "org.freedesktop.portal.Settings",
+ nullptr,
+ nullptr);
+ if (!m_pSettingsPortal)
+ return;
+
+ g_autoptr (GVariant) value = nullptr;
+
+ if (!ReadColorScheme(m_pSettingsPortal, &value))
+ return;
+
+ SetColorScheme(value);
+ m_nPortalSettingChangedSignalId = g_signal_connect(m_pSettingsPortal, "g-signal", G_CALLBACK(settings_portal_changed_cb), this);
+}
void GtkSalFrame::Init( SalFrame* pParent, SalFrameStyleFlags nStyle )
{
@@ -1403,6 +1497,9 @@ void GtkSalFrame::Init( SalFrame* pParent, SalFrameStyleFlags nStyle )
{
// Enable GMenuModel native menu
attach_menu_model(this);
+
+ // Listen to portal settings for e.g. prefer dark theme
+ ListenPortalSettings();
}
}
@@ -3901,12 +3998,6 @@ gboolean GtkSalFrame::signalKey(GtkWidget* pWidget, GdkEventKey* pEvent, gpointe
if (GTK_IS_WINDOW(pThis->m_pWindow))
{
- // tdf#144846 If this is registered as a menubar mnemonic then ensure
- // that any other widget won't be considered as a candidate by taking
- // over the task of launch the menubar menu outself
- if (pThis->HandleMenubarMnemonic(pEvent->state, pEvent->keyval))
- return true;
-
GtkWidget* pFocusWindow = gtk_window_get_focus(GTK_WINDOW(pThis->m_pWindow));
bFocusInAnotherGtkWidget = pFocusWindow && pFocusWindow != GTK_WIDGET(pThis->m_pFixedContainer);
if (bFocusInAnotherGtkWidget)
@@ -4058,6 +4149,20 @@ gboolean GtkSalFrame::signalKey(GtkWidget* pWidget, GdkEventKey* pEvent, gpointe
sal_Unicode(gdk_keyval_to_unicode( pEvent->keyval )),
(pEvent->type == GDK_KEY_PRESS),
false);
+
+ // tdf#144846 If this is registered as a menubar mnemonic then ensure
+ // that any other widget won't be considered as a candidate by taking
+ // over the task of launch the menubar menu outself
+ // The code was moved here from its original position at beginning
+ // of this function in order to resolve tdf#146174.
+ if (!bStopProcessingKey && // module key handler did not process key
+ pEvent->type == GDK_KEY_PRESS && // module key handler handles only GDK_KEY_PRESS
+ GTK_IS_WINDOW(pThis->m_pWindow) &&
+ pThis->HandleMenubarMnemonic(pEvent->state, pEvent->keyval))
+ {
+ return true;
+ }
+
if (!aDel.isDeleted())
{
pThis->m_nKeyModifiers = ModKeyFlags::NONE;
@@ -5807,16 +5912,39 @@ void GtkSalFrame::startDrag(const css::datatransfer::dnd::DragGestureEvent& rEve
aFakeEvent.type = GDK_BUTTON_PRESS;
aFakeEvent.button.window = widget_get_surface(getMouseEventWidget());
aFakeEvent.button.time = GDK_CURRENT_TIME;
- GdkDeviceManager* pDeviceManager = gdk_display_get_device_manager(getGdkDisplay());
- aFakeEvent.button.device = gdk_device_manager_get_client_pointer(pDeviceManager);
-
- GdkDragContext *pDrag = gtk_drag_begin_with_coordinates(getMouseEventWidget(),
- pTargetList,
- sourceActions,
- nDragButton,
- &aFakeEvent,
- rEvent.DragOriginX,
- rEvent.DragOriginY);
+
+ aFakeEvent.button.device = gtk_get_current_event_device();
+ // if no current event to determine device, or (tdf#140272) the device will be unsuitable then find an
+ // appropiate device to use.
+ if (!aFakeEvent.button.device || !gdk_device_get_window_at_position(aFakeEvent.button.device, nullptr, nullptr))
+ {
+ GdkDeviceManager* pDeviceManager = gdk_display_get_device_manager(getGdkDisplay());
+ GList* pDevices = gdk_device_manager_list_devices(pDeviceManager, GDK_DEVICE_TYPE_MASTER);
+ for (GList* pEntry = pDevices; pEntry; pEntry = pEntry->next)
+ {
+ GdkDevice* pDevice = static_cast<GdkDevice*>(pEntry->data);
+ if (gdk_device_get_source(pDevice) == GDK_SOURCE_KEYBOARD)
+ continue;
+ if (gdk_device_get_window_at_position(pDevice, nullptr, nullptr))
+ {
+ aFakeEvent.button.device = pDevice;
+ break;
+ }
+ }
+ g_list_free(pDevices);
+ }
+
+ GdkDragContext *pDrag;
+ if (!aFakeEvent.button.device || !gdk_device_get_window_at_position(aFakeEvent.button.device, nullptr, nullptr))
+ pDrag = nullptr;
+ else
+ pDrag = gtk_drag_begin_with_coordinates(getMouseEventWidget(),
+ pTargetList,
+ sourceActions,
+ nDragButton,
+ &aFakeEvent,
+ rEvent.DragOriginX,
+ rEvent.DragOriginY);
gtk_target_list_unref(pTargetList);