From c8c6f121ce2b72ebe43d2d51833ead32e1822679 Mon Sep 17 00:00:00 2001 From: Caolán McNamara Date: Nov 30 2015 12:31:13 +0000 Subject: Related: rhbz#1281906 wayland toolbar drawn over menus etc --- diff --git a/0001-Related-rhbz-1281906-wayland-toolbar-drawn-over-menu.patch b/0001-Related-rhbz-1281906-wayland-toolbar-drawn-over-menu.patch new file mode 100644 index 0000000..28bae4b --- /dev/null +++ b/0001-Related-rhbz-1281906-wayland-toolbar-drawn-over-menu.patch @@ -0,0 +1,319 @@ +From 2e071f6dd64561ae173b903a76065e2fab48a266 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= +Date: Fri, 24 Jul 2015 12:22:14 +0100 +Subject: [PATCH] Related: rhbz#1281906 wayland toolbar drawn over menus etc + +gtk3: draw/paint to the fixed container + +which fills the toplevel window, rather than directly to the toplevel window. + +It makes no difference for X, but for wayland the window decorations are part +of the toplevel window, dropping down a level means we don't draw out menu bar +under the window decoration space + +(cherry picked from commit 298c089df77d9afe2cf86bb7a6a8544a0151e8c5) + +Change-Id: Icec400efacd16b5d901107c13b6fa90c59cad0e6 + +gtk3: insert an event box between toplevel and contents + +Change-Id: Ic78aa62baaa4260645a80ffb6704103440339595 +(cherry picked from commit 2796d7f1723d5b45177fe6da7a6e66cb914ae6d2) + +gtk3: connect to the eventbox and not toplevel for mouse events + +this leaves whatever magic gtk3 under wayland is doing on the toplevel +alone so the window can be resized and the title bar responds to +clicks as expected + +Change-Id: I9952cb719f3148660e17951b4f66a2525e11a6df +(cherry picked from commit 10d2467c2532178efe3d672405839bc1d0aab1e5) + +attach gestures to event widget instead of toplevel + +Change-Id: Id0658cf561570a2ae15fb7fd603e6437da9cfaf2 +(cherry picked from commit 848f685ae8f614ad62d205ef628f259cafb738b3) +--- + vcl/inc/unx/gtk/gtkframe.hxx | 5 +- + vcl/unx/gtk/a11y/atkfactory.cxx | 21 +++++++-- + vcl/unx/gtk/window/gtksalframe.cxx | 93 +++++++++++++++++++++++++++----------- + 3 files changed, 88 insertions(+), 31 deletions(-) + +diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx +index 604f2a6..3531c41 100644 +--- a/vcl/inc/unx/gtk/gtkframe.hxx ++++ b/vcl/inc/unx/gtk/gtkframe.hxx +@@ -173,6 +173,8 @@ class GtkSalFrame : public SalFrame, public X11WindowProvider + + SalX11Screen m_nXScreen; + GtkWidget* m_pWindow; ++ GtkEventBox* m_pEventBox; ++ GtkFixed* m_pFixedContainer; + GdkWindow* m_pForeignParent; + GdkNativeWindow m_aForeignParentWindow; + GdkWindow* m_pForeignTopLevel; +@@ -180,7 +182,6 @@ class GtkSalFrame : public SalFrame, public X11WindowProvider + Pixmap m_hBackgroundPixmap; + sal_uLong m_nStyle; + SalExtStyle m_nExtStyle; +- GtkFixed* m_pFixedContainer; + GtkSalFrame* m_pParent; + std::list< GtkSalFrame* > m_aChildren; + GdkWindowState m_nState; +@@ -335,6 +336,7 @@ public: + guint m_nActionGroupExportId; + guint m_nAppActionGroupExportId; + guint m_nHudAwarenessId; ++ std::vector m_aMouseSignalIds; + + // dispatches an event, returns true if dispatched + // and false else; if true was returned the event should +@@ -347,6 +349,7 @@ public: + static GdkDisplay* getGdkDisplay(); + GtkWidget* getWindow() const { return m_pWindow; } + GtkFixed* getFixedContainer() const { return m_pFixedContainer; } ++ GtkWidget* getMouseEventWidget() const; + GdkWindow* getForeignParent() const { return m_pForeignParent; } + GdkNativeWindow getForeignParentWindow() const { return m_aForeignParentWindow; } + GdkWindow* getForeignTopLevel() const { return m_pForeignTopLevel; } +diff --git a/vcl/unx/gtk/a11y/atkfactory.cxx b/vcl/unx/gtk/a11y/atkfactory.cxx +index 99ed750..9edc7ab 100644 +--- a/vcl/unx/gtk/a11y/atkfactory.cxx ++++ b/vcl/unx/gtk/a11y/atkfactory.cxx +@@ -101,14 +101,27 @@ wrapper_factory_get_accessible_type() + static AtkObject* + wrapper_factory_create_accessible( GObject *obj ) + { +- GtkWidget* parent_widget = gtk_widget_get_parent( GTK_WIDGET( obj ) ); ++#if GTK_CHECK_VERSION(3,0,0) ++ GtkWidget* pEventBox = gtk_widget_get_parent(GTK_WIDGET(obj)); + + // gail_container_real_remove_gtk tries to re-instanciate an accessible + // for a widget that is about to vanish .. +- if( ! parent_widget ) ++ if (!pEventBox) + return atk_noop_object_wrapper_new(); + +- GtkSalFrame* pFrame = GtkSalFrame::getFromWindow( GTK_WINDOW( parent_widget ) ); ++ GtkWidget* pTopLevel = gtk_widget_get_parent(pEventBox); ++ if (!pTopLevel) ++ return atk_noop_object_wrapper_new(); ++#else ++ GtkWidget* pTopLevel = gtk_widget_get_parent(GTK_WIDGET(obj)); ++ ++ // gail_container_real_remove_gtk tries to re-instanciate an accessible ++ // for a widget that is about to vanish .. ++ if (!pTopLevel) ++ return atk_noop_object_wrapper_new(); ++#endif ++ ++ GtkSalFrame* pFrame = GtkSalFrame::getFromWindow(GTK_WINDOW(pTopLevel)); + g_return_val_if_fail( pFrame != NULL, NULL ); + + vcl::Window* pFrameWindow = pFrame->GetWindow(); +@@ -130,7 +143,7 @@ wrapper_factory_create_accessible( GObject *obj ) + if( accessible ) + g_object_ref( G_OBJECT(accessible) ); + else +- accessible = atk_object_wrapper_new( xAccessible, gtk_widget_get_accessible(parent_widget) ); ++ accessible = atk_object_wrapper_new( xAccessible, gtk_widget_get_accessible(pTopLevel) ); + + return accessible; + } +diff --git a/vcl/unx/gtk/window/gtksalframe.cxx b/vcl/unx/gtk/window/gtksalframe.cxx +index eef48cd..8acdf8a 100644 +--- a/vcl/unx/gtk/window/gtksalframe.cxx ++++ b/vcl/unx/gtk/window/gtksalframe.cxx +@@ -414,7 +414,7 @@ void GtkSalFrame::doKeyCallback( guint state, + if (keyval == GDK_0) + { + fprintf( stderr, "force widget_queue_draw\n"); +- gtk_widget_queue_draw (m_pWindow); ++ gtk_widget_queue_draw (m_pFixedContainer); + return; + } + else if (keyval == GDK_1) +@@ -894,8 +894,13 @@ GtkSalFrame::~GtkSalFrame() + if( m_pIMHandler ) + delete m_pIMHandler; + ++ GtkWidget *pEventWidget = getMouseEventWidget(); ++ for (auto handler_id : m_aMouseSignalIds) ++ g_signal_handler_disconnect(G_OBJECT(pEventWidget), handler_id); + if( m_pFixedContainer ) + gtk_widget_destroy( GTK_WIDGET( m_pFixedContainer ) ); ++ if( m_pEventBox ) ++ gtk_widget_destroy( GTK_WIDGET(m_pEventBox) ); + { + SolarMutexGuard aGuard; + #if defined ENABLE_GMENU_INTEGRATION +@@ -1036,38 +1041,75 @@ void GtkSalFrame::updateScreenNumber() + maGeometry.nDisplayScreenNumber = nScreen; + } + ++GtkWidget *GtkSalFrame::getMouseEventWidget() const ++{ ++#if GTK_CHECK_VERSION(3,0,0) ++ return GTK_WIDGET(m_pEventBox); ++#else ++ return m_pWindow; ++#endif ++} ++ + void GtkSalFrame::InitCommon() + { ++#if GTK_CHECK_VERSION(3,0,0) ++ m_pEventBox = GTK_EVENT_BOX(gtk_event_box_new()); ++ gtk_widget_add_events( GTK_WIDGET(m_pEventBox), ++ GDK_ALL_EVENTS_MASK ); ++ gtk_container_add( GTK_CONTAINER(m_pWindow), GTK_WIDGET(m_pEventBox) ); ++ ++ // add the fixed container child, ++ // fixed is needed since we have to position plugin windows ++ m_pFixedContainer = GTK_FIXED(g_object_new( ooo_fixed_get_type(), NULL )); ++ gtk_container_add( GTK_CONTAINER(m_pEventBox), GTK_WIDGET(m_pFixedContainer) ); ++#else ++ m_pEventBox = 0; ++ // add the fixed container child, ++ // fixed is needed since we have to position plugin windows ++ m_pFixedContainer = GTK_FIXED(g_object_new( ooo_fixed_get_type(), NULL )); ++ gtk_container_add( GTK_CONTAINER(m_pWindow), GTK_WIDGET(m_pFixedContainer) ); ++#endif ++ ++ GtkWidget *pEventWidget = getMouseEventWidget(); ++ ++ gtk_widget_set_app_paintable(GTK_WIDGET(m_pFixedContainer), true); ++ /*non-X11 displays won't show anything at all without double-buffering ++ enabled*/ ++ if (GDK_IS_X11_DISPLAY(getGdkDisplay())) ++ gtk_widget_set_double_buffered(GTK_WIDGET(m_pFixedContainer), false); ++ gtk_widget_set_redraw_on_allocate(GTK_WIDGET(m_pFixedContainer), false); ++ ++ + // connect signals + g_signal_connect( G_OBJECT(m_pWindow), "style-set", G_CALLBACK(signalStyleSet), this ); +- g_signal_connect( G_OBJECT(m_pWindow), "button-press-event", G_CALLBACK(signalButton), this ); +- g_signal_connect( G_OBJECT(m_pWindow), "button-release-event", G_CALLBACK(signalButton), this ); ++ m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "button-press-event", G_CALLBACK(signalButton), this )); ++ m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "motion-notify-event", G_CALLBACK(signalMotion), this )); ++ m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "button-release-event", G_CALLBACK(signalButton), this )); + #if GTK_CHECK_VERSION(3,0,0) +- g_signal_connect( G_OBJECT(m_pWindow), "draw", G_CALLBACK(signalDraw), this ); ++ g_signal_connect( G_OBJECT(m_pFixedContainer), "draw", G_CALLBACK(signalDraw), this ); + g_signal_connect( G_OBJECT(m_pWindow), "size-allocate", G_CALLBACK(sizeAllocated), this ); + // g_signal_connect( G_OBJECT(m_pWindow), "state-flags-changed", G_CALLBACK(signalFlagsChanged), this ); + #if GTK_CHECK_VERSION(3,14,0) +- GtkGesture *pSwipe = gtk_gesture_swipe_new(m_pWindow); ++ GtkGesture *pSwipe = gtk_gesture_swipe_new(pEventWidget); + g_signal_connect(pSwipe, "swipe", G_CALLBACK(gestureSwipe), this); + gtk_event_controller_set_propagation_phase(GTK_EVENT_CONTROLLER (pSwipe), GTK_PHASE_TARGET); +- g_object_weak_ref(G_OBJECT(m_pWindow), reinterpret_cast(g_object_unref), pSwipe); ++ g_object_weak_ref(G_OBJECT(pEventWidget), reinterpret_cast(g_object_unref), pSwipe); + +- GtkGesture *pLongPress = gtk_gesture_long_press_new(m_pWindow); ++ GtkGesture *pLongPress = gtk_gesture_long_press_new(pEventWidget); + g_signal_connect(pLongPress, "pressed", G_CALLBACK(gestureLongPress), this); + gtk_event_controller_set_propagation_phase(GTK_EVENT_CONTROLLER (pLongPress), GTK_PHASE_TARGET); +- g_object_weak_ref(G_OBJECT(m_pWindow), reinterpret_cast(g_object_unref), pLongPress); ++ g_object_weak_ref(G_OBJECT(pEventWidget), reinterpret_cast(g_object_unref), pLongPress); + + #endif + + #else +- g_signal_connect( G_OBJECT(m_pWindow), "expose-event", G_CALLBACK(signalExpose), this ); ++ g_signal_connect( G_OBJECT(m_pFixedContainer), "expose-event", G_CALLBACK(signalExpose), this ); + #endif + g_signal_connect( G_OBJECT(m_pWindow), "focus-in-event", G_CALLBACK(signalFocus), this ); + g_signal_connect( G_OBJECT(m_pWindow), "focus-out-event", G_CALLBACK(signalFocus), this ); + g_signal_connect( G_OBJECT(m_pWindow), "map-event", G_CALLBACK(signalMap), this ); + g_signal_connect( G_OBJECT(m_pWindow), "unmap-event", G_CALLBACK(signalUnmap), this ); + g_signal_connect( G_OBJECT(m_pWindow), "configure-event", G_CALLBACK(signalConfigure), this ); +- g_signal_connect( G_OBJECT(m_pWindow), "motion-notify-event", G_CALLBACK(signalMotion), this ); + g_signal_connect( G_OBJECT(m_pWindow), "key-press-event", G_CALLBACK(signalKey), this ); + g_signal_connect( G_OBJECT(m_pWindow), "key-release-event", G_CALLBACK(signalKey), this ); + g_signal_connect( G_OBJECT(m_pWindow), "delete-event", G_CALLBACK(signalDelete), this ); +@@ -1102,26 +1144,18 @@ void GtkSalFrame::InitCommon() + m_nAppActionGroupExportId = 0; + m_nHudAwarenessId = 0; + +- gtk_widget_set_app_paintable( m_pWindow, TRUE ); +- /*non-X11 displays won't show anything at all without double-buffering +- enabled*/ +- if (GDK_IS_X11_DISPLAY(getGdkDisplay())) +- gtk_widget_set_double_buffered( m_pWindow, FALSE ); +- gtk_widget_set_redraw_on_allocate( m_pWindow, FALSE ); +- + gtk_widget_add_events( m_pWindow, + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | + GDK_VISIBILITY_NOTIFY_MASK | GDK_SCROLL_MASK + ); + +- // add the fixed container child, +- // fixed is needed since we have to position plugin windows +- m_pFixedContainer = GTK_FIXED(g_object_new( ooo_fixed_get_type(), NULL )); +- gtk_container_add( GTK_CONTAINER(m_pWindow), GTK_WIDGET(m_pFixedContainer) ); +- + // show the widgets +- gtk_widget_show( GTK_WIDGET(m_pFixedContainer) ); ++#if GTK_CHECK_VERSION(3,0,0) ++ gtk_widget_show_all( GTK_WIDGET(m_pEventBox) ); ++#else ++ gtk_widget_show_all( GTK_WIDGET(m_pFixedContainer) ); ++#endif + + // realize the window, we need an XWindow id + gtk_widget_realize( m_pWindow ); +@@ -2780,7 +2814,7 @@ void GtkSalFrame::grabPointer( bool bGrab, bool bOwnerEvents ) + GdkDeviceManager* pDeviceManager = gdk_display_get_device_manager(getGdkDisplay()); + GdkDevice* pPointer = gdk_device_manager_get_client_pointer(pDeviceManager); + if (bGrab) +- gdk_device_grab(pPointer, widget_get_window(m_pWindow), GDK_OWNERSHIP_NONE, bOwnerEvents, (GdkEventMask) nMask, m_pCurrentCursor, GDK_CURRENT_TIME); ++ gdk_device_grab(pPointer, widget_get_window(getMouseEventWidget()), GDK_OWNERSHIP_NONE, bOwnerEvents, (GdkEventMask) nMask, m_pCurrentCursor, GDK_CURRENT_TIME); + else + gdk_device_ungrab(pPointer, GDK_CURRENT_TIME); + #else +@@ -3189,8 +3223,14 @@ void GtkSalFrame::createNewWindow( ::Window aNewParent, bool bXEmbed, SalX11Scre + { + gdk_region_destroy( m_pRegion ); + } ++ ++ GtkWidget *pEventWidget = getMouseEventWidget(); ++ for (auto handler_id : m_aMouseSignalIds) ++ g_signal_handler_disconnect(G_OBJECT(pEventWidget), handler_id); + if( m_pFixedContainer ) + gtk_widget_destroy( GTK_WIDGET(m_pFixedContainer) ); ++ if( m_pEventBox ) ++ gtk_widget_destroy( GTK_WIDGET(m_pEventBox) ); + if( m_pWindow ) + gtk_widget_destroy( m_pWindow ); + if( m_pForeignParent ) +@@ -3651,7 +3691,7 @@ void GtkSalFrame::damaged (const basegfx::B2IBox& rDamageRect) + cairo_destroy(cr); + } + +- gtk_widget_queue_draw_area(m_pWindow, ++ gtk_widget_queue_draw_area(GTK_WIDGET(m_pFixedContainer), + rDamageRect.getMinX(), + rDamageRect.getMinY(), + rDamageRect.getWidth(), +@@ -3874,7 +3914,7 @@ void GtkSalFrame::TriggerPaintEvent() + SAL_INFO("vcl.gtk3", "force painting" << 0 << "," << 0 << " " << maGeometry.nWidth << "x" << maGeometry.nHeight); + SalPaintEvent aPaintEvt(0, 0, maGeometry.nWidth, maGeometry.nHeight, true); + CallCallback(SALEVENT_PAINT, &aPaintEvt); +- gtk_widget_queue_draw(m_pWindow); ++ gtk_widget_queue_draw(GTK_WIDGET(m_pFixedContainer)); + #endif + } + +@@ -4212,6 +4252,7 @@ void GtkSalFrame::signalDestroy( GtkWidget* pObj, gpointer frame ) + if( pObj == pThis->m_pWindow ) + { + pThis->m_pFixedContainer = NULL; ++ pThis->m_pEventBox = NULL; + pThis->m_pWindow = NULL; + pThis->InvalidateGraphics(); + } +-- +2.5.0 + diff --git a/libreoffice.spec b/libreoffice.spec index 4c7e8c1..dac82af 100644 --- a/libreoffice.spec +++ b/libreoffice.spec @@ -354,6 +354,7 @@ Patch45: 0001-backport-5-1-idle-timers-loop-to-5-0.patch Patch46: 0001-gtk3-implement-SAL_INVERT_50-rectangle-case.patch Patch47: 0001-rhbz-1286416-Be-more-resilient-during-auto-recovery-.patch Patch48: 0001-Resolves-tdf-95962-incorrect-scanline-stride.patch +Patch49: 0001-Related-rhbz-1281906-wayland-toolbar-drawn-over-menu.patch %define instdir %{_libdir} %define baseinstdir %{instdir}/libreoffice @@ -2474,8 +2475,9 @@ update-desktop-database %{_datadir}/applications &> /dev/null || : %endif %changelog -* Mon Nov 30 2015 Stephan Bergmann - 1:5.0.3.2-9-UNBUILT +* Mon Nov 30 2015 Stephan Bergmann - 1:5.0.3.2-9 - Related: rhbz#1286416 Be more resilient during auto-recovery attempts +- Related: rhbz#1281906 wayland toolbar drawn over menus etc * Sun Nov 29 2015 Caolán McNamara - 1:5.0.3.2-8 - Related: rhbz#1277445 backport 5-1 idle + timers + mainloop to 5.0