Compare commits

...

46 Commits

Author SHA1 Message Date
Luca Bacci
e4aa58b4c0 GdkWin32: Add Utility functions 2024-10-10 15:04:24 +02:00
Luca Bacci
be2adb1838 Merge branch 'msys2-switch-to-ucrt64' into 'main'
MSYS2: Switch to UCRT64

See merge request GNOME/gtk!7812
2024-10-10 08:26:45 +00:00
Luca Bacci
0113fdc8d5 Merge branch 'gdk-win32-purge-globals' into 'main'
GDK/Win32: Drop most of the global variables

See merge request GNOME/gtk!7804
2024-10-10 08:26:30 +00:00
Matthias Clasen
53cbc64f41 Merge branch 'alatiera/sysprof-uri' into 'main'
gtkcssprovider: Only add the marker if the file is not null

See merge request GNOME/gtk!7807
2024-10-09 15:40:12 +00:00
Jordan Petridis
83387608ee gtkcssprovider: Use g_file_peek_path to get the uri for the sysprof marker
This avoids an extra allocation.

Additionally avoid calling it if file is already null.
2024-10-09 17:39:08 +03:00
Benjamin Otte
a5b4d2b500 Merge branch 'typo-fix' into 'main'
Fix a typo

Closes #6984

See merge request GNOME/gtk!7816
2024-10-08 23:30:07 +00:00
ARAKHNID
1b83d87cf5 Fix a typo
Closes #6984
2024-10-08 13:41:04 -05:00
Emmanuele Bassi
6c2eb08b07 Merge branch 'wip/chergert/fix-a11y-default-attributes' into 'main'
gtk/accessibletext: handle NULL default values

Closes #7069

See merge request GNOME/gtk!7813
2024-10-08 18:10:26 +00:00
Christian Hergert
ab1c85830c gtk/accessibletext: handle NULL default values
The default implementation for get_default_attributes() returns NULL for
both names and values yet the code which iterates them is assuming they
will never be NULL.

Since the interface implies that if the values are set, they will return
valid strings, make the default implementation do that.

Fixes: #7069
2024-10-08 10:41:19 -07:00
Luca Bacci
d154decbb5 CI/MSYS2: Switch to UCRT64 2024-10-08 14:01:32 +02:00
Luca Bacci
c7705f156a Rework test-msys2.sh a bit 2024-10-08 13:59:43 +02:00
Luca Bacci
20bdb0d7d5 Merge branch 'wgl-updates' into 'main'
WGL: Avoid using swap exchange on NVidia drivers

Closes #7019

See merge request GNOME/gtk!7776
2024-10-08 10:24:02 +00:00
Luca Bacci
f840ae1337 WGL: Avoid using swap method exchange on NVidia drivers
It seems that NVidia sets PFD_SWAP_EXCHANGE / WGL_SWAP_EXCHANGE_ARB
on pixel formats but doesn't guarantee that the backbuffer age is
constantly 2. My guess is that they use swap exchange only to signal
usage of a flip present method.

Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/7019
2024-10-08 11:27:05 +02:00
Benjamin Otte
02feba87f2 Merge branch 'wip/otte/for-main' into 'main'
gpu: Remove warning

See merge request GNOME/gtk!7805
2024-10-07 10:20:37 +00:00
Benjamin Otte
220d7a3d5e picture: Queue a redraw when not resizing
When changing the code to do the resize only when the size changed, I
forgot to queue a draw when the size did not change.

Fixes: 5031f30f28
Related: !7786
2024-10-07 11:35:50 +02:00
Benjamin Otte
39686daa23 gpu: Remove warning
The warning gets triggered by rounding errors.

In particular when using fractional scales, the final tile may end up
not accurately matching the computed final value (in the example I was
debugging it was computing 1 vs 1.00000036 for the final tile index,
but that result computed a 0px wide tile size.
And for that tile size we hit that exit condition.
2024-10-07 11:31:34 +02:00
Chun-wei Fan
b6269a3234 gdkevents-win32.c: Drop AeroSnap global variables
Put them into our GdkWin32Display under an appropriate sub-struct.
2024-10-07 14:37:40 +08:00
Chun-wei Fan
2879f6a99b gdkevents-win32.c: Drop event debug indent global variable
Tuck it as appropriate into our GdkWin32Display.
2024-10-07 14:37:40 +08:00
Chun-wei Fan
03a86b4667 GDK/Win32: Drop global variable on both shifts pressed 2024-10-07 14:37:39 +08:00
Chun-wei Fan
7eb96c39c5 GDK/Win32: Drop global variable tracking IME state
Tuck it into our GdkDisplay structure under an appropriate sub-struct.
2024-10-07 14:37:38 +08:00
Chun-wei Fan
b4c5a7af69 GDK/Win32: Fold pen input global vars into GdkDeviceManagerWin32
This way, we just grab and set the values from there.
2024-10-07 14:37:38 +08:00
Chun-wei Fan
d120aaf6ee GDK/Win32: Drop global variables from GdkKeys implementation
We get to create our GdkKey with a display as a property for free, so
just stuff the default keymap and keymap serial (to track IME state
changes and so) into our GdkWin32Display under an existing sub-struct
that is for holding these items.
2024-10-07 14:37:23 +08:00
Chun-wei Fan
004d787cb2 Gdk/Win32: Drop _gdk_display global variable
On Windows, we really only support a single GdkDisplay, so we can just
make the GdkDisplay that we obtain a property of our GdkDeviceManagerWin32
and GdkWin32Screen objects, and so we can just do away with the global
_gdk_display global variable.

This way, we can also drop the venerable gdkglobals-win32.c source file.
Yay!
2024-10-07 12:07:05 +08:00
Chun-wei Fan
7b554240f3 GDK/Win32: Drop modal surface-related global variables
Tuck them into GdkWin32Display as we track these operations.
2024-10-07 12:01:08 +08:00
Chun-wei Fan
7837f342e9 GdkDeviceManagerWin32: Drop global variables
Tuck the wintab global variables into the GdkDeviceManagerWin32
structure, and initialize and utilize items accordingly.
2024-10-07 12:01:07 +08:00
Chun-wei Fan
236139c78a gdkdisplay-win32.c: Drop debug_indent global variable
Instead, use [Set|Get]WindowLongPtr(), to store and retrieve that
value from the notification window HWND that we are using, as it
is where we are using that value.
2024-10-07 12:01:06 +08:00
Chun-wei Fan
789bb83b5a GDK/Win32: Drop surface tracking global variables
...including the list of modal surfaces and hashes of opened HWNDs for
various surfaces, and tuck them into GdkWin32Display.
2024-10-07 12:00:59 +08:00
Chun-wei Fan
0a65221721 GDK/Win32: Drop global variables in Direct Manipuation code
Tuck them into GdkWin32Display.
2024-10-07 11:56:21 +08:00
Chun-wei Fan
b37947ff20 GDK/Win32: Drop global variables related to GdkDevice
Tuck the _win32_device_manager global variable into GdkWin32Display, and
drop the global variables that have to do with GdkDeviceManagerWin32.

Also improve how we query the WinPointer APIs from user32.dll, so that
we are sure that it is done once and only once.
2024-10-07 11:56:20 +08:00
Chun-wei Fan
0d4f827de8 GDK/Win32: Drop Clipdrop/DND global variables
Tuck the GdkWin32Clipdrop that we create in our GdkWin32Display, and
tuck the other associated global variables into GdkWin32ClipDrop and
GdkWin32Drag, as appropriate.

Also, since we are already registering "GDK_WORKER_THREAD_WAKEUP" as our
custom message to look for in our DND/clipboard ops, only register it
once, not twice, as it's not really necessary to do so since
RegisterWindowMessage() returns the same value for the same identifier
that is being used.,
2024-10-07 11:56:12 +08:00
Chun-wei Fan
1f52048e77 GDK/Win32: Drop global variable to track main thread
Instead, record the current thread in the GdkDisplay, under a structure
for DND items, which will hold other relevant Windows Clipbord/DND global
variables.

Add a new function in gdkdrag-win32.c to check whether the current
thread is (or is not) equivilant to the thread that is initiated when
the GdkDisplay is initialized (which also returns true if there is no
GdkDisplay that is associated with the GdkDrag in question).
2024-10-07 11:54:26 +08:00
Chun-wei Fan
7600d44995 GDK/Win32: Drop _gdk_ignore_input_core global variable
...and fold it into GdkWin32Display under pointer_device_items.
2024-10-07 11:50:21 +08:00
Chun-wei Fan
8bb806cd85 gdkmain-win32.c: Tuck global varianbles into local variables
...and use g_once_init_[enter|leave]() to mark that GDK did or did not
indeed successfully initialize COM and OLE2.
2024-10-07 11:39:04 +08:00
Chun-wei Fan
28aacf3db4 GDK/Win32: Drop input locale global variables
Rename gdkwin32id.c as gdkwin32misc.c.

Fold these items into GdkWin32Display, and also fold gdkproperty-win32.c
and gdkwin32langnoticiation.[c|h] into gdkwin32misc.c and gdkdisplay-win32.h as
appropriate.

This way, we get rid of few more global variables, and these items
should have been initialized (and registered with the system) when we
open a GdkWin32Display anyways.
2024-10-07 11:37:14 +08:00
Chun-wei Fan
95ad05181c gdksurface-win32.c: Drop a global variable
Use the gdk_win32_surface_parent_class that is given to us by
G_DEFINE_TYPE() instead of using a global variable to store up the
parent class of GdkWin32Surface.
2024-10-07 10:28:34 +08:00
Martin
b4a54bb9cb Update Slovenian translation 2024-10-05 18:36:53 +00:00
Matthias Clasen
12dd5be649 Merge branch '3to4-separator' into 'main'
gtk4-builder-tool: Rewrite Gtk{H,V}Seperator

See merge request GNOME/gtk!7800
2024-10-05 14:52:30 +00:00
Guido Günther
c86e45c432 gtk4-builder-tool: Rewrite Gtk{H,V}Seperator
One less UI element to worry about when migrating from GTK3.

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2024-10-05 15:54:49 +02:00
Matthias Clasen
1ad5943cd8 Merge branch 'for-main' into 'main'
image tool: Better color state support

See merge request GNOME/gtk!7799
2024-10-05 13:38:07 +00:00
Matthias Clasen
34c69b2868 build: Don't use / in target names
It is unnecessary, and meson doesn't like it.
2024-10-05 08:55:50 -04:00
Matthias Clasen
28817b4bb2 image tool: Better color state support
Show cicp color states with their tuple.
2024-10-05 08:16:07 -04:00
Matthias Clasen
b0acf2a7a8 Merge branch 'for-main' into 'main'
docs: Update GSK_GPU_DISABLE docs

See merge request GNOME/gtk!7798
2024-10-05 02:05:34 +00:00
Matthias Clasen
32d03a548e Drop some demos
The gtk4-icon-browser and gtk4-constraint-editor demos are basically
unmaintained, and not great showcases for GTK, so lets drop them.
2024-10-04 21:24:11 -04:00
Matthias Clasen
fecadae80c docs: Update GSK_GPU_DISABLE docs
Add `repeat`.
2024-10-04 14:42:38 -04:00
Matthias Clasen
2d1367ccdc Merge branch 'wip/otte/this-looks-correct-but-is-it' into 'main'
listitemfactory: Don't rebind on position or selection changes

See merge request GNOME/gtk!7420
2024-10-04 18:32:08 +00:00
Benjamin Otte
3a8e1c55e1 listitemfactory: Don't rebind on position or selection changes
When the item doesn't change and only the position / selection state,
then the signal list item factory should not emit bind + unbind signals.

This used to work, but probably broke while refactoring for ColumnView
during 4.10.

This caused excessive rebinding when items got inserted at the top of a
list instead of add the end.
2024-07-07 05:38:22 +02:00
74 changed files with 2154 additions and 4676 deletions

View File

@@ -198,11 +198,11 @@ fedora-mingw64:
- subprojects/libepoxy/
- subprojects/pango/
msys2-mingw64:
msys2-ucrt64:
extends: .mingw-defaults
needs: []
variables:
MSYSTEM: "MINGW64"
MSYSTEM: "UCRT64"
CHERE_INVOKING: "yes"
artifacts:
when: always

View File

@@ -2,12 +2,6 @@
set -e
if [[ "$MSYSTEM" == "MINGW32" ]]; then
export MSYS2_ARCH="i686"
else
export MSYS2_ARCH="x86_64"
fi
# Update everything
pacman --noconfirm -Suy
@@ -15,27 +9,27 @@ pacman --noconfirm -Suy
pacman --noconfirm -S --needed \
base-devel \
git \
mingw-w64-$MSYS2_ARCH-cc \
mingw-w64-$MSYS2_ARCH-ccache \
mingw-w64-$MSYS2_ARCH-pkgconf \
mingw-w64-$MSYS2_ARCH-gobject-introspection \
mingw-w64-$MSYS2_ARCH-meson \
mingw-w64-$MSYS2_ARCH-adwaita-icon-theme \
mingw-w64-$MSYS2_ARCH-atk \
mingw-w64-$MSYS2_ARCH-cairo \
mingw-w64-$MSYS2_ARCH-gdk-pixbuf2 \
mingw-w64-$MSYS2_ARCH-glib2 \
mingw-w64-$MSYS2_ARCH-graphene \
mingw-w64-$MSYS2_ARCH-json-glib \
mingw-w64-$MSYS2_ARCH-libepoxy \
mingw-w64-$MSYS2_ARCH-pango \
mingw-w64-$MSYS2_ARCH-fribidi \
mingw-w64-$MSYS2_ARCH-gst-plugins-bad-libs \
mingw-w64-$MSYS2_ARCH-shared-mime-info \
mingw-w64-$MSYS2_ARCH-python-gobject \
mingw-w64-$MSYS2_ARCH-shaderc \
mingw-w64-$MSYS2_ARCH-vulkan \
mingw-w64-$MSYS2_ARCH-vulkan-headers
${MINGW_PACKAGE_PREFIX}-cc \
${MINGW_PACKAGE_PREFIX}-ccache \
${MINGW_PACKAGE_PREFIX}-pkgconf \
${MINGW_PACKAGE_PREFIX}-gobject-introspection \
${MINGW_PACKAGE_PREFIX}-meson \
${MINGW_PACKAGE_PREFIX}-adwaita-icon-theme \
${MINGW_PACKAGE_PREFIX}-atk \
${MINGW_PACKAGE_PREFIX}-cairo \
${MINGW_PACKAGE_PREFIX}-gdk-pixbuf2 \
${MINGW_PACKAGE_PREFIX}-glib2 \
${MINGW_PACKAGE_PREFIX}-graphene \
${MINGW_PACKAGE_PREFIX}-json-glib \
${MINGW_PACKAGE_PREFIX}-libepoxy \
${MINGW_PACKAGE_PREFIX}-pango \
${MINGW_PACKAGE_PREFIX}-fribidi \
${MINGW_PACKAGE_PREFIX}-gst-plugins-bad-libs \
${MINGW_PACKAGE_PREFIX}-shared-mime-info \
${MINGW_PACKAGE_PREFIX}-python-gobject \
${MINGW_PACKAGE_PREFIX}-shaderc \
${MINGW_PACKAGE_PREFIX}-vulkan \
${MINGW_PACKAGE_PREFIX}-vulkan-headers
mkdir -p _ccache
export CCACHE_BASEDIR="$(pwd)"

View File

@@ -1,115 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "config.h"
#include "constraint-editor-application.h"
#include "constraint-editor-window.h"
struct _ConstraintEditorApplication
{
GtkApplication parent_instance;
};
G_DEFINE_TYPE(ConstraintEditorApplication, constraint_editor_application, GTK_TYPE_APPLICATION);
static void
constraint_editor_application_init (ConstraintEditorApplication *app)
{
}
static void
quit_activated (GSimpleAction *action,
GVariant *parameter,
gpointer data)
{
g_application_quit (G_APPLICATION (data));
}
static GActionEntry app_entries[] =
{
{ "quit", quit_activated, NULL, NULL, NULL }
};
static void
constraint_editor_application_startup (GApplication *app)
{
const char *quit_accels[2] = { "<Ctrl>Q", NULL };
const char *open_accels[2] = { "<Ctrl>O", NULL };
GtkCssProvider *provider;
G_APPLICATION_CLASS (constraint_editor_application_parent_class)->startup (app);
g_action_map_add_action_entries (G_ACTION_MAP (app),
app_entries, G_N_ELEMENTS (app_entries),
app);
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "app.quit", quit_accels);
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "win.open", open_accels);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/org/gtk/gtk4/constraint-editor/constraint-editor.css");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
static void
constraint_editor_application_activate (GApplication *app)
{
ConstraintEditorWindow *win;
win = constraint_editor_window_new (CONSTRAINT_EDITOR_APPLICATION (app));
gtk_window_present (GTK_WINDOW (win));
}
static void
constraint_editor_application_open (GApplication *app,
GFile **files,
int n_files,
const char *hint)
{
ConstraintEditorWindow *win;
int i;
for (i = 0; i < n_files; i++)
{
win = constraint_editor_window_new (CONSTRAINT_EDITOR_APPLICATION (app));
constraint_editor_window_load (win, files[i]);
gtk_window_present (GTK_WINDOW (win));
}
}
static void
constraint_editor_application_class_init (ConstraintEditorApplicationClass *class)
{
GApplicationClass *application_class = G_APPLICATION_CLASS (class);
application_class->startup = constraint_editor_application_startup;
application_class->activate = constraint_editor_application_activate;
application_class->open = constraint_editor_application_open;
}
ConstraintEditorApplication *
constraint_editor_application_new (void)
{
return g_object_new (CONSTRAINT_EDITOR_APPLICATION_TYPE,
"application-id", "org.gtk.gtk4.ConstraintEditor",
"flags", G_APPLICATION_HANDLES_OPEN,
NULL);
}

View File

@@ -1,652 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "config.h"
#include "constraint-editor-window.h"
#include "constraint-view.h"
#include "constraint-editor.h"
#include "guide-editor.h"
struct _ConstraintEditorWindow
{
GtkApplicationWindow parent_instance;
GtkWidget *paned;
GtkWidget *view;
GtkWidget *list;
};
G_DEFINE_TYPE(ConstraintEditorWindow, constraint_editor_window, GTK_TYPE_APPLICATION_WINDOW);
static GtkConstraintTarget *
find_target (GListModel *model,
GtkConstraintTarget *orig)
{
const char *name;
const char *model_name;
gpointer item;
int i;
if (orig == NULL)
return NULL;
if (GTK_IS_LABEL (orig))
name = gtk_label_get_label (GTK_LABEL (orig));
else if (GTK_IS_CONSTRAINT_GUIDE (orig))
name = gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (orig));
else
{
g_warning ("Don't know how to handle %s targets", G_OBJECT_TYPE_NAME (orig));
return NULL;
}
for (i = 0; i < g_list_model_get_n_items (model); i++)
{
item = g_list_model_get_item (model, i);
g_object_unref (item);
if (GTK_IS_WIDGET (item))
model_name = gtk_widget_get_name (GTK_WIDGET (item));
else
model_name = gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (item));
if (strcmp (name, model_name) == 0)
return GTK_CONSTRAINT_TARGET (item);
}
g_warning ("Failed to find target '%s'", name);
return NULL;
}
gboolean
constraint_editor_window_load (ConstraintEditorWindow *self,
GFile *file)
{
char *path;
GtkBuilder *builder;
GError *error = NULL;
GtkWidget *view;
GtkLayoutManager *layout;
GtkWidget *child;
const char *name;
gpointer item;
int i;
GListModel *list;
path = g_file_get_path (file);
builder = gtk_builder_new ();
if (!gtk_builder_add_from_file (builder, path, &error))
{
g_print ("Could not load %s: %s", path, error->message);
g_error_free (error);
g_free (path);
g_object_unref (builder);
return FALSE;
}
view = GTK_WIDGET (gtk_builder_get_object (builder, "view"));
if (!GTK_IS_BOX (view))
{
g_print ("Could not load %s: No GtkBox named 'view'", path);
g_free (path);
g_object_unref (builder);
return FALSE;
}
layout = gtk_widget_get_layout_manager (view);
if (!GTK_IS_CONSTRAINT_LAYOUT (layout))
{
g_print ("Could not load %s: Widget 'view' does not use GtkConstraintLayout", path);
g_free (path);
g_object_unref (builder);
return FALSE;
}
for (child = gtk_widget_get_first_child (view);
child;
child = gtk_widget_get_next_sibling (child))
{
if (!GTK_IS_LABEL (child))
{
g_print ("Skipping non-GtkLabel child\n");
continue;
}
name = gtk_label_get_label (GTK_LABEL (child));
constraint_view_add_child (CONSTRAINT_VIEW (self->view), name);
}
list = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (layout));
for (i = 0; i < g_list_model_get_n_items (list); i++)
{
GtkConstraintGuide *guide, *clone;
int w, h;
item = g_list_model_get_item (list, i);
guide = GTK_CONSTRAINT_GUIDE (item);
/* need to clone here, to attach to the right targets */
clone = gtk_constraint_guide_new ();
gtk_constraint_guide_set_name (clone, gtk_constraint_guide_get_name (guide));
gtk_constraint_guide_set_strength (clone, gtk_constraint_guide_get_strength (guide));
gtk_constraint_guide_get_min_size (guide, &w, &h);
gtk_constraint_guide_set_min_size (clone, w, h);
gtk_constraint_guide_get_nat_size (guide, &w, &h);
gtk_constraint_guide_set_nat_size (clone, w, h);
gtk_constraint_guide_get_max_size (guide, &w, &h);
gtk_constraint_guide_set_max_size (clone, w, h);
constraint_view_add_guide (CONSTRAINT_VIEW (self->view), clone);
g_object_unref (guide);
g_object_unref (clone);
}
g_object_unref (list);
list = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (layout));
for (i = 0; i < g_list_model_get_n_items (list); i++)
{
GtkConstraint *constraint;
GtkConstraint *clone;
GtkConstraintTarget *target;
GtkConstraintTarget *source;
GtkConstraintAttribute source_attr;
item = g_list_model_get_item (list, i);
constraint = GTK_CONSTRAINT (item);
target = gtk_constraint_get_target (constraint);
source = gtk_constraint_get_source (constraint);
source_attr = gtk_constraint_get_source_attribute (constraint);
if (source == NULL && source_attr == GTK_CONSTRAINT_ATTRIBUTE_NONE)
clone = gtk_constraint_new_constant (find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), target),
gtk_constraint_get_target_attribute (constraint),
gtk_constraint_get_relation (constraint),
gtk_constraint_get_constant (constraint),
gtk_constraint_get_strength (constraint));
else
clone = gtk_constraint_new (find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), target),
gtk_constraint_get_target_attribute (constraint),
gtk_constraint_get_relation (constraint),
find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), source),
source_attr,
gtk_constraint_get_multiplier (constraint),
gtk_constraint_get_constant (constraint),
gtk_constraint_get_strength (constraint));
constraint_view_add_constraint (CONSTRAINT_VIEW (self->view), clone);
g_object_unref (constraint);
g_object_unref (clone);
}
g_object_unref (list);
g_free (path);
g_object_unref (builder);
return TRUE;
}
static void
open_response_cb (GObject *source,
GAsyncResult *result,
void *user_data)
{
GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
ConstraintEditorWindow *self = user_data;
GFile *file;
file = gtk_file_dialog_open_finish (dialog, result, NULL);
if (file)
{
constraint_editor_window_load (self, file);
g_object_unref (file);
}
}
static void
open_cb (GtkWidget *button,
ConstraintEditorWindow *self)
{
GtkFileDialog *dialog;
GFile *cwd;
dialog = gtk_file_dialog_new ();
gtk_file_dialog_set_title (dialog, "Open file");
cwd = g_file_new_for_path (".");
gtk_file_dialog_set_initial_folder (dialog, cwd);
g_object_unref (cwd);
gtk_file_dialog_open (dialog, GTK_WINDOW (self), NULL, open_response_cb, self);
g_object_unref (dialog);
}
static void
serialize_child (GString *str,
int indent,
GtkWidget *child)
{
const char *name;
name = gtk_widget_get_name (child);
g_string_append_printf (str, "%*s<child>\n", indent, "");
g_string_append_printf (str, "%*s <object class=\"GtkLabel\" id=\"%s\">\n", indent, "", name);
g_string_append_printf (str, "%*s <property name=\"label\">%s</property>\n", indent, "", name);
g_string_append_printf (str, "%*s </object>\n", indent, "");
g_string_append_printf (str, "%*s</child>\n", indent, "");
}
static char *
serialize_model (GListModel *list)
{
GString *str = g_string_new ("");
int i;
g_string_append (str, "<interface>\n");
g_string_append (str, " <object class=\"GtkBox\" id=\"view\">\n");
g_string_append (str, " <property name=\"layout-manager\">\n");
g_string_append (str, " <object class=\"GtkConstraintLayout\">\n");
g_string_append (str, " <constraints>\n");
for (i = 0; i < g_list_model_get_n_items (list); i++)
{
gpointer item = g_list_model_get_item (list, i);
g_object_unref (item);
if (GTK_IS_CONSTRAINT (item))
constraint_editor_serialize_constraint (str, 10, GTK_CONSTRAINT (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
guide_editor_serialize_guide (str, 10, GTK_CONSTRAINT_GUIDE (item));
}
g_string_append (str, " </constraints>\n");
g_string_append (str, " </object>\n");
g_string_append (str, " </property>\n");
for (i = 0; i < g_list_model_get_n_items (list); i++)
{
gpointer item = g_list_model_get_item (list, i);
g_object_unref (item);
if (GTK_IS_WIDGET (item))
serialize_child (str, 4, GTK_WIDGET (item));
}
g_string_append (str, " </object>\n");
g_string_append (str, "</interface>\n");
return g_string_free (str, FALSE);
}
static void
save_response_cb (GObject *source,
GAsyncResult *result,
void *user_data)
{
GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
ConstraintEditorWindow *self = user_data;
GFile *file;
file = gtk_file_dialog_save_finish (dialog, result, NULL);
if (file)
{
GListModel *model;
char *text;
GError *error = NULL;
model = constraint_view_get_model (CONSTRAINT_VIEW (self->view));
text = serialize_model (model);
g_file_replace_contents (file, text, strlen (text),
NULL, FALSE,
G_FILE_CREATE_NONE,
NULL,
NULL,
&error);
if (error != NULL)
{
GtkAlertDialog *alert;
alert = gtk_alert_dialog_new ("Saving failed");
gtk_alert_dialog_set_detail (alert, error->message);
gtk_alert_dialog_show (alert,
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))));
g_object_unref (alert);
g_error_free (error);
}
g_free (text);
g_object_unref (file);
}
}
static void
save_cb (GtkWidget *button,
ConstraintEditorWindow *self)
{
GtkFileDialog *dialog;
GFile *cwd;
dialog = gtk_file_dialog_new ();
gtk_file_dialog_set_title (dialog, "Save constraints");
cwd = g_file_new_for_path (".");
gtk_file_dialog_set_initial_folder (dialog, cwd);
g_object_unref (cwd);
gtk_file_dialog_save (dialog,
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
NULL,
save_response_cb, self);
g_object_unref (dialog);
}
static void
constraint_editor_window_dispose (GObject *object)
{
gtk_widget_dispose_template (GTK_WIDGET (object), CONSTRAINT_EDITOR_WINDOW_TYPE);
G_OBJECT_CLASS (constraint_editor_window_parent_class)->dispose (object);
}
static int child_counter;
static int guide_counter;
static void
add_child (ConstraintEditorWindow *win)
{
char *name;
child_counter++;
name = g_strdup_printf ("Child %d", child_counter);
constraint_view_add_child (CONSTRAINT_VIEW (win->view), name);
g_free (name);
}
static void
add_guide (ConstraintEditorWindow *win)
{
char *name;
GtkConstraintGuide *guide;
guide_counter++;
name = g_strdup_printf ("Guide %d", guide_counter);
guide = gtk_constraint_guide_new ();
gtk_constraint_guide_set_name (guide, name);
g_free (name);
constraint_view_add_guide (CONSTRAINT_VIEW (win->view), guide);
}
static void
constraint_editor_done (ConstraintEditor *editor,
GtkConstraint *constraint,
ConstraintEditorWindow *win)
{
GtkConstraint *old_constraint;
g_object_get (editor, "constraint", &old_constraint, NULL);
if (old_constraint)
constraint_view_remove_constraint (CONSTRAINT_VIEW (win->view), old_constraint);
constraint_view_add_constraint (CONSTRAINT_VIEW (win->view), constraint);
g_clear_object (&old_constraint);
gtk_window_destroy (GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW)));
}
static void
edit_constraint (ConstraintEditorWindow *win,
GtkConstraint *constraint)
{
GtkWidget *window;
ConstraintEditor *editor;
GListModel *model;
window = gtk_window_new ();
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
if (constraint)
gtk_window_set_title (GTK_WINDOW (window), "Edit Constraint");
else
gtk_window_set_title (GTK_WINDOW (window), "Create Constraint");
model = constraint_view_get_model (CONSTRAINT_VIEW (win->view));
editor = constraint_editor_new (model, constraint);
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (editor));
g_signal_connect (editor, "done", G_CALLBACK (constraint_editor_done), win);
gtk_window_present (GTK_WINDOW (window));
}
static void
add_constraint (ConstraintEditorWindow *win)
{
edit_constraint (win, NULL);
}
static void
guide_editor_done (GuideEditor *editor,
GtkConstraintGuide *guide,
ConstraintEditorWindow *win)
{
gtk_window_destroy (GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW)));
}
static void
edit_guide (ConstraintEditorWindow *win,
GtkConstraintGuide *guide)
{
GtkWidget *window;
GuideEditor *editor;
window = gtk_window_new ();
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
gtk_window_set_title (GTK_WINDOW (window), "Edit Guide");
editor = guide_editor_new (guide);
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (editor));
g_signal_connect (editor, "done", G_CALLBACK (guide_editor_done), win);
gtk_window_present (GTK_WINDOW (window));
}
static void
row_activated (GtkListBox *list,
GtkListBoxRow *row,
ConstraintEditorWindow *win)
{
GObject *item;
item = G_OBJECT (g_object_get_data (G_OBJECT (row), "item"));
if (GTK_IS_CONSTRAINT (item))
edit_constraint (win, GTK_CONSTRAINT (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
edit_guide (win, GTK_CONSTRAINT_GUIDE (item));
}
static void
constraint_editor_window_class_init (ConstraintEditorWindowClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
g_type_ensure (CONSTRAINT_VIEW_TYPE);
object_class->dispose = constraint_editor_window_dispose;
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gtk/gtk4/constraint-editor/constraint-editor-window.ui");
gtk_widget_class_bind_template_child (widget_class, ConstraintEditorWindow, paned);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditorWindow, view);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditorWindow, list);
gtk_widget_class_bind_template_callback (widget_class, open_cb);
gtk_widget_class_bind_template_callback (widget_class, save_cb);
gtk_widget_class_bind_template_callback (widget_class, add_child);
gtk_widget_class_bind_template_callback (widget_class, add_guide);
gtk_widget_class_bind_template_callback (widget_class, add_constraint);
gtk_widget_class_bind_template_callback (widget_class, row_activated);
}
static void
row_edit (GtkButton *button,
ConstraintEditorWindow *win)
{
GtkWidget *row;
GObject *item;
row = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_LIST_BOX_ROW);
item = (GObject *)g_object_get_data (G_OBJECT (row), "item");
if (GTK_IS_CONSTRAINT (item))
edit_constraint (win, GTK_CONSTRAINT (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
edit_guide (win, GTK_CONSTRAINT_GUIDE (item));
}
static void
mark_constraints_invalid (ConstraintEditorWindow *win,
gpointer removed)
{
GtkWidget *child;
GObject *item;
for (child = gtk_widget_get_first_child (win->list);
child;
child = gtk_widget_get_next_sibling (child))
{
item = (GObject *)g_object_get_data (G_OBJECT (child), "item");
if (GTK_IS_CONSTRAINT (item))
{
GtkConstraint *constraint = GTK_CONSTRAINT (item);
if (gtk_constraint_get_target (constraint) == (GtkConstraintTarget *)removed ||
gtk_constraint_get_source (constraint) == (GtkConstraintTarget *)removed)
{
GtkWidget *button;
button = (GtkWidget *)g_object_get_data (G_OBJECT (child), "edit");
gtk_button_set_icon_name (GTK_BUTTON (button), "dialog-warning-symbolic");
gtk_widget_set_tooltip_text (button, "Constraint is invalid");
}
}
}
}
static void
row_delete (GtkButton *button,
ConstraintEditorWindow *win)
{
GtkWidget *row;
GObject *item;
row = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_LIST_BOX_ROW);
item = (GObject *)g_object_get_data (G_OBJECT (row), "item");
if (GTK_IS_CONSTRAINT (item))
constraint_view_remove_constraint (CONSTRAINT_VIEW (win->view),
GTK_CONSTRAINT (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
{
mark_constraints_invalid (win, item);
constraint_view_remove_guide (CONSTRAINT_VIEW (win->view),
GTK_CONSTRAINT_GUIDE (item));
}
else if (GTK_IS_WIDGET (item))
{
mark_constraints_invalid (win, item);
constraint_view_remove_child (CONSTRAINT_VIEW (win->view),
GTK_WIDGET (item));
}
}
static GtkWidget *
create_widget_func (gpointer item,
gpointer user_data)
{
ConstraintEditorWindow *win = user_data;
const char *name;
char *freeme = NULL;
GtkWidget *row, *box, *label, *button;
if (GTK_IS_WIDGET (item))
name = gtk_widget_get_name (GTK_WIDGET (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
name = gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (item));
else if (GTK_IS_CONSTRAINT (item))
name = freeme = constraint_editor_constraint_to_string (GTK_CONSTRAINT (item));
else
name = "";
row = gtk_list_box_row_new ();
g_object_set_data_full (G_OBJECT (row), "item", g_object_ref (item), g_object_unref);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
label = gtk_label_new (name);
if (GTK_IS_WIDGET (item) || GTK_IS_CONSTRAINT_GUIDE (item))
g_object_bind_property (item, "name",
label, "label",
G_BINDING_DEFAULT);
gtk_widget_set_margin_start (label, 10);
gtk_widget_set_margin_end (label, 10);
gtk_widget_set_margin_top (label, 10);
gtk_widget_set_margin_bottom (label, 10);
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_widget_set_hexpand (label, TRUE);
gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), box);
gtk_box_append (GTK_BOX (box), label);
if (GTK_IS_CONSTRAINT (item) || GTK_IS_CONSTRAINT_GUIDE (item))
{
button = gtk_button_new_from_icon_name ("document-edit-symbolic");
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
g_signal_connect (button, "clicked", G_CALLBACK (row_edit), win);
g_object_set_data (G_OBJECT (row), "edit", button);
gtk_box_append (GTK_BOX (box), button);
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
gtk_box_append (GTK_BOX (box), button);
}
else if (GTK_IS_WIDGET (item))
{
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
gtk_box_append (GTK_BOX (box), button);
}
g_free (freeme);
return row;
}
static void
constraint_editor_window_init (ConstraintEditorWindow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
gtk_list_box_bind_model (GTK_LIST_BOX (self->list),
constraint_view_get_model (CONSTRAINT_VIEW (self->view)),
create_widget_func,
self,
NULL);
}
ConstraintEditorWindow *
constraint_editor_window_new (ConstraintEditorApplication *application)
{
return g_object_new (CONSTRAINT_EDITOR_WINDOW_TYPE,
"application", application,
NULL);
}

View File

@@ -1,34 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#include "constraint-editor-application.h"
#define CONSTRAINT_EDITOR_WINDOW_TYPE (constraint_editor_window_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintEditorWindow, constraint_editor_window, CONSTRAINT, EDITOR_WINDOW, GtkApplicationWindow)
ConstraintEditorWindow * constraint_editor_window_new (ConstraintEditorApplication *application);
gboolean constraint_editor_window_load (ConstraintEditorWindow *self,
GFile *file);

View File

@@ -1,77 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ConstraintEditorWindow" parent="GtkApplicationWindow">
<property name="title" translatable="yes">GTK Constraint Editor</property>
<property name="default-width">1024</property>
<property name="default-height">768</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<child type="start">
<object class="GtkButton">
<property name="icon-name">document-open-symbolic</property>
<property name="tooltip-text">Open ui file</property>
<signal name="clicked" handler="open_cb"/>
</object>
</child>
<child type="start">
<object class="GtkButton">
<property name="icon-name">document-save-symbolic</property>
<property name="tooltip-text">Save to ui file</property>
<signal name="clicked" handler="save_cb"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkPaned" id="paned">
<property name="orientation">horizontal</property>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<child>
<object class="GtkButton">
<property name="label">Add Child</property>
<signal name="clicked" handler="add_child" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label">Add Guide</property>
<signal name="clicked" handler="add_guide" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label">Add Constraint</property>
<signal name="clicked" handler="add_constraint" swapped="yes"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="vscrollbar-policy">automatic</property>
<property name="vexpand">1</property>
<child>
<object class="GtkListBox" id="list">
<property name="show-separators">1</property>
<property name="selection-mode">none</property>
<signal name="row-activated" handler="row_activated"/>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="ConstraintView" id="view">
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,716 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "config.h"
#include "constraint-editor.h"
#include "constraint-view.h"
struct _ConstraintEditor
{
GtkWidget parent_instance;
GtkWidget *grid;
GtkWidget *target;
GtkWidget *target_attr;
GtkWidget *relation;
GtkWidget *source;
GtkWidget *source_attr;
GtkWidget *multiplier;
GtkWidget *constant;
GtkWidget *strength;
GtkWidget *preview;
GtkWidget *button;
GtkConstraint *constraint;
GListModel *model;
gboolean constructed;
};
enum {
PROP_MODEL = 1,
PROP_CONSTRAINT,
LAST_PROP
};
static GParamSpec *pspecs[LAST_PROP];
enum {
DONE,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE(ConstraintEditor, constraint_editor, GTK_TYPE_WIDGET);
static const char *
get_target_name (GtkConstraintTarget *target)
{
if (target == NULL)
return "Super";
else if (GTK_IS_WIDGET (target))
return gtk_widget_get_name (GTK_WIDGET (target));
else if (GTK_IS_CONSTRAINT_GUIDE (target))
return gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (target));
else
return "";
}
static void
constraint_target_combo (GListModel *model,
GtkWidget *combo,
gboolean is_source)
{
GtkStringList *targets;
int i;
targets = gtk_string_list_new (NULL);
gtk_string_list_append (targets, "Super");
if (model)
{
for (i = 0; i < g_list_model_get_n_items (model); i++)
{
GObject *item = g_list_model_get_object (model, i);
if (GTK_IS_CONSTRAINT (item))
continue;
gtk_string_list_append (targets, get_target_name (GTK_CONSTRAINT_TARGET (item)));
g_object_unref (item);
}
}
gtk_drop_down_set_model (GTK_DROP_DOWN (combo), G_LIST_MODEL (targets));
g_object_unref (targets);
}
static gpointer
get_target (GListModel *model,
const char *id)
{
int i;
if (id == NULL)
return NULL;
if (strcmp ("Super", id) == 0)
return NULL;
for (i = 0; i < g_list_model_get_n_items (model); i++)
{
GObject *item = g_list_model_get_object (model, i);
g_object_unref (item);
if (GTK_IS_CONSTRAINT (item))
continue;
else if (GTK_IS_WIDGET (item))
{
if (strcmp (id, gtk_widget_get_name (GTK_WIDGET (item))) == 0)
return item;
}
else if (GTK_IS_CONSTRAINT_GUIDE (item))
{
if (strcmp (id, gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (item))) == 0)
return item;
}
}
return NULL;
}
static void
select_target (GtkDropDown *combo,
const char *target_name)
{
GListModel *model = gtk_drop_down_get_model (combo);
for (unsigned int i = 0; i < g_list_model_get_n_items (model); i++)
{
GtkStringObject *s = g_list_model_get_item (model, i);
g_object_unref (s);
if (strcmp (target_name, gtk_string_object_get_string (s)) == 0)
{
gtk_drop_down_set_selected (GTK_DROP_DOWN (combo), i);
return;
}
}
}
static GtkConstraintAttribute
get_attr (unsigned int id)
{
switch (id)
{
case 0: return GTK_CONSTRAINT_ATTRIBUTE_NONE;
case 1: return GTK_CONSTRAINT_ATTRIBUTE_LEFT;
case 2: return GTK_CONSTRAINT_ATTRIBUTE_RIGHT;
case 3: return GTK_CONSTRAINT_ATTRIBUTE_TOP;
case 4: return GTK_CONSTRAINT_ATTRIBUTE_BOTTOM;
case 5: return GTK_CONSTRAINT_ATTRIBUTE_START;
case 6: return GTK_CONSTRAINT_ATTRIBUTE_END;
case 7: return GTK_CONSTRAINT_ATTRIBUTE_WIDTH;
case 8: return GTK_CONSTRAINT_ATTRIBUTE_HEIGHT;
case 9: return GTK_CONSTRAINT_ATTRIBUTE_CENTER_X;
case 10: return GTK_CONSTRAINT_ATTRIBUTE_CENTER_Y;
case 11: return GTK_CONSTRAINT_ATTRIBUTE_BASELINE;
default: g_assert_not_reached ();
}
}
static unsigned int
get_attr_id (GtkConstraintAttribute attr)
{
switch (attr)
{
case GTK_CONSTRAINT_ATTRIBUTE_NONE: return 0;
case GTK_CONSTRAINT_ATTRIBUTE_LEFT: return 1;
case GTK_CONSTRAINT_ATTRIBUTE_RIGHT: return 2;
case GTK_CONSTRAINT_ATTRIBUTE_TOP: return 3;
case GTK_CONSTRAINT_ATTRIBUTE_BOTTOM: return 4;
case GTK_CONSTRAINT_ATTRIBUTE_START: return 5;
case GTK_CONSTRAINT_ATTRIBUTE_END: return 6;
case GTK_CONSTRAINT_ATTRIBUTE_WIDTH: return 7;
case GTK_CONSTRAINT_ATTRIBUTE_HEIGHT: return 8;
case GTK_CONSTRAINT_ATTRIBUTE_CENTER_X: return 9;
case GTK_CONSTRAINT_ATTRIBUTE_CENTER_Y: return 10;
case GTK_CONSTRAINT_ATTRIBUTE_BASELINE: return 11;
default: g_assert_not_reached ();
}
}
static const char *
get_attr_nick (GtkConstraintAttribute attr)
{
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_ATTRIBUTE);
GEnumValue *value = g_enum_get_value (class, attr);
const char *nick = value->value_nick;
g_type_class_unref (class);
return nick;
}
static GtkConstraintRelation
get_relation (unsigned int id)
{
switch (id)
{
case 0: return GTK_CONSTRAINT_RELATION_LE;
case 1: return GTK_CONSTRAINT_RELATION_EQ;
case 2: return GTK_CONSTRAINT_RELATION_GE;
default: g_assert_not_reached ();
}
}
static unsigned int
get_relation_id (GtkConstraintRelation relation)
{
switch (relation)
{
case GTK_CONSTRAINT_RELATION_LE: return 0;
case GTK_CONSTRAINT_RELATION_EQ: return 1;
case GTK_CONSTRAINT_RELATION_GE: return 2;
default: g_assert_not_reached ();
}
}
static const char *
get_relation_nick (GtkConstraintRelation relation)
{
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_RELATION);
GEnumValue *value = g_enum_get_value (class, relation);
const char *nick = value->value_nick;
g_type_class_unref (class);
return nick;
}
static const char *
get_relation_display_name (GtkConstraintRelation relation)
{
switch (relation)
{
case GTK_CONSTRAINT_RELATION_LE:
return "";
case GTK_CONSTRAINT_RELATION_EQ:
return "=";
case GTK_CONSTRAINT_RELATION_GE:
return "";
default:
return "?";
}
}
static GtkConstraintStrength
get_strength (unsigned int id)
{
switch (id)
{
case 0: return GTK_CONSTRAINT_STRENGTH_WEAK;
case 1: return GTK_CONSTRAINT_STRENGTH_MEDIUM;
case 2: return GTK_CONSTRAINT_STRENGTH_STRONG;
case 3: return GTK_CONSTRAINT_STRENGTH_REQUIRED;
default: g_assert_not_reached ();
}
}
static unsigned int
get_strength_id (GtkConstraintStrength strength)
{
switch (strength)
{
case GTK_CONSTRAINT_STRENGTH_WEAK: return 0;
case GTK_CONSTRAINT_STRENGTH_MEDIUM: return 1;
case GTK_CONSTRAINT_STRENGTH_STRONG: return 2;
case GTK_CONSTRAINT_STRENGTH_REQUIRED: return 3;
default: g_assert_not_reached ();
}
}
static const char *
get_strength_nick (GtkConstraintStrength strength)
{
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
GEnumValue *value = g_enum_get_value (class, strength);
const char *nick = value->value_nick;
g_type_class_unref (class);
return nick;
}
void
constraint_editor_serialize_constraint (GString *str,
int indent,
GtkConstraint *constraint)
{
const char *target;
const char *target_attr;
const char *relation;
const char *source;
const char *source_attr;
double multiplier;
double constant;
const char *strength;
target = get_target_name (gtk_constraint_get_target (constraint));
target_attr = get_attr_nick (gtk_constraint_get_target_attribute (constraint));
relation = get_relation_nick (gtk_constraint_get_relation (constraint));
source = get_target_name (gtk_constraint_get_source (constraint));
source_attr = get_attr_nick (gtk_constraint_get_source_attribute (constraint));
multiplier = gtk_constraint_get_multiplier (constraint);
constant = gtk_constraint_get_constant (constraint);
strength = get_strength_nick (gtk_constraint_get_strength (constraint));
g_string_append_printf (str, "%*s<constraint target=\"%s\" target-attribute=\"%s\"\n", indent, "", target, target_attr);
g_string_append_printf (str, "%*s relation=\"%s\"\n", indent, "", relation);
if (strcmp (source_attr, "none") != 0)
{
g_string_append_printf (str, "%*s source=\"%s\" source-attribute=\"%s\"\n", indent, "", source, source_attr);
g_string_append_printf (str, "%*s multiplier=\"%g\"\n", indent, "", multiplier);
}
g_string_append_printf (str, "%*s constant=\"%g\"\n", indent, "", constant);
g_string_append_printf (str, "%*s strength=\"%s\" />\n", indent, "", strength);
}
static void
create_constraint (GtkButton *button,
ConstraintEditor *editor)
{
gpointer obj;
gpointer target;
GtkConstraintAttribute target_attr;
gpointer source;
GtkConstraintAttribute source_attr;
GtkConstraintRelation relation;
double multiplier;
double constant;
int strength;
GtkConstraint *constraint;
obj = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->target));
if (obj)
target = get_target (editor->model, gtk_string_object_get_string (GTK_STRING_OBJECT (obj)));
else
target = NULL;
target_attr = get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->target_attr)));
obj = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->source));
if (obj)
source = get_target (editor->model, gtk_string_object_get_string (GTK_STRING_OBJECT (obj)));
else
source = NULL;
source_attr = get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN(editor->source_attr)));
relation = get_relation (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->relation)));
multiplier = g_ascii_strtod (gtk_editable_get_text (GTK_EDITABLE (editor->multiplier)), NULL);
constant = g_ascii_strtod (gtk_editable_get_text (GTK_EDITABLE (editor->constant)), NULL);
strength = get_strength (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->strength)));
constraint = gtk_constraint_new (target, target_attr,
relation,
source, source_attr,
multiplier,
constant,
strength);
g_signal_emit (editor, signals[DONE], 0, constraint);
g_object_unref (constraint);
}
static void
source_attr_changed (ConstraintEditor *editor)
{
if (get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->source_attr))) == GTK_CONSTRAINT_ATTRIBUTE_NONE)
{
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->source), GTK_INVALID_LIST_POSITION);
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "");
gtk_widget_set_sensitive (editor->source, FALSE);
gtk_widget_set_sensitive (editor->multiplier, FALSE);
}
else
{
gtk_widget_set_sensitive (editor->source, TRUE);
gtk_widget_set_sensitive (editor->multiplier, TRUE);
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "1");
}
}
char *
constraint_editor_constraint_to_string (GtkConstraint *constraint)
{
GString *str;
const char *name;
const char *attr;
const char *relation;
double c, m;
str = g_string_new ("");
name = get_target_name (gtk_constraint_get_target (constraint));
attr = get_attr_nick (gtk_constraint_get_target_attribute (constraint));
relation = get_relation_display_name (gtk_constraint_get_relation (constraint));
if (name == NULL)
name = "[ ]";
g_string_append_printf (str, "%s.%s %s ", name, attr, relation);
c = gtk_constraint_get_constant (constraint);
attr = get_attr_nick (gtk_constraint_get_source_attribute (constraint));
if (strcmp (attr, "none") != 0)
{
name = get_target_name (gtk_constraint_get_source (constraint));
m = gtk_constraint_get_multiplier (constraint);
if (name == NULL)
name = "[ ]";
g_string_append_printf (str, "%s.%s", name, attr);
if (m != 1.0)
g_string_append_printf (str, " × %g", m);
if (c > 0.0)
g_string_append_printf (str, " + %g", c);
else if (c < 0.0)
g_string_append_printf (str, " - %g", -c);
}
else
g_string_append_printf (str, "%g", c);
return g_string_free (str, FALSE);
}
static void
update_preview (ConstraintEditor *editor)
{
GString *str;
const char *name;
const char *attr;
const char *relation;
const char *multiplier;
const char *constant;
double c, m;
if (!editor->constructed)
return;
str = g_string_new ("");
name = gtk_string_object_get_string (GTK_STRING_OBJECT (gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->target))));
attr = get_attr_nick (get_attr (gtk_drop_down_get_selected ((GTK_DROP_DOWN (editor->target_attr)))));
relation = get_relation_nick (get_relation (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->relation))));
if (name == NULL)
name = "[ ]";
g_string_append_printf (str, "%s.%s %s ", name, attr, relation);
constant = gtk_editable_get_text (GTK_EDITABLE (editor->constant));
c = g_ascii_strtod (constant, NULL);
attr = get_attr_nick (get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->source_attr))));
if (strcmp (attr, "none") != 0)
{
name = gtk_string_object_get_string (GTK_STRING_OBJECT (gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->source))));
multiplier = gtk_editable_get_text (GTK_EDITABLE (editor->multiplier));
m = g_ascii_strtod (multiplier, NULL);
if (name == NULL)
name = "[ ]";
g_string_append_printf (str, "%s.%s", name, attr);
if (m != 1.0)
g_string_append_printf (str, " × %g", m);
if (c > 0.0)
g_string_append_printf (str, " + %g", c);
else if (c < 0.0)
g_string_append_printf (str, " - %g", -c);
}
else
g_string_append_printf (str, "%g", c);
gtk_label_set_label (GTK_LABEL (editor->preview), str->str);
g_string_free (str, TRUE);
}
static void
update_button (ConstraintEditor *editor)
{
gpointer obj;
const char *target;
const char *source;
GtkConstraintAttribute source_attr = get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->source_attr)));
obj = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->target));
target = obj ? gtk_string_object_get_string (GTK_STRING_OBJECT (obj)) : NULL;
obj = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->source));
source = obj ? gtk_string_object_get_string (GTK_STRING_OBJECT (obj)) : NULL;
if (target && (source || (source_attr == GTK_CONSTRAINT_ATTRIBUTE_NONE)))
gtk_widget_set_sensitive (editor->button, TRUE);
else
gtk_widget_set_sensitive (editor->button, FALSE);
}
static void
constraint_editor_init (ConstraintEditor *editor)
{
gtk_widget_init_template (GTK_WIDGET (editor));
}
static void
constraint_editor_constructed (GObject *object)
{
ConstraintEditor *editor = CONSTRAINT_EDITOR (object);
constraint_target_combo (editor->model, editor->target, FALSE);
constraint_target_combo (editor->model, editor->source, TRUE);
if (editor->constraint)
{
GtkConstraintTarget *target;
GtkConstraintAttribute attr;
GtkConstraintRelation relation;
GtkConstraintStrength strength;
char *val;
double multiplier;
double constant;
target = gtk_constraint_get_target (editor->constraint);
select_target (GTK_DROP_DOWN (editor->target), get_target_name (target));
attr = gtk_constraint_get_target_attribute (editor->constraint);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->target_attr), get_attr_id (attr));
target = gtk_constraint_get_source (editor->constraint);
select_target (GTK_DROP_DOWN (editor->source), get_target_name (target));
attr = gtk_constraint_get_source_attribute (editor->constraint);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->source_attr), get_attr_id (attr));
relation = gtk_constraint_get_relation (editor->constraint);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->relation), get_relation_id (relation));
multiplier = gtk_constraint_get_multiplier (editor->constraint);
val = g_strdup_printf ("%g", multiplier);
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), val);
g_free (val);
constant = gtk_constraint_get_constant (editor->constraint);
val = g_strdup_printf ("%g", constant);
gtk_editable_set_text (GTK_EDITABLE (editor->constant), val);
g_free (val);
strength = gtk_constraint_get_strength (editor->constraint);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->strength), get_strength_id (strength));
gtk_button_set_label (GTK_BUTTON (editor->button), "Apply");
}
else
{
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->target_attr), get_attr_id (GTK_CONSTRAINT_ATTRIBUTE_LEFT));
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->source_attr), get_attr_id (GTK_CONSTRAINT_ATTRIBUTE_LEFT));
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->relation), get_relation_id (GTK_CONSTRAINT_RELATION_EQ));
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->strength), get_strength_id (GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "1.0");
gtk_editable_set_text (GTK_EDITABLE (editor->constant), "0.0");
gtk_button_set_label (GTK_BUTTON (editor->button), "Create");
}
editor->constructed = TRUE;
update_preview (editor);
update_button (editor);
}
static void
constraint_editor_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
ConstraintEditor *self = CONSTRAINT_EDITOR (object);
switch (property_id)
{
case PROP_MODEL:
self->model = g_value_dup_object (value);
break;
case PROP_CONSTRAINT:
self->constraint = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
constraint_editor_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
ConstraintEditor *self = CONSTRAINT_EDITOR (object);
switch (property_id)
{
case PROP_MODEL:
g_value_set_object (value, self->model);
break;
case PROP_CONSTRAINT:
g_value_set_object (value, self->constraint);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
constraint_editor_dispose (GObject *object)
{
ConstraintEditor *self = (ConstraintEditor *)object;
g_clear_object (&self->model);
g_clear_object (&self->constraint);
gtk_widget_dispose_template (GTK_WIDGET (object), CONSTRAINT_EDITOR_TYPE);
G_OBJECT_CLASS (constraint_editor_parent_class)->dispose (object);
}
static void
constraint_editor_class_init (ConstraintEditorClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->constructed = constraint_editor_constructed;
object_class->dispose = constraint_editor_dispose;
object_class->set_property = constraint_editor_set_property;
object_class->get_property = constraint_editor_get_property;
pspecs[PROP_CONSTRAINT] =
g_param_spec_object ("constraint", "constraint", "constraint",
GTK_TYPE_CONSTRAINT,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
pspecs[PROP_MODEL] =
g_param_spec_object ("model", "model", "model",
G_TYPE_LIST_MODEL,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, LAST_PROP, pspecs);
signals[DONE] =
g_signal_new ("done",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 1, GTK_TYPE_CONSTRAINT);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gtk/gtk4/constraint-editor/constraint-editor.ui");
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, grid);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, target);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, target_attr);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, relation);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, source);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, source_attr);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, multiplier);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, constant);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, strength);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, preview);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, button);
gtk_widget_class_bind_template_callback (widget_class, update_preview);
gtk_widget_class_bind_template_callback (widget_class, update_button);
gtk_widget_class_bind_template_callback (widget_class, create_constraint);
gtk_widget_class_bind_template_callback (widget_class, source_attr_changed);
}
ConstraintEditor *
constraint_editor_new (GListModel *model,
GtkConstraint *constraint)
{
return g_object_new (CONSTRAINT_EDITOR_TYPE,
"model", model,
"constraint", constraint,
NULL);
}

View File

@@ -1,12 +0,0 @@
constraintview {
background: black;
color: white;
}
constraintview .child {
background: red;
}
constraintview .guide {
background: blue;
}

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gtk/gtk4/constraint-editor">
<file preprocess="xml-stripblanks">constraint-editor-window.ui</file>
<file preprocess="xml-stripblanks">constraint-editor.ui</file>
<file preprocess="xml-stripblanks">guide-editor.ui</file>
<file>constraint-editor.css</file>
</gresource>
</gresources>

View File

@@ -1,34 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define CONSTRAINT_EDITOR_TYPE (constraint_editor_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintEditor, constraint_editor, CONSTRAINT, EDITOR, GtkWidget)
ConstraintEditor * constraint_editor_new (GListModel *model,
GtkConstraint *constraint);
void constraint_editor_serialize_constraint (GString *str,
int indent,
GtkConstraint *constraint);
char *constraint_editor_constraint_to_string (GtkConstraint *constraint);

View File

@@ -1,204 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkStringList" id="targets">
<items>
<item>None</item>
<item>Left</item>
<item>Right</item>
<item>Top</item>
<item>Bottom</item>
<item>Start</item>
<item>End</item>
<item>Width</item>
<item>Height</item>
<item>Center X</item>
<item>Center Y</item>
<item>Baseline</item>
</items>
</object>
<template class="ConstraintEditor" parent="GtkWidget">
<child>
<object class="GtkGrid" id="grid">
<property name="margin-start">20</property>
<property name="margin-end">20</property>
<property name="margin-top">20</property>
<property name="margin-bottom">20</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<child>
<object class="GtkLabel">
<property name="label">Target</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkDropDown" id="target">
<signal name="notify::selected" handler="update_preview" swapped="yes"/>
<signal name="notify::selected" handler="update_button" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkDropDown" id="target_attr">
<property name="model">targets</property>
<signal name="notify::selected" handler="update_preview" swapped="yes"/>
<layout>
<property name="column">2</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Relation</property>
<layout>
<property name="column">0</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkDropDown" id="relation">
<signal name="notify::selected" handler="update_preview" swapped="yes"/>
<property name="model">
<object class="GtkStringList">
<items>
<item>≤</item>
<item>=</item>
<item>≥</item>
</items>
</object>
</property>
<layout>
<property name="column">1</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Source</property>
<layout>
<property name="column">0</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkDropDown" id="source">
<signal name="notify::selected" handler="update_preview" swapped="yes"/>
<signal name="notify::selected" handler="update_button" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkDropDown" id="source_attr">
<property name="model">targets</property>
<signal name="notify::selected" handler="update_preview" swapped="yes"/>
<signal name="notify::selected" handler="source_attr_changed" swapped="yes"/>
<signal name="notify::selected" handler="update_button" swapped="yes"/>
<layout>
<property name="column">2</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Multiplier</property>
<layout>
<property name="column">0</property>
<property name="row">4</property>
</layout>
</object>
</child>
<child>
<object class="GtkEntry" id="multiplier">
<signal name="changed" handler="update_preview" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">4</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Constant</property>
<layout>
<property name="column">0</property>
<property name="row">5</property>
</layout>
</object>
</child>
<child>
<object class="GtkEntry" id="constant">
<signal name="changed" handler="update_preview" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">5</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Strength</property>
<layout>
<property name="column">0</property>
<property name="row">6</property>
</layout>
</object>
</child>
<child>
<object class="GtkDropDown" id="strength">
<property name="model">
<object class="GtkStringList">
<items>
<item>Weak</item>
<item>Medium</item>
<item>Strong</item>
<item>Required</item>
</items>
</object>
</property>
<layout>
<property name="column">1</property>
<property name="row">6</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel" id="preview">
<property name="xalign">0</property>
<layout>
<property name="column">1</property>
<property name="row">7</property>
<property name="column-span">2</property>
</layout>
<attributes>
<attribute name="scale" value="1.44"/>
</attributes>
</object>
</child>
<child>
<object class="GtkButton" id="button">
<property name="label">Create</property>
<signal name="clicked" handler="create_constraint"/>
<layout>
<property name="column">2</property>
<property name="row">8</property>
</layout>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,93 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "constraint-view-child.h"
struct _ConstraintViewChild
{
GObject parent_instance;
char *name;
};
enum {
PROP_NAME = 1,
LAST_PROP
};
static GParamSpec props[LAST_PROP];
G_DEFINE_TYPE (ConstraintViewChild, constraint_view_child, G_TYPE_OBJECT)
static void
constraint_view_child_init (ConstraintViewChild *child)
{
}
static void
constraint_view_child_finalize (GObject *object)
{
ConstraintViewChild *child = CONSTRAINT_VIEW_CHILD (object);
g_free (child->name);
G_OBJECT_CLASS (constraint_view_child_parent_class)->finalize (object);
}
static void
constraint_view_child_set_property (GObject *object,
static void
constraint_view_child_class_init (ConstraintViewChildClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->finalize = constraint_view_child_finalize;
object_class->get_property = constraint_view_child_get_property;
object_class->set_property = constraint_view_child_set_property;
props[PROP_NAME] =
g_param_spec_string ("name", "name", "name",
NULL,
G_PARAM_READWRITE);
g_object_class_install_properties (object_class, LAST_PROP, props);
}
#define CONSTRAINT_VIEW_CHILD_TYPE (constraint_view_get_type ())
G_DECLARE_TYPE (ConstraintViewChild, constraint_view_child, CONSTRAINT, VIEW_CHILD, GObject)
#define CONSTRAINT_VIEW_WIDGET_TYPE (constraint_view_widget_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewWidget, constraint_view_widget, CONSTRAINT, VIEW_WIDGET, ConstraintViewChild)
ConstraintViewWidget * constraint_view_widget_new (void);
#define CONSTRAINT_VIEW_GUIDE_TYPE (constraint_view_guide_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewGuide, constraint_view_guide, CONSTRAINT, VIEW_GUIDE, ConstraintViewChild)
ConstraintViewGuide * constraint_view_guide_new (void);
#define CONSTRAINT_VIEW_CONSTRAINT_TYPE (constraint_view_constraint_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewConstraint, constraint_view_constraint, CONSTRAINT, VIEW_CONSTRAINT, ConstraintViewChild)
ConstraintViewGuide * constraint_view_constraint_new (void);

View File

@@ -1,44 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define CONSTRAINT_VIEW_CHILD_TYPE (constraint_view_get_type ())
G_DECLARE_TYPE (ConstraintViewChild, constraint_view_child, CONSTRAINT, VIEW_CHILD, GObject)
#define CONSTRAINT_VIEW_WIDGET_TYPE (constraint_view_widget_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewWidget, constraint_view_widget, CONSTRAINT, VIEW_WIDGET, ConstraintViewChild)
ConstraintViewWidget * constraint_view_widget_new (void);
#define CONSTRAINT_VIEW_GUIDE_TYPE (constraint_view_guide_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewGuide, constraint_view_guide, CONSTRAINT, VIEW_GUIDE, ConstraintViewChild)
ConstraintViewGuide * constraint_view_guide_new (void);
#define CONSTRAINT_VIEW_CONSTRAINT_TYPE (constraint_view_constraint_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewConstraint, constraint_view_constraint, CONSTRAINT, VIEW_CONSTRAINT, ConstraintViewChild)
ConstraintViewGuide * constraint_view_constraint_new (void);

View File

@@ -1,345 +0,0 @@
/* Copyright (C) 2019 Red Hat, Inc.
*
* 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 <gtk/gtk.h>
#include "constraint-view.h"
struct _ConstraintView
{
GtkWidget parent;
GListModel *model;
GtkWidget *drag_widget;
};
G_DEFINE_TYPE (ConstraintView, constraint_view, GTK_TYPE_WIDGET);
static void
constraint_view_dispose (GObject *object)
{
ConstraintView *view = CONSTRAINT_VIEW (object);
GtkWidget *child;
while ((child = gtk_widget_get_first_child (GTK_WIDGET (view))) != NULL)
gtk_widget_unparent (child);
g_clear_object (&view->model);
G_OBJECT_CLASS (constraint_view_parent_class)->dispose (object);
}
static void
constraint_view_class_init (ConstraintViewClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = constraint_view_dispose;
gtk_widget_class_set_css_name (widget_class, "constraintview");
}
static void
update_weak_position (ConstraintView *self,
GtkWidget *child,
double x,
double y)
{
GtkLayoutManager *manager;
GtkConstraint *constraint;
manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
constraint = (GtkConstraint *)g_object_get_data (G_OBJECT (child), "x-constraint");
if (constraint)
{
gtk_constraint_layout_remove_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
g_object_set_data (G_OBJECT (child), "x-constraint", NULL);
}
if (x != -100)
{
constraint = gtk_constraint_new_constant (child,
GTK_CONSTRAINT_ATTRIBUTE_CENTER_X,
GTK_CONSTRAINT_RELATION_EQ,
x,
GTK_CONSTRAINT_STRENGTH_WEAK);
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
g_object_set_data (G_OBJECT (child), "x-constraint", constraint);
}
constraint = (GtkConstraint *)g_object_get_data (G_OBJECT (child), "y-constraint");
if (constraint)
{
gtk_constraint_layout_remove_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
g_object_set_data (G_OBJECT (child), "y-constraint", NULL);
}
if (y != -100)
{
constraint = gtk_constraint_new_constant (child,
GTK_CONSTRAINT_ATTRIBUTE_CENTER_Y,
GTK_CONSTRAINT_RELATION_EQ,
y,
GTK_CONSTRAINT_STRENGTH_WEAK);
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
g_object_set_data (G_OBJECT (child), "y-constraint", constraint);
}
}
static void
drag_begin (GtkGestureDrag *drag,
double start_x,
double start_y,
ConstraintView *self)
{
GtkWidget *widget;
widget = gtk_widget_pick (GTK_WIDGET (self), start_x, start_y, GTK_PICK_DEFAULT);
if (GTK_IS_LABEL (widget))
{
widget = gtk_widget_get_ancestor (widget, GTK_TYPE_FRAME);
if (widget &&
gtk_widget_get_parent (widget) == (GtkWidget *)self)
{
self->drag_widget = widget;
}
}
}
static void
drag_update (GtkGestureDrag *drag,
double offset_x,
double offset_y,
ConstraintView *self)
{
double x, y;
if (!self->drag_widget)
return;
gtk_gesture_drag_get_start_point (drag, &x, &y);
update_weak_position (self, self->drag_widget, x + offset_x, y + offset_y);
}
static void
drag_end (GtkGestureDrag *drag,
double offset_x,
double offset_y,
ConstraintView *self)
{
self->drag_widget = NULL;
}
static gboolean
omit_internal (gpointer item, gpointer user_data)
{
if (g_object_get_data (G_OBJECT (item), "internal"))
return FALSE;
return TRUE;
}
static void
constraint_view_init (ConstraintView *self)
{
GtkLayoutManager *manager;
GtkEventController *controller;
GListStore *list;
GListModel *all_children;
GListModel *all_constraints;
GListModel *guides;
GListModel *children;
GListModel *constraints;
GtkFilter *filter;
manager = gtk_constraint_layout_new ();
gtk_widget_set_layout_manager (GTK_WIDGET (self), manager);
guides = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (manager));
all_constraints = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (manager));
filter = GTK_FILTER (gtk_custom_filter_new (omit_internal, NULL, NULL));
constraints = (GListModel *)gtk_filter_list_model_new (all_constraints, filter);
all_children = gtk_widget_observe_children (GTK_WIDGET (self));
filter = GTK_FILTER (gtk_custom_filter_new (omit_internal, NULL, NULL));
children = (GListModel *)gtk_filter_list_model_new (all_children, filter);
list = g_list_store_new (G_TYPE_LIST_MODEL);
g_list_store_append (list, children);
g_list_store_append (list, guides);
g_list_store_append (list, constraints);
g_object_unref (children);
g_object_unref (guides);
g_object_unref (constraints);
self->model = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (list)));
controller = (GtkEventController *)gtk_gesture_drag_new ();
g_signal_connect (controller, "drag-begin", G_CALLBACK (drag_begin), self);
g_signal_connect (controller, "drag-update", G_CALLBACK (drag_update), self);
g_signal_connect (controller, "drag-end", G_CALLBACK (drag_end), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
}
ConstraintView *
constraint_view_new (void)
{
return g_object_new (CONSTRAINT_VIEW_TYPE, NULL);
}
void
constraint_view_add_child (ConstraintView *view,
const char *name)
{
GtkWidget *frame;
GtkWidget *label;
label = gtk_label_new (name);
frame = gtk_frame_new (NULL);
gtk_widget_add_css_class (frame, "child");
gtk_widget_set_name (frame, name);
gtk_frame_set_child (GTK_FRAME (frame), label);
gtk_widget_set_parent (frame, GTK_WIDGET (view));
update_weak_position (view, frame, 100, 100);
}
void
constraint_view_remove_child (ConstraintView *view,
GtkWidget *child)
{
update_weak_position (view, child, -100, -100);
gtk_widget_unparent (child);
}
void
constraint_view_add_guide (ConstraintView *view,
GtkConstraintGuide *guide)
{
GtkConstraintLayout *layout;
GtkWidget *frame;
GtkWidget *label;
const char *name;
GtkConstraint *constraint;
struct {
const char *name;
GtkConstraintAttribute attr;
} names[] = {
{ "left-constraint", GTK_CONSTRAINT_ATTRIBUTE_LEFT },
{ "top-constraint", GTK_CONSTRAINT_ATTRIBUTE_TOP },
{ "width-constraint", GTK_CONSTRAINT_ATTRIBUTE_WIDTH },
{ "height-constraint", GTK_CONSTRAINT_ATTRIBUTE_HEIGHT },
};
int i;
name = gtk_constraint_guide_get_name (guide);
label = gtk_label_new (name);
g_object_bind_property (guide, "name",
label, "label",
G_BINDING_DEFAULT);
frame = gtk_frame_new (NULL);
gtk_widget_add_css_class (frame, "guide");
g_object_set_data (G_OBJECT (frame), "internal", (char *)"yes");
gtk_frame_set_child (GTK_FRAME (frame), label);
gtk_widget_insert_after (frame, GTK_WIDGET (view), NULL);
g_object_set_data (G_OBJECT (guide), "frame", frame);
layout = GTK_CONSTRAINT_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (view)));
gtk_constraint_layout_add_guide (layout, g_object_ref (guide));
for (i = 0; i < G_N_ELEMENTS (names); i++)
{
constraint = gtk_constraint_new (frame,
names[i].attr,
GTK_CONSTRAINT_RELATION_EQ,
guide,
names[i].attr,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
gtk_constraint_layout_add_constraint (layout, constraint);
g_object_set_data (G_OBJECT (guide), names[i].name, constraint);
}
update_weak_position (view, frame, 150, 150);
}
void
constraint_view_remove_guide (ConstraintView *view,
GtkConstraintGuide *guide)
{
GtkConstraintLayout *layout;
GtkWidget *frame;
GtkConstraint *constraint;
const char *names[] = {
"left-constraint",
"top-constraint",
"width-constraint",
"height-constraint"
};
int i;
layout = GTK_CONSTRAINT_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (view)));
for (i = 0; i < G_N_ELEMENTS (names); i++)
{
constraint = (GtkConstraint*)g_object_get_data (G_OBJECT (guide), names[i]);
gtk_constraint_layout_remove_constraint (layout, constraint);
}
frame = (GtkWidget *)g_object_get_data (G_OBJECT (guide), "frame");
update_weak_position (view, frame, -100, -100);
gtk_widget_unparent (frame);
gtk_constraint_layout_remove_guide (layout, guide);
}
void
constraint_view_add_constraint (ConstraintView *view,
GtkConstraint *constraint)
{
GtkLayoutManager *manager;
manager = gtk_widget_get_layout_manager (GTK_WIDGET (view));
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
g_object_ref (constraint));
}
void
constraint_view_remove_constraint (ConstraintView *view,
GtkConstraint *constraint)
{
GtkLayoutManager *manager;
manager = gtk_widget_get_layout_manager (GTK_WIDGET (view));
gtk_constraint_layout_remove_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
}
GListModel *
constraint_view_get_model (ConstraintView *view)
{
return view->model;
}

View File

@@ -1,45 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define CONSTRAINT_VIEW_TYPE (constraint_view_get_type ())
G_MODULE_EXPORT
G_DECLARE_FINAL_TYPE (ConstraintView, constraint_view, CONSTRAINT, VIEW, GtkWidget)
ConstraintView * constraint_view_new (void);
void constraint_view_add_child (ConstraintView *view,
const char *name);
void constraint_view_remove_child (ConstraintView *view,
GtkWidget *child);
void constraint_view_add_guide (ConstraintView *view,
GtkConstraintGuide *guide);
void constraint_view_remove_guide (ConstraintView *view,
GtkConstraintGuide *guide);
void constraint_view_guide_changed (ConstraintView *view,
GtkConstraintGuide *guide);
void constraint_view_add_constraint (ConstraintView *view,
GtkConstraint *constraint);
void constraint_view_remove_constraint (ConstraintView *view,
GtkConstraint *constraint);
GListModel * constraint_view_get_model (ConstraintView *view);

View File

@@ -1,355 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "config.h"
#include "guide-editor.h"
struct _GuideEditor
{
GtkWidget parent_instance;
GtkWidget *grid;
GtkWidget *name;
GtkWidget *min_width;
GtkWidget *min_height;
GtkWidget *nat_width;
GtkWidget *nat_height;
GtkWidget *max_width;
GtkWidget *max_height;
GtkWidget *strength;
GtkWidget *button;
GtkConstraintGuide *guide;
gboolean constructed;
};
enum {
PROP_GUIDE = 1,
LAST_PROP
};
static GParamSpec *pspecs[LAST_PROP];
enum {
DONE,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE(GuideEditor, guide_editor, GTK_TYPE_WIDGET);
static GtkConstraintStrength
get_strength (unsigned int id)
{
switch (id)
{
case 0: return GTK_CONSTRAINT_STRENGTH_WEAK;
case 1: return GTK_CONSTRAINT_STRENGTH_MEDIUM;
case 2: return GTK_CONSTRAINT_STRENGTH_STRONG;
case 3: return GTK_CONSTRAINT_STRENGTH_REQUIRED;
default: g_assert_not_reached ();
}
}
static unsigned int
get_strength_id (GtkConstraintStrength strength)
{
switch (strength)
{
case GTK_CONSTRAINT_STRENGTH_WEAK: return 0;
case GTK_CONSTRAINT_STRENGTH_MEDIUM: return 1;
case GTK_CONSTRAINT_STRENGTH_STRONG: return 2;
case GTK_CONSTRAINT_STRENGTH_REQUIRED: return 3;
default: g_assert_not_reached ();
}
}
static const char *
get_strength_nick (GtkConstraintStrength strength)
{
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
GEnumValue *value = g_enum_get_value (class, strength);
const char *nick = value->value_nick;
g_type_class_unref (class);
return nick;
}
void
guide_editor_serialize_guide (GString *str,
int indent,
GtkConstraintGuide *guide)
{
int min_width, min_height;
int nat_width, nat_height;
int max_width, max_height;
const char *name;
const char *strength;
gtk_constraint_guide_get_min_size (guide, &min_width, &min_height);
gtk_constraint_guide_get_nat_size (guide, &nat_width, &nat_height);
gtk_constraint_guide_get_max_size (guide, &max_width, &max_height);
name = gtk_constraint_guide_get_name (guide);
strength = get_strength_nick (gtk_constraint_guide_get_strength (guide));
g_string_append_printf (str, "%*s<guide min-width=\"%d\" min-height=\"%d\"\n", indent, "", min_width, min_height);
g_string_append_printf (str, "%*s nat-width=\"%d\" nat-height=\"%d\"\n", indent, "", nat_width, nat_height);
g_string_append_printf (str, "%*s max-width=\"%d\" max-height=\"%d\"\n", indent, "", max_width, max_height);
g_string_append_printf (str, "%*s name=\"%s\" strength=\"%s\" />\n", indent, "", name, strength);
}
static void
create_guide (GtkButton *button,
GuideEditor *editor)
{
int strength;
const char *name;
int w, h;
GtkConstraintGuide *guide;
unsigned int id;
if (editor->guide)
guide = g_object_ref (editor->guide);
else
guide = gtk_constraint_guide_new ();
name = gtk_editable_get_text (GTK_EDITABLE (editor->name));
gtk_constraint_guide_set_name (guide, name);
w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->min_width));
h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->min_height));
gtk_constraint_guide_set_min_size (guide, w, h);
w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->nat_width));
h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->nat_height));
gtk_constraint_guide_set_nat_size (guide, w, h);
w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->max_width));
h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->max_height));
gtk_constraint_guide_set_max_size (guide, w, h);
id = gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->strength));
strength = get_strength (id);
gtk_constraint_guide_set_strength (guide, strength);
g_signal_emit (editor, signals[DONE], 0, guide);
g_object_unref (guide);
}
static void
guide_editor_init (GuideEditor *editor)
{
gtk_widget_init_template (GTK_WIDGET (editor));
}
static int guide_counter;
static int
min_input (GtkSpinButton *spin_button,
double *new_val)
{
if (strcmp (gtk_editable_get_text (GTK_EDITABLE (spin_button)), "") == 0)
{
*new_val = 0.0;
return TRUE;
}
return FALSE;
}
static int
max_input (GtkSpinButton *spin_button,
double *new_val)
{
if (strcmp (gtk_editable_get_text (GTK_EDITABLE (spin_button)), "") == 0)
{
*new_val = G_MAXINT;
return TRUE;
}
return FALSE;
}
static void
guide_editor_constructed (GObject *object)
{
GuideEditor *editor = GUIDE_EDITOR (object);
g_signal_connect (editor->min_width, "input", G_CALLBACK (min_input), NULL);
g_signal_connect (editor->min_height, "input", G_CALLBACK (min_input), NULL);
g_signal_connect (editor->max_width, "input", G_CALLBACK (max_input), NULL);
g_signal_connect (editor->max_height, "input", G_CALLBACK (max_input), NULL);
if (editor->guide)
{
GtkConstraintStrength strength;
const char *nick;
int w, h;
nick = gtk_constraint_guide_get_name (editor->guide);
if (nick)
gtk_editable_set_text (GTK_EDITABLE (editor->name), nick);
gtk_constraint_guide_get_min_size (editor->guide, &w, &h);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_width), w);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_height), h);
gtk_constraint_guide_get_nat_size (editor->guide, &w, &h);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_width), w);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_height), h);
gtk_constraint_guide_get_max_size (editor->guide, &w, &h);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_width), w);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_height), h);
strength = gtk_constraint_guide_get_strength (editor->guide);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->strength), get_strength_id (strength));
gtk_button_set_label (GTK_BUTTON (editor->button), "Apply");
}
else
{
char *name;
guide_counter++;
name = g_strdup_printf ("Guide %d", guide_counter);
gtk_editable_set_text (GTK_EDITABLE (editor->name), name);
g_free (name);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_width), 0.0);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_height), 0.0);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_width), 0.0);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_height), 0.0);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_width), G_MAXINT);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_height), G_MAXINT);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->strength), get_strength_id (GTK_CONSTRAINT_STRENGTH_MEDIUM));
gtk_button_set_label (GTK_BUTTON (editor->button), "Create");
}
editor->constructed = TRUE;
}
static void
guide_editor_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GuideEditor *self = GUIDE_EDITOR (object);
switch (property_id)
{
case PROP_GUIDE:
self->guide = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
guide_editor_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GuideEditor *self = GUIDE_EDITOR (object);
switch (property_id)
{
case PROP_GUIDE:
g_value_set_object (value, self->guide);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
guide_editor_dispose (GObject *object)
{
GuideEditor *self = (GuideEditor *)object;
g_clear_object (&self->guide);
gtk_widget_dispose_template (GTK_WIDGET (self), GUIDE_EDITOR_TYPE);
G_OBJECT_CLASS (guide_editor_parent_class)->dispose (object);
}
static void
guide_editor_class_init (GuideEditorClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->constructed = guide_editor_constructed;
object_class->dispose = guide_editor_dispose;
object_class->set_property = guide_editor_set_property;
object_class->get_property = guide_editor_get_property;
pspecs[PROP_GUIDE] =
g_param_spec_object ("guide", "guide", "guide",
GTK_TYPE_CONSTRAINT_GUIDE,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, LAST_PROP, pspecs);
signals[DONE] =
g_signal_new ("done",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 1, GTK_TYPE_CONSTRAINT_GUIDE);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gtk/gtk4/constraint-editor/guide-editor.ui");
gtk_widget_class_bind_template_child (widget_class, GuideEditor, grid);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, name);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, min_width);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, min_height);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, nat_width);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, nat_height);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, max_width);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, max_height);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, strength);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, button);
gtk_widget_class_bind_template_callback (widget_class, create_guide);
}
GuideEditor *
guide_editor_new (GtkConstraintGuide *guide)
{
return g_object_new (GUIDE_EDITOR_TYPE,
"guide", guide,
NULL);
}

View File

@@ -1,32 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define GUIDE_EDITOR_TYPE (guide_editor_get_type ())
G_DECLARE_FINAL_TYPE (GuideEditor, guide_editor, GUIDE, EDITOR, GtkWidget)
GuideEditor * guide_editor_new (GtkConstraintGuide *guide);
void guide_editor_serialize_guide (GString *str,
int indent,
GtkConstraintGuide *guide);

View File

@@ -1,201 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkAdjustment" id="min_width_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<object class="GtkAdjustment" id="min_height_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<object class="GtkAdjustment" id="nat_width_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<object class="GtkAdjustment" id="nat_height_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<object class="GtkAdjustment" id="max_width_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<object class="GtkAdjustment" id="max_height_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<template class="GuideEditor" parent="GtkWidget">
<child>
<object class="GtkGrid" id="grid">
<property name="margin-start">20</property>
<property name="margin-end">20</property>
<property name="margin-top">20</property>
<property name="margin-bottom">20</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<child>
<object class="GtkLabel">
<property name="label">Name</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkEntry" id="name">
<property name="max-width-chars">20</property>
<layout>
<property name="column">1</property>
<property name="row">0</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Min Size</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="min_width">
<property name="adjustment">min_width_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">1</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="min_height">
<property name="adjustment">min_height_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">2</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Nat Size</property>
<layout>
<property name="column">0</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="nat_width">
<property name="adjustment">nat_width_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">1</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="nat_height">
<property name="adjustment">nat_height_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">2</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Max Size</property>
<layout>
<property name="column">0</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="max_width">
<property name="adjustment">max_width_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">1</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="max_height">
<property name="adjustment">max_height_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">2</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Strength</property>
<layout>
<property name="column">0</property>
<property name="row">4</property>
</layout>
</object>
</child>
<child>
<object class="GtkDropDown" id="strength">
<property name="model">
<object class="GtkStringList">
<items>
<item>Weak</item>
<item>Medium</item>
<item>Strong</item>
<item>Required</item>
</items>
</object>
</property>
<layout>
<property name="column">1</property>
<property name="row">4</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkButton" id="button">
<property name="label">Create</property>
<signal name="clicked" handler="create_guide"/>
<layout>
<property name="column">2</property>
<property name="row">5</property>
</layout>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,28 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include <constraint-editor-application.h>
int
main (int argc, char *argv[])
{
return g_application_run (G_APPLICATION (constraint_editor_application_new ()), argc, argv);
}

View File

@@ -1,23 +0,0 @@
constraint_editor_sources = [
'main.c',
'constraint-editor-application.c',
'constraint-editor-window.c',
'constraint-view.c',
'constraint-editor.c',
'guide-editor.c',
]
constraint_editor_resources = gnome.compile_resources('constraint_editor_resources',
'constraint-editor.gresource.xml',
source_dir: meson.current_source_dir(),
)
executable('gtk4-constraint-editor',
sources: [ constraint_editor_sources, constraint_editor_resources, ],
c_args: common_cflags,
dependencies: libgtk_dep,
include_directories: confinc,
win_subsystem: 'windows',
link_args: extra_demo_ldflags,
install: false,
)

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.2 KiB

View File

@@ -1,136 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="org.gtk.IconBrowser4-symbolic.svg"
height="16.03125"
id="svg7384"
inkscape:version="0.92.4 5da689c313, 2019-01-14"
version="1.1"
width="16">
<metadata
id="metadata90">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Gnome Symbolic Icon Theme</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
inkscape:bbox-paths="true"
bordercolor="#666666"
borderopacity="1"
inkscape:current-layer="layer9"
inkscape:cx="-2.5662459"
inkscape:cy="11.558672"
gridtolerance="10"
inkscape:guide-bbox="true"
guidetolerance="10"
id="namedview88"
inkscape:object-nodes="false"
inkscape:object-paths="false"
objecttolerance="10"
pagecolor="#555753"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
showborder="true"
showgrid="false"
showguides="true"
inkscape:snap-bbox="true"
inkscape:snap-bbox-midpoints="false"
inkscape:snap-global="true"
inkscape:snap-grids="true"
inkscape:snap-nodes="true"
inkscape:snap-others="false"
inkscape:snap-to-guides="true"
inkscape:window-height="1375"
inkscape:window-maximized="1"
inkscape:window-width="2560"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:zoom="1">
<inkscape:grid
empspacing="2"
enabled="true"
id="grid4866"
originx="-203"
originy="-251.96875"
snapvisiblegridlinesonly="true"
spacingx="1"
spacingy="1"
type="xygrid"
visible="true" />
</sodipodi:namedview>
<title
id="title9167">Gnome Symbolic Icon Theme</title>
<defs
id="defs7386">
<linearGradient
id="linearGradient7212"
osb:paint="solid">
<stop
id="stop7214"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
</linearGradient>
</defs>
<g
inkscape:groupmode="layer"
id="layer9"
inkscape:label="apps"
style="display:inline"
transform="translate(-444.0002,35)">
<path
style="display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
d="m 457.9846,-27.96875 v -3 h 1 l -3,-3 -3,3 h 1 v 3 z"
id="path2809"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<path
style="display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
d="m 451.9846,-23.96875 v 2 h 1 l 2,2 v -6 l -2,2 z"
id="path2811"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
style="display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
d="m 455.9846,-24.96875 v 4 c 0,0 1,-1 1,-2 0,-1.31515 -1,-2 -1,-2 z"
id="path2813"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccsc" />
<path
style="display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
d="m 457.9846,-25.96875 v 6 c 0,0 1,-1.94591 1,-3 0,-1.05409 -1,-3 -1,-3 z"
id="path2815"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccsc" />
<path
inkscape:connector-curvature="0"
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;enable-background:new"
d="m 450.53751,-25.96846 c 0.24647,0 0.44708,0.19694 0.44708,0.44708 v 0.0289 c -0.008,3.05189 -2.48438,5.5237 -5.53812,5.5237 h -0.0148 c -0.25145,0 -0.44711,-0.20581 -0.44711,-0.4615 v -0.46152 -0.92302 c 0,-0.25567 0.20581,-0.4615 0.4615,-0.4615 h 0.92302 c 0.25569,0 0.46152,0.20581 0.46152,0.4615 v 0.21634 c 1.18002,-0.41715 2.10674,-1.34386 2.52389,-2.52388 h -0.21635 c -0.25566,0 -0.4615,-0.20581 -0.4615,-0.46152 v -0.92302 c 0,-0.25567 0.20581,-0.4615 0.4615,-0.4615 h 0.46152 0.4615 0.44709 0.0148 0.0148 z"
id="rect5922-7-3" />
<g
id="g904-6"
transform="matrix(0.26785369,0,0,0.26785369,436.44908,-87.00581)"
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:3.73338151;enable-background:new">
<path
sodipodi:nodetypes="csscccssssccccccsccsssssccccccsssss"
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.46676302;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 37,198.00759 c -2.76142,0 -5,2.23858 -5,5 0,2.76142 2.23858,5 5,5 0.89216,0 1.71236,-0.27804 2.4375,-0.6875 l 3.9375,3.6875 -3.9375,3.6875 c -0.72514,-0.40946 -1.54534,-0.6875 -2.4375,-0.6875 -2.76142,0 -5,2.23858 -5,5 0,2.76142 2.23858,5 5,5 2.76142,0 5,-2.23858 5,-5 0,-0.45832 -0.072,-0.89082 -0.1874,-1.3125 l 4.25,-4.125 8.9374,8.4375 h 3 v -2 l -16.1875,-15.6875 c 0.1156,-0.42168 0.1874,-0.85418 0.1874,-1.3125 0,-2.76142 -2.23858,-5 -5,-5 z m 0,3 c 1.10456,0 2,0.89544 2,2 0,1.10456 -0.89544,2 -2,2 -1.10456,0 -2,-0.89544 -2,-2 0,-1.10456 0.89544,-2 2,-2 z m 18,-1 -7.875,7.4375 2.625,2.5625 8.25,-8 v -2 z m -18,17 c 1.10456,0 2,0.89544 2,2 0,1.10456 -0.89544,2 -2,2 -1.10456,0 -2,-0.89544 -2,-2 0,-1.10456 0.89544,-2 2,-2 z"
id="path1079-7" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.1 KiB

View File

@@ -3,9 +3,7 @@
appdata_config = configuration_data()
appdata_config.set('BUILD_VERSION', meson.project_version())
subdir('constraint-editor')
subdir('gtk-demo')
subdir('icon-browser')
subdir('node-editor')
subdir('widget-factory')
subdir('print-editor')

View File

@@ -1,32 +0,0 @@
.. _gtk4-icon-browser(1):
=================
gtk4-icon-browser
=================
-----------------
List themed icons
-----------------
:Version: GTK
:Manual section: 1
:Manual group: GTK commands
SYNOPSIS
--------
| **gtk4-icon-browser** [OPTIONS...]
DESCRIPTION
-----------
``gtk4-icon-browser`` is a utility to explore the icons in the current icon
theme. It shows icons in various sizes, their symbolic variants where available,
as well as a description of the icon and its context.
OPTIONS
-------
``-h, --help``
Show the application help.

View File

@@ -98,7 +98,6 @@ if get_option('build-demos')
[ 'gtk4-demo', '1', ],
[ 'gtk4-demo-application', '1', ],
[ 'gtk4-widget-factory', '1', ],
[ 'gtk4-icon-browser', '1', ],
[ 'gtk4-node-editor', '1', ],
]
endif

View File

@@ -474,6 +474,8 @@ disable certain optimizations of the "ngl" and "vulkan" renderer.
`occlusion`
: Disable occlusion culling via opacity tracking
`repeat`
: Repeat drawing operations instead of using offscreen and GL_REPEAT
The special value `all` can be used to turn on all values. The special
value `help` can be used to obtain a list of all supported values.

View File

@@ -19,6 +19,7 @@
#include "gdkclipboardprivate.h"
#include "gdkclipboard-win32.h"
#include "gdkdisplay-win32.h"
#include "gdkdebugprivate.h"
#include <glib/gi18n-lib.h>
@@ -62,7 +63,7 @@ gdk_win32_clipboard_request_contentformats (GdkWin32Clipboard *cb)
UINT w32_formats_allocated;
gsize i;
GArray *formatpairs;
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
GdkWin32Clipdrop *clipdrop = gdk_win32_clipboard_get_clipdrop (GDK_CLIPBOARD (cb));
DWORD error_code;
SetLastError (0);
@@ -94,7 +95,7 @@ gdk_win32_clipboard_request_contentformats (GdkWin32Clipboard *cb)
MIN (w32_formats_len, w32_formats_allocated));
for (i = 0; i < MIN (w32_formats_len, w32_formats_allocated); i++)
_gdk_win32_add_w32format_to_pairs (w32_formats[i], formatpairs, NULL);
gdk_win32_clipdrop_add_win32_format_to_pairs (clipdrop, w32_formats[i], formatpairs, NULL);
g_free (w32_formats);
@@ -164,7 +165,7 @@ gdk_win32_clipboard_claim (GdkClipboard *clipboard,
GdkContentProvider *content)
{
if (local)
_gdk_win32_advertise_clipboard_contentformats (NULL, content ? formats : NULL);
_gdk_win32_advertise_clipboard_contentformats (clipboard, NULL, content ? formats : NULL);
return GDK_CLIPBOARD_CLASS (gdk_win32_clipboard_parent_class)->claim (clipboard, formats, local, content);
}
@@ -232,7 +233,7 @@ gdk_win32_clipboard_read_async (GdkClipboard *clipboard,
g_task_set_priority (task, io_priority);
g_task_set_source_tag (task, gdk_win32_clipboard_read_async);
_gdk_win32_retrieve_clipboard_contentformats (task, contentformats);
_gdk_win32_retrieve_clipboard_contentformats (clipboard, task, contentformats);
return;
}
@@ -296,3 +297,8 @@ gdk_win32_clipboard_new (GdkDisplay *display)
return GDK_CLIPBOARD (cb);
}
GdkWin32Clipdrop *
gdk_win32_clipboard_get_clipdrop (GdkClipboard *cb)
{
return gdk_win32_display_get_clipdrop (gdk_clipboard_get_display (GDK_CLIPBOARD (cb)));
}

View File

@@ -18,6 +18,7 @@
#pragma once
#include "gdk/gdkclipboard.h"
#include "gdkprivate-win32.h"
G_BEGIN_DECLS
@@ -33,5 +34,7 @@ GdkClipboard * gdk_win32_clipboard_new (GdkDisplay *dis
void gdk_win32_clipboard_claim_remote (GdkWin32Clipboard *cb);
GdkWin32Clipdrop * gdk_win32_clipboard_get_clipdrop (GdkClipboard *cb);
G_END_DECLS

View File

@@ -279,6 +279,7 @@ Otherwise it's similar to how the clipboard works. Only the DnD server
#include "gdkclipboardprivate.h"
#include "gdkclipboard-win32.h"
#include "gdkclipdrop-win32.h"
#include "gdkdisplay-win32.h"
#include "gdkhdataoutputstream-win32.h"
#include "gdkwin32dnd.h"
#include "gdkwin32dnd-private.h"
@@ -300,15 +301,6 @@ Otherwise it's similar to how the clipboard works. Only the DnD server
*/
#define CLIPBOARD_RENDER_TIMEOUT (G_USEC_PER_SEC * 29)
gboolean _gdk_win32_transmute_windows_data (UINT from_w32format,
const char *to_contentformat,
HANDLE hdata,
guchar **set_data,
gsize *set_data_length);
/* Just to avoid calling RegisterWindowMessage() every time */
static UINT thread_wakeup_message;
typedef enum _GdkWin32ClipboardThreadQueueItemType GdkWin32ClipboardThreadQueueItemType;
enum _GdkWin32ClipboardThreadQueueItemType
@@ -437,11 +429,6 @@ struct _GdkWin32ClipboardThread
gboolean ignore_destroy_clipboard;
};
/* The code is much more secure if we don't rely on the OS to keep
* this around for us.
*/
static GdkWin32ClipboardThread *clipboard_thread_data = NULL;
typedef struct _GdkWin32ClipboardThreadResponse GdkWin32ClipboardThreadResponse;
struct _GdkWin32ClipboardThreadResponse
@@ -485,7 +472,7 @@ _gdk_win32_format_uses_hdata (UINT w32format)
static gboolean
clipboard_hwnd_created (gpointer user_data)
{
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
GdkWin32Clipdrop *clipdrop = gdk_win32_display_get_clipdrop (gdk_display_get_default ());
clipdrop->clipboard_hwnd = (HWND) user_data;
@@ -518,7 +505,7 @@ clipboard_render_hdata_ready (GObject *clipboard,
{
GError *error = NULL;
GdkWin32ClipboardRenderAndStream render_and_stream = *(GdkWin32ClipboardRenderAndStream *) user_data;
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
GdkWin32Clipdrop *clipdrop = gdk_win32_clipboard_get_clipdrop (GDK_CLIPBOARD (clipboard));
g_free (user_data);
@@ -553,11 +540,11 @@ static gboolean
clipboard_render (gpointer user_data)
{
GdkWin32ClipboardThreadRender *render = (GdkWin32ClipboardThreadRender *) user_data;
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
GdkDisplay *display = gdk_display_get_default ();
GdkWin32Clipdrop *clipdrop = gdk_win32_display_get_clipdrop (display);
GdkClipboard *clipboard = gdk_display_get_clipboard (display);
GError *error = NULL;
GOutputStream *stream = gdk_win32_hdata_output_stream_new (&render->pair, &error);
GOutputStream *stream = gdk_win32_hdata_output_stream_new (clipdrop, &render->pair, &error);
GdkWin32ClipboardRenderAndStream *render_and_stream;
if (stream == NULL)
@@ -684,28 +671,32 @@ send_input_stream (GdkWin32ClipboardThreadQueueItemType request_type,
g_idle_add_full (G_PRIORITY_DEFAULT, clipboard_thread_response, response, NULL);
}
#define CLIPDROP_CB_THREAD_MEMBER(c,m) ((GdkWin32ClipboardThread *)(c->clipboard_thread_items))->m
static DWORD
try_open_clipboard (HWND hwnd)
try_open_clipboard (GdkWin32Clipdrop *clipdrop,
HWND hwnd)
{
if (clipboard_thread_data->clipboard_opened_for == hwnd)
if (CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_opened_for) == hwnd)
return NO_ERROR;
if (clipboard_thread_data->clipboard_opened_for != INVALID_HANDLE_VALUE)
if (CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_opened_for) != INVALID_HANDLE_VALUE)
{
API_CALL (CloseClipboard, ());
clipboard_thread_data->clipboard_opened_for = INVALID_HANDLE_VALUE;
CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_opened_for) = INVALID_HANDLE_VALUE;
}
if (!OpenClipboard (hwnd))
return GetLastError ();
clipboard_thread_data->clipboard_opened_for = hwnd;
CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_opened_for) = hwnd;
return NO_ERROR;
}
static gboolean
process_advertise (GdkWin32ClipboardThreadAdvertise *adv)
process_advertise (GdkWin32Clipdrop *clipdrop,
GdkWin32ClipboardThreadAdvertise *adv)
{
DWORD error_code;
int i;
@@ -720,7 +711,7 @@ process_advertise (GdkWin32ClipboardThreadAdvertise *adv)
return FALSE;
}
if (clipboard_thread_data->owner_change_time > adv->parent.start_time)
if (CLIPDROP_CB_THREAD_MEMBER (clipdrop, owner_change_time) > adv->parent.start_time)
{
GDK_NOTE (CLIPBOARD, g_printerr ("An advertise task timed out due to ownership change\n"));
send_response (adv->parent.item_type,
@@ -730,7 +721,7 @@ process_advertise (GdkWin32ClipboardThreadAdvertise *adv)
return FALSE;
}
error_code = try_open_clipboard (adv->unset ? NULL : clipboard_thread_data->clipboard_hwnd);
error_code = try_open_clipboard (clipdrop, adv->unset ? NULL : CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd));
if (error_code == ERROR_ACCESS_DENIED)
return TRUE;
@@ -744,10 +735,10 @@ process_advertise (GdkWin32ClipboardThreadAdvertise *adv)
return FALSE;
}
clipboard_thread_data->ignore_destroy_clipboard = TRUE;
CLIPDROP_CB_THREAD_MEMBER (clipdrop, ignore_destroy_clipboard) = TRUE;
if (!EmptyClipboard ())
{
clipboard_thread_data->ignore_destroy_clipboard = FALSE;
CLIPDROP_CB_THREAD_MEMBER (clipdrop, ignore_destroy_clipboard) = FALSE;
error_code = GetLastError ();
send_response (adv->parent.item_type,
adv->parent.opaque_task,
@@ -756,7 +747,7 @@ process_advertise (GdkWin32ClipboardThreadAdvertise *adv)
return FALSE;
}
clipboard_thread_data->ignore_destroy_clipboard = FALSE;
CLIPDROP_CB_THREAD_MEMBER (clipdrop, ignore_destroy_clipboard) = FALSE;
if (adv->unset)
return FALSE;
@@ -768,10 +759,10 @@ process_advertise (GdkWin32ClipboardThreadAdvertise *adv)
SetClipboardData (pair->w32format, NULL);
}
if (clipboard_thread_data->cached_advertisement)
g_array_free (clipboard_thread_data->cached_advertisement, TRUE);
if (CLIPDROP_CB_THREAD_MEMBER (clipdrop, cached_advertisement))
g_array_free (CLIPDROP_CB_THREAD_MEMBER (clipdrop, cached_advertisement), TRUE);
clipboard_thread_data->cached_advertisement = adv->pairs;
CLIPDROP_CB_THREAD_MEMBER (clipdrop, cached_advertisement) = adv->pairs;
/* To enure that we don't free it later on */
adv->pairs = NULL;
@@ -784,7 +775,8 @@ process_advertise (GdkWin32ClipboardThreadAdvertise *adv)
}
static gboolean
process_store (GdkWin32ClipboardThreadStore *store)
process_store (GdkWin32Clipdrop *clipdrop,
GdkWin32ClipboardThreadStore *store)
{
DWORD error_code;
int i;
@@ -799,7 +791,7 @@ process_store (GdkWin32ClipboardThreadStore *store)
return FALSE;
}
if (clipboard_thread_data->owner_change_time > store->parent.start_time)
if (CLIPDROP_CB_THREAD_MEMBER (clipdrop, owner_change_time) > store->parent.start_time)
{
GDK_NOTE (CLIPBOARD, g_printerr ("A store task timed out due to ownership change\n"));
send_response (store->parent.item_type,
@@ -809,7 +801,7 @@ process_store (GdkWin32ClipboardThreadStore *store)
return FALSE;
}
error_code = try_open_clipboard (clipboard_thread_data->clipboard_hwnd);
error_code = try_open_clipboard (clipdrop, CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd));
if (error_code == ERROR_ACCESS_DENIED)
return TRUE;
@@ -831,7 +823,7 @@ process_store (GdkWin32ClipboardThreadStore *store)
* that we already own, otherwise we're just killing stuff that some other
* process put in there, which is not nice.
*/
if (GetClipboardOwner () != clipboard_thread_data->clipboard_hwnd)
if (GetClipboardOwner () != CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd))
{
send_response (store->parent.item_type,
store->parent.opaque_task,
@@ -910,7 +902,8 @@ grab_data_from_hdata (GdkWin32ClipboardThreadRetrieve *retr,
}
static gboolean
process_retrieve (GdkWin32ClipboardThreadRetrieve *retr)
process_retrieve (GdkWin32Clipdrop *clipdrop,
GdkWin32ClipboardThreadRetrieve *retr)
{
DWORD error_code;
int i;
@@ -931,7 +924,7 @@ process_retrieve (GdkWin32ClipboardThreadRetrieve *retr)
return FALSE;
}
if (clipboard_thread_data->owner_change_time > retr->parent.start_time)
if (CLIPDROP_CB_THREAD_MEMBER (clipdrop, owner_change_time) > retr->parent.start_time)
{
GDK_NOTE (CLIPBOARD, g_printerr ("A retrieve task timed out due to ownership change\n"));
send_response (retr->parent.item_type,
@@ -951,10 +944,10 @@ process_retrieve (GdkWin32ClipboardThreadRetrieve *retr)
return FALSE;
}
if (clipboard_thread_data->clipboard_opened_for == INVALID_HANDLE_VALUE)
error_code = try_open_clipboard (clipboard_thread_data->clipboard_hwnd);
if (CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_opened_for) == INVALID_HANDLE_VALUE)
error_code = try_open_clipboard (clipdrop, CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd));
else
error_code = try_open_clipboard (clipboard_thread_data->clipboard_opened_for);
error_code = try_open_clipboard (clipdrop, CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_opened_for));
if (error_code == ERROR_ACCESS_DENIED)
return TRUE;
@@ -1021,7 +1014,7 @@ process_retrieve (GdkWin32ClipboardThreadRetrieve *retr)
}
else
{
_gdk_win32_transmute_windows_data (pair->w32format, pair->contentformat, hdata, &data, &data_len);
gdk_win32_clipdrop_transmute_windows_data (clipdrop, pair->w32format, pair->contentformat, hdata, &data, &data_len);
if (data == NULL)
return FALSE;
@@ -1040,14 +1033,14 @@ process_retrieve (GdkWin32ClipboardThreadRetrieve *retr)
}
static gboolean
process_clipboard_queue ()
process_clipboard_queue (GdkWin32Clipdrop *clipdrop)
{
GdkWin32ClipboardThreadQueueItem *placeholder;
GList *p;
gboolean try_again;
GList *p_next;
for (p = clipboard_thread_data->dequeued_items, p_next = NULL; p; p = p_next)
for (p = CLIPDROP_CB_THREAD_MEMBER (clipdrop, dequeued_items), p_next = NULL; p; p = p_next)
{
placeholder = (GdkWin32ClipboardThreadQueueItem *) p->data;
p_next = p->next;
@@ -1055,35 +1048,35 @@ process_clipboard_queue ()
switch (placeholder->item_type)
{
case GDK_WIN32_CLIPBOARD_THREAD_QUEUE_ITEM_ADVERTISE:
try_again = process_advertise ((GdkWin32ClipboardThreadAdvertise *) placeholder);
try_again = process_advertise (clipdrop, (GdkWin32ClipboardThreadAdvertise *) placeholder);
break;
case GDK_WIN32_CLIPBOARD_THREAD_QUEUE_ITEM_RETRIEVE:
try_again = process_retrieve ((GdkWin32ClipboardThreadRetrieve *) placeholder);
try_again = process_retrieve (clipdrop, (GdkWin32ClipboardThreadRetrieve *) placeholder);
break;
case GDK_WIN32_CLIPBOARD_THREAD_QUEUE_ITEM_STORE:
try_again = process_store ((GdkWin32ClipboardThreadStore *) placeholder);
try_again = process_store (clipdrop, (GdkWin32ClipboardThreadStore *) placeholder);
break;
}
if (try_again)
return FALSE;
clipboard_thread_data->dequeued_items = g_list_delete_link (clipboard_thread_data->dequeued_items, p);
CLIPDROP_CB_THREAD_MEMBER (clipdrop, dequeued_items) = g_list_delete_link (CLIPDROP_CB_THREAD_MEMBER (clipdrop, dequeued_items), p);
free_queue_item (placeholder);
}
while ((placeholder = g_async_queue_try_pop (clipboard_thread_data->input_queue)) != NULL)
while ((placeholder = g_async_queue_try_pop (CLIPDROP_CB_THREAD_MEMBER (clipdrop, input_queue))) != NULL)
{
switch (placeholder->item_type)
{
case GDK_WIN32_CLIPBOARD_THREAD_QUEUE_ITEM_ADVERTISE:
try_again = process_advertise ((GdkWin32ClipboardThreadAdvertise *) placeholder);
try_again = process_advertise (clipdrop, (GdkWin32ClipboardThreadAdvertise *) placeholder);
break;
case GDK_WIN32_CLIPBOARD_THREAD_QUEUE_ITEM_RETRIEVE:
try_again = process_retrieve ((GdkWin32ClipboardThreadRetrieve *) placeholder);
try_again = process_retrieve (clipdrop, (GdkWin32ClipboardThreadRetrieve *) placeholder);
break;
case GDK_WIN32_CLIPBOARD_THREAD_QUEUE_ITEM_STORE:
try_again = process_store ((GdkWin32ClipboardThreadStore *) placeholder);
try_again = process_store (clipdrop, (GdkWin32ClipboardThreadStore *) placeholder);
break;
}
@@ -1093,7 +1086,7 @@ process_clipboard_queue ()
continue;
}
clipboard_thread_data->dequeued_items = g_list_append (clipboard_thread_data->dequeued_items, placeholder);
CLIPDROP_CB_THREAD_MEMBER (clipdrop, dequeued_items) = g_list_append (CLIPDROP_CB_THREAD_MEMBER (clipdrop, dequeued_items), placeholder);
return FALSE;
}
@@ -1124,23 +1117,37 @@ inner_clipboard_hwnd_procedure (HWND hwnd,
WPARAM wparam,
LPARAM lparam)
{
if (message == thread_wakeup_message ||
GdkWin32Clipdrop *clipdrop = NULL;
if (message == WM_NCCREATE)
{
CREATESTRUCT *cs = (CREATESTRUCT *)lparam;
clipdrop = (GdkWin32Clipdrop *) cs->lpCreateParams;
SetWindowLongPtr (hwnd, GWLP_USERDATA, (LONG_PTR) clipdrop);
return TRUE;
}
else if (message == WM_CREATE)
return DefWindowProcW (hwnd, message, wparam, lparam);
else
clipdrop = (GdkWin32Clipdrop *) GetWindowLongPtr (hwnd, GWLP_USERDATA);
if (message == clipdrop->thread_wakeup_message ||
message == WM_TIMER)
{
gboolean queue_is_empty = FALSE;
if (clipboard_thread_data == NULL)
if (clipdrop->clipboard_thread_items == NULL)
{
g_warning ("Clipboard thread got an actionable message with no thread data");
return DefWindowProcW (hwnd, message, wparam, lparam);
}
queue_is_empty = process_clipboard_queue ();
queue_is_empty = process_clipboard_queue (clipdrop);
if (queue_is_empty && clipboard_thread_data->wakeup_timer)
if (queue_is_empty && CLIPDROP_CB_THREAD_MEMBER (clipdrop, wakeup_timer))
{
API_CALL (KillTimer, (clipboard_thread_data->clipboard_hwnd, clipboard_thread_data->wakeup_timer));
clipboard_thread_data->wakeup_timer = 0;
API_CALL (KillTimer, (CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd), CLIPDROP_CB_THREAD_MEMBER (clipdrop, wakeup_timer)));
CLIPDROP_CB_THREAD_MEMBER (clipdrop, wakeup_timer) = 0;
}
/* Close the clipboard after each queue run, if it's open.
@@ -1149,21 +1156,21 @@ inner_clipboard_hwnd_procedure (HWND hwnd,
* queue_is_empty == FALSE implies that the clipboard
* is closed already, but it's better to be sure.
*/
if (clipboard_thread_data->clipboard_opened_for != INVALID_HANDLE_VALUE)
if (CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_opened_for) != INVALID_HANDLE_VALUE)
{
API_CALL (CloseClipboard, ());
clipboard_thread_data->clipboard_opened_for = INVALID_HANDLE_VALUE;
CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_opened_for) = INVALID_HANDLE_VALUE;
}
if (queue_is_empty ||
clipboard_thread_data->wakeup_timer != 0)
CLIPDROP_CB_THREAD_MEMBER (clipdrop, wakeup_timer) != 0)
return 0;
if (SetTimer (clipboard_thread_data->clipboard_hwnd, 1, 1000, NULL))
clipboard_thread_data->wakeup_timer = 1;
if (SetTimer (CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd), 1, 1000, NULL))
CLIPDROP_CB_THREAD_MEMBER (clipdrop, wakeup_timer) = 1;
else
g_critical ("Failed to set a timer for the clipboard HWND 0x%p: %lu",
clipboard_thread_data->clipboard_hwnd,
CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd),
GetLastError ());
}
@@ -1171,7 +1178,7 @@ inner_clipboard_hwnd_procedure (HWND hwnd,
{
case WM_DESTROY: /* unregister the clipboard listener */
{
if (clipboard_thread_data == NULL)
if (clipdrop->clipboard_thread_items == NULL)
{
g_warning ("Clipboard thread got an actionable message with no thread data");
return DefWindowProcW (hwnd, message, wparam, lparam);
@@ -1192,7 +1199,7 @@ inner_clipboard_hwnd_procedure (HWND hwnd,
/*
GdkEvent *event;
*/
if (clipboard_thread_data == NULL)
if (clipdrop->clipboard_thread_items == NULL)
{
g_warning ("Clipboard thread got an actionable message with no thread data");
return DefWindowProcW (hwnd, message, wparam, lparam);
@@ -1210,7 +1217,7 @@ inner_clipboard_hwnd_procedure (HWND hwnd,
if (GDK_DEBUG_CHECK (DND))
{
/* FIXME: grab and print clipboard formats without opening the clipboard
if (clipboard_thread_data->clipboard_opened_for != INVALID_HANDLE_VALUE ||
if (CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_opened_for) != INVALID_HANDLE_VALUE ||
OpenClipboard (hwnd))
{
UINT nFormat = 0;
@@ -1218,7 +1225,7 @@ inner_clipboard_hwnd_procedure (HWND hwnd,
while ((nFormat = EnumClipboardFormats (nFormat)) != 0)
g_print ("%s ", _gdk_win32_cf_to_string (nFormat));
if (clipboard_thread_data->clipboard_opened_for == INVALID_HANDLE_VALUE)
if (CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_opened_for) == INVALID_HANDLE_VALUE)
CloseClipboard ();
}
else
@@ -1230,22 +1237,22 @@ inner_clipboard_hwnd_procedure (HWND hwnd,
GDK_NOTE (DND, g_print (" \n"));
if (clipboard_thread_data->stored_hwnd_owner != hwnd_owner)
if (CLIPDROP_CB_THREAD_MEMBER (clipdrop, stored_hwnd_owner) != hwnd_owner)
{
clipboard_thread_data->stored_hwnd_owner = hwnd_owner;
clipboard_thread_data->owner_change_time = g_get_monotonic_time ();
CLIPDROP_CB_THREAD_MEMBER (clipdrop, stored_hwnd_owner) = hwnd_owner;
CLIPDROP_CB_THREAD_MEMBER (clipdrop, owner_change_time) = g_get_monotonic_time ();
if (hwnd_owner != clipboard_thread_data->clipboard_hwnd)
if (hwnd_owner != CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd))
{
if (clipboard_thread_data->cached_advertisement)
g_array_free (clipboard_thread_data->cached_advertisement, TRUE);
if (CLIPDROP_CB_THREAD_MEMBER (clipdrop, cached_advertisement))
g_array_free (CLIPDROP_CB_THREAD_MEMBER (clipdrop, cached_advertisement), TRUE);
clipboard_thread_data->cached_advertisement = NULL;
CLIPDROP_CB_THREAD_MEMBER (clipdrop, cached_advertisement) = NULL;
}
API_CALL (PostMessage, (clipboard_thread_data->clipboard_hwnd, thread_wakeup_message, 0, 0));
API_CALL (PostMessage, (CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd), clipdrop->thread_wakeup_message, 0, 0));
if (hwnd_owner != clipboard_thread_data->clipboard_hwnd)
if (hwnd_owner != CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd))
g_idle_add_full (G_PRIORITY_DEFAULT, clipboard_owner_changed, NULL, NULL);
}
@@ -1256,13 +1263,13 @@ inner_clipboard_hwnd_procedure (HWND hwnd,
}
case WM_RENDERALLFORMATS:
{
if (clipboard_thread_data == NULL)
if (clipdrop->clipboard_thread_items == NULL)
{
g_warning ("Clipboard thread got an actionable message with no thread data");
return DefWindowProcW (hwnd, message, wparam, lparam);
}
if (clipboard_thread_data->cached_advertisement == NULL)
if (CLIPDROP_CB_THREAD_MEMBER (clipdrop, cached_advertisement == NULL))
return DefWindowProcW (hwnd, message, wparam, lparam);
if (API_CALL (OpenClipboard, (hwnd)))
@@ -1271,10 +1278,10 @@ inner_clipboard_hwnd_procedure (HWND hwnd,
GdkWin32ContentFormatPair *pair;
for (pair = NULL, i = 0;
i < clipboard_thread_data->cached_advertisement->len;
i < CLIPDROP_CB_THREAD_MEMBER (clipdrop, cached_advertisement)->len;
i++)
{
pair = &g_array_index (clipboard_thread_data->cached_advertisement, GdkWin32ContentFormatPair, i);
pair = &g_array_index (CLIPDROP_CB_THREAD_MEMBER (clipdrop, cached_advertisement), GdkWin32ContentFormatPair, i);
if (pair->w32format != 0)
SendMessage (hwnd, WM_RENDERFORMAT, pair->w32format, 0);
@@ -1295,20 +1302,20 @@ inner_clipboard_hwnd_procedure (HWND hwnd,
GDK_NOTE (EVENTS, g_print (" %s", _gdk_win32_cf_to_string (wparam)));
if (clipboard_thread_data == NULL)
if (clipdrop->clipboard_thread_items == NULL)
{
g_warning ("Clipboard thread got an actionable message with no thread data");
return DefWindowProcW (hwnd, message, wparam, lparam);
}
if (clipboard_thread_data->cached_advertisement == NULL)
if (CLIPDROP_CB_THREAD_MEMBER (clipdrop, cached_advertisement) == NULL)
return DefWindowProcW (hwnd, message, wparam, lparam);
for (pair = NULL, i = 0;
i < clipboard_thread_data->cached_advertisement->len;
i < CLIPDROP_CB_THREAD_MEMBER (clipdrop, cached_advertisement)->len;
i++)
{
pair = &g_array_index (clipboard_thread_data->cached_advertisement, GdkWin32ContentFormatPair, i);
pair = &g_array_index (CLIPDROP_CB_THREAD_MEMBER (clipdrop, cached_advertisement), GdkWin32ContentFormatPair, i);
if (pair->w32format == wparam)
break;
@@ -1323,13 +1330,13 @@ inner_clipboard_hwnd_procedure (HWND hwnd,
}
/* Clear the queue */
while ((render = g_async_queue_try_pop (clipboard_thread_data->render_queue)) != NULL)
while ((render = g_async_queue_try_pop (CLIPDROP_CB_THREAD_MEMBER (clipdrop, render_queue))) != NULL)
discard_render (render, FALSE);
render = g_new0 (GdkWin32ClipboardThreadRender, 1);
render->pair = *pair;
g_idle_add_full (G_PRIORITY_DEFAULT, clipboard_render, render, NULL);
returned_render = g_async_queue_timeout_pop (clipboard_thread_data->render_queue, CLIPBOARD_RENDER_TIMEOUT);
returned_render = g_async_queue_timeout_pop (CLIPDROP_CB_THREAD_MEMBER (clipdrop, render_queue), CLIPBOARD_RENDER_TIMEOUT);
/* We should get back the same pointer, ignore everything else. */
while (returned_render != NULL && returned_render != render)
@@ -1343,7 +1350,7 @@ inner_clipboard_hwnd_procedure (HWND hwnd,
* If you get many "Clipboard rendering timed out" warnings,
* this is probably why.
*/
returned_render = g_async_queue_try_pop (clipboard_thread_data->render_queue);
returned_render = g_async_queue_try_pop (CLIPDROP_CB_THREAD_MEMBER (clipdrop, render_queue));
}
/* Just in case */
@@ -1403,7 +1410,7 @@ _clipboard_hwnd_procedure (HWND hwnd,
* Creates a hidden HWND and add a clipboard listener
*/
static gboolean
register_clipboard_notification ()
register_clipboard_notification (GdkWin32Clipdrop *clipdrop)
{
WNDCLASS wclass = { 0, };
ATOM klass;
@@ -1417,23 +1424,24 @@ register_clipboard_notification ()
if (!klass)
return FALSE;
clipboard_thread_data->clipboard_hwnd = CreateWindow (MAKEINTRESOURCE (klass),
NULL, WS_POPUP,
0, 0, 0, 0, NULL, NULL,
this_module (), NULL);
CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd) =
CreateWindow (MAKEINTRESOURCE (klass),
NULL, WS_POPUP,
0, 0, 0, 0, NULL, NULL,
this_module (), clipdrop);
if (clipboard_thread_data->clipboard_hwnd == NULL)
if (CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd) == NULL)
goto failed;
SetLastError (0);
if (AddClipboardFormatListener (clipboard_thread_data->clipboard_hwnd) == FALSE)
if (AddClipboardFormatListener (CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd)) == FALSE)
{
DestroyWindow (clipboard_thread_data->clipboard_hwnd);
DestroyWindow (CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd));
goto failed;
}
g_idle_add_full (G_PRIORITY_DEFAULT, clipboard_hwnd_created, (gpointer) clipboard_thread_data->clipboard_hwnd, NULL);
g_idle_add_full (G_PRIORITY_DEFAULT, clipboard_hwnd_created, (gpointer) CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd), NULL);
return TRUE;
@@ -1447,20 +1455,21 @@ static gpointer
_gdk_win32_clipboard_thread_main (gpointer data)
{
MSG msg;
GAsyncQueue *queue = (GAsyncQueue *) data;
clipdrop_thread_items *items = (clipdrop_thread_items*) data;
GAsyncQueue *queue = items->queue;
GAsyncQueue *render_queue = (GAsyncQueue *) g_async_queue_pop (queue);
g_assert (clipboard_thread_data == NULL);
g_assert (items->clipdrop->clipboard_thread_items == NULL);
clipboard_thread_data = g_new0 (GdkWin32ClipboardThread, 1);
clipboard_thread_data->input_queue = queue;
clipboard_thread_data->render_queue = render_queue;
clipboard_thread_data->clipboard_opened_for = INVALID_HANDLE_VALUE;
items->clipdrop->clipboard_thread_items = g_new0 (GdkWin32ClipboardThread, 1);
CLIPDROP_CB_THREAD_MEMBER (items->clipdrop, input_queue) = queue;
CLIPDROP_CB_THREAD_MEMBER (items->clipdrop, render_queue) = render_queue;
CLIPDROP_CB_THREAD_MEMBER (items->clipdrop, clipboard_opened_for) = INVALID_HANDLE_VALUE;
if (!register_clipboard_notification ())
if (!register_clipboard_notification (items->clipdrop))
{
g_async_queue_unref (queue);
g_clear_pointer (&clipboard_thread_data, g_free);
g_clear_pointer (&items->clipdrop->clipboard_thread_items, g_free);
return NULL;
}
@@ -1472,10 +1481,10 @@ _gdk_win32_clipboard_thread_main (gpointer data)
}
/* Just in case, as this should only happen when we shut down */
DestroyWindow (clipboard_thread_data->clipboard_hwnd);
CloseHandle (clipboard_thread_data->clipboard_hwnd);
DestroyWindow (CLIPDROP_CB_THREAD_MEMBER (items->clipdrop, clipboard_hwnd));
CloseHandle (CLIPDROP_CB_THREAD_MEMBER (items->clipdrop, clipboard_hwnd));
g_async_queue_unref (queue);
g_clear_pointer (&clipboard_thread_data, g_free);
g_clear_pointer (&items->clipdrop->clipboard_thread_items, g_free);
return NULL;
}
@@ -1483,15 +1492,22 @@ _gdk_win32_clipboard_thread_main (gpointer data)
G_DEFINE_TYPE (GdkWin32Clipdrop, gdk_win32_clipdrop, G_TYPE_OBJECT)
static void
gdk_win32_clipdrop_class_init (GdkWin32ClipdropClass *klass)
gdk_win32_clipdrop_finalize (GObject *object)
{
GdkWin32Clipdrop *clipdrop = GDK_WIN32_CLIPDROP (object);
DestroyWindow (CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd));
CloseHandle (CLIPDROP_CB_THREAD_MEMBER (clipdrop, clipboard_hwnd));
g_clear_pointer (&clipdrop->dnd_thread_items, g_free);
g_clear_pointer (&clipdrop->clipboard_thread_items, g_free);
}
void
_gdk_win32_clipdrop_init (void)
static void
gdk_win32_clipdrop_class_init (GdkWin32ClipdropClass *klass)
{
_win32_main_thread = g_thread_self ();
_win32_clipdrop = GDK_WIN32_CLIPDROP (g_object_new (GDK_TYPE_WIN32_CLIPDROP, NULL));
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gdk_win32_clipdrop_finalize;
}
static void
@@ -1505,8 +1521,9 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
GArray *comp;
GdkWin32ContentFormatPair fmt;
HMODULE user32;
clipdrop_thread_items cb_items, dnd_items;
thread_wakeup_message = RegisterWindowMessage (L"GDK_WORKER_THREAD_WEAKEUP");
win32_clipdrop->thread_wakeup_message = RegisterWindowMessage (L"GDK_WORKER_THREAD_WEAKEUP");
user32 = LoadLibrary (L"user32.dll");
win32_clipdrop->GetUpdatedClipboardFormats = (GetUpdatedClipboardFormatsFunc) GetProcAddress (user32, "GetUpdatedClipboardFormats");
@@ -1798,14 +1815,17 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
* pointers and then passing *that* to the thread.
*/
g_async_queue_push (win32_clipdrop->clipboard_open_thread_queue, g_async_queue_ref (win32_clipdrop->clipboard_render_queue));
cb_items.clipdrop = dnd_items.clipdrop = win32_clipdrop;
cb_items.queue = g_async_queue_ref (win32_clipdrop->clipboard_open_thread_queue);
win32_clipdrop->clipboard_open_thread = g_thread_new ("GDK Win32 Clipboard Thread",
_gdk_win32_clipboard_thread_main,
g_async_queue_ref (win32_clipdrop->clipboard_open_thread_queue));
&cb_items);
win32_clipdrop->dnd_queue = g_async_queue_new ();
dnd_items.queue = g_async_queue_ref (win32_clipdrop->dnd_queue);
win32_clipdrop->dnd_thread = g_thread_new ("GDK Win32 DnD Thread",
_gdk_win32_dnd_thread_main,
g_async_queue_ref (win32_clipdrop->dnd_queue));
&dnd_items);
win32_clipdrop->dnd_thread_id = GPOINTER_TO_UINT (g_async_queue_pop (win32_clipdrop->dnd_queue));
}
@@ -1927,11 +1947,11 @@ _gdk_win32_get_clipboard_format_name_as_interned_mimetype (char *w32format_name)
}
static GArray *
get_compatibility_w32formats_for_contentformat (const char *contentformat)
get_compatibility_w32formats_for_contentformat (GdkWin32Clipdrop *clipdrop,
const char *contentformat)
{
GArray *result = NULL;
int i;
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
result = g_hash_table_lookup (clipdrop->compatibility_w32formats, contentformat);
@@ -1945,7 +1965,7 @@ get_compatibility_w32formats_for_contentformat (const char *contentformat)
/* Any format known to gdk-pixbuf can be presented as PNG or BMP */
result = g_hash_table_lookup (clipdrop->compatibility_w32formats,
_gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_IMAGE_PNG));
_gdk_win32_clipdrop_atom (clipdrop, GDK_WIN32_ATOM_INDEX_IMAGE_PNG));
break;
}
@@ -1953,10 +1973,10 @@ get_compatibility_w32formats_for_contentformat (const char *contentformat)
}
static GArray *
_gdk_win32_get_compatibility_contentformats_for_w32format (UINT w32format)
_gdk_win32_get_compatibility_contentformats_for_w32format (GdkWin32Clipdrop *clipdrop,
UINT w32format)
{
GArray *result = NULL;
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
result = g_hash_table_lookup (clipdrop->compatibility_contentformats, GINT_TO_POINTER (w32format));
@@ -1983,9 +2003,10 @@ _gdk_win32_get_compatibility_contentformats_for_w32format (UINT w32format)
* (builder already takes care of that for itself).
*/
void
_gdk_win32_add_w32format_to_pairs (UINT w32format,
GArray *pairs,
GdkContentFormatsBuilder *builder)
gdk_win32_clipdrop_add_win32_format_to_pairs (GdkWin32Clipdrop *clipdrop,
UINT w32format,
GArray *pairs,
GdkContentFormatsBuilder *builder)
{
gboolean predef;
char *w32format_name = _gdk_win32_get_clipboard_format_name (w32format, &predef);
@@ -2017,7 +2038,7 @@ _gdk_win32_add_w32format_to_pairs (UINT w32format,
gdk_content_formats_builder_add_mime_type (builder, interned_w32format_name);
}
comp_pairs = _gdk_win32_get_compatibility_contentformats_for_w32format (w32format);
comp_pairs = _gdk_win32_get_compatibility_contentformats_for_w32format (clipdrop, w32format);
if (pairs != NULL && comp_pairs != NULL)
for (i = 0; i < comp_pairs->len; i++)
@@ -2548,11 +2569,12 @@ transmute_image_bmp_to_cf_dib (const guchar *data,
}
gboolean
_gdk_win32_transmute_windows_data (UINT from_w32format,
const char *to_contentformat,
HANDLE hdata,
guchar **set_data,
gsize *set_data_length)
gdk_win32_clipdrop_transmute_windows_data (GdkWin32Clipdrop *clipdrop,
UINT from_w32format,
const char *to_contentformat,
HANDLE hdata,
guchar **set_data,
gsize *set_data_length)
{
const guchar *data;
SIZE_T hdata_length;
@@ -2572,37 +2594,37 @@ _gdk_win32_transmute_windows_data (UINT from_w32format,
length = (gsize) hdata_length;
if ((to_contentformat == _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_IMAGE_PNG) &&
from_w32format == _gdk_win32_clipdrop_cf (GDK_WIN32_CF_INDEX_PNG)) ||
(to_contentformat == _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_IMAGE_JPEG) &&
from_w32format == _gdk_win32_clipdrop_cf (GDK_WIN32_CF_INDEX_JFIF)) ||
(to_contentformat == _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_GIF) &&
from_w32format == _gdk_win32_clipdrop_cf (GDK_WIN32_CF_INDEX_GIF)))
if ((to_contentformat == _gdk_win32_clipdrop_atom (clipdrop, GDK_WIN32_ATOM_INDEX_IMAGE_PNG) &&
from_w32format == _gdk_win32_clipdrop_cf (clipdrop, GDK_WIN32_CF_INDEX_PNG)) ||
(to_contentformat == _gdk_win32_clipdrop_atom (clipdrop, GDK_WIN32_ATOM_INDEX_IMAGE_JPEG) &&
from_w32format == _gdk_win32_clipdrop_cf (clipdrop, GDK_WIN32_CF_INDEX_JFIF)) ||
(to_contentformat == _gdk_win32_clipdrop_atom (clipdrop, GDK_WIN32_ATOM_INDEX_GIF) &&
from_w32format == _gdk_win32_clipdrop_cf (clipdrop, GDK_WIN32_CF_INDEX_GIF)))
{
/* No transmutation needed */
*set_data = g_memdup2 (data, length);
*set_data_length = length;
}
else if (to_contentformat == _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_TEXT_PLAIN_UTF8) &&
else if (to_contentformat == _gdk_win32_clipdrop_atom (clipdrop, GDK_WIN32_ATOM_INDEX_TEXT_PLAIN_UTF8) &&
from_w32format == CF_UNICODETEXT)
{
transmute_cf_unicodetext_to_utf8_string (data, length, set_data, set_data_length, NULL);
res = TRUE;
}
else if (to_contentformat == _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_TEXT_PLAIN_UTF8) &&
else if (to_contentformat == _gdk_win32_clipdrop_atom (clipdrop, GDK_WIN32_ATOM_INDEX_TEXT_PLAIN_UTF8) &&
from_w32format == CF_TEXT)
{
transmute_cf_text_to_utf8_string (data, length, set_data, set_data_length, NULL);
res = TRUE;
}
else if (to_contentformat == _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_IMAGE_BMP) &&
else if (to_contentformat == _gdk_win32_clipdrop_atom (clipdrop, GDK_WIN32_ATOM_INDEX_IMAGE_BMP) &&
(from_w32format == CF_DIB || from_w32format == CF_DIBV5))
{
transmute_cf_dib_to_image_bmp (data, length, set_data, set_data_length, NULL);
res = TRUE;
}
else if (to_contentformat == _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_TEXT_URI_LIST) &&
from_w32format == _gdk_win32_clipdrop_cf (GDK_WIN32_CF_INDEX_CFSTR_SHELLIDLIST))
else if (to_contentformat == _gdk_win32_clipdrop_atom (clipdrop, GDK_WIN32_ATOM_INDEX_TEXT_URI_LIST) &&
from_w32format == _gdk_win32_clipdrop_cf (clipdrop, GDK_WIN32_CF_INDEX_CFSTR_SHELLIDLIST))
{
transmute_cf_shell_id_list_to_text_uri_list (data, length, set_data, set_data_length, NULL);
res = TRUE;
@@ -2621,47 +2643,48 @@ out:
}
gboolean
_gdk_win32_transmute_contentformat (const char *from_contentformat,
UINT to_w32format,
const guchar *data,
gsize length,
guchar **set_data,
gsize *set_data_length)
gdk_win32_clipdrop_transmute_contentformat (GdkWin32Clipdrop *clipdrop,
const char *from_contentformat,
UINT to_w32format,
const guchar *data,
gsize length,
guchar **set_data,
gsize *set_data_length)
{
if ((from_contentformat == _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_IMAGE_PNG) &&
to_w32format == _gdk_win32_clipdrop_cf (GDK_WIN32_CF_INDEX_PNG)) ||
(from_contentformat == _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_IMAGE_JPEG) &&
to_w32format == _gdk_win32_clipdrop_cf (GDK_WIN32_CF_INDEX_JFIF)) ||
(from_contentformat == _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_GIF) &&
to_w32format == _gdk_win32_clipdrop_cf (GDK_WIN32_CF_INDEX_GIF)))
if ((from_contentformat == _gdk_win32_clipdrop_atom (clipdrop, GDK_WIN32_ATOM_INDEX_IMAGE_PNG) &&
to_w32format == _gdk_win32_clipdrop_cf (clipdrop, GDK_WIN32_CF_INDEX_PNG)) ||
(from_contentformat == _gdk_win32_clipdrop_atom (clipdrop, GDK_WIN32_ATOM_INDEX_IMAGE_JPEG) &&
to_w32format == _gdk_win32_clipdrop_cf (clipdrop, GDK_WIN32_CF_INDEX_JFIF)) ||
(from_contentformat == _gdk_win32_clipdrop_atom (clipdrop, GDK_WIN32_ATOM_INDEX_GIF) &&
to_w32format == _gdk_win32_clipdrop_cf (clipdrop, GDK_WIN32_CF_INDEX_GIF)))
{
/* No conversion needed */
*set_data = g_memdup2 (data, length);
*set_data_length = length;
}
else if (from_contentformat == _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_TEXT_PLAIN_UTF8) &&
else if (from_contentformat == _gdk_win32_clipdrop_atom (clipdrop, GDK_WIN32_ATOM_INDEX_TEXT_PLAIN_UTF8) &&
to_w32format == CF_UNICODETEXT)
{
transmute_utf8_string_to_cf_unicodetext (data, length, set_data, set_data_length, NULL);
}
else if (from_contentformat == _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_TEXT_PLAIN_UTF8) &&
else if (from_contentformat == _gdk_win32_clipdrop_atom (clipdrop, GDK_WIN32_ATOM_INDEX_TEXT_PLAIN_UTF8) &&
to_w32format == CF_TEXT)
{
transmute_utf8_string_to_cf_text (data, length, set_data, set_data_length, NULL);
}
else if (from_contentformat == _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_IMAGE_BMP) &&
else if (from_contentformat == _gdk_win32_clipdrop_atom (clipdrop, GDK_WIN32_ATOM_INDEX_IMAGE_BMP) &&
to_w32format == CF_DIB)
{
transmute_image_bmp_to_cf_dib (data, length, set_data, set_data_length, NULL);
}
else if (from_contentformat == _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_IMAGE_BMP) &&
else if (from_contentformat == _gdk_win32_clipdrop_atom (clipdrop, GDK_WIN32_ATOM_INDEX_IMAGE_BMP) &&
to_w32format == CF_DIBV5)
{
transmute_image_bmp_to_cf_dib (data, length, set_data, set_data_length, NULL);
}
/*
else if (from_contentformat == _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_TEXT_URI_LIST) &&
to_w32format == _gdk_win32_clipdrop_cf (GDK_WIN32_CF_INDEX_CFSTR_SHELLIDLIST))
else if (from_contentformat == _gdk_win32_clipdrop_atom (clipdrop, GDK_WIN32_ATOM_INDEX_TEXT_URI_LIST) &&
to_w32format == _gdk_win32_clipdrop_cf (clipdrop, GDK_WIN32_CF_INDEX_CFSTR_SHELLIDLIST))
{
transmute_text_uri_list_to_shell_id_list (data, length, set_data, set_data_length, NULL);
}
@@ -2677,8 +2700,9 @@ _gdk_win32_transmute_contentformat (const char *from_contentformat,
}
int
_gdk_win32_add_contentformat_to_pairs (const char *contentformat,
GArray *array)
_gdk_win32_add_contentformat_to_pairs (GdkWin32Clipdrop *clip_drop,
const char *contentformat,
GArray *array)
{
int added_count = 0;
wchar_t *contentformat_w;
@@ -2723,7 +2747,7 @@ _gdk_win32_add_contentformat_to_pairs (const char *contentformat,
g_array_append_val (array, fmt);
added_count += 1;
comp_pairs = get_compatibility_w32formats_for_contentformat (contentformat);
comp_pairs = get_compatibility_w32formats_for_contentformat (clip_drop, contentformat);
for (i = 0; comp_pairs != NULL && i < comp_pairs->len; i++)
{
int j;
@@ -2747,10 +2771,11 @@ _gdk_win32_add_contentformat_to_pairs (const char *contentformat,
}
void
_gdk_win32_advertise_clipboard_contentformats (GTask *task,
_gdk_win32_advertise_clipboard_contentformats (GdkClipboard *cb,
GTask *task,
GdkContentFormats *contentformats)
{
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
GdkWin32Clipdrop *clipdrop = gdk_win32_display_get_clipdrop (gdk_clipboard_get_display (cb));
GdkWin32ClipboardThreadAdvertise *adv = g_new0 (GdkWin32ClipboardThreadAdvertise, 1);
const char * const *mime_types;
gsize mime_types_len;
@@ -2775,20 +2800,21 @@ _gdk_win32_advertise_clipboard_contentformats (GTask *task,
mime_types = gdk_content_formats_get_mime_types (contentformats, &mime_types_len);
for (i = 0; i < mime_types_len; i++)
_gdk_win32_add_contentformat_to_pairs (mime_types[i], adv->pairs);
_gdk_win32_add_contentformat_to_pairs (clipdrop, mime_types[i], adv->pairs);
}
g_async_queue_push (clipdrop->clipboard_open_thread_queue, adv);
API_CALL (PostMessage, (clipdrop->clipboard_hwnd, thread_wakeup_message, 0, 0));
API_CALL (PostMessage, (clipdrop->clipboard_hwnd, clipdrop->thread_wakeup_message, 0, 0));
return;
}
void
_gdk_win32_retrieve_clipboard_contentformats (GTask *task,
_gdk_win32_retrieve_clipboard_contentformats (GdkClipboard *cb,
GTask *task,
GdkContentFormats *contentformats)
{
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
GdkWin32Clipdrop *clipdrop = gdk_win32_display_get_clipdrop (gdk_clipboard_get_display (cb));
GdkWin32ClipboardThreadRetrieve *retr = g_new0 (GdkWin32ClipboardThreadRetrieve, 1);
const char * const *mime_types;
gsize mime_types_len;
@@ -2806,10 +2832,10 @@ _gdk_win32_retrieve_clipboard_contentformats (GTask *task,
mime_types = gdk_content_formats_get_mime_types (contentformats, &mime_types_len);
for (i = 0; i < mime_types_len; i++)
_gdk_win32_add_contentformat_to_pairs (mime_types[i], retr->pairs);
_gdk_win32_add_contentformat_to_pairs (clipdrop, mime_types[i], retr->pairs);
g_async_queue_push (clipdrop->clipboard_open_thread_queue, retr);
API_CALL (PostMessage, (clipdrop->clipboard_hwnd, thread_wakeup_message, 0, 0));
API_CALL (PostMessage, (clipdrop->clipboard_hwnd, clipdrop->thread_wakeup_message, 0, 0));
return;
}
@@ -2879,7 +2905,7 @@ clipboard_store_hdata_ready (GObject *clipboard,
if (!no_other_streams)
return;
clipdrop = _gdk_win32_clipdrop_get ();
clipdrop = gdk_win32_clipboard_get_clipdrop (GDK_CLIPBOARD (clipboard));
store = g_new0 (GdkWin32ClipboardThreadStore, 1);
@@ -2890,7 +2916,7 @@ clipboard_store_hdata_ready (GObject *clipboard,
store->elements = prep->elements;
g_async_queue_push (clipdrop->clipboard_open_thread_queue, store);
API_CALL (PostMessage, (clipdrop->clipboard_hwnd, thread_wakeup_message, 0, 0));
API_CALL (PostMessage, (clipdrop->clipboard_hwnd, clipdrop->thread_wakeup_message, 0, 0));
g_free (prep);
}
@@ -2904,7 +2930,7 @@ _gdk_win32_store_clipboard_contentformats (GdkClipboard *cb,
const char * const *mime_types;
gsize n_mime_types;
gsize i;
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
GdkWin32Clipdrop *clipdrop = gdk_win32_display_get_clipdrop (gdk_clipboard_get_display (cb));
GdkWin32ClipboardStorePrep *prep;
g_assert (clipdrop->clipboard_hwnd != NULL);
@@ -2917,7 +2943,7 @@ _gdk_win32_store_clipboard_contentformats (GdkClipboard *cb,
n_mime_types);
for (i = 0; i < n_mime_types; i++)
_gdk_win32_add_contentformat_to_pairs (mime_types[i], pairs);
_gdk_win32_add_contentformat_to_pairs (clipdrop, mime_types[i], pairs);
if (pairs->len <= 0)
{
@@ -2935,7 +2961,7 @@ _gdk_win32_store_clipboard_contentformats (GdkClipboard *cb,
GdkWin32ClipboardStorePrepElement el;
GdkWin32ContentFormatPair *pair = &g_array_index (pairs, GdkWin32ContentFormatPair, i);
el.stream = gdk_win32_hdata_output_stream_new (pair, NULL);
el.stream = gdk_win32_hdata_output_stream_new (clipdrop, pair, NULL);
if (!el.stream)
continue;

View File

@@ -22,11 +22,10 @@
G_BEGIN_DECLS
#define _gdk_win32_clipdrop_get() (_win32_clipdrop)
#define _gdk_atom_array_index(a, i) (g_array_index (a, const char *, i))
#define _gdk_win32_clipdrop_atom(i) (_gdk_atom_array_index (_gdk_win32_clipdrop_get ()->known_atoms, i))
#define _gdk_win32_clipdrop_atom(c, i) (_gdk_atom_array_index (c->known_atoms, i))
#define _gdk_cf_array_index(a, i) (g_array_index (a, UINT, i))
#define _gdk_win32_clipdrop_cf(i) (_gdk_cf_array_index (_gdk_win32_clipdrop_get ()->known_clipboard_formats, i))
#define _gdk_win32_clipdrop_cf(c,i) (_gdk_cf_array_index (c->known_clipboard_formats, i))
/* Maps GDK contentformats to w32formats or vice versa, depending on the
* semantics of the array that holds these.
@@ -114,6 +113,15 @@ typedef enum _GdkWin32CFIndex GdkWin32CFIndex;
typedef struct _GdkWin32Clipdrop GdkWin32Clipdrop;
typedef struct _GdkWin32ClipdropClass GdkWin32ClipdropClass;
/* this is shared with gdkdrag-win32.c as well */
struct _clipdrop_thread_items
{
GdkWin32Clipdrop *clipdrop;
GAsyncQueue *queue;
};
typedef struct _clipdrop_thread_items clipdrop_thread_items;
typedef BOOL (WINAPI * GetUpdatedClipboardFormatsFunc)(
_Out_ PUINT lpuiFormats,
_In_ UINT cFormats,
@@ -224,6 +232,15 @@ struct _GdkWin32Clipdrop
* dnd thread is not active.
*/
GHashTable *active_source_drags;
/* our custom MSG UINT that we register once to prcoess DND/Clipbord actions */
UINT thread_wakeup_message;
/* this is a GdkWin32ClipboardThread structure */
void *clipboard_thread_items;
/* this is a GdkWin32DndThread structure */
void *dnd_thread_items;
};
struct _GdkWin32ClipdropClass
@@ -233,44 +250,46 @@ struct _GdkWin32ClipdropClass
GType gdk_win32_clipdrop_get_type (void) G_GNUC_CONST;
void _gdk_win32_clipdrop_init (void);
gboolean _gdk_win32_format_uses_hdata (UINT w32format);
char * _gdk_win32_get_clipboard_format_name (UINT fmt,
gboolean *is_predefined);
void _gdk_win32_add_w32format_to_pairs (UINT format,
GArray *array,
GdkContentFormatsBuilder *builder);
int _gdk_win32_add_contentformat_to_pairs (const char *target,
int _gdk_win32_add_contentformat_to_pairs (GdkWin32Clipdrop *clip_drop,
const char *target,
GArray *array);
void _gdk_win32_clipboard_default_output_done (GObject *clipboard,
GAsyncResult *result,
gpointer user_data);
gboolean _gdk_win32_transmute_contentformat (const char *from_contentformat,
gboolean gdk_win32_clipdrop_transmute_contentformat (GdkWin32Clipdrop *clipdrop,
const char *from_contentformat,
UINT to_w32format,
const guchar *data,
gsize length,
guchar **set_data,
gsize *set_data_length);
gboolean _gdk_win32_transmute_windows_data (UINT from_w32format,
const char *to_contentformat,
HANDLE hdata,
guchar **set_data,
gsize *set_data_length);
gboolean gdk_win32_clipdrop_transmute_windows_data (GdkWin32Clipdrop *clipdrop,
UINT from_w32format,
const char *to_contentformat,
HANDLE hdata,
guchar **set_data,
gsize *set_data_length);
gboolean _gdk_win32_store_clipboard_contentformats (GdkClipboard *cb,
GTask *task,
GdkContentFormats *contentformats);
void _gdk_win32_retrieve_clipboard_contentformats (GTask *task,
void _gdk_win32_retrieve_clipboard_contentformats (GdkClipboard *cb,
GTask *task,
GdkContentFormats *contentformats);
void _gdk_win32_advertise_clipboard_contentformats (GTask *task,
void _gdk_win32_advertise_clipboard_contentformats (GdkClipboard *cb,
GTask *task,
GdkContentFormats *contentformats);
void gdk_win32_clipdrop_add_win32_format_to_pairs (GdkWin32Clipdrop *clipdrop,
UINT format,
GArray *array,
GdkContentFormatsBuilder *builder);

View File

@@ -75,6 +75,7 @@ gdk_device_win32_query_state (GdkDevice *device,
POINT point;
HWND hwnd, hwndc;
int scale;
GdkDisplay *display = gdk_device_get_display (device);
if (surface)
{
@@ -83,13 +84,11 @@ gdk_device_win32_query_state (GdkDevice *device,
}
else
{
GdkDisplay *display = gdk_device_get_display (device);
scale = GDK_WIN32_DISPLAY (display)->surface_scale;
hwnd = NULL;
}
_gdk_win32_get_cursor_pos (&point);
_gdk_win32_get_cursor_pos (display, &point);
if (hwnd)
ScreenToClient (hwnd, &point);
@@ -105,7 +104,7 @@ gdk_device_win32_query_state (GdkDevice *device,
hwndc = ChildWindowFromPoint (hwnd, point);
if (hwndc && hwndc != hwnd)
*child_surface = gdk_win32_handle_table_lookup_ (hwndc);
*child_surface = gdk_win32_display_handle_table_lookup_ (display, hwndc);
else
*child_surface = NULL; /* Direct child unknown to gdk */
}
@@ -167,8 +166,9 @@ _gdk_device_win32_surface_at_position (GdkDevice *device,
POINT screen_pt, client_pt;
HWND hwnd;
RECT rect;
GdkDisplay *display = gdk_device_get_display (device);
if (!_gdk_win32_get_cursor_pos (&screen_pt))
if (!_gdk_win32_get_cursor_pos (display, &screen_pt))
return NULL;
/* Use WindowFromPoint instead of ChildWindowFromPoint(Ex).
@@ -183,7 +183,7 @@ _gdk_device_win32_surface_at_position (GdkDevice *device,
if (!PtInRect (&rect, client_pt))
hwnd = NULL;
surface = gdk_win32_handle_table_lookup_ (hwnd);
surface = gdk_win32_display_handle_table_lookup_ (display, hwnd);
if (surface && (win_x || win_y))
{

View File

@@ -65,6 +65,7 @@ gdk_device_winpointer_query_state (GdkDevice *device,
POINT point;
HWND hwnd, hwndc;
int scale;
GdkDisplay *display = gdk_device_get_display (device);
device_winpointer = GDK_DEVICE_WINPOINTER (device);
if (surface)
@@ -74,13 +75,11 @@ gdk_device_winpointer_query_state (GdkDevice *device,
}
else
{
GdkDisplay *display = gdk_device_get_display (device);
scale = GDK_WIN32_DISPLAY (display)->surface_scale;
hwnd = NULL;
}
_gdk_win32_get_cursor_pos (&point);
_gdk_win32_get_cursor_pos (display, &point);
if (hwnd)
ScreenToClient (hwnd, &point);
@@ -96,7 +95,7 @@ gdk_device_winpointer_query_state (GdkDevice *device,
hwndc = ChildWindowFromPoint (hwnd, point);
if (hwndc && hwndc != hwnd)
*child_surface = gdk_win32_handle_table_lookup_ (hwndc);
*child_surface = gdk_win32_display_handle_table_lookup_ (display, hwndc);
else
*child_surface = NULL; /* Direct child unknown to gdk */
}
@@ -144,8 +143,9 @@ gdk_device_winpointer_surface_at_position (GdkDevice *device,
POINT screen_pt, client_pt;
HWND hwnd;
RECT rect;
GdkDisplay *display = gdk_device_get_display (device);
if (!_gdk_win32_get_cursor_pos (&screen_pt))
if (!_gdk_win32_get_cursor_pos (display, &screen_pt))
return NULL;
/* Use WindowFromPoint instead of ChildWindowFromPoint(Ex).
@@ -160,7 +160,7 @@ gdk_device_winpointer_surface_at_position (GdkDevice *device,
if (!PtInRect (&rect, client_pt))
hwnd = NULL;
surface = gdk_win32_handle_table_lookup_ (hwnd);
surface = gdk_win32_display_handle_table_lookup_ (display, hwnd);
if (surface && (win_x || win_y))
{

View File

@@ -73,6 +73,7 @@ gdk_device_wintab_query_state (GdkDevice *device,
POINT point;
HWND hwnd, hwndc;
int scale;
GdkDisplay *display = gdk_device_get_display (device);
device_wintab = GDK_DEVICE_WINTAB (device);
if (surface)
@@ -82,13 +83,11 @@ gdk_device_wintab_query_state (GdkDevice *device,
}
else
{
GdkDisplay *display = gdk_device_get_display (device);
scale = GDK_WIN32_DISPLAY (display)->surface_scale;
hwnd = NULL;
}
_gdk_win32_get_cursor_pos (&point);
_gdk_win32_get_cursor_pos (display, &point);
if (hwnd)
ScreenToClient (hwnd, &point);
@@ -104,7 +103,7 @@ gdk_device_wintab_query_state (GdkDevice *device,
hwndc = ChildWindowFromPoint (hwnd, point);
if (hwndc && hwndc != hwnd)
*child_surface = gdk_win32_handle_table_lookup_ (hwndc);
*child_surface = gdk_win32_display_handle_table_lookup_ (display, hwndc);
else
*child_surface = NULL; /* Direct child unknown to gdk */
}

View File

@@ -45,11 +45,6 @@
#define DEBUG_WINTAB 1 /* Verbose debug messages enabled */
#define TWOPI (2 * G_PI)
/* TODO: get rid of these global variables */
static GList *wintab_contexts = NULL;
static GdkSurface *wintab_surface = NULL;
extern int _gdk_input_ignore_core;
typedef UINT (WINAPI *t_WTInfoA) (UINT a, UINT b, LPVOID c);
typedef UINT (WINAPI *t_WTInfoW) (UINT a, UINT b, LPVOID c);
typedef BOOL (WINAPI *t_WTEnable) (HCTX a, BOOL b);
@@ -60,22 +55,39 @@ typedef BOOL (WINAPI *t_WTOverlap) (HCTX a, BOOL b);
typedef BOOL (WINAPI *t_WTPacket) (HCTX a, UINT b, LPVOID c);
typedef int (WINAPI *t_WTQueueSizeSet) (HCTX a, int b);
static t_WTInfoA p_WTInfoA;
static t_WTInfoW p_WTInfoW;
static t_WTEnable p_WTEnable;
static t_WTOpenA p_WTOpenA;
static t_WTGetA p_WTGetA;
static t_WTSetA p_WTSetA;
static t_WTOverlap p_WTOverlap;
static t_WTPacket p_WTPacket;
struct _wintab_items
{
GList *wintab_contexts;
GdkSurface *wintab_surface;
HMODULE wintab32;
t_WTInfoA p_WTInfoA;
t_WTInfoW p_WTInfoW;
t_WTEnable p_WTEnable;
t_WTOpenA p_WTOpenA;
t_WTGetA p_WTGetA;
t_WTSetA p_WTSetA;
t_WTOverlap p_WTOverlap;
t_WTPacket p_WTPacket;
t_WTQueueSizeSet p_WTQueueSizeSet;
};
static t_WTQueueSizeSet p_WTQueueSizeSet;
static gboolean default_display_opened = FALSE;
G_DEFINE_TYPE (GdkDeviceManagerWin32, gdk_device_manager_win32, G_TYPE_OBJECT)
enum {
PROP_0,
PROP_DISPLAY,
LAST_PROP
};
static GParamSpec *device_manager_props[LAST_PROP] = { NULL, };
static GdkDevice *
create_pointer (GdkDeviceManagerWin32 *device_manager,
create_pointer (GdkDisplay *display,
GType g_type,
const char *name,
gboolean has_cursor)
@@ -84,12 +96,12 @@ create_pointer (GdkDeviceManagerWin32 *device_manager,
"name", name,
"source", GDK_SOURCE_MOUSE,
"has-cursor", has_cursor,
"display", _gdk_display,
"display", display,
NULL);
}
static GdkDevice *
create_keyboard (GdkDeviceManagerWin32 *device_manager,
create_keyboard (GdkDisplay *display,
GType g_type,
const char *name)
{
@@ -97,7 +109,7 @@ create_keyboard (GdkDeviceManagerWin32 *device_manager,
"name", name,
"source", GDK_SOURCE_KEYBOARD,
"has-cursor", FALSE,
"display", _gdk_display,
"display", display,
NULL);
}
@@ -113,6 +125,38 @@ gdk_device_manager_win32_finalize (GObject *object)
device_manager_win32 = GDK_DEVICE_MANAGER_WIN32 (object);
if (device_manager_win32->ignored_interactions != NULL)
{
g_ptr_array_free (device_manager_win32->ignored_interactions, FALSE);
device_manager_win32->ignored_interactions = NULL;
}
g_clear_pointer (&device_manager_win32->winpointer_funcs, g_free);
/* Sadly, no g_clear_pointer() on DestroyWindow() as it is __stdcall */
if (device_manager_win32->winpointer_notification_hwnd != NULL)
{
DestroyWindow (device_manager_win32->winpointer_notification_hwnd);
device_manager_win32->winpointer_notification_hwnd = NULL;
}
if (device_manager_win32->wintab_items)
{
if (device_manager_win32->wintab_items->wintab_contexts)
{
g_list_free_full (device_manager_win32->wintab_items->wintab_contexts, g_free);
device_manager_win32->wintab_items->wintab_contexts = NULL;
}
g_clear_pointer (&device_manager_win32->wintab_items->wintab_surface, g_object_unref);
if (device_manager_win32->wintab_items->wintab32 != NULL)
{
FreeLibrary (device_manager_win32->wintab_items->wintab32);
device_manager_win32->wintab_items->wintab32 = NULL;
}
g_clear_pointer (&device_manager_win32->wintab_items, g_free);
}
g_object_unref (device_manager_win32->core_pointer);
g_object_unref (device_manager_win32->core_keyboard);
@@ -215,8 +259,13 @@ print_lc(LOGCONTEXTA *lc)
lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.);
}
#define WINTAB_API_CHECK(device_manager,f)\
((device_manager->wintab_items->p_##f = (t_##f) GetProcAddress (device_manager->wintab_items->wintab32, "##f##")) != NULL)
#define WINTAB_API_CALL(device_manager,f) device_manager->wintab_items->p_##f
static void
print_cursor (int index)
print_cursor (GdkDeviceManagerWin32 *device_manager,
int index)
{
int size;
int i;
@@ -241,13 +290,13 @@ print_cursor (int index)
UINT minbuttons;
UINT capabilities;
size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_NAME, NULL);
size = WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_NAME, NULL);
name = g_malloc (size + 1);
(*p_WTInfoA) (WTI_CURSORS + index, CSR_NAME, name);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_NAME, name);
g_print ("NAME: %s\n", name);
(*p_WTInfoA) (WTI_CURSORS + index, CSR_ACTIVE, &active);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_ACTIVE, &active);
g_print ("ACTIVE: %s\n", active ? "YES" : "NO");
(*p_WTInfoA) (WTI_CURSORS + index, CSR_PKTDATA, &wtpkt);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_PKTDATA, &wtpkt);
g_print ("PKTDATA: %#x:", (guint) wtpkt);
#define BIT(x) if (wtpkt & PK_##x) g_print (" " #x)
BIT (CONTEXT);
@@ -265,16 +314,16 @@ print_cursor (int index)
BIT (ROTATION);
#undef BIT
g_print ("\n");
(*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONS, &buttons);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_BUTTONS, &buttons);
g_print ("BUTTONS: %d\n", buttons);
(*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONBITS, &buttonbits);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_BUTTONBITS, &buttonbits);
g_print ("BUTTONBITS: %d\n", buttonbits);
size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_BTNNAMES, NULL);
size = WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_BTNNAMES, NULL);
g_print ("BTNNAMES:");
if (size > 0)
{
btnnames = g_malloc (size + 1);
(*p_WTInfoA) (WTI_CURSORS + index, CSR_BTNNAMES, btnnames);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_BTNNAMES, btnnames);
p = btnnames;
while (*p)
{
@@ -283,47 +332,47 @@ print_cursor (int index)
}
}
g_print ("\n");
(*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONMAP, buttonmap);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_BUTTONMAP, buttonmap);
g_print ("BUTTONMAP:");
for (i = 0; i < buttons; i++)
g_print (" %d", buttonmap[i]);
g_print ("\n");
(*p_WTInfoA) (WTI_CURSORS + index, CSR_SYSBTNMAP, sysbtnmap);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_SYSBTNMAP, sysbtnmap);
g_print ("SYSBTNMAP:");
for (i = 0; i < buttons; i++)
g_print (" %d", sysbtnmap[i]);
g_print ("\n");
(*p_WTInfoA) (WTI_CURSORS + index, CSR_NPBUTTON, &npbutton);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_NPBUTTON, &npbutton);
g_print ("NPBUTTON: %d\n", npbutton);
(*p_WTInfoA) (WTI_CURSORS + index, CSR_NPBTNMARKS, npbtnmarks);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_NPBTNMARKS, npbtnmarks);
g_print ("NPBTNMARKS: %d %d\n", npbtnmarks[0], npbtnmarks[1]);
size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPRESPONSE, NULL);
size = WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_NPRESPONSE, NULL);
g_print ("NPRESPONSE:");
if (size > 0)
{
npresponse = g_malloc (size);
(*p_WTInfoA) (WTI_CURSORS + index, CSR_NPRESPONSE, npresponse);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_NPRESPONSE, npresponse);
for (i = 0; i < size / sizeof (UINT); i++)
g_print (" %d", npresponse[i]);
}
g_print ("\n");
(*p_WTInfoA) (WTI_CURSORS + index, CSR_TPBUTTON, &tpbutton);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_TPBUTTON, &tpbutton);
g_print ("TPBUTTON: %d\n", tpbutton);
(*p_WTInfoA) (WTI_CURSORS + index, CSR_TPBTNMARKS, tpbtnmarks);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_TPBTNMARKS, tpbtnmarks);
g_print ("TPBTNMARKS: %d %d\n", tpbtnmarks[0], tpbtnmarks[1]);
size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPRESPONSE, NULL);
size = WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_TPRESPONSE, NULL);
g_print ("TPRESPONSE:");
if (size > 0)
{
tpresponse = g_malloc (size);
(*p_WTInfoA) (WTI_CURSORS + index, CSR_TPRESPONSE, tpresponse);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_TPRESPONSE, tpresponse);
for (i = 0; i < size / sizeof (UINT); i++)
g_print (" %d", tpresponse[i]);
}
g_print ("\n");
(*p_WTInfoA) (WTI_CURSORS + index, CSR_PHYSID, &physid);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_PHYSID, &physid);
g_print ("PHYSID: %#x\n", (guint) physid);
(*p_WTInfoA) (WTI_CURSORS + index, CSR_CAPABILITIES, &capabilities);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_CAPABILITIES, &capabilities);
g_print ("CAPABILITIES: %#x:", capabilities);
#define BIT(x) if (capabilities & CRC_##x) g_print (" " #x)
BIT (MULTIMODE);
@@ -333,14 +382,14 @@ print_cursor (int index)
g_print ("\n");
if (capabilities & CRC_MULTIMODE)
{
(*p_WTInfoA) (WTI_CURSORS + index, CSR_MODE, &mode);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_MODE, &mode);
g_print ("MODE: %d\n", mode);
}
if (capabilities & CRC_AGGREGATE)
{
(*p_WTInfoA) (WTI_CURSORS + index, CSR_MINPKTDATA, &minpktdata);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_MINPKTDATA, &minpktdata);
g_print ("MINPKTDATA: %d\n", minpktdata);
(*p_WTInfoA) (WTI_CURSORS + index, CSR_MINBUTTONS, &minbuttons);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + index, CSR_MINBUTTONS, &minbuttons);
g_print ("MINBUTTONS: %d\n", minbuttons);
}
}
@@ -373,7 +422,8 @@ wintab_init_check (GdkDeviceManagerWin32 *device_manager)
wintab_initialized = TRUE;
wintab_contexts = NULL;
device_manager->wintab_items = g_new0 (wintab_items, 1);
device_manager->wintab_items->wintab_contexts = NULL;
n = GetSystemDirectoryA (&dummy, 0);
@@ -396,41 +446,35 @@ wintab_init_check (GdkDeviceManagerWin32 *device_manager)
if ((wintab32 = LoadLibraryA (wintab32_dll_path)) == NULL)
return;
if ((p_WTInfoA = (t_WTInfoA) GetProcAddress (wintab32, "WTInfoA")) == NULL)
return;
if ((p_WTInfoW = (t_WTInfoW) GetProcAddress (wintab32, "WTInfoW")) == NULL)
return;
if ((p_WTEnable = (t_WTEnable) GetProcAddress (wintab32, "WTEnable")) == NULL)
return;
if ((p_WTOpenA = (t_WTOpenA) GetProcAddress (wintab32, "WTOpenA")) == NULL)
return;
if ((p_WTGetA = (t_WTGetA) GetProcAddress (wintab32, "WTGetA")) == NULL)
return;
if ((p_WTSetA = (t_WTSetA) GetProcAddress (wintab32, "WTSetA")) == NULL)
return;
if ((p_WTOverlap = (t_WTOverlap) GetProcAddress (wintab32, "WTOverlap")) == NULL)
return;
if ((p_WTPacket = (t_WTPacket) GetProcAddress (wintab32, "WTPacket")) == NULL)
return;
if ((p_WTQueueSizeSet = (t_WTQueueSizeSet) GetProcAddress (wintab32, "WTQueueSizeSet")) == NULL)
device_manager->wintab_items->wintab32 = wintab32;
if (!WINTAB_API_CHECK (device_manager, WTInfoA) ||
!WINTAB_API_CHECK (device_manager, WTInfoW) ||
!WINTAB_API_CHECK (device_manager, WTEnable) ||
!WINTAB_API_CHECK (device_manager, WTOpenA) ||
!WINTAB_API_CHECK (device_manager, WTGetA) ||
!WINTAB_API_CHECK (device_manager, WTSetA) ||
!WINTAB_API_CHECK (device_manager, WTOverlap) ||
!WINTAB_API_CHECK (device_manager, WTPacket) ||
!WINTAB_API_CHECK (device_manager, WTQueueSizeSet))
return;
if (!(*p_WTInfoA) (0, 0, NULL))
if (!WINTAB_API_CALL (device_manager, WTInfoA) (0, 0, NULL))
return;
(*p_WTInfoA) (WTI_INTERFACE, IFC_SPECVERSION, &specversion);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_INTERFACE, IFC_SPECVERSION, &specversion);
GDK_NOTE (INPUT, g_print ("Wintab interface version %d.%d\n",
HIBYTE (specversion), LOBYTE (specversion)));
(*p_WTInfoA) (WTI_INTERFACE, IFC_NDEVICES, &ndevices);
(*p_WTInfoA) (WTI_INTERFACE, IFC_NCURSORS, &ncursors);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_INTERFACE, IFC_NDEVICES, &ndevices);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_INTERFACE, IFC_NCURSORS, &ncursors);
#if DEBUG_WINTAB
GDK_NOTE (INPUT, g_print ("NDEVICES: %d, NCURSORS: %d\n",
ndevices, ncursors));
#endif
/* Create a dummy surface to receive wintab events */
wintab_surface = gdk_win32_drag_surface_new (display);
device_manager->wintab_items->wintab_surface = gdk_win32_drag_surface_new (display);
g_object_ref (wintab_surface);
g_object_ref (device_manager->wintab_items->wintab_surface);
for (devix = 0; devix < ndevices; devix++)
{
@@ -442,25 +486,25 @@ wintab_init_check (GdkDeviceManagerWin32 *device_manager)
* cursor. This seems much more natural.
*/
(*p_WTInfoW) (WTI_DEVICES + devix, DVC_NAME, devname);
WINTAB_API_CALL (device_manager, WTInfoW) (WTI_DEVICES + devix, DVC_NAME, devname);
devname_utf8 = g_utf16_to_utf8 (devname, -1, NULL, NULL, NULL);
#ifdef DEBUG_WINTAB
GDK_NOTE (INPUT, (g_print("Device %u: %s\n", devix, devname_utf8)));
#endif
(*p_WTInfoA) (WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes);
(*p_WTInfoA) (WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr);
(*p_WTInfoA) (WTI_DEVICES + devix, DVC_HARDWARE, &hardware);
(*p_WTInfoA) (WTI_DEVICES + devix, DVC_X, &axis_x);
(*p_WTInfoA) (WTI_DEVICES + devix, DVC_Y, &axis_y);
(*p_WTInfoA) (WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure);
(*p_WTInfoA) (WTI_DEVICES + devix, DVC_ORIENTATION, axis_or);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_DEVICES + devix, DVC_HARDWARE, &hardware);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_DEVICES + devix, DVC_X, &axis_x);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_DEVICES + devix, DVC_Y, &axis_y);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_DEVICES + devix, DVC_ORIENTATION, axis_or);
defcontext_done = FALSE;
if (HIBYTE (specversion) > 1 || LOBYTE (specversion) >= 1)
{
/* Try to get device-specific default context */
/* Some drivers, e.g. Aiptek, don't provide this info */
if ((*p_WTInfoA) (WTI_DSCTXS + devix, 0, &lc) > 0)
if (WINTAB_API_CALL (device_manager, WTInfoA) (WTI_DSCTXS + devix, 0, &lc) > 0)
defcontext_done = TRUE;
#if DEBUG_WINTAB
if (defcontext_done)
@@ -471,7 +515,7 @@ wintab_init_check (GdkDeviceManagerWin32 *device_manager)
}
if (!defcontext_done)
(*p_WTInfoA) (WTI_DEFSYSCTX, 0, &lc);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_DEFSYSCTX, 0, &lc);
#if DEBUG_WINTAB
GDK_NOTE (INPUT, (g_print("Default context:\n"), print_lc(&lc)));
#endif
@@ -493,7 +537,10 @@ wintab_init_check (GdkDeviceManagerWin32 *device_manager)
print_lc(&lc)));
#endif
hctx = g_new (HCTX, 1);
if ((*hctx = (*p_WTOpenA) (GDK_SURFACE_HWND (wintab_surface), &lc, TRUE)) == NULL)
if ((*hctx =
WINTAB_API_CALL (device_manager, WTOpenA) (GDK_SURFACE_HWND (device_manager->wintab_items->wintab_surface),
&lc,
TRUE)) == NULL)
{
g_warning ("gdk_input_wintab_init: WTOpen failed");
return;
@@ -501,11 +548,12 @@ wintab_init_check (GdkDeviceManagerWin32 *device_manager)
GDK_NOTE (INPUT, g_print ("opened Wintab device %u %p\n",
devix, *hctx));
wintab_contexts = g_list_append (wintab_contexts, hctx);
device_manager->wintab_items->wintab_contexts =
g_list_append (device_manager->wintab_items->wintab_contexts, hctx);
#if 0
(*p_WTEnable) (*hctx, TRUE);
WINTAB_API_CALL (device_manager, WTEnable) (*hctx, TRUE);
#endif
(*p_WTOverlap) (*hctx, TRUE);
WINTAB_API_CALL (device_manager, WTOverlap) (*hctx, TRUE);
#if DEBUG_WINTAB
GDK_NOTE (INPUT, (g_print("context for device %u after WTOpen:\n", devix),
@@ -518,7 +566,7 @@ wintab_init_check (GdkDeviceManagerWin32 *device_manager)
GDK_NOTE (INPUT, g_print("Attempting to increase queue size\n"));
for (i = 128; i >= 1; i >>= 1)
{
if ((*p_WTQueueSizeSet) (*hctx, i))
if (WINTAB_API_CALL (device_manager, WTQueueSizeSet) (*hctx, i))
{
GDK_NOTE (INPUT, g_print("Queue size set to %d\n", i));
break;
@@ -529,10 +577,10 @@ wintab_init_check (GdkDeviceManagerWin32 *device_manager)
for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes; cursorix++)
{
#ifdef DEBUG_WINTAB
GDK_NOTE (INPUT, (g_print("Cursor %u:\n", cursorix), print_cursor (cursorix)));
GDK_NOTE (INPUT, (g_print("Cursor %u:\n", cursorix), print_cursor (device_manager, cursorix)));
#endif
active = FALSE;
(*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
if (!active)
continue;
@@ -544,11 +592,11 @@ wintab_init_check (GdkDeviceManagerWin32 *device_manager)
* second instances of the styluses report physid zero. So
* at least for Wacom, skip cursors with physid zero.
*/
(*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_PHYSID, &physid);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + cursorix, CSR_PHYSID, &physid);
if (wcscmp (devname, L"WACOM Tablet") == 0 && physid == 0)
continue;
(*p_WTInfoW) (WTI_CURSORS + cursorix, CSR_NAME, csrname);
WINTAB_API_CALL (device_manager, WTInfoW) (WTI_CURSORS + cursorix, CSR_NAME, csrname);
csrname_utf8 = g_utf16_to_utf8 (csrname, -1, NULL, NULL, NULL);
device_name = g_strconcat (devname_utf8, " ", csrname_utf8, NULL);
@@ -570,7 +618,7 @@ wintab_init_check (GdkDeviceManagerWin32 *device_manager)
device->hctx = *hctx;
device->cursor = cursorix;
(*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_PKTDATA, &device->pktdata);
WINTAB_API_CALL (device_manager, WTInfoA) (WTI_CURSORS + cursorix, CSR_PKTDATA, &device->pktdata);
if (device->pktdata & PK_X)
{
@@ -670,7 +718,7 @@ wintab_default_display_notify_cb (GdkDisplayManager *display_manager)
g_assert (display != NULL);
device_manager = GDK_DEVICE_MANAGER_WIN32 (_gdk_device_manager);
device_manager = GDK_WIN32_DISPLAY (display)->device_manager;
g_assert (display_manager != NULL);
default_display_opened = TRUE;
@@ -687,16 +735,16 @@ gdk_device_manager_win32_constructed (GObject *object)
const char *api_preference = NULL;
gboolean have_api_preference = TRUE;
display_win32 = GDK_WIN32_DISPLAY (_gdk_display);
device_manager = GDK_DEVICE_MANAGER_WIN32 (object);
display_win32 = GDK_WIN32_DISPLAY (device_manager->display);
device_manager->core_pointer =
create_pointer (device_manager,
create_pointer (device_manager->display,
GDK_TYPE_DEVICE_VIRTUAL,
"Virtual Core Pointer",
TRUE);
device_manager->system_pointer =
create_pointer (device_manager,
create_pointer (device_manager->display,
GDK_TYPE_DEVICE_WIN32,
"System Aggregated Pointer",
FALSE);
@@ -706,11 +754,11 @@ gdk_device_manager_win32_constructed (GObject *object)
_gdk_device_add_physical_device (device_manager->core_pointer, device_manager->system_pointer);
device_manager->core_keyboard =
create_keyboard (device_manager,
create_keyboard (device_manager->display,
GDK_TYPE_DEVICE_VIRTUAL,
"Virtual Core Keyboard");
device_manager->system_keyboard =
create_keyboard (device_manager,
create_keyboard (device_manager->display,
GDK_TYPE_DEVICE_WIN32,
"System Aggregated Keyboard");
_gdk_device_virtual_set_active (device_manager->core_keyboard,
@@ -723,12 +771,12 @@ gdk_device_manager_win32_constructed (GObject *object)
seat = gdk_seat_default_new_for_logical_pair (device_manager->core_pointer,
device_manager->core_keyboard);
gdk_display_add_seat (_gdk_display, seat);
gdk_display_add_seat (device_manager->display, seat);
gdk_seat_default_add_physical_device (GDK_SEAT_DEFAULT (seat), device_manager->system_pointer);
gdk_seat_default_add_physical_device (GDK_SEAT_DEFAULT (seat), device_manager->system_keyboard);
g_object_unref (seat);
_gdk_device_manager = device_manager;
display_win32->device_manager = device_manager;
api_preference = g_getenv ("GDK_WIN32_TABLET_INPUT_API");
if (g_strcmp0 (api_preference, "none") == 0)
@@ -754,7 +802,7 @@ gdk_device_manager_win32_constructed (GObject *object)
if (display_win32->tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINPOINTER)
{
gboolean init_successful = gdk_winpointer_initialize ();
gboolean init_successful = gdk_winpointer_initialize (device_manager);
if (!init_successful && !have_api_preference)
{
@@ -783,6 +831,44 @@ gdk_device_manager_win32_constructed (GObject *object)
}
}
static void
gdk_device_manager_win32_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdkDeviceManagerWin32 *device_manager = GDK_DEVICE_MANAGER_WIN32 (object);
switch (prop_id)
{
case PROP_DISPLAY:
g_value_set_object (value, device_manager->display);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdk_device_manager_win32_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GdkDeviceManagerWin32 *device_manager = GDK_DEVICE_MANAGER_WIN32 (object);
switch (prop_id)
{
case PROP_DISPLAY:
device_manager->display = g_value_get_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdk_device_manager_win32_class_init (GdkDeviceManagerWin32Class *klass)
{
@@ -790,10 +876,19 @@ gdk_device_manager_win32_class_init (GdkDeviceManagerWin32Class *klass)
object_class->finalize = gdk_device_manager_win32_finalize;
object_class->constructed = gdk_device_manager_win32_constructed;
object_class->set_property = gdk_device_manager_win32_set_property;
object_class->get_property = gdk_device_manager_win32_get_property;
device_manager_props[PROP_DISPLAY] =
g_param_spec_object ("display", NULL, NULL,
GDK_TYPE_DISPLAY,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, LAST_PROP, device_manager_props);
}
void
_gdk_wintab_set_tablet_active (void)
_gdk_wintab_set_tablet_active (GdkDeviceManagerWin32 *device_manager)
{
GList *tmp_list;
HCTX *hctx;
@@ -801,18 +896,18 @@ _gdk_wintab_set_tablet_active (void)
/* Bring the contexts to the top of the overlap order when one of the
* application's HWNDs is activated */
if (!wintab_contexts)
if (!device_manager->wintab_items->wintab_contexts)
return; /* No tablet devices found, or Wintab not initialized yet */
GDK_NOTE (INPUT, g_print ("_gdk_wintab_set_tablet_active: "
"Bringing Wintab contexts to the top of the overlap order\n"));
tmp_list = wintab_contexts;
tmp_list = device_manager->wintab_items->wintab_contexts;
while (tmp_list)
{
hctx = (HCTX *) (tmp_list->data);
(*p_WTOverlap) (*hctx, TRUE);
WINTAB_API_CALL (device_manager, WTOverlap) (*hctx, TRUE);
tmp_list = tmp_list->next;
}
}
@@ -933,13 +1028,13 @@ gdk_wintab_make_event (GdkDisplay *display,
*/
static guint button_map[8] = {0, 1, 4, 5, 2, 3, 6, 7};
if (surface != wintab_surface)
device_manager = GDK_WIN32_DISPLAY (display)->device_manager;
if (surface != device_manager->wintab_items->wintab_surface)
{
g_warning ("gdk_wintab_make_event: not wintab_surface?");
return NULL;
}
device_manager = GDK_DEVICE_MANAGER_WIN32 (_gdk_device_manager);
surface = gdk_device_get_surface_at_position (device_manager->core_pointer, &x, &y);
if (surface)
@@ -951,7 +1046,7 @@ gdk_wintab_make_event (GdkDisplay *display,
if (msg->message == WT_PACKET || msg->message == WT_CSRCHANGE)
{
if (!(*p_WTPacket) ((HCTX) msg->lParam, msg->wParam, &packet))
if (!WINTAB_API_CALL (device_manager, WTPacket) ((HCTX) msg->lParam, msg->wParam, &packet))
return NULL;
}
@@ -976,12 +1071,12 @@ gdk_wintab_make_event (GdkDisplay *display,
{
_gdk_device_virtual_set_active (device_manager->core_pointer,
GDK_DEVICE (source_device));
_gdk_input_ignore_core += 1;
GDK_WIN32_DISPLAY (display)->pointer_device_items->input_ignore_core += 1;
}
}
else if (source_device != NULL &&
source_device->sends_core &&
_gdk_input_ignore_core == 0)
GDK_WIN32_DISPLAY (display)->pointer_device_items->input_ignore_core == 0)
{
/* A fallback for cases when two devices (disabled and enabled)
* were in proximity simultaneously.
@@ -997,7 +1092,7 @@ gdk_wintab_make_event (GdkDisplay *display,
*/
_gdk_device_virtual_set_active (device_manager->core_pointer,
GDK_DEVICE (source_device));
_gdk_input_ignore_core += 1;
GDK_WIN32_DISPLAY (display)->pointer_device_items->input_ignore_core += 1;
}
if (source_device == NULL)
@@ -1006,7 +1101,7 @@ gdk_wintab_make_event (GdkDisplay *display,
/* Don't produce any button or motion events while a surface is being
* moved or resized, see bug #151090.
*/
if (_modal_operation_in_progress & GDK_WIN32_MODAL_OP_SIZEMOVE_MASK)
if (GDK_WIN32_DISPLAY (display)->display_surface_record->modal_operation_in_progress & GDK_WIN32_MODAL_OP_SIZEMOVE_MASK)
{
GDK_NOTE (EVENTS_OR_INPUT, g_print ("... ignored when moving/sizing\n"));
return NULL;
@@ -1160,7 +1255,7 @@ gdk_wintab_make_event (GdkDisplay *display,
{
_gdk_device_virtual_set_active (device_manager->core_pointer,
GDK_DEVICE (source_device));
_gdk_input_ignore_core += 1;
GDK_WIN32_DISPLAY (display)->pointer_device_items->input_ignore_core += 1;
}
return NULL;
@@ -1168,11 +1263,11 @@ gdk_wintab_make_event (GdkDisplay *display,
case WT_PROXIMITY:
if (LOWORD (msg->lParam) == 0)
{
if (_gdk_input_ignore_core > 0)
if (GDK_WIN32_DISPLAY (display)->pointer_device_items->input_ignore_core > 0)
{
_gdk_input_ignore_core -= 1;
GDK_WIN32_DISPLAY (display)->pointer_device_items->input_ignore_core -= 1;
if (_gdk_input_ignore_core == 0)
if (GDK_WIN32_DISPLAY (display)->pointer_device_items->input_ignore_core == 0)
_gdk_device_virtual_set_active (device_manager->core_pointer,
device_manager->system_pointer);
}

View File

@@ -28,6 +28,7 @@ G_BEGIN_DECLS
typedef struct _GdkDeviceManagerWin32 GdkDeviceManagerWin32;
typedef struct _GdkDeviceManagerWin32Class GdkDeviceManagerWin32Class;
typedef struct _wintab_items wintab_items;
struct _GdkDeviceManagerWin32
{
@@ -43,11 +44,23 @@ struct _GdkDeviceManagerWin32
GList *winpointer_devices;
GList *wintab_devices;
/* Bumped up every time a wintab device enters the proximity
* of our context (WT_PROXIMITY). Bumped down when we either
* receive a WT_PACKET, or a WT_CSRCHANGE.
*/
int dev_entered_proximity;
/* used for wintab support */
wintab_items *wintab_items;
/* used for winpointer support, etc */
HWND winpointer_notification_hwnd;
GPtrArray *ignored_interactions;
void *winpointer_funcs; /* GdkDeviceManagerWin32WinpointerFuncs */
gboolean pen_touch_input;
POINT latest_pen_touch_position;
LONG last_digitizer_time;
};
struct _GdkDeviceManagerWin32Class
@@ -57,10 +70,10 @@ 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,
MSG *msg,
GdkSurface *surface);
void _gdk_wintab_set_tablet_active (GdkDeviceManagerWin32 *device_manager);
GdkEvent *gdk_wintab_make_event (GdkDisplay *display,
MSG *msg,
GdkSurface *surface);
G_END_DECLS

View File

@@ -28,6 +28,7 @@
#include "gdkdisplay-win32.h"
#include "gdkdevicemanager-win32.h"
#include "gdkglcontext-win32.h"
#include "gdkinput-dmanipulation.h"
#include "gdksurface-win32.h"
#include "gdkwin32display.h"
#include "gdkwin32screen.h"
@@ -38,7 +39,6 @@
#include <dwmapi.h>
#include "gdkwin32langnotification.h"
#ifdef HAVE_EGL
# include <epoxy/egl.h>
#endif
@@ -47,8 +47,6 @@
# define IMAGE_FILE_MACHINE_ARM64 0xAA64
#endif
static int debug_indent = 0;
/**
* gdk_win32_display_add_filter:
* @display: a `GdkWin32Display`
@@ -439,7 +437,7 @@ inner_display_change_hwnd_procedure (HWND hwnd,
}
case WM_DISPLAYCHANGE:
{
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (_gdk_display);
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (GetWindowLongPtr (hwnd, GWLP_USERDATA));
_gdk_win32_screen_on_displaychange_event (GDK_WIN32_SCREEN (win32_display->screen));
return 0;
@@ -458,16 +456,37 @@ display_change_hwnd_procedure (HWND hwnd,
LPARAM lparam)
{
LRESULT retval;
GdkDisplay *display;
GDK_NOTE (EVENTS, g_print ("%s%*s%s %p",
(debug_indent > 0 ? "\n" : ""),
debug_indent, "",
_gdk_win32_message_to_string (message), hwnd));
debug_indent += 2;
retval = inner_display_change_hwnd_procedure (hwnd, message, wparam, lparam);
debug_indent -= 2;
if (message == WM_NCCREATE)
{
CREATESTRUCT *cs = (CREATESTRUCT *)lparam;
display = (GdkDisplay *)cs->lpCreateParams;
GDK_NOTE (EVENTS, g_print (" => %" G_GINT64_FORMAT "%s", (gint64) retval, (debug_indent == 0 ? "\n" : "")));
SetWindowLongPtr (hwnd, GWLP_USERDATA, (LONG_PTR) display);
retval = TRUE;
}
else
{
int debug_indent;
display = GDK_DISPLAY (GetWindowLongPtr (hwnd, GWLP_USERDATA));
debug_indent = GDK_WIN32_DISPLAY (display)->event_record->debug_indent_displaychange;
GDK_NOTE (EVENTS, g_print ("%s%*s%s %p",
(debug_indent > 0 ? "\n" : ""),
debug_indent, "",
_gdk_win32_message_to_string (message), hwnd));
GDK_WIN32_DISPLAY (display)->event_record->debug_indent_displaychange += 2;
retval = inner_display_change_hwnd_procedure (hwnd, message, wparam, lparam);
GDK_WIN32_DISPLAY (display)->event_record->debug_indent_displaychange -= 2;
SetWindowLongPtr (hwnd, GWLP_USERDATA, (LONG_PTR) display);
debug_indent = GDK_WIN32_DISPLAY (display)->event_record->debug_indent_displaychange;
GDK_NOTE (EVENTS, g_print (" => %" G_GINT64_FORMAT "%s", (gint64) retval, (debug_indent == 0 ? "\n" : "")));
}
return retval;
}
@@ -491,7 +510,7 @@ register_display_change_notification (GdkDisplay *display)
display_win32->hwnd = CreateWindow (MAKEINTRESOURCE (klass),
NULL, WS_POPUP,
0, 0, 0, 0, NULL, NULL,
this_module (), NULL);
this_module (), display);
if (!display_win32->hwnd)
{
UnregisterClass (MAKEINTRESOURCE (klass), this_module ());
@@ -502,58 +521,66 @@ register_display_change_notification (GdkDisplay *display)
GdkDisplay *
_gdk_win32_display_open (const char *display_name)
{
static gsize display_inited = 0;
static GdkDisplay *display = NULL;
GdkWin32Display *win32_display;
GDK_NOTE (MISC, g_print ("gdk_display_open: %s\n", (display_name ? display_name : "NULL")));
if (display_name == NULL ||
g_ascii_strcasecmp (display_name,
gdk_display_get_name (_gdk_display)) == 0)
if (display_name == NULL || g_ascii_strcasecmp (display_name, gdk_display_get_name (display)) == 0)
{
if (_gdk_display != NULL)
{
GDK_NOTE (MISC, g_print ("... return _gdk_display\n"));
return _gdk_display;
}
if (display != NULL)
{
GDK_NOTE (MISC, g_print ("... return existing gdkdisplay\n"));
return display;
}
}
else
{
/* we don't really support multiple GdkDisplay's on Windows at this point */
GDK_NOTE (MISC, g_print ("... return NULL\n"));
return NULL;
}
_gdk_display = g_object_new (GDK_TYPE_WIN32_DISPLAY, NULL);
win32_display = GDK_WIN32_DISPLAY (_gdk_display);
if (g_once_init_enter (&display_inited))
{
display = g_object_new (GDK_TYPE_WIN32_DISPLAY, NULL);
win32_display->screen = g_object_new (GDK_TYPE_WIN32_SCREEN, NULL);
win32_display = GDK_WIN32_DISPLAY (display);
_gdk_events_init (_gdk_display);
win32_display->screen = g_object_new (GDK_TYPE_WIN32_SCREEN,
"display", display,
NULL);
_gdk_input_ignore_core = 0;
_gdk_events_init (display);
_gdk_device_manager = g_object_new (GDK_TYPE_DEVICE_MANAGER_WIN32,
NULL);
_gdk_device_manager->display = _gdk_display;
win32_display->device_manager = g_object_new (GDK_TYPE_DEVICE_MANAGER_WIN32,
"display", display,
NULL);
gdk_dmanipulation_initialize (win32_display);
_gdk_win32_lang_notification_init ();
_gdk_drag_init ();
gdk_win32_display_lang_notification_init (win32_display);
_gdk_drag_init ();
_gdk_display->clipboard = gdk_win32_clipboard_new (_gdk_display);
_gdk_display->primary_clipboard = gdk_clipboard_new (_gdk_display);
display->clipboard = gdk_win32_clipboard_new (display);
display->primary_clipboard = gdk_clipboard_new (display);
/* Precalculate display name */
(void) gdk_display_get_name (_gdk_display);
/* Precalculate display name */
gdk_display_get_name (display);
register_display_change_notification (_gdk_display);
register_display_change_notification (display);
g_signal_emit_by_name (_gdk_display, "opened");
g_signal_emit_by_name (display, "opened");
/* Precalculate keymap, see #6203 */
(void) _gdk_win32_display_get_keymap (_gdk_display);
/* Precalculate keymap, see #6203 */
gdk_display_get_keymap (display);
GDK_NOTE (MISC, g_print ("... _gdk_display now set up\n"));
GDK_NOTE (MISC, g_print ("... gdk_display now set up\n"));
return _gdk_display;
g_once_init_leave (&display_inited, 1);
}
return display;
}
G_DEFINE_TYPE (GdkWin32Display, gdk_win32_display, GDK_TYPE_DISPLAY)
@@ -639,7 +666,7 @@ gdk_win32_display_beep (GdkDisplay *display)
static void
gdk_win32_display_flush (GdkDisplay * display)
{
g_return_if_fail (display == _gdk_display);
g_return_if_fail (display == gdk_display_get_default());
GdiFlush ();
}
@@ -647,7 +674,7 @@ gdk_win32_display_flush (GdkDisplay * display)
static void
gdk_win32_display_sync (GdkDisplay * display)
{
g_return_if_fail (display == _gdk_display);
g_return_if_fail (display == gdk_display_get_default());
GdiFlush ();
}
@@ -687,9 +714,22 @@ gdk_win32_display_finalize (GObject *object)
{
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (object);
g_free (display_win32->event_record);
if (display_win32->display_surface_record->modal_timer != 0)
{
KillTimer (NULL, display_win32->display_surface_record->modal_timer);
display_win32->display_surface_record->modal_timer = 0;
}
g_slist_free_full (display_win32->display_surface_record->modal_surface_stack, g_object_unref);
g_hash_table_destroy (display_win32->display_surface_record->handle_ht);
g_free (display_win32->display_surface_record);
_gdk_win32_display_finalize_cursors (display_win32);
gdk_win32_display_close_dmanip_manager (GDK_DISPLAY (display_win32));
_gdk_win32_dnd_exit ();
_gdk_win32_lang_notification_exit ();
gdk_win32_display_lang_notification_exit (display_win32);
g_free (display_win32->pointer_device_items);
g_object_unref (display_win32->cb_dnd_items->clipdrop);
g_free (display_win32->cb_dnd_items);
g_list_store_remove_all (G_LIST_STORE (display_win32->monitors));
g_object_unref (display_win32->monitors);
@@ -1024,13 +1064,45 @@ _gdk_win32_check_processor (GdkWin32ProcessorCheckType check_type)
}
}
static guint
gdk_handle_hash (HANDLE *handle)
{
#ifdef _WIN64
return ((guint *) handle)[0] ^ ((guint *) handle)[1];
#else
return (guint) *handle;
#endif
}
static int
gdk_handle_equal (HANDLE *a,
HANDLE *b)
{
return (*a == *b);
}
/* facts of life, DestroyWindow() is a __stdcall function */
static void
gdk_destroy_surface_hwnd (gpointer hwnd)
{
DestroyWindow ((HWND)hwnd);
}
static void
gdk_win32_display_init (GdkWin32Display *display_win32)
{
const char *scale_str = g_getenv ("GDK_SCALE");
display_win32->monitors = G_LIST_MODEL (g_list_store_new (GDK_TYPE_MONITOR));
display_win32->pointer_device_items = g_new0 (GdkWin32PointerDeviceItems, 1);
display_win32->cb_dnd_items = g_new0 (GdkWin32CbDnDItems, 1);
display_win32->cb_dnd_items->display_main_thread = g_thread_self ();
display_win32->cb_dnd_items->clipdrop = GDK_WIN32_CLIPDROP (g_object_new (GDK_TYPE_WIN32_CLIPDROP, NULL));
display_win32->display_surface_record = g_new0 (surface_records, 1);
display_win32->display_surface_record->handle_ht = g_hash_table_new ((GHashFunc) gdk_handle_hash,
(GEqualFunc) gdk_handle_equal);
display_win32->event_record = g_new0 (event_records, 1);
_gdk_win32_enable_hidpi (display_win32);
display_win32->running_on_arm64 = _gdk_win32_check_processor (GDK_WIN32_ARM64);
@@ -1175,17 +1247,6 @@ gdk_win32_display_get_monitor_scale_factor (GdkWin32Display *display_win32,
return 1;
}
static gboolean
gdk_win32_display_get_setting (GdkDisplay *display,
const char *name,
GValue *value)
{
if (gdk_display_get_debug_flags (display) & GDK_DEBUG_DEFAULT_SETTINGS)
return FALSE;
return _gdk_win32_get_setting (name, value);
}
#ifndef EGL_PLATFORM_ANGLE_ANGLE
#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
#endif
@@ -1271,6 +1332,22 @@ gdk_win32_display_get_egl_display (GdkDisplay *display)
return gdk_display_get_egl_display (display);
}
GdkWin32Clipdrop *
gdk_win32_display_get_clipdrop (GdkDisplay *display)
{
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
return display_win32->cb_dnd_items->clipdrop;
}
static GdkKeymap*
_gdk_win32_display_get_keymap (GdkDisplay *display)
{
g_return_val_if_fail (display == gdk_display_get_default (), NULL);
return gdk_win32_display_get_default_keymap (GDK_WIN32_DISPLAY (display));
}
static void
gdk_win32_display_class_init (GdkWin32DisplayClass *klass)
{
@@ -1308,6 +1385,4 @@ gdk_win32_display_class_init (GdkWin32DisplayClass *klass)
display_class->get_setting = gdk_win32_display_get_setting;
display_class->set_cursor_theme = gdk_win32_display_set_cursor_theme;
display_class->init_gl = gdk_win32_display_init_gl;
_gdk_win32_surfaceing_init ();
}

View File

@@ -23,13 +23,37 @@
#include "gdkwin32screen.h"
#include "gdkwin32cursor.h"
#include "gdkprivate-win32.h"
#include "gdkglversionprivate.h"
/* Used for active language or text service change notifications */
#define COBJMACROS
#include <msctf.h>
#ifdef HAVE_EGL
# include <epoxy/egl.h>
#endif
struct _GdkWin32PointerDeviceItems
{
/* Input Core items */
int input_ignore_core;
};
typedef struct _GdkWin32PointerDeviceItems GdkWin32PointerDeviceItems;
typedef struct _GdkWin32InputLocaleItems GdkWin32InputLocaleItems;
struct _GdkWin32CbDnDItems
{
/* used to identify the main thread for this GdkWin32Display */
GThread *display_main_thread;
GdkWin32Clipdrop *clipdrop;
};
typedef struct _GdkWin32CbDnDItems GdkWin32CbDnDItems;
/* Define values used to set DPI-awareness */
typedef enum _GdkWin32ProcessDpiAwareness {
PROCESS_DPI_UNAWARE = 0,
@@ -113,6 +137,52 @@ typedef struct
HGLRC hglrc;
} GdkWin32GLDummyContextWGL;
/* for Direct Manipulation support */
typedef struct
{
/* this is an IDirectManipulationManager object */
void *manager;
/* GetPointerType (UINT32 pointerId, POINTER_INPUT_TYPE *pointerType) function pointer */
void *getPointerType;
} dmanip_items;
/* for surface tracking items (modal, HWNDs used, etc) */
typedef struct
{
GHashTable *handle_ht;
GSList *modal_surface_stack;
HWND modal_move_resize_hwnd;
/* Non-zero while a modal sizing, moving, or dnd operation is in progress */
GdkWin32ModalOpKind modal_operation_in_progress;
UINT modal_timer;
} surface_records;
/* for tracking various events that go on */
typedef struct
{
/* for tracking various mouse/wintab/winpointer events */
GdkSurface *mouse_surface;
GdkSurface *mouse_surface_ignored_leave;
int current_root_x;
int current_root_y;
int debug_indent_displaychange;
int debug_indent_surface_events;
/* for tracking whether we are using IME */
guint in_ime_composition : 1;
/* to store keycodes for shift keys */
int both_shift_pressed[2];
/* AeroSnap emulation event handling */
/* low-level keyboard hook handle */
HHOOK aerosnap_keyboard_hook;
UINT aerosnap_message;
} event_records;
struct _GdkWin32Display
{
GdkDisplay display;
@@ -125,17 +195,28 @@ struct _GdkWin32Display
HWND hwnd;
GListModel *monitors;
GdkWin32InputLocaleItems *input_locale_items;
GdkWin32PointerDeviceItems *pointer_device_items;
GdkWin32CbDnDItems *cb_dnd_items;
GdkDeviceManagerWin32 *device_manager;
surface_records *display_surface_record;
event_records *event_record;
dmanip_items *dmanip_items;
/* WGL/OpenGL Items */
GdkWin32GLDummyContextWGL dummy_context_wgl;
GListModel *monitors;
guint hasWglARBCreateContext : 1;
guint hasWglEXTSwapControl : 1;
guint hasWglOMLSyncControl : 1;
guint hasWglARBPixelFormat : 1;
guint hasGlWINSwapHint : 1;
guint wgl_support_gdi : 1;
struct wgl_quirks {
guint force_gdi_compatibility : 1;
guint disallow_swap_exchange : 1;
} *wgl_quirks;
#ifdef HAVE_EGL
guint hasEglKHRCreateContext : 1;
@@ -184,9 +265,11 @@ GPtrArray *_gdk_win32_display_get_monitor_list (GdkWin32Display *display);
void gdk_win32_display_check_composited (GdkWin32Display *display);
guint gdk_win32_display_get_monitor_scale_factor (GdkWin32Display *display_win32,
GdkSurface *surface,
HMONITOR hmonitor);
guint gdk_win32_display_get_monitor_scale_factor (GdkWin32Display *display_win32,
GdkSurface *surface,
HMONITOR hmonitor);
GdkWin32Clipdrop *gdk_win32_display_get_clipdrop (GdkDisplay *display);
typedef struct _GdkWin32MessageFilter GdkWin32MessageFilter;

View File

@@ -217,8 +217,8 @@
#include <gdk/gdk.h>
#include <glib/gstdio.h>
/* Just to avoid calling RegisterWindowMessage() every time */
static UINT thread_wakeup_message;
/* accessors to thread data structs in GdkWin32Clipdrop/GdkWin32Drag */
#define OBJECT_DND_THREAD_MEMBER(o,m) ((GdkWin32DnDThread *)(o->dnd_thread_items))->m
typedef struct
{
@@ -362,27 +362,22 @@ struct _GdkWin32DnDThread
data_object *src_object;
};
/* The code is much more secure if we don't rely on the OS to keep
* this around for us.
*/
static GdkWin32DnDThread *dnd_thread_data = NULL;
static gboolean
dnd_queue_is_empty ()
dnd_queue_is_empty (GdkDisplay *display)
{
return g_atomic_int_get (&_win32_clipdrop->dnd_queue_counter) == 0;
return g_atomic_int_get (&(gdk_win32_display_get_clipdrop (display)->dnd_queue_counter)) == 0;
}
static void
decrement_dnd_queue_counter ()
decrement_dnd_queue_counter (GdkDisplay *display)
{
g_atomic_int_dec_and_test (&_win32_clipdrop->dnd_queue_counter);
g_atomic_int_dec_and_test (&(gdk_win32_display_get_clipdrop (display)->dnd_queue_counter));
}
static void
increment_dnd_queue_counter ()
increment_dnd_queue_counter (GdkDisplay *display)
{
g_atomic_int_inc (&_win32_clipdrop->dnd_queue_counter);
g_atomic_int_inc (&(gdk_win32_display_get_clipdrop (display)->dnd_queue_counter));
}
static void
@@ -427,13 +422,15 @@ free_queue_item (GdkWin32DnDThreadQueueItem *item)
}
static gboolean
process_dnd_queue (gboolean timed,
process_dnd_queue (GdkDrag *drag,
gboolean timed,
guint64 end_time,
GdkWin32DnDThreadGetData *getdata_check)
{
GdkWin32DnDThreadQueueItem *item;
GdkWin32DnDThreadUpdateDragState *updatestate;
GdkWin32DnDThreadDoDragDrop *ddd;
GdkWin32Drag *drag_win32 = GDK_WIN32_DRAG (drag);
while (TRUE)
{
@@ -444,17 +441,17 @@ process_dnd_queue (gboolean timed,
if (current_time >= end_time)
break;
item = g_async_queue_timeout_pop (dnd_thread_data->input_queue, end_time - current_time);
item = g_async_queue_timeout_pop (OBJECT_DND_THREAD_MEMBER (drag_win32, input_queue), end_time - current_time);
}
else
{
item = g_async_queue_try_pop (dnd_thread_data->input_queue);
item = g_async_queue_try_pop (OBJECT_DND_THREAD_MEMBER (drag_win32, input_queue));
}
if (item == NULL)
break;
decrement_dnd_queue_counter ();
decrement_dnd_queue_counter (gdk_surface_get_display (drag_win32->drag_surface));
switch (item->item_type)
{
@@ -490,7 +487,7 @@ do_drag_drop_response (gpointer user_data)
HRESULT hr = ddd->received_result;
GdkDrag *drag = GDK_DRAG (ddd->base.opaque_context);
GdkWin32Drag *drag_win32 = GDK_WIN32_DRAG (drag);
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
GdkWin32Clipdrop *clipdrop = gdk_win32_display_get_clipdrop (gdk_surface_get_display (drag_win32->drag_surface));
gpointer table_value = g_hash_table_lookup (clipdrop->active_source_drags, drag);
if (ddd == table_value)
@@ -546,7 +543,7 @@ received_drag_context_data (GObject *drag,
{
GError *error = NULL;
GdkWin32DnDThreadGetData *getdata = (GdkWin32DnDThreadGetData *) user_data;
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
GdkWin32Clipdrop *clipdrop = gdk_win32_display_get_clipdrop (gdk_surface_get_display (GDK_WIN32_DRAG (drag)->drag_surface));
if (!gdk_drag_write_finish (GDK_DRAG (drag), result, &error))
{
@@ -571,17 +568,17 @@ received_drag_context_data (GObject *drag,
}
g_clear_object (&getdata->stream);
increment_dnd_queue_counter ();
increment_dnd_queue_counter (gdk_surface_get_display (GDK_WIN32_DRAG (drag)->drag_surface));
g_async_queue_push (clipdrop->dnd_queue, getdata);
API_CALL (PostThreadMessage, (clipdrop->dnd_thread_id, thread_wakeup_message, 0, 0));
API_CALL (PostThreadMessage, (clipdrop->dnd_thread_id, clipdrop->thread_wakeup_message, 0, 0));
}
static gboolean
get_data_response (gpointer user_data)
{
GdkWin32DnDThreadGetData *getdata = (GdkWin32DnDThreadGetData *) user_data;
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
GdkDrag *drag = GDK_DRAG (getdata->base.opaque_context);
GdkWin32Clipdrop *clipdrop = gdk_win32_display_get_clipdrop (gdk_surface_get_display (GDK_WIN32_DRAG (getdata->base.opaque_context)->drag_surface));
gpointer ddd = g_hash_table_lookup (clipdrop->active_source_drags, drag);
GDK_NOTE (DND, g_print ("idataobject_getdata will request target 0x%p (%s)",
@@ -593,7 +590,7 @@ get_data_response (gpointer user_data)
if (ddd)
{
GError *error = NULL;
GOutputStream *stream = gdk_win32_hdata_output_stream_new (&getdata->pair, &error);
GOutputStream *stream = gdk_win32_hdata_output_stream_new (clipdrop, &getdata->pair, &error);
if (stream)
{
@@ -610,9 +607,9 @@ get_data_response (gpointer user_data)
}
}
increment_dnd_queue_counter ();
increment_dnd_queue_counter (gdk_surface_get_display (GDK_WIN32_DRAG (drag)->drag_surface));
g_async_queue_push (clipdrop->dnd_queue, getdata);
API_CALL (PostThreadMessage, (clipdrop->dnd_thread_id, thread_wakeup_message, 0, 0));
API_CALL (PostThreadMessage, (clipdrop->dnd_thread_id, clipdrop->thread_wakeup_message, 0, 0));
return G_SOURCE_REMOVE;
}
@@ -622,11 +619,13 @@ do_drag_drop (GdkWin32DnDThreadDoDragDrop *ddd)
{
HRESULT hr;
dnd_thread_data->src_object = ddd->src_object;
dnd_thread_data->src_context = ddd->src_context;
GdkWin32Drag *drag = ddd->base.opaque_context;
hr = DoDragDrop (&dnd_thread_data->src_object->ido,
&dnd_thread_data->src_context->ids,
OBJECT_DND_THREAD_MEMBER (drag, src_object) = ddd->src_object;
OBJECT_DND_THREAD_MEMBER (drag, src_context) = ddd->src_context;
hr = DoDragDrop (&OBJECT_DND_THREAD_MEMBER (drag, src_object->ido),
&OBJECT_DND_THREAD_MEMBER (drag, src_context->ids),
ddd->allowed_drop_effects,
&ddd->received_drop_effect);
@@ -638,15 +637,18 @@ do_drag_drop (GdkWin32DnDThreadDoDragDrop *ddd)
gpointer
_gdk_win32_dnd_thread_main (gpointer data)
{
GAsyncQueue *queue = (GAsyncQueue *) data;
clipdrop_thread_items *clipdrop_items = (clipdrop_thread_items *) data;
GAsyncQueue *queue = clipdrop_items->queue;
GdkWin32Clipdrop *clipdrop = clipdrop_items->clipdrop;
GdkWin32DnDThreadQueueItem *item;
MSG msg;
HRESULT hr;
g_assert (dnd_thread_data == NULL);
g_assert (clipdrop->dnd_thread_items == NULL);
dnd_thread_data = g_new0 (GdkWin32DnDThread, 1);
dnd_thread_data->input_queue = queue;
clipdrop->dnd_thread_items = g_new0 (GdkWin32DnDThread, 1);
OBJECT_DND_THREAD_MEMBER (clipdrop, input_queue) = queue;
CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
@@ -658,8 +660,6 @@ _gdk_win32_dnd_thread_main (gpointer data)
/* Create a message queue */
PeekMessage (&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
thread_wakeup_message = RegisterWindowMessage (L"GDK_WORKER_THREAD_WEAKEUP");
/* Signal the main thread that we're ready.
* This is the only time the queue works in reverse.
*/
@@ -667,11 +667,13 @@ _gdk_win32_dnd_thread_main (gpointer data)
while (GetMessage (&msg, NULL, 0, 0))
{
if (!dnd_queue_is_empty ())
GdkDisplay *display = gdk_display_get_default ();
if (!dnd_queue_is_empty (display))
{
while ((item = g_async_queue_try_pop (queue)) != NULL)
{
decrement_dnd_queue_counter ();
decrement_dnd_queue_counter (display);
if (item->item_type != GDK_WIN32_DND_THREAD_QUEUE_ITEM_DO_DRAG_DROP)
{
@@ -680,7 +682,7 @@ _gdk_win32_dnd_thread_main (gpointer data)
}
do_drag_drop ((GdkWin32DnDThreadDoDragDrop *) item);
API_CALL (PostThreadMessage, (GetCurrentThreadId (), thread_wakeup_message, 0, 0));
API_CALL (PostThreadMessage, (GetCurrentThreadId (), clipdrop->thread_wakeup_message, 0, 0));
break;
}
}
@@ -691,7 +693,8 @@ _gdk_win32_dnd_thread_main (gpointer data)
}
g_async_queue_unref (queue);
g_clear_pointer (&dnd_thread_data, g_free);
g_clear_pointer (&clipdrop->dnd_thread_items, g_free);
OleUninitialize ();
CoUninitialize ();
@@ -703,6 +706,25 @@ static gboolean drag_context_grab (GdkDrag *drag);
G_DEFINE_TYPE (GdkWin32Drag, gdk_win32_drag, GDK_TYPE_DRAG)
static gboolean
check_drag_display_thread_status (GdkDrag *drag,
gboolean is_self)
{
GdkDisplay *display = gdk_drag_get_display (drag);
GThread *current_thread, *display_thread;
if (display == NULL)
return TRUE;
current_thread = g_thread_self ();
display_thread = GDK_WIN32_DISPLAY (display)->cb_dnd_items->display_main_thread;
if (display_thread == NULL)
return TRUE;
return is_self ? display_thread == current_thread : display_thread != current_thread;
}
static void
move_drag_surface (GdkDrag *drag,
guint x_root,
@@ -710,8 +732,7 @@ move_drag_surface (GdkDrag *drag,
{
GdkWin32Drag *drag_win32 = GDK_WIN32_DRAG (drag);
g_assert (_win32_main_thread == NULL ||
_win32_main_thread == g_thread_self ());
g_assert (check_drag_display_thread_status (drag, TRUE));
gdk_win32_surface_move (drag_win32->drag_surface,
x_root - drag_win32->hot_x,
@@ -722,8 +743,7 @@ move_drag_surface (GdkDrag *drag,
static void
gdk_win32_drag_init (GdkWin32Drag *drag)
{
g_assert (_win32_main_thread == NULL ||
_win32_main_thread == g_thread_self ());
g_assert (check_drag_display_thread_status (GDK_DRAG (drag), TRUE));
drag->handle_events = TRUE;
drag->dest_hwnd = INVALID_HANDLE_VALUE;
@@ -738,14 +758,14 @@ gdk_win32_drag_finalize (GObject *object)
GdkWin32Drag *drag_win32;
GdkSurface *drag_surface;
g_assert (_win32_main_thread == NULL ||
_win32_main_thread == g_thread_self ());
GDK_NOTE (DND, g_print ("gdk_win32_drag_finalize %p\n", object));
g_return_if_fail (GDK_IS_WIN32_DRAG (object));
drag = GDK_DRAG (object);
g_assert (check_drag_display_thread_status (drag, TRUE));
drag_win32 = GDK_WIN32_DRAG (drag);
gdk_drag_set_cursor (drag, NULL);
@@ -786,6 +806,8 @@ gdk_drag_new (GdkDisplay *display,
else
drag_win32->scale = gdk_win32_display_get_monitor_scale_factor (display_win32, NULL, NULL);
drag_win32->dnd_thread_items = display_win32->cb_dnd_items->clipdrop->dnd_thread_items;
return drag;
}
@@ -810,17 +832,17 @@ static enum_formats *enum_formats_new (GArray *formats);
* Does not give a reference.
*/
GdkDrag *
_gdk_win32_find_drag_for_dest_hwnd (HWND dest_hwnd)
gdk_win32_find_drag_for_dest_surface (GdkSurface *surface)
{
GHashTableIter iter;
GdkWin32Drag *drag_win32;
GdkWin32DnDThreadDoDragDrop *ddd;
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
GdkWin32Clipdrop *clipdrop = gdk_win32_display_get_clipdrop (gdk_surface_get_display (surface));
g_hash_table_iter_init (&iter, clipdrop->active_source_drags);
while (g_hash_table_iter_next (&iter, (gpointer *) &drag_win32, (gpointer *) &ddd))
if (ddd->src_context->dest_window_handle == dest_hwnd)
if (ddd->src_context->dest_window_handle == GDK_SURFACE_HWND (surface))
return GDK_DRAG (drag_win32);
return NULL;
@@ -897,8 +919,8 @@ idropsourcenotify_dragentertarget (IDropSourceNotify *This,
source_drag_context *ctx = (source_drag_context *) (((char *) This) - G_STRUCT_OFFSET (source_drag_context, idsn));
GdkWin32DnDEnterLeaveNotify *notify;
if (!dnd_queue_is_empty ())
process_dnd_queue (FALSE, 0, NULL);
if (!dnd_queue_is_empty (gdk_surface_get_display (GDK_WIN32_DRAG (ctx->drag)->drag_surface)))
process_dnd_queue (ctx->drag, FALSE, 0, NULL);
GDK_NOTE (DND, g_print ("idropsourcenotify_dragentertarget %p (SDC %p) 0x%p\n", This, ctx, hwndTarget));
@@ -918,8 +940,8 @@ idropsourcenotify_dragleavetarget (IDropSourceNotify *This)
source_drag_context *ctx = (source_drag_context *) (((char *) This) - G_STRUCT_OFFSET (source_drag_context, idsn));
GdkWin32DnDEnterLeaveNotify *notify;
if (!dnd_queue_is_empty ())
process_dnd_queue (FALSE, 0, NULL);
if (!dnd_queue_is_empty (gdk_surface_get_display (GDK_WIN32_DRAG (ctx->drag)->drag_surface)))
process_dnd_queue (ctx->drag, FALSE, 0, NULL);
GDK_NOTE (DND, g_print ("idropsourcenotify_dragleavetarget %p (SDC %p) 0x%p\n", This, ctx, ctx->dest_window_handle));
@@ -1020,8 +1042,8 @@ idropsource_querycontinuedrag (LPDROPSOURCE This,
GDK_NOTE (DND, g_print ("idropsource_querycontinuedrag %p esc=%d keystate=0x%lx with state %d\n", This, fEscapePressed, grfKeyState, ctx->util_data.state));
if (!dnd_queue_is_empty ())
process_dnd_queue (FALSE, 0, NULL);
if (!dnd_queue_is_empty (gdk_surface_get_display (GDK_WIN32_DRAG (ctx->drag)->drag_surface)))
process_dnd_queue (ctx->drag, FALSE, 0, NULL);
GDK_NOTE (DND, g_print ("idropsource_querycontinuedrag state %d\n", ctx->util_data.state));
@@ -1057,14 +1079,13 @@ static gboolean
give_feedback (gpointer user_data)
{
GdkWin32DnDThreadGiveFeedback *feedback = (GdkWin32DnDThreadGiveFeedback *) user_data;
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
GdkDrag *drag = GDK_DRAG (feedback->base.opaque_context);
GdkWin32Drag *drag_win32 = GDK_WIN32_DRAG (drag);
GdkWin32Clipdrop *clipdrop = gdk_win32_display_get_clipdrop (gdk_surface_get_display (drag_win32->drag_surface));
gpointer ddd = g_hash_table_lookup (clipdrop->active_source_drags, feedback->base.opaque_context);
if (ddd)
{
GdkDrag *drag = GDK_DRAG (feedback->base.opaque_context);
GdkWin32Drag *drag_win32 = GDK_WIN32_DRAG (drag);
GDK_NOTE (DND, g_print ("gdk_dnd_handle_drag_status: 0x%p\n",
drag));
@@ -1085,8 +1106,8 @@ idropsource_givefeedback (LPDROPSOURCE This,
GDK_NOTE (DND, g_print ("idropsource_givefeedback %p with drop effect %lu S_OK\n", This, dwEffect));
if (!dnd_queue_is_empty ())
process_dnd_queue (FALSE, 0, NULL);
if (!dnd_queue_is_empty (gdk_surface_get_display (GDK_WIN32_DRAG (ctx->drag)->drag_surface)))
process_dnd_queue (ctx->drag, FALSE, 0, NULL);
feedback = g_new0 (GdkWin32DnDThreadGiveFeedback, 1);
feedback->base.item_type = GDK_WIN32_DND_THREAD_QUEUE_ITEM_GIVE_FEEDBACK;
@@ -1224,8 +1245,8 @@ idataobject_getdata (LPDATAOBJECT This,
return hr;
}
if (!dnd_queue_is_empty ())
process_dnd_queue (FALSE, 0, NULL);
if (!dnd_queue_is_empty (gdk_surface_get_display (GDK_WIN32_DRAG (ctx->drag)->drag_surface)))
process_dnd_queue (ctx->drag, FALSE, 0, NULL);
getdata = g_new0 (GdkWin32DnDThreadGetData, 1);
getdata->base.item_type = GDK_WIN32_DND_THREAD_QUEUE_ITEM_GET_DATA;
@@ -1233,7 +1254,7 @@ idataobject_getdata (LPDATAOBJECT This,
getdata->pair = *pair;
g_idle_add_full (G_PRIORITY_DEFAULT, get_data_response, getdata, NULL);
if (!process_dnd_queue (TRUE, g_get_monotonic_time () + G_USEC_PER_SEC * 30, getdata))
if (!process_dnd_queue (ctx->drag, TRUE, g_get_monotonic_time () + G_USEC_PER_SEC * 30, getdata))
return E_FAIL;
if (getdata->produced_data_medium.tymed == TYMED_NULL)
@@ -1269,8 +1290,9 @@ idataobject_querygetdata (LPDATAOBJECT This,
{
HRESULT hr;
g_assert (_win32_main_thread == NULL ||
_win32_main_thread != g_thread_self ());
data_object *ctx = (data_object *) This;
g_assert (check_drag_display_thread_status (ctx->drag, FALSE));
hr = query (This, pFormatEtc, NULL);
@@ -1309,8 +1331,9 @@ idataobject_enumformatetc (LPDATAOBJECT This,
DWORD dwDirection,
LPENUMFORMATETC *ppEnumFormatEtc)
{
g_assert (_win32_main_thread == NULL ||
_win32_main_thread != g_thread_self ());
data_object *ctx = (data_object *) This;
g_assert (check_drag_display_thread_status (ctx->drag, FALSE));
if (dwDirection != DATADIR_GET)
{
@@ -1598,7 +1621,9 @@ data_object_new (GdkDrag *drag)
GDK_NOTE (DND, g_print ("DataObject supports contentformat 0x%p (%s)\n", mime_types[i], mime_types[i]));
added_count = _gdk_win32_add_contentformat_to_pairs (mime_types[i], result->formats);
added_count = _gdk_win32_add_contentformat_to_pairs (gdk_win32_display_get_clipdrop (gdk_surface_get_display (GDK_WIN32_DRAG (drag)->drag_surface)),
mime_types[i],
result->formats);
for (j = 0; j < added_count && result->formats->len - 1 - j >= 0; j++)
GDK_NOTE (DND, g_print ("DataObject will support w32format 0x%x\n", g_array_index (result->formats, GdkWin32ContentFormatPair, j).w32format));
@@ -1654,7 +1679,7 @@ _gdk_win32_surface_drag_begin (GdkSurface *surface,
{
GdkDrag *drag;
GdkWin32Drag *drag_win32;
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
GdkWin32Clipdrop *clipdrop = gdk_win32_display_get_clipdrop (gdk_surface_get_display (surface));
double px, py;
int x_root, y_root;
GdkWin32DnDThreadDoDragDrop *ddd;
@@ -1709,9 +1734,9 @@ _gdk_win32_surface_drag_begin (GdkSurface *surface,
ddd->allowed_drop_effects |= DROPEFFECT_LINK;
g_hash_table_replace (clipdrop->active_source_drags, g_object_ref (drag), ddd);
increment_dnd_queue_counter ();
increment_dnd_queue_counter (gdk_surface_get_display (drag_win32->drag_surface));
g_async_queue_push (clipdrop->dnd_queue, ddd);
API_CALL (PostThreadMessage, (clipdrop->dnd_thread_id, thread_wakeup_message, 0, 0));
API_CALL (PostThreadMessage, (clipdrop->dnd_thread_id, clipdrop->thread_wakeup_message, 0, 0));
drag_win32->util_data.state = GDK_WIN32_DND_PENDING;
@@ -1750,9 +1775,9 @@ send_source_state_update (GdkWin32Clipdrop *clipdrop,
status->base.item_type = GDK_WIN32_DND_THREAD_QUEUE_ITEM_UPDATE_DRAG_STATE;
status->opaque_ddd = ddd;
status->produced_util_data = drag_win32->util_data;
increment_dnd_queue_counter ();
increment_dnd_queue_counter (gdk_surface_get_display (drag_win32->drag_surface));
g_async_queue_push (clipdrop->dnd_queue, status);
API_CALL (PostThreadMessage, (clipdrop->dnd_thread_id, thread_wakeup_message, 0, 0));
API_CALL (PostThreadMessage, (clipdrop->dnd_thread_id, clipdrop->thread_wakeup_message, 0, 0));
}
static void
@@ -1760,11 +1785,10 @@ gdk_win32_drag_drop (GdkDrag *drag,
guint32 time_)
{
GdkWin32Drag *drag_win32 = GDK_WIN32_DRAG (drag);
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
GdkWin32Clipdrop *clipdrop = gdk_win32_display_get_clipdrop (gdk_surface_get_display (drag_win32->drag_surface));
gpointer ddd;
g_assert (_win32_main_thread == NULL ||
_win32_main_thread == g_thread_self ());
g_assert (check_drag_display_thread_status (drag, TRUE));
g_return_if_fail (drag != NULL);
@@ -1876,7 +1900,7 @@ 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 ();
clipdrop = gdk_win32_display_get_clipdrop (gdk_surface_get_display (drag_win32->drag_surface));
ddd = g_hash_table_lookup (clipdrop->active_source_drags, drag);
if (success)
@@ -2034,7 +2058,7 @@ gdk_dnd_handle_motion_event (GdkDrag *drag,
key_state = manufacture_keystate_from_GMT (state);
clipdrop = _gdk_win32_clipdrop_get ();
clipdrop = gdk_win32_display_get_clipdrop (gdk_surface_get_display (event->surface));
GDK_NOTE (DND, g_print ("Post WM_MOUSEMOVE keystate=%lu\n", key_state));

View File

@@ -269,7 +269,8 @@ idroptarget_release (LPDROPTARGET This)
}
static GdkContentFormats *
query_object_formats (LPDATAOBJECT pDataObj,
query_object_formats (GdkDisplay *display,
LPDATAOBJECT pDataObj,
GArray *w32format_contentformat_map)
{
IEnumFORMATETC *pfmt = NULL;
@@ -298,7 +299,7 @@ query_object_formats (LPDATAOBJECT pDataObj,
GDK_NOTE (DND, g_print ("supported unnamed? source format 0x%x\n", fmt.cfFormat));
g_free (registered_name);
_gdk_win32_add_w32format_to_pairs (fmt.cfFormat, w32format_contentformat_map, builder);
gdk_win32_clipdrop_add_win32_format_to_pairs (gdk_win32_display_get_clipdrop (display), fmt.cfFormat, w32format_contentformat_map, builder);
hr = IEnumFORMATETC_Next (pfmt, 1, &fmt, NULL);
}
@@ -490,12 +491,12 @@ idroptarget_dragenter (LPDROPTARGET This,
drag = NULL;
if (ctx->surface)
drag = _gdk_win32_find_drag_for_dest_hwnd (GDK_SURFACE_HWND (ctx->surface));
drag = gdk_win32_find_drag_for_dest_surface (ctx->surface);
display = gdk_surface_get_display (ctx->surface);
droptarget_w32format_contentformat_map = g_array_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair));
formats = query_object_formats (pDataObj, droptarget_w32format_contentformat_map);
formats = query_object_formats (display, pDataObj, droptarget_w32format_contentformat_map);
drop = gdk_drop_new (display,
gdk_seat_get_pointer (gdk_display_get_default_seat (display)),
drag,
@@ -1110,7 +1111,12 @@ gdk_win32_drop_read_async (GdkDrop *drop,
}
else
{
_gdk_win32_transmute_windows_data (pair->w32format, pair->contentformat, storage.hGlobal, &data, &data_len);
GdkDisplay *display = gdk_drop_get_display (drop);
gdk_win32_clipdrop_transmute_windows_data (gdk_win32_display_get_clipdrop (display),
pair->w32format, pair->contentformat,
storage.hGlobal,
&data,
&data_len);
}
ReleaseStgMedium (&storage);

File diff suppressed because it is too large Load Diff

View File

@@ -270,17 +270,20 @@ attribs_fini (attribs_t *attribs)
#define attribs_add_static_array(attribs, array) \
do attribs_add_bulk (attribs, array, G_N_ELEMENTS (array)); while (0)
static int
find_pixel_format_with_defined_swap_flag (HDC hdc,
int formats[],
UINT count)
static bool
find_pixel_format_with_defined_swap_method (HDC hdc,
int formats[],
UINT count,
UINT *index,
int *swap_method)
{
SetLastError (0);
for (UINT i = 0; i < count; i++)
{
int query = WGL_SWAP_METHOD_ARB;
int value = WGL_SWAP_UNDEFINED_ARB;
SetLastError (0);
if (!wglGetPixelFormatAttribivARB (hdc, formats[i], 0, 1, &query, &value))
{
WIN32_API_FAILED ("wglGetPixelFormatAttribivARB");
@@ -288,10 +291,15 @@ find_pixel_format_with_defined_swap_flag (HDC hdc,
}
if (value != WGL_SWAP_UNDEFINED_ARB)
return formats[i];
{
*index = i;
*swap_method = value;
return true;
}
}
return 0;
return false;
}
static int
@@ -337,6 +345,8 @@ choose_pixel_format_arb_attribs (GdkWin32Display *display_win32,
UINT count = 0;
int format = 0;
int saved = 0;
UINT index = 0;
int swap_method = WGL_SWAP_UNDEFINED_ARB;
#define EXT_CALL(api, args) \
do { \
@@ -357,7 +367,7 @@ choose_pixel_format_arb_attribs (GdkWin32Display *display_win32,
attribs_add_static_array (&attribs, attribs_base);
if (display_win32->wgl_support_gdi)
if (display_win32->wgl_quirks->force_gdi_compatibility)
attribs_add (&attribs, WGL_SUPPORT_GDI_ARB, GL_TRUE);
attribs_commit (&attribs);
@@ -383,26 +393,40 @@ choose_pixel_format_arb_attribs (GdkWin32Display *display_win32,
/* Do we have a defined swap method? */
format = find_pixel_format_with_defined_swap_flag (hdc, formats, count);
if (format > 0)
goto done;
if (find_pixel_format_with_defined_swap_method (hdc, formats, count, &index, &swap_method))
{
if (!display_win32->wgl_quirks->disallow_swap_exchange || swap_method != WGL_SWAP_EXCHANGE_ARB)
{
format = formats[index];
goto done;
}
}
/* Nope, but we can try to ask for it explicitly */
const int swap_methods[] = {
WGL_SWAP_EXCHANGE_ARB,
const int swap_methods[] =
{
(display_win32->wgl_quirks->disallow_swap_exchange) ? 0 : WGL_SWAP_EXCHANGE_ARB,
WGL_SWAP_COPY_ARB,
};
for (size_t i = 0; i < G_N_ELEMENTS (swap_methods); i++)
{
if (swap_methods[i] == 0)
continue;
attribs_add (&attribs, WGL_SWAP_METHOD_ARB, swap_methods[i]);
EXT_CALL (wglChoosePixelFormatARB, (hdc, attribs_data (&attribs), NULL,
G_N_ELEMENTS (formats), formats,
&count));
format = find_pixel_format_with_defined_swap_flag (hdc, formats, count);
if (format > 0)
goto done;
if (find_pixel_format_with_defined_swap_method (hdc, formats, count, &index, &swap_method))
{
if (!display_win32->wgl_quirks->disallow_swap_exchange || swap_method != WGL_SWAP_EXCHANGE_ARB)
{
format = formats[index];
goto done;
}
}
attribs_reset (&attribs);
}
@@ -420,10 +444,9 @@ done:
}
static int
get_distance (PIXELFORMATDESCRIPTOR *pfd)
get_distance (PIXELFORMATDESCRIPTOR *pfd,
DWORD swap_flags)
{
const DWORD swap_flags = PFD_SWAP_COPY | PFD_SWAP_EXCHANGE;
int is_double_buffered = (pfd->dwFlags & PFD_DOUBLEBUFFER) != 0;
int is_swap_defined = (pfd->dwFlags & swap_flags) != 0;
int is_mono = (pfd->dwFlags & PFD_STEREO) == 0;
@@ -438,7 +461,7 @@ get_distance (PIXELFORMATDESCRIPTOR *pfd)
memory_distance;
}
/* ChoosePixelFormat ignored some fields and flags, which makes it
/* ChoosePixelFormat ignores some fields and flags, which makes it
* less useful for GTK. In particular, it ignores the PFD_SWAP flags,
* which are very important for GUI toolkits. Here we implement an
* analog function which is tied to the needs of GTK.
@@ -455,7 +478,9 @@ choose_pixel_format_opengl32 (GdkWin32Display *display_win32,
PFD_GENERIC_ACCELERATED;
const DWORD required_flags = PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
(display_win32->wgl_support_gdi ? PFD_SUPPORT_GDI : 0);
(display_win32->wgl_quirks->force_gdi_compatibility ? PFD_SUPPORT_GDI : 0);
const DWORD best_swap_flags = PFD_SWAP_COPY |
(display_win32->wgl_quirks->disallow_swap_exchange ? 0 : PFD_SWAP_EXCHANGE);
struct {
int index;
@@ -481,7 +506,7 @@ choose_pixel_format_opengl32 (GdkWin32Display *display_win32,
pfd.cBlueBits != 8 || pfd.cAlphaBits != 8))
continue;
current.distance = get_distance (&pfd);
current.distance = get_distance (&pfd, best_swap_flags);
if (best.index == 0 || current.distance < best.distance)
best = current;
@@ -606,6 +631,14 @@ check_driver_is_d3d12 (void)
g_ascii_strncasecmp (renderer, "D3D12", strlen ("D3D12")) == 0;
}
static bool
check_vendor_is_nvidia (void)
{
const char *vendor = (const char *) glGetString (GL_VENDOR);
return g_ascii_strncasecmp (vendor, "NVIDIA", strlen ("NVIDIA")) == 0;
}
GdkGLContext *
gdk_win32_display_init_wgl (GdkDisplay *display,
GError **error)
@@ -618,6 +651,9 @@ gdk_win32_display_init_wgl (GdkDisplay *display,
if (!gdk_gl_backend_can_be_used (GDK_GL_WGL, error))
return NULL;
g_assert (display_win32->wgl_quirks == NULL);
display_win32->wgl_quirks = g_new0 (struct wgl_quirks, 1);
/* acquire and cache dummy Window (HWND & HDC) and
* dummy GL Context, it is used to query functions
* and used for other stuff as well
@@ -658,7 +694,8 @@ gdk_win32_display_init_wgl (GdkDisplay *display,
display_win32->hasGlWINSwapHint =
epoxy_has_gl_extension ("GL_WIN_swap_hint");
display_win32->wgl_support_gdi = check_driver_is_d3d12();
display_win32->wgl_quirks->force_gdi_compatibility = check_driver_is_d3d12 ();
display_win32->wgl_quirks->disallow_swap_exchange = check_vendor_is_nvidia ();
context = g_object_new (GDK_TYPE_WIN32_GL_CONTEXT_WGL,
"display", display,
@@ -677,7 +714,8 @@ gdk_win32_display_init_wgl (GdkDisplay *display,
GDK_NOTE (OPENGL, g_print ("WGL API version %d.%d found\n"
" - Vendor: %s\n"
" - Renderer: %s\n"
" - GDI compatibility required: %s\n"
" - Quirks / force GDI compatiblity: %s\n"
" - Quirks / disallow swap exchange: %s\n"
" - Checked extensions:\n"
"\t* WGL_ARB_pixel_format: %s\n"
"\t* WGL_ARB_create_context: %s\n"
@@ -687,7 +725,8 @@ gdk_win32_display_init_wgl (GdkDisplay *display,
major, minor,
glGetString (GL_VENDOR),
glGetString (GL_RENDERER),
display_win32->wgl_support_gdi ? "yes" : "no",
display_win32->wgl_quirks->force_gdi_compatibility ? "enabled" : "disabled",
display_win32->wgl_quirks->disallow_swap_exchange ? "enabled" : "disabled",
display_win32->hasWglARBPixelFormat ? "yes" : "no",
display_win32->hasWglARBCreateContext ? "yes" : "no",
display_win32->hasWglEXTSwapControl ? "yes" : "no",
@@ -1095,16 +1134,15 @@ gdk_win32_gl_context_wgl_realize (GdkGLContext *context,
{
context_wgl->double_buffered = (query_values[0] == GL_TRUE);
context_wgl->swap_method = SWAP_METHOD_UNDEFINED;
switch (query_values[1])
{
case WGL_SWAP_COPY_ARB:
context_wgl->swap_method = SWAP_METHOD_COPY;
break;
case WGL_SWAP_EXCHANGE_ARB:
context_wgl->swap_method = SWAP_METHOD_EXCHANGE;
break;
default:
context_wgl->swap_method = SWAP_METHOD_UNDEFINED;
if (!display_win32->wgl_quirks->disallow_swap_exchange)
context_wgl->swap_method = SWAP_METHOD_EXCHANGE;
break;
}
}
@@ -1119,7 +1157,7 @@ gdk_win32_gl_context_wgl_realize (GdkGLContext *context,
if (pfd.dwFlags & PFD_SWAP_COPY)
context_wgl->swap_method = SWAP_METHOD_COPY;
else if (pfd.dwFlags & PFD_SWAP_EXCHANGE)
else if ((pfd.dwFlags & PFD_SWAP_EXCHANGE) && !display_win32->wgl_quirks->disallow_swap_exchange)
context_wgl->swap_method = SWAP_METHOD_EXCHANGE;
else
context_wgl->swap_method = SWAP_METHOD_UNDEFINED;

View File

@@ -1,44 +0,0 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Copyright (C) 1998-2002 Tor Lillqvist
*
* 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/>.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "config.h"
#include "gdktypes.h"
#include "gdkprivate-win32.h"
GdkDisplay *_gdk_display = NULL;
GdkDeviceManagerWin32 *_gdk_device_manager = NULL;
int _gdk_input_ignore_core;
HKL _gdk_input_locale;
gboolean _gdk_input_locale_is_ime = FALSE;
GdkWin32ModalOpKind _modal_operation_in_progress = GDK_WIN32_MODAL_OP_NONE;
HWND _modal_move_resize_hwnd = NULL;
/* The singleton clipdrop object pointer */
GdkWin32Clipdrop *_win32_clipdrop = NULL;
GThread *_win32_main_thread = NULL;

View File

@@ -37,6 +37,7 @@ typedef struct _GdkWin32HDataOutputStreamPrivate GdkWin32HDataOutputStreamPriva
struct _GdkWin32HDataOutputStreamPrivate
{
HANDLE handle;
GdkWin32Clipdrop *clipdrop;
guchar *data;
gsize data_allocated_size;
gsize data_length;
@@ -204,12 +205,13 @@ gdk_win32_hdata_output_stream_close (GOutputStream *output_stream,
return FALSE;
}
if (!_gdk_win32_transmute_contentformat (priv->pair.contentformat,
priv->pair.w32format,
priv->data,
priv->data_length,
&transmuted_data,
&transmuted_data_length))
if (!gdk_win32_clipdrop_transmute_contentformat (priv->clipdrop,
priv->pair.contentformat,
priv->pair.w32format,
priv->data,
priv->data_length,
&transmuted_data,
&transmuted_data_length))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Failed to transmute %zu bytes of data from %s to %u"),
@@ -343,7 +345,8 @@ gdk_win32_hdata_output_stream_init (GdkWin32HDataOutputStream *stream)
}
GOutputStream *
gdk_win32_hdata_output_stream_new (GdkWin32ContentFormatPair *pair,
gdk_win32_hdata_output_stream_new (GdkWin32Clipdrop *clipdrop,
GdkWin32ContentFormatPair *pair,
GError **error)
{
GdkWin32HDataOutputStream *stream;
@@ -369,6 +372,7 @@ gdk_win32_hdata_output_stream_new (GdkWin32ContentFormatPair *pair,
stream = g_object_new (GDK_TYPE_WIN32_HDATA_OUTPUT_STREAM, NULL);
priv = gdk_win32_hdata_output_stream_get_instance_private (stream);
priv->clipdrop = clipdrop;
priv->pair = *pair;
if (hmem)

View File

@@ -51,7 +51,8 @@ struct GdkWin32HDataOutputStreamClass
GType gdk_win32_hdata_output_stream_get_type (void) G_GNUC_CONST;
GOutputStream *gdk_win32_hdata_output_stream_new (GdkWin32ContentFormatPair *pair,
GOutputStream *gdk_win32_hdata_output_stream_new (GdkWin32Clipdrop *clipdrop,
GdkWin32ContentFormatPair *pair,
GError **error);
HANDLE gdk_win32_hdata_output_stream_get_handle (GdkWin32HDataOutputStream *stream,

View File

@@ -37,7 +37,7 @@
#include "gdkdevicemanager-win32.h"
#include "gdkdevice-virtual.h"
#include "gdkdeviceprivate.h"
#include "gdkdisplayprivate.h"
#include "gdkdisplay-win32.h"
#include "gdkeventsprivate.h"
#include "gdkseatdefaultprivate.h"
#include "gdkinput-dmanipulation.h"
@@ -48,9 +48,6 @@
typedef BOOL
(WINAPI *getPointerType_t)(UINT32 pointerId, POINTER_INPUT_TYPE *pointerType);
static getPointerType_t getPointerType;
static IDirectManipulationManager *dmanipulation_manager;
typedef struct
{
@@ -203,12 +200,13 @@ DManipEventHandler_OnContentUpdated (IDirectManipulationViewportEventHandler *se
POINT cursor = {0, 0};
float scale;
GdkEvent *event;
GdkDisplay *display = gdk_surface_get_display (self->surface);
scale = transform[0];
state = util_get_modifier_state ();
time = (uint32_t) GetMessageTime ();
_gdk_win32_get_cursor_pos (&cursor);
_gdk_win32_get_cursor_pos (display, &cursor);
ScreenToClient (GDK_SURFACE_HWND (self->surface), &cursor);
@@ -266,13 +264,14 @@ DManipEventHandler_OnViewportStatusChanged (IDirectManipulationViewportEventHand
uint32_t time;
POINT cursor = {0, 0};
GdkEvent *event;
GdkDisplay *display = gdk_surface_get_display (self->surface);
if (self->phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN)
break;
state = util_get_modifier_state ();
time = (uint32_t) GetMessageTime ();
_gdk_win32_get_cursor_pos (&cursor);
_gdk_win32_get_cursor_pos (display, &cursor);
ScreenToClient (GDK_SURFACE_HWND (self->surface), &cursor);
@@ -327,7 +326,7 @@ dmanip_event_handler_new (GdkSurface *surface,
handler->gesture = gesture;
handler->surface = surface;
handler->device = _gdk_device_manager->core_pointer;
handler->device = GDK_WIN32_DISPLAY (gdk_surface_get_display (surface))->device_manager->core_pointer;
dmanip_event_handler_running_state_clear (handler);
@@ -378,6 +377,28 @@ close_viewport (IDirectManipulationViewport **p_viewport)
}
}
#define GDK_DISPLAY_GET_DMANIP_MANAGER(d) GDK_WIN32_DISPLAY(d)->dmanip_items != NULL ? \
(IDirectManipulationManager *) ((dmanip_items *)(GDK_WIN32_DISPLAY(d)->dmanip_items)->manager) : \
NULL
#define GDK_DISPLAY_GET_GET_POINTER_TYPE(d) GDK_WIN32_DISPLAY(d)->dmanip_items != NULL ? \
(getPointerType_t) ((dmanip_items *)(GDK_WIN32_DISPLAY(d)->dmanip_items)->getPointerType) : \
NULL
void
gdk_win32_display_close_dmanip_manager (GdkDisplay *display)
{
if (GDK_WIN32_DISPLAY (display)->dmanip_items != NULL)
{
IDirectManipulationManager *manager = GDK_DISPLAY_GET_DMANIP_MANAGER (display);
if (manager != NULL)
IUnknown_Release (manager);
g_clear_pointer (&GDK_WIN32_DISPLAY (display)->dmanip_items, g_free);
}
}
static void
create_viewport (GdkSurface *surface,
int gesture,
@@ -388,6 +409,7 @@ create_viewport (GdkSurface *surface,
IDirectManipulationViewportEventHandler *handler = NULL;
DWORD cookie = 0;
HRESULT hr;
IDirectManipulationManager *dmanipulation_manager = GDK_DISPLAY_GET_DMANIP_MANAGER (gdk_surface_get_display (surface));
hr = IDirectManipulationManager_CreateViewport (dmanipulation_manager, NULL, hwnd,
&IID_IDirectManipulationViewport,
@@ -441,11 +463,14 @@ failed:
/* {{{ Public */
void gdk_dmanipulation_initialize (void)
void gdk_dmanipulation_initialize (GdkWin32Display *display)
{
if (!getPointerType)
if (display->dmanip_items == NULL)
{
IDirectManipulationManager *dmanipulation_manager;
getPointerType_t getPointerType;
HMODULE user32_mod;
HRESULT hr;
user32_mod = LoadLibraryW (L"user32.dll");
if (!user32_mod)
@@ -459,20 +484,22 @@ void gdk_dmanipulation_initialize (void)
if (!getPointerType)
return;
}
if (!gdk_win32_ensure_com ())
if (!gdk_win32_ensure_com ())
return;
if (dmanipulation_manager == NULL)
{
HRESULT hr;
display->dmanip_items = g_new0 (dmanip_items, 1);
display->dmanip_items->getPointerType = getPointerType;
hr = CoCreateInstance (&CLSID_DirectManipulationManager,
NULL,
CLSCTX_INPROC_SERVER,
&IID_IDirectManipulationManager,
(LPVOID*)&dmanipulation_manager);
if (SUCCEEDED (hr))
display->dmanip_items->manager = dmanipulation_manager;
if (FAILED (hr))
{
if (hr == REGDB_E_CLASSNOTREG || hr == E_NOINTERFACE);
@@ -487,6 +514,7 @@ void gdk_dmanipulation_initialize_surface (GdkSurface *surface)
{
GdkWin32Surface *surface_win32;
HRESULT hr;
IDirectManipulationManager *dmanipulation_manager = GDK_DISPLAY_GET_DMANIP_MANAGER (gdk_surface_get_display (surface));
if (!dmanipulation_manager)
return;
@@ -508,6 +536,8 @@ void gdk_dmanipulation_finalize_surface (GdkSurface *surface)
{
GdkWin32Surface *surface_win32 = GDK_WIN32_SURFACE (surface);
IDirectManipulationManager_Deactivate (GDK_DISPLAY_GET_DMANIP_MANAGER (gdk_surface_get_display (surface)),
GDK_SURFACE_HWND (surface));
close_viewport (&surface_win32->dmanipulation_viewport_zoom);
close_viewport (&surface_win32->dmanipulation_viewport_pan);
}
@@ -517,6 +547,9 @@ void gdk_dmanipulation_maybe_add_contact (GdkSurface *surface,
{
POINTER_INPUT_TYPE type = PT_POINTER;
UINT32 pointer_id = GET_POINTERID_WPARAM (msg->wParam);
GdkDisplay *display = gdk_surface_get_display (surface);
IDirectManipulationManager *dmanipulation_manager = GDK_DISPLAY_GET_DMANIP_MANAGER (display);
getPointerType_t getPointerType = GDK_DISPLAY_GET_GET_POINTER_TYPE (display);
if (!dmanipulation_manager)
return;

View File

@@ -20,7 +20,8 @@
#pragma once
void gdk_dmanipulation_initialize (void);
void gdk_dmanipulation_initialize (GdkWin32Display *display);
void gdk_win32_display_close_dmanip_manager (GdkDisplay *display);
void gdk_dmanipulation_initialize_surface (GdkSurface *surface);
void gdk_dmanipulation_finalize_surface (GdkSurface *surface);

View File

@@ -25,7 +25,7 @@
#include "gdkdevice-winpointer.h"
#include "gdkdeviceprivate.h"
#include "gdkdevicetoolprivate.h"
#include "gdkdisplayprivate.h"
#include "gdkdisplay-win32.h"
#include "gdkeventsprivate.h"
#include "gdkseatdefaultprivate.h"
@@ -65,40 +65,44 @@ typedef BOOL
typedef BOOL
(WINAPI *setWindowFeedbackSetting_t)(HWND hwnd, FEEDBACK_TYPE feedback, DWORD dwFlags, UINT32 size, const VOID *configuration);
static registerPointerDeviceNotifications_t registerPointerDeviceNotifications;
static getPointerDevices_t getPointerDevices;
static getPointerDeviceCursors_t getPointerDeviceCursors;
static getPointerDeviceRects_t getPointerDeviceRects;
static getPointerType_t getPointerType;
static getPointerCursorId_t getPointerCursorId;
static getPointerPenInfo_t getPointerPenInfo;
static getPointerTouchInfo_t getPointerTouchInfo;
static getPointerPenInfoHistory_t getPointerPenInfoHistory;
static getPointerTouchInfoHistory_t getPointerTouchInfoHistory;
static setGestureConfig_t setGestureConfig;
static setWindowFeedbackSetting_t setWindowFeedbackSetting;
struct _GdkDeviceManagerWin32WinpointerFuncs
{
registerPointerDeviceNotifications_t registerPointerDeviceNotifications;
getPointerDevices_t getPointerDevices;
getPointerDeviceCursors_t getPointerDeviceCursors;
getPointerDeviceRects_t getPointerDeviceRects;
getPointerType_t getPointerType;
getPointerCursorId_t getPointerCursorId;
getPointerPenInfo_t getPointerPenInfo;
getPointerTouchInfo_t getPointerTouchInfo;
getPointerPenInfoHistory_t getPointerPenInfoHistory;
getPointerTouchInfoHistory_t getPointerTouchInfoHistory;
setGestureConfig_t setGestureConfig;
setWindowFeedbackSetting_t setWindowFeedbackSetting;
};
typedef struct _GdkDeviceManagerWin32WinpointerFuncs GdkDeviceManagerWin32WinpointerFuncs;
static ATOM notifications_window_class;
static HWND notifications_window_handle;
static GPtrArray *ignored_interactions;
#define WINPOINTER_API(dm,f) ((GdkDeviceManagerWin32WinpointerFuncs *)dm->winpointer_funcs)->f
static inline void
winpointer_ignore_interaction (UINT32 pointer_id)
winpointer_ignore_interaction (GdkDeviceManagerWin32 *device_manager,
UINT32 pointer_id)
{
g_ptr_array_add (ignored_interactions, GUINT_TO_POINTER (pointer_id));
g_ptr_array_add (device_manager->ignored_interactions, GUINT_TO_POINTER (pointer_id));
}
static inline void
winpointer_remove_ignored_interaction (UINT32 pointer_id)
winpointer_remove_ignored_interaction (GdkDeviceManagerWin32 *device_manager,
UINT32 pointer_id)
{
g_ptr_array_remove_fast (ignored_interactions, GUINT_TO_POINTER (pointer_id));
g_ptr_array_remove_fast (device_manager->ignored_interactions, GUINT_TO_POINTER (pointer_id));
}
static inline gboolean
winpointer_should_ignore_interaction (UINT32 pointer_id)
winpointer_should_ignore_interaction (GdkDeviceManagerWin32 *device_manager,
UINT32 pointer_id)
{
return g_ptr_array_find (ignored_interactions, GUINT_TO_POINTER (pointer_id), NULL);
return g_ptr_array_find (device_manager->ignored_interactions, GUINT_TO_POINTER (pointer_id), NULL);
}
static inline guint32
@@ -136,11 +140,12 @@ copy_axes (double *axes)
}
static GdkDeviceWinpointer*
winpointer_find_device_with_source (HANDLE device_handle,
UINT32 cursor_id,
GdkInputSource input_source)
winpointer_find_device_with_source (GdkDeviceManagerWin32 *device_manager,
HANDLE device_handle,
UINT32 cursor_id,
GdkInputSource input_source)
{
for (GList *l = _gdk_device_manager->winpointer_devices; l != NULL; l = l->next)
for (GList *l = device_manager->winpointer_devices; l != NULL; l = l->next)
{
GdkDeviceWinpointer *device = (GdkDeviceWinpointer*) l->data;
@@ -157,9 +162,10 @@ winpointer_find_device_with_source (HANDLE device_handle,
}
static gboolean
winpointer_get_event_type (MSG *msg,
POINTER_INFO *info,
GdkEventType *evt_type)
winpointer_get_event_type (GdkDeviceManagerWin32 *device_manager,
MSG *msg,
POINTER_INFO *info,
GdkEventType *evt_type)
{
switch (info->pointerType)
{
@@ -189,7 +195,7 @@ winpointer_get_event_type (MSG *msg,
if (IS_POINTER_CANCELED_WPARAM (msg->wParam) ||
!HAS_POINTER_CONFIDENCE_WPARAM (msg->wParam))
{
winpointer_ignore_interaction (GET_POINTERID_WPARAM (msg->wParam));
winpointer_ignore_interaction (device_manager, GET_POINTERID_WPARAM (msg->wParam));
if (((info->pointerFlags & POINTER_FLAG_INCONTACT) &&
(info->pointerFlags & POINTER_FLAG_UPDATE)) ||
@@ -249,10 +255,11 @@ winpointer_make_event (GdkDeviceWinpointer *device,
GdkEventType evt_type;
GdkEvent *evt = NULL;
GdkDevice *core_device = NULL;
GdkDeviceManagerWin32 *device_manager = GDK_WIN32_DISPLAY (gdk_surface_get_display (surface))->device_manager;
core_device = _gdk_device_manager->core_pointer;
core_device = device_manager->core_pointer;
if (!winpointer_get_event_type (msg, info, &evt_type))
if (!winpointer_get_event_type (device_manager, msg, info, &evt_type))
return;
time = winpointer_get_time (msg, info);
@@ -399,14 +406,16 @@ gdk_winpointer_input_events (GdkSurface *surface,
UINT32 pointer_id = GET_POINTERID_WPARAM (msg->wParam);
POINTER_INPUT_TYPE type = PT_POINTER;
UINT32 cursor_id = 0;
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (gdk_surface_get_display (surface));
GdkDeviceManagerWin32 *device_manager = display_win32->device_manager;
if (!getPointerType (pointer_id, &type))
if (!WINPOINTER_API (device_manager, getPointerType) (pointer_id, &type))
{
WIN32_API_FAILED_LOG_ONCE ("GetPointerType");
return;
}
if (!getPointerCursorId (pointer_id, &cursor_id))
if (!WINPOINTER_API (device_manager, getPointerCursorId) (pointer_id, &cursor_id))
{
WIN32_API_FAILED_LOG_ONCE ("GetPointerCursorId");
return;
@@ -415,7 +424,7 @@ gdk_winpointer_input_events (GdkSurface *surface,
if (winpointer_should_filter_message (msg, type))
return;
if (winpointer_should_ignore_interaction (pointer_id))
if (winpointer_should_ignore_interaction (device_manager, pointer_id))
return;
switch (type)
@@ -431,7 +440,7 @@ gdk_winpointer_input_events (GdkSurface *surface,
do
{
infos = g_new0 (POINTER_PEN_INFO, history_count);
if (!getPointerPenInfoHistory (pointer_id, &history_count, infos))
if (!WINPOINTER_API (device_manager, getPointerPenInfoHistory) (pointer_id, &history_count, infos))
{
WIN32_API_FAILED_LOG_ONCE ("GetPointerPenInfoHistory");
g_free (infos);
@@ -443,7 +452,7 @@ gdk_winpointer_input_events (GdkSurface *surface,
if (G_UNLIKELY (history_count == 0))
return;
device = winpointer_find_device_with_source (infos->pointerInfo.sourceDevice, cursor_id, GDK_SOURCE_PEN);
device = winpointer_find_device_with_source (device_manager, infos->pointerInfo.sourceDevice, cursor_id, GDK_SOURCE_PEN);
if (G_UNLIKELY (!device))
{
g_free (infos);
@@ -484,7 +493,7 @@ gdk_winpointer_input_events (GdkSurface *surface,
do
{
infos = g_new0 (POINTER_TOUCH_INFO, history_count);
if (!getPointerTouchInfoHistory (pointer_id, &history_count, infos))
if (!WINPOINTER_API (device_manager, getPointerTouchInfoHistory) (pointer_id, &history_count, infos))
{
WIN32_API_FAILED_LOG_ONCE ("GetPointerTouchInfoHistory");
g_free (infos);
@@ -496,7 +505,7 @@ gdk_winpointer_input_events (GdkSurface *surface,
if (G_UNLIKELY (history_count == 0))
return;
device = winpointer_find_device_with_source (infos->pointerInfo.sourceDevice, cursor_id, GDK_SOURCE_TOUCHSCREEN);
device = winpointer_find_device_with_source (device_manager, infos->pointerInfo.sourceDevice, cursor_id, GDK_SOURCE_TOUCHSCREEN);
if (G_UNLIKELY (!device))
{
g_free (infos);
@@ -524,21 +533,23 @@ gdk_winpointer_input_events (GdkSurface *surface,
}
gboolean
gdk_winpointer_get_message_info (MSG *msg,
GdkDevice **device,
guint32 *time)
gdk_winpointer_get_message_info (MSG *msg,
GdkDevice **device,
GdkWin32Display *display_win32,
guint32 *time)
{
UINT32 pointer_id = GET_POINTERID_WPARAM (msg->wParam);
POINTER_INPUT_TYPE type = PT_POINTER;
UINT32 cursor_id = 0;
GdkDeviceManagerWin32 *device_manager = display_win32->device_manager;
if (!getPointerType (pointer_id, &type))
if (!WINPOINTER_API (device_manager, getPointerType) (pointer_id, &type))
{
WIN32_API_FAILED_LOG_ONCE ("GetPointerType");
return FALSE;
}
if (!getPointerCursorId (pointer_id, &cursor_id))
if (!WINPOINTER_API (device_manager, getPointerCursorId) (pointer_id, &cursor_id))
{
WIN32_API_FAILED_LOG_ONCE ("GetPointerCursorId");
return FALSE;
@@ -550,13 +561,13 @@ gdk_winpointer_get_message_info (MSG *msg,
{
POINTER_PEN_INFO pen_info;
if (!getPointerPenInfo (pointer_id, &pen_info))
if (!WINPOINTER_API (device_manager, getPointerPenInfo) (pointer_id, &pen_info))
{
WIN32_API_FAILED_LOG_ONCE ("GetPointerPenInfo");
return FALSE;
}
*device = (GdkDevice*) winpointer_find_device_with_source (pen_info.pointerInfo.sourceDevice, cursor_id, GDK_SOURCE_PEN);
*device = (GdkDevice*) winpointer_find_device_with_source (device_manager, pen_info.pointerInfo.sourceDevice, cursor_id, GDK_SOURCE_PEN);
*time = winpointer_get_time (msg, &pen_info.pointerInfo);
}
break;
@@ -564,13 +575,14 @@ gdk_winpointer_get_message_info (MSG *msg,
{
POINTER_TOUCH_INFO touch_info;
if (!getPointerTouchInfo (pointer_id, &touch_info))
if (!WINPOINTER_API (device_manager, getPointerTouchInfo) (pointer_id, &touch_info))
{
WIN32_API_FAILED_LOG_ONCE ("GetPointerTouchInfo");
return FALSE;
}
*device = GDK_DEVICE (winpointer_find_device_with_source (touch_info.pointerInfo.sourceDevice,
*device = GDK_DEVICE (winpointer_find_device_with_source (device_manager,
touch_info.pointerInfo.sourceDevice,
cursor_id,
GDK_SOURCE_TOUCHSCREEN));
@@ -587,12 +599,13 @@ gdk_winpointer_get_message_info (MSG *msg,
}
gboolean
gdk_winpointer_should_forward_message (MSG *msg)
gdk_winpointer_should_forward_message (GdkDeviceManagerWin32 *device_manager,
MSG *msg)
{
UINT32 pointer_id = GET_POINTERID_WPARAM (msg->wParam);
POINTER_INPUT_TYPE type = PT_POINTER;
if (!getPointerType (pointer_id, &type))
if (!WINPOINTER_API (device_manager, getPointerType) (pointer_id, &type))
{
WIN32_API_FAILED_LOG_ONCE ("GetPointerType");
return TRUE;
@@ -602,9 +615,10 @@ gdk_winpointer_should_forward_message (MSG *msg)
}
void
gdk_winpointer_interaction_ended (MSG *msg)
gdk_winpointer_interaction_ended (GdkDeviceManagerWin32 *device_manager,
MSG *msg)
{
winpointer_remove_ignored_interaction (GET_POINTERID_WPARAM (msg->wParam));
winpointer_remove_ignored_interaction (device_manager, GET_POINTERID_WPARAM (msg->wParam));
}
static inline double
@@ -626,12 +640,13 @@ utils_rect_is_degenerate (RECT *rect)
}
static gboolean
winpointer_device_update_scale_factors (GdkDeviceWinpointer *device)
winpointer_device_update_scale_factors (GdkDeviceWinpointer *device,
GdkDeviceManagerWin32 *device_manager)
{
RECT device_rect;
RECT display_rect;
if (!getPointerDeviceRects (device->device_handle, &device_rect, &display_rect))
if (!WINPOINTER_API (device_manager, getPointerDeviceRects) (device->device_handle, &device_rect, &display_rect))
{
WIN32_API_FAILED ("GetPointerDeviceRects");
return FALSE;
@@ -716,8 +731,9 @@ winpointer_get_device_details (HANDLE device,
}
static void
winpointer_create_device (POINTER_DEVICE_INFO *info,
GdkInputSource source)
winpointer_create_device (GdkDeviceManagerWin32 *device_manager,
POINTER_DEVICE_INFO *info,
GdkInputSource source)
{
GdkDeviceWinpointer *device = NULL;
GdkSeat *seat = NULL;
@@ -731,12 +747,12 @@ winpointer_create_device (POINTER_DEVICE_INFO *info,
UINT32 num_cursors = 0;
GdkAxisFlags axes_flags = 0;
seat = gdk_display_get_default_seat (_gdk_display);
seat = gdk_display_get_default_seat (device_manager->display);
memset (pid, 0, VID_PID_CHARS + 1);
memset (vid, 0, VID_PID_CHARS + 1);
if (!getPointerDeviceCursors (info->device, &num_cursors, NULL))
if (!WINPOINTER_API (device_manager, getPointerDeviceCursors) (info->device, &num_cursors, NULL))
{
WIN32_API_FAILED ("GetPointerDeviceCursors");
return;
@@ -780,7 +796,7 @@ winpointer_create_device (POINTER_DEVICE_INFO *info,
}
device = g_object_new (GDK_TYPE_DEVICE_WINPOINTER,
"display", _gdk_display,
"display", device_manager->display,
"seat", seat,
"has-cursor", TRUE,
"source", source,
@@ -820,7 +836,7 @@ winpointer_create_device (POINTER_DEVICE_INFO *info,
device->start_cursor_id = info->startingCursorId;
device->end_cursor_id = info->startingCursorId + num_cursors - 1;
if (!winpointer_device_update_scale_factors (device))
if (!winpointer_device_update_scale_factors (device, device_manager))
{
g_set_object (&device, NULL);
goto cleanup;
@@ -844,10 +860,10 @@ winpointer_create_device (POINTER_DEVICE_INFO *info,
break;
}
_gdk_device_manager->winpointer_devices = g_list_append (_gdk_device_manager->winpointer_devices, device);
device_manager->winpointer_devices = g_list_append (device_manager->winpointer_devices, device);
_gdk_device_set_associated_device (GDK_DEVICE (device), _gdk_device_manager->core_pointer);
_gdk_device_add_physical_device (_gdk_device_manager->core_pointer, GDK_DEVICE (device));
_gdk_device_set_associated_device (GDK_DEVICE (device), device_manager->core_pointer);
_gdk_device_add_physical_device (device_manager->core_pointer, GDK_DEVICE (device));
gdk_seat_default_add_physical_device (GDK_SEAT_DEFAULT (seat), GDK_DEVICE (device));
@@ -859,16 +875,17 @@ cleanup:
}
static void
winpointer_create_devices (POINTER_DEVICE_INFO *info)
winpointer_create_devices (GdkDeviceManagerWin32 *device_manager,
POINTER_DEVICE_INFO *info)
{
switch (info->pointerDeviceType)
{
case POINTER_DEVICE_TYPE_INTEGRATED_PEN:
case POINTER_DEVICE_TYPE_EXTERNAL_PEN:
winpointer_create_device (info, GDK_SOURCE_PEN);
winpointer_create_device (device_manager, info, GDK_SOURCE_PEN);
break;
case POINTER_DEVICE_TYPE_TOUCH:
winpointer_create_device (info, GDK_SOURCE_TOUCHSCREEN);
winpointer_create_device (device_manager, info, GDK_SOURCE_TOUCHSCREEN);
break;
default:
g_warn_if_reached ();
@@ -894,9 +911,10 @@ winpointer_find_device_in_system_list (GdkDeviceWinpointer *device,
}
static gboolean
winpointer_find_system_device_in_device_manager (POINTER_DEVICE_INFO *info)
winpointer_find_system_device_in_device_manager (GdkDeviceManagerWin32 *device_manager,
POINTER_DEVICE_INFO *info)
{
for (GList *l = _gdk_device_manager->winpointer_devices; l != NULL; l = l->next)
for (GList *l = device_manager->winpointer_devices; l != NULL; l = l->next)
{
GdkDeviceWinpointer *device = GDK_DEVICE_WINPOINTER (l->data);
@@ -911,7 +929,7 @@ winpointer_find_system_device_in_device_manager (POINTER_DEVICE_INFO *info)
}
static void
winpointer_enumerate_devices (void)
winpointer_enumerate_devices (GdkDeviceManagerWin32 *device_manager)
{
POINTER_DEVICE_INFO *infos = NULL;
UINT32 infos_count = 0;
@@ -921,7 +939,7 @@ winpointer_enumerate_devices (void)
do
{
infos = g_new0 (POINTER_DEVICE_INFO, infos_count);
if (!getPointerDevices (&infos_count, infos))
if (!WINPOINTER_API (device_manager, getPointerDevices) (&infos_count, infos))
{
WIN32_API_FAILED ("GetPointerDevices");
g_free (infos);
@@ -930,7 +948,7 @@ winpointer_enumerate_devices (void)
}
while (infos_count > 0 && !infos);
current = _gdk_device_manager->winpointer_devices;
current = device_manager->winpointer_devices;
while (current != NULL)
{
@@ -941,7 +959,7 @@ winpointer_enumerate_devices (void)
{
GdkSeat *seat = gdk_device_get_seat (GDK_DEVICE (device));
_gdk_device_manager->winpointer_devices = g_list_delete_link (_gdk_device_manager->winpointer_devices,
device_manager->winpointer_devices = g_list_delete_link (device_manager->winpointer_devices,
current);
gdk_device_update_tool (GDK_DEVICE (device), NULL);
@@ -953,7 +971,7 @@ winpointer_enumerate_devices (void)
gdk_seat_default_remove_tool (GDK_SEAT_DEFAULT (seat), device->tool_eraser);
_gdk_device_set_associated_device (GDK_DEVICE (device), NULL);
_gdk_device_remove_physical_device (_gdk_device_manager->core_pointer, GDK_DEVICE (device));
_gdk_device_remove_physical_device (device_manager->core_pointer, GDK_DEVICE (device));
gdk_seat_default_remove_physical_device (GDK_SEAT_DEFAULT (seat), GDK_DEVICE (device));
@@ -961,7 +979,7 @@ winpointer_enumerate_devices (void)
}
else
{
winpointer_device_update_scale_factors (device);
winpointer_device_update_scale_factors (device, device_manager);
}
current = next;
@@ -970,9 +988,9 @@ winpointer_enumerate_devices (void)
/* create new gdk devices */
for (i = 0; i < infos_count; i++)
{
if (!winpointer_find_system_device_in_device_manager (&infos[i]))
if (!winpointer_find_system_device_in_device_manager (device_manager, &infos[i]))
{
winpointer_create_devices (&infos[i]);
winpointer_create_devices (device_manager, &infos[i]);
}
}
@@ -985,20 +1003,31 @@ winpointer_notifications_window_procedure (HWND hWnd,
WPARAM wParam,
LPARAM lParam)
{
GdkDeviceManagerWin32 *device_manager;
CREATESTRUCT *cs = NULL;
switch (uMsg)
{
case WM_NCCREATE:
cs = (CREATESTRUCT *)lParam;
device_manager = cs->lpCreateParams;
SetWindowLongPtr (hWnd, GWLP_USERDATA, (LONG_PTR)device_manager);
return TRUE;
case WM_POINTERDEVICECHANGE:
winpointer_enumerate_devices ();
device_manager = (GdkDeviceManagerWin32 *) GetWindowLongPtr (hWnd, GWLP_USERDATA);
winpointer_enumerate_devices (device_manager);
return 0;
}
return DefWindowProcW (hWnd, uMsg, wParam, lParam);
}
static gboolean
winpointer_notif_window_create (void)
static HWND
winpointer_notif_window_create (GdkDeviceManagerWin32 *device_manager)
{
WNDCLASSEXW wndclassex;
ATOM notifications_window_class;
HWND notification_window_hwnd = NULL;
memset (&wndclassex, 0, sizeof (wndclassex));
wndclassex.cbSize = sizeof (wndclassex);
@@ -1006,100 +1035,111 @@ winpointer_notif_window_create (void)
wndclassex.lpfnWndProc = winpointer_notifications_window_procedure;
wndclassex.hInstance = this_module ();
if ((notifications_window_class = RegisterClassExW (&wndclassex)) == 0)
{
WIN32_API_FAILED ("RegisterClassExW");
return FALSE;
}
notifications_window_class = RegisterClassExW (&wndclassex);
if (!(notifications_window_handle = CreateWindowExW (0,
(LPCWSTR)(guintptr)notifications_window_class,
L"GdkWin32 Winpointer Notifications",
0,
0, 0, 0, 0,
HWND_MESSAGE,
NULL,
this_module (),
NULL)))
if (notifications_window_class != 0)
{
WIN32_API_FAILED ("CreateWindowExW");
return FALSE;
}
notification_window_hwnd = CreateWindowExW (0,
(LPCWSTR)(guintptr)notifications_window_class,
L"GdkWin32 Winpointer Notifications",
0,
0, 0, 0, 0,
HWND_MESSAGE,
NULL,
this_module (),
device_manager);
return TRUE;
if (notification_window_hwnd == NULL)
WIN32_API_FAILED ("CreateWindowExW");
}
else
WIN32_API_FAILED ("RegisterClassExW");
return notification_window_hwnd;
}
static gboolean
winpointer_ensure_procedures (void)
winpointer_ensure_procedures (GdkDeviceManagerWin32 *device_manager)
{
static HMODULE user32_dll = NULL;
GdkDeviceManagerWin32WinpointerFuncs *funcs = NULL;
static gsize user32_dll_checked = 0;
if (!user32_dll)
if (g_once_init_enter (&user32_dll_checked))
{
user32_dll = LoadLibraryW (L"user32.dll");
if (!user32_dll)
{
WIN32_API_FAILED ("LoadLibraryW");
return FALSE;
}
HMODULE user32_dll = NULL;
registerPointerDeviceNotifications = (registerPointerDeviceNotifications_t)
GetProcAddress (user32_dll, "RegisterPointerDeviceNotifications");
getPointerDevices = (getPointerDevices_t)
GetProcAddress (user32_dll, "GetPointerDevices");
getPointerDeviceCursors = (getPointerDeviceCursors_t)
GetProcAddress (user32_dll, "GetPointerDeviceCursors");
getPointerDeviceRects = (getPointerDeviceRects_t)
GetProcAddress (user32_dll, "GetPointerDeviceRects");
getPointerType = (getPointerType_t)
GetProcAddress (user32_dll, "GetPointerType");
getPointerCursorId = (getPointerCursorId_t)
GetProcAddress (user32_dll, "GetPointerCursorId");
getPointerPenInfo = (getPointerPenInfo_t)
GetProcAddress (user32_dll, "GetPointerPenInfo");
getPointerTouchInfo = (getPointerTouchInfo_t)
GetProcAddress (user32_dll, "GetPointerTouchInfo");
getPointerPenInfoHistory = (getPointerPenInfoHistory_t)
GetProcAddress (user32_dll, "GetPointerPenInfoHistory");
getPointerTouchInfoHistory = (getPointerTouchInfoHistory_t)
GetProcAddress (user32_dll, "GetPointerTouchInfoHistory");
setGestureConfig = (setGestureConfig_t)
GetProcAddress (user32_dll, "SetGestureConfig");
setWindowFeedbackSetting = (setWindowFeedbackSetting_t)
GetProcAddress (user32_dll, "SetWindowFeedbackSetting");
user32_dll = LoadLibraryW (L"user32.dll");
if (user32_dll)
{
funcs = g_new0 (GdkDeviceManagerWin32WinpointerFuncs, 1);
funcs->registerPointerDeviceNotifications = (registerPointerDeviceNotifications_t)
GetProcAddress (user32_dll, "RegisterPointerDeviceNotifications");
funcs->getPointerDevices = (getPointerDevices_t)
GetProcAddress (user32_dll, "GetPointerDevices");
funcs->getPointerDeviceCursors = (getPointerDeviceCursors_t)
GetProcAddress (user32_dll, "GetPointerDeviceCursors");
funcs->getPointerDeviceRects = (getPointerDeviceRects_t)
GetProcAddress (user32_dll, "GetPointerDeviceRects");
funcs->getPointerType = (getPointerType_t)
GetProcAddress (user32_dll, "GetPointerType");
funcs->getPointerCursorId = (getPointerCursorId_t)
GetProcAddress (user32_dll, "GetPointerCursorId");
funcs->getPointerPenInfo = (getPointerPenInfo_t)
GetProcAddress (user32_dll, "GetPointerPenInfo");
funcs->getPointerTouchInfo = (getPointerTouchInfo_t)
GetProcAddress (user32_dll, "GetPointerTouchInfo");
funcs->getPointerPenInfoHistory = (getPointerPenInfoHistory_t)
GetProcAddress (user32_dll, "GetPointerPenInfoHistory");
funcs->getPointerTouchInfoHistory = (getPointerTouchInfoHistory_t)
GetProcAddress (user32_dll, "GetPointerTouchInfoHistory");
funcs->setGestureConfig = (setGestureConfig_t)
GetProcAddress (user32_dll, "SetGestureConfig");
funcs->setWindowFeedbackSetting = (setWindowFeedbackSetting_t)
GetProcAddress (user32_dll, "SetWindowFeedbackSetting");
if (funcs->registerPointerDeviceNotifications &&
funcs->getPointerDevices &&
funcs->getPointerDeviceCursors &&
funcs->getPointerDeviceRects &&
funcs->getPointerType &&
funcs->getPointerCursorId &&
funcs->getPointerPenInfo &&
funcs->getPointerTouchInfo &&
funcs->getPointerPenInfoHistory &&
funcs->getPointerTouchInfoHistory)
device_manager->winpointer_funcs = funcs;
}
else
WIN32_API_FAILED ("LoadLibraryW");
g_once_init_leave (&user32_dll_checked, 1);
}
return registerPointerDeviceNotifications &&
getPointerDevices &&
getPointerDeviceCursors &&
getPointerDeviceRects &&
getPointerType &&
getPointerCursorId &&
getPointerPenInfo &&
getPointerTouchInfo &&
getPointerPenInfoHistory &&
getPointerTouchInfoHistory &&
setGestureConfig;
return (device_manager->winpointer_funcs != NULL);
}
gboolean
gdk_winpointer_initialize (void)
gdk_winpointer_initialize (GdkDeviceManagerWin32 *device_manager)
{
if (!winpointer_ensure_procedures ())
HWND notification_hwnd = NULL;
if (!winpointer_ensure_procedures (device_manager))
return FALSE;
if (!winpointer_notif_window_create ())
notification_hwnd = winpointer_notif_window_create (device_manager);
if (notification_hwnd == NULL)
return FALSE;
if (!registerPointerDeviceNotifications (notifications_window_handle, FALSE))
if (!WINPOINTER_API (device_manager, registerPointerDeviceNotifications) (notification_hwnd, FALSE))
{
WIN32_API_FAILED ("RegisterPointerDeviceNotifications");
return FALSE;
}
ignored_interactions = g_ptr_array_new ();
device_manager->winpointer_notification_hwnd = notification_hwnd;
device_manager->ignored_interactions = g_ptr_array_new ();
winpointer_enumerate_devices ();
winpointer_enumerate_devices (device_manager);
return TRUE;
}
@@ -1120,13 +1160,14 @@ gdk_winpointer_initialize_surface (GdkSurface *surface)
TABLET_DISABLE_FLICKS |
TABLET_DISABLE_FLICKFALLBACKKEYS);
winpointer_ensure_procedures ();
GdkDeviceManagerWin32 *device_manager = GDK_WIN32_DISPLAY (gdk_surface_get_display (surface))->device_manager;
winpointer_ensure_procedures (device_manager);
key = GlobalAddAtom (MICROSOFT_TABLETPENSERVICE_PROPERTY);
API_CALL (SetPropW, (hwnd, (LPCWSTR)(guintptr)key, val));
GlobalDeleteAtom (key);
if (setGestureConfig != NULL)
if (WINPOINTER_API (device_manager, setGestureConfig) != NULL)
{
GESTURECONFIG gesture_config;
memset (&gesture_config, 0, sizeof (gesture_config));
@@ -1135,10 +1176,10 @@ gdk_winpointer_initialize_surface (GdkSurface *surface)
gesture_config.dwWant = 0;
gesture_config.dwBlock = GC_ALLGESTURES;
API_CALL (setGestureConfig, (hwnd, 0, 1, &gesture_config, sizeof (gesture_config)));
API_CALL (WINPOINTER_API (device_manager,setGestureConfig), (hwnd, 0, 1, &gesture_config, sizeof (gesture_config)));
}
if (setWindowFeedbackSetting != NULL)
if (WINPOINTER_API (device_manager, setWindowFeedbackSetting) != NULL)
{
FEEDBACK_TYPE feedbacks[] = {
FEEDBACK_TOUCH_CONTACTVISUALIZATION,
@@ -1159,7 +1200,7 @@ gdk_winpointer_initialize_surface (GdkSurface *surface)
{
BOOL setting = FALSE;
API_CALL (setWindowFeedbackSetting, (hwnd, feedbacks[i], 0, sizeof (BOOL), &setting));
API_CALL (WINPOINTER_API (device_manager, setWindowFeedbackSetting), (hwnd, feedbacks[i], 0, sizeof (BOOL), &setting));
}
}
}

View File

@@ -19,7 +19,7 @@
#include "winpointer.h"
gboolean gdk_winpointer_initialize (void);
gboolean gdk_winpointer_initialize (GdkDeviceManagerWin32 *device_manager);
void gdk_winpointer_initialize_surface (GdkSurface *surface);
void gdk_winpointer_finalize_surface (GdkSurface *surface);
@@ -30,12 +30,15 @@ typedef void
POINT *screen_pt,
guint32 time_);
gboolean gdk_winpointer_should_forward_message (MSG *msg);
gboolean gdk_winpointer_should_forward_message (GdkDeviceManagerWin32 *device_manager,
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);
gboolean gdk_winpointer_get_message_info (MSG *msg,
GdkDevice **device,
GdkWin32Display *display_win32,
guint32 *time_);
void gdk_winpointer_interaction_ended (GdkDeviceManagerWin32 *device_manager,
MSG *msg);

View File

@@ -29,7 +29,7 @@
#include "gdkprivate-win32.h"
#include "gdkdebugprivate.h"
#include "gdkdisplayprivate.h"
#include "gdkdisplay-win32.h"
#include "gdkkeysyms.h"
#include "gdkkeysprivate.h"
#include "gdkkeys-win32.h"
@@ -77,9 +77,7 @@ struct _GdkWin32Keymap
G_DEFINE_TYPE (GdkWin32Keymap, gdk_win32_keymap, GDK_TYPE_KEYMAP)
guint _gdk_keymap_serial = 0;
static GdkKeymap *default_keymap = NULL;
/* forward declarations */
static void update_keymap (GdkWin32Keymap *gdk_keymap);
static void clear_keyboard_layout_info (gpointer data);
@@ -107,7 +105,14 @@ gdk_win32_keymap_init (GdkWin32Keymap *keymap)
if (_gdk_win32_check_processor (GDK_WIN32_WOW64))
keymap->gdkwin32_keymap_impl = &gdkwin32_keymap_impl_wow64;
#endif
}
static void
gdk_win32_keymap_constructed (GObject *object)
{
GdkWin32Keymap *keymap;
keymap = GDK_WIN32_KEYMAP (object);
update_keymap (keymap);
}
@@ -583,8 +588,10 @@ update_keymap (GdkWin32Keymap *keymap)
BOOL changed = FALSE;
int n_layouts;
int i;
GdkWin32Display *display = GDK_WIN32_DISPLAY (GDK_KEYMAP (keymap)->display);
if (keymap->current_serial == _gdk_keymap_serial &&
if (keymap->current_serial == gdk_win32_display_get_keymap_serial (display) &&
keymap->layout_handles->len > 0)
{
return;
@@ -643,7 +650,7 @@ update_keymap (GdkWin32Keymap *keymap)
if (changed)
ActivateKeyboardLayout (current_layout, 0);
keymap->current_serial = _gdk_keymap_serial;
keymap->current_serial = gdk_win32_display_get_keymap_serial (display);
}
guint8
@@ -677,17 +684,6 @@ _gdk_win32_keymap_get_active_group (GdkWin32Keymap *keymap)
return 0;
}
GdkKeymap*
_gdk_win32_display_get_keymap (GdkDisplay *display)
{
g_return_val_if_fail (display == gdk_display_get_default (), NULL);
if (default_keymap == NULL)
default_keymap = g_object_new (gdk_win32_keymap_get_type (), NULL);
return default_keymap;
}
GdkModifierType
_gdk_win32_keymap_get_mod_mask (GdkWin32Keymap *keymap)
{
@@ -1071,6 +1067,7 @@ gdk_win32_keymap_class_init (GdkWin32KeymapClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
object_class->constructed = gdk_win32_keymap_constructed;
object_class->finalize = gdk_win32_keymap_finalize;
keymap_class->get_direction = gdk_win32_keymap_get_direction;

View File

@@ -26,6 +26,7 @@
#include <io.h>
#include "gdk.h"
#include "gdkmain-win32.h"
#include "gdkdebugprivate.h"
#include "gdkkeysyms.h"
#include <glib/gi18n-lib.h>
@@ -39,24 +40,15 @@
#include <wintab.h>
#include <imm.h>
#include <stdbool.h>
/* Whether GDK initialized COM */
static gboolean co_initialized = FALSE;
/* Whether GDK initialized OLE */
static gboolean ole_initialized = FALSE;
void
_gdk_win32_surfaceing_init (void)
{
_gdk_win32_clipdrop_init ();
gdk_dmanipulation_initialize ();
}
gboolean
gdk_win32_ensure_com (void)
{
if (!co_initialized)
static gsize co_initialized = 0;
if (g_once_init_enter (&co_initialized))
{
/* UI thread should only use STA model. See
* -> https://devblogs.microsoft.com/oldnewthing/20080424-00/?p=22603
@@ -64,11 +56,12 @@ gdk_win32_ensure_com (void)
*/
const DWORD flags = COINIT_APARTMENTTHREADED |
COINIT_DISABLE_OLE1DDE;
gboolean init_result = FALSE;
HRESULT hr;
hr = CoInitializeEx (NULL, flags);
if (SUCCEEDED (hr))
co_initialized = TRUE;
init_result = TRUE;
else switch (hr)
{
case RPC_E_CHANGED_MODE:
@@ -79,19 +72,26 @@ gdk_win32_ensure_com (void)
HR_LOG (hr);
break;
}
g_once_init_leave (&co_initialized, init_result);
}
return co_initialized;
}
/* Whether GDK initialized OLE */
gboolean
gdk_win32_ensure_ole (void)
{
if (!ole_initialized)
static gsize ole_initialized = 0;
if (g_once_init_enter (&ole_initialized))
{
gboolean init_result = FALSE;
HRESULT hr = OleInitialize (NULL);
if (SUCCEEDED (hr))
ole_initialized = TRUE;
init_result = TRUE;
else switch (hr)
{
case RPC_E_CHANGED_MODE:
@@ -102,11 +102,117 @@ gdk_win32_ensure_ole (void)
HR_LOG (hr);
break;
}
g_once_init_leave (&ole_initialized, init_result);
}
return ole_initialized;
}
/** gdk_win32_check_app_container:
*
* Check if running sandboxed in an app container
*/
bool
gdk_win32_check_app_container (void)
{
HANDLE token_handle = NULL;
DWORD is_app_container = 0;
DWORD size = sizeof (is_app_container);
bool result = false;
/* Since Windows 8: use GetCurrentProcessToken() and remove the call to CloseHandle() */
if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token_handle))
{
WIN32_API_FAILED ("OpenProcessToken");
return false;
}
if (!GetTokenInformation (token_handle, TokenIsAppContainer, &is_app_container, size, &size))
WIN32_API_FAILED ("GetTokenInformation");
else if (size > 0)
result = !!is_app_container;
CloseHandle (token_handle);
return result;
}
/** gdk_win32_check_high_integrity:
*
* Check if the app is running with high integrity
*
* Code based on:
* https://devblogs.microsoft.com/oldnewthing/20221017-00/?p=107291
* https://github.com/microsoft/WindowsAppSDK/blob/main/dev/Common/Security.IntegrityLevel.h
*/
bool
gdk_win32_check_high_integrity (void)
{
HANDLE token_handle = NULL;
TOKEN_MANDATORY_LABEL integrity_level;
DWORD size = sizeof (integrity_level);
bool result = false;
/* Since Windows 8: use GetCurrentProcessToken() and remove the call to CloseHandle() */
if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token_handle))
{
WIN32_API_FAILED ("OpenProcessToken");
return false;
}
memset (&integrity_level, 0, sizeof (integrity_level));
if (!GetTokenInformation (token_handle, TokenIntegrityLevel, &integrity_level, size, &size))
WIN32_API_FAILED ("GetTokenInformation");
else if (size > 0 && IsValidSid (integrity_level.Label.Sid))
{
UCHAR subauthority_count = *GetSidSubAuthorityCount (integrity_level.Label.Sid);
if (subauthority_count > 0)
{
DWORD level = *GetSidSubAuthority (integrity_level.Label.Sid, subauthority_count - 1);
result = (level >= SECURITY_MANDATORY_HIGH_RID);
}
}
CloseHandle (token_handle);
return result;
}
/** gdk_win32_check_manually_elevated:
*
* Code based on:
* https://devblogs.microsoft.com/oldnewthing/20241003-00/?p=110336
*/
bool
gdk_win32_check_manually_elevated (void)
{
HANDLE token_handle = NULL;
TOKEN_ELEVATION_TYPE elevation_type = TokenElevationTypeDefault;
DWORD size = sizeof (elevation_type);
bool result = false;
/* Since Windows 8: use GetCurrentProcessToken() and remove the call to CloseHandle() */
if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token_handle))
{
WIN32_API_FAILED ("OpenProcessToken");
return false;
}
if (!GetTokenInformation (token_handle, TokenElevationType, &elevation_type, size, &size))
WIN32_API_FAILED ("GetTokenInformation");
else if (size > 0)
result = (elevation_type == TokenElevationTypeFull);
CloseHandle (token_handle);
return result;
}
void
_gdk_win32_api_failed (const char *where,
const char *api)

View File

@@ -1,10 +1,11 @@
/*
* Copyright © 2019 Red Hat, Inc.
/* GTK - The GIMP Toolkit
*
* Copyright (C) 2024 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.1 of the License, or (at your option) any later version.
* 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
@@ -13,16 +14,24 @@
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#include <stdbool.h>
#define CONSTRAINT_EDITOR_APPLICATION_TYPE (constraint_editor_application_get_type ())
typedef enum {
OSVersionWindows7,
OSVersionWindows8,
OSVersionWindows8_1,
OSVersionWindows10,
OSVersionWindows11,
} OSVersion;
G_DECLARE_FINAL_TYPE (ConstraintEditorApplication, constraint_editor_application, CONSTRAINT, EDITOR_APPLICATION, GtkApplication)
bool gdk_win32_check_app_container (void);
ConstraintEditorApplication *constraint_editor_application_new (void);
bool gdk_win32_check_high_integrity (void);
bool gdk_win32_check_manually_elevated (void);
OSVersion gdk_win32_get_os_version (void);

View File

@@ -70,15 +70,20 @@ typedef enum
} GdkDragProtocol;
gulong _gdk_win32_get_next_tick (gulong suggested_tick);
BOOL _gdk_win32_get_cursor_pos (LPPOINT lpPoint);
BOOL _gdk_win32_get_cursor_pos (GdkDisplay *display,
LPPOINT lpPoint);
gboolean _gdk_win32_surface_enable_transparency (GdkSurface *surface);
void _gdk_win32_dnd_exit (void);
void gdk_win32_handle_table_insert (HANDLE *handle,
gpointer data);
void gdk_win32_handle_table_remove (HANDLE handle);
void gdk_win32_display_handle_table_insert (GdkDisplay *display,
HANDLE *handle,
gpointer data);
void gdk_win32_display_handle_table_remove (GdkDisplay *display,
HANDLE handle);
gpointer gdk_win32_display_handle_table_lookup_ (GdkDisplay *display,
HWND handle);
cairo_region_t *_gdk_win32_hrgn_to_region (HRGN hrgn,
guint scale);
@@ -135,25 +140,9 @@ void _gdk_other_api_failed (const char *where,
extern LRESULT CALLBACK _gdk_win32_surface_procedure (HWND, UINT, WPARAM, LPARAM);
extern GdkDisplay *_gdk_display;
extern GdkDeviceManagerWin32 *_gdk_device_manager;
extern int _gdk_input_ignore_core;
/* These are thread specific, but GDK/win32 works OK only when invoked
* from a single thread anyway.
*/
extern HKL _gdk_input_locale;
extern gboolean _gdk_input_locale_is_ime;
extern guint _gdk_keymap_serial;
/* The singleton clipdrop object pointer */
extern GdkWin32Clipdrop *_win32_clipdrop;
/* Used to identify the main thread */
extern GThread *_win32_main_thread;
typedef enum {
GDK_WIN32_MODAL_OP_NONE = 0x0,
@@ -165,14 +154,6 @@ typedef enum {
#define GDK_WIN32_MODAL_OP_SIZEMOVE_MASK (GDK_WIN32_MODAL_OP_SIZE | GDK_WIN32_MODAL_OP_MOVE)
/* Non-zero while a modal sizing, moving, or dnd operation is in progress */
extern GdkWin32ModalOpKind _modal_operation_in_progress;
extern HWND _modal_move_resize_hwnd;
void _gdk_win32_begin_modal_call (GdkWin32ModalOpKind kind);
void _gdk_win32_end_modal_call (GdkWin32ModalOpKind kind);
void _gdk_win32_display_init_cursors (GdkWin32Display *display);
void _gdk_win32_display_finalize_cursors (GdkWin32Display *display);
void _gdk_win32_display_update_cursors (GdkWin32Display *display);
@@ -223,8 +204,6 @@ void _gdk_win32_keymap_set_active_layout (GdkWin32Keymap *keymap,
HKL hkl);
GdkModifierType _gdk_win32_keymap_get_mod_mask (GdkWin32Keymap *keymap);
GdkKeymap *_gdk_win32_display_get_keymap (GdkDisplay *display);
/* stray GdkSurfaceImplWin32 members */
void _gdk_win32_surface_register_dnd (GdkSurface *surface);
void _gdk_win32_surface_unregister_dnd (GdkSurface *surface);
@@ -236,8 +215,20 @@ GdkDrag *_gdk_win32_surface_drag_begin (GdkSurface *surface,
double x_root,
double y_root);
/* miscellaneous items (property setup, language notification, keymap serial) */
gboolean gdk_win32_display_get_setting (GdkDisplay *display,
const char *name,
GValue *value);
void gdk_win32_display_lang_notification_init (GdkWin32Display *display);
void gdk_win32_display_lang_notification_exit (GdkWin32Display *display);
void gdk_win32_display_set_input_locale (GdkWin32Display *display,
HKL input_locale);
gboolean gdk_win32_display_input_locale_is_ime (GdkWin32Display *display);
GdkKeymap *gdk_win32_display_get_default_keymap (GdkWin32Display *display);
void gdk_win32_display_increment_keymap_serial (GdkWin32Display *display);
guint gdk_win32_display_get_keymap_serial (GdkWin32Display *display);
/* Stray GdkWin32Screen members */
gboolean _gdk_win32_get_setting (const char *name, GValue *value);
void _gdk_win32_screen_on_displaychange_event (GdkWin32Screen *screen);
/* Distributed display manager implementation */
@@ -290,8 +281,6 @@ GdkPixbuf *gdk_win32_icon_to_pixbuf_libgtk_only (HICON hicon,
double *y_hot);
void gdk_win32_set_modal_dialog_libgtk_only (HWND hwnd);
gpointer gdk_win32_handle_table_lookup_ (HWND handle);
extern IMAGE_DOS_HEADER __ImageBase;
static inline HMODULE

View File

@@ -29,6 +29,7 @@
struct _GdkWin32Screen
{
GObject parent_instance;
GdkDisplay *display;
int width, height;
int surface_scale;
@@ -41,12 +42,20 @@ struct _GdkWin32ScreenClass
G_DEFINE_TYPE (GdkWin32Screen, gdk_win32_screen, G_TYPE_OBJECT)
enum {
PROP_0,
PROP_DISPLAY,
LAST_PROP
};
static GParamSpec *screen_props[LAST_PROP] = { NULL, };
static void
init_root_window_size (GdkWin32Screen *screen)
{
GdkRectangle result = { 0, };
int i;
GdkDisplay *display = _gdk_display;
GdkDisplay *display = screen->display;
GListModel *monitors;
GdkMonitor *monitor;
@@ -73,7 +82,7 @@ init_root_window (GdkWin32Screen *screen_win32)
init_root_window_size (screen_win32);
win32_display = GDK_WIN32_DISPLAY (_gdk_display);
win32_display = GDK_WIN32_DISPLAY (screen_win32->display);
if (win32_display->dpi_aware_type != PROCESS_DPI_UNAWARE)
screen_win32->surface_scale = gdk_win32_display_get_monitor_scale_factor (win32_display,
@@ -86,14 +95,21 @@ init_root_window (GdkWin32Screen *screen_win32)
static void
gdk_win32_screen_init (GdkWin32Screen *win32_screen)
{
_gdk_win32_display_init_monitors (GDK_WIN32_DISPLAY (_gdk_display));
init_root_window (win32_screen);
}
static void
gdk_win32_screen_constructed (GObject *object)
{
GdkWin32Screen *screen = GDK_WIN32_SCREEN (object);
_gdk_win32_display_init_monitors (GDK_WIN32_DISPLAY (screen->display));
init_root_window (screen);
}
void
_gdk_win32_screen_on_displaychange_event (GdkWin32Screen *screen)
{
_gdk_win32_display_init_monitors (GDK_WIN32_DISPLAY (_gdk_display));
_gdk_win32_display_init_monitors (GDK_WIN32_DISPLAY (screen->display));
init_root_window_size (screen);
}
@@ -103,10 +119,58 @@ gdk_win32_screen_finalize (GObject *object)
G_OBJECT_CLASS (gdk_win32_screen_parent_class)->finalize (object);
}
static void
gdk_win32_screen_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdkWin32Screen *screen = GDK_WIN32_SCREEN (object);
switch (prop_id)
{
case PROP_DISPLAY:
g_value_set_object (value, screen->display);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdk_win32_screen_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GdkWin32Screen *screen = GDK_WIN32_SCREEN (object);
switch (prop_id)
{
case PROP_DISPLAY:
screen->display = g_value_get_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdk_win32_screen_class_init (GdkWin32ScreenClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = gdk_win32_screen_constructed;
object_class->set_property = gdk_win32_screen_set_property;
object_class->get_property = gdk_win32_screen_get_property;
object_class->finalize = gdk_win32_screen_finalize;
screen_props[PROP_DISPLAY] =
g_param_spec_object ("display", NULL, NULL,
GDK_TYPE_DISPLAY,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, LAST_PROP, screen_props);
}

View File

@@ -75,10 +75,6 @@ static void gdk_win32_surface_maximize (GdkSurface *surface);
static void gdk_win32_surface_unmaximize (GdkSurface *surface);
static void gdk_win32_surface_minimize (GdkSurface *surface);
/* TODO: get rid of these global variables */
static gpointer parent_class = NULL;
static GSList *modal_surface_stack = NULL;
typedef struct _FullscreenInfo FullscreenInfo;
struct _FullscreenInfo
@@ -171,7 +167,7 @@ gdk_surface_win32_dispose (GObject *object)
g_clear_object (&surface->cursor);
G_OBJECT_CLASS (parent_class)->dispose (object);
G_OBJECT_CLASS (gdk_win32_surface_parent_class)->dispose (object);
}
@@ -186,7 +182,8 @@ gdk_surface_win32_finalize (GObject *object)
if (!GDK_SURFACE_DESTROYED (surface))
{
gdk_win32_handle_table_remove (surface->handle);
gdk_win32_display_handle_table_remove (gdk_surface_get_display (GDK_SURFACE (surface)),
surface->handle);
}
g_clear_pointer (&surface->snap_stash, g_free);
@@ -209,7 +206,7 @@ gdk_surface_win32_finalize (GObject *object)
g_assert (surface->transient_owner == NULL);
g_assert (surface->transient_children == NULL);
G_OBJECT_CLASS (parent_class)->finalize (object);
G_OBJECT_CLASS (gdk_win32_surface_parent_class)->finalize (object);
}
void
@@ -518,7 +515,7 @@ gdk_win32_surface_constructed (GObject *object)
* on the bitness of the OS. That pointer is still unique,
* so this works out in the end.
*/
gdk_win32_handle_table_insert (&GDK_SURFACE_HWND (impl), impl);
gdk_win32_display_handle_table_insert (display, &GDK_SURFACE_HWND (impl), impl);
g_free (wtitle);
@@ -544,7 +541,7 @@ gdk_win32_surface_constructed (GObject *object)
impl->hdc = GetDC (impl->handle);
impl->inhibit_configure = TRUE;
G_OBJECT_CLASS (parent_class)->constructed (object);
G_OBJECT_CLASS (gdk_win32_surface_parent_class)->constructed (object);
}
static void
@@ -606,7 +603,8 @@ gdk_win32_surface_destroy_notify (GdkSurface *surface)
_gdk_surface_destroy (surface, TRUE);
}
gdk_win32_handle_table_remove (GDK_SURFACE_HWND (surface));
gdk_win32_display_handle_table_remove (gdk_surface_get_display (surface),
GDK_SURFACE_HWND (surface));
g_object_unref (surface);
}
@@ -989,7 +987,7 @@ gdk_win32_surface_move_resize_internal (GdkSurface *surface,
{
/* We ignore changes to the surface being moved or resized by the
user, as we don't want to fight the user */
if (GDK_SURFACE_HWND (surface) == _modal_move_resize_hwnd)
if (GDK_SURFACE_HWND (surface) == GDK_WIN32_DISPLAY (gdk_surface_get_display (surface))->display_surface_record->modal_move_resize_hwnd)
goto out;
if (with_move && (width < 0 && height < 0))
@@ -1400,10 +1398,12 @@ gdk_win32_surface_set_transient_for (GdkSurface *surface,
WIN32_API_FAILED ("SetWindowLongPtr");
}
#define MODAL_SURFACE_STACK(s) GDK_WIN32_DISPLAY (gdk_surface_get_display (s))->display_surface_record->modal_surface_stack
static void
gdk_win32_push_modal_surface (GdkSurface *surface)
{
modal_surface_stack = g_slist_prepend (modal_surface_stack, surface);
MODAL_SURFACE_STACK (surface) = g_slist_prepend (MODAL_SURFACE_STACK (surface), surface);
}
static void
@@ -1415,15 +1415,15 @@ gdk_win32_remove_modal_surface (GdkSurface *surface)
/* It's possible to be NULL here if someone sets the modal hint of the surface
* to FALSE before a modal surface stack has ever been created. */
if (modal_surface_stack == NULL)
if (MODAL_SURFACE_STACK (surface) == NULL)
return;
/* Find the requested surface in the stack and remove it. Yeah, I realize this
* means we're not a 'real stack', strictly speaking. Sue me. :) */
tmp = g_slist_find (modal_surface_stack, surface);
tmp = g_slist_find (MODAL_SURFACE_STACK (surface), surface);
if (tmp != NULL)
{
modal_surface_stack = g_slist_delete_link (modal_surface_stack, tmp);
MODAL_SURFACE_STACK (surface) = g_slist_delete_link (MODAL_SURFACE_STACK (surface), tmp);
}
}
@@ -1433,7 +1433,7 @@ _gdk_modal_blocked (GdkSurface *surface)
GSList *l;
gboolean found_any = FALSE;
for (l = modal_surface_stack; l != NULL; l = l->next)
for (l = MODAL_SURFACE_STACK (surface); l != NULL; l = l->next)
{
GdkSurface *modal = l->data;
@@ -1451,8 +1451,11 @@ GdkSurface *
_gdk_modal_current (void)
{
GSList *l;
GdkDisplay *display = gdk_display_get_default ();
for (l = modal_surface_stack; l != NULL; l = l->next)
for (l = GDK_WIN32_DISPLAY (display)->display_surface_record->modal_surface_stack;
l != NULL;
l = l->next)
{
GdkSurface *modal = l->data;
@@ -4134,7 +4137,7 @@ gdk_win32_surface_lookup_for_display (GdkDisplay *display,
{
g_return_val_if_fail (display == gdk_display_get_default (), NULL);
return (GdkSurface*) gdk_win32_handle_table_lookup_ (anid);
return (GdkSurface*) gdk_win32_display_handle_table_lookup_ (display, anid);
}
/**
@@ -4519,8 +4522,6 @@ gdk_win32_surface_class_init (GdkWin32SurfaceClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkSurfaceClass *impl_class = GDK_SURFACE_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
object_class->constructed = gdk_win32_surface_constructed;
object_class->dispose = gdk_surface_win32_dispose;
object_class->finalize = gdk_surface_win32_finalize;

View File

@@ -83,6 +83,9 @@ struct _GdkWin32Drag
guint drag_status : 4; /* Current status of drag */
guint drop_failed : 1; /* Whether the drop was unsuccessful */
guint handle_events : 1; /* Whether handle_event() should do anything */
/* keep track of thread data for the DnD op, kept in the GdkDisplay that we create, a GdkWin32DndThread structure */
void *dnd_thread_items;
};
struct _GdkWin32DragClass
@@ -91,9 +94,9 @@ struct _GdkWin32DragClass
};
gpointer _gdk_win32_dnd_thread_main (gpointer data);
gpointer _gdk_win32_dnd_thread_main (gpointer data);
GdkDrag *_gdk_win32_find_drag_for_dest_hwnd (HWND dest_hwnd);
GdkDrag *gdk_win32_find_drag_for_dest_surface (GdkSurface *surface);
G_END_DECLS

View File

@@ -1,87 +0,0 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* 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/>.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "config.h"
#include <gdk/gdk.h>
#include "gdkprivate-win32.h"
static GHashTable *handle_ht = NULL;
static guint
gdk_handle_hash (HANDLE *handle)
{
#ifdef _WIN64
return ((guint *) handle)[0] ^ ((guint *) handle)[1];
#else
return (guint) *handle;
#endif
}
static int
gdk_handle_equal (HANDLE *a,
HANDLE *b)
{
return (*a == *b);
}
void
gdk_win32_handle_table_insert (HANDLE *handle,
gpointer data)
{
g_return_if_fail (handle != NULL);
if (!handle_ht)
handle_ht = g_hash_table_new ((GHashFunc) gdk_handle_hash,
(GEqualFunc) gdk_handle_equal);
g_hash_table_insert (handle_ht, handle, data);
}
void
gdk_win32_handle_table_remove (HANDLE handle)
{
if (!handle_ht)
handle_ht = g_hash_table_new ((GHashFunc) gdk_handle_hash,
(GEqualFunc) gdk_handle_equal);
g_hash_table_remove (handle_ht, &handle);
}
gpointer
gdk_win32_handle_table_lookup_ (HWND handle)
{
gpointer data = NULL;
if (handle_ht)
data = g_hash_table_lookup (handle_ht, &handle);
return data;
}
gpointer
gdk_win32_handle_table_lookup (HWND handle)
{
return gdk_win32_handle_table_lookup_ (handle);
}

View File

@@ -1,172 +0,0 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2019 Руслан Ижбулатов <lrn1986@gmail.com>
*
* 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"
#define COBJMACROS
#include <msctf.h>
#include <gdk/gdk.h>
#include "gdkprivate-win32.h"
struct _GdkWin32ALPNSink
{
ITfActiveLanguageProfileNotifySink itf_alpn_sink;
int ref_count;
};
typedef struct _GdkWin32ALPNSink GdkWin32ALPNSink;
static GdkWin32ALPNSink *actlangchangenotify = NULL;
static ITfSource *itf_source = NULL;
static DWORD actlangchangenotify_id = 0;
static ULONG STDMETHODCALLTYPE
alpn_sink_addref (ITfActiveLanguageProfileNotifySink *This)
{
GdkWin32ALPNSink *alpn_sink = (GdkWin32ALPNSink *) This;
int ref_count = ++alpn_sink->ref_count;
return ref_count;
}
static HRESULT STDMETHODCALLTYPE
alpn_sink_queryinterface (ITfActiveLanguageProfileNotifySink *This,
REFIID riid,
LPVOID *ppvObject)
{
*ppvObject = NULL;
if (IsEqualGUID (riid, &IID_IUnknown))
{
ITfActiveLanguageProfileNotifySink_AddRef (This);
*ppvObject = This;
return S_OK;
}
if (IsEqualGUID (riid, &IID_ITfActiveLanguageProfileNotifySink))
{
ITfActiveLanguageProfileNotifySink_AddRef (This);
*ppvObject = This;
return S_OK;
}
return E_NOINTERFACE;
}
static ULONG STDMETHODCALLTYPE
alpn_sink_release (ITfActiveLanguageProfileNotifySink *This)
{
GdkWin32ALPNSink *alpn_sink = (GdkWin32ALPNSink *) This;
int ref_count = --alpn_sink->ref_count;
if (ref_count == 0)
{
g_free (This);
}
return ref_count;
}
static HRESULT STDMETHODCALLTYPE
alpn_sink_on_activated (ITfActiveLanguageProfileNotifySink *This,
REFCLSID clsid,
REFGUID guidProfile,
BOOL fActivated)
{
_gdk_input_locale_is_ime = fActivated;
return S_OK;
}
static ITfActiveLanguageProfileNotifySinkVtbl alpn_sink_vtbl = {
alpn_sink_queryinterface,
alpn_sink_addref,
alpn_sink_release,
alpn_sink_on_activated,
};
static GdkWin32ALPNSink *
alpn_sink_new ()
{
GdkWin32ALPNSink *result;
result = g_new0 (GdkWin32ALPNSink, 1);
result->itf_alpn_sink.lpVtbl = &alpn_sink_vtbl;
result->ref_count = 0;
ITfActiveLanguageProfileNotifySink_AddRef (&result->itf_alpn_sink);
return result;
}
void
_gdk_win32_lang_notification_init ()
{
HRESULT hr;
ITfThreadMgr *itf_threadmgr;
CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
if (actlangchangenotify != NULL)
return;
hr = CoCreateInstance (&CLSID_TF_ThreadMgr,
NULL,
CLSCTX_INPROC_SERVER,
&IID_ITfThreadMgr,
(LPVOID *) &itf_threadmgr);
if (!SUCCEEDED (hr))
return;
hr = ITfThreadMgr_QueryInterface (itf_threadmgr, &IID_ITfSource, (VOID **) &itf_source);
ITfThreadMgr_Release (itf_threadmgr);
if (!SUCCEEDED (hr))
return;
actlangchangenotify = alpn_sink_new ();
hr = ITfSource_AdviseSink (itf_source,
&IID_ITfActiveLanguageProfileNotifySink,
(IUnknown *) actlangchangenotify,
&actlangchangenotify_id);
if (!SUCCEEDED (hr))
{
ITfActiveLanguageProfileNotifySink_Release (&actlangchangenotify->itf_alpn_sink);
actlangchangenotify = NULL;
ITfSource_Release (itf_source);
itf_source = NULL;
}
}
void
_gdk_win32_lang_notification_exit ()
{
if (actlangchangenotify != NULL && itf_source != NULL)
{
ITfSource_UnadviseSink (itf_source, actlangchangenotify_id);
ITfSource_Release (itf_source);
ITfActiveLanguageProfileNotifySink_Release (&actlangchangenotify->itf_alpn_sink);
}
CoUninitialize ();
}

View File

@@ -1,24 +0,0 @@
/*
* gdkwin32langnotification.h
*
* Copyright 2019 Руслан Ижбулатов <lrn1986@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
void _gdk_win32_lang_notification_init (void);
void _gdk_win32_lang_notification_exit (void);

View File

@@ -1,6 +1,5 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Copyright (C) 1998-2002 Tor Lillqvist
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,15 +23,273 @@
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <glib/gprintf.h>
#include <pango/pangowin32.h>
#include "gdkdisplayprivate.h"
#include "gdkprivate-win32.h"
#include "gdkdisplay-win32.h"
#include "gdkwin32.h"
#include <pango/pangowin32.h>
struct _GdkWin32ALPNSink
{
ITfActiveLanguageProfileNotifySink itf_alpn_sink;
int ref_count;
guint input_locale_is_ime : 1;
};
typedef struct _GdkWin32ALPNSink GdkWin32ALPNSink;
struct _GdkWin32InputLocaleItems
{
/* Input locale items */
HKL input_locale;
/* COM objects to receive language or text service change notifcations in GdkWin32 */
GdkWin32ALPNSink *notification_sink;
ITfSource *itf_source;
DWORD actlangchangenotify_id;
/* keymap items */
GdkKeymap *default_keymap;
guint keymap_serial;
};
static guint
gdk_handle_hash (HANDLE *handle)
{
#ifdef _WIN64
return ((guint *) handle)[0] ^ ((guint *) handle)[1];
#else
return (guint) *handle;
#endif
}
static int
gdk_handle_equal (HANDLE *a,
HANDLE *b)
{
return (*a == *b);
}
#define GDK_DISPLAY_HANDLE_HT(d) GDK_WIN32_DISPLAY(d)->display_surface_record->handle_ht
void
gdk_win32_display_handle_table_insert (GdkDisplay *display,
HANDLE *handle,
gpointer data)
{
g_return_if_fail (handle != NULL);
g_hash_table_insert (GDK_DISPLAY_HANDLE_HT (display), handle, data);
}
void
gdk_win32_display_handle_table_remove (GdkDisplay *display,
HANDLE handle)
{
g_hash_table_remove (GDK_DISPLAY_HANDLE_HT (display), &handle);
}
gpointer
gdk_win32_display_handle_table_lookup_ (GdkDisplay *display,
HWND handle)
{
gpointer data = NULL;
if (display == NULL)
display = gdk_display_get_default ();
data = g_hash_table_lookup (GDK_DISPLAY_HANDLE_HT (display), &handle);
return data;
}
gpointer
gdk_win32_handle_table_lookup (HWND handle)
{
return gdk_win32_display_handle_table_lookup_ (NULL, handle);
}
/* set up input language or text service change notification for our GdkDisplay */
/* COM implementation for receiving notifications when input language or text service has changed in GDK */
static ULONG STDMETHODCALLTYPE
alpn_sink_addref (ITfActiveLanguageProfileNotifySink *This)
{
GdkWin32ALPNSink *alpn_sink = (GdkWin32ALPNSink *) This;
int ref_count = ++alpn_sink->ref_count;
return ref_count;
}
static HRESULT STDMETHODCALLTYPE
alpn_sink_queryinterface (ITfActiveLanguageProfileNotifySink *This,
REFIID riid,
LPVOID *ppvObject)
{
*ppvObject = NULL;
if (IsEqualGUID (riid, &IID_IUnknown))
{
ITfActiveLanguageProfileNotifySink_AddRef (This);
*ppvObject = This;
return S_OK;
}
if (IsEqualGUID (riid, &IID_ITfActiveLanguageProfileNotifySink))
{
ITfActiveLanguageProfileNotifySink_AddRef (This);
*ppvObject = This;
return S_OK;
}
return E_NOINTERFACE;
}
static ULONG STDMETHODCALLTYPE
alpn_sink_release (ITfActiveLanguageProfileNotifySink *This)
{
GdkWin32ALPNSink *alpn_sink = (GdkWin32ALPNSink *) This;
int ref_count = --alpn_sink->ref_count;
if (ref_count == 0)
{
g_free (This);
}
return ref_count;
}
static HRESULT STDMETHODCALLTYPE
alpn_sink_on_activated (ITfActiveLanguageProfileNotifySink *This,
REFCLSID clsid,
REFGUID guidProfile,
BOOL fActivated)
{
GdkWin32ALPNSink *alpn_sink = (GdkWin32ALPNSink *) This;
alpn_sink->input_locale_is_ime = fActivated;
return S_OK;
}
static const ITfActiveLanguageProfileNotifySinkVtbl alpn_sink_vtbl = {
alpn_sink_queryinterface,
alpn_sink_addref,
alpn_sink_release,
alpn_sink_on_activated,
};
void
gdk_win32_display_lang_notification_init (GdkWin32Display *display)
{
HRESULT hr;
ITfThreadMgr *itf_threadmgr;
if (display->input_locale_items == NULL)
display->input_locale_items = g_new0 (GdkWin32InputLocaleItems, 1);
CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
if (display->input_locale_items->notification_sink != NULL)
return;
hr = CoCreateInstance (&CLSID_TF_ThreadMgr,
NULL,
CLSCTX_INPROC_SERVER,
&IID_ITfThreadMgr,
(LPVOID *) &itf_threadmgr);
if (!SUCCEEDED (hr))
return;
hr = ITfThreadMgr_QueryInterface (itf_threadmgr, &IID_ITfSource, (VOID **) &display->input_locale_items->itf_source);
ITfThreadMgr_Release (itf_threadmgr);
if (!SUCCEEDED (hr))
return;
display->input_locale_items->notification_sink = g_new0 (GdkWin32ALPNSink, 1);
display->input_locale_items->notification_sink->itf_alpn_sink.lpVtbl = &alpn_sink_vtbl;
display->input_locale_items->notification_sink->ref_count = 0;
ITfActiveLanguageProfileNotifySink_AddRef (&display->input_locale_items->notification_sink->itf_alpn_sink);
hr = ITfSource_AdviseSink (display->input_locale_items->itf_source,
&IID_ITfActiveLanguageProfileNotifySink,
(IUnknown *) display->input_locale_items->notification_sink,
&display->input_locale_items->actlangchangenotify_id);
if (!SUCCEEDED (hr))
{
ITfActiveLanguageProfileNotifySink_Release (&display->input_locale_items->notification_sink->itf_alpn_sink);
display->input_locale_items->notification_sink = NULL;
ITfSource_Release (display->input_locale_items->itf_source);
display->input_locale_items->itf_source = NULL;
}
}
void
gdk_win32_display_lang_notification_exit (GdkWin32Display *display)
{
if (display->input_locale_items->notification_sink != NULL && display->input_locale_items->itf_source != NULL)
{
ITfSource_UnadviseSink (display->input_locale_items->itf_source, display->input_locale_items->actlangchangenotify_id);
ITfSource_Release (display->input_locale_items->itf_source);
ITfActiveLanguageProfileNotifySink_Release (&display->input_locale_items->notification_sink->itf_alpn_sink);
}
CoUninitialize ();
g_clear_pointer (&display->input_locale_items->default_keymap, g_object_unref);
g_free (display->input_locale_items->notification_sink);
g_free (display->input_locale_items);
}
void
gdk_win32_display_set_input_locale (GdkWin32Display *display,
HKL input_locale)
{
g_return_if_fail (GDK_IS_WIN32_DISPLAY (display));
display->input_locale_items->input_locale = input_locale;
}
gboolean
gdk_win32_display_input_locale_is_ime (GdkWin32Display *display)
{
g_return_val_if_fail (GDK_IS_WIN32_DISPLAY (display), FALSE);
return display->input_locale_items->notification_sink->input_locale_is_ime;
}
GdkKeymap *
gdk_win32_display_get_default_keymap (GdkWin32Display *display)
{
g_return_val_if_fail (GDK_IS_WIN32_DISPLAY (display), NULL);
if (display->input_locale_items->default_keymap == NULL)
{
display->input_locale_items->default_keymap =
g_object_new (GDK_TYPE_WIN32_KEYMAP,
"display", display,
NULL);
}
return display->input_locale_items->default_keymap;
}
void
gdk_win32_display_increment_keymap_serial (GdkWin32Display *display)
{
g_return_if_fail (GDK_IS_WIN32_DISPLAY (display));
display->input_locale_items->keymap_serial++;
}
guint
gdk_win32_display_get_keymap_serial (GdkWin32Display *display)
{
g_return_val_if_fail (GDK_IS_WIN32_DISPLAY (display), 0);
return display->input_locale_items->keymap_serial;
}
static char *
_get_system_font_name (HDC hdc)
@@ -61,9 +318,13 @@ _get_system_font_name (HDC hdc)
}
gboolean
_gdk_win32_get_setting (const char *name,
GValue *value)
gdk_win32_display_get_setting (GdkDisplay *display,
const char *name,
GValue *value)
{
if (gdk_display_get_debug_flags (display) & GDK_DEBUG_DEFAULT_SETTINGS)
return FALSE;
if (strcmp ("gtk-alternative-button-order", name) == 0)
{
GDK_NOTE(MISC, g_print("gdk_display_get_setting(\"%s\") : TRUE\n", name));
@@ -145,7 +406,7 @@ _gdk_win32_get_setting (const char *name,
}
else if (strcmp ("gtk-im-module", name) == 0)
{
const char *im_module = _gdk_input_locale_is_ime ? "ime" : "";
const char *im_module = GDK_WIN32_DISPLAY (display)->input_locale_items->notification_sink->input_locale_is_ime ? "ime" : "";
GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %s\n", name, im_module));
g_value_set_static_string (value, im_module);
return TRUE;
@@ -203,10 +464,10 @@ _gdk_win32_get_setting (const char *name,
}
else if (strcmp ("gtk-xft-dpi", name) == 0)
{
GdkWin32Display *display = GDK_WIN32_DISPLAY (_gdk_display);
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
if (display->dpi_aware_type == PROCESS_SYSTEM_DPI_AWARE &&
!display->has_fixed_scale)
if (display_win32->dpi_aware_type == PROCESS_SYSTEM_DPI_AWARE &&
!display_win32->has_fixed_scale)
{
HDC hdc = GetDC (NULL);
@@ -217,7 +478,7 @@ _gdk_win32_get_setting (const char *name,
if (dpi >= 96)
{
int xft_dpi = 1024 * dpi / display->surface_scale;
int xft_dpi = 1024 * dpi / display_win32->surface_scale;
GDK_NOTE(MISC, g_print ("gdk_screen_get_setting(\"%s\") : %d\n", name, xft_dpi));
g_value_set_int (value, xft_dpi);
return TRUE;
@@ -258,3 +519,4 @@ _gdk_win32_get_setting (const char *name,
return FALSE;
}

View File

@@ -5,7 +5,7 @@ gdk_win32_public_sources = files([
'gdkdrag-win32.c',
'gdkglcontext-win32.c',
'gdkglcontext-win32-wgl.c',
'gdkwin32id.c',
'gdkwin32misc.c',
'gdksurface-win32.c',
'gdkevents-win32.c',
'gdkmonitor-win32.c',
@@ -22,7 +22,6 @@ gdk_win32_sources = gdk_win32_public_sources + files([
'gdkdevice-winpointer.c',
'gdkdevice-wintab.c',
'gdkdrop-win32.c',
'gdkglobals-win32.c',
'gdkglcontext-win32-wgl-private.c',
'gdkhdataoutputstream-win32.c',
'gdkinput-dmanipulation.c',
@@ -30,9 +29,7 @@ gdk_win32_sources = gdk_win32_public_sources + files([
'gdkkeys-win32.c',
'gdkkeys-win32-impl.c',
'gdkkeys-win32-impl-wow64.c',
'gdkwin32langnotification.c',
'gdkmain-win32.c',
'gdkproperty-win32.c',
'gdkvulkancontext-win32.c',
'gdkwin32cursor.h',
'gdkwin32display.h',

View File

@@ -3225,8 +3225,7 @@ gsk_gpu_node_processor_repeat_tile (GskGpuNodeProcessor *self,
- y * child_bounds->size.height));
if (!gsk_rect_intersection (&offset_rect, child_bounds, &clipped_child_bounds))
{
/* The math has gone wrong probably, someone should look at this. */
g_warn_if_reached ();
/* rounding error hits again */
return;
}

View File

@@ -68,8 +68,8 @@ gtk_accessible_text_default_get_default_attributes (GtkAccessibleText *self,
char ***attribute_names,
char ***attribute_values)
{
*attribute_names = NULL;
*attribute_values = NULL;
*attribute_names = g_new0 (char *, 1);
*attribute_values = g_new0 (char *, 1);
}
static void
@@ -289,10 +289,7 @@ gtk_accessible_text_get_attributes (GtkAccessibleText *self,
* - a name, typically in the form of a reverse DNS identifier
* - a value
*
* If this function returns true, `n_attributes` will be set to a value
* greater than or equal to one, @ranges will be set to a newly
* allocated array of [struct#Gtk.AccessibleTextRange] which should
* be freed with g_free(), @attribute_names and @attribute_values
* If this function returns true, @attribute_names and @attribute_values
* will be set to string arrays that should be freed with g_strfreev().
*
* Since: 4.14

View File

@@ -160,7 +160,7 @@ GType gtk_application_impl_quartz_get_type (void);
GtkApplicationImpl * gtk_application_impl_new (GtkApplication *application,
GdkDisplay *display);
void gtk_application_impl_startup (GtkApplicationImpl *impl,
gboolean register_sesion);
gboolean register_session);
void gtk_application_impl_shutdown (GtkApplicationImpl *impl);
void gtk_application_impl_before_emit (GtkApplicationImpl *impl,
GVariant *platform_data);

View File

@@ -1267,9 +1267,9 @@ gtk_css_provider_load_internal (GtkCssProvider *self,
if (GDK_PROFILER_IS_RUNNING)
{
char *uri = g_file_get_uri (file);
const char *uri G_GNUC_UNUSED;
uri = file ? g_file_peek_path (file) : NULL;
gdk_profiler_end_mark (before, "CSS theme load", uri);
g_free (uri);
}
}

View File

@@ -191,10 +191,12 @@ gtk_list_factory_widget_update (GtkListItemBase *base,
if (priv->object)
{
gpointer old_item = gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self));
gtk_list_item_factory_update (priv->factory,
priv->object,
gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self)) != NULL,
item != NULL,
item != old_item && old_item != NULL,
item != old_item && item != NULL,
gtk_list_factory_widget_update_func,
&update);
}

View File

@@ -875,6 +875,8 @@ gtk_picture_set_paintable (GtkPicture *self,
if (size_changed)
gtk_widget_queue_resize (GTK_WIDGET (self));
else
gtk_widget_queue_draw (GTK_WIDGET (self));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PAINTABLE]);

158
po/sl.po
View File

@@ -11,8 +11,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gtk+ master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gtk/-/issues/\n"
"POT-Creation-Date: 2024-09-17 05:42+0000\n"
"PO-Revision-Date: 2024-09-17 17:21+0200\n"
"POT-Creation-Date: 2024-10-05 13:38+0000\n"
"PO-Revision-Date: 2024-10-05 20:36+0200\n"
"Last-Translator: Martin Srebotnjak <miles@filmsi.net>\n"
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
"Language: sl_SI\n"
@@ -72,35 +72,35 @@ msgstr "Ni mogoče določiti vsebine kot »%s«."
msgid "Cannot provide contents as %s"
msgstr "Ni mogoče določiti vsebine kot %s."
#: gdk/gdkdisplay.c:176 gdk/gdkglcontext.c:472
#: gdk/gdkdisplay.c:176 gdk/gdkglcontext.c:469
msgid "The current backend does not support OpenGL"
msgstr "Trenutno zagnan ozadnji program ne podpira OpenGL"
#: gdk/gdkdisplay.c:1315 gdk/gdkvulkancontext.c:1668
#: gdk/gdkdisplay.c:1317 gdk/gdkvulkancontext.c:1634
msgid "Vulkan support disabled via GDK_DISABLE"
msgstr "Podpora Vulkan je onemogočena z GDK_DISABLE"
#: gdk/gdkdisplay.c:1369
#: gdk/gdkdisplay.c:1371
msgid "OpenGL support disabled via GDK_DISABLE"
msgstr "Podpora OpenGL je onemogočena z GDK_DISABLE"
#: gdk/gdkdisplay.c:1683
#: gdk/gdkdisplay.c:1685
msgid "No EGL configuration available"
msgstr "Nastavitve EGL niso na voljo"
#: gdk/gdkdisplay.c:1691
#: gdk/gdkdisplay.c:1693
msgid "Failed to get EGL configurations"
msgstr "Pridobivanje nastavitev EGL je sodletelo"
#: gdk/gdkdisplay.c:1721
#: gdk/gdkdisplay.c:1723
msgid "No EGL configuration with required features found"
msgstr "Ni mogoče najti nastavitev EGL za zahtevane možnosti"
#: gdk/gdkdisplay.c:1728
#: gdk/gdkdisplay.c:1730
msgid "No perfect EGL configuration found"
msgstr "Nastavitve EGL ni mogoče najti"
#: gdk/gdkdisplay.c:1770
#: gdk/gdkdisplay.c:1772
#, c-format
msgid "EGL implementation is missing extension %s"
msgid_plural "EGL implementation is missing %2$d extensions: %1$s"
@@ -109,23 +109,23 @@ msgstr[1] "Vstavku EGL manjka %2$d razširitev: %1$s"
msgstr[2] "Vstavku EGL manjkata %2$d razširitvi: %1$s"
msgstr[3] "Vstavku EGL manjkajo %2$d razširitve: %1$s"
#: gdk/gdkdisplay.c:1819
#: gdk/gdkdisplay.c:1821
msgid "libEGL not available in this sandbox"
msgstr "Sandbox ne podpira knjižnice libEGL"
#: gdk/gdkdisplay.c:1820
#: gdk/gdkdisplay.c:1822
msgid "libEGL not available"
msgstr "Knjižnica libEL ni na voljo"
#: gdk/gdkdisplay.c:1830
#: gdk/gdkdisplay.c:1832
msgid "Failed to create EGL display"
msgstr "Ustvarjanje zaslona EGL je sodletelo"
#: gdk/gdkdisplay.c:1839
#: gdk/gdkdisplay.c:1841
msgid "Could not initialize EGL display"
msgstr "Ni mogoče začeti zaslona EGL"
#: gdk/gdkdisplay.c:1849
#: gdk/gdkdisplay.c:1851
#, c-format
msgid "EGL version %d.%d is too old. GTK requires %d.%d"
msgstr "Različica EGL %d.%d je prestara, Oklje GTK zahteva različico %d.%d"
@@ -138,25 +138,25 @@ msgstr "Funkcija Poteg/Spust iz drugih programov ni podprta."
msgid "No compatible formats to transfer contents."
msgstr "Ni skladnih zapisov za prenos vsebine."
#: gdk/gdkglcontext.c:432 gdk/x11/gdkglcontext-glx.c:651
#: gdk/gdkglcontext.c:429 gdk/x11/gdkglcontext-glx.c:651
msgid "No GL API allowed."
msgstr "API GL ni dovoljen."
#: gdk/gdkglcontext.c:455 gdk/win32/gdkglcontext-win32-wgl.c:723
#: gdk/gdkglcontext.c:452 gdk/win32/gdkglcontext-win32-wgl.c:723
#: gdk/win32/gdkglcontext-win32-wgl.c:866
#: gdk/win32/gdkglcontext-win32-wgl.c:910 gdk/x11/gdkglcontext-glx.c:697
msgid "Unable to create a GL context"
msgstr "Ni mogoče ustvariti vsebine GL"
#: gdk/gdkglcontext.c:1340
#: gdk/gdkglcontext.c:1330
msgid "OpenGL ES API disabled via GDK_DISABLE"
msgstr "Podpora OpenGL ES API je onemogočena z GDK_DISABLE"
#: gdk/gdkglcontext.c:1352
#: gdk/gdkglcontext.c:1342
msgid "OpenGL API disabled via GDK_DISABLE"
msgstr "Podpora OpenGL API je onemogočena z GDK_DISABLE"
#: gdk/gdkglcontext.c:1363
#: gdk/gdkglcontext.c:1353
#, c-format
msgid "Application does not support %s API"
msgstr "Program ne podpira vmesnika API %s"
@@ -164,12 +164,12 @@ msgstr "Program ne podpira vmesnika API %s"
#. translators: This is about OpenGL backend names, like
#. * "Trying to use X11 GLX, but EGL is already in use"
#.
#: gdk/gdkglcontext.c:2175
#: gdk/gdkglcontext.c:2132
#, c-format
msgid "Trying to use %s, but %s is already in use"
msgstr "Podana je zahteva za uporabo %s, a je %s že v uporabi."
#: gdk/gdkglcontext.c:2186
#: gdk/gdkglcontext.c:2143
#, c-format
msgid "Trying to use %s, but it is disabled via GDK_DISABLE"
msgstr "Poskus uporabe %s, vendar je onemogočeno prek GDK_DISABLE"
@@ -603,8 +603,8 @@ msgstr "Ni mogoče naložiti podatkov slike TIFF"
msgid "Reading data failed at row %d"
msgstr "Ni mogoče pridobiti podatkov v vrstici %d"
#: gdk/macos/gdkmacospasteboard.c:211 gdk/wayland/gdkclipboard-wayland.c:238
#: gdk/wayland/gdkdrop-wayland.c:205 gdk/wayland/gdkprimary-wayland.c:337
#: gdk/macos/gdkmacospasteboard.c:211 gdk/wayland/gdkclipboard-wayland.c:244
#: gdk/wayland/gdkdrop-wayland.c:205 gdk/wayland/gdkprimary-wayland.c:343
#: gdk/win32/gdkdrop-win32.c:1018 gdk/win32/gdkdrop-win32.c:1067
#: gdk/x11/gdkclipboard-x11.c:799 gdk/x11/gdkdrop-x11.c:235
msgid "No compatible transfer format found"
@@ -886,17 +886,12 @@ msgstr "Neveljavni zapisi pri sestavljeni pretvorbi besedila."
msgid "Unsupported encoding “%s”"
msgstr "Nepodprto kodiranje »%s«."
#: gsk/gl/gskglrenderer.c:215
#, c-format
msgid "This GLES %d.%d implementation does not support half-float vertex data"
msgstr "Sistem GLES %d.%d ne podpira pol-plavajočih podatkov"
#: gsk/gpu/gskgldevice.c:252
#: gsk/gpu/gskgldevice.c:253
#, c-format
msgid "OpenGL ES 3.0 is not supported by this renderer."
msgstr "Izrisovalnik ne podpira OpenGL ES 3.0"
#: gsk/gpu/gsknglrenderer.c:68
#: gsk/gpu/gsknglrenderer.c:66
msgid "OpenGL 3.3 required"
msgstr "Potrebujete OpenGL 3.3"
@@ -2398,7 +2393,7 @@ msgid "If you delete an item, it will be permanently lost."
msgstr "V primeru, da predmet izbrišete, bo trajno izgubljen."
#: gtk/gtkfilechooserwidget.c:1213 gtk/gtkfilechooserwidget.c:1815
#: gtk/gtklabel.c:5883 gtk/gtktext.c:6334 gtk/gtktextview.c:9237
#: gtk/gtklabel.c:5888 gtk/gtktext.c:6334 gtk/gtktextview.c:9237
msgid "_Delete"
msgstr "_Izbriši"
@@ -2737,31 +2732,31 @@ msgstr "Zapri"
msgid "Close the infobar"
msgstr "Zapri vrstico podrobnosti"
#: gtk/gtklabel.c:5880 gtk/gtktext.c:6322 gtk/gtktextview.c:9225
#: gtk/gtklabel.c:5885 gtk/gtktext.c:6322 gtk/gtktextview.c:9225
msgid "Cu_t"
msgstr "Iz_reži"
#: gtk/gtklabel.c:5881 gtk/gtktext.c:6326 gtk/gtktextview.c:9229
#: gtk/gtklabel.c:5886 gtk/gtktext.c:6326 gtk/gtktextview.c:9229
msgid "_Copy"
msgstr "_Kopiraj"
#: gtk/gtklabel.c:5882 gtk/gtktext.c:6330 gtk/gtktextview.c:9233
#: gtk/gtklabel.c:5887 gtk/gtktext.c:6330 gtk/gtktextview.c:9233
msgid "_Paste"
msgstr "Pr_ilepi"
#: gtk/gtklabel.c:5888 gtk/gtktext.c:6343 gtk/gtktextview.c:9258
#: gtk/gtklabel.c:5893 gtk/gtktext.c:6343 gtk/gtktextview.c:9258
msgid "Select _All"
msgstr "Izberi _vse"
#: gtk/gtklabel.c:5893
#: gtk/gtklabel.c:5898
msgid "_Open Link"
msgstr "_Odpri povezavo"
#: gtk/gtklabel.c:5897
#: gtk/gtklabel.c:5902
msgid "Copy _Link Address"
msgstr "Kopiraj _naslov povezave"
#: gtk/gtklabel.c:5941 gtk/gtktext.c:2851 gtk/gtktextview.c:9307
#: gtk/gtklabel.c:5946 gtk/gtktext.c:2851 gtk/gtktextview.c:9307
msgid "Context menu"
msgstr "Vsebinski meni"
@@ -3357,89 +3352,89 @@ msgstr "Ni na voljo"
#. * jobs. %s gets replaced by the application name, %d gets replaced
#. * by the job number.
#.
#: gtk/print/gtkprintoperation.c:252
#: gtk/print/gtkprintoperation.c:255
#, c-format
msgid "%s job #%d"
msgstr "%s - posel št. %d"
#: gtk/print/gtkprintoperation.c:1699
#: gtk/print/gtkprintoperation.c:1702
msgctxt "print operation status"
msgid "Initial state"
msgstr "Začetno stanje"
#: gtk/print/gtkprintoperation.c:1700
#: gtk/print/gtkprintoperation.c:1703
msgctxt "print operation status"
msgid "Preparing to print"
msgstr "Priprava na tiskanje"
#: gtk/print/gtkprintoperation.c:1701
#: gtk/print/gtkprintoperation.c:1704
msgctxt "print operation status"
msgid "Generating data"
msgstr "Ustvarjanje podatkov"
#: gtk/print/gtkprintoperation.c:1702
#: gtk/print/gtkprintoperation.c:1705
msgctxt "print operation status"
msgid "Sending data"
msgstr "Pošiljanje podatkov"
#: gtk/print/gtkprintoperation.c:1703
#: gtk/print/gtkprintoperation.c:1706
msgctxt "print operation status"
msgid "Waiting"
msgstr "Čakanje"
#: gtk/print/gtkprintoperation.c:1704
#: gtk/print/gtkprintoperation.c:1707
msgctxt "print operation status"
msgid "Blocking on issue"
msgstr "Blokirano zaradi napake"
#: gtk/print/gtkprintoperation.c:1705
#: gtk/print/gtkprintoperation.c:1708
msgctxt "print operation status"
msgid "Printing"
msgstr "Tiskanje"
#: gtk/print/gtkprintoperation.c:1706
#: gtk/print/gtkprintoperation.c:1709
msgctxt "print operation status"
msgid "Finished"
msgstr "Končano"
#: gtk/print/gtkprintoperation.c:1707
#: gtk/print/gtkprintoperation.c:1710
msgctxt "print operation status"
msgid "Finished with error"
msgstr "Končano z napako"
#: gtk/print/gtkprintoperation.c:2250
#: gtk/print/gtkprintoperation.c:2254
#, c-format
msgid "Preparing %d"
msgstr "Pripravljanje %d"
#: gtk/print/gtkprintoperation.c:2252 gtk/print/gtkprintoperation.c:2871
#: gtk/print/gtkprintoperation.c:2256 gtk/print/gtkprintoperation.c:2875
#, c-format
msgid "Preparing"
msgstr "Pripravljanje"
#: gtk/print/gtkprintoperation.c:2255
#: gtk/print/gtkprintoperation.c:2259
#, c-format
msgid "Printing %d"
msgstr "Tiskanje %d"
#: gtk/print/gtkprintoperation.c:2904
#: gtk/print/gtkprintoperation.c:2908
#, c-format
msgid "Error creating print preview"
msgstr "Napaka med ustvarjanjem predogleda tiskanja"
#: gtk/print/gtkprintoperation.c:2907
#: gtk/print/gtkprintoperation.c:2911
#, c-format
msgid "The most probable reason is that a temporary file could not be created."
msgstr "Najverjetnejši razlog je, da začasne datoteke ni mogoče ustvariti"
#. window
#: gtk/print/gtkprintoperation-portal.c:264
#: gtk/print/gtkprintoperation-portal.c:594
#: gtk/print/gtkprintoperation-portal.c:663 gtk/print/gtkprintunixdialog.c:3015
#: gtk/print/gtkprintoperation-portal.c:273
#: gtk/print/gtkprintoperation-portal.c:603
#: gtk/print/gtkprintoperation-portal.c:672 gtk/print/gtkprintunixdialog.c:3015
msgid "Print"
msgstr "Natisni"
#: gtk/print/gtkprintoperation-unix.c:481
#: gtk/print/gtkprintoperation-unix.c:490
#: gtk/print/gtkprintoperation-win32.c:1505
msgid "Application"
msgstr "Program"
@@ -3695,7 +3690,7 @@ msgstr "Ni zadetkov"
msgid "Try a different search"
msgstr "Poskusite drugačno iskanje"
#: gtk/gtkstacksidebar.c:154
#: gtk/gtkstacksidebar.c:155
msgctxt "accessibility"
msgid "Sidebar"
msgstr "Stranska vrstica"
@@ -3812,17 +3807,17 @@ msgstr "Pokaži"
msgid "Hover to load"
msgstr "Naloži ob prehodu"
#: gtk/inspector/clipboard.c:278
#: gtk/inspector/clipboard.c:286
msgctxt "clipboard"
msgid "empty"
msgstr "prazno"
#: gtk/inspector/clipboard.c:283 gtk/inspector/clipboard.c:325
#: gtk/inspector/clipboard.c:291 gtk/inspector/clipboard.c:344
msgctxt "clipboard"
msgid "local"
msgstr "krajevno"
#: gtk/inspector/clipboard.c:285 gtk/inspector/clipboard.c:327
#: gtk/inspector/clipboard.c:293 gtk/inspector/clipboard.c:346
msgctxt "clipboard"
msgid "remote"
msgstr "oddaljeno"
@@ -4253,7 +4248,7 @@ msgstr "Vir:"
msgid "Defined At"
msgstr "Določeno pri"
#: gtk/inspector/recorder.c:2021
#: gtk/inspector/recorder.c:2022
#, c-format
msgid "Saving RenderNode failed"
msgstr "Shranjevanje izrisovanja vozlišča je spodletelo"
@@ -4306,7 +4301,7 @@ msgstr "Ime:"
msgid "Type:"
msgstr "Vrsta:"
#: gtk/inspector/resource-list.ui:164 tools/gtk-image-tool-info.c:54
#: gtk/inspector/resource-list.ui:164 tools/gtk-image-tool-info.c:56
msgid "Size:"
msgstr "Velikost:"
@@ -7163,35 +7158,35 @@ msgctxt "printer option value"
msgid "Unavailable"
msgstr "Ni na voljo"
#: modules/printbackends/gtkprintbackendfile.c:238
#: modules/printbackends/gtkprintbackendfile.c:263
msgid "output"
msgstr "odvod"
#: modules/printbackends/gtkprintbackendfile.c:510
#: modules/printbackends/gtkprintbackendfile.c:543
msgid "Print to File"
msgstr "Natisni v datoteko"
#: modules/printbackends/gtkprintbackendfile.c:636
#: modules/printbackends/gtkprintbackendfile.c:675
msgid "PDF"
msgstr "PDF"
#: modules/printbackends/gtkprintbackendfile.c:636
#: modules/printbackends/gtkprintbackendfile.c:675
msgid "PostScript"
msgstr "PostScript"
#: modules/printbackends/gtkprintbackendfile.c:636
#: modules/printbackends/gtkprintbackendfile.c:675
msgid "SVG"
msgstr "SVG"
#: modules/printbackends/gtkprintbackendfile.c:649
#: modules/printbackends/gtkprintbackendfile.c:688
msgid "Pages per _sheet:"
msgstr "Strani na _list:"
#: modules/printbackends/gtkprintbackendfile.c:709
#: modules/printbackends/gtkprintbackendfile.c:758
msgid "File"
msgstr "Datoteka"
#: modules/printbackends/gtkprintbackendfile.c:719
#: modules/printbackends/gtkprintbackendfile.c:768
msgid "_Output format"
msgstr "_Izhodni zapis"
@@ -7273,7 +7268,7 @@ msgstr ""
#: tools/gtk-builder-tool-enumerate.c:56 tools/gtk-builder-tool-preview.c:179
#: tools/gtk-builder-tool-preview.c:180 tools/gtk-builder-tool-screenshot.c:360
#: tools/gtk-builder-tool-simplify.c:2623 tools/gtk-builder-tool-validate.c:261
#: tools/gtk-image-tool-compare.c:43 tools/gtk-image-tool-info.c:68
#: tools/gtk-image-tool-compare.c:43 tools/gtk-image-tool-info.c:79
#: tools/gtk-path-tool-render.c:121 tools/gtk-rendernode-tool-compare.c:67
#: tools/gtk-rendernode-tool-extract.c:294 tools/gtk-rendernode-tool-info.c:226
#: tools/gtk-rendernode-tool-show.c:116
@@ -7526,7 +7521,7 @@ msgid "Compare two images"
msgstr "Primerjaj sliki"
#: tools/gtk-image-tool-compare.c:70 tools/gtk-image-tool-convert.c:113
#: tools/gtk-image-tool-info.c:90 tools/gtk-image-tool-relabel.c:109
#: tools/gtk-image-tool-info.c:101 tools/gtk-image-tool-relabel.c:109
#: tools/gtk-image-tool-show.c:141
#, c-format
msgid "No image file specified\n"
@@ -7627,19 +7622,24 @@ msgstr "Ni mogoče hkrati določiti --color-state in --cicp\n"
msgid "Not a supported cicp tuple: %s\n"
msgstr "Ni podprti n-terec cicp: %s\n"
#: tools/gtk-image-tool-info.c:55
#: tools/gtk-image-tool-info.c:57
msgid "Format:"
msgstr "Oblika zapisa:"
#: tools/gtk-image-tool-info.c:56
#: tools/gtk-image-tool-info.c:63 tools/gtk-image-tool-info.c:65
#: tools/gtk-image-tool-info.c:67
msgid "Color state:"
msgstr "Barvno stanje:"
#: tools/gtk-image-tool-info.c:77
#: tools/gtk-image-tool-info.c:67
msgid "unknown"
msgstr "neznano"
#: tools/gtk-image-tool-info.c:88
msgid "Provide information about the image."
msgstr "Navedite podatke o sliki."
#: tools/gtk-image-tool-info.c:96
#: tools/gtk-image-tool-info.c:107
#, c-format
msgid "Can only accept a single image file\n"
msgstr "Lahko sprejme samo eno slikovno datoteko\n"
@@ -7665,7 +7665,7 @@ msgstr "Ne dodaj vrstice naziva"
msgid "Show one or more images."
msgstr "Prikažite eno ali več slik."
#: tools/gtk-image-tool-utils.c:234
#: tools/gtk-image-tool-utils.c:255
#, c-format
msgid "cicp must be 4 numbers, separated by /\n"
msgstr "CICP mora biti sestavljen iz 4 števk, ločenih z /\n"

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<object class="GtkSeparator">
<property name="orientation">vertical</property>
</object>
<object class="GtkSeparator"/>
</interface>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkVSeparator">
<property name="visible">True</property>
</object>
<object class="GtkHSeparator">
<property name="visible">True</property>
</object>
</interface>

View File

@@ -1935,6 +1935,36 @@ rewrite_scale (Element *element,
}
}
static Element *
write_separator_prop (Element *element,
Element *parent,
const char *name,
const char *value)
{
if (element)
g_free (element->data);
else
{
element = add_element (parent, "property");
set_attribute_value (element, "name", name);
}
element->data = g_strdup (value);
return element;
}
static void
rewrite_separator (Element *element,
MyParserData *data)
{
if (g_str_equal (get_class_name (element), "GtkVSeparator"))
write_separator_prop (NULL, element, "orientation", "vertical");
if (!g_str_equal (get_class_name (element), "GtkSeparator"))
set_attribute_value (element, "class", "GtkSeparator");
}
static void
rewrite_requires (Element *element,
MyParserData *data)
@@ -2287,6 +2317,11 @@ rewrite_element_3to4 (Element *element,
g_str_equal (get_class_name (element), "GtkScale"))
rewrite_scale (element, data);
if (element_is_object_or_template (element) &&
(g_str_equal (get_class_name (element), "GtkHSeparator") ||
g_str_equal (get_class_name (element), "GtkVSeparator")))
rewrite_separator(element, data);
if (g_str_equal (element->element_name, "property"))
maybe_rename_property (element, data);

View File

@@ -48,12 +48,23 @@ static void
file_info (const char *filename)
{
GdkTexture *texture;
char *name;
char *cicp;
texture = load_image_file (filename);
g_print ("%s %dx%d\n", _("Size:"), gdk_texture_get_width (texture), gdk_texture_get_height (texture));
g_print ("%s %s\n", _("Format:"), get_format_name (gdk_texture_get_format (texture)));
g_print ("%s %s\n", _("Color state:"), get_color_state_name (gdk_texture_get_color_state (texture)));
name = get_color_state_name (gdk_texture_get_color_state (texture));
cicp = get_color_state_cicp (gdk_texture_get_color_state (texture));
if (name && cicp)
g_print ("%s %s (cicp %s)\n", _("Color state:"), name, cicp);
else if (cicp)
g_print ("%s cicp %s\n", _("Color state:"), cicp);
else
g_print ("%s %s\n", _("Color state:"), _("unknown"));
g_object_unref (texture);
}

View File

@@ -188,6 +188,27 @@ get_color_state_names (void)
return g_strdupv ((char **) names);
}
char *
get_color_state_cicp (GdkColorState *color_state)
{
GdkCicpParams *params;
char *str = NULL;
params = gdk_color_state_create_cicp_params (color_state);
if (params)
{
str = g_strdup_printf ("%u/%u/%u/%u",
gdk_cicp_params_get_color_primaries (params),
gdk_cicp_params_get_transfer_function (params),
gdk_cicp_params_get_matrix_coefficients (params),
gdk_cicp_params_get_range (params));
g_object_unref (params);
}
return str;
}
char *
get_color_state_name (GdkColorState *color_state)
{

View File

@@ -18,6 +18,7 @@ GdkColorState * find_color_state_by_name (const char *name);
char ** get_color_state_names (void);
char * get_color_state_name (GdkColorState *color_state);
char * get_color_state_cicp (GdkColorState *color_state);
GdkColorState *parse_cicp_tuple (const char *cicp_tuple,
GError **error);

View File

@@ -11,7 +11,7 @@ if win32_enabled
# compile_resources doesn't like to consume targets with multiple outputs,
# and the xxx.exe.manifest and xxx.rc are tied together
uac_rc = custom_target(
'tools/@0@.rc'.format(uac_exe_name),
'@0@-rc'.format(uac_exe_name),
output: ['@0@.rc'.format(uac_exe_name)],
command: [gen_uac_manifest,
'-p=@0@'.format(uac_exe_pkg),