1{%MainUnit gtkproc.pp}{%MainUnit gtkint.pp}
2{ $Id$ }
3{
4 *****************************************************************************
5  This file is part of the Lazarus Component Library (LCL)
6
7  See the file COPYING.modifiedLGPL.txt, included in this distribution,
8  for details about the license.
9 *****************************************************************************
10}
11
12function G_OBJECT(p: Pointer): PGtkObject;
13begin
14  Result:=PGtkObject(p);
15end;
16
17function G_CALLBACK(p: Pointer): TGTKSignalFunc;
18begin
19  Result:=TGTKSignalFunc(p);
20end;
21
22function GDK_GET_CURRENT_DESKTOP(): gint;
23var
24  XDisplay: PDisplay;
25  XScreen: PScreen;
26  XWindow: TWindow;
27  AtomType: x.TAtom;
28  Format: gint;
29  nitems: gulong;
30  bytes_after: gulong;
31  current_desktop: pguint;
32begin
33  Result := -1;
34
35  xdisplay := gdk_display;
36  xscreen := XDefaultScreenOfDisplay(xdisplay);
37  xwindow := XRootWindowOfScreen(xscreen);
38
39  XGetWindowProperty (xdisplay, xwindow,
40             XInternAtom(xdisplay, '_NET_CURRENT_DESKTOP', false),
41             0, MaxInt, False, XA_CARDINAL, @atomtype, @format, @nitems,
42             @bytes_after, gpointer(@current_desktop));
43
44  if (atomtype = XA_CARDINAL) and (format = 32) and  (nitems > 0) then
45    Result := current_desktop[0];
46  if current_desktop <> nil then
47    XFree (current_desktop);
48end;
49
50
51function GDK_WINDOW_GET_DESKTOP(Window: PGdkWindowPrivate): gint;
52var
53  xdisplay: PDisplay;
54  xwindow: TWindow;
55
56  atomtype: x.TAtom;
57  format: gint;
58  nitems: gulong;
59  bytes_after: gulong;
60  current_desktop: pguint;
61begin
62  Result := -1;
63  XWindow := GDK_WINDOW_XWINDOW (Window);
64  XDisplay := GDK_WINDOW_XDISPLAY (Window);
65  XGetWindowProperty (xdisplay, xwindow,
66             XInternAtom(xdisplay, '_NET_WM_DESKTOP', false),
67             0, MaxInt, False, XA_CARDINAL, @atomtype, @format, @nitems,
68             @bytes_after, gpointer(@current_desktop));
69
70  if (atomtype = XA_CARDINAL) and (format = 32) and  (nitems > 0) then
71    Result := current_desktop[0];
72  if current_desktop <> nil then
73    XFree (current_desktop);
74end;
75
76function GDK_WINDOW_SET_DESKTOP(Window: PGdkWindowPrivate; Desktop: gint): gint;
77var
78  XDisplay: PDisplay;
79  XScreen: PScreen;
80  XRootWindow,
81  XWindow: TWindow;
82  XEvent: TXClientMessageEvent;
83  _NET_WM_DESKTOP: Integer;
84begin
85
86  Result := -1;
87
88  XDisplay := GDK_WINDOW_XDISPLAY (Window);
89  XScreen := XDefaultScreenOfDisplay(xdisplay);
90  XRootWindow := XRootWindowOfScreen(xscreen);
91  XWindow := GDK_WINDOW_XWINDOW (Window);
92
93  _NET_WM_DESKTOP := XInternAtom(xdisplay, '_NET_WM_DESKTOP', false);
94
95  XEvent._type := ClientMessage;
96  XEvent.window := XWindow;
97  XEvent.message_type := _NET_WM_DESKTOP;
98  XEvent.format := 32;
99  XEvent.data.l[0] := Desktop;
100
101  XSendEvent(XDisplay, XRootWindow, False, SubstructureNotifyMask, PXEvent(@XEvent));
102end;
103
104
105procedure GDK_WINDOW_ACTIVATE(Window: PGdkWindowPrivate);
106var
107  XDisplay: PDisplay;
108  XScreen: PScreen;
109  aXRootWindow,
110  XWindow: x.TWindow;
111  XEvent: xlib.TXClientMessageEvent;
112  _NET_ACTIVE_WINDOW: Integer;
113begin
114  if (Window=nil) or (gdk.destroyed(Window^)<>0) then exit;
115
116  XDisplay := GDK_WINDOW_XDISPLAY (Window);
117  if XDisplay=nil then exit;
118  XScreen := XDefaultScreenOfDisplay(xdisplay);
119  if XScreen=nil then exit;
120  aXRootWindow := XRootWindowOfScreen(xscreen);
121  if aXRootWindow=0 then exit;
122  XWindow := GDK_WINDOW_XWINDOW (Window);
123  if XWindow=0 then exit;
124
125  _NET_ACTIVE_WINDOW := XInternAtom(xdisplay, '_NET_ACTIVE_WINDOW', false);
126
127  XEvent._type := ClientMessage;
128  XEvent.window := XWindow;
129  XEvent.message_type := _NET_ACTIVE_WINDOW;
130  XEvent.format := 32;
131  XEvent.data.l[0] := 1; //Message is from program
132  XEvent.data.l[1] := CurrentTime;
133  XEvent.data.l[2] := 0; // Applications current active window
134
135  XSendEvent(XDisplay, aXRootWindow, False, SubstructureNotifyMask, PXEvent(@XEvent));
136end;
137
138procedure GDK_WINDOW_MAXIMIZE(Window: PGdkWindowPrivate);
139const
140  _NET_WM_STATE_REMOVE    =    0;   // remove/unset property
141  _NET_WM_STATE_ADD       =    1;   // add/set property
142  _NET_WM_STATE_TOGGLE    =    2;   // toggle property
143var
144  XDisplay: PDisplay;
145  XScreen: PScreen;
146  aXRootWindow,
147  XWindow: TWindow;
148  XEvent: TXClientMessageEvent;
149  _NET_WM_STATE,
150  _NET_WM_STATE_MAXIMIZED_VERT,
151  _NET_WM_STATE_MAXIMIZED_HORZ: Integer;
152
153begin
154  XDisplay := GDK_WINDOW_XDISPLAY (Window);
155  XScreen := XDefaultScreenOfDisplay(xdisplay);
156  aXRootWindow := XRootWindowOfScreen(xscreen);
157  XWindow := GDK_WINDOW_XWINDOW (Window);
158
159  _NET_WM_STATE := XInternAtom(xdisplay, '_NET_WM_STATE', false);
160  _NET_WM_STATE_MAXIMIZED_VERT := XInternAtom(xdisplay, '_NET_WM_STATE_MAXIMIZED_VERT', false);
161  _NET_WM_STATE_MAXIMIZED_HORZ := XInternAtom(xdisplay, '_NET_WM_STATE_MAXIMIZED_HORZ', false);
162
163  XEvent._type := ClientMessage;
164  XEvent.window := XWindow;
165  XEvent.message_type := _NET_WM_STATE;
166  XEvent.format := 32;
167  XEvent.data.l[0] := _NET_WM_STATE_ADD;
168  XEvent.data.l[1] := _NET_WM_STATE_MAXIMIZED_HORZ;
169  XEvent.data.l[2] := _NET_WM_STATE_MAXIMIZED_VERT;
170
171  XSendEvent(XDisplay, aXRootWindow, False, SubstructureNotifyMask, PXEvent(@XEvent));
172end;
173
174function GDK_WINDOW_GET_MINIMIZED(Window: PGdkWindowPrivate): gboolean;
175const
176  _NET_WM_STATE_REMOVE    =    0;   // remove/unset property
177  _NET_WM_STATE_ADD       =    1;   // add/set property
178  _NET_WM_STATE_TOGGLE    =    2;   // toggle property
179var
180  XDisplay: PDisplay;
181  XWindow: x.TWindow;
182  _NET_WM_STATE,
183  _NET_WM_STATE_HIDDEN: Integer;
184  atomtype: x.TAtom;
185  format: gint;
186  nitems: gulong;
187  bytes_after: gulong;
188  state_array: pguint;
189  X: Integer;
190begin
191  Result := False;
192  XDisplay := GDK_WINDOW_XDISPLAY(Window);
193  XWindow := GDK_WINDOW_XWINDOW(Window);
194
195  _NET_WM_STATE := XInternAtom(XDisplay, '_NET_WM_STATE', False);
196  _NET_WM_STATE_HIDDEN := XInternAtom(XDisplay, '_NET_WM_STATE_HIDDEN', False);
197
198  XGetWindowProperty(XDisplay, XWindow, _NET_WM_STATE,
199             0, MaxInt, False, XA_ATOM, @atomtype, @format, @nitems,
200             @bytes_after, @state_array);
201  if (atomtype = XA_ATOM) and (format = 32) and  (nitems > 0) then
202  begin
203    // Check to see if the window is already minimized...
204    for X := 0 to nitems - 1 do
205    begin
206      if (state_array[X] = _NET_WM_STATE_HIDDEN) then
207      begin
208        XFree(state_array);
209        Exit(True);
210      end;
211    end;
212  end;
213  if state_array <> nil then
214    XFree(state_array);
215end;
216
217procedure GDK_WINDOW_MINIMIZE(Window: PGdkWindowPrivate);
218var
219  XDisplay: PDisplay;
220  XScreen: PScreen;
221  XWindow: x.TWindow;
222begin
223  if GDK_WINDOW_GET_MINIMIZED(Window) then
224    Exit;
225
226  XDisplay := GDK_WINDOW_XDISPLAY(Window);
227  XScreen := XDefaultScreenOfDisplay(XDisplay);
228  XWindow := GDK_WINDOW_XWINDOW(Window);
229
230  XIconifyWindow(XDisplay, XWindow, XScreenNumberOfScreen(XScreen));
231end;
232
233function GDK_WINDOW_GET_MAXIMIZED(Window: PGdkWindowPrivate): gboolean;
234var
235  xdisplay: PDisplay;
236  xwindow: TWindow;
237
238  atomtype: x.TAtom;
239  format: gint;
240  nitems: gulong;
241  bytes_after: gulong;
242  state_array: pguint;
243  _NET_WM_STATE,
244  _NET_WM_STATE_MAXIMIZED_VERT,
245  _NET_WM_STATE_MAXIMIZED_HORZ: x.TAtom;
246  X: Integer;
247  maximized_horz, maximized_vert: Boolean;
248begin
249  Result := False;
250  XWindow := GDK_WINDOW_XWINDOW(Window);
251  XDisplay := GDK_WINDOW_XDISPLAY(Window);
252
253  _NET_WM_STATE := XInternAtom(XDisplay, '_NET_WM_STATE', False);
254  _NET_WM_STATE_MAXIMIZED_VERT := XInternAtom(XDisplay, '_NET_WM_STATE_MAXIMIZED_VERT', False);
255  _NET_WM_STATE_MAXIMIZED_HORZ := XInternAtom(XDisplay, '_NET_WM_STATE_MAXIMIZED_HORZ', False);
256
257  XGetWindowProperty (xdisplay, xwindow,
258             _NET_WM_STATE,
259             0, MaxInt, False, XA_ATOM, @atomtype, @format, @nitems,
260             @bytes_after, gpointer(@state_array));
261
262  if (atomtype = XA_ATOM) and (format = 32) and  (nitems > 0) then
263  begin
264    maximized_horz := False;
265    maximized_vert := False;
266    for X := 0 to nitems - 1 do
267    begin
268      if (state_array[X] = _NET_WM_STATE_MAXIMIZED_VERT) then maximized_vert := True;
269      if (state_array[X] = _NET_WM_STATE_MAXIMIZED_HORZ) then maximized_horz := True;
270      Result := (maximized_horz and maximized_vert);
271
272      if Result then Break;
273    end;
274  end;
275  if state_array <> nil then
276    XFree(state_array);
277end;
278
279procedure GDK_WINDOW_SHOW_IN_TASKBAR(Window: PGdkWindowPrivate; Show: Boolean);
280// this is a try to hide windows from the taskbar.
281// Unpleasantly, some windowmanagers like metacity also hides from the Alt-Tab
282// cycle.
283// This feature is therefore disabled on default.
284{$IFDEF EnableHideFromTaskBar}
285var
286  XDisplay: PDisplay;
287  XScreen: PScreen;
288  XRootWindow,
289  XWindow: TWindow;
290  XEvent: TXClientMessageEvent;
291  _NET_WM_STATE,
292  _NET_WM_STATE_SKIP_TASKBAR: clong;
293{$ENDIF}
294begin
295  {$IFDEF EnableHideFromTaskBar}
296  // GTK1: reshowing does not work, so a modal form will hide the whole application
297  // GTK
298
299  XDisplay := GDK_WINDOW_XDISPLAY (Window);
300  XScreen := XDefaultScreenOfDisplay(xdisplay);
301  XRootWindow := XRootWindowOfScreen(xscreen);
302  XWindow := GDK_WINDOW_XWINDOW (Window);
303
304  _NET_WM_STATE := XInternAtom(xdisplay, '_NET_WM_STATE', false);
305  _NET_WM_STATE_SKIP_TASKBAR := XInternAtom(xdisplay, '_NET_WM_STATE_SKIP_TASKBAR', false);
306
307  XEvent._type := ClientMessage;
308  XEvent.window := XWindow;
309  XEvent.message_type := _NET_WM_STATE;
310  XEvent.format := 32;
311  if Show then
312    XEvent.data.l[0] := 1
313  else
314    XEvent.data.l[0] := 0;// 0=Remove 1=Add 2=Toggle
315  XEvent.data.l[1] := _NET_WM_STATE_SKIP_TASKBAR;
316
317  XSendEvent(XDisplay, XRootWindow, False, SubstructureNotifyMask, @XEvent);
318  {$ENDIF}
319end;
320
321function gtk_class_get_type(aclass : Pointer) : TGtkType;
322begin
323  If (aclass <> nil) then
324    result := PGtkTypeClass(aclass)^.thetype
325  else
326    result := 0;
327end;
328
329function gtk_object_get_class(anobject : Pointer) : Pointer;
330begin
331  If (anobject <> nil) then
332    result := PGtkTypeObject(anobject)^.klass
333  else
334    result := nil;
335end;
336
337function gtk_window_get_modal(window:PGtkWindow):gboolean;
338begin
339  if assigned(Window) then
340    result := (Window^.flag0 and bm_modal)<>0
341  else
342    result := False;
343end;
344
345function gtk_bin_get_child(bin : PGTKBin) : PGTKWidget;
346begin
347  if (bin <> nil) then
348    result := bin^.Child
349  else
350    result := nil;
351end;
352
353procedure gtk_menu_item_set_right_justified(menu_item : PGtkMenuItem; right_justified : gboolean);
354begin
355  if right_justified then
356    menu_item^.flag0:=menu_item^.flag0 or bm_right_justify
357  else
358    menu_item^.flag0:=menu_item^.flag0 and (not bm_right_justify);
359end;
360
361function gtk_check_menu_item_get_active(menu_item : PGtkCheckMenuItem) : gboolean;
362begin
363   Result:=(menu_item^.flag0 and bm_checkmenuitem_active <> 0);
364end;
365
366procedure gtk_menu_append(menu : PGTKWidget; Item : PGtkWidget);
367begin
368  gtk.gtk_menu_append(PGTKMenu(menu), Item);
369end;
370
371procedure gtk_menu_insert(menu : PGtkWidget; Item : PGTKWidget; Index : gint);
372begin
373  gtk.gtk_menu_insert(PGTKMenu(menu), Item, Index);
374end;
375
376procedure gtk_menu_bar_insert(menubar : PGtkWidget; Item : PGTKWidget; Index : gint);
377begin
378  gtk.gtk_menu_bar_insert(PGtkMenuBar(menubar), Item, Index);
379end;
380
381function gtk_image_new :PGTKWidget;
382begin
383  result := gtk.gtk_image_new(nil,nil);
384end;
385
386function gtk_toolbar_new : PGTKWidget;
387begin
388  result := gtk.gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL,GTK_TOOLBAR_BOTH);
389end;
390
391procedure gtk_color_selection_get_current_color(colorsel : PGTKColorSelection; Color : PGDKColor);
392var
393  colorArray : array[0..2] of double;
394begin
395  gtk_color_selection_get_color(colorsel, @colorArray[0]);
396  Color^.pixel := 0;
397  Color^.red := gushort(TruncToCardinal(colorArray[0] * $FFFF));
398  Color^.green := gushort(TruncToCardinal(colorArray[1] * $FFFF));
399  Color^.blue := gushort(TruncToCardinal(colorArray[2] * $FFFF));
400  {$IFDEF VerboseColorDialog}
401  DebugLn('gtk_color_selection_get_current_color ',
402    ' Red=',DbgS(Color^.Red),
403    ' Green=',DbgS(Color^.Green),
404    ' Blue=',DbgS(Color^.Blue),
405    '');
406  {$ENDIF}
407end;
408
409procedure gtk_color_selection_set_current_color(colorsel : PGTKColorSelection;
410  Color : PGDKColor);
411var
412  SelectionColor: PGDouble;
413begin
414  {$IFDEF VerboseColorDialog}
415  DebugLn('gtk_color_selection_set_current_color ',
416    ' Red=',DbgS(Color^.Red),
417    ' Green=',DbgS(Color^.Green),
418    ' Blue=',DbgS(Color^.Blue),
419    '');
420  {$ENDIF}
421  GetMem(SelectionColor,4*SizeOf(GDouble));
422  try
423    SelectionColor[0]:=gdouble(Color^.Red)/65535;
424    SelectionColor[1]:=gdouble(Color^.Green)/65535;
425    SelectionColor[2]:=gdouble(Color^.Blue)/65535;
426    SelectionColor[3]:=0.0;
427    gtk_color_selection_set_color(colorSel,SelectionColor);
428  finally
429    FreeMem(SelectionColor);
430  end;
431end;
432
433procedure gdk_image_unref(Image : PGdkImage);
434begin
435  gdk_window_unref(PGdkWindow(Image));
436end;
437
438procedure gdk_colormap_query_color(colormap : PGDKColormap; Pixel : gulong; Result : PGDKColor);
439var
440  GdkColorContext: PGdkColorContext;
441begin
442  if (Colormap = nil) or (Result = nil) then exit;
443  GdkColorContext:= gdk_color_context_new(gdk_colormap_get_visual(colormap),colormap);
444  Result^.Pixel := Pixel;
445  gdk_color_context_query_color(GdkColorContext, Result);
446  gdk_color_context_free(GdkColorContext);
447end;
448
449function gdk_region_intersect(source1:PGdkRegion; source2:PGdkRegion) : PGdkRegion;
450begin
451  result := gdk_regions_intersect(source1, source2);
452end;
453
454function gdk_region_union(source1:PGdkRegion; source2:PGdkRegion) : PGdkRegion;
455begin
456  result := gdk_regions_union(source1, source2);
457end;
458
459function gdk_region_subtract(source1:PGdkRegion; source2:PGdkRegion) : PGdkRegion;
460begin
461  result := gdk_regions_subtract(source1, source2);
462end;
463
464function gdk_region_xor(source1:PGdkRegion; source2:PGdkRegion) : PGdkRegion;
465begin
466  result := gdk_regions_xor(source1, source2);
467end;
468
469function gdk_region_copy(region: PGDKRegion): PGDKRegion;
470var
471  EmptyRegion: PGdkRegion;
472begin
473  EmptyRegion := gdk_region_new;
474  Result := gdk_regions_union(region, EmptyRegion);
475  gdk_region_destroy(EmptyRegion);
476end;
477
478function gdk_region_rectangle(rect: PGdkRectangle): PGDKRegion;
479var
480  EmptyRegion: PGdkRegion;
481begin
482  EmptyRegion := gdk_region_new;
483  Result := gdk_region_union_with_rect(EmptyRegion,Rect);
484  gdk_region_destroy(EmptyRegion);
485end;
486
487function gdk_pixmap_create_from_xpm_d (window : PGdkWindow; var mask : PGdkBitmap; transparent_color : PGdkColor; data : PPgchar) : PGdkPixmap;
488begin
489  result := gdk.gdk_pixmap_create_from_xpm_d(window, @mask, transparent_color, data)
490end;
491
492function gdk_pixmap_colormap_create_from_xpm_d (window : PGdkWindow; colormap: PGdkColormap; var mask : PGdkBitmap; transparent_color : PGdkColor; data : PPgchar) : PGdkPixmap;
493begin
494  result := gdk.gdk_pixmap_colormap_create_from_xpm_d(window, colormap, @mask, transparent_color, data)
495end;
496
497function gdk_pixmap_colormap_create_from_xpm (window : PGdkWindow; colormap: PGdkColormap; var mask : PGdkBitmap; transparent_color : PGdkColor; filename : Pgchar) : PGdkPixmap;
498begin
499  result := gdk.gdk_pixmap_colormap_create_from_xpm(window, colormap, @mask, transparent_color, filename)
500end;
501
502procedure gdk_pixbuf_render_pixmap_and_mask(pixbuf : PGdkPixbuf; var pixmap_return : PGdkPixmap; var mask_return : PGdkBitmap; alpha_threshold : gint);
503begin
504  gdkpixbuf.gdk_pixbuf_render_pixmap_and_mask(pixbuf, @pixmap_return, @mask_return, alpha_threshold);
505end;
506
507function gdk_pixbuf_new_subpixbuf(src_pixbuf: PGdkPixbuf; src_x: longint; src_y: longint; width: longint; height: longint): PGdkPixbuf;
508var
509  tmp: PGdkPixbuf;
510  buf: PChar;
511  rowstride: Integer;
512begin
513  buf := gdk_pixbuf_get_pixels(src_pixbuf);
514
515  rowstride := gdk_pixbuf_get_rowstride(src_pixbuf);
516
517  inc(buf, src_y * rowstride + src_x * gdk_pixbuf_get_n_channels(src_pixbuf));
518  tmp := gdk_pixbuf_new_from_data(buf, gdk_pixbuf_get_colorspace(src_pixbuf),
519    gdk_pixbuf_get_has_alpha(src_pixbuf), gdk_pixbuf_get_bits_per_sample(src_pixbuf),
520    width, height, rowstride, nil, nil);
521  Result := gdk_pixbuf_copy(tmp);
522  gdk_pixbuf_unref(tmp);
523end;
524
525function gdk_drawable_get_depth(Drawable : PGDKDrawable) : gint;
526begin
527  gdk_window_get_geometry(Drawable, nil, nil, nil, nil, @result);
528end;
529
530procedure gdk_drawable_get_size(Drawable : PGDKDrawable; Width, Height : PGInt);
531begin
532  gdk_window_get_geometry(Drawable, nil, nil, Width, Height, nil);
533end;
534
535function gdk_drawable_get_image(Drawable : PGDKDrawable; x, y, width, height : gint) : PGdkImage;
536begin
537  result := gdk_image_get(Drawable, x, y, width, height);
538end;
539
540function gdk_drawable_get_colormap(Drawable : PGDKDrawable) : PGdkColormap;
541begin
542  result := gdk_window_get_colormap(Drawable);
543end;
544
545{$ifdef HasX}
546function gdk_x11_image_get_ximage(image: PGdkImage): PXImage;
547begin
548  Result := PGdkImagePrivate(Image)^.ximage;
549end;
550{$endif}
551
552