Compare commits

...

553 Commits

Author SHA1 Message Date
Emmanuele Bassi 258233efa9 WIP: Import the GTK 2 treeview tutorial
The tree view tutorial at http://scentric.net/tutorial should be part of
the GTK API reference.

This is a work in progress import; the tutorial needs heavy editing, and
the overall state of the docbook markup is pretty dire.
2019-01-14 15:49:45 +00:00
Timm Bäder 59bf76dce1 gl renderer: Force blur shadow node children offscreen
This broke the overlay blur demoe when resizing the window to a size
that would completely move the image below a button, causing the
GtkSnapshot code to remove the clip node below the blur node.
2019-01-13 08:41:37 +01:00
Timm Bäder 44a2a49f31 overlay: Directly create cairo_region
Instead of doing a cairo_region_create + union, just pass the rect
directly to cairo_region_create_rectangle
2019-01-13 08:41:37 +01:00
Timm Bäder 69bc42f444 rendernodepaintable: Don't try to snapshot 0×0 nodes
Considering the operations that some of the rendernode constructors
do, nodes with width or height 0 (or both of course) are very well
possible. This would break in the rendernodepaintable when adding a
transform, which divides by width/height of the rendernode.
2019-01-13 08:39:05 +01:00
Timm Bäder 269535c844 overlay: Blur the clipped node, not clip the blurred node
Blurring is a lot more expensive than clipping, so try to blur less by
clipping first.
2019-01-13 08:23:25 +01:00
Timm Bäder c7f773f3e3 overlay: Trivial indentation fix 2019-01-13 08:23:25 +01:00
Timm Bäder c6da0c9a7a demo: Fix tranparency overlay demo
We'd like the rose picture to be bigger than 16×16. Also remove the
scrolledwindow since the GtkPicture now automatically scales down the
rose image. This also fixes the picture always being allocated at y=0.
2019-01-13 08:23:25 +01:00
Timm Bäder d098cd5865 overlay: Don't offset the main window snapshot
We need the node without an offset applied.

Fixes the rose picture being offset in tests/testoverlay
2019-01-13 08:23:25 +01:00
Timm Bäder 4dc8ab58a3 testoverlay: Re-enable blurring
Accidentally disabled in 8b14c8d0a8
2019-01-13 08:23:25 +01:00
Timm Bäder 5680393f9d label: Add missing nullable annotation 2019-01-13 08:23:25 +01:00
Piotr Drąg aadcec3d1e Update Polish translation 2019-01-12 13:19:35 +01:00
Timm Bäder 5fd936beef spinbutton: Use increment/decrement icon names
And add list-{remove,add}-symbolic as fallback.

Fixes #1569
2019-01-11 18:29:20 +01:00
Timm Bäder 563b80d434 label: Skip updating link state if we have no layout
This can happen whenever the ::activate-link handler sets different
markup on the label, causing all links to be recreated. In this case,
the GtkLabelLink* passed to emit_activate_link is garbage after the
g_signal_emit call and we shouldn't try to do anything with it.

Fixes #1498
2019-01-11 17:46:12 +01:00
Timm Bäder f4f0f0e6a0 snapshot: Get new GArray item directly
Instead of building it up ourselves, then coping it into the GArray and
then getting the last element of that array.
2019-01-11 17:02:23 +01:00
Emmanuele Bassi ba9b0c6f7d Use the IEC power symbols for GtkSwitch labels
Unicode 9.0 introduced glyps for the "on" and "off" power states, in the
form of:

 - U+23FD POWER ON SYMBOL, or ⏽
 - U+2B58 HEAVY CIRCLE, or ⭘

With `HEAVY CIRCLE` as "power off symbol" selected to avoid adding yet
another circle to the standard.

Since we moved GtkSwitch to always show glyphs instead of (translatable)
strings, asking the localisation teams to either come up with a suitable
short string to replace the English "ON" and "OFF", or to fall back to
Unicode glyphs, we should ensure we're using the appropriate symbols to
begin with.

See also: gtk!503 for the corresponding gtk-3-24 change.
2019-01-11 15:25:30 +00:00
Timm Bäder 3ce3de98da Merge branch 'wip/muktupavels/listbox-master' into 'master'
listbox: set selected_row before emitting signal

See merge request GNOME/gtk!502
2019-01-11 11:38:27 +00:00
Alberts Muktupāvels 1cd934e105 listbox: set selected_row before emitting signal
Signal emittion was added in 6f857f87dc commit and it seems that
this is only place where selected_row is set after emitting signal.

Because of this gtk_list_box_get_selected_row currently returns NULL
as selected row if selection mode is set to GTK_SELECTION_BROWSE.
2019-01-11 13:19:28 +02:00
Timm Bäder dc1d3824a2 Merge branch 'wip/dboles/EventControllerKey-docs-4' into 'master'
EventControllerKey: Add missing documentation bits

See merge request GNOME/gtk!454
2019-01-11 09:39:25 +00:00
Matthias Clasen 927e49ed86 switch: Always use I/O
This allows for smaller switches, and goes better with
modern themes that have round switches.
2019-01-10 17:21:48 -05:00
Timm Bäder d55fc8b7b1 gl renderer: Dont't try to draw glyphs at scale 0
Fixes #1475
2019-01-10 17:14:48 +01:00
Timm Bäder e72d0a9118 gl glyphcache: Only support one dirty glyph per atlas 2019-01-10 16:49:19 +01:00
Timm Bäder 8b14c8d0a8 testoverlay: Fix fancy effect 2019-01-10 16:49:19 +01:00
Timm Bäder 913b4fcc49 iconcache: Remove unused defines 2019-01-10 16:49:19 +01:00
Timm Bäder fb7d033953 gl renderer: Remove debug code 2019-01-10 16:49:19 +01:00
Timm Bäder cfa440bbae gl renderer: Fix hidpi transform nodes 2019-01-10 16:49:19 +01:00
Timm Bäder 7ac9fe3b60 shadowvalue: Remove unused API 2019-01-10 16:49:19 +01:00
Timm Bäder b0a8b7da63 gl renderer: Only compile the vertex shader once
All our programs use the same vertex shader, so don't compile it over
and over again. This improves startup times by at least 0.001%, I swear.
2019-01-10 16:49:19 +01:00
Timm Bäder b2ff6e91cd gl renderer: Don't forget the offset when rendering blur nodes 2019-01-10 16:49:19 +01:00
Daniel Mustieles b4d906c464 Update Spanish translation 2019-01-10 08:50:55 +00:00
Timm Bäder ae03caacc4 Merge branch 'patch-1' into 'master'
Fix a typo in “popup-context-menu” documentation.

See merge request GNOME/gtk!500
2019-01-10 06:23:09 +00:00
bodqhrohro ec22646210 Fix a typo in “popup-context-menu” documentation. 2019-01-09 14:24:29 +00:00
Timm Bäder ba1644cba1 Merge branch 'wip/sadiq/750-gtk4' into 'master'
gtkpopover: Fix popover when parent widget is partially visible

Closes #750

See merge request GNOME/gtk!496
2019-01-09 11:53:45 +00:00
Mohammed Sadiq d11bc68b27 gtkpopover: Fix popover when parent widget is partially visible
fixes https://gitlab.gnome.org/GNOME/gtk/issues/750
2019-01-09 17:12:23 +05:30
Daniel Mustieles 5720e406b9 Updated Spanish translation 2019-01-09 09:52:53 +01:00
Emmanuele Bassi b3f8f358b5 Merge branch 'meson-warning' into 'master'
build: Avoid a Meson deprecation warning

See merge request GNOME/gtk!493
2019-01-08 14:59:21 +00:00
Emmanuele Bassi e458ea2f3d build: Avoid a Meson deprecation warning
Using an empty `configuration_data` object to copy a configuration file
is deprecated since Meson 0.47 (released July 2018); the equivalent
behaviour is available by using `copy: true`.
2019-01-08 14:46:46 +00:00
Benjamin Otte b6d8d3975e revealer: Handle child-visible properly
The target position is irrelevant for determining if the child should be
visible. When the current position is 0, it needs to be hidden, period.

Fixes #1355
2019-01-08 01:29:41 +01:00
Benjamin Otte 5e96129be1 settings: Don't special case IM modules
The previous fixes made it unnecessary to hardcode IM modules for
different display types. The code now automatically skips system IM
modules for other displays.
2019-01-08 00:41:12 +01:00
Benjamin Otte 0ef7d07880 immodule: Check if module matches display
When loading IM modules from environment variables or GtkSettings, we
would accept "xim" on Wayland. That is a bad idea.
2019-01-08 00:41:12 +01:00
Benjamin Otte 545e95bb5c immodule: Don't load unsupported IM module
The code would technically allow loading the xim module when X11 support
was not compiled in.

This is probably an artificial concern, because it's pretty hard to
compile XIM support without X11 support, but it makes the code clearer,
so there we go.
2019-01-08 00:41:12 +01:00
Benjamin Otte ca76675a69 immodule: Pass a GdkDisplay for default context ID
After all, the context depends on the display - we want to use the
wayland context for Wayland,  xim for X11 and so on.
2019-01-08 00:41:12 +01:00
Benjamin Otte 16d4ce4d03 immulticontext: Don't have a global_context_id
Context IDs are dependant on the display - both because displays can use
different backends, but also because changing the GtkSetting is a
per-display operation.

So just remove the cache.
If it turns out we need a per-display cache, we can add one to
GtkSettings.
2019-01-08 00:41:12 +01:00
Olivier Fourdan 58e273d056 a11y: Check display in *grab_cell_focus()
Calling the accessibility function `grab_focus()` on a `GtkCell` under
Wayland will cause the client to crash.

This is another case of `gdk_x11_get_server_time()` being called
regardless of the actual windowing backend used.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1507
2019-01-07 21:06:57 +00:00
Carlos Garnacho 1c14285dee flowbox: Accept multipress gesture late
So it's able to operate properly with the DnD gesture set by
gtk_drag_source_set(). We usually just react on button release,
that's the right time to claim the gesture.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1557
2019-01-07 21:01:59 +00:00
Daniel Boles cd69570e78 searchenginequartz: Fix naming of Beagle @ comment
As funny as that is, it's not very instructive. :P

https://gitlab.gnome.org/GNOME/gtk/merge_requests/490#note_400993
2019-01-07 20:46:08 +00:00
John Ralls 52b9e4703b [GtkSearchEngineQuartz] Limit the returned hits.
When the result set is larger than the limit.
2019-01-07 20:46:08 +00:00
Daniel Boles d7193eaf8b [GtkSearchEngineQuartz] Resolve the path to a GtkFile* for the hit list.
Instead of a char* path, which the search_hit parser doesn't expect,
causing a crash.

Closes: $https://gitlab.gnome.org/GNOME/gtk/issues/815
2019-01-07 20:46:08 +00:00
Carlos Garnacho b52dea7a10 Merge branch 'fix-corner-resize' into 'master'
Fix resize corners

See merge request GNOME/gtk!481
2019-01-07 18:14:33 +00:00
Matthias Clasen 7bb5888272 Merge branch 'commit-docs' into 'master'
docs: Move commit style docs to the contribution guide

See merge request GNOME/gtk!358
2019-01-07 16:44:41 +00:00
Ryuta Fujii 4404afc9f3 Update Japanese translation 2019-01-05 01:16:56 +00:00
Ryuta Fujii dadac6a9e1 Update Japanese translation
(cherry picked from commit 69ddfcf1ed)
2019-01-04 22:21:43 +00:00
Aurimas Černius 210a06174d Updated Lithuanian translation 2019-01-04 23:23:00 +02:00
Timm Bäder f9a5a474f0 imcontextwayland: (Hopefully) fix if expression 2019-01-04 05:55:26 +01:00
Piotr Drąg c51f1fda28 Update POTFILES.in 2019-01-03 19:21:09 +01:00
Timm Bäder ea3d0c0f01 buttonbox: Remove redundant if statement
This used to do something in the past.
2019-01-03 08:57:16 +01:00
Timm Bäder 2c1198f6c2 colorchooser: Remove extra custom color 2019-01-03 08:56:46 +01:00
Timm Bäder 9d3120cc1e popover demo: Fix size-allocate callback signature 2019-01-03 08:56:40 +01:00
Timm Bäder 66d3aa8101 window: Fix state_flags_changed impl name
This is unrelated to GdkSurface and was changed by accident.
2019-01-03 08:56:34 +01:00
Timm Bäder 0530637fef stack: Don't queue an unnecessary redraw
Both queue_allocate and queue_resize already queue a draw.
2019-01-03 08:52:35 +01:00
Timm Bäder 3d6bdb9af3 entry: Remove unused struct 2019-01-03 08:52:08 +01:00
Matthias Clasen 7e7c90961c Check for the session bus before using it
Patch by Chris Allen, #475
2019-01-02 20:35:19 -05:00
Matthias Clasen 3da9280a8a Merge branch 'wip/nbenitezl/move-bookmark-placeholder-index-4' into 'master'
gtkplacessidebar.c: move bookmark at the placeholder index

See merge request GNOME/gtk!459
2019-01-03 01:27:49 +00:00
Matthias Clasen ed17a8ddd7 Merge branch 'patch-1' into 'master'
Zero-fill new GtkTextIter

See merge request GNOME/gtk!455
2019-01-03 01:02:07 +00:00
Matthias Clasen cd7e70680c Merge branch 'wip/carlosg/imwayland-for-master' into 'master'
Use zwp_text_input_v3 on gtk4

Closes #1317 and #1525

See merge request GNOME/gtk!462
2019-01-03 00:36:35 +00:00
Matthias Clasen a80007ac12 Fix XChangeProperty calls
They must be long...

Closes: #1556
2019-01-02 19:26:56 -05:00
Matthias Clasen dc68d04c32 Fix resize corners
I was stuck in an X session and noticed that my resize corners
all got east or north cursors. It turns out that gnome-shell
does not properly advertise support for edge constraints under X11,
and the absence of that makes the code for determining the edge
under the cursor misbehave.

This change should fix that.
2019-01-02 19:08:02 -05:00
Timm Bäder bd95e16372 Merge branch 'wip/carlosg/revealer-fix-interrupted-animations-master' into 'master'
revealer: Fully set the target state if unmapped during animation

See merge request GNOME/gtk!466
2019-01-02 08:50:25 +00:00
Timm Bäder c1e1e2da80 image: Avoid some unnecessary signal connections
Equivalent if fd9879e5ff but for GtkImage.
2018-12-31 12:44:02 +01:00
Timm Bäder ea8f1469c1 image: Indentation fix 2018-12-31 12:44:02 +01:00
Timm Bäder 1d3aa9207c gl renderer: Add a clip stack
So we can check that the currently set clip is the first one and now
intersect with it. This first clip is always the entire viewport or the
entire render_area and we don't want to end up drawing things to a
texture because of it.
2018-12-31 12:44:02 +01:00
Timm Bäder b4f2a3416e picture: Avoid some unnecessary signal connections
We don't need to ever invalidate the picture size if the paintable tells
us its size is static. Same for the contents.
2018-12-31 12:44:02 +01:00
Timm Bäder 3b46e2a558 image: Remove private struct from public header 2018-12-31 12:44:02 +01:00
Daniel Boles 480a04131c CellAccessible: Fix return type of row|column_span
See:
 * c876c74eb7
 * 63e0eb5de5
2018-12-30 18:15:11 +00:00
Jordi Mas 171a710a23 Update Catalan translation 2018-12-29 09:31:36 +01:00
Emmanuele Bassi 4f532a414c docs: Clarify the section on dependencies 2018-12-28 18:44:36 +00:00
Emmanuele Bassi 3f567781dd docs: Clarify the section on commit access
The section is about rules for direct commit access to the upstream
repository, so let's be more clear about it.
2018-12-28 18:44:36 +00:00
Emmanuele Bassi 0397c8b628 docs: Clarify autoclosing issues syntax
Link to the GitLab documentation, and clarify that if no single commit
in a merge requests closes an issue, you should add a reference to the
issue in the commit message anyway.
2018-12-28 18:44:36 +00:00
Emmanuele Bassi 3939824d11 docs: Make the contribution guide slightly more friendly
This is an important document for newcomers, so we should err on the
side of being more detailed on what kind of contributions we expect,
and how we expect them.

The text is heavily modelled on the contributing-template by Nadia
Eghbal available here:

  https://github.com/nayafia/contributing-template
2018-12-28 18:44:36 +00:00
Emmanuele Bassi d7cafca118 docs: Move commit style docs to the contribution guide
There's no point in having a separate file detailing how commits ought
to work, considering we already have a contribution guide.
2018-12-28 18:28:52 +00:00
Jordi Mas d10709c917 Update Catalan translation 2018-12-28 09:55:51 +01:00
Jordi Mas e9d4823c57 Update Catalan translation 2018-12-25 09:57:57 +01:00
Jordi Mas 06d764d046 Update Catalan translation 2018-12-24 17:38:01 +01:00
Christoph Reiter 325badc3eb Merge branch 'fix-typo-win32-compilation-speedup-macro-gtk4' into 'master'
Win32: Fix typo on compilation speedup macro define [Gtk4]

See merge request GNOME/gtk!473
2018-12-22 17:54:08 +00:00
Tomasz Miąsko c665a1d5a5 Annotate values of PRIORITY constants
g-ir-scanner incorrectly evaluates macro definition that include
references to other macro definitions. Provide a correct value as an
annotation.

Differences in generated gir files:

```diff
@@ -19017 +19017 @@
-    <constant name="PRIORITY_REDRAW" value="20" c:type="GDK_PRIORITY_REDRAW">
+    <constant name="PRIORITY_REDRAW" value="120" c:type="GDK_PRIORITY_REDRAW">
@@ -74229,3 +74229,3 @@
     </constant>
-    <constant name="PRIORITY_RESIZE" value="10" c:type="GTK_PRIORITY_RESIZE">
+    <constant name="PRIORITY_RESIZE" value="110" c:type="GTK_PRIORITY_RESIZE">
       <doc xml:space="preserve">Use this priority for functionality related to size allocation.
@@ -106786,3 +106786,3 @@
     <constant name="TEXT_VIEW_PRIORITY_VALIDATE"
-              value="5"
+              value="125"
               c:type="GTK_TEXT_VIEW_PRIORITY_VALIDATE">
```

See !472
2018-12-22 18:52:20 +01:00
Jordi Mas c7f1a275ac Update Catalan translation 2018-12-22 10:33:41 +01:00
Luca Bacci a52989842e Win32: Fix typo on compilation speedup macro define
There is a typo, the correct macro to define is WIN32_LEAN_AND_MEAN.
After this change <shellapi.h> must be included in order to use
ExtractIconExW().
2018-12-22 01:18:17 +01:00
Mohammed Sadiq 1df276f263 mediastream: Fix possible memory leak
@error is (transfer full).  So the error passed should be freed if not used
2018-12-20 10:26:56 +05:30
Carlos Garnacho 615f10f7c8 revealer: Fully set the target state if unmapped during animation
If the revealer is told do animate and then unrealize itself, we do
(correctly) stop the animation, but used to do a shortcut where we
just set the target state as current.

Other things are dependent on the animation properly finishing though,
like the contained widget child visibility. This may lead to inconsistent
state where gtk_revealer_get_child_revealed() returns TRUE but the child
widget is unmapped, or vice-versa.

Fully finish the animation here, so the child state is coherent the next
time the revealer is mapped. We can also skip notifying on the property
since it will be handled by gtk_revealer_set_position().
2018-12-19 20:53:40 +01:00
Peter Hutterer 38cba6895a x11: make the tool lookup dependent on the hw id as well
Tools on the same physical item have the same serial number, so the eraser
and the pen part of a single pen share that serial number. With the current
lookup code, we'll always return whichever tool comes first into proximity.

Change the code to use the hw id in addition to the serial number, this way we
can differ between two tools.
2018-12-18 21:41:49 +01:00
Peter Hutterer e95e045898 x11: don't add unknown tools to our list
Generic tools (Bamboo, built-in tablets) always have the same serial number
assigned by the wacom driver. This includes the touch tool when the wacom
driver handles the touch evdev node (common where users require the wacom
gestures to work).

When the first device is the touch device, a tool is created with that serial.
All future tools now return the touch tool on lookup since they all share the
same serial number. Worse, this happens *across* devices, so the pen
event node gets assigned the touch tool because they all have the same serial.

Since we don't actually care about the touch as a tool, let's skip any unknown
tool. This captures pads as well.
2018-12-18 21:41:09 +01:00
Peter Hutterer 1b730dcf31 x11: get the tool type from the wacom driver properties
Any wacom device currently sets the tool type to UNKNOWN. The wacom driver has
a property that exports the tool type as one of stylus, eraser, cursor, pad or
touch. Only three of those are useful here but that's better than having all
of them as unknown.
2018-12-18 21:41:08 +01:00
Carlos Garnacho beb9ee6d4a build: wrap IM protocol building under have_wayland altogether
We poke variables that might not be defined if the wayland backend
is disabled.
2018-12-18 20:51:53 +01:00
Carlos Garnacho 8ce6d03c7b imwayland: Respect maximum length of 4000 Bytes on strings being sent.
Hitting the limit will raise protocol errors.
2018-12-18 20:38:44 +01:00
Carlos Garnacho 904202a636 imwayland: Plug leaks
The various strings (pending/current preedit, surrounding, and commit
buffer) are being leaked in the case of GtkIMContext destruction.
2018-12-18 20:38:44 +01:00
Dorota Czaplejewicz 7a0b6a3639 imwayland.c: fix formatting 2018-12-18 20:38:44 +01:00
Dorota Czaplejewicz b465e04ae2 imwayland: rearrange functions to remove prototypes 2018-12-18 20:38:41 +01:00
Dorota Czaplejewicz f67627875f imwayland: Handle enter and leave events
Before this patch, imwayland would assume that text-input enter and leave events follow the general (wl_keyboard) focus, and was unable to handle the situation where they would not be provided at the same time.
2018-12-18 20:27:12 +01:00
Carlos Garnacho 8912dc226c imwayland: Collect return value from ::delete-surrounding signal
There's not much we can do about the signal not being handled, but
we should fetch the return value anyway.
2018-12-18 20:27:12 +01:00
Dorota Czaplejewicz 12ac9f351e imwayland: Don't reset serial while text-input is alive
The serial number is a persistent property of the text-input object.
2018-12-18 20:27:12 +01:00
Dorota Czaplejewicz c4b4e90f98 imwayland: Fix clearing of preedit text in webkitgtk
Fixes webkitgtk misbehaviour as outlined in https://gitlab.gnome.org/GNOME/gtk/issues/1316#note_312942 , which was introduced in 49b17e6c.
The preedit will be cleared on exit only if it is already present.
2018-12-18 20:27:12 +01:00
Dorota Czaplejewicz fcf28ded42 imwayland: Fix clearing of preedit text
Fixes terminal emulator misbehaviour as outlined in https://gitlab.gnome.org/GNOME/gtk/issues/1316, which was introduced in 49b17e6c. The original commit cleared preedit text by setting it to an empty string, which still counted as existing preedit. The fix sets preedit string to null, which is correctly understood as not present.
2018-12-18 20:27:12 +01:00
Carlos Garnacho 1e69d248cb modules: Check current context before retrieving surrounding
There may be situations where this might get called while the
currently focused context just went away (eg. after setting the
text widget unsensitive).

Closes: #1317
2018-12-18 20:27:12 +01:00
Dorota Czaplejewicz c49b29fa53 imwayland: clear preedit on focus out 2018-12-18 20:27:12 +01:00
Dorota Czaplejewicz 024220aee8 imwayland: Add text-input-unstable-v3 support
The wayland input module now represents text-input-unstable-v3 support, while the old module supporting gtk-text-input was renamed to gtkwayland.
2018-12-18 20:27:12 +01:00
Benjamin Otte 1423265610 gstmedia: Implement error handling.
I wonder who forgot that.
Whoops.
2018-12-18 02:04:54 +01:00
Benjamin Otte 89c48a08a0 mediastream: Allow multiple calls to gtk_media_stream_error()
Just ignore all further ones.
2018-12-18 02:04:16 +01:00
Benjamin Otte c30968861f a11y: Fix function return type
Typo right there.
2018-12-18 01:20:36 +01:00
Daniel Boles a8ac6f833c RGBA: tiny grammar improvements in to_string doc 2018-12-17 20:49:34 +00:00
Daniel Boles 271acaff53 RGBA: Consistently use “” around inline arg names
instead of being inconsistent and not using them later, which leaves a
bunch of single letters floating among real words, not the prettiest.
2018-12-17 20:49:34 +00:00
Daniel Boles c35e0cba39 RGBA: Fix example to_string output for reality/CSS
* We don't output spaces anywhere in the code, unlike the doc suggested.
* CSS explicitly forbids whitespace between function names and lparens:
  https://stackoverflow.com/questions/13877198
2018-12-17 20:49:34 +00:00
Nelson Benítez León 65240967e4 gtkplacessidebar.c: move bookmark at the placeholder index
As that index is set in drag_motion_callback() and visually shown
on the widget as a drop target hint.

https://bugzilla.gnome.org/show_bug.cgi?id=787356
https://gitlab.gnome.org/GNOME/gtk/issues/904
2018-12-17 19:19:20 +00:00
Christoph Reiter a99bd2a422 ci: Update Docker image to Fedora 29 and meson to 0.49.0 2018-12-16 21:33:22 +01:00
Orivej Desh 3ec2d5fa38 Zero-fill new GtkTextIter
iter_init_common() is used on uninitialized GtkTextIter, and since neither it
nor its callers initiliaze its padding fields, they contain garbage.

This is a problem for Go - which checks that structs passed to C functions do
not contain pointers to Go-allocated memory - when the garbage happens to be
such a pointer.  Although Go zero-fills all GtkTextIter that it allocates, this
does not help when GTK functions such as insert_pixbuf_or_widget_segment called
for gtk_text_buffer_create_child_anchor copy garbage from their stack-allocated
GtkTextIter into a clean iter.  To work around this a GtkTextIter has to be
discraded after use in text buffer anchor inserting functions:
https://github.com/gotk3/gotk3/pull/307
2018-12-16 17:03:47 +00:00
Andre Klapper a0b5b39bbd Replace git.gnome.org by Gitlab URL in <GitRepository> in DOAP file 2018-12-16 00:45:41 +01:00
Andre Klapper ab52862a5d Replace Bugzilla by Gitlab URL in DOAP file 2018-12-15 23:32:24 +01:00
Daniel Boles a350192ea2 EventControllerKey: Add missing documentation bits 2018-12-14 23:28:54 +00:00
Emmanuele Bassi cb0d8d6d90 Remove gtk_widget_show_all() call
Extraneous chunk from 7601bca758.

Cherry picked from gtk-3-24, which has a gtk_widget_show_all() function.
2018-12-14 20:38:03 +00:00
Matthias Clasen 86ad3e8f2a Merge branch 'master' into 'master'
A11y: Add support for AtkTableCell

See merge request GNOME/gtk!411
2018-12-14 19:25:27 +00:00
Mike Gorse 8f29a0633b A11y: Add support for AtkTableCell 2018-12-14 19:25:27 +00:00
António Fernandes 7601bca758 placesview: List only available protocols as available
We display a list of supported protocols in the server_addresses_popover.

However, this curated list contains protocols which may or may not be
available, depending on the respective gvfs backend being installed.

So, populate the list only with protocols which are available.

https://gitlab.gnome.org/GNOME/gtk/issues/1476
2018-12-14 12:30:52 -05:00
António Fernandes 3bbfff9280 placesview: Set .error style if unsupported protocol
When the user types an address with a schema that is not supported,
the Connect button doesn't become sensitive, but there is no visible
feedback at all.

This feels unresponsive and leaves the user clueless.

While it doesn't help explain why the address doesn't work, this will
provide a hint that the input was acknowledged but doesn't work.

https://gitlab.gnome.org/GNOME/gtk/issues/1476
2018-12-14 12:28:47 -05:00
Matthias Clasen 5b049364dc Merge branch 'fix-polygon-svg-recolor' into 'master'
icontheme: Recolor <polygon> elements in SVGs too

See merge request GNOME/gtk!443
2018-12-14 17:02:30 +00:00
Timm Bäder 7997bdc5d7 Merge branch 'demo-combobox-typo-gtk4' into 'master'
demos/gtk-demo/combobox: fix typo

See merge request GNOME/gtk!444
2018-12-13 12:05:14 +00:00
LRN 04aebda1e9 Merge branch 'win32-honest-clipboard-gtk4' into 'master'
GDK W32: Be honest about supported clipboard formats (GTK4)

See merge request GNOME/gtk!399
2018-12-11 13:47:57 +00:00
Jakub Steiner 77792b6475 Revert "Adwaita: GNOME 3.32"
This reverts all GNOME 3.32 styling from master
2018-12-10 21:22:56 +01:00
Christoph Reiter 5612e84551 GDK W32: Always set gtk-font-name to the active UI font. Fixes #1484
This makes apps use "Segoe UI 9" by default instead of whatever matches "Sans 10".
It also cleans up the code and uses some new pango API while at it.

This was previously disabled in 9e686d1fb5 because it led to a poor glyph coverage
on certain versions of Windows which don't default to "Segoe UI 9" (Chinese, Korean, ..)
because the font fallback list was missing in pango.

This is about to get fixed in https://gitlab.gnome.org/GNOME/pango/merge_requests/34
so enable it again when we detect a new enough pango version.

(See !436 for the original MR)
2018-12-10 09:00:50 +01:00
Jeremy Bicha 462193ae26 demos/gtk-demo/combobox: fix typo
Fix typo that prevented the P-S submenu from displaying correctly
2018-12-09 23:30:38 -05:00
Matej Urbančič 80a90a084e Updated Slovenian translation 2018-12-09 21:26:33 +01:00
Christoph Reiter 2f29cb9e6f win32: Don't multiply the scroll event deltas by the Windows scroll lines setting. See #1408
GTK widgets expect the scroll deltas to be 1 or -1 and calculate a scroll value from that.
Multiplying the delta by the Windows scroll line setting (which defaults to 3) results
in a much larger delta and vastly different behaviour for running a GTK app on Windows
vs on Linux. For example text view and tree view scroll by 9 lines per scroll wheel tick
per default this way while on Linux it is around 3.

Remove the multiplication for now.

See !426 for the gtk3 MR
2018-12-08 15:28:37 +01:00
Christoph Reiter 67fdfca3ba GDK W32: set default settings for fontconfig.
Enables hinting, antialiasing and set the subpixel orientation according to the
active clear type setting. This ensures that font rendering with the fontconfig backend
looks similar to the win32 backend, at least with the default system font.

See !437
2018-12-08 14:54:15 +01:00
Philip Chimento 284d909347 icontheme: Recolor <polygon> elements in SVGs too
Otherwise, it's possible to have a symbolic icon where some of the
shapes keep the #bebebe chroma key color.
2018-12-08 01:40:32 +00:00
Timm Bäder 43ef4d7b53 menushell: Listen to non-primary button clicks
Menus should also be deactivated on right-button clicks.
2018-12-07 17:03:45 +01:00
Timm Bäder 3ce45508e1 gl renderer: Track border width state separately 2018-12-07 16:36:10 +01:00
Timm Bäder 57efdcfbbe gl renderer: Ignore subsequent render target ops 2018-12-07 16:36:10 +01:00
Timm Bäder df817bd118 gl renderer: Ignore viewport ops to the same viewport 2018-12-07 16:36:10 +01:00
Timm Bäder 82a1d4f280 gesturestylus: Use proper syntax when refering to signals 2018-12-07 16:36:10 +01:00
Jakub Steiner 80f2660838 Adwaita: regenerate CSS
- for the previous patch
2018-12-07 12:00:21 +01:00
Jakub Steiner edd4d2918a Merge branch 'context_menus' into 'master'
Adwaita GTK Theme: Add bigger shadow and border-radius to menus

See merge request GNOME/gtk!432
2018-12-07 09:58:56 +00:00
Jakub Steiner 320d272ec8 Adwaita: buttons & headerbar tweaks
- tone down the button z-depth
- flatter headerbars
2018-12-05 16:21:45 +01:00
Daniel Boles 72d09d22e9 Box, Grid: Improve various bits of documentation
Issue #1495 showed that the docs of GtkGrid retain outdated implications
that (as was once, but is no longer, the case) it is intended to replace
GtkBox, by discussing HfW and widget properties in a way that suggests
GtkBox can't handle them. But of course it does, and it's preferable for
simple single-row/column cases. Worse, we said GtkGrid “provides exactly
the same functionality” for the latter case, but the original point of
that Issues was that it doesn’t, at least for CSS positional selectors!

Box:
• Use an actually meaningful @Short_description.
• Remove unhelpful @See_also references to unrelated containers.
• Remove references to “rectangular area”: it might be another shape
  via CSS, or “rectangular” might falsely imply 2 dimensions of children.
• Mention Orientable:orientation.
• Emphasise usefulness of :[hv]align for allocating in the other axis.
• Don’t say that Grid “provides exactly the same functionality” for a
  single row or column, since (A) it is overkill for that case and (B)
  said Issue proved that it *doesn’t* for CSS child order, for example.

Grid:
• Don’t dwell on widget properties and height-for-width in a way that
  wrongly implies that Box can’t handle those (or Grid can better). In
  fact, just get rid of that bit altogether: Box handles them fine, and
  such wording was only needed years ago for migration from GTK+ 2 to 3.
• Point to GtkBox as being preferred for the simple row/column use case.
2018-12-04 20:43:19 +00:00
Timm Bäder a2a4603329 Merge branch 'bye-app-menu-gtk4' into 'master'
widget-factory: move app menu contents to primary menu (gtk4)

Closes #916

See merge request GNOME/gtk!365
2018-12-04 14:32:22 +00:00
Timm Bäder 8de1ba2cc4 application: Remove dead assignment 2018-12-04 06:30:47 +01:00
Timm Bäder 2644da106b button: Remove some dead code 2018-12-04 06:30:47 +01:00
Timm Bäder 4860410c4a button: Remove some unnecessary includes 2018-12-04 06:30:47 +01:00
Timm Bäder 4b3a94f382 gl renderer: Fix remaining TODO about offset nodes
All of the nodes should now support offsets.
2018-12-04 06:30:47 +01:00
Timm Bäder d67dacedba gl renderer: transform nodes: offset 2018-12-04 06:30:47 +01:00
Timm Bäder e1feb1b712 gl renderer: Clip nodes: offset 2018-12-04 06:30:47 +01:00
Timm Bäder e8670c89ae gl renderer: Linear gradients: offset 2018-12-04 06:30:47 +01:00
Timm Bäder b4f918904c gl renderer: Outset shadow nodes: offset 2018-12-04 06:30:47 +01:00
Timm Bäder aead150ce2 gl renderer: Care about offset when rendering border nodes 2018-12-04 06:30:47 +01:00
Timm Bäder fd47e57e4b gl renderer: care about offset when rendering shadow nodes 2018-12-04 06:30:47 +01:00
Matthias Clasen 1e129c1dd2 emoji chooser: Actually force Emoji presentation
The previous commit was using the text presentation selector
instead of the Emoji one. Oops.
2018-12-03 21:47:53 -05:00
Timm Bäder e0a7d28339 testuite Add translucent offscreen rendering test case 2018-12-02 16:15:17 +01:00
Timm Bäder ad93806005 showrendernode: Fix GtkImage size
Make sure we show the paintable unscaled.
2018-12-02 16:14:31 +01:00
Timm Bäder 2b95a5daee gl renderer: Remove blend shader
It's unused.
2018-12-02 16:04:40 +01:00
Timm Bäder 0681c5d5bc gl renderer: Reset opacity when rendering to a texture
The opacity will already be applied when rendering the final texture.
2018-12-02 16:03:08 +01:00
Timm Bäder b19926c079 gl renderer: Add function to draw debug rectangle 2018-12-02 14:31:57 +01:00
Timm Bäder 692ed4f994 gl renderer: Refactor render op builder 2018-12-02 14:17:18 +01:00
Timm Bäder ad759307f8 gl renderer: Add more node types to print_render_node_tree
debugging ++
2018-12-02 13:39:55 +01:00
Timm Bäder fb6adaaa62 window: Don't try to size-allocate unmapped popovers
The gtk_widget_size_allocate call won't do anything anyway.
2018-12-02 13:25:43 +01:00
Timm Bäder 58a4ae94e9 gl renderer: Use ops_transform_bounds_modelview in more places 2018-12-02 13:25:43 +01:00
Timm Bäder 9df9087a13 gl renderer: Add NodeSample
As a quick way of checking what a particular sample of nodes (e.g. all
offset node children) are made up of.
2018-12-02 13:25:43 +01:00
Timm Bäder f8df527c68 sizerequest: Directly query new request_mode
We are already inside the function that populates the size request
cache, so do it here instead of implicitly in get_request_mode.
2018-12-02 13:25:43 +01:00
Timm Bäder 71512cf9ad gl renderer: Move geometry calculation further down
We don't need it above, so move it to where it belongs.
2018-12-02 13:25:43 +01:00
Timm Bäder 79cc8fb261 gl renderer: Apply offset with scale 2018-12-02 13:25:43 +01:00
Timm Bäder 2831dbb110 gl renderer: Refactor add_offscreen_ops
Use a graphene_rect_t for the node bounds instead of 4 floats.
This makes it simpler to pass the size in without the offset applied.
2018-12-02 13:25:43 +01:00
Timm Bäder 933acb3682 gl renderer: Add offscreen ops without offset applied
When doing color matrix nodes. This fixes color matrix node with scale =
2.
2018-12-02 13:25:43 +01:00
Timm Bäder 574ebafa46 gl renderer: Reset offset when rendering offscreen
We want to apply the offset to the rendered texture, not to the
offscreen-rendered content.
2018-12-02 13:25:43 +01:00
Timm Bäder 74dd05b45e gl renderer: add render ops for dumping the framebuffer
So offscreen rendering can be properly debugged.
2018-12-02 13:25:43 +01:00
Timm Bäder 3eb2cef421 gl renderer: Set the render region as initial clip
So we avoid creating render ops for things outside of it.
2018-12-02 13:25:43 +01:00
Timm Bäder 94745241c2 GdkGLContext: Fix damage computation with buffer_age
As per the spec:

> The back buffer can
> either be reported as invalid (has an age of 0) or it may be
> reported to contain the contents from n frames prior to the
> current frame.

So a  buffer age of 1 means that the buffer was used in the last frame.
We were handling buffer_age==1 the same as buffer_age==0, i.e. we
returned the full damage for the surface.

[1] https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_buffer_age.txt
2018-12-02 13:25:43 +01:00
Timm Bäder 538491efa1 gl renderer: Fix only_translation check 2018-12-02 13:25:43 +01:00
Matthias Clasen 6f8c4f873d Merge branch 'force-emoji' into 'master'
Force emoji presentation

See merge request GNOME/gtk!431
2018-11-30 21:38:02 +00:00
Matthias Clasen 7a4e9fa4d3 Force emoji presentation
Append a variation selector to the Emoji sequences,
to force Emoji presentation. Without this, some
Emoji come out with text presentation by default.

Closes: Pango #334
2018-11-30 16:20:44 -05:00
Jakub Steiner f3c704b82e Adwaita: updated switch control
- might be nasty to hide labels with CSS. We can fix properly later.
- the blue border seesm aliased when :checked
2018-11-30 20:55:00 +01:00
frederik.feichtmeier a6a69dd567 Adapt border-radius and box-shadow of menus to popovers 2018-11-30 11:54:22 +01:00
Jakub Steiner 8921c868a5 Adwaita: shade buttons
- it was a bit too flat
2018-11-29 21:56:45 +01:00
Jakub Steiner 3f8598baa4 Adwaita: button tweaks
- step back on toning down the borders. Flatness !> legibility.
- darker active state for light
- draw gradinets from bottom up, to keep px sized shading regardless
  of button size.
2018-11-29 20:19:41 +01:00
Jakub Steiner b5fd7b3211 Adwaita: headerbar backdrop state 2018-11-29 14:34:53 +01:00
Jakub Steiner e9fe9410e0 Adwaita: sync headerbar styling for devel mode 2018-11-29 13:12:44 +01:00
Timm Bäder 904fd5f1fc Remove gtk_widget_intersect
It's been broken for quite a while now and doesn't make sense anymore
these days.
2018-11-29 11:14:26 +01:00
Timm Bäder f598836d6c popover: Don't recalculate position if unmapped 2018-11-29 08:50:18 +01:00
Timm Bäder 5907ff694f gl renderer: Render non-trivial transforms to a texture
This way we can e.g. render rotated clips, borders, etc.
2018-11-29 08:50:18 +01:00
Timm Bäder 7c020bfaaa inspect-button: Remove custom pick() implementation
This was added to work around the fact that pick() does not look at
insensitive widgets at all, but the replacement didn't properly work
either.
2018-11-29 08:50:18 +01:00
Timm Bäder 2bd02d9185 popover: Get rid of a gtk_widget_get_allocation call
Use _compute_bounds instead.
2018-11-29 08:50:18 +01:00
Timm Bäder c0cf592336 gl renderer: Cache offscreen textures per node, not size 2018-11-29 08:50:16 +01:00
Timm Bäder 12378f0afa gl renderer: Expand matrix metadata extraction
Instead of getting the translation x/y everytime we use the modelview,
get it once, when extracting the metadata. Do the same with the scale.
And save if the matrix is "simple" at all, i.e. if it only consists of a
translation and/or scale. This will be helpful later when we start
drawing transformed nodes on textures.
2018-11-29 08:23:42 +01:00
Timm Bäder 5ea211bbb1 Revert "gldriver: Don't create surfaces to upload textures"
This reverts commit 6466e53bfc.

This breaks GtkGLArea.
2018-11-29 07:39:11 +01:00
Timm Bäder c17c18f1ae widget: Remove one translate_coordinates copy
Just use the double version in the integer version.
2018-11-29 07:39:11 +01:00
Jakub Steiner dbde7b68c0 Adwaita: flatten the headerbar again 2018-11-28 20:28:56 +01:00
frederik.feichtmeier 95f06f6e75 Add bigger shadow and border-radius to menus
Increase the visibility of the box-shadow for menus
Introduce a border-radius variable for menus
Use this variable for all corners of menus except top for the top menus
2018-11-28 17:43:55 +01:00
Jakub Steiner a26edd59d1 Adwaita: tune button & hederbar colors 2018-11-28 14:22:21 +01:00
Mohammed Sadiq dcd21e12cd texttag: Replace gtk3-demo reference with gtk4-demo 2018-11-28 16:51:45 +05:30
Jakub Steiner e5efc84eda Adwaita: buttons & headerbars
- tone down the bottom border contrast (increase bottom lightness,
  decrease overall lightness)
- darken headerbars slightly (might require darkening wm colors when
  dust settles)
2018-11-28 00:16:20 +01:00
Matthias Clasen 8035969860 Merge branch 'master-escape-included-svg' into 'master'
(#1471): base64-encode included SVGs to avoid mis-escaped characters

Closes #1471

See merge request GNOME/gtk!430
2018-11-27 20:25:28 +00:00
Federico Mena Quintero e5f9bf2e9b (#1471): base64-encode included SVGs to avoid mis-escaped characters
We wrap SVG data from icons within another SVG with extra styling
information.  The wrapped SVG may contain characters that cannot be
part of a data: URL (https://fetch.spec.whatwg.org/#data-urls).

Librsvg 2.45 got more strict in its parsing of data: URLs; whereas
previously it ignored '#' characters in them, now it considers them to
be the start of a fragment identifier, which is not allowed in data:
URLs anyway.

To avoid unallowed characters, we now create a data: URL with a
base-64 encoded SVG.

Fixes https://gitlab.gnome.org/GNOME/gtk/issues/1471
2018-11-27 13:57:21 -06:00
Timm Bäder 0be4d31217 headerbar: Remove superfluous parentheses 2018-11-27 06:06:28 +01:00
Timm Bäder eebb849760 widget: Query CSS values later in size_allocate
Move it below the "this widget only changed its position" check.
2018-11-27 06:00:30 +01:00
Timm Bäder f92745aacf widget: Save baseline without CSS values applied
Similar to what we do with width/height.
2018-11-27 05:59:47 +01:00
Timm Bäder 7aee30bfc2 adwaita: icon-shadow -> -gtk-icon-shadow 2018-11-27 05:41:53 +01:00
Timm Bäder ef751bc809 gl renderer: Use stack to keep track of modelview matrix
So we can avoid calculating metadata for matrices all the time.
2018-11-27 05:39:27 +01:00
Timm Bäder fe49f83982 colorplane: Convert crosshair rendering to snapshot
This is slightly different than the cairo version since the
half-transparent lines now overlap but nobody can see that anyway.
2018-11-27 05:37:38 +01:00
Timm Bäder 059d9376da colorscale: Cache hue texture
Otherwise we regenerate a new one on every snapshot() call.
2018-11-27 05:37:38 +01:00
Timm Bäder 6466e53bfc gldriver: Don't create surfaces to upload textures 2018-11-27 05:37:38 +01:00
Timm Bäder b7963a06ab widget: Parent widgets may also consume motions
This is important when the target widget of an event is not the one that
would otherwise receive the gesture. For example, the GtkSwitch
implementation currently attaches a pan gesture to the switch itself,
but the target widget below the pointer might be the switch slider or
label.

See #1465
2018-11-27 05:37:38 +01:00
Timm Bäder eeeefb40c7 switch: Shorten size_allocate impl a bit 2018-11-27 05:37:38 +01:00
Jakub Steiner 97d8676b40 Adwaita: help fullcolor app icons
- draw a large dropshadow for aboutboxes
- draw an outline for low res

See issues #1434 and #1445.
2018-11-26 17:33:28 +01:00
Jakub Steiner 6e28d004ae Adwaita: tone down broders, buttons
- very contrasty lines feel dated in today's flat world
- tone down the contrast a little
2018-11-23 17:32:46 +01:00
Jakub Steiner 8d7bf3ad0c Adwaita: list buttons
- tone down buttons when inside lists

Fixes issue #1473
2018-11-22 13:24:49 +01:00
Timm Bäder d76a0feef6 widget: gdk_display_get_monitor can return NULL
Fixes #1466
2018-11-20 12:45:18 +01:00
Timm Bäder 08a07d4ae5 entry: Shorten finalize implementation
By using g_clear_pointer and g_clear_object where appropriate.
2018-11-20 12:45:18 +01:00
Timm Bäder b42d99b37e Merge branch 'zbrown/emit-transient-for' into 'master'
window: Actually emit notify::transient-for

See merge request GNOME/gtk!424
2018-11-20 11:29:18 +00:00
Zander Brown ea487b2233 window: Actually emit notify::transient-for
Because it seems we weren't doing that
2018-11-19 21:17:01 +00:00
Timm Bäder 40ae5c1319 Merge branch 'benzea/foreach-documentation' into 'master'
container: Document that removal from foreach is permissible

Closes #1461

See merge request GNOME/gtk!423
2018-11-19 13:38:34 +00:00
Benjamin Berg 8c9c3e4426 container: Document that removal from foreach is permissible
It is permissable to remove a widget using gtk_container_remove from the
gtk_container_foreach callback handler. Document this fact to make it
more discoverable.

Fixes #1461
2018-11-19 13:58:34 +01:00
Timm Bäder d0f4fcb6fd Merge branch 'akitouni/gdkvulkan-doc-typo' into 'master'
vulkancontext: fix typos in documentation

See merge request GNOME/gtk!417
2018-11-19 07:41:36 +00:00
Timm Bäder 4142d0a69a Merge branch 'more-nullable' into 'master'
g-i: Add some nullable annotations

See merge request GNOME/gtk!419
2018-11-19 07:40:39 +00:00
Christoph Reiter b061821f24 g-i: Add some nullable annotations
Based on grepping arg docs for NULL.
See https://gitlab.gnome.org/GNOME/pygobject/issues/261
2018-11-18 13:36:50 +01:00
Abderrahim Kitouni e0833e492c vulkancontext: fix typos in documentation 2018-11-17 19:35:47 +01:00
Timm Bäder 55faaf1aa1 Merge branch 'jjardon/no_G_TYPE_INSTANCE_GET_PRIVATE' into 'master'
Stop using G_TYPE_INSTANCE_GET_PRIVATE completely

See merge request GNOME/gtk!402
2018-11-15 09:59:01 +00:00
Timm Bäder 7aa02b9e95 Merge branch 'include-ft2build.h' into 'master'
font chooser: Properly include freetype headers

Closes #1432

See merge request GNOME/gtk!413
2018-11-14 13:30:28 +00:00
Timm Bäder c65c6ba11f widget: Fix size-allocate signal docs 2018-11-13 20:54:18 +01:00
Timm Bäder 359d874ddb Use g_clear_pointer to unparent widgets 2018-11-13 20:53:14 +01:00
Timm Bäder ade171a2ed widget: Don't pass a position to ->size_allocate
The values have been 0/0 for a long time now, so just drop the
GtkAllocation argument and replace it with width and height.
2018-11-13 16:28:54 +01:00
Timm Bäder 1f1306a53b docs: Add GtkEventControllerLegacy 2018-11-13 15:40:42 +01:00
Timm Bäder ce3d5fcb0a vulkancontext: Add missing error switch 2018-11-13 15:28:46 +01:00
Timm Bäder 28bd56454d appchooserbutton: Remove priv pointer 2018-11-13 15:19:07 +01:00
Timm Bäder 75deff035b testappchooserbutton: Fix for class hierarchy change 2018-11-13 15:19:07 +01:00
Timm Bäder 87ee7e31a4 appchooserbutton: Inherit from GtkWidget 2018-11-13 15:19:05 +01:00
Timm Bäder 5a3ecb9703 render: Fix a position/size mixup
Fixes the foreigndrawing demo.
2018-11-13 14:10:17 +01:00
Timm Bäder e656f66720 toolbar: Remove dead code
The size definitely changes, otherwise ->size_allocate does not get
called.
2018-11-13 14:10:17 +01:00
Timm Bäder 0d47a6c970 toolbar: Remove some unused defines 2018-11-13 14:10:16 +01:00
Matthias Clasen 39f8e1e137 wayland: Adapt to settings portal api change
ReadAll now accepts an array of patterns.
2018-11-12 13:51:56 -05:00
Carlos Garnacho d7c2e5844b Merge branch 'scroll-event-propagation' into 'master'
eventcontrollerscroll: Conditionally propagate ::scroll

Closes #45

See merge request GNOME/gtk!250
2018-11-12 10:05:46 +00:00
Ernestas Kulik edc4b2f7d0 eventcontrollerscroll: Conditionally propagate ::scroll
Currently, gtk_event_controller_scroll_handle_event() always returns
TRUE if it is handled, which stops the propagation of the event. If
there’s a single GtkEventControllerScroll in the widget hierarchy, that
means that no others will run, depending on the propagation phase. In
Nautilus, this can be observed when adding a scroll controller to the
GtkScrolledWindow (ctrl-scrolling controls the zoom level) - either the
scrolling or the zooming breaks.

Fixes https://gitlab.gnome.org/GNOME/gtk/issues/45
2018-11-12 10:35:37 +01:00
Leonardo Taccari b3ba2961d2 font chooser: Properly include freetype headers
freetype headers should be included via <ft2build.h> and then
indirectly via FT_*_H macros.

Fixes issue #1432.
2018-11-09 22:13:30 +01:00
Timm Bäder c2c1acc73e calendar: Remove unused struct member 2018-11-09 20:18:13 +01:00
Timm Bäder c44728282c scrolledwindow: Remove some useless code
This is all being done already be the add_class/remove_class calls
before.
2018-11-09 19:37:55 +01:00
Timm Bäder 85a002bf9f scale: Don't set label css name to "label"
That's already the css name of all labels.
2018-11-09 18:59:30 +01:00
Timm Bäder 6eba544ad4 colorscale: Remove x/y arguments from snapshot_scale
We only pass 0 anyway.
2018-11-09 18:01:58 +01:00
Jakub Steiner f610fbfc0e Adwaita: use HIG grey for bg_color
- refresh with a light bg color, use the new color palette
2018-11-09 15:37:08 +01:00
Jakub Steiner 1e2d11cc62 Adwaita: fix osd bg color
- don't try deriving from bg_color, osd should be consistent
  for light & dark.

FIxes issue #1449
2018-11-09 11:19:41 +01:00
Adrien Plazas f1e24ca30a Adwaita: Propagate bg color to titlebar separator descendants
Gives the same background color to all separators descending from a
title bar than to its direct childrens.

This prevents separators which are in a titlebar but not direct children
from the widget with the titlebar style class from being almost
transparent and hence it prevent them from revealing the clear color of
the window's titlebar (black).

https://gitlab.gnome.org/GNOME/gtk/issues/1231
2018-11-09 08:49:38 +01:00
Jakub Steiner 1787f04097 Merge branch 'wip/jimmac/insensitive-progress' into 'master'
Adwaita: draw insensitive progressbars

See merge request GNOME/gtk!360
2018-11-09 07:27:49 +00:00
Jakub Steiner 671f69c6ca Merge branch 'wip/jimmac/hig-colors-gtk4' into 'master'
Adwaita: use new HIG colors

See merge request GNOME/gtk!407
2018-11-09 07:25:05 +00:00
Jakub Steiner 7b51de6bbd Adwaita: use new HIG colors
- blue selection color, success & destructive colors updates
- blueish tint for dark

Addresses issue #1443
2018-11-08 16:58:13 +01:00
Timm Bäder 45b909f2c5 testpopup: Fix GtkEventControllerMotion::motion callback signature 2018-11-08 05:48:14 +01:00
Timm Bäder 0b4ee06f8e eventcontrollerlegact: Fix ::event docs
As discussed in !388.
2018-11-08 05:48:14 +01:00
Timm Bäder 797739198f icontheme: Stop exporting gtk_icon_info_new_for_file 2018-11-08 05:48:14 +01:00
Timm Bäder 0c017ff109 icontheme: Stop exporting gtk_icon_theme_color_symbolic_pixbuf 2018-11-08 05:48:14 +01:00
Timm Bäder aad3686726 icontheme: Drop remaining emblem code 2018-11-08 05:48:14 +01:00
Timm Bäder fe7a2635d0 icontheme: Don't reference nonexistent parameter in docs 2018-11-08 05:48:14 +01:00
Timm Bäder 2834b38d2c icontheme: Use a bit field in AsyncSymbolicData
176 -> 144 bytes
2018-11-08 05:48:14 +01:00
Timm Bäder 29563a33ba icontheme: Stop strdup'ing css colors when loading
... symbolic icons.
2018-11-08 05:48:10 +01:00
Timm Bäder 5936d7f8f2 gl renderer: Properly retrieve matrix scale
So rotating offscreen nodes works.
2018-11-08 05:13:50 +01:00
Timm Bäder 481a78eee7 widget: Avoid some more ->priv accesses 2018-11-08 05:13:50 +01:00
Timm Bäder ac4134c298 range: Remove multipress_gesture member
We don't need it in the instance struct since we only set it up and then
access it in its signal callbacks.
2018-11-08 05:13:50 +01:00
Timm Bäder 145659af93 widget: Some whitespace fixes 2018-11-08 05:13:50 +01:00
Daniel Boles 31b8e0f109 Popover: Minimally document the ::closed signal
This is better than nothing at all. The wording is taken from Carlos's
commit message when he added this shortly before 3.12 (but skip Since).
Skip the bit from his commit message explaining what this replaced; we
don't need to say all the less good things our convenience API replaces.
2018-11-07 20:33:15 +00:00
Daniel Boles 18199a3cef testtreelistmodel: Don't use non-standard function
as per efd3758f6a strcasecmp() is not a C
standard thing (not that we bothered including any header for it anyway)
and so this test failed to build on Windows with Microsoft Visual C.
2018-11-07 20:32:55 +00:00
Daniel Boles 3194c39471 TreeMenu: Don't manually reinvent g_list_index()
g_list_index() "Gets the position of the element containing the given
data (starting from 0)." That is exactly what we were manually doing.
2018-11-07 20:32:55 +00:00
Javier Jardón 9d51a8f53a gtk/gtktoolbutton.c: Document why we need to still use G_TYPE_INSTANCE_GET_PRIVATE
This is the excellent explanation from Emmanuele at
https://gitlab.gnome.org/GNOME/gtk/merge_requests/402#note_361210:
"
Every time you instantiate a type, the instance_init() function is called for each
parent type T_p of your type T; to preserve invariants, the class pointer inside
the instance data is set to the parent type before each invocation, until you hit
your type T. This means that calling GET_CLASS() inside an instance_init() function
will give you a pointer to the class vtable for the parent type T_p while you're
iterating over parent types. What if you want to access the actual class vtable of
the type T, though? Well, you can because the actual signature of instance_init() is:

  void (* GInstanceInitFunc) (GTypeInstance *instance, gpointer g_class);

i.e. all instance_init() functions get passed the instance they are initialising
and the class vtable of the real type you're instantiating.

This is how GtkToolButton works: it "peeks ahead" at instance initialisation time,
to use the button_type class field of the actual type you're instantiating,
and calls g_object_new() with it to store the resulting object in its own private
data structure.

This whole contrived mechanism is needed to allow out-of-tree tool buttons to just
set the button type on their class init, and have their parent class create the
button they want, instead of asking all tool buttons to do this themselves and have
a virtual function called get_button() for GtkToolButton to call whenever it needs
to operate on the button instance.

Now we're coming to a close: we cannot use the G_DEFINE_TYPE macro because the
instance_init() function it creates internally will not pass the class pointer
to your custom instance_init(). Since we cannot use G_DEFINE_TYPE, we also cannot use
G_ADD_PRIVATE either.

This is the reason why, when I ported GTK 3 to the new private instance data structure
macros, I left GtkToolButton alone. I should have left a comment there, because @matthiasc
tried doing that as well, and then had to revert it in commit 1c4a7bd5. So: my bad,
sorry about that.

If we want to drop the G_TYPE_INSTANCE_GET_PRIVATE and the g_type_class_add_private() calls,
we cannot use G_DEFINE_TYPE, but what we can do is unrolling what the macros do themselves:

- add a global GtkToolButton_private_offset variable
- add a static inline gtk_tool_button_get_instance_private() that does return
(G_STRUCT_MEMBER_P (self, GtkToolButton_private_offset));
- call g_type_add_instance_private (g_define_type_id, sizeof (GtkToolButtonPrivate)) inside
gtk_tool_button_get_type() and store the result in GtkToolButton_private_offset
- replace g_type_class_add_private() inside gtk_tool_button_class_init() with
g_type_class_adjust_private_offset (klass, &GtkToolButton_private_offset)
"
2018-11-07 17:50:04 +00:00
Javier Jardón c37c86a9bf gtk/gtktextview.c: Remove unused GTK_TEXT_VIEW_GET_PRIVATE() macro 2018-11-06 13:45:58 +00:00
Timm Bäder b4b30b4951 Merge branch 'wip/3v1n0/recent-info-cleanup' into 'master'
gtk-autocleanups: add cleanup function for GtkRecentInfo

See merge request GNOME/gtk!409
2018-11-06 09:52:11 +00:00
Matthias Clasen 54830a2af3 wayland: Fix a thinko in settings portal support
When we decide to fall back because the settings portal
is not present, adhere to that decision elsewhere. And
treat the fontconfig-timestamp like the other special-cased
settings, with G_TYPE_NONE.
2018-11-05 18:34:13 -05:00
Marco Trevisan 9946dd2ab7 gtk-autocleanups: add cleanup function for GtkRecentInfo 2018-11-05 21:37:42 +00:00
Matthias Clasen 5028cb35bc Merge branch 'wip/settings-portal' into 'master'
settings portal

See merge request GNOME/gtk!403
2018-11-04 20:57:26 +00:00
Matthias Clasen 48b569eae0 wayland: Support the settings portal
Under Wayland, we are currently directly using GSettings
for desktop settings. But in a sandbox, we may not have
access to dconf, so this may fail. Use the new settings
portal instead.
2018-11-04 15:44:50 -05:00
Matthias Clasen 8099669466 Move the should_use_portal helper to gdk
We want to use it there too, in the future.
Update all callers.
2018-11-04 08:17:32 -05:00
Matthias Clasen 1c465604d5 Use a simpler sandbox check
No need to use the runtime dir and allocate a string.
We can just check in /.
2018-11-04 08:17:32 -05:00
Matthias Clasen 833442e1e2 Merge branch 'wip/fmuellner/deco-setting' into 'master'
wayland: Remove GNOME Classic-specific workaround

See merge request GNOME/gtk!400
2018-11-02 16:18:25 +00:00
Florian Müllner 1e39f999e3 wayland: Remove GNOME Classic-specific workaround
As GSettings now supports session-specific defaults, GNOME Classic
no longer uses a separate schema and the decoration layout is always
determined by the regular schema.

This essentially reverts commit add67b516c (although the code was
moved since then).

https://gitlab.gnome.org/GNOME/gtk/merge_requests/400
2018-11-02 16:44:33 +01:00
John Ralls e31187e1cf GdkQuartz: Handle NULL from [NSGraphicsContext currentContext].
By returning a default surface. The situation where there's no
currentContext arises when GtkCSS is trying to determine the
layout sizes so no actual display is necessary.

Closes: #1411
2018-11-01 15:39:27 -07:00
John Ralls e457a7823c Use [NSGraphicsContext CGContext] instead of graphicsPort after Yosemite. 2018-11-01 15:38:43 -07:00
John Ralls 88c77eb7be Update GDK_OSX versions to current MacOS release. 2018-11-01 15:38:29 -07:00
Piotr Drąg f57d337fac Update POTFILES.in 2018-10-31 18:46:48 +01:00
Timm Bäder 60b0f48fbc Merge branch 'wip/carlosg/public-legacy-controller' into 'master'
Make legacy controller public

See merge request GNOME/gtk!388
2018-10-31 13:39:08 +00:00
Руслан Ижбулатов 4c6d60ce2b GDK W32: Be honest about supported clipboard formats
Do not lie to W32 about the formats that we provide or accept.

Originally the logic behind such lies was that GdkPixbuf allows us to
convert any supported image to BMP or PNG, and therefore we should
announce that we always provide/accept BMP and PNG along with other
formats.

But that's not how it works. GDK has built-in serializers and
deserializers for all pixbuf formats (where it just invokes GdkPixbuf
API) and will use them automatically to read or write GdkTexture
objects (internally wrapping GdkPixbuf objects where necessary). The
encoding and decoding of images is handled
by GdkContent(De)Serializers, backend has nothing to do with it.

Therefore W32 GDK backend should only offer formats that it can
actually do conversion for by itself (such as image/bmp <-> CF_DIB,
or text/uri-list <-> CFSTR_SHELLIDLIST).
2018-10-31 08:40:50 +00:00
Timm Bäder b4acf81609 Merge branch '1422-gtkentry-s-minimum-width-is-hardcoded-to-150px-GTK4' into 'master'
gtkentry: set minimum-width to 0 instead of 150

Closes #1422 and evince#1002

See merge request GNOME/gtk!393
2018-10-26 09:25:36 +00:00
Matej Urbančič 62871400b1 Updated Slovenian translation 2018-10-25 22:06:19 +02:00
Matej Urbančič c4b3337569 Added Slovenian translation 2018-10-25 22:03:51 +02:00
Nelson Benítez León 45e6e0cd04 gtkentry: set minimum-width to 0 instead of 150
and use 150 as natural-width.

Currently there's no way for a GtkEntry to be less
than 150px wide (apart from using "width-chars" property),
this is too much for a default minimum-width, an app
developer may need to have a shorter GtkEntry, for example
when the UI it's been shrunk by the user (see [1]) or when
you want to match the size of another widget (which is less
than 150px) see [2] for Evince bug on using
gtk_combo_box_new_with_model_and_entry() for PDF forms where
GtkEntry of ComboBox is too wide and doesn't match the combo
list width.

Using "width-chars" property may be a workaround to obtain
a short minimum-width for the entry, but is not a proper
solution for the mentioned cases as you may not know how
short your GtkEntry will be, or the fact that using "chars"
as a width unit is not pixel accurate.

Curious note: the commit that introduced the GtkEntry
minimum-width to be 150px is from 20 years ago, see
https://bit.ly/2ySEfK4

[1] This change was already suggested by Benjamin Otte
in a blog comment https://bit.ly/2J96wRo

[2] Fixes issue evince#1002
2018-10-24 23:02:31 +05:00
Timm Bäder 98dd53c2c3 Merge branch 'nirbheek/meson-fallback-dep-fixes' into 'master'
Misc meson fixes for using subproject dependencies

See merge request GNOME/gtk!232
2018-10-24 09:42:12 +00:00
Kristjan SCHMIDT ad7eaf2bb8 Update Esperanto translation 2018-10-24 08:14:41 +00:00
Jakub Steiner ef82f1799f Adwaita: prevent devel styling break selection mode
- Selection mode does not get the special devel styling.

- removed teh last-child() selector for it doesn't work anymore.
  Better style all section of the headerbar than none. Proper fix pending.

https://source.puri.sm/Librem5/libhandy/issues/57
2018-10-22 10:31:20 +02:00
Ignacio Casal Quinteiro 1729da8a3e quartz: do not cache the screen in the gdkmonitor
Instead we just cache the monitor number and get
out of it the nsscreen when it is needed. This is
a requirement since it nsscreen it is not supposed
to be cached.

Fixes: https://gitlab.gnome.org/GNOME/gtk/issues/1312
2018-10-17 10:10:44 +02:00
Matthias Clasen a3ac3b61ef Merge branch '1397-gtknotebook-built-in-popup-menu-listing-tabs-doesn-t-use-tab-label-text-for-the-last-tab-4' into 'master'
Notebook: Ensure menu label updates with tab_label

Closes #1397

See merge request GNOME/gtk!386
2018-10-16 20:49:42 +00:00
LRN 532a48aa92 Merge branch 'lrn/zorder-gtk4' into 'master'
Don't let the OS maintain relative Z-order for windows (GTK4)

See merge request GNOME/gtk!197
2018-10-15 22:48:14 +00:00
Carlos Garnacho f3674688bf tests: Drop "saved positions" test in testgtk
This test solely relies on configure events, which aren't supported anymore.
2018-10-15 20:05:54 +02:00
Carlos Garnacho dd6aa7b870 tests: Drop ::event handler in testgtk
We can use ::size-allocate for it, as window positions in root coordinates
are neither supported nor crucial here.
2018-10-15 17:39:04 +02:00
Carlos Garnacho 21d0e30903 testsuite: Fix gestures tests for the legacy controller
Let it create one with the right propagation phase, so the event propagation
chain stays the same.
2018-10-15 17:39:04 +02:00
Carlos Garnacho 3c73f70dae tests: Use GtkEventControllerMotion in testpopup
Track motion through it, instead of a GtkWidget::event handler.
2018-10-15 17:39:04 +02:00
Carlos Garnacho 65fbd0af4e tests: Remove ::event handler in testwindowsize
We just want widget size here, not windowing configuration events.
2018-10-15 17:39:04 +02:00
Carlos Garnacho 55b32c8a8f gtkwidget: Drop obsolete code
This path is not being hit anymore, gtkmain.c does handle those events
itself.
2018-10-15 17:39:04 +02:00
Carlos Garnacho bb0e964f56 testsuite: Fix gestures test
Was broken by the removal of the default GtkEventControllerLegacy.
2018-10-15 17:39:04 +02:00
Carlos Garnacho 0f4a6bfbf8 gtkeventcontrollerlegacy: Make public
And move ::event into it, dropping the GtkWidget::event signal.
2018-10-15 17:39:04 +02:00
Daniel Boles 4e884b6056 Notebook: Ensure menu_label updates with tab_label
This was noticed in Firefox and demonstrated using a GtkBuilder ui file.
buildable_add_child() calls set_tab_label(), but the latter did nothing
to update the menu_label corresponding to that tab with the new text.
Using Builder to populate the tab child, only tabs other than last got
the right non-default labels, and even that was mostly coincidental, as
adding the main child called update_labels() via real_insert_page(), so
it took effect when the 2nd last main child is added, updating the rest
but leaving the last with the default label, not that given in Builder.

Fix by factoring out the code from child_reordered() to a new helper
menu_item_recreate() and calling that in set_tab_label(), so that
whenever the tab_label is updated, so is its corresponding menu_label.

This fixes the reported case and presumably others that we could write.

fixes https://gitlab.gnome.org/GNOME/gtk/issues/1397
2018-10-12 23:50:12 +01:00
Daniel Boles f252bbc02c Notebook: Don't notify 2x from set_tab_label_text
It calls set_tab_label(), which already does that.
2018-10-12 23:40:16 +01:00
Daniel Boles 9cbd3ac017 gtk-demo/main: Suppress implicit fallthru warning
Comments matched to reassure the compiler that fallthrough is
intentional are supposed to precede the case or default keywords, at
least in GCC, so the one here did not suppress the warning with GCC. We
can just the if condition and put the comment at the end to solve that.

https://developers.redhat.com/blog/2017/03/10/wimplicit-fallthrough-in-gcc-7/
2018-10-12 22:19:25 +01:00
Nirbheek Chauhan 4bae7fb0fd .gitignore: Ignore all subdirs in the subprojects dir 2018-10-12 14:23:53 +05:30
Nirbheek Chauhan b98f5a0823 meson: Always fetch pangoft2_dep from the pango subproject
This ensures that we will use pangoft2 if it is available, and not if
it is not available.

See: https://gitlab.gnome.org/GNOME/pango/merge_requests/6
2018-10-12 13:08:48 +05:30
Nirbheek Chauhan 00c29e1fbe meson: Use proxy-libintl subproject when needed and available
Such as on Windows with MSVC.
2018-10-12 13:08:48 +05:30
Nirbheek Chauhan de3e5be235 meson: Add a fallback for the harfbuzz dependency
This meson port is not upstream yet, so a wrap file is not included.
Upstream has expressed interest but the port hasn't been tested on all
platforms yet. Will be added when it gets upstreamed.

Link to WIP port: https://github.com/centricular/harfbuzz
2018-10-12 13:08:48 +05:30
Timm Bäder ae3e6d1949 emojichooser: Pass chooser to add_emoji 2018-10-11 12:27:56 +02:00
Timm Bäder 114efa83c6 widget: Stop adding a legacy event controller
The only event signal left is ::event and everything needing that
connects to it directly.
2018-10-11 12:27:56 +02:00
Timm Bäder d15df65a9d gl renderer: Save some matrix multiplications
We do this for every single node, which is a little costly, especially
since the common case for the modelview matrix these days is a simple
translation. So, check whether the new modelview matrix is only a
translation matrix and if so, don't do a full matrix multiplication per
node.
2018-10-11 12:27:56 +02:00
Timm Bäder e0a1311e5b spinbutton: Don't use gfloat in a code sample 2018-10-11 12:27:56 +02:00
Timm Bäder 48e88c6ea4 Merge branch 'file-sealing' into 'master'
gdk: seal in-memory files when possible

See merge request GNOME/gtk!353
2018-10-10 11:12:03 +00:00
Timm Bäder 50c63fc39a Merge branch 'gtkbuilder-tag-end-wrong-type' into 'master'
GtkBuildable: Fix the type of the user_data in GtkBuildable.custom_tag_end

See merge request GNOME/gtk!378
2018-10-10 11:09:25 +00:00
Chun-wei Fan 1ca5b41571 gtkimcontextime.c: Fix Korean input
Commit 64a489ad inadvertently introduced a regression that broke Korean
text input because the changes there resulted that only the last input
string that we have from ImmGetCompositionStringW() for each time the
commit signal is emitted is kept, and also as a result the final Korean
character that is input by hitting space is also lost as a result, as we
didn't check for whether we are done with preediting.

Fix these issues by doing the following when we receive the
WM_IME_COMPOSITION message with GCS_RESULTSTR from Windows:
-Do not emit the commit signal during WM_IME_ENDCOMPOSITION, and...
-Emit the commit signal anyways, as we did before c255ba68, however...
-We still save up the string to commit, because we need to re-compute
 the cursor position when we do ->get_preedit_string(), which needs to
 take the GCS_RESULTSTR string we get from WM_IME_COMPOSITION into
 account as well, so that we avoid getting the Pango criticals that
 occur during Chinese (and most likely Japanese) input as the cursor
 position is out-of-range.

Fixes issue #1350.
2018-10-09 17:10:23 +08:00
Chun-wei Fan cebf5ed46c testsuite/gtk/filterlistmodel.c: Avoid GCCism
Pointer arithmetic on gpointers (void *) is a GCCism, so avoid that by
being more explicit with things.
2018-10-09 16:26:36 +08:00
Chun-wei Fan 1ca906008e testsuite/gtk/[flatten|sort]listmodel.c: Avoid VLA usage
Visual Studio is unlikely to support VLAs at any point, so avoid using
them and use g_newa() instead.
2018-10-09 16:26:21 +08:00
Robert Ancell dd69c4e0f2 GtkBuildable: Fix the type of the user_data in GtkBuildable.custom_tag_end
The previous type was a pointer to a pointer, which seems to be a copy-paste
error from GtkBuildable.custom_tag_start which is an out parameter. It was
always cast in use so this is an API break, but not an ABI one.
2018-10-08 11:38:20 +13:00
Daniel Boles cbb0d7ba69 Merge branch 'master' into 'master'
gtkstack: fix null pointer dereference

See merge request GNOME/gtk!361
2018-10-07 17:28:31 +00:00
Aurimas Černius cbdb744c40 Updated Lithuanian translation 2018-10-07 16:57:01 +03:00
LRN 10fef2fbb4 Merge branch 'win32-runtime-immodule-swap-gtk4' into 'master'
GDK W32: Support switching IM contexts at runtime (GTK4)

See merge request GNOME/gtk!372
2018-10-07 09:05:16 +00:00
Benjamin Otte 8e2fb9c2be docs: Update GtkSliceListModel 2018-10-07 02:23:40 +00:00
Mohammed Sadiq f48ed12e78 slicelistmodel: Fix typos in docs 2018-10-07 07:46:58 +05:30
Руслан Ижбулатов 66c0336ead GDK W32: Support switching IM contexts at runtime
This leverages the normal input context switching mechanism in GTK
by making it think that the gtk-im-module setting changed.
The backend returns gtk-im-module value as "ime" if W32
IME API says that an IME is in use. Otherwise it returns
and empty string - this still triggers an input context
switching code, which, not being able to create the desired context
(which is and empty string), falls back to looking at current
keyboard layout (currently that code is still a FIXME).

Paired with the code that signals gtk-im-module change on keyboard layout
switches, this is sufficient to make GTK capable of switching to
the appropriate IM context at runtime. At least, the kinds of context
that specify languages for which they are used automatically by default
(once locale matching is implemented), and the IME context.

Loading other kinds of IM context might still work via specifying
the gtk-im-module setting in gtk ini file, but doing so will likely
make GTK incapable of using the IME context that is used
for Korean, Chinese and Japanese (and some other languages).

Until someone figures out a way to actually change gtk-im-module
setting on Windows at runtime with meaningful values, the behaviour
introduced by this commit seems like a sufficient workaround.
2018-10-06 17:45:30 +00:00
Benjamin Otte 0657a53940 inspector: Highlight CSS node on selection
Fixes #1383
2018-10-06 00:29:31 +02:00
Benjamin Otte eecd5823d0 docs: Put subsection into right section
The widget observer APIs belong into the widget docs, not the window
docs. Oops.
2018-10-06 00:29:31 +02:00
Benjamin Otte 99b769706c video: Add header include guard 2018-10-06 00:29:31 +02:00
Jakub Steiner 39843ebb3f Adwaita: fix devel styling for sidebar apps
- don't put the gradient/cogged wheel on apps that have a split headerbar
  due to having a sidebar
2018-10-04 20:36:44 +02:00
Jeremy Bicha 52bcf7fd46 widget-factory: Add Keyboard Shortcuts menu item
Closes: https://gitlab.gnome.org/GNOME/gtk/issues/916
2018-09-30 20:43:53 -04:00
Jeremy Bicha 43997fb550 widget-factory: Rename About menu item to About Widget Factory
This follows the recommendation in
https://gitlab.gnome.org/GNOME/Initiatives/wikis/App-Menu-Retirement
2018-09-30 20:43:51 -04:00
Jeremy Bicha c59669d376 widget-factory: Move app menu contents to primary menu
GNOME Shell 3.32 will remove support for the app menu
so we need to move its contents to the primary (hamburger)
menu.

widget-factory already had a primary menu.

The only item in the app menu was About.

https://gitlab.gnome.org/GNOME/Initiatives/issues/4
2018-09-30 20:43:41 -04:00
Kristjan SCHMIDT ac97d2be0c Update Esperanto translation 2018-09-30 10:24:25 +00:00
emersion e9a67cc6d0 gdk: seal in-memory files when possible
This can be used by compositors to mmap memory without having to
handle SIGBUS.
2018-09-27 23:35:18 +02:00
Hugo Lefeuvre 44655932c4 gtkstack: fix null pointer dereference
The gtk_stack_snapshot_slide() function dereferences the
last_visible_child pointer without proper != NULL ckeck. This might
result in NULL pointer dereference and crash if last_visible_child is
invalid.

Add a != NULL check before dereferencing the pointer.
2018-09-27 09:53:22 -04:00
Jakub Steiner 278f9a9eda Adwaita: draw insensitive progressbars
- keep inheriting stuff from scales, but
  do draw highlights

Addresses issue #1191
2018-09-26 22:43:31 +02:00
Matthias Clasen a28c7e8839 Merge branch 'wip/sadiq/fixes' into 'master'
docs: Fix inclusion of source files in tutorial

See merge request GNOME/gtk!341
2018-09-26 18:28:23 +00:00
Matthias Clasen 77c8d2df00 Merge branch 'wip/jimmac/nightly-headerbar' into 'master'
Adwaita: tone down the 'devel' styling

See merge request GNOME/gtk!357
2018-09-26 16:11:43 +00:00
Jakub Steiner aeca5858d8 Adwaita: tone down the 'devel' styling
The selected bg was too prominent and intefered with button styling.
2018-09-26 15:50:58 +02:00
Timm Bäder 89b96a864e Merge branch 'wip/arnaudb/fix-dashed-border-4' into 'master'
Make dashed border-style work correctly

See merge request GNOME/gtk!355
2018-09-25 07:12:58 +00:00
Timm Bäder 26302cada5 Update expected node files
We don't technically hide the arrow nodes anymore.
2018-09-24 21:05:07 +02:00
Arnaud B 42d064c62f Make dashed border-style work correctly
There’s a short-path done for focus rectangles, but it can be taken in other conditions, and then fail occasionally to render a dashed line if the border-width is too big.
2018-09-24 09:39:55 +02:00
Piotr Drąg 273189fc1a Update Polish translation 2018-09-23 18:27:30 +02:00
Timm Bäder d51abaea2e scalebutton: Remove unused define 2018-09-23 18:01:59 +02:00
Timm Bäder 248708c282 button: Remove key_controller member
Unneeded now.
2018-09-23 17:59:37 +02:00
Timm Bäder 0e2748006a assistant: Remove some unused defines 2018-09-23 17:34:03 +02:00
Timm Bäder e89bd7dfa2 menu: Remove useless if statement 2018-09-23 17:34:03 +02:00
Timm Bäder 2f6e998a27 menu: Show scroll arrows if necessary 2018-09-23 17:34:03 +02:00
Timm Bäder 7b7296410e menu: Remove arrow visibility flags 2018-09-23 17:34:03 +02:00
Jan Alexander Steffens (heftig) d90e2733ea GtkApplication: Fix CRITICAL on shutdown when register_session=FALSE
Close https://gitlab.gnome.org/GNOME/gtk/issues/1323#note_327705
2018-09-22 17:56:38 +01:00
Daniel Boles 19bf502fde Merge branch 'master' into 'master'
flattenlistmodel: Fix uninitialized variable warning

See merge request GNOME/gtk!347
2018-09-22 16:52:49 +00:00
Piotr Drąg 2b8e30a8ed Use Unicode apostrophes in new strings
See https://developer.gnome.org/hig/stable/typography.html

https://bugzilla.gnome.org/show_bug.cgi?id=772371
2018-09-20 19:01:14 +02:00
Yi-Soo An 4ad8dcebd8 flattenlistmodel: Fix uninitialized variable warning
Variable, added, would be a garbage value if model is NULL and
the following code, if condition, use the uninitialized variable.
A side effect could be occurred by that.

To avoid, the variable is initialized to zero.
2018-09-20 12:45:33 +09:00
Matthias Clasen a966b90e51 Merge branch 'master' into 'master'
Remove some duplication in testfilechooserbutton

See merge request GNOME/gtk!342
2018-09-19 13:46:50 +00:00
Matthias Clasen 5b2a451e75 Merge branch 'installed-tests' into 'master'
Get GTK+ 4 installed-tests closer to working

See merge request GNOME/gtk!348
2018-09-19 11:59:16 +00:00
Emin Tufan Çetin 8105bde835 Update Turkish translation 2018-09-19 11:13:18 +00:00
Emin Tufan Çetin 2329b62c14 Update Turkish translation 2018-09-19 11:05:05 +00:00
Emin Tufan Çetin 1e1bed056f Update Turkish translation 2018-09-19 10:56:13 +00:00
Simon McVittie a0d83bdfa7 testsuite: Install accessibility-dump executable alongside tests
The installed-tests want to run this.

Signed-off-by: Simon McVittie <smcv@debian.org>
2018-09-19 09:41:49 +01:00
Simon McVittie fa8190328d testsuite: Fix installed-test metadata for autotestkeywords
The executable is called autotestkeywords, so we shouldn't try to run
an executable named keywords. Also rename the metadata file to match.

Signed-off-by: Simon McVittie <smcv@debian.org>
2018-09-19 09:40:37 +01:00
Simon McVittie d19cba429d reftests: Fix path to installed-tests in .test metadata
The installed-tests are now namespaced as gtk-4.0 to avoid colliding
with GTK+ 3, but these files weren't updated.

Signed-off-by: Simon McVittie <smcv@debian.org>
2018-09-19 09:37:06 +01:00
Benjamin Otte be2609a271 inspector: Handle case where there's no default application 2018-09-19 04:31:29 +02:00
Benjamin Otte 5bf009a203 cssrbtree: Fix a crasher
After removing elements, there were a few cases where the tree wasn't
properly balanced which could further down violate assumptions about the
layout.

Attached is the original testcase that triggered it. I didn't bother
simplifying it.
2018-09-19 04:31:29 +02:00
LRN 93a89a371e Merge branch 'win32-scroll-both-gtk4' into 'master'
GDK W32: send both smooth and discrete scrolling events (GTK4)

See merge request GNOME/gtk!337
2018-09-18 16:43:37 +00:00
Benjamin Otte 60cb315be6 Merge branch 'revealer-support-min-size-master' into 'master'
gtkrevealer: support minimum size of child

Closes #635

See merge request GNOME/gtk!317
2018-09-18 15:19:12 +00:00
Eduard Braun 73728814b0 GDK W32: fix direction of horizontal smooth scrolling events
Commit 359df028be changed the
code to send GDK_SCROLL_SMOOTH with deltas instead of
GDK_SCROLL_(UP|DOWN|LEFT|RIGHT).

Windows defines deltas inversed for vertical direction
(positive values mean the wheel was turned forward)
but not for horizontal direction
(positive values mean the wheel was turned towards the right).

This commit fixes behavior as both axes were inverted previously.
2018-09-18 13:52:36 +00:00
Руслан Ижбулатов d4098099dd GDK W32: send both smooth and discrete scrolling events
Commit d64467b334 changed the
code to send GDK_SCROLL_SMOOTH with deltas instead of
GDK_SCROLL_(UP|DOWN|LEFT|RIGHT). Change it again, to send
both the GDK_SCROLL_SMOOTH and the GDK_SCROLL_(UP|DOWN|LEFT|RIGHT)
event separately (with the discrete event marked as emulated),
as this is what other backends (such as wayland) do.
2018-09-18 13:52:35 +00:00
Carlos Soriano 57ef793e6d revealer: Support minimum size of child
Up until now when allocating the child it only used the natural size
while the measuring also used the minimum size, resulting in a clipped
child when animating if the child had different minimum size and
natural size. This was an obvious case when using labels that had
ellipsization.

This commit gives full allocation to the child by inverting the size
the revealer reduces from its animation progress.

Code done by Benjamin Otte.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/635
2018-09-18 11:36:29 +02:00
Christoph Reiter 58cdd5139e ci/docker: add lcov so we can create coverage reports
This was requested on IRC; the docker image in the registry is updated already.
2018-09-18 09:55:50 +02:00
Benjamin Otte 2c84049769 treelistmodel: Improve naming a bit
The complexity with model items vs row items is really confusing. Add to
that treelistmodel position vs child model position vs parent position,
and you're so confused, even the best naming can't help.

And once you're there, consider passthrough vs non-passthrough...
2018-09-18 08:03:03 +02:00
Benjamin Otte 29c700d1c7 listmodels: Clarify documentation for function prototypes
Fixes #1341
2018-09-18 08:02:21 +02:00
Mohammed Sadiq 0d7c987b1a Revert "listlistmodel: Fix documentation comment"
This reverts commit 03679d4342.

listlistmodel is private
2018-09-18 10:01:12 +05:30
Mohammed Sadiq 03679d4342 listlistmodel: Fix documentation comment 2018-09-18 09:56:19 +05:30
Georges Basile Stavracas Neto 1a4b60fb36 tree-list-model: Return the correct item type
When passthrough is enabled, it should return the GType
of the child GListModels; when disabled, it should be
GTK_TYPE_TREE_LIST_ROW.

The conditions are inverted however, causing a few
warnings to trigger.

Fix that by returning the correct GType.
2018-09-18 00:51:57 -03:00
Mohammed Sadiq 05b2ae0f31 Merge branch 'wip/sadiq/model-fixes' into 'master'
treelistmodel: Fix memory leak

See merge request GNOME/gtk!344
2018-09-18 02:54:30 +00:00
Mohammed Sadiq f211d71f74 treelistmodel: Fix memory leak
gtk_tree_list_model_init_node() increases the reference count
of the model passed. Let's not do that, and let it take the
model passed.
2018-09-18 07:50:44 +05:30
Mohammed Sadiq 691ab421fb Merge branch 'wip/sadiq/model-fixes' into 'master'
treelistmodel: Fix signal emission on row destroy

See merge request GNOME/gtk!343
2018-09-18 02:03:58 +00:00
Mohammed Sadiq 9e3e9e83ef treelistmodel: Fix signal emission on row destroy 2018-09-18 07:11:27 +05:30
Manu Cornet a0056d5ca8 Remove some duplication in testfilechooserbutton
Most of the code creating the two types of dialogs (open file,
choose folder) is the same. This refactors the common code into a
helper method. This also makes it easier to add other chooser types
for this test (e.g. save file).
2018-09-17 12:27:46 +00:00
Rico Tzschichholz f3e6d00db1 gtk: Fix some g-i annotations warnings 2018-09-17 13:00:36 +02:00
Robert Ancell e55df03fe2 Merge branch 'toolbar-expand' into 'master'
toolbar: Use hexpand/vexpand Gtk+ properties

See merge request GNOME/gtk!334
2018-09-17 08:59:19 +00:00
Robert Ancell c8a13a2d8a toolbar: Use hexpand/vexpand Gtk+ properties 2018-09-17 10:25:59 +02:00
Mohammed Sadiq 6971e2923d docs: Fix inclusion of source files in tutorial 2018-09-17 13:39:22 +05:30
Matthias Clasen 231b76bdd1 tree list model: Add docs 2018-09-16 23:07:00 -04:00
Matthias Clasen 57ba4048de Minor doc fix
Clarify some wording.
2018-09-16 23:07:00 -04:00
Benjamin Otte 545c5f18b2 testsuite: Disable some tests for older glib 2018-09-17 04:30:28 +02:00
Benjamin Otte 5571217218 testsuite: Add tests for GtkSortListModel 2018-09-17 03:57:37 +02:00
Benjamin Otte b92c328425 sortlistmodel: Actually insert unsorted items at the wrong place
We were adding items in reverse order, oops.
2018-09-17 03:57:37 +02:00
Piotr Drąg 8bdcff3320 Update POTFILES.in 2018-09-16 21:02:31 +02:00
Benjamin Otte 9ffd88012d docs: Add missing TreeListModel docs 2018-09-16 19:39:39 +02:00
Matthias Clasen 563fb97f90 Merge branch 'wip/sadiq/fixes' into 'master'
gdkselectioninputstream-x11: Fix memory leak

See merge request GNOME/gtk!340
2018-09-16 17:06:29 +00:00
Benjamin Otte ee5708f543 testtreelistmodel: Display the file icon, because why not 2018-09-16 18:50:17 +02:00
Benjamin Otte b7bf04fabd inspector: Update the controllers list to show parent controllers
Now we show all the controllers that are relevant when widget gets sent
events.
2018-09-16 18:50:17 +02:00
Benjamin Otte b94b8ac38d testtreelistmodel: Make the statusbar display more info
Now display how many items were filtered (if any) and how many
directories remain to be sanned (if any).
2018-09-16 18:50:17 +02:00
Benjamin Otte afd69db678 testtreelistmodel: Sort files by name 2018-09-16 18:50:17 +02:00
Benjamin Otte f3834138f7 GtkSortListModel: Add 2018-09-16 18:50:17 +02:00
Benjamin Otte 64b7c123cc testtreelistmodel: Add search
Add a simple search that does a case insensitive substring search of the
file paths.
2018-09-16 18:50:17 +02:00
Benjamin Otte fcb780ee13 testtreelistmodel: Make the directory loading async
This is way more complicated than it should be, because it requires
manually limiting the number of open file enumerators.

On the other hand, it exhaustively tests the items-changed emission of
all involved listmodels because those signals come in pretty much
randomly.

It's also 50% slower than the sync version, with the caeat that the sync
version only shows the UI after it's done loading, while this version
shows it right away.
2018-09-16 18:50:17 +02:00
Benjamin Otte 65b795b861 testtreelistmodel: Add a hack to handle LONG lists
... and make the lists long by autoexpanding the tree.
2018-09-16 18:50:17 +02:00
Benjamin Otte 64d97b233b GtkSliceListModel: add 2018-09-16 18:50:17 +02:00
Benjamin Otte db8474e5b1 inspector: Make controllers page use gtk_list_box_bind_model() 2018-09-16 18:50:17 +02:00
Benjamin Otte 5e8983883e inspector: Rename "Gestures" page to "Controllers"
And rename GtkInspectorGestures => GtkInspectorControllers, too.
2018-09-16 18:50:17 +02:00
Benjamin Otte 59006e2e03 inspector: Make gestures page handle all controllers
This requires removing support for gesture groups.
2018-09-16 18:50:17 +02:00
Benjamin Otte b6acc31d44 GtkMapListModel: add 2018-09-16 18:50:17 +02:00
Benjamin Otte 6d0fe46cba propertylookuplistmodel: Add
This model just takes an object and a property name and recursively
looks it up. In particular, I want it for:

widget, widget.parent, widget.parent.parent, ...
2018-09-16 18:50:17 +02:00
Benjamin Otte 05e752e096 inspector: Turn object tree into a GtkListBox
The code gets rid of the GtkTreeView and replaces it with a GtkListBox.

Most of the logic is now done via GListModel subclasses.

A big change is that this new list is now tracking updates itself and
doesn't need to be manually updated. All code that used to cause rescans
or add forgotten objects to the tree has been removed.

If objects are missing from the object tree, the logic for tracking them
needs to be added.
2018-09-16 18:50:17 +02:00
Benjamin Otte 2237009983 testsuite: Disable some tests with older glib
Fixes CI.
2018-09-16 18:50:17 +02:00
Benjamin Otte 417ac4ab43 inspector: Use a GtkPicture to display render nodes
Instead of the outdated render node view, use modern GTK APIs.
2018-09-16 18:50:17 +02:00
Benjamin Otte 4495eaae84 inspector: Add an icon to the render node list 2018-09-16 18:50:17 +02:00
Benjamin Otte aba76fe8e9 inspector: Make the render node tree use a ListBox
It used to be a treeview.
2018-09-16 18:50:17 +02:00
Benjamin Otte 867042f88f widget: Add gtk_widget_observe_controllers()
This mirrors gtk_widget_observe_children() - just that it observes the
controllers, not the children.
2018-09-16 18:50:17 +02:00
Benjamin Otte 32ec7dec61 gtk: Add GtkFlattenListModel
We can flatten lists of lists into lists now!
2018-09-16 18:50:17 +02:00
Benjamin Otte d6161e09cd treelistmodel: Add more API to navigate the tree
This adds functionality from GtkTreeIter into GtkTreeListRow that allows
finding items in the model and getting their position for use in
GtkListBox.
2018-09-16 18:50:17 +02:00
Benjamin Otte 4b5fb5ec79 treelistmodel: Refactor to add GtkTreeListRow
This patch does multiple things:

1. Add a custom persistent per-row object.
2. Move all per-row API to that object. This means notifications are now
   possible.
3. Add a "passthrough" construct-only property to the TreeListModel that
   influences if the model returns these new object or passes through
   the ones from the model.

This greatly simplifies the code needed to be written for widgetry,
because one can just connect the per-row object to the expanders that
expand and collapse rows.

As an added power feature, these objects can also be passed through
further models (like filter models).

It also adds kind of a hack to Adwaita to make the test look neat.
2018-09-16 18:50:17 +02:00
Benjamin Otte 4f70f72349 gtk: Add GtkFilterListModel
This is a GListModel implementation that filters the given source model.
2018-09-16 18:50:17 +02:00
Benjamin Otte dd94129e27 widget: Add gtk_widget_observe_children()
This creates a listmodel that tracks a widget's children. Doing so turns
adding/removing children from O(1) to O(N) though, so use with caution.
2018-09-16 18:50:17 +02:00
Benjamin Otte 63e5b827ed window: Add gtk_window_get_toplevels()
This one returns a list of all toplevel windows.
2018-09-16 18:50:17 +02:00
Benjamin Otte 573c63973a gtk: Add GtkTreeListModel
This is a GListModel implementation with a neat API that can be used to
implement trees inside GtkListBox.
2018-09-16 18:50:17 +02:00
Mohammed Sadiq 1ce960c85b gdkselectioninputstream-x11: Fix memory leak 2018-09-16 20:08:25 +05:30
Matthias Clasen d7a5dcba0b gtk_application_inihit: allow no reason
We document this argument as nullable, so treat it as such.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1327
2018-09-13 23:31:48 -04:00
Emin Tufan Çetin a4b1c6b384 Update Turkish translation 2018-09-11 20:17:29 +00:00
Jakub Steiner 0edec9bcae Merge branch 'adwaita-fixes' into 'master'
Adwaita fixes

See merge request GNOME/gtk!333
2018-09-10 14:29:54 +00:00
Adrien Plazas 7d12a843f2 Adwaita: Set selection mode to headerbars if it's on ancestors
This allows to set the container of the headerbars in selection mode
rather than having to set the mode to each element of the title bar.
2018-09-10 15:51:12 +02:00
Adrien Plazas 867efe2e33 Adwaita: Style separator.sidebar
Let separators be declared as sidebars to have the same style as those
drawn by GtkStackSidebar. This also let them handle the selection-mode
class, whether they are assigned it or they descend from something in
selection mode.

Also drop setting the selection mode color for non-sidebar separators.

This is convenient when building a custom sidebar using a GtkSeparator
and to extend a sidebar to the title bar.
2018-09-10 15:50:43 +02:00
Adrien Plazas a121bfa7ec Adwaita: Drop the background of nested headerbars
This is needed to work around headerbar sliding animation issues without
refactoring Adwaita's support of titlebars and headerbars as it may
break applications.

https://gitlab.gnome.org/GNOME/gtk/issues/1264
2018-09-10 15:49:37 +02:00
Jakub Steiner 02758cd48d Merge branch 'wip/adwaita/linked-entry-error-state-fix-master' into 'master'
Adwaita: Fix linked elements in error state

See merge request GNOME/gtk!315
2018-09-10 10:47:05 +00:00
Jakub Steiner 005f932d13 Merge branch 'css-fix' into 'master'
win32 theme: Fix css syntax error

See merge request GNOME/gtk!324
2018-09-07 20:35:07 +00:00
Peter Simonyi 4e8c06eb7a win32 theme: Fix css syntax error 2018-09-07 08:31:22 -04:00
Matthias Clasen ca9aa23619 Add devel style to demos
Lets show this off. Its cool.
2018-09-05 20:10:41 -04:00
Matthias Clasen ae2c765ffd Fix portal path handling
This was broken when I recently introduced this helper
function.
2018-09-05 19:54:32 -04:00
Benjamin Otte ab9455ea1b rendernodepaintable: Fix clipping
We need to translate before clipping, otherwise we clip in totally the
wrong place.
2018-09-05 16:25:07 +02:00
Benjamin Otte 89522e6923 iconhelper: Fix drawing of empty and paintable helpers
Empty helpers did try to draw a NULL paintable (not good) and in the
non-null case code used the wrong width/height.
2018-09-05 06:34:32 +02:00
Timm Bäder 506a4ddad5 Merge branch 'gtkbbox-doc-fix' into 'master'
Minor fixes in documentation of gtkbbox

See merge request GNOME/gtk!318
2018-09-04 10:02:05 +00:00
Lennart Buhl 272e4a0a9d Minor fixes in documentation of gtkbbox 2018-09-03 19:53:16 +02:00
Ask Hjorth Larsen 16deffb48d Updated Danish translation of gtk-properties 2018-09-02 23:46:33 +02:00
Ask Hjorth Larsen a60e951941 Updated Danish translation of gtk 2018-09-02 23:45:47 +02:00
Ask Hjorth Larsen 05306470b0 Updated Danish translation of gtk 2018-09-02 23:19:35 +02:00
Ask Hjorth Larsen 803a8cf333 Updated Danish translation of gtk-properties 2018-09-02 21:42:45 +02:00
Alex Monday 3e5746356e themes: Fix linked elements in error state
Add instructions for color of linked elements border which ajoints
entry, when parent linked entry is in error state.
2018-09-02 14:48:53 +05:00
Daniel Boles c9f1c56776 Adwaita: Regenerate CSS to get window.devel styles
This step was missed before, again.

SASS 3.6 emits rgba(0, 0, 0, 0) instead of transparent, so it wants to
change those too, but that patch was only committed in March and isn't
being backported to the previous stable, so I don't know if others'
versions will do the same - so until it's shown that anyone else (A) is
regenerating CSS and (B) also has 3.6, I'm skipping those changes. See:
https://github.com/sass/libsass/commit/c287f312ac9735aa274bbce56762391ca348cad9
2018-09-02 09:27:38 +01:00
Piotr Drąg fc026b95dd Update Polish translation 2018-08-31 19:47:44 +02:00
Matthias Clasen 2bb97bc136 GtkApplication: Improve the docs
Expand the docs for ::register-session a bit.
2018-08-31 13:38:01 -04:00
Matthias Clasen d4d12171f4 Avoid a pointless goto
We can just return here.
2018-08-31 13:24:17 -04:00
Matthias Clasen 21e484731a Add a helpful comment 2018-08-31 13:23:25 -04:00
Matthias Clasen b82a32676b GtkApplication: track screensaver state
A number of applications want to track the state of the screensaver.
Make this information available as a boolean property. We only listen
for state changes when ::register-session is set to TRUE.

This is implemented for unsandboxed D-Bus access by talking
directly to org.gnome.ScreenSaver or org.freedesktop.ScreenSaver,
and for sandboxed D-Bus by using a (new) portal API.
A Quartz implementation is missing.
2018-08-30 22:53:36 -04:00
Matthias Clasen d7228ae025 GtkApplication: Respect GTK_USE_PORTAL
When the environment variable is set, don't connect
to the session manager, but instead rely on the
inhibit portal.
2018-08-30 22:53:36 -04:00
Matthias Clasen 04c02e9aec file chooser portal: use request path utilities
Less code duplication, more sticky toffee!
2018-08-30 22:53:36 -04:00
Matthias Clasen d6945d81f0 print portal: use request path utilities
Less code duplication, more cookies!
2018-08-30 22:53:36 -04:00
Matthias Clasen 6d6559f982 color picker portal: Add request path utility
Less code duplication, more cake!
2018-08-30 22:53:36 -04:00
Matthias Clasen b271db253f Add utility functions for portal paths
The paths that we create for requests and sessions
need some icky code to create. Keep it in one place.
2018-08-30 22:53:36 -04:00
Marek Cernocky eb9f95e9fa Updated Czech translation 2018-08-30 16:51:17 +02:00
Marek Cernocky d7a5723d66 Updated Czech translation 2018-08-30 14:45:16 +02:00
Jakub Steiner 72498b9e28 Merge branch 'selection-mode-separator' into 'master'
Adwaita: Add color to separator.selection-mode

See merge request GNOME/gtk!309
2018-08-30 07:40:46 +00:00
Matthias Clasen b904fc6ee0 Add a missing cast
This fixes a warning introduced in the previous commit.
2018-08-29 19:55:58 -04:00
Aurimas Černius 9622ba8a0d Updated Lithuanian translation 2018-08-29 22:23:47 +03:00
Matthias Clasen 3b8d206143 The file chooser is no box anymore
Don't treat it as one, it does not like it.

Closes https://gitlab.gnome.org/GNOME/gtk/issues/1297
2018-08-29 13:11:06 -04:00
Anders Jonsson e027fc9272 Update Swedish translation 2018-08-28 21:11:58 +00:00
Kai Willadsen ba6c5ef201 FileChooserWidget: Don't show recent items with private hint set 2018-08-28 16:15:45 -04:00
Piotr Drąg 6a8013735d Update Polish translation 2018-08-28 18:49:34 +02:00
Matthias Clasen c3e72c4d7e Fix a typo
Its Hieroglyphs!

Closes: #1292
2018-08-28 12:24:13 -04:00
Timm Bäder a6c47cb3ab Merge branch 'revealer-clipping' into 'master'
revealer: Only clip child when animating

See merge request GNOME/gtk!301
2018-08-28 14:49:37 +00:00
Rafael Fontenelle cc129e564a Update Brazilian Portuguese translation 2018-08-28 03:28:14 +00:00
Timm Bäder 9fbcbc55d7 Revert "paned: Use a GtkIcon as separator"
This reverts commit 749ef4d71c.

The GtkIcon and GtkGizmo measure code is different, the former uses
-gtk-icon-size.
2018-08-27 18:55:31 +02:00
Timm Bäder 00a27c1e28 box: Remove gtk_box_get_size
One function to measure the box in the opposite of its internal
direction is enough.
2018-08-27 18:53:56 +02:00
Timm Bäder f5f6597abc box: Rename avail_size to for_size everywhere
So we call it like we call it everywhere else.
2018-08-27 18:48:09 +02:00
Timm Bäder fade0afbef box: Simplify compute_size_for_orientation 2018-08-27 18:45:03 +02:00
Timm Bäder 0082675de8 testoverlaystyleclass: Fix CSS snippet 2018-08-27 18:13:01 +02:00
Timm Bäder ed8e784879 remove tests/testinput
It's broken and almost the exact same thing as the drawing demo in
gtk4-demo.
2018-08-27 17:56:02 +02:00
Adrien Plazas a4790b7eaa Adwaita: Add color to separator.selection-mode
This makes separators to look good when separating two header bars in
selection mode.

https://gitlab.gnome.org/GNOME/gtk/issues/1286
2018-08-27 14:07:17 +02:00
Matthias Clasen ed434519d2 Merge branch 'robertroth/readme-fix' into 'master'
docs: README.commits converted to markdown

See merge request GNOME/gtk!304
2018-08-26 23:48:51 +00:00
Robert Roth 4ed4b4fd6a docs: README.commits converted to markdown 2018-08-26 23:48:51 +00:00
Christian Kirbach 369cb702e4 Update German translation 2018-08-26 17:21:13 +00:00
Timm Bäder d246abd085 fishbowl: Use a GtkPicture for videos 2018-08-25 08:06:37 +02:00
Timm Bäder 911627fa0b menuitem: Remove duplicate include 2018-08-25 08:06:34 +02:00
Timm Bäder ec576088bb picture: Fix doc typo 2018-08-25 08:06:28 +02:00
Timm Bäder ab0b54db76 spinner: Remove private struct
Since priv->active is equivalent to the widget state being CHECKED, we
can as well use that everywhere.
2018-08-25 08:06:21 +02:00
Timm Bäder fb51f8be9a colorswatch: Remove dead assignment 2018-08-25 08:06:18 +02:00
Timm Bäder eb22c7c9c3 image: Fix gtkdoc property syntax 2018-08-25 08:06:14 +02:00
Timm Bäder 749ef4d71c paned: Use a GtkIcon as separator
And save a few lines that way.
2018-08-25 08:06:11 +02:00
Timm Bäder f6fae1dd09 menubutton: Remove outdated line
.menu-button is not a style class we use anywhere.
2018-08-25 08:06:07 +02:00
Timm Bäder f21abba82f renderborder: Remove unused function 2018-08-25 08:06:03 +02:00
Timm Bäder bf222a9292 renderborder: Pull some locals into the closest scope
Especially the bounds graphene_rect_t, which is unused in the
non-border-image case.
2018-08-25 08:05:57 +02:00
Timm Bäder 96e465b6d9 checkbutton: Remove snapshot implementation
It just does when the default GtkWidget implementation does anyway:
snapshot all child widgets
2018-08-25 08:05:52 +02:00
Timm Bäder 016de68ceb radiobutton: Save signal IDs like everything else 2018-08-25 08:05:48 +02:00
Timm Bäder d2178bcb94 fixed: Remove unused struct member 2018-08-25 08:04:43 +02:00
Ernestas Kulik f40eb8a1fe revealer: Only clip child when animating
Currently, GtkRevealer clips the child if the transition type is
sliding, regardless of whether the animation had already ended. An
example where that is a problem would be in Nautilus: the file
operations popover button is animated on reveal to draw attention, but,
given that the button is in turn stashed inside a revealer with a
sliding animation, things suddenly fall apart.
2018-08-23 11:13:36 +03:00
Matthias Clasen 9e0f43e8cb entry completion: Avoid critical warnings
We must not call move-to-rect unless we have
a transient parent.
2018-08-20 19:15:27 +00:00
Matthias Clasen 3e4d7250a0 Merge branch 'fix-shifted-scrolling' into 'master'
gtkscrolledwindow: Consider shift key presses when decelerating

Closes #770

See merge request GNOME/gtk!286
2018-08-20 18:26:28 +00:00
Rico Tzschichholz 4ebd14c045 gesturestylus: Add missing array g-i annotation for *_get_axes params 2018-08-20 16:57:54 +02:00
Piotr Drąg ca39b35e2f Update POTFILES.in 2018-08-19 22:05:06 +02:00
Matthias Clasen a32fb5b849 Merge branch 'kill-subsurface' into 'master'
Kill subsurfaces

See merge request GNOME/gtk!299
2018-08-19 03:50:40 +00:00
Matthias Clasen eed19c9269 Move tools to a subdirectory
A small step towards splitting up gtk/
2018-08-19 03:41:25 +00:00
Matthias Clasen e2d691bdb1 gdk: Drop GDK_SURFACE_SUBSURFACE
None of the backends supports this type anymore.
2018-08-18 23:25:12 -04:00
Matthias Clasen a73f961e65 wayland: drop subsurfaces
We don't use them in GTK+ anymore.
2018-08-18 23:25:05 -04:00
Matthias Clasen a7aed5af4b Drop gtk_window_set_use_subsurface
This is no longer used.
2018-08-18 23:24:59 -04:00
Matthias Clasen 220a51e7cb entry completion: stop using subsurfaces
Instead, use a popup and gdk_surface_move_to_rect.
I have not tried to reproduce all details of the old
positioning logic, but moving the popup above/below
the entry works as before.
2018-08-18 23:24:53 -04:00
Jonas Ådahl 6df28420d7 tooltip: Implement positioning using gdk_window_move_to_rect()
In order to make tooltip positioning portable, make use of the
move_to_rect API. Some semantical changes are made, as identical
semantics cannot be implemented using the move-to-rect API.

Primarily the implemented semantics are:

Position the tooltip in the center pixels slightly below (defaults to 4
units below) the tooltipped widget. This is always the case for keyboard
driven tooltips; the case where it tries to avoid the pointer cursor is
not implemented.

For pointer position triggered tooltips, implement the following
additional semantics:

Use the current cursor size to determine the padding used to enlarge the
anchor rectangle. This is to try to avoid the cursor overlapping the
tooltip.

If the anchor rectangle is too tall (meaning if we'd be constrained
and flip on the Y axis, it'd flip too far away from the originally
intended position), rely only on the pointer position to position the
tooltip. The approximate pointer cursor rectangle is used as a anchor
rectangle. Ideally we should use the actual pointer cursor rectangle
(image used as well as hotspot coordinate), but we don't have API to
get that information.

If the anchor rectangle isn't to tall, just make sure the tooltip isn't
too far away from the pointer position on the X axis.

Closes: #134
Closes: #432
Closes: #574
Closes: #579
Closes: #878
2018-08-19 01:26:20 +00:00
Matthias Clasen 081b45399f gdk/wayland: Avoid idempotent wl_subsurface.set_position calls
These may not result on wl_surface.frame callbacks, yet we do trigger
a frame clock tick that would get stuck on the lack of such callback.

https://bugzilla.gnome.org/show_bug.cgi?id=784314
https://gitlab.gnome.org/GNOME/gtk/issues/844

Closes: #844
2018-08-19 01:26:20 +00:00
Matthias Clasen 0874a54708 gdk/wayland: Always map windows 'moved-to-rect' as popups
Only popups can make use of the move-to-rect semantics so it makes no
sense to try anything other surface type.
2018-08-19 01:26:20 +00:00
Matthias Clasen cd40ec2200 gdk/wayland: Don't remap non-subsurface as subsurface
Let's just use the fact that a window was mapped as a subsurface to
remap it above another transient parent instead of relying on the more
complicated 'should-map-as-subsurface' helper function.
2018-08-19 01:26:20 +00:00
Matthias Clasen 62b887e064 Merge branch 'win32-smooth-scrolling-gtk4' into 'master'
GDK W32: Support smooth scrolling (GTK4)

See merge request GNOME/gtk!298
2018-08-18 20:39:56 +00:00
Timm Bäder ce9ce8a5bc menu: Remove key_controller member
Unused.
2018-08-18 20:54:29 +02:00
Timm Bäder 2322f38bf9 menu: Remove initially_pushed_in flag
Unused.
2018-08-18 20:54:29 +02:00
Timm Bäder dcb6c9b4cf menu: Remove seen_item_enter flag
Unused.
2018-08-18 20:54:29 +02:00
Timm Bäder afdeffd820 menu: Remove have_position flag
It's always FALSE.
2018-08-18 20:54:29 +02:00
Timm Bäder 10439aaefe menu: Remove an unnecessary gtk_widget_destroy() call
The unref will already properly free the menu item's resources.
2018-08-18 20:54:29 +02:00
Руслан Ижбулатов d64467b334 GDK W32: Support smooth scrolling
Set delta_x or delta_y for GdkScrollEvent.
HIWORD (wParam) in WM_MOUSE(H)WHEEL is the scroll delta.
A delta value of WHEEL_DELTA (which is 120) means scrolling
one full unit of something (for example, a line).

The delta should also be multiplied by the value that the
SystemParametersInfo (SPI_GETWHEELSCROLL(LINES|CHARS), 0, &value, 0)
call gives back, unless it gives back 0xffffffff, in which case
it indicates that scrolling is page- or screen-based, not line-based
(GDK doesn't support that at the moment).

Also, all deltas should be inverted, since MS sends negative deltas
when scrolling down (rotating the wheel back, in the direction of
the user).

With deltas set the mode should be set to GDK_SCROLL_SMOOTH.

Fixes issue 1263.
2018-08-18 17:02:39 +00:00
Matthias Clasen 099b967885 Don't fail the build if c++ isn't found
The intention of this check was to skip the keyword
test if no c++ compiler is found. But the meson
docs say that add_languages() will abort unless we
pass required: false.
2018-08-18 02:14:56 +00:00
Matthias Clasen d13cd9cb67 Merge branch 'fix-shell-colorpicker' into 'master'
colorpickershell: Unpack the tuple returned from PickColor()

See merge request GNOME/gtk!296
2018-08-17 12:35:46 +00:00
Matthias Clasen 79b87cc543 print portal: don't leak window handles
Pointed out by Christian Persch.

Closes https://gitlab.gnome.org/GNOME/gtk/issues/1274
2018-08-15 23:21:15 +00:00
Matthias Clasen 3c2aceba63 print portal: Plug a memory leak
Pointed out by Christian Persch.

Closes https://gitlab.gnome.org/GNOME/gtk/issues/1271
2018-08-15 23:13:15 +00:00
Matthias Clasen a01feae15b Use defines for bus names
This helps eradicate typos (we had some here).

Closes https://gitlab.gnome.org/GNOME/gtk/issues/1267
2018-08-15 15:54:34 -07:00
Matthias Clasen b4d4f73d9f Merge branch 'sort' into 'master'
updateiconcache: Sort list of entries

See merge request GNOME/gtk!297
2018-08-15 22:00:13 +00:00
Matthias Clasen c1de6219ed font chooser: Remove an unneeded ifdef
We can just always create the axes hashtable.
2018-08-15 14:52:37 -07:00
Bernhard M. Wiedemann b364827a5b updateiconcache: Sort list of entries
because filesystem readdir order is indeterministic.

Without this patch, building openSUSE's balsa package
had variations between builds in /usr/share/balsa/icon-theme.cache
2018-08-15 03:15:14 +02:00
Matthias Clasen bbe362d015 Merge branch 'master' into 'master'
window: Fix memory leak

See merge request GNOME/gtk!295
2018-08-13 19:33:56 +00:00
Iain Lane 08f32c6560 colorpickershell: Unpack the tuple returned from PickColor()
When calling PickColor on org.gnome.Shell, we get back an "a{sv}", which
GDBus provides to us as "(a{sv})".

At the minute we're not unpacking this tuple, and so picking fails with
messages like:

  GLib-CRITICAL **: 13:38:19.439: g_variant_lookup_value: assertion 'g_variant_is_of_type (dictionary, G_VARIANT_TYPE ("a{s*}")) || g_variant_is_of_type (dictionary, G_VARIANT_TYPE ("a{o*}"))' failed

  Gtk-WARNING **: 13:38:19.439: Picking color failed: No color received

Let's unpack it.
2018-08-13 13:52:41 +01:00
Yi-Soo An b3c8c8e592 window: Fix memory leak
https://gitlab.gnome.org/GNOME/gtk/issues/1268
2018-08-13 17:21:42 +09:00
Emin Tufan Çetin ed36933232 Update Turkish translation 2018-08-12 10:47:44 +00:00
Piotr Drąg a90fc088f2 Update Polish translation 2018-08-12 00:01:28 +02:00
Matthias Clasen ff6c4ed07e Merge branch 'gtk-4-improve-error-message' into 'master'
gtkplacessidebar: Improve error message when unlocking volume fails

See merge request GNOME/gtk!267
2018-08-07 10:01:09 +00:00
Piotr Drąg 201f635559 Update Polish translation 2018-08-06 19:01:40 +02:00
Matthias Clasen 59077e4843 migration guide: Mention GtkEventBox
Its gone.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1243
2018-08-05 19:53:02 -04:00
Carlos Soriano 3e6a473082 README: Fix Gdk doc website link 2018-08-05 21:59:27 +00:00
Carlos Soriano 580d96620e README: Document nightly docs location
Useful for exposing the documentation early.
2018-08-05 20:41:29 +00:00
segfault 61f50f2410 gtkplacessidebar: Improve error message when unlocking volume fails 2018-08-05 18:59:40 +02:00
Aurimas Černius 61b2f3c996 Updated Lithuanian translation 2018-08-05 16:06:33 +03:00
Timm Bäder ab30850aad widget: Rename width and height member to {width,height}_request
Because that's much closer to the meaning of those values.
2018-08-05 10:22:11 +02:00
Timm Bäder f5e04b59e9 main: Pass toplevel_widget directly to GtkWidget API
We already have the toplevel as GtkWidget: toplevel_widget.
2018-08-05 10:22:10 +02:00
Timm Bäder c67bcf09b9 sizerequestcache: Inline out-var assignments
The additional assignment to the old result variable just adds an
indirection even though we know the point where we assign it in all
cases. Just pass the values out and return in those cases instead.
2018-08-05 10:22:10 +02:00
Timm Bäder 5eba0bc932 widgetprivate: Remove useless prototype
We implement that function lower down in that header file.
2018-08-05 10:22:10 +02:00
Timm Bäder ff2ba52bc6 pathbar: Remove priv pointer 2018-08-05 10:22:10 +02:00
Timm Bäder a822d6fce9 menuitem: Don't redraw unnecessarily
The gtk_widget_(un)set_state_flags calls before will do this if
necessary.
2018-08-05 10:22:10 +02:00
Timm Bäder b749fe4270 menu: Use correct content height 2018-08-05 10:22:10 +02:00
Timm Bäder 933cb857cf menu: Allocate children according to scroll_offset
This was done by simply moving the bin_window before but now we have to
do it ourselves.
2018-08-05 10:22:10 +02:00
Timm Bäder dde535bbdf levelbar: Don't return a double value from a gboolean function 2018-08-05 10:22:10 +02:00
Timm Bäder 71b36db88d acitonbar: Remove snapshot implementation 2018-08-05 10:22:10 +02:00
Timm Bäder b5576397f7 modelbutton: Remove snapshot implementation
Previously, GtkBin was only snapshot'ing its one and only child, but
nowadays it doesn't implement snapshot at all and the default
implementation in GtkWidget just snapshots all child widgets, which is
exactly what the implementation in gtkmodelbutton.c was doing.
2018-08-05 10:22:10 +02:00
Matthias Clasen 4e86858405 Make color picker circular
The need for center alignment was pointed out by Timm Baeder.
2018-08-04 21:42:28 -04:00
Sebastian Keller 14b21d78db gtkscrolledwindow: Consider shift key presses when decelerating
Otherwise horizontal scrolling using the shift key would decelerate
vertically.

Fixes https://gitlab.gnome.org/GNOME/gtk/issues/770
2018-08-04 16:24:33 +02:00
Mario Blättermann 35829a7272 Update German translation 2018-08-04 11:25:21 +00:00
Ernestas Kulik 0eb60fb03e Merge branch 'sidebar-spinner-visibility' into 'master'
sidebarrow: Hide busy_spinner by default

See merge request GNOME/gtk!285
2018-08-03 10:45:04 +00:00
Ernestas Kulik 94162197a1 sidebarrow: Hide busy_spinner by default
Since the original implementation was likely based on GTK+ 3, the change
in default visibility might have not been considered, which results in
all rows suddenly sporting a visible spinner when opening a fresh file
chooser.
2018-08-03 13:29:07 +03:00
Matthias Clasen 877fffdd5e Merge branch 'fix-app-id' into 'master'
Make xdg-shell's app_id match GApplication's application-id property

Closes #653

See merge request GNOME/gtk!284
2018-08-03 02:09:09 +00:00
Matthias Clasen 8669d31c30 color picker: Also try kwin
use a kwin color picker when we run under kwin.
2018-08-02 20:55:07 -04:00
Matthias Clasen e76d17a786 Only use the portal color picker when appropriate
This is just moving this check around.
2018-08-02 20:54:21 -04:00
Matthias Clasen 5ab90f1a80 Add a kwin color picker
This uses the org.kde.kwin.ColorPicker interface.
2018-08-02 20:53:37 -04:00
Benjamin Otte 5b1fd111d1 Merge branch 'gbsneto/issue-1258' into 'master'
listbox: Unparent child after removing from sequence

Closes #1258

See merge request GNOME/gtk!283
2018-08-02 14:14:10 +00:00
Georges Basile Stavracas Neto 5596feae9b listbox: Store child iter in a variable when removing
Unparenting a GtkListBoxRow can drop its last reference, which
will free its memory. Right after unparenting, though, we were
accessing the row's iter - which assumes that the row is still
alive. This causes a crash when, for example, binding two or
more models to the listbox.

Fix that by storing the iter in a variable, and not trying to
access it after unparenting. After unparenting, the variables
that are potentially garbage were explicitly assigned NULL for
clarity.

Fixes https://gitlab.gnome.org/GNOME/gtk/issues/1258
2018-08-02 10:24:12 -03:00
Guido Günther 8fb8303ba0 demos: Make desktop file names match the application id 2018-08-02 12:15:43 +02:00
Guido Günther 06e4c3c991 examples: Use appliction id as desktop file base name 2018-08-02 11:10:21 +02:00
Guido Günther f25f3b3c47 docs: Explain desktop file id == application_id in migration guide 2018-08-02 11:10:21 +02:00
Guido Günther 72ec8963d7 gdk: Use application_id as xdg_shell's app_id if available
This (manually) reverts commit e1fd87728d

This makes sure xdg_shell's app_id matches the DBus name of the the
appliation when using GtkApplication. It also allows the compositor to
derive the desktop file ID from the app_id:

   https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/xdg-shell/xdg-shell.xml?id=298d888ac718eae57ff2245d373d4327074506ea#n598

Closes #653
2018-08-02 11:03:41 +02:00
Benjamin Otte 50d5666db0 container: Remove focus chains
They're prectically unused.

Widgets who want to influcence the focus chain behavior should implement
GtkWidgetClass::focus and deal with focus there.
2018-07-31 22:34:27 +02:00
Benjamin Otte e06044530f widgetfocus: Fix copy/paste error
This lead to erratic focus behavior with <Tab> in hboxes, where the
smallest child got focus first instead of the leftmost child.
2018-07-31 22:34:27 +02:00
Benjamin Otte 7ce7e5503f colorpicker: Fix gcc warning 2018-07-31 22:34:27 +02:00
Matthias Clasen 0ba307995d Mention gtk_widget_show_all in the migration guide
This function is gone.

Closes https://gitlab.gnome.org/GNOME/gtk/issues/1242
2018-07-31 13:38:10 -04:00
Руслан Ижбулатов b7f9a5419f GDK W32: Use SWP_NOOWNERZORDER everywhere it can be applied
There is no reason why we shouldn't pass this flag every time
Z-order changes. We have separate routines that are used to
maintain relative Z-order, so it should be completely OK to
pass SWP_NOOWNERZORDER to let the OS know that it shouldn't try
to maintain relative Z-order of the windows when raising them.
2018-06-17 10:59:49 +00:00
Руслан Ижбулатов 6cfa799ca1 GDK W32: Don't let TEMP surfaces cause zorder side-effects
Pass SWP_NOOWNERZORDER when rising TEMP surfaces to the top. This ensures that
they don't drag anything else to the top with them. The use-case for this is
a tooltip appearing for a non-foreground surface, causing said surface to rise
above other surfaces, some of which maybe foreground at the moment.

https://bugzilla.gnome.org/show_bug.cgi?id=784766
2018-06-17 10:59:47 +00:00
417 changed files with 70638 additions and 47958 deletions
+1
View File
@@ -0,0 +1 @@
/subprojects/*/
+2 -2
View File
@@ -13,7 +13,7 @@ stages:
- subprojects/pango/
fedora-x86_64:
image: registry.gitlab.gnome.org/gnome/gtk/master:v1
image: registry.gitlab.gnome.org/gnome/gtk/master:v2
stage: build
script:
- bash -x ./.gitlab-ci/test-docker.sh
@@ -64,7 +64,7 @@ flatpak:widget-factory:
<<: *flatpak-defaults
pages:
image: registry.gitlab.gnome.org/gnome/gtk/master:v1
image: registry.gitlab.gnome.org/gnome/gtk/master:v2
stage: deploy
script:
- meson -Ddocumentation=true _build .
+3 -2
View File
@@ -1,4 +1,4 @@
FROM fedora:28
FROM fedora:29
RUN dnf -y install \
hicolor-icon-theme \
@@ -33,6 +33,7 @@ RUN dnf -y install \
iso-codes \
itstool \
json-glib-devel \
lcov \
libattr-devel \
libepoxy-devel \
libffi-devel \
@@ -69,7 +70,7 @@ RUN dnf -y install \
xorg-x11-server-Xvfb \
&& dnf clean all
RUN pip3 install meson
RUN pip3 install meson==0.49.0
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}
+1 -1
View File
@@ -2,7 +2,7 @@
set -e
TAG="registry.gitlab.gnome.org/gnome/gtk/master:v1"
TAG="registry.gitlab.gnome.org/gnome/gtk/master:v2"
sudo docker build --build-arg HOST_USER_ID="$UID" --tag "${TAG}" \
--file "Dockerfile" .
+223 -22
View File
@@ -1,31 +1,144 @@
If you want to hack on the GTK+ project, you'll need to have the development
tools appropriate for your operating system, including:
# Contribution guidelines
Thank you for considering contributing to the GTK project!
These guidelines are meant for new contributors, regardless of their level
of proficiency; following them allows the maintainers of the GTK project to
more effectively evaluate your contribution, and provide prompt feedback to
you. Additionally, by following these guidelines you clearly communicate
that you respect the time and effort that the people developing GTK put into
managing the project.
GTK is a complex free software GUI toolkit, and it would not exist without
contributions from the free and open source software community. There are
many things that we value:
- bug reporting and fixing
- documentation and examples
- tests
- new features
Please, do not use the issue tracker for support questions. If you have
questions on how to use GTK effectively, you can use:
- the `#gtk+` IRC channel on irc.gnome.org
- the [gtk](https://mail.gnome.org/mailman/listinfo/gtk-list) mailing list,
for general questions on GTK
- the [gtk-app-devel](https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list)
mailing list, for questions on application development with GTK
- the [gtk-devel](https://mail.gnome.org/mailman/listinfo/gtk-devel-list)
mailing list, for questions on developing GTK itself
You can also look at the GTK tag on [Stack
Overflow](https://stackoverflow.com/questions/tagged/gtk).
The issue tracker is meant to be used for actionable issues only.
## How to report bugs
### Security issues
You should not open a new issue for security related questions.
When in doubt, send an email to the [security](mailto:security@gnome.org)
mailing list.
### Bug reports
If you're reporting a bug make sure to list:
0. which version of GTK are you using?
0. which operating system are you using?
0. the necessary steps to reproduce the issue
0. the expected outcome
0. a description of the behavior; screenshots are also welcome
0. a small, self-contained example exhibiting the behavior; if this
is not available, try reproducing the issue using the GTK examples
or interactive tests
If the issue includes a crash, you should also include:
0. the eventual warnings printed on the terminal
0. a backtrace, obtained with tools such as GDB or LLDB
For small issues, such as:
- spelling/grammar fixes in the documentation
- typo correction
- comment clean ups
- changes to metadata files (CI, `.gitignore`)
- build system changes
- source tree clean ups and reorganizations
You should directly open a merge request instead of filing a new issue.
### Features and enhancements
Feature discussion can be open ended and require high bandwidth channels; if
you are proposing a new feature on the issue tracker, make sure to make
an actionable proposal, and list:
0. what you're trying to achieve
0. prior art, in other toolkits or applications
0. design and theming changes
If you're proposing the integration of new features it helps to have
multiple applications using shared or similar code, especially if they have
iterated over it various times.
Each feature should also come fully documented, and with tests.
## Your first contribution
### Prerequisites
If you want to contribute to the GTK project, you will need to have the
development tools appropriate for your operating system, including:
- Python 3.x
- Meson
- Ninja
- Gettext (19.7 or newer)
- a C99 compatible compiler
- a [C99 compatible compiler](https://wiki.gnome.org/Projects/GLib/CompilerRequirements)
Up-to-date instructions about developing GNOME applications and libraries
can be found here:
can be found on [the GNOME Developer Center](https://developer.gnome.org).
* https://developer.gnome.org
The GTK project uses GitLab for code hosting and for tracking issues. More
information about using GitLab can be found [on the GNOME
wiki](https://wiki.gnome.org/GitLab).
Information about using GitLab with GNOME can be found here:
### Dependencies
* https://wiki.gnome.org/GitLab
In order to get GTK from Git installed on your system, you need to have the
required versions of all the software dependencies required by GTK; typically,
this means a recent version of GLib, Cairo, Pango, and ATK, as well as the
platform-specific dependencies for the windowing system you are using (Wayland,
X11, Windows, or macOS).
In order to get Git GTK+ installed on your system, you need to have the
required versions of all the GTK+ dependencies; typically, this means a
recent version of GLib, Cairo, Pango, and ATK, as well as the platform
specific dependencies for the windowing system you are using (Wayland, X11,
Windows, or macOS).
The core dependencies for GTK are:
- [GLib, GObject, and GIO](https://gitlab.gnome.org/GNOME/glib)
- [Cairo](http://cairographics.org)
- [Pango](https://gitlab.gnome.org/GNOME/pango)
- [GdkPixbuf](https://gitlab.gnome.org/GNOME/gdk-pixbuf)
- [Epoxy](https://github.com/anholt/libepoxy)
- [ATK](https://gitlab.gnome.org/GNOME/atk)
- [Graphene](https://github.com/ebassi/graphene)
GTK will attempt to download and build some of these dependencies if it
cannot find them on your system.
Additionally, you may want to look at projects that create a development
environment for you, like [jhbuild](https://wiki.gnome.org/HowDoI/Jhbuild)
and [gvsbuild](https://github.com/wingtk/gvsbuild).
### Getting started
You should start by forking the GTK repository from the GitLab web UI, and
cloning from your fork:
```ssh
```sh
$ git clone https://gitlab.gnome.org/yourusername/gtk.git
$ cd gtk
```
@@ -38,7 +151,7 @@ $ git clone git@gitlab.gnome.org:GNOME/gtk.git
$ cd gtk
```
To compile the Git version of GTK+ on your system, you will need to
To compile the Git version of GTK on your system, you will need to
configure your build using Meson:
```sh
@@ -47,11 +160,6 @@ $ cd _builddir
$ ninja
```
**Note**: For information about submitting patches and pushing changes
to Git, see the `README.md` and `README.commits` files. In particular,
don't, under any circumstances, push anything to Git before reading and
understanding `README.commmits`.
Typically, you should work on your own branch:
```sh
@@ -60,6 +168,99 @@ $ git checkout -b your-branch
Once you've finished working on the bug fix or feature, push the branch
to the Git repository and open a new merge request, to let the GTK
maintainers review your contribution. The [CODE-OWNERS](./docs-CODE-OWNERS)
document contains the list of core contributors to GTK and the areas for
which they are responsible.
maintainers review your contribution.
### Code reviews
Each contribution is reviewed by the core developers of the GTK project.
The [CODE-OWNERS](./docs/CODE-OWNERS) document contains the list of core
contributors to GTK and the areas for which they are responsible; you
should ensure to receive their review and signoff on your changes.
### Commit messages
The expected format for git commit messages is as follows:
```plain
Short explanation of the commit
Longer explanation explaining exactly what's changed, whether any
external or private interfaces changed, what bugs were fixed (with bug
tracker reference if applicable) and so forth. Be concise but not too
brief.
Closes #1234
```
- Always add a brief description of the commit to the _first_ line of
the commit and terminate by two newlines (it will work without the
second newline, but that is not nice for the interfaces).
- First line (the brief description) must only be one sentence and
should start with a capital letter unless it starts with a lowercase
symbol or identifier. Don't use a trailing period either. Don't exceed
72 characters.
- The main description (the body) is normal prose and should use normal
punctuation and capital letters where appropriate. Consider the commit
message as an email sent to the developers (or yourself, six months
down the line) detailing **why** you changed something. There's no need
to specify the **how**: the changes can be inlined.
- When committing code on behalf of others use the `--author` option, e.g.
`git commit -a --author "Joe Coder <joe@coder.org>"` and `--signoff`.
- If your commit is addressing an issue, use the
[GitLab syntax](https://docs.gitlab.com/ce/user/project/issues/automatic_issue_closing.html)
to automatically close the issue when merging the commit with the upstream
repository:
```plain
Closes #1234
Fixes #1234
Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1234
```
- If you have a merge request with multiple commits and none of them
completely fixes an issue, you should add a reference to the issue in
the commit message, e.g. `Bug: #1234`, and use the automatic issue
closing syntax in the description of the merge request.
### Commit access to the GTK repository
GTK is part of the GNOME infrastructure. At the current time, any
person with write access to the GNOME repository can merge changes to
GTK. This is a good thing, in that it encourages many people to work
on GTK, and progress can be made quickly. However, GTK is a fairly
large and complicated project on which many other things depend, so to
avoid unnecessary breakage, and to take advantage of the knowledge
about GTK that has been built up over the years, we'd like to ask
people committing to GTK to follow a few rules:
0. Ask first. If your changes are major, or could possibly break existing
code, you should always ask. If your change is minor and you've been
working on GTK for a while it probably isn't necessary to ask. But when
in doubt, ask. Even if your change is correct, somebody may know a
better way to do things. If you are making changes to GTK, you should
be subscribed to the [gtk-devel](https://mail.gnome.org/mailman/listinfo/gtk-devel-list)
mailing list; this is a good place to ask about intended changes.
The `#gtk+` IRC channel on irc.gnome.org is also a good place to find GTK
developers to discuss changes, but if you live outside of the EU/US time
zones, an email to the gtk-devel mailing list is the most certain and
preferred method.
0. Ask _first_.
0. Always write a meaningful commit message. Changes without a sufficient
commit message will be reverted.
0. Never push to the `master` branch, or any stable branches, directly; you
should always go through a merge request, to ensure that the code is
tested on the CI infrastructure at the very least. A merge request is
also the proper place to get a comprehensive code review from the core
developers of GTK.
If you have been contributing to GTK for a while and you don't have commit
access to the repository, you may ask to obtain it following the [GNOME account
process](https://wiki.gnome.org/AccountsTeam/NewAccounts).
-72
View File
@@ -1,72 +0,0 @@
GTK+ is part of the GNOME git repository. At the current time, any
person with write access to the GNOME repository, can make changes to
GTK+. This is a good thing, in that it encourages many people to work
on GTK+, and progress can be made quickly. However, GTK+ is a fairly
large and complicated package that many other things depend on, so to
avoid unnecessary breakage, and to take advantage of the knowledge
about GTK+ that has been built up over the years, we'd like to ask
people committing to GTK+ to follow a few rules:
0) Ask first. If your changes are major, or could possibly break existing
code, you should always ask. If your change is minor and you've
been working on GTK+ for a while it probably isn't necessary
to ask. But when in doubt, ask. Even if your change is correct,
somebody may know a better way to do things.
If you are making changes to GTK+, you should be subscribed
to gtk-devel-list@gnome.org. (Subscription address:
gtk-devel-list-request@gnome.org.) This is a good place to ask
about intended changes.
#gtk+ on GIMPNet (irc.gimp.org, irc.us.gimp.org, irc.eu.gimp.org, ...)
is also a good place to find GTK+ developers to discuss changes with,
however, email to gtk-devel-list is the most certain and preferred
method.
1) Ask _first_.
2) With git, we no longer maintain a ChangeLog file, but you are expected
to produce a meaningful commit message. Changes without a sufficient
commit message will be reverted. See below for the expected format
of commit messages.
Notes:
* When developing larger features or complicated bug fixes, it is
advisable to work in a branch in your own cloned GTK+ repository.
You may even consider making your repository publically available
so that others can easily test and review your changes.
* The expected format for git commit messages is as follows:
=== begin example commit ===
Short explanation of the commit
Longer explanation explaining exactly what's changed, whether any
external or private interfaces changed, what bugs were fixed (with bug
tracker reference if applicable) and so forth. Be concise but not too brief.
=== end example commit ===
- Always add a brief description of the commit to the _first_ line of
the commit and terminate by two newlines (it will work without the
second newline, but that is not nice for the interfaces).
- First line (the brief description) must only be one sentence and
should start with a capital letter unless it starts with a lowercase
symbol or identifier. Don't use a trailing period either. Don't exceed
72 characters.
- The main description (the body) is normal prose and should use normal
punctuation and capital letters where appropriate. Normally, for patches
sent to a mailing list it's copied from there.
- When committing code on behalf of others use the --author option, e.g.
git commit -a --author "Joe Coder <joe@coder.org>" and --signoff.
Owen Taylor
13 Aug 1998
17 Apr 2001
Matthias Clasen
31 Mar 2009
+5
View File
@@ -31,6 +31,11 @@ Information about mailing lists can be found at
- http://www.gtk.org/mailing-lists.php
Nightly documentation can be found at
- Gtk: https://gnome.pages.gitlab.gnome.org/gtk/gtk/
- Gdk: https://gnome.pages.gitlab.gnome.org/gtk/gdk/
- Gsk: https://gnome.pages.gitlab.gnome.org/gtk/gsk/
Building and installing
-----------------------
-1
View File
@@ -5,7 +5,6 @@
"sdk": "org.gnome.Sdk",
"command": "gtk4-demo",
"tags": ["devel", "development", "nightly"],
"rename-desktop-file": "gtk4-demo.desktop",
"rename-icon": "gtk4-demo",
"desktop-file-name-prefix": "(Development) ",
"finish-args": [
@@ -5,7 +5,6 @@
"sdk": "org.gnome.Sdk",
"command": "gtk4-widget-factory",
"tags": ["devel", "development", "nightly"],
"rename-desktop-file": "gtk4-widget-factory.desktop",
"rename-icon": "gtk4-widget-factory",
"desktop-file-name-prefix": "(Development) ",
"finish-args": [
+7 -4
View File
@@ -455,13 +455,16 @@ demo_application_window_constructed (GObject *object)
}
static void
demo_application_window_size_allocate (GtkWidget *widget,
const GtkAllocation *allocation,
int baseline)
demo_application_window_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
DemoApplicationWindow *window = (DemoApplicationWindow *)widget;
GTK_WIDGET_CLASS (demo_application_window_parent_class)->size_allocate (widget, allocation,
GTK_WIDGET_CLASS (demo_application_window_parent_class)->size_allocate (widget,
width,
height,
baseline);
if (!window->maximized && !window->fullscreen)
+2 -2
View File
@@ -144,7 +144,7 @@ create_capital_store (void)
{ NULL, "Jackson" },
{ NULL, "Jefferson City" },
{ NULL, "Juneau" },
{ "K - O" },
{ "K - O", NULL },
{ NULL, "Lansing" },
{ NULL, "Lincoln" },
{ NULL, "Little Rock" },
@@ -154,7 +154,7 @@ create_capital_store (void)
{ NULL, "Nashville" },
{ NULL, "Oklahoma City" },
{ NULL, "Olympia" },
{ NULL, "P - S" },
{ "P - S", NULL },
{ NULL, "Phoenix" },
{ NULL, "Pierre" },
{ NULL, "Providence" },
+3 -1
View File
@@ -134,7 +134,9 @@ static GtkWidget *
create_video (void)
{
GtkMediaStream *stream = gtk_media_file_new_for_resource ("/images/gtk-logo.webm");
GtkWidget *w = gtk_image_new_from_paintable (GDK_PAINTABLE (stream));
GtkWidget *w = gtk_picture_new_for_paintable (GDK_PAINTABLE (stream));
gtk_widget_set_size_request (w, 64, 64);
gtk_media_stream_set_loop (stream, TRUE);
gtk_media_stream_play (stream);
g_object_unref (stream);
+6 -5
View File
@@ -128,9 +128,10 @@ gtk_fishbowl_measure (GtkWidget *widget,
}
static void
gtk_fishbowl_size_allocate (GtkWidget *widget,
const GtkAllocation *allocation,
int baseline)
gtk_fishbowl_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkFishbowl *fishbowl = GTK_FISHBOWL (widget);
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
@@ -147,8 +148,8 @@ gtk_fishbowl_size_allocate (GtkWidget *widget,
continue;
gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
child_allocation.x = allocation->x + round (child->x * (allocation->width - child_requisition.width));
child_allocation.y = allocation->y + round (child->y * (allocation->height - child_requisition.height));
child_allocation.x = round (child->x * (width - child_requisition.width));
child_allocation.y = round (child->y * (height - child_requisition.height));
child_allocation.width = child_requisition.width;
child_allocation.height = child_requisition.height;
+6 -7
View File
@@ -831,15 +831,14 @@ load_file (const gchar *demoname,
/* Skipping blank lines */
while (g_ascii_isspace (*p))
p++;
if (*p)
{
p = lines[i];
state++;
/* Fall through */
}
else
if (!*p)
break;
p = lines[i];
state++;
/* Fall through */
case 3:
/* Reading program body */
gtk_text_buffer_insert (source_buffer, &start, p, -1);
+1
View File
@@ -16,6 +16,7 @@
</columns>
</object>
<object class="GtkApplicationWindow" id="window">
<style><class name="devel"/></style>
<property name="default-width">800</property>
<property name="default-height">600</property>
<property name="title">GTK+ Demo</property>
+1 -1
View File
@@ -129,7 +129,7 @@ foreach icon_size: [ '16x16', '22x22', '24x24', '32x32', '48x48', '256x256', ]
endforeach
# desktop file
install_data('gtk4-demo.desktop', install_dir: gtk_applicationsdir)
install_data('org.gtk.Demo.desktop', install_dir: gtk_applicationsdir)
# GSettings
install_data('org.gtk.Demo.gschema.xml', install_dir: gtk_schemasdir)
+6 -5
View File
@@ -84,15 +84,16 @@ drawing_area_ensure_surface (DrawingArea *area,
}
static void
drawing_area_size_allocate (GtkWidget *widget,
const GtkAllocation *allocation,
int baseline)
drawing_area_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
DrawingArea *area = (DrawingArea *) widget;
drawing_area_ensure_surface (area, allocation->width, allocation->height);
drawing_area_ensure_surface (area, width, height);
GTK_WIDGET_CLASS (drawing_area_parent_class)->size_allocate (widget, allocation, baseline);
GTK_WIDGET_CLASS (drawing_area_parent_class)->size_allocate (widget, width, height, baseline);
}
static void
+5 -4
View File
@@ -55,10 +55,11 @@ create_complex_popover (GtkWidget *parent,
}
static void
entry_size_allocate_cb (GtkEntry *entry,
const GtkAllocation *allocation,
int baseline,
gpointer user_data)
entry_size_allocate_cb (GtkEntry *entry,
int width,
int height,
int baseline,
gpointer user_data)
{
GtkEntryIconPosition popover_pos;
GtkPopover *popover = user_data;
+3 -14
View File
@@ -12,12 +12,10 @@ do_transparent (GtkWidget *do_widget)
if (!window)
{
GtkWidget *sw;
GtkWidget *overlay;
GtkWidget *button;
GtkWidget *label;
GtkWidget *box;
GtkWidget *image;
GtkWidget *picture;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
@@ -54,17 +52,8 @@ do_transparent (GtkWidget *do_widget)
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), button);
gtk_container_child_set (GTK_CONTAINER (overlay), button, "blur", 5.0, NULL);
sw = gtk_scrolled_window_new (NULL, NULL);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (overlay), sw);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (sw), box);
image = gtk_image_new_from_resource ("/transparent/portland-rose.jpg");
gtk_container_add (GTK_CONTAINER (box), image);
picture = gtk_picture_new_for_resource ("/transparent/portland-rose.jpg");
gtk_container_add (GTK_CONTAINER (overlay), picture);
}
if (!gtk_widget_get_visible (window))
+1 -1
View File
@@ -17,4 +17,4 @@ executable('gtk4-icon-browser',
link_args: extra_demo_ldflags,
install: true)
install_data('gtk4-icon-browser.desktop', install_dir: gtk_applicationsdir)
install_data('org.gtk.IconBrowser.desktop', install_dir: gtk_applicationsdir)
+1
View File
@@ -6,6 +6,7 @@
<property name="child-model">store</property>
</object>
<template class="IconBrowserWindow" parent="GtkApplicationWindow">
<style><class name="devel"/></style>
<property name="title" translatable="yes">Icon Browser</property>
<property name="default-width">1024</property>
<property name="default-height">768</property>
-19
View File
@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<menu id="app-menu">
<section>
<item>
<attribute name="label" translatable="yes">About</attribute>
<attribute name="action">app.about</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">_Quit</attribute>
<attribute name="action">app.quit</attribute>
<attribute name="accel">&lt;Primary&gt;q</attribute>
</item>
</section>
</menu>
</interface>
+1 -1
View File
@@ -13,7 +13,7 @@ executable('gtk4-widget-factory',
install: true)
# desktop file
install_data('gtk4-widget-factory.desktop', install_dir: gtk_applicationsdir)
install_data('org.gtk.WidgetFactory.desktop', install_dir: gtk_applicationsdir)
# icons
icontheme_dir = join_paths(gtk_datadir, 'icons/hicolor')
@@ -6,9 +6,6 @@
<gresource prefix="/org/gtk/WidgetFactory">
<file>widget-factory.css</file>
</gresource>
<gresource prefix="/org/gtk/WidgetFactory/gtk">
<file preprocess="xml-stripblanks">menus.ui</file>
</gresource>
<gresource prefix="/org/gtk/WidgetFactory/gtk">
<file preprocess="xml-stripblanks">help-overlay.ui</file>
</gresource>
+12 -1
View File
@@ -16,6 +16,16 @@
<attribute name="action">win.transition</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
<attribute name="action">win.show-help-overlay</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_About Widget Factory</attribute>
<attribute name="action">app.about</attribute>
</item>
</section>
</menu>
<menu id="dinner_menu">
<section>
@@ -396,6 +406,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
</columns>
</object>
<object class="GtkApplicationWindow" id="window">
<style><class name="devel"/></style>
<property name="title">GTK+ Widget Factory</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="headerbar1">
@@ -3583,4 +3594,4 @@ bad things might happen.</property>
</object>
</child>
</object>
</interface>
</interface>
@@ -44,7 +44,7 @@
<informalexample>
<para>Create a new file with the following content named <filename>example-0.c.</filename></para>
<programlisting><xi:include href="../../../../examples/window-default.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/window-default.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>
@@ -153,7 +153,7 @@
<example id="gtk-getting-started-hello-world">
<title>Hello World in GTK+</title>
<para>Create a new file with the following content named example-1.c.</para>
<programlisting><xi:include href="../../../../examples/hello-world.c" parse="text">
<programlisting><xi:include href="@SRC_DIR@/examples/hello-world.c" parse="text">
<xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</example>
@@ -233,7 +233,7 @@
<example id="gtk-getting-started-grid-packing">
<title>Packing buttons</title>
<para>Create a new file with the following content named example-2.c.</para>
<programlisting><xi:include href="../../../../examples/grid-packing.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/grid-packing.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</example>
<para>
You can compile the program above with GCC using:
@@ -257,9 +257,9 @@
<example>
<title>Packing buttons with GtkBuilder</title>
<para>Create a new file with the following content named example-3.c.</para>
<programlisting><xi:include href="../../../../examples/builder.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/builder.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<para>Create a new file with the following content named builder.ui.</para>
<programlisting><xi:include href="../../../../examples/builder.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/builder.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</example>
<para>
You can compile the program above with GCC using:
@@ -346,7 +346,7 @@
of our application class.</para>
<informalexample>
<programlisting><xi:include href="../../../../examples/application1/main.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/application1/main.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>All the application logic is in the application class, which
@@ -364,7 +364,7 @@
GIO <ulink url="https://developer.gnome.org/gio/2.36/GApplication.html#GApplication.description">documentation</ulink>.</para>
<informalexample>
<programlisting><xi:include href="../../../../examples/application1/exampleapp.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/application1/exampleapp.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>Another important class that is part of the application support
@@ -373,7 +373,7 @@
window.</para>
<informalexample>
<programlisting><xi:include href="../../../../examples/application1/exampleappwin.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/application1/exampleappwin.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>As part of the initial setup of our application, we also
@@ -388,7 +388,7 @@
</informalfigure>
<informalexample>
<programlisting><xi:include href="../../../../examples/application1/exampleapp.desktop" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/application1/org.gtk.exampleapp.desktop" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>Note that <replaceable>@<!-- -->bindir@</replaceable> needs to be replaced
@@ -420,7 +420,7 @@
</para>
<informalexample>
<programlisting><xi:include href="../../../../examples/application2/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/application2/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>To make use of this file in our application, we revisit
@@ -460,7 +460,7 @@ example_app_window_class_init (ExampleAppWindowClass *class)
</para>
<informalexample>
<programlisting><xi:include href="../../../../examples/application2/exampleapp.gresource.xml" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/application2/exampleapp.gresource.xml" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>This file has to be converted into a C source file that will be
@@ -599,7 +599,7 @@ example_app_window_open (ExampleAppWindow *win,
in a ui file, and add it as a resource to our binary.</para>
<informalexample>
<programlisting><xi:include href="../../../../examples/application4/app-menu.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/application4/app-menu.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>To associate the app menu with the application, we have to call
@@ -698,7 +698,7 @@ example_app_class_init (ExampleAppClass *class)
GSettings requires a schema that describes our settings:</para>
<informalexample>
<programlisting><xi:include href="../../../../examples/application5/org.gtk.exampleapp.gschema.xml" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/application5/org.gtk.exampleapp.gschema.xml" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>Before we can make use of this schema in our application,
@@ -747,13 +747,13 @@ example_app_window_init (ExampleAppWindow *win)
<para>Lets start with the template.</para>
<informalexample>
<programlisting><xi:include href="../../../../examples/application6/prefs.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/application6/prefs.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>Next comes the dialog subclass.</para>
<informalexample>
<programlisting><xi:include href="../../../../examples/application6/exampleappprefs.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/application6/exampleappprefs.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>Now we revisit the <literal>preferences_activated(<!-- -->)</literal> function in our
@@ -805,7 +805,7 @@ preferences_activated (GSimpleAction *action,
to slide out the search bar below the header bar.</para>
<informalexample>
<programlisting><xi:include href="../../../../examples/application7/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/application7/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>Implementing the search needs quite a few code changes that
@@ -882,7 +882,7 @@ example_app_window_init (ExampleAppWindow *win)
which demonstrates #GtkMenuButton, #GtkRevealer and #GtkListBox.</para>
<informalexample>
<programlisting><xi:include href="../../../../examples/application8/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/application8/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>The code to populate the sidebar with buttons for the words
@@ -893,7 +893,7 @@ example_app_window_init (ExampleAppWindow *win)
ui file.</para>
<informalexample>
<programlisting><xi:include href="../../../../examples/application8/gears-menu.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/application8/gears-menu.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>To connect the menuitem to the show-words setting, we use
@@ -952,7 +952,7 @@ example_app_window_init (ExampleAppWindow *win)
triggers the show-lines action:</para>
<informalexample>
<programlisting><xi:include href="../../../../examples/application9/gears-menu.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/application9/gears-menu.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>To make this menu item do something, we create a property
@@ -1012,7 +1012,7 @@ example_app_window_init (ExampleAppWindow *win)
be a direct child of the window, and set its type to be titlebar.</para>
<informalexample>
<programlisting><xi:include href="../../../../examples/application10/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/application10/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>A small extra bonus of using a header bar is that we get
@@ -1068,7 +1068,7 @@ example_app_window_init (ExampleAppWindow *win)
<example id="gtk-getting-started-drawing">
<title>Drawing in response to input</title>
<para>Create a new file with the following content named example-4.c.</para>
<programlisting><xi:include href="../../../../examples/drawing.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/drawing.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</example>
<para>
You can compile the program above with GCC using:
+12
View File
@@ -41,6 +41,16 @@
<xi:include href="visual_index.xml" />
</chapter>
<chapter id="Lists">
<title>GListModel support</title>
<xi:include href="xml/gtkfilterlistmodel.xml" />
<xi:include href="xml/gtkflattenlistmodel.xml" />
<xi:include href="xml/gtkmaplistmodel.xml" />
<xi:include href="xml/gtkslicelistmodel.xml" />
<xi:include href="xml/gtksortlistmodel.xml" />
<xi:include href="xml/gtktreelistmodel.xml" />
</chapter>
<chapter id="Application">
<title>Application support</title>
<xi:include href="xml/gtkapplication.xml" />
@@ -152,6 +162,7 @@
<chapter id="TreeWidgetObjects">
<title>Tree, List and Icon Grid Widgets</title>
<xi:include href="xml/tree_widget.sgml" />
<xi:include href="xml/treeview_tutorial.xml" />
<xi:include href="xml/gtktreemodel.xml" />
<xi:include href="xml/gtktreeselection.xml" />
<xi:include href="xml/gtktreeviewcolumn.xml" />
@@ -301,6 +312,7 @@
<title>Gestures and event handling</title>
<xi:include href="xml/gtkeventcontroller.xml" />
<xi:include href="xml/gtkeventcontrollerkey.xml" />
<xi:include href="xml/gtkeventcontrollerlegacy.xml" />
<xi:include href="xml/gtkeventcontrollerscroll.xml" />
<xi:include href="xml/gtkeventcontrollermotion.xml" />
<xi:include href="xml/gtkgesture.xml" />
+170 -4
View File
@@ -758,9 +758,6 @@ gtk_container_child_set_valist
gtk_container_child_notify
gtk_container_child_notify_by_pspec
gtk_container_forall
gtk_container_get_focus_chain
gtk_container_set_focus_chain
gtk_container_unset_focus_chain
gtk_container_class_find_child_property
gtk_container_class_install_child_property
gtk_container_class_install_child_properties
@@ -1242,6 +1239,26 @@ GTK_TYPE_FILE_FILTER
gtk_file_filter_get_type
</SECTION>
<SECTION>
<FILE>gtkfilterlistmodel</FILE>
<TITLE>GtkFilterListModel</TITLE>
GtkFilterListModel
gtk_filter_list_model_new
gtk_filter_list_model_get_model
gtk_filter_list_model_set_filter_func
gtk_filter_list_model_has_filter
gtk_filter_list_model_refilter
<SUBSECTION Standard>
GTK_FILTER_LIST_MODEL
GTK_IS_FILTER_LIST_MODEL
GTK_TYPE_FILTER_LIST_MODEL
GTK_FILTER_LIST_MODEL_CLASS
GTK_IS_FILTER_LIST_MODEL_CLASS
GTK_FILTER_LIST_MODEL_GET_CLASS
<SUBSECTION Private>
gtk_filter_list_model_get_type
</SECTION>
<SECTION>
<FILE>gtkfixed</FILE>
<TITLE>GtkFixed</TITLE>
@@ -1262,6 +1279,24 @@ GtkFixedChild
gtk_fixed_get_type
</SECTION>
<SECTION>
<FILE>gtkflattenlistmodel</FILE>
<TITLE>GtkFlattenListModel</TITLE>
GtkFlattenListModel
gtk_flatten_list_model_new
gtk_flatten_list_model_set_model
gtk_flatten_list_model_get_model
<SUBSECTION Standard>
GTK_FLATTEN_LIST_MODEL
GTK_IS_FLATTEN_LIST_MODEL
GTK_TYPE_FLATTEN_LIST_MODEL
GTK_FLATTEN_LIST_MODEL_CLASS
GTK_IS_FLATTEN_LIST_MODEL_CLASS
GTK_FLATTEN_LIST_MODEL_GET_CLASS
<SUBSECTION Private>
gtk_flatten_list_model_get_type
</SECTION>
<SECTION>
<FILE>gtkfontbutton</FILE>
<TITLE>GtkFontButton</TITLE>
@@ -1709,6 +1744,27 @@ GtkLinkButtonPrivate
gtk_link_button_get_type
</SECTION>
<SECTION>
<FILE>gtkmaplistmodel</FILE>
<TITLE>GtkMapListModel</TITLE>
GtkMapListModel
GtkMapListModelMapFunc
gtk_map_list_model_new
gtk_map_list_model_set_map_func
gtk_map_list_model_set_model
gtk_map_list_model_get_model
gtk_map_list_model_has_map
<SUBSECTION Standard>
GTK_MAP_LIST_MODEL
GTK_IS_MAP_LIST_MODEL
GTK_TYPE_MAP_LIST_MODEL
GTK_MAP_LIST_MODEL_CLASS
GTK_IS_MAP_LIST_MODEL_CLASS
GTK_MAP_LIST_MODEL_GET_CLASS
<SUBSECTION Private>
gtk_map_list_model_get_type
</SECTION>
<SECTION>
<FILE>gtkmenu</FILE>
<TITLE>GtkMenu</TITLE>
@@ -2537,6 +2593,51 @@ GtkSizeGroupPrivate
gtk_size_group_get_type
</SECTION>
<SECTION>
<FILE>gtkslicelistmodel</FILE>
<TITLE>GtkSliceListModel</TITLE>
GtkSliceListModel
gtk_slice_list_model_new
gtk_slice_list_model_new_for_type
gtk_slice_list_model_set_model
gtk_slice_list_model_get_model
gtk_slice_list_model_set_offset
gtk_slice_list_model_get_offset
gtk_slice_list_model_set_size
gtk_slice_list_model_get_size
<SUBSECTION Standard>
GTK_SLICE_LIST_MODEL
GTK_IS_SLICE_LIST_MODEL
GTK_TYPE_SLICE_LIST_MODEL
GTK_SLICE_LIST_MODEL_CLASS
GTK_IS_SLICE_LIST_MODEL_CLASS
GTK_SLICE_LIST_MODEL_GET_CLASS
<SUBSECTION Private>
gtk_slice_list_model_get_type
</SECTION>
<SECTION>
<FILE>gtksortlistmodel</FILE>
<TITLE>GtkSortListModel</TITLE>
GtkSortListModel
gtk_sort_list_model_new
gtk_sort_list_model_new_for_type
gtk_sort_list_model_set_sort_func
gtk_sort_list_model_has_sort
gtk_sort_list_model_set_model
gtk_sort_list_model_get_model
gtk_sort_list_model_resort
<SUBSECTION Standard>
GTK_SORT_LIST_MODEL
GTK_IS_SORT_LIST_MODEL
GTK_TYPE_SORT_LIST_MODEL
GTK_SORT_LIST_MODEL_CLASS
GTK_IS_SORT_LIST_MODEL_CLASS
GTK_SORT_LIST_MODEL_GET_CLASS
<SUBSECTION Private>
gtk_sort_list_model_get_type
</SECTION>
<SECTION>
<FILE>gtkspinbutton</FILE>
<TITLE>GtkSpinButton</TITLE>
@@ -3271,6 +3372,49 @@ GTK_TOOLTIP
gtk_tooltip_get_type
</SECTION>
<SECTION>
<FILE>gtktreelistmodel</FILE>
<TITLE>GtkTreeListModel</TITLE>
GtkTreeListModel
GtkTreeListRow
GtkTreeListModelCreateModelFunc
gtk_tree_list_model_new
gtk_tree_list_model_get_model
gtk_tree_list_model_get_passthrough
gtk_tree_list_model_set_autoexpand
gtk_tree_list_model_get_autoexpand
gtk_tree_list_model_get_child_row
gtk_tree_list_model_get_row
<SUBSECTION>
gtk_tree_list_row_get_item
gtk_tree_list_row_set_expanded
gtk_tree_list_row_get_expanded
gtk_tree_list_row_is_expandable
gtk_tree_list_row_get_position
gtk_tree_list_row_get_depth
gtk_tree_list_row_get_children
gtk_tree_list_row_get_parent
gtk_tree_list_row_get_child_row
<SUBSECTION Standard>
GTK_TREE_LIST_MODEL
GTK_IS_TREE_LIST_MODEL
GTK_TYPE_TREE_LIST_MODEL
GTK_TREE_LIST_MODEL_CLASS
GTK_IS_TREE_LIST_MODEL_CLASS
GTK_TREE_LIST_MODEL_GET_CLASS
GTK_TREE_LIST_ROW
GTK_IS_TREE_LIST_ROW
GTK_TYPE_TREE_LIST_ROW
GTK_TREE_LIST_ROW_CLASS
GTK_IS_TREE_LIST_ROW_CLASS
GTK_TREE_LIST_ROW_GET_CLASS
<SUBSECTION Private>
gtk_tree_list_model_get_type
gtk_tree_list_row_get_type
</SECTION>
<SECTION>
<FILE>gtktreemodel</FILE>
<TITLE>GtkTreeModel</TITLE>
@@ -4277,7 +4421,6 @@ gtk_widget_list_accel_closures
gtk_widget_can_activate_accel
gtk_widget_event
gtk_widget_activate
gtk_widget_intersect
gtk_widget_is_focus
gtk_widget_grab_focus
gtk_widget_grab_default
@@ -4460,6 +4603,10 @@ gtk_widget_class_bind_template_callback
gtk_widget_class_bind_template_callback_full
gtk_widget_class_set_connect_func
<SUBSECTION>
gtk_widget_observe_children
gtk_widget_observe_controllers
<SUBSECTION Standard>
GTK_WIDGET
GTK_IS_WIDGET
@@ -4503,6 +4650,7 @@ gtk_window_set_destroy_with_parent
gtk_window_set_display
gtk_window_is_active
gtk_window_is_maximized
gtk_window_get_toplevels
gtk_window_list_toplevels
gtk_window_add_mnemonic
gtk_window_remove_mnemonic
@@ -6456,6 +6604,24 @@ GTK_GESTURE_SINGLE_GET_CLASS
gtk_gesture_single_get_type
</SECTION>
<SECTION>
<FILE>gtkeventcontrollerlegacy</FILE>
<TITLE>GtkEventControllerlegacy</TITLE>
GtkEventControllerlegacy
gtk_event_controller_legacy_new
<SUBSECTION Standard>
GTK_TYPE_EVENT_CONTROLLER_LEGACY
GTK_EVENT_CONTROLLER_LEGACY
GTK_EVENT_CONTROLLER_LEGACY_CLASS
GTK_IS_EVENT_CONTROLLER_LEGACY
GTK_IS_EVENT_CONTROLLER_LEGACY_CLASS
GTK_EVENT_CONTROLLER_LEGACY_GET_CLASS
<SUBSECTION Private>
gtk_event_controller_legacy_get_type
</SECTION>
<SECTION>
<FILE>gtkeventcontrollerscroll</FILE>
<TITLE>GtkEventControllerScroll</TITLE>
+1
View File
@@ -54,6 +54,7 @@ gtk_entry_completion_get_type
gtk_entry_get_type
gtk_event_controller_get_type
gtk_event_controller_key_get_type
gtk_event_controller_legacy_get_type
gtk_event_controller_motion_get_type
gtk_event_controller_scroll_get_type
gtk_expander_get_type
+3 -2
View File
@@ -340,7 +340,6 @@ content_files = [
'css-overview.xml',
'css-properties.xml',
'drawing-model.xml',
'getting_started.xml',
'glossary.xml',
'gtk4-broadwayd.xml',
'gtk4-builder-tool.xml',
@@ -363,6 +362,7 @@ content_files = [
'running.sgml',
'text_widget.sgml',
'tree_widget.sgml',
'treeview_tutorial.xml',
'visual_index.xml',
'wayland.xml',
'windows.sgml',
@@ -372,7 +372,6 @@ content_files = [
expand_content_files = [
'compiling.sgml',
'drawing-model.xml',
'getting_started.xml',
'glossary.xml',
'input-handling.xml',
'migrating-2to4.xml',
@@ -380,9 +379,11 @@ expand_content_files = [
'question_index.sgml',
'text_widget.sgml',
'tree_widget.sgml',
'treeview_tutorial.xml',
]
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)
types_conf = configuration_data()
if os_win32
+28
View File
@@ -177,6 +177,22 @@
</para>
</section>
<section>
<title>Set a proper app_id</title>
<para>
In GTK+4 we want the application's #GApplication
'application-id' (and therefore the D-Bus name), the desktop
file basename and Wayland's xdg-shell app_id to match. In
order to achieve this with GTK+3 call g_set_prgname() with the same
application id you passed to #GtkApplication. Rename your
desktop files to match the application id if needed.
</para>
<para>
The call to g_set_prgname() can be removed once you fully migrated
to GTK+4.
</para>
</section>
</section>
<section>
@@ -270,6 +286,14 @@
</para>
</section>
<section>
<title>Stop using GtkEventBox</title>
<para>
GtkEventBox is no longer needed and has been removed.
All widgets receive all events.
</para>
</section>
<section>
<title>Adapt to GtkHeaderBar API changes</title>
<para>
@@ -408,6 +432,10 @@
from ui files it run the command <command>gtk4-builder-tool simplify --replace</command>
on them.
</para>
<para>
The function gtk_widget_show_all(), the #GtkWidget::no-show-all property
and its getter and setter have been removed in GTK+ 4, so you should stop using them.
</para>
</section>
<section>
+143
View File
@@ -0,0 +1,143 @@
<?xml version="1.0"?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
]>
<refentry id="TreeView-tutorial">
<refmeta>
<refentrytitle>TreeView Tutorial</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>GTK Library</refmiscinfo>
</refmeta>
<refnamediv>
<refname>TreeView Tutorial</refname>
<refpurpose>A tutorial on the use of GtkTreeModel, GtkTreeView, and friends</refpurpose>
</refnamediv>
<refsect1>
<title>Overview</title>
<para>GtkTreeView is a widget that displays single- or multi-columned
lists and trees.</para>
<para>The purpose of this tutorial is not to provide an exhaustive
documentation of #GtkTreeView - that is what the API documentation is
for, which should be read alongside with this tutorial. The goal is
rather to present an introduction to the most commonly-used aspects
of #GtkTreeView, and to demonstrate how the various #GtkTreeView
components and concepts work together. Furthermore, an attempt has
been made to shed some light on custom tree models and custom cell
renderers, which seem to be often-mentioned, but rarely
explained.</para>
<para>Developers looking for a quick and dirty introduction that
teaches them everything they need to know in less than five paragraphs
will not find it here. In the author's experience, developers who do
not understand how the tree view and the models work together will run
into problems once they try to modify the given examples, whereas
developers who have worked with other toolkits that employ the
Model/View/Controller-design will find that the API reference provides
all the information they need to know in more condensed form anyway.
Those who disagree may jump straight to the working example code of
course.</para>
<para>Please note that the code examples in the following sections do
not necessarily demonstrate how GtkTreeView is used best in a particular
situation. There are different ways to achieve the same result, and the
examples merely show those different ways, so that developers are able
to decide which one is most suitable for the task at hand.</para>
<refsect2>
<title>Components</title>
<para>The most important concept underlying #GtkTreeView is that of
complete separation between data and how that data is displayed on
the screen. This is commonly known as Model/View/Controller-design,
or MVC. Data of various type (strings, numbers, images, etc.) is
stored in a "model". The "view" is then told which data to display,
where to display it, and how to display it. One of the advantages
of this approach is that you can have multiple views that display
the same data (a directory tree for example) in different ways, or
in the same way multiple times, with only one copy of the underlying
data. This avoids duplication of data and programming effort if the
same data is re-used in different contexts. Also, when the data in
the model is updated, all views automatically get updated as
well.</para>
<para>So, while #GtkTreeModel is used to store data, there are other
components that determine which data is displayed in the #GtkTreeView
and how it is displayed. These components are #GtkTreeViewColumn and
#GtkCellRenderer. A #GtkTreeView is made up of tree view columns.
These are the columns that users perceive as columns. They have a
clickable column header with a column title that can be hidden, and
can be resized and sorted. Tree view columns do not display any data,
they are only used as a device to represent the user-side of the tree
view (sorting etc.) and serve as packing widgets for the components
that do the actual rendering of data onto the screen, namely the
#GtkCellRenderer family of objects. There are a number of different
cell renderers that specialise in rendering certain data like
strings, pixbufs, or toggle buttons. More on this later.</para>
<para>Cell renderers are packed into tree view columns to display data.
A tree view column needs to contain at least one cell renderer, but can
contain multiple cell renderers. For example, if one wanted to display
a 'Filename' column where each filename has a little icon on the left
indicating the file type, one would pack a GtkCellRendererPixbuf and a
GtkCellRendererText into one tree view column. Packing renderers into a
tree view column is similar to packing widgets into a #GtkBox.</para>
</refsect2>
<refsect2>
<title>GtkTreeModels for Data Storage: GtkListStore and GtkTreeStore</title>
<para>It is important to realise what #GtkTreeModel is and what it is
not. #GtkTreeModel is basically just an 'interface' to the data store,
meaning that it is a standardised set of functions that allows a
#GtkTreeView widget (and the application programmer) to query certain
characteristics of a data store, for example how many rows there are,
which rows have children, and how many children a particular row has.
It also provides functions to retrieve data from the data store, and
tell the tree view what type of data is stored in the model. Every
data store must implement the #GtkTreeModel interface and provide these
functions. #GtkTreeModel itself only provides a way to query a data
store's characteristics and to retrieve existing data, it does not
provide a way to remove or add rows to the store or put data into the
store. This is done using the specific store's functions.</para>
<para>GTK comes with two built-in data stores (models): #GtkListStore
and #GtkTreeStore. As the names imply, #GtkListStore is used for simple
lists of data items where items have no hierarchical parent-child
relationships, and #GtkTreeStore is used for tree-like data structures,
where items can have parent-child relationships. A list of files in a
directory would be an example of a simple list structure, whereas a
directory tree is an example for a tree structure. A list is basically
just a special case of a tree with none of the items having any
children, so one could use a tree store to maintain a simple list of
items as well. The only reason #GtkListStore exists is in order to
provide an easier interface that does not need to cater for
child-parent relationships, and because a simple list model can be
optimised for the special case where no children exist, which makes it
faster and more efficient.</para>
<para>#GtkListStore and #GtkTreeStore should cater for most types of
data an application developer might want to display in a #GtkTreeView.
However, it should be noted that #GtkListStore and #GtkTreeStore have
been designed to cater to a large number of potential use cases, and
so are not overly optimized. If you already have your specialized data
store; if you plan to store a lot of data; or if have a large number
of rows, you should consider implementing your own custom model that
stores and manipulates data your own way and implements the
#GtkTreeModel interface. This will not only be more efficient, but
probably also lead to saner code in the long run, and give you more
control over your data. See below for more details on how to implement
custom models.</para>
<para>Tree model implementations like #GtkListStore and #GtkTreeStore
will take care of the view side for you once you have configured the
#GtkTreeView to display what you want. If you change data in the store,
the model will notify the tree view and your data display will be
updated. If you add or remove rows, the model will also notify the
store, and your row will appear in or disappear from the view as
well.</para>
</refsect2>
</refsect1>
+3
View File
@@ -12,6 +12,9 @@ docpath = join_paths(gtk_datadir, 'gtk-doc', 'html')
version_conf = configuration_data()
version_conf.set('GTK_VERSION', meson.project_version())
src_dir_conf = configuration_data()
src_dir_conf.set('SRC_DIR', meson.source_root())
subdir('gdk')
subdir('gsk')
subdir('gtk')
+2 -2
View File
@@ -2,8 +2,8 @@ To make gnome-shell use the desktop file and icon for this example
while running it uninstalled, do the following:
mkdir -p ~/.local/share/applications
sed -e "s#@bindir@#$PWD#" exampleapp.desktop \
> ~/.local/share/applications/lt-exampleapp.desktop
sed -e "s#@bindir@#$PWD#" org.gtk.exampleapp.desktop \
> ~/.local/share/applications/org.gtk.exampleapp.desktop
mkdir -p ~/.local/share/icons/hicolor/48x48/apps
cp exampleapp.png ~/.local/share/icons/hicolor/48x48/apps
+1
View File
@@ -32,6 +32,7 @@ void gdk_display_set_cursor_theme (GdkDisplay *display,
const char *theme,
int size);
gboolean gdk_running_in_sandbox (void);
gboolean gdk_should_use_portal (void);
const gchar * gdk_get_startup_notification_id (void);
+19 -6
View File
@@ -269,14 +269,27 @@ gdk_get_startup_notification_id (void)
gboolean
gdk_running_in_sandbox (void)
{
char *path;
gboolean ret;
return g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS);
}
path = g_build_filename (g_get_user_runtime_dir (), "flatpak-info", NULL);
ret = g_file_test (path, G_FILE_TEST_EXISTS);
g_free (path);
gboolean
gdk_should_use_portal (void)
{
static const char *use_portal = NULL;
return ret;
if (G_UNLIKELY (use_portal == NULL))
{
if (gdk_running_in_sandbox ())
use_portal = "1";
else
{
use_portal = g_getenv ("GTK_USE_PORTAL");
if (!use_portal)
use_portal = "";
}
}
return use_portal[0] == '1';
}
/**
+1 -1
View File
@@ -107,7 +107,7 @@ gdk_drop_read_local_async (GdkDrop *self,
if (priv->drag == NULL)
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("Drag'n'drop from other applications is not supported."));
_("Dragndrop from other applications is not supported."));
g_object_unref (task);
return;
}
+1 -1
View File
@@ -54,7 +54,7 @@ G_BEGIN_DECLS
#define GDK_PRIORITY_EVENTS (G_PRIORITY_DEFAULT)
/**
* GDK_PRIORITY_REDRAW:
* GDK_PRIORITY_REDRAW: (value 120)
*
* This is the priority that the idle handler processing surface updates
* is given in the
+8 -8
View File
@@ -175,7 +175,7 @@ parse_rgb_value (const gchar *str,
* - A RGBA color in the form “rgba(r,g,b,a)”
*
* Where “r”, “g”, “b” and “a” are respectively the red, green, blue and
* alpha color values. In the last two cases, r g and b are either integers
* alpha color values. In the last two cases, “r”, “g”, and “b” are either integers
* in the range 0 to 255 or percentage values in the range 0% to 100%, and
* a is a floating point value in the range 0 to 1.
*
@@ -353,18 +353,18 @@ gdk_rgba_equal (gconstpointer p1,
* @rgba: a #GdkRGBA
*
* Returns a textual specification of @rgba in the form
* `rgb (r, g, b)` or
* `rgba (r, g, b, a)`,
* `rgb(r,g,b)` or
* `rgba(r g,b,a)`,
* where “r”, “g”, “b” and “a” represent the red, green,
* blue and alpha values respectively. r, g, and b are
* represented as integers in the range 0 to 255, and a
* is represented as floating point value in the range 0 to 1.
* blue and alpha values respectively. “r”, “g”, and “b” are
* represented as integers in the range 0 to 255, and “a”
* is represented as a floating point value in the range 0 to 1.
*
* These string forms are string forms those supported by
* These string forms are string forms that are supported by
* the CSS3 colors module, and can be parsed by gdk_rgba_parse().
*
* Note that this string representation may lose some
* precision, since r, g and b are represented as 8-bit
* precision, since “r”, “g” and “b” are represented as 8-bit
* integers. If this is a concern, you should use a
* different representation.
*
+3 -2
View File
@@ -434,14 +434,15 @@ gdk_seat_tool_removed (GdkSeat *seat,
GdkDeviceTool *
gdk_seat_get_tool (GdkSeat *seat,
guint64 serial)
guint64 serial,
guint64 hw_id)
{
GdkSeatClass *seat_class;
g_return_val_if_fail (GDK_IS_SEAT (seat), NULL);
seat_class = GDK_SEAT_GET_CLASS (seat);
return seat_class->get_tool (seat, serial);
return seat_class->get_tool (seat, serial, hw_id);
}
/**
+4 -4
View File
@@ -282,7 +282,8 @@ gdk_seat_default_get_slaves (GdkSeat *seat,
static GdkDeviceTool *
gdk_seat_default_get_tool (GdkSeat *seat,
guint64 serial)
guint64 serial,
guint64 hw_id)
{
GdkSeatDefaultPrivate *priv;
GdkDeviceTool *tool;
@@ -297,7 +298,7 @@ gdk_seat_default_get_tool (GdkSeat *seat,
{
tool = g_ptr_array_index (priv->tools, i);
if (tool->serial == serial)
if (tool->serial == serial && tool->hw_id == hw_id)
return tool;
}
@@ -457,8 +458,7 @@ gdk_seat_default_remove_tool (GdkSeatDefault *seat,
priv = gdk_seat_default_get_instance_private (seat);
if (tool != gdk_seat_get_tool (GDK_SEAT (seat),
gdk_device_tool_get_serial (tool)))
if (tool != gdk_seat_get_tool (GDK_SEAT (seat), tool->serial, tool->hw_id))
return;
g_signal_emit_by_name (seat, "tool-removed", tool);
+4 -2
View File
@@ -57,7 +57,8 @@ struct _GdkSeatClass
GdkSeatCapabilities capabilities);
GdkDeviceTool * (* get_tool) (GdkSeat *seat,
guint64 serial);
guint64 serial,
guint64 tool_id);
GList * (* get_master_pointers) (GdkSeat *seat,
GdkSeatCapabilities capabilities);
};
@@ -74,6 +75,7 @@ void gdk_seat_tool_removed (GdkSeat *seat,
GdkDeviceTool *
gdk_seat_get_tool (GdkSeat *seat,
guint64 serial);
guint64 serial,
guint64 hw_id);
#endif /* __GDK_SEAT_PRIVATE_H__ */
+3 -31
View File
@@ -461,12 +461,6 @@ gdk_surface_get_property (GObject *object,
}
}
static gboolean
gdk_surface_is_subsurface (GdkSurface *surface)
{
return surface->surface_type == GDK_SURFACE_SUBSURFACE;
}
static GdkSurface *
gdk_surface_get_impl_surface (GdkSurface *surface)
{
@@ -555,10 +549,7 @@ recompute_visible_regions_internal (GdkSurface *private,
old_abs_y = private->abs_y;
/* Update absolute position */
if ((gdk_surface_has_impl (private) &&
private->surface_type != GDK_SURFACE_SUBSURFACE) ||
(gdk_surface_is_toplevel (private) &&
private->surface_type == GDK_SURFACE_SUBSURFACE))
if (gdk_surface_has_impl (private))
{
/* Native surfaces and toplevel subsurfaces start here */
private->abs_x = 0;
@@ -677,15 +668,6 @@ gdk_surface_new (GdkDisplay *display,
if (parent != NULL)
g_warning (G_STRLOC "Toplevel surfaces must be created without a parent");
break;
case GDK_SURFACE_SUBSURFACE:
#ifdef GDK_WINDOWING_WAYLAND
if (!GDK_IS_WAYLAND_DISPLAY (display))
{
g_warning (G_STRLOC "Subsurface surfaces can only be used on Wayland");
return NULL;
}
#endif
break;
case GDK_SURFACE_CHILD:
break;
default:
@@ -715,11 +697,6 @@ gdk_surface_new (GdkDisplay *display,
native = TRUE; /* Always use native surfaces for toplevels */
}
#ifdef GDK_WINDOWING_WAYLAND
if (surface->surface_type == GDK_SURFACE_SUBSURFACE)
native = TRUE; /* Always use native windows for subsurfaces as well */
#endif
if (native)
{
/* Create the impl */
@@ -922,7 +899,6 @@ _gdk_surface_destroy_hierarchy (GdkSurface *surface,
case GDK_SURFACE_TOPLEVEL:
case GDK_SURFACE_CHILD:
case GDK_SURFACE_TEMP:
case GDK_SURFACE_SUBSURFACE:
if (surface->parent)
{
if (surface->parent->children)
@@ -1173,10 +1149,7 @@ gdk_surface_get_parent (GdkSurface *surface)
{
g_return_val_if_fail (GDK_IS_SURFACE (surface), NULL);
if (gdk_surface_is_subsurface (surface))
return surface->transient_for;
else
return surface->parent;
return surface->parent;
}
/**
@@ -1196,8 +1169,7 @@ gdk_surface_get_toplevel (GdkSurface *surface)
{
g_return_val_if_fail (GDK_IS_SURFACE (surface), NULL);
while (surface->surface_type == GDK_SURFACE_CHILD ||
surface->surface_type == GDK_SURFACE_SUBSURFACE)
while (surface->surface_type == GDK_SURFACE_CHILD)
{
if (gdk_surface_is_toplevel (surface))
break;
+2 -7
View File
@@ -43,11 +43,7 @@ typedef struct _GdkGeometry GdkGeometry;
* GdkSurfaceType:
* @GDK_SURFACE_TOPLEVEL: toplevel window (used to implement #GtkWindow)
* @GDK_SURFACE_CHILD: child surface (used to implement e.g. #GtkEntry)
* @GDK_SURFACE_TEMP: override redirect temporary surface (used to implement
* #GtkMenu)
* @GDK_SURFACE_SUBSURFACE: subsurface; This surface is visually
* tied to a toplevel, and is moved/stacked with it. Currently this window
* type is only implemented in Wayland
* @GDK_SURFACE_TEMP: override redirect temporary surface (used to implement #GtkMenu)
*
* Describes the kind of surface.
*/
@@ -55,8 +51,7 @@ typedef enum
{
GDK_SURFACE_TOPLEVEL,
GDK_SURFACE_CHILD,
GDK_SURFACE_TEMP,
GDK_SURFACE_SUBSURFACE
GDK_SURFACE_TEMP
} GdkSurfaceType;
/* Size restriction enumeration.
+7 -2
View File
@@ -190,6 +190,11 @@ gdk_vulkan_strerror (VkResult result)
case VK_ERROR_FRAGMENTATION_EXT:
return "A descriptor pool creation has failed due to fragmentation";
#endif
#if VK_HEADER_VERSION >= 89
case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
return "Invalid DRM format modifier plane layout";
#endif
case VK_RESULT_RANGE_SIZE:
case VK_RESULT_MAX_ENUM:
default:
@@ -706,7 +711,7 @@ gdk_vulkan_context_get_image (GdkVulkanContext *context,
*
* Gets the index of the image that is currently being drawn.
*
* This function can only be used between gdk_cairo_context_begin_frame() and
* This function can only be used between gdk_draw_context_begin_frame() and
* gdk_draw_context_end_frame() calls.
*
* Returns: the index of the images that is being drawn
@@ -729,7 +734,7 @@ gdk_vulkan_context_get_draw_index (GdkVulkanContext *context)
* Gets the Vulkan semaphore that protects access to the image that is
* currently being drawn.
*
* This function can only be used between gdk_cairo_context_begin_frame() and
* This function can only be used between gdk_draw_context_begin_frame() and
* gdk_draw_context_end_frame() calls.
*
* Returns: (transfer none): the VkSemaphore
+12 -5
View File
@@ -35,12 +35,19 @@ gdk_quartz_monitor_get_workarea (GdkMonitor *monitor,
GDK_QUARTZ_ALLOC_POOL;
NSRect rect = [quartz_monitor->nsscreen visibleFrame];
NSArray *array = [NSScreen screens];
if (quartz_monitor->monitor_num < [array count])
{
NSScreen *screen = [array objectAtIndex:quartz_monitor->monitor_num];
NSRect rect = [screen visibleFrame];
dest->x = rect.origin.x - quartz_screen->min_x;
dest->y = quartz_screen->height - (rect.origin.y + rect.size.height) + quartz_screen->min_y;
dest->width = rect.size.width;
dest->height = rect.size.height;
dest->x = rect.origin.x - quartz_screen->min_x;
dest->y = quartz_screen->height - (rect.origin.y + rect.size.height) + quartz_screen->min_y;
dest->width = rect.size.width;
dest->height = rect.size.height;
}
else
*dest = monitor->geometry;
GDK_QUARTZ_RELEASE_POOL;
}
+1 -1
View File
@@ -30,7 +30,7 @@ struct _GdkQuartzMonitor
{
GdkMonitor parent;
NSScreen *nsscreen;
gint monitor_num;
};
struct _GdkQuartzMonitorClass {
+3 -1
View File
@@ -52,7 +52,9 @@ typedef enum
GDK_OSX_YOSEMITE = 10,
GDK_OSX_EL_CAPITAN = 11,
GDK_OSX_SIERRA = 12,
GDK_OSX_CURRENT = 12,
GDK_OSX_HIGH_SIERRA = 13,
GDK_OSX_MOJAVE = 14,
GDK_OSX_CURRENT = 14,
GDK_OSX_NEW = 99
} GdkOSXVersion;
+1 -1
View File
@@ -144,7 +144,7 @@ gdk_quartz_screen_calculate_layout (GdkQuartzScreen *screen)
"display", display,
NULL);
g_ptr_array_add (display_quartz->monitors, monitor);
monitor->nsscreen = [array objectAtIndex:i];
monitor->monitor_num = i;
NSRect rect = [[array objectAtIndex:i] frame];
+11 -7
View File
@@ -134,8 +134,12 @@ gdk_surface_impl_quartz_get_context (GdkSurfaceImplQuartz *surface_impl,
if (![surface_impl->view lockFocusIfCanDraw])
return NULL;
}
cg_context = [[NSGraphicsContext currentContext] graphicsPort];
if (gdk_quartz_osx_version () < GDK_OSX_YOSEMITE)
cg_context = [[NSGraphicsContext currentContext] graphicsPort];
else
cg_context = [[NSGraphicsContext currentContext] CGContext];
if (!cg_context)
return NULL;
CGContextSaveGState (cg_context);
CGContextSetAllowsAntialiasing (cg_context, antialias);
@@ -276,15 +280,15 @@ gdk_quartz_create_cairo_surface (GdkSurfaceImplQuartz *impl,
cg_context = gdk_quartz_surface_get_context (impl, TRUE);
if (!cg_context)
return NULL;
surface_data = g_new (GdkQuartzCairoSurfaceData, 1);
surface_data->surface_impl = impl;
surface_data->cg_context = cg_context;
surface = cairo_quartz_surface_create_for_cg_context (cg_context,
width, height);
if (cg_context)
surface = cairo_quartz_surface_create_for_cg_context (cg_context,
width, height);
else
surface = cairo_quartz_surface_create(CAIRO_FORMAT_ARGB32, width, height);
cairo_surface_set_user_data (surface, &gdk_quartz_cairo_key,
surface_data,
+327 -56
View File
@@ -730,7 +730,10 @@ gdk_wayland_display_finalize (GObject *object)
g_ptr_array_free (display_wayland->monitors, TRUE);
g_hash_table_destroy (display_wayland->settings);
if (display_wayland->settings)
g_hash_table_destroy (display_wayland->settings);
g_clear_object (&display_wayland->settings_portal);
G_OBJECT_CLASS (gdk_wayland_display_parent_class)->finalize (object);
}
@@ -1207,13 +1210,21 @@ open_shared_memory (void)
#if defined (__NR_memfd_create)
if (!force_shm_open)
{
ret = syscall (__NR_memfd_create, "gdk-wayland", MFD_CLOEXEC);
int options = MFD_CLOEXEC;
#if defined (MFD_ALLOW_SEALING)
options |= MFD_ALLOW_SEALING;
#endif
ret = syscall (__NR_memfd_create, "gdk-wayland", options);
/* fall back to shm_open until debian stops shipping 3.16 kernel
* See bug 766341
*/
if (ret < 0 && errno == ENOSYS)
force_shm_open = TRUE;
#if defined (F_ADD_SEALS) && defined (F_SEAL_SHRINK)
if (ret >= 0)
fcntl (ret, F_ADD_SEALS, F_SEAL_SHRINK);
#endif
}
#endif
@@ -1368,6 +1379,19 @@ typedef enum
GSD_FONT_ANTIALIASING_MODE_RGBA
} GsdFontAntialiasingMode;
static int
get_antialiasing (const char *s)
{
const char *names[] = { "none", "grayscale", "rgba" };
int i;
for (i = 0; i < G_N_ELEMENTS (names); i++)
if (strcmp (s, names[i]) == 0)
return i;
return 0;
}
typedef enum
{
GSD_FONT_HINTING_NONE,
@@ -1376,6 +1400,19 @@ typedef enum
GSD_FONT_HINTING_FULL
} GsdFontHinting;
static int
get_hinting (const char *s)
{
const char *names[] = { "none", "slight", "medium", "full" };
int i;
for (i = 0; i < G_N_ELEMENTS (names); i++)
if (strcmp (s, names[i]) == 0)
return i;
return 0;
}
typedef enum
{
GSD_FONT_RGBA_ORDER_RGBA,
@@ -1385,6 +1422,19 @@ typedef enum
GSD_FONT_RGBA_ORDER_VBGR
} GsdFontRgbaOrder;
static int
get_order (const char *s)
{
const char *names[] = { "rgba", "rgb", "bgr", "vrgb", "vbgr" };
int i;
for (i = 0; i < G_N_ELEMENTS (names); i++)
if (strcmp (s, names[i]) == 0)
return i;
return 0;
}
static gdouble
get_dpi_from_gsettings (GdkWaylandDisplay *display_wayland)
{
@@ -1401,6 +1451,26 @@ get_dpi_from_gsettings (GdkWaylandDisplay *display_wayland)
return 96.0 * factor;
}
/* When using the Settings portal, we cache the value in
* the fallback member, and we ignore the valid field
*/
typedef struct _TranslationEntry TranslationEntry;
struct _TranslationEntry {
gboolean valid;
const gchar *schema;
const gchar *key;
const gchar *setting;
GType type;
union {
const char *s;
gint i;
gboolean b;
} fallback;
};
static TranslationEntry * find_translation_entry_by_schema (const char *schema,
const char *key);
static void
update_xft_settings (GdkDisplay *display)
{
@@ -1411,25 +1481,47 @@ update_xft_settings (GdkDisplay *display)
GsdFontRgbaOrder order;
gboolean use_rgba = FALSE;
GsdXftSettings xft_settings;
double dpi;
settings = g_hash_table_lookup (display_wayland->settings,
"org.gnome.settings-daemon.plugins.xsettings");
if (settings)
if (display_wayland->settings_portal)
{
antialiasing = g_settings_get_enum (settings, "antialiasing");
hinting = g_settings_get_enum (settings, "hinting");
order = g_settings_get_enum (settings, "rgba-order");
TranslationEntry *entry;
entry = find_translation_entry_by_schema ("org.gnome.settings-daemon.plugins.xsettings", "antialiasing");
antialiasing = entry->fallback.i;
entry = find_translation_entry_by_schema ("org.gnome.settings-daemon.plugins.xsettings", "hinting");
hinting = entry->fallback.i;
entry = find_translation_entry_by_schema ("org.gnome.settings-daemon.plugins.xsettings", "rgba-order");
order = entry->fallback.i;
entry = find_translation_entry_by_schema ("org.gnome.desktop.interface", "text-scaling-factor");
dpi = 96.0 * entry->fallback.i / 65536.0 * 1024; /* Xft wants 1/1024th of an inch */
}
else
{
antialiasing = GSD_FONT_ANTIALIASING_MODE_GRAYSCALE;
hinting = GSD_FONT_HINTING_MEDIUM;
order = GSD_FONT_RGBA_ORDER_RGB;
settings = g_hash_table_lookup (display_wayland->settings,
"org.gnome.settings-daemon.plugins.xsettings");
if (settings)
{
antialiasing = g_settings_get_enum (settings, "antialiasing");
hinting = g_settings_get_enum (settings, "hinting");
order = g_settings_get_enum (settings, "rgba-order");
}
else
{
antialiasing = GSD_FONT_ANTIALIASING_MODE_GRAYSCALE;
hinting = GSD_FONT_HINTING_MEDIUM;
order = GSD_FONT_RGBA_ORDER_RGB;
}
dpi = get_dpi_from_gsettings (display_wayland) * 1024;
}
xft_settings.hinting = (hinting != GSD_FONT_HINTING_NONE);
xft_settings.dpi = get_dpi_from_gsettings (display_wayland) * 1024; /* Xft wants 1/1024ths of an inch */
xft_settings.dpi = dpi;
switch (hinting)
{
@@ -1516,23 +1608,6 @@ update_xft_settings (GdkDisplay *display)
}
}
#define WM_SETTINGS_SCHEMA "org.gnome.desktop.wm.preferences"
#define CLASSIC_WM_SETTINGS_SCHEMA "org.gnome.shell.extensions.classic-overrides"
typedef struct _TranslationEntry TranslationEntry;
struct _TranslationEntry {
gboolean valid;
const gchar *schema;
const gchar *key;
const gchar *setting;
GType type;
union {
const gchar *s;
gint i;
gboolean b;
} fallback;
};
static TranslationEntry translations[] = {
{ FALSE, "org.gnome.desktop.interface", "gtk-theme", "gtk-theme-name" , G_TYPE_STRING, { .s = "Adwaita" } },
{ FALSE, "org.gnome.desktop.interface", "icon-theme", "gtk-icon-theme-name", G_TYPE_STRING, { .s = "gnome" } },
@@ -1552,41 +1627,48 @@ static TranslationEntry translations[] = {
{ FALSE, "org.gnome.desktop.sound", "input-feedback-sounds", "gtk-enable-input-feedback-sounds", G_TYPE_BOOLEAN, { . b = FALSE } },
{ FALSE, "org.gnome.desktop.privacy", "recent-files-max-age", "gtk-recent-files-max-age", G_TYPE_INT, { .i = 30 } },
{ FALSE, "org.gnome.desktop.privacy", "remember-recent-files", "gtk-recent-files-enabled", G_TYPE_BOOLEAN, { .b = TRUE } },
{ FALSE, WM_SETTINGS_SCHEMA, "button-layout", "gtk-decoration-layout", G_TYPE_STRING, { .s = "menu:close" } },
{ FALSE, CLASSIC_WM_SETTINGS_SCHEMA, "button-layout", "gtk-decoration-layout", G_TYPE_STRING, { .s = "menu:close" } },
{ FALSE, "org.gnome.desktop.wm.preferences", "button-layout", "gtk-decoration-layout", G_TYPE_STRING, { .s = "menu:close" } },
{ FALSE, "org.gnome.settings-daemon.plugins.xsettings", "antialiasing", "gtk-xft-antialias", G_TYPE_NONE, { .i = 0 } },
{ FALSE, "org.gnome.settings-daemon.plugins.xsettings", "hinting", "gtk-xft-hinting", G_TYPE_NONE, { .i = 0 } },
{ FALSE, "org.gnome.settings-daemon.plugins.xsettings", "hinting", "gtk-xft-hintstyle", G_TYPE_NONE, { .i = 0 } },
{ FALSE, "org.gnome.settings-daemon.plugins.xsettings", "rgba-order", "gtk-xft-rgba", G_TYPE_NONE, { .i = 0 } },
{ FALSE, "org.gnome.desktop.interface", "text-scaling-factor", "gtk-xft-dpi" , G_TYPE_NONE, { .i = 0 } },
{ FALSE, "org.gnome.desktop.interface", "text-scaling-factor", "gtk-xft-dpi" , G_TYPE_NONE, { .i = 0 } }, /* We store the factor as 16.16 */
{ FALSE, "org.gnome.desktop.wm.preferences", "action-double-click-titlebar", "gtk-titlebar-double-click", G_TYPE_STRING, { .s = "toggle-maximize" } },
{ FALSE, "org.gnome.desktop.wm.preferences", "action-middle-click-titlebar", "gtk-titlebar-middle-click", G_TYPE_STRING, { .s = "none" } },
{ FALSE, "org.gnome.desktop.wm.preferences", "action-right-click-titlebar", "gtk-titlebar-right-click", G_TYPE_STRING, { .s = "menu" } },
{ FALSE, "org.gnome.desktop.a11y", "always-show-text-caret", "gtk-keynav-use-caret", G_TYPE_BOOLEAN, { .b = FALSE } }
{ FALSE, "org.gnome.desktop.a11y", "always-show-text-caret", "gtk-keynav-use-caret", G_TYPE_BOOLEAN, { .b = FALSE } },
{ FALSE, "org.gnome.fontconfig", "serial", "gtk-fontconfig-timestamp", G_TYPE_NONE, { .i = 0 } }
};
static TranslationEntry *
find_translation_entry_by_key (GSettings *settings,
const char *key)
find_translation_entry_by_schema (const char *schema,
const char *key)
{
guint i;
char *schema;
g_object_get (settings, "schema", &schema, NULL);
for (i = 0; i < G_N_ELEMENTS (translations); i++)
{
if (g_str_equal (schema, translations[i].schema) &&
g_str_equal (key, translations[i].key))
{
g_free (schema);
return &translations[i];
}
return &translations[i];
}
return NULL;
}
static TranslationEntry *
find_translation_entry_by_key (GSettings *settings,
const char *key)
{
char *schema;
TranslationEntry *entry;
g_object_get (settings, "schema", &schema, NULL);
entry = find_translation_entry_by_schema (schema, key);
g_free (schema);
return NULL;
return entry;
}
static TranslationEntry *
@@ -1621,6 +1703,79 @@ settings_changed (GSettings *settings,
}
}
static void
apply_portal_setting (TranslationEntry *entry,
GVariant *value,
GdkDisplay *display)
{
switch (entry->type)
{
case G_TYPE_STRING:
entry->fallback.s = g_intern_string (g_variant_get_string (value, NULL));
break;
case G_TYPE_INT:
entry->fallback.i = g_variant_get_int32 (value);
break;
case G_TYPE_BOOLEAN:
entry->fallback.b = g_variant_get_boolean (value);
break;
case G_TYPE_NONE:
if (strcmp (entry->key, "serial") == 0)
{
entry->fallback.i = g_variant_get_int32 (value);
break;
}
if (strcmp (entry->key, "antialiasing") == 0)
entry->fallback.i = get_antialiasing (g_variant_get_string (value, NULL));
else if (strcmp (entry->key, "hinting") == 0)
entry->fallback.i = get_hinting (g_variant_get_string (value, NULL));
else if (strcmp (entry->key, "rgba-order") == 0)
entry->fallback.i = get_order (g_variant_get_string (value, NULL));
else if (strcmp (entry->key, "text-scaling-factor") == 0)
entry->fallback.i = (int) (g_variant_get_double (value) * 65536.0);
update_xft_settings (display);
break;
default:
break;
}
}
static void
settings_portal_changed (GDBusProxy *proxy,
const char *sender_name,
const char *signal_name,
GVariant *parameters,
GdkDisplay *display)
{
if (strcmp (signal_name, "SettingChanged") == 0)
{
const char *namespace;
const char *name;
GVariant *value;
TranslationEntry *entry;
g_variant_get (parameters, "(&s&sv)", &namespace, &name, &value);
entry = find_translation_entry_by_schema (namespace, name);
if (entry != NULL)
{
char *a = g_variant_print (value, FALSE);
g_debug ("Using changed portal setting %s %s: %s", namespace, name, a);
g_free (a);
apply_portal_setting (entry, value, display);
gdk_display_setting_changed (display, entry->setting);
}
else
g_debug ("Ignoring portal setting %s %s", namespace, name);
g_variant_unref (value);
}
}
#define PORTAL_BUS_NAME "org.freedesktop.portal.Desktop"
#define PORTAL_OBJECT_PATH "/org/freedesktop/portal/desktop"
#define PORTAL_SETTINGS_INTERFACE "org.freedesktop.portal.Settings"
static void
init_settings (GdkDisplay *display)
{
@@ -1630,6 +1785,86 @@ init_settings (GdkDisplay *display)
GSettings *settings;
gint i;
if (gdk_should_use_portal ())
{
GVariant *ret;
GError *error = NULL;
const char *schema;
GVariant *val;
GVariantIter *iter;
const char *patterns[] = { "org.gnome.*", NULL };
display_wayland->settings_portal = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
PORTAL_BUS_NAME,
PORTAL_OBJECT_PATH,
PORTAL_SETTINGS_INTERFACE,
NULL,
&error);
if (error)
{
g_warning ("Settings portal not found: %s", error->message);
g_error_free (error);
goto fallback;
}
ret = g_dbus_proxy_call_sync (display_wayland->settings_portal,
"ReadAll",
g_variant_new ("(^as)", patterns),
G_DBUS_CALL_FLAGS_NONE,
G_MAXINT,
NULL,
&error);
if (error)
{
g_warning ("Failed to read portal settings: %s", error->message);
g_error_free (error);
g_clear_object (&display_wayland->settings_portal);
goto fallback;
}
g_variant_get (ret, "(a{sa{sv}})", &iter);
while (g_variant_iter_loop (iter, "{s@a{sv}}", &schema, &val))
{
GVariantIter *iter2 = g_variant_iter_new (val);
const char *key;
GVariant *v;
while (g_variant_iter_loop (iter2, "{sv}", &key, &v))
{
TranslationEntry *entry = find_translation_entry_by_schema (schema, key);
if (entry)
{
char *a = g_variant_print (v, FALSE);
g_debug ("Using portal setting for %s %s: %s\n", schema, key, a);
g_free (a);
apply_portal_setting (entry, v, display);
}
else
{
g_debug ("Ignoring portal setting for %s %s", schema, key);
}
}
g_variant_iter_free (iter2);
}
g_variant_iter_free (iter);
g_variant_unref (ret);
g_signal_connect (display_wayland->settings_portal, "g-signal",
G_CALLBACK (settings_portal_changed), display_wayland);
return;
fallback:
g_debug ("Failed to use Settings portal; falling back to gsettings");
}
g_intern_static_string ("antialiasing");
g_intern_static_string ("hinting");
g_intern_static_string ("rgba-order");
@@ -1701,6 +1936,43 @@ set_value_from_entry (GdkDisplay *display,
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
GSettings *settings;
if (display_wayland->settings_portal)
{
switch (entry->type)
{
case G_TYPE_STRING:
g_value_set_string (value, entry->fallback.s);
break;
case G_TYPE_INT:
g_value_set_int (value, entry->fallback.i);
break;
case G_TYPE_BOOLEAN:
g_value_set_boolean (value, entry->fallback.b);
break;
case G_TYPE_NONE:
if (g_str_equal (entry->setting, "gtk-fontconfig-timestamp"))
g_value_set_uint (value, (guint)entry->fallback.i);
else if (g_str_equal (entry->setting, "gtk-xft-antialias"))
g_value_set_int (value, display_wayland->xft_settings.antialias);
else if (g_str_equal (entry->setting, "gtk-xft-hinting"))
g_value_set_int (value, display_wayland->xft_settings.hinting);
else if (g_str_equal (entry->setting, "gtk-xft-hintstyle"))
g_value_set_static_string (value, display_wayland->xft_settings.hintstyle);
else if (g_str_equal (entry->setting, "gtk-xft-rgba"))
g_value_set_static_string (value, display_wayland->xft_settings.rgba);
else if (g_str_equal (entry->setting, "gtk-xft-dpi"))
g_value_set_int (value, display_wayland->xft_settings.dpi);
else
g_assert_not_reached ();
break;
default:
g_assert_not_reached ();
break;
}
return;
}
settings = (GSettings *)g_hash_table_lookup (display_wayland->settings, entry->schema);
switch (entry->type)
{
@@ -1728,7 +2000,9 @@ set_value_from_entry (GdkDisplay *display,
: entry->fallback.b);
break;
case G_TYPE_NONE:
if (g_str_equal (entry->setting, "gtk-xft-antialias"))
if (g_str_equal (entry->setting, "gtk-fontconfig-timestamp"))
g_value_set_uint (value, (guint)entry->fallback.i);
else if (g_str_equal (entry->setting, "gtk-xft-antialias"))
g_value_set_int (value, display_wayland->xft_settings.antialias);
else if (g_str_equal (entry->setting, "gtk-xft-hinting"))
g_value_set_int (value, display_wayland->xft_settings.hinting);
@@ -1753,18 +2027,14 @@ set_decoration_layout_from_entry (GdkDisplay *display,
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
GSettings *settings = NULL;
const char *session;
/* Hack: until we get session-dependent defaults in GSettings,
* swap out the usual schema for the "classic" one when
* running in classic mode
*/
session = g_getenv ("XDG_CURRENT_DESKTOP");
if (session && strstr (session, "GNOME-Classic"))
settings = (GSettings *)g_hash_table_lookup (display_wayland->settings, CLASSIC_WM_SETTINGS_SCHEMA);
if (display_wayland->settings_portal)
{
g_value_set_string (value, entry->fallback.s);
return;
}
if (settings == NULL)
settings = (GSettings *)g_hash_table_lookup (display_wayland->settings, WM_SETTINGS_SCHEMA);
settings = (GSettings *)g_hash_table_lookup (display_wayland->settings, entry->schema);
if (settings)
{
@@ -1800,7 +2070,8 @@ gdk_wayland_display_get_setting (GdkDisplay *display,
{
TranslationEntry *entry;
if (g_hash_table_size (GDK_WAYLAND_DISPLAY (display)->settings) == 0)
if (GDK_WAYLAND_DISPLAY (display)->settings != NULL &&
g_hash_table_size (GDK_WAYLAND_DISPLAY (display)->settings) == 0)
return FALSE;
entry = find_translation_entry_by_setting (name);
+1
View File
@@ -77,6 +77,7 @@ struct _GdkWaylandDisplay
GHashTable *settings;
GsdXftSettings xft_settings;
GDBusProxy *settings_portal;
guint32 shell_capabilities;
+23 -14
View File
@@ -170,7 +170,7 @@ gdk_wayland_gl_context_get_damage (GdkGLContext *context)
{
GdkGLContext *shared;
GdkWaylandGLContext *shared_wayland;
shared = gdk_gl_context_get_shared_context (context);
if (shared == NULL)
shared = context;
@@ -182,20 +182,29 @@ gdk_wayland_gl_context_get_damage (GdkGLContext *context)
eglQuerySurface (display_wayland->egl_display, egl_surface,
EGL_BUFFER_AGE_EXT, &buffer_age);
if (buffer_age == 2)
switch (buffer_age)
{
if (context->old_updated_area[0])
return cairo_region_copy (context->old_updated_area[0]);
}
else if (buffer_age == 3)
{
if (context->old_updated_area[0] &&
context->old_updated_area[1])
{
cairo_region_t *damage = cairo_region_copy (context->old_updated_area[0]);
cairo_region_union (damage, context->old_updated_area[1]);
return damage;
}
case 1:
return cairo_region_create ();
break;
case 2:
if (context->old_updated_area[0])
return cairo_region_copy (context->old_updated_area[0]);
break;
case 3:
if (context->old_updated_area[0] &&
context->old_updated_area[1])
{
cairo_region_t *damage = cairo_region_copy (context->old_updated_area[0]);
cairo_region_union (damage, context->old_updated_area[1]);
return damage;
}
break;
default:
;
}
}
+10 -226
View File
@@ -117,7 +117,6 @@ struct _GdkSurfaceImplWayland
struct zxdg_popup_v6 *zxdg_popup_v6;
struct gtk_surface1 *gtk_surface;
struct wl_subsurface *wl_subsurface;
struct wl_egl_window *egl_window;
struct wl_egl_window *dummy_egl_window;
struct zxdg_exported_v1 *xdg_exported;
@@ -218,8 +217,6 @@ static void gdk_wayland_surface_maybe_configure (GdkSurface *surface,
static void maybe_set_gtk_surface_dbus_properties (GdkSurface *surface);
static void maybe_set_gtk_surface_modal (GdkSurface *surface);
static void gdk_surface_request_transient_parent_commit (GdkSurface *surface);
static void gdk_wayland_surface_sync_margin (GdkSurface *surface);
static void gdk_wayland_surface_sync_input_region (GdkSurface *surface);
static void gdk_wayland_surface_sync_opaque_region (GdkSurface *surface);
@@ -1030,31 +1027,6 @@ gdk_wayland_surface_sync_input_region (GdkSurface *surface)
impl->input_region_dirty = FALSE;
}
static void
gdk_wayland_set_input_region_if_empty (GdkSurface *surface)
{
GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl);
GdkWaylandDisplay *display;
struct wl_region *empty;
if (!impl->input_region_dirty)
return;
if (impl->input_region == NULL)
return;
if (!cairo_region_is_empty (impl->input_region))
return;
display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
empty = wl_compositor_create_region (display->compositor);
wl_surface_set_input_region (impl->display_server.wl_surface, empty);
wl_region_destroy (empty);
impl->input_region_dirty = FALSE;
}
static void
surface_enter (void *data,
struct wl_surface *wl_surface,
@@ -1093,61 +1065,6 @@ static const struct wl_surface_listener surface_listener = {
surface_leave
};
static void
on_parent_surface_committed (GdkSurfaceImplWayland *parent_impl,
GdkSurface *surface)
{
GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl);
g_signal_handler_disconnect (parent_impl,
impl->parent_surface_committed_handler);
impl->parent_surface_committed_handler = 0;
wl_subsurface_set_desync (impl->display_server.wl_subsurface);
/* Special case if the input region is empty, it won't change on resize */
gdk_wayland_set_input_region_if_empty (surface);
}
static void
gdk_wayland_surface_create_subsurface (GdkSurface *surface)
{
GdkSurfaceImplWayland *impl, *parent_impl = NULL;
GdkWaylandDisplay *display_wayland;
impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl);
if (!impl->display_server.wl_surface)
return; /* Bail out, surface and subsurface will be created later when shown */
if (impl->display_server.wl_subsurface)
return;
if (impl->transient_for)
parent_impl = GDK_SURFACE_IMPL_WAYLAND (impl->transient_for->impl);
if (parent_impl && parent_impl->display_server.wl_surface)
{
display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
impl->display_server.wl_subsurface =
wl_subcompositor_get_subsurface (display_wayland->subcompositor,
impl->display_server.wl_surface, parent_impl->display_server.wl_surface);
wl_subsurface_set_position (impl->display_server.wl_subsurface,
surface->x + surface->abs_x,
surface->y + surface->abs_y);
/* In order to synchronize the initial position with the initial frame
* content, wait with making the subsurface desynchronized until after
* the parent was committed.
*/
impl->parent_surface_committed_handler =
g_signal_connect_object (parent_impl, "committed",
G_CALLBACK (on_parent_surface_committed),
surface, 0);
gdk_surface_request_transient_parent_commit (surface);
}
}
static void
gdk_wayland_surface_create_surface (GdkSurface *surface)
{
@@ -1515,7 +1432,9 @@ gdk_wayland_surface_create_xdg_toplevel (GdkSurface *surface)
impl->initial_fullscreen_output = NULL;
app_id = g_get_prgname ();
app_id = impl->application.application_id;
if (app_id == NULL)
app_id = g_get_prgname ();
if (app_id == NULL)
app_id = "GTK+ Application";
@@ -1567,6 +1486,8 @@ gdk_wayland_surface_handle_configure_popup (GdkSurface *surface,
&flipped_x,
&flipped_y);
impl->position_method = POSITION_METHOD_MOVE_TO_RECT;
g_signal_emit_by_name (surface,
"moved-to-rect",
&flipped_rect,
@@ -1789,23 +1710,15 @@ get_real_parent_and_translate (GdkSurface *surface,
while (parent)
{
GdkSurfaceImplWayland *parent_impl =
GDK_SURFACE_IMPL_WAYLAND (parent->impl);
GdkSurface *effective_parent = gdk_surface_get_parent (parent);
if ((gdk_surface_has_native (parent) &&
!parent_impl->display_server.wl_subsurface) ||
!effective_parent)
if (gdk_surface_has_native (parent) && !effective_parent)
break;
*x += parent->x;
*y += parent->y;
if (gdk_surface_has_native (parent) &&
parent_impl->display_server.wl_subsurface)
parent = parent->transient_for;
else
parent = effective_parent;
parent = effective_parent;
}
return parent;
@@ -2465,38 +2378,9 @@ should_map_as_popup (GdkSurface *surface)
break;
}
return FALSE;
}
static gboolean
should_map_as_subsurface (GdkSurface *surface)
{
GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl);
if (GDK_SURFACE_TYPE (surface) == GDK_SURFACE_SUBSURFACE)
if (impl->position_method == POSITION_METHOD_MOVE_TO_RECT)
return TRUE;
if (GDK_SURFACE_TYPE (surface) != GDK_SURFACE_TEMP)
return FALSE;
/* if we want a popup, we do not want a subsurface */
if (should_map_as_popup (surface))
return FALSE;
if (impl->transient_for)
{
GdkSurfaceImplWayland *impl_parent;
impl_parent = GDK_SURFACE_IMPL_WAYLAND (impl->transient_for->impl);
/* subsurface require that the parent is mapped */
if (impl_parent->mapped)
return TRUE;
else
g_warning ("Couldn't map surface %p as subsurface because its parent is not mapped.",
surface);
}
return FALSE;
}
@@ -2532,15 +2416,7 @@ gdk_wayland_surface_map (GdkSurface *surface)
if (impl->mapped || impl->use_custom_surface)
return;
if (should_map_as_subsurface (surface))
{
if (impl->transient_for)
gdk_wayland_surface_create_subsurface (surface);
else
g_warning ("Couldn't map surface %p as susburface yet because it doesn't have a parent",
surface);
}
else if (should_map_as_popup (surface))
if (should_map_as_popup (surface))
{
gboolean create_fallback = FALSE;
struct wl_seat *grab_input_seat;
@@ -2641,26 +2517,6 @@ gdk_wayland_surface_show (GdkSurface *surface,
gdk_wayland_surface_map (surface);
}
static void
unmap_subsurface (GdkSurface *surface)
{
GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl);
GdkSurfaceImplWayland *parent_impl;
g_return_if_fail (impl->display_server.wl_subsurface);
g_return_if_fail (impl->transient_for);
parent_impl = GDK_SURFACE_IMPL_WAYLAND (impl->transient_for->impl);
wl_subsurface_destroy (impl->display_server.wl_subsurface);
if (impl->parent_surface_committed_handler)
{
g_signal_handler_disconnect (parent_impl,
impl->parent_surface_committed_handler);
impl->parent_surface_committed_handler = 0;
}
impl->display_server.wl_subsurface = NULL;
}
static void
unmap_popups_for_surface (GdkSurface *surface)
{
@@ -2761,9 +2617,6 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
impl->initial_configure_received = FALSE;
}
if (impl->display_server.wl_subsurface)
unmap_subsurface (surface);
if (impl->awaiting_frame)
{
GdkFrameClock *frame_clock;
@@ -2837,32 +2690,6 @@ gdk_surface_wayland_restack_toplevel (GdkSurface *surface,
{
}
static void
gdk_surface_request_transient_parent_commit (GdkSurface *surface)
{
GdkSurfaceImplWayland *surface_impl, *impl;
GdkFrameClock *frame_clock;
surface_impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl);
if (!surface_impl->transient_for)
return;
impl = GDK_SURFACE_IMPL_WAYLAND (surface_impl->transient_for->impl);
if (!impl->display_server.wl_surface || impl->pending_commit)
return;
frame_clock = gdk_surface_get_frame_clock (surface_impl->transient_for);
if (!frame_clock)
return;
impl->pending_commit = TRUE;
gdk_frame_clock_request_phase (frame_clock,
GDK_FRAME_CLOCK_PHASE_AFTER_PAINT);
}
static void
gdk_surface_wayland_move_resize (GdkSurface *surface,
gboolean with_move,
@@ -2881,14 +2708,6 @@ gdk_surface_wayland_move_resize (GdkSurface *surface,
surface->x = x;
surface->y = y;
impl->position_method = POSITION_METHOD_MOVE_RESIZE;
if (impl->display_server.wl_subsurface)
{
wl_subsurface_set_position (impl->display_server.wl_subsurface,
surface->x + surface->abs_x,
surface->y + surface->abs_y);
gdk_surface_request_transient_parent_commit (surface);
}
}
}
@@ -3414,9 +3233,6 @@ gdk_wayland_surface_set_transient_for (GdkSurface *surface,
unset_transient_for_exported (surface);
if (impl->display_server.wl_subsurface)
unmap_subsurface (surface);
previous_parent = impl->transient_for;
impl->transient_for = parent;
@@ -3429,9 +3245,6 @@ gdk_wayland_surface_set_transient_for (GdkSurface *surface,
g_list_remove (display_wayland->orphan_dialogs, surface);
}
gdk_wayland_surface_sync_parent (surface, NULL);
if (should_map_as_subsurface (surface) &&
parent && gdk_surface_is_visible (surface))
gdk_wayland_surface_create_subsurface (surface);
}
static void
@@ -4098,34 +3911,6 @@ _gdk_wayland_surface_set_grab_seat (GdkSurface *surface,
impl->grab_input_seat = seat;
}
/**
* gdk_wayland_surface_new_subsurface: (constructor)
* @display: the display to create the surface on
* @position: position relative to the transient surface
*
* Creates a new subsurface surface.
*
* Returns: (transfer full): the new #GdkSurface
**/
GdkSurface *
gdk_wayland_surface_new_subsurface (GdkDisplay *display,
const GdkRectangle *position)
{
GdkSurfaceAttr attr;
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
g_return_val_if_fail (position != NULL, NULL);
attr.wclass = GDK_INPUT_OUTPUT;
attr.x = position->x;
attr.y = position->y;
attr.width = position->width;
attr.height = position->height;
attr.surface_type = GDK_SURFACE_SUBSURFACE;
return gdk_surface_new (display, NULL, &attr);
}
/**
* gdk_wayland_surface_get_wl_surface:
* @surface: (type GdkWaylandSurface): a #GdkSurface
@@ -4533,8 +4318,7 @@ gdk_wayland_surface_set_transient_for_exported (GdkSurface *surface,
g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (surface), FALSE);
g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), FALSE);
g_return_val_if_fail (!should_map_as_subsurface (surface) &&
!should_map_as_popup (surface), FALSE);
g_return_val_if_fail (!should_map_as_popup (surface), FALSE);
impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl);
display_wayland = GDK_WAYLAND_DISPLAY (display);
+8 -44
View File
@@ -1655,7 +1655,7 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
g_hash_table_replace (win32_clipdrop->compatibility_w32formats, (gpointer) fmt.contentformat, comp);
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 3);
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 2);
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_PNG);
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_IMAGE_PNG);
@@ -1665,14 +1665,10 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_PNG);
g_array_append_val (comp, fmt);
fmt.w32format = CF_DIB;
fmt.transmute = TRUE;
g_array_append_val (comp, fmt);
g_hash_table_replace (win32_clipdrop->compatibility_w32formats, (gpointer) fmt.contentformat, comp);
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 4);
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 2);
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_JPEG);
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_IMAGE_JPEG);
@@ -1682,17 +1678,10 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_JFIF);
g_array_append_val (comp, fmt);
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_PNG);
fmt.transmute = TRUE;
g_array_append_val (comp, fmt);
fmt.w32format = CF_DIB;
g_array_append_val (comp, fmt);
g_hash_table_replace (win32_clipdrop->compatibility_w32formats, (gpointer) fmt.contentformat, comp);
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 4);
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 2);
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_GIF);
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_IMAGE_GIF);
@@ -1702,13 +1691,6 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_GIF);
g_array_append_val (comp, fmt);
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_PNG);
fmt.transmute = TRUE;
g_array_append_val (comp, fmt);
fmt.w32format = CF_DIB;
g_array_append_val (comp, fmt);
g_hash_table_replace (win32_clipdrop->compatibility_w32formats, (gpointer) fmt.contentformat, comp);
@@ -1771,7 +1753,7 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
g_hash_table_replace (win32_clipdrop->compatibility_contentformats, GINT_TO_POINTER (CF_UNICODETEXT), comp);
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 3);
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 2);
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_PNG);
fmt.transmute = FALSE;
@@ -1781,14 +1763,10 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_PNG);
g_array_append_val (comp, fmt);
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_BMP);
fmt.transmute = TRUE;
g_array_append_val (comp, fmt);
g_hash_table_replace (win32_clipdrop->compatibility_contentformats, GINT_TO_POINTER (_gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_PNG)), comp);
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 4);
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 2);
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_JFIF);
fmt.transmute = FALSE;
@@ -1798,17 +1776,10 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_JPEG);
g_array_append_val (comp, fmt);
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_PNG);
fmt.transmute = TRUE;
g_array_append_val (comp, fmt);
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_BMP);
g_array_append_val (comp, fmt);
g_hash_table_replace (win32_clipdrop->compatibility_contentformats, GINT_TO_POINTER (_gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_JFIF)), comp);
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 4);
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 2);
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_GIF);
fmt.transmute = FALSE;
@@ -1818,17 +1789,10 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_GIF);
g_array_append_val (comp, fmt);
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_PNG);
fmt.transmute = TRUE;
g_array_append_val (comp, fmt);
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_BMP);
g_array_append_val (comp, fmt);
g_hash_table_replace (win32_clipdrop->compatibility_contentformats, GINT_TO_POINTER (_gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_GIF)), comp);
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 3);
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 2);
fmt.w32format = CF_DIB;
fmt.transmute = FALSE;
@@ -1842,7 +1806,7 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
g_hash_table_replace (win32_clipdrop->compatibility_contentformats, GINT_TO_POINTER (CF_DIB), comp);
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 3);
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 2);
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_CFSTR_SHELLIDLIST);
fmt.transmute = FALSE;
+29 -7
View File
@@ -1701,7 +1701,7 @@ ensure_stacking_on_unminimize (MSG *msg)
g_print (" restacking %p above %p",
msg->hwnd, lowest_transient));
SetWindowPos (msg->hwnd, lowest_transient, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER);
}
}
@@ -1782,7 +1782,7 @@ ensure_stacking_on_activate_app (MSG *msg,
impl->transient_owner != NULL)
{
SetWindowPos (msg->hwnd, HWND_TOP, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER);
return;
}
@@ -1824,7 +1824,7 @@ ensure_stacking_on_activate_app (MSG *msg,
g_print (" restacking %p above %p",
msg->hwnd, rover));
SetWindowPos (msg->hwnd, rover, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER);
break;
}
}
@@ -2124,6 +2124,7 @@ gdk_event_translate (MSG *msg,
(gulong) msg->wParam,
(gpointer) msg->lParam, _gdk_input_locale_is_ime ? " (IME)" : "",
_gdk_input_codepage));
gdk_display_setting_changed (display, "gtk-im-module");
break;
case WM_SYSKEYUP:
@@ -2712,13 +2713,20 @@ gdk_event_translate (MSG *msg,
event = gdk_event_new (GDK_SCROLL);
event->any.surface = window;
event->scroll.direction = GDK_SCROLL_SMOOTH;
if (msg->message == WM_MOUSEWHEEL)
event->scroll.direction = (((short) HIWORD (msg->wParam)) > 0) ?
GDK_SCROLL_UP : GDK_SCROLL_DOWN;
{
event->scroll.delta_y = (gdouble) GET_WHEEL_DELTA_WPARAM (msg->wParam) / (gdouble) WHEEL_DELTA;
}
else if (msg->message == WM_MOUSEHWHEEL)
event->scroll.direction = (((short) HIWORD (msg->wParam)) > 0) ?
GDK_SCROLL_RIGHT : GDK_SCROLL_LEFT;
{
event->scroll.delta_x = (gdouble) GET_WHEEL_DELTA_WPARAM (msg->wParam) / (gdouble) WHEEL_DELTA;
}
/* Positive delta scrolls up, not down,
see API documentation for WM_MOUSEWHEEL message.
*/
event->scroll.delta_y *= -1.0;
event->scroll.time = _gdk_win32_get_next_tick (msg->time);
event->scroll.x = (gint16) point.x / impl->surface_scale;
event->scroll.y = (gint16) point.y / impl->surface_scale;
@@ -2727,6 +2735,20 @@ gdk_event_translate (MSG *msg,
event->scroll.state = build_pointer_event_state (msg);
gdk_event_set_device (event, device_manager_win32->core_pointer);
gdk_event_set_source_device (event, device_manager_win32->system_pointer);
gdk_event_set_pointer_emulated (event, FALSE);
_gdk_win32_append_event (gdk_event_copy (event));
/* Append the discrete version too */
if (msg->message == WM_MOUSEWHEEL)
event->scroll.direction = (((short) HIWORD (msg->wParam)) > 0) ?
GDK_SCROLL_UP : GDK_SCROLL_DOWN;
else if (msg->message == WM_MOUSEHWHEEL)
event->scroll.direction = (((short) HIWORD (msg->wParam)) > 0) ?
GDK_SCROLL_RIGHT : GDK_SCROLL_LEFT;
event->scroll.delta_x = 0;
event->scroll.delta_y = 0;
gdk_event_set_pointer_emulated (event, TRUE);
_gdk_win32_append_event (event);
+1 -1
View File
@@ -201,7 +201,7 @@ gdk_win32_hdata_output_stream_close (GOutputStream *output_stream,
if (priv->handle_is_buffer)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Can't transmute a single handle"));
_("Cant transmute a single handle"));
return FALSE;
}
+89 -48
View File
@@ -27,12 +27,39 @@
#include <string.h>
#include <stdlib.h>
#include <glib/gprintf.h>
#include <pango/pangowin32.h>
#include "gdkproperty.h"
#include "gdkdisplayprivate.h"
#include "gdkprivate-win32.h"
#include "gdkwin32.h"
static gchar*
_get_system_font_name (HDC hdc)
{
NONCLIENTMETRICSW ncm;
PangoFontDescription *font_desc;
gchar *result, *font_desc_string;
int logpixelsy;
gint font_size;
ncm.cbSize = sizeof(NONCLIENTMETRICSW);
if (!SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0))
return NULL;
logpixelsy = GetDeviceCaps (hdc, LOGPIXELSY);
font_desc = pango_win32_font_description_from_logfontw (&ncm.lfMessageFont);
font_desc_string = pango_font_description_to_string (font_desc);
pango_font_description_free (font_desc);
/* https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/ns-wingdi-taglogfonta */
font_size = -MulDiv (ncm.lfMessageFont.lfHeight, 72, logpixelsy);
result = g_strdup_printf ("%s %d", font_desc_string, font_size);
g_free (font_desc_string);
return result;
}
/*
For reference, from gdk/x11/gdksettings.c:
@@ -124,61 +151,75 @@ _gdk_win32_get_setting (const gchar *name,
g_value_set_boolean (value, TRUE);
return TRUE;
}
else if (strcmp ("gtk-xft-hinting", name) == 0)
{
GDK_NOTE(MISC, g_print ("gdk_screen_get_setting(\"%s\") : 1\n", name));
g_value_set_int (value, 1);
return TRUE;
}
else if (strcmp ("gtk-xft-antialias", name) == 0)
{
GDK_NOTE(MISC, g_print ("gdk_screen_get_setting(\"%s\") : 1\n", name));
g_value_set_int (value, 1);
return TRUE;
}
else if (strcmp ("gtk-xft-hintstyle", name) == 0)
{
g_value_set_static_string (value, "hintfull");
GDK_NOTE(MISC, g_print ("gdk_screen_get_setting(\"%s\") : %s\n", name, g_value_get_string (value)));
return TRUE;
}
else if (strcmp ("gtk-xft-rgba", name) == 0)
{
unsigned int orientation = 0;
if (SystemParametersInfoW (SPI_GETFONTSMOOTHINGORIENTATION, 0, &orientation, 0))
{
if (orientation == FE_FONTSMOOTHINGORIENTATIONRGB)
g_value_set_static_string (value, "rgb");
else if (orientation == FE_FONTSMOOTHINGORIENTATIONBGR)
g_value_set_static_string (value, "bgr");
else
g_value_set_static_string (value, "none");
}
else
g_value_set_static_string (value, "none");
GDK_NOTE(MISC, g_print ("gdk_screen_get_setting(\"%s\") : %s\n", name, g_value_get_string (value)));
return TRUE;
}
else if (strcmp ("gtk-font-name", name) == 0)
{
NONCLIENTMETRICS ncm;
CPINFOEX cpinfoex_default, cpinfoex_curr_thread;
OSVERSIONINFO info;
BOOL result_default, result_curr_thread;
gchar *font_name = _get_system_font_name (_gdk_display_hdc);
info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
/* TODO: Fallback to using Pango on Windows 8 and later,
* as this method of handling gtk-font-name does not work
* well there, where garbled text will be displayed for texts
* that are not supported by the default menu font. Look for
* whether there is a better solution for this on Windows 8 and
* later
*/
if (!GetVersionEx (&info) ||
info.dwMajorVersion > 6 ||
(info.dwMajorVersion == 6 && info.dwMinorVersion >= 2))
return FALSE;
/* check whether the system default ANSI codepage matches the
* ANSI code page of the running thread. If so, continue, otherwise
* fall back to using Pango to handle gtk-font-name
*/
result_default = GetCPInfoEx (CP_ACP, 0, &cpinfoex_default);
result_curr_thread = GetCPInfoEx (CP_THREAD_ACP, 0, &cpinfoex_curr_thread);
if (!result_default ||
!result_curr_thread ||
cpinfoex_default.CodePage != cpinfoex_curr_thread.CodePage)
return FALSE;
ncm.cbSize = sizeof(NONCLIENTMETRICS);
if (SystemParametersInfo (SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, FALSE))
if (font_name)
{
/* Pango finally uses GetDeviceCaps to scale, we use simple
* approximation here.
*/
int nHeight = (0 > ncm.lfMenuFont.lfHeight ? - 3 * ncm.lfMenuFont.lfHeight / 4 : 10);
if (OUT_STRING_PRECIS == ncm.lfMenuFont.lfOutPrecision)
GDK_NOTE(MISC, g_print("gdk_display_get_setting(%s) : ignoring bitmap font '%s'\n",
name, ncm.lfMenuFont.lfFaceName));
else if (ncm.lfMenuFont.lfFaceName && strlen(ncm.lfMenuFont.lfFaceName) > 0 &&
/* Avoid issues like those described in bug #135098 */
g_utf8_validate (ncm.lfMenuFont.lfFaceName, -1, NULL))
/* The pango font fallback list got fixed during 1.43, before that
* using anything but "Segoe UI" would lead to a poor glyph coverage */
if (pango_version_check (1, 43, 0) != NULL &&
g_ascii_strncasecmp (font_name, "Segoe UI", strlen ("Segoe UI")) != 0)
{
char *s = g_strdup_printf ("%s %d", ncm.lfMenuFont.lfFaceName, nHeight);
GDK_NOTE(MISC, g_print("gdk_display_get_setting(%s) : %s\n", name, s));
g_value_set_string (value, s);
g_free(s);
return TRUE;
g_free (font_name);
return FALSE;
}
GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %s\n", name, font_name));
g_value_take_string (value, font_name);
return TRUE;
}
else
{
g_warning ("gdk_screen_get_setting: Detecting the system font failed");
return FALSE;
}
}
else if (strcmp ("gtk-im-module", name) == 0)
{
if (_gdk_input_locale_is_ime)
g_value_set_string (value, "ime");
else
g_value_set_string (value, "");
return TRUE;
}
return FALSE;
+9 -9
View File
@@ -1118,7 +1118,7 @@ show_window_internal (GdkSurface *window,
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
(window->state & GDK_SURFACE_STATE_ABOVE)?HWND_TOPMOST:HWND_NOTOPMOST,
0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOOWNERZORDER));
}
}
@@ -1376,7 +1376,7 @@ gdk_win32_surface_raise (GdkSurface *window)
if (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP)
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_TOPMOST,
0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER));
else if (window->accept_focus)
/* Do not wrap this in an API_CALL macro as SetForegroundWindow might
* fail when for example dragging a window belonging to a different
@@ -1386,7 +1386,7 @@ gdk_win32_surface_raise (GdkSurface *window)
else
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_TOP,
0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER));
}
}
@@ -1403,7 +1403,7 @@ gdk_win32_surface_lower (GdkSurface *window)
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_BOTTOM,
0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER));
}
}
@@ -2313,7 +2313,7 @@ _gdk_win32_surface_update_style_bits (GdkSurface *window)
rect.right += after.right - before.right;
rect.bottom += after.bottom - before.bottom;
flags = SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOREPOSITION;
flags = SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOREPOSITION | SWP_NOOWNERZORDER;
if (will_be_topmost && !was_topmost)
{
@@ -4767,7 +4767,7 @@ gdk_win32_surface_fullscreen (GdkSurface *window)
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_TOP,
x, y, width, height,
SWP_NOCOPYBITS | SWP_SHOWWINDOW));
SWP_NOCOPYBITS | SWP_SHOWWINDOW | SWP_NOOWNERZORDER));
}
}
@@ -4790,7 +4790,7 @@ gdk_win32_surface_unfullscreen (GdkSurface *window)
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_NOTOPMOST,
fi->r.left, fi->r.top,
fi->r.right - fi->r.left, fi->r.bottom - fi->r.top,
SWP_NOCOPYBITS | SWP_SHOWWINDOW));
SWP_NOCOPYBITS | SWP_SHOWWINDOW | SWP_NOOWNERZORDER));
g_object_set_data (G_OBJECT (window), "fullscreen-info", NULL);
g_free (fi);
@@ -4816,7 +4816,7 @@ gdk_win32_surface_set_keep_above (GdkSurface *window,
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
setting ? HWND_TOPMOST : HWND_NOTOPMOST,
0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOOWNERZORDER));
}
gdk_synthesize_surface_state (window,
@@ -4842,7 +4842,7 @@ gdk_win32_surface_set_keep_below (GdkSurface *window,
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
setting ? HWND_BOTTOM : HWND_NOTOPMOST,
0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOOWNERZORDER));
}
gdk_synthesize_surface_state (window,
+1
View File
@@ -45,6 +45,7 @@ install_headers(gdk_win32_public_headers, subdir: 'gtk-4.0/gdk/win32/')
install_headers('gdkwin32.h', subdir: 'gtk-4.0/gdk/')
gdk_win32_deps = [ # FIXME
pangowin32_dep
]
libgdk_win32 = static_library('gdk-win32',
+1 -1
View File
@@ -261,7 +261,7 @@ gdk_x11_cursor_create_for_name (GdkDisplay *display,
/**
* gdk_x11_display_set_cursor_theme:
* @display: (type GdkX11Display): a #GdkDisplay
* @theme: the name of the cursor theme to use, or %NULL to unset
* @theme: (nullable): the name of the cursor theme to use, or %NULL to unset
* a previously set value
* @size: the cursor size to use, or 0 to keep the previous size
*
+86 -4
View File
@@ -40,6 +40,23 @@
#include <string.h>
static const char *wacom_type_atoms[] = {
"STYLUS",
"CURSOR",
"ERASER",
"PAD",
"TOUCH"
};
#define N_WACOM_TYPE_ATOMS G_N_ELEMENTS (wacom_type_atoms)
enum {
WACOM_TYPE_STYLUS,
WACOM_TYPE_CURSOR,
WACOM_TYPE_ERASER,
WACOM_TYPE_PAD,
WACOM_TYPE_TOUCH,
};
struct _GdkX11DeviceManagerXI2
{
GdkX11DeviceManagerCore parent_object;
@@ -999,6 +1016,66 @@ device_get_tool_serial_and_id (GdkDevice *device,
return TRUE;
}
static GdkDeviceToolType
device_get_tool_type (GdkDevice *device)
{
GdkDisplay *display;
gulong nitems, bytes_after;
guint32 *data;
int rc, format;
Atom type;
Atom device_type;
Atom types[N_WACOM_TYPE_ATOMS];
GdkDeviceToolType tool_type = GDK_DEVICE_TOOL_TYPE_UNKNOWN;
display = gdk_device_get_display (device);
gdk_x11_display_error_trap_push (display);
rc = XIGetProperty (GDK_DISPLAY_XDISPLAY (display),
gdk_x11_device_get_id (device),
gdk_x11_get_xatom_by_name_for_display (display, "Wacom Tool Type"),
0, 1, False, XA_ATOM, &type, &format, &nitems, &bytes_after,
(guchar **) &data);
gdk_x11_display_error_trap_pop_ignored (display);
if (rc != Success)
return GDK_DEVICE_TOOL_TYPE_UNKNOWN;
if (type != XA_ATOM || format != 32 || nitems != 1)
{
XFree (data);
return GDK_DEVICE_TOOL_TYPE_UNKNOWN;
}
device_type = *data;
XFree (data);
if (device_type == 0)
return GDK_DEVICE_TOOL_TYPE_UNKNOWN;
gdk_x11_display_error_trap_push (display);
rc = XInternAtoms (GDK_DISPLAY_XDISPLAY (display),
(char **) wacom_type_atoms,
N_WACOM_TYPE_ATOMS,
False,
types);
gdk_x11_display_error_trap_pop_ignored (display);
if (rc == 0)
return GDK_DEVICE_TOOL_TYPE_UNKNOWN;
if (device_type == types[WACOM_TYPE_STYLUS])
tool_type = GDK_DEVICE_TOOL_TYPE_PEN;
else if (device_type == types[WACOM_TYPE_CURSOR])
tool_type = GDK_DEVICE_TOOL_TYPE_MOUSE;
else if (device_type == types[WACOM_TYPE_ERASER])
tool_type = GDK_DEVICE_TOOL_TYPE_ERASER;
else if (device_type == types[WACOM_TYPE_TOUCH])
tool_type = GDK_DEVICE_TOOL_TYPE_UNKNOWN;
return tool_type;
}
static void
handle_property_change (GdkX11DeviceManagerXI2 *device_manager,
XIPropertyEvent *ev)
@@ -1019,13 +1096,18 @@ handle_property_change (GdkX11DeviceManagerXI2 *device_manager,
device_get_tool_serial_and_id (device, &serial_id, &tool_id))
{
seat = gdk_device_get_seat (device);
tool = gdk_seat_get_tool (seat, serial_id);
tool = gdk_seat_get_tool (seat, serial_id, tool_id);
if (!tool && serial_id > 0)
{
tool = gdk_device_tool_new (serial_id, tool_id,
GDK_DEVICE_TOOL_TYPE_UNKNOWN, 0);
gdk_seat_default_add_tool (GDK_SEAT_DEFAULT (seat), tool);
GdkDeviceToolType tool_type;
tool_type = device_get_tool_type (device);
if (tool_type != GDK_DEVICE_TOOL_TYPE_UNKNOWN)
{
tool = gdk_device_tool_new (serial_id, tool_id, tool_type, 0);
gdk_seat_default_add_tool (GDK_SEAT_DEFAULT (seat), tool);
}
}
}
+3 -3
View File
@@ -1600,7 +1600,7 @@ gdk_x11_display_open (const gchar *display_name)
if (!gdk_running_in_sandbox ())
{
/* if sandboxed, we're likely in a pid namespace and would only confuse the wm with this */
pid_t pid = getpid ();
long pid = getpid ();
XChangeProperty (display_x11->xdisplay,
display_x11->leader_window,
gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PID"),
@@ -2822,8 +2822,8 @@ gdk_x11_display_error_trap_pop_ignored (GdkDisplay *display)
/**
* gdk_x11_set_sm_client_id:
* @sm_client_id: the client id assigned by the session manager when the
* connection was opened, or %NULL to remove the property.
* @sm_client_id: (nullable): the client id assigned by the session manager
* when the connection was opened, or %NULL to remove the property.
*
* Sets the `SM_CLIENT_ID` property on the applications leader window so that
* the window manager can save the applications state using the X11R6 ICCCM
+26 -16
View File
@@ -201,31 +201,41 @@ gdk_x11_gl_context_get_damage (GdkGLContext *context)
{
GdkGLContext *shared;
GdkX11GLContext *shared_x11;
shared = gdk_gl_context_get_shared_context (context);
if (shared == NULL)
shared = context;
shared_x11 = GDK_X11_GL_CONTEXT (shared);
gdk_gl_context_make_current (shared);
glXQueryDrawable(dpy, shared_x11->attached_drawable,
GLX_BACK_BUFFER_AGE_EXT, &buffer_age);
glXQueryDrawable (dpy, shared_x11->attached_drawable,
GLX_BACK_BUFFER_AGE_EXT, &buffer_age);
if (buffer_age == 2)
switch (buffer_age)
{
if (context->old_updated_area[0])
return cairo_region_copy (context->old_updated_area[0]);
}
else if (buffer_age == 3)
{
if (context->old_updated_area[0] &&
context->old_updated_area[1])
{
cairo_region_t *damage = cairo_region_copy (context->old_updated_area[0]);
cairo_region_union (damage, context->old_updated_area[1]);
return damage;
}
case 1:
return cairo_region_create ();
break;
case 2:
if (context->old_updated_area[0])
return cairo_region_copy (context->old_updated_area[0]);
break;
case 3:
if (context->old_updated_area[0] &&
context->old_updated_area[1])
{
cairo_region_t *damage = cairo_region_copy (context->old_updated_area[0]);
cairo_region_union (damage, context->old_updated_area[1]);
return damage;
}
break;
default:
;
}
}
return GDK_GL_CONTEXT_CLASS (gdk_x11_gl_context_parent_class)->get_damage (context);
+1 -1
View File
@@ -140,7 +140,7 @@ gdk_x11_selection_input_stream_flush (GdkX11SelectionInputStream *stream)
written, priv->pending_size));
g_task_return_int (priv->pending_task, written);
priv->pending_task = NULL;
g_clear_object (&priv->pending_task);
priv->pending_data = NULL;
priv->pending_size = 0;
}
+1 -1
View File
@@ -746,7 +746,7 @@ setup_toplevel_window (GdkSurface *surface,
if (!gdk_running_in_sandbox ())
{
/* if sandboxed, we're likely in a pid namespace and would only confuse the wm with this */
pid_t pid = getpid ();
long pid = getpid ();
XChangeProperty (xdisplay, xid,
gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_PID"),
XA_CARDINAL, 32,
+49 -35
View File
@@ -46,6 +46,7 @@ struct _GskGLDriver
Fbo default_fbo;
GHashTable *textures;
GHashTable *pointer_textures;
const Texture *bound_source_texture;
const Fbo *bound_fbo;
@@ -119,6 +120,7 @@ gsk_gl_driver_finalize (GObject *gobject)
gdk_gl_context_make_current (self->gl_context);
g_clear_pointer (&self->textures, g_hash_table_unref);
g_clear_pointer (&self->pointer_textures, g_hash_table_unref);
g_clear_object (&self->profiler);
if (self->gl_context == gdk_gl_context_get_current ())
@@ -263,7 +265,28 @@ gsk_gl_driver_collect_textures (GskGLDriver *self)
}
}
else
g_hash_table_iter_remove (&iter);
{
/* Remove from self->pointer_textures. */
/* TODO: Is there a better way for this? */
if (self->pointer_textures)
{
GHashTableIter pointer_iter;
gpointer value;
gpointer p;
g_hash_table_iter_init (&pointer_iter, self->pointer_textures);
while (g_hash_table_iter_next (&pointer_iter, &p, &value))
{
if (GPOINTER_TO_INT (value) == t->texture_id)
{
g_hash_table_iter_remove (&pointer_iter);
break;
}
}
}
g_hash_table_iter_remove (&iter);
}
}
return old_size - g_hash_table_size (self->textures);
@@ -307,26 +330,6 @@ gsk_gl_driver_get_fbo (GskGLDriver *self,
return &t->fbo;
}
static Texture *
find_texture_by_size (GHashTable *textures,
int width,
int height)
{
GHashTableIter iter;
gpointer value_p = NULL;
g_hash_table_iter_init (&iter, textures);
while (g_hash_table_iter_next (&iter, NULL, &value_p))
{
Texture *t = value_p;
if (t->width == width && t->height == height)
return t;
}
return NULL;
}
static Texture *
create_texture (GskGLDriver *self,
float fwidth,
@@ -351,21 +354,7 @@ create_texture (GskGLDriver *self,
height = MIN (height, self->max_texture_size);
}
t = find_texture_by_size (self->textures, width, height);
if (t != NULL && !t->in_use && t->user == NULL)
{
GSK_NOTE (OPENGL, g_message ("Reusing Texture(%d) for size %dx%d",
t->texture_id, t->width, t->height));
t->in_use = TRUE;
#ifdef G_ENABLE_DEBUG
gsk_profiler_counter_inc (self->profiler, self->counters.reused_textures);
#endif
return t;
}
glGenTextures (1, &texture_id);
t = texture_new ();
t->texture_id = texture_id;
t->width = width;
@@ -547,6 +536,31 @@ gsk_gl_driver_get_texture_for_texture (GskGLDriver *self,
return t->texture_id;
}
int
gsk_gl_driver_get_texture_for_pointer (GskGLDriver *self,
gpointer pointer)
{
int id = 0;
if (G_UNLIKELY (self->pointer_textures == NULL))
self->pointer_textures = g_hash_table_new (NULL, NULL);
id = GPOINTER_TO_INT (g_hash_table_lookup (self->pointer_textures, pointer));
return id;
}
void
gsk_gl_driver_set_texture_for_pointer (GskGLDriver *self,
gpointer pointer,
int texture_id)
{
if (G_UNLIKELY (self->pointer_textures == NULL))
self->pointer_textures = g_hash_table_new (NULL, NULL);
g_hash_table_insert (self->pointer_textures, pointer, GINT_TO_POINTER (texture_id));
}
int
gsk_gl_driver_create_permanent_texture (GskGLDriver *self,
float width,
+5
View File
@@ -33,6 +33,11 @@ int gsk_gl_driver_get_texture_for_texture (GskGLDriver *driver
GdkTexture *texture,
int min_filter,
int mag_filter);
int gsk_gl_driver_get_texture_for_pointer (GskGLDriver *driver,
gpointer pointer);
void gsk_gl_driver_set_texture_for_pointer (GskGLDriver *driver,
gpointer pointer,
int texture_id);
int gsk_gl_driver_create_permanent_texture (GskGLDriver *driver,
float width,
float height);
+19 -51
View File
@@ -24,21 +24,6 @@
#define ATLAS_SIZE 512
typedef struct
{
PangoFont *font;
PangoGlyph glyph;
guint scale; /* times 1024 */
} GlyphCacheKey;
typedef struct
{
GlyphCacheKey *key;
GskGLCachedGlyph *value;
cairo_surface_t *surface;
} DirtyGlyph;
static guint glyph_cache_hash (gconstpointer v);
static gboolean glyph_cache_equal (gconstpointer v1,
gconstpointer v2);
@@ -58,8 +43,6 @@ create_atlas (GskGLGlyphCache *cache)
atlas->y = 1;
atlas->x = 1;
atlas->image = NULL;
atlas->num_glyphs = 0;
atlas->dirty_glyphs = NULL;
return atlas;
}
@@ -74,7 +57,7 @@ free_atlas (gpointer v)
g_assert (atlas->image->texture_id == 0);
g_free (atlas->image);
}
g_list_free_full (atlas->dirty_glyphs, dirty_glyph_free);
g_free (atlas);
}
@@ -153,17 +136,15 @@ dirty_glyph_free (gpointer v)
if (glyph->surface)
cairo_surface_destroy (glyph->surface);
g_free (glyph);
}
static void
add_to_cache (GskGLGlyphCache *cache,
GlyphCacheKey *key,
GlyphCacheKey *key,
GskGLCachedGlyph *value)
{
GskGLGlyphAtlas *atlas;
int i;
DirtyGlyph *dirty;
int width = value->draw_width * key->scale / 1024;
int height = value->draw_height * key->scale / 1024;
@@ -205,16 +186,12 @@ add_to_cache (GskGLGlyphCache *cache,
value->atlas = atlas;
dirty = g_new0 (DirtyGlyph, 1);
dirty->key = key;
dirty->value = value;
atlas->dirty_glyphs = g_list_prepend (atlas->dirty_glyphs, dirty);
atlas->pending_glyph.key = key;
atlas->pending_glyph.value = value;
atlas->x = atlas->x + width + 1;
atlas->y = MAX (atlas->y, atlas->y0 + height + 1);
atlas->num_glyphs++;
#ifdef G_ENABLE_DEBUG
if (GSK_RENDERER_DEBUG_CHECK (cache->renderer, GLYPH_CACHE))
{
@@ -222,9 +199,8 @@ add_to_cache (GskGLGlyphCache *cache,
for (i = 0; i < cache->atlases->len; i++)
{
atlas = g_ptr_array_index (cache->atlases, i);
g_print ("\tGskGLGlyphAtlas %d (%dx%d): %d glyphs (%d dirty), %.2g%% old pixels, filled to %d, %d / %d\n",
g_print ("\tGskGLGlyphAtlas %d (%dx%d): %.2g%% old pixels, filled to %d, %d / %d\n",
i, atlas->width, atlas->height,
atlas->num_glyphs, g_list_length (atlas->dirty_glyphs),
100.0 * (double)atlas->old_pixels / (double)(atlas->width * atlas->height),
atlas->x, atlas->y0, atlas->y);
}
@@ -284,28 +260,20 @@ render_glyph (const GskGLGlyphAtlas *atlas,
}
static void
upload_dirty_glyphs (GskGLGlyphCache *self,
GskGLGlyphAtlas *atlas)
upload_dirty_glyph (GskGLGlyphCache *self,
GskGLGlyphAtlas *atlas)
{
GList *l;
guint num_regions;
GskImageRegion *regions;
int i;
GskImageRegion region;
num_regions = g_list_length (atlas->dirty_glyphs);
regions = alloca (sizeof (GskImageRegion) * num_regions);
g_assert (atlas->pending_glyph.key != NULL);
for (l = atlas->dirty_glyphs, i = 0; l; l = l->next, i++)
render_glyph (atlas, (DirtyGlyph *)l->data, &regions[i]);
render_glyph (atlas, &atlas->pending_glyph, &region);
GSK_RENDERER_NOTE (self->renderer, GLYPH_CACHE,
g_message ("uploading %d glyphs to cache", num_regions));
gsk_gl_image_upload_regions (atlas->image, self->gl_driver, 1, &region);
gsk_gl_image_upload_regions (atlas->image, self->gl_driver, num_regions, regions);
g_list_free_full (atlas->dirty_glyphs, dirty_glyph_free);
atlas->dirty_glyphs = NULL;
dirty_glyph_free (&atlas->pending_glyph);
atlas->pending_glyph.key = NULL;
atlas->pending_glyph.value = NULL;
}
const GskGLCachedGlyph *
@@ -354,12 +322,13 @@ gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache,
value->draw_height = ink_rect.height;
value->timestamp = cache->timestamp;
value->atlas = NULL; /* For now */
value->scale = (guint)(scale * 1024);
key->font = g_object_ref (font);
key->glyph = glyph;
key->scale = (guint)(scale * 1024);
if (ink_rect.width > 0 && ink_rect.height > 0)
if (ink_rect.width > 0 && ink_rect.height > 0 && key->scale > 0)
add_to_cache (cache, key, value);
g_hash_table_insert (cache->hash_table, key, value);
@@ -369,22 +338,21 @@ gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache,
}
GskGLImage *
gsk_gl_glyph_cache_get_glyph_image (GskGLGlyphCache *self,
gsk_gl_glyph_cache_get_glyph_image (GskGLGlyphCache *self,
const GskGLCachedGlyph *glyph)
{
GskGLGlyphAtlas *atlas = glyph->atlas;
g_assert (atlas != NULL);
if (atlas->image == NULL)
{
atlas->image = g_new0 (GskGLImage, 1);
gsk_gl_image_create (atlas->image, self->gl_driver, atlas->width, atlas->height);
}
if (atlas->dirty_glyphs)
upload_dirty_glyphs (self, atlas);
if (atlas->pending_glyph.key != NULL)
upload_dirty_glyph (self, atlas);
return atlas->image;
}
+23 -4
View File
@@ -18,18 +18,34 @@ typedef struct
guint64 timestamp;
} GskGLGlyphCache;
typedef struct
{
PangoFont *font;
PangoGlyph glyph;
guint scale; /* times 1024 */
} GlyphCacheKey;
typedef struct _DirtyGlyph DirtyGlyph;
typedef struct _GskGLCachedGlyph GskGLCachedGlyph;
struct _DirtyGlyph
{
GlyphCacheKey *key;
GskGLCachedGlyph *value;
cairo_surface_t *surface;
};
typedef struct
{
GskGLImage *image;
int width, height;
int x, y, y0;
int num_glyphs;
GList *dirty_glyphs;
guint old_pixels;
DirtyGlyph pending_glyph;
} GskGLGlyphAtlas;
typedef struct
struct _GskGLCachedGlyph
{
GskGLGlyphAtlas *atlas;
@@ -43,8 +59,11 @@ typedef struct
int draw_width;
int draw_height;
float scale;
guint64 timestamp;
} GskGLCachedGlyph;
};
void gsk_gl_glyph_cache_init (GskGLGlyphCache *self,
GskRenderer *renderer,
+51
View File
@@ -0,0 +1,51 @@
#include <glib/gprintf.h>
#include "gskglnodesampleprivate.h"
#include "gskrendernodeprivate.h"
void
node_sample_init (NodeSample *self)
{
memset (self->nodes, 0, sizeof (self->nodes));
self->count = 0;
}
void
node_sample_reset (NodeSample *self)
{
node_sample_init (self);
}
void
node_sample_add (NodeSample *self,
GskRenderNode *node)
{
const guint node_type = gsk_render_node_get_node_type (node);
g_assert (node_type <= N_NODE_TYPES);
if (self->nodes[node_type].class_name == NULL)
self->nodes[node_type].class_name = node->node_class->type_name;
self->nodes[node_type].count ++;
self->count ++;
}
void
node_sample_print (const NodeSample *self,
const char *prefix)
{
guint i;
g_printf ("%s:\n", prefix);
for (i = 0; i < N_NODE_TYPES; i ++)
{
if (self->nodes[i].count > 0)
{
double p = (double)self->nodes[i].count / (double)self->count;
g_printf ("%s: %u (%.2f%%)\n", self->nodes[i].class_name, self->nodes[i].count, p * 100.0);
}
}
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef __GSK_GL_NODE_SAMPLE_PRIVATE_H__
#define __GSK_GL_NODE_SAMPLE_PRIVATE_H__
#include <glib.h>
#include "gskenums.h"
#include "gskrendernode.h"
/* TODO: We have no other way for this...? */
#define N_NODE_TYPES (GSK_DEBUG_NODE + 1)
typedef struct
{
struct {
const char *class_name;
guint count;
} nodes[N_NODE_TYPES];
guint count;
} NodeSample;
void node_sample_init (NodeSample *self);
void node_sample_reset (NodeSample *self);
void node_sample_add (NodeSample *self,
GskRenderNode *node);
void node_sample_print (const NodeSample *self,
const char *prefix);
#endif
+379 -163
View File
@@ -14,6 +14,7 @@
#include "gskglrenderopsprivate.h"
#include "gskcairoblurprivate.h"
#include "gskglshadowcacheprivate.h"
#include "gskglnodesampleprivate.h"
#include "gskprivate.h"
@@ -104,8 +105,19 @@ print_render_node_tree (GskRenderNode *root, int level)
g_print ("%*s Texture %p\n", level * INDENT, " ", gsk_texture_node_get_texture (root));
break;
case GSK_DEBUG_NODE:
g_print ("%*s Debug: %s\n", level * INDENT, " ", gsk_debug_node_get_message (root));
print_render_node_tree (gsk_debug_node_get_child (root), level + 1);
break;
case GSK_CLIP_NODE:
g_print ("%*s Clip (%f, %f, %f, %f):\n", level * INDENT, " ",
root->bounds.origin.x, root->bounds.origin.y, root->bounds.size.width, root->bounds.size.height);
print_render_node_tree (gsk_clip_node_get_child (root), level + 1);
break;
default:
g_print ("UNKNOWN: %u\n", type);
g_print ("%*s %s\n", level * INDENT, " ", root->node_class->type_name);
}
#undef INDENT
@@ -219,18 +231,40 @@ gsk_rounded_rect_shrink_to_minimum (GskRoundedRect *self)
MAX (self->corner[2].height, self->corner[3].height)) * 2);
}
static inline gboolean
node_supports_transform (GskRenderNode *node)
{
/* Some nodes can't handle non-trivial transforms without being
* rendered to a texture (e.g. rotated clips, etc.). Some however
* work just fine, mostly because they already draw their child
* to a texture and just render the texture manipulated in some
* way, think opacity or color matrix. */
const guint node_type = gsk_render_node_get_node_type (node);
switch (node_type)
{
case GSK_COLOR_NODE:
case GSK_OPACITY_NODE:
case GSK_COLOR_MATRIX_NODE:
case GSK_TEXTURE_NODE:
return TRUE;
default:
return FALSE;
}
return FALSE;
}
static void gsk_gl_renderer_setup_render_mode (GskGLRenderer *self);
static void add_offscreen_ops (GskGLRenderer *self,
RenderOpBuilder *builder,
float min_x,
float max_x,
float min_y,
float max_y,
GskRenderNode *child_node,
int *texture_id,
gboolean *is_offscreen,
gboolean force_offscreen,
gboolean reset_clip);
RenderOpBuilder *builder,
const graphene_rect_t *bounds,
GskRenderNode *child_node,
int *texture_id,
gboolean *is_offscreen,
gboolean force_offscreen,
gboolean reset_clip);
static void gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder);
@@ -248,7 +282,6 @@ struct _GskGLRenderer
union {
Program programs[GL_N_PROGRAMS];
struct {
Program blend_program;
Program blit_program;
Program color_program;
Program coloring_program;
@@ -289,6 +322,49 @@ struct _GskGLRendererClass
G_DEFINE_TYPE (GskGLRenderer, gsk_gl_renderer, GSK_TYPE_RENDERER)
static void G_GNUC_UNUSED
add_rect_ops (RenderOpBuilder *builder,
const graphene_rect_t *r)
{
const float min_x = r->origin.x;
const float min_y = r->origin.y;
const float max_x = min_x + r->size.width;
const float max_y = min_y + r->size.height;
ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
{ { 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 }, },
});
}
static void G_GNUC_UNUSED
add_rect_outline_ops (GskGLRenderer *self,
RenderOpBuilder *builder,
const graphene_rect_t *rect)
{
ops_set_program (builder, &self->color_program);
ops_set_color (builder, &(GdkRGBA) { 1, 0, 0, 1 });
add_rect_ops (builder,
&GRAPHENE_RECT_INIT (rect->origin.x, rect->origin.y,
1, rect->size.height));
add_rect_ops (builder,
&GRAPHENE_RECT_INIT (rect->origin.x, rect->origin.y,
rect->size.width, 1));
add_rect_ops (builder,
&GRAPHENE_RECT_INIT (rect->origin.x + rect->size.width - 1, rect->origin.y,
1, rect->size.height));
add_rect_ops (builder,
&GRAPHENE_RECT_INIT (rect->origin.x, rect->origin.y + rect->size.height - 1,
rect->size.width, 1));
}
static inline void
rounded_rect_to_floats (GskGLRenderer *self,
RenderOpBuilder *builder,
@@ -301,7 +377,7 @@ rounded_rect_to_floats (GskGLRenderer *self,
int i;
graphene_rect_t transformed_bounds;
graphene_matrix_transform_bounds (&builder->current_modelview, &rect->bounds, &transformed_bounds);
ops_transform_bounds_modelview (builder, &rect->bounds, &transformed_bounds);
outline[0] = transformed_bounds.origin.x;
outline[1] = transformed_bounds.origin.y;
@@ -420,7 +496,7 @@ render_text_node (GskGLRenderer *self,
text_scale);
/* e.g. whitespace */
if (glyph->draw_width <= 0 || glyph->draw_height <= 0)
if (glyph->draw_width <= 0 || glyph->draw_height <= 0 || glyph->scale <= 0)
goto next;
cx = (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
@@ -460,8 +536,8 @@ render_border_node (GskGLRenderer *self,
RenderOpBuilder *builder)
{
const float scale = ops_get_scale (builder);
const float min_x = node->bounds.origin.x;
const float min_y = node->bounds.origin.y;
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;
const GdkRGBA *colors = gsk_border_node_peek_colors (node);
@@ -578,8 +654,8 @@ render_border_node (GskGLRenderer *self,
/* Prepare outline */
outline = *rounded_outline;
graphene_matrix_transform_bounds (&builder->current_modelview,
&outline.bounds, &outline.bounds);
ops_transform_bounds_modelview (builder, &outline.bounds, &outline.bounds);
for (i = 0; i < 4; i ++)
{
outline.corner[i].width *= scale;
@@ -587,7 +663,8 @@ render_border_node (GskGLRenderer *self,
}
ops_set_program (builder, &self->border_program);
ops_set_border (builder, widths, &outline);
ops_set_border_width (builder, widths);
ops_set_border (builder, &outline);
for (i = 0; i < 4; i ++)
{
@@ -689,41 +766,12 @@ render_offset_node (GskGLRenderer *self,
RenderOpBuilder *builder)
{
GskRenderNode *child = gsk_offset_node_get_child (node);
const guint child_type = gsk_render_node_get_node_type (child);
const float dx = gsk_offset_node_get_x_offset (node);
const float dy = gsk_offset_node_get_y_offset (node);
/* TODO: We do this only for selected node type we know handle
* builder->dx/dy correctly. That should be "all nodes" eventually.
*/
switch (child_type)
{
case GSK_TEXT_NODE:
case GSK_TEXTURE_NODE:
case GSK_COLOR_NODE:
case GSK_COLOR_MATRIX_NODE:
{
ops_offset (builder, dx, dy);
gsk_gl_renderer_add_render_ops (self, child, builder);
ops_offset (builder, - dx, - dy);
}
break;
default:
{
graphene_matrix_t prev_mv;
graphene_matrix_t transform, transformed_mv;
graphene_matrix_init_translate (&transform,
&GRAPHENE_POINT3D_INIT(dx, dy, 1.0));
graphene_matrix_multiply (&transform, &builder->current_modelview, &transformed_mv);
prev_mv = ops_set_modelview (builder, &transformed_mv);
gsk_gl_renderer_add_render_ops (self, child, builder);
ops_set_modelview (builder, &prev_mv);
}
}
ops_offset (builder, dx, dy);
gsk_gl_renderer_add_render_ops (self, child, builder);
ops_offset (builder, - dx, - dy);
}
static inline void
@@ -731,17 +779,64 @@ render_transform_node (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder)
{
const float scale = ops_get_scale (builder);
GskRenderNode *child = gsk_transform_node_get_child (node);
graphene_matrix_t prev_mv;
graphene_matrix_t transform, transformed_mv;
graphene_matrix_init_from_matrix (&transform, gsk_transform_node_peek_transform (node));
graphene_matrix_multiply (&transform, &builder->current_modelview, &transformed_mv);
prev_mv = ops_set_modelview (builder, &transformed_mv);
graphene_matrix_multiply (&transform, builder->current_modelview, &transformed_mv);
graphene_matrix_translate (&transformed_mv,
&(graphene_point3d_t) { builder->dx * scale, builder->dy * scale, 0});
gsk_gl_renderer_add_render_ops (self, child, builder);
/* We just added the offset to the new modelview matrix, so the following
* cases dont' have to care about builder->dx/dy! */
ops_set_modelview (builder, &prev_mv);
ops_push_modelview (builder, &transformed_mv);
if (ops_modelview_is_simple (builder) ||
node_supports_transform (child))
{
const float dx = builder->dx;
const float dy = builder->dy;
builder->dx = 0;
builder->dy = 0;
gsk_gl_renderer_add_render_ops (self, child, builder);
builder->dx = dx;
builder->dy = dy;
}
else
{
const float min_x = node->bounds.origin.x;
const float min_y = node->bounds.origin.y;
const float max_x = min_x + node->bounds.size.width;
const float max_y = min_y + node->bounds.size.height;
const GskQuadVertex vertex_data[GL_N_VERTICES] = {
{ { 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 }, },
};
int texture_id;
gboolean is_offscreen;
/* For non-trivial transforms, we draw everything on a texture and then
* draw the texture transformed. */
/* TODO: We should compute a modelview containing only the "non-trivial"
* part (e.g. the rotation) and use that. We want to keep the scale
* for the texture.
*/
add_offscreen_ops (self, builder,
&node->bounds,
child,
&texture_id, &is_offscreen,
FALSE, TRUE);
ops_set_texture (builder, texture_id);
ops_set_program (builder, &self->blit_program);
ops_draw (builder, vertex_data);
}
ops_pop_modelview (builder);
}
static inline void
@@ -787,7 +882,11 @@ render_linear_gradient_node (GskGLRenderer *self,
op.op = OP_CHANGE_LINEAR_GRADIENT;
op.linear_gradient.n_color_stops = n_color_stops;
op.linear_gradient.start_point = *start;
op.linear_gradient.start_point.x += builder->dx;
op.linear_gradient.start_point.y += builder->dy;
op.linear_gradient.end_point = *end;
op.linear_gradient.end_point.x += builder->dx;
op.linear_gradient.end_point.y += builder->dy;
ops_add (builder, &op);
ops_draw (builder, vertex_data);
@@ -798,64 +897,98 @@ render_clip_node (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder)
{
GskRoundedRect prev_clip;
GskRenderNode *child = gsk_clip_node_get_child (node);
graphene_rect_t transformed_clip;
graphene_rect_t intersection;
GskRoundedRect child_clip;
transformed_clip = *gsk_clip_node_peek_clip (node);
graphene_matrix_transform_bounds (&builder->current_modelview, &transformed_clip, &transformed_clip);
ops_transform_bounds_modelview (builder, &transformed_clip, &transformed_clip);
graphene_rect_intersection (&transformed_clip,
&builder->current_clip.bounds,
&builder->current_clip->bounds,
&intersection);
gsk_rounded_rect_init_from_rect (&child_clip, &intersection, 0.0f);
prev_clip = ops_set_clip (builder, &child_clip);
ops_push_clip (builder, &child_clip);
gsk_gl_renderer_add_render_ops (self, child, builder);
ops_set_clip (builder, &prev_clip);
ops_pop_clip (builder);
}
static gboolean
gsk_rounded_rect_intersection (const GskRoundedRect *self,
const GskRoundedRect *other,
GskRoundedRect *out_intersection)
{
const graphene_rect_t *self_bounds = &self->bounds;
const graphene_rect_t *other_bounds = &other->bounds;
if (graphene_rect_contains_rect (self_bounds, other_bounds))
{
*out_intersection = *other;
return TRUE;
}
/* TODO: There are a few cases here that we can express using a single
* rounded rectangle, which are even interesting in every day usage.
* For example, a partially scrolled-away rounded rectangle
* might just work.
*/
return FALSE;
}
static inline void
render_rounded_clip_node (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder)
{
const float scale = ops_get_scale (builder);
const float min_x = node->bounds.origin.x;
const float min_y = node->bounds.origin.y;
const float max_x = min_x + node->bounds.size.width;
const float max_y = min_y + node->bounds.size.height;
GskRoundedRect child_clip = *gsk_rounded_clip_node_peek_clip (node);
GskRoundedRect transformed_clip;
GskRoundedRect prev_clip;
GskRenderNode *child = gsk_rounded_clip_node_get_child (node);
GskRoundedRect intersection;
gboolean need_offscreen;
int i;
transformed_clip = child_clip;
graphene_matrix_transform_bounds (&builder->current_modelview, &child_clip.bounds, &transformed_clip.bounds);
ops_transform_bounds_modelview (builder, &child_clip.bounds, &transformed_clip.bounds);
if (graphene_rect_contains_rect (&builder->current_clip.bounds,
&transformed_clip.bounds))
if (!ops_has_clip (builder))
{
intersection = transformed_clip;
need_offscreen = FALSE;
}
else
{
need_offscreen = !gsk_rounded_rect_intersection (builder->current_clip,
&transformed_clip,
&intersection);
}
if (!need_offscreen)
{
/* If they don't intersect at all, we can simply set
* the new clip and add the render ops */
for (i = 0; i < 4; i ++)
{
transformed_clip.corner[i].width *= scale;
transformed_clip.corner[i].height *= scale;
intersection.corner[i].width *= scale;
intersection.corner[i].height *= scale;
}
prev_clip = ops_set_clip (builder, &transformed_clip);
ops_push_clip (builder, &intersection);
gsk_gl_renderer_add_render_ops (self, child, builder);
ops_set_clip (builder, &prev_clip);
ops_pop_clip (builder);
}
else if (graphene_rect_intersection (&builder->current_clip.bounds,
&transformed_clip.bounds, NULL))
else
{
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;
graphene_matrix_t scale_matrix;
gboolean is_offscreen;
int texture_id;
@@ -876,12 +1009,12 @@ render_rounded_clip_node (GskGLRenderer *self,
child_clip.corner[i].height *= scale;
}
prev_clip = ops_set_clip (builder, &child_clip);
add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y,
ops_push_clip (builder, &child_clip);
add_offscreen_ops (self, builder, &node->bounds,
child,
&texture_id, &is_offscreen, TRUE, FALSE);
ops_pop_clip (builder);
ops_set_clip (builder, &prev_clip);
ops_set_program (builder, &self->blit_program);
ops_set_texture (builder, texture_id);
@@ -911,7 +1044,9 @@ render_color_matrix_node (GskGLRenderer *self,
int texture_id;
gboolean is_offscreen;
add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y,
/* Pass min_x/max_x/min_y/max_y without builder->dx/dy! */
add_offscreen_ops (self, builder,
&node->bounds,
gsk_color_matrix_node_get_child (node),
&texture_id, &is_offscreen, FALSE, TRUE);
@@ -948,16 +1083,23 @@ render_blur_node (GskGLRenderer *self,
RenderOpBuilder *builder,
const GskQuadVertex *vertex_data)
{
const float min_x = node->bounds.origin.x;
const float min_y = node->bounds.origin.y;
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;
int texture_id;
gboolean is_offscreen;
RenderOp op;
add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y,
/* TODO(perf): We're forcing the child offscreen even if it's a texture
* so the resulting offscreen texture is bigger by the gaussian blur factor
* (see gsk_blur_node_new), but we didn't have to do that if the blur
* shader could handle that situation. */
add_offscreen_ops (self, builder,
&node->bounds,
gsk_blur_node_get_child (node),
&texture_id, &is_offscreen, FALSE, TRUE);
&texture_id, &is_offscreen, TRUE, TRUE);
ops_set_program (builder, &self->blur_program);
op.op = OP_CHANGE_BLUR;
@@ -1063,15 +1205,14 @@ render_outset_shadow_node (GskGLRenderer *self,
const float spread = gsk_outset_shadow_node_get_spread (node);
const float dx = gsk_outset_shadow_node_get_dx (node);
const float dy = gsk_outset_shadow_node_get_dy (node);
const float min_x = outline->bounds.origin.x - spread - blur_extra / 2.0;
const float min_y = outline->bounds.origin.y - spread - blur_extra / 2.0;
const float min_x = builder->dx + outline->bounds.origin.x - spread - blur_extra / 2.0;
const float min_y = builder->dy + outline->bounds.origin.y - spread - blur_extra / 2.0;
const float max_x = min_x + outline->bounds.size.width + (spread + blur_extra/2.0) * 2;
const float max_y = min_y + outline->bounds.size.height + (spread + blur_extra/2.0) * 2;
float texture_width, texture_height;
RenderOp op;
graphene_matrix_t identity;
graphene_matrix_t prev_projection;
graphene_matrix_t prev_modelview;
graphene_rect_t prev_viewport;
graphene_matrix_t item_proj;
int blurred_texture_id;
@@ -1106,7 +1247,7 @@ render_outset_shadow_node (GskGLRenderer *self,
int texture_id, render_target;
int blurred_render_target;
int prev_render_target;
GskRoundedRect prev_clip, blit_clip;
GskRoundedRect blit_clip;
texture_id = gsk_gl_driver_create_texture (self->gl_driver, texture_width, texture_height);
gsk_gl_driver_bind_source_texture (self->gl_driver, texture_id);
@@ -1124,12 +1265,12 @@ render_outset_shadow_node (GskGLRenderer *self,
op.op = OP_CLEAR;
ops_add (builder, &op);
prev_projection = ops_set_projection (builder, &item_proj);
prev_modelview = ops_set_modelview (builder, &identity);
ops_push_modelview (builder, &identity);
prev_viewport = ops_set_viewport (builder, &GRAPHENE_RECT_INIT (0, 0, texture_width, texture_height));
/* Draw outline */
ops_set_program (builder, &self->color_program);
prev_clip = ops_set_clip (builder, &offset_outline);
ops_push_clip (builder, &offset_outline);
ops_set_color (builder, gsk_outset_shadow_node_peek_color (node));
ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
{ { 0, }, { 0, 1 }, },
@@ -1147,6 +1288,7 @@ render_outset_shadow_node (GskGLRenderer *self,
blurred_render_target = gsk_gl_driver_create_render_target (self->gl_driver, blurred_texture_id, TRUE, TRUE);
ops_set_render_target (builder, blurred_render_target);
ops_pop_clip (builder);
op.op = OP_CLEAR;
ops_add (builder, &op);
@@ -1160,7 +1302,7 @@ render_outset_shadow_node (GskGLRenderer *self,
op.blur.radius = blur_radius;
ops_add (builder, &op);
ops_set_clip (builder, &blit_clip);
ops_push_clip (builder, &blit_clip);
ops_set_texture (builder, texture_id);
ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
{ { 0, 0 }, { 0, 1 }, },
@@ -1173,9 +1315,9 @@ render_outset_shadow_node (GskGLRenderer *self,
});
ops_set_clip (builder, &prev_clip);
ops_pop_clip (builder);
ops_set_viewport (builder, &prev_viewport);
ops_set_modelview (builder, &prev_modelview);
ops_pop_modelview (builder);
ops_set_projection (builder, &prev_projection);
ops_set_render_target (builder, prev_render_target);
@@ -1459,11 +1601,6 @@ render_shadow_node (GskGLRenderer *self,
g_assert (shadow->radius <= 0);
min_x = shadow_child->bounds.origin.x;
min_y = shadow_child->bounds.origin.y;
max_x = min_x + shadow_child->bounds.size.width;
max_y = min_y + shadow_child->bounds.size.height;
if (gsk_render_node_get_node_type (shadow_child) == GSK_TEXT_NODE)
{
ops_offset (builder, dx, dy);
@@ -1472,9 +1609,14 @@ render_shadow_node (GskGLRenderer *self,
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,
min_x, max_x, min_y, max_y,
&shadow_child->bounds,
shadow_child, &texture_id, &is_offscreen, FALSE, TRUE);
ops_offset (builder, dx, dy);
@@ -1522,8 +1664,8 @@ render_cross_fade_node (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder)
{
const float min_x = node->bounds.origin.x;
const float min_y = node->bounds.origin.y;
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 *start_node = gsk_cross_fade_node_get_start_child (node);
@@ -1546,10 +1688,14 @@ render_cross_fade_node (GskGLRenderer *self,
/* TODO: We create 2 textures here as big as the cross-fade node, but both the
* start and the end node might be a lot smaller than that. */
add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y, start_node,
add_offscreen_ops (self, builder,
&node->bounds,
start_node,
&start_texture_id, &is_offscreen1, TRUE, TRUE);
add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y, end_node,
add_offscreen_ops (self, builder,
&node->bounds,
end_node,
&end_texture_id, &is_offscreen2, TRUE, TRUE);
ops_set_program (builder, &self->cross_fade_program);
@@ -1777,8 +1923,7 @@ apply_border_op (const Program *program,
float widths[4];
float heights[4];
int i;
OP_PRINT (" -> Border (%f, %f, %f, %f)",
op->border.widths[0], op->border.widths[1], op->border.widths[2], op->border.widths[3]);
OP_PRINT (" -> Border Outline");
outline[0] = o->bounds.origin.x;
outline[1] = o->bounds.origin.y;
@@ -1791,12 +1936,21 @@ apply_border_op (const Program *program,
heights[i] = o->corner[i].height;
}
glUniform4fv (program->border.widths_location, 1, op->border.widths);
glUniform4fv (program->border.outline_location, 1, outline);
glUniform4fv (program->border.corner_widths_location, 1, widths);
glUniform4fv (program->border.corner_heights_location, 1, heights);
}
static inline void
apply_border_width_op (const Program *program,
const RenderOp *op)
{
OP_PRINT (" -> Border width (%f, %f, %f, %f)",
op->border.widths[0], op->border.widths[1], op->border.widths[2], op->border.widths[3]);
glUniform4fv (program->border.widths_location, 1, op->border.widths);
}
static inline void
apply_border_color_op (const Program *program,
const RenderOp *op)
@@ -1847,21 +2001,19 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
int i;
static const struct {
const char *name;
const char *vs;
const char *fs;
} program_definitions[] = {
{ "blend", "blend.vs.glsl", "blend.fs.glsl" },
{ "blit", "blit.vs.glsl", "blit.fs.glsl" },
{ "color", "blit.vs.glsl", "color.fs.glsl" },
{ "coloring", "blit.vs.glsl", "coloring.fs.glsl" },
{ "color matrix", "blit.vs.glsl", "color_matrix.fs.glsl" },
{ "linear gradient", "blit.vs.glsl", "linear_gradient.fs.glsl" },
{ "blur", "blit.vs.glsl", "blur.fs.glsl" },
{ "inset shadow", "blit.vs.glsl", "inset_shadow.fs.glsl" },
{ "outset shadow", "blit.vs.glsl", "outset_shadow.fs.glsl" },
{ "unblurred outset shadow", "blit.vs.glsl", "unblurred_outset_shadow.fs.glsl" },
{ "border", "blit.vs.glsl", "border.fs.glsl" },
{ "cross fade", "blit.vs.glsl", "cross_fade.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" },
};
builder = gsk_shader_builder_new ();
@@ -1902,13 +2054,17 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
gsk_shader_builder_add_define (builder, "GSK_DEBUG", "1");
#endif
gsk_shader_builder_set_common_vertex_shader (builder, "blit.vs.glsl",
&shader_error);
g_assert_no_error (shader_error);
for (i = 0; i < GL_N_PROGRAMS; i ++)
{
Program *prog = &self->programs[i];
prog->index = i;
prog->id = gsk_shader_builder_create_program (builder,
program_definitions[i].vs,
program_definitions[i].fs,
&shader_error);
@@ -1917,7 +2073,7 @@ 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,
program_definitions[i].vs,
"blit.vs.glsl",
program_definitions[i].fs);
g_object_unref (builder);
@@ -2140,12 +2296,11 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
{
graphene_rect_t transformed_node_bounds;
graphene_matrix_transform_bounds (&builder->current_modelview,
&node->bounds,
&transformed_node_bounds);
graphene_rect_offset (&transformed_node_bounds, builder->dx, builder->dy);
ops_transform_bounds_modelview (builder,
&node->bounds,
&transformed_node_bounds);
if (!graphene_rect_intersection (&builder->current_clip.bounds,
if (!graphene_rect_intersection (&builder->current_clip->bounds,
&transformed_node_bounds, NULL))
return;
}
@@ -2254,30 +2409,29 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
}
static void
add_offscreen_ops (GskGLRenderer *self,
RenderOpBuilder *builder,
float min_x,
float max_x,
float min_y,
float max_y,
GskRenderNode *child_node,
int *texture_id,
gboolean *is_offscreen,
gboolean force_offscreen,
gboolean reset_clip)
add_offscreen_ops (GskGLRenderer *self,
RenderOpBuilder *builder,
const graphene_rect_t *bounds,
GskRenderNode *child_node,
int *texture_id_out,
gboolean *is_offscreen,
gboolean force_offscreen,
gboolean reset_clip)
{
const float scale = ops_get_scale (builder);
const float width = (max_x - min_x) * scale;
const float height = (max_y - min_y) * scale;
const float width = bounds->size.width * scale;
const float height = bounds->size.height * scale;
const float dx = builder->dx;
const float dy = builder->dy;
int render_target;
int prev_render_target;
RenderOp op;
graphene_matrix_t identity;
graphene_matrix_t prev_projection;
graphene_matrix_t prev_modelview;
graphene_rect_t prev_viewport;
graphene_matrix_t item_proj;
GskRoundedRect prev_clip;
float prev_opacity;
int texture_id = 0;
/* We need the child node as a texture. If it already is one, we don't need to draw
* it on a framebuffer of course. */
@@ -2288,22 +2442,37 @@ add_offscreen_ops (GskGLRenderer *self,
get_gl_scaling_filters (child_node, &gl_min_filter, &gl_mag_filter);
*texture_id = gsk_gl_driver_get_texture_for_texture (self->gl_driver,
texture,
gl_min_filter,
gl_mag_filter);
*texture_id_out = gsk_gl_driver_get_texture_for_texture (self->gl_driver,
texture,
gl_min_filter,
gl_mag_filter);
*is_offscreen = FALSE;
return;
}
*texture_id = gsk_gl_driver_create_texture (self->gl_driver, width, height);
gsk_gl_driver_bind_source_texture (self->gl_driver, *texture_id);
gsk_gl_driver_init_texture_empty (self->gl_driver, *texture_id);
render_target = gsk_gl_driver_create_render_target (self->gl_driver, *texture_id, TRUE, TRUE);
/* Check if we've already cached the drawn texture. */
{
const int cached_id = gsk_gl_driver_get_texture_for_pointer (self->gl_driver, child_node);
if (cached_id != 0)
{
*texture_id_out = cached_id;
/* We didn't render it offscreen, but hand out an offscreen texture id */
*is_offscreen = TRUE;
return;
}
}
texture_id = gsk_gl_driver_create_texture (self->gl_driver, width, height);
gsk_gl_driver_bind_source_texture (self->gl_driver, texture_id);
gsk_gl_driver_init_texture_empty (self->gl_driver, texture_id);
render_target = gsk_gl_driver_create_render_target (self->gl_driver, texture_id, TRUE, TRUE);
graphene_matrix_init_ortho (&item_proj,
min_x * scale, max_x * scale,
min_y * scale, max_y * scale,
bounds->origin.x * scale,
(bounds->origin.x + bounds->size.width) * scale,
bounds->origin.y * scale,
(bounds->origin.y + bounds->size.height) * scale,
ORTHO_NEAR_PLANE, ORTHO_FAR_PLANE);
graphene_matrix_scale (&item_proj, 1, -1, 1);
graphene_matrix_init_identity (&identity);
@@ -2314,27 +2483,39 @@ add_offscreen_ops (GskGLRenderer *self,
op.op = OP_CLEAR;
ops_add (builder, &op);
prev_projection = ops_set_projection (builder, &item_proj);
prev_modelview = ops_set_modelview (builder, &identity);
prev_viewport = ops_set_viewport (builder, &GRAPHENE_RECT_INIT (min_x * scale,
min_y * scale,
width, height));
ops_push_modelview (builder, &identity);
prev_viewport = ops_set_viewport (builder,
&GRAPHENE_RECT_INIT (bounds->origin.x * scale,
bounds->origin.y * scale,
width, height));
if (reset_clip)
prev_clip = ops_set_clip (builder,
&GSK_ROUNDED_RECT_INIT (min_x * scale,
min_y * scale,
width, height));
ops_push_clip (builder,
&GSK_ROUNDED_RECT_INIT (bounds->origin.x * scale,
bounds->origin.y * scale,
width, height));
builder->dx = 0;
builder->dy = 0;
prev_opacity = ops_set_opacity (builder, 1.0);
gsk_gl_renderer_add_render_ops (self, child_node, builder);
ops_set_opacity (builder, prev_opacity);
builder->dx = dx;
builder->dy = dy;
if (reset_clip)
ops_set_clip (builder, &prev_clip);
ops_pop_clip (builder);
ops_set_viewport (builder, &prev_viewport);
ops_set_modelview (builder, &prev_modelview);
ops_pop_modelview (builder);
ops_set_projection (builder, &prev_projection);
ops_set_render_target (builder, prev_render_target);
*is_offscreen = TRUE;
*texture_id_out = texture_id;
gsk_gl_driver_set_texture_for_pointer (self->gl_driver, child_node, texture_id);
}
static void
@@ -2481,6 +2662,10 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
apply_border_op (program, op);
break;
case OP_CHANGE_BORDER_WIDTH:
apply_border_width_op (program, op);
break;
case OP_CHANGE_UNBLURRED_OUTSET_SHADOW:
apply_unblurred_outset_shadow_op (program, op);
break;
@@ -2491,6 +2676,10 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
glDrawArrays (GL_TRIANGLES, op->draw.vao_offset, op->draw.vao_size);
break;
case OP_DUMP_FRAMEBUFFER:
dump_framebuffer (op->dump.filename, op->dump.width, op->dump.height);
break;
default:
g_warn_if_reached ();
}
@@ -2548,11 +2737,35 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
memset (&render_op_builder, 0, sizeof (render_op_builder));
render_op_builder.renderer = self;
render_op_builder.current_projection = projection;
render_op_builder.current_modelview = modelview;
render_op_builder.current_viewport = *viewport;
render_op_builder.current_opacity = 1.0f;
render_op_builder.render_ops = self->render_ops;
gsk_rounded_rect_init_from_rect (&render_op_builder.current_clip, viewport, 0.0f);
ops_push_modelview (&render_op_builder, &modelview);
/* Initial clip is self->render_region! */
if (self->render_region != NULL)
{
GskRoundedRect transformed_render_region = { 0, };
cairo_rectangle_int_t render_extents;
cairo_region_get_extents (self->render_region, &render_extents);
ops_transform_bounds_modelview (&render_op_builder,
&GRAPHENE_RECT_INIT (render_extents.x,
render_extents.y,
render_extents.width,
render_extents.height),
&transformed_render_region.bounds);
ops_push_clip (&render_op_builder, &transformed_render_region);
}
else
{
ops_push_clip (&render_op_builder,
&GSK_ROUNDED_RECT_INIT (viewport->origin.x,
viewport->origin.y,
viewport->size.width,
viewport->size.height));
}
if (fbo_id != 0)
ops_set_render_target (&render_op_builder, fbo_id);
@@ -2561,6 +2774,9 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
/* We correctly reset the state everywhere */
g_assert_cmpint (render_op_builder.current_render_target, ==, fbo_id);
ops_pop_modelview (&render_op_builder);
ops_pop_clip (&render_op_builder);
ops_finish (&render_op_builder);
/*g_message ("Ops: %u", self->render_ops->len);*/
+312 -60
View File
@@ -1,5 +1,22 @@
#include "gskglrenderopsprivate.h"
static inline gboolean
rect_equal (const graphene_rect_t *a,
const graphene_rect_t *b)
{
return memcmp (a, b, sizeof (graphene_rect_t)) == 0;
}
void
ops_finish (RenderOpBuilder *builder)
{
if (builder->mv_stack)
g_array_free (builder->mv_stack, TRUE);
if (builder->clip_stack)
g_array_free (builder->clip_stack, TRUE);
}
static inline void
rgba_to_float (const GdkRGBA *c,
float *f)
@@ -10,13 +27,134 @@ rgba_to_float (const GdkRGBA *c,
f[3] = c->alpha;
}
/* Debugging only! */
void
ops_dump_framebuffer (RenderOpBuilder *builder,
const char *filename,
int width,
int height)
{
RenderOp op;
op.op = OP_DUMP_FRAMEBUFFER;
op.dump.filename = g_strdup (filename);
op.dump.width = width;
op.dump.height = height;
g_array_append_val (builder->render_ops, op);
}
float
ops_get_scale (const RenderOpBuilder *builder)
{
const graphene_matrix_t *mv = &builder->current_modelview;
const MatrixStackEntry *head;
return MAX (graphene_matrix_get_x_scale (mv),
graphene_matrix_get_y_scale (mv));
g_assert (builder->mv_stack != NULL);
g_assert (builder->mv_stack->len >= 1);
head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
/* TODO: Use two separate values */
return MAX (head->metadata.scale_x,
head->metadata.scale_y);
}
static void
extract_matrix_metadata (const graphene_matrix_t *m,
OpsMatrixMetadata *md)
{
graphene_vec3_t col1;
graphene_vec3_t col2;
/* Translate */
md->translate_x = graphene_matrix_get_value (m, 3, 0);
md->translate_y = graphene_matrix_get_value (m, 3, 1);
/* Scale */
graphene_vec3_init (&col1,
graphene_matrix_get_value (m, 0, 0),
graphene_matrix_get_value (m, 1, 0),
graphene_matrix_get_value (m, 2, 0));
graphene_vec3_init (&col2,
graphene_matrix_get_value (m, 0, 1),
graphene_matrix_get_value (m, 1, 1),
graphene_matrix_get_value (m, 2, 1));
md->scale_x = graphene_vec3_length (&col1);
md->scale_y = graphene_vec3_length (&col2);
/* A simple matrix (in our case) is one that doesn't do anything but scale
* and/or translate.
*
* For orher matrices, we fall back to offscreen drawing.
*/
md->simple = TRUE;
{
static const guchar check_zero[4][4] = {
{ 0, 1, 0, 1 }, /* If any of the values marked as '1' here is non-zero, */
{ 1, 0, 0, 1 }, /* We have to resort to offscreen drawing later on. */
{ 1, 1, 0, 1 },
{ 0, 0, 0, 0 },
};
int x, y;
for (x = 0; x < 4; x ++)
for (y = 0; y < 4; y ++)
if (check_zero[y][x] &&
graphene_matrix_get_value (m, y, x) != 0.0f)
{
md->simple = FALSE;
goto out;
}
}
out:
md->only_translation = (md->simple && md->scale_x == 1 && md->scale_y == 1);
}
void
ops_transform_bounds_modelview (const RenderOpBuilder *builder,
const graphene_rect_t *src,
graphene_rect_t *dst)
{
const float scale = ops_get_scale (builder);
const MatrixStackEntry *head;
g_assert (builder->mv_stack != NULL);
g_assert (builder->mv_stack->len >= 1);
head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
if (head->metadata.only_translation)
{
*dst = *src;
graphene_rect_offset (dst,
head->metadata.translate_x,
head->metadata.translate_y);
}
else
{
graphene_matrix_transform_bounds (builder->current_modelview,
src,
dst);
}
graphene_rect_offset (dst, builder->dx * scale, builder->dy * scale);
}
gboolean
ops_modelview_is_simple (const RenderOpBuilder *builder)
{
const MatrixStackEntry *head;
g_assert (builder->mv_stack != NULL);
g_assert (builder->mv_stack->len >= 1);
head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
return head->metadata.simple;
}
void
@@ -29,6 +167,7 @@ ops_set_program (RenderOpBuilder *builder,
static const graphene_matrix_t empty_matrix;
static const graphene_rect_t empty_rect;
RenderOp op;
ProgramState *program_state;
if (builder->current_program == program)
return;
@@ -38,58 +177,61 @@ ops_set_program (RenderOpBuilder *builder,
g_array_append_val (builder->render_ops, op);
builder->current_program = program;
program_state = &builder->program_state[program->index];
/* If the projection is not yet set for this program, we use the current one. */
if (memcmp (&empty_matrix, &builder->program_state[program->index].projection, sizeof (graphene_matrix_t)) == 0 ||
memcmp (&builder->current_projection, &builder->program_state[program->index].projection, sizeof (graphene_matrix_t)) != 0)
if (memcmp (&empty_matrix, &program_state->projection, sizeof (graphene_matrix_t)) == 0 ||
memcmp (&builder->current_projection, &program_state->projection, sizeof (graphene_matrix_t)) != 0)
{
op.op = OP_CHANGE_PROJECTION;
op.projection = builder->current_projection;
g_array_append_val (builder->render_ops, op);
builder->program_state[program->index].projection = builder->current_projection;
program_state->projection = builder->current_projection;
}
if (memcmp (&empty_matrix, &builder->program_state[program->index].modelview, sizeof (graphene_matrix_t)) == 0 ||
memcmp (&builder->current_modelview, &builder->program_state[program->index].modelview, sizeof (graphene_matrix_t)) != 0)
if (memcmp (&empty_matrix, &program_state->modelview, sizeof (graphene_matrix_t)) == 0 ||
memcmp (builder->current_modelview, &program_state->modelview, sizeof (graphene_matrix_t)) != 0)
{
op.op = OP_CHANGE_MODELVIEW;
op.modelview = builder->current_modelview;
op.modelview = *builder->current_modelview;
g_array_append_val (builder->render_ops, op);
builder->program_state[program->index].modelview = builder->current_modelview;
program_state->modelview = *builder->current_modelview;
}
if (memcmp (&empty_rect, &builder->program_state[program->index].viewport, sizeof (graphene_rect_t)) == 0 ||
memcmp (&builder->current_viewport, &builder->program_state[program->index].viewport, sizeof (graphene_rect_t)) != 0)
if (rect_equal (&empty_rect, &program_state->viewport) ||
!rect_equal (&builder->current_viewport, &program_state->viewport))
{
op.op = OP_CHANGE_VIEWPORT;
op.viewport = builder->current_viewport;
g_array_append_val (builder->render_ops, op);
builder->program_state[program->index].viewport = builder->current_viewport;
program_state->viewport = builder->current_viewport;
}
if (memcmp (&empty_clip, &builder->program_state[program->index].clip, sizeof (GskRoundedRect)) == 0 ||
memcmp (&builder->current_clip, &builder->program_state[program->index].clip, sizeof (GskRoundedRect)) != 0)
if (memcmp (&empty_clip, &program_state->clip, sizeof (GskRoundedRect)) == 0 ||
memcmp (&builder->current_clip, &program_state->clip, sizeof (GskRoundedRect)) != 0)
{
op.op = OP_CHANGE_CLIP;
op.clip = builder->current_clip;
op.clip = *builder->current_clip;
g_array_append_val (builder->render_ops, op);
builder->program_state[program->index].clip = builder->current_clip;
program_state->clip = *builder->current_clip;
}
if (builder->program_state[program->index].opacity != builder->current_opacity)
if (program_state->opacity != builder->current_opacity)
{
op.op = OP_CHANGE_OPACITY;
op.opacity = builder->current_opacity;
g_array_append_val (builder->render_ops, op);
builder->program_state[program->index].opacity = builder->current_opacity;
program_state->opacity = builder->current_opacity;
}
builder->current_program_state = &builder->program_state[program->index];
}
GskRoundedRect
static void
ops_set_clip (RenderOpBuilder *builder,
const GskRoundedRect *clip)
{
RenderOp *last_op;
GskRoundedRect prev_clip;
if (builder->render_ops->len > 0)
{
@@ -110,25 +252,62 @@ ops_set_clip (RenderOpBuilder *builder,
}
if (builder->current_program != NULL)
builder->program_state[builder->current_program->index].clip = *clip;
prev_clip = builder->current_clip;
builder->current_clip = *clip;
return prev_clip;
builder->current_program_state->clip = *clip;
}
graphene_matrix_t
void
ops_push_clip (RenderOpBuilder *self,
const GskRoundedRect *clip)
{
if (G_UNLIKELY (self->clip_stack == NULL))
self->clip_stack = g_array_new (FALSE, TRUE, sizeof (GskRoundedRect));
g_assert (self->clip_stack != NULL);
g_array_append_val (self->clip_stack, *clip);
self->current_clip = &g_array_index (self->clip_stack, GskRoundedRect, self->clip_stack->len - 1);
ops_set_clip (self, clip);
}
void
ops_pop_clip (RenderOpBuilder *self)
{
const GskRoundedRect *head;
g_assert (self->clip_stack);
g_assert (self->clip_stack->len >= 1);
self->clip_stack->len --;
head = &g_array_index (self->clip_stack, GskRoundedRect, self->clip_stack->len - 1);
if (self->clip_stack->len >= 1)
{
self->current_clip = head;
ops_set_clip (self, head);
}
else
{
self->current_clip = NULL;
}
}
gboolean
ops_has_clip (RenderOpBuilder *self)
{
return self->clip_stack != NULL &&
self->clip_stack->len > 1;
}
static void
ops_set_modelview (RenderOpBuilder *builder,
const graphene_matrix_t *modelview)
{
RenderOp op;
graphene_matrix_t prev_mv;
if (builder->current_program &&
memcmp (&builder->program_state[builder->current_program->index].modelview, modelview,
memcmp (&builder->current_program_state->modelview, modelview,
sizeof (graphene_matrix_t)) == 0)
return *modelview;
return;
if (builder->render_ops->len > 0)
{
@@ -152,12 +331,52 @@ ops_set_modelview (RenderOpBuilder *builder,
}
if (builder->current_program != NULL)
builder->program_state[builder->current_program->index].modelview = *modelview;
builder->current_program_state->modelview = *modelview;
}
prev_mv = builder->current_modelview;
builder->current_modelview = *modelview;
void
ops_push_modelview (RenderOpBuilder *builder,
const graphene_matrix_t *mv)
{
MatrixStackEntry *entry;
return prev_mv;
if (G_UNLIKELY (builder->mv_stack == NULL))
builder->mv_stack = g_array_new (FALSE, TRUE, sizeof (MatrixStackEntry));
g_assert (builder->mv_stack != NULL);
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->matrix = *mv;
extract_matrix_metadata (mv, &entry->metadata);
builder->current_modelview = &entry->matrix;
ops_set_modelview (builder, mv);
}
void
ops_pop_modelview (RenderOpBuilder *builder)
{
const graphene_matrix_t *m;
const MatrixStackEntry *head;
g_assert (builder->mv_stack);
g_assert (builder->mv_stack->len >= 1);
builder->mv_stack->len --;
head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
m = &head->matrix;
if (builder->mv_stack->len >= 1)
{
builder->current_modelview = m;
ops_set_modelview (builder, m);
}
else
{
builder->current_modelview = NULL;
}
}
graphene_matrix_t
@@ -189,7 +408,7 @@ ops_set_projection (RenderOpBuilder *builder,
}
if (builder->current_program != NULL)
builder->program_state[builder->current_program->index].projection = *projection;
builder->current_program_state->projection = *projection;
prev_mv = builder->current_projection;
builder->current_projection = *projection;
@@ -204,12 +423,16 @@ ops_set_viewport (RenderOpBuilder *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;
op.op = OP_CHANGE_VIEWPORT;
op.viewport = *viewport;
g_array_append_val (builder->render_ops, op);
if (builder->current_program != NULL)
builder->program_state[builder->current_program->index].viewport = *viewport;
builder->current_program_state->viewport = *viewport;
prev_viewport = builder->current_viewport;
builder->current_viewport = *viewport;
@@ -243,9 +466,28 @@ ops_set_render_target (RenderOpBuilder *builder,
return render_target_id;
prev_render_target = builder->current_render_target;
op.op = OP_CHANGE_RENDER_TARGET;
op.render_target_id = render_target_id;
g_array_append_val (builder->render_ops, op);
if (builder->render_ops->len > 0)
{
RenderOp *last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
if (last_op->op == OP_CHANGE_RENDER_TARGET)
{
last_op->render_target_id = render_target_id;
}
else
{
op.op = OP_CHANGE_RENDER_TARGET;
op.render_target_id = render_target_id;
g_array_append_val (builder->render_ops, op);
}
}
else
{
op.op = OP_CHANGE_RENDER_TARGET;
op.render_target_id = render_target_id;
g_array_append_val (builder->render_ops, op);
}
builder->current_render_target = render_target_id;
return prev_render_target;
@@ -288,7 +530,7 @@ ops_set_opacity (RenderOpBuilder *builder,
builder->current_opacity = opacity;
if (builder->current_program != NULL)
builder->program_state[builder->current_program->index].opacity = opacity;
builder->current_program_state->opacity = opacity;
return prev_opacity;
}
@@ -299,10 +541,10 @@ ops_set_color (RenderOpBuilder *builder,
{
RenderOp op;
if (gdk_rgba_equal (color, &builder->program_state[builder->current_program->index].color))
if (gdk_rgba_equal (color, &builder->current_program_state->color))
return;
builder->program_state[builder->current_program->index].color = *color;
builder->current_program_state->color = *color;
op.op = OP_CHANGE_COLOR;
op.color = *color;
@@ -317,15 +559,15 @@ ops_set_color_matrix (RenderOpBuilder *builder,
RenderOp op;
if (memcmp (matrix,
&builder->program_state[builder->current_program->index].color_matrix.matrix,
&builder->current_program_state->color_matrix.matrix,
sizeof (graphene_matrix_t)) == 0 &&
memcmp (offset,
&builder->program_state[builder->current_program->index].color_matrix.offset,
&builder->current_program_state->color_matrix.offset,
sizeof (graphene_vec4_t)) == 0)
return;
builder->program_state[builder->current_program->index].color_matrix.matrix = *matrix;
builder->program_state[builder->current_program->index].color_matrix.offset = *offset;
builder->current_program_state->color_matrix.matrix = *matrix;
builder->current_program_state->color_matrix.offset = *offset;
op.op = OP_CHANGE_COLOR_MATRIX;
op.color_matrix.matrix = *matrix;
@@ -335,30 +577,40 @@ ops_set_color_matrix (RenderOpBuilder *builder,
void
ops_set_border (RenderOpBuilder *builder,
const float *widths,
const GskRoundedRect *outline)
{
RenderOp op;
/* TODO: Assert that current_program == border program? */
if (memcmp (&builder->program_state[builder->current_program->index].border.widths,
widths, sizeof (float) * 4) == 0 &&
memcmp (&builder->program_state[builder->current_program->index].border.outline,
if (memcmp (&builder->current_program_state->border.outline,
outline, sizeof (GskRoundedRect)) == 0)
return;
memcpy (&builder->program_state[builder->current_program->index].border.widths,
widths, sizeof (float) * 4);
builder->program_state[builder->current_program->index].border.outline = *outline;
builder->current_program_state->border.outline = *outline;
op.op = OP_CHANGE_BORDER;
op.border.outline = *outline;
g_array_append_val (builder->render_ops, op);
}
void
ops_set_border_width (RenderOpBuilder *builder,
const float *widths)
{
RenderOp op;
if (memcmp (builder->current_program_state->border.widths,
widths, sizeof (float) * 4) == 0)
return;
memcpy (&builder->current_program_state->border.widths,
widths, sizeof (float) * 4);
op.op = OP_CHANGE_BORDER_WIDTH;
op.border.widths[0] = widths[0];
op.border.widths[1] = widths[1];
op.border.widths[2] = widths[2];
op.border.widths[3] = widths[3];
op.border.outline = *outline;
g_array_append_val (builder->render_ops, op);
}
@@ -370,11 +622,11 @@ ops_set_border_color (RenderOpBuilder *builder,
op.op = OP_CHANGE_BORDER_COLOR;
rgba_to_float (color, op.border.color);
if (memcmp (&op.border.color, &builder->program_state[builder->current_program->index].border.color,
if (memcmp (&op.border.color, &builder->current_program_state->border.color,
sizeof (float) * 4) == 0)
return;
rgba_to_float (color, builder->program_state[builder->current_program->index].border.color);
rgba_to_float (color, builder->current_program_state->border.color);
g_array_append_val (builder->render_ops, op);
}
+82 -33
View File
@@ -10,7 +10,26 @@
#include "gskglrendererprivate.h"
#define GL_N_VERTICES 6
#define GL_N_PROGRAMS 12
#define GL_N_PROGRAMS 11
typedef struct
{
float translate_x;
float translate_y;
float scale_x;
float scale_y;
guint simple : 1;
guint only_translation : 1;
} OpsMatrixMetadata;
typedef struct
{
graphene_matrix_t matrix;
OpsMatrixMetadata metadata;
} MatrixStackEntry;
enum {
OP_NONE,
@@ -31,10 +50,12 @@ enum {
OP_CHANGE_OUTSET_SHADOW = 15,
OP_CHANGE_BORDER = 16,
OP_CHANGE_BORDER_COLOR = 17,
OP_CHANGE_CROSS_FADE = 18,
OP_CHANGE_UNBLURRED_OUTSET_SHADOW = 19,
OP_CLEAR = 20,
OP_DRAW = 21,
OP_CHANGE_BORDER_WIDTH = 18,
OP_CHANGE_CROSS_FADE = 19,
OP_CHANGE_UNBLURRED_OUTSET_SHADOW = 20,
OP_CLEAR = 21,
OP_DRAW = 22,
OP_DUMP_FRAMEBUFFER = 23,
};
typedef struct
@@ -188,40 +209,46 @@ typedef struct
float progress;
int source2;
} cross_fade;
struct {
char *filename;
int width;
int height;
} dump;
};
} RenderOp;
typedef struct
{
/* Per-Program State */
struct {
GskRoundedRect clip;
graphene_matrix_t modelview;
graphene_matrix_t projection;
int source_texture;
graphene_rect_t viewport;
float opacity;
/* Per-program state */
union {
GdkRGBA color;
struct {
graphene_matrix_t matrix;
graphene_vec4_t offset;
} color_matrix;
struct {
float widths[4];
float color[4];
GskRoundedRect outline;
} border;
};
} program_state[GL_N_PROGRAMS];
GskRoundedRect clip;
graphene_matrix_t modelview;
graphene_matrix_t projection;
int source_texture;
graphene_rect_t viewport;
float opacity;
/* Per-program state */
union {
GdkRGBA color;
struct {
graphene_matrix_t matrix;
graphene_vec4_t offset;
} color_matrix;
struct {
float widths[4];
float color[4];
GskRoundedRect outline;
} border;
};
} ProgramState;
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;
GskRoundedRect current_clip;
graphene_matrix_t current_modelview;
graphene_matrix_t current_projection;
graphene_rect_t current_viewport;
float current_opacity;
@@ -231,20 +258,41 @@ typedef struct
GArray *render_ops;
GskGLRenderer *renderer;
/* Stack of modelview matrices */
GArray *mv_stack;
/* Pointer into mv_stack */
const graphene_matrix_t *current_modelview;
/* Same thing */
GArray *clip_stack;
const GskRoundedRect *current_clip;
} RenderOpBuilder;
void ops_dump_framebuffer (RenderOpBuilder *builder,
const char *filename,
int width,
int height);
void ops_finish (RenderOpBuilder *builder);
void ops_push_modelview (RenderOpBuilder *builder,
const graphene_matrix_t *mv);
void ops_pop_modelview (RenderOpBuilder *builder);
gboolean ops_modelview_is_simple (const RenderOpBuilder *builder);
float ops_get_scale (const RenderOpBuilder *builder);
void ops_set_program (RenderOpBuilder *builder,
const Program *program);
GskRoundedRect ops_set_clip (RenderOpBuilder *builder,
void ops_push_clip (RenderOpBuilder *builder,
const GskRoundedRect *clip);
void ops_pop_clip (RenderOpBuilder *builder);
gboolean ops_has_clip (RenderOpBuilder *builder);
graphene_matrix_t ops_set_modelview (RenderOpBuilder *builder,
const graphene_matrix_t *modelview);
void ops_transform_bounds_modelview (const RenderOpBuilder *builder,
const graphene_rect_t *src,
graphene_rect_t *dst);
graphene_matrix_t ops_set_projection (RenderOpBuilder *builder,
const graphene_matrix_t *projection);
@@ -268,8 +316,9 @@ void ops_set_color_matrix (RenderOpBuilder *builder,
const graphene_vec4_t *offset);
void ops_set_border (RenderOpBuilder *builder,
const float *widths,
const GskRoundedRect *outline);
void ops_set_border_width (RenderOpBuilder *builder,
const float *widths);
void ops_set_border_color (RenderOpBuilder *builder,
const GdkRGBA *color);
+29 -11
View File
@@ -15,6 +15,9 @@ struct _GskShaderBuilder
char *vertex_preamble;
char *fragment_preamble;
int common_vertex_shader_id;
int version;
GPtrArray *defines;
@@ -37,6 +40,9 @@ gsk_shader_builder_finalize (GObject *gobject)
g_clear_pointer (&self->defines, g_ptr_array_unref);
if (self->common_vertex_shader_id > 0)
glDeleteShader (self->common_vertex_shader_id);
G_OBJECT_CLASS (gsk_shader_builder_parent_class)->finalize (gobject);
}
@@ -230,27 +236,39 @@ gsk_shader_builder_compile_shader (GskShaderBuilder *builder,
return shader_id;
}
void
gsk_shader_builder_set_common_vertex_shader (GskShaderBuilder *self,
const char *vertex_shader,
GError **error)
{
int shader_id;
shader_id = gsk_shader_builder_compile_shader (self,
GL_VERTEX_SHADER,
self->vertex_preamble,
vertex_shader,
error);
g_assert (shader_id > 0);
self->common_vertex_shader_id = shader_id;
}
int
gsk_shader_builder_create_program (GskShaderBuilder *builder,
const char *vertex_shader,
const char *fragment_shader,
GError **error)
{
int vertex_id, fragment_id;
int vertex_id;
int fragment_id;
int program_id;
int status;
g_return_val_if_fail (GSK_IS_SHADER_BUILDER (builder), -1);
g_return_val_if_fail (vertex_shader != NULL, -1);
g_return_val_if_fail (fragment_shader != NULL, -1);
g_return_val_if_fail (builder->common_vertex_shader_id != 0, -1);
vertex_id = gsk_shader_builder_compile_shader (builder, GL_VERTEX_SHADER,
builder->vertex_preamble,
vertex_shader,
error);
if (vertex_id < 0)
return -1;
vertex_id = builder->common_vertex_shader_id;
fragment_id = gsk_shader_builder_compile_shader (builder, GL_FRAGMENT_SHADER,
builder->fragment_preamble,
fragment_shader,
@@ -290,8 +308,8 @@ gsk_shader_builder_create_program (GskShaderBuilder *builder,
out:
if (vertex_id > 0)
{
/* We delete the common vertex shader when destroying the shader builder */
glDetachShader (program_id, vertex_id);
glDeleteShader (vertex_id);
}
if (fragment_id > 0)
+4 -1
View File
@@ -25,8 +25,11 @@ void gsk_shader_builder_add_define (GskShad
const char *define_name,
const char *define_value);
void gsk_shader_builder_set_common_vertex_shader (GskShaderBuilder *self,
const char *vertex_shader,
GError **error);
int gsk_shader_builder_create_program (GskShaderBuilder *builder,
const char *vertex_shader,
const char *fragment_shader,
GError **error);
+1 -2
View File
@@ -1,6 +1,4 @@
gsk_private_gl_shaders = [
'resources/glsl/blend.fs.glsl',
'resources/glsl/blend.vs.glsl',
'resources/glsl/blit.fs.glsl',
'resources/glsl/blit.vs.glsl',
'resources/glsl/color.fs.glsl',
@@ -43,6 +41,7 @@ gsk_private_sources = files([
'gl/gskgldriver.c',
'gl/gskglrenderops.c',
'gl/gskglshadowcache.c',
'gl/gskglnodesample.c',
])
gsk_public_headers = files([
-61
View File
@@ -1,61 +0,0 @@
vec3 BlendMultiply(vec3 Cb, vec3 Cs) {
return Cb * Cs;
}
vec3 BlendScreen(vec3 Cb, vec3 Cs) {
return Cb + Cs - (Cb * Cs);
}
vec3 BlendHardLight(vec3 Cb, vec3 Cs) {
vec3 m = BlendMultiply(Cb, 2.0 * Cs);
vec3 s = BlendScreen(Cb, 2.0 * Cs - 1.0);
vec3 edge = vec3(0.5, 0.5, 0.5);
/* Use mix() and step() to avoid a branch */
return mix(m, s, step(edge, Cs));
}
vec3 BlendOverlay(vec3 Cb, vec3 Cs) {
return BlendHardLight(Cs, Cb);
}
vec3 BlendDarken(vec3 Cb, vec3 Cs) {
return min(Cb, Cs);
}
vec3 BlendLighten(vec3 Cb, vec3 Cs) {
return max(Cb, Cs);
}
void main() {
vec4 Cs = Texture(u_source, vUv);
vec4 Cb = Texture(u_mask, vUv);
vec3 res;
if (uBlendMode == 0) {
res = Cs.xyz;
}
else if (uBlendMode == 1) {
res = BlendMultiply(Cb.xyz, Cs.xyz);
}
else if (uBlendMode == 2) {
res = BlendScreen(Cb.xyz, Cs.xyz);
}
else if (uBlendMode == 3) {
res = BlendOverlay(Cb.xyz, Cs.xyz);
}
else if (uBlendMode == 4) {
res = BlendDarken(Cb.xyz, Cs.xyz);
}
else if (uBlendMode == 5) {
res = BlendLighten(Cb.xyz, Cs.xyz);
}
else if (uBlendMode == 8) {
res = BlendHardLight(Cb.xyz, Cs.xyz);
}
else {
// Use red for debugging missing blend modes
res = vec3(1.0, 0.0, 0.0);
}
setOutputColor(vec4(res, Cs.a) * u_alpha);
}
-5
View File
@@ -1,5 +0,0 @@
void main() {
gl_Position = u_modelview * u_projection * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
+3 -3
View File
@@ -24,7 +24,7 @@ developers, including those developing proprietary software, without
any license fees or royalties.</description>
<homepage rdf:resource="http://www.gtk.org/" />
<license rdf:resource="http://usefulinc.com/doap/licenses/lgpl" />
<bug-database rdf:resource="http://bugzilla.gnome.org/enter_bug.cgi?product=gtk%2B" />
<bug-database rdf:resource="https://gitlab.gnome.org/GNOME/gtk/issues/" />
<download-page rdf:resource="http://download.gnome.org/sources/gtk+/" />
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gtk-list" />
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list" />
@@ -39,8 +39,8 @@ any license fees or royalties.</description>
<repository>
<GitRepository>
<browse rdf:resource="http://git.gnome.org/browse/gtk+/"/>
<location rdf:resource="git://git.gnome.org/gtk+"/>
<browse rdf:resource="https://gitlab.gnome.org/GNOME/gtk/"/>
<location rdf:resource="https://gitlab.gnome.org/GNOME/gtk.git"/>
</GitRepository>
</repository>
+87 -1
View File
@@ -46,11 +46,13 @@ static const struct {
static GtkCellRendererState gtk_cell_accessible_get_state (GtkCellAccessible *cell);
static void atk_action_interface_init (AtkActionIface *iface);
static void atk_component_interface_init (AtkComponentIface *iface);
static void atk_table_cell_interface_init (AtkTableCellIface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkCellAccessible, gtk_cell_accessible, GTK_TYPE_ACCESSIBLE,
G_ADD_PRIVATE (GtkCellAccessible)
G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init)
G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, atk_component_interface_init))
G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, atk_component_interface_init)
G_IMPLEMENT_INTERFACE (ATK_TYPE_TABLE_CELL, atk_table_cell_interface_init))
static gint
gtk_cell_accessible_get_index_in_parent (AtkObject *obj)
@@ -366,6 +368,90 @@ atk_component_interface_init (AtkComponentIface *iface)
iface->grab_focus = gtk_cell_accessible_grab_focus;
}
static int
gtk_cell_accessible_get_column_span (AtkTableCell *table_cell)
{
return 1;
}
static GPtrArray *
gtk_cell_accessible_get_column_header_cells (AtkTableCell *table_cell)
{
GtkCellAccessible *cell;
AtkObject *parent;
cell = GTK_CELL_ACCESSIBLE (table_cell);
parent = gtk_widget_get_accessible (gtk_accessible_get_widget (GTK_ACCESSIBLE (cell)));
return gtk_cell_accessible_parent_get_column_header_cells (GTK_CELL_ACCESSIBLE_PARENT (parent),
cell);
}
static gboolean
gtk_cell_accessible_get_position (AtkTableCell *table_cell,
gint *row,
gint *column)
{
GtkCellAccessible *cell;
AtkObject *parent;
cell = GTK_CELL_ACCESSIBLE (table_cell);
parent = gtk_widget_get_accessible (gtk_accessible_get_widget (GTK_ACCESSIBLE (cell)));
gtk_cell_accessible_parent_get_cell_position (GTK_CELL_ACCESSIBLE_PARENT (parent),
cell,
row, column);
return ((row && *row > 0) || (column && *column > 0));
}
static int
gtk_cell_accessible_get_row_span (AtkTableCell *table_cell)
{
return 1;
}
static GPtrArray *
gtk_cell_accessible_get_row_header_cells (AtkTableCell *table_cell)
{
GtkCellAccessible *cell;
AtkObject *parent;
cell = GTK_CELL_ACCESSIBLE (table_cell);
parent = gtk_widget_get_accessible (gtk_accessible_get_widget (GTK_ACCESSIBLE (cell)));
return gtk_cell_accessible_parent_get_row_header_cells (GTK_CELL_ACCESSIBLE_PARENT (parent),
cell);
}
static AtkObject *
gtk_cell_accessible_get_table (AtkTableCell *table_cell)
{
AtkObject *obj;
obj = ATK_OBJECT (table_cell);
do
{
AtkRole role;
obj = atk_object_get_parent (obj);
role = atk_object_get_role (obj);
if (role == ATK_ROLE_TABLE || role == ATK_ROLE_TREE_TABLE)
break;
}
while (obj);
return obj;
}
static void
atk_table_cell_interface_init (AtkTableCellIface *iface)
{
iface->get_column_span = gtk_cell_accessible_get_column_span;
iface->get_column_header_cells = gtk_cell_accessible_get_column_header_cells;
iface->get_position = gtk_cell_accessible_get_position;
iface->get_row_span = gtk_cell_accessible_get_row_span;
iface->get_row_header_cells = gtk_cell_accessible_get_row_header_cells;
iface->get_table = gtk_cell_accessible_get_table;
}
static GtkCellRendererState
gtk_cell_accessible_get_state (GtkCellAccessible *cell)
{
+66
View File
@@ -187,3 +187,69 @@ gtk_cell_accessible_parent_update_relationset (GtkCellAccessibleParent *parent,
if (iface->update_relationset)
(iface->update_relationset) (parent, cell, relationset);
}
void
gtk_cell_accessible_parent_get_cell_position (GtkCellAccessibleParent *parent,
GtkCellAccessible *cell,
gint *row,
gint *column)
{
GtkCellAccessibleParentIface *iface;
g_return_if_fail (GTK_IS_CELL_ACCESSIBLE_PARENT (parent));
g_return_if_fail (GTK_IS_CELL_ACCESSIBLE (cell));
iface = GTK_CELL_ACCESSIBLE_PARENT_GET_IFACE (parent);
if (iface->get_cell_position)
(iface->get_cell_position) (parent, cell, row, column);
else
{
if (row)
*row = -1;
if (column)
*column = -1;
}
}
/**
* gtk_cell_accessible_parent_get_column_header_cells:
* Returns: (transfer full) (element-type AtkObject)
*/
GPtrArray *
gtk_cell_accessible_parent_get_column_header_cells (GtkCellAccessibleParent *parent,
GtkCellAccessible *cell)
{
GtkCellAccessibleParentIface *iface;
g_return_val_if_fail (GTK_IS_CELL_ACCESSIBLE_PARENT (parent), NULL);
g_return_val_if_fail (GTK_IS_CELL_ACCESSIBLE (cell), NULL);
iface = GTK_CELL_ACCESSIBLE_PARENT_GET_IFACE (parent);
if (iface->get_column_header_cells)
return (iface->get_column_header_cells) (parent, cell);
else
return NULL;
}
/**
* gtk_cell_accessible_parent_get_row_header_cells:
* Returns: (transfer full) (element-type AtkObject)
*/
GPtrArray *
gtk_cell_accessible_parent_get_row_header_cells (GtkCellAccessibleParent *parent,
GtkCellAccessible *cell)
{
GtkCellAccessibleParentIface *iface;
g_return_val_if_fail (GTK_IS_CELL_ACCESSIBLE_PARENT (parent), NULL);
g_return_val_if_fail (GTK_IS_CELL_ACCESSIBLE (cell), NULL);
iface = GTK_CELL_ACCESSIBLE_PARENT_GET_IFACE (parent);
if (iface->get_row_header_cells)
return (iface->get_row_header_cells) (parent, cell);
else
return NULL;
}
+19
View File
@@ -75,6 +75,14 @@ struct _GtkCellAccessibleParentIface
void ( *update_relationset) (GtkCellAccessibleParent *parent,
GtkCellAccessible *cell,
AtkRelationSet *relationset);
void ( *get_cell_position) (GtkCellAccessibleParent *parent,
GtkCellAccessible *cell,
gint *row,
gint *column);
GPtrArray * ( *get_column_header_cells) (GtkCellAccessibleParent *parent,
GtkCellAccessible *cell);
GPtrArray * ( *get_row_header_cells) (GtkCellAccessibleParent *parent,
GtkCellAccessible *cell);
};
GDK_AVAILABLE_IN_ALL
@@ -115,6 +123,17 @@ GDK_AVAILABLE_IN_ALL
void gtk_cell_accessible_parent_update_relationset (GtkCellAccessibleParent *parent,
GtkCellAccessible *cell,
AtkRelationSet *relationset);
GDK_AVAILABLE_IN_ALL
void gtk_cell_accessible_parent_get_cell_position(GtkCellAccessibleParent *parent,
GtkCellAccessible *cell,
gint *row,
gint *column);
GPtrArray *gtk_cell_accessible_parent_get_column_header_cells (GtkCellAccessibleParent *parent,
GtkCellAccessible *cell);
GPtrArray *gtk_cell_accessible_parent_get_row_header_cells (GtkCellAccessibleParent *parent,
GtkCellAccessible *cell);
G_END_DECLS
+57 -4
View File
@@ -1174,11 +1174,12 @@ gtk_tree_view_accessible_grab_cell_focus (GtkCellAccessibleParent *parent,
if (gtk_widget_is_toplevel (toplevel))
{
#ifdef GDK_WINDOWING_X11
gtk_window_present_with_time (GTK_WINDOW (toplevel),
gdk_x11_get_server_time (gtk_widget_get_surface (widget)));
#else
gtk_window_present (GTK_WINDOW (toplevel));
if (GDK_IS_X11_DISPLAY (gtk_widget_get_display (toplevel)))
gtk_window_present_with_time (GTK_WINDOW (toplevel),
gdk_x11_get_server_time (gtk_widget_get_surface (widget)));
else
#endif
gtk_window_present (GTK_WINDOW (toplevel));
}
return TRUE;
@@ -1391,6 +1392,56 @@ gtk_tree_view_accessible_update_relationset (GtkCellAccessibleParent *parent,
}
}
static void
gtk_tree_view_accessible_get_cell_position (GtkCellAccessibleParent *parent,
GtkCellAccessible *cell,
gint *row,
gint *column)
{
GtkWidget *widget;
GtkTreeView *tree_view;
GtkTreeViewAccessibleCellInfo *cell_info;
GtkTreeViewAccessible *accessible;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
if (widget == NULL)
return;
tree_view = GTK_TREE_VIEW (widget);
accessible = GTK_TREE_VIEW_ACCESSIBLE (parent);
cell_info = find_cell_info (accessible, cell);
if (!cell_info)
return;
if (row)
(*row) = _gtk_rbtree_node_get_index (cell_info->tree, cell_info->node);
if (column)
(*column) = get_column_number (tree_view, cell_info->cell_col_ref);
}
static GPtrArray *
gtk_tree_view_accessible_get_column_header_cells (GtkCellAccessibleParent *parent,
GtkCellAccessible *cell)
{
GtkWidget *widget;
GtkTreeViewAccessibleCellInfo *cell_info;
GtkTreeViewAccessible *accessible;
GPtrArray *array;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
if (widget == NULL)
return NULL;
accessible = GTK_TREE_VIEW_ACCESSIBLE (parent);
cell_info = find_cell_info (accessible, cell);
if (!cell_info)
return NULL;
array = g_ptr_array_new_full (1, g_object_unref);
g_ptr_array_add (array, g_object_ref (get_header_from_column ( (cell_info->cell_col_ref))));
return array;
}
static void
gtk_cell_accessible_parent_interface_init (GtkCellAccessibleParentIface *iface)
{
@@ -1403,6 +1454,8 @@ gtk_cell_accessible_parent_interface_init (GtkCellAccessibleParentIface *iface)
iface->activate = gtk_tree_view_accessible_activate;
iface->edit = gtk_tree_view_accessible_edit;
iface->update_relationset = gtk_tree_view_accessible_update_relationset;
iface->get_cell_position = gtk_tree_view_accessible_get_cell_position;
iface->get_column_header_cells = gtk_tree_view_accessible_get_column_header_cells;
}
void
+11 -6
View File
@@ -59,8 +59,9 @@ notify_cb (GObject *obj,
/* Translate GtkWidget::size-allocate to AtkComponent::bounds-changed */
static void
size_allocate_cb (GtkWidget *widget,
GtkAllocation *allocation)
size_allocate_cb (GtkWidget *widget,
int width,
int height)
{
AtkObject* accessible;
AtkRectangle rect;
@@ -68,10 +69,14 @@ size_allocate_cb (GtkWidget *widget,
accessible = gtk_widget_get_accessible (widget);
if (ATK_IS_COMPONENT (accessible))
{
rect.x = allocation->x;
rect.y = allocation->y;
rect.width = allocation->width;
rect.height = allocation->height;
GtkAllocation alloc;
gtk_widget_get_allocation (widget, &alloc);
rect.x = alloc.x;
rect.y = alloc.y;
rect.width = alloc.width;
rect.height = alloc.height;
g_signal_emit_by_name (accessible, "bounds-changed", &rect);
}
}
+1
View File
@@ -180,6 +180,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkViewport, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkVolumeButton, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPaperSize, gtk_paper_size_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkRecentInfo, gtk_recent_info_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSelectionData, gtk_selection_data_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkTextIter, gtk_text_iter_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkTreeIter, gtk_tree_iter_free)
+7
View File
@@ -94,6 +94,7 @@
#include <gtk/gtkenums.h>
#include <gtk/gtkeventcontroller.h>
#include <gtk/gtkeventcontrollerkey.h>
#include <gtk/gtkeventcontrollerlegacy.h>
#include <gtk/gtkeventcontrollermotion.h>
#include <gtk/gtkeventcontrollerscroll.h>
#include <gtk/gtkexpander.h>
@@ -104,6 +105,8 @@
#include <gtk/gtkfilechoosernative.h>
#include <gtk/gtkfilechooserwidget.h>
#include <gtk/gtkfilefilter.h>
#include <gtk/gtkfilterlistmodel.h>
#include <gtk/gtkflattenlistmodel.h>
#include <gtk/gtkflowbox.h>
#include <gtk/gtkfontbutton.h>
#include <gtk/gtkfontchooser.h>
@@ -139,6 +142,7 @@
#include <gtk/gtkliststore.h>
#include <gtk/gtklockbutton.h>
#include <gtk/gtkmain.h>
#include <gtk/gtkmaplistmodel.h>
#include <gtk/gtkmediacontrols.h>
#include <gtk/gtkmediafile.h>
#include <gtk/gtkmediastream.h>
@@ -192,7 +196,9 @@
#include <gtk/gtkshortcutsshortcut.h>
#include <gtk/gtkshortcutswindow.h>
#include <gtk/gtkshow.h>
#include <gtk/gtkslicelistmodel.h>
#include <gtk/gtksnapshot.h>
#include <gtk/gtksortlistmodel.h>
#include <gtk/gtkstacksidebar.h>
#include <gtk/gtksizegroup.h>
#include <gtk/gtksizerequest.h>
@@ -220,6 +226,7 @@
#include <gtk/gtktooltip.h>
#include <gtk/gtktestutils.h>
#include <gtk/gtktreednd.h>
#include <gtk/gtktreelistmodel.h>
#include <gtk/gtktreemodel.h>
#include <gtk/gtktreemodelfilter.h>
#include <gtk/gtktreemodelsort.h>
+9 -4
View File
@@ -160,14 +160,19 @@ static void gtk_accel_label_measure (GtkWidget *widget,
G_DEFINE_TYPE_WITH_PRIVATE (GtkAccelLabel, gtk_accel_label, GTK_TYPE_WIDGET)
static void
gtk_accel_label_size_allocate (GtkWidget *widget,
const GtkAllocation *allocation,
int baseline)
gtk_accel_label_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkAccelLabel *al = GTK_ACCEL_LABEL (widget);
GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (al);
gtk_widget_size_allocate (priv->box, allocation, baseline);
gtk_widget_size_allocate (priv->box,
&(GtkAllocation) {
0, 0,
width, height
},baseline);
}
static void
+1 -1
View File
@@ -144,7 +144,7 @@ gtk_actionable_get_action_target_value (GtkActionable *actionable)
/**
* gtk_actionable_set_action_target_value:
* @actionable: a #GtkActionable widget
* @target_value: a #GVariant to set as the target value, or %NULL
* @target_value: (nullable): a #GVariant to set as the target value, or %NULL
*
* Sets the target value of an actionable widget.
*
+11 -15
View File
@@ -259,22 +259,19 @@ gtk_action_bar_set_child_property (GtkContainer *container,
}
static void
gtk_action_bar_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GtkActionBar *self = GTK_ACTION_BAR (widget);
GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (self);
gtk_widget_snapshot_child (GTK_WIDGET (self), priv->revealer, snapshot);
}
static void
gtk_action_bar_size_allocate (GtkWidget *widget,
const GtkAllocation *allocation,
int baseline)
gtk_action_bar_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (GTK_ACTION_BAR (widget));
gtk_widget_size_allocate (priv->revealer, allocation, baseline);
gtk_widget_size_allocate (priv->revealer,
&(GtkAllocation) {
0, 0,
width, height
},
baseline);
}
static void
@@ -364,7 +361,6 @@ gtk_action_bar_class_init (GtkActionBarClass *klass)
object_class->get_property = gtk_action_bar_get_property;
object_class->finalize = gtk_action_bar_finalize;
widget_class->snapshot = gtk_action_bar_snapshot;
widget_class->size_allocate = gtk_action_bar_size_allocate;
widget_class->measure = gtk_action_bar_measure_;
widget_class->destroy = gtk_action_bar_destroy;
+169 -79
View File
@@ -1,4 +1,4 @@
/* gtkappchooserbutton.c: an app-chooser combobox
/* gtkappchooserbutton.c: an app-chooser button
*
* Copyright (C) 2010 Red Hat, Inc.
*
@@ -44,7 +44,7 @@
* emitted when they are selected.
*
* To track changes in the selected application, use the
* #GtkComboBox::changed signal.
* #GtkAppChooserbutton::changed signal.
*/
#include "config.h"
@@ -71,6 +71,7 @@ enum {
};
enum {
SIGNAL_CHANGED,
SIGNAL_CUSTOM_ITEM_ACTIVATED,
NUM_SIGNALS
};
@@ -103,7 +104,9 @@ static void real_insert_separator (GtkAppChooserButton *self,
static guint signals[NUM_SIGNALS] = { 0, };
static GParamSpec *properties[NUM_PROPERTIES];
struct _GtkAppChooserButtonPrivate {
typedef struct
{
GtkWidget *combobox;
GtkListStore *store;
gchar *content_type;
@@ -113,9 +116,9 @@ struct _GtkAppChooserButtonPrivate {
gboolean show_default_item;
GHashTable *custom_item_names;
};
} GtkAppChooserButtonPrivate;
G_DEFINE_TYPE_WITH_CODE (GtkAppChooserButton, gtk_app_chooser_button, GTK_TYPE_COMBO_BOX,
G_DEFINE_TYPE_WITH_CODE (GtkAppChooserButton, gtk_app_chooser_button, GTK_TYPE_WIDGET,
G_ADD_PRIVATE (GtkAppChooserButton)
G_IMPLEMENT_INTERFACE (GTK_TYPE_APP_CHOOSER,
app_chooser_iface_init));
@@ -174,6 +177,8 @@ select_application_func_cb (GtkTreeModel *model,
gpointer user_data)
{
SelectAppData *data = user_data;
GtkAppChooserButton *self = data->self;
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
GAppInfo *app_to_match = data->info;
GAppInfo *app = NULL;
gboolean custom;
@@ -191,7 +196,7 @@ select_application_func_cb (GtkTreeModel *model,
result = TRUE;
else if (g_app_info_equal (app, app_to_match))
{
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (data->self), iter);
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->combobox), iter);
result = TRUE;
}
else
@@ -206,13 +211,14 @@ static void
gtk_app_chooser_button_select_application (GtkAppChooserButton *self,
GAppInfo *info)
{
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
SelectAppData *data;
data = g_slice_new0 (SelectAppData);
data->self = g_object_ref (self);
data->info = g_object_ref (info);
gtk_tree_model_foreach (GTK_TREE_MODEL (self->priv->store),
gtk_tree_model_foreach (GTK_TREE_MODEL (priv->store),
select_application_func_cb, data);
select_app_data_free (data);
@@ -224,6 +230,7 @@ other_application_dialog_response_cb (GtkDialog *dialog,
gpointer user_data)
{
GtkAppChooserButton *self = user_data;
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
GAppInfo *info;
if (response_id != GTK_RESPONSE_OK)
@@ -231,7 +238,7 @@ other_application_dialog_response_cb (GtkDialog *dialog,
/* reset the active item, otherwise we are stuck on
* 'Other application'
*/
gtk_combo_box_set_active (GTK_COMBO_BOX (self), self->priv->last_active);
gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combobox), priv->last_active);
gtk_widget_destroy (GTK_WIDGET (dialog));
return;
}
@@ -250,17 +257,18 @@ other_application_dialog_response_cb (GtkDialog *dialog,
static void
other_application_item_activated_cb (GtkAppChooserButton *self)
{
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
GtkWidget *dialog, *widget;
GtkWindow *toplevel;
toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self)));
dialog = gtk_app_chooser_dialog_new_for_content_type (toplevel,
GTK_DIALOG_DESTROY_WITH_PARENT,
self->priv->content_type);
priv->content_type);
gtk_window_set_modal (GTK_WINDOW (dialog), gtk_window_get_modal (toplevel));
gtk_app_chooser_dialog_set_heading (GTK_APP_CHOOSER_DIALOG (dialog),
self->priv->heading);
priv->heading);
widget = gtk_app_chooser_dialog_get_widget (GTK_APP_CHOOSER_DIALOG (dialog));
g_object_set (widget,
@@ -277,20 +285,21 @@ static void
gtk_app_chooser_button_ensure_dialog_item (GtkAppChooserButton *self,
GtkTreeIter *prev_iter)
{
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
GtkTreeIter iter, iter2;
if (!self->priv->show_dialog_item || !self->priv->content_type)
if (!priv->show_dialog_item || !priv->content_type)
return;
if (prev_iter == NULL)
gtk_list_store_append (self->priv->store, &iter);
gtk_list_store_append (priv->store, &iter);
else
gtk_list_store_insert_after (self->priv->store, &iter, prev_iter);
gtk_list_store_insert_after (priv->store, &iter, prev_iter);
real_insert_separator (self, FALSE, &iter);
iter2 = iter;
gtk_list_store_insert_after (self->priv->store, &iter, &iter2);
gtk_list_store_insert_after (priv->store, &iter, &iter2);
real_insert_custom_item (self, CUSTOM_ITEM_OTHER_APP,
_("Other application…"), NULL,
FALSE, &iter);
@@ -301,6 +310,7 @@ insert_one_application (GtkAppChooserButton *self,
GAppInfo *app,
GtkTreeIter *iter)
{
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
GIcon *icon;
icon = g_app_info_get_icon (app);
@@ -310,7 +320,7 @@ insert_one_application (GtkAppChooserButton *self,
else
g_object_ref (icon);
gtk_list_store_set (self->priv->store, iter,
gtk_list_store_set (priv->store, iter,
COLUMN_APP_INFO, app,
COLUMN_LABEL, g_app_info_get_name (app),
COLUMN_ICON, icon,
@@ -323,25 +333,26 @@ insert_one_application (GtkAppChooserButton *self,
static void
gtk_app_chooser_button_populate (GtkAppChooserButton *self)
{
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
GList *recommended_apps = NULL, *l;
GAppInfo *app, *default_app = NULL;
GtkTreeIter iter, iter2;
gboolean cycled_recommended;
#ifndef G_OS_WIN32
if (self->priv->content_type)
recommended_apps = g_app_info_get_recommended_for_type (self->priv->content_type);
if (priv->content_type)
recommended_apps = g_app_info_get_recommended_for_type (priv->content_type);
#endif
cycled_recommended = FALSE;
if (self->priv->show_default_item)
if (priv->show_default_item)
{
if (self->priv->content_type)
default_app = g_app_info_get_default_for_type (self->priv->content_type, FALSE);
if (priv->content_type)
default_app = g_app_info_get_default_for_type (priv->content_type, FALSE);
if (default_app != NULL)
{
get_first_iter (self->priv->store, &iter);
get_first_iter (priv->store, &iter);
cycled_recommended = TRUE;
insert_one_application (self, default_app, &iter);
@@ -359,12 +370,12 @@ gtk_app_chooser_button_populate (GtkAppChooserButton *self)
if (cycled_recommended)
{
gtk_list_store_insert_after (self->priv->store, &iter2, &iter);
gtk_list_store_insert_after (priv->store, &iter2, &iter);
iter = iter2;
}
else
{
get_first_iter (self->priv->store, &iter);
get_first_iter (priv->store, &iter);
cycled_recommended = TRUE;
}
@@ -379,21 +390,22 @@ gtk_app_chooser_button_populate (GtkAppChooserButton *self)
else
gtk_app_chooser_button_ensure_dialog_item (self, &iter);
gtk_combo_box_set_active (GTK_COMBO_BOX (self), 0);
gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combobox), 0);
}
static void
gtk_app_chooser_button_build_ui (GtkAppChooserButton *self)
{
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
GtkCellRenderer *cell;
GtkCellArea *area;
gtk_combo_box_set_model (GTK_COMBO_BOX (self),
GTK_TREE_MODEL (self->priv->store));
gtk_combo_box_set_model (GTK_COMBO_BOX (priv->combobox),
GTK_TREE_MODEL (priv->store));
area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (self));
area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (priv->combobox));
gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (self),
gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (priv->combobox),
row_separator_func, NULL, NULL);
cell = gtk_cell_renderer_pixbuf_new ();
@@ -402,7 +414,7 @@ gtk_app_chooser_button_build_ui (GtkAppChooserButton *self)
"expand", FALSE,
"fixed-size", FALSE,
NULL);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (self), cell,
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->combobox), cell,
"gicon", COLUMN_ICON,
NULL);
@@ -411,7 +423,7 @@ gtk_app_chooser_button_build_ui (GtkAppChooserButton *self)
"align", FALSE,
"expand", TRUE,
NULL);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (self), cell,
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->combobox), cell,
"text", COLUMN_LABEL,
NULL);
@@ -421,11 +433,12 @@ gtk_app_chooser_button_build_ui (GtkAppChooserButton *self)
static void
gtk_app_chooser_button_remove_non_custom (GtkAppChooserButton *self)
{
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
GtkTreeModel *model;
GtkTreeIter iter;
gboolean custom, res;
model = GTK_TREE_MODEL (self->priv->store);
model = GTK_TREE_MODEL (priv->store);
if (!gtk_tree_model_get_iter_first (model, &iter))
return;
@@ -442,9 +455,11 @@ gtk_app_chooser_button_remove_non_custom (GtkAppChooserButton *self)
}
static void
gtk_app_chooser_button_changed (GtkComboBox *object)
gtk_app_chooser_button_changed (GtkComboBox *object,
gpointer user_data)
{
GtkAppChooserButton *self = GTK_APP_CHOOSER_BUTTON (object);
GtkAppChooserButton *self = user_data;
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
GtkTreeIter iter;
gchar *name = NULL;
gboolean custom;
@@ -453,7 +468,7 @@ gtk_app_chooser_button_changed (GtkComboBox *object)
if (!gtk_combo_box_get_active_iter (object, &iter))
return;
gtk_tree_model_get (GTK_TREE_MODEL (self->priv->store), &iter,
gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
COLUMN_NAME, &name,
COLUMN_CUSTOM, &custom,
-1);
@@ -464,7 +479,7 @@ gtk_app_chooser_button_changed (GtkComboBox *object)
{
name_quark = g_quark_from_string (name);
g_signal_emit (self, signals[SIGNAL_CUSTOM_ITEM_ACTIVATED], name_quark, name);
self->priv->last_active = gtk_combo_box_get_active (object);
priv->last_active = gtk_combo_box_get_active (object);
}
else
{
@@ -475,7 +490,9 @@ gtk_app_chooser_button_changed (GtkComboBox *object)
g_free (name);
}
else
self->priv->last_active = gtk_combo_box_get_active (object);
priv->last_active = gtk_combo_box_get_active (object);
g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
}
static void
@@ -491,13 +508,14 @@ static GAppInfo *
gtk_app_chooser_button_get_app_info (GtkAppChooser *object)
{
GtkAppChooserButton *self = GTK_APP_CHOOSER_BUTTON (object);
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
GtkTreeIter iter;
GAppInfo *info;
if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self), &iter))
if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->combobox), &iter))
return NULL;
gtk_tree_model_get (GTK_TREE_MODEL (self->priv->store), &iter,
gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
COLUMN_APP_INFO, &info,
-1);
@@ -522,11 +540,12 @@ gtk_app_chooser_button_set_property (GObject *obj,
GParamSpec *pspec)
{
GtkAppChooserButton *self = GTK_APP_CHOOSER_BUTTON (obj);
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
switch (property_id)
{
case PROP_CONTENT_TYPE:
self->priv->content_type = g_value_dup_string (value);
priv->content_type = g_value_dup_string (value);
break;
case PROP_SHOW_DIALOG_ITEM:
gtk_app_chooser_button_set_show_dialog_item (self, g_value_get_boolean (value));
@@ -550,20 +569,21 @@ gtk_app_chooser_button_get_property (GObject *obj,
GParamSpec *pspec)
{
GtkAppChooserButton *self = GTK_APP_CHOOSER_BUTTON (obj);
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
switch (property_id)
{
case PROP_CONTENT_TYPE:
g_value_set_string (value, self->priv->content_type);
g_value_set_string (value, priv->content_type);
break;
case PROP_SHOW_DIALOG_ITEM:
g_value_set_boolean (value, self->priv->show_dialog_item);
g_value_set_boolean (value, priv->show_dialog_item);
break;
case PROP_SHOW_DEFAULT_ITEM:
g_value_set_boolean (value, self->priv->show_default_item);
g_value_set_boolean (value, priv->show_default_item);
break;
case PROP_HEADING:
g_value_set_string (value, self->priv->heading);
g_value_set_string (value, priv->heading);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
@@ -575,15 +595,46 @@ static void
gtk_app_chooser_button_finalize (GObject *obj)
{
GtkAppChooserButton *self = GTK_APP_CHOOSER_BUTTON (obj);
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
g_hash_table_destroy (self->priv->custom_item_names);
g_free (self->priv->content_type);
g_free (self->priv->heading);
g_object_unref (self->priv->store);
g_hash_table_destroy (priv->custom_item_names);
g_free (priv->content_type);
g_free (priv->heading);
g_object_unref (priv->store);
gtk_widget_unparent (priv->combobox);
G_OBJECT_CLASS (gtk_app_chooser_button_parent_class)->finalize (obj);
}
static void
gtk_app_chooser_button_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkAppChooserButton *button = GTK_APP_CHOOSER_BUTTON (widget);
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (button);
gtk_widget_measure (priv->combobox, orientation, for_size,
minimum, natural,
minimum_baseline, natural_baseline);
}
static void
gtk_app_chooser_button_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkAppChooserButton *button = GTK_APP_CHOOSER_BUTTON (widget);
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (button);
gtk_widget_size_allocate (priv->combobox, &(GtkAllocation){0, 0, width, height}, baseline);
}
static void
app_chooser_iface_init (GtkAppChooserIface *iface)
{
@@ -595,14 +646,15 @@ static void
gtk_app_chooser_button_class_init (GtkAppChooserButtonClass *klass)
{
GObjectClass *oclass = G_OBJECT_CLASS (klass);
GtkComboBoxClass *combo_class = GTK_COMBO_BOX_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
oclass->set_property = gtk_app_chooser_button_set_property;
oclass->get_property = gtk_app_chooser_button_get_property;
oclass->finalize = gtk_app_chooser_button_finalize;
oclass->constructed = gtk_app_chooser_button_constructed;
combo_class->changed = gtk_app_chooser_button_changed;
widget_class->measure = gtk_app_chooser_button_measure;
widget_class->size_allocate = gtk_app_chooser_button_size_allocate;
g_object_class_override_property (oclass, PROP_CONTENT_TYPE, "content-type");
@@ -649,6 +701,16 @@ gtk_app_chooser_button_class_init (GtkAppChooserButtonClass *klass)
g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
signals[SIGNAL_CHANGED] =
g_signal_new (I_("changed"),
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkAppChooserButtonClass, changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
/**
* GtkAppChooserButton::custom-item-activated:
* @self: the object which received the signal
@@ -667,21 +729,29 @@ gtk_app_chooser_button_class_init (GtkAppChooserButtonClass *klass)
NULL,
G_TYPE_NONE,
1, G_TYPE_STRING);
}
static void
gtk_app_chooser_button_init (GtkAppChooserButton *self)
{
self->priv = gtk_app_chooser_button_get_instance_private (self);
self->priv->custom_item_names =
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
self->priv->store = gtk_list_store_new (NUM_COLUMNS,
G_TYPE_APP_INFO,
G_TYPE_STRING, /* name */
G_TYPE_STRING, /* label */
G_TYPE_ICON,
G_TYPE_BOOLEAN, /* separator */
G_TYPE_BOOLEAN); /* custom */
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
gtk_widget_set_has_surface (GTK_WIDGET (self), FALSE);
priv->custom_item_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
priv->store = gtk_list_store_new (NUM_COLUMNS,
G_TYPE_APP_INFO,
G_TYPE_STRING, /* name */
G_TYPE_STRING, /* label */
G_TYPE_ICON,
G_TYPE_BOOLEAN, /* separator */
G_TYPE_BOOLEAN); /* custom */
priv->combobox = gtk_combo_box_new_with_model (GTK_TREE_MODEL (priv->store));
gtk_widget_set_parent (priv->combobox, GTK_WIDGET (self));
g_signal_connect (priv->combobox, "changed",
G_CALLBACK (gtk_app_chooser_button_changed), self);
}
static gboolean
@@ -689,14 +759,15 @@ app_chooser_button_iter_from_custom_name (GtkAppChooserButton *self,
const gchar *name,
GtkTreeIter *set_me)
{
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
GtkTreeIter iter;
gchar *custom_name = NULL;
if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->priv->store), &iter))
if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->store), &iter))
return FALSE;
do {
gtk_tree_model_get (GTK_TREE_MODEL (self->priv->store), &iter,
gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
COLUMN_NAME, &custom_name,
-1);
@@ -709,7 +780,7 @@ app_chooser_button_iter_from_custom_name (GtkAppChooserButton *self,
}
g_free (custom_name);
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->priv->store), &iter));
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->store), &iter));
return FALSE;
}
@@ -722,20 +793,21 @@ real_insert_custom_item (GtkAppChooserButton *self,
gboolean custom,
GtkTreeIter *iter)
{
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
if (custom)
{
if (g_hash_table_lookup (self->priv->custom_item_names, name) != NULL)
if (g_hash_table_lookup (priv->custom_item_names, name) != NULL)
{
g_warning ("Attempting to add custom item %s to GtkAppChooserButton, "
"when there's already an item with the same name", name);
return;
}
g_hash_table_insert (self->priv->custom_item_names,
g_hash_table_insert (priv->custom_item_names,
g_strdup (name), GINT_TO_POINTER (1));
}
gtk_list_store_set (self->priv->store, iter,
gtk_list_store_set (priv->store, iter,
COLUMN_NAME, name,
COLUMN_LABEL, label,
COLUMN_ICON, icon,
@@ -749,7 +821,9 @@ real_insert_separator (GtkAppChooserButton *self,
gboolean custom,
GtkTreeIter *iter)
{
gtk_list_store_set (self->priv->store, iter,
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
gtk_list_store_set (priv->store, iter,
COLUMN_CUSTOM, custom,
COLUMN_SEPARATOR, TRUE,
-1);
@@ -784,11 +858,12 @@ gtk_app_chooser_button_new (const gchar *content_type)
void
gtk_app_chooser_button_append_separator (GtkAppChooserButton *self)
{
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
GtkTreeIter iter;
g_return_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self));
gtk_list_store_append (self->priv->store, &iter);
gtk_list_store_append (priv->store, &iter);
real_insert_separator (self, TRUE, &iter);
}
@@ -812,12 +887,13 @@ gtk_app_chooser_button_append_custom_item (GtkAppChooserButton *self,
const gchar *label,
GIcon *icon)
{
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
GtkTreeIter iter;
g_return_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self));
g_return_if_fail (name != NULL);
gtk_list_store_append (self->priv->store, &iter);
gtk_list_store_append (priv->store, &iter);
real_insert_custom_item (self, name, label, icon, TRUE, &iter);
}
@@ -836,19 +912,20 @@ void
gtk_app_chooser_button_set_active_custom_item (GtkAppChooserButton *self,
const gchar *name)
{
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
GtkTreeIter iter;
g_return_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self));
g_return_if_fail (name != NULL);
if (!g_hash_table_contains (self->priv->custom_item_names, name) ||
if (!g_hash_table_contains (priv->custom_item_names, name) ||
!app_chooser_button_iter_from_custom_name (self, name, &iter))
{
g_warning ("Can't find the item named %s in the app chooser.", name);
return;
}
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self), &iter);
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->combobox), &iter);
}
/**
@@ -863,9 +940,11 @@ gtk_app_chooser_button_set_active_custom_item (GtkAppChooserButton *self,
gboolean
gtk_app_chooser_button_get_show_dialog_item (GtkAppChooserButton *self)
{
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
g_return_val_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self), FALSE);
return self->priv->show_dialog_item;
return priv->show_dialog_item;
}
/**
@@ -880,9 +959,10 @@ void
gtk_app_chooser_button_set_show_dialog_item (GtkAppChooserButton *self,
gboolean setting)
{
if (self->priv->show_dialog_item != setting)
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
if (priv->show_dialog_item != setting)
{
self->priv->show_dialog_item = setting;
priv->show_dialog_item = setting;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SHOW_DIALOG_ITEM]);
@@ -902,9 +982,11 @@ gtk_app_chooser_button_set_show_dialog_item (GtkAppChooserButton *self,
gboolean
gtk_app_chooser_button_get_show_default_item (GtkAppChooserButton *self)
{
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
g_return_val_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self), FALSE);
return self->priv->show_default_item;
return priv->show_default_item;
}
/**
@@ -919,9 +1001,13 @@ void
gtk_app_chooser_button_set_show_default_item (GtkAppChooserButton *self,
gboolean setting)
{
if (self->priv->show_default_item != setting)
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
g_return_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self));
if (priv->show_default_item != setting)
{
self->priv->show_default_item = setting;
priv->show_default_item = setting;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SHOW_DEFAULT_ITEM]);
@@ -941,10 +1027,12 @@ void
gtk_app_chooser_button_set_heading (GtkAppChooserButton *self,
const gchar *heading)
{
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
g_return_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self));
g_free (self->priv->heading);
self->priv->heading = g_strdup (heading);
g_free (priv->heading);
priv->heading = g_strdup (heading);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HEADING]);
}
@@ -961,7 +1049,9 @@ gtk_app_chooser_button_set_heading (GtkAppChooserButton *self,
const gchar *
gtk_app_chooser_button_get_heading (GtkAppChooserButton *self)
{
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
g_return_val_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self), NULL);
return self->priv->heading;
return priv->heading;
}
+5 -8
View File
@@ -1,5 +1,5 @@
/*
* gtkappchooserbutton.h: an app-chooser combobox
* gtkappchooserbutton.h: an app-chooser button
*
* Copyright (C) 2010 Red Hat, Inc.
*
@@ -26,7 +26,7 @@
#error "Only <gtk/gtk.h> can be included directly."
#endif
#include <gtk/gtkcombobox.h>
#include <gtk/gtkwidget.h>
#include <gio/gio.h>
G_BEGIN_DECLS
@@ -40,13 +40,9 @@ G_BEGIN_DECLS
typedef struct _GtkAppChooserButton GtkAppChooserButton;
typedef struct _GtkAppChooserButtonClass GtkAppChooserButtonClass;
typedef struct _GtkAppChooserButtonPrivate GtkAppChooserButtonPrivate;
struct _GtkAppChooserButton {
GtkComboBox parent;
/*< private >*/
GtkAppChooserButtonPrivate *priv;
GtkWidget parent_instance;
};
/**
@@ -57,10 +53,11 @@ struct _GtkAppChooserButton {
* is activated from the dropdown menu.
*/
struct _GtkAppChooserButtonClass {
GtkComboBoxClass parent_class;
GtkWidgetClass parent_class;
/*< public >*/
void (* changed) (GtkAppChooserButton *self);
void (* custom_item_activated) (GtkAppChooserButton *self,
const gchar *item_name);
+9 -4
View File
@@ -934,16 +934,21 @@ gtk_app_chooser_widget_snapshot (GtkWidget *widget,
}
static void
gtk_app_chooser_widget_size_allocate (GtkWidget *widget,
const GtkAllocation *allocation,
gtk_app_chooser_widget_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (widget);
GtkAppChooserWidgetPrivate *priv = gtk_app_chooser_widget_get_instance_private (self);
GTK_WIDGET_CLASS (gtk_app_chooser_widget_parent_class)->size_allocate (widget, allocation, baseline);
GTK_WIDGET_CLASS (gtk_app_chooser_widget_parent_class)->size_allocate (widget, width, height, baseline);
gtk_widget_size_allocate (priv->overlay, allocation, baseline);
gtk_widget_size_allocate (priv->overlay,
&(GtkAllocation) {
0, 0,
width, height
},baseline);
}
static void
+148 -10
View File
@@ -24,9 +24,13 @@
#include "gtkapplicationprivate.h"
#include "gtksettings.h"
#include "gtkprivate.h"
G_DEFINE_TYPE (GtkApplicationImplDBus, gtk_application_impl_dbus, GTK_TYPE_APPLICATION_IMPL)
#define DBUS_BUS_NAME "org.freedesktop.DBus"
#define DBUS_OBJECT_PATH "/org/freedesktop/DBus"
#define DBUS_BUS_INTERFACE "org.freedesktop.DBus"
#define GNOME_DBUS_NAME "org.gnome.SessionManager"
#define GNOME_DBUS_OBJECT_PATH "/org/gnome/SessionManager"
#define GNOME_DBUS_INTERFACE "org.gnome.SessionManager"
@@ -35,6 +39,9 @@ G_DEFINE_TYPE (GtkApplicationImplDBus, gtk_application_impl_dbus, GTK_TYPE_APPLI
#define XFCE_DBUS_OBJECT_PATH "/org/xfce/SessionManager"
#define XFCE_DBUS_INTERFACE "org.xfce.Session.Manager"
#define XFCE_DBUS_CLIENT_INTERFACE "org.xfce.Session.Client"
#define GNOME_SCREENSAVER_DBUS_NAME "org.gnome.ScreenSaver"
#define GNOME_SCREENSAVER_DBUS_OBJECT_PATH "/org/gnome/ScreenSaver"
#define GNOME_SCREENSAVER_DBUS_INTERFACE "org.gnome.ScreenSaver"
static void
unregister_client (GtkApplicationImplDBus *dbus)
@@ -171,6 +178,63 @@ stash_desktop_autostart_id (void)
g_unsetenv ("DESKTOP_AUTOSTART_ID");
}
static void
screensaver_signal_session (GDBusProxy *proxy,
const char *sender_name,
const char *signal_name,
GVariant *parameters,
GtkApplication *application)
{
gboolean active;
if (!g_str_equal (signal_name, "ActiveChanged"))
return;
g_variant_get (parameters, "(b)", &active);
gtk_application_set_screensaver_active (application, active);
}
static void
screensaver_signal_portal (GDBusConnection *connection,
const char *sender_name,
const char *object_path,
const char *interface_name,
const char *signal_name,
GVariant *parameters,
gpointer data)
{
GtkApplication *application = data;
gboolean active;
GVariant *state;
if (!g_str_equal (signal_name, "StateChanged"))
return;
g_variant_get (parameters, "(o@a{sv})", NULL, &state);
g_variant_lookup (state, "screensaver-active", "b", &active);
gtk_application_set_screensaver_active (application, active);
}
static void
create_monitor_cb (GObject *source,
GAsyncResult *result,
gpointer data)
{
GDBusProxy *proxy = G_DBUS_PROXY (source);
GError *error = NULL;
GVariant *ret = NULL;
ret = g_dbus_proxy_call_finish (proxy, result, &error);
if (ret == NULL)
{
g_warning ("Creating a portal monitor failed: %s", error->message);
g_error_free (error);
return;
}
g_variant_unref (ret);
}
static void
gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
gboolean register_session)
@@ -195,6 +259,9 @@ gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
dbus->object_path = g_application_get_dbus_object_path (G_APPLICATION (impl->application));
dbus->unique_name = g_dbus_connection_get_unique_name (dbus->session);
if (gdk_should_use_portal ())
goto out;
g_debug ("Connecting to session manager");
/* Try the GNOME session manager first */
@@ -236,6 +303,27 @@ gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
if (!register_session)
goto out;
dbus->ss_proxy = gtk_application_get_proxy_if_service_present (dbus->session,
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
G_DBUS_PROXY_FLAGS_NONE,
GNOME_SCREENSAVER_DBUS_NAME,
GNOME_SCREENSAVER_DBUS_OBJECT_PATH,
GNOME_SCREENSAVER_DBUS_INTERFACE,
&error);
if (error)
{
g_debug ("Failed to get the GNOME screensaver proxy: %s", error->message);
g_clear_error (&error);
g_clear_object (&dbus->ss_proxy);
}
if (dbus->ss_proxy)
{
g_signal_connect (dbus->ss_proxy, "g-signal",
G_CALLBACK (screensaver_signal_session), impl->application);
}
g_debug ("Registering client '%s' '%s'", dbus->application_id, client_id);
res = g_dbus_proxy_call_sync (dbus->sm_proxy,
@@ -304,9 +392,9 @@ gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
if (id && id[0])
{
res = g_dbus_connection_call_sync (dbus->session,
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
DBUS_BUS_NAME,
DBUS_OBJECT_PATH,
DBUS_BUS_INTERFACE,
"GetId",
NULL,
NULL,
@@ -336,18 +424,51 @@ gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
"gtk-shell-shows-menubar", FALSE,
NULL);
if (dbus->sm_proxy == NULL)
if (dbus->sm_proxy == NULL && dbus->session)
{
dbus->inhibit_proxy = gtk_application_get_proxy_if_service_present (dbus->session,
G_DBUS_PROXY_FLAGS_NONE,
"org.freedesktop.portal.Desktop",
"/org/freedesktop/portal/desktop",
"org.freedesktop.portal.Inhibit",
PORTAL_BUS_NAME,
PORTAL_OBJECT_PATH,
PORTAL_INHIBIT_INTERFACE,
&error);
if (error)
{
g_debug ("Failed to get an inhibit portal proxy: %s", error->message);
g_clear_error (&error);
return;
}
if (register_session)
{
char *token;
GVariantBuilder opt_builder;
/* Monitor screensaver state */
dbus->session_id = gtk_get_portal_session_path (dbus->session, &token);
dbus->state_changed_handler =
g_dbus_connection_signal_subscribe (dbus->session,
PORTAL_BUS_NAME,
PORTAL_INHIBIT_INTERFACE,
"StateChanged",
PORTAL_OBJECT_PATH,
NULL,
G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
screensaver_signal_portal,
impl->application,
NULL);
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add (&opt_builder, "{sv}",
"session_handle_token", g_variant_new_string (token));
g_dbus_proxy_call (dbus->inhibit_proxy,
"CreateMonitor",
g_variant_new ("(sa{sv})", "", &opt_builder),
G_DBUS_CALL_FLAGS_NONE,
G_MAXINT,
NULL,
create_monitor_cb, dbus);
g_free (token);
}
}
}
@@ -510,7 +631,7 @@ gtk_application_impl_dbus_inhibit (GtkApplicationImpl *impl,
g_variant_new ("(s@usu)",
dbus->application_id,
window ? gtk_application_impl_dbus_get_window_system_id (dbus, window) : g_variant_new_uint32 (0),
reason,
reason ? reason : "",
flags),
G_DBUS_CALL_FLAGS_NONE,
G_MAXINT,
@@ -608,9 +729,9 @@ gtk_application_impl_dbus_uninhibit (GtkApplicationImpl *impl,
if (handle->cookie == cookie)
{
g_dbus_connection_call (dbus->session,
"org.freedesktop.portal.Desktop",
PORTAL_BUS_NAME,
handle->handle,
"org.freedesktop.portal.Request",
PORTAL_REQUEST_INTERFACE,
"Close",
g_variant_new ("()"),
G_VARIANT_TYPE_UNIT,
@@ -667,11 +788,28 @@ gtk_application_impl_dbus_finalize (GObject *object)
{
GtkApplicationImplDBus *dbus = (GtkApplicationImplDBus *) object;
if (dbus->session_id)
{
g_dbus_connection_call (dbus->session,
PORTAL_BUS_NAME,
dbus->session_id,
PORTAL_SESSION_INTERFACE,
"Close",
NULL, NULL, 0, -1, NULL, NULL, NULL);
g_free (dbus->session_id);
}
if (dbus->state_changed_handler)
g_dbus_connection_signal_unsubscribe (dbus->session,
dbus->state_changed_handler);
g_clear_object (&dbus->inhibit_proxy);
g_slist_free_full (dbus->inhibit_handles, inhibit_handle_free);
g_free (dbus->app_menu_path);
g_free (dbus->menubar_path);
g_clear_object (&dbus->sm_proxy);
g_clear_object (&dbus->ss_proxy);
G_OBJECT_CLASS (gtk_application_impl_dbus_parent_class)->finalize (object);
}
+39 -2
View File
@@ -137,6 +137,7 @@ static guint gtk_application_signals[LAST_SIGNAL];
enum {
PROP_ZERO,
PROP_REGISTER_SESSION,
PROP_SCREENSAVER_ACTIVE,
PROP_APP_MENU,
PROP_MENUBAR,
PROP_ACTIVE_WINDOW,
@@ -157,6 +158,7 @@ typedef struct
guint last_window_id;
gboolean register_session;
gboolean screensaver_active;
GtkActionMuxer *muxer;
GtkBuilder *menus_builder;
gchar *help_overlay_path;
@@ -385,8 +387,6 @@ gtk_application_init (GtkApplication *application)
{
GtkApplicationPrivate *priv = gtk_application_get_instance_private (application);
priv = gtk_application_get_instance_private (application);
priv->muxer = gtk_action_muxer_new ();
priv->accels = gtk_application_accels_new ();
@@ -534,6 +534,10 @@ gtk_application_get_property (GObject *object,
g_value_set_boolean (value, priv->register_session);
break;
case PROP_SCREENSAVER_ACTIVE:
g_value_set_boolean (value, priv->screensaver_active);
break;
case PROP_APP_MENU:
g_value_set_object (value, gtk_application_get_app_menu (application));
break;
@@ -653,6 +657,8 @@ gtk_application_class_init (GtkApplicationClass *class)
* GtkApplication:register-session:
*
* Set this property to %TRUE to register with the session manager.
* This will make GTK+ track the session state (such as the
* #GtkApplication::screensaver-active property).
*/
gtk_application_props[PROP_REGISTER_SESSION] =
g_param_spec_boolean ("register-session",
@@ -661,6 +667,24 @@ gtk_application_class_init (GtkApplicationClass *class)
FALSE,
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS);
/**
* GtkApplication:screensaver-active:
*
* This property is %TRUE if GTK+ believes that the screensaver is
* currently active. GTK+ only tracks session state (including this)
* when #GtkApplication::register-session is set to %TRUE.
*
* Tracking the screensaver state is supported on Linux.
*
* Since: 3.24
*/
gtk_application_props[PROP_SCREENSAVER_ACTIVE] =
g_param_spec_boolean ("screensaver-active",
P_("Screensaver Active"),
P_("Whether the screensaver is active"),
FALSE,
G_PARAM_READABLE|G_PARAM_STATIC_STRINGS);
gtk_application_props[PROP_APP_MENU] =
g_param_spec_object ("app-menu",
P_("Application menu"),
@@ -1370,3 +1394,16 @@ gtk_application_get_menu_by_id (GtkApplication *application,
return G_MENU (object);
}
void
gtk_application_set_screensaver_active (GtkApplication *application,
gboolean active)
{
GtkApplicationPrivate *priv = gtk_application_get_instance_private (application);
if (priv->screensaver_active != active)
{
priv->screensaver_active = active;
g_object_notify (G_OBJECT (application), "screensaver-active");
}
}

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