Compare commits

..

12 Commits

Author SHA1 Message Date
Matthias Clasen 406a32d825 Fix the build 2023-02-12 16:31:40 -05:00
Matthias Clasen beabe8c33b gsk: Drop an unnecessary call
The renderer should make all the necessary
make_current calls.
2023-02-12 15:12:43 -05:00
Matthias Clasen 90500519d6 gst: Add a comment about context confusion 2023-02-12 15:12:43 -05:00
Matthias Clasen 06921674a9 gsk: Only wait if we need to
If the texture was created in the same context
we are using it in, then waiting on the sync
will be a no-op.
2023-02-12 15:12:43 -05:00
Matthias Clasen a91fa9a680 gltexture: Only wait if we need to
If the texture was created in the same context
we are downloading it from, then waiting on the
sync will be a no-op.
2023-02-12 15:12:43 -05:00
Matthias Clasen ead40dc834 gldriver: Add a sync when creating textures 2023-02-12 15:12:43 -05:00
Matthias Clasen 2be928b569 gstreamer: Defer the sync
Don't sync right when we receive the buffer,
pass it along with the texture to be executed
later in the renderer.
2023-02-12 15:12:43 -05:00
Matthias Clasen 621ba6d67c Export gdk_gl_texture_new_with_sync
Otherwise we can't use it in the loadable modules,
like the GStreamer media stream.

This change puts gdk_gl_texture_new_with_sync into
the private, but exported bucket for now. We will
make new public APIs for textures (including
synchronization) when we add color management support.
2023-02-12 15:12:43 -05:00
Matthias Clasen af929a8787 glarea: Synchronize
Create a fence object and pass it along when
creating the GL texture, so that the GL renderer
can wait for the texture to be ready.
2023-02-12 15:12:43 -05:00
Matthias Clasen ef986f4256 gsk: Synchronize when using textures
Pass the GLsync object from texture into our
command queue, and when executing the queue,
wait on the sync object the first time we
use its associated texture.
2023-02-12 15:12:41 -05:00
Matthias Clasen ab36c275cf gltexture: Synchronize when downloading
If the GL texture has a sync object, wait
on it before downloading the data.
2023-02-12 15:09:21 -05:00
Matthias Clasen 720327bc00 gltexture: Optionally take a sync object
Add a new (private, for now) constructor takes
a GLsync together with a texture id, for synchronization.
2023-02-12 15:09:21 -05:00
397 changed files with 41264 additions and 46826 deletions
+56 -73
View File
@@ -26,31 +26,25 @@ variables:
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled -Ddemos=false -Dbuild-examples=false -Dbuild-tests=false -Dbuild-testsuite=true"
MESON_TEST_TIMEOUT_MULTIPLIER: 3
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v41"
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v40"
FLATPAK_IMAGE: "quay.io/gnome_infrastructure/gnome-runtime-images:gnome-master"
workflow:
rules:
- if: $CI_COMMIT_TAG
- if: $CI_COMMIT_BRANCH
default:
retry:
max: 2
when:
- 'runner_system_failure'
- 'stuck_or_timeout_failure'
- 'scheduler_failure'
- 'api_failure'
interruptible: true
.only-default:
only:
- branches
except:
- tags
style-check-diff:
extends: .only-default
image: $FEDORA_IMAGE
stage: check
when: manual
allow_failure: true
script:
- .gitlab-ci/run-style-check-diff.sh
.build-fedora-default:
extends: .only-default
image: $FEDORA_IMAGE
artifacts:
when: always
@@ -166,6 +160,7 @@ fedora-mingw64:
- ninja -C _build
.mingw-defaults:
extends: .only-default
stage: build
tags:
- win32-ps
@@ -197,8 +192,9 @@ msys2-mingw64:
macos:
# Sadly, this fails regularly, and its failure is never enlightening
allow_failure: true
rules:
- if: $CI_PROJECT_NAMESPACE == "GNOME"
extends: .only-default
only:
- branches@GNOME/gtk
stage: build
tags:
- macos
@@ -231,9 +227,10 @@ macos:
- "${CI_PROJECT_DIR}/_build/meson-logs"
vs2017-x64:
extends: .only-default
# TODO: Uncomment this when ready to merge.
# rules:
# - if: $CI_PROJECT_NAMESPACE == "GNOME"
#only:
# - branches@GNOME/gtk
stage: build
tags:
- win32-ps
@@ -246,7 +243,7 @@ vs2017-x64:
- "${CI_PROJECT_DIR}/_build/meson-logs"
.flatpak-defaults:
image: "quay.io/gnome_infrastructure/gnome-runtime-images:gnome-master"
image: $FLATPAK_IMAGE
stage: flatpak
allow_failure: true
tags:
@@ -256,67 +253,65 @@ vs2017-x64:
- "${APPID}-dev.flatpak"
- 'repo.tar'
expire_in: 1 day
rules:
# Only build Flatpak bundles automatically on main
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH != "main"
when: "manual"
script:
- bash -x ./.gitlab-ci/flatpak-build.sh "${APPID}"
flatpak:demo:
extends: '.flatpak-defaults'
# Manual jobs, for branches and MRs
.flatpak-manual:
extends: .flatpak-defaults
when: manual
# Only build Flatpak bundles automatically on main
.flatpak-main:
extends: .flatpak-defaults
only:
- main
flatpak-manual:demo:
extends: .flatpak-manual
needs: []
variables:
APPID: org.gtk.Demo4
flatpak:demo:aarch64:
extends: '.flatpak-defaults'
flatpak-main:demo:
extends: .flatpak-main
needs: []
tags:
- flatpak-aarch64
variables:
APPID: org.gtk.Demo4
flatpak:widget-factory:
extends: '.flatpak-defaults'
flatpak-manual:widget-factory:
extends: .flatpak-manual
needs: []
variables:
APPID: org.gtk.WidgetFactory4
flatpak:widget-factory:aarch64:
extends: '.flatpak-defaults'
flatpak-main:widget-factory:
extends: .flatpak-main
needs: []
tags:
- flatpak-aarch64
variables:
APPID: org.gtk.WidgetFactory4
flatpak:icon-browser:
extends: '.flatpak-defaults'
flatpak-manual:icon-browser:
extends: .flatpak-manual
needs: []
variables:
APPID: org.gtk.IconBrowser4
flatpak:icon-browser:aarch64:
extends: '.flatpak-defaults'
flatpak-main:icon-browser:
extends: .flatpak-main
needs: []
tags:
- flatpak-aarch64
variables:
APPID: org.gtk.IconBrowser4
flatpak:node-editor:
extends: '.flatpak-defaults'
flatpak-manual:node-editor:
extends: .flatpak-manual
needs: []
variables:
APPID: org.gtk.gtk4.NodeEditor
flatpak:node-editor:aarch64:
extends: '.flatpak-defaults'
flatpak-main:node-editor:
extends: .flatpak-main
needs: []
tags:
- flatpak-aarch64
variables:
APPID: org.gtk.gtk4.NodeEditor
@@ -325,35 +320,23 @@ flatpak:node-editor:aarch64:
# https://gitlab.gnome.org/GNOME/Initiatives/-/wikis/DevOps-with-Flatpak
nightly demo:
extends: '.publish_nightly'
needs: ['flatpak:demo']
nightly demo aarch64:
extends: '.publish_nightly'
needs: ['flatpak:demo:aarch64']
dependencies: ['flatpak-main:demo']
needs: ['flatpak-main:demo']
nightly factory:
extends: '.publish_nightly'
needs: ['flatpak:widget-factory']
nightly factory aarch64:
extends: '.publish_nightly'
needs: ['flatpak:widget-factory:aarch64']
dependencies: ['flatpak-main:widget-factory']
needs: ['flatpak-main:widget-factory']
nightly icon-browser:
extends: '.publish_nightly'
needs: ['flatpak:icon-browser']
nightly icon-browser aarch64:
extends: '.publish_nightly'
needs: ['flatpak:icon-browser:aarch64']
dependencies: ['flatpak-main:icon-browser']
needs: ['flatpak-main:icon-browser']
nightly node-editor:
extends: '.publish_nightly'
needs: ['flatpak:node-editor']
nightly node-editor aarch64:
extends: '.publish_nightly'
needs: ['flatpak:node-editor:aarch64']
dependencies: ['flatpak-main:node-editor']
needs: ['flatpak-main:node-editor']
static-scan:
image: $FEDORA_IMAGE
@@ -436,9 +419,9 @@ reference:
publish-docs:
image: fedora:latest
stage: publish
interruptible: false
needs: ['reference']
script:
- "curl -X POST -F token=${PAGES_TRIGGER_TOKEN} -F ref=docs-gtk-org https://gitlab.gnome.org/api/v4/projects/665/trigger/pipeline"
rules:
- if: $CI_COMMIT_REF_NAME == "main"
only:
refs:
- main
-1
View File
@@ -82,7 +82,6 @@ RUN dnf -y install \
python3-gobject \
python3-jinja2 \
python3-markdown \
python3-packaging \
python3-pip \
python3-pygments \
python3-typogrify \
-1
View File
@@ -20,7 +20,6 @@ flatpak build ${builddir} meson \
-Dx11-backend=true \
-Dwayland-backend=true \
-Dbuild-tests=false \
-Dbuild-testsuite=false \
-Dbuild-examples=false \
-Dintrospection=disabled \
-Ddemos=true \
+5 -17
View File
@@ -23,7 +23,6 @@ push=0
list=0
print_help=0
no_login=0
no_cache=0
while (($# > 0)); do
case "${1%%=*}" in
@@ -35,7 +34,6 @@ while (($# > 0)); do
--base|-b) read_arg base "$@" || shift;;
--version|-v) read_arg base_version "$@" || shift;;
--no-login) no_login=1;;
--no-cache) no_cache=1;;
*) echo -e "\e[1;31mERROR\e[0m: Unknown option '$1'"; exit 1;;
esac
shift
@@ -105,21 +103,11 @@ TAG="${REGISTRY}/gnome/gtk/${base}:${base_version}"
if [ $build == 1 ]; then
echo -e "\e[1;32mBUILDING\e[0m: ${base} as ${TAG}"
if [ $no_cache == 0 ]; then
${CMD} build \
${format} \
--build-arg HOST_USER_ID="$UID" \
--tag "${TAG}" \
--file "${base}.Dockerfile" .
else
${CMD} build \
${format} \
--no-cache \
--build-arg HOST_USER_ID="$UID" \
--tag "${TAG}" \
--file "${base}.Dockerfile" .
fi
${CMD} build \
${format} \
--build-arg HOST_USER_ID="$UID" \
--tag "${TAG}" \
--file "${base}.Dockerfile" .
exit $?
fi
+2 -232
View File
@@ -1,230 +1,8 @@
Overview of Changes in 4.10.5, 05-08-2023
=========================================
* Fix ordering problems with filter model signals
* Avoid lingering resize cursors
* Fix alignment issues on sparc
* Fix a problem with CSS corner values
* Translation updates
Brazilian Portuguese
Czech
Greek
Spanish
Vietnamese
Overview of Changes in 4.10.4, 05-06-2023
=========================================
* GtkFileChooser
- Fix some memory leaks
* GtkUriLauncher
- Validate the uri
* GtkStack
- Fix a crash
* GtkGridView
- Respect css border-spacing
* GtkScrolledWindow
- Propagate child measure size whenever possible
* GtkPopoverMenu:
- Avoid unnecessary left padding
* GtkSearchEntry:
- Improve size allocation for the clear icon
* X11
- Avoid black flickering with xwayland window decorations
- Trap XRandr errors
* CSS
- Various fixes to transitions
* Translation updates:
Basque
Catalan
Chinese (China)
French
Galician
Indonesian
Lithuanian
Persian
Russian
Swedish
Turkish
Ukrainian
Overview of Changes in 4.10.3, 22-04-2023
=========================================
* Fix a popover positioning regression in 4.10.2
* Fix issues with slow loading files in the file chooser
Overview of Changes in 4.10.2, 21-04-2023
=========================================
* Fixed issues:
- Holding control to select multiple files broken in filechooser (#5669)
- Inspector crash (#5681)
- Listbase doesn't account for bottom padding in size_allocate_child (#5380)
- Leaking AT contexts (#5690)
- OpenGL / Windows: Crash when closing gtk4-widget-factory (#5685)
- GTK apps crash on startup when setting cursor-size to 0 on Wayland (#5700)
- Segmentation fault: gdk_wayland_toplevel_set_startup_id() needs to null-check
display->xdg_activation before using it (#5701)
- Possible use-after-free under gtk_scrolled_window_update_use_indicators() (#5684)
- Wrong error message in `gtk_init` (#5704)
- Segfault when scrolling after changing ListView model (#5763)
- Bluetooth panel from the Settings app: clicking in the "Downloads" link
no longer opens Nautilus (#5671)
- Broadway docs or code is broken (#5662)
- Disabled GtkPicture's are not properly themed (#5683)
- Setting CSS padding to a GtkTextView gives the context menu an offset (#5695)
- A11y: the Showing state is used only for windows (#5194)
- Gtk4 expander: CSS nodes mismatch code vs. documentation (#5723)
- Invoking gtk inspector on a folder results in a crash (#5729)
- Double tap requires very precise touch input (#5580)
- Name autocompletion dropdown in the GTK4 FileChooser's Save dialog gets
stuck, creates artifacts, jumps around (#5743)
- Links are not opened when xdg-desktop-portal OpenURI is not available (#5733)
- GtkSnapshot generates no nodes appending whitespace-only layouts (#5747)
* Translation updates
British English
Bulgarian
Chinese (China)
French
Indonesian
Korean
Russian
Serbian
Slovenian
Turkish
Overview of Changes in 4.10.1, 14-03-2023
=========================================
* GtkFileChooser
- Improve search performance
- Be safe against pathless files
- Fix memory leaks
- Only show local files in recent files
- Show most recent files first
- Make files non-selectable in selet_folder mode
* GtkListView / GtkColumnView / GtkGridView
- Fix scrolling problems
- Support CSS border-spacing
* GtkComboBox
- Fix a size allocation problem
* gtk
- Size allocation fixes
* Accessibility
- Miscellaneous property fixes and improvements
* Wayland
- Fix an ordering problem in surface disposal
* Windows
- Fix Visual Studio build with older GLib
* Translation updates
Basque
Bulgarian
Catalan
Czech
Danish
Finnish
Friulian
Galician
Georgian
Hungarian
Lithuanian
Polish
Portuguese
Swedish
Turkish
Ukrainian
Overview of Changes in 4.10.0, 04-03-2023
=========================================
* GtkTextView
- Document hanging indentation
* GtkListView
- Fix a size allocation problem
* GtkFileChooser
- Fix paned behavior
- Fix a crash
* GtkText
- Fix various problems with undo
* Accessibility
- Make some getters transfer-full
- Allow setting accessible parents and siblings
- Add a role for toggle buttons
- Miscellaneous property fixes and improvements
* gtk
- Improve the handling resize-during-size-allocate
* gdk
- Introduce GdkTextureDownloader and use it
- Make gdk_texture_get_format public
* gsk
- Make mask nodes more versatile
- Improve the GL implementation for texture scale nodes
* X11
- Fix key handling during DND
* Tools
- gtk-builder-tool: Try harder to handle templates
- gtk-builder-tool: Prefer properties over <child>
* Translation updates
Basque
Belarusian
Bulgarian
Indonesian
Galician
Georgian
German
Hebrew
Lithuanian
Portuguese
Spanish
Swedish
Turkish
Ukrainian
Overview of Changes in 4.9.4, 12-02-2023
Overview of Changes in 4.9.4, xx-xx-xxxx
========================================
* Printing:
- Add a CPDB backend
- Drop the lpr backend
- Add a CPDB print backend
* GtkFileDialog:
- Robustness fixes
@@ -232,28 +10,20 @@ Overview of Changes in 4.9.4, 12-02-2023
* GtkScaleButton:
- Add an 'active' property
* GtkSearchEntry:
- Add placeholder text
* Fix conflicting type names between gtk and gio
* Gsk:
- Settable filtering for scaled textures
- Add mask nodes
- Some robustness and crash fixes
* Wayland:
- Handle dispatch failing in more places
* Deprecations:
- GtkVolumeButton
* Translation updates:
Belarusian
Chinese (Taiwan)
Georgian
Turkish
Ukrainian
Overview of Changes in 4.9.3, 04-02-2023
+1 -1
View File
@@ -9,7 +9,7 @@ constraint_editor_sources = [
constraint_editor_resources = gnome.compile_resources('constraint_editor_resources',
'constraint-editor.gresource.xml',
source_dir: meson.current_source_dir(),
source_dir: '.',
)
executable('gtk4-constraint-editor',
+24 -171
View File
@@ -5,8 +5,7 @@ enum
{
PROP_TEXTURE = 1,
PROP_FILTER,
PROP_SCALE,
PROP_ANGLE,
PROP_SCALE
};
struct _Demo3Widget
@@ -15,7 +14,6 @@ struct _Demo3Widget
GdkTexture *texture;
float scale;
float angle;
GskScalingFilter filter;
GtkWidget *menu;
@@ -28,85 +26,10 @@ struct _Demo3WidgetClass
G_DEFINE_TYPE (Demo3Widget, demo3_widget, GTK_TYPE_WIDGET)
static gboolean
query_tooltip (GtkWidget *widget,
int x,
int y,
gboolean keyboard_mode,
GtkTooltip *tooltip,
gpointer data)
{
Demo3Widget *self = DEMO3_WIDGET (widget);
GtkWidget *grid;
GtkWidget *label;
char *s, *s2;
const char *filter[] = { "Linear", "Nearest", "Trilinear" };
int precision, l;
grid = gtk_grid_new ();
gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
label = gtk_label_new ("Texture");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
s = g_strdup_printf ("%d\342\200\206\303\227\342\200\206%d",
gdk_texture_get_width (self->texture),
gdk_texture_get_height (self->texture));
label = gtk_label_new (s);
g_free (s);
gtk_label_set_xalign (GTK_LABEL (label), 1);
gtk_grid_attach (GTK_GRID (grid), label, 1, 0, 1, 1);
label = gtk_label_new ("Rotation");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
s = g_strdup_printf ("%.1f", self->angle);
if (g_str_has_suffix (s, ".0"))
s[strlen (s) - 2] = '\0';
s2 = g_strconcat (s, "\302\260", NULL);
label = gtk_label_new (s2);
g_free (s2);
g_free (s);
gtk_label_set_xalign (GTK_LABEL (label), 1);
gtk_grid_attach (GTK_GRID (grid), label, 1, 1, 1, 1);
label = gtk_label_new ("Scale");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 2, 1, 1);
precision = 1;
do {
s = g_strdup_printf ("%.*f", precision, self->scale);
l = strlen (s) - 1;
while (s[l] == '0')
l--;
if (s[l] == '.')
s[l] = '\0';
precision++;
} while (strcmp (s, "0") == 0);
label = gtk_label_new (s);
g_free (s);
gtk_label_set_xalign (GTK_LABEL (label), 1);
gtk_grid_attach (GTK_GRID (grid), label, 1, 2, 1, 1);
label = gtk_label_new ("Filter");
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 3, 1, 1);
label = gtk_label_new (filter[self->filter]);
gtk_label_set_xalign (GTK_LABEL (label), 1);
gtk_grid_attach (GTK_GRID (grid), label, 1, 3, 1, 1);
gtk_tooltip_set_custom (tooltip, grid);
return TRUE;
}
static void
demo3_widget_init (Demo3Widget *self)
{
self->scale = 1.f;
self->angle = 0.f;
self->filter = GSK_SCALING_FILTER_LINEAR;
gtk_widget_init_template (GTK_WIDGET (self));
}
@@ -129,35 +52,26 @@ demo3_widget_snapshot (GtkWidget *widget,
{
Demo3Widget *self = DEMO3_WIDGET (widget);
int x, y, width, height;
double w, h, w2, h2;
double w, h;
GskRenderNode *node;
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
w2 = w = self->scale * gdk_texture_get_width (self->texture);
h2 = h = self->scale * gdk_texture_get_height (self->texture);
w = self->scale * gdk_texture_get_width (self->texture);
h = self->scale * gdk_texture_get_height (self->texture);
if (G_APPROX_VALUE (self->angle, 90.f, FLT_EPSILON) ||
G_APPROX_VALUE (self->angle, 270.f, FLT_EPSILON))
{
double s = w2;
w2 = h2;
h2 = s;
}
x = (width - ceil (w2)) / 2;
y = (height - ceil (h2)) / 2;
x = MAX (0, (width - ceil (w)) / 2);
y = MAX (0, (height - ceil (h)) / 2);
gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_save (snapshot);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (w2 / 2, h2 / 2));
gtk_snapshot_rotate (snapshot, self->angle);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- w / 2, - h / 2));
gtk_snapshot_append_scaled_texture (snapshot,
self->texture,
self->filter,
&GRAPHENE_RECT_INIT (0, 0, w, h));
node = gsk_texture_scale_node_new (self->texture,
&GRAPHENE_RECT_INIT (0, 0, w, h),
self->filter);
gtk_snapshot_append_node (snapshot, node);
gsk_render_node_unref (node);
gtk_snapshot_restore (snapshot);
gtk_snapshot_pop (snapshot);
}
@@ -172,26 +86,14 @@ demo3_widget_measure (GtkWidget *widget,
int *natural_baseline)
{
Demo3Widget *self = DEMO3_WIDGET (widget);
int width, height;
int size;
width = gdk_texture_get_width (self->texture);
height = gdk_texture_get_height (self->texture);
if (G_APPROX_VALUE (self->angle, 90.f, FLT_EPSILON) ||
G_APPROX_VALUE (self->angle, 270.f, FLT_EPSILON))
{
int s = width;
width = height;
height = s;
}
if (orientation == GTK_ORIENTATION_HORIZONTAL)
size = width;
size = gdk_texture_get_width (self->texture);
else
size = height;
size = gdk_texture_get_height (self->texture);
*minimum = *natural = (int) ceil (self->scale * size);
*minimum = *natural = self->scale * size;
}
static void
@@ -209,8 +111,6 @@ demo3_widget_size_allocate (GtkWidget *widget,
gtk_popover_present (GTK_POPOVER (self->menu));
}
static void update_actions (Demo3Widget *self);
static void
demo3_widget_set_property (GObject *object,
guint prop_id,
@@ -224,24 +124,11 @@ demo3_widget_set_property (GObject *object,
case PROP_TEXTURE:
g_clear_object (&self->texture);
self->texture = g_value_dup_object (value);
self->scale = 1.f;
self->angle = 0.f;
self->filter = GSK_SCALING_FILTER_LINEAR;
update_actions (self);
gtk_widget_queue_resize (GTK_WIDGET (object));
g_object_notify (object, "scale");
g_object_notify (object, "angle");
g_object_notify (object, "filter");
break;
case PROP_SCALE:
self->scale = g_value_get_float (value);
update_actions (self);
gtk_widget_queue_resize (GTK_WIDGET (object));
break;
case PROP_ANGLE:
self->angle = fmodf (g_value_get_float (value), 360.f);
gtk_widget_queue_resize (GTK_WIDGET (object));
break;
@@ -274,10 +161,6 @@ demo3_widget_get_property (GObject *object,
g_value_set_float (value, self->scale);
break;
case PROP_ANGLE:
g_value_set_float (value, self->angle);
break;
case PROP_FILTER:
g_value_set_enum (value, self->filter);
break;
@@ -303,14 +186,6 @@ pressed_cb (GtkGestureClick *gesture,
gtk_popover_popup (GTK_POPOVER (self->menu));
}
static void
update_actions (Demo3Widget *self)
{
gtk_widget_action_set_enabled (GTK_WIDGET (self), "zoom.in", self->scale < 1024.);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "zoom.out", self->scale > 1./1024.);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "zoom.reset", self->scale != 1.);
}
static void
zoom_cb (GtkWidget *widget,
const char *action_name,
@@ -320,30 +195,19 @@ zoom_cb (GtkWidget *widget,
float scale;
if (g_str_equal (action_name, "zoom.in"))
scale = MIN (1024., self->scale * M_SQRT2);
scale = MIN (10, self->scale * M_SQRT2);
else if (g_str_equal (action_name, "zoom.out"))
scale = MAX (1./1024., self->scale / M_SQRT2);
else if (g_str_equal (action_name, "zoom.reset"))
scale = 1.0;
scale = MAX (0.01, self->scale / M_SQRT2);
else
g_assert_not_reached ();
scale = 1.0;
gtk_widget_action_set_enabled (widget, "zoom.in", scale < 10);
gtk_widget_action_set_enabled (widget, "zoom.out", scale > 0.01);
gtk_widget_action_set_enabled (widget, "zoom.reset", scale != 1);
g_object_set (widget, "scale", scale, NULL);
}
static void
rotate_cb (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
Demo3Widget *self = DEMO3_WIDGET (widget);
int angle;
g_variant_get (parameter, "i", &angle);
g_object_set (widget, "angle", fmodf (self->angle + angle, 360.f), NULL);
}
static void
demo3_widget_class_init (Demo3WidgetClass *class)
{
@@ -365,12 +229,7 @@ demo3_widget_class_init (Demo3WidgetClass *class)
g_object_class_install_property (object_class, PROP_SCALE,
g_param_spec_float ("scale", NULL, NULL,
1./1024., 1024., 1.0,
G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_ANGLE,
g_param_spec_float ("angle", NULL, NULL,
0.0, 360.0, 0.0,
0.0, 10.0, 1.0,
G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_FILTER,
@@ -382,7 +241,6 @@ demo3_widget_class_init (Demo3WidgetClass *class)
gtk_widget_class_install_action (widget_class, "zoom.in", NULL, zoom_cb);
gtk_widget_class_install_action (widget_class, "zoom.out", NULL, zoom_cb);
gtk_widget_class_install_action (widget_class, "zoom.reset", NULL, zoom_cb);
gtk_widget_class_install_action (widget_class, "rotate", "i", rotate_cb);
gtk_widget_class_set_template_from_resource (widget_class, "/menu/demo3widget.ui");
gtk_widget_class_bind_template_child (widget_class, Demo3Widget, menu);
@@ -397,12 +255,7 @@ demo3_widget_new (const char *resource)
texture = gdk_texture_new_from_resource (resource);
self = g_object_new (DEMO3_TYPE_WIDGET,
"texture", texture,
"has-tooltip", TRUE,
NULL);
g_signal_connect (self, "query-tooltip", G_CALLBACK (query_tooltip), NULL);
self = g_object_new (DEMO3_TYPE_WIDGET, "texture", texture, NULL);
g_object_unref (texture);
-5
View File
@@ -12,11 +12,6 @@
<attribute name="label">11</attribute>
<attribute name="action">zoom.reset</attribute>
</item>
<item>
<attribute name="label">Rotate</attribute>
<attribute name="action">rotate</attribute>
<attribute name="target" type="i">90</attribute>
</item>
</menu>
<template class="Demo3Widget">
<child>
+4 -107
View File
@@ -2,19 +2,12 @@
#include "demo4widget.h"
#include "hsla.h"
enum
{
PROP_0,
PROP_PROGRESS,
};
struct _Demo4Widget
{
GtkWidget parent_instance;
PangoLayout *layout;
GskColorStop stops[8];
gsize n_stops;
double progress;
guint tick;
};
@@ -56,8 +49,6 @@ demo4_widget_init (Demo4Widget *self)
{
PangoFontDescription *desc;
self->progress = 0.5;
self->n_stops = 8;
self->stops[0].offset = 0;
self->stops[0].color = (GdkRGBA) { 1, 0, 0, 1 };
@@ -92,24 +83,16 @@ demo4_widget_dispose (GObject *object)
}
static void
demo4_widget_snapshot_content (GtkWidget *widget,
GtkSnapshot *snapshot,
GskMaskMode mode)
demo4_widget_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
Demo4Widget *self = DEMO4_WIDGET (widget);
int width, height, layout_width, layout_height;
double scale;
int width, height;
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
gtk_snapshot_push_mask (snapshot, mode);
pango_layout_get_pixel_size (self->layout, &layout_width, &layout_height);
scale = MIN ((double) width / layout_width, (double) height / layout_height);
gtk_snapshot_translate (snapshot,
&GRAPHENE_POINT_INIT ((width - scale * layout_width) / 2,
(height - scale * layout_height) / 2));
gtk_snapshot_scale (snapshot, scale, scale);
gtk_snapshot_push_mask (snapshot);
gtk_snapshot_append_layout (snapshot, self->layout, &(GdkRGBA) { 0, 0, 0, 1 });
gtk_snapshot_pop (snapshot);
@@ -122,84 +105,6 @@ demo4_widget_snapshot_content (GtkWidget *widget,
gtk_snapshot_pop (snapshot);
}
static void
demo4_widget_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
Demo4Widget *self = DEMO4_WIDGET (widget);
int width, height;
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
gtk_snapshot_push_mask (snapshot, GSK_MASK_MODE_INVERTED_LUMINANCE);
gtk_snapshot_append_linear_gradient (snapshot,
&GRAPHENE_RECT_INIT (0, 0, width, height),
&GRAPHENE_POINT_INIT (0, 0),
&GRAPHENE_POINT_INIT (width, 0),
(GskColorStop[2]) {
{ MAX (0.0, self->progress - 5.0 / width), { 1, 1, 1, 1 } },
{ MIN (1.0, self->progress + 5.0 / width), { 0, 0, 0, 1 } }
}, 2);
gtk_snapshot_pop (snapshot);
demo4_widget_snapshot_content (widget, snapshot, GSK_MASK_MODE_INVERTED_ALPHA);
gtk_snapshot_pop (snapshot);
gtk_snapshot_push_mask (snapshot, GSK_MASK_MODE_LUMINANCE);
gtk_snapshot_append_linear_gradient (snapshot,
&GRAPHENE_RECT_INIT (0, 0, width, height),
&GRAPHENE_POINT_INIT (0, 0),
&GRAPHENE_POINT_INIT (width, 0),
(GskColorStop[2]) {
{ MAX (0.0, self->progress - 5.0 / width), { 1, 1, 1, 1 } },
{ MIN (1.0, self->progress + 5.0 / width), { 0, 0, 0, 1 } }
}, 2);
gtk_snapshot_pop (snapshot);
demo4_widget_snapshot_content (widget, snapshot, GSK_MASK_MODE_ALPHA);
gtk_snapshot_pop (snapshot);
}
static void
demo4_widget_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
Demo4Widget *self = DEMO4_WIDGET (object);
switch (prop_id)
{
case PROP_PROGRESS:
self->progress = g_value_get_double (value);
gtk_widget_queue_draw (GTK_WIDGET (object));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
demo4_widget_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
Demo4Widget *self = DEMO4_WIDGET (object);
switch (prop_id)
{
case PROP_PROGRESS:
g_value_set_double (value, self->progress);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
demo4_widget_class_init (Demo4WidgetClass *class)
{
@@ -207,15 +112,8 @@ demo4_widget_class_init (Demo4WidgetClass *class)
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->dispose = demo4_widget_dispose;
object_class->get_property = demo4_widget_get_property;
object_class->set_property = demo4_widget_set_property;
widget_class->snapshot = demo4_widget_snapshot;
g_object_class_install_property (object_class, PROP_PROGRESS,
g_param_spec_double ("progress", NULL, NULL,
0.0, 1.0, 0.5,
G_PARAM_READWRITE));
}
GtkWidget *
@@ -223,4 +121,3 @@ demo4_widget_new (void)
{
return g_object_new (DEMO4_TYPE_WIDGET, NULL);
}
+1 -12
View File
@@ -356,10 +356,6 @@ canvas_item_start_editing (CanvasItem *item)
}
typedef struct {
double x, y;
} Hotspot;
static GdkContentProvider *
prepare (GtkDragSource *source,
double x,
@@ -367,7 +363,6 @@ prepare (GtkDragSource *source,
{
GtkWidget *canvas;
GtkWidget *item;
Hotspot *hotspot;
canvas = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
item = gtk_widget_pick (canvas, x, y, GTK_PICK_DEFAULT);
@@ -378,10 +373,6 @@ prepare (GtkDragSource *source,
g_object_set_data (G_OBJECT (canvas), "dragged-item", item);
hotspot = g_new (Hotspot, 1);
gtk_widget_translate_coordinates (canvas, item, x, y, &hotspot->x, &hotspot->y);
g_object_set_data_full (G_OBJECT (canvas), "hotspot", hotspot, g_free);
return gdk_content_provider_new_typed (GTK_TYPE_WIDGET, item);
}
@@ -392,14 +383,12 @@ drag_begin (GtkDragSource *source,
GtkWidget *canvas;
CanvasItem *item;
GdkPaintable *paintable;
Hotspot *hotspot;
canvas = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
item = CANVAS_ITEM (g_object_get_data (G_OBJECT (canvas), "dragged-item"));
hotspot = (Hotspot *) g_object_get_data (G_OBJECT (canvas), "hotspot");
paintable = canvas_item_get_drag_icon (item);
gtk_drag_source_set_icon (source, paintable, hotspot->x, hotspot->y);
gtk_drag_source_set_icon (source, paintable, item->r, item->r);
g_object_unref (paintable);
gtk_widget_set_opacity (GTK_WIDGET (item), 0.3);
+10 -12
View File
@@ -48,16 +48,14 @@
#define VERTICES_PER_TOOTH 34
#define GEAR_VERTEX_STRIDE 6
static inline void
_sincos (double x, double *_sin, double *_cos)
#ifndef HAVE_SINCOS
static void
sincos (double x, double *_sin, double *_cos)
{
#ifdef HAVE_SINCOS
sincos (x, _sin, _cos);
#else
*_sin = sin (x);
*_cos = cos (x);
#endif
}
#endif
/**
* Struct describing the vertices in triangle strip
@@ -309,11 +307,11 @@ create_gear (GLfloat inner_radius,
struct point p[7];
/* Calculate needed sin/cos for various angles */
_sincos(i * 2.0 * G_PI / teeth + da * 0, &s[0], &c[0]);
_sincos(i * 2.0 * M_PI / teeth + da * 1, &s[1], &c[1]);
_sincos(i * 2.0 * M_PI / teeth + da * 2, &s[2], &c[2]);
_sincos(i * 2.0 * M_PI / teeth + da * 3, &s[3], &c[3]);
_sincos(i * 2.0 * M_PI / teeth + da * 4, &s[4], &c[4]);
sincos(i * 2.0 * G_PI / teeth + da * 0, &s[0], &c[0]);
sincos(i * 2.0 * M_PI / teeth + da * 1, &s[1], &c[1]);
sincos(i * 2.0 * M_PI / teeth + da * 2, &s[2], &c[2]);
sincos(i * 2.0 * M_PI / teeth + da * 3, &s[3], &c[3]);
sincos(i * 2.0 * M_PI / teeth + da * 4, &s[4], &c[4]);
GEAR_POINT(p[0], r2, 1);
GEAR_POINT(p[1], r2, 2);
@@ -522,7 +520,7 @@ void perspective(GLfloat *m, GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloa
identity(tmp);
deltaZ = zFar - zNear;
_sincos(radians, &sine, &cosine);
sincos(radians, &sine, &cosine);
if ((deltaZ == 0) || (sine == 0) || (aspect == 0))
return;
+203 -195
View File
@@ -30,86 +30,90 @@
</object>
</child>
<child>
<object class="GtkListBox">
<property name="selection-mode">none</property>
<signal name="row-activated" handler="row_activated"/>
<style>
<class name="rich-list"/>
<class name="boxed-list"/>
</style>
<object class="GtkFrame">
<child>
<object class="GtkListBoxRow">
<object class="GtkListBox">
<property name="selection-mode">none</property>
<property name="show-separators">1</property>
<signal name="row-activated" handler="row_activated"/>
<style>
<class name="rich-list"/>
</style>
<child>
<object class="GtkBox">
<object class="GtkListBoxRow">
<child>
<object class="GtkLabel" id="switch_label">
<property name="label" translatable="yes">Switch</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkSwitch" id="switch">
<property name="halign">end</property>
<property name="valign">center</property>
<object class="GtkBox">
<child>
<object class="GtkLabel" id="switch_label">
<property name="label" translatable="yes">Switch</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkSwitch" id="switch">
<property name="halign">end</property>
<property name="valign">center</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<child>
<object class="GtkBox">
<object class="GtkListBoxRow">
<child>
<object class="GtkLabel" id="check_label">
<property name="label" translatable="yes">Check</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkCheckButton" id="check">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="active">1</property>
<object class="GtkBox">
<child>
<object class="GtkLabel" id="check_label">
<property name="label" translatable="yes">Check</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkCheckButton" id="check">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="active">1</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<child>
<object class="GtkBox">
<object class="GtkListBoxRow">
<child>
<object class="GtkLabel" id="image_label">
<property name="label" translatable="yes">Click here!</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkImage" id="image">
<property name="icon-name">object-select-symbolic</property>
<property name="halign">end</property>
<property name="valign">center</property>
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="opacity">0</property>
<object class="GtkBox">
<child>
<object class="GtkLabel" id="image_label">
<property name="label" translatable="yes">Click here!</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkImage" id="image">
<property name="icon-name">object-select-symbolic</property>
<property name="halign">end</property>
<property name="valign">center</property>
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="opacity">0</property>
</object>
</child>
</object>
</child>
</object>
@@ -130,142 +134,146 @@
</style>
</object>
</child>
<child>
<object class="GtkListBox">
<property name="selection-mode">none</property>
<style>
<class name="rich-list"/>
<class name="boxed-list"/>
</style>
<child>
<object class="GtkFrame">
<child>
<object class="GtkListBox">
<property name="selection-mode">none</property>
<property name="show-separators">1</property>
<style>
<class name="rich-list"/>
</style>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel" id="scale_label">
<property name="label" translatable="yes">Scale</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkScale">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="draw-value">0</property>
<property name="width-request">150</property>
<property name="adjustment">
<object class="GtkAdjustment">
<property name="upper">100</property>
<property name="value">50</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel" id="scale_label">
<property name="label" translatable="yes">Scale</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkScale">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="draw-value">0</property>
<property name="width-request">150</property>
<property name="adjustment">
<object class="GtkAdjustment">
<property name="upper">100</property>
<property name="value">50</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel" id="spin_label">
<property name="label" translatable="yes">Spinbutton</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkSpinButton">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="adjustment">
<object class="GtkAdjustment">
<property name="upper">100</property>
<property name="value">50</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel" id="dropdown_label">
<property name="label" translatable="yes">Dropdown</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkDropDown">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="model">
<object class="GtkStringList">
<items>
<item>Choice 1</item>
<item>Choice 2</item>
<item>Choice 3</item>
<item>Choice 4</item>
</items>
</object>
</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel" id="spin_label">
<property name="label" translatable="yes">Spinbutton</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkSpinButton">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="adjustment">
<object class="GtkAdjustment">
<property name="upper">100</property>
<property name="value">50</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel" id="dropdown_label">
<property name="label" translatable="yes">Dropdown</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkDropDown">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="model">
<object class="GtkStringList">
<items>
<item>Choice 1</item>
<item>Choice 2</item>
<item>Choice 3</item>
<item>Choice 4</item>
</items>
</object>
</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel" id="entry_label">
<property name="label" translatable="yes">Entry</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkEntry">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="placeholder-text">Type here…</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel" id="entry_label">
<property name="label" translatable="yes">Entry</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkEntry">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="placeholder-text">Type here…</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
+5 -12
View File
@@ -18,8 +18,7 @@ do_mask (GtkWidget *do_widget)
if (!window)
{
GtkWidget *box;
GtkWidget *demo;
GtkWidget *scale;
GtkWidget *widget;
window = gtk_window_new ();
gtk_window_set_title (GTK_WINDOW (window), "Mask Nodes");
@@ -31,17 +30,11 @@ do_mask (GtkWidget *do_widget)
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_window_set_child (GTK_WINDOW (window), box);
demo = demo4_widget_new ();
gtk_widget_set_hexpand (demo, TRUE);
gtk_widget_set_vexpand (demo, TRUE);
widget = demo4_widget_new ();
gtk_widget_set_hexpand (widget, TRUE);
gtk_widget_set_vexpand (widget, TRUE);
gtk_box_append (GTK_BOX (box), demo);
scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0, 1, 0.1);
gtk_range_set_value (GTK_RANGE (scale), 0.5);
g_object_bind_property (gtk_range_get_adjustment (GTK_RANGE (scale)), "value", demo, "progress", 0);
gtk_box_append (GTK_BOX (box), scale);
gtk_box_append (GTK_BOX (box), widget);
}
if (!gtk_widget_get_visible (window))
+14 -133
View File
@@ -1,120 +1,18 @@
/* Image Scaling
* #Keywords: zoom, scale, filter, action, menu
/* Menu
* #Keywords: action, zoom
*
* Demonstrates how to add a context menu to a custom widget
* and connect it with widget actions.
*
* The custom widget we create here is similar to a GtkPicture,
* but allows setting a zoom level and filtering mode for the
* displayed paintable.
* but allows setting a zoom level for the displayed paintable.
*
* It also demonstrates how to add a context menu to a custom
* widget and connect it with widget actions.
*
* The context menu has items to change the zoom level.
* Our context menu has items to change the zoom level.
*/
#include <gtk/gtk.h>
#include "demo3widget.h"
static void
file_opened (GObject *source,
GAsyncResult *result,
void *data)
{
GFile *file;
GError *error = NULL;
GdkTexture *texture;
file = gtk_file_dialog_open_finish (GTK_FILE_DIALOG (source), result, &error);
if (!file)
{
g_print ("%s\n", error->message);
g_error_free (error);
return;
}
texture = gdk_texture_new_from_file (file, &error);
g_object_unref (file);
if (!texture)
{
g_print ("%s\n", error->message);
g_error_free (error);
return;
}
g_object_set (G_OBJECT (data), "texture", texture, NULL);
g_object_unref (texture);
}
static void
open_file (GtkWidget *picker,
GtkWidget *demo)
{
GtkWindow *parent = GTK_WINDOW (gtk_widget_get_root (picker));
GtkFileDialog *dialog;
GtkFileFilter *filter;
GListStore *filters;
dialog = gtk_file_dialog_new ();
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, "Images");
gtk_file_filter_add_pixbuf_formats (filter);
filters = g_list_store_new (GTK_TYPE_FILE_FILTER);
g_list_store_append (filters, filter);
g_object_unref (filter);
gtk_file_dialog_set_filters (dialog, G_LIST_MODEL (filters));
g_object_unref (filters);
gtk_file_dialog_open (dialog, parent, NULL, file_opened, demo);
g_object_unref (dialog);
}
static void
rotate (GtkWidget *button,
GtkWidget *demo)
{
float angle;
g_object_get (demo, "angle", &angle, NULL);
angle = fmodf (angle + 90.f, 360.f);
g_object_set (demo, "angle", angle, NULL);
}
static gboolean
transform_to (GBinding *binding,
const GValue *src,
GValue *dest,
gpointer user_data)
{
double from;
float to;
from = g_value_get_double (src);
to = (float) pow (2., from);
g_value_set_float (dest, to);
return TRUE;
}
static gboolean
transform_from (GBinding *binding,
const GValue *src,
GValue *dest,
gpointer user_data)
{
float to;
double from;
to = g_value_get_float (src);
from = log2 (to);
g_value_set_double (dest, from);
return TRUE;
}
GtkWidget *
do_menu (GtkWidget *do_widget)
@@ -129,10 +27,9 @@ do_menu (GtkWidget *do_widget)
GtkWidget *widget;
GtkWidget *scale;
GtkWidget *dropdown;
GtkWidget *button;
window = gtk_window_new ();
gtk_window_set_title (GTK_WINDOW (window), "Image Scaling");
gtk_window_set_title (GTK_WINDOW (window), "Menu");
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
@@ -151,35 +48,19 @@ do_menu (GtkWidget *do_widget)
box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_append (GTK_BOX (box), box2);
button = gtk_button_new_from_icon_name ("document-open-symbolic");
gtk_widget_set_tooltip_text (button, "Open File");
g_signal_connect (button, "clicked", G_CALLBACK (open_file), widget);
gtk_box_append (GTK_BOX (box2), button);
button = gtk_button_new_from_icon_name ("object-rotate-right-symbolic");
gtk_widget_set_tooltip_text (button, "Rotate");
g_signal_connect (button, "clicked", G_CALLBACK (rotate), widget);
gtk_box_append (GTK_BOX (box2), button);
scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, -10., 10., 0.1);
gtk_scale_add_mark (GTK_SCALE (scale), 0., GTK_POS_TOP, NULL);
gtk_widget_set_tooltip_text (scale, "Zoom");
gtk_range_set_value (GTK_RANGE (scale), 0.);
scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0.01, 10.0, 0.1);
gtk_range_set_value (GTK_RANGE (scale), 1.0);
gtk_widget_set_hexpand (scale, TRUE);
gtk_box_append (GTK_BOX (box2), scale);
dropdown = gtk_drop_down_new (G_LIST_MODEL (gtk_string_list_new ((const char *[]){ "Linear", "Nearest", "Trilinear", NULL })), NULL);
gtk_widget_set_tooltip_text (dropdown, "Filter");
gtk_box_append (GTK_BOX (box2), dropdown);
g_object_bind_property (dropdown, "selected", widget, "filter", G_BINDING_DEFAULT);
g_object_bind_property_full (gtk_range_get_adjustment (GTK_RANGE (scale)), "value",
widget, "scale",
G_BINDING_BIDIRECTIONAL,
transform_to,
transform_from,
NULL, NULL);
g_object_bind_property (gtk_range_get_adjustment (GTK_RANGE (scale)), "value",
widget, "scale",
G_BINDING_BIDIRECTIONAL);
}
if (!gtk_widget_get_visible (window))
+1 -1
View File
@@ -225,7 +225,7 @@ if not meson.is_cross_build() and build_machine.cpu_family() != 'arm' and build_
else
gtkdemo_resources = gnome.compile_resources('gtkdemo_resources',
'demo.gresource.xml',
source_dir: meson.current_source_dir()
source_dir: '.',
)
endif
+8 -26
View File
@@ -24,7 +24,6 @@ typedef struct
GdkRGBA draw_color;
GtkPadController *pad_controller;
double brush_size;
GtkGesture *gesture;
} DrawingArea;
typedef struct
@@ -263,7 +262,7 @@ drawing_area_apply_stroke (DrawingArea *area,
double y,
double pressure)
{
if (tool && gdk_device_tool_get_tool_type (tool) == GDK_DEVICE_TOOL_TYPE_ERASER)
if (gdk_device_tool_get_tool_type (tool) == GDK_DEVICE_TOOL_TYPE_ERASER)
{
cairo_set_line_width (area->cr, 10 * pressure * area->brush_size);
cairo_set_operator (area->cr, CAIRO_OPERATOR_DEST_OUT);
@@ -314,9 +313,7 @@ stylus_gesture_motion (GtkGestureStylus *gesture,
drawing_area_apply_stroke (area, tool,
backlog[i].axes[GDK_AXIS_X],
backlog[i].axes[GDK_AXIS_Y],
backlog[i].flags & GDK_AXIS_FLAG_PRESSURE
? backlog[i].axes[GDK_AXIS_PRESSURE]
: 1);
backlog[i].axes[GDK_AXIS_PRESSURE]);
}
g_free (backlog);
@@ -346,8 +343,6 @@ drawing_area_init (DrawingArea *area)
area->draw_color = (GdkRGBA) { 0, 0, 0, 1 };
area->brush_size = 1;
area->gesture = gesture;
}
static GtkWidget *
@@ -386,12 +381,6 @@ drawing_area_color_set (DrawingArea *area,
gtk_color_dialog_button_set_rgba (button, color);
}
static GtkGesture *
drawing_area_get_gesture (DrawingArea *area)
{
return area->gesture;
}
GtkWidget *
do_paint (GtkWidget *toplevel)
{
@@ -399,7 +388,7 @@ do_paint (GtkWidget *toplevel)
if (!window)
{
GtkWidget *draw_area, *headerbar, *button;
GtkWidget *draw_area, *headerbar, *colorbutton;
window = gtk_window_new ();
@@ -408,22 +397,15 @@ do_paint (GtkWidget *toplevel)
headerbar = gtk_header_bar_new ();
button = gtk_color_dialog_button_new (gtk_color_dialog_new ());
g_signal_connect (button, "notify::rgba",
colorbutton = gtk_color_dialog_button_new (gtk_color_dialog_new ());
g_signal_connect (colorbutton, "notify::rgba",
G_CALLBACK (color_button_color_set), draw_area);
g_signal_connect (draw_area, "color-set",
G_CALLBACK (drawing_area_color_set), button);
gtk_color_dialog_button_set_rgba (GTK_COLOR_DIALOG_BUTTON (button),
G_CALLBACK (drawing_area_color_set), colorbutton);
gtk_color_dialog_button_set_rgba (GTK_COLOR_DIALOG_BUTTON (colorbutton),
&(GdkRGBA) { 0, 0, 0, 1 });
gtk_header_bar_pack_end (GTK_HEADER_BAR (headerbar), button);
button = gtk_check_button_new_with_label ("Stylus only");
g_object_bind_property (button, "active",
drawing_area_get_gesture ((DrawingArea *)draw_area), "stylus-only",
G_BINDING_SYNC_CREATE);
gtk_header_bar_pack_start (GTK_HEADER_BAR (headerbar), button);
gtk_header_bar_pack_end (GTK_HEADER_BAR (headerbar), colorbutton);
gtk_window_set_titlebar (GTK_WINDOW (window), headerbar);
gtk_window_set_title (GTK_WINDOW (window), "Paint");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
+9 -44
View File
@@ -13,13 +13,20 @@
static GtkWidget *app_picker;
static void
set_file (GFile *file,
gpointer data)
file_opened (GObject *source,
GAsyncResult *result,
void *data)
{
GFile *file;
GError *error = NULL;
char *name;
file = gtk_file_dialog_open_finish (GTK_FILE_DIALOG (source), result, &error);
if (!file)
{
g_print ("%s\n", error->message);
g_error_free (error);
gtk_widget_set_sensitive (app_picker, FALSE);
g_object_set_data (G_OBJECT (app_picker), "file", NULL);
return;
@@ -33,25 +40,6 @@ set_file (GFile *file,
g_object_set_data_full (G_OBJECT (app_picker), "file", g_object_ref (file), g_object_unref);
}
static void
file_opened (GObject *source,
GAsyncResult *result,
void *data)
{
GFile *file;
GError *error = NULL;
file = gtk_file_dialog_open_finish (GTK_FILE_DIALOG (source), result, &error);
if (!file)
{
g_print ("%s\n", error->message);
g_error_free (error);
}
set_file (file, data);
}
static gboolean
abort_mission (gpointer data)
{
@@ -142,28 +130,11 @@ launch_uri (GtkButton *picker)
g_object_unref (launcher);
}
static gboolean
on_drop (GtkDropTarget *target,
const GValue *value,
double x,
double y,
gpointer data)
{
if (G_VALUE_HOLDS (value, G_TYPE_FILE))
{
set_file (g_value_get_object (value), data);
return TRUE;
}
return FALSE;
}
GtkWidget *
do_pickers (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
GtkWidget *table, *label, *picker, *button;
GtkDropTarget *drop_target;
if (!window)
{
@@ -208,13 +179,7 @@ do_pickers (GtkWidget *do_widget)
picker = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
button = gtk_button_new_from_icon_name ("document-open-symbolic");
label = gtk_label_new ("None");
drop_target = gtk_drop_target_new (G_TYPE_FILE, GDK_ACTION_COPY);
g_signal_connect (drop_target, "drop", G_CALLBACK (on_drop), label);
gtk_widget_add_controller (button, GTK_EVENT_CONTROLLER (drop_target));
gtk_label_set_xalign (GTK_LABEL (label), 0.);
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE);
gtk_widget_set_hexpand (label, TRUE);
-1
View File
@@ -22,7 +22,6 @@ show_shortcuts (GtkWidget *window,
gtk_window_set_transient_for (GTK_WINDOW (overlay), GTK_WINDOW (window));
g_object_set (overlay, "view-name", view, NULL);
g_object_unref (builder);
gtk_window_present (GTK_WINDOW (overlay));
}
G_MODULE_EXPORT void
+1 -1
View File
@@ -1,5 +1,5 @@
/* Overlay/Transparency
* #Keywords: GtkOverlay, GtkSnapshot, blur
* #Keywords: GtkOverlay, GtkSnapshot
*
* Blur the background behind an overlay.
*/
+1 -1
View File
@@ -8,7 +8,7 @@ iconbrowser_sources = [
iconbrowser_resources = gnome.compile_resources('iconbrowser_resources',
'iconbrowser.gresource.xml',
source_dir: meson.current_source_dir(),
source_dir: '.',
)
executable('gtk4-icon-browser',
+1 -1
View File
@@ -7,7 +7,7 @@ node_editor_sources = [
node_editor_resources = gnome.compile_resources('node_editor_resources',
'node-editor.gresource.xml',
source_dir: meson.current_source_dir(),
source_dir: '.',
)
executable('gtk4-node-editor',
+23 -205
View File
@@ -32,11 +32,6 @@
#include "gsk/vulkan/gskvulkanrenderer.h"
#endif
#include <cairo.h>
#ifdef CAIRO_HAS_SVG_SURFACE
#include <cairo-svg.h>
#endif
typedef struct
{
gsize start_chars;
@@ -174,7 +169,6 @@ text_changed (GtkTextBuffer *buffer,
GtkTextIter iter;
GtkTextIter start, end;
float scale;
GskRenderNode *big_node;
g_array_remove_range (self->errors, 0, self->errors->len);
text = get_current_text (self->text_buffer);
@@ -187,18 +181,13 @@ text_changed (GtkTextBuffer *buffer,
self->node = gsk_render_node_deserialize (bytes, deserialize_error_func, self);
scale = gtk_scale_button_get_value (GTK_SCALE_BUTTON (self->scale_scale));
if (self->node && scale != 0.)
if (self->node && scale != 1.0)
{
scale = pow (2., scale);
big_node = gsk_transform_node_new (self->node, gsk_transform_scale (NULL, scale, scale));
}
else if (self->node)
{
big_node = gsk_render_node_ref (self->node);
}
else
{
big_node = NULL;
GskRenderNode *node;
node = gsk_transform_node_new (self->node, gsk_transform_scale (NULL, scale, scale));
gsk_render_node_unref (self->node);
self->node = node;
}
g_bytes_unref (bytes);
@@ -210,27 +199,18 @@ text_changed (GtkTextBuffer *buffer,
graphene_rect_t bounds;
guint i;
snapshot = gtk_snapshot_new ();
gsk_render_node_get_bounds (big_node, &bounds);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- bounds.origin.x, - bounds.origin.y));
gtk_snapshot_append_node (snapshot, big_node);
paintable = gtk_snapshot_free_to_paintable (snapshot, &bounds.size);
gtk_picture_set_paintable (GTK_PICTURE (self->picture), paintable);
g_clear_object (&paintable);
snapshot = gtk_snapshot_new ();
gsk_render_node_get_bounds (self->node, &bounds);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- bounds.origin.x, - bounds.origin.y));
gtk_snapshot_append_node (snapshot, self->node);
paintable = gtk_snapshot_free_to_paintable (snapshot, &bounds.size);
gtk_picture_set_paintable (GTK_PICTURE (self->picture), paintable);
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (self->renderers)); i++)
{
gpointer item = g_list_model_get_item (G_LIST_MODEL (self->renderers), i);
gtk_renderer_paintable_set_paintable (item, paintable);
g_object_unref (item);
}
g_clear_object (&paintable);
}
else
@@ -238,8 +218,6 @@ text_changed (GtkTextBuffer *buffer,
gtk_picture_set_paintable (GTK_PICTURE (self->picture), NULL);
}
g_clear_pointer (&big_node, gsk_render_node_unref);
gtk_text_buffer_get_start_iter (self->text_buffer, &iter);
while (!gtk_text_iter_is_end (&iter))
@@ -665,34 +643,23 @@ save_cb (GtkWidget *button,
g_object_unref (dialog);
}
static GskRenderNode *
create_node (NodeEditorWindow *self)
static GdkTexture *
create_texture (NodeEditorWindow *self)
{
GdkPaintable *paintable;
GtkSnapshot *snapshot;
GskRenderer *renderer;
GskRenderNode *node;
GdkTexture *texture;
paintable = gtk_picture_get_paintable (GTK_PICTURE (self->picture));
if (paintable == NULL ||
gdk_paintable_get_intrinsic_width (paintable) <= 0 ||
gdk_paintable_get_intrinsic_height (paintable) <= 0)
return NULL;
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (paintable, snapshot, gdk_paintable_get_intrinsic_width (paintable), gdk_paintable_get_intrinsic_height (paintable));
node = gtk_snapshot_free_to_node (snapshot);
return node;
}
static GdkTexture *
create_texture (NodeEditorWindow *self)
{
GskRenderer *renderer;
GskRenderNode *node;
GdkTexture *texture;
node = create_node (self);
if (node == NULL)
return NULL;
@@ -703,58 +670,6 @@ create_texture (NodeEditorWindow *self)
return texture;
}
#ifdef CAIRO_HAS_SVG_SURFACE
static cairo_status_t
cairo_serializer_write (gpointer user_data,
const unsigned char *data,
unsigned int length)
{
g_byte_array_append (user_data, data, length);
return CAIRO_STATUS_SUCCESS;
}
static GBytes *
create_svg (GskRenderNode *node,
GError **error)
{
cairo_surface_t *surface;
cairo_t *cr;
graphene_rect_t bounds;
GByteArray *array;
gsk_render_node_get_bounds (node, &bounds);
array = g_byte_array_new ();
surface = cairo_svg_surface_create_for_stream (cairo_serializer_write,
array,
bounds.size.width,
bounds.size.height);
cairo_svg_surface_set_document_unit (surface, CAIRO_SVG_UNIT_PX);
cairo_surface_set_device_offset (surface, -bounds.origin.x, -bounds.origin.y);
cr = cairo_create (surface);
gsk_render_node_draw (node, cr);
cairo_destroy (cr);
cairo_surface_finish (surface);
if (cairo_surface_status (surface) == CAIRO_STATUS_SUCCESS)
{
cairo_surface_destroy (surface);
return g_byte_array_free_to_bytes (array);
}
else
{
g_set_error (error,
G_IO_ERROR, G_IO_ERROR_FAILED,
"%s", cairo_status_to_string (cairo_surface_status (surface)));
cairo_surface_destroy (surface);
g_byte_array_unref (array);
return NULL;
}
}
#endif
static GdkTexture *
create_cairo_texture (NodeEditorWindow *self)
{
@@ -787,140 +702,50 @@ create_cairo_texture (NodeEditorWindow *self)
}
static void
export_image_saved_cb (GObject *source,
GAsyncResult *result,
void *user_data)
{
GError *error = NULL;
if (!g_file_replace_contents_finish (G_FILE (source), result, NULL, &error))
{
GtkAlertDialog *alert;
alert = gtk_alert_dialog_new ("Exporting to image failed");
gtk_alert_dialog_set_detail (alert, error->message);
gtk_alert_dialog_show (alert, NULL);
g_object_unref (alert);
g_clear_error (&error);
}
}
static void
export_image_response_cb (GObject *source,
export_image_response_cb (GObject *source,
GAsyncResult *result,
void *user_data)
void *user_data)
{
GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
GskRenderNode *node = user_data;
GdkTexture *texture = user_data;
GFile *file;
char *uri;
GBytes *bytes;
file = gtk_file_dialog_save_finish (dialog, result, NULL);
if (file == NULL)
if (file)
{
gsk_render_node_unref (node);
return;
}
uri = g_file_get_uri (file);
#ifdef CAIRO_HAS_SVG_SURFACE
if (g_str_has_suffix (uri, "svg"))
{
GError *error = NULL;
bytes = create_svg (node, &error);
if (bytes == NULL)
if (!gdk_texture_save_to_png (texture, g_file_peek_path (file)))
{
GtkAlertDialog *alert;
alert = gtk_alert_dialog_new ("Exporting to image failed");
gtk_alert_dialog_set_detail (alert, error->message);
gtk_alert_dialog_show (alert, NULL);
gtk_alert_dialog_show (alert, GTK_WINDOW (gtk_window_get_transient_for (GTK_WINDOW (dialog))));
g_object_unref (alert);
g_clear_error (&error);
}
}
else
#endif
{
GdkTexture *texture;
GskRenderer *renderer;
renderer = gsk_gl_renderer_new ();
if (!gsk_renderer_realize (renderer, NULL, NULL))
{
g_object_unref (renderer);
renderer = gsk_cairo_renderer_new ();
if (!gsk_renderer_realize (renderer, NULL, NULL))
{
g_assert_not_reached ();
}
}
texture = gsk_renderer_render_texture (renderer, node, NULL);
gsk_renderer_unrealize (renderer);
g_object_unref (renderer);
if (g_str_has_suffix (uri, "tiff"))
bytes = gdk_texture_save_to_tiff_bytes (texture);
else
bytes = gdk_texture_save_to_png_bytes (texture);
g_object_unref (texture);
g_object_unref (file);
}
g_free (uri);
if (bytes)
{
g_file_replace_contents_bytes_async (file,
bytes,
NULL,
FALSE,
0,
NULL,
export_image_saved_cb,
NULL);
g_bytes_unref (bytes);
}
gsk_render_node_unref (node);
g_object_unref (file);
g_object_unref (texture);
}
static void
export_image_cb (GtkWidget *button,
NodeEditorWindow *self)
{
GskRenderNode *node;
GdkTexture *texture;
GtkFileDialog *dialog;
GtkFileFilter *filter;
GListStore *filters;
node = create_node (self);
if (node == NULL)
texture = create_texture (self);
if (texture == NULL)
return;
filters = g_list_store_new (GTK_TYPE_FILE_FILTER);
filter = gtk_file_filter_new ();
gtk_file_filter_add_mime_type (filter, "image/png");
g_list_store_append (filters, filter);
g_object_unref (filter);
filter = gtk_file_filter_new ();
gtk_file_filter_add_mime_type (filter, "image/svg+xml");
g_list_store_append (filters, filter);
g_object_unref (filter);
filter = gtk_file_filter_new ();
gtk_file_filter_add_mime_type (filter, "image/tiff");
g_list_store_append (filters, filter);
g_object_unref (filter);
dialog = gtk_file_dialog_new ();
gtk_file_dialog_set_title (dialog, "");
gtk_file_dialog_set_initial_name (dialog, "example.png");
gtk_file_dialog_set_filters (dialog, G_LIST_MODEL (filters));
gtk_file_dialog_save (dialog,
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
NULL,
export_image_response_cb, node);
g_object_unref (filters);
export_image_response_cb, texture);
g_object_unref (dialog);
}
@@ -1309,13 +1134,6 @@ node_editor_window_init (NodeEditorWindow *self)
" }\n"
" transform: translate(0, 140);\n"
"}", -1);
if (g_getenv ("GSK_RENDERER"))
{
char *new_title = g_strdup_printf ("GTK Node Editor - %s", g_getenv ("GSK_RENDERER"));
gtk_window_set_title (GTK_WINDOW (self), new_title);
g_free (new_title);
}
}
NodeEditorWindow *
+3 -3
View File
@@ -163,9 +163,9 @@
<property name="valign">center</property>
<property name="adjustment">
<object class="GtkAdjustment">
<property name="lower">-4</property>
<property name="value">0</property>
<property name="upper">4</property>
<property name="lower">1</property>
<property name="value">1</property>
<property name="upper">10</property>
<property name="step-increment">0.1</property>
<property name="page-increment">0.5</property>
</object>
-10
View File
@@ -178,16 +178,6 @@ Creates a node like `gsk_inset_shadow_node_new()` with the given properties.
Creates a node like `gsk_linear_gradient_node_new()` with the given properties.
### mask
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| source | `<node>` | color { } | always |
| mode | `<blend-mode>` | alpha | non-default |
| mask | `<node>` | color { } | always |
Creates a node like `gsk_mask_node_new()` with the given properties.
### opacity
| property | syntax | default | printed |
+1 -1
View File
@@ -69,7 +69,7 @@ if not meson.is_cross_build() and build_machine.cpu_family() != 'arm' and build_
else
widgetfactory_resources = gnome.compile_resources('widgetfactory_resources',
'widget-factory.gresource.xml',
source_dir: meson.current_source_dir(),
source_dir: '.',
)
endif
+2 -2
View File
@@ -220,6 +220,6 @@ clipboard.cut, clipboard.copy, clipboard.paste
selection.delete, selection.select-all
: Selection operations on entries, text view and labels
color.select, color.customize
color.select, color.customize:
: Operate on colors in a `GtkColorChooserWidget`. These actions are
unusual in that they have the non-trivial parameter type (dddd).
unusual in that they have the non-trivial parameter type (dddd):
+11 -6
View File
@@ -6,15 +6,22 @@ Slug: broadway
The GDK Broadway backend provides support for displaying GTK applications in
a web browser, using HTML5 and web sockets.
To run your application in this way, first run the broadway server,
`gtk-broadwayd`, that ships with GTK:
To run your application in this way, select the Broadway backend by setting
`GDK_BACKEND=broadway`. Then you can make your application appear in a web
browser by pointing it at `http://127.0.0.1:8080`. Note that you need to
enable web sockets in your web browser.
You can choose a different port from the default 8080 by setting the
`BROADWAY_DISPLAY` environment variable to the port that you want to use.
It is also possible to use multiple GTK applications in the same web browser
window, by using the Broadway server, `gtk4-broadwayd`, that ships with GTK.
To start the Broadway server use:
```
gtk4-broadwayd :5
```
The server expects the colon-prefixed display number as a commandline argument.
Then point your web browser at `http://127.0.0.1:8085`.
Once the Broadway server is running, you can start your applications like
@@ -24,8 +31,6 @@ this:
GDK_BACKEND=broadway BROADWAY_DISPLAY=:5 gtk4-demo
```
Multiple applications can be presented in the same web browser window.
## Broadway-specific environment variables
### `BROADWAY_DISPLAY`
+5 -5
View File
@@ -239,14 +239,14 @@ control whether Vulkan should be used.
### `media-gstreamer` and `media-ffmpeg`
By default, GTK will try to build the gstreamer backend for
media playback support. These options can be used to explicitly
media playback support. These option can be used to explicitly
control which media backends should be built.
### `print-cups` and `print-cpdb`
### `print-cups`
By default, GTK will try to build the cups and file print backends
if their dependencies are found. These options can be used to
explicitly control which print backends should be built.
By default, GTK will try to build various print backends
if their dependencies are found. This option can be used
to explicitly control whether the cups print backend should be built.
### `cloudproviders`
+1 -1
View File
@@ -68,7 +68,7 @@ in a selector, widget names must be prefixed with a &num; character.
| E:focus-within | [CSS Selector Level 4](https://drafts.csswg.org/selectors/#focus-within-pseudo) | Set on all ancestors of the focus widget, unlike CSS |
| E:focus-visible | [CSS Selector Level 4](https://drafts.csswg.org/selectors/#focus-within-pseudo) | Set on focus widget and all ancestors, unlike CSS |
| E:disabled | [CSS Selector Level 3](https://www.w3.org/TR/css3-selectors/#UIstates) | Corresponds to GTK_STATE_FLAG_INSENSITIVE |
| E:checked | [CSS Selector Level 3](https://www.w3.org/TR/css3-selectors/#UIstates) | Corresponds to GTK_STATE_FLAG_CHECKED |
| E:disabled | [CSS Selector Level 3](https://www.w3.org/TR/css3-selectors/#UIstates) | Corresponds to GTK_STATE_FLAG_CHECKED |
| E:indeterminate | [CSS Selector Level 3](https://www.w3.org/TR/css3-selectors/#indeterminate) | Corresponds to GTK_STATE_FLAG_INCONSISTENT |
| E:backdrop, E:selected | | Corresponds to GTK_STATE_FLAG_BACKDROP, GTK_STATE_FLAG_SELECTED |
| E:not(selector) | [CSS Selector Level 3](https://www.w3.org/TR/css3-selectors/#negation) | |
-4
View File
@@ -66,10 +66,6 @@ You can compile the program above with GCC using:
gcc $( pkg-config --cflags gtk4 ) -o example-0 example-0.c $( pkg-config --libs gtk4 )
```
**Note**: If the above compilation does not work due to an error regarding `G_APPLICATION_DEFAULT_FLAGS`
this could be due to your OS providing an older version of GLib. For GLib versions older than 2.74 you
will need to replace `G_APPLICATION_DEFAULT_FLAGS` with `G_APPLICATION_FLAGS_NONE` in this example, and
others in this documentation.
For more information on how to compile a GTK application, please
refer to the [Compiling GTK Applications](compiling.html)
section in this reference.
-5
View File
@@ -33,11 +33,6 @@ Validation
The ``validate`` command validates the given UI definition file and reports
errors to ``stderr``.
Note that there are limitations to the validation that can be done for templates,
since they are closely tied to the class_init function they are used in.
If your UI file uses types from third-party libraries, it may help to add those
libraries to the `LD_PRELOAD` environment variable.
``--deprecations``
Warn about uses of deprecated types in the UI definition file.
+13 -16
View File
@@ -103,15 +103,14 @@ fields, but e.g. buttons can take the focus too.
Input widgets can be given the focus by clicking on them, but focus
can also be moved around with certain key events (this is known as
“keyboard navigation”).
GTK reserves the <kbd>Tab</kbd> key to move the focus to the next location,
and <kbd>Shift</kbd>+<kbd>Tab</kbd> to move it back to the previous one.
In addition many containers allow “directional navigation” with the arrow keys.
“keyboard navigation”). GTK reserves the Tab key to move the focus
to the next location, and Shift-Tab to move it back to the previous
one. In addition many containers allow “directional navigation” with
the arrow keys.
Many widgets can be “activated” to trigger and action.
E.g., you can activate a button or switch by clicking on them,
but you can also activate them with the keyboard,
by using the <kbd>Enter</kbd> or <kbd>Space</kbd> keys.
Many widgets can be “activated” to trigger and action. E.g., you can
activate a button or switch by clicking on them, but you can also
activate them with the keyboard, by using the Enter or Space keys.
Apart from keyboard navigation, activation and directly typing into
entries or text views, GTK widgets can use key events for activating
@@ -122,17 +121,15 @@ GTK has traditionally supported different kinds of shortcuts:
- Accelerators are any other shortcuts that can be activated regardless
of where the focus is, and typically trigger global actions, such as
<kbd>Ctrl</kbd>+<kbd>Q</kbd> to quit an application.
- Mnemonics are usually triggered using <kbd>Alt</kbd>
as a modifier for a letter.
Ctrl-Q to quit an application.
- Mnemonics are usually triggered using Alt as a modifier for a letter.
They are used in places where a label is associated with a control,
and are indicated by underlining the letter in the label. As a special
case, inside menus (i.e. inside `GtkPopoverMenu`), mnemonics can be
triggered without the modifier.
- Key bindings are specific to individual widgets,
such as <kbd>Ctrl</kbd>+<kbd>C</kbd> or <kbd>Ctrl</kbd>+<kbd>V</kbd>
in an entry copy to or paste from the clipboard.
They are only triggered when the widget has focus.
- Key bindings are specific to individual widgets, such as Ctrl-C or
Ctrl-V in an entry copy to or paste from the clipboard. They are only
triggered when the widget has focus.
GTK handles accelerators and mnemonics in a global scope, during the
capture phase, and key bindings locally, during the target phase.
@@ -211,4 +208,4 @@ sequence, so setting the state on one does transfer the state to
the others. They also are mutually exclusive, within a widget
where may be only one gesture group claiming a given sequence.
If another gesture group claims later that same sequence, the
first group will deny the sequence.
first group will deny the sequence:
+51 -70
View File
@@ -7,50 +7,37 @@ the question you have, this list is a good place to start.
## General Questions
* How do I get started with GTK?
1. How do I get started with GTK?
The GTK [website](https://www.gtk.org) offers some
[tutorials](https://www.gtk.org/documentation.php) and other documentation
This reference manual also contains a introductory
(most of it about GTK 2.x and 3.x, but still somewhat applicable). This
reference manual also contains a introductory
[Getting Started](#gtk-getting-started) part.
More documentation ranging from whitepapers to online books can be found at
the [GNOME developer's site](https://developer.gnome.org). After studying these
materials you should be well prepared to come back to this reference manual for details.
* Where can I get help with GTK, submit a bug report, or make a feature request?
2. Where can I get help with GTK, submit a bug report, or make a feature request?
See the [documentation](#gtk-resources) on this topic.
* How do I port from one GTK version to another?
3. How do I port from one GTK version to another?
Every major version of GTK comes with a [migration guide](#migrating). You may also
find useful information in the documentation for specific widgets and functions. If
you have a question not covered in the manual, feel free to ask, and please
See the [migration guide](#migrating). You may also find useful information in
the documentation for specific widgets and functions. If you have a question not
covered in the manual, feel free to ask, and please
[file a bug report](https://gitlab.gnome.org/GNOME/gtk/issues/new) against the
documentation.
* Should I maintain parallel versions of my UI in GTK x and GTK y?
At the end of the day, that is up to you.
Our experience is that it is a lot of work, and usually not a good idea.
If you are not ready to make the jump to the next major version of GTK,
it is perfectly fine to stick with the stable release. We maintain them
for that reason.
* How does memory management work in GTK? Should I free data returned from functions?
4. How does memory management work in GTK? Should I free data returned from functions?
See the documentation for `GObject` and `GInitiallyUnowned`. For `GObject` note
specifically `g_object_ref()` and `g_object_unref()`. `GInitiallyUnowned` is a
subclass of `GObject` so the same points apply, except that it has a "floating"
state (explained in its documentation).
In a widget tree, each container owns a reference to its children. The root
object (typically a `GtkWindow`) is owned by GTK. GTK will drop its reference
when you call [method@Gtk.Window.destroy].
For strings returned from functions, they will be declared "const" if they should
not be freed. Non-const strings should be freed with `g_free()`. Arrays follow the
same rule. If you find an undocumented exception to the rules, please
@@ -59,7 +46,7 @@ the question you have, this list is a good place to start.
The transfer annotations for gobject-introspection that are part of the
documentation can provide useful hints for memory handling semantics as well.
* Why does my program leak memory, if I destroy a widget immediately
5. Why does my program leak memory, if I destroy a widget immediately
after creating it?
If `GtkFoo` isn't a toplevel window, then
@@ -82,7 +69,7 @@ the question you have, this list is a good place to start.
the initial floating reference and you don't have to worry about reference
counting at all ... just remove the widget from the container to get rid of it.
* How do I use GTK with threads?
6. How do I use GTK with threads?
GTK requires that all GTK API calls are made from the same thread in which
the `GtkApplication` was created, or `gtk_init()` was called (the _main thread_).
@@ -92,7 +79,7 @@ the question you have, this list is a good place to start.
the results back to the main thread using `g_idle_add()` or `GAsyncQueue`. GIO
offers useful tools for such an approach such as `GTask`.
* How do I internationalize a GTK program?
7. How do I internationalize a GTK program?
Most people use [GNU gettext](https://www.gnu.org/software/gettext/),
already required in order to install GLib. On a UNIX or Linux system with
@@ -147,7 +134,7 @@ the question you have, this list is a good place to start.
#define _(x) dgettext (GETTEXT_PACKAGE, x)
* How do I use non-ASCII characters in GTK programs ?
8. How do I use non-ASCII characters in GTK programs ?
GTK uses [Unicode](http://www.unicode.org) (more exactly UTF-8) for all text.
UTF-8 encodes each Unicode codepoint as a sequence of one to six bytes and
@@ -230,7 +217,7 @@ the question you have, this list is a good place to start.
to call bind_textdomain_codeset() to ensure that translated strings
are returned in UTF-8 encoding.
* How do I use GTK with C++?
9. How do I use GTK with C++?
There are two ways to approach this. The GTK header files use the subset
of C that's also valid C++, so you can simply use the normal GTK API
@@ -255,26 +242,19 @@ the question you have, this list is a good place to start.
There are very few functions that require this cast, however.
* How do I use GTK with other non-C languages?
10. How do I use GTK with other non-C languages?
See the list of [language bindings](https://www.gtk.org/language-bindings.php)
on the GTK [website](https://www.gtk.org).
* How do I load an image or animation from a file?
11. How do I load an image or animation from a file?
To load an image file straight into a display widget, use
[ctor@Gtk.Picture.new_for_file] or [ctor@Gtk.Picture.new_for_filename].
To load an image for another purpose, use [ctor@Gdk.Texture.new_from_file].
To load a video from a file, use [ctor@Gtk.MediaFile.new_for_file].
[ctor@Gtk.Image.new_from_file]. To load an image for another purpose, use
[ctor@Gdk.Texture.new_from_file]. To load a video from a file, use
[ctor@Gtk.MediaFile.new_for_file].
Note that [class@Gtk.Image] is meant for fixed-size icons. For arbitrary
image files, you should use [class@Gtk.Picture].
* How do I draw text?
If you just want to put text into your user interface somewhere, it is
usually easiest to just use one of ready-made widgets for this purpose,
such as [class@Gtk.Label].
12. How do I draw text?
To draw a piece of text onto a cairo surface, use a Pango layout and
[func@PangoCairo.show_layout].
@@ -286,13 +266,13 @@ the question you have, this list is a good place to start.
pango_font_description_free (fontdesc);
g_object_unref (layout);
See also the [Cairo Rendering](https://docs.gtk.org/PangoCairo/pango_cairo.html)
section of the [Pango documentation](https://docs.gtk.org/Pango/).
See also the [Cairo Rendering](https://developer.gnome.org/pango/stable/pango-Cairo-Rendering.html)
section of the [Pango documentation](https://developer.gnome.org/pango/stable/).
To draw a piece of text in a widget [vfunc@Gtk.Widget.snapshot] implementation,
use [method@Gtk.Snapshot.append_layout].
* How do I measure the size of a piece of text?
13. How do I measure the size of a piece of text?
To obtain the size of a piece of text, use a Pango layout and
[method@Pango.Layout.get_pixel_size], using code like the following:
@@ -304,10 +284,10 @@ the question you have, this list is a good place to start.
pango_font_description_free (fontdesc);
g_object_unref (layout);
See also the [Layout Objects](https://docs.gtk.org/Pango/class.Layout.html)
section of the [Pango documentation](https://docs.gtk.org/Pango/).
See also the [Layout Objects](https://developer.gnome.org/pango/stable/pango-Layout-Objects.html)
section of the [Pango documentation](https://developer.gnome.org/pango/stable/).
* Why are types not registered if I use their `GTK_TYPE_BLAH` macro?
14. Why are types not registered if I use their `GTK_TYPE_BLAH` macro?
The %GTK_TYPE_BLAH macros are defined as calls to gtk_blah_get_type(), and
the `_get_type()` functions are declared as %G_GNUC_CONST which allows the
@@ -318,14 +298,14 @@ the question you have, this list is a good place to start.
g_type_ensure (GTK_TYPE_BLAH);
* How do I create a transparent toplevel window?
15. How do I create a transparent toplevel window?
Any toplevel window can be transparent. It is just a matter of setting a
transparent background in the CSS style for it.
## Which widget should I use...
* ...for lists and trees?
16. ...for lists and trees?
This question has different answers, depending on the size of the dataset
and the required formatting flexibility.
@@ -341,7 +321,7 @@ the question you have, this list is a good place to start.
and widgetry inside the list, then you probably want to use a [class@Gtk.ListBox],
which uses regular widgets for display.
* ...for multi-line text display or editing?
17. ...for multi-line text display or editing?
See the [text widget overview](#TextWidget) -- you should use the
[class@Gtk.TextView] widget.
@@ -350,7 +330,7 @@ the question you have, this list is a good place to start.
of course. It can be made selectable with [method@Gtk.Label.set_selectable]. For a
single-line text entry, see [class@Gtk.Entry].
* ...to display an image or animation?
18. ...to display an image or animation?
GTK has two widgets that are dedicated to displaying images. [class@Gtk.Image], for
small, fixed-size icons and [class@Gtk.Picture] for content images.
@@ -366,14 +346,17 @@ the question you have, this list is a good place to start.
mediafile = gtk_media_file_new_for_filename ("example.webm");
picture = gtk_picture_new_for_paintable (GDK_PAINTABLE (mediafile));
* ...for presenting a set of mutually-exclusive choices, where Windows
19. ...for presenting a set of mutually-exclusive choices, where Windows
would use a combo box?
With GTK, a [class@Gtk.DropDown] is the recommended widget to use for this use case.
With GTK, a [class@Gtk.ComboBox] is the recommended widget to use for this use case.
If you need an editable text entry, use the [property@Gtk.ComboBox:has-entry] property.
A newer alternative is [class@Gtk.DropDown].
## Questions about GtkWidget
* How do I change the color of a widget?
20. How do I change the color of a widget?
The background color of a widget is determined by the CSS style that applies
to it. To change that, you can set style classes on the widget, and provide
@@ -381,7 +364,7 @@ the question you have, this list is a good place to start.
[method@Gtk.CssProvider.load_from_file] and its variants.
See [method@Gtk.StyleContext.add_provider].
* How do I change the font of a widget?
21. How do I change the font of a widget?
If you want to make the text of a label larger, you can use
gtk_label_set_markup():
@@ -405,14 +388,14 @@ the question you have, this list is a good place to start.
of this approach is that users can then override the font you have chosen.
See the `GtkStyleContext` documentation for more discussion.
* How do I disable/ghost/desensitize a widget?
22. How do I disable/ghost/desensitize a widget?
In GTK a disabled widget is termed _insensitive_.
See [method@Gtk.Widget.set_sensitive].
## GtkTextView questions
* How do I get the contents of the entire text widget as a string?
23. How do I get the contents of the entire text widget as a string?
See [method@Gtk.TextBuffer.get_bounds] and [method@Gtk.TextBuffer.get_text]
or [method@Gtk.TextIter.get_text].
@@ -427,14 +410,14 @@ the question you have, this list is a good place to start.
/* use text */
g_free (text);
* How do I make a text widget display its complete contents in a specific font?
24. How do I make a text widget display its complete contents in a specific font?
If you use [method@Gtk.TextBuffer.insert_with_tags] with appropriate tags to
select the font, the inserted text will have the desired appearance, but
text typed in by the user before or after the tagged block will appear in
the default style.
* How do I make a text view scroll to the end of the buffer automatically ?
25. How do I make a text view scroll to the end of the buffer automatically ?
A good way to keep a text buffer scrolled to the end is to place a
[mark](#GtkTextMark) at the end of the buffer, and give it right gravity.
@@ -449,21 +432,21 @@ the question you have, this list is a good place to start.
## GtkTreeView questions
* How do I associate some data with a row in the tree?
26. How do I associate some data with a row in the tree?
Remember that the [iface@Gtk.TreeModel] columns don't necessarily have to be
displayed. So you can put non-user-visible data in your model just
like any other data, and retrieve it with [method@Gtk.TreeModel.get].
See the [tree widget overview](#TreeWidget).
* How do I put an image and some text in the same column?
27. How do I put an image and some text in the same column?
You can pack more than one [class@Gtk.CellRenderer] into a single [class@Gtk.TreeViewColumn]
using [method@Gtk.TreeViewColumn.pack_start] or [method@Gtk.TreeViewColumn.pack_end].
So pack both a [class@Gtk.CellRendererPixbuf] and a [class@Gtk.CellRendererText] into the
column.
* I can set data easily on my [class@Gtk.TreeStore] or [class@Gtk.ListStore] models using
28. I can set data easily on my [class@Gtk.TreeStore] or [class@Gtk.ListStore] models using
[method@Gtk.ListStore.set] and [method@Gtk.TreeStore.set], but can't read it back?
Both the [class@Gtk.TreeStore] and the [class@Gtk.ListStore] implement the [iface@Gtk.TreeModel]
@@ -471,7 +454,7 @@ the question you have, this list is a good place to start.
implements. The easiest way to read a set of data back is to use
[method@Gtk.TreeModel.get].
* How do I change the way that numbers are formatted by `GtkTreeView`?
29. How do I change the way that numbers are formatted by `GtkTreeView`?
Use [method@Gtk.TreeView.insert_column_with_data_func] or
[method@Gtk.TreeViewColumn.set_cell_data_func] and do the conversion
@@ -545,21 +528,19 @@ the question you have, this list is a good place to start.
(gpointer)DOUBLE_COLUMN, NULL);
}
* How do I hide the expander arrows in my tree view?
30. How do I hide the expander arrows in my tree view?
Set the expander-column property of the tree view to a hidden column.
See [method@Gtk.TreeView.set_expander_column] and [method@Gtk.TreeViewColumn.set_visible].
## Using cairo with GTK
* How do I use cairo to draw in GTK applications?
31. How do I use cairo to draw in GTK applications?
[class@Gtk.DrawingArea] is a ready-made widget for drawing with cairo.
Use [method@Gtk.Snapshot.append_cairo] in your [vfunc@Gtk.Widget.snapshot] vfunc
to obtain a cairo context and draw with that.
If you implement a custom widget, use [method@Gtk.Snapshot.append_cairo]
in your [vfunc@Gtk.Widget.snapshot] vfunc to obtain a cairo context and draw with that.
* Can I improve the performance of my application by using another backend
32. Can I improve the performance of my application by using another backend
of cairo (such as GL)?
No. Most drawing in GTK is not done via cairo anymore (but instead
@@ -570,7 +551,7 @@ the question you have, this list is a good place to start.
If you are interested in using GL for your own drawing, see [class@Gtk.GLArea].
* Can I use cairo to draw on a `GdkPixbuf`?
33. Can I use cairo to draw on a `GdkPixbuf`?
No. The cairo image surface does not support the pixel format used by `GdkPixbuf`.
+1 -1
View File
@@ -1,6 +1,6 @@
app2_resources = gnome.compile_resources('exampleapp2_resources',
'exampleapp.gresource.xml',
source_dir: meson.current_source_dir())
source_dir: '.')
executable('exampleapp2',
'exampleapp.c', 'exampleappwin.c', 'main.c', app2_resources,
+1 -1
View File
@@ -1,6 +1,6 @@
app3_resources = gnome.compile_resources('exampleapp3_resources',
'exampleapp.gresource.xml',
source_dir: meson.current_source_dir())
source_dir: '.')
executable('exampleapp3',
'exampleapp.c', 'exampleappwin.c', 'main.c', app3_resources,
+1 -1
View File
@@ -1,6 +1,6 @@
app4_resources = gnome.compile_resources('exampleapp4_resources',
'exampleapp.gresource.xml',
source_dir: meson.current_source_dir())
source_dir: '.')
executable('exampleapp4',
'exampleapp.c', 'exampleappwin.c', 'main.c', app4_resources,
+1 -1
View File
@@ -1,6 +1,6 @@
app5_resources = gnome.compile_resources('exampleapp5_resources',
'exampleapp.gresource.xml',
source_dir: meson.current_source_dir())
source_dir: '.')
app5_schemas = gnome.compile_schemas()
+1 -1
View File
@@ -1,6 +1,6 @@
app6_resources = gnome.compile_resources('exampleapp6_resources',
'exampleapp.gresource.xml',
source_dir: meson.current_source_dir())
source_dir: '.')
app6_schemas = gnome.compile_schemas()
+1 -1
View File
@@ -1,6 +1,6 @@
app7_resources = gnome.compile_resources('exampleapp7_resources',
'exampleapp.gresource.xml',
source_dir: meson.current_source_dir())
source_dir: '.')
app7_schemas = gnome.compile_schemas()
+1 -1
View File
@@ -1,6 +1,6 @@
app8_resources = gnome.compile_resources('exampleapp8 resources',
'exampleapp.gresource.xml',
source_dir: meson.current_source_dir())
source_dir: '.')
app8_schemas = gnome.compile_schemas()
+1 -1
View File
@@ -1,6 +1,6 @@
app9_resources = gnome.compile_resources('exampleapp9_resources',
'exampleapp.gresource.xml',
source_dir: meson.current_source_dir())
source_dir: '.')
app9_schemas = gnome.compile_schemas()
+1 -1
View File
@@ -1,5 +1,5 @@
bp_resources = gnome.compile_resources('bloatpad_resources',
'bloatpad.gresources.xml',
source_dir: meson.current_source_dir())
source_dir: '.')
executable('bloatpad', 'bloatpad.c', bp_resources, dependencies: libgtk_dep, c_args: common_cflags)
-7
View File
@@ -1,7 +0,0 @@
A trivial example
=================
This is a very minimal example of an app that can be built against GTK.
We use this in CI to test that building against the installed GTK works.
That is why there is a standalone meson.build in this subdirectory.
+4 -4
View File
@@ -1574,8 +1574,7 @@ broadway_server_query_mouse (BroadwayServer *server,
void
broadway_server_destroy_surface (BroadwayServer *server,
int id,
gboolean disconnected)
int id)
{
BroadwaySurface *surface;
gint32 transient_for = -1;
@@ -1590,7 +1589,8 @@ broadway_server_destroy_surface (BroadwayServer *server,
server->pointer_grab_surface_id = -1;
if (server->output)
broadway_output_destroy_surface (server->output, id);
broadway_output_destroy_surface (server->output,
id);
surface = broadway_server_lookup_surface (server, id);
if (surface != NULL)
@@ -1604,7 +1604,7 @@ broadway_server_destroy_surface (BroadwayServer *server,
broadway_surface_free (server, surface);
}
if (transient_for != -1 && !disconnected)
if (transient_for != -1)
{
surface = broadway_server_lookup_surface (server, transient_for);
if (surface != NULL)
+1 -2
View File
@@ -93,8 +93,7 @@ guint32 broadway_server_new_surface (BroadwayServer *
int width,
int height);
void broadway_server_destroy_surface (BroadwayServer *server,
int id,
gboolean disconnected);
int id);
gboolean broadway_server_surface_show (BroadwayServer *server,
int id);
gboolean broadway_server_surface_hide (BroadwayServer *server,
+3 -2
View File
@@ -101,7 +101,8 @@ client_disconnected (BroadwayClient *client)
}
for (l = client->surfaces; l != NULL; l = l->next)
broadway_server_destroy_surface (server, GPOINTER_TO_UINT (l->data), TRUE);
broadway_server_destroy_surface (server,
GPOINTER_TO_UINT (l->data));
g_list_free (client->surfaces);
client->surfaces = NULL;
@@ -267,7 +268,7 @@ client_handle_request (BroadwayClient *client,
client->surfaces =
g_list_remove (client->surfaces,
GUINT_TO_POINTER (request->destroy_surface.id));
broadway_server_destroy_surface (server, request->destroy_surface.id, FALSE);
broadway_server_destroy_surface (server, request->destroy_surface.id);
break;
case BROADWAY_REQUEST_SHOW_SURFACE:
broadway_server_surface_show (server, request->show_surface.id);
-1
View File
@@ -69,7 +69,6 @@
#include <gdk/gdksnapshot.h>
#include <gdk/gdksurface.h>
#include <gdk/gdktexture.h>
#include <gdk/gdktexturedownloader.h>
#include <gdk/gdktoplevel.h>
#include <gdk/gdktoplevellayout.h>
#include <gdk/gdktoplevelsize.h>
-4
View File
@@ -60,11 +60,7 @@ GdkDebugFlags gdk_display_get_debug_flags (GdkDisplay *display);
void gdk_display_set_debug_flags (GdkDisplay *display,
GdkDebugFlags flags);
#ifdef GLIB_USING_SYSTEM_PRINTF
#define gdk_debug_message(format, ...) fprintf (stderr, format "\n", ##__VA_ARGS__)
#else
#define gdk_debug_message(format, ...) g_fprintf (stderr, format "\n", ##__VA_ARGS__)
#endif
#ifdef G_ENABLE_DEBUG
+2
View File
@@ -1723,6 +1723,8 @@ gdk_display_init_egl (GdkDisplay *self,
epoxy_has_egl_extension (priv->egl_display, "EGL_KHR_no_config_context");
self->have_egl_pixel_format_float =
epoxy_has_egl_extension (priv->egl_display, "EGL_EXT_pixel_format_float");
self->have_egl_win32_libangle =
epoxy_has_egl_extension (priv->egl_display, "EGL_ANGLE_d3d_share_handle_client_buffer");
if (self->have_egl_no_config_context)
priv->egl_config_high_depth = gdk_display_create_egl_config (self,
+2 -15
View File
@@ -410,19 +410,12 @@ gdk_display_manager_open_display (GdkDisplayManager *manager,
{
const char *backend = backends[i];
gboolean any = g_str_equal (backend, "*");
gboolean found = FALSE;
if (!allow_any && !any && !strstr (allowed_backends, backend))
{
GDK_DEBUG (MISC, "Skipping %s backend", backend);
continue;
}
continue;
for (j = 0; gdk_backends[j].name != NULL; j++)
{
if (g_str_equal (backend, gdk_backends[j].name))
found = TRUE;
if ((any && allow_any) ||
(any && strstr (allowed_backends, gdk_backends[j].name)) ||
g_str_equal (backend, gdk_backends[j].name))
@@ -430,15 +423,9 @@ gdk_display_manager_open_display (GdkDisplayManager *manager,
GDK_DEBUG (MISC, "Trying %s backend", gdk_backends[j].name);
display = gdk_backends[j].open_display (name);
if (display)
{
GDK_DEBUG (MISC, "Using %s display %s", gdk_backends[j].name, gdk_display_get_name (display));
break;
}
break;
}
}
if (!found && !display)
g_warning ("No such backend: %s", backend);
}
g_strfreev (backends);
+1
View File
@@ -109,6 +109,7 @@ struct _GdkDisplay
guint have_egl_buffer_age : 1;
guint have_egl_no_config_context : 1;
guint have_egl_pixel_format_float : 1;
guint have_egl_win32_libangle : 1;
};
struct _GdkDisplayClass
-6
View File
@@ -371,12 +371,6 @@ gdk_draw_context_begin_frame_full (GdkDrawContext *context,
priv->surface->paint_context = g_object_ref (context);
GDK_DRAW_CONTEXT_GET_CLASS (context)->begin_frame (context, prefers_high_depth, priv->frame_region);
cairo_region_intersect_rectangle (priv->frame_region,
&(cairo_rectangle_int_t) {
0, 0,
priv->surface->width, priv->surface->height
});
}
#ifdef HAVE_SYSPROF
+2 -2
View File
@@ -48,7 +48,7 @@
* for the synchronization being implemented, the clock will process a frame and
* emit signals for each phase that has been requested. (See the signals of the
* `GdkFrameClock` class for documentation of the phases.
* %GDK_FRAME_CLOCK_PHASE_UPDATE and the [signal@Gdk.FrameClock::update] signal
* %GDK_FRAME_CLOCK_PHASE_UPDATE and the [signal@GdkFrameClock::update] signal
* are most interesting for application writers, and are used to update the
* animations, using the frame time given by [method@Gdk.FrameClock.get_frame_time].
*
@@ -60,7 +60,7 @@
* are called at a similar time get the same value. This means that
* if different animations are timed by looking at the difference in
* time between an initial value from [method@Gdk.FrameClock.get_frame_time]
* and the value inside the [signal@Gdk.FrameClock::update] signal of the clock,
* and the value inside the [signal@GdkFrameClock::update] signal of the clock,
* they will stay exactly synchronized.
*/
+12 -2
View File
@@ -295,6 +295,7 @@ gdk_gl_context_create_egl_context (GdkGLContext *context,
/* We will use the default version matching the context status
* unless the user requested a version which makes sense */
gdk_gl_context_get_matching_version (api, legacy,
display->have_egl_win32_libangle,
&min_major, &min_minor);
gdk_gl_context_get_clipped_version (context,
min_major, min_minor,
@@ -967,6 +968,7 @@ gdk_gl_context_get_forward_compatible (GdkGLContext *context)
void
gdk_gl_context_get_matching_version (GdkGLAPI api,
gboolean legacy,
gboolean win32_libangle,
int *major,
int *minor)
{
@@ -987,8 +989,16 @@ gdk_gl_context_get_matching_version (GdkGLAPI api,
}
else
{
maj = GDK_GL_MIN_GLES_VERSION_MAJOR;
min = GDK_GL_MIN_GLES_VERSION_MINOR;
if (win32_libangle)
{
maj = GDK_GL_MIN_GLES_WIN32_ANGLE_VERSION_MAJOR;
min = GDK_GL_MIN_GLES_WIN32_ANGLE_VERSION_MINOR;
}
else
{
maj = GDK_GL_MIN_GLES_VERSION_MAJOR;
min = GDK_GL_MIN_GLES_VERSION_MINOR;
}
}
if (major != NULL)
+6 -1
View File
@@ -37,7 +37,8 @@ G_BEGIN_DECLS
* Backends should make sure to never create a context of a previous version.
*
* The macros refer to OpenGL; OpenGL with OPENGL_COMPATIBILITY_PROFILE_BIT as
* OPENGL_PROFILE_MASK; and OpenGL ES respectively
* OPENGL_PROFILE_MASK; OpenGL ES; and OpenGL ES win32 Angle implementation,
* respectively
*/
#define GDK_GL_MIN_GL_VERSION_MAJOR (3)
#define GDK_GL_MIN_GL_VERSION_MINOR (2)
@@ -45,6 +46,8 @@ G_BEGIN_DECLS
#define GDK_GL_MIN_GL_LEGACY_VERSION_MINOR (0)
#define GDK_GL_MIN_GLES_VERSION_MAJOR (2)
#define GDK_GL_MIN_GLES_VERSION_MINOR (0)
#define GDK_GL_MIN_GLES_WIN32_ANGLE_VERSION_MAJOR (3)
#define GDK_GL_MIN_GLES_WIN32_ANGLE_VERSION_MINOR (0)
typedef enum {
GDK_GL_NONE = 0,
@@ -98,6 +101,7 @@ typedef struct {
} GdkGLContextProgram;
typedef struct {
guint vertex_array_object;
guint tmp_framebuffer;
guint tmp_vertex_buffer;
@@ -137,6 +141,7 @@ void gdk_gl_context_get_clipped_version (GdkGLContext
int *minor);
void gdk_gl_context_get_matching_version (GdkGLAPI api,
gboolean legacy,
gboolean win32_libangle,
int *major,
int *minor);
+53 -1
View File
@@ -24,6 +24,7 @@
#include "gdkglcontextprivate.h"
#include "gdkmemoryformatprivate.h"
#include "gdkmemorytextureprivate.h"
#include "gdktextureprivate.h"
#include <epoxy/gl.h>
@@ -38,6 +39,7 @@ struct _GdkGLTexture {
GdkGLContext *context;
guint id;
GLsync sync;
GdkTexture *saved;
@@ -63,6 +65,7 @@ drop_gl_resources (GdkGLTexture *self)
g_clear_object (&self->context);
self->id = 0;
self->sync = NULL;
}
static void
@@ -98,6 +101,10 @@ gdk_gl_texture_invoke_callback (gpointer data)
context = gdk_display_get_gl_context (gdk_gl_context_get_display (invoke->self->context));
gdk_gl_context_make_current (context);
if (invoke->self->sync && context != invoke->self->context)
glWaitSync (invoke->self->sync, 0, GL_TIMEOUT_IGNORED);
glBindTexture (GL_TEXTURE_2D, invoke->self->id);
invoke->func (invoke->self, context, invoke->data);
@@ -335,7 +342,6 @@ gdk_gl_texture_determine_format (GdkGLTexture *self)
switch (internal_format)
{
case GL_RGB8:
case GL_RGB:
texture->format = GDK_MEMORY_R8G8B8;
break;
@@ -440,6 +446,46 @@ gdk_gl_texture_new (GdkGLContext *context,
int height,
GDestroyNotify destroy,
gpointer data)
{
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL);
g_return_val_if_fail (id != 0, NULL);
g_return_val_if_fail (width > 0, NULL);
g_return_val_if_fail (height > 0, NULL);
return gdk_gl_texture_new_with_sync (context, id, NULL, width, height, destroy, data);
}
/*< private >
* gdk_gl_texture_new_with_sync:
* @context: a `GdkGLContext`
* @id: the ID of a texture that was created with @context
* @sync: (nullable): an optional GLsync object
* @width: the nominal width of the texture
* @height: the nominal height of the texture
* @destroy: a destroy notify that will be called when the GL resources
* are released
* @data: data that gets passed to @destroy
*
* Creates a new texture for an existing GL texture.
*
* If @sync is given, consumers of the texture are required to wait on
* it before attempting to use the GL texture.
*
* The GL texture and the sync object must stay alive unmodified until
* @destroy is called, which will happen when the GdkTexture object is
* finalized, or due to an explicit call of [method@Gdk.GLTexture.release].
*
* Return value: (transfer full) (type GdkGLTexture): A newly-created
* `GdkTexture`
*/
GdkTexture *
gdk_gl_texture_new_with_sync (GdkGLContext *context,
guint id,
gpointer sync,
int width,
int height,
GDestroyNotify destroy,
gpointer data)
{
GdkGLTexture *self;
@@ -455,6 +501,7 @@ gdk_gl_texture_new (GdkGLContext *context,
self->context = g_object_ref (context);
self->id = id;
self->sync = sync;
self->destroy = destroy;
self->data = data;
@@ -463,3 +510,8 @@ gdk_gl_texture_new (GdkGLContext *context,
return GDK_TEXTURE (self);
}
gpointer
gdk_gl_texture_get_sync (GdkGLTexture *self)
{
return self->sync;
}
+10
View File
@@ -9,6 +9,16 @@ G_BEGIN_DECLS
GdkGLContext * gdk_gl_texture_get_context (GdkGLTexture *self);
guint gdk_gl_texture_get_id (GdkGLTexture *self);
gpointer gdk_gl_texture_get_sync (GdkGLTexture *self);
GDK_AVAILABLE_IN_4_10
GdkTexture * gdk_gl_texture_new_with_sync (GdkGLContext *context,
guint id,
gpointer sync,
int width,
int height,
GDestroyNotify destroy,
gpointer data);
G_END_DECLS
+14 -10
View File
@@ -178,10 +178,10 @@ gdk_memory_texture_new_subtexture (GdkMemoryTexture *source,
GBytes *bytes;
g_return_val_if_fail (GDK_IS_MEMORY_TEXTURE (source), NULL);
g_return_val_if_fail (x >= 0 && x < GDK_TEXTURE (source)->width, NULL);
g_return_val_if_fail (y >= 0 && y < GDK_TEXTURE (source)->height, NULL);
g_return_val_if_fail (width > 0 && x + width <= GDK_TEXTURE (source)->width, NULL);
g_return_val_if_fail (height > 0 && y + height <= GDK_TEXTURE (source)->height, NULL);
g_return_val_if_fail (x >= 0 || x < GDK_TEXTURE (source)->width, NULL);
g_return_val_if_fail (y >= 0 || y < GDK_TEXTURE (source)->height, NULL);
g_return_val_if_fail (width > 0 || x + width <= GDK_TEXTURE (source)->width, NULL);
g_return_val_if_fail (height > 0 || y + height <= GDK_TEXTURE (source)->height, NULL);
texture = GDK_TEXTURE (source);
bpp = gdk_memory_format_bytes_per_pixel (texture->format);
@@ -222,7 +222,7 @@ gdk_memory_texture_from_texture (GdkTexture *texture,
data = g_malloc_n (stride, texture->height);
gdk_texture_do_download (texture, format, data, stride);
bytes = g_bytes_new_take (data, stride * texture->height);
bytes = g_bytes_new_take (data, stride);
result = gdk_memory_texture_new (texture->width,
texture->height,
format,
@@ -233,11 +233,15 @@ gdk_memory_texture_from_texture (GdkTexture *texture,
return GDK_MEMORY_TEXTURE (result);
}
GBytes *
gdk_memory_texture_get_bytes (GdkMemoryTexture *self,
gsize *out_stride)
const guchar *
gdk_memory_texture_get_data (GdkMemoryTexture *self)
{
*out_stride = self->stride;
return self->bytes;
return g_bytes_get_data (self->bytes, NULL);
}
gsize
gdk_memory_texture_get_stride (GdkMemoryTexture *self)
{
return self->stride;
}
+2 -2
View File
@@ -37,8 +37,8 @@ GdkTexture * gdk_memory_texture_new_subtexture (GdkMemoryTexture *
int width,
int height);
GBytes * gdk_memory_texture_get_bytes (GdkMemoryTexture *self,
gsize *out_stride);
const guchar * gdk_memory_texture_get_data (GdkMemoryTexture *self);
gsize gdk_memory_texture_get_stride (GdkMemoryTexture *self);
G_END_DECLS
+5 -5
View File
@@ -50,7 +50,7 @@ void gtk_snapshot_pop (GdkSnapshot
* to do, it is suggested that you scale your paintable ignoring any potential
* aspect ratio.
*
* The contents that a `GdkPaintable` produces may depend on the [class@Gdk.Snapshot]
* The contents that a `GdkPaintable` produces may depend on the [class@GdkSnapshot]
* passed to it. For example, paintables may decide to use more detailed images
* on higher resolution screens or when OpenGL is available. A `GdkPaintable`
* will however always produce the same output for the same snapshot.
@@ -58,7 +58,7 @@ void gtk_snapshot_pop (GdkSnapshot
* A `GdkPaintable` may change its contents, meaning that it will now produce
* a different output with the same snapshot. Once that happens, it will call
* [method@Gdk.Paintable.invalidate_contents] which will emit the
* [signal@Gdk.Paintable::invalidate-contents] signal. If a paintable is known
* [signal@GdkPaintable::invalidate-contents] signal. If a paintable is known
* to never change its contents, it will set the %GDK_PAINTABLE_STATIC_CONTENTS
* flag. If a consumer cannot deal with changing contents, it may call
* [method@Gdk.Paintable.get_current_image] which will return a static
@@ -69,7 +69,7 @@ void gtk_snapshot_pop (GdkSnapshot
* can use this information to layout thepaintable appropriately. Just like the
* contents, the size of a paintable can change. A paintable will indicate this
* by calling [method@Gdk.Paintable.invalidate_size] which will emit the
* [signal@Gdk.Paintable::invalidate-size] signal. And just like for contents,
* [signal@GdkPaintable::invalidate-size] signal. And just like for contents,
* if a paintable is known to never change its size, it will set the
* %GDK_PAINTABLE_STATIC_SIZE flag.
*
@@ -529,7 +529,7 @@ gdk_paintable_compute_concrete_size (GdkPaintable *paintable,
* the missing dimension is calculated from the present
* dimension and the intrinsic aspect ratio.
* Otherwise, the missing dimension is taken from the default
* object size.
* object size.
*/
if (image_width)
*concrete_width = image_width;
@@ -559,7 +559,7 @@ gdk_paintable_compute_concrete_size (GdkPaintable *paintable,
* dimensions, the missing dimension is taken from the object's intrinsic
* dimensions.
* Otherwise, the missing dimension of the concrete object size is taken
* from the default object size.
* from the default object size.
*/
if (specified_width)
{
+3 -3
View File
@@ -37,10 +37,10 @@ G_DECLARE_INTERFACE (GdkPaintable, gdk_paintable, GDK, PAINTABLE, GObject)
/**
* GdkPaintableFlags:
* @GDK_PAINTABLE_STATIC_SIZE: The size is immutable.
* The [signal@Gdk.Paintable::invalidate-size] signal will never be
* The [signal@GdkPaintable::invalidate-size] signal will never be
* emitted.
* @GDK_PAINTABLE_STATIC_CONTENTS: The content is immutable.
* The [signal@Gdk.Paintable::invalidate-contents] signal will never be
* The [signal@GdkPaintable::invalidate-contents] signal will never be
* emitted.
*
* Flags about a paintable object.
@@ -97,7 +97,7 @@ struct _GdkPaintableInterface
double height);
/* get the current contents in an immutable form (optional) */
GdkPaintable * (* get_current_image) (GdkPaintable *paintable);
/* get flags for potential optimizations (optional) */
GdkPaintableFlags (* get_flags) (GdkPaintable *paintable);
/* preferred width of paintable or 0 if it has no width (optional) */
+12 -17
View File
@@ -27,7 +27,7 @@
#include "gdkmemoryformatprivate.h"
#include "gdkmemorytextureprivate.h"
#include "gdksurface.h"
#include "gdktexturedownloaderprivate.h"
#include "gdktextureprivate.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
@@ -218,9 +218,9 @@ gdk_pixbuf_get_from_surface (cairo_surface_t *surface,
static void
pixbuf_texture_unref_cb (guchar *pixels,
gpointer bytes)
gpointer texture)
{
g_bytes_unref (bytes);
g_object_unref (texture);
}
/**
@@ -238,27 +238,22 @@ pixbuf_texture_unref_cb (guchar *pixels,
GdkPixbuf *
gdk_pixbuf_get_from_texture (GdkTexture *texture)
{
GdkTextureDownloader downloader;
GBytes *bytes;
gsize stride;
GdkMemoryTexture *memtex;
gboolean alpha;
alpha = gdk_memory_format_alpha (gdk_texture_get_format (texture)) != GDK_MEMORY_ALPHA_OPAQUE;
gdk_texture_downloader_init (&downloader, texture);
gdk_texture_downloader_set_format (&downloader,
alpha ? GDK_MEMORY_GDK_PIXBUF_ALPHA
: GDK_MEMORY_GDK_PIXBUF_OPAQUE);
bytes = gdk_texture_downloader_download_bytes (&downloader, &stride);
gdk_texture_downloader_finish (&downloader);
memtex = gdk_memory_texture_from_texture (texture,
alpha ? GDK_MEMORY_GDK_PIXBUF_ALPHA
: GDK_MEMORY_GDK_PIXBUF_OPAQUE);
return gdk_pixbuf_new_from_data (g_bytes_get_data (bytes, NULL),
return gdk_pixbuf_new_from_data (gdk_memory_texture_get_data (memtex),
GDK_COLORSPACE_RGB,
alpha,
8,
gdk_texture_get_width (texture),
gdk_texture_get_height (texture),
stride,
gdk_texture_get_width (GDK_TEXTURE (memtex)),
gdk_texture_get_height (GDK_TEXTURE (memtex)),
gdk_memory_texture_get_stride (memtex),
pixbuf_texture_unref_cb,
bytes);
memtex);
}
+2 -2
View File
@@ -31,7 +31,7 @@
* The `GdkPopup` is positioned relative to its parent surface.
*
* `GdkPopup`s are typically used to implement menus and similar popups.
* They can be modal, which is indicated by the [property@Gdk.Popup:autohide]
* They can be modal, which is indicated by the [property@GdkPopup:autohide]
* property.
*/
@@ -113,7 +113,7 @@ gdk_popup_default_init (GdkPopupInterface *iface)
* otherwise it will change position according to @layout.
*
* After calling this function, the result should be handled in response
* to the [signal@Gdk.Surface::layout] signal being emitted. The resulting
* to the [signal@GdkSurface::layout] signal being emitted. The resulting
* popup position can be queried using [method@Gdk.Popup.get_position_x],
* [method@Gdk.Popup.get_position_y], and the resulting size will be sent as
* parameters in the layout signal. Use [method@Gdk.Popup.get_rect_anchor]
+1 -3
View File
@@ -165,7 +165,7 @@ parse_rgb_value (const char *str,
*
* The string can be either one of:
*
* - A standard name (Taken from the CSS specification).
* - A standard name (Taken from the Css specification).
* - A hexadecimal value in the form \#rgb, \#rrggbb,
* \#rrrgggbbb or \#rrrrggggbbbb
* - A hexadecimal value in the form \#rgba, \#rrggbbaa,
@@ -173,8 +173,6 @@ parse_rgb_value (const char *str,
* - A RGB color in the form rgb(r,g,b) (In this case the color
* will have full opacity)
* - A RGBA color in the form rgba(r,g,b,a)
* - A HSL color in the form "hsl(hue, saturation, lightness)"
* - A HSLA color in the form "hsla(hue, saturation, lightness, alpha)"
*
* Where r, g, b and a are respectively the red, green,
* blue and alpha color values. In the last two cases, r, g,
+1 -24
View File
@@ -395,7 +395,7 @@ gdk_texture_new_for_pixbuf (GdkPixbuf *pixbuf)
bytes = g_bytes_new_with_free_func (gdk_pixbuf_get_pixels (pixbuf),
gdk_pixbuf_get_height (pixbuf)
* (gsize) gdk_pixbuf_get_rowstride (pixbuf),
* gdk_pixbuf_get_rowstride (pixbuf),
g_object_unref,
g_object_ref (pixbuf));
texture = gdk_memory_texture_new (gdk_pixbuf_get_width (pixbuf),
@@ -722,9 +722,6 @@ gdk_texture_download_surface (GdkTexture *texture)
* cairo_image_surface_get_stride (surface));
* cairo_surface_mark_dirty (surface);
* ```
*
* For more flexible download capabilites, see
* [struct@Gdk.TextureDownloader].
*/
void
gdk_texture_download (GdkTexture *texture,
@@ -741,29 +738,9 @@ gdk_texture_download (GdkTexture *texture,
stride);
}
/**
* gdk_texture_get_format:
* @self: a GdkTexture
*
* Gets the memory format most closely associated with the data of
* the texture.
*
* Note that it may not be an exact match for texture data
* stored on the GPU or with compression.
*
* The format can give an indication about the bit depth and opacity
* of the texture and is useful to determine the best format for
* downloading the texture.
*
* Returns: the preferred format for the texture's data
*
* Since: 4.10
**/
GdkMemoryFormat
gdk_texture_get_format (GdkTexture *self)
{
g_return_val_if_fail (GDK_IS_TEXTURE (self), GDK_MEMORY_DEFAULT);
return self->format;
}
-3
View File
@@ -24,7 +24,6 @@
#endif
#include <gdk/gdkversionmacros.h>
#include <gdk/gdkenums.h>
#include <gdk/gdktypes.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
@@ -83,8 +82,6 @@ GDK_AVAILABLE_IN_ALL
int gdk_texture_get_width (GdkTexture *texture) G_GNUC_PURE;
GDK_AVAILABLE_IN_ALL
int gdk_texture_get_height (GdkTexture *texture) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_10
GdkMemoryFormat gdk_texture_get_format (GdkTexture *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_ALL
void gdk_texture_download (GdkTexture *texture,
-268
View File
@@ -1,268 +0,0 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2023 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 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/>.
*/
/**
* GdkTextureDownloader:
*
* The `GdkTextureDownloader` is used to download the contents of a
* [class@Gdk.Texture].
*
* It is intended to be created as a short-term object for a single download,
* but can be used for multipe downloads of different textures or with different
* settings.
*
* `GdkTextureDownloader` can be used to convert data between different formats.
* Create a `GdkTexture` for the existing format and then download it in a
* different format.
*
* Since: 4.10
*/
#include "config.h"
#include "gdktexturedownloaderprivate.h"
#include "gdkmemoryformatprivate.h"
#include "gdkmemorytextureprivate.h"
#include "gdktextureprivate.h"
G_DEFINE_BOXED_TYPE (GdkTextureDownloader, gdk_texture_downloader,
gdk_texture_downloader_copy,
gdk_texture_downloader_free)
void
gdk_texture_downloader_init (GdkTextureDownloader *self,
GdkTexture *texture)
{
self->texture = g_object_ref (texture);
self->format = GDK_MEMORY_DEFAULT;
}
void
gdk_texture_downloader_finish (GdkTextureDownloader *self)
{
g_object_unref (self->texture);
}
/**
* gdk_texture_downloader_new:
* @texture: texture to download
*
* Creates a new texture downloader for @texture.
*
* Returns: A new texture downloader
*
* Since: 4.10
**/
GdkTextureDownloader *
gdk_texture_downloader_new (GdkTexture *texture)
{
GdkTextureDownloader *self;
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
self = g_slice_new (GdkTextureDownloader);
gdk_texture_downloader_init (self, texture);
return self;
}
/**
* gdk_texture_downloader_copy:
* @self: the downloader to copy
*
* Creates a copy of the downloader.
*
* This function is meant for language bindings.
*
* Returns: A copy of the downloader
*
* Since: 4.10
**/
GdkTextureDownloader *
gdk_texture_downloader_copy (const GdkTextureDownloader *self)
{
GdkTextureDownloader *copy;
g_return_val_if_fail (self != NULL, NULL);
copy = gdk_texture_downloader_new (self->texture);
gdk_texture_downloader_set_format (copy, self->format);
return copy;
}
/**
* gdk_texture_downloader_free:
* @self: texture downloader to free
*
* Frees the given downloader and all its associated resources.
*
* Since: 4.10
**/
void
gdk_texture_downloader_free (GdkTextureDownloader *self)
{
g_return_if_fail (self != NULL);
gdk_texture_downloader_finish (self);
g_slice_free (GdkTextureDownloader, self);
}
/**
* gdk_texture_downloader_set_texture:
* @self: a texture downloader
* @texture: the new texture to download
*
* Changes the texture the downloader will download.
*
* Since: 4.10
**/
void
gdk_texture_downloader_set_texture (GdkTextureDownloader *self,
GdkTexture *texture)
{
g_return_if_fail (self != NULL);
g_return_if_fail (GDK_IS_TEXTURE (texture));
g_set_object (&self->texture, texture);
}
/**
* gdk_texture_downloader_get_texture:
* @self: a texture downloader
*
* Gets the texture that the downloader will download.
*
* Returns: (transfer none): The texture to download
*
* Since: 4.10
**/
GdkTexture *
gdk_texture_downloader_get_texture (const GdkTextureDownloader *self)
{
g_return_val_if_fail (self != NULL, NULL);
return self->texture;
}
/**
* gdk_texture_downloader_set_format:
* @self: a texture downloader
* @format: the format to use
*
* Sets the format the downloader will download.
*
* By default, GDK_MEMORY_DEFAULT is set.
*
* Since: 4.10
*/
void
gdk_texture_downloader_set_format (GdkTextureDownloader *self,
GdkMemoryFormat format)
{
g_return_if_fail (self != NULL);
self->format = format;
}
/**
* gdk_texture_downloader_get_format:
* @self: a texture downloader
*
* Gets the format that the data will be downloaded in.
*
* Returns: The format of the download
*
* Since: 4.10
**/
GdkMemoryFormat
gdk_texture_downloader_get_format (const GdkTextureDownloader *self)
{
g_return_val_if_fail (self != NULL, GDK_MEMORY_DEFAULT);
return self->format;
}
/**
* gdk_texture_downloader_download_into:
* @self: a texture downloader
* @data: (array): pointer to enough memory to be filled with the
* downloaded data of the texture
* @stride: rowstride in bytes
*
* Downloads the @texture into local memory.
*
* Since: 4.10
**/
void
gdk_texture_downloader_download_into (const GdkTextureDownloader *self,
guchar *data,
gsize stride)
{
g_return_if_fail (self != NULL);
g_return_if_fail (data != NULL);
g_return_if_fail (stride >= gdk_texture_get_width (self->texture) * gdk_memory_format_bytes_per_pixel (self->format));
gdk_texture_do_download (self->texture, self->format, data, stride);
}
/**
* gdk_texture_downloader_download_bytes:
* @self: the downloader
* @out_stride: (out): The stride of the resulting data in bytes.
*
* Downloads the given texture pixels into a `GBytes`. The rowstride will
* be stored in the stride value.
*
* This function will abort if it tries to download a large texture and
* fails to allocate memory. If you think that may happen, you should
* handle memory allocation yourself and use
* gdk_texture_downloader_download_into() once allocation succeeded.
*
* Returns: The downloaded pixels.
*
* Since: 4.10
**/
GBytes *
gdk_texture_downloader_download_bytes (const GdkTextureDownloader *self,
gsize *out_stride)
{
guchar *data;
gsize stride;
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (out_stride != NULL, NULL);
if (GDK_IS_MEMORY_TEXTURE (self->texture) &&
gdk_texture_get_format (self->texture) == self->format)
{
GdkMemoryTexture *memtex = GDK_MEMORY_TEXTURE (self->texture);
return g_bytes_ref (gdk_memory_texture_get_bytes (memtex, out_stride));
}
stride = self->texture->width * gdk_memory_format_bytes_per_pixel (self->format);
data = g_malloc_n (stride, self->texture->height);
gdk_texture_do_download (self->texture, self->format, data, stride);
*out_stride = stride;
return g_bytes_new_take (data, stride * self->texture->height);
}
-69
View File
@@ -1,69 +0,0 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2023 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 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/>.
*/
#ifndef __GTK_TEXTURE_DOWNLOADER_H__
#define __GTK_TEXTURE_DOWNLOADER_H__
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#include <gdk/gdkversionmacros.h>
#include <gdk/gdkenums.h>
#include <gdk/gdktypes.h>
G_BEGIN_DECLS
#define GDK_TYPE_TEXTURE_DOWNLOADER (gdk_texture_downloader_get_type ())
GDK_AVAILABLE_IN_4_10
GType gdk_texture_downloader_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_4_10
GdkTextureDownloader * gdk_texture_downloader_new (GdkTexture *texture);
GDK_AVAILABLE_IN_4_10
GdkTextureDownloader * gdk_texture_downloader_copy (const GdkTextureDownloader *self);
GDK_AVAILABLE_IN_4_10
void gdk_texture_downloader_free (GdkTextureDownloader *self);
GDK_AVAILABLE_IN_4_10
void gdk_texture_downloader_set_texture (GdkTextureDownloader *self,
GdkTexture *texture);
GDK_AVAILABLE_IN_4_10
GdkTexture * gdk_texture_downloader_get_texture (const GdkTextureDownloader *self);
GDK_AVAILABLE_IN_4_10
void gdk_texture_downloader_set_format (GdkTextureDownloader *self,
GdkMemoryFormat format);
GDK_AVAILABLE_IN_4_10
GdkMemoryFormat gdk_texture_downloader_get_format (const GdkTextureDownloader *self);
GDK_AVAILABLE_IN_4_10
void gdk_texture_downloader_download_into (const GdkTextureDownloader *self,
guchar *data,
gsize stride);
GDK_AVAILABLE_IN_4_10
GBytes * gdk_texture_downloader_download_bytes (const GdkTextureDownloader *self,
gsize *out_stride);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkTextureDownloader, gdk_texture_downloader_free)
G_END_DECLS
#endif /* __GTK_TEXTURE_DOWNLOADER_H__ */
-41
View File
@@ -1,41 +0,0 @@
/* GTK - The GIMP Toolkit
*
* Copyright (C) 2023 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/>.
*/
#ifndef __GTK_TEXTURE_DOWNLOADER_PRIVATE_H__
#define __GTK_TEXTURE_DOWNLOADER_PRIVATE_H__
#include "gdktexturedownloader.h"
G_BEGIN_DECLS
struct _GdkTextureDownloader
{
/*< private >*/
GdkTexture *texture;
GdkMemoryFormat format;
};
void gdk_texture_downloader_init (GdkTextureDownloader *self,
GdkTexture *texture);
void gdk_texture_downloader_finish (GdkTextureDownloader *self);
G_END_DECLS
#endif /* __GTK_TEXTURE_DOWNLOADER_PRIVATE_H__ */
+1
View File
@@ -43,6 +43,7 @@ void gdk_texture_do_download (GdkTexture
GdkMemoryFormat format,
guchar *data,
gsize stride);
GdkMemoryFormat gdk_texture_get_format (GdkTexture *self);
gboolean gdk_texture_set_render_data (GdkTexture *self,
gpointer key,
gpointer data,
+5 -6
View File
@@ -261,16 +261,15 @@ gdk_toplevel_default_init (GdkToplevelInterface *iface)
/**
* GdkToplevel::compute-size:
* @toplevel: a `GdkToplevel`
* @size: (type Gdk.ToplevelSize): a `GdkToplevelSize`
* @size: (type Gdk.ToplevelSize) (out caller-allocates): a `GdkToplevelSize`
*
* Emitted when the size for the surface needs to be computed, when
* it is present.
*
* This signal will normally be emitted during or after a call to
* [method@Gdk.Toplevel.present], depending on the configuration
* received by the windowing system. It may also be emitted at any
* other point in time, in response to the windowing system
* spontaneously changing the configuration of the toplevel surface.
* It will normally be emitted during or after [method@Gdk.Toplevel.present],
* depending on the configuration received by the windowing system.
* It may also be emitted at any other point in time, in response
* to the windowing system spontaneously changing the configuration.
*
* It is the responsibility of the toplevel user to handle this signal
* and compute the desired size of the toplevel, given the information
-1
View File
@@ -77,7 +77,6 @@ typedef struct _GdkContentFormats GdkContentFormats;
typedef struct _GdkContentProvider GdkContentProvider;
typedef struct _GdkCursor GdkCursor;
typedef struct _GdkTexture GdkTexture;
typedef struct _GdkTextureDownloader GdkTextureDownloader;
typedef struct _GdkDevice GdkDevice;
typedef struct _GdkDrag GdkDrag;
typedef struct _GdkDrop GdkDrop;
+8 -10
View File
@@ -23,7 +23,7 @@
#include <glib/gi18n-lib.h>
#include "gdktexture.h"
#include "gdktexturedownloaderprivate.h"
#include "gdkmemorytextureprivate.h"
#include "gdkprofilerprivate.h"
@@ -251,8 +251,7 @@ gdk_save_jpeg (GdkTexture *texture)
guchar *data = NULL;
gulong size = 0;
guchar *input = NULL;
GdkTextureDownloader downloader;
GBytes *texbytes;
GdkMemoryTexture *memtex = NULL;
const guchar *texdata;
gsize texstride;
guchar *row;
@@ -271,7 +270,7 @@ gdk_save_jpeg (GdkTexture *texture)
free (data);
g_free (input);
jpeg_destroy_compress (&info);
g_clear_pointer (&texbytes, g_bytes_unref);
g_clear_object (&memtex);
return NULL;
}
@@ -290,11 +289,10 @@ gdk_save_jpeg (GdkTexture *texture)
jpeg_mem_dest (&info, &data, &size);
gdk_texture_downloader_init (&downloader, texture);
gdk_texture_downloader_set_format (&downloader, GDK_MEMORY_R8G8B8);
texbytes = gdk_texture_downloader_download_bytes (&downloader, &texstride);
gdk_texture_downloader_finish (&downloader);
texdata = g_bytes_get_data (texbytes, NULL);
memtex = gdk_memory_texture_from_texture (texture,
GDK_MEMORY_R8G8B8);
texdata = gdk_memory_texture_get_data (memtex);
texstride = gdk_memory_texture_get_stride (memtex);
jpeg_start_compress (&info, TRUE);
@@ -306,7 +304,7 @@ gdk_save_jpeg (GdkTexture *texture)
jpeg_finish_compress (&info);
g_bytes_unref (texbytes);
g_object_unref (memtex);
g_free (input);
jpeg_destroy_compress (&info);
+11 -13
View File
@@ -21,9 +21,10 @@
#include <glib/gi18n-lib.h>
#include "gdkmemoryformatprivate.h"
#include "gdkmemorytexture.h"
#include "gdkmemorytextureprivate.h"
#include "gdkprofilerprivate.h"
#include "gdktexturedownloaderprivate.h"
#include "gdktexture.h"
#include "gdktextureprivate.h"
#include "gsk/gl/fp16private.h"
#include <png.h>
#include <stdio.h>
@@ -296,12 +297,11 @@ gdk_save_png (GdkTexture *texture)
png_info *info;
png_io io = { NULL, 0, 0 };
int width, height;
int y;
GdkMemoryFormat format;
GdkTextureDownloader downloader;
GBytes *bytes;
gsize stride;
const guchar *data;
int y;
GdkMemoryTexture *memtex;
GdkMemoryFormat format;
int png_format;
int depth;
@@ -370,15 +370,11 @@ gdk_save_png (GdkTexture *texture)
return NULL;
}
gdk_texture_downloader_init (&downloader, texture);
gdk_texture_downloader_set_format (&downloader, format);
bytes = gdk_texture_downloader_download_bytes (&downloader, &stride);
gdk_texture_downloader_finish (&downloader);
data = g_bytes_get_data (bytes, NULL);
memtex = gdk_memory_texture_from_texture (texture, format);
if (sigsetjmp (png_jmpbuf (png), 1))
{
g_bytes_unref (bytes);
g_object_unref (memtex);
g_free (io.data);
png_destroy_read_struct (&png, &info, NULL);
return NULL;
@@ -398,6 +394,8 @@ gdk_save_png (GdkTexture *texture)
png_set_swap (png);
#endif
data = gdk_memory_texture_get_data (memtex);
stride = gdk_memory_texture_get_stride (memtex);
for (y = 0; y < height; y++)
png_write_row (png, data + y * stride);
@@ -405,7 +403,7 @@ gdk_save_png (GdkTexture *texture)
png_destroy_write_struct (&png, &info);
g_bytes_unref (bytes);
g_object_unref (memtex);
return g_bytes_new_take (io.data, io.size);
}
+11 -13
View File
@@ -21,9 +21,10 @@
#include <glib/gi18n-lib.h>
#include "gdkmemoryformatprivate.h"
#include "gdkmemorytexture.h"
#include "gdkmemorytextureprivate.h"
#include "gdkprofilerprivate.h"
#include "gdktexturedownloaderprivate.h"
#include "gdktexture.h"
#include "gdktextureprivate.h"
#include <tiffio.h>
@@ -259,12 +260,11 @@ GBytes *
gdk_save_tiff (GdkTexture *texture)
{
TIFF *tif;
int width, height;
gsize stride;
int width, height, stride;
const guchar *line;
const guchar *data;
GBytes *bytes, *result = NULL;
GdkTextureDownloader downloader;
GBytes *result = NULL;
GdkMemoryTexture *memtex;
GdkMemoryFormat format;
const FormatData *fdata = NULL;
@@ -292,11 +292,9 @@ gdk_save_tiff (GdkTexture *texture)
TIFFSetField (tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
TIFFSetField (tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
gdk_texture_downloader_init (&downloader, texture);
gdk_texture_downloader_set_format (&downloader, fdata->format);
bytes = gdk_texture_downloader_download_bytes (&downloader, &stride);
gdk_texture_downloader_finish (&downloader);
data = g_bytes_get_data (bytes, NULL);
memtex = gdk_memory_texture_from_texture (texture, fdata->format);
data = gdk_memory_texture_get_data (memtex);
stride = gdk_memory_texture_get_stride (memtex);
line = (const guchar *)data;
for (int y = 0; y < height; y++)
@@ -304,7 +302,7 @@ gdk_save_tiff (GdkTexture *texture)
if (TIFFWriteScanline (tif, (void *)line, y, 0) == -1)
{
TIFFClose (tif);
g_bytes_unref (bytes);
g_object_unref (memtex);
return NULL;
}
@@ -316,7 +314,7 @@ gdk_save_tiff (GdkTexture *texture)
g_assert (result);
g_bytes_unref (bytes);
g_object_unref (memtex);
return result;
}
+1 -3
View File
@@ -43,7 +43,6 @@ gdk_public_sources = files([
'gdkseatdefault.c',
'gdksnapshot.c',
'gdktexture.c',
'gdktexturedownloader.c',
'gdkvulkancontext.c',
'gdksurface.c',
'gdkpopuplayout.c',
@@ -96,7 +95,6 @@ gdk_public_headers = files([
'gdkseat.h',
'gdksnapshot.h',
'gdktexture.h',
'gdktexturedownloader.h',
'gdktypes.h',
'gdkvulkancontext.h',
'gdksurface.h',
@@ -131,7 +129,7 @@ gdk_gresource_xml = configure_file(output: 'gdk.gresource.xml',
gdkresources = gnome.compile_resources('gdkresources',
gdk_gresource_xml,
source_dir: meson.current_source_dir(),
source_dir: '.',
c_name: '_gdk',
extra_args: '--manual-register',
)
+14 -12
View File
@@ -207,7 +207,7 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
{
char *path;
XcursorImages *images;
struct wl_cursor *cursor;
struct cursor *cursor;
struct cursor_image *image;
int i, nbytes;
unsigned int load_size;
@@ -240,16 +240,17 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
return NULL;
}
cursor->images =
malloc(images->nimage * sizeof cursor->images[0]);
if (!cursor->images) {
cursor->cursor.images =
malloc(images->nimage * sizeof cursor->cursor.images[0]);
if (!cursor->cursor.images) {
free(cursor);
xcursor_images_destroy (images);
return NULL;
}
cursor->name = strdup(name);
cursor->size = load_size;
cursor->cursor.name = strdup(name);
cursor->cursor.size = load_size;
cursor->total_delay = 0;
for (i = 0; i < images->nimage; i++) {
image = malloc(sizeof *image);
@@ -290,13 +291,14 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
}
}
}
cursor->images[i] = (struct wl_cursor_image *) image;
cursor->total_delay += image->image.delay;
cursor->cursor.images[i] = (struct wl_cursor_image *) image;
}
cursor->image_count = i;
cursor->cursor.image_count = i;
if (cursor->image_count == 0) {
free(cursor->name);
free(cursor->images);
if (cursor->cursor.image_count == 0) {
free(cursor->cursor.name);
free(cursor->cursor.images);
free(cursor);
xcursor_images_destroy (images);
return NULL;
@@ -304,7 +306,7 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
xcursor_images_destroy (images);
return cursor;
return &cursor->cursor;
}
static void
+7 -3
View File
@@ -586,6 +586,13 @@ _gdk_wayland_display_open (const char *display_name)
GDK_DEBUG (MISC, "opening display %s", display_name ? display_name : "");
/* If this variable is unset then wayland initialisation will surely
* fail, logging a fatal error in the process. Save ourselves from
* that.
*/
if (g_getenv ("XDG_RUNTIME_DIR") == NULL)
return NULL;
wl_log_set_handler_client (log_handler);
wl_display = wl_display_connect (display_name);
@@ -1075,9 +1082,6 @@ gdk_wayland_display_set_cursor_theme (GdkDisplay *display,
g_assert (display_wayland);
g_assert (display_wayland->shm);
if (size == 0)
size = 24;
if (g_strcmp0 (name, display_wayland->cursor_theme_name) == 0 &&
display_wayland->cursor_theme_size == size)
return;
+1 -12
View File
@@ -25,7 +25,6 @@
#include "gdkdisplay-wayland.h"
#include "gdksurface-wayland.h"
#include "gdksurface-wayland-private.h"
#include "gdkwaylanddisplay.h"
#include "gdkwaylandglcontext.h"
@@ -61,20 +60,10 @@ gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
cairo_region_t *painted)
{
GdkSurface *surface = gdk_draw_context_get_surface (draw_context);
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
int dx = impl->pending_buffer_offset_x;
int dy = impl->pending_buffer_offset_y;
impl->pending_buffer_offset_x = 0;
impl->pending_buffer_offset_y = 0;
gdk_wayland_surface_sync (surface);
gdk_wayland_surface_request_frame (surface);
if (wl_surface_get_version (impl->display_server.wl_surface) >=
WL_SURFACE_OFFSET_SINCE_VERSION)
wl_surface_offset (impl->display_server.wl_surface, dx, dy);
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->end_frame (draw_context, painted);
gdk_wayland_surface_notify_committed (surface);
@@ -121,7 +110,7 @@ gdk_wayland_display_init_gl (GdkDisplay *display,
{
GdkWaylandDisplay *self = GDK_WAYLAND_DISPLAY (display);
if (!gdk_display_init_egl (display,
if (!gdk_display_init_egl (display,
EGL_PLATFORM_WAYLAND_EXT,
self->wl_display,
TRUE,
+17 -34
View File
@@ -398,11 +398,7 @@ gdk_wayland_popup_handle_configure (GdkWaylandSurface *wayland_surface)
g_warn_if_reached ();
if (wayland_popup->pending.has_repositioned_token)
{
wayland_popup->received_reposition_token =
wayland_popup->pending.repositioned_token;
wayland_popup->pending.has_repositioned_token = FALSE;
}
wayland_popup->received_reposition_token = wayland_popup->pending.repositioned_token;
switch (wayland_popup->state)
{
@@ -747,7 +743,9 @@ create_dynamic_positioner (GdkWaylandPopup *wayland_popup,
GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
GdkRectangle geometry;
uint32_t constraint_adjustment = ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE;
GdkRectangle anchor_rect;
const GdkRectangle *anchor_rect;
int real_anchor_rect_x, real_anchor_rect_y;
int anchor_rect_width, anchor_rect_height;
int rect_anchor_dx;
int rect_anchor_dy;
GdkGravity rect_anchor;
@@ -773,24 +771,12 @@ create_dynamic_positioner (GdkWaylandPopup *wayland_popup,
gdk_wayland_surface_get_window_geometry (surface->parent, &parent_geometry);
anchor_rect = *gdk_popup_layout_get_anchor_rect (layout);
anchor_rect = gdk_popup_layout_get_anchor_rect (layout);
real_anchor_rect_x = anchor_rect->x - parent_geometry.x;
real_anchor_rect_y = anchor_rect->y - parent_geometry.y;
/* Wayland protocol requires that the anchor rect is specified
* wrt. to the parent geometry, and that it is non-empty and
* contained in the parent geometry.
*/
if (!gdk_rectangle_intersect (&parent_geometry, &anchor_rect, &anchor_rect))
{
anchor_rect.x = 0;
anchor_rect.y = 0;
anchor_rect.width = 1;
anchor_rect.height = 1;
}
else
{
anchor_rect.x -= parent_geometry.x;
anchor_rect.y -= parent_geometry.y;
}
anchor_rect_width = MAX (anchor_rect->width, 1);
anchor_rect_height = MAX (anchor_rect->height, 1);
gdk_popup_layout_get_offset (layout, &rect_anchor_dx, &rect_anchor_dy);
@@ -811,10 +797,10 @@ create_dynamic_positioner (GdkWaylandPopup *wayland_popup,
xdg_positioner_set_size (positioner, geometry.width, geometry.height);
xdg_positioner_set_anchor_rect (positioner,
anchor_rect.x,
anchor_rect.y,
anchor_rect.width,
anchor_rect.height);
real_anchor_rect_x,
real_anchor_rect_y,
anchor_rect_width,
anchor_rect_height);
xdg_positioner_set_offset (positioner, rect_anchor_dx, rect_anchor_dy);
anchor = rect_anchor_to_anchor (rect_anchor);
@@ -865,10 +851,10 @@ create_dynamic_positioner (GdkWaylandPopup *wayland_popup,
zxdg_positioner_v6_set_size (positioner, geometry.width, geometry.height);
zxdg_positioner_v6_set_anchor_rect (positioner,
anchor_rect.x,
anchor_rect.y,
anchor_rect.width,
anchor_rect.height);
real_anchor_rect_x,
real_anchor_rect_y,
anchor_rect_width,
anchor_rect_height);
zxdg_positioner_v6_set_offset (positioner,
rect_anchor_dx,
rect_anchor_dy);
@@ -982,9 +968,6 @@ gdk_wayland_surface_create_xdg_popup (GdkWaylandPopup *wayland_popup,
g_assert_not_reached ();
}
wayland_popup->received_reposition_token = 0;
wayland_popup->reposition_token = 0;
gdk_popup_layout_get_shadow_width (layout,
&impl->shadow_left,
&impl->shadow_right,
+4 -11
View File
@@ -99,7 +99,7 @@ gdk_wayland_primary_claim_remote (GdkWaylandPrimary *cb,
if (cb->source)
{
GDK_DISPLAY_DEBUG (gdk_clipboard_get_display (GDK_CLIPBOARD (cb)), CLIPBOARD, "%p: Ignoring primary offer for self", cb);
GDK_DISPLAY_DEBUG (gdk_clipboard_get_display (GDK_CLIPBOARD (cb)), CLIPBOARD, "%p: Ignoring clipboard offer for self", cb);
gdk_content_formats_unref (formats);
g_clear_pointer (&offer, zwp_primary_selection_offer_v1_destroy);
return;
@@ -111,7 +111,7 @@ gdk_wayland_primary_claim_remote (GdkWaylandPrimary *cb,
if (GDK_DISPLAY_DEBUG_CHECK (gdk_clipboard_get_display (GDK_CLIPBOARD (cb)), CLIPBOARD))
{
char *s = gdk_content_formats_to_string (formats);
gdk_debug_message ("%p: remote primary claim for %s", cb, s);
gdk_debug_message ("%p: remote clipboard claim for %s", cb, s);
g_free (s);
}
#endif
@@ -119,7 +119,8 @@ gdk_wayland_primary_claim_remote (GdkWaylandPrimary *cb,
cb->offer_formats = formats;
cb->offer = offer;
gdk_clipboard_claim_remote (GDK_CLIPBOARD (cb), cb->offer_formats);
gdk_clipboard_claim_remote (GDK_CLIPBOARD (cb),
cb->offer_formats);
}
static void
@@ -270,14 +271,6 @@ gdk_wayland_primary_claim (GdkClipboard *clipboard,
{
GdkWaylandPrimary *cb = GDK_WAYLAND_PRIMARY (clipboard);
#ifdef G_ENABLE_DEBUG
if (GDK_DISPLAY_DEBUG_CHECK (gdk_clipboard_get_display (clipboard), CLIPBOARD))
{
char *s = gdk_content_formats_to_string (formats);
gdk_debug_message ("%p: claim primary (%s) for %s", cb, local ? "local" : "remote", s);
g_free (s);
}
#endif
if (local)
{
GdkWaylandDisplay *wdisplay = GDK_WAYLAND_DISPLAY (gdk_clipboard_get_display (clipboard));
+36 -19
View File
@@ -229,7 +229,7 @@ gdk_wayland_surface_update_size (GdkSurface *surface,
if (impl->display_server.egl_window)
wl_egl_window_resize (impl->display_server.egl_window, width * scale, height * scale, 0, 0);
if (impl->display_server.wl_surface && scale_changed)
if (impl->display_server.wl_surface)
wl_surface_set_buffer_scale (impl->display_server.wl_surface, scale);
gdk_surface_invalidate_rect (surface, NULL);
@@ -520,6 +520,8 @@ _gdk_wayland_display_create_surface (GdkDisplay *display,
surface->width = width;
surface->height = height;
g_object_ref (surface);
/* More likely to be right than just assuming 1 */
if (display_wayland->compositor_version >= WL_SURFACE_HAS_BUFFER_SCALE)
{
@@ -559,14 +561,8 @@ gdk_wayland_surface_attach_image (GdkSurface *surface,
/* Attach this new buffer to the surface */
wl_surface_attach (impl->display_server.wl_surface,
_gdk_wayland_shm_surface_get_wl_buffer (cairo_surface),
0, 0);
if ((impl->pending_buffer_offset_x || impl->pending_buffer_offset_y) &&
wl_surface_get_version (impl->display_server.wl_surface) >=
WL_SURFACE_OFFSET_SINCE_VERSION)
wl_surface_offset (impl->display_server.wl_surface,
impl->pending_buffer_offset_x,
impl->pending_buffer_offset_y);
impl->pending_buffer_offset_x,
impl->pending_buffer_offset_y);
impl->pending_buffer_offset_x = 0;
impl->pending_buffer_offset_y = 0;
@@ -583,12 +579,33 @@ gdk_wayland_surface_attach_image (GdkSurface *surface,
}
}
static void
gdk_wayland_surface_sync_offset (GdkSurface *surface)
{
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
if (wl_surface_get_version (impl->display_server.wl_surface) <
WL_SURFACE_OFFSET_SINCE_VERSION)
return;
if (impl->pending_buffer_offset_x == 0 &&
impl->pending_buffer_offset_y == 0)
return;
wl_surface_offset (impl->display_server.wl_surface,
impl->pending_buffer_offset_x,
impl->pending_buffer_offset_y);
impl->pending_buffer_offset_x = 0;
impl->pending_buffer_offset_y = 0;
}
void
gdk_wayland_surface_sync (GdkSurface *surface)
{
gdk_wayland_surface_sync_shadow (surface);
gdk_wayland_surface_sync_opaque_region (surface);
gdk_wayland_surface_sync_input_region (surface);
gdk_wayland_surface_sync_offset (surface);
}
static gboolean
@@ -630,7 +647,7 @@ gdk_wayland_surface_dispose (GObject *object)
GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
display_wayland->event_queues =
g_list_remove (display_wayland->event_queues, impl->event_queue);
g_list_remove (display_wayland->event_queues, surface);
g_clear_pointer (&impl->event_queue, wl_event_queue_destroy);
}
@@ -975,15 +992,6 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
impl->display_server.egl_window = NULL;
}
impl->awaiting_frame = FALSE;
if (impl->awaiting_frame_frozen)
{
impl->awaiting_frame_frozen = FALSE;
gdk_surface_thaw_updates (surface);
}
GDK_WAYLAND_SURFACE_GET_CLASS (impl)->hide_surface (impl);
if (impl->display_server.xdg_surface)
{
xdg_surface_destroy (impl->display_server.xdg_surface);
@@ -1002,6 +1010,15 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
impl->initial_configure_received = FALSE;
}
impl->awaiting_frame = FALSE;
if (impl->awaiting_frame_frozen)
{
impl->awaiting_frame_frozen = FALSE;
gdk_surface_thaw_updates (surface);
}
GDK_WAYLAND_SURFACE_GET_CLASS (impl)->hide_surface (impl);
g_clear_pointer (&impl->display_server.wl_surface, wl_surface_destroy);
g_slist_free (impl->display_server.outputs);
+1 -1
View File
@@ -991,7 +991,7 @@ gdk_wayland_toplevel_set_startup_id (GdkWaylandToplevel *toplevel,
startup_id = free_me;
}
if (display->xdg_activation && startup_id)
if (startup_id)
xdg_activation_v1_activate (display->xdg_activation,
startup_id,
surface->display_server.wl_surface);
+4 -5
View File
@@ -1005,8 +1005,7 @@ gdk_win32_icon_to_pixbuf_libgtk_only (HICON hicon,
} bmi;
HDC hdc;
uint8_t *pixels, *bits;
int x, y, w, h;
gsize rowstride;
int rowstride, x, y, w, h;
if (!GDI_CALL (GetIconInfo, (hicon, &ii)))
return NULL;
@@ -1058,7 +1057,7 @@ gdk_win32_icon_to_pixbuf_libgtk_only (HICON hicon,
no_alpha = FALSE;
pixels += 4;
}
pixels += rowstride - w * 4;
pixels += (w * 4 - rowstride);
}
/* mask */
@@ -1073,7 +1072,7 @@ gdk_win32_icon_to_pixbuf_libgtk_only (HICON hicon,
pixels[3] = 255 - bits[(x + y * w) * 4];
pixels += 4;
}
pixels += rowstride - w * 4;
pixels += (w * 4 - rowstride);
}
}
}
@@ -1147,7 +1146,7 @@ gdk_win32_icon_to_pixbuf_libgtk_only (HICON hicon,
xorp++;
}
}
pixels += rowstride - w * 4;
pixels += (w * 4 - rowstride);
}
}
-1
View File
@@ -1207,7 +1207,6 @@ gdk_win32_display_init_gl (GdkDisplay *display,
{
return g_object_new (GDK_TYPE_WIN32_GL_CONTEXT_EGL,
"display", display,
"allowed-apis", GDK_GL_API_GLES,
NULL);
}
else
+7
View File
@@ -83,13 +83,20 @@ gdk_win32_gl_context_egl_end_frame (GdkDrawContext *draw_context,
cairo_region_t *painted)
{
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
GdkWin32GLContextEGL *context_egl = GDK_WIN32_GL_CONTEXT_EGL (context);
GdkSurface *surface = gdk_gl_context_get_surface (context);
GdkDisplay *display = gdk_gl_context_get_display (context);
cairo_rectangle_int_t whole_window;
EGLSurface egl_surface;
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_egl_parent_class)->end_frame (draw_context, painted);
gdk_gl_context_make_current (context);
whole_window =
(GdkRectangle) { 0, 0,
gdk_surface_get_width (surface),
gdk_surface_get_height (surface)
};
egl_surface = gdk_surface_get_egl_surface (surface);
@@ -1,56 +0,0 @@
/* GDK - The GIMP Drawing Kit
*
* gdkglcontext-win32-wgl-private.c: Win32 specific OpenGL wrappers
*
* Copyright © 2023 Chun-wei Fan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* These wrapper functions are used when we don't want to use the wgl*() core functions
* that we acquire via libepoxy (such as when we are disposing the Gdk(W)GLContext from,
* different threads, so for these calls, we are actually linking to the system's/ICD
* opengl32.dll directly, so that we are guaranteed that the "right" versions of these
* WGL calls are carried out. This must be a separate source file because we can't include
* the system's GL/gl.h with epoxy/(w)gl.h together in a single source file. We should not
* need to use these when we are creating/initializing a WGL context in GDK, since we should
* be in the same thread at this point.
*/
#define DONT_INCLUDE_LIBEPOXY
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <GL/gl.h>
#include "gdkglcontext-win32.h"
void
gdk_win32_private_wglDeleteContext (HGLRC hglrc)
{
wglDeleteContext (hglrc);
}
HGLRC
gdk_win32_private_wglGetCurrentContext (void)
{
return wglGetCurrentContext ();
}
BOOL
gdk_win32_private_wglMakeCurrent (HDC hdc,
HGLRC hglrc)
{
return wglMakeCurrent (hdc, hglrc);
}
+6 -6
View File
@@ -60,12 +60,12 @@ gdk_win32_gl_context_wgl_dispose (GObject *gobject)
if (context_wgl->wgl_context != NULL)
{
if (gdk_win32_private_wglGetCurrentContext () == context_wgl->wgl_context)
gdk_win32_private_wglMakeCurrent (NULL, NULL);
if (wglGetCurrentContext () == context_wgl->wgl_context)
wglMakeCurrent (NULL, NULL);
GDK_NOTE (OPENGL, g_print ("Destroying WGL context\n"));
gdk_win32_private_wglDeleteContext (context_wgl->wgl_context);
wglDeleteContext (context_wgl->wgl_context);
context_wgl->wgl_context = NULL;
}
@@ -628,7 +628,7 @@ gdk_win32_gl_context_wgl_realize (GdkGLContext *context,
static gboolean
gdk_win32_gl_context_wgl_clear_current (GdkGLContext *context)
{
return gdk_win32_private_wglMakeCurrent (NULL, NULL);
return wglMakeCurrent (NULL, NULL);
}
static gboolean
@@ -636,7 +636,7 @@ gdk_win32_gl_context_wgl_is_current (GdkGLContext *context)
{
GdkWin32GLContextWGL *self = GDK_WIN32_GL_CONTEXT_WGL (context);
return self->wgl_context == gdk_win32_private_wglGetCurrentContext ();
return self->wgl_context == wglGetCurrentContext ();
}
static gboolean
@@ -654,7 +654,7 @@ gdk_win32_gl_context_wgl_make_current (GdkGLContext *context,
else
hdc = GDK_WIN32_SURFACE (surface)->hdc;
if (!gdk_win32_private_wglMakeCurrent (hdc, context_wgl->wgl_context))
if (!wglMakeCurrent (hdc, context_wgl->wgl_context))
return FALSE;
if (!surfaceless && display_win32->hasWglEXTSwapControl)
-17
View File
@@ -21,7 +21,6 @@
#ifndef __GDK_WIN32_GL_CONTEXT__
#define __GDK_WIN32_GL_CONTEXT__
#ifndef DONT_INCLUDE_LIBEPOXY
#include <epoxy/gl.h>
#include <epoxy/wgl.h>
@@ -32,18 +31,9 @@
#include "gdkglcontextprivate.h"
#include "gdkdisplayprivate.h"
#include "gdksurface.h"
#else
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <GL/gl.h>
# include <glib.h>
#endif
G_BEGIN_DECLS
#ifndef DONT_INCLUDE_LIBEPOXY
#define GDK_WIN32_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WIN32_GL_CONTEXT, GdkWin32GLContextClass))
#define GDK_WIN32_GL_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WIN32_GL_CONTEXT, GdkWin32GLContextClass))
#define GDK_WIN32_IS_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WIN32_GL_CONTEXT))
@@ -88,13 +78,6 @@ GType gdk_win32_gl_context_egl_get_type (void) G_GNUC_CONST;
void
_gdk_win32_surface_invalidate_egl_framebuffer (GdkSurface *surface);
#endif /* !DONT_INCLUDE_LIBEPOXY */
HGLRC gdk_win32_private_wglGetCurrentContext (void);
BOOL gdk_win32_private_wglMakeCurrent (HDC hdc,
HGLRC hglrc);
void gdk_win32_private_wglDeleteContext (HGLRC hglrc);
G_END_DECLS
#endif /* __GDK_WIN32_GL_CONTEXT__ */
+3 -6
View File
@@ -443,6 +443,9 @@ populate_monitor_devices_from_display_config (GPtrArray *monitors)
char *path, *path_lower;
DISPLAYCONFIG_RATIONAL *refresh;
if ((dispconf_paths[path_index].flags & DISPLAYCONFIG_PATH_ACTIVE) == 0)
continue;
tdn.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
tdn.header.size = sizeof (tdn);
tdn.header.adapterId = dispconf_paths[path_index].targetInfo.adapterId;
@@ -478,12 +481,6 @@ populate_monitor_devices_from_display_config (GPtrArray *monitors)
if (w32mon == NULL)
continue;
if ((dispconf_paths[path_index].flags & DISPLAYCONFIG_PATH_ACTIVE) == 0)
{
w32mon->remove = TRUE;
continue;
}
mon = GDK_MONITOR (w32mon);
if (!tdn.flags.friendlyNameForced)
-2
View File
@@ -23,7 +23,6 @@ gdk_win32_sources = gdk_win32_public_sources + files([
'gdkdevice-wintab.c',
'gdkdrop-win32.c',
'gdkglobals-win32.c',
'gdkglcontext-win32-wgl-private.c',
'gdkhdataoutputstream-win32.c',
'gdkinput-dmanipulation.c',
'gdkinput-winpointer.c',
@@ -60,7 +59,6 @@ endif
gdk_win32_deps = [
pangowin32_dep, # FIXME
cc.find_library('hid'),
cc.find_library('opengl32'),
]
libgdk_win32 = static_library('gdk-win32',
+1 -2
View File
@@ -145,8 +145,7 @@ struct _GdkX11Display
guint server_time_is_monotonic_time : 1;
/* GLX extensions we check */
guint has_glx_sgi_swap_control : 1;
guint has_glx_swap_control : 1;
guint has_glx_swap_interval : 1;
guint has_glx_create_context : 1;
guint has_glx_texture_from_pixmap : 1;
guint has_glx_video_sync : 1;
+203
View File
@@ -134,6 +134,35 @@ struct _GdkX11DragClass
GdkDragClass parent_class;
};
typedef struct {
int keysym;
int modifiers;
} GrabKey;
static GrabKey grab_keys[] = {
{ XK_Escape, 0 },
{ XK_space, 0 },
{ XK_KP_Space, 0 },
{ XK_Return, 0 },
{ XK_KP_Enter, 0 },
{ XK_Up, 0 },
{ XK_Up, Mod1Mask },
{ XK_Down, 0 },
{ XK_Down, Mod1Mask },
{ XK_Left, 0 },
{ XK_Left, Mod1Mask },
{ XK_Right, 0 },
{ XK_Right, Mod1Mask },
{ XK_KP_Up, 0 },
{ XK_KP_Up, Mod1Mask },
{ XK_KP_Down, 0 },
{ XK_KP_Down, Mod1Mask },
{ XK_KP_Left, 0 },
{ XK_KP_Left, Mod1Mask },
{ XK_KP_Right, 0 },
{ XK_KP_Right, Mod1Mask }
};
/* Forward declarations */
static GdkSurfaceCache *gdk_surface_cache_ref (GdkSurfaceCache *cache);
@@ -1870,12 +1899,17 @@ drag_grab (GdkDrag *drag)
{
GdkX11Drag *x11_drag = GDK_X11_DRAG (drag);
GdkSeatCapabilities capabilities;
GdkDisplay *display;
Window root;
GdkSeat *seat;
int keycode, i;
GdkCursor *cursor;
if (!x11_drag->ipc_surface)
return FALSE;
display = gdk_drag_get_display (drag);
root = GDK_DISPLAY_XROOTWIN (display);
seat = gdk_device_get_seat (gdk_drag_get_device (drag));
capabilities = GDK_SEAT_CAPABILITY_ALL_POINTING;
@@ -1890,6 +1924,46 @@ drag_grab (GdkDrag *drag)
g_set_object (&x11_drag->grab_seat, seat);
gdk_x11_display_error_trap_push (display);
for (i = 0; i < G_N_ELEMENTS (grab_keys); ++i)
{
int deviceid = gdk_x11_device_get_id (gdk_seat_get_keyboard (seat));
unsigned char mask[XIMaskLen(XI_LASTEVENT)];
XIGrabModifiers mods;
XIEventMask evmask;
int num_mods;
keycode = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (display),
grab_keys[i].keysym);
if (keycode == NoSymbol)
continue;
memset (mask, 0, sizeof (mask));
XISetMask (mask, XI_KeyPress);
XISetMask (mask, XI_KeyRelease);
evmask.deviceid = deviceid;
evmask.mask_len = sizeof (mask);
evmask.mask = mask;
num_mods = 1;
mods.modifiers = grab_keys[i].modifiers;
XIGrabKeycode (GDK_DISPLAY_XDISPLAY (display),
deviceid,
keycode,
root,
GrabModeAsync,
GrabModeAsync,
False,
&evmask,
num_mods,
&mods);
}
gdk_x11_display_error_trap_pop_ignored (display);
return TRUE;
}
@@ -1897,13 +1971,41 @@ static void
drag_ungrab (GdkDrag *drag)
{
GdkX11Drag *x11_drag = GDK_X11_DRAG (drag);
GdkDisplay *display;
GdkDevice *keyboard;
Window root;
int keycode, i;
if (!x11_drag->grab_seat)
return;
gdk_seat_ungrab (x11_drag->grab_seat);
display = gdk_drag_get_display (drag);
keyboard = gdk_seat_get_keyboard (x11_drag->grab_seat);
root = GDK_DISPLAY_XROOTWIN (display);
g_clear_object (&x11_drag->grab_seat);
for (i = 0; i < G_N_ELEMENTS (grab_keys); ++i)
{
XIGrabModifiers mods;
int num_mods;
keycode = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (display),
grab_keys[i].keysym);
if (keycode == NoSymbol)
continue;
num_mods = 1;
mods.modifiers = grab_keys[i].modifiers;
XIUngrabKeycode (GDK_DISPLAY_XDISPLAY (display),
gdk_x11_device_get_id (keyboard),
keycode,
root,
num_mods,
&mods);
}
}
GdkDrag *
@@ -2130,6 +2232,103 @@ gdk_dnd_handle_motion_event (GdkDrag *drag,
return TRUE;
}
static gboolean
gdk_dnd_handle_key_event (GdkDrag *drag,
GdkEvent *event)
{
GdkX11Drag *x11_drag = GDK_X11_DRAG (drag);
GdkModifierType state;
GdkDevice *pointer;
GdkSeat *seat;
int dx, dy;
dx = dy = 0;
state = gdk_event_get_modifier_state (event);
seat = gdk_event_get_seat (event);
pointer = gdk_seat_get_pointer (seat);
if (event->event_type == GDK_KEY_PRESS)
{
guint keyval = gdk_key_event_get_keyval (event);
switch (keyval)
{
case GDK_KEY_Escape:
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_USER_CANCELLED);
return TRUE;
case GDK_KEY_space:
case GDK_KEY_Return:
case GDK_KEY_ISO_Enter:
case GDK_KEY_KP_Enter:
case GDK_KEY_KP_Space:
if ((gdk_drag_get_selected_action (drag) != 0) &&
(x11_drag->proxy_xid != None))
{
g_signal_emit_by_name (drag, "drop-performed");
}
else
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_NO_TARGET);
return TRUE;
case GDK_KEY_Up:
case GDK_KEY_KP_Up:
dy = (state & GDK_ALT_MASK) ? -BIG_STEP : -SMALL_STEP;
break;
case GDK_KEY_Down:
case GDK_KEY_KP_Down:
dy = (state & GDK_ALT_MASK) ? BIG_STEP : SMALL_STEP;
break;
case GDK_KEY_Left:
case GDK_KEY_KP_Left:
dx = (state & GDK_ALT_MASK) ? -BIG_STEP : -SMALL_STEP;
break;
case GDK_KEY_Right:
case GDK_KEY_KP_Right:
dx = (state & GDK_ALT_MASK) ? BIG_STEP : SMALL_STEP;
break;
default:
break;
}
}
/* The state is not yet updated in the event, so we need
* to query it here. We could use XGetModifierMapping, but
* that would be overkill.
*/
gdk_x11_device_xi2_query_state (pointer, NULL, NULL, NULL, &state);
if (dx != 0 || dy != 0)
{
GdkDisplay *display;
Display *xdisplay;
GdkX11Screen *screen;
Window dest;
x11_drag->last_x += dx;
x11_drag->last_y += dy;
display = gdk_event_get_display ((GdkEvent *)event);
xdisplay = GDK_DISPLAY_XDISPLAY (display);
screen = GDK_X11_DISPLAY (display)->screen;
dest = GDK_SCREEN_XROOTWIN (screen);
XWarpPointer (xdisplay, None, dest, 0, 0, 0, 0,
round (x11_drag->last_x * screen->surface_scale),
round (x11_drag->last_y * screen->surface_scale));
}
gdk_drag_update (drag, x11_drag->last_x, x11_drag->last_y, state,
gdk_event_get_time (event));
return TRUE;
}
static gboolean
gdk_dnd_handle_grab_broken_event (GdkDrag *drag,
GdkEvent *event)
@@ -2196,6 +2395,10 @@ gdk_x11_drag_handle_event (GdkDrag *drag,
case GDK_BUTTON_RELEASE:
return gdk_dnd_handle_button_event (drag, event);
case GDK_KEY_PRESS:
case GDK_KEY_RELEASE:
return gdk_dnd_handle_key_event (drag, event);
case GDK_GRAB_BROKEN:
return gdk_dnd_handle_grab_broken_event (drag, event);
+11 -36
View File
@@ -162,7 +162,7 @@ gdk_x11_gl_context_glx_end_frame (GdkDrawContext *draw_context,
if (display_x11->has_glx_video_sync)
glXGetVideoSyncSGI (&end_frame_counter);
if (self->do_frame_sync && !display_x11->has_glx_sgi_swap_control && !display_x11->has_glx_swap_control)
if (self->do_frame_sync && !display_x11->has_glx_swap_interval)
{
glFinish ();
@@ -249,7 +249,7 @@ gdk_x11_gl_context_glx_make_current (GdkGLContext *context,
if (!glXMakeContextCurrent (dpy, drawable, drawable, self->glx_context))
return FALSE;
if (!surfaceless)
if (!surfaceless && GDK_X11_DISPLAY (display)->has_glx_swap_interval)
{
/* If the WM is compositing there is no particular need to delay
* the swap when drawing on the offscreen, rendering to the screen
@@ -257,35 +257,14 @@ gdk_x11_gl_context_glx_make_current (GdkGLContext *context,
* to the vblank. */
do_frame_sync = ! gdk_display_is_composited (display);
if (GDK_X11_DISPLAY (display)->has_glx_swap_control)
if (do_frame_sync != self->do_frame_sync)
{
if (do_frame_sync != self->do_frame_sync)
{
self->do_frame_sync = do_frame_sync;
self->do_frame_sync = do_frame_sync;
if (do_frame_sync)
glXSwapIntervalEXT (dpy, drawable, 1);
else
glXSwapIntervalEXT (dpy, drawable, 0);
}
}
else if (GDK_X11_DISPLAY (display)->has_glx_sgi_swap_control)
{
/* If the WM is compositing there is no particular need to delay
* the swap when drawing on the offscreen, rendering to the screen
* happens later anyway, and its up to the compositor to sync that
* to the vblank. */
do_frame_sync = ! gdk_display_is_composited (display);
if (do_frame_sync != self->do_frame_sync)
{
self->do_frame_sync = do_frame_sync;
if (do_frame_sync)
glXSwapIntervalSGI (1);
else
glXSwapIntervalSGI (0);
}
if (do_frame_sync)
glXSwapIntervalSGI (1);
else
glXSwapIntervalSGI (0);
}
}
@@ -509,7 +488,7 @@ gdk_x11_context_create_glx_context (GdkGLContext *context,
/* We will use the default version matching the context status
* unless the user requested a version which makes sense */
gdk_gl_context_get_matching_version (api, legacy,
gdk_gl_context_get_matching_version (api, legacy, 0,
&min_major, &min_minor);
gdk_gl_context_get_clipped_version (context, min_major, min_minor,
&major, &minor);
@@ -946,10 +925,8 @@ gdk_x11_display_init_glx (GdkX11Display *display_x11,
epoxy_has_glx_extension (dpy, screen_num, "GLX_ARB_create_context_profile");
display_x11->has_glx_create_es2_context =
epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_create_context_es2_profile");
display_x11->has_glx_sgi_swap_control =
display_x11->has_glx_swap_interval =
epoxy_has_glx_extension (dpy, screen_num, "GLX_SGI_swap_control");
display_x11->has_glx_swap_control =
epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_swap_control");
display_x11->has_glx_texture_from_pixmap =
epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_texture_from_pixmap");
display_x11->has_glx_video_sync =
@@ -1010,7 +987,6 @@ gdk_x11_display_init_glx (GdkX11Display *display_x11,
"\t* GLX_ARB_create_context_profile: %s\n"
"\t* GLX_EXT_create_context_es2_profile: %s\n"
"\t* GLX_SGI_swap_control: %s\n"
"\t* GLX_EXT_swap_control: %s\n"
"\t* GLX_EXT_texture_from_pixmap: %s\n"
"\t* GLX_SGI_video_sync: %s\n"
"\t* GLX_EXT_buffer_age: %s\n"
@@ -1022,8 +998,7 @@ gdk_x11_display_init_glx (GdkX11Display *display_x11,
glXGetClientString (dpy, GLX_VENDOR),
display_x11->has_glx_create_context ? "yes" : "no",
display_x11->has_glx_create_es2_context ? "yes" : "no",
display_x11->has_glx_sgi_swap_control ? "yes" : "no",
display_x11->has_glx_swap_control ? "yes" : "no",
display_x11->has_glx_swap_interval ? "yes" : "no",
display_x11->has_glx_texture_from_pixmap ? "yes" : "no",
display_x11->has_glx_video_sync ? "yes" : "no",
display_x11->has_glx_buffer_age ? "yes" : "no",
+3 -19
View File
@@ -685,13 +685,8 @@ init_randr13 (GdkX11Screen *x11_screen)
for (i = 0; i < resources->noutput; ++i)
{
RROutput output = resources->outputs[i];
XRROutputInfo *output_info;
gdk_x11_display_error_trap_push (display);
output_info = XRRGetOutputInfo (x11_screen->xdisplay, resources, output);
if (gdk_x11_display_error_trap_pop (display))
continue;
XRROutputInfo *output_info =
XRRGetOutputInfo (x11_screen->xdisplay, resources, output);
if (output_info->connection == RR_Disconnected)
{
@@ -702,22 +697,13 @@ init_randr13 (GdkX11Screen *x11_screen)
if (output_info->crtc)
{
GdkX11Monitor *monitor;
XRRCrtcInfo *crtc;
XRRCrtcInfo *crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc);
char *name;
GdkRectangle geometry;
GdkRectangle newgeo;
int j;
int refresh_rate = 0;
gdk_x11_display_error_trap_push (display);
crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc);
if (gdk_x11_display_error_trap_pop (display))
{
XRRFreeOutputInfo (output_info);
continue;
}
for (j = 0; j < resources->nmode; j++)
{
XRRModeInfo *xmode = &resources->modes[j];
@@ -789,10 +775,8 @@ init_randr13 (GdkX11Screen *x11_screen)
}
x11_display->primary_monitor = 0;
gdk_x11_display_error_trap_push (display);
primary_output = XRRGetOutputPrimary (x11_screen->xdisplay,
x11_screen->xroot_window);
gdk_x11_display_error_trap_pop_ignored (display);
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (x11_display->monitors)); i++)
{
+12 -12
View File
@@ -89,7 +89,7 @@ gdk_x11_selection_input_stream_fill_buffer (GdkX11SelectionInputStream *stream,
if (size == 0)
{
/* EOF marker, put it back */
g_async_queue_push_front_unlocked (priv->chunks, g_steal_pointer (&bytes));
g_async_queue_push_front_unlocked (priv->chunks, bytes);
break;
}
else if (size > count)
@@ -107,7 +107,7 @@ gdk_x11_selection_input_stream_fill_buffer (GdkX11SelectionInputStream *stream,
memcpy (buffer, g_bytes_get_data (bytes, NULL), size);
}
g_bytes_unref (g_steal_pointer (&bytes));
g_bytes_unref (bytes);
result += size;
if (buffer)
buffer += size;
@@ -165,7 +165,9 @@ gdk_x11_selection_input_stream_complete (GdkX11SelectionInputStream *stream)
GDK_X11_DISPLAY (priv->display)->streams = g_slist_remove (GDK_X11_DISPLAY (priv->display)->streams, stream);
g_signal_handlers_disconnect_by_func (priv->display,
gdk_x11_selection_input_stream_xevent,
g_steal_pointer (&stream));
stream);
g_object_unref (stream);
}
static gssize
@@ -414,7 +416,7 @@ gdk_x11_selection_input_stream_xevent (GdkDisplay *display,
"%s:%s: got PropertyNotify erroring out of INCR",
priv->selection, priv->target);
/* error, should we signal one? */
g_clear_pointer (&stream, gdk_x11_selection_input_stream_complete);
gdk_x11_selection_input_stream_complete (stream);
}
else if (g_bytes_get_size (bytes) == 0 || type == None)
{
@@ -422,7 +424,7 @@ gdk_x11_selection_input_stream_xevent (GdkDisplay *display,
"%s:%s: got PropertyNotify ending INCR",
priv->selection, priv->target);
g_bytes_unref (bytes);
g_clear_pointer (&stream, gdk_x11_selection_input_stream_complete);
gdk_x11_selection_input_stream_complete (stream);
}
else
{
@@ -465,7 +467,7 @@ gdk_x11_selection_input_stream_xevent (GdkDisplay *display,
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
_("Format %s not supported"), priv->target);
g_clear_pointer (&stream, gdk_x11_selection_input_stream_complete);
gdk_x11_selection_input_stream_complete (stream);
}
else
{
@@ -476,7 +478,7 @@ gdk_x11_selection_input_stream_xevent (GdkDisplay *display,
if (bytes == NULL)
{
g_clear_pointer (&stream, gdk_x11_selection_input_stream_complete);
gdk_x11_selection_input_stream_complete (stream);
}
else
{
@@ -498,7 +500,7 @@ gdk_x11_selection_input_stream_xevent (GdkDisplay *display,
g_bytes_get_size (bytes));
g_async_queue_push (priv->chunks, bytes);
g_clear_pointer (&stream, gdk_x11_selection_input_stream_complete);
gdk_x11_selection_input_stream_complete (stream);
}
}
@@ -539,10 +541,7 @@ gdk_x11_selection_input_stream_new_async (GdkDisplay *display,
priv->property = g_strdup_printf ("GDK_SELECTION_%p", stream);
priv->xproperty = gdk_x11_get_xatom_by_name_for_display (display, priv->property);
g_signal_connect_data (display, "xevent",
G_CALLBACK (gdk_x11_selection_input_stream_xevent),
g_steal_pointer (&stream),
(GClosureNotify) g_object_unref, 0);
g_signal_connect (display, "xevent", G_CALLBACK (gdk_x11_selection_input_stream_xevent), stream);
XConvertSelection (GDK_DISPLAY_XDISPLAY (display),
priv->xselection,
@@ -578,6 +577,7 @@ gdk_x11_selection_input_stream_new_finish (GAsyncResult *result,
*type = priv->type;
if (format)
*format = priv->format;
g_object_ref (stream);
}
return G_INPUT_STREAM (stream);
-3
View File
@@ -208,8 +208,6 @@ gdk_x11_surface_update_size (GdkX11Surface *self,
cairo_surface_set_device_scale (self->cairo_surface, scale, scale);
}
gdk_surface_invalidate_rect (surface, NULL);
return TRUE;
}
@@ -1360,7 +1358,6 @@ gdk_x11_surface_destroy (GdkSurface *surface,
unhook_surface_changed (surface);
disconnect_frame_clock (surface);
g_clear_handle_id (&impl->compute_size_source_id, g_source_remove);
if (impl->cairo_surface)
{
+21 -21
View File
@@ -27,8 +27,8 @@
#include <gdk/gdkglcontextprivate.h>
#include <gdk/gdkmemoryformatprivate.h>
#include <gdk/gdkmemorytextureprivate.h>
#include <gdk/gdkprofilerprivate.h>
#include <gdk/gdktexturedownloaderprivate.h>
#include <gsk/gskdebugprivate.h>
#include <gsk/gskroundedrectprivate.h>
@@ -403,6 +403,7 @@ gsk_gl_command_queue_dispose (GObject *object)
gsk_gl_command_batches_clear (&self->batches);
gsk_gl_command_binds_clear (&self->batch_binds);
gsk_gl_command_uniforms_clear (&self->batch_uniforms);
gsk_gl_syncs_clear (&self->syncs);
gsk_gl_buffer_destroy (&self->vertices);
@@ -425,6 +426,7 @@ gsk_gl_command_queue_init (GskGLCommandQueue *self)
gsk_gl_command_batches_init (&self->batches, 128);
gsk_gl_command_binds_init (&self->batch_binds, 1024);
gsk_gl_command_uniforms_init (&self->batch_uniforms, 2048);
gsk_gl_syncs_init (&self->syncs, 10);
gsk_gl_buffer_init (&self->vertices, GL_ARRAY_BUFFER, sizeof (GskGLDrawVertex));
}
@@ -662,10 +664,6 @@ gsk_gl_command_queue_split_draw (GskGLCommandQueue *self)
g_assert (GSK_IS_GL_COMMAND_QUEUE (self));
g_assert (self->batches.len > 0);
if (will_ignore_batch (self))
return;
g_assert (self->in_draw == TRUE);
program = self->program_info;
@@ -1006,11 +1004,8 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation (GL_FUNC_ADD);
if (!gdk_gl_context_get_use_es (self->context))
{
glGenVertexArrays (1, &vao_id);
glBindVertexArray (vao_id);
}
glGenVertexArrays (1, &vao_id);
glBindVertexArray (vao_id);
vbo_id = gsk_gl_buffer_submit (&self->vertices);
@@ -1105,17 +1100,25 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
if G_UNLIKELY (batch->draw.bind_count > 0)
{
const GskGLCommandBind *bind = &self->batch_binds.items[batch->draw.bind_offset];
for (guint i = 0; i < batch->draw.bind_count; i++)
{
if (textures[bind->texture] != bind->id)
{
GskGLSync *s;
if (active != bind->texture)
{
active = bind->texture;
glActiveTexture (GL_TEXTURE0 + bind->texture);
}
s = gsk_gl_syncs_get_sync (&self->syncs, bind->id);
if (s && s->sync)
{
glWaitSync ((GLsync) s->sync, 0, GL_TIMEOUT_IGNORED);
s->sync = NULL;
}
glBindTexture (GL_TEXTURE_2D, bind->id);
textures[bind->texture] = bind->id;
}
@@ -1166,8 +1169,7 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
}
glDeleteBuffers (1, &vbo_id);
if (!gdk_gl_context_get_use_es (self->context))
glDeleteVertexArrays (1, &vao_id);
glDeleteVertexArrays (1, &vao_id);
gdk_profiler_set_int_counter (self->metrics.n_binds, n_binds);
gdk_profiler_set_int_counter (self->metrics.n_uniforms, n_uniforms);
@@ -1244,6 +1246,7 @@ gsk_gl_command_queue_end_frame (GskGLCommandQueue *self)
self->batches.len = 0;
self->batch_binds.len = 0;
self->batch_uniforms.len = 0;
self->syncs.len = 0;
self->n_uploads = 0;
self->tail_batch_index = -1;
self->in_frame = FALSE;
@@ -1367,8 +1370,7 @@ gsk_gl_command_queue_do_upload_texture (GskGLCommandQueue *self,
GdkGLContext *context;
const guchar *data;
gsize stride;
GBytes *bytes;
GdkTextureDownloader downloader;
GdkMemoryTexture *memtex;
GdkMemoryFormat data_format;
int width, height;
GLenum gl_internalformat;
@@ -1403,11 +1405,9 @@ gsk_gl_command_queue_do_upload_texture (GskGLCommandQueue *self,
}
}
gdk_texture_downloader_init (&downloader, texture);
gdk_texture_downloader_set_format (&downloader, data_format);
bytes = gdk_texture_downloader_download_bytes (&downloader, &stride);
gdk_texture_downloader_finish (&downloader);
data = g_bytes_get_data (bytes, NULL);
memtex = gdk_memory_texture_from_texture (texture, data_format);
data = gdk_memory_texture_get_data (memtex);
stride = gdk_memory_texture_get_stride (memtex);
bpp = gdk_memory_format_bytes_per_pixel (data_format);
glPixelStorei (GL_UNPACK_ALIGNMENT, gdk_memory_format_alignment (data_format));
@@ -1437,7 +1437,7 @@ gsk_gl_command_queue_do_upload_texture (GskGLCommandQueue *self,
}
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
g_bytes_unref (bytes);
g_object_unref (memtex);
}
int
+39
View File
@@ -167,9 +167,15 @@ typedef union _GskGLCommandBatch
G_STATIC_ASSERT (sizeof (GskGLCommandBatch) == 32);
typedef struct _GskGLSync {
guint id;
gpointer sync;
} GskGLSync;
DEFINE_INLINE_ARRAY (GskGLCommandBatches, gsk_gl_command_batches, GskGLCommandBatch)
DEFINE_INLINE_ARRAY (GskGLCommandBinds, gsk_gl_command_binds, GskGLCommandBind)
DEFINE_INLINE_ARRAY (GskGLCommandUniforms, gsk_gl_command_uniforms, GskGLCommandUniform)
DEFINE_INLINE_ARRAY (GskGLSyncs, gsk_gl_syncs, GskGLSync)
struct _GskGLCommandQueue
{
@@ -225,6 +231,8 @@ struct _GskGLCommandQueue
*/
GskGLCommandUniforms batch_uniforms;
GskGLSyncs syncs;
/* Discovered max texture size when loading the command queue so that we
* can either scale down or slice textures to fit within this size. Assumed
* to be both height and width.
@@ -354,6 +362,37 @@ gsk_gl_command_queue_bind_framebuffer (GskGLCommandQueue *self,
return ret;
}
static inline GskGLSync *
gsk_gl_syncs_get_sync (GskGLSyncs *syncs,
guint id)
{
for (unsigned int i = 0; i < syncs->len; i++)
{
GskGLSync *sync = &syncs->items[i];
if (sync->id == id)
return sync;
}
return NULL;
}
static inline void
gsk_gl_syncs_add_sync (GskGLSyncs *syncs,
guint id,
gpointer sync)
{
GskGLSync *s;
s = gsk_gl_syncs_get_sync (syncs, id);
if (s)
g_assert (s->sync == sync);
else
{
s = gsk_gl_syncs_append (syncs);
s->id = id;
s->sync = sync;
}
}
G_END_DECLS
#endif /* __GSK_GL_COMMAND_QUEUE_PRIVATE_H__ */
+13 -7
View File
@@ -35,6 +35,7 @@
#include "gskgliconlibraryprivate.h"
#include "gskglprogramprivate.h"
#include "gskglshadowlibraryprivate.h"
#include "gskgltextureprivate.h"
#include "fp16private.h"
#include <gdk/gdkglcontextprivate.h>
@@ -733,7 +734,7 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
format = GL_RGBA8;
if (GDK_IS_GL_TEXTURE (texture) && min_filter == GL_LINEAR && mag_filter == GL_LINEAR)
if (GDK_IS_GL_TEXTURE (texture))
{
GdkGLTexture *gl_texture = (GdkGLTexture *) texture;
GdkGLContext *texture_context = gdk_gl_texture_get_context (gl_texture);
@@ -1328,6 +1329,7 @@ typedef struct _GskGLTextureState
{
GdkGLContext *context;
GLuint texture_id;
GLsync sync;
} GskGLTextureState;
static void
@@ -1340,6 +1342,7 @@ create_texture_from_texture_destroy (gpointer data)
gdk_gl_context_make_current (state->context);
glDeleteTextures (1, &state->texture_id);
glDeleteSync (state->sync);
g_clear_object (&state->context);
g_slice_free (GskGLTextureState, state);
}
@@ -1374,10 +1377,13 @@ gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
texture->texture_id = 0;
gsk_gl_texture_free (texture);
return gdk_gl_texture_new (self->command_queue->context,
texture_id,
width,
height,
create_texture_from_texture_destroy,
state);
state->sync = glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
return gdk_gl_texture_new_with_sync (self->command_queue->context,
texture_id,
state->sync,
width,
height,
create_texture_from_texture_destroy,
state);
}

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