Compare commits
2 Commits
textview-b
...
content_fo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cb7e60c73 | ||
|
|
f9194042f4 |
@@ -7,7 +7,6 @@ stages:
|
||||
- analysis
|
||||
- docs
|
||||
- flatpak
|
||||
- publish
|
||||
- deploy
|
||||
|
||||
.cache-paths: &cache-paths
|
||||
@@ -25,7 +24,7 @@ variables:
|
||||
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
|
||||
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled"
|
||||
MESON_TEST_TIMEOUT_MULTIPLIER: 3
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v33"
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v32"
|
||||
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
|
||||
|
||||
.only-default:
|
||||
@@ -58,7 +57,6 @@ style-check-diff:
|
||||
- "${CI_PROJECT_DIR}/_build/report*.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/report*.html"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*/*.png"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/tools/output/*/*"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*/*.png"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/css/output/*/*.syscap"
|
||||
- "${CI_PROJECT_DIR}/_build_hello/meson-logs"
|
||||
@@ -338,11 +336,14 @@ reference:
|
||||
paths:
|
||||
- _reference
|
||||
|
||||
publish-docs:
|
||||
stage: publish
|
||||
pages:
|
||||
stage: deploy
|
||||
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"
|
||||
- mv _reference/ public/
|
||||
- cp .gitlab-ci/pages/* public/
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
refs:
|
||||
- master
|
||||
- master
|
||||
|
||||
@@ -48,9 +48,7 @@ RUN dnf -y install \
|
||||
libcloudproviders-devel \
|
||||
libepoxy-devel \
|
||||
libffi-devel \
|
||||
libjpeg-turbo-devel \
|
||||
libmount-devel \
|
||||
libpng-devel \
|
||||
librsvg2 \
|
||||
libselinux-devel \
|
||||
libubsan \
|
||||
|
||||
@@ -40,7 +40,7 @@ export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
|
||||
# https://gitlab.gnome.org/GNOME/gtk/-/issues/2243
|
||||
# https://gitlab.gnome.org/GNOME/gtk/-/issues/3002
|
||||
|
||||
if ! pkg-config --atleast-version=2.66.0 glib-2.0; then
|
||||
if ! pkg-config --atleast-version=2.65.0 glib-2.0; then
|
||||
git clone https://gitlab.gnome.org/GNOME/glib.git _glib
|
||||
meson setup _glib_build _glib
|
||||
meson compile -C _glib_build
|
||||
@@ -48,7 +48,7 @@ if ! pkg-config --atleast-version=2.66.0 glib-2.0; then
|
||||
fi
|
||||
pkg-config --modversion glib-2.0
|
||||
|
||||
if ! pkg-config --atleast-version=1.49.0 pango; then
|
||||
if ! pkg-config --atleast-version=1.47.0 pango; then
|
||||
git clone https://gitlab.gnome.org/GNOME/pango.git _pango
|
||||
meson setup _pango_build _pango
|
||||
meson compile -C _pango_build
|
||||
|
||||
81
NEWS
81
NEWS
@@ -1,84 +1,3 @@
|
||||
Overview of Changes
|
||||
===================
|
||||
|
||||
* gsk:
|
||||
- Drop the GL renderer in favor of NGL
|
||||
|
||||
* css:
|
||||
- Add support for line-height
|
||||
- Add support for text-transform
|
||||
|
||||
* GtkTextView:
|
||||
- Add support for line height
|
||||
- Add support for text transforms
|
||||
|
||||
* Build:
|
||||
- Require Pango 1.49
|
||||
|
||||
|
||||
Overview of Changes in 4.4.0
|
||||
============================
|
||||
|
||||
* Input:
|
||||
- Match IBus for display of Compose sequences
|
||||
- Match IBus for handling of mismatches
|
||||
- Handle Escape in Compose sequences
|
||||
- Allow multiple dead keys
|
||||
- Support 32bit keysyms
|
||||
|
||||
* GtkCheckButton:
|
||||
- Activate when moving focus
|
||||
|
||||
* GtkLabel:
|
||||
- Propertly ignore double underscores for mnemonics
|
||||
|
||||
* GtkPopoverMenu:
|
||||
- Fix focus cycling
|
||||
|
||||
* GtkTextView:
|
||||
- Improve word selection
|
||||
- Fix block cursors on empty lines
|
||||
|
||||
* GdkToplevel:
|
||||
- Support the gnome-shell titlebar gesture protocol
|
||||
|
||||
* GdkDropTarget:
|
||||
- Allow creating drop targets in ui files
|
||||
|
||||
* gsk:
|
||||
- Handle partial color fonts correctly
|
||||
- Use harfbuzz for color font information
|
||||
- Avoid pango for glyph cache rendering
|
||||
- Shrink shadow extents
|
||||
|
||||
* Settings:
|
||||
- Change the default for gtk-split-cursor to FALSE
|
||||
|
||||
* Demos:
|
||||
- Small improvements to widget-factory
|
||||
- gtk-demo: Improve the hypertext demo
|
||||
- gtk-dem: Improve the clipboard demo
|
||||
|
||||
* X11:
|
||||
- Set WM_CLASS on toplevels
|
||||
|
||||
* Wayland:
|
||||
- Support wl_seat v7
|
||||
|
||||
* Windows:
|
||||
- Drop the local DND protocol
|
||||
- Avoid WGL if shaders don't work
|
||||
- Use WinPointer API
|
||||
|
||||
* Translation updates:
|
||||
Belarusian
|
||||
Friulian
|
||||
Hebrew
|
||||
Khmer
|
||||
Persian
|
||||
Polish
|
||||
|
||||
|
||||
Overview of Changes in 4.3.2
|
||||
============================
|
||||
|
||||
|
||||
@@ -321,7 +321,6 @@
|
||||
<file>paintable_emblem.c</file>
|
||||
<file>paintable_mediastream.c</file>
|
||||
<file>paintable_svg.c</file>
|
||||
<file>paintable_symbolic.c</file>
|
||||
<file>panes.c</file>
|
||||
<file>password_entry.c</file>
|
||||
<file>peg_solitaire.c</file>
|
||||
|
||||
@@ -100,11 +100,7 @@ prepare_drag (GtkDragSource *source,
|
||||
DemoImage *demo = DEMO_IMAGE (widget);
|
||||
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (demo->image));
|
||||
|
||||
/* Textures can be serialized, paintables can't, so special case the textures */
|
||||
if (GDK_IS_TEXTURE (paintable))
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, paintable);
|
||||
else
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_PAINTABLE, paintable);
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_PAINTABLE, paintable);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -133,11 +129,7 @@ copy_image (GtkWidget *widget,
|
||||
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (demo->image));
|
||||
GValue value = G_VALUE_INIT;
|
||||
|
||||
/* Textures can be serialized, paintables can't, so special case the textures */
|
||||
if (GDK_IS_TEXTURE (paintable))
|
||||
g_value_init (&value, GDK_TYPE_TEXTURE);
|
||||
else
|
||||
g_value_init (&value, GDK_TYPE_PAINTABLE);
|
||||
g_value_init (&value, GDK_TYPE_PAINTABLE);
|
||||
g_value_set_object (&value, paintable);
|
||||
gdk_clipboard_set_value (clipboard, &value);
|
||||
g_value_unset (&value);
|
||||
@@ -146,46 +138,24 @@ copy_image (GtkWidget *widget,
|
||||
g_object_unref (paintable);
|
||||
}
|
||||
|
||||
static void
|
||||
paste_image_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GdkClipboard *clipboard = GDK_CLIPBOARD (source);
|
||||
DemoImage *demo = DEMO_IMAGE (data);
|
||||
const GValue *value;
|
||||
|
||||
value = gdk_clipboard_read_value_finish (clipboard, result, NULL);
|
||||
if (value == NULL)
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (demo));
|
||||
g_object_unref (demo);
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_image_set_from_paintable (GTK_IMAGE (demo->image), g_value_get_object (value));
|
||||
g_object_unref (demo);
|
||||
}
|
||||
|
||||
static void
|
||||
paste_image (GtkWidget *widget,
|
||||
const char *action_name,
|
||||
GVariant *parameter)
|
||||
{
|
||||
GdkClipboard *clipboard = gtk_widget_get_clipboard (widget);
|
||||
GType type;
|
||||
DemoImage *demo = DEMO_IMAGE (widget);
|
||||
GdkContentProvider *content = gdk_clipboard_get_content (clipboard);
|
||||
GValue value = G_VALUE_INIT;
|
||||
GdkPaintable *paintable;
|
||||
|
||||
if (gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), GDK_TYPE_TEXTURE))
|
||||
type = GDK_TYPE_TEXTURE;
|
||||
else
|
||||
type = GDK_TYPE_PAINTABLE;
|
||||
g_value_init (&value, GDK_TYPE_PAINTABLE);
|
||||
if (!gdk_content_provider_get_value (content, &value, NULL))
|
||||
return;
|
||||
|
||||
gdk_clipboard_read_value_async (clipboard,
|
||||
type,
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
paste_image_cb,
|
||||
g_object_ref (widget));
|
||||
paintable = GDK_PAINTABLE (g_value_get_object (&value));
|
||||
gtk_image_set_from_paintable (GTK_IMAGE (demo->image), paintable);
|
||||
g_value_unset (&value);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -131,19 +131,6 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
|
||||
gtk_text_buffer_apply_tag (buffer, tag, start, end); \
|
||||
}
|
||||
|
||||
#define VOID_ATTR(attr_name) \
|
||||
{ \
|
||||
tag = gtk_text_tag_table_lookup (table, #attr_name); \
|
||||
if (!tag) \
|
||||
{ \
|
||||
tag = gtk_text_tag_new (#attr_name); \
|
||||
g_object_set (tag, #attr_name, TRUE, NULL); \
|
||||
gtk_text_tag_table_add (table, tag); \
|
||||
g_object_unref (tag); \
|
||||
} \
|
||||
gtk_text_buffer_apply_tag (buffer, tag, start, end); \
|
||||
}
|
||||
|
||||
fg_alpha = bg_alpha = 1.;
|
||||
|
||||
attrs = pango_attr_iterator_get_attrs (iter);
|
||||
@@ -268,30 +255,6 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
|
||||
INT_ATTR (insert_hyphens);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_LINE_HEIGHT:
|
||||
FLOAT_ATTR (line_height);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_ABSOLUTE_LINE_HEIGHT:
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_WORD:
|
||||
VOID_ATTR (word);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_SENTENCE:
|
||||
VOID_ATTR (sentence);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_BASELINE_SHIFT:
|
||||
INT_ATTR (baseline_shift);
|
||||
break;
|
||||
|
||||
/* Ignore font scale, since we treat baseline-shift as indicating
|
||||
* both. And in practice, they will basically always occur together
|
||||
* (from a <sup> or <sub>)
|
||||
*/
|
||||
case PANGO_ATTR_FONT_SCALE:
|
||||
case PANGO_ATTR_SHAPE:
|
||||
case PANGO_ATTR_ABSOLUTE_SIZE:
|
||||
case PANGO_ATTR_GRAVITY:
|
||||
@@ -300,10 +263,6 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
|
||||
case PANGO_ATTR_BACKGROUND_ALPHA:
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_TEXT_TRANSFORM:
|
||||
INT_ATTR (text_transform);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_INVALID:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
|
||||
@@ -61,26 +61,12 @@ show_page (GtkTextView *text_view,
|
||||
int page)
|
||||
{
|
||||
GtkTextBuffer *buffer;
|
||||
GtkTextIter iter, start;
|
||||
GtkTextMark *mark;
|
||||
GtkTextIter iter;
|
||||
GtkWidget *child;
|
||||
GtkTextChildAnchor *anchor;
|
||||
GtkEventController *controller;
|
||||
GtkTextTag *bold, *mono, *nobreaks;
|
||||
|
||||
buffer = gtk_text_view_get_buffer (text_view);
|
||||
|
||||
bold = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"weight", PANGO_WEIGHT_BOLD,
|
||||
"scale", PANGO_SCALE_X_LARGE,
|
||||
NULL);
|
||||
mono = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"family", "monospace",
|
||||
NULL);
|
||||
nobreaks = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"allow-breaks", FALSE,
|
||||
NULL);
|
||||
|
||||
gtk_text_buffer_set_text (buffer, "", 0);
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
|
||||
gtk_text_buffer_begin_irreversible_action (buffer);
|
||||
@@ -118,22 +104,17 @@ show_page (GtkTextView *text_view,
|
||||
}
|
||||
else if (page == 2)
|
||||
{
|
||||
mark = gtk_text_buffer_create_mark (buffer, "mark", &iter, TRUE);
|
||||
GtkTextTag *tag;
|
||||
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "tag", -1, bold, NULL);
|
||||
gtk_text_buffer_insert (buffer, &iter, " /", -1);
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
|
||||
gtk_text_buffer_apply_tag (buffer, nobreaks, &start, &iter);
|
||||
gtk_text_buffer_insert (buffer, &iter, " ", -1);
|
||||
|
||||
gtk_text_buffer_move_mark (buffer, mark, &iter);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "tag", -1, mono, NULL);
|
||||
gtk_text_buffer_insert (buffer, &iter, " /", -1);
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
|
||||
gtk_text_buffer_apply_tag (buffer, nobreaks, &start, &iter);
|
||||
gtk_text_buffer_insert (buffer, &iter, " ", -1);
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"weight", PANGO_WEIGHT_BOLD,
|
||||
"scale", PANGO_SCALE_X_LARGE,
|
||||
NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "tag", -1, tag, NULL);
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"family", "monospace",
|
||||
NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, " / tag / ", -1, tag, NULL);
|
||||
|
||||
anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
|
||||
child = gtk_image_new_from_icon_name ("audio-volume-high-symbolic");
|
||||
@@ -151,26 +132,20 @@ show_page (GtkTextView *text_view,
|
||||
"behavior of mouse and key presses, “lock” a range of text so the "
|
||||
"user can't edit it, or countless other things.\n", -1);
|
||||
insert_link (buffer, &iter, "Go back", 1);
|
||||
|
||||
gtk_text_buffer_delete_mark (buffer, mark);
|
||||
}
|
||||
else if (page == 3)
|
||||
{
|
||||
mark = gtk_text_buffer_create_mark (buffer, "mark", &iter, TRUE);
|
||||
GtkTextTag *tag;
|
||||
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "hypertext", -1, bold, NULL);
|
||||
gtk_text_buffer_insert (buffer, &iter, " /", -1);
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
|
||||
gtk_text_buffer_apply_tag (buffer, nobreaks, &start, &iter);
|
||||
gtk_text_buffer_insert (buffer, &iter, " ", -1);
|
||||
|
||||
gtk_text_buffer_move_mark (buffer, mark, &iter);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "ˈhaɪ pərˌtɛkst", -1, mono, NULL);
|
||||
gtk_text_buffer_insert (buffer, &iter, " /", -1);
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
|
||||
gtk_text_buffer_apply_tag (buffer, nobreaks, &start, &iter);
|
||||
gtk_text_buffer_insert (buffer, &iter, " ", -1);
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"weight", PANGO_WEIGHT_BOLD,
|
||||
"scale", PANGO_SCALE_X_LARGE,
|
||||
NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "hypertext", -1, tag, NULL);
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"family", "monospace",
|
||||
NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, " / ˈhaɪ pərˌtɛkst / ", -1, tag, NULL);
|
||||
|
||||
anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
|
||||
child = gtk_image_new_from_icon_name ("audio-volume-high-symbolic");
|
||||
@@ -184,8 +159,6 @@ show_page (GtkTextView *text_view,
|
||||
"Machine-readable text that is not sequential but is organized "
|
||||
"so that related items of information are connected.\n", -1);
|
||||
insert_link (buffer, &iter, "Go back", 1);
|
||||
|
||||
gtk_text_buffer_delete_mark (buffer, mark);
|
||||
}
|
||||
gtk_text_buffer_end_irreversible_action (buffer);
|
||||
}
|
||||
@@ -385,7 +358,7 @@ do_hypertext (GtkWidget *do_widget)
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
|
||||
GTK_POLICY_NEVER,
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
gtk_window_set_child (GTK_WINDOW (window), sw);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), view);
|
||||
|
||||
@@ -58,7 +58,7 @@ do_markup (GtkWidget *do_widget)
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 680);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 450, 450);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
stack = gtk_stack_new ();
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
|
||||
Text sizes: <span size="xx-small">tiny </span><span size="x-small">very small </span><span size="small">small </span><span size="medium">normal </span><span size="large">large </span><span size="x-large">very large </span><span size="xx-large">huge</span>
|
||||
|
||||
Text styles: <span style="normal">Normal</span> <span style="italic">Italic</span> <span style="oblique">Olique</span>
|
||||
|
||||
Text weights: <span weight="thin">thin</span> <span weight="light">light</span> <span weight="normal">normal</span> <span weight="bold">bold</span> <span weight="ultraheavy">ultraheavy</span>
|
||||
Text sizes: <span size="xx-small">tiny</span> <span size="x-small">very small</span> <span size="small">small</span> <span size="medium">normal</span> <span size="large">large</span> <span size="x-large">very large</span> <span size="xx-large">huge</span>
|
||||
|
||||
Text <span color="gray">c<span color="green">o</span>l<span color="tomato">o</span>rs</span> and <span background="pink">backgrounds</span>
|
||||
|
||||
@@ -11,7 +7,7 @@ Colorful <span underline="low" underline-color="blue"><span underline="double" u
|
||||
|
||||
Colorful <span strikethrough="true" strikethrough-color="magenta">strikethroughs</span> and <span overline="single" overline_color="green">overlines</span>
|
||||
|
||||
Superscripts and subscripts: <span font="italic">ε<sub><span size='smaller'>0</span></sub> = ω<sup>ω<sup>ω<sup>.<sup>.<sup>.</sup></sup></sup></sup></sup></span>
|
||||
Superscripts and subscripts: 𝜀<span rise="-6000" size="x-small" font_desc="italic">0</span> = 𝜔<span rise="8000" size="smaller">𝜔<span rise="14000" size="smaller">𝜔<span rise="20000">.<span rise="23000">.<span rise="26000">.</span></span></span></span></span>
|
||||
|
||||
<span letter_spacing="3000">Letterspacing</span>
|
||||
|
||||
@@ -19,12 +15,6 @@ OpenType font features: <span font_desc="sans regular" font_features="dlig=0">fe
|
||||
|
||||
Shortcuts: <tt>Monospace</tt> – <b>Bold</b> – <i>Italic</i> – <big>Big</big> – <small>Small</small> – <u>Underlined</u> – <s>Strikethrough</s> – Super<sup>script</sup> – Sub<sub>script</sub>
|
||||
|
||||
hyphenation algorithm is a <span allow_breaks="false" style="italic">set of rules</span>, especially one codified for implementation in a computer program, that decides at which points a word can be broken over two lines with a hyphen. For example, a hyphenation algorithm might decide that impeachment can be broken as impeach‧ment or im‧peachment but not impe‧achment.
|
||||
<span allow_breaks="false">A</span> hyphenation algorithm is a set of rules, especially one codified for implementation in a computer program, that decides at which points a word can be broken over two lines with a hyphen. For example, a hyphenation algorithm might decide that impeachment can be broken as <span allow_breaks="false">impeach‧ment</span> or <span allow_breaks="false">im‧peachment</span> but not <span allow_breaks="false">impe‧achment.</span>
|
||||
|
||||
<span insert_hyphens="false">one/two three/four five/six seven/eight nine/ten</span>
|
||||
|
||||
<span line_height='1.33'>Line height: This is an example of widely spaced text. It was achieved by setting the line-height factor to 1.33. You can set the line-height factor to any value between 0 and 10.
|
||||
Note that the line height affects the spacing between paragraphs as well as between the wrapped lines inside a paragraph.</span>
|
||||
|
||||
Transforms: <span text_transform='uppercase'>straße</span> <span text_transform='capitalize'>up, up and away</span>
|
||||
|
||||
|
||||
@@ -67,7 +67,6 @@ demos = files([
|
||||
'paintable_animated.c',
|
||||
'paintable_emblem.c',
|
||||
'paintable_mediastream.c',
|
||||
'paintable_symbolic.c',
|
||||
'panes.c',
|
||||
'password_entry.c',
|
||||
'peg_solitaire.c',
|
||||
|
||||
@@ -45,27 +45,26 @@ struct _GtkNuclearIconClass
|
||||
* so that it can be called from all the other demos, too.
|
||||
*/
|
||||
void
|
||||
gtk_nuclear_snapshot (GtkSnapshot *snapshot,
|
||||
const GdkRGBA *foreground,
|
||||
const GdkRGBA *background,
|
||||
double width,
|
||||
double height,
|
||||
double rotation)
|
||||
gtk_nuclear_snapshot (GtkSnapshot *snapshot,
|
||||
double width,
|
||||
double height,
|
||||
double rotation,
|
||||
gboolean draw_background)
|
||||
{
|
||||
#define RADIUS 0.3
|
||||
cairo_t *cr;
|
||||
double size;
|
||||
|
||||
gtk_snapshot_append_color (snapshot,
|
||||
background,
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
if (draw_background)
|
||||
gtk_snapshot_append_color (snapshot,
|
||||
&(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 },
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
|
||||
size = MIN (width, height);
|
||||
cr = gtk_snapshot_append_cairo (snapshot,
|
||||
&GRAPHENE_RECT_INIT ((width - size) / 2.0,
|
||||
(height - size) / 2.0,
|
||||
size, size));
|
||||
gdk_cairo_set_source_rgba (cr, foreground);
|
||||
cairo_translate (cr, width / 2.0, height / 2.0);
|
||||
cairo_scale (cr, size, size);
|
||||
cairo_rotate (cr, rotation);
|
||||
@@ -95,10 +94,9 @@ gtk_nuclear_icon_snapshot (GdkPaintable *paintable,
|
||||
*/
|
||||
|
||||
gtk_nuclear_snapshot (snapshot,
|
||||
&(GdkRGBA) { 0, 0, 0, 1 }, /* black */
|
||||
&(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 }, /* yellow */
|
||||
width, height,
|
||||
nuclear->rotation);
|
||||
nuclear->rotation,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static GdkPaintableFlags
|
||||
|
||||
@@ -4,11 +4,10 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
void gtk_nuclear_snapshot (GtkSnapshot *snapshot,
|
||||
const GdkRGBA *foreground,
|
||||
const GdkRGBA *background,
|
||||
double width,
|
||||
double height,
|
||||
double rotation);
|
||||
double rotation,
|
||||
gboolean draw_background);
|
||||
|
||||
GdkPaintable * gtk_nuclear_icon_new (double rotation);
|
||||
GdkPaintable * gtk_nuclear_animation_new (gboolean draw_background);
|
||||
|
||||
@@ -65,12 +65,9 @@ gtk_nuclear_animation_snapshot (GdkPaintable *paintable,
|
||||
|
||||
/* We call the function from the previous example here. */
|
||||
gtk_nuclear_snapshot (snapshot,
|
||||
&(GdkRGBA) { 0, 0, 0, 1 }, /* black */
|
||||
nuclear->draw_background
|
||||
? &(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 } /* yellow */
|
||||
: &(GdkRGBA) { 0, 0, 0, 0 }, /* transparent */
|
||||
width, height,
|
||||
2 * G_PI * nuclear->progress / MAX_PROGRESS);
|
||||
2 * G_PI * nuclear->progress / MAX_PROGRESS,
|
||||
nuclear->draw_background);
|
||||
}
|
||||
|
||||
static GdkPaintable *
|
||||
|
||||
@@ -73,10 +73,9 @@ gtk_nuclear_media_stream_snapshot (GdkPaintable *paintable,
|
||||
|
||||
/* We call the function from the previous example here. */
|
||||
gtk_nuclear_snapshot (snapshot,
|
||||
&(GdkRGBA) { 0, 0, 0, 1 }, /* black */
|
||||
&(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 }, /* yellow */
|
||||
width, height,
|
||||
2 * G_PI * nuclear->progress / DURATION);
|
||||
2 * G_PI * nuclear->progress / DURATION,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static GdkPaintable *
|
||||
|
||||
@@ -1,208 +0,0 @@
|
||||
/* Paintable/Symbolic Paintable
|
||||
*
|
||||
* GdkPaintables can be made to follow the theme's colors. GTK calls
|
||||
* icons that do this symbolic icons, paintables that want to have
|
||||
* the same effect can implement the GtkSymbolicPaintable interface.
|
||||
*
|
||||
* We will adapt the original paintable example by adding the ability
|
||||
* to recolor the paintable based on the symbolic colors.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "paintable.h"
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
/* First, add the boilerplate for the object itself.
|
||||
* This part would normally go in the header.
|
||||
*/
|
||||
#define GTK_TYPE_NUCLEAR_SYMBOLIC (gtk_nuclear_symbolic_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkNuclearSymbolic, gtk_nuclear_symbolic, GTK, NUCLEAR_SYMBOLIC, GObject)
|
||||
|
||||
/* Declare a few warning levels, so we can pick colors based on them */
|
||||
typedef enum
|
||||
{
|
||||
WARNING_NONE,
|
||||
WARNING_ALERT,
|
||||
WARNING_EMERGENCY
|
||||
} WarningLevel;
|
||||
|
||||
/* Declare the struct. */
|
||||
struct _GtkNuclearSymbolic
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
WarningLevel warning_level;
|
||||
};
|
||||
|
||||
struct _GtkNuclearSymbolicClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/* Add a function to draw the nuclear icon in the given colors */
|
||||
static void
|
||||
gtk_nuclear_symbolic_snapshot_symbolic (GtkSymbolicPaintable *paintable,
|
||||
GdkSnapshot *snapshot,
|
||||
double width,
|
||||
double height,
|
||||
const GdkRGBA *colors,
|
||||
gsize n_colors)
|
||||
{
|
||||
GtkNuclearSymbolic *self = GTK_NUCLEAR_SYMBOLIC (paintable);
|
||||
static const GdkRGBA transparent = { 0, };
|
||||
const GdkRGBA *bg_color;
|
||||
|
||||
/* select the right background color from the warning level */
|
||||
switch (self->warning_level)
|
||||
{
|
||||
case WARNING_NONE:
|
||||
bg_color = &transparent;
|
||||
break;
|
||||
case WARNING_ALERT:
|
||||
bg_color = &colors[GTK_SYMBOLIC_COLOR_WARNING];
|
||||
break;
|
||||
case WARNING_EMERGENCY:
|
||||
bg_color = &colors[GTK_SYMBOLIC_COLOR_ERROR];
|
||||
break;
|
||||
default:
|
||||
/* This should never happen, but we better do defensive coding
|
||||
* with this critical icon */
|
||||
g_assert_not_reached ();
|
||||
bg_color = &transparent;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Draw the icon with the selected warning color */
|
||||
gtk_nuclear_snapshot (snapshot,
|
||||
&colors[GTK_SYMBOLIC_COLOR_FOREGROUND],
|
||||
bg_color,
|
||||
width, height,
|
||||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_nuclear_symbolic_symbolic_paintable_init (GtkSymbolicPaintableInterface *iface)
|
||||
{
|
||||
iface->snapshot_symbolic = gtk_nuclear_symbolic_snapshot_symbolic;
|
||||
}
|
||||
|
||||
/* We need to implement the functionality required by the GdkPaintable interface */
|
||||
static void
|
||||
gtk_nuclear_symbolic_snapshot (GdkPaintable *paintable,
|
||||
GdkSnapshot *snapshot,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
/* Calling this function without passing a color is a neat trick
|
||||
* to make GTK use default colors and otherwise forward the call
|
||||
* to the snapshotting function above.
|
||||
*/
|
||||
gtk_symbolic_paintable_snapshot_symbolic (GTK_SYMBOLIC_PAINTABLE (paintable),
|
||||
snapshot,
|
||||
width, height,
|
||||
NULL, 0);
|
||||
}
|
||||
|
||||
static GdkPaintableFlags
|
||||
gtk_nuclear_symbolic_get_flags (GdkPaintable *paintable)
|
||||
{
|
||||
/* This image has a static size, but the contents may change:
|
||||
* We draw different things when the warning level changes.
|
||||
*/
|
||||
return GDK_PAINTABLE_STATIC_SIZE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_nuclear_symbolic_paintable_init (GdkPaintableInterface *iface)
|
||||
{
|
||||
iface->snapshot = gtk_nuclear_symbolic_snapshot;
|
||||
iface->get_flags = gtk_nuclear_symbolic_get_flags;
|
||||
}
|
||||
|
||||
/* When defining the GType, we need to implement bot the GdkPaintable
|
||||
* and the GtkSymbolicPaintable interface */
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkNuclearSymbolic, gtk_nuclear_symbolic, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
||||
gtk_nuclear_symbolic_paintable_init)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_SYMBOLIC_PAINTABLE,
|
||||
gtk_nuclear_symbolic_symbolic_paintable_init))
|
||||
|
||||
static void
|
||||
gtk_nuclear_symbolic_class_init (GtkNuclearSymbolicClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_nuclear_symbolic_init (GtkNuclearSymbolic *nuclear)
|
||||
{
|
||||
}
|
||||
|
||||
/* And finally, we add the simple constructor we declared in the header. */
|
||||
GdkPaintable *
|
||||
gtk_nuclear_symbolic_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_NUCLEAR_SYMBOLIC, NULL);
|
||||
}
|
||||
|
||||
/* Add some fun feature to the button */
|
||||
static void
|
||||
nuclear_button_clicked (GtkButton *button,
|
||||
GtkNuclearSymbolic *nuclear)
|
||||
{
|
||||
if (nuclear->warning_level >= WARNING_EMERGENCY)
|
||||
{
|
||||
/* On maximum warning level, reset the warning */
|
||||
nuclear->warning_level = WARNING_NONE;
|
||||
/* And sometimes (but not always to confuse people)
|
||||
* close the window.
|
||||
*/
|
||||
if (g_random_boolean ())
|
||||
gtk_window_close (GTK_WINDOW (window));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise just increase the warning level */
|
||||
nuclear->warning_level++;
|
||||
}
|
||||
|
||||
/* Don't forget to emit the signal causing the paintable to redraw.
|
||||
* Changing the warning level changes the background color after all.
|
||||
*/
|
||||
gdk_paintable_invalidate_contents (GDK_PAINTABLE (nuclear));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_paintable_symbolic (GtkWidget *do_widget)
|
||||
{
|
||||
GdkPaintable *nuclear;
|
||||
GtkWidget *image, *button;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Don't click!");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
button = gtk_button_new ();
|
||||
gtk_window_set_child (GTK_WINDOW (window), button);
|
||||
|
||||
nuclear = gtk_nuclear_symbolic_new ();
|
||||
image = gtk_image_new_from_paintable (nuclear);
|
||||
|
||||
gtk_button_set_child (GTK_BUTTON (button), image);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (nuclear_button_clicked), nuclear);
|
||||
g_object_unref (nuclear);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "gtkrendererpaintableprivate.h"
|
||||
|
||||
#include "gsk/gskrendernodeparserprivate.h"
|
||||
#include "gsk/gl/gskglrenderer.h"
|
||||
#include "gsk/ngl/gsknglrenderer.h"
|
||||
#ifdef GDK_WINDOWING_BROADWAY
|
||||
#include "gsk/broadway/gskbroadwayrenderer.h"
|
||||
@@ -60,7 +61,7 @@ struct _NodeEditorWindow
|
||||
|
||||
GtkWidget *renderer_listbox;
|
||||
GListStore *renderers;
|
||||
GskRenderNode *node;
|
||||
GdkPaintable *paintable;
|
||||
|
||||
GFileMonitor *file_monitor;
|
||||
|
||||
@@ -167,6 +168,7 @@ static void
|
||||
text_changed (GtkTextBuffer *buffer,
|
||||
NodeEditorWindow *self)
|
||||
{
|
||||
GskRenderNode *node;
|
||||
char *text;
|
||||
GBytes *bytes;
|
||||
GtkTextIter iter;
|
||||
@@ -177,12 +179,10 @@ text_changed (GtkTextBuffer *buffer,
|
||||
text_buffer_remove_all_tags (self->text_buffer);
|
||||
bytes = g_bytes_new_take (text, strlen (text));
|
||||
|
||||
g_clear_pointer (&self->node, gsk_render_node_unref);
|
||||
|
||||
/* If this is too slow, go fix the parser performance */
|
||||
self->node = gsk_render_node_deserialize (bytes, deserialize_error_func, self);
|
||||
node = gsk_render_node_deserialize (bytes, deserialize_error_func, self);
|
||||
g_bytes_unref (bytes);
|
||||
if (self->node)
|
||||
if (node)
|
||||
{
|
||||
/* XXX: Is this code necessary or can we have API to turn nodes into paintables? */
|
||||
GtkSnapshot *snapshot;
|
||||
@@ -191,9 +191,10 @@ text_changed (GtkTextBuffer *buffer,
|
||||
guint i;
|
||||
|
||||
snapshot = gtk_snapshot_new ();
|
||||
gsk_render_node_get_bounds (self->node, &bounds);
|
||||
gsk_render_node_get_bounds (node, &bounds);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- bounds.origin.x, - bounds.origin.y));
|
||||
gtk_snapshot_append_node (snapshot, self->node);
|
||||
gtk_snapshot_append_node (snapshot, node);
|
||||
gsk_render_node_unref (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++)
|
||||
@@ -337,9 +338,15 @@ text_view_query_tooltip_cb (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
load_bytes (NodeEditorWindow *self,
|
||||
GBytes *bytes)
|
||||
load_file_contents (NodeEditorWindow *self,
|
||||
GFile *file)
|
||||
{
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = g_file_load_bytes (file, NULL, NULL, NULL);
|
||||
if (bytes == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!g_utf8_validate (g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), NULL))
|
||||
{
|
||||
g_bytes_unref (bytes);
|
||||
@@ -355,105 +362,6 @@ load_bytes (NodeEditorWindow *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
load_file_contents (NodeEditorWindow *self,
|
||||
GFile *file)
|
||||
{
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = g_file_load_bytes (file, NULL, NULL, NULL);
|
||||
if (bytes == NULL)
|
||||
return FALSE;
|
||||
|
||||
return load_bytes (self, bytes);
|
||||
}
|
||||
|
||||
static GdkContentProvider *
|
||||
on_picture_drag_prepare_cb (GtkDragSource *source,
|
||||
double x,
|
||||
double y,
|
||||
NodeEditorWindow *self)
|
||||
{
|
||||
if (self->node == NULL)
|
||||
return NULL;
|
||||
|
||||
return gdk_content_provider_new_typed (GSK_TYPE_RENDER_NODE, self->node);
|
||||
}
|
||||
|
||||
static void
|
||||
on_picture_drop_read_done_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
NodeEditorWindow *self = data;
|
||||
GOutputStream *stream = G_OUTPUT_STREAM (source);
|
||||
GdkDrop *drop = g_object_get_data (source, "drop");
|
||||
GdkDragAction action = 0;
|
||||
GBytes *bytes;
|
||||
|
||||
if (g_output_stream_splice_finish (stream, res, NULL) >= 0)
|
||||
{
|
||||
bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (stream));
|
||||
if (load_bytes (self, bytes))
|
||||
action = GDK_ACTION_COPY;
|
||||
}
|
||||
|
||||
g_object_unref (self);
|
||||
gdk_drop_finish (drop, action);
|
||||
g_object_unref (drop);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
on_picture_drop_read_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
NodeEditorWindow *self = data;
|
||||
GdkDrop *drop = GDK_DROP (source);
|
||||
GInputStream *input;
|
||||
GOutputStream *output;
|
||||
|
||||
input = gdk_drop_read_finish (drop, res, NULL, NULL);
|
||||
if (input == NULL)
|
||||
{
|
||||
g_object_unref (self);
|
||||
gdk_drop_finish (drop, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
output = g_memory_output_stream_new_resizable ();
|
||||
g_object_set_data (G_OBJECT (output), "drop", drop);
|
||||
g_object_ref (drop);
|
||||
|
||||
g_output_stream_splice_async (output,
|
||||
input,
|
||||
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
on_picture_drop_read_done_cb,
|
||||
self);
|
||||
g_object_unref (output);
|
||||
g_object_unref (input);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_picture_drop_cb (GtkDropTargetAsync *dest,
|
||||
GdkDrop *drop,
|
||||
double x,
|
||||
double y,
|
||||
NodeEditorWindow *self)
|
||||
{
|
||||
gdk_drop_read_async (drop,
|
||||
(const char *[2]) { "application/x-gtk-render-node", NULL },
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
on_picture_drop_read_cb,
|
||||
g_object_ref (self));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
file_changed_cb (GFileMonitor *monitor,
|
||||
GFile *file,
|
||||
@@ -828,7 +736,6 @@ node_editor_window_finalize (GObject *object)
|
||||
|
||||
g_array_free (self->errors, TRUE);
|
||||
|
||||
g_clear_pointer (&self->node, gsk_render_node_unref);
|
||||
g_clear_object (&self->renderers);
|
||||
|
||||
G_OBJECT_CLASS (node_editor_window_parent_class)->finalize (object);
|
||||
@@ -872,8 +779,11 @@ node_editor_window_realize (GtkWidget *widget)
|
||||
"Default");
|
||||
#endif
|
||||
node_editor_window_add_renderer (self,
|
||||
gsk_ngl_renderer_new (),
|
||||
gsk_gl_renderer_new (),
|
||||
"OpenGL");
|
||||
node_editor_window_add_renderer (self,
|
||||
gsk_ngl_renderer_new (),
|
||||
"NGL");
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
node_editor_window_add_renderer (self,
|
||||
gsk_vulkan_renderer_new (),
|
||||
@@ -938,8 +848,6 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
|
||||
gtk_widget_class_bind_template_callback (widget_class, testcase_save_clicked_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, testcase_name_entry_changed_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, dark_mode_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_picture_drag_prepare_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_picture_drop_cb);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
|
||||
@@ -200,19 +200,6 @@
|
||||
<property name="can-shrink">0</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<property name="actions">copy</property>
|
||||
<signal name="prepare" handler="on_picture_drag_prepare_cb" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropTargetAsync">
|
||||
<property name="actions">copy</property>
|
||||
<property name="formats">application/x-gtk-render-node</property>
|
||||
<signal name="drop" handler="on_picture_drop_cb" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.2 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.4 MiB |
BIN
demos/widget-factory/snowy.jpg
Normal file
BIN
demos/widget-factory/snowy.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 MiB |
@@ -696,37 +696,6 @@ on_range_to_changed (GtkSpinButton *to)
|
||||
gtk_spin_button_set_value (from, v2);
|
||||
}
|
||||
|
||||
static GdkContentProvider *
|
||||
on_picture_drag_prepare (GtkDragSource *source,
|
||||
double x,
|
||||
double y,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkWidget *picture;
|
||||
|
||||
picture = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
|
||||
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, gtk_picture_get_paintable (GTK_PICTURE (picture)));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_picture_drop (GtkDropTarget *dest,
|
||||
const GValue *value,
|
||||
double x,
|
||||
double y,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkWidget *picture;
|
||||
GdkPaintable *paintable;
|
||||
|
||||
picture = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
|
||||
paintable = g_value_get_object (value);
|
||||
|
||||
gtk_picture_set_paintable (GTK_PICTURE (picture), paintable);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
info_bar_response (GtkWidget *infobar, int response_id)
|
||||
{
|
||||
@@ -1213,7 +1182,7 @@ populate_flowbox (GtkWidget *flowbox)
|
||||
GtkWidget *child;
|
||||
int i;
|
||||
const char *resources[] = {
|
||||
"sunset.jpg", "portland-rose.jpg", "beach.jpg", "nyc.jpg"
|
||||
"sunset.jpg", "snowy.jpg", "portland-rose.jpg"
|
||||
};
|
||||
|
||||
if (GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (flowbox), "populated")))
|
||||
@@ -2071,8 +2040,6 @@ activate (GApplication *app)
|
||||
"on_page_combo_changed", (GCallback)on_page_combo_changed,
|
||||
"on_range_from_changed", (GCallback)on_range_from_changed,
|
||||
"on_range_to_changed", (GCallback)on_range_to_changed,
|
||||
"on_picture_drag_prepare", (GCallback)on_picture_drag_prepare,
|
||||
"on_picture_drop", (GCallback)on_picture_drop,
|
||||
"tab_close_cb", (GCallback)tab_close_cb,
|
||||
"increase_icon_size", (GCallback)increase_icon_size,
|
||||
"decrease_icon_size", (GCallback)decrease_icon_size,
|
||||
|
||||
@@ -115,8 +115,7 @@
|
||||
<gresource prefix="/org/gtk/WidgetFactory4">
|
||||
<file>gtk-logo.webm</file>
|
||||
<file>sunset.jpg</file>
|
||||
<file>snowy.jpg</file>
|
||||
<file>portland-rose.jpg</file>
|
||||
<file>nyc.jpg</file>
|
||||
<file>beach.jpg</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
||||
@@ -1051,9 +1051,22 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<property name="spacing">10</property>
|
||||
<property name="hexpand">1</property>
|
||||
<child>
|
||||
<object class="GtkFrame">
|
||||
<object class="GtkFrame" id="frame1">
|
||||
<property name="valign">start</property>
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="label" translatable="yes"><b>Video</b></property>
|
||||
<property name="use-markup">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVideo">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin-start">6</property>
|
||||
<property name="margin-end">6</property>
|
||||
<property name="margin-top">6</property>
|
||||
<property name="margin-bottom">6</property>
|
||||
<property name="autoplay">1</property>
|
||||
<property name="loop">1</property>
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/gtk-logo.webm</property>
|
||||
@@ -1062,78 +1075,66 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFrame">
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="label" translatable="yes"><b>Text Styles</b></property>
|
||||
<property name="use-markup">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="vexpand">1</property>
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="vexpand">1</property>
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<property name="propagate-natural-height">1</property>
|
||||
<property name="propagate-natural-width">1</property>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Large Title</property>
|
||||
<style><class name="large-title"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 1</property>
|
||||
<style><class name="title-1"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 2</property>
|
||||
<style><class name="title-2"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 3</property>
|
||||
<style><class name="title-3"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 4</property>
|
||||
<style><class name="title-4"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Heading</property>
|
||||
<style><class name="heading"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Body</property>
|
||||
<style><class name="body"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Caption Heading</property>
|
||||
<style><class name="caption-heading"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Caption</property>
|
||||
<style><class name="caption"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Large Title</property>
|
||||
<style><class name="large-title"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 1</property>
|
||||
<style><class name="title-1"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 2</property>
|
||||
<style><class name="title-2"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 3</property>
|
||||
<style><class name="title-3"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 4</property>
|
||||
<style><class name="title-4"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Heading</property>
|
||||
<style><class name="heading"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Body</property>
|
||||
<style><class name="body"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Caption Heading</property>
|
||||
<style><class name="caption-heading"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Caption</property>
|
||||
<style><class name="caption"/></style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@@ -1250,21 +1251,8 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="child">
|
||||
<object class="GtkPicture">
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/sunset.jpg</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<property name="actions">copy</property>
|
||||
<signal name="prepare" handler="on_picture_drag_prepare" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropTarget">
|
||||
<property name="actions">copy</property>
|
||||
<property name="formats">GdkTexture</property>
|
||||
<signal name="drop" handler="on_picture_drop" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<object class="GtkBox" id="box6">
|
||||
<property name="orientation">vertical</property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="tab">
|
||||
@@ -1277,21 +1265,8 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="child">
|
||||
<object class="GtkPicture">
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/nyc.jpg</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<property name="actions">copy</property>
|
||||
<signal name="prepare" handler="on_picture_drag_prepare" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropTarget">
|
||||
<property name="actions">copy</property>
|
||||
<property name="formats">GdkTexture</property>
|
||||
<signal name="drop" handler="on_picture_drop" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<object class="GtkBox" id="box7">
|
||||
<property name="orientation">vertical</property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="tab">
|
||||
@@ -1303,22 +1278,10 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="position">2</property>
|
||||
<property name="child">
|
||||
<object class="GtkPicture">
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/beach.jpg</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<property name="actions">copy</property>
|
||||
<signal name="prepare" handler="on_picture_drag_prepare" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropTarget">
|
||||
<property name="actions">copy</property>
|
||||
<property name="formats">GdkTexture</property>
|
||||
<signal name="drop" handler="on_picture_drop" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<object class="GtkBox" id="box8">
|
||||
<property name="orientation">vertical</property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="tab">
|
||||
@@ -1336,7 +1299,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="child">
|
||||
<object class="GtkBox" id="box8">
|
||||
<object class="GtkBox" id="box9">
|
||||
<property name="orientation">vertical</property>
|
||||
</object>
|
||||
</property>
|
||||
|
||||
@@ -13,7 +13,7 @@ devhelp = true
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable"
|
||||
|
||||
[theme]
|
||||
name = "basic"
|
||||
|
||||
@@ -13,7 +13,7 @@ devhelp = true
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable"
|
||||
|
||||
[theme]
|
||||
name = "basic"
|
||||
|
||||
@@ -14,7 +14,7 @@ search_index = true
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable"
|
||||
|
||||
[dependencies."cairo-1.0"]
|
||||
name = "Cairo"
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
expand_content_md_files = [
|
||||
]
|
||||
|
||||
if get_option('gtk_doc')
|
||||
gdk4_toml = configure_file(
|
||||
input: 'gdk4.toml.in',
|
||||
output: 'gdk4.toml',
|
||||
configuration: toml_conf,
|
||||
install: true,
|
||||
install_dir: docs_dir / 'gdk4',
|
||||
)
|
||||
gdk4_toml = configure_file(input: 'gdk4.toml.in', output: 'gdk4.toml', configuration: toml_conf)
|
||||
gdk4x11_toml = configure_file(input: 'gdk4-x11.toml.in', output: 'gdk4-x11.toml', configuration: toml_conf)
|
||||
gdk4wayland_toml = configure_file(input: 'gdk4-wayland.toml.in', output: 'gdk4-wayland.toml', configuration: toml_conf)
|
||||
|
||||
if get_option('gtk_doc')
|
||||
custom_target('gdk4-doc',
|
||||
input: [ gdk4_toml, gdk_gir[0] ],
|
||||
output: 'gdk4',
|
||||
@@ -32,14 +28,6 @@ if get_option('gtk_doc')
|
||||
)
|
||||
|
||||
if x11_enabled
|
||||
gdk4x11_toml = configure_file(
|
||||
input: 'gdk4-x11.toml.in',
|
||||
output: 'gdk4-x11.toml',
|
||||
configuration: toml_conf,
|
||||
install: true,
|
||||
install_dir: docs_dir / 'gdk4-x11',
|
||||
)
|
||||
|
||||
custom_target('gdk4-x11-doc',
|
||||
input: [ gdk4x11_toml, gdk_x11_gir[0] ],
|
||||
output: 'gdk4-x11',
|
||||
@@ -64,14 +52,6 @@ if get_option('gtk_doc')
|
||||
endif
|
||||
|
||||
if wayland_enabled
|
||||
gdk4wayland_toml = configure_file(
|
||||
input: 'gdk4-wayland.toml.in',
|
||||
output: 'gdk4-wayland.toml',
|
||||
configuration: toml_conf,
|
||||
install: true,
|
||||
install_dir: docs_dir / 'gdk4-wayland',
|
||||
)
|
||||
|
||||
custom_target('gdk4-wayland-doc',
|
||||
input: [ gdk4wayland_toml, gdk_wayland_gir[0] ],
|
||||
output: 'gdk4-wayland',
|
||||
|
||||
@@ -3,14 +3,11 @@
|
||||
|
||||
// A map between namespaces and base URLs for their online documentation
|
||||
baseURLs = [
|
||||
[ 'GLib', 'https://docs.gtk.org/glib/' ],
|
||||
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
|
||||
[ 'Gio', 'https://docs.gtk.org/gio/' ],
|
||||
[ 'Gdk', 'https://docs.gtk.org/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://docs.gtk.org/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://docs.gtk.org/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://docs.gtk.org/gsk4/' ],
|
||||
[ 'Gtk', 'https://docs.gtk.org/gtk4/' ],
|
||||
[ 'Pango', 'https://docs.gtk.org/Pango/' ],
|
||||
[ 'PangoCairo', 'https://docs.gtk.org/PangoCairo/' ],
|
||||
[ 'Gdk', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://gnome.pages.gitlab.gnome.org/gtk/gsk4/' ],
|
||||
[ 'Gtk', 'https://gnome.pages.gitlab.gnome.org/gtk/gtk4/' ],
|
||||
[ 'Pango', 'https://gnome.pages/gitlab.gnome.org/pango/pango/' ],
|
||||
[ 'PangoCairo', 'https://gnome.pages.gitlab.gnome.org/pango/pangocairo/' ],
|
||||
]
|
||||
|
||||
@@ -14,7 +14,7 @@ search_index = true
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable/"
|
||||
|
||||
[dependencies."Graphene-1.0"]
|
||||
name = "Graphene"
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
if get_option('gtk_doc')
|
||||
gsk4_toml = configure_file(
|
||||
input: 'gsk4.toml.in',
|
||||
output: 'gsk4.toml',
|
||||
configuration: toml_conf,
|
||||
install: true,
|
||||
install_dir: docs_dir / 'gsk4',
|
||||
)
|
||||
gsk4_toml = configure_file(input: 'gsk4.toml.in', output: 'gsk4.toml', configuration: toml_conf)
|
||||
|
||||
if get_option('gtk_doc')
|
||||
custom_target('gsk4-doc',
|
||||
input: [ gsk4_toml, gsk_gir[0] ],
|
||||
output: 'gsk4',
|
||||
|
||||
@@ -3,14 +3,11 @@
|
||||
|
||||
// A map between namespaces and base URLs for their online documentation
|
||||
baseURLs = [
|
||||
[ 'GLib', 'https://docs.gtk.org/glib/' ],
|
||||
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
|
||||
[ 'Gio', 'https://docs.gtk.org/gio/' ],
|
||||
[ 'Gdk', 'https://docs.gtk.org/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://docs.gtk.org/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://docs.gtk.org/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://docs.gtk.org/gsk4/' ],
|
||||
[ 'Gtk', 'https://docs.gtk.org/gtk4/' ],
|
||||
[ 'Pango', 'https://docs.gtk.org/Pango/' ],
|
||||
[ 'PangoCairo', 'https://docs.gtk.org/PangoCairo/' ],
|
||||
[ 'Gdk', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://gnome.pages.gitlab.gnome.org/gtk/gsk4/' ],
|
||||
[ 'Gtk', 'https://gnome.pages.gitlab.gnome.org/gtk/gtk4/' ],
|
||||
[ 'Pango', 'https://gnome.pages/gitlab.gnome.org/pango/pango/' ],
|
||||
[ 'PangoCairo', 'https://gnome.pages.gitlab.gnome.org/pango/pangocairo/' ],
|
||||
]
|
||||
|
||||
@@ -162,8 +162,6 @@ done with
|
||||
|caret-color|[CSS Basic User Interface Level 3](https://www.w3.org/TR/css3-ui/#caret-color) | CSS allows an auto value |
|
||||
|-gtk-secondary-caret-color|[Color](https://www.w3.org/TR/css-color-3/#valuea-def-color) | used for the secondary caret in bidirectional text |
|
||||
|letter-spacing| [CSS Text Level 3](https://www.w3.org/TR/css3-text/#letter-spacing) | |
|
||||
|text-transform| [CSS Text Level 3](https://www.w3.org/TR/css-text-3/#text-transform-property) | CSS allows full-width and full-size-kana. Since 4.6 |
|
||||
|line-height| [CSS Inline Layout Level 3](https://www.w3.org/TR/css-inline-3/#line-height-property) | Since 4.6 |
|
||||
|text-decoration-line| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-line-property) | |
|
||||
|text-decoration-color| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-color-property) | |
|
||||
|text-decoration-style| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-style-property) | CSS allows dashed and dotted |
|
||||
|
||||
@@ -14,7 +14,7 @@ search_index = true
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable"
|
||||
|
||||
[dependencies."Graphene-1.0"]
|
||||
name = "Graphene"
|
||||
|
||||
@@ -137,14 +137,6 @@ capture phase, and key bindings locally, during the target phase.
|
||||
Under the hood, all shortcuts are represented as instances of `GtkShortcut`,
|
||||
and they are managed by `GtkShortcutController`.
|
||||
|
||||
## Text input
|
||||
|
||||
When actual text input is needed (i.e. not just keyboard shortcuts),
|
||||
input method support can be added to a widget by connecting an input
|
||||
method context and listening to its `::commit` signal. To create a new
|
||||
input method context, use gtk_im_multicontext_new(), to provide it with
|
||||
input, use gtk_event_controller_key_set_im_context().
|
||||
|
||||
## Event controllers and gestures
|
||||
|
||||
Event controllers are standalone objects that can perform
|
||||
|
||||
@@ -27,15 +27,9 @@ expand_content_md_files = [
|
||||
'visual_index.md'
|
||||
]
|
||||
|
||||
if get_option('gtk_doc')
|
||||
gtk4_toml = configure_file(
|
||||
input: 'gtk4.toml.in',
|
||||
output: 'gtk4.toml',
|
||||
configuration: toml_conf,
|
||||
install: true,
|
||||
install_dir: docs_dir / 'gtk4',
|
||||
)
|
||||
gtk4_toml = configure_file(input: 'gtk4.toml.in', output: 'gtk4.toml', configuration: toml_conf)
|
||||
|
||||
if get_option('gtk_doc')
|
||||
custom_target('gtk4-doc',
|
||||
input: [ gtk4_toml, gtk_gir[0] ],
|
||||
output: 'gtk4',
|
||||
|
||||
@@ -3,14 +3,11 @@
|
||||
|
||||
// A map between namespaces and base URLs for their online documentation
|
||||
baseURLs = [
|
||||
[ 'GLib', 'https://docs.gtk.org/glib/' ],
|
||||
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
|
||||
[ 'Gio', 'https://docs.gtk.org/gio/' ],
|
||||
[ 'Gdk', 'https://docs.gtk.org/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://docs.gtk.org/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://docs.gtk.org/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://docs.gtk.org/gsk4/' ],
|
||||
[ 'Gtk', 'https://docs.gtk.org/gtk4/' ],
|
||||
[ 'Pango', 'https://docs.gtk.org/Pango/' ],
|
||||
[ 'PangoCairo', 'https://docs.gtk.org/PangoCairo/' ],
|
||||
[ 'Gdk', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://gnome.pages.gitlab.gnome.org/gtk/gsk4/' ],
|
||||
[ 'Gtk', 'https://gnome.pages.gitlab.gnome.org/gtk/gtk4/' ],
|
||||
[ 'Pango', 'https://gnome.pages/gitlab.gnome.org/pango/pango/' ],
|
||||
[ 'PangoCairo', 'https://gnome.pages.gitlab.gnome.org/pango/pangocairo/' ],
|
||||
]
|
||||
|
||||
@@ -14,19 +14,14 @@ instructions, binary downloads, etc, can be found
|
||||
The Win32 GDK backend can be influenced with some additional environment
|
||||
variables.
|
||||
|
||||
### GDK_WIN32_TABLET_INPUT_API
|
||||
### GDK_IGNORE_WINTAB
|
||||
|
||||
If this variable is set, it determines the API that GTK uses for tablet support.
|
||||
The possible values are:
|
||||
If this variable is set, GTK doesn't use the Wintab API for tablet support.
|
||||
|
||||
`none`
|
||||
: Disables tablet support
|
||||
### GDK_USE_WINTAB
|
||||
|
||||
`wintab`
|
||||
: Use the Wintab API
|
||||
|
||||
`winpointer`
|
||||
: Use the Windows Pointer Input Stack API. This is the default.
|
||||
If this variable is set, GTK uses the Wintab API for tablet support.
|
||||
This is the default.
|
||||
|
||||
## Windows-specific handling of cursors
|
||||
|
||||
|
||||
@@ -5,10 +5,6 @@ gidocgen = find_program('gi-docgen', required: get_option('gtk_doc'))
|
||||
|
||||
docs_dir = gtk_datadir / 'doc'
|
||||
|
||||
if get_option('gtk_doc') and not build_gir
|
||||
error('API reference requires introspection.')
|
||||
endif
|
||||
|
||||
subdir('gdk')
|
||||
subdir('gsk')
|
||||
subdir('gtk')
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include <gdk/gdktextureprivate.h>
|
||||
#include "gdk-private.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
@@ -464,7 +463,7 @@ gdk_broadway_display_flush_in_idle (GdkDisplay *display)
|
||||
if (broadway_display->idle_flush_id == 0)
|
||||
{
|
||||
broadway_display->idle_flush_id = g_idle_add (flush_idle, g_object_ref (display));
|
||||
gdk_source_set_static_name_by_id (broadway_display->idle_flush_id, "[gtk] flush_idle");
|
||||
g_source_set_name_by_id (broadway_display->idle_flush_id, "[gtk] flush_idle");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,11 +57,4 @@ guint gdk_parse_debug_var (const char *variable,
|
||||
# define g_memdup2(mem,size) g_memdup((mem),(size))
|
||||
#endif
|
||||
|
||||
void gdk_source_set_static_name_by_id (guint tag,
|
||||
const char *name);
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2, 69, 1)
|
||||
#define g_source_set_static_name(source, name) g_source_set_name ((source), (name))
|
||||
#endif
|
||||
|
||||
#endif /* __GDK__PRIVATE_H__ */
|
||||
|
||||
16
gdk/gdk.c
16
gdk/gdk.c
@@ -132,7 +132,7 @@ static const GdkDebugKey gdk_debug_keys[] = {
|
||||
{ "gl-wgl", GDK_DEBUG_GL_WGL, "Use WGL on Windows" },
|
||||
{ "vulkan-disable", GDK_DEBUG_VULKAN_DISABLE, "Disable Vulkan support" },
|
||||
{ "vulkan-validate", GDK_DEBUG_VULKAN_VALIDATE, "Load the Vulkan validation layer" },
|
||||
{ "default-settings",GDK_DEBUG_DEFAULT_SETTINGS, "Force default values for xsettings", TRUE },
|
||||
{ "default-settings",GDK_DEBUG_DEFAULT_SETTINGS, "Force default values for xsettings" },
|
||||
};
|
||||
|
||||
|
||||
@@ -414,17 +414,3 @@ gdk_find_base_dir (const char *text,
|
||||
return dir;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_source_set_static_name_by_id (guint tag,
|
||||
const char *name)
|
||||
{
|
||||
GSource *source;
|
||||
|
||||
g_return_if_fail (tag > 0);
|
||||
|
||||
source = g_main_context_find_source_by_id (NULL, tag);
|
||||
if (source == NULL)
|
||||
return;
|
||||
|
||||
g_source_set_static_name (source, name);
|
||||
}
|
||||
|
||||
@@ -635,7 +635,7 @@ gdk_clipboard_read_internal (GdkClipboard *clipboard,
|
||||
/**
|
||||
* gdk_clipboard_read_async:
|
||||
* @clipboard: a `GdkClipboard`
|
||||
* @mime_types: (array zero-terminated=1): a %NULL-terminated array of mime types to choose from
|
||||
* @mime_types: a %NULL-terminated array of mime types to choose from
|
||||
* @io_priority: the I/O priority of the request
|
||||
* @cancellable: (nullable): optional `GCancellable` object
|
||||
* @callback: (scope async): callback to call when the request is satisfied
|
||||
@@ -1253,15 +1253,9 @@ gdk_clipboard_set_content (GdkClipboard *clipboard,
|
||||
* @...: value contents conforming to @type
|
||||
*
|
||||
* Sets the clipboard to contain the value collected from the given varargs.
|
||||
*
|
||||
* Values should be passed the same way they are passed to other value
|
||||
* collecting APIs, such as [`method@GObject.Object.set`] or
|
||||
* [`id@g_signal_emit`].
|
||||
*
|
||||
* ```c
|
||||
* gdk_clipboard_set (clipboard, GTK_TYPE_STRING, "Hello World");
|
||||
*
|
||||
* gdk_clipboard_set (clipboard, GDK_TYPE_TEXTURE, some_texture);
|
||||
* gdk_clipboard_set (clipboard, GTK_TYPE_TEXT_BUFFER, buffer);
|
||||
* ```
|
||||
*/
|
||||
void
|
||||
|
||||
@@ -553,8 +553,6 @@ gdk_content_deserialize_async (GInputStream *stream,
|
||||
Deserializer *deserializer;
|
||||
|
||||
g_return_if_fail (G_IS_INPUT_STREAM (stream));
|
||||
g_return_if_fail (mime_type != NULL);
|
||||
g_return_if_fail (G_TYPE_IS_VALUE_TYPE (type));
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
@@ -593,10 +591,7 @@ gdk_content_deserialize_finish (GAsyncResult *result,
|
||||
g_return_val_if_fail (GDK_IS_CONTENT_DESERIALIZER (result), FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
deserializer = GDK_CONTENT_DESERIALIZER (result);
|
||||
if (G_VALUE_TYPE (value) == 0)
|
||||
g_value_init (value, G_VALUE_TYPE (&deserializer->value));
|
||||
else
|
||||
g_return_val_if_fail (G_VALUE_HOLDS (value, G_VALUE_TYPE (&deserializer->value)), FALSE);
|
||||
g_return_val_if_fail (G_VALUE_HOLDS (value, G_VALUE_TYPE (&deserializer->value)), FALSE);
|
||||
|
||||
if (deserializer->error)
|
||||
{
|
||||
|
||||
@@ -179,76 +179,6 @@ gdk_content_formats_new_for_gtype (GType type)
|
||||
return gdk_content_formats_new_take (data, 1, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_content_formats_parse:
|
||||
* @string: the string to parse
|
||||
*
|
||||
* Parses the given @string into `GdkContentFormats` and
|
||||
* returns the formats.
|
||||
*
|
||||
* Strings printed via [method@Gdk.ContentFormats.to_string]
|
||||
* can be read in again successfully using this function.
|
||||
*
|
||||
* If @string does not describe valid content formats, %NULL
|
||||
* is returned.
|
||||
*
|
||||
* Returns: (nullable): the content formats if @string is valid
|
||||
*
|
||||
* Since: 4.4
|
||||
*/
|
||||
GdkContentFormats *
|
||||
gdk_content_formats_parse (const char *string)
|
||||
{
|
||||
GdkContentFormatsBuilder *builder;
|
||||
char **split;
|
||||
gsize i;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
|
||||
split = g_strsplit_set (string, "\t\n\f\r ", -1); /* same as g_ascii_isspace() */
|
||||
builder = gdk_content_formats_builder_new ();
|
||||
|
||||
/* first the GTypes */
|
||||
for (i = 0; split[i] != NULL; i++)
|
||||
{
|
||||
GType type;
|
||||
|
||||
if (split[i][0] == 0)
|
||||
continue;
|
||||
|
||||
type = g_type_from_name (split[i]);
|
||||
if (type != 0)
|
||||
gdk_content_formats_builder_add_gtype (builder, type);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* then the mime types */
|
||||
for (; split[i] != NULL; i++)
|
||||
{
|
||||
const char *mime_type;
|
||||
|
||||
if (split[i][0] == 0)
|
||||
continue;
|
||||
|
||||
mime_type = gdk_intern_mime_type (split[i]);
|
||||
if (mime_type)
|
||||
gdk_content_formats_builder_add_mime_type (builder, mime_type);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (split[i] != NULL)
|
||||
{
|
||||
g_strfreev (split);
|
||||
gdk_content_formats_builder_unref (builder);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_strfreev (split);
|
||||
return gdk_content_formats_builder_free_to_formats (builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_content_formats_ref:
|
||||
* @formats: a `GdkContentFormats`
|
||||
@@ -297,8 +227,10 @@ gdk_content_formats_unref (GdkContentFormats *formats)
|
||||
*
|
||||
* Prints the given @formats into a string for human consumption.
|
||||
*
|
||||
* The result of this function can later be parsed with
|
||||
* [func@Gdk.ContentFormats.parse].
|
||||
* This is meant for debugging and logging.
|
||||
*
|
||||
* The form of the representation may change at any time and is
|
||||
* not guaranteed to stay identical.
|
||||
*/
|
||||
void
|
||||
gdk_content_formats_print (GdkContentFormats *formats,
|
||||
@@ -309,18 +241,20 @@ gdk_content_formats_print (GdkContentFormats *formats,
|
||||
g_return_if_fail (formats != NULL);
|
||||
g_return_if_fail (string != NULL);
|
||||
|
||||
g_string_append (string, "{ ");
|
||||
for (i = 0; i < formats->n_gtypes; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
g_string_append (string, " ");
|
||||
g_string_append (string, ", ");
|
||||
g_string_append (string, g_type_name (formats->gtypes[i]));
|
||||
}
|
||||
for (i = 0; i < formats->n_mime_types; i++)
|
||||
{
|
||||
if (i > 0 || formats->n_gtypes > 0)
|
||||
g_string_append (string, " ");
|
||||
g_string_append (string, ", ");
|
||||
g_string_append (string, formats->mime_types[i]);
|
||||
}
|
||||
g_string_append (string, " }");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -329,8 +263,6 @@ gdk_content_formats_print (GdkContentFormats *formats,
|
||||
*
|
||||
* Prints the given @formats into a human-readable string.
|
||||
*
|
||||
* The resulting string can be parsed with [func@Gdk.ContentFormats.parse].
|
||||
*
|
||||
* This is a small wrapper around [method@Gdk.ContentFormats.print]
|
||||
* to help when debugging.
|
||||
*
|
||||
|
||||
@@ -40,8 +40,6 @@ GdkContentFormats * gdk_content_formats_new (const char
|
||||
guint n_mime_types);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkContentFormats * gdk_content_formats_new_for_gtype (GType type);
|
||||
GDK_AVAILABLE_IN_4_4
|
||||
GdkContentFormats * gdk_content_formats_parse (const char *string);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkContentFormats * gdk_content_formats_ref (GdkContentFormats *formats);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
||||
@@ -80,7 +80,7 @@ gdk_content_provider_value_get_value (GdkContentProvider *provider,
|
||||
{
|
||||
GdkContentProviderValue *content = GDK_CONTENT_PROVIDER_VALUE (provider);
|
||||
|
||||
if (G_VALUE_HOLDS (&content->value, G_VALUE_TYPE (value)))
|
||||
if (G_VALUE_HOLDS (value, G_VALUE_TYPE (&content->value)))
|
||||
{
|
||||
g_value_copy (&content->value, value);
|
||||
return TRUE;
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkframeclockprivate.h"
|
||||
#include "gdk.h"
|
||||
#include "gdk-private.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
@@ -308,15 +307,12 @@ maybe_start_idle (GdkFrameClockIdle *clock_idle,
|
||||
|
||||
if (priv->flush_idle_id == 0 && RUN_FLUSH_IDLE (priv))
|
||||
{
|
||||
GSource *source;
|
||||
|
||||
priv->flush_idle_id = g_timeout_add_full (GDK_PRIORITY_EVENTS + 1,
|
||||
min_interval,
|
||||
gdk_frame_clock_flush_idle,
|
||||
g_object_ref (clock_idle),
|
||||
(GDestroyNotify) g_object_unref);
|
||||
source = g_main_context_find_source_by_id (NULL, priv->flush_idle_id);
|
||||
g_source_set_static_name (source, "[gtk] gdk_frame_clock_flush_idle");
|
||||
g_source_set_name_by_id (priv->flush_idle_id, "[gtk] gdk_frame_clock_flush_idle");
|
||||
}
|
||||
|
||||
if (!priv->in_paint_idle &&
|
||||
@@ -328,7 +324,7 @@ maybe_start_idle (GdkFrameClockIdle *clock_idle,
|
||||
gdk_frame_clock_paint_idle,
|
||||
g_object_ref (clock_idle),
|
||||
(GDestroyNotify) g_object_unref);
|
||||
gdk_source_set_static_name_by_id (priv->paint_idle_id, "[gtk] gdk_frame_clock_paint_idle");
|
||||
g_source_set_name_by_id (priv->paint_idle_id, "[gtk] gdk_frame_clock_paint_idle");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -856,8 +856,6 @@ gdk_gl_context_set_is_legacy (GdkGLContext *context,
|
||||
* is not, this function will return %FALSE.
|
||||
*
|
||||
* Returns: %TRUE if the two GL contexts are compatible.
|
||||
*
|
||||
* Since: 4.4
|
||||
*/
|
||||
gboolean
|
||||
gdk_gl_context_is_shared (GdkGLContext *self,
|
||||
|
||||
@@ -70,17 +70,17 @@ typedef enum {
|
||||
* snapshot at or 0 if none. This is purely a hint. The object must still
|
||||
* be able to render at any size.
|
||||
* @get_intrinsic_aspect_ratio: The preferred aspect ratio for this object
|
||||
* or 0 if none. If both [vfunc@Gdk.Paintable.get_intrinsic_width]
|
||||
* and [vfunc@Gdk.Paintable.get_intrinsic_height] return non-zero
|
||||
* or 0 if none. If both [vfunc@Gdk.PaintableInterface.get_intrinsic_width]
|
||||
* and [vfunc@Gdk.PaintableInterface.get_intrinsic_height] return non-zero
|
||||
* values, this function should return the aspect ratio computed from those.
|
||||
*
|
||||
* The list of functions that can be implemented for the `GdkPaintable`
|
||||
* interface.
|
||||
*
|
||||
* Note that apart from the [vfunc@Gdk.Paintable.snapshot] function,
|
||||
* Note that apart from the [vfunc@Gdk.PaintableInterface.snapshot] function,
|
||||
* no virtual function of this interface is mandatory to implement, though it
|
||||
* is a good idea to implement [vfunc@Gdk.Paintable.get_current_image]
|
||||
* for non-static paintables and [vfunc@Gdk.Paintable.get_flags] if the
|
||||
* is a good idea to implement [vfunc@Gdk.PaintableInterface.get_current_image]
|
||||
* for non-static paintables and [vfunc@Gdk.PaintableInterface.get_flags] if the
|
||||
* image is not dynamic as the default implementation returns no flags and
|
||||
* that will make the implementation likely quite slow.
|
||||
*/
|
||||
|
||||
@@ -78,13 +78,6 @@ gdk_toplevel_default_show_window_menu (GdkToplevel *toplevel,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_toplevel_default_titlebar_gesture (GdkToplevel *toplevel,
|
||||
GdkTitlebarGesture gesture)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_toplevel_default_supports_edge_constraints (GdkToplevel *toplevel)
|
||||
{
|
||||
@@ -121,7 +114,6 @@ gdk_toplevel_default_init (GdkToplevelInterface *iface)
|
||||
iface->supports_edge_constraints = gdk_toplevel_default_supports_edge_constraints;
|
||||
iface->inhibit_system_shortcuts = gdk_toplevel_default_inhibit_system_shortcuts;
|
||||
iface->restore_system_shortcuts = gdk_toplevel_default_restore_system_shortcuts;
|
||||
iface->titlebar_gesture = gdk_toplevel_default_titlebar_gesture;
|
||||
|
||||
/**
|
||||
* GdkToplevel:state: (attributes org.gtk.Property.get=gdk_toplevel_get_state)
|
||||
@@ -724,13 +716,3 @@ gdk_toplevel_begin_move (GdkToplevel *toplevel,
|
||||
x, y,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_toplevel_titlebar_gesture (GdkToplevel *toplevel,
|
||||
GdkTitlebarGesture gesture)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), FALSE);
|
||||
|
||||
return GDK_TOPLEVEL_GET_IFACE (toplevel)->titlebar_gesture (toplevel,
|
||||
gesture);
|
||||
}
|
||||
|
||||
@@ -115,13 +115,6 @@ typedef enum
|
||||
GDK_TOPLEVEL_STATE_LEFT_RESIZABLE = 1 << 15
|
||||
} GdkToplevelState;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GDK_TITLEBAR_GESTURE_DOUBLE_CLICK = 1,
|
||||
GDK_TITLEBAR_GESTURE_RIGHT_CLICK = 2,
|
||||
GDK_TITLEBAR_GESTURE_MIDDLE_CLICK = 3
|
||||
} GdkTitlebarGesture;
|
||||
|
||||
|
||||
#define GDK_TYPE_TOPLEVEL (gdk_toplevel_get_type ())
|
||||
|
||||
@@ -203,10 +196,6 @@ void gdk_toplevel_begin_move (GdkToplevel *toplevel,
|
||||
double y,
|
||||
guint32 timestamp);
|
||||
|
||||
GDK_AVAILABLE_IN_4_4
|
||||
gboolean gdk_toplevel_titlebar_gesture (GdkToplevel *toplevel,
|
||||
GdkTitlebarGesture gesture);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_TOPLEVEL_H__ */
|
||||
|
||||
@@ -38,8 +38,6 @@ struct _GdkToplevelInterface
|
||||
double x,
|
||||
double y,
|
||||
guint32 timestamp);
|
||||
gboolean (* titlebar_gesture) (GdkToplevel *toplevel,
|
||||
GdkTitlebarGesture gesture);
|
||||
};
|
||||
|
||||
typedef enum
|
||||
|
||||
@@ -94,14 +94,6 @@
|
||||
*/
|
||||
#define GDK_VERSION_4_4 (G_ENCODE_VERSION (4, 4))
|
||||
|
||||
/**
|
||||
* GDK_VERSION_4_6:
|
||||
*
|
||||
* A macro that evaluates to the 4.6 version of GDK, in a format
|
||||
* that can be used by the C pre-processor.
|
||||
*/
|
||||
#define GDK_VERSION_4_6 (G_ENCODE_VERSION (4, 6))
|
||||
|
||||
|
||||
/* evaluates to the current stable version; for development cycles,
|
||||
* this means the next stable target, with a hard backstop to the
|
||||
@@ -229,18 +221,4 @@
|
||||
# define GDK_DEPRECATED_IN_4_4_FOR(f) _GDK_EXTERN
|
||||
#endif
|
||||
|
||||
#if GDK_VERSION_MAX_ALLOWED < GDK_VERSION_4_6
|
||||
# define GDK_AVAILABLE_IN_4_6 GDK_UNAVAILABLE(4, 6)
|
||||
#else
|
||||
# define GDK_AVAILABLE_IN_4_6 _GDK_EXTERN
|
||||
#endif
|
||||
|
||||
#if GDK_VERSION_MIN_REQUIRED >= GDK_VERSION_4_6
|
||||
# define GDK_DEPRECATED_IN_4_6 GDK_DEPRECATED
|
||||
# define GDK_DEPRECATED_IN_4_6_FOR(f) GDK_DEPRECATED_FOR(f)
|
||||
#else
|
||||
# define GDK_DEPRECATED_IN_4_6 _GDK_EXTERN
|
||||
# define GDK_DEPRECATED_IN_4_6_FOR(f) _GDK_EXTERN
|
||||
#endif
|
||||
|
||||
#endif /* __GDK_VERSION_MACROS_H__ */
|
||||
|
||||
@@ -117,104 +117,104 @@ gdk_vulkan_strerror (VkResult result)
|
||||
switch (result)
|
||||
{
|
||||
case VK_SUCCESS:
|
||||
return "Command successfully completed. (VK_SUCCESS)";
|
||||
return "Command successfully completed.";
|
||||
case VK_NOT_READY:
|
||||
return "A fence or query has not yet completed. (VK_NOT_READY)";
|
||||
return "A fence or query has not yet completed.";
|
||||
case VK_TIMEOUT:
|
||||
return "A wait operation has not completed in the specified time. (VK_TIMEOUT)";
|
||||
return "A wait operation has not completed in the specified time.";
|
||||
case VK_EVENT_SET:
|
||||
return "An event is signaled. (VK_EVENT_SET)";
|
||||
return "An event is signaled.";
|
||||
case VK_EVENT_RESET:
|
||||
return "An event is unsignaled. (VK_EVENT_RESET)";
|
||||
return "An event is unsignaled.";
|
||||
case VK_INCOMPLETE:
|
||||
return "A return array was too small for the result. (VK_INCOMPLETE)";
|
||||
return "A return array was too small for the result.";
|
||||
case VK_SUBOPTIMAL_KHR:
|
||||
return "A swapchain no longer matches the surface properties exactly, but can still be used to present to the surface successfully. (VK_SUBOPTIMAL_KHR)";
|
||||
return "A swapchain no longer matches the surface properties exactly, but can still be used to present to the surface successfully.";
|
||||
case VK_ERROR_OUT_OF_HOST_MEMORY:
|
||||
return "A host memory allocation has failed. (VK_ERROR_OUT_OF_HOST_MEMORY)";
|
||||
return "A host memory allocation has failed.";
|
||||
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
|
||||
return "A device memory allocation has failed. (VK_ERROR_OUT_OF_DEVICE_MEMORY)";
|
||||
return "A device memory allocation has failed.";
|
||||
case VK_ERROR_INITIALIZATION_FAILED:
|
||||
return "Initialization of an object could not be completed for implementation-specific reasons. (VK_ERROR_INITIALIZATION_FAILED)";
|
||||
return "Initialization of an object could not be completed for implementation-specific reasons.";
|
||||
case VK_ERROR_DEVICE_LOST:
|
||||
return "The logical or physical device has been lost. (VK_ERROR_DEVICE_LOST)";
|
||||
return "The logical or physical device has been lost.";
|
||||
case VK_ERROR_MEMORY_MAP_FAILED:
|
||||
return "Mapping of a memory object has failed. (VK_ERROR_MEMORY_MAP_FAILED)";
|
||||
return "Mapping of a memory object has failed.";
|
||||
case VK_ERROR_LAYER_NOT_PRESENT:
|
||||
return "A requested layer is not present or could not be loaded. (VK_ERROR_LAYER_NOT_PRESENT)";
|
||||
return "A requested layer is not present or could not be loaded.";
|
||||
case VK_ERROR_EXTENSION_NOT_PRESENT:
|
||||
return "A requested extension is not supported. (VK_ERROR_EXTENSION_NOT_PRESENT)";
|
||||
return "A requested extension is not supported.";
|
||||
case VK_ERROR_FEATURE_NOT_PRESENT:
|
||||
return "A requested feature is not supported. (VK_ERROR_FEATURE_NOT_PRESENT)";
|
||||
return "A requested feature is not supported.";
|
||||
case VK_ERROR_INCOMPATIBLE_DRIVER:
|
||||
return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible for implementation-specific reasons. (VK_ERROR_INCOMPATIBLE_DRIVER)";
|
||||
return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible for implementation-specific reasons.";
|
||||
case VK_ERROR_TOO_MANY_OBJECTS:
|
||||
return "Too many objects of the type have already been created. (VK_ERROR_TOO_MANY_OBJECTS)";
|
||||
return "Too many objects of the type have already been created.";
|
||||
case VK_ERROR_FORMAT_NOT_SUPPORTED:
|
||||
return "A requested format is not supported on this device. (VK_ERROR_FORMAT_NOT_SUPPORTED)";
|
||||
return "A requested format is not supported on this device.";
|
||||
#if VK_HEADER_VERSION >= 24
|
||||
case VK_ERROR_FRAGMENTED_POOL:
|
||||
return "A requested pool allocation has failed due to fragmentation of the pool’s memory. (VK_ERROR_FRAGMENTED_POOL)";
|
||||
return "A requested pool allocation has failed due to fragmentation of the pool’s memory.";
|
||||
#endif
|
||||
case VK_ERROR_SURFACE_LOST_KHR:
|
||||
return "A surface is no longer available. (VK_ERROR_SURFACE_LOST_KHR)";
|
||||
return "A surface is no longer available.";
|
||||
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
|
||||
return "The requested window is already in use by Vulkan or another API in a manner which prevents it from being used again. (VK_ERROR_NATIVE_WINDOW_IN_USE_KHR)";
|
||||
return "The requested window is already in use by Vulkan or another API in a manner which prevents it from being used again.";
|
||||
case VK_ERROR_OUT_OF_DATE_KHR:
|
||||
return "A surface has changed in such a way that it is no longer compatible with the swapchain. (VK_ERROR_OUT_OF_DATE_KHR)";
|
||||
return "A surface has changed in such a way that it is no longer compatible with the swapchain.";
|
||||
case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
|
||||
return "The display used by a swapchain does not use the same presentable image layout, or is incompatible in a way that prevents sharing an image. (VK_ERROR_INCOMPATIBLE_DISPLAY_KHR)";
|
||||
return "The display used by a swapchain does not use the same presentable image layout, or is incompatible in a way that prevents sharing an image.";
|
||||
case VK_ERROR_VALIDATION_FAILED_EXT:
|
||||
return "The application caused the validation layer to fail. (VK_ERROR_VALIDATION_FAILED_EXT)";
|
||||
return "The application caused the validation layer to fail.";
|
||||
case VK_ERROR_INVALID_SHADER_NV:
|
||||
return "One or more shaders failed to compile or link. (VK_ERROR_INVALID_SHADER_NV)";
|
||||
return "One or more shaders failed to compile or link.";
|
||||
#if VK_HEADER_VERSION >= 39
|
||||
case VK_ERROR_OUT_OF_POOL_MEMORY_KHR:
|
||||
return "A pool memory allocation has failed. (VK_ERROR_OUT_OF_POOL_MEMORY_KHR)";
|
||||
return "A pool memory allocation has failed.";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 54
|
||||
case VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR:
|
||||
return "An external handle is not a valid handle of the specified type. (VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR)";
|
||||
return "An external handle is not a valid handle of the specified type.";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 64
|
||||
case VK_ERROR_NOT_PERMITTED_EXT:
|
||||
return "The caller does not have sufficient privileges. (VK_ERROR_NOT_PERMITTED_EXT)";
|
||||
return "The caller does not have sufficient privileges.";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 72
|
||||
case VK_ERROR_FRAGMENTATION_EXT:
|
||||
return "A descriptor pool creation has failed due to fragmentation. (VK_ERROR_FRAGMENTATION_EXT)";
|
||||
return "A descriptor pool creation has failed due to fragmentation";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 89
|
||||
case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
|
||||
return "Invalid DRM format modifier plane layout (VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT)";
|
||||
return "Invalid DRM format modifier plane layout";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 97
|
||||
case VK_ERROR_INVALID_DEVICE_ADDRESS_EXT:
|
||||
return "Invalid device address (VK_ERROR_INVALID_DEVICE_ADDRESS_EXT)";
|
||||
return "Invalid device address";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 105
|
||||
case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT:
|
||||
return "An operation on a swapchain created with VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT failed as it did not have exclusive full-screen access. (VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)";
|
||||
return "An operation on a swapchain created with VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT failed as it did not have exclusive full-screen access.";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 131
|
||||
case VK_ERROR_UNKNOWN:
|
||||
return "An unknown error has occurred; either the application has provided invalid input, or an implementation failure has occurred. (VK_ERROR_UNKNOWN)";
|
||||
return "An unknown error has occurred; either the application has provided invalid input, or an implementation failure has occurred.";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 135
|
||||
#if VK_HEADER_VERSION < 162
|
||||
case VK_ERROR_INCOMPATIBLE_VERSION_KHR:
|
||||
return "This error was removed by the Vulkan gods. (VK_ERROR_INCOMPATIBLE_VERSION_KHR)";
|
||||
return "This error was removed by the Vulkan gods.";
|
||||
#endif
|
||||
case VK_THREAD_IDLE_KHR:
|
||||
return "A deferred operation is not complete but there is currently no work for this thread to do at the time of this call. (VK_THREAD_IDLE_KHR)";
|
||||
return "A deferred operation is not complete but there is currently no work for this thread to do at the time of this call.";
|
||||
case VK_THREAD_DONE_KHR:
|
||||
return "A deferred operation is not complete but there is no work remaining to assign to additional threads. (VK_THREAD_DONE_KHR)";
|
||||
return "A deferred operation is not complete but there is no work remaining to assign to additional threads.";
|
||||
case VK_OPERATION_DEFERRED_KHR:
|
||||
return "A deferred operation was requested and at least some of the work was deferred. (VK_OPERATION_DEFERRED_KHR)";
|
||||
return "A deferred operation was requested and at least some of the work was deferred.";
|
||||
case VK_OPERATION_NOT_DEFERRED_KHR:
|
||||
return "A deferred operation was requested and no operations were deferred. (VK_OPERATION_NOT_DEFERRED_KHR)";
|
||||
return "A deferred operation was requested and no operations were deferred.";
|
||||
case VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT:
|
||||
return "A requested pipeline creation would have required compilation, but the application requested compilation to not be performed. (VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT)";
|
||||
return "A requested pipeline creation would have required compilation, but the application requested compilation to not be performed.";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION < 140
|
||||
case VK_RESULT_RANGE_SIZE:
|
||||
|
||||
@@ -197,7 +197,7 @@ gdk_display_link_source_new (void)
|
||||
gdk_display_link_source_frame_cb,
|
||||
source);
|
||||
|
||||
g_source_set_static_name (source, "[gdk] quartz frame clock");
|
||||
g_source_set_name (source, "[gdk] quartz frame clock");
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdk-private.h"
|
||||
|
||||
#include "gdkmacosdevice-private.h"
|
||||
#include "gdkmacoscursor-private.h"
|
||||
@@ -162,7 +161,7 @@ gdk_macos_drag_drop_done (GdkDrag *drag,
|
||||
gdk_macos_zoomback_timeout,
|
||||
zb,
|
||||
(GDestroyNotify) gdk_macos_zoomback_destroy);
|
||||
gdk_source_set_static_name_by_id (id, "[gtk] gdk_macos_zoomback_timeout");
|
||||
g_source_set_name_by_id (id, "[gtk] gdk_macos_zoomback_timeout");
|
||||
g_object_unref (drag);
|
||||
}
|
||||
|
||||
@@ -243,11 +242,9 @@ gdk_macos_drag_drop_performed (GdkDrag *drag,
|
||||
|
||||
g_assert (GDK_IS_MACOS_DRAG (self));
|
||||
|
||||
g_object_ref (self);
|
||||
drag_ungrab (self);
|
||||
g_signal_emit_by_name (drag, "dnd-finished");
|
||||
gdk_drag_drop_done (drag, TRUE);
|
||||
g_object_unref (self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -32,8 +32,6 @@
|
||||
#include "gdkmacoseventsource-private.h"
|
||||
#include "gdkmacosdisplay-private.h"
|
||||
|
||||
#include "gdk-private.h"
|
||||
|
||||
/*
|
||||
* This file implementations integration between the GLib main loop and
|
||||
* the native system of the Core Foundation run loop and Cocoa event
|
||||
@@ -1065,7 +1063,7 @@ _gdk_macos_event_source_new (GdkMacosDisplay *display)
|
||||
event_poll_fd.fd = -1;
|
||||
|
||||
source = g_source_new (&event_funcs, sizeof (GdkMacosEventSource));
|
||||
g_source_set_static_name (source, "GDK Quartz event source");
|
||||
g_source_set_name (source, "GDK Quartz event source");
|
||||
g_source_add_poll (source, &event_poll_fd);
|
||||
g_source_set_priority (source, GDK_PRIORITY_EVENTS);
|
||||
g_source_set_can_recurse (source, TRUE);
|
||||
|
||||
@@ -460,7 +460,6 @@ gdk_wayland_device_update_surface_cursor (GdkDevice *device)
|
||||
pointer->cursor_timeout_id == 0)
|
||||
{
|
||||
guint id;
|
||||
GSource *source;
|
||||
|
||||
gdk_wayland_pointer_stop_cursor_animation (pointer);
|
||||
|
||||
@@ -468,8 +467,7 @@ gdk_wayland_device_update_surface_cursor (GdkDevice *device)
|
||||
id = g_timeout_add (next_image_delay,
|
||||
(GSourceFunc) gdk_wayland_device_update_surface_cursor,
|
||||
device);
|
||||
source = g_main_context_find_source_by_id (NULL, id);
|
||||
g_source_set_static_name (source, "[gtk] gdk_wayland_device_update_surface_cursor");
|
||||
g_source_set_name_by_id (id, "[gtk] gdk_wayland_device_update_surface_cursor");
|
||||
pointer->cursor_timeout_id = id;
|
||||
}
|
||||
else
|
||||
@@ -2220,7 +2218,7 @@ deliver_key_event (GdkWaylandSeat *seat,
|
||||
timeout = (seat->repeat_deadline - now) / 1000L;
|
||||
|
||||
seat->repeat_timer = g_timeout_add (timeout, keyboard_repeat, seat);
|
||||
gdk_source_set_static_name_by_id (seat->repeat_timer, "[gtk] keyboard_repeat");
|
||||
g_source_set_name_by_id (seat->repeat_timer, "[gtk] keyboard_repeat");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2634,23 +2632,6 @@ touch_handle_cancel (void *data,
|
||||
GDK_SEAT_NOTE (seat, EVENTS, g_message ("touch cancel"));
|
||||
}
|
||||
|
||||
static void
|
||||
touch_handle_shape (void *data,
|
||||
struct wl_touch *touch,
|
||||
int32_t id,
|
||||
wl_fixed_t major,
|
||||
wl_fixed_t minor)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
touch_handle_orientation (void *data,
|
||||
struct wl_touch *touch,
|
||||
int32_t id,
|
||||
wl_fixed_t orientation)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
emit_gesture_swipe_event (GdkWaylandSeat *seat,
|
||||
GdkTouchpadGesturePhase phase,
|
||||
@@ -3038,9 +3019,7 @@ static const struct wl_touch_listener touch_listener = {
|
||||
touch_handle_up,
|
||||
touch_handle_motion,
|
||||
touch_handle_frame,
|
||||
touch_handle_cancel,
|
||||
touch_handle_shape,
|
||||
touch_handle_orientation,
|
||||
touch_handle_cancel
|
||||
};
|
||||
|
||||
static const struct zwp_pointer_gesture_swipe_v1_listener gesture_swipe_listener = {
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
|
||||
#define MIN_SYSTEM_BELL_DELAY_MS 20
|
||||
|
||||
#define GTK_SHELL1_VERSION 5
|
||||
#define GTK_SHELL1_VERSION 4
|
||||
#define OUTPUT_VERSION_WITH_DONE 2
|
||||
#define NO_XDG_OUTPUT_DONE_SINCE_VERSION 3
|
||||
#define XDG_ACTIVATION_VERSION 1
|
||||
@@ -240,7 +240,7 @@ _gdk_wayland_display_add_seat (GdkWaylandDisplay *display_wayland,
|
||||
{
|
||||
struct wl_seat *seat;
|
||||
|
||||
display_wayland->seat_version = MIN (version, 7);
|
||||
display_wayland->seat_version = MIN (version, 5);
|
||||
seat = wl_registry_bind (display_wayland->wl_registry,
|
||||
id, &wl_seat_interface,
|
||||
display_wayland->seat_version);
|
||||
@@ -2117,7 +2117,7 @@ gdk_wayland_display_get_setting (GdkDisplay *display,
|
||||
{
|
||||
TranslationEntry *entry;
|
||||
|
||||
if (gdk_display_get_debug_flags (display) & GDK_DEBUG_DEFAULT_SETTINGS)
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (display, DEFAULT_SETTINGS))
|
||||
return FALSE;
|
||||
|
||||
if (GDK_WAYLAND_DISPLAY (display)->settings != NULL &&
|
||||
|
||||
@@ -290,10 +290,8 @@ data_source_dnd_finished (void *data,
|
||||
{
|
||||
GdkDrag *drag = data;
|
||||
|
||||
g_object_ref (drag);
|
||||
g_signal_emit_by_name (drag, "dnd-finished");
|
||||
gdk_drag_drop_done (drag, TRUE);
|
||||
g_object_unref (drag);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "gdkprivate-wayland.h"
|
||||
|
||||
#include "gdkinternals.h"
|
||||
#include "gdk-private.h"
|
||||
#include "gdksurfaceprivate.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
|
||||
@@ -475,28 +474,14 @@ gdk_wayland_display_init_gl (GdkDisplay *display,
|
||||
G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
|
||||
G_GNUC_UNUSED gint64 start_time2;
|
||||
|
||||
if (!epoxy_has_egl ())
|
||||
{
|
||||
gboolean sandboxed = gdk_running_in_sandbox ();
|
||||
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
sandboxed ? _("libEGL not available in this sandbox")
|
||||
: _("libEGL not available"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
start_time2 = GDK_PROFILER_CURRENT_TIME;
|
||||
dpy = get_egl_display (display_wayland);
|
||||
gdk_profiler_end_mark (start_time, "get_egl_display", NULL);
|
||||
if (dpy == NULL)
|
||||
{
|
||||
gboolean sandboxed = gdk_running_in_sandbox ();
|
||||
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
sandboxed ? _("Sandbox does not provide an OpenGL implementation")
|
||||
: _("No OpenGL implementation available"));
|
||||
_("Failed to create EGL display"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -542,7 +542,7 @@ _gdk_wayland_keymap_update_from_fd (GdkKeymap *keymap,
|
||||
|
||||
context = xkb_context_new (0);
|
||||
|
||||
map_str = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
map_str = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (map_str == MAP_FAILED)
|
||||
{
|
||||
close(fd);
|
||||
|
||||
@@ -4190,65 +4190,6 @@ gdk_wayland_surface_show_window_menu (GdkSurface *surface,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
translate_gesture (GdkTitlebarGesture gesture,
|
||||
enum gtk_surface1_gesture *out_gesture)
|
||||
{
|
||||
switch (gesture)
|
||||
{
|
||||
case GDK_TITLEBAR_GESTURE_DOUBLE_CLICK:
|
||||
*out_gesture = GTK_SURFACE1_GESTURE_DOUBLE_CLICK;
|
||||
break;
|
||||
|
||||
case GDK_TITLEBAR_GESTURE_RIGHT_CLICK:
|
||||
*out_gesture = GTK_SURFACE1_GESTURE_RIGHT_CLICK;
|
||||
break;
|
||||
|
||||
case GDK_TITLEBAR_GESTURE_MIDDLE_CLICK:
|
||||
*out_gesture = GTK_SURFACE1_GESTURE_MIDDLE_CLICK;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warning ("Not handling unknown titlebar gesture %u", gesture);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_wayland_surface_titlebar_gesture (GdkSurface *surface,
|
||||
GdkTitlebarGesture gesture)
|
||||
{
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||
struct gtk_surface1 *gtk_surface = impl->display_server.gtk_surface;
|
||||
enum gtk_surface1_gesture gtk_gesture;
|
||||
GdkSeat *seat;
|
||||
struct wl_seat *wl_seat;
|
||||
uint32_t serial;
|
||||
|
||||
if (!gtk_surface)
|
||||
return FALSE;
|
||||
|
||||
if (gtk_surface1_get_version (gtk_surface) < GTK_SURFACE1_TITLEBAR_GESTURE_SINCE_VERSION)
|
||||
return FALSE;
|
||||
|
||||
if (!translate_gesture (gesture, >k_gesture))
|
||||
return FALSE;
|
||||
|
||||
seat = gdk_display_get_default_seat (surface->display);
|
||||
wl_seat = gdk_wayland_seat_get_wl_seat (seat);
|
||||
|
||||
serial = _gdk_wayland_seat_get_last_implicit_grab_serial (GDK_WAYLAND_SEAT (seat), NULL);
|
||||
|
||||
gtk_surface1_titlebar_gesture (impl->display_server.gtk_surface,
|
||||
serial,
|
||||
wl_seat,
|
||||
gtk_gesture);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_wayland_surface_supports_edge_constraints (GdkSurface *surface)
|
||||
{
|
||||
@@ -5046,13 +4987,6 @@ gdk_wayland_toplevel_show_window_menu (GdkToplevel *toplevel,
|
||||
return gdk_wayland_surface_show_window_menu (GDK_SURFACE (toplevel), event);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_wayland_toplevel_titlebar_gesture (GdkToplevel *toplevel,
|
||||
GdkTitlebarGesture gesture)
|
||||
{
|
||||
return gdk_wayland_surface_titlebar_gesture (GDK_SURFACE (toplevel), gesture);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_wayland_toplevel_supports_edge_constraints (GdkToplevel *toplevel)
|
||||
{
|
||||
@@ -5131,7 +5065,6 @@ gdk_wayland_toplevel_iface_init (GdkToplevelInterface *iface)
|
||||
iface->lower = gdk_wayland_toplevel_lower;
|
||||
iface->focus = gdk_wayland_toplevel_focus;
|
||||
iface->show_window_menu = gdk_wayland_toplevel_show_window_menu;
|
||||
iface->titlebar_gesture = gdk_wayland_toplevel_titlebar_gesture;
|
||||
iface->supports_edge_constraints = gdk_wayland_toplevel_supports_edge_constraints;
|
||||
iface->inhibit_system_shortcuts = gdk_wayland_toplevel_inhibit_system_shortcuts;
|
||||
iface->restore_system_shortcuts = gdk_wayland_toplevel_restore_system_shortcuts;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<protocol name="gtk">
|
||||
|
||||
<interface name="gtk_shell1" version="5">
|
||||
<interface name="gtk_shell1" version="4">
|
||||
<description summary="gtk specific extensions">
|
||||
gtk_shell is a protocol extension providing additional features for
|
||||
clients implementing it.
|
||||
@@ -35,7 +35,7 @@
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="gtk_surface1" version="5">
|
||||
<interface name="gtk_surface1" version="4">
|
||||
<request name="set_dbus_properties">
|
||||
<arg name="application_id" type="string" allow-null="true"/>
|
||||
<arg name="app_menu_path" type="string" allow-null="true"/>
|
||||
@@ -85,23 +85,6 @@
|
||||
|
||||
<!-- Version 4 additions -->
|
||||
<request name="release" type="destructor" since="4"/>
|
||||
|
||||
<!-- Version 5 additions -->
|
||||
<enum name="gesture" since="5">
|
||||
<entry name="double_click" value="1"/>
|
||||
<entry name="right_click" value="2"/>
|
||||
<entry name="middle_click" value="3"/>
|
||||
</enum>
|
||||
|
||||
<enum name="error" since="5">
|
||||
<entry name="invalid_gesture" value="0"/>
|
||||
</enum>
|
||||
|
||||
<request name="titlebar_gesture" since="5">
|
||||
<arg name="serial" type="uint"/>
|
||||
<arg name="seat" type="object" interface="wl_seat"/>
|
||||
<arg name="gesture" type="uint" enum="gesture"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
</protocol>
|
||||
|
||||
@@ -89,7 +89,7 @@ gdk_device_win32_query_state (GdkDevice *device,
|
||||
hwnd = NULL;
|
||||
}
|
||||
|
||||
_gdk_win32_get_cursor_pos (&point);
|
||||
GetCursorPos (&point);
|
||||
|
||||
if (hwnd)
|
||||
ScreenToClient (hwnd, &point);
|
||||
@@ -177,7 +177,7 @@ _gdk_device_win32_surface_at_position (GdkDevice *device,
|
||||
HWND hwnd;
|
||||
RECT rect;
|
||||
|
||||
if (!_gdk_win32_get_cursor_pos (&screen_pt))
|
||||
if (!GetCursorPos (&screen_pt))
|
||||
return NULL;
|
||||
|
||||
/* Use WindowFromPoint instead of ChildWindowFromPoint(Ex).
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2020 the GTK team
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk/gdksurface.h>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "gdkwin32.h"
|
||||
#include "gdkdevice-winpointer.h"
|
||||
#include "gdkdisplay-win32.h"
|
||||
|
||||
G_DEFINE_TYPE (GdkDeviceWinpointer, gdk_device_winpointer, GDK_TYPE_DEVICE)
|
||||
|
||||
static GdkModifierType
|
||||
get_keyboard_mask (void)
|
||||
{
|
||||
GdkModifierType mask = 0;
|
||||
BYTE kbd[256];
|
||||
|
||||
GetKeyboardState (kbd);
|
||||
if (kbd[VK_SHIFT] & 0x80)
|
||||
mask |= GDK_SHIFT_MASK;
|
||||
if (kbd[VK_CAPITAL] & 0x80)
|
||||
mask |= GDK_LOCK_MASK;
|
||||
if (kbd[VK_CONTROL] & 0x80)
|
||||
mask |= GDK_CONTROL_MASK;
|
||||
if (kbd[VK_MENU] & 0x80)
|
||||
mask |= GDK_ALT_MASK;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_winpointer_set_surface_cursor (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
GdkCursor *cursor)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
gdk_device_winpointer_query_state (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
GdkSurface **child_window,
|
||||
double *win_x,
|
||||
double *win_y,
|
||||
GdkModifierType *mask)
|
||||
{
|
||||
GdkDeviceWinpointer *device_winpointer;
|
||||
POINT point;
|
||||
HWND hwnd, hwndc;
|
||||
int scale;
|
||||
|
||||
device_winpointer = GDK_DEVICE_WINPOINTER (device);
|
||||
if (window)
|
||||
{
|
||||
scale = GDK_WIN32_SURFACE (window)->surface_scale;
|
||||
hwnd = GDK_SURFACE_HWND (window);
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkDisplay *display = gdk_device_get_display (device);
|
||||
|
||||
scale = GDK_WIN32_DISPLAY (display)->surface_scale;
|
||||
hwnd = NULL;
|
||||
}
|
||||
|
||||
_gdk_win32_get_cursor_pos (&point);
|
||||
|
||||
if (hwnd)
|
||||
ScreenToClient (hwnd, &point);
|
||||
|
||||
if (win_x)
|
||||
*win_x = point.x / scale;
|
||||
|
||||
if (win_y)
|
||||
*win_y = point.y / scale;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
if (win_x)
|
||||
*win_x += _gdk_offset_x;
|
||||
|
||||
if (win_y)
|
||||
*win_y += _gdk_offset_y;
|
||||
}
|
||||
|
||||
if (hwnd && child_window)
|
||||
{
|
||||
hwndc = ChildWindowFromPoint (hwnd, point);
|
||||
|
||||
if (hwndc && hwndc != hwnd)
|
||||
*child_window = gdk_win32_handle_table_lookup (hwndc);
|
||||
else
|
||||
*child_window = NULL; /* Direct child unknown to gdk */
|
||||
}
|
||||
|
||||
if (mask)
|
||||
{
|
||||
*mask = get_keyboard_mask ();
|
||||
*mask |= device_winpointer->last_button_mask;
|
||||
}
|
||||
}
|
||||
|
||||
static GdkGrabStatus
|
||||
gdk_device_winpointer_grab (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
gboolean owner_events,
|
||||
GdkEventMask event_mask,
|
||||
GdkSurface *confine_to,
|
||||
GdkCursor *cursor,
|
||||
guint32 time_)
|
||||
{
|
||||
return GDK_GRAB_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_winpointer_ungrab (GdkDevice *device,
|
||||
guint32 time_)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
screen_to_client (HWND hwnd, POINT screen_pt, POINT *client_pt)
|
||||
{
|
||||
*client_pt = screen_pt;
|
||||
ScreenToClient (hwnd, client_pt);
|
||||
}
|
||||
|
||||
static GdkSurface *
|
||||
gdk_device_winpointer_surface_at_position (GdkDevice *device,
|
||||
double *win_x,
|
||||
double *win_y,
|
||||
GdkModifierType *mask)
|
||||
{
|
||||
GdkSurface *surface = NULL;
|
||||
GdkWin32Surface *impl = NULL;
|
||||
POINT screen_pt, client_pt;
|
||||
HWND hwnd;
|
||||
RECT rect;
|
||||
|
||||
if (!_gdk_win32_get_cursor_pos (&screen_pt))
|
||||
return NULL;
|
||||
|
||||
/* Use WindowFromPoint instead of ChildWindowFromPoint(Ex).
|
||||
* Only WindowFromPoint is able to look through transparent
|
||||
* layered windows.
|
||||
*/
|
||||
hwnd = GetAncestor (WindowFromPoint (screen_pt), GA_ROOT);
|
||||
|
||||
/* Verify that we're really inside the client area of the surface */
|
||||
GetClientRect (hwnd, &rect);
|
||||
screen_to_client (hwnd, screen_pt, &client_pt);
|
||||
if (!PtInRect (&rect, client_pt))
|
||||
hwnd = NULL;
|
||||
|
||||
surface = gdk_win32_handle_table_lookup (hwnd);
|
||||
|
||||
if (surface && (win_x || win_y))
|
||||
{
|
||||
impl = GDK_WIN32_SURFACE (surface);
|
||||
|
||||
if (win_x)
|
||||
*win_x = client_pt.x / impl->surface_scale;
|
||||
if (win_y)
|
||||
*win_y = client_pt.y / impl->surface_scale;
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_winpointer_init (GdkDeviceWinpointer *device_winpointer)
|
||||
{
|
||||
device_winpointer->device_handle = NULL;
|
||||
device_winpointer->start_cursor_id = 0;
|
||||
device_winpointer->end_cursor_id = 0;
|
||||
|
||||
device_winpointer->origin_x = 0;
|
||||
device_winpointer->origin_y = 0;
|
||||
device_winpointer->scale_x = 0.0;
|
||||
device_winpointer->scale_y = 0.0;
|
||||
|
||||
device_winpointer->last_button_mask = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_winpointer_finalize (GObject *object)
|
||||
{
|
||||
GdkDeviceWinpointer *device_winpointer = GDK_DEVICE_WINPOINTER (object);
|
||||
|
||||
g_clear_object (&device_winpointer->tool_pen);
|
||||
g_clear_object (&device_winpointer->tool_eraser);
|
||||
|
||||
G_OBJECT_CLASS (gdk_device_winpointer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_winpointer_class_init (GdkDeviceWinpointerClass *klass)
|
||||
{
|
||||
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gdk_device_winpointer_finalize;
|
||||
device_class->set_surface_cursor = gdk_device_winpointer_set_surface_cursor;
|
||||
device_class->grab = gdk_device_winpointer_grab;
|
||||
device_class->ungrab = gdk_device_winpointer_ungrab;
|
||||
device_class->surface_at_position = gdk_device_winpointer_surface_at_position;
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2020 the GTK team
|
||||
*
|
||||
* 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 __GDK_DEVICE_WINPOINTER_H__
|
||||
#define __GDK_DEVICE_WINPOINTER_H__
|
||||
|
||||
#include <gdk/gdkdeviceprivate.h>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "winpointer.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_DEVICE_WINPOINTER (gdk_device_winpointer_get_type ())
|
||||
#define GDK_DEVICE_WINPOINTER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_WINPOINTER, GdkDeviceWinpointer))
|
||||
#define GDK_DEVICE_WINPOINTER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE_WINPOINTER, GdkDeviceWinpointerClass))
|
||||
#define GDK_IS_DEVICE_WINPOINTER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE_WINPOINTER))
|
||||
#define GDK_IS_DEVICE_WINPOINTER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_DEVICE_WINPOINTER))
|
||||
#define GDK_DEVICE_WINPOINTER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE_WINPOINTER, GdkDeviceWinpointerClass))
|
||||
|
||||
typedef struct _GdkDeviceWinpointer GdkDeviceWinpointer;
|
||||
typedef struct _GdkDeviceWinpointerClass GdkDeviceWinpointerClass;
|
||||
|
||||
struct _GdkDeviceWinpointer
|
||||
{
|
||||
GdkDevice parent_instance;
|
||||
|
||||
HANDLE device_handle;
|
||||
UINT32 start_cursor_id;
|
||||
UINT32 end_cursor_id;
|
||||
|
||||
int origin_x;
|
||||
int origin_y;
|
||||
double scale_x;
|
||||
double scale_y;
|
||||
|
||||
GdkModifierType last_button_mask;
|
||||
|
||||
GdkDeviceTool *tool_pen;
|
||||
GdkDeviceTool *tool_eraser;
|
||||
};
|
||||
|
||||
struct _GdkDeviceWinpointerClass
|
||||
{
|
||||
GdkDeviceClass parent_class;
|
||||
};
|
||||
|
||||
GType gdk_device_winpointer_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_DEVICE_WINPOINTER_H__ */
|
||||
@@ -88,7 +88,7 @@ gdk_device_wintab_query_state (GdkDevice *device,
|
||||
hwnd = NULL;
|
||||
}
|
||||
|
||||
_gdk_win32_get_cursor_pos (&point);
|
||||
GetCursorPos (&point);
|
||||
|
||||
if (hwnd)
|
||||
ScreenToClient (hwnd, &point);
|
||||
|
||||
@@ -29,9 +29,7 @@
|
||||
#include "gdkdevice-win32.h"
|
||||
#include "gdkdevice-virtual.h"
|
||||
#include "gdkdevice-wintab.h"
|
||||
#include "gdkinput-winpointer.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkdisplay-win32.h"
|
||||
#include "gdkseatdefaultprivate.h"
|
||||
|
||||
#define WINTAB32_DLL "Wintab32.dll"
|
||||
@@ -373,6 +371,9 @@ wintab_init_check (GdkDeviceManagerWin32 *device_manager)
|
||||
|
||||
wintab_contexts = NULL;
|
||||
|
||||
if (_gdk_input_ignore_wintab)
|
||||
return;
|
||||
|
||||
n = GetSystemDirectory (&dummy, 0);
|
||||
|
||||
if (n <= 0)
|
||||
@@ -683,13 +684,10 @@ wintab_default_display_notify_cb (GdkDisplayManager *display_manager)
|
||||
static void
|
||||
gdk_device_manager_win32_constructed (GObject *object)
|
||||
{
|
||||
GdkWin32Display *display_win32;
|
||||
GdkDeviceManagerWin32 *device_manager;
|
||||
GdkSeat *seat;
|
||||
const char *api_preference = NULL;
|
||||
gboolean have_api_preference = TRUE;
|
||||
|
||||
display_win32 = GDK_WIN32_DISPLAY (_gdk_display);
|
||||
GdkDisplayManager *display_manager = NULL;
|
||||
GdkDisplay *default_display = NULL;
|
||||
|
||||
device_manager = GDK_DEVICE_MANAGER_WIN32 (object);
|
||||
device_manager->core_pointer =
|
||||
@@ -730,59 +728,18 @@ gdk_device_manager_win32_constructed (GObject *object)
|
||||
gdk_seat_default_add_physical_device (GDK_SEAT_DEFAULT (seat), device_manager->system_keyboard);
|
||||
g_object_unref (seat);
|
||||
|
||||
_gdk_device_manager = device_manager;
|
||||
/* Only call Wintab init stuff after the default display
|
||||
* is globally known and accessible through the display manager
|
||||
* singleton. Approach lifted from gtkmodules.c.
|
||||
*/
|
||||
display_manager = gdk_display_manager_get ();
|
||||
g_assert (display_manager != NULL);
|
||||
default_display = gdk_display_manager_get_default_display (display_manager);
|
||||
g_assert (default_display == NULL);
|
||||
|
||||
api_preference = g_getenv ("GDK_WIN32_TABLET_INPUT_API");
|
||||
if (g_strcmp0 (api_preference, "none") == 0)
|
||||
{
|
||||
display_win32->tablet_input_api = GDK_WIN32_TABLET_INPUT_API_NONE;
|
||||
}
|
||||
else if (g_strcmp0 (api_preference, "wintab") == 0)
|
||||
{
|
||||
display_win32->tablet_input_api = GDK_WIN32_TABLET_INPUT_API_WINTAB;
|
||||
}
|
||||
else if (g_strcmp0 (api_preference, "winpointer") == 0)
|
||||
{
|
||||
display_win32->tablet_input_api = GDK_WIN32_TABLET_INPUT_API_WINPOINTER;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No user preference, default to WinPointer. If unsuccessful,
|
||||
* try to initialize other API's in sequence until one succeeds.
|
||||
*/
|
||||
display_win32->tablet_input_api = GDK_WIN32_TABLET_INPUT_API_WINPOINTER;
|
||||
have_api_preference = FALSE;
|
||||
}
|
||||
|
||||
if (display_win32->tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINPOINTER)
|
||||
{
|
||||
gboolean init_successful = gdk_winpointer_initialize ();
|
||||
|
||||
if (!init_successful && !have_api_preference)
|
||||
{
|
||||
/* Try Wintab */
|
||||
display_win32->tablet_input_api = GDK_WIN32_TABLET_INPUT_API_WINTAB;
|
||||
}
|
||||
}
|
||||
|
||||
if (display_win32->tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINTAB)
|
||||
{
|
||||
GdkDisplayManager *display_manager = NULL;
|
||||
GdkDisplay *default_display = NULL;
|
||||
|
||||
/* Only call Wintab init stuff after the default display
|
||||
* is globally known and accessible through the display manager
|
||||
* singleton. Approach lifted from gtkmodules.c.
|
||||
*/
|
||||
display_manager = gdk_display_manager_get ();
|
||||
g_assert (display_manager != NULL);
|
||||
default_display = gdk_display_manager_get_default_display (display_manager);
|
||||
g_assert (default_display == NULL);
|
||||
|
||||
g_signal_connect (display_manager, "notify::default-display",
|
||||
G_CALLBACK (wintab_default_display_notify_cb),
|
||||
NULL);
|
||||
}
|
||||
g_signal_connect (display_manager, "notify::default-display",
|
||||
G_CALLBACK (wintab_default_display_notify_cb),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -795,7 +752,7 @@ gdk_device_manager_win32_class_init (GdkDeviceManagerWin32Class *klass)
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_wintab_set_tablet_active (void)
|
||||
_gdk_input_set_tablet_active (void)
|
||||
{
|
||||
GList *tmp_list;
|
||||
HCTX *hctx;
|
||||
@@ -806,7 +763,7 @@ _gdk_wintab_set_tablet_active (void)
|
||||
if (!wintab_contexts)
|
||||
return; /* No tablet devices found, or Wintab not initialized yet */
|
||||
|
||||
GDK_NOTE (INPUT, g_print ("_gdk_wintab_set_tablet_active: "
|
||||
GDK_NOTE (INPUT, g_print ("_gdk_input_set_tablet_active: "
|
||||
"Bringing Wintab contexts to the top of the overlap order\n"));
|
||||
|
||||
tmp_list = wintab_contexts;
|
||||
@@ -909,7 +866,7 @@ gdk_device_manager_find_wintab_device (GdkDeviceManagerWin32 *device_manager,
|
||||
}
|
||||
|
||||
GdkEvent *
|
||||
gdk_wintab_make_event (GdkDisplay *display,
|
||||
gdk_input_other_event (GdkDisplay *display,
|
||||
MSG *msg,
|
||||
GdkSurface *window)
|
||||
{
|
||||
@@ -937,7 +894,7 @@ gdk_wintab_make_event (GdkDisplay *display,
|
||||
|
||||
if (window != wintab_window)
|
||||
{
|
||||
g_warning ("gdk_wintab_make_event: not wintab_window?");
|
||||
g_warning ("gdk_input_other_event: not wintab_window?");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -948,7 +905,7 @@ gdk_wintab_make_event (GdkDisplay *display,
|
||||
g_object_ref (window);
|
||||
|
||||
GDK_NOTE (EVENTS_OR_INPUT,
|
||||
g_print ("gdk_wintab_make_event: window=%p %+g%+g\n",
|
||||
g_print ("gdk_input_other_event: window=%p %+g%+g\n",
|
||||
window ? GDK_SURFACE_HWND (window) : NULL, x, y));
|
||||
|
||||
if (msg->message == WT_PACKET || msg->message == WT_CSRCHANGE)
|
||||
|
||||
@@ -40,8 +40,6 @@ struct _GdkDeviceManagerWin32
|
||||
/* Fake physical devices */
|
||||
GdkDevice *system_pointer;
|
||||
GdkDevice *system_keyboard;
|
||||
|
||||
GList *winpointer_devices;
|
||||
GList *wintab_devices;
|
||||
|
||||
/* Bumped up every time a wintab device enters the proximity
|
||||
@@ -58,8 +56,8 @@ struct _GdkDeviceManagerWin32Class
|
||||
|
||||
GType gdk_device_manager_win32_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void _gdk_wintab_set_tablet_active (void);
|
||||
GdkEvent * gdk_wintab_make_event (GdkDisplay *display,
|
||||
void _gdk_input_set_tablet_active (void);
|
||||
GdkEvent * gdk_input_other_event (GdkDisplay *display,
|
||||
MSG *msg,
|
||||
GdkSurface *window);
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#define VK_USE_PLATFORM_WIN32_KHR
|
||||
|
||||
#include "gdk.h"
|
||||
@@ -534,6 +535,7 @@ _gdk_win32_display_open (const char *display_name)
|
||||
|
||||
_gdk_win32_lang_notification_init ();
|
||||
_gdk_drag_init ();
|
||||
_gdk_drop_init ();
|
||||
|
||||
_gdk_display->clipboard = gdk_win32_clipboard_new (_gdk_display);
|
||||
_gdk_display->primary_clipboard = gdk_clipboard_new (_gdk_display);
|
||||
|
||||
@@ -99,12 +99,6 @@ typedef struct _GdkWin32User32DPIFuncs
|
||||
funcADACE areDACEqual;
|
||||
} GdkWin32User32DPIFuncs;
|
||||
|
||||
typedef enum {
|
||||
GDK_WIN32_TABLET_INPUT_API_NONE,
|
||||
GDK_WIN32_TABLET_INPUT_API_WINTAB,
|
||||
GDK_WIN32_TABLET_INPUT_API_WINPOINTER
|
||||
} GdkWin32TabletInputAPI;
|
||||
|
||||
/* Detect running architecture */
|
||||
typedef BOOL (WINAPI *funcIsWow64Process2) (HANDLE, USHORT *, USHORT *);
|
||||
typedef struct _GdkWin32KernelCPUFuncs
|
||||
@@ -165,9 +159,7 @@ struct _GdkWin32Display
|
||||
|
||||
GdkWin32ShcoreFuncs shcore_funcs;
|
||||
GdkWin32User32DPIFuncs user32_dpi_funcs;
|
||||
|
||||
GdkWin32TabletInputAPI tablet_input_api;
|
||||
|
||||
|
||||
/* Cursor Items (GdkCursor->GdkWin32HCursor) */
|
||||
GHashTable *cursors;
|
||||
/* The cursor that is used by current grab (if any) */
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "gdk-private.h"
|
||||
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <math.h>
|
||||
@@ -158,6 +156,9 @@
|
||||
* drag window) in response to this, as all the functions
|
||||
* that GDK could perform here are already handled by the
|
||||
* OS driving the DnD process via DoDragDrop() call.
|
||||
* The LOCAL protocol, on the other hand, does a lot,
|
||||
* similar to what X11 backend does with XDND - it sends
|
||||
* GDK_DRAG_LEAVE and GDK_DRAG_ENTER, emits GDK_DRAG_MOTION.
|
||||
*
|
||||
* GDK_BUTTON_RELEASE checks the
|
||||
* released button - if it's the button that was used to
|
||||
@@ -178,7 +179,11 @@
|
||||
* the OS notifies the process about these things happening.
|
||||
* For X11 backend that is done in Xdnd event filters,
|
||||
* for W32 backend this is done in IDropSource/IDropTarget
|
||||
* object methods for the OLE2 protocol.
|
||||
* object methods for the OLE2 protocol, whereas for the
|
||||
* LOCAL protocol these events are emitted only by GDK itself
|
||||
* (with the exception of WM_DROPFILES message, which causes
|
||||
* GDK to create a drop context and then immediately finish
|
||||
* the drag, providing the list of files it got from the message).
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -480,6 +485,17 @@ process_dnd_queue (gboolean timed,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_win32_local_drag_drop_response (GdkDrag *drag,
|
||||
GdkDragAction action)
|
||||
{
|
||||
GDK_NOTE (DND, g_print ("_gdk_win32_local_drag_drop_response: 0x%p\n",
|
||||
drag));
|
||||
|
||||
g_signal_emit_by_name (drag, "dnd-finished");
|
||||
gdk_drag_drop_done (drag, action != 0);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_drag_drop_response (gpointer user_data)
|
||||
{
|
||||
@@ -696,6 +712,16 @@ _gdk_win32_dnd_thread_main (gpointer data)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* For the LOCAL protocol */
|
||||
typedef enum {
|
||||
GDK_DRAG_STATUS_DRAG,
|
||||
GDK_DRAG_STATUS_MOTION_WAIT,
|
||||
GDK_DRAG_STATUS_ACTION_WAIT,
|
||||
GDK_DRAG_STATUS_DROP
|
||||
} GdkDragStatus;
|
||||
|
||||
static gboolean use_ole2_dnd = TRUE;
|
||||
|
||||
static gboolean drag_context_grab (GdkDrag *drag);
|
||||
|
||||
G_DEFINE_TYPE (GdkWin32Drag, gdk_win32_drag, GDK_TYPE_DRAG)
|
||||
@@ -763,7 +789,8 @@ gdk_drag_new (GdkDisplay *display,
|
||||
GdkSurface *surface,
|
||||
GdkContentProvider *content,
|
||||
GdkDragAction actions,
|
||||
GdkDevice *device)
|
||||
GdkDevice *device,
|
||||
GdkDragProtocol protocol)
|
||||
{
|
||||
GdkWin32Drag *drag_win32;
|
||||
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
|
||||
@@ -783,6 +810,8 @@ gdk_drag_new (GdkDisplay *display,
|
||||
else
|
||||
drag_win32->scale = gdk_win32_display_get_monitor_scale_factor (display_win32, NULL, NULL);
|
||||
|
||||
drag_win32->protocol = protocol;
|
||||
|
||||
return drag;
|
||||
}
|
||||
|
||||
@@ -1050,6 +1079,21 @@ maybe_emit_action_changed (GdkWin32Drag *drag_win32,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_win32_local_drag_give_feedback (GdkDrag *drag,
|
||||
GdkDragAction actions)
|
||||
{
|
||||
GdkWin32Drag *drag_win32 = GDK_WIN32_DRAG (drag);
|
||||
|
||||
if (drag_win32->drag_status == GDK_DRAG_STATUS_MOTION_WAIT)
|
||||
drag_win32->drag_status = GDK_DRAG_STATUS_DRAG;
|
||||
|
||||
GDK_NOTE (DND, g_print ("_gdk_win32_local_drag_give_feedback: 0x%p\n",
|
||||
drag));
|
||||
|
||||
maybe_emit_action_changed (drag_win32, actions);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
give_feedback (gpointer user_data)
|
||||
{
|
||||
@@ -1624,20 +1668,30 @@ enum_formats_new (GArray *formats)
|
||||
void
|
||||
_gdk_drag_init (void)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
|
||||
|
||||
hr = OleInitialize (NULL);
|
||||
if (g_strcmp0 (getenv ("GDK_WIN32_OLE2_DND"), "0") == 0)
|
||||
use_ole2_dnd = FALSE;
|
||||
|
||||
if (! SUCCEEDED (hr))
|
||||
g_error ("OleInitialize failed");
|
||||
if (use_ole2_dnd)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
hr = OleInitialize (NULL);
|
||||
|
||||
if (! SUCCEEDED (hr))
|
||||
g_error ("OleInitialize failed");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_win32_dnd_exit (void)
|
||||
{
|
||||
OleUninitialize ();
|
||||
if (use_ole2_dnd)
|
||||
{
|
||||
OleUninitialize ();
|
||||
}
|
||||
|
||||
CoUninitialize ();
|
||||
}
|
||||
|
||||
@@ -1667,9 +1721,6 @@ _gdk_win32_surface_drag_begin (GdkSurface *surface,
|
||||
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
|
||||
double px, py;
|
||||
int x_root, y_root;
|
||||
GdkWin32DnDThreadDoDragDrop *ddd;
|
||||
source_drag_context *source_ctx;
|
||||
data_object *data_obj;
|
||||
|
||||
g_return_val_if_fail (surface != NULL, NULL);
|
||||
|
||||
@@ -1677,7 +1728,8 @@ _gdk_win32_surface_drag_begin (GdkSurface *surface,
|
||||
surface,
|
||||
content,
|
||||
actions,
|
||||
device);
|
||||
device,
|
||||
use_ole2_dnd ? GDK_DRAG_PROTO_OLE2 : GDK_DRAG_PROTO_LOCAL);
|
||||
drag_win32 = GDK_WIN32_DRAG (drag);
|
||||
|
||||
GDK_NOTE (DND, g_print ("_gdk_win32_surface_drag_begin\n"));
|
||||
@@ -1701,35 +1753,121 @@ _gdk_win32_surface_drag_begin (GdkSurface *surface,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ddd = g_new0 (GdkWin32DnDThreadDoDragDrop, 1);
|
||||
if (drag_win32->protocol == GDK_DRAG_PROTO_OLE2)
|
||||
{
|
||||
GdkWin32DnDThreadDoDragDrop *ddd = g_new0 (GdkWin32DnDThreadDoDragDrop, 1);
|
||||
source_drag_context *source_ctx;
|
||||
data_object *data_obj;
|
||||
|
||||
source_ctx = source_context_new (drag, gdk_drag_get_formats (drag));
|
||||
data_obj = data_object_new (drag);
|
||||
source_ctx = source_context_new (drag, gdk_drag_get_formats (drag));
|
||||
data_obj = data_object_new (drag);
|
||||
|
||||
ddd->base.item_type = GDK_WIN32_DND_THREAD_QUEUE_ITEM_DO_DRAG_DROP;
|
||||
ddd->base.opaque_context = drag_win32;
|
||||
ddd->src_context = source_ctx;
|
||||
ddd->src_object = data_obj;
|
||||
ddd->allowed_drop_effects = 0;
|
||||
if (actions & GDK_ACTION_COPY)
|
||||
ddd->allowed_drop_effects |= DROPEFFECT_COPY;
|
||||
if (actions & GDK_ACTION_MOVE)
|
||||
ddd->allowed_drop_effects |= DROPEFFECT_MOVE;
|
||||
if (actions & GDK_ACTION_LINK)
|
||||
ddd->allowed_drop_effects |= DROPEFFECT_LINK;
|
||||
ddd->base.item_type = GDK_WIN32_DND_THREAD_QUEUE_ITEM_DO_DRAG_DROP;
|
||||
ddd->base.opaque_context = drag_win32;
|
||||
ddd->src_context = source_ctx;
|
||||
ddd->src_object = data_obj;
|
||||
ddd->allowed_drop_effects = 0;
|
||||
if (actions & GDK_ACTION_COPY)
|
||||
ddd->allowed_drop_effects |= DROPEFFECT_COPY;
|
||||
if (actions & GDK_ACTION_MOVE)
|
||||
ddd->allowed_drop_effects |= DROPEFFECT_MOVE;
|
||||
if (actions & GDK_ACTION_LINK)
|
||||
ddd->allowed_drop_effects |= DROPEFFECT_LINK;
|
||||
|
||||
g_hash_table_replace (clipdrop->active_source_drags, g_object_ref (drag), ddd);
|
||||
increment_dnd_queue_counter ();
|
||||
g_async_queue_push (clipdrop->dnd_queue, ddd);
|
||||
API_CALL (PostThreadMessage, (clipdrop->dnd_thread_id, thread_wakeup_message, 0, 0));
|
||||
g_hash_table_replace (clipdrop->active_source_drags, g_object_ref (drag), ddd);
|
||||
increment_dnd_queue_counter ();
|
||||
g_async_queue_push (clipdrop->dnd_queue, ddd);
|
||||
API_CALL (PostThreadMessage, (clipdrop->dnd_thread_id, thread_wakeup_message, 0, 0));
|
||||
|
||||
drag_win32->util_data.state = GDK_WIN32_DND_PENDING;
|
||||
drag_win32->util_data.state = GDK_WIN32_DND_PENDING;
|
||||
}
|
||||
|
||||
move_drag_surface (drag, x_root, y_root);
|
||||
|
||||
return drag;
|
||||
}
|
||||
|
||||
/* TODO: remove this?
|
||||
* window finder is only used by our gdk_drag_update() to
|
||||
* find the window at drag coordinates - which is
|
||||
* something IDropSourceNotify already gives us.
|
||||
* Unless, of course, we keep the LOCAL protocol around.
|
||||
*/
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
HWND ignore;
|
||||
HWND result;
|
||||
} find_window_enum_arg;
|
||||
|
||||
static BOOL CALLBACK
|
||||
find_window_enum_proc (HWND hwnd,
|
||||
LPARAM lparam)
|
||||
{
|
||||
RECT rect;
|
||||
POINT tl, br;
|
||||
find_window_enum_arg *a = (find_window_enum_arg *) lparam;
|
||||
|
||||
if (hwnd == a->ignore)
|
||||
return TRUE;
|
||||
|
||||
if (!IsWindowVisible (hwnd))
|
||||
return TRUE;
|
||||
|
||||
tl.x = tl.y = 0;
|
||||
ClientToScreen (hwnd, &tl);
|
||||
GetClientRect (hwnd, &rect);
|
||||
br.x = rect.right;
|
||||
br.y = rect.bottom;
|
||||
ClientToScreen (hwnd, &br);
|
||||
|
||||
if (a->x >= tl.x && a->y >= tl.y && a->x < br.x && a->y < br.y)
|
||||
{
|
||||
a->result = hwnd;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Finds the HWND under cursor. Local DnD protocol
|
||||
* uses this function, since local protocol is implemented
|
||||
* entirely in GDK and cannot rely on the OS to notify
|
||||
* drop targets about drags that move over them.
|
||||
*/
|
||||
static HWND
|
||||
gdk_win32_drag_find_window (GdkDrag *drag,
|
||||
GdkSurface *drag_surface,
|
||||
int x_root,
|
||||
int y_root)
|
||||
{
|
||||
GdkWin32Drag *drag_win32 = GDK_WIN32_DRAG (drag);
|
||||
find_window_enum_arg a;
|
||||
|
||||
g_assert (_win32_main_thread == NULL ||
|
||||
_win32_main_thread == g_thread_self ());
|
||||
|
||||
a.x = x_root * drag_win32->scale - _gdk_offset_x;
|
||||
a.y = y_root * drag_win32->scale - _gdk_offset_y;
|
||||
a.ignore = drag_surface ? GDK_SURFACE_HWND (drag_surface) : NULL;
|
||||
a.result = INVALID_HANDLE_VALUE;
|
||||
|
||||
GDK_NOTE (DND,
|
||||
g_print ("gdk_win32_drag_find_window: %p %+d%+d\n",
|
||||
(drag_surface ? GDK_SURFACE_HWND (drag_surface) : NULL),
|
||||
a.x, a.y));
|
||||
|
||||
EnumWindows (find_window_enum_proc, (LPARAM) &a);
|
||||
|
||||
GDK_NOTE (DND,
|
||||
g_print ("gdk_win32_drag_find_window: %p %+d%+d: %p\n",
|
||||
(drag_surface ? GDK_SURFACE_HWND (drag_surface) : NULL),
|
||||
x_root, y_root,
|
||||
a.result));
|
||||
|
||||
return a.result;
|
||||
}
|
||||
|
||||
static DWORD
|
||||
manufacture_keystate_from_GMT (GdkModifierType state)
|
||||
{
|
||||
@@ -1751,6 +1889,100 @@ manufacture_keystate_from_GMT (GdkModifierType state)
|
||||
return key_state;
|
||||
}
|
||||
|
||||
/* This only works if dest_window our window and the DnD operation
|
||||
* is currently local to the application.
|
||||
*/
|
||||
static GdkDrop *
|
||||
_gdk_win32_get_drop_for_dest_window (HWND dest_window)
|
||||
{
|
||||
GdkSurface *drop_surface = gdk_win32_handle_table_lookup (dest_window);
|
||||
GdkDrop *result = NULL;
|
||||
|
||||
if (drop_surface)
|
||||
result = _gdk_win32_get_drop_for_dest_surface (drop_surface);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_win32_local_drag_motion (GdkDrag *drag,
|
||||
HWND dest_window,
|
||||
int x_root,
|
||||
int y_root,
|
||||
GdkDragAction possible_actions,
|
||||
DWORD key_state,
|
||||
guint32 time_)
|
||||
{
|
||||
GdkWin32Drag *drag_win32;
|
||||
GdkDrop *drop;
|
||||
GdkDragAction actions;
|
||||
|
||||
g_assert (_win32_main_thread == NULL ||
|
||||
_win32_main_thread == g_thread_self ());
|
||||
|
||||
g_return_val_if_fail (drag != NULL, FALSE);
|
||||
|
||||
drag_win32 = GDK_WIN32_DRAG (drag);
|
||||
|
||||
drop = _gdk_win32_get_drop_for_dest_window (drag_win32->dest_window);
|
||||
|
||||
actions = gdk_drag_get_actions (drag);
|
||||
|
||||
GDK_NOTE (DND, g_print ("gdk_win32_local_drag_motion: @ %+d:%+d possible=%s\n"
|
||||
" dest=%p (current %p) drop=%p drag=%p:{actions=%s,action=%s}\n",
|
||||
x_root, y_root,
|
||||
_gdk_win32_drag_action_to_string (possible_actions),
|
||||
dest_window, drag_win32->dest_window, drop, drag,
|
||||
_gdk_win32_drag_action_to_string (actions),
|
||||
_gdk_win32_drag_action_to_string (gdk_drag_get_selected_action (drag))));
|
||||
|
||||
if (drag_win32->dest_window != dest_window)
|
||||
{
|
||||
/* Send a leave to the last destination */
|
||||
if (drop)
|
||||
_gdk_win32_local_drop_target_dragleave (drop, time_);
|
||||
|
||||
drag_win32->dest_window = dest_window;
|
||||
drag_win32->drag_status = GDK_DRAG_STATUS_DRAG;
|
||||
|
||||
_gdk_win32_local_drop_target_dragenter (drag,
|
||||
gdk_win32_handle_table_lookup (dest_window),
|
||||
x_root,
|
||||
y_root,
|
||||
key_state,
|
||||
time_,
|
||||
&actions);
|
||||
|
||||
drop = _gdk_win32_get_drop_for_dest_window (drag_win32->dest_window);
|
||||
maybe_emit_action_changed (drag_win32, actions);
|
||||
}
|
||||
|
||||
/* Send a drag-motion event */
|
||||
|
||||
drag_win32->util_data.last_x = x_root;
|
||||
drag_win32->util_data.last_y = y_root;
|
||||
|
||||
if (drop != NULL &&
|
||||
drag_win32->drag_status == GDK_DRAG_STATUS_DRAG &&
|
||||
_gdk_win32_local_drop_target_will_emit_motion (drop, x_root, y_root, key_state))
|
||||
{
|
||||
actions = gdk_drag_get_actions (drag);
|
||||
drag_win32->drag_status = GDK_DRAG_STATUS_MOTION_WAIT;
|
||||
|
||||
_gdk_win32_local_drop_target_dragover (drop, drag, x_root, y_root, key_state, time_, &actions);
|
||||
|
||||
maybe_emit_action_changed (drag_win32, actions);
|
||||
}
|
||||
|
||||
GDK_NOTE (DND, g_print (" returning %s\n"
|
||||
" drag=%p:{actions=%s,action=%s}\n",
|
||||
(drop != NULL && drag_win32->drag_status == GDK_DRAG_STATUS_DRAG) ? "TRUE" : "FALSE",
|
||||
drag,
|
||||
_gdk_win32_drag_action_to_string (gdk_drag_get_actions (drag)),
|
||||
_gdk_win32_drag_action_to_string (gdk_drag_get_selected_action (drag))));
|
||||
return (drop != NULL && drag_win32->drag_status == GDK_DRAG_STATUS_DRAG);
|
||||
}
|
||||
|
||||
static void
|
||||
send_source_state_update (GdkWin32Clipdrop *clipdrop,
|
||||
GdkWin32Drag *drag_win32,
|
||||
@@ -1771,7 +2003,6 @@ gdk_win32_drag_drop (GdkDrag *drag,
|
||||
{
|
||||
GdkWin32Drag *drag_win32 = GDK_WIN32_DRAG (drag);
|
||||
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
|
||||
gpointer ddd;
|
||||
|
||||
g_assert (_win32_main_thread == NULL ||
|
||||
_win32_main_thread == g_thread_self ());
|
||||
@@ -1780,12 +2011,29 @@ gdk_win32_drag_drop (GdkDrag *drag,
|
||||
|
||||
GDK_NOTE (DND, g_print ("gdk_win32_drag_drop\n"));
|
||||
|
||||
ddd = g_hash_table_lookup (clipdrop->active_source_drags, drag);
|
||||
if (drag_win32->protocol == GDK_DRAG_PROTO_LOCAL)
|
||||
{
|
||||
GdkDrop *drop = _gdk_win32_get_drop_for_dest_window (drag_win32->dest_window);
|
||||
|
||||
drag_win32->util_data.state = GDK_WIN32_DND_DROPPED;
|
||||
if (drop)
|
||||
{
|
||||
GdkDragAction actions;
|
||||
|
||||
if (ddd)
|
||||
send_source_state_update (clipdrop, drag_win32, ddd);
|
||||
actions = gdk_drag_get_actions (drag);
|
||||
_gdk_win32_local_drop_target_drop (drop, drag, time_, &actions);
|
||||
maybe_emit_action_changed (drag_win32, actions);
|
||||
_gdk_win32_local_drag_drop_response (drag, actions);
|
||||
}
|
||||
}
|
||||
else if (drag_win32->protocol == GDK_DRAG_PROTO_OLE2)
|
||||
{
|
||||
gpointer ddd = g_hash_table_lookup (clipdrop->active_source_drags, drag);
|
||||
|
||||
drag_win32->util_data.state = GDK_WIN32_DND_DROPPED;
|
||||
|
||||
if (ddd)
|
||||
send_source_state_update (clipdrop, drag_win32, ddd);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1875,8 +2123,6 @@ gdk_win32_drag_drop_done (GdkDrag *drag,
|
||||
{
|
||||
GdkWin32Drag *drag_win32 = GDK_WIN32_DRAG (drag);
|
||||
GdkDragAnim *anim;
|
||||
GdkWin32Clipdrop *clipdrop;
|
||||
gpointer ddd;
|
||||
/*
|
||||
cairo_surface_t *win_surface;
|
||||
cairo_surface_t *surface;
|
||||
@@ -1891,16 +2137,23 @@ gdk_win32_drag_drop_done (GdkDrag *drag,
|
||||
/* FIXME: This is temporary, until the code is fixed to ensure that
|
||||
* gdk_drag_finish () is called by GTK.
|
||||
*/
|
||||
clipdrop = _gdk_win32_clipdrop_get ();
|
||||
ddd = g_hash_table_lookup (clipdrop->active_source_drags, drag);
|
||||
if (drag_win32->protocol == GDK_DRAG_PROTO_OLE2)
|
||||
{
|
||||
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
|
||||
gpointer ddd = g_hash_table_lookup (clipdrop->active_source_drags, drag);
|
||||
|
||||
if (success)
|
||||
drag_win32->util_data.state = GDK_WIN32_DND_DROPPED;
|
||||
else
|
||||
drag_win32->util_data.state = GDK_WIN32_DND_NONE;
|
||||
if (success)
|
||||
drag_win32->util_data.state = GDK_WIN32_DND_DROPPED;
|
||||
else
|
||||
drag_win32->util_data.state = GDK_WIN32_DND_NONE;
|
||||
|
||||
if (ddd)
|
||||
send_source_state_update (clipdrop, drag_win32, ddd);
|
||||
if (ddd)
|
||||
send_source_state_update (clipdrop, drag_win32, ddd);
|
||||
}
|
||||
else if (drag_win32->protocol == GDK_DRAG_PROTO_LOCAL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
drag_win32->handle_events = FALSE;
|
||||
|
||||
@@ -1943,7 +2196,7 @@ gdk_win32_drag_drop_done (GdkDrag *drag,
|
||||
id = g_timeout_add_full (G_PRIORITY_DEFAULT, 17,
|
||||
gdk_drag_anim_timeout, anim,
|
||||
(GDestroyNotify) gdk_drag_anim_destroy);
|
||||
gdk_source_set_static_name_by_id (id, "[gtk] gdk_drag_anim_timeout");
|
||||
g_source_set_name_by_id (id, "[gtk] gdk_drag_anim_timeout");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -2026,6 +2279,14 @@ gdk_win32_drag_cancel (GdkDrag *drag,
|
||||
drag,
|
||||
reason_str));
|
||||
|
||||
if (drag_win32->protocol == GDK_DRAG_PROTO_LOCAL)
|
||||
{
|
||||
GdkDrop *drop = _gdk_win32_get_drop_for_dest_window (drag_win32->dest_window);
|
||||
if (drop)
|
||||
_gdk_win32_local_drop_target_dragleave (drop, GDK_CURRENT_TIME);
|
||||
drop = NULL;
|
||||
}
|
||||
|
||||
gdk_drag_set_cursor (drag, NULL);
|
||||
drag_context_ungrab (drag);
|
||||
gdk_drag_drop_done (drag, FALSE);
|
||||
@@ -2047,6 +2308,28 @@ gdk_win32_drag_drop_performed (GdkDrag *drag,
|
||||
#define BIG_STEP 20
|
||||
#define SMALL_STEP 1
|
||||
|
||||
static void
|
||||
gdk_local_drag_update (GdkDrag *drag,
|
||||
double x_root,
|
||||
double y_root,
|
||||
DWORD grfKeyState,
|
||||
guint32 evtime)
|
||||
{
|
||||
GdkWin32Drag *drag_win32 = GDK_WIN32_DRAG (drag);
|
||||
HWND dest_window;
|
||||
|
||||
g_assert (_win32_main_thread == NULL ||
|
||||
_win32_main_thread == g_thread_self ());
|
||||
|
||||
dest_window = gdk_win32_drag_find_window (drag,
|
||||
drag_win32->drag_surface,
|
||||
x_root, y_root);
|
||||
|
||||
gdk_win32_local_drag_motion (drag, dest_window, x_root, y_root,
|
||||
gdk_drag_get_actions (drag),
|
||||
grfKeyState, evtime);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_dnd_handle_motion_event (GdkDrag *drag,
|
||||
GdkEvent *event)
|
||||
@@ -2056,7 +2339,6 @@ gdk_dnd_handle_motion_event (GdkDrag *drag,
|
||||
DWORD key_state;
|
||||
double x, y;
|
||||
double x_root, y_root;
|
||||
GdkWin32Clipdrop *clipdrop;
|
||||
|
||||
GDK_NOTE (DND, g_print ("gdk_dnd_handle_motion_event: 0x%p\n", drag));
|
||||
|
||||
@@ -2071,18 +2353,26 @@ gdk_dnd_handle_motion_event (GdkDrag *drag,
|
||||
|
||||
key_state = manufacture_keystate_from_GMT (state);
|
||||
|
||||
clipdrop = _gdk_win32_clipdrop_get ();
|
||||
if (drag_win32->protocol == GDK_DRAG_PROTO_LOCAL)
|
||||
{
|
||||
gdk_local_drag_update (drag, x_root, y_root, key_state,
|
||||
gdk_event_get_time (event));
|
||||
}
|
||||
else if (drag_win32->protocol == GDK_DRAG_PROTO_OLE2)
|
||||
{
|
||||
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
|
||||
|
||||
GDK_NOTE (DND, g_print ("Post WM_MOUSEMOVE keystate=%lu\n", key_state));
|
||||
GDK_NOTE (DND, g_print ("Post WM_MOUSEMOVE keystate=%lu\n", key_state));
|
||||
|
||||
drag_win32->util_data.last_x = x_root;
|
||||
drag_win32->util_data.last_y = y_root;
|
||||
drag_win32->util_data.last_x = x_root;
|
||||
drag_win32->util_data.last_y = y_root;
|
||||
|
||||
API_CALL (PostThreadMessage, (clipdrop->dnd_thread_id,
|
||||
WM_MOUSEMOVE,
|
||||
key_state,
|
||||
MAKELPARAM (x * drag_win32->scale,
|
||||
y * drag_win32->scale)));
|
||||
API_CALL (PostThreadMessage, (clipdrop->dnd_thread_id,
|
||||
WM_MOUSEMOVE,
|
||||
key_state,
|
||||
MAKELPARAM (x * drag_win32->scale,
|
||||
y * drag_win32->scale)));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -2164,6 +2454,11 @@ gdk_dnd_handle_key_event (GdkDrag *drag,
|
||||
if (drag_win32->drag_surface)
|
||||
move_drag_surface (drag, drag_win32->util_data.last_x, drag_win32->util_data.last_y);
|
||||
|
||||
if (drag_win32->protocol == GDK_DRAG_PROTO_LOCAL)
|
||||
gdk_local_drag_update (drag, drag_win32->util_data.last_x, drag_win32->util_data.last_y,
|
||||
manufacture_keystate_from_GMT (state),
|
||||
gdk_event_get_time (event));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -140,6 +140,9 @@ struct _drop_target_context
|
||||
IDataObject *data_object;
|
||||
};
|
||||
|
||||
/* TRUE to use OLE2 protocol, FALSE to use local protocol */
|
||||
static gboolean use_ole2_dnd = TRUE;
|
||||
|
||||
static void
|
||||
gdk_win32_drop_init (GdkWin32Drop *drop)
|
||||
{
|
||||
@@ -193,6 +196,28 @@ gdk_drop_new (GdkDisplay *display,
|
||||
return GDK_DROP (drop_win32);
|
||||
}
|
||||
|
||||
/* Gets the GdkDrop that corresponds to a particular GdkSurface.
|
||||
* Will be NULL for surfaces that are not registered as drop targets,
|
||||
* or for surfaces that are currently not under the drag cursor.
|
||||
* This function is only used for local DnD, where we do have
|
||||
* a real GdkSurface that corresponds to the HWND under cursor.
|
||||
*/
|
||||
GdkDrop *
|
||||
_gdk_win32_get_drop_for_dest_surface (GdkSurface *dest)
|
||||
{
|
||||
GdkWin32Surface *impl;
|
||||
|
||||
if (dest == NULL)
|
||||
return NULL;
|
||||
|
||||
impl = GDK_WIN32_SURFACE (dest);
|
||||
|
||||
if (impl->drop_target != NULL)
|
||||
return impl->drop_target->drop;
|
||||
|
||||
return impl->drop;
|
||||
}
|
||||
|
||||
|
||||
#define PRINT_GUID(guid) \
|
||||
g_print ("%.08lx-%.04x-%.04x-%.02x%.02x-%.02x%.02x%.02x%.02x%.02x%.02x", \
|
||||
@@ -426,6 +451,51 @@ set_source_actions_helper (GdkDrop *drop,
|
||||
return actions;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_win32_local_drop_target_dragenter (GdkDrag *drag,
|
||||
GdkSurface *dest_surface,
|
||||
int x_root,
|
||||
int y_root,
|
||||
DWORD grfKeyState,
|
||||
guint32 time_,
|
||||
GdkDragAction *actions)
|
||||
{
|
||||
GdkDrop *drop;
|
||||
GdkWin32Drop *drop_win32;
|
||||
GdkDisplay *display;
|
||||
GdkDragAction source_actions;
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (dest_surface);
|
||||
|
||||
GDK_NOTE (DND, g_print ("_gdk_win32_local_drop_target_dragenter %p @ %d : %d"
|
||||
" for dest window 0x%p"
|
||||
". actions = %s\n",
|
||||
drag, x_root, y_root,
|
||||
dest_surface,
|
||||
_gdk_win32_drag_action_to_string (*actions)));
|
||||
|
||||
display = gdk_surface_get_display (dest_surface);
|
||||
drop = gdk_drop_new (display,
|
||||
gdk_seat_get_pointer (gdk_display_get_default_seat (display)),
|
||||
drag,
|
||||
gdk_drag_get_formats (drag),
|
||||
dest_surface,
|
||||
GDK_DRAG_PROTO_LOCAL);
|
||||
drop_win32 = GDK_WIN32_DROP (drop);
|
||||
|
||||
impl->drop = drop;
|
||||
|
||||
source_actions = set_source_actions_helper (drop, *actions, grfKeyState);
|
||||
|
||||
gdk_drop_emit_enter_event (drop, TRUE, x_root, y_root, time_);
|
||||
drop_win32->last_key_state = grfKeyState;
|
||||
drop_win32->last_x = x_root;
|
||||
drop_win32->last_y = y_root;
|
||||
*actions = filter_actions (drop_win32->actions, source_actions);
|
||||
|
||||
GDK_NOTE (DND, g_print ("_gdk_win32_local_drop_target_dragenter returns with actions %s\n",
|
||||
_gdk_win32_drag_action_to_string (*actions)));
|
||||
}
|
||||
|
||||
/* The pdwEffect here initially points
|
||||
* to a DWORD that contains the value of dwOKEffects argument in DoDragDrop,
|
||||
* i.e. the drag action that the drag source deems acceptable.
|
||||
@@ -505,6 +575,55 @@ idroptarget_dragenter (LPDROPTARGET This,
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gdk_win32_local_drop_target_will_emit_motion (GdkDrop *drop,
|
||||
int x_root,
|
||||
int y_root,
|
||||
DWORD grfKeyState)
|
||||
{
|
||||
GdkWin32Drop *drop_win32 = GDK_WIN32_DROP (drop);
|
||||
|
||||
if (x_root != drop_win32->last_x ||
|
||||
y_root != drop_win32->last_y ||
|
||||
grfKeyState != drop_win32->last_key_state)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_win32_local_drop_target_dragover (GdkDrop *drop,
|
||||
GdkDrag *drag,
|
||||
int x_root,
|
||||
int y_root,
|
||||
DWORD grfKeyState,
|
||||
guint32 time_,
|
||||
GdkDragAction *actions)
|
||||
{
|
||||
GdkWin32Drop *drop_win32 = GDK_WIN32_DROP (drop);
|
||||
GdkDragAction source_actions;
|
||||
|
||||
source_actions = set_source_actions_helper (drop, *actions, grfKeyState);
|
||||
|
||||
GDK_NOTE (DND, g_print ("_gdk_win32_local_drop_target_dragover %p @ %d : %d"
|
||||
", actions = %s\n",
|
||||
drop, x_root, y_root,
|
||||
_gdk_win32_drag_action_to_string (*actions)));
|
||||
|
||||
if (_gdk_win32_local_drop_target_will_emit_motion (drop, x_root, y_root, grfKeyState))
|
||||
{
|
||||
gdk_drop_emit_motion_event (drop, TRUE, x_root, y_root, time_);
|
||||
drop_win32->last_key_state = grfKeyState;
|
||||
drop_win32->last_x = x_root;
|
||||
drop_win32->last_y = y_root;
|
||||
}
|
||||
|
||||
*actions = filter_actions (drop_win32->actions, source_actions);
|
||||
|
||||
GDK_NOTE (DND, g_print ("_gdk_win32_local_drop_target_dragover returns with actions %s\n",
|
||||
_gdk_win32_drag_action_to_string (*actions)));
|
||||
}
|
||||
|
||||
/* NOTE: This method is called continuously, even if nothing is
|
||||
* happening, as long as the drag operation is in progress and
|
||||
* the cursor is above our window.
|
||||
@@ -562,6 +681,18 @@ idroptarget_dragover (LPDROPTARGET This,
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_win32_local_drop_target_dragleave (GdkDrop *drop,
|
||||
guint32 time_)
|
||||
{
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (gdk_drop_get_surface (drop));
|
||||
GDK_NOTE (DND, g_print ("_gdk_win32_local_drop_target_dragleave %p\n", drop));
|
||||
|
||||
gdk_drop_emit_leave_event (drop, TRUE, time_);
|
||||
|
||||
g_clear_object (&impl->drop);
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
idroptarget_dragleave (LPDROPTARGET This)
|
||||
{
|
||||
@@ -577,6 +708,35 @@ idroptarget_dragleave (LPDROPTARGET This)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_win32_local_drop_target_drop (GdkDrop *drop,
|
||||
GdkDrag *drag,
|
||||
guint32 time_,
|
||||
GdkDragAction *actions)
|
||||
{
|
||||
GdkWin32Drop *drop_win32 = GDK_WIN32_DROP (drop);
|
||||
|
||||
GDK_NOTE (DND, g_print ("_gdk_win32_local_drop_target_drop %p ", drop));
|
||||
|
||||
set_source_actions_helper (drop,
|
||||
*actions,
|
||||
drop_win32->last_key_state);
|
||||
|
||||
drop_win32->drop_finished = FALSE;
|
||||
gdk_drop_emit_drop_event (drop, TRUE, drop_win32->last_x, drop_win32->last_y, time_);
|
||||
|
||||
while (!drop_win32->drop_finished)
|
||||
g_main_context_iteration (NULL, FALSE);
|
||||
|
||||
/* Notify local source of the DnD result
|
||||
* Special case:
|
||||
* drop_win32->actions is guaranteed to contain 1 action after gdk_drop_finish ()
|
||||
*/
|
||||
*actions = drop_win32->actions;
|
||||
|
||||
GDK_NOTE (DND, g_print ("drop with action %s\n", _gdk_win32_drag_action_to_string (*actions)));
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
idroptarget_drop (LPDROPTARGET This,
|
||||
LPDATAOBJECT pDataObj,
|
||||
@@ -918,6 +1078,14 @@ gdk_win32_drop_status (GdkDrop *drop,
|
||||
_gdk_win32_drag_action_to_string (preferred)));
|
||||
|
||||
drop_win32->actions = actions;
|
||||
|
||||
if (drop_win32->protocol == GDK_DRAG_PROTO_OLE2)
|
||||
return;
|
||||
|
||||
drag = gdk_drop_get_drag (drop);
|
||||
|
||||
if (drag != NULL)
|
||||
_gdk_win32_local_drag_give_feedback (drag, actions);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -933,6 +1101,9 @@ gdk_win32_drop_finish (GdkDrop *drop,
|
||||
|
||||
drop_win32->actions = action;
|
||||
drop_win32->drop_finished = TRUE;
|
||||
|
||||
if (drop_win32->protocol == GDK_DRAG_PROTO_OLE2)
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@ -965,7 +1136,6 @@ _gdk_win32_surface_register_dnd (GdkSurface *window)
|
||||
{
|
||||
drop_target_context *ctx;
|
||||
HRESULT hr;
|
||||
GdkWin32Surface *impl;
|
||||
|
||||
g_return_if_fail (window != NULL);
|
||||
|
||||
@@ -976,30 +1146,43 @@ _gdk_win32_surface_register_dnd (GdkSurface *window)
|
||||
|
||||
GDK_NOTE (DND, g_print ("gdk_win32_surface_register_dnd: %p\n", GDK_SURFACE_HWND (window)));
|
||||
|
||||
impl = GDK_WIN32_SURFACE (window);
|
||||
|
||||
/* Return if window is already setup for DND. */
|
||||
if (impl->drop_target != NULL)
|
||||
return;
|
||||
|
||||
ctx = target_context_new (window);
|
||||
|
||||
hr = CoLockObjectExternal ((IUnknown *) &ctx->idt, TRUE, FALSE);
|
||||
if (!SUCCEEDED (hr))
|
||||
OTHER_API_FAILED ("CoLockObjectExternal");
|
||||
if (!use_ole2_dnd)
|
||||
{
|
||||
/* We always claim to accept dropped files, but in fact we might not,
|
||||
* of course. This function is called in such a way that it cannot know
|
||||
* whether the window (widget) in question actually accepts files
|
||||
* (in gtk, data of type text/uri-list) or not.
|
||||
*/
|
||||
gdk_win32_display_add_filter (GDK_WIN32_DISPLAY (gdk_display_get_default ()), gdk_dropfiles_filter, NULL);
|
||||
DragAcceptFiles (GDK_SURFACE_HWND (window), TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = RegisterDragDrop (GDK_SURFACE_HWND (window), &ctx->idt);
|
||||
if (hr == DRAGDROP_E_ALREADYREGISTERED)
|
||||
{
|
||||
g_print ("DRAGDROP_E_ALREADYREGISTERED\n");
|
||||
CoLockObjectExternal ((IUnknown *) &ctx->idt, FALSE, FALSE);
|
||||
}
|
||||
else if (!SUCCEEDED (hr))
|
||||
OTHER_API_FAILED ("RegisterDragDrop");
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (window);
|
||||
|
||||
/* Return if window is already setup for DND. */
|
||||
if (impl->drop_target != NULL)
|
||||
return;
|
||||
|
||||
ctx = target_context_new (window);
|
||||
|
||||
hr = CoLockObjectExternal ((IUnknown *) &ctx->idt, TRUE, FALSE);
|
||||
if (!SUCCEEDED (hr))
|
||||
OTHER_API_FAILED ("CoLockObjectExternal");
|
||||
else
|
||||
{
|
||||
impl->drop_target = ctx;
|
||||
hr = RegisterDragDrop (GDK_SURFACE_HWND (window), &ctx->idt);
|
||||
if (hr == DRAGDROP_E_ALREADYREGISTERED)
|
||||
{
|
||||
g_print ("DRAGDROP_E_ALREADYREGISTERED\n");
|
||||
CoLockObjectExternal ((IUnknown *) &ctx->idt, FALSE, FALSE);
|
||||
}
|
||||
else if (!SUCCEEDED (hr))
|
||||
OTHER_API_FAILED ("RegisterDragDrop");
|
||||
else
|
||||
{
|
||||
impl->drop_target = ctx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1235,3 +1418,10 @@ gdk_win32_drop_class_init (GdkWin32DropClass *klass)
|
||||
drop_class->read_async = gdk_win32_drop_read_async;
|
||||
drop_class->read_finish = gdk_win32_drop_read_finish;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_drop_init (void)
|
||||
{
|
||||
if (g_strcmp0 (getenv ("GDK_WIN32_OLE2_DND"), "0") == 0)
|
||||
use_ole2_dnd = FALSE;
|
||||
}
|
||||
|
||||
@@ -55,15 +55,12 @@
|
||||
#include "gdkdevicemanager-win32.h"
|
||||
#include "gdkdisplay-win32.h"
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include "gdkdevice-virtual.h"
|
||||
#include "gdkdevice-wintab.h"
|
||||
#include "gdkinput-winpointer.h"
|
||||
#include "gdkwin32dnd.h"
|
||||
#include "gdkwin32dnd-private.h"
|
||||
#include "gdkdisplay-win32.h"
|
||||
//#include "gdkselection-win32.h"
|
||||
#include "gdkdragprivate.h"
|
||||
#include "gdk-private.h"
|
||||
|
||||
#include <windowsx.h>
|
||||
|
||||
@@ -73,9 +70,8 @@
|
||||
#endif
|
||||
|
||||
#include <objbase.h>
|
||||
|
||||
#include <imm.h>
|
||||
#include <tchar.h>
|
||||
#include <tpcshrd.h>
|
||||
|
||||
#define GDK_MOD2_MASK (1 << 4)
|
||||
|
||||
@@ -166,10 +162,6 @@ static int both_shift_pressed[2]; /* to store keycodes for shift keys */
|
||||
static HHOOK keyboard_hook = NULL;
|
||||
static UINT aerosnap_message;
|
||||
|
||||
static gboolean pen_touch_input;
|
||||
static POINT pen_touch_cursor_position;
|
||||
static LONG last_digitizer_time;
|
||||
|
||||
static void
|
||||
track_mouse_event (DWORD dwFlags,
|
||||
HWND hwnd)
|
||||
@@ -204,18 +196,6 @@ _gdk_win32_get_next_tick (gulong suggested_tick)
|
||||
return cur_tick = suggested_tick;
|
||||
}
|
||||
|
||||
BOOL
|
||||
_gdk_win32_get_cursor_pos (LPPOINT lpPoint)
|
||||
{
|
||||
if (pen_touch_input)
|
||||
{
|
||||
*lpPoint = pen_touch_cursor_position;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return GetCursorPos (lpPoint);
|
||||
}
|
||||
|
||||
static void
|
||||
generate_focus_event (GdkDeviceManagerWin32 *device_manager,
|
||||
GdkSurface *window,
|
||||
@@ -522,7 +502,7 @@ _gdk_events_init (GdkDisplay *display)
|
||||
#endif
|
||||
|
||||
source = g_source_new (&event_funcs, sizeof (GdkWin32EventSource));
|
||||
g_source_set_static_name (source, "GDK Win32 event source");
|
||||
g_source_set_name (source, "GDK Win32 event source");
|
||||
g_source_set_priority (source, GDK_PRIORITY_EVENTS);
|
||||
|
||||
event_source = (GdkWin32EventSource *)source;
|
||||
@@ -1055,12 +1035,11 @@ do_show_window (GdkSurface *window, gboolean hide_window)
|
||||
|
||||
static void
|
||||
send_crossing_event (GdkDisplay *display,
|
||||
GdkDevice *physical_device,
|
||||
GdkSurface *window,
|
||||
GdkSurface *window,
|
||||
GdkEventType type,
|
||||
GdkCrossingMode mode,
|
||||
GdkNotifyType notify_type,
|
||||
GdkSurface *subwindow,
|
||||
GdkSurface *subwindow,
|
||||
POINT *screen_pt,
|
||||
GdkModifierType mask,
|
||||
guint32 time_)
|
||||
@@ -1087,18 +1066,16 @@ send_crossing_event (GdkDisplay *display,
|
||||
pt = *screen_pt;
|
||||
ScreenToClient (GDK_SURFACE_HWND (window), &pt);
|
||||
|
||||
_gdk_device_virtual_set_active (_gdk_device_manager->core_pointer, physical_device);
|
||||
|
||||
event = gdk_crossing_event_new (type,
|
||||
window,
|
||||
device_manager->core_pointer,
|
||||
time_,
|
||||
_gdk_win32_get_next_tick (time_),
|
||||
mask,
|
||||
pt.x / impl->surface_scale,
|
||||
pt.y / impl->surface_scale,
|
||||
mode,
|
||||
notify_type);
|
||||
|
||||
|
||||
_gdk_win32_append_event (event);
|
||||
}
|
||||
|
||||
@@ -1141,9 +1118,8 @@ find_common_ancestor (GdkSurface *win1,
|
||||
|
||||
void
|
||||
synthesize_crossing_events (GdkDisplay *display,
|
||||
GdkDevice *physical_device,
|
||||
GdkSurface *src,
|
||||
GdkSurface *dest,
|
||||
GdkSurface *src,
|
||||
GdkSurface *dest,
|
||||
GdkCrossingMode mode,
|
||||
POINT *screen_pt,
|
||||
GdkModifierType mask,
|
||||
@@ -1176,7 +1152,6 @@ synthesize_crossing_events (GdkDisplay *display,
|
||||
else
|
||||
notify_type = GDK_NOTIFY_ANCESTOR;
|
||||
send_crossing_event (display,
|
||||
physical_device,
|
||||
a, GDK_LEAVE_NOTIFY,
|
||||
mode,
|
||||
notify_type,
|
||||
@@ -1196,7 +1171,6 @@ synthesize_crossing_events (GdkDisplay *display,
|
||||
while (win != c && win != NULL)
|
||||
{
|
||||
send_crossing_event (display,
|
||||
physical_device,
|
||||
win, GDK_LEAVE_NOTIFY,
|
||||
mode,
|
||||
notify_type,
|
||||
@@ -1239,7 +1213,6 @@ synthesize_crossing_events (GdkDisplay *display,
|
||||
next = b;
|
||||
|
||||
send_crossing_event (display,
|
||||
physical_device,
|
||||
win, GDK_ENTER_NOTIFY,
|
||||
mode,
|
||||
notify_type,
|
||||
@@ -1259,7 +1232,6 @@ synthesize_crossing_events (GdkDisplay *display,
|
||||
notify_type = GDK_NOTIFY_INFERIOR;
|
||||
|
||||
send_crossing_event (display,
|
||||
physical_device,
|
||||
b, GDK_ENTER_NOTIFY,
|
||||
mode,
|
||||
notify_type,
|
||||
@@ -1269,26 +1241,6 @@ synthesize_crossing_events (GdkDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
make_crossing_event (GdkDevice *physical_device,
|
||||
GdkSurface *surface,
|
||||
POINT *screen_pt,
|
||||
guint32 time_)
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_print (" mouse_window %p -> %p",
|
||||
mouse_window ? GDK_SURFACE_HWND (mouse_window) : NULL,
|
||||
surface ? GDK_SURFACE_HWND (surface) : NULL));
|
||||
synthesize_crossing_events (_gdk_display,
|
||||
physical_device,
|
||||
mouse_window, surface,
|
||||
GDK_CROSSING_NORMAL,
|
||||
screen_pt,
|
||||
0, /* TODO: Set right mask */
|
||||
time_,
|
||||
FALSE);
|
||||
g_set_object (&mouse_window, surface);
|
||||
}
|
||||
|
||||
/* Acquires actual client area size of the underlying native window.
|
||||
* Rectangle is in GDK screen coordinates (_gdk_offset_* is added).
|
||||
* Returns FALSE if configure events should be inhibited,
|
||||
@@ -1573,9 +1525,6 @@ generate_button_event (GdkEventType type,
|
||||
current_x = (gint16) GET_X_LPARAM (msg->lParam) / impl->surface_scale;
|
||||
current_y = (gint16) GET_Y_LPARAM (msg->lParam) / impl->surface_scale;
|
||||
|
||||
_gdk_device_virtual_set_active (_gdk_device_manager->core_pointer,
|
||||
_gdk_device_manager->system_pointer);
|
||||
|
||||
event = gdk_button_event_new (type,
|
||||
window,
|
||||
device_manager->core_pointer,
|
||||
@@ -1807,8 +1756,6 @@ gdk_event_translate (MSG *msg,
|
||||
GdkDeviceGrabInfo *pointer_grab = NULL;
|
||||
GdkSurface *grab_window = NULL;
|
||||
|
||||
crossing_cb_t crossing_cb = NULL;
|
||||
|
||||
int button;
|
||||
|
||||
char buf[256];
|
||||
@@ -2231,8 +2178,6 @@ gdk_event_translate (MSG *msg,
|
||||
g_print (" (%d,%d)",
|
||||
GET_X_LPARAM (msg->lParam), GET_Y_LPARAM (msg->lParam)));
|
||||
|
||||
pen_touch_input = FALSE;
|
||||
|
||||
g_set_object (&window, find_window_for_mouse_event (window, msg));
|
||||
/* TODO_CSW?: there used to some synthesize and propagate */
|
||||
if (GDK_SURFACE_DESTROYED (window))
|
||||
@@ -2275,8 +2220,6 @@ gdk_event_translate (MSG *msg,
|
||||
g_print (" (%d,%d)",
|
||||
GET_X_LPARAM (msg->lParam), GET_Y_LPARAM (msg->lParam)));
|
||||
|
||||
pen_touch_input = FALSE;
|
||||
|
||||
g_set_object (&window, find_window_for_mouse_event (window, msg));
|
||||
|
||||
if (pointer_grab == NULL && implicit_grab_surface != NULL)
|
||||
@@ -2301,12 +2244,11 @@ gdk_event_translate (MSG *msg,
|
||||
}
|
||||
|
||||
synthesize_crossing_events (display,
|
||||
_gdk_device_manager->system_pointer,
|
||||
implicit_grab_surface, new_window,
|
||||
GDK_CROSSING_UNGRAB,
|
||||
&msg->pt,
|
||||
0, /* TODO: Set right mask */
|
||||
_gdk_win32_get_next_tick (msg->time),
|
||||
msg->time,
|
||||
FALSE);
|
||||
g_set_object (&implicit_grab_surface, NULL);
|
||||
g_set_object (&mouse_window, new_window);
|
||||
@@ -2335,23 +2277,6 @@ gdk_event_translate (MSG *msg,
|
||||
(gpointer) msg->wParam,
|
||||
GET_X_LPARAM (msg->lParam), GET_Y_LPARAM (msg->lParam)));
|
||||
|
||||
/* Even if we handle WM_POINTER messages, synthetic WM_MOUSEMOVE messages
|
||||
* are still sent occasionally by the OS, e.g. when a surface is hidden
|
||||
* or shown. Discard spurious WM_MOUSEMOVE messages while handling pen or
|
||||
* touch input
|
||||
*
|
||||
* See the article
|
||||
* "Why do I get spurious WM_MOUSEMOVE messages?" by Raymond Chen:
|
||||
* https://devblogs.microsoft.com/oldnewthing/20031001-00/?p=42343
|
||||
*
|
||||
*/
|
||||
if (win32_display->tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINPOINTER &&
|
||||
( (msg->time - last_digitizer_time) < 200 ||
|
||||
-(msg->time - last_digitizer_time) < 200 ))
|
||||
break;
|
||||
|
||||
pen_touch_input = FALSE;
|
||||
|
||||
new_window = window;
|
||||
|
||||
if (pointer_grab != NULL)
|
||||
@@ -2379,16 +2304,15 @@ gdk_event_translate (MSG *msg,
|
||||
|
||||
if (mouse_window != new_window)
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_print (" mouse_window %p -> %p",
|
||||
GDK_NOTE (EVENTS, g_print (" mouse_sinwod %p -> %p",
|
||||
mouse_window ? GDK_SURFACE_HWND (mouse_window) : NULL,
|
||||
new_window ? GDK_SURFACE_HWND (new_window) : NULL));
|
||||
synthesize_crossing_events (display,
|
||||
_gdk_device_manager->system_pointer,
|
||||
mouse_window, new_window,
|
||||
GDK_CROSSING_NORMAL,
|
||||
&msg->pt,
|
||||
0, /* TODO: Set right mask */
|
||||
_gdk_win32_get_next_tick (msg->time),
|
||||
msg->time,
|
||||
FALSE);
|
||||
g_set_object (&mouse_window, new_window);
|
||||
mouse_window_ignored_leave = NULL;
|
||||
@@ -2426,9 +2350,6 @@ gdk_event_translate (MSG *msg,
|
||||
current_x = (gint16) GET_X_LPARAM (msg->lParam) / impl->surface_scale;
|
||||
current_y = (gint16) GET_Y_LPARAM (msg->lParam) / impl->surface_scale;
|
||||
|
||||
_gdk_device_virtual_set_active (_gdk_device_manager->core_pointer,
|
||||
_gdk_device_manager->system_pointer);
|
||||
|
||||
event = gdk_motion_event_new (window,
|
||||
device_manager_win32->core_pointer,
|
||||
NULL,
|
||||
@@ -2454,8 +2375,6 @@ gdk_event_translate (MSG *msg,
|
||||
GDK_NOTE (EVENTS, g_print (" %d (%ld,%ld)",
|
||||
HIWORD (msg->wParam), msg->pt.x, msg->pt.y));
|
||||
|
||||
pen_touch_input = FALSE;
|
||||
|
||||
new_window = NULL;
|
||||
hwnd = WindowFromPoint (msg->pt);
|
||||
ignore_leave = FALSE;
|
||||
@@ -2481,12 +2400,11 @@ gdk_event_translate (MSG *msg,
|
||||
|
||||
if (!ignore_leave)
|
||||
synthesize_crossing_events (display,
|
||||
_gdk_device_manager->system_pointer,
|
||||
mouse_window, new_window,
|
||||
GDK_CROSSING_NORMAL,
|
||||
&msg->pt,
|
||||
0, /* TODO: Set right mask */
|
||||
_gdk_win32_get_next_tick (msg->time),
|
||||
msg->time,
|
||||
FALSE);
|
||||
g_set_object (&mouse_window, new_window);
|
||||
mouse_window_ignored_leave = ignore_leave ? new_window : NULL;
|
||||
@@ -2495,213 +2413,6 @@ gdk_event_translate (MSG *msg,
|
||||
return_val = TRUE;
|
||||
break;
|
||||
|
||||
case WM_POINTERDOWN:
|
||||
if (win32_display->tablet_input_api != GDK_WIN32_TABLET_INPUT_API_WINPOINTER ||
|
||||
gdk_winpointer_should_forward_message (msg))
|
||||
{
|
||||
return_val = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (IS_POINTER_PRIMARY_WPARAM (msg->wParam))
|
||||
{
|
||||
current_root_x = pen_touch_cursor_position.x = GET_X_LPARAM (msg->lParam);
|
||||
current_root_y = pen_touch_cursor_position.y = GET_Y_LPARAM (msg->lParam);
|
||||
pen_touch_input = TRUE;
|
||||
last_digitizer_time = msg->time;
|
||||
}
|
||||
|
||||
if (pointer_grab != NULL &&
|
||||
!pointer_grab->implicit &&
|
||||
!pointer_grab->owner_events)
|
||||
g_set_object (&window, pointer_grab->surface);
|
||||
|
||||
if (IS_POINTER_PRIMARY_WPARAM (msg->wParam) && mouse_window != window)
|
||||
crossing_cb = make_crossing_event;
|
||||
|
||||
gdk_winpointer_input_events (window, crossing_cb, msg);
|
||||
|
||||
*ret_valp = 0;
|
||||
return_val = TRUE;
|
||||
break;
|
||||
|
||||
case WM_POINTERUP:
|
||||
if (win32_display->tablet_input_api != GDK_WIN32_TABLET_INPUT_API_WINPOINTER ||
|
||||
gdk_winpointer_should_forward_message (msg))
|
||||
{
|
||||
return_val = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (IS_POINTER_PRIMARY_WPARAM (msg->wParam))
|
||||
{
|
||||
current_root_x = pen_touch_cursor_position.x = GET_X_LPARAM (msg->lParam);
|
||||
current_root_y = pen_touch_cursor_position.y = GET_Y_LPARAM (msg->lParam);
|
||||
pen_touch_input = TRUE;
|
||||
last_digitizer_time = msg->time;
|
||||
}
|
||||
|
||||
if (pointer_grab != NULL &&
|
||||
!pointer_grab->implicit &&
|
||||
!pointer_grab->owner_events)
|
||||
g_set_object (&window, pointer_grab->surface);
|
||||
|
||||
gdk_winpointer_input_events (window, NULL, msg);
|
||||
|
||||
impl = GDK_WIN32_SURFACE (window);
|
||||
if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
|
||||
{
|
||||
gdk_win32_surface_end_move_resize_drag (window);
|
||||
}
|
||||
|
||||
*ret_valp = 0;
|
||||
return_val = TRUE;
|
||||
break;
|
||||
|
||||
case WM_POINTERUPDATE:
|
||||
if (win32_display->tablet_input_api != GDK_WIN32_TABLET_INPUT_API_WINPOINTER ||
|
||||
gdk_winpointer_should_forward_message (msg))
|
||||
{
|
||||
return_val = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (IS_POINTER_PRIMARY_WPARAM (msg->wParam))
|
||||
{
|
||||
current_root_x = pen_touch_cursor_position.x = GET_X_LPARAM (msg->lParam);
|
||||
current_root_y = pen_touch_cursor_position.y = GET_Y_LPARAM (msg->lParam);
|
||||
pen_touch_input = TRUE;
|
||||
last_digitizer_time = msg->time;
|
||||
}
|
||||
|
||||
if (pointer_grab != NULL &&
|
||||
!pointer_grab->implicit &&
|
||||
!pointer_grab->owner_events)
|
||||
g_set_object (&window, pointer_grab->surface);
|
||||
|
||||
if (IS_POINTER_PRIMARY_WPARAM (msg->wParam) && mouse_window != window)
|
||||
crossing_cb = make_crossing_event;
|
||||
|
||||
impl = GDK_WIN32_SURFACE (window);
|
||||
|
||||
if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
|
||||
{
|
||||
gdk_win32_surface_do_move_resize_drag (window, current_root_x, current_root_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdk_winpointer_input_events (window, crossing_cb, msg);
|
||||
}
|
||||
|
||||
*ret_valp = 0;
|
||||
return_val = TRUE;
|
||||
break;
|
||||
|
||||
case WM_NCPOINTERUPDATE:
|
||||
if (win32_display->tablet_input_api != GDK_WIN32_TABLET_INPUT_API_WINPOINTER ||
|
||||
gdk_winpointer_should_forward_message (msg))
|
||||
{
|
||||
return_val = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (IS_POINTER_PRIMARY_WPARAM (msg->wParam))
|
||||
{
|
||||
current_root_x = pen_touch_cursor_position.x = GET_X_LPARAM (msg->lParam);
|
||||
current_root_y = pen_touch_cursor_position.y = GET_Y_LPARAM (msg->lParam);
|
||||
pen_touch_input = TRUE;
|
||||
last_digitizer_time = msg->time;
|
||||
}
|
||||
|
||||
if (IS_POINTER_PRIMARY_WPARAM (msg->wParam) &&
|
||||
!IS_POINTER_INCONTACT_WPARAM (msg->wParam) &&
|
||||
mouse_window != NULL)
|
||||
{
|
||||
GdkDevice *event_device = NULL;
|
||||
guint32 event_time = 0;
|
||||
|
||||
if (gdk_winpointer_get_message_info (msg, &event_device, &event_time))
|
||||
{
|
||||
make_crossing_event(event_device,
|
||||
NULL,
|
||||
&pen_touch_cursor_position,
|
||||
event_time);
|
||||
}
|
||||
}
|
||||
|
||||
return_val = FALSE; /* forward to DefWindowProc */
|
||||
break;
|
||||
|
||||
case WM_POINTERENTER:
|
||||
if (win32_display->tablet_input_api != GDK_WIN32_TABLET_INPUT_API_WINPOINTER ||
|
||||
gdk_winpointer_should_forward_message (msg))
|
||||
{
|
||||
return_val = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (IS_POINTER_PRIMARY_WPARAM (msg->wParam))
|
||||
{
|
||||
current_root_x = pen_touch_cursor_position.x = GET_X_LPARAM (msg->lParam);
|
||||
current_root_y = pen_touch_cursor_position.y = GET_Y_LPARAM (msg->lParam);
|
||||
pen_touch_input = TRUE;
|
||||
last_digitizer_time = msg->time;
|
||||
}
|
||||
|
||||
if (pointer_grab != NULL &&
|
||||
!pointer_grab->implicit &&
|
||||
!pointer_grab->owner_events)
|
||||
g_set_object (&window, pointer_grab->surface);
|
||||
|
||||
if (IS_POINTER_NEW_WPARAM (msg->wParam))
|
||||
{
|
||||
gdk_winpointer_input_events (window, NULL, msg);
|
||||
}
|
||||
|
||||
*ret_valp = 0;
|
||||
return_val = TRUE;
|
||||
break;
|
||||
|
||||
case WM_POINTERLEAVE:
|
||||
if (win32_display->tablet_input_api != GDK_WIN32_TABLET_INPUT_API_WINPOINTER ||
|
||||
gdk_winpointer_should_forward_message (msg))
|
||||
{
|
||||
return_val = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (IS_POINTER_PRIMARY_WPARAM (msg->wParam))
|
||||
{
|
||||
current_root_x = pen_touch_cursor_position.x = GET_X_LPARAM (msg->lParam);
|
||||
current_root_y = pen_touch_cursor_position.y = GET_Y_LPARAM (msg->lParam);
|
||||
pen_touch_input = TRUE;
|
||||
last_digitizer_time = msg->time;
|
||||
}
|
||||
|
||||
if (!IS_POINTER_INRANGE_WPARAM (msg->wParam))
|
||||
{
|
||||
gdk_winpointer_input_events (window, NULL, msg);
|
||||
}
|
||||
else if (IS_POINTER_PRIMARY_WPARAM (msg->wParam) && mouse_window != NULL)
|
||||
{
|
||||
GdkDevice *event_device = NULL;
|
||||
guint32 event_time = 0;
|
||||
|
||||
if (gdk_winpointer_get_message_info (msg, &event_device, &event_time))
|
||||
{
|
||||
make_crossing_event(event_device,
|
||||
NULL,
|
||||
&pen_touch_cursor_position,
|
||||
event_time);
|
||||
}
|
||||
}
|
||||
|
||||
gdk_winpointer_interaction_ended (msg);
|
||||
|
||||
*ret_valp = 0;
|
||||
return_val = TRUE;
|
||||
break;
|
||||
|
||||
case WM_MOUSEWHEEL:
|
||||
case WM_MOUSEHWHEEL:
|
||||
GDK_NOTE (EVENTS, g_print (" %d", (short) HIWORD (msg->wParam)));
|
||||
@@ -2764,9 +2475,6 @@ gdk_event_translate (MSG *msg,
|
||||
*/
|
||||
delta_y *= -1.0;
|
||||
|
||||
_gdk_device_virtual_set_active (_gdk_device_manager->core_pointer,
|
||||
_gdk_device_manager->system_pointer);
|
||||
|
||||
event = gdk_scroll_event_new (window,
|
||||
device_manager_win32->core_pointer,
|
||||
NULL,
|
||||
@@ -2800,6 +2508,44 @@ gdk_event_translate (MSG *msg,
|
||||
return_val = TRUE;
|
||||
break;
|
||||
|
||||
case WM_HSCROLL:
|
||||
/* Just print more debugging information, don't actually handle it. */
|
||||
GDK_NOTE (EVENTS,
|
||||
(g_print (" %s",
|
||||
(LOWORD (msg->wParam) == SB_ENDSCROLL ? "ENDSCROLL" :
|
||||
(LOWORD (msg->wParam) == SB_LEFT ? "LEFT" :
|
||||
(LOWORD (msg->wParam) == SB_RIGHT ? "RIGHT" :
|
||||
(LOWORD (msg->wParam) == SB_LINELEFT ? "LINELEFT" :
|
||||
(LOWORD (msg->wParam) == SB_LINERIGHT ? "LINERIGHT" :
|
||||
(LOWORD (msg->wParam) == SB_PAGELEFT ? "PAGELEFT" :
|
||||
(LOWORD (msg->wParam) == SB_PAGERIGHT ? "PAGERIGHT" :
|
||||
(LOWORD (msg->wParam) == SB_THUMBPOSITION ? "THUMBPOSITION" :
|
||||
(LOWORD (msg->wParam) == SB_THUMBTRACK ? "THUMBTRACK" :
|
||||
"???")))))))))),
|
||||
(LOWORD (msg->wParam) == SB_THUMBPOSITION ||
|
||||
LOWORD (msg->wParam) == SB_THUMBTRACK) ?
|
||||
(g_print (" %d", HIWORD (msg->wParam)), 0) : 0));
|
||||
break;
|
||||
|
||||
case WM_VSCROLL:
|
||||
/* Just print more debugging information, don't actually handle it. */
|
||||
GDK_NOTE (EVENTS,
|
||||
(g_print (" %s",
|
||||
(LOWORD (msg->wParam) == SB_ENDSCROLL ? "ENDSCROLL" :
|
||||
(LOWORD (msg->wParam) == SB_BOTTOM ? "BOTTOM" :
|
||||
(LOWORD (msg->wParam) == SB_TOP ? "TOP" :
|
||||
(LOWORD (msg->wParam) == SB_LINEDOWN ? "LINDOWN" :
|
||||
(LOWORD (msg->wParam) == SB_LINEUP ? "LINEUP" :
|
||||
(LOWORD (msg->wParam) == SB_PAGEDOWN ? "PAGEDOWN" :
|
||||
(LOWORD (msg->wParam) == SB_PAGEUP ? "PAGEUP" :
|
||||
(LOWORD (msg->wParam) == SB_THUMBPOSITION ? "THUMBPOSITION" :
|
||||
(LOWORD (msg->wParam) == SB_THUMBTRACK ? "THUMBTRACK" :
|
||||
"???")))))))))),
|
||||
(LOWORD (msg->wParam) == SB_THUMBPOSITION ||
|
||||
LOWORD (msg->wParam) == SB_THUMBTRACK) ?
|
||||
(g_print (" %d", HIWORD (msg->wParam)), 0) : 0));
|
||||
break;
|
||||
|
||||
case WM_MOUSEACTIVATE:
|
||||
{
|
||||
if (GDK_IS_DRAG_SURFACE (window))
|
||||
@@ -2817,16 +2563,6 @@ gdk_event_translate (MSG *msg,
|
||||
|
||||
break;
|
||||
|
||||
case WM_POINTERACTIVATE:
|
||||
if (GDK_IS_DRAG_SURFACE (window) ||
|
||||
_gdk_modal_blocked (window))
|
||||
{
|
||||
*ret_valp = PA_NOACTIVATE;
|
||||
return_val = TRUE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WM_KILLFOCUS:
|
||||
if (keyboard_grab != NULL &&
|
||||
!GDK_SURFACE_DESTROYED (keyboard_grab->surface) &&
|
||||
@@ -3218,13 +2954,6 @@ gdk_event_translate (MSG *msg,
|
||||
*ret_valp = 0;
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
if (win32_display->tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINPOINTER)
|
||||
gdk_winpointer_finalize_surface (window);
|
||||
|
||||
return_val = FALSE;
|
||||
break;
|
||||
|
||||
case WM_NCDESTROY:
|
||||
if ((pointer_grab != NULL && pointer_grab->surface == window) ||
|
||||
(keyboard_grab && keyboard_grab->surface == window))
|
||||
@@ -3305,15 +3034,12 @@ gdk_event_translate (MSG *msg,
|
||||
{
|
||||
gdk_synthesize_surface_state (window, 0, GDK_TOPLEVEL_STATE_FOCUSED);
|
||||
|
||||
if (win32_display->tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINTAB)
|
||||
{
|
||||
/* Bring any tablet contexts to the top of the overlap order when
|
||||
* one of our windows is activated.
|
||||
* NOTE: It doesn't seem to work well if it is done in WM_ACTIVATEAPP
|
||||
* instead
|
||||
*/
|
||||
_gdk_wintab_set_tablet_active ();
|
||||
}
|
||||
/* Bring any tablet contexts to the top of the overlap order when
|
||||
* one of our windows is activated.
|
||||
* NOTE: It doesn't seem to work well if it is done in WM_ACTIVATEAPP
|
||||
* instead
|
||||
*/
|
||||
_gdk_input_set_tablet_active ();
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -3330,16 +3056,6 @@ gdk_event_translate (MSG *msg,
|
||||
GET_Y_LPARAM (msg->lParam), ret_valp);
|
||||
break;
|
||||
|
||||
case WM_TABLET_QUERYSYSTEMGESTURESTATUS:
|
||||
*ret_valp = TABLET_DISABLE_PRESSANDHOLD |
|
||||
TABLET_DISABLE_PENTAPFEEDBACK |
|
||||
TABLET_DISABLE_PENBARRELFEEDBACK |
|
||||
TABLET_DISABLE_FLICKS |
|
||||
TABLET_DISABLE_FLICKFALLBACKKEYS;
|
||||
return_val = TRUE;
|
||||
break;
|
||||
|
||||
|
||||
/* Handle WINTAB events here, as we know that the device manager will
|
||||
* use the fixed WT_DEFBASE as lcMsgBase, and we thus can use the
|
||||
* constants as case labels.
|
||||
@@ -3362,14 +3078,11 @@ gdk_event_translate (MSG *msg,
|
||||
/* Fall through */
|
||||
wintab:
|
||||
|
||||
if (win32_display->tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINTAB)
|
||||
event = gdk_input_other_event (display, msg, window);
|
||||
if (event)
|
||||
{
|
||||
event = gdk_wintab_make_event (display, msg, window);
|
||||
if (event)
|
||||
{
|
||||
_gdk_win32_append_event (event);
|
||||
gdk_event_unref (event);
|
||||
}
|
||||
_gdk_win32_append_event (event);
|
||||
gdk_event_unref (event);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -277,7 +277,7 @@ gdk_win32_display_init_egl (GdkDisplay *display,
|
||||
display_win32->egl_disp = egl_disp;
|
||||
display_win32->egl_version = epoxy_egl_version (egl_disp);
|
||||
|
||||
eglBindAPI (EGL_OPENGL_ES_API);
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
display_win32->hasEglSurfacelessContext =
|
||||
epoxy_has_egl_extension (egl_disp, "EGL_KHR_surfaceless_context");
|
||||
|
||||
@@ -278,9 +278,6 @@ gdk_win32_display_init_wgl (GdkDisplay *display,
|
||||
if (best_idx == 0 ||
|
||||
!wglMakeCurrent (hdc, display_win32->dummy_context_wgl.hglrc))
|
||||
{
|
||||
if (display_win32->dummy_context_wgl.hglrc != NULL)
|
||||
wglDeleteContext (display_win32->dummy_context_wgl.hglrc);
|
||||
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("No GL implementation is available"));
|
||||
@@ -291,22 +288,6 @@ gdk_win32_display_init_wgl (GdkDisplay *display,
|
||||
display_win32->wgl_pixel_format = best_idx;
|
||||
display_win32->gl_version = epoxy_gl_version ();
|
||||
|
||||
/* We must have OpenGL/WGL 2.0 or later, or have the GL_ARB_shader_objects extension */
|
||||
if (display_win32->gl_version < 20)
|
||||
{
|
||||
if (!epoxy_has_gl_extension ("GL_ARB_shader_objects"))
|
||||
{
|
||||
wglMakeCurrent (NULL, NULL);
|
||||
wglDeleteContext (display_win32->dummy_context_wgl.hglrc);
|
||||
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("No GL implementation is available"));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
display_win32->hasWglARBCreateContext =
|
||||
epoxy_has_wgl_extension (hdc, "WGL_ARB_create_context");
|
||||
display_win32->hasWglEXTSwapControl =
|
||||
|
||||
@@ -42,6 +42,9 @@ HKL _gdk_input_locale;
|
||||
gboolean _gdk_input_locale_is_ime = FALSE;
|
||||
UINT _gdk_input_codepage;
|
||||
|
||||
int _gdk_input_ignore_wintab = FALSE;
|
||||
int _gdk_max_colors = 0;
|
||||
|
||||
GdkWin32ModalOpKind _modal_operation_in_progress = GDK_WIN32_MODAL_OP_NONE;
|
||||
HWND _modal_move_resize_window = NULL;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,43 +0,0 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2021 the GTK team
|
||||
*
|
||||
* 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 __GDK_INPUT_WINPOINTER_H__
|
||||
#define __GDK_INPUT_WINPOINTER_H__
|
||||
|
||||
#include "winpointer.h"
|
||||
|
||||
gboolean gdk_winpointer_initialize (void);
|
||||
|
||||
void gdk_winpointer_initialize_surface (GdkSurface *surface);
|
||||
void gdk_winpointer_finalize_surface (GdkSurface *surface);
|
||||
|
||||
typedef void
|
||||
(*crossing_cb_t)(GdkDevice *physical_device,
|
||||
GdkSurface *surface,
|
||||
POINT *screen_pt,
|
||||
guint32 time_);
|
||||
|
||||
gboolean gdk_winpointer_should_forward_message (MSG *msg);
|
||||
void gdk_winpointer_input_events (GdkSurface *surface,
|
||||
crossing_cb_t crossing_cb,
|
||||
MSG *msg);
|
||||
gboolean gdk_winpointer_get_message_info (MSG *msg,
|
||||
GdkDevice **device,
|
||||
guint32 *time_);
|
||||
void gdk_winpointer_interaction_ended (MSG *msg);
|
||||
|
||||
#endif /* __GDK_INPUT_WINPOINTER_H__ */
|
||||
@@ -54,6 +54,11 @@ _gdk_win32_surfaceing_init (void)
|
||||
{
|
||||
char buf[10];
|
||||
|
||||
if (getenv ("GDK_IGNORE_WINTAB") != NULL)
|
||||
_gdk_input_ignore_wintab = TRUE;
|
||||
else if (getenv ("GDK_USE_WINTAB") != NULL)
|
||||
_gdk_input_ignore_wintab = FALSE;
|
||||
|
||||
if (gdk_synchronize)
|
||||
GdiSetBatchLimit (1);
|
||||
|
||||
@@ -248,6 +253,7 @@ _gdk_win32_drag_protocol_to_string (GdkDragProtocol protocol)
|
||||
CASE (NONE);
|
||||
CASE (WIN32_DROPFILES);
|
||||
CASE (OLE2);
|
||||
CASE (LOCAL);
|
||||
#undef CASE
|
||||
default: return static_printf ("illegal_%d", protocol);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,22 @@
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined (_WIN32_WINNT) && WIN32_WINNT < 0x0601
|
||||
# undef _WIN32_WINNT
|
||||
|
||||
# define _WIN32_WINNT 0x0601
|
||||
# ifdef WINVER
|
||||
# undef WINVER
|
||||
# endif
|
||||
# define WINVER _WIN32_WINNT
|
||||
#elif !defined (_WIN32_WINNT)
|
||||
# define _WIN32_WINNT 0x0601
|
||||
# ifdef WINVER
|
||||
# undef WINVER
|
||||
# endif
|
||||
# define WINVER _WIN32_WINNT
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkprivate-win32.h"
|
||||
|
||||
@@ -25,6 +25,15 @@
|
||||
#ifndef __GDK_PRIVATE_WIN32_H__
|
||||
#define __GDK_PRIVATE_WIN32_H__
|
||||
|
||||
#ifndef WINVER
|
||||
/* Vista or newer */
|
||||
#define WINVER 0x0600
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT WINVER
|
||||
#endif
|
||||
|
||||
#include <gdk/gdkcursorprivate.h>
|
||||
#include <gdk/win32/gdksurface-win32.h>
|
||||
#include <gdk/win32/gdkwin32display.h>
|
||||
@@ -145,14 +154,13 @@ typedef enum
|
||||
GDK_DRAG_PROTO_NONE = 0,
|
||||
GDK_DRAG_PROTO_WIN32_DROPFILES,
|
||||
GDK_DRAG_PROTO_OLE2,
|
||||
GDK_DRAG_PROTO_LOCAL,
|
||||
} GdkDragProtocol;
|
||||
|
||||
GType _gdk_gc_win32_get_type (void);
|
||||
|
||||
gulong _gdk_win32_get_next_tick (gulong suggested_tick);
|
||||
|
||||
BOOL _gdk_win32_get_cursor_pos (LPPOINT lpPoint);
|
||||
|
||||
void _gdk_surface_init_position (GdkSurface *window);
|
||||
void _gdk_surface_move_resize_child (GdkSurface *window,
|
||||
int x,
|
||||
@@ -242,8 +250,6 @@ void _gdk_other_api_failed (const char *where,
|
||||
#define WIN32_GDI_FAILED(api) WIN32_API_FAILED (api)
|
||||
#define OTHER_API_FAILED(api) _gdk_other_api_failed (G_STRLOC, api)
|
||||
|
||||
#define WIN32_API_FAILED_LOG_ONCE(api) G_STMT_START { static gboolean logged = 0; if (!logged) { _gdk_win32_api_failed (G_STRLOC , api); logged = 1; }} G_STMT_END
|
||||
|
||||
/* These two macros call a GDI or other Win32 API and if the return
|
||||
* value is zero or NULL, print a warning message. The majority of GDI
|
||||
* calls return zero or NULL on failure. The value of the macros is nonzero
|
||||
@@ -307,6 +313,11 @@ extern HWND _modal_move_resize_window;
|
||||
void _gdk_win32_begin_modal_call (GdkWin32ModalOpKind kind);
|
||||
void _gdk_win32_end_modal_call (GdkWin32ModalOpKind kind);
|
||||
|
||||
|
||||
/* Options */
|
||||
extern gboolean _gdk_input_ignore_wintab;
|
||||
extern int _gdk_max_colors;
|
||||
|
||||
/* Convert a pixbuf to an HICON (or HCURSOR). Supports alpha under
|
||||
* Windows XP, thresholds alpha otherwise.
|
||||
*/
|
||||
@@ -431,6 +442,7 @@ BOOL WINAPI GtkShowWindow (GdkSurface *window,
|
||||
/* Initialization */
|
||||
void _gdk_win32_surfaceing_init (void);
|
||||
void _gdk_drag_init (void);
|
||||
void _gdk_drop_init (void);
|
||||
void _gdk_events_init (GdkDisplay *display);
|
||||
|
||||
#endif /* __GDK_PRIVATE_WIN32_H__ */
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define _WIN32_WINNT 0x0600
|
||||
|
||||
#include "gdk.h"
|
||||
#include "gdkprivate-win32.h"
|
||||
#include "gdkwin32screen.h"
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
#include "gdkmonitorprivate.h"
|
||||
#include "gdkwin32surface.h"
|
||||
#include "gdkwin32cursor.h"
|
||||
#include "gdkinput-winpointer.h"
|
||||
#include "gdkglcontext-win32.h"
|
||||
#include "gdkdisplay-win32.h"
|
||||
#include "gdkdevice-win32.h"
|
||||
@@ -205,6 +204,7 @@ gdk_surface_win32_finalize (GObject *object)
|
||||
}
|
||||
|
||||
_gdk_win32_surface_unregister_dnd (GDK_SURFACE (surface));
|
||||
g_clear_object (&surface->drop);
|
||||
|
||||
g_assert (surface->transient_owner == NULL);
|
||||
g_assert (surface->transient_children == NULL);
|
||||
@@ -646,9 +646,6 @@ _gdk_win32_display_create_surface (GdkDisplay *display,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (display_win32->tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINPOINTER)
|
||||
gdk_winpointer_initialize_surface (surface);
|
||||
|
||||
_gdk_win32_surface_enable_transparency (surface);
|
||||
_gdk_win32_surface_register_dnd (surface);
|
||||
|
||||
|
||||
@@ -251,6 +251,10 @@ struct _GdkWin32Surface
|
||||
* For OLE2 protocol only.
|
||||
*/
|
||||
drop_target_context *drop_target;
|
||||
/* Temporarily holds the GdkDrop currently associated with this window.
|
||||
* For LOCAL protocol only.
|
||||
*/
|
||||
GdkDrop *drop;
|
||||
|
||||
GdkSurface *transient_owner;
|
||||
GSList *transient_children;
|
||||
|
||||
@@ -93,6 +93,38 @@ struct _GdkWin32DragClass
|
||||
gpointer _gdk_win32_dnd_thread_main (gpointer data);
|
||||
|
||||
GdkDrag *_gdk_win32_find_drag_for_dest_window (HWND dest_window);
|
||||
GdkDrop *_gdk_win32_get_drop_for_dest_surface (GdkSurface *dest);
|
||||
|
||||
gboolean _gdk_win32_local_drop_target_will_emit_motion (GdkDrop *drop,
|
||||
int x_root,
|
||||
int y_root,
|
||||
DWORD grfKeyState);
|
||||
|
||||
void _gdk_win32_local_drop_target_dragenter (GdkDrag *drag,
|
||||
GdkSurface *dest_surface,
|
||||
int x_root,
|
||||
int y_root,
|
||||
DWORD grfKeyState,
|
||||
guint32 time_,
|
||||
GdkDragAction *actions);
|
||||
void _gdk_win32_local_drop_target_dragover (GdkDrop *drop,
|
||||
GdkDrag *drag,
|
||||
int x_root,
|
||||
int y_root,
|
||||
DWORD grfKeyState,
|
||||
guint32 time_,
|
||||
GdkDragAction *actions);
|
||||
void _gdk_win32_local_drop_target_dragleave (GdkDrop *drop,
|
||||
guint32 time_);
|
||||
void _gdk_win32_local_drop_target_drop (GdkDrop *drop,
|
||||
GdkDrag *drag,
|
||||
guint32 time_,
|
||||
GdkDragAction *actions);
|
||||
|
||||
void _gdk_win32_local_drag_give_feedback (GdkDrag *drag,
|
||||
GdkDragAction actions);
|
||||
void _gdk_win32_local_drag_drop_response (GdkDrag *drag,
|
||||
GdkDragAction action);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -6,7 +6,6 @@ gdk_win32_sources = files([
|
||||
'gdkdevicemanager-win32.c',
|
||||
'gdkdevice-virtual.c',
|
||||
'gdkdevice-win32.c',
|
||||
'gdkdevice-winpointer.c',
|
||||
'gdkdevice-wintab.c',
|
||||
'gdkdisplay-win32.c',
|
||||
'gdkdisplaymanager-win32.c',
|
||||
@@ -17,7 +16,6 @@ gdk_win32_sources = files([
|
||||
'gdkglcontext-win32-wgl.c',
|
||||
'gdkglobals-win32.c',
|
||||
'gdkhdataoutputstream-win32.c',
|
||||
'gdkinput-winpointer.c',
|
||||
'gdkkeys-win32.c',
|
||||
'gdkwin32langnotification.c',
|
||||
'gdkmain-win32.c',
|
||||
@@ -53,9 +51,8 @@ if win32_has_egl
|
||||
gdk_win32_sources += ['gdkglcontext-win32-egl.c']
|
||||
endif
|
||||
|
||||
gdk_win32_deps = [
|
||||
pangowin32_dep, # FIXME
|
||||
cc.find_library('hid'),
|
||||
gdk_win32_deps = [ # FIXME
|
||||
pangowin32_dep
|
||||
]
|
||||
|
||||
libgdk_win32 = static_library('gdk-win32',
|
||||
@@ -65,8 +62,6 @@ libgdk_win32 = static_library('gdk-win32',
|
||||
'-DGTK_COMPILATION',
|
||||
'-DG_LOG_DOMAIN="Gdk"',
|
||||
'-DINSIDE_GDK_WIN32',
|
||||
'-D_WIN32_WINNT=0x0601',
|
||||
'-DWINVER=0x0601',
|
||||
] + GDK_WIN32_EGL_CFLAGS,
|
||||
dependencies: [ gdk_deps, gdk_win32_deps ],
|
||||
)
|
||||
|
||||
@@ -1,320 +0,0 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2021 the GTK team
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* This code is derived from portions provided by the mingw-w64 project
|
||||
* (mingw-w64.org), originally licensed under the Zope Public License
|
||||
* (ZPL) version 2.1, with modifications made on May 12, 2021.
|
||||
* Legal notice of the Zope Public License version 2.1 follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions in source code must retain the accompanying copyright
|
||||
* notice, this list of conditions, and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the accompanying
|
||||
* copyright notice, this list of conditions, and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Names of the copyright holders must not be used to endorse or promote
|
||||
* products derived from this software without prior written permission
|
||||
* from the copyright holders.
|
||||
* 4. The right to distribute this software or to use it for any purpose does
|
||||
* not give you the right to use Servicemarks (sm) or Trademarks (tm) of
|
||||
* the copyright holders. Use of them is covered by separate agreement
|
||||
* with the copyright holders.
|
||||
* 5. If any files are modified, you must cause the modified files to carry
|
||||
* prominent notices stating that you changed the files and the date of
|
||||
* any change.
|
||||
*/
|
||||
|
||||
#ifndef POINTER_FLAG_NONE
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#define WM_POINTERDEVICECHANGE 0x238
|
||||
#define WM_POINTERDEVICEINRANGE 0x239
|
||||
#define WM_POINTERDEVICEOUTOFRANGE 0x23a
|
||||
|
||||
#define WM_NCPOINTERUPDATE 0x0241
|
||||
#define WM_NCPOINTERDOWN 0x0242
|
||||
#define WM_NCPOINTERUP 0x0243
|
||||
#define WM_POINTERUPDATE 0x0245
|
||||
#define WM_POINTERDOWN 0x0246
|
||||
#define WM_POINTERUP 0x0247
|
||||
#define WM_POINTERENTER 0x0249
|
||||
#define WM_POINTERLEAVE 0x024a
|
||||
#define WM_POINTERACTIVATE 0x024b
|
||||
#define WM_POINTERCAPTURECHANGED 0x024c
|
||||
#define WM_TOUCHHITTESTING 0x024d
|
||||
#define WM_POINTERWHEEL 0x024e
|
||||
#define WM_POINTERHWHEEL 0x024f
|
||||
#define DM_POINTERHITTEST 0x0250
|
||||
#define WM_POINTERROUTEDTO 0x0251
|
||||
#define WM_POINTERROUTEDAWAY 0x0252
|
||||
#define WM_POINTERROUTEDRELEASED 0x0253
|
||||
|
||||
#define POINTER_FLAG_NONE 0x00000000
|
||||
#define POINTER_FLAG_NEW 0x00000001
|
||||
#define POINTER_FLAG_INRANGE 0x00000002
|
||||
#define POINTER_FLAG_INCONTACT 0x00000004
|
||||
#define POINTER_FLAG_FIRSTBUTTON 0x00000010
|
||||
#define POINTER_FLAG_SECONDBUTTON 0x00000020
|
||||
#define POINTER_FLAG_THIRDBUTTON 0x00000040
|
||||
#define POINTER_FLAG_FOURTHBUTTON 0x00000080
|
||||
#define POINTER_FLAG_FIFTHBUTTON 0x00000100
|
||||
#define POINTER_FLAG_PRIMARY 0x00002000
|
||||
#define POINTER_FLAG_CONFIDENCE 0x00004000
|
||||
#define POINTER_FLAG_CANCELED 0x00008000
|
||||
#define POINTER_FLAG_DOWN 0x00010000
|
||||
#define POINTER_FLAG_UPDATE 0x00020000
|
||||
#define POINTER_FLAG_UP 0x00040000
|
||||
#define POINTER_FLAG_WHEEL 0x00080000
|
||||
#define POINTER_FLAG_HWHEEL 0x00100000
|
||||
#define POINTER_FLAG_CAPTURECHANGED 0x00200000
|
||||
#define POINTER_FLAG_HASTRANSFORM 0x00400000
|
||||
|
||||
#define POINTER_MOD_SHIFT (0x0004)
|
||||
#define POINTER_MOD_CTRL (0x0008)
|
||||
|
||||
#define TOUCH_FLAG_NONE 0x00000000
|
||||
|
||||
#define TOUCH_MASK_NONE 0x00000000
|
||||
#define TOUCH_MASK_CONTACTAREA 0x00000001
|
||||
#define TOUCH_MASK_ORIENTATION 0x00000002
|
||||
#define TOUCH_MASK_PRESSURE 0x00000004
|
||||
|
||||
#define PEN_FLAG_NONE 0x00000000
|
||||
#define PEN_FLAG_BARREL 0x00000001
|
||||
#define PEN_FLAG_INVERTED 0x00000002
|
||||
#define PEN_FLAG_ERASER 0x00000004
|
||||
|
||||
#define PEN_MASK_NONE 0x00000000
|
||||
#define PEN_MASK_PRESSURE 0x00000001
|
||||
#define PEN_MASK_ROTATION 0x00000002
|
||||
#define PEN_MASK_TILT_X 0x00000004
|
||||
#define PEN_MASK_TILT_Y 0x00000008
|
||||
|
||||
#define POINTER_MESSAGE_FLAG_NEW 0x00000001
|
||||
#define POINTER_MESSAGE_FLAG_INRANGE 0x00000002
|
||||
#define POINTER_MESSAGE_FLAG_INCONTACT 0x00000004
|
||||
#define POINTER_MESSAGE_FLAG_FIRSTBUTTON 0x00000010
|
||||
#define POINTER_MESSAGE_FLAG_SECONDBUTTON 0x00000020
|
||||
#define POINTER_MESSAGE_FLAG_THIRDBUTTON 0x00000040
|
||||
#define POINTER_MESSAGE_FLAG_FOURTHBUTTON 0x00000080
|
||||
#define POINTER_MESSAGE_FLAG_FIFTHBUTTON 0x00000100
|
||||
#define POINTER_MESSAGE_FLAG_PRIMARY 0x00002000
|
||||
#define POINTER_MESSAGE_FLAG_CONFIDENCE 0x00004000
|
||||
#define POINTER_MESSAGE_FLAG_CANCELED 0x00008000
|
||||
|
||||
#define GET_POINTERID_WPARAM(wParam) (LOWORD (wParam))
|
||||
#define IS_POINTER_FLAG_SET_WPARAM(wParam, flag) (((DWORD)HIWORD (wParam) &(flag)) == (flag))
|
||||
#define IS_POINTER_NEW_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM (wParam, POINTER_MESSAGE_FLAG_NEW)
|
||||
#define IS_POINTER_INRANGE_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM (wParam, POINTER_MESSAGE_FLAG_INRANGE)
|
||||
#define IS_POINTER_INCONTACT_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM (wParam, POINTER_MESSAGE_FLAG_INCONTACT)
|
||||
#define IS_POINTER_FIRSTBUTTON_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM (wParam, POINTER_MESSAGE_FLAG_FIRSTBUTTON)
|
||||
#define IS_POINTER_SECONDBUTTON_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM (wParam, POINTER_MESSAGE_FLAG_SECONDBUTTON)
|
||||
#define IS_POINTER_THIRDBUTTON_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM (wParam, POINTER_MESSAGE_FLAG_THIRDBUTTON)
|
||||
#define IS_POINTER_FOURTHBUTTON_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM (wParam, POINTER_MESSAGE_FLAG_FOURTHBUTTON)
|
||||
#define IS_POINTER_FIFTHBUTTON_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM (wParam, POINTER_MESSAGE_FLAG_FIFTHBUTTON)
|
||||
#define IS_POINTER_PRIMARY_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM (wParam, POINTER_MESSAGE_FLAG_PRIMARY)
|
||||
#define HAS_POINTER_CONFIDENCE_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM (wParam, POINTER_MESSAGE_FLAG_CONFIDENCE)
|
||||
#define IS_POINTER_CANCELED_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM (wParam, POINTER_MESSAGE_FLAG_CANCELED)
|
||||
|
||||
#define PA_ACTIVATE MA_ACTIVATE
|
||||
#define PA_NOACTIVATE MA_NOACTIVATE
|
||||
|
||||
typedef DWORD POINTER_INPUT_TYPE;
|
||||
typedef UINT32 POINTER_FLAGS;
|
||||
typedef UINT32 TOUCH_FLAGS;
|
||||
typedef UINT32 TOUCH_MASK;
|
||||
typedef UINT32 PEN_FLAGS;
|
||||
typedef UINT32 PEN_MASK;
|
||||
|
||||
enum tagPOINTER_INPUT_TYPE {
|
||||
PT_POINTER = 0x00000001,
|
||||
PT_TOUCH = 0x00000002,
|
||||
PT_PEN = 0x00000003,
|
||||
PT_MOUSE = 0x00000004,
|
||||
PT_TOUCHPAD = 0x00000005
|
||||
};
|
||||
|
||||
typedef enum tagFEEDBACK_TYPE {
|
||||
FEEDBACK_TOUCH_CONTACTVISUALIZATION = 1,
|
||||
FEEDBACK_PEN_BARRELVISUALIZATION = 2,
|
||||
FEEDBACK_PEN_TAP = 3,
|
||||
FEEDBACK_PEN_DOUBLETAP = 4,
|
||||
FEEDBACK_PEN_PRESSANDHOLD = 5,
|
||||
FEEDBACK_PEN_RIGHTTAP = 6,
|
||||
FEEDBACK_TOUCH_TAP = 7,
|
||||
FEEDBACK_TOUCH_DOUBLETAP = 8,
|
||||
FEEDBACK_TOUCH_PRESSANDHOLD = 9,
|
||||
FEEDBACK_TOUCH_RIGHTTAP = 10,
|
||||
FEEDBACK_GESTURE_PRESSANDTAP = 11,
|
||||
FEEDBACK_MAX = 0xffffffff
|
||||
} FEEDBACK_TYPE;
|
||||
|
||||
typedef enum tagPOINTER_BUTTON_CHANGE_TYPE {
|
||||
POINTER_CHANGE_NONE,
|
||||
POINTER_CHANGE_FIRSTBUTTON_DOWN,
|
||||
POINTER_CHANGE_FIRSTBUTTON_UP,
|
||||
POINTER_CHANGE_SECONDBUTTON_DOWN,
|
||||
POINTER_CHANGE_SECONDBUTTON_UP,
|
||||
POINTER_CHANGE_THIRDBUTTON_DOWN,
|
||||
POINTER_CHANGE_THIRDBUTTON_UP,
|
||||
POINTER_CHANGE_FOURTHBUTTON_DOWN,
|
||||
POINTER_CHANGE_FOURTHBUTTON_UP,
|
||||
POINTER_CHANGE_FIFTHBUTTON_DOWN,
|
||||
POINTER_CHANGE_FIFTHBUTTON_UP,
|
||||
} POINTER_BUTTON_CHANGE_TYPE;
|
||||
|
||||
typedef struct tagPOINTER_INFO {
|
||||
POINTER_INPUT_TYPE pointerType;
|
||||
UINT32 pointerId;
|
||||
UINT32 frameId;
|
||||
POINTER_FLAGS pointerFlags;
|
||||
HANDLE sourceDevice;
|
||||
HWND hwndTarget;
|
||||
POINT ptPixelLocation;
|
||||
POINT ptHimetricLocation;
|
||||
POINT ptPixelLocationRaw;
|
||||
POINT ptHimetricLocationRaw;
|
||||
DWORD dwTime;
|
||||
UINT32 historyCount;
|
||||
INT32 InputData;
|
||||
DWORD dwKeyStates;
|
||||
UINT64 PerformanceCount;
|
||||
POINTER_BUTTON_CHANGE_TYPE ButtonChangeType;
|
||||
} POINTER_INFO;
|
||||
|
||||
typedef struct tagPOINTER_TOUCH_INFO {
|
||||
POINTER_INFO pointerInfo;
|
||||
TOUCH_FLAGS touchFlags;
|
||||
TOUCH_MASK touchMask;
|
||||
RECT rcContact;
|
||||
RECT rcContactRaw;
|
||||
UINT32 orientation;
|
||||
UINT32 pressure;
|
||||
} POINTER_TOUCH_INFO;
|
||||
|
||||
typedef struct tagPOINTER_PEN_INFO {
|
||||
POINTER_INFO pointerInfo;
|
||||
PEN_FLAGS penFlags;
|
||||
PEN_MASK penMask;
|
||||
UINT32 pressure;
|
||||
UINT32 rotation;
|
||||
INT32 tiltX;
|
||||
INT32 tiltY;
|
||||
} POINTER_PEN_INFO;
|
||||
|
||||
typedef enum {
|
||||
POINTER_FEEDBACK_DEFAULT = 1,
|
||||
POINTER_FEEDBACK_INDIRECT = 2,
|
||||
POINTER_FEEDBACK_NONE = 3
|
||||
} POINTER_FEEDBACK_MODE;
|
||||
|
||||
typedef struct tagUSAGE_PROPERTIES {
|
||||
USHORT level;
|
||||
USHORT page;
|
||||
USHORT usage;
|
||||
INT32 logicalMinimum;
|
||||
INT32 logicalMaximum;
|
||||
USHORT unit;
|
||||
USHORT exponent;
|
||||
BYTE count;
|
||||
INT32 physicalMinimum;
|
||||
INT32 physicalMaximum;
|
||||
} USAGE_PROPERTIES, *PUSAGE_PROPERTIES;
|
||||
|
||||
typedef struct tagPOINTER_TYPE_INFO {
|
||||
POINTER_INPUT_TYPE type;
|
||||
union {
|
||||
POINTER_TOUCH_INFO touchInfo;
|
||||
POINTER_PEN_INFO penInfo;
|
||||
} DUMMYUNIONNAME;
|
||||
} POINTER_TYPE_INFO, *PPOINTER_TYPE_INFO;
|
||||
|
||||
#define POINTER_DEVICE_PRODUCT_STRING_MAX 520
|
||||
#define PDC_ARRIVAL 0x001
|
||||
#define PDC_REMOVAL 0x002
|
||||
#define PDC_ORIENTATION_0 0x004
|
||||
#define PDC_ORIENTATION_90 0x008
|
||||
#define PDC_ORIENTATION_180 0x010
|
||||
#define PDC_ORIENTATION_270 0x020
|
||||
#define PDC_MODE_DEFAULT 0x040
|
||||
#define PDC_MODE_CENTERED 0x080
|
||||
#define PDC_MAPPING_CHANGE 0x100
|
||||
#define PDC_RESOLUTION 0x200
|
||||
#define PDC_ORIGIN 0x400
|
||||
#define PDC_MODE_ASPECTRATIOPRESERVED 0x800
|
||||
|
||||
typedef enum tagPOINTER_DEVICE_TYPE {
|
||||
POINTER_DEVICE_TYPE_INTEGRATED_PEN = 0x00000001,
|
||||
POINTER_DEVICE_TYPE_EXTERNAL_PEN = 0x00000002,
|
||||
POINTER_DEVICE_TYPE_TOUCH = 0x00000003,
|
||||
POINTER_DEVICE_TYPE_TOUCH_PAD = 0x00000004,
|
||||
POINTER_DEVICE_TYPE_MAX = 0xffffffff
|
||||
} POINTER_DEVICE_TYPE;
|
||||
|
||||
typedef struct tagPOINTER_DEVICE_INFO {
|
||||
DWORD displayOrientation;
|
||||
HANDLE device;
|
||||
POINTER_DEVICE_TYPE pointerDeviceType;
|
||||
HMONITOR monitor;
|
||||
ULONG startingCursorId;
|
||||
USHORT maxActiveContacts;
|
||||
WCHAR productString[POINTER_DEVICE_PRODUCT_STRING_MAX];
|
||||
} POINTER_DEVICE_INFO;
|
||||
|
||||
typedef struct tagPOINTER_DEVICE_PROPERTY {
|
||||
INT32 logicalMin;
|
||||
INT32 logicalMax;
|
||||
INT32 physicalMin;
|
||||
INT32 physicalMax;
|
||||
UINT32 unit;
|
||||
UINT32 unitExponent;
|
||||
USHORT usagePageId;
|
||||
USHORT usageId;
|
||||
} POINTER_DEVICE_PROPERTY;
|
||||
|
||||
typedef enum tagPOINTER_DEVICE_CURSOR_TYPE {
|
||||
POINTER_DEVICE_CURSOR_TYPE_UNKNOWN = 0x00000000,
|
||||
POINTER_DEVICE_CURSOR_TYPE_TIP = 0x00000001,
|
||||
POINTER_DEVICE_CURSOR_TYPE_ERASER = 0x00000002,
|
||||
POINTER_DEVICE_CURSOR_TYPE_MAX = 0xffffffff
|
||||
} POINTER_DEVICE_CURSOR_TYPE;
|
||||
|
||||
typedef struct tagPOINTER_DEVICE_CURSOR_INFO {
|
||||
UINT32 cursorId;
|
||||
POINTER_DEVICE_CURSOR_TYPE cursor;
|
||||
} POINTER_DEVICE_CURSOR_INFO;
|
||||
|
||||
#endif /* POINTER_FLAG_NONE */
|
||||
|
||||
#if WINVER < 0x0601
|
||||
|
||||
typedef struct tagGESTURECONFIG {
|
||||
DWORD dwID;
|
||||
DWORD dwWant;
|
||||
DWORD dwBlock;
|
||||
} GESTURECONFIG,*PGESTURECONFIG;
|
||||
|
||||
#endif /* WINVER < 0x0601 */
|
||||
|
||||
#ifndef MICROSOFT_TABLETPENSERVICE_PROPERTY
|
||||
#define MICROSOFT_TABLETPENSERVICE_PROPERTY _T("MicrosoftTabletPenServiceProperty")
|
||||
#endif
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "gdkintl.h"
|
||||
#include "gdkprivate-x11.h"
|
||||
#include "gdkdisplay-x11.h"
|
||||
#include "gdk-private.h"
|
||||
|
||||
#include <glib.h>
|
||||
#ifdef HAVE_DESKTOPAPPINFO
|
||||
@@ -220,7 +219,7 @@ startup_timeout (void *data)
|
||||
std->timeout_id = 0;
|
||||
else {
|
||||
std->timeout_id = g_timeout_add_seconds ((min_timeout + 500)/1000, startup_timeout, std);
|
||||
gdk_source_set_static_name_by_id (std->timeout_id, "[gtk] startup_timeout");
|
||||
g_source_set_name_by_id (std->timeout_id, "[gtk] startup_timeout");
|
||||
}
|
||||
|
||||
/* always remove this one, but we may have reinstalled another one. */
|
||||
@@ -257,7 +256,7 @@ add_startup_timeout (GdkX11Screen *screen,
|
||||
if (data->timeout_id == 0) {
|
||||
data->timeout_id = g_timeout_add_seconds (STARTUP_TIMEOUT_LENGTH_SECONDS,
|
||||
startup_timeout, data);
|
||||
gdk_source_set_static_name_by_id (data->timeout_id, "[gtk] startup_timeout");
|
||||
g_source_set_name_by_id (data->timeout_id, "[gtk] startup_timeout");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ in this Software without prior written authorization from The Open Group.
|
||||
#include "gdkasync.h"
|
||||
#include "gdkprivate-x11.h"
|
||||
#include "gdkdisplay-x11.h"
|
||||
#include "gdk-private.h"
|
||||
|
||||
#include <X11/Xlibint.h>
|
||||
|
||||
@@ -172,7 +171,7 @@ send_event_handler (Display *dpy,
|
||||
{
|
||||
guint id;
|
||||
id = g_idle_add (callback_idle, state);
|
||||
gdk_source_set_static_name_by_id (id, "[gtk] callback_idle");
|
||||
g_source_set_name_by_id (id, "[gtk] callback_idle");
|
||||
}
|
||||
|
||||
DeqAsyncHandler(state->dpy, &state->async);
|
||||
@@ -708,7 +707,7 @@ roundtrip_handler (Display *dpy,
|
||||
{
|
||||
guint id;
|
||||
id = g_idle_add (roundtrip_callback_idle, state);
|
||||
gdk_source_set_static_name_by_id (id, "[gtk] roundtrip_callback_idle");
|
||||
g_source_set_name_by_id (id, "[gtk] roundtrip_callback_idle");
|
||||
}
|
||||
|
||||
DeqAsyncHandler(state->dpy, &state->async);
|
||||
|
||||
@@ -1037,8 +1037,8 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
|
||||
if (xevent->type - display_x11->xrandr_event_base == RRScreenChangeNotify ||
|
||||
xevent->type - display_x11->xrandr_event_base == RRNotify)
|
||||
{
|
||||
if (display_x11->screen)
|
||||
_gdk_x11_screen_size_changed (display_x11->screen, xevent);
|
||||
if (x11_screen)
|
||||
_gdk_x11_screen_size_changed (x11_screen, xevent);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
@@ -884,10 +884,8 @@ gdk_x11_drag_handle_finished (GdkDisplay *display,
|
||||
if (drag_x11->version == 5)
|
||||
drag_x11->drop_failed = xevent->xclient.data.l[1] == 0;
|
||||
|
||||
g_object_ref (drag);
|
||||
g_signal_emit_by_name (drag, "dnd-finished");
|
||||
gdk_drag_drop_done (drag, !drag_x11->drop_failed);
|
||||
g_object_unref (drag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1864,7 +1862,7 @@ gdk_x11_drag_drop_done (GdkDrag *drag,
|
||||
id = g_timeout_add_full (G_PRIORITY_DEFAULT, 17,
|
||||
gdk_drag_anim_timeout, anim,
|
||||
(GDestroyNotify) gdk_drag_anim_destroy);
|
||||
gdk_source_set_static_name_by_id (id, "[gtk] gdk_drag_anim_timeout");
|
||||
g_source_set_name_by_id (id, "[gtk] gdk_drag_anim_timeout");
|
||||
g_object_unref (drag);
|
||||
}
|
||||
|
||||
|
||||
@@ -1282,10 +1282,7 @@ _gdk_x11_display_create_surface (GdkDisplay *display,
|
||||
|
||||
class_hint = XAllocClassHint ();
|
||||
class_hint->res_name = (char *) g_get_prgname ();
|
||||
if (display_x11->program_class)
|
||||
class_hint->res_class = (char *) display_x11->program_class;
|
||||
else
|
||||
class_hint->res_class = class_hint->res_name;
|
||||
class_hint->res_class = (char *) display_x11->program_class;
|
||||
XSetClassHint (xdisplay, impl->xid, class_hint);
|
||||
XFree (class_hint);
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ get_boolean_default (GdkX11Screen *x11_screen,
|
||||
char *v;
|
||||
int i;
|
||||
|
||||
if (gdk_display_get_debug_flags (GDK_SCREEN_DISPLAY (x11_screen)) & GDK_DEBUG_DEFAULT_SETTINGS)
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (GDK_SCREEN_DISPLAY (x11_screen), DEFAULT_SETTINGS))
|
||||
return FALSE;
|
||||
|
||||
v = XGetDefault (dpy, "Xft", option);
|
||||
@@ -114,7 +114,7 @@ get_double_default (GdkX11Screen *x11_screen,
|
||||
Display *dpy = GDK_SCREEN_XDISPLAY (x11_screen);
|
||||
char *v, *e;
|
||||
|
||||
if (gdk_display_get_debug_flags (GDK_SCREEN_DISPLAY (x11_screen)) & GDK_DEBUG_DEFAULT_SETTINGS)
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (GDK_SCREEN_DISPLAY (x11_screen), DEFAULT_SETTINGS))
|
||||
return FALSE;
|
||||
|
||||
v = XGetDefault (dpy, "Xft", option);
|
||||
@@ -141,7 +141,7 @@ get_integer_default (GdkX11Screen *x11_screen,
|
||||
Display *dpy = GDK_SCREEN_XDISPLAY (x11_screen);
|
||||
char *v, *e;
|
||||
|
||||
if (gdk_display_get_debug_flags (GDK_SCREEN_DISPLAY (x11_screen)) & GDK_DEBUG_DEFAULT_SETTINGS)
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (GDK_SCREEN_DISPLAY (x11_screen), DEFAULT_SETTINGS))
|
||||
return FALSE;
|
||||
|
||||
v = XGetDefault (dpy, "Xft", option);
|
||||
|
||||
317
gsk/gl/glutilsprivate.h
Normal file
317
gsk/gl/glutilsprivate.h
Normal file
@@ -0,0 +1,317 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define SANITY_CHECKS 0
|
||||
|
||||
|
||||
|
||||
#define rounded_rect_top_left(r) (GRAPHENE_RECT_INIT(r->bounds.origin.x, \
|
||||
r->bounds.origin.y, \
|
||||
r->corner[0].width, r->corner[0].height))
|
||||
|
||||
#define rounded_rect_top_right(r) (GRAPHENE_RECT_INIT(r->bounds.origin.x + r->bounds.size.width - r->corner[1].width, \
|
||||
r->bounds.origin.y, \
|
||||
r->corner[1].width, r->corner[1].height))
|
||||
|
||||
#define rounded_rect_bottom_right(r) (GRAPHENE_RECT_INIT(r->bounds.origin.x + r->bounds.size.width - r->corner[2].width, \
|
||||
r->bounds.origin.y + r->bounds.size.height - r->corner[2].height, \
|
||||
r->corner[2].width, r->corner[2].height))
|
||||
|
||||
#define rounded_rect_bottom_left(r) (GRAPHENE_RECT_INIT(r->bounds.origin.x, \
|
||||
r->bounds.origin.y + r->bounds.size.height - r->corner[2].height, \
|
||||
r->corner[3].width, r->corner[3].height))
|
||||
|
||||
|
||||
#define rounded_rect_corner0(r) rounded_rect_top_left(r)
|
||||
#define rounded_rect_corner1(r) rounded_rect_top_right(r)
|
||||
#define rounded_rect_corner2(r) rounded_rect_bottom_right(r)
|
||||
#define rounded_rect_corner3(r) rounded_rect_bottom_left(r)
|
||||
|
||||
#define rounded_rect_corner(r, i) (rounded_rect_corner ##i(r))
|
||||
#define graphene_size_non_zero(s) (s->width > 0 && s->height > 0)
|
||||
#define rounded_rect_has_corner(r, i) (r->corner[i].width > 0 && r->corner[i].height > 0)
|
||||
|
||||
#define rect_contains_point(r, _x, _y) (_x >= (r)->origin.x && _x <= (r)->origin.x + (r)->size.width && \
|
||||
_y >= (r)->origin.y && _y <= (r)->origin.y + (r)->size.height)
|
||||
|
||||
enum {
|
||||
NINE_SLICE_TOP_LEFT = 0,
|
||||
NINE_SLICE_TOP_CENTER = 1,
|
||||
NINE_SLICE_TOP_RIGHT = 2,
|
||||
NINE_SLICE_LEFT_CENTER = 3,
|
||||
NINE_SLICE_CENTER = 4,
|
||||
NINE_SLICE_RIGHT_CENTER = 5,
|
||||
NINE_SLICE_BOTTOM_LEFT = 6,
|
||||
NINE_SLICE_BOTTOM_CENTER = 7,
|
||||
NINE_SLICE_BOTTOM_RIGHT = 8,
|
||||
};
|
||||
#define NINE_SLICE_SIZE 9 /* Hah. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int texture_id;
|
||||
float x;
|
||||
float y;
|
||||
float x2;
|
||||
float y2;
|
||||
} TextureRegion;
|
||||
|
||||
static inline bool G_GNUC_PURE
|
||||
slice_is_visible (const cairo_rectangle_int_t *r)
|
||||
{
|
||||
return (r->width > 0 && r->height > 0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
nine_slice_rounded_rect (const GskRoundedRect *rect,
|
||||
cairo_rectangle_int_t *out_rects)
|
||||
{
|
||||
const graphene_point_t *origin = &rect->bounds.origin;
|
||||
const graphene_size_t *size = &rect->bounds.size;
|
||||
const int top_height = ceilf (MAX (rect->corner[GSK_CORNER_TOP_LEFT].height,
|
||||
rect->corner[GSK_CORNER_TOP_RIGHT].height));
|
||||
const int bottom_height = ceilf (MAX (rect->corner[GSK_CORNER_BOTTOM_LEFT].height,
|
||||
rect->corner[GSK_CORNER_BOTTOM_RIGHT].height));
|
||||
const int right_width = ceilf (MAX (rect->corner[GSK_CORNER_TOP_RIGHT].width,
|
||||
rect->corner[GSK_CORNER_BOTTOM_RIGHT].width));
|
||||
const int left_width = ceilf (MAX (rect->corner[GSK_CORNER_TOP_LEFT].width,
|
||||
rect->corner[GSK_CORNER_BOTTOM_LEFT].width));
|
||||
|
||||
/* Top left */
|
||||
out_rects[0] = (cairo_rectangle_int_t) {
|
||||
origin->x, origin->y,
|
||||
left_width, top_height,
|
||||
};
|
||||
|
||||
/* Top center */
|
||||
out_rects[1] = (cairo_rectangle_int_t) {
|
||||
origin->x + size->width / 2.0 - 0.5, origin->y,
|
||||
1, top_height,
|
||||
};
|
||||
|
||||
/* Top right */
|
||||
out_rects[2] = (cairo_rectangle_int_t) {
|
||||
origin->x + size->width - right_width, origin->y,
|
||||
right_width, top_height
|
||||
};
|
||||
|
||||
/* Left center */
|
||||
out_rects[3] = (cairo_rectangle_int_t) {
|
||||
origin->x, origin->y + size->height / 2,
|
||||
left_width, 1,
|
||||
};
|
||||
|
||||
/* center */
|
||||
out_rects[4] = (cairo_rectangle_int_t) {
|
||||
origin->x + size->width / 2.0 - 0.5,
|
||||
origin->y + size->height / 2.0 - 0.5,
|
||||
1, 1
|
||||
};
|
||||
|
||||
/* Right center */
|
||||
out_rects[5] = (cairo_rectangle_int_t) {
|
||||
origin->x + size->width - right_width,
|
||||
origin->y + (size->height / 2.0) - 0.5,
|
||||
right_width,
|
||||
1,
|
||||
};
|
||||
|
||||
/* Bottom Left */
|
||||
out_rects[6] = (cairo_rectangle_int_t) {
|
||||
origin->x, origin->y + size->height - bottom_height,
|
||||
left_width, bottom_height,
|
||||
};
|
||||
|
||||
/* Bottom center */
|
||||
out_rects[7] = (cairo_rectangle_int_t) {
|
||||
origin->x + (size->width / 2.0) - 0.5,
|
||||
origin->y + size->height - bottom_height,
|
||||
1, bottom_height,
|
||||
};
|
||||
|
||||
/* Bottom right */
|
||||
out_rects[8] = (cairo_rectangle_int_t) {
|
||||
origin->x + size->width - right_width,
|
||||
origin->y + size->height - bottom_height,
|
||||
right_width, bottom_height,
|
||||
};
|
||||
|
||||
#if SANITY_CHECKS
|
||||
g_assert_cmpfloat (size->width, >=, left_width + right_width);
|
||||
g_assert_cmpfloat (size->height, >=, top_height + bottom_height);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
nine_slice_grow (cairo_rectangle_int_t *slices,
|
||||
const int amount)
|
||||
{
|
||||
/* top left */
|
||||
slices[0].x -= amount;
|
||||
slices[0].y -= amount;
|
||||
if (amount > slices[0].width)
|
||||
slices[0].width += amount * 2;
|
||||
else
|
||||
slices[0].width += amount;
|
||||
|
||||
if (amount > slices[0].height)
|
||||
slices[0].height += amount * 2;
|
||||
else
|
||||
slices[0].height += amount;
|
||||
|
||||
|
||||
/* Top center */
|
||||
slices[1].y -= amount;
|
||||
if (amount > slices[1].height)
|
||||
slices[1].height += amount * 2;
|
||||
else
|
||||
slices[1].height += amount;
|
||||
|
||||
/* top right */
|
||||
slices[2].y -= amount;
|
||||
if (amount > slices[2].width)
|
||||
{
|
||||
slices[2].x -= amount;
|
||||
slices[2].width += amount * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
slices[2].width += amount;
|
||||
}
|
||||
|
||||
if (amount > slices[2].height)
|
||||
slices[2].height += amount * 2;
|
||||
else
|
||||
slices[2].height += amount;
|
||||
|
||||
|
||||
|
||||
slices[3].x -= amount;
|
||||
if (amount > slices[3].width)
|
||||
slices[3].width += amount * 2;
|
||||
else
|
||||
slices[3].width += amount;
|
||||
|
||||
/* Leave Britney^Wcenter alone */
|
||||
|
||||
if (amount > slices[5].width)
|
||||
{
|
||||
slices[5].x -= amount;
|
||||
slices[5].width += amount * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
slices[5].width += amount;
|
||||
}
|
||||
|
||||
|
||||
/* Bottom left */
|
||||
slices[6].x -= amount;
|
||||
if (amount > slices[6].width)
|
||||
{
|
||||
slices[6].width += amount * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
slices[6].width += amount;
|
||||
}
|
||||
|
||||
if (amount > slices[6].height)
|
||||
{
|
||||
slices[6].y -= amount;
|
||||
slices[6].height += amount * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
slices[6].height += amount;
|
||||
}
|
||||
|
||||
|
||||
/* Bottom center */
|
||||
if (amount > slices[7].height)
|
||||
{
|
||||
slices[7].y -= amount;
|
||||
slices[7].height += amount * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
slices[7].height += amount;
|
||||
}
|
||||
|
||||
if (amount > slices[8].width)
|
||||
{
|
||||
slices[8].x -= amount;
|
||||
slices[8].width += amount * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
slices[8].width += amount;
|
||||
}
|
||||
|
||||
if (amount > slices[8].height)
|
||||
{
|
||||
slices[8].y -= amount;
|
||||
slices[8].height += amount * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
slices[8].height += amount;
|
||||
}
|
||||
|
||||
#if SANITY_CHECKS
|
||||
{
|
||||
for (int i = 0; i < 9; i ++)
|
||||
{
|
||||
g_assert_cmpint (slices[i].x, >=, 0);
|
||||
g_assert_cmpint (slices[i].y, >=, 0);
|
||||
g_assert_cmpint (slices[i].width, >=, 0);
|
||||
g_assert_cmpint (slices[i].height, >=, 0);
|
||||
}
|
||||
|
||||
/* Rows don't overlap */
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
g_assert_cmpint (slices[i * 3 + 0].x + slices[i * 3 + 0].width, <, slices[i * 3 + 1].x);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static inline void
|
||||
nine_slice_to_texture_coords (const cairo_rectangle_int_t *slices,
|
||||
const int texture_width,
|
||||
const int texture_height,
|
||||
TextureRegion *out_regions)
|
||||
{
|
||||
const float fw = (float)texture_width;
|
||||
const float fh = (float)texture_height;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 9; i++)
|
||||
{
|
||||
out_regions[i] = (TextureRegion) {
|
||||
0, /* Texture id */
|
||||
slices[i].x / fw,
|
||||
1.0 - ((slices[i].y + slices[i].height) / fh),
|
||||
(slices[i].x + slices[i].width) / fw,
|
||||
1.0 - (slices[i].y / fh),
|
||||
};
|
||||
}
|
||||
|
||||
#if SANITY_CHECKS
|
||||
{
|
||||
for (i = 0; i < 9; i++)
|
||||
{
|
||||
const TextureRegion *r = &out_regions[i];
|
||||
g_assert_cmpfloat (r->x, >=, 0);
|
||||
g_assert_cmpfloat (r->x, <=, 1);
|
||||
g_assert_cmpfloat (r->y, >=, 0);
|
||||
g_assert_cmpfloat (r->y, <=, 1);
|
||||
|
||||
g_assert_cmpfloat (r->x, <, r->x2);
|
||||
g_assert_cmpfloat (r->y, <, r->y2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
849
gsk/gl/gskgldriver.c
Normal file
849
gsk/gl/gskgldriver.c
Normal file
@@ -0,0 +1,849 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gskgldriverprivate.h"
|
||||
|
||||
#include "gskdebugprivate.h"
|
||||
#include "gskprofilerprivate.h"
|
||||
#include "gdk/gdkglcontextprivate.h"
|
||||
#include "gdk/gdktextureprivate.h"
|
||||
#include "gdk/gdkgltextureprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
typedef struct {
|
||||
GLuint fbo_id;
|
||||
GLuint depth_stencil_id;
|
||||
} Fbo;
|
||||
|
||||
typedef struct {
|
||||
GLuint texture_id;
|
||||
int width;
|
||||
int height;
|
||||
GLuint min_filter;
|
||||
GLuint mag_filter;
|
||||
Fbo fbo;
|
||||
GdkTexture *user;
|
||||
guint in_use : 1;
|
||||
guint permanent : 1;
|
||||
|
||||
/* TODO: Make this optional and not for every texture... */
|
||||
TextureSlice *slices;
|
||||
guint n_slices;
|
||||
} Texture;
|
||||
|
||||
struct _GskGLDriver
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GdkGLContext *gl_context;
|
||||
GskProfiler *profiler;
|
||||
struct {
|
||||
GQuark created_textures;
|
||||
GQuark reused_textures;
|
||||
GQuark surface_uploads;
|
||||
} counters;
|
||||
|
||||
Fbo default_fbo;
|
||||
|
||||
GHashTable *textures; /* texture_id -> Texture */
|
||||
GHashTable *pointer_textures; /* pointer -> texture_id */
|
||||
|
||||
const Texture *bound_source_texture;
|
||||
|
||||
int max_texture_size;
|
||||
|
||||
gboolean in_frame : 1;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskGLDriver, gsk_gl_driver, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
upload_gdk_texture (GdkTexture *source_texture,
|
||||
int target,
|
||||
int x_offset,
|
||||
int y_offset,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_surface_t *surface = NULL;
|
||||
GdkMemoryFormat data_format;
|
||||
const guchar *data;
|
||||
gsize data_stride;
|
||||
gsize bpp;
|
||||
|
||||
g_return_if_fail (source_texture != NULL);
|
||||
g_return_if_fail (x_offset + width <= gdk_texture_get_width (source_texture));
|
||||
g_return_if_fail (y_offset + height <= gdk_texture_get_height (source_texture));
|
||||
|
||||
/* Note: GdkGLTextures are already handled before we reach this and reused as-is */
|
||||
|
||||
if (GDK_IS_MEMORY_TEXTURE (source_texture))
|
||||
{
|
||||
GdkMemoryTexture *memory_texture = GDK_MEMORY_TEXTURE (source_texture);
|
||||
data = gdk_memory_texture_get_data (memory_texture);
|
||||
data_format = gdk_memory_texture_get_format (memory_texture);
|
||||
data_stride = gdk_memory_texture_get_stride (memory_texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fall back to downloading to a surface */
|
||||
surface = gdk_texture_download_surface (source_texture);
|
||||
cairo_surface_flush (surface);
|
||||
data = cairo_image_surface_get_data (surface);
|
||||
data_format = GDK_MEMORY_DEFAULT;
|
||||
data_stride = cairo_image_surface_get_stride (surface);
|
||||
}
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (data_format);
|
||||
|
||||
gdk_gl_context_upload_texture (gdk_gl_context_get_current (),
|
||||
data + x_offset * bpp + y_offset * data_stride,
|
||||
width, height, data_stride,
|
||||
data_format, target);
|
||||
|
||||
if (surface)
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
|
||||
static Texture *
|
||||
texture_new (void)
|
||||
{
|
||||
return g_slice_new0 (Texture);
|
||||
}
|
||||
|
||||
static inline void
|
||||
fbo_clear (const Fbo *f)
|
||||
{
|
||||
if (f->depth_stencil_id != 0)
|
||||
glDeleteRenderbuffers (1, &f->depth_stencil_id);
|
||||
|
||||
glDeleteFramebuffers (1, &f->fbo_id);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_free (gpointer data)
|
||||
{
|
||||
Texture *t = data;
|
||||
guint i;
|
||||
|
||||
if (t->user)
|
||||
gdk_texture_clear_render_data (t->user);
|
||||
|
||||
if (t->fbo.fbo_id != 0)
|
||||
fbo_clear (&t->fbo);
|
||||
|
||||
if (t->texture_id != 0)
|
||||
{
|
||||
glDeleteTextures (1, &t->texture_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_cmpint (t->n_slices, >, 0);
|
||||
|
||||
for (i = 0; i < t->n_slices; i ++)
|
||||
glDeleteTextures (1, &t->slices[i].texture_id);
|
||||
}
|
||||
|
||||
g_slice_free (Texture, t);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_driver_set_texture_parameters (GskGLDriver *self,
|
||||
int min_filter,
|
||||
int mag_filter)
|
||||
{
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
|
||||
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_driver_finalize (GObject *gobject)
|
||||
{
|
||||
GskGLDriver *self = GSK_GL_DRIVER (gobject);
|
||||
|
||||
gdk_gl_context_make_current (self->gl_context);
|
||||
|
||||
g_clear_pointer (&self->textures, g_hash_table_unref);
|
||||
g_clear_pointer (&self->pointer_textures, g_hash_table_unref);
|
||||
g_clear_object (&self->profiler);
|
||||
|
||||
if (self->gl_context == gdk_gl_context_get_current ())
|
||||
gdk_gl_context_clear_current ();
|
||||
|
||||
G_OBJECT_CLASS (gsk_gl_driver_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_driver_class_init (GskGLDriverClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = gsk_gl_driver_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_driver_init (GskGLDriver *self)
|
||||
{
|
||||
self->textures = g_hash_table_new_full (NULL, NULL, NULL, texture_free);
|
||||
|
||||
self->max_texture_size = -1;
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
self->profiler = gsk_profiler_new ();
|
||||
self->counters.created_textures = gsk_profiler_add_counter (self->profiler,
|
||||
"created_textures",
|
||||
"Textures created this frame",
|
||||
TRUE);
|
||||
self->counters.reused_textures = gsk_profiler_add_counter (self->profiler,
|
||||
"reused_textures",
|
||||
"Textures reused this frame",
|
||||
TRUE);
|
||||
self->counters.surface_uploads = gsk_profiler_add_counter (self->profiler,
|
||||
"surface_uploads",
|
||||
"Texture uploads from surfaces this frame",
|
||||
TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
GskGLDriver *
|
||||
gsk_gl_driver_new (GdkGLContext *context)
|
||||
{
|
||||
GskGLDriver *self;
|
||||
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL);
|
||||
|
||||
self = (GskGLDriver *) g_object_new (GSK_TYPE_GL_DRIVER, NULL);
|
||||
self->gl_context = context;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_driver_begin_frame (GskGLDriver *self)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_GL_DRIVER (self));
|
||||
g_return_if_fail (!self->in_frame);
|
||||
|
||||
self->in_frame = TRUE;
|
||||
|
||||
if (self->max_texture_size < 0)
|
||||
{
|
||||
glGetIntegerv (GL_MAX_TEXTURE_SIZE, (GLint *) &self->max_texture_size);
|
||||
GSK_NOTE (OPENGL, g_message ("GL max texture size: %d", self->max_texture_size));
|
||||
}
|
||||
|
||||
glBindFramebuffer (GL_FRAMEBUFFER, 0);
|
||||
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
|
||||
glActiveTexture (GL_TEXTURE0 + 1);
|
||||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
|
||||
glBindVertexArray (0);
|
||||
glUseProgram (0);
|
||||
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
gsk_profiler_reset (self->profiler);
|
||||
#endif
|
||||
}
|
||||
|
||||
gboolean
|
||||
gsk_gl_driver_in_frame (GskGLDriver *self)
|
||||
{
|
||||
return self->in_frame;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_driver_end_frame (GskGLDriver *self)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_GL_DRIVER (self));
|
||||
g_return_if_fail (self->in_frame);
|
||||
|
||||
self->bound_source_texture = NULL;
|
||||
|
||||
self->default_fbo.fbo_id = 0;
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
GSK_NOTE (OPENGL,
|
||||
g_message ("Textures created: %" G_GINT64_FORMAT "\n"
|
||||
" Textures reused: %" G_GINT64_FORMAT "\n"
|
||||
" Surface uploads: %" G_GINT64_FORMAT,
|
||||
gsk_profiler_counter_get (self->profiler, self->counters.created_textures),
|
||||
gsk_profiler_counter_get (self->profiler, self->counters.reused_textures),
|
||||
gsk_profiler_counter_get (self->profiler, self->counters.surface_uploads)));
|
||||
#endif
|
||||
|
||||
GSK_NOTE (OPENGL,
|
||||
g_message ("*** Frame end: textures=%d",
|
||||
g_hash_table_size (self->textures)));
|
||||
|
||||
self->in_frame = FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
gsk_gl_driver_collect_textures (GskGLDriver *self)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer value_p = NULL;
|
||||
int old_size;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_GL_DRIVER (self), 0);
|
||||
g_return_val_if_fail (!self->in_frame, 0);
|
||||
|
||||
old_size = g_hash_table_size (self->textures);
|
||||
|
||||
g_hash_table_iter_init (&iter, self->textures);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &value_p))
|
||||
{
|
||||
Texture *t = value_p;
|
||||
|
||||
if (t->user || t->permanent)
|
||||
continue;
|
||||
|
||||
if (t->in_use)
|
||||
{
|
||||
t->in_use = FALSE;
|
||||
|
||||
if (t->fbo.fbo_id != 0)
|
||||
{
|
||||
fbo_clear (&t->fbo);
|
||||
t->fbo.fbo_id = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remove from self->pointer_textures. */
|
||||
/* TODO: Is there a better way for this? */
|
||||
if (self->pointer_textures)
|
||||
{
|
||||
GHashTableIter pointer_iter;
|
||||
gpointer value;
|
||||
gpointer p;
|
||||
|
||||
g_hash_table_iter_init (&pointer_iter, self->pointer_textures);
|
||||
while (g_hash_table_iter_next (&pointer_iter, &p, &value))
|
||||
{
|
||||
if (GPOINTER_TO_INT (value) == t->texture_id)
|
||||
{
|
||||
g_hash_table_iter_remove (&pointer_iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_iter_remove (&iter);
|
||||
}
|
||||
}
|
||||
|
||||
return old_size - g_hash_table_size (self->textures);
|
||||
}
|
||||
|
||||
|
||||
GdkGLContext *
|
||||
gsk_gl_driver_get_gl_context (GskGLDriver *self)
|
||||
{
|
||||
return self->gl_context;
|
||||
}
|
||||
|
||||
int
|
||||
gsk_gl_driver_get_max_texture_size (GskGLDriver *self)
|
||||
{
|
||||
if (self->max_texture_size < 0)
|
||||
{
|
||||
if (gdk_gl_context_get_use_es (self->gl_context))
|
||||
return 2048;
|
||||
|
||||
return 1024;
|
||||
}
|
||||
|
||||
return self->max_texture_size;
|
||||
}
|
||||
|
||||
static Texture *
|
||||
gsk_gl_driver_get_texture (GskGLDriver *self,
|
||||
int texture_id)
|
||||
{
|
||||
Texture *t;
|
||||
|
||||
if (g_hash_table_lookup_extended (self->textures, GINT_TO_POINTER (texture_id), NULL, (gpointer *) &t))
|
||||
return t;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Texture *
|
||||
create_texture (GskGLDriver *self,
|
||||
float fwidth,
|
||||
float fheight)
|
||||
{
|
||||
guint texture_id;
|
||||
Texture *t;
|
||||
int width = ceilf (fwidth);
|
||||
int height = ceilf (fheight);
|
||||
|
||||
g_assert (width > 0);
|
||||
g_assert (height > 0);
|
||||
|
||||
if (width > self->max_texture_size ||
|
||||
height > self->max_texture_size)
|
||||
{
|
||||
g_critical ("Texture %d x %d is bigger than supported texture limit of %d; clipping...",
|
||||
width, height,
|
||||
self->max_texture_size);
|
||||
|
||||
width = MIN (width, self->max_texture_size);
|
||||
height = MIN (height, self->max_texture_size);
|
||||
}
|
||||
|
||||
glGenTextures (1, &texture_id);
|
||||
t = texture_new ();
|
||||
t->texture_id = texture_id;
|
||||
t->width = width;
|
||||
t->height = height;
|
||||
t->min_filter = GL_NEAREST;
|
||||
t->mag_filter = GL_NEAREST;
|
||||
t->in_use = TRUE;
|
||||
g_hash_table_insert (self->textures, GINT_TO_POINTER (texture_id), t);
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
gsk_profiler_counter_inc (self->profiler, self->counters.created_textures);
|
||||
#endif
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_driver_release_texture (gpointer data)
|
||||
{
|
||||
Texture *t = data;
|
||||
|
||||
t->user = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_driver_slice_texture (GskGLDriver *self,
|
||||
GdkTexture *texture,
|
||||
TextureSlice **out_slices,
|
||||
guint *out_n_slices)
|
||||
{
|
||||
const int max_texture_size = gsk_gl_driver_get_max_texture_size (self) / 4; // XXX Too much?
|
||||
const int cols = (texture->width / max_texture_size) + 1;
|
||||
const int rows = (texture->height / max_texture_size) + 1;
|
||||
int col, row;
|
||||
int x = 0, y = 0; /* Position in the texture */
|
||||
TextureSlice *slices;
|
||||
Texture *tex;
|
||||
|
||||
g_assert (texture->width > max_texture_size || texture->height > max_texture_size);
|
||||
|
||||
|
||||
tex = gdk_texture_get_render_data (texture, self);
|
||||
|
||||
if (tex != NULL)
|
||||
{
|
||||
g_assert (tex->n_slices > 0);
|
||||
*out_slices = tex->slices;
|
||||
*out_n_slices = tex->n_slices;
|
||||
return;
|
||||
}
|
||||
|
||||
slices = g_new0 (TextureSlice, cols * rows);
|
||||
|
||||
for (col = 0; col < cols; col ++)
|
||||
{
|
||||
const int slice_width = MIN (max_texture_size, texture->width - x);
|
||||
|
||||
for (row = 0; row < rows; row ++)
|
||||
{
|
||||
const int slice_height = MIN (max_texture_size, texture->height - y);
|
||||
const int slice_index = (col * rows) + row;
|
||||
guint texture_id;
|
||||
|
||||
glGenTextures (1, &texture_id);
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
gsk_profiler_counter_inc (self->profiler, self->counters.created_textures);
|
||||
#endif
|
||||
glBindTexture (GL_TEXTURE_2D, texture_id);
|
||||
gsk_gl_driver_set_texture_parameters (self, GL_NEAREST, GL_NEAREST);
|
||||
upload_gdk_texture (texture, GL_TEXTURE_2D, x, y, slice_width, slice_height);
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
gsk_profiler_counter_inc (self->profiler, self->counters.surface_uploads);
|
||||
#endif
|
||||
|
||||
slices[slice_index].rect = (GdkRectangle){x, y, slice_width, slice_height};
|
||||
slices[slice_index].texture_id = texture_id;
|
||||
|
||||
y += slice_height;
|
||||
}
|
||||
|
||||
y = 0;
|
||||
x += slice_width;
|
||||
}
|
||||
|
||||
/* Allocate one Texture for the entire thing. */
|
||||
tex = texture_new ();
|
||||
tex->width = texture->width;
|
||||
tex->height = texture->height;
|
||||
tex->min_filter = GL_NEAREST;
|
||||
tex->mag_filter = GL_NEAREST;
|
||||
tex->in_use = TRUE;
|
||||
tex->slices = slices;
|
||||
tex->n_slices = cols * rows;
|
||||
|
||||
/* Use texture_free as destroy notify here since we are not inserting this Texture
|
||||
* into self->textures! */
|
||||
gdk_texture_set_render_data (texture, self, tex, texture_free);
|
||||
|
||||
*out_slices = slices;
|
||||
*out_n_slices = cols * rows;
|
||||
}
|
||||
|
||||
int
|
||||
gsk_gl_driver_get_texture_for_texture (GskGLDriver *self,
|
||||
GdkTexture *texture,
|
||||
int min_filter,
|
||||
int mag_filter)
|
||||
{
|
||||
Texture *t;
|
||||
GdkTexture *downloaded_texture = NULL;
|
||||
GdkTexture *source_texture;
|
||||
|
||||
if (GDK_IS_GL_TEXTURE (texture))
|
||||
{
|
||||
GdkGLTexture *gl_texture = (GdkGLTexture *) texture;
|
||||
GdkGLContext *texture_context = gdk_gl_texture_get_context (gl_texture);
|
||||
|
||||
if (gdk_gl_context_is_shared (self->gl_context, texture_context))
|
||||
{
|
||||
/* A GL texture from the same GL context is a simple task... */
|
||||
return gdk_gl_texture_get_id (gl_texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
|
||||
/* In this case, we have to temporarily make the texture's context the current one,
|
||||
* download its data into our context and then create a texture from it. */
|
||||
if (texture_context)
|
||||
gdk_gl_context_make_current (texture_context);
|
||||
|
||||
surface = gdk_texture_download_surface (texture);
|
||||
downloaded_texture = gdk_texture_new_for_surface (surface);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
gdk_gl_context_make_current (self->gl_context);
|
||||
|
||||
source_texture = downloaded_texture;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
t = gdk_texture_get_render_data (texture, self);
|
||||
|
||||
if (t)
|
||||
{
|
||||
if (t->min_filter == min_filter && t->mag_filter == mag_filter)
|
||||
return t->texture_id;
|
||||
}
|
||||
|
||||
source_texture = texture;
|
||||
}
|
||||
|
||||
t = create_texture (self, gdk_texture_get_width (texture), gdk_texture_get_height (texture));
|
||||
|
||||
if (gdk_texture_set_render_data (texture, self, t, gsk_gl_driver_release_texture))
|
||||
t->user = texture;
|
||||
|
||||
gsk_gl_driver_bind_source_texture (self, t->texture_id);
|
||||
gsk_gl_driver_init_texture (self,
|
||||
t->texture_id,
|
||||
source_texture,
|
||||
min_filter,
|
||||
mag_filter);
|
||||
gdk_gl_context_label_object_printf (self->gl_context, GL_TEXTURE, t->texture_id,
|
||||
"GdkTexture<%p> %d", texture, t->texture_id);
|
||||
|
||||
if (downloaded_texture)
|
||||
g_object_unref (downloaded_texture);
|
||||
|
||||
return t->texture_id;
|
||||
}
|
||||
|
||||
static guint
|
||||
texture_key_hash (gconstpointer v)
|
||||
{
|
||||
const GskTextureKey *k = (GskTextureKey *)v;
|
||||
|
||||
return GPOINTER_TO_UINT (k->pointer)
|
||||
+ (guint)(k->scale_x * 100)
|
||||
+ (guint)(k->scale_y * 100)
|
||||
+ (guint)k->filter * 2 +
|
||||
+ (guint)k->pointer_is_child;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
texture_key_equal (gconstpointer v1, gconstpointer v2)
|
||||
{
|
||||
const GskTextureKey *k1 = (GskTextureKey *)v1;
|
||||
const GskTextureKey *k2 = (GskTextureKey *)v2;
|
||||
|
||||
return k1->pointer == k2->pointer &&
|
||||
k1->scale_x == k2->scale_x &&
|
||||
k1->scale_y == k2->scale_y &&
|
||||
k1->filter == k2->filter &&
|
||||
k1->pointer_is_child == k2->pointer_is_child &&
|
||||
(!k1->pointer_is_child || graphene_rect_equal (&k1->parent_rect, &k2->parent_rect));
|
||||
}
|
||||
|
||||
int
|
||||
gsk_gl_driver_get_texture_for_key (GskGLDriver *self,
|
||||
GskTextureKey *key)
|
||||
{
|
||||
int id = 0;
|
||||
|
||||
if (G_UNLIKELY (self->pointer_textures == NULL))
|
||||
self->pointer_textures = g_hash_table_new_full (texture_key_hash, texture_key_equal, g_free, NULL);
|
||||
|
||||
id = GPOINTER_TO_INT (g_hash_table_lookup (self->pointer_textures, key));
|
||||
|
||||
if (id != 0)
|
||||
{
|
||||
Texture *t;
|
||||
|
||||
t = g_hash_table_lookup (self->textures, GINT_TO_POINTER (id));
|
||||
|
||||
if (t != NULL)
|
||||
t->in_use = TRUE;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_driver_set_texture_for_key (GskGLDriver *self,
|
||||
GskTextureKey *key,
|
||||
int texture_id)
|
||||
{
|
||||
GskTextureKey *k;
|
||||
|
||||
if (G_UNLIKELY (self->pointer_textures == NULL))
|
||||
self->pointer_textures = g_hash_table_new_full (texture_key_hash, texture_key_equal, g_free, NULL);
|
||||
|
||||
k = g_new (GskTextureKey, 1);
|
||||
*k = *key;
|
||||
|
||||
g_hash_table_insert (self->pointer_textures, k, GINT_TO_POINTER (texture_id));
|
||||
}
|
||||
|
||||
int
|
||||
gsk_gl_driver_create_texture (GskGLDriver *self,
|
||||
float width,
|
||||
float height)
|
||||
{
|
||||
Texture *t;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_GL_DRIVER (self), -1);
|
||||
|
||||
t = create_texture (self, width, height);
|
||||
|
||||
return t->texture_id;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_driver_create_render_target (GskGLDriver *self,
|
||||
int width,
|
||||
int height,
|
||||
int min_filter,
|
||||
int mag_filter,
|
||||
int *out_texture_id,
|
||||
int *out_render_target_id)
|
||||
{
|
||||
GLuint fbo_id;
|
||||
Texture *texture;
|
||||
|
||||
g_return_if_fail (self->in_frame);
|
||||
|
||||
texture = create_texture (self, width, height);
|
||||
gsk_gl_driver_bind_source_texture (self, texture->texture_id);
|
||||
gsk_gl_driver_init_texture_empty (self, texture->texture_id, min_filter, mag_filter);
|
||||
|
||||
glGenFramebuffers (1, &fbo_id);
|
||||
glBindFramebuffer (GL_FRAMEBUFFER, fbo_id);
|
||||
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture_id, 0);
|
||||
|
||||
#if 0
|
||||
if (add_depth_buffer || add_stencil_buffer)
|
||||
{
|
||||
glGenRenderbuffersEXT (1, &depth_stencil_buffer_id);
|
||||
gdk_gl_context_label_object_printf (self->gl_context, GL_RENDERBUFFER, depth_stencil_buffer_id,
|
||||
"%s buffer for %d", add_depth_buffer ? "Depth" : "Stencil", texture_id);
|
||||
}
|
||||
else
|
||||
depth_stencil_buffer_id = 0;
|
||||
|
||||
glBindRenderbuffer (GL_RENDERBUFFER, depth_stencil_buffer_id);
|
||||
|
||||
if (add_depth_buffer || add_stencil_buffer)
|
||||
{
|
||||
if (add_stencil_buffer)
|
||||
glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, t->width, t->height);
|
||||
else
|
||||
glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, t->width, t->height);
|
||||
|
||||
if (add_depth_buffer)
|
||||
glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
||||
GL_RENDERBUFFER, depth_stencil_buffer_id);
|
||||
|
||||
if (add_stencil_buffer)
|
||||
glFramebufferRenderbufferEXT (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
|
||||
GL_RENDERBUFFER, depth_stencil_buffer_id);
|
||||
texture->fbo.depth_stencil_id = depth_stencil_buffer_id;
|
||||
}
|
||||
#endif
|
||||
|
||||
texture->fbo.fbo_id = fbo_id;
|
||||
|
||||
g_assert_cmphex (glCheckFramebufferStatus (GL_FRAMEBUFFER), ==, GL_FRAMEBUFFER_COMPLETE);
|
||||
|
||||
glBindFramebuffer (GL_FRAMEBUFFER, self->default_fbo.fbo_id);
|
||||
|
||||
*out_texture_id = texture->texture_id;
|
||||
*out_render_target_id = fbo_id;
|
||||
}
|
||||
|
||||
/* Mark the texture permanent, meaning it won'e be reused by the GLDriver.
|
||||
* E.g. to store it in some other cache. */
|
||||
void
|
||||
gsk_gl_driver_mark_texture_permanent (GskGLDriver *self,
|
||||
int texture_id)
|
||||
{
|
||||
Texture *t = gsk_gl_driver_get_texture (self, texture_id);
|
||||
|
||||
g_assert (t != NULL);
|
||||
|
||||
t->permanent = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_driver_bind_source_texture (GskGLDriver *self,
|
||||
int texture_id)
|
||||
{
|
||||
Texture *t;
|
||||
|
||||
g_return_if_fail (GSK_IS_GL_DRIVER (self));
|
||||
g_return_if_fail (self->in_frame);
|
||||
|
||||
t = gsk_gl_driver_get_texture (self, texture_id);
|
||||
if (t == NULL)
|
||||
{
|
||||
g_critical ("No texture %d found.", texture_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->bound_source_texture != t)
|
||||
{
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
glBindTexture (GL_TEXTURE_2D, t->texture_id);
|
||||
|
||||
self->bound_source_texture = t;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_driver_destroy_texture (GskGLDriver *self,
|
||||
int texture_id)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_GL_DRIVER (self));
|
||||
|
||||
g_hash_table_remove (self->textures, GINT_TO_POINTER (texture_id));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gsk_gl_driver_init_texture_empty (GskGLDriver *self,
|
||||
int texture_id,
|
||||
int min_filter,
|
||||
int mag_filter)
|
||||
{
|
||||
Texture *t;
|
||||
|
||||
g_return_if_fail (GSK_IS_GL_DRIVER (self));
|
||||
|
||||
t = gsk_gl_driver_get_texture (self, texture_id);
|
||||
if (t == NULL)
|
||||
{
|
||||
g_critical ("No texture %d found.", texture_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->bound_source_texture != t)
|
||||
{
|
||||
g_critical ("You must bind the texture before initializing it.");
|
||||
return;
|
||||
}
|
||||
|
||||
t->min_filter = min_filter;
|
||||
t->mag_filter = mag_filter;
|
||||
|
||||
gsk_gl_driver_set_texture_parameters (self, t->min_filter, t->mag_filter);
|
||||
|
||||
if (gdk_gl_context_get_use_es (self->gl_context))
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, t->width, t->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
else
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, t->width, t->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
filter_uses_mipmaps (int filter)
|
||||
{
|
||||
return filter != GL_NEAREST && filter != GL_LINEAR;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_driver_init_texture (GskGLDriver *self,
|
||||
int texture_id,
|
||||
GdkTexture *texture,
|
||||
int min_filter,
|
||||
int mag_filter)
|
||||
{
|
||||
Texture *t;
|
||||
|
||||
g_return_if_fail (GSK_IS_GL_DRIVER (self));
|
||||
|
||||
t = gsk_gl_driver_get_texture (self, texture_id);
|
||||
if (t == NULL)
|
||||
{
|
||||
g_critical ("No texture %d found.", texture_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->bound_source_texture != t)
|
||||
{
|
||||
g_critical ("You must bind the texture before initializing it.");
|
||||
return;
|
||||
}
|
||||
|
||||
gsk_gl_driver_set_texture_parameters (self, min_filter, mag_filter);
|
||||
|
||||
upload_gdk_texture (texture, GL_TEXTURE_2D, 0, 0, t->width, t->height);
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
gsk_profiler_counter_inc (self->profiler, self->counters.surface_uploads);
|
||||
#endif
|
||||
|
||||
t->min_filter = min_filter;
|
||||
t->mag_filter = mag_filter;
|
||||
|
||||
if (filter_uses_mipmaps (t->min_filter))
|
||||
glGenerateMipmap (GL_TEXTURE_2D);
|
||||
}
|
||||
86
gsk/gl/gskgldriverprivate.h
Normal file
86
gsk/gl/gskgldriverprivate.h
Normal file
@@ -0,0 +1,86 @@
|
||||
#ifndef __GSK_GL_DRIVER_PRIVATE_H__
|
||||
#define __GSK_GL_DRIVER_PRIVATE_H__
|
||||
|
||||
#include <cairo.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <graphene.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_GL_DRIVER (gsk_gl_driver_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GskGLDriver, gsk_gl_driver, GSK, GL_DRIVER, GObject)
|
||||
|
||||
typedef struct {
|
||||
float position[2];
|
||||
float uv[2];
|
||||
} GskQuadVertex;
|
||||
|
||||
typedef struct {
|
||||
cairo_rectangle_int_t rect;
|
||||
guint texture_id;
|
||||
} TextureSlice;
|
||||
|
||||
typedef struct {
|
||||
gpointer pointer;
|
||||
float scale_x;
|
||||
float scale_y;
|
||||
int filter;
|
||||
int pointer_is_child;
|
||||
graphene_rect_t parent_rect; /* Only set if pointer_is_child */
|
||||
} GskTextureKey;
|
||||
|
||||
GskGLDriver * gsk_gl_driver_new (GdkGLContext *context);
|
||||
GdkGLContext *gsk_gl_driver_get_gl_context (GskGLDriver *driver);
|
||||
|
||||
int gsk_gl_driver_get_max_texture_size (GskGLDriver *driver);
|
||||
|
||||
void gsk_gl_driver_begin_frame (GskGLDriver *driver);
|
||||
void gsk_gl_driver_end_frame (GskGLDriver *driver);
|
||||
gboolean gsk_gl_driver_in_frame (GskGLDriver *driver);
|
||||
int gsk_gl_driver_get_texture_for_texture (GskGLDriver *driver,
|
||||
GdkTexture *texture,
|
||||
int min_filter,
|
||||
int mag_filter);
|
||||
int gsk_gl_driver_get_texture_for_key (GskGLDriver *driver,
|
||||
GskTextureKey *key);
|
||||
void gsk_gl_driver_set_texture_for_key (GskGLDriver *driver,
|
||||
GskTextureKey *key,
|
||||
int texture_id);
|
||||
int gsk_gl_driver_create_texture (GskGLDriver *driver,
|
||||
float width,
|
||||
float height);
|
||||
void gsk_gl_driver_create_render_target (GskGLDriver *driver,
|
||||
int width,
|
||||
int height,
|
||||
int min_filter,
|
||||
int mag_filter,
|
||||
int *out_texture_id,
|
||||
int *out_render_target_id);
|
||||
void gsk_gl_driver_mark_texture_permanent (GskGLDriver *self,
|
||||
int texture_id);
|
||||
void gsk_gl_driver_bind_source_texture (GskGLDriver *driver,
|
||||
int texture_id);
|
||||
|
||||
void gsk_gl_driver_init_texture_empty (GskGLDriver *driver,
|
||||
int texture_id,
|
||||
int min_filter,
|
||||
int max_filter);
|
||||
void gsk_gl_driver_init_texture (GskGLDriver *driver,
|
||||
int texture_id,
|
||||
GdkTexture *texture,
|
||||
int min_filter,
|
||||
int mag_filter);
|
||||
|
||||
void gsk_gl_driver_destroy_texture (GskGLDriver *driver,
|
||||
int texture_id);
|
||||
|
||||
int gsk_gl_driver_collect_textures (GskGLDriver *driver);
|
||||
void gsk_gl_driver_slice_texture (GskGLDriver *self,
|
||||
GdkTexture *texture,
|
||||
TextureSlice **out_slices,
|
||||
guint *out_n_slices);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_GL_DRIVER_PRIVATE_H__ */
|
||||
397
gsk/gl/gskglglyphcache.c
Normal file
397
gsk/gl/gskglglyphcache.c
Normal file
@@ -0,0 +1,397 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gskglglyphcacheprivate.h"
|
||||
#include "gskgldriverprivate.h"
|
||||
#include "gskdebugprivate.h"
|
||||
#include "gskprivate.h"
|
||||
#include "gskgltextureatlasprivate.h"
|
||||
|
||||
#include "gdk/gdkglcontextprivate.h"
|
||||
#include "gdk/gdkmemorytextureprivate.h"
|
||||
|
||||
#include <graphene.h>
|
||||
#include <cairo.h>
|
||||
#include <epoxy/gl.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Cache eviction strategy
|
||||
*
|
||||
* We mark glyphs as accessed every time we use them.
|
||||
* Every few frames, we mark glyphs that haven't been
|
||||
* accessed since the last check as old.
|
||||
*
|
||||
* We keep count of the pixels of each atlas that are
|
||||
* taken up by old data. When the fraction of old pixels
|
||||
* gets too high, we drop the atlas and all the items it
|
||||
* contained.
|
||||
*
|
||||
* Big glyphs are not stored in the atlas, they get their
|
||||
* own texture, but they are still cached.
|
||||
*/
|
||||
|
||||
#define MAX_FRAME_AGE (60)
|
||||
#define MAX_GLYPH_SIZE 128 /* Will get its own texture if bigger */
|
||||
|
||||
static guint glyph_cache_hash (gconstpointer v);
|
||||
static gboolean glyph_cache_equal (gconstpointer v1,
|
||||
gconstpointer v2);
|
||||
static void glyph_cache_key_free (gpointer v);
|
||||
static void glyph_cache_value_free (gpointer v);
|
||||
|
||||
GskGLGlyphCache *
|
||||
gsk_gl_glyph_cache_new (GdkDisplay *display,
|
||||
GskGLTextureAtlases *atlases)
|
||||
{
|
||||
GskGLGlyphCache *glyph_cache;
|
||||
|
||||
glyph_cache = g_new0 (GskGLGlyphCache, 1);
|
||||
|
||||
glyph_cache->display = display;
|
||||
glyph_cache->hash_table = g_hash_table_new_full (glyph_cache_hash, glyph_cache_equal,
|
||||
glyph_cache_key_free, glyph_cache_value_free);
|
||||
|
||||
glyph_cache->atlases = gsk_gl_texture_atlases_ref (atlases);
|
||||
|
||||
glyph_cache->ref_count = 1;
|
||||
|
||||
return glyph_cache;
|
||||
}
|
||||
|
||||
GskGLGlyphCache *
|
||||
gsk_gl_glyph_cache_ref (GskGLGlyphCache *self)
|
||||
{
|
||||
self->ref_count++;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_glyph_cache_unref (GskGLGlyphCache *self)
|
||||
{
|
||||
g_assert (self->ref_count > 0);
|
||||
|
||||
if (self->ref_count == 1)
|
||||
{
|
||||
gsk_gl_texture_atlases_unref (self->atlases);
|
||||
g_hash_table_unref (self->hash_table);
|
||||
g_free (self);
|
||||
return;
|
||||
}
|
||||
|
||||
self->ref_count--;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
glyph_cache_equal (gconstpointer v1, gconstpointer v2)
|
||||
{
|
||||
return memcmp (v1, v2, sizeof (CacheKeyData)) == 0;
|
||||
}
|
||||
|
||||
static guint
|
||||
glyph_cache_hash (gconstpointer v)
|
||||
{
|
||||
const GlyphCacheKey *key = v;
|
||||
|
||||
return key->hash;
|
||||
}
|
||||
|
||||
static void
|
||||
glyph_cache_key_free (gpointer v)
|
||||
{
|
||||
GlyphCacheKey *f = v;
|
||||
|
||||
g_object_unref (f->data.font);
|
||||
g_free (f);
|
||||
}
|
||||
|
||||
static void
|
||||
glyph_cache_value_free (gpointer v)
|
||||
{
|
||||
g_free (v);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
render_glyph (GlyphCacheKey *key,
|
||||
GskGLCachedGlyph *value,
|
||||
GskImageRegion *region)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
cairo_scaled_font_t *scaled_font;
|
||||
PangoGlyphString glyph_string;
|
||||
PangoGlyphInfo glyph_info;
|
||||
int surface_width, surface_height;
|
||||
int stride;
|
||||
unsigned char *data;
|
||||
|
||||
scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)key->data.font);
|
||||
if (G_UNLIKELY (!scaled_font || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS))
|
||||
{
|
||||
g_warning ("Failed to get a font");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
surface_width = value->draw_width * key->data.scale / 1024;
|
||||
surface_height = value->draw_height * key->data.scale / 1024;
|
||||
|
||||
stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, surface_width);
|
||||
data = g_malloc0 (stride * surface_height);
|
||||
surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32,
|
||||
surface_width, surface_height,
|
||||
stride);
|
||||
cairo_surface_set_device_scale (surface, key->data.scale / 1024.0, key->data.scale / 1024.0);
|
||||
|
||||
cr = cairo_create (surface);
|
||||
|
||||
cairo_set_scaled_font (cr, scaled_font);
|
||||
cairo_set_source_rgba (cr, 1, 1, 1, 1);
|
||||
|
||||
glyph_info.glyph = key->data.glyph;
|
||||
glyph_info.geometry.width = value->draw_width * 1024;
|
||||
if (glyph_info.glyph & PANGO_GLYPH_UNKNOWN_FLAG)
|
||||
glyph_info.geometry.x_offset = 256 * key->data.xshift;
|
||||
else
|
||||
glyph_info.geometry.x_offset = 256 * key->data.xshift - value->draw_x * 1024;
|
||||
glyph_info.geometry.y_offset = 256 * key->data.yshift - value->draw_y * 1024;
|
||||
|
||||
glyph_string.num_glyphs = 1;
|
||||
glyph_string.glyphs = &glyph_info;
|
||||
|
||||
pango_cairo_show_glyph_string (cr, key->data.font, &glyph_string);
|
||||
cairo_destroy (cr);
|
||||
|
||||
cairo_surface_flush (surface);
|
||||
|
||||
region->width = cairo_image_surface_get_width (surface);
|
||||
region->height = cairo_image_surface_get_height (surface);
|
||||
region->stride = cairo_image_surface_get_stride (surface);
|
||||
region->data = data;
|
||||
if (value->atlas)
|
||||
{
|
||||
region->x = (gsize)(value->tx * value->atlas->width);
|
||||
region->y = (gsize)(value->ty * value->atlas->height);
|
||||
}
|
||||
else
|
||||
{
|
||||
region->x = 0;
|
||||
region->y = 0;
|
||||
}
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
upload_glyph (GlyphCacheKey *key,
|
||||
GskGLCachedGlyph *value)
|
||||
{
|
||||
GskImageRegion r;
|
||||
guchar *pixel_data;
|
||||
guchar *free_data = NULL;
|
||||
guint gl_format;
|
||||
guint gl_type;
|
||||
|
||||
gdk_gl_context_push_debug_group_printf (gdk_gl_context_get_current (),
|
||||
"Uploading glyph %d",
|
||||
key->data.glyph);
|
||||
|
||||
if (render_glyph (key, value, &r))
|
||||
{
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, r.stride / 4);
|
||||
glBindTexture (GL_TEXTURE_2D, value->texture_id);
|
||||
|
||||
if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
|
||||
{
|
||||
pixel_data = free_data = g_malloc (r.width * r.height * 4);
|
||||
gdk_memory_convert (pixel_data, r.width * 4,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
r.data, r.width * 4,
|
||||
GDK_MEMORY_DEFAULT, r.width, r.height);
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pixel_data = r.data;
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
}
|
||||
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0, r.x, r.y, r.width, r.height,
|
||||
gl_format, gl_type, pixel_data);
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
|
||||
g_free (r.data);
|
||||
g_free (free_data);
|
||||
}
|
||||
|
||||
gdk_gl_context_pop_debug_group (gdk_gl_context_get_current ());
|
||||
}
|
||||
|
||||
static void
|
||||
add_to_cache (GskGLGlyphCache *self,
|
||||
GlyphCacheKey *key,
|
||||
GskGLDriver *driver,
|
||||
GskGLCachedGlyph *value)
|
||||
{
|
||||
const int width = value->draw_width * key->data.scale / 1024;
|
||||
const int height = value->draw_height * key->data.scale / 1024;
|
||||
|
||||
if (width < MAX_GLYPH_SIZE && height < MAX_GLYPH_SIZE)
|
||||
{
|
||||
GskGLTextureAtlas *atlas = NULL;
|
||||
int packed_x = 0;
|
||||
int packed_y = 0;
|
||||
|
||||
gsk_gl_texture_atlases_pack (self->atlases, width + 2, height + 2, &atlas, &packed_x, &packed_y);
|
||||
|
||||
value->tx = (float)(packed_x + 1) / atlas->width;
|
||||
value->ty = (float)(packed_y + 1) / atlas->height;
|
||||
value->tw = (float)width / atlas->width;
|
||||
value->th = (float)height / atlas->height;
|
||||
value->used = TRUE;
|
||||
|
||||
value->atlas = atlas;
|
||||
value->texture_id = atlas->texture_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
value->atlas = NULL;
|
||||
value->texture_id = gsk_gl_driver_create_texture (driver, width, height);
|
||||
gsk_gl_driver_mark_texture_permanent (driver, value->texture_id);
|
||||
|
||||
gsk_gl_driver_bind_source_texture (driver, value->texture_id);
|
||||
gsk_gl_driver_init_texture_empty (driver, value->texture_id, GL_LINEAR, GL_LINEAR);
|
||||
|
||||
value->tx = 0.0f;
|
||||
value->ty = 0.0f;
|
||||
value->tw = 1.0f;
|
||||
value->th = 1.0f;
|
||||
}
|
||||
|
||||
upload_glyph (key, value);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_glyph_cache_lookup_or_add (GskGLGlyphCache *cache,
|
||||
GlyphCacheKey *lookup,
|
||||
GskGLDriver *driver,
|
||||
const GskGLCachedGlyph **cached_glyph_out)
|
||||
{
|
||||
GskGLCachedGlyph *value;
|
||||
|
||||
value = g_hash_table_lookup (cache->hash_table, lookup);
|
||||
|
||||
if (value)
|
||||
{
|
||||
if (value->atlas && !value->used)
|
||||
{
|
||||
gsk_gl_texture_atlas_mark_used (value->atlas, value->draw_width, value->draw_height);
|
||||
value->used = TRUE;
|
||||
}
|
||||
value->accessed = TRUE;
|
||||
|
||||
*cached_glyph_out = value;
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
GlyphCacheKey *key;
|
||||
PangoRectangle ink_rect;
|
||||
|
||||
pango_font_get_glyph_extents (lookup->data.font, lookup->data.glyph, &ink_rect, NULL);
|
||||
pango_extents_to_pixels (&ink_rect, NULL);
|
||||
if (lookup->data.xshift != 0)
|
||||
ink_rect.width += 1;
|
||||
if (lookup->data.yshift != 0)
|
||||
ink_rect.height += 1;
|
||||
|
||||
value = g_new0 (GskGLCachedGlyph, 1);
|
||||
|
||||
value->draw_x = ink_rect.x;
|
||||
value->draw_y = ink_rect.y;
|
||||
value->draw_width = ink_rect.width;
|
||||
value->draw_height = ink_rect.height;
|
||||
value->accessed = TRUE;
|
||||
value->atlas = NULL; /* For now */
|
||||
|
||||
key = g_new0 (GlyphCacheKey, 1);
|
||||
|
||||
key->data.font = g_object_ref (lookup->data.font);
|
||||
key->data.glyph = lookup->data.glyph;
|
||||
key->data.xshift = lookup->data.xshift;
|
||||
key->data.yshift = lookup->data.yshift;
|
||||
key->data.scale = lookup->data.scale;
|
||||
key->hash = lookup->hash;
|
||||
|
||||
if (key->data.scale > 0 &&
|
||||
value->draw_width * key->data.scale / 1024 > 0 &&
|
||||
value->draw_height * key->data.scale / 1024 > 0)
|
||||
add_to_cache (cache, key, driver, value);
|
||||
|
||||
*cached_glyph_out = value;
|
||||
g_hash_table_insert (cache->hash_table, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache *self,
|
||||
GskGLDriver *driver,
|
||||
GPtrArray *removed_atlases)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
GlyphCacheKey *key;
|
||||
GskGLCachedGlyph *value;
|
||||
guint dropped = 0;
|
||||
|
||||
self->timestamp++;
|
||||
|
||||
if (removed_atlases->len > 0)
|
||||
{
|
||||
g_hash_table_iter_init (&iter, self->hash_table);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
|
||||
{
|
||||
if (g_ptr_array_find (removed_atlases, value->atlas, NULL))
|
||||
{
|
||||
g_hash_table_iter_remove (&iter);
|
||||
dropped++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (self->timestamp % MAX_FRAME_AGE == 30)
|
||||
{
|
||||
g_hash_table_iter_init (&iter, self->hash_table);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
|
||||
{
|
||||
if (!value->accessed)
|
||||
{
|
||||
if (value->atlas)
|
||||
{
|
||||
if (value->used)
|
||||
{
|
||||
gsk_gl_texture_atlas_mark_unused (value->atlas, value->draw_width, value->draw_height);
|
||||
value->used = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gsk_gl_driver_destroy_texture (driver, value->texture_id);
|
||||
g_hash_table_iter_remove (&iter);
|
||||
|
||||
/* Sadly, if we drop an atlas-less cached glyph, we
|
||||
* have to treat it like a dropped atlas and purge
|
||||
* text node render data.
|
||||
*/
|
||||
dropped++;
|
||||
}
|
||||
}
|
||||
else
|
||||
value->accessed = FALSE;
|
||||
}
|
||||
|
||||
GSK_NOTE(GLYPH_CACHE, g_message ("%d glyphs cached", g_hash_table_size (self->hash_table)));
|
||||
}
|
||||
|
||||
GSK_NOTE(GLYPH_CACHE, if (dropped > 0) g_message ("Dropped %d glyphs", dropped));
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user