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