Compare commits
322 Commits
columnview
...
search-eng
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a59ef54dc8 | ||
|
|
63692a491d | ||
|
|
bbe79c1ef9 | ||
|
|
4b241f8da2 | ||
|
|
bdd6ae3252 | ||
|
|
24a3ff3aef | ||
|
|
ba988cd899 | ||
|
|
1bf1646d25 | ||
|
|
2c82151d65 | ||
|
|
d2235b71f3 | ||
|
|
57135acd2d | ||
|
|
54c098761f | ||
|
|
2f98400b80 | ||
|
|
ea7c9b93ea | ||
|
|
4317c008f0 | ||
|
|
d605d9ae73 | ||
|
|
c9fad25131 | ||
|
|
693200f1eb | ||
|
|
5f087a9dff | ||
|
|
b9cde6f8ea | ||
|
|
86eece78b1 | ||
|
|
8cb50ac6e9 | ||
|
|
997fbbde8f | ||
|
|
805ddc3c3a | ||
|
|
da9b3a9256 | ||
|
|
876560924f | ||
|
|
ca1c89c5bd | ||
|
|
7875e28d9f | ||
|
|
bd2f2a6f65 | ||
|
|
541aaa2392 | ||
|
|
d294b01cee | ||
|
|
5d9dc25115 | ||
|
|
c8988ec784 | ||
|
|
071dbc1115 | ||
|
|
80c5e4a156 | ||
|
|
6eac3063fa | ||
|
|
27925fcb0e | ||
|
|
5f4d21422a | ||
|
|
b0bb413faa | ||
|
|
37633985bd | ||
|
|
6ff8f1b2fd | ||
|
|
d13a3c7540 | ||
|
|
0a469d7bd6 | ||
|
|
115edc5fd1 | ||
|
|
a28c75f215 | ||
|
|
b9d7dab329 | ||
|
|
bb7500e984 | ||
|
|
e94268944b | ||
|
|
3225b487e8 | ||
|
|
e35c0e043e | ||
|
|
b251893030 | ||
|
|
15257e3922 | ||
|
|
180a5a1ad7 | ||
|
|
11f971d870 | ||
|
|
7c382c6b47 | ||
|
|
087f42d998 | ||
|
|
2abb5b6419 | ||
|
|
f2259adcdc | ||
|
|
a73457237d | ||
|
|
9f335d3ee6 | ||
|
|
856c8950ff | ||
|
|
61ccf4e719 | ||
|
|
1567db1f02 | ||
|
|
8316d5e366 | ||
|
|
8fca040163 | ||
|
|
c0fe1a7ffe | ||
|
|
e72c243aca | ||
|
|
14605d4b92 | ||
|
|
d1509971d8 | ||
|
|
951c9c5d73 | ||
|
|
3e6e247e56 | ||
|
|
27ce68b74a | ||
|
|
b0cf7a95b0 | ||
|
|
fd7f19c934 | ||
|
|
8090e213de | ||
|
|
de6327a885 | ||
|
|
8699c0f340 | ||
|
|
bda5454549 | ||
|
|
c3a6e35070 | ||
|
|
71c29bfcff | ||
|
|
647ed59d11 | ||
|
|
a0c489048a | ||
|
|
0f9def660d | ||
|
|
9fa65eadae | ||
|
|
facfff0022 | ||
|
|
f8b4083f47 | ||
|
|
b047b7838d | ||
|
|
b1c00ecee6 | ||
|
|
93abd8da59 | ||
|
|
3412f0554f | ||
|
|
61c83f9ffe | ||
|
|
3d7c1f8950 | ||
|
|
b0e81acc12 | ||
|
|
a682d97663 | ||
|
|
0e5137ae61 | ||
|
|
005a3da18f | ||
|
|
be6bcf882d | ||
|
|
fb344e8108 | ||
|
|
b99389bcb8 | ||
|
|
0fefdc99b2 | ||
|
|
e63419fbf4 | ||
|
|
428bb09a35 | ||
|
|
7c2c795681 | ||
|
|
165f352c58 | ||
|
|
3d6e702f63 | ||
|
|
597e9a96b4 | ||
|
|
6f4ed6c105 | ||
|
|
c3eafed472 | ||
|
|
7480fb703e | ||
|
|
24e8b484e0 | ||
|
|
d60f7f2e7a | ||
|
|
0dcffe7c33 | ||
|
|
9f09cfcfbd | ||
|
|
7373cd962c | ||
|
|
ac3f0df083 | ||
|
|
f95d54a13d | ||
|
|
fc512f0b9f | ||
|
|
f5ed59b7f2 | ||
|
|
9d51aa1443 | ||
|
|
f0bdc865b9 | ||
|
|
eda1703f9d | ||
|
|
51fc382582 | ||
|
|
6e52ef96a4 | ||
|
|
9606c1eee9 | ||
|
|
959c101400 | ||
|
|
6b096e5c5b | ||
|
|
9ac1eacdc8 | ||
|
|
8e7395a7e3 | ||
|
|
80fbc1b72d | ||
|
|
17ea03eee2 | ||
|
|
985b5a052e | ||
|
|
ed1872f0a8 | ||
|
|
34841c3a5f | ||
|
|
185f0181ac | ||
|
|
60d6a0f2d5 | ||
|
|
99a1d10bf1 | ||
|
|
2f1028ed79 | ||
|
|
f631e0e1e0 | ||
|
|
6df489d5a9 | ||
|
|
15c6ad88c0 | ||
|
|
40f6a9d830 | ||
|
|
bd06c00f3a | ||
|
|
f6d23f0c29 | ||
|
|
2a24459b92 | ||
|
|
f6da324670 | ||
|
|
11a18bd61a | ||
|
|
972134abe4 | ||
|
|
f8770b78ea | ||
|
|
10f2b11fda | ||
|
|
ea1cc4b991 | ||
|
|
8bee3e2fe0 | ||
|
|
1f7adfd9ff | ||
|
|
9e55cd68e4 | ||
|
|
2a6dc67fd7 | ||
|
|
1061ad289a | ||
|
|
0f81b58545 | ||
|
|
2437c5a0ae | ||
|
|
669a6ddeaa | ||
|
|
f5de46670b | ||
|
|
91af8a705b | ||
|
|
82c314f1af | ||
|
|
672413f1f6 | ||
|
|
843bf23f84 | ||
|
|
eeb2d2cc38 | ||
|
|
c370b8f309 | ||
|
|
acd9c12667 | ||
|
|
5535b26395 | ||
|
|
20611cf68c | ||
|
|
06c34ce02f | ||
|
|
4fb50c7408 | ||
|
|
c37bea1676 | ||
|
|
ed985640e8 | ||
|
|
2bd938952d | ||
|
|
623a56391c | ||
|
|
1b7fb10361 | ||
|
|
f6b6688186 | ||
|
|
99453e937c | ||
|
|
d3e0a1f68c | ||
|
|
76ff1a2a49 | ||
|
|
51c6ce1734 | ||
|
|
1998b673f4 | ||
|
|
627497f942 | ||
|
|
f9287941b4 | ||
|
|
5059854a2e | ||
|
|
aa8a061a83 | ||
|
|
3f2d44d517 | ||
|
|
b4af23be23 | ||
|
|
8ddf1f1ea5 | ||
|
|
475d8c4c11 | ||
|
|
fc823eb610 | ||
|
|
8707bab450 | ||
|
|
612955f2b7 | ||
|
|
36314c3ff7 | ||
|
|
33fb38d8de | ||
|
|
38e2a910df | ||
|
|
ef32df77be | ||
|
|
5154693ea4 | ||
|
|
4b68362981 | ||
|
|
658e4c5357 | ||
|
|
ce0dd650d7 | ||
|
|
77b65ada4f | ||
|
|
fa37225a42 | ||
|
|
78a06859b9 | ||
|
|
3ec8f4e84e | ||
|
|
f13a596d15 | ||
|
|
94f14778a3 | ||
|
|
7312284e4f | ||
|
|
ebc07d1458 | ||
|
|
510f719975 | ||
|
|
03c2202942 | ||
|
|
b3a97cb755 | ||
|
|
a9273e1c73 | ||
|
|
14d11ebcab | ||
|
|
7dc458d925 | ||
|
|
a0f04bdcf3 | ||
|
|
28f6e27276 | ||
|
|
5ef427bd65 | ||
|
|
03c1fa43f4 | ||
|
|
3b9f0ab866 | ||
|
|
9617a00ae3 | ||
|
|
1408199957 | ||
|
|
067df8d4dd | ||
|
|
2ab1b13092 | ||
|
|
964d0c219a | ||
|
|
c58eb9c276 | ||
|
|
5d4893b3f0 | ||
|
|
11b4e0d4c0 | ||
|
|
e637693131 | ||
|
|
c9d5b77403 | ||
|
|
574595993c | ||
|
|
50f4e53aef | ||
|
|
ac082e5504 | ||
|
|
f65f9591a1 | ||
|
|
a1eadde25b | ||
|
|
66e5027756 | ||
|
|
aa2d339508 | ||
|
|
d43aacefc9 | ||
|
|
f0a0e20b2f | ||
|
|
befdd8bb66 | ||
|
|
27ed2cc009 | ||
|
|
a60c866a12 | ||
|
|
a84f6228ca | ||
|
|
19da93b675 | ||
|
|
aa38fc712f | ||
|
|
0b1c91dc7c | ||
|
|
ab2c8de4de | ||
|
|
00f2b134e3 | ||
|
|
0b8cebd6ef | ||
|
|
53a9b7f6c0 | ||
|
|
667fd927ee | ||
|
|
a8956838d3 | ||
|
|
e7c9e2060c | ||
|
|
f6be407e33 | ||
|
|
2bf9b37e59 | ||
|
|
d2e0ada794 | ||
|
|
c07ae5806e | ||
|
|
5afe6f7825 | ||
|
|
d02c48f987 | ||
|
|
c835214540 | ||
|
|
cb2901ec40 | ||
|
|
f27bd061fb | ||
|
|
572386e4ce | ||
|
|
67a972182e | ||
|
|
5955e11a5a | ||
|
|
8daaafc864 | ||
|
|
ebaa96c0fa | ||
|
|
fb3d08c651 | ||
|
|
9d15e64f0b | ||
|
|
b62564fd98 | ||
|
|
0266bcab7a | ||
|
|
6652e14662 | ||
|
|
7a50f86f3f | ||
|
|
59218d02c8 | ||
|
|
fe73730d21 | ||
|
|
b814970bdd | ||
|
|
8dfbef5e6f | ||
|
|
0b9a3fc160 | ||
|
|
79105962a7 | ||
|
|
a36e2bc764 | ||
|
|
cc878160bd | ||
|
|
382153e82d | ||
|
|
e195341e30 | ||
|
|
c6c8263704 | ||
|
|
ed02bea20d | ||
|
|
f89a1b05fe | ||
|
|
af65b7e6d7 | ||
|
|
1995ad6d63 | ||
|
|
83c0937a46 | ||
|
|
f5cc2c0d20 | ||
|
|
931d68bc92 | ||
|
|
06946c35d3 | ||
|
|
cbe81fd443 | ||
|
|
173e919d2a | ||
|
|
73fdb8f7b0 | ||
|
|
8e0ba37866 | ||
|
|
8780f50e7e | ||
|
|
06dc357ea0 | ||
|
|
fb587cb529 | ||
|
|
a026677849 | ||
|
|
1c389b1f24 | ||
|
|
55b9aa0309 | ||
|
|
2d5cf2b4c4 | ||
|
|
4877bb5b5c | ||
|
|
b9269d5644 | ||
|
|
1a4723988e | ||
|
|
93353888ca | ||
|
|
c3a90b76d0 | ||
|
|
43e5ca9a1b | ||
|
|
c5829bd0e2 | ||
|
|
2a9d2cc7e9 | ||
|
|
0d9873d8bc | ||
|
|
23bc38ed06 | ||
|
|
42d26b4b05 | ||
|
|
04700789e1 | ||
|
|
e23baa59f0 | ||
|
|
e8e28b61db | ||
|
|
b766707f28 | ||
|
|
0787f262a0 | ||
|
|
d833f4a632 | ||
|
|
ce1e364ab8 | ||
|
|
adb5b299c9 | ||
|
|
0bd039a524 |
89
NEWS
89
NEWS
@@ -1,3 +1,92 @@
|
||||
Overview of Changes in GTK 3.98.5
|
||||
=================================
|
||||
|
||||
* Introduce new list widgets and supporting infrastructure.
|
||||
The main APIs are:
|
||||
- GtkListView
|
||||
- GtkGridView
|
||||
- GtkColumnView and GtkColumnViewColumn
|
||||
- GtkDropDown
|
||||
- GtkListItemFactory and implementations
|
||||
- GtkExpression
|
||||
- GtkFilter and subclasses, and GtkFilterListModel
|
||||
- GtkSorter and subclasses, and GtkSortListModel
|
||||
- GtkSelectionModel and subclasses
|
||||
- GtkTreeListModel, GtkTreeExpander and GtkTreeListRowSorter
|
||||
|
||||
* GtkFileChooser:
|
||||
- Add a tracker3-based search engine implementation
|
||||
- Rate-limit updates from the trash monitor
|
||||
|
||||
* GtkWindow:
|
||||
- Redo the css node setup. There is now a single 'window' node
|
||||
- Fix rounded corners on tiled windows
|
||||
|
||||
* GtkApplication:
|
||||
- Drop app menu support. Menubar support is still there
|
||||
|
||||
* GtkFixed:
|
||||
- Change coordinate APIs to take doubles
|
||||
|
||||
* GtkOverlay:
|
||||
- Make GtkOverlayLayout public
|
||||
|
||||
* GtkTooltips:
|
||||
- Fix line wrapping of tooltips
|
||||
|
||||
* Shortcuts:
|
||||
- Fix mnemonic cycling
|
||||
- Fix using '0' as a mnemonic
|
||||
|
||||
* Menus:
|
||||
- Differentiate keypad keys in accelerators
|
||||
|
||||
* GtkIMContext:
|
||||
- Add gtk_im_context_filter_key to allow event reinjection
|
||||
|
||||
* Themes:
|
||||
- Adwaita: Limit the scope of backdrop
|
||||
|
||||
* Accessibility:
|
||||
- Clean up and reorganize the code to prepare for the
|
||||
dropping of ATK
|
||||
|
||||
* GDK:
|
||||
- Drop unused enum and struct definitions from headers
|
||||
- Make keymap translation API public again. Still needed
|
||||
- Frameclock: Always use compositor refresh rate info
|
||||
- Frameclock: Use quadratic correction for frame time jitter
|
||||
- Frameclock: Ensure monotonicity
|
||||
- Frameclock: Track resason for paint
|
||||
- X11: Improve sync when the Nvidia driver is used
|
||||
|
||||
* GSK:
|
||||
- GL renderer: Fix blurred outset shadows
|
||||
- GL renderer: handle nested transform nodes properly
|
||||
- GL renderer: Optimize clip handling
|
||||
|
||||
* gtk-demo:
|
||||
- Improve the Drag-and-Drop demo with proper drag icons
|
||||
- Don't show the main window if --run is given
|
||||
- Add demos for list widgets and GtkDropDrown
|
||||
|
||||
* Documentation:
|
||||
- Convert freestanding sections to markdown
|
||||
- Drop the glossary
|
||||
- Expand and improve the migration guide
|
||||
|
||||
* Build:
|
||||
- We require pandoc now, for building the documentation
|
||||
- Require Pango 1.45
|
||||
|
||||
* Translation updates:
|
||||
Polish
|
||||
Romanian
|
||||
Slovenian
|
||||
Turkish
|
||||
Ukrainian
|
||||
|
||||
|
||||
Overview of Changes in GTK 3.98.4
|
||||
=================================
|
||||
|
||||
|
||||
@@ -27,18 +27,6 @@
|
||||
/* Define to 1 if you have the `dcgettext' function. */
|
||||
#mesondefine HAVE_DCGETTEXT
|
||||
|
||||
/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't.
|
||||
*/
|
||||
#mesondefine HAVE_DECL_ISINF
|
||||
|
||||
/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't.
|
||||
*/
|
||||
#mesondefine HAVE_DECL_ISNAN
|
||||
|
||||
/* Define to 1 if you have the declaration of `isnanf', and to 0 if you don't.
|
||||
*/
|
||||
#mesondefine HAVE_DECL_ISNANF
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#mesondefine HAVE_DLFCN_H
|
||||
|
||||
@@ -84,9 +72,6 @@
|
||||
/* Define to 1 if you have a working `mmap' system call. */
|
||||
#mesondefine HAVE_MMAP
|
||||
|
||||
/* Define to 1 if you have the `nearbyint' function. */
|
||||
#mesondefine HAVE_NEARBYINT
|
||||
|
||||
/* Define to 1 if you have the `posix_fallocate' function. */
|
||||
#mesondefine HAVE_POSIX_FALLOCATE
|
||||
|
||||
@@ -96,21 +81,9 @@
|
||||
/* Have the Xrandr 1.5 extension library */
|
||||
#mesondefine HAVE_RANDR15
|
||||
|
||||
/* Define to 1 if you have the `rint' function. */
|
||||
#mesondefine HAVE_RINT
|
||||
|
||||
/* Define to 1 if you have the `round' function. */
|
||||
#mesondefine HAVE_ROUND
|
||||
|
||||
/* Define to 1 if you have the `sincos' function. */
|
||||
#mesondefine HAVE_SINCOS
|
||||
|
||||
/* Define to 1 if you have the `log2` function */
|
||||
#mesondefine HAVE_LOG2
|
||||
|
||||
/* Define to 1 if you ahve the `exp2` function */
|
||||
#mesondefine HAVE_EXP2
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#mesondefine HAVE_STDINT_H
|
||||
|
||||
@@ -150,6 +123,9 @@
|
||||
/* Have the Xcursor library */
|
||||
#mesondefine HAVE_XCURSOR
|
||||
|
||||
/* Have the XDAMAGE X extension */
|
||||
#mesondefine HAVE_XDAMAGE
|
||||
|
||||
/* Have the XFIXES X extension */
|
||||
#mesondefine HAVE_XFIXES
|
||||
|
||||
|
||||
@@ -1,247 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2018 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "award.h"
|
||||
|
||||
struct _GtkAward
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
char *explanation;
|
||||
char *name;
|
||||
char *title;
|
||||
GDateTime *granted; /* or NULL if not granted */
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_EXPLANATION,
|
||||
PROP_NAME,
|
||||
PROP_TITLE,
|
||||
PROP_GRANTED,
|
||||
|
||||
N_PROPS,
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
G_DEFINE_TYPE (GtkAward, gtk_award, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_award_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
|
||||
{
|
||||
GtkAward *self = GTK_AWARD (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_EXPLANATION:
|
||||
self->explanation = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
self->name = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_TITLE:
|
||||
self->title = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_award_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkAward *self = GTK_AWARD (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_EXPLANATION:
|
||||
g_value_set_string (value, self->explanation);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, self->name);
|
||||
break;
|
||||
|
||||
case PROP_TITLE:
|
||||
g_value_set_string (value, self->title);
|
||||
break;
|
||||
|
||||
case PROP_GRANTED:
|
||||
g_value_set_boxed (value, self->granted);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_award_dispose (GObject *object)
|
||||
{
|
||||
GtkAward *self = GTK_AWARD (object);
|
||||
|
||||
g_clear_pointer (&self->name, g_free);
|
||||
g_clear_pointer (&self->title, g_free);
|
||||
g_clear_pointer (&self->granted, g_date_time_unref);
|
||||
|
||||
G_OBJECT_CLASS (gtk_award_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_award_class_init (GtkAwardClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
|
||||
gobject_class->set_property = gtk_award_set_property;
|
||||
gobject_class->get_property = gtk_award_get_property;
|
||||
gobject_class->dispose = gtk_award_dispose;
|
||||
|
||||
properties[PROP_EXPLANATION] =
|
||||
g_param_spec_string ("explanation",
|
||||
"Explanation",
|
||||
"How to get the title",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_NAME] =
|
||||
g_param_spec_string ("name",
|
||||
"Name",
|
||||
"internal name of the award",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_TITLE] =
|
||||
g_param_spec_string ("title",
|
||||
"Title",
|
||||
"user-visible title",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_GRANTED] =
|
||||
g_param_spec_boxed ("granted",
|
||||
"Granted",
|
||||
"Timestamp the award was granted or NULL if not granted yet",
|
||||
G_TYPE_DATE_TIME,
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_award_init (GtkAward *self)
|
||||
{
|
||||
}
|
||||
|
||||
GListModel *
|
||||
gtk_award_get_list (void)
|
||||
{
|
||||
static GListModel *list = NULL;
|
||||
|
||||
if (list == NULL)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
|
||||
g_type_ensure (GTK_TYPE_AWARD);
|
||||
builder = gtk_builder_new_from_resource ("/awards.ui");
|
||||
list = G_LIST_MODEL (gtk_builder_get_object (builder, "list"));
|
||||
g_object_ref (list);
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
return g_object_ref (list);
|
||||
}
|
||||
|
||||
const char *
|
||||
gtk_award_get_name (GtkAward *award)
|
||||
{
|
||||
return award->name;
|
||||
}
|
||||
|
||||
const char *
|
||||
gtk_award_get_title (GtkAward *award)
|
||||
{
|
||||
return award->title;
|
||||
}
|
||||
|
||||
GDateTime *
|
||||
gtk_award_get_granted (GtkAward *award)
|
||||
{
|
||||
return award->granted;
|
||||
}
|
||||
|
||||
GtkAward *
|
||||
award_find (const char *name)
|
||||
{
|
||||
GListModel *list;
|
||||
GtkAward *self;
|
||||
guint i;
|
||||
|
||||
list = gtk_award_get_list ();
|
||||
g_object_unref (list);
|
||||
|
||||
for (i = 0; i < g_list_model_get_n_items (list); i++)
|
||||
{
|
||||
self = g_list_model_get_item (list, i);
|
||||
g_object_unref (self);
|
||||
|
||||
if (g_ascii_strcasecmp (name, self->name) == 0)
|
||||
return self;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
award (const char *name)
|
||||
{
|
||||
GtkAward *self;
|
||||
GNotification *notification;
|
||||
|
||||
self = award_find (name);
|
||||
if (self == NULL)
|
||||
{
|
||||
g_warning ("Did not find award \"%s\"", name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->granted)
|
||||
return;
|
||||
|
||||
self->granted = g_date_time_new_now_utc ();
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_GRANTED]);
|
||||
|
||||
notification = g_notification_new ("You won an award!");
|
||||
g_notification_set_body (notification, self->title);
|
||||
g_application_send_notification (g_application_get_default (), NULL, notification);
|
||||
g_object_unref (notification);
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
#ifndef __AWARD_H__
|
||||
#define __AWARD_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define GTK_TYPE_AWARD (gtk_award_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GtkAward, gtk_award, GTK, AWARD, GObject)
|
||||
|
||||
GListModel * gtk_award_get_list (void);
|
||||
|
||||
const char * gtk_award_get_name (GtkAward *award);
|
||||
const char * gtk_award_get_title (GtkAward *award);
|
||||
GDateTime * gtk_award_get_granted (GtkAward *award);
|
||||
|
||||
void award (const char *name);
|
||||
|
||||
#endif /* __AWARD_H__ */
|
||||
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="gtk40">
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="label" bind-source="GtkListItem" bind-property="position"></property>
|
||||
<property name="margin">6</property>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
@@ -1,89 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GListStore" id="list">
|
||||
<property name="item-type">GtkAward</property>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">demo-inspector</property>
|
||||
<!-- Transformers -->
|
||||
<property name="title" translatable="yes">You got a high-rise double-pump carburetor.</property>
|
||||
<property name="explanation" translatable="yes">Launch the inspector</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">demo-start</property>
|
||||
<!-- The Matrix -->
|
||||
<property name="title" translatable="yes">After this, there is no turning back.</property>
|
||||
<property name="explanation" translatable="yes">Start gtk-demo</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">listbox-reshare</property>
|
||||
<!-- Mean Girls -->
|
||||
<property name="title" translatable="yes">Trying to make fetch happen</property>
|
||||
<property name="explanation" translatable="yes">Reshare a tweet</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">listbox-100th-row</property>
|
||||
<!-- Aladdin -->
|
||||
<property name="title" translatable="yes">The ever impressive, long contained, often imitated, but never duplicated Genie of the lamp.</property>
|
||||
<property name="explanation" translatable="yes">Select a 100th row in a list</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">password-best</property>
|
||||
<!-- Spaceballs -->
|
||||
<property name="title" translatable="yes">I've got the same combination on my luggage!</property>
|
||||
<property name="explanation" translatable="yes">Use "12345" as the password</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">password-correct</property>
|
||||
<!-- Stanley Parable -->
|
||||
<property name="title" translatable="yes">Night Shark 1-1-5</property>
|
||||
<property name="explanation" translatable="yes">Correctly enter a password</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">puzzle-give-up</property>
|
||||
<!-- Pretty Woman -->
|
||||
<property name="title" translatable="yes">Big Mistake. Big. Huge!</property>
|
||||
<property name="explanation" translatable="yes">Close the puzzle without finishing it</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">puzzle-solve</property>
|
||||
<!-- The Incredibles -->
|
||||
<property name="title" translatable="yes">That was totally wicked!</property>
|
||||
<property name="explanation" translatable="yes">Solve a puzzle</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">puzzle-solve-animated</property>
|
||||
<!-- The Phantom Menace -->
|
||||
<property name="title" translatable="yes">A surprise to be sure but a welcome one.</property>
|
||||
<property name="explanation" translatable="yes">Solve an animated puzzle</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">puzzle-solve-large</property>
|
||||
<!-- Portal -->
|
||||
<property name="title" translatable="yes">Science isn't about WHY. It's about WHY NOT?!</property>
|
||||
<property name="explanation" translatable="yes">Solve a puzzle with at least 20 pieces</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -1,48 +0,0 @@
|
||||
/* Awards
|
||||
*
|
||||
* This demo demonstrates how to use lists to show the awards you have collected
|
||||
* while exploring this demo.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/* Include the header for accessing the awards */
|
||||
#include "award.h"
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
do_awardview (GtkWidget *do_widget)
|
||||
{
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *sw, *listview;
|
||||
GListModel *list;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Awards");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
|
||||
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_window_set_child (GTK_WINDOW (window), sw);
|
||||
|
||||
listview = gtk_list_view_new_with_factory (
|
||||
gtk_builder_list_item_factory_new_from_resource (NULL, "/awardview/awardlistitem.ui"));
|
||||
list = gtk_award_get_list ();
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (listview), list);
|
||||
g_object_unref (list);
|
||||
gtk_list_view_set_show_separators (GTK_LIST_VIEW (listview), TRUE);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), listview);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/* Constraints/Interactive
|
||||
*
|
||||
* Demonstrate how constraints can be updates during
|
||||
* user interaction.
|
||||
* Demonstrate how constraints can be updates during user interaction.
|
||||
* The vertical edge between the buttons can be dragged with the mouse.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
/* Cursors
|
||||
*
|
||||
* Demonstrates a useful set of available cursors. The cursors shown here are the ones
|
||||
* defined by CSS, which we assume to be available.
|
||||
*
|
||||
* The example shows creating cursors by name or from an image, with or without a fallback.
|
||||
* Demonstrates a useful set of available cursors. The cursors shown here are the
|
||||
* ones defined by CSS, which we assume to be available. The example shows creating
|
||||
* cursors by name or from an image, with or without a fallback.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/">
|
||||
<file>awards.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/ui">
|
||||
<file preprocess="xml-stripblanks">main.ui</file>
|
||||
@@ -12,9 +11,6 @@
|
||||
<file>application.ui</file>
|
||||
<file>menus.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/awardview">
|
||||
<file>awardlistitem.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/builder">
|
||||
<file>demo.ui</file>
|
||||
</gresource>
|
||||
@@ -127,6 +123,7 @@
|
||||
</gresource>
|
||||
<gresource prefix="/listview_filebrowser">
|
||||
<file>listview_filebrowser.ui</file>
|
||||
<file>listview_filebrowser.css</file>
|
||||
</gresource>
|
||||
<gresource prefix="/listview_minesweeper">
|
||||
<file>listview_minesweeper.ui</file>
|
||||
@@ -177,7 +174,6 @@
|
||||
</gresource>
|
||||
<gresource prefix="/sources">
|
||||
<file>application_demo.c</file>
|
||||
<file>awardview.c</file>
|
||||
<file>assistant.c</file>
|
||||
<file>builder.c</file>
|
||||
<file>clipboard.c</file>
|
||||
@@ -194,6 +190,7 @@
|
||||
<file>cursors.c</file>
|
||||
<file>dialog.c</file>
|
||||
<file>drawingarea.c</file>
|
||||
<file>dropdown.c</file>
|
||||
<file>dnd.c</file>
|
||||
<file>editable_cells.c</file>
|
||||
<file>entry_completion.c</file>
|
||||
|
||||
305
demos/gtk-demo/dropdown.c
Normal file
305
demos/gtk-demo/dropdown.c
Normal file
@@ -0,0 +1,305 @@
|
||||
/* Drop Downs
|
||||
*
|
||||
* The GtkDropDown widget is a modern alternative to GtkComboBox.
|
||||
* It uses list models instead of tree models, and the content is
|
||||
* displayed using widgets instead of cell renderers.
|
||||
*
|
||||
* The examples here demonstrate how to use different kinds of
|
||||
* list models with GtkDropDown, how to use search and how to
|
||||
* display the selected item differently from the presentation
|
||||
* in the popup.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
||||
#define STRING_TYPE_HOLDER (string_holder_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (StringHolder, string_holder, STRING, HOLDER, GObject)
|
||||
|
||||
struct _StringHolder {
|
||||
GObject parent_instance;
|
||||
char *title;
|
||||
char *icon;
|
||||
char *description;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (StringHolder, string_holder, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
string_holder_init (StringHolder *holder)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
string_holder_finalize (GObject *object)
|
||||
{
|
||||
StringHolder *holder = STRING_HOLDER (object);
|
||||
|
||||
g_free (holder->title);
|
||||
g_free (holder->icon);
|
||||
g_free (holder->description);
|
||||
|
||||
G_OBJECT_CLASS (string_holder_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
string_holder_class_init (StringHolderClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = string_holder_finalize;
|
||||
}
|
||||
|
||||
static StringHolder *
|
||||
string_holder_new (const char *title, const char *icon, const char *description)
|
||||
{
|
||||
StringHolder *holder = g_object_new (STRING_TYPE_HOLDER, NULL);
|
||||
holder->title = g_strdup (title);
|
||||
holder->icon = g_strdup (icon);
|
||||
holder->description = g_strdup (description);
|
||||
return holder;
|
||||
}
|
||||
|
||||
static void
|
||||
strings_setup_item_single_line (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GtkWidget *box, *image, *title;
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
|
||||
|
||||
image = gtk_image_new ();
|
||||
title = gtk_label_new ("");
|
||||
gtk_label_set_xalign (GTK_LABEL (title), 0.0);
|
||||
|
||||
gtk_box_append (GTK_BOX (box), image);
|
||||
gtk_box_append (GTK_BOX (box), title);
|
||||
|
||||
g_object_set_data (G_OBJECT (item), "title", title);
|
||||
g_object_set_data (G_OBJECT (item), "image", image);
|
||||
|
||||
gtk_list_item_set_child (item, box);
|
||||
}
|
||||
|
||||
static void
|
||||
strings_setup_item_full (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GtkWidget *box, *box2, *image, *title, *description;
|
||||
|
||||
image = gtk_image_new ();
|
||||
title = gtk_label_new ("");
|
||||
gtk_label_set_xalign (GTK_LABEL (title), 0.0);
|
||||
description = gtk_label_new ("");
|
||||
gtk_label_set_xalign (GTK_LABEL (description), 0.0);
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (description), "dim-label");
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
|
||||
box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
|
||||
|
||||
gtk_box_append (GTK_BOX (box), image);
|
||||
gtk_box_append (GTK_BOX (box), box2);
|
||||
gtk_box_append (GTK_BOX (box2), title);
|
||||
gtk_box_append (GTK_BOX (box2), description);
|
||||
|
||||
g_object_set_data (G_OBJECT (item), "title", title);
|
||||
g_object_set_data (G_OBJECT (item), "image", image);
|
||||
g_object_set_data (G_OBJECT (item), "description", description);
|
||||
|
||||
gtk_list_item_set_child (item, box);
|
||||
}
|
||||
|
||||
static void
|
||||
strings_bind_item (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GtkWidget *image, *title, *description;
|
||||
StringHolder *holder;
|
||||
|
||||
holder = gtk_list_item_get_item (item);
|
||||
|
||||
title = g_object_get_data (G_OBJECT (item), "title");
|
||||
image = g_object_get_data (G_OBJECT (item), "image");
|
||||
description = g_object_get_data (G_OBJECT (item), "description");
|
||||
|
||||
gtk_label_set_label (GTK_LABEL (title), holder->title);
|
||||
if (image)
|
||||
{
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (image), holder->icon);
|
||||
gtk_widget_set_visible (image, holder->icon != NULL);
|
||||
}
|
||||
if (description)
|
||||
{
|
||||
gtk_label_set_label (GTK_LABEL (description), holder->description);
|
||||
gtk_widget_set_visible (description , holder->description != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static GtkListItemFactory *
|
||||
strings_factory_new (gboolean full)
|
||||
{
|
||||
GtkListItemFactory *factory;
|
||||
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
if (full)
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (strings_setup_item_full), NULL);
|
||||
else
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (strings_setup_item_single_line), NULL);
|
||||
g_signal_connect (factory, "bind", G_CALLBACK (strings_bind_item), NULL);
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
strings_model_new (const char *const *titles,
|
||||
const char *const *icons,
|
||||
const char *const *descriptions)
|
||||
{
|
||||
GListStore *store;
|
||||
int i;
|
||||
|
||||
store = g_list_store_new (STRING_TYPE_HOLDER);
|
||||
for (i = 0; titles[i]; i++)
|
||||
{
|
||||
StringHolder *holder = string_holder_new (titles[i],
|
||||
icons ? icons[i] : NULL,
|
||||
descriptions ? descriptions[i] : NULL);
|
||||
g_list_store_append (store, holder);
|
||||
g_object_unref (holder);
|
||||
}
|
||||
|
||||
return G_LIST_MODEL (store);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
drop_down_new_from_strings (const char *const *titles,
|
||||
const char *const *icons,
|
||||
const char *const *descriptions)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GListModel *model;
|
||||
GtkListItemFactory *factory;
|
||||
GtkListItemFactory *list_factory;
|
||||
|
||||
g_return_val_if_fail (titles != NULL, NULL);
|
||||
g_return_val_if_fail (icons == NULL || g_strv_length ((char **)icons) == g_strv_length ((char **)titles), NULL);
|
||||
g_return_val_if_fail (descriptions == NULL || g_strv_length ((char **)icons) == g_strv_length ((char **)descriptions), NULL);
|
||||
|
||||
model = strings_model_new (titles, icons, descriptions);
|
||||
factory = strings_factory_new (FALSE);
|
||||
if (icons != NULL || descriptions != NULL)
|
||||
list_factory = strings_factory_new (TRUE);
|
||||
else
|
||||
list_factory = NULL;
|
||||
|
||||
widget = g_object_new (GTK_TYPE_DROP_DOWN,
|
||||
"model", model,
|
||||
"factory", factory,
|
||||
"list-factory", list_factory,
|
||||
NULL);
|
||||
|
||||
g_object_unref (model);
|
||||
g_object_unref (factory);
|
||||
if (list_factory)
|
||||
g_object_unref (list_factory);
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_family_name (gpointer item)
|
||||
{
|
||||
return g_strdup (pango_font_family_get_name (PANGO_FONT_FAMILY (item)));
|
||||
}
|
||||
|
||||
static char *
|
||||
get_title (gpointer item)
|
||||
{
|
||||
return g_strdup (STRING_HOLDER (item)->title);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_dropdown (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
GtkWidget *button, *box, *spin, *check;
|
||||
GListModel *model;
|
||||
GtkExpression *expression;
|
||||
const char * const times[] = { "1 minute", "2 minutes", "5 minutes", "20 minutes", NULL };
|
||||
const char * const many_times[] = {
|
||||
"1 minute", "2 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes",
|
||||
"25 minutes", "30 minutes", "35 minutes", "40 minutes", "45 minutes", "50 minutes",
|
||||
"55 minutes", "1 hour", "2 hours", "3 hours", "5 hours", "6 hours", "7 hours",
|
||||
"8 hours", "9 hours", "10 hours", "11 hours", "12 hours", NULL
|
||||
};
|
||||
const char * const device_titles[] = { "Digital Output", "Headphones", "Digital Output", "Analog Output", NULL };
|
||||
const char * const device_icons[] = { "audio-card-symbolic", "audio-headphones-symbolic", "audio-card-symbolic", "audio-card-symbolic", NULL };
|
||||
const char * const device_descriptions[] = {
|
||||
"Built-in Audio", "Built-in audio", "Thinkpad Tunderbolt 3 Dock USB Audio", "Thinkpad Tunderbolt 3 Dock USB Audio", NULL
|
||||
};
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Drop Downs");
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
|
||||
gtk_widget_set_margin_start (box, 10);
|
||||
gtk_widget_set_margin_end (box, 10);
|
||||
gtk_widget_set_margin_top (box, 10);
|
||||
gtk_widget_set_margin_bottom (box, 10);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
|
||||
button = gtk_drop_down_new ();
|
||||
|
||||
model = G_LIST_MODEL (pango_cairo_font_map_get_default ());
|
||||
gtk_drop_down_set_model (GTK_DROP_DOWN (button), model);
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (button), 0);
|
||||
|
||||
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
|
||||
0, NULL,
|
||||
(GCallback)get_family_name,
|
||||
NULL, NULL);
|
||||
gtk_drop_down_set_expression (GTK_DROP_DOWN (button), expression);
|
||||
gtk_expression_unref (expression);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
spin = gtk_spin_button_new_with_range (-1, g_list_model_get_n_items (G_LIST_MODEL (model)), 1);
|
||||
gtk_widget_set_halign (spin, GTK_ALIGN_START);
|
||||
g_object_bind_property (button, "selected", spin, "value", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
||||
gtk_box_append (GTK_BOX (box), spin);
|
||||
|
||||
check = gtk_check_button_new_with_label ("Enable search");
|
||||
g_object_bind_property (button, "enable-search", check, "active", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
||||
gtk_box_append (GTK_BOX (box), check);
|
||||
|
||||
g_object_unref (model);
|
||||
|
||||
button = drop_down_new_from_strings (times, NULL, NULL);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
button = drop_down_new_from_strings (many_times, NULL, NULL);
|
||||
gtk_drop_down_set_enable_search (GTK_DROP_DOWN (button), TRUE);
|
||||
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
|
||||
0, NULL,
|
||||
(GCallback)get_title,
|
||||
NULL, NULL);
|
||||
gtk_drop_down_set_expression (GTK_DROP_DOWN (button), expression);
|
||||
gtk_expression_unref (expression);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
button = drop_down_new_from_strings (device_titles, device_icons, device_descriptions);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Fixed layout
|
||||
/* Fixed Layout
|
||||
*
|
||||
* GtkFixed is a container that allows placing and transforming
|
||||
* widgets manually.
|
||||
@@ -126,7 +126,7 @@ create_demo_window (GtkWidget *do_widget)
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Fixed layout");
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Fixed Layout");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
/* Flow Box
|
||||
*
|
||||
* GtkFlowBox allows flexible and responsive grids which reflow
|
||||
* as needed and support sorting and filtering.
|
||||
*
|
||||
* The children of a GtkFlowBox are regular widgets
|
||||
* as needed and support sorting and filtering. The children of
|
||||
* a GtkFlowBox are regular widgets
|
||||
*
|
||||
* The dataset used here has 665 colors.
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,7 @@ typedef struct _GtkFishbowlChild GtkFishbowlChild;
|
||||
struct _GtkFishbowlPrivate
|
||||
{
|
||||
GtkFishCreationFunc creation_func;
|
||||
GList *children;
|
||||
GHashTable *children;
|
||||
guint count;
|
||||
|
||||
gint64 last_frame_time;
|
||||
@@ -67,6 +67,8 @@ gtk_fishbowl_init (GtkFishbowl *fishbowl)
|
||||
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
|
||||
|
||||
priv->update_delay = G_USEC_PER_SEC;
|
||||
priv->children = g_hash_table_new_full (NULL, NULL,
|
||||
NULL, (GDestroyNotify) g_free);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,16 +95,18 @@ gtk_fishbowl_measure (GtkWidget *widget,
|
||||
{
|
||||
GtkFishbowl *fishbowl = GTK_FISHBOWL (widget);
|
||||
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
GtkFishbowlChild *child;
|
||||
GList *children;
|
||||
gint child_min, child_nat;
|
||||
|
||||
*minimum = 0;
|
||||
*natural = 0;
|
||||
|
||||
for (children = priv->children; children; children = children->next)
|
||||
g_hash_table_iter_init (&iter, priv->children);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
child = children->data;
|
||||
child = value;
|
||||
|
||||
if (!gtk_widget_get_visible (child->widget))
|
||||
continue;
|
||||
@@ -136,11 +140,13 @@ gtk_fishbowl_size_allocate (GtkWidget *widget,
|
||||
GtkFishbowlChild *child;
|
||||
GtkAllocation child_allocation;
|
||||
GtkRequisition child_requisition;
|
||||
GList *children;
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
|
||||
for (children = priv->children; children; children = children->next)
|
||||
g_hash_table_iter_init (&iter, priv->children);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
child = children->data;
|
||||
child = value;
|
||||
|
||||
if (!gtk_widget_get_visible (child->widget))
|
||||
continue;
|
||||
@@ -181,7 +187,7 @@ gtk_fishbowl_add (GtkFishbowl *fishbowl,
|
||||
|
||||
gtk_widget_set_parent (widget, GTK_WIDGET (fishbowl));
|
||||
|
||||
priv->children = g_list_prepend (priv->children, child_info);
|
||||
g_hash_table_insert (priv->children, widget, child_info);
|
||||
priv->count++;
|
||||
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_COUNT]);
|
||||
}
|
||||
@@ -191,34 +197,32 @@ gtk_fishbowl_remove (GtkFishbowl *fishbowl,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
|
||||
GtkFishbowlChild *child;
|
||||
GtkWidget *widget_bowl = GTK_WIDGET (fishbowl);
|
||||
GList *children;
|
||||
|
||||
for (children = priv->children; children; children = children->next)
|
||||
if (g_hash_table_remove (priv->children, widget))
|
||||
{
|
||||
child = children->data;
|
||||
gboolean was_visible = gtk_widget_get_visible (widget);
|
||||
|
||||
if (child->widget == widget)
|
||||
{
|
||||
gboolean was_visible = gtk_widget_get_visible (widget);
|
||||
gtk_widget_unparent (widget);
|
||||
|
||||
gtk_widget_unparent (widget);
|
||||
if (was_visible && gtk_widget_get_visible (widget_bowl))
|
||||
gtk_widget_queue_resize (widget_bowl);
|
||||
|
||||
priv->children = g_list_remove_link (priv->children, children);
|
||||
g_list_free (children);
|
||||
g_free (child);
|
||||
|
||||
if (was_visible && gtk_widget_get_visible (widget_bowl))
|
||||
gtk_widget_queue_resize (widget_bowl);
|
||||
|
||||
priv->count--;
|
||||
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_COUNT]);
|
||||
break;
|
||||
}
|
||||
priv->count--;
|
||||
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_COUNT]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_fishbowl_finalize (GObject *object)
|
||||
{
|
||||
GtkFishbowl *fishbowl = GTK_FISHBOWL (object);
|
||||
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
|
||||
|
||||
g_hash_table_destroy (priv->children);
|
||||
priv->children = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_fishbowl_dispose (GObject *object)
|
||||
{
|
||||
@@ -304,6 +308,7 @@ gtk_fishbowl_class_init (GtkFishbowlClass *klass)
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_fishbowl_finalize;
|
||||
object_class->dispose = gtk_fishbowl_dispose;
|
||||
object_class->set_property = gtk_fishbowl_set_property;
|
||||
object_class->get_property = gtk_fishbowl_get_property;
|
||||
@@ -535,8 +540,9 @@ gtk_fishbowl_tick (GtkWidget *widget,
|
||||
GtkFishbowl *fishbowl = GTK_FISHBOWL (widget);
|
||||
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
|
||||
GtkFishbowlChild *child;
|
||||
GList *l;
|
||||
gint64 frame_time, elapsed;
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
gboolean do_update;
|
||||
|
||||
frame_time = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget));
|
||||
@@ -548,9 +554,10 @@ gtk_fishbowl_tick (GtkWidget *widget,
|
||||
if (elapsed == frame_time)
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
||||
for (l = priv->children; l; l = l->next)
|
||||
g_hash_table_iter_init (&iter, priv->children);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
child = l->data;
|
||||
child = value;
|
||||
|
||||
child->x += child->dx * ((double) elapsed / G_USEC_PER_SEC);
|
||||
child->y += child->dy * ((double) elapsed / G_USEC_PER_SEC);
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "award.h"
|
||||
|
||||
static GdkPixbuf *avatar_pixbuf_other;
|
||||
static GtkWidget *window = NULL;
|
||||
@@ -235,7 +234,6 @@ reshare_clicked (GtkMessageRow *row,
|
||||
{
|
||||
GtkMessageRowPrivate *priv = row->priv;
|
||||
|
||||
award ("listbox-reshare");
|
||||
priv->message->n_reshares++;
|
||||
gtk_message_row_update (row);
|
||||
}
|
||||
@@ -262,8 +260,6 @@ gtk_message_row_state_flags_changed (GtkWidget *widget,
|
||||
|
||||
visible = flags & (GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_SELECTED) ? TRUE : FALSE;
|
||||
gtk_widget_set_visible (priv->extra_buttons_box, visible);
|
||||
if (visible && gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (widget)) % 100 == 99)
|
||||
award ("listbox-100th-row");
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_message_row_parent_class)->state_flags_changed (widget, previous_state_flags);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Lists/Application launcher
|
||||
*
|
||||
* This demo uses the GtkCoverFlow widget as a fancy application launcher.
|
||||
* This demo uses the GtkListView widget as a fancy application launcher.
|
||||
*
|
||||
* It is also a very small introduction to listviews.
|
||||
*/
|
||||
@@ -30,9 +30,7 @@ create_application_list (void)
|
||||
apps = g_app_info_get_all ();
|
||||
|
||||
for (l = apps; l; l = l->next)
|
||||
{
|
||||
g_list_store_append (store, l->data);
|
||||
}
|
||||
g_list_store_append (store, l->data);
|
||||
|
||||
g_list_free_full (apps, g_object_unref);
|
||||
|
||||
@@ -40,19 +38,24 @@ create_application_list (void)
|
||||
}
|
||||
|
||||
/* This is the function we use for setting up new listitems to display.
|
||||
* We add just a #GtkImage here to display the application's icon as this is just
|
||||
* a simple demo.
|
||||
* We add just an #GtkImage and a #GtkKabel here to display the application's
|
||||
* icon and name, as this is just a simple demo.
|
||||
*/
|
||||
static void
|
||||
setup_listitem_cb (GtkListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *box;
|
||||
GtkWidget *image;
|
||||
GtkWidget *label;
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
||||
image = gtk_image_new ();
|
||||
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
|
||||
|
||||
gtk_list_item_set_child (list_item, image);
|
||||
gtk_box_append (GTK_BOX (box), image);
|
||||
label = gtk_label_new ("");
|
||||
gtk_box_append (GTK_BOX (box), label);
|
||||
gtk_list_item_set_child (list_item, box);
|
||||
}
|
||||
|
||||
/* Here we need to prepare the listitem for displaying its item. We get the
|
||||
@@ -66,12 +69,15 @@ bind_listitem_cb (GtkListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *image;
|
||||
GtkWidget *label;
|
||||
GAppInfo *app_info;
|
||||
|
||||
image = gtk_list_item_get_child (list_item);
|
||||
image = gtk_widget_get_first_child (gtk_list_item_get_child (list_item));
|
||||
label = gtk_widget_get_next_sibling (image);
|
||||
app_info = gtk_list_item_get_item (list_item);
|
||||
|
||||
gtk_image_set_from_gicon (GTK_IMAGE (image), g_app_info_get_icon (app_info));
|
||||
gtk_label_set_label (GTK_LABEL (label), g_app_info_get_display_name (app_info));
|
||||
}
|
||||
|
||||
/* In more complex code, we would also need functions to unbind and teardown
|
||||
@@ -90,7 +96,7 @@ bind_listitem_cb (GtkListItemFactory *factory,
|
||||
* above, but this is a simple demo, so we'll use the simple way.
|
||||
*/
|
||||
static void
|
||||
activate_cb (GtkCoverFlow *coverflow,
|
||||
activate_cb (GtkListView *list,
|
||||
guint position,
|
||||
gpointer unused)
|
||||
{
|
||||
@@ -98,15 +104,15 @@ activate_cb (GtkCoverFlow *coverflow,
|
||||
GdkAppLaunchContext *context;
|
||||
GError *error = NULL;
|
||||
|
||||
app_info = g_list_model_get_item (gtk_cover_flow_get_model (coverflow), position);
|
||||
app_info = g_list_model_get_item (gtk_list_view_get_model (list), position);
|
||||
|
||||
/* Prepare the context for launching the application and launch it. This
|
||||
* code is explained in detail in the documentation for #GdkAppLaunchContext
|
||||
* and #GAppInfo.
|
||||
*/
|
||||
context = gdk_display_get_app_launch_context (gtk_widget_get_display (GTK_WIDGET (coverflow)));
|
||||
context = gdk_display_get_app_launch_context (gtk_widget_get_display (GTK_WIDGET (list)));
|
||||
if (!g_app_info_launch (app_info,
|
||||
NULL,
|
||||
NULL,
|
||||
G_APP_LAUNCH_CONTEXT (context),
|
||||
&error))
|
||||
{
|
||||
@@ -115,7 +121,7 @@ activate_cb (GtkCoverFlow *coverflow,
|
||||
/* And because error handling is important, even a simple demo has it:
|
||||
* We display an error dialog that something went wrong.
|
||||
*/
|
||||
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (coverflow))),
|
||||
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (list))),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_CLOSE,
|
||||
@@ -136,7 +142,7 @@ do_listview_applauncher (GtkWidget *do_widget)
|
||||
{
|
||||
if (window == NULL)
|
||||
{
|
||||
GtkWidget *coverflow, *sw;;
|
||||
GtkWidget *list, *sw;
|
||||
GListModel *model;
|
||||
GtkListItemFactory *factory;
|
||||
|
||||
@@ -147,7 +153,7 @@ do_listview_applauncher (GtkWidget *do_widget)
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Application Launcher");
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
|
||||
|
||||
|
||||
/* The #GtkListitemFactory is what is used to create #GtkListItems
|
||||
* to display the data from the model. So it is absolutely necessary
|
||||
* to create one.
|
||||
@@ -160,25 +166,22 @@ do_listview_applauncher (GtkWidget *do_widget)
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem_cb), NULL);
|
||||
g_signal_connect (factory, "bind", G_CALLBACK (bind_listitem_cb), NULL);
|
||||
|
||||
/* Create the list widget here: We use a coverflow widget because it's
|
||||
* the coolest one. We could just as well use other list widgets such
|
||||
* as a #GtkListView or a #GtkGridView and the code would look very
|
||||
* similar.
|
||||
/* Create the list widget here.
|
||||
*/
|
||||
coverflow = gtk_cover_flow_new_with_factory (factory);
|
||||
list = gtk_list_view_new_with_factory (factory);
|
||||
/* We connect the activate signal here. It's the function we defined
|
||||
* above for launching the selected application.
|
||||
*/
|
||||
g_signal_connect (coverflow, "activate", G_CALLBACK (activate_cb), NULL);
|
||||
g_signal_connect (list, "activate", G_CALLBACK (activate_cb), NULL);
|
||||
|
||||
/* And of course we need to set the data model. Here we call the function
|
||||
* we wrote above that gives us the list of applications. Then we set
|
||||
* it on the coverflow list widget.
|
||||
* The coverflow will now take items from the model and use the factory
|
||||
* it on the list widget.
|
||||
* The list will now take items from the model and use the factory
|
||||
* to create as many listitems as it needs to show itself to the user.
|
||||
*/
|
||||
model = create_application_list ();
|
||||
gtk_cover_flow_set_model (GTK_COVER_FLOW (coverflow), model);
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (list), model);
|
||||
g_object_unref (model);
|
||||
|
||||
/* List widgets should always be contained in a #GtkScrolledWindow,
|
||||
@@ -187,7 +190,7 @@ do_listview_applauncher (GtkWidget *do_widget)
|
||||
*/
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_window_set_child (GTK_WINDOW (window), sw);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), coverflow);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), list);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
* This demo displays the time in different timezones.
|
||||
*
|
||||
* The goal is to show how to set up expressions that track changes
|
||||
* in objects and make them update widgets.
|
||||
*
|
||||
* For that, we create a GtkClock object that updates its time every
|
||||
* second and then use various ways to display that time.
|
||||
* in objects and make them update widgets. For that, we create a
|
||||
* GtkClock object that updates its time every second and then use
|
||||
* various ways to display that time.
|
||||
*
|
||||
* Typically, this will be done using GtkBuilder .ui files with the
|
||||
* help of the <binding> tag, but this demo shows the code that runs
|
||||
@@ -41,7 +40,8 @@ enum {
|
||||
|
||||
/* This function returns the current time in the clock's timezone.
|
||||
* Note that this returns a new object every time, so we need to
|
||||
* remember to unref it after use. */
|
||||
* remember to unref it after use.
|
||||
*/
|
||||
static GDateTime *
|
||||
gtk_clock_get_time (GtkClock *clock)
|
||||
{
|
||||
@@ -51,10 +51,11 @@ gtk_clock_get_time (GtkClock *clock)
|
||||
return g_date_time_new_now_local ();
|
||||
}
|
||||
|
||||
/* Here, we implement the functionality required by the GdkPaintable interface.
|
||||
* This way we have a trivial way to display an analog clock.
|
||||
* It also allows demonstrating how to directly use objects in the listview
|
||||
* later by making this object do something interesting. */
|
||||
/* Here, we implement the functionality required by the GdkPaintable
|
||||
* interface. This way we have a trivial way to display an analog clock.
|
||||
* It also allows demonstrating how to directly use objects in the
|
||||
* listview later by making this object do something interesting.
|
||||
*/
|
||||
static void
|
||||
gtk_clock_snapshot (GdkPaintable *paintable,
|
||||
GdkSnapshot *snapshot,
|
||||
@@ -68,26 +69,31 @@ gtk_clock_snapshot (GdkPaintable *paintable,
|
||||
#define BLACK ((GdkRGBA) { 0, 0, 0, 1 })
|
||||
|
||||
/* save/restore() is necessary so we can undo the transforms we start
|
||||
* out with. */
|
||||
* out with.
|
||||
*/
|
||||
gtk_snapshot_save (snapshot);
|
||||
|
||||
/* First, we move the (0, 0) point to the center of the area so
|
||||
* we can draw everything relative to it. */
|
||||
* we can draw everything relative to it.
|
||||
*/
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (width / 2, height / 2));
|
||||
|
||||
/* Next we scale it, so that we can pretend that the clock is
|
||||
* 100px in size. That way, we don't need to do any complicated
|
||||
* math later.
|
||||
* We use MIN() here so that we use the smaller dimension for sizing.
|
||||
* That way we don't overdraw but keep the aspect ratio. */
|
||||
* math later. We use MIN() here so that we use the smaller
|
||||
* dimension for sizing. That way we don't overdraw but keep
|
||||
* the aspect ratio.
|
||||
*/
|
||||
gtk_snapshot_scale (snapshot, MIN (width, height) / 100.0, MIN (width, height) / 100.0);
|
||||
/* Now we have a circle with diameter 100px (and radius 50px) that
|
||||
* has its (0, 0) point at the center.
|
||||
* Let's draw a simple clock into it. */
|
||||
|
||||
/* Now we have a circle with diameter 100px (and radius 50px) that
|
||||
* has its (0, 0) point at the center. Let's draw a simple clock into it.
|
||||
*/
|
||||
time = gtk_clock_get_time (self);
|
||||
|
||||
/* First, draw a circle. This is a neat little trick to draw a circle
|
||||
* without requiring Cairo. */
|
||||
* without requiring Cairo.
|
||||
*/
|
||||
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-50, -50, 100, 100), 50);
|
||||
gtk_snapshot_append_border (snapshot,
|
||||
&outline,
|
||||
@@ -95,9 +101,11 @@ gtk_clock_snapshot (GdkPaintable *paintable,
|
||||
(GdkRGBA [4]) { BLACK, BLACK, BLACK, BLACK });
|
||||
|
||||
/* Next, draw the hour hand.
|
||||
* We do this using tranforms again: Instead of computing where the angle points
|
||||
* to, we just rotate everything and then draw the hand as if if was :00.
|
||||
* We don't even need to care about am/pm here because rotations just work. */
|
||||
* We do this using tranforms again: Instead of computing where the angle
|
||||
* points to, we just rotate everything and then draw the hand as if it
|
||||
* was :00. We don't even need to care about am/pm here because rotations
|
||||
* just work.
|
||||
*/
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_rotate (snapshot, 30 * g_date_time_get_hour (time) + 0.5 * g_date_time_get_minute (time));
|
||||
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-2, -23, 4, 25), 2);
|
||||
@@ -107,7 +115,8 @@ gtk_clock_snapshot (GdkPaintable *paintable,
|
||||
gtk_snapshot_restore (snapshot);
|
||||
|
||||
/* And the same as above for the minute hand. Just make this one longer
|
||||
* so people can tell the hands apart. */
|
||||
* so people can tell the hands apart.
|
||||
*/
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_rotate (snapshot, 6 * g_date_time_get_minute (time));
|
||||
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-2, -43, 4, 45), 2);
|
||||
@@ -125,8 +134,9 @@ gtk_clock_snapshot (GdkPaintable *paintable,
|
||||
gtk_snapshot_pop (snapshot);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
|
||||
/* And finally, don't forget to restore the initial save() that we did for
|
||||
* the initial transformations. */
|
||||
/* And finally, don't forget to restore the initial save() that
|
||||
* we did for the initial transformations.
|
||||
*/
|
||||
gtk_snapshot_restore (snapshot);
|
||||
|
||||
g_date_time_unref (time);
|
||||
@@ -145,10 +155,9 @@ gtk_clock_get_intrinsic_height (GdkPaintable *paintable)
|
||||
return 100;
|
||||
}
|
||||
|
||||
/* Initialize the paintable interface. This way we turn our clock objects
|
||||
* into objects that can be drawn.
|
||||
* There are more functions to this interface to define desired size,
|
||||
* but this is enough.
|
||||
/* Initialize the paintable interface. This way we turn our clocks
|
||||
* into objects that can be drawn. There are more functions to this
|
||||
* interface to define desired size, but this is enough.
|
||||
*/
|
||||
static void
|
||||
gtk_clock_paintable_init (GdkPaintableInterface *iface)
|
||||
@@ -158,8 +167,9 @@ gtk_clock_paintable_init (GdkPaintableInterface *iface)
|
||||
iface->get_intrinsic_height = gtk_clock_get_intrinsic_height;
|
||||
}
|
||||
|
||||
/* Finally, we define the type. The important part is adding the paintable
|
||||
* interface, so GTK knows that this object can indeed be drawm.
|
||||
/* Finally, we define the type. The important part is adding the
|
||||
* paintable interface, so GTK knows that this object can indeed
|
||||
* be drawn.
|
||||
*/
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkClock, gtk_clock, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
||||
@@ -221,11 +231,14 @@ gtk_clock_set_property (GObject *object,
|
||||
|
||||
/* This is the list of all the ticking clocks */
|
||||
static GSList *ticking_clocks = NULL;
|
||||
/* This is the id of the timeout source that is updating all ticking clocks */
|
||||
|
||||
/* This is the ID of the timeout source that is updating all
|
||||
* ticking clocks.
|
||||
*/
|
||||
static guint ticking_clock_id = 0;
|
||||
|
||||
/* Every second, this function is called to tell everybody that the
|
||||
* clocks are ticking.
|
||||
/* Every second, this function is called to tell everybody that
|
||||
* the clocks are ticking.
|
||||
*/
|
||||
static gboolean
|
||||
gtk_clock_tick (gpointer unused)
|
||||
@@ -240,6 +253,7 @@ gtk_clock_tick (gpointer unused)
|
||||
* so notify about that.
|
||||
*/
|
||||
g_object_notify_by_pspec (G_OBJECT (clock), properties[PROP_TIME]);
|
||||
|
||||
/* We will also draw the hands of the clock differently.
|
||||
* So notify about that, too.
|
||||
*/
|
||||
@@ -309,16 +323,16 @@ gtk_clock_init (GtkClock *self)
|
||||
|
||||
static GtkClock *
|
||||
gtk_clock_new (const char *location,
|
||||
GTimeZone *timezone)
|
||||
GTimeZone *_timezone)
|
||||
{
|
||||
GtkClock *result;
|
||||
|
||||
result = g_object_new (GTK_TYPE_CLOCK,
|
||||
"location", location,
|
||||
"timezone", timezone,
|
||||
"timezone", _timezone,
|
||||
NULL);
|
||||
|
||||
g_clear_pointer (&timezone, g_time_zone_unref);
|
||||
g_clear_pointer (&_timezone, g_time_zone_unref);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -343,6 +357,9 @@ create_clocks_model (void)
|
||||
clock = gtk_clock_new ("San Francisco", g_time_zone_new ("America/Los_Angeles"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
clock = gtk_clock_new ("Xalapa", g_time_zone_new ("America/Mexico_City"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
clock = gtk_clock_new ("Boston", g_time_zone_new ("America/New_York"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
|
||||
@@ -6,11 +6,13 @@
|
||||
* and sort the data in various ways. The controls for
|
||||
* this are implemented using GtkDropDown.
|
||||
*
|
||||
* The dataset used here has 9283 items.
|
||||
* The dataset used here has 9 283 items.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define GTK_TYPE_COLOR (gtk_color_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkColor, gtk_color, GTK, COLOR, GObject)
|
||||
|
||||
@@ -23,6 +25,7 @@ struct _GtkColor
|
||||
char *name;
|
||||
GdkRGBA *color;
|
||||
int h, s, v;
|
||||
gboolean selected;
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -35,6 +38,7 @@ enum {
|
||||
PROP_HUE,
|
||||
PROP_SATURATION,
|
||||
PROP_VALUE,
|
||||
PROP_SELECTED,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
@@ -122,6 +126,10 @@ gtk_color_get_property (GObject *object,
|
||||
g_value_set_int (value, self->v);
|
||||
break;
|
||||
|
||||
case PROP_SELECTED:
|
||||
g_value_set_boolean (value, self->selected);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
@@ -158,6 +166,10 @@ gtk_color_set_property (GObject *object,
|
||||
self->v = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
case PROP_SELECTED:
|
||||
self->selected = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
@@ -200,6 +212,8 @@ gtk_color_class_init (GtkColorClass *klass)
|
||||
g_param_spec_int ("saturation", NULL, NULL, 0, 100, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
properties[PROP_VALUE] =
|
||||
g_param_spec_int ("value", NULL, NULL, 0, 100, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
properties[PROP_SELECTED] =
|
||||
g_param_spec_boolean ("selected", NULL, NULL, FALSE, G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
@@ -259,7 +273,7 @@ create_colors_model (void)
|
||||
h = atoi (fields[9]);
|
||||
s = atoi (fields[10]);
|
||||
v = atoi (fields[11]);
|
||||
|
||||
|
||||
color = gtk_color_new (name, red / 255., green / 255., blue / 255., h, s, v);
|
||||
g_list_store_append (result, color);
|
||||
g_object_unref (color);
|
||||
@@ -320,7 +334,7 @@ static void
|
||||
setup_listitem_cb (GtkListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *box, *picture, *name_label, *rgb_label, *hsv_label;;
|
||||
GtkWidget *box, *picture, *name_label, *rgb_label, *hsv_label;
|
||||
GtkExpression *color_expression, *expression;
|
||||
GtkExpression *params[1];
|
||||
|
||||
@@ -420,12 +434,12 @@ create_color_grid (void)
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_simple_listitem_cb), NULL);
|
||||
gtk_grid_view_set_factory (GTK_GRID_VIEW (gridview), factory);
|
||||
g_object_unref (factory);
|
||||
|
||||
|
||||
gtk_grid_view_set_max_columns (GTK_GRID_VIEW (gridview), 24);
|
||||
gtk_grid_view_set_enable_rubberband (GTK_GRID_VIEW (gridview), TRUE);
|
||||
|
||||
model = G_LIST_MODEL (gtk_sort_list_model_new (create_colors_model (), NULL));
|
||||
selection = G_LIST_MODEL (gtk_multi_selection_new (model));
|
||||
selection = G_LIST_MODEL (gtk_property_selection_new (model, "selected"));
|
||||
gtk_grid_view_set_model (GTK_GRID_VIEW (gridview), selection);
|
||||
g_object_unref (selection);
|
||||
g_object_unref (model);
|
||||
|
||||
@@ -18,6 +18,7 @@ struct _FileBrowserView
|
||||
|
||||
GtkListItemFactory *factory;
|
||||
char *icon_name;
|
||||
char *title;
|
||||
GtkOrientation orientation;
|
||||
};
|
||||
|
||||
@@ -25,6 +26,7 @@ enum {
|
||||
PROP_0,
|
||||
PROP_FACTORY,
|
||||
PROP_ICON_NAME,
|
||||
PROP_TITLE,
|
||||
PROP_ORIENTATION,
|
||||
|
||||
N_PROPS
|
||||
@@ -54,6 +56,10 @@ file_browser_view_get_property (GObject *object,
|
||||
g_value_set_string (value, self->icon_name);
|
||||
break;
|
||||
|
||||
case PROP_TITLE:
|
||||
g_value_set_string (value, self->title);
|
||||
break;
|
||||
|
||||
case PROP_ORIENTATION:
|
||||
g_value_set_enum (value, self->orientation);
|
||||
break;
|
||||
@@ -83,6 +89,11 @@ file_browser_view_set_property (GObject *object,
|
||||
self->icon_name = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_TITLE:
|
||||
g_free (self->title);
|
||||
self->title = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_ORIENTATION:
|
||||
self->orientation = g_value_get_enum (value);
|
||||
break;
|
||||
@@ -100,6 +111,7 @@ file_browser_view_finalize (GObject *object)
|
||||
|
||||
g_object_unref (self->factory);
|
||||
g_free (self->icon_name);
|
||||
g_free (self->title);
|
||||
|
||||
G_OBJECT_CLASS (file_browser_view_parent_class)->dispose (object);
|
||||
}
|
||||
@@ -125,6 +137,12 @@ file_browser_view_class_init (FileBrowserViewClass *klass)
|
||||
"icon to display for selecting this view",
|
||||
NULL,
|
||||
G_PARAM_READWRITE);
|
||||
properties[PROP_TITLE] =
|
||||
g_param_spec_string ("title",
|
||||
"title",
|
||||
"title to display for selecting this view",
|
||||
NULL,
|
||||
G_PARAM_READWRITE);
|
||||
properties[PROP_ORIENTATION] =
|
||||
g_param_spec_enum ("orientation",
|
||||
"orientation",
|
||||
@@ -224,6 +242,14 @@ do_listview_filebrowser (GtkWidget *do_widget)
|
||||
GtkDirectoryList *dirlist;
|
||||
GFile *file;
|
||||
char *cwd;
|
||||
GtkCssProvider *provider;
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_resource (provider, "/listview_filebrowser/listview_filebrowser.css");
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
800);
|
||||
g_object_unref (provider);
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/listview_filebrowser/listview_filebrowser.ui");
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
||||
|
||||
11
demos/gtk-demo/listview_filebrowser.css
Normal file
11
demos/gtk-demo/listview_filebrowser.css
Normal file
@@ -0,0 +1,11 @@
|
||||
list.viewswitcher {
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
list.viewswitcher > row {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
list.viewswitcher row:selected {
|
||||
background: gray;
|
||||
}
|
||||
@@ -39,12 +39,14 @@
|
||||
</object>
|
||||
</property>
|
||||
<property name="icon-name">view-list-symbolic</property>
|
||||
<property name="title" translatable="yes">List</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="FileBrowserView">
|
||||
<property name="icon-name">view-grid-symbolic</property>
|
||||
<property name="title" translatable="yes">Grid</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
@@ -92,6 +94,7 @@
|
||||
<child>
|
||||
<object class="FileBrowserView">
|
||||
<property name="icon-name">view-paged-symbolic</property>
|
||||
<property name="title" translatable="yes">Paged</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
@@ -174,7 +177,7 @@
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">go-up</property>
|
||||
<property name="icon-name">go-up-symbolic</property>
|
||||
<signal name="clicked" handler="filebrowser_up_clicked_cb" object="dirlist" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
@@ -184,6 +187,7 @@
|
||||
<property name="orientation">horizontal</property>
|
||||
<style>
|
||||
<class name="linked"/>
|
||||
<class name="viewswitcher"/>
|
||||
</style>
|
||||
<property name="model">
|
||||
<object class="GtkSingleSelection" id="selected-view">
|
||||
@@ -203,6 +207,11 @@
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
<binding name="tooltip-text">
|
||||
<lookup type="FileBrowserView" name="title">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Create an object that wraps GSettingsSchemaKey because that's a boxed type */
|
||||
typedef struct _SettingsKey SettingsKey;
|
||||
struct _SettingsKey
|
||||
@@ -25,6 +27,8 @@ enum {
|
||||
PROP_SUMMARY,
|
||||
PROP_DESCRIPTION,
|
||||
PROP_VALUE,
|
||||
PROP_TYPE,
|
||||
PROP_DEFAULT_VALUE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
@@ -65,6 +69,21 @@ settings_key_get_property (GObject *object,
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_TYPE:
|
||||
{
|
||||
const GVariantType *type = g_settings_schema_key_get_value_type (self->key);
|
||||
g_value_set_string (value, g_variant_type_peek_string (type));
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_DEFAULT_VALUE:
|
||||
{
|
||||
GVariant *variant = g_settings_schema_key_get_default_value (self->key);
|
||||
g_value_take_string (value, g_variant_print (variant, FALSE));
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
@@ -98,6 +117,10 @@ settings_key_class_init (SettingsKeyClass *klass)
|
||||
g_param_spec_string ("summary", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_VALUE] =
|
||||
g_param_spec_string ("value", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_TYPE] =
|
||||
g_param_spec_string ("type", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_DEFAULT_VALUE] =
|
||||
g_param_spec_string ("default-value", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
@@ -119,6 +142,43 @@ settings_key_new (GSettings *settings,
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
item_value_changed (GtkListItem *item,
|
||||
GtkEntry *entry)
|
||||
{
|
||||
SettingsKey *self;
|
||||
const char *text;
|
||||
const GVariantType *type;
|
||||
GVariant *variant;
|
||||
GError *error = NULL;
|
||||
const char *name;
|
||||
|
||||
text = gtk_editable_get_text (GTK_EDITABLE (entry));
|
||||
|
||||
g_object_get (item, "item", &self, NULL);
|
||||
g_object_unref (self);
|
||||
|
||||
type = g_settings_schema_key_get_value_type (self->key);
|
||||
name = g_settings_schema_key_get_name (self->key);
|
||||
|
||||
variant = g_variant_parse (type, text, NULL, NULL, &error);
|
||||
if (!variant)
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_settings_schema_key_range_check (self->key, variant))
|
||||
{
|
||||
g_warning ("Not a valid value for %s", name);
|
||||
return;
|
||||
}
|
||||
|
||||
g_settings_set_value (self->settings, name, variant);
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
|
||||
static int
|
||||
strvcmp (gconstpointer p1,
|
||||
gconstpointer p2)
|
||||
@@ -144,6 +204,7 @@ transform_settings_to_keys (GBinding *binding,
|
||||
GtkSortListModel *sort_model;
|
||||
GtkFilterListModel *filter_model;
|
||||
GtkFilter *filter;
|
||||
GtkNoSelection *selection_model;
|
||||
GtkExpression *expression;
|
||||
char **keys;
|
||||
guint i;
|
||||
@@ -186,7 +247,10 @@ transform_settings_to_keys (GBinding *binding,
|
||||
|
||||
g_object_unref (filter);
|
||||
|
||||
g_value_take_object (to_value, filter_model);
|
||||
selection_model = gtk_no_selection_new (G_LIST_MODEL (filter_model));
|
||||
g_object_unref (filter_model);
|
||||
|
||||
g_value_take_object (to_value, selection_model);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -279,7 +343,13 @@ do_listview_settings (GtkWidget *do_widget)
|
||||
GtkBuilderScope *scope;
|
||||
GtkBuilder *builder;
|
||||
GtkColumnViewColumn *name_column;
|
||||
GtkColumnViewColumn *type_column;
|
||||
GtkColumnViewColumn *default_column;
|
||||
GtkColumnViewColumn *summary_column;
|
||||
GtkColumnViewColumn *description_column;
|
||||
GtkSorter *sorter;
|
||||
GActionGroup *actions;
|
||||
GAction *action;
|
||||
|
||||
g_type_ensure (SETTINGS_TYPE_KEY);
|
||||
|
||||
@@ -287,6 +357,7 @@ do_listview_settings (GtkWidget *do_widget)
|
||||
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "search_enabled", (GCallback)search_enabled);
|
||||
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "search_changed", (GCallback)search_changed);
|
||||
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "stop_search", (GCallback)stop_search);
|
||||
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "item_value_changed", (GCallback)item_value_changed);
|
||||
|
||||
builder = gtk_builder_new ();
|
||||
gtk_builder_set_scope (builder, scope);
|
||||
@@ -299,6 +370,32 @@ do_listview_settings (GtkWidget *do_widget)
|
||||
|
||||
listview = GTK_WIDGET (gtk_builder_get_object (builder, "listview"));
|
||||
columnview = GTK_WIDGET (gtk_builder_get_object (builder, "columnview"));
|
||||
type_column = GTK_COLUMN_VIEW_COLUMN (gtk_builder_get_object (builder, "type_column"));
|
||||
default_column = GTK_COLUMN_VIEW_COLUMN (gtk_builder_get_object (builder, "default_column"));
|
||||
summary_column = GTK_COLUMN_VIEW_COLUMN (gtk_builder_get_object (builder, "summary_column"));
|
||||
description_column = GTK_COLUMN_VIEW_COLUMN (gtk_builder_get_object (builder, "description_column"));
|
||||
|
||||
actions = G_ACTION_GROUP (g_simple_action_group_new ());
|
||||
|
||||
action = G_ACTION (g_property_action_new ("show-type", type_column, "visible"));
|
||||
g_action_map_add_action (G_ACTION_MAP (actions), action);
|
||||
g_object_unref (action);
|
||||
|
||||
action = G_ACTION (g_property_action_new ("show-default", default_column, "visible"));
|
||||
g_action_map_add_action (G_ACTION_MAP (actions), action);
|
||||
g_object_unref (action);
|
||||
|
||||
action = G_ACTION (g_property_action_new ("show-summary", summary_column, "visible"));
|
||||
g_action_map_add_action (G_ACTION_MAP (actions), action);
|
||||
g_object_unref (action);
|
||||
|
||||
action = G_ACTION (g_property_action_new ("show-description", description_column, "visible"));
|
||||
g_action_map_add_action (G_ACTION_MAP (actions), action);
|
||||
g_object_unref (action);
|
||||
|
||||
gtk_widget_insert_action_group (columnview, "columnview", actions);
|
||||
g_object_unref (actions);
|
||||
|
||||
model = create_settings_model (NULL, NULL);
|
||||
treemodel = gtk_tree_list_model_new (FALSE,
|
||||
model,
|
||||
@@ -322,6 +419,8 @@ do_listview_settings (GtkWidget *do_widget)
|
||||
sorter = gtk_string_sorter_new (gtk_property_expression_new (SETTINGS_TYPE_KEY, NULL, "name"));
|
||||
gtk_column_view_column_set_sorter (name_column, sorter);
|
||||
g_object_unref (sorter);
|
||||
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
<child>
|
||||
<object class="GtkColumnViewColumn" id="name_column">
|
||||
<property name="title">Name</property>
|
||||
<property name="header-menu">header_menu</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
@@ -103,6 +104,37 @@
|
||||
<child>
|
||||
<object class="GtkColumnViewColumn">
|
||||
<property name="title">Value</property>
|
||||
<property name="resizable">1</property>
|
||||
<property name="header-menu">header_menu</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkEntry">
|
||||
<signal name="activate" handler="item_value_changed" object="GtkListItem" swapped="yes"/>
|
||||
<property name="xalign">0</property>
|
||||
<binding name="text">
|
||||
<lookup name="value" type="SettingsKey">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColumnViewColumn" id="type_column">
|
||||
<property name="title">Type</property>
|
||||
<property name="resizable">1</property>
|
||||
<property name="header-menu">header_menu</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
@@ -113,7 +145,98 @@
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="value" type="SettingsKey">
|
||||
<lookup name="type" type="SettingsKey">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColumnViewColumn" id="default_column">
|
||||
<property name="title">Default</property>
|
||||
<property name="resizable">1</property>
|
||||
<property name="expand">1</property>
|
||||
<property name="header-menu">header_menu</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="default-value" type="SettingsKey">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColumnViewColumn" id="summary_column">
|
||||
<property name="title">Summary</property>
|
||||
<property name="resizable">1</property>
|
||||
<property name="visible">0</property>
|
||||
<property name="expand">1</property>
|
||||
<property name="header-menu">header_menu</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<property name="wrap">1</property>
|
||||
<binding name="label">
|
||||
<lookup name="summary" type="SettingsKey">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColumnViewColumn" id="description_column">
|
||||
<property name="title">Description</property>
|
||||
<property name="resizable">1</property>
|
||||
<property name="visible">0</property>
|
||||
<property name="expand">1</property>
|
||||
<property name="header-menu">header_menu</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<property name="wrap">1</property>
|
||||
<binding name="label">
|
||||
<lookup name="description" type="SettingsKey">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
@@ -135,4 +258,24 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<menu id="header_menu">
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Type</attribute>
|
||||
<attribute name="action">columnview.show-type</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Default value</attribute>
|
||||
<attribute name="action">columnview.show-default</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Summary</attribute>
|
||||
<attribute name="action">columnview.show-summary</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Description</attribute>
|
||||
<attribute name="action">columnview.show-description</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</menu>
|
||||
</interface>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* A GtkNoSelectionModel is used to make sure no item in the list can be
|
||||
* selected. All other interactions with the items is still possible.
|
||||
*
|
||||
* The dataset used here has 70000 items.
|
||||
* The dataset used here has 70 000 items.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
@@ -78,13 +78,13 @@ gtk_weather_info_new (GDateTime *timestamp,
|
||||
|
||||
static GDateTime *
|
||||
parse_timestamp (const char *string,
|
||||
GTimeZone *timezone)
|
||||
GTimeZone *_timezone)
|
||||
{
|
||||
char *with_seconds;
|
||||
GDateTime *result;
|
||||
|
||||
with_seconds = g_strconcat (string, ":00", NULL);
|
||||
result = g_date_time_new_from_iso8601 (with_seconds, timezone);
|
||||
result = g_date_time_new_from_iso8601 (with_seconds, _timezone);
|
||||
g_free (with_seconds);
|
||||
|
||||
return result;
|
||||
@@ -301,7 +301,7 @@ do_listview_weather (GtkWidget *do_widget)
|
||||
{
|
||||
if (window == NULL)
|
||||
{
|
||||
GtkWidget *listview, *sw;;
|
||||
GtkWidget *listview, *sw;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include "award.h"
|
||||
#include "demos.h"
|
||||
|
||||
static GtkWidget *info_view;
|
||||
@@ -213,7 +212,6 @@ activate_inspector (GSimpleAction *action,
|
||||
gpointer user_data)
|
||||
{
|
||||
gtk_window_set_interactive_debugging (TRUE);
|
||||
award ("demo-inspector");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -601,7 +599,7 @@ display_image (const char *resource)
|
||||
{
|
||||
GtkWidget *sw, *image;
|
||||
|
||||
image = gtk_image_new_from_resource (resource);
|
||||
image = gtk_picture_new_for_resource (resource);
|
||||
gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_valign (image, GTK_ALIGN_CENTER);
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
@@ -1042,7 +1040,7 @@ activate (GApplication *app)
|
||||
listmodel = create_demo_model ();
|
||||
treemodel = gtk_tree_list_model_new (FALSE,
|
||||
G_LIST_MODEL (listmodel),
|
||||
FALSE,
|
||||
TRUE,
|
||||
get_child_model,
|
||||
NULL,
|
||||
NULL);
|
||||
@@ -1051,10 +1049,6 @@ activate (GApplication *app)
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (listview),
|
||||
G_LIST_MODEL (selection));
|
||||
|
||||
award ("demo-start");
|
||||
|
||||
gtk_widget_show (GTK_WIDGET (window));
|
||||
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
@@ -1113,11 +1107,11 @@ command_line (GApplication *app,
|
||||
return 0;
|
||||
}
|
||||
|
||||
window = gtk_application_get_windows (GTK_APPLICATION (app))->data;
|
||||
|
||||
if (name == NULL)
|
||||
goto out;
|
||||
|
||||
window = gtk_application_get_windows (GTK_APPLICATION (app))->data;
|
||||
|
||||
d = gtk_demos;
|
||||
|
||||
while (d->title)
|
||||
@@ -1147,7 +1141,11 @@ out:
|
||||
|
||||
gtk_window_set_transient_for (GTK_WINDOW (demo), GTK_WINDOW (window));
|
||||
gtk_window_set_modal (GTK_WINDOW (demo), TRUE);
|
||||
|
||||
g_signal_connect_swapped (G_OBJECT (demo), "destroy", G_CALLBACK (g_application_quit), app);
|
||||
}
|
||||
else
|
||||
gtk_widget_show (GTK_WIDGET (window));
|
||||
|
||||
if (autoquit)
|
||||
g_timeout_add_seconds (1, auto_quit, app);
|
||||
|
||||
@@ -5,7 +5,7 @@ Text <span color="gray">c<span color="green">o</span>l<span color="tomato">o</sp
|
||||
|
||||
Colorful <span underline="low" underline-color="blue"><span underline="double" underline-color="red">under</span>lines</span> and <span background="pink"><span underline="error">mo</span><span underline="error" underline-color="green">re</span></span>
|
||||
|
||||
Colorful <span strikethrough="true" strikethrough-color="magenta">strikethroughs</span>
|
||||
Colorful <span strikethrough="true" strikethrough-color="magenta">strikethroughs</span> and <span overline="single" overline_color="green">overlines</span>
|
||||
|
||||
Superscripts and subscripts: 𝜀<span rise="-6000" size="x-small" font_desc="italic">0</span> = 𝜔<span rise="8000" size="smaller">𝜔<span rise="14000" size="smaller">𝜔<span rise="20000">.<span rise="23000">.<span rise="26000">.</span></span></span></span></span>
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
demos = files([
|
||||
'application_demo.c',
|
||||
'assistant.c',
|
||||
'awardview.c',
|
||||
'builder.c',
|
||||
'clipboard.c',
|
||||
'combobox.c',
|
||||
@@ -19,6 +18,7 @@ demos = files([
|
||||
'cursors.c',
|
||||
'dialog.c',
|
||||
'drawingarea.c',
|
||||
'dropdown.c',
|
||||
'dnd.c',
|
||||
'editable_cells.c',
|
||||
'entry_completion.c',
|
||||
@@ -92,7 +92,6 @@ demos = files([
|
||||
gtkdemo_deps = [ libgtk_dep, ]
|
||||
|
||||
extra_demo_sources = files(['main.c',
|
||||
'award.c',
|
||||
'gtkfishbowl.c',
|
||||
'fontplane.c',
|
||||
'gtkgears.c',
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "award.h"
|
||||
|
||||
static GtkWidget *entry;
|
||||
static GtkWidget *entry2;
|
||||
@@ -27,17 +26,12 @@ update_button (GObject *object,
|
||||
|
||||
gtk_widget_set_sensitive (button,
|
||||
text[0] != '\0' && g_str_equal (text, text2));
|
||||
|
||||
if (g_str_equal (text, text2) &&
|
||||
g_ascii_strcasecmp (text, "12345") == 0)
|
||||
award ("password-best");
|
||||
}
|
||||
|
||||
static void
|
||||
button_pressed (GtkButton *widget,
|
||||
GtkWidget *window)
|
||||
{
|
||||
award ("password-correct");
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Sliding puzzle
|
||||
/* Sliding Puzzle
|
||||
*
|
||||
* This demo demonstrates how to use gestures and paintables to create a
|
||||
* small sliding puzzle game.
|
||||
@@ -11,8 +11,6 @@
|
||||
#include "puzzlepiece.h"
|
||||
#include "paintable.h"
|
||||
|
||||
/* Give out awards */
|
||||
#include "award.h"
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
static GtkWidget *frame = NULL;
|
||||
@@ -159,14 +157,6 @@ check_solved (GtkWidget *grid)
|
||||
picture = gtk_grid_get_child_at (GTK_GRID (grid), pos_x, pos_y);
|
||||
gtk_picture_set_paintable (GTK_PICTURE (picture), piece);
|
||||
|
||||
/* Hand out a bunch of awards
|
||||
*/
|
||||
award ("puzzle-solve");
|
||||
if ((gdk_paintable_get_flags (piece) & GDK_PAINTABLE_STATIC_CONTENTS) == 0)
|
||||
award ("puzzle-solve-animated");
|
||||
if (height * width > 20)
|
||||
award ("puzzle-solve-large");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -251,6 +241,8 @@ puzzle_button_pressed (GtkGestureClick *gesture,
|
||||
{
|
||||
gtk_widget_error_bell (grid);
|
||||
}
|
||||
|
||||
check_solved (grid);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -291,6 +283,8 @@ start_puzzle (GdkPaintable *paintable)
|
||||
/* Add shortcuts so people can use the arrow
|
||||
* keys to move the puzzle */
|
||||
controller = gtk_shortcut_controller_new ();
|
||||
gtk_shortcut_controller_set_scope (GTK_SHORTCUT_CONTROLLER (controller),
|
||||
GTK_SHORTCUT_SCOPE_GLOBAL);
|
||||
add_move_binding (GTK_SHORTCUT_CONTROLLER (controller),
|
||||
GDK_KEY_Left, GDK_KEY_KP_Left,
|
||||
-1, 0);
|
||||
@@ -351,11 +345,16 @@ reshuffle (void)
|
||||
{
|
||||
GtkWidget *grid;
|
||||
|
||||
grid = gtk_aspect_frame_get_child (GTK_ASPECT_FRAME (frame));
|
||||
if (solved)
|
||||
start_puzzle (puzzle);
|
||||
{
|
||||
start_puzzle (puzzle);
|
||||
grid = gtk_aspect_frame_get_child (GTK_ASPECT_FRAME (frame));
|
||||
}
|
||||
else
|
||||
shuffle_puzzle (grid);
|
||||
{
|
||||
grid = gtk_aspect_frame_get_child (GTK_ASPECT_FRAME (frame));
|
||||
shuffle_puzzle (grid);
|
||||
}
|
||||
gtk_widget_grab_focus (grid);
|
||||
}
|
||||
|
||||
@@ -407,9 +406,6 @@ widget_destroyed (gpointer data,
|
||||
{
|
||||
if (data)
|
||||
*(gpointer *) data = NULL;
|
||||
|
||||
if (!solved)
|
||||
award ("puzzle-give-up");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -92,12 +92,11 @@ static Theme themes[] = {
|
||||
static int theme;
|
||||
|
||||
static gboolean
|
||||
change_theme (GtkWidget *widget,
|
||||
change_theme (GtkWidget *widget,
|
||||
GdkFrameClock *frame_clock,
|
||||
gpointer data)
|
||||
gpointer data)
|
||||
{
|
||||
GtkBuilder *builder = data;
|
||||
GtkWidget *label;
|
||||
GtkWidget *label = data;
|
||||
Theme next = themes[theme++ % G_N_ELEMENTS (themes)];
|
||||
char *name;
|
||||
|
||||
@@ -110,7 +109,6 @@ change_theme (GtkWidget *widget,
|
||||
gtk_window_set_title (GTK_WINDOW (widget), name);
|
||||
g_free (name);
|
||||
|
||||
label = GTK_WIDGET (gtk_builder_get_object (builder, "fps"));
|
||||
if (frame_clock)
|
||||
{
|
||||
char *fps;
|
||||
@@ -127,10 +125,10 @@ change_theme (GtkWidget *widget,
|
||||
|
||||
static void
|
||||
clicked (GtkGestureClick *gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data)
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GdkEvent *event;
|
||||
@@ -165,6 +163,29 @@ clicked (GtkGestureClick *gesture,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
toggle_cycle (GObject *button,
|
||||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
gboolean active;
|
||||
GtkWidget *window;
|
||||
|
||||
g_object_get (button, "active", &active, NULL);
|
||||
|
||||
window = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_WINDOW);
|
||||
|
||||
if (active && !tick_cb)
|
||||
{
|
||||
tick_cb = gtk_widget_add_tick_callback (window, change_theme, data, NULL);
|
||||
}
|
||||
else if (!active && tick_cb)
|
||||
{
|
||||
gtk_widget_remove_tick_callback (window, tick_cb);
|
||||
tick_cb = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_themes (GtkWidget *do_widget)
|
||||
{
|
||||
@@ -174,6 +195,8 @@ do_themes (GtkWidget *do_widget)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GtkWidget *header;
|
||||
GtkWidget *button;
|
||||
GtkWidget *label;
|
||||
GtkGesture *gesture;
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/themes/themes.ui");
|
||||
@@ -183,11 +206,17 @@ do_themes (GtkWidget *do_widget)
|
||||
gtk_widget_get_display (do_widget));
|
||||
|
||||
header = GTK_WIDGET (gtk_builder_get_object (builder, "header"));
|
||||
label = GTK_WIDGET (gtk_builder_get_object (builder, "fps"));
|
||||
|
||||
gesture = gtk_gesture_click_new ();
|
||||
g_signal_connect (gesture, "pressed", G_CALLBACK (clicked), builder);
|
||||
g_signal_connect (gesture, "pressed", G_CALLBACK (clicked), label);
|
||||
gtk_widget_add_controller (header, GTK_EVENT_CONTROLLER (gesture));
|
||||
|
||||
button = GTK_WIDGET (gtk_builder_get_object (builder, "toggle"));
|
||||
g_signal_connect (button, "notify::active", G_CALLBACK (toggle_cycle), label);
|
||||
gtk_widget_realize (window);
|
||||
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="start">
|
||||
<object class="GtkToggleButton" id="toggle">
|
||||
<property name="label">Cycle</property>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkLabel" id="fps"/>
|
||||
</child>
|
||||
|
||||
@@ -93,7 +93,6 @@ gdk_display_get_clipboard
|
||||
gdk_display_get_primary_clipboard
|
||||
gdk_display_get_setting
|
||||
gdk_display_get_startup_notification_id
|
||||
gdk_display_setup_window_visual
|
||||
|
||||
<SUBSECTION>
|
||||
gdk_display_put_event
|
||||
@@ -358,9 +357,6 @@ gdk_device_get_name
|
||||
gdk_device_get_vendor_id
|
||||
gdk_device_get_product_id
|
||||
gdk_device_get_source
|
||||
gdk_device_set_key
|
||||
gdk_device_get_key
|
||||
gdk_device_set_axis_use
|
||||
gdk_device_get_axis_use
|
||||
gdk_device_get_associated_device
|
||||
gdk_device_list_slave_devices
|
||||
@@ -368,7 +364,6 @@ gdk_device_get_device_type
|
||||
gdk_device_get_display
|
||||
gdk_device_get_has_cursor
|
||||
gdk_device_get_n_axes
|
||||
gdk_device_get_n_keys
|
||||
gdk_device_get_axes
|
||||
gdk_device_get_seat
|
||||
gdk_device_get_num_touches
|
||||
@@ -383,8 +378,6 @@ gdk_device_has_bidi_layouts
|
||||
<SUBSECTION>
|
||||
gdk_device_get_state
|
||||
gdk_device_get_surface_at_position
|
||||
gdk_device_get_history
|
||||
gdk_device_free_history
|
||||
GdkTimeCoord
|
||||
gdk_device_get_axis
|
||||
gdk_device_get_axis_names
|
||||
@@ -501,7 +494,9 @@ gdk_event_get_modifier_state
|
||||
gdk_event_get_position
|
||||
gdk_event_get_axes
|
||||
gdk_event_get_axis
|
||||
gdk_event_get_history
|
||||
gdk_event_get_pointer_emulated
|
||||
gdk_event_triggers_context_menu
|
||||
gdk_button_event_get_button
|
||||
gdk_scroll_event_get_direction
|
||||
gdk_scroll_event_get_deltas
|
||||
@@ -520,6 +515,7 @@ gdk_crossing_event_get_mode
|
||||
gdk_crossing_event_get_detail
|
||||
gdk_crossing_event_get_focus
|
||||
gdk_grab_broken_event_get_grab_surface
|
||||
gdk_grab_broken_event_get_implicit
|
||||
gdk_dnd_event_get_drop
|
||||
gdk_configure_event_get_size
|
||||
gdk_touchpad_event_get_gesture_phase
|
||||
@@ -530,7 +526,6 @@ gdk_touchpad_event_get_pinch_scale
|
||||
gdk_pad_event_get_axis_value
|
||||
gdk_pad_event_get_button
|
||||
gdk_pad_event_get_group_mode
|
||||
gdk_motion_event_get_history
|
||||
|
||||
<SUBSECTION>
|
||||
gdk_events_get_angle
|
||||
@@ -545,8 +540,23 @@ GDK_TYPE_CROSSING_MODE
|
||||
GDK_TYPE_SCROLL_DIRECTION
|
||||
GDK_TYPE_NOTIFY_TYPE
|
||||
GDK_IS_EVENT
|
||||
|
||||
gdk_event_get_type
|
||||
gdk_event_sequence_get_type
|
||||
gdk_button_event_get_type
|
||||
gdk_configure_event_get_type
|
||||
gdk_crossing_event_get_type
|
||||
gdk_delete_event_get_type
|
||||
gdk_dnd_event_get_type
|
||||
gdk_focus_event_get_type
|
||||
gdk_grab_broken_event_get_type
|
||||
gdk_key_event_get_type
|
||||
gdk_motion_event_get_type
|
||||
gdk_pad_event_get_type
|
||||
gdk_proximity_event_get_type
|
||||
gdk_scroll_event_get_type
|
||||
gdk_touch_event_get_type
|
||||
gdk_touchpad_event_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
||||
@@ -27,15 +27,19 @@ private_headers = [
|
||||
'gdkmonitorprivate.h',
|
||||
'gdkmemorytextureprivate.h',
|
||||
'gdkpipeiostreamprivate.h',
|
||||
'gdkpopupprivate.h',
|
||||
'gdkprofilerprivate.h',
|
||||
'gdkscreenprivate.h',
|
||||
'gdkseatdefaultprivate.h',
|
||||
'gdkseatprivate.h',
|
||||
'gdksnapshotprivate.h',
|
||||
'gdksurfaceimpl.h',
|
||||
'gdksurfaceprivate.h',
|
||||
'gdktextureprivate.h',
|
||||
'gdktoplevelprivate.h',
|
||||
'gdkvulkancontextprivate.h',
|
||||
'keyname-table.h',
|
||||
'gdkprivate-x11.h',
|
||||
'x11/gdkprivate-x11.h',
|
||||
'x11/gdkeventsource.h',
|
||||
'gtk-primary-selection-client-protocol.h',
|
||||
'gtk-shell-client-protocol.h',
|
||||
|
||||
@@ -236,7 +236,6 @@ gsk_transform_to_translate
|
||||
gsk_transform_transform
|
||||
gsk_transform_invert
|
||||
gsk_transform_matrix
|
||||
gsk_transform_matrix_with_category
|
||||
gsk_transform_translate
|
||||
gsk_transform_translate_3d
|
||||
gsk_transform_rotate
|
||||
|
||||
@@ -9,9 +9,11 @@ private_headers = [
|
||||
'gskprofilerprivate.h',
|
||||
'gskrendererprivate.h',
|
||||
'gskrendernodeprivate.h',
|
||||
'gskrendernodeparserprivate.h',
|
||||
'gskroundedrectprivate.h',
|
||||
'gskshaderbuilderprivate.h',
|
||||
'gsktextureprivate.h',
|
||||
'gsktransformprivate.h',
|
||||
'gskvulkanblendpipelineprivate.h',
|
||||
'gskvulkanborderpipelineprivate.h',
|
||||
'gskvulkanboxshadowpipelineprivate.h',
|
||||
|
||||
@@ -37,7 +37,7 @@ this range will trigger compiler warnings.
|
||||
Here is how you would compile hello.c if you want to allow it
|
||||
to use symbols that were not deprecated in 4.2:
|
||||
```
|
||||
$ cc `pkg-config --cflags gtk4` -DGDK_VERSION_MIN_REQIRED=GDK_VERSION_4_2 hello.c -o hello `pkg-config --libs gtk4`
|
||||
$ cc `pkg-config --cflags gtk4` -DGDK_VERSION_MIN_REQUIRED=GDK_VERSION_4_2 hello.c -o hello `pkg-config --libs gtk4`
|
||||
```
|
||||
|
||||
And here is how you would compile hello.c if you don't want
|
||||
|
||||
@@ -68,8 +68,12 @@
|
||||
<xi:include href="xml/gtkmultisorter.xml" />
|
||||
</section>
|
||||
<xi:include href="xml/gtkselectionmodel.xml" />
|
||||
<xi:include href="xml/gtknoselection.xml" />
|
||||
<xi:include href="xml/gtksingleselection.xml" />
|
||||
<section>
|
||||
<xi:include href="xml/gtknoselection.xml" />
|
||||
<xi:include href="xml/gtksingleselection.xml" />
|
||||
<xi:include href="xml/gtkmultiselection.xml" />
|
||||
<xi:include href="xml/gtkpropertyselection.xml" />
|
||||
</section>
|
||||
<xi:include href="xml/gtkdirectorylist.xml" />
|
||||
</chapter>
|
||||
|
||||
@@ -90,8 +94,11 @@
|
||||
</chapter>
|
||||
|
||||
<chapter id="Trees">
|
||||
<xi:include href="xml/gtktreelistrow.xml" />
|
||||
<title>Tree support</title>
|
||||
<xi:include href="xml/gtktreelistmodel.xml" />
|
||||
<section>
|
||||
<xi:include href="xml/gtktreelistrow.xml" />
|
||||
</section>
|
||||
<xi:include href="xml/gtktreelistrowsorter.xml" />
|
||||
<xi:include href="xml/gtktreeexpander.xml" />
|
||||
</chapter>
|
||||
@@ -120,6 +127,7 @@
|
||||
<xi:include href="xml/gtkaboutdialog.xml" />
|
||||
<xi:include href="xml/gtkassistant.xml" />
|
||||
<xi:include href="xml/gtkwindowgroup.xml" />
|
||||
<xi:include href="xml/gtknativedialog.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="LayoutContainers">
|
||||
|
||||
@@ -350,6 +350,9 @@ gtk_selection_model_select_range
|
||||
gtk_selection_model_unselect_range
|
||||
gtk_selection_model_select_all
|
||||
gtk_selection_model_unselect_all
|
||||
GtkSelectionCallback
|
||||
gtk_selection_model_select_callback
|
||||
gtk_selection_model_unselect_callback
|
||||
gtk_selection_model_query_range
|
||||
<SUBSECTION>
|
||||
gtk_selection_model_selection_changed
|
||||
@@ -392,6 +395,24 @@ gtk_single_selection_set_can_unselect
|
||||
gtk_single_selection_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkmultiselection</FILE>
|
||||
<TITLE>GtkMultiSeledction</TITLE>
|
||||
GtkMultiSelection
|
||||
gtk_multi_selection_new
|
||||
<SUBSECTION Private>
|
||||
gtk_multi_selection_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkpropertyselection</FILE>
|
||||
<TITLE>GtkPropertySelection</TITLE>
|
||||
GtkPropertySelection
|
||||
gtk_property_selection_new
|
||||
<SUBSECTION Private>
|
||||
gtk_property_selection_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtklistitem</FILE>
|
||||
<TITLE>GtkListItem</TITLE>
|
||||
@@ -481,9 +502,6 @@ gtk_list_view_set_single_click_activate
|
||||
gtk_list_view_get_single_click_activate
|
||||
gtk_list_view_set_enable_rubberband
|
||||
gtk_list_view_get_enable_rubberband
|
||||
gtk_list_view_set_search_filter
|
||||
gtk_list_view_get_search_filter
|
||||
gtk_list_view_next_match
|
||||
<SUBSECTION Standard>
|
||||
GTK_LIST_VIEW
|
||||
GTK_LIST_VIEW_CLASS
|
||||
@@ -507,16 +525,17 @@ gtk_column_view_get_columns
|
||||
gtk_column_view_get_model
|
||||
gtk_column_view_set_model
|
||||
gtk_column_view_get_sorter
|
||||
gtk_column_view_get_show_separators
|
||||
gtk_column_view_set_show_separators
|
||||
gtk_column_view_get_show_row_separators
|
||||
gtk_column_view_set_show_row_separators
|
||||
gtk_column_view_get_show_column_separators
|
||||
gtk_column_view_set_show_column_separators
|
||||
gtk_column_view_sort_by_column
|
||||
gtk_column_view_set_single_click_activate
|
||||
gtk_column_view_get_single_click_activate
|
||||
gtk_column_view_set_reorderable
|
||||
gtk_column_view_get_reorderable
|
||||
gtk_column_view_set_enable_rubberband
|
||||
gtk_column_view_get_enable_rubberband
|
||||
gtk_column_view_set_search_filter
|
||||
gtk_column_view_get_search_filter
|
||||
gtk_column_view_next_match
|
||||
<SUBSECTION Standard>
|
||||
GTK_COLUMN_VIEW
|
||||
GTK_COLUMN_VIEW_CLASS
|
||||
@@ -543,8 +562,15 @@ gtk_column_view_column_set_sorter
|
||||
gtk_column_view_column_get_sorter
|
||||
gtk_column_view_column_set_visible
|
||||
gtk_column_view_column_get_visible
|
||||
gtk_column_view_column_set_resizable
|
||||
gtk_column_view_column_get_resizable
|
||||
gtk_column_view_column_set_header_menu
|
||||
gtk_column_view_column_get_header_menu
|
||||
gtk_column_view_column_set_fixed_width
|
||||
gtk_column_view_column_get_fixed_width
|
||||
gtk_column_view_column_set_expand
|
||||
gtk_column_view_column_get_expand
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_COLUMN_VIEW_COLUMN
|
||||
GTK_COLUMN_VIEW_COLUMN_CLASS
|
||||
@@ -571,9 +597,6 @@ gtk_grid_view_set_single_click_activate
|
||||
gtk_grid_view_get_single_click_activate
|
||||
gtk_grid_view_set_enable_rubberband
|
||||
gtk_grid_view_get_enable_rubberband
|
||||
gtk_grid_view_set_search_filter
|
||||
gtk_grid_view_get_search_filter
|
||||
gtk_grid_view_next_match
|
||||
<SUBSECTION Standard>
|
||||
GTK_GRID_VIEW
|
||||
GTK_GRID_VIEW_CLASS
|
||||
@@ -1443,7 +1466,6 @@ gtk_custom_filter_get_type
|
||||
<FILE>gtkfilterlistmodel</FILE>
|
||||
<TITLE>GtkFilterListModel</TITLE>
|
||||
GtkFilterListModel
|
||||
GtkFilterListModelFilterFunc
|
||||
gtk_filter_list_model_new
|
||||
gtk_filter_list_model_new_for_type
|
||||
gtk_filter_list_model_set_model
|
||||
@@ -2033,7 +2055,7 @@ gtk_info_bar_get_type
|
||||
<SECTION>
|
||||
<FILE>gtknativedialog</FILE>
|
||||
<TITLE>GtkNativeDialog</TITLE>
|
||||
GTK_TYPE_NATIVE_DIALOG
|
||||
GtkNativeDialog
|
||||
GtkNativeDialogClass
|
||||
gtk_native_dialog_show
|
||||
gtk_native_dialog_hide
|
||||
@@ -2045,9 +2067,8 @@ gtk_native_dialog_set_title
|
||||
gtk_native_dialog_get_title
|
||||
gtk_native_dialog_set_transient_for
|
||||
gtk_native_dialog_get_transient_for
|
||||
<SUBSECTION Standard>
|
||||
GtkNativeDialog
|
||||
<SUBSECTION Private>
|
||||
GTK_TYPE_NATIVE_DIALOG
|
||||
gtk_native_dialog_get_type
|
||||
</SECTION>
|
||||
|
||||
@@ -2121,12 +2142,18 @@ GtkNotebookPrivate
|
||||
<TITLE>GtkPaned</TITLE>
|
||||
GtkPaned
|
||||
gtk_paned_new
|
||||
gtk_paned_add1
|
||||
gtk_paned_add2
|
||||
gtk_paned_pack1
|
||||
gtk_paned_pack2
|
||||
gtk_paned_get_child1
|
||||
gtk_paned_get_child2
|
||||
gtk_paned_set_start_child
|
||||
gtk_paned_get_start_child
|
||||
gtk_paned_set_end_child
|
||||
gtk_paned_get_end_child
|
||||
gtk_paned_set_resize_start_child
|
||||
gtk_paned_get_resize_start_child
|
||||
gtk_paned_set_resize_end_child
|
||||
gtk_paned_get_resize_end_child
|
||||
gtk_paned_set_shrink_start_child
|
||||
gtk_paned_get_shrink_start_child
|
||||
gtk_paned_set_shrink_end_child
|
||||
gtk_paned_get_shrink_end_child
|
||||
gtk_paned_set_position
|
||||
gtk_paned_get_position
|
||||
gtk_paned_set_wide_handle
|
||||
|
||||
@@ -139,6 +139,7 @@ gtk_menu_button_get_type
|
||||
gtk_message_dialog_get_type
|
||||
gtk_mount_operation_get_type
|
||||
gtk_multi_filter_get_type
|
||||
gtk_multi_selection_get_type
|
||||
gtk_multi_sorter_get_type
|
||||
gtk_native_get_type
|
||||
gtk_native_dialog_get_type
|
||||
@@ -168,6 +169,7 @@ gtk_print_operation_preview_get_type
|
||||
gtk_print_settings_get_type
|
||||
@DISABLE_ON_W32@gtk_print_unix_dialog_get_type
|
||||
gtk_progress_bar_get_type
|
||||
gtk_property_selection_get_type
|
||||
gtk_radio_button_get_type
|
||||
gtk_range_get_type
|
||||
gtk_recent_manager_get_type
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
# List widgets
|
||||
|
||||
GTK provides powerful widgets to display and edit lists of data. This document gives an overview over the concepts and how they work together to allow developers to implement lists.
|
||||
|
||||
Lists are intended to be used whenever developers want to display lists of objects in roughly the same way.
|
||||
|
||||
Lists are perfectly fine to be used for very short list of only 2 or 3 elements, but generally scale fine to millions of items. Of course, the larger the list grows, the more care needs to be taken to choose the right data structures to keep things running well.
|
||||
|
||||
Lists are meant to be used with changing data, both with the items itself changing as well as the list adding and removing items. Of course, they work just as well with static data.
|
||||
|
||||
## Terminology
|
||||
|
||||
These terms are used throughout the documentation when talking about lists and you should be aware of what they refer to. These are often generic terms that have a specific meaning in this context.
|
||||
|
||||
**_Views_** or **_list widgets_** are the widgets that hold and manage the lists. Examples of thse widgets would be #GtkListView or #GtkGridView.
|
||||
|
||||
Views display data from a **_model_**. A model is a #GListModel and models can be provided in 3 ways or combinations thereof:
|
||||
|
||||
* Many list models implementations already exist. There are models that provide specific data, like #GtkDirectoryList. And there are models like #GListStore that allow building lists manually.
|
||||
|
||||
* Wrapping list models exists like #GtkFilterListModel or #GtkSortListModel that modify or adapt or combine other models.
|
||||
|
||||
* Last but not least, developers are encouraged to create their own #GListModel implementations. The interface is kept deliberately small to make this easy.
|
||||
|
||||
The same model can be used in multiple different views and wrapped with multiple different models at once.
|
||||
|
||||
The elements in a model are called **_items_**. All items are #GObjects.
|
||||
|
||||
Every item in a model has a **_position_** which is the unsigned integer that describes where in the model the item is located. This position can of course change as items are added or removed from the model.
|
||||
|
||||
It is important to be aware of the difference between items and positions because the mapping from position to item is not permanent, so developers should think about whether they want to track items or positions when working with models. Oftentimes some things are really hard to do one way but very easy the other way.
|
||||
|
||||
The other important part of a view is a **_factory_**. Each factory is a #GtkListItemFactory implementation that takes care of mapping the items of the model to widgets that can be shown in the view.
|
||||
|
||||
The way factories do this is by creating a **_listitem_** for each item that is currently in use. Listitems are always #GtkListItem objects. They are only ever created by GTK and provide information about what item they are meant to display.
|
||||
|
||||
Different factory implementations use various different methods to allow developers to add the right widgets to listitems and to link those widgets with the item managed by the listitem. Finding a suitable factory implementation for the data displayed, the programming language and development environment is an important task that can simplify setting up the view tremendously.
|
||||
|
||||
Views support selections via a **_selection model_**. A selection model is an implementation of the #GtkSelectionModel interface on top of the #GListModel interface that allows marking each item in a model as either selected or not selected. Just like regular models, this can be implemented either by implementing #GtkSelectionModel directly or by wrapping a model with one of the GTK models provided for this purposes, such as #GtkNoSelection or #GtkSingleSelection. The behavior of selection models - ie which items they allow selecting and what effect this has on other items - is completely up to the selection model. As such, single-selections, multi-selections or sharing selection state between different selection models and/or views is possible. The selection state of an item is exposed in the listitem via the GtkListItem:selected property.
|
||||
|
||||
Views and listitems also support activation. Activation means that double clicking or pressing enter while inside a focused row will cause the view to emit and activation signal such as GtkListView::activate. This provides an easy way to set up lists, but can also be turned off on listitems if undesired.
|
||||
|
||||
Both selections and activation are supported among other things via widget actions (FIXME: Link docs). This allows developers to add widgets to their lists that cause selections to change or to trigger activation via the #GtkActionable interface. For a list of all supported actions see the relevant documentation. (FIXME: where do we document actions and how to I link that?)
|
||||
|
||||
## Behind the scenes
|
||||
|
||||
While for short lists it is not a problem to instantiate widgets for every item in the model, once lists grow to thousands or millions of elements, this gets less feasible. Because of this, the views only create a limited amount of listitems and recycle them by binding them to new items. In general, views try to keep listitems available only for the items that can actually be seen on screen.
|
||||
|
||||
While this behavior allows views to scale effortlessly to huge lists, it has a few implication on what can be done with views. For example, it is not possible to query a view for a listitem used for a certain position - there might not be one and even if there is, that listitem might soon be recycled for a new position.
|
||||
|
||||
It is also important that developers save state they care about in the item and do not rely on the widgets they created as those widgets can be recycled for a new position at any time causing any state to be lost.
|
||||
|
||||
Another important requirement for views is that they need to know which items are not visible so they can be recycled. Views achieve that by implementing the #GtkScrollable interface and expecting to be placed directly into a #GtkScrolledWindow.
|
||||
|
||||
Of course, if you are only using models with few items, this is not important and you can treat views like any other widget. But if you use large lists and your performance suffers, you should be aware of this. Views also allow tuning the number of listitems they create such as with gtk_grid_view_set_max_columns(), and developers running into performance problems should definitely study the tradeoffs of those and experiment with them.
|
||||
|
||||
## Displaying trees
|
||||
|
||||
While #GtkTreeView provided builtin support for trees, the list widgets, and in particular #GListModel do not. This was a design choice because the common use case is displaying lists and not trees and it greatly simplifies the API interface provided.
|
||||
|
||||
However, GTK provides functionality to make trees look and behave like lists for the people who still want to display lists. This is achieved by using the #GtkTreeListModel model to flatten a tree into a list. The #GtkTreeExpander widget can then be used inside a listitem to allow users to expand and collapse rows and provide a similar experience to #GtkTreeView.
|
||||
|
||||
Developers should refer to those objects' API reference for more discussion on the topic.
|
||||
|
||||
## comparison to GtkTreeView
|
||||
|
||||
Developers familiar with #GtkTreeView may wonder how this way of doing lists compares to the way they know. This section will try to outline the similarities and differences between the two.
|
||||
|
||||
This new approach tries to provide roughly the same functionality as the old approach but often uses a very different approach to achieve these goals.
|
||||
|
||||
The main difference and one of the primary reasons for this new development is that items can be displayed using regular widgets and #GtkCellRenderer is no longer necessary. This allows all benefits that widgets provide, such as complex layout and animating widgets and not only makes cell renderers obsolete, but also #GtkCellArea.
|
||||
|
||||
The other big difference is the massive change to the data model. #GtkTreeModel was a rather complex interface for a tree data structure and #GListModel was deliberately designed to be a simple data structure for lists only. (See above (FIXME: link) for how to still do trees with this new model.) Another big change is that the new model allows for bulk changes via the #GListModel:items-changed signal while #GtkTreeModel only allows a single item to change at once. The goal here is of course to encourage implementation of custom list models.
|
||||
|
||||
Another consequence of the new model is that it is now easily possible to refer to the contents of a row in the model directly by keeping the item, while #GtkTreeRowReference was a very slow mechanism to achieve the same. And because the items are real objects, developers can make them emit change signals causing listitems and their children to update, which wasn't possible with #GtkTreeModel.
|
||||
|
||||
The selection handling is also different. While selections used to be managed via custom code in each widget, selection state is now meant to be managed by the selection models. In particular this allows for complex use cases with specialized requirements (FIXME: Can I add a shoutout to @mitch here because I vividly remember a huge discussion about GtkTreeView's selection behavior and the Gimp).
|
||||
|
||||
Finally here's a quick list of equivalent functionality to look for when transitioning code for easy lookup:
|
||||
|
||||
| old | new |
|
||||
| ------------------- | ----------------------------------- |
|
||||
| #GtkTreeModel | #GListModel |
|
||||
| #GtkTreePath | #guint position, #GtkTreeListRow |
|
||||
| #GtkTreeIter | #guint position |
|
||||
| GtkTreeRowReference | #GObject item |
|
||||
| #GtkListStore | #GListStore |
|
||||
| #GtkTreeStore | #GtkTreeListModel, #GtkTreeExpander |
|
||||
| #GtkTreeSelection | #GtkSelectionModel |
|
||||
| #GtkTreeViewColumn | #GtkColumnView |
|
||||
| #GtkTreeView | #GtkListView, #GtkColumnView |
|
||||
| #GtkCellView | |
|
||||
| #GtkComboBox | |
|
||||
| #GtkIconView | #GtkGridView |
|
||||
| #GtkTreeSortable | |
|
||||
| #GtkTreeModelSort | #GtkSortListModel |
|
||||
| #GtkTreeModelFilter | #GtkFilterListModel |
|
||||
| #GtkCellLayout | #GtkListItemFactory |
|
||||
| #GtkCellArea | #GtkWidget |
|
||||
| #GtkCellRenderer | #GtkWidget |
|
||||
|
||||
@@ -13,6 +13,7 @@ private_headers = [
|
||||
'gtkappchooserprivate.h',
|
||||
'gtkapplicationaccelsprivate.h',
|
||||
'gtkapplicationprivate.h',
|
||||
'gtkarrayimplprivate.h',
|
||||
'gtkbindingsprivate.h',
|
||||
'gtkbitmaskprivate.h',
|
||||
'gtkbuilderprivate.h',
|
||||
@@ -148,11 +149,14 @@ private_headers = [
|
||||
'gtkmagnifierprivate.h',
|
||||
'gtkmediafileprivate.h',
|
||||
'gtkmenubuttonprivate.h',
|
||||
'gtkmenusectionboxprivate.h',
|
||||
'gtkmenutrackeritemprivate.h',
|
||||
'gtkmenutrackerprivate.h',
|
||||
'gtkmodulesprivate.h',
|
||||
'gtkmountoperationprivate.h',
|
||||
'gtknativedialogprivate.h',
|
||||
'gtknomediafileprivate.h',
|
||||
'gtkorientableprivate.h',
|
||||
'gtkpango.h',
|
||||
'gtkplacessidebarprivate.h',
|
||||
'gtkplacesviewprivate.h',
|
||||
'gtkplacesviewrowprivate.h',
|
||||
@@ -162,6 +166,7 @@ private_headers = [
|
||||
'gtkprintoperation-private.h',
|
||||
'gtkprivate.h',
|
||||
'gtkprogresstrackerprivate.h',
|
||||
'gtkquery.h',
|
||||
'gtkrangeprivate.h',
|
||||
'gtkrbtreeprivate.h',
|
||||
'gtkrenderbackgroundprivate.h',
|
||||
@@ -171,7 +176,9 @@ private_headers = [
|
||||
'gtkroundedboxprivate.h',
|
||||
'gtkscalerprivate.h',
|
||||
'gtksearchentryprivate.h',
|
||||
'gtkset.h',
|
||||
'gtksettingsprivate.h',
|
||||
'gtkshortcutcontrollerprivate.h',
|
||||
'gtkshortcutsshortcutprivate.h',
|
||||
'gtkshortcutswindowprivate.h',
|
||||
'gtksidebarrowprivate.h',
|
||||
@@ -198,7 +205,9 @@ private_headers = [
|
||||
'gtktoolbarprivate.h',
|
||||
'gtktooltipprivate.h',
|
||||
'gtktooltipwindowprivate.h',
|
||||
'gtktreepopoverprivate.h',
|
||||
'gtktreeprivate.h',
|
||||
'gtktreerbtreeprivate.h',
|
||||
'gtkutilsprivate.h',
|
||||
'gtkwidgetpaintableprivate.h',
|
||||
'gtkwidgetpathprivate.h',
|
||||
|
||||
@@ -1,85 +1,181 @@
|
||||
# List Widget Overview {#ListWidget}
|
||||
|
||||
GTK provides powerful widgets to display and edit lists of data. This document gives an overview over the concepts and how they work together to allow developers to implement lists.
|
||||
GTK provides powerful widgets to display and edit lists of data. This document
|
||||
gives an overview over the concepts and how they work together to allow
|
||||
developers to implement lists.
|
||||
|
||||
Lists are intended to be used whenever developers want to display lists of objects in roughly the same way.
|
||||
Lists are intended to be used whenever developers want to display lists of
|
||||
objects in roughly the same way.
|
||||
|
||||
Lists are perfectly fine to be used for very short list of only 2 or 3 elements, but generally scale fine to millions of items. Of course, the larger the list grows, the more care needs to be taken to choose the right data structures to keep things running well.
|
||||
Lists are perfectly fine to be used for very short list of only 2 or 3 elements,
|
||||
but generally scale fine to millions of items. Of course, the larger the list
|
||||
grows, the more care needs to be taken to choose the right data structures to
|
||||
keep things running well.
|
||||
|
||||
Lists are meant to be used with changing data, both with the items itself changing as well as the list adding and removing items. Of course, they work just as well with static data.
|
||||
Lists are meant to be used with changing data, both with the items itself changing
|
||||
as well as the list adding and removing items. Of course, they work just as well
|
||||
with static data.
|
||||
|
||||
## Terminology
|
||||
|
||||
These terms are used throughout the documentation when talking about lists and you should be aware of what they refer to. These are often generic terms that have a specific meaning in this context.
|
||||
These terms are used throughout the documentation when talking about lists and
|
||||
you should be aware of what they refer to. These are often generic terms that
|
||||
have a specific meaning in this context.
|
||||
|
||||
**_Views_** or **_list widgets_** are the widgets that hold and manage the lists. Examples of thse widgets would be #GtkListView or #GtkGridView.
|
||||
**_Views_** or **_list widgets_** are the widgets that hold and manage the lists.
|
||||
Examples of these widgets would be #GtkListView or #GtkGridView.
|
||||
|
||||
Views display data from a **_model_**. A model is a #GListModel and models can be provided in 3 ways or combinations thereof:
|
||||
Views display data from a **_model_**. A model is a #GListModel and models can
|
||||
be provided in 3 ways or combinations thereof:
|
||||
|
||||
* Many list models implementations already exist. There are models that provide specific data, like #GtkDirectoryList. And there are models like #GListStore that allow building lists manually.
|
||||
* Many list models implementations already exist. There are models that provide
|
||||
specific data, like #GtkDirectoryList. And there are models like #GListStore
|
||||
that allow building lists manually.
|
||||
|
||||
* Wrapping list models exists like #GtkFilterListModel or #GtkSortListModel that modify or adapt or combine other models.
|
||||
* Wrapping list models exists like #GtkFilterListModel or #GtkSortListModel
|
||||
that modify or adapt or combine other models.
|
||||
|
||||
* Last but not least, developers are encouraged to create their own #GListModel implementations. The interface is kept deliberately small to make this easy.
|
||||
* Last but not least, developers are encouraged to create their own #GListModel
|
||||
implementations. The interface is kept deliberately small to make this easy.
|
||||
|
||||
The same model can be used in multiple different views and wrapped with multiple different models at once.
|
||||
The same model can be used in multiple different views and wrapped with
|
||||
multiple different models at once.
|
||||
|
||||
The elements in a model are called **_items_**. All items are #GObjects.
|
||||
|
||||
Every item in a model has a **_position_** which is the unsigned integer that describes where in the model the item is located. This position can of course change as items are added or removed from the model.
|
||||
Every item in a model has a **_position_** which is the unsigned integer that
|
||||
describes where in the model the item is located. This position can of course
|
||||
change as items are added or removed from the model.
|
||||
|
||||
It is important to be aware of the difference between items and positions because the mapping from position to item is not permanent, so developers should think about whether they want to track items or positions when working with models. Oftentimes some things are really hard to do one way but very easy the other way.
|
||||
It is important to be aware of the difference between items and positions
|
||||
because the mapping from position to item is not permanent, so developers
|
||||
should think about whether they want to track items or positions when working
|
||||
with models. Oftentimes some things are really hard to do one way but very easy
|
||||
the other way.
|
||||
|
||||
The other important part of a view is a **_factory_**. Each factory is a #GtkListItemFactory implementation that takes care of mapping the items of the model to widgets that can be shown in the view.
|
||||
The other important part of a view is a **_factory_**. Each factory is
|
||||
a #GtkListItemFactory implementation that takes care of mapping the items
|
||||
of the model to widgets that can be shown in the view.
|
||||
|
||||
The way factories do this is by creating a **_listitem_** for each item that is currently in use. Listitems are always #GtkListItem objects. They are only ever created by GTK and provide information about what item they are meant to display.
|
||||
The way factories do this is by creating a **_listitem_** for each item that
|
||||
is currently in use. Listitems are always #GtkListItem objects. They are only
|
||||
ever created by GTK and provide information about what item they are meant
|
||||
to display.
|
||||
|
||||
Different factory implementations use various different methods to allow developers to add the right widgets to listitems and to link those widgets with the item managed by the listitem. Finding a suitable factory implementation for the data displayed, the programming language and development environment is an important task that can simplify setting up the view tremendously.
|
||||
Different factory implementations use various different methods to allow
|
||||
developers to add the right widgets to listitems and to link those widgets
|
||||
with the item managed by the listitem. Finding a suitable factory implementation
|
||||
for the data displayed, the programming language and development environment
|
||||
is an important task that can simplify setting up the view tremendously.
|
||||
|
||||
Views support selections via a **_selection model_**. A selection model is an implementation of the #GtkSelectionModel interface on top of the #GListModel interface that allows marking each item in a model as either selected or not selected. Just like regular models, this can be implemented either by implementing #GtkSelectionModel directly or by wrapping a model with one of the GTK models provided for this purposes, such as #GtkNoSelection or #GtkSingleSelection.
|
||||
The behavior of selection models - ie which items they allow selecting and what effect this has on other items - is completely up to the selection model. As such, single-selections, multi-selections or sharing selection state between different selection models and/or views is possible.
|
||||
The selection state of an item is exposed in the listitem via the GtkListItem:selected property.
|
||||
Views support selections via a **_selection model_**. A selection model is an
|
||||
implementation of the #GtkSelectionModel interface on top of the #GListModel
|
||||
interface that allows marking each item in a model as either selected or not
|
||||
selected. Just like regular models, this can be implemented either by
|
||||
implementing #GtkSelectionModel directly or by wrapping a model with one of
|
||||
the GTK models provided for this purposes, such as #GtkNoSelection
|
||||
or #GtkSingleSelection.
|
||||
|
||||
Views and listitems also support activation. Activation means that double clicking or pressing enter while inside a focused row will cause the view to emit and activation signal such as GtkListView::activate. This provides an easy way to set up lists, but can also be turned off on listitems if undesired.
|
||||
The behavior of selection models - ie which items they allow selecting and
|
||||
what effect this has on other items - is completely up to the selection model.
|
||||
As such, single-selections, multi-selections or sharing selection state between
|
||||
different selection models and/or views is possible. The selection state of an
|
||||
item is exposed in the listitem via the GtkListItem:selected property.
|
||||
|
||||
Both selections and activation are supported among other things via widget actions (FIXME: Link docs). This allows developers to add widgets to their lists that cause selections to change or to trigger activation via the #GtkActionable interface. For a list of all supported actions see the relevant documentation. (FIXME: where do we document actions and how to I link that?)
|
||||
Views and listitems also support activation. Activation means that double
|
||||
clicking or pressing enter while inside a focused row will cause the view
|
||||
to emit and activation signal such as #GtkListView::activate. This provides
|
||||
an easy way to set up lists, but can also be turned off on listitems if undesired.
|
||||
|
||||
Both selections and activation are supported among other things via widget
|
||||
[actions](#actions-overview). This allows developers to add widgets to their
|
||||
lists that cause selections to change or to trigger activation via
|
||||
the #GtkActionable interface. For a list of all supported actions see the
|
||||
relevant documentation.
|
||||
|
||||
## Behind the scenes
|
||||
|
||||
While for short lists it is not a problem to instantiate widgets for every item in the model, once lists grow to thousands or millions of elements, this gets less feasible. Because of this, the views only create a limited amount of listitems and recycle them by binding them to new items. In general, views try to keep listitems available only for the items that can actually be seen on screen.
|
||||
While for short lists it is not a problem to instantiate widgets for every
|
||||
item in the model, once lists grow to thousands or millions of elements, this
|
||||
gets less feasible. Because of this, the views only create a limited amount of
|
||||
listitems and recycle them by binding them to new items. In general, views try
|
||||
to keep listitems available only for the items that can actually be seen on screen.
|
||||
|
||||
While this behavior allows views to scale effortlessly to huge lists, it has a few implication on what can be done with views. For example, it is not possible to query a view for a listitem used for a certain position - there might not be one and even if there is, that listitem might soon be recycled for a new position.
|
||||
While this behavior allows views to scale effortlessly to huge lists, it has a
|
||||
few implication on what can be done with views. For example, it is not possible
|
||||
to query a view for a listitem used for a certain position - there might not be
|
||||
one and even if there is, that listitem might soon be recycled for a new position.
|
||||
|
||||
It is also important that developers save state they care about in the item and do not rely on the widgets they created as those widgets can be recycled for a new position at any time causing any state to be lost.
|
||||
It is also important that developers save state they care about in the item and
|
||||
do not rely on the widgets they created as those widgets can be recycled for a
|
||||
new position at any time causing any state to be lost.
|
||||
|
||||
Another important requirement for views is that they need to know which items are not visible so they can be recycled. Views achieve that by implementing the #GtkScrollable interface and expecting to be placed directly into a #GtkScrolledWindow.
|
||||
Another important requirement for views is that they need to know which items
|
||||
are not visible so they can be recycled. Views achieve that by implementing
|
||||
the #GtkScrollable interface and expecting to be placed directly into
|
||||
a #GtkScrolledWindow.
|
||||
|
||||
Of course, if you are only using models with few items, this is not important and you can treat views like any other widget. But if you use large lists and your performance suffers, you should be aware of this. Views also allow tuning the number of listitems they create such as with gtk_grid_view_set_max_columns(), and developers running into performance problems should definitely study the tradeoffs of those and experiment with them.
|
||||
Of course, if you are only using models with few items, this is not important
|
||||
and you can treat views like any other widget. But if you use large lists and
|
||||
your performance suffers, you should be aware of this. Views also allow tuning
|
||||
the number of listitems they create such as with gtk_grid_view_set_max_columns(),
|
||||
and developers running into performance problems should definitely study the
|
||||
tradeoffs of those and experiment with them.
|
||||
|
||||
## Displaying trees
|
||||
## Displaying trees {#displaying-trees}
|
||||
|
||||
While #GtkTreeView provided builtin support for trees, the list widgets, and in particular #GListModel do not. This was a design choice because the common use case is displaying lists and not trees and it greatly simplifies the API interface provided.
|
||||
While #GtkTreeView provided built-in support for trees, the list widgets, and
|
||||
in particular #GListModel do not. This was a design choice because the common
|
||||
use case is displaying lists and not trees and it greatly simplifies the API
|
||||
interface provided.
|
||||
|
||||
However, GTK provides functionality to make trees look and behave like lists for the people who still want to display lists. This is achieved by using the #GtkTreeListModel model to flatten a tree into a list. The #GtkTreeExpander widget can then be used inside a listitem to allow users to expand and collapse rows and provide a similar experience to #GtkTreeView.
|
||||
However, GTK provides functionality to make trees look and behave like lists
|
||||
for the people who still want to display lists. This is achieved by using
|
||||
the #GtkTreeListModel model to flatten a tree into a list. The #GtkTreeExpander
|
||||
widget can then be used inside a listitem to allow users to expand and collapse
|
||||
rows and provide a similar experience to #GtkTreeView.
|
||||
|
||||
Developers should refer to those objects' API reference for more discussion on the topic.
|
||||
Developers should refer to those objects' API reference for more discussion
|
||||
on the topic.
|
||||
|
||||
## comparison to GtkTreeView
|
||||
## Comparison to GtkTreeView
|
||||
|
||||
Developers familiar with #GtkTreeView may wonder how this way of doing lists compares to the way they know. This section will try to outline the similarities and differences between the two.
|
||||
Developers familiar with #GtkTreeView may wonder how this way of doing lists
|
||||
compares to the way they know. This section will try to outline the similarities
|
||||
and differences between the two.
|
||||
|
||||
This new approach tries to provide roughly the same functionality as the old approach but often uses a very different approach to achieve these goals.
|
||||
This new approach tries to provide roughly the same functionality as the old
|
||||
approach but often uses a very different approach to achieve these goals.
|
||||
|
||||
The main difference and one of the primary reasons for this new development is that items can be displayed using regular widgets and #GtkCellRenderer is no longer necessary. This allows all benefits that widgets provide, such as complex layout and animating widgets and not only makes cell renderers obsolete, but also #GtkCellArea.
|
||||
The main difference and one of the primary reasons for this new development is
|
||||
that items can be displayed using regular widgets and #GtkCellRenderer is no
|
||||
longer necessary. This allows all benefits that widgets provide, such as complex
|
||||
layout and animating widgets and not only makes cell renderers obsolete, but
|
||||
also #GtkCellArea.
|
||||
|
||||
The other big difference is the massive change to the data model. #GtkTreeModel was a rather complex interface for a tree data structure and #GListModel was deliberately designed to be a simple data structure for lists only. (See above (FIXME: link) for how to still do trees with this new model.) Another big change is that the new model allows for bulk changes via the #GListModel:items-changed signal while #GtkTreeModel only allows a single item to change at once.
|
||||
The goal here is of course to encourage implementation of custom list models.
|
||||
The other big difference is the massive change to the data model. #GtkTreeModel
|
||||
was a rather complex interface for a tree data structure and #GListModel was
|
||||
deliberately designed to be a simple data structure for lists only. (See
|
||||
[above](#displaying-trees)) for how to still do trees with this new model.)
|
||||
Another big change is that the new model allows for bulk changes via
|
||||
the #GListModel:items-changed signal while #GtkTreeModel only allows a single
|
||||
item to change at once. The goal here is of course to encourage implementation
|
||||
of custom list models.
|
||||
|
||||
Another consequence of the new model is that it is now easily possible to refer to the contents of a row in the model directly by keeping the item, while #GtkTreeRowReference was a very slow mechanism to achieve the same. And because the items are real objects, developers can make them emit change signals causing listitems and their children to update, which wasn't possible with #GtkTreeModel.
|
||||
Another consequence of the new model is that it is now easily possible to
|
||||
refer to the contents of a row in the model directly by keeping the item,
|
||||
while #GtkTreeRowReference was a very slow mechanism to achieve the same.
|
||||
And because the items are real objects, developers can make them emit change
|
||||
signals causing listitems and their children to update, which wasn't possible
|
||||
with #GtkTreeModel.
|
||||
|
||||
The selection handling is also different. While selections used to be managed via custom code in each widget, selection state is now meant to be managed by the selection models. In particular this allows for complex use cases with specialized requirements (FIXME: Can I add a shoutout to @mitch here because I vividly remember a huge discussion about GtkTreeView's selection behavior and the Gimp).
|
||||
The selection handling is also different. While selections used to be managed
|
||||
via custom code in each widget, selection state is now meant to be managed by
|
||||
the selection models. In particular this allows for complex use cases with
|
||||
specialized requirements.
|
||||
|
||||
Finally here's a quick list of equivalent functionality to look for when transitioning code for easy lookup:
|
||||
Finally here's a quick list of equivalent functionality to look for when
|
||||
transitioning code for easy lookup:
|
||||
|
||||
| Old | New |
|
||||
| ------------------- | ----------------------------------- |
|
||||
|
||||
@@ -23,12 +23,6 @@
|
||||
#include "gdksurfaceprivate.h"
|
||||
#include "gdkprivate-broadway.h"
|
||||
|
||||
static gboolean gdk_broadway_device_get_history (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
guint32 start,
|
||||
guint32 stop,
|
||||
GdkTimeCoord ***events,
|
||||
gint *n_events);
|
||||
static void gdk_broadway_device_get_state (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
gdouble *axes,
|
||||
@@ -64,7 +58,6 @@ gdk_broadway_device_class_init (GdkBroadwayDeviceClass *klass)
|
||||
{
|
||||
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
|
||||
|
||||
device_class->get_history = gdk_broadway_device_get_history;
|
||||
device_class->get_state = gdk_broadway_device_get_state;
|
||||
device_class->set_surface_cursor = gdk_broadway_device_set_surface_cursor;
|
||||
device_class->query_state = gdk_broadway_device_query_state;
|
||||
@@ -80,19 +73,8 @@ gdk_broadway_device_init (GdkBroadwayDevice *device_core)
|
||||
|
||||
device = GDK_DEVICE (device_core);
|
||||
|
||||
_gdk_device_add_axis (device, NULL, GDK_AXIS_X, 0, 0, 1);
|
||||
_gdk_device_add_axis (device, NULL, GDK_AXIS_Y, 0, 0, 1);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_broadway_device_get_history (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
guint32 start,
|
||||
guint32 stop,
|
||||
GdkTimeCoord ***events,
|
||||
gint *n_events)
|
||||
{
|
||||
return FALSE;
|
||||
_gdk_device_add_axis (device, GDK_AXIS_X, 0, 0, 1);
|
||||
_gdk_device_add_axis (device, GDK_AXIS_Y, 0, 0, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2011 Chun-wei Fan <fanc999@yahoo.com.tw>
|
||||
*
|
||||
* Author: Chun-wei Fan <fanc999@yahoo.com.tw>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#ifndef HAVE_DECL_ISNAN
|
||||
/* it seems of the supported compilers only
|
||||
* MSVC does not have isnan(), but it does
|
||||
* have _isnan() which does the same as isnan()
|
||||
*/
|
||||
static inline gboolean
|
||||
isnan (double x)
|
||||
{
|
||||
return _isnan (x);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_DECL_ISINF
|
||||
/* Unfortunately MSVC does not have finite()
|
||||
* but it does have _finite() which is the same
|
||||
* as finite() except when x is a NaN
|
||||
*/
|
||||
static inline gboolean
|
||||
isinf (double x)
|
||||
{
|
||||
return (!_finite (x) && !_isnan (x));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Workaround for round() for non-GCC/non-C99 compilers */
|
||||
#ifndef HAVE_ROUND
|
||||
static inline double
|
||||
round (double x)
|
||||
{
|
||||
if (x >= 0)
|
||||
return floor (x + 0.5);
|
||||
else
|
||||
return ceil (x - 0.5);
|
||||
}
|
||||
#endif
|
||||
392
gdk/gdkdevice.c
392
gdk/gdkdevice.c
@@ -26,9 +26,6 @@
|
||||
#include "gdkintl.h"
|
||||
#include "gdkkeysprivate.h"
|
||||
|
||||
/* for the use of round() */
|
||||
#include "fallback-c89.c"
|
||||
|
||||
/**
|
||||
* SECTION:gdkdevice
|
||||
* @Short_description: Object representing an input device
|
||||
@@ -54,9 +51,7 @@ typedef struct _GdkAxisInfo GdkAxisInfo;
|
||||
|
||||
struct _GdkAxisInfo
|
||||
{
|
||||
char *label;
|
||||
GdkAxisUse use;
|
||||
|
||||
gdouble min_axis;
|
||||
gdouble max_axis;
|
||||
gdouble min_value;
|
||||
@@ -369,19 +364,10 @@ gdk_device_class_init (GdkDeviceClass *klass)
|
||||
G_TYPE_NONE, 1, GDK_TYPE_DEVICE_TOOL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_axis_info_clear (gpointer data)
|
||||
{
|
||||
GdkAxisInfo *info = data;
|
||||
|
||||
g_free (info->label);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_init (GdkDevice *device)
|
||||
{
|
||||
device->axes = g_array_new (FALSE, TRUE, sizeof (GdkAxisInfo));
|
||||
g_array_set_clear_func (device->axes, gdk_device_axis_info_clear);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -396,7 +382,6 @@ gdk_device_finalize (GObject *object)
|
||||
}
|
||||
|
||||
g_clear_pointer (&device->name, g_free);
|
||||
g_clear_pointer (&device->keys, g_free);
|
||||
g_clear_pointer (&device->vendor_id, g_free);
|
||||
g_clear_pointer (&device->product_id, g_free);
|
||||
|
||||
@@ -638,93 +623,6 @@ gdk_device_get_surface_at_position (GdkDevice *device,
|
||||
return surface;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_get_history: (skip)
|
||||
* @device: a #GdkDevice
|
||||
* @surface: the surface with respect to which the event coordinates will be reported
|
||||
* @start: starting timestamp for range of events to return
|
||||
* @stop: ending timestamp for the range of events to return
|
||||
* @events: (array length=n_events) (out) (transfer full) (optional):
|
||||
* location to store a newly-allocated array of #GdkTimeCoord, or
|
||||
* %NULL
|
||||
* @n_events: (out) (optional): location to store the length of
|
||||
* @events, or %NULL
|
||||
*
|
||||
* Obtains the motion history for a pointer device; given a starting and
|
||||
* ending timestamp, return all events in the motion history for
|
||||
* the device in the given range of time. Some windowing systems
|
||||
* do not support motion history, in which case, %FALSE will
|
||||
* be returned. (This is not distinguishable from the case where
|
||||
* motion history is supported and no events were found.)
|
||||
*
|
||||
* Note that there is also gdk_surface_set_event_compression() to get
|
||||
* more motion events delivered directly, independent of the windowing
|
||||
* system.
|
||||
*
|
||||
* Returns: %TRUE if the windowing system supports motion history and
|
||||
* at least one event was found.
|
||||
**/
|
||||
gboolean
|
||||
gdk_device_get_history (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
guint32 start,
|
||||
guint32 stop,
|
||||
GdkTimeCoord ***events,
|
||||
gint *n_events)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
|
||||
g_return_val_if_fail (device->source != GDK_SOURCE_KEYBOARD, FALSE);
|
||||
g_return_val_if_fail (GDK_IS_SURFACE (surface), FALSE);
|
||||
|
||||
if (n_events)
|
||||
*n_events = 0;
|
||||
|
||||
if (events)
|
||||
*events = NULL;
|
||||
|
||||
if (GDK_SURFACE_DESTROYED (surface))
|
||||
return FALSE;
|
||||
|
||||
if (!GDK_DEVICE_GET_CLASS (device)->get_history)
|
||||
return FALSE;
|
||||
|
||||
return GDK_DEVICE_GET_CLASS (device)->get_history (device, surface,
|
||||
start, stop,
|
||||
events, n_events);
|
||||
}
|
||||
|
||||
GdkTimeCoord **
|
||||
_gdk_device_allocate_history (GdkDevice *device,
|
||||
gint n_events)
|
||||
{
|
||||
GdkTimeCoord **result = g_new (GdkTimeCoord *, n_events);
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < n_events; i++)
|
||||
result[i] = g_malloc (sizeof (GdkTimeCoord) -
|
||||
sizeof (double) * (GDK_MAX_TIMECOORD_AXES - device->axes->len));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_free_history: (skip)
|
||||
* @events: (array length=n_events): an array of #GdkTimeCoord.
|
||||
* @n_events: the length of the array.
|
||||
*
|
||||
* Frees an array of #GdkTimeCoord that was returned by gdk_device_get_history().
|
||||
*/
|
||||
void
|
||||
gdk_device_free_history (GdkTimeCoord **events,
|
||||
gint n_events)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < n_events; i++)
|
||||
g_free (events[i]);
|
||||
|
||||
g_free (events);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_get_name:
|
||||
* @device: a #GdkDevice
|
||||
@@ -774,79 +672,6 @@ gdk_device_get_source (GdkDevice *device)
|
||||
return device->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_get_n_keys:
|
||||
* @device: a #GdkDevice
|
||||
*
|
||||
* Returns the number of keys the device currently has.
|
||||
*
|
||||
* Returns: the number of keys.
|
||||
**/
|
||||
gint
|
||||
gdk_device_get_n_keys (GdkDevice *device)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DEVICE (device), 0);
|
||||
|
||||
return device->num_keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_get_key:
|
||||
* @device: a #GdkDevice.
|
||||
* @index_: the index of the macro button to get.
|
||||
* @keyval: (out): return value for the keyval.
|
||||
* @modifiers: (out): return value for modifiers.
|
||||
*
|
||||
* If @index_ has a valid keyval, this function will return %TRUE
|
||||
* and fill in @keyval and @modifiers with the keyval settings.
|
||||
*
|
||||
* Returns: %TRUE if keyval is set for @index.
|
||||
**/
|
||||
gboolean
|
||||
gdk_device_get_key (GdkDevice *device,
|
||||
guint index_,
|
||||
guint *keyval,
|
||||
GdkModifierType *modifiers)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
|
||||
g_return_val_if_fail (index_ < device->num_keys, FALSE);
|
||||
|
||||
if (!device->keys[index_].keyval &&
|
||||
!device->keys[index_].modifiers)
|
||||
return FALSE;
|
||||
|
||||
if (keyval)
|
||||
*keyval = device->keys[index_].keyval;
|
||||
|
||||
if (modifiers)
|
||||
*modifiers = device->keys[index_].modifiers;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_set_key:
|
||||
* @device: a #GdkDevice
|
||||
* @index_: the index of the macro button to set
|
||||
* @keyval: the keyval to generate
|
||||
* @modifiers: the modifiers to set
|
||||
*
|
||||
* Specifies the X key event to generate when a macro button of a device
|
||||
* is pressed.
|
||||
**/
|
||||
void
|
||||
gdk_device_set_key (GdkDevice *device,
|
||||
guint index_,
|
||||
guint keyval,
|
||||
GdkModifierType modifiers)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DEVICE (device));
|
||||
g_return_if_fail (index_ < device->num_keys);
|
||||
|
||||
device->keys[index_].keyval = keyval;
|
||||
device->keys[index_].modifiers = modifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_get_axis_use:
|
||||
* @device: a pointer #GdkDevice.
|
||||
@@ -871,47 +696,6 @@ gdk_device_get_axis_use (GdkDevice *device,
|
||||
return info->use;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_set_axis_use:
|
||||
* @device: a pointer #GdkDevice
|
||||
* @index_: the index of the axis
|
||||
* @use: specifies how the axis is used
|
||||
*
|
||||
* Specifies how an axis of a device is used.
|
||||
**/
|
||||
void
|
||||
gdk_device_set_axis_use (GdkDevice *device,
|
||||
guint index_,
|
||||
GdkAxisUse use)
|
||||
{
|
||||
GdkAxisInfo *info;
|
||||
|
||||
g_return_if_fail (GDK_IS_DEVICE (device));
|
||||
g_return_if_fail (device->source != GDK_SOURCE_KEYBOARD);
|
||||
g_return_if_fail (index_ < device->axes->len);
|
||||
|
||||
info = &g_array_index (device->axes, GdkAxisInfo, index_);
|
||||
info->use = use;
|
||||
|
||||
switch ((guint) use)
|
||||
{
|
||||
case GDK_AXIS_X:
|
||||
case GDK_AXIS_Y:
|
||||
info->min_axis = 0;
|
||||
info->max_axis = 0;
|
||||
break;
|
||||
case GDK_AXIS_XTILT:
|
||||
case GDK_AXIS_YTILT:
|
||||
info->min_axis = -1;
|
||||
info->max_axis = 1;
|
||||
break;
|
||||
default:
|
||||
info->min_axis = 0;
|
||||
info->max_axis = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_get_display:
|
||||
* @device: a #GdkDevice
|
||||
@@ -1077,89 +861,6 @@ gdk_device_get_n_axes (GdkDevice *device)
|
||||
return device->axes->len;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_get_axis_names:
|
||||
* @device: a #GdkDevice
|
||||
*
|
||||
* Returns a null-terminated array of strings, containing the labels for
|
||||
* the axes that @device currently has.
|
||||
* If the device has no axes, %NULL is returned.
|
||||
*
|
||||
* Returns: (nullable) (transfer full): A null-terminated string array,
|
||||
* free with g_strfreev().
|
||||
**/
|
||||
char **
|
||||
gdk_device_get_axis_names (GdkDevice *device)
|
||||
{
|
||||
GPtrArray *axes;
|
||||
gint i;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
|
||||
g_return_val_if_fail (device->source != GDK_SOURCE_KEYBOARD, NULL);
|
||||
|
||||
if (device->axes->len == 0)
|
||||
return NULL;
|
||||
|
||||
axes = g_ptr_array_new ();
|
||||
|
||||
for (i = 0; i < device->axes->len; i++)
|
||||
{
|
||||
GdkAxisInfo axis_info;
|
||||
|
||||
axis_info = g_array_index (device->axes, GdkAxisInfo, i);
|
||||
g_ptr_array_add (axes, g_strdup (axis_info.label));
|
||||
}
|
||||
|
||||
g_ptr_array_add (axes, NULL);
|
||||
|
||||
return (char **) g_ptr_array_free (axes, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_get_axis_value: (skip)
|
||||
* @device: a pointer #GdkDevice.
|
||||
* @axes: (array): pointer to an array of axes
|
||||
* @axis_label: name of the label
|
||||
* @value: (out): location to store the found value.
|
||||
*
|
||||
* Interprets an array of double as axis values for a given device,
|
||||
* and locates the value in the array for a given axis label, as returned
|
||||
* by gdk_device_get_axes()
|
||||
*
|
||||
* Returns: %TRUE if the given axis use was found, otherwise %FALSE.
|
||||
**/
|
||||
gboolean
|
||||
gdk_device_get_axis_value (GdkDevice *device,
|
||||
gdouble *axes,
|
||||
const char *axis_label,
|
||||
gdouble *value)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
|
||||
g_return_val_if_fail (device->source != GDK_SOURCE_KEYBOARD, FALSE);
|
||||
|
||||
if (axes == NULL)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < device->axes->len; i++)
|
||||
{
|
||||
GdkAxisInfo axis_info;
|
||||
|
||||
axis_info = g_array_index (device->axes, GdkAxisInfo, i);
|
||||
|
||||
if (!g_str_equal (axis_info.label, axis_label))
|
||||
continue;
|
||||
|
||||
if (value)
|
||||
*value = axes[i];
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_get_axis: (skip)
|
||||
* @device: a #GdkDevice
|
||||
@@ -1296,7 +997,6 @@ _gdk_device_reset_axes (GdkDevice *device)
|
||||
|
||||
guint
|
||||
_gdk_device_add_axis (GdkDevice *device,
|
||||
const char *label_name,
|
||||
GdkAxisUse use,
|
||||
gdouble min_value,
|
||||
gdouble max_value,
|
||||
@@ -1306,7 +1006,6 @@ _gdk_device_add_axis (GdkDevice *device,
|
||||
guint pos;
|
||||
|
||||
axis_info.use = use;
|
||||
axis_info.label = g_strdup (label_name);
|
||||
axis_info.min_value = min_value;
|
||||
axis_info.max_value = max_value;
|
||||
axis_info.resolution = resolution;
|
||||
@@ -1342,12 +1041,11 @@ _gdk_device_add_axis (GdkDevice *device,
|
||||
|
||||
void
|
||||
_gdk_device_get_axis_info (GdkDevice *device,
|
||||
guint index_,
|
||||
const char **label_name,
|
||||
GdkAxisUse *use,
|
||||
gdouble *min_value,
|
||||
gdouble *max_value,
|
||||
gdouble *resolution)
|
||||
guint index_,
|
||||
GdkAxisUse *use,
|
||||
gdouble *min_value,
|
||||
gdouble *max_value,
|
||||
gdouble *resolution)
|
||||
{
|
||||
GdkAxisInfo *info;
|
||||
|
||||
@@ -1356,23 +1054,12 @@ _gdk_device_get_axis_info (GdkDevice *device,
|
||||
|
||||
info = &g_array_index (device->axes, GdkAxisInfo, index_);
|
||||
|
||||
*label_name = info->label;
|
||||
*use = info->use;
|
||||
*min_value = info->min_value;
|
||||
*max_value = info->max_value;
|
||||
*resolution = info->resolution;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_device_set_keys (GdkDevice *device,
|
||||
guint num_keys)
|
||||
{
|
||||
g_free (device->keys);
|
||||
|
||||
device->num_keys = num_keys;
|
||||
device->keys = g_new0 (GdkDeviceKey, num_keys);
|
||||
}
|
||||
|
||||
static GdkAxisInfo *
|
||||
find_axis_info (GArray *array,
|
||||
GdkAxisUse use)
|
||||
@@ -1393,10 +1080,10 @@ find_axis_info (GArray *array,
|
||||
|
||||
gboolean
|
||||
_gdk_device_translate_surface_coord (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
guint index_,
|
||||
gdouble value,
|
||||
gdouble *axis_value)
|
||||
GdkSurface *surface,
|
||||
guint index_,
|
||||
gdouble value,
|
||||
gdouble *axis_value)
|
||||
{
|
||||
GdkAxisInfo axis_info;
|
||||
GdkAxisInfo *axis_info_x, *axis_info_y;
|
||||
@@ -1778,6 +1465,15 @@ gdk_device_get_device_tool (GdkDevice *device)
|
||||
return device->last_tool;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_get_caps_lock_state:
|
||||
* @device: a #GdkDevice
|
||||
*
|
||||
* Retrieves whether the Caps Lock modifier of the
|
||||
* keyboard is locked, if @device is a keyboard device.
|
||||
*
|
||||
* Returns: %TRUE if Caps Lock is on for @device
|
||||
*/
|
||||
gboolean
|
||||
gdk_device_get_caps_lock_state (GdkDevice *device)
|
||||
{
|
||||
@@ -1789,6 +1485,15 @@ gdk_device_get_caps_lock_state (GdkDevice *device)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_get_num_lock_state:
|
||||
* @device: a #GdkDevice
|
||||
*
|
||||
* Retrieves whether the Num Lock modifier of the
|
||||
* keyboard is locked, if @device is a keyboard device.
|
||||
*
|
||||
* Returns: %TRUE if Num Lock is on for @device
|
||||
*/
|
||||
gboolean
|
||||
gdk_device_get_num_lock_state (GdkDevice *device)
|
||||
{
|
||||
@@ -1800,6 +1505,15 @@ gdk_device_get_num_lock_state (GdkDevice *device)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_get_scroll_lock_state:
|
||||
* @device: a #GdkDevice
|
||||
*
|
||||
* Retrieves whether the Scroll Lock modifier of the
|
||||
* keyboard is locked, if @device is a keyboard device.
|
||||
*
|
||||
* Returns: %TRUE if Scroll Lock is on for @device
|
||||
*/
|
||||
gboolean
|
||||
gdk_device_get_scroll_lock_state (GdkDevice *device)
|
||||
{
|
||||
@@ -1811,6 +1525,15 @@ gdk_device_get_scroll_lock_state (GdkDevice *device)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_get_modifier_state:
|
||||
* @device: a #GdkDevice
|
||||
*
|
||||
* Retrieves the current modifier state of the keyboard,
|
||||
* if @device is a keyboard device.
|
||||
*
|
||||
* Returns: the current modifier state
|
||||
*/
|
||||
GdkModifierType
|
||||
gdk_device_get_modifier_state (GdkDevice *device)
|
||||
{
|
||||
@@ -1822,6 +1545,20 @@ gdk_device_get_modifier_state (GdkDevice *device)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_get_direction:
|
||||
* @device: a #GdkDevice
|
||||
*
|
||||
* Returns the direction of effective layout of the keyboard,
|
||||
* if @device is a keyboard device.
|
||||
*
|
||||
* The direction of a layout is the direction of the majority
|
||||
* of its symbols. See pango_unichar_direction().
|
||||
*
|
||||
* Returns: %PANGO_DIRECTION_LTR or %PANGO_DIRECTION_RTL
|
||||
* if it can determine the direction. %PANGO_DIRECTION_NEUTRAL
|
||||
* otherwise
|
||||
*/
|
||||
PangoDirection
|
||||
gdk_device_get_direction (GdkDevice *device)
|
||||
{
|
||||
@@ -1833,6 +1570,17 @@ gdk_device_get_direction (GdkDevice *device)
|
||||
return PANGO_DIRECTION_NEUTRAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_has_bidi_layouts:
|
||||
* @device: a #GdkDevice
|
||||
*
|
||||
* Determines if keyboard layouts for both right-to-left and
|
||||
* left-to-right languages are in use on the keyboard, if
|
||||
* @device is a keyboard device.
|
||||
*
|
||||
* Returns: %TRUE if there are layouts with both directions,
|
||||
* %FALSE otherwise
|
||||
*/
|
||||
gboolean
|
||||
gdk_device_has_bidi_layouts (GdkDevice *device)
|
||||
{
|
||||
|
||||
@@ -85,22 +85,20 @@ typedef enum {
|
||||
GDK_DEVICE_TYPE_FLOATING
|
||||
} GdkDeviceType;
|
||||
|
||||
/* We don't allocate each coordinate this big, but we use it to
|
||||
* be ANSI compliant and avoid accessing past the defined limits.
|
||||
*/
|
||||
#define GDK_MAX_TIMECOORD_AXES 128
|
||||
|
||||
/**
|
||||
* GdkTimeCoord:
|
||||
* @time: The timestamp for this event.
|
||||
* @axes: the values of the device’s axes.
|
||||
* @flags: Flags indicating what axes are present
|
||||
* @axes: axis values
|
||||
*
|
||||
* A #GdkTimeCoord stores a single event in a motion history.
|
||||
*/
|
||||
struct _GdkTimeCoord
|
||||
{
|
||||
guint32 time;
|
||||
gdouble axes[GDK_MAX_TIMECOORD_AXES];
|
||||
GdkAxisFlags flags;
|
||||
double axes[GDK_AXIS_LAST];
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
@@ -115,26 +113,9 @@ gboolean gdk_device_get_has_cursor (GdkDevice *device);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkInputSource gdk_device_get_source (GdkDevice *device);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gint gdk_device_get_n_keys (GdkDevice *device);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_device_get_key (GdkDevice *device,
|
||||
guint index_,
|
||||
guint *keyval,
|
||||
GdkModifierType *modifiers);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_device_set_key (GdkDevice *device,
|
||||
guint index_,
|
||||
guint keyval,
|
||||
GdkModifierType modifiers);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkAxisUse gdk_device_get_axis_use (GdkDevice *device,
|
||||
guint index_);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_device_set_axis_use (GdkDevice *device,
|
||||
guint index_,
|
||||
GdkAxisUse use);
|
||||
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
@@ -146,25 +127,12 @@ GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface * gdk_device_get_surface_at_position (GdkDevice *device,
|
||||
double *win_x,
|
||||
double *win_y);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_device_get_history (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
guint32 start,
|
||||
guint32 stop,
|
||||
GdkTimeCoord ***events,
|
||||
gint *n_events);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_device_free_history (GdkTimeCoord **events,
|
||||
gint n_events);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gint gdk_device_get_n_axes (GdkDevice *device);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
char ** gdk_device_get_axis_names (GdkDevice *device);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_device_get_axis_value (GdkDevice *device,
|
||||
gdouble *axes,
|
||||
const char *axis_label,
|
||||
gdouble *value);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
||||
@@ -31,13 +31,6 @@ G_BEGIN_DECLS
|
||||
#define GDK_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE, GdkDeviceClass))
|
||||
|
||||
typedef struct _GdkDeviceClass GdkDeviceClass;
|
||||
typedef struct _GdkDeviceKey GdkDeviceKey;
|
||||
|
||||
struct _GdkDeviceKey
|
||||
{
|
||||
guint keyval;
|
||||
GdkModifierType modifiers;
|
||||
};
|
||||
|
||||
struct _GdkDevice
|
||||
{
|
||||
@@ -46,9 +39,7 @@ struct _GdkDevice
|
||||
gchar *name;
|
||||
GdkInputSource source;
|
||||
gboolean has_cursor;
|
||||
gint num_keys;
|
||||
GdkAxisFlags axis_flags;
|
||||
GdkDeviceKey *keys;
|
||||
GdkDisplay *display;
|
||||
/* Paired master for master,
|
||||
* associated master for slaves
|
||||
@@ -70,13 +61,6 @@ struct _GdkDeviceClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
gboolean (* get_history) (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
guint32 start,
|
||||
guint32 stop,
|
||||
GdkTimeCoord ***events,
|
||||
gint *n_events);
|
||||
|
||||
void (* get_state) (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
gdouble *axes,
|
||||
@@ -113,21 +97,16 @@ void _gdk_device_set_associated_device (GdkDevice *device,
|
||||
|
||||
void _gdk_device_reset_axes (GdkDevice *device);
|
||||
guint _gdk_device_add_axis (GdkDevice *device,
|
||||
const char *label_atom,
|
||||
GdkAxisUse use,
|
||||
gdouble min_value,
|
||||
gdouble max_value,
|
||||
gdouble resolution);
|
||||
void _gdk_device_get_axis_info (GdkDevice *device,
|
||||
guint index,
|
||||
const char**label_atom,
|
||||
GdkAxisUse *use,
|
||||
gdouble *min_value,
|
||||
gdouble *max_value,
|
||||
gdouble *resolution);
|
||||
|
||||
void _gdk_device_set_keys (GdkDevice *device,
|
||||
guint num_keys);
|
||||
guint index,
|
||||
GdkAxisUse *use,
|
||||
gdouble *min_value,
|
||||
gdouble *max_value,
|
||||
gdouble *resolution);
|
||||
|
||||
gboolean _gdk_device_translate_surface_coord (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
|
||||
@@ -38,9 +38,6 @@
|
||||
#include <math.h>
|
||||
#include <glib.h>
|
||||
|
||||
/* for the use of round() */
|
||||
#include "fallback-c89.c"
|
||||
|
||||
/**
|
||||
* SECTION:gdkdisplay
|
||||
* @Short_description: Controls a set of monitors and their associated input devices
|
||||
@@ -1735,11 +1732,11 @@ gdk_display_map_keycode (GdkDisplay *display,
|
||||
* @keycode: a keycode
|
||||
* @state: a modifier state
|
||||
* @group: active keyboard group
|
||||
* @keyval: (out) (allow-none): return location for keyval, or %NULL
|
||||
* @effective_group: (out) (allow-none): return location for effective
|
||||
* @keyval: (out) (optional): return location for keyval, or %NULL
|
||||
* @effective_group: (out) (optional): return location for effective
|
||||
* group, or %NULL
|
||||
* @level: (out) (allow-none): return location for level, or %NULL
|
||||
* @consumed_modifiers: (out) (allow-none): return location for modifiers
|
||||
* @level: (out) (optional): return location for level, or %NULL
|
||||
* @consumed: (out) (optional): return location for modifiers
|
||||
* that were used to determine the group or level, or %NULL
|
||||
*
|
||||
* Translates the contents of a #GdkEventKey (ie @keycode, @state, and @group)
|
||||
|
||||
194
gdk/gdkevents.c
194
gdk/gdkevents.c
@@ -619,6 +619,114 @@ _gdk_event_unqueue (GdkDisplay *display)
|
||||
return event;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the last N events in the event queue are smooth scroll events
|
||||
* for the same surface and device, combine them into one.
|
||||
*/
|
||||
void
|
||||
gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
|
||||
{
|
||||
GList *l;
|
||||
GdkSurface *surface = NULL;
|
||||
GdkDevice *device = NULL;
|
||||
GdkEvent *last_event = NULL;
|
||||
GList *scrolls = NULL;
|
||||
double delta_x, delta_y;
|
||||
GArray *history = NULL;
|
||||
GdkTimeCoord hist;
|
||||
|
||||
l = g_queue_peek_tail_link (&display->queued_events);
|
||||
|
||||
while (l)
|
||||
{
|
||||
GdkEvent *event = l->data;
|
||||
|
||||
if (event->flags & GDK_EVENT_PENDING)
|
||||
break;
|
||||
|
||||
if (event->event_type != GDK_SCROLL ||
|
||||
gdk_scroll_event_get_direction (event) != GDK_SCROLL_SMOOTH)
|
||||
break;
|
||||
|
||||
if (surface != NULL &&
|
||||
surface != event->surface)
|
||||
break;
|
||||
|
||||
if (device != NULL &&
|
||||
device != event->device)
|
||||
break;
|
||||
|
||||
if (!last_event)
|
||||
last_event = event;
|
||||
|
||||
surface = event->surface;
|
||||
device = event->device;
|
||||
scrolls = l;
|
||||
|
||||
l = l->prev;
|
||||
}
|
||||
|
||||
delta_x = delta_y = 0;
|
||||
|
||||
while (scrolls && scrolls->next != NULL)
|
||||
{
|
||||
GdkEvent *event = scrolls->data;
|
||||
GList *next = scrolls->next;
|
||||
double dx, dy;
|
||||
|
||||
if (!history)
|
||||
history = g_array_new (FALSE, TRUE, sizeof (GdkTimeCoord));
|
||||
|
||||
gdk_scroll_event_get_deltas (event, &dx, &dy);
|
||||
delta_x += dx;
|
||||
delta_y += dy;
|
||||
|
||||
memset (&hist, 0, sizeof (GdkTimeCoord));
|
||||
hist.time = gdk_event_get_time (event);
|
||||
hist.flags = GDK_AXIS_FLAG_DELTA_X | GDK_AXIS_FLAG_DELTA_Y;
|
||||
hist.axes[GDK_AXIS_DELTA_X] = dx;
|
||||
hist.axes[GDK_AXIS_DELTA_Y] = dy;
|
||||
|
||||
g_array_append_val (history, hist);
|
||||
|
||||
gdk_event_unref (event);
|
||||
g_queue_delete_link (&display->queued_events, scrolls);
|
||||
scrolls = next;
|
||||
}
|
||||
|
||||
if (scrolls)
|
||||
{
|
||||
GdkEvent *old_event, *event;
|
||||
double dx, dy;
|
||||
|
||||
old_event = scrolls->data;
|
||||
|
||||
gdk_scroll_event_get_deltas (old_event, &dx, &dy);
|
||||
event = gdk_scroll_event_new (surface,
|
||||
device,
|
||||
gdk_event_get_source_device (old_event),
|
||||
gdk_event_get_device_tool (old_event),
|
||||
gdk_event_get_time (old_event),
|
||||
gdk_event_get_modifier_state (old_event),
|
||||
delta_x + dx,
|
||||
delta_y + dy,
|
||||
gdk_scroll_event_is_stop (old_event));
|
||||
|
||||
((GdkScrollEvent *)event)->history = history;
|
||||
|
||||
g_queue_delete_link (&display->queued_events, scrolls);
|
||||
g_queue_push_tail (&display->queued_events, event);
|
||||
}
|
||||
|
||||
if (g_queue_get_length (&display->queued_events) == 1 &&
|
||||
g_queue_peek_head_link (&display->queued_events) == scrolls)
|
||||
{
|
||||
GdkFrameClock *clock = gdk_surface_get_frame_clock (surface);
|
||||
if (clock) /* might be NULL if surface was destroyed */
|
||||
gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_motion_event_push_history (GdkEvent *event,
|
||||
GdkEvent *history_event)
|
||||
@@ -634,14 +742,20 @@ gdk_motion_event_push_history (GdkEvent *event,
|
||||
device = gdk_event_get_device (history_event);
|
||||
n_axes = gdk_device_get_n_axes (device);
|
||||
|
||||
for (i = 0; i <= MIN (n_axes, GDK_MAX_TIMECOORD_AXES); i++)
|
||||
gdk_event_get_axis (history_event, i, &hist.axes[i]);
|
||||
memset (&hist, 0, sizeof (GdkTimeCoord));
|
||||
hist.time = gdk_event_get_time (history_event);
|
||||
hist.flags = gdk_device_get_axes (device);
|
||||
|
||||
for (i = 0; i < n_axes; i++)
|
||||
{
|
||||
GdkAxisUse use = gdk_device_get_axis_use (device, i);
|
||||
gdk_event_get_axis (history_event, use, &hist.axes[use]);
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (!self->history))
|
||||
self->history = g_array_new (FALSE, TRUE, sizeof (GdkTimeCoord));
|
||||
|
||||
g_array_append_val (self->history, hist);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@@ -710,7 +824,7 @@ _gdk_event_queue_handle_motion_compression (GdkDisplay *display)
|
||||
{
|
||||
GdkFrameClock *clock = gdk_surface_get_frame_clock (pending_motion_surface);
|
||||
if (clock) /* might be NULL if surface was destroyed */
|
||||
gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS);
|
||||
gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2130,7 +2244,7 @@ gdk_focus_event_new (GdkSurface *surface,
|
||||
|
||||
/**
|
||||
* gdk_focus_event_get_in:
|
||||
* @event: (type GdkScrollEvent): a focus change event
|
||||
* @event: (type GdkFocusEvent): a focus change event
|
||||
*
|
||||
* Extracts whether this event is about focus entering or
|
||||
* leaving the surface.
|
||||
@@ -2152,21 +2266,14 @@ gdk_focus_event_get_in (GdkEvent *event)
|
||||
|
||||
/* {{{ GdkScrollEvent */
|
||||
|
||||
static void
|
||||
gdk_scroll_event_init (GdkEvent *event)
|
||||
{
|
||||
GdkScrollEvent *self = (GdkScrollEvent *) event;
|
||||
|
||||
self->x = NAN;
|
||||
self->y = NAN;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_scroll_event_finalize (GdkEvent *event)
|
||||
{
|
||||
GdkScrollEvent *self = (GdkScrollEvent *) event;
|
||||
|
||||
g_clear_object (&self->tool);
|
||||
if (self->history)
|
||||
g_array_free (self->history, TRUE);
|
||||
|
||||
GDK_EVENT_SUPER (self)->finalize (event);
|
||||
}
|
||||
@@ -2179,19 +2286,6 @@ gdk_scroll_event_get_state (GdkEvent *event)
|
||||
return self->state;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_scroll_event_get_position (GdkEvent *event,
|
||||
double *x,
|
||||
double *y)
|
||||
{
|
||||
GdkScrollEvent *self = (GdkScrollEvent *) event;
|
||||
|
||||
*x = self->x;
|
||||
*y = self->y;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GdkDeviceTool *
|
||||
gdk_scroll_event_get_tool (GdkEvent *event)
|
||||
{
|
||||
@@ -2202,10 +2296,10 @@ gdk_scroll_event_get_tool (GdkEvent *event)
|
||||
|
||||
static const GdkEventTypeInfo gdk_scroll_event_info = {
|
||||
sizeof (GdkScrollEvent),
|
||||
gdk_scroll_event_init,
|
||||
NULL,
|
||||
gdk_scroll_event_finalize,
|
||||
gdk_scroll_event_get_state,
|
||||
gdk_scroll_event_get_position,
|
||||
NULL,
|
||||
NULL,
|
||||
gdk_scroll_event_get_tool,
|
||||
NULL,
|
||||
@@ -2799,35 +2893,51 @@ gdk_motion_event_new (GdkSurface *surface,
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_motion_event_get_history:
|
||||
* @event: (type GdkMotionEvent): a motion #GdkEvent
|
||||
* gdk_event_get_history:
|
||||
* @event: a motion or scroll #GdkEvent
|
||||
* @out_n_coords: (out): Return location for the length of the returned array
|
||||
*
|
||||
* Retrieves the history of the @event motion, as a list of time and
|
||||
* coordinates.
|
||||
* Retrieves the history of the @event, as a list of time and coordinates.
|
||||
*
|
||||
* The history includes events that are not delivered to the application
|
||||
* because they occurred in the same frame as @event.
|
||||
*
|
||||
* Note that only motion and scroll events record history, and motion
|
||||
* events only if one of the mouse buttons is down.
|
||||
*
|
||||
* Returns: (transfer container) (array length=out_n_coords) (nullable): an
|
||||
* array of time and coordinates
|
||||
*/
|
||||
GdkTimeCoord *
|
||||
gdk_motion_event_get_history (GdkEvent *event,
|
||||
guint *out_n_coords)
|
||||
gdk_event_get_history (GdkEvent *event,
|
||||
guint *out_n_coords)
|
||||
{
|
||||
GdkMotionEvent *self = (GdkMotionEvent *) event;
|
||||
GArray *history;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_EVENT (event), NULL);
|
||||
g_return_val_if_fail (GDK_IS_EVENT_TYPE (event, GDK_MOTION_NOTIFY), NULL);
|
||||
g_return_val_if_fail (GDK_IS_EVENT_TYPE (event, GDK_MOTION_NOTIFY) ||
|
||||
GDK_IS_EVENT_TYPE (event, GDK_SCROLL), NULL);
|
||||
g_return_val_if_fail (out_n_coords != NULL, NULL);
|
||||
|
||||
if (self->history &&
|
||||
self->history->len > 0)
|
||||
if (GDK_IS_EVENT_TYPE (event, GDK_MOTION_NOTIFY))
|
||||
{
|
||||
GdkMotionEvent *self = (GdkMotionEvent *) event;
|
||||
history = self->history;
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkScrollEvent *self = (GdkScrollEvent *) event;
|
||||
history = self->history;
|
||||
}
|
||||
|
||||
if (history && history->len > 0)
|
||||
{
|
||||
GdkTimeCoord *result;
|
||||
|
||||
*out_n_coords = self->history->len;
|
||||
*out_n_coords = history->len;
|
||||
|
||||
result = g_malloc (sizeof (GdkTimeCoord) * self->history->len);
|
||||
memcpy (result, self->history->data, sizeof (GdkTimeCoord) * self->history->len);
|
||||
result = g_malloc (sizeof (GdkTimeCoord) * history->len);
|
||||
memcpy (result, history->data, sizeof (GdkTimeCoord) * history->len);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -378,6 +378,9 @@ gboolean gdk_event_get_axis (GdkEvent *event,
|
||||
GdkAxisUse axis_use,
|
||||
double *value);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkTimeCoord * gdk_event_get_history (GdkEvent *event,
|
||||
guint *out_n_coords);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_event_get_pointer_emulated (GdkEvent *event);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
@@ -392,6 +395,7 @@ GDK_AVAILABLE_IN_ALL
|
||||
void gdk_scroll_event_get_deltas (GdkEvent *event,
|
||||
double *delta_x,
|
||||
double *delta_y);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_scroll_event_is_stop (GdkEvent *event);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
@@ -470,9 +474,6 @@ gboolean gdk_grab_broken_event_get_implicit (GdkEvent *event)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_motion_event_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkTimeCoord * gdk_motion_event_get_history (GdkEvent *event,
|
||||
guint *out_n_coords);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_delete_event_get_type (void) G_GNUC_CONST;
|
||||
|
||||
@@ -211,6 +211,9 @@ struct _GdkTouchEvent
|
||||
* @pointer_emulated: whether the scroll event was the result of
|
||||
* a pointer emulation
|
||||
* @tool: a #GdkDeviceTool
|
||||
* @history: (element-type GdkScrollHistory): array of times and deltas
|
||||
* for other scroll events that were compressed before delivering the
|
||||
* current event
|
||||
*
|
||||
* Generated from button presses for the buttons 4 to 7. Wheel mice are
|
||||
* usually configured to generate button press events for buttons 4 and 5
|
||||
@@ -225,8 +228,6 @@ struct _GdkScrollEvent
|
||||
{
|
||||
GdkEvent parent_instance;
|
||||
|
||||
double x;
|
||||
double y;
|
||||
GdkModifierType state;
|
||||
GdkScrollDirection direction;
|
||||
double delta_x;
|
||||
@@ -234,6 +235,7 @@ struct _GdkScrollEvent
|
||||
gboolean pointer_emulated;
|
||||
gboolean is_stop;
|
||||
GdkDeviceTool *tool;
|
||||
GArray *history; /* <GdkScrollHistory> */
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -56,6 +56,7 @@ struct _GdkFrameClockIdlePrivate
|
||||
GdkFrameClockPhase phase;
|
||||
|
||||
guint in_paint_idle : 1;
|
||||
guint paint_is_thaw : 1;
|
||||
#ifdef G_OS_WIN32
|
||||
guint begin_period : 1;
|
||||
#endif
|
||||
@@ -162,7 +163,7 @@ gdk_frame_clock_idle_dispose (GObject *object)
|
||||
static gint64
|
||||
compute_smooth_frame_time (GdkFrameClock *clock,
|
||||
gint64 new_frame_time,
|
||||
gboolean new_frame_time_is_regular,
|
||||
gboolean new_frame_time_is_vsync_related,
|
||||
gint64 smoothed_frame_time_base,
|
||||
gint64 frame_interval)
|
||||
{
|
||||
@@ -204,13 +205,13 @@ compute_smooth_frame_time (GdkFrameClock *clock,
|
||||
* (current_error/frame_interval)*(current_error/frame_interval)*frame_interval
|
||||
* But this can be simplified as below.
|
||||
*
|
||||
* Note: We only do this correction if we're regularly animating (no
|
||||
* or low frame skip). If the last frame was a long time ago, or if
|
||||
* we're not doing this in the frame cycle this call was likely
|
||||
* triggered by an input event and new_frame_time is essentially
|
||||
* random and not tied to the presentation time.
|
||||
* Note: We only do this correction if the new frame is caused by a
|
||||
* thaw of the frame clock, so that we know the time is actually
|
||||
* related to the physical vblank. For frameclock cycles triggered
|
||||
* by other events we always step up in whole frames from the last
|
||||
* reported time.
|
||||
*/
|
||||
if (new_frame_time_is_regular)
|
||||
if (new_frame_time_is_vsync_related)
|
||||
{
|
||||
current_error = new_smoothed_time - new_frame_time;
|
||||
correction_magnitude = current_error * current_error / frame_interval; /* Note, this is always > 0 due to the square */
|
||||
@@ -236,7 +237,8 @@ gdk_frame_clock_idle_get_frame_time (GdkFrameClock *clock)
|
||||
|
||||
/* can't change frame time during a paint */
|
||||
if (priv->phase != GDK_FRAME_CLOCK_PHASE_NONE &&
|
||||
priv->phase != GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS)
|
||||
priv->phase != GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS &&
|
||||
(priv->phase != GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT || priv->in_paint_idle))
|
||||
return priv->smoothed_frame_time_base;
|
||||
|
||||
/* Outside a paint, pick something smoothed close to now */
|
||||
@@ -274,7 +276,8 @@ gdk_frame_clock_idle_get_frame_time (GdkFrameClock *clock)
|
||||
(priv)->updating_count > 0))
|
||||
|
||||
static void
|
||||
maybe_start_idle (GdkFrameClockIdle *clock_idle)
|
||||
maybe_start_idle (GdkFrameClockIdle *clock_idle,
|
||||
gboolean caused_by_thaw)
|
||||
{
|
||||
GdkFrameClockIdlePrivate *priv = clock_idle->priv;
|
||||
|
||||
@@ -302,6 +305,7 @@ maybe_start_idle (GdkFrameClockIdle *clock_idle)
|
||||
if (!priv->in_paint_idle &&
|
||||
priv->paint_idle_id == 0 && RUN_PAINT_IDLE (priv))
|
||||
{
|
||||
priv->paint_is_thaw = caused_by_thaw;
|
||||
priv->paint_idle_id = g_timeout_add_full (GDK_PRIORITY_REDRAW,
|
||||
min_interval,
|
||||
gdk_frame_clock_paint_idle,
|
||||
@@ -408,7 +412,6 @@ gdk_frame_clock_paint_idle (void *data)
|
||||
{
|
||||
gint64 frame_interval = FRAME_INTERVAL;
|
||||
GdkFrameTimings *prev_timings = gdk_frame_clock_get_current_timings (clock);
|
||||
gint64 old_frame_time = priv->frame_time;
|
||||
|
||||
if (prev_timings && prev_timings->refresh_interval)
|
||||
frame_interval = prev_timings->refresh_interval;
|
||||
@@ -423,11 +426,9 @@ gdk_frame_clock_paint_idle (void *data)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For long delays, cycle was probably caused by input event rather than animation */
|
||||
gboolean is_regular = priv->frame_time - old_frame_time < 4 * FRAME_INTERVAL;
|
||||
priv->smoothed_frame_time_base =
|
||||
compute_smooth_frame_time (clock, priv->frame_time,
|
||||
is_regular,
|
||||
priv->paint_is_thaw,
|
||||
priv->smoothed_frame_time_base,
|
||||
priv->smoothed_frame_time_period);
|
||||
priv->smoothed_frame_time_period = frame_interval;
|
||||
@@ -558,8 +559,8 @@ gdk_frame_clock_paint_idle (void *data)
|
||||
if (priv->freeze_count == 0)
|
||||
{
|
||||
priv->min_next_frame_time = compute_min_next_frame_time (clock_idle,
|
||||
priv->frame_time);
|
||||
maybe_start_idle (clock_idle);
|
||||
priv->smoothed_frame_time_base);
|
||||
maybe_start_idle (clock_idle, FALSE);
|
||||
}
|
||||
|
||||
if (priv->freeze_count == 0)
|
||||
@@ -579,7 +580,7 @@ gdk_frame_clock_idle_request_phase (GdkFrameClock *clock,
|
||||
GdkFrameClockIdlePrivate *priv = clock_idle->priv;
|
||||
|
||||
priv->requested |= phase;
|
||||
maybe_start_idle (clock_idle);
|
||||
maybe_start_idle (clock_idle, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -598,7 +599,7 @@ gdk_frame_clock_idle_begin_updating (GdkFrameClock *clock)
|
||||
#endif
|
||||
|
||||
priv->updating_count++;
|
||||
maybe_start_idle (clock_idle);
|
||||
maybe_start_idle (clock_idle, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -648,7 +649,7 @@ gdk_frame_clock_idle_thaw (GdkFrameClock *clock)
|
||||
priv->freeze_count--;
|
||||
if (priv->freeze_count == 0)
|
||||
{
|
||||
maybe_start_idle (clock_idle);
|
||||
maybe_start_idle (clock_idle, TRUE);
|
||||
/* If nothing is requested so we didn't start an idle, we need
|
||||
* to skip to the end of the state chain, since the idle won't
|
||||
* run and do it for us.
|
||||
|
||||
@@ -123,6 +123,7 @@ GList* _gdk_event_queue_append (GdkDisplay *display,
|
||||
GdkEvent *event);
|
||||
|
||||
void _gdk_event_queue_handle_motion_compression (GdkDisplay *display);
|
||||
void gdk_event_queue_handle_scroll_compression (GdkDisplay *display);
|
||||
void _gdk_event_queue_flush (GdkDisplay *display);
|
||||
|
||||
gboolean _gdk_cairo_surface_extents (cairo_surface_t *surface,
|
||||
|
||||
@@ -71,6 +71,8 @@ typedef enum
|
||||
|
||||
/**
|
||||
* GdkPopupLayout:
|
||||
*
|
||||
* Struct containing information for gdk_popup_present()
|
||||
*/
|
||||
typedef struct _GdkPopupLayout GdkPopupLayout;
|
||||
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "fallback-c89.c"
|
||||
|
||||
/**
|
||||
* SECTION:rgba_colors
|
||||
* @Short_description: RGBA colors
|
||||
|
||||
@@ -47,9 +47,6 @@
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
/* for the use of round() */
|
||||
#include "fallback-c89.c"
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
#include "wayland/gdkwayland.h"
|
||||
#endif
|
||||
@@ -2369,6 +2366,7 @@ _gdk_windowing_got_event (GdkDisplay *display,
|
||||
* candidate it queues up flushing the event queue.
|
||||
*/
|
||||
_gdk_event_queue_handle_motion_compression (display);
|
||||
gdk_event_queue_handle_scroll_compression (display);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,6 +31,8 @@ G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* GdkTopLevelLayout:
|
||||
*
|
||||
* Struct containing information for gdk_toplevel_present()
|
||||
*/
|
||||
typedef struct _GdkToplevelLayout GdkToplevelLayout;
|
||||
|
||||
|
||||
@@ -247,6 +247,8 @@ typedef enum {
|
||||
* @GDK_AXIS_IGNORE: the axis is ignored.
|
||||
* @GDK_AXIS_X: the axis is used as the x axis.
|
||||
* @GDK_AXIS_Y: the axis is used as the y axis.
|
||||
* @GDK_AXIS_DELTA_X: the axis is used as the scroll x delta
|
||||
* @GDK_AXIS_DELTA_Y: the axis is used as the scroll y delta
|
||||
* @GDK_AXIS_PRESSURE: the axis is used for pressure information.
|
||||
* @GDK_AXIS_XTILT: the axis is used for x tilt information.
|
||||
* @GDK_AXIS_YTILT: the axis is used for y tilt information.
|
||||
@@ -269,6 +271,8 @@ typedef enum
|
||||
GDK_AXIS_IGNORE,
|
||||
GDK_AXIS_X,
|
||||
GDK_AXIS_Y,
|
||||
GDK_AXIS_DELTA_X,
|
||||
GDK_AXIS_DELTA_Y,
|
||||
GDK_AXIS_PRESSURE,
|
||||
GDK_AXIS_XTILT,
|
||||
GDK_AXIS_YTILT,
|
||||
@@ -283,6 +287,8 @@ typedef enum
|
||||
* GdkAxisFlags:
|
||||
* @GDK_AXIS_FLAG_X: X axis is present
|
||||
* @GDK_AXIS_FLAG_Y: Y axis is present
|
||||
* @GDK_AXIS_FLAG_DELTA_X: Scroll X delta axis is present
|
||||
* @GDK_AXIS_FLAG_DELTA_Y: Scroll Y delta axis is present
|
||||
* @GDK_AXIS_FLAG_PRESSURE: Pressure axis is present
|
||||
* @GDK_AXIS_FLAG_XTILT: X tilt axis is present
|
||||
* @GDK_AXIS_FLAG_YTILT: Y tilt axis is present
|
||||
@@ -297,6 +303,8 @@ typedef enum
|
||||
{
|
||||
GDK_AXIS_FLAG_X = 1 << GDK_AXIS_X,
|
||||
GDK_AXIS_FLAG_Y = 1 << GDK_AXIS_Y,
|
||||
GDK_AXIS_FLAG_DELTA_X = 1 << GDK_AXIS_DELTA_X,
|
||||
GDK_AXIS_FLAG_DELTA_Y = 1 << GDK_AXIS_DELTA_Y,
|
||||
GDK_AXIS_FLAG_PRESSURE = 1 << GDK_AXIS_PRESSURE,
|
||||
GDK_AXIS_FLAG_XTILT = 1 << GDK_AXIS_XTILT,
|
||||
GDK_AXIS_FLAG_YTILT = 1 << GDK_AXIS_YTILT,
|
||||
|
||||
@@ -309,17 +309,6 @@ static void deliver_key_event (GdkWaylandSeat *seat,
|
||||
uint32_t state,
|
||||
gboolean from_key_repeat);
|
||||
|
||||
static gboolean
|
||||
gdk_wayland_device_get_history (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
guint32 start,
|
||||
guint32 stop,
|
||||
GdkTimeCoord ***events,
|
||||
gint *n_events)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_device_get_state (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
@@ -828,7 +817,6 @@ gdk_wayland_device_class_init (GdkWaylandDeviceClass *klass)
|
||||
{
|
||||
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
|
||||
|
||||
device_class->get_history = gdk_wayland_device_get_history;
|
||||
device_class->get_state = gdk_wayland_device_get_state;
|
||||
device_class->set_surface_cursor = gdk_wayland_device_set_surface_cursor;
|
||||
device_class->query_state = gdk_wayland_device_query_state;
|
||||
@@ -844,8 +832,8 @@ gdk_wayland_device_init (GdkWaylandDevice *device_core)
|
||||
|
||||
device = GDK_DEVICE (device_core);
|
||||
|
||||
_gdk_device_add_axis (device, NULL, GDK_AXIS_X, 0, 0, 1);
|
||||
_gdk_device_add_axis (device, NULL, GDK_AXIS_Y, 0, 0, 1);
|
||||
_gdk_device_add_axis (device, GDK_AXIS_X, 0, 0, 1);
|
||||
_gdk_device_add_axis (device, GDK_AXIS_Y, 0, 0, 1);
|
||||
}
|
||||
|
||||
static gint
|
||||
@@ -3398,42 +3386,42 @@ gdk_wayland_device_tablet_clone_tool_axes (GdkWaylandTabletData *tablet,
|
||||
g_object_freeze_notify (G_OBJECT (tablet->current_device));
|
||||
_gdk_device_reset_axes (tablet->current_device);
|
||||
|
||||
_gdk_device_add_axis (tablet->current_device, NULL, GDK_AXIS_X, 0, 0, 0);
|
||||
_gdk_device_add_axis (tablet->current_device, NULL, GDK_AXIS_Y, 0, 0, 0);
|
||||
_gdk_device_add_axis (tablet->current_device, GDK_AXIS_X, 0, 0, 0);
|
||||
_gdk_device_add_axis (tablet->current_device, GDK_AXIS_Y, 0, 0, 0);
|
||||
|
||||
if (tool->tool_axes & (GDK_AXIS_FLAG_XTILT | GDK_AXIS_FLAG_YTILT))
|
||||
{
|
||||
axis_pos = _gdk_device_add_axis (tablet->current_device, NULL,
|
||||
axis_pos = _gdk_device_add_axis (tablet->current_device,
|
||||
GDK_AXIS_XTILT, -90, 90, 0);
|
||||
tablet->axis_indices[GDK_AXIS_XTILT] = axis_pos;
|
||||
|
||||
axis_pos = _gdk_device_add_axis (tablet->current_device, NULL,
|
||||
axis_pos = _gdk_device_add_axis (tablet->current_device,
|
||||
GDK_AXIS_YTILT, -90, 90, 0);
|
||||
tablet->axis_indices[GDK_AXIS_YTILT] = axis_pos;
|
||||
}
|
||||
if (tool->tool_axes & GDK_AXIS_FLAG_DISTANCE)
|
||||
{
|
||||
axis_pos = _gdk_device_add_axis (tablet->current_device, NULL,
|
||||
axis_pos = _gdk_device_add_axis (tablet->current_device,
|
||||
GDK_AXIS_DISTANCE, 0, 65535, 0);
|
||||
tablet->axis_indices[GDK_AXIS_DISTANCE] = axis_pos;
|
||||
}
|
||||
if (tool->tool_axes & GDK_AXIS_FLAG_PRESSURE)
|
||||
{
|
||||
axis_pos = _gdk_device_add_axis (tablet->current_device, NULL,
|
||||
axis_pos = _gdk_device_add_axis (tablet->current_device,
|
||||
GDK_AXIS_PRESSURE, 0, 65535, 0);
|
||||
tablet->axis_indices[GDK_AXIS_PRESSURE] = axis_pos;
|
||||
}
|
||||
|
||||
if (tool->tool_axes & GDK_AXIS_FLAG_ROTATION)
|
||||
{
|
||||
axis_pos = _gdk_device_add_axis (tablet->current_device, NULL,
|
||||
axis_pos = _gdk_device_add_axis (tablet->current_device,
|
||||
GDK_AXIS_ROTATION, 0, 360, 0);
|
||||
tablet->axis_indices[GDK_AXIS_ROTATION] = axis_pos;
|
||||
}
|
||||
|
||||
if (tool->tool_axes & GDK_AXIS_FLAG_SLIDER)
|
||||
{
|
||||
axis_pos = _gdk_device_add_axis (tablet->current_device, NULL,
|
||||
axis_pos = _gdk_device_add_axis (tablet->current_device,
|
||||
GDK_AXIS_SLIDER, -65535, 65535, 0);
|
||||
tablet->axis_indices[GDK_AXIS_SLIDER] = axis_pos;
|
||||
}
|
||||
@@ -3452,7 +3440,6 @@ gdk_wayland_mimic_device_axes (GdkDevice *master,
|
||||
GdkDevice *slave)
|
||||
{
|
||||
gdouble axis_min, axis_max, axis_resolution;
|
||||
const char *axis_label;
|
||||
GdkAxisUse axis_use;
|
||||
gint axis_count;
|
||||
gint i;
|
||||
@@ -3463,9 +3450,9 @@ gdk_wayland_mimic_device_axes (GdkDevice *master,
|
||||
|
||||
for (i = 0; i < axis_count; i++)
|
||||
{
|
||||
_gdk_device_get_axis_info (slave, i, &axis_label, &axis_use, &axis_min,
|
||||
_gdk_device_get_axis_info (slave, i, &axis_use, &axis_min,
|
||||
&axis_max, &axis_resolution);
|
||||
_gdk_device_add_axis (master, axis_label, axis_use, axis_min,
|
||||
_gdk_device_add_axis (master, axis_use, axis_min,
|
||||
axis_max, axis_resolution);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fribidi.h>
|
||||
|
||||
#include "gdk.h"
|
||||
#include "gdkwayland.h"
|
||||
|
||||
@@ -32,11 +32,10 @@ G_DEFINE_TYPE (GdkDeviceVirtual, gdk_device_virtual, GDK_TYPE_DEVICE)
|
||||
|
||||
void
|
||||
_gdk_device_virtual_set_active (GdkDevice *device,
|
||||
GdkDevice *new_active)
|
||||
GdkDevice *new_active)
|
||||
{
|
||||
GdkDeviceVirtual *virtual = GDK_DEVICE_VIRTUAL (device);
|
||||
int n_axes, i;
|
||||
const char *label_atom;
|
||||
GdkAxisUse use;
|
||||
gdouble min_value, max_value, resolution;
|
||||
|
||||
@@ -50,31 +49,16 @@ _gdk_device_virtual_set_active (GdkDevice *device,
|
||||
_gdk_device_reset_axes (device);
|
||||
n_axes = gdk_device_get_n_axes (new_active);
|
||||
for (i = 0; i < n_axes; i++)
|
||||
{
|
||||
_gdk_device_get_axis_info (new_active, i,
|
||||
&label_atom, &use,
|
||||
&min_value, &max_value, &resolution);
|
||||
_gdk_device_add_axis (device,
|
||||
label_atom, use,
|
||||
min_value, max_value, resolution);
|
||||
}
|
||||
{
|
||||
_gdk_device_get_axis_info (new_active, i, &use,
|
||||
&min_value, &max_value, &resolution);
|
||||
_gdk_device_add_axis (device, use, min_value, max_value, resolution);
|
||||
}
|
||||
}
|
||||
|
||||
g_signal_emit_by_name (G_OBJECT (device), "changed");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_device_virtual_get_history (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
guint32 start,
|
||||
guint32 stop,
|
||||
GdkTimeCoord ***events,
|
||||
gint *n_events)
|
||||
{
|
||||
/* History is only per slave device */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_virtual_get_state (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
@@ -188,7 +172,6 @@ gdk_device_virtual_class_init (GdkDeviceVirtualClass *klass)
|
||||
{
|
||||
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
|
||||
|
||||
device_class->get_history = gdk_device_virtual_get_history;
|
||||
device_class->get_state = gdk_device_virtual_get_state;
|
||||
device_class->set_surface_cursor = gdk_device_virtual_set_surface_cursor;
|
||||
device_class->query_state = gdk_device_virtual_query_state;
|
||||
|
||||
@@ -29,17 +29,6 @@
|
||||
|
||||
G_DEFINE_TYPE (GdkDeviceWin32, gdk_device_win32, GDK_TYPE_DEVICE)
|
||||
|
||||
static gboolean
|
||||
gdk_device_win32_get_history (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
guint32 start,
|
||||
guint32 stop,
|
||||
GdkTimeCoord ***events,
|
||||
gint *n_events)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_win32_get_state (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
@@ -235,7 +224,6 @@ gdk_device_win32_class_init (GdkDeviceWin32Class *klass)
|
||||
{
|
||||
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
|
||||
|
||||
device_class->get_history = gdk_device_win32_get_history;
|
||||
device_class->get_state = gdk_device_win32_get_state;
|
||||
device_class->set_surface_cursor = gdk_device_win32_set_surface_cursor;
|
||||
device_class->query_state = gdk_device_win32_query_state;
|
||||
@@ -251,6 +239,6 @@ gdk_device_win32_init (GdkDeviceWin32 *device_win32)
|
||||
|
||||
device = GDK_DEVICE (device_win32);
|
||||
|
||||
_gdk_device_add_axis (device, NULL, GDK_AXIS_X, 0, 0, 1);
|
||||
_gdk_device_add_axis (device, NULL, GDK_AXIS_Y, 0, 0, 1);
|
||||
_gdk_device_add_axis (device, GDK_AXIS_X, 0, 0, 1);
|
||||
_gdk_device_add_axis (device, GDK_AXIS_Y, 0, 0, 1);
|
||||
}
|
||||
|
||||
@@ -28,17 +28,6 @@
|
||||
|
||||
G_DEFINE_TYPE (GdkDeviceWintab, gdk_device_wintab, GDK_TYPE_DEVICE)
|
||||
|
||||
static gboolean
|
||||
gdk_device_wintab_get_history (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
guint32 start,
|
||||
guint32 stop,
|
||||
GdkTimeCoord ***events,
|
||||
gint *n_events)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GdkModifierType
|
||||
get_current_mask (void)
|
||||
{
|
||||
@@ -267,7 +256,6 @@ gdk_device_wintab_class_init (GdkDeviceWintabClass *klass)
|
||||
{
|
||||
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
|
||||
|
||||
device_class->get_history = gdk_device_wintab_get_history;
|
||||
device_class->get_state = gdk_device_wintab_get_state;
|
||||
device_class->set_surface_cursor = gdk_device_wintab_set_surface_cursor;
|
||||
device_class->query_state = gdk_device_wintab_query_state;
|
||||
|
||||
@@ -577,7 +577,6 @@ wintab_init_check (GdkDeviceManagerWin32 *device_manager)
|
||||
if (device->pktdata & PK_X)
|
||||
{
|
||||
_gdk_device_add_axis (GDK_DEVICE (device),
|
||||
NULL,
|
||||
GDK_AXIS_X,
|
||||
axis_x.axMin,
|
||||
axis_x.axMax,
|
||||
@@ -588,7 +587,6 @@ wintab_init_check (GdkDeviceManagerWin32 *device_manager)
|
||||
if (device->pktdata & PK_Y)
|
||||
{
|
||||
_gdk_device_add_axis (GDK_DEVICE (device),
|
||||
NULL,
|
||||
GDK_AXIS_Y,
|
||||
axis_y.axMin,
|
||||
axis_y.axMax,
|
||||
@@ -600,7 +598,6 @@ wintab_init_check (GdkDeviceManagerWin32 *device_manager)
|
||||
if (device->pktdata & PK_NORMAL_PRESSURE)
|
||||
{
|
||||
_gdk_device_add_axis (GDK_DEVICE (device),
|
||||
NULL,
|
||||
GDK_AXIS_PRESSURE,
|
||||
axis_npressure.axMin,
|
||||
axis_npressure.axMax,
|
||||
@@ -617,14 +614,12 @@ wintab_init_check (GdkDeviceManagerWin32 *device_manager)
|
||||
* we convert to x and y tilt in the -1000..1000 range
|
||||
*/
|
||||
_gdk_device_add_axis (GDK_DEVICE (device),
|
||||
NULL,
|
||||
GDK_AXIS_XTILT,
|
||||
-1000,
|
||||
1000,
|
||||
1000);
|
||||
|
||||
_gdk_device_add_axis (GDK_DEVICE (device),
|
||||
NULL,
|
||||
GDK_AXIS_YTILT,
|
||||
-1000,
|
||||
1000,
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
#include <cairo-win32.h>
|
||||
#include <dwmapi.h>
|
||||
#include <math.h>
|
||||
#include "fallback-c89.c"
|
||||
|
||||
static void gdk_surface_win32_finalize (GObject *object);
|
||||
|
||||
|
||||
@@ -211,7 +211,6 @@ translate_valuator_class (GdkDisplay *display,
|
||||
static gboolean initialized = FALSE;
|
||||
static Atom label_atoms [GDK_AXIS_LAST] = { 0 };
|
||||
GdkAxisUse use = GDK_AXIS_IGNORE;
|
||||
const char *label;
|
||||
gint i;
|
||||
|
||||
if (!initialized)
|
||||
@@ -234,13 +233,18 @@ translate_valuator_class (GdkDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
if (valuator_label != None)
|
||||
label = gdk_x11_get_xatom_name_for_display (display, valuator_label);
|
||||
else
|
||||
label = NULL;
|
||||
_gdk_device_add_axis (device, use, min, max, resolution);
|
||||
GDK_DISPLAY_NOTE (display, INPUT,
|
||||
{
|
||||
const char *label;
|
||||
|
||||
_gdk_device_add_axis (device, label, use, min, max, resolution);
|
||||
GDK_DISPLAY_NOTE (display, INPUT, g_message ("\n\taxis: %s %s", label, use == GDK_AXIS_IGNORE ? "(ignored)" : "(used)"));
|
||||
if (valuator_label != None)
|
||||
label = gdk_x11_get_xatom_name_for_display (display, valuator_label);
|
||||
else
|
||||
label = NULL;
|
||||
|
||||
g_message ("\n\taxis: %s %s", label, use == GDK_AXIS_IGNORE ? "(ignored)" : "(used)");
|
||||
});
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -261,13 +265,7 @@ translate_device_classes (GdkDisplay *display,
|
||||
{
|
||||
case XIKeyClass:
|
||||
{
|
||||
XIKeyClassInfo *key_info = (XIKeyClassInfo *) class_info;
|
||||
gint j;
|
||||
|
||||
_gdk_device_set_keys (device, key_info->num_keycodes);
|
||||
|
||||
for (j = 0; j < key_info->num_keycodes; j++)
|
||||
gdk_device_set_key (device, j, key_info->keycodes[j], 0);
|
||||
/* Not used */
|
||||
}
|
||||
break;
|
||||
case XIValuatorClass:
|
||||
|
||||
@@ -1603,6 +1603,14 @@ gdk_x11_display_open (const gchar *display_name)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
display_x11->have_damage = FALSE;
|
||||
if (XDamageQueryExtension (display_x11->xdisplay,
|
||||
&display_x11->damage_event_base,
|
||||
&display_x11->damage_error_base))
|
||||
display_x11->have_damage = TRUE;
|
||||
#endif
|
||||
|
||||
display->clipboard = gdk_x11_clipboard_new (display, "CLIPBOARD");
|
||||
display->primary_clipboard = gdk_x11_clipboard_new (display, "PRIMARY");
|
||||
|
||||
|
||||
@@ -149,6 +149,13 @@ struct _GdkX11Display
|
||||
guint has_glx_multisample : 1;
|
||||
guint has_glx_visual_rating : 1;
|
||||
guint has_glx_create_es2_context : 1;
|
||||
guint has_async_glx_swap_buffers : 1;
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
gint damage_event_base;
|
||||
gint damage_error_base;
|
||||
guint have_damage;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _GdkX11DisplayClass
|
||||
|
||||
@@ -183,6 +183,22 @@ gdk_x11_gl_context_end_frame (GdkDrawContext *draw_context,
|
||||
|
||||
gdk_x11_surface_pre_damage (surface);
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
if (context_x11->xdamage != 0)
|
||||
{
|
||||
g_assert (context_x11->frame_fence == 0);
|
||||
|
||||
context_x11->frame_fence = glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
/* We consider the frame still getting painted until the GL operation is
|
||||
* finished, and the window gets damage reported from the X server.
|
||||
* It's only at this point the compositor can be sure it has full
|
||||
* access to the new updates.
|
||||
*/
|
||||
_gdk_x11_surface_set_frame_still_painting (surface, TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
glXSwapBuffers (dpy, drawable);
|
||||
|
||||
if (context_x11->do_frame_sync && info != NULL && display_x11->has_glx_video_sync)
|
||||
@@ -565,6 +581,81 @@ create_legacy_context (GdkDisplay *display,
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
static gboolean
|
||||
on_gl_surface_xevent (GdkGLContext *context,
|
||||
XEvent *xevent,
|
||||
GdkX11Display *display_x11)
|
||||
{
|
||||
GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context);
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
XDamageNotifyEvent *damage_xevent;
|
||||
|
||||
if (!context_x11->is_attached)
|
||||
return FALSE;
|
||||
|
||||
if (xevent->type != (display_x11->damage_event_base + XDamageNotify))
|
||||
return FALSE;
|
||||
|
||||
damage_xevent = (XDamageNotifyEvent *) xevent;
|
||||
|
||||
if (damage_xevent->damage != context_x11->xdamage)
|
||||
return FALSE;
|
||||
|
||||
if (context_x11->frame_fence)
|
||||
{
|
||||
GLenum wait_result;
|
||||
|
||||
wait_result = glClientWaitSync (context_x11->frame_fence, 0, 0);
|
||||
|
||||
switch (wait_result)
|
||||
{
|
||||
/* We assume that if the fence has been signaled, that this damage
|
||||
* event is the damage event that was triggered by the GL drawing
|
||||
* associated with the fence. That's, technically, not necessarly
|
||||
* always true. The X server could have generated damage for
|
||||
* an unrelated event (say the size of the window changing), at
|
||||
* just the right moment such that we're picking it up instead.
|
||||
*
|
||||
* We're choosing not to handle this edge case, but if it does ever
|
||||
* happen in the wild, it could lead to slight underdrawing by
|
||||
* the compositor for one frame. In the future, if we find out
|
||||
* this edge case is noticeable, we can compensate by copying the
|
||||
* painted region from gdk_x11_gl_context_end_frame and subtracting
|
||||
* damaged areas from the copy as they come in. Once the copied
|
||||
* region goes empty, we know that there won't be any underdraw,
|
||||
* and can mark painting has finished. It's not worth the added
|
||||
* complexity and resource usage to do this bookkeeping, however,
|
||||
* unless the problem is practically visible.
|
||||
*/
|
||||
case GL_ALREADY_SIGNALED:
|
||||
case GL_CONDITION_SATISFIED:
|
||||
case GL_WAIT_FAILED:
|
||||
if (wait_result == GL_WAIT_FAILED)
|
||||
g_warning ("failed to wait on GL fence associated with last swap buffers call");
|
||||
glDeleteSync (context_x11->frame_fence);
|
||||
context_x11->frame_fence = 0;
|
||||
_gdk_x11_surface_set_frame_still_painting (surface, FALSE);
|
||||
break;
|
||||
|
||||
/* We assume that if the fence hasn't been signaled, that this
|
||||
* damage event is not the damage event that was triggered by the
|
||||
* GL drawing associated with the fence. That's only true for
|
||||
* the Nvidia vendor driver. When using open source drivers, damage
|
||||
* is emitted immediately on swap buffers, before the fence ever
|
||||
* has a chance to signal.
|
||||
*/
|
||||
case GL_TIMEOUT_EXPIRED:
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
gdk_x11_gl_context_realize (GdkGLContext *context,
|
||||
GError **error)
|
||||
@@ -737,6 +828,24 @@ gdk_x11_gl_context_realize (GdkGLContext *context,
|
||||
context_x11->attached_drawable = info->glx_drawable ? info->glx_drawable : gdk_x11_surface_get_xid (surface);
|
||||
context_x11->unattached_drawable = info->dummy_glx ? info->dummy_glx : info->dummy_xwin;
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
if (display_x11->have_damage && display_x11->has_async_glx_swap_buffers)
|
||||
{
|
||||
gdk_x11_display_error_trap_push (display);
|
||||
context_x11->xdamage = XDamageCreate (dpy,
|
||||
gdk_x11_surface_get_xid (surface),
|
||||
XDamageReportRawRectangles);
|
||||
if (gdk_x11_display_error_trap_pop (display))
|
||||
context_x11->xdamage = 0;
|
||||
else
|
||||
g_signal_connect_object (G_OBJECT (display),
|
||||
"xevent",
|
||||
G_CALLBACK (on_gl_surface_xevent),
|
||||
context,
|
||||
G_CONNECT_SWAPPED);
|
||||
}
|
||||
#endif
|
||||
|
||||
context_x11->is_direct = glXIsDirect (dpy, context_x11->glx_context);
|
||||
|
||||
GDK_DISPLAY_NOTE (display, OPENGL,
|
||||
@@ -766,6 +875,10 @@ gdk_x11_gl_context_dispose (GObject *gobject)
|
||||
context_x11->glx_context = NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
context_x11->xdamage = 0;
|
||||
#endif
|
||||
|
||||
G_OBJECT_CLASS (gdk_x11_gl_context_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
@@ -841,6 +954,21 @@ gdk_x11_screen_init_gl (GdkX11Screen *screen)
|
||||
display_x11->has_glx_visual_rating =
|
||||
epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_visual_rating");
|
||||
|
||||
if (g_strcmp0 (glXGetClientString (dpy, GLX_VENDOR), "NVIDIA Corporation") == 0)
|
||||
{
|
||||
/* With the mesa based drivers, we can safely assume the compositor can
|
||||
* access the updated surface texture immediately after glXSwapBuffers is
|
||||
* run, because the kernel ensures there is an implicit synchronization
|
||||
* operation upon texture access. This is not true with the Nvidia vendor
|
||||
* driver. There is a window of time after glXSwapBuffers before other
|
||||
* processes can see the updated drawing. We need to take special care,
|
||||
* in that case, to defer telling the compositor our latest frame is
|
||||
* ready until after the GPU has completed all issued commands related
|
||||
* to the frame, and that the X server says the frame has been drawn.
|
||||
*/
|
||||
display_x11->has_async_glx_swap_buffers = TRUE;
|
||||
}
|
||||
|
||||
GDK_DISPLAY_NOTE (display, OPENGL,
|
||||
g_message ("GLX version %d.%d found\n"
|
||||
" - Vendor: %s\n"
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#endif
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
#include <epoxy/glx.h>
|
||||
|
||||
@@ -44,6 +48,11 @@ struct _GdkX11GLContext
|
||||
GLXDrawable attached_drawable;
|
||||
GLXDrawable unattached_drawable;
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
GLsync frame_fence;
|
||||
Damage xdamage;
|
||||
#endif
|
||||
|
||||
guint is_attached : 1;
|
||||
guint is_direct : 1;
|
||||
guint do_frame_sync : 1;
|
||||
|
||||
@@ -104,6 +104,11 @@ void _gdk_x11_surface_grab_check_unmap (GdkSurface *window,
|
||||
gulong serial);
|
||||
void _gdk_x11_surface_grab_check_destroy (GdkSurface *window);
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
void _gdk_x11_surface_set_frame_still_painting (GdkSurface *surface,
|
||||
gboolean painting);
|
||||
#endif
|
||||
|
||||
gboolean _gdk_x11_display_is_root_window (GdkDisplay *display,
|
||||
Window xroot_window);
|
||||
|
||||
|
||||
@@ -360,6 +360,77 @@ gdk_x11_surface_begin_frame (GdkSurface *surface,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
should_sync_frame_drawing (GdkSurface *surface)
|
||||
{
|
||||
GdkX11Surface *impl = GDK_X11_SURFACE (surface);
|
||||
|
||||
/* disabled client side */
|
||||
if (!impl->frame_sync_enabled)
|
||||
return FALSE;
|
||||
|
||||
/* disabled compositor side */
|
||||
if (!gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (surface),
|
||||
g_intern_static_string ("_NET_WM_FRAME_DRAWN")))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_counter_for_end_frame (GdkSurface *surface)
|
||||
{
|
||||
GdkX11Surface *impl = GDK_X11_SURFACE (surface);
|
||||
|
||||
g_assert (!impl->toplevel->in_frame);
|
||||
g_assert (impl->toplevel->extended_update_counter != None);
|
||||
g_assert ((impl->toplevel->current_counter_value % 2) == 0);
|
||||
|
||||
set_sync_counter (GDK_SURFACE_XDISPLAY (surface),
|
||||
impl->toplevel->extended_update_counter,
|
||||
impl->toplevel->current_counter_value);
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_sync_counter_for_end_frame (GdkSurface *surface)
|
||||
{
|
||||
GdkX11Surface *impl = GDK_X11_SURFACE (surface);
|
||||
gboolean frame_sync_negotiated = should_sync_frame_drawing (surface);
|
||||
gboolean frame_done_painting = !impl->toplevel->frame_pending;
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
frame_done_painting = !impl->toplevel->frame_still_painting && frame_sync_negotiated;
|
||||
#endif
|
||||
|
||||
if (!impl->toplevel->frame_pending)
|
||||
{
|
||||
if (!frame_sync_negotiated || frame_done_painting)
|
||||
sync_counter_for_end_frame (surface);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (frame_done_painting)
|
||||
sync_counter_for_end_frame (surface);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
void
|
||||
_gdk_x11_surface_set_frame_still_painting (GdkSurface *surface,
|
||||
gboolean painting)
|
||||
{
|
||||
GdkX11Surface *impl = GDK_X11_SURFACE (surface);
|
||||
|
||||
if (impl->toplevel->frame_still_painting == painting)
|
||||
return;
|
||||
|
||||
impl->toplevel->frame_still_painting = painting;
|
||||
|
||||
if (!impl->toplevel->frame_still_painting)
|
||||
maybe_sync_counter_for_end_frame (surface);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
gdk_x11_surface_end_frame (GdkSurface *surface)
|
||||
{
|
||||
@@ -405,13 +476,9 @@ gdk_x11_surface_end_frame (GdkSurface *surface)
|
||||
else
|
||||
impl->toplevel->current_counter_value += 1;
|
||||
|
||||
set_sync_counter(GDK_SURFACE_XDISPLAY (surface),
|
||||
impl->toplevel->extended_update_counter,
|
||||
impl->toplevel->current_counter_value);
|
||||
maybe_sync_counter_for_end_frame (surface);
|
||||
|
||||
if (impl->frame_sync_enabled &&
|
||||
gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (surface),
|
||||
g_intern_static_string ("_NET_WM_FRAME_DRAWN")))
|
||||
if (should_sync_frame_drawing (surface))
|
||||
{
|
||||
impl->toplevel->frame_pending = TRUE;
|
||||
gdk_surface_freeze_updates (surface);
|
||||
|
||||
@@ -124,6 +124,9 @@ struct _GdkToplevelX11
|
||||
|
||||
guint in_frame : 1;
|
||||
|
||||
/* If we're waiting for damage from the X server after painting a frame */
|
||||
guint frame_still_painting : 1;
|
||||
|
||||
/* If we're expecting a response from the compositor after painting a frame */
|
||||
guint frame_pending : 1;
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ gdk_x11_deps = [
|
||||
xext_dep,
|
||||
x11_dep,
|
||||
xcursor_dep,
|
||||
xdamage_dep,
|
||||
xfixes_dep,
|
||||
xcomposite_dep,
|
||||
xrandr_dep,
|
||||
|
||||
@@ -370,7 +370,7 @@ gsk_linear_gradient_node_get_n_color_stops (GskRenderNode *node)
|
||||
* @node: (type GskLinearGradientNode): a #GskRenderNode for a linear gradient
|
||||
* @n_stops: (out) (optional): the number of color stops in the returned array
|
||||
*
|
||||
* Retrievs the color stops in the gradient.
|
||||
* Retrieves the color stops in the gradient.
|
||||
*
|
||||
* Returns: (array length=n_stops): the color stops in the gradient
|
||||
*/
|
||||
@@ -555,6 +555,14 @@ gsk_border_node_diff (GskRenderNode *node1,
|
||||
gsk_render_node_diff_impossible (node1, node2, region);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_border_node_peek_outline:
|
||||
* @node: (type GskBorderNode): a #GskRenderNode for a border
|
||||
*
|
||||
* Retrieves the outline of the border.
|
||||
*
|
||||
* Returns: the outline of the border
|
||||
*/
|
||||
const GskRoundedRect *
|
||||
gsk_border_node_peek_outline (GskRenderNode *node)
|
||||
{
|
||||
@@ -563,6 +571,15 @@ gsk_border_node_peek_outline (GskRenderNode *node)
|
||||
return &self->outline;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_border_node_peek_widths:
|
||||
* @node: (type GskBorderNode): a #GskRenderNode for a border
|
||||
*
|
||||
* Retrieves the stroke widths of the border.
|
||||
*
|
||||
* Returns: (transfer none): an array of 4 floats for the top,
|
||||
* right, bottom and left stroke width of the border
|
||||
*/
|
||||
const float *
|
||||
gsk_border_node_peek_widths (GskRenderNode *node)
|
||||
{
|
||||
@@ -571,6 +588,15 @@ gsk_border_node_peek_widths (GskRenderNode *node)
|
||||
return self->border_width;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_border_node_peek_colors:
|
||||
* @node: (type GskBorderNode): a #GskRenderNode for a border
|
||||
*
|
||||
* Retrieves the colors of the border.
|
||||
*
|
||||
* Returns: (transfer none): an array of 4 #GdkRGBA structs
|
||||
* for the top, right, bottom and left color of the border
|
||||
*/
|
||||
const GdkRGBA *
|
||||
gsk_border_node_peek_colors (GskRenderNode *node)
|
||||
{
|
||||
@@ -3626,6 +3652,14 @@ gsk_text_node_has_color_glyphs (GskRenderNode *node)
|
||||
return self->has_color_glyphs;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_text_node_get_num_glyphs:
|
||||
* @node: (type GskTextNode): a text #GskRenderNode
|
||||
*
|
||||
* Retrieves the number of glyphs in the text node.
|
||||
*
|
||||
* Returns: the number of glyphs
|
||||
*/
|
||||
guint
|
||||
gsk_text_node_get_num_glyphs (GskRenderNode *node)
|
||||
{
|
||||
|
||||
@@ -171,37 +171,30 @@ gtk_button_accessible_ref_state_set (AtkObject *obj)
|
||||
return state_set;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_button_accessible_notify_gtk (GObject *obj,
|
||||
GParamSpec *pspec)
|
||||
void
|
||||
gtk_button_accessible_update_label (GtkButtonAccessible *self)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (obj);
|
||||
AtkObject *atk_obj = gtk_widget_get_accessible (widget);
|
||||
g_return_if_fail (GTK_IS_BUTTON_ACCESSIBLE (self));
|
||||
|
||||
if (strcmp (pspec->name, "label") == 0)
|
||||
{
|
||||
if (atk_obj->name == NULL)
|
||||
g_object_notify (G_OBJECT (atk_obj), "accessible-name");
|
||||
/* If we don't have an overridden name, we use the label as the
|
||||
* accessible name
|
||||
*/
|
||||
if (atk_object_get_name (ATK_OBJECT (self)) == NULL)
|
||||
g_object_notify (G_OBJECT (self), "accessible-name");
|
||||
|
||||
g_signal_emit_by_name (atk_obj, "visible-data-changed");
|
||||
}
|
||||
else
|
||||
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_button_accessible_parent_class)->notify_gtk (obj, pspec);
|
||||
g_signal_emit_by_name (self, "visible-data-changed");
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_button_accessible_class_init (GtkButtonAccessibleClass *klass)
|
||||
{
|
||||
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
||||
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
|
||||
|
||||
class->get_name = gtk_button_accessible_get_name;
|
||||
class->get_n_children = gtk_button_accessible_get_n_children;
|
||||
class->ref_child = gtk_button_accessible_ref_child;
|
||||
class->ref_state_set = gtk_button_accessible_ref_state_set;
|
||||
class->initialize = gtk_button_accessible_initialize;
|
||||
|
||||
widget_class->notify_gtk = gtk_button_accessible_notify_gtk;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -52,6 +52,9 @@ struct _GtkButtonAccessibleClass
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gtk_button_accessible_get_type (void);
|
||||
|
||||
/*< private >*/
|
||||
void gtk_button_accessible_update_label (GtkButtonAccessible *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_BUTTON_ACCESSIBLE_H__ */
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtkcolorswatchprivate.h"
|
||||
#include "gtkcolorswatchaccessibleprivate.h"
|
||||
#include "gtkcolorswatchprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
static void atk_action_interface_init (AtkActionIface *iface);
|
||||
|
||||
@@ -29,9 +29,9 @@ G_DEFINE_TYPE_WITH_CODE (GtkColorSwatchAccessible, _gtk_color_swatch_accessible,
|
||||
|
||||
static void
|
||||
state_changed_cb (GtkWidget *widget,
|
||||
GtkStateFlags previous_flags)
|
||||
GtkStateFlags previous_flags,
|
||||
AtkObject *accessible)
|
||||
{
|
||||
AtkObject *accessible;
|
||||
GtkStateFlags flags;
|
||||
gboolean was_selected;
|
||||
gboolean selected;
|
||||
@@ -41,23 +41,46 @@ state_changed_cb (GtkWidget *widget,
|
||||
was_selected = (previous_flags & GTK_STATE_FLAG_SELECTED) != 0;
|
||||
selected = (flags & GTK_STATE_FLAG_SELECTED) != 0;
|
||||
|
||||
accessible = gtk_widget_get_accessible (widget);
|
||||
if (selected && !was_selected)
|
||||
atk_object_notify_state_change (accessible, ATK_STATE_CHECKED, TRUE);
|
||||
else if (!selected && was_selected)
|
||||
atk_object_notify_state_change (accessible, ATK_STATE_CHECKED, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
on_selectable_changed_cb (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
AtkObject *accessible)
|
||||
{
|
||||
GtkColorSwatch *swatch = GTK_COLOR_SWATCH (gobject);
|
||||
AtkRole role;
|
||||
|
||||
if (gtk_color_swatch_get_selectable (swatch))
|
||||
role = ATK_ROLE_RADIO_BUTTON;
|
||||
else
|
||||
role = ATK_ROLE_PUSH_BUTTON;
|
||||
|
||||
atk_object_set_role (accessible, role);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_color_swatch_accessible_initialize (AtkObject *obj,
|
||||
gpointer data)
|
||||
{
|
||||
GtkColorSwatch *swatch = data;
|
||||
|
||||
ATK_OBJECT_CLASS (_gtk_color_swatch_accessible_parent_class)->initialize (obj, data);
|
||||
|
||||
g_signal_connect (data, "state-flags-changed",
|
||||
G_CALLBACK (state_changed_cb), NULL);
|
||||
G_CALLBACK (state_changed_cb),
|
||||
obj);
|
||||
g_signal_connect (data, "notify::selectable",
|
||||
G_CALLBACK (on_selectable_changed_cb),
|
||||
obj);
|
||||
|
||||
atk_object_set_role (obj, ATK_ROLE_RADIO_BUTTON);
|
||||
obj->role = gtk_color_swatch_get_selectable (swatch)
|
||||
? ATK_ROLE_RADIO_BUTTON
|
||||
: ATK_ROLE_PUSH_BUTTON;
|
||||
}
|
||||
|
||||
static AtkStateSet *
|
||||
@@ -78,39 +101,19 @@ gtk_color_swatch_accessible_ref_state_set (AtkObject *accessible)
|
||||
return state_set;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_color_swatch_accessible_notify_gtk (GObject *obj,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (obj);
|
||||
AtkObject *atk_obj = gtk_widget_get_accessible (widget);
|
||||
|
||||
if (strcmp (pspec->name, "selectable") == 0)
|
||||
{
|
||||
if (gtk_color_swatch_get_selectable (GTK_COLOR_SWATCH (widget)))
|
||||
atk_object_set_role (atk_obj, ATK_ROLE_RADIO_BUTTON);
|
||||
else
|
||||
atk_object_set_role (atk_obj, ATK_ROLE_PUSH_BUTTON);
|
||||
}
|
||||
else
|
||||
GTK_WIDGET_ACCESSIBLE_CLASS (_gtk_color_swatch_accessible_parent_class)->notify_gtk (obj, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_color_swatch_accessible_class_init (GtkColorSwatchAccessibleClass *klass)
|
||||
{
|
||||
AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass);
|
||||
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass *)klass;
|
||||
|
||||
atk_class->initialize = gtk_color_swatch_accessible_initialize;
|
||||
atk_class->ref_state_set = gtk_color_swatch_accessible_ref_state_set;
|
||||
|
||||
widget_class->notify_gtk = gtk_color_swatch_accessible_notify_gtk;
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_color_swatch_accessible_init (GtkColorSwatchAccessible *scale)
|
||||
_gtk_color_swatch_accessible_init (GtkColorSwatchAccessible *self)
|
||||
{
|
||||
ATK_OBJECT (self)->role = ATK_ROLE_RADIO_BUTTON;
|
||||
}
|
||||
|
||||
static gint
|
||||
|
||||
@@ -17,20 +17,21 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkentryaccessible.h"
|
||||
|
||||
#include "gtkcomboboxaccessible.h"
|
||||
|
||||
#include "gtkentryprivate.h"
|
||||
#include "gtklabel.h"
|
||||
#include "gtkpango.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtktextprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
|
||||
#include "gdk/gdkeventsprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <string.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtkpango.h"
|
||||
#include "gtkentryaccessible.h"
|
||||
#include "gtkentryprivate.h"
|
||||
#include "gtksearchentryprivate.h"
|
||||
#include "gtkpasswordentry.h"
|
||||
#include "gtktextprivate.h"
|
||||
#include "gtkcomboboxaccessible.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
|
||||
#define GTK_TYPE_ENTRY_ICON_ACCESSIBLE (gtk_entry_icon_accessible_get_type ())
|
||||
#define GTK_ENTRY_ICON_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ENTRY_ICON_ACCESSIBLE, GtkEntryIconAccessible))
|
||||
@@ -157,7 +158,7 @@ gtk_entry_icon_accessible_ref_state_set (AtkObject *accessible)
|
||||
if (!entry_set || atk_state_set_contains_state (entry_set, ATK_STATE_DEFUNCT))
|
||||
{
|
||||
atk_state_set_add_state (set, ATK_STATE_DEFUNCT);
|
||||
g_clear_object (&entry_set);
|
||||
g_clear_object (&entry_set);
|
||||
return set;
|
||||
}
|
||||
|
||||
@@ -356,15 +357,6 @@ icon_atk_component_interface_init (AtkComponentIface *iface)
|
||||
}
|
||||
|
||||
/* Callbacks */
|
||||
|
||||
static void insert_text_cb (GtkEditable *editable,
|
||||
gchar *new_text,
|
||||
gint new_text_length,
|
||||
gint *position);
|
||||
static void delete_text_cb (GtkEditable *editable,
|
||||
gint start,
|
||||
gint end);
|
||||
|
||||
static gboolean check_for_selection_change (GtkEntryAccessible *entry,
|
||||
GtkEditable *editable);
|
||||
|
||||
@@ -380,6 +372,277 @@ G_DEFINE_TYPE_WITH_CODE (GtkEntryAccessible, gtk_entry_accessible, GTK_TYPE_WIDG
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init)
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init))
|
||||
|
||||
static GtkText *
|
||||
get_text (AtkText *atk_text)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
|
||||
if (widget == NULL)
|
||||
return NULL;
|
||||
|
||||
return gtk_entry_get_text_widget (GTK_ENTRY (widget));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_for_selection_change (GtkEntryAccessible *accessible,
|
||||
GtkEditable *editable)
|
||||
{
|
||||
gboolean ret_val = FALSE;
|
||||
gint start, end;
|
||||
|
||||
if (gtk_editable_get_selection_bounds (editable, &start, &end))
|
||||
{
|
||||
if (end != accessible->priv->cursor_position ||
|
||||
start != accessible->priv->selection_bound)
|
||||
/*
|
||||
* This check is here as this function can be called
|
||||
* for notification of selection_bound and current_pos.
|
||||
* The values of current_pos and selection_bound may be the same
|
||||
* for both notifications and we only want to generate one
|
||||
* text_selection_changed signal.
|
||||
*/
|
||||
ret_val = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We had a selection */
|
||||
ret_val = (accessible->priv->cursor_position != accessible->priv->selection_bound);
|
||||
}
|
||||
|
||||
accessible->priv->cursor_position = end;
|
||||
accessible->priv->selection_bound = start;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static void
|
||||
insert_text_cb (GtkEditable *editable,
|
||||
gchar *new_text,
|
||||
gint new_text_length,
|
||||
gint *position,
|
||||
GtkEntryAccessible *self)
|
||||
{
|
||||
int length;
|
||||
|
||||
if (new_text_length == 0)
|
||||
return;
|
||||
|
||||
length = g_utf8_strlen (new_text, new_text_length);
|
||||
|
||||
g_signal_emit_by_name (self,
|
||||
"text-changed::insert",
|
||||
*position - length,
|
||||
length);
|
||||
}
|
||||
|
||||
/* We connect to GtkEditable::delete-text, since it carries
|
||||
* the information we need. But we delay emitting our own
|
||||
* text_changed::delete signal until the entry has update
|
||||
* all its internal state and emits GtkEntry::changed.
|
||||
*/
|
||||
static void
|
||||
delete_text_cb (GtkEditable *editable,
|
||||
gint start,
|
||||
gint end,
|
||||
GtkEntryAccessible *self)
|
||||
{
|
||||
GtkText *textw;
|
||||
|
||||
textw = get_text (ATK_TEXT (self));
|
||||
if (textw == NULL)
|
||||
return;
|
||||
|
||||
if (end < 0)
|
||||
{
|
||||
gchar *text;
|
||||
|
||||
text = gtk_text_get_display_text (textw, 0, -1);
|
||||
end = g_utf8_strlen (text, -1);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
if (end == start)
|
||||
return;
|
||||
|
||||
g_signal_emit_by_name (self,
|
||||
"text-changed::delete",
|
||||
start,
|
||||
end - start);
|
||||
}
|
||||
|
||||
static void
|
||||
on_notify (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
GtkEntryAccessible *self)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
AtkObject* atk_obj;
|
||||
GtkEntryAccessiblePrivate *priv;
|
||||
|
||||
widget = GTK_WIDGET (gobject);
|
||||
atk_obj = gtk_widget_get_accessible (widget);
|
||||
priv = gtk_entry_accessible_get_instance_private (self);
|
||||
|
||||
if (g_strcmp0 (pspec->name, "cursor-position") == 0)
|
||||
{
|
||||
if (check_for_selection_change (self, GTK_EDITABLE (widget)))
|
||||
g_signal_emit_by_name (atk_obj, "text-selection-changed");
|
||||
/*
|
||||
* The entry cursor position has moved so generate the signal.
|
||||
*/
|
||||
g_signal_emit_by_name (atk_obj, "text-caret-moved",
|
||||
gtk_editable_get_position (GTK_EDITABLE (widget)));
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "selection-bound") == 0)
|
||||
{
|
||||
if (check_for_selection_change (self, GTK_EDITABLE (widget)))
|
||||
g_signal_emit_by_name (atk_obj, "text-selection-changed");
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "editable") == 0)
|
||||
{
|
||||
gboolean value;
|
||||
|
||||
g_object_get (gobject, "editable", &value, NULL);
|
||||
atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE, value);
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "visibility") == 0)
|
||||
{
|
||||
gboolean visibility;
|
||||
AtkRole new_role;
|
||||
|
||||
visibility = gtk_entry_get_visibility (GTK_ENTRY (widget));
|
||||
new_role = visibility ? ATK_ROLE_TEXT : ATK_ROLE_PASSWORD_TEXT;
|
||||
atk_object_set_role (atk_obj, new_role);
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "primary-icon-storage-type") == 0)
|
||||
{
|
||||
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY &&
|
||||
!priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
priv->icons[GTK_ENTRY_ICON_PRIMARY] = gtk_entry_icon_accessible_new (self, GTK_ENTRY_ICON_PRIMARY);
|
||||
g_signal_emit_by_name (self, "children-changed::add", 0,
|
||||
priv->icons[GTK_ENTRY_ICON_PRIMARY], NULL);
|
||||
}
|
||||
else if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) == GTK_IMAGE_EMPTY &&
|
||||
priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
gtk_entry_icon_accessible_invalidate (GTK_ENTRY_ICON_ACCESSIBLE (priv->icons[GTK_ENTRY_ICON_PRIMARY]));
|
||||
g_signal_emit_by_name (self, "children-changed::remove", 0,
|
||||
priv->icons[GTK_ENTRY_ICON_PRIMARY], NULL);
|
||||
g_clear_object (&priv->icons[GTK_ENTRY_ICON_PRIMARY]);
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "secondary-icon-storage-type") == 0)
|
||||
{
|
||||
gint index = (priv->icons[GTK_ENTRY_ICON_PRIMARY] ? 1 : 0);
|
||||
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY &&
|
||||
!priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
priv->icons[GTK_ENTRY_ICON_SECONDARY] = gtk_entry_icon_accessible_new (self, GTK_ENTRY_ICON_SECONDARY);
|
||||
g_signal_emit_by_name (self, "children-changed::add", index,
|
||||
priv->icons[GTK_ENTRY_ICON_SECONDARY], NULL);
|
||||
}
|
||||
else if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY &&
|
||||
priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
gtk_entry_icon_accessible_invalidate (GTK_ENTRY_ICON_ACCESSIBLE (priv->icons[GTK_ENTRY_ICON_SECONDARY]));
|
||||
g_signal_emit_by_name (self, "children-changed::remove", index,
|
||||
priv->icons[GTK_ENTRY_ICON_SECONDARY], NULL);
|
||||
g_clear_object (&priv->icons[GTK_ENTRY_ICON_SECONDARY]);
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "primary-icon-name") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
const gchar *name;
|
||||
name = gtk_entry_get_icon_name (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
|
||||
if (name)
|
||||
atk_object_set_name (priv->icons[GTK_ENTRY_ICON_PRIMARY], name);
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "secondary-icon-name") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
const gchar *name;
|
||||
name = gtk_entry_get_icon_name (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
|
||||
if (name)
|
||||
atk_object_set_name (priv->icons[GTK_ENTRY_ICON_SECONDARY], name);
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "primary-icon-tooltip-text") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
gchar *text;
|
||||
text = gtk_entry_get_icon_tooltip_text (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
|
||||
if (text)
|
||||
{
|
||||
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY], text);
|
||||
g_free (text);
|
||||
}
|
||||
else
|
||||
{
|
||||
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY], "");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "secondary-icon-tooltip-text") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
gchar *text;
|
||||
text = gtk_entry_get_icon_tooltip_text (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
|
||||
if (text)
|
||||
{
|
||||
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY], text);
|
||||
g_free (text);
|
||||
}
|
||||
else
|
||||
{
|
||||
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY], "");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "primary-icon-activatable") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
gboolean on = gtk_entry_get_icon_activatable (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
|
||||
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_PRIMARY],
|
||||
ATK_STATE_ENABLED, on);
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "secondary-icon-activatable") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
gboolean on = gtk_entry_get_icon_activatable (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
|
||||
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_SECONDARY],
|
||||
ATK_STATE_ENABLED, on);
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "primary-icon-sensitive") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
gboolean on = gtk_entry_get_icon_sensitive (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
|
||||
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_PRIMARY],
|
||||
ATK_STATE_SENSITIVE, on);
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "secondary-icon-sensitive") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
gboolean on = gtk_entry_get_icon_sensitive (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
|
||||
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_SECONDARY],
|
||||
ATK_STATE_SENSITIVE, on);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static AtkStateSet *
|
||||
gtk_entry_accessible_ref_state_set (AtkObject *accessible)
|
||||
@@ -423,9 +686,7 @@ gtk_entry_accessible_get_attributes (AtkObject *accessible)
|
||||
if (widget == NULL)
|
||||
return attributes;
|
||||
|
||||
if (GTK_IS_ENTRY (widget) || GTK_IS_SEARCH_ENTRY (widget))
|
||||
g_object_get (widget, "placeholder-text", &text, NULL);
|
||||
|
||||
g_object_get (widget, "placeholder-text", &text, NULL);
|
||||
if (text == NULL)
|
||||
return attributes;
|
||||
|
||||
@@ -456,197 +717,9 @@ gtk_entry_accessible_initialize (AtkObject *obj,
|
||||
gtk_entry_accessible->priv->selection_bound = start_pos;
|
||||
|
||||
/* Set up signal callbacks */
|
||||
g_signal_connect_after (widget, "insert-text", G_CALLBACK (insert_text_cb), NULL);
|
||||
g_signal_connect (widget, "delete-text", G_CALLBACK (delete_text_cb), NULL);
|
||||
|
||||
if (GTK_IS_PASSWORD_ENTRY (widget))
|
||||
obj->role = ATK_ROLE_PASSWORD_TEXT;
|
||||
else
|
||||
obj->role = ATK_ROLE_TEXT;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_entry_accessible_notify_gtk (GObject *obj,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
AtkObject* atk_obj;
|
||||
GtkEntryAccessible* entry;
|
||||
GtkEntryAccessiblePrivate *priv;
|
||||
|
||||
widget = GTK_WIDGET (obj);
|
||||
atk_obj = gtk_widget_get_accessible (widget);
|
||||
entry = GTK_ENTRY_ACCESSIBLE (atk_obj);
|
||||
priv = entry->priv;
|
||||
|
||||
if (g_strcmp0 (pspec->name, "cursor-position") == 0)
|
||||
{
|
||||
if (check_for_selection_change (entry, GTK_EDITABLE (widget)))
|
||||
g_signal_emit_by_name (atk_obj, "text-selection-changed");
|
||||
/*
|
||||
* The entry cursor position has moved so generate the signal.
|
||||
*/
|
||||
g_signal_emit_by_name (atk_obj, "text-caret-moved",
|
||||
gtk_editable_get_position (GTK_EDITABLE (widget)));
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "selection-bound") == 0)
|
||||
{
|
||||
if (check_for_selection_change (entry, GTK_EDITABLE (widget)))
|
||||
g_signal_emit_by_name (atk_obj, "text-selection-changed");
|
||||
}
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "editable") == 0)
|
||||
{
|
||||
gboolean value;
|
||||
|
||||
g_object_get (obj, "editable", &value, NULL);
|
||||
atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE, value);
|
||||
}
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "visibility") == 0)
|
||||
{
|
||||
gboolean visibility;
|
||||
AtkRole new_role;
|
||||
|
||||
visibility = gtk_entry_get_visibility (GTK_ENTRY (widget));
|
||||
new_role = visibility ? ATK_ROLE_TEXT : ATK_ROLE_PASSWORD_TEXT;
|
||||
atk_object_set_role (atk_obj, new_role);
|
||||
}
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "primary-icon-storage-type") == 0)
|
||||
{
|
||||
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY && !priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
priv->icons[GTK_ENTRY_ICON_PRIMARY] = gtk_entry_icon_accessible_new (entry, GTK_ENTRY_ICON_PRIMARY);
|
||||
g_signal_emit_by_name (entry, "children-changed::add", 0,
|
||||
priv->icons[GTK_ENTRY_ICON_PRIMARY], NULL);
|
||||
}
|
||||
else if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) == GTK_IMAGE_EMPTY && priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
gtk_entry_icon_accessible_invalidate (GTK_ENTRY_ICON_ACCESSIBLE (priv->icons[GTK_ENTRY_ICON_PRIMARY]));
|
||||
g_signal_emit_by_name (entry, "children-changed::remove", 0,
|
||||
priv->icons[GTK_ENTRY_ICON_PRIMARY], NULL);
|
||||
g_clear_object (&priv->icons[GTK_ENTRY_ICON_PRIMARY]);
|
||||
}
|
||||
}
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "secondary-icon-storage-type") == 0)
|
||||
{
|
||||
gint index = (priv->icons[GTK_ENTRY_ICON_PRIMARY] ? 1 : 0);
|
||||
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY && !priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
priv->icons[GTK_ENTRY_ICON_SECONDARY] = gtk_entry_icon_accessible_new (entry, GTK_ENTRY_ICON_SECONDARY);
|
||||
g_signal_emit_by_name (entry, "children-changed::add", index,
|
||||
priv->icons[GTK_ENTRY_ICON_SECONDARY], NULL);
|
||||
}
|
||||
else if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY && priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
gtk_entry_icon_accessible_invalidate (GTK_ENTRY_ICON_ACCESSIBLE (priv->icons[GTK_ENTRY_ICON_SECONDARY]));
|
||||
g_signal_emit_by_name (entry, "children-changed::remove", index,
|
||||
priv->icons[GTK_ENTRY_ICON_SECONDARY], NULL);
|
||||
g_clear_object (&priv->icons[GTK_ENTRY_ICON_SECONDARY]);
|
||||
}
|
||||
}
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "primary-icon-name") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
const gchar *name;
|
||||
name = gtk_entry_get_icon_name (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
|
||||
if (name)
|
||||
atk_object_set_name (priv->icons[GTK_ENTRY_ICON_PRIMARY], name);
|
||||
}
|
||||
}
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "secondary-icon-name") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
const gchar *name;
|
||||
name = gtk_entry_get_icon_name (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
|
||||
if (name)
|
||||
atk_object_set_name (priv->icons[GTK_ENTRY_ICON_SECONDARY], name);
|
||||
}
|
||||
}
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "primary-icon-tooltip-text") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
gchar *text;
|
||||
text = gtk_entry_get_icon_tooltip_text (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
|
||||
if (text)
|
||||
{
|
||||
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY], text);
|
||||
g_free (text);
|
||||
}
|
||||
else
|
||||
{
|
||||
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY], "");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "secondary-icon-tooltip-text") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
gchar *text;
|
||||
text = gtk_entry_get_icon_tooltip_text (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
|
||||
if (text)
|
||||
{
|
||||
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY], text);
|
||||
g_free (text);
|
||||
}
|
||||
else
|
||||
{
|
||||
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY], "");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "primary-icon-activatable") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
gboolean on = gtk_entry_get_icon_activatable (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
|
||||
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_PRIMARY],
|
||||
ATK_STATE_ENABLED, on);
|
||||
}
|
||||
}
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "secondary-icon-activatable") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
gboolean on = gtk_entry_get_icon_activatable (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
|
||||
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_SECONDARY],
|
||||
ATK_STATE_ENABLED, on);
|
||||
}
|
||||
}
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "primary-icon-sensitive") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
gboolean on = gtk_entry_get_icon_sensitive (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
|
||||
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_PRIMARY],
|
||||
ATK_STATE_SENSITIVE, on);
|
||||
}
|
||||
}
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "secondary-icon-sensitive") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
gboolean on = gtk_entry_get_icon_sensitive (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
|
||||
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_SECONDARY],
|
||||
ATK_STATE_SENSITIVE, on);
|
||||
}
|
||||
}
|
||||
else
|
||||
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_entry_accessible_parent_class)->notify_gtk (obj, pspec);
|
||||
g_signal_connect_after (widget, "insert-text", G_CALLBACK (insert_text_cb), obj);
|
||||
g_signal_connect (widget, "delete-text", G_CALLBACK (delete_text_cb), obj);
|
||||
g_signal_connect (widget, "notify", G_CALLBACK (on_notify), obj);
|
||||
}
|
||||
|
||||
static gint
|
||||
@@ -673,13 +746,10 @@ gtk_entry_accessible_get_n_children (AtkObject* obj)
|
||||
if (widget == NULL)
|
||||
return 0;
|
||||
|
||||
if (GTK_IS_ENTRY (widget))
|
||||
{
|
||||
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY)
|
||||
count++;
|
||||
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY)
|
||||
count++;
|
||||
}
|
||||
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY)
|
||||
count++;
|
||||
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -697,9 +767,6 @@ gtk_entry_accessible_ref_child (AtkObject *obj,
|
||||
if (widget == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!GTK_IS_ENTRY (widget))
|
||||
return NULL;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
@@ -741,8 +808,7 @@ gtk_entry_accessible_finalize (GObject *object)
|
||||
static void
|
||||
gtk_entry_accessible_class_init (GtkEntryAccessibleClass *klass)
|
||||
{
|
||||
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
||||
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
|
||||
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
class->ref_state_set = gtk_entry_accessible_ref_state_set;
|
||||
@@ -752,8 +818,6 @@ gtk_entry_accessible_class_init (GtkEntryAccessibleClass *klass)
|
||||
class->get_n_children = gtk_entry_accessible_get_n_children;
|
||||
class->ref_child = gtk_entry_accessible_ref_child;
|
||||
|
||||
widget_class->notify_gtk = gtk_entry_accessible_notify_gtk;
|
||||
|
||||
gobject_class->finalize = gtk_entry_accessible_finalize;
|
||||
}
|
||||
|
||||
@@ -763,23 +827,8 @@ gtk_entry_accessible_init (GtkEntryAccessible *entry)
|
||||
entry->priv = gtk_entry_accessible_get_instance_private (entry);
|
||||
entry->priv->cursor_position = 0;
|
||||
entry->priv->selection_bound = 0;
|
||||
}
|
||||
|
||||
static GtkText *
|
||||
get_text (AtkText *atk_text)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
|
||||
if (widget == NULL)
|
||||
return NULL;
|
||||
|
||||
if (GTK_IS_ENTRY (widget))
|
||||
return gtk_entry_get_text_widget (GTK_ENTRY (widget));
|
||||
else if (GTK_IS_SEARCH_ENTRY (widget))
|
||||
return gtk_search_entry_get_text_widget (GTK_SEARCH_ENTRY (widget));
|
||||
else
|
||||
return NULL; // FIXME;
|
||||
ATK_OBJECT (entry)->role = ATK_ROLE_TEXT;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
@@ -1377,96 +1426,6 @@ atk_editable_text_interface_init (AtkEditableTextIface *iface)
|
||||
iface->set_run_attributes = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
insert_text_cb (GtkEditable *editable,
|
||||
gchar *new_text,
|
||||
gint new_text_length,
|
||||
gint *position)
|
||||
{
|
||||
GtkEntryAccessible *accessible;
|
||||
gint length;
|
||||
|
||||
if (new_text_length == 0)
|
||||
return;
|
||||
|
||||
accessible = GTK_ENTRY_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (editable)));
|
||||
length = g_utf8_strlen (new_text, new_text_length);
|
||||
|
||||
g_signal_emit_by_name (accessible,
|
||||
"text-changed::insert",
|
||||
*position - length,
|
||||
length);
|
||||
}
|
||||
|
||||
/* We connect to GtkEditable::delete-text, since it carries
|
||||
* the information we need. But we delay emitting our own
|
||||
* text_changed::delete signal until the entry has update
|
||||
* all its internal state and emits GtkEntry::changed.
|
||||
*/
|
||||
static void
|
||||
delete_text_cb (GtkEditable *editable,
|
||||
gint start,
|
||||
gint end)
|
||||
{
|
||||
GtkEntryAccessible *accessible;
|
||||
GtkText *textw;
|
||||
|
||||
accessible = GTK_ENTRY_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (editable)));
|
||||
|
||||
textw = get_text (ATK_TEXT (accessible));
|
||||
if (textw == NULL)
|
||||
return;
|
||||
|
||||
if (end < 0)
|
||||
{
|
||||
gchar *text;
|
||||
|
||||
text = gtk_text_get_display_text (textw, 0, -1);
|
||||
end = g_utf8_strlen (text, -1);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
if (end == start)
|
||||
return;
|
||||
|
||||
g_signal_emit_by_name (accessible,
|
||||
"text-changed::delete",
|
||||
start,
|
||||
end - start);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_for_selection_change (GtkEntryAccessible *accessible,
|
||||
GtkEditable *editable)
|
||||
{
|
||||
gboolean ret_val = FALSE;
|
||||
gint start, end;
|
||||
|
||||
if (gtk_editable_get_selection_bounds (editable, &start, &end))
|
||||
{
|
||||
if (end != accessible->priv->cursor_position ||
|
||||
start != accessible->priv->selection_bound)
|
||||
/*
|
||||
* This check is here as this function can be called
|
||||
* for notification of selection_bound and current_pos.
|
||||
* The values of current_pos and selection_bound may be the same
|
||||
* for both notifications and we only want to generate one
|
||||
* text_selection_changed signal.
|
||||
*/
|
||||
ret_val = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We had a selection */
|
||||
ret_val = (accessible->priv->cursor_position != accessible->priv->selection_bound);
|
||||
}
|
||||
|
||||
accessible->priv->cursor_position = end;
|
||||
accessible->priv->selection_bound = start;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_entry_accessible_do_action (AtkAction *action,
|
||||
gint i)
|
||||
|
||||
@@ -17,9 +17,10 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkexpanderaccessibleprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtkexpanderaccessible.h"
|
||||
|
||||
static void atk_action_interface_init (AtkActionIface *iface);
|
||||
|
||||
@@ -91,41 +92,27 @@ gtk_expander_accessible_ref_child (AtkObject *obj,
|
||||
return accessible;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_expander_accessible_initialize (AtkObject *obj,
|
||||
gpointer data)
|
||||
void
|
||||
gtk_expander_accessible_update_label (GtkExpanderAccessible *self)
|
||||
{
|
||||
ATK_OBJECT_CLASS (gtk_expander_accessible_parent_class)->initialize (obj, data);
|
||||
AtkObject *atk_obj = ATK_OBJECT (self);
|
||||
|
||||
obj->role = ATK_ROLE_TOGGLE_BUTTON;
|
||||
if (atk_obj->name == NULL)
|
||||
g_object_notify (G_OBJECT (atk_obj), "accessible-name");
|
||||
|
||||
g_signal_emit_by_name (atk_obj, "visible-data-changed");
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_expander_accessible_notify_gtk (GObject *obj,
|
||||
GParamSpec *pspec)
|
||||
void
|
||||
gtk_expander_accessible_update_state (GtkExpanderAccessible *self,
|
||||
gboolean expanded)
|
||||
{
|
||||
AtkObject* atk_obj;
|
||||
GtkExpander *expander;
|
||||
AtkObject *atk_obj = ATK_OBJECT (self);
|
||||
|
||||
expander = GTK_EXPANDER (obj);
|
||||
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (expander));
|
||||
;
|
||||
if (g_strcmp0 (pspec->name, "label") == 0)
|
||||
{
|
||||
if (atk_obj->name == NULL)
|
||||
g_object_notify (G_OBJECT (atk_obj), "accessible-name");
|
||||
g_signal_emit_by_name (atk_obj, "visible-data-changed");
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "expanded") == 0)
|
||||
{
|
||||
atk_object_notify_state_change (atk_obj, ATK_STATE_CHECKED,
|
||||
gtk_expander_get_expanded (expander));
|
||||
atk_object_notify_state_change (atk_obj, ATK_STATE_EXPANDED,
|
||||
gtk_expander_get_expanded (expander));
|
||||
g_signal_emit_by_name (atk_obj, "visible-data-changed");
|
||||
}
|
||||
else
|
||||
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_expander_accessible_parent_class)->notify_gtk (obj, pspec);
|
||||
atk_object_notify_state_change (atk_obj, ATK_STATE_CHECKED, expanded);
|
||||
atk_object_notify_state_change (atk_obj, ATK_STATE_EXPANDED, expanded);
|
||||
|
||||
g_signal_emit_by_name (atk_obj, "visible-data-changed");
|
||||
}
|
||||
|
||||
static AtkStateSet *
|
||||
@@ -158,21 +145,17 @@ static void
|
||||
gtk_expander_accessible_class_init (GtkExpanderAccessibleClass *klass)
|
||||
{
|
||||
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
||||
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
|
||||
|
||||
widget_class->notify_gtk = gtk_expander_accessible_notify_gtk;
|
||||
|
||||
class->get_name = gtk_expander_accessible_get_name;
|
||||
class->get_n_children = gtk_expander_accessible_get_n_children;
|
||||
class->ref_child = gtk_expander_accessible_ref_child;
|
||||
class->ref_state_set = gtk_expander_accessible_ref_state_set;
|
||||
|
||||
class->initialize = gtk_expander_accessible_initialize;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_expander_accessible_init (GtkExpanderAccessible *expander)
|
||||
gtk_expander_accessible_init (GtkExpanderAccessible *self)
|
||||
{
|
||||
ATK_OBJECT (self)->role = ATK_ROLE_TOGGLE_BUTTON;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
||||
31
gtk/a11y/gtkexpanderaccessibleprivate.h
Normal file
31
gtk/a11y/gtkexpanderaccessibleprivate.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/* gtkexpanderaccessibleprivate.h: GtkExpanderAccessible private API
|
||||
*
|
||||
* Copyright 2020 GNOME Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gtkexpanderaccessible.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gtk_expander_accessible_update_label (GtkExpanderAccessible *self);
|
||||
void gtk_expander_accessible_update_state (GtkExpanderAccessible *self,
|
||||
gboolean expanded);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -32,11 +32,11 @@
|
||||
#define GTK_ICON_VIEW_ITEM_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE, GtkIconViewItemAccessible))
|
||||
#define GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE))
|
||||
|
||||
struct _GtkIconViewAccessiblePrivate
|
||||
typedef struct
|
||||
{
|
||||
GList *items;
|
||||
GtkTreeModel *model;
|
||||
};
|
||||
} GtkIconViewAccessiblePrivate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -265,7 +265,8 @@ get_text (GtkIconView *icon_view,
|
||||
|
||||
_gtk_icon_view_set_cell_data (icon_view, item);
|
||||
gtk_cell_area_foreach (icon_view->priv->cell_area,
|
||||
(GtkCellCallback)get_text_foreach, &text);
|
||||
(GtkCellCallback) get_text_foreach,
|
||||
&text);
|
||||
|
||||
return text;
|
||||
}
|
||||
@@ -742,8 +743,9 @@ gtk_icon_view_item_accessible_set_visibility (GtkIconViewItemAccessible *item,
|
||||
static void
|
||||
_gtk_icon_view_item_accessible_init (GtkIconViewItemAccessible *item)
|
||||
{
|
||||
item->state_set = atk_state_set_new ();
|
||||
atk_object_set_role (ATK_OBJECT (item), ATK_ROLE_ICON);
|
||||
|
||||
item->state_set = atk_state_set_new ();
|
||||
atk_state_set_add_state (item->state_set, ATK_STATE_ENABLED);
|
||||
atk_state_set_add_state (item->state_set, ATK_STATE_FOCUSABLE);
|
||||
atk_state_set_add_state (item->state_set, ATK_STATE_SENSITIVE);
|
||||
@@ -860,25 +862,25 @@ G_DEFINE_TYPE_WITH_CODE (GtkIconViewAccessible, gtk_icon_view_accessible, GTK_TY
|
||||
typedef struct
|
||||
{
|
||||
AtkObject *item;
|
||||
gint index;
|
||||
} GtkIconViewItemAccessibleInfo;
|
||||
int index;
|
||||
} ItemAccessibleInfo;
|
||||
|
||||
|
||||
static void
|
||||
gtk_icon_view_item_accessible_info_new (AtkObject *accessible,
|
||||
AtkObject *item,
|
||||
gint index)
|
||||
gtk_icon_view_item_accessible_info_new (GtkIconViewAccessible *self,
|
||||
GtkIconViewItemAccessible *item,
|
||||
int index)
|
||||
{
|
||||
GtkIconViewAccessible *view = (GtkIconViewAccessible *)accessible;
|
||||
GtkIconViewItemAccessibleInfo *info;
|
||||
GtkIconViewItemAccessibleInfo *tmp_info;
|
||||
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
|
||||
ItemAccessibleInfo *info;
|
||||
ItemAccessibleInfo *tmp_info;
|
||||
GList *items;
|
||||
|
||||
info = g_new (GtkIconViewItemAccessibleInfo, 1);
|
||||
info->item = item;
|
||||
info = g_new (ItemAccessibleInfo, 1);
|
||||
info->item = ATK_OBJECT (item);
|
||||
info->index = index;
|
||||
|
||||
items = view->priv->items;
|
||||
items = priv->items;
|
||||
while (items)
|
||||
{
|
||||
tmp_info = items->data;
|
||||
@@ -886,7 +888,8 @@ gtk_icon_view_item_accessible_info_new (AtkObject *accessible,
|
||||
break;
|
||||
items = items->next;
|
||||
}
|
||||
view->priv->items = g_list_insert_before (view->priv->items, items, info);
|
||||
|
||||
priv->items = g_list_insert_before (priv->items, items, info);
|
||||
}
|
||||
|
||||
static gint
|
||||
@@ -904,22 +907,24 @@ gtk_icon_view_accessible_get_n_children (AtkObject *accessible)
|
||||
return g_list_length (icon_view->priv->items);
|
||||
}
|
||||
|
||||
static AtkObject *
|
||||
gtk_icon_view_accessible_find_child (AtkObject *accessible,
|
||||
gint index)
|
||||
static GtkIconViewItemAccessible *
|
||||
gtk_icon_view_accessible_find_child (GtkIconViewAccessible *self,
|
||||
gint index)
|
||||
{
|
||||
GtkIconViewAccessible *view = (GtkIconViewAccessible*)accessible;
|
||||
GtkIconViewItemAccessibleInfo *info;
|
||||
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
|
||||
GList *items;
|
||||
|
||||
items = view->priv->items;
|
||||
items = priv->items;
|
||||
|
||||
while (items)
|
||||
{
|
||||
info = items->data;
|
||||
ItemAccessibleInfo *info = items->data;
|
||||
GList *next = items->next;
|
||||
|
||||
if (info->index == index)
|
||||
return info->item;
|
||||
items = items->next;
|
||||
return GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
|
||||
|
||||
items = next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -929,31 +934,28 @@ static AtkObject *
|
||||
gtk_icon_view_accessible_ref_child (AtkObject *accessible,
|
||||
gint index)
|
||||
{
|
||||
GtkIconViewAccessible *self = GTK_ICON_VIEW_ACCESSIBLE (accessible);
|
||||
GtkIconViewItemAccessible *a11y_item;
|
||||
GtkIconView *icon_view;
|
||||
GtkWidget *widget;
|
||||
GList *icons;
|
||||
AtkObject *obj;
|
||||
GtkIconViewItemAccessible *a11y_item;
|
||||
|
||||
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
|
||||
if (!widget)
|
||||
if (widget == NULL)
|
||||
return NULL;
|
||||
|
||||
icon_view = GTK_ICON_VIEW (widget);
|
||||
icons = g_list_nth (icon_view->priv->items, index);
|
||||
obj = NULL;
|
||||
if (icons)
|
||||
{
|
||||
GtkIconViewItem *item = icons->data;
|
||||
|
||||
g_return_val_if_fail (item->index == index, NULL);
|
||||
obj = gtk_icon_view_accessible_find_child (accessible, index);
|
||||
if (!obj)
|
||||
|
||||
a11y_item = gtk_icon_view_accessible_find_child (self, index);
|
||||
if (a11y_item == NULL)
|
||||
{
|
||||
obj = g_object_new (GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE, NULL);
|
||||
gtk_icon_view_item_accessible_info_new (accessible, obj, index);
|
||||
obj->role = ATK_ROLE_ICON;
|
||||
a11y_item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (obj);
|
||||
a11y_item = g_object_new (GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE, NULL);
|
||||
a11y_item->item = item;
|
||||
a11y_item->widget = widget;
|
||||
|
||||
@@ -962,60 +964,62 @@ gtk_icon_view_accessible_ref_child (AtkObject *accessible,
|
||||
|
||||
gtk_icon_view_item_accessible_set_visibility (a11y_item, FALSE);
|
||||
g_object_add_weak_pointer (G_OBJECT (widget), (gpointer) &(a11y_item->widget));
|
||||
|
||||
gtk_icon_view_item_accessible_info_new (self, a11y_item, index);
|
||||
}
|
||||
g_object_ref (obj);
|
||||
|
||||
g_object_ref (a11y_item);
|
||||
|
||||
return ATK_OBJECT (a11y_item);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_icon_view_accessible_traverse_items (GtkIconViewAccessible *view,
|
||||
gtk_icon_view_accessible_traverse_items (GtkIconViewAccessible *self,
|
||||
GList *list)
|
||||
{
|
||||
GtkIconViewItemAccessibleInfo *info;
|
||||
GtkIconViewItemAccessible *item;
|
||||
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
|
||||
GtkWidget *widget;
|
||||
gboolean act_on_item;
|
||||
GList *items;
|
||||
|
||||
if (view->priv->items)
|
||||
if (priv->items == NULL)
|
||||
return;
|
||||
|
||||
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (self));
|
||||
if (widget == NULL)
|
||||
return;
|
||||
|
||||
items = priv->items;
|
||||
|
||||
act_on_item = (list == NULL);
|
||||
|
||||
while (items)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
gboolean act_on_item;
|
||||
ItemAccessibleInfo *info = items->data;
|
||||
GtkIconViewItemAccessible *item;
|
||||
GList *next = items->next;
|
||||
|
||||
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (view));
|
||||
if (widget == NULL)
|
||||
return;
|
||||
item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
|
||||
|
||||
items = view->priv->items;
|
||||
if (act_on_item == FALSE && list == items)
|
||||
act_on_item = TRUE;
|
||||
|
||||
act_on_item = (list == NULL);
|
||||
if (act_on_item)
|
||||
gtk_icon_view_item_accessible_set_visibility (item, TRUE);
|
||||
|
||||
while (items)
|
||||
{
|
||||
|
||||
info = (GtkIconViewItemAccessibleInfo *)items->data;
|
||||
item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
|
||||
|
||||
if (act_on_item == FALSE && list == items)
|
||||
act_on_item = TRUE;
|
||||
|
||||
if (act_on_item)
|
||||
gtk_icon_view_item_accessible_set_visibility (item, TRUE);
|
||||
|
||||
items = items->next;
|
||||
}
|
||||
items = next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_icon_view_accessible_adjustment_changed (GtkIconView *icon_view)
|
||||
gtk_icon_view_accessible_adjustment_changed (GtkIconViewAccessible *self)
|
||||
{
|
||||
GtkIconViewAccessible *view;
|
||||
|
||||
view = GTK_ICON_VIEW_ACCESSIBLE (_gtk_widget_peek_accessible (GTK_WIDGET (icon_view)));
|
||||
if (view == NULL)
|
||||
return;
|
||||
|
||||
gtk_icon_view_accessible_traverse_items (view, NULL);
|
||||
gtk_icon_view_accessible_traverse_items (self, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1024,36 +1028,26 @@ gtk_icon_view_accessible_model_row_changed (GtkTreeModel *tree_model,
|
||||
GtkTreeIter *iter,
|
||||
gpointer user_data)
|
||||
{
|
||||
AtkObject *atk_obj;
|
||||
gint index;
|
||||
GtkWidget *widget;
|
||||
GtkIconView *icon_view;
|
||||
GtkIconViewItem *item;
|
||||
GtkIconViewAccessible *self = user_data;
|
||||
GtkIconViewItemAccessible *a11y_item;
|
||||
const gchar *name;
|
||||
|
||||
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
|
||||
index = gtk_tree_path_get_indices(path)[0];
|
||||
a11y_item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (
|
||||
gtk_icon_view_accessible_find_child (atk_obj, index));
|
||||
int index;
|
||||
|
||||
index = gtk_tree_path_get_indices (path)[0];
|
||||
a11y_item = gtk_icon_view_accessible_find_child (self, index);
|
||||
if (a11y_item)
|
||||
{
|
||||
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_obj));
|
||||
icon_view = GTK_ICON_VIEW (widget);
|
||||
item = a11y_item->item;
|
||||
GtkIconViewItem *item = a11y_item->item;
|
||||
GtkIconView *icon_view = GTK_ICON_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (self)));
|
||||
|
||||
name = atk_object_get_name (ATK_OBJECT (a11y_item));
|
||||
if (!name || strcmp (name, "") == 0)
|
||||
const char *name = atk_object_get_name (ATK_OBJECT (a11y_item));
|
||||
if (name == NULL || *name == '\0')
|
||||
{
|
||||
g_free (a11y_item->text);
|
||||
a11y_item->text = get_text (icon_view, item);
|
||||
}
|
||||
}
|
||||
|
||||
g_signal_emit_by_name (atk_obj, "visible-data-changed");
|
||||
|
||||
return;
|
||||
g_signal_emit_by_name (self, "visible-data-changed");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1062,24 +1056,22 @@ gtk_icon_view_accessible_model_row_inserted (GtkTreeModel *tree_model,
|
||||
GtkTreeIter *iter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkIconViewItemAccessibleInfo *info;
|
||||
GtkIconViewAccessible *view;
|
||||
GtkIconViewItemAccessible *item;
|
||||
GtkIconViewAccessible *self = user_data;
|
||||
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
|
||||
GList *items;
|
||||
GList *tmp_list;
|
||||
AtkObject *atk_obj;
|
||||
gint index;
|
||||
int index;
|
||||
|
||||
index = gtk_tree_path_get_indices(path)[0];
|
||||
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
|
||||
view = GTK_ICON_VIEW_ACCESSIBLE (atk_obj);
|
||||
index = gtk_tree_path_get_indices (path)[0];
|
||||
|
||||
items = view->priv->items;
|
||||
items = priv->items;
|
||||
tmp_list = NULL;
|
||||
while (items)
|
||||
{
|
||||
info = items->data;
|
||||
item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
|
||||
ItemAccessibleInfo *info = items->data;
|
||||
GtkIconViewItemAccessible *item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
|
||||
GList *next = items->next;
|
||||
|
||||
if (info->index != item->item->index)
|
||||
{
|
||||
if (info->index < index)
|
||||
@@ -1091,40 +1083,36 @@ gtk_icon_view_accessible_model_row_inserted (GtkTreeModel *tree_model,
|
||||
info->index = item->item->index;
|
||||
}
|
||||
|
||||
items = items->next;
|
||||
items = next;
|
||||
}
|
||||
gtk_icon_view_accessible_traverse_items (view, tmp_list);
|
||||
g_signal_emit_by_name (atk_obj, "children-changed::add",
|
||||
|
||||
gtk_icon_view_accessible_traverse_items (self, tmp_list);
|
||||
g_signal_emit_by_name (self,
|
||||
"children-changed::add",
|
||||
index, NULL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_icon_view_accessible_model_row_deleted (GtkTreeModel *tree_model,
|
||||
GtkTreePath *path,
|
||||
gpointer user_data)
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkIconViewItemAccessibleInfo *info;
|
||||
GtkIconViewAccessible *view;
|
||||
GtkIconViewItemAccessible *item;
|
||||
GtkIconViewAccessible *self = user_data;
|
||||
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
|
||||
GList *items;
|
||||
GList *tmp_list;
|
||||
GList *deleted_item;
|
||||
AtkObject *atk_obj;
|
||||
gint index;
|
||||
GList *tmp_list = NULL;
|
||||
GList *deleted_item = NULL;
|
||||
int index;
|
||||
|
||||
index = gtk_tree_path_get_indices(path)[0];
|
||||
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
|
||||
view = GTK_ICON_VIEW_ACCESSIBLE (atk_obj);
|
||||
index = gtk_tree_path_get_indices (path)[0];
|
||||
|
||||
items = view->priv->items;
|
||||
tmp_list = NULL;
|
||||
deleted_item = NULL;
|
||||
info = NULL;
|
||||
items = priv->items;
|
||||
while (items)
|
||||
{
|
||||
info = items->data;
|
||||
item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
|
||||
ItemAccessibleInfo *info = items->data;
|
||||
GtkIconViewItemAccessible *item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
|
||||
GList *next = items->next;
|
||||
|
||||
if (info->index == index)
|
||||
{
|
||||
deleted_item = items;
|
||||
@@ -1137,26 +1125,32 @@ gtk_icon_view_accessible_model_row_deleted (GtkTreeModel *tree_model,
|
||||
info->index = item->item->index;
|
||||
}
|
||||
|
||||
items = items->next;
|
||||
items = next;
|
||||
}
|
||||
|
||||
if (deleted_item)
|
||||
{
|
||||
info = deleted_item->data;
|
||||
gtk_icon_view_item_accessible_add_state (GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item), ATK_STATE_DEFUNCT, TRUE);
|
||||
g_signal_emit_by_name (atk_obj, "children-changed::remove",
|
||||
ItemAccessibleInfo *info = deleted_item->data;
|
||||
|
||||
gtk_icon_view_item_accessible_add_state (GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item),
|
||||
ATK_STATE_DEFUNCT,
|
||||
TRUE);
|
||||
|
||||
g_signal_emit_by_name (self,
|
||||
"children-changed::remove",
|
||||
index, NULL, NULL);
|
||||
view->priv->items = g_list_delete_link (view->priv->items, deleted_item);
|
||||
|
||||
priv->items = g_list_delete_link (priv->items, deleted_item);
|
||||
g_object_unref (info->item);
|
||||
g_free (info);
|
||||
}
|
||||
gtk_icon_view_accessible_traverse_items (view, tmp_list);
|
||||
|
||||
return;
|
||||
gtk_icon_view_accessible_traverse_items (self, tmp_list);
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_icon_view_accessible_item_compare (GtkIconViewItemAccessibleInfo *i1,
|
||||
GtkIconViewItemAccessibleInfo *i2)
|
||||
gtk_icon_view_accessible_item_compare (ItemAccessibleInfo *i1,
|
||||
ItemAccessibleInfo *i2)
|
||||
{
|
||||
return i1->index - i2->index;
|
||||
}
|
||||
@@ -1166,151 +1160,138 @@ gtk_icon_view_accessible_model_rows_reordered (GtkTreeModel *tree_model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
gint *new_order,
|
||||
gpointer user_data)
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkIconViewAccessible *view;
|
||||
GtkIconViewItemAccessibleInfo *info;
|
||||
GtkIconViewAccessible *self = user_data;
|
||||
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
|
||||
GtkIconView *icon_view;
|
||||
GtkIconViewItemAccessible *item;
|
||||
GList *items;
|
||||
AtkObject *atk_obj;
|
||||
gint *order;
|
||||
gint length, i;
|
||||
|
||||
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
|
||||
icon_view = GTK_ICON_VIEW (user_data);
|
||||
view = (GtkIconViewAccessible*)atk_obj;
|
||||
int *order;
|
||||
int length, i;
|
||||
|
||||
icon_view = GTK_ICON_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (self)));
|
||||
length = gtk_tree_model_iter_n_children (tree_model, NULL);
|
||||
|
||||
order = g_new (gint, length);
|
||||
order = g_new (int, length);
|
||||
for (i = 0; i < length; i++)
|
||||
order [new_order[i]] = i;
|
||||
|
||||
items = view->priv->items;
|
||||
items = priv->items;
|
||||
while (items)
|
||||
{
|
||||
info = items->data;
|
||||
item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
|
||||
ItemAccessibleInfo *info = items->data;
|
||||
GtkIconViewItemAccessible *item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
|
||||
GList *next = items->next;
|
||||
|
||||
info->index = order[info->index];
|
||||
item->item = g_list_nth_data (icon_view->priv->items, info->index);
|
||||
items = items->next;
|
||||
|
||||
items = next;
|
||||
}
|
||||
|
||||
g_free (order);
|
||||
view->priv->items = g_list_sort (view->priv->items,
|
||||
(GCompareFunc)gtk_icon_view_accessible_item_compare);
|
||||
|
||||
return;
|
||||
priv->items = g_list_sort (priv->items, (GCompareFunc) gtk_icon_view_accessible_item_compare);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_icon_view_accessible_disconnect_model_signals (GtkTreeModel *model,
|
||||
GtkWidget *widget)
|
||||
gtk_icon_view_accessible_disconnect_model_signals (GtkIconViewAccessible *self)
|
||||
{
|
||||
GObject *obj;
|
||||
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
|
||||
|
||||
obj = G_OBJECT (model);
|
||||
g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_row_changed, widget);
|
||||
g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_row_inserted, widget);
|
||||
g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_row_deleted, widget);
|
||||
g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_rows_reordered, widget);
|
||||
g_signal_handlers_disconnect_by_func (priv->model, gtk_icon_view_accessible_model_row_changed, self);
|
||||
g_signal_handlers_disconnect_by_func (priv->model, gtk_icon_view_accessible_model_row_inserted, self);
|
||||
g_signal_handlers_disconnect_by_func (priv->model, gtk_icon_view_accessible_model_row_deleted, self);
|
||||
g_signal_handlers_disconnect_by_func (priv->model, gtk_icon_view_accessible_model_rows_reordered, self);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_icon_view_accessible_connect_model_signals (GtkIconView *icon_view)
|
||||
gtk_icon_view_accessible_connect_model_signals (GtkIconViewAccessible *self)
|
||||
{
|
||||
GObject *obj;
|
||||
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
|
||||
|
||||
obj = G_OBJECT (icon_view->priv->model);
|
||||
g_signal_connect_object (obj, "row-changed",
|
||||
g_signal_connect_object (priv->model, "row-changed",
|
||||
G_CALLBACK (gtk_icon_view_accessible_model_row_changed),
|
||||
icon_view, 0);
|
||||
g_signal_connect_object (obj, "row-inserted",
|
||||
self, 0);
|
||||
g_signal_connect_object (priv->model, "row-inserted",
|
||||
G_CALLBACK (gtk_icon_view_accessible_model_row_inserted),
|
||||
icon_view, G_CONNECT_AFTER);
|
||||
g_signal_connect_object (obj, "row-deleted",
|
||||
self, G_CONNECT_AFTER);
|
||||
g_signal_connect_object (priv->model, "row-deleted",
|
||||
G_CALLBACK (gtk_icon_view_accessible_model_row_deleted),
|
||||
icon_view, G_CONNECT_AFTER);
|
||||
g_signal_connect_object (obj, "rows-reordered",
|
||||
self, G_CONNECT_AFTER);
|
||||
g_signal_connect_object (priv->model, "rows-reordered",
|
||||
G_CALLBACK (gtk_icon_view_accessible_model_rows_reordered),
|
||||
icon_view, G_CONNECT_AFTER);
|
||||
self, G_CONNECT_AFTER);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_icon_view_accessible_clear_cache (GtkIconViewAccessible *view)
|
||||
gtk_icon_view_accessible_clear_cache (GtkIconViewAccessible *self)
|
||||
{
|
||||
GtkIconViewItemAccessibleInfo *info;
|
||||
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
|
||||
GList *items;
|
||||
|
||||
items = view->priv->items;
|
||||
while (items)
|
||||
if (priv->items == NULL)
|
||||
return;
|
||||
|
||||
items = priv->items;
|
||||
while (items != NULL)
|
||||
{
|
||||
info = (GtkIconViewItemAccessibleInfo *) items->data;
|
||||
gtk_icon_view_item_accessible_add_state (GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item), ATK_STATE_DEFUNCT, TRUE);
|
||||
ItemAccessibleInfo *info = items->data;
|
||||
GList *next = items->next;
|
||||
|
||||
gtk_icon_view_item_accessible_add_state (GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item),
|
||||
ATK_STATE_DEFUNCT,
|
||||
TRUE);
|
||||
g_object_unref (info->item);
|
||||
g_free (items->data);
|
||||
items = items->next;
|
||||
g_free (info);
|
||||
|
||||
items = next;
|
||||
}
|
||||
g_list_free (view->priv->items);
|
||||
view->priv->items = NULL;
|
||||
|
||||
g_clear_pointer (&priv->items, g_list_free);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_icon_view_accessible_notify_gtk (GObject *obj,
|
||||
GParamSpec *pspec)
|
||||
void
|
||||
gtk_icon_view_accessible_update_model (GtkIconViewAccessible *self,
|
||||
GtkTreeModel *model)
|
||||
{
|
||||
GtkIconView *icon_view;
|
||||
GtkWidget *widget;
|
||||
AtkObject *atk_obj;
|
||||
GtkIconViewAccessible *view;
|
||||
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
|
||||
|
||||
if (strcmp (pspec->name, "model") == 0)
|
||||
if (priv->model != NULL)
|
||||
{
|
||||
widget = GTK_WIDGET (obj);
|
||||
atk_obj = gtk_widget_get_accessible (widget);
|
||||
view = (GtkIconViewAccessible*)atk_obj;
|
||||
if (view->priv->model)
|
||||
{
|
||||
g_object_remove_weak_pointer (G_OBJECT (view->priv->model),
|
||||
(gpointer *)&view->priv->model);
|
||||
gtk_icon_view_accessible_disconnect_model_signals (view->priv->model, widget);
|
||||
}
|
||||
gtk_icon_view_accessible_clear_cache (view);
|
||||
|
||||
icon_view = GTK_ICON_VIEW (obj);
|
||||
view->priv->model = icon_view->priv->model;
|
||||
/* If there is no model the GtkIconView is probably being destroyed */
|
||||
if (view->priv->model)
|
||||
{
|
||||
g_object_add_weak_pointer (G_OBJECT (view->priv->model), (gpointer *)&view->priv->model);
|
||||
gtk_icon_view_accessible_connect_model_signals (icon_view);
|
||||
}
|
||||
g_object_remove_weak_pointer (G_OBJECT (priv->model),
|
||||
(gpointer *) &priv->model);
|
||||
gtk_icon_view_accessible_disconnect_model_signals (self);
|
||||
}
|
||||
|
||||
return;
|
||||
gtk_icon_view_accessible_clear_cache (self);
|
||||
|
||||
priv->model = model;
|
||||
|
||||
/* If there is no model the GtkIconView is probably being destroyed */
|
||||
if (priv->model != NULL)
|
||||
{
|
||||
g_object_add_weak_pointer (G_OBJECT (priv->model), (gpointer *) &priv->model);
|
||||
gtk_icon_view_accessible_connect_model_signals (self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_icon_view_accessible_initialize (AtkObject *accessible,
|
||||
gpointer data)
|
||||
{
|
||||
GtkIconViewAccessible *view;
|
||||
GtkIconView *icon_view;
|
||||
GtkIconViewAccessible *self = GTK_ICON_VIEW_ACCESSIBLE (accessible);
|
||||
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
|
||||
GtkIconView *icon_view = data;
|
||||
|
||||
if (ATK_OBJECT_CLASS (gtk_icon_view_accessible_parent_class)->initialize)
|
||||
ATK_OBJECT_CLASS (gtk_icon_view_accessible_parent_class)->initialize (accessible, data);
|
||||
|
||||
icon_view = (GtkIconView*)data;
|
||||
view = (GtkIconViewAccessible*)accessible;
|
||||
|
||||
g_signal_connect (data, "notify",
|
||||
G_CALLBACK (gtk_icon_view_accessible_notify_gtk), NULL);
|
||||
|
||||
view->priv->model = icon_view->priv->model;
|
||||
if (view->priv->model)
|
||||
priv->model = icon_view->priv->model;
|
||||
if (priv->model)
|
||||
{
|
||||
g_object_add_weak_pointer (G_OBJECT (view->priv->model), (gpointer *)&view->priv->model);
|
||||
gtk_icon_view_accessible_connect_model_signals (icon_view);
|
||||
g_object_add_weak_pointer (G_OBJECT (priv->model), (gpointer *) &priv->model);
|
||||
gtk_icon_view_accessible_connect_model_signals (self);
|
||||
}
|
||||
|
||||
accessible->role = ATK_ROLE_LAYERED_PANE;
|
||||
@@ -1319,7 +1300,7 @@ gtk_icon_view_accessible_initialize (AtkObject *accessible,
|
||||
static void
|
||||
gtk_icon_view_accessible_finalize (GObject *object)
|
||||
{
|
||||
GtkIconViewAccessible *view = (GtkIconViewAccessible*)object;
|
||||
GtkIconViewAccessible *view = GTK_ICON_VIEW_ACCESSIBLE (object);
|
||||
|
||||
gtk_icon_view_accessible_clear_cache (view);
|
||||
|
||||
@@ -1329,11 +1310,8 @@ gtk_icon_view_accessible_finalize (GObject *object)
|
||||
static void
|
||||
gtk_icon_view_accessible_class_init (GtkIconViewAccessibleClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
AtkObjectClass *atk_class;
|
||||
|
||||
gobject_class = (GObjectClass *)klass;
|
||||
atk_class = (AtkObjectClass *)klass;
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = gtk_icon_view_accessible_finalize;
|
||||
|
||||
@@ -1345,7 +1323,6 @@ gtk_icon_view_accessible_class_init (GtkIconViewAccessibleClass *klass)
|
||||
static void
|
||||
gtk_icon_view_accessible_init (GtkIconViewAccessible *accessible)
|
||||
{
|
||||
accessible->priv = gtk_icon_view_accessible_get_instance_private (accessible);
|
||||
}
|
||||
|
||||
static AtkObject*
|
||||
|
||||
@@ -35,13 +35,10 @@ G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkIconViewAccessible GtkIconViewAccessible;
|
||||
typedef struct _GtkIconViewAccessibleClass GtkIconViewAccessibleClass;
|
||||
typedef struct _GtkIconViewAccessiblePrivate GtkIconViewAccessiblePrivate;
|
||||
|
||||
struct _GtkIconViewAccessible
|
||||
{
|
||||
GtkWidgetAccessible parent;
|
||||
|
||||
GtkIconViewAccessiblePrivate *priv;
|
||||
};
|
||||
|
||||
struct _GtkIconViewAccessibleClass
|
||||
|
||||
@@ -19,12 +19,14 @@
|
||||
#define __GTK_ICON_VIEW_ACCESSIBLE_PRIVATE_H__
|
||||
|
||||
#include <gtk/a11y/gtkiconviewaccessible.h>
|
||||
|
||||
#include <gtk/gtkiconview.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void _gtk_icon_view_accessible_adjustment_changed (GtkIconView *icon_view);
|
||||
void gtk_icon_view_accessible_adjustment_changed (GtkIconViewAccessible *self);
|
||||
|
||||
void gtk_icon_view_accessible_update_model (GtkIconViewAccessible *self,
|
||||
GtkTreeModel *model);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -18,10 +18,11 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtklevelbaraccessible.h"
|
||||
|
||||
#include "gtklevelbar.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static void atk_value_interface_init (AtkValueIface *iface);
|
||||
|
||||
@@ -29,45 +30,36 @@ G_DEFINE_TYPE_WITH_CODE (GtkLevelBarAccessible, gtk_level_bar_accessible, GTK_TY
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_VALUE, atk_value_interface_init))
|
||||
|
||||
static void
|
||||
gtk_level_bar_accessible_initialize (AtkObject *obj,
|
||||
gpointer data)
|
||||
on_value_changed (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
ATK_OBJECT_CLASS (gtk_level_bar_accessible_parent_class)->initialize (obj, data);
|
||||
GtkLevelBarAccessible *self = user_data;
|
||||
|
||||
obj->role = ATK_ROLE_LEVEL_BAR;
|
||||
g_object_notify (G_OBJECT (self), "accessible-value");
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_level_bar_accessible_notify_gtk (GObject *obj,
|
||||
GParamSpec *pspec)
|
||||
gtk_level_bar_accessible_initialize (AtkObject *object,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (obj);
|
||||
GtkLevelBarAccessible *level_bar = GTK_LEVEL_BAR_ACCESSIBLE (gtk_widget_get_accessible (widget));
|
||||
GtkLevelBar *level_bar = data;
|
||||
|
||||
if (strcmp (pspec->name, "value") == 0)
|
||||
{
|
||||
g_object_notify (G_OBJECT (level_bar), "accessible-value");
|
||||
}
|
||||
else
|
||||
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_level_bar_accessible_parent_class)->notify_gtk (obj, pspec);
|
||||
g_signal_connect (level_bar, "notify::value", G_CALLBACK (on_value_changed), object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
gtk_level_bar_accessible_class_init (GtkLevelBarAccessibleClass *klass)
|
||||
{
|
||||
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
||||
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
|
||||
AtkObjectClass *object_class = ATK_OBJECT_CLASS (klass);
|
||||
|
||||
widget_class->notify_gtk = gtk_level_bar_accessible_notify_gtk;
|
||||
|
||||
class->initialize = gtk_level_bar_accessible_initialize;
|
||||
object_class->initialize = gtk_level_bar_accessible_initialize;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_level_bar_accessible_init (GtkLevelBarAccessible *button)
|
||||
gtk_level_bar_accessible_init (GtkLevelBarAccessible *self)
|
||||
{
|
||||
ATK_OBJECT (self)->role = ATK_ROLE_LEVEL_BAR;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtknotebookaccessible.h"
|
||||
#include "gtknotebookaccessibleprivate.h"
|
||||
|
||||
#include "gtknotebookpageaccessible.h"
|
||||
#include "gtknotebook.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
struct _GtkNotebookAccessiblePrivate
|
||||
{
|
||||
@@ -153,55 +155,41 @@ gtk_notebook_accessible_ref_child (AtkObject *obj,
|
||||
return child;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_notebook_accessible_notify_gtk (GObject *obj,
|
||||
GParamSpec *pspec)
|
||||
void
|
||||
gtk_notebook_accessible_update_page (GtkNotebookAccessible *self,
|
||||
int page_num)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
AtkObject* atk_obj;
|
||||
GtkNotebookAccessiblePrivate *priv = gtk_notebook_accessible_get_instance_private (self);
|
||||
AtkObject *atk_obj = ATK_OBJECT (self);
|
||||
int old_page_num = priv->selected_page;
|
||||
|
||||
widget = GTK_WIDGET (obj);
|
||||
atk_obj = gtk_widget_get_accessible (widget);
|
||||
priv->selected_page = page_num;
|
||||
|
||||
if (strcmp (pspec->name, "page") == 0)
|
||||
/* Notify SELECTED state change for old and new page */
|
||||
if (page_num != old_page_num)
|
||||
{
|
||||
gint page_num, old_page_num;
|
||||
GtkNotebookAccessible *accessible;
|
||||
GtkNotebook *notebook;
|
||||
AtkObject *child;
|
||||
|
||||
accessible = GTK_NOTEBOOK_ACCESSIBLE (atk_obj);
|
||||
notebook = GTK_NOTEBOOK (widget);
|
||||
|
||||
/* Notify SELECTED state change for old and new page */
|
||||
old_page_num = accessible->priv->selected_page;
|
||||
page_num = gtk_notebook_get_current_page (notebook);
|
||||
accessible->priv->selected_page = page_num;
|
||||
|
||||
if (page_num != old_page_num)
|
||||
if (old_page_num != -1)
|
||||
{
|
||||
AtkObject *child;
|
||||
|
||||
if (old_page_num != -1)
|
||||
child = gtk_notebook_accessible_ref_child (atk_obj, old_page_num);
|
||||
if (child != NULL)
|
||||
{
|
||||
child = gtk_notebook_accessible_ref_child (atk_obj, old_page_num);
|
||||
if (child)
|
||||
{
|
||||
atk_object_notify_state_change (child, ATK_STATE_SELECTED, FALSE);
|
||||
g_object_unref (child);
|
||||
}
|
||||
}
|
||||
child = gtk_notebook_accessible_ref_child (atk_obj, page_num);
|
||||
if (child)
|
||||
{
|
||||
atk_object_notify_state_change (child, ATK_STATE_SELECTED, TRUE);
|
||||
atk_object_notify_state_change (child, ATK_STATE_SELECTED, FALSE);
|
||||
g_object_unref (child);
|
||||
}
|
||||
g_signal_emit_by_name (atk_obj, "selection-changed");
|
||||
g_signal_emit_by_name (atk_obj, "visible-data-changed");
|
||||
}
|
||||
|
||||
child = gtk_notebook_accessible_ref_child (atk_obj, page_num);
|
||||
if (child != NULL)
|
||||
{
|
||||
atk_object_notify_state_change (child, ATK_STATE_SELECTED, TRUE);
|
||||
g_object_unref (child);
|
||||
}
|
||||
|
||||
g_signal_emit_by_name (atk_obj, "selection-changed");
|
||||
g_signal_emit_by_name (atk_obj, "visible-data-changed");
|
||||
}
|
||||
else
|
||||
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_notebook_accessible_parent_class)->notify_gtk (obj, pspec);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -230,14 +218,11 @@ gtk_notebook_accessible_class_init (GtkNotebookAccessibleClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
||||
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
|
||||
|
||||
gobject_class->finalize = gtk_notebook_accessible_finalize;
|
||||
|
||||
class->ref_child = gtk_notebook_accessible_ref_child;
|
||||
class->initialize = gtk_notebook_accessible_initialize;
|
||||
|
||||
widget_class->notify_gtk = gtk_notebook_accessible_notify_gtk;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
30
gtk/a11y/gtknotebookaccessibleprivate.h
Normal file
30
gtk/a11y/gtknotebookaccessibleprivate.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/* gtknotebookaccessibleprivate.h: GtkNotebookAccessible private API
|
||||
*
|
||||
* Copyright 2020 GNOME Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gtknotebookaccessible.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gtk_notebook_accessible_update_page (GtkNotebookAccessible *self,
|
||||
int page_num);
|
||||
|
||||
G_END_DECLS
|
||||
654
gtk/a11y/gtkpasswordentryaccessible.c
Normal file
654
gtk/a11y/gtkpasswordentryaccessible.c
Normal file
@@ -0,0 +1,654 @@
|
||||
/* gtkpasswordentryaccessible.c: A GtkWidgetAccessible for GtkPasswordEntry
|
||||
*
|
||||
* Copyright 2020 GNOME Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkpasswordentryaccessibleprivate.h"
|
||||
|
||||
#include "gtkeditable.h"
|
||||
#include "gtkimage.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtklabel.h"
|
||||
#include "gtkpango.h"
|
||||
#include "gtkpasswordentryprivate.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtktextprivate.h"
|
||||
|
||||
struct _GtkPasswordEntryAccessible
|
||||
{
|
||||
GtkWidgetAccessible parent_instance;
|
||||
|
||||
int cursor_position;
|
||||
int selection_bound;
|
||||
};
|
||||
|
||||
static void atk_editable_text_interface_init (AtkEditableTextIface *iface);
|
||||
static void atk_text_interface_init (AtkTextIface *iface);
|
||||
static void atk_action_interface_init (AtkActionIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkPasswordEntryAccessible, gtk_password_entry_accessible, GTK_TYPE_WIDGET_ACCESSIBLE,
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_EDITABLE_TEXT, atk_editable_text_interface_init)
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init)
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init))
|
||||
|
||||
static inline GtkText *
|
||||
get_text_widget (GtkAccessible *accessible)
|
||||
{
|
||||
GtkWidget *widget = gtk_accessible_get_widget (accessible);
|
||||
|
||||
if (widget == NULL)
|
||||
return NULL;
|
||||
|
||||
GtkPasswordEntry *entry = GTK_PASSWORD_ENTRY (widget);
|
||||
|
||||
return gtk_password_entry_get_text_widget (entry);
|
||||
}
|
||||
|
||||
static gunichar
|
||||
gtk_password_entry_accessible_get_character_at_offset (AtkText *atk_text,
|
||||
gint offset)
|
||||
{
|
||||
GtkText *text = get_text_widget (GTK_ACCESSIBLE (atk_text));
|
||||
char *contents, *index;
|
||||
gunichar result;
|
||||
|
||||
result = '\0';
|
||||
|
||||
text = get_text_widget (GTK_ACCESSIBLE (atk_text));
|
||||
if (text == NULL)
|
||||
return 0;
|
||||
|
||||
if (!gtk_text_get_visibility (text))
|
||||
return result;
|
||||
|
||||
contents = gtk_text_get_display_text (text, 0, -1);
|
||||
if (offset < g_utf8_strlen (contents, -1))
|
||||
{
|
||||
index = g_utf8_offset_to_pointer (contents, offset);
|
||||
result = g_utf8_get_char (index);
|
||||
g_free (contents);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_password_entry_accessible_get_caret_offset (AtkText *atk_text)
|
||||
{
|
||||
GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
|
||||
|
||||
if (widget == NULL)
|
||||
return -1;
|
||||
|
||||
int cursor_position = 0;
|
||||
gboolean result = gtk_editable_get_selection_bounds (GTK_EDITABLE (widget), NULL, &cursor_position);
|
||||
if (!result)
|
||||
return -1;
|
||||
|
||||
return cursor_position;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_password_entry_accessible_set_caret_offset (AtkText *atk_text,
|
||||
gint offset)
|
||||
{
|
||||
GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
|
||||
if (widget == NULL)
|
||||
return FALSE;
|
||||
|
||||
gtk_editable_set_position (GTK_EDITABLE (widget), offset);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_password_entry_accessible_get_character_count (AtkText *atk_text)
|
||||
{
|
||||
GtkText *text = get_text_widget (GTK_ACCESSIBLE (atk_text));
|
||||
if (text == NULL)
|
||||
return 0;
|
||||
|
||||
char *display_text = gtk_text_get_display_text (text, 0, -1);
|
||||
|
||||
int char_count = 0;
|
||||
if (display_text)
|
||||
{
|
||||
char_count = g_utf8_strlen (display_text, -1);
|
||||
g_free (display_text);
|
||||
}
|
||||
|
||||
return char_count;
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_password_entry_accessible_get_offset_at_point (AtkText *atk_text,
|
||||
gint x,
|
||||
gint y,
|
||||
AtkCoordType coords)
|
||||
{
|
||||
GtkText *text = get_text_widget (GTK_ACCESSIBLE (atk_text));
|
||||
int index, x_layout, y_layout;
|
||||
int x_local, y_local;
|
||||
glong offset;
|
||||
|
||||
if (text == NULL)
|
||||
return 1;
|
||||
|
||||
gtk_text_get_layout_offsets (text, &x_layout, &y_layout);
|
||||
|
||||
x_local = x - x_layout;
|
||||
y_local = y - y_layout;
|
||||
|
||||
if (!pango_layout_xy_to_index (gtk_text_get_layout (text),
|
||||
x_local * PANGO_SCALE,
|
||||
y_local * PANGO_SCALE,
|
||||
&index, NULL))
|
||||
{
|
||||
if (x_local < 0 || y_local < 0)
|
||||
index = 0;
|
||||
else
|
||||
index = -1;
|
||||
}
|
||||
|
||||
offset = -1;
|
||||
if (index != -1)
|
||||
{
|
||||
char *entry_text = gtk_text_get_display_text (text, 0, -1);
|
||||
offset = g_utf8_pointer_to_offset (entry_text, entry_text + index);
|
||||
g_free (entry_text);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static void
|
||||
atk_text_interface_init (AtkTextIface *iface)
|
||||
{
|
||||
iface->get_character_at_offset = gtk_password_entry_accessible_get_character_at_offset;
|
||||
iface->get_caret_offset = gtk_password_entry_accessible_get_caret_offset;
|
||||
iface->set_caret_offset = gtk_password_entry_accessible_set_caret_offset;
|
||||
iface->get_character_count = gtk_password_entry_accessible_get_character_count;
|
||||
iface->get_offset_at_point = gtk_password_entry_accessible_get_offset_at_point;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_password_entry_accessible_set_text_contents (AtkEditableText *text,
|
||||
const gchar *string)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
|
||||
if (widget == NULL)
|
||||
return;
|
||||
|
||||
if (!gtk_editable_get_editable (GTK_EDITABLE (widget)))
|
||||
return;
|
||||
|
||||
gtk_editable_set_text (GTK_EDITABLE (widget), string);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_password_entry_accessible_insert_text (AtkEditableText *text,
|
||||
const gchar *string,
|
||||
gint length,
|
||||
gint *position)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkEditable *editable;
|
||||
int pos = 0;
|
||||
|
||||
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
|
||||
if (widget == NULL)
|
||||
return;
|
||||
|
||||
editable = GTK_EDITABLE (widget);
|
||||
if (!gtk_editable_get_editable (editable))
|
||||
return;
|
||||
|
||||
if (position != NULL)
|
||||
pos = *position;
|
||||
|
||||
gtk_editable_insert_text (editable, string, length, &pos);
|
||||
gtk_editable_set_position (editable, pos);
|
||||
|
||||
if (position != NULL)
|
||||
*position = pos;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_password_entry_accessible_delete_text (AtkEditableText *text,
|
||||
gint start_pos,
|
||||
gint end_pos)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkEditable *editable;
|
||||
|
||||
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
|
||||
if (widget == NULL)
|
||||
return;
|
||||
|
||||
editable = GTK_EDITABLE (widget);
|
||||
if (!gtk_editable_get_editable (editable))
|
||||
return;
|
||||
|
||||
gtk_editable_delete_text (editable, start_pos, end_pos);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkEditable *entry;
|
||||
int position;
|
||||
} PasteData;
|
||||
|
||||
static void
|
||||
paste_received_cb (GObject *clipboard,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
PasteData *paste = data;
|
||||
char *text;
|
||||
|
||||
text = gdk_clipboard_read_text_finish (GDK_CLIPBOARD (clipboard), result, NULL);
|
||||
if (text != NULL)
|
||||
gtk_editable_insert_text (paste->entry,
|
||||
text, -1,
|
||||
&(paste->position));
|
||||
|
||||
g_object_unref (paste->entry);
|
||||
g_free (paste);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_password_entry_accessible_paste_text (AtkEditableText *text,
|
||||
gint position)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkEditable *editable;
|
||||
PasteData *paste;
|
||||
GdkClipboard *clipboard;
|
||||
|
||||
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
|
||||
if (widget == NULL)
|
||||
return;
|
||||
|
||||
editable = GTK_EDITABLE (widget);
|
||||
if (!gtk_editable_get_editable (editable))
|
||||
return;
|
||||
|
||||
paste = g_new0 (PasteData, 1);
|
||||
paste->entry = GTK_EDITABLE (widget);
|
||||
paste->position = position;
|
||||
|
||||
g_object_ref (paste->entry);
|
||||
clipboard = gtk_widget_get_clipboard (widget);
|
||||
gdk_clipboard_read_text_async (clipboard, NULL, paste_received_cb, paste);
|
||||
}
|
||||
|
||||
static void
|
||||
atk_editable_text_interface_init (AtkEditableTextIface *iface)
|
||||
{
|
||||
iface->set_text_contents = gtk_password_entry_accessible_set_text_contents;
|
||||
iface->insert_text = gtk_password_entry_accessible_insert_text;
|
||||
iface->copy_text = NULL;
|
||||
iface->cut_text = NULL;
|
||||
iface->delete_text = gtk_password_entry_accessible_delete_text;
|
||||
iface->paste_text = gtk_password_entry_accessible_paste_text;
|
||||
iface->set_run_attributes = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_password_entry_accessible_do_action (AtkAction *action,
|
||||
gint i)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
|
||||
if (widget == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!gtk_widget_get_sensitive (widget) || !gtk_widget_get_visible (widget))
|
||||
return FALSE;
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
gtk_widget_activate (widget);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (i == 1)
|
||||
{
|
||||
GtkText *text = get_text_widget (GTK_ACCESSIBLE (action));
|
||||
|
||||
gboolean visibility = gtk_text_get_visibility (text);
|
||||
gtk_text_set_visibility (text, !visibility);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_password_entry_accessible_get_n_actions (AtkAction *action)
|
||||
{
|
||||
GtkAccessible *accessible = GTK_ACCESSIBLE (action);
|
||||
|
||||
GtkWidget *widget = gtk_accessible_get_widget (accessible);
|
||||
if (widget == NULL)
|
||||
return 0;
|
||||
|
||||
int n_actions = 1;
|
||||
if (gtk_password_entry_get_show_peek_icon (GTK_PASSWORD_ENTRY (widget)))
|
||||
n_actions += 1;
|
||||
|
||||
return n_actions;
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
gtk_password_entry_accessible_get_keybinding (AtkAction *action,
|
||||
gint i)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkWidget *label;
|
||||
AtkRelationSet *set;
|
||||
AtkRelation *relation;
|
||||
GPtrArray *target;
|
||||
gpointer target_object;
|
||||
guint key_val;
|
||||
|
||||
if (i != 0)
|
||||
return NULL;
|
||||
|
||||
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
|
||||
if (widget == NULL)
|
||||
return NULL;
|
||||
|
||||
set = atk_object_ref_relation_set (ATK_OBJECT (action));
|
||||
if (!set)
|
||||
return NULL;
|
||||
|
||||
label = NULL;
|
||||
relation = atk_relation_set_get_relation_by_type (set, ATK_RELATION_LABELLED_BY);
|
||||
if (relation)
|
||||
{
|
||||
target = atk_relation_get_target (relation);
|
||||
|
||||
target_object = g_ptr_array_index (target, 0);
|
||||
label = gtk_accessible_get_widget (GTK_ACCESSIBLE (target_object));
|
||||
}
|
||||
|
||||
g_object_unref (set);
|
||||
|
||||
if (GTK_IS_LABEL (label))
|
||||
{
|
||||
key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
|
||||
if (key_val != GDK_KEY_VoidSymbol)
|
||||
return gtk_accelerator_name (key_val, GDK_ALT_MASK);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
gtk_password_entry_accessible_action_get_name (AtkAction *action,
|
||||
gint i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
return "activate";
|
||||
|
||||
case 1:
|
||||
return "peek";
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const gchar*
|
||||
gtk_password_entry_accessible_action_get_localized_name (AtkAction *action,
|
||||
gint i)
|
||||
{
|
||||
if (i == 0)
|
||||
return C_("Action name", "Activate");
|
||||
if (i == 1)
|
||||
return C_("Action name", "Peek");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
gtk_password_entry_accessible_action_get_description (AtkAction *action,
|
||||
gint i)
|
||||
{
|
||||
if (i == 0)
|
||||
return C_("Action description", "Activates the entry");
|
||||
|
||||
if (i == 1)
|
||||
return C_("Action description", "Reveals the contents the entry");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
atk_action_interface_init (AtkActionIface *iface)
|
||||
{
|
||||
iface->do_action = gtk_password_entry_accessible_do_action;
|
||||
iface->get_n_actions = gtk_password_entry_accessible_get_n_actions;
|
||||
iface->get_keybinding = gtk_password_entry_accessible_get_keybinding;
|
||||
iface->get_name = gtk_password_entry_accessible_action_get_name;
|
||||
iface->get_localized_name = gtk_password_entry_accessible_action_get_localized_name;
|
||||
iface->get_description = gtk_password_entry_accessible_action_get_description;
|
||||
}
|
||||
|
||||
static AtkAttributeSet *
|
||||
gtk_password_entry_accessible_get_attributes (AtkObject *accessible)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
AtkAttributeSet *attributes;
|
||||
AtkAttribute *placeholder_text;
|
||||
char *text = NULL;
|
||||
|
||||
attributes = ATK_OBJECT_CLASS (gtk_password_entry_accessible_parent_class)->get_attributes (accessible);
|
||||
|
||||
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
|
||||
if (widget == NULL)
|
||||
return attributes;
|
||||
|
||||
g_object_get (widget, "placeholder-text", &text, NULL);
|
||||
if (text == NULL)
|
||||
return attributes;
|
||||
|
||||
placeholder_text = g_malloc (sizeof (AtkAttribute));
|
||||
placeholder_text->name = g_strdup ("placeholder-text");
|
||||
placeholder_text->value = text;
|
||||
|
||||
attributes = g_slist_append (attributes, placeholder_text);
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_for_selection_change (GtkPasswordEntryAccessible *self,
|
||||
GtkEditable *editable)
|
||||
{
|
||||
gboolean ret_val = FALSE;
|
||||
gint start, end;
|
||||
|
||||
if (gtk_editable_get_selection_bounds (editable, &start, &end))
|
||||
{
|
||||
if (end != self->cursor_position ||
|
||||
start != self->selection_bound)
|
||||
/*
|
||||
* This check is here as this function can be called
|
||||
* for notification of selection_bound and current_pos.
|
||||
* The values of current_pos and selection_bound may be the same
|
||||
* for both notifications and we only want to generate one
|
||||
* text_selection_changed signal.
|
||||
*/
|
||||
ret_val = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We had a selection */
|
||||
ret_val = (self->cursor_position != self->selection_bound);
|
||||
}
|
||||
|
||||
self->cursor_position = end;
|
||||
self->selection_bound = start;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static void
|
||||
on_cursor_position_changed (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
GtkPasswordEntryAccessible *self = data;
|
||||
GtkEditable *editable = GTK_EDITABLE (gobject);
|
||||
|
||||
if (check_for_selection_change (self, editable))
|
||||
g_signal_emit_by_name (self, "text-selection-changed");
|
||||
|
||||
// The entry cursor position has moved so generate the signal
|
||||
g_signal_emit_by_name (self, "text-caret-moved",
|
||||
gtk_editable_get_position (editable));
|
||||
}
|
||||
|
||||
static void
|
||||
on_selection_bound_changed (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
GtkPasswordEntryAccessible *self = data;
|
||||
GtkEditable *editable = GTK_EDITABLE (gobject);
|
||||
|
||||
if (check_for_selection_change (self, editable))
|
||||
g_signal_emit_by_name (self, "text-selection-changed");
|
||||
}
|
||||
|
||||
static void
|
||||
insert_text_cb (GtkEditable *editable,
|
||||
gchar *new_text,
|
||||
gint new_text_length,
|
||||
gint *position,
|
||||
GtkPasswordEntryAccessible *self)
|
||||
{
|
||||
int length;
|
||||
|
||||
if (new_text_length == 0)
|
||||
return;
|
||||
|
||||
length = g_utf8_strlen (new_text, new_text_length);
|
||||
|
||||
g_signal_emit_by_name (self,
|
||||
"text-changed::insert",
|
||||
*position - length,
|
||||
length);
|
||||
}
|
||||
|
||||
static void
|
||||
delete_text_cb (GtkEditable *editable,
|
||||
gint start,
|
||||
gint end,
|
||||
GtkPasswordEntryAccessible *self)
|
||||
{
|
||||
GtkText *text;
|
||||
|
||||
text = get_text_widget (GTK_ACCESSIBLE (self));
|
||||
if (text == NULL)
|
||||
return;
|
||||
|
||||
if (end < 0)
|
||||
{
|
||||
char *contents;
|
||||
|
||||
contents = gtk_text_get_display_text (text, 0, -1);
|
||||
end = g_utf8_strlen (contents, -1);
|
||||
|
||||
g_free (contents);
|
||||
}
|
||||
|
||||
if (end == start)
|
||||
return;
|
||||
|
||||
g_signal_emit_by_name (self,
|
||||
"text-changed::delete",
|
||||
start,
|
||||
end - start);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_password_entry_accessible_initialize (AtkObject *atk_object,
|
||||
gpointer data)
|
||||
{
|
||||
GtkPasswordEntryAccessible *self = GTK_PASSWORD_ENTRY_ACCESSIBLE (atk_object);
|
||||
GtkEditable *editable = data;
|
||||
GtkWidget *widget = data;
|
||||
int start_pos, end_pos;
|
||||
|
||||
gtk_editable_get_selection_bounds (editable, &start_pos, &end_pos);
|
||||
self->cursor_position = end_pos;
|
||||
self->selection_bound = start_pos;
|
||||
|
||||
/* Set up signal callbacks */
|
||||
g_signal_connect_after (widget, "insert-text", G_CALLBACK (insert_text_cb), self);
|
||||
g_signal_connect (widget, "delete-text", G_CALLBACK (delete_text_cb), self);
|
||||
g_signal_connect (widget, "notify::cursor-position",
|
||||
G_CALLBACK (on_cursor_position_changed), self);
|
||||
g_signal_connect (widget, "notify::selection-bound",
|
||||
G_CALLBACK (on_selection_bound_changed), self);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_password_entry_accessible_class_init (GtkPasswordEntryAccessibleClass *klass)
|
||||
{
|
||||
AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
|
||||
|
||||
atk_object_class->initialize = gtk_password_entry_accessible_initialize;
|
||||
atk_object_class->get_attributes = gtk_password_entry_accessible_get_attributes;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_password_entry_accessible_init (GtkPasswordEntryAccessible *self)
|
||||
{
|
||||
AtkObject *atk_obj = ATK_OBJECT (self);
|
||||
|
||||
atk_obj->role = ATK_ROLE_PASSWORD_TEXT;
|
||||
atk_object_set_name (atk_obj, _("Password"));
|
||||
}
|
||||
|
||||
void
|
||||
gtk_password_entry_accessible_update_visibility (GtkPasswordEntryAccessible *self)
|
||||
{
|
||||
GtkText *text = get_text_widget (GTK_ACCESSIBLE (self));
|
||||
|
||||
if (text == NULL)
|
||||
return;
|
||||
|
||||
gboolean visibility = gtk_text_get_visibility (text);
|
||||
AtkRole role = visibility ? ATK_ROLE_TEXT : ATK_ROLE_PASSWORD_TEXT;
|
||||
atk_object_set_role (ATK_OBJECT (self), role);
|
||||
}
|
||||
48
gtk/a11y/gtkpasswordentryaccessible.h
Normal file
48
gtk/a11y/gtkpasswordentryaccessible.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* gtkpasswordentryaccessible.h: A GtkWidgetAccessible for GtkPasswordEntry
|
||||
*
|
||||
* Copyright 2020 GNOME Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GTK_A11Y_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk-a11y.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/a11y/gtkentryaccessible.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_PASSWORD_ENTRY_ACCESSIBLE (gtk_password_entry_accessible_get_type())
|
||||
#define GTK_PASSWORD_ENTRY_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PASSWORD_ENTRY_ACCESSIBLE, GtkPasswordEntryAccessible))
|
||||
#define GTK_IS_PASSWORD_ENTRY_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PASSWORD_ENTRY_ACCESSIBLE))
|
||||
|
||||
typedef struct _GtkPasswordEntryAccessible GtkPasswordEntryAccessible;
|
||||
typedef struct _GtkPasswordEntryAccessibleClass GtkPasswordEntryAccessibleClass;
|
||||
|
||||
struct _GtkPasswordEntryAccessibleClass
|
||||
{
|
||||
GtkWidgetAccessibleClass parent_class;
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gtk_password_entry_accessible_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkPasswordEntryAccessible, g_object_unref)
|
||||
|
||||
G_END_DECLS
|
||||
29
gtk/a11y/gtkpasswordentryaccessibleprivate.h
Normal file
29
gtk/a11y/gtkpasswordentryaccessibleprivate.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* gtkpasswordentryaccessibleprivate.h: Private API for GtkPasswordEntryAccessible
|
||||
*
|
||||
* Copyright 2020 GNOME Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gtkpasswordentryaccessible.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gtk_password_entry_accessible_update_visibility (GtkPasswordEntryAccessible *self);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -21,52 +21,28 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gtkprogressbaraccessible.h"
|
||||
|
||||
#include "gtkprogressbaraccessibleprivate.h"
|
||||
|
||||
static void atk_value_interface_init (AtkValueIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkProgressBarAccessible, gtk_progress_bar_accessible, GTK_TYPE_WIDGET_ACCESSIBLE,
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_VALUE, atk_value_interface_init))
|
||||
|
||||
static void
|
||||
gtk_progress_bar_accessible_initialize (AtkObject *obj,
|
||||
gpointer data)
|
||||
void
|
||||
gtk_progress_bar_accessible_update_value (GtkProgressBarAccessible *self)
|
||||
{
|
||||
ATK_OBJECT_CLASS (gtk_progress_bar_accessible_parent_class)->initialize (obj, data);
|
||||
|
||||
obj->role = ATK_ROLE_PROGRESS_BAR;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_progress_bar_accessible_notify_gtk (GObject *obj,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (obj);
|
||||
AtkObject *accessible;
|
||||
|
||||
accessible = gtk_widget_get_accessible (widget);
|
||||
|
||||
if (strcmp (pspec->name, "fraction") == 0)
|
||||
g_object_notify (G_OBJECT (accessible), "accessible-value");
|
||||
else
|
||||
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_progress_bar_accessible_parent_class)->notify_gtk (obj, pspec);
|
||||
g_object_notify (G_OBJECT (self), "accessible-value");
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_progress_bar_accessible_class_init (GtkProgressBarAccessibleClass *klass)
|
||||
{
|
||||
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
||||
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
|
||||
|
||||
widget_class->notify_gtk = gtk_progress_bar_accessible_notify_gtk;
|
||||
|
||||
class->initialize = gtk_progress_bar_accessible_initialize;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_progress_bar_accessible_init (GtkProgressBarAccessible *bar)
|
||||
gtk_progress_bar_accessible_init (GtkProgressBarAccessible *self)
|
||||
{
|
||||
ATK_OBJECT (self)->role = ATK_ROLE_PROGRESS_BAR;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
/* gtkprogressbaraccessibleprivate.h: Private GtkProgressBarAccessible API
|
||||
*
|
||||
* Copyright 2020 GNOME Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
@@ -12,18 +15,15 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_ORIENTABLE_PRIVATE_H__
|
||||
#define __GTK_ORIENTABLE_PRIVATE_H__
|
||||
#pragma once
|
||||
|
||||
#include "gtkorientable.h"
|
||||
#include "gtkprogressbaraccessible.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void _gtk_orientable_set_style_classes (GtkOrientable *orientable);
|
||||
void gtk_progress_bar_accessible_update_value (GtkProgressBarAccessible *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_ORIENTABLE_H__ */
|
||||
@@ -21,10 +21,12 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtkrangeaccessible.h"
|
||||
|
||||
struct _GtkRangeAccessiblePrivate
|
||||
typedef struct
|
||||
{
|
||||
GtkAdjustment *adjustment;
|
||||
};
|
||||
|
||||
gulong value_changed_id;
|
||||
} GtkRangeAccessiblePrivate;
|
||||
|
||||
static void atk_value_interface_init (AtkValueIface *iface);
|
||||
|
||||
@@ -42,35 +44,44 @@ gtk_range_accessible_value_changed (GtkAdjustment *adjustment,
|
||||
static void
|
||||
gtk_range_accessible_widget_set (GtkAccessible *accessible)
|
||||
{
|
||||
GtkRangeAccessiblePrivate *priv = GTK_RANGE_ACCESSIBLE (accessible)->priv;
|
||||
GtkRangeAccessible *self = GTK_RANGE_ACCESSIBLE (accessible);
|
||||
GtkRangeAccessiblePrivate *priv = gtk_range_accessible_get_instance_private (self);
|
||||
GtkWidget *range;
|
||||
GtkAdjustment *adj;
|
||||
|
||||
range = gtk_accessible_get_widget (accessible);
|
||||
adj = gtk_range_get_adjustment (GTK_RANGE (range));
|
||||
if (adj)
|
||||
if (adj != NULL)
|
||||
{
|
||||
priv->adjustment = adj;
|
||||
g_object_ref (priv->adjustment);
|
||||
g_signal_connect (priv->adjustment, "value-changed",
|
||||
G_CALLBACK (gtk_range_accessible_value_changed),
|
||||
accessible);
|
||||
priv->adjustment = g_object_ref (adj);
|
||||
priv->value_changed_id =
|
||||
g_signal_connect (priv->adjustment, "value-changed",
|
||||
G_CALLBACK (gtk_range_accessible_value_changed),
|
||||
self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_range_accessible_widget_unset (GtkAccessible *accessible)
|
||||
{
|
||||
GtkRangeAccessiblePrivate *priv = GTK_RANGE_ACCESSIBLE (accessible)->priv;
|
||||
GtkRangeAccessible *self = GTK_RANGE_ACCESSIBLE (accessible);
|
||||
GtkRangeAccessiblePrivate *priv = gtk_range_accessible_get_instance_private (self);
|
||||
|
||||
if (priv->adjustment)
|
||||
if (priv->adjustment != NULL &&
|
||||
priv->value_changed_id != 0)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (priv->adjustment,
|
||||
G_CALLBACK (gtk_range_accessible_value_changed),
|
||||
accessible);
|
||||
g_object_unref (priv->adjustment);
|
||||
priv->adjustment = NULL;
|
||||
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
|
||||
priv->value_changed_id = 0;
|
||||
}
|
||||
|
||||
g_clear_object (&priv->adjustment);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_range_accessible_update_adjustment (GtkRangeAccessible *self)
|
||||
{
|
||||
gtk_range_accessible_widget_unset (GTK_ACCESSIBLE (self));
|
||||
gtk_range_accessible_widget_set (GTK_ACCESSIBLE (self));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -82,42 +93,40 @@ gtk_range_accessible_initialize (AtkObject *obj,
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_range_accessible_notify_gtk (GObject *obj,
|
||||
GParamSpec *pspec)
|
||||
gtk_range_accessible_dispose (GObject *gobject)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (obj);
|
||||
AtkObject *range;
|
||||
GtkRangeAccessible *self = GTK_RANGE_ACCESSIBLE (gobject);
|
||||
GtkRangeAccessiblePrivate *priv = gtk_range_accessible_get_instance_private (self);
|
||||
|
||||
if (strcmp (pspec->name, "adjustment") == 0)
|
||||
if (priv->adjustment != NULL && priv->value_changed_id != 0)
|
||||
{
|
||||
range = gtk_widget_get_accessible (widget);
|
||||
gtk_range_accessible_widget_unset (GTK_ACCESSIBLE (range));
|
||||
gtk_range_accessible_widget_set (GTK_ACCESSIBLE (range));
|
||||
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
|
||||
priv->value_changed_id = 0;
|
||||
}
|
||||
else
|
||||
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_range_accessible_parent_class)->notify_gtk (obj, pspec);
|
||||
}
|
||||
|
||||
g_clear_object (&priv->adjustment);
|
||||
|
||||
G_OBJECT_CLASS (gtk_range_accessible_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_range_accessible_class_init (GtkRangeAccessibleClass *klass)
|
||||
{
|
||||
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
AtkObjectClass *atkobject_class = ATK_OBJECT_CLASS (klass);
|
||||
GtkAccessibleClass *accessible_class = (GtkAccessibleClass*)klass;
|
||||
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
|
||||
|
||||
class->initialize = gtk_range_accessible_initialize;
|
||||
gobject_class->dispose = gtk_range_accessible_dispose;
|
||||
|
||||
atkobject_class->initialize = gtk_range_accessible_initialize;
|
||||
|
||||
accessible_class->widget_set = gtk_range_accessible_widget_set;
|
||||
accessible_class->widget_unset = gtk_range_accessible_widget_unset;
|
||||
|
||||
widget_class->notify_gtk = gtk_range_accessible_notify_gtk;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_range_accessible_init (GtkRangeAccessible *range)
|
||||
{
|
||||
range->priv = gtk_range_accessible_get_instance_private (range);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -35,13 +35,10 @@ G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkRangeAccessible GtkRangeAccessible;
|
||||
typedef struct _GtkRangeAccessibleClass GtkRangeAccessibleClass;
|
||||
typedef struct _GtkRangeAccessiblePrivate GtkRangeAccessiblePrivate;
|
||||
|
||||
struct _GtkRangeAccessible
|
||||
{
|
||||
GtkWidgetAccessible parent;
|
||||
|
||||
GtkRangeAccessiblePrivate *priv;
|
||||
};
|
||||
|
||||
struct _GtkRangeAccessibleClass
|
||||
@@ -52,6 +49,9 @@ struct _GtkRangeAccessibleClass
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gtk_range_accessible_get_type (void);
|
||||
|
||||
/*< private >*/
|
||||
void gtk_range_accessible_update_adjustment (GtkRangeAccessible *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_RANGE_ACCESSIBLE_H__ */
|
||||
|
||||
@@ -23,79 +23,107 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
GtkAdjustment *adjustment;
|
||||
gulong value_changed_id;
|
||||
} GtkScaleButtonAccessiblePrivate;
|
||||
|
||||
static void atk_action_interface_init (AtkActionIface *iface);
|
||||
static void atk_value_interface_init (AtkValueIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkScaleButtonAccessible, gtk_scale_button_accessible, GTK_TYPE_WIDGET_ACCESSIBLE,
|
||||
G_ADD_PRIVATE (GtkScaleButtonAccessible)
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init)
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_VALUE, atk_value_interface_init));
|
||||
|
||||
static void
|
||||
gtk_scale_button_accessible_value_changed (GtkAdjustment *adjustment,
|
||||
gpointer data)
|
||||
on_value_changed (GtkAdjustment *adjustment,
|
||||
gpointer data)
|
||||
{
|
||||
g_object_notify (G_OBJECT (data), "accessible-value");
|
||||
GtkScaleButtonAccessible *self = data;
|
||||
|
||||
g_object_notify (G_OBJECT (self), "accessible-value");
|
||||
}
|
||||
|
||||
static void
|
||||
on_adjustment_changed (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
GtkScaleButton *scale_button = GTK_SCALE_BUTTON (gobject);
|
||||
GtkScaleButtonAccessible *self = data;
|
||||
GtkScaleButtonAccessiblePrivate *priv =
|
||||
gtk_scale_button_accessible_get_instance_private (self);
|
||||
GtkAdjustment *adjustment =
|
||||
gtk_scale_button_get_adjustment (scale_button);
|
||||
|
||||
if (priv->adjustment == adjustment)
|
||||
return;
|
||||
|
||||
if (priv->adjustment != NULL && priv->value_changed_id != 0)
|
||||
{
|
||||
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
|
||||
priv->value_changed_id = 0;
|
||||
}
|
||||
|
||||
g_clear_object (&priv->adjustment);
|
||||
|
||||
if (adjustment != NULL)
|
||||
{
|
||||
priv->adjustment = g_object_ref (adjustment);
|
||||
priv->value_changed_id =
|
||||
g_signal_connect (priv->adjustment, "notify::value-changed",
|
||||
G_CALLBACK (on_value_changed),
|
||||
self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_scale_button_accessible_initialize (AtkObject *obj,
|
||||
gpointer data)
|
||||
{
|
||||
GtkAdjustment *adjustment;
|
||||
GtkScaleButton *scale_button = data;
|
||||
|
||||
ATK_OBJECT_CLASS (gtk_scale_button_accessible_parent_class)->initialize (obj, data);
|
||||
|
||||
adjustment = gtk_scale_button_get_adjustment (GTK_SCALE_BUTTON (data));
|
||||
if (adjustment)
|
||||
g_signal_connect (adjustment,
|
||||
"value-changed",
|
||||
G_CALLBACK (gtk_scale_button_accessible_value_changed),
|
||||
obj);
|
||||
|
||||
obj->role = ATK_ROLE_SLIDER;
|
||||
g_signal_connect (scale_button, "notify::adjustment",
|
||||
G_CALLBACK (on_adjustment_changed),
|
||||
obj);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_scale_button_accessible_notify_gtk (GObject *obj,
|
||||
GParamSpec *pspec)
|
||||
gtk_scale_button_accessible_dispose (GObject *gobject)
|
||||
{
|
||||
GtkScaleButton *scale_button;
|
||||
GtkScaleButtonAccessible *accessible;
|
||||
GtkScaleButtonAccessible *self = GTK_SCALE_BUTTON_ACCESSIBLE (gobject);
|
||||
GtkScaleButtonAccessiblePrivate *priv =
|
||||
gtk_scale_button_accessible_get_instance_private (self);
|
||||
|
||||
scale_button = GTK_SCALE_BUTTON (obj);
|
||||
accessible = GTK_SCALE_BUTTON_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (scale_button)));
|
||||
|
||||
if (strcmp (pspec->name, "adjustment") == 0)
|
||||
if (priv->adjustment != NULL && priv->value_changed_id != 0)
|
||||
{
|
||||
GtkAdjustment* adjustment;
|
||||
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
|
||||
priv->value_changed_id = 0;
|
||||
}
|
||||
|
||||
adjustment = gtk_scale_button_get_adjustment (scale_button);
|
||||
g_signal_connect (adjustment,
|
||||
"value-changed",
|
||||
G_CALLBACK (gtk_scale_button_accessible_value_changed),
|
||||
accessible);
|
||||
}
|
||||
else
|
||||
{
|
||||
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_scale_button_accessible_parent_class)->notify_gtk (obj, pspec);
|
||||
}
|
||||
g_clear_object (&priv->adjustment);
|
||||
|
||||
G_OBJECT_CLASS (gtk_scale_button_accessible_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_scale_button_accessible_class_init (GtkScaleButtonAccessibleClass *klass)
|
||||
{
|
||||
AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
|
||||
GtkWidgetAccessibleClass *widget_class = GTK_WIDGET_ACCESSIBLE_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = gtk_scale_button_accessible_dispose;
|
||||
|
||||
atk_object_class->initialize = gtk_scale_button_accessible_initialize;
|
||||
|
||||
widget_class->notify_gtk = gtk_scale_button_accessible_notify_gtk;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_scale_button_accessible_init (GtkScaleButtonAccessible *button)
|
||||
gtk_scale_button_accessible_init (GtkScaleButtonAccessible *self)
|
||||
{
|
||||
ATK_OBJECT (self)->role = ATK_ROLE_SLIDER;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
||||
@@ -35,13 +35,10 @@ G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkScaleButtonAccessible GtkScaleButtonAccessible;
|
||||
typedef struct _GtkScaleButtonAccessibleClass GtkScaleButtonAccessibleClass;
|
||||
typedef struct _GtkScaleButtonAccessiblePrivate GtkScaleButtonAccessiblePrivate;
|
||||
|
||||
struct _GtkScaleButtonAccessible
|
||||
{
|
||||
GtkWidgetAccessible parent;
|
||||
|
||||
GtkScaleButtonAccessiblePrivate *priv;
|
||||
};
|
||||
|
||||
struct _GtkScaleButtonAccessibleClass
|
||||
|
||||
@@ -21,10 +21,11 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtkscrollbaraccessible.h"
|
||||
|
||||
struct _GtkScrollbarAccessiblePrivate
|
||||
typedef struct
|
||||
{
|
||||
GtkAdjustment *adjustment;
|
||||
};
|
||||
gulong value_changed_id;
|
||||
} GtkScrollbarAccessiblePrivate;
|
||||
|
||||
static void atk_value_interface_init (AtkValueIface *iface);
|
||||
|
||||
@@ -33,91 +34,93 @@ G_DEFINE_TYPE_WITH_CODE (GtkScrollbarAccessible, gtk_scrollbar_accessible, GTK_T
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_VALUE, atk_value_interface_init))
|
||||
|
||||
static void
|
||||
gtk_scrollbar_accessible_value_changed (GtkAdjustment *adjustment,
|
||||
gpointer data)
|
||||
on_value_changed (GtkAdjustment *adjustment,
|
||||
gpointer data)
|
||||
{
|
||||
g_object_notify (G_OBJECT (data), "accessible-value");
|
||||
GtkScrollbarAccessible *self = data;
|
||||
|
||||
g_object_notify (G_OBJECT (self), "accessible-value");
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_scrollbar_accessible_widget_set (GtkAccessible *accessible)
|
||||
on_adjustment_changed (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
GtkScrollbarAccessiblePrivate *priv = GTK_SCROLLBAR_ACCESSIBLE (accessible)->priv;
|
||||
GtkWidget *scrollbar;
|
||||
GtkAdjustment *adj;
|
||||
GtkScrollbar *scrollbar = GTK_SCROLLBAR (gobject);
|
||||
GtkScrollbarAccessible *self = data;
|
||||
GtkScrollbarAccessiblePrivate *priv =
|
||||
gtk_scrollbar_accessible_get_instance_private (self);
|
||||
GtkAdjustment *adjustment =
|
||||
gtk_scrollbar_get_adjustment (scrollbar);
|
||||
|
||||
scrollbar = gtk_accessible_get_widget (accessible);
|
||||
adj = gtk_scrollbar_get_adjustment (GTK_SCROLLBAR (scrollbar));
|
||||
if (adj)
|
||||
if (priv->adjustment == adjustment)
|
||||
return;
|
||||
|
||||
if (priv->adjustment != NULL && priv->value_changed_id != 0)
|
||||
{
|
||||
priv->adjustment = adj;
|
||||
g_object_ref (priv->adjustment);
|
||||
g_signal_connect (priv->adjustment, "value-changed",
|
||||
G_CALLBACK (gtk_scrollbar_accessible_value_changed),
|
||||
accessible);
|
||||
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
|
||||
priv->value_changed_id = 0;
|
||||
}
|
||||
|
||||
g_clear_object (&priv->adjustment);
|
||||
|
||||
if (adjustment != NULL)
|
||||
{
|
||||
priv->adjustment = g_object_ref (adjustment);
|
||||
priv->value_changed_id =
|
||||
g_signal_connect (priv->adjustment, "value-changed",
|
||||
G_CALLBACK (on_value_changed),
|
||||
self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_scrollbar_accessible_widget_unset (GtkAccessible *accessible)
|
||||
gtk_scrollbar_accessible_dispose (GObject *gobject)
|
||||
{
|
||||
GtkScrollbarAccessiblePrivate *priv = GTK_SCROLLBAR_ACCESSIBLE (accessible)->priv;
|
||||
GtkScrollbarAccessible *self = GTK_SCROLLBAR_ACCESSIBLE (gobject);
|
||||
GtkScrollbarAccessiblePrivate *priv =
|
||||
gtk_scrollbar_accessible_get_instance_private (self);
|
||||
|
||||
if (priv->adjustment)
|
||||
if (priv->adjustment != NULL && priv->value_changed_id != 0)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (priv->adjustment,
|
||||
G_CALLBACK (gtk_scrollbar_accessible_value_changed),
|
||||
accessible);
|
||||
g_object_unref (priv->adjustment);
|
||||
priv->adjustment = NULL;
|
||||
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
|
||||
priv->value_changed_id = 0;
|
||||
}
|
||||
|
||||
g_clear_object (&priv->adjustment);
|
||||
|
||||
G_OBJECT_CLASS (gtk_scrollbar_accessible_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_scrollbar_accessible_initialize (AtkObject *obj,
|
||||
gpointer data)
|
||||
{
|
||||
GtkScrollbar *scrollbar = data;
|
||||
|
||||
ATK_OBJECT_CLASS (gtk_scrollbar_accessible_parent_class)->initialize (obj, data);
|
||||
obj->role = ATK_ROLE_SCROLL_BAR;
|
||||
|
||||
g_signal_connect (scrollbar, "notify::adjustment",
|
||||
G_CALLBACK (on_adjustment_changed),
|
||||
obj);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_scrollbar_accessible_notify_gtk (GObject *obj,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (obj);
|
||||
AtkObject *scrollbar;
|
||||
|
||||
if (strcmp (pspec->name, "adjustment") == 0)
|
||||
{
|
||||
scrollbar = gtk_widget_get_accessible (widget);
|
||||
gtk_scrollbar_accessible_widget_unset (GTK_ACCESSIBLE (scrollbar));
|
||||
gtk_scrollbar_accessible_widget_set (GTK_ACCESSIBLE (scrollbar));
|
||||
}
|
||||
else
|
||||
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_scrollbar_accessible_parent_class)->notify_gtk (obj, pspec);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gtk_scrollbar_accessible_class_init (GtkScrollbarAccessibleClass *klass)
|
||||
{
|
||||
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
||||
GtkAccessibleClass *accessible_class = (GtkAccessibleClass*)klass;
|
||||
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
|
||||
AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
class->initialize = gtk_scrollbar_accessible_initialize;
|
||||
atk_object_class->initialize = gtk_scrollbar_accessible_initialize;
|
||||
|
||||
accessible_class->widget_set = gtk_scrollbar_accessible_widget_set;
|
||||
accessible_class->widget_unset = gtk_scrollbar_accessible_widget_unset;
|
||||
|
||||
widget_class->notify_gtk = gtk_scrollbar_accessible_notify_gtk;
|
||||
gobject_class->dispose = gtk_scrollbar_accessible_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_scrollbar_accessible_init (GtkScrollbarAccessible *scrollbar)
|
||||
gtk_scrollbar_accessible_init (GtkScrollbarAccessible *self)
|
||||
{
|
||||
scrollbar->priv = gtk_scrollbar_accessible_get_instance_private (scrollbar);
|
||||
ATK_OBJECT (self)->role = ATK_ROLE_SCROLL_BAR;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -35,13 +35,10 @@ G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkScrollbarAccessible GtkScrollbarAccessible;
|
||||
typedef struct _GtkScrollbarAccessibleClass GtkScrollbarAccessibleClass;
|
||||
typedef struct _GtkScrollbarAccessiblePrivate GtkScrollbarAccessiblePrivate;
|
||||
|
||||
struct _GtkScrollbarAccessible
|
||||
{
|
||||
GtkWidgetAccessible parent;
|
||||
|
||||
GtkScrollbarAccessiblePrivate *priv;
|
||||
};
|
||||
|
||||
struct _GtkScrollbarAccessibleClass
|
||||
|
||||
1010
gtk/a11y/gtksearchentryaccessible.c
Normal file
1010
gtk/a11y/gtksearchentryaccessible.c
Normal file
File diff suppressed because it is too large
Load Diff
48
gtk/a11y/gtksearchentryaccessible.h
Normal file
48
gtk/a11y/gtksearchentryaccessible.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* gtksearchentryaccessible.h: A GtkWidgetAccessible for GtkSearchEntry
|
||||
*
|
||||
* Copyright 2020 GNOME Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GTK_A11Y_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk-a11y.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/a11y/gtkentryaccessible.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SEARCH_ENTRY_ACCESSIBLE (gtk_search_entry_accessible_get_type())
|
||||
#define GTK_SEARCH_ENTRY_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SEARCH_ENTRY_ACCESSIBLE, GtkSearchEntryAccessible))
|
||||
#define GTK_IS_SEARCH_ENTRY_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SEARCH_ENTRY_ACCESSIBLE))
|
||||
|
||||
typedef struct _GtkSearchEntryAccessible GtkSearchEntryAccessible;
|
||||
typedef struct _GtkSearchEntryAccessibleClass GtkSearchEntryAccessibleClass;
|
||||
|
||||
struct _GtkSearchEntryAccessibleClass
|
||||
{
|
||||
GtkWidgetAccessibleClass parent_class;
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gtk_search_entry_accessible_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkSearchEntryAccessible, g_object_unref)
|
||||
|
||||
G_END_DECLS
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user