1{ $Id$ }
2{
3                  ----------------------------------------
4                  GtkWSprivate.pp  -  Gtk internal classes
5                  ----------------------------------------
6
7 @created(Thu Feb 1st WET 2007)
8 @lastmod($Date$)
9 @author(Marc Weustink <marc@@lazarus.dommelstein.net>)
10
11 This unit contains the private classhierarchy for the gtk implemetations
12 This hierarchy reflects (more or less) the gtk widget hierarchy
13
14 *****************************************************************************
15  This file is part of the Lazarus Component Library (LCL)
16
17  See the file COPYING.modifiedLGPL.txt, included in this distribution,
18  for details about the license.
19 *****************************************************************************
20}
21
22unit GtkWSPrivate;
23{$mode objfpc}{$H+}
24
25interface
26
27uses
28  // libs
29  {$IFDEF GTK2}
30  Gtk2, Glib2, Gdk2,
31  {$ELSE}
32  Gtk, Glib, Gdk,
33  {$ENDIF}
34  // RTL
35  Classes, SysUtils,
36  // LCL
37  LCLType, LMessages, LCLProc, Controls, Forms,
38  // widgetset
39  WSControls, WSLCLClasses, WSProc,
40  // interface
41  GtkDef, GtkProc, GtkWsControls;
42
43
44type
45  { TGtkPrivate }
46  { Generic base class, don't know if it is needed }
47
48  TGtkPrivate = class(TWSPrivate)
49  private
50  protected
51  public
52  end;
53
54  { TGtkPrivateWidget }
55  { Private class for all gtk widgets }
56
57  TGtkPrivateWidget = class(TGtkPrivate)
58  private
59  protected
60  public
61    class procedure SetZPosition(const AWinControl: TWinControl; const APosition: TWSZPosition); virtual;
62    class procedure UpdateCursor(AInfo: PWidgetInfo); virtual;
63    class procedure SetDefaultCursor(AInfo: PWidgetInfo); virtual;
64  end;
65  TGtkPrivateWidgetClass = class of TGtkPrivateWidget;
66
67  { TGtkPrivateEntry }
68  { Private class for gtkentries (text fields) }
69
70  TGtkPrivateEntry = class(TGtkPrivateWidget)
71  private
72  protected
73  public
74    class procedure SetDefaultCursor(AInfo: PWidgetInfo); override;
75  end;
76
77  { TGtkPrivateContainer }
78  { Private class for gtkcontainers }
79
80  TGtkPrivateContainer = class(TGtkPrivateWidget)
81  private
82  protected
83  public
84  end;
85
86
87  { ------------------------------------}
88  { temp classes to keep things working }
89
90  { TGtkWSScrollingPrivate }
91  { we may want to use something  like a compund class }
92
93  TGtkPrivateScrolling = class(TGtkPrivateContainer)
94  private
95  protected
96  public
97    class procedure SetZPosition(const AWinControl: TWinControl; const APosition: TWSZPosition); override;
98  end;
99
100  TGtkPrivateScrollingWinControl = class(TGtkPrivateScrolling)
101  private
102  protected
103  public
104    class procedure SetZPosition(const AWinControl: TWinControl; const APosition: TWSZPosition); override;
105  end;
106  { ------------------------------------}
107
108
109
110
111  { TGtkPrivateBin }
112  { Private class for gtkbins }
113
114  TGtkPrivateBin = class(TGtkPrivateContainer)
115  private
116  protected
117  public
118  end;
119
120
121  { TGtkPrivateWindow }
122  { Private class for gtkwindows }
123
124  TGtkPrivateWindow = class(TGtkPrivateBin)
125  private
126  protected
127  public
128  end;
129
130
131  { TGtkPrivateDialog }
132  { Private class for gtkdialogs }
133
134  TGtkPrivateDialog = class(TGtkPrivateWindow)
135  private
136  protected
137  public
138  end;
139
140
141  { TGtkPrivateButton }
142  { Private class for gtkbuttons }
143
144  TGtkPrivateButton = class(TGtkPrivateBin)
145  private
146  protected
147  public
148  end;
149
150  { TGtkPrivateList }
151  { Private class for gtklists }
152
153  TGtkPrivateListClass = class of TGtkPrivateList;
154  TGtkPrivateList = class(TGtkPrivateScrolling)
155  private
156  protected
157  public
158    class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); virtual;
159  end;
160
161  { TGtkPrivateNotebook }
162  { Private class for gtknotebooks }
163
164  TGtkPrivateNotebook = class(TGtkPrivateBin)
165  private
166  protected
167  public
168  end;
169
170  { TGtkPrivatePaned }
171  { Private class for gtkpaned }
172  TGtkPrivatePaned = class(TGtkPrivateContainer)
173  private
174  protected
175  public
176    class procedure UpdateCursor(AInfo: PWidgetInfo); override;
177  end;
178
179
180function GetWidgetWithWindow(const AHandle: THandle): PGtkWidget;
181procedure SetWindowCursor(AWindow: PGdkWindow; ACursor: HCursor; ARecursive: Boolean);
182procedure SetCursorForWindowsWithInfo(AWindow: PGdkWindow; AInfo: PWidgetInfo);
183
184implementation
185
186// some circles are needed.
187uses
188  GtkInt;
189
190// Helper functions
191
192function GetWidgetWithWindow(const AHandle: THandle): PGtkWidget;
193var
194  Children: PGList;
195begin
196  Result := PGTKWidget(AHandle);
197  while (Result <> nil) and GTK_WIDGET_NO_WINDOW(Result)
198  and GtkWidgetIsA(Result,gtk_container_get_type) do
199  begin
200    Children := gtk_container_children(PGtkContainer(Result));
201    if Children = nil
202    then Result := nil
203    else Result := Children^.Data;
204  end;
205end;
206
207{------------------------------------------------------------------------------
208  procedure: SetWindowCursor
209  Params:  AWindow : PGDkWindow, ACursor: HCursor, ARecursive: Boolean
210  Returns: Nothing
211
212  Sets the cursor for a window (or recursively for window with children)
213 ------------------------------------------------------------------------------}
214procedure SetWindowCursor(AWindow: PGdkWindow; ACursor: HCursor; ARecursive: Boolean);
215var
216  Cursor: PGdkCursor;
217
218  procedure SetCursorRecursive(AWindow: PGdkWindow);
219  var
220    ChildWindows, ListEntry: PGList;
221  begin
222    gdk_window_set_cursor(AWindow, Cursor);
223
224    ChildWindows := gdk_window_get_children(AWindow);
225
226    ListEntry := ChildWindows;
227    while ListEntry <> nil do
228    begin
229      SetCursorRecursive(PGdkWindow(ListEntry^.Data));
230      ListEntry := ListEntry^.Next;
231    end;
232    g_list_free(ChildWindows);
233  end;
234begin
235  Cursor := PGdkCursor(ACursor);
236  if Cursor = nil then Exit;
237  if ARecursive
238  then SetCursorRecursive(AWindow)
239  else gdk_window_set_cursor(AWindow, Cursor);
240end;
241
242procedure SetCursorForWindowsWithInfo(AWindow: PGdkWindow; AInfo: PWidgetInfo);
243var
244  Cursor: PGdkCursor;
245  Data: gpointer;
246  Info: PWidgetInfo;
247
248  procedure SetCursorRecursive(AWindow: PGdkWindow);
249  var
250    ChildWindows, ListEntry: PGList;
251  begin
252    gdk_window_get_user_data(AWindow, @Data);
253    if (Data <> nil) and GTK_IS_WIDGET(Data) then
254    begin
255      Info := GetWidgetInfo(PGtkWidget(Data), False);
256      if Info = AInfo then
257        gdk_window_set_cursor(AWindow, Cursor);
258    end;
259
260    ChildWindows := gdk_window_get_children(AWindow);
261
262    ListEntry := ChildWindows;
263    while ListEntry <> nil do
264    begin
265      SetCursorRecursive(PGdkWindow(ListEntry^.Data));
266      ListEntry := ListEntry^.Next;
267    end;
268    g_list_free(ChildWindows);
269  end;
270begin
271  if AInfo = nil then Exit;
272  Cursor := PGdkCursor(AInfo^.ControlCursor);
273  if Cursor = nil then Exit;
274  SetCursorRecursive(AWindow);
275end;
276
277{ TGtkPrivateScrolling }
278{ temp class to keep things working }
279
280class procedure TGtkPrivateScrolling.SetZPosition(const AWinControl: TWinControl; const APosition: TWSZPosition);
281var
282  ScrollWidget: PGtkScrolledWindow;
283//  WidgetInfo: PWidgetInfo;
284  Widget: PGtkWidget;
285begin
286  if not WSCheckHandleAllocated(AWincontrol, 'SetZPosition')
287  then Exit;
288
289  ScrollWidget := Pointer(AWinControl.Handle);
290//  WidgetInfo := GetWidgetInfo(ScrollWidget);
291  // Some controls have viewports, so we get the first window.
292  Widget := GetWidgetWithWindow(AWinControl.Handle);
293
294  case APosition of
295    wszpBack:  begin
296      //gdk_window_lower(WidgetInfo^.CoreWidget^.Window);
297      gdk_window_lower(Widget^.Window);
298      if ScrollWidget^.hscrollbar <> nil
299      then gdk_window_lower(ScrollWidget^.hscrollbar^.Window);
300      if ScrollWidget^.vscrollbar <> nil
301      then gdk_window_lower(ScrollWidget^.vscrollbar^.Window);
302    end;
303    wszpFront: begin
304      //gdk_window_raise(WidgetInfo^.CoreWidget^.Window);
305      gdk_window_raise(Widget^.Window);
306      if ScrollWidget^.hscrollbar <> nil
307      then gdk_window_raise(ScrollWidget^.hscrollbar^.Window);
308      if ScrollWidget^.vscrollbar <> nil
309      then gdk_window_raise(ScrollWidget^.vscrollbar^.Window);
310    end;
311  end;
312end;
313
314{ TGtkPrivateScrollingWinControl }
315
316class procedure TGtkPrivateScrollingWinControl.SetZPosition(
317  const AWinControl: TWinControl; const APosition: TWSZPosition);
318var
319  Widget: PGtkWidget;
320  ScrollWidget: PGtkScrolledWindow;
321//  WidgetInfo: PWidgetInfo;
322begin
323  if not WSCheckHandleAllocated(AWincontrol, 'SetZPosition')
324  then Exit;
325
326  //TODO: when all scrolling controls are "derived" from TGtkWSBaseScrollingWinControl
327  //      retrieve scrollbars from WidgetInfo^.Userdata. In that case, the following
328  //      code can be removed and a call to TGtkWSBaseScrollingWinControl.SetZPosition
329  //      can be made. This is not possible now since we have a frame around us
330
331  Widget := Pointer(AWinControl.Handle);
332  //  WidgetInfo := GetWidgetInfo(Widget);
333
334  // Only do the scrollbars, leave the core to the default (we might have a viewport)
335  TGtkPrivateWidget.SetZPosition(AWinControl, APosition);
336
337  if GtkWidgetIsA(Widget, gtk_frame_get_type) then
338    ScrollWidget := PGtkScrolledWindow(PGtkFrame(Widget)^.Bin.Child)
339  else
340  if GtkWidgetIsA(Widget, gtk_scrolled_window_get_type) then
341    ScrollWidget := PGtkScrolledWindow(Widget)
342  else
343    ScrollWidget := nil;
344
345  if ScrollWidget <> nil then
346  begin
347    case APosition of
348      wszpBack:  begin
349        // gdk_window_lower(WidgetInfo^.CoreWidget^.Window);
350        if ScrollWidget^.hscrollbar <> nil then
351        begin
352          {$ifndef gtk1}
353          if GDK_IS_WINDOW(ScrollWidget^.hscrollbar^.Window) then
354          {$endif}
355            gdk_window_lower(ScrollWidget^.hscrollbar^.Window);
356        end;
357
358        if ScrollWidget^.vscrollbar <> nil then
359        begin
360          {$ifndef gtk1}
361          if GDK_IS_WINDOW(ScrollWidget^.vscrollbar^.Window) then
362          {$endif}
363            gdk_window_lower(ScrollWidget^.vscrollbar^.Window);
364        end;
365      end;
366      wszpFront: begin
367        // gdk_window_raise(WidgetInfo^.CoreWidget^.Window);
368        if ScrollWidget^.hscrollbar <> nil then
369        begin
370          {$ifndef gtk1}
371          if GDK_IS_WINDOW(ScrollWidget^.hscrollbar^.Window) then
372          {$endif}
373            gdk_window_raise(ScrollWidget^.hscrollbar^.Window);
374        end;
375        if ScrollWidget^.vscrollbar <> nil then
376        begin
377          {$ifndef gtk1}
378          if GDK_IS_WINDOW(ScrollWidget^.vscrollbar^.Window) then
379          {$endif}
380            gdk_window_raise(ScrollWidget^.vscrollbar^.Window);
381        end;
382      end;
383    end;
384  end;
385end;
386
387{$I gtkprivatewidget.inc}
388{$I gtkprivatelist.inc}
389
390end.
391
392