Compare commits

..

42 Commits

Author SHA1 Message Date
Matthias Clasen d17f224e71 Add search support
Add a filter to GtkListBase, and move the selection
to the first matching item whenever the filter changes.
This is meant to be used with single selection and
a string filter that is hooked up to a search entry.
2020-05-30 22:27:54 -04:00
Matthias Clasen b73be6e344 printdialog: Port to column view
This is not 100% complete. The search is not there yet.
2020-05-30 22:27:54 -04:00
Matthias Clasen 4a80f23213 printer: Fix the default value of icon-name
Just set this to "printer", so we don't have
to fix it up in the print dialog.
2020-05-30 20:01:14 -04:00
Matthias Clasen 3b8888acda printbackend: Add a list model getter
Now that we have a list model for printers,
we can start using it.
2020-05-30 20:01:14 -04:00
Matthias Clasen 786c95e503 printbackend: Use a list store 2020-05-30 20:01:14 -04:00
Matthias Clasen 7007c72fc5 inspector: Expand the actions list 2020-05-30 20:01:14 -04:00
Matthias Clasen 9eaeb81433 inspector: Expand the resource list
This is an experiment with adding a filler column.
2020-05-30 20:01:14 -04:00
Matthias Clasen 3bddbcdd52 inspector: Expand the property list
It looks better this way.
2020-05-30 20:01:14 -04:00
Matthias Clasen 13d5d60db0 inspector: Expand the object tree
This is how it used to look, and it looks better that way.
2020-05-30 20:01:14 -04:00
Matthias Clasen 1b24528b9c columnview: Take expand into account
When allocating columns, distribute extra space
to columns that have expand set to TRUE.
2020-05-30 20:01:14 -04:00
Matthias Clasen 6e7ebc49eb columnviewcolumn: Add an expand property
This will be used to determine how to distribute
available extra space in a column view.
2020-05-30 20:01:14 -04:00
Matthias Clasen bdc6770bd9 gtk-demo: Add more scrolling benchmarks
Add a listview and gridview to the scrolling
benchmarks.
2020-05-30 20:01:14 -04:00
Matthias Clasen 8d2fef1e23 gtk-demo: Make gridview demo use rubberbanding 2020-05-30 20:01:14 -04:00
Matthias Clasen 90668f7e01 Add rubberband api
Add an enable-rubberband property to GtkListView,
GtkGridView and GtkColumnView.
2020-05-30 20:01:14 -04:00
Matthias Clasen 74f72a146c listbase: Add rubberband selection
Implement the typical rubberband selection, including
autoscroll. This is only useful with multiselection,
and not very compatible with single-click-activate.
Therefore, it is not enabled by default, and needs
to be turned on with the enable-rubber-band property.
2020-05-30 20:01:14 -04:00
Matthias Clasen 5553bf1c39 Add GtkMultiSelection
This is implemented using a private GtkSet helper.
2020-05-30 20:01:14 -04:00
Matthias Clasen 77a3f81971 Add a selection model test
The test shows that we are failing to emit
::selection-changed in some circumstances.
2020-05-30 20:01:14 -04:00
Matthias Clasen b3e0353e6b testcolumnview: Reordering in the column editor
Use Ctrl-Up/Down to move the column around.
2020-05-30 20:01:14 -04:00
Matthias Clasen 780915e318 testcolumnview: Flesh out column editor
Turn the column list into an editor with
controls for visibility, resizability, reorderability
and width.
2020-05-30 20:01:14 -04:00
Matthias Clasen 7242b801ff columnviewtitle: Display a context menu
When the ::header-menu property is set on the
column, use the menu model to create and show
a context menu.
2020-05-30 20:01:14 -04:00
Matthias Clasen 88669080c4 columnviewcolumn: Add a menu property
Add a ::header-menu property that will be used
to create a context menu for the header of the
column.
2020-05-30 20:01:14 -04:00
Matthias Clasen 51e8dc924b columnview: Add autoscroll
Autoscroll when the pointer gets close to the
edge during column resizing or reordering. This
is similar to what the treeview does, but it is
implemented using a tick callback, and has
variable speed.
2020-05-30 20:01:14 -04:00
Matthias Clasen 29b5d3ab38 columnview: Allow to cancel reorder with Escape
The treeview does this too.
2020-05-30 20:01:14 -04:00
Matthias Clasen bb06fffab1 columnview: Interactive column reordering
Allow rearranging columns by dragging, in the same
way the treeview does.

We add the "dnd" style class to the header while
it is dragged, and we move the header of the dragged
column to the end of its parents children, so that
it gets drawn on top.
2020-05-30 20:01:14 -04:00
Matthias Clasen 94c5b00231 columnviewcolumn: Add a reorderable property
This will be used for interactive column reordering
in the future.
2020-05-30 20:01:14 -04:00
Matthias Clasen 59e49dafd7 columnviewlayout: Use header allocation for titles
Normally, this will be identical to the column
allocation, but we will temporarily change it
during column reordering.
2020-05-30 20:01:14 -04:00
Matthias Clasen d5ce5b53d6 columnviewcolumn: Add reordering helpers
Add helper functions that let us temporarily give
a different allocation to headers. These will be
used to implement interactive column reordering
in GtkColumnView.
2020-05-30 20:01:14 -04:00
Matthias Clasen 915bdf24a7 columnviewtitle: Invert on release
This is necessary to make drag-to-reorder work
without triggering inversion.
2020-05-30 20:01:14 -04:00
Matthias Clasen 114054266b columnview: Interactive column resizing
This copies just enough of the treeview code to
get columns moving.
2020-05-30 20:01:14 -04:00
Matthias Clasen dcea6d6cda columnviewcolumn: Add a helper
We need to check whether clicks are in the headers
of columns, so let the column view get at the the
header widget.
2020-05-30 20:01:14 -04:00
Matthias Clasen a118267ab7 columnviewcolumn: Add a resizable property
This will be used for interactive column resizing
in the future.
2020-05-30 20:01:14 -04:00
Matthias Clasen cc63c581c3 columnview: Add a helper
The column code needs to get access to the
listitem widgets that are children of the listview,
so add a getter.
2020-05-30 20:01:14 -04:00
Matthias Clasen dbc1a8ba11 columnview: Add column reordering
Add an API to allow reordering columns.
2020-05-30 20:01:14 -04:00
Matthias Clasen 515a86645a columnview: Implement horizontal scrolling
The listview inside always thinks it gets its full size,
and updates its horizontal adjustment accordingly.

So keep our own adjustment, and update it in size_allocate.
2020-05-30 20:01:14 -04:00
Matthias Clasen cbabb85e6d columnview: Revise scroll-minimum handling
Tweak the behavior slightly. We don't show
a scrollbar as long as we have at least
min-size available, but we still give the
entire size to the child, up to nat-size.

This matches how viewports handle scroll-minimum.
2020-05-30 20:01:14 -04:00
Matthias Clasen 1031625bd4 columnviewcolumn: Add a visible property
This lets us hide columns, which is useful.
2020-05-30 20:01:14 -04:00
Matthias Clasen 65ed3aa1d9 inspector: Touch up list styling
This is just the minimal amount of work to make
headers recognizable.
2020-05-30 20:01:14 -04:00
Matthias Clasen ed04c46078 inspector: Use a column view for actions
A straight conversion from list box to column view.
2020-05-30 20:01:14 -04:00
Matthias Clasen 1b2df91e6d inspector: Make the resource list sortable
This is using a GtkTreeListRowSorter to keep expanded
state of the tree while changing the sorting.
2020-05-30 20:01:14 -04:00
Matthias Clasen f745c0c2aa inspector: Use a column view for the resource list
A conversion from tree view to column view.
2020-05-30 20:01:14 -04:00
Matthias Clasen 2ed46450ea inspector: Use a column view for properties
Just a straight conversion from list box to column view.
2020-05-30 20:01:14 -04:00
Matthias Clasen 6d168079d4 inspector: Add columns to the object tree
Add columnview columns in the object tree.
We do the same for treeview columns.
2020-05-30 20:01:14 -04:00
260 changed files with 10879 additions and 14753 deletions
+15 -12
View File
@@ -17,12 +17,7 @@ stages:
# Common variables
variables:
COMMON_MESON_FLAGS: "--fatal-meson-warnings --werror"
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true -Dvulkan=yes"
FEATURE_FLAGS: "-Dcloudproviders=true"
MESON_TEST_TIMEOUT_MULTIPLIER: 2
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v18"
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
DOCS_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora-docs:v19"
.only-default:
only:
@@ -32,14 +27,14 @@ variables:
style-check-diff:
extends: .only-default
image: $FEDORA_IMAGE
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v17
stage: .pre
allow_failure: true
script:
- .gitlab-ci/run-style-check-diff.sh
.build-fedora-default:
image: $FEDORA_IMAGE
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v17
artifacts:
when: always
reports:
@@ -71,7 +66,11 @@ fedora-x86_64:
variables:
EXTRA_MESON_FLAGS: "--buildtype=debug --default-library=both"
script:
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS}
-Dx11-backend=true
-Dwayland-backend=true
-Dbroadway-backend=true
-Dvulkan=yes
-Dprofiler=true
_build
- ninja -C _build
@@ -85,7 +84,11 @@ release-build:
variables:
EXTRA_MESON_FLAGS: "--buildtype=release"
script:
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS}
-Dx11-backend=true
-Dwayland-backend=true
-Dbroadway-backend=true
-Dvulkan=yes
_build
- ninja -C _build
- .gitlab-ci/run-tests.sh _build x11
@@ -114,7 +117,7 @@ msys2-mingw32:
CHERE_INVOKING: "yes"
.flatpak-defaults:
image: $FLATPAK_IMAGE
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
stage: flatpak
allow_failure: true
tags:
@@ -168,7 +171,7 @@ flatpak-master:icon-browser:
APPID: org.gtk.IconBrowser4
static-scan:
image: $FEDORA_IMAGE
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v16
stage: analysis
variables:
EXTRA_MESON_FLAGS: "--buildtype=debug"
@@ -181,7 +184,7 @@ static-scan:
allow_failure: true
reference:
image: $DOCS_IMAGE
image: registry.gitlab.gnome.org/gnome/gtk/fedora-docs:v19
stage: docs
variables:
EXTRA_MESON_FLAGS: "--buildtype=release"
-1
View File
@@ -42,7 +42,6 @@ RUN dnf -y install \
json-glib-devel \
lcov \
libattr-devel \
libcloudproviders-devel \
libepoxy-devel \
libffi-devel \
libmount-devel \
+1 -1
View File
@@ -1,4 +1,4 @@
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v20
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v19
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}
-89
View File
@@ -1,92 +1,3 @@
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 -3
View File
@@ -27,6 +27,18 @@
/* 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
@@ -72,6 +84,9 @@
/* 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
@@ -81,9 +96,21 @@
/* 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
@@ -123,9 +150,6 @@
/* Have the Xcursor library */
#mesondefine HAVE_XCURSOR
/* Have the XDAMAGE X extension */
#mesondefine HAVE_XDAMAGE
/* Have the XFIXES X extension */
#mesondefine HAVE_XFIXES
+247
View File
@@ -0,0 +1,247 @@
/*
* 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);
}
+18
View File
@@ -0,0 +1,18 @@
#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__ */
+11
View File
@@ -0,0 +1,11 @@
<?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>
+89
View File
@@ -0,0 +1,89 @@
<?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>
+48
View File
@@ -0,0 +1,48 @@
/* 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;
}
+2 -2
View File
@@ -1,7 +1,7 @@
/* Constraints/Interactive
*
* Demonstrate how constraints can be updates during user interaction.
* The vertical edge between the buttons can be dragged with the mouse.
* Demonstrate how constraints can be updates during
* user interaction.
*/
#include <glib/gi18n.h>
+4 -3
View File
@@ -1,8 +1,9 @@
/* 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>
+5 -2
View File
@@ -1,6 +1,7 @@
<?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>
@@ -11,6 +12,9 @@
<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>
@@ -123,7 +127,6 @@
</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>
@@ -174,6 +177,7 @@
</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>
@@ -190,7 +194,6 @@
<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
View File
@@ -1,305 +0,0 @@
/* 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;
}
+2 -2
View File
@@ -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);
+3 -2
View File
@@ -1,8 +1,9 @@
/* 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.
*/
+30 -37
View File
@@ -25,7 +25,7 @@ typedef struct _GtkFishbowlChild GtkFishbowlChild;
struct _GtkFishbowlPrivate
{
GtkFishCreationFunc creation_func;
GHashTable *children;
GList *children;
guint count;
gint64 last_frame_time;
@@ -67,8 +67,6 @@ 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);
}
/**
@@ -95,18 +93,16 @@ 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;
g_hash_table_iter_init (&iter, priv->children);
while (g_hash_table_iter_next (&iter, &key, &value))
for (children = priv->children; children; children = children->next)
{
child = value;
child = children->data;
if (!gtk_widget_get_visible (child->widget))
continue;
@@ -140,13 +136,11 @@ gtk_fishbowl_size_allocate (GtkWidget *widget,
GtkFishbowlChild *child;
GtkAllocation child_allocation;
GtkRequisition child_requisition;
GHashTableIter iter;
gpointer key, value;
GList *children;
g_hash_table_iter_init (&iter, priv->children);
while (g_hash_table_iter_next (&iter, &key, &value))
for (children = priv->children; children; children = children->next)
{
child = value;
child = children->data;
if (!gtk_widget_get_visible (child->widget))
continue;
@@ -187,7 +181,7 @@ gtk_fishbowl_add (GtkFishbowl *fishbowl,
gtk_widget_set_parent (widget, GTK_WIDGET (fishbowl));
g_hash_table_insert (priv->children, widget, child_info);
priv->children = g_list_prepend (priv->children, child_info);
priv->count++;
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_COUNT]);
}
@@ -197,32 +191,34 @@ 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;
if (g_hash_table_remove (priv->children, widget))
for (children = priv->children; children; children = children->next)
{
gboolean was_visible = gtk_widget_get_visible (widget);
child = children->data;
gtk_widget_unparent (widget);
if (child->widget == widget)
{
gboolean was_visible = gtk_widget_get_visible (widget);
if (was_visible && gtk_widget_get_visible (widget_bowl))
gtk_widget_queue_resize (widget_bowl);
gtk_widget_unparent (widget);
priv->count--;
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_COUNT]);
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;
}
}
}
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)
{
@@ -308,7 +304,6 @@ 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;
@@ -540,9 +535,8 @@ 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));
@@ -554,10 +548,9 @@ gtk_fishbowl_tick (GtkWidget *widget,
if (elapsed == frame_time)
return G_SOURCE_CONTINUE;
g_hash_table_iter_init (&iter, priv->children);
while (g_hash_table_iter_next (&iter, &key, &value))
for (l = priv->children; l; l = l->next)
{
child = value;
child = l->data;
child->x += child->dx * ((double) elapsed / G_USEC_PER_SEC);
child->y += child->dy * ((double) elapsed / G_USEC_PER_SEC);
+4
View File
@@ -8,6 +8,7 @@
#include <gtk/gtk.h>
#include <stdlib.h>
#include <string.h>
#include "award.h"
static GdkPixbuf *avatar_pixbuf_other;
static GtkWidget *window = NULL;
@@ -234,6 +235,7 @@ reshare_clicked (GtkMessageRow *row,
{
GtkMessageRowPrivate *priv = row->priv;
award ("listbox-reshare");
priv->message->n_reshares++;
gtk_message_row_update (row);
}
@@ -260,6 +262,8 @@ 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);
}
+26 -29
View File
@@ -1,6 +1,6 @@
/* Lists/Application launcher
*
* This demo uses the GtkListView widget as a fancy application launcher.
* This demo uses the GtkCoverFlow widget as a fancy application launcher.
*
* It is also a very small introduction to listviews.
*/
@@ -30,7 +30,9 @@ 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);
@@ -38,24 +40,19 @@ create_application_list (void)
}
/* This is the function we use for setting up new listitems to display.
* We add just an #GtkImage and a #GtkKabel here to display the application's
* icon and name, as this is just a simple demo.
* We add just a #GtkImage here to display the application's icon 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_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);
gtk_list_item_set_child (list_item, image);
}
/* Here we need to prepare the listitem for displaying its item. We get the
@@ -69,15 +66,12 @@ bind_listitem_cb (GtkListItemFactory *factory,
GtkListItem *list_item)
{
GtkWidget *image;
GtkWidget *label;
GAppInfo *app_info;
image = gtk_widget_get_first_child (gtk_list_item_get_child (list_item));
label = gtk_widget_get_next_sibling (image);
image = gtk_list_item_get_child (list_item);
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
@@ -96,7 +90,7 @@ bind_listitem_cb (GtkListItemFactory *factory,
* above, but this is a simple demo, so we'll use the simple way.
*/
static void
activate_cb (GtkListView *list,
activate_cb (GtkCoverFlow *coverflow,
guint position,
gpointer unused)
{
@@ -104,15 +98,15 @@ activate_cb (GtkListView *list,
GdkAppLaunchContext *context;
GError *error = NULL;
app_info = g_list_model_get_item (gtk_list_view_get_model (list), position);
app_info = g_list_model_get_item (gtk_cover_flow_get_model (coverflow), 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 (list)));
context = gdk_display_get_app_launch_context (gtk_widget_get_display (GTK_WIDGET (coverflow)));
if (!g_app_info_launch (app_info,
NULL,
NULL,
G_APP_LAUNCH_CONTEXT (context),
&error))
{
@@ -121,7 +115,7 @@ activate_cb (GtkListView *list,
/* 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 (list))),
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (coverflow))),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
@@ -142,7 +136,7 @@ do_listview_applauncher (GtkWidget *do_widget)
{
if (window == NULL)
{
GtkWidget *list, *sw;
GtkWidget *coverflow, *sw;;
GListModel *model;
GtkListItemFactory *factory;
@@ -153,7 +147,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.
@@ -166,22 +160,25 @@ 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.
/* 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.
*/
list = gtk_list_view_new_with_factory (factory);
coverflow = gtk_cover_flow_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 (list, "activate", G_CALLBACK (activate_cb), NULL);
g_signal_connect (coverflow, "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 list widget.
* The list will now take items from the model and use the factory
* it on the coverflow list widget.
* The coverflow 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_list_view_set_model (GTK_LIST_VIEW (list), model);
gtk_cover_flow_set_model (GTK_COVER_FLOW (coverflow), model);
g_object_unref (model);
/* List widgets should always be contained in a #GtkScrolledWindow,
@@ -190,7 +187,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), list);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), coverflow);
}
if (!gtk_widget_get_visible (window))
+36 -53
View File
@@ -3,9 +3,10 @@
* 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
@@ -40,8 +41,7 @@ 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,11 +51,10 @@ 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,
@@ -69,31 +68,26 @@ 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.
*/
* 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,
@@ -101,11 +95,9 @@ 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 it
* 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 if 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);
@@ -115,8 +107,7 @@ 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);
@@ -134,9 +125,8 @@ 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);
@@ -155,9 +145,10 @@ gtk_clock_get_intrinsic_height (GdkPaintable *paintable)
return 100;
}
/* 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.
/* 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.
*/
static void
gtk_clock_paintable_init (GdkPaintableInterface *iface)
@@ -167,9 +158,8 @@ 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 drawn.
/* Finally, we define the type. The important part is adding the paintable
* interface, so GTK knows that this object can indeed be drawm.
*/
G_DEFINE_TYPE_WITH_CODE (GtkClock, gtk_clock, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
@@ -231,14 +221,11 @@ 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)
@@ -253,7 +240,6 @@ 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.
*/
@@ -323,16 +309,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;
}
@@ -357,9 +343,6 @@ 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);
+5 -19
View File
@@ -6,13 +6,11 @@
* 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 9283 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)
@@ -25,7 +23,6 @@ struct _GtkColor
char *name;
GdkRGBA *color;
int h, s, v;
gboolean selected;
};
enum {
@@ -38,7 +35,6 @@ enum {
PROP_HUE,
PROP_SATURATION,
PROP_VALUE,
PROP_SELECTED,
N_PROPS
};
@@ -126,10 +122,6 @@ 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;
@@ -166,10 +158,6 @@ 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;
@@ -212,8 +200,6 @@ 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);
}
@@ -273,7 +259,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);
@@ -334,7 +320,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];
@@ -434,12 +420,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_property_selection_new (model, "selected"));
selection = G_LIST_MODEL (gtk_multi_selection_new (model));
gtk_grid_view_set_model (GTK_GRID_VIEW (gridview), selection);
g_object_unref (selection);
g_object_unref (model);
-26
View File
@@ -18,7 +18,6 @@ struct _FileBrowserView
GtkListItemFactory *factory;
char *icon_name;
char *title;
GtkOrientation orientation;
};
@@ -26,7 +25,6 @@ enum {
PROP_0,
PROP_FACTORY,
PROP_ICON_NAME,
PROP_TITLE,
PROP_ORIENTATION,
N_PROPS
@@ -56,10 +54,6 @@ 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;
@@ -89,11 +83,6 @@ 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;
@@ -111,7 +100,6 @@ 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);
}
@@ -137,12 +125,6 @@ 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",
@@ -242,14 +224,6 @@ 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
View File
@@ -1,11 +0,0 @@
list.viewswitcher {
border: 1px solid gray;
}
list.viewswitcher > row {
padding: 5px;
}
list.viewswitcher row:selected {
background: gray;
}
+1 -10
View File
@@ -39,14 +39,12 @@
</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[
@@ -94,7 +92,6 @@
<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[
@@ -177,7 +174,7 @@
<property name="show-title-buttons">1</property>
<child>
<object class="GtkButton">
<property name="icon-name">go-up-symbolic</property>
<property name="icon-name">go-up</property>
<signal name="clicked" handler="filebrowser_up_clicked_cb" object="dirlist" swapped="no"/>
</object>
</child>
@@ -187,7 +184,6 @@
<property name="orientation">horizontal</property>
<style>
<class name="linked"/>
<class name="viewswitcher"/>
</style>
<property name="model">
<object class="GtkSingleSelection" id="selected-view">
@@ -207,11 +203,6 @@
<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>
+1 -100
View File
@@ -9,8 +9,6 @@
#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
@@ -27,8 +25,6 @@ enum {
PROP_SUMMARY,
PROP_DESCRIPTION,
PROP_VALUE,
PROP_TYPE,
PROP_DEFAULT_VALUE,
N_PROPS
};
@@ -69,21 +65,6 @@ 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;
@@ -117,10 +98,6 @@ 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);
}
@@ -142,43 +119,6 @@ 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)
@@ -204,7 +144,6 @@ transform_settings_to_keys (GBinding *binding,
GtkSortListModel *sort_model;
GtkFilterListModel *filter_model;
GtkFilter *filter;
GtkNoSelection *selection_model;
GtkExpression *expression;
char **keys;
guint i;
@@ -247,10 +186,7 @@ transform_settings_to_keys (GBinding *binding,
g_object_unref (filter);
selection_model = gtk_no_selection_new (G_LIST_MODEL (filter_model));
g_object_unref (filter_model);
g_value_take_object (to_value, selection_model);
g_value_take_object (to_value, filter_model);
return TRUE;
}
@@ -343,13 +279,7 @@ 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);
@@ -357,7 +287,6 @@ 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);
@@ -370,32 +299,6 @@ 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,
@@ -419,8 +322,6 @@ 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))
+2 -145
View File
@@ -77,7 +77,6 @@
<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[
@@ -104,8 +103,6 @@
<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[
@@ -113,10 +110,9 @@
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkEntry">
<signal name="activate" handler="item_value_changed" object="GtkListItem" swapped="yes"/>
<object class="GtkLabel">
<property name="xalign">0</property>
<binding name="text">
<binding name="label">
<lookup name="value" type="SettingsKey">
<lookup name="item">GtkListItem</lookup>
</lookup>
@@ -124,125 +120,6 @@
</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[
<?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="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>
</object>
</property>
</template>
</interface>
]]></property>
</object>
@@ -258,24 +135,4 @@
</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>
+4 -4
View File
@@ -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 70000 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);
+10 -8
View File
@@ -8,6 +8,7 @@
#include <gtk/gtk.h>
#include <glib/gstdio.h>
#include "award.h"
#include "demos.h"
static GtkWidget *info_view;
@@ -212,6 +213,7 @@ activate_inspector (GSimpleAction *action,
gpointer user_data)
{
gtk_window_set_interactive_debugging (TRUE);
award ("demo-inspector");
}
static void
@@ -599,7 +601,7 @@ display_image (const char *resource)
{
GtkWidget *sw, *image;
image = gtk_picture_new_for_resource (resource);
image = gtk_image_new_from_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);
@@ -1040,7 +1042,7 @@ activate (GApplication *app)
listmodel = create_demo_model ();
treemodel = gtk_tree_list_model_new (FALSE,
G_LIST_MODEL (listmodel),
TRUE,
FALSE,
get_child_model,
NULL,
NULL);
@@ -1049,6 +1051,10 @@ 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);
}
@@ -1107,11 +1113,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)
@@ -1141,11 +1147,7 @@ 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);
+1 -1
View File
@@ -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> and <span overline="single" overline_color="green">overlines</span>
Colorful <span strikethrough="true" strikethrough-color="magenta">strikethroughs</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>
+2 -1
View File
@@ -3,6 +3,7 @@
demos = files([
'application_demo.c',
'assistant.c',
'awardview.c',
'builder.c',
'clipboard.c',
'combobox.c',
@@ -18,7 +19,6 @@ demos = files([
'cursors.c',
'dialog.c',
'drawingarea.c',
'dropdown.c',
'dnd.c',
'editable_cells.c',
'entry_completion.c',
@@ -92,6 +92,7 @@ demos = files([
gtkdemo_deps = [ libgtk_dep, ]
extra_demo_sources = files(['main.c',
'award.c',
'gtkfishbowl.c',
'fontplane.c',
'gtkgears.c',
+6
View File
@@ -11,6 +11,7 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "award.h"
static GtkWidget *entry;
static GtkWidget *entry2;
@@ -26,12 +27,17 @@ 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));
}
+17 -13
View File
@@ -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,6 +11,8 @@
#include "puzzlepiece.h"
#include "paintable.h"
/* Give out awards */
#include "award.h"
static GtkWidget *window = NULL;
static GtkWidget *frame = NULL;
@@ -157,6 +159,14 @@ 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;
}
@@ -241,8 +251,6 @@ puzzle_button_pressed (GtkGestureClick *gesture,
{
gtk_widget_error_bell (grid);
}
check_solved (grid);
}
static void
@@ -283,8 +291,6 @@ 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);
@@ -345,16 +351,11 @@ reshuffle (void)
{
GtkWidget *grid;
grid = gtk_aspect_frame_get_child (GTK_ASPECT_FRAME (frame));
if (solved)
{
start_puzzle (puzzle);
grid = gtk_aspect_frame_get_child (GTK_ASPECT_FRAME (frame));
}
start_puzzle (puzzle);
else
{
grid = gtk_aspect_frame_get_child (GTK_ASPECT_FRAME (frame));
shuffle_puzzle (grid);
}
shuffle_puzzle (grid);
gtk_widget_grab_focus (grid);
}
@@ -406,6 +407,9 @@ widget_destroyed (gpointer data,
{
if (data)
*(gpointer *) data = NULL;
if (!solved)
award ("puzzle-give-up");
}
+10 -39
View File
@@ -92,11 +92,12 @@ static Theme themes[] = {
static int theme;
static gboolean
change_theme (GtkWidget *widget,
change_theme (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer data)
gpointer data)
{
GtkWidget *label = data;
GtkBuilder *builder = data;
GtkWidget *label;
Theme next = themes[theme++ % G_N_ELEMENTS (themes)];
char *name;
@@ -109,6 +110,7 @@ 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;
@@ -125,10 +127,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;
@@ -163,29 +165,6 @@ 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)
{
@@ -195,8 +174,6 @@ do_themes (GtkWidget *do_widget)
{
GtkBuilder *builder;
GtkWidget *header;
GtkWidget *button;
GtkWidget *label;
GtkGesture *gesture;
builder = gtk_builder_new_from_resource ("/themes/themes.ui");
@@ -206,17 +183,11 @@ 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), label);
g_signal_connect (gesture, "pressed", G_CALLBACK (clicked), builder);
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
View File
@@ -5,11 +5,6 @@
<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>
+3 -17
View File
@@ -93,6 +93,7 @@ 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
@@ -382,6 +383,8 @@ 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
@@ -499,7 +502,6 @@ gdk_event_get_position
gdk_event_get_axes
gdk_event_get_axis
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
@@ -518,7 +520,6 @@ 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
@@ -544,23 +545,8 @@ 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>
+1 -5
View File
@@ -27,19 +27,15 @@ 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',
'x11/gdkprivate-x11.h',
'gdkprivate-x11.h',
'x11/gdkeventsource.h',
'gtk-primary-selection-client-protocol.h',
'gtk-shell-client-protocol.h',
+1
View File
@@ -236,6 +236,7 @@ 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
-2
View File
@@ -9,11 +9,9 @@ private_headers = [
'gskprofilerprivate.h',
'gskrendererprivate.h',
'gskrendernodeprivate.h',
'gskrendernodeparserprivate.h',
'gskroundedrectprivate.h',
'gskshaderbuilderprivate.h',
'gsktextureprivate.h',
'gsktransformprivate.h',
'gskvulkanblendpipelineprivate.h',
'gskvulkanborderpipelineprivate.h',
'gskvulkanboxshadowpipelineprivate.h',
+1 -1
View File
@@ -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_REQUIRED=GDK_VERSION_4_2 hello.c -o hello `pkg-config --libs gtk4`
$ cc `pkg-config --cflags gtk4` -DGDK_VERSION_MIN_REQIRED=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
+3 -11
View File
@@ -68,12 +68,8 @@
<xi:include href="xml/gtkmultisorter.xml" />
</section>
<xi:include href="xml/gtkselectionmodel.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/gtknoselection.xml" />
<xi:include href="xml/gtksingleselection.xml" />
<xi:include href="xml/gtkdirectorylist.xml" />
</chapter>
@@ -94,11 +90,8 @@
</chapter>
<chapter id="Trees">
<title>Tree support</title>
<xi:include href="xml/gtktreelistrow.xml" />
<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>
@@ -127,7 +120,6 @@
<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">
+21 -48
View File
@@ -350,9 +350,6 @@ 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
@@ -395,24 +392,6 @@ 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>
@@ -502,6 +481,9 @@ 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
@@ -525,17 +507,16 @@ 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_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_get_show_separators
gtk_column_view_set_show_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
@@ -562,15 +543,8 @@ 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
@@ -597,6 +571,9 @@ 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
@@ -1466,6 +1443,7 @@ 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
@@ -2055,7 +2033,7 @@ gtk_info_bar_get_type
<SECTION>
<FILE>gtknativedialog</FILE>
<TITLE>GtkNativeDialog</TITLE>
GtkNativeDialog
GTK_TYPE_NATIVE_DIALOG
GtkNativeDialogClass
gtk_native_dialog_show
gtk_native_dialog_hide
@@ -2067,8 +2045,9 @@ 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>
@@ -2142,18 +2121,12 @@ GtkNotebookPrivate
<TITLE>GtkPaned</TITLE>
GtkPaned
gtk_paned_new
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_add1
gtk_paned_add2
gtk_paned_pack1
gtk_paned_pack2
gtk_paned_get_child1
gtk_paned_get_child2
gtk_paned_set_position
gtk_paned_get_position
gtk_paned_set_wide_handle
-2
View File
@@ -139,7 +139,6 @@ 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
@@ -169,7 +168,6 @@ 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
+101
View File
@@ -0,0 +1,101 @@
# 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 |
+1 -10
View File
@@ -13,7 +13,6 @@ private_headers = [
'gtkappchooserprivate.h',
'gtkapplicationaccelsprivate.h',
'gtkapplicationprivate.h',
'gtkarrayimplprivate.h',
'gtkbindingsprivate.h',
'gtkbitmaskprivate.h',
'gtkbuilderprivate.h',
@@ -149,14 +148,11 @@ private_headers = [
'gtkmagnifierprivate.h',
'gtkmediafileprivate.h',
'gtkmenubuttonprivate.h',
'gtkmenusectionboxprivate.h',
'gtkmenutrackeritemprivate.h',
'gtkmenutrackerprivate.h',
'gtkmodulesprivate.h',
'gtkmountoperationprivate.h',
'gtknativedialogprivate.h',
'gtknomediafileprivate.h',
'gtkpango.h',
'gtkorientableprivate.h',
'gtkplacessidebarprivate.h',
'gtkplacesviewprivate.h',
'gtkplacesviewrowprivate.h',
@@ -166,7 +162,6 @@ private_headers = [
'gtkprintoperation-private.h',
'gtkprivate.h',
'gtkprogresstrackerprivate.h',
'gtkquery.h',
'gtkrangeprivate.h',
'gtkrbtreeprivate.h',
'gtkrenderbackgroundprivate.h',
@@ -176,9 +171,7 @@ private_headers = [
'gtkroundedboxprivate.h',
'gtkscalerprivate.h',
'gtksearchentryprivate.h',
'gtkset.h',
'gtksettingsprivate.h',
'gtkshortcutcontrollerprivate.h',
'gtkshortcutsshortcutprivate.h',
'gtkshortcutswindowprivate.h',
'gtksidebarrowprivate.h',
@@ -205,9 +198,7 @@ private_headers = [
'gtktoolbarprivate.h',
'gtktooltipprivate.h',
'gtktooltipwindowprivate.h',
'gtktreepopoverprivate.h',
'gtktreeprivate.h',
'gtktreerbtreeprivate.h',
'gtkutilsprivate.h',
'gtkwidgetpaintableprivate.h',
'gtkwidgetpathprivate.h',
+39 -135
View File
@@ -1,181 +1,85 @@
# 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 these widgets would be #GtkListView or #GtkGridView.
**_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:
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.
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.
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.
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.
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 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 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.
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.
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](#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.
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.
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.
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:
Finally here's a quick list of equivalent functionality to look for when transitioning code for easy lookup:
| Old | New |
| ------------------- | ----------------------------------- |
+18
View File
@@ -23,6 +23,12 @@
#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,
@@ -58,6 +64,7 @@ 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;
@@ -77,6 +84,17 @@ gdk_broadway_device_init (GdkBroadwayDevice *device_core)
_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;
}
static void
gdk_broadway_device_get_state (GdkDevice *device,
GdkSurface *surface,
+58
View File
@@ -0,0 +1,58 @@
/* 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
+90 -61
View File
@@ -26,6 +26,9 @@
#include "gdkintl.h"
#include "gdkkeysprivate.h"
/* for the use of round() */
#include "fallback-c89.c"
/**
* SECTION:gdkdevice
* @Short_description: Object representing an input device
@@ -635,6 +638,93 @@ 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
@@ -1688,15 +1778,6 @@ 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)
{
@@ -1708,15 +1789,6 @@ 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)
{
@@ -1728,15 +1800,6 @@ 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)
{
@@ -1748,15 +1811,6 @@ 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)
{
@@ -1768,20 +1822,6 @@ 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)
{
@@ -1793,17 +1833,6 @@ 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)
{
+10
View File
@@ -146,6 +146,16 @@ 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);
+7
View File
@@ -70,6 +70,13 @@ 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,
+7 -4
View File
@@ -38,6 +38,9 @@
#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
@@ -1732,11 +1735,11 @@ gdk_display_map_keycode (GdkDisplay *display,
* @keycode: a keycode
* @state: a modifier state
* @group: active keyboard group
* @keyval: (out) (optional): return location for keyval, or %NULL
* @effective_group: (out) (optional): return location for effective
* @keyval: (out) (allow-none): return location for keyval, or %NULL
* @effective_group: (out) (allow-none): return location for effective
* group, or %NULL
* @level: (out) (optional): return location for level, or %NULL
* @consumed: (out) (optional): return location for modifiers
* @level: (out) (allow-none): return location for level, or %NULL
* @consumed_modifiers: (out) (allow-none): 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)
+25 -3
View File
@@ -2130,7 +2130,7 @@ gdk_focus_event_new (GdkSurface *surface,
/**
* gdk_focus_event_get_in:
* @event: (type GdkFocusEvent): a focus change event
* @event: (type GdkScrollEvent): a focus change event
*
* Extracts whether this event is about focus entering or
* leaving the surface.
@@ -2152,6 +2152,15 @@ 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)
{
@@ -2170,6 +2179,19 @@ 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)
{
@@ -2180,10 +2202,10 @@ gdk_scroll_event_get_tool (GdkEvent *event)
static const GdkEventTypeInfo gdk_scroll_event_info = {
sizeof (GdkScrollEvent),
NULL,
gdk_scroll_event_init,
gdk_scroll_event_finalize,
gdk_scroll_event_get_state,
NULL,
gdk_scroll_event_get_position,
NULL,
gdk_scroll_event_get_tool,
NULL,
+2
View File
@@ -225,6 +225,8 @@ struct _GdkScrollEvent
{
GdkEvent parent_instance;
double x;
double y;
GdkModifierType state;
GdkScrollDirection direction;
double delta_x;
+18 -19
View File
@@ -56,7 +56,6 @@ struct _GdkFrameClockIdlePrivate
GdkFrameClockPhase phase;
guint in_paint_idle : 1;
guint paint_is_thaw : 1;
#ifdef G_OS_WIN32
guint begin_period : 1;
#endif
@@ -163,7 +162,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_vsync_related,
gboolean new_frame_time_is_regular,
gint64 smoothed_frame_time_base,
gint64 frame_interval)
{
@@ -205,13 +204,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 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.
* 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.
*/
if (new_frame_time_is_vsync_related)
if (new_frame_time_is_regular)
{
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 */
@@ -237,8 +236,7 @@ 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_BEFORE_PAINT || priv->in_paint_idle))
priv->phase != GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS)
return priv->smoothed_frame_time_base;
/* Outside a paint, pick something smoothed close to now */
@@ -276,8 +274,7 @@ gdk_frame_clock_idle_get_frame_time (GdkFrameClock *clock)
(priv)->updating_count > 0))
static void
maybe_start_idle (GdkFrameClockIdle *clock_idle,
gboolean caused_by_thaw)
maybe_start_idle (GdkFrameClockIdle *clock_idle)
{
GdkFrameClockIdlePrivate *priv = clock_idle->priv;
@@ -305,7 +302,6 @@ 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,
@@ -412,6 +408,7 @@ 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;
@@ -426,9 +423,11 @@ 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,
priv->paint_is_thaw,
is_regular,
priv->smoothed_frame_time_base,
priv->smoothed_frame_time_period);
priv->smoothed_frame_time_period = frame_interval;
@@ -559,8 +558,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->smoothed_frame_time_base);
maybe_start_idle (clock_idle, FALSE);
priv->frame_time);
maybe_start_idle (clock_idle);
}
if (priv->freeze_count == 0)
@@ -580,7 +579,7 @@ gdk_frame_clock_idle_request_phase (GdkFrameClock *clock,
GdkFrameClockIdlePrivate *priv = clock_idle->priv;
priv->requested |= phase;
maybe_start_idle (clock_idle, FALSE);
maybe_start_idle (clock_idle);
}
static void
@@ -599,7 +598,7 @@ gdk_frame_clock_idle_begin_updating (GdkFrameClock *clock)
#endif
priv->updating_count++;
maybe_start_idle (clock_idle, FALSE);
maybe_start_idle (clock_idle);
}
static void
@@ -649,7 +648,7 @@ gdk_frame_clock_idle_thaw (GdkFrameClock *clock)
priv->freeze_count--;
if (priv->freeze_count == 0)
{
maybe_start_idle (clock_idle, TRUE);
maybe_start_idle (clock_idle);
/* 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.
-2
View File
@@ -71,8 +71,6 @@ typedef enum
/**
* GdkPopupLayout:
*
* Struct containing information for gdk_popup_present()
*/
typedef struct _GdkPopupLayout GdkPopupLayout;
+2
View File
@@ -30,6 +30,8 @@
#include <errno.h>
#include <math.h>
#include "fallback-c89.c"
/**
* SECTION:rgba_colors
* @Short_description: RGBA colors
+3
View File
@@ -47,6 +47,9 @@
#include <epoxy/gl.h>
/* for the use of round() */
#include "fallback-c89.c"
#ifdef GDK_WINDOWING_WAYLAND
#include "wayland/gdkwayland.h"
#endif
-2
View File
@@ -31,8 +31,6 @@ G_BEGIN_DECLS
/**
* GdkTopLevelLayout:
*
* Struct containing information for gdk_toplevel_present()
*/
typedef struct _GdkToplevelLayout GdkToplevelLayout;
+12
View File
@@ -309,6 +309,17 @@ 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,
@@ -817,6 +828,7 @@ 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;
+1
View File
@@ -31,6 +31,7 @@
#include <limits.h>
#include <errno.h>
#include <sys/mman.h>
#include <fribidi.h>
#include "gdk.h"
#include "gdkwayland.h"
+13
View File
@@ -63,6 +63,18 @@ _gdk_device_virtual_set_active (GdkDevice *device,
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,
@@ -176,6 +188,7 @@ 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;
+12
View File
@@ -29,6 +29,17 @@
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,
@@ -224,6 +235,7 @@ 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;
+12
View File
@@ -28,6 +28,17 @@
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)
{
@@ -256,6 +267,7 @@ 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;
+1
View File
@@ -49,6 +49,7 @@
#include <cairo-win32.h>
#include <dwmapi.h>
#include <math.h>
#include "fallback-c89.c"
static void gdk_surface_win32_finalize (GObject *object);
-8
View File
@@ -1603,14 +1603,6 @@ 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");
-7
View File
@@ -149,13 +149,6 @@ 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
-128
View File
@@ -183,22 +183,6 @@ 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)
@@ -581,81 +565,6 @@ 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)
@@ -828,24 +737,6 @@ 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,
@@ -875,10 +766,6 @@ 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);
}
@@ -954,21 +841,6 @@ 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"
-9
View File
@@ -24,10 +24,6 @@
#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>
@@ -48,11 +44,6 @@ 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;
-5
View File
@@ -104,11 +104,6 @@ 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);
+6 -73
View File
@@ -360,77 +360,6 @@ 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)
{
@@ -476,9 +405,13 @@ gdk_x11_surface_end_frame (GdkSurface *surface)
else
impl->toplevel->current_counter_value += 1;
maybe_sync_counter_for_end_frame (surface);
set_sync_counter(GDK_SURFACE_XDISPLAY (surface),
impl->toplevel->extended_update_counter,
impl->toplevel->current_counter_value);
if (should_sync_frame_drawing (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")))
{
impl->toplevel->frame_pending = TRUE;
gdk_surface_freeze_updates (surface);
-3
View File
@@ -124,9 +124,6 @@ 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;
-1
View File
@@ -65,7 +65,6 @@ gdk_x11_deps = [
xext_dep,
x11_dep,
xcursor_dep,
xdamage_dep,
xfixes_dep,
xcomposite_dep,
xrandr_dep,
+1 -35
View File
@@ -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
*
* Retrieves the color stops in the gradient.
* Retrievs the color stops in the gradient.
*
* Returns: (array length=n_stops): the color stops in the gradient
*/
@@ -555,14 +555,6 @@ 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)
{
@@ -571,15 +563,6 @@ 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)
{
@@ -588,15 +571,6 @@ 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)
{
@@ -3652,14 +3626,6 @@ 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)
{
+16 -9
View File
@@ -171,30 +171,37 @@ gtk_button_accessible_ref_state_set (AtkObject *obj)
return state_set;
}
void
gtk_button_accessible_update_label (GtkButtonAccessible *self)
static void
gtk_button_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
g_return_if_fail (GTK_IS_BUTTON_ACCESSIBLE (self));
GtkWidget *widget = GTK_WIDGET (obj);
AtkObject *atk_obj = gtk_widget_get_accessible (widget);
/* 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");
if (strcmp (pspec->name, "label") == 0)
{
if (atk_obj->name == NULL)
g_object_notify (G_OBJECT (atk_obj), "accessible-name");
g_signal_emit_by_name (self, "visible-data-changed");
g_signal_emit_by_name (atk_obj, "visible-data-changed");
}
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_button_accessible_parent_class)->notify_gtk (obj, pspec);
}
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
-3
View File
@@ -52,9 +52,6 @@ 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__ */
+34 -37
View File
@@ -17,10 +17,10 @@
#include "config.h"
#include "gtkcolorswatchaccessibleprivate.h"
#include "gtkcolorswatchprivate.h"
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
#include "gtkcolorswatchprivate.h"
#include "gtkcolorswatchaccessibleprivate.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,
AtkObject *accessible)
GtkStateFlags previous_flags)
{
AtkObject *accessible;
GtkStateFlags flags;
gboolean was_selected;
gboolean selected;
@@ -41,46 +41,23 @@ 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),
obj);
g_signal_connect (data, "notify::selectable",
G_CALLBACK (on_selectable_changed_cb),
obj);
G_CALLBACK (state_changed_cb), NULL);
obj->role = gtk_color_swatch_get_selectable (swatch)
? ATK_ROLE_RADIO_BUTTON
: ATK_ROLE_PUSH_BUTTON;
atk_object_set_role (obj, ATK_ROLE_RADIO_BUTTON);
}
static AtkStateSet *
@@ -102,18 +79,38 @@ gtk_color_swatch_accessible_ref_state_set (AtkObject *accessible)
}
static void
_gtk_color_swatch_accessible_class_init (GtkColorSwatchAccessibleClass *klass)
gtk_color_swatch_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass);
GtkWidget *widget = GTK_WIDGET (obj);
AtkObject *atk_obj = gtk_widget_get_accessible (widget);
atk_class->initialize = gtk_color_swatch_accessible_initialize;
atk_class->ref_state_set = gtk_color_swatch_accessible_ref_state_set;
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_init (GtkColorSwatchAccessible *self)
_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)
{
ATK_OBJECT (self)->role = ATK_ROLE_RADIO_BUTTON;
}
static gint
+334 -293
View File
@@ -17,21 +17,20 @@
#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))
@@ -158,7 +157,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;
}
@@ -357,6 +356,15 @@ 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);
@@ -372,277 +380,6 @@ 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)
@@ -686,7 +423,9 @@ gtk_entry_accessible_get_attributes (AtkObject *accessible)
if (widget == NULL)
return attributes;
g_object_get (widget, "placeholder-text", &text, NULL);
if (GTK_IS_ENTRY (widget) || GTK_IS_SEARCH_ENTRY (widget))
g_object_get (widget, "placeholder-text", &text, NULL);
if (text == NULL)
return attributes;
@@ -717,9 +456,197 @@ 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), obj);
g_signal_connect (widget, "delete-text", G_CALLBACK (delete_text_cb), obj);
g_signal_connect (widget, "notify", G_CALLBACK (on_notify), obj);
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);
}
static gint
@@ -746,10 +673,13 @@ gtk_entry_accessible_get_n_children (AtkObject* obj)
if (widget == NULL)
return 0;
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_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++;
}
return count;
}
@@ -767,6 +697,9 @@ gtk_entry_accessible_ref_child (AtkObject *obj,
if (widget == NULL)
return NULL;
if (!GTK_IS_ENTRY (widget))
return NULL;
switch (i)
{
case 0:
@@ -808,7 +741,8 @@ gtk_entry_accessible_finalize (GObject *object)
static void
gtk_entry_accessible_class_init (GtkEntryAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
class->ref_state_set = gtk_entry_accessible_ref_state_set;
@@ -818,6 +752,8 @@ 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;
}
@@ -827,8 +763,23 @@ 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;
}
ATK_OBJECT (entry)->role = ATK_ROLE_TEXT;
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;
}
static gchar *
@@ -1426,6 +1377,96 @@ 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)
+36 -19
View File
@@ -17,10 +17,9 @@
#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);
@@ -92,27 +91,41 @@ gtk_expander_accessible_ref_child (AtkObject *obj,
return accessible;
}
void
gtk_expander_accessible_update_label (GtkExpanderAccessible *self)
static void
gtk_expander_accessible_initialize (AtkObject *obj,
gpointer data)
{
AtkObject *atk_obj = ATK_OBJECT (self);
ATK_OBJECT_CLASS (gtk_expander_accessible_parent_class)->initialize (obj, data);
if (atk_obj->name == NULL)
g_object_notify (G_OBJECT (atk_obj), "accessible-name");
g_signal_emit_by_name (atk_obj, "visible-data-changed");
obj->role = ATK_ROLE_TOGGLE_BUTTON;
}
void
gtk_expander_accessible_update_state (GtkExpanderAccessible *self,
gboolean expanded)
static void
gtk_expander_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
AtkObject *atk_obj = ATK_OBJECT (self);
AtkObject* atk_obj;
GtkExpander *expander;
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");
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);
}
static AtkStateSet *
@@ -145,17 +158,21 @@ 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 *self)
gtk_expander_accessible_init (GtkExpanderAccessible *expander)
{
ATK_OBJECT (self)->role = ATK_ROLE_TOGGLE_BUTTON;
}
static gboolean
-31
View File
@@ -1,31 +0,0 @@
/* 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
+225 -202
View File
@@ -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))
typedef struct
struct _GtkIconViewAccessiblePrivate
{
GList *items;
GtkTreeModel *model;
} GtkIconViewAccessiblePrivate;
};
typedef struct
{
@@ -265,8 +265,7 @@ 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;
}
@@ -743,9 +742,8 @@ gtk_icon_view_item_accessible_set_visibility (GtkIconViewItemAccessible *item,
static void
_gtk_icon_view_item_accessible_init (GtkIconViewItemAccessible *item)
{
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);
@@ -862,25 +860,25 @@ G_DEFINE_TYPE_WITH_CODE (GtkIconViewAccessible, gtk_icon_view_accessible, GTK_TY
typedef struct
{
AtkObject *item;
int index;
} ItemAccessibleInfo;
gint index;
} GtkIconViewItemAccessibleInfo;
static void
gtk_icon_view_item_accessible_info_new (GtkIconViewAccessible *self,
GtkIconViewItemAccessible *item,
int index)
gtk_icon_view_item_accessible_info_new (AtkObject *accessible,
AtkObject *item,
gint index)
{
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
ItemAccessibleInfo *info;
ItemAccessibleInfo *tmp_info;
GtkIconViewAccessible *view = (GtkIconViewAccessible *)accessible;
GtkIconViewItemAccessibleInfo *info;
GtkIconViewItemAccessibleInfo *tmp_info;
GList *items;
info = g_new (ItemAccessibleInfo, 1);
info->item = ATK_OBJECT (item);
info = g_new (GtkIconViewItemAccessibleInfo, 1);
info->item = item;
info->index = index;
items = priv->items;
items = view->priv->items;
while (items)
{
tmp_info = items->data;
@@ -888,8 +886,7 @@ gtk_icon_view_item_accessible_info_new (GtkIconViewAccessible *self,
break;
items = items->next;
}
priv->items = g_list_insert_before (priv->items, items, info);
view->priv->items = g_list_insert_before (view->priv->items, items, info);
}
static gint
@@ -907,24 +904,22 @@ gtk_icon_view_accessible_get_n_children (AtkObject *accessible)
return g_list_length (icon_view->priv->items);
}
static GtkIconViewItemAccessible *
gtk_icon_view_accessible_find_child (GtkIconViewAccessible *self,
gint index)
static AtkObject *
gtk_icon_view_accessible_find_child (AtkObject *accessible,
gint index)
{
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GtkIconViewAccessible *view = (GtkIconViewAccessible*)accessible;
GtkIconViewItemAccessibleInfo *info;
GList *items;
items = priv->items;
items = view->priv->items;
while (items)
{
ItemAccessibleInfo *info = items->data;
GList *next = items->next;
info = items->data;
if (info->index == index)
return GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
items = next;
return info->item;
items = items->next;
}
return NULL;
@@ -934,28 +929,31 @@ 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 == NULL)
if (!widget)
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);
a11y_item = gtk_icon_view_accessible_find_child (self, index);
if (a11y_item == NULL)
obj = gtk_icon_view_accessible_find_child (accessible, index);
if (!obj)
{
a11y_item = g_object_new (GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE, 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->item = item;
a11y_item->widget = widget;
@@ -964,62 +962,60 @@ 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 (a11y_item);
return ATK_OBJECT (a11y_item);
}
else
{
return NULL;
g_object_ref (obj);
}
return obj;
}
static void
gtk_icon_view_accessible_traverse_items (GtkIconViewAccessible *self,
gtk_icon_view_accessible_traverse_items (GtkIconViewAccessible *view,
GList *list)
{
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GtkWidget *widget;
gboolean act_on_item;
GtkIconViewItemAccessibleInfo *info;
GtkIconViewItemAccessible *item;
GList *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)
if (view->priv->items)
{
ItemAccessibleInfo *info = items->data;
GtkIconViewItemAccessible *item;
GList *next = items->next;
GtkWidget *widget;
gboolean act_on_item;
item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (view));
if (widget == NULL)
return;
if (act_on_item == FALSE && list == items)
act_on_item = TRUE;
items = view->priv->items;
if (act_on_item)
gtk_icon_view_item_accessible_set_visibility (item, TRUE);
act_on_item = (list == NULL);
items = next;
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;
}
}
}
void
gtk_icon_view_accessible_adjustment_changed (GtkIconViewAccessible *self)
_gtk_icon_view_accessible_adjustment_changed (GtkIconView *icon_view)
{
gtk_icon_view_accessible_traverse_items (self, NULL);
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);
}
static void
@@ -1028,26 +1024,36 @@ gtk_icon_view_accessible_model_row_changed (GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer user_data)
{
GtkIconViewAccessible *self = user_data;
AtkObject *atk_obj;
gint index;
GtkWidget *widget;
GtkIconView *icon_view;
GtkIconViewItem *item;
GtkIconViewItemAccessible *a11y_item;
int index;
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));
index = gtk_tree_path_get_indices (path)[0];
a11y_item = gtk_icon_view_accessible_find_child (self, index);
if (a11y_item)
{
GtkIconViewItem *item = a11y_item->item;
GtkIconView *icon_view = GTK_ICON_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (self)));
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_obj));
icon_view = GTK_ICON_VIEW (widget);
item = a11y_item->item;
const char *name = atk_object_get_name (ATK_OBJECT (a11y_item));
if (name == NULL || *name == '\0')
name = atk_object_get_name (ATK_OBJECT (a11y_item));
if (!name || strcmp (name, "") == 0)
{
g_free (a11y_item->text);
a11y_item->text = get_text (icon_view, item);
}
}
g_signal_emit_by_name (self, "visible-data-changed");
g_signal_emit_by_name (atk_obj, "visible-data-changed");
return;
}
static void
@@ -1056,22 +1062,24 @@ gtk_icon_view_accessible_model_row_inserted (GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer user_data)
{
GtkIconViewAccessible *self = user_data;
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GtkIconViewItemAccessibleInfo *info;
GtkIconViewAccessible *view;
GtkIconViewItemAccessible *item;
GList *items;
GList *tmp_list;
int index;
AtkObject *atk_obj;
gint index;
index = gtk_tree_path_get_indices (path)[0];
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);
items = priv->items;
items = view->priv->items;
tmp_list = NULL;
while (items)
{
ItemAccessibleInfo *info = items->data;
GtkIconViewItemAccessible *item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
GList *next = items->next;
info = items->data;
item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
if (info->index != item->item->index)
{
if (info->index < index)
@@ -1083,36 +1091,40 @@ gtk_icon_view_accessible_model_row_inserted (GtkTreeModel *tree_model,
info->index = item->item->index;
}
items = next;
items = items->next;
}
gtk_icon_view_accessible_traverse_items (self, tmp_list);
g_signal_emit_by_name (self,
"children-changed::add",
gtk_icon_view_accessible_traverse_items (view, tmp_list);
g_signal_emit_by_name (atk_obj, "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)
{
GtkIconViewAccessible *self = user_data;
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GtkIconViewItemAccessibleInfo *info;
GtkIconViewAccessible *view;
GtkIconViewItemAccessible *item;
GList *items;
GList *tmp_list = NULL;
GList *deleted_item = NULL;
int index;
GList *tmp_list;
GList *deleted_item;
AtkObject *atk_obj;
gint index;
index = gtk_tree_path_get_indices (path)[0];
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);
items = priv->items;
items = view->priv->items;
tmp_list = NULL;
deleted_item = NULL;
info = NULL;
while (items)
{
ItemAccessibleInfo *info = items->data;
GtkIconViewItemAccessible *item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
GList *next = items->next;
info = items->data;
item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
if (info->index == index)
{
deleted_item = items;
@@ -1125,32 +1137,26 @@ gtk_icon_view_accessible_model_row_deleted (GtkTreeModel *tree_model,
info->index = item->item->index;
}
items = next;
items = items->next;
}
if (deleted_item)
{
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",
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",
index, NULL, NULL);
priv->items = g_list_delete_link (priv->items, deleted_item);
view->priv->items = g_list_delete_link (view->priv->items, deleted_item);
g_object_unref (info->item);
g_free (info);
}
gtk_icon_view_accessible_traverse_items (view, tmp_list);
gtk_icon_view_accessible_traverse_items (self, tmp_list);
return;
}
static gint
gtk_icon_view_accessible_item_compare (ItemAccessibleInfo *i1,
ItemAccessibleInfo *i2)
gtk_icon_view_accessible_item_compare (GtkIconViewItemAccessibleInfo *i1,
GtkIconViewItemAccessibleInfo *i2)
{
return i1->index - i2->index;
}
@@ -1160,138 +1166,151 @@ gtk_icon_view_accessible_model_rows_reordered (GtkTreeModel *tree_model,
GtkTreePath *path,
GtkTreeIter *iter,
gint *new_order,
gpointer user_data)
gpointer user_data)
{
GtkIconViewAccessible *self = user_data;
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GtkIconViewAccessible *view;
GtkIconViewItemAccessibleInfo *info;
GtkIconView *icon_view;
GtkIconViewItemAccessible *item;
GList *items;
int *order;
int length, i;
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;
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 (int, length);
order = g_new (gint, length);
for (i = 0; i < length; i++)
order [new_order[i]] = i;
items = priv->items;
items = view->priv->items;
while (items)
{
ItemAccessibleInfo *info = items->data;
GtkIconViewItemAccessible *item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
GList *next = items->next;
info = items->data;
item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
info->index = order[info->index];
item->item = g_list_nth_data (icon_view->priv->items, info->index);
items = next;
items = items->next;
}
g_free (order);
view->priv->items = g_list_sort (view->priv->items,
(GCompareFunc)gtk_icon_view_accessible_item_compare);
priv->items = g_list_sort (priv->items, (GCompareFunc) gtk_icon_view_accessible_item_compare);
return;
}
static void
gtk_icon_view_accessible_disconnect_model_signals (GtkIconViewAccessible *self)
gtk_icon_view_accessible_disconnect_model_signals (GtkTreeModel *model,
GtkWidget *widget)
{
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GObject *obj;
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);
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);
}
static void
gtk_icon_view_accessible_connect_model_signals (GtkIconViewAccessible *self)
gtk_icon_view_accessible_connect_model_signals (GtkIconView *icon_view)
{
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GObject *obj;
g_signal_connect_object (priv->model, "row-changed",
obj = G_OBJECT (icon_view->priv->model);
g_signal_connect_object (obj, "row-changed",
G_CALLBACK (gtk_icon_view_accessible_model_row_changed),
self, 0);
g_signal_connect_object (priv->model, "row-inserted",
icon_view, 0);
g_signal_connect_object (obj, "row-inserted",
G_CALLBACK (gtk_icon_view_accessible_model_row_inserted),
self, G_CONNECT_AFTER);
g_signal_connect_object (priv->model, "row-deleted",
icon_view, G_CONNECT_AFTER);
g_signal_connect_object (obj, "row-deleted",
G_CALLBACK (gtk_icon_view_accessible_model_row_deleted),
self, G_CONNECT_AFTER);
g_signal_connect_object (priv->model, "rows-reordered",
icon_view, G_CONNECT_AFTER);
g_signal_connect_object (obj, "rows-reordered",
G_CALLBACK (gtk_icon_view_accessible_model_rows_reordered),
self, G_CONNECT_AFTER);
icon_view, G_CONNECT_AFTER);
}
static void
gtk_icon_view_accessible_clear_cache (GtkIconViewAccessible *self)
gtk_icon_view_accessible_clear_cache (GtkIconViewAccessible *view)
{
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GtkIconViewItemAccessibleInfo *info;
GList *items;
if (priv->items == NULL)
return;
items = priv->items;
while (items != NULL)
items = view->priv->items;
while (items)
{
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);
info = (GtkIconViewItemAccessibleInfo *) items->data;
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 (info);
items = next;
g_free (items->data);
items = items->next;
}
g_clear_pointer (&priv->items, g_list_free);
g_list_free (view->priv->items);
view->priv->items = NULL;
}
void
gtk_icon_view_accessible_update_model (GtkIconViewAccessible *self,
GtkTreeModel *model)
static void
gtk_icon_view_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GtkIconView *icon_view;
GtkWidget *widget;
AtkObject *atk_obj;
GtkIconViewAccessible *view;
if (priv->model != NULL)
if (strcmp (pspec->name, "model") == 0)
{
g_object_remove_weak_pointer (G_OBJECT (priv->model),
(gpointer *) &priv->model);
gtk_icon_view_accessible_disconnect_model_signals (self);
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);
}
}
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);
}
return;
}
static void
gtk_icon_view_accessible_initialize (AtkObject *accessible,
gpointer data)
{
GtkIconViewAccessible *self = GTK_ICON_VIEW_ACCESSIBLE (accessible);
GtkIconViewAccessiblePrivate *priv = gtk_icon_view_accessible_get_instance_private (self);
GtkIconView *icon_view = data;
GtkIconViewAccessible *view;
GtkIconView *icon_view;
if (ATK_OBJECT_CLASS (gtk_icon_view_accessible_parent_class)->initialize)
ATK_OBJECT_CLASS (gtk_icon_view_accessible_parent_class)->initialize (accessible, data);
priv->model = icon_view->priv->model;
if (priv->model)
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)
{
g_object_add_weak_pointer (G_OBJECT (priv->model), (gpointer *) &priv->model);
gtk_icon_view_accessible_connect_model_signals (self);
g_object_add_weak_pointer (G_OBJECT (view->priv->model), (gpointer *)&view->priv->model);
gtk_icon_view_accessible_connect_model_signals (icon_view);
}
accessible->role = ATK_ROLE_LAYERED_PANE;
@@ -1300,7 +1319,7 @@ gtk_icon_view_accessible_initialize (AtkObject *accessible,
static void
gtk_icon_view_accessible_finalize (GObject *object)
{
GtkIconViewAccessible *view = GTK_ICON_VIEW_ACCESSIBLE (object);
GtkIconViewAccessible *view = (GtkIconViewAccessible*)object;
gtk_icon_view_accessible_clear_cache (view);
@@ -1310,8 +1329,11 @@ gtk_icon_view_accessible_finalize (GObject *object)
static void
gtk_icon_view_accessible_class_init (GtkIconViewAccessibleClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass);
GObjectClass *gobject_class;
AtkObjectClass *atk_class;
gobject_class = (GObjectClass *)klass;
atk_class = (AtkObjectClass *)klass;
gobject_class->finalize = gtk_icon_view_accessible_finalize;
@@ -1323,6 +1345,7 @@ 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*
+3
View File
@@ -35,10 +35,13 @@ G_BEGIN_DECLS
typedef struct _GtkIconViewAccessible GtkIconViewAccessible;
typedef struct _GtkIconViewAccessibleClass GtkIconViewAccessibleClass;
typedef struct _GtkIconViewAccessiblePrivate GtkIconViewAccessiblePrivate;
struct _GtkIconViewAccessible
{
GtkWidgetAccessible parent;
GtkIconViewAccessiblePrivate *priv;
};
struct _GtkIconViewAccessibleClass
+2 -4
View File
@@ -19,14 +19,12 @@
#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 (GtkIconViewAccessible *self);
void gtk_icon_view_accessible_update_model (GtkIconViewAccessible *self,
GtkTreeModel *model);
void _gtk_icon_view_accessible_adjustment_changed (GtkIconView *icon_view);
G_END_DECLS
+24 -16
View File
@@ -18,11 +18,10 @@
#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);
@@ -30,36 +29,45 @@ G_DEFINE_TYPE_WITH_CODE (GtkLevelBarAccessible, gtk_level_bar_accessible, GTK_TY
G_IMPLEMENT_INTERFACE (ATK_TYPE_VALUE, atk_value_interface_init))
static void
on_value_changed (GObject *gobject,
GParamSpec *pspec,
gpointer user_data)
gtk_level_bar_accessible_initialize (AtkObject *obj,
gpointer data)
{
GtkLevelBarAccessible *self = user_data;
ATK_OBJECT_CLASS (gtk_level_bar_accessible_parent_class)->initialize (obj, data);
g_object_notify (G_OBJECT (self), "accessible-value");
obj->role = ATK_ROLE_LEVEL_BAR;
}
static void
gtk_level_bar_accessible_initialize (AtkObject *object,
gpointer data)
gtk_level_bar_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
GtkLevelBar *level_bar = data;
GtkWidget *widget = GTK_WIDGET (obj);
GtkLevelBarAccessible *level_bar = GTK_LEVEL_BAR_ACCESSIBLE (gtk_widget_get_accessible (widget));
g_signal_connect (level_bar, "notify::value", G_CALLBACK (on_value_changed), object);
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);
}
static void
gtk_level_bar_accessible_class_init (GtkLevelBarAccessibleClass *klass)
{
AtkObjectClass *object_class = ATK_OBJECT_CLASS (klass);
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
object_class->initialize = gtk_level_bar_accessible_initialize;
widget_class->notify_gtk = gtk_level_bar_accessible_notify_gtk;
class->initialize = gtk_level_bar_accessible_initialize;
}
static void
gtk_level_bar_accessible_init (GtkLevelBarAccessible *self)
gtk_level_bar_accessible_init (GtkLevelBarAccessible *button)
{
ATK_OBJECT (self)->role = ATK_ROLE_LEVEL_BAR;
}
static void
+44 -29
View File
@@ -17,12 +17,10 @@
#include "config.h"
#include "gtknotebookaccessibleprivate.h"
#include "gtknotebookpageaccessible.h"
#include "gtknotebook.h"
#include <string.h>
#include <gtk/gtk.h>
#include "gtknotebookaccessible.h"
#include "gtknotebookpageaccessible.h"
struct _GtkNotebookAccessiblePrivate
{
@@ -155,41 +153,55 @@ gtk_notebook_accessible_ref_child (AtkObject *obj,
return child;
}
void
gtk_notebook_accessible_update_page (GtkNotebookAccessible *self,
int page_num)
static void
gtk_notebook_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
GtkNotebookAccessiblePrivate *priv = gtk_notebook_accessible_get_instance_private (self);
AtkObject *atk_obj = ATK_OBJECT (self);
int old_page_num = priv->selected_page;
GtkWidget *widget;
AtkObject* atk_obj;
priv->selected_page = page_num;
widget = GTK_WIDGET (obj);
atk_obj = gtk_widget_get_accessible (widget);
/* Notify SELECTED state change for old and new page */
if (page_num != old_page_num)
if (strcmp (pspec->name, "page") == 0)
{
AtkObject *child;
gint page_num, old_page_num;
GtkNotebookAccessible *accessible;
GtkNotebook *notebook;
if (old_page_num != -1)
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)
{
child = gtk_notebook_accessible_ref_child (atk_obj, old_page_num);
if (child != NULL)
AtkObject *child;
if (old_page_num != -1)
{
atk_object_notify_state_change (child, ATK_STATE_SELECTED, FALSE);
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);
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);
}
/*
@@ -218,11 +230,14 @@ 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
View File
@@ -1,30 +0,0 @@
/* 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
View File
@@ -1,654 +0,0 @@
/* 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
View File
@@ -1,48 +0,0 @@
/* 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
@@ -1,29 +0,0 @@
/* 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
+30 -6
View File
@@ -21,28 +21,52 @@
#include <gtk/gtk.h>
#include "gtkprogressbaraccessibleprivate.h"
#include "gtkprogressbaraccessible.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))
void
gtk_progress_bar_accessible_update_value (GtkProgressBarAccessible *self)
static void
gtk_progress_bar_accessible_initialize (AtkObject *obj,
gpointer data)
{
g_object_notify (G_OBJECT (self), "accessible-value");
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);
}
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 *self)
gtk_progress_bar_accessible_init (GtkProgressBarAccessible *bar)
{
ATK_OBJECT (self)->role = ATK_ROLE_PROGRESS_BAR;
}
static void
+33 -42
View File
@@ -21,12 +21,10 @@
#include <gtk/gtk.h>
#include "gtkrangeaccessible.h"
typedef struct
struct _GtkRangeAccessiblePrivate
{
GtkAdjustment *adjustment;
gulong value_changed_id;
} GtkRangeAccessiblePrivate;
};
static void atk_value_interface_init (AtkValueIface *iface);
@@ -44,44 +42,35 @@ gtk_range_accessible_value_changed (GtkAdjustment *adjustment,
static void
gtk_range_accessible_widget_set (GtkAccessible *accessible)
{
GtkRangeAccessible *self = GTK_RANGE_ACCESSIBLE (accessible);
GtkRangeAccessiblePrivate *priv = gtk_range_accessible_get_instance_private (self);
GtkRangeAccessiblePrivate *priv = GTK_RANGE_ACCESSIBLE (accessible)->priv;
GtkWidget *range;
GtkAdjustment *adj;
range = gtk_accessible_get_widget (accessible);
adj = gtk_range_get_adjustment (GTK_RANGE (range));
if (adj != NULL)
if (adj)
{
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);
priv->adjustment = adj;
g_object_ref (priv->adjustment);
g_signal_connect (priv->adjustment, "value-changed",
G_CALLBACK (gtk_range_accessible_value_changed),
accessible);
}
}
static void
gtk_range_accessible_widget_unset (GtkAccessible *accessible)
{
GtkRangeAccessible *self = GTK_RANGE_ACCESSIBLE (accessible);
GtkRangeAccessiblePrivate *priv = gtk_range_accessible_get_instance_private (self);
GtkRangeAccessiblePrivate *priv = GTK_RANGE_ACCESSIBLE (accessible)->priv;
if (priv->adjustment != NULL &&
priv->value_changed_id != 0)
if (priv->adjustment)
{
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
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_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
@@ -93,40 +82,42 @@ gtk_range_accessible_initialize (AtkObject *obj,
}
static void
gtk_range_accessible_dispose (GObject *gobject)
gtk_range_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
GtkRangeAccessible *self = GTK_RANGE_ACCESSIBLE (gobject);
GtkRangeAccessiblePrivate *priv = gtk_range_accessible_get_instance_private (self);
GtkWidget *widget = GTK_WIDGET (obj);
AtkObject *range;
if (priv->adjustment != NULL && priv->value_changed_id != 0)
if (strcmp (pspec->name, "adjustment") == 0)
{
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
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_clear_object (&priv->adjustment);
G_OBJECT_CLASS (gtk_range_accessible_parent_class)->dispose (gobject);
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_range_accessible_parent_class)->notify_gtk (obj, pspec);
}
static void
gtk_range_accessible_class_init (GtkRangeAccessibleClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
AtkObjectClass *atkobject_class = ATK_OBJECT_CLASS (klass);
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkAccessibleClass *accessible_class = (GtkAccessibleClass*)klass;
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
gobject_class->dispose = gtk_range_accessible_dispose;
atkobject_class->initialize = gtk_range_accessible_initialize;
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
+3 -3
View File
@@ -35,10 +35,13 @@ G_BEGIN_DECLS
typedef struct _GtkRangeAccessible GtkRangeAccessible;
typedef struct _GtkRangeAccessibleClass GtkRangeAccessibleClass;
typedef struct _GtkRangeAccessiblePrivate GtkRangeAccessiblePrivate;
struct _GtkRangeAccessible
{
GtkWidgetAccessible parent;
GtkRangeAccessiblePrivate *priv;
};
struct _GtkRangeAccessibleClass
@@ -49,9 +52,6 @@ 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__ */
+35 -63
View File
@@ -23,107 +23,79 @@
#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
on_value_changed (GtkAdjustment *adjustment,
gpointer data)
gtk_scale_button_accessible_value_changed (GtkAdjustment *adjustment,
gpointer data)
{
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);
}
g_object_notify (G_OBJECT (data), "accessible-value");
}
static void
gtk_scale_button_accessible_initialize (AtkObject *obj,
gpointer data)
{
GtkScaleButton *scale_button = data;
GtkAdjustment *adjustment;
ATK_OBJECT_CLASS (gtk_scale_button_accessible_parent_class)->initialize (obj, data);
g_signal_connect (scale_button, "notify::adjustment",
G_CALLBACK (on_adjustment_changed),
obj);
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;
}
static void
gtk_scale_button_accessible_dispose (GObject *gobject)
gtk_scale_button_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
GtkScaleButtonAccessible *self = GTK_SCALE_BUTTON_ACCESSIBLE (gobject);
GtkScaleButtonAccessiblePrivate *priv =
gtk_scale_button_accessible_get_instance_private (self);
GtkScaleButton *scale_button;
GtkScaleButtonAccessible *accessible;
if (priv->adjustment != NULL && priv->value_changed_id != 0)
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)
{
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
priv->value_changed_id = 0;
GtkAdjustment* adjustment;
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);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = gtk_scale_button_accessible_dispose;
GtkWidgetAccessibleClass *widget_class = GTK_WIDGET_ACCESSIBLE_CLASS (klass);
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 *self)
gtk_scale_button_accessible_init (GtkScaleButtonAccessible *button)
{
ATK_OBJECT (self)->role = ATK_ROLE_SLIDER;
}
static gboolean
+3
View File
@@ -35,10 +35,13 @@ G_BEGIN_DECLS
typedef struct _GtkScaleButtonAccessible GtkScaleButtonAccessible;
typedef struct _GtkScaleButtonAccessibleClass GtkScaleButtonAccessibleClass;
typedef struct _GtkScaleButtonAccessiblePrivate GtkScaleButtonAccessiblePrivate;
struct _GtkScaleButtonAccessible
{
GtkWidgetAccessible parent;
GtkScaleButtonAccessiblePrivate *priv;
};
struct _GtkScaleButtonAccessibleClass
+54 -57
View File
@@ -21,11 +21,10 @@
#include <gtk/gtk.h>
#include "gtkscrollbaraccessible.h"
typedef struct
struct _GtkScrollbarAccessiblePrivate
{
GtkAdjustment *adjustment;
gulong value_changed_id;
} GtkScrollbarAccessiblePrivate;
};
static void atk_value_interface_init (AtkValueIface *iface);
@@ -34,93 +33,91 @@ G_DEFINE_TYPE_WITH_CODE (GtkScrollbarAccessible, gtk_scrollbar_accessible, GTK_T
G_IMPLEMENT_INTERFACE (ATK_TYPE_VALUE, atk_value_interface_init))
static void
on_value_changed (GtkAdjustment *adjustment,
gpointer data)
gtk_scrollbar_accessible_value_changed (GtkAdjustment *adjustment,
gpointer data)
{
GtkScrollbarAccessible *self = data;
g_object_notify (G_OBJECT (self), "accessible-value");
g_object_notify (G_OBJECT (data), "accessible-value");
}
static void
on_adjustment_changed (GObject *gobject,
GParamSpec *pspec,
gpointer data)
gtk_scrollbar_accessible_widget_set (GtkAccessible *accessible)
{
GtkScrollbar *scrollbar = GTK_SCROLLBAR (gobject);
GtkScrollbarAccessible *self = data;
GtkScrollbarAccessiblePrivate *priv =
gtk_scrollbar_accessible_get_instance_private (self);
GtkAdjustment *adjustment =
gtk_scrollbar_get_adjustment (scrollbar);
GtkScrollbarAccessiblePrivate *priv = GTK_SCROLLBAR_ACCESSIBLE (accessible)->priv;
GtkWidget *scrollbar;
GtkAdjustment *adj;
if (priv->adjustment == adjustment)
return;
if (priv->adjustment != NULL && priv->value_changed_id != 0)
scrollbar = gtk_accessible_get_widget (accessible);
adj = gtk_scrollbar_get_adjustment (GTK_SCROLLBAR (scrollbar));
if (adj)
{
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);
priv->adjustment = adj;
g_object_ref (priv->adjustment);
g_signal_connect (priv->adjustment, "value-changed",
G_CALLBACK (gtk_scrollbar_accessible_value_changed),
accessible);
}
}
static void
gtk_scrollbar_accessible_dispose (GObject *gobject)
gtk_scrollbar_accessible_widget_unset (GtkAccessible *accessible)
{
GtkScrollbarAccessible *self = GTK_SCROLLBAR_ACCESSIBLE (gobject);
GtkScrollbarAccessiblePrivate *priv =
gtk_scrollbar_accessible_get_instance_private (self);
GtkScrollbarAccessiblePrivate *priv = GTK_SCROLLBAR_ACCESSIBLE (accessible)->priv;
if (priv->adjustment != NULL && priv->value_changed_id != 0)
if (priv->adjustment)
{
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
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_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);
g_signal_connect (scrollbar, "notify::adjustment",
G_CALLBACK (on_adjustment_changed),
obj);
obj->role = ATK_ROLE_SCROLL_BAR;
}
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 *atk_object_class = ATK_OBJECT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkAccessibleClass *accessible_class = (GtkAccessibleClass*)klass;
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
atk_object_class->initialize = gtk_scrollbar_accessible_initialize;
class->initialize = gtk_scrollbar_accessible_initialize;
gobject_class->dispose = gtk_scrollbar_accessible_dispose;
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;
}
static void
gtk_scrollbar_accessible_init (GtkScrollbarAccessible *self)
gtk_scrollbar_accessible_init (GtkScrollbarAccessible *scrollbar)
{
ATK_OBJECT (self)->role = ATK_ROLE_SCROLL_BAR;
scrollbar->priv = gtk_scrollbar_accessible_get_instance_private (scrollbar);
}
static void
+3
View File
@@ -35,10 +35,13 @@ G_BEGIN_DECLS
typedef struct _GtkScrollbarAccessible GtkScrollbarAccessible;
typedef struct _GtkScrollbarAccessibleClass GtkScrollbarAccessibleClass;
typedef struct _GtkScrollbarAccessiblePrivate GtkScrollbarAccessiblePrivate;
struct _GtkScrollbarAccessible
{
GtkWidgetAccessible parent;
GtkScrollbarAccessiblePrivate *priv;
};
struct _GtkScrollbarAccessibleClass
File diff suppressed because it is too large Load Diff
-48
View File
@@ -1,48 +0,0 @@
/* 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
+51 -45
View File
@@ -24,7 +24,6 @@
struct _GtkSpinButtonAccessiblePrivate
{
GtkAdjustment *adjustment;
gulong value_changed_id;
};
static void atk_value_interface_init (AtkValueIface *iface);
@@ -34,84 +33,91 @@ G_DEFINE_TYPE_WITH_CODE (GtkSpinButtonAccessible, gtk_spin_button_accessible, GT
G_IMPLEMENT_INTERFACE (ATK_TYPE_VALUE, atk_value_interface_init))
static void
on_value_changed (GtkAdjustment *adjustment,
GtkSpinButtonAccessible *self)
gtk_spin_button_accessible_value_changed (GtkAdjustment *adjustment,
gpointer data)
{
g_object_notify (G_OBJECT (self), "accessible-value");
g_object_notify (G_OBJECT (data), "accessible-value");
}
static void
on_adjustment_changed (GObject *gobject,
GParamSpec *pspec,
gpointer data)
gtk_spin_button_accessible_widget_set (GtkAccessible *accessible)
{
GtkSpinButton *spin = GTK_SPIN_BUTTON (gobject);
GtkSpinButtonAccessible *self = data;
GtkSpinButtonAccessiblePrivate *priv = gtk_spin_button_accessible_get_instance_private (self);
GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (spin);
GtkSpinButtonAccessiblePrivate *priv = GTK_SPIN_BUTTON_ACCESSIBLE (accessible)->priv;
GtkWidget *spin;
GtkAdjustment *adj;
if (priv->adjustment == adjustment)
return;
if (priv->adjustment != NULL && priv->value_changed_id != 0)
spin = gtk_accessible_get_widget (accessible);
adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin));
if (adj)
{
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
priv->value_changed_id = 0;
priv->adjustment = adj;
g_object_ref (priv->adjustment);
g_signal_connect (priv->adjustment, "value-changed",
G_CALLBACK (gtk_spin_button_accessible_value_changed),
accessible);
}
}
g_clear_object (&priv->adjustment);
static void
gtk_spin_button_accessible_widget_unset (GtkAccessible *accessible)
{
GtkSpinButtonAccessiblePrivate *priv = GTK_SPIN_BUTTON_ACCESSIBLE (accessible)->priv;
if (adjustment != NULL)
if (priv->adjustment)
{
priv->adjustment = g_object_ref (adjustment);
priv->value_changed_id = g_signal_connect (priv->adjustment, "value-changed",
G_CALLBACK (on_value_changed),
self);
g_signal_handlers_disconnect_by_func (priv->adjustment,
G_CALLBACK (gtk_spin_button_accessible_value_changed),
accessible);
g_object_unref (priv->adjustment);
priv->adjustment = NULL;
}
}
static void
gtk_spin_button_accessible_initialize (AtkObject *obj,
gpointer data)
gpointer data)
{
ATK_OBJECT_CLASS (gtk_spin_button_accessible_parent_class)->initialize (obj, data);
g_signal_connect (data, "notify::adjustment", G_CALLBACK (on_adjustment_changed), obj);
obj->role = ATK_ROLE_SPIN_BUTTON;
}
static void
gtk_spin_button_accessible_dispose (GObject *gobject)
gtk_spin_button_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
GtkSpinButtonAccessible *self = GTK_SPIN_BUTTON_ACCESSIBLE (gobject);
GtkSpinButtonAccessiblePrivate *priv =
gtk_spin_button_accessible_get_instance_private (self);
GtkWidget *widget = GTK_WIDGET (obj);
AtkObject *spin;
if (priv->adjustment != NULL && priv->value_changed_id != 0)
if (strcmp (pspec->name, "adjustment") == 0)
{
g_signal_handler_disconnect (priv->adjustment, priv->value_changed_id);
priv->value_changed_id = 0;
spin = gtk_widget_get_accessible (widget);
gtk_spin_button_accessible_widget_unset (GTK_ACCESSIBLE (spin));
gtk_spin_button_accessible_widget_set (GTK_ACCESSIBLE (spin));
}
g_clear_object (&priv->adjustment);
G_OBJECT_CLASS (gtk_spin_button_accessible_parent_class)->dispose (gobject);
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_spin_button_accessible_parent_class)->notify_gtk (obj, pspec);
}
static void
gtk_spin_button_accessible_class_init (GtkSpinButtonAccessibleClass *klass)
{
AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkAccessibleClass *accessible_class = (GtkAccessibleClass*)klass;
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
atk_object_class->initialize = gtk_spin_button_accessible_initialize;
class->initialize = gtk_spin_button_accessible_initialize;
gobject_class->dispose = gtk_spin_button_accessible_dispose;
accessible_class->widget_set = gtk_spin_button_accessible_widget_set;
accessible_class->widget_unset = gtk_spin_button_accessible_widget_unset;
widget_class->notify_gtk = gtk_spin_button_accessible_notify_gtk;
}
static void
gtk_spin_button_accessible_init (GtkSpinButtonAccessible *self)
gtk_spin_button_accessible_init (GtkSpinButtonAccessible *button)
{
ATK_OBJECT (self)->role = ATK_ROLE_SPIN_BUTTON;
button->priv = gtk_spin_button_accessible_get_instance_private (button);
}
static void
@@ -201,8 +207,8 @@ gtk_spin_button_accessible_set_current_value (AtkValue *obj,
static void
gtk_spin_button_accessible_get_value_and_text (AtkValue *obj,
gdouble *value,
gchar **text)
gdouble *value,
gchar **text)
{
GtkWidget *widget;
GtkAdjustment *adjustment;
+56 -64
View File
@@ -109,65 +109,9 @@ gtk_text_accessible_get_attributes (AtkObject *accessible)
return attributes;
}
static void
on_cursor_position_changed (GObject *gobject,
GParamSpec *pspec,
AtkObject *accessible)
{
GtkTextAccessible *self = GTK_TEXT_ACCESSIBLE (accessible);
GtkTextAccessiblePrivate *priv = gtk_text_accessible_get_instance_private (self);
GtkText *text = GTK_TEXT (gobject);
if (check_for_selection_change (self, text))
g_signal_emit_by_name (accessible, "text-selection-changed");
/* The entry cursor position has moved so generate the signal */
g_signal_emit_by_name (accessible,
"text-caret-moved",
priv->cursor_position);
}
static void
on_selection_bound_changed (GObject *gobject,
GParamSpec *pspec,
AtkObject *accessible)
{
GtkTextAccessible *self = GTK_TEXT_ACCESSIBLE (accessible);
GtkText *text = GTK_TEXT (gobject);
if (check_for_selection_change (self, text))
g_signal_emit_by_name (accessible, "text-selection-changed");
}
static void
on_editable_changed (GObject *gobject,
GParamSpec *pspec,
AtkObject *accessible)
{
GtkEditable *editable = GTK_EDITABLE (gobject);
gboolean value = gtk_editable_get_editable (editable);
atk_object_notify_state_change (accessible, ATK_STATE_EDITABLE, value);
}
static void
on_visibility_changed (GObject *gobject,
GParamSpec *pspec,
AtkObject *accessible)
{
GtkText *text = GTK_TEXT (gobject);
AtkRole new_role;
new_role = gtk_text_get_visibility (text)
? ATK_ROLE_TEXT
: ATK_ROLE_PASSWORD_TEXT;
atk_object_set_role (accessible, new_role);
}
static void
gtk_text_accessible_initialize (AtkObject *obj,
gpointer data)
gpointer data)
{
GtkText *entry;
GtkTextAccessible *gtk_text_accessible;
@@ -186,21 +130,66 @@ gtk_text_accessible_initialize (AtkObject *obj,
g_signal_connect_after (entry, "insert-text", G_CALLBACK (insert_text_cb), NULL);
g_signal_connect (entry, "delete-text", G_CALLBACK (delete_text_cb), NULL);
g_signal_connect (entry, "notify::cursor-position", G_CALLBACK (on_cursor_position_changed), obj);
g_signal_connect (entry, "notify::selection-bound", G_CALLBACK (on_selection_bound_changed), obj);
g_signal_connect (entry, "notify::editable", G_CALLBACK (on_editable_changed), obj);
g_signal_connect (entry, "notify::visibility", G_CALLBACK (on_visibility_changed), obj);
if (gtk_text_get_visibility (entry))
obj->role = ATK_ROLE_TEXT;
else
obj->role = ATK_ROLE_PASSWORD_TEXT;
}
static void
gtk_text_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
GtkWidget *widget;
AtkObject* atk_obj;
GtkText* gtk_text;
GtkTextAccessible* entry;
widget = GTK_WIDGET (obj);
atk_obj = gtk_widget_get_accessible (widget);
gtk_text = GTK_TEXT (widget);
entry = GTK_TEXT_ACCESSIBLE (atk_obj);
if (g_strcmp0 (pspec->name, "cursor-position") == 0)
{
if (check_for_selection_change (entry, gtk_text))
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",
entry->priv->cursor_position);
}
else if (g_strcmp0 (pspec->name, "selection-bound") == 0)
{
if (check_for_selection_change (entry, gtk_text))
g_signal_emit_by_name (atk_obj, "text-selection-changed");
}
else if (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 (g_strcmp0 (pspec->name, "visibility") == 0)
{
gboolean visibility;
AtkRole new_role;
visibility = gtk_text_get_visibility (gtk_text);
new_role = visibility ? ATK_ROLE_TEXT : ATK_ROLE_PASSWORD_TEXT;
atk_object_set_role (atk_obj, new_role);
}
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_text_accessible_parent_class)->notify_gtk (obj, pspec);
}
static gint
gtk_text_accessible_get_index_in_parent (AtkObject *accessible)
{
/* If the parent widget is a combo box then the index is 1
/*
* If the parent widget is a combo box then the index is 1
* otherwise do the normal thing.
*/
if (accessible->accessible_parent)
@@ -213,12 +202,15 @@ gtk_text_accessible_get_index_in_parent (AtkObject *accessible)
static void
gtk_text_accessible_class_init (GtkTextAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
class->ref_state_set = gtk_text_accessible_ref_state_set;
class->get_index_in_parent = gtk_text_accessible_get_index_in_parent;
class->initialize = gtk_text_accessible_initialize;
class->get_attributes = gtk_text_accessible_get_attributes;
widget_class->notify_gtk = gtk_text_accessible_notify_gtk;
}
static void
+21 -15
View File
@@ -67,18 +67,6 @@ G_DEFINE_TYPE_WITH_CODE (GtkTextViewAccessible, gtk_text_view_accessible, GTK_TY
G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init))
static void
on_editable_changed (GObject *gobject,
GParamSpec *pspec,
AtkObject *accessible)
{
GtkTextView *text_view = GTK_TEXT_VIEW (gobject);
atk_object_notify_state_change (accessible,
ATK_STATE_EDITABLE,
gtk_text_view_get_editable (text_view));
}
static void
gtk_text_view_accessible_initialize (AtkObject *obj,
gpointer data)
@@ -86,10 +74,25 @@ gtk_text_view_accessible_initialize (AtkObject *obj,
ATK_OBJECT_CLASS (gtk_text_view_accessible_parent_class)->initialize (obj, data);
obj->role = ATK_ROLE_TEXT;
}
g_signal_connect (data, "notify::editable",
G_CALLBACK (on_editable_changed),
obj);
static void
gtk_text_view_accessible_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
AtkObject *atk_obj;
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (obj));
if (!strcmp (pspec->name, "editable"))
{
gboolean editable;
editable = gtk_text_view_get_editable (GTK_TEXT_VIEW (obj));
atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE, editable);
}
else
GTK_WIDGET_ACCESSIBLE_CLASS (gtk_text_view_accessible_parent_class)->notify_gtk (obj, pspec);
}
static AtkStateSet*
@@ -164,12 +167,15 @@ gtk_text_view_accessible_class_init (GtkTextViewAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkAccessibleClass *accessible_class = GTK_ACCESSIBLE_CLASS (klass);
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
accessible_class->widget_set = gtk_text_view_accessible_widget_set;
accessible_class->widget_unset = gtk_text_view_accessible_widget_unset;
class->ref_state_set = gtk_text_view_accessible_ref_state_set;
class->initialize = gtk_text_view_accessible_initialize;
widget_class->notify_gtk = gtk_text_view_accessible_notify_gtk;
}
static void

Some files were not shown because too many files have changed in this diff Show More