diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx index 3610addde351..f033efff2506 100644 --- a/vcl/inc/unx/gtk/gtkframe.hxx +++ b/vcl/inc/unx/gtk/gtkframe.hxx @@ -271,6 +271,7 @@ class GtkSalFrame : public SalFrame static void gestureSwipe(GtkGestureSwipe* gesture, gdouble velocity_x, gdouble velocity_y, gpointer frame); static void gestureLongPress(GtkGestureLongPress* gesture, gpointer frame); #endif + gboolean handleKey(GtkWidget* pWidget, GdkEventKey* pEvent); #else static gboolean signalExpose( GtkWidget*, GdkEventExpose*, gpointer ); #endif diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx index 3dc58afd7c42..701616584493 100644 --- a/vcl/unx/gtk3/gtk3gtkframe.cxx +++ b/vcl/unx/gtk3/gtk3gtkframe.cxx @@ -1424,21 +1424,6 @@ void GtkSalFrame::Show( bool bVisible, bool bNoActivate ) SetDefaultSize(); setMinMaxSize(); - if( isFloatGrabWindow() && - m_pParent && - m_nFloats == 0 && - ! getDisplay()->GetCaptureFrame() ) - { - /* #i63086# - * outsmart Metacity's "focus:mouse" mode - * which insists on taking the focus from the document - * to the new float. Grab focus to parent frame BEFORE - * showing the float (cannot grab it to the float - * before show). - */ - m_pParent->grabPointer( true, true ); - } - if( ! bNoActivate && (m_nStyle & SalFrameStyleFlags::TOOLWINDOW) ) m_bSetFocusOnMap = true; @@ -1449,9 +1434,9 @@ void GtkSalFrame::Show( bool bVisible, bool bNoActivate ) m_nFloats++; if( ! getDisplay()->GetCaptureFrame() && m_nFloats == 1 ) { - grabPointer(true, true); - GtkSalFrame *pKeyboardFrame = m_pParent ? m_pParent : this; - pKeyboardFrame->grabKeyboard(true); + gtk_grab_add(getMouseEventWidget()); + grabPointer(true); + grabKeyboard(true); } // #i44068# reset parent's IM context if( m_pParent ) @@ -1467,9 +1452,9 @@ void GtkSalFrame::Show( bool bVisible, bool bNoActivate ) m_nFloats--; if( ! getDisplay()->GetCaptureFrame() && m_nFloats == 0) { - GtkSalFrame *pKeyboardFrame = m_pParent ? m_pParent : this; - pKeyboardFrame->grabKeyboard(false); + grabKeyboard(false); grabPointer(false); + gtk_grab_remove(getMouseEventWidget()); } } gtk_widget_hide( m_pWindow ); @@ -2076,9 +2061,13 @@ 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(getMouseEventWidget()), GDK_OWNERSHIP_NONE, bOwnerEvents, (GdkEventMask) nMask, m_pCurrentCursor, gtk_get_current_event_time()); + } else + { gdk_device_ungrab(pPointer, gtk_get_current_event_time()); + } } void GtkSalFrame::grabKeyboard( bool bGrab ) @@ -2414,13 +2403,6 @@ void GtkSalFrame::SetModal(bool bModal) if (!m_pWindow) return; gtk_window_set_modal(GTK_WINDOW(m_pWindow), bModal); - if (bModal) - { - //gtk_window_set_modal bTrue adds a grab, so ungrab here. Quite - //possibly we should alternatively call grab_add grab_ungrab on - //show/hide of menus ? - gtk_grab_remove(m_pWindow); - } } gboolean GtkSalFrame::signalTooltipQuery(GtkWidget*, gint /*x*/, gint /*y*/, @@ -2600,9 +2582,12 @@ gboolean GtkSalFrame::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer { if( m_nFloats > 0 ) { - // close popups if user clicks outside our application - gint x, y; - bClosePopups = (gdk_display_get_window_at_pointer( GtkSalFrame::getGdkDisplay(), &x, &y ) == nullptr); + // close popups if user clicks outside our menu + if (aEvent.mnX < 0 || aEvent.mnY < 0 || + aEvent.mnX > (long)pThis->maGeometry.nWidth || aEvent.mnY > (long)pThis->maGeometry.nHeight) + { + bClosePopups = true; + } } /* #i30306# release implicit pointer grab if no popups are open; else * Drag cannot grab the pointer and will fail. @@ -2795,7 +2780,7 @@ gboolean GtkSalFrame::signalMotion( GtkWidget*, GdkEventMotion* pEvent, gpointer // ask for the next hint gint x, y; GdkModifierType mask; - gdk_window_get_pointer( widget_get_window(GTK_WIDGET(pThis->m_pWindow)), &x, &y, &mask ); + gdk_window_get_pointer( widget_get_window(GTK_WIDGET(pThis->getMouseEventWidget())), &x, &y, &mask ); } } @@ -2977,15 +2962,28 @@ gboolean GtkSalFrame::signalUnmap( GtkWidget*, GdkEvent*, gpointer frame ) return false; } -gboolean GtkSalFrame::signalKey( GtkWidget*, GdkEventKey* pEvent, gpointer frame ) +gboolean GtkSalFrame::signalKey(GtkWidget* pWidget, GdkEventKey* pEvent, gpointer frame) { GtkSalFrame* pThis = static_cast(frame); + return pThis->handleKey(pWidget, pEvent); +} - vcl::DeletionListener aDel( pThis ); - - if( pThis->m_pIMHandler ) +gboolean GtkSalFrame::handleKey(GtkWidget* pWidget, GdkEventKey* pEvent) +{ + //If we're the type of menu that wants to forward keypresses to our parent + //widget, do that here, this is related to the gtk_grab_add use in + //GtkSalFrame::Show where we want the mouse events to go to us, but + //the keyboard events to go to our parent + if (isFloatGrabWindow() && !getDisplay()->GetCaptureFrame() && m_nFloats == 1 && m_pParent) { - if( pThis->m_pIMHandler->handleKeyEvent( pEvent ) ) + return m_pParent->handleKey(pWidget, pEvent); + } + + vcl::DeletionListener aDel(this); + + if( m_pIMHandler ) + { + if( m_pIMHandler->handleKeyEvent( pEvent ) ) return true; } @@ -3001,13 +2999,13 @@ gboolean GtkSalFrame::signalKey( GtkWidget*, GdkEventKey* pEvent, gpointer frame sal_uInt16 nModCode = GetKeyModCode( pEvent->state ); aModEvt.mnModKeyCode = 0; // emit no MODKEYCHANGE events - if( pEvent->type == GDK_KEY_PRESS && !pThis->m_nKeyModifiers ) - pThis->m_bSendModChangeOnRelease = true; + if( pEvent->type == GDK_KEY_PRESS && !m_nKeyModifiers ) + m_bSendModChangeOnRelease = true; else if( pEvent->type == GDK_KEY_RELEASE && - pThis->m_bSendModChangeOnRelease ) + m_bSendModChangeOnRelease ) { - aModEvt.mnModKeyCode = pThis->m_nKeyModifiers; + aModEvt.mnModKeyCode = m_nKeyModifiers; } sal_uInt16 nExtModMask = 0; @@ -3058,37 +3056,37 @@ gboolean GtkSalFrame::signalKey( GtkWidget*, GdkEventKey* pEvent, gpointer frame if( pEvent->type == GDK_KEY_RELEASE ) { nModCode &= ~nModMask; - pThis->m_nKeyModifiers &= ~nExtModMask; + m_nKeyModifiers &= ~nExtModMask; } else { nModCode |= nModMask; - pThis->m_nKeyModifiers |= nExtModMask; + m_nKeyModifiers |= nExtModMask; } aModEvt.mnCode = nModCode; aModEvt.mnTime = pEvent->time; - aModEvt.mnModKeyCode = pThis->m_nKeyModifiers; + aModEvt.mnModKeyCode = m_nKeyModifiers; - pThis->CallCallback( SALEVENT_KEYMODCHANGE, &aModEvt ); + CallCallback( SALEVENT_KEYMODCHANGE, &aModEvt ); } else { - pThis->doKeyCallback( pEvent->state, - pEvent->keyval, - pEvent->hardware_keycode, - pEvent->group, - pEvent->time, - sal_Unicode(gdk_keyval_to_unicode( pEvent->keyval )), - (pEvent->type == GDK_KEY_PRESS), - false ); + doKeyCallback( pEvent->state, + pEvent->keyval, + pEvent->hardware_keycode, + pEvent->group, + pEvent->time, + sal_Unicode(gdk_keyval_to_unicode( pEvent->keyval )), + (pEvent->type == GDK_KEY_PRESS), + false ); if( ! aDel.isDeleted() ) - pThis->m_bSendModChangeOnRelease = false; + m_bSendModChangeOnRelease = false; } - if( !aDel.isDeleted() && pThis->m_pIMHandler ) - pThis->m_pIMHandler->updateIMSpotLocation(); + if( !aDel.isDeleted() && m_pIMHandler ) + m_pIMHandler->updateIMSpotLocation(); return false; }