[Lazarus] GTK2: Drag files to other applications (to the file manager, Thunar, Nautilus, etc)

Bernd prof7bit at gmail.com
Mon Aug 20 14:26:25 CEST 2012


I am making progress. The handle is indeed a PGTKWidget but there are
always multiple widgets nested inside each other, for example a
TButton is really a GTKLabel inside a GTKButton inside a GTKEventBox,
so I have to recursively go through all the child widgets and set up
drag&drop for them all.

Here is what I have now (for everybody who also wants to experiment with this):

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  StdCtrls, ComCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    ScrollBox1: TScrollBox;
    StaticText1: TStaticText;
    TreeView1: TTreeView;
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation
{$ifdef LCLGTK2}
uses
  glib2, gtk2, gdk2;
{$endif}

{$R *.lfm}

{$ifdef LCLGTK2}
procedure GtkDragDataGet(GtkW: PGtkWidget;
                      Context: PGdkDragContext;
                      SelData: PGtkSelectionData;
                   TargetType: guint;
                         Time: guint;
                      Control: TWinControl); cdecl;
begin
  writeln('drag_data_get from ', Control.Name);
end;

procedure GtkDragBegin(GtkW: PGtkWidget;
                    Context: PGdkDragContext;
                    Control: TWinControl); cdecl;
begin
  writeln('drag_begin from ', Control.Name);
end;

procedure GtkRecursiveConnect(GtkW: PGtkWidget; Control: TWinControl); cdecl;
const
  FileDragTarget: TGtkTargetEntry = (target: 'text/uri-list'; flags:
0; info: 0;);
begin
  WriteLn('connecting: ', gtk_widget_get_name(GtkW));
  gtk_drag_source_set(GtkW, GDK_BUTTON1_MASK, @FileDragTarget, 1,
GDK_ACTION_COPY);
  g_signal_connect(GtkW, 'drag-data-get', TGCallback(@GtkDragDataGet), Control);
  g_signal_connect(GtkW, 'drag-begin', TGCallback(@GtkDragBegin), Control);

  // recurse through all child widgets
  if GTK_IS_CONTAINER(GtkW) then
    gtk_container_foreach(PGTKContainer(GtkW),
TGtkCallback(@GtkRecursiveConnect), Control);
end;

procedure GTkSetupDragDrop(AControl: TWinControl);
var
  GtkW: PGtkWidget;
begin
  writeln(LineEnding, 'now setting up: ', AControl.Name);
  GtkW := PGtkWidget(AControl.Handle);
  GtkRecursiveConnect(GtkW, AControl);
end;
{$endif}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  {$ifdef LCLGTK2}
  //SetupDragDrop(Form1);
  GTkSetupDragDrop(Button1);
  GTkSetupDragDrop(ScrollBox1);
  GTkSetupDragDrop(StaticText1);
  GTkSetupDragDrop(TreeView1);
  {$endif}
end;

end.

it prints the following to the console (and file manager and desktop
behave as if they would accept the file drop although it does not yet
send any data):

now setting up: Button1
connecting: GtkEventBox
connecting: GtkButton
connecting: GtkLabel

now setting up: ScrollBox1
connecting: GtkScrolledWindow
connecting: GtkLayout

now setting up: StaticText1
connecting: GtkFrame
connecting: GtkEventBox
connecting: GtkLabel

now setting up: TreeView1
connecting: LCLWinapiWidget
connecting: LCLWinapiClient
drag_begin from ScrollBox1
drag_begin from ScrollBox1
drag_data_get from ScrollBox1
drag_begin from StaticText1
drag_data_get from StaticText1
drag_begin from Button1
drag_data_get from Button1

The only thing that is not working is the TTreeView, it does not seem
to be based on any native GTK widget and will not behave like the
other widgets.




More information about the Lazarus mailing list