51
51
TGtk2WSDragImageList = class(TWSDragImageList)
53
class function BeginDrag(const ADragImageList: TDragImageList; Window: HWND; AIndex, X, Y: Integer): Boolean; override;
54
class function DragMove(const ADragImageList: TDragImageList; X, Y: Integer): Boolean; override;
55
class procedure EndDrag(const ADragImageList: TDragImageList); override;
56
class function HideDragImage(const ADragImageList: TDragImageList;
57
ALockedWindow: HWND; DoUnLock: Boolean): Boolean; override;
58
class function ShowDragImage(const ADragImageList: TDragImageList;
59
ALockedWindow: HWND; X, Y: Integer; DoLock: Boolean): Boolean; override;
53
class function BeginDrag(const ADragImageList: TDragImageList; {%H-}Window: HWND; AIndex, X, Y: Integer): Boolean; override;
54
class function DragMove(const {%H-}ADragImageList: TDragImageList; X, Y: Integer): Boolean; override;
55
class procedure EndDrag(const {%H-}ADragImageList: TDragImageList); override;
56
class function HideDragImage(const {%H-}ADragImageList: TDragImageList;
57
{%H-}ALockedWindow: HWND; {%H-}DoUnLock: Boolean): Boolean; override;
58
class function ShowDragImage(const {%H-}ADragImageList: TDragImageList;
59
{%H-}ALockedWindow: HWND; X, Y: Integer; {%H-}DoLock: Boolean): Boolean; override;
88
88
class procedure SetBorderStyle(const AWinControl: TWinControl; const ABorderStyle: TBorderStyle); override;
89
89
class procedure SetBounds(const AWinControl: TWinControl; const ALeft, ATop, AWidth, AHeight: Integer); override;
90
class procedure SetChildZPosition(const AWinControl, AChild: TWinControl; const AOldPos, ANewPos: Integer; const AChildren: TFPList); override;
90
class procedure SetChildZPosition(const AWinControl, AChild: TWinControl; const {%H-}AOldPos, ANewPos: Integer; const AChildren: TFPList); override;
91
91
class procedure SetColor(const AWinControl: TWinControl); override;
92
92
class procedure SetCursor(const AWinControl: TWinControl; const ACursor: HCursor); override;
93
93
class procedure SetFont(const AWinControl: TWinControl; const AFont: TFont); override;
147
147
function GetWidgetHAdjustment(AWidget: PGTKWidget): PGTKAdjustment;
148
148
function GetWidgetVAdjustment(AWidget: PGTKWidget): PGTKAdjustment;
151
HasWarnedLibOverlay: boolean = false;
153
Gtk2Int, LMessages, Math, Gtk2WSPrivate, Forms;
156
Gtk2Int, LMessages, Gtk2WSPrivate, Forms;
155
158
{ TGtk2WSWinControl }
157
function Gtk2ScrolledWindowScrollCB(AScrollWindow: PGtkScrolledWindow; AEvent: PGdkEventScroll; AWidgetInfo: PWidgetInfo): gboolean; cdecl;
163
case AEvent^.direction of
165
GDK_SCROLL_DOWN: Msg.Msg := LM_VSCROLL;
167
GDK_SCROLL_RIGHT: Msg.Msg := LM_HSCROLL;
171
LM_VSCROLL: Range := GTK_RANGE(AScrollWindow^.vscrollbar);
172
LM_HSCROLL: Range := GTK_RANGE(AScrollWindow^.hscrollbar);
175
AValue := power(Range^.adjustment^.page_size, 2 / 3);
177
if (AEvent^.direction = GDK_SCROLL_UP) or
178
(AEvent^.direction = GDK_SCROLL_LEFT)
182
AValue := gtk_range_get_value(Range) + AValue;
184
AValue := Max(AValue, Range^.adjustment^.lower);
185
AValue := Min(AValue, Range^.adjustment^.upper - Range^.adjustment^.page_size);
189
Pos := Round(AValue);
190
if Pos < High(SmallPos) then
193
SmallPos := High(SmallPos);
195
ScrollBar := HWND(PtrUInt(Range));
196
ScrollCode := SB_THUMBPOSITION;
198
Result := DeliverMessage(AWidgetInfo^.LCLObject, Msg) <> 0;
202
161
class function TGtk2WSWinControl.CreateHandle(const AWinControl: TWinControl;
203
162
const AParams: TCreateParams): HWND;
205
164
Widget: PGtkWidget;
206
165
WidgetInfo: PWidgetInfo;
207
166
Allocation: TGTKAllocation;
167
ScrollBar: PGtkWidget;
168
Adjustment: PGtkAdjustment;
209
170
Widget := GTK2WidgetSet.CreateAPIWidget(AWinControl);
210
171
{$IFDEF DebugLCLComponents}
211
172
DebugGtkWidgets.MarkCreated(Widget, dbgsName(AWinControl));
214
Result := THandle(PtrUInt(Widget));
175
Result := THandle({%H-}PtrUInt(Widget));
215
176
if Result = 0 then Exit;
217
178
WidgetInfo := GetWidgetInfo(Widget); // Widget info already created in CreateAPIWidget
218
179
WidgetInfo^.Style := AParams.Style;
219
180
WidgetInfo^.ExStyle := AParams.ExStyle;
220
WidgetInfo^.WndProc := PtrUInt(AParams.WindowClass.lpfnWndProc);
181
WidgetInfo^.WndProc := {%H-}PtrUInt(AParams.WindowClass.lpfnWndProc);
222
183
// set allocation
223
184
Allocation.X := AParams.X;
231
192
TGtk2WSWinControl.SetCallbacks(GTK_OBJECT(Widget), AWinControl);
233
g_signal_connect(GTK_SCROLLED_WINDOW(Widget)^.hscrollbar, 'change-value',
234
TGCallback(@Gtk2RangeScrollCB), WidgetInfo);
235
g_signal_connect(GTK_SCROLLED_WINDOW(Widget)^.vscrollbar, 'change-value',
236
TGCallback(@Gtk2RangeScrollCB), WidgetInfo);
195
if (GetWidgetClassName(GTK_SCROLLED_WINDOW(Widget)^.vscrollbar)='OsScrollbar')
196
or (GetWidgetClassName(GTK_SCROLLED_WINDOW(Widget)^.hscrollbar)='OsScrollbar')
198
// ubuntu liboverlay scrollbar is active
199
if not HasWarnedLibOverlay then begin
200
HasWarnedLibOverlay:=true;
201
debugln(['WARNING: liboverlay_scrollbar is active for control=',AWinControl,'. Set environment option LIBOVERLAY_SCROLLBAR=0 before starting this application, otherwise scrollbars will not work properly.']);
205
ScrollBar:=GTK_SCROLLED_WINDOW(Widget)^.hscrollbar;
206
if (GetWidgetClassName(ScrollBar)='OsScrollbar')
208
// the ubuntu scroll bar eats the change-value signal => use value-changed
209
Adjustment:=gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(Widget));
210
g_signal_connect_after(Adjustment, 'value-changed',TGCallback(@Gtk2RangeUbuntuScrollCB), WidgetInfo);
212
g_signal_connect_after(ScrollBar, 'change-value',
213
TGCallback(@Gtk2RangeScrollCB), WidgetInfo);
216
ScrollBar:=GTK_SCROLLED_WINDOW(Widget)^.vscrollbar;
217
if (GetWidgetClassName(ScrollBar)='OsScrollbar')
219
// the ubuntu scroll bar eats the change-value signal => use value-changed
220
Adjustment:=gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(Widget));
221
g_signal_connect_after(Adjustment, 'value-changed',TGCallback(@Gtk2RangeUbuntuScrollCB), WidgetInfo);
223
g_signal_connect_after(ScrollBar, 'change-value',
224
TGCallback(@Gtk2RangeScrollCB), WidgetInfo);
227
g_signal_connect(GTK_SCROLLED_WINDOW(Widget)^.hscrollbar, 'button-press-event',
228
TGCallback(@Gtk2RangeScrollPressCB), WidgetInfo);
229
g_signal_connect(GTK_SCROLLED_WINDOW(Widget)^.hscrollbar, 'button-release-event',
230
TGCallback(@Gtk2RangeScrollReleaseCB), WidgetInfo);
231
g_signal_connect(GTK_SCROLLED_WINDOW(Widget)^.vscrollbar, 'button-press-event',
232
TGCallback(@Gtk2RangeScrollPressCB), WidgetInfo);
233
g_signal_connect(GTK_SCROLLED_WINDOW(Widget)^.vscrollbar, 'button-release-event',
234
TGCallback(@Gtk2RangeScrollReleaseCB), WidgetInfo);
238
236
g_signal_connect(Widget, 'scroll-event', TGCallback(@Gtk2ScrolledWindowScrollCB), WidgetInfo);
249
247
if not WSCheckHandleAllocated(AWinControl, 'SetBiDiMode') then
251
gtk_widget_set_direction(PGtkWidget(AWinControl.Handle),
249
gtk_widget_set_direction({%H-}PGtkWidget(AWinControl.Handle),
252
250
WidgetDirection[UseRightToLeftAlign]);
253
Info := GetWidgetInfo(PGtkWidget(AWinControl.Handle));
251
Info := GetWidgetInfo({%H-}PGtkWidget(AWinControl.Handle));
254
252
if Info <> nil then
256
254
if Info^.CoreWidget <> nil then
276
274
case AWinControl.fCompStyle of
279
AText := StrPas(gtk_entry_get_text(PGtkEntry(PGtkCombo(Handle)^.entry)));
277
AText := StrPas(gtk_entry_get_text(PGtkEntry({%H-}PGtkCombo(Handle)^.entry)));
283
AText:= StrPas(gtk_entry_get_text(PgtkEntry(Handle)));
280
csEdit: AText:= StrPas(gtk_entry_get_text({%H-}PgtkEntry(Handle)));
281
csSpinEdit: AText:= StrPas(gtk_entry_get_text(@{%H-}PGtkSpinButton(Handle)^.entry));
287
CS := gtk_editable_get_chars(PGtkOldEditable(
288
GetWidgetInfo(Pointer(Handle), True)^.CoreWidget), 0, -1);
286
CS := gtk_editable_get_chars(PGtkEditable(
287
GetWidgetInfo({%H-}Pointer(Handle), True)^.CoreWidget), 0, -1);
289
288
AText := StrPas(CS);
309
308
case AWinControl.fCompStyle of
312
TextBuf := gtk_text_view_get_buffer(PGtkTextView(GetWidgetInfo(Pointer(Handle), True)^.CoreWidget));
311
TextBuf := gtk_text_view_get_buffer(PGtkTextView(GetWidgetInfo({%H-}Pointer(Handle), True)^.CoreWidget));
313
312
gtk_text_buffer_get_start_iter(TextBuf, @StartIter);
314
313
gtk_text_buffer_get_end_iter(TextBuf, @EndIter);
315
314
CS := gtk_text_buffer_get_text(TextBuf, @StartIter, @EndIter, False);
467
466
TWinControlHack = class(TWinControl)
469
function Gtk2TreeViewEditorEvent(widget: PGtkWidget; event: PGdkEvent; data: GPointer): gboolean; cdecl;
472
Alloc: TGtkAllocation;
474
AOrientation: TGtkOrientation;
476
Result := CallBackDefaultReturn;
480
// cheat GtkTreeView container , so we are visible and ready for input.
481
if event^.focus_change._in = 1 then
483
R := TWinControl(Data).BoundsRect;
490
Alloc.width := Right - Left;
491
Alloc.height := Bottom - Top;
493
gtk_widget_size_allocate(Widget, @Alloc);
497
w := gtk_widget_get_parent(Widget);
498
if Assigned(w) and GTK_IS_ICON_VIEW(w) then
500
//gtk2 does not layout items correctly when iconArrangement is iaTop.
501
//so we force it to do so.
502
AOrientation := gtk_icon_view_get_orientation(PGtkIconView(w));
503
if AOrientation = GTK_ORIENTATION_HORIZONTAL then
504
gtk_icon_view_set_orientation(PGtkIconView(w), GTK_ORIENTATION_VERTICAL)
506
gtk_icon_view_set_orientation(PGtkIconView(w), GTK_ORIENTATION_HORIZONTAL);
507
gtk_icon_view_set_orientation(PGtkIconView(w), AOrientation)
470
514
class procedure TGtk2WSWinControl.AddControl(const AControl: TControl);
472
516
AParent: TWinControl;
482
526
AParent := TWinControl(AControl).Parent;
483
//debugln('LM_AddChild: ',TWinControl(Sender).Name,' ',dbgs(AParent<>nil));
527
// DebugLn('LM_AddChild: ',dbgsName(AControl),' ',dbgs(AParent<>nil));
484
528
if not Assigned(AParent) then
485
529
Assert(true, Format('Trace: [TGtkWSWinControl.AddControl] %s --> Parent is not assigned', [AControl.ClassName]))
488
Assert(False, Format('Trace: [TGtkWSWinControl.AddControl] %s --> Calling Add Child: %s', [AParent.ClassName, AControl.ClassName]));
489
ParentWidget := Pgtkwidget(AParent.Handle);
532
// DebugLn(Format('Trace: [TGtkWSWinControl.AddControl] %s --> Calling Add Child: %s', [AParent.ClassName, AControl.ClassName]));
534
ParentWidget := {%H-}PGtkwidget(AParent.Handle);
490
535
pFixed := GetFixedWidget(ParentWidget);
491
if pFixed <> ParentWidget then
493
// parent changed for child
494
ChildWidget := PGtkWidget(TWinControl(AControl).Handle);
495
FixedPutControl(pFixed, ChildWidget, AControl.Left, AControl.Top);
496
RegroupAccelerator(ChildWidget);
537
// gtk2 is pretty tricky about adding editor into control
538
if (AParent.FCompStyle = csListView) and
539
(TWinControl(AControl).FCompStyle = csEdit) then
541
ChildWidget := {%H-}PGtkWidget(TWinControl(AControl).Handle);
542
ParentWidget := gtk_bin_get_child(PGtkBin(PFixed)); // treeview
543
// MUST allocate some size before adding it to container !
544
gtk_widget_set_size_request(ChildWidget, 80, 25);
545
gtk_widget_set_parent(ChildWidget, ParentWidget);
546
// now we connect our GtkEntry directly to event filter
547
g_signal_connect(PGtkObject(ChildWidget), 'event',
548
gtk_signal_func(@Gtk2TreeViewEditorEvent), AControl);
551
if pFixed <> ParentWidget then
553
// parent changed for child
554
ChildWidget := {%H-}PGtkWidget(TWinControl(AControl).Handle);
555
FixedPutControl(pFixed, ChildWidget, AControl.Left, AControl.Top);
556
RegroupAccelerator(ChildWidget);
608
win_gravity := gtk_window_get_gravity(PGtkWindow(Widget));
548
610
//debugln('TGtk2WSWinControl.ConstraintsChange A ',GetWidgetDebugReport(Widget),' max=',dbgs(Geometry.max_width),'x',dbgs(Geometry.max_height));
549
611
gtk_window_set_geometry_hints(PGtkWindow(Widget), nil, @Geometry,
550
GDK_HINT_MIN_SIZE or GDK_HINT_MAX_SIZE);
612
GDK_HINT_POS or GDK_HINT_MIN_SIZE or GDK_HINT_MAX_SIZE);
562
624
if not WSCheckHandleAllocated(AWinControl, 'Invalidate')
565
Assert(false, 'Trace:Trying to invalidate window... !!!');
566
gtk_widget_queue_draw(PGtkWidget(AWinControl.Handle));
627
//DebugLn('Trace:Trying to invalidate window... !!!');
628
gtk_widget_queue_draw({%H-}PGtkWidget(AWinControl.Handle));
569
631
class procedure TGtk2WSWinControl.ShowHide(const AWinControl: TWinControl);
628
690
class procedure TGtk2WSWinControl.SetCursor(const AWinControl: TWinControl; const ACursor: HCursor);
630
692
WidgetInfo: PWidgetInfo;
632
695
if not WSCheckHandleAllocated(AWinControl, 'SetCursor')
635
WidgetInfo := GetWidgetInfo(Pointer(AWinControl.Handle));
636
if (WidgetInfo^.ControlCursor = ACursor) and
637
(WidgetInfo^.DefaultCursor <> HCursor(-1)) then Exit;
638
698
if ACursor <> Screen.Cursors[crDefault] then
639
WidgetInfo^.ControlCursor := ACursor
702
WidgetInfo := GetWidgetInfo({%H-}Pointer(AWinControl.Handle));
703
if WidgetInfo^.ControlCursor <> NewCursor then
642
if WidgetInfo^.DefaultCursor = HCursor(-1) then
643
TGtkPrivateWidgetClass(AWinControl.WidgetSetClass.WSPrivate).SetDefaultCursor(WidgetInfo);
644
WidgetInfo^.ControlCursor := WidgetInfo^.DefaultCursor;
705
WidgetInfo^.ControlCursor := NewCursor;
706
TGtkPrivateWidgetClass(AWinControl.WidgetSetClass.WSPrivate).UpdateCursor(WidgetInfo);
646
TGtkPrivateWidgetClass(AWinControl.WidgetSetClass.WSPrivate).UpdateCursor(WidgetInfo);
649
710
class procedure TGtk2WSWinControl.SetFont(const AWinControl: TWinControl;
678
739
DebugLn(['TGtk2WSWinControl.SetPos ',DbgSName(AWinControl),' ',ALeft,',',ATop]);
681
Widget := PGtkWidget(AWinControl.Handle);
742
Widget := {%H-}PGtkWidget(AWinControl.Handle);
682
743
Allocation.X := gint16(ALeft);
683
744
Allocation.Y := gint16(ATop);
684
745
Allocation.Width := guint16(Widget^.Allocation.Width);
698
759
DebugLn(['TGtk2WSWinControl.SetSize ',DbgSName(AWinControl),' ',AWidth,',',AHeight]);
701
Widget := PGtkWidget(AWinControl.Handle);
762
Widget := {%H-}PGtkWidget(AWinControl.Handle);
702
763
Allocation.X := Widget^.Allocation.X;
703
764
Allocation.Y := Widget^.Allocation.Y;
704
765
Allocation.Width := guint16(AWidth);
711
772
if not WSCheckHandleAllocated(AWinControl, 'SetColor')
775
// do not change color of scrollbar. issue #22996
776
if (AWinControl.FCompStyle = csScrollBar) then
714
779
if ((csOpaque in AWinControl.ControlStyle) and
715
GtkWidgetIsA(pGtkWidget(AWinControl.handle),GTKAPIWidget_GetType)) then
780
GtkWidgetIsA({%H-}pGtkWidget(AWinControl.handle),GTKAPIWidget_GetType)) then
718
783
//DebugLn('TGtk2WSWinControl.SetColor ',DbgSName(AWinControl));
719
Gtk2WidgetSet.SetWidgetColor(PGtkWidget(AWinControl.Handle),
784
Gtk2WidgetSet.SetWidgetColor({%H-}PGtkWidget(AWinControl.Handle),
720
785
AWinControl.Font.Color, AWinControl.Color,
721
786
[GTK_STATE_NORMAL, GTK_STATE_ACTIVE,
722
787
GTK_STATE_PRELIGHT, GTK_STATE_SELECTED]);
772
837
//TODO: create classprocedures for this in the corresponding classes
774
P := Pointer(AWinControl.Handle);
775
Assert(p = nil, 'Trace:WARNING: [TGtkWidgetSet.SetLabel] --> got nil pointer');
776
Assert(False, 'Trace:Setting Str1 in SetLabel');
839
P := {%H-}Pointer(AWinControl.Handle);
840
Assert(p <> nil, 'Trace:WARNING: [TGtkWidgetSet.SetLabel] --> got nil pointer');
841
//DebugLn('Trace:Setting Str1 in SetLabel');
777
842
pLabel := pchar(AText);
779
844
case AWinControl.fCompStyle of
791
856
//Accel := Ampersands2Underscore(aLabel);
792
857
if gtk_bin_get_child(P) = nil then
794
Assert(False, Format('trace: [TGtkWidgetSet.SetLabel] %s has no child label', [AWinControl.ClassName]));
859
//DebugLn(Format('trace: [TGtkWidgetSet.SetLabel] %s has no child label', [AWinControl.ClassName]));
795
860
gtk_container_add(P, gtk_label_new(aLabel));
798
Assert(False, Format('trace: [TGtkWidgetSet.SetLabel] %s has child label', [AWinControl.ClassName]));
863
//DebugLn(Format('trace: [TGtkWidgetSet.SetLabel] %s has child label', [AWinControl.ClassName]));
799
864
gtk_label_set_text(pgtkLabel( gtk_bin_get_child(P)), aLabel);
801
866
//If Accel <> -1 then
877
942
if not WSCheckHandleAllocated(AWinControl, 'SetShape') then
880
GtkWidget := PGtkWidget(AWinControl.Handle);
945
GtkWidget := {%H-}PGtkWidget(AWinControl.Handle);
881
946
FixedWidget := GetFixedWidget(GtkWidget);
883
948
if AShape <> 0 then
885
950
if Gtk2Widgetset.IsValidGDIObjectType(AShape, gdiBitmap) then
886
GdkBitmap := PGdiObject(AShape)^.GDIBitmapObject
951
GdkBitmap := {%H-}PGdiObject(AShape)^.GDIBitmapObject
888
953
GdkBitmap := nil;
904
969
DC: TGtkDeviceContext absolute ADC;
971
procedure PaintGtkForm(AWindow: PGdkWindow);
975
MenuPixBuf: PGdkPixBuf;
976
AMenuBar: PGtkWidget;
982
if Assigned(TCustomForm(AWinControl).Menu) then
984
AMenuBar := {%H-}PGtkWidget(TCustomForm(AWinControl).Menu.Handle);
985
if GTK_IS_MENU_BAR(AMenuBar) and GTK_WIDGET_VISIBLE(AMenuBar) then
987
OffsetY := AMenuBar^.allocation.height;
988
MenuPixbuf := gdk_pixbuf_get_from_drawable(nil, AMenuBar^.Window, nil,
989
0, 0, 0, 0, AMenuBar^.allocation.Width, AMenuBar^.Allocation.Height);
991
gdk_pixbuf_render_to_drawable(MenuPixbuf, DC.Drawable, DC.GC, 0, 0, X, Y + OffsetY,
992
AMenuBar^.allocation.Width, AMenuBar^.Allocation.Height, GDK_RGB_DITHER_NONE, 0, 0);
994
gdk_pixbuf_unref(MenuPixbuf);
997
gdk_window_get_size(AWindow, @W, @H);
999
Pixbuf := gdk_pixbuf_get_from_drawable(nil, AWindow, nil,
1002
// put menubar into form screenshoot too
1003
if OffsetY <> 0 then
1005
MenuPixBuf := gdk_pixbuf_scale_simple(PixBuf, W, H - OffsetY,GDK_INTERP_NEAREST);
1006
gdk_pixbuf_render_to_drawable(MenuPixbuf, DC.Drawable, DC.GC, 0, 0, X, Y + (OffsetY * 2),
1007
-1, -1, GDK_RGB_DITHER_NONE, 0, 0);
1008
if MenuPixBuf <> nil then
1009
gdk_pixbuf_unref(MenuPixBuf);
1011
gdk_pixbuf_render_to_drawable(Pixbuf, DC.Drawable, DC.GC, 0, 0, X, Y,
1012
-1, -1, GDK_RGB_DITHER_NONE, 0, 0);
1014
gdk_pixbuf_unref(Pixbuf);
906
1017
procedure PaintWindow(AWindow: PGdkWindow);
920
1031
procedure PaintWidget(AWidget: PGtkWidget);
923
1033
AWindow: PGdkWindow;
925
AWindow := GetControlWindow(AWidget);
927
if AWindow <> nil then
928
PaintWindow(AWindow);
1035
if (AWinControl.FCompStyle = csForm) then
1036
PaintGtkForm(AWidget^.window)
1039
AWindow := GetControlWindow(AWidget);
1040
if AWindow <> nil then
1041
PaintWindow(AWindow);
932
if not WSCheckHandleAllocated(AWinControl, 'PaintTo')
934
PaintWidget(GetFixedWidget(PGtkWidget(AWinControl.Handle)));
1046
if not WSCheckHandleAllocated(AWinControl, 'PaintTo') then
1048
PaintWidget(GetFixedWidget({%H-}PGtkWidget(AWinControl.Handle)));
937
1051
{ TGtk2WSBaseScrollingWinControl }