2022-04-21 16:53:28 +02:00
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "utf-8" / >
< meta name = "generator" content = "pandoc" / >
< meta name = "viewport" content = "width=device-width, initial-scale=1" / >
< link href = "https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel = "stylesheet" integrity = "sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin = "anonymous" >
2023-01-18 06:27:57 +01:00
< title > GTK 4 tutorial< / title >
2022-04-21 16:53:28 +02:00
< style >
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
pre{overflow: visible;}
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
2022-04-17 13:54:42 +02:00
}
2022-04-21 16:53:28 +02:00
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::after
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
div.sourceCode { margin: 10px; padding: 16px 10px 8px 10px; border: 2px solid silver; background-color: ghostwhite; overflow-x:scroll}
pre:not(.sourceCode) { margin: 10px; padding: 16px 10px 8px 10px; border: 2px solid silver; background-color: ghostwhite; overflow-x:scroll}
table {margin-left: auto; margin-right: auto; border-collapse: collapse; border: 1px solid;}
th {padding: 2px 6px; border: 1px solid; background-color: ghostwhite;}
td {padding: 2px 6px; border: 1px solid;}
img {display: block; margin-left: auto; margin-right: auto;}
figcaption {text-align: center;}
< / style >
< / head >
< body style = "padding-top: 70px;" >
< div class = "container" >
< nav class = "navbar fixed-top navbar-expand-lg navbar-dark bg-primary" >
< div class = "container-fluid" >
< span class = "navbar-brand" > Gtk4 tutorial< / span >
< button class = "navbar-toggler" type = "button" data-bs-toggle = "collapse" data-bs-target = "#navbarSupportedContent" aria-controls = "navbarSupportedContent" aria-expanded = "false" aria-label = "Toggle navigation" >
< span class = "navbar-toggler-icon" > < / span >
< / button >
< div class = "collapse navbar-collapse" id = "navbarSupportedContent" >
< ul class = "navbar-nav me-auto mb-2 mb-lg-0" >
< li class = "nav-item" >
< a class = "nav-link" href = "index.html" > Home< / a >
< / li >
< li class = "nav-item" >
< a class = "nav-link" href = "sec27.html" > Prev: section27< / a >
< / li >
< li class = "nav-item" >
< a class = "nav-link" href = "sec29.html" > Next: section29< / a >
< / li >
< / ul >
< / div >
< / div >
< / nav >
2023-07-29 14:41:57 +02:00
< h1 id = "drag-and-drop" > Drag and drop< / h1 >
< h2 id = "whats-drag-and-drop" > What’ s drag and drop?< / h2 >
< p > Drag and drop is also written as “Drag-and-Drop”, or “DND” in short.
DND is like “copy and paste” or “cut and paste”. If a user drags a UI
element, which is a widget, selected part or something, data is
transferred from the source to the destination.< / p >
< p > You probably have experience that you moved a file with DND.< / p >
2023-07-15 10:27:53 +02:00
< figure >
2023-07-29 14:41:57 +02:00
< img src = "image/dnd.png" alt = "DND on the GUI file manager" / >
< figcaption aria-hidden = "true" > DND on the GUI file manager< / figcaption >
2023-07-15 10:27:53 +02:00
< / figure >
2023-07-29 14:41:57 +02:00
< p > When the DND starts, the file < code > sample_file.txt< / code > is given
to the system. When the DND ends, the system gives
< code > sample_file.txt< / code > to the directory < code > sample_folder< / code >
in the file manager. Therefore, it is like “cut and paste”. The actual
behavior may be different from the explanation here, but the concept is
similar.< / p >
< h2 id = "example-for-dnd" > Example for DND< / h2 >
< p > This tutorial provides a simple example in the < code > src/dnd< / code >
directory. It has three labels for the source and one label for the
destination. The source labels have “red”, “green” or “blue” labels. If
a user drags the label to the destination label, the font color will be
changed.< / p >
2023-07-15 10:27:53 +02:00
< figure >
2023-07-29 14:41:57 +02:00
< img src = "image/dnd_canvas.png" alt = "DND example" / >
< figcaption aria-hidden = "true" > DND example< / figcaption >
2023-07-15 10:27:53 +02:00
< / figure >
2023-07-29 14:41:57 +02:00
< h2 id = "ui-file" > UI file< / h2 >
< p > The widgets are defined in the XML file < code > dnd.ui< / code > .< / p >
< div class = "sourceCode" id = "cb1" > < pre
class="sourceCode numberSource xml numberLines">< code class = "sourceCode xml" > < span id = "cb1-1" > < a href = "#cb1-1" > < / a > < span class = "fu" > < ?xml< / span > < span class = "ot" > version=< / span > < span class = "st" > " 1.0" < / span > < span class = "ot" > encoding=< / span > < span class = "st" > " UTF-8" < / span > < span class = "fu" > ?> < / span > < / span >
< span id = "cb1-2" > < a href = "#cb1-2" > < / a > < < span class = "kw" > interface< / span > > < / span >
< span id = "cb1-3" > < a href = "#cb1-3" > < / a > < < span class = "kw" > object< / span > < span class = "ot" > class=< / span > < span class = "st" > " GtkApplicationWindow" < / span > < span class = "ot" > id=< / span > < span class = "st" > " win" < / span > > < / span >
< span id = "cb1-4" > < a href = "#cb1-4" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " default-width" < / span > > 800< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-5" > < a href = "#cb1-5" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " default-height" < / span > > 600< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-6" > < a href = "#cb1-6" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " resizable" < / span > > FALSE< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-7" > < a href = "#cb1-7" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " title" < / span > > Drag and Drop< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-8" > < a href = "#cb1-8" > < / a > < < span class = "kw" > child< / span > > < / span >
< span id = "cb1-9" > < a href = "#cb1-9" > < / a > < < span class = "kw" > object< / span > < span class = "ot" > class=< / span > < span class = "st" > " GtkBox" < / span > > < / span >
< span id = "cb1-10" > < a href = "#cb1-10" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " hexpand" < / span > > TRUE< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-11" > < a href = "#cb1-11" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " vexpand" < / span > > TRUE< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-12" > < a href = "#cb1-12" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " orientation" < / span > > GTK_ORIENTATION_VERTICAL< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-13" > < a href = "#cb1-13" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " spacing" < / span > > 5< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-14" > < a href = "#cb1-14" > < / a > < < span class = "kw" > child< / span > > < / span >
< span id = "cb1-15" > < a href = "#cb1-15" > < / a > < < span class = "kw" > object< / span > < span class = "ot" > class=< / span > < span class = "st" > " GtkBox" < / span > > < / span >
< span id = "cb1-16" > < a href = "#cb1-16" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " orientation" < / span > > GTK_ORIENTATION_HORIZONTAL< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-17" > < a href = "#cb1-17" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " homogeneous" < / span > > TRUE< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-18" > < a href = "#cb1-18" > < / a > < < span class = "kw" > child< / span > > < / span >
< span id = "cb1-19" > < a href = "#cb1-19" > < / a > < < span class = "kw" > object< / span > < span class = "ot" > class=< / span > < span class = "st" > " GtkLabel" < / span > < span class = "ot" > id=< / span > < span class = "st" > " red" < / span > > < / span >
< span id = "cb1-20" > < a href = "#cb1-20" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " label" < / span > > RED< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-21" > < a href = "#cb1-21" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " justify" < / span > > GTK_JUSTIFY_CENTER< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-22" > < a href = "#cb1-22" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " name" < / span > > red< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-23" > < a href = "#cb1-23" > < / a > < /< span class = "kw" > object< / span > > < / span >
< span id = "cb1-24" > < a href = "#cb1-24" > < / a > < /< span class = "kw" > child< / span > > < / span >
< span id = "cb1-25" > < a href = "#cb1-25" > < / a > < < span class = "kw" > child< / span > > < / span >
< span id = "cb1-26" > < a href = "#cb1-26" > < / a > < < span class = "kw" > object< / span > < span class = "ot" > class=< / span > < span class = "st" > " GtkLabel" < / span > < span class = "ot" > id=< / span > < span class = "st" > " green" < / span > > < / span >
< span id = "cb1-27" > < a href = "#cb1-27" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " label" < / span > > GREEN< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-28" > < a href = "#cb1-28" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " justify" < / span > > GTK_JUSTIFY_CENTER< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-29" > < a href = "#cb1-29" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " name" < / span > > green< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-30" > < a href = "#cb1-30" > < / a > < /< span class = "kw" > object< / span > > < / span >
< span id = "cb1-31" > < a href = "#cb1-31" > < / a > < /< span class = "kw" > child< / span > > < / span >
< span id = "cb1-32" > < a href = "#cb1-32" > < / a > < < span class = "kw" > child< / span > > < / span >
< span id = "cb1-33" > < a href = "#cb1-33" > < / a > < < span class = "kw" > object< / span > < span class = "ot" > class=< / span > < span class = "st" > " GtkLabel" < / span > < span class = "ot" > id=< / span > < span class = "st" > " blue" < / span > > < / span >
< span id = "cb1-34" > < a href = "#cb1-34" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " label" < / span > > BLUE< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-35" > < a href = "#cb1-35" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " justify" < / span > > GTK_JUSTIFY_CENTER< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-36" > < a href = "#cb1-36" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " name" < / span > > blue< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-37" > < a href = "#cb1-37" > < / a > < /< span class = "kw" > object< / span > > < / span >
< span id = "cb1-38" > < a href = "#cb1-38" > < / a > < /< span class = "kw" > child< / span > > < / span >
< span id = "cb1-39" > < a href = "#cb1-39" > < / a > < /< span class = "kw" > object< / span > > < / span >
< span id = "cb1-40" > < a href = "#cb1-40" > < / a > < /< span class = "kw" > child< / span > > < / span >
< span id = "cb1-41" > < a href = "#cb1-41" > < / a > < < span class = "kw" > child< / span > > < / span >
< span id = "cb1-42" > < a href = "#cb1-42" > < / a > < < span class = "kw" > object< / span > < span class = "ot" > class=< / span > < span class = "st" > " GtkLabel" < / span > < span class = "ot" > id=< / span > < span class = "st" > " canvas" < / span > > < / span >
< span id = "cb1-43" > < a href = "#cb1-43" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " label" < / span > > CANVAS< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-44" > < a href = "#cb1-44" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " justify" < / span > > GTK_JUSTIFY_CENTER< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-45" > < a href = "#cb1-45" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " name" < / span > > canvas< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-46" > < a href = "#cb1-46" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " hexpand" < / span > > TRUE< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-47" > < a href = "#cb1-47" > < / a > < < span class = "kw" > property< / span > < span class = "ot" > name=< / span > < span class = "st" > " vexpand" < / span > > TRUE< /< span class = "kw" > property< / span > > < / span >
< span id = "cb1-48" > < a href = "#cb1-48" > < / a > < /< span class = "kw" > object< / span > > < / span >
< span id = "cb1-49" > < a href = "#cb1-49" > < / a > < /< span class = "kw" > child< / span > > < / span >
< span id = "cb1-50" > < a href = "#cb1-50" > < / a > < /< span class = "kw" > object< / span > > < / span >
< span id = "cb1-51" > < a href = "#cb1-51" > < / a > < /< span class = "kw" > child< / span > > < / span >
< span id = "cb1-52" > < a href = "#cb1-52" > < / a > < /< span class = "kw" > object< / span > > < / span >
< span id = "cb1-53" > < a href = "#cb1-53" > < / a > < /< span class = "kw" > interface< / span > > < / span > < / code > < / pre > < / div >
< p > It is converted to a resource file by
< code > glib-compile-resources< / code > . The compiler uses an XML file
< code > dnd.gresource.xml< / code > .< / p >
2023-07-15 10:27:53 +02:00
< div class = "sourceCode" id = "cb2" > < pre
2023-07-29 14:41:57 +02:00
class="sourceCode numberSource xml numberLines">< code class = "sourceCode xml" > < span id = "cb2-1" > < a href = "#cb2-1" > < / a > < span class = "fu" > < ?xml< / span > < span class = "ot" > version=< / span > < span class = "st" > " 1.0" < / span > < span class = "ot" > encoding=< / span > < span class = "st" > " UTF-8" < / span > < span class = "fu" > ?> < / span > < / span >
< span id = "cb2-2" > < a href = "#cb2-2" > < / a > < < span class = "kw" > gresources< / span > > < / span >
< span id = "cb2-3" > < a href = "#cb2-3" > < / a > < < span class = "kw" > gresource< / span > < span class = "ot" > prefix=< / span > < span class = "st" > " /com/github/ToshioCP/dnd" < / span > > < / span >
< span id = "cb2-4" > < a href = "#cb2-4" > < / a > < < span class = "kw" > file< / span > > dnd.ui< /< span class = "kw" > file< / span > > < / span >
< span id = "cb2-5" > < a href = "#cb2-5" > < / a > < /< span class = "kw" > gresource< / span > > < / span >
< span id = "cb2-6" > < a href = "#cb2-6" > < / a > < /< span class = "kw" > gresources< / span > > < / span > < / code > < / pre > < / div >
< h2 id = "c-file-dnd.c" > C file dnd.c< / h2 >
< p > The C file < code > dnd.c< / code > isn’ t a big file. The number of the
lines is less than a hundred. A GtkApplication object is created in the
function < code > main< / code > .< / p >
2023-07-15 10:27:53 +02:00
< div class = "sourceCode" id = "cb3" > < pre
2023-07-29 14:41:57 +02:00
class="sourceCode numberSource C numberLines">< code class = "sourceCode c" > < span id = "cb3-1" > < a href = "#cb3-1" > < / a > < span class = "dt" > int< / span > < / span >
< span id = "cb3-2" > < a href = "#cb3-2" > < / a > main < span class = "op" > (< / span > < span class = "dt" > int< / span > argc< span class = "op" > ,< / span > < span class = "dt" > char< / span > < span class = "op" > **< / span > argv< span class = "op" > )< / span > < span class = "op" > {< / span > < / span >
< span id = "cb3-3" > < a href = "#cb3-3" > < / a > GtkApplication < span class = "op" > *< / span > app< span class = "op" > ;< / span > < / span >
< span id = "cb3-4" > < a href = "#cb3-4" > < / a > < span class = "dt" > int< / span > stat< span class = "op" > ;< / span > < / span >
< span id = "cb3-5" > < a href = "#cb3-5" > < / a > < / span >
< span id = "cb3-6" > < a href = "#cb3-6" > < / a > app < span class = "op" > =< / span > gtk_application_new < span class = "op" > (< / span > APPLICATION_ID< span class = "op" > ,< / span > G_APPLICATION_DEFAULT_FLAGS< span class = "op" > );< / span > < / span >
< span id = "cb3-7" > < a href = "#cb3-7" > < / a > g_signal_connect < span class = "op" > (< / span > app< span class = "op" > ,< / span > < span class = "st" > " startup" < / span > < span class = "op" > ,< / span > G_CALLBACK < span class = "op" > (< / span > app_startup< span class = "op" > ),< / span > NULL< span class = "op" > );< / span > < / span >
< span id = "cb3-8" > < a href = "#cb3-8" > < / a > g_signal_connect < span class = "op" > (< / span > app< span class = "op" > ,< / span > < span class = "st" > " activate" < / span > < span class = "op" > ,< / span > G_CALLBACK < span class = "op" > (< / span > app_activate< span class = "op" > ),< / span > NULL< span class = "op" > );< / span > < / span >
< span id = "cb3-9" > < a href = "#cb3-9" > < / a > stat < span class = "op" > =< / span > g_application_run < span class = "op" > (< / span > G_APPLICATION < span class = "op" > (< / span > app< span class = "op" > ),< / span > argc< span class = "op" > ,< / span > argv< span class = "op" > );< / span > < / span >
< span id = "cb3-10" > < a href = "#cb3-10" > < / a > g_object_unref < span class = "op" > (< / span > app< span class = "op" > );< / span > < / span >
< span id = "cb3-11" > < a href = "#cb3-11" > < / a > < span class = "cf" > return< / span > stat< span class = "op" > ;< / span > < / span >
< span id = "cb3-12" > < a href = "#cb3-12" > < / a > < span class = "op" > }< / span > < / span > < / code > < / pre > < / div >
< p > The application ID is defined as:< / p >
< div class = "sourceCode" id = "cb4" > < pre class = "sourceCode C" > < code class = "sourceCode c" > < span id = "cb4-1" > < a href = "#cb4-1" aria-hidden = "true" tabindex = "-1" > < / a > < span class = "pp" > #define APPLICATION_ID " com.github.ToshioCP.dnd" < / span > < / span > < / code > < / pre > < / div >
< h3 id = "startup-signal-handler" > Startup signal handler< / h3 >
< p > Most of the work is done in the “startup” signal handler.< / p >
< p > Two objects GtkDragSource and GtkDropTarget is used for DND
implementation.< / p >
< ul >
< li > Drag source: A drag source (GtkDragSource instance) is an event
controller. It initiates a DND operation when the user clicks and drags
the widget. If a data, in the form of GdkContentProvider, is set in
advance, it gives the data to the system at the beginning of the
drag.< / li >
< li > Drop target: A drop target (GtkDropTarget) is also an event
controller. You can get the data in the GtkDropTarget::drop signal
handler.< / li >
< / ul >
< p > The example below uses these objects in a very simple way. You can
use number of features that the two objects have. See the following
links for more information.< / p >
< ul >
< li > < a href = "https://docs.gtk.org/gtk4/drag-and-drop.html" > Drag-and-Drop
in GTK< / a > < / li >
< li > < a
href="https://docs.gtk.org/gtk4/class.DragSource.html">GtkDragSource< / a > < / li >
< li > < a
href="https://docs.gtk.org/gtk4/class.DropTarget.html">GtkDropTarget< / a > < / li >
< / ul >
2023-07-15 10:27:53 +02:00
< div class = "sourceCode" id = "cb5" > < pre
2023-07-29 14:41:57 +02:00
class="sourceCode numberSource C numberLines">< code class = "sourceCode c" > < span id = "cb5-1" > < a href = "#cb5-1" > < / a > < span class = "dt" > static< / span > < span class = "dt" > void< / span > < / span >
< span id = "cb5-2" > < a href = "#cb5-2" > < / a > app_startup < span class = "op" > (< / span > GApplication < span class = "op" > *< / span > application< span class = "op" > )< / span > < span class = "op" > {< / span > < / span >
< span id = "cb5-3" > < a href = "#cb5-3" > < / a > GtkApplication < span class = "op" > *< / span > app < span class = "op" > =< / span > GTK_APPLICATION < span class = "op" > (< / span > application< span class = "op" > );< / span > < / span >
< span id = "cb5-4" > < a href = "#cb5-4" > < / a > GtkBuilder < span class = "op" > *< / span > build< span class = "op" > ;< / span > < / span >
< span id = "cb5-5" > < a href = "#cb5-5" > < / a > GtkWindow < span class = "op" > *< / span > win< span class = "op" > ;< / span > < / span >
< span id = "cb5-6" > < a href = "#cb5-6" > < / a > GtkLabel < span class = "op" > *< / span > src_labels< span class = "op" > [< / span > < span class = "dv" > 3< / span > < span class = "op" > ];< / span > < / span >
< span id = "cb5-7" > < a href = "#cb5-7" > < / a > < span class = "dt" > int< / span > i< span class = "op" > ;< / span > < / span >
< span id = "cb5-8" > < a href = "#cb5-8" > < / a > GtkLabel < span class = "op" > *< / span > canvas< span class = "op" > ;< / span > < / span >
< span id = "cb5-9" > < a href = "#cb5-9" > < / a > GtkDragSource < span class = "op" > *< / span > src< span class = "op" > ;< / span > < / span >
< span id = "cb5-10" > < a href = "#cb5-10" > < / a > GdkContentProvider< span class = "op" > *< / span > content< span class = "op" > ;< / span > < / span >
< span id = "cb5-11" > < a href = "#cb5-11" > < / a > GtkDropTarget < span class = "op" > *< / span > tgt< span class = "op" > ;< / span > < / span >
< span id = "cb5-12" > < a href = "#cb5-12" > < / a > GdkDisplay < span class = "op" > *< / span > display< span class = "op" > ;< / span > < / span >
< span id = "cb5-13" > < a href = "#cb5-13" > < / a > < span class = "dt" > char< / span > < span class = "op" > *< / span > s< span class = "op" > ;< / span > < / span >
< span id = "cb5-14" > < a href = "#cb5-14" > < / a > < / span >
< span id = "cb5-15" > < a href = "#cb5-15" > < / a > build < span class = "op" > =< / span > gtk_builder_new_from_resource < span class = "op" > (< / span > < span class = "st" > " /com/github/ToshioCP/dnd/dnd.ui" < / span > < span class = "op" > );< / span > < / span >
< span id = "cb5-16" > < a href = "#cb5-16" > < / a > win < span class = "op" > =< / span > GTK_WINDOW < span class = "op" > (< / span > gtk_builder_get_object < span class = "op" > (< / span > build< span class = "op" > ,< / span > < span class = "st" > " win" < / span > < span class = "op" > ));< / span > < / span >
< span id = "cb5-17" > < a href = "#cb5-17" > < / a > src_labels< span class = "op" > [< / span > < span class = "dv" > 0< / span > < span class = "op" > ]< / span > < span class = "op" > =< / span > GTK_LABEL < span class = "op" > (< / span > gtk_builder_get_object < span class = "op" > (< / span > build< span class = "op" > ,< / span > < span class = "st" > " red" < / span > < span class = "op" > ));< / span > < / span >
< span id = "cb5-18" > < a href = "#cb5-18" > < / a > src_labels< span class = "op" > [< / span > < span class = "dv" > 1< / span > < span class = "op" > ]< / span > < span class = "op" > =< / span > GTK_LABEL < span class = "op" > (< / span > gtk_builder_get_object < span class = "op" > (< / span > build< span class = "op" > ,< / span > < span class = "st" > " green" < / span > < span class = "op" > ));< / span > < / span >
< span id = "cb5-19" > < a href = "#cb5-19" > < / a > src_labels< span class = "op" > [< / span > < span class = "dv" > 2< / span > < span class = "op" > ]< / span > < span class = "op" > =< / span > GTK_LABEL < span class = "op" > (< / span > gtk_builder_get_object < span class = "op" > (< / span > build< span class = "op" > ,< / span > < span class = "st" > " blue" < / span > < span class = "op" > ));< / span > < / span >
< span id = "cb5-20" > < a href = "#cb5-20" > < / a > canvas < span class = "op" > =< / span > GTK_LABEL < span class = "op" > (< / span > gtk_builder_get_object < span class = "op" > (< / span > build< span class = "op" > ,< / span > < span class = "st" > " canvas" < / span > < span class = "op" > ));< / span > < / span >
< span id = "cb5-21" > < a href = "#cb5-21" > < / a > gtk_window_set_application < span class = "op" > (< / span > win< span class = "op" > ,< / span > app< span class = "op" > );< / span > < / span >
< span id = "cb5-22" > < a href = "#cb5-22" > < / a > g_object_unref < span class = "op" > (< / span > build< span class = "op" > );< / span > < / span >
< span id = "cb5-23" > < a href = "#cb5-23" > < / a > < / span >
< span id = "cb5-24" > < a href = "#cb5-24" > < / a > < span class = "cf" > for< / span > < span class = "op" > (< / span > i< span class = "op" > =< / span > < span class = "dv" > 0< / span > < span class = "op" > ;< / span > i< span class = "op" > < < / span > < span class = "dv" > 3< / span > < span class = "op" > ;< / span > < span class = "op" > ++< / span > i< span class = "op" > )< / span > < span class = "op" > {< / span > < / span >
< span id = "cb5-25" > < a href = "#cb5-25" > < / a > src < span class = "op" > =< / span > gtk_drag_source_new < span class = "op" > ();< / span > < / span >
< span id = "cb5-26" > < a href = "#cb5-26" > < / a > content < span class = "op" > =< / span > gdk_content_provider_new_typed < span class = "op" > (< / span > G_TYPE_STRING< span class = "op" > ,< / span > gtk_widget_get_name < span class = "op" > (< / span > GTK_WIDGET < span class = "op" > (< / span > src_labels< span class = "op" > [< / span > i< span class = "op" > ])));< / span > < / span >
< span id = "cb5-27" > < a href = "#cb5-27" > < / a > gtk_drag_source_set_content < span class = "op" > (< / span > src< span class = "op" > ,< / span > content< span class = "op" > );< / span > < / span >
< span id = "cb5-28" > < a href = "#cb5-28" > < / a > g_object_unref < span class = "op" > (< / span > content< span class = "op" > );< / span > < / span >
< span id = "cb5-29" > < a href = "#cb5-29" > < / a > gtk_widget_add_controller < span class = "op" > (< / span > GTK_WIDGET < span class = "op" > (< / span > src_labels< span class = "op" > [< / span > i< span class = "op" > ]),< / span > GTK_EVENT_CONTROLLER < span class = "op" > (< / span > src< span class = "op" > ));< / span > < span class = "co" > // The ownership of src is taken by the instance.< / span > < / span >
< span id = "cb5-30" > < a href = "#cb5-30" > < / a > < span class = "op" > }< / span > < / span >
< span id = "cb5-31" > < a href = "#cb5-31" > < / a > < / span >
< span id = "cb5-32" > < a href = "#cb5-32" > < / a > tgt < span class = "op" > =< / span > gtk_drop_target_new < span class = "op" > (< / span > G_TYPE_STRING< span class = "op" > ,< / span > GDK_ACTION_COPY< span class = "op" > );< / span > < / span >
< span id = "cb5-33" > < a href = "#cb5-33" > < / a > g_signal_connect < span class = "op" > (< / span > tgt< span class = "op" > ,< / span > < span class = "st" > " drop" < / span > < span class = "op" > ,< / span > G_CALLBACK < span class = "op" > (< / span > drop_cb< span class = "op" > ),< / span > NULL< span class = "op" > );< / span > < / span >
< span id = "cb5-34" > < a href = "#cb5-34" > < / a > gtk_widget_add_controller < span class = "op" > (< / span > GTK_WIDGET < span class = "op" > (< / span > canvas< span class = "op" > ),< / span > GTK_EVENT_CONTROLLER < span class = "op" > (< / span > tgt< span class = "op" > ));< / span > < span class = "co" > // The ownership of tgt is taken by the instance.< / span > < / span >
< span id = "cb5-35" > < a href = "#cb5-35" > < / a > < / span >
< span id = "cb5-36" > < a href = "#cb5-36" > < / a > provider < span class = "op" > =< / span > gtk_css_provider_new < span class = "op" > ();< / span > < / span >
< span id = "cb5-37" > < a href = "#cb5-37" > < / a > s < span class = "op" > =< / span > g_strdup_printf < span class = "op" > (< / span > format< span class = "op" > ,< / span > < span class = "st" > " black" < / span > < span class = "op" > );< / span > < / span >
< span id = "cb5-38" > < a href = "#cb5-38" > < / a > gtk_css_provider_load_from_data < span class = "op" > (< / span > provider< span class = "op" > ,< / span > s< span class = "op" > ,< / span > < span class = "op" > -< / span > < span class = "dv" > 1< / span > < span class = "op" > );< / span > < / span >
< span id = "cb5-39" > < a href = "#cb5-39" > < / a > g_free < span class = "op" > (< / span > s< span class = "op" > );< / span > < / span >
< span id = "cb5-40" > < a href = "#cb5-40" > < / a > display < span class = "op" > =< / span > gdk_display_get_default < span class = "op" > ();< / span > < / span >
< span id = "cb5-41" > < a href = "#cb5-41" > < / a > gtk_style_context_add_provider_for_display < span class = "op" > (< / span > display< span class = "op" > ,< / span > GTK_STYLE_PROVIDER < span class = "op" > (< / span > provider< span class = "op" > ),< / span > < / span >
< span id = "cb5-42" > < a href = "#cb5-42" > < / a > GTK_STYLE_PROVIDER_PRIORITY_APPLICATION< span class = "op" > );< / span > < / span >
< span id = "cb5-43" > < a href = "#cb5-43" > < / a > g_object_unref < span class = "op" > (< / span > provider< span class = "op" > );< / span > < span class = "co" > // The provider is still alive because the display owns it.< / span > < / span >
< span id = "cb5-44" > < a href = "#cb5-44" > < / a > < span class = "op" > }< / span > < / span > < / code > < / pre > < / div >
2022-04-17 13:54:42 +02:00
< ul >
2023-07-29 14:41:57 +02:00
< li > 15-22: Builds the widgets. The array < code > source_labels[]< / code >
points the source labels red, green and blue in the ui file. The
variable < code > canvas< / code > points the destination label.< / li >
< li > 24-30: Sets the DND source widgets. The for-loop carries out through
the array < code > src_labels[]< / code > each of which points the source
widget, red, green or blue label.< / li >
< li > 25: Creates a new GtkDragSource instance.< / li >
< li > 26: Creates a new GdkContentProvider instance with the string “red”,
“green” or “blue. They are the name of the widgets. These strings are
the data to transfer through the DND operation.< / li >
< li > 27: Sets the content of the drag source to the GdkContentProvider
instance above.< / li >
< li > 28: Content is useless so it is destroyed.< / li >
< li > 29: Add the event controller, which is actually the drag source, to
the widget. If a DND operation starts on the widget, the corresponding
drag source works and the data is given to the system.< / li >
< li > 32-34: Sets the DND drop target.< / li >
< li > 32: Creates a new GtkDropTarget instance. The first parameter is the
GType of the data. The second parameter is a GdkDragAction enumerate
constant. The arguments here are string type and the constant for
copy.< / li >
< li > 33: Connects the “drop” signal and the handler
< code > drop_cb< / code > .< / li >
< li > 34: Add the event controller, which is actually the drop target, to
the widget.< / li >
< li > 36-43: Sets CSS.< / li >
< li > 37: A varable < code > format< / code > is static and defined at the top
of the program. Static variables are shown below.< / li >
2022-04-17 13:54:42 +02:00
< / ul >
2023-07-29 14:41:57 +02:00
< div class = "sourceCode" id = "cb6" > < pre class = "sourceCode C" > < code class = "sourceCode c" > < span id = "cb6-1" > < a href = "#cb6-1" aria-hidden = "true" tabindex = "-1" > < / a > < span class = "dt" > static< / span > GtkCssProvider < span class = "op" > *< / span > provider < span class = "op" > =< / span > NULL< span class = "op" > ;< / span > < / span >
< span id = "cb6-2" > < a href = "#cb6-2" aria-hidden = "true" tabindex = "-1" > < / a > < span class = "dt" > static< / span > < span class = "dt" > const< / span > < span class = "dt" > char< / span > < span class = "op" > *< / span > format < span class = "op" > =< / span > < span class = "st" > " label {padding: 20px;} label#red {background: red;} " < / span > < / span >
< span id = "cb6-3" > < a href = "#cb6-3" aria-hidden = "true" tabindex = "-1" > < / a > < span class = "st" > " label#green {background: green;} label#blue {background: blue;} " < / span > < / span >
< span id = "cb6-4" > < a href = "#cb6-4" aria-hidden = "true" tabindex = "-1" > < / a > < span class = "st" > " label#canvas {color: %s; font-weight: bold; font-size: 72pt;}" < / span > < span class = "op" > ;< / span > < / span > < / code > < / pre > < / div >
< h3 id = "activate-signal-handler" > Activate signal handler< / h3 >
< div class = "sourceCode" id = "cb7" > < pre
class="sourceCode numberSource C numberLines">< code class = "sourceCode c" > < span id = "cb7-1" > < a href = "#cb7-1" > < / a > < span class = "dt" > static< / span > < span class = "dt" > void< / span > < / span >
< span id = "cb7-2" > < a href = "#cb7-2" > < / a > app_activate < span class = "op" > (< / span > GApplication < span class = "op" > *< / span > application< span class = "op" > )< / span > < span class = "op" > {< / span > < / span >
< span id = "cb7-3" > < a href = "#cb7-3" > < / a > GtkApplication < span class = "op" > *< / span > app < span class = "op" > =< / span > GTK_APPLICATION < span class = "op" > (< / span > application< span class = "op" > );< / span > < / span >
< span id = "cb7-4" > < a href = "#cb7-4" > < / a > GtkWindow < span class = "op" > *< / span > win< span class = "op" > ;< / span > < / span >
< span id = "cb7-5" > < a href = "#cb7-5" > < / a > < / span >
< span id = "cb7-6" > < a href = "#cb7-6" > < / a > win < span class = "op" > =< / span > gtk_application_get_active_window < span class = "op" > (< / span > app< span class = "op" > );< / span > < / span >
< span id = "cb7-7" > < a href = "#cb7-7" > < / a > gtk_window_present < span class = "op" > (< / span > win< span class = "op" > );< / span > < / span >
< span id = "cb7-8" > < a href = "#cb7-8" > < / a > < span class = "op" > }< / span > < / span > < / code > < / pre > < / div >
< p > This handler just shows the window.< / p >
< h3 id = "drop-signal-handler" > Drop signal handler< / h3 >
< div class = "sourceCode" id = "cb8" > < pre
class="sourceCode numberSource C numberLines">< code class = "sourceCode c" > < span id = "cb8-1" > < a href = "#cb8-1" > < / a > < span class = "dt" > static< / span > gboolean< / span >
< span id = "cb8-2" > < a href = "#cb8-2" > < / a > drop_cb < span class = "op" > (< / span > GtkDropTarget< span class = "op" > *< / span > self< span class = "op" > ,< / span > < span class = "dt" > const< / span > GValue< span class = "op" > *< / span > value< span class = "op" > ,< / span > gdouble x< span class = "op" > ,< / span > gdouble y< span class = "op" > ,< / span > gpointer user_data< span class = "op" > )< / span > < span class = "op" > {< / span > < / span >
< span id = "cb8-3" > < a href = "#cb8-3" > < / a > < span class = "dt" > char< / span > < span class = "op" > *< / span > s< span class = "op" > ;< / span > < / span >
< span id = "cb8-4" > < a href = "#cb8-4" > < / a > < / span >
< span id = "cb8-5" > < a href = "#cb8-5" > < / a > s < span class = "op" > =< / span > g_strdup_printf < span class = "op" > (< / span > format< span class = "op" > ,< / span > g_value_get_string < span class = "op" > (< / span > value< span class = "op" > ));< / span > < / span >
< span id = "cb8-6" > < a href = "#cb8-6" > < / a > gtk_css_provider_load_from_data < span class = "op" > (< / span > provider< span class = "op" > ,< / span > s< span class = "op" > ,< / span > < span class = "op" > -< / span > < span class = "dv" > 1< / span > < span class = "op" > );< / span > < / span >
< span id = "cb8-7" > < a href = "#cb8-7" > < / a > g_free < span class = "op" > (< / span > s< span class = "op" > );< / span > < / span >
< span id = "cb8-8" > < a href = "#cb8-8" > < / a > < span class = "cf" > return< / span > TRUE< span class = "op" > ;< / span > < / span >
< span id = "cb8-9" > < a href = "#cb8-9" > < / a > < span class = "op" > }< / span > < / span > < / code > < / pre > < / div >
< p > The “drop” signal handler has five parameters.< / p >
2022-04-17 13:54:42 +02:00
< ul >
2023-07-29 14:41:57 +02:00
< li > GtkDropTarget instance on which the signal has been emitted.< / li >
< li > GValue that holds the data from the source.< / li >
< li > The arguments < code > x< / code > and < code > y< / code > are the coordinate
of the mouse when released.< / li >
< li > User data was set when the signal and handler was connected.< / li >
2022-04-17 13:54:42 +02:00
< / ul >
2023-07-29 14:41:57 +02:00
< p > The string from the GValue is “red”, “green” or “blue”. It replaces
“%s” in the variable < code > format< / code > . That means the font color of
the label < code > canvas< / code > will turn to the color.< / p >
< h2 id = "meson.build" > Meson.build< / h2 >
< p > The file < code > meson.build< / code > controls the building process.< / p >
< div class = "sourceCode" id = "cb9" > < pre
class="sourceCode numberSource numberLines">< code class = "sourceCode" > < span id = "cb9-1" > < a href = "#cb9-1" > < / a > project(' dnd' , ' c' )< / span >
< span id = "cb9-2" > < a href = "#cb9-2" > < / a > < / span >
< span id = "cb9-3" > < a href = "#cb9-3" > < / a > gtkdep = dependency(' gtk4' )< / span >
< span id = "cb9-4" > < a href = "#cb9-4" > < / a > < / span >
< span id = "cb9-5" > < a href = "#cb9-5" > < / a > gnome = import(' gnome' )< / span >
< span id = "cb9-6" > < a href = "#cb9-6" > < / a > resources = gnome.compile_resources(' resources' ,' dnd.gresource.xml' )< / span >
< span id = "cb9-7" > < a href = "#cb9-7" > < / a > < / span >
< span id = "cb9-8" > < a href = "#cb9-8" > < / a > executable(meson.project_name(), ' dnd.c' , resources, dependencies: gtkdep, export_dynamic: true, install: false)< / span > < / code > < / pre > < / div >
< p > You can build it from the command line.< / p >
< pre > < code > $ cd src/dnd
$ meson setup _build
$ ninja -C _build
$ _build/dnd< / code > < / pre >
< p > The source files are under the directory < code > src/dnd< / code > of the
< a href = "https://github.com/ToshioCP/Gtk4-tutorial" > repository< / a > .
Download it and see the directory.< / p >
2022-04-21 16:53:28 +02:00
< / div >
< script src = "https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity = "sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin = "anonymous" > < / script >
< / body >
< / html >