View Issue Details

IDProjectCategoryView StatusLast Update
0030235LazarusWidgetsetpublic2020-03-08 17:13
ReporterOndrej Pokorny Assigned ToZeljan Rikalo  
PrioritynormalSeverityminorReproducibilityalways
Status acknowledgedResolutionfixed 
Product Version1.7 (SVN) 
Summary0030235: Non-transparent hint windows don't receive mouse messages when shown from modal windows on Gtk2/Qt
DescriptionWhen no modal form is shown, non-transparent hint windows receive mouse messages. When a modal form is shown, they don't.
Steps To ReproduceSee the attached sample project. Hover with mouse over the label - you'll get a hint window and mouse move coordinates are written to form caption. Click on the button to open the same form as modal dialog -> new hint window doesn't receive mouse messages.
TagsNo tags attached.
Fixed in Revision52880
LazTarget-
WidgetsetGTK 2, QT
Attached Files

Relationships

related to 0030232 closedZeljan Rikalo Request: remove workaround for mouse-transparent forms in Qt 
related to 0031381 resolvedZeljan Rikalo Qt: treeview tooltip: rt-click dont work if clicked over tooltip 
related to 0036773 closedZeljan Rikalo Qt,Qt: THintWindow crash 

Activities

Ondrej Pokorny

2016-06-03 22:30

developer  

transp_demo.lpr (2,477 bytes)

Zeljan Rikalo

2016-06-04 10:26

developer   ~0093008

Qt have same problem, so added to the WS list

Zeljan Rikalo

2016-06-04 10:27

developer  

qthintovermodal.diff (1,132 bytes)   
Index: lcl/interfaces/qt/qtwsforms.pp
===================================================================
--- lcl/interfaces/qt/qtwsforms.pp	(revision 52435)
+++ lcl/interfaces/qt/qtwsforms.pp	(working copy)
@@ -112,6 +112,7 @@
   TQtWSHintWindow = class(TWSHintWindow)
   published
     class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
+    class procedure ShowHide(const AWinControl: TWinControl); override;
   end;
 
   { TQtWSScreen }
@@ -1011,4 +1012,24 @@
   Result := TLCLIntfHandle(QtMainWindow);
 end;
 
+class procedure TQtWSHintWindow.ShowHide(const AWinControl: TWinControl);
+var
+  AWidget: TQtHintWindow;
+begin
+  if not WSCheckHandleAllocated(AWinControl, 'ShowHide') then
+    Exit;
+
+  AWidget := TQtHintWindow(AWinControl.Handle);
+
+  AWidget.BeginUpdate;
+
+  if AWinControl.HandleObjectShouldBeVisible then
+  begin
+    if QApplication_activeModalWidget <> nil then
+      QWidget_setWindowModality(AWidget.Widget, QtWindowModal);
+  end;
+  AWidget.setVisible(AWinControl.HandleObjectShouldBeVisible);
+  AWidget.EndUpdate;
+end;
+
 end.
qthintovermodal.diff (1,132 bytes)   

Zeljan Rikalo

2016-06-04 10:28

developer   ~0093009

Possible patch for Qt attached. IMO, gtk2 can be solved in same way ... just need testing what will happen in this case with real apps.

Zeljan Rikalo

2016-06-04 10:42

developer   ~0093010

hm...gtk2 won't be fixed just like that :(

Luiz Americo

2016-06-04 20:33

developer  

hint-events.diff (2,428 bytes)   
diff --git a/lcl/interfaces/gtk2/gtk2wsforms.pp b/lcl/interfaces/gtk2/gtk2wsforms.pp
index 3e7abbc..f4e9a5a 100644
--- a/lcl/interfaces/gtk2/gtk2wsforms.pp
+++ b/lcl/interfaces/gtk2/gtk2wsforms.pp
@@ -1034,11 +1034,60 @@ class function TGtk2WSHintWindow.CreateHandle(const AWinControl: TWinControl;
   SetCallbacks(P, WidgetInfo);
 end;
 
+function GrabWidgetMotionNotify(Widget:PGTKWidget; Event: PGDKEventMotion;
+  Data: gPointer): GBoolean; cdecl;
+var
+  AWinControl: TWinControl absolute Data;
+  Fixed: PGtkWidget;
+begin
+  Result := CallBackDefaultReturn;
+  //ensure is a HintWindow to avoid clash with the ordinary callback
+  if AWinControl is THintWindow then
+  begin
+    Fixed := GetFixedWidget(PGtkWindow(AWinControl.Handle));
+    Result := gtkMotionNotify(Fixed, Event, AWinControl);
+  end;
+end;
+
+function GrabWidgetButtonPressNotify(Widget:PGTKWidget; Event: PGdkEventButton;
+  Data: gPointer): GBoolean; cdecl;
+var
+  AWinControl: TWinControl absolute Data;
+  Fixed: PGtkWidget;
+begin
+  Result := CallBackDefaultReturn;
+  //ensure is a HintWindow to avoid clash with the ordinary callback
+  if AWinControl is THintWindow then
+  begin
+    Fixed := GetFixedWidget(PGtkWindow(AWinControl.Handle));
+    Result := gtkMouseBtnPress(Fixed, Event, AWinControl);
+  end;
+end;
+
 class procedure TGtk2WSHintWindow.ShowHide(const AWinControl: TWinControl);
+var
+  GrabWidget: PGtkWidget;
+  ShouldBeVisible: Boolean;
 begin
   if not WSCheckHandleAllocated(AWinControl, 'SetColor') then
     exit;
-  Gtk2WidgetSet.SetVisible(AWinControl, AWinControl.HandleObjectShouldBeVisible);
+  ShouldBeVisible := AWinControl.HandleObjectShouldBeVisible;
+  GrabWidget := gtk_grab_get_current;
+  if GrabWidget <> nil then
+  begin
+    if ShouldBeVisible then
+    begin
+      g_signal_connect(GrabWidget, 'motion-notify-event', TGTKSignalFunc(@GrabWidgetMotionNotify), AWinControl);
+      g_signal_connect(GrabWidget, 'button-press-event', TGTKSignalFunc(@GrabWidgetButtonPressNotify), AWinControl);
+    end
+    else
+    begin
+      g_signal_handlers_disconnect_by_func(GrabWidget, TGTKSignalFunc(@GrabWidgetMotionNotify), AWinControl);
+      g_signal_handlers_disconnect_by_func(GrabWidget, TGTKSignalFunc(@GrabWidgetButtonPressNotify), AWinControl);
+    end;
+  end;
+
+  Gtk2WidgetSet.SetVisible(AWinControl, ShouldBeVisible);
   InvalidateLastWFPResult(AWinControl, AWinControl.BoundsRect);
 end;
 
hint-events.diff (2,428 bytes)   

Luiz Americo

2016-06-04 20:40

developer   ~0093019

Here's its what happens:

When a modal is show, a grab is set so motion and button press events from other windows (that are not child, grandchild of the modal form) are intercepted and forwarded to the modal window.

But even this intercepted event is not know by the WidgetSet because the grab forwards the event to the main window and not the layout window, each is the one registered to receive the events.

The attached patch does the inverse. It captures the previously intercepts event and forwards to the event handler with the adjusted params

Luiz Americo

2016-06-04 20:44

developer   ~0093020

There are other ways to fix it:

Set the gtk parent of THintWindow to the grab widget (modal form) -> If we can predict the side effects would be the cheaper solution

Set a Gdk event handler and change the behavior of motion event handling -> too invasive to my taste. The changes of side effects are high it would require heavy testing.

Ondrej Pokorny

2016-06-05 02:16

developer   ~0093022

Last edited: 2016-06-05 02:17

View 2 revisions

@Zeljko: Qt looks/works good. IMO you can apply the patch.

@Luiz: it looks promising, the hint window doesn't receive mouse up/down messages though. Easy test:

procedure TSolidHintWindow.MouseDown(Button: TMouseButton; Shift: TShiftState;
  X, Y: Integer);
begin
  (Owner as TForm).Caption := 'down';
  inherited MouseDown(Button, Shift, X, Y);
end;

procedure TSolidHintWindow.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
  Y: Integer);
begin
  (Owner as TForm).Caption := 'up';
  inherited MouseUp(Button, Shift, X, Y);
end;


Thank you both!

Zeljan Rikalo

2016-06-05 10:46

developer   ~0093035

@Ondrej, you tested Qt patch on windows and mac ?

Ondrej Pokorny

2016-06-05 14:37

developer   ~0093042

> @Ondrej, you tested Qt patch on windows and mac ?

I tested Qt/win and Qt/linux. I cannot test Qt/mac.

Zeljan Rikalo

2016-06-05 15:17

developer   ~0093044

ok, I'll test Qt on osx then

Luiz Americo

2016-06-05 17:16

developer   ~0093047

MouseUp and MouseDown are working here.

Try to set the caption of another label instead of form caption. the mouse move event can override that

Ondrej Pokorny

2016-06-06 09:57

developer  

Ondrej Pokorny

2016-06-06 09:59

developer   ~0093059

Last edited: 2016-06-06 10:00

View 2 revisions

@Luiz: not working here.

If the hint window is above a form, mouse down/up is forwarded to the form bar -> if I click the hint window I start dragging the form underneath.

If the hint window is outside a form, mouse down/up works.

See TrHintGtk2.mp4.

Luiz Americo

2016-06-08 17:53

developer   ~0093081

I tested with Ubuntu 16.4 32bit, Ubuntu-Mate 16.4 64bit and Mint 17.3 64bit.

All working as expected.

Can someone else test?

@ondrej

What's your environment?

Is there any other change in your repository?

The behavior seen in the video is from the first form or in the form opened as modal?

Ondrej Pokorny

2016-06-08 20:58

developer   ~0093082

@Luiz:
> What's your environment?
Kubuntu Linux 13.10 64bit

> Is there any other change in your repository?
No.

> The behavior seen in the video is from the first form or in the form opened as modal?

main form is always OK (with/without patch), modal form behavior changes:

Without your patch:
main form: OK = no dragging through hint window, mouse move/down/up messages are OK.
modal form:
- no dragging through hint window;
- mouse move/down/up messages are not received.

With your patch:
main form: OK = no dragging through hint window, mouse move/down/up messages are OK.
modal form:
- dragging through hint window if hint is above modal form;
- mouse move messages are OK;
- mouse down/up messages are received only if hint window is outside the modal form.

Luiz Americo

2016-06-09 00:25

developer   ~0093085

In GrabWidgetButtonPressNotify, please use the following implementation.

See if the debugln is fired, inside and outside of if AWinControl is THintWindow check.

Also try remove comment of g_signal_stop_emission_by_name. Try also moving g_signal_stop_emission_by_name out of THintWindow check

begin
  Result := CallBackDefaultReturn;
  //ensure is a HintWindow to avoid clash with the ordinary callback
  if AWinControl is THintWindow then
  begin
    Fixed := GetFixedWidget(PGtkWindow(AWinControl.Handle));
    Result := gtkMouseBtnPress(Fixed, Event, AWinControl);
    DebugLn('GrabWidgetButtonPressNotify - HintWindow');
    //g_signal_stop_emission_by_name(Widget, 'button-press-event');
  end;
end;

Zeljan Rikalo

2016-08-28 10:37

developer   ~0094333

Qt part is fixed with r52880, please test

Zeljan Rikalo

2016-08-28 10:37

developer   ~0094334

Gtk2 is still open for good patch.

Issue History

Date Modified Username Field Change
2016-06-03 22:30 Ondrej Pokorny New Issue
2016-06-03 22:30 Ondrej Pokorny File Added: transp_demo.lpr
2016-06-04 10:26 Zeljan Rikalo Widgetset GTK 2 => GTK 2, QT
2016-06-04 10:26 Zeljan Rikalo Note Added: 0093008
2016-06-04 10:27 Zeljan Rikalo File Added: qthintovermodal.diff
2016-06-04 10:28 Zeljan Rikalo Note Added: 0093009
2016-06-04 10:42 Zeljan Rikalo Note Added: 0093010
2016-06-04 14:10 Zeljan Rikalo Relationship added related to 0030232
2016-06-04 20:33 Luiz Americo File Added: hint-events.diff
2016-06-04 20:40 Luiz Americo Note Added: 0093019
2016-06-04 20:44 Luiz Americo Note Added: 0093020
2016-06-05 02:16 Ondrej Pokorny Note Added: 0093022
2016-06-05 02:17 Ondrej Pokorny Note Edited: 0093022 View Revisions
2016-06-05 02:17 Ondrej Pokorny Summary Non-transparent hint windows don't receive mouse messages when shown from modal windows on Gtk2 => Non-transparent hint windows don't receive mouse messages when shown from modal windows on Gtk2/Qt
2016-06-05 10:46 Zeljan Rikalo Note Added: 0093035
2016-06-05 14:37 Ondrej Pokorny Note Added: 0093042
2016-06-05 15:17 Zeljan Rikalo Note Added: 0093044
2016-06-05 17:16 Luiz Americo Note Added: 0093047
2016-06-06 09:57 Ondrej Pokorny File Added: TrHintGtk2.mp4
2016-06-06 09:59 Ondrej Pokorny Note Added: 0093059
2016-06-06 10:00 Ondrej Pokorny Note Edited: 0093059 View Revisions
2016-06-08 17:53 Luiz Americo Note Added: 0093081
2016-06-08 20:58 Ondrej Pokorny Note Added: 0093082
2016-06-09 00:25 Luiz Americo Note Added: 0093085
2016-08-28 10:37 Zeljan Rikalo Fixed in Revision => 52880
2016-08-28 10:37 Zeljan Rikalo Note Added: 0094333
2016-08-28 10:37 Zeljan Rikalo Status new => resolved
2016-08-28 10:37 Zeljan Rikalo Resolution open => fixed
2016-08-28 10:37 Zeljan Rikalo Assigned To => Zeljan Rikalo
2016-08-28 10:37 Zeljan Rikalo Note Added: 0094334
2016-08-28 10:37 Zeljan Rikalo Status resolved => acknowledged
2017-02-13 08:29 Zeljan Rikalo Relationship added related to 0031381
2020-03-08 17:13 Zeljan Rikalo Relationship added related to 0036773