Compare commits
384 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ad4b8bf9a | |||
| a1cacc590d | |||
| f3fa4fcb75 | |||
| bd35ff61e3 | |||
| aa6f3a627f | |||
| ee27587428 | |||
| d2f76d689f | |||
| 20cd6cc155 | |||
| 960e766206 | |||
| 1c9fbe3773 | |||
| 6669ddad09 | |||
| 6e872715ef | |||
| dc582b478f | |||
| 55839dc508 | |||
| 6dd23b2bf0 | |||
| afd64f3740 | |||
| a7b6663b33 | |||
| 487e095d24 | |||
| b487e8f694 | |||
| 171e3454ad | |||
| 164ebee129 | |||
| 76f2c4f0aa | |||
| 9999ac1255 | |||
| 3242174f81 | |||
| 6f1cade817 | |||
| c6961f1b61 | |||
| 8c88453816 | |||
| 0415574acf | |||
| c812e1dc94 | |||
| 251bf45cf2 | |||
| 13c0a9e27b | |||
| 4c70bf6c9c | |||
| 2914c360a9 | |||
| 8d1a2247e0 | |||
| 4fba7f8c59 | |||
| a93745238f | |||
| b812ff2597 | |||
| 8a51796150 | |||
| dd7d171186 | |||
| 0ac20f978e | |||
| 0a96c3f062 | |||
| 42e6630c3e | |||
| 1125d08f0d | |||
| 0544633755 | |||
| a642883e33 | |||
| c1bb699151 | |||
| 120cfcc120 | |||
| 55af84d359 | |||
| 4ae362d138 | |||
| fd201e4df7 | |||
| 21123a1264 | |||
| 87aeec2b63 | |||
| ea5fc348fa | |||
| ebc0d3760f | |||
| b4a6d69f5d | |||
| 1c8b746b42 | |||
| 05cdce2e8d | |||
| 509b781079 | |||
| c38deef753 | |||
| 4b7a6a885d | |||
| 68869a0e0f | |||
| 048957cd49 | |||
| 434d32bf95 | |||
| 1178a0011a | |||
| 0af2e65c80 | |||
| e8f3b47bf3 | |||
| 8b16e44d26 | |||
| 002abc6d48 | |||
| aca31c3ab6 | |||
| a3609c3f6d | |||
| ddc74a08be | |||
| 76614ea5f2 | |||
| 2eabe21aae | |||
| 72f574a9c0 | |||
| 02935afe94 | |||
| 234d0443b2 | |||
| 822deabdfe | |||
| b2e94f81cf | |||
| 109df77d87 | |||
| 76e3284ca1 | |||
| 576504390d | |||
| 660f46fcb1 | |||
| 2bd93c1e9e | |||
| 1612e38cda | |||
| 176ab784dc | |||
| b576aef2b1 | |||
| a357995484 | |||
| 5d10100fc0 | |||
| 6118dfba74 | |||
| d276d2629a | |||
| e3ee1df456 | |||
| 2691e4e949 | |||
| 20d7b7f59b | |||
| 1fcd08d76a | |||
| 060a9f072c | |||
| 4a631787bd | |||
| 032473fef8 | |||
| 5dd8801ee5 | |||
| 5c9643b6eb | |||
| 4de670b0b4 | |||
| ade40a7a0c | |||
| 9926e6ebde | |||
| b930c5a8a2 | |||
| 7eb5dfd294 | |||
| 8752564fea | |||
| 988fac404a | |||
| 7a3eaad193 | |||
| 3fccb16ca6 | |||
| 2c38b71ca5 | |||
| 1c93bef0d5 | |||
| eea76e8cce | |||
| 3b604331ec | |||
| 92546cf9f7 | |||
| 3c9f9d598b | |||
| ed46053dc9 | |||
| a3db7437b3 | |||
| b2d639b6d9 | |||
| f1c7803f80 | |||
| c179fce6c7 | |||
| 795899f9d5 | |||
| 88ab3a6942 | |||
| 58e8dd1c0d | |||
| b8bbf7b63b | |||
| 05e28fb498 | |||
| c6d9963d1a | |||
| 2d3a902beb | |||
| 8b1f3936b6 | |||
| 108ea50179 | |||
| df1892c052 | |||
| 0820a79bf5 | |||
| 4427bde8a7 | |||
| dec4db5943 | |||
| fd7f6ca7ad | |||
| dea309144b | |||
| f1e4efebb7 | |||
| 0885eb0a7b | |||
| fc68d1b1e6 | |||
| b329090e69 | |||
| 6314ebd435 | |||
| e89e182565 | |||
| 552fe0406c | |||
| b062dea1aa | |||
| 9b561581d5 | |||
| 7f6c31c041 | |||
| 717c55c9aa | |||
| 7d1c6272be | |||
| 2f387c2a23 | |||
| 0d95c5dfe2 | |||
| f2a2908c59 | |||
| f4cb60dcca | |||
| b3d0629709 | |||
| 30f55c4d07 | |||
| f00d964f4f | |||
| d2920c501d | |||
| af528b08dc | |||
| a628907891 | |||
| 19ad4d67ef | |||
| a4e427b44a | |||
| 5b94e3c2f2 | |||
| 3278e9ab6c | |||
| 02d8e95b73 | |||
| e0b9b51e9f | |||
| fb06b7fa94 | |||
| 7b451678f5 | |||
| 3be9e819d6 | |||
| 758c54eab8 | |||
| c39cc15573 | |||
| 8999bb0b78 | |||
| 7a81b7c7be | |||
| e475d4bdc5 | |||
| 980a6a20b1 | |||
| 064ad42432 | |||
| 4ff9163c47 | |||
| 45ebe47d94 | |||
| 2803bd93ce | |||
| 51161fb0d6 | |||
| 63fd97749c | |||
| f2d736d2cc | |||
| 9b9a656e54 | |||
| 8f734b01b2 | |||
| 69250371b0 | |||
| 731613d70b | |||
| 5f21c45f75 | |||
| 8beea4d958 | |||
| 1583200e24 | |||
| 03fa8ed259 | |||
| 0bd939624e | |||
| b658a1a8e3 | |||
| 7eae9d115c | |||
| 2ca56d4c4c | |||
| f6d7967e96 | |||
| 9bddc0ff85 | |||
| 6e47ebe030 | |||
| 9728dabf12 | |||
| e904c49e8a | |||
| 27ddd39d69 | |||
| 86e907b088 | |||
| 8b46538af9 | |||
| 5910a28aa5 | |||
| 3935027880 | |||
| 8665828d7f | |||
| a8b559e99f | |||
| 5674a3db46 | |||
| dd3acc9014 | |||
| a9364bc053 | |||
| 59313e1459 | |||
| 3e54d374de | |||
| 9856218073 | |||
| 97cdf87350 | |||
| d8f91e7df9 | |||
| 91d4e2b3e3 | |||
| e5cccbf5a0 | |||
| 5cfe9ab603 | |||
| 01a6bbdc73 | |||
| 24a4063645 | |||
| 4f11bbc59b | |||
| 9ceb41f9a4 | |||
| 831309eed2 | |||
| 4bb4a98493 | |||
| 70b0f712ad | |||
| c6e9372ba3 | |||
| 13b055ab2d | |||
| 38f4a7708e | |||
| 6abcd8d013 | |||
| 37906a2200 | |||
| b9b5072668 | |||
| 459edfa77b | |||
| 92a79d3f96 | |||
| 984dff54ab | |||
| 1866aa93e3 | |||
| 2884691740 | |||
| b8549a142e | |||
| 0f3ca349e7 | |||
| a13d6bbbdf | |||
| d15dc6f90b | |||
| 58e6c277b0 | |||
| 1d29d44ddb | |||
| bda3c6c084 | |||
| 159913be2f | |||
| b05d1676d3 | |||
| 0b21ed0c7a | |||
| 564a92830b | |||
| a20fd5e14e | |||
| 138986f064 | |||
| f286c99338 | |||
| ea48d1de5e | |||
| dbd2a81501 | |||
| be6ec8f50b | |||
| 264d4bada6 | |||
| 633172fd66 | |||
| 042f7d117f | |||
| b062594ae6 | |||
| 95f30fee87 | |||
| dbc49e7742 | |||
| 449c96ffb3 | |||
| 1459ca2c26 | |||
| 4123c85021 | |||
| d1c37c41d9 | |||
| ea6d3f589f | |||
| 1e6120e776 | |||
| a77f8e886b | |||
| 96b782c026 | |||
| 6455a54f6c | |||
| 3bae6fa1c7 | |||
| 68f19a8e6a | |||
| 12ebbd1b24 | |||
| 9b7bda6137 | |||
| 1b4ed58331 | |||
| b2868d7218 | |||
| bdc8f9dccf | |||
| 9768f35931 | |||
| 19a4ee031d | |||
| a7ee1b4e85 | |||
| 5db079b052 | |||
| a2ff6af4b3 | |||
| f66e764855 | |||
| a8c23d06ac | |||
| 36b4cd4bfc | |||
| 46c59e3c3d | |||
| b5aee936a9 | |||
| aa8687316f | |||
| 5a3cf5a194 | |||
| c5e1b00994 | |||
| 377f0c1a0a | |||
| a442e6e8de | |||
| 274c47e5ba | |||
| b2f15a622d | |||
| 04aaf02881 | |||
| d5f8e1bf29 | |||
| 33bd7051f2 | |||
| 61345b3216 | |||
| 129691f3a6 | |||
| 4eaf860e86 | |||
| 72814c54a8 | |||
| 4d4e02c9d0 | |||
| 8ab609e4e7 | |||
| 6bc156c237 | |||
| b435dc4366 | |||
| 4dd1de4129 | |||
| 48e6cd4255 | |||
| 658397fad0 | |||
| 670fc5bb94 | |||
| b224df8109 | |||
| c88e7c180d | |||
| 2aabd64f1a | |||
| 7990b24287 | |||
| c76c1a46e4 | |||
| 68fed63eac | |||
| 46403bac12 | |||
| 74c626f835 | |||
| d45a662679 | |||
| f6019f1a16 | |||
| 514de0b91a | |||
| 9a463056d0 | |||
| 035baa092c | |||
| 499738c903 | |||
| f2d7433bf6 | |||
| 405121bccc | |||
| cb96b34315 | |||
| 9edf6fb6cb | |||
| e3c4fb67ca | |||
| a9dfca04e4 | |||
| 71b52f485e | |||
| f62fc4e2f2 | |||
| 511e2b435e | |||
| 3f36340921 | |||
| b1f0f4478e | |||
| 90f8dcc5e1 | |||
| 5a019bfccd | |||
| b39a5fe5dc | |||
| c7ef8411bd | |||
| dab8a8b5c5 | |||
| 8b9c5e3a04 | |||
| 3d3a672deb | |||
| 2f97134a08 | |||
| 47237d32eb | |||
| 139a59cae3 | |||
| 60fb9092fe | |||
| 61b4febbaf | |||
| 4f4ba8c4f6 | |||
| 651adbfb39 | |||
| 3204347bb0 | |||
| b929846cc1 | |||
| fe65da05be | |||
| 06c825df90 | |||
| 46430ea85b | |||
| 859c95b435 | |||
| 5ea8167802 | |||
| 92d3d55164 | |||
| ba2125d8e1 | |||
| 7c96326c18 | |||
| 38d353dc1a | |||
| 7ae04ba36b | |||
| 39c284c490 | |||
| 895e8e25a8 | |||
| 04562a76e3 | |||
| b6781e06c1 | |||
| 54104b6676 | |||
| 21450d5f23 | |||
| a39bbb2041 | |||
| 176d9c6baf | |||
| 64afa765c8 | |||
| a246d8c926 | |||
| 0531e663ee | |||
| bd2349c0a0 | |||
| 636fbc0f1a | |||
| cdf80f1d65 | |||
| e7b2c530c5 | |||
| e07098da03 | |||
| 98a21bf498 | |||
| c694dd6049 | |||
| 6b308cd71e | |||
| 3b6ee32f83 | |||
| 3bc3e140dd | |||
| a6a9853676 | |||
| 6b42e5b433 | |||
| 99c01607f1 | |||
| 071748592d | |||
| 8dd74eac2e | |||
| f6a2678486 | |||
| e28ec2a3eb | |||
| c4fd786866 | |||
| 8fa7de5563 | |||
| afbadc5e1b |
+17
-18
@@ -1,7 +1,7 @@
|
||||
stages:
|
||||
- build
|
||||
- flatpak
|
||||
- deploy
|
||||
# - deploy
|
||||
|
||||
.cache-paths: &cache-paths
|
||||
paths:
|
||||
@@ -101,20 +101,19 @@ flatpak-master:icon-browser:
|
||||
APPID: org.gtk.IconBrowser4
|
||||
<<: *flatpak-master
|
||||
|
||||
pages:
|
||||
image: registry.gitlab.gnome.org/gnome/gtk/master:v6
|
||||
stage: deploy
|
||||
script:
|
||||
- meson -Ddocumentation=true _build .
|
||||
- ninja -C _build
|
||||
- ninja -C _build gdk4-doc gsk4-doc gtk4-doc
|
||||
|
||||
- mkdir -p public/
|
||||
- mv _build/docs/reference/gtk/html/ public/gtk/
|
||||
- mv _build/docs/reference/gdk/html/ public/gdk/
|
||||
- mv _build/docs/reference/gsk/html/ public/gsk/
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- master
|
||||
#pages:
|
||||
# image: registry.gitlab.gnome.org/gnome/gtk/master:v6
|
||||
# stage: deploy
|
||||
# script:
|
||||
# - meson -Dgtk_doc=true _build .
|
||||
# - ninja -C _build
|
||||
# - ninja -C _build gdk4-doc gsk4-doc gtk4-doc
|
||||
# - mkdir -p public/
|
||||
# - mv _build/docs/reference/gtk/html/ public/gtk/
|
||||
# - mv _build/docs/reference/gdk/html/ public/gdk/
|
||||
# - mv _build/docs/reference/gsk/html/ public/gsk/
|
||||
# artifacts:
|
||||
# paths:
|
||||
# - public
|
||||
# only:
|
||||
# - master
|
||||
|
||||
@@ -56,12 +56,6 @@
|
||||
/* Define if GStreamer support is available */
|
||||
#mesondefine HAVE_GSTREAMER
|
||||
|
||||
/* Define to 1 if you have the `httpGetAuthString' function. */
|
||||
#mesondefine HAVE_HTTPGETAUTHSTRING
|
||||
|
||||
/* Define if cups http_t authstring field is accessible */
|
||||
#mesondefine HAVE_HTTP_AUTHSTRING
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#mesondefine HAVE_INTTYPES_H
|
||||
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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,
|
||||
gint n_files,
|
||||
const gchar *hint)
|
||||
{
|
||||
ConstraintEditorWindow *win;
|
||||
gint 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);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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_APPLICATION_TYPE (constraint_editor_application_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintEditorApplication, constraint_editor_application, CONSTRAINT, EDITOR_APPLICATION, GtkApplication)
|
||||
|
||||
ConstraintEditorApplication *constraint_editor_application_new (void);
|
||||
@@ -0,0 +1,639 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
item = g_list_model_get_item (list, i);
|
||||
constraint = GTK_CONSTRAINT (item);
|
||||
|
||||
target = gtk_constraint_get_target (constraint);
|
||||
source = gtk_constraint_get_source (constraint);
|
||||
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),
|
||||
gtk_constraint_get_target_attribute (constraint),
|
||||
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 (GtkNativeDialog *dialog,
|
||||
gint response,
|
||||
ConstraintEditorWindow *self)
|
||||
{
|
||||
gtk_native_dialog_hide (dialog);
|
||||
|
||||
if (response == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
|
||||
constraint_editor_window_load (self, file);
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
gtk_native_dialog_destroy (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
open_cb (GtkWidget *button,
|
||||
ConstraintEditorWindow *self)
|
||||
{
|
||||
GtkFileChooserNative *dialog;
|
||||
|
||||
dialog = gtk_file_chooser_native_new ("Open file",
|
||||
GTK_WINDOW (self),
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
"_Load",
|
||||
"_Cancel");
|
||||
|
||||
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
|
||||
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
|
||||
g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), self);
|
||||
gtk_native_dialog_show (GTK_NATIVE_DIALOG (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 (GtkNativeDialog *dialog,
|
||||
gint response,
|
||||
ConstraintEditorWindow *self)
|
||||
{
|
||||
gtk_native_dialog_hide (dialog);
|
||||
|
||||
if (response == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
GListModel *model;
|
||||
char *text, *filename;
|
||||
GError *error = NULL;
|
||||
|
||||
model = constraint_view_get_model (CONSTRAINT_VIEW (self->view));
|
||||
text = serialize_model (model);
|
||||
|
||||
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
||||
if (!g_file_set_contents (filename, text, -1, &error))
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))),
|
||||
GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_BUTTONS_OK,
|
||||
"Saving failed");
|
||||
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
|
||||
"%s", error->message);
|
||||
g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
|
||||
gtk_widget_show (dialog);
|
||||
g_error_free (error);
|
||||
}
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
gtk_native_dialog_destroy (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
save_cb (GtkWidget *button,
|
||||
ConstraintEditorWindow *self)
|
||||
{
|
||||
GtkFileChooserNative *dialog;
|
||||
|
||||
dialog = gtk_file_chooser_native_new ("Save constraints",
|
||||
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
"_Save",
|
||||
"_Cancel");
|
||||
|
||||
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
|
||||
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
|
||||
g_signal_connect (dialog, "response", G_CALLBACK (save_response_cb), self);
|
||||
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_window_finalize (GObject *object)
|
||||
{
|
||||
//ConstraintEditorWindow *self = (ConstraintEditorWindow *)object;
|
||||
|
||||
G_OBJECT_CLASS (constraint_editor_window_parent_class)->finalize (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_widget_destroy (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_TOPLEVEL);
|
||||
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_container_add (GTK_CONTAINER (window), GTK_WIDGET (editor));
|
||||
|
||||
g_signal_connect (editor, "done", G_CALLBACK (constraint_editor_done), win);
|
||||
|
||||
gtk_widget_show (window);
|
||||
}
|
||||
|
||||
static void
|
||||
add_constraint (ConstraintEditorWindow *win)
|
||||
{
|
||||
edit_constraint (win, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_done (GuideEditor *editor,
|
||||
GtkConstraintGuide *guide,
|
||||
ConstraintEditorWindow *win)
|
||||
{
|
||||
gtk_widget_destroy (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_TOPLEVEL);
|
||||
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_container_add (GTK_CONTAINER (window), GTK_WIDGET (editor));
|
||||
|
||||
g_signal_connect (editor, "done", G_CALLBACK (guide_editor_done), win);
|
||||
gtk_widget_show (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->finalize = constraint_editor_window_finalize;
|
||||
|
||||
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);
|
||||
g_object_set (label, "margin", 10, NULL);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (row), box);
|
||||
gtk_container_add (GTK_CONTAINER (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_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (row_edit), win);
|
||||
g_object_set_data (G_OBJECT (row), "edit", button);
|
||||
gtk_container_add (GTK_CONTAINER (box), button);
|
||||
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
|
||||
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
|
||||
gtk_container_add (GTK_CONTAINER (box), button);
|
||||
}
|
||||
else if (GTK_IS_WIDGET (item))
|
||||
{
|
||||
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
|
||||
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
|
||||
gtk_container_add (GTK_CONTAINER (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);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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);
|
||||
@@ -0,0 +1,82 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="ConstraintEditorWindow" parent="GtkApplicationWindow">
|
||||
<style>
|
||||
<class name="devel"/>
|
||||
</style>
|
||||
<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">
|
||||
<property name="title" translatable="yes">GTK Constraint Editor</property>
|
||||
<property name="show-title-buttons">1</property>
|
||||
<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>
|
||||
@@ -0,0 +1,656 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "super", "Super");
|
||||
|
||||
if (model)
|
||||
{
|
||||
for (i = 0; i < g_list_model_get_n_items (model); i++)
|
||||
{
|
||||
GObject *item = g_list_model_get_object (model, i);
|
||||
const char *name;
|
||||
|
||||
if (GTK_IS_CONSTRAINT (item))
|
||||
continue;
|
||||
|
||||
name = get_target_name (GTK_CONSTRAINT_TARGET (item));
|
||||
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), name, name);
|
||||
g_object_unref (item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_attribute_combo (GtkWidget *combo,
|
||||
gboolean is_source)
|
||||
{
|
||||
if (is_source)
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "none", "None");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "left", "Left");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "right", "Right");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "top", "Top");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "bottom", "Bottom");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "start", "Start");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "end", "End");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "width", "Width");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "height", "Height");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "center-x", "Center X");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "center-y", "Center Y");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "baseline", "Baseline");
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_relation_combo (GtkWidget *combo)
|
||||
{
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "le", "≤");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "eq", "=");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "ge", "≥");
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_strength_combo (GtkWidget *combo)
|
||||
{
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "weak", "Weak");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "medium", "Medium");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "strong", "Strong");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "required", "Required");
|
||||
}
|
||||
|
||||
static gpointer
|
||||
get_target (GListModel *model,
|
||||
const char *id)
|
||||
{
|
||||
int i;
|
||||
|
||||
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 GtkConstraintAttribute
|
||||
get_target_attr (const char *id)
|
||||
{
|
||||
GtkConstraintAttribute attr;
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_ATTRIBUTE);
|
||||
GEnumValue *value = g_enum_get_value_by_nick (class, id);
|
||||
attr = value->value;
|
||||
g_type_class_unref (class);
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
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 (const char *id)
|
||||
{
|
||||
GtkConstraintRelation relation;
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_RELATION);
|
||||
GEnumValue *value = g_enum_get_value_by_nick (class, id);
|
||||
relation = value->value;
|
||||
g_type_class_unref (class);
|
||||
|
||||
return relation;
|
||||
}
|
||||
|
||||
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 GtkConstraintStrength
|
||||
get_strength (const char *id)
|
||||
{
|
||||
GtkConstraintStrength strength;
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
|
||||
GEnumValue *value = g_enum_get_value_by_nick (class, id);
|
||||
strength = value->value;
|
||||
g_type_class_unref (class);
|
||||
|
||||
return strength;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
const char *id;
|
||||
gpointer target;
|
||||
GtkConstraintAttribute target_attr;
|
||||
gpointer source;
|
||||
GtkConstraintAttribute source_attr;
|
||||
GtkConstraintRelation relation;
|
||||
double multiplier;
|
||||
double constant;
|
||||
int strength;
|
||||
GtkConstraint *constraint;
|
||||
|
||||
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target));
|
||||
target = get_target (editor->model, id);
|
||||
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target_attr));
|
||||
target_attr = get_target_attr (id);
|
||||
|
||||
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source));
|
||||
source = get_target (editor->model, id);
|
||||
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
|
||||
source_attr = get_target_attr (id);
|
||||
|
||||
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->relation));
|
||||
relation = get_relation (id);
|
||||
|
||||
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);
|
||||
|
||||
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->strength));
|
||||
strength = get_strength (id);
|
||||
|
||||
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)
|
||||
{
|
||||
const char *id;
|
||||
|
||||
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
|
||||
if (strcmp (id, "none") == 0)
|
||||
{
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX (editor->source), -1);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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_nick (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;
|
||||
char *relation;
|
||||
const char *multiplier;
|
||||
const char *constant;
|
||||
double c, m;
|
||||
|
||||
if (!editor->constructed)
|
||||
return;
|
||||
|
||||
str = g_string_new ("");
|
||||
|
||||
name = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target));
|
||||
attr = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target_attr));
|
||||
relation = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (editor->relation));
|
||||
|
||||
if (name == NULL)
|
||||
name = "[ ]";
|
||||
|
||||
g_string_append_printf (str, "%s.%s %s ", name, attr, relation);
|
||||
g_free (relation);
|
||||
|
||||
constant = gtk_editable_get_text (GTK_EDITABLE (editor->constant));
|
||||
c = g_ascii_strtod (constant, NULL);
|
||||
|
||||
attr = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
|
||||
if (strcmp (attr, "none") != 0)
|
||||
{
|
||||
name = gtk_combo_box_get_active_id (GTK_COMBO_BOX (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)
|
||||
{
|
||||
if (gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target)) != NULL &&
|
||||
gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source)) != NULL)
|
||||
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_attribute_combo (editor->target_attr, FALSE);
|
||||
constraint_relation_combo (editor->relation);
|
||||
constraint_target_combo (editor->model, editor->source, TRUE);
|
||||
constraint_attribute_combo (editor->source_attr, TRUE);
|
||||
|
||||
constraint_strength_combo (editor->strength);
|
||||
|
||||
if (editor->constraint)
|
||||
{
|
||||
GtkConstraintTarget *target;
|
||||
GtkConstraintAttribute attr;
|
||||
GtkConstraintRelation relation;
|
||||
GtkConstraintStrength strength;
|
||||
const char *nick;
|
||||
char *val;
|
||||
double multiplier;
|
||||
double constant;
|
||||
|
||||
target = gtk_constraint_get_target (editor->constraint);
|
||||
nick = get_target_name (target);
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->target), nick);
|
||||
|
||||
attr = gtk_constraint_get_target_attribute (editor->constraint);
|
||||
nick = get_attr_nick (attr);
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->target_attr), nick);
|
||||
|
||||
target = gtk_constraint_get_source (editor->constraint);
|
||||
nick = get_target_name (target);
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->source), nick);
|
||||
|
||||
attr = gtk_constraint_get_source_attribute (editor->constraint);
|
||||
nick = get_attr_nick (attr);
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->source_attr), nick);
|
||||
|
||||
relation = gtk_constraint_get_relation (editor->constraint);
|
||||
nick = get_relation_nick (relation);
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->relation), nick);
|
||||
|
||||
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);
|
||||
nick = get_strength_nick (strength);
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->strength), nick);
|
||||
|
||||
gtk_button_set_label (GTK_BUTTON (editor->button), "Apply");
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->target_attr), "left");
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->source_attr), "left");
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->relation), "eq");
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->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_pointer (&self->grid, gtk_widget_unparent);
|
||||
g_clear_object (&self->model);
|
||||
g_clear_object (&self->constraint);
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
constraintview {
|
||||
background: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
constraintview .child {
|
||||
background: red;
|
||||
}
|
||||
|
||||
constraintview .guide {
|
||||
background: blue;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?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>
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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);
|
||||
@@ -0,0 +1,163 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="ConstraintEditor" parent="GtkWidget">
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid">
|
||||
<property name="margin">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="left-attach">0</property>
|
||||
<property name="top-attach">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="target">
|
||||
<signal name="changed" handler="update_preview" swapped="yes"/>
|
||||
<signal name="changed" handler="update_button" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="target_attr">
|
||||
<signal name="changed" handler="update_preview" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="left-attach">2</property>
|
||||
<property name="top-attach">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Relation</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="relation">
|
||||
<signal name="changed" handler="update_preview" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Source</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="source">
|
||||
<signal name="changed" handler="update_preview" swapped="yes"/>
|
||||
<signal name="changed" handler="update_button" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="source_attr">
|
||||
<signal name="changed" handler="update_preview" swapped="yes"/>
|
||||
<signal name="changed" handler="source_attr_changed" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="left-attach">2</property>
|
||||
<property name="top-attach">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Multiplier</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">4</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="multiplier">
|
||||
<signal name="changed" handler="update_preview" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">4</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Constant</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">5</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="constant">
|
||||
<signal name="changed" handler="update_preview" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">5</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Strength</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">6</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="strength">
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">6</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="preview">
|
||||
<property name="xalign">0</property>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">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="left-attach">2</property>
|
||||
<property name="top-attach">8</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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);
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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);
|
||||
@@ -0,0 +1,343 @@
|
||||
/* 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", "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", "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;
|
||||
|
||||
manager = gtk_constraint_layout_new ();
|
||||
gtk_widget_set_layout_manager (GTK_WIDGET (self), manager);
|
||||
|
||||
all_children = gtk_widget_observe_children (GTK_WIDGET (self));
|
||||
all_constraints = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (manager));
|
||||
guides = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (manager));
|
||||
constraints = (GListModel *)gtk_filter_list_model_new (all_constraints, omit_internal, NULL, NULL);
|
||||
children = (GListModel *)gtk_filter_list_model_new (all_children, omit_internal, NULL, NULL);
|
||||
|
||||
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);
|
||||
self->model = G_LIST_MODEL (gtk_flatten_list_model_new (G_TYPE_OBJECT, G_LIST_MODEL (list)));
|
||||
g_object_unref (children);
|
||||
g_object_unref (guides);
|
||||
g_object_unref (constraints);
|
||||
g_object_unref (all_children);
|
||||
g_object_unref (all_constraints);
|
||||
g_object_unref (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_style_context_add_class (gtk_widget_get_style_context (frame), "child");
|
||||
gtk_widget_set_name (frame, name);
|
||||
gtk_container_add (GTK_CONTAINER (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_style_context_add_class (gtk_widget_get_style_context (frame), "guide");
|
||||
g_object_set_data (G_OBJECT (frame), "internal", "yes");
|
||||
gtk_container_add (GTK_CONTAINER (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", "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;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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_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);
|
||||
@@ -0,0 +1,411 @@
|
||||
/*
|
||||
* 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 void
|
||||
guide_strength_combo (GtkWidget *combo)
|
||||
{
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "weak", "Weak");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "medium", "Medium");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "strong", "Strong");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "required", "Required");
|
||||
}
|
||||
|
||||
static GtkConstraintStrength
|
||||
get_strength (const char *id)
|
||||
{
|
||||
GtkConstraintStrength strength;
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
|
||||
GEnumValue *value = g_enum_get_value_by_nick (class, id);
|
||||
strength = value->value;
|
||||
g_type_class_unref (class);
|
||||
|
||||
return strength;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
const char *id;
|
||||
int strength;
|
||||
const char *name;
|
||||
int w, h;
|
||||
GtkConstraintGuide *guide;
|
||||
|
||||
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_combo_box_get_active_id (GTK_COMBO_BOX (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 gboolean
|
||||
min_output (GtkSpinButton *spin_button)
|
||||
{
|
||||
GtkAdjustment *adjustment;
|
||||
double value;
|
||||
GtkWidget *box, *text;
|
||||
|
||||
adjustment = gtk_spin_button_get_adjustment (spin_button);
|
||||
value = gtk_adjustment_get_value (adjustment);
|
||||
|
||||
box = gtk_widget_get_first_child (GTK_WIDGET (spin_button));
|
||||
text = gtk_widget_get_first_child (box);
|
||||
|
||||
if (value == 0.0)
|
||||
{
|
||||
gtk_editable_set_text (GTK_EDITABLE (spin_button), "");
|
||||
gtk_text_set_placeholder_text (GTK_TEXT (text), "unset");
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_text_set_placeholder_text (GTK_TEXT (text), "");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
max_output (GtkSpinButton *spin_button)
|
||||
{
|
||||
GtkAdjustment *adjustment;
|
||||
double value;
|
||||
GtkWidget *box, *text;
|
||||
|
||||
adjustment = gtk_spin_button_get_adjustment (spin_button);
|
||||
value = gtk_adjustment_get_value (adjustment);
|
||||
|
||||
box = gtk_widget_get_first_child (GTK_WIDGET (spin_button));
|
||||
text = gtk_widget_get_first_child (box);
|
||||
|
||||
if (value == (double)G_MAXINT)
|
||||
{
|
||||
gtk_editable_set_text (GTK_EDITABLE (spin_button), "");
|
||||
gtk_text_set_placeholder_text (GTK_TEXT (text), "unset");
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_text_set_placeholder_text (GTK_TEXT (text), "");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_constructed (GObject *object)
|
||||
{
|
||||
GuideEditor *editor = GUIDE_EDITOR (object);
|
||||
|
||||
guide_strength_combo (editor->strength);
|
||||
|
||||
g_signal_connect (editor->min_width, "input", G_CALLBACK (min_input), NULL);
|
||||
g_signal_connect (editor->min_width, "output", G_CALLBACK (min_output), NULL);
|
||||
|
||||
g_signal_connect (editor->min_height, "input", G_CALLBACK (min_input), NULL);
|
||||
g_signal_connect (editor->min_height, "output", G_CALLBACK (min_output), NULL);
|
||||
|
||||
g_signal_connect (editor->max_width, "input", G_CALLBACK (max_input), NULL);
|
||||
g_signal_connect (editor->max_width, "output", G_CALLBACK (max_output), NULL);
|
||||
|
||||
g_signal_connect (editor->max_height, "input", G_CALLBACK (max_input), NULL);
|
||||
g_signal_connect (editor->max_height, "output", G_CALLBACK (max_output), 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);
|
||||
nick = get_strength_nick (strength);
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->strength), nick);
|
||||
|
||||
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_combo_box_set_active_id (GTK_COMBO_BOX (editor->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_pointer (&self->grid, gtk_widget_unparent);
|
||||
g_clear_object (&self->guide);
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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);
|
||||
@@ -0,0 +1,188 @@
|
||||
<?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">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="left-attach">0</property>
|
||||
<property name="top-attach">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="name">
|
||||
<property name="max-width-chars">20</property>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">0</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Min Size</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">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="left-attach">1</property>
|
||||
<property name="top-attach">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="left-attach">2</property>
|
||||
<property name="top-attach">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Nat Size</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">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="left-attach">1</property>
|
||||
<property name="top-attach">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="left-attach">2</property>
|
||||
<property name="top-attach">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Max Size</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">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="left-attach">1</property>
|
||||
<property name="top-attach">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="left-attach">2</property>
|
||||
<property name="top-attach">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Strength</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">4</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="strength">
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">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="left-attach">2</property>
|
||||
<property name="top-attach">5</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
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: '.')
|
||||
|
||||
executable('gtk4-constraint-editor',
|
||||
constraint_editor_sources, constraint_editor_resources,
|
||||
dependencies: libgtk_dep,
|
||||
include_directories: confinc,
|
||||
gui_app: true,
|
||||
link_args: extra_demo_ldflags,
|
||||
install: false)
|
||||
@@ -0,0 +1,289 @@
|
||||
/* Constraints/Simple
|
||||
*
|
||||
* GtkConstraintLayout provides a layout manager that uses relations
|
||||
* between widgets (also known as "constraints") to compute the position
|
||||
* and size of each child.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_DECLARE_FINAL_TYPE (SimpleGrid, simple_grid, SIMPLE, GRID, GtkWidget)
|
||||
|
||||
struct _SimpleGrid
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *button1, *button2;
|
||||
GtkWidget *button3;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (SimpleGrid, simple_grid, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
simple_grid_destroy (GtkWidget *widget)
|
||||
{
|
||||
SimpleGrid *self = SIMPLE_GRID (widget);
|
||||
|
||||
g_clear_pointer (&self->button1, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button2, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button3, gtk_widget_destroy);
|
||||
|
||||
GTK_WIDGET_CLASS (simple_grid_parent_class)->destroy (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
simple_grid_class_init (SimpleGridClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->destroy = simple_grid_destroy;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
|
||||
}
|
||||
|
||||
/* Layout:
|
||||
*
|
||||
* +-------------------------------------+
|
||||
* | +-----------++-------++-----------+ |
|
||||
* | | Child 1 || Space || Child 2 | |
|
||||
* | +-----------++-------++-----------+ |
|
||||
* | +---------------------------------+ |
|
||||
* | | Child 3 | |
|
||||
* | +---------------------------------+ |
|
||||
* +-------------------------------------+
|
||||
*
|
||||
* Constraints:
|
||||
*
|
||||
* super.start = child1.start - 8
|
||||
* child1.width = child2.width
|
||||
* child1.end = space.start
|
||||
* space.end = child2.start
|
||||
* child2.end = super.end - 8
|
||||
* super.start = child3.start - 8
|
||||
* child3.end = super.end - 8
|
||||
* super.top = child1.top - 8
|
||||
* super.top = child2.top - 8
|
||||
* child1.bottom = child3.top - 12
|
||||
* child2.bottom = child3.top - 12
|
||||
* child3.height = child1.height
|
||||
* child3.height = child2.height
|
||||
* child3.bottom = super.bottom - 8
|
||||
*
|
||||
* To add some flexibility, we make the space
|
||||
* stretchable:
|
||||
*
|
||||
* space.width >= 10
|
||||
* space.width = 100
|
||||
* space.width <= 200
|
||||
*/
|
||||
static void
|
||||
build_constraints (SimpleGrid *self,
|
||||
GtkConstraintLayout *manager)
|
||||
{
|
||||
GtkConstraintGuide *guide;
|
||||
|
||||
guide = gtk_constraint_guide_new ();
|
||||
gtk_constraint_guide_set_name (guide, "space");
|
||||
gtk_constraint_guide_set_min_size (guide, 10, 10);
|
||||
gtk_constraint_guide_set_nat_size (guide, 100, 10);
|
||||
gtk_constraint_guide_set_max_size (guide, 200, 20);
|
||||
gtk_constraint_guide_set_strength (guide, GTK_CONSTRAINT_STRENGTH_STRONG);
|
||||
gtk_constraint_layout_add_guide (manager, guide);
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new_constant (GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
|
||||
GTK_CONSTRAINT_RELATION_LE,
|
||||
200.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
guide,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (guide,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
-12.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
-12.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
}
|
||||
|
||||
static void
|
||||
simple_grid_init (SimpleGrid *self)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (self);
|
||||
|
||||
self->button1 = gtk_button_new_with_label ("Child 1");
|
||||
gtk_widget_set_parent (self->button1, widget);
|
||||
gtk_widget_set_name (self->button1, "button1");
|
||||
|
||||
self->button2 = gtk_button_new_with_label ("Child 2");
|
||||
gtk_widget_set_parent (self->button2, widget);
|
||||
gtk_widget_set_name (self->button2, "button2");
|
||||
|
||||
self->button3 = gtk_button_new_with_label ("Child 3");
|
||||
gtk_widget_set_parent (self->button3, widget);
|
||||
gtk_widget_set_name (self->button3, "button3");
|
||||
|
||||
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_constraints (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *header, *box, *grid, *button;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Constraints");
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
gtk_container_add (GTK_CONTAINER (window), box);
|
||||
|
||||
grid = g_object_new (simple_grid_get_type (), NULL);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
gtk_widget_set_vexpand (grid, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (box), grid);
|
||||
|
||||
button = gtk_button_new_with_label ("Close");
|
||||
gtk_container_add (GTK_CONTAINER (box), button);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
g_signal_connect_swapped (button, "clicked",
|
||||
G_CALLBACK (gtk_widget_destroy), window);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/* Constraints/Interactive
|
||||
*
|
||||
* Demonstrate how constraints can be updates during
|
||||
* user interaction.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_DECLARE_FINAL_TYPE (InteractiveGrid, interactive_grid, INTERACTIVE, GRID, GtkWidget)
|
||||
|
||||
struct _InteractiveGrid
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *button1, *button2;
|
||||
GtkWidget *button3;
|
||||
GtkConstraintGuide *guide;
|
||||
GtkConstraint *constraint;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (InteractiveGrid, interactive_grid, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
interactive_grid_destroy (GtkWidget *widget)
|
||||
{
|
||||
InteractiveGrid *self = INTERACTIVE_GRID (widget);
|
||||
|
||||
g_clear_pointer (&self->button1, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button2, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button3, gtk_widget_destroy);
|
||||
|
||||
GTK_WIDGET_CLASS (interactive_grid_parent_class)->destroy (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
interactive_grid_class_init (InteractiveGridClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->destroy = interactive_grid_destroy;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
|
||||
}
|
||||
|
||||
static void
|
||||
build_constraints (InteractiveGrid *self,
|
||||
GtkConstraintLayout *manager)
|
||||
{
|
||||
self->guide = g_object_new (GTK_TYPE_CONSTRAINT_GUIDE, NULL);
|
||||
gtk_constraint_layout_add_guide (manager, self->guide);
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new_constant (GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button2),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button2),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button3),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button3),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button2),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button3),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button2),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button3),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
}
|
||||
|
||||
static void
|
||||
drag_cb (GtkGestureDrag *drag,
|
||||
double offset_x,
|
||||
double offset_y,
|
||||
InteractiveGrid *self)
|
||||
{
|
||||
GtkConstraintLayout *layout = GTK_CONSTRAINT_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (self)));
|
||||
double x, y;
|
||||
|
||||
if (self->constraint)
|
||||
{
|
||||
gtk_constraint_layout_remove_constraint (layout, self->constraint);
|
||||
g_clear_object (&self->constraint);
|
||||
}
|
||||
|
||||
gtk_gesture_drag_get_start_point (drag, &x, &y);
|
||||
self->constraint = gtk_constraint_new_constant (GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_LEFT,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
x + offset_x,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
gtk_constraint_layout_add_constraint (layout, g_object_ref (self->constraint));
|
||||
gtk_widget_queue_allocate (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static void
|
||||
interactive_grid_init (InteractiveGrid *self)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (self);
|
||||
GtkGesture *drag;
|
||||
|
||||
self->button1 = gtk_button_new_with_label ("Child 1");
|
||||
gtk_widget_set_parent (self->button1, widget);
|
||||
gtk_widget_set_name (self->button1, "button1");
|
||||
|
||||
self->button2 = gtk_button_new_with_label ("Child 2");
|
||||
gtk_widget_set_parent (self->button2, widget);
|
||||
gtk_widget_set_name (self->button2, "button2");
|
||||
|
||||
self->button3 = gtk_button_new_with_label ("Child 3");
|
||||
gtk_widget_set_parent (self->button3, widget);
|
||||
gtk_widget_set_name (self->button3, "button3");
|
||||
|
||||
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
|
||||
|
||||
drag = gtk_gesture_drag_new ();
|
||||
g_signal_connect (drag, "drag-update", G_CALLBACK (drag_cb), self);
|
||||
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (drag));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_constraints2 (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *header, *box, *grid, *button;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Constraints");
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
gtk_container_add (GTK_CONTAINER (window), box);
|
||||
|
||||
grid = g_object_new (interactive_grid_get_type (), NULL);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
gtk_widget_set_vexpand (grid, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (box), grid);
|
||||
|
||||
button = gtk_button_new_with_label ("Close");
|
||||
gtk_container_add (GTK_CONTAINER (box), button);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
g_signal_connect_swapped (button, "clicked",
|
||||
G_CALLBACK (gtk_widget_destroy), window);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/* Constraints/VFL
|
||||
*
|
||||
* GtkConstraintLayout allows defining constraints using a
|
||||
* compact syntax called Visual Format Language, or VFL.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_DECLARE_FINAL_TYPE (VflGrid, vfl_grid, VFL, GRID, GtkWidget)
|
||||
|
||||
struct _VflGrid
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *button1, *button2;
|
||||
GtkWidget *button3;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (VflGrid, vfl_grid, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
vfl_grid_destroy (GtkWidget *widget)
|
||||
{
|
||||
VflGrid *self = VFL_GRID (widget);
|
||||
|
||||
g_clear_pointer (&self->button1, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button2, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button3, gtk_widget_destroy);
|
||||
|
||||
GTK_WIDGET_CLASS (vfl_grid_parent_class)->destroy (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
vfl_grid_class_init (VflGridClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->destroy = vfl_grid_destroy;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
|
||||
}
|
||||
|
||||
/* Layout:
|
||||
*
|
||||
* +-----------------------------+
|
||||
* | +-----------+ +-----------+ |
|
||||
* | | Child 1 | | Child 2 | |
|
||||
* | +-----------+ +-----------+ |
|
||||
* | +-------------------------+ |
|
||||
* | | Child 3 | |
|
||||
* | +-------------------------+ |
|
||||
* +-----------------------------+
|
||||
*
|
||||
* Constraints:
|
||||
*
|
||||
* super.start = child1.start - 8
|
||||
* child1.width = child2.width
|
||||
* child1.end = child2.start - 12
|
||||
* child2.end = super.end - 8
|
||||
* super.start = child3.start - 8
|
||||
* child3.end = super.end - 8
|
||||
* super.top = child1.top - 8
|
||||
* super.top = child2.top - 8
|
||||
* child1.bottom = child3.top - 12
|
||||
* child2.bottom = child3.top - 12
|
||||
* child3.height = child1.height
|
||||
* child3.height = child2.height
|
||||
* child3.bottom = super.bottom - 8
|
||||
*
|
||||
* Visual format:
|
||||
*
|
||||
* H:|-8-[view1(==view2)-12-[view2]-8-|
|
||||
* H:|-8-[view3]-8-|
|
||||
* V:|-8-[view1]-12-[view3(==view1)]-8-|
|
||||
* V:|-8-[view2]-12-[view3(==view2)]-8-|
|
||||
*/
|
||||
static void
|
||||
build_constraints (VflGrid *self,
|
||||
GtkConstraintLayout *manager)
|
||||
{
|
||||
const char * const vfl[] = {
|
||||
"H:|-[button1(==button2)]-12-[button2]-|",
|
||||
"H:|-[button3]-|",
|
||||
"V:|-[button1]-12-[button3(==button1)]-|",
|
||||
"V:|-[button2]-12-[button3(==button2)]-|",
|
||||
};
|
||||
GError *error = NULL;
|
||||
|
||||
gtk_constraint_layout_add_constraints_from_description (manager, vfl, G_N_ELEMENTS (vfl),
|
||||
8, 8,
|
||||
&error,
|
||||
"button1", self->button1,
|
||||
"button2", self->button2,
|
||||
"button3", self->button3,
|
||||
NULL);
|
||||
if (error != NULL)
|
||||
{
|
||||
g_printerr ("VFL parsing error:\n%s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vfl_grid_init (VflGrid *self)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (self);
|
||||
|
||||
self->button1 = gtk_button_new_with_label ("Child 1");
|
||||
gtk_widget_set_parent (self->button1, widget);
|
||||
gtk_widget_set_name (self->button1, "button1");
|
||||
|
||||
self->button2 = gtk_button_new_with_label ("Child 2");
|
||||
gtk_widget_set_parent (self->button2, widget);
|
||||
gtk_widget_set_name (self->button2, "button2");
|
||||
|
||||
self->button3 = gtk_button_new_with_label ("Child 3");
|
||||
gtk_widget_set_parent (self->button3, widget);
|
||||
gtk_widget_set_name (self->button3, "button3");
|
||||
|
||||
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_constraints3 (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *header, *box, *grid, *button;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Constraints");
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
gtk_container_add (GTK_CONTAINER (window), box);
|
||||
|
||||
grid = g_object_new (vfl_grid_get_type (), NULL);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
gtk_widget_set_vexpand (grid, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (box), grid);
|
||||
|
||||
button = gtk_button_new_with_label ("Close");
|
||||
gtk_container_add (GTK_CONTAINER (box), button);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
g_signal_connect_swapped (button, "clicked",
|
||||
G_CALLBACK (gtk_widget_destroy), window);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -150,6 +150,9 @@
|
||||
<file>clipboard.c</file>
|
||||
<file>colorsel.c</file>
|
||||
<file>combobox.c</file>
|
||||
<file>constraints.c</file>
|
||||
<file>constraints2.c</file>
|
||||
<file>constraints3.c</file>
|
||||
<file>css_accordion.c</file>
|
||||
<file>css_basics.c</file>
|
||||
<file>css_blendmodes.c</file>
|
||||
@@ -171,6 +174,7 @@
|
||||
<file>foreigndrawing.c</file>
|
||||
<file>font_features.c</file>
|
||||
<file>fontplane.c</file>
|
||||
<file>fontrendering.c</file>
|
||||
<file>gestures.c</file>
|
||||
<file>glarea.c</file>
|
||||
<file>headerbar.c</file>
|
||||
@@ -278,6 +282,9 @@
|
||||
<gresource prefix="/fixed">
|
||||
<file>fixed.css</file>
|
||||
</gresource>
|
||||
<gresource prefix="/fontrendering">
|
||||
<file>fontrendering.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/org/gtk/Demo4">
|
||||
<file>icons/16x16/actions/application-exit.png</file>
|
||||
<file>icons/16x16/actions/document-new.png</file>
|
||||
|
||||
@@ -306,6 +306,7 @@ do_fishbowl (GtkWidget *do_widget)
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
gtk_widget_realize (window);
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
/* Pango/Font rendering
|
||||
*
|
||||
* Demonstrates various aspects of font rendering.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
static GtkWidget *font_button = NULL;
|
||||
static GtkWidget *entry = NULL;
|
||||
static GtkWidget *image = NULL;
|
||||
static GtkWidget *hinting = NULL;
|
||||
static GtkWidget *hint_metrics = NULL;
|
||||
static GtkWidget *up_button = NULL;
|
||||
static GtkWidget *down_button = NULL;
|
||||
static GtkWidget *text_radio = NULL;
|
||||
static GtkWidget *show_grid = NULL;
|
||||
static GtkWidget *show_extents = NULL;
|
||||
|
||||
static PangoContext *context;
|
||||
|
||||
static int scale = 10;
|
||||
|
||||
static void
|
||||
on_destroy (gpointer data)
|
||||
{
|
||||
window = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
update_image (void)
|
||||
{
|
||||
const char *text;
|
||||
PangoFontDescription *desc;
|
||||
PangoLayout *layout;
|
||||
PangoRectangle ink, pink, logical;
|
||||
int baseline;
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkPixbuf *pixbuf2;
|
||||
const char *hint;
|
||||
cairo_font_options_t *fopt;
|
||||
cairo_hint_style_t hintstyle;
|
||||
cairo_hint_metrics_t hintmetrics;
|
||||
int i;
|
||||
|
||||
if (!context)
|
||||
context = gtk_widget_create_pango_context (image);
|
||||
|
||||
text = gtk_editable_get_text (GTK_EDITABLE (entry));
|
||||
desc = gtk_font_chooser_get_font_desc (GTK_FONT_CHOOSER (font_button));
|
||||
|
||||
fopt = cairo_font_options_copy (pango_cairo_context_get_font_options (context));
|
||||
|
||||
hint = gtk_combo_box_get_active_id (GTK_COMBO_BOX (hinting));
|
||||
if (strcmp (hint, "none") == 0)
|
||||
hintstyle = CAIRO_HINT_STYLE_NONE;
|
||||
else if (strcmp (hint, "slight") == 0)
|
||||
hintstyle = CAIRO_HINT_STYLE_SLIGHT;
|
||||
else if (strcmp (hint, "medium") == 0)
|
||||
hintstyle = CAIRO_HINT_STYLE_MEDIUM;
|
||||
else if (strcmp (hint, "full") == 0)
|
||||
hintstyle = CAIRO_HINT_STYLE_FULL;
|
||||
else
|
||||
hintstyle = CAIRO_HINT_STYLE_DEFAULT;
|
||||
cairo_font_options_set_hint_style (fopt, hintstyle);
|
||||
|
||||
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (hint_metrics)))
|
||||
hintmetrics = CAIRO_HINT_METRICS_ON;
|
||||
else
|
||||
hintmetrics = CAIRO_HINT_METRICS_OFF;
|
||||
cairo_font_options_set_hint_metrics (fopt, hintmetrics);
|
||||
|
||||
pango_cairo_context_set_font_options (context, fopt);
|
||||
cairo_font_options_destroy (fopt);
|
||||
pango_context_changed (context);
|
||||
|
||||
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (text_radio)))
|
||||
{
|
||||
layout = pango_layout_new (context);
|
||||
pango_layout_set_font_description (layout, desc);
|
||||
pango_layout_set_text (layout, text, -1);
|
||||
pango_layout_get_extents (layout, &ink, &logical);
|
||||
pink = ink;
|
||||
baseline = pango_layout_get_baseline (layout);
|
||||
|
||||
pango_extents_to_pixels (&ink, NULL);
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ink.width + 20, ink.height + 20);
|
||||
cr = cairo_create (surface);
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_move_to (cr, 10, 10);
|
||||
pango_cairo_show_layout (cr, layout);
|
||||
|
||||
cairo_destroy (cr);
|
||||
g_object_unref (layout);
|
||||
|
||||
pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface));
|
||||
pixbuf2 = gdk_pixbuf_scale_simple (pixbuf, gdk_pixbuf_get_width (pixbuf) * scale, gdk_pixbuf_get_height (pixbuf) * scale, GDK_INTERP_NEAREST);
|
||||
|
||||
g_object_unref (pixbuf);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
surface = cairo_image_surface_create_for_data (gdk_pixbuf_get_pixels (pixbuf2),
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
gdk_pixbuf_get_width (pixbuf2),
|
||||
gdk_pixbuf_get_height (pixbuf2),
|
||||
gdk_pixbuf_get_rowstride (pixbuf2));
|
||||
|
||||
cr = cairo_create (surface);
|
||||
cairo_set_line_width (cr, 1);
|
||||
|
||||
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (show_grid)))
|
||||
{
|
||||
cairo_set_source_rgba (cr, 0.2, 0, 0, 0.2);
|
||||
for (i = 1; i < ink.height + 20; i++)
|
||||
{
|
||||
cairo_move_to (cr, 0, scale * i - 0.5);
|
||||
cairo_line_to (cr, scale * (ink.width + 20), scale * i - 0.5);
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
for (i = 1; i < ink.width + 20; i++)
|
||||
{
|
||||
cairo_move_to (cr, scale * i - 0.5, 0);
|
||||
cairo_line_to (cr, scale * i - 0.5, scale * (ink.height + 20));
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
}
|
||||
|
||||
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (show_extents)))
|
||||
{
|
||||
cairo_set_source_rgba (cr, 0, 0, 1, 1);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
scale * (10 + pango_units_to_double (logical.x)) - 0.5,
|
||||
scale * (10 + pango_units_to_double (logical.y)) - 0.5,
|
||||
scale * pango_units_to_double (logical.width) + 1,
|
||||
scale * pango_units_to_double (logical.height) + 1);
|
||||
cairo_stroke (cr);
|
||||
cairo_move_to (cr, scale * (10 + pango_units_to_double (logical.x)) - 0.5,
|
||||
scale * (10 + pango_units_to_double (baseline)) - 0.5);
|
||||
cairo_line_to (cr, scale * (10 + pango_units_to_double (logical.x + logical.width)) + 1,
|
||||
scale * (10 + pango_units_to_double (baseline)) - 0.5);
|
||||
cairo_stroke (cr);
|
||||
cairo_set_source_rgba (cr, 1, 0, 0, 1);
|
||||
cairo_rectangle (cr,
|
||||
scale * (10 + pango_units_to_double (pink.x)) + 0.5,
|
||||
scale * (10 + pango_units_to_double (pink.y)) + 0.5,
|
||||
scale * pango_units_to_double (pink.width) - 1,
|
||||
scale * pango_units_to_double (pink.height) - 1);
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
else
|
||||
{
|
||||
PangoLayoutIter *iter;
|
||||
PangoLayoutRun *run;
|
||||
PangoGlyphInfo *g;
|
||||
int i, j;
|
||||
|
||||
layout = pango_layout_new (context);
|
||||
pango_layout_set_font_description (layout, desc);
|
||||
pango_layout_set_text (layout, "aaaa", -1);
|
||||
pango_layout_get_extents (layout, &ink, &logical);
|
||||
pango_extents_to_pixels (&logical, NULL);
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, logical.width * 3 / 2, 4*logical.height);
|
||||
cr = cairo_create (surface);
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_paint (cr);
|
||||
|
||||
iter = pango_layout_get_iter (layout);
|
||||
run = pango_layout_iter_get_run (iter);
|
||||
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
g = &(run->glyphs->glyphs[i]);
|
||||
g->geometry.width = PANGO_UNITS_ROUND (g->geometry.width * 3 / 2);
|
||||
}
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
g = &(run->glyphs->glyphs[i]);
|
||||
g->geometry.x_offset = i * (PANGO_SCALE / 4);
|
||||
g->geometry.y_offset = j * (PANGO_SCALE / 4);
|
||||
}
|
||||
|
||||
cairo_move_to (cr, 0, j * logical.height);
|
||||
pango_cairo_show_layout (cr, layout);
|
||||
}
|
||||
|
||||
cairo_destroy (cr);
|
||||
pango_layout_iter_free (iter);
|
||||
g_object_unref (layout);
|
||||
|
||||
pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface));
|
||||
pixbuf2 = gdk_pixbuf_scale_simple (pixbuf, gdk_pixbuf_get_width (pixbuf) * scale, gdk_pixbuf_get_height (pixbuf) * scale, GDK_INTERP_NEAREST);
|
||||
g_object_unref (pixbuf);
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
|
||||
|
||||
gtk_picture_set_pixbuf (GTK_PICTURE (image), pixbuf2);
|
||||
|
||||
g_object_unref (pixbuf2);
|
||||
|
||||
pango_font_description_free (desc);
|
||||
}
|
||||
|
||||
static void
|
||||
update_buttons (void)
|
||||
{
|
||||
gtk_widget_set_sensitive (up_button, scale < 32);
|
||||
gtk_widget_set_sensitive (down_button, scale > 1);
|
||||
}
|
||||
|
||||
static void
|
||||
scale_up (void)
|
||||
{
|
||||
scale += 1;
|
||||
update_buttons ();
|
||||
update_image ();
|
||||
}
|
||||
|
||||
static void
|
||||
scale_down (void)
|
||||
{
|
||||
scale -= 1;
|
||||
update_buttons ();
|
||||
update_image ();
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_fontrendering (GtkWidget *do_widget)
|
||||
{
|
||||
if (!window)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/fontrendering/fontrendering.ui");
|
||||
gtk_builder_connect_signals (builder, NULL);
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (on_destroy), NULL);
|
||||
g_object_set_data_full (G_OBJECT (window), "builder", builder, g_object_unref);
|
||||
font_button = GTK_WIDGET (gtk_builder_get_object (builder, "font_button"));
|
||||
up_button = GTK_WIDGET (gtk_builder_get_object (builder, "up_button"));
|
||||
down_button = GTK_WIDGET (gtk_builder_get_object (builder, "down_button"));
|
||||
entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry"));
|
||||
image = GTK_WIDGET (gtk_builder_get_object (builder, "image"));
|
||||
hinting = GTK_WIDGET (gtk_builder_get_object (builder, "hinting"));
|
||||
hint_metrics = GTK_WIDGET (gtk_builder_get_object (builder, "hint_metrics"));
|
||||
text_radio = GTK_WIDGET (gtk_builder_get_object (builder, "text_radio"));
|
||||
show_grid = GTK_WIDGET (gtk_builder_get_object (builder, "show_grid"));
|
||||
show_extents = GTK_WIDGET (gtk_builder_get_object (builder, "show_extents"));
|
||||
|
||||
g_signal_connect (up_button, "clicked", G_CALLBACK (scale_up), NULL);
|
||||
g_signal_connect (down_button, "clicked", G_CALLBACK (scale_down), NULL);
|
||||
g_signal_connect (entry, "notify::text", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (font_button, "notify::font-desc", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (hinting, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (hint_metrics, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (text_radio, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (show_grid, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (show_extents, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
|
||||
update_image ();
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GtkAdjustment" id="scale_adj">
|
||||
<property name="upper">24</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="page-increment">4</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="default-width">600</property>
|
||||
<property name="default-height">300</property>
|
||||
<property name="title">Font rendering</property>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<property name="margin-top">10</property>
|
||||
<property name="row-spacing">10</property>
|
||||
<property name="column-spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="label">Text</property>
|
||||
<property name="xalign">1</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="entry">
|
||||
<property name="text">Fonts render</property>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="label">Font</property>
|
||||
<property name="xalign">1</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFontButton" id="font_button">
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Hinting</property>
|
||||
<property name="xalign">1</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
<layout>
|
||||
<property name="left-attach">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="hinting">
|
||||
<property name="active">0</property>
|
||||
<property name="valign">center</property>
|
||||
<items>
|
||||
<item translatable="yes" id="none">None</item>
|
||||
<item translatable="yes" id="slight">Slight</item>
|
||||
<item translatable="yes" id="medium">Medium</item>
|
||||
<item translatable="yes" id="full">Full</item>
|
||||
</items>
|
||||
<layout>
|
||||
<property name="left-attach">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="hint_metrics">
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Hint Metrics</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="left-attach">3</property>
|
||||
<property name="top-attach">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="show_extents">
|
||||
<property name="active">1</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Show Extents</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="left-attach">4</property>
|
||||
<property name="top-attach">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="show_grid">
|
||||
<property name="active">1</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Show Grid</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="left-attach">4</property>
|
||||
<property name="top-attach">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="up_button">
|
||||
<property name="icon-name">list-add-symbolic</property>
|
||||
<style>
|
||||
<class name="circular"/>
|
||||
</style>
|
||||
<layout>
|
||||
<property name="left-attach">5</property>
|
||||
<property name="top-attach">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="down_button">
|
||||
<property name="icon-name">list-remove-symbolic</property>
|
||||
<style>
|
||||
<class name="circular"/>
|
||||
</style>
|
||||
<layout>
|
||||
<property name="left-attach">5</property>
|
||||
<property name="top-attach">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="hexpand">1</property>
|
||||
<layout>
|
||||
<property name="left-attach">6</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<style><class name="linked"/></style>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="text_radio">
|
||||
<property name="draw-indicator">0</property>
|
||||
<property name="label">Text</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="grid_radio">
|
||||
<property name="draw-indicator">0</property>
|
||||
<property name="label">Grid</property>
|
||||
<property name="group">text_radio</property>
|
||||
</object>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">3</property>
|
||||
<property name="column-span">7</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="propagate-natural-height">1</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
<child>
|
||||
<object class="GtkPicture" id="image">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="can-shrink">0</property>
|
||||
</object>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">4</property>
|
||||
<property name="column-span">7</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -202,7 +202,7 @@ languages_variant_init (const char *variant)
|
||||
else
|
||||
g_warning ("Failed to load '%s': %s\n", filename, error->message);
|
||||
|
||||
g_free (error);
|
||||
g_clear_error (&error);
|
||||
g_free (filename);
|
||||
g_free (buf);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ demos = files([
|
||||
'clipboard.c',
|
||||
'colorsel.c',
|
||||
'combobox.c',
|
||||
'constraints.c',
|
||||
'constraints2.c',
|
||||
'constraints3.c',
|
||||
'css_accordion.c',
|
||||
'css_basics.c',
|
||||
'css_blendmodes.c',
|
||||
@@ -25,6 +28,7 @@ demos = files([
|
||||
'filtermodel.c',
|
||||
'fishbowl.c',
|
||||
'fixed.c',
|
||||
'fontrendering.c',
|
||||
'foreigndrawing.c',
|
||||
'gestures.c',
|
||||
'glarea.c',
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
subdir('constraint-editor')
|
||||
subdir('gtk-demo')
|
||||
subdir('icon-browser')
|
||||
subdir('node-editor')
|
||||
|
||||
@@ -707,6 +707,14 @@ static void
|
||||
node_editor_window_unrealize (GtkWidget *widget)
|
||||
{
|
||||
NodeEditorWindow *self = NODE_EDITOR_WINDOW (widget);
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (self->renderers)); i ++)
|
||||
{
|
||||
gpointer item = g_list_model_get_item (G_LIST_MODEL (self->renderers), i);
|
||||
gsk_renderer_unrealize (gtk_renderer_paintable_get_renderer (item));
|
||||
g_object_unref (item);
|
||||
}
|
||||
|
||||
g_list_store_remove_all (self->renderers);
|
||||
|
||||
|
||||
@@ -1405,8 +1405,10 @@ text_view_add_to_context_menu (GtkTextView *text_view)
|
||||
item = g_menu_item_new (_("Underline"), "format.underline");
|
||||
g_menu_item_set_attribute (item, "touch-icon", "s", "format-text-underline-symbolic");
|
||||
g_menu_append_item (G_MENU (menu), item);
|
||||
g_object_unref (item);
|
||||
|
||||
gtk_text_view_set_extra_menu (text_view, G_MENU_MODEL (menu));
|
||||
g_object_unref (menu);
|
||||
|
||||
g_signal_connect (gtk_text_view_get_buffer (text_view), "changed", G_CALLBACK (text_changed), NULL);
|
||||
g_signal_connect (gtk_text_view_get_buffer (text_view), "mark-set", G_CALLBACK (text_changed), NULL);
|
||||
@@ -1601,14 +1603,14 @@ reset_icon_size (GtkWidget *iv)
|
||||
gtk_widget_queue_resize (iv);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
scale_format_value_blank (GtkScale *scale, gdouble value)
|
||||
static char *
|
||||
scale_format_value_blank (GtkScale *scale, double value, gpointer user_data)
|
||||
{
|
||||
return g_strdup (" ");
|
||||
}
|
||||
|
||||
static gchar *
|
||||
scale_format_value (GtkScale *scale, gdouble value)
|
||||
static char *
|
||||
scale_format_value (GtkScale *scale, double value, gpointer user_data)
|
||||
{
|
||||
return g_strdup_printf ("%0.*f", 1, value);
|
||||
}
|
||||
@@ -1707,7 +1709,7 @@ activate (GApplication *app)
|
||||
gtk_css_provider_load_from_resource (provider, "/org/gtk/WidgetFactory4/widget-factory.css");
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
g_object_unref (provider);
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/org/gtk/WidgetFactory4/widget-factory.ui");
|
||||
@@ -1722,8 +1724,6 @@ activate (GApplication *app)
|
||||
gtk_builder_add_callback_symbol (builder, "increase_icon_size", (GCallback)increase_icon_size);
|
||||
gtk_builder_add_callback_symbol (builder, "decrease_icon_size", (GCallback)decrease_icon_size);
|
||||
gtk_builder_add_callback_symbol (builder, "reset_icon_size", (GCallback)reset_icon_size);
|
||||
gtk_builder_add_callback_symbol (builder, "scale_format_value", (GCallback)scale_format_value);
|
||||
gtk_builder_add_callback_symbol (builder, "scale_format_value_blank", (GCallback)scale_format_value_blank);
|
||||
gtk_builder_add_callback_symbol (builder, "osd_frame_pressed", (GCallback)osd_frame_pressed);
|
||||
|
||||
gtk_builder_connect_signals (builder, NULL);
|
||||
@@ -1943,6 +1943,12 @@ activate (GApplication *app)
|
||||
widget = (GtkWidget *)gtk_builder_get_object (builder, "extra_info_entry");
|
||||
g_timeout_add (100, (GSourceFunc)pulse_it, widget);
|
||||
|
||||
widget = (GtkWidget *)gtk_builder_get_object (builder, "scale3");
|
||||
gtk_scale_set_format_value_func (GTK_SCALE (widget), scale_format_value, NULL, NULL);
|
||||
|
||||
widget = (GtkWidget *)gtk_builder_get_object (builder, "scale4");
|
||||
gtk_scale_set_format_value_func (GTK_SCALE (widget), scale_format_value_blank, NULL, NULL);
|
||||
|
||||
widget = (GtkWidget *)gtk_builder_get_object (builder, "box_for_context");
|
||||
model = (GMenuModel *)gtk_builder_get_object (builder, "new_style_context_menu_model");
|
||||
set_up_context_popover (widget, model);
|
||||
|
||||
@@ -1019,7 +1019,6 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<property name="fill-level">75</property>
|
||||
<property name="digits">-1</property>
|
||||
<property name="halign">end</property>
|
||||
<signal name="format-value" handler="scale_format_value"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
@@ -1033,7 +1032,6 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<property name="fill-level">75</property>
|
||||
<property name="digits">-1</property>
|
||||
<property name="halign">start</property>
|
||||
<signal name="format-value" handler="scale_format_value_blank"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@@ -3435,6 +3433,7 @@ bad things might happen.</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="icon-name">emblem-system-symbolic</property>
|
||||
<property name="menu-model">gear_menu</property>
|
||||
<property name="tooltip-text">This is a menu button</property>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">3</property>
|
||||
|
||||
@@ -99,7 +99,7 @@ if wayland_enabled
|
||||
src_dir += [ gdkwayland_inc ]
|
||||
endif
|
||||
|
||||
if get_option('documentation')
|
||||
if get_option('gtk_doc')
|
||||
configure_file(input: 'version.xml.in', output: 'version.xml', configuration: version_conf)
|
||||
|
||||
gnome.gtkdoc('gdk4',
|
||||
|
||||
@@ -34,7 +34,7 @@ private_headers = [
|
||||
images = [
|
||||
]
|
||||
|
||||
if get_option('documentation')
|
||||
if get_option('gtk_doc')
|
||||
configure_file(input: 'version.xml.in', output: 'version.xml', configuration: version_conf)
|
||||
|
||||
gnome.gtkdoc('gsk4',
|
||||
|
||||
@@ -355,8 +355,8 @@ How to compile GTK itself
|
||||
</group>
|
||||
<sbr/>
|
||||
<group>
|
||||
<arg choice="plain">-Ddocumentation=true</arg>
|
||||
<arg choice="plain">-Ddocumentation=false</arg>
|
||||
<arg choice="plain">-Dgtk_doc=true</arg>
|
||||
<arg choice="plain">-Dgtk_doc=false</arg>
|
||||
</group>
|
||||
<sbr/>
|
||||
<group>
|
||||
@@ -382,7 +382,7 @@ How to compile GTK itself
|
||||
</formalpara>
|
||||
|
||||
<formalpara>
|
||||
<title><systemitem>documentation</systemitem> and
|
||||
<title><systemitem>gtk_doc</systemitem> and
|
||||
<systemitem>man-pages</systemitem></title>
|
||||
|
||||
<para>
|
||||
@@ -394,7 +394,7 @@ How to compile GTK itself
|
||||
<application>gtk-doc</application> installed and
|
||||
are modifying GTK, you may want to enable
|
||||
<application>gtk-doc</application> support by passing
|
||||
in <systemitem>documentation</systemitem>.
|
||||
in <systemitem>gtk_doc</systemitem>.
|
||||
</para>
|
||||
<para>
|
||||
Additionally, some tools provided by GTK have their own
|
||||
|
||||
@@ -109,6 +109,9 @@
|
||||
<xi:include href="xml/gtkcustomlayout.xml" />
|
||||
<xi:include href="xml/gtkfixedlayout.xml" />
|
||||
<xi:include href="xml/gtkgridlayout.xml" />
|
||||
<xi:include href="xml/gtkconstraintlayout.xml" />
|
||||
<xi:include href="xml/gtkconstraint.xml" />
|
||||
<xi:include href="xml/gtkconstraintguide.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="DisplayWidgets">
|
||||
|
||||
@@ -136,6 +136,7 @@ gtk_accel_map_get_type
|
||||
GtkAccelLabel
|
||||
gtk_accel_label_new
|
||||
gtk_accel_label_set_accel_closure
|
||||
gtk_accel_label_get_accel_closure
|
||||
gtk_accel_label_get_accel_widget
|
||||
gtk_accel_label_set_accel_widget
|
||||
gtk_accel_label_get_accel_width
|
||||
@@ -4432,7 +4433,6 @@ gtk_widget_realize
|
||||
gtk_widget_unrealize
|
||||
gtk_widget_queue_draw
|
||||
gtk_widget_queue_resize
|
||||
gtk_widget_queue_resize_no_redraw
|
||||
gtk_widget_queue_allocate
|
||||
gtk_widget_get_frame_clock
|
||||
gtk_widget_get_scale_factor
|
||||
@@ -4604,7 +4604,6 @@ gtk_widget_get_vexpand
|
||||
gtk_widget_set_vexpand
|
||||
gtk_widget_get_vexpand_set
|
||||
gtk_widget_set_vexpand_set
|
||||
gtk_widget_queue_compute_expand
|
||||
gtk_widget_compute_expand
|
||||
|
||||
<SUBSECTION Templates>
|
||||
@@ -6739,6 +6738,8 @@ gtk_gesture_drag_get_type
|
||||
<TITLE>GtkGestureLongPress</TITLE>
|
||||
GtkGestureLongPress
|
||||
gtk_gesture_long_press_new
|
||||
gtk_gesture_long_press_set_delay_factor
|
||||
gtk_gesture_long_press_get_delay_factor
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_GESTURE_LONG_PRESS
|
||||
@@ -7287,3 +7288,87 @@ gtk_grid_layout_get_type
|
||||
GTK_TYPE_GRID_LAYOUT_CHILD
|
||||
gtk_grid_layout_child_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkconstraint</FILE>
|
||||
GtkConstraint
|
||||
GtkConstraintTarget
|
||||
|
||||
gtk_constraint_new
|
||||
gtk_constraint_new_constant
|
||||
gtk_constraint_get_target
|
||||
GtkConstraintAttribute
|
||||
gtk_constraint_get_target_attribute
|
||||
GtkConstraintRelation
|
||||
gtk_constraint_get_relation
|
||||
gtk_constraint_get_source
|
||||
gtk_constraint_get_source_attribute
|
||||
gtk_constraint_get_multiplier
|
||||
gtk_constraint_get_constant
|
||||
GtkConstraintStrength
|
||||
gtk_constraint_get_strength
|
||||
gtk_constraint_is_required
|
||||
gtk_constraint_is_attached
|
||||
gtk_constraint_is_constant
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_CONSTRAINT
|
||||
gtk_constraint_get_type
|
||||
GTK_TYPE_CONSTRAINT_TARGET
|
||||
gtk_constraint_target_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkconstraintlayout</FILE>
|
||||
GtkConstraintLayout
|
||||
GtkConstraintLayoutChild
|
||||
GtkConstraintVflParserError
|
||||
|
||||
gtk_constraint_layout_new
|
||||
|
||||
<SUBSECTION Constraints>
|
||||
gtk_constraint_layout_add_constraint
|
||||
gtk_constraint_layout_remove_constraint
|
||||
gtk_constraint_layout_remove_all_constraints
|
||||
|
||||
<SUBSECTION Guides>
|
||||
gtk_constraint_layout_add_guide
|
||||
gtk_constraint_layout_remove_guide
|
||||
|
||||
<SUBSECTION VFL>
|
||||
gtk_constraint_layout_add_constraints_from_description
|
||||
gtk_constraint_layout_add_constraints_from_descriptionv
|
||||
|
||||
<SUBSECTION>
|
||||
gtk_constraint_layout_observe_constraints
|
||||
gtk_constraint_layout_observe_guides
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_CONSTRAINT_LAYOUT
|
||||
gtk_constraint_layout_get_type
|
||||
GTK_TYPE_CONSTRAINT_LAYOUT_CHILD
|
||||
gtk_constraint_layout_child_get_type
|
||||
GTK_CONSTRAINT_VFL_PARSER_ERROR
|
||||
gtk_constraint_vfl_parser_error_quark
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkconstraintguide</FILE>
|
||||
GtkConstraintGuide
|
||||
|
||||
gtk_constraint_guide_new
|
||||
gtk_constraint_guide_set_name
|
||||
gtk_constraint_guide_get_name
|
||||
gtk_constraint_guide_set_strength
|
||||
gtk_constraint_guide_get_strength
|
||||
gtk_constraint_guide_set_min_size
|
||||
gtk_constraint_guide_get_min_size
|
||||
gtk_constraint_guide_set_nat_size
|
||||
gtk_constraint_guide_get_nat_size
|
||||
gtk_constraint_guide_set_max_size
|
||||
gtk_constraint_guide_get_max_size
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_CONSTRAINT_GUIDE
|
||||
gtk_constraint_guide_get_tyoe
|
||||
</SECTION>
|
||||
|
||||
@@ -49,6 +49,10 @@ gtk_color_chooser_dialog_get_type
|
||||
gtk_color_chooser_widget_get_type
|
||||
gtk_combo_box_get_type
|
||||
gtk_combo_box_text_get_type
|
||||
gtk_constraint_get_type
|
||||
gtk_constraint_guide_get_type
|
||||
gtk_constraint_layout_get_type
|
||||
gtk_constraint_target_get_type
|
||||
gtk_container_get_type
|
||||
gtk_css_provider_get_type
|
||||
gtk_dialog_get_type
|
||||
|
||||
@@ -23,6 +23,13 @@ private_headers = [
|
||||
'gtkcolorswatchprivate.h',
|
||||
'gtkcomboboxprivate.h',
|
||||
'gtkcontainerprivate.h',
|
||||
'gtkconstraintexpressionprivate.h',
|
||||
'gtkconstraintguideprivate.h',
|
||||
'gtkconstraintlayoutprivate.h',
|
||||
'gtkconstraintprivate.h',
|
||||
'gtkconstraintsolverprivate.h',
|
||||
'gtkconstrainttypesprivate.h',
|
||||
'gtkconstraintvflparserprivate.h',
|
||||
'gtkcssanimatedstyleprivate.h',
|
||||
'gtkcssanimationprivate.h',
|
||||
'gtkcssarrayvalueprivate.h',
|
||||
@@ -394,7 +401,7 @@ else
|
||||
types_conf.set('DISABLE_ON_QUARTZ', '')
|
||||
endif
|
||||
|
||||
if get_option('documentation')
|
||||
if get_option('gtk_doc')
|
||||
configure_file(input: 'version.xml.in', output: 'version.xml', configuration: version_conf)
|
||||
configure_file(input: 'getting_started.xml.in', output: 'getting_started.xml', configuration: src_dir_conf)
|
||||
|
||||
|
||||
@@ -11,7 +11,10 @@ GTK is released under the GNU Library General Public License
|
||||
applications. GTK has a C-based object-oriented architecture that
|
||||
allows for maximum flexibility. Bindings for many other languages have
|
||||
been written, including C++, Objective-C, Guile/Scheme, Perl, Python,
|
||||
TOM, Ada95, Free Pascal, and Eiffel.
|
||||
TOM, Ada95, Free Pascal, and Eiffel. The GTK library itself contains
|
||||
<firstterm>widgets</firstterm>, that is, GUI components such as GtkButton
|
||||
or GtkTextView.
|
||||
|
||||
</para>
|
||||
<para>
|
||||
GTK depends on the following libraries:
|
||||
@@ -105,14 +108,6 @@ and rendering it using different rendering APIs. GSK provides renderers
|
||||
for OpenGL, Vulkan and cairo.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>GTK</term>
|
||||
<listitem><para>
|
||||
The GTK library itself contains <firstterm>widgets</firstterm>,
|
||||
that is, GUI components such as GtkButton or GtkTextView.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
if get_option('documentation')
|
||||
if get_option('gtk_doc')
|
||||
glib_prefix = dependency('glib-2.0').get_pkgconfig_variable('prefix')
|
||||
glib_docpath = join_paths(glib_prefix, 'share', 'gtk-doc', 'html')
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
if x11_enabled and get_option('documentation')
|
||||
if x11_enabled and get_option('gtk_doc')
|
||||
doc_shooter_sources = [
|
||||
'shadow.c',
|
||||
'shooter.c',
|
||||
|
||||
@@ -98,7 +98,9 @@ _gdk_broadway_display_size_changed (GdkDisplay *display,
|
||||
GdkBroadwaySurface *toplevel = l->data;
|
||||
|
||||
if (toplevel->maximized)
|
||||
gdk_surface_move_resize (GDK_SURFACE (toplevel), 0, 0, msg->width, msg->height);
|
||||
gdk_broadway_surface_move_resize (GDK_SURFACE (toplevel),
|
||||
0, 0,
|
||||
msg->width, msg->height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,12 @@ void _gdk_broadway_surface_grab_check_unmap (GdkSurface *surface,
|
||||
gulong serial);
|
||||
void gdk_broadway_surface_update_popups (GdkSurface *surface);
|
||||
|
||||
void gdk_broadway_surface_move_resize (GdkSurface *surface,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
|
||||
void _gdk_keymap_keys_changed (GdkDisplay *display);
|
||||
gint _gdk_broadway_get_group_for_state (GdkDisplay *display,
|
||||
GdkModifierType state);
|
||||
|
||||
@@ -88,10 +88,10 @@ gdk_broadway_surface_finalize (GObject *object)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
thaw_clock_cb (GdkFrameClock *clock)
|
||||
thaw_updates_cb (GdkSurface *surface)
|
||||
{
|
||||
_gdk_frame_clock_thaw (clock);
|
||||
g_object_unref (clock);
|
||||
gdk_surface_thaw_updates (surface);
|
||||
g_object_unref (surface);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
@@ -109,9 +109,9 @@ _gdk_broadway_roundtrip_notify (GdkSurface *surface,
|
||||
|
||||
/* If there is no remote web client, rate limit update to once a second */
|
||||
if (local_reply)
|
||||
g_timeout_add_seconds (1, (GSourceFunc)thaw_clock_cb, g_object_ref (clock));
|
||||
g_timeout_add_seconds (1, (GSourceFunc)thaw_updates_cb, g_object_ref (surface));
|
||||
else
|
||||
_gdk_frame_clock_thaw (clock);
|
||||
gdk_surface_thaw_updates (surface);
|
||||
|
||||
if (timings)
|
||||
{
|
||||
@@ -140,7 +140,7 @@ on_frame_clock_after_paint (GdkFrameClock *clock,
|
||||
GdkBroadwayDisplay *broadway_display;
|
||||
|
||||
impl->pending_frame_counter = gdk_frame_clock_get_frame_counter (clock);
|
||||
_gdk_frame_clock_freeze (gdk_surface_get_frame_clock (surface));
|
||||
gdk_surface_freeze_updates (surface);
|
||||
|
||||
broadway_display = GDK_BROADWAY_DISPLAY (display);
|
||||
|
||||
@@ -368,12 +368,12 @@ gdk_broadway_surface_withdraw (GdkSurface *surface)
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_surface_move_resize (GdkSurface *surface,
|
||||
gboolean with_move,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
gdk_broadway_surface_move_resize_internal (GdkSurface *surface,
|
||||
gboolean with_move,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
GdkBroadwaySurface *impl = GDK_BROADWAY_SURFACE (surface);
|
||||
GdkBroadwayDisplay *broadway_display;
|
||||
@@ -424,6 +424,84 @@ gdk_broadway_surface_move_resize (GdkSurface *surface,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gdk_broadway_surface_move_resize (GdkSurface *surface,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
gdk_broadway_surface_move_resize_internal (surface, TRUE,
|
||||
x, y,
|
||||
width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_surface_toplevel_resize (GdkSurface *surface,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
gdk_broadway_surface_move_resize_internal (surface, FALSE,
|
||||
0, 0,
|
||||
width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_surface_move (GdkSurface *surface,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
gdk_broadway_surface_move_resize_internal (surface, TRUE, x, y, -1, -1);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_surface_moved_to_rect (GdkSurface *surface,
|
||||
GdkRectangle final_rect)
|
||||
{
|
||||
GdkSurface *toplevel;
|
||||
int x, y;
|
||||
|
||||
if (surface->surface_type == GDK_SURFACE_POPUP)
|
||||
toplevel = surface->parent;
|
||||
else
|
||||
toplevel = surface->transient_for;
|
||||
|
||||
gdk_surface_get_origin (toplevel, &x, &y);
|
||||
x += final_rect.x;
|
||||
y += final_rect.y;
|
||||
|
||||
if (final_rect.width != surface->width ||
|
||||
final_rect.height != surface->height)
|
||||
{
|
||||
gdk_broadway_surface_move_resize (surface,
|
||||
x, y,
|
||||
final_rect.width, final_rect.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdk_broadway_surface_move (surface, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_surface_move_to_rect (GdkSurface *surface,
|
||||
const GdkRectangle *rect,
|
||||
GdkGravity rect_anchor,
|
||||
GdkGravity surface_anchor,
|
||||
GdkAnchorHints anchor_hints,
|
||||
gint rect_anchor_dx,
|
||||
gint rect_anchor_dy)
|
||||
{
|
||||
gdk_surface_move_to_rect_helper (surface,
|
||||
rect,
|
||||
rect_anchor,
|
||||
surface_anchor,
|
||||
anchor_hints,
|
||||
rect_anchor_dx,
|
||||
rect_anchor_dy,
|
||||
gdk_broadway_surface_moved_to_rect);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_surface_raise (GdkSurface *surface)
|
||||
{
|
||||
@@ -695,9 +773,9 @@ gdk_broadway_surface_maximize (GdkSurface *surface)
|
||||
monitor = gdk_display_get_primary_monitor (display);
|
||||
gdk_monitor_get_geometry (monitor, &geom);
|
||||
|
||||
gdk_surface_move_resize (surface,
|
||||
geom.x, geom.y,
|
||||
geom.width, geom.height);
|
||||
gdk_broadway_surface_move_resize (surface,
|
||||
geom.x, geom.y,
|
||||
geom.width, geom.height);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -718,11 +796,11 @@ gdk_broadway_surface_unmaximize (GdkSurface *surface)
|
||||
|
||||
gdk_synthesize_surface_state (surface, GDK_SURFACE_STATE_MAXIMIZED, 0);
|
||||
|
||||
gdk_surface_move_resize (surface,
|
||||
impl->pre_maximize_x,
|
||||
impl->pre_maximize_y,
|
||||
impl->pre_maximize_width,
|
||||
impl->pre_maximize_height);
|
||||
gdk_broadway_surface_move_resize (surface,
|
||||
impl->pre_maximize_x,
|
||||
impl->pre_maximize_y,
|
||||
impl->pre_maximize_width,
|
||||
impl->pre_maximize_height);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -813,7 +891,9 @@ gdk_broadway_surface_update_popups (GdkSurface *parent)
|
||||
int new_y = parent->y + popup_impl->offset_y;
|
||||
|
||||
if (new_x != popup->x || new_y != popup->y)
|
||||
gdk_broadway_surface_move_resize (popup, TRUE, new_x, new_y, popup->width, popup->height);
|
||||
gdk_broadway_surface_move_resize (popup,
|
||||
new_x, new_y,
|
||||
popup->width, popup->height);
|
||||
gdk_broadway_surface_restack_toplevel (popup, parent, TRUE);
|
||||
}
|
||||
}
|
||||
@@ -935,7 +1015,8 @@ update_pos (MoveResizeData *mv_resize,
|
||||
w, h, &w, &h);
|
||||
}
|
||||
|
||||
gdk_surface_move_resize (mv_resize->moveresize_surface, x, y, w, h);
|
||||
gdk_broadway_surface_move_resize (mv_resize->moveresize_surface,
|
||||
x, y, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -944,7 +1025,7 @@ update_pos (MoveResizeData *mv_resize,
|
||||
x = mv_resize->moveresize_orig_x + dx;
|
||||
y = mv_resize->moveresize_orig_y + dy;
|
||||
|
||||
gdk_surface_move (mv_resize->moveresize_surface, x, y);
|
||||
gdk_broadway_surface_move (mv_resize->moveresize_surface, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1311,7 +1392,8 @@ gdk_broadway_surface_class_init (GdkBroadwaySurfaceClass *klass)
|
||||
impl_class->raise = gdk_broadway_surface_raise;
|
||||
impl_class->lower = gdk_broadway_surface_lower;
|
||||
impl_class->restack_toplevel = gdk_broadway_surface_restack_toplevel;
|
||||
impl_class->move_resize = gdk_broadway_surface_move_resize;
|
||||
impl_class->toplevel_resize = gdk_broadway_surface_toplevel_resize;
|
||||
impl_class->move_to_rect = gdk_broadway_surface_move_to_rect;
|
||||
impl_class->get_geometry = gdk_broadway_surface_get_geometry;
|
||||
impl_class->get_root_coords = gdk_broadway_surface_get_root_coords;
|
||||
impl_class->get_device_state = gdk_broadway_surface_get_device_state;
|
||||
|
||||
+44
-2
@@ -97,10 +97,14 @@ struct _GdkFrameClockPrivate
|
||||
gint n_timings;
|
||||
gint current;
|
||||
GdkFrameTimings *timings[FRAME_HISTORY_MAX_LENGTH];
|
||||
gint n_freeze_inhibitors;
|
||||
};
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkFrameClock, gdk_frame_clock, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
_gdk_frame_clock_freeze (GdkFrameClock *clock);
|
||||
|
||||
static void
|
||||
gdk_frame_clock_finalize (GObject *object)
|
||||
{
|
||||
@@ -114,12 +118,21 @@ gdk_frame_clock_finalize (GObject *object)
|
||||
G_OBJECT_CLASS (gdk_frame_clock_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_frame_clock_constructed (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (gdk_frame_clock_parent_class)->constructed (object);
|
||||
|
||||
_gdk_frame_clock_freeze (GDK_FRAME_CLOCK (object));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_frame_clock_class_init (GdkFrameClockClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass*) klass;
|
||||
|
||||
gobject_class->finalize = gdk_frame_clock_finalize;
|
||||
gobject_class->constructed = gdk_frame_clock_constructed;
|
||||
|
||||
/**
|
||||
* GdkFrameClock::flush-events:
|
||||
@@ -335,7 +348,7 @@ gdk_frame_clock_end_updating (GdkFrameClock *frame_clock)
|
||||
GDK_FRAME_CLOCK_GET_CLASS (frame_clock)->end_updating (frame_clock);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
_gdk_frame_clock_freeze (GdkFrameClock *clock)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
|
||||
@@ -344,7 +357,7 @@ _gdk_frame_clock_freeze (GdkFrameClock *clock)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
static void
|
||||
_gdk_frame_clock_thaw (GdkFrameClock *clock)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
|
||||
@@ -352,6 +365,35 @@ _gdk_frame_clock_thaw (GdkFrameClock *clock)
|
||||
GDK_FRAME_CLOCK_GET_CLASS (clock)->thaw (clock);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_frame_clock_inhibit_freeze (GdkFrameClock *clock)
|
||||
{
|
||||
GdkFrameClockPrivate *priv;
|
||||
|
||||
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
|
||||
|
||||
priv = clock->priv;
|
||||
|
||||
priv->n_freeze_inhibitors++;
|
||||
if (priv->n_freeze_inhibitors == 1)
|
||||
_gdk_frame_clock_thaw (clock);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_gdk_frame_clock_uninhibit_freeze (GdkFrameClock *clock)
|
||||
{
|
||||
GdkFrameClockPrivate *priv;
|
||||
|
||||
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
|
||||
|
||||
priv = clock->priv;
|
||||
|
||||
priv->n_freeze_inhibitors--;
|
||||
if (priv->n_freeze_inhibitors == 0)
|
||||
_gdk_frame_clock_freeze (clock);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_frame_clock_get_frame_counter:
|
||||
* @frame_clock: a #GdkFrameClock
|
||||
|
||||
@@ -105,8 +105,8 @@ struct _GdkFrameTimings
|
||||
guint slept_before : 1;
|
||||
};
|
||||
|
||||
void _gdk_frame_clock_freeze (GdkFrameClock *clock);
|
||||
void _gdk_frame_clock_thaw (GdkFrameClock *clock);
|
||||
void _gdk_frame_clock_inhibit_freeze (GdkFrameClock *clock);
|
||||
void _gdk_frame_clock_uninhibit_freeze (GdkFrameClock *clock);
|
||||
|
||||
void _gdk_frame_clock_begin_frame (GdkFrameClock *clock);
|
||||
void _gdk_frame_clock_debug_print_timings (GdkFrameClock *clock,
|
||||
|
||||
@@ -264,16 +264,6 @@ void gdk_surface_get_geometry (GdkSurface *surface,
|
||||
gint *width,
|
||||
gint *height);
|
||||
|
||||
void gdk_surface_move (GdkSurface *surface,
|
||||
gint x,
|
||||
gint y);
|
||||
|
||||
void gdk_surface_move_resize (GdkSurface *surface,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
|
||||
GdkGLContext *gdk_surface_get_shared_data_gl_context (GdkSurface *surface);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
+69
-136
@@ -246,14 +246,15 @@ maybe_flip_position (gint bounds_pos,
|
||||
return primary;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_surface_real_move_to_rect (GdkSurface *surface,
|
||||
const GdkRectangle *rect,
|
||||
GdkGravity rect_anchor,
|
||||
GdkGravity surface_anchor,
|
||||
GdkAnchorHints anchor_hints,
|
||||
gint rect_anchor_dx,
|
||||
gint rect_anchor_dy)
|
||||
void
|
||||
gdk_surface_move_to_rect_helper (GdkSurface *surface,
|
||||
const GdkRectangle *rect,
|
||||
GdkGravity rect_anchor,
|
||||
GdkGravity surface_anchor,
|
||||
GdkAnchorHints anchor_hints,
|
||||
gint rect_anchor_dx,
|
||||
gint rect_anchor_dy,
|
||||
GdkSurfaceMovedToRect moved_to_rect)
|
||||
{
|
||||
GdkSurface *toplevel;
|
||||
GdkDisplay *display;
|
||||
@@ -362,17 +363,14 @@ gdk_surface_real_move_to_rect (GdkSurface *surface,
|
||||
final_rect.width += surface->shadow_left + surface->shadow_right;
|
||||
final_rect.height += surface->shadow_top + surface->shadow_bottom;
|
||||
|
||||
if (final_rect.width != surface->width || final_rect.height != surface->height)
|
||||
gdk_surface_move_resize (surface, final_rect.x, final_rect.y, final_rect.width, final_rect.height);
|
||||
else
|
||||
gdk_surface_move (surface, final_rect.x, final_rect.y);
|
||||
|
||||
gdk_surface_get_origin (toplevel, &x, &y);
|
||||
final_rect.x -= x;
|
||||
final_rect.y -= y;
|
||||
flipped_rect.x -= x;
|
||||
flipped_rect.y -= y;
|
||||
|
||||
moved_to_rect (surface, final_rect);
|
||||
|
||||
g_signal_emit_by_name (surface,
|
||||
"moved-to-rect",
|
||||
&flipped_rect,
|
||||
@@ -411,7 +409,6 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
|
||||
object_class->get_property = gdk_surface_get_property;
|
||||
|
||||
klass->beep = gdk_surface_real_beep;
|
||||
klass->move_to_rect = gdk_surface_real_move_to_rect;
|
||||
|
||||
/**
|
||||
* GdkSurface:cursor:
|
||||
@@ -1341,10 +1338,14 @@ gdk_surface_schedule_update (GdkSurface *surface)
|
||||
{
|
||||
GdkFrameClock *frame_clock;
|
||||
|
||||
if (surface &&
|
||||
(surface->update_freeze_count ||
|
||||
gdk_surface_is_toplevel_frozen (surface)))
|
||||
return;
|
||||
g_return_if_fail (surface);
|
||||
|
||||
if (surface->update_freeze_count ||
|
||||
gdk_surface_is_toplevel_frozen (surface))
|
||||
{
|
||||
surface->pending_schedule_update = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If there's no frame clock (a foreign surface), then the invalid
|
||||
* region will just stick around unless gdk_surface_process_updates()
|
||||
@@ -1400,7 +1401,6 @@ gdk_surface_paint_on_clock (GdkFrameClock *clock,
|
||||
void *data)
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (data);
|
||||
GList *l;
|
||||
|
||||
g_return_if_fail (GDK_IS_SURFACE (surface));
|
||||
|
||||
@@ -1421,9 +1421,6 @@ gdk_surface_paint_on_clock (GdkFrameClock *clock,
|
||||
gdk_surface_remove_update_surface (surface);
|
||||
}
|
||||
|
||||
for (l = surface->children; l; l = l->next)
|
||||
gdk_surface_paint_on_clock (clock, l->data);
|
||||
|
||||
g_object_unref (surface);
|
||||
}
|
||||
|
||||
@@ -1581,13 +1578,17 @@ gdk_surface_freeze_updates (GdkSurface *surface)
|
||||
g_return_if_fail (GDK_IS_SURFACE (surface));
|
||||
|
||||
surface->update_freeze_count++;
|
||||
if (surface->update_freeze_count == 1)
|
||||
_gdk_frame_clock_uninhibit_freeze (surface->frame_clock);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_surface_thaw_updates:
|
||||
* @surface: a #GdkSurface
|
||||
*
|
||||
* Thaws a surface frozen with gdk_surface_freeze_updates().
|
||||
* Thaws a surface frozen with gdk_surface_freeze_updates(). Note that this
|
||||
* will not necessarily schedule updates if the surface freeze count reaches
|
||||
* zero.
|
||||
**/
|
||||
void
|
||||
gdk_surface_thaw_updates (GdkSurface *surface)
|
||||
@@ -1597,7 +1598,15 @@ gdk_surface_thaw_updates (GdkSurface *surface)
|
||||
g_return_if_fail (surface->update_freeze_count > 0);
|
||||
|
||||
if (--surface->update_freeze_count == 0)
|
||||
gdk_surface_schedule_update (surface);
|
||||
{
|
||||
_gdk_frame_clock_inhibit_freeze (surface->frame_clock);
|
||||
|
||||
if (surface->pending_schedule_update)
|
||||
{
|
||||
surface->pending_schedule_update = FALSE;
|
||||
gdk_surface_schedule_update (surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1606,7 +1615,7 @@ gdk_surface_freeze_toplevel_updates (GdkSurface *surface)
|
||||
g_return_if_fail (GDK_IS_SURFACE (surface));
|
||||
|
||||
surface->update_and_descendants_freeze_count++;
|
||||
_gdk_frame_clock_freeze (gdk_surface_get_frame_clock (surface));
|
||||
gdk_surface_freeze_updates (surface);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1616,9 +1625,9 @@ gdk_surface_thaw_toplevel_updates (GdkSurface *surface)
|
||||
g_return_if_fail (surface->update_and_descendants_freeze_count > 0);
|
||||
|
||||
surface->update_and_descendants_freeze_count--;
|
||||
_gdk_frame_clock_thaw (gdk_surface_get_frame_clock (surface));
|
||||
|
||||
gdk_surface_schedule_update (surface);
|
||||
gdk_surface_thaw_updates (surface);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2060,59 +2069,6 @@ G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
GDK_SURFACE_GET_CLASS (surface)->hide (surface);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_surface_move_resize_toplevel (GdkSurface *surface,
|
||||
gboolean with_move,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
GDK_SURFACE_GET_CLASS (surface)->move_resize (surface, with_move, x, y, width, height);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gdk_surface_move_resize_internal (GdkSurface *surface,
|
||||
gboolean with_move,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_SURFACE (surface));
|
||||
|
||||
if (surface->destroyed)
|
||||
return;
|
||||
|
||||
gdk_surface_move_resize_toplevel (surface, with_move, x, y, width, height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* gdk_surface_move:
|
||||
* @surface: a #GdkSurface
|
||||
* @x: X coordinate relative to surface’s parent
|
||||
* @y: Y coordinate relative to surface’s parent
|
||||
*
|
||||
* Repositions a surface relative to its parent surface.
|
||||
* For toplevel surfaces, window managers may ignore or modify the move;
|
||||
* you should probably use gtk_window_move() on a #GtkWindow widget
|
||||
* anyway, instead of using GDK functions. For child surfaces,
|
||||
* the move will reliably succeed.
|
||||
*
|
||||
* If you’re also planning to resize the surface, use gdk_surface_move_resize()
|
||||
* to both move and resize simultaneously, for a nicer visual effect.
|
||||
**/
|
||||
void
|
||||
gdk_surface_move (GdkSurface *surface,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
gdk_surface_move_resize_internal (surface, TRUE, x, y, -1, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_surface_resize:
|
||||
* @surface: a #GdkSurface
|
||||
@@ -2130,31 +2086,7 @@ gdk_surface_resize (GdkSurface *surface,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
gdk_surface_move_resize_internal (surface, FALSE, 0, 0, width, height);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* gdk_surface_move_resize:
|
||||
* @surface: a #GdkSurface
|
||||
* @x: new X position relative to surface’s parent
|
||||
* @y: new Y position relative to surface’s parent
|
||||
* @width: new width
|
||||
* @height: new height
|
||||
*
|
||||
* Equivalent to calling gdk_surface_move() and gdk_surface_resize(),
|
||||
* except that both operations are performed at once, avoiding strange
|
||||
* visual effects. (i.e. the user may be able to see the surface first
|
||||
* move, then resize, if you don’t use gdk_surface_move_resize().)
|
||||
**/
|
||||
void
|
||||
gdk_surface_move_resize (GdkSurface *surface,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
gdk_surface_move_resize_internal (surface, TRUE, x, y, width, height);
|
||||
GDK_SURFACE_GET_CLASS (surface)->toplevel_resize (surface, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2951,8 +2883,7 @@ gdk_surface_set_modal_hint (GdkSurface *surface,
|
||||
* this is to constrain user resizing, but the windowing system
|
||||
* will typically (but is not required to) also constrain the
|
||||
* current size of the surface to the provided values and
|
||||
* constrain programatic resizing via gdk_surface_resize() or
|
||||
* gdk_surface_move_resize().
|
||||
* constrain programatic resizing via gdk_surface_resize().
|
||||
*
|
||||
* Note that on X11, this effect has no effect on surfaces
|
||||
* of type %GDK_SURFACE_TEMP since these surfaces are not resizable
|
||||
@@ -3703,40 +3634,42 @@ gdk_surface_set_frame_clock (GdkSurface *surface,
|
||||
if (clock)
|
||||
{
|
||||
g_object_ref (clock);
|
||||
if (surface->parent == NULL)
|
||||
{
|
||||
g_signal_connect (G_OBJECT (clock),
|
||||
"flush-events",
|
||||
G_CALLBACK (gdk_surface_flush_events),
|
||||
surface);
|
||||
g_signal_connect (G_OBJECT (clock),
|
||||
"resume-events",
|
||||
G_CALLBACK (gdk_surface_resume_events),
|
||||
surface);
|
||||
g_signal_connect (G_OBJECT (clock),
|
||||
"paint",
|
||||
G_CALLBACK (gdk_surface_paint_on_clock),
|
||||
surface);
|
||||
}
|
||||
|
||||
g_signal_connect (G_OBJECT (clock),
|
||||
"flush-events",
|
||||
G_CALLBACK (gdk_surface_flush_events),
|
||||
surface);
|
||||
g_signal_connect (G_OBJECT (clock),
|
||||
"resume-events",
|
||||
G_CALLBACK (gdk_surface_resume_events),
|
||||
surface);
|
||||
g_signal_connect (G_OBJECT (clock),
|
||||
"paint",
|
||||
G_CALLBACK (gdk_surface_paint_on_clock),
|
||||
surface);
|
||||
|
||||
if (surface->update_freeze_count == 0)
|
||||
_gdk_frame_clock_inhibit_freeze (clock);
|
||||
}
|
||||
|
||||
if (surface->frame_clock)
|
||||
{
|
||||
if (surface->parent == NULL)
|
||||
{
|
||||
if (surface->frame_clock_events_paused)
|
||||
gdk_surface_resume_events (surface->frame_clock, G_OBJECT (surface));
|
||||
if (surface->frame_clock_events_paused)
|
||||
gdk_surface_resume_events (surface->frame_clock, G_OBJECT (surface));
|
||||
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
|
||||
G_CALLBACK (gdk_surface_flush_events),
|
||||
surface);
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
|
||||
G_CALLBACK (gdk_surface_resume_events),
|
||||
surface);
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
|
||||
G_CALLBACK (gdk_surface_paint_on_clock),
|
||||
surface);
|
||||
|
||||
if (surface->update_freeze_count == 0)
|
||||
_gdk_frame_clock_uninhibit_freeze (surface->frame_clock);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
|
||||
G_CALLBACK (gdk_surface_flush_events),
|
||||
surface);
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
|
||||
G_CALLBACK (gdk_surface_resume_events),
|
||||
surface);
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
|
||||
G_CALLBACK (gdk_surface_paint_on_clock),
|
||||
surface);
|
||||
}
|
||||
g_object_unref (surface->frame_clock);
|
||||
}
|
||||
|
||||
|
||||
+15
-4
@@ -49,6 +49,7 @@ struct _GdkSurface
|
||||
|
||||
cairo_region_t *update_area;
|
||||
guint update_freeze_count;
|
||||
gboolean pending_schedule_update;
|
||||
/* This is the update_area that was in effect when the current expose
|
||||
started. It may be smaller than the expose area if we'e painting
|
||||
more than we have to, but it represents the "true" damage. */
|
||||
@@ -112,10 +113,7 @@ struct _GdkSurfaceClass
|
||||
GdkSurface *sibling,
|
||||
gboolean above);
|
||||
|
||||
void (* move_resize) (GdkSurface *surface,
|
||||
gboolean with_move,
|
||||
gint x,
|
||||
gint y,
|
||||
void (* toplevel_resize) (GdkSurface *surface,
|
||||
gint width,
|
||||
gint height);
|
||||
void (* move_to_rect) (GdkSurface *surface,
|
||||
@@ -257,6 +255,19 @@ struct _GdkSurfaceClass
|
||||
void gdk_surface_set_state (GdkSurface *surface,
|
||||
GdkSurfaceState new_state);
|
||||
|
||||
typedef void (* GdkSurfaceMovedToRect) (GdkSurface *surface,
|
||||
GdkRectangle final_rect);
|
||||
|
||||
void
|
||||
gdk_surface_move_to_rect_helper (GdkSurface *surface,
|
||||
const GdkRectangle *rect,
|
||||
GdkGravity rect_anchor,
|
||||
GdkGravity surface_anchor,
|
||||
GdkAnchorHints anchor_hints,
|
||||
gint rect_anchor_dx,
|
||||
gint rect_anchor_dy,
|
||||
GdkSurfaceMovedToRect moved_to_rect);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_SURFACE_PRIVATE_H__ */
|
||||
|
||||
@@ -1237,24 +1237,61 @@ window_quartz_move_resize (GdkSurface *window,
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_surface_quartz_move_resize (GdkSurface *window,
|
||||
gboolean with_move,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
gdk_surface_quartz_toplevel_resize (GdkSurface *surface,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
if (with_move && (width < 0 && height < 0))
|
||||
window_quartz_move (window, x, y);
|
||||
window_quartz_resize (window, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_quartz_surface_moved_to_rect (GdkSurface *surface,
|
||||
GdkRectangle final_rect)
|
||||
{
|
||||
GdkSurface *toplevel;
|
||||
int x, y;
|
||||
|
||||
if (surface->surface_type == GDK_SURFACE_POPUP)
|
||||
toplevel = surface->parent;
|
||||
else
|
||||
toplevel = surface->transient_for;
|
||||
|
||||
gdk_surface_get_origin (toplevel, &x, &y);
|
||||
x += final_rect.x;
|
||||
y += final_rect.y;
|
||||
|
||||
if (final_rect.width != surface->width ||
|
||||
final_rect.height != surface->height)
|
||||
{
|
||||
window_quartz_move_resize (surface,
|
||||
x, y,
|
||||
final_rect.width, final_rect.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (with_move)
|
||||
window_quartz_move_resize (window, x, y, width, height);
|
||||
else
|
||||
window_quartz_resize (window, width, height);
|
||||
window_quartz_resize (surface, final_rect.width, final_rect.height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_quartz_surface_move_to_rect (GdkSurface *surface,
|
||||
const GdkRectangle *rect,
|
||||
GdkGravity rect_anchor,
|
||||
GdkGravity surface_anchor,
|
||||
GdkAnchorHints anchor_hints,
|
||||
gint rect_anchor_dx,
|
||||
gint rect_anchor_dy)
|
||||
{
|
||||
gdk_surface_move_to_rect_helper (surface,
|
||||
rect,
|
||||
rect_anchor,
|
||||
surface_anchor,
|
||||
anchor_hints,
|
||||
rect_anchor_dx,
|
||||
rect_anchor_dy,
|
||||
gdk_quartz_surface_moved_to_rect);
|
||||
}
|
||||
|
||||
/* Get the toplevel ordering from NSApp and update our own list. We do
|
||||
* this on demand since the NSApp’s list is not up to date directly
|
||||
* after we get windowDidBecomeMain.
|
||||
@@ -2641,7 +2678,8 @@ gdk_surface_impl_quartz_class_init (GdkSurfaceImplQuartzClass *klass)
|
||||
impl_class->raise = gdk_surface_quartz_raise;
|
||||
impl_class->lower = gdk_surface_quartz_lower;
|
||||
impl_class->restack_toplevel = gdk_surface_quartz_restack_toplevel;
|
||||
impl_class->move_resize = gdk_surface_quartz_move_resize;
|
||||
impl_class->toplevel_resize = gdk_surface_quartz_toplevel_resize;
|
||||
impl_class->move_to_rect = gdk_surface_quartz_move_to_rect;
|
||||
impl_class->get_geometry = gdk_surface_quartz_get_geometry;
|
||||
impl_class->get_root_coords = gdk_surface_quartz_get_root_coords;
|
||||
impl_class->get_device_state = gdk_surface_quartz_get_device_state;
|
||||
|
||||
@@ -93,6 +93,7 @@
|
||||
|
||||
#define GTK_SHELL1_VERSION 2
|
||||
#define OUTPUT_VERSION_WITH_DONE 2
|
||||
#define NO_XDG_OUTPUT_DONE_SINCE_VERSION 3
|
||||
|
||||
static void _gdk_wayland_display_load_cursor_theme (GdkWaylandDisplay *display_wayland);
|
||||
|
||||
@@ -531,7 +532,7 @@ gdk_registry_handle_global (void *data,
|
||||
}
|
||||
else if (strcmp(interface, "zxdg_output_manager_v1") == 0)
|
||||
{
|
||||
display_wayland->xdg_output_manager_version = MIN (version, 2);
|
||||
display_wayland->xdg_output_manager_version = MIN (version, 3);
|
||||
display_wayland->xdg_output_manager =
|
||||
wl_registry_bind (display_wayland->wl_registry, id,
|
||||
&zxdg_output_manager_v1_interface,
|
||||
@@ -2217,6 +2218,9 @@ should_update_monitor (GdkWaylandMonitor *monitor)
|
||||
static void
|
||||
apply_monitor_change (GdkWaylandMonitor *monitor)
|
||||
{
|
||||
GdkDisplay *display = GDK_MONITOR (monitor)->display;
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
|
||||
GDK_NOTE (MISC,
|
||||
g_message ("monitor %d changed position %d %d, size %d %d",
|
||||
monitor->id,
|
||||
@@ -2227,7 +2231,11 @@ apply_monitor_change (GdkWaylandMonitor *monitor)
|
||||
gdk_monitor_set_size (GDK_MONITOR (monitor), monitor->width, monitor->height);
|
||||
gdk_monitor_set_connector (GDK_MONITOR (monitor), monitor->name);
|
||||
monitor->wl_output_done = FALSE;
|
||||
monitor->xdg_output_done = FALSE;
|
||||
/* xdg_output v3 marks xdg_output.done as deprecated, so if using
|
||||
* that version, no need to wait for xdg-output.done event.
|
||||
*/
|
||||
monitor->xdg_output_done =
|
||||
(display_wayland->xdg_output_manager_version >= NO_XDG_OUTPUT_DONE_SINCE_VERSION);
|
||||
|
||||
update_scale (GDK_MONITOR (monitor)->display);
|
||||
}
|
||||
|
||||
+165
-101
@@ -150,9 +150,20 @@ struct _GdkWaylandSurface
|
||||
} pending_move_to_rect;
|
||||
|
||||
struct {
|
||||
int width;
|
||||
int height;
|
||||
GdkSurfaceState state;
|
||||
struct {
|
||||
int width;
|
||||
int height;
|
||||
GdkSurfaceState state;
|
||||
} toplevel;
|
||||
|
||||
struct {
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
} popup;
|
||||
|
||||
uint32_t serial;
|
||||
} pending;
|
||||
|
||||
struct {
|
||||
@@ -170,10 +181,12 @@ struct _GdkWaylandSurfaceClass
|
||||
GdkSurfaceClass parent_class;
|
||||
};
|
||||
|
||||
static void gdk_wayland_surface_maybe_configure (GdkSurface *surface,
|
||||
int width,
|
||||
int height,
|
||||
int scale);
|
||||
static void gdk_wayland_surface_maybe_resize (GdkSurface *surface,
|
||||
int width,
|
||||
int height,
|
||||
int scale);
|
||||
|
||||
static void gdk_wayland_surface_configure (GdkSurface *surface);
|
||||
|
||||
static void maybe_set_gtk_surface_dbus_properties (GdkSurface *surface);
|
||||
static void maybe_set_gtk_surface_modal (GdkSurface *surface);
|
||||
@@ -184,6 +197,12 @@ static void gdk_wayland_surface_sync_opaque_region (GdkSurface *surface);
|
||||
|
||||
static void unset_transient_for_exported (GdkSurface *surface);
|
||||
|
||||
static void gdk_wayland_surface_move_resize (GdkSurface *surface,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
|
||||
static void calculate_moved_to_rect_result (GdkSurface *surface,
|
||||
int x,
|
||||
int y,
|
||||
@@ -349,7 +368,7 @@ frame_callback (void *data,
|
||||
return;
|
||||
|
||||
impl->awaiting_frame = FALSE;
|
||||
_gdk_frame_clock_thaw (clock);
|
||||
gdk_surface_thaw_updates (surface);
|
||||
|
||||
timings = gdk_frame_clock_get_timings (clock, impl->pending_frame_counter);
|
||||
impl->pending_frame_counter = 0;
|
||||
@@ -465,8 +484,9 @@ on_frame_clock_after_paint (GdkFrameClock *clock,
|
||||
g_signal_emit (impl, signals[COMMITTED], 0);
|
||||
}
|
||||
|
||||
if (impl->awaiting_frame)
|
||||
_gdk_frame_clock_freeze (clock);
|
||||
if (impl->awaiting_frame &&
|
||||
impl->pending_frame_counter == gdk_frame_clock_get_frame_counter (clock))
|
||||
gdk_surface_freeze_updates (surface);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -491,7 +511,9 @@ gdk_wayland_surface_update_scale (GdkSurface *surface)
|
||||
}
|
||||
|
||||
/* Notify app that scale changed */
|
||||
gdk_wayland_surface_maybe_configure (surface, surface->width, surface->height, scale);
|
||||
gdk_wayland_surface_maybe_resize (surface,
|
||||
surface->width, surface->height,
|
||||
scale);
|
||||
}
|
||||
|
||||
static void gdk_wayland_surface_create_surface (GdkSurface *surface);
|
||||
@@ -648,10 +670,10 @@ gdk_wayland_surface_finalize (GObject *object)
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_configure (GdkSurface *surface,
|
||||
int width,
|
||||
int height,
|
||||
int scale)
|
||||
gdk_wayland_surface_resize (GdkSurface *surface,
|
||||
int width,
|
||||
int height,
|
||||
int scale)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkEvent *event;
|
||||
@@ -701,10 +723,10 @@ static void gdk_wayland_surface_show (GdkSurface *surface,
|
||||
static void gdk_wayland_surface_hide (GdkSurface *surface);
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_maybe_configure (GdkSurface *surface,
|
||||
int width,
|
||||
int height,
|
||||
int scale)
|
||||
gdk_wayland_surface_maybe_resize (GdkSurface *surface,
|
||||
int width,
|
||||
int height,
|
||||
int scale)
|
||||
{
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||
gboolean is_xdg_popup;
|
||||
@@ -727,7 +749,7 @@ gdk_wayland_surface_maybe_configure (GdkSurface *surface,
|
||||
if (is_xdg_popup && is_visible && !impl->initial_configure_received)
|
||||
gdk_wayland_surface_hide (surface);
|
||||
|
||||
gdk_wayland_surface_configure (surface, width, height, scale);
|
||||
gdk_wayland_surface_resize (surface, width, height, scale);
|
||||
|
||||
if (is_xdg_popup && is_visible && !impl->initial_configure_received)
|
||||
gdk_wayland_surface_show (surface, FALSE);
|
||||
@@ -1038,44 +1060,27 @@ gdk_wayland_surface_create_surface (GdkSurface *surface)
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_handle_configure (GdkSurface *surface,
|
||||
uint32_t serial)
|
||||
gdk_wayland_surface_configure_toplevel (GdkSurface *surface)
|
||||
{
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||
GdkWaylandDisplay *display_wayland =
|
||||
GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
|
||||
GdkSurfaceState new_state;
|
||||
int width = impl->pending.width;
|
||||
int height = impl->pending.height;
|
||||
int width, height;
|
||||
gboolean fixed_size;
|
||||
gboolean saved_size;
|
||||
|
||||
if (!impl->initial_configure_received)
|
||||
{
|
||||
gdk_surface_thaw_updates (surface);
|
||||
impl->initial_configure_received = TRUE;
|
||||
}
|
||||
|
||||
if (impl->display_server.xdg_popup)
|
||||
{
|
||||
xdg_surface_ack_configure (impl->display_server.xdg_surface, serial);
|
||||
return;
|
||||
}
|
||||
else if (impl->display_server.zxdg_popup_v6)
|
||||
{
|
||||
zxdg_surface_v6_ack_configure (impl->display_server.zxdg_surface_v6,
|
||||
serial);
|
||||
return;
|
||||
}
|
||||
|
||||
new_state = impl->pending.state;
|
||||
impl->pending.state = 0;
|
||||
new_state = impl->pending.toplevel.state;
|
||||
impl->pending.toplevel.state = 0;
|
||||
|
||||
fixed_size =
|
||||
new_state & (GDK_SURFACE_STATE_MAXIMIZED |
|
||||
GDK_SURFACE_STATE_FULLSCREEN |
|
||||
GDK_SURFACE_STATE_TILED);
|
||||
|
||||
width = impl->pending.toplevel.width;
|
||||
height = impl->pending.toplevel.height;
|
||||
|
||||
saved_size = (width == 0 && height == 0);
|
||||
/* According to xdg_shell, an xdg_surface.configure with size 0x0
|
||||
* should be interpreted as that it is up to the client to set a
|
||||
@@ -1112,7 +1117,7 @@ gdk_wayland_surface_handle_configure (GdkSurface *surface,
|
||||
_gdk_wayland_surface_save_size (surface);
|
||||
}
|
||||
|
||||
gdk_wayland_surface_configure (surface, width, height, impl->scale);
|
||||
gdk_wayland_surface_resize (surface, width, height, impl->scale);
|
||||
}
|
||||
|
||||
GDK_DISPLAY_NOTE (gdk_surface_get_display (surface), EVENTS,
|
||||
@@ -1128,11 +1133,12 @@ gdk_wayland_surface_handle_configure (GdkSurface *surface,
|
||||
switch (display_wayland->shell_variant)
|
||||
{
|
||||
case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
|
||||
xdg_surface_ack_configure (impl->display_server.xdg_surface, serial);
|
||||
xdg_surface_ack_configure (impl->display_server.xdg_surface,
|
||||
impl->pending.serial);
|
||||
break;
|
||||
case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
|
||||
zxdg_surface_v6_ack_configure (impl->display_server.zxdg_surface_v6,
|
||||
serial);
|
||||
impl->pending.serial);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
@@ -1143,6 +1149,87 @@ gdk_wayland_surface_handle_configure (GdkSurface *surface,
|
||||
gdk_wayland_surface_update_dialogs (surface);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_configure_popup (GdkSurface *surface)
|
||||
{
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||
int x, y, width, height;
|
||||
GdkRectangle flipped_rect;
|
||||
GdkRectangle final_rect;
|
||||
gboolean flipped_x;
|
||||
gboolean flipped_y;
|
||||
|
||||
g_return_if_fail (impl->transient_for);
|
||||
|
||||
if (impl->display_server.xdg_popup)
|
||||
{
|
||||
xdg_surface_ack_configure (impl->display_server.xdg_surface,
|
||||
impl->pending.serial);
|
||||
}
|
||||
else if (impl->display_server.zxdg_popup_v6)
|
||||
{
|
||||
zxdg_surface_v6_ack_configure (impl->display_server.zxdg_surface_v6,
|
||||
impl->pending.serial);
|
||||
}
|
||||
|
||||
if (impl->position_method != POSITION_METHOD_MOVE_TO_RECT)
|
||||
return;
|
||||
|
||||
x = impl->pending.popup.x;
|
||||
y = impl->pending.popup.y;
|
||||
width = impl->pending.popup.width;
|
||||
height = impl->pending.popup.height;
|
||||
|
||||
gdk_wayland_surface_resize (surface, width, height, impl->scale);
|
||||
|
||||
calculate_moved_to_rect_result (surface,
|
||||
x, y,
|
||||
width, height,
|
||||
&flipped_rect,
|
||||
&final_rect,
|
||||
&flipped_x,
|
||||
&flipped_y);
|
||||
|
||||
impl->position_method = POSITION_METHOD_MOVE_TO_RECT;
|
||||
|
||||
g_signal_emit_by_name (surface,
|
||||
"moved-to-rect",
|
||||
&flipped_rect,
|
||||
&final_rect,
|
||||
flipped_x,
|
||||
flipped_y);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_configure (GdkSurface *surface)
|
||||
{
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||
|
||||
if (!impl->initial_configure_received)
|
||||
{
|
||||
gdk_surface_thaw_updates (surface);
|
||||
impl->initial_configure_received = TRUE;
|
||||
}
|
||||
|
||||
if (is_realized_popup (surface))
|
||||
gdk_wayland_surface_configure_popup (surface);
|
||||
else if (is_realized_toplevel (surface))
|
||||
gdk_wayland_surface_configure_toplevel (surface);
|
||||
else
|
||||
g_warn_if_reached ();
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_handle_configure (GdkSurface *surface,
|
||||
uint32_t serial)
|
||||
{
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||
|
||||
impl->pending.serial = serial;
|
||||
|
||||
gdk_wayland_surface_configure (surface);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_handle_configure_toplevel (GdkSurface *surface,
|
||||
int32_t width,
|
||||
@@ -1151,9 +1238,9 @@ gdk_wayland_surface_handle_configure_toplevel (GdkSurface *surface,
|
||||
{
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||
|
||||
impl->pending.state |= state;
|
||||
impl->pending.width = width;
|
||||
impl->pending.height = height;
|
||||
impl->pending.toplevel.state |= state;
|
||||
impl->pending.toplevel.width = width;
|
||||
impl->pending.toplevel.height = height;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1432,30 +1519,11 @@ gdk_wayland_surface_handle_configure_popup (GdkSurface *surface,
|
||||
int32_t height)
|
||||
{
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||
GdkRectangle flipped_rect;
|
||||
GdkRectangle final_rect;
|
||||
gboolean flipped_x;
|
||||
gboolean flipped_y;
|
||||
|
||||
g_return_if_fail (impl->transient_for);
|
||||
|
||||
if (impl->position_method != POSITION_METHOD_MOVE_TO_RECT)
|
||||
return;
|
||||
|
||||
calculate_moved_to_rect_result (surface, x, y, width, height,
|
||||
&flipped_rect,
|
||||
&final_rect,
|
||||
&flipped_x,
|
||||
&flipped_y);
|
||||
|
||||
impl->position_method = POSITION_METHOD_MOVE_TO_RECT;
|
||||
|
||||
g_signal_emit_by_name (surface,
|
||||
"moved-to-rect",
|
||||
&flipped_rect,
|
||||
&final_rect,
|
||||
flipped_x,
|
||||
flipped_y);
|
||||
impl->pending.popup.x = x;
|
||||
impl->pending.popup.y = y;
|
||||
impl->pending.popup.width = width;
|
||||
impl->pending.popup.height = height;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1901,9 +1969,9 @@ calculate_moved_to_rect_result (GdkSurface *surface,
|
||||
surface_width = width + surface->shadow_left + surface->shadow_right;
|
||||
surface_height = height + surface->shadow_top + surface->shadow_bottom;
|
||||
|
||||
gdk_surface_move_resize (surface,
|
||||
surface_x, surface_y,
|
||||
surface_width, surface_height);
|
||||
gdk_wayland_surface_move_resize (surface,
|
||||
surface_x, surface_y,
|
||||
surface_width, surface_height);
|
||||
|
||||
calculate_popup_rect (surface,
|
||||
impl->pending_move_to_rect.rect_anchor,
|
||||
@@ -2577,12 +2645,8 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
|
||||
|
||||
if (impl->awaiting_frame)
|
||||
{
|
||||
GdkFrameClock *frame_clock;
|
||||
|
||||
impl->awaiting_frame = FALSE;
|
||||
frame_clock = gdk_surface_get_frame_clock (surface);
|
||||
if (frame_clock)
|
||||
_gdk_frame_clock_thaw (frame_clock);
|
||||
gdk_surface_thaw_updates (surface);
|
||||
}
|
||||
|
||||
if (impl->display_server.gtk_surface)
|
||||
@@ -2650,7 +2714,6 @@ gdk_wayland_surface_restack_toplevel (GdkSurface *surface,
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_move_resize (GdkSurface *surface,
|
||||
gboolean with_move,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
@@ -2658,22 +2721,21 @@ gdk_wayland_surface_move_resize (GdkSurface *surface,
|
||||
{
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||
|
||||
if (with_move)
|
||||
{
|
||||
/* Each toplevel has in its own "root" coordinate system */
|
||||
if (GDK_SURFACE_TYPE (surface) != GDK_SURFACE_TOPLEVEL)
|
||||
{
|
||||
surface->x = x;
|
||||
surface->y = y;
|
||||
impl->position_method = POSITION_METHOD_MOVE_RESIZE;
|
||||
}
|
||||
}
|
||||
surface->x = x;
|
||||
surface->y = y;
|
||||
gdk_wayland_surface_maybe_resize (surface, width, height, impl->scale);
|
||||
}
|
||||
|
||||
/* If this function is called with width and height = -1 then that means
|
||||
* just move the surface - don't update its size
|
||||
*/
|
||||
if (width > 0 && height > 0)
|
||||
gdk_wayland_surface_maybe_configure (surface, width, height, impl->scale);
|
||||
static void
|
||||
gdk_wayland_surface_toplevel_resize (GdkSurface *surface,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||
|
||||
gdk_wayland_surface_maybe_resize (surface,
|
||||
width, height,
|
||||
impl->scale);
|
||||
}
|
||||
|
||||
/* Avoid zero width/height as this is a protocol error */
|
||||
@@ -2927,7 +2989,7 @@ gtk_surface_configure (void *data,
|
||||
}
|
||||
}
|
||||
|
||||
impl->pending.state |= new_state;
|
||||
impl->pending.toplevel.state |= new_state;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2964,7 +3026,7 @@ gtk_surface_configure_edges (void *data,
|
||||
}
|
||||
}
|
||||
|
||||
impl->pending.state |= new_state;
|
||||
impl->pending.toplevel.state |= new_state;
|
||||
}
|
||||
|
||||
static const struct gtk_surface1_listener gtk_surface_listener = {
|
||||
@@ -3666,7 +3728,9 @@ gdk_wayland_surface_set_shadow_width (GdkSurface *surface,
|
||||
(impl->margin_left + impl->margin_right) + (left + right);
|
||||
new_height = surface->height -
|
||||
(impl->margin_top + impl->margin_bottom) + (top + bottom);
|
||||
gdk_wayland_surface_maybe_configure (surface, new_width, new_height, impl->scale);
|
||||
gdk_wayland_surface_maybe_resize (surface,
|
||||
new_width, new_height,
|
||||
impl->scale);
|
||||
|
||||
impl->margin_left = left;
|
||||
impl->margin_right = right;
|
||||
@@ -3749,7 +3813,7 @@ gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass)
|
||||
impl_class->raise = gdk_wayland_surface_raise;
|
||||
impl_class->lower = gdk_wayland_surface_lower;
|
||||
impl_class->restack_toplevel = gdk_wayland_surface_restack_toplevel;
|
||||
impl_class->move_resize = gdk_wayland_surface_move_resize;
|
||||
impl_class->toplevel_resize = gdk_wayland_surface_toplevel_resize;
|
||||
impl_class->move_to_rect = gdk_wayland_surface_move_to_rect;
|
||||
impl_class->get_geometry = gdk_wayland_surface_get_geometry;
|
||||
impl_class->get_root_coords = gdk_wayland_surface_get_root_coords;
|
||||
|
||||
@@ -736,9 +736,9 @@ move_drag_surface (GdkDrag *drag,
|
||||
g_assert (_win32_main_thread == NULL ||
|
||||
_win32_main_thread == g_thread_self ());
|
||||
|
||||
gdk_surface_move (drag_win32->drag_surface,
|
||||
x_root - drag_win32->hot_x,
|
||||
y_root - drag_win32->hot_y);
|
||||
gdk_win32_surface_move (drag_win32->drag_surface,
|
||||
x_root - drag_win32->hot_x,
|
||||
y_root - drag_win32->hot_y);
|
||||
gdk_surface_raise (drag_win32->drag_surface);
|
||||
}
|
||||
|
||||
@@ -2090,6 +2090,7 @@ gdk_drag_anim_timeout (gpointer data)
|
||||
gint64 current_time;
|
||||
double f;
|
||||
double t;
|
||||
gint x, y;
|
||||
|
||||
if (!frame_clock)
|
||||
return G_SOURCE_REMOVE;
|
||||
@@ -2104,9 +2105,13 @@ gdk_drag_anim_timeout (gpointer data)
|
||||
t = ease_out_cubic (f);
|
||||
|
||||
gdk_surface_show (drag->drag_surface);
|
||||
gdk_surface_move (drag->drag_surface,
|
||||
drag->util_data.last_x + (drag->start_x - drag->util_data.last_x) * t - drag->hot_x,
|
||||
drag->util_data.last_y + (drag->start_y - drag->util_data.last_y) * t - drag->hot_y);
|
||||
x = (drag->util_data.last_x +
|
||||
(drag->start_x - drag->util_data.last_x) * t -
|
||||
drag->hot_x);
|
||||
y = (drag->util_data.last_y +
|
||||
(drag->start_y - drag->util_data.last_y) * t -
|
||||
drag->hot_y);
|
||||
gdk_win32_surface_move (drag->drag_surface, x, y);
|
||||
gdk_surface_set_opacity (drag->drag_surface, 1.0 - f);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
||||
@@ -1588,7 +1588,9 @@ handle_dpi_changed (GdkSurface *window,
|
||||
_gdk_win32_adjust_client_rect (window, rect);
|
||||
|
||||
if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
|
||||
gdk_surface_move_resize (window, window->x, window->y, window->width, window->height);
|
||||
gdk_win32_surface_move_resize (window,
|
||||
window->x, window->y,
|
||||
window->width, window->height);
|
||||
else
|
||||
gdk_surface_resize (window, window->width, window->height);
|
||||
}
|
||||
|
||||
+102
-23
@@ -1098,8 +1098,8 @@ gdk_win32_surface_withdraw (GdkSurface *window)
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_surface_move (GdkSurface *window,
|
||||
gint x, gint y)
|
||||
gdk_win32_surface_do_move (GdkSurface *window,
|
||||
gint x, gint y)
|
||||
{
|
||||
RECT outer_rect;
|
||||
GdkWin32Surface *impl;
|
||||
@@ -1174,11 +1174,11 @@ gdk_win32_surface_resize (GdkSurface *window,
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_surface_move_resize_internal (GdkSurface *window,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
gdk_win32_surface_do_move_resize (GdkSurface *window,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
RECT outer_rect;
|
||||
GdkWin32Surface *impl;
|
||||
@@ -1224,12 +1224,12 @@ gdk_win32_surface_move_resize_internal (GdkSurface *window,
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_surface_move_resize (GdkSurface *window,
|
||||
gboolean with_move,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
gdk_win32_surface_move_resize_internal (GdkSurface *window,
|
||||
gboolean with_move,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
GdkWin32Surface *surface = GDK_WIN32_SURFACE (window);
|
||||
|
||||
@@ -1242,13 +1242,13 @@ gdk_win32_surface_move_resize (GdkSurface *window,
|
||||
|
||||
if (with_move && (width < 0 && height < 0))
|
||||
{
|
||||
gdk_win32_surface_move (window, x, y);
|
||||
gdk_win32_surface_do_move (window, x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (with_move)
|
||||
{
|
||||
gdk_win32_surface_move_resize_internal (window, x, y, width, height);
|
||||
gdk_win32_surface_do_move_resize (window, x, y, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1262,6 +1262,80 @@ gdk_win32_surface_move_resize (GdkSurface *window,
|
||||
_gdk_win32_emit_configure_event (window);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_win32_surface_move_resize (GdkSurface *window,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
gdk_win32_surface_move_resize_internal (window, TRUE, x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_surface_toplevel_resize (GdkSurface *surface,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
gdk_win32_surface_move_resize_internal (surface, FALSE, 0, 0, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_win32_surface_move (GdkSurface *surface,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
gdk_win32_surface_move_resize_internal (surface, TRUE, x, y, -1, -1);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_surface_moved_to_rect (GdkSurface *surface,
|
||||
GdkRectangle final_rect)
|
||||
{
|
||||
GdkSurface *toplevel;
|
||||
int x, y;
|
||||
|
||||
if (surface->surface_type == GDK_SURFACE_POPUP)
|
||||
toplevel = surface->parent;
|
||||
else
|
||||
toplevel = surface->transient_for;
|
||||
|
||||
gdk_surface_get_origin (toplevel, &x, &y);
|
||||
x += final_rect.x;
|
||||
y += final_rect.y;
|
||||
|
||||
if (final_rect.width != surface->width ||
|
||||
final_rect.height != surface->height)
|
||||
{
|
||||
gdk_win32_surface_move_resize (surface,
|
||||
x, y,
|
||||
final_rect.width, final_rect.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdk_win32_surface_move (surface, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_surface_move_to_rect (GdkSurface *surface,
|
||||
const GdkRectangle *rect,
|
||||
GdkGravity rect_anchor,
|
||||
GdkGravity surface_anchor,
|
||||
GdkAnchorHints anchor_hints,
|
||||
gint rect_anchor_dx,
|
||||
gint rect_anchor_dy)
|
||||
{
|
||||
gdk_surface_move_to_rect_helper (surface,
|
||||
rect,
|
||||
rect_anchor,
|
||||
surface_anchor,
|
||||
anchor_hints,
|
||||
rect_anchor_dx,
|
||||
rect_anchor_dy,
|
||||
gdk_win32_surface_moved_to_rect);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_surface_raise (GdkSurface *window)
|
||||
{
|
||||
@@ -2518,8 +2592,8 @@ unsnap (GdkSurface *window,
|
||||
|
||||
GDK_NOTE (MISC, g_print ("Unsnapped window size %d x %d @ %d : %d\n", rect.width, rect.height, rect.x, rect.y));
|
||||
|
||||
gdk_surface_move_resize (window, rect.x, rect.y,
|
||||
rect.width, rect.height);
|
||||
gdk_win32_surface_move_resize (window, rect.x, rect.y,
|
||||
rect.width, rect.height);
|
||||
|
||||
g_clear_pointer (&impl->snap_stash, g_free);
|
||||
g_clear_pointer (&impl->snap_stash_int, g_free);
|
||||
@@ -2624,7 +2698,7 @@ snap_up (GdkSurface *window)
|
||||
width += impl->margins_x;
|
||||
height += impl->margins_y;
|
||||
|
||||
gdk_surface_move_resize (window, x, y, width, height);
|
||||
gdk_win32_surface_move_resize (window, x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2650,7 +2724,9 @@ snap_left (GdkSurface *window,
|
||||
rect.width = rect.width + impl->margins_x;
|
||||
rect.height = rect.height + impl->margins_y;
|
||||
|
||||
gdk_surface_move_resize (window, rect.x, rect.y, rect.width, rect.height);
|
||||
gdk_win32_surface_move_resize (window,
|
||||
rect.x, rect.y,
|
||||
rect.width, rect.height);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2677,7 +2753,9 @@ snap_right (GdkSurface *window,
|
||||
rect.width = rect.width + impl->margins_x;
|
||||
rect.height = rect.height + impl->margins_y;
|
||||
|
||||
gdk_surface_move_resize (window, rect.x, rect.y, rect.width, rect.height);
|
||||
gdk_win32_surface_move_resize (window,
|
||||
rect.x, rect.y,
|
||||
rect.width, rect.height);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -3928,8 +4006,8 @@ setup_drag_move_resize_context (GdkSurface *window,
|
||||
GDK_NOTE (MISC, g_print ("Unsnapped window to %d : %d\n",
|
||||
new_pos.x, new_pos.y));
|
||||
discard_snapinfo (window);
|
||||
gdk_surface_move_resize (window, new_pos.x, new_pos.y,
|
||||
new_pos.width, new_pos.height);
|
||||
gdk_win32_surface_move_resize (window, new_pos.x, new_pos.y,
|
||||
new_pos.width, new_pos.height);
|
||||
}
|
||||
|
||||
|
||||
@@ -5082,7 +5160,8 @@ gdk_win32_surface_class_init (GdkWin32SurfaceClass *klass)
|
||||
impl_class->raise = gdk_win32_surface_raise;
|
||||
impl_class->lower = gdk_win32_surface_lower;
|
||||
impl_class->restack_toplevel = gdk_win32_surface_restack_toplevel;
|
||||
impl_class->move_resize = gdk_win32_surface_move_resize;
|
||||
impl_class->toplevel_resize = gdk_win32_surface_toplevel_resize;
|
||||
impl_class->move_to_rect = gdk_win32_surface_move_to_rect;
|
||||
impl_class->get_geometry = gdk_win32_surface_get_geometry;
|
||||
impl_class->get_device_state = gdk_surface_win32_get_device_state;
|
||||
impl_class->get_root_coords = gdk_win32_surface_get_root_coords;
|
||||
|
||||
@@ -361,6 +361,15 @@ void _gdk_win32_update_layered_window_from_cache (GdkSurface *window,
|
||||
gboolean do_resize,
|
||||
gboolean do_paint);
|
||||
|
||||
void gdk_win32_surface_move (GdkSurface *surface,
|
||||
gint x,
|
||||
gint y);
|
||||
|
||||
void gdk_win32_surface_move_resize (GdkSurface *window,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
|
||||
void
|
||||
gdk_win32_surface_get_queued_window_rect (GdkSurface *surface,
|
||||
|
||||
@@ -289,7 +289,7 @@ gdk_x11_app_launch_context_get_startup_notify_id (GAppLaunchContext *context,
|
||||
files_count = g_list_length (files);
|
||||
if (files_count == 0)
|
||||
{
|
||||
description = g_strdup_printf (_("Starting %s"), g_app_info_get_name (info));
|
||||
description = g_strdup_printf (_("Starting “%s”"), g_app_info_get_name (info));
|
||||
}
|
||||
else if (files_count == 1)
|
||||
{
|
||||
@@ -302,7 +302,7 @@ gdk_x11_app_launch_context_get_startup_notify_id (GAppLaunchContext *context,
|
||||
0, NULL, NULL);
|
||||
|
||||
display_name = get_display_name (files->data, fileinfo);
|
||||
description = g_strdup_printf (_("Opening %s"), display_name);
|
||||
description = g_strdup_printf (_("Opening “%s”"), display_name);
|
||||
g_free (display_name);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -874,7 +874,7 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
|
||||
surface_impl->toplevel->frame_pending)
|
||||
{
|
||||
surface_impl->toplevel->frame_pending = FALSE;
|
||||
_gdk_frame_clock_thaw (gdk_surface_get_frame_clock (event->any.surface));
|
||||
gdk_surface_thaw_updates (event->any.surface);
|
||||
}
|
||||
|
||||
if (toplevel)
|
||||
@@ -1238,7 +1238,7 @@ _gdk_wm_protocols_filter (const XEvent *xevent,
|
||||
if (surface_impl->toplevel->frame_pending)
|
||||
{
|
||||
surface_impl->toplevel->frame_pending = FALSE;
|
||||
_gdk_frame_clock_thaw (clock);
|
||||
gdk_surface_thaw_updates (event->any.surface);
|
||||
}
|
||||
|
||||
gdk_frame_clock_get_refresh_info (clock,
|
||||
|
||||
@@ -1459,9 +1459,9 @@ move_drag_surface (GdkDrag *drag,
|
||||
{
|
||||
GdkX11Drag *drag_x11 = GDK_X11_DRAG (drag);
|
||||
|
||||
gdk_surface_move (drag_x11->drag_surface,
|
||||
x_root - drag_x11->hot_x,
|
||||
y_root - drag_x11->hot_y);
|
||||
gdk_x11_surface_move (drag_x11->drag_surface,
|
||||
x_root - drag_x11->hot_x,
|
||||
y_root - drag_x11->hot_y);
|
||||
gdk_surface_raise (drag_x11->drag_surface);
|
||||
}
|
||||
|
||||
@@ -1841,9 +1841,9 @@ gdk_drag_anim_timeout (gpointer data)
|
||||
t = ease_out_cubic (f);
|
||||
|
||||
gdk_surface_show (drag->drag_surface);
|
||||
gdk_surface_move (drag->drag_surface,
|
||||
drag->last_x + (drag->start_x - drag->last_x) * t,
|
||||
drag->last_y + (drag->start_y - drag->last_y) * t);
|
||||
gdk_x11_surface_move (drag->drag_surface,
|
||||
drag->last_x + (drag->start_x - drag->last_x) * t,
|
||||
drag->last_y + (drag->start_y - drag->last_y) * t);
|
||||
gdk_surface_set_opacity (drag->drag_surface, 1.0 - f);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
||||
@@ -503,6 +503,7 @@ gdk_x11_selection_output_stream_invoke_close (gpointer stream)
|
||||
g_signal_handlers_disconnect_by_func (priv->display,
|
||||
gdk_x11_selection_output_stream_xevent,
|
||||
stream);
|
||||
g_object_unref (stream);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
@@ -512,7 +513,7 @@ gdk_x11_selection_output_stream_close (GOutputStream *stream,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_main_context_invoke (NULL, gdk_x11_selection_output_stream_invoke_close, stream);
|
||||
g_main_context_invoke (NULL, gdk_x11_selection_output_stream_invoke_close, g_object_ref (stream));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -397,7 +397,7 @@ gdk_x11_surface_end_frame (GdkSurface *surface)
|
||||
g_intern_static_string ("_NET_WM_FRAME_DRAWN")))
|
||||
{
|
||||
impl->toplevel->frame_pending = TRUE;
|
||||
_gdk_frame_clock_freeze (gdk_surface_get_frame_clock (surface));
|
||||
gdk_surface_freeze_updates (surface);
|
||||
timings->cookie = impl->toplevel->current_counter_value;
|
||||
}
|
||||
}
|
||||
@@ -1392,6 +1392,71 @@ gdk_x11_surface_move_resize (GdkSurface *surface,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_surface_toplevel_resize (GdkSurface *surface,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
x11_surface_resize (surface, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_x11_surface_move (GdkSurface *surface,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
gdk_x11_surface_move_resize (surface, TRUE, x, y, -1, -1);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_surface_moved_to_rect (GdkSurface *surface,
|
||||
GdkRectangle final_rect)
|
||||
{
|
||||
GdkSurface *toplevel;
|
||||
int x, y;
|
||||
|
||||
if (surface->surface_type == GDK_SURFACE_POPUP)
|
||||
toplevel = surface->parent;
|
||||
else
|
||||
toplevel = surface->transient_for;
|
||||
|
||||
gdk_surface_get_origin (toplevel, &x, &y);
|
||||
x += final_rect.x;
|
||||
y += final_rect.y;
|
||||
|
||||
if (final_rect.width != surface->width ||
|
||||
final_rect.height != surface->height)
|
||||
{
|
||||
gdk_x11_surface_move_resize (surface,
|
||||
TRUE,
|
||||
x, y,
|
||||
final_rect.width, final_rect.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdk_x11_surface_move (surface, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_surface_move_to_rect (GdkSurface *surface,
|
||||
const GdkRectangle *rect,
|
||||
GdkGravity rect_anchor,
|
||||
GdkGravity surface_anchor,
|
||||
GdkAnchorHints anchor_hints,
|
||||
gint rect_anchor_dx,
|
||||
gint rect_anchor_dy)
|
||||
{
|
||||
gdk_surface_move_to_rect_helper (surface,
|
||||
rect,
|
||||
rect_anchor,
|
||||
surface_anchor,
|
||||
anchor_hints,
|
||||
rect_anchor_dx,
|
||||
rect_anchor_dy,
|
||||
gdk_x11_surface_moved_to_rect);
|
||||
}
|
||||
|
||||
static void gdk_x11_surface_restack_toplevel (GdkSurface *surface,
|
||||
GdkSurface *sibling,
|
||||
gboolean above);
|
||||
@@ -3245,7 +3310,7 @@ gdk_x11_surface_fullscreen_on_monitor (GdkSurface *surface,
|
||||
return;
|
||||
|
||||
gdk_monitor_get_geometry (monitor, &geom);
|
||||
gdk_surface_move (surface, geom.x, geom.y);
|
||||
gdk_x11_surface_move (surface, geom.x, geom.y);
|
||||
|
||||
gdk_surface_set_fullscreen_mode (surface, GDK_FULLSCREEN_ON_CURRENT_MONITOR);
|
||||
gdk_x11_surface_fullscreen (surface);
|
||||
@@ -3887,7 +3952,8 @@ update_pos (MoveResizeData *mv_resize,
|
||||
w, h, &w, &h);
|
||||
}
|
||||
|
||||
gdk_surface_move_resize (mv_resize->moveresize_surface, x, y, w, h);
|
||||
gdk_x11_surface_move_resize (mv_resize->moveresize_surface, TRUE,
|
||||
x, y, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3896,7 +3962,7 @@ update_pos (MoveResizeData *mv_resize,
|
||||
x = mv_resize->moveresize_orig_x + dx;
|
||||
y = mv_resize->moveresize_orig_y + dy;
|
||||
|
||||
gdk_surface_move (mv_resize->moveresize_surface, x, y);
|
||||
gdk_x11_surface_move (mv_resize->moveresize_surface, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4589,7 +4655,8 @@ gdk_x11_surface_class_init (GdkX11SurfaceClass *klass)
|
||||
impl_class->raise = gdk_x11_surface_raise;
|
||||
impl_class->lower = gdk_x11_surface_lower;
|
||||
impl_class->restack_toplevel = gdk_x11_surface_restack_toplevel;
|
||||
impl_class->move_resize = gdk_x11_surface_move_resize;
|
||||
impl_class->toplevel_resize = gdk_x11_surface_toplevel_resize;
|
||||
impl_class->move_to_rect = gdk_x11_surface_move_to_rect;
|
||||
impl_class->get_geometry = gdk_x11_surface_get_geometry;
|
||||
impl_class->get_root_coords = gdk_x11_surface_get_root_coords;
|
||||
impl_class->get_device_state = gdk_x11_surface_get_device_state;
|
||||
|
||||
@@ -183,6 +183,10 @@ void _gdk_x11_surface_set_surface_scale (GdkSurface *window,
|
||||
|
||||
void gdk_x11_surface_pre_damage (GdkSurface *surface);
|
||||
|
||||
void gdk_x11_surface_move (GdkSurface *surface,
|
||||
gint x,
|
||||
gint y);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_X11_SURFACE__ */
|
||||
|
||||
+68
-78
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
#define MAX_FRAME_AGE (5 * 60)
|
||||
#define MAX_GLYPH_SIZE 128 /* Will get its own texture if bigger */
|
||||
|
||||
static guint glyph_cache_hash (gconstpointer v);
|
||||
static gboolean glyph_cache_equal (gconstpointer v1,
|
||||
@@ -82,6 +83,8 @@ glyph_cache_equal (gconstpointer v1, gconstpointer v2)
|
||||
|
||||
return key1->font == key2->font &&
|
||||
key1->glyph == key2->glyph &&
|
||||
key1->xshift == key2->xshift &&
|
||||
key1->yshift == key2->yshift &&
|
||||
key1->scale == key2->scale;
|
||||
}
|
||||
|
||||
@@ -90,7 +93,11 @@ glyph_cache_hash (gconstpointer v)
|
||||
{
|
||||
const GlyphCacheKey *key = v;
|
||||
|
||||
return GPOINTER_TO_UINT (key->font) ^ key->glyph ^ key->scale;
|
||||
return GPOINTER_TO_UINT (key->font) ^
|
||||
key->glyph ^
|
||||
(key->xshift << 24) ^
|
||||
(key->yshift << 26) ^
|
||||
key->scale;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -193,10 +200,10 @@ upload_glyph (GlyphCacheKey *key,
|
||||
if (render_glyph (key, value, &r))
|
||||
{
|
||||
glBindTexture (GL_TEXTURE_2D, value->texture_id);
|
||||
glTextureSubImage2D (value->texture_id, 0,
|
||||
r.x, r.y, r.width, r.height,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
r.data);
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
r.x, r.y, r.width, r.height,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
r.data);
|
||||
g_free (r.data);
|
||||
}
|
||||
|
||||
@@ -206,86 +213,70 @@ upload_glyph (GlyphCacheKey *key,
|
||||
static void
|
||||
add_to_cache (GskGLGlyphCache *self,
|
||||
GlyphCacheKey *key,
|
||||
GskGLDriver *driver,
|
||||
GskGLCachedGlyph *value)
|
||||
{
|
||||
const int width = value->draw_width * key->scale / 1024;
|
||||
const int height = value->draw_height * key->scale / 1024;
|
||||
GskGLTextureAtlas *atlas = NULL;
|
||||
int packed_x = 0;
|
||||
int packed_y = 0;
|
||||
|
||||
gsk_gl_texture_atlases_pack (self->atlases, width + 2, height + 2, &atlas, &packed_x, &packed_y);
|
||||
if (width < MAX_GLYPH_SIZE && height < MAX_GLYPH_SIZE)
|
||||
{
|
||||
GskGLTextureAtlas *atlas = NULL;
|
||||
int packed_x = 0;
|
||||
int packed_y = 0;
|
||||
|
||||
value->tx = (float)(packed_x + 1) / atlas->width;
|
||||
value->ty = (float)(packed_y + 1) / atlas->height;
|
||||
value->tw = (float)width / atlas->width;
|
||||
value->th = (float)height / atlas->height;
|
||||
value->used = TRUE;
|
||||
gsk_gl_texture_atlases_pack (self->atlases, width + 2, height + 2, &atlas, &packed_x, &packed_y);
|
||||
|
||||
value->atlas = atlas;
|
||||
value->texture_id = atlas->texture_id;
|
||||
value->tx = (float)(packed_x + 1) / atlas->width;
|
||||
value->ty = (float)(packed_y + 1) / atlas->height;
|
||||
value->tw = (float)width / atlas->width;
|
||||
value->th = (float)height / atlas->height;
|
||||
value->used = TRUE;
|
||||
|
||||
value->atlas = atlas;
|
||||
value->texture_id = atlas->texture_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
value->atlas = NULL;
|
||||
value->texture_id = gsk_gl_driver_create_texture (driver, width, height);
|
||||
|
||||
gsk_gl_driver_bind_source_texture (driver, value->texture_id);
|
||||
gsk_gl_driver_init_texture_empty (driver, value->texture_id, GL_LINEAR, GL_LINEAR);
|
||||
|
||||
value->tx = 0.0f;
|
||||
value->ty = 0.0f;
|
||||
value->tw = 1.0f;
|
||||
value->th = 1.0f;
|
||||
}
|
||||
|
||||
upload_glyph (key, value);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_glyph_cache_get_texture (GskGLDriver *driver,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph,
|
||||
float scale,
|
||||
GskGLCachedGlyph *value)
|
||||
{
|
||||
PangoRectangle ink_rect;
|
||||
GlyphCacheKey key;
|
||||
int width, height;
|
||||
guint texture_id;
|
||||
|
||||
pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL);
|
||||
pango_extents_to_pixels (&ink_rect, NULL);
|
||||
|
||||
key.font = font;
|
||||
key.glyph = glyph;
|
||||
key.scale = (guint)(scale * 1024);
|
||||
|
||||
value->atlas = NULL;
|
||||
value->timestamp = 0;
|
||||
|
||||
value->draw_x = ink_rect.x;
|
||||
value->draw_y = ink_rect.y;
|
||||
value->draw_width = ink_rect.width;
|
||||
value->draw_height = ink_rect.height;
|
||||
|
||||
value->tx = 0.0f;
|
||||
value->ty = 0.0f;
|
||||
value->tw = 1.0f;
|
||||
value->th = 1.0f;
|
||||
|
||||
width = value->draw_width * key.scale / 1024;
|
||||
height = value->draw_height * key.scale / 1024;
|
||||
|
||||
texture_id = gsk_gl_driver_create_texture (driver, width, height);
|
||||
gsk_gl_driver_bind_source_texture (driver, texture_id);
|
||||
gsk_gl_driver_init_texture_empty (driver, texture_id, GL_NEAREST, GL_NEAREST);
|
||||
|
||||
value->texture_id = texture_id;
|
||||
|
||||
upload_glyph (&key, value);
|
||||
}
|
||||
#define PHASE(x) ((int)(floor (4 * (x + 0.125)) - 4 * floor (x + 0.125)))
|
||||
|
||||
gboolean
|
||||
gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph,
|
||||
float x,
|
||||
float y,
|
||||
float scale,
|
||||
GskGLDriver *driver,
|
||||
GskGLCachedGlyph *cached_glyph_out)
|
||||
{
|
||||
GskGLCachedGlyph *value;
|
||||
guint xshift = PHASE (x);
|
||||
guint yshift = PHASE (y);
|
||||
const guint key_scale = (guint)(scale * 1024);
|
||||
|
||||
value = g_hash_table_lookup (cache->hash_table,
|
||||
&(GlyphCacheKey) {
|
||||
.font = font,
|
||||
.glyph = glyph,
|
||||
.scale = (guint)(scale * 1024)
|
||||
.xshift = xshift,
|
||||
.yshift = yshift,
|
||||
.scale = key_scale
|
||||
});
|
||||
|
||||
if (value)
|
||||
@@ -310,10 +301,15 @@ gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache,
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
GlyphCacheKey *key;
|
||||
PangoRectangle ink_rect;
|
||||
|
||||
pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL);
|
||||
pango_extents_to_pixels (&ink_rect, NULL);
|
||||
if (xshift != 0)
|
||||
ink_rect.width += 1;
|
||||
if (yshift != 0)
|
||||
ink_rect.height += 1;
|
||||
|
||||
value = g_new0 (GskGLCachedGlyph, 1);
|
||||
|
||||
@@ -324,27 +320,21 @@ gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache,
|
||||
value->timestamp = cache->timestamp;
|
||||
value->atlas = NULL; /* For now */
|
||||
|
||||
if (ink_rect.width < 128 && ink_rect.height < 128)
|
||||
{
|
||||
GlyphCacheKey *key;
|
||||
key = g_new0 (GlyphCacheKey, 1);
|
||||
|
||||
key = g_new0 (GlyphCacheKey, 1);
|
||||
key->font = g_object_ref (font);
|
||||
key->glyph = glyph;
|
||||
key->xshift = xshift;
|
||||
key->yshift = yshift;
|
||||
key->scale = key_scale;
|
||||
|
||||
key->font = g_object_ref (font);
|
||||
key->glyph = glyph;
|
||||
key->scale = (guint)(scale * 1024);
|
||||
if (key->scale > 0 &&
|
||||
value->draw_width * key->scale / 1024 > 0 &&
|
||||
value->draw_height * key->scale / 1024 > 0)
|
||||
add_to_cache (cache, key, driver, value);
|
||||
|
||||
if (ink_rect.width > 0 && ink_rect.height > 0 && key->scale > 0)
|
||||
add_to_cache (cache, key, value);
|
||||
|
||||
*cached_glyph_out = *value;
|
||||
g_hash_table_insert (cache->hash_table, key, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
*cached_glyph_out = *value;
|
||||
glyph_cache_value_free (value);
|
||||
}
|
||||
*cached_glyph_out = *value;
|
||||
g_hash_table_insert (cache->hash_table, key, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -22,6 +22,8 @@ typedef struct
|
||||
{
|
||||
PangoFont *font;
|
||||
PangoGlyph glyph;
|
||||
guint xshift;
|
||||
guint yshift;
|
||||
guint scale; /* times 1024 */
|
||||
} GlyphCacheKey;
|
||||
|
||||
@@ -55,12 +57,10 @@ void gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache
|
||||
gboolean gsk_gl_glyph_cache_lookup (GskGLGlyphCache *self,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph,
|
||||
float x,
|
||||
float y,
|
||||
float scale,
|
||||
GskGLCachedGlyph *cached_glyph_out);
|
||||
void gsk_gl_glyph_cache_get_texture (GskGLDriver *driver,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph,
|
||||
float scale,
|
||||
GskGLCachedGlyph *glyph_out);
|
||||
GskGLDriver *driver,
|
||||
GskGLCachedGlyph *cached_glyph_out);
|
||||
|
||||
#endif
|
||||
|
||||
+20
-5
@@ -13,11 +13,13 @@ typedef struct
|
||||
GskGLTextureAtlas *atlas;
|
||||
int frame_age; /* Number of frames this icon is unused */
|
||||
guint used: 1;
|
||||
GdkTexture *source_texture;
|
||||
} IconData;
|
||||
|
||||
static void
|
||||
icon_data_free (gpointer p)
|
||||
{
|
||||
g_object_unref (((IconData *)p)->source_texture);
|
||||
g_free (p);
|
||||
}
|
||||
|
||||
@@ -136,7 +138,7 @@ upload_region_or_else (GskGLIconCache *self,
|
||||
GskImageRegion *region)
|
||||
{
|
||||
glBindTexture (GL_TEXTURE_2D, texture_id);
|
||||
glTextureSubImage2D (texture_id, 0, region->x, region->y, region->width, region->height,
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0, region->x, region->y, region->width, region->height,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, region->data);
|
||||
}
|
||||
|
||||
@@ -182,6 +184,7 @@ gsk_gl_icon_cache_lookup_or_add (GskGLIconCache *self,
|
||||
icon_data->atlas = atlas;
|
||||
icon_data->frame_age = 0;
|
||||
icon_data->used = TRUE;
|
||||
icon_data->source_texture = g_object_ref (texture);
|
||||
graphene_rect_init (&icon_data->texture_rect,
|
||||
(float)(packed_x + 1) / atlas->width,
|
||||
(float)(packed_y + 1) / atlas->height,
|
||||
@@ -213,10 +216,22 @@ gsk_gl_icon_cache_lookup_or_add (GskGLIconCache *self,
|
||||
cairo_surface_destroy (padded_surface);
|
||||
|
||||
#if 0
|
||||
/* Some obvious debugging */
|
||||
static int k;
|
||||
gsk_gl_image_write_to_png (&atlas->image, self->gl_driver,
|
||||
g_strdup_printf ("icon%d.png", k ++));
|
||||
{
|
||||
static int k;
|
||||
const int stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, atlas->width);
|
||||
guchar *data = g_malloc (atlas->height * stride);
|
||||
cairo_surface_t *s;
|
||||
char *filename = g_strdup_printf ("atlas_%u_%d.png", atlas->texture_id, k++);
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, atlas->texture_id);
|
||||
glGetTexImage (GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
|
||||
s = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32, atlas->width, atlas->height, stride);
|
||||
cairo_surface_write_to_png (s, filename);
|
||||
|
||||
cairo_surface_destroy (s);
|
||||
g_free (data);
|
||||
g_free (filename);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
+187
-50
@@ -340,6 +340,7 @@ struct _GskGLRenderer
|
||||
Program border_program;
|
||||
Program cross_fade_program;
|
||||
Program blend_program;
|
||||
Program repeat_program;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -592,29 +593,24 @@ render_text_node (GskGLRenderer *self,
|
||||
if (gi->glyph == PANGO_GLYPH_EMPTY)
|
||||
continue;
|
||||
|
||||
cx = (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
|
||||
cy = (double)(gi->geometry.y_offset) / PANGO_SCALE;
|
||||
|
||||
gsk_gl_glyph_cache_lookup (self->glyph_cache,
|
||||
(PangoFont *)font,
|
||||
gi->glyph,
|
||||
x + cx,
|
||||
+ y + cy,
|
||||
text_scale,
|
||||
self->gl_driver,
|
||||
&glyph);
|
||||
|
||||
/* e.g. whitespace */
|
||||
if (glyph.draw_width <= 0 || glyph.draw_height <= 0)
|
||||
goto next;
|
||||
|
||||
/* big glyphs are not cached */
|
||||
if (!glyph.texture_id)
|
||||
{
|
||||
gsk_gl_glyph_cache_get_texture (self->gl_driver,
|
||||
(PangoFont *)font,
|
||||
gi->glyph,
|
||||
text_scale,
|
||||
&glyph);
|
||||
g_assert (glyph.texture_id != 0);
|
||||
}
|
||||
|
||||
cx = (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
|
||||
cy = (double)(gi->geometry.y_offset) / PANGO_SCALE;
|
||||
if (glyph.texture_id == 0)
|
||||
goto next;
|
||||
|
||||
ops_set_texture (builder, glyph.texture_id);
|
||||
|
||||
@@ -623,8 +619,8 @@ render_text_node (GskGLRenderer *self,
|
||||
tx2 = tx + glyph.tw;
|
||||
ty2 = ty + glyph.th;
|
||||
|
||||
glyph_x = x + cx + glyph.draw_x;
|
||||
glyph_y = y + cy + glyph.draw_y;
|
||||
glyph_x = floor (x + cx + 0.125) + glyph.draw_x;
|
||||
glyph_y = floor (y + cy + 0.125) + glyph.draw_y;
|
||||
glyph_w = glyph.draw_width;
|
||||
glyph_h = glyph.draw_height;
|
||||
|
||||
@@ -808,7 +804,8 @@ upload_texture (GskGLRenderer *self,
|
||||
int texture_id;
|
||||
|
||||
if (texture->width <= 128 &&
|
||||
texture->height <= 128)
|
||||
texture->height <= 128 &&
|
||||
!GDK_IS_GL_TEXTURE (texture))
|
||||
{
|
||||
graphene_rect_t trect;
|
||||
|
||||
@@ -943,11 +940,9 @@ render_transform_node (GskGLRenderer *self,
|
||||
case GSK_TRANSFORM_CATEGORY_2D:
|
||||
default:
|
||||
{
|
||||
graphene_matrix_t mat;
|
||||
|
||||
if (node_supports_transform (child))
|
||||
{
|
||||
gsk_transform_to_matrix (node_transform, &mat);
|
||||
ops_push_modelview (builder, node_transform);
|
||||
gsk_gl_renderer_add_render_ops (self, child, builder);
|
||||
ops_pop_modelview (builder);
|
||||
@@ -972,7 +967,6 @@ render_transform_node (GskGLRenderer *self,
|
||||
®ion, &is_offscreen,
|
||||
RESET_CLIP | RESET_OPACITY);
|
||||
|
||||
gsk_transform_to_matrix (node_transform, &mat);
|
||||
ops_push_modelview (builder, node_transform);
|
||||
ops_set_texture (builder, region.texture_id);
|
||||
ops_set_program (builder, &self->blit_program);
|
||||
@@ -1017,12 +1011,49 @@ render_opacity_node (GskGLRenderer *self,
|
||||
GskRenderNode *node,
|
||||
RenderOpBuilder *builder)
|
||||
{
|
||||
GskRenderNode *child = gsk_opacity_node_get_child (node);
|
||||
const float opacity = gsk_opacity_node_get_opacity (node);
|
||||
float prev_opacity;
|
||||
|
||||
prev_opacity = ops_set_opacity (builder,
|
||||
builder->current_opacity * gsk_opacity_node_get_opacity (node));
|
||||
if (gsk_render_node_get_node_type (child) == GSK_CONTAINER_NODE)
|
||||
{
|
||||
const float min_x = builder->dx + node->bounds.origin.x;
|
||||
const float min_y = builder->dy + node->bounds.origin.y;
|
||||
const float max_x = min_x + node->bounds.size.width;
|
||||
const float max_y = min_y + node->bounds.size.height;
|
||||
gboolean is_offscreen;
|
||||
TextureRegion region;
|
||||
|
||||
gsk_gl_renderer_add_render_ops (self, gsk_opacity_node_get_child (node), builder);
|
||||
/* The semantics of an opacity node mandate that when, e.g., two color nodes overlap,
|
||||
* there may not be any blending between them */
|
||||
add_offscreen_ops (self, builder, &child->bounds,
|
||||
child,
|
||||
®ion, &is_offscreen,
|
||||
FORCE_OFFSCREEN | RESET_OPACITY | RESET_CLIP);
|
||||
|
||||
prev_opacity = ops_set_opacity (builder,
|
||||
builder->current_opacity * opacity);
|
||||
|
||||
ops_set_program (builder, &self->blit_program);
|
||||
ops_set_texture (builder, region.texture_id);
|
||||
|
||||
ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
|
||||
{ { min_x, min_y }, { region.x, region.y2 }, },
|
||||
{ { min_x, max_y }, { region.x, region.y }, },
|
||||
{ { max_x, min_y }, { region.x2, region.y2 }, },
|
||||
|
||||
{ { max_x, max_y }, { region.x2, region.y }, },
|
||||
{ { min_x, max_y }, { region.x, region.y }, },
|
||||
{ { max_x, min_y }, { region.x2, region.y2 }, },
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_opacity = ops_set_opacity (builder,
|
||||
builder->current_opacity * opacity);
|
||||
|
||||
gsk_gl_renderer_add_render_ops (self, child, builder);
|
||||
}
|
||||
|
||||
ops_set_opacity (builder, prev_opacity);
|
||||
}
|
||||
@@ -1292,7 +1323,7 @@ render_rounded_clip_node (GskGLRenderer *self,
|
||||
{ { min_x, min_y }, { 0, 1 }, },
|
||||
{ { min_x, max_y }, { 0, 0 }, },
|
||||
{ { max_x, min_y }, { 1, 1 }, },
|
||||
|
||||
|
||||
{ { max_x, max_y }, { 1, 0 }, },
|
||||
{ { min_x, max_y }, { 0, 0 }, },
|
||||
{ { max_x, min_y }, { 1, 1 }, },
|
||||
@@ -1393,7 +1424,7 @@ render_blur_node (GskGLRenderer *self,
|
||||
ops_set_program (builder, &self->blur_program);
|
||||
op.op = OP_CHANGE_BLUR;
|
||||
graphene_size_init_from_size (&op.blur.size, &node->bounds.size);
|
||||
op.blur.radius = gsk_blur_node_get_radius (node);
|
||||
op.blur.radius = blur_radius;
|
||||
ops_add (builder, &op);
|
||||
|
||||
ops_set_texture (builder, region.texture_id);
|
||||
@@ -1404,7 +1435,7 @@ render_blur_node (GskGLRenderer *self,
|
||||
{ { min_x, min_y }, { 0, 1 }, },
|
||||
{ { min_x, max_y }, { 0, 0 }, },
|
||||
{ { max_x, min_y }, { 1, 1 }, },
|
||||
|
||||
|
||||
{ { max_x, max_y }, { 1, 0 }, },
|
||||
{ { min_x, max_y }, { 0, 0 }, },
|
||||
{ { max_x, min_y }, { 1, 1 }, },
|
||||
@@ -1855,10 +1886,10 @@ render_shadow_node (GskGLRenderer *self,
|
||||
RenderOpBuilder *builder,
|
||||
const GskQuadVertex *vertex_data)
|
||||
{
|
||||
float min_x = node->bounds.origin.x;
|
||||
float min_y = node->bounds.origin.y;
|
||||
float max_x = min_x + node->bounds.size.width;
|
||||
float max_y = min_y + node->bounds.size.height;
|
||||
float min_x;
|
||||
float min_y;
|
||||
float max_x;
|
||||
float max_y;
|
||||
GskRenderNode *original_child = gsk_shadow_node_get_child (node);
|
||||
GskRenderNode *shadow_child = original_child;
|
||||
gsize n_shadows = gsk_shadow_node_get_n_shadows (node);
|
||||
@@ -1884,6 +1915,11 @@ render_shadow_node (GskGLRenderer *self,
|
||||
shadow_child = gsk_color_matrix_node_get_child (shadow_child);
|
||||
}
|
||||
|
||||
min_x = builder->dx + shadow_child->bounds.origin.x;
|
||||
min_y = builder->dy + shadow_child->bounds.origin.y;
|
||||
max_x = min_x + shadow_child->bounds.size.width;
|
||||
max_y = min_y + shadow_child->bounds.size.height;
|
||||
|
||||
for (i = 0; i < n_shadows; i ++)
|
||||
{
|
||||
const GskShadow *shadow = gsk_shadow_node_peek_shadow (node, i);
|
||||
@@ -1905,11 +1941,6 @@ render_shadow_node (GskGLRenderer *self,
|
||||
if (gdk_rgba_is_clear (&shadow->color))
|
||||
continue;
|
||||
|
||||
min_x = builder->dx + shadow_child->bounds.origin.x;
|
||||
min_y = builder->dy + shadow_child->bounds.origin.y;
|
||||
max_x = min_x + shadow_child->bounds.size.width;
|
||||
max_y = min_y + shadow_child->bounds.size.height;
|
||||
|
||||
/* Draw the child offscreen, without the offset. */
|
||||
add_offscreen_ops (self, builder,
|
||||
&shadow_child->bounds,
|
||||
@@ -2052,6 +2083,90 @@ render_blend_node (GskGLRenderer *self,
|
||||
ops_draw (builder, vertex_data);
|
||||
}
|
||||
|
||||
static inline void
|
||||
render_repeat_node (GskGLRenderer *self,
|
||||
GskRenderNode *node,
|
||||
RenderOpBuilder *builder)
|
||||
{
|
||||
const float min_x = builder->dx + node->bounds.origin.x;
|
||||
const float min_y = builder->dy + node->bounds.origin.y;
|
||||
const float max_x = min_x + node->bounds.size.width;
|
||||
const float max_y = min_y + node->bounds.size.height;
|
||||
GskRenderNode *child = gsk_repeat_node_get_child (node);
|
||||
const graphene_rect_t *child_bounds = gsk_repeat_node_peek_child_bounds (node);
|
||||
TextureRegion region;
|
||||
gboolean is_offscreen;
|
||||
RenderOp op;
|
||||
|
||||
if (child_bounds != NULL &&
|
||||
!graphene_rect_equal (child_bounds, &child->bounds))
|
||||
{
|
||||
/* TODO: Implement these repeat nodes. */
|
||||
render_fallback_node (self, node, builder);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Draw the entire child on a texture */
|
||||
add_offscreen_ops (self, builder,
|
||||
&child->bounds,
|
||||
child,
|
||||
®ion, &is_offscreen,
|
||||
RESET_CLIP | RESET_OPACITY);
|
||||
|
||||
ops_set_program (builder, &self->repeat_program);
|
||||
ops_set_texture (builder, region.texture_id);
|
||||
op.op = OP_CHANGE_REPEAT;
|
||||
op.repeat.child_bounds[0] = 0; /* Both currently unused */
|
||||
op.repeat.child_bounds[1] = 0;
|
||||
op.repeat.child_bounds[2] = node->bounds.size.width / child_bounds->size.width;
|
||||
op.repeat.child_bounds[3] = node->bounds.size.height / child_bounds->size.height;
|
||||
|
||||
op.repeat.texture_rect[0] = region.x;
|
||||
op.repeat.texture_rect[2] = region.x2;
|
||||
|
||||
if (is_offscreen)
|
||||
{
|
||||
op.repeat.texture_rect[1] = region.y2;
|
||||
op.repeat.texture_rect[3] = region.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
op.repeat.texture_rect[1] = region.y;
|
||||
op.repeat.texture_rect[3] = region.y2;
|
||||
}
|
||||
|
||||
ops_add (builder, &op);
|
||||
|
||||
if (is_offscreen)
|
||||
{
|
||||
const GskQuadVertex offscreen_vertex_data[GL_N_VERTICES] = {
|
||||
{ { min_x, min_y }, { region.x, region.y2 }, },
|
||||
{ { min_x, max_y }, { region.x, region.y }, },
|
||||
{ { max_x, min_y }, { region.x2, region.y2 }, },
|
||||
|
||||
{ { max_x, max_y }, { region.x2, region.y }, },
|
||||
{ { min_x, max_y }, { region.x, region.y }, },
|
||||
{ { max_x, min_y }, { region.x2, region.y2 }, },
|
||||
};
|
||||
|
||||
ops_draw (builder, offscreen_vertex_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
const GskQuadVertex onscreen_vertex_data[GL_N_VERTICES] = {
|
||||
{ { min_x, min_y }, { region.x, region.y }, },
|
||||
{ { min_x, max_y }, { region.x, region.y2 }, },
|
||||
{ { max_x, min_y }, { region.x2, region.y }, },
|
||||
|
||||
{ { max_x, max_y }, { region.x2, region.y2 }, },
|
||||
{ { min_x, max_y }, { region.x, region.y2 }, },
|
||||
{ { max_x, min_y }, { region.x2, region.y }, },
|
||||
};
|
||||
|
||||
ops_draw (builder, onscreen_vertex_data);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
apply_viewport_op (const Program *program,
|
||||
const RenderOp *op)
|
||||
@@ -2338,12 +2453,21 @@ apply_blend_op (const Program *program,
|
||||
glUniform1i (program->blend.mode_location, op->blend.mode);
|
||||
}
|
||||
|
||||
static inline void
|
||||
apply_repeat_op (const Program *program,
|
||||
const RenderOp *op)
|
||||
{
|
||||
glUniform4fv (program->repeat.child_bounds_location, 1, op->repeat.child_bounds);
|
||||
glUniform4fv (program->repeat.texture_rect_location, 1, op->repeat.texture_rect);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_dispose (GObject *gobject)
|
||||
{
|
||||
GskGLRenderer *self = GSK_GL_RENDERER (gobject);
|
||||
|
||||
g_clear_pointer (&self->render_ops, g_array_unref);
|
||||
ops_free (&self->op_builder);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gl_renderer_parent_class)->dispose (gobject);
|
||||
}
|
||||
@@ -2358,19 +2482,21 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
static const struct {
|
||||
const char *name;
|
||||
const char *fs;
|
||||
const char *vs;
|
||||
} program_definitions[] = {
|
||||
{ "blit", "blit.fs.glsl" },
|
||||
{ "color", "color.fs.glsl" },
|
||||
{ "coloring", "coloring.fs.glsl" },
|
||||
{ "color matrix", "color_matrix.fs.glsl" },
|
||||
{ "linear gradient", "linear_gradient.fs.glsl" },
|
||||
{ "blur", "blur.fs.glsl" },
|
||||
{ "inset shadow", "inset_shadow.fs.glsl" },
|
||||
{ "outset shadow", "outset_shadow.fs.glsl" },
|
||||
{ "blit", "blit.fs.glsl" },
|
||||
{ "color", "color.fs.glsl" },
|
||||
{ "coloring", "coloring.fs.glsl" },
|
||||
{ "color matrix", "color_matrix.fs.glsl" },
|
||||
{ "linear gradient", "linear_gradient.fs.glsl" },
|
||||
{ "blur", "blur.fs.glsl" },
|
||||
{ "inset shadow", "inset_shadow.fs.glsl" },
|
||||
{ "outset shadow", "outset_shadow.fs.glsl" },
|
||||
{ "unblurred outset shadow", "unblurred_outset_shadow.fs.glsl" },
|
||||
{ "border", "border.fs.glsl" },
|
||||
{ "cross fade", "cross_fade.fs.glsl" },
|
||||
{ "blend", "blend.fs.glsl" },
|
||||
{ "border", "border.fs.glsl" },
|
||||
{ "cross fade", "cross_fade.fs.glsl" },
|
||||
{ "blend", "blend.fs.glsl" },
|
||||
{ "repeat", "repeat.fs.glsl" },
|
||||
};
|
||||
|
||||
builder = gsk_shader_builder_new ();
|
||||
@@ -2423,6 +2549,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
prog->index = i;
|
||||
prog->id = gsk_shader_builder_create_program (builder,
|
||||
program_definitions[i].fs,
|
||||
program_definitions[i].vs,
|
||||
&shader_error);
|
||||
|
||||
if (shader_error != NULL)
|
||||
@@ -2430,8 +2557,8 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
g_propagate_prefixed_error (error, shader_error,
|
||||
"Unable to create '%s' program (from %s and %s):\n",
|
||||
program_definitions[i].name,
|
||||
"blit.vs.glsl",
|
||||
program_definitions[i].fs);
|
||||
program_definitions[i].fs,
|
||||
program_definitions[i].vs);
|
||||
|
||||
g_object_unref (builder);
|
||||
return FALSE;
|
||||
@@ -2505,6 +2632,10 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (blend, source2);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (blend, mode);
|
||||
|
||||
/* repeat */
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (repeat, child_bounds);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (repeat, texture_rect);
|
||||
|
||||
g_object_unref (builder);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -2832,8 +2963,11 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
||||
render_blend_node (self, node, builder);
|
||||
break;
|
||||
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
case GSK_REPEAT_NODE:
|
||||
render_repeat_node (self, node, builder);
|
||||
break;
|
||||
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
case GSK_CAIRO_NODE:
|
||||
default:
|
||||
{
|
||||
@@ -3120,6 +3254,10 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
|
||||
apply_unblurred_outset_shadow_op (program, op);
|
||||
break;
|
||||
|
||||
case OP_CHANGE_REPEAT:
|
||||
apply_repeat_op (program, op);
|
||||
break;
|
||||
|
||||
case OP_DRAW:
|
||||
OP_PRINT (" -> draw %ld, size %ld and program %d\n",
|
||||
op->draw.vao_offset, op->draw.vao_size, program->index);
|
||||
@@ -3160,7 +3298,7 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
|
||||
int scale_factor)
|
||||
{
|
||||
GskGLRenderer *self = GSK_GL_RENDERER (renderer);
|
||||
graphene_matrix_t modelview, projection;
|
||||
graphene_matrix_t projection;
|
||||
gsize buffer_size;
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
GskProfiler *profiler;
|
||||
@@ -3180,7 +3318,6 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
|
||||
g_assert (gsk_gl_driver_in_frame (self->gl_driver));
|
||||
|
||||
/* Set up the modelview and projection matrices to fit our viewport */
|
||||
graphene_matrix_init_scale (&modelview, scale_factor, scale_factor, 1.0);
|
||||
graphene_matrix_init_ortho (&projection,
|
||||
viewport->origin.x,
|
||||
viewport->origin.x + viewport->size.width,
|
||||
|
||||
+68
-32
@@ -8,6 +8,15 @@ rect_equal (const graphene_rect_t *a,
|
||||
return memcmp (a, b, sizeof (graphene_rect_t)) == 0;
|
||||
}
|
||||
|
||||
static inline ProgramState *
|
||||
get_current_program_state (RenderOpBuilder *builder)
|
||||
{
|
||||
if (!builder->current_program)
|
||||
return NULL;
|
||||
|
||||
return &builder->program_state[builder->current_program->index];
|
||||
}
|
||||
|
||||
void
|
||||
ops_finish (RenderOpBuilder *builder)
|
||||
{
|
||||
@@ -27,7 +36,6 @@ ops_finish (RenderOpBuilder *builder)
|
||||
builder->current_render_target = 0;
|
||||
builder->current_texture = 0;
|
||||
builder->current_program = NULL;
|
||||
builder->current_program_state = NULL;
|
||||
graphene_matrix_init_identity (&builder->current_projection);
|
||||
builder->current_viewport = GRAPHENE_RECT_INIT (0, 0, 0, 0);
|
||||
}
|
||||
@@ -187,6 +195,17 @@ ops_init (RenderOpBuilder *builder)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ops_free (RenderOpBuilder *builder)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < GL_N_PROGRAMS; i ++)
|
||||
{
|
||||
gsk_transform_unref (builder->program_state[i].modelview);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ops_set_program (RenderOpBuilder *builder,
|
||||
const Program *program)
|
||||
@@ -225,6 +244,7 @@ ops_set_program (RenderOpBuilder *builder,
|
||||
op.op = OP_CHANGE_MODELVIEW;
|
||||
gsk_transform_to_matrix (builder->current_modelview, &op.modelview);
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
gsk_transform_unref (program_state->modelview);
|
||||
program_state->modelview = gsk_transform_ref (builder->current_modelview);
|
||||
}
|
||||
|
||||
@@ -253,8 +273,6 @@ ops_set_program (RenderOpBuilder *builder,
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
program_state->opacity = builder->current_opacity;
|
||||
}
|
||||
|
||||
builder->current_program_state = &builder->program_state[program->index];
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -262,9 +280,10 @@ ops_set_clip (RenderOpBuilder *builder,
|
||||
const GskRoundedRect *clip)
|
||||
{
|
||||
RenderOp *last_op;
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
|
||||
if (builder->current_program_state &&
|
||||
memcmp (&builder->current_program_state->clip, clip,sizeof (GskRoundedRect)) == 0)
|
||||
if (current_program_state &&
|
||||
memcmp (¤t_program_state->clip, clip,sizeof (GskRoundedRect)) == 0)
|
||||
return;
|
||||
|
||||
if (builder->render_ops->len > 0)
|
||||
@@ -286,7 +305,7 @@ ops_set_clip (RenderOpBuilder *builder,
|
||||
}
|
||||
|
||||
if (builder->current_program != NULL)
|
||||
builder->current_program_state->clip = *clip;
|
||||
current_program_state->clip = *clip;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -336,12 +355,16 @@ static void
|
||||
ops_set_modelview_internal (RenderOpBuilder *builder,
|
||||
GskTransform *transform)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp op;
|
||||
graphene_matrix_t matrix;
|
||||
|
||||
#if 0
|
||||
XXX This is not possible if we want pop() to work.
|
||||
if (builder->current_program &&
|
||||
gsk_transform_equal (builder->current_program_state->modelview, transform))
|
||||
return;
|
||||
#endif
|
||||
|
||||
gsk_transform_to_matrix (transform, &matrix);
|
||||
|
||||
@@ -367,10 +390,18 @@ ops_set_modelview_internal (RenderOpBuilder *builder,
|
||||
}
|
||||
|
||||
if (builder->current_program != NULL)
|
||||
builder->current_program_state->modelview = transform;
|
||||
{
|
||||
gsk_transform_unref (current_program_state->modelview);
|
||||
current_program_state->modelview = gsk_transform_ref (transform);
|
||||
}
|
||||
}
|
||||
|
||||
/* This sets the modelview to the given one without looking at the
|
||||
/**
|
||||
* ops_set_modelview:
|
||||
* @builder
|
||||
* @transform: (transfer full): The new modelview transform
|
||||
*
|
||||
* This sets the modelview to the given one without looking at the
|
||||
* one that's currently set */
|
||||
void
|
||||
ops_set_modelview (RenderOpBuilder *builder,
|
||||
@@ -386,11 +417,11 @@ ops_set_modelview (RenderOpBuilder *builder,
|
||||
g_array_set_size (builder->mv_stack, builder->mv_stack->len + 1);
|
||||
entry = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
|
||||
|
||||
entry->transform = gsk_transform_ref (transform);
|
||||
entry->transform = transform;
|
||||
|
||||
entry->metadata.dx_before = builder->dx;
|
||||
entry->metadata.dy_before = builder->dy;
|
||||
extract_matrix_metadata (transform, &entry->metadata);
|
||||
extract_matrix_metadata (entry->transform, &entry->metadata);
|
||||
|
||||
builder->dx = 0;
|
||||
builder->dy = 0;
|
||||
@@ -404,7 +435,6 @@ void
|
||||
ops_push_modelview (RenderOpBuilder *builder,
|
||||
GskTransform *transform)
|
||||
{
|
||||
float scale = ops_get_scale (builder);
|
||||
MatrixStackEntry *entry;
|
||||
|
||||
if (G_UNLIKELY (builder->mv_stack == NULL))
|
||||
@@ -424,10 +454,9 @@ ops_push_modelview (RenderOpBuilder *builder,
|
||||
/* Multiply given matrix with current modelview */
|
||||
|
||||
t = gsk_transform_translate (gsk_transform_ref (cur->transform),
|
||||
&(graphene_point_t) { builder->dx * scale, builder->dy * scale});
|
||||
&(graphene_point_t) { builder->dx, builder->dy});
|
||||
t = gsk_transform_transform (t, transform);
|
||||
entry->transform = t;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -436,7 +465,6 @@ ops_push_modelview (RenderOpBuilder *builder,
|
||||
|
||||
entry->metadata.dx_before = builder->dx;
|
||||
entry->metadata.dy_before = builder->dy;
|
||||
|
||||
extract_matrix_metadata (entry->transform, &entry->metadata);
|
||||
|
||||
builder->dx = 0;
|
||||
@@ -476,6 +504,7 @@ graphene_matrix_t
|
||||
ops_set_projection (RenderOpBuilder *builder,
|
||||
const graphene_matrix_t *projection)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp op;
|
||||
graphene_matrix_t prev_mv;
|
||||
|
||||
@@ -501,7 +530,7 @@ ops_set_projection (RenderOpBuilder *builder,
|
||||
}
|
||||
|
||||
if (builder->current_program != NULL)
|
||||
builder->current_program_state->projection = *projection;
|
||||
current_program_state->projection = *projection;
|
||||
|
||||
prev_mv = builder->current_projection;
|
||||
builder->current_projection = *projection;
|
||||
@@ -513,19 +542,20 @@ graphene_rect_t
|
||||
ops_set_viewport (RenderOpBuilder *builder,
|
||||
const graphene_rect_t *viewport)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp op;
|
||||
graphene_rect_t prev_viewport;
|
||||
|
||||
if (builder->current_program_state != NULL &&
|
||||
rect_equal (&builder->current_program_state->viewport, viewport))
|
||||
return builder->current_program_state->viewport;
|
||||
if (current_program_state != NULL &&
|
||||
rect_equal (¤t_program_state->viewport, viewport))
|
||||
return current_program_state->viewport;
|
||||
|
||||
op.op = OP_CHANGE_VIEWPORT;
|
||||
op.viewport = *viewport;
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
|
||||
if (builder->current_program != NULL)
|
||||
builder->current_program_state->viewport = *viewport;
|
||||
current_program_state->viewport = *viewport;
|
||||
|
||||
prev_viewport = builder->current_viewport;
|
||||
builder->current_viewport = *viewport;
|
||||
@@ -590,6 +620,7 @@ float
|
||||
ops_set_opacity (RenderOpBuilder *builder,
|
||||
float opacity)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp op;
|
||||
float prev_opacity;
|
||||
RenderOp *last_op;
|
||||
@@ -623,7 +654,7 @@ ops_set_opacity (RenderOpBuilder *builder,
|
||||
builder->current_opacity = opacity;
|
||||
|
||||
if (builder->current_program != NULL)
|
||||
builder->current_program_state->opacity = opacity;
|
||||
current_program_state->opacity = opacity;
|
||||
|
||||
return prev_opacity;
|
||||
}
|
||||
@@ -632,12 +663,13 @@ void
|
||||
ops_set_color (RenderOpBuilder *builder,
|
||||
const GdkRGBA *color)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp op;
|
||||
|
||||
if (gdk_rgba_equal (color, &builder->current_program_state->color))
|
||||
if (gdk_rgba_equal (color, ¤t_program_state->color))
|
||||
return;
|
||||
|
||||
builder->current_program_state->color = *color;
|
||||
current_program_state->color = *color;
|
||||
|
||||
op.op = OP_CHANGE_COLOR;
|
||||
op.color = *color;
|
||||
@@ -649,18 +681,19 @@ ops_set_color_matrix (RenderOpBuilder *builder,
|
||||
const graphene_matrix_t *matrix,
|
||||
const graphene_vec4_t *offset)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp op;
|
||||
|
||||
if (memcmp (matrix,
|
||||
&builder->current_program_state->color_matrix.matrix,
|
||||
¤t_program_state->color_matrix.matrix,
|
||||
sizeof (graphene_matrix_t)) == 0 &&
|
||||
memcmp (offset,
|
||||
&builder->current_program_state->color_matrix.offset,
|
||||
¤t_program_state->color_matrix.offset,
|
||||
sizeof (graphene_vec4_t)) == 0)
|
||||
return;
|
||||
|
||||
builder->current_program_state->color_matrix.matrix = *matrix;
|
||||
builder->current_program_state->color_matrix.offset = *offset;
|
||||
current_program_state->color_matrix.matrix = *matrix;
|
||||
current_program_state->color_matrix.offset = *offset;
|
||||
|
||||
op.op = OP_CHANGE_COLOR_MATRIX;
|
||||
op.color_matrix.matrix = *matrix;
|
||||
@@ -672,13 +705,14 @@ void
|
||||
ops_set_border (RenderOpBuilder *builder,
|
||||
const GskRoundedRect *outline)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp op;
|
||||
|
||||
if (memcmp (&builder->current_program_state->border.outline,
|
||||
if (memcmp (¤t_program_state->border.outline,
|
||||
outline, sizeof (GskRoundedRect)) == 0)
|
||||
return;
|
||||
|
||||
builder->current_program_state->border.outline = *outline;
|
||||
current_program_state->border.outline = *outline;
|
||||
|
||||
op.op = OP_CHANGE_BORDER;
|
||||
op.border.outline = *outline;
|
||||
@@ -689,13 +723,14 @@ void
|
||||
ops_set_border_width (RenderOpBuilder *builder,
|
||||
const float *widths)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp op;
|
||||
|
||||
if (memcmp (builder->current_program_state->border.widths,
|
||||
if (memcmp (current_program_state->border.widths,
|
||||
widths, sizeof (float) * 4) == 0)
|
||||
return;
|
||||
|
||||
memcpy (&builder->current_program_state->border.widths,
|
||||
memcpy (¤t_program_state->border.widths,
|
||||
widths, sizeof (float) * 4);
|
||||
|
||||
op.op = OP_CHANGE_BORDER_WIDTH;
|
||||
@@ -711,15 +746,16 @@ void
|
||||
ops_set_border_color (RenderOpBuilder *builder,
|
||||
const GdkRGBA *color)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp op;
|
||||
op.op = OP_CHANGE_BORDER_COLOR;
|
||||
rgba_to_float (color, op.border.color);
|
||||
|
||||
if (memcmp (&op.border.color, &builder->current_program_state->border.color,
|
||||
if (memcmp (&op.border.color, ¤t_program_state->border.color,
|
||||
sizeof (float) * 4) == 0)
|
||||
return;
|
||||
|
||||
rgba_to_float (color, builder->current_program_state->border.color);
|
||||
rgba_to_float (color, current_program_state->border.color);
|
||||
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "gskrendernodeprivate.h"
|
||||
|
||||
#define GL_N_VERTICES 6
|
||||
#define GL_N_PROGRAMS 12
|
||||
#define GL_N_PROGRAMS 13
|
||||
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ enum {
|
||||
OP_PUSH_DEBUG_GROUP = 24,
|
||||
OP_POP_DEBUG_GROUP = 25,
|
||||
OP_CHANGE_BLEND = 26,
|
||||
OP_CHANGE_REPEAT = 27,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
@@ -139,6 +140,10 @@ typedef struct
|
||||
int source2_location;
|
||||
int mode_location;
|
||||
} blend;
|
||||
struct {
|
||||
int child_bounds_location;
|
||||
int texture_rect_location;
|
||||
} repeat;
|
||||
};
|
||||
|
||||
} Program;
|
||||
@@ -149,7 +154,7 @@ typedef struct
|
||||
|
||||
union {
|
||||
float opacity;
|
||||
graphene_matrix_t modelview; /* TODO: Make both matrix members just "matrix" */
|
||||
graphene_matrix_t modelview;
|
||||
graphene_matrix_t projection;
|
||||
const Program *program;
|
||||
int texture_id;
|
||||
@@ -221,6 +226,10 @@ typedef struct
|
||||
int source2;
|
||||
int mode;
|
||||
} blend;
|
||||
struct {
|
||||
float child_bounds[4];
|
||||
float texture_rect[4];
|
||||
} repeat;
|
||||
struct {
|
||||
char *filename;
|
||||
int width;
|
||||
@@ -258,8 +267,6 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
ProgramState program_state[GL_N_PROGRAMS];
|
||||
/* Current global state */
|
||||
ProgramState *current_program_state;
|
||||
const Program *current_program;
|
||||
int current_render_target;
|
||||
int current_texture;
|
||||
@@ -290,6 +297,7 @@ void ops_dump_framebuffer (RenderOpBuilder *builder,
|
||||
int width,
|
||||
int height);
|
||||
void ops_init (RenderOpBuilder *builder);
|
||||
void ops_free (RenderOpBuilder *builder);
|
||||
void ops_push_debug_group (RenderOpBuilder *builder,
|
||||
const char *text);
|
||||
void ops_pop_debug_group (RenderOpBuilder *builder);
|
||||
|
||||
@@ -257,6 +257,7 @@ gsk_shader_builder_set_common_vertex_shader (GskShaderBuilder *self,
|
||||
int
|
||||
gsk_shader_builder_create_program (GskShaderBuilder *builder,
|
||||
const char *fragment_shader,
|
||||
const char *vertex_shader,
|
||||
GError **error)
|
||||
{
|
||||
int vertex_id;
|
||||
@@ -268,7 +269,16 @@ gsk_shader_builder_create_program (GskShaderBuilder *builder,
|
||||
g_return_val_if_fail (fragment_shader != NULL, -1);
|
||||
g_return_val_if_fail (builder->common_vertex_shader_id != 0, -1);
|
||||
|
||||
vertex_id = builder->common_vertex_shader_id;
|
||||
if (vertex_shader == NULL)
|
||||
vertex_id = builder->common_vertex_shader_id;
|
||||
else
|
||||
vertex_id = gsk_shader_builder_compile_shader (builder, GL_VERTEX_SHADER,
|
||||
builder->vertex_preamble,
|
||||
vertex_shader,
|
||||
error);
|
||||
if (vertex_id < 0)
|
||||
return -1;
|
||||
|
||||
fragment_id = gsk_shader_builder_compile_shader (builder, GL_FRAGMENT_SHADER,
|
||||
builder->fragment_preamble,
|
||||
fragment_shader,
|
||||
|
||||
@@ -31,6 +31,7 @@ void gsk_shader_builder_set_common_vertex_shader (GskShad
|
||||
|
||||
int gsk_shader_builder_create_program (GskShaderBuilder *builder,
|
||||
const char *fragment_shader,
|
||||
const char *vertex_shader,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -1966,14 +1966,14 @@ gsk_transform_node_diff (GskRenderNode *node1,
|
||||
cairo_region_t *tmp = cairo_region_copy (sub);
|
||||
cairo_region_translate (tmp, 1, 0);
|
||||
cairo_region_union (sub, tmp);
|
||||
cairo_region_destroy (sub);
|
||||
cairo_region_destroy (tmp);
|
||||
}
|
||||
if (floor (dy) != dy)
|
||||
{
|
||||
cairo_region_t *tmp = cairo_region_copy (sub);
|
||||
cairo_region_translate (tmp, 0, 1);
|
||||
cairo_region_union (sub, tmp);
|
||||
cairo_region_destroy (sub);
|
||||
cairo_region_destroy (tmp);
|
||||
}
|
||||
cairo_region_union (region, sub);
|
||||
cairo_region_destroy (sub);
|
||||
|
||||
@@ -94,6 +94,7 @@ parse_texture (GtkCssParser *parser,
|
||||
if (bytes)
|
||||
{
|
||||
stream = g_memory_input_stream_new_from_bytes (bytes);
|
||||
g_bytes_unref (bytes);
|
||||
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &error);
|
||||
g_object_unref (stream);
|
||||
if (pixbuf != NULL)
|
||||
@@ -748,6 +749,8 @@ parse_glyphs (GtkCssParser *parser,
|
||||
pango_glyph_string_set_size (glyph_string, glyph_string->num_glyphs + 1);
|
||||
glyph_string->glyphs[glyph_string->num_glyphs - 1] = gi;
|
||||
}
|
||||
|
||||
g_free (s);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -817,7 +820,7 @@ parse_container_node (GtkCssParser *parser)
|
||||
token = gtk_css_parser_get_token (parser))
|
||||
{
|
||||
node = NULL;
|
||||
/* We don't wand a semicolon here, but the parse_node function will figure
|
||||
/* We don't want a semicolon here, but the parse_node function will figure
|
||||
* that out itself and return an error if we encounter one.
|
||||
*/
|
||||
gtk_css_parser_start_semicolon_block (parser, GTK_CSS_TOKEN_OPEN_CURLY);
|
||||
|
||||
+49
-9
@@ -646,7 +646,7 @@ gsk_transform_translate_3d (GskTransform *next,
|
||||
GskTranslateTransform *result;
|
||||
|
||||
if (graphene_point3d_equal (point, graphene_point3d_zero ()))
|
||||
return gsk_transform_ref (next);
|
||||
return next;
|
||||
|
||||
if (gsk_transform_has_class (next, &GSK_TRANSLATE_TRANSFORM_CLASS))
|
||||
{
|
||||
@@ -801,7 +801,7 @@ gsk_transform_rotate (GskTransform *next,
|
||||
GskRotateTransform *result;
|
||||
|
||||
if (angle == 0.0f)
|
||||
return gsk_transform_ref (next);
|
||||
return next;
|
||||
|
||||
if (gsk_transform_has_class (next, &GSK_ROTATE_TRANSFORM_CLASS))
|
||||
{
|
||||
@@ -932,7 +932,7 @@ gsk_transform_rotate_3d (GskTransform *next,
|
||||
return gsk_transform_rotate (next, angle);
|
||||
|
||||
if (angle == 0.0f)
|
||||
return gsk_transform_ref (next);
|
||||
return next;
|
||||
|
||||
result = gsk_transform_alloc (&GSK_ROTATE3D_TRANSFORM_CLASS,
|
||||
GSK_TRANSFORM_CATEGORY_3D,
|
||||
@@ -1121,7 +1121,7 @@ gsk_transform_scale_3d (GskTransform *next,
|
||||
GskScaleTransform *result;
|
||||
|
||||
if (factor_x == 1 && factor_y == 1 && factor_z == 1)
|
||||
return gsk_transform_ref (next);
|
||||
return next;
|
||||
|
||||
if (gsk_transform_has_class (next, &GSK_SCALE_TRANSFORM_CLASS))
|
||||
{
|
||||
@@ -1250,7 +1250,7 @@ gsk_transform_perspective (GskTransform *next,
|
||||
float depth)
|
||||
{
|
||||
GskPerspectiveTransform *result;
|
||||
|
||||
|
||||
if (gsk_transform_has_class (next, &GSK_PERSPECTIVE_TRANSFORM_CLASS))
|
||||
{
|
||||
GskTransform *r = gsk_transform_perspective (gsk_transform_ref (next->next),
|
||||
@@ -1690,11 +1690,26 @@ gsk_transform_transform_bounds (GskTransform *self,
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_TRANSFORM_CATEGORY_2D_AFFINE:
|
||||
{
|
||||
float dx, dy, scale_x, scale_y;
|
||||
|
||||
gsk_transform_to_affine (self, &scale_x, &scale_y, &dx, &dy);
|
||||
|
||||
*out_rect = *rect;
|
||||
out_rect->origin.x *= scale_x;
|
||||
out_rect->origin.y *= scale_y;
|
||||
out_rect->size.width *= scale_x;
|
||||
out_rect->size.height *= scale_y;
|
||||
out_rect->origin.x += dx;
|
||||
out_rect->origin.y += dy;
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_TRANSFORM_CATEGORY_UNKNOWN:
|
||||
case GSK_TRANSFORM_CATEGORY_ANY:
|
||||
case GSK_TRANSFORM_CATEGORY_3D:
|
||||
case GSK_TRANSFORM_CATEGORY_2D:
|
||||
case GSK_TRANSFORM_CATEGORY_2D_AFFINE:
|
||||
default:
|
||||
{
|
||||
graphene_matrix_t mat;
|
||||
@@ -1886,18 +1901,43 @@ gsk_transform_parser_parse (GtkCssParser *parser,
|
||||
|
||||
transform = gsk_transform_translate_3d (transform, &GRAPHENE_POINT3D_INIT (0.f, 0.f, f[0]));
|
||||
}
|
||||
#if 0
|
||||
/* FIXME: add these */
|
||||
else if (gtk_css_token_is_function (token, "skew"))
|
||||
{
|
||||
graphene_matrix_t matrix;
|
||||
|
||||
if (!gtk_css_parser_consume_function (parser, 2, 2, gsk_transform_parse_float, f))
|
||||
goto fail;
|
||||
|
||||
f[0] = f[0] / 180.0 * G_PI;
|
||||
f[1] = f[1] / 180.0 * G_PI;
|
||||
|
||||
graphene_matrix_init_skew (&matrix, f[0], f[1]);
|
||||
transform = gsk_transform_matrix (transform, &matrix);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "skewX"))
|
||||
{
|
||||
graphene_matrix_t matrix;
|
||||
|
||||
if (!gtk_css_parser_consume_function (parser, 1, 1, gsk_transform_parse_float, f))
|
||||
goto fail;
|
||||
|
||||
f[0] = f[0] / 180.0 * G_PI;
|
||||
|
||||
graphene_matrix_init_skew (&matrix, f[0], 0);
|
||||
transform = gsk_transform_matrix (transform, &matrix);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "skewY"))
|
||||
{
|
||||
graphene_matrix_t matrix;
|
||||
|
||||
if (!gtk_css_parser_consume_function (parser, 1, 1, gsk_transform_parse_float, f))
|
||||
goto fail;
|
||||
|
||||
f[0] = f[0] / 180.0 * G_PI;
|
||||
|
||||
graphene_matrix_init_skew (&matrix, 0, f[0]);
|
||||
transform = gsk_transform_matrix (transform, &matrix);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
break;
|
||||
|
||||
@@ -12,6 +12,7 @@ gsk_private_gl_shaders = [
|
||||
'resources/glsl/border.fs.glsl',
|
||||
'resources/glsl/cross_fade.fs.glsl',
|
||||
'resources/glsl/blend.fs.glsl',
|
||||
'resources/glsl/repeat.fs.glsl',
|
||||
'resources/glsl/es2_common.fs.glsl',
|
||||
'resources/glsl/es2_common.vs.glsl',
|
||||
'resources/glsl/gl3_common.fs.glsl',
|
||||
|
||||
@@ -4,14 +4,14 @@ uniform sampler2D u_source2;
|
||||
float
|
||||
combine (float source, float backdrop)
|
||||
{
|
||||
return source + backdrop * (1 - source);
|
||||
return source + backdrop * (1.0 - source);
|
||||
}
|
||||
|
||||
vec4
|
||||
composite (vec4 Cs, vec4 Cb, vec3 B)
|
||||
{
|
||||
float ao = Cs.a + Cb.a * (1 - Cs.a);
|
||||
vec3 Co = (Cs.a*(1 - Cb.a)*Cs.rgb + Cs.a*Cb.a*B + (1 - Cs.a)*Cb.a*Cb.rgb) / ao;
|
||||
float ao = Cs.a + Cb.a * (1.0 - Cs.a);
|
||||
vec3 Co = (Cs.a*(1.0 - Cb.a)*Cs.rgb + Cs.a*Cb.a*B + (1.0 - Cs.a)*Cb.a*Cb.rgb) / ao;
|
||||
return vec4(Co, ao);
|
||||
}
|
||||
|
||||
@@ -43,9 +43,9 @@ float
|
||||
hard_light (float source, float backdrop)
|
||||
{
|
||||
if (source <= 0.5)
|
||||
return 2 * backdrop * source;
|
||||
return 2.0 * backdrop * source;
|
||||
else
|
||||
return 2 * (backdrop + source - backdrop * source) - 1;
|
||||
return 2.0 * (backdrop + source - backdrop * source) - 1.0;
|
||||
}
|
||||
|
||||
vec4
|
||||
@@ -63,14 +63,14 @@ soft_light (float source, float backdrop)
|
||||
float db;
|
||||
|
||||
if (backdrop <= 0.25)
|
||||
db = ((16 * backdrop - 12) * backdrop + 4) * backdrop;
|
||||
db = ((16.0 * backdrop - 12.0) * backdrop + 4.0) * backdrop;
|
||||
else
|
||||
db = sqrt (backdrop);
|
||||
|
||||
if (source <= 0.5)
|
||||
return backdrop - (1 - 2 * source) * backdrop * (1 - backdrop);
|
||||
return backdrop - (1.0 - 2.0 * source) * backdrop * (1.0 - backdrop);
|
||||
else
|
||||
return backdrop + (2 * source - 1) * (db - backdrop);
|
||||
return backdrop + (2.0 * source - 1.0) * (db - backdrop);
|
||||
}
|
||||
|
||||
vec4
|
||||
@@ -155,8 +155,8 @@ clip_color (vec3 c)
|
||||
float l = lum (c);
|
||||
float n = min (c.r, min (c.g, c.b));
|
||||
float x = max (c.r, max (c.g, c.b));
|
||||
if (n < 0) c = l + (((c - l) * l) / (l - n));
|
||||
if (x > 1) c = l + (((c - l) * (1 - l)) / (x - l));
|
||||
if (n < 0.0) c = l + (((c - l) * l) / (l - n));
|
||||
if (x > 1.0) c = l + (((c - l) * (1.0 - l)) / (x - l));
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -189,12 +189,12 @@ set_sat (vec3 c, float s)
|
||||
if (c.g == cmin)
|
||||
{
|
||||
res.b = ((c.b - cmin) * s) / (cmax - cmin);
|
||||
res.g = 0;
|
||||
res.g = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
res.g = ((c.g - cmin) * s) / (cmax - cmin);
|
||||
res.b = 0;
|
||||
res.b = 0.0;
|
||||
}
|
||||
res.r = s;
|
||||
}
|
||||
@@ -203,12 +203,12 @@ set_sat (vec3 c, float s)
|
||||
if (c.r == cmin)
|
||||
{
|
||||
res.b = ((c.b - cmin) * s) / (cmax - cmin);
|
||||
res.r = 0;
|
||||
res.r = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
res.r = ((c.r - cmin) * s) / (cmax - cmin);
|
||||
res.b = 0;
|
||||
res.b = 0.0;
|
||||
}
|
||||
res.g = s;
|
||||
}
|
||||
@@ -217,12 +217,12 @@ set_sat (vec3 c, float s)
|
||||
if (c.r == cmin)
|
||||
{
|
||||
res.g = ((c.g - cmin) * s) / (cmax - cmin);
|
||||
res.r = 0;
|
||||
res.r = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
res.r = ((c.r - cmin) * s) / (cmax - cmin);
|
||||
res.g = 0;
|
||||
res.g = 0.0;
|
||||
}
|
||||
res.b = s;
|
||||
}
|
||||
@@ -263,25 +263,74 @@ void main() {
|
||||
vec4 top_color = Texture(u_source2, vUv);
|
||||
|
||||
vec4 result;
|
||||
switch(u_mode) {
|
||||
case 0: result = normal(top_color, bottom_color); break;
|
||||
case 1: result = multiply(top_color, bottom_color); break;
|
||||
case 2: result = screen(top_color, bottom_color); break;
|
||||
case 3: result = overlay(top_color, bottom_color); break;
|
||||
case 4: result = darken(top_color, bottom_color); break;
|
||||
case 5: result = lighten(top_color, bottom_color); break;
|
||||
case 6: result = color_dodge(top_color, bottom_color); break;
|
||||
case 7: result = color_burn(top_color, bottom_color); break;
|
||||
case 8: result = hard_light(top_color, bottom_color); break;
|
||||
case 9: result = soft_light(top_color, bottom_color); break;
|
||||
case 10: result = difference(top_color, bottom_color); break;
|
||||
case 11: result = exclusion(top_color, bottom_color); break;
|
||||
case 12: result = color(top_color, bottom_color); break;
|
||||
case 13: result = hue(top_color, bottom_color); break;
|
||||
case 14: result = saturation(top_color, bottom_color); break;
|
||||
case 15: result = luminosity(top_color, bottom_color); break;
|
||||
default: discard;
|
||||
}
|
||||
if (u_mode == 0)
|
||||
{
|
||||
result = normal(top_color, bottom_color);
|
||||
}
|
||||
else if (u_mode == 1)
|
||||
{
|
||||
result = multiply(top_color, bottom_color);
|
||||
}
|
||||
else if (u_mode == 2)
|
||||
{
|
||||
result = screen(top_color, bottom_color);
|
||||
}
|
||||
else if (u_mode == 3)
|
||||
{
|
||||
result = overlay(top_color, bottom_color);
|
||||
}
|
||||
else if (u_mode == 4)
|
||||
{
|
||||
result = darken(top_color, bottom_color);
|
||||
}
|
||||
else if (u_mode == 5)
|
||||
{
|
||||
result = lighten(top_color, bottom_color);
|
||||
}
|
||||
else if (u_mode == 6)
|
||||
{
|
||||
result = color_dodge(top_color, bottom_color);
|
||||
}
|
||||
else if (u_mode == 7)
|
||||
{
|
||||
result = color_burn(top_color, bottom_color);
|
||||
}
|
||||
else if (u_mode == 8)
|
||||
{
|
||||
result = hard_light(top_color, bottom_color);
|
||||
}
|
||||
else if (u_mode == 9)
|
||||
{
|
||||
result = soft_light(top_color, bottom_color);
|
||||
}
|
||||
else if (u_mode == 10)
|
||||
{
|
||||
result = difference(top_color, bottom_color);
|
||||
}
|
||||
else if (u_mode == 11)
|
||||
{
|
||||
result = exclusion(top_color, bottom_color);
|
||||
}
|
||||
else if (u_mode == 12)
|
||||
{
|
||||
result = color(top_color, bottom_color);
|
||||
}
|
||||
else if (u_mode == 13)
|
||||
{
|
||||
result = hue(top_color, bottom_color);
|
||||
}
|
||||
else if (u_mode == 14)
|
||||
{
|
||||
result = saturation(top_color, bottom_color);
|
||||
}
|
||||
else if (u_mode == 15)
|
||||
{
|
||||
result = luminosity(top_color, bottom_color);
|
||||
}
|
||||
else
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
setOutputColor(result * u_alpha);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
uniform vec4 u_child_bounds;
|
||||
uniform vec4 u_texture_rect;
|
||||
|
||||
|
||||
float wrap(float f, float wrap_for) {
|
||||
return mod(f, wrap_for);
|
||||
}
|
||||
|
||||
/* We get the texture coordinates via vUv,
|
||||
* but that might be on a texture atlas, so we need to do the
|
||||
* wrapping ourselves.
|
||||
*/
|
||||
void main() {
|
||||
|
||||
/* We map the texture coordinate to [1;0], then wrap it and scale the result again */
|
||||
|
||||
float tw = u_texture_rect.z - u_texture_rect.x;
|
||||
float th = u_texture_rect.w - u_texture_rect.y;
|
||||
|
||||
float mapped_x = (vUv.x - u_texture_rect.x) / tw;
|
||||
float mapped_y = (vUv.y - u_texture_rect.y) / th;
|
||||
|
||||
float wrapped_x = wrap(mapped_x * u_child_bounds.z, 1.0);
|
||||
float wrapped_y = wrap(mapped_y * u_child_bounds.w, 1.0);
|
||||
|
||||
vec2 tp;
|
||||
tp.x = u_texture_rect.x + (wrapped_x * tw);
|
||||
tp.y = u_texture_rect.y + (wrapped_y * th);
|
||||
|
||||
vec4 diffuse = Texture(u_source, tp);
|
||||
|
||||
setOutputColor(diffuse * u_alpha);
|
||||
}
|
||||
@@ -119,12 +119,17 @@ gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline *
|
||||
|
||||
if (gi->glyph != PANGO_GLYPH_EMPTY)
|
||||
{
|
||||
double cx = (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
|
||||
double cy = (double)(gi->geometry.y_offset) / PANGO_SCALE;
|
||||
double cx = (x_position + gi->geometry.x_offset) / PANGO_SCALE;
|
||||
double cy = gi->geometry.y_offset / PANGO_SCALE;
|
||||
GskVulkanColorTextInstance *instance = &instances[count];
|
||||
GskVulkanCachedGlyph *glyph;
|
||||
|
||||
glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph, scale);
|
||||
glyph = gsk_vulkan_renderer_get_cached_glyph (renderer,
|
||||
font,
|
||||
gi->glyph,
|
||||
x_position + gi->geometry.x_offset,
|
||||
gi->geometry.y_offset,
|
||||
scale);
|
||||
|
||||
instance->tex_rect[0] = glyph->tx;
|
||||
instance->tex_rect[1] = glyph->ty;
|
||||
|
||||
@@ -115,6 +115,8 @@ gsk_vulkan_glyph_cache_class_init (GskVulkanGlyphCacheClass *klass)
|
||||
typedef struct {
|
||||
PangoFont *font;
|
||||
PangoGlyph glyph;
|
||||
guint xshift;
|
||||
guint yshift;
|
||||
guint scale; /* times 1024 */
|
||||
} GlyphCacheKey;
|
||||
|
||||
@@ -126,6 +128,8 @@ glyph_cache_equal (gconstpointer v1, gconstpointer v2)
|
||||
|
||||
return key1->font == key2->font &&
|
||||
key1->glyph == key2->glyph &&
|
||||
key1->xshift == key2->xshift &&
|
||||
key1->yshift == key2->yshift &&
|
||||
key1->scale == key2->scale;
|
||||
}
|
||||
|
||||
@@ -134,7 +138,7 @@ glyph_cache_hash (gconstpointer v)
|
||||
{
|
||||
const GlyphCacheKey *key = v;
|
||||
|
||||
return GPOINTER_TO_UINT (key->font) ^ key->glyph ^ key->scale;
|
||||
return GPOINTER_TO_UINT (key->font) ^ key->glyph ^ (key->xshift << 24) ^ (key->yshift << 26) ^ key->scale;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -267,10 +271,10 @@ render_glyph (Atlas *atlas,
|
||||
gi.glyph = key->glyph;
|
||||
gi.geometry.width = value->draw_width * 1024;
|
||||
if (key->glyph & PANGO_GLYPH_UNKNOWN_FLAG)
|
||||
gi.geometry.x_offset = 0;
|
||||
gi.geometry.x_offset = key->xshift * 256;
|
||||
else
|
||||
gi.geometry.x_offset = - value->draw_x * 1024;
|
||||
gi.geometry.y_offset = - value->draw_y * 1024;
|
||||
gi.geometry.x_offset = key->xshift * 256 - value->draw_x * 1024;
|
||||
gi.geometry.y_offset = key->yshift * 256 - value->draw_y * 1024;
|
||||
|
||||
glyphs.num_glyphs = 1;
|
||||
glyphs.glyphs = &gi;
|
||||
@@ -328,18 +332,29 @@ gsk_vulkan_glyph_cache_new (GskRenderer *renderer,
|
||||
return cache;
|
||||
}
|
||||
|
||||
#define PHASE(x) ((x % PANGO_SCALE) * 4 / PANGO_SCALE)
|
||||
|
||||
GskVulkanCachedGlyph *
|
||||
gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache,
|
||||
gboolean create,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph,
|
||||
int x,
|
||||
int y,
|
||||
float scale)
|
||||
{
|
||||
GlyphCacheKey lookup_key;
|
||||
GskVulkanCachedGlyph *value;
|
||||
guint xshift;
|
||||
guint yshift;
|
||||
|
||||
xshift = PHASE (x);
|
||||
yshift = PHASE (y);
|
||||
|
||||
lookup_key.font = font;
|
||||
lookup_key.glyph = glyph;
|
||||
lookup_key.xshift = xshift;
|
||||
lookup_key.yshift = yshift;
|
||||
lookup_key.scale = (guint)(scale * 1024);
|
||||
|
||||
value = g_hash_table_lookup (cache->hash_table, &lookup_key);
|
||||
@@ -374,6 +389,8 @@ gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache,
|
||||
|
||||
key->font = g_object_ref (font);
|
||||
key->glyph = glyph;
|
||||
key->xshift = xshift;
|
||||
key->yshift = yshift;
|
||||
key->scale = (guint)(scale * 1024);
|
||||
|
||||
if (ink_rect.width > 0 && ink_rect.height > 0)
|
||||
|
||||
@@ -22,6 +22,9 @@ GskVulkanCachedGlyph *gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache
|
||||
gboolean create,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph,
|
||||
int x,
|
||||
int y,
|
||||
|
||||
float scale);
|
||||
|
||||
void gsk_vulkan_glyph_cache_begin_frame (GskVulkanGlyphCache *cache);
|
||||
|
||||
@@ -362,15 +362,6 @@ gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self,
|
||||
return image;
|
||||
}
|
||||
|
||||
guint
|
||||
gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *self,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph,
|
||||
float scale)
|
||||
{
|
||||
return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, TRUE, font, glyph, scale)->texture_index;
|
||||
}
|
||||
|
||||
GskVulkanImage *
|
||||
gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self,
|
||||
GskVulkanUploader *uploader,
|
||||
@@ -379,13 +370,26 @@ gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self,
|
||||
return g_object_ref (gsk_vulkan_glyph_cache_get_glyph_image (self->glyph_cache, uploader, index));
|
||||
}
|
||||
|
||||
guint
|
||||
gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *self,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph,
|
||||
int x,
|
||||
int y,
|
||||
float scale)
|
||||
{
|
||||
return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, TRUE, font, glyph, x, y, scale)->texture_index;
|
||||
}
|
||||
|
||||
GskVulkanCachedGlyph *
|
||||
gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph,
|
||||
int x,
|
||||
int y,
|
||||
float scale)
|
||||
{
|
||||
return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, FALSE, font, glyph, scale);
|
||||
return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, FALSE, font, glyph, x, y, scale);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,6 +30,8 @@ typedef struct
|
||||
guint gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *renderer,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph,
|
||||
int x,
|
||||
int y,
|
||||
float scale);
|
||||
|
||||
GskVulkanImage * gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self,
|
||||
@@ -39,6 +41,8 @@ GskVulkanImage * gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *
|
||||
GskVulkanCachedGlyph * gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph,
|
||||
int x,
|
||||
int y,
|
||||
float scale);
|
||||
|
||||
|
||||
|
||||
@@ -370,6 +370,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
|
||||
int i;
|
||||
guint count;
|
||||
guint texture_index;
|
||||
gint x_position;
|
||||
GskVulkanRenderer *renderer = GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render));
|
||||
|
||||
if (font_has_color_glyphs (font))
|
||||
@@ -402,11 +403,17 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
|
||||
op.text.texture_index = G_MAXUINT;
|
||||
op.text.scale = self->scale_factor;
|
||||
|
||||
x_position = 0;
|
||||
for (i = 0, count = 0; i < num_glyphs; i++)
|
||||
{
|
||||
const PangoGlyphInfo *gi = &glyphs[i];
|
||||
|
||||
texture_index = gsk_vulkan_renderer_cache_glyph (renderer, (PangoFont *)font, gi->glyph, op.text.scale);
|
||||
texture_index = gsk_vulkan_renderer_cache_glyph (renderer,
|
||||
(PangoFont *)font,
|
||||
gi->glyph,
|
||||
x_position + gi->geometry.x_offset,
|
||||
gi->geometry.y_offset,
|
||||
op.text.scale);
|
||||
if (op.text.texture_index == G_MAXUINT)
|
||||
op.text.texture_index = texture_index;
|
||||
if (texture_index != op.text.texture_index)
|
||||
@@ -421,6 +428,8 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
|
||||
}
|
||||
else
|
||||
count++;
|
||||
|
||||
x_position += gi->geometry.width;
|
||||
}
|
||||
|
||||
if (op.text.texture_index != G_MAXUINT && count != 0)
|
||||
|
||||
@@ -127,12 +127,17 @@ gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline *pipeline,
|
||||
|
||||
if (gi->glyph != PANGO_GLYPH_EMPTY)
|
||||
{
|
||||
double cx = (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
|
||||
double cy = (double)(gi->geometry.y_offset) / PANGO_SCALE;
|
||||
double cx = (x_position + gi->geometry.x_offset) / PANGO_SCALE;
|
||||
double cy = gi->geometry.y_offset / PANGO_SCALE;
|
||||
GskVulkanTextInstance *instance = &instances[count];
|
||||
GskVulkanCachedGlyph *glyph;
|
||||
|
||||
glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph, scale);
|
||||
glyph = gsk_vulkan_renderer_get_cached_glyph (renderer,
|
||||
font,
|
||||
gi->glyph,
|
||||
x_position + gi->geometry.x_offset,
|
||||
gi->geometry.y_offset,
|
||||
scale);
|
||||
|
||||
instance->tex_rect[0] = glyph->tx;
|
||||
instance->tex_rect[1] = glyph->ty;
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
# Actual GTK things
|
||||
{
|
||||
GtkWidgetClass action GPtrArray
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
fun:g_malloc
|
||||
fun:g_slice_alloc
|
||||
fun:g_ptr_array_sized_new
|
||||
fun:g_ptr_array_new
|
||||
fun:gtk_widget_class_add_action
|
||||
}
|
||||
|
||||
{
|
||||
GTK media extension gio modules
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
fun:g_malloc
|
||||
fun:g_slice_alloc
|
||||
fun:g_slice_alloc0
|
||||
fun:g_type_create_instance
|
||||
fun:g_object_new_internal
|
||||
fun:g_object_new_with_properties
|
||||
fun:g_object_new
|
||||
fun:g_io_module_new
|
||||
fun:g_io_modules_scan_all_in_directory_with_scope
|
||||
fun:gtk_media_file_extension_init
|
||||
}
|
||||
|
||||
# mesa driver stuff
|
||||
{
|
||||
i965 addr4
|
||||
Memcheck:Addr4
|
||||
obj:/usr/lib/dri/i965_dri.so*
|
||||
}
|
||||
|
||||
{
|
||||
i965 addr8
|
||||
Memcheck:Addr8
|
||||
obj:/usr/lib/dri/i965_dri.so*
|
||||
}
|
||||
|
||||
{
|
||||
i965 memcpy
|
||||
Memcheck:Addr8
|
||||
fun:memcpy*
|
||||
obj:/usr/lib/dri/i965_dri.so*
|
||||
}
|
||||
|
||||
{
|
||||
i965 memcpy
|
||||
Memcheck:Addr2
|
||||
fun:memcpy*
|
||||
obj:/usr/lib/dri/i965_dri.so*
|
||||
}
|
||||
|
||||
{
|
||||
mesa memcmp 8
|
||||
Memcheck:Addr8
|
||||
fun:*memcmp*
|
||||
obj:/usr/lib/dri/i965_dri.so*
|
||||
}
|
||||
|
||||
{
|
||||
mesa memcmp 1
|
||||
Memcheck:Addr1
|
||||
fun:*memcmp*
|
||||
obj:/usr/lib/dri/i965_dri.so*
|
||||
}
|
||||
|
||||
{
|
||||
mesa memset 8
|
||||
Memcheck:Addr8
|
||||
fun:*memset*
|
||||
obj:/usr/lib/dri/i965_dri.so
|
||||
}
|
||||
|
||||
{
|
||||
mesa realpath
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
fun:realpath@@GLIBC_2.3
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
fun:epoxy_eglInitialize_global_rewrite_ptr
|
||||
}
|
||||
|
||||
{
|
||||
mesa calloc
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:calloc
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
fun:epoxy_eglInitialize_global_rewrite_ptr
|
||||
}
|
||||
|
||||
{
|
||||
mesa malloc
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
obj:/usr/lib/dri/i965_dri.so*
|
||||
}
|
||||
|
||||
{
|
||||
mesa glReadPixels
|
||||
Memcheck:Addr16
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
fun:epoxy_glReadPixels_global_rewrite_ptr
|
||||
}
|
||||
|
||||
{
|
||||
epoxy glxQueryServerString 1
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
fun:XextAddDisplay
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
fun:epoxy_glXQueryServerString_global_rewrite_ptr
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
epoxy glxQueryServerString 2
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
fun:realpath*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
fun:epoxy_glXQueryServerString_global_rewrite_ptr
|
||||
}
|
||||
|
||||
{
|
||||
epoxy glGetTexImage
|
||||
Memcheck:Addr16
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
fun:epoxy_glGetTexImage_global_rewrite_ptr
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
# Fontconfig
|
||||
{
|
||||
FcFontSetList
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
fun:FcFontSetList
|
||||
}
|
||||
|
||||
{
|
||||
FcFontRenderPrepare
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:realloc
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
fun:FcFontRenderPrepare
|
||||
}
|
||||
|
||||
{
|
||||
FcDefaultSubstitute
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:realloc
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
fun:FcDefaultSubstitute
|
||||
}
|
||||
|
||||
# Pixman
|
||||
{
|
||||
pixman_image_composite32
|
||||
Memcheck:Cond
|
||||
obj:/usr/lib/libpixman-1.so*
|
||||
obj:/usr/lib/libpixman-1.so*
|
||||
fun:pixman_image_composite32
|
||||
}
|
||||
|
||||
# Pango
|
||||
{
|
||||
pango 1
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:realloc
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
obj:/usr/lib/libcairo.so*
|
||||
fun:pango_cairo_fc_font_map_fontset_key_substitute
|
||||
}
|
||||
|
||||
{
|
||||
pango 2
|
||||
Memcheck:Leak
|
||||
fun:realloc
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
fun:_cairo_ft_font_options_substitute
|
||||
}
|
||||
+206
-157
@@ -23,41 +23,26 @@
|
||||
#include "gsk/gskrendernodeprivate.h"
|
||||
#include "gskpango.h"
|
||||
#include "gtksnapshotprivate.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtktextlayoutprivate.h"
|
||||
#include "gtktextviewprivate.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <pango/pango.h>
|
||||
#include <cairo.h>
|
||||
|
||||
#define GSK_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_PANGO_RENDERER, GskPangoRendererClass))
|
||||
#define GSK_IS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_PANGO_RENDERER))
|
||||
#define GSK_PANGO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_PANGO_RENDERER, GskPangoRendererClass))
|
||||
|
||||
/*
|
||||
* This is a PangoRenderer implementation that translates all the draw calls to
|
||||
* gsk render nodes, using the GtkSnapshot helper class. Glyphs are translated
|
||||
* to text nodes, all other draw calls fall back to cairo nodes.
|
||||
*/
|
||||
|
||||
struct _GskPangoRenderer
|
||||
{
|
||||
PangoRenderer parent_instance;
|
||||
|
||||
GtkSnapshot *snapshot;
|
||||
GdkRGBA fg_color;
|
||||
graphene_rect_t bounds;
|
||||
|
||||
/* house-keeping options */
|
||||
gboolean is_cached_renderer;
|
||||
};
|
||||
|
||||
struct _GskPangoRendererClass
|
||||
{
|
||||
PangoRendererClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskPangoRenderer, gsk_pango_renderer, PANGO_TYPE_RENDERER)
|
||||
|
||||
void
|
||||
gsk_pango_renderer_set_state (GskPangoRenderer *crenderer,
|
||||
GskPangoRendererState state)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_PANGO_RENDERER (crenderer));
|
||||
|
||||
crenderer->state = state;
|
||||
}
|
||||
|
||||
static void
|
||||
get_color (GskPangoRenderer *crenderer,
|
||||
PangoRenderPart part,
|
||||
@@ -101,16 +86,11 @@ set_color (GskPangoRenderer *crenderer,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_pango_renderer_show_text_glyphs (PangoRenderer *renderer,
|
||||
const char *text,
|
||||
int text_len,
|
||||
PangoGlyphString *glyphs,
|
||||
cairo_text_cluster_t *clusters,
|
||||
int num_clusters,
|
||||
gboolean backward,
|
||||
PangoFont *font,
|
||||
int x,
|
||||
int y)
|
||||
gsk_pango_renderer_draw_glyph_item (PangoRenderer *renderer,
|
||||
const char *text,
|
||||
PangoGlyphItem *glyph_item,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
GskPangoRenderer *crenderer = (GskPangoRenderer *) (renderer);
|
||||
GdkRGBA color;
|
||||
@@ -118,36 +98,13 @@ gsk_pango_renderer_show_text_glyphs (PangoRenderer *renderer,
|
||||
get_color (crenderer, PANGO_RENDER_PART_FOREGROUND, &color);
|
||||
|
||||
gtk_snapshot_append_text (crenderer->snapshot,
|
||||
font,
|
||||
glyphs,
|
||||
glyph_item->item->analysis.font,
|
||||
glyph_item->glyphs,
|
||||
&color,
|
||||
(float) x / PANGO_SCALE,
|
||||
(float) y / PANGO_SCALE);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_pango_renderer_draw_glyphs (PangoRenderer *renderer,
|
||||
PangoFont *font,
|
||||
PangoGlyphString *glyphs,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
gsk_pango_renderer_show_text_glyphs (renderer, NULL, 0, glyphs, NULL, 0, FALSE, font, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_pango_renderer_draw_glyph_item (PangoRenderer *renderer,
|
||||
const char *text,
|
||||
PangoGlyphItem *glyph_item,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
PangoFont *font = glyph_item->item->analysis.font;
|
||||
PangoGlyphString *glyphs = glyph_item->glyphs;
|
||||
|
||||
gsk_pango_renderer_show_text_glyphs (renderer, NULL, 0, glyphs, NULL, 0, FALSE, font, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_pango_renderer_draw_rectangle (PangoRenderer *renderer,
|
||||
PangoRenderPart part,
|
||||
@@ -158,15 +115,14 @@ gsk_pango_renderer_draw_rectangle (PangoRenderer *renderer,
|
||||
{
|
||||
GskPangoRenderer *crenderer = (GskPangoRenderer *) (renderer);
|
||||
GdkRGBA rgba;
|
||||
graphene_rect_t bounds;
|
||||
|
||||
get_color (crenderer, part, &rgba);
|
||||
|
||||
graphene_rect_init (&bounds,
|
||||
(double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
|
||||
(double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
|
||||
|
||||
gtk_snapshot_append_color (crenderer->snapshot, &rgba, &bounds);
|
||||
gtk_snapshot_append_color (crenderer->snapshot,
|
||||
&rgba,
|
||||
&GRAPHENE_RECT_INIT ((double)x / PANGO_SCALE,
|
||||
(double)y / PANGO_SCALE,
|
||||
(double)width / PANGO_SCALE,
|
||||
(double)height / PANGO_SCALE));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -203,78 +159,7 @@ gsk_pango_renderer_draw_trapezoid (PangoRenderer *renderer,
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
/* Draws an error underline that looks like one of:
|
||||
* H E H
|
||||
* /\ /\ /\ /\ /\ -
|
||||
* A/ \ / \ / \ A/ \ / \ |
|
||||
* \ \ / \ / /D \ \ / \ |
|
||||
* \ \/ C \/ / \ \/ C \ | height = HEIGHT_SQUARES * square
|
||||
* \ /\ F / \ F /\ \ |
|
||||
* \ / \ / \ / \ \G |
|
||||
* \ / \ / \ / \ / |
|
||||
* \/ \/ \/ \/ -
|
||||
* B B
|
||||
* |---|
|
||||
* unit_width = (HEIGHT_SQUARES - 1) * square
|
||||
*
|
||||
* The x, y, width, height passed in give the desired bounding box;
|
||||
* x/width are adjusted to make the underline a integer number of units
|
||||
* wide.
|
||||
*/
|
||||
#define HEIGHT_SQUARES 2.5
|
||||
|
||||
static void
|
||||
draw_error_underline (cairo_t *cr,
|
||||
double x,
|
||||
double y,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
double square = height / HEIGHT_SQUARES;
|
||||
double unit_width = (HEIGHT_SQUARES - 1) * square;
|
||||
double double_width = 2 * unit_width;
|
||||
int width_units = (width + unit_width / 2) / unit_width;
|
||||
double y_top, y_bottom;
|
||||
double x_left, x_middle, x_right;
|
||||
int i;
|
||||
|
||||
x += (width - width_units * unit_width) / 2;
|
||||
|
||||
y_top = y;
|
||||
y_bottom = y + height;
|
||||
|
||||
/* Bottom of squiggle */
|
||||
x_middle = x + unit_width;
|
||||
x_right = x + double_width;
|
||||
cairo_move_to (cr, x - square / 2, y_top + square / 2); /* A */
|
||||
for (i = 0; i < width_units-2; i += 2)
|
||||
{
|
||||
cairo_line_to (cr, x_middle, y_bottom); /* B */
|
||||
cairo_line_to (cr, x_right, y_top + square); /* C */
|
||||
|
||||
x_middle += double_width;
|
||||
x_right += double_width;
|
||||
}
|
||||
cairo_line_to (cr, x_middle, y_bottom); /* B */
|
||||
|
||||
if (i + 1 == width_units)
|
||||
cairo_line_to (cr, x_middle + square / 2, y_bottom - square / 2); /* G */
|
||||
else if (i + 2 == width_units) {
|
||||
cairo_line_to (cr, x_right + square / 2, y_top + square / 2); /* D */
|
||||
cairo_line_to (cr, x_right, y_top); /* E */
|
||||
}
|
||||
|
||||
/* Top of squiggle */
|
||||
x_left = x_middle - unit_width;
|
||||
for (; i >= 0; i -= 2)
|
||||
{
|
||||
cairo_line_to (cr, x_middle, y_bottom - square); /* F */
|
||||
cairo_line_to (cr, x_left, y_top); /* H */
|
||||
|
||||
x_left -= double_width;
|
||||
x_middle -= double_width;
|
||||
}
|
||||
}
|
||||
#define HEIGHT_RATIO (M_SQRT2/5.0)
|
||||
|
||||
static void
|
||||
gsk_pango_renderer_draw_error_underline (PangoRenderer *renderer,
|
||||
@@ -283,22 +168,61 @@ gsk_pango_renderer_draw_error_underline (PangoRenderer *renderer,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
GdkRGBA rgba;
|
||||
double xx, yy, ww, hh;
|
||||
double hs;
|
||||
double e, o;
|
||||
|
||||
GskPangoRenderer *crenderer = (GskPangoRenderer *) (renderer);
|
||||
cairo_t *cr;
|
||||
|
||||
cr = gtk_snapshot_append_cairo (crenderer->snapshot, &crenderer->bounds);
|
||||
xx = (double)x / PANGO_SCALE;
|
||||
yy = (double)y / PANGO_SCALE;
|
||||
ww = (double)width / PANGO_SCALE;
|
||||
hh = (double)height / PANGO_SCALE;
|
||||
hs = hh / M_SQRT2;
|
||||
|
||||
set_color (crenderer, PANGO_RENDER_PART_UNDERLINE, cr);
|
||||
e = fmod (ww - 2 * hs * HEIGHT_RATIO, hs * (1 - HEIGHT_RATIO));
|
||||
|
||||
cairo_new_path (cr);
|
||||
#if 0
|
||||
gdk_rgba_parse (&rgba, "yellow");
|
||||
gtk_snapshot_append_color (crenderer->snapshot, &rgba,
|
||||
&GRAPHENE_RECT_INIT (xx, yy, ww, hh));
|
||||
#endif
|
||||
|
||||
draw_error_underline (cr,
|
||||
(double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
|
||||
(double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
|
||||
|
||||
cairo_fill (cr);
|
||||
get_color (crenderer, PANGO_RENDER_PART_UNDERLINE, &rgba);
|
||||
gtk_snapshot_save (crenderer->snapshot);
|
||||
gtk_snapshot_translate (crenderer->snapshot,
|
||||
&GRAPHENE_POINT_INIT (xx, yy));
|
||||
|
||||
cairo_destroy (cr);
|
||||
gtk_snapshot_rotate (crenderer->snapshot, 45);
|
||||
gtk_snapshot_translate (crenderer->snapshot,
|
||||
&GRAPHENE_POINT_INIT (e / 2 + hs * HEIGHT_RATIO,
|
||||
- hs * HEIGHT_RATIO));
|
||||
|
||||
xx = yy = o = 0;
|
||||
while (1)
|
||||
{
|
||||
if (o + hs * (1 + HEIGHT_RATIO) >= ww)
|
||||
break;
|
||||
|
||||
gtk_snapshot_append_color (crenderer->snapshot, &rgba,
|
||||
&GRAPHENE_RECT_INIT (xx, yy, hh, hh * HEIGHT_RATIO));
|
||||
|
||||
xx += hh * (1 - HEIGHT_RATIO);
|
||||
yy -= hh * (1 - HEIGHT_RATIO);
|
||||
o += hs * (1 - HEIGHT_RATIO);
|
||||
|
||||
if (o + hs * (1 + HEIGHT_RATIO) >= ww)
|
||||
break;
|
||||
|
||||
gtk_snapshot_append_color (crenderer->snapshot, &rgba,
|
||||
&GRAPHENE_RECT_INIT (xx, yy, hh * HEIGHT_RATIO, hh));
|
||||
|
||||
o += hs * (1 - HEIGHT_RATIO);
|
||||
}
|
||||
|
||||
gtk_snapshot_restore (crenderer->snapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -336,6 +260,124 @@ gsk_pango_renderer_draw_shape (PangoRenderer *renderer,
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
text_renderer_set_rgba (GskPangoRenderer *crenderer,
|
||||
PangoRenderPart part,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
PangoRenderer *renderer = PANGO_RENDERER (crenderer);
|
||||
PangoColor color = { 0, };
|
||||
guint16 alpha;
|
||||
|
||||
if (rgba)
|
||||
{
|
||||
color.red = (guint16)(rgba->red * 65535);
|
||||
color.green = (guint16)(rgba->green * 65535);
|
||||
color.blue = (guint16)(rgba->blue * 65535);
|
||||
alpha = (guint16)(rgba->alpha * 65535);
|
||||
pango_renderer_set_color (renderer, part, &color);
|
||||
pango_renderer_set_alpha (renderer, part, alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
pango_renderer_set_color (renderer, part, NULL);
|
||||
pango_renderer_set_alpha (renderer, part, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static GtkTextAppearance *
|
||||
get_item_appearance (PangoItem *item)
|
||||
{
|
||||
GSList *tmp_list = item->analysis.extra_attrs;
|
||||
|
||||
while (tmp_list)
|
||||
{
|
||||
PangoAttribute *attr = tmp_list->data;
|
||||
|
||||
if (attr->klass->type == gtk_text_attr_appearance_type)
|
||||
return &((GtkTextAttrAppearance *)attr)->appearance;
|
||||
|
||||
tmp_list = tmp_list->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_pango_renderer_prepare_run (PangoRenderer *renderer,
|
||||
PangoLayoutRun *run)
|
||||
{
|
||||
GtkStyleContext *context;
|
||||
GskPangoRenderer *crenderer = GSK_PANGO_RENDERER (renderer);
|
||||
GdkRGBA *bg_rgba = NULL;
|
||||
GdkRGBA *fg_rgba = NULL;
|
||||
GtkTextAppearance *appearance;
|
||||
|
||||
PANGO_RENDERER_CLASS (gsk_pango_renderer_parent_class)->prepare_run (renderer, run);
|
||||
|
||||
appearance = get_item_appearance (run->item);
|
||||
|
||||
if (appearance == NULL)
|
||||
return;
|
||||
|
||||
context = gtk_widget_get_style_context (crenderer->widget);
|
||||
|
||||
if (appearance->draw_bg && crenderer->state == GSK_PANGO_RENDERER_NORMAL)
|
||||
bg_rgba = appearance->bg_rgba;
|
||||
else
|
||||
bg_rgba = NULL;
|
||||
|
||||
text_renderer_set_rgba (crenderer, PANGO_RENDER_PART_BACKGROUND, bg_rgba);
|
||||
|
||||
if (crenderer->state == GSK_PANGO_RENDERER_SELECTED &&
|
||||
GTK_IS_TEXT_VIEW (crenderer->widget))
|
||||
{
|
||||
GtkCssNode *selection_node;
|
||||
|
||||
selection_node = gtk_text_view_get_selection_node ((GtkTextView *)crenderer->widget);
|
||||
gtk_style_context_save_to_node (context, selection_node);
|
||||
|
||||
gtk_style_context_get (context,
|
||||
"color", &fg_rgba,
|
||||
NULL);
|
||||
|
||||
gtk_style_context_restore (context);
|
||||
}
|
||||
else if (crenderer->state == GSK_PANGO_RENDERER_CURSOR && gtk_widget_has_focus (crenderer->widget))
|
||||
{
|
||||
gtk_style_context_get (context,
|
||||
"background-color", &fg_rgba,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
fg_rgba = appearance->fg_rgba;
|
||||
|
||||
text_renderer_set_rgba (crenderer, PANGO_RENDER_PART_FOREGROUND, fg_rgba);
|
||||
|
||||
if (appearance->strikethrough_rgba)
|
||||
text_renderer_set_rgba (crenderer, PANGO_RENDER_PART_STRIKETHROUGH, appearance->strikethrough_rgba);
|
||||
else
|
||||
text_renderer_set_rgba (crenderer, PANGO_RENDER_PART_STRIKETHROUGH, fg_rgba);
|
||||
|
||||
if (appearance->underline_rgba)
|
||||
text_renderer_set_rgba (crenderer, PANGO_RENDER_PART_UNDERLINE, appearance->underline_rgba);
|
||||
else if (appearance->underline == PANGO_UNDERLINE_ERROR)
|
||||
{
|
||||
if (!crenderer->error_color)
|
||||
{
|
||||
static const GdkRGBA red = { 1, 0, 0, 1 };
|
||||
crenderer->error_color = gdk_rgba_copy (&red);
|
||||
}
|
||||
|
||||
text_renderer_set_rgba (crenderer, PANGO_RENDER_PART_UNDERLINE, crenderer->error_color);
|
||||
}
|
||||
else
|
||||
text_renderer_set_rgba (crenderer, PANGO_RENDER_PART_UNDERLINE, fg_rgba);
|
||||
|
||||
if (fg_rgba != appearance->fg_rgba)
|
||||
gdk_rgba_free (fg_rgba);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_pango_renderer_init (GskPangoRenderer *renderer G_GNUC_UNUSED)
|
||||
{
|
||||
@@ -346,19 +388,19 @@ gsk_pango_renderer_class_init (GskPangoRendererClass *klass)
|
||||
{
|
||||
PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
|
||||
|
||||
renderer_class->draw_glyphs = gsk_pango_renderer_draw_glyphs;
|
||||
renderer_class->draw_glyph_item = gsk_pango_renderer_draw_glyph_item;
|
||||
renderer_class->draw_rectangle = gsk_pango_renderer_draw_rectangle;
|
||||
renderer_class->draw_trapezoid = gsk_pango_renderer_draw_trapezoid;
|
||||
renderer_class->draw_error_underline = gsk_pango_renderer_draw_error_underline;
|
||||
renderer_class->draw_shape = gsk_pango_renderer_draw_shape;
|
||||
renderer_class->prepare_run = gsk_pango_renderer_prepare_run;
|
||||
}
|
||||
|
||||
static GskPangoRenderer *cached_renderer = NULL; /* MT-safe */
|
||||
G_LOCK_DEFINE_STATIC (cached_renderer);
|
||||
|
||||
static GskPangoRenderer *
|
||||
acquire_renderer (void)
|
||||
GskPangoRenderer *
|
||||
gsk_pango_renderer_acquire (void)
|
||||
{
|
||||
GskPangoRenderer *renderer;
|
||||
|
||||
@@ -380,13 +422,20 @@ acquire_renderer (void)
|
||||
return renderer;
|
||||
}
|
||||
|
||||
static void
|
||||
release_renderer (GskPangoRenderer *renderer)
|
||||
void
|
||||
gsk_pango_renderer_release (GskPangoRenderer *renderer)
|
||||
{
|
||||
if (G_LIKELY (renderer->is_cached_renderer))
|
||||
{
|
||||
renderer->widget = NULL;
|
||||
renderer->snapshot = NULL;
|
||||
|
||||
if (renderer->error_color)
|
||||
{
|
||||
gdk_rgba_free (renderer->error_color);
|
||||
renderer->error_color = NULL;
|
||||
}
|
||||
|
||||
G_UNLOCK (cached_renderer);
|
||||
}
|
||||
else
|
||||
@@ -414,7 +463,7 @@ gtk_snapshot_append_layout (GtkSnapshot *snapshot,
|
||||
g_return_if_fail (snapshot != NULL);
|
||||
g_return_if_fail (PANGO_IS_LAYOUT (layout));
|
||||
|
||||
crenderer = acquire_renderer ();
|
||||
crenderer = gsk_pango_renderer_acquire ();
|
||||
|
||||
crenderer->snapshot = snapshot;
|
||||
crenderer->fg_color = *color;
|
||||
@@ -424,5 +473,5 @@ gtk_snapshot_append_layout (GtkSnapshot *snapshot,
|
||||
|
||||
pango_renderer_draw_layout (PANGO_RENDERER (crenderer), layout, 0, 0);
|
||||
|
||||
release_renderer (crenderer);
|
||||
gsk_pango_renderer_release (crenderer);
|
||||
}
|
||||
|
||||
+48
-6
@@ -24,15 +24,57 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_PANGO_RENDERER (gsk_pango_renderer_get_type ())
|
||||
#define GSK_TYPE_PANGO_RENDERER (gsk_pango_renderer_get_type ())
|
||||
#define GSK_PANGO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_PANGO_RENDERER, GskPangoRenderer))
|
||||
#define GSK_IS_PANGO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_PANGO_RENDERER))
|
||||
#define GSK_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_PANGO_RENDERER, GskPangoRendererClass))
|
||||
#define GSK_IS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_PANGO_RENDERER))
|
||||
#define GSK_PANGO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_PANGO_RENDERER, GskPangoRendererClass))
|
||||
|
||||
#define GSK_PANGO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_PANGO_RENDERER, GskPangoRenderer))
|
||||
#define GSK_IS_PANGO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_PANGO_RENDERER))
|
||||
typedef struct _GskPangoRenderer GskPangoRenderer;
|
||||
typedef struct _GskPangoRendererClass GskPangoRendererClass;
|
||||
|
||||
typedef struct _GskPangoRenderer GskPangoRenderer;
|
||||
typedef struct _GskPangoRendererClass GskPangoRendererClass;
|
||||
typedef enum
|
||||
{
|
||||
GSK_PANGO_RENDERER_NORMAL,
|
||||
GSK_PANGO_RENDERER_SELECTED,
|
||||
GSK_PANGO_RENDERER_CURSOR
|
||||
} GskPangoRendererState;
|
||||
|
||||
GType gsk_pango_renderer_get_type (void) G_GNUC_CONST;
|
||||
/*
|
||||
* This is a PangoRenderer implementation that translates all the draw calls to
|
||||
* gsk render nodes, using the GtkSnapshot helper class. Glyphs are translated
|
||||
* to text nodes, all other draw calls fall back to cairo nodes.
|
||||
*/
|
||||
|
||||
struct _GskPangoRenderer
|
||||
{
|
||||
PangoRenderer parent_instance;
|
||||
|
||||
GtkWidget *widget;
|
||||
GtkSnapshot *snapshot;
|
||||
GdkRGBA fg_color;
|
||||
graphene_rect_t bounds;
|
||||
|
||||
/* Error underline color for this widget */
|
||||
GdkRGBA *error_color;
|
||||
|
||||
GskPangoRendererState state;
|
||||
|
||||
/* house-keeping options */
|
||||
guint is_cached_renderer : 1;
|
||||
};
|
||||
|
||||
struct _GskPangoRendererClass
|
||||
{
|
||||
PangoRendererClass parent_class;
|
||||
};
|
||||
|
||||
GType gsk_pango_renderer_get_type (void) G_GNUC_CONST;
|
||||
void gsk_pango_renderer_set_state (GskPangoRenderer *crenderer,
|
||||
GskPangoRendererState state);
|
||||
GskPangoRenderer *gsk_pango_renderer_acquire (void);
|
||||
void gsk_pango_renderer_release (GskPangoRenderer *crenderer);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
#include <gtk/gtkcolorutils.h>
|
||||
#include <gtk/gtkcombobox.h>
|
||||
#include <gtk/gtkcomboboxtext.h>
|
||||
#include <gtk/gtkconstraintlayout.h>
|
||||
#include <gtk/gtkconstraint.h>
|
||||
#include <gtk/gtkcontainer.h>
|
||||
#include <gtk/gtkcssprovider.h>
|
||||
#include <gtk/gtkcustomlayout.h>
|
||||
|
||||
+22
-1
@@ -373,7 +373,8 @@ gtk_accel_label_finalize (GObject *object)
|
||||
* Fetches the widget monitored by this accelerator label. See
|
||||
* gtk_accel_label_set_accel_widget().
|
||||
*
|
||||
* Returns: (nullable) (transfer none): the object monitored by the accelerator label, or %NULL.
|
||||
* Returns: (nullable) (transfer none): the widget monitored by @accel_label,
|
||||
* or %NULL if it is not monitoring a widget.
|
||||
**/
|
||||
GtkWidget *
|
||||
gtk_accel_label_get_accel_widget (GtkAccelLabel *accel_label)
|
||||
@@ -561,6 +562,26 @@ gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_accel_label_get_accel_closure:
|
||||
* @accel_label: a #GtkAccelLabel
|
||||
*
|
||||
* Fetches the closure monitored by this accelerator label. See
|
||||
* gtk_accel_label_set_accel_closure().
|
||||
*
|
||||
* Returns: (nullable) (transfer none): the closure monitored by @accel_label,
|
||||
* or %NULL if it is not monitoring a closure.
|
||||
*/
|
||||
GClosure *
|
||||
gtk_accel_label_get_accel_closure (GtkAccelLabel *accel_label)
|
||||
{
|
||||
GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
|
||||
|
||||
g_return_val_if_fail (GTK_IS_ACCEL_LABEL (accel_label), NULL);
|
||||
|
||||
return priv->accel_closure;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
find_accel (GtkAccelKey *key,
|
||||
GClosure *closure,
|
||||
|
||||
+6
-4
@@ -44,17 +44,19 @@ typedef struct _GtkAccelLabel GtkAccelLabel;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gtk_accel_label_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget* gtk_accel_label_new (const gchar *string);
|
||||
GtkWidget *gtk_accel_label_new (const gchar *string);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget* gtk_accel_label_get_accel_widget (GtkAccelLabel *accel_label);
|
||||
GtkWidget *gtk_accel_label_get_accel_widget (GtkAccelLabel *accel_label);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
guint gtk_accel_label_get_accel_width (GtkAccelLabel *accel_label);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label,
|
||||
GtkWidget *accel_widget);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label,
|
||||
GClosure *accel_closure);
|
||||
void gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label,
|
||||
GClosure *accel_closure);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GClosure * gtk_accel_label_get_accel_closure (GtkAccelLabel *accel_label);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_accel_label_refetch (GtkAccelLabel *accel_label);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
||||
+21
-5
@@ -155,6 +155,16 @@ accel_entry_equal (gconstpointer key1,
|
||||
return g_str_equal (entry1->accel_path, entry2->accel_path);
|
||||
}
|
||||
|
||||
static int
|
||||
accel_entry_compare (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
const AccelEntry *entry1 = a;
|
||||
const AccelEntry *entry2 = b;
|
||||
|
||||
return strcmp (entry1->accel_path, entry2->accel_path);
|
||||
}
|
||||
|
||||
static inline AccelEntry*
|
||||
accel_path_lookup (const gchar *accel_path)
|
||||
{
|
||||
@@ -817,17 +827,23 @@ gtk_accel_map_foreach (gpointer data,
|
||||
g_return_if_fail (foreach_func != NULL);
|
||||
|
||||
entries = g_hash_table_slist_values (accel_entry_ht);
|
||||
entries = g_slist_sort (entries, accel_entry_compare);
|
||||
|
||||
for (slist = entries; slist; slist = slist->next)
|
||||
{
|
||||
AccelEntry *entry = slist->data;
|
||||
gboolean changed = entry->accel_key != entry->std_accel_key || entry->accel_mods != entry->std_accel_mods;
|
||||
gboolean skip = FALSE;
|
||||
|
||||
for (node = accel_filters; node; node = node->next)
|
||||
if (g_pattern_match_string (node->data, entry->accel_path))
|
||||
goto skip_accel;
|
||||
foreach_func (data, entry->accel_path, entry->accel_key, entry->accel_mods, changed);
|
||||
skip_accel:
|
||||
/* noop */;
|
||||
if (g_pattern_match_string (node->data, entry->accel_path))
|
||||
{
|
||||
skip = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!skip)
|
||||
foreach_func (data, entry->accel_path, entry->accel_key, entry->accel_mods, changed);
|
||||
}
|
||||
g_slist_free (entries);
|
||||
}
|
||||
|
||||
@@ -561,13 +561,6 @@ prop_actions_connect (GtkActionMuxer *muxer)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
prop_actions_disconnect (GtkActionMuxer *muxer)
|
||||
{
|
||||
if (muxer->widget)
|
||||
g_signal_handlers_disconnect_by_func (muxer->widget,
|
||||
prop_action_notify, muxer);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_action_muxer_query_action (GActionGroup *action_group,
|
||||
@@ -810,6 +803,8 @@ gtk_action_muxer_finalize (GObject *object)
|
||||
if (muxer->primary_accels)
|
||||
g_hash_table_unref (muxer->primary_accels);
|
||||
|
||||
g_free (muxer->widget_actions_enabled);
|
||||
|
||||
G_OBJECT_CLASS (gtk_action_muxer_parent_class)
|
||||
->finalize (object);
|
||||
}
|
||||
@@ -819,8 +814,6 @@ gtk_action_muxer_dispose (GObject *object)
|
||||
{
|
||||
GtkActionMuxer *muxer = GTK_ACTION_MUXER (object);
|
||||
|
||||
prop_actions_disconnect (muxer);
|
||||
|
||||
if (muxer->parent)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, gtk_action_muxer_action_added_to_parent, muxer);
|
||||
|
||||
+3
-4
@@ -131,9 +131,9 @@
|
||||
*
|
||||
* It is also possible to bind a property value to another object's
|
||||
* property value using the attributes
|
||||
* "bind-source" to specify the source object of the binding,
|
||||
* "bind-property" to specify the source property and optionally
|
||||
* "bind-flags" to specify the binding flags
|
||||
* "bind-source" to specify the source object of the binding, and
|
||||
* optionally, "bind-property" and "bind-flags" to specify the
|
||||
* source property and source binding flags respectively.
|
||||
* Internally builder implement this using GBinding objects.
|
||||
* For more information see g_object_bind_property()
|
||||
*
|
||||
@@ -289,7 +289,6 @@ gtk_builder_init (GtkBuilder *builder)
|
||||
{
|
||||
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
|
||||
|
||||
priv = gtk_builder_get_instance_private (builder);
|
||||
priv->domain = NULL;
|
||||
priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_object_unref);
|
||||
|
||||
@@ -598,7 +598,7 @@ parse_property (ParserData *data,
|
||||
|
||||
g_markup_parse_context_get_position (data->ctx, &line, &col);
|
||||
|
||||
if (bind_source && bind_property)
|
||||
if (bind_source)
|
||||
{
|
||||
BindingInfo *binfo;
|
||||
|
||||
@@ -606,17 +606,17 @@ parse_property (ParserData *data,
|
||||
binfo->target = NULL;
|
||||
binfo->target_pspec = pspec;
|
||||
binfo->source = g_strdup (bind_source);
|
||||
binfo->source_property = g_strdup (bind_property);
|
||||
binfo->source_property = bind_property ? g_strdup (bind_property) : g_strdup (name);
|
||||
binfo->flags = bind_flags;
|
||||
binfo->line = line;
|
||||
binfo->col = col;
|
||||
|
||||
object_info->bindings = g_slist_prepend (object_info->bindings, binfo);
|
||||
}
|
||||
else if (bind_source || bind_property)
|
||||
else if (bind_property)
|
||||
{
|
||||
error_missing_attribute (data, element_name,
|
||||
(bind_source) ? "bind-property" : "bind-source",
|
||||
"bind-source",
|
||||
error);
|
||||
return;
|
||||
}
|
||||
@@ -626,7 +626,7 @@ parse_property (ParserData *data,
|
||||
info->pspec = pspec;
|
||||
info->text = g_string_new ("");
|
||||
info->translatable = translatable;
|
||||
info->bound = (bind_source && bind_property);
|
||||
info->bound = bind_source != NULL;
|
||||
info->context = g_strdup (context);
|
||||
info->line = line;
|
||||
info->col = col;
|
||||
|
||||
+2
-2
@@ -3474,7 +3474,7 @@ gtk_calendar_set_detail_width_chars (GtkCalendar *calendar,
|
||||
{
|
||||
priv->detail_width_chars = chars;
|
||||
g_object_notify (G_OBJECT (calendar), "detail-width-chars");
|
||||
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (calendar));
|
||||
gtk_widget_queue_resize (GTK_WIDGET (calendar));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3498,7 +3498,7 @@ gtk_calendar_set_detail_height_rows (GtkCalendar *calendar,
|
||||
{
|
||||
priv->detail_height_rows = rows;
|
||||
g_object_notify (G_OBJECT (calendar), "detail-height-rows");
|
||||
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (calendar));
|
||||
gtk_widget_queue_resize (GTK_WIDGET (calendar));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -1212,13 +1212,13 @@ apply_cell_attributes (GtkCellRenderer *renderer,
|
||||
* provided by the view (as these states can vary across views
|
||||
* accessing the same model).
|
||||
*/
|
||||
g_object_get (renderer, "is-expander", &is_expander, NULL);
|
||||
is_expander = gtk_cell_renderer_get_is_expander (renderer);
|
||||
if (is_expander != data->is_expander)
|
||||
g_object_set (renderer, "is-expander", data->is_expander, NULL);
|
||||
gtk_cell_renderer_set_is_expander (renderer, data->is_expander);
|
||||
|
||||
g_object_get (renderer, "is-expanded", &is_expanded, NULL);
|
||||
is_expanded = gtk_cell_renderer_get_is_expanded (renderer);
|
||||
if (is_expanded != data->is_expanded)
|
||||
g_object_set (renderer, "is-expanded", data->is_expanded, NULL);
|
||||
gtk_cell_renderer_set_is_expanded (renderer, data->is_expanded);
|
||||
|
||||
/* Apply the attributes directly to the renderer */
|
||||
for (list = info->attributes; list; list = list->next)
|
||||
|
||||
@@ -1722,6 +1722,62 @@ gtk_cell_renderer_get_state (GtkCellRenderer *cell,
|
||||
return state;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_cell_renderer_set_is_expander (GtkCellRenderer *cell,
|
||||
gboolean is_expander)
|
||||
{
|
||||
GtkCellRendererPrivate *priv = gtk_cell_renderer_get_instance_private (cell);
|
||||
|
||||
g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
|
||||
|
||||
is_expander = !!is_expander;
|
||||
|
||||
if (is_expander != priv->is_expander)
|
||||
{
|
||||
priv->is_expander = is_expander;
|
||||
|
||||
g_object_notify (G_OBJECT (cell), "is-expander");
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_cell_renderer_get_is_expander (GtkCellRenderer *cell)
|
||||
{
|
||||
GtkCellRendererPrivate *priv = gtk_cell_renderer_get_instance_private (cell);
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CELL_RENDERER (cell), FALSE);
|
||||
|
||||
return priv->is_expander;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_cell_renderer_set_is_expanded (GtkCellRenderer *cell,
|
||||
gboolean is_expanded)
|
||||
{
|
||||
GtkCellRendererPrivate *priv = gtk_cell_renderer_get_instance_private (cell);
|
||||
|
||||
g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
|
||||
|
||||
is_expanded = !!is_expanded;
|
||||
|
||||
if (is_expanded != priv->is_expanded)
|
||||
{
|
||||
priv->is_expanded = is_expanded;
|
||||
|
||||
g_object_notify (G_OBJECT (cell), "is-expanded");
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_cell_renderer_get_is_expanded (GtkCellRenderer *cell)
|
||||
{
|
||||
GtkCellRendererPrivate *priv = gtk_cell_renderer_get_instance_private (cell);
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CELL_RENDERER (cell), FALSE);
|
||||
|
||||
return priv->is_expanded;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_cell_renderer_class_set_accessible_type:
|
||||
* @renderer_class: class to set the accessible type for
|
||||
|
||||
@@ -283,6 +283,21 @@ gboolean gtk_cell_renderer_get_sensitive (GtkCellRenderer *cell);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_cell_renderer_is_activatable (GtkCellRenderer *cell);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_cell_renderer_set_is_expander (GtkCellRenderer *cell,
|
||||
gboolean is_expander);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_cell_renderer_get_is_expander (GtkCellRenderer *cell);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_cell_renderer_set_is_expanded (GtkCellRenderer *cell,
|
||||
gboolean is_expander);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_cell_renderer_get_is_expanded (GtkCellRenderer *cell);
|
||||
|
||||
|
||||
|
||||
|
||||
/* For use by cell renderer implementations only */
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_cell_renderer_stop_editing (GtkCellRenderer *cell,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user