Gtk2: fixed setCapture(), now it uses new way of capturing, old can be used with -dGTK2_USE_OLD_CAPTURE.

fixed unwanted focus grab of THintWindow.
fixed bug when scrollbar button double clicked, we need 2 clicks to focus our client area. Fixed bugs #13878 #17596.

git-svn-id: trunk@27638 -
This commit is contained in:
zeljko 2010-10-10 15:26:45 +00:00
parent 923c7f1753
commit afb190401d
8 changed files with 107 additions and 22 deletions

View File

@ -1277,11 +1277,12 @@ function gtkMotionNotify(Widget:PGTKWidget; Event: PGDKEventMotion;
var
DesignOnlySignal: boolean;
ShiftState: TShiftState;
{$IFNDEF GTK2_USE_OLD_CAPTURE}
W: PGtkWidget;
{$ENDIF}
begin
Result := CallBackDefaultReturn;
MousePositionValid:=false;
{$IFDEF VerboseMouseBugfix}
DesignOnlySignal:=GetDesignOnlySignalFlag(Widget,dstMouseMotion);
DebugLn('[GTKMotionNotify] ',
@ -1295,12 +1296,22 @@ begin
UpdateMouseCaptureControl;
ShiftState := GTKEventStateToShiftState(Event^.State);
if (MouseCaptureWidget=Widget)
and (MouseCaptureType=mctGTK)
and ([ssLeft,ssRight,ssMiddle]*ShiftState=[]) then begin
if (MouseCaptureWidget = Widget) and (MouseCaptureType = mctGTK) and
([ssLeft,ssRight,ssMiddle]*ShiftState=[]) then
begin
{$IFNDEF GTK2_USE_OLD_CAPTURE}
W := gtk_grab_get_current;
{$ENDIF}
{$IFDEF VerboseMouseCapture}
DebugLn(['gtkMotionNotify gtk capture without mouse down: ',GetWidgetDebugReport(Widget)]);
{$ENDIF}
{$IFNDEF GTK2_USE_OLD_CAPTURE}
if W = nil then
SetCapture(0)
else
gtk_grab_remove(W);
{$ENDIF}
end;
if not (csDesigning in TComponent(Data).ComponentState) then
@ -1331,7 +1342,6 @@ function GTKMotionNotifyAfter(widget:PGTKWidget; event: PGDKEventMotion;
data: gPointer): GBoolean; cdecl;
begin
Result := true; // stop event propagation
MousePositionValid := False;
{$IFDEF VerboseMouseBugfix}
DebugLn('[GTKMotionNotifyAfter] ',
@ -1364,6 +1374,33 @@ begin
end;
end;
{-------------------------------------------------------------------------------
We must stop delivery of events from scrollbars of GtkScrollable, otherwise
if we make an double click on scollbar button, and after that click into
our control client area we need 2 click to make it focused.
gtk_signal_connect_after() is used, otherwise our scrollbar won't react on
such event.
-------------------------------------------------------------------------------}
function gtk2ScrollBarMouseBtnPress(widget: PGtkWidget; event: pgdkEventButton;
data: gPointer): GBoolean; cdecl;
begin
Result := True;
end;
{-------------------------------------------------------------------------------
We must stop delivery of events from scrollbars of GtkScrollable, otherwise
if we make an double click on scollbar button, and after that click into
our control client area we need 2 click to make it focused.
gtk_signal_connect_after() is used, otherwise our scrollbar won't react on
such event.
-------------------------------------------------------------------------------}
function gtk2ScrollBarMouseBtnRelease(widget: PGtkWidget; event: pgdkEventButton;
data: gPointer): GBoolean; cdecl;
begin
Result := True;
end;
{-------------------------------------------------------------------------------
gtkMouseBtnPress
Params: widget: PGTKWidget; event: PGDKEventMotion; data: gPointer
@ -1429,7 +1466,6 @@ var
{$ENDIF}
begin
Result := CallBackDefaultReturn;
MousePositionValid := False;
{$IFDEF VerboseMouseBugfix}
AWinControl := TWinControl(Data);
@ -1640,7 +1676,6 @@ var
end;
begin
MousePositionValid := False;
EventXY := Point(TruncToInt(Event^.X), TruncToInt(Event^.Y));
ShiftState := GTKEventStateToShiftState(Event^.State);
@ -1709,7 +1744,6 @@ function gtkMouseBtnPressAfter(widget: PGtkWidget; event : pgdkEventButton;
data: gPointer) : GBoolean; cdecl;
begin
Result := True;
MousePositionValid := False;
{$IFDEF VerboseMouseBugfix}
debugln('[gtkMouseBtnPressAfter] ',
@ -1822,7 +1856,6 @@ var
DesignOnlySignal: boolean;
begin
Result := CallBackDefaultReturn;
MousePositionValid := False;
{$IFDEF VerboseMouseBugfix}
DesignOnlySignal:=GetDesignOnlySignalFlag(Widget,dstMouseRelease);
@ -1856,7 +1889,6 @@ begin
Result := not CallBackDefaultReturn;
end;
end;
if DeliverMouseUpMessage(Widget, Event, TWinControl(Data)) then
Result := not CallBackDefaultReturn;
end;
@ -1873,7 +1905,6 @@ function gtkMouseBtnReleaseAfter(widget: PGtkWidget; event : pgdkEventButton;
data: gPointer) : GBoolean; cdecl;
begin
Result := True;
MousePositionValid := False;
{$IFDEF VerboseMouseBugfix}
DebugLn('[gtkMouseBtnReleaseAfter] ',DbgSName(TObject(Data)),' ',

View File

@ -61,7 +61,6 @@ var
MouseCaptureWidget: PGtkWidget;
MouseCaptureType: TMouseCaptureType;
MouseCaptureIndex: cardinal;
MousePositionValid: boolean = false;
MousePosition: TPoint;
MousePositionTime: TDateTime;

View File

@ -4467,6 +4467,9 @@ var
OldMouseCaptureWidget,
CurMouseCaptureWidget: PGtkWidget;
begin
{$IFNDEF GTK2_USE_OLD_CAPTURE}
exit;
{$ENDIF}
OldMouseCaptureWidget:=MouseCaptureWidget;
CurMouseCaptureWidget:=gtk_grab_get_current;
@ -4510,7 +4513,7 @@ begin
{$ENDIF}
if not (Owner in [mctGTKIntf,mctLCL]) then exit;
// not every widget can capture the mouse
CaptureWidget:=GetDefaultMouseCaptureWidget(Widget);
CaptureWidget := GetDefaultMouseCaptureWidget(Widget);
if CaptureWidget=nil then exit;
UpdateMouseCaptureControl;
@ -4548,7 +4551,7 @@ var
LCLObject: TObject;
CanCapture: Boolean;
Parent: TWinControl;
{$IFDEF DEBUG_GTK_MOUSECAPTURE}
{$IFDEF VerboseMouseCapture}
CurrentGrab: PGtkWidget;
GrabInfo: PWinWidgetInfo;
{$ENDIF}
@ -4571,7 +4574,6 @@ begin
if CanCapture then
begin
if GTK_IS_NOTEBOOK(PGtkWidget(TWinControl(LCLObject).Handle)) then
exit;
@ -4584,7 +4586,7 @@ begin
WidgetInfo:=GetWidgetInfo(PGtkWidget(TWinControl(LCLObject).Handle),false);
if WidgetInfo <> nil then
begin
{$IFDEF DEBUG_GTK_MOUSECAPTURE}
{$IFDEF VerboseMouseCapture}
CurrentGrab := gtk_grab_get_current;
writeln('GetDefaultMouseCaptureWidget: ',TWinControl(LCLObject).ClassName,' core ',
dbghex(PtrUInt(WidgetInfo^.CoreWidget)),' client ',dbghex(PtrUInt(WidgetInfo^.ClientWidget)),

View File

@ -151,6 +151,14 @@ function ControlGetsMouseDownBefore(AControl: TControl;
AWidget: PGtkWidget): boolean;
procedure DeliverMouseDownMessage(widget: PGtkWidget; event: pgdkEventButton;
AWinControl: TWinControl);
function gtk2ScrollBarMouseBtnPress(widget: PGtkWidget; event: pgdkEventButton;
data: gPointer): GBoolean; cdecl;
function gtk2ScrollBarMouseBtnRelease(widget: PGtkWidget; event: pgdkEventButton;
data: gPointer): GBoolean; cdecl;
function gtkMouseBtnPress(widget: PGtkWidget; event: pgdkEventButton;
data: gPointer): GBoolean; cdecl;
function gtkMouseBtnPressAfter(widget: PGtkWidget; event: pgdkEventButton;

View File

@ -912,8 +912,23 @@ end;
procedure TGtk2WidgetSet.SetCommonCallbacks(const AGTKObject: PGTKObject;
const ALCLObject: TObject);
var
Widget: PGtkWidget;
begin
// original gtk1 code
if GTK_IS_SCROLLED_WINDOW(AGtkObject) then
begin
Widget := PGtkWidget(AGTKObject);
g_signal_connect_after(GTK_SCROLLED_WINDOW(Widget)^.vscrollbar, 'button-press-event',
TGCallback(@gtk2ScrollBarMouseBtnPress), ALCLObject);
g_signal_connect_after(GTK_SCROLLED_WINDOW(Widget)^.vscrollbar, 'button-release-event',
TGCallback(@gtk2ScrollBarMouseBtnRelease), ALCLObject);
g_signal_connect_after(GTK_SCROLLED_WINDOW(Widget)^.hscrollbar, 'button-press-event',
TGCallback(@gtk2ScrollBarMouseBtnPress), ALCLObject);
g_signal_connect_after(GTK_SCROLLED_WINDOW(Widget)^.hscrollbar, 'button-release-event',
TGCallback(@gtk2ScrollBarMouseBtnRelease), ALCLObject);
end;
SetCallback(LM_SHOWWINDOW, AGTKObject, ALCLObject);
SetCallback(LM_DESTROY, AGTKObject, ALCLObject);
SetCallback(LM_FOCUS, AGTKObject, ALCLObject);

View File

@ -7738,6 +7738,9 @@ end;
function TGtk2WidgetSet.SetCapture(AHandle: HWND): HWND;
var
Widget: PGtkWidget;
{$IFNDEF GTK2_USE_OLD_CAPTURE}
CaptureWidget: PGtkWidget;
{$ENDIF}
begin
Assert(False, Format('Trace:> [TGtk2WidgetSet.SetCapture] 0x%x', [AHandle]));
Widget := PGtkWidget(AHandle);
@ -7748,8 +7751,31 @@ begin
// return old capture handle
Result := GetCapture;
{$IFDEF GTK2_USE_OLD_CAPTURE}
// capture
CaptureMouseForWidget(Widget, mctLCL);
{$ELSE}
if Result <> 0 then
gtk_grab_remove(gtk_grab_get_current);
MouseCaptureWidget := nil;
if Widget = nil then
exit;
CaptureWidget := GetDefaultMouseCaptureWidget(Widget);
if CaptureWidget = nil then exit;
if not gtk_widget_has_focus(CaptureWidget) then
gtk_widget_grab_focus(CaptureWidget);
gtk_grab_add(CaptureWidget);
MouseCaptureWidget := CaptureWidget;
if MouseCaptureWidget<>nil then
SendMessage(HWnd(PtrUInt(MouseCaptureWidget)), LM_CAPTURECHANGED, 0,
Result);
{$ENDIF}
end;
{------------------------------------------------------------------------------

View File

@ -228,11 +228,13 @@ begin
gtk_widget_size_allocate(Widget, @Allocation);
Set_RC_Name(AWinControl, Widget);
TGtk2WSWinControl.SetCallbacks(GTK_OBJECT(Widget), AWinControl);
g_signal_connect(GTK_SCROLLED_WINDOW(Widget)^.hscrollbar, 'change-value', TGCallback(@Gtk2RangeScrollCB), WidgetInfo);
g_signal_connect(GTK_SCROLLED_WINDOW(Widget)^.vscrollbar, 'change-value', TGCallback(@Gtk2RangeScrollCB), WidgetInfo);
g_signal_connect(GTK_SCROLLED_WINDOW(Widget)^.hscrollbar, 'change-value',
TGCallback(@Gtk2RangeScrollCB), WidgetInfo);
g_signal_connect(GTK_SCROLLED_WINDOW(Widget)^.vscrollbar, 'change-value',
TGCallback(@Gtk2RangeScrollCB), WidgetInfo);
g_signal_connect(Widget, 'scroll-event', TGCallback(@Gtk2ScrolledWindowScrollCB), WidgetInfo);
end;

View File

@ -813,13 +813,15 @@ var
begin
ACustomForm := TCustomForm(AWinControl);
p := gtk_window_new(gtk_window_popup);
p := gtk_window_new(GTK_WINDOW_POPUP);
WidgetInfo := CreateWidgetInfo(p, AWinControl, AParams);
gtk_window_set_policy(GTK_WINDOW(p), 0, 0, 0);
gtk_window_set_focus_on_map(P, False);
// Create the form client area
TempWidget := CreateFixedClientWidget;
gtk_container_add(p, TempWidget);
GTK_WIDGET_UNSET_FLAGS(TempWidget, GTK_CAN_FOCUS);
gtk_widget_show(TempWidget);
SetFixedWidget(p, TempWidget);
SetMainWidget(p, TempWidget);