From eb27eda272dd9fe6dfa4ebcfef24069bd117e5b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= Date: Fri, 18 Oct 2013 10:04:45 +0100 Subject: [PATCH] Related: rhbz#919070 display -1 means span all displays So try to set size to full "screen" size. most window managers will ignore this however unless _NET_WM_FULLSCREEN_MONITORS is set, Under gtk3 we can use gdk_window_set_fullscreen_mode to do that. Its effectively impractical for LibreOffice to itself calculate the right parameters for _NET_WM_FULLSCREEN_MONITORS as far as I can see Change-Id: Ia725f21048bfcec3dbf1478b4303ccd9cfec0b36 (cherry picked from commit a8dd794356cb62480b2dc12504ad9e0158a0b583) Resolves: rhbz#919070 offload set span-all-displays to a gtk3 utility Jaw dropping hack to set a slideshow to span all monitors if gtk3 is available at runtime (cherry picked from commit 14bb85e0a3d95419c484bfa23881f03c54031c5d) Conflicts: Repository.mk Change-Id: I363f63c9855d5cb1f92d65d0b34add0c60f7263c missing .mk Change-Id: I923153579d6cc50354450a5b3a55ecc133ae5e41 (cherry picked from commit 2d3dd8594ee3e43fcf9a65887f90d187a4393297) move xid-fullscreen into gnome package Change-Id: I2ad0838a12ce06b2c6e77b7f55cdc2cd0627a38b (cherry picked from commit 9c1170b25a9fab13084d2677aa4fc986db5ab675) pScreen uninitialized Change-Id: I244c3b5a949ae5c8a5bf46d1b58439e080b2c848 (cherry picked from commit 1b4aa55ecd7b2c3f6e0d281642d0ed0a066dec69) --- Repository.mk | 3 + scp2/source/gnome/module_gnome.scp | 3 +- scp2/source/ooo/file_library_ooo.scp | 10 ++ vcl/Executable_xid_fullscreen_on_all_monitors.mk | 20 +++ vcl/Module_vcl.mk | 1 + vcl/inc/unx/gtk/gtkframe.hxx | 1 + vcl/unx/gtk/window/gtksalframe.cxx | 134 ++++++++++++++++----- .../gtk/window/xid_fullscreen_on_all_monitors.c | 99 +++++++++++++++ 8 files changed, 243 insertions(+), 28 deletions(-) create mode 100644 vcl/Executable_xid_fullscreen_on_all_monitors.mk create mode 100644 vcl/unx/gtk/window/xid_fullscreen_on_all_monitors.c diff --git a/Repository.mk b/Repository.mk index e0d4d7c..99278bc 100644 --- a/Repository.mk +++ b/Repository.mk @@ -89,6 +89,9 @@ endif $(eval $(call gb_Helper_register_executables,OOO, \ gnome-open-url.bin \ spadmin.bin \ + $(if $(filter $(GUIBASE)$(ENABLE_GTK),unxTRUE), \ + xid-fullscreen-on-all-monitors \ + ) \ $(if $(filter $(GUIBASE)$(ENABLE_TDE),unxTRUE), \ tdefilepicker \ ) \ diff --git a/scp2/source/gnome/module_gnome.scp b/scp2/source/gnome/module_gnome.scp index e8a22bf..75214d5 100644 --- a/scp2/source/gnome/module_gnome.scp +++ b/scp2/source/gnome/module_gnome.scp @@ -34,7 +34,8 @@ Module gid_Module_Optional_Gnome gid_File_Share_Registry_Gnome_Xcd, #endif gid_File_Bin_Gnome_Open_Url, - gid_File_Bin_Gnome_Open_Url_Bin + gid_File_Bin_Gnome_Open_Url_Bin, + gid_File_Bin_XidFullscreen ); End diff --git a/scp2/source/ooo/file_library_ooo.scp b/scp2/source/ooo/file_library_ooo.scp index 36ec8d4..417f483 100644 --- a/scp2/source/ooo/file_library_ooo.scp +++ b/scp2/source/ooo/file_library_ooo.scp @@ -343,6 +343,16 @@ File gid_File_Bin_KdeFilePicker Name = "kdefilepicker"; End #endif + +#ifdef ENABLE_GTK +File gid_File_Bin_XidFullscreen + BIN_FILE_BODY; + Styles = (PACKED); + Dir = gid_Brand_Dir_Program; + Name = "xid-fullscreen-on-all-monitors"; +End +#endif + #endif #ifdef MACOSX diff --git a/vcl/Executable_xid_fullscreen_on_all_monitors.mk b/vcl/Executable_xid_fullscreen_on_all_monitors.mk new file mode 100644 index 0000000..5f9c127 --- /dev/null +++ b/vcl/Executable_xid_fullscreen_on_all_monitors.mk @@ -0,0 +1,20 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Executable_Executable,xid-fullscreen-on-all-monitors)) + +$(eval $(call gb_Executable_add_libs,xid-fullscreen-on-all-monitors,\ + -ldl \ +)) + +$(eval $(call gb_Executable_add_cobjects,xid-fullscreen-on-all-monitors,\ + vcl/unx/gtk/window/xid_fullscreen_on_all_monitors \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk index fd2be4c5..47031b3 100644 --- a/vcl/Module_vcl.mk +++ b/vcl/Module_vcl.mk @@ -39,6 +39,7 @@ $(eval $(call gb_Module_add_targets,vcl,\ ifneq ($(ENABLE_GTK),) $(eval $(call gb_Module_add_targets,vcl,\ + Executable_xid_fullscreen_on_all_monitors \ Library_vclplug_gtk \ )) endif diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx index c3ea919..3edd2cb 100644 --- a/vcl/inc/unx/gtk/gtkframe.hxx +++ b/vcl/inc/unx/gtk/gtkframe.hxx @@ -196,6 +196,7 @@ class GtkSalFrame : public SalFrame guint m_nGSMCookie; int m_nWorkArea; bool m_bFullscreen; + bool m_bSpanMonitorsWhenFullscreen; bool m_bDefaultPos; bool m_bDefaultSize; bool m_bSendModChangeOnRelease; diff --git a/vcl/unx/gtk/window/gtksalframe.cxx b/vcl/unx/gtk/window/gtksalframe.cxx index fef8407..4a3d01c 100644 --- a/vcl/unx/gtk/window/gtksalframe.cxx +++ b/vcl/unx/gtk/window/gtksalframe.cxx @@ -29,6 +29,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -83,6 +86,8 @@ #define GSM_DBUS_INTERFACE "org.gnome.SessionManager" #endif +#include + // make compile on gtk older than 2.10 #if GTK_MINOR_VERSION < 10 #define GDK_SUPER_MASK (1 << 26) @@ -814,6 +819,7 @@ void GtkSalFrame::InitCommon() m_pCurrentCursor = NULL; m_nKeyModifiers = 0; m_bFullscreen = false; + m_bSpanMonitorsWhenFullscreen = false; m_nState = GDK_WINDOW_STATE_WITHDRAWN; m_nVisibility = GDK_VISIBILITY_FULLY_OBSCURED; m_bSendModChangeOnRelease = false; @@ -2045,43 +2051,68 @@ void GtkSalFrame::SetScreen( unsigned int nNewScreen, int eType, Rectangle *pSiz if (maGeometry.nDisplayScreenNumber == nNewScreen && eType == SET_RETAIN_SIZE) return; - gint nMonitor; - bool bSameMonitor = false; - GdkScreen *pScreen = getDisplay()->getSystem()->getScreenMonitorFromIdx( nNewScreen, nMonitor ); - if (!pScreen) + GdkScreen *pScreen = NULL; + GdkRectangle aNewMonitor; + + bool bSpanAllScreens = nNewScreen == (unsigned int)-1; + m_bSpanMonitorsWhenFullscreen = bSpanAllScreens && getDisplay()->getSystem()->GetDisplayScreenCount() > 1; + + if (m_bSpanMonitorsWhenFullscreen) //span all screens { - g_warning ("Attempt to move GtkSalFrame to invalid screen %d => " - "fallback to current\n", nNewScreen); pScreen = gtk_widget_get_screen( m_pWindow ); - bSameMonitor = true; + aNewMonitor.x = 0; + aNewMonitor.y = 0; + aNewMonitor.width = gdk_screen_get_width(pScreen); + aNewMonitor.height = gdk_screen_get_height(pScreen); } + else + { + gint nMonitor; + bool bSameMonitor = false; - // Heavy lifting, need to move screen ... - if( pScreen != gtk_widget_get_screen( m_pWindow )) - gtk_window_set_screen( GTK_WINDOW( m_pWindow ), pScreen ); + if (!bSpanAllScreens) + { + pScreen = getDisplay()->getSystem()->getScreenMonitorFromIdx( nNewScreen, nMonitor ); + if (!pScreen) + { + g_warning ("Attempt to move GtkSalFrame to invalid screen %d => " + "fallback to current\n", nNewScreen); + } + } - gint nOldMonitor = gdk_screen_get_monitor_at_window( - pScreen, widget_get_window( m_pWindow ) ); - if (bSameMonitor) - nMonitor = nOldMonitor; + if (!pScreen) + { + pScreen = gtk_widget_get_screen( m_pWindow ); + bSameMonitor = true; + } -#if OSL_DEBUG_LEVEL > 1 - if( nMonitor == nOldMonitor ) - g_warning( "An apparently pointless SetScreen - should we elide it ?" ); -#endif + // Heavy lifting, need to move screen ... + if( pScreen != gtk_widget_get_screen( m_pWindow )) + gtk_window_set_screen( GTK_WINDOW( m_pWindow ), pScreen ); + + gint nOldMonitor = gdk_screen_get_monitor_at_window( + pScreen, widget_get_window( m_pWindow ) ); + if (bSameMonitor) + nMonitor = nOldMonitor; - GdkRectangle aOldMonitor, aNewMonitor; - gdk_screen_get_monitor_geometry( pScreen, nOldMonitor, &aOldMonitor ); - gdk_screen_get_monitor_geometry( pScreen, nMonitor, &aNewMonitor ); + #if OSL_DEBUG_LEVEL > 1 + if( nMonitor == nOldMonitor ) + g_warning( "An apparently pointless SetScreen - should we elide it ?" ); + #endif + + GdkRectangle aOldMonitor; + gdk_screen_get_monitor_geometry( pScreen, nOldMonitor, &aOldMonitor ); + gdk_screen_get_monitor_geometry( pScreen, nMonitor, &aNewMonitor ); + + maGeometry.nX = aNewMonitor.x + maGeometry.nX - aOldMonitor.x; + maGeometry.nY = aNewMonitor.y + maGeometry.nY - aOldMonitor.y; + } bool bResize = false; bool bVisible = IS_WIDGET_MAPPED( m_pWindow ); if( bVisible ) Show( sal_False ); - maGeometry.nX = aNewMonitor.x + maGeometry.nX - aOldMonitor.x; - maGeometry.nY = aNewMonitor.y + maGeometry.nY - aOldMonitor.y; - if( eType == SET_FULLSCREEN ) { maGeometry.nX = aNewMonitor.x; @@ -2093,8 +2124,8 @@ void GtkSalFrame::SetScreen( unsigned int nNewScreen, int eType, Rectangle *pSiz // #i110881# for the benefit of compiz set a max size here // else setting to fullscreen fails for unknown reasons - m_aMaxSize.Width() = aNewMonitor.width+100; - m_aMaxSize.Height() = aNewMonitor.height+100; + m_aMaxSize.Width() = aNewMonitor.width; + m_aMaxSize.Height() = aNewMonitor.height; } if( pSize && eType == SET_UN_FULLSCREEN ) @@ -2119,14 +2150,19 @@ void GtkSalFrame::SetScreen( unsigned int nNewScreen, int eType, Rectangle *pSiz #if !GTK_CHECK_VERSION(3,0,0) // _NET_WM_STATE_FULLSCREEN (Metacity <-> KWin) - if( ! getDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() ) + if( ! getDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() ) #endif { +#if GTK_CHECK_VERSION(3,8,0) + gdk_window_set_fullscreen_mode( gtk_widget_get_window(m_pWindow), m_bSpanMonitorsWhenFullscreen + ? GDK_FULLSCREEN_ON_ALL_MONITORS : GDK_FULLSCREEN_ON_CURRENT_MONITOR ); +#endif if( eType == SET_FULLSCREEN ) gtk_window_fullscreen( GTK_WINDOW( m_pWindow ) ); else if( eType == SET_UN_FULLSCREEN ) gtk_window_unfullscreen( GTK_WINDOW( m_pWindow ) ); } + if( eType == SET_UN_FULLSCREEN && !(m_nStyle & SAL_FRAME_STYLE_SIZEABLE) ) gtk_window_set_resizable( GTK_WINDOW( m_pWindow ), FALSE ); @@ -3339,10 +3375,54 @@ gboolean GtkSalFrame::signalFocus( GtkWidget*, GdkEventFocus* pEvent, gpointer f return sal_False; } +#if !GTK_CHECK_VERSION(3,8,0) +static OString getDisplayString() +{ + int nParams = rtl_getAppCommandArgCount(); + OUString aParam; + for( int i = 0; i < nParams; i++ ) + { + rtl_getAppCommandArg( i, &aParam.pData ); + if( i < nParams-1 && (aParam == "-display" || aParam == "--display" ) ) + { + rtl_getAppCommandArg( i+1, &aParam.pData ); + return OUStringToOString( aParam, osl_getThreadTextEncoding() ); + } + } + return OString(); +} +#endif + gboolean GtkSalFrame::signalMap( GtkWidget *pWidget, GdkEvent*, gpointer frame ) { GtkSalFrame* pThis = (GtkSalFrame*)frame; +#if !GTK_CHECK_VERSION(3,8,0) + //Spawn off a helper program that will attempt to set this fullscreen + //window to span all displays. + if (pThis->m_bFullscreen && pThis->m_bSpanMonitorsWhenFullscreen) + { + GdkWindow* gdkwin = gtk_widget_get_window(pThis->m_pWindow); + if (gdkwin) + { + OUString sProgramURL( "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER "/xid-fullscreen-on-all-monitors"); + rtl::Bootstrap::expandMacros(sProgramURL); + OUString sProgram; + if (osl::FileBase::getSystemPathFromFileURL(sProgramURL, sProgram) == osl::File::E_None) + { + OString sFinalProgram(OUStringToOString(sProgram, osl_getThreadTextEncoding()) + + " " + OString::number((int)GDK_WINDOW_XID(gdkwin))); + OString sDisplay(getDisplayString()); + if (!sDisplay.isEmpty()) + { + sFinalProgram += "--display " + sDisplay; + } + system(sFinalProgram.getStr()); + } + } + } +#endif + bool bSetFocus = pThis->m_bSetFocusOnMap; pThis->m_bSetFocusOnMap = false; diff --git a/vcl/unx/gtk/window/xid_fullscreen_on_all_monitors.c b/vcl/unx/gtk/window/xid_fullscreen_on_all_monitors.c new file mode 100644 index 0000000..00554b1 --- /dev/null +++ b/vcl/unx/gtk/window/xid_fullscreen_on_all_monitors.c @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +typedef int Window; +typedef union _GdkEvent GdkEvent; +typedef struct _GdkWindow GdkWindow; +typedef struct _GdkDisplay GdkDisplay; +typedef struct _GdkScreen GdkScreen; + +typedef enum +{ + GDK_FULLSCREEN_ON_CURRENT_MONITOR, + GDK_FULLSCREEN_ON_ALL_MONITORS +} GdkFullscreenMode; + +int main(int argc, char *argv[]) +{ + void *handle; + void (*gtk_init)(int*, char***); + GdkWindow* (*gdk_x11_window_foreign_new_for_display)(GdkDisplay*, Window); + GdkDisplay* (*gdk_display_get_default)(void); + GdkEvent* (*gdk_event_get)(void); + void (*gtk_main_do_event)(GdkEvent*); + void (*gdk_event_free)(GdkEvent*); + void (*gdk_window_fullscreen)(GdkWindow *); + void (*gdk_window_set_fullscreen_mode)(GdkWindow *, GdkFullscreenMode); + + GdkEvent *event; + GdkWindow *window; + int windowid; + + handle = dlopen("libgtk-3.so.0", RTLD_LAZY); + if( NULL == handle ) + return -1; + + gtk_init = (void (*) (int*, char***)) + dlsym(handle, "gtk_init"); + gdk_x11_window_foreign_new_for_display = (GdkWindow* (*)(GdkDisplay*, Window)) + dlsym(handle, "gdk_x11_window_foreign_new_for_display"); + gdk_display_get_default = (GdkDisplay* (*)(void)) + dlsym(handle, "gdk_display_get_default"); + gdk_event_get = (GdkEvent* (*)(void)) + dlsym(handle, "gdk_event_get"); + gtk_main_do_event = (void (*)(GdkEvent*)) + dlsym(handle, "gtk_main_do_event"); + gdk_event_free = (void (*)(GdkEvent*)) + dlsym(handle, "gdk_event_free"); + gdk_window_fullscreen = (void (*)(GdkWindow *)) + dlsym(handle, "gdk_window_fullscreen"); + gdk_window_set_fullscreen_mode = (void (*)(GdkWindow *, GdkFullscreenMode)) + dlsym(handle, "gdk_window_set_fullscreen_mode"); + + if (!gtk_init || + !gdk_x11_window_foreign_new_for_display || + !gdk_display_get_default || + !gdk_event_get || + !gtk_main_do_event || + !gdk_event_free || + !gdk_window_fullscreen || + !gdk_window_set_fullscreen_mode) + { + dlclose(handle); + return -1; + } + + gtk_init(&argc, &argv); + + windowid = atoi(argv[1]); + + window = gdk_x11_window_foreign_new_for_display(gdk_display_get_default(), windowid); + if (!window) + { + dlclose(handle); + return -1; + } + + gdk_window_set_fullscreen_mode(window, GDK_FULLSCREEN_ON_ALL_MONITORS); + gdk_window_fullscreen(window); + + while ((event = gdk_event_get()) != NULL) + { + gtk_main_do_event(event); + gdk_event_free(event); + } + + dlclose(handle); + return 0; +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + -- 1.8.3.1