You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

226 lines
6.8 KiB

  1. unit uglcContextGtkCustomVisual;
  2. { Package: OpenGLCore
  3. Prefix: glc - OpenGL Core
  4. Beschreibung: diese Unit enthält Klassen zum Erzeugen von Visuals (unter Linux),
  5. auf denen ein OpenGL Kontext erstellt werden kann }
  6. {$mode objfpc}{$H+}
  7. interface
  8. uses
  9. Classes, SysUtils, Controls, LCLType, InterfaceBase, LMessages, WSLCLClasses, WSControls,
  10. X, XLib, glib2, gdk2, gdk2x, gtk2, Gtk2Def, Gtk2Int;
  11. type
  12. TCustomVisualControl = class(TWinControl)
  13. private
  14. FIntWidget: PGtkWidget;
  15. FVisualID: TVisualID;
  16. protected
  17. function WSCreateHandle({%H-}const WSPrivate: TWSPrivateClass; const AParams: TCreateParams): TLCLIntfHandle;
  18. procedure WSBeforeDestroyHandle;
  19. public
  20. constructor Create(TheOwner: TComponent; const aVisualID: TVisualID); overload;
  21. property Widget: PGtkWidget read FIntWidget;
  22. end;
  23. TWSCustomVisualControl = class(TWSWinControl)
  24. published
  25. class function CreateHandle(const AWinControl: TWinControl;
  26. const AParams: TCreateParams): TLCLIntfHandle; override;
  27. class procedure DestroyHandle(const AWinControl: TWinControl); override;
  28. end;
  29. implementation
  30. type
  31. PGtkCustomWidget = ^TGtkCustomWidget;
  32. TGtkCustomWidget = record
  33. darea: TGtkDrawingArea;
  34. end;
  35. PGtkCustomWidgetClass = ^TGtkCustomWidgetClass;
  36. TGtkCustomWidgetClass = record
  37. parent_class: TGtkDrawingAreaClass;
  38. end;
  39. var
  40. custom_widget_type: TGtkType = 0;
  41. custom_widget_parent_class: Pointer = nil;
  42. function GTK_TYPE_CUSTOM_WIDGET: TGtkType; forward;
  43. procedure g_return_if_fail(b: boolean; const Msg: string);
  44. begin
  45. if not b then raise Exception.Create(Msg);
  46. end;
  47. procedure g_return_if_fail(b: boolean);
  48. begin
  49. g_return_if_fail(b,'');
  50. end;
  51. function GTK_IS_CUSTOM_WIDGET(obj: Pointer): Boolean;
  52. begin
  53. GTK_IS_CUSTOM_WIDGET:=GTK_CHECK_TYPE(obj,GTK_TYPE_CUSTOM_WIDGET);
  54. end;
  55. function GTK_CUSTOM_WIDGET(obj: Pointer): PGtkCustomWidget;
  56. begin
  57. g_return_if_fail(GTK_IS_CUSTOM_WIDGET(obj),'');
  58. Result:=PGtkCustomWidget(obj);
  59. end;
  60. procedure gtk_custom_widget_init(custom_widget: PGTypeInstance; theClass: gpointer); cdecl;
  61. begin
  62. if theClass=nil then ;
  63. //DebugLn(['gtk_custom_widget_init START']);
  64. gtk_widget_set_double_buffered(PGtkWidget(custom_widget),gdkFALSE);
  65. GTK_WIDGET_UNSET_FLAGS(PGtkWidget(custom_widget),GTK_NO_WINDOW);
  66. //DebugLn(['gtk_custom_widget_init END']);
  67. end;
  68. procedure gtk_custom_widget_destroy(obj: PGtkObject); cdecl;
  69. begin
  70. g_return_if_fail (obj <>nil,'');
  71. g_return_if_fail (GTK_IS_CUSTOM_WIDGET(obj),'');
  72. if Assigned(GTK_OBJECT_CLASS(custom_widget_parent_class)^.destroy) then
  73. GTK_OBJECT_CLASS(custom_widget_parent_class)^.destroy(obj);
  74. end;
  75. procedure gtk_custom_widget_class_init(klass: Pointer); cdecl;
  76. var
  77. object_class: PGtkObjectClass;
  78. begin
  79. custom_widget_parent_class := gtk_type_class(gtk_drawing_area_get_type());
  80. g_return_if_fail(custom_widget_parent_class<>nil,'gtk_custom_widget_class_init parent_class=nil');
  81. object_class := PGtkObjectClass(klass);
  82. g_return_if_fail(object_class<>nil,'gtk_custom_widget_class_init object_class=nil');
  83. object_class^.destroy := @gtk_custom_widget_destroy;
  84. end;
  85. function custom_widget_size_allocateCB(Widget: PGtkWidget; Size: pGtkAllocation;
  86. Data: gPointer): GBoolean; cdecl;
  87. const
  88. CallBackDefaultReturn = {$IFDEF GTK2}false{$ELSE}true{$ENDIF};
  89. var
  90. SizeMsg: TLMSize;
  91. GtkWidth, GtkHeight: integer;
  92. LCLControl: TWinControl;
  93. begin
  94. Result := CallBackDefaultReturn;
  95. if not GTK_WIDGET_REALIZED(Widget) then begin
  96. // the widget is not yet realized, so this GTK resize was not a user change.
  97. // => ignore
  98. exit;
  99. end;
  100. if Size=nil then ;
  101. LCLControl:=TWinControl(Data);
  102. if LCLControl=nil then exit;
  103. //DebugLn(['gtkglarea_size_allocateCB ',DbgSName(LCLControl)]);
  104. gtk_widget_get_size_request(Widget, @GtkWidth, @GtkHeight);
  105. SizeMsg.Msg:=0;
  106. FillChar(SizeMsg,SizeOf(SizeMsg),0);
  107. with SizeMsg do
  108. begin
  109. Result := 0;
  110. Msg := LM_SIZE;
  111. SizeType := Size_SourceIsInterface;
  112. Width := SmallInt(GtkWidth);
  113. Height := SmallInt(GtkHeight);
  114. end;
  115. //DebugLn(['gtkglarea_size_allocateCB ',GtkWidth,',',GtkHeight]);
  116. LCLControl.WindowProc(TLMessage(SizeMsg));
  117. end;
  118. function GTK_TYPE_CUSTOM_WIDGET: TGtkType;
  119. const
  120. custom_widget_type_name = 'GtkGLArea';
  121. custom_widget_info: TGtkTypeInfo = (
  122. type_name: custom_widget_type_name;
  123. object_size: SizeOf(TGtkCustomWidget);
  124. class_size: SizeOf(TGtkCustomWidgetClass);
  125. class_init_func: @gtk_custom_widget_class_init;
  126. object_init_func: @gtk_custom_widget_init;
  127. reserved_1: nil;
  128. reserved_2: nil;
  129. base_class_init_func: nil;
  130. );
  131. begin
  132. if (custom_widget_type=0) then begin
  133. custom_widget_type:=gtk_type_unique(gtk_drawing_area_get_type(),@custom_widget_info);
  134. end;
  135. Result:=custom_widget_type;
  136. end;
  137. { TCustomVisualControl }
  138. constructor TCustomVisualControl.Create(TheOwner: TComponent; const aVisualID: TVisualID);
  139. begin
  140. inherited Create(TheOwner);
  141. FIntWidget:= nil;
  142. fVisualID:= aVisualID;
  143. SetBounds(0, 0, 200, 200);
  144. end;
  145. function TCustomVisualControl.WSCreateHandle(const WSPrivate: TWSPrivateClass; const AParams: TCreateParams): TLCLIntfHandle;
  146. var
  147. cmap: PGdkColormap;
  148. gdkvis: PGdkVisual;
  149. begin
  150. // is the requested VisualID different from what the widget would get?
  151. cmap := gdk_colormap_get_system;
  152. gdkvis:= gdk_colormap_get_visual(cmap);
  153. if XVisualIDFromVisual(gdk_x11_visual_get_xvisual(gdkvis)) <> FVisualID then begin
  154. gdkvis:= gdkx_visual_get(FVisualID);
  155. cmap := gdk_colormap_new(gdkvis, false);
  156. end;
  157. FIntWidget:= gtk_type_new(GTK_TYPE_CUSTOM_WIDGET);
  158. gtk_widget_set_colormap(FIntWidget, cmap);
  159. Result:= TLCLIntfHandle({%H-}PtrUInt(FIntWidget));
  160. PGtkobject(FIntWidget)^.flags:= PGtkobject(FIntWidget)^.flags or GTK_CAN_FOCUS;
  161. TGTK2WidgetSet(WidgetSet).FinishCreateHandle(Self,FIntWidget,AParams);
  162. g_signal_connect_after(FIntWidget, 'size-allocate', TGTKSignalFunc(@custom_widget_size_allocateCB), Self);
  163. end;
  164. procedure TCustomVisualControl.WSBeforeDestroyHandle;
  165. begin
  166. if not HandleAllocated then exit;
  167. end;
  168. { TWSCustomVisualControl }
  169. class function TWSCustomVisualControl.CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle;
  170. begin
  171. if csDesigning in AWinControl.ComponentState then begin
  172. // do not use "inherited CreateHandle", because the LCL changes the hierarchy at run time
  173. Result:= TWSWinControlClass(ClassParent).CreateHandle(AWinControl,AParams);
  174. end else
  175. Result:= (AWinControl as TCustomVisualControl).WSCreateHandle(WSPrivate, AParams);
  176. end;
  177. class procedure TWSCustomVisualControl.DestroyHandle(const AWinControl: TWinControl);
  178. begin
  179. (AWinControl as TCustomVisualControl).WSBeforeDestroyHandle;
  180. // do not use "inherited DestroyHandle", because the LCL changes the hierarchy at run time
  181. TWSWinControlClass(ClassParent).DestroyHandle(AWinControl);
  182. end;
  183. initialization
  184. RegisterWSComponent(TCustomVisualControl,TWSCustomVisualControl);
  185. end.