Compare commits

..

135 Commits

Author SHA1 Message Date
Carlos Garnacho
a416bed34c wayland: Send primary offer to all data devices from the same client
Make the data device track the keyboard focus, and use that list to
forward the primary selection to all data devices from the same
client.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1253

(cherry-pick of commit b45d5ef3f5a497703fd2c77b7088249cbf3ef367)

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1262
2020-06-23 20:40:33 +02:00
Carlos Garnacho
80c0a470e7 wayland: Send clipboard offers to all data devices from the same client
Make the data device track the keyboard focus, and use that list to
forward the clipboard selection to all data devices from the same
client.

This is however not the case of DnD data offers, as the semantics
of multiple in-flight offers is unclear.

Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1250

(cherry-pick of commit 7e4e3714663952a69ba0a26662841fc5c0cb266c)

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1262
2020-06-23 20:40:21 +02:00
Jonas Ådahl
8802f7f0d8 stage/x11: Check that message is WM_PROTOCOLS before assuming so
When a touch sequence was rejected, we'd update the event timestamps of
incoming touch events to help with implementing grabs. This was done by
sending a ClientMessage with a counter, and comparing the counter to
decide whether we're seing a replayed event or not.

This had the unforseen consequence that we would potentially end up
destroying all actors including the stage, since, when mutter receives a
ClientMessage event, it would assume that it's a WM_PROTOCOLS event, and
handle it as such. The problem with this approach is that it would
ignore fact that there might be other ClientMessage types sent to it,
for example the touch synchronization one. What could happen is that the
touch count value would match up with the value of the WM_DELETE_WINDOW
atom, clutter would treat this as WM_PROTOCOLS:WM_DELETE_WINDOW, which
it'd translate to clutter_actor_destroy(stage).

Destroying the stage in such a way is not expected, and caused wierd
crashes in different places depending on what was going on.

This commit make sure we only treat WM_PROTOCOLS client messages as
WM_PROTOCOLS client messages effectively avoiding the issue.

This fixes crashes such as:

 #0  meta_window_get_buffer_rect (window=0x0, rect=rect@entry=0x7ffd7fc62e40) at core/window.c:4396
 #1  0x00007f1e2634837f in get_top_visible_window_actor (compositor=0x297d700, compositor=0x297d700) at compositor/compositor.c:1059
 #2  meta_compositor_sync_stack (compositor=0x297d700, stack=<optimized out>, stack@entry=0x26e3140) at compositor/compositor.c:1176
 #3  0x00007f1e263757ac in meta_stack_tracker_sync_stack (tracker=0x297dbc0) at core/stack-tracker.c:871
 #4  0x00007f1e26375899 in stack_tracker_sync_stack_later (data=<optimized out>) at core/stack-tracker.c:881
 #5  0x00007f1e26376914 in run_repaint_laters (laters_list=0x7f1e2663b7d8 <laters+24>) at core/util.c:809
 #6  run_all_repaint_laters (data=<optimized out>) at core/util.c:826
 #7  0x00007f1e26b18325 in _clutter_run_repaint_functions (flags=flags@entry=CLUTTER_REPAINT_FLAGS_PRE_PAINT) at clutter-main.c:3448
 #8  0x00007f1e26b18fc5 in master_clock_update_stages (master_clock=0x32d6a80, stages=0x4e5a740) at clutter-master-clock-default.c:437
 #9  clutter_clock_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at clutter-master-clock-default.c:567
 #10 0x00007f1e27e48049 in g_main_dispatch (context=0x225b8d0) at gmain.c:3175
 #11 g_main_context_dispatch (context=context@entry=0x225b8d0) at gmain.c:3828
 #12 0x00007f1e27e483a8 in g_main_context_iterate (context=0x225b8d0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3901
 #13 0x00007f1e27e4867a in g_main_loop_run (loop=0x24e29f0) at gmain.c:4097
 #14 0x00007f1e2636a3dc in meta_run () at core/main.c:666
 #15 0x000000000040219c in main (argc=1, argv=0x7ffd7fc63238) at ../src/main.c:534

and

 #0  0x00007f93943c1f25 in raise () at /usr/lib/libc.so.6
 #1  0x00007f93943ab897 in abort () at /usr/lib/libc.so.6
 #2  0x00007f9393e1e062 in g_assertion_message (domain=<optimized out>, file=<optimized out>, line=<optimized out>, func=0x7f93933e6860 <__func__.116322> "meta_x11_get_stage_window",
 #3  0x00007f9393e4ab1d in g_assertion_message_expr ()
 #4  0x00007f939338ecd7 in meta_x11_get_stage_window (stage=<optimized out>) at ../mutter/src/backends/x11/meta-stage-x11.c:923
 #5  0x00007f939339e599 in meta_backend_x11_cm_translate_device_event (x11=<optimized out>, device_event=0x55bc8bcfd6b0) at ../mutter/src/backends/x11/cm/meta-backend-x11-cm.c:381
 #6  0x00007f939339f2e2 in meta_backend_x11_translate_device_event (device_event=0x55bc8bcfd6b0, x11=0x55bc89dd5220) at ../mutter/src/backends/x11/meta-backend-x11.c:179
 #7  0x00007f939339f2e2 in translate_device_event (device_event=0x55bc8bcfd6b0, x11=0x55bc89dd5220) at ../mutter/src/backends/x11/meta-backend-x11.c:208
 #8  0x00007f939339f2e2 in maybe_spoof_event_as_stage_event (input_event=0x55bc8bcfd6b0, x11=0x55bc89dd5220) at ../mutter/src/backends/x11/meta-backend-x11.c:284
 #9  0x00007f939339f2e2 in handle_input_event (event=0x7fff62d60490, x11=0x55bc89dd5220) at ../mutter/src/backends/x11/meta-backend-x11.c:309
 #10 0x00007f939339f2e2 in handle_host_xevent (event=0x7fff62d60490, backend=0x55bc89dd5220) at ../mutter/src/backends/x11/meta-backend-x11.c:413
 #11 0x00007f939339f2e2 in x_event_source_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at ../mutter/src/backends/x11/meta-backend-x11.c:467
 #12 0x00007f9393e6c39e in g_main_dispatch (context=0x55bc89dd03e0) at ../glib/glib/gmain.c:3179
 #13 0x00007f9393e6c39e in g_main_context_dispatch (context=context@entry=0x55bc89dd03e0) at ../glib/glib/gmain.c:3844
 #14 0x00007f9393e6e1b1 in g_main_context_iterate (context=0x55bc89dd03e0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/glib/gmain.c:3917
 #15 0x00007f9393e6f0c3 in g_main_loop_run (loop=0x55bc8a042640) at ../glib/glib/gmain.c:4111
 #16 0x00007f9393369a0c in meta_run () at ../mutter/src/core/main.c:676
 #17 0x000055bc880f2426 in main (argc=<optimized out>, argv=<optimized out>) at ../gnome-shell/src/main.c:552

Related: https://gitlab.gnome.org/GNOME/mutter/-/issues/338
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/951

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1317
(cherry picked from commit e5ea8f54836ed2d041f0caa420ee1bcee0ff146a)
2020-06-16 16:27:02 +02:00
Daniel van Vugt
8b3f1117be backend-x11: Reintroduce XInitThreads
It was removed in 3.34 as part of 6ed5d2e2. And we thought that was the
only thread that might exist and use X11. But the top gnome-shell crasher
in 3.36 seems to suggest otherwise.

We don't know what or where the offending thread is, but since:

 1. We used XInitThreads for years already prior to 3.34; and

 2. Extensions or any change to mutter/gnome-shell could conceivably use
    threads to make X calls, directly or indirectly,

it's probably a good idea to reintroduce XInitThreads. The failing assertion
in libx11 is also accompanied by a strong hint:

```
fprintf(stderr, "[xcb] Most likely this is a multi-threaded client " \
                "and XInitThreads has not been called\n");
```

https://bugs.launchpad.net/bugs/1877075

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1252

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1256

(cherry picked from commit 1d5f9b6917517d6e777a652cfa5e648794dc632a)
2020-05-15 12:50:23 +02:00
Florian Müllner
48ffbb5824 Bump version to 3.34.6
Update NEWS.
2020-04-30 17:13:07 +02:00
Olivier Fourdan
129d134704 wayland: preserve xkb_state on VT switch
On VT switch, the devices are removed, which means for Wayland disabling
the keyboard.

When the keyboard is disabled, the associated `xkb_state` is freed and
recreated whenever the keyboard is re-enabled when switching back to the
compositor VT.

That means the `xkb_state` for Wayland is lost whereas the same for
clutter is kept, which causes to a discrepancy with locked modifiers on
VT switch.

To avoid that issue, preserve the XKB info only to dispose it when the
keyboard is eventually finalized.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/344
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1185
(cherry picked from commit 5b30a52bbda87f903d7008d09d1d70cd750cac4a)
2020-04-30 16:52:40 +02:00
Olivier Fourdan
4078ba1828 keybindings: Mask out the reserved modifiers mask
When switching layouts, special modifiers bits may be be set for
internal use by Xkb.

As we now ignore a set of modifiers when processing the special
modifiers keys, we ought to also mask out those reserved modifiers
otherwise we would discard the [Super] key after switching layouts
in X11.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/1144
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1219
(cherry picked from commit 61356caa0693f19ccb289597bbab5138319e7f3c)
2020-04-30 14:26:28 +00:00
Carlos Garnacho
fd8ccbac82 keybindings: Check the special modifiers specifically
Make sure it is only the special modifier (hardcoded to 1 currently)
which is being pressed (not counting locked modifiers) before notifying
that the special modifier is pressed, as we are interested in it being
pressed alone and not in combination with other modifier keys.

This helps in two ways:
- Pressing alt, then ctrl, then releasing both won't trigger the locate
  pointer action.
- Pressing alt, then ctrl, then down/up to switch workspace won't interpret
  the last up/down keypress as an additional key on top of the special ctrl
  modifier, thus won't be forwarded down to the focused client in the last
  second.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/812

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1014
(cherry picked from commit 23da6c2426932dcb2057849eec9e1d79c34fc405)
2020-04-30 14:26:27 +00:00
Laurent Bigonville
93417d0ceb compositor: Only include meta-window-actor-wayland.h when building with wayland
https://gitlab.gnome.org/GNOME/mutter/-/issues/1074

(cherry picked from commit d26dc4ae44c1fa921f9e3524ee540e62b3a0ace1)
2020-04-27 16:06:55 +02:00
Pekka Paalanen
3bafd23424 kms-impl/simple: Fix page_flip_data ref leak on fallback
If drmModePageFlip() or custom_page_flip_func fails, process_page_flip() was
forgetting to undo the ref taken for that call. This would leak page_flip_data.

The reference counting works like this:
- when created, ref count is 1
- when calling drmModePageFlip, ref count is increased to 2
- new: if flip failed, ref count is decreased back to 1
- if calling schedule_retry_page_flip(), it takes a ref internally
- if calling mode_set_fallback(), it takes a ref internally
- all return FALSE paths have an explicit unref
- return TRUE path has an explicit unref

This issue was found by code inspection and while debugging an unrelated issue
with debug prints sprinkled around. I am not aware of any end-user visible
issues being fixed by this, as the leak is small and probably very rare.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1209
(cherry picked from commit 36111270aa23dffdc757cb76f4ca01f3425bfbf2)
2020-04-24 14:18:49 +03:00
Pekka Paalanen
e328fcc379 kms: Make GSource ready by default
When testing a laptop with intel and DisplayLink devices, attempting to set the
DL output as the only active output resulted in GNOME/Wayland freezing. The
main event loop was running fine, but nothing on screen would get updated once
the DL output become the only one. This patch fixes that issue.

DisplayLink USB 3 devices use an out-of-tree kernel DRM driver called EVDI.
EVDI can sometimes fail drmModePageFlip(). For me, the flip fails reliably when
hotplugging the DL dock and when changing display configuration to DL only.
Mutter has a workaround for failing flips, it just calls drmModeSetCrtc() and
that succeeds.

What does not work reliably in the fallback path is Mutter keeping track of the
pageflip. Since drmModePageFlip() failed, there will not be a pageflip event
coming and instead Mutter queues a callback in its stead. When you have more
than one output, some other output repainting will attempt to swap buffers and
calls wait_for_pending_flips() which has the side-effect of dispatching any
queued flip callbacks. With multiple outputs, you don't get stuck (unless they
all fail the exact same way at the same time?). When you have only one output,
it cannot proceed to repaint and buffer swap because the pageflip is not marked
complete yet. Nothing dispatches the flip callback, leading to the freeze.

The flip callback is intended to be an idle callback, implemented with a
GSource. It is supposed to be called as soon as execution returns to the main
event loop. The setup of the GSource is incomplete, so it will never dispatch.

Fix the GSource setup by setting its ready-time to be always in the past. That
gets it dispatched on the next cycle of the main event loop. This is now the
default behavior for all sources created by meta_kms_add_source_in_impl().
Sources that need a delay continue to do that by overriding the ready-time
explicitly.

An alternative solution could have been to implement GSource prepare and check
callbacks returning TRUE. However, since meta_kms_add_source_in_impl() is used
by flip retry code as well, and that code needs a delay through the ready-time,
I was afraid I might break the flip retry code. Hence I decided to use
ready-time instead.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1209
(cherry picked from commit 6e0cfd3e55d554360b7e6963b39bcf996121847b)
2020-04-24 14:18:49 +03:00
Carlos Garnacho
e845bbd579 core: Add private function to get the current selection owner
This is a bit untidy to expose, however may be necessary internally.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1186

(cherry picked from commit fbd6366eddf39704fb79be608dd22cb3fad328e6)
2020-04-22 01:34:22 +02:00
Carlos Garnacho
025730349d x11: Allow X11 clients to clear the selection
According to the XSetSelectionOwner libX11 documentation:

  [...] If the owner window it has specified in the request is later
  destroyed, the owner of the selection automatically reverts to None,
  but the last-change time is not affected.

This is indeed visible through the selection_timestamp field in
XFixesSelectionNotify events.

Use this to check whether the selection time is recent-ish (thus
likely coming from an explicit XSetSelectionOwner request) and honor
the client intent by setting a "NULL" owner. If the selection time
is too old, it's definitely an indication of the owner client being
closed, the scenario where we do want the clipboard manager to take
over.

This fixes two usecases:
- X11 LibreOffice / WPS clear the selection each time before copying
  its own content. Mutter's clipboard manager would see each of those
  as a hint to take over, competing with the client over selection
  ownership. This would simply no longer happen
- Password managers may want to clear the selection, which would be
  frustrated by our clipboard manager.

There's a slight window of opportunity for the heuristics to fail
though, if a X11 client sets the selection and closes within 50ms, we
would miss the clipboard manager taking over.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1206

(cherry picked from commit 5671f0a284a5875f7d964a4d368470c33581ba80)
2020-04-22 01:27:19 +02:00
Carlos Garnacho
f6d0af0c93 x11: Generalize x11 selection owner checks
Shuffle things so the x11 selection can check the current owner directly,
instead of its type.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1206

(cherry picked from commit a7e63bea6cac06216ed2f2b98b7112d41b704c36)
2020-04-22 01:27:05 +02:00
Carlos Garnacho
8acff5309d x11: Clear X11 selection source after unsetting owner
The X11 selection source was being preserved after unsetting its
ownership. This is no leak as it would be eventually replaced by
another source, or destroyed on finalize. But it's pointless to
keep it.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1206

(cherry picked from commit 94b3c334e5a141f68911c6e69fa2dab49ff260b7)
2020-04-22 01:26:21 +02:00
Carlos Garnacho
0ab8b17433 x11: Forward current selection state when initializing X11 selections
Most visible with xwayland-on-demand, at the time of setting things up
for X11 selections, we don't forward the current state. This makes the
first started X11 app oblivious to eg. the current clipboard.

Syncing selections up at the time of initializing the X11 selection
stuff ensures that doesn't happen.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1186

(cherry picked from commit 167fd07e010e25feb7ff195706bf91d7c70d1273)
2020-04-22 01:26:21 +02:00
Sebastian Keller
50f383d2e9 x11-selection: Plug MetaSelectionSourceX11 leak
meta_selection_source_x11_new_finish() transfers the ownership of the
selection source, but source_new_cb() was not freeing it.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/998
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1001

(cherry picked from commit 8e6821bc6586c9bd8c917cc37c40686c28ca95ad)
2020-04-22 01:26:21 +02:00
Carlos Garnacho
7fbba4ad14 wayland: Rely on MetaSelection::owner-changed for .selection event emission
We already have a signal callback that translates selection ownership changes to
data_device/primary .selection events. Given both will be run when a data source
is being replaced, and this event emission being deleted is kinda short sighted
in that in only knows about Wayland, rely entirely on MetaSelection::owner-changed
emission.

Fixes spurious .selection(null) events being sent when a compositor-local source
takes over the selection without the focus changing (eg. screenshot to clipboard).

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1160

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1204

(cherry picked from commit 1363246d4452c0eebf404f2668df9931d06eae92)
2020-04-19 21:59:52 +02:00
Carlos Garnacho
eb6189d6b6 wayland: Do not cancel old data source when setting new selection
This is taken care already by the MetaSelection machinery, by
deactivating the previous selection source when setting a new one.
That works across X11 and internal selection sources. This
only works when replacing one wayland source with another, and
actually results in doubly .cancelled events due to the other
paths.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1177

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1203

(cherry picked from commit 0b6560fac41beaf08d89d30b4450dc7318c5a740)
2020-04-19 21:59:43 +02:00
Carlos Garnacho
668d13ffb5 wayland: Shuffle wl_data_source.cancelled version checks on DnD
We are meant to send a .cancelled event after the drop is performed
in certain situations, but only for version>3 clients. Since this is
all version 3 business, only set the drop_performed flag for v3
clients. This drops the need to perform version checks at the time
of cancelling (which is present for other usecases in v1).

Fixes emission of wl_data_source.cancelled for v1 clients.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1177

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1203

(cherry picked from commit d4c3870286353e58d7e4c95111f1cdd354ba17ce)
2020-04-19 21:59:35 +02:00
Carlos Garnacho
02947e7872 core: Cater for reading selection in chunks
For the cases where we read a fixed size from the selection (eg. imposing
limits for the clipboard manager), g_input_stream_read_bytes_async() might
not read up to this given size if the other side is spoonfeeding it content.

Cater for multiple read/write cycles here, until (maximum) transfer size is
reached.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1198

(cherry picked from commit 4bdf9a1e70e8aef0066fb3af72ad580069b02fa1)
2020-04-19 21:59:27 +02:00
Carlos Garnacho
ebfe5e44c2 x11: Do not trust there is task in error paths
Flushing the X11 selection output stream may happen synchronously or
implicitly, in which case there is not a task to complete. Check there
is actually a task before returning errors. We additionally set the
pipe_error flag, so future operations will fail with an error, albeit
with a more generic message.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1198

(cherry picked from commit 1909977a6787d6e06d4931df158b821f6fb35ad1)
2020-04-19 21:59:20 +02:00
Carlos Garnacho
8f64b3dcad x11: Don't stall on write_async()
If a write_async() comes up while we are flushing on the background,
the task will be queued, but not deemed a reason on itself to keep
flushing (and finish the task) after a property delete event.

To fix this, do not ever queue up write_async tasks (this leaves
priv->pending_task only used for flush(), so the "flush to end"
behavior in the background is consistent). We only start a
background flush if there's reasons to do it, but the tasks are
immediately finished.

All data will still be ensured to be transfered on flush/close,
this makes the caller in this situation still able to reach to it.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1198

(cherry picked from commit 655a783891ac38c01834cb6d9631aa5834666892)
2020-04-19 21:59:11 +02:00
Carlos Garnacho
8de5b95123 x11: Fix iterative INCR property checks
It does not make sense to check for the stream not being closed,
this might happen multiple times during the lifetime of the stream
for a single transfer. We want to notify the INCR transfer just
once.

Check for the explicit conditions that we want, that the remaining
data is bigger than we can transfer at once, and that we are not
yet within the INCR transfer.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1198

(cherry picked from commit a4596becc43959c3cd049fd49a236a9920fd9f24)
2020-04-19 21:59:02 +02:00
Carlos Garnacho
cedab9442f x11: Don't exceed transfer size in INCR chunks
The stream automatically flushes after data size exceeds the
size we deem for INCR chunks, but we still try to copy it all.
Actually limit the data we copy, and leave the rest for future
INCR chunks.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1198

(cherry picked from commit 7015bb3efd5e588e50be9948f32ee04fa4bd8319)
2020-04-19 21:58:53 +02:00
Carlos Garnacho
7cc5ed96fc x11: Don't invariably queue a pending delete request
We don't need doing this roundtrip for non-INCR transfers.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1198

(cherry picked from commit d2c762cc66718f1b79bb476b68439d00a16fd2a2)
2020-04-19 21:58:44 +02:00
Carlos Garnacho
bb831f04c5 x11: Finish INCR transfers properly
INCR transfers are mandated to finish with a final 0-size XChangeProperty
roundtrip after the final data chunk. Actually honor this and ensure we
iterate just once more for this.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1198

(cherry picked from commit 04d429b743a641c81e2fd8b683a8ec40775b3213)
2020-04-19 21:58:34 +02:00
Carlos Garnacho
c92267feb2 x11: Wait till data is flushed before notifying on the pending task
It does not make sense to notify flushes mid-transfer. We should wait
till the data is actually finished before notifying on the pending
task.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1198

(cherry picked from commit 0b21dcfe08c9a3ac137da518d6ef5f3a80528883)
2020-04-19 21:58:24 +02:00
Carlos Garnacho
8240aba80f x11: Only send SelectionNotify on first INCR chunk
This should only be sent if the selection can be sent at once, or
if we are right about to notify on the first chunk of an INCR
transfer.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1198

(cherry picked from commit 7c939d78c2b20989412a710665cbbea6b12ff8dd)
2020-04-19 21:58:13 +02:00
Carlos Garnacho
5f34a0f245 x11: Ensure flush() Flushes all output stream data
This seemed to work under the assumption that a flush() call can
only result in one INCR roundtrip. This is evidently not true, so
we should hold things off until all pending data is actually flushed.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1198

(cherry picked from commit 8a2b82897db66b3edbe985a370429b4f36b9918c)
2020-04-19 21:58:05 +02:00
Carlos Garnacho
83eeb3dbd2 x11: Unset pending flush flag right before notifying on task
Together with some other state. We can do this altogether on task
notification, instead of lost somewhere in this function flow.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1198

(cherry picked from commit e95c365cf01837862f87dea90190b47392ee7f67)
2020-04-19 21:57:56 +02:00
Carlos Garnacho
c25011ffba x11: Intern INCR atom
We want to use it, despite it not existing previously.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1198

(cherry picked from commit a32cb7133b1dc97f02ad20496fd03908f0d9328e)
2020-04-19 21:57:46 +02:00
Carlos Garnacho
abd67819fe x11: Flag flushes despite having less than the element size
If say we want 32bit data, but have 2 bytes stored, we would simply
ignore flush requests. Allow (and don't clear) the needs_flush flag
if we have less than the element size accumulated.

Instead handle this in can_flush(), so it's triggered whenever we
have enough data to fill 1 element, or if the stream is closing
(seems a broken situation, but triggered by the caller).

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1198

(cherry picked from commit 967966cdee13306501eacd3f25791f56d1fc8249)
2020-04-19 21:57:36 +02:00
Carlos Garnacho
6f3b7b733a x11: XMaxRequestSize returns 4-byte units
XMaxRequestSize/XMaxExtendedRequestSize are documented to return
the maximum size in 4-byte units, whereas we are comparing this
to byte lenghts. We can afford 4x the data here.

Since I don't know the payload size of the XChangeProperty request,
be generous and allot 400 bytes for it, we have some to spare.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1198

(cherry picked from commit 06d67b6abfd4d5ed8ceecd998b08cd1103946f26)
2020-04-19 21:57:26 +02:00
Florian Müllner
e2c61f2739 window: Really propagate effective on-all-workspaces setting to transients
Commit cda9579034b fixed a corner case when setting the initial workspace
state of transient windows, but it still missed a case:

should_be_on_all_workspaces() returns whether the window should be on all
workspaces according to its properties/placement, but it doesn't take
transient relations into account.

That means in case of nested transients, we can still fail the assert:

 1. on-all-workspaces toplevel
 2. should_be_on_all_workspaces() is TRUE for the first transient's parent,
    as the window from (1) has on_all_workspaces_requested == TRUE
 3. should_be_on_all_workspaces() is FALSE for the second transient's
    parent, as the window from (2) is only on-all-workspace because
    of its parent

We can fix this by either using the state from the root ancestor
instead of the direct transient parent, or by using the parent's
on_all_workspaces_state.

The latter is simpler, so go with that.

https://gitlab.gnome.org/GNOME/mutter/issues/1083
2020-04-09 00:35:36 +02:00
Florian Müllner
1a3dfd8110 Bump version to 3.34.5
Update NEWS.
2020-03-31 01:17:00 +02:00
Carlos Garnacho
aeb781acd6 x11: Handle windowing errors while writing selection INCR data
This error was just logged but not raised. Do as the code comment said
and raise a pipe error at that moment, and for subsequent operations
on the output stream (although none besides close() should be expected
after propagating the error properly).

Related: https://gitlab.gnome.org/GNOME/mutter/issues/1065

(cherry picked from commit 2ecbf6d74637508203290c0e324d736de10a9174)
2020-03-30 16:35:12 +02:00
Robert Mader
092591b872 core: Demote tiff and bmp image formats in the clipboard manager
Support for them appears to be way less common than e.g. png, which is
currently the preferred format from Firefox, Chromium, Libreoffice and others.
Adopt to that fact.

As a side effect, this works around a bug observed when copying images in
Firefox on Wayland.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1141

(cherry picked from commit 6aa546145fe614d15f23f2a022637fa72bb50149)
2020-03-29 12:41:38 +02:00
Jonas Ådahl
57992f37cc wayland: Don't crash when trying to fullscreen on inert wl_output
There is a race where an output can be used as a fullscreen target, but
it has already been removed due to a hotplug. Handle this gracefully by
ignoring said output in such situations.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1120


(cherry picked from commit 512bb7d1cd0836e6d110609a16fdbf9f9f5b30df)
2020-03-12 20:46:43 +00:00
Jonas Ådahl
7655a63af6 kms-impl-device: Clean up state if drm resources disappear
It may happen that drmModeGetResources() starts returning NULL. Handle
this gracefully by removing all connectors, CRTCs and planes making the
device in practice defunct.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1121


(cherry picked from commit 5319949a45bb22f5c998b485e955c1ddd13810f3)
2020-03-12 20:45:55 +00:00
Pekka Paalanen
a5b5e95ad9 cursor-renderer/native: Handle GPU hotplug
Listen for GPU hotplug events to initialize their cursor support.

This fixes one reason for why DisplayLink devices may not be using a hardware
cursor. Particularly, when a DisplayLink device is hotplugged for the first
time such that EVDI creates a new DRM device node after gnome-shell has already
started, we used to forget to initialize the cursor support.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/1097
(cherry picked from commit 8abdf16a3992e3332f2378ea7c65e6e251e418e0)
2020-03-10 11:48:40 +02:00
Pekka Paalanen
11da42b2f8 cursor-renderer/native: Refactor init to per-gpu
Extract the code to initialize a single GPU cursor support into its own
function. The new function will be used by GPU hotplug in the future.

This is a pure refactoring without any behavioral changes.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/1097

Backported from 4cc29cfb619102a8e7cd32731205c8018d83544e.
2020-03-10 11:47:23 +02:00
Olivier Fourdan
2709a4ffb1 wayland/data-device: Fix crash with offer from X11 client
If a data offer comes from an X11 client, the Wayland resource would be
NULL, causing a crash in `data_offer_choose_action()` trying to get the
resource version.

So instead of doing the version check in `data_offer_choose_action()`,
do it early when creating the data source.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/1057
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1073

(cherry picked from commit f9326cfa3d5f0fd9f63f561d6dfbb92a8f6fb34a)
2020-02-23 18:19:23 +01:00
Olivier Fourdan
c65db40178 wayland/data-device: Check resource version on cancel
For clarity, check the resource version needs the "cancelled" message in
the actual vmethod rather than from the caller function.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/1073

(cherry picked from commit 963108a9a6a0a3a811945da5354eafe0b86ffde2)
2020-02-23 18:18:59 +01:00
Jonas Ådahl
011ff15603 window-actor: Don't show actor until meta_window_actor_show()
By default clutter will show an actor as it is added to a parent. This
means that after we create the window actor, when it's added to the
window group, we implicitly show it. What we really want is to not show
it until the window is supposed to be shown, which happens when
meta_window_actor_show() is called, as showing prior to that, could
cause issues.

Avoid the implicit show by setting the "show-on-set-parent" property on
the window actor to `FALSE` on window actor construction.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/1066
2020-02-20 01:27:50 +01:00
Florian Müllner
c3d2f3f399 window: Ignore requests to be placed on non-existent workspaces
When an X11 window requests an initial workspace, we currently trust
it that the workspace actually exists. However dynamic workspaces
make this easy to get wrong for applications: They make it likely
for the number of workspaces to change between application starts,
and if the app blindly applies its saved state on startup, it will
trigger an assertion.

Make sure that we pass valid parameters to set_workspace_state(),
and simply let the workspace assignment fall through to the default
handling otherwise.

https://gitlab.gnome.org/GNOME/mutter/issues/1029
2020-02-20 01:26:41 +01:00
Yi-Jyun Pan
053bb5901a Update Chinese (Taiwan) translation 2020-02-19 03:08:50 +00:00
Florian Müllner
0bce4323c7 Bump version to 3.34.4
Update NEWS.
2020-02-16 15:49:35 +01:00
Olivier Fourdan
b2bc345463 wayland/subsurface: Keep subsurface actors reactive
The actors of Wayland subsurfaces are set to be reactive on creation,
when receiving the `wl_subcompositor.get_subsurface` request.

However, if a client creates several subsurfaces and then creates the
xdg_toplevel object after, the previous subsurface actors are reset.

As a result, Clutter picking will skip and ignore those actors in
`clutter_actor_should_pick_paint()` because they aren't marked as
reactive anymore.

An example of such a client being affected by this issue is SCTK, the
Rust library implementing client side decorations for Wayland used
internally by winit and alacritty.

Move the `set_reactive()` call from `get_subsurface()` to the subsurface
`sync_actor_subsurface_state()` vfunc to make sure those remain reactive
even after `xdg_surface.get_toplevel` is invoked.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/1024
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1040


(cherry picked from commit 934a829a57d0b00c5eef8d405473e8a56923cd22)
2020-02-10 09:02:30 +00:00
Robert Mader
2235629d25 core: Extend list of image formats to be stored in the clipboard manager
These types are probably common enough to support.

See also:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Complete_list_of_MIME_types

https://gitlab.gnome.org/GNOME/mutter/merge_requests/1034

(cherry picked from commit b91d66bf983c427edfa65914a188a4fc263dadbc)
2020-02-04 00:27:46 +01:00
Carlos Garnacho
59da900a45 core: Define specific image formats to be stored in the clipboard manager
And order those preferences in order of lossiness (jpeg < png < bmp). This
avoids us from prefering other formats that are not useful or widely
recognized.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/939

(cherry picked from commit 832c0fb0ea79d4cf904b1519b11ef0b11cbbfbdc)
2020-02-04 00:27:17 +01:00
Carlos Garnacho
0e0dae2774 core: Demote image formats' priority from preservation in clipboard manager
Most usually, applications either expose clipboard content either as text
or as images, so the prioritization here is pointless. However there's some
outliers like LibreOffice Calc which exports content as both image and text
formats (besides other internal ones).

In that mixed case, we probably prefer to keep text formats, rather than
image based ones.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/919

(cherry picked from commit 2fbbf657d51f14bdcb75c045637e6ebf4df10063)
2020-02-04 00:26:39 +01:00
Georges Basile Stavracas Neto
4959ae8bc4 clutter/brightness-contrast-effect: Compare float with G_APPROX_VALUE
Nobody should ever compare float for equality. Use G_APPROX_VALUE to
check that.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/992

(cherry picked from commit 84ea4ad9902bae6542fb657ce9e12c1038b697fc)
2020-02-02 17:50:30 +01:00
Georges Basile Stavracas Neto
aea5541ffa clutter/offscreen-effect: Clear offscreen when pre-paint fails
Some ClutterOffscreenEffect subclasses, such as ClutterBrightnessContrastEffect,
early-return FALSE in pre-paint before chaining up. It's an important optimization
that avoids creating or updating the offscreen framebuffer.

However, if an offscreen framebuffer already exists by the time pre-paint fails,
it will be used *without* repaint the actor over it. That causes an old picture
of the actor to be displayed.

Fix that by always clearing the offscreen framebuffer when pre-paint fails.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/810

https://gitlab.gnome.org/GNOME/mutter/merge_requests/992

(cherry picked from commit 64685f4b20162b78964a5ab6fd57a93fb3860671)
2020-02-02 17:49:34 +01:00
Georges Basile Stavracas Neto
47fe7ac25b clutter/offscreen-effect: Clear offscreen framebuffer when disabling
When changing the 'enabled' property and disabling the offscreen effect,
it doesn't make sense to preserve the offscreen framebuffer. It's not
drawing, after all.

Furthermore, because ClutterOffscreenEffect only checks if the offscreen
framebuffer exists to decide whether or not to redraw, keeping the fbo
alive is a waste of resources.

Clear the offscreen framebuffer when the effect is disabled or enabled.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/810

https://gitlab.gnome.org/GNOME/mutter/merge_requests/992

(cherry picked from commit bf594e9fb6d973259163f73881dd91c8910dd54f)
2020-02-02 17:31:46 +01:00
Georges Basile Stavracas Neto
d35d7fb618 clutter/offscreen-effect: Use g_clear_pointer for cleanup
It does the exact same checks, and saves us a few lines of code.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/992

(cherry picked from commit 3958e75ed2a9afb5d32c59b017691e3ed2289ee2)
2020-02-02 17:31:46 +01:00
Carlos Garnacho
666bd25005 wayland: Handle dragging from/dropping to v1 data device users
Interoperation between wl_data_device_manager v1 and v3 got broken
at some point. Ensure that we resort to the "copy" action if either
the drop site or the drag source are from a client that requested v1.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/965

(cherry picked from commit ffad55c66f5b131cdaa92ef61c44d99b7c7312b5)
2020-02-01 16:30:25 +01:00
Robert Mader
208fd1b083 wayland/data-device: Small style fixes
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1031

(cherry picked from commit 15b46a6f882e910913d56c118b036309f1ce81ec,
to keep future backports easy)
2020-01-31 15:21:18 +01:00
Robert Mader
12152c7edb wayland/data-device: Guard against a potential crash
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1031

(cherry picked from commit c27fc3537b3fb83d1551b72b2fc468567c79e6e0)
2020-01-31 15:20:55 +01:00
Robert Mader
de7782221a wayland/data-device: Cancel drag source when the drag finished unsuccessfully
When a drag was performed but did not finish successfully, e.g. because no
mimetype was accepted, we need to send the source cancel event so clients
know they can destroy the drag source (since version 3).

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/740

https://gitlab.gnome.org/GNOME/mutter/merge_requests/1031

(cherry picked from commit 6cc748cce9bb7cb47a4098cdc251c554d9f99b6b)
2020-01-31 15:20:20 +01:00
Carlos Garnacho
651d2a57f8 wayland: Check focus surface client in wl_data_device.set_selection()
Similar to our handling in set_primary(), ignore set_selection() requests
that come from unfocused clients.

https://gitlab.gnome.org/GNOME/mutter/issues/878

(cherry picked from commit e865fcc460d7666873475f7bb9efc7fd4b336ab8)
2020-01-31 15:18:42 +01:00
Carlos Garnacho
e18aa564b0 wayland: Clean up meta_wayland_data_device_set_primary()
This function is already checking for the focus surface client
matching the requestor. The type check was slightly bogus though
as it'd be an screwup in our code, make it an assert instead.

Also, move the check for the client having the focus into the
upper call, so this and wl_data_device.set_selection code can
get more in line.

https://gitlab.gnome.org/GNOME/mutter/issues/878

(cherry picked from commit 16eb46105425a9a677c408f5a19e1bebae88a602)
2020-01-31 15:18:16 +01:00
Carlos Garnacho
4cc5b85c5d wayland: Flatten data source object hierarchy
We have an abstract MetaWaylandDataSource and 2 subclasses for
clipboard/primary data sources. Since the abstraction provided
by the additional sublevel is arguable, push the wl_resource
field up, and leave us with just 2 objects to think about, all
of them containing a wl_resource.

https://gitlab.gnome.org/GNOME/mutter/issues/878

(cherry picked from commit c11ef6ef079eeaa8024c8703bbe432356d06388a)
2020-01-31 15:17:43 +01:00
Adam Jackson
ca5ed7369d cogl: Fix GLES2 fallback
Say you're using intel gen3, you poor soul. Your big-GL maxes out at 1.5
unless you use dirty tricks, but you do have GLES2. We try to fall back
to GLES in this case, but we only ever say eglBindAPI(EGL_OPENGL_API).
So when we go to do CreateContext, even though we think we've requested
GLES 2.0, the driver will compare that "2.0" against the maximum big-GL
version, and things will fail.

Fix this by binding EGL_OPENGL_ES_API before trying a GLES context.

https://gitlab.gnome.org/GNOME/mutter/issues/635

(cherry picket from commit f4f7e31303d78b2a8a0881b61311b8d750301b8f)
2020-01-27 17:09:09 +01:00
Carlos Garnacho
5ae317e004 wayland: Do not check current offer on DnD button release
This check was added on commit 48639ac5 as a means to disregard
DnD drops where the offer would disappear beforehand. However since
that commit was all about wl_data_device_manager version < 3,
forgetting about the selected mimetype seems a behavior more inline
with those versions.

Since no current drop is something expected on X11 drop sites, fixes
DnD over those, while keeping the original bug fixed.

Found by Robert Mader (https://gitlab.gnome.org/GNOME/mutter/issues/974#note_688144)

https://gitlab.gnome.org/GNOME/mutter/issues/974
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1005

(cherry picked from commit 30bf588a38c326897efb8637aad5dfeb0cafe5c9)
2020-01-27 15:28:57 +01:00
Carlos Garnacho
21dca32934 xwayland: Set XDND source-side actions as per XDND
In XDND, we just get a hint on XdndPosition about what's the action
chosen by the user. Make the data source actions the full set on
XdndEnter (as we can't know better), and pass the hint in XdndPosition
as the user chosen action as it should be.

Makes Wayland drop sites aware of the user action as per XDND with X11
drag sources, and still makes modifiers during DnD work.

https://gitlab.gnome.org/GNOME/mutter/issues/974
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1005

(cherry picked from commit 090a6ad409ce0ea0bcf30b66cb1048dfdb86ab9e)
2020-01-27 15:28:30 +01:00
Carlos Garnacho
41c6e1375b x11: Map x11 (UTF8_)STRING requests to text/plain mimetypes
Make the x11 selection proxy map UTF8_STRING and STRING to proper
mimetypes, as the selection source (wayland or memory) might not
offer those for backwards compatibility.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1355
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1005

(cherry picked from commit a6c195b05cb000e061a539b9df3e60f9ae0267fb)
2020-01-27 15:28:03 +01:00
Carlos Garnacho
d38c30c128 wayland: Preserve XdndTypeList for future callers
This Xdnd property is owned by the drag source, we shouldn't delete
it when reading/proxying it to Wayland clients.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/2347
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1005

(cherry picked from commit c1df48befd254684f0c2969b0656af03d0de024a)
2020-01-27 15:27:11 +01:00
Adam Jackson
59e9b073a5 renderer-native: Fix memory leak in secondary GPU update
Leaking a texture object and a framebuffer object every time you update
the secondary GPU is perhaps not the best plan.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/1011


(cherry picked from commit 545fcb3dbff00adf1899012524926730a8c23572)
2020-01-21 14:47:09 +00:00
Sebastian Keller
6b6e724425 shaped-texture: Plug region leak
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1002


(cherry picked from commit b30a29f830c3580bdf5a9b4757f4984691af7f58)
2020-01-21 14:26:15 +00:00
Carlos Garnacho
156dd576f4 x11: Iterate over selections in a safer manner for event handling
It might be the case that handling an event induces the stream to
trigger completion, hence removing itself from the list. In that
case we would operate on the no longer valid list element to fetch
the next one.

Keep a pointer to the next element beforehand, so we can tiptoe
over streams that did remove themselves.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/869
(cherry picked from commit 45a8806e652346523cb66fb4777e15b63aa90c2a)
2020-01-17 13:57:31 +01:00
Carlos Garnacho
4d0a331cfe x11: Detach selection streams on dispose
The streams were only detached from MetaX11Display (and its event handling)
on completion. This is too much to expect, and those might be in some
circumstances replaced while operating.

Make those streams detach themselves on dispose(), so we don't trip into
freed memory later on when trying to dispatch unrelated X11 selection events.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/869
(cherry picked from commit e1fa0734a9985c06b5a9cbd031d3563ad463904b)
2020-01-17 13:57:24 +01:00
Jonas Ådahl
01d93f2819 kms-impl-simple: Handle mode set race conditions gracefully
If we end up trying to do a mode set on a DRM state that has already
changed behind our back without us yet having seen the hotplug event we
may fail with `EINVAL`. Since the renderer layer doesn't handle mode set
failure, it'll still try to page flip later on, which will then also
fail. When failing, it'll try to look up the cached mode set in order to
retry the mode set later on, as is needed to handle other error
conditions. However, if the mode set prior to the page flip failed, we
won't cache the mode set, and the page flip error handling code will get
confused.

Instead of asserting that a page flip always has a valid cached mode set
ready to look up, handle it being missing more gracefully by failing to
mode set. It is expected that things will correct themself as there
should be a hotplug event waiting around the the corner, to reconfigure
the monitor configuration setting new modes.

Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/917

https://gitlab.gnome.org/GNOME/mutter/merge_requests/1007
(cherry picked from commit ce3409b2b7f887ca2e83c939ff73ba4d3bc8c4c0)
2020-01-16 16:02:42 +01:00
Jonas Ådahl
be777dbd79 kms-impl-simple: Include mode name in error message
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1007
(cherry picked from commit 7733f8816810780ad857bce0d59ee65920e6989e)
2020-01-16 16:02:42 +01:00
Jonas Ådahl
a9a0110818 wayland/actor-surface: Always consider unmapped actors not on output
This avoids using bogus geometric values from an unmapped actor to
determine whether an actor is on a logical monitor or not. This would
happen when committing to a subsurface of a yet to be mapped toplevel.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/961
(cherry picked from commit 6d15231f10a22ee96f32dee9df8db8296c73376f)
2020-01-16 08:54:31 +01:00
Jonas Ådahl
fd7d0fb339 wayland/surface: Move shaped-texture synchronization to actor surface
As with most other state that ends up being pushed to the actor and the
associated shaped texture, also push the texture and the corresponding
metadata from the actor surface. This fixes an issue when a toplevel
surface was reset, where before the subsurface content was not properly
re-initialized, as content state synchronization only happened on
commit, not when asked to synchronize.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/961
(cherry picked from commit f0df07cba3ca308b47c9aefcc8112e8880fd9950)
2020-01-16 08:54:31 +01:00
Jonas Ådahl
1671692590 wayland/surface-actor: Reset and sync subsurface state when resetting
A actor surface may be reset by an xdg_toplevel if a NULL buffer is
attached. This should reset the actor state of the toplevel to an empty
state, while unmapping the previous actor. Subsurfaces, however, should
stay intact, including their relationship to the toplevel. They should
also not be yanked away from the actor of the actor surface prior to it
resetting, so that a window-destroy animation can include the subsurface
actor.

This fixes a potential crash when a subsurface tries to commit to its
wl_surface after the destroy animation of the toplevel has finished, as
the actor would at that point have been destroyed and cleared from the
actor surface struct, causing a segmentation fault.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/961
(cherry picked from commit fe7bece31e9462b8018f7d9cc5122dcb23ece2cd)
2020-01-16 08:54:31 +01:00
Jonas Ådahl
06fc756f0f shaped-texture: Make setting the same texture a no-op
Will be helpful when pushing state to the shaped texture, letting the
one pushing not have to care about checking if anything changed.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/961
(cherry picked from commit 3969285e5cf1068c26775d3fcc9c2c95e61ac467)
2020-01-16 08:54:31 +01:00
Jonas Ådahl
81b7196ad9 shaped-texture: Minor clean up
Use cogl_clear_object(), add reference to texture when setting, and
remove redundant runtime type check.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/961
(cherry picked from commit 60ebf19c9ed3d340330f643d9ebdaa20838f5ebd)
2020-01-16 08:54:31 +01:00
Jonas Ådahl
e91b12fdf9 wayland: Replace manual GNode subsurface iteration with macro
Similar to wl_list_foreach(), add
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE() that iterates over all the
subsurfaces of a surface, without the caller needing to care about
implementation details, such as leaf nodes vs non-leaf nodes.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/961
(cherry picked from commit fcfe90aa9fe0db130c94ae3fe5cee38daba20a50)
2020-01-16 08:54:31 +01:00
Jonas Ådahl
f52c0a3bf7 wayland/egl-stream: Cache texture snippet
While it's not very relevant now, as we would rarely create it anyway
since the buffer nor texture never changes for a surface, it will be in
the future, as the actor state (including its content,
MetaShapedTexture) will be synchronized by the MetaWaylandActorSurface
at a later point in time, and not by MetaWaylandSurface, at state
application time.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/961
(cherry picked from commit 76ee026caa1ab0215be389e4a33a6994ce3d26fc)
2020-01-16 08:54:31 +01:00
Umarzuki Bin Mochlis Moktar
78a45e1813 Update Malay translation 2020-01-08 15:06:57 +00:00
Florian Müllner
4947e8ae5b Bump version to 3.34.3
Update NEWS.
2020-01-05 12:37:05 +01:00
Sebastian Keller
5724310899 clutter/stage: Fix picking of rectangles with negative positions
FLT_MIN is the smallest *positive* number above 0 that can be
represented as floating point number. If this is used to initialize the
maximum x/y coordinates of a rectangle, this will always be used if all
x/y coordinates of the rectangle are negative. This means that picking
at 0,0 will always be a hit for such rectangles.

Since mutter creates such a window for server side decorations on X11,
this window will always be picked at 0,0 preventing clicking/hovering
the activities button in gnome-shell at that coordinate.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/893


(cherry picked from commit 674f52ba747b59a7e72a4a18fea763ee9e617b7c)
2019-12-24 16:52:37 +00:00
Pascal Nowack
9772f084bf screen-cast: Fix window recording on HiDPI
Using the same scale for the window as the
logical monitor only works correctly when having
the experimental 'scale-monitor-framebuffer'
feature enabled.
Without this experimental feature, the stream
will contain a black screen, where the actual
window only takes a small part of it.

Therefore, use a scale of 1 for the non-
experimental case.

Patch is based on commit 3fa6a92cc5dda6ab3939c3e982185f6caf453360.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/976


(cherry picked from commit e89cea8e5a9c944919cc0632b88bd68432778806)
2019-12-18 19:54:03 +00:00
Florian Müllner
8b087cfe56 Bump version to 3.34.2
Update NEWS.
2019-12-11 20:05:26 +01:00
Bruce Cowan
c05328f76a Update British English translation 2019-12-11 10:25:27 +00:00
Tim Crawford
868a617907 backends/native: Fix double free of error
error is an autoptr, so must not be explicitly freed.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1852
Fixes: 5c500ad402194 ("backend: Move GPU ownership from the monitor manager to the backend")

https://gitlab.gnome.org/GNOME/mutter/merge_requests/960


(cherry picked from commit d70ddc65ea923d14dfa8f5b1f486455e6b6234b6)
2019-12-06 19:56:51 +00:00
Pekka Paalanen
6f02d2ead0 kms-impl/simple: Fix meta_set_fallback_feedback_idle
Presumably this function is supposed to be like
meta_kms_impl_simple_handle_page_flip_callback() but the condition in the
if-statement is inverted. Fix the inversion to make these two functions look
alike.

This is part 2 of 2 fixing a complete desktop freeze when drmModePageFlip()
fails with EINVAL and the fallback to drmModeSetCrtc() succeeds but the success
is not registered correctly as completed "flip". The freeze occurs under
wait_for_pending_flips() which calls down into meta_kms_impl_device_dispatch()
which ends up poll()'ing the DRM fd even though drmModeSetCrtc() will not
produce a DRM event, hence the poll() never returns. The freeze was observed
when hotplugging a DisplayLink dock for the first time on Ubuntu 19.10.

This patch makes meta_set_fallback_feedback_idle() actually end up calling into
notify_view_crtc_presented() which decrements
secondary_gpu_state->pending_flips so that wait_for_pending_flips() can finish.

CC stable: gnome-3-34

https://gitlab.gnome.org/GNOME/mutter/merge_requests/953
(cherry picked from commit 832a522cce4a40a520d21b1c67472a6e4d2ea382)
2019-12-06 17:27:15 +01:00
Pekka Paalanen
fc77efbcd7 kms: Process impl idle callbacks before pre dispatch flush
mode_set_fallback() schedules a call to mode_set_fallback_feedback_idle(), but
it is possible for Mutter to repaint before the idle callbacks are dispatched.
If that happens, mode_set_fallback_feedback_idle() does not get called before
Mutter enters wait_for_pending_flips(), leading to a deadlock.

Add the needed interfaces so that meta_kms_device_dispatch_sync() can flush all
the implementation idle callbacks before it checks if any "events" are
available. This prevents the deadlock by ensuring
mode_set_fallback_feedback_idle() does get called before potentially waiting
for actual DRM events.

Presumably this call would not be needed if the implementation was running in
its own thread, since it would eventually dispatch its idle callbacks before
going to sleep polling on the DRM fd. This call might even be unnecessary
overhead in that case, synchronizing with the implementation thread needlessly.
But the thread does not exist yet, so this is needed for now.

This is part 1 of 2 fixing a complete desktop freeze when drmModePageFlip()
fails with EINVAL and the fallback to drmModeSetCrtc() succeeds but the success
is not registered correctly as completed "flip". The freeze occurs under
wait_for_pending_flips() which calls down into meta_kms_impl_device_dispatch()
which ends up poll()'ing the DRM fd even though drmModeSetCrtc() will not
produce a DRM event, hence the poll() never returns. The freeze was observed
when hotplugging a DisplayLink dock for the first time on Ubuntu 19.10.

CC stable: gnome-3-34

https://gitlab.gnome.org/GNOME/mutter/merge_requests/953
(cherry picked from commit 79491df2b8d90af3011d6a3a29b0d63ad52677f8)
2019-12-06 17:27:14 +01:00
Florian Müllner
c0e76186da stack: Allow promoting transient windows to their parent's layer
When a window that should be stacked above another one is placed in a lower
layer than the other window, we currently allow promoting it to the higher
layer when it has a "transient type". We should do the same when the window
is an actual transient of the other window.

This is particularly relevant for wayland windows, where types play a
much smaller role: Transient windows like non-modal dialogs (and since
commit 666bef7a, popup windows as well) currently end up underneath their
always-on-top parent.

https://gitlab.gnome.org/GNOME/mutter/issues/587


(cherry picked from commit 1c89fce30e0f478f11f90221ddb6b831d7f0f5e8)
2019-11-29 14:18:59 +00:00
Robert Mader
1b75d78c72 shaped-texture: Do not invalidate content on set_cogl_texture()
This was wrongly introduced in 75cffd0ec4. As the comment above explains, we
only want to queue redraws in response to surface/buffer damage.

This triggered a full redraw when using DMA buffers on Wayland as we currently
create a new texture on every buffer_attach(), breaking partial invalidation.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/947


(cherry picked from commit 0247d35e5a8e642cb093fcda1c5645e49a769f4b)
2019-11-26 22:43:54 +00:00
Jonas Dreßler
cbbffd1db7 cursor-tracker: Add API to keep the wayland pointer focus while hidden
Since commit a2a8f0cda we force the focus surface of the
meta-wayland-pointer to NULL while the pointer is invisible. This
introduced an issue with the a11y magnifier of the shell, which uses
`meta_cursor_tracker_set_pointer_visible` to hide the real cursor and
show its own magnified cursor at the correct position: Because the
meta-wayland-pointer is still used to communicate with Wayland clients,
the UI of the windows will not respond to mouse movement anymore as
soon as the real cursor is hidden.

Fix this issue for now by adding an additional method to the
cursor-tracker which allows disabling the behavior commit a2a8f0cda
introduced.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/832
2019-11-25 16:15:14 +01:00
Marco Trevisan (Treviño)
06202c342b device-manager-x11: Ignore events if no source device is set
There might be some inconsistent event for which we don't have a known
source device.

In the current state we don't handle them and we could crash when getting
the current device tool.

So, add an utility function that retrieves the source device for an event
that warns if no device is found, and use this for Motion, Key and Button
events.

In case we don't have a valid source in such case, just return early instead
of trying to generate invalid clutter events.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/823


(cherry picked from commit 427670cc638d02f84897ae7fa174de4ac995e7dc)
2019-11-23 01:47:33 +00:00
Robert Mader
9c372388da clutter/cally-root: Use g_clear_signal_handler and fix a signal leak
This commit was split out from `cleanup: Use g_clear_signal_handler()
where possible` as it fixes an actual signal leak and should therefore
get backported to stable releases.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/940
2019-11-21 16:22:14 +01:00
Carlos Garnacho
7e741fe2d2 wayland: Move "ownership" of the DnD selection source to the data device
On wl_data_source destruction we used to indirectly unset the DnD selection
owner via the wl_resource destructor triggering the destruction of the
MetaWaylandDataSource, which would be caught through the weak ref set by
the MetaWaylandDragGrab.

This works as long as the grab is held, however we have a window between
the button being released and the drop site replying with
wl_data_offer.finish that the MetaWaylandDataSource is alive, but its
destruction wouldn't result in the call chain above to unsetting the DnD
source.

In other selection sources, we let the MetaWaylandDataDevice hold the
"ownership" of the MetaWaylandDataSource, and its weak ref functions unset
the respective MetaSelection owners. Do the same here, so the
MetaWaylandDataSource destruction is listened for all its lifetime.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/591

(cherry picked from commit e5af790acb979ae9c8a0509052a42208c67639a6)
2019-11-20 12:59:58 +01:00
Carlos Garnacho
edb618b2a4 wayland: Do not cancel data source on offer destruction
This is wrong for both clipboard and DnD, as the selection source
will still be able to focus another surface, and churn another
wl_offer.

We should just detach the data offer from the data source in this
case, and let the source live on. However, we should still check
that there is a source and an offer to finish DnD, do that when
handling the drop operation instead.

https://gitlab.gnome.org/GNOME/mutter/issues/591

(cherry picked from commit 48639ac5da35697d885bd0736dea46e34a832ca2)
2019-11-20 12:59:40 +01:00
Carlos Garnacho
e2d6b33b61 wayland: Avoid redundant cancel() call
This is unnecessary as we are unsetting the DnD selection owner,
and will result in the related data source being cancelled already.

https://gitlab.gnome.org/GNOME/mutter/issues/591

(cherry picked from commit e7b2f9603e90d87092c9e755c176f1244a8b3e36)
2019-11-20 12:59:19 +01:00
Carlos Garnacho
eac37b17b0 wayland: Drop unused wl_signal structs
Those were used to signal clipboard ownership around, but that got
replaced by MetaSelection and friends. These signals are no longer
listened on, so can be safely removed.

https://gitlab.gnome.org/GNOME/mutter/issues/591

(cherry picked from commit 46b3811e22b3b898342141b1575c888285e51caf)
2019-11-20 12:58:30 +01:00
Hans de Goede
d78585d68a cursor-renderer/native: Fix cursor drawing in combination with panel_orientation_transform
Properly take the panel_orientation_transform into account in
update_monitor_crtc_cursor. This fixes us sometimes drawing the cursor
on two monitors at the same time as we did not properly swap the crtc
width/height when a panel_orientation_transform is active.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/927


(cherry picked from commit 8907a299127be21169aba05ab1751c66c6d36754)
2019-11-13 10:35:31 +00:00
Hans de Goede
c462544f78 output-kms: Fix "panel orientation" kms-prop being ignored on native outputs
Actually store the panel_orientation_transform in the meta_output, so
that it gets honored by the core code.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/927


(cherry picked from commit a5f986259f8e68dbad2f7835d1481840b446408f)
2019-11-13 10:35:04 +00:00
Carlos Garnacho
eb78b7d0d1 compositor: Plug cairo_region_t leak
The MetaBackgroundActor uses a region to find out the areas that need
repainting, but forgot to free it, oops.

(cherry-picked from 40e6aa7d94e64d80fe07f020d75d540200004ea9)

https://gitlab.gnome.org/GNOME/mutter/merge_requests/873
2019-11-12 13:37:30 +01:00
Carlos Garnacho
cc00e55513 backends: Plug MetaKmsPageFlipData leak
If the page flip is postponed, keep a ref to it, but still unref it
on the page flip callback anyways. Fix suggested by Jonas Ådahl.

(cherry-picked from 668be1f4bd309fedc846a0022180aef5a9e44869)

https://gitlab.gnome.org/GNOME/mutter/merge_requests/873
2019-11-12 13:37:30 +01:00
Hans de Goede
a14e7b441c input-settings/x11: Add missing clutter_x11_trap_x_errors around XIGetProperty
Add missing clutter_x11_[un]trap_x_errors around the XIGetProperty call
in meta-input-settings-x11.c's get_property helper function.

This fixes mutter crashing with the following error if the XInput device
goes away at an unconvenient time:

 X Error of failed request:  XI_BadDevice (invalid Device parameter)
   Major opcode of failed request:  131 (XInputExtension)
   Minor opcode of failed request:  59 ()
   Device id in failed request: 0x200011
   Serial number of failed request:  454
   Current serial number in output stream:  454

https://gitlab.gnome.org/GNOME/mutter/merge_requests/928
2019-11-10 22:42:44 +01:00
Robert Mader
403d8fcc66 plugin-manager: Kill window effects on destroy
We do so for all other window effects already. Why this was left out
is unknown (9b3a0d1ad8f), but we will need it for a fix in GS.

Related: https://gitlab.gnome.org/GNOME/mutter/issues/655

https://gitlab.gnome.org/GNOME/mutter/merge_requests/924


(cherry picked from commit a4f51da184e8eab0a2d44d0fc535032515436e8d)
2019-11-08 22:44:34 +00:00
Florian Müllner
7e5366f233 plugins/default: Handle skipped animations
We currently assume that the actor_animate() helper function returns
a timeline. However Clutter may skip implicit animations and simple
set properties directly, for example when the actor is hidden.

The returned timeline will be NULL in that case, and we abort when
using it as instance parameter to g_signal_connect().

Fix this by only setting up a completed handler when we are actually
animating, and complete the effect directly otherwise.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/925
2019-11-08 19:19:45 -03:00
Xiang Fan
cf78598974 wayland/surface: Don't double scale when getting absolute coordinates
The actor is already in surface coordinate space, so we should not scale
with the buffer scale to transform surface coordinates to stage
coordinates.

This bug causes input method using wayland text-input protocol to
receive wrong cursor location. Reproduced in ibus (when candidate
window is open) with scaling factor other than 1.

This commit also fixes pointer confinement.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/915
2019-11-07 17:56:14 +01:00
Marco Trevisan (Treviño)
7c1f3498fe window-props: Don't set override redirect windows as top-level parent
Java applications might use override-redirect windows as parent windows for
top-level windows, although this is not following the standard [1].

In such case, the first non-override-redirect child window that is created
was marked as being on_all_workspaces since the call to
should_be_on_all_workspaces() returns TRUE for its parent, and this even
though the on_all_workspaces_requested bit is unset.
When a further child of this window was added, it was set as not having a
workspace and not being on_all_workspaces, since the call to
should_be_on_all_workspaces() for its parent would return FALSE (unless if
it is in a different monitor, and the multiple-monitors workspaces are
disabled).

Since per commit 09bab98b we don't recompute the workspace if the
on_all_workspaces bit is unset, we could end up in a case where a window can
be nor in all the workspaces or in a specific workspace.

So let's just ignore the transient_for bit for a window if that points to an
override-redirect, using the x11 root window instead.

Add a stacking test to verify this scenario (was failing before of this
commit).

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/885
https://gitlab.gnome.org/GNOME/mutter/merge_requests/895

[1] https://standards.freedesktop.org/wm-spec/wm-spec-latest.html#idm140200472512128


(cherry picked from commit bacbbbd628fd68618f14bdf07ba3f9e6ccd1c038)
2019-11-07 16:21:37 +00:00
Marco Trevisan (Treviño)
598be2b1d8 window-props: Don't look for parent multiple times
Once we set the transient_for, we look for parent MetaWindow, so instead
of overwriting this value for loops check, just use another function
and avoid to look for the xwindow again when setting the MetaWindow parent.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/895


(cherry picked from commit c85fb107c0556283062f2bf9b8d990f1e2c0acae)
2019-11-07 16:21:09 +00:00
Marco Trevisan (Treviño)
a8776a9634 window: Assert we only set a NULL workspace when unmanaging
There might be cases in which a window might be marked as both not in all
workspaces and with NULL workspace.

So to avoid this to happen, let's just assert early instead of doing this at
later point where the context might not be clear.

Related to https://gitlab.gnome.org/GNOME/mutter/issues/885

https://gitlab.gnome.org/GNOME/mutter/merge_requests/895


(cherry picked from commit 13f10e36e4ac162f0b54fa57de24120e0e5a5453)
2019-11-07 16:19:25 +00:00
Marco Trevisan (Treviño)
4b238c10f4 window: Warn if O-R window workspace state is used
Override-redirect windows have no workspace by default, and can't be parent
of a top-level window, so we must check that the parent window is not an
O-R one when setting the workspace state.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/895


(cherry picked from commit 2644e54c514377009a9d4d747874a55b387c6beb)
2019-11-07 16:18:55 +00:00
Jonas Ådahl
6fa860481c wayland/actor-surface: Always store away frame callbacks on commit
We're expected by MetaWaylandSurface to always pick the frame callbacks
out from the pending state when committing (applying) so that no frame
callbacks are unaccounted for. We failed to do this if our actor for
some reason (e.g. associated window was unmanaged) was destroyed. To
handle this situation better, store away the frame callbacks until we
some later point in time need to pass them on forward.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/893


(cherry picked from commit 0e5a5df5fe4d147197d85d4191d8a5c2eefb1561)
2019-11-07 13:51:43 +00:00
Florian Müllner
4ba3c4537e ci: Fix checking out gnome-shell on stable branches
For stable branches, we currently only check out the correct shell
branch for merge requests. For the regular pipeline, our code to
determine the current mutter branch fails because CI runs on a
temporary "pipeline/12345" branch that doesn't exist for gnome-shell.

Switching to the correct gitlab environment variable fixes that.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/811
2019-11-07 00:14:41 +01:00
Marco Trevisan (Treviño)
1f56514e40 x11-display: Don't unset the X11 focused window after setting one
When using DesktopIcons extension and clicking in an icon, gnome-shell
starts an infinite loop caused by the first focus change that may trigger
on X11 a focus in/out event that leads to stage activation/deactivation
which never ends.

This happens because as part of meta_x11_display_set_input_focus_xwindow()
to focus the X11 stage window, we unset the display focus, but this also
causes to request the X11 display to unset the focus since we convolute by
calling meta_x11_display_set_input_focus() with no window, that leads to
focusing the no_focus_window and then a focus-in / focus-out dance that the
shell amplifies in order to give back the focus to the stage.

In order to fix this, mimic what meta_display_set_input_focus() does, but
without updating the X11 display, and so without implicitly calling
meta_x11_display_set_input_focus(), stopping the said convolution and
properly focusing the requested xwindow.
Also ensure that we're not doing this when using an older timestamp, since
this check isn't performed anymore.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/896
Fixes https://gitlab.gnome.org/GNOME/mutter/issues/899

https://gitlab.gnome.org/GNOME/mutter/merge_requests/909


(cherry picked from commit efe5bed5b4a8706fc796dfd7dc07562a866c12ed)
2019-11-06 17:48:19 +00:00
Jonas Ådahl
5e1bbb770e tests/monitor-unit-tests: Add another tiling window hot plug test
Checks that we handle hot plugs of a untiled window, that was previously
tiled.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:26 -03:00
Jonas Ådahl
3df4348f23 window: Reset tile monitor number when untiling
Otherwise we'll end up trying to access the out of date state later.

Fixes the following test failure backtrace:

    #0  _g_log_abort ()
    #1  g_logv ()
    #2  g_log ()
    #3  meta_monitor_manager_get_logical_monitor_from_number ()
    #4  meta_window_get_work_area_for_monitor ()
    #5  meta_window_get_tile_area ()
    #6  constrain_maximization ()
    #7  do_all_constraints ()
    #8  meta_window_constrain ()
    #9  meta_window_move_resize_internal ()
    #10 meta_window_tile ()

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:25 -03:00
Jonas Ådahl
9ed33dc72e tests/monitor-unit-tests: Add window tiling hot plug test
This test that we handle hot plugs correctly together with tiled
windows.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:23 -03:00
Jonas Ådahl
8cb0646b62 tests/runner: Move window shown synchronization to helper
https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:22 -03:00
Jonas Ådahl
c9a05d4581 tests/monitor-unit-tests: Move test client sanity check into helper
https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:21 -03:00
Jonas Ådahl
98a1630fa2 window: Always update tile monitor number on hot plug
Otherwise we'll end up crashing if we had two connected monitors,
unplugged both, then replugged in a single one.

Avoids the following error:

    #0  _g_log_abort ()
    #1  g_logv ()
    #2  g_log ()
    #3  meta_monitor_manager_get_logical_monitor_from_number ()
    #4  meta_window_get_work_area_for_monitor ()
    #5  meta_window_get_tile_area ()
    #6  constrain_maximization ()
    #7  do_all_constraints ()
    #8  meta_window_constrain ()
    #9  meta_window_move_resize_internal ()
    #10 meta_window_move_resize_frame ()
    #11 meta_window_move_resize_now ()
    #12 idle_move_resize ()
    #13 call_idle_later ()

https://bugzilla.redhat.com/show_bug.cgi?id=1767703

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:20 -03:00
Jonas Ådahl
4c48c859ea plugins/default: Clean up tile preview when closing display
On finalize, the preview actor will have been destroyed behind our back;
avoid that by cleaning up before it's too late.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:19 -03:00
Jonas Ådahl
d7bdaeeb82 plugin/default: Init quark before using
Cut lines in pieces, and remove useless "optimizations" while at it

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:17 -03:00
Jonas Ådahl
3564b0df4a display: Add 'closing' signal
Emitted when the MetaDisplay is closing. Meant for clean up that depends
on things that will be torn down during closing.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/912
2019-11-05 08:56:15 -03:00
Olivier Fourdan
34b5a07d58 renderer-native: Separate offscreen and shadowfb
Create the intermediate shadow framebuffer for use exclusively when a
shadowfb is required.

Keep the previous offscreen framebuffer is as an intermediate
framebuffer for transformations only.

This way, we can apply transformations between in-memory framebuffers
prior to blit the result to screen, and achieve acceptable performance
even with software rendering on discrete GPU.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/917

(cherry picked from commit 551641c74822ca2e3c685e49603836ebf5397df2)
2019-11-04 11:08:02 +01:00
Olivier Fourdan
a112d7a10e clutter/stage-view: Separate offscreen and shadowfb
Previously, we would use a single offscreen framebuffer for both
transformations and when a shadow framebuffer should be used, but that
can be dreadfully slow when using software rendering with a discrete GPU
due to bandwidth limitations.

Keep the offscreen framebuffer for transformations only and add another
intermediate shadow framebuffer used as a copy of the onscreen
framebuffer.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/917

(cherry picked from commit 2b8b450fe16c21f0f37a1779560c0e5da61a9b89)
2019-11-04 11:08:02 +01:00
Carlos Garnacho
51f7e8c4dd wayland: Check stylus serials on meta_wayland_seat_can_popup()
This allows xdg_popup.grab() to work with styli. Without this check
we would bail out and emit xdg_popup.popup_done, leaving stylus users
unable to interact with popup menus, comboboxes, etc...

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/886
2019-10-30 10:08:51 +01:00
Jonas Ådahl
f4574ea36f x11: Limit touch replay pointer events to when replaying
When a touch sequence was rejected, the emulated pointer events would be
replayed with old timestamps. This caused issues with grabs as they
would be ignored due to being too old. This was mitigated by making sure
device event timestamps never travelled back in time by tampering with
any event that had a timestamp seemingly in the past.

This failed when the most recent timestamp that had been received were
much older than the timestamp of the new event. This could for example
happen when a session was left not interacted with for 40+ days or so;
when interacted with again, as any new timestamp would according to
XSERVER_TIME_IS_BEFORE() still be in the past compared to the "most
recent" one. The effect is that we'd always use the `latest_evtime` for
all new device events without ever updating it.

The end result of this was that passive grabs would become active when
interacted with, but would then newer be released, as the timestamps to
XIAllowEvents() would out of date, resulting in the desktop effectively
freezing, as the Shell would have an active pointer grab.

To avoid the situation where we get stuck with an old `latest_evtime`
timestamp, limit the tampering with device event timestamp to 1) only
pointer events, and 2) only during the replay sequence. The second part
is implemented by sending an asynchronous message via the X server after
rejecting a touch sequence, only potentially tampering with the device
event timestamps until the reply. This should avoid the stuck timestamp
as in those situations, we'll always have a relatively up to date
`latest_evtime` meaning XSERVER_TIME_IS_BEFORE() will not get confused.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/886
2019-10-30 10:08:39 +01:00
Jonas Ådahl
2301cde8f7 display: Move finishing of touch sequence to the backend
We need to manipulate an X11 grab when a touch sequence ends; move that
logic to where it belongs - in the X11 backend.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/886
2019-10-30 10:08:32 +01:00
Carlos Garnacho
ef2f5f07f0 x11: Update X11 focus before updating MetaDisplay focus
In a similar vein to commit 8fd55fef853. This notably failed when setting
the focus on the stage (eg. to redirect key events to Clutter actors).
Deeper in MetaDisplay focus updating machinery, it would check
meta_stage_is_focused() which would still return FALSE at the time it's
called.

This would not typically have side effects, but our "App does not respond"
dialogs see the focus change under their feet, so they try to bring
themselves to focus again. This results in a feedback loop.

Changing the order results in later checks on the X11 POV of the focus
being correct, so focus is not mistakenly stolen from the close dialog,
and it actually succeeds in keeping the key focus.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1607

https://gitlab.gnome.org/GNOME/mutter/merge_requests/876


(cherry picked from commit 71c3f4af3196b77fb52f395238f0704e7fa4d273)
2019-10-24 15:52:41 +00:00
Robert Mader
85f5db7e73 wayland/surface: Reset buffer_destroy_handler_id
Syncronized subsurfaces that call into `merge_pending_state` might
otherwise not create new destroy handlers, ending up with a invalid
handler ids, throwing errors and leaking.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/868


(cherry picked from commit 98892391d764d1cf4b32e57367e45f39b10880e4)
2019-10-21 13:03:25 +00:00
Robert Mader
c0037305eb window-actor: Add a missing NULL-check
We shouldn't crash on a NULL-clip.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/856
2019-10-18 13:40:20 +02:00
Cosimo Cecchi
ff885fea31 monitor-manager: check for underscan setting validity upfront
Instead of doing a roundtrip to the X server before setting it, rely on
the previous value fetched before the configuration was sent over DBus.
This matches the argument check we already do elsewhere, and will allow
us to more easily add an additional condition to determine if underscan
is supported.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/673


(cherry picked from commit 8665084df15190adc0d18cc77b7fcb738d3e4fa6)
2019-10-18 11:36:34 +00:00
Marco Trevisan (Treviño)
bf17e04010 clutter/stage: Actually set key focus to an actor on key focus
As per commit c2d03bf73 we're using a private method to set the actors key
focus and emit key-focus-in signal, but we're using inverted logic here.

So flip the parameter to match the expected result.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/860


(cherry picked from commit 553211dd81a849f33f0aca447c8683f031fff868)
2019-10-15 18:31:50 +00:00
Marco Trevisan (Treviño)
a22731e2b2 clutter/actor: Save key-focus state and unset it before destruction
When clutter actors with key focus are destroyed we emit ::key-focus-out on
them just after their destruction. This is against our assumption that no
signal should be emitted after "::destroy" (see GNOME/mutter!769 [1]), and
in fact could cause the shell to do actions that we won't ever stop on
destroy callback.

To avoid this to happen, use a private function to set its key-state (so we
can avoid looking for the stage) and emit ::key-focus-in/out events and use
this value in both clutter_actor_has_key_focus(),
clutter_actor_grab_key_focus() and on unmap and destruction to unset the
stage key focus before we emit the ::destroy signal.

As result of this, we can now avoid to unset the key focus on actor
destruction in the stage.

[1] https://gitlab.gnome.org/GNOME/mutter/merge_requests/769

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1704


(cherry picked from commit c2d03bf73e5a945296d22c4d95709eeebf2eb57c)
2019-10-15 10:42:55 +00:00
Niels De Graef
b6ed7d6781 dbus-session-watcher: Chain up to parent finalize()
https://gitlab.gnome.org/GNOME/mutter/merge_requests/847


(cherry picked from commit 3a688988e0834c4605445425f3b35bb08c324691)
2019-10-14 07:51:15 +00:00
1402 changed files with 141534 additions and 124070 deletions

1
.gitignore vendored
View File

@ -103,4 +103,3 @@ doc/reference/meta.types
.dirstamp
**/tags.*
build/
subprojects/sysprof/

View File

@ -1,372 +1,79 @@
include:
- remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/bbe5232986c9b98eb1efe62484e07216f7d1a4df/templates/fedora.yml'
- remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/bbe5232986c9b98eb1efe62484e07216f7d1a4df/templates/ci-fairy.yml'
image: registry.gitlab.gnome.org/gnome/mutter/master:v2
stages:
- review
- prepare
- code-review
- build
- test
- analyze
- deploy
variables:
FDO_UPSTREAM_REPO: GNOME/mutter
.mutter.fedora:34@common:
variables:
FDO_DISTRIBUTION_VERSION: 34
BASE_TAG: '2021-09-04.1'
FDO_DISTRIBUTION_PACKAGES:
asciidoc
clang
gcovr
gdm
gnome-shell
python3-dbusmock
sassc
uncrustify
xorg-x11-server-Xvfb
FDO_DISTRIBUTION_EXEC: |
dnf install -y 'dnf-command(builddep)' &&
dnf builddep -y mutter --setopt=install_weak_deps=False &&
dnf builddep -y gnome-shell --setopt=install_weak_deps=False &&
./.gitlab-ci/install-meson-project.sh \
https://gitlab.gnome.org/GNOME/glib.git \
main . 02742ef957b532789c003eef80ec7f51c370e3d5 &&
./.gitlab-ci/install-meson-project.sh \
https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas.git \
41.alpha . &&
./.gitlab-ci/install-meson-project.sh \
https://gitlab.gnome.org/GNOME/gjs.git \
1.69.2 . &&
rpm -e --nodeps gnome-bluetooth-libs-devel \
mutter mutter-devel \
gnome-shell &&
dnf clean all
default:
# Cancel jobs if newer commits are pushed to the branch
interruptible: true
# Auto-retry jobs in case of infra failures
retry:
max: 1
when:
- 'runner_system_failure'
- 'stuck_or_timeout_failure'
- 'scheduler_failure'
- 'api_failure'
.mutter.fedora:34@x86_64:
extends: .mutter.fedora:34@common
variables:
FDO_DISTRIBUTION_TAG: "x86_64-${BASE_TAG}"
.mutter.fedora:34@aarch64:
extends: .mutter.fedora:34@common
variables:
FDO_DISTRIBUTION_TAG: "aarch64-${BASE_TAG}"
tags:
- aarch64
workflow:
rules:
- if: '$CI_MERGE_REQUEST_IID'
- if: '$CI_COMMIT_TAG'
- if: '$CI_COMMIT_BRANCH'
.pipline-guard: &pipline-guard
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_TAG'
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
- if: '$CI_COMMIT_BRANCH =~ /^gnome-[0-9-]+$/'
- when: 'manual'
check-commit-log:
extends:
- .fdo.ci-fairy
stage: review
variables:
GIT_DEPTH: "100"
script:
- if [[ x"$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" != "x" ]] ;
then
ci-fairy check-commits --junit-xml=commit-message-junit-report.xml ;
else
echo "Not a merge request" ;
fi
artifacts:
expire_in: 1 week
paths:
- commit-message-junit-report.xml
reports:
junit: commit-message-junit-report.xml
<<: *pipline-guard
- ./.gitlab-ci/check-commit-log.sh
only:
- merge_requests
check-merge-request:
extends:
- .fdo.ci-fairy
stage: review
variables:
GIT_STRATEGY: none
script:
- if [[ x"$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" != "x" ]] ;
then
ci-fairy check-merge-request --require-allow-collaboration --junit-xml=check-merge-request-report.xml ;
else
echo "Not a merge request" ;
fi
artifacts:
expire_in: 1 week
paths:
- check-merge-request-report.xml
reports:
junit: check-merge-request-report.xml
<<: *pipline-guard
build-fedora-container@x86_64:
extends:
- .fdo.container-build@fedora@x86_64
- .mutter.fedora:34@x86_64
stage: prepare
needs:
- check-commit-log
- check-merge-request
variables:
GIT_STRATEGY: none
build-fedora-container@aarch64:
extends:
- .fdo.container-build@fedora@aarch64
- .mutter.fedora:34@aarch64
stage: prepare
needs:
- check-commit-log
- check-merge-request
variables:
GIT_STRATEGY: none
check-code-style:
extends:
- .fdo.distribution-image@fedora
- .mutter.fedora:34@x86_64
stage: code-review
needs:
- build-fedora-container@x86_64
script:
- if [[ x"$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" != "x" ]] ;
then
git remote add target $CI_MERGE_REQUEST_PROJECT_URL.git ;
git fetch target $CI_MERGE_REQUEST_TARGET_BRANCH_NAME ;
export common_parent_sha=$(diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "target/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME") <(git rev-list --first-parent HEAD) | head -1) ;
python3 -u ./check-style.py --dry-run --sha $common_parent_sha ;
else
echo "Not a merge request" ;
fi
allow_failure: true
.build-mutter:
extends:
- .fdo.distribution-image@fedora
build-mutter:
stage: build
script:
- meson . build -Dbuildtype=debugoptimized -Db_coverage=true -Degl_device=true -Dwayland_eglstream=true --werror --prefix /usr
- meson compile -C build
- meson install -C build
- meson . build -Dbuildtype=debugoptimized -Degl_device=true -Dwayland_eglstream=true --werror --prefix /usr
- ninja -C build
- ninja -C build install
artifacts:
expire_in: 1 day
paths:
- build
only:
- merge_requests
- /^.*$/
build-mutter@x86_64:
extends:
- .build-mutter
- .mutter.fedora:34@x86_64
needs:
- build-fedora-container@x86_64
build-mutter@aarch64:
extends:
- .build-mutter
- .mutter.fedora:34@aarch64
needs:
- build-fedora-container@aarch64
build-without-opengl-and-glx@x86_64:
extends:
- .fdo.distribution-image@fedora
- .mutter.fedora:34@x86_64
build-without-native-backend-and-wayland:
stage: build
needs:
- build-fedora-container@x86_64
script:
- meson . build -Dbuildtype=debugoptimized -Dopengl=false -Dglx=false -Degl_device=true -Dwayland_eglstream=true --werror --prefix /usr
- meson compile -C build
- meson install -C build
- meson . build -Dbuildtype=debugoptimized -Dnative_backend=false -Dudev=false -Dwayland=false -Dcore_tests=false --werror --prefix /usr
- ninja -C build
- ninja -C build install
artifacts:
expire_in: 1 day
paths:
- build/meson-logs
- build
only:
- merge_requests
- /^.*$/
build-without-native-backend-and-wayland@x86_64:
extends:
- .fdo.distribution-image@fedora
- .mutter.fedora:34@x86_64
stage: build
needs:
- build-fedora-container@x86_64
script:
- meson . build -Dbuildtype=debugoptimized -Dnative_backend=false -Dudev=false -Dwayland=false -Dcore_tests=false -Dnative_tests=false --werror --prefix /usr
- meson compile -C build
- meson install -C build
artifacts:
paths:
- build/meson-logs
.test-setup: &test-setup
test-mutter:
stage: test
dependencies:
- build-mutter
variables:
XDG_RUNTIME_DIR: "$CI_PROJECT_DIR/runtime-dir"
GSETTINGS_SCHEMA_DIR: "$CI_PROJECT_DIR/build/data"
MUTTER_DEBUG_DUMMY_MODE_SPECS: "800x600@10.0"
PIPEWIRE_DEBUG: 2
PIPEWIRE_LOG: "$CI_PROJECT_DIR/build/meson-logs/pipewire.log"
XVFB_SERVER_ARGS: "+iglx -noreset"
G_SLICE: "always-malloc"
MALLOC_CHECK_: "3"
NO_AT_BRIDGE: "1"
before_script:
- glib-compile-schemas $GSETTINGS_SCHEMA_DIR
# Disable e.g. audio support to not dead lock screen cast tests
- rm -f /usr/share/pipewire/media-session.d/with-*
MALLOC_PERTURB_: "123"
script:
- dconf update
- mkdir -m 700 $XDG_RUNTIME_DIR
- pipewire & sleep 2
- glib-compile-schemas $GSETTINGS_SCHEMA_DIR
- >
dbus-run-session -- xvfb-run -s '+iglx -noreset'
meson test -C build --no-rebuild -t 10 --verbose --no-stdsplit --print-errorlogs --wrap catchsegv
only:
- merge_requests
- /^.*$/
.test-mutter:
extends:
- .fdo.distribution-image@fedora
<<: *test-setup
can-build-gnome-shell:
stage: test
script:
- dbus-run-session -- xvfb-run -a -s "$XVFB_SERVER_ARGS"
catchsegv meson test -C build --no-rebuild -t 10
artifacts:
expire_in: 1 day
reports:
junit: "build/meson-logs/testlog-catchsegv.junit.xml"
name: "mutter-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}"
when: always
paths:
- build
test-mutter@x86_64:
extends:
- .test-mutter
- .mutter.fedora:34@x86_64
needs:
- build-mutter@x86_64
test-mutter@aarch64:
extends:
- .test-mutter
- .mutter.fedora:34@aarch64
needs:
- build-mutter@aarch64
.test-mutter-coverage:
extends:
- .fdo.distribution-image@fedora
stage: analyze
script:
- ninja -C build coverage
- cat build/meson-logs/coverage.txt
artifacts:
paths:
- build/meson-logs/coveragereport
coverage: '/^TOTAL.*\s+(\d+\%)$/'
test-mutter-coverage@x86_64:
extends:
- .test-mutter-coverage
- .mutter.fedora:34@x86_64
needs:
- test-mutter@x86_64
test-mutter-coverage@aarch64:
extends:
- .test-mutter-coverage
- .mutter.fedora:34@aarch64
needs:
- test-mutter@aarch64
can-build-gnome-shell@x86_64:
extends:
- .fdo.distribution-image@fedora
- .mutter.fedora:34@x86_64
stage: test
needs:
- build-mutter@x86_64
dependencies:
- build-mutter
before_script:
- meson install --no-rebuild -C build
script:
- .gitlab-ci/checkout-gnome-shell.sh
- meson gnome-shell gnome-shell/build --prefix /usr -Dman=false
- meson install -C gnome-shell/build
test-mutter-coverity:
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule" && $MUTTER_SCHEDULED_JOB == "coverity"'
when: always
- when: manual
extends:
- .fdo.distribution-image@fedora
- .mutter.fedora:34@x86_64
needs:
- build-fedora-container@x86_64
stage: analyze
allow_failure: true
script:
- .gitlab-ci/download-coverity-tarball.sh
- CC=clang meson coverity-build -Dprofiler=false
- ./coverity/cov-analysis-linux64-*/bin/cov-build --dir cov-int meson compile -C coverity-build
- tar czf cov-int.tar.gz cov-int
- curl https://scan.coverity.com/builds?project=mutter
--form token=$COVERITY_TOKEN --form email=carlosg@gnome.org
--form file=@cov-int.tar.gz --form version="`git describe --tags`"
--form description="GitLab CI build"
cache:
key: coverity-tarball
paths:
- coverity
dist-mutter:
extends:
- .fdo.distribution-image@fedora
- .mutter.fedora:34@x86_64
<<: *test-setup
stage: deploy
needs:
- build-mutter@x86_64
script:
- dbus-run-session -- xvfb-run -a -s "$XVFB_SERVER_ARGS" meson dist -C build
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
changes:
- "**/meson.build"
- meson/*
dist-mutter-tarball:
extends: dist-mutter
artifacts:
expose_as: 'Get tarball here'
paths:
- build/meson-dist/$CI_PROJECT_NAME-$CI_COMMIT_TAG.tar.xz
rules:
- if: '$CI_COMMIT_TAG'
- ninja -C gnome-shell/build install
only:
- merge_requests
- /^.*$/

40
.gitlab-ci/Dockerfile Normal file
View File

@ -0,0 +1,40 @@
# Rebuild and push with
#
# cd .gitlab-ci/
# docker build --no-cache -t registry.gitlab.gnome.org/gnome/mutter/master:v2 .
# docker push registry.gitlab.gnome.org/gnome/mutter/master:v2
#
FROM fedora:30
RUN dnf -y update && dnf -y upgrade && \
dnf install -y 'dnf-command(builddep)' && \
dnf install -y 'dnf-command(copr)' && \
dnf copr enable -y fmuellner/gnome-shell-ci && \
dnf copr enable -y jadahl/mutter-ci && \
dnf copr enable -y hergertme/sysprof-3 && \
dnf -y update && dnf -y upgrade && \
dnf builddep -y mutter && \
# Until Fedora catches up with meson build-deps
dnf install -y meson xorg-x11-server-Xorg gnome-settings-daemon-devel egl-wayland-devel xorg-x11-server-Xwayland && \
# Until Fedora catches up with mesa bug fixes
dnf upgrade -y mesa-dri-drivers mesa-libEGL && \
# For running unit tests
dnf install -y xorg-x11-server-Xvfb mesa-dri-drivers dbus dbus-x11 '*/xvfb-run' gdm-lib accountsservice-libs && \
dnf install -y sysprof-devel && \
dnf install -y intltool redhat-rpm-config make && \
# GNOME Shell
dnf builddep -y gnome-shell --setopt=install_weak_deps=False && \
# New dep this cycle
dnf install -y 'pkgconfig(gnome-autoar-0)' && \
dnf remove -y gnome-bluetooth-libs-devel dbus-glib-devel upower-devel python3-devel && \
dnf remove -y --noautoremove mutter mutter-devel && \
dnf clean all

57
.gitlab-ci/check-commit-log.sh Executable file
View File

@ -0,0 +1,57 @@
#!/usr/bin/env bash
if [ -z "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
echo Cannot review non-merge request
exit 1
fi
git fetch $CI_MERGE_REQUEST_PROJECT_URL.git $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
branch_point=$(git merge-base HEAD FETCH_HEAD)
commits=$(git log --format='format:%H' $branch_point..$CI_COMMIT_SHA)
if [ -z "$commits" ]; then
echo Commit range empty
exit 1
fi
function commit_message_has_url() {
commit=$1
commit_message=$(git show -s --format='format:%b' $commit)
echo "$commit_message" | grep -qe "\($CI_MERGE_REQUEST_PROJECT_URL/\(issues\|merge_requests\)/[0-9]\+\|https://bugzilla.gnome.org/show_bug.cgi?id=[0-9]\+\)"
return $?
}
function commit_message_subject_is_compliant() {
commit=$1
commit_message_subject=$(git show -s --format='format:%s' $commit)
if echo "$commit_message_subject" | grep -qe "\(^meta-\|^Meta\)"; then
echo " - message subject should not be prefixed with 'meta-' or 'Meta'"
return 1
fi
if echo "$commit_message_subject" | grep -qe "\.[ch]:"; then
echo " - message subject prefix should not include .c, .h, etc."
return 1
fi
return 0
}
for commit in $commits; do
commit_short=$(echo $commit | cut -c -8)
if ! commit_message_has_url $commit; then
echo "Missing merge request or issue URL on commit $commit_short"
exit 1
fi
errors=$(commit_message_subject_is_compliant $commit)
if [ $? != 0 ]; then
echo "Commit message for $commit_short is not compliant:"
echo "$errors"
exit 1
fi
done

View File

@ -1,19 +1,11 @@
#!/usr/bin/bash
fetch() {
local remote=$1
local ref=$2
git fetch --quiet --depth=1 $remote $ref 2>/dev/null
}
gnome_shell_target=
echo -n Cloning into gnome-shell ...
if git clone --quiet --depth=1 https://gitlab.gnome.org/GNOME/gnome-shell.git; then
echo \ done
else
echo \ failed
git clone https://gitlab.gnome.org/GNOME/gnome-shell.git
if [ $? -ne 0 ]; then
echo Checkout failed
exit 1
fi
@ -23,33 +15,19 @@ if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
merge_request_remote=${CI_MERGE_REQUEST_SOURCE_PROJECT_URL//mutter/gnome-shell}
merge_request_branch=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
echo -n Looking for $merge_request_branch on remote ...
if fetch $merge_request_remote $merge_request_branch; then
echo \ found
echo Looking for $merge_request_branch on remote ...
if git fetch -q $merge_request_remote $merge_request_branch 2>/dev/null; then
gnome_shell_target=FETCH_HEAD
else
echo \ not found
echo -n Looking for $CI_MERGE_REQUEST_TARGET_BRANCH_NAME instead ...
if fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME; then
echo \ found
gnome_shell_target=FETCH_HEAD
else
echo \ not found
fi
fi
fi
if [ -z "$gnome_shell_target" ]; then
echo -n Looking for $CI_COMMIT_REF_NAME on remote ...
if fetch origin $CI_COMMIT_REF_NAME; then
echo \ found
gnome_shell_target=FETCH_HEAD
else
echo \ not found
gnome_shell_target=HEAD
gnome_shell_target=origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME
echo Using $gnome_shell_target instead
fi
fi
if [ -z "$gnome_shell_target" ]; then
gnome_shell_target=$(git branch -r -l origin/$CI_COMMIT_REF_NAME)
gnome_shell_target=${gnome_shell_target:-origin/master}
echo Using $gnome_shell_target instead
fi
git checkout -q $gnome_shell_target

View File

@ -1,19 +0,0 @@
patterns:
deny:
- regex: '^$CI_MERGE_REQUEST_PROJECT_URL/(-/)?merge_requests/$CI_MERGE_REQUEST_IID$'
message: Commit message must not contain a link to its own merge request
- regex: '^(meta-|Meta)'
message: Commit message subject should not be prefixed with 'meta-' or 'Meta'
where: subject
- regex: '^(clutter-|Clutter)'
message: Commit message subject should not be prefixed with 'clutter-' or 'Clutter', use 'clutter/' instead
where: subject
- regex: '^(cogl-|Cogl)'
message: Commit message subject should not be prefixed with 'cogl-' or 'Cogl', use 'cogl/' instead
where: subject
- regex: '^[^:]+: [a-z]'
message: "Commit message subject should be properly Capitalized. E.g. 'window: Marginalize extradicity'"
where: subject
- regex: '^\S*\.[ch]:'
message: Commit message subject prefix should not include .c, .h, etc.
where: subject

View File

@ -1,38 +0,0 @@
#!/usr/bin/bash
# We need a coverity token to fetch the tarball
if [ -x $COVERITY_TOKEN ]
then
echo "No coverity token. Run this job from a protected branch."
exit -1
fi
mkdir -p coverity
# Download and check MD5 first
curl https://scan.coverity.com/download/linux64 \
--data "token=$COVERITY_TOKEN&project=mutter&md5=1" \
--output /tmp/coverity_tool.md5
diff /tmp/coverity_tool.md5 coverity/coverity_tool.md5 >/dev/null 2>&1
if [ $? -eq 0 -a -d coverity/cov-analysis* ]
then
echo "Coverity tarball is up-to-date"
exit 0
fi
# Download and extract coverity tarball
curl https://scan.coverity.com/download/linux64 \
--data "token=$COVERITY_TOKEN&project=mutter" \
--output /tmp/coverity_tool.tgz
rm -rf ./coverity/cov-analysis*
tar zxf /tmp/coverity_tool.tgz -C coverity/
if [ $? -eq 0 ]
then
mv /tmp/coverity_tool.md5 coverity/
fi
rm /tmp/coverity_tool.tgz

View File

@ -1,39 +0,0 @@
#!/bin/bash
set -e
if [[ $# -lt 3 ]]; then
echo Usage: $0 [options] [repo-url] [commit] [subdir]
echo Options:
echo -Dkey=val
exit 1
fi
MESON_OPTIONS=()
while [[ $1 =~ ^-D ]]; do
MESON_OPTIONS+=( "$1" )
shift
done
REPO_URL="$1"
TAG_OR_BRANCH="$2"
SUBDIR="$3"
COMMIT="$4"
REPO_DIR="$(basename ${REPO_URL%.git})"
git clone --depth 1 "$REPO_URL" -b "$TAG_OR_BRANCH"
pushd "$REPO_DIR"
pushd "$SUBDIR"
if [ ! -z "$COMMIT" ]; then
git fetch origin "$COMMIT"
git checkout "$COMMIT"
fi
meson --prefix=/usr _build "${MESON_OPTIONS[@]}"
meson install -C _build
popd
popd
rm -rf "$REPO_DIR"

View File

@ -1,55 +0,0 @@
<!--
Please read https://wiki.gnome.org/Community/GettingInTouch/BugReportingGuidelines
first to ensure that you create a clear and specific issue.
-->
### Affected version
<!--
Provide at least the following information:
* Your OS and version
* Affected Mutter version
* Does this issue appear in XOrg and/or Wayland
-->
### Bug summary
<!--
Provide a short summary of the bug you encountered.
-->
### Steps to reproduce
<!--
1. Step one
2. Step two
3. ...
-->
### What happened
<!--
What did Mutter do that was unexpected?
-->
### What did you expect to happen
<!--
What did you expect Mutter to do?
-->
### Relevant logs, screenshots, screencasts etc.
<!--
If you have further information, such as technical documentation, logs,
screenshots or screencasts related, please provide them here.
If the bug is a crash, please obtain a stack trace with installed debug
symbols (at least for GNOME Shell and Mutter) and attach it to
this issue following the instructions on
https://wiki.gnome.org/Community/GettingInTouch/Bugzilla/GettingTraces.
-->
<!-- Do not remove the following line. -->
/label ~"1. Bug"

View File

@ -1,30 +0,0 @@
<!--
Please read https://wiki.gnome.org/Community/GettingInTouch/BugReportingGuidelines
first to ensure that you create a clear and specific issue.
-->
### Feature summary
<!--
Describe what you would like to be able to do with Mutter
that you currently cannot do.
-->
### How would you like it to work
<!--
If you can think of a way Mutter might be able to do this,
let us know here.
-->
### Relevant links, screenshots, screencasts etc.
<!--
If you have further information, such as technical documentation,
code, mockups or a similar feature in another window managers,
please provide them here.
-->
<!-- Do not remove the following line. -->
/label ~"1. Feature"

View File

@ -1,286 +0,0 @@
# Style
The coding style used is primarily the GNU flavor of the [GNOME coding
style][gnome-coding-style], with some additions described below.
## General
* Use this code style on new code. When changing old code with a different
code style, feel free to also adjust it to use this code style.
* Use regular C types and `stdint.h` types instead of GLib fundamental
types, except for `gboolean`, and `guint`/`gulong` for GSource IDs and
signal handler IDs. That means e.g. `uint64_t` instead of `guint64`, `int`
instead of `gint`, `unsigned int` instead of `guint` if unsignedness
is of importance, `uint8_t` instead of `guchar`, and so on.
* Try to to limit line length to 80 characters, although it's not a
strict limit.
* Usage of `g_autofree` and `g_autoptr` is encouraged. The style to use is
```c
g_autofree char *text = NULL;
g_autoptr (MetaSomeThing) thing = NULL;
text = g_strdup_printf ("The text: %d", a_number);
thing = g_object_new (META_TYPE_SOME_THING,
"text", text,
NULL);
thinger_use_thing (rocket, thing);
```
* Declare variables at the top of the block they are used, but avoid
non-trivial logic among variable declarations. Non-trivial logic can be
getting a pointer that may be `NULL`, any kind of math, or anything
that may have side effects.
* Instead of boolean arguments in functions, prefer enums or flags when
they're more expressive. The naming convention for flags is
```c
typedef _MetaSomeThingFlags
{
META_SOME_THING_FLAG_NONE = 0,
META_SOME_THING_FLAG_ALTER_REALITY = 1 << 0,
META_SOME_THING_FLAG_MANIPULATE_PERCEPTION = 1 << 1,
} MetaSomeThingFlags;
```
* Use `g_new0 ()` etc. instead of `g_slice_new0 ()`.
* Initialize and assign floating point variables (i.e. `float` or
`double`) using the form `floating_point = 3.14159` or `ratio = 2.0`.
## Header (.h) files
* The return type and `*` are separated by a space.
* Function name starts one space after the last `*`.
* Parenthesis comes one space after the function name.
As an example, this is how functions in a header file should look like:
```c
gboolean meta_udev_is_drm_device (MetaUdev *udev,
GUdevDevice *device);
GList * meta_udev_list_drm_devices (MetaUdev *udev,
GError **error);
MetaUdev * meta_udev_new (MetaBackendNative *backend_native);
```
## Source code
Keep functions in the following order in source files:
1. GPL header
2. Enums
3. Structures
4. Function prototypes
5. `G_DEFINE_TYPE()`
6. Static variables
7. Auxiliary functions
8. Callbacks
9. Interface implementations
10. Parent vfunc overrides
11. class_init and init
12. Public API
### Structures
Each structure field has a space after their type name. Structure fields aren't
aligned. For example:
```c
struct _MetaFooBar
{
MetaFoo parent;
MetaBar *bar;
MetaSomething *something;
};
```
### Function Prototypes
Function prototypes must be formatted just like in header files.
### Overrides
When overriding parent class vfuncs, or implementing an interface, vfunc
overrides should be named as a composition of the current class prefix,
followed by the vfunc name. For example:
```c
static void
meta_bar_spawn_unicorn (MetaParent *parent)
{
/* ... */
}
static void
meta_bar_dispose (GObject *object)
{
/* ... */
}
static void
meta_bar_finalize (GObject *object)
{
/* ... */
}
static void
meta_bar_class_init (MetaBarClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MetaParentClass *parent_class = META_PARENT_CLASS (klass);
object_class->dispose = meta_bar_dispose;
object_class->finalize = meta_bar_finalize;
parent_class->spawn_unicorn = meta_bar_spawn_unicorn;
}
```
### Interface Implementations
When implementing interfaces, two groups of functions are involved: the init
function, and the overrides.
The interface init function is named after the interface type in snake case,
followed by the `_iface_init` suffix. For example:
```c
static void meta_foo_iface_init (MetaFooInterface *foo_iface);
G_DEFINE_TYPE_WITH_CODE (MetaBar, meta_bar, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (META_TYPE_FOO,
meta_foo_iface_init));
```
Then, when implementing each vfunc of the interface, follow the same pattern
of the [Overrides](###Overrides) section. Here's an example:
```c
static void
meta_bar_do_something (MetaFoo *foo)
{
/* ... */
}
static void
meta_foo_iface_init (MetaFooInterface *foo_iface)
{
foo_iface->do_something = meta_bar_do_something;
}
```
### Auxiliary Functions
Auxiliary functions are above every other functions to minimize the number of
function prototypes in the file. These functions often grow when factoring out
the same code between two or more functions:
```c
static void
do_something_on_data (Foo *data,
Bar *bar)
{
/* ... */
}
static void
random_function (Foo *foo)
{
do_something_on_data (foo, bar);
}
static void
another_random_function (Foo *foo)
{
do_something_on_data (foo, bar);
}
```
Sometimes, however, auxiliary functions are created to break down otherwise
large functions - in this case, it is appropriate to keep these auxiliary
functions close to the function they are tightly related to.
Auxiliary function names must have a verb in the imperative form, and should
always perform an action over something. They usually don't have the class
prefix (`meta_`, `clutter_`, or `cogl_`). For example:
```c
static void
do_something_on_data (Foo *data,
Bar *bar)
{
/* ... */
}
```
Exceptionally, when converting between types, auxiliary function names may
have the class prefix to this rule. For example:
```c
static MetaFoo *
meta_foo_from_bar (Bar *bar)
{
/* ... */
}
```
### Callback Functions
Callback function names should have the name of the action in imperative
form. They don't have any prefix, but have a `_func` suffix. For example:
```c
static void
filter_something_func (Foo *foo,
Bar *bar,
gpointer user_data)
{
/* ... */
}
```
### Signal Callbacks
Signal callbacks generally have the signal name. They should be prefixed with
`on_`, or suffixed with `_cb`, but not both. For example:
```c
static void
on_realize (ClutterActor *actor,
gpointer user_data)
{
/* ... */
}
static void
destroy_cb (ClutterActor *actor,
gpointer user_data)
{
/* ... */
}
```
When the callback is named after the object that generated it, and the signal,
then passive voice is used. For example:
```c
static void
click_action_clicked_cb (ClutterClickAction *click_action,
ClutterActor *actor,
gpointer user_data)
{
/* ... */
}
```
[gnome-coding-style]: https://developer.gnome.org/programming-guidelines/stable/c-coding-style.html.en

780
NEWS
View File

@ -1,740 +1,90 @@
41.1
====
* Fix monitor screencast scanouts [Michel; !1914]
* dma-buf: Use alpha-less pixel formats where appropriate [Robert; !1810]
* wayland: Allow clients to maximize windows regardless of constraints
[Christian; !1997]
* Handle hotplug events without relevant changes more effectively
[Marco; !1964]
* Improve error reporting when startup fails [Jonas; !1994]
* dma-buf: Add support for ABGR and XBGR formats [Erfan; !1999]
* Fix X11 middle button emulation setting [José; !2000]
* Include server-side shadows in window screenshots [Robert; !1996]
* Don't change workspaces of unmanaged windows [Sebastian; !2003]
* Reset idletime when unplugging the power cable [Bastien; !2029]
* xwayland: Avoid unnecessary _NET_WM_STATE events [Dor; !2032]
* Fix videos in Firefox stuttering in overview [Robert; !2034]
* Don't use atomic mode setting for virtio_gpu driver [Jonas; !2040]
* Improve on-screen keyboard on X11 [Sebastian, Ray; !1955, !2039]
* misc [Daniel, Jonas, Corentin, Robert; !1992, !2007, !2008, !2026, !2044]
* Fix text glitches after size changes [Sebastian; !2006]
* Fix reporting output rotation to xwayland [Olivier; !2050]
* wayland: Accept final preference of drop destination [Robert; !2043]
* Fix erratic scrolling in GTK apps [Carlos; gnome-shell#4647]
* Fix tilt direction of pen/tablet inputs [Quytelda; !2065]
* Use b/w unicode for tablet mode OSD [Carlos; !2064]
* Fix negative paint volume offscreen effect [Sebastian; !2031]
* Only add paint volumes of mapped actors to stage clip [Robert; !2035]
* Fix mapping tablet input to correct monitor [Jason; !1934]
* Misc. bug fixes and cleanups
Contributors:
Marco Trevisan (Treviño), Erfan Abdi, Dor Askayo, Michel Dänzer,
José Expósito, Olivier Fourdan, Carlos Garnacho, Jason Gerecke,
Quytelda Kahja, Sebastian Keller, Robert Mader, Bastien Nocera, Corentin Noël,
Christian Rauch, Ray Strode, Daniel van Vugt, Jonas Ådahl
Translators:
eshagh shahidani [fa], Danial Behzadi [fa], Марко Костић [sr],
Zander Brown [en_GB], Ngọc Quân Trần [vi], Rūdolfs Mazurs [lv]
41.0
====
* Avoid race in wl_seat capabilities [Olivier; !77]
* Expose option groups/entries to introspection [Corentin; !1976]
Contributors:
Olivier Fourdan, Corentin Noël
Translators:
Daniel Șerbănescu [ro], Goran Vidović [hr], Luna Jernberg [sv],
eshagh shahidani [fa], Gwan-gyeong Mun [ko], Emin Tufan Çetin [tr],
Philipp Kiemle [de], Balázs Úr [hu], Piotr Drąg [pl], Nathan Follens [nl],
Jordi Mas [ca], Ask Hjorth Larsen [da]
41.rc
=====
* Add clutter_stage_paint_to_content() [Ivan; !1899]
* Add meta_cursor_tracker_get_scale() [Ivan; !1967]
* wayland: Make each wl_output correspond to one monitor [Jonas; !1712]
* Expose 'inactive-since' timestamp to uresourced [Nishal; !1960]
* Pass dirty rects to secondary GPU [Piotr; !1879]
* Support commiting preedit string on focus loss [Carlos; !1940]
* Improve auto-rotation support [Marco; !1233]
* Add meta_window_actor_paint_to_content() [Robert; !1893]
* Fixed crashes [Jonas, Ray, Robert; !1947, !1979, !1965, !1958]
* Misc. bug fixes and cleanups [Florian, Carlos, Robert, Daniel, Erico, Dor;
!1957, !1924, !1970, !1971, !1972, !1973, !1974, !1977, !1978, !1975, !1886,
!1983, !1990, !1980]
Contributors:
Marco Trevisan (Treviño), Dor Askayo, Carlos Garnacho, Nishal Kulkarni,
Piotr Lopatka, Robert Mader, Ivan Molodetskikh, Florian Müllner, Erico Nunes,
Ray Strode, Daniel van Vugt, Jonas Ådahl
Translators:
Asier Sarasua Garmendia [eu], Claude Paroz [fr], Jiri Grönroos [fi],
Baurzhan Muftakhidinov [kk], Aurimas Černius [lt]
41.beta
=======
* Fix mouse position in remote desktop with fractional scaling [Pascal; !1867]
* Manage idle monitors via MetaIdleManager [Jonas Å.; !1859]
* Disable KMS modifiers on radeon driver [Carlos; !1872]
* Fix fd leak [Carlos; !1870]
* Fix adding virtual monitor to physical session [Jonas Å.; !1891]
* Unbreak press-drag-release to pop up and select right click menus
[Carlos; !1885]
* Fix VKMS detection [Jonas Å.; !1892]
* Fix swipe cancellation [JoseExposito; !1857]
* Add ClutterTextureContent [Robert; !1888]
* Fix mapping tablet to monitor [Christoph; !1887]
* Fix area screencasts when window is unredirected [Michel; !1902]
* Don't require a newly attached buffer to apply state [Christian, Jonas; !1795]
* Close unused mode setting and rendering devices [Jonas Å.; !1828]
* Only support super+scroll on wayland [Florian; !1922]
* Implement the xdg-activation protocol [Carlos; !1845]
* Reduce input latency by computing max render time heuristically [Ivan; !1762]
* Apply dithering to dispatch time when needed [Daniel; !1826]
* Introduce MetaContext [Jonas Å.; !1861]
* x11: Compute monitor scale per output [Marco; !336]
* Shrink and optimize the rounded-background-clip shader [Daniel; !1860]
* remote-desktop: Handle non-responding selection owners [Pascal; !1874]
* Improve sysprof support [Jonas Å.; !1700]
* Allow clients to delegate titlebar gestures to the compositor [Florian; !1944]
* Fix upside-down Xshape surface with EGLstream [Robert; !1937]
* Fix 'kms-modifiers' experimental setting [Robert; !1953]
* Make default focus window on each workspace appear focused [Alexander; !850]
* Plugged memory leaks [Jonas Å.; !1869]
* Fixed crashes crash [Daniel, Jonas Å., Florian; !1883, !1895,
!1910, !1925, !1956]
* Misc. bug fixes and cleanups [Jonas Å., Marco, Daniel, Florian, Georges,
Zander, Carlos, Robert; !1833, !1863, !1876, !1873, !1884, !1890, !1900,
!1912, !1916, !1911, !1920, !1865, !1927, !1923, !1929, !1100, !1932, !1931,
!1862, !1933, !1930, !1935, !1936, !1878, !1938, !1942, !1951, !522, !1941]
Contributors:
Marco Trevisan (Treviño), Zander Brown, Piotr Drąg, Michel Dänzer,
Carlos Garnacho, JoseExposito, Robert Mader, Alexander Mikhaylenko,
Ivan Molodetskikh, Florian Müllner, Georges Basile Stavracas Neto,
Pascal Nowack, Christian Rauch, Christoph Trassl, Daniel van Vugt, Jonas Ådahl
Translators:
Pawan Chitrakar [ne], Charles Monzat [fr], Dušan Kazik [sk],
Quentin PAGÈS [oc], Alexey Rubtsov [ru], Alexander Shopov [bg],
Florentina Mușat [ro], Chao-Hsiung Liao [zh_TW], Yuri Chornoivan [uk],
Fran Dieguez [gl], Hugo Carvalho [pt], Rafael Fontenelle [pt_BR],
Fabio Tomat [fur], Kukuh Syafaat [id], Yaron Shahrabani [he],
Marek Černocký [cs], Matej Urbančič [sl], Boyuan Yang [zh_CN],
Daniel Mustieles [es]
40.1
====
* Prevent clients from pasting old selection data [Carlos; !1772]
* Fix forward_key IM functionality on wayland [Takao; !1802]
* Ensure valid window texture size after viewport changes [Robert; !1799]
* Only update cached paint volumes when necessary [Jonas D.; !1773, !1829]
* Only disable KMS modifiers for drivers with known problems [Jonas Å; !1792]
* Fix X11 client resize during moves [Olivier; !1777]
* Fix performance drop during night light transition with Nvidia [Aaron; !1816]
* kms: Don't add common modes that exceed the max bandwidth [Jonas Å.; !1834]
* Create virtual input devices on demand [Jonas Å; !1800, !1858]
* Fix wrong night light gamma when leaving power saving [Jonas Å.; !1835]
* Fix picking edge case [Sebastian; !1842]
* Properly tear down things when shutting down [Jonas Å.; !1822, !1856, !1853]
* Fix monitor screencasting with fractional scaling [kirbykevinson; !1855]
* Fixed crash [Carlos; !1849]
* Plugged memory leak [Carlos; !1839]
* Misc. bug fixes and cleanups [Carlos, Daniel, Jonas D., Jonas Å., Robert,
Aleksandr, Florian, Michel, Sebastian, Olivier; !1785, !1798, !1784,
!1791, !1801, !1807, !1786, !1793, !1804, !1820, !1824, !1819, !1803,
!1821, !1806, !1814, !1831, !1832, !1836, !1843, !1740, !1841, !1827,
!1844, !1852, !1850, !1851]
Contributors:
Jonas Ådahl, Michel Dänzer, Jonas Dreßler, Olivier Fourdan, Takao Fujiwara,
Carlos Garnacho, Sebastian Keller, kirbykevinson, Robert Mader,
Aleksandr Mezin, Florian Müllner, Aaron Plattner, Daniel van Vugt
Translators:
Bruce Cowan [en_GB], Ngọc Quân Trần [vi], Marek Černocký [cs],
Dz Chen [zh_CN], Yosef Or Boczko [he], Nathan Follens [nl],
Yuri Chornoivan [uk], Jordi Mas [ca], Piotr Drąg [pl], Tim Sabsch [de],
Luna Jernberg [sv], Hugo Carvalho [pt], Rafael Fontenelle [pt_BR],
Asier Sarasua Garmendia [eu], Quentin PAGÈS [oc], Matej Urbančič [sl]
40.0
====
* xwayland: Check permissions on /tmp/.X11-unix [Olivier; !1787]
Contributors:
Olivier Fourdan
Translators:
Hugo Carvalho [pt], Tim Sabsch [de], Daniel Mustieles [es],
Matej Urbančič [sl], Марко Костић [sr], Fran Dieguez [gl]
40.rc
=====
* Fix keyboard input from remote desktop in Xorg session [Pascal; !1732]
* Fix restoring focus to windows using globally active input [Olivier; !1716]
* Expose unaccalerated touchpad gesture deltas [Alexander; !1353]
* Avoid relayout on text attribute changes when possible [Jonas D.; !1750]
* Add remote desktop caps- and num-lock state properties [Jonas Å.; !1739]
* Improve refresh rate calculation [Akihiko; !1737]
* Implement presentation-time protocol [Ivan; !1484]
* Disable double-buffered shadow buffering [Jonas Å.; !1724]
* Fix missing cursor on tablet devices [Jonas D.; !1758]
* Fix frame timings causing X11 clients to get stuck [Jonas Å.; !1754]
* Fix applying input settings on X11 [Marco, Suryashankar; !1769, !1767]
* Add headless native backend [Jonas Å.; !1698]
* Fix high latency and stalls with proprietary nvidia driver [Daniel; !1726]
* Fix maximized windows not reacting to strut changes [Aleksandr; !1755]
* Only start XWayland on demand when running under systemd [Benjamin; !1771]
* Sync LEDs when a new input device is added [Olivier; !1662]
* Fix order in which subsurface placement operations are handled [Robert; !1768]
* Fixed crashes [Jonas Å., Sebastian; !1745, !1747, !1759, !1748, !1776, !1775]
* Plugged leaks [Philip, Sebastian; !1738, !1728]
* Misc. bug fixes and cleanups [Jonas Å., Jonas D., Ivan, Florian, Marco,
Robert; !1688, !1744, !1736, !1749, !1752, !1753, !427, !1757, !1751, !1760,
!1765, !1770, !1763, !1774, !1780, !1779, !1783]
Contributors:
Jonas Ådahl, Benjamin Berg, Suryashankar Das, Jonas Dreßler, Olivier Fourdan,
Sebastian Keller, Robert Mader, Aleksandr Mezin, Alexander Mikhaylenko,
Ivan Molodetskikh, Florian Müllner, Pascal Nowack, Akihiko Odaki,
Marco Trevisan (Treviño), Daniel van Vugt, Philip Withnall
Translators:
Fran Dieguez [gl], Asier Sarasua Garmendia [eu], Claude Paroz [fr],
Piotr Drąg [pl], Hugo Carvalho [pt], Jordi Mas [ca], Fabio Tomat [fur],
Yuri Chornoivan [uk], Enrico Nicoletto [pt_BR], Emin Tufan Çetin [tr],
Daniel Șerbănescu [ro], Marek Černocký [cs], Balázs Úr [hu],
Aurimas Černius [lt], Kukuh Syafaat [id], A S Alam [pa], Anders Jonsson [sv],
Milo Casagrande [it], Gwan-gyeong Mun [ko]
40.beta
=======
* Consider clients without mapped windows for xwayland auto-shutdown
[Olivier; !1671]
* Let compositor to handle super+scroll events [Florian; !1674, !1695]
* Default to starting Xwayland on demand [Olivier; !1673]
* xwayland: Restore abstract socket support [James, Olivier; !1669]
* Add support for atomic mode setting [Jonas Å.; !1488]
* Fix clip region glitches when using fractional scaling [Daniel; !1554]
* Default to horizontal workspace layout [Georges, Florian; !1684, !1706]
* Do not ping unmanaging windows [Florian; gnome-shell#2467]
* Handle monitor changes during screencasts [Jonas Å.; !1691]
* Fix unexpected jumps after restoring misbehaving clients [Jonas Å.; !1445]
* Fix newly opened X11 windows being invisible in overview [Olivier; !1678]
* Fix viewport of offscreen effects [Daniel; !1053]
* Fix drag cancel animation when using geometry scaling [Robert; !1683]
* Improve touch-mode heuristics [Carlos; !1710]
* Integrate clipboard with remote desktop sessions [Jonas Å.; !1552]
* Fix stuck icon in DND operation between X11 and wayland [Carlos; !1720]
* Automatically synchronize pointer position after modal grabs [Carlos; !1659]
* Reimplement support for CLUTTER_SHOW_FPS [Daniel; !154]
* Only pick on events that may move the pointer [Jonas D.; !1729, !1733]
* Emit discrete scroll events for accumulated smooth events in virtual
X11 devices [Pascal; !1727]
* Add support for rounded clipping when drawing background [Jonas D.; !1717]
* Plugged memory leaks [Sebastian; !1307, !1699]
* Fixed crashes [Carlos, Thomas, Jonas Å., Olivier; !1677, !1685, !1692,
!1719, !1718, !1735]
* Misc. bug fixes and cleanups [Jonas Å., Carlos, Olivier, Sebastian, Björn,
Jonas D., Ivan, Georges, Dor, Michel, Robert; !1670, !1679, !1680, !1682,
!1681, !1661, !1689, !1690, !1693, !1514, !1696, !1697, !1708, !1709, !1707,
!1701, !1702, !1715, !1725, !1734, !1512]
Contributors:
Jonas Ådahl, Dor Askayo, Björn Daase, Michel Dänzer, Jonas Dreßler,
Olivier Fourdan, Carlos Garnacho, James Henstridge, Sebastian Keller,
Robert Mader, Ivan Molodetskikh, Thomas Mühlbacher, Florian Müllner,
Georges Basile Stavracas Neto, Pascal Nowack, Daniel van Vugt
Translators:
Марко Костић [sr], Jordi Mas [ca], Yuri Chornoivan [uk],
Daniel Șerbănescu [ro], Hugo Carvalho [pt], Fran Dieguez [gl],
Matej Urbančič [sl], Marek Černocký [cs], Rafael Fontenelle [pt_BR],
Philipp Kiemle [de], A S Alam [pa], Balázs Úr [hu], Anders Jonsson [sv],
Daniel Mustieles [es], Emin Tufan Çetin [tr], Kukuh Syafaat [id],
Aurimas Černius [lt]
40.alpha.1.1
============
* Adapt to settings moving to gsettings-desktop-schemas [Carlos; !1416]
* Misc. bug fixes and cleanups [Georges; !1667]
Contributors:
Carlos Garnacho, Georges Basile Stavracas Neto
40.alpha.1
==========
* Base ClutterEffects on ClutterPaintNodes [Georges; !1340, !1355]
* xwayland: Set xrandr primary output [Aleksandr; !1558]
* Add paint node based blur support [Georges; !1627, !1646]
* Disable CRTCs if there is no monitor [Kai-Heng; !1561]
* Fix updates of mipmapped animated backgrounds [Daniel; !1664]
* Allow remote desktop clients to specify scroll source [Pascal; !1636]
* Support the color transform matrix RandR property on X11 [Aaron; !1048]
* Plugged memory leaks [Jonas D.; !1632]
* Fixed crashes [Jonas Å., Olivier, Carlos; !1557, !1648, !1643, !1654, !1663]
* Misc. bug fixes and cleanups [Olivier, Niels, Carlos, Jonas Å., Florian,
Jonas D., Daniel, Georges, Michel, Sebastian, Marc-Antoine; !1621, !1622,
!1624, !1623, !1625, !1626, !1630, !1631, !1576, !1635, !1640, !1642,
!1639, !1644, !1637, !1615, !1647, !1633, !1634, !1651, !1652, !1657,
!1660, !1658, !1665, !1649, !1668, !1655]
Contributors:
Jonas Ådahl, Michel Dänzer, Jonas Dreßler, Kai-Heng Feng, Olivier Fourdan,
Carlos Garnacho, Niels De Graef, Sebastian Keller, Aleksandr Mezin,
Florian Müllner, Georges Basile Stavracas Neto, Pascal Nowack,
Marc-Antoine Perennou, Aaron Plattner, Daniel van Vugt
Translators:
Kjartan Maraas [nb], Juliano de Souza Camargo [pt], Florentina Mușat [ro],
Daniel Mustieles [es], Jordi Mas i Hernandez [ca], Fabio Tomat [fur],
Philipp Kiemle [de], Asier Sarasua Garmendia [eu], Aurimas Černius [lt],
Fran Dieguez [gl], Hugo Carvalho [pt], Matej Urbančič [sl]
40.alpha
========
* Replace CoglMatrix with graphene_matrix [Georges; !1439]
* Allow to specify debug topics in MUTTER_DEBUG [Jonas Å.; !1465]
* Fix unwanted position changes on window resize
[Jonas Å., Olivier, Robert; !1477, !1495]
* Do not disable the X Security extension by default [Olivier; !1485]
* Fix _NET_WM_FRAME_DRAWN timestamps [Jonas Å.; !1494]
* Fix tiling to the correct monitor [Florian; #1389]
* Only snap to window edges when CTRL is pressed [Florian; #679609]
* Add support for scroll button locking [Peter; !1432]
* Clip Frustra [Georges; !1489]
* Improve tablet-mode-switch support [Hans; !1506]
* Fix missed redraws of newly-mapped actors [Jonas D.; !1366, #1494]
* Gracefully handle Xwayland crashes [Carlos; !1447]
* wayland: Provide previous window dimensions on restore [Christian; !801]
* Remove the ClutterActor::paint signal [Jonas; !1522]
* Fix background artifacts in magnifier [Daniel; #1480]
* Use raycasting for picking [Georges; !1509]
* Fix monitor tiling support on X11 [Jonas Å.; #1524]
* Fix xwayland grabs for override-redirect windows [Olivier; !1254]
* Fix device configuration not being picked up on X11 [Carlos; !1553]
* Support tagging devices as primary GPU via udev [Jonas Å.; !1562]
* Fix size hints with CSD [Olivier; !1594]
* Fix unresponsive input after screen blank [Simon; !1601]
* Cull actors when picking [Georges; !1520]
* Handle input in a thread [Carlos; !1403]
* Improve freezes when switching workspace [Jonas Å.; !1616]
* Plugged memory leaks [Ray; !1225]
* Fixed crashes [Christian, Olivier, Daniel, Robert, Jonas Å., Florian Z.,
Simon, Carlos; #1481, !1529, !1519, !1534, #1521, !1563, !1604, !1605,
!1607, !1612]
* Misc. bug fixes and cleanups [Florian, Carlos, Olivier, Georges, Björn,
Jonas Å., Julius, Corentin, Bastien, Robert, Daniel, Niels, Jonas D., Uday,
Ian, Jordan, Piotr; !1473, !1472, !1438, #1449, !1475, !1474, !1481, !1466,
!1483, !1427, !1413, !1103, !1467, !1339, !1297, #1384, !1491, !528, !1496,
!1510, !1507, !1387, !1498, !1515, !1516, !1517, !1486, !1524, !1527, !1528,
!1531, !1532, !1521, !1535, #1490, !1545, !1555, !1564, !1549, !1567, !1565,
!1572, !1569, !1573, !1566, !1525, !1468, !1578, !1583, !1584, !1585, !1571,
!1327, !1586, !1590, !1588, !1050, !1596, !1592, !1587, !1599, !1577, !1511,
!1591, !1603, !1611, !1593, !1617, !1619]
Contributors:
Björn Daase, Jonas Dreßler, Piotr Drąg, Olivier Fourdan, Carlos Garnacho,
Hans de Goede, Niels De Graef, Peter Hutterer, Julius Lehmann, Robert Mader,
Simon McVittie, Florian Müllner, Georges Basile Stavracas Neto,
Bastien Nocera, Corentin Noël, Jordan Petridis, Uday Kiran Pichika,
Christian Rauch, Ian Douglas Scott, Ray Strode, Daniel van Vugt,
Florian Zwoch, Jonas Ådahl
Translators:
Juliano de Souza Camargo [pt], Ask Hjorth Larsen [da], Yuri Chornoivan [uk]
3.38.1
3.34.6
======
* Fix Night Light updates after DPMS [Jonas, Benjamin; #1392]
* Fix button scrolling on X11 [Peter; !1431]
* Always use correct font-dpi setting on X11 [Marco; !1444]
* Improve handling of scanout failures [Jonas; #1410]
* Fix middle/right button mixup in scroll button assignment [Peter; !1433]
* Fix resizing of attached modal dialogs on wayland [Jonas; !1446]
* Enable KMS modifiers on devices that need them [Karol; !1443]
* Fix IM handling on X11 [Carlos; #1413]
* Fix glitches in "undefined" screencast areas [Jonas; !1459]
* Fix visual glitches on background with fractional scaling [Daniel; !1464]
* Fix using correct refresh rate [Jonas; #1430]
* Misc. bug fixes and cleanups [Daniel, Carlos, Robert, Simon, Sergio; !1362,
!1448, !1452, !1273, !1454, !1429, !1460, !1458, !1463, !1462]
* Plugged memory leaks [Ray; !1449, !1451]
Contributors:
Marco Trevisan (Treviño), Benjamin Berg, Sergio Costas, Carlos Garnacho,
Karol Herbst, Peter Hutterer, Robert Mader, Simon McVittie, Ray Strode,
Daniel van Vugt, Jonas Ådahl
Translators:
Juliano de Souza Camargo [pt], Rafael Fontenelle [pt_BR],
Yosef Or Boczko [he], Jordi Mas [ca]
3.38.0
======
* screencast: Only use DMA buffers for i915 [Jonas; !1442]
* Fixed crashes [Jonas, Simon; !1430, #1414]
Contributors:
Simon McVittie, Jonas Ådahl
Translators:
Anders Jonsson [sv], Gil Forcada [ca], Balázs Meskó [hu], Tim Sabsch [de],
Milo Casagrande [it], Bruce Cowan [en_GB], Rūdolfs Mazurs [lv]
3.37.92
=======
* Fix stale cursor positions in remote desktop sessions [Georges; !1417]
* xwayland: Add a setting to disable selected X extensions [Olivier; !1405]
* Fix screencasting when using QXL [Jonas Å., Grey; !1318]
* Cull actors that don't intersect with the redraw clip [Daniel; !1359]
* Optimize painting of backgrounds when culling is unavailable [Daniel; !1363]
* Improve support for Hangul input method [Carlos; !1286]
* Support debug paint overlay for opaque regions [Robert; !1372]
* Fix launching flatpak applications when autostarting Xwayland [Carlos; !1424]
* Add support for capture scanouts in screencasts [Georges; !1421]
* Allow integrated tablet devices to cycle outputs [Carlos; !1201]
* Improve mapping input devices to the most relevant output [Carlos; !1202]
* Only enable auto-rotation in touch mode [Carlos; !1311]
* Fixed crashes [Pascal, Robert, Carlos, Benjamin, Marco; !1414, !1409, !1408,
!1415, #1395, !1392, !1371, #1345]
* Misc. bug fixes and cleanups [Björn, Jonas D., Florian; !1410, !1358, !1425]
Contributors:
Marco Trevisan (Treviño), Benjamin Berg, Grey Christoforo, Björn Daase,
Jonas Dreßler, Olivier Fourdan, Carlos Garnacho, Robert Mader,
Florian Müllner, Georges Basile Stavracas Neto, Pascal Nowack,
Daniel van Vugt, Jonas Ådahl
Translators:
Marek Černocký [cs], Aurimas Černius [lt], Asier Sarasua Garmendia [eu],
Gwan-gyeong Mun [ko], Yuri Chornoivan [uk], Boyuan Yang [zh_CN],
Kukuh Syafaat [id], Piotr Drąg [pl], Rafael Fontenelle [pt_BR],
Марко Костић [sr], Matej Urbančič [sl], Fabio Tomat [fur],
Daniel Mustieles [es], Fran Dieguez [gl], Goran Vidović [hr],
Claude Paroz [fr], Andre Klapper [or, ug, te], Emin Tufan Çetin [tr]
3.37.91
=======
* Fix initial state of display mode OSD [Jian-Hong; #1362]
* Fixed crashes [Jonas Å., Robert; !1407, !1411]
* Misc. bug fixes and cleanups [Jonas Å., Christian; !1404, !1364, #1331]
Contributors:
Jonas Ådahl, Robert Mader, Jian-Hong Pan, Christian Rauch
Translators:
Fran Dieguez [gl], Daniel Mustieles [es], Florentina Mușat [ro],
Kukuh Syafaat [id], Piotr Drąg [pl], Emin Tufan Çetin [tr], Марко Костић [sr],
Akarshan Biswas [bn_IN], Matej Urbančič [sl], Boyuan Yang [zh_CN],
Goran Vidović [hr], Rafael Fontenelle [pt_BR]
3.37.90
=======
* Fix using NEAREST filter for backgrounds on scaled monitors [Daniel V.; !1346]
* Screencast fixes and improvements [Jonas; !1361, !1377, !1391]
* Support tap-button-map and tap-drag-lock touchpad settings [Giusy; !1319]
* Fix wine copy & paste [Sebastian; !1369]
* Fix shadows of server-side decorated XWayland windows [Olivier; #1358]
* Replace some loaded terms with more descriptive ones [Olivier; !1396]
* Add API to launch trusted wayland clients [Sergio; #741]
* Skip displays with 'non-desktop' property set [Philipp; !1393]
* Invalidate offscreen effect cache on video memory purge [Daniel V.; !1374]
* Add wl_shm support for 10 bpc and 16 bpc half float formats [Jonas; !804]
* Fixed crashes [Jonas, Erik, Martin; !1365, !1375, #1343]
* Misc. bug fixes and cleanups [Daniel V., Carlos, Olivier, Christian,
Daniel * G., Jonas, Florian; !1370, !1376, !1385, !1352, !1386, !1390,
!1388, !1397, !1398, !1401]
Contributors:
Jonas Ådahl, Sergio Costas, Olivier Fourdan, Carlos Garnacho,
Christian Hergert, Sebastian Keller, Erik Kurzinger, Giusy Margarita,
Daniel García Moreno, Florian Müllner, Daniel van Vugt, Martin Whitaker,
Philipp Zabel
Translators:
Fabio Tomat [fur], Rafael Fontenelle [pt_BR], Jordi Mas [ca],
Yuri Chornoivan [uk], Alexandre Franke [fr]
3.37.3
======
* Support custom keyboard layouts in $XDG_CONFIG_HOME/xkb [Peter; !936]
* Optimize resource scale computation [Jonas D.; !1196, !1276, !1343]
* Allow animating ClutterActor's content property [Georges; !1301]
* Implement backgrounds as ClutterContent [Georges; !1302]
* Add ClutterAlignContraint:pivot-point property [Jonas D.; !737]
* Fix crash on area screenshots with fractional scaling [Sebastian; !1320]
* Do not paint textures of fully obscured windows [Robert; !1326]
* Use a more appropriate combine function on opaque areas [Daniel; !1331]
* Fix remote desktop being broken without screencast session [Olivier; #1307]
* Remove more long-deprecated Clutter APIs [Adam, Georges; !1194, !1332]
* Drive each monitor by its own frame clock [Jonas Å.; !1285]
* Fix copy/paste failures on X11 [Carlos; !1350]
* Mipmap background texture rendering [Daniel; !1347]
* Plugged memory leaks [Sebastian, Jonas D.; !1293, !1281, !1304]
* Misc. bug fixes and cleanups [Jonas Å., Jonas D., Daniel, Corentin, Carlos,
Sebastian, Michel, Robert, Florian; !1288, !1289, !1291, !1296, !1292, !1298,
!1300, !1303, !1290, !1287, !1306, !1305, !1308, !1313, !1250, !1314, !1267,
!1275, !1317, !1270, !1322, !1181, !1282, !1325, !1323, !1240, !1295, !1329,
!1333, !1334, !1336, !1341, #1312, !1345, !1349, !1356, #873, !1310, !1357]
Contributors:
Jonas Dreßler, Michel Dänzer, Olivier Fourdan, Carlos Garnacho,
Peter Hutterer, Adam Jackson, Sebastian Keller, Robert Mader, Florian Müllner,
Georges Basile Stavracas Neto, Corentin Noël, Daniel van Vugt, Jonas Ådahl
3.37.2
======
* Fix move-to-center keybinding with multiple monitors [Sergey; #1073]
* Fix stuck buttons when a virtual device is destroyed [Carlos; !1239]
* Use workarea when centering new windows [Akatsuki; #964]
* Limit mipmap levels when rendering background [Daniel; !1003]
* Broadcast clipboard/primary offers [Carlos; !1253]
* Support primary-selection protocol from wayland-protocols [Carlos; !1255]
* Fix monitor screen cast on X11 [Jonas Å.; !1251]
* Support a "blank" cursor type [Florian; !1244]
* Improve stage view damage tracking [Jonas Å.; !1237]
* Implement touch-mode detecation for the X11 backend [Carlos; !1278]
* Drop external keyboard detection from touch-mode heuristics [Carlos; !1277]
* Optimize actor allocations [Jonas D.; !1247]
* Fixed crashes [Daniel, Carlos, Jonas Å., Jonas D.; !1256, !1258, !1217, !1280]
* Misc. bug fixes and cleanups [Christian, Jonas D., Olivier, Ting-Wei,
Jonas Å., Marco, Corentin, Daniel, Robert, Niels, Florian, Simon; !1231,
!1228, !1238, !1229, !1192, !1236, !1171, !1134, #1126, !1234, !1230, !1210,
!1242, !1243, !1252, !1113, !1232, !1259, !1245, !1265, !1180, !1261, !788,
!1264, !1235, !1218, !1150, !1274, !1271, !1279, !1283, !1272]
Contributors:
Marco Trevisan (Treviño), Akatsuki, Jonas Dreßler, Olivier Fourdan,
Carlos Garnacho, Niels De Graef, Ting-Wei Lan, Robert Mader, Simon McVittie,
Florian Müllner, Corentin Noël, Christian Rauch, Daniel van Vugt,
Sergey Zigachev, Jonas Ådahl
3.37.1
======
* Fix screencasting non-maximized windows [Jonas Å.; !1174]
* Make window-aliveness checks less aggressive [Jonas Å.; !1182]
* Fix stylus coordinates when using screen rotation [Jonas T.; #1118]
* Preserve keyboard state on VT switch [Olivier; !1185]
* Remove Clutter's drag and drop actions [Jonas D.; !789]
* Cancel clicks/gestures actions on disable [Georges; !1188]
* Fix various clipboard issues [Carlos; !1186, !1198, !1203, !1204, !1206]
* Fix trackball button scrolling [Phillip; #1120]
* Fix tiled monitor support [Jonas; !1199]
* Support unredirecting fullscreen wayland surfaces [Jonas Å.; !798]
* Support area screencasts [Jonas Å.; !1207]
* Synchronize shadows to server-side decorations [Olivier; !1214]
* Allow inhibiting remote access [Jonas Å.; !1212]
* Fix various clipboard issues [Carlos; !1198, !1203, !1204, !1186, !1206]
* Fix locate-pointer feature interfering with keybindings [Carlos; !1014]
* Fix overview key on X11 when using multiple keyboard layouts [Olivier; !1219]
* Fixed crashes [Jonas, D., Carlos; !1173, !1183, !1012]
* Misc. bug fixes and cleanups [Andre, Georges, Christian, Jonas Å., Andre,
Simon, Florian, Carlos, Adam, Marco, Thomas, Elias, Pekka, Jonas D.,
Laurent; !1169, !1168, !1166, !1170, !1167, !1172, !1175, !1176, !1184,
!1126, !1187, !1191, !1195, !1179, !1200, !1193, !1209, !1213, !1208,
#1074, !1223]
* Preserve keyboard state on VT switch [Olivier; !1185]
* Fixed crashes [Florian; #1083]
* Plugged memory leaks [Sebastian; !1001]
* Misc. bug fixes and cleanups [Pekka, Laurent; !1209, #1074]
Contributors:
Marco Trevisan (Treviño), Elias Aebi, Thomas Hindoe Paaboel Andersen,
Laurent Bigonville, Jonas Dreßler, Olivier Fourdan, Carlos Garnacho,
Adam Jackson, Andre Moreira Magalhaes, Simon McVittie, Florian Müllner,
Georges Basile Stavracas Neto, Pekka Paalanen, Christian Rauch, Jonas Troeger,
Phillip Wood, Jonas Ådahl
Laurent Bigonville, Olivier Fourdan, Carlos Garnacho, Sebastian Keller,
Florian Müllner, Pekka Paalanen
Translators:
Dušan Kazik [sk], Christian Kirbach [de]
3.36.0
3.34.5
======
* Fix placement of popup windows in multi-monitor setups [Jonas; !1110]
* Fix invisible mouse cursor on some hardware [Jonas; !1079]
* Fix visibility of initially hidden windows [Jonas; !1066]
* Fix hardware cursor on GPU hotplug [Pekka; !1097]
* Fix pasting images from wayland [Robert, Carlos; !1141, #1065]
* Fixed crashes [Florian, Olivier, Jonas; #1029, !1073, !1121, !1120]
Contributors:
Jonas Ådahl
Olivier Fourdan, Carlos Garnacho, Robert Mader, Florian Müllner,
Pekka Paalanen, Jonas Ådahl
Translators:
Aurimas Černius [lt], Goran Vidović [hr], Anders Jonsson [sv],
Guillaume Bernard [fr], Milo Casagrande [it], Daniel Korostil [uk],
Andre Klapper [cy], Aman Alam [pa], Nathan Follens [nl]
3.35.92
=======
* Fix visibility of initially hidden windows [Jonas Å.; !1066]
* Avoid flicker when (un)redirecting windows [Sebastian; #997]
* Let BindConstraints update the preferred size [Emmanuele; !1070]
* Learn about GLES3 [Adam; !882]
* Ping windows on every window focus [Jonas D.; !891]
* Remove overhead from hot code paths [Christian;
#1056, !1081, !1083, !1071, !1087]
* Allow remote desktop services to inhibit animations [Jonas Å.; !838]
* Update screen-cast code to PipeWire 0.3 API [Wim; !1062]
* Make check-alive timeouts configurable [Jonas Å.; !1080]
* Make each stage view correspond to a single CRTC [Jonas Å.; !1042]
* Implement scaled/transformed hardware cursors [Robert; !526]
* Use DMA buffers for screencasting if possible [Georges; !1086]
* Make Xwayland startup asynchronous [Carlos; !944]
* Fix clipping glitches in long text entries [Jonas D.; !1096]
* Add side channel for starting required X11 services [Carlos; !945]
* Support synchronized wayland popup moving [Jonas Å.; !705]
* Fixed crashes [Olivier, Jonas Å.; !1073, !1093]
* Plugged memory leaks [Sebastian, Jonas Å.; !1089, !1095]
* Misc. bug fixes and cleanups [Jonas Å, Olivier, Florian, Daniel, Jonas D.,
Robert, Sebastian, Christian, Arun, Carlos, worldofpeace; !1061, #1043,
!1067, !1068, !1065, !835, !1058, !1069, !1075, #1060, !1077, !423, !1090,
!1088, !1094, #1067, !1064, !1099, !957, !1000, !1082]
Contributors:
Emmanuele Bassi, Jonas Dreßler, Olivier Fourdan, Carlos Garnacho,
Christian Hergert, Adam Jackson, Sebastian Keller, Robert Mader,
Florian Müllner, Georges Basile Stavracas Neto, Arun Raghavan, Wim Taymans,
Daniel van Vugt, worldofpeace, Jonas Ådahl
Translators:
Yi-Jyun Pan [zh_TW], Asier Sarasua Garmendia [eu], Rafael Fontenelle [pt_BR],
Emin Tufan Çetin [tr], Daniel Mustieles [es], Balázs Úr [hu],
Gwan-gyeong Mun [ko], Marek Černocký [cs], Fran Dieguez [gl],
Kukuh Syafaat [id], Alan Mortensen [da], Piotr Drąg [pl], sicklylife [ja],
Matej Urbančič [sl]
3.35.91
=======
* Honor accelerometer orientation on monitor config changes [Hans; !959]
* Enable culling for integer-scaled actors [Robert; !1036]
* Add ClutterSeat::touch-mode property [Carlos; !1044]
* Fix mis-scaling when streaming windows [Olivier; !1022]
* Make the cursor renderer use the transactional KMS API [Jonas; !930]
* Advertise MetaMonitor as wl_output [Olivier; !994]
* Fix culling of XWayland windows [Robert; !1049]
* Only consider enabled effects when disabling culling [Robert; !1052]
* Misc. bug fixes and cleanups [Olivier, Sergio, Adam, Carlos, Björn; !1040,
#985, !1024, !1039, !1051]
Contributors:
Sergio Costas, Björn Daase, Olivier Fourdan, Carlos Garnacho, Hans de Goede,
Adam Jackson, Robert Mader, Jonas Ådahl
Translators:
sicklylife [ja]
3.35.90
=======
* Cull out clip region [Robert; !985]
* Always enable tap-to-click/drag on opaque Wacom tablets [Carlos; !968]
* Fix visual glitches with offscreen effects applied [Georges; !992]
* Fix "sticky corner" in multi-head setups [Jonas D.; #774]
* Fix black shadows around XWayland windows during resizes [Ray, Olivier; #858]
* Zero-copy path for GPU-less secondary GPUs [Pekka; !810]
* Cancel DND on Esc [Carlos; #1020]
* Sync XWayland window shadows to frame during resizes [Olivier; !1009]
* Add support for per-monitor workareas [Alberts; !370]
* Ensure newly mapped wayland windows receive ENTER event [Olivier; !1026]
* Add ClutterSeat object [Carlos; !852]
* Honour CLUTTER_ACTOR_NO_LAYOUT flag more efficiently [Daniel; !575]
Yi-Jyun Pan [zh_TW]
3.34.4
======
* Handle mode set race conditions more gracefully [Jonas; !1007]
* Fix fallback to GLES2 [Adam; #635]
* Fix interoperation with wl_data_device_manager v1 [Carlos; #965]
* Fix visual glitches with offscreen effects applied [Georges; !992]
* Favor text over images in clipboard manager [Carlos; #919]
* Apply monitor scale after background texture creation [Daniel; !1004]
* Plugged memory leaks [Sebastian, Adam; !991, #1000, !1011, !1020, !1030,
!1001, !1033]
* Fixed crashes [Jonas Å., Florian, Olivier; !961, #1029, !1037]
* Misc. bug fixes and cleanups [Björn, Jonas Å., Adam, Sebastian, Jonas D.,
Daniel, Carlos, Corentin, Sebastian, Robert, Daniel; #385, !998, !1007, !995,
!1016, !1018, !1017, !1005, !1019, !1025, !1028, !1029, !1031, !1015, !1032,
!1034, #1025]
* Fixes crashes [Jonas, Carlos; !961, !869]
* Plugged memory leaks [Sebastian, Adam; !1002, !1011]
* Misc. bug fixes [Carlos, Robert, Olivier; !1005, #878, !1031, !1034, !1040]
Contributors:
Björn Daase, Jonas Dreßler, Olivier Fourdan, Carlos Garnacho, Adam Jackson,
Sebastian Keller, Robert Mader, Alberts Muktupāvels, Florian Müllner,
Georges Basile Stavracas Neto, Corentin Noël, Pekka Paalanen, Ray Strode,
Daniel van Vugt, Jonas Ådahl
Olivier Fourdan, Carlos Garnacho, Adam Jackson, Sebastian Keller,
Robert Mader, Georges Basile Stavracas Neto, Jonas Ådahl
Translators:
sicklylife [ja], Umarzuki Bin Mochlis Moktar [ms]
Umarzuki Bin Mochlis Moktar [ms]
3.35.3
3.34.3
======
* backends/native: Correct dy value in pinch gesture event [Yariv; !974]
* Upload clipping rectangles in parallel [Daniel; !969]
* More cogl API cleanups [Adam; !978, !977, !973]
* Fix window recording on HiDPI [Pascal; !976]
* Fix top-left pixel being insensitive to clicks [Sebastian; #893]
* Misc. bug fixes and cleanups [Daniel, Adam; !979, !980]
Contributors:
Yariv Barkan, Adam Jackson, Sebastian Keller, Pascal Nowack, Daniel van Vugt
Sebastian Keller, Pascal Nowack
Translators:
Fran Dieguez [gl], Dz Chen [zh_CN]
3.35.2
3.34.2
======
* Don't emit focus event after destruction [Marco; gnome-shell#1704, !860]
* Add a notion of pixel format planes [Niels; !858]
* Replace various Cogl/Clutter types with Graphene [Georges; !458]
* Improve CoglJournal [Georges, Jasper; !402]
* Split pick and paint [Georges; !865]
* Remove deprecated/unused cogl/clutter APIs [Adam; !866, !878, !879, !880,
!885, !900, !902, !904, !896, !913, !922, !883, !903, !921, !933, !819]
* Fix immediate screen blank after releasing inhibitor [Tim; #573]
* Respond to frame callbacks regardless of damage [Jonas Å.; !839]
* Translate well-known selection atoms to mimetypes [Carlos; !842]
* Fix Night Light on wayland [Jonas Å.; !840]
* Fix various copy+paste/DND regressions [Carlos; !848, #789, #842,
#793, #845, #854]
* Don't emit focus event after desctruction [Marco; gnome-shell#1704, !860]
* Fix hang when opening not-responding dialog on Xorg [Carlos; !876]
* Allow changing Clutter debug flags at runtime [Georges; !862]
* Fix frozen grabs on Xorg after weeks of inactivity [Jonas; !886]
* Fix triggering popups from stylus devices o wayland [Carlos; #886]
* Fix fallback to GLES2 [Adam; #635]
* Fix buffer age checks on multiple monitors [Carlos; !906]
* Adjust to Sysprof API change [Christian; !908]
* Improve support for (X11) fullscreen games under wayland [Hans; !739]
* Support shadow framebuffers for offscreen rendering [Olivier; !877]
* Fix frozen grabs on Xorg after weeks of inactivity [Jonas Å.; !886]
* Fix triggering popups from stylus devices on wayland [Carlos; #886]
* Support shadow framebuffers for offscreen rendering [Olivier; !917]
* Fix hang after interacting with desktop icons on X11 [Marco; !909]
* Don't double scale when getting absolute surface coordinates [Xiang; !915]
* Respect NET_WM_TRANSIENT_FOR for override-redirect windows [Marco; !920]
* Kill window effects on destroy [Robert; !924]
* Remove deprecated ClutterTexture [Jonas; !932]
* Use regions instead of bounding box for clipping and culling [Carlos; !867]
* Use partial damage for dma-buf and EGLImage buffers on wayland [Robert; #947]
* Do not stack transients underneath their always-on-top parent [Florian; #587]
* Add explicit paint/pick contexts [Jonas; !935]
* Fix KMS freeze after pageflip fallback [Pekka; !953]
* Fixed crashes [Robert, Carlos, Jonas, Marco, Hans, Tim; !856, !869, !912,
!895, !928, #591, !823, !960]
* Plugged memory leaks [Niels, Robert, Carlos, Marco; !847, !868, !873, #908]
* Misc. bug fixes and cleanups [Niels, Robert, Jonas, Marco, Carlos, Daniel,
Jan, Adam, Cosimo, Florian, Thomas, Georges, Hans, Corentin, Christian,
Benjamin; !853, !822, !451, !854, !816, !857, !859, !734, !844, !851, #876,
!874, !673, !692, !888, !889, !894, !901, !905, !872, !898, !911, !918, !863,
#878, !811, !893, !925, !926, !890, !931, !927, !934, !938, !940, !947, !941,
!929, !949, !952, !871, !955, !956, !958, !907, !965, !964, !966]
* Fix KMS freeze after pageflip [Pekka; !953]
* Fixed crashes [Robert, Jonas Å., Marco, Hans, Carlos, Tim; !856, !912, !895,
!928, #591, !823, !960]
* Plugged memory leaks [Niels, Robert, Carlos; !847, !868, !873]
* Misc. bug fixes and cleanups [Daniel, Marco, Jonas Å., Georges, Cosimo,
Florian, Hans, Robert, Jonas D.; !841, !764, !837, !846, !673, !811, !893,
!925, !927, !940, !832]
Contributors:
Marco Trevisan (Treviño), Jan Alexander Steffens (heftig),
Thomas Hindoe Paaboel Andersen, Benjamin Berg, Cosimo Cecchi, Tim Crawford,
Piotr Drąg, Xiang Fan, Olivier Fourdan, Carlos Garnacho, Hans de Goede,
Niels De Graef, Christian Hergert, Adam Jackson, Robert Mader,
Florian Müllner, Georges Basile Stavracas Neto, Bastien Nocera, Corentin Noël,
Pekka Paalanen, Jasper St. Pierre, Christian Rauch, Daniel van Vugt,
Jonas Ådahl
Marco Trevisan (Treviño), Cosimo Cecchi, Tim Crawford, Jonas Dreßler,
Xiang Fan, Olivier Fourdan, Carlos Garnacho, Hans de Goede, Niels De Graef,
Tim Klocke, Robert Mader, Florian Müllner, Georges Basile Stavracas Neto,
Pekka Paalanen, Daniel van Vugt, Jonas Ådahl
Translators:
Bruce Cowan [en_GB]
3.35.1
======
* Fix immediate screen blank after releaseing inhibitor [Tim; #573]
* Respond to frame callbacks regardless of damage [Jonas; !839]
* selection [Carlos; !842]
* Fix Night Light on wayland [Jonas; !840]
* Fix various copy+paste/DND regressions [Carlos; !848, #789, #842,
#793, #845, #854]
* Misc. bug fixes and cleanups [Daniel, Marco, Jonas, Georges;
!841, !764, !837, !846]
Contributors:
Marco Trevisan (Treviño), Carlos Garnacho, Tim Klocke,
Georges Basile Stavracas Neto, Daniel van Vugt, Jonas Ådahl
3.34.1
======
* Fix startup of X11 session services on wayland [Carlos; #771]
@ -994,7 +344,7 @@ Contributors:
3.31.92
=======
* Fix flicker of apps that use multiple SHM buffers [Jonas Å.; #199]
* Don't disable page flips after temporary failures [Jonas Å.; #460]
* Don't disable page flips after temporary failues [Jonas Å.; #460]
* Improve redraw performance [Carlos; !196]
* Add cursor-mode support to window screencasting [Jonas Å.; !413]
* Add back support for system-wide monitor configurations [Jonas Å.; !253]
@ -1406,7 +756,7 @@ Translations:
=======
* Reduce memory use of suspended instances [Jonas; #786299]
* Make supported scales determination saner [Rui; #786474]
* Fix crash on inhibit-shortcuts dialog response [Jonas; #786385]
* Fix crash on inhibit-shortcuts dialog reponse [Jonas; #786385]
* Support libinput's tag-and-drag setting [freeroot; #775755]
* Avoid overlapping keybindings with multiple layouts [Jonas; #786408]
* Fix non-transformed cursor on rotated monitors [Jonas; #786023]
@ -1725,7 +1075,7 @@ Translations:
* Consider XDG_SESSION_TYPE when determining session type [Jouke; #759388]
* Re-add support for edge scrolling on some touchpads [Bastien; #768245]
* Support mouse and trackball acceleration profile [Jonas; #769179]
* Draw monitor content to individual framebuffer [Jonas; #768976]
* Draw monitor contentn to individual framebuffer [Jonas; #768976]
* Support virtual input devices [Jonas, Carlos; #765009]
* Set correct output scale on hotplug [Jonas; #769505]
* Misc. bug fixes and cleanups [Florian, Jonas, Thomas, Bastien, Carlos;
@ -2550,7 +1900,7 @@ Translations:
* Ignore skip-taskbar hints on parentless dialogs [Giovanni; #673399]
* Don't save pixbuf data in user data [Tim; #706777]
* Don't queue redraws for obscured regions [Adel; #703332]
* Support the opaque region hints for wayland clients [Jasper; #707019]
* Suppor the opaque region hints for wayland clients [Jasper; #707019]
* Turn blending off when drawing entirely opaque regions [Jasper; #707019]
* Check event timestamps before reconfiguring [Giovanni; #706735]
* Merge the DBus API for display configuration in the wayland branch [Giovanni]
@ -3035,7 +2385,7 @@ Translations:
======
* Automaximize large windows on map [Adel; #671677]
* When unmaximizing windows, make sure the unminimized size
is significantly less than the maximized size [Adel; #671677]
is signficantly less than the maximized size [Adel; #671677]
* Don't offer maximize option for windows larger than the screen
[Jasper; #643606]
* Always focus the window immediately underneath without restacking
@ -3135,7 +2485,7 @@ Translations:
* Move from GConf to GSettings for preferences [Florian; #635378]
* Add meta_display_add_keybinding()/meta_display_remove_keybinding()
to allow creating new keybindings at runtime [Florian; #663428]
* Add support for new _NET_WM_STATE_FOCUSED atom in _NET_WM_STATE
* Add suport for new _NET_WM_STATE_FOCUSED atom in _NET_WM_STATE
to allow applications to draw unfocused windows differently
[Rui; #661427]
* Add meta_window_move_resize_frame() to allow specifying the
@ -3247,7 +2597,7 @@ Contributors:
for easy resizing with thin borders. (New draggable_border_width GConf key
controls the total width of visible and invisible borders.)
[Jasper; #644930]
* Draw rounded window corners with antialiasing [Jasper; #628195]
* Draw rounded window corners with antialising [Jasper; #628195]
* Unredirect override-redirect fullscreen windows, such as full-screen
3D games to avoid any performance impact [Adel; #597014]
* Add :resizable and :above properties to MetaWindow. [Tim; #653858]
@ -3340,7 +2690,7 @@ Translations:
3.0.2.1
=======
* When saving the session, use the "program name" rather than
hardcoding mutter, fixing session saving for gnome-shell [Matthias]
harcoding mutter, fixing session saving for gnome-shell [Matthias]
https://bugzilla.gnome.org/show_bug.cgi?id=648828
Contributors:
@ -3658,7 +3008,7 @@ Bugs fixed:
634779 MetaWindowGroup: further optimize paints by using current scissor
634833 Draw the root window background
592382 improve shadow effect
628199 Add antialiasing to arc and line drawing operations
628199 Add antialising to arc and line drawing operations
633002 meta-actor-window: Use G_UNLIKELY for TFP check
634771 MetaStackTracker: Avoid queueing resync for obvious no-ops
635421 Fix crash in check_needs_shadow
@ -3855,7 +3205,7 @@ Fixed Bugs:
- Allow a theme to turn on title ellipsization
* Performance enhancements:
- Stream raw damage updates to ClutterX11TexturePixmap
to enable partial stage updates when windows change [Robert]
to enable partial stage updates when windos change [Robert]
- Don't trap XErrors in meta_compositor_process_event [Adel]
* Add meta_prefs_override_preference_location(); this allows
a plugin like GNOME Shell to redirect preferences to a
@ -3900,7 +3250,7 @@ Fixed Bugs:
613136 - remove over-restrictive assert from meta_prefs_get_workspace_name()
613398 - Don't trap XErrors in meta_compositor_process_event
615586 - Allow redirecting preferences to a different GConf key
615672 - can't compile mutter error: dereferencing pointer p does break
615672 - cant' compile mutter error: dereferencing pointer p does break
strict-aliasing rules
616050 - alt-tab infrastructure patches
616274 - mutter from git fails with gcc 4.5 (on new warning)
@ -4846,7 +4196,7 @@ Arthur Taylor, Elijah Newren, Josselin Mouette, Havoc Pennington,
Benjamin Berg, and Carlo Wood for improvements in this release.
- new icon for the force-quit dialog (Jaap) [#396655]
- add configurable mouse click action abilities, and clean up lots of
- add configureable mouse click action abilities, and clean up lots of
related code (Linus) [#408899, #408902, others]
- add schemeas for middle and right click titlebar actions (Charlie)
[#408903]
@ -5400,7 +4750,7 @@ this release.
running with --disable-gconf. Make --disable-gconf actually work.
(Elijah) [#326661]
- fix some reading-from-free'd-data errors (Søren) [#327575]
- fix an uninitialized value problem when in raise-on-click mode
- fix an unitialized value problem when in raise-on-click mode
(Søren) [#327572]
- avoid flashing original-sized window when closing a maximized
window (Elijah) [#317254]

View File

@ -26,34 +26,15 @@ debugging purposes.
To contribute, open merge requests at https://gitlab.gnome.org/GNOME/mutter.
It can be useful to look at the documentation available at the
[Wiki](https://gitlab.gnome.org/GNOME/mutter/-/wikis/home).
## Coding style and conventions
See [HACKING.md](./HACKING.md).
## Git messages
The coding style used is primarily the GNU flavor of the [GNOME coding
style](https://developer.gnome.org/programming-guidelines/stable/c-coding-style.html.en)
with some minor additions such as preferring `stdint.h` types over GLib
fundamental types, and a soft 80 character line limit. However, in general,
look at the file you're editing for inspiration.
Commit messages should follow the [GNOME commit message
guidelines](https://wiki.gnome.org/Git/CommitMessages). We require an URL
to either an issue or a merge request in each commit. Try to always prefix
commit subjects with a relevant topic, such as `compositor:` or
`clutter/actor:`, and it's always better to write too much in the commit
message body than too little.
## Default branch
The default development branch is `main`. If you still have a local
checkout under the old name, use:
```sh
git checkout master
git branch -m master main
git fetch
git branch --unset-upstream
git branch -u origin/main
git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main
```
to either an issue or a merge request in each commit.
## License

View File

@ -1,138 +0,0 @@
#!/bin/env python3
import argparse
import os
import re
import subprocess
import sys
import tempfile
# Path relative to this script
uncrustify_cfg = 'tools/uncrustify.cfg'
def run_diff(sha):
proc = subprocess.Popen(["git", "diff", "-U0", "--function-context", sha, "HEAD"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
files = proc.stdout.read().strip().decode('utf-8')
return files.split('\n')
def find_chunks(diff):
file_entry_re = re.compile('^\+\+\+ b/(.*)$')
diff_chunk_re = re.compile('^@@ -\d+,\d+ \+(\d+),(\d+)')
file = None
chunks = []
for line in diff:
match = file_entry_re.match(line)
if match:
file = match.group(1)
match = diff_chunk_re.match(line)
if match:
start = int(match.group(1))
len = int(match.group(2))
end = start + len
if len > 0 and (file.endswith('.c') or file.endswith('.h') or file.endswith('.vala')):
chunks.append({ 'file': file, 'start': start, 'end': end })
return chunks
def reformat_chunks(chunks, rewrite):
# Creates temp file with INDENT-ON/OFF comments
def create_temp_file(file, start, end):
with open(file) as f:
tmp = tempfile.NamedTemporaryFile()
tmp.write(b'/** *INDENT-OFF* **/\n')
for i, line in enumerate(f):
if i == start - 2:
tmp.write(b'/** *INDENT-ON* **/\n')
tmp.write(bytes(line, 'utf-8'))
if i == end - 2:
tmp.write(b'/** *INDENT-OFF* **/\n')
tmp.seek(0)
return tmp
# Removes uncrustify INDENT-ON/OFF helper comments
def remove_indent_comments(output):
tmp = tempfile.NamedTemporaryFile()
for line in output:
if line != b'/** *INDENT-OFF* **/\n' and line != b'/** *INDENT-ON* **/\n':
tmp.write(line)
tmp.seek(0)
return tmp
changed = None
for chunk in chunks:
# Add INDENT-ON/OFF comments
tmp = create_temp_file(chunk['file'], chunk['start'], chunk['end'])
# uncrustify chunk
proc = subprocess.Popen(["uncrustify", "-c", uncrustify_cfg, "-f", tmp.name], stdout=subprocess.PIPE)
reindented = proc.stdout.readlines()
proc.wait()
if proc.returncode != 0:
continue
tmp.close()
# Remove INDENT-ON/OFF comments
formatted = remove_indent_comments(reindented)
if dry_run is True:
# Show changes
proc = subprocess.Popen(["diff", "-up", "--color=always", chunk['file'], formatted.name], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
diff = proc.stdout.read().decode('utf-8')
if diff != '':
output = re.sub('\t', '\t', diff)
print(output)
changed = True
else:
# Apply changes
diff = subprocess.Popen(["diff", "-up", chunk['file'], formatted.name], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
patch = subprocess.Popen(["patch", chunk['file']], stdin=diff.stdout)
diff.stdout.close()
patch.communicate()
formatted.close()
return changed
parser = argparse.ArgumentParser(description='Check code style.')
parser.add_argument('--sha', metavar='SHA', type=str,
help='SHA for the commit to compare HEAD with')
parser.add_argument('--dry-run', '-d', type=bool,
action=argparse.BooleanOptionalAction,
help='Only print changes to stdout, do not change code')
parser.add_argument('--rewrite', '-r', type=bool,
action=argparse.BooleanOptionalAction,
help='Whether to amend the result to the last commit (e.g. \'git rebase --exec "%(prog)s -r"\')')
# Change CWD to script location, necessary for always locating the configuration file
os.chdir(os.path.dirname(os.path.abspath(sys.argv[0])))
args = parser.parse_args()
sha = args.sha or 'HEAD^'
rewrite = args.rewrite
dry_run = args.dry_run
diff = run_diff(sha)
chunks = find_chunks(diff)
changed = reformat_chunks(chunks, rewrite)
if dry_run is not True and rewrite is True:
proc = subprocess.Popen(["git", "commit", "--all", "--amend", "-C", "HEAD"], stdout=subprocess.DEVNULL)
os._exit(0)
elif dry_run is True and changed is True:
print ("\nIssue the following command in your local tree to apply the suggested changes (needs uncrustify installed):\n\n $ git rebase origin/main --exec \"./check-style.py -r\" \n")
os._exit(-1)
os._exit(0)

View File

@ -28,7 +28,7 @@
#include "cally-actor.h"
/*
* Auxiliary define, in order to get the clutter actor from the AtkObject using
* Auxiliar define, in order to get the clutter actor from the AtkObject using
* AtkGObject methods
*
*/

View File

@ -72,7 +72,9 @@
#include <glib.h>
#include <clutter/clutter.h>
#include "clutter/clutter-actor-private.h"
#ifdef CLUTTER_WINDOWING_X11
#include <clutter/x11/clutter-x11.h>
#endif
#include <math.h>
@ -308,7 +310,11 @@ cally_actor_finalize (GObject *obj)
_cally_actor_clean_action_list (cally_actor);
g_clear_handle_id (&priv->action_idle_handler, g_source_remove);
if (priv->action_idle_handler)
{
g_source_remove (priv->action_idle_handler);
priv->action_idle_handler = 0;
}
if (priv->action_queue)
{
@ -598,11 +604,10 @@ cally_actor_real_remove_actor (ClutterActor *container,
g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), 0);
atk_parent = ATK_OBJECT (data);
atk_child = clutter_actor_get_accessible (actor);
if (clutter_actor_has_accessible (actor))
if (atk_child)
{
atk_child = clutter_actor_get_accessible (actor);
g_value_init (&values.old_value, G_TYPE_POINTER);
g_value_set_pointer (&values.old_value, atk_parent);
@ -652,7 +657,7 @@ cally_actor_get_extents (AtkComponent *component,
ClutterActor *actor = NULL;
gint top_level_x, top_level_y;
gfloat f_width, f_height;
graphene_point3d_t verts[4];
ClutterVertex verts[4];
ClutterActor *stage = NULL;
g_return_if_fail (CALLY_IS_ACTOR (component));
@ -765,11 +770,10 @@ static gboolean
cally_actor_action_do_action (AtkAction *action,
gint index)
{
CallyActor *cally_actor = NULL;
AtkStateSet *set = NULL;
CallyActorPrivate *priv = NULL;
CallyActorActionInfo *info = NULL;
gboolean did_action = FALSE;
CallyActor *cally_actor = NULL;
AtkStateSet *set = NULL;
CallyActorPrivate *priv = NULL;
CallyActorActionInfo *info = NULL;
cally_actor = CALLY_ACTOR (action);
priv = cally_actor->priv;
@ -777,19 +781,21 @@ cally_actor_action_do_action (AtkAction *action,
set = atk_object_ref_state_set (ATK_OBJECT (cally_actor));
if (atk_state_set_contains_state (set, ATK_STATE_DEFUNCT))
goto out;
return FALSE;
if (!atk_state_set_contains_state (set, ATK_STATE_SENSITIVE) ||
!atk_state_set_contains_state (set, ATK_STATE_SHOWING))
goto out;
return FALSE;
g_object_unref (set);
info = _cally_actor_get_action_info (cally_actor, index);
if (info == NULL)
goto out;
return FALSE;
if (info->do_action_func == NULL)
goto out;
return FALSE;
if (!priv->action_queue)
priv->action_queue = g_queue_new ();
@ -799,12 +805,7 @@ cally_actor_action_do_action (AtkAction *action,
if (!priv->action_idle_handler)
priv->action_idle_handler = g_idle_add (idle_do_action, cally_actor);
did_action = TRUE;
out:
g_clear_object (&set);
return did_action;
return TRUE;
}
static gboolean
@ -970,7 +971,7 @@ cally_actor_real_notify_clutter (GObject *obj,
* paint it; we don't want this to generate an ATK
* state change
*/
if (clutter_actor_is_painting_unmapped (actor))
if (clutter_actor_is_in_clone_paint (actor))
return;
state = ATK_STATE_SHOWING;
@ -1086,7 +1087,7 @@ cally_actor_add_action_full (CallyActor *cally_actor,
priv = cally_actor->priv;
info = g_new0 (CallyActorActionInfo, 1);
info = g_slice_new (CallyActorActionInfo);
info->name = g_strdup (action_name);
info->description = g_strdup (action_description);
info->keybinding = g_strdup (action_keybinding);
@ -1106,7 +1107,7 @@ cally_actor_add_action_full (CallyActor *cally_actor,
*
* Removes a action, using the @action_id returned by cally_actor_add_action()
*
* Return value: %TRUE if the operation was successful, %FALSE otherwise
* Return value: %TRUE if the operation was succesful, %FALSE otherwise
*
* Since: 1.4
*/
@ -1140,7 +1141,7 @@ cally_actor_remove_action (CallyActor *cally_actor,
* Removes an action, using the @action_name used when the action was added
* with cally_actor_add_action()
*
* Return value: %TRUE if the operation was successful, %FALSE otherwise
* Return value: %TRUE if the operation was succesful, %FALSE otherwise
*
* Since: 1.4
*/
@ -1191,5 +1192,5 @@ _cally_actor_destroy_action_info (gpointer action_info,
if (info->notify)
info->notify (info->user_data);
g_free (info);
g_slice_free (CallyActorActionInfo, info);
}

View File

@ -0,0 +1,147 @@
/* CALLY - The Clutter Accessibility Implementation Library
*
* Copyright (C) 2008 Igalia, S.L.
*
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
*
* Based on GailContainer from GAIL
* Copyright 2001, 2002, 2003 Sun Microsystems Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:cally-group
* @Title: CallyGroup
* @short_description: Implementation of the ATK interfaces for a #ClutterGroup
* @see_also: #ClutterGroup
*
* #CallyGroup implements the required ATK interfaces of #ClutterGroup
* In particular it exposes each of the Clutter actors contained in the
* group.
*/
#include "clutter-build-config.h"
#include "cally-group.h"
#include "cally-actor-private.h"
static gint cally_group_get_n_children (AtkObject *obj);
static AtkObject* cally_group_ref_child (AtkObject *obj,
gint i);
static void cally_group_real_initialize (AtkObject *obj,
gpointer data);
G_DEFINE_TYPE (CallyGroup, cally_group, CALLY_TYPE_ACTOR)
static void
cally_group_class_init (CallyGroupClass *klass)
{
/* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
class->get_n_children = cally_group_get_n_children;
class->ref_child = cally_group_ref_child;
class->initialize = cally_group_real_initialize;
}
static void
cally_group_init (CallyGroup *group)
{
/* nothing to do yet */
}
/**
* cally_group_new:
* @actor: a #ClutterGroup
*
* Creates a #CallyGroup for @actor
*
* Return value: the newly created #CallyGroup
*
* Since: 1.4
*/
AtkObject *
cally_group_new (ClutterActor *actor)
{
GObject *object = NULL;
AtkObject *accessible = NULL;
g_return_val_if_fail (CLUTTER_IS_GROUP (actor), NULL);
object = g_object_new (CALLY_TYPE_GROUP, NULL);
accessible = ATK_OBJECT (object);
atk_object_initialize (accessible, actor);
return accessible;
}
static gint
cally_group_get_n_children (AtkObject *obj)
{
ClutterActor *actor = NULL;
gint count = 0;
g_return_val_if_fail (CALLY_IS_GROUP (obj), count);
actor = CALLY_GET_CLUTTER_ACTOR (obj);
if (actor == NULL) /* defunct */
return 0;
g_return_val_if_fail (CLUTTER_IS_GROUP(actor), count);
count = clutter_actor_get_n_children (actor);
return count;
}
static AtkObject*
cally_group_ref_child (AtkObject *obj,
gint i)
{
AtkObject *accessible = NULL;
ClutterActor *actor = NULL;
ClutterActor *child = NULL;
g_return_val_if_fail (CALLY_IS_GROUP (obj), NULL);
g_return_val_if_fail ((i >= 0), NULL);
actor = CALLY_GET_CLUTTER_ACTOR (obj);
g_return_val_if_fail (CLUTTER_IS_GROUP(actor), NULL);
child = clutter_actor_get_child_at_index (actor, i);
if (!child)
return NULL;
accessible = clutter_actor_get_accessible (child);
if (accessible != NULL)
g_object_ref (accessible);
return accessible;
}
static void
cally_group_real_initialize (AtkObject *obj,
gpointer data)
{
ATK_OBJECT_CLASS (cally_group_parent_class)->initialize (obj, data);
obj->role = ATK_ROLE_PANEL;
}

View File

@ -0,0 +1,87 @@
/* CALLY - The Clutter Accessibility Implementation Library
*
* Copyright (C) 2008 Igalia, S.L.
*
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
*
* Based on GailContainer from GAIL
* Copyright 2001, 2002, 2003 Sun Microsystems Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CALLY_GROUP_H__
#define __CALLY_GROUP_H__
#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <cally/cally.h> can be included directly."
#endif
#include <cally/cally-actor.h>
#include <clutter/clutter.h>
G_BEGIN_DECLS
#define CALLY_TYPE_GROUP (cally_group_get_type ())
#define CALLY_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_GROUP, CallyGroup))
#define CALLY_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_GROUP, CallyGroupClass))
#define CALLY_IS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_GROUP))
#define CALLY_IS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_GROUP))
#define CALLY_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_GROUP, CallyGroupClass))
typedef struct _CallyGroup CallyGroup;
typedef struct _CallyGroupClass CallyGroupClass;
typedef struct _CallyGroupPrivate CallyGroupPrivate;
/**
* CallyGroup:
*
* The <structname>CallyGroup</structname> structure contains only
* private data and should be accessed using the provided API
*
* Since: 1.4
*/
struct _CallyGroup
{
/*< private >*/
CallyActor parent;
CallyGroupPrivate *priv;
};
/**
* CallyGroupClass:
*
* The <structname>CallyGroupClass</structname> structure contains only
* private data
*
* Since: 1.4
*/
struct _CallyGroupClass
{
/*< private >*/
CallyActorClass parent_class;
/* padding for future expansion */
gpointer _padding_dummy[8];
};
CLUTTER_EXPORT
GType cally_group_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
AtkObject* cally_group_new (ClutterActor *actor);
G_END_DECLS
#endif /* __CALLY_GROUP_H__ */

View File

@ -0,0 +1,98 @@
/* CALLY - The Clutter Accessibility Implementation Library
*
* Copyright (C) 2009 Igalia, S.L.
*
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:cally-rectangle
* @short_description: Implementation of the ATK interfaces for a #ClutterRectangle
* @see_also: #ClutterRectangle
*
* #CallyRectangle implements the required ATK interfaces of #ClutterRectangle
*
* In particular it sets a proper role for the rectangle.
*/
#include "clutter-build-config.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "cally-rectangle.h"
#include "cally-actor-private.h"
#include "clutter-color.h"
#include "deprecated/clutter-rectangle.h"
/* AtkObject */
static void cally_rectangle_real_initialize (AtkObject *obj,
gpointer data);
G_DEFINE_TYPE (CallyRectangle, cally_rectangle, CALLY_TYPE_ACTOR)
static void
cally_rectangle_class_init (CallyRectangleClass *klass)
{
/* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
class->initialize = cally_rectangle_real_initialize;
}
static void
cally_rectangle_init (CallyRectangle *rectangle)
{
/* nothing to do yet */
}
/**
* cally_rectangle_new:
* @actor: a #ClutterActor
*
* Creates a new #CallyRectangle for the given @actor. @actor must be
* a #ClutterRectangle.
*
* Return value: the newly created #AtkObject
*
* Since: 1.4
*/
AtkObject*
cally_rectangle_new (ClutterActor *actor)
{
GObject *object = NULL;
AtkObject *accessible = NULL;
g_return_val_if_fail (CLUTTER_IS_RECTANGLE (actor), NULL);
object = g_object_new (CALLY_TYPE_RECTANGLE, NULL);
accessible = ATK_OBJECT (object);
atk_object_initialize (accessible, actor);
return accessible;
}
static void
cally_rectangle_real_initialize (AtkObject *obj,
gpointer data)
{
ATK_OBJECT_CLASS (cally_rectangle_parent_class)->initialize (obj, data);
obj->role = ATK_ROLE_IMAGE;
}

View File

@ -0,0 +1,84 @@
/* CALLY - The Clutter Accessibility Implementation Library
*
* Copyright (C) 2009 Igalia, S.L.
*
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CALLY_RECTANGLE_H__
#define __CALLY_RECTANGLE_H__
#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <cally/cally.h> can be included directly."
#endif
#include <cally/cally-actor.h>
#include <clutter/clutter.h>
G_BEGIN_DECLS
#define CALLY_TYPE_RECTANGLE (cally_rectangle_get_type ())
#define CALLY_RECTANGLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_RECTANGLE, CallyRectangle))
#define CALLY_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_RECTANGLE, CallyRectangleClass))
#define CALLY_IS_RECTANGLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_RECTANGLE))
#define CALLY_IS_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_RECTANGLE))
#define CALLY_RECTANGLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_RECTANGLE, CallyRectangleClass))
typedef struct _CallyRectangle CallyRectangle;
typedef struct _CallyRectangleClass CallyRectangleClass;
typedef struct _CallyRectanglePrivate CallyRectanglePrivate;
/**
* CallyRectangle:
*
* The <structname>CallyRectangle</structname> structure contains only private
* data and should be accessed using the provided API
*
* Since: 1.4
*/
struct _CallyRectangle
{
/*< private >*/
CallyActor parent;
CallyRectanglePrivate *priv;
};
/**
* CallyRectangleClass:
*
* The <structname>CallyRectangleClass</structname> structure contains
* only private data
*
* Since: 1.4
*/
struct _CallyRectangleClass
{
/*< private >*/
CallyActorClass parent_class;
/* padding for future expansion */
gpointer _padding_dummy[8];
};
CLUTTER_EXPORT
GType cally_rectangle_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
AtkObject* cally_rectangle_new (ClutterActor *actor);
G_END_DECLS
#endif /* __CALLY_RECTANGLE_H__ */

View File

@ -47,7 +47,7 @@ static AtkStateSet* cally_stage_ref_state_set (AtkObject *obj);
/* AtkWindow */
static void cally_stage_window_interface_init (AtkWindowIface *iface);
/* Auxiliary */
/* Auxiliar */
static void cally_stage_activate_cb (ClutterStage *stage,
gpointer data);
static void cally_stage_deactivate_cb (ClutterStage *stage,
@ -63,7 +63,7 @@ struct _CallyStagePrivate
G_DEFINE_TYPE_WITH_CODE (CallyStage,
cally_stage,
CALLY_TYPE_ACTOR,
CALLY_TYPE_GROUP,
G_ADD_PRIVATE (CallyStage)
G_IMPLEMENT_INTERFACE (ATK_TYPE_WINDOW,
cally_stage_window_interface_init));
@ -134,11 +134,8 @@ cally_stage_notify_key_focus_cb (ClutterStage *stage,
if (self->priv->key_focus != NULL)
{
if (self->priv->key_focus != CLUTTER_ACTOR (stage))
{
g_object_remove_weak_pointer (G_OBJECT (self->priv->key_focus),
(gpointer *) &self->priv->key_focus);
}
g_object_remove_weak_pointer (G_OBJECT (self->priv->key_focus),
(gpointer *) &self->priv->key_focus);
old = clutter_actor_get_accessible (self->priv->key_focus);
}
else
@ -163,11 +160,8 @@ cally_stage_notify_key_focus_cb (ClutterStage *stage,
*
* we remove the weak pointer above.
*/
if (key_focus != CLUTTER_ACTOR (stage))
{
g_object_add_weak_pointer (G_OBJECT (self->priv->key_focus),
(gpointer *) &self->priv->key_focus);
}
g_object_add_weak_pointer (G_OBJECT (self->priv->key_focus),
(gpointer *) &self->priv->key_focus);
new = clutter_actor_get_accessible (key_focus);
}
@ -228,7 +222,7 @@ cally_stage_window_interface_init (AtkWindowIface *iface)
/* At this moment AtkWindow is just about signals */
}
/* Auxiliary */
/* Auxiliar */
static void
cally_stage_activate_cb (ClutterStage *stage,
gpointer data)

View File

@ -25,7 +25,7 @@
#error "Only <cally/cally.h> can be included directly."
#endif
#include <cally/cally-actor.h>
#include <cally/cally-group.h>
#include <clutter/clutter.h>
G_BEGIN_DECLS
@ -52,7 +52,7 @@ typedef struct _CallyStagePrivate CallyStagePrivate;
struct _CallyStage
{
/*< private >*/
CallyActor parent;
CallyGroup parent;
CallyStagePrivate *priv;
};
@ -68,7 +68,7 @@ struct _CallyStage
struct _CallyStageClass
{
/*< private >*/
CallyActorClass parent_class;
CallyGroupClass parent_class;
/* padding for future expansion */
gpointer _padding_dummy[16];

View File

@ -247,7 +247,11 @@ cally_text_finalize (GObject *obj)
/* g_object_unref (cally_text->priv->textutil); */
/* cally_text->priv->textutil = NULL; */
g_clear_handle_id (&cally_text->priv->insert_idle_handler, g_source_remove);
if (cally_text->priv->insert_idle_handler)
{
g_source_remove (cally_text->priv->insert_idle_handler);
cally_text->priv->insert_idle_handler = 0;
}
G_OBJECT_CLASS (cally_text_parent_class)->finalize (obj);
}
@ -1434,7 +1438,7 @@ static void cally_text_get_character_extents (AtkText *text,
PangoLayout *layout;
PangoRectangle extents;
const gchar *text_value;
graphene_point3d_t verts[4];
ClutterVertex verts[4];
actor = CALLY_GET_CLUTTER_ACTOR (text);
if (actor == NULL) /* State is defunct */
@ -1513,7 +1517,7 @@ cally_text_get_offset_at_point (AtkText *text,
}
/******** Auxiliary private methods ******/
/******** Auxiliar private methods ******/
/* ClutterText only maintains the current cursor position and a extra selection
bound, but this could be before or after the cursor. This method returns
@ -1552,7 +1556,7 @@ _cally_text_delete_text_cb (ClutterText *clutter_text,
g_return_if_fail (CALLY_IS_TEXT (data));
/* Ignore zero length deletions */
/* Ignore zero lengh deletions */
if (end_pos - start_pos == 0)
return;
@ -1653,7 +1657,7 @@ cally_text_insert_text (AtkEditableText *text,
clutter_text_insert_text (CLUTTER_TEXT (actor),
string, *position);
/* we suppose that the text insertion will be successful,
/* we suppose that the text insertion will be succesful,
clutter-text doesn't warn about it. A option would be search for
the text, but it seems not really required */
*position += length;
@ -1866,7 +1870,7 @@ static gint
_cally_atk_attribute_lookup_func (gconstpointer data,
gconstpointer user_data)
{
AtkTextAttribute attr = (AtkTextAttribute) GPOINTER_TO_INT (user_data);
AtkTextAttribute attr = (AtkTextAttribute) user_data;
AtkAttribute *at = (AtkAttribute *) data;
if (!g_strcmp0 (at->name, atk_text_attribute_get_name (attr)))
return 0;
@ -2290,7 +2294,7 @@ _cally_misc_get_index_at_point (ClutterText *clutter_text,
gint index, x_window, y_window, x_toplevel, y_toplevel;
gint x_temp, y_temp;
gboolean ret;
graphene_point3d_t verts[4];
ClutterVertex verts[4];
PangoLayout *layout;
gint x_layout, y_layout;

View File

@ -0,0 +1,98 @@
/* CALLY - The Clutter Accessibility Implementation Library
*
* Copyright (C) 2009 Igalia, S.L.
*
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:cally-texture
* @Title: CallyTexture
* @short_description: Implementation of the ATK interfaces for a #ClutterTexture
* @see_also: #ClutterTexture
*
* #CallyTexture implements the required ATK interfaces of #ClutterTexture
*
* In particular it sets a proper role for the texture.
*/
#include "clutter-build-config.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "cally-texture.h"
#include "cally-actor-private.h"
#include "deprecated/clutter-texture.h"
/* AtkObject */
static void cally_texture_real_initialize (AtkObject *obj,
gpointer data);
G_DEFINE_TYPE (CallyTexture, cally_texture, CALLY_TYPE_ACTOR)
static void
cally_texture_class_init (CallyTextureClass *klass)
{
/* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
class->initialize = cally_texture_real_initialize;
}
static void
cally_texture_init (CallyTexture *texture)
{
/* nothing to do yet */
}
/**
* cally_texture_new:
* @actor: a #ClutterActor
*
* Creates a new #CallyTexture for the given @actor. @actor must be
* a #ClutterTexture.
*
* Return value: the newly created #AtkObject
*
* Since: 1.4
*/
AtkObject*
cally_texture_new (ClutterActor *actor)
{
GObject *object = NULL;
AtkObject *accessible = NULL;
g_return_val_if_fail (CLUTTER_IS_TEXTURE (actor), NULL);
object = g_object_new (CALLY_TYPE_TEXTURE, NULL);
accessible = ATK_OBJECT (object);
atk_object_initialize (accessible, actor);
return accessible;
}
static void
cally_texture_real_initialize (AtkObject *obj,
gpointer data)
{
ATK_OBJECT_CLASS (cally_texture_parent_class)->initialize (obj, data);
/* default role */
obj->role = ATK_ROLE_IMAGE;
}

View File

@ -0,0 +1,84 @@
/* CALLY - The Clutter Accessibility Implementation Library
*
* Copyright (C) 2009 Igalia, S.L.
*
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CALLY_TEXTURE_H__
#define __CALLY_TEXTURE_H__
#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <cally/cally.h> can be included directly."
#endif
#include <clutter/clutter.h>
#include <cally/cally-actor.h>
G_BEGIN_DECLS
#define CALLY_TYPE_TEXTURE (cally_texture_get_type ())
#define CALLY_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_TEXTURE, CallyTexture))
#define CALLY_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_TEXTURE, CallyTextureClass))
#define CALLY_IS_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_TEXTURE))
#define CALLY_IS_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_TEXTURE))
#define CALLY_TEXTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_TEXTURE, CallyTextureClass))
typedef struct _CallyTexture CallyTexture;
typedef struct _CallyTextureClass CallyTextureClass;
typedef struct _CallyTexturePrivate CallyTexturePrivate;
/**
* CallyTexture:
*
* The <structname>CallyTexture</structname> structure contains only
* private data and should be accessed using the provided API
*
* Since: 1.4
*/
struct _CallyTexture
{
/*< private >*/
CallyActor parent;
CallyTexturePrivate *priv;
};
/**
* CallyTextureClass:
*
* The <structname>CallyTextureClass</structname> structure contains
* only private data
*
* Since: 1.4
*/
struct _CallyTextureClass
{
/*< private >*/
CallyActorClass parent_class;
/* padding for future expansion */
gpointer _padding_dummy[8];
};
CLUTTER_EXPORT
GType cally_texture_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
AtkObject *cally_texture_new (ClutterActor *actor);
G_END_DECLS
#endif /* __CALLY_TEXTURE_H__ */

View File

@ -36,8 +36,11 @@
#include "cally.h"
#include "cally-actor.h"
#include "cally-group.h"
#include "cally-stage.h"
#include "cally-text.h"
#include "cally-texture.h"
#include "cally-rectangle.h"
#include "cally-clone.h"
#include "cally-factory.h"
@ -50,8 +53,11 @@
/* factories initialization*/
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_ACTOR, cally_actor, cally_actor_new)
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_GROUP, cally_group, cally_group_new)
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_STAGE, cally_stage, cally_stage_new)
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_TEXT, cally_text, cally_text_new)
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_TEXTURE, cally_texture, cally_texture_new)
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_RECTANGLE, cally_rectangle, cally_rectangle_new)
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_CLONE, cally_clone, cally_clone_new)
/**
@ -69,8 +75,11 @@ cally_accessibility_init (void)
{
/* setting the factories */
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_ACTOR, cally_actor);
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_GROUP, cally_group);
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_STAGE, cally_stage);
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_TEXT, cally_text);
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_TEXTURE, cally_texture);
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_RECTANGLE, cally_rectangle);
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_CLONE, cally_clone);
/* Initialize the CallyUtility class */

View File

@ -26,10 +26,13 @@
#include "cally-actor.h"
#include "cally-clone.h"
#include "cally-factory.h"
#include "cally-group.h"
#include "cally-main.h"
#include "cally-rectangle.h"
#include "cally-root.h"
#include "cally-stage.h"
#include "cally-text.h"
#include "cally-texture.h"
#include "cally-util.h"
#undef __CALLY_H_INSIDE__

View File

@ -33,11 +33,28 @@
G_BEGIN_DECLS
#define CLUTTER_TYPE_ACTION (clutter_action_get_type ())
#define CLUTTER_TYPE_ACTION (clutter_action_get_type ())
#define CLUTTER_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ACTION, ClutterAction))
#define CLUTTER_IS_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ACTION))
#define CLUTTER_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ACTION, ClutterActionClass))
#define CLUTTER_IS_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ACTION))
#define CLUTTER_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ACTION, ClutterActionClass))
CLUTTER_EXPORT
G_DECLARE_DERIVABLE_TYPE (ClutterAction, clutter_action,
CLUTTER, ACTION, ClutterActorMeta);
typedef struct _ClutterActionClass ClutterActionClass;
/**
* ClutterAction:
*
* The #ClutterAction structure contains only private data and
* should be accessed using the provided API.
*
* Since: 1.4
*/
struct _ClutterAction
{
/*< private >*/
ClutterActorMeta parent_instance;
};
/**
* ClutterActionClass:
@ -61,6 +78,9 @@ struct _ClutterActionClass
void (* _clutter_action8) (void);
};
CLUTTER_EXPORT
GType clutter_action_get_type (void) G_GNUC_CONST;
/* ClutterActor API */
CLUTTER_EXPORT
void clutter_actor_add_action (ClutterActor *self,

View File

@ -54,7 +54,7 @@ clutter_actor_box_new (gfloat x_1,
ClutterActorBox *
clutter_actor_box_alloc (void)
{
return g_new0 (ClutterActorBox, 1);
return g_slice_new0 (ClutterActorBox);
}
/**
@ -130,7 +130,7 @@ ClutterActorBox *
clutter_actor_box_copy (const ClutterActorBox *box)
{
if (G_LIKELY (box != NULL))
return g_memdup2 (box, sizeof (ClutterActorBox));
return g_slice_dup (ClutterActorBox, box);
return NULL;
}
@ -148,7 +148,7 @@ void
clutter_actor_box_free (ClutterActorBox *box)
{
if (G_LIKELY (box != NULL))
g_free (box);
g_slice_free (ClutterActorBox, box);
}
/**
@ -320,7 +320,7 @@ clutter_actor_box_get_area (const ClutterActorBox *box)
* @y: Y coordinate of the point
*
* Checks whether a point with @x, @y coordinates is contained
* within @box
* withing @box
*
* Return value: %TRUE if the point is contained by the #ClutterActorBox
*
@ -340,7 +340,7 @@ clutter_actor_box_contains (const ClutterActorBox *box,
/**
* clutter_actor_box_from_vertices:
* @box: a #ClutterActorBox
* @verts: (array fixed-size=4): array of four #graphene_point3d_t
* @verts: (array fixed-size=4): array of four #ClutterVertex
*
* Calculates the bounding box represented by the four vertices; for details
* of the vertex array see clutter_actor_get_abs_allocation_vertices().
@ -348,8 +348,8 @@ clutter_actor_box_contains (const ClutterActorBox *box,
* Since: 1.0
*/
void
clutter_actor_box_from_vertices (ClutterActorBox *box,
const graphene_point3d_t verts[])
clutter_actor_box_from_vertices (ClutterActorBox *box,
const ClutterVertex verts[])
{
gfloat x_1, x_2, y_1, y_2;
@ -554,7 +554,7 @@ _clutter_actor_box_enlarge_for_effects (ClutterActorBox *box)
*
* The reason this is important is because effects will use this
* API to determine the size of offscreen framebuffers and so for
* a fixed-size object that may be animated across the screen we
* a fixed-size object that may be animated accross the screen we
* want to make sure that the stage paint-box has an equally stable
* size so that effects aren't made to continuously re-allocate
* a corresponding fbo.
@ -583,7 +583,7 @@ _clutter_actor_box_enlarge_for_effects (ClutterActorBox *box)
/* Now we redefine the top-left relative to the bottom right based on the
* rounded width/height determined above + a constant so that the overall
* size of the box will be stable and not dependent on the box's
* size of the box will be stable and not dependant on the box's
* position.
*
* Adding 3px to the width/height will ensure we cover the maximum of
@ -615,32 +615,6 @@ clutter_actor_box_scale (ClutterActorBox *box,
box->y2 *= scale;
}
/**
* clutter_actor_box_is_initialized:
* @box: a #ClutterActorBox
*
* Checks if @box has been initialized, a #ClutterActorBox is uninitialized
* if it has a size of -1 at an origin of 0, 0.
*
* Returns: %TRUE if the box is uninitialized, %FALSE if it isn't
*/
gboolean
clutter_actor_box_is_initialized (ClutterActorBox *box)
{
gboolean x1_uninitialized, x2_uninitialized;
gboolean y1_uninitialized, y2_uninitialized;
g_return_val_if_fail (box != NULL, TRUE);
x1_uninitialized = isinf (box->x1);
x2_uninitialized = isinf (box->x2) && signbit (box->x2);
y1_uninitialized = isinf (box->y1);
y2_uninitialized = isinf (box->y2) && signbit (box->y2);
return !x1_uninitialized || !x2_uninitialized ||
!y1_uninitialized || !y2_uninitialized;
}
G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterActorBox, clutter_actor_box,
clutter_actor_box_copy,
clutter_actor_box_free,

View File

@ -51,7 +51,7 @@
struct _ClutterActorMetaPrivate
{
ClutterActor *actor;
gulong destroy_id;
guint destroy_id;
gchar *name;
@ -81,49 +81,28 @@ static void
on_actor_destroy (ClutterActor *actor,
ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (meta);
priv->actor = NULL;
meta->priv->actor = NULL;
}
static void
clutter_actor_meta_real_set_actor (ClutterActorMeta *meta,
ClutterActor *actor)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (meta);
g_warn_if_fail (!priv->actor ||
!CLUTTER_ACTOR_IN_PAINT (priv->actor));
g_warn_if_fail (!actor || !CLUTTER_ACTOR_IN_PAINT (actor));
if (priv->actor == actor)
if (meta->priv->actor == actor)
return;
g_clear_signal_handler (&priv->destroy_id, priv->actor);
if (meta->priv->destroy_id != 0)
{
g_signal_handler_disconnect (meta->priv->actor, meta->priv->destroy_id);
meta->priv->destroy_id = 0;
}
priv->actor = actor;
meta->priv->actor = actor;
if (priv->actor != NULL)
priv->destroy_id = g_signal_connect (priv->actor, "destroy",
G_CALLBACK (on_actor_destroy),
meta);
}
static void
clutter_actor_meta_real_set_enabled (ClutterActorMeta *meta,
gboolean is_enabled)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (meta);
g_warn_if_fail (!priv->actor ||
!CLUTTER_ACTOR_IN_PAINT (priv->actor));
priv->is_enabled = is_enabled;
g_object_notify_by_pspec (G_OBJECT (meta), obj_props[PROP_ENABLED]);
if (meta->priv->actor != NULL)
meta->priv->destroy_id = g_signal_connect (meta->priv->actor, "destroy",
G_CALLBACK (on_actor_destroy),
meta);
}
static void
@ -156,21 +135,20 @@ clutter_actor_meta_get_property (GObject *gobject,
GValue *value,
GParamSpec *pspec)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (CLUTTER_ACTOR_META (gobject));
ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject);
switch (prop_id)
{
case PROP_ACTOR:
g_value_set_object (value, priv->actor);
g_value_set_object (value, meta->priv->actor);
break;
case PROP_NAME:
g_value_set_string (value, priv->name);
g_value_set_string (value, meta->priv->name);
break;
case PROP_ENABLED:
g_value_set_boolean (value, priv->is_enabled);
g_value_set_boolean (value, meta->priv->is_enabled);
break;
default:
@ -182,11 +160,10 @@ clutter_actor_meta_get_property (GObject *gobject,
static void
clutter_actor_meta_finalize (GObject *gobject)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (CLUTTER_ACTOR_META (gobject));
ClutterActorMetaPrivate *priv = CLUTTER_ACTOR_META (gobject)->priv;
if (priv->actor != NULL)
g_clear_signal_handler (&priv->destroy_id, priv->actor);
if (priv->destroy_id != 0 && priv->actor != NULL)
g_signal_handler_disconnect (priv->actor, priv->destroy_id);
g_free (priv->name);
@ -199,7 +176,6 @@ clutter_actor_meta_class_init (ClutterActorMetaClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
klass->set_actor = clutter_actor_meta_real_set_actor;
klass->set_enabled = clutter_actor_meta_real_set_enabled;
/**
* ClutterActorMeta:actor:
@ -254,11 +230,9 @@ clutter_actor_meta_class_init (ClutterActorMetaClass *klass)
void
clutter_actor_meta_init (ClutterActorMeta *self)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (self);
priv->is_enabled = TRUE;
priv->priority = CLUTTER_ACTOR_META_PRIORITY_DEFAULT;
self->priv = clutter_actor_meta_get_instance_private (self);
self->priv->is_enabled = TRUE;
self->priv->priority = CLUTTER_ACTOR_META_PRIORITY_DEFAULT;
}
/**
@ -276,17 +250,13 @@ void
clutter_actor_meta_set_name (ClutterActorMeta *meta,
const gchar *name)
{
ClutterActorMetaPrivate *priv;
g_return_if_fail (CLUTTER_IS_ACTOR_META (meta));
priv = clutter_actor_meta_get_instance_private (meta);
if (g_strcmp0 (priv->name, name) == 0)
if (g_strcmp0 (meta->priv->name, name) == 0)
return;
g_free (priv->name);
priv->name = g_strdup (name);
g_free (meta->priv->name);
meta->priv->name = g_strdup (name);
g_object_notify_by_pspec (G_OBJECT (meta), obj_props[PROP_NAME]);
}
@ -307,13 +277,9 @@ clutter_actor_meta_set_name (ClutterActorMeta *meta,
const gchar *
clutter_actor_meta_get_name (ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), NULL);
priv = clutter_actor_meta_get_instance_private (meta);
return priv->name;
return meta->priv->name;
}
/**
@ -329,17 +295,16 @@ void
clutter_actor_meta_set_enabled (ClutterActorMeta *meta,
gboolean is_enabled)
{
ClutterActorMetaPrivate *priv;
g_return_if_fail (CLUTTER_IS_ACTOR_META (meta));
priv = clutter_actor_meta_get_instance_private (meta);
is_enabled = !!is_enabled;
if (priv->is_enabled == is_enabled)
if (meta->priv->is_enabled == is_enabled)
return;
CLUTTER_ACTOR_META_GET_CLASS (meta)->set_enabled (meta, is_enabled);
meta->priv->is_enabled = is_enabled;
g_object_notify_by_pspec (G_OBJECT (meta), obj_props[PROP_ENABLED]);
}
/**
@ -355,13 +320,9 @@ clutter_actor_meta_set_enabled (ClutterActorMeta *meta,
gboolean
clutter_actor_meta_get_enabled (ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), FALSE);
priv = clutter_actor_meta_get_instance_private (meta);
return priv->is_enabled;
return meta->priv->is_enabled;
}
/*
@ -397,54 +358,40 @@ _clutter_actor_meta_set_actor (ClutterActorMeta *meta,
ClutterActor *
clutter_actor_meta_get_actor (ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), NULL);
priv = clutter_actor_meta_get_instance_private (meta);
return priv->actor;
return meta->priv->actor;
}
void
_clutter_actor_meta_set_priority (ClutterActorMeta *meta,
gint priority)
{
ClutterActorMetaPrivate *priv;
g_return_if_fail (CLUTTER_IS_ACTOR_META (meta));
priv = clutter_actor_meta_get_instance_private (meta);
/* This property shouldn't be modified after the actor meta is in
use because ClutterMetaGroup doesn't resort the list when it
changes. If we made the priority public then we could either make
the priority a construct-only property or listen for
notifications on the property from the ClutterMetaGroup and
resort. */
g_return_if_fail (priv->actor == NULL);
g_return_if_fail (meta->priv->actor == NULL);
priv->priority = priority;
meta->priv->priority = priority;
}
gint
_clutter_actor_meta_get_priority (ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), 0);
priv = clutter_actor_meta_get_instance_private (meta);
return priv->priority;
return meta->priv->priority;
}
gboolean
_clutter_actor_meta_is_internal (ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (meta);
gint priority = priv->priority;
gint priority = meta->priv->priority;
return (priority <= CLUTTER_ACTOR_META_PRIORITY_INTERNAL_LOW ||
priority >= CLUTTER_ACTOR_META_PRIORITY_INTERNAL_HIGH);
@ -491,21 +438,19 @@ void
_clutter_meta_group_add_meta (ClutterMetaGroup *group,
ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (meta);
GList *prev = NULL, *l;
if (priv->actor != NULL)
if (meta->priv->actor != NULL)
{
g_warning ("The meta of type '%s' with name '%s' is "
"already attached to actor '%s'",
G_OBJECT_TYPE_NAME (meta),
priv->name != NULL
? priv->name
meta->priv->name != NULL
? meta->priv->name
: "<unknown>",
clutter_actor_get_name (priv->actor) != NULL
? clutter_actor_get_name (priv->actor)
: G_OBJECT_TYPE_NAME (priv->actor));
clutter_actor_get_name (meta->priv->actor) != NULL
? clutter_actor_get_name (meta->priv->actor)
: G_OBJECT_TYPE_NAME (meta->priv->actor));
return;
}
@ -541,16 +486,13 @@ void
_clutter_meta_group_remove_meta (ClutterMetaGroup *group,
ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (meta);
if (priv->actor != group->actor)
if (meta->priv->actor != group->actor)
{
g_warning ("The meta of type '%s' with name '%s' is not "
"attached to the actor '%s'",
G_OBJECT_TYPE_NAME (meta),
priv->name != NULL
? priv->name
meta->priv->name != NULL
? meta->priv->name
: "<unknown>",
clutter_actor_get_name (group->actor) != NULL
? clutter_actor_get_name (group->actor)
@ -693,10 +635,8 @@ _clutter_meta_group_get_meta (ClutterMetaGroup *group,
for (l = group->meta; l != NULL; l = l->next)
{
ClutterActorMeta *meta = l->data;
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (meta);
if (g_strcmp0 (priv->name, name) == 0)
if (g_strcmp0 (meta->priv->name, name) == 0)
return meta;
}
@ -716,8 +656,6 @@ _clutter_meta_group_get_meta (ClutterMetaGroup *group,
const gchar *
_clutter_actor_meta_get_debug_name (ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (meta);
return priv->name != NULL ? priv->name : G_OBJECT_TYPE_NAME (meta);
return meta->priv->name != NULL ? meta->priv->name
: G_OBJECT_TYPE_NAME (meta);
}

View File

@ -33,13 +33,31 @@
G_BEGIN_DECLS
#define CLUTTER_TYPE_ACTOR_META (clutter_actor_meta_get_type ())
#define CLUTTER_TYPE_ACTOR_META (clutter_actor_meta_get_type ())
#define CLUTTER_ACTOR_META(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ACTOR_META, ClutterActorMeta))
#define CLUTTER_IS_ACTOR_META(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ACTOR_META))
#define CLUTTER_ACTOR_META_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ACTOR_META, ClutterActorMetaClass))
#define CLUTTER_IS_ACTOR_META_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ACTOR_META))
#define CLUTTER_ACTOR_META_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ACTOR_META, ClutterActorMetaClass))
CLUTTER_EXPORT
G_DECLARE_DERIVABLE_TYPE (ClutterActorMeta, clutter_actor_meta,
CLUTTER, ACTOR_META, GInitiallyUnowned);
typedef struct _ClutterActorMetaPrivate ClutterActorMetaPrivate;
typedef struct _ClutterActorMetaClass ClutterActorMetaClass;
typedef struct _ClutterActorMetaPrivate ClutterActorMetaPrivate;
/**
* ClutterActorMeta:
*
* The #ClutterActorMeta structure contains only
* private data and should be accessed using the provided API
*
* Since: 1.4
*/
struct _ClutterActorMeta
{
/*< private >*/
GInitiallyUnowned parent_instance;
ClutterActorMetaPrivate *priv;
};
/**
* ClutterActorMetaClass:
@ -69,9 +87,6 @@ struct _ClutterActorMetaClass
void (* set_actor) (ClutterActorMeta *meta,
ClutterActor *actor);
void (* set_enabled) (ClutterActorMeta *meta,
gboolean is_enabled);
/*< private >*/
void (* _clutter_meta1) (void);
void (* _clutter_meta2) (void);
@ -79,8 +94,12 @@ struct _ClutterActorMetaClass
void (* _clutter_meta4) (void);
void (* _clutter_meta5) (void);
void (* _clutter_meta6) (void);
void (* _clutter_meta7) (void);
};
CLUTTER_EXPORT
GType clutter_actor_meta_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
void clutter_actor_meta_set_name (ClutterActorMeta *meta,
const gchar *name);

View File

@ -26,6 +26,23 @@
G_BEGIN_DECLS
/*< private >
* ClutterRedrawFlags:
* @CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION: Tells clutter the maximum
* extents of what needs to be redrawn lies within the actors
* current allocation. (Only use this for 2D actors though because
* any actor with depth may be projected outside of its allocation)
*
* Flags passed to the clutter_actor_queue_redraw_with_clip ()
* function
*
* Since: 1.6
*/
typedef enum
{
CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION = 1 << 0
} ClutterRedrawFlags;
/*< private >
* ClutterActorTraverseFlags:
* CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST: Traverse the graph in
@ -93,12 +110,35 @@ typedef ClutterActorTraverseVisitFlags (*ClutterTraverseCallback) (ClutterActor
typedef gboolean (*ClutterForeachCallback) (ClutterActor *actor,
gpointer user_data);
typedef struct _AnchorCoord AnchorCoord;
typedef struct _SizeRequest SizeRequest;
typedef struct _ClutterLayoutInfo ClutterLayoutInfo;
typedef struct _ClutterTransformInfo ClutterTransformInfo;
typedef struct _ClutterAnimationInfo ClutterAnimationInfo;
/* Internal helper struct to represent a point that can be stored in
either direct pixel coordinates or as a fraction of the actor's
size. It is used for the anchor point, scale center and rotation
centers. */
struct _AnchorCoord
{
gboolean is_fractional;
union
{
/* Used when is_fractional == TRUE */
struct
{
gdouble x;
gdouble y;
} fraction;
/* Use when is_fractional == FALSE */
ClutterVertex units;
} v;
};
struct _SizeRequest
{
guint age;
@ -123,7 +163,7 @@ struct _SizeRequest
struct _ClutterLayoutInfo
{
/* fixed position coordinates */
graphene_point_t fixed_pos;
ClutterPoint fixed_pos;
ClutterMargin margin;
@ -133,8 +173,8 @@ struct _ClutterLayoutInfo
guint x_expand : 1;
guint y_expand : 1;
graphene_size_t minimum;
graphene_size_t natural;
ClutterSize minimum;
ClutterSize natural;
};
const ClutterLayoutInfo * _clutter_actor_get_layout_info_or_defaults (ClutterActor *self);
@ -143,30 +183,39 @@ ClutterLayoutInfo * _clutter_actor_peek_layout_info
struct _ClutterTransformInfo
{
/* rotation */
/* rotation (angle and center) */
gdouble rx_angle;
AnchorCoord rx_center;
gdouble ry_angle;
AnchorCoord ry_center;
gdouble rz_angle;
AnchorCoord rz_center;
/* scaling */
gdouble scale_x;
gdouble scale_y;
gdouble scale_z;
AnchorCoord scale_center;
/* anchor point */
AnchorCoord anchor;
/* translation */
graphene_point3d_t translation;
ClutterVertex translation;
/* z_position */
gfloat z_position;
/* transformation center */
graphene_point_t pivot;
ClutterPoint pivot;
gfloat pivot_z;
graphene_matrix_t transform;
CoglMatrix transform;
guint transform_set : 1;
graphene_matrix_t child_transform;
CoglMatrix child_transform;
guint child_transform_set : 1;
};
@ -203,11 +252,11 @@ void _clutter_actor_traverse
gpointer user_data);
ClutterActor * _clutter_actor_get_stage_internal (ClutterActor *actor);
void _clutter_actor_apply_modelview_transform (ClutterActor *self,
graphene_matrix_t *matrix);
void _clutter_actor_apply_relative_transformation_matrix (ClutterActor *self,
ClutterActor *ancestor,
graphene_matrix_t *matrix);
void _clutter_actor_apply_modelview_transform (ClutterActor *self,
CoglMatrix *matrix);
void _clutter_actor_apply_relative_transformation_matrix (ClutterActor *self,
ClutterActor *ancestor,
CoglMatrix *matrix);
void _clutter_actor_rerealize (ClutterActor *self,
ClutterCallback callback,
@ -228,21 +277,30 @@ void _clutter_actor_set_has_pointer
void _clutter_actor_set_has_key_focus (ClutterActor *self,
gboolean has_key_focus);
void _clutter_actor_queue_redraw_with_clip (ClutterActor *self,
ClutterRedrawFlags flags,
const ClutterPaintVolume *clip_volume);
void _clutter_actor_queue_redraw_full (ClutterActor *self,
ClutterRedrawFlags flags,
const ClutterPaintVolume *volume,
ClutterEffect *effect);
void _clutter_actor_finish_queue_redraw (ClutterActor *self);
void _clutter_actor_finish_queue_redraw (ClutterActor *self,
ClutterPaintVolume *clip);
gboolean _clutter_actor_set_default_paint_volume (ClutterActor *self,
GType check_gtype,
ClutterPaintVolume *volume);
const char * _clutter_actor_get_debug_name (ClutterActor *self);
const gchar * _clutter_actor_get_debug_name (ClutterActor *self);
void _clutter_actor_push_clone_paint (void);
void _clutter_actor_pop_clone_paint (void);
void _clutter_actor_shader_pre_paint (ClutterActor *actor,
gboolean repeat);
void _clutter_actor_shader_post_paint (ClutterActor *actor);
ClutterActorAlign _clutter_actor_get_effective_x_align (ClutterActor *self);
void _clutter_actor_handle_event (ClutterActor *actor,
@ -252,25 +310,18 @@ void _clutter_actor_attach_clone
ClutterActor *clone);
void _clutter_actor_detach_clone (ClutterActor *actor,
ClutterActor *clone);
void _clutter_actor_queue_redraw_on_clones (ClutterActor *actor);
void _clutter_actor_queue_relayout_on_clones (ClutterActor *actor);
void _clutter_actor_queue_only_relayout (ClutterActor *actor);
void clutter_actor_clear_stage_views_recursive (ClutterActor *actor);
void _clutter_actor_queue_update_resource_scale_recursive (ClutterActor *actor);
float clutter_actor_get_real_resource_scale (ClutterActor *actor);
CoglFramebuffer * _clutter_actor_get_active_framebuffer (ClutterActor *actor);
gboolean _clutter_actor_get_real_resource_scale (ClutterActor *actor,
float *resource_scale);
ClutterPaintNode * clutter_actor_create_texture_paint_node (ClutterActor *self,
CoglTexture *texture);
void clutter_actor_finish_layout (ClutterActor *self,
int phase);
void clutter_actor_queue_immediate_relayout (ClutterActor *self);
gboolean clutter_actor_is_painting_unmapped (ClutterActor *self);
gboolean clutter_actor_get_redraw_clip (ClutterActor *self,
ClutterPaintVolume *dst_old_pv,
ClutterPaintVolume *dst_new_pv);
G_END_DECLS
#endif /* __CLUTTER_ACTOR_PRIVATE_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -39,8 +39,6 @@
#include <clutter/clutter-types.h>
#include <clutter/clutter-event.h>
#include <clutter/clutter-paint-context.h>
#include <clutter/clutter-pick-context.h>
G_BEGIN_DECLS
@ -142,6 +140,11 @@ struct _ClutterActor
* ClutterActorClass:
* @show: signal class handler for #ClutterActor::show; it must chain
* up to the parent's implementation
* @show_all: virtual function for containers and composite actors, to
* determine which children should be shown when calling
* clutter_actor_show_all() on the actor. Defaults to calling
* clutter_actor_show(). This virtual function is deprecated and it
* should not be overridden.
* @hide: signal class handler for #ClutterActor::hide; it must chain
* up to the parent's implementation
* @hide_all: virtual function for containers and composite actors, to
@ -170,23 +173,18 @@ struct _ClutterActor
* @get_preferred_height: virtual function, used when querying the minimum
* and natural heights of an actor for a given width; it is used by
* clutter_actor_get_preferred_height()
* @allocate: virtual function, used when setting the coordinates of an
* actor; it is used by clutter_actor_allocate(); when overriding this
* function without chaining up, clutter_actor_set_allocation() must be
* called and children must be allocated by the implementation, when
* chaining up though, those things will be done by the parent's
* implementation.
* @allocate: virtual function, used when settings the coordinates of an
* actor; it is used by clutter_actor_allocate(); it must chain up to
* the parent's implementation, or call clutter_actor_set_allocation()
* @apply_transform: virtual function, used when applying the transformations
* to an actor before painting it or when transforming coordinates or
* the allocation; if the transformation calculated by this function may
* have changed, the cached transformation must be invalidated by calling
* clutter_actor_invalidate_transform(); it must chain up to the parent's
* implementation
* the allocation; it must chain up to the parent's implementation
* @parent_set: signal class handler for the #ClutterActor::parent-set
* @destroy: signal class handler for #ClutterActor::destroy. It must
* chain up to the parent's implementation
* @pick: virtual function, used to draw an outline of the actor with
* the given color
* @queue_redraw: class handler for #ClutterActor::queue-redraw
* @event: class handler for #ClutterActor::event
* @button_press_event: class handler for #ClutterActor::button-press-event
* @button_release_event: class handler for
@ -223,20 +221,24 @@ struct _ClutterActorClass
/*< public >*/
void (* show) (ClutterActor *self);
void (* show_all) (ClutterActor *self);
void (* hide) (ClutterActor *self);
void (* hide_all) (ClutterActor *self);
void (* realize) (ClutterActor *self);
void (* unrealize) (ClutterActor *self);
void (* map) (ClutterActor *self);
void (* unmap) (ClutterActor *self);
void (* paint) (ClutterActor *self,
ClutterPaintContext *paint_context);
void (* paint) (ClutterActor *self);
void (* parent_set) (ClutterActor *actor,
ClutterActor *old_parent);
void (* destroy) (ClutterActor *self);
void (* pick) (ClutterActor *actor,
ClutterPickContext *pick_context);
const ClutterColor *color);
gboolean (* queue_redraw) (ClutterActor *actor,
ClutterActor *leaf_that_queued,
ClutterPaintVolume *paint_volume);
/* size negotiation */
void (* get_preferred_width) (ClutterActor *self,
@ -248,11 +250,12 @@ struct _ClutterActorClass
gfloat *min_height_p,
gfloat *natural_height_p);
void (* allocate) (ClutterActor *self,
const ClutterActorBox *box);
const ClutterActorBox *box,
ClutterAllocationFlags flags);
/* transformations */
void (* apply_transform) (ClutterActor *actor,
graphene_matrix_t *matrix);
ClutterMatrix *matrix);
/* event signals */
gboolean (* event) (ClutterActor *actor,
@ -293,14 +296,10 @@ struct _ClutterActorClass
gboolean (* touch_event) (ClutterActor *self,
ClutterTouchEvent *event);
gboolean (* has_accessible) (ClutterActor *self);
void (* resource_scale_changed) (ClutterActor *self);
float (* calculate_resource_scale) (ClutterActor *self,
int phase);
/*< private >*/
/* padding for future expansion */
gpointer _padding_dummy[25];
gpointer _padding_dummy[26];
};
/**
@ -351,17 +350,9 @@ void clutter_actor_map
CLUTTER_EXPORT
void clutter_actor_unmap (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_paint (ClutterActor *self,
ClutterPaintContext *paint_context);
void clutter_actor_paint (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_continue_paint (ClutterActor *self,
ClutterPaintContext *paint_context);
CLUTTER_EXPORT
void clutter_actor_pick (ClutterActor *actor,
ClutterPickContext *pick_context);
CLUTTER_EXPORT
void clutter_actor_continue_pick (ClutterActor *actor,
ClutterPickContext *pick_context);
void clutter_actor_continue_paint (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_queue_redraw (ClutterActor *self);
CLUTTER_EXPORT
@ -378,8 +369,6 @@ CLUTTER_EXPORT
const gchar * clutter_actor_get_name (ClutterActor *self);
CLUTTER_EXPORT
AtkObject * clutter_actor_get_accessible (ClutterActor *self);
CLUTTER_EXPORT
gboolean clutter_actor_has_accessible (ClutterActor *self);
CLUTTER_EXPORT
gboolean clutter_actor_is_visible (ClutterActor *self);
@ -412,31 +401,38 @@ void clutter_actor_get_preferred_size
gfloat *natural_height_p);
CLUTTER_EXPORT
void clutter_actor_allocate (ClutterActor *self,
const ClutterActorBox *box);
const ClutterActorBox *box,
ClutterAllocationFlags flags);
CLUTTER_EXPORT
void clutter_actor_allocate_preferred_size (ClutterActor *self,
float x,
float y);
ClutterAllocationFlags flags);
CLUTTER_EXPORT
void clutter_actor_allocate_available_size (ClutterActor *self,
gfloat x,
gfloat y,
gfloat available_width,
gfloat available_height);
gfloat available_height,
ClutterAllocationFlags flags);
CLUTTER_EXPORT
void clutter_actor_allocate_align_fill (ClutterActor *self,
const ClutterActorBox *box,
gdouble x_align,
gdouble y_align,
gboolean x_fill,
gboolean y_fill);
gboolean y_fill,
ClutterAllocationFlags flags);
CLUTTER_EXPORT
void clutter_actor_set_allocation (ClutterActor *self,
const ClutterActorBox *box);
const ClutterActorBox *box,
ClutterAllocationFlags flags);
CLUTTER_EXPORT
void clutter_actor_get_allocation_box (ClutterActor *self,
ClutterActorBox *box);
CLUTTER_EXPORT
void clutter_actor_get_allocation_vertices (ClutterActor *self,
ClutterActor *ancestor,
ClutterVertex verts[]);
CLUTTER_EXPORT
gboolean clutter_actor_has_allocation (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_set_size (ClutterActor *self,
@ -451,10 +447,6 @@ void clutter_actor_set_position
gfloat x,
gfloat y);
CLUTTER_EXPORT
gboolean clutter_actor_get_fixed_position (ClutterActor *self,
float *x,
float *y);
CLUTTER_EXPORT
void clutter_actor_get_position (ClutterActor *self,
gfloat *x,
gfloat *y);
@ -586,8 +578,7 @@ void clutter_actor_set_offscreen_redirect
CLUTTER_EXPORT
ClutterOffscreenRedirect clutter_actor_get_offscreen_redirect (ClutterActor *self);
CLUTTER_EXPORT
gboolean clutter_actor_should_pick (ClutterActor *self,
ClutterPickContext *pick_context);
gboolean clutter_actor_should_pick_paint (ClutterActor *self);
CLUTTER_EXPORT
gboolean clutter_actor_is_in_clone_paint (ClutterActor *self);
CLUTTER_EXPORT
@ -595,7 +586,8 @@ gboolean clutter_actor_get_paint_box
ClutterActorBox *box);
CLUTTER_EXPORT
float clutter_actor_get_resource_scale (ClutterActor *self);
gboolean clutter_actor_get_resource_scale (ClutterActor *self,
gfloat *resource_scale);
CLUTTER_EXPORT
gboolean clutter_actor_has_overlaps (ClutterActor *self);
@ -799,21 +791,16 @@ void clutter_actor_get_translation
gfloat *translate_z);
CLUTTER_EXPORT
void clutter_actor_set_transform (ClutterActor *self,
const graphene_matrix_t *transform);
const ClutterMatrix *transform);
CLUTTER_EXPORT
void clutter_actor_get_transform (ClutterActor *self,
graphene_matrix_t *transform);
ClutterMatrix *transform);
CLUTTER_EXPORT
void clutter_actor_set_child_transform (ClutterActor *self,
const graphene_matrix_t *transform);
const ClutterMatrix *transform);
CLUTTER_EXPORT
void clutter_actor_get_child_transform (ClutterActor *self,
graphene_matrix_t *transform);
CLUTTER_EXPORT
void clutter_actor_get_transformed_extents (ClutterActor *self,
graphene_rect_t *rect);
ClutterMatrix *transform);
CLUTTER_EXPORT
void clutter_actor_get_transformed_position (ClutterActor *self,
gfloat *x,
@ -830,16 +817,16 @@ gboolean clutter_actor_transform_stage_point
gfloat *y_out);
CLUTTER_EXPORT
void clutter_actor_get_abs_allocation_vertices (ClutterActor *self,
graphene_point3d_t *verts);
ClutterVertex verts[]);
CLUTTER_EXPORT
void clutter_actor_apply_transform_to_point (ClutterActor *self,
const graphene_point3d_t *point,
graphene_point3d_t *vertex);
const ClutterVertex *point,
ClutterVertex *vertex);
CLUTTER_EXPORT
void clutter_actor_apply_relative_transform_to_point (ClutterActor *self,
ClutterActor *ancestor,
const graphene_point3d_t *point,
graphene_point3d_t *vertex);
const ClutterVertex *point,
ClutterVertex *vertex);
/* Implicit animations */
CLUTTER_EXPORT
@ -883,11 +870,6 @@ void clutter_actor_set_opacity_override
CLUTTER_EXPORT
gint clutter_actor_get_opacity_override (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_inhibit_culling (ClutterActor *actor);
CLUTTER_EXPORT
void clutter_actor_uninhibit_culling (ClutterActor *actor);
/**
* ClutterActorCreateChildFunc:
* @item: (type GObject): the item in the model
@ -922,18 +904,8 @@ void clutter_actor_bind_model_with_properties
CLUTTER_EXPORT
void clutter_actor_pick_box (ClutterActor *self,
ClutterPickContext *pick_context,
const ClutterActorBox *box);
CLUTTER_EXPORT
GList * clutter_actor_peek_stage_views (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_invalidate_transform (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_invalidate_paint_volume (ClutterActor *self);
G_END_DECLS
#endif /* __CLUTTER_ACTOR_H__ */

View File

@ -58,7 +58,6 @@ struct _ClutterAlignConstraint
ClutterActor *actor;
ClutterActor *source;
ClutterAlignAxis align_axis;
graphene_point_t pivot;
gfloat factor;
};
@ -73,7 +72,6 @@ enum
PROP_SOURCE,
PROP_ALIGN_AXIS,
PROP_PIVOT_POINT,
PROP_FACTOR,
PROP_LAST
@ -86,11 +84,13 @@ G_DEFINE_TYPE (ClutterAlignConstraint,
CLUTTER_TYPE_CONSTRAINT);
static void
source_queue_relayout (ClutterActor *actor,
ClutterAlignConstraint *align)
source_position_changed (ClutterActor *actor,
const ClutterActorBox *allocation,
ClutterAllocationFlags flags,
ClutterAlignConstraint *align)
{
if (align->actor != NULL)
_clutter_actor_queue_only_relayout (align->actor);
clutter_actor_queue_relayout (align->actor);
}
static void
@ -135,41 +135,35 @@ clutter_align_constraint_update_allocation (ClutterConstraint *constraint,
ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (constraint);
gfloat source_width, source_height;
gfloat actor_width, actor_height;
gfloat offset_x_start, offset_y_start;
gfloat pivot_x, pivot_y;
gfloat source_x, source_y;
if (align->source == NULL)
return;
clutter_actor_box_get_size (allocation, &actor_width, &actor_height);
clutter_actor_get_position (align->source, &source_x, &source_y);
clutter_actor_get_size (align->source, &source_width, &source_height);
pivot_x = align->pivot.x == -1.f
? align->factor
: align->pivot.x;
pivot_y = align->pivot.y == -1.f
? align->factor
: align->pivot.y;
offset_x_start = pivot_x * -actor_width;
offset_y_start = pivot_y * -actor_height;
switch (align->align_axis)
{
case CLUTTER_ALIGN_X_AXIS:
allocation->x1 += offset_x_start + (source_width * align->factor);
allocation->x1 = ((source_width - actor_width) * align->factor)
+ source_x;
allocation->x2 = allocation->x1 + actor_width;
break;
case CLUTTER_ALIGN_Y_AXIS:
allocation->y1 += offset_y_start + (source_height * align->factor);
allocation->y1 = ((source_height - actor_height) * align->factor)
+ source_y;
allocation->y2 = allocation->y1 + actor_height;
break;
case CLUTTER_ALIGN_BOTH:
allocation->x1 += offset_x_start + (source_width * align->factor);
allocation->y1 += offset_y_start + (source_height * align->factor);
allocation->x1 = ((source_width - actor_width) * align->factor)
+ source_x;
allocation->y1 = ((source_height - actor_height) * align->factor)
+ source_y;
allocation->x2 = allocation->x1 + actor_width;
allocation->y2 = allocation->y1 + actor_height;
break;
@ -193,7 +187,7 @@ clutter_align_constraint_dispose (GObject *gobject)
G_CALLBACK (source_destroyed),
align);
g_signal_handlers_disconnect_by_func (align->source,
G_CALLBACK (source_queue_relayout),
G_CALLBACK (source_position_changed),
align);
align->source = NULL;
}
@ -219,10 +213,6 @@ clutter_align_constraint_set_property (GObject *gobject,
clutter_align_constraint_set_align_axis (align, g_value_get_enum (value));
break;
case PROP_PIVOT_POINT:
clutter_align_constraint_set_pivot_point (align, g_value_get_boxed (value));
break;
case PROP_FACTOR:
clutter_align_constraint_set_factor (align, g_value_get_float (value));
break;
@ -251,16 +241,6 @@ clutter_align_constraint_get_property (GObject *gobject,
g_value_set_enum (value, align->align_axis);
break;
case PROP_PIVOT_POINT:
{
graphene_point_t point;
clutter_align_constraint_get_pivot_point (align, &point);
g_value_set_boxed (value, &point);
}
break;
case PROP_FACTOR:
g_value_set_float (value, align->factor);
break;
@ -314,30 +294,6 @@ clutter_align_constraint_class_init (ClutterAlignConstraintClass *klass)
CLUTTER_ALIGN_X_AXIS,
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT);
/**
* ClutterAlignConstraint:pivot-point:
*
* The pivot point used by the constraint. The pivot point is the
* point in the constraint actor around which the aligning is applied,
* with (0, 0) being the top left corner of the actor and (1, 1) the
* bottom right corner of the actor.
*
* For example, setting the pivot point to (0.5, 0.5) and using a factor
* of 1 for both axes will align the actors horizontal and vertical
* center point with the bottom right corner of the source actor.
*
* By default, the pivot point is set to (-1, -1), which means it's not
* used and the constrained actor will be aligned to always stay inside
* the source actor.
*/
obj_props[PROP_PIVOT_POINT] =
g_param_spec_boxed ("pivot-point",
P_("Pivot point"),
P_("The pivot point"),
GRAPHENE_TYPE_POINT,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
/**
* ClutterAlignConstraint:factor:
*
@ -370,8 +326,6 @@ clutter_align_constraint_init (ClutterAlignConstraint *self)
self->actor = NULL;
self->source = NULL;
self->align_axis = CLUTTER_ALIGN_X_AXIS;
self->pivot.x = -1.f;
self->pivot.y = -1.f;
self->factor = 0.0f;
}
@ -449,15 +403,15 @@ clutter_align_constraint_set_source (ClutterAlignConstraint *align,
G_CALLBACK (source_destroyed),
align);
g_signal_handlers_disconnect_by_func (old_source,
G_CALLBACK (source_queue_relayout),
G_CALLBACK (source_position_changed),
align);
}
align->source = source;
if (align->source != NULL)
{
g_signal_connect (align->source, "queue-relayout",
G_CALLBACK (source_queue_relayout),
g_signal_connect (align->source, "allocation-changed",
G_CALLBACK (source_position_changed),
align);
g_signal_connect (align->source, "destroy",
G_CALLBACK (source_destroyed),
@ -534,60 +488,6 @@ clutter_align_constraint_get_align_axis (ClutterAlignConstraint *align)
return align->align_axis;
}
/**
* clutter_align_constraint_set_pivot_point:
* @align: a #ClutterAlignConstraint
* @pivot_point: A #GraphenePoint
*
* Sets the pivot point used by the constraint, the pivot point is the
* point in the constraint actor around which the aligning is applied,
* with (0, 0) being the top left corner of the actor and (1, 1) the
* bottom right corner of the actor.
*
* If -1 is used, the pivot point is unset and the constrained actor
* will be aligned to always stay inside the source actor.
*/
void
clutter_align_constraint_set_pivot_point (ClutterAlignConstraint *align,
const graphene_point_t *pivot_point)
{
g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align));
g_return_if_fail (pivot_point != NULL);
g_return_if_fail (pivot_point->x == -1.f ||
(pivot_point->x >= 0.f && pivot_point->x <= 1.f));
g_return_if_fail (pivot_point->y == -1.f ||
(pivot_point->y >= 0.f && pivot_point->y <= 1.f));
if (graphene_point_equal (&align->pivot, pivot_point))
return;
align->pivot = *pivot_point;
if (align->actor != NULL)
clutter_actor_queue_relayout (align->actor);
g_object_notify_by_pspec (G_OBJECT (align), obj_props[PROP_PIVOT_POINT]);
}
/**
* clutter_align_constraint_get_pivot_point
* @align: a #ClutterAlignConstraint
* @pivot_point: (out caller-allocates): return location for a #GraphenePoint
*
* Gets the pivot point used by the constraint set with
* clutter_align_constraint_set_pivot_point(). If no custom pivot
* point is set, -1 is set.
*/
void
clutter_align_constraint_get_pivot_point (ClutterAlignConstraint *align,
graphene_point_t *pivot_point)
{
g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align));
g_return_if_fail (pivot_point != NULL);
*pivot_point = align->pivot;
}
/**
* clutter_align_constraint_set_factor:
* @align: a #ClutterAlignConstraint

View File

@ -67,12 +67,6 @@ void clutter_align_constraint_set_align_axis (ClutterAlignConstrai
CLUTTER_EXPORT
ClutterAlignAxis clutter_align_constraint_get_align_axis (ClutterAlignConstraint *align);
CLUTTER_EXPORT
void clutter_align_constraint_set_pivot_point (ClutterAlignConstraint *align,
const graphene_point_t *pivot_point);
CLUTTER_EXPORT
void clutter_align_constraint_get_pivot_point (ClutterAlignConstraint *align,
graphene_point_t *pivot_point);
CLUTTER_EXPORT
void clutter_align_constraint_set_factor (ClutterAlignConstraint *align,
gfloat factor);
CLUTTER_EXPORT

View File

@ -27,23 +27,36 @@
* @short_description: Interface for animatable classes
*
* #ClutterAnimatable is an interface that allows a #GObject class
* to control how an actor will animate a property.
* to control how a #ClutterAnimation will animate a property.
*
* Each #ClutterAnimatable should implement the
* #ClutterAnimatableInterface.interpolate_property() virtual function of the
* interface to compute the animation state between two values of an interval
* depending on a progress factor, expressed as a floating point value.
*
* If a #ClutterAnimatable is animated by a #ClutterAnimation
* instance, the #ClutterAnimation will call
* clutter_animatable_interpolate_property() passing the name of the
* currently animated property; the values interval; and the progress factor.
* The #ClutterAnimatable implementation should return the computed value for
* the animated
* property.
*
* #ClutterAnimatable is available since Clutter 1.0
*/
#include "clutter-build-config.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "clutter-animatable.h"
#include "clutter-interval.h"
#include "clutter-debug.h"
#include "clutter-private.h"
#include "deprecated/clutter-animatable.h"
#include "deprecated/clutter-animation.h"
G_DEFINE_INTERFACE (ClutterAnimatable, clutter_animatable, G_TYPE_OBJECT);
static void
@ -51,6 +64,80 @@ clutter_animatable_default_init (ClutterAnimatableInterface *iface)
{
}
/**
* clutter_animatable_animate_property:
* @animatable: a #ClutterAnimatable
* @animation: a #ClutterAnimation
* @property_name: the name of the animated property
* @initial_value: the initial value of the animation interval
* @final_value: the final value of the animation interval
* @progress: the progress factor
* @value: return location for the animation value
*
* Calls the animate_property() virtual function for @animatable.
*
* The @initial_value and @final_value #GValue<!-- -->s must contain
* the same type; @value must have been initialized to the same
* type of @initial_value and @final_value.
*
* All implementation of the #ClutterAnimatable interface must
* implement this function.
*
* Return value: %TRUE if the value has been validated and can
* be applied to the #ClutterAnimatable, and %FALSE otherwise
*
* Since: 1.0
*
* Deprecated: 1.8: Use clutter_animatable_interpolate_value()
* instead
*/
gboolean
clutter_animatable_animate_property (ClutterAnimatable *animatable,
ClutterAnimation *animation,
const gchar *property_name,
const GValue *initial_value,
const GValue *final_value,
gdouble progress,
GValue *value)
{
ClutterAnimatableInterface *iface;
gboolean res;
g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), FALSE);
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), FALSE);
g_return_val_if_fail (property_name != NULL, FALSE);
g_return_val_if_fail (initial_value != NULL && final_value != NULL, FALSE);
g_return_val_if_fail (G_VALUE_TYPE (initial_value) != G_TYPE_INVALID, FALSE);
g_return_val_if_fail (G_VALUE_TYPE (final_value) != G_TYPE_INVALID, FALSE);
g_return_val_if_fail (value != NULL, FALSE);
g_return_val_if_fail (G_VALUE_TYPE (value) == G_VALUE_TYPE (initial_value) &&
G_VALUE_TYPE (value) == G_VALUE_TYPE (final_value),
FALSE);
iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable);
if (iface->animate_property == NULL)
{
ClutterInterval *interval;
interval = clutter_animation_get_interval (animation, property_name);
if (interval == NULL)
return FALSE;
res = clutter_animatable_interpolate_value (animatable, property_name,
interval,
progress,
value);
}
else
res = iface->animate_property (animatable, animation,
property_name,
initial_value, final_value,
progress,
value);
return res;
}
/**
* clutter_animatable_find_property:
* @animatable: a #ClutterAnimatable
@ -194,25 +281,3 @@ clutter_animatable_interpolate_value (ClutterAnimatable *animatable,
else
return clutter_interval_compute_value (interval, progress, value);
}
/**
* clutter_animatable_get_actor:
* @animatable: a #ClutterAnimatable
*
* Get animated actor.
*
* Return value: (transfer none): a #ClutterActor
*/
ClutterActor *
clutter_animatable_get_actor (ClutterAnimatable *animatable)
{
ClutterAnimatableInterface *iface;
g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), NULL);
iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable);
g_return_val_if_fail (iface->get_actor, NULL);
return iface->get_actor (animatable);
}

View File

@ -42,6 +42,8 @@ G_DECLARE_INTERFACE (ClutterAnimatable, clutter_animatable,
/**
* ClutterAnimatableInterface:
* @animate_property: virtual function for custom interpolation of a
* property. This virtual function is deprecated
* @find_property: virtual function for retrieving the #GParamSpec of
* an animatable property
* @get_initial_state: virtual function for retrieving the initial
@ -50,7 +52,9 @@ G_DECLARE_INTERFACE (ClutterAnimatable, clutter_animatable,
* animatable property
* @interpolate_value: virtual function for interpolating the progress
* of a property
* @get_actor: virtual function for getting associated actor
*
* Base interface for #GObject<!-- -->s that can be animated by a
* a #ClutterAnimation.
*
* Since: 1.0
*/
@ -60,6 +64,13 @@ struct _ClutterAnimatableInterface
GTypeInterface parent_iface;
/*< public >*/
gboolean (* animate_property) (ClutterAnimatable *animatable,
ClutterAnimation *animation,
const gchar *property_name,
const GValue *initial_value,
const GValue *final_value,
gdouble progress,
GValue *value);
GParamSpec *(* find_property) (ClutterAnimatable *animatable,
const gchar *property_name);
void (* get_initial_state) (ClutterAnimatable *animatable,
@ -73,7 +84,6 @@ struct _ClutterAnimatableInterface
ClutterInterval *interval,
gdouble progress,
GValue *value);
ClutterActor * (* get_actor) (ClutterAnimatable *animatable);
};
CLUTTER_EXPORT
@ -94,9 +104,6 @@ gboolean clutter_animatable_interpolate_value (ClutterAnimatable *animatable,
gdouble progress,
GValue *value);
CLUTTER_EXPORT
ClutterActor * clutter_animatable_get_actor (ClutterAnimatable *animatable);
G_END_DECLS
#endif /* __CLUTTER_ANIMATABLE_H__ */

View File

@ -30,7 +30,9 @@
#ifndef __GI_SCANNER__
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterAction, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterActor, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterActorMeta, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterAlignConstraint, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBackend, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBindConstraint, g_object_unref)
@ -41,15 +43,19 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBoxLayout, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBrightnessContrastEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterCanvas, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterChildMeta, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterClickAction, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterClone, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterColorizeEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterConstraint, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterContainer, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDeformEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDesaturateEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDragAction, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDropAction, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterFixedLayout, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterFlowLayout, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterGestureAction, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterGridLayout, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterImage, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterInputDevice, g_object_unref)
@ -83,10 +89,14 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterZoomAction, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterActorBox, clutter_actor_box_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterColor, clutter_color_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterMargin, clutter_margin_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintContext, clutter_paint_context_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterMatrix, clutter_matrix_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintNode, clutter_paint_node_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintVolume, clutter_paint_volume_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPathNode, clutter_path_node_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPoint, clutter_point_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterRect, clutter_rect_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterSize, clutter_size_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterVertex, clutter_vertex_free)
#endif /* __GI_SCANNER__ */

View File

@ -23,7 +23,8 @@
#define __CLUTTER_BACKEND_PRIVATE_H__
#include <clutter/clutter-backend.h>
#include <clutter/clutter-seat.h>
#include <clutter/clutter-device-manager.h>
#include <clutter/clutter-keymap.h>
#include <clutter/clutter-stage-window.h>
#define CLUTTER_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND, ClutterBackendClass))
@ -46,6 +47,8 @@ struct _ClutterBackend
CoglOnscreen *dummy_onscreen;
ClutterDeviceManager *device_manager;
cairo_font_options_t *font_options;
gchar *font_name;
@ -53,11 +56,11 @@ struct _ClutterBackend
gfloat units_per_em;
gint32 units_serial;
float fallback_resource_scale;
ClutterStageWindow *stage_window;
ClutterInputMethod *input_method;
ClutterKeymap *keymap;
};
struct _ClutterBackendClass
@ -73,6 +76,7 @@ struct _ClutterBackendClass
ClutterStageWindow * (* create_stage) (ClutterBackend *backend,
ClutterStage *wrapper,
GError **error);
void (* init_events) (ClutterBackend *backend);
void (* init_features) (ClutterBackend *backend);
void (* add_options) (ClutterBackend *backend,
GOptionGroup *group);
@ -85,14 +89,17 @@ struct _ClutterBackendClass
GError **error);
gboolean (* create_context) (ClutterBackend *backend,
GError **error);
ClutterDeviceManager *(* get_device_manager) (ClutterBackend *backend);
gboolean (* translate_event) (ClutterBackend *backend,
gpointer native,
ClutterEvent *event);
ClutterSeat * (* get_default_seat) (ClutterBackend *backend);
PangoDirection (* get_keymap_direction) (ClutterBackend *backend);
gboolean (* is_display_server) (ClutterBackend *backend);
void (* bell_notify) (ClutterBackend *backend);
ClutterKeymap * (* get_keymap) (ClutterBackend *backend);
/* signals */
void (* resolution_changed) (ClutterBackend *backend);
@ -115,6 +122,12 @@ gboolean _clutter_backend_pre_parse (Clutter
gboolean _clutter_backend_post_parse (ClutterBackend *backend,
GError **error);
void _clutter_backend_init_events (ClutterBackend *backend);
void _clutter_backend_copy_event_data (ClutterBackend *backend,
const ClutterEvent *src,
ClutterEvent *dest);
void _clutter_backend_free_event_data (ClutterBackend *backend,
ClutterEvent *event);
CLUTTER_EXPORT
gboolean _clutter_backend_translate_event (ClutterBackend *backend,
gpointer native,
@ -126,22 +139,16 @@ gfloat _clutter_backend_get_units_per_em (Clutter
PangoFontDescription *font_desc);
gint32 _clutter_backend_get_units_serial (ClutterBackend *backend);
PangoDirection _clutter_backend_get_keymap_direction (ClutterBackend *backend);
CLUTTER_EXPORT
void _clutter_backend_reset_cogl_framebuffer (ClutterBackend *backend);
void clutter_set_allowed_drivers (const char *drivers);
CLUTTER_EXPORT
ClutterStageWindow * clutter_backend_get_stage_window (ClutterBackend *backend);
CLUTTER_EXPORT
void clutter_backend_set_fallback_resource_scale (ClutterBackend *backend,
float fallback_resource_scale);
float clutter_backend_get_fallback_resource_scale (ClutterBackend *backend);
gboolean clutter_backend_is_display_server (ClutterBackend *backend);
CLUTTER_EXPORT
void clutter_backend_destroy (ClutterBackend *backend);
G_END_DECLS
#endif /* __CLUTTER_BACKEND_PRIVATE_H__ */

View File

@ -40,6 +40,8 @@
#include "clutter-build-config.h"
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include "clutter-backend-private.h"
#include "clutter-debug.h"
#include "clutter-event-private.h"
@ -49,9 +51,27 @@
#include "clutter-stage-manager-private.h"
#include "clutter-stage-private.h"
#include "clutter-stage-window.h"
#include "clutter-device-manager-private.h"
#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
#include "wayland/clutter-wayland-compositor.h"
#endif
#include <cogl/cogl.h>
#ifdef CLUTTER_INPUT_X11
#include "x11/clutter-backend-x11.h"
#endif
#ifdef CLUTTER_WINDOWING_EGL
#include "egl/clutter-backend-eglnative.h"
#endif
#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
#include <cogl/cogl-wayland-server.h>
#include <wayland-server.h>
#include "wayland/clutter-wayland-compositor.h"
#endif
#define DEFAULT_FONT_NAME "Sans 10"
enum
@ -67,6 +87,12 @@ G_DEFINE_ABSTRACT_TYPE (ClutterBackend, clutter_backend, G_TYPE_OBJECT)
static guint backend_signals[LAST_SIGNAL] = { 0, };
/* Global for being able to specify a compositor side wayland display
* pointer before clutter initialization */
#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
static struct wl_display *_wayland_compositor_display;
#endif
static void
clutter_backend_dispose (GObject *gobject)
{
@ -75,20 +101,28 @@ clutter_backend_dispose (GObject *gobject)
/* clear the events still in the queue of the main context */
_clutter_clear_events_queue ();
g_clear_object (&backend->dummy_onscreen);
g_clear_pointer (&backend->dummy_onscreen, cogl_object_unref);
if (backend->stage_window)
{
g_object_remove_weak_pointer (G_OBJECT (backend->stage_window),
(gpointer *) &backend->stage_window);
backend->stage_window = NULL;
}
g_clear_pointer (&backend->cogl_source, g_source_destroy);
g_clear_pointer (&backend->font_name, g_free);
g_clear_pointer (&backend->font_options, cairo_font_options_destroy);
G_OBJECT_CLASS (clutter_backend_parent_class)->dispose (gobject);
}
static void
clutter_backend_finalize (GObject *gobject)
{
ClutterBackend *backend = CLUTTER_BACKEND (gobject);
g_source_destroy (backend->cogl_source);
g_free (backend->font_name);
clutter_backend_set_font_options (backend, NULL);
g_clear_object (&backend->input_method);
G_OBJECT_CLASS (clutter_backend_parent_class)->dispose (gobject);
G_OBJECT_CLASS (clutter_backend_parent_class)->finalize (gobject);
}
static gfloat
@ -189,20 +223,22 @@ clutter_backend_do_real_create_context (ClutterBackend *backend,
{
ClutterBackendClass *klass;
CoglSwapChain *swap_chain;
GError *internal_error;
klass = CLUTTER_BACKEND_GET_CLASS (backend);
swap_chain = NULL;
internal_error = NULL;
CLUTTER_NOTE (BACKEND, "Creating Cogl renderer");
backend->cogl_renderer = klass->get_renderer (backend, error);
backend->cogl_renderer = klass->get_renderer (backend, &internal_error);
if (backend->cogl_renderer == NULL)
goto error;
CLUTTER_NOTE (BACKEND, "Connecting the renderer");
cogl_renderer_set_driver (backend->cogl_renderer, driver_id);
if (!cogl_renderer_connect (backend->cogl_renderer, error))
if (!cogl_renderer_connect (backend->cogl_renderer, &internal_error))
goto error;
CLUTTER_NOTE (BACKEND, "Creating Cogl swap chain");
@ -214,7 +250,7 @@ clutter_backend_do_real_create_context (ClutterBackend *backend,
backend->cogl_display = klass->get_display (backend,
backend->cogl_renderer,
swap_chain,
error);
&internal_error);
}
else
{
@ -230,7 +266,7 @@ clutter_backend_do_real_create_context (ClutterBackend *backend,
*/
res = cogl_renderer_check_onscreen_template (backend->cogl_renderer,
tmpl,
error);
&internal_error);
if (!res)
goto error;
@ -244,12 +280,17 @@ clutter_backend_do_real_create_context (ClutterBackend *backend,
if (backend->cogl_display == NULL)
goto error;
#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
cogl_wayland_display_set_compositor_display (backend->cogl_display,
_wayland_compositor_display);
#endif
CLUTTER_NOTE (BACKEND, "Setting up the display");
if (!cogl_display_setup (backend->cogl_display, error))
if (!cogl_display_setup (backend->cogl_display, &internal_error))
goto error;
CLUTTER_NOTE (BACKEND, "Creating the Cogl context");
backend->cogl_context = cogl_context_new (backend->cogl_display, error);
backend->cogl_context = cogl_context_new (backend->cogl_display, &internal_error);
if (backend->cogl_context == NULL)
goto error;
@ -382,6 +423,14 @@ clutter_backend_real_get_features (ClutterBackend *backend)
flags |= CLUTTER_FEATURE_STAGE_STATIC;
}
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_THROTTLE))
{
CLUTTER_NOTE (BACKEND, "Cogl supports swap buffers throttling");
flags |= CLUTTER_FEATURE_SWAP_THROTTLE;
}
else
CLUTTER_NOTE (BACKEND, "Cogl doesn't support swap buffers throttling");
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT))
{
CLUTTER_NOTE (BACKEND, "Cogl supports swap buffers complete events");
@ -391,8 +440,23 @@ clutter_backend_real_get_features (ClutterBackend *backend)
return flags;
}
static const char *allowed_backends;
static ClutterBackend * (* custom_backend_func) (void);
static const struct {
const char *name;
ClutterBackend * (* create_backend) (void);
} available_backends[] = {
#ifdef CLUTTER_WINDOWING_X11
{ CLUTTER_WINDOWING_X11, clutter_backend_x11_new },
#endif
#ifdef CLUTTER_WINDOWING_EGL
{ CLUTTER_WINDOWING_EGL, clutter_backend_egl_native_new },
#endif
{ NULL, NULL },
};
void
clutter_set_custom_backend_func (ClutterBackend *(* func) (void))
{
@ -402,23 +466,99 @@ clutter_set_custom_backend_func (ClutterBackend *(* func) (void))
ClutterBackend *
_clutter_create_backend (void)
{
const char *backends_list;
ClutterBackend *retval;
gboolean allow_any;
char **backends;
int i;
g_return_val_if_fail (custom_backend_func, NULL);
if (custom_backend_func)
{
retval = custom_backend_func ();
retval = custom_backend_func ();
if (!retval)
g_error ("Failed to create custom backend.");
if (!retval)
g_error ("Failed to create custom backend.");
return retval;
}
if (allowed_backends == NULL)
allowed_backends = "*";
allow_any = strstr (allowed_backends, "*") != NULL;
backends_list = g_getenv ("CLUTTER_BACKEND");
if (backends_list == NULL)
backends_list = allowed_backends;
backends = g_strsplit (backends_list, ",", 0);
retval = NULL;
for (i = 0; retval == NULL && backends[i] != NULL; i++)
{
const char *backend = backends[i];
gboolean is_any = g_str_equal (backend, "*");
int j;
for (j = 0; available_backends[j].name != NULL; j++)
{
if ((is_any && allow_any) ||
(is_any && strstr (allowed_backends, available_backends[j].name)) ||
g_str_equal (backend, available_backends[j].name))
{
retval = available_backends[j].create_backend ();
if (retval != NULL)
break;
}
}
}
g_strfreev (backends);
if (retval == NULL)
g_error ("No default Clutter backend found.");
return retval;
}
static void
clutter_backend_real_init_events (ClutterBackend *backend)
{
g_error ("Unknown input backend");
}
static ClutterDeviceManager *
clutter_backend_real_get_device_manager (ClutterBackend *backend)
{
if (G_UNLIKELY (backend->device_manager == NULL))
{
g_critical ("No device manager available, expect broken input");
return NULL;
}
return backend->device_manager;
}
static ClutterKeymap *
clutter_backend_real_get_keymap (ClutterBackend *backend)
{
if (G_UNLIKELY (backend->keymap == NULL))
{
g_critical ("No keymap available, expect broken keyboard input");
return NULL;
}
return backend->keymap;
}
static void
clutter_backend_class_init (ClutterBackendClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = clutter_backend_dispose;
gobject_class->finalize = clutter_backend_finalize;
/**
* ClutterBackend::resolution-changed:
@ -474,8 +614,11 @@ clutter_backend_class_init (ClutterBackendClass *klass)
klass->resolution_changed = clutter_backend_real_resolution_changed;
klass->font_changed = clutter_backend_real_font_changed;
klass->init_events = clutter_backend_real_init_events;
klass->get_device_manager = clutter_backend_real_get_device_manager;
klass->create_context = clutter_backend_real_create_context;
klass->get_features = clutter_backend_real_get_features;
klass->get_keymap = clutter_backend_real_get_keymap;
}
static void
@ -484,9 +627,7 @@ clutter_backend_init (ClutterBackend *self)
self->units_per_em = -1.0;
self->units_serial = 1;
self->dummy_onscreen = NULL;
self->fallback_resource_scale = 1.f;
self->dummy_onscreen = COGL_INVALID_HANDLE;
}
void
@ -612,6 +753,17 @@ _clutter_backend_get_features (ClutterBackend *backend)
return 0;
}
void
_clutter_backend_init_events (ClutterBackend *backend)
{
ClutterBackendClass *klass;
g_assert (CLUTTER_IS_BACKEND (backend));
klass = CLUTTER_BACKEND_GET_CLASS (backend);
klass->init_events (backend);
}
gfloat
_clutter_backend_get_units_per_em (ClutterBackend *backend,
PangoFontDescription *font_desc)
@ -626,6 +778,31 @@ _clutter_backend_get_units_per_em (ClutterBackend *backend,
return backend->units_per_em;
}
void
_clutter_backend_copy_event_data (ClutterBackend *backend,
const ClutterEvent *src,
ClutterEvent *dest)
{
ClutterDeviceManagerClass *device_manager_class;
ClutterDeviceManager *device_manager;
device_manager = clutter_device_manager_get_default ();
device_manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
device_manager_class->copy_event_data (device_manager, src, dest);
}
void
_clutter_backend_free_event_data (ClutterBackend *backend,
ClutterEvent *event)
{
ClutterDeviceManagerClass *device_manager_class;
ClutterDeviceManager *device_manager;
device_manager = clutter_device_manager_get_default ();
device_manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
device_manager_class->free_event_data (device_manager, event);
}
/**
* clutter_get_default_backend:
*
@ -795,6 +972,64 @@ clutter_backend_get_cogl_context (ClutterBackend *backend)
return backend->cogl_context;
}
#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
/**
* clutter_wayland_set_compositor_display:
* @display: A compositor side struct wl_display pointer
*
* This informs Clutter of your compositor side Wayland display
* object. This must be called before calling clutter_init().
*
* Since: 1.8
* Stability: unstable
*/
void
clutter_wayland_set_compositor_display (void *display)
{
if (_clutter_context_is_initialized ())
{
g_warning ("%s() can only be used before calling clutter_init()",
G_STRFUNC);
return;
}
_wayland_compositor_display = display;
}
#endif
PangoDirection
_clutter_backend_get_keymap_direction (ClutterBackend *backend)
{
ClutterBackendClass *klass;
klass = CLUTTER_BACKEND_GET_CLASS (backend);
if (klass->get_keymap_direction != NULL)
return klass->get_keymap_direction (backend);
return PANGO_DIRECTION_NEUTRAL;
}
void
_clutter_backend_reset_cogl_framebuffer (ClutterBackend *backend)
{
if (backend->dummy_onscreen == COGL_INVALID_HANDLE)
{
GError *internal_error = NULL;
backend->dummy_onscreen = cogl_onscreen_new (backend->cogl_context, 1, 1);
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (backend->dummy_onscreen),
&internal_error))
{
g_critical ("Unable to create dummy onscreen: %s", internal_error->message);
g_error_free (internal_error);
return;
}
}
cogl_set_framebuffer (COGL_FRAMEBUFFER (backend->dummy_onscreen));
}
void
clutter_set_allowed_drivers (const char *drivers)
{
@ -807,6 +1042,16 @@ clutter_set_allowed_drivers (const char *drivers)
allowed_drivers = g_strdup (drivers);
}
void
clutter_backend_bell_notify (ClutterBackend *backend)
{
ClutterBackendClass *klass;
klass = CLUTTER_BACKEND_GET_CLASS (backend);
if (klass->bell_notify)
klass->bell_notify (backend);
}
/**
* clutter_backend_get_input_method:
* @backend: the #CLutterBackend
@ -835,50 +1080,22 @@ clutter_backend_set_input_method (ClutterBackend *backend,
g_set_object (&backend->input_method, method);
}
/**
* clutter_backend_get_keymap:
* @backend: the #ClutterBackend
*
* Gets the keymap used by Clutter
*
* Returns: (transfer none): the keymap
**/
ClutterKeymap *
clutter_backend_get_keymap (ClutterBackend *backend)
{
return CLUTTER_BACKEND_GET_CLASS (backend)->get_keymap (backend);
}
ClutterStageWindow *
clutter_backend_get_stage_window (ClutterBackend *backend)
{
return backend->stage_window;
}
/**
* clutter_backend_get_default_seat:
* @backend: the #ClutterBackend
*
* Returns the default seat
*
* Returns: (transfer none): the default seat
**/
ClutterSeat *
clutter_backend_get_default_seat (ClutterBackend *backend)
{
g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), NULL);
return CLUTTER_BACKEND_GET_CLASS (backend)->get_default_seat (backend);
}
void
clutter_backend_set_fallback_resource_scale (ClutterBackend *backend,
float fallback_resource_scale)
{
backend->fallback_resource_scale = fallback_resource_scale;
}
float
clutter_backend_get_fallback_resource_scale (ClutterBackend *backend)
{
return backend->fallback_resource_scale;
}
gboolean
clutter_backend_is_display_server (ClutterBackend *backend)
{
return CLUTTER_BACKEND_GET_CLASS (backend)->is_display_server (backend);
}
void
clutter_backend_destroy (ClutterBackend *backend)
{
g_object_run_dispose (G_OBJECT (backend));
g_object_unref (backend);
}

View File

@ -33,9 +33,9 @@
#include <cogl/cogl.h>
#include <clutter/clutter-config.h>
#include <clutter/clutter-keymap.h>
#include <clutter/clutter-types.h>
#include <clutter/clutter-seat.h>
G_BEGIN_DECLS
@ -72,6 +72,9 @@ const cairo_font_options_t * clutter_backend_get_font_options (Clutter
CLUTTER_EXPORT
CoglContext * clutter_backend_get_cogl_context (ClutterBackend *backend);
CLUTTER_EXPORT
void clutter_backend_bell_notify (ClutterBackend *backend);
CLUTTER_EXPORT
ClutterInputMethod * clutter_backend_get_input_method (ClutterBackend *backend);
@ -79,7 +82,7 @@ CLUTTER_EXPORT
void clutter_backend_set_input_method (ClutterBackend *backend,
ClutterInputMethod *method);
CLUTTER_EXPORT
ClutterSeat * clutter_backend_get_default_seat (ClutterBackend *backend);
ClutterKeymap * clutter_backend_get_keymap (ClutterBackend *backend);
G_END_DECLS

File diff suppressed because it is too large Load Diff

View File

@ -35,7 +35,7 @@
#undef CBZ_L2T_INTERPOLATION
/****************************************************************************
* ClutterBezier -- representation of a cubic bezier curve *
* ClutterBezier -- represenation of a cubic bezier curve *
* (private; a building block for the public bspline object) *
****************************************************************************/
@ -104,7 +104,7 @@ struct _ClutterBezier
ClutterBezier *
_clutter_bezier_new (void)
{
return g_new0 (ClutterBezier, 1);
return g_slice_new0 (ClutterBezier);
}
void
@ -112,7 +112,7 @@ _clutter_bezier_free (ClutterBezier * b)
{
if (G_LIKELY (b))
{
g_free (b);
g_slice_free (ClutterBezier, b);
}
}
@ -213,7 +213,7 @@ sqrti (int number)
* algorithm does not calculate the square root, but its reciprocal ('y'
* below), which is only at the end turned to the inverse value. In order
* for the algorithm to produce satisfactory results, the reciprocal value
* must be represented with sufficient precision; the 16.16 we use
* must be represented with sufficient precission; the 16.16 we use
* elsewhere in clutter is not good enough, and 10.22 is used instead.
*/
_FixedT x;
@ -236,7 +236,7 @@ sqrti (int number)
/* Now, we convert the float to 10.22 fixed. We exploit the mechanism
* described at http://www.d6.com/users/checker/pdfs/gdmfp.pdf.
*
* We want 22 bit fraction; a single precision float uses 23 bit
* We want 22 bit fraction; a single precission float uses 23 bit
* mantisa, so we only need to add 2^(23-22) (no need for the 1.5
* multiplier as we are only dealing with positive numbers).
*
@ -256,7 +256,7 @@ sqrti (int number)
flt2.i = (flt2.i >> 11) * (y_1 >> 11);
/* If the original argument is less than 342, we do another
* iteration to improve precision (for arguments >= 342, the single
* iteration to improve precission (for arguments >= 342, the single
* iteration produces generally better results).
*/
if (x < 171)

View File

@ -49,10 +49,10 @@
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "deprecated/clutter-container.h"
#include "deprecated/clutter-bin-layout.h"
#include "clutter-actor-private.h"
#include "clutter-animatable.h"
#include "clutter-bin-layout.h"
#include "clutter-child-meta.h"
#include "clutter-debug.h"
#include "clutter-enum-types.h"
@ -406,7 +406,8 @@ get_actor_align_factor (ClutterActorAlign alignment)
static void
clutter_bin_layout_allocate (ClutterLayoutManager *manager,
ClutterContainer *container,
const ClutterActorBox *allocation)
const ClutterActorBox *allocation,
ClutterAllocationFlags flags)
{
gfloat allocation_x, allocation_y;
gfloat available_w, available_h;
@ -514,7 +515,8 @@ clutter_bin_layout_allocate (ClutterLayoutManager *manager,
clutter_actor_allocate_align_fill (child, &child_alloc,
x_align, y_align,
x_fill, y_fill);
x_fill, y_fill,
flags);
}
}
@ -696,3 +698,187 @@ clutter_bin_layout_new (ClutterBinAlignment x_align,
"y-align", y_align,
NULL);
}
/**
* clutter_bin_layout_set_alignment:
* @self: a #ClutterBinLayout
* @child: (allow-none): a child of @container
* @x_align: the horizontal alignment policy to be used for the @child
* inside @container
* @y_align: the vertical aligment policy to be used on the @child
* inside @container
*
* Sets the horizontal and vertical alignment policies to be applied
* to a @child of @self
*
* If @child is %NULL then the @x_align and @y_align values will
* be set as the default alignment policies
*
* Since: 1.2
*
* Deprecated: 1.12: Use the #ClutterActor:x-align and
* #ClutterActor:y-align properties of #ClutterActor instead.
*/
void
clutter_bin_layout_set_alignment (ClutterBinLayout *self,
ClutterActor *child,
ClutterBinAlignment x_align,
ClutterBinAlignment y_align)
{
ClutterBinLayoutPrivate *priv;
ClutterLayoutManager *manager;
ClutterLayoutMeta *meta;
g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
g_return_if_fail (child == NULL || CLUTTER_IS_ACTOR (child));
priv = self->priv;
if (priv->container == NULL)
{
if (child == NULL)
{
set_x_align (self, x_align);
set_y_align (self, y_align);
}
else
g_warning ("The layout of type '%s' must be associated to "
"a ClutterContainer before setting the alignment "
"on its children",
G_OBJECT_TYPE_NAME (self));
return;
}
manager = CLUTTER_LAYOUT_MANAGER (self);
meta = clutter_layout_manager_get_child_meta (manager,
priv->container,
child);
g_assert (CLUTTER_IS_BIN_LAYER (meta));
set_layer_x_align (CLUTTER_BIN_LAYER (meta), x_align);
set_layer_y_align (CLUTTER_BIN_LAYER (meta), y_align);
}
/**
* clutter_bin_layout_get_alignment:
* @self: a #ClutterBinLayout
* @child: (allow-none): a child of @container
* @x_align: (out) (allow-none): return location for the horizontal
* alignment policy
* @y_align: (out) (allow-none): return location for the vertical
* alignment policy
*
* Retrieves the horizontal and vertical alignment policies for
* a child of @self
*
* If @child is %NULL the default alignment policies will be returned
* instead
*
* Since: 1.2
*
* Deprecated: 1.12: Use the #ClutterActor:x-align and the
* #ClutterActor:y-align properties of #ClutterActor instead.
*/
void
clutter_bin_layout_get_alignment (ClutterBinLayout *self,
ClutterActor *child,
ClutterBinAlignment *x_align,
ClutterBinAlignment *y_align)
{
ClutterBinLayoutPrivate *priv;
ClutterLayoutManager *manager;
ClutterLayoutMeta *meta;
ClutterBinLayer *layer;
g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
priv = self->priv;
if (priv->container == NULL)
{
if (child == NULL)
{
if (x_align)
*x_align = priv->x_align;
if (y_align)
*y_align = priv->y_align;
}
else
g_warning ("The layout of type '%s' must be associated to "
"a ClutterContainer before getting the alignment "
"of its children",
G_OBJECT_TYPE_NAME (self));
return;
}
manager = CLUTTER_LAYOUT_MANAGER (self);
meta = clutter_layout_manager_get_child_meta (manager,
priv->container,
child);
g_assert (CLUTTER_IS_BIN_LAYER (meta));
layer = CLUTTER_BIN_LAYER (meta);
if (x_align)
*x_align = layer->x_align;
if (y_align)
*y_align = layer->y_align;
}
/**
* clutter_bin_layout_add:
* @self: a #ClutterBinLayout
* @child: a #ClutterActor
* @x_align: horizontal alignment policy for @child
* @y_align: vertical alignment policy for @child
*
* Adds a #ClutterActor to the container using @self and
* sets the alignment policies for it
*
* This function is equivalent to clutter_container_add_actor()
* and clutter_layout_manager_child_set_property() but it does not
* require a pointer to the #ClutterContainer associated to the
* #ClutterBinLayout
*
* Since: 1.2
*
* Deprecated: 1.12: Use clutter_actor_add_child() instead.
*/
void
clutter_bin_layout_add (ClutterBinLayout *self,
ClutterActor *child,
ClutterBinAlignment x_align,
ClutterBinAlignment y_align)
{
ClutterBinLayoutPrivate *priv;
ClutterLayoutManager *manager;
ClutterLayoutMeta *meta;
g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
g_return_if_fail (CLUTTER_IS_ACTOR (child));
priv = self->priv;
if (priv->container == NULL)
{
g_warning ("The layout of type '%s' must be associated to "
"a ClutterContainer before adding children",
G_OBJECT_TYPE_NAME (self));
return;
}
clutter_container_add_actor (priv->container, child);
manager = CLUTTER_LAYOUT_MANAGER (self);
meta = clutter_layout_manager_get_child_meta (manager,
priv->container,
child);
g_assert (CLUTTER_IS_BIN_LAYER (meta));
set_layer_x_align (CLUTTER_BIN_LAYER (meta), x_align);
set_layer_y_align (CLUTTER_BIN_LAYER (meta), y_align);
}

View File

@ -38,14 +38,12 @@
*
* |[<!-- language="C" -->
* // source
* rect[0] = clutter_actor_new ();
* clutter_actor_set_background_color (rect[0], &red_color);
* rect[0] = clutter_rectangle_new_with_color (&red_color);
* clutter_actor_set_position (rect[0], x_pos, y_pos);
* clutter_actor_set_size (rect[0], 100, 100);
*
* // second rectangle
* rect[1] = clutter_actor_new ();
* clutter_actor_set_background_color (rect[1], &green_color);
* rect[1] = clutter_rectangle_new_with_color (&green_color);
* clutter_actor_set_size (rect[1], 100, 100);
* clutter_actor_set_opacity (rect[1], 0);
*
@ -55,8 +53,7 @@
* clutter_actor_add_constraint_with_name (rect[1], "green-y", constraint);
*
* // third rectangle
* rect[2] = clutter_actor_new ();
* clutter_actor_set_background_color (rect[2], &blue_color);
* rect[2] = clutter_rectangle_new_with_color (&blue_color);
* clutter_actor_set_size (rect[2], 100, 100);
* clutter_actor_set_opacity (rect[2], 0);
*
@ -147,58 +144,6 @@ source_destroyed (ClutterActor *actor,
bind->source = NULL;
}
static void
clutter_bind_constraint_update_preferred_size (ClutterConstraint *constraint,
ClutterActor *actor,
ClutterOrientation direction,
float for_size,
float *minimum_size,
float *natural_size)
{
ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (constraint);
float source_min, source_nat;
if (bind->source == NULL)
return;
/* only these bindings affect the preferred size */
if (!(bind->coordinate == CLUTTER_BIND_WIDTH ||
bind->coordinate == CLUTTER_BIND_HEIGHT ||
bind->coordinate == CLUTTER_BIND_SIZE ||
bind->coordinate == CLUTTER_BIND_ALL))
return;
if (clutter_actor_contains (bind->source, actor))
return;
switch (direction)
{
case CLUTTER_ORIENTATION_HORIZONTAL:
if (bind->coordinate != CLUTTER_BIND_HEIGHT)
{
clutter_actor_get_preferred_width (bind->source, for_size,
&source_min,
&source_nat);
*minimum_size = source_min;
*natural_size = source_nat;
}
break;
case CLUTTER_ORIENTATION_VERTICAL:
if (bind->coordinate != CLUTTER_BIND_WIDTH)
{
clutter_actor_get_preferred_height (bind->source, for_size,
&source_min,
&source_nat);
*minimum_size = source_min;
*natural_size = source_nat;
}
break;
}
}
static void
clutter_bind_constraint_update_allocation (ClutterConstraint *constraint,
ClutterActor *actor,
@ -207,9 +152,7 @@ clutter_bind_constraint_update_allocation (ClutterConstraint *constraint,
ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (constraint);
gfloat source_width, source_height;
gfloat actor_width, actor_height;
graphene_point3d_t source_position;
source_position = GRAPHENE_POINT3D_INIT (0.f, 0.f, 0.f);
ClutterVertex source_position = { 0., };
if (bind->source == NULL)
return;
@ -383,8 +326,6 @@ clutter_bind_constraint_class_init (ClutterBindConstraintClass *klass)
meta_class->set_actor = clutter_bind_constraint_set_actor;
constraint_class->update_allocation = clutter_bind_constraint_update_allocation;
constraint_class->update_preferred_size = clutter_bind_constraint_update_preferred_size;
/**
* ClutterBindConstraint:source:
*

View File

@ -189,7 +189,7 @@ binding_entry_new (const gchar *name,
modifiers = modifiers & BINDING_MOD_MASK;
entry = g_new0 (ClutterBindingEntry, 1);
entry = g_slice_new (ClutterBindingEntry);
entry->key_val = key_val;
entry->modifiers = modifiers;
entry->name = (gchar *) g_intern_string (name);
@ -221,7 +221,7 @@ binding_entry_free (gpointer data)
g_closure_unref (entry->closure);
g_free (entry);
g_slice_free (ClutterBindingEntry, entry);
}
}

View File

@ -39,6 +39,8 @@
#include "clutter-build-config.h"
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include "clutter-blur-effect.h"
#include "cogl/cogl.h"
@ -79,6 +81,9 @@ struct _ClutterBlurEffect
gint pixel_step_uniform;
gint tex_width;
gint tex_height;
CoglPipeline *pipeline;
};
@ -93,42 +98,19 @@ G_DEFINE_TYPE (ClutterBlurEffect,
clutter_blur_effect,
CLUTTER_TYPE_OFFSCREEN_EFFECT);
static CoglPipeline *
clutter_blur_effect_create_pipeline (ClutterOffscreenEffect *effect,
CoglTexture *texture)
{
ClutterBlurEffect *blur_effect = CLUTTER_BLUR_EFFECT (effect);
if (blur_effect->pixel_step_uniform > -1)
{
float pixel_step[2];
int tex_width, tex_height;
tex_width = cogl_texture_get_width (texture);
tex_height = cogl_texture_get_height (texture);
pixel_step[0] = 1.0f / tex_width;
pixel_step[1] = 1.0f / tex_height;
cogl_pipeline_set_uniform_float (blur_effect->pipeline,
blur_effect->pixel_step_uniform,
2, /* n_components */
1, /* count */
pixel_step);
}
cogl_pipeline_set_layer_texture (blur_effect->pipeline, 0, texture);
return cogl_object_ref (blur_effect->pipeline);
}
static gboolean
clutter_blur_effect_pre_paint (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
clutter_blur_effect_pre_paint (ClutterEffect *effect)
{
ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (effect);
ClutterEffectClass *parent_class;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
return FALSE;
self->actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
if (self->actor == NULL)
return FALSE;
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
{
/* if we don't have support for GLSL shaders then we
@ -142,7 +124,57 @@ clutter_blur_effect_pre_paint (ClutterEffect *effect,
}
parent_class = CLUTTER_EFFECT_CLASS (clutter_blur_effect_parent_class);
return parent_class->pre_paint (effect, node, paint_context);
if (parent_class->pre_paint (effect))
{
ClutterOffscreenEffect *offscreen_effect =
CLUTTER_OFFSCREEN_EFFECT (effect);
CoglHandle texture;
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
self->tex_width = cogl_texture_get_width (texture);
self->tex_height = cogl_texture_get_height (texture);
if (self->pixel_step_uniform > -1)
{
gfloat pixel_step[2];
pixel_step[0] = 1.0f / self->tex_width;
pixel_step[1] = 1.0f / self->tex_height;
cogl_pipeline_set_uniform_float (self->pipeline,
self->pixel_step_uniform,
2, /* n_components */
1, /* count */
pixel_step);
}
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
return TRUE;
}
else
return FALSE;
}
static void
clutter_blur_effect_paint_target (ClutterOffscreenEffect *effect)
{
ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (effect);
CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
guint8 paint_opacity;
paint_opacity = clutter_actor_get_paint_opacity (self->actor);
cogl_pipeline_set_color4ub (self->pipeline,
paint_opacity,
paint_opacity,
paint_opacity,
paint_opacity);
cogl_framebuffer_draw_rectangle (framebuffer,
self->pipeline,
0, 0,
self->tex_width, self->tex_height);
}
static gboolean
@ -150,7 +182,7 @@ clutter_blur_effect_modify_paint_volume (ClutterEffect *effect,
ClutterPaintVolume *volume)
{
gfloat cur_width, cur_height;
graphene_point3d_t origin;
ClutterVertex origin;
clutter_paint_volume_get_origin (volume, &origin);
cur_width = clutter_paint_volume_get_width (volume);
@ -194,7 +226,7 @@ clutter_blur_effect_class_init (ClutterBlurEffectClass *klass)
effect_class->modify_paint_volume = clutter_blur_effect_modify_paint_volume;
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
offscreen_class->create_pipeline = clutter_blur_effect_create_pipeline;
offscreen_class->paint_target = clutter_blur_effect_paint_target;
}
static void

View File

@ -1,40 +0,0 @@
/*
* Copyright (C) 2020 Endless OS Foundation, LLC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CLUTTER_BLUR_PRIVATE_H
#define CLUTTER_BLUR_PRIVATE_H
#include <glib-object.h>
#include <cogl/cogl.h>
G_BEGIN_DECLS
typedef struct _ClutterBlur ClutterBlur;
ClutterBlur * clutter_blur_new (CoglTexture *texture,
float sigma);
void clutter_blur_apply (ClutterBlur *blur);
CoglTexture * clutter_blur_get_texture (ClutterBlur *blur);
void clutter_blur_free (ClutterBlur *blur);
G_END_DECLS
#endif /* CLUTTER_BLUR_PRIVATE_H */

View File

@ -1,431 +0,0 @@
/*
* Copyright (C) 2020 Endless OS Foundation, LLC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "clutter-blur-private.h"
#include "clutter-backend.h"
/**
* SECTION:clutter-blur
* @short_description: Blur textures
*
* #ClutterBlur is a moderately fast gaussian blur implementation.
*
* # Optimizations
*
* There are a number of optimizations in place to make this blur implementation
* real-time. All in all, the implementation performs best when using large
* blur-radii that allow downscaling the texture to smaller sizes, at small
* radii where no downscaling is possible this can easily halve the framerate.
*
* ## Multipass
*
* It is implemented in 2 passes: vertical and horizontal.
*
* ## Downscaling
*
* #ClutterBlur uses dynamic downscaling to speed up blurring. Downscaling
* happens in factors of 2 (the image is downscaled either by 2, 4, 8, 16, )
* and depends on the blur radius, the texture size, among others.
*
* The texture is drawn into a downscaled framebuffer; the blur passes are
* applied on the downscaled texture contents; and finally, the blurred
* contents are drawn
* upscaled again.
*
* ## Hardware Interpolation
*
* This blur implementation cuts down the number of sampling operations by
* exploiting the hardware interpolation that is performed when sampling between
* pixel boundaries. This technique is described at:
*
* http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
*
* ## Incremental gauss-factor calculation
*
* The kernel values for the gaussian kernel are computed incrementally instead
* of running the expensive calculations multiple times inside the blur shader.
* The implementation is based on the algorithm presented by K. Turkowski in
* GPU Gems 3, chapter 40:
*
* https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch40.html
*
*/
static const char *gaussian_blur_glsl_declarations =
"uniform float sigma; \n"
"uniform float pixel_step; \n"
"uniform vec2 direction; \n";
static const char *gaussian_blur_glsl =
" vec2 uv = vec2 (cogl_tex_coord.st); \n"
" \n"
" vec3 gauss_coefficient; \n"
" gauss_coefficient.x = 1.0 / (sqrt (2.0 * 3.14159265) * sigma); \n"
" gauss_coefficient.y = exp (-0.5 / (sigma * sigma)); \n"
" gauss_coefficient.z = gauss_coefficient.y * gauss_coefficient.y; \n"
" \n"
" float gauss_coefficient_total = gauss_coefficient.x; \n"
" \n"
" vec4 ret = texture2D (cogl_sampler, uv) * gauss_coefficient.x; \n"
" gauss_coefficient.xy *= gauss_coefficient.yz; \n"
" \n"
" int n_steps = int (ceil (1.5 * sigma)) * 2; \n"
" \n"
" for (int i = 1; i <= n_steps; i += 2) { \n"
" float coefficient_subtotal = gauss_coefficient.x; \n"
" gauss_coefficient.xy *= gauss_coefficient.yz; \n"
" coefficient_subtotal += gauss_coefficient.x; \n"
" \n"
" float gauss_ratio = gauss_coefficient.x / coefficient_subtotal; \n"
" \n"
" float foffset = float (i) + gauss_ratio; \n"
" vec2 offset = direction * foffset * pixel_step; \n"
" \n"
" ret += texture2D (cogl_sampler, uv + offset) * coefficient_subtotal; \n"
" ret += texture2D (cogl_sampler, uv - offset) * coefficient_subtotal; \n"
" \n"
" gauss_coefficient_total += 2.0 * coefficient_subtotal; \n"
" gauss_coefficient.xy *= gauss_coefficient.yz; \n"
" } \n"
" \n"
" cogl_texel = ret / gauss_coefficient_total; \n";
#define MIN_DOWNSCALE_SIZE 256.f
#define MAX_SIGMA 6.f
enum
{
VERTICAL,
HORIZONTAL,
};
typedef struct
{
CoglFramebuffer *framebuffer;
CoglPipeline *pipeline;
CoglTexture *texture;
int orientation;
} BlurPass;
struct _ClutterBlur
{
CoglTexture *source_texture;
float sigma;
float downscale_factor;
BlurPass pass[2];
};
static CoglPipeline*
create_blur_pipeline (void)
{
static CoglPipelineKey blur_pipeline_key = "clutter-blur-pipeline-private";
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
CoglPipeline *blur_pipeline;
blur_pipeline =
cogl_context_get_named_pipeline (ctx, &blur_pipeline_key);
if (G_UNLIKELY (blur_pipeline == NULL))
{
CoglSnippet *snippet;
blur_pipeline = cogl_pipeline_new (ctx);
cogl_pipeline_set_layer_null_texture (blur_pipeline, 0);
cogl_pipeline_set_layer_filters (blur_pipeline,
0,
COGL_PIPELINE_FILTER_LINEAR,
COGL_PIPELINE_FILTER_LINEAR);
cogl_pipeline_set_layer_wrap_mode (blur_pipeline,
0,
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP,
gaussian_blur_glsl_declarations,
NULL);
cogl_snippet_set_replace (snippet, gaussian_blur_glsl);
cogl_pipeline_add_layer_snippet (blur_pipeline, 0, snippet);
cogl_object_unref (snippet);
cogl_context_set_named_pipeline (ctx, &blur_pipeline_key, blur_pipeline);
}
return cogl_pipeline_copy (blur_pipeline);
}
static void
update_blur_uniforms (ClutterBlur *blur,
BlurPass *pass)
{
gboolean vertical = pass->orientation == VERTICAL;
int sigma_uniform;
int pixel_step_uniform;
int direction_uniform;
pixel_step_uniform =
cogl_pipeline_get_uniform_location (pass->pipeline, "pixel_step");
if (pixel_step_uniform > -1)
{
float pixel_step;
if (vertical)
pixel_step = 1.f / cogl_texture_get_height (pass->texture);
else
pixel_step = 1.f / cogl_texture_get_width (pass->texture);
cogl_pipeline_set_uniform_1f (pass->pipeline,
pixel_step_uniform,
pixel_step);
}
sigma_uniform = cogl_pipeline_get_uniform_location (pass->pipeline, "sigma");
if (sigma_uniform > -1)
{
cogl_pipeline_set_uniform_1f (pass->pipeline,
sigma_uniform,
blur->sigma / blur->downscale_factor);
}
direction_uniform =
cogl_pipeline_get_uniform_location (pass->pipeline, "direction");
if (direction_uniform > -1)
{
gboolean horizontal = !vertical;
float direction[2] = {
horizontal,
vertical,
};
cogl_pipeline_set_uniform_float (pass->pipeline,
direction_uniform,
2, 1,
direction);
}
}
static gboolean
create_fbo (ClutterBlur *blur,
BlurPass *pass)
{
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
float scaled_height;
float scaled_width;
float height;
float width;
g_clear_pointer (&pass->texture, cogl_object_unref);
g_clear_object (&pass->framebuffer);
width = cogl_texture_get_width (blur->source_texture);
height = cogl_texture_get_height (blur->source_texture);
scaled_width = floorf (width / blur->downscale_factor);
scaled_height = floorf (height / blur->downscale_factor);
pass->texture = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx,
scaled_width,
scaled_height));
if (!pass->texture)
return FALSE;
pass->framebuffer =
COGL_FRAMEBUFFER (cogl_offscreen_new_with_texture (pass->texture));
if (!pass->framebuffer)
{
g_warning ("%s: Unable to create an Offscreen buffer", G_STRLOC);
return FALSE;
}
cogl_framebuffer_orthographic (pass->framebuffer,
0.0, 0.0,
scaled_width,
scaled_height,
0.0, 1.0);
return TRUE;
}
static gboolean
setup_blur_pass (ClutterBlur *blur,
BlurPass *pass,
int orientation,
CoglTexture *texture)
{
pass->orientation = orientation;
pass->pipeline = create_blur_pipeline ();
cogl_pipeline_set_layer_texture (pass->pipeline, 0, texture);
if (!create_fbo (blur, pass))
return FALSE;
update_blur_uniforms (blur, pass);
return TRUE;
}
static float
calculate_downscale_factor (float width,
float height,
float sigma)
{
float downscale_factor = 1.f;
float scaled_width = width;
float scaled_height = height;
float scaled_sigma = sigma;
/* This is the algorithm used by Firefox; keep downscaling until either the
* blur radius is lower than the threshold, or the downscaled texture is too
* small.
*/
while (scaled_sigma > MAX_SIGMA &&
scaled_width > MIN_DOWNSCALE_SIZE &&
scaled_height > MIN_DOWNSCALE_SIZE)
{
downscale_factor *= 2.f;
scaled_width = width / downscale_factor;
scaled_height = height / downscale_factor;
scaled_sigma = sigma / downscale_factor;
}
return downscale_factor;
}
static void
apply_blur_pass (BlurPass *pass)
{
CoglColor transparent;
cogl_color_init_from_4ub (&transparent, 0, 0, 0, 0);
cogl_framebuffer_clear (pass->framebuffer,
COGL_BUFFER_BIT_COLOR,
&transparent);
cogl_framebuffer_draw_rectangle (pass->framebuffer,
pass->pipeline,
0, 0,
cogl_texture_get_width (pass->texture),
cogl_texture_get_height (pass->texture));
}
static void
clear_blur_pass (BlurPass *pass)
{
g_clear_pointer (&pass->pipeline, cogl_object_unref);
g_clear_pointer (&pass->texture, cogl_object_unref);
g_clear_object (&pass->framebuffer);
}
/**
* clutter_blur_new:
* @texture: a #CoglTexture
* @sigma: blur sigma
*
* Creates a new #ClutterBlur.
*
* Returns: (transfer full) (nullable): A newly created #ClutterBlur
*/
ClutterBlur *
clutter_blur_new (CoglTexture *texture,
float sigma)
{
ClutterBlur *blur;
unsigned int height;
unsigned int width;
BlurPass *hpass;
BlurPass *vpass;
g_return_val_if_fail (texture != NULL, NULL);
g_return_val_if_fail (sigma >= 0.0, NULL);
width = cogl_texture_get_width (texture);
height = cogl_texture_get_height (texture);
blur = g_new0 (ClutterBlur, 1);
blur->sigma = sigma;
blur->source_texture = cogl_object_ref (texture);
blur->downscale_factor = calculate_downscale_factor (width, height, sigma);
if (G_APPROX_VALUE (sigma, 0.0, FLT_EPSILON))
goto out;
vpass = &blur->pass[VERTICAL];
hpass = &blur->pass[HORIZONTAL];
if (!setup_blur_pass (blur, vpass, VERTICAL, texture) ||
!setup_blur_pass (blur, hpass, HORIZONTAL, vpass->texture))
{
clutter_blur_free (blur);
return NULL;
}
out:
return g_steal_pointer (&blur);
}
/**
* clutter_blur_apply:
* @blur: a #ClutterBlur
*
* Applies the blur. The resulting texture can be retrieved by
* clutter_blur_get_texture().
*/
void
clutter_blur_apply (ClutterBlur *blur)
{
if (G_APPROX_VALUE (blur->sigma, 0.0, FLT_EPSILON))
return;
apply_blur_pass (&blur->pass[VERTICAL]);
apply_blur_pass (&blur->pass[HORIZONTAL]);
}
/**
* clutter_blur_get_texture:
* @blur: a #ClutterBlur
*
* Retrieves the texture where the blurred contents are stored. The
* contents are undefined until clutter_blur_apply() is called.
*
* Returns: (transfer none): a #CoglTexture
*/
CoglTexture *
clutter_blur_get_texture (ClutterBlur *blur)
{
if (G_APPROX_VALUE (blur->sigma, 0.0, FLT_EPSILON))
return blur->source_texture;
else
return blur->pass[HORIZONTAL].texture;
}
/**
* clutter_blur_free:
* @blur: A #ClutterBlur
*
* Frees @blur.
*/
void
clutter_blur_free (ClutterBlur *blur)
{
g_assert (blur);
clear_blur_pass (&blur->pass[VERTICAL]);
clear_blur_pass (&blur->pass[HORIZONTAL]);
cogl_clear_object (&blur->source_texture);
g_free (blur);
}

File diff suppressed because it is too large Load Diff

View File

@ -105,6 +105,64 @@ void clutter_box_layout_set_pack_start (ClutterBoxLayou
CLUTTER_EXPORT
gboolean clutter_box_layout_get_pack_start (ClutterBoxLayout *layout);
CLUTTER_DEPRECATED_FOR(clutter_box_layout_set_orientation)
void clutter_box_layout_set_vertical (ClutterBoxLayout *layout,
gboolean vertical);
CLUTTER_DEPRECATED_FOR(clutter_box_layout_get_orientation)
gboolean clutter_box_layout_get_vertical (ClutterBoxLayout *layout);
CLUTTER_EXPORT
void clutter_box_layout_pack (ClutterBoxLayout *layout,
ClutterActor *actor,
gboolean expand,
gboolean x_fill,
gboolean y_fill,
ClutterBoxAlignment x_align,
ClutterBoxAlignment y_align);
CLUTTER_DEPRECATED
void clutter_box_layout_set_alignment (ClutterBoxLayout *layout,
ClutterActor *actor,
ClutterBoxAlignment x_align,
ClutterBoxAlignment y_align);
CLUTTER_DEPRECATED
void clutter_box_layout_get_alignment (ClutterBoxLayout *layout,
ClutterActor *actor,
ClutterBoxAlignment *x_align,
ClutterBoxAlignment *y_align);
CLUTTER_DEPRECATED
void clutter_box_layout_set_fill (ClutterBoxLayout *layout,
ClutterActor *actor,
gboolean x_fill,
gboolean y_fill);
CLUTTER_DEPRECATED
void clutter_box_layout_get_fill (ClutterBoxLayout *layout,
ClutterActor *actor,
gboolean *x_fill,
gboolean *y_fill);
CLUTTER_DEPRECATED
void clutter_box_layout_set_expand (ClutterBoxLayout *layout,
ClutterActor *actor,
gboolean expand);
CLUTTER_DEPRECATED
gboolean clutter_box_layout_get_expand (ClutterBoxLayout *layout,
ClutterActor *actor);
CLUTTER_DEPRECATED
void clutter_box_layout_set_use_animations (ClutterBoxLayout *layout,
gboolean animate);
CLUTTER_DEPRECATED
gboolean clutter_box_layout_get_use_animations (ClutterBoxLayout *layout);
CLUTTER_DEPRECATED
void clutter_box_layout_set_easing_mode (ClutterBoxLayout *layout,
gulong mode);
CLUTTER_DEPRECATED
gulong clutter_box_layout_get_easing_mode (ClutterBoxLayout *layout);
CLUTTER_DEPRECATED
void clutter_box_layout_set_easing_duration (ClutterBoxLayout *layout,
guint msecs);
CLUTTER_DEPRECATED
guint clutter_box_layout_get_easing_duration (ClutterBoxLayout *layout);
G_END_DECLS
#endif /* __CLUTTER_BOX_LAYOUT_H__ */

View File

@ -41,6 +41,8 @@
#include <math.h>
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include "clutter-brightness-contrast-effect.h"
#include <cogl/cogl.h>
@ -67,6 +69,9 @@ struct _ClutterBrightnessContrastEffect
gint brightness_offset_uniform;
gint contrast_uniform;
gint tex_width;
gint tex_height;
CoglPipeline *pipeline;
};
@ -124,26 +129,15 @@ will_have_no_effect (ClutterBrightnessContrastEffect *self)
G_APPROX_VALUE (self->contrast_blue, no_change, FLT_EPSILON));
}
static CoglPipeline *
clutter_brightness_contrast_effect_create_pipeline (ClutterOffscreenEffect *effect,
CoglTexture *texture)
{
ClutterBrightnessContrastEffect *self =
CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect);
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
return cogl_object_ref (self->pipeline);
}
static gboolean
clutter_brightness_contrast_effect_pre_paint (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
clutter_brightness_contrast_effect_pre_paint (ClutterEffect *effect)
{
ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect);
ClutterEffectClass *parent_class;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
return FALSE;
if (will_have_no_effect (self))
return FALSE;
@ -162,8 +156,45 @@ clutter_brightness_contrast_effect_pre_paint (ClutterEffect *effect,
parent_class =
CLUTTER_EFFECT_CLASS (clutter_brightness_contrast_effect_parent_class);
if (parent_class->pre_paint (effect))
{
ClutterOffscreenEffect *offscreen_effect =
CLUTTER_OFFSCREEN_EFFECT (effect);
CoglHandle texture;
return parent_class->pre_paint (effect, node, paint_context);
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
self->tex_width = cogl_texture_get_width (texture);
self->tex_height = cogl_texture_get_height (texture);
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
return TRUE;
}
else
return FALSE;
}
static void
clutter_brightness_contrast_effect_paint_target (ClutterOffscreenEffect *effect)
{
ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect);
CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
ClutterActor *actor;
guint8 paint_opacity;
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
paint_opacity = clutter_actor_get_paint_opacity (actor);
cogl_pipeline_set_color4ub (self->pipeline,
paint_opacity,
paint_opacity,
paint_opacity,
paint_opacity);
cogl_framebuffer_draw_rectangle (framebuffer,
self->pipeline,
0, 0,
self->tex_width, self->tex_height);
}
static void
@ -263,7 +294,7 @@ clutter_brightness_contrast_effect_class_init (ClutterBrightnessContrastEffectCl
ClutterOffscreenEffectClass *offscreen_class;
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
offscreen_class->create_pipeline = clutter_brightness_contrast_effect_create_pipeline;
offscreen_class->paint_target = clutter_brightness_contrast_effect_paint_target;
effect_class->pre_paint = clutter_brightness_contrast_effect_pre_paint;

View File

@ -4,5 +4,11 @@
/* List of Cogl drivers */
#mesondefine CLUTTER_DRIVERS
/* Have evdev support for input handling */
#mesondefine HAVE_EVDEV
/* Building with libwacom for advanced tablet management */
#mesondefine HAVE_LIBWACOM
/* Supports PangoFt2 */
#mesondefine HAVE_PANGO_FT2

View File

@ -50,6 +50,8 @@
#include "clutter-canvas.h"
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include "clutter-actor-private.h"
#include "clutter-backend.h"
#include "clutter-cairo.h"
@ -326,10 +328,9 @@ clutter_canvas_init (ClutterCanvas *self)
}
static void
clutter_canvas_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *root,
ClutterPaintContext *paint_context)
clutter_canvas_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *root)
{
ClutterCanvas *self = CLUTTER_CANVAS (content);
ClutterCanvasPrivate *priv = self->priv;
@ -350,7 +351,7 @@ clutter_canvas_paint_content (ClutterContent *content,
return;
node = clutter_actor_create_texture_paint_node (actor, priv->texture);
clutter_paint_node_set_static_name (node, "Canvas Content");
clutter_paint_node_set_name (node, "Canvas Content");
clutter_paint_node_add_child (root, node);
clutter_paint_node_unref (node);

View File

@ -105,8 +105,8 @@ struct _ClutterClickActionPrivate
{
ClutterActor *stage;
gulong event_id;
gulong capture_id;
guint event_id;
guint capture_id;
guint long_press_id;
gint long_press_threshold;
@ -114,7 +114,7 @@ struct _ClutterClickActionPrivate
gint drag_threshold;
guint press_button;
ClutterInputDevice *press_device;
gint press_device_id;
ClutterEventSequence *press_sequence;
ClutterModifierType modifier_state;
gfloat press_x;
@ -159,8 +159,7 @@ static inline void
click_action_set_pressed (ClutterClickAction *action,
gboolean is_pressed)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
is_pressed = !!is_pressed;
@ -175,8 +174,7 @@ static inline void
click_action_set_held (ClutterClickAction *action,
gboolean is_held)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
is_held = !!is_held;
@ -191,8 +189,7 @@ static gboolean
click_action_emit_long_press (gpointer data)
{
ClutterClickAction *action = data;
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
ClutterActor *actor;
gboolean result;
@ -205,7 +202,11 @@ click_action_emit_long_press (gpointer data)
CLUTTER_LONG_PRESS_ACTIVATE,
&result);
g_clear_signal_handler (&priv->capture_id, priv->stage);
if (priv->capture_id != 0)
{
g_signal_handler_disconnect (priv->stage, priv->capture_id);
priv->capture_id = 0;
}
click_action_set_pressed (action, FALSE);
click_action_set_held (action, FALSE);
@ -216,8 +217,7 @@ click_action_emit_long_press (gpointer data)
static inline void
click_action_query_long_press (ClutterClickAction *action)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
ClutterActor *actor;
gboolean result = FALSE;
gint timeout;
@ -242,7 +242,6 @@ click_action_query_long_press (ClutterClickAction *action)
if (result)
{
g_clear_handle_id (&priv->long_press_id, g_source_remove);
priv->long_press_id =
clutter_threads_add_timeout (timeout,
click_action_emit_long_press,
@ -253,8 +252,7 @@ click_action_query_long_press (ClutterClickAction *action)
static inline void
click_action_cancel_long_press (ClutterClickAction *action)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
if (priv->long_press_id != 0)
{
@ -263,7 +261,8 @@ click_action_cancel_long_press (ClutterClickAction *action)
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
g_clear_handle_id (&priv->long_press_id, g_source_remove);
g_source_remove (priv->long_press_id);
priv->long_press_id = 0;
g_signal_emit (action, click_signals[LONG_PRESS], 0,
actor,
@ -272,30 +271,12 @@ click_action_cancel_long_press (ClutterClickAction *action)
}
}
static inline gboolean
event_within_drag_threshold (ClutterClickAction *click_action,
ClutterEvent *event)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (click_action);
float motion_x, motion_y;
float delta_x, delta_y;
clutter_event_get_coords (event, &motion_x, &motion_y);
delta_x = ABS (motion_x - priv->press_x);
delta_y = ABS (motion_y - priv->press_y);
return delta_x <= priv->drag_threshold && delta_y <= priv->drag_threshold;
}
static gboolean
on_event (ClutterActor *actor,
ClutterEvent *event,
ClutterClickAction *action)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
gboolean has_button = TRUE;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action)))
@ -316,7 +297,7 @@ on_event (ClutterActor *actor,
return CLUTTER_EVENT_PROPAGATE;
priv->press_button = has_button ? clutter_event_get_button (event) : 0;
priv->press_device = clutter_event_get_device (event);
priv->press_device_id = clutter_event_get_device_id (event);
priv->press_sequence = clutter_event_get_event_sequence (event);
priv->modifier_state = clutter_event_get_state (event);
clutter_event_get_coords (event, &priv->press_x, &priv->press_y);
@ -365,8 +346,7 @@ on_captured_event (ClutterActor *stage,
ClutterEvent *event,
ClutterClickAction *action)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
ClutterActor *actor;
ClutterModifierType modifier_state;
gboolean has_button = TRUE;
@ -387,7 +367,7 @@ on_captured_event (ClutterActor *stage,
if ((has_button && clutter_event_get_button (event) != priv->press_button) ||
(has_button && clutter_event_get_click_count (event) != 1) ||
clutter_event_get_device (event) != priv->press_device ||
clutter_event_get_device_id (event) != priv->press_device_id ||
clutter_event_get_event_sequence (event) != priv->press_sequence)
return CLUTTER_EVENT_PROPAGATE;
@ -395,9 +375,17 @@ on_captured_event (ClutterActor *stage,
click_action_cancel_long_press (action);
/* disconnect the capture */
g_clear_signal_handler (&priv->capture_id, priv->stage);
if (priv->capture_id != 0)
{
g_signal_handler_disconnect (priv->stage, priv->capture_id);
priv->capture_id = 0;
}
g_clear_handle_id (&priv->long_press_id, g_source_remove);
if (priv->long_press_id != 0)
{
g_source_remove (priv->long_press_id);
priv->long_press_id = 0;
}
if (!clutter_actor_contains (actor, clutter_event_get_source (event)))
return CLUTTER_EVENT_PROPAGATE;
@ -419,23 +407,30 @@ on_captured_event (ClutterActor *stage,
priv->modifier_state = 0;
click_action_set_pressed (action, FALSE);
if (event_within_drag_threshold (action, event))
g_signal_emit (action, click_signals[CLICKED], 0, actor);
g_signal_emit (action, click_signals[CLICKED], 0, actor);
break;
case CLUTTER_MOTION:
case CLUTTER_TOUCH_UPDATE:
{
if (clutter_event_get_device (event) != priv->press_device ||
gfloat motion_x, motion_y;
gfloat delta_x, delta_y;
if (clutter_event_get_device_id (event) != priv->press_device_id ||
clutter_event_get_event_sequence (event) != priv->press_sequence)
return CLUTTER_EVENT_PROPAGATE;
if (!priv->is_held)
return CLUTTER_EVENT_PROPAGATE;
if (!event_within_drag_threshold (action, event))
clutter_click_action_release (action);
clutter_event_get_coords (event, &motion_x, &motion_y);
delta_x = ABS (motion_x - priv->press_x);
delta_y = ABS (motion_y - priv->press_y);
if (delta_x > priv->drag_threshold ||
delta_y > priv->drag_threshold)
click_action_cancel_long_press (action);
}
break;
@ -451,15 +446,14 @@ clutter_click_action_set_actor (ClutterActorMeta *meta,
ClutterActor *actor)
{
ClutterClickAction *action = CLUTTER_CLICK_ACTION (meta);
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
if (priv->event_id != 0)
{
ClutterActor *old_actor = clutter_actor_meta_get_actor (meta);
if (old_actor != NULL)
g_clear_signal_handler (&priv->event_id, old_actor);
g_signal_handler_disconnect (old_actor, priv->event_id);
priv->event_id = 0;
}
@ -467,13 +461,17 @@ clutter_click_action_set_actor (ClutterActorMeta *meta,
if (priv->capture_id != 0)
{
if (priv->stage != NULL)
g_clear_signal_handler (&priv->capture_id, priv->stage);
g_signal_handler_disconnect (priv->stage, priv->capture_id);
priv->capture_id = 0;
priv->stage = NULL;
}
g_clear_handle_id (&priv->long_press_id, g_source_remove);
if (priv->long_press_id != 0)
{
g_source_remove (priv->long_press_id);
priv->long_press_id = 0;
}
click_action_set_pressed (action, FALSE);
click_action_set_held (action, FALSE);
@ -486,28 +484,13 @@ clutter_click_action_set_actor (ClutterActorMeta *meta,
CLUTTER_ACTOR_META_CLASS (clutter_click_action_parent_class)->set_actor (meta, actor);
}
static void
clutter_click_action_set_enabled (ClutterActorMeta *meta,
gboolean is_enabled)
{
ClutterClickAction *click_action = CLUTTER_CLICK_ACTION (meta);
ClutterActorMetaClass *parent_class =
CLUTTER_ACTOR_META_CLASS (clutter_click_action_parent_class);
if (!is_enabled)
clutter_click_action_release (click_action);
parent_class->set_enabled (meta, is_enabled);
}
static void
clutter_click_action_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (CLUTTER_CLICK_ACTION (gobject));
ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (gobject)->priv;
switch (prop_id)
{
@ -531,8 +514,7 @@ clutter_click_action_get_property (GObject *gobject,
GValue *value,
GParamSpec *pspec)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (CLUTTER_CLICK_ACTION (gobject));
ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (gobject)->priv;
switch (prop_id)
{
@ -561,15 +543,26 @@ clutter_click_action_get_property (GObject *gobject,
static void
clutter_click_action_dispose (GObject *gobject)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (CLUTTER_CLICK_ACTION (gobject));
ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (gobject)->priv;
g_clear_signal_handler (&priv->event_id,
clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gobject)));
if (priv->event_id)
{
g_signal_handler_disconnect (clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gobject)),
priv->event_id);
priv->event_id = 0;
}
g_clear_signal_handler (&priv->capture_id, priv->stage);
if (priv->capture_id)
{
g_signal_handler_disconnect (priv->stage, priv->capture_id);
priv->capture_id = 0;
}
g_clear_handle_id (&priv->long_press_id, g_source_remove);
if (priv->long_press_id)
{
g_source_remove (priv->long_press_id);
priv->long_press_id = 0;
}
G_OBJECT_CLASS (clutter_click_action_parent_class)->dispose (gobject);
}
@ -582,7 +575,6 @@ clutter_click_action_class_init (ClutterClickActionClass *klass)
ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass);
meta_class->set_actor = clutter_click_action_set_actor;
meta_class->set_enabled = clutter_click_action_set_enabled;
gobject_class->dispose = clutter_click_action_dispose;
gobject_class->set_property = clutter_click_action_set_property;
@ -720,11 +712,9 @@ clutter_click_action_class_init (ClutterClickActionClass *klass)
static void
clutter_click_action_init (ClutterClickAction *self)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (self);
priv->long_press_threshold = -1;
priv->long_press_duration = -1;
self->priv = clutter_click_action_get_instance_private (self);
self->priv->long_press_threshold = -1;
self->priv->long_press_duration = -1;
}
/**
@ -764,13 +754,17 @@ clutter_click_action_release (ClutterClickAction *action)
g_return_if_fail (CLUTTER_IS_CLICK_ACTION (action));
priv = clutter_click_action_get_instance_private (action);
priv = action->priv;
if (!priv->is_held)
return;
/* disconnect the capture */
g_clear_signal_handler (&priv->capture_id, priv->stage);
if (priv->capture_id != 0)
{
g_signal_handler_disconnect (priv->stage, priv->capture_id);
priv->capture_id = 0;
}
click_action_cancel_long_press (action);
click_action_set_held (action, FALSE);
@ -790,13 +784,9 @@ clutter_click_action_release (ClutterClickAction *action)
guint
clutter_click_action_get_button (ClutterClickAction *action)
{
ClutterClickActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_CLICK_ACTION (action), 0);
priv = clutter_click_action_get_instance_private (action);
return priv->press_button;
return action->priv->press_button;
}
/**
@ -812,13 +802,9 @@ clutter_click_action_get_button (ClutterClickAction *action)
ClutterModifierType
clutter_click_action_get_state (ClutterClickAction *action)
{
ClutterClickActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_CLICK_ACTION (action), 0);
priv = clutter_click_action_get_instance_private (action);
return priv->modifier_state;
return action->priv->modifier_state;
}
/**
@ -836,15 +822,11 @@ clutter_click_action_get_coords (ClutterClickAction *action,
gfloat *press_x,
gfloat *press_y)
{
ClutterClickActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_ACTION (action));
priv = clutter_click_action_get_instance_private (action);
if (press_x != NULL)
*press_x = priv->press_x;
*press_x = action->priv->press_x;
if (press_y != NULL)
*press_y = priv->press_y;
*press_y = action->priv->press_y;
}

View File

@ -37,13 +37,32 @@
G_BEGIN_DECLS
#define CLUTTER_TYPE_CLICK_ACTION (clutter_click_action_get_type ())
#define CLUTTER_TYPE_CLICK_ACTION (clutter_click_action_get_type ())
#define CLUTTER_CLICK_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_CLICK_ACTION, ClutterClickAction))
#define CLUTTER_IS_CLICK_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_CLICK_ACTION))
#define CLUTTER_CLICK_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_CLICK_ACTION, ClutterClickActionClass))
#define CLUTTER_IS_CLICK_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_CLICK_ACTION))
#define CLUTTER_CLICK_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_CLICK_ACTION, ClutterClickActionClass))
CLUTTER_EXPORT
G_DECLARE_DERIVABLE_TYPE (ClutterClickAction, clutter_click_action,
CLUTTER, CLICK_ACTION, ClutterAction);
typedef struct _ClutterClickAction ClutterClickAction;
typedef struct _ClutterClickActionPrivate ClutterClickActionPrivate;
typedef struct _ClutterClickActionClass ClutterClickActionClass;
typedef struct _ClutterClickActionPrivate ClutterClickActionPrivate;
/**
* ClutterClickAction:
*
* The #ClutterClickAction structure contains
* only private data and should be accessed using the provided API
*
* Since: 1.4
*/
struct _ClutterClickAction
{
/*< private >*/
ClutterAction parent_instance;
ClutterClickActionPrivate *priv;
};
/**
* ClutterClickActionClass:
@ -78,6 +97,9 @@ struct _ClutterClickActionClass
void (* _clutter_click_action7) (void);
};
CLUTTER_EXPORT
GType clutter_click_action_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterAction * clutter_click_action_new (void);

View File

@ -39,6 +39,7 @@
#include "clutter-build-config.h"
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include "clutter-actor-private.h"
#include "clutter-clone.h"
#include "clutter-debug.h"
@ -51,8 +52,6 @@
struct _ClutterClonePrivate
{
ClutterActor *clone_source;
float x_scale, y_scale;
gulong source_destroy_id;
};
@ -120,22 +119,40 @@ clutter_clone_get_preferred_height (ClutterActor *self,
}
static void
clutter_clone_apply_transform (ClutterActor *self,
graphene_matrix_t *matrix)
clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix)
{
ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
ClutterActorBox box, source_box;
gfloat x_scale, y_scale;
if (priv->clone_source)
graphene_matrix_scale (matrix, priv->x_scale, priv->y_scale, 1.f);
/* First chain up and apply all the standard ClutterActor
* transformations... */
CLUTTER_ACTOR_CLASS (clutter_clone_parent_class)->apply_transform (self,
matrix);
/* if we don't have a source, nothing else to do */
if (priv->clone_source == NULL)
return;
/* get our allocated size */
clutter_actor_get_allocation_box (self, &box);
/* and get the allocated size of the source */
clutter_actor_get_allocation_box (priv->clone_source, &source_box);
/* We need to scale what the clone-source actor paints to fill our own
* allocation...
*/
x_scale = clutter_actor_box_get_width (&box)
/ clutter_actor_box_get_width (&source_box);
y_scale = clutter_actor_box_get_height (&box)
/ clutter_actor_box_get_height (&source_box);
cogl_matrix_scale (matrix, x_scale, y_scale, x_scale);
}
static void
clutter_clone_paint (ClutterActor *actor,
ClutterPaintContext *paint_context)
clutter_clone_paint (ClutterActor *actor)
{
ClutterClone *self = CLUTTER_CLONE (actor);
ClutterClonePrivate *priv = self->priv;
@ -172,7 +189,7 @@ clutter_clone_paint (ClutterActor *actor,
if (clutter_actor_is_realized (priv->clone_source))
{
_clutter_actor_push_clone_paint ();
clutter_actor_paint (priv->clone_source, paint_context);
clutter_actor_paint (priv->clone_source);
_clutter_actor_pop_clone_paint ();
}
@ -195,7 +212,7 @@ clutter_clone_get_paint_volume (ClutterActor *actor,
if (priv->clone_source == NULL)
return TRUE;
/* query the volume of the source actor and simply masquerade it as
/* query the volume of the source actor and simply masquarade it as
* the clones volume... */
source_volume = clutter_actor_get_paint_volume (priv->clone_source);
if (source_volume == NULL)
@ -222,16 +239,15 @@ clutter_clone_has_overlaps (ClutterActor *actor)
static void
clutter_clone_allocate (ClutterActor *self,
const ClutterActorBox *box)
const ClutterActorBox *box,
ClutterAllocationFlags flags)
{
ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
ClutterActorClass *parent_class;
ClutterActorBox source_box;
float x_scale, y_scale;
/* chain up */
parent_class = CLUTTER_ACTOR_CLASS (clutter_clone_parent_class);
parent_class->allocate (self, box);
parent_class->allocate (self, box, flags);
if (priv->clone_source == NULL)
return;
@ -241,31 +257,7 @@ clutter_clone_allocate (ClutterActor *self,
*/
if (clutter_actor_get_parent (priv->clone_source) != NULL &&
!clutter_actor_has_allocation (priv->clone_source))
{
float x = 0.f;
float y = 0.f;
clutter_actor_get_fixed_position (priv->clone_source, &x, &y);
clutter_actor_allocate_preferred_size (priv->clone_source, x, y);
}
clutter_actor_get_allocation_box (priv->clone_source, &source_box);
/* We need to scale what the clone-source actor paints to fill our own
* allocation...
*/
x_scale = clutter_actor_box_get_width (box)
/ clutter_actor_box_get_width (&source_box);
y_scale = clutter_actor_box_get_height (box)
/ clutter_actor_box_get_height (&source_box);
if (!G_APPROX_VALUE (priv->x_scale, x_scale, FLT_EPSILON) ||
!G_APPROX_VALUE (priv->y_scale, y_scale, FLT_EPSILON))
{
priv->x_scale = x_scale;
priv->y_scale = y_scale;
clutter_actor_invalidate_transform (CLUTTER_ACTOR (self));
}
clutter_actor_allocate_preferred_size (priv->clone_source, flags);
#if 0
/* XXX - this is wrong: ClutterClone cannot clone unparented
@ -280,7 +272,7 @@ clutter_clone_allocate (ClutterActor *self,
* paint cycle, we can safely give it as much size as it requires
*/
if (clutter_actor_get_parent (priv->clone_source) == NULL)
clutter_actor_allocate_preferred_size (priv->clone_source);
clutter_actor_allocate_preferred_size (priv->clone_source, flags);
#endif
}
@ -372,9 +364,6 @@ static void
clutter_clone_init (ClutterClone *self)
{
self->priv = clutter_clone_get_instance_private (self);
self->priv->x_scale = 1.f;
self->priv->y_scale = 1.f;
}
/**
@ -411,7 +400,8 @@ clutter_clone_set_source_internal (ClutterClone *self,
if (priv->clone_source != NULL)
{
g_clear_signal_handler (&priv->source_destroy_id, priv->clone_source);
g_signal_handler_disconnect (priv->clone_source, priv->source_destroy_id);
priv->source_destroy_id = 0;
_clutter_actor_detach_clone (priv->clone_source, CLUTTER_ACTOR (self));
g_object_unref (priv->clone_source);
priv->clone_source = NULL;

View File

@ -611,7 +611,7 @@ parse_hsla (ClutterColor *color,
/**
* clutter_color_from_string:
* @color: (out caller-allocates): return location for a #ClutterColor
* @str: a string specifying a color
* @str: a string specifiying a color
*
* Parses a string definition of a color, filling the #ClutterColor.red,
* #ClutterColor.green, #ClutterColor.blue and #ClutterColor.alpha fields
@ -911,7 +911,7 @@ ClutterColor *
clutter_color_copy (const ClutterColor *color)
{
if (G_LIKELY (color != NULL))
return g_memdup2 (color, sizeof (ClutterColor));
return g_slice_dup (ClutterColor, color);
return NULL;
}
@ -928,7 +928,7 @@ void
clutter_color_free (ClutterColor *color)
{
if (G_LIKELY (color != NULL))
g_free (color);
g_slice_free (ClutterColor, color);
}
/**
@ -977,7 +977,7 @@ clutter_color_new (guint8 red,
ClutterColor *
clutter_color_alloc (void)
{
return g_new0 (ClutterColor, 1);
return g_slice_new0 (ClutterColor);
}
/**

View File

@ -39,6 +39,8 @@
#include "clutter-build-config.h"
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include "clutter-colorize-effect.h"
#include "cogl/cogl.h"
@ -57,6 +59,9 @@ struct _ClutterColorizeEffect
gint tint_uniform;
gint tex_width;
gint tex_height;
CoglPipeline *pipeline;
};
@ -99,24 +104,15 @@ G_DEFINE_TYPE (ClutterColorizeEffect,
clutter_colorize_effect,
CLUTTER_TYPE_OFFSCREEN_EFFECT);
static CoglPipeline *
clutter_colorize_effect_create_pipeline (ClutterOffscreenEffect *effect,
CoglTexture *texture)
{
ClutterColorizeEffect *colorize_effect = CLUTTER_COLORIZE_EFFECT (effect);
cogl_pipeline_set_layer_texture (colorize_effect->pipeline, 0, texture);
return cogl_object_ref (colorize_effect->pipeline);
}
static gboolean
clutter_colorize_effect_pre_paint (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
clutter_colorize_effect_pre_paint (ClutterEffect *effect)
{
ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect);
ClutterEffectClass *parent_class;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
return FALSE;
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
{
/* if we don't have support for GLSL shaders then we
@ -130,7 +126,45 @@ clutter_colorize_effect_pre_paint (ClutterEffect *effect,
}
parent_class = CLUTTER_EFFECT_CLASS (clutter_colorize_effect_parent_class);
return parent_class->pre_paint (effect, node, paint_context);
if (parent_class->pre_paint (effect))
{
ClutterOffscreenEffect *offscreen_effect =
CLUTTER_OFFSCREEN_EFFECT (effect);
CoglHandle texture;
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
self->tex_width = cogl_texture_get_width (texture);
self->tex_height = cogl_texture_get_height (texture);
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
return TRUE;
}
else
return FALSE;
}
static void
clutter_colorize_effect_paint_target (ClutterOffscreenEffect *effect)
{
ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect);
CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
ClutterActor *actor;
guint8 paint_opacity;
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
paint_opacity = clutter_actor_get_paint_opacity (actor);
cogl_pipeline_set_color4ub (self->pipeline,
paint_opacity,
paint_opacity,
paint_opacity,
paint_opacity);
cogl_framebuffer_draw_rectangle (framebuffer,
self->pipeline,
0, 0,
self->tex_width, self->tex_height);
}
static void
@ -196,7 +230,7 @@ clutter_colorize_effect_class_init (ClutterColorizeEffectClass *klass)
ClutterOffscreenEffectClass *offscreen_class;
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
offscreen_class->create_pipeline = clutter_colorize_effect_create_pipeline;
offscreen_class->paint_target = clutter_colorize_effect_paint_target;
effect_class->pre_paint = clutter_colorize_effect_pre_paint;

View File

@ -0,0 +1,16 @@
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#ifndef __CLUTTER_CONFIG_H__
#define __CLUTTER_CONFIG_H__
#include <glib.h>
G_BEGIN_DECLS
@CLUTTER_CONFIG_DEFINES@
G_END_DECLS
#endif /* __CLUTTER_CONFIG_H__ */

View File

@ -30,6 +30,13 @@ gboolean clutter_constraint_update_allocation (ClutterConstraint *constraint,
ClutterActor *actor,
ClutterActorBox *allocation);
void clutter_constraint_update_preferred_size (ClutterConstraint *constraint,
ClutterActor *actor,
ClutterOrientation direction,
float for_size,
float *minimum_size,
float *natural_size);
G_END_DECLS
#endif /* __CLUTTER_CONSTRAINT_PRIVATE_H__ */

View File

@ -48,7 +48,7 @@
* Constraints provide a way to build user interfaces by using
* relations between #ClutterActors, without explicit fixed
* positioning and sizing, similarly to how fluid layout managers like
* #ClutterBoxLayout lay out their children.
* #ClutterBoxLayout and #ClutterTableLayout lay out their children.
*
* Constraints are attached to a #ClutterActor, and are available
* for inspection using clutter_actor_get_constraints().
@ -160,26 +160,28 @@ constraint_update_preferred_size (ClutterConstraint *constraint,
}
static void
clutter_constraint_set_enabled (ClutterActorMeta *meta,
gboolean is_enabled)
clutter_constraint_notify (GObject *gobject,
GParamSpec *pspec)
{
ClutterActorMetaClass *parent_class =
CLUTTER_ACTOR_META_CLASS (clutter_constraint_parent_class);
ClutterActor *actor;
if (strcmp (pspec->name, "enabled") == 0)
{
ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject);
ClutterActor *actor = clutter_actor_meta_get_actor (meta);
actor = clutter_actor_meta_get_actor (meta);
if (actor)
clutter_actor_queue_relayout (actor);
if (actor != NULL)
clutter_actor_queue_relayout (actor);
}
parent_class->set_enabled (meta, is_enabled);
if (G_OBJECT_CLASS (clutter_constraint_parent_class)->notify != NULL)
G_OBJECT_CLASS (clutter_constraint_parent_class)->notify (gobject, pspec);
}
static void
clutter_constraint_class_init (ClutterConstraintClass *klass)
{
ClutterActorMetaClass *actor_meta_class = CLUTTER_ACTOR_META_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
actor_meta_class->set_enabled = clutter_constraint_set_enabled;
gobject_class->notify = clutter_constraint_notify;
klass->update_allocation = constraint_update_allocation;
klass->update_preferred_size = constraint_update_preferred_size;
@ -220,17 +222,6 @@ clutter_constraint_update_allocation (ClutterConstraint *constraint,
return !clutter_actor_box_equal (allocation, &old_alloc);
}
/**
* clutter_constraint_update_preferred_size:
* @constraint: a #ClutterConstraint
* @actor: a #ClutterActor
* @direction: a #ClutterOrientation
* @for_size: the size in the opposite direction
* @minimum_size: (inout): the minimum size to modify
* @natural_size: (inout): the natural size to modify
*
* Asks the @constraint to update the size request of a #ClutterActor.
*/
void
clutter_constraint_update_preferred_size (ClutterConstraint *constraint,
ClutterActor *actor,

View File

@ -99,14 +99,6 @@ struct _ClutterConstraintClass
CLUTTER_EXPORT
GType clutter_constraint_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
void clutter_constraint_update_preferred_size (ClutterConstraint *constraint,
ClutterActor *actor,
ClutterOrientation direction,
float for_size,
float *minimum_size,
float *natural_size);
/* ClutterActor API */
CLUTTER_EXPORT
void clutter_actor_add_constraint (ClutterActor *self,

View File

@ -37,7 +37,6 @@
#include "clutter-actor-private.h"
#include "clutter-child-meta.h"
#include "clutter-container-private.h"
#include "clutter-debug.h"
#include "clutter-main.h"
#include "clutter-marshal.h"
@ -119,6 +118,37 @@ container_real_remove (ClutterContainer *container,
clutter_actor_remove_child (CLUTTER_ACTOR (container), actor);
}
typedef struct {
ClutterCallback callback;
gpointer data;
} ForeachClosure;
static gboolean
foreach_cb (ClutterActor *actor,
gpointer data)
{
ForeachClosure *clos = data;
clos->callback (actor, clos->data);
return TRUE;
}
static void
container_real_foreach (ClutterContainer *container,
ClutterCallback callback,
gpointer user_data)
{
ForeachClosure clos;
clos.callback = callback;
clos.data = user_data;
_clutter_actor_foreach_child (CLUTTER_ACTOR (container),
foreach_cb,
&clos);
}
static void
container_real_raise (ClutterContainer *container,
ClutterActor *child,
@ -213,6 +243,7 @@ clutter_container_default_init (ClutterContainerInterface *iface)
iface->add = container_real_add;
iface->remove = container_real_remove;
iface->foreach = container_real_foreach;
iface->raise = container_real_raise;
iface->lower = container_real_lower;
iface->sort_depth_order = container_real_sort_depth_order;
@ -385,6 +416,33 @@ clutter_container_add_actor (ClutterContainer *container,
container_add_actor (container, actor);
}
/**
* clutter_container_add_valist: (skip)
* @container: a #ClutterContainer
* @first_actor: the first #ClutterActor to add
* @var_args: list of actors to add, followed by %NULL
*
* Alternative va_list version of clutter_container_add().
*
* This function will call #ClutterContainerIface.add(), which is a
* deprecated virtual function. The default implementation will
* call clutter_actor_add_child().
*
* Since: 0.4
*
* Deprecated: 1.10: Use clutter_actor_add_child() instead.
*/
void
clutter_container_add_valist (ClutterContainer *container,
ClutterActor *first_actor,
va_list var_args)
{
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
g_return_if_fail (CLUTTER_IS_ACTOR (first_actor));
container_add_valist (container, first_actor, var_args);
}
/**
* clutter_container_remove: (skip)
* @container: a #ClutterContainer
@ -448,6 +506,42 @@ clutter_container_remove_actor (ClutterContainer *container,
container_remove_actor (container, actor);
}
/**
* clutter_container_remove_valist: (skip)
* @container: a #ClutterContainer
* @first_actor: the first #ClutterActor to add
* @var_args: list of actors to remove, followed by %NULL
*
* Alternative va_list version of clutter_container_remove().
*
* This function will call #ClutterContainerIface.remove(), which is a
* deprecated virtual function. The default implementation will call
* clutter_actor_remove_child().
*
* Since: 0.4
*
* Deprecated: 1.10: Use clutter_actor_remove_child() instead.
*/
void
clutter_container_remove_valist (ClutterContainer *container,
ClutterActor *first_actor,
va_list var_args)
{
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
g_return_if_fail (CLUTTER_IS_ACTOR (first_actor));
container_remove_valist (container, first_actor, var_args);
}
static void
get_children_cb (ClutterActor *child,
gpointer data)
{
GList **children = data;
*children = g_list_prepend (*children, child);
}
/**
* clutter_container_get_children:
* @container: a #ClutterContainer
@ -465,9 +559,108 @@ clutter_container_remove_actor (ClutterContainer *container,
GList *
clutter_container_get_children (ClutterContainer *container)
{
GList *retval;
g_return_val_if_fail (CLUTTER_IS_CONTAINER (container), NULL);
return clutter_actor_get_children (CLUTTER_ACTOR (container));
retval = NULL;
clutter_container_foreach (container, get_children_cb, &retval);
return g_list_reverse (retval);
}
/**
* clutter_container_foreach:
* @container: a #ClutterContainer
* @callback: (scope call): a function to be called for each child
* @user_data: data to be passed to the function, or %NULL
*
* Calls @callback for each child of @container that was added
* by the application (with clutter_container_add_actor()). Does
* not iterate over "internal" children that are part of the
* container's own implementation, if any.
*
* This function calls the #ClutterContainerIface.foreach()
* virtual function, which has been deprecated.
*
* Since: 0.4
*
* Deprecated: 1.10: Use clutter_actor_get_first_child() or
* clutter_actor_get_last_child() to retrieve the beginning of
* the list of children, and clutter_actor_get_next_sibling()
* and clutter_actor_get_previous_sibling() to iterate over it;
* alternatively, use the #ClutterActorIter API.
*/
void
clutter_container_foreach (ClutterContainer *container,
ClutterCallback callback,
gpointer user_data)
{
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
g_return_if_fail (callback != NULL);
#ifdef CLUTTER_ENABLE_DEBUG
if (G_UNLIKELY (_clutter_diagnostic_enabled ()))
{
ClutterContainerIface *iface = CLUTTER_CONTAINER_GET_IFACE (container);
if (iface->foreach != container_real_foreach)
_clutter_diagnostic_message ("The ClutterContainer::foreach() "
"virtual function has been deprecated "
"and it should not be overridden by "
"newly written code");
}
#endif /* CLUTTER_ENABLE_DEBUG */
CLUTTER_CONTAINER_GET_IFACE (container)->foreach (container,
callback,
user_data);
}
/**
* clutter_container_foreach_with_internals:
* @container: a #ClutterContainer
* @callback: (scope call): a function to be called for each child
* @user_data: data to be passed to the function, or %NULL
*
* Calls @callback for each child of @container, including "internal"
* children built in to the container itself that were never added
* by the application.
*
* This function calls the #ClutterContainerIface.foreach_with_internals()
* virtual function, which has been deprecated.
*
* Since: 1.0
*
* Deprecated: 1.10: See clutter_container_foreach().
*/
void
clutter_container_foreach_with_internals (ClutterContainer *container,
ClutterCallback callback,
gpointer user_data)
{
ClutterContainerIface *iface;
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
g_return_if_fail (callback != NULL);
iface = CLUTTER_CONTAINER_GET_IFACE (container);
#ifdef CLUTTER_ENABLE_DEBUG
if (G_UNLIKELY (_clutter_diagnostic_enabled ()))
{
if (iface->foreach_with_internals != NULL)
_clutter_diagnostic_message ("The ClutterContainer::foreach_with_internals() "
"virtual function has been deprecated "
"and it should not be overridden by "
"newly written code");
}
#endif /* CLUTTER_ENABLE_DEBUG */
if (iface->foreach_with_internals != NULL)
iface->foreach_with_internals (container, callback, user_data);
else
iface->foreach (container, callback, user_data);
}
/**
@ -1251,23 +1444,3 @@ clutter_container_child_notify (ClutterContainer *container,
child,
pspec);
}
void
_clutter_container_emit_actor_added (ClutterContainer *container,
ClutterActor *actor)
{
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
g_signal_emit (container, container_signals[ACTOR_ADDED], 0, actor);
}
void
_clutter_container_emit_actor_removed (ClutterContainer *container,
ClutterActor *actor)
{
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
g_signal_emit (container, container_signals[ACTOR_REMOVED], 0, actor);
}

View File

@ -59,6 +59,14 @@ typedef struct _ClutterContainerIface ClutterContainerIface;
* function is deprecated, and it should not be overridden.
* @remove: virtual function for removing an actor from the container. This
* virtual function is deprecated, and it should not be overridden.
* @foreach: virtual function for iterating over the container's children.
* This virtual function is deprecated, and it should not be overridden.
* @foreach_with_internals: virtual functions for iterating over the
* container's children, both added using the #ClutterContainer API
* and internal children. The implementation of this virtual function
* is required only if the #ClutterContainer implementation has
* internal children. This virtual function is deprecated, and it should
* not be overridden.
* @raise: virtual function for raising a child. This virtual function is
* deprecated and it should not be overridden.
* @lower: virtual function for lowering a child. This virtual function is
@ -74,13 +82,13 @@ typedef struct _ClutterContainerIface ClutterContainerIface;
* fields in the instance and add the record to a data structure for
* subsequent access for #ClutterContainerIface::get_child_meta
* @destroy_child_meta: virtual function that gets called when a child is
* removed; it should release all resources held by the record
* removed; it shuld release all resources held by the record
* @get_child_meta: return the record for a container child
* @actor_added: class handler for #ClutterContainer::actor-added
* @actor_removed: class handler for #ClutterContainer::actor-removed
* @child_notify: class handler for #ClutterContainer::child-notify
*
* Base interface for container actors. The @add and @remove
* Base interface for container actors. The @add, @remove and @foreach
* virtual functions must be provided by any implementation; the other
* virtual functions are optional.
*
@ -96,6 +104,13 @@ struct _ClutterContainerIface
ClutterActor *actor);
void (* remove) (ClutterContainer *container,
ClutterActor *actor);
void (* foreach) (ClutterContainer *container,
ClutterCallback callback,
gpointer user_data);
void (* foreach_with_internals) (ClutterContainer *container,
ClutterCallback callback,
gpointer user_data);
/* child stacking */
void (* raise) (ClutterContainer *container,

View File

@ -34,10 +34,9 @@ void _clutter_content_attached (ClutterContent *conte
void _clutter_content_detached (ClutterContent *content,
ClutterActor *actor);
void _clutter_content_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *node,
ClutterPaintContext *paint_context);
void _clutter_content_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *node);
G_END_DECLS

View File

@ -96,10 +96,9 @@ clutter_content_real_invalidate_size (ClutterContent *content)
}
static void
clutter_content_real_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *context,
ClutterPaintContext *paint_context)
clutter_content_real_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *context)
{
}
@ -301,8 +300,7 @@ _clutter_content_detached (ClutterContent *content,
* _clutter_content_paint_content:
* @content: a #ClutterContent
* @actor: a #ClutterActor
* @node: a #ClutterPaintNode
* @paint_context: a #ClutterPaintContext
* @context: a #ClutterPaintNode
*
* Creates the render tree for the @content and @actor.
*
@ -310,13 +308,11 @@ _clutter_content_detached (ClutterContent *content,
* virtual function.
*/
void
_clutter_content_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
_clutter_content_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *node)
{
CLUTTER_CONTENT_GET_IFACE (content)->paint_content (content, actor, node,
paint_context);
CLUTTER_CONTENT_GET_IFACE (content)->paint_content (content, actor, node);
}
/**

View File

@ -65,10 +65,9 @@ struct _ClutterContentInterface
gboolean (* get_preferred_size) (ClutterContent *content,
gfloat *width,
gfloat *height);
void (* paint_content) (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *node,
ClutterPaintContext *paint_context);
void (* paint_content) (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *node);
void (* attached) (ClutterContent *content,
ClutterActor *actor);

View File

@ -1,92 +0,0 @@
/*
* Copyright (C) 2007,2008,2009,2010,2011 Intel Corporation.
* Copyright (C) 2020 Red Hat Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "clutter-build-config.h"
#include "clutter-damage-history.h"
#define DAMAGE_HISTORY_LENGTH 0x10
struct _ClutterDamageHistory
{
cairo_region_t *damages[DAMAGE_HISTORY_LENGTH];
int index;
};
ClutterDamageHistory *
clutter_damage_history_new (void)
{
ClutterDamageHistory *history;
history = g_new0 (ClutterDamageHistory, 1);
return history;
}
void
clutter_damage_history_free (ClutterDamageHistory *history)
{
int i;
for (i = 0; i < G_N_ELEMENTS (history->damages); i++)
g_clear_pointer (&history->damages[i], cairo_region_destroy);
g_free (history);
}
gboolean
clutter_damage_history_is_age_valid (ClutterDamageHistory *history,
int age)
{
if (age >= DAMAGE_HISTORY_LENGTH ||
age < 1)
return FALSE;
if (!clutter_damage_history_lookup (history, age))
return FALSE;
return TRUE;
}
void
clutter_damage_history_record (ClutterDamageHistory *history,
const cairo_region_t *damage)
{
g_clear_pointer (&history->damages[history->index], cairo_region_destroy);
history->damages[history->index] = cairo_region_copy (damage);
}
static inline int
step_damage_index (int current,
int diff)
{
return (current + diff) & (DAMAGE_HISTORY_LENGTH - 1);
}
void
clutter_damage_history_step (ClutterDamageHistory *history)
{
history->index = step_damage_index (history->index, 1);
}
const cairo_region_t *
clutter_damage_history_lookup (ClutterDamageHistory *history,
int age)
{
return history->damages[step_damage_index (history->index, -age)];
}

View File

@ -1,50 +0,0 @@
/*
* Copyright (C) 2007,2008,2009,2010,2011 Intel Corporation.
* Copyright (C) 2020 Red Hat Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CLUTTER_DAMAGE_HISTORY_H
#define CLUTTER_DAMAGE_HISTORY_H
#include <cairo.h>
#include <glib.h>
#include "clutter-macros.h"
typedef struct _ClutterDamageHistory ClutterDamageHistory;
CLUTTER_EXPORT
ClutterDamageHistory * clutter_damage_history_new (void);
CLUTTER_EXPORT
void clutter_damage_history_free (ClutterDamageHistory *history);
CLUTTER_EXPORT
gboolean clutter_damage_history_is_age_valid (ClutterDamageHistory *history,
int age);
CLUTTER_EXPORT
void clutter_damage_history_record (ClutterDamageHistory *history,
const cairo_region_t *damage);
CLUTTER_EXPORT
void clutter_damage_history_step (ClutterDamageHistory *history);
CLUTTER_EXPORT
const cairo_region_t * clutter_damage_history_lookup (ClutterDamageHistory *history,
int age);
#endif /* CLUTTER_DAMAGE_HISTORY_H */

View File

@ -6,6 +6,45 @@
G_BEGIN_DECLS
typedef enum
{
CLUTTER_DEBUG_MISC = 1 << 0,
CLUTTER_DEBUG_ACTOR = 1 << 1,
CLUTTER_DEBUG_TEXTURE = 1 << 2,
CLUTTER_DEBUG_EVENT = 1 << 3,
CLUTTER_DEBUG_PAINT = 1 << 4,
CLUTTER_DEBUG_PANGO = 1 << 5,
CLUTTER_DEBUG_BACKEND = 1 << 6,
CLUTTER_DEBUG_SCHEDULER = 1 << 7,
CLUTTER_DEBUG_SCRIPT = 1 << 8,
CLUTTER_DEBUG_SHADER = 1 << 9,
CLUTTER_DEBUG_MULTISTAGE = 1 << 10,
CLUTTER_DEBUG_ANIMATION = 1 << 11,
CLUTTER_DEBUG_LAYOUT = 1 << 12,
CLUTTER_DEBUG_PICK = 1 << 13,
CLUTTER_DEBUG_EVENTLOOP = 1 << 14,
CLUTTER_DEBUG_CLIPPING = 1 << 15,
CLUTTER_DEBUG_OOB_TRANSFORMS = 1 << 16
} ClutterDebugFlag;
typedef enum
{
CLUTTER_DEBUG_NOP_PICKING = 1 << 0,
} ClutterPickDebugFlag;
typedef enum
{
CLUTTER_DEBUG_DISABLE_SWAP_EVENTS = 1 << 0,
CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS = 1 << 1,
CLUTTER_DEBUG_REDRAWS = 1 << 2,
CLUTTER_DEBUG_PAINT_VOLUMES = 1 << 3,
CLUTTER_DEBUG_DISABLE_CULLING = 1 << 4,
CLUTTER_DEBUG_DISABLE_OFFSCREEN_REDIRECT = 1 << 5,
CLUTTER_DEBUG_CONTINUOUS_REDRAW = 1 << 6,
CLUTTER_DEBUG_PAINT_DEFORM_TILES = 1 << 7,
CLUTTER_DEBUG_PAINT_DAMAGE_REGION = 1 << 8,
} ClutterDrawDebugFlag;
#ifdef CLUTTER_ENABLE_DEBUG
#define CLUTTER_HAS_DEBUG(type) ((clutter_debug_flags & CLUTTER_DEBUG_##type) != FALSE)
@ -41,7 +80,6 @@ G_BEGIN_DECLS
extern guint clutter_debug_flags;
extern guint clutter_pick_debug_flags;
extern guint clutter_paint_debug_flags;
extern int clutter_max_render_time_constant_us;
void _clutter_debug_messagev (const char *format,
va_list var_args) G_GNUC_PRINTF (1, 0);

View File

@ -53,16 +53,14 @@
#include "clutter-build-config.h"
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include "clutter-deform-effect.h"
#include <cogl/cogl.h>
#include "clutter-color.h"
#include "clutter-debug.h"
#include "clutter-enum-types.h"
#include "clutter-offscreen-effect-private.h"
#include "clutter-paint-node.h"
#include "clutter-paint-nodes.h"
#include "clutter-private.h"
#define DEFAULT_N_TILES 32
@ -130,9 +128,10 @@ clutter_deform_effect_deform_vertex (ClutterDeformEffect *effect,
}
static void
vbo_invalidate (ClutterActor *actor,
GParamSpec *pspec,
ClutterDeformEffect *effect)
vbo_invalidate (ClutterActor *actor,
const ClutterActorBox *allocation,
ClutterAllocationFlags flags,
ClutterDeformEffect *effect)
{
effect->priv->is_dirty = TRUE;
}
@ -148,7 +147,7 @@ clutter_deform_effect_set_actor (ClutterActorMeta *meta,
ClutterActor *old_actor = clutter_actor_meta_get_actor (meta);
if (old_actor != NULL)
g_clear_signal_handler (&priv->allocation_id, old_actor);
g_signal_handler_disconnect (old_actor, priv->allocation_id);
priv->allocation_id = 0;
}
@ -157,7 +156,7 @@ clutter_deform_effect_set_actor (ClutterActorMeta *meta,
* changes
*/
if (actor != NULL)
priv->allocation_id = g_signal_connect (actor, "notify::allocation",
priv->allocation_id = g_signal_connect (actor, "allocation-changed",
G_CALLBACK (vbo_invalidate),
meta);
@ -167,17 +166,18 @@ clutter_deform_effect_set_actor (ClutterActorMeta *meta,
}
static void
clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect)
{
ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect);
ClutterDeformEffectPrivate *priv = self->priv;
CoglHandle material;
CoglPipeline *pipeline;
CoglDepthState depth_state;
CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
if (priv->is_dirty)
{
ClutterRect rect;
gboolean mapped_buffer;
CoglVertexP3T2C4 *verts;
ClutterActor *actor;
@ -191,7 +191,12 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
/* if we don't have a target size, fall back to the actor's
* allocation, though wrong it might be
*/
if (!clutter_offscreen_effect_get_target_size (effect, &width, &height))
if (clutter_offscreen_effect_get_target_rect (effect, &rect))
{
width = clutter_rect_get_width (&rect);
height = clutter_rect_get_height (&rect);
}
else
clutter_actor_get_size (actor, &width, &height);
/* XXX ideally, the sub-classes should tell us what they
@ -271,7 +276,8 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
priv->is_dirty = FALSE;
}
pipeline = clutter_offscreen_effect_get_pipeline (effect);
material = clutter_offscreen_effect_get_target (effect);
pipeline = COGL_PIPELINE (material);
/* enable depth testing */
cogl_depth_state_init (&depth_state);
@ -285,22 +291,12 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
COGL_PIPELINE_CULL_FACE_MODE_BACK);
/* draw the front */
if (pipeline != NULL)
{
ClutterPaintNode *front_node;
front_node = clutter_pipeline_node_new (pipeline);
clutter_paint_node_set_static_name (front_node,
"ClutterDeformEffect (front)");
clutter_paint_node_add_child (node, front_node);
clutter_paint_node_add_primitive (front_node, priv->primitive);
clutter_paint_node_unref (front_node);
}
if (material != NULL)
cogl_framebuffer_draw_primitive (fb, pipeline, priv->primitive);
/* draw the back */
if (priv->back_pipeline != NULL)
{
ClutterPaintNode *back_node;
CoglPipeline *back_pipeline;
/* We probably shouldn't be modifying the user's material so
@ -310,30 +306,20 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
cogl_pipeline_set_cull_face_mode (back_pipeline,
COGL_PIPELINE_CULL_FACE_MODE_FRONT);
cogl_framebuffer_draw_primitive (fb, back_pipeline, priv->primitive);
back_node = clutter_pipeline_node_new (back_pipeline);
clutter_paint_node_set_static_name (back_node,
"ClutterDeformEffect (back)");
clutter_paint_node_add_child (node, back_node);
clutter_paint_node_add_primitive (back_node, priv->primitive);
clutter_paint_node_unref (back_node);
cogl_object_unref (back_pipeline);
}
if (G_UNLIKELY (priv->lines_primitive != NULL))
{
const ClutterColor *red;
ClutterPaintNode *lines_node;
red = clutter_color_get_static (CLUTTER_COLOR_RED);
lines_node = clutter_color_node_new (red);
clutter_paint_node_set_static_name (lines_node,
"ClutterDeformEffect (lines)");
clutter_paint_node_add_child (node, lines_node);
clutter_paint_node_add_primitive (lines_node, priv->lines_primitive);
clutter_paint_node_unref (lines_node);
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
CoglPipeline *lines_pipeline = cogl_pipeline_new (ctx);
cogl_pipeline_set_color4f (lines_pipeline, 1.0, 0, 0, 1.0);
cogl_framebuffer_draw_primitive (fb, lines_pipeline,
priv->lines_primitive);
cogl_object_unref (lines_pipeline);
}
}

View File

@ -3,7 +3,27 @@
#define __CLUTTER_DEPRECATED_H_INSIDE__
#include "deprecated/clutter-actor.h"
#include "deprecated/clutter-alpha.h"
#include "deprecated/clutter-animatable.h"
#include "deprecated/clutter-animation.h"
#include "deprecated/clutter-behaviour.h"
#include "deprecated/clutter-behaviour-depth.h"
#include "deprecated/clutter-behaviour-opacity.h"
#include "deprecated/clutter-behaviour-scale.h"
#include "deprecated/clutter-bin-layout.h"
#include "deprecated/clutter-box.h"
#include "deprecated/clutter-cairo-texture.h"
#include "deprecated/clutter-container.h"
#include "deprecated/clutter-group.h"
#include "deprecated/clutter-keysyms.h"
#include "deprecated/clutter-rectangle.h"
#include "deprecated/clutter-stage-manager.h"
#include "deprecated/clutter-stage.h"
#include "deprecated/clutter-state.h"
#include "deprecated/clutter-table-layout.h"
#include "deprecated/clutter-texture.h"
#include "deprecated/clutter-timeline.h"
#undef __CLUTTER_DEPRECATED_H_INSIDE__

View File

@ -28,7 +28,7 @@
* @see_also: #ClutterEffect, #ClutterOffscreenEffect
*
* #ClutterDesaturateEffect is a sub-class of #ClutterEffect that
* desaturates the color of an actor and its contents. The strength
* desaturates the color of an actor and its contents. The strenght
* of the desaturation effect is controllable and animatable through
* the #ClutterDesaturateEffect:factor property.
*
@ -41,6 +41,8 @@
#include "clutter-build-config.h"
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include <math.h>
#include "clutter-desaturate-effect.h"
@ -109,25 +111,15 @@ G_DEFINE_TYPE (ClutterDesaturateEffect,
clutter_desaturate_effect,
CLUTTER_TYPE_OFFSCREEN_EFFECT);
static CoglPipeline *
clutter_desaturate_effect_create_pipeline (ClutterOffscreenEffect *effect,
CoglTexture *texture)
{
ClutterDesaturateEffect *desaturate_effect =
CLUTTER_DESATURATE_EFFECT (effect);
cogl_pipeline_set_layer_texture (desaturate_effect->pipeline, 0, texture);
return cogl_object_ref (desaturate_effect->pipeline);
}
static gboolean
clutter_desaturate_effect_pre_paint (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
clutter_desaturate_effect_pre_paint (ClutterEffect *effect)
{
ClutterDesaturateEffect *self = CLUTTER_DESATURATE_EFFECT (effect);
ClutterEffectClass *parent_class;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
return FALSE;
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
{
/* if we don't have support for GLSL shaders then we
@ -141,7 +133,50 @@ clutter_desaturate_effect_pre_paint (ClutterEffect *effect,
}
parent_class = CLUTTER_EFFECT_CLASS (clutter_desaturate_effect_parent_class);
return parent_class->pre_paint (effect, node, paint_context);
if (parent_class->pre_paint (effect))
{
ClutterOffscreenEffect *offscreen_effect =
CLUTTER_OFFSCREEN_EFFECT (effect);
CoglHandle texture;
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
self->tex_width = cogl_texture_get_width (texture);
self->tex_height = cogl_texture_get_height (texture);
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
return TRUE;
}
else
return FALSE;
}
static void
clutter_desaturate_effect_paint_target (ClutterOffscreenEffect *effect)
{
ClutterDesaturateEffect *self = CLUTTER_DESATURATE_EFFECT (effect);
CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
ClutterActor *actor;
CoglHandle texture;
guint8 paint_opacity;
texture = clutter_offscreen_effect_get_texture (effect);
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
paint_opacity = clutter_actor_get_paint_opacity (actor);
cogl_pipeline_set_color4ub (self->pipeline,
paint_opacity,
paint_opacity,
paint_opacity,
paint_opacity);
cogl_framebuffer_draw_rectangle (framebuffer,
self->pipeline,
0, 0,
cogl_texture_get_width (texture),
cogl_texture_get_height (texture));
}
static void
@ -216,7 +251,7 @@ clutter_desaturate_effect_class_init (ClutterDesaturateEffectClass *klass)
ClutterOffscreenEffectClass *offscreen_class;
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
offscreen_class->create_pipeline = clutter_desaturate_effect_create_pipeline;
offscreen_class->paint_target = clutter_desaturate_effect_paint_target;
effect_class->pre_paint = clutter_desaturate_effect_pre_paint;

View File

@ -0,0 +1,306 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2010 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
#ifndef __CLUTTER_DEVICE_MANAGER_PRIVATE_H__
#define __CLUTTER_DEVICE_MANAGER_PRIVATE_H__
#include <clutter/clutter-backend.h>
#include <clutter/clutter-device-manager.h>
#include <clutter/clutter-event.h>
G_BEGIN_DECLS
typedef struct _ClutterAxisInfo
{
ClutterInputAxis axis;
gdouble min_axis;
gdouble max_axis;
gdouble min_value;
gdouble max_value;
gdouble resolution;
} ClutterAxisInfo;
typedef struct _ClutterKeyInfo
{
guint keyval;
ClutterModifierType modifiers;
} ClutterKeyInfo;
typedef struct _ClutterScrollInfo
{
guint axis_id;
ClutterScrollDirection direction;
gdouble increment;
gdouble last_value;
guint last_value_valid : 1;
} ClutterScrollInfo;
typedef struct _ClutterTouchInfo
{
ClutterEventSequence *sequence;
ClutterActor *actor;
gfloat current_x;
gfloat current_y;
} ClutterTouchInfo;
typedef struct _ClutterPtrA11yData
{
int n_btn_pressed;
float current_x;
float current_y;
float dwell_x;
float dwell_y;
gboolean dwell_drag_started;
gboolean dwell_gesture_started;
guint dwell_timer;
guint dwell_position_timer;
guint secondary_click_timer;
gboolean secondary_click_triggered;
} ClutterPtrA11yData;
struct _ClutterInputDevice
{
GObject parent_instance;
gint id;
ClutterInputDeviceType device_type;
ClutterInputMode device_mode;
gchar *device_name;
ClutterDeviceManager *device_manager;
ClutterBackend *backend;
/* the associated device */
ClutterInputDevice *associated;
GList *slaves;
/* the actor underneath the pointer */
ClutterActor *cursor_actor;
GHashTable *inv_touch_sequence_actors;
/* the actor that has a grab in place for the device */
ClutterActor *pointer_grab_actor;
ClutterActor *keyboard_grab_actor;
GHashTable *sequence_grab_actors;
GHashTable *inv_sequence_grab_actors;
/* the current click count */
gint click_count;
/* the stage the device is on */
ClutterStage *stage;
/* the current state */
gfloat current_x;
gfloat current_y;
guint32 current_time;
gint current_button_number;
ClutterModifierType current_state;
/* the current touch points states */
GHashTable *touch_sequences_info;
/* the previous state, used for click count generation */
gint previous_x;
gint previous_y;
guint32 previous_time;
gint previous_button_number;
ClutterModifierType previous_state;
GArray *axes;
guint n_keys;
GArray *keys;
GArray *scroll_info;
gchar *vendor_id;
gchar *product_id;
gchar *node_path;
GPtrArray *tools;
gint n_rings;
gint n_strips;
gint n_mode_groups;
ClutterInputDeviceMapping mapping_mode;
guint has_cursor : 1;
guint is_enabled : 1;
/* Accessiblity */
ClutterVirtualInputDevice *accessibility_virtual_device;
ClutterPtrA11yData *ptr_a11y_data;
};
typedef void (*ClutterEmitInputDeviceEvent) (ClutterEvent *event,
ClutterInputDevice *device);
struct _ClutterInputDeviceClass
{
GObjectClass parent_class;
gboolean (* keycode_to_evdev) (ClutterInputDevice *device,
guint hardware_keycode,
guint *evdev_keycode);
void (* update_from_tool) (ClutterInputDevice *device,
ClutterInputDeviceTool *tool);
gboolean (* is_mode_switch_button) (ClutterInputDevice *device,
guint group,
guint button);
gint (* get_group_n_modes) (ClutterInputDevice *device,
gint group);
gboolean (* is_grouped) (ClutterInputDevice *device,
ClutterInputDevice *other_device);
/* Keyboard accessbility */
void (* process_kbd_a11y_event) (ClutterEvent *event,
ClutterInputDevice *device,
ClutterEmitInputDeviceEvent emit_event_func);
};
/* device manager */
CLUTTER_EXPORT
void _clutter_device_manager_add_device (ClutterDeviceManager *device_manager,
ClutterInputDevice *device);
CLUTTER_EXPORT
void _clutter_device_manager_remove_device (ClutterDeviceManager *device_manager,
ClutterInputDevice *device);
void _clutter_device_manager_update_devices (ClutterDeviceManager *device_manager);
CLUTTER_EXPORT
void _clutter_device_manager_select_stage_events (ClutterDeviceManager *device_manager,
ClutterStage *stage);
ClutterBackend *_clutter_device_manager_get_backend (ClutterDeviceManager *device_manager);
void _clutter_device_manager_compress_motion (ClutterDeviceManager *device_manger,
ClutterEvent *event,
const ClutterEvent *to_discard);
CLUTTER_EXPORT
void clutter_device_manager_ensure_a11y_state (ClutterDeviceManager *device_manager);
/* input device */
CLUTTER_EXPORT
gboolean _clutter_input_device_has_sequence (ClutterInputDevice *device,
ClutterEventSequence *sequence);
CLUTTER_EXPORT
void _clutter_input_device_add_event_sequence (ClutterInputDevice *device,
ClutterEvent *event);
CLUTTER_EXPORT
void _clutter_input_device_remove_event_sequence (ClutterInputDevice *device,
ClutterEvent *event);
CLUTTER_EXPORT
void _clutter_input_device_set_coords (ClutterInputDevice *device,
ClutterEventSequence *sequence,
gfloat x,
gfloat y,
ClutterStage *stage);
CLUTTER_EXPORT
void _clutter_input_device_set_state (ClutterInputDevice *device,
ClutterModifierType state);
CLUTTER_EXPORT
void _clutter_input_device_set_time (ClutterInputDevice *device,
guint32 time_);
CLUTTER_EXPORT
void _clutter_input_device_set_stage (ClutterInputDevice *device,
ClutterStage *stage);
CLUTTER_EXPORT
ClutterStage * _clutter_input_device_get_stage (ClutterInputDevice *device);
void _clutter_input_device_set_actor (ClutterInputDevice *device,
ClutterEventSequence *sequence,
ClutterActor *actor,
gboolean emit_crossing);
ClutterActor * _clutter_input_device_update (ClutterInputDevice *device,
ClutterEventSequence *sequence,
gboolean emit_crossing);
CLUTTER_EXPORT
void _clutter_input_device_set_n_keys (ClutterInputDevice *device,
guint n_keys);
CLUTTER_EXPORT
guint _clutter_input_device_add_axis (ClutterInputDevice *device,
ClutterInputAxis axis,
gdouble min_value,
gdouble max_value,
gdouble resolution);
CLUTTER_EXPORT
void _clutter_input_device_reset_axes (ClutterInputDevice *device);
CLUTTER_EXPORT
void _clutter_input_device_set_associated_device (ClutterInputDevice *device,
ClutterInputDevice *associated);
CLUTTER_EXPORT
void _clutter_input_device_add_slave (ClutterInputDevice *master,
ClutterInputDevice *slave);
CLUTTER_EXPORT
void _clutter_input_device_remove_slave (ClutterInputDevice *master,
ClutterInputDevice *slave);
CLUTTER_EXPORT
gboolean _clutter_input_device_translate_axis (ClutterInputDevice *device,
guint index_,
gdouble value,
gdouble *axis_value);
CLUTTER_EXPORT
void _clutter_input_device_add_scroll_info (ClutterInputDevice *device,
guint index_,
ClutterScrollDirection direction,
gdouble increment);
CLUTTER_EXPORT
void _clutter_input_device_reset_scroll_info (ClutterInputDevice *device);
CLUTTER_EXPORT
gboolean _clutter_input_device_get_scroll_delta (ClutterInputDevice *device,
guint index_,
gdouble value,
ClutterScrollDirection *direction_p,
gdouble *delta_p);
CLUTTER_EXPORT
ClutterInputDeviceTool * clutter_input_device_lookup_tool (ClutterInputDevice *device,
guint64 serial,
ClutterInputDeviceToolType type);
CLUTTER_EXPORT
void clutter_input_device_add_tool (ClutterInputDevice *device,
ClutterInputDeviceTool *tool);
CLUTTER_EXPORT
void clutter_input_device_update_from_tool (ClutterInputDevice *device,
ClutterInputDeviceTool *tool);
G_END_DECLS
#endif /* __CLUTTER_DEVICE_MANAGER_PRIVATE_H__ */

View File

@ -0,0 +1,753 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2009 Intel Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Emmanuele Bassi <ebassi@linux.intel.com>
*/
/**
* SECTION:clutter-device-manager
* @short_description: Maintains the list of input devices
*
* #ClutterDeviceManager is a singleton object, owned by Clutter, which
* maintains the list of #ClutterInputDevice<!-- -->s.
*
* Depending on the backend used by Clutter it is possible to use the
* #ClutterDeviceManager::device-added and
* #ClutterDeviceManager::device-removed to monitor addition and removal
* of devices.
*
* #ClutterDeviceManager is available since Clutter 1.2
*/
#include "clutter-build-config.h"
#include "clutter-backend-private.h"
#include "clutter-debug.h"
#include "clutter-device-manager-private.h"
#include "clutter-enum-types.h"
#include "clutter-marshal.h"
#include "clutter-private.h"
#include "clutter-stage-private.h"
#include "clutter-virtual-input-device.h"
#include "clutter-input-device-tool.h"
#include "clutter-input-pointer-a11y-private.h"
struct _ClutterDeviceManagerPrivate
{
/* back-pointer to the backend */
ClutterBackend *backend;
/* Keyboard a11y */
ClutterKbdA11ySettings kbd_a11y_settings;
/* Pointer a11y */
ClutterPointerA11ySettings pointer_a11y_settings;
};
enum
{
PROP_0,
PROP_BACKEND,
PROP_LAST
};
static GParamSpec *obj_props[PROP_LAST];
enum
{
DEVICE_ADDED,
DEVICE_REMOVED,
TOOL_CHANGED,
KBD_A11Y_MASK_CHANGED,
KBD_A11Y_FLAGS_CHANGED,
PTR_A11Y_DWELL_CLICK_TYPE_CHANGED,
PTR_A11Y_TIMEOUT_STARTED,
PTR_A11Y_TIMEOUT_STOPPED,
LAST_SIGNAL
};
static guint manager_signals[LAST_SIGNAL] = { 0, };
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterDeviceManager,
clutter_device_manager,
G_TYPE_OBJECT)
static void
clutter_device_manager_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterDeviceManager *self = CLUTTER_DEVICE_MANAGER (gobject);
ClutterDeviceManagerPrivate *priv = clutter_device_manager_get_instance_private (self);
switch (prop_id)
{
case PROP_BACKEND:
priv->backend = g_value_get_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
}
static void
clutter_device_manager_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
ClutterDeviceManager *self = CLUTTER_DEVICE_MANAGER (gobject);
ClutterDeviceManagerPrivate *priv = clutter_device_manager_get_instance_private (self);
switch (prop_id)
{
case PROP_BACKEND:
g_value_set_object (value, priv->backend);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
}
static void
clutter_device_manager_class_init (ClutterDeviceManagerClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
obj_props[PROP_BACKEND] =
g_param_spec_object ("backend",
P_("Backend"),
P_("The ClutterBackend of the device manager"),
CLUTTER_TYPE_BACKEND,
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
gobject_class->set_property = clutter_device_manager_set_property;
gobject_class->get_property = clutter_device_manager_get_property;
g_object_class_install_properties (gobject_class,
PROP_LAST,
obj_props);
/**
* ClutterDeviceManager::device-added:
* @manager: the #ClutterDeviceManager that emitted the signal
* @device: the newly added #ClutterInputDevice
*
* The ::device-added signal is emitted each time a device has been
* added to the #ClutterDeviceManager
*
* Since: 1.2
*/
manager_signals[DEVICE_ADDED] =
g_signal_new (I_("device-added"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 1,
CLUTTER_TYPE_INPUT_DEVICE);
/**
* ClutterDeviceManager::device-removed:
* @manager: the #ClutterDeviceManager that emitted the signal
* @device: the removed #ClutterInputDevice
*
* The ::device-removed signal is emitted each time a device has been
* removed from the #ClutterDeviceManager
*
* Since: 1.2
*/
manager_signals[DEVICE_REMOVED] =
g_signal_new (I_("device-removed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 1,
CLUTTER_TYPE_INPUT_DEVICE);
manager_signals[TOOL_CHANGED] =
g_signal_new (I_("tool-changed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
_clutter_marshal_VOID__OBJECT_OBJECT,
G_TYPE_NONE, 2,
CLUTTER_TYPE_INPUT_DEVICE,
CLUTTER_TYPE_INPUT_DEVICE_TOOL);
/**
* ClutterDeviceManager::kbd-a11y-mods-state-changed:
* @manager: the #ClutterDeviceManager that emitted the signal
* @latched_mask: the latched modifier mask from stickykeys
* @locked_mask: the locked modifier mask from stickykeys
*
* The ::kbd-a11y-mods-state-changed signal is emitted each time either the
* latched modifiers mask or locked modifiers mask are changed as the
* result of keyboard accessibilty's sticky keys operations.
*/
manager_signals[KBD_A11Y_MASK_CHANGED] =
g_signal_new (I_("kbd-a11y-mods-state-changed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
_clutter_marshal_VOID__UINT_UINT,
G_TYPE_NONE, 2,
G_TYPE_UINT,
G_TYPE_UINT);
/**
* ClutterDeviceManager::kbd-a11y-flags-changed:
* @manager: the #ClutterDeviceManager that emitted the signal
* @settings_flags: the new ClutterKeyboardA11yFlags configuration
* @changed_mask: the ClutterKeyboardA11yFlags changed
*
* The ::kbd-a11y-flags-changed signal is emitted each time the
* ClutterKeyboardA11yFlags configuration is changed as the result of
* keyboard accessibilty operations.
*/
manager_signals[KBD_A11Y_FLAGS_CHANGED] =
g_signal_new (I_("kbd-a11y-flags-changed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
_clutter_marshal_VOID__UINT_UINT,
G_TYPE_NONE, 2,
G_TYPE_UINT,
G_TYPE_UINT);
/**
* ClutterDeviceManager::ptr-a11y-dwell-click-type-changed:
* @manager: the #ClutterDeviceManager that emitted the signal
* @click_type: the new #ClutterPointerA11yDwellClickType mode
*
* The ::ptr-a11y-dwell-click-type-changed signal is emitted each time
* the ClutterPointerA11yDwellClickType mode is changed as the result
* of pointer accessibility operations.
*/
manager_signals[PTR_A11Y_DWELL_CLICK_TYPE_CHANGED] =
g_signal_new (I_("ptr-a11y-dwell-click-type-changed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__FLAGS,
G_TYPE_NONE, 1,
CLUTTER_TYPE_POINTER_A11Y_DWELL_CLICK_TYPE);
/**
* ClutterDeviceManager::ptr-a11y-timeout-started:
* @manager: the #ClutterDeviceManager that emitted the signal
* @device: the core pointer #ClutterInputDevice
* @timeout_type: the type of timeout #ClutterPointerA11yTimeoutType
* @delay: the delay in ms before secondary-click is triggered.
*
* The ::ptr-a11y-timeout-started signal is emitted when a
* pointer accessibility timeout delay is started, so that upper
* layers can notify the user with some visual feedback.
*/
manager_signals[PTR_A11Y_TIMEOUT_STARTED] =
g_signal_new (I_("ptr-a11y-timeout-started"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
_clutter_marshal_VOID__OBJECT_FLAGS_UINT,
G_TYPE_NONE, 3,
CLUTTER_TYPE_INPUT_DEVICE,
CLUTTER_TYPE_POINTER_A11Y_TIMEOUT_TYPE,
G_TYPE_UINT);
/**
* ClutterDeviceManager::ptr-a11y-timeout-stopped:
* @manager: the #ClutterDeviceManager that emitted the signal
* @device: the core pointer #ClutterInputDevice
* @timeout_type: the type of timeout #ClutterPointerA11yTimeoutType
* @clicked: %TRUE if the timeout finished and triggered a click
*
* The ::ptr-a11y-timeout-stopped signal is emitted when a running
* pointer accessibility timeout delay is stopped, either because
* it's triggered at the end of the delay or cancelled, so that
* upper layers can notify the user with some visual feedback.
*/
manager_signals[PTR_A11Y_TIMEOUT_STOPPED] =
g_signal_new (I_("ptr-a11y-timeout-stopped"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
_clutter_marshal_VOID__OBJECT_FLAGS_BOOLEAN,
G_TYPE_NONE, 3,
CLUTTER_TYPE_INPUT_DEVICE,
CLUTTER_TYPE_POINTER_A11Y_TIMEOUT_TYPE,
G_TYPE_BOOLEAN);
}
static void
clutter_device_manager_init (ClutterDeviceManager *self)
{
}
/**
* clutter_device_manager_get_default:
*
* Retrieves the device manager singleton
*
* Return value: (transfer none): the #ClutterDeviceManager singleton.
* The returned instance is owned by Clutter and it should not be
* modified or freed
*
* Since: 1.2
*/
ClutterDeviceManager *
clutter_device_manager_get_default (void)
{
ClutterBackend *backend = clutter_get_default_backend ();
return CLUTTER_BACKEND_GET_CLASS (backend)->get_device_manager (backend);
}
/**
* clutter_device_manager_list_devices:
* @device_manager: a #ClutterDeviceManager
*
* Lists all currently registered input devices
*
* Return value: (transfer container) (element-type Clutter.InputDevice):
* a newly allocated list of #ClutterInputDevice objects. Use
* g_slist_free() to deallocate it when done
*
* Since: 1.2
*/
GSList *
clutter_device_manager_list_devices (ClutterDeviceManager *device_manager)
{
const GSList *devices;
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL);
devices = clutter_device_manager_peek_devices (device_manager);
return g_slist_copy ((GSList *) devices);
}
/**
* clutter_device_manager_peek_devices:
* @device_manager: a #ClutterDeviceManager
*
* Lists all currently registered input devices
*
* Return value: (transfer none) (element-type Clutter.InputDevice):
* a pointer to the internal list of #ClutterInputDevice objects. The
* returned list is owned by the #ClutterDeviceManager and should never
* be modified or freed
*
* Since: 1.2
*/
const GSList *
clutter_device_manager_peek_devices (ClutterDeviceManager *device_manager)
{
ClutterDeviceManagerClass *manager_class;
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL);
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
return manager_class->get_devices (device_manager);
}
/**
* clutter_device_manager_get_device:
* @device_manager: a #ClutterDeviceManager
* @device_id: the integer id of a device
*
* Retrieves the #ClutterInputDevice with the given @device_id
*
* Return value: (transfer none): a #ClutterInputDevice or %NULL. The
* returned device is owned by the #ClutterDeviceManager and should
* never be modified or freed
*
* Since: 1.2
*/
ClutterInputDevice *
clutter_device_manager_get_device (ClutterDeviceManager *device_manager,
gint device_id)
{
ClutterDeviceManagerClass *manager_class;
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL);
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
return manager_class->get_device (device_manager, device_id);
}
/**
* clutter_device_manager_get_core_device:
* @device_manager: a #ClutterDeviceManager
* @device_type: the type of the core device
*
* Retrieves the core #ClutterInputDevice of type @device_type
*
* Core devices are devices created automatically by the default
* Clutter backend
*
* Return value: (transfer none): a #ClutterInputDevice or %NULL. The
* returned device is owned by the #ClutterDeviceManager and should
* not be modified or freed
*
* Since: 1.2
*/
ClutterInputDevice *
clutter_device_manager_get_core_device (ClutterDeviceManager *device_manager,
ClutterInputDeviceType device_type)
{
ClutterDeviceManagerClass *manager_class;
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL);
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
return manager_class->get_core_device (device_manager, device_type);
}
void
_clutter_device_manager_select_stage_events (ClutterDeviceManager *device_manager,
ClutterStage *stage)
{
ClutterDeviceManagerClass *manager_class;
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
if (manager_class->select_stage_events)
manager_class->select_stage_events (device_manager, stage);
}
/*
* _clutter_device_manager_add_device:
* @device_manager: a #ClutterDeviceManager
* @device: a #ClutterInputDevice
*
* Adds @device to the list of #ClutterInputDevice<!-- -->s maintained
* by @device_manager
*
* The reference count of @device is not increased
*
* The #ClutterDeviceManager::device-added signal is emitted after
* adding @device to the list
*/
void
_clutter_device_manager_add_device (ClutterDeviceManager *device_manager,
ClutterInputDevice *device)
{
ClutterDeviceManagerClass *manager_class;
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
g_assert (manager_class->add_device != NULL);
manager_class->add_device (device_manager, device);
g_signal_emit (device_manager, manager_signals[DEVICE_ADDED], 0, device);
}
/*
* _clutter_device_manager_remove_device:
* @device_manager: a #ClutterDeviceManager
* @device: a #ClutterInputDevice
*
* Removes @device from the list of #ClutterInputDevice<!-- -->s
* maintained by @device_manager
*
* The reference count of @device is not decreased
*
* The #ClutterDeviceManager::device-removed signal is emitted after
* removing @device from the list
*/
void
_clutter_device_manager_remove_device (ClutterDeviceManager *device_manager,
ClutterInputDevice *device)
{
ClutterDeviceManagerClass *manager_class;
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
g_assert (manager_class->remove_device != NULL);
/* The subclass remove_device() method will likely unref it but we
have to keep it alive during the signal emission. */
g_object_ref (device);
manager_class->remove_device (device_manager, device);
g_signal_emit (device_manager, manager_signals[DEVICE_REMOVED], 0, device);
g_object_unref (device);
}
/*
* _clutter_device_manager_update_devices:
* @device_manager: a #ClutterDeviceManager
*
* Updates every #ClutterInputDevice handled by @device_manager
* by performing a pick paint at the coordinates of each pointer
* device
*/
void
_clutter_device_manager_update_devices (ClutterDeviceManager *device_manager)
{
const GSList *d;
for (d = clutter_device_manager_peek_devices (device_manager);
d != NULL;
d = d->next)
{
ClutterInputDevice *device = d->data;
ClutterInputDeviceType device_type;
/* we only care about pointer devices */
device_type = clutter_input_device_get_device_type (device);
if (device_type != CLUTTER_POINTER_DEVICE)
continue;
/* out of stage */
if (device->stage == NULL)
continue;
/* the user disabled motion events delivery on actors for
* the stage the device is on; we don't perform any picking
* since the source of the events will always be set to be
* the stage
*/
if (!clutter_stage_get_motion_events_enabled (device->stage))
continue;
_clutter_input_device_update (device, NULL, TRUE);
}
}
ClutterBackend *
_clutter_device_manager_get_backend (ClutterDeviceManager *manager)
{
ClutterDeviceManagerPrivate *priv = clutter_device_manager_get_instance_private (manager);
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (manager), NULL);
return priv->backend;
}
/**
* clutter_device_manager_create_virtual_device:
* @device_manager: a #ClutterDeviceManager
* @device_type: the type of the virtual device
*
* Creates a virtual input device.
*
* Returns: (transfer full): a newly created virtual device
**/
ClutterVirtualInputDevice *
clutter_device_manager_create_virtual_device (ClutterDeviceManager *device_manager,
ClutterInputDeviceType device_type)
{
ClutterDeviceManagerClass *manager_class;
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL);
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
return manager_class->create_virtual_device (device_manager,
device_type);
}
/**
* clutter_device_manager_supported_virtua_device_types: (skip)
*/
ClutterVirtualDeviceType
clutter_device_manager_get_supported_virtual_device_types (ClutterDeviceManager *device_manager)
{
ClutterDeviceManagerClass *manager_class;
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager),
CLUTTER_VIRTUAL_DEVICE_TYPE_NONE);
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
return manager_class->get_supported_virtual_device_types (device_manager);
}
void
_clutter_device_manager_compress_motion (ClutterDeviceManager *device_manager,
ClutterEvent *event,
const ClutterEvent *to_discard)
{
ClutterDeviceManagerClass *manager_class;
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
if (!manager_class->compress_motion)
return;
manager_class->compress_motion (device_manager, event, to_discard);
}
void
clutter_device_manager_ensure_a11y_state (ClutterDeviceManager *device_manager)
{
ClutterInputDevice *core_pointer;
core_pointer = clutter_device_manager_get_core_device (device_manager,
CLUTTER_POINTER_DEVICE);
if (core_pointer)
{
if (_clutter_is_input_pointer_a11y_enabled (core_pointer))
_clutter_input_pointer_a11y_add_device (core_pointer);
}
}
static gboolean
are_kbd_a11y_settings_equal (ClutterKbdA11ySettings *a,
ClutterKbdA11ySettings *b)
{
return (memcmp (a, b, sizeof (ClutterKbdA11ySettings)) == 0);
}
void
clutter_device_manager_set_kbd_a11y_settings (ClutterDeviceManager *device_manager,
ClutterKbdA11ySettings *settings)
{
ClutterDeviceManagerClass *manager_class;
ClutterDeviceManagerPrivate *priv = clutter_device_manager_get_instance_private (device_manager);
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
if (are_kbd_a11y_settings_equal (&priv->kbd_a11y_settings, settings))
return;
priv->kbd_a11y_settings = *settings;
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
if (manager_class->apply_kbd_a11y_settings)
manager_class->apply_kbd_a11y_settings (device_manager, settings);
}
void
clutter_device_manager_get_kbd_a11y_settings (ClutterDeviceManager *device_manager,
ClutterKbdA11ySettings *settings)
{
ClutterDeviceManagerPrivate *priv = clutter_device_manager_get_instance_private (device_manager);
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
*settings = priv->kbd_a11y_settings;
}
static gboolean
are_pointer_a11y_settings_equal (ClutterPointerA11ySettings *a,
ClutterPointerA11ySettings *b)
{
return (memcmp (a, b, sizeof (ClutterPointerA11ySettings)) == 0);
}
static void
clutter_device_manager_enable_pointer_a11y (ClutterDeviceManager *device_manager)
{
ClutterInputDevice *core_pointer;
core_pointer = clutter_device_manager_get_core_device (device_manager,
CLUTTER_POINTER_DEVICE);
_clutter_input_pointer_a11y_add_device (core_pointer);
}
static void
clutter_device_manager_disable_pointer_a11y (ClutterDeviceManager *device_manager)
{
ClutterInputDevice *core_pointer;
core_pointer = clutter_device_manager_get_core_device (device_manager,
CLUTTER_POINTER_DEVICE);
_clutter_input_pointer_a11y_remove_device (core_pointer);
}
/**
* clutter_device_manager_set_pointer_a11y_settings:
* @device_manager: a #ClutterDeviceManager
* @settings: a pointer to a #ClutterPointerA11ySettings
*
* Sets the pointer accessibility settings
**/
void
clutter_device_manager_set_pointer_a11y_settings (ClutterDeviceManager *device_manager,
ClutterPointerA11ySettings *settings)
{
ClutterDeviceManagerPrivate *priv =
clutter_device_manager_get_instance_private (device_manager);
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
if (are_pointer_a11y_settings_equal (&priv->pointer_a11y_settings, settings))
return;
if (priv->pointer_a11y_settings.controls == 0 && settings->controls != 0)
clutter_device_manager_enable_pointer_a11y (device_manager);
else if (priv->pointer_a11y_settings.controls != 0 && settings->controls == 0)
clutter_device_manager_disable_pointer_a11y (device_manager);
priv->pointer_a11y_settings = *settings;
}
/**
* clutter_device_manager_get_pointer_a11y_settings:
* @device_manager: a #ClutterDeviceManager
* @settings: a pointer to a #ClutterPointerA11ySettings
*
* Gets the current pointer accessibility settings
**/
void
clutter_device_manager_get_pointer_a11y_settings (ClutterDeviceManager *device_manager,
ClutterPointerA11ySettings *settings)
{
ClutterDeviceManagerPrivate *priv =
clutter_device_manager_get_instance_private (device_manager);
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
*settings = priv->pointer_a11y_settings;
}
/**
* clutter_device_manager_set_pointer_a11y_dwell_click_type:
* @device_manager: a #ClutterDeviceManager
* @click_type: type of click as #ClutterPointerA11yDwellClickType
*
* Sets the dwell click type
**/
void
clutter_device_manager_set_pointer_a11y_dwell_click_type (ClutterDeviceManager *device_manager,
ClutterPointerA11yDwellClickType click_type)
{
ClutterDeviceManagerPrivate *priv =
clutter_device_manager_get_instance_private (device_manager);
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
priv->pointer_a11y_settings.dwell_click_type = click_type;
}

View File

@ -0,0 +1,181 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2009 Intel Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Emmanuele Bassi <ebassi@linux.intel.com>
*/
#ifndef __CLUTTER_DEVICE_MANAGER_H__
#define __CLUTTER_DEVICE_MANAGER_H__
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#include <clutter/clutter-input-device.h>
#include <clutter/clutter-stage.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_DEVICE_MANAGER (clutter_device_manager_get_type ())
CLUTTER_EXPORT
G_DECLARE_DERIVABLE_TYPE (ClutterDeviceManager, clutter_device_manager,
CLUTTER, DEVICE_MANAGER, GObject)
typedef struct _ClutterDeviceManagerPrivate ClutterDeviceManagerPrivate;
/**
* ClutterVirtualDeviceType:
*/
typedef enum _ClutterVirtualDeviceType
{
CLUTTER_VIRTUAL_DEVICE_TYPE_NONE = 0,
CLUTTER_VIRTUAL_DEVICE_TYPE_KEYBOARD = 1 << 0,
CLUTTER_VIRTUAL_DEVICE_TYPE_POINTER = 1 << 1,
CLUTTER_VIRTUAL_DEVICE_TYPE_TOUCHSCREEN = 1 << 2,
} ClutterVirtualDeviceType;
/**
* ClutterKbdA11ySettings:
*
* The #ClutterKbdA11ySettings structure contains keyboard accessibility
* settings
*
*/
typedef struct _ClutterKbdA11ySettings
{
ClutterKeyboardA11yFlags controls;
gint slowkeys_delay;
gint debounce_delay;
gint timeout_delay;
gint mousekeys_init_delay;
gint mousekeys_max_speed;
gint mousekeys_accel_time;
} ClutterKbdA11ySettings;
/**
* ClutterPointerA11ySettings:
*
* The #ClutterPointerA11ySettings structure contains pointer accessibility
* settings
*
*/
typedef struct _ClutterPointerA11ySettings
{
ClutterPointerA11yFlags controls;
ClutterPointerA11yDwellClickType dwell_click_type;
ClutterPointerA11yDwellMode dwell_mode;
ClutterPointerA11yDwellDirection dwell_gesture_single;
ClutterPointerA11yDwellDirection dwell_gesture_double;
ClutterPointerA11yDwellDirection dwell_gesture_drag;
ClutterPointerA11yDwellDirection dwell_gesture_secondary;
gint secondary_click_delay;
gint dwell_delay;
gint dwell_threshold;
} ClutterPointerA11ySettings;
/**
* ClutterDeviceManagerClass:
*
* The #ClutterDeviceManagerClass structure contains only private data
*
* Since: 1.2
*/
struct _ClutterDeviceManagerClass
{
/*< private >*/
GObjectClass parent_class;
const GSList * (* get_devices) (ClutterDeviceManager *device_manager);
ClutterInputDevice *(* get_core_device) (ClutterDeviceManager *device_manager,
ClutterInputDeviceType device_type);
ClutterInputDevice *(* get_device) (ClutterDeviceManager *device_manager,
gint device_id);
void (* add_device) (ClutterDeviceManager *manager,
ClutterInputDevice *device);
void (* remove_device) (ClutterDeviceManager *manager,
ClutterInputDevice *device);
void (* select_stage_events) (ClutterDeviceManager *manager,
ClutterStage *stage);
ClutterVirtualInputDevice *(* create_virtual_device) (ClutterDeviceManager *device_manager,
ClutterInputDeviceType device_type);
ClutterVirtualDeviceType (* get_supported_virtual_device_types) (ClutterDeviceManager *device_manager);
void (* compress_motion) (ClutterDeviceManager *device_manger,
ClutterEvent *event,
const ClutterEvent *to_discard);
/* Keyboard accessbility */
void (* apply_kbd_a11y_settings) (ClutterDeviceManager *device_manger,
ClutterKbdA11ySettings *settings);
/* Event platform data */
void (* copy_event_data) (ClutterDeviceManager *device_manager,
const ClutterEvent *src,
ClutterEvent *dest);
void (* free_event_data) (ClutterDeviceManager *device_manager,
ClutterEvent *event);
/* padding */
gpointer _padding[4];
};
CLUTTER_EXPORT
ClutterDeviceManager *clutter_device_manager_get_default (void);
CLUTTER_EXPORT
GSList * clutter_device_manager_list_devices (ClutterDeviceManager *device_manager);
CLUTTER_EXPORT
const GSList * clutter_device_manager_peek_devices (ClutterDeviceManager *device_manager);
CLUTTER_EXPORT
ClutterInputDevice * clutter_device_manager_get_device (ClutterDeviceManager *device_manager,
gint device_id);
CLUTTER_EXPORT
ClutterInputDevice * clutter_device_manager_get_core_device (ClutterDeviceManager *device_manager,
ClutterInputDeviceType device_type);
CLUTTER_EXPORT
ClutterVirtualInputDevice *clutter_device_manager_create_virtual_device (ClutterDeviceManager *device_manager,
ClutterInputDeviceType device_type);
CLUTTER_EXPORT
ClutterVirtualDeviceType clutter_device_manager_get_supported_virtual_device_types (ClutterDeviceManager *device_manager);
CLUTTER_EXPORT
void clutter_device_manager_set_kbd_a11y_settings (ClutterDeviceManager *device_manager,
ClutterKbdA11ySettings *settings);
CLUTTER_EXPORT
void clutter_device_manager_get_kbd_a11y_settings (ClutterDeviceManager *device_manager,
ClutterKbdA11ySettings *settings);
CLUTTER_EXPORT
void clutter_device_manager_set_pointer_a11y_settings (ClutterDeviceManager *device_manager,
ClutterPointerA11ySettings *settings);
CLUTTER_EXPORT
void clutter_device_manager_get_pointer_a11y_settings (ClutterDeviceManager *device_manager,
ClutterPointerA11ySettings *settings);
CLUTTER_EXPORT
void clutter_device_manager_set_pointer_a11y_dwell_click_type (ClutterDeviceManager *device_manager,
ClutterPointerA11yDwellClickType click_type);
G_END_DECLS
#endif /* __CLUTTER_DEVICE_MANAGER_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,152 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2010 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
#ifndef __CLUTTER_DRAG_ACTION_H__
#define __CLUTTER_DRAG_ACTION_H__
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#include <clutter/clutter-action.h>
#include <clutter/clutter-event.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_DRAG_ACTION (clutter_drag_action_get_type ())
#define CLUTTER_DRAG_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DRAG_ACTION, ClutterDragAction))
#define CLUTTER_IS_DRAG_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DRAG_ACTION))
#define CLUTTER_DRAG_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DRAG_ACTION, ClutterDragActionClass))
#define CLUTTER_IS_DRAG_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DRAG_ACTION))
#define CLUTTER_DRAG_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DRAG_ACTION, ClutterDragActionClass))
typedef struct _ClutterDragAction ClutterDragAction;
typedef struct _ClutterDragActionPrivate ClutterDragActionPrivate;
typedef struct _ClutterDragActionClass ClutterDragActionClass;
/**
* ClutterDragAction:
*
* The #ClutterDragAction structure contains only
* private data and should be accessed using the provided API
*
* Since: 1.4
*/
struct _ClutterDragAction
{
/*< private >*/
ClutterAction parent_instance;
ClutterDragActionPrivate *priv;
};
/**
* ClutterDragActionClass:
* @drag_begin: class handler of the #ClutterDragAction::drag-begin signal
* @drag_motion: class handler of the #ClutterDragAction::drag-motion signal
* @drag_end: class handler of the #ClutterDragAction::drag-end signal
* @drag_progress: class handler of the #ClutterDragAction::drag-progress signal
*
* The #ClutterDragActionClass structure contains
* only private data
*
* Since: 1.4
*/
struct _ClutterDragActionClass
{
/*< private >*/
ClutterActionClass parent_class;
/*< public >*/
void (* drag_begin) (ClutterDragAction *action,
ClutterActor *actor,
gfloat event_x,
gfloat event_y,
ClutterModifierType modifiers);
void (* drag_motion) (ClutterDragAction *action,
ClutterActor *actor,
gfloat delta_x,
gfloat delta_y);
void (* drag_end) (ClutterDragAction *action,
ClutterActor *actor,
gfloat event_x,
gfloat event_y,
ClutterModifierType modifiers);
gboolean (* drag_progress) (ClutterDragAction *action,
ClutterActor *actor,
gfloat delta_x,
gfloat delta_y);
/*< private >*/
void (* _clutter_drag_action1) (void);
void (* _clutter_drag_action2) (void);
void (* _clutter_drag_action3) (void);
void (* _clutter_drag_action4) (void);
};
CLUTTER_EXPORT
GType clutter_drag_action_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterAction * clutter_drag_action_new (void);
CLUTTER_EXPORT
void clutter_drag_action_set_drag_threshold (ClutterDragAction *action,
gint x_threshold,
gint y_threshold);
CLUTTER_EXPORT
void clutter_drag_action_get_drag_threshold (ClutterDragAction *action,
guint *x_threshold,
guint *y_threshold);
CLUTTER_EXPORT
void clutter_drag_action_set_drag_handle (ClutterDragAction *action,
ClutterActor *handle);
CLUTTER_EXPORT
ClutterActor * clutter_drag_action_get_drag_handle (ClutterDragAction *action);
CLUTTER_EXPORT
void clutter_drag_action_set_drag_axis (ClutterDragAction *action,
ClutterDragAxis axis);
CLUTTER_EXPORT
ClutterDragAxis clutter_drag_action_get_drag_axis (ClutterDragAction *action);
CLUTTER_EXPORT
void clutter_drag_action_get_press_coords (ClutterDragAction *action,
gfloat *press_x,
gfloat *press_y);
CLUTTER_EXPORT
void clutter_drag_action_get_motion_coords (ClutterDragAction *action,
gfloat *motion_x,
gfloat *motion_y);
CLUTTER_EXPORT
gboolean clutter_drag_action_get_drag_area (ClutterDragAction *action,
ClutterRect *drag_area);
CLUTTER_EXPORT
void clutter_drag_action_set_drag_area (ClutterDragAction *action,
const ClutterRect *drag_area);
G_END_DECLS
#endif /* __CLUTTER_DRAG_ACTION_H__ */

View File

@ -0,0 +1,529 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright © 2011 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
/**
* SECTION:clutter-drop-action
* @Title: ClutterDropAction
* @short_description: An action for drop targets
*
* #ClutterDropAction is a #ClutterAction that allows a #ClutterActor
* implementation to control what happens when an actor dragged using
* a #ClutterDragAction crosses the target area or when a dragged actor
* is released (or "dropped") on the target area.
*
* A trivial use of #ClutterDropAction consists in connecting to the
* #ClutterDropAction::drop signal and handling the drop from there,
* for instance:
*
* |[<!-- language="C" -->
* ClutterAction *action = clutter_drop_action ();
*
* g_signal_connect (action, "drop", G_CALLBACK (on_drop), NULL);
* clutter_actor_add_action (an_actor, action);
* ]|
*
* The #ClutterDropAction::can-drop can be used to control whether the
* #ClutterDropAction::drop signal is going to be emitted; returning %FALSE
* from a handler connected to the #ClutterDropAction::can-drop signal will
* cause the #ClutterDropAction::drop signal to be skipped when the input
* device button is released.
*
* It's important to note that #ClutterDropAction will only work with
* actors dragged using #ClutterDragAction.
*
* See [drop-action.c](https://git.gnome.org/browse/clutter/tree/examples/drop-action.c?h=clutter-1.18)
* for an example of how to use #ClutterDropAction.
*
* #ClutterDropAction is available since Clutter 1.8
*/
#include "clutter-build-config.h"
#include "clutter-drop-action.h"
#include "clutter-actor-meta-private.h"
#include "clutter-actor-private.h"
#include "clutter-drag-action.h"
#include "clutter-main.h"
#include "clutter-marshal.h"
#include "clutter-stage-private.h"
struct _ClutterDropActionPrivate
{
ClutterActor *actor;
ClutterActor *stage;
gulong mapped_id;
};
typedef struct _DropTarget {
ClutterActor *stage;
gulong capture_id;
GHashTable *actions;
ClutterDropAction *last_action;
} DropTarget;
enum
{
CAN_DROP,
OVER_IN,
OVER_OUT,
DROP,
DROP_CANCEL,
LAST_SIGNAL
};
static guint drop_signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE_WITH_PRIVATE (ClutterDropAction, clutter_drop_action, CLUTTER_TYPE_ACTION)
static void
drop_target_free (gpointer _data)
{
DropTarget *data = _data;
g_signal_handler_disconnect (data->stage, data->capture_id);
g_hash_table_destroy (data->actions);
g_free (data);
}
static gboolean
on_stage_capture (ClutterStage *stage,
ClutterEvent *event,
gpointer user_data)
{
DropTarget *data = user_data;
gfloat event_x, event_y;
ClutterActor *actor, *drag_actor;
ClutterDropAction *drop_action;
ClutterInputDevice *device;
gboolean was_reactive;
switch (clutter_event_type (event))
{
case CLUTTER_MOTION:
case CLUTTER_BUTTON_RELEASE:
if (clutter_event_type (event) == CLUTTER_MOTION &&
!(clutter_event_get_state (event) & CLUTTER_BUTTON1_MASK))
return CLUTTER_EVENT_PROPAGATE;
if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE &&
clutter_event_get_button (event) != CLUTTER_BUTTON_PRIMARY)
return CLUTTER_EVENT_PROPAGATE;
device = clutter_event_get_device (event);
drag_actor = _clutter_stage_get_pointer_drag_actor (stage, device);
if (drag_actor == NULL)
return CLUTTER_EVENT_PROPAGATE;
break;
case CLUTTER_TOUCH_UPDATE:
case CLUTTER_TOUCH_END:
drag_actor = _clutter_stage_get_touch_drag_actor (stage,
clutter_event_get_event_sequence (event));
if (drag_actor == NULL)
return CLUTTER_EVENT_PROPAGATE;
break;
default:
return CLUTTER_EVENT_PROPAGATE;
}
clutter_event_get_coords (event, &event_x, &event_y);
/* get the actor under the cursor, excluding the dragged actor; we
* use reactivity because it won't cause any scene invalidation
*/
was_reactive = clutter_actor_get_reactive (drag_actor);
clutter_actor_set_reactive (drag_actor, FALSE);
actor = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_REACTIVE,
event_x,
event_y);
if (actor == NULL || actor == CLUTTER_ACTOR (stage))
{
if (data->last_action != NULL)
{
ClutterActorMeta *meta = CLUTTER_ACTOR_META (data->last_action);
g_signal_emit (data->last_action, drop_signals[OVER_OUT], 0,
clutter_actor_meta_get_actor (meta));
data->last_action = NULL;
}
goto out;
}
drop_action = g_hash_table_lookup (data->actions, actor);
if (drop_action == NULL)
{
if (data->last_action != NULL)
{
ClutterActorMeta *meta = CLUTTER_ACTOR_META (data->last_action);
g_signal_emit (data->last_action, drop_signals[OVER_OUT], 0,
clutter_actor_meta_get_actor (meta));
data->last_action = NULL;
}
goto out;
}
else
{
if (data->last_action != drop_action)
{
ClutterActorMeta *meta;
if (data->last_action != NULL)
{
meta = CLUTTER_ACTOR_META (data->last_action);
g_signal_emit (data->last_action, drop_signals[OVER_OUT], 0,
clutter_actor_meta_get_actor (meta));
}
meta = CLUTTER_ACTOR_META (drop_action);
g_signal_emit (drop_action, drop_signals[OVER_IN], 0,
clutter_actor_meta_get_actor (meta));
}
data->last_action = drop_action;
}
out:
if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE ||
clutter_event_type (event) == CLUTTER_TOUCH_END)
{
if (data->last_action != NULL)
{
ClutterActorMeta *meta = CLUTTER_ACTOR_META (data->last_action);
gboolean can_drop = FALSE;
g_signal_emit (data->last_action, drop_signals[CAN_DROP], 0,
clutter_actor_meta_get_actor (meta),
event_x, event_y,
&can_drop);
if (can_drop)
{
g_signal_emit (data->last_action, drop_signals[DROP], 0,
clutter_actor_meta_get_actor (meta),
event_x, event_y);
}
else
{
g_signal_emit (data->last_action, drop_signals[DROP_CANCEL], 0,
clutter_actor_meta_get_actor (meta),
event_x, event_y);
}
}
data->last_action = NULL;
}
if (drag_actor != NULL)
clutter_actor_set_reactive (drag_actor, was_reactive);
return CLUTTER_EVENT_PROPAGATE;
}
static void
drop_action_register (ClutterDropAction *self)
{
ClutterDropActionPrivate *priv = self->priv;
DropTarget *data;
g_assert (priv->stage != NULL);
data = g_object_get_data (G_OBJECT (priv->stage), "__clutter_drop_targets");
if (data == NULL)
{
data = g_new0 (DropTarget, 1);
data->stage = priv->stage;
data->actions = g_hash_table_new (NULL, NULL);
data->capture_id = g_signal_connect (priv->stage, "captured-event",
G_CALLBACK (on_stage_capture),
data);
g_object_set_data_full (G_OBJECT (priv->stage), "__clutter_drop_targets",
data,
drop_target_free);
}
g_hash_table_replace (data->actions, priv->actor, self);
}
static void
drop_action_unregister (ClutterDropAction *self)
{
ClutterDropActionPrivate *priv = self->priv;
DropTarget *data = NULL;
if (priv->stage != NULL)
data = g_object_get_data (G_OBJECT (priv->stage), "__clutter_drop_targets");
if (data == NULL)
return;
g_hash_table_remove (data->actions, priv->actor);
if (g_hash_table_size (data->actions) == 0)
g_object_set_data (G_OBJECT (data->stage), "__clutter_drop_targets", NULL);
}
static void
on_actor_mapped (ClutterActor *actor,
GParamSpec *pspec,
ClutterDropAction *self)
{
if (clutter_actor_is_mapped (actor))
{
if (self->priv->stage == NULL)
self->priv->stage = clutter_actor_get_stage (actor);
drop_action_register (self);
}
else
drop_action_unregister (self);
}
static void
clutter_drop_action_set_actor (ClutterActorMeta *meta,
ClutterActor *actor)
{
ClutterDropActionPrivate *priv = CLUTTER_DROP_ACTION (meta)->priv;
if (priv->actor != NULL)
{
drop_action_unregister (CLUTTER_DROP_ACTION (meta));
if (priv->mapped_id != 0)
g_signal_handler_disconnect (priv->actor, priv->mapped_id);
priv->stage = NULL;
priv->actor = NULL;
priv->mapped_id = 0;
}
priv->actor = actor;
if (priv->actor != NULL)
{
priv->stage = clutter_actor_get_stage (actor);
priv->mapped_id = g_signal_connect (actor, "notify::mapped",
G_CALLBACK (on_actor_mapped),
meta);
if (priv->stage != NULL)
drop_action_register (CLUTTER_DROP_ACTION (meta));
}
CLUTTER_ACTOR_META_CLASS (clutter_drop_action_parent_class)->set_actor (meta, actor);
}
static gboolean
signal_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return,
gpointer user_data)
{
gboolean continue_emission;
continue_emission = g_value_get_boolean (handler_return);
g_value_set_boolean (return_accu, continue_emission);
return continue_emission;
}
static gboolean
clutter_drop_action_real_can_drop (ClutterDropAction *action,
ClutterActor *actor,
gfloat event_x,
gfloat event_y)
{
return TRUE;
}
static void
clutter_drop_action_class_init (ClutterDropActionClass *klass)
{
ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass);
meta_class->set_actor = clutter_drop_action_set_actor;
klass->can_drop = clutter_drop_action_real_can_drop;
/**
* ClutterDropAction::can-drop:
* @action: the #ClutterDropAction that emitted the signal
* @actor: the #ClutterActor attached to the @action
* @event_x: the X coordinate (in stage space) of the drop event
* @event_y: the Y coordinate (in stage space) of the drop event
*
* The ::can-drop signal is emitted when the dragged actor is dropped
* on @actor. The return value of the ::can-drop signal will determine
* whether or not the #ClutterDropAction::drop signal is going to be
* emitted on @action.
*
* The default implementation of #ClutterDropAction returns %TRUE for
* this signal.
*
* Return value: %TRUE if the drop is accepted, and %FALSE otherwise
*
* Since: 1.8
*/
drop_signals[CAN_DROP] =
g_signal_new (I_("can-drop"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterDropActionClass, can_drop),
signal_accumulator, NULL,
_clutter_marshal_BOOLEAN__OBJECT_FLOAT_FLOAT,
G_TYPE_BOOLEAN, 3,
CLUTTER_TYPE_ACTOR,
G_TYPE_FLOAT,
G_TYPE_FLOAT);
/**
* ClutterDropAction::over-in:
* @action: the #ClutterDropAction that emitted the signal
* @actor: the #ClutterActor attached to the @action
*
* The ::over-in signal is emitted when the dragged actor crosses
* into @actor.
*
* Since: 1.8
*/
drop_signals[OVER_IN] =
g_signal_new (I_("over-in"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterDropActionClass, over_in),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
CLUTTER_TYPE_ACTOR);
/**
* ClutterDropAction::over-out:
* @action: the #ClutterDropAction that emitted the signal
* @actor: the #ClutterActor attached to the @action
*
* The ::over-out signal is emitted when the dragged actor crosses
* outside @actor.
*
* Since: 1.8
*/
drop_signals[OVER_OUT] =
g_signal_new (I_("over-out"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterDropActionClass, over_out),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
CLUTTER_TYPE_ACTOR);
/**
* ClutterDropAction::drop:
* @action: the #ClutterDropAction that emitted the signal
* @actor: the #ClutterActor attached to the @action
* @event_x: the X coordinate (in stage space) of the drop event
* @event_y: the Y coordinate (in stage space) of the drop event
*
* The ::drop signal is emitted when the dragged actor is dropped
* on @actor. This signal is only emitted if at least an handler of
* #ClutterDropAction::can-drop returns %TRUE.
*
* Since: 1.8
*/
drop_signals[DROP] =
g_signal_new (I_("drop"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterDropActionClass, drop),
NULL, NULL,
_clutter_marshal_VOID__OBJECT_FLOAT_FLOAT,
G_TYPE_NONE, 3,
CLUTTER_TYPE_ACTOR,
G_TYPE_FLOAT,
G_TYPE_FLOAT);
/**
* ClutterDropAction::drop-cancel:
* @action: the #ClutterDropAction that emitted the signal
* @actor: the #ClutterActor attached to the @action
* @event_x: the X coordinate (in stage space) of the drop event
* @event_y: the Y coordinate (in stage space) of the drop event
*
* The ::drop-cancel signal is emitted when the drop is refused
* by an emission of the #ClutterDropAction::can-drop signal.
*
* After the ::drop-cancel signal is fired the active drag is
* terminated.
*
* Since: 1.12
*/
drop_signals[DROP_CANCEL] =
g_signal_new (I_("drop-cancel"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterDropActionClass, drop),
NULL, NULL,
_clutter_marshal_VOID__OBJECT_FLOAT_FLOAT,
G_TYPE_NONE, 3,
CLUTTER_TYPE_ACTOR,
G_TYPE_FLOAT,
G_TYPE_FLOAT);
}
static void
clutter_drop_action_init (ClutterDropAction *self)
{
self->priv = clutter_drop_action_get_instance_private (self);
}
/**
* clutter_drop_action_new:
*
* Creates a new #ClutterDropAction.
*
* Use clutter_actor_add_action() to add the action to a #ClutterActor.
*
* Return value: the newly created #ClutterDropAction
*
* Since: 1.8
*/
ClutterAction *
clutter_drop_action_new (void)
{
return g_object_new (CLUTTER_TYPE_DROP_ACTION, NULL);
}

View File

@ -0,0 +1,115 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright © 2011 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
#ifndef __CLUTTER_DROP_ACTION_H__
#define __CLUTTER_DROP_ACTION_H__
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be directly included."
#endif
#include <clutter/clutter-action.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_DROP_ACTION (clutter_drop_action_get_type ())
#define CLUTTER_DROP_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DROP_ACTION, ClutterDropAction))
#define CLUTTER_IS_DROP_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DROP_ACTION))
#define CLUTTER_DROP_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DROP_ACTION, ClutterDropActionClass))
#define CLUTTER_IS_DROP_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DROP_ACTION))
#define CLUTTER_DROP_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DROP_ACTION, ClutterDropActionClass))
typedef struct _ClutterDropAction ClutterDropAction;
typedef struct _ClutterDropActionPrivate ClutterDropActionPrivate;
typedef struct _ClutterDropActionClass ClutterDropActionClass;
/**
* ClutterDropAction:
*
* The #ClutterDropAction structure contains only
* private data and should be accessed using the provided API.
*
* Since: 1.8
*/
struct _ClutterDropAction
{
/*< private >*/
ClutterAction parent_instance;
ClutterDropActionPrivate *priv;
};
/**
* ClutterDropActionClass:
* @can_drop: class handler for the #ClutterDropAction::can-drop signal
* @over_in: class handler for the #ClutterDropAction::over-in signal
* @over_out: class handler for the #ClutterDropAction::over-out signal
* @drop: class handler for the #ClutterDropAction::drop signal
*
* The #ClutterDropActionClass structure contains
* only private data.
*
* Since: 1.8
*/
struct _ClutterDropActionClass
{
/*< private >*/
ClutterActionClass parent_class;
/*< public >*/
gboolean (* can_drop) (ClutterDropAction *action,
ClutterActor *actor,
gfloat event_x,
gfloat event_y);
void (* over_in) (ClutterDropAction *action,
ClutterActor *actor);
void (* over_out) (ClutterDropAction *action,
ClutterActor *actor);
void (* drop) (ClutterDropAction *action,
ClutterActor *actor,
gfloat event_x,
gfloat event_y);
/*< private >*/
void (*_clutter_drop_action1) (void);
void (*_clutter_drop_action2) (void);
void (*_clutter_drop_action3) (void);
void (*_clutter_drop_action4) (void);
void (*_clutter_drop_action5) (void);
void (*_clutter_drop_action6) (void);
void (*_clutter_drop_action7) (void);
void (*_clutter_drop_action8) (void);
};
CLUTTER_EXPORT
GType clutter_drop_action_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterAction * clutter_drop_action_new (void);
G_END_DECLS
#endif /* __CLUTTER_DROP_ACTION_H__ */

View File

@ -5,15 +5,15 @@
G_BEGIN_DECLS
gboolean _clutter_effect_pre_paint (ClutterEffect *effect);
void _clutter_effect_post_paint (ClutterEffect *effect);
gboolean _clutter_effect_modify_paint_volume (ClutterEffect *effect,
ClutterPaintVolume *volume);
gboolean _clutter_effect_has_custom_paint_volume (ClutterEffect *effect);
void _clutter_effect_paint (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context,
ClutterEffectPaintFlags flags);
void _clutter_effect_pick (ClutterEffect *effect,
ClutterPickContext *pick_context);
ClutterEffectPaintFlags flags);
G_END_DECLS

View File

@ -100,13 +100,13 @@
* // Clear the previous state //
* if (self->rect_1)
* {
* cogl_object_unref (self->rect_1);
* cogl_handle_unref (self->rect_1);
* self->rect_1 = NULL;
* }
*
* if (self->rect_2)
* {
* cogl_object_unref (self->rect_2);
* cogl_handle_unref (self->rect_2);
* self->rect_2 = NULL;
* }
*
@ -169,8 +169,6 @@
#include "clutter-effect-private.h"
#include "clutter-enum-types.h"
#include "clutter-marshal.h"
#include "clutter-paint-node-private.h"
#include "clutter-paint-nodes.h"
#include "clutter-private.h"
#include "clutter-actor-private.h"
@ -179,17 +177,13 @@ G_DEFINE_ABSTRACT_TYPE (ClutterEffect,
CLUTTER_TYPE_ACTOR_META);
static gboolean
clutter_effect_real_pre_paint (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
clutter_effect_real_pre_paint (ClutterEffect *effect)
{
return TRUE;
}
static void
clutter_effect_real_post_paint (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
clutter_effect_real_post_paint (ClutterEffect *effect)
{
}
@ -200,94 +194,66 @@ clutter_effect_real_modify_paint_volume (ClutterEffect *effect,
return TRUE;
}
static void
add_actor_node (ClutterEffect *effect,
ClutterPaintNode *node)
{
ClutterPaintNode *actor_node;
ClutterActor *actor;
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
actor_node = clutter_actor_node_new (actor, -1);
clutter_paint_node_add_child (node, actor_node);
clutter_paint_node_unref (actor_node);
}
static void
clutter_effect_real_paint_node (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context,
ClutterEffectPaintFlags flags)
{
add_actor_node (effect, node);
}
static void
clutter_effect_real_paint (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context,
ClutterEffectPaintFlags flags)
{
ClutterEffectClass *effect_class = CLUTTER_EFFECT_GET_CLASS (effect);
ClutterActorMeta *actor_meta = CLUTTER_ACTOR_META (effect);
ClutterActor *actor;
gboolean pre_paint_succeeded;
/* The default implementation provides a compatibility wrapper for
effects that haven't migrated to use the 'paint' virtual yet. This
just calls the old pre and post virtuals before chaining on */
pre_paint_succeeded = effect_class->pre_paint (effect, node,paint_context);
pre_paint_succeeded = _clutter_effect_pre_paint (effect);
actor = clutter_actor_meta_get_actor (actor_meta);
clutter_actor_continue_paint (actor);
if (pre_paint_succeeded)
{
effect_class->paint_node (effect, node, paint_context, flags);
effect_class->post_paint (effect, node, paint_context);
}
else
{
/* Just paint the actor as fallback */
add_actor_node (effect, node);
}
_clutter_effect_post_paint (effect);
}
static void
clutter_effect_real_pick (ClutterEffect *effect,
ClutterPickContext *pick_context)
clutter_effect_real_pick (ClutterEffect *effect,
ClutterEffectPaintFlags flags)
{
ClutterActorMeta *actor_meta = CLUTTER_ACTOR_META (effect);
ClutterActor *actor;
actor = clutter_actor_meta_get_actor (actor_meta);
clutter_actor_continue_pick (actor, pick_context);
clutter_actor_continue_paint (actor);
}
static void
clutter_effect_set_enabled (ClutterActorMeta *meta,
gboolean is_enabled)
clutter_effect_notify (GObject *gobject,
GParamSpec *pspec)
{
ClutterActorMetaClass *parent_class =
CLUTTER_ACTOR_META_CLASS (clutter_effect_parent_class);
ClutterActor *actor;
if (strcmp (pspec->name, "enabled") == 0)
{
ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject);
ClutterActor *actor = clutter_actor_meta_get_actor (meta);
actor = clutter_actor_meta_get_actor (meta);
if (actor)
clutter_actor_queue_redraw (actor);
if (actor != NULL)
clutter_actor_queue_redraw (actor);
}
parent_class->set_enabled (meta, is_enabled);
if (G_OBJECT_CLASS (clutter_effect_parent_class)->notify != NULL)
G_OBJECT_CLASS (clutter_effect_parent_class)->notify (gobject, pspec);
}
static void
clutter_effect_class_init (ClutterEffectClass *klass)
{
ClutterActorMetaClass *actor_meta_class = CLUTTER_ACTOR_META_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
actor_meta_class->set_enabled = clutter_effect_set_enabled;
gobject_class->notify = clutter_effect_notify;
klass->pre_paint = clutter_effect_real_pre_paint;
klass->post_paint = clutter_effect_real_post_paint;
klass->modify_paint_volume = clutter_effect_real_modify_paint_volume;
klass->paint = clutter_effect_real_paint;
klass->paint_node = clutter_effect_real_paint_node;
klass->pick = clutter_effect_real_pick;
}
@ -296,27 +262,38 @@ clutter_effect_init (ClutterEffect *self)
{
}
gboolean
_clutter_effect_pre_paint (ClutterEffect *effect)
{
g_return_val_if_fail (CLUTTER_IS_EFFECT (effect), FALSE);
return CLUTTER_EFFECT_GET_CLASS (effect)->pre_paint (effect);
}
void
_clutter_effect_post_paint (ClutterEffect *effect)
{
g_return_if_fail (CLUTTER_IS_EFFECT (effect));
CLUTTER_EFFECT_GET_CLASS (effect)->post_paint (effect);
}
void
_clutter_effect_paint (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context,
ClutterEffectPaintFlags flags)
{
g_return_if_fail (CLUTTER_IS_EFFECT (effect));
CLUTTER_EFFECT_GET_CLASS (effect)->paint (effect,
node,
paint_context,
flags);
CLUTTER_EFFECT_GET_CLASS (effect)->paint (effect, flags);
}
void
_clutter_effect_pick (ClutterEffect *effect,
ClutterPickContext *pick_context)
_clutter_effect_pick (ClutterEffect *effect,
ClutterEffectPaintFlags flags)
{
g_return_if_fail (CLUTTER_IS_EFFECT (effect));
CLUTTER_EFFECT_GET_CLASS (effect)->pick (effect, pick_context);
CLUTTER_EFFECT_GET_CLASS (effect)->pick (effect, flags);
}
gboolean
@ -368,7 +345,7 @@ _clutter_effect_has_custom_paint_volume (ClutterEffect *effect)
* the actor itself so the %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY would still
* not be set. The effect can detect this case by keeping track of the
* last modelview matrix that was used to render the actor and
* verifying that it remains the same in the next paint.
* veryifying that it remains the same in the next paint.
*
* Any other effects that are layered on top of the passed in effect
* will still be passed the %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY flag. If
@ -392,6 +369,7 @@ clutter_effect_queue_repaint (ClutterEffect *effect)
/* If the effect has no actor then nothing needs to be done */
if (actor != NULL)
_clutter_actor_queue_redraw_full (actor,
0, /* flags */
NULL, /* clip volume */
effect /* effect */);
}

View File

@ -30,8 +30,6 @@
#endif
#include <clutter/clutter-actor-meta.h>
#include <clutter/clutter-paint-context.h>
#include <clutter/clutter-pick-context.h>
G_BEGIN_DECLS
@ -76,26 +74,16 @@ struct _ClutterEffectClass
ClutterActorMetaClass parent_class;
/*< public >*/
gboolean (* pre_paint) (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context);
void (* post_paint) (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context);
gboolean (* pre_paint) (ClutterEffect *effect);
void (* post_paint) (ClutterEffect *effect);
gboolean (* modify_paint_volume) (ClutterEffect *effect,
ClutterPaintVolume *volume);
void (* paint) (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context,
ClutterEffectPaintFlags flags);
void (* paint_node) (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context,
ClutterEffectPaintFlags flags);
void (* pick) (ClutterEffect *effect,
ClutterPickContext *pick_context);
ClutterEffectPaintFlags flags);
/*< private >*/
void (* _clutter_effect4) (void);

View File

@ -14,9 +14,9 @@
GType
@enum_name@_get_type (void)
{
static size_t g_enum_type_id = 0;
static volatile gsize g_enum_type_id__volatile = 0;
if (g_once_init_enter (&g_enum_type_id))
if (g_once_init_enter (&g_enum_type_id__volatile))
{
static const G@Type@Value values[] = {
/*** END value-header ***/
@ -28,13 +28,14 @@ GType
/*** BEGIN value-tail ***/
{ 0, NULL, NULL }
};
GType id;
GType g_enum_type_id;
id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
g_enum_type_id =
g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
g_once_init_leave (&g_enum_type_id, id);
g_once_init_leave (&g_enum_type_id__volatile, g_enum_type_id);
}
return g_enum_type_id;
return g_enum_type_id__volatile;
}
/*** END value-tail ***/

View File

@ -127,7 +127,7 @@ typedef enum /*< prefix=CLUTTER_REQUEST >*/
* @CLUTTER_EASE_IN_OUT_QUAD: quadratic tweening, combininig
* %CLUTTER_EASE_IN_QUAD and %CLUTTER_EASE_OUT_QUAD
* @CLUTTER_EASE_IN_CUBIC: cubic tweening
* @CLUTTER_EASE_OUT_CUBIC: cubic tweening, inverse of
* @CLUTTER_EASE_OUT_CUBIC: cubic tweening, invers of
* %CLUTTER_EASE_IN_CUBIC
* @CLUTTER_EASE_IN_OUT_CUBIC: cubic tweening, combining
* %CLUTTER_EASE_IN_CUBIC and %CLUTTER_EASE_OUT_CUBIC
@ -190,7 +190,7 @@ typedef enum /*< prefix=CLUTTER_REQUEST >*/
* @CLUTTER_ANIMATION_LAST: last animation mode, used as a guard for
* registered global alpha functions
*
* The animation modes used by #ClutterAnimatable. This
* The animation modes used by #ClutterAlpha and #ClutterAnimation. This
* enumeration can be expanded in later versions of Clutter.
*
* <figure id="easing-modes">
@ -387,6 +387,44 @@ typedef enum
CLUTTER_MODIFIER_MASK = 0x5c001fff
} ClutterModifierType;
/**
* ClutterKeyboardA11yFlags:
* @CLUTTER_A11Y_KEYBOARD_ENABLED:
* @CLUTTER_A11Y_TIMEOUT_ENABLED:
* @CLUTTER_A11Y_MOUSE_KEYS_ENABLED:
* @CLUTTER_A11Y_SLOW_KEYS_ENABLED:
* @CLUTTER_A11Y_SLOW_KEYS_BEEP_PRESS:
* @CLUTTER_A11Y_SLOW_KEYS_BEEP_ACCEPT:
* @CLUTTER_A11Y_SLOW_KEYS_BEEP_REJECT:
* @CLUTTER_A11Y_BOUNCE_KEYS_ENABLED:
* @CLUTTER_A11Y_BOUNCE_KEYS_BEEP_REJECT:
* @CLUTTER_A11Y_TOGGLE_KEYS_ENABLED:
* @CLUTTER_A11Y_STICKY_KEYS_ENABLED:
* @CLUTTER_A11Y_STICKY_KEYS_TWO_KEY_OFF:
* @CLUTTER_A11Y_STICKY_KEYS_BEEP:
* @CLUTTER_A11Y_FEATURE_STATE_CHANGE_BEEP:
*
* Keyboard accessibility features applied to a ClutterInputDevice keyboard.
*
*/
typedef enum
{
CLUTTER_A11Y_KEYBOARD_ENABLED = 1 << 0,
CLUTTER_A11Y_TIMEOUT_ENABLED = 1 << 1,
CLUTTER_A11Y_MOUSE_KEYS_ENABLED = 1 << 2,
CLUTTER_A11Y_SLOW_KEYS_ENABLED = 1 << 3,
CLUTTER_A11Y_SLOW_KEYS_BEEP_PRESS = 1 << 4,
CLUTTER_A11Y_SLOW_KEYS_BEEP_ACCEPT = 1 << 5,
CLUTTER_A11Y_SLOW_KEYS_BEEP_REJECT = 1 << 6,
CLUTTER_A11Y_BOUNCE_KEYS_ENABLED = 1 << 7,
CLUTTER_A11Y_BOUNCE_KEYS_BEEP_REJECT = 1 << 8,
CLUTTER_A11Y_TOGGLE_KEYS_ENABLED = 1 << 9,
CLUTTER_A11Y_STICKY_KEYS_ENABLED = 1 << 10,
CLUTTER_A11Y_STICKY_KEYS_TWO_KEY_OFF = 1 << 11,
CLUTTER_A11Y_STICKY_KEYS_BEEP = 1 << 12,
CLUTTER_A11Y_FEATURE_STATE_CHANGE_BEEP = 1 << 13,
} ClutterKeyboardA11yFlags;
/**
* ClutterPointerA11yFlags:
* @CLUTTER_A11Y_POINTER_ENABLED:
@ -475,7 +513,7 @@ typedef enum {
* a toplevel, and all parents visible)
* @CLUTTER_ACTOR_REALIZED: the resources associated to the actor have been
* allocated
* @CLUTTER_ACTOR_REACTIVE: the actor 'reacts' to mouse events emitting event
* @CLUTTER_ACTOR_REACTIVE: the actor 'reacts' to mouse events emmitting event
* signals
* @CLUTTER_ACTOR_VISIBLE: the actor has been shown by the application program
* @CLUTTER_ACTOR_NO_LAYOUT: the actor provides an explicit layout management
@ -497,13 +535,9 @@ typedef enum /*< prefix=CLUTTER_ACTOR >*/
* ClutterOffscreenRedirect:
* @CLUTTER_OFFSCREEN_REDIRECT_AUTOMATIC_FOR_OPACITY: Only redirect
* the actor if it is semi-transparent and its has_overlaps()
* virtual returns %TRUE.
* virtual returns %TRUE. This is the default.
* @CLUTTER_OFFSCREEN_REDIRECT_ALWAYS: Always redirect the actor to an
* offscreen buffer even if it is fully opaque.
* @CLUTTER_OFFSCREEN_REDIRECT_ON_IDLE: Only redirect the actor if it is the
* most efficient thing to do based on its recent repaint behaviour. That
* means when its contents are changing less frequently than it's being used
* on stage.
*
* Possible flags to pass to clutter_actor_set_offscreen_redirect().
*
@ -511,11 +545,36 @@ typedef enum /*< prefix=CLUTTER_ACTOR >*/
*/
typedef enum /*< prefix=CLUTTER_OFFSCREEN_REDIRECT >*/
{
CLUTTER_OFFSCREEN_REDIRECT_AUTOMATIC_FOR_OPACITY = 1 << 0,
CLUTTER_OFFSCREEN_REDIRECT_ALWAYS = 1 << 1,
CLUTTER_OFFSCREEN_REDIRECT_ON_IDLE = 1 << 2
CLUTTER_OFFSCREEN_REDIRECT_AUTOMATIC_FOR_OPACITY = 1<<0,
CLUTTER_OFFSCREEN_REDIRECT_ALWAYS = 1<<1
} ClutterOffscreenRedirect;
/**
* ClutterAllocationFlags:
* @CLUTTER_ALLOCATION_NONE: No flag set
* @CLUTTER_ABSOLUTE_ORIGIN_CHANGED: Whether the absolute origin of the
* actor has changed; this implies that any ancestor of the actor has
* been moved.
* @CLUTTER_DELEGATE_LAYOUT: Whether the allocation should be delegated
* to the #ClutterLayoutManager instance stored inside the
* #ClutterActor:layout-manager property of #ClutterActor. This flag
* should only be used if you are subclassing #ClutterActor and
* overriding the #ClutterActorClass.allocate() virtual function, but
* you wish to use the default implementation of the virtual function
* inside #ClutterActor. Added in Clutter 1.10.
*
* Flags passed to the #ClutterActorClass.allocate() virtual function
* and to the clutter_actor_allocate() function.
*
* Since: 1.0
*/
typedef enum
{
CLUTTER_ALLOCATION_NONE = 0,
CLUTTER_ABSOLUTE_ORIGIN_CHANGED = 1 << 1,
CLUTTER_DELEGATE_LAYOUT = 1 << 2
} ClutterAllocationFlags;
/**
* ClutterAlignAxis:
* @CLUTTER_ALIGN_X_AXIS: Maintain the alignment on the X axis
@ -614,15 +673,12 @@ typedef enum /*< prefix=CLUTTER_BIND >*/
* has queued a redraw before this paint. This implies that the effect
* should call clutter_actor_continue_paint() to chain to the next
* effect and can not cache any results from a previous paint.
* @CLUTTER_EFFECT_PAINT_BYPASS_EFFECT: The effect should not be used
* on this frame, but it will be asked to paint the actor still.
*
* Flags passed to the paint or pick method of #ClutterEffect.
*/
typedef enum /*< prefix=CLUTTER_EFFECT_PAINT >*/
{
CLUTTER_EFFECT_PAINT_ACTOR_DIRTY = (1 << 0),
CLUTTER_EFFECT_PAINT_BYPASS_EFFECT = (1 << 1)
CLUTTER_EFFECT_PAINT_ACTOR_DIRTY = (1 << 0)
} ClutterEffectPaintFlags;
/**
@ -802,8 +858,7 @@ typedef enum /*< flags prefix=CLUTTER_EVENT >*/
CLUTTER_EVENT_NONE = 0,
CLUTTER_EVENT_FLAG_SYNTHETIC = 1 << 0,
CLUTTER_EVENT_FLAG_INPUT_METHOD = 1 << 1,
CLUTTER_EVENT_FLAG_REPEATED = 1 << 2,
CLUTTER_EVENT_FLAG_RELATIVE_MOTION = 1 << 3,
CLUTTER_EVENT_FLAG_REPEATED = 1 << 2
} ClutterEventFlags;
/**
@ -817,6 +872,10 @@ typedef enum /*< flags prefix=CLUTTER_EVENT >*/
* @CLUTTER_BUTTON_PRESS: Pointer button press event
* @CLUTTER_BUTTON_RELEASE: Pointer button release event
* @CLUTTER_SCROLL: Pointer scroll event
* @CLUTTER_STAGE_STATE: Stage state change event
* @CLUTTER_DESTROY_NOTIFY: Destroy notification event
* @CLUTTER_CLIENT_MESSAGE: Client message event
* @CLUTTER_DELETE: Stage delete event
* @CLUTTER_TOUCH_BEGIN: A new touch event sequence has started;
* event added in 1.10
* @CLUTTER_TOUCH_UPDATE: A touch event sequence has been updated;
@ -851,6 +910,10 @@ typedef enum /*< prefix=CLUTTER >*/
CLUTTER_BUTTON_PRESS,
CLUTTER_BUTTON_RELEASE,
CLUTTER_SCROLL,
CLUTTER_STAGE_STATE,
CLUTTER_DESTROY_NOTIFY,
CLUTTER_CLIENT_MESSAGE,
CLUTTER_DELETE,
CLUTTER_TOUCH_BEGIN,
CLUTTER_TOUCH_UPDATE,
CLUTTER_TOUCH_END,
@ -863,11 +926,6 @@ typedef enum /*< prefix=CLUTTER >*/
CLUTTER_PAD_BUTTON_RELEASE,
CLUTTER_PAD_STRIP,
CLUTTER_PAD_RING,
CLUTTER_DEVICE_ADDED,
CLUTTER_DEVICE_REMOVED,
CLUTTER_IM_COMMIT,
CLUTTER_IM_DELETE,
CLUTTER_IM_PREEDIT,
CLUTTER_EVENT_LAST /* helper */
} ClutterEventType;
@ -896,8 +954,24 @@ typedef enum /*< prefix=CLUTTER_SCROLL >*/
CLUTTER_SCROLL_SMOOTH
} ClutterScrollDirection;
/**
* ClutterStageState:
* @CLUTTER_STAGE_STATE_ACTIVATED: Activated mask
*
* Stage state masks, used by the #ClutterEvent of type %CLUTTER_STAGE_STATE.
*
* Since: 0.4
*/
typedef enum
{
CLUTTER_STAGE_STATE_ACTIVATED = (1 << 3)
} ClutterStageState;
/**
* ClutterFeatureFlags:
* @CLUTTER_FEATURE_SWAP_THROTTLE: Set if backend throttles buffer swaps.
* @CLUTTER_FEATURE_TEXTURE_YUV: Set if YUV based textures supported.
* @CLUTTER_FEATURE_TEXTURE_READ_PIXELS: Set if texture pixels can be read.
* @CLUTTER_FEATURE_STAGE_STATIC: Set if stage size if fixed (i.e framebuffer)
* @CLUTTER_FEATURE_STAGE_CURSOR: Set if stage has a graphical cursor.
* @CLUTTER_FEATURE_SHADERS_GLSL: Set if the backend supports GLSL shaders.
@ -912,6 +986,9 @@ typedef enum /*< prefix=CLUTTER_SCROLL >*/
*/
typedef enum
{
CLUTTER_FEATURE_SWAP_THROTTLE = (1 << 3),
CLUTTER_FEATURE_TEXTURE_YUV = (1 << 4),
CLUTTER_FEATURE_TEXTURE_READ_PIXELS = (1 << 5),
CLUTTER_FEATURE_STAGE_STATIC = (1 << 6),
CLUTTER_FEATURE_STAGE_CURSOR = (1 << 8),
CLUTTER_FEATURE_SHADERS_GLSL = (1 << 9),
@ -979,11 +1056,11 @@ typedef enum
/**
* ClutterInputMode:
* @CLUTTER_INPUT_MODE_LOGICAL: A logical, virtual device
* @CLUTTER_INPUT_MODE_PHYSICAL: A physical device, attached to
* a logical device
* @CLUTTER_INPUT_MODE_FLOATING: A physical device, not attached
* to a logical device
* @CLUTTER_INPUT_MODE_MASTER: A master, virtual device
* @CLUTTER_INPUT_MODE_SLAVE: A slave, physical device, attached to
* a master device
* @CLUTTER_INPUT_MODE_FLOATING: A slave, physical device, not attached
* to a master device
*
* The mode for input devices available.
*
@ -991,8 +1068,8 @@ typedef enum
*/
typedef enum
{
CLUTTER_INPUT_MODE_LOGICAL,
CLUTTER_INPUT_MODE_PHYSICAL,
CLUTTER_INPUT_MODE_MASTER,
CLUTTER_INPUT_MODE_SLAVE,
CLUTTER_INPUT_MODE_FLOATING
} ClutterInputMode;
@ -1032,20 +1109,6 @@ typedef enum
CLUTTER_INPUT_AXIS_LAST
} ClutterInputAxis;
typedef enum
{
CLUTTER_INPUT_AXIS_FLAG_NONE = 0,
CLUTTER_INPUT_AXIS_FLAG_X = 1 << CLUTTER_INPUT_AXIS_X,
CLUTTER_INPUT_AXIS_FLAG_Y = 1 << CLUTTER_INPUT_AXIS_Y,
CLUTTER_INPUT_AXIS_FLAG_PRESSURE = 1 << CLUTTER_INPUT_AXIS_PRESSURE,
CLUTTER_INPUT_AXIS_FLAG_XTILT = 1 << CLUTTER_INPUT_AXIS_XTILT,
CLUTTER_INPUT_AXIS_FLAG_YTILT = 1 << CLUTTER_INPUT_AXIS_YTILT,
CLUTTER_INPUT_AXIS_FLAG_WHEEL = 1 << CLUTTER_INPUT_AXIS_WHEEL,
CLUTTER_INPUT_AXIS_FLAG_DISTANCE = 1 << CLUTTER_INPUT_AXIS_DISTANCE,
CLUTTER_INPUT_AXIS_FLAG_ROTATION = 1 << CLUTTER_INPUT_AXIS_ROTATION,
CLUTTER_INPUT_AXIS_FLAG_SLIDER = 1 << CLUTTER_INPUT_AXIS_SLIDER,
} ClutterInputAxisFlags;
/**
* ClutterSnapEdge:
* @CLUTTER_SNAP_EDGE_TOP: the top edge
@ -1124,6 +1187,29 @@ typedef enum /*< prefix=CLUTTER_PAN >*/
CLUTTER_PAN_AXIS_AUTO
} ClutterPanAxis;
/**
* ClutterTableAlignment:
* @CLUTTER_TABLE_ALIGNMENT_START: Align the child to the top or to the
* left of a cell in the table, depending on the axis
* @CLUTTER_TABLE_ALIGNMENT_CENTER: Align the child to the center of
* a cell in the table
* @CLUTTER_TABLE_ALIGNMENT_END: Align the child to the bottom or to the
* right of a cell in the table, depending on the axis
*
* The alignment policies available on each axis of the #ClutterTableLayout
*
* Since: 1.4
*
* Deprecated: 1.22: Use the alignment properties of #ClutterActor
*/
typedef enum
{
CLUTTER_TABLE_ALIGNMENT_START,
CLUTTER_TABLE_ALIGNMENT_CENTER,
CLUTTER_TABLE_ALIGNMENT_END
} ClutterTableAlignment;
/**
* ClutterTextureFlags:
* @CLUTTER_TEXTURE_NONE: No flags
@ -1131,7 +1217,8 @@ typedef enum /*< prefix=CLUTTER_PAN >*/
* @CLUTTER_TEXTURE_RGB_FLAG_PREMULT: Unused flag
* @CLUTTER_TEXTURE_YUV_FLAG_YUV2: Unused flag
*
* Flags for clutter_texture_set_from_rgb_data().
* Flags for clutter_texture_set_from_rgb_data() and
* clutter_texture_set_from_yuv_data().
*
* Since: 0.4
*
@ -1159,7 +1246,7 @@ typedef enum /*< prefix=CLUTTER_TEXTURE >*/
*
* Since: 0.8
*
* Deprecated: 1.22: The #ClutterTexture class was the only user of
* Deprecated: 1.22: The #ClutterTexture class was the only used ot
* this API; use #ClutterImage and clutter_actor_set_content_scaling_filters()
* instead.
*/
@ -1276,6 +1363,8 @@ typedef enum
* painting the stages
* @CLUTTER_REPAINT_FLAGS_POST_PAINT: Run the repaint function after
* painting the stages
* @CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD: Ensure that a new frame
* is queued after adding the repaint function
*
* Flags to pass to clutter_threads_add_repaint_func_full().
*
@ -1285,6 +1374,7 @@ typedef enum
{
CLUTTER_REPAINT_FLAGS_PRE_PAINT = 1 << 0,
CLUTTER_REPAINT_FLAGS_POST_PAINT = 1 << 1,
CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD = 1 << 2
} ClutterRepaintFlags;
/**
@ -1595,10 +1685,9 @@ typedef enum
typedef enum
{
CLUTTER_PAD_FEATURE_BUTTON,
CLUTTER_PAD_FEATURE_RING,
CLUTTER_PAD_FEATURE_STRIP,
} ClutterInputDevicePadFeature;
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE,
CLUTTER_INPUT_DEVICE_MAPPING_RELATIVE,
} ClutterInputDeviceMapping;
typedef enum
{
@ -1638,12 +1727,6 @@ typedef enum
CLUTTER_INPUT_PANEL_STATE_TOGGLE,
} ClutterInputPanelState;
typedef enum
{
CLUTTER_PREEDIT_RESET_CLEAR,
CLUTTER_PREEDIT_RESET_COMMIT,
} ClutterPreeditResetMode;
G_END_DECLS
#endif /* __CLUTTER_ENUMS_H__ */

View File

@ -18,6 +18,7 @@ gboolean _clutter_event_process_filters (ClutterEvent *eve
/* clears the event queue inside the main context */
void _clutter_clear_events_queue (void);
void _clutter_clear_events_queue_for_stage (ClutterStage *stage);
CLUTTER_EXPORT
void _clutter_event_set_platform_data (ClutterEvent *event,

View File

@ -73,6 +73,8 @@ typedef struct _ClutterEventFilter {
gpointer user_data;
} ClutterEventFilter;
static GHashTable *all_events = NULL;
G_DEFINE_BOXED_TYPE (ClutterEvent, clutter_event,
clutter_event_copy,
clutter_event_free);
@ -94,6 +96,15 @@ G_DEFINE_BOXED_TYPE (ClutterEventSequence, clutter_event_sequence,
clutter_event_sequence_copy,
clutter_event_sequence_free);
static gboolean
is_event_allocated (const ClutterEvent *event)
{
if (all_events == NULL)
return FALSE;
return g_hash_table_lookup (all_events, event) != NULL;
}
/*
* _clutter_event_get_platform_data:
* @event: a #ClutterEvent
@ -107,6 +118,9 @@ G_DEFINE_BOXED_TYPE (ClutterEventSequence, clutter_event_sequence,
gpointer
_clutter_event_get_platform_data (const ClutterEvent *event)
{
if (!is_event_allocated (event))
return NULL;
return ((ClutterEventPrivate *) event)->platform_data;
}
@ -123,6 +137,9 @@ void
_clutter_event_set_platform_data (ClutterEvent *event,
gpointer data)
{
if (!is_event_allocated (event))
return;
((ClutterEventPrivate *) event)->platform_data = data;
}
@ -130,6 +147,9 @@ void
_clutter_event_set_pointer_emulated (ClutterEvent *event,
gboolean is_emulated)
{
if (!is_event_allocated (event))
return;
((ClutterEventPrivate *) event)->is_pointer_emulated = !!is_emulated;
}
@ -350,7 +370,7 @@ clutter_event_get_coords (const ClutterEvent *event,
gfloat *x,
gfloat *y)
{
graphene_point_t coords;
ClutterPoint coords;
g_return_if_fail (event != NULL);
@ -366,15 +386,15 @@ clutter_event_get_coords (const ClutterEvent *event,
/**
* clutter_event_get_position:
* @event: a #ClutterEvent
* @position: a #graphene_point_t
* @position: a #ClutterPoint
*
* Retrieves the event coordinates as a #graphene_point_t.
* Retrieves the event coordinates as a #ClutterPoint.
*
* Since: 1.12
*/
void
clutter_event_get_position (const ClutterEvent *event,
graphene_point_t *position)
ClutterPoint *position)
{
g_return_if_fail (event != NULL);
g_return_if_fail (position != NULL);
@ -384,6 +404,10 @@ clutter_event_get_position (const ClutterEvent *event,
case CLUTTER_NOTHING:
case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE:
case CLUTTER_STAGE_STATE:
case CLUTTER_DESTROY_NOTIFY:
case CLUTTER_CLIENT_MESSAGE:
case CLUTTER_DELETE:
case CLUTTER_EVENT_LAST:
case CLUTTER_PROXIMITY_IN:
case CLUTTER_PROXIMITY_OUT:
@ -391,47 +415,42 @@ clutter_event_get_position (const ClutterEvent *event,
case CLUTTER_PAD_BUTTON_RELEASE:
case CLUTTER_PAD_STRIP:
case CLUTTER_PAD_RING:
case CLUTTER_DEVICE_ADDED:
case CLUTTER_DEVICE_REMOVED:
case CLUTTER_IM_COMMIT:
case CLUTTER_IM_DELETE:
case CLUTTER_IM_PREEDIT:
graphene_point_init (position, 0.f, 0.f);
clutter_point_init (position, 0.f, 0.f);
break;
case CLUTTER_ENTER:
case CLUTTER_LEAVE:
graphene_point_init (position, event->crossing.x, event->crossing.y);
clutter_point_init (position, event->crossing.x, event->crossing.y);
break;
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
graphene_point_init (position, event->button.x, event->button.y);
clutter_point_init (position, event->button.x, event->button.y);
break;
case CLUTTER_MOTION:
graphene_point_init (position, event->motion.x, event->motion.y);
clutter_point_init (position, event->motion.x, event->motion.y);
break;
case CLUTTER_TOUCH_BEGIN:
case CLUTTER_TOUCH_UPDATE:
case CLUTTER_TOUCH_END:
case CLUTTER_TOUCH_CANCEL:
graphene_point_init (position, event->touch.x, event->touch.y);
clutter_point_init (position, event->touch.x, event->touch.y);
break;
case CLUTTER_SCROLL:
graphene_point_init (position, event->scroll.x, event->scroll.y);
clutter_point_init (position, event->scroll.x, event->scroll.y);
break;
case CLUTTER_TOUCHPAD_PINCH:
graphene_point_init (position, event->touchpad_pinch.x,
event->touchpad_pinch.y);
clutter_point_init (position, event->touchpad_pinch.x,
event->touchpad_pinch.y);
break;
case CLUTTER_TOUCHPAD_SWIPE:
graphene_point_init (position, event->touchpad_swipe.x,
event->touchpad_swipe.y);
clutter_point_init (position, event->touchpad_swipe.x,
event->touchpad_swipe.y);
break;
}
@ -459,6 +478,10 @@ clutter_event_set_coords (ClutterEvent *event,
case CLUTTER_NOTHING:
case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE:
case CLUTTER_STAGE_STATE:
case CLUTTER_DESTROY_NOTIFY:
case CLUTTER_CLIENT_MESSAGE:
case CLUTTER_DELETE:
case CLUTTER_EVENT_LAST:
case CLUTTER_PROXIMITY_IN:
case CLUTTER_PROXIMITY_OUT:
@ -466,11 +489,6 @@ clutter_event_set_coords (ClutterEvent *event,
case CLUTTER_PAD_BUTTON_RELEASE:
case CLUTTER_PAD_STRIP:
case CLUTTER_PAD_RING:
case CLUTTER_DEVICE_ADDED:
case CLUTTER_DEVICE_REMOVED:
case CLUTTER_IM_COMMIT:
case CLUTTER_IM_DELETE:
case CLUTTER_IM_PREEDIT:
break;
case CLUTTER_ENTER:
@ -697,6 +715,9 @@ clutter_event_set_scroll_delta (ClutterEvent *event,
g_return_if_fail (event != NULL);
g_return_if_fail (event->type == CLUTTER_SCROLL);
if (!is_event_allocated (event))
return;
event->scroll.direction = CLUTTER_SCROLL_SMOOTH;
((ClutterEventPrivate *) event)->delta_x = dx;
@ -727,8 +748,13 @@ clutter_event_get_scroll_delta (const ClutterEvent *event,
g_return_if_fail (event->type == CLUTTER_SCROLL);
g_return_if_fail (event->scroll.direction == CLUTTER_SCROLL_SMOOTH);
delta_x = ((ClutterEventPrivate *) event)->delta_x;
delta_y = ((ClutterEventPrivate *) event)->delta_y;
delta_x = delta_y = 0;
if (is_event_allocated (event))
{
delta_x = ((ClutterEventPrivate *) event)->delta_x;
delta_y = ((ClutterEventPrivate *) event)->delta_y;
}
if (dx != NULL)
*dx = delta_x;
@ -1002,6 +1028,29 @@ clutter_event_get_event_sequence (const ClutterEvent *event)
return NULL;
}
/**
* clutter_event_get_device_id:
* @event: a clutter event
*
* Retrieves the events device id if set.
*
* Return value: A unique identifier for the device or -1 if the event has
* no specific device set.
*/
gint
clutter_event_get_device_id (const ClutterEvent *event)
{
ClutterInputDevice *device = NULL;
g_return_val_if_fail (event != NULL, CLUTTER_POINTER_DEVICE);
device = clutter_event_get_device (event);
if (device != NULL)
return clutter_input_device_get_device_id (device);
return -1;
}
/**
* clutter_event_get_device_type:
* @event: a #ClutterEvent
@ -1040,20 +1089,24 @@ void
clutter_event_set_device (ClutterEvent *event,
ClutterInputDevice *device)
{
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
g_return_if_fail (event != NULL);
g_return_if_fail (device == NULL || CLUTTER_IS_INPUT_DEVICE (device));
g_set_object (&real_event->device, device);
if (is_event_allocated (event))
{
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
g_set_object (&real_event->device, device);
}
switch (event->type)
{
case CLUTTER_NOTHING:
case CLUTTER_STAGE_STATE:
case CLUTTER_DESTROY_NOTIFY:
case CLUTTER_CLIENT_MESSAGE:
case CLUTTER_DELETE:
case CLUTTER_EVENT_LAST:
case CLUTTER_IM_COMMIT:
case CLUTTER_IM_DELETE:
case CLUTTER_IM_PREEDIT:
break;
case CLUTTER_ENTER:
@ -1108,11 +1161,6 @@ clutter_event_set_device (ClutterEvent *event,
case CLUTTER_PAD_RING:
event->pad_ring.device = device;
break;
case CLUTTER_DEVICE_ADDED:
case CLUTTER_DEVICE_REMOVED:
event->device.device = device;
break;
}
}
@ -1137,19 +1185,24 @@ ClutterInputDevice *
clutter_event_get_device (const ClutterEvent *event)
{
ClutterInputDevice *device = NULL;
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
g_return_val_if_fail (event != NULL, NULL);
if (real_event->device != NULL)
return real_event->device;
if (is_event_allocated (event))
{
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
if (real_event->device != NULL)
return real_event->device;
}
switch (event->type)
{
case CLUTTER_NOTHING:
case CLUTTER_IM_COMMIT:
case CLUTTER_IM_DELETE:
case CLUTTER_IM_PREEDIT:
case CLUTTER_STAGE_STATE:
case CLUTTER_DESTROY_NOTIFY:
case CLUTTER_CLIENT_MESSAGE:
case CLUTTER_DELETE:
case CLUTTER_EVENT_LAST:
break;
@ -1205,11 +1258,6 @@ clutter_event_get_device (const ClutterEvent *event)
case CLUTTER_PAD_RING:
device = event->pad_ring.device;
break;
case CLUTTER_DEVICE_ADDED:
case CLUTTER_DEVICE_REMOVED:
device = event->device.device;
break;
}
return device;
@ -1228,11 +1276,14 @@ void
clutter_event_set_device_tool (ClutterEvent *event,
ClutterInputDeviceTool *tool)
{
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
g_return_if_fail (event != NULL);
real_event->tool = tool;
if (is_event_allocated (event))
{
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
real_event->tool = tool;
}
}
/**
@ -1248,11 +1299,16 @@ clutter_event_set_device_tool (ClutterEvent *event,
ClutterInputDeviceTool *
clutter_event_get_device_tool (const ClutterEvent *event)
{
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
g_return_val_if_fail (event != NULL, NULL);
return real_event->tool;
if (is_event_allocated (event))
{
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
return real_event->tool;
}
return NULL;
}
/**
@ -1269,11 +1325,16 @@ clutter_event_new (ClutterEventType type)
ClutterEvent *new_event;
ClutterEventPrivate *priv;
priv = g_new0 (ClutterEventPrivate, 1);
priv = g_slice_new0 (ClutterEventPrivate);
new_event = (ClutterEvent *) priv;
new_event->type = new_event->any.type = type;
if (G_UNLIKELY (all_events == NULL))
all_events = g_hash_table_new (NULL, NULL);
g_hash_table_replace (all_events, priv, GUINT_TO_POINTER (1));
return new_event;
}
@ -1290,7 +1351,8 @@ clutter_event_copy (const ClutterEvent *event)
{
ClutterEvent *new_event;
ClutterEventPrivate *new_real_event;
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
ClutterInputDevice *device;
gint n_axes = 0;
g_return_val_if_fail (event != NULL, NULL);
@ -1299,45 +1361,45 @@ clutter_event_copy (const ClutterEvent *event)
*new_event = *event;
g_set_object (&new_real_event->device, real_event->device);
g_set_object (&new_real_event->source_device, real_event->source_device);
new_real_event->delta_x = real_event->delta_x;
new_real_event->delta_y = real_event->delta_y;
new_real_event->is_pointer_emulated = real_event->is_pointer_emulated;
new_real_event->base_state = real_event->base_state;
new_real_event->button_state = real_event->button_state;
new_real_event->latched_state = real_event->latched_state;
new_real_event->locked_state = real_event->locked_state;
new_real_event->tool = real_event->tool;
if (is_event_allocated (event))
{
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
g_set_object (&new_real_event->device, real_event->device);
g_set_object (&new_real_event->source_device, real_event->source_device);
new_real_event->delta_x = real_event->delta_x;
new_real_event->delta_y = real_event->delta_y;
new_real_event->is_pointer_emulated = real_event->is_pointer_emulated;
new_real_event->base_state = real_event->base_state;
new_real_event->button_state = real_event->button_state;
new_real_event->latched_state = real_event->latched_state;
new_real_event->locked_state = real_event->locked_state;
new_real_event->tool = real_event->tool;
}
device = clutter_event_get_device (event);
if (device != NULL)
n_axes = clutter_input_device_get_n_axes (device);
switch (event->type)
{
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
if (event->button.axes != NULL)
{
new_event->button.axes =
g_memdup2 (event->button.axes,
sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
}
new_event->button.axes = g_memdup (event->button.axes,
sizeof (gdouble) * n_axes);
break;
case CLUTTER_SCROLL:
if (event->scroll.axes != NULL)
{
new_event->scroll.axes =
g_memdup2 (event->scroll.axes,
sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
}
new_event->scroll.axes = g_memdup (event->scroll.axes,
sizeof (gdouble) * n_axes);
break;
case CLUTTER_MOTION:
if (event->motion.axes != NULL)
{
new_event->motion.axes =
g_memdup2 (event->motion.axes,
sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
}
new_event->motion.axes = g_memdup (event->motion.axes,
sizeof (gdouble) * n_axes);
break;
case CLUTTER_TOUCH_BEGIN:
@ -1345,26 +1407,19 @@ clutter_event_copy (const ClutterEvent *event)
case CLUTTER_TOUCH_END:
case CLUTTER_TOUCH_CANCEL:
if (event->touch.axes != NULL)
{
new_event->touch.axes =
g_memdup2 (event->touch.axes,
sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
}
break;
case CLUTTER_DEVICE_ADDED:
case CLUTTER_DEVICE_REMOVED:
new_event->device.device = event->device.device;
break;
case CLUTTER_IM_COMMIT:
case CLUTTER_IM_PREEDIT:
new_event->im.text = g_strdup (event->im.text);
new_event->touch.axes = g_memdup (event->touch.axes,
sizeof (gdouble) * n_axes);
break;
default:
break;
}
if (is_event_allocated (event))
_clutter_backend_copy_event_data (clutter_get_default_backend (),
event,
new_event);
return new_event;
}
@ -1379,10 +1434,15 @@ clutter_event_free (ClutterEvent *event)
{
if (G_LIKELY (event != NULL))
{
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
_clutter_backend_free_event_data (clutter_get_default_backend (), event);
g_clear_object (&real_event->device);
g_clear_object (&real_event->source_device);
if (is_event_allocated (event))
{
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
g_clear_object (&real_event->device);
g_clear_object (&real_event->source_device);
}
switch (event->type)
{
@ -1406,16 +1466,12 @@ clutter_event_free (ClutterEvent *event)
g_free (event->touch.axes);
break;
case CLUTTER_IM_COMMIT:
case CLUTTER_IM_PREEDIT:
g_free (event->im.text);
break;
default:
break;
}
g_free ((ClutterEventPrivate *) event);
g_hash_table_remove (all_events, event);
g_slice_free (ClutterEventPrivate, (ClutterEventPrivate *) event);
}
}
@ -1433,11 +1489,40 @@ ClutterEvent *
clutter_event_get (void)
{
ClutterMainContext *context = _clutter_context_get_default ();
ClutterEvent *event;
event = g_async_queue_try_pop (context->events_queue);
if (context->events_queue == NULL)
return NULL;
return event;
if (g_queue_is_empty (context->events_queue))
return NULL;
return g_queue_pop_tail (context->events_queue);
}
/**
* clutter_event_peek:
*
* Returns a pointer to the first event from the event queue but
* does not remove it.
*
* Return value: (transfer none): A #ClutterEvent or NULL if queue empty.
*
* Since: 0.4
*/
ClutterEvent *
clutter_event_peek (void)
{
ClutterMainContext *context = _clutter_context_get_default ();
g_return_val_if_fail (context != NULL, NULL);
if (context->events_queue == NULL)
return NULL;
if (g_queue_is_empty (context->events_queue))
return NULL;
return g_queue_peek_tail (context->events_queue);
}
void
@ -1445,9 +1530,21 @@ _clutter_event_push (const ClutterEvent *event,
gboolean do_copy)
{
ClutterMainContext *context = _clutter_context_get_default ();
ClutterInputDevice *device;
g_assert (context != NULL);
if (context->events_queue == NULL)
context->events_queue = g_queue_new ();
/* disabled devices don't propagate events */
device = clutter_event_get_device (event);
if (device != NULL)
{
if (!clutter_input_device_get_enabled (device))
return;
}
if (do_copy)
{
ClutterEvent *copy;
@ -1456,8 +1553,7 @@ _clutter_event_push (const ClutterEvent *event,
event = copy;
}
g_async_queue_push (context->events_queue, (gpointer) event);
g_main_context_wakeup (NULL);
g_queue_push_head (context->events_queue, (gpointer) event);
}
/**
@ -1494,7 +1590,10 @@ clutter_events_pending (void)
g_return_val_if_fail (context != NULL, FALSE);
return g_async_queue_length (context->events_queue) > 0;
if (context->events_queue == NULL)
return FALSE;
return g_queue_is_empty (context->events_queue) == FALSE;
}
/**
@ -1564,6 +1663,9 @@ clutter_event_get_source_device (const ClutterEvent *event)
{
ClutterEventPrivate *real_event;
if (!is_event_allocated (event))
return NULL;
real_event = (ClutterEventPrivate *) event;
if (real_event->source_device != NULL)
@ -1592,6 +1694,9 @@ clutter_event_set_source_device (ClutterEvent *event,
g_return_if_fail (event != NULL);
g_return_if_fail (device == NULL || CLUTTER_IS_INPUT_DEVICE (device));
if (!is_event_allocated (event))
return;
real_event = (ClutterEventPrivate *) event;
g_set_object (&real_event->source_device, device);
}
@ -1612,10 +1717,15 @@ clutter_event_get_axes (const ClutterEvent *event,
guint *n_axes)
{
gdouble *retval = NULL;
guint len = 0;
switch (event->type)
{
case CLUTTER_NOTHING:
case CLUTTER_STAGE_STATE:
case CLUTTER_DESTROY_NOTIFY:
case CLUTTER_CLIENT_MESSAGE:
case CLUTTER_DELETE:
case CLUTTER_ENTER:
case CLUTTER_LEAVE:
case CLUTTER_KEY_PRESS:
@ -1623,8 +1733,6 @@ clutter_event_get_axes (const ClutterEvent *event,
case CLUTTER_EVENT_LAST:
case CLUTTER_PROXIMITY_IN:
case CLUTTER_PROXIMITY_OUT:
case CLUTTER_DEVICE_ADDED:
case CLUTTER_DEVICE_REMOVED:
break;
case CLUTTER_SCROLL:
@ -1653,14 +1761,22 @@ clutter_event_get_axes (const ClutterEvent *event,
case CLUTTER_PAD_BUTTON_RELEASE:
case CLUTTER_PAD_STRIP:
case CLUTTER_PAD_RING:
case CLUTTER_IM_COMMIT:
case CLUTTER_IM_DELETE:
case CLUTTER_IM_PREEDIT:
break;
}
if (retval != NULL)
{
ClutterInputDevice *device;
device = clutter_event_get_device (event);
if (device != NULL)
len = clutter_input_device_get_n_axes (device);
else
retval = NULL;
}
if (n_axes)
*n_axes = CLUTTER_INPUT_AXIS_LAST;
*n_axes = len;
return retval;
}
@ -1680,12 +1796,12 @@ float
clutter_event_get_distance (const ClutterEvent *source,
const ClutterEvent *target)
{
graphene_point_t p0, p1;
ClutterPoint p0, p1;
clutter_event_get_position (source, &p0);
clutter_event_get_position (source, &p1);
return graphene_point_distance (&p0, &p1, NULL, NULL);
return clutter_point_distance (&p0, &p1, NULL, NULL);
}
/**
@ -1706,17 +1822,17 @@ double
clutter_event_get_angle (const ClutterEvent *source,
const ClutterEvent *target)
{
graphene_point_t p0, p1;
ClutterPoint p0, p1;
float x_distance, y_distance;
double angle;
clutter_event_get_position (source, &p0);
clutter_event_get_position (target, &p1);
if (graphene_point_equal (&p0, &p1))
if (clutter_point_equals (&p0, &p1))
return 0;
graphene_point_distance (&p0, &p1, &x_distance, &y_distance);
clutter_point_distance (&p0, &p1, &x_distance, &y_distance);
angle = atan2 (x_distance, y_distance);
@ -1779,6 +1895,9 @@ clutter_event_is_pointer_emulated (const ClutterEvent *event)
{
g_return_val_if_fail (event != NULL, FALSE);
if (!is_event_allocated (event))
return FALSE;
return ((ClutterEventPrivate *) event)->is_pointer_emulated;
}
@ -1830,7 +1949,7 @@ clutter_event_add_filter (ClutterStage *stage,
gpointer user_data)
{
ClutterMainContext *context = _clutter_context_get_default ();
ClutterEventFilter *event_filter = g_new0 (ClutterEventFilter, 1);
ClutterEventFilter *event_filter = g_slice_new (ClutterEventFilter);
static guint event_filter_id = 0;
event_filter->stage = stage;
@ -1871,7 +1990,7 @@ clutter_event_remove_filter (guint id)
event_filter->notify (event_filter->user_data);
context->event_filters = g_list_delete_link (context->event_filters, l);
g_free (event_filter);
g_slice_free (ClutterEventFilter, event_filter);
return;
}
}
@ -2007,42 +2126,6 @@ clutter_event_get_gesture_motion_delta (const ClutterEvent *event,
}
}
/**
* clutter_event_get_gesture_motion_delta_unaccelerated:
* @event: A clutter touchpad gesture event
* @dx: (out) (allow-none): the displacement relative to the pointer
* position in the X axis, or %NULL
* @dy: (out) (allow-none): the displacement relative to the pointer
* position in the Y axis, or %NULL
*
* Returns the unaccelerated gesture motion deltas relative to the current
* pointer position. Unlike clutter_event_get_gesture_motion_delta(),
* pointer acceleration is ignored.
**/
void
clutter_event_get_gesture_motion_delta_unaccelerated (const ClutterEvent *event,
gdouble *dx,
gdouble *dy)
{
g_return_if_fail (event != NULL);
g_return_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH ||
event->type == CLUTTER_TOUCHPAD_SWIPE);
if (event->type == CLUTTER_TOUCHPAD_PINCH)
{
if (dx)
*dx = event->touchpad_pinch.dx_unaccel;
if (dy)
*dy = event->touchpad_pinch.dy_unaccel;
}
else if (event->type == CLUTTER_TOUCHPAD_SWIPE)
{
if (dx)
*dx = event->touchpad_swipe.dx_unaccel;
if (dy)
*dy = event->touchpad_swipe.dy_unaccel;
}
}
/**
* clutter_event_get_scroll_source:
* @event: an scroll event
@ -2078,9 +2161,9 @@ clutter_event_get_scroll_source (const ClutterEvent *event)
ClutterScrollFinishFlags
clutter_event_get_scroll_finish_flags (const ClutterEvent *event)
{
g_return_val_if_fail (event != NULL, CLUTTER_SCROLL_FINISHED_NONE);
g_return_val_if_fail (event != NULL, CLUTTER_SCROLL_SOURCE_UNKNOWN);
g_return_val_if_fail (event->type == CLUTTER_SCROLL,
CLUTTER_SCROLL_FINISHED_NONE);
CLUTTER_SCROLL_SOURCE_UNKNOWN);
return event->scroll.finish_flags;
}
@ -2163,58 +2246,3 @@ clutter_event_get_pad_event_details (const ClutterEvent *event,
return TRUE;
}
uint32_t
clutter_event_get_event_code (const ClutterEvent *event)
{
if (event->type == CLUTTER_KEY_PRESS ||
event->type == CLUTTER_KEY_RELEASE)
return event->key.evdev_code;
else if (event->type == CLUTTER_BUTTON_PRESS ||
event->type == CLUTTER_BUTTON_RELEASE)
return event->button.evdev_code;
return 0;
}
int32_t
clutter_event_sequence_get_slot (const ClutterEventSequence *sequence)
{
g_return_val_if_fail (sequence != NULL, -1);
return GPOINTER_TO_INT (sequence) - 1;
}
int64_t
clutter_event_get_time_us (const ClutterEvent *event)
{
if (event->type == CLUTTER_MOTION)
return event->motion.time_us;
return 0;
}
gboolean
clutter_event_get_relative_motion (const ClutterEvent *event,
double *dx,
double *dy,
double *dx_unaccel,
double *dy_unaccel)
{
if (event->type == CLUTTER_MOTION &&
event->motion.flags & CLUTTER_EVENT_FLAG_RELATIVE_MOTION)
{
if (dx)
*dx = event->motion.dx;
if (dy)
*dy = event->motion.dy;
if (dx_unaccel)
*dx_unaccel = event->motion.dx_unaccel;
if (dy_unaccel)
*dy_unaccel = event->motion.dy_unaccel;
return TRUE;
}
else
return FALSE;
}

View File

@ -112,6 +112,7 @@ typedef struct _ClutterButtonEvent ClutterButtonEvent;
typedef struct _ClutterKeyEvent ClutterKeyEvent;
typedef struct _ClutterMotionEvent ClutterMotionEvent;
typedef struct _ClutterScrollEvent ClutterScrollEvent;
typedef struct _ClutterStageStateEvent ClutterStageStateEvent;
typedef struct _ClutterCrossingEvent ClutterCrossingEvent;
typedef struct _ClutterTouchEvent ClutterTouchEvent;
typedef struct _ClutterTouchpadPinchEvent ClutterTouchpadPinchEvent;
@ -120,8 +121,6 @@ typedef struct _ClutterProximityEvent ClutterProximityEvent;
typedef struct _ClutterPadButtonEvent ClutterPadButtonEvent;
typedef struct _ClutterPadStripEvent ClutterPadStripEvent;
typedef struct _ClutterPadRingEvent ClutterPadRingEvent;
typedef struct _ClutterDeviceEvent ClutterDeviceEvent;
typedef struct _ClutterIMEvent ClutterIMEvent;
/**
* ClutterAnyEvent:
@ -173,7 +172,6 @@ struct _ClutterKeyEvent
guint keyval;
guint16 hardware_keycode;
gunichar unicode_value;
uint32_t evdev_code;
ClutterInputDevice *device;
};
@ -217,7 +215,6 @@ struct _ClutterButtonEvent
guint click_count;
gdouble *axes; /* Future use */
ClutterInputDevice *device;
uint32_t evdev_code;
};
/**
@ -307,12 +304,6 @@ struct _ClutterMotionEvent
ClutterModifierType modifier_state;
gdouble *axes; /* Future use */
ClutterInputDevice *device;
int64_t time_us;
double dx;
double dy;
double dx_unaccel;
double dy_unaccel;
};
/**
@ -354,6 +345,32 @@ struct _ClutterScrollEvent
ClutterScrollFinishFlags finish_flags;
};
/**
* ClutterStageStateEvent:
* @type: event type
* @time: event time
* @flags: event flags
* @stage: event source stage
* @source: event source actor (unused)
* @changed_mask: bitwise OR of the changed flags
* @new_state: bitwise OR of the current state flags
*
* Event signalling a change in the #ClutterStage state.
*
* Since: 0.2
*/
struct _ClutterStageStateEvent
{
ClutterEventType type;
guint32 time;
ClutterEventFlags flags;
ClutterStage *stage;
ClutterActor *source; /* XXX: should probably be the stage itself */
ClutterStageState changed_mask;
ClutterStageState new_state;
};
/**
* ClutterTouchEvent:
* @type: event type
@ -414,10 +431,6 @@ struct _ClutterTouchEvent
* @y: the Y coordinate of the pointer, relative to the stage
* @dx: movement delta of the pinch focal point in the X axis
* @dy: movement delta of the pinch focal point in the Y axis
* @dx_unaccel: unaccelerated movement delta of the pinch focal
* point in the X axis
* @dy_unaccel: unaccelerated movement delta of the pinch focal
* point in the Y axis
* @angle_delta: angle delta in degrees, clockwise rotations are
* represented by positive deltas
* @scale: the current scale
@ -445,8 +458,6 @@ struct _ClutterTouchpadPinchEvent
gfloat y;
gfloat dx;
gfloat dy;
gfloat dx_unaccel;
gfloat dy_unaccel;
gfloat angle_delta;
gfloat scale;
guint n_fingers;
@ -463,12 +474,8 @@ struct _ClutterTouchpadPinchEvent
* @n_fingers: the number of fingers triggering the swipe
* @x: the X coordinate of the pointer, relative to the stage
* @y: the Y coordinate of the pointer, relative to the stage
* @dx: movement delta of the swipe center point in the X axis
* @dy: movement delta of the swipe center point in the Y axis
* @dx_unaccel: unaccelerated movement delta of the swipe center
* point in the X axis
* @dy_unaccel: unaccelerated movement delta of the swipe center
* point in the Y axis
* @dx: movement delta of the pinch focal point in the X axis
* @dy: movement delta of the pinch focal point in the Y axis
*
* Used for touchpad swipe gesture events. The current state of the
* gesture will be determined by the @phase field.
@ -489,8 +496,6 @@ struct _ClutterTouchpadSwipeEvent
gfloat y;
gfloat dx;
gfloat dy;
gfloat dx_unaccel;
gfloat dy_unaccel;
};
struct _ClutterPadButtonEvent
@ -539,31 +544,6 @@ struct _ClutterPadRingEvent
guint32 mode;
};
struct _ClutterDeviceEvent
{
ClutterEventType type;
guint32 time;
ClutterEventFlags flags;
ClutterStage *stage;
ClutterActor *source;
ClutterInputDevice *device;
};
struct _ClutterIMEvent
{
ClutterEventType type;
uint32_t time;
ClutterEventFlags flags;
ClutterStage *stage;
ClutterActor *source;
char *text;
int32_t offset;
uint32_t len;
ClutterPreeditResetMode mode;
};
/**
* ClutterEvent:
*
@ -581,6 +561,7 @@ union _ClutterEvent
ClutterKeyEvent key;
ClutterMotionEvent motion;
ClutterScrollEvent scroll;
ClutterStageStateEvent stage_state;
ClutterCrossingEvent crossing;
ClutterTouchEvent touch;
ClutterTouchpadPinchEvent touchpad_pinch;
@ -589,8 +570,6 @@ union _ClutterEvent
ClutterPadButtonEvent pad_button;
ClutterPadStripEvent pad_strip;
ClutterPadRingEvent pad_ring;
ClutterDeviceEvent device;
ClutterIMEvent im;
};
/**
@ -622,6 +601,8 @@ gboolean clutter_events_pending (void);
CLUTTER_EXPORT
ClutterEvent * clutter_event_get (void);
CLUTTER_EXPORT
ClutterEvent * clutter_event_peek (void);
CLUTTER_EXPORT
void clutter_event_put (const ClutterEvent *event);
CLUTTER_EXPORT
@ -692,6 +673,8 @@ void clutter_event_set_stage (ClutterEvent
CLUTTER_EXPORT
ClutterStage * clutter_event_get_stage (const ClutterEvent *event);
CLUTTER_EXPORT
gint clutter_event_get_device_id (const ClutterEvent *event);
CLUTTER_EXPORT
ClutterInputDeviceType clutter_event_get_device_type (const ClutterEvent *event);
CLUTTER_EXPORT
void clutter_event_set_coords (ClutterEvent *event,
@ -703,7 +686,7 @@ void clutter_event_get_coords (const ClutterEv
gfloat *y);
CLUTTER_EXPORT
void clutter_event_get_position (const ClutterEvent *event,
graphene_point_t *position);
ClutterPoint *position);
CLUTTER_EXPORT
float clutter_event_get_distance (const ClutterEvent *source,
const ClutterEvent *target);
@ -790,11 +773,6 @@ void clutter_event_get_gesture_motion_delta (const Clut
gdouble *dx,
gdouble *dy);
CLUTTER_EXPORT
void clutter_event_get_gesture_motion_delta_unaccelerated (const ClutterEvent *event,
gdouble *dx,
gdouble *dy);
CLUTTER_EXPORT
ClutterScrollSource clutter_event_get_scroll_source (const ClutterEvent *event);
@ -809,20 +787,6 @@ gboolean clutter_event_get_pad_event_details (const Clut
guint *number,
guint *mode,
gdouble *value);
CLUTTER_EXPORT
uint32_t clutter_event_get_event_code (const ClutterEvent *event);
CLUTTER_EXPORT
int32_t clutter_event_sequence_get_slot (const ClutterEventSequence *sequence);
CLUTTER_EXPORT
int64_t clutter_event_get_time_us (const ClutterEvent *event);
CLUTTER_EXPORT
gboolean clutter_event_get_relative_motion (const ClutterEvent *event,
double *dx,
double *dy,
double *dx_unaccel,
double *dy_unaccel);
G_END_DECLS

View File

@ -33,6 +33,8 @@
*
* It is possible to ask whether Clutter has support for specific features at
* run-time.
*
* See also cogl_get_features() and #CoglFeatureFlags
*/
#include "clutter-build-config.h"
@ -58,13 +60,20 @@ typedef struct ClutterFeatures
static ClutterFeatures* __features = NULL;
static ClutterFeatureFlags
clutter_features_from_cogl (void)
clutter_features_from_cogl (guint cogl_flags)
{
ClutterFeatureFlags clutter_flags = 0;
if (cogl_flags & COGL_FEATURE_TEXTURE_YUV)
clutter_flags |= CLUTTER_FEATURE_TEXTURE_YUV;
if (cogl_flags & COGL_FEATURE_TEXTURE_READ_PIXELS)
clutter_flags |= CLUTTER_FEATURE_TEXTURE_READ_PIXELS;
clutter_flags |= CLUTTER_FEATURE_SHADERS_GLSL;
clutter_flags |= CLUTTER_FEATURE_OFFSCREEN;
if (cogl_flags & COGL_FEATURE_OFFSCREEN)
clutter_flags |= CLUTTER_FEATURE_OFFSCREEN;
return clutter_flags;
}
@ -92,7 +101,7 @@ _clutter_feature_init (GError **error)
if (!_clutter_backend_create_context (context->backend, error))
return FALSE;
__features->flags = (clutter_features_from_cogl ()
__features->flags = (clutter_features_from_cogl (cogl_get_features ())
| _clutter_backend_get_features (context->backend));
__features->features_set = TRUE;

View File

@ -131,7 +131,8 @@ clutter_fixed_layout_get_preferred_height (ClutterLayoutManager *manager,
static void
clutter_fixed_layout_allocate (ClutterLayoutManager *manager,
ClutterContainer *container,
const ClutterActorBox *allocation)
const ClutterActorBox *allocation,
ClutterAllocationFlags flags)
{
ClutterActor *child;
@ -139,11 +140,7 @@ clutter_fixed_layout_allocate (ClutterLayoutManager *manager,
child != NULL;
child = clutter_actor_get_next_sibling (child))
{
float x = 0.f;
float y = 0.f;
clutter_actor_get_fixed_position (child, &x, &y);
clutter_actor_allocate_preferred_size (child, x, y);
clutter_actor_allocate_preferred_size (child, flags);
}
}

View File

@ -566,7 +566,8 @@ clutter_flow_layout_get_preferred_height (ClutterLayoutManager *manager,
static void
clutter_flow_layout_allocate (ClutterLayoutManager *manager,
ClutterContainer *container,
const ClutterActorBox *allocation)
const ClutterActorBox *allocation,
ClutterAllocationFlags flags)
{
ClutterFlowLayoutPrivate *priv = CLUTTER_FLOW_LAYOUT (manager)->priv;
ClutterActor *actor, *child;
@ -728,7 +729,7 @@ clutter_flow_layout_allocate (ClutterLayoutManager *manager,
child_alloc.y1 = ceil (item_y);
child_alloc.x2 = ceil (child_alloc.x1 + item_width);
child_alloc.y2 = ceil (child_alloc.y1 + item_height);
clutter_actor_allocate (child, &child_alloc);
clutter_actor_allocate (child, &child_alloc, flags);
if (priv->orientation == CLUTTER_FLOW_HORIZONTAL)
item_x = new_x;
@ -913,7 +914,7 @@ clutter_flow_layout_class_init (ClutterFlowLayoutClass *klass)
* ClutterFlowLayout:orientation:
*
* The orientation of the #ClutterFlowLayout. The children
* of the layout will be laid out following the orientation.
* of the layout will be layed out following the orientation.
*
* This property also controls the overflowing directions
*

View File

@ -1,843 +0,0 @@
/*
* Copyright (C) 2019 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "clutter-build-config.h"
#include "clutter/clutter-frame-clock.h"
#include "clutter/clutter-debug.h"
#include "clutter/clutter-main.h"
#include "clutter/clutter-private.h"
#include "clutter/clutter-timeline-private.h"
#include "cogl/cogl-trace.h"
enum
{
DESTROY,
N_SIGNALS
};
static guint signals[N_SIGNALS];
/* An estimate queue holds several int64_t values. Adding a new value to the
* queue overwrites the oldest value.
*/
#define ESTIMATE_QUEUE_LENGTH 16
typedef struct _EstimateQueue
{
int64_t values[ESTIMATE_QUEUE_LENGTH];
int next_index;
} EstimateQueue;
/* When heuristic render time is off,
* wait 2ms after vblank before starting to draw next frame.
*/
#define SYNC_DELAY_FALLBACK_US ms2us (2)
typedef struct _ClutterFrameListener
{
const ClutterFrameListenerIface *iface;
gpointer user_data;
} ClutterFrameListener;
typedef struct _ClutterClockSource
{
GSource source;
ClutterFrameClock *frame_clock;
} ClutterClockSource;
typedef enum _ClutterFrameClockState
{
CLUTTER_FRAME_CLOCK_STATE_INIT,
CLUTTER_FRAME_CLOCK_STATE_IDLE,
CLUTTER_FRAME_CLOCK_STATE_SCHEDULED,
CLUTTER_FRAME_CLOCK_STATE_DISPATCHING,
CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED,
} ClutterFrameClockState;
struct _ClutterFrameClock
{
GObject parent;
float refresh_rate;
int64_t refresh_interval_us;
ClutterFrameListener listener;
GSource *source;
int64_t frame_count;
ClutterFrameClockState state;
int64_t last_dispatch_time_us;
int64_t last_dispatch_lateness_us;
int64_t last_presentation_time_us;
gboolean is_next_presentation_time_valid;
int64_t next_presentation_time_us;
/* Buffer must be submitted to KMS and GPU rendering must be finished
* this amount of time before the next presentation time.
*/
int64_t vblank_duration_us;
/* Last KMS buffer submission time. */
int64_t last_flip_time_us;
/* Last few durations between dispatch start and buffer swap. */
EstimateQueue dispatch_to_swap_us;
/* Last few durations between buffer swap and GPU rendering finish. */
EstimateQueue swap_to_rendering_done_us;
/* Last few durations between buffer swap and KMS submission. */
EstimateQueue swap_to_flip_us;
/* If we got new measurements last frame. */
gboolean got_measurements_last_frame;
gboolean pending_reschedule;
gboolean pending_reschedule_now;
int inhibit_count;
GList *timelines;
};
G_DEFINE_TYPE (ClutterFrameClock, clutter_frame_clock,
G_TYPE_OBJECT)
static void
estimate_queue_add_value (EstimateQueue *queue,
int64_t value)
{
queue->values[queue->next_index] = value;
queue->next_index = (queue->next_index + 1) % ESTIMATE_QUEUE_LENGTH;
}
float
clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock)
{
return frame_clock->refresh_rate;
}
static void
clutter_frame_clock_set_refresh_rate (ClutterFrameClock *frame_clock,
float refresh_rate)
{
frame_clock->refresh_rate = refresh_rate;
frame_clock->refresh_interval_us =
(int64_t) (0.5 + G_USEC_PER_SEC / refresh_rate);
}
void
clutter_frame_clock_add_timeline (ClutterFrameClock *frame_clock,
ClutterTimeline *timeline)
{
gboolean is_first;
if (g_list_find (frame_clock->timelines, timeline))
return;
is_first = !frame_clock->timelines;
frame_clock->timelines = g_list_prepend (frame_clock->timelines, timeline);
if (is_first)
clutter_frame_clock_schedule_update (frame_clock);
}
void
clutter_frame_clock_remove_timeline (ClutterFrameClock *frame_clock,
ClutterTimeline *timeline)
{
frame_clock->timelines = g_list_remove (frame_clock->timelines, timeline);
}
static void
advance_timelines (ClutterFrameClock *frame_clock,
int64_t time_us)
{
GList *timelines;
GList *l;
/* we protect ourselves from timelines being removed during
* the advancement by other timelines by copying the list of
* timelines, taking a reference on them, iterating over the
* copied list and then releasing the reference.
*
* we cannot simply take a reference on the timelines and still
* use the list held by the master clock because the do_tick()
* might result in the creation of a new timeline, which gets
* added at the end of the list with no reference increase and
* thus gets disposed at the end of the iteration.
*
* this implies that a newly added timeline will not be advanced
* by this clock iteration, which is perfectly fine since we're
* in its first cycle.
*
* we also cannot steal the frame clock timelines list because
* a timeline might be removed as the direct result of do_tick()
* and remove_timeline() would not find the timeline, failing
* and leaving a dangling pointer behind.
*/
timelines = g_list_copy (frame_clock->timelines);
g_list_foreach (timelines, (GFunc) g_object_ref, NULL);
for (l = timelines; l; l = l->next)
{
ClutterTimeline *timeline = l->data;
_clutter_timeline_do_tick (timeline, time_us / 1000);
}
g_list_free_full (timelines, g_object_unref);
}
static void
maybe_reschedule_update (ClutterFrameClock *frame_clock)
{
if (frame_clock->pending_reschedule ||
frame_clock->timelines)
{
frame_clock->pending_reschedule = FALSE;
if (frame_clock->pending_reschedule_now)
{
frame_clock->pending_reschedule_now = FALSE;
clutter_frame_clock_schedule_update_now (frame_clock);
}
else
{
clutter_frame_clock_schedule_update (frame_clock);
}
}
}
void
clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
ClutterFrameInfo *frame_info)
{
frame_clock->last_presentation_time_us = frame_info->presentation_time;
frame_clock->got_measurements_last_frame = FALSE;
if (frame_info->cpu_time_before_buffer_swap_us != 0 &&
frame_info->gpu_rendering_duration_ns != 0)
{
int64_t dispatch_to_swap_us, swap_to_rendering_done_us, swap_to_flip_us;
dispatch_to_swap_us =
frame_info->cpu_time_before_buffer_swap_us -
frame_clock->last_dispatch_time_us;
swap_to_rendering_done_us =
frame_info->gpu_rendering_duration_ns / 1000;
swap_to_flip_us =
frame_clock->last_flip_time_us -
frame_info->cpu_time_before_buffer_swap_us;
CLUTTER_NOTE (FRAME_TIMINGS,
"dispatch2swap %ld µs, swap2render %ld µs, swap2flip %ld µs",
dispatch_to_swap_us,
swap_to_rendering_done_us,
swap_to_flip_us);
estimate_queue_add_value (&frame_clock->dispatch_to_swap_us,
dispatch_to_swap_us);
estimate_queue_add_value (&frame_clock->swap_to_rendering_done_us,
swap_to_rendering_done_us);
estimate_queue_add_value (&frame_clock->swap_to_flip_us,
swap_to_flip_us);
frame_clock->got_measurements_last_frame = TRUE;
}
if (frame_info->refresh_rate > 1)
{
clutter_frame_clock_set_refresh_rate (frame_clock,
frame_info->refresh_rate);
}
switch (frame_clock->state)
{
case CLUTTER_FRAME_CLOCK_STATE_INIT:
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
g_warn_if_reached ();
break;
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
maybe_reschedule_update (frame_clock);
break;
}
}
void
clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock)
{
switch (frame_clock->state)
{
case CLUTTER_FRAME_CLOCK_STATE_INIT:
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
g_warn_if_reached ();
break;
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
maybe_reschedule_update (frame_clock);
break;
}
}
static int64_t
clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock)
{
int64_t refresh_interval_us;
int64_t max_dispatch_to_swap_us = 0;
int64_t max_swap_to_rendering_done_us = 0;
int64_t max_swap_to_flip_us = 0;
int64_t max_render_time_us;
int i;
refresh_interval_us =
(int64_t) (0.5 + G_USEC_PER_SEC / frame_clock->refresh_rate);
if (!frame_clock->got_measurements_last_frame ||
G_UNLIKELY (clutter_paint_debug_flags &
CLUTTER_DEBUG_DISABLE_DYNAMIC_MAX_RENDER_TIME))
return refresh_interval_us - SYNC_DELAY_FALLBACK_US;
for (i = 0; i < ESTIMATE_QUEUE_LENGTH; ++i)
{
max_dispatch_to_swap_us =
MAX (max_dispatch_to_swap_us,
frame_clock->dispatch_to_swap_us.values[i]);
max_swap_to_rendering_done_us =
MAX (max_swap_to_rendering_done_us,
frame_clock->swap_to_rendering_done_us.values[i]);
max_swap_to_flip_us =
MAX (max_swap_to_flip_us,
frame_clock->swap_to_flip_us.values[i]);
}
/* Max render time shows how early the frame clock needs to be dispatched
* to make it to the predicted next presentation time. It is composed of:
* - An estimate of duration from dispatch start to buffer swap.
* - Maximum between estimates of duration from buffer swap to GPU rendering
* finish and duration from buffer swap to buffer submission to KMS. This
* is because both of these things need to happen before the vblank, and
* they are done in parallel.
* - Duration of the vblank.
* - A constant to account for variations in the above estimates.
*/
max_render_time_us =
max_dispatch_to_swap_us +
MAX (max_swap_to_rendering_done_us, max_swap_to_flip_us) +
frame_clock->vblank_duration_us +
clutter_max_render_time_constant_us;
max_render_time_us = CLAMP (max_render_time_us, 0, refresh_interval_us);
return max_render_time_us;
}
static void
calculate_next_update_time_us (ClutterFrameClock *frame_clock,
int64_t *out_next_update_time_us,
int64_t *out_next_presentation_time_us)
{
int64_t last_presentation_time_us;
int64_t now_us;
int64_t refresh_interval_us;
int64_t min_render_time_allowed_us;
int64_t max_render_time_allowed_us;
int64_t last_next_presentation_time_us;
int64_t time_since_last_next_presentation_time_us;
int64_t next_presentation_time_us;
int64_t next_update_time_us;
now_us = g_get_monotonic_time ();
refresh_interval_us = frame_clock->refresh_interval_us;
if (frame_clock->last_presentation_time_us == 0)
{
*out_next_update_time_us =
frame_clock->last_dispatch_time_us ?
((frame_clock->last_dispatch_time_us -
frame_clock->last_dispatch_lateness_us) + refresh_interval_us) :
now_us;
*out_next_presentation_time_us = 0;
return;
}
min_render_time_allowed_us = refresh_interval_us / 2;
max_render_time_allowed_us =
clutter_frame_clock_compute_max_render_time_us (frame_clock);
if (min_render_time_allowed_us > max_render_time_allowed_us)
min_render_time_allowed_us = max_render_time_allowed_us;
/*
* The common case is that the next presentation happens 1 refresh interval
* after the last presentation:
*
* last_presentation_time_us
* / next_presentation_time_us
* / /
* / /
* |--|--o----|-------|--> presentation times
* | | \ |
* | | now_us
* | \______/
* | refresh_interval_us
* |
* 0
*
*/
last_presentation_time_us = frame_clock->last_presentation_time_us;
next_presentation_time_us = last_presentation_time_us + refresh_interval_us;
/*
* However, the last presentation could have happened more than a frame ago.
* For example, due to idling (nothing on screen changed, so no need to
* redraw) or due to frames missing deadlines (GPU busy with heavy rendering).
* The following code adjusts next_presentation_time_us to be in the future,
* but still aligned to display presentation times. Instead of
* next presentation = last presentation + 1 * refresh interval, it will be
* next presentation = last presentation + N * refresh interval.
*/
if (next_presentation_time_us < now_us)
{
int64_t presentation_phase_us;
int64_t current_phase_us;
int64_t current_refresh_interval_start_us;
/*
* Let's say we're just past next_presentation_time_us.
*
* First, we compute presentation_phase_us. Real presentation times don't
* have to be exact multiples of refresh_interval_us and
* presentation_phase_us represents this difference. Next, we compute
* current phase and the refresh interval start corresponding to now_us.
* Finally, add presentation_phase_us and a refresh interval to get the
* next presentation after now_us.
*
* last_presentation_time_us
* / next_presentation_time_us
* / / now_us
* / / / new next_presentation_time_us
* |--|-------|---o---|-------|--> presentation times
* | __|
* | |presentation_phase_us
* | |
* | | now_us - presentation_phase_us
* | | /
* |-------|---o---|-------|-----> integer multiples of refresh_interval_us
* | \__/
* | |current_phase_us
* | \
* | current_refresh_interval_start_us
* 0
*
*/
presentation_phase_us = last_presentation_time_us % refresh_interval_us;
current_phase_us = (now_us - presentation_phase_us) % refresh_interval_us;
current_refresh_interval_start_us =
now_us - presentation_phase_us - current_phase_us;
next_presentation_time_us =
current_refresh_interval_start_us +
presentation_phase_us +
refresh_interval_us;
}
/*
* Skip one interval if we got an early presented event.
*
* last frame this was last_presentation_time
* / frame_clock->next_presentation_time_us
* / /
* |---|-o-----|-x----->
* | \
* \ next_presentation_time_us is thus right after the last one
* but got an unexpected early presentation
* \_/
* time_since_last_next_presentation_time_us
*
*/
last_next_presentation_time_us = frame_clock->next_presentation_time_us;
time_since_last_next_presentation_time_us =
next_presentation_time_us - last_next_presentation_time_us;
if (frame_clock->is_next_presentation_time_valid &&
time_since_last_next_presentation_time_us < (refresh_interval_us / 2))
{
next_presentation_time_us =
frame_clock->next_presentation_time_us + refresh_interval_us;
}
while (next_presentation_time_us < now_us + min_render_time_allowed_us)
next_presentation_time_us += refresh_interval_us;
next_update_time_us = next_presentation_time_us - max_render_time_allowed_us;
*out_next_update_time_us = next_update_time_us;
*out_next_presentation_time_us = next_presentation_time_us;
}
void
clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock)
{
frame_clock->inhibit_count++;
if (frame_clock->inhibit_count == 1)
{
switch (frame_clock->state)
{
case CLUTTER_FRAME_CLOCK_STATE_INIT:
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
break;
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
frame_clock->pending_reschedule = TRUE;
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
break;
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
break;
}
g_source_set_ready_time (frame_clock->source, -1);
}
}
void
clutter_frame_clock_uninhibit (ClutterFrameClock *frame_clock)
{
g_return_if_fail (frame_clock->inhibit_count > 0);
frame_clock->inhibit_count--;
if (frame_clock->inhibit_count == 0)
maybe_reschedule_update (frame_clock);
}
void
clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock)
{
int64_t next_update_time_us = -1;
if (frame_clock->inhibit_count > 0)
{
frame_clock->pending_reschedule = TRUE;
frame_clock->pending_reschedule_now = TRUE;
return;
}
switch (frame_clock->state)
{
case CLUTTER_FRAME_CLOCK_STATE_INIT:
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
next_update_time_us = g_get_monotonic_time ();
break;
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
return;
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
frame_clock->pending_reschedule = TRUE;
frame_clock->pending_reschedule_now = TRUE;
return;
}
g_warn_if_fail (next_update_time_us != -1);
g_source_set_ready_time (frame_clock->source, next_update_time_us);
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
frame_clock->is_next_presentation_time_valid = FALSE;
}
void
clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
{
int64_t next_update_time_us = -1;
if (frame_clock->inhibit_count > 0)
{
frame_clock->pending_reschedule = TRUE;
return;
}
switch (frame_clock->state)
{
case CLUTTER_FRAME_CLOCK_STATE_INIT:
next_update_time_us = g_get_monotonic_time ();
break;
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
calculate_next_update_time_us (frame_clock,
&next_update_time_us,
&frame_clock->next_presentation_time_us);
frame_clock->is_next_presentation_time_valid =
(frame_clock->next_presentation_time_us != 0);
break;
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
return;
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
frame_clock->pending_reschedule = TRUE;
return;
}
g_warn_if_fail (next_update_time_us != -1);
g_source_set_ready_time (frame_clock->source, next_update_time_us);
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
}
static void
clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
int64_t time_us)
{
int64_t frame_count;
ClutterFrameResult result;
int64_t ideal_dispatch_time_us, lateness_us;
COGL_TRACE_BEGIN_SCOPED (ClutterFrameClockDispatch, "Frame Clock (dispatch)");
ideal_dispatch_time_us = (frame_clock->last_dispatch_time_us -
frame_clock->last_dispatch_lateness_us) +
frame_clock->refresh_interval_us;
lateness_us = time_us - ideal_dispatch_time_us;
if (lateness_us < 0 || lateness_us >= frame_clock->refresh_interval_us)
frame_clock->last_dispatch_lateness_us = 0;
else
frame_clock->last_dispatch_lateness_us = lateness_us;
frame_clock->last_dispatch_time_us = time_us;
g_source_set_ready_time (frame_clock->source, -1);
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHING;
frame_count = frame_clock->frame_count++;
COGL_TRACE_BEGIN (ClutterFrameClockEvents, "Frame Clock (before frame)");
if (frame_clock->listener.iface->before_frame)
{
frame_clock->listener.iface->before_frame (frame_clock,
frame_count,
frame_clock->listener.user_data);
}
COGL_TRACE_END (ClutterFrameClockEvents);
COGL_TRACE_BEGIN (ClutterFrameClockTimelines, "Frame Clock (timelines)");
advance_timelines (frame_clock, time_us);
COGL_TRACE_END (ClutterFrameClockTimelines);
COGL_TRACE_BEGIN (ClutterFrameClockFrame, "Frame Clock (frame)");
result = frame_clock->listener.iface->frame (frame_clock,
frame_count,
time_us,
frame_clock->listener.user_data);
COGL_TRACE_END (ClutterFrameClockFrame);
switch (frame_clock->state)
{
case CLUTTER_FRAME_CLOCK_STATE_INIT:
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
g_warn_if_reached ();
break;
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
break;
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
switch (result)
{
case CLUTTER_FRAME_RESULT_PENDING_PRESENTED:
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED;
break;
case CLUTTER_FRAME_RESULT_IDLE:
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
maybe_reschedule_update (frame_clock);
break;
}
break;
}
}
static gboolean
frame_clock_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
ClutterClockSource *clock_source = (ClutterClockSource *) source;
ClutterFrameClock *frame_clock = clock_source->frame_clock;
int64_t dispatch_time_us;
dispatch_time_us = g_source_get_time (source);
clutter_frame_clock_dispatch (frame_clock, dispatch_time_us);
return G_SOURCE_CONTINUE;
}
void
clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock,
int64_t flip_time_us)
{
frame_clock->last_flip_time_us = flip_time_us;
}
GString *
clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock)
{
int64_t max_dispatch_to_swap_us = 0;
int64_t max_swap_to_rendering_done_us = 0;
int64_t max_swap_to_flip_us = 0;
int i;
GString *string;
string = g_string_new (NULL);
g_string_append_printf (string, "Max render time: %ld µs",
clutter_frame_clock_compute_max_render_time_us (frame_clock));
if (frame_clock->got_measurements_last_frame)
g_string_append_printf (string, " =");
else
g_string_append_printf (string, " (no measurements last frame)");
for (i = 0; i < ESTIMATE_QUEUE_LENGTH; ++i)
{
max_dispatch_to_swap_us =
MAX (max_dispatch_to_swap_us,
frame_clock->dispatch_to_swap_us.values[i]);
max_swap_to_rendering_done_us =
MAX (max_swap_to_rendering_done_us,
frame_clock->swap_to_rendering_done_us.values[i]);
max_swap_to_flip_us =
MAX (max_swap_to_flip_us,
frame_clock->swap_to_flip_us.values[i]);
}
g_string_append_printf (string, "\nVblank duration: %ld µs +",
frame_clock->vblank_duration_us);
g_string_append_printf (string, "\nDispatch to swap: %ld µs +",
max_dispatch_to_swap_us);
g_string_append_printf (string, "\nmax(Swap to rendering done: %ld µs,",
max_swap_to_rendering_done_us);
g_string_append_printf (string, "\nSwap to flip: %ld µs) +",
max_swap_to_flip_us);
g_string_append_printf (string, "\nConstant: %d µs",
clutter_max_render_time_constant_us);
return string;
}
static GSourceFuncs frame_clock_source_funcs = {
NULL,
NULL,
frame_clock_source_dispatch,
NULL
};
static void
init_frame_clock_source (ClutterFrameClock *frame_clock)
{
GSource *source;
ClutterClockSource *clock_source;
g_autofree char *name = NULL;
source = g_source_new (&frame_clock_source_funcs, sizeof (ClutterClockSource));
clock_source = (ClutterClockSource *) source;
name = g_strdup_printf ("Clutter frame clock (%p)", frame_clock);
g_source_set_name (source, name);
g_source_set_priority (source, CLUTTER_PRIORITY_REDRAW);
g_source_set_can_recurse (source, FALSE);
clock_source->frame_clock = frame_clock;
frame_clock->source = source;
g_source_attach (source, NULL);
}
ClutterFrameClock *
clutter_frame_clock_new (float refresh_rate,
int64_t vblank_duration_us,
const ClutterFrameListenerIface *iface,
gpointer user_data)
{
ClutterFrameClock *frame_clock;
g_assert_cmpfloat (refresh_rate, >, 0.0);
frame_clock = g_object_new (CLUTTER_TYPE_FRAME_CLOCK, NULL);
frame_clock->listener.iface = iface;
frame_clock->listener.user_data = user_data;
init_frame_clock_source (frame_clock);
clutter_frame_clock_set_refresh_rate (frame_clock, refresh_rate);
frame_clock->vblank_duration_us = vblank_duration_us;
return frame_clock;
}
void
clutter_frame_clock_destroy (ClutterFrameClock *frame_clock)
{
g_object_run_dispose (G_OBJECT (frame_clock));
g_object_unref (frame_clock);
}
static void
clutter_frame_clock_dispose (GObject *object)
{
ClutterFrameClock *frame_clock = CLUTTER_FRAME_CLOCK (object);
if (frame_clock->source)
{
g_signal_emit (frame_clock, signals[DESTROY], 0);
g_source_destroy (frame_clock->source);
g_clear_pointer (&frame_clock->source, g_source_unref);
}
G_OBJECT_CLASS (clutter_frame_clock_parent_class)->dispose (object);
}
static void
clutter_frame_clock_init (ClutterFrameClock *frame_clock)
{
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_INIT;
}
static void
clutter_frame_clock_class_init (ClutterFrameClockClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = clutter_frame_clock_dispose;
signals[DESTROY] =
g_signal_new (I_("destroy"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE,
0);
}

View File

@ -1,99 +0,0 @@
/*
* Copyright (C) 2019 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CLUTTER_FRAME_CLOCK_H
#define CLUTTER_FRAME_CLOCK_H
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#include <glib.h>
#include <glib-object.h>
#include <stdint.h>
#include "clutter/clutter-types.h"
typedef enum _ClutterFrameResult
{
CLUTTER_FRAME_RESULT_PENDING_PRESENTED,
CLUTTER_FRAME_RESULT_IDLE,
} ClutterFrameResult;
#define CLUTTER_TYPE_FRAME_CLOCK (clutter_frame_clock_get_type ())
CLUTTER_EXPORT
G_DECLARE_FINAL_TYPE (ClutterFrameClock, clutter_frame_clock,
CLUTTER, FRAME_CLOCK,
GObject)
/**
* ClutterFrameListenerIface: (skip)
*/
typedef struct _ClutterFrameListenerIface
{
void (* before_frame) (ClutterFrameClock *frame_clock,
int64_t frame_count,
gpointer user_data);
ClutterFrameResult (* frame) (ClutterFrameClock *frame_clock,
int64_t frame_count,
int64_t time_us,
gpointer user_data);
} ClutterFrameListenerIface;
CLUTTER_EXPORT
ClutterFrameClock * clutter_frame_clock_new (float refresh_rate,
int64_t vblank_duration_us,
const ClutterFrameListenerIface *iface,
gpointer user_data);
CLUTTER_EXPORT
void clutter_frame_clock_destroy (ClutterFrameClock *frame_clock);
CLUTTER_EXPORT
void clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
ClutterFrameInfo *frame_info);
CLUTTER_EXPORT
void clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock);
CLUTTER_EXPORT
void clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock);
CLUTTER_EXPORT
void clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock);
CLUTTER_EXPORT
void clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock);
CLUTTER_EXPORT
void clutter_frame_clock_uninhibit (ClutterFrameClock *frame_clock);
void clutter_frame_clock_add_timeline (ClutterFrameClock *frame_clock,
ClutterTimeline *timeline);
void clutter_frame_clock_remove_timeline (ClutterFrameClock *frame_clock,
ClutterTimeline *timeline);
CLUTTER_EXPORT
float clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock);
void clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock,
int64_t flip_time_us);
GString * clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock);
#endif /* CLUTTER_FRAME_CLOCK_H */

View File

@ -1,33 +0,0 @@
/*
* Copyright (C) 2020 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CLUTTER_FRAME_PRIVATE_H
#define CLUTTER_FRAME_PRIVATE_H
#include "clutter/clutter-frame.h"
struct _ClutterFrame
{
gboolean has_result;
ClutterFrameResult result;
};
#define CLUTTER_FRAME_INIT ((ClutterFrame) { 0 })
ClutterFrameResult clutter_frame_get_result (ClutterFrame *frame);
#endif /* CLUTTER_FRAME_PRIVATE_H */

View File

@ -1,42 +0,0 @@
/*
* Copyright (C) 2020 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "clutter/clutter-frame-private.h"
ClutterFrameResult
clutter_frame_get_result (ClutterFrame *frame)
{
g_return_val_if_fail (frame->has_result, CLUTTER_FRAME_RESULT_IDLE);
return frame->result;
}
gboolean
clutter_frame_has_result (ClutterFrame *frame)
{
return frame->has_result;
}
void
clutter_frame_set_result (ClutterFrame *frame,
ClutterFrameResult result)
{
g_warn_if_fail (!frame->has_result);
frame->result = result;
frame->has_result = TRUE;
}

View File

@ -118,7 +118,7 @@ struct _ClutterGestureActionPrivate
gint requested_nb_points;
GArray *points;
gulong actor_capture_id;
guint actor_capture_id;
gulong stage_capture_id;
ClutterGestureTriggerEdge edge;
@ -157,8 +157,7 @@ G_DEFINE_TYPE_WITH_PRIVATE (ClutterGestureAction, clutter_gesture_action, CLUTTE
static GesturePoint *
gesture_register_point (ClutterGestureAction *action, ClutterEvent *event)
{
ClutterGestureActionPrivate *priv =
clutter_gesture_action_get_instance_private (action);
ClutterGestureActionPrivate *priv = action->priv;
GesturePoint *point = NULL;
if (priv->points->len >= MAX_GESTURE_POINTS)
@ -191,8 +190,7 @@ gesture_find_point (ClutterGestureAction *action,
ClutterEvent *event,
gint *position)
{
ClutterGestureActionPrivate *priv =
clutter_gesture_action_get_instance_private (action);
ClutterGestureActionPrivate *priv = action->priv;
GesturePoint *point = NULL;
ClutterEventType type = clutter_event_type (event);
ClutterInputDevice *device = clutter_event_get_device (event);
@ -222,10 +220,9 @@ gesture_find_point (ClutterGestureAction *action,
static void
gesture_unregister_point (ClutterGestureAction *action, gint position)
{
ClutterGestureActionPrivate *priv =
clutter_gesture_action_get_instance_private (action);
ClutterGestureActionPrivate *priv = action->priv;
if (priv->points->len == 0)
if (action->priv->points->len == 0)
return;
g_array_remove_index (priv->points, position);
@ -306,26 +303,28 @@ gesture_point_unset (GesturePoint *point)
static void
cancel_gesture (ClutterGestureAction *action)
{
ClutterGestureActionPrivate *priv =
clutter_gesture_action_get_instance_private (action);
ClutterGestureActionPrivate *priv = action->priv;
ClutterActor *actor;
priv->in_gesture = FALSE;
g_clear_signal_handler (&priv->stage_capture_id, priv->stage);
if (priv->stage_capture_id != 0)
{
g_signal_handler_disconnect (priv->stage, priv->stage_capture_id);
priv->stage_capture_id = 0;
}
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
g_signal_emit (action, gesture_signals[GESTURE_CANCEL], 0, actor);
g_array_set_size (priv->points, 0);
g_array_set_size (action->priv->points, 0);
}
static gboolean
begin_gesture (ClutterGestureAction *action,
ClutterActor *actor)
{
ClutterGestureActionPrivate *priv =
clutter_gesture_action_get_instance_private (action);
ClutterGestureActionPrivate *priv = action->priv;
gboolean return_value;
priv->in_gesture = TRUE;
@ -358,8 +357,7 @@ stage_captured_event_cb (ClutterActor *stage,
ClutterEvent *event,
ClutterGestureAction *action)
{
ClutterGestureActionPrivate *priv =
clutter_gesture_action_get_instance_private (action);
ClutterGestureActionPrivate *priv = action->priv;
ClutterActor *actor;
gint position;
float threshold_x, threshold_y;
@ -416,10 +414,12 @@ stage_captured_event_cb (ClutterActor *stage,
return CLUTTER_EVENT_PROPAGATE;
}
gesture_update_motion_point (point, event);
if (!begin_gesture (action, actor))
return CLUTTER_EVENT_PROPAGATE;
{
if ((point = gesture_find_point (action, event, &position)) != NULL)
gesture_update_motion_point (point, event);
return CLUTTER_EVENT_PROPAGATE;
}
if ((point = gesture_find_point (action, event, &position)) == NULL)
return CLUTTER_EVENT_PROPAGATE;
@ -481,8 +481,11 @@ stage_captured_event_cb (ClutterActor *stage,
break;
}
if (priv->points->len == 0)
g_clear_signal_handler (&priv->stage_capture_id, priv->stage);
if (priv->points->len == 0 && priv->stage_capture_id)
{
g_signal_handler_disconnect (priv->stage, priv->stage_capture_id);
priv->stage_capture_id = 0;
}
return CLUTTER_EVENT_PROPAGATE;
}
@ -492,8 +495,7 @@ actor_captured_event_cb (ClutterActor *actor,
ClutterEvent *event,
ClutterGestureAction *action)
{
ClutterGestureActionPrivate *priv =
clutter_gesture_action_get_instance_private (action);
ClutterGestureActionPrivate *priv = action->priv;
GesturePoint *point G_GNUC_UNUSED;
if ((clutter_event_type (event) != CLUTTER_BUTTON_PRESS) &&
@ -527,8 +529,7 @@ static void
clutter_gesture_action_set_actor (ClutterActorMeta *meta,
ClutterActor *actor)
{
ClutterGestureActionPrivate *priv =
clutter_gesture_action_get_instance_private (CLUTTER_GESTURE_ACTION (meta));
ClutterGestureActionPrivate *priv = CLUTTER_GESTURE_ACTION (meta)->priv;
ClutterActorMetaClass *meta_class =
CLUTTER_ACTOR_META_CLASS (clutter_gesture_action_parent_class);
@ -537,7 +538,7 @@ clutter_gesture_action_set_actor (ClutterActorMeta *meta,
ClutterActor *old_actor = clutter_actor_meta_get_actor (meta);
if (old_actor != NULL)
g_clear_signal_handler (&priv->actor_capture_id, old_actor);
g_signal_handler_disconnect (old_actor, priv->actor_capture_id);
priv->actor_capture_id = 0;
}
@ -545,7 +546,7 @@ clutter_gesture_action_set_actor (ClutterActorMeta *meta,
if (priv->stage_capture_id != 0)
{
if (priv->stage != NULL)
g_clear_signal_handler (&priv->stage_capture_id, priv->stage);
g_signal_handler_disconnect (priv->stage, priv->stage_capture_id);
priv->stage_capture_id = 0;
priv->stage = NULL;
@ -562,27 +563,6 @@ clutter_gesture_action_set_actor (ClutterActorMeta *meta,
meta_class->set_actor (meta, actor);
}
static void
clutter_gesture_action_set_enabled (ClutterActorMeta *meta,
gboolean is_enabled)
{
ClutterActorMetaClass *meta_class =
CLUTTER_ACTOR_META_CLASS (clutter_gesture_action_parent_class);
ClutterGestureAction *gesture_action = CLUTTER_GESTURE_ACTION (meta);
ClutterGestureActionPrivate *priv =
clutter_gesture_action_get_instance_private (gesture_action);
if (!is_enabled)
{
if (priv->in_gesture)
cancel_gesture (gesture_action);
else
g_array_set_size (priv->points, 0);
}
meta_class->set_enabled (meta, is_enabled);
}
static gboolean
default_event_handler (ClutterGestureAction *action,
ClutterActor *actor)
@ -597,8 +577,6 @@ clutter_gesture_action_set_property (GObject *gobject,
GParamSpec *pspec)
{
ClutterGestureAction *self = CLUTTER_GESTURE_ACTION (gobject);
ClutterGestureActionPrivate *priv =
clutter_gesture_action_get_instance_private (self);
switch (prop_id)
{
@ -611,15 +589,11 @@ clutter_gesture_action_set_property (GObject *gobject,
break;
case PROP_THRESHOLD_TRIGGER_DISTANCE_X:
clutter_gesture_action_set_threshold_trigger_distance (self,
g_value_get_float (value),
priv->distance_y);
clutter_gesture_action_set_threshold_trigger_distance (self, g_value_get_float (value), self->priv->distance_y);
break;
case PROP_THRESHOLD_TRIGGER_DISTANCE_Y:
clutter_gesture_action_set_threshold_trigger_distance (self,
priv->distance_x,
g_value_get_float (value));
clutter_gesture_action_set_threshold_trigger_distance (self, self->priv->distance_x, g_value_get_float (value));
break;
default:
@ -634,29 +608,28 @@ clutter_gesture_action_get_property (GObject *gobject,
GValue *value,
GParamSpec *pspec)
{
ClutterGestureActionPrivate *priv =
clutter_gesture_action_get_instance_private (CLUTTER_GESTURE_ACTION (gobject));
ClutterGestureAction *self = CLUTTER_GESTURE_ACTION (gobject);
switch (prop_id)
{
case PROP_N_TOUCH_POINTS:
g_value_set_int (value, priv->requested_nb_points);
g_value_set_int (value, self->priv->requested_nb_points);
break;
case PROP_THRESHOLD_TRIGGER_EDGE:
g_value_set_enum (value, priv->edge);
g_value_set_enum (value, self->priv->edge);
break;
case PROP_THRESHOLD_TRIGGER_DISTANCE_X:
if (priv->distance_x > 0.0)
g_value_set_float (value, priv->distance_x);
if (self->priv->distance_x > 0.0)
g_value_set_float (value, self->priv->distance_x);
else
g_value_set_float (value, gesture_get_default_threshold ());
break;
case PROP_THRESHOLD_TRIGGER_DISTANCE_Y:
if (priv->distance_y > 0.0)
g_value_set_float (value, priv->distance_y);
if (self->priv->distance_y > 0.0)
g_value_set_float (value, self->priv->distance_y);
else
g_value_set_float (value, gesture_get_default_threshold ());
break;
@ -670,8 +643,7 @@ clutter_gesture_action_get_property (GObject *gobject,
static void
clutter_gesture_action_finalize (GObject *gobject)
{
ClutterGestureActionPrivate *priv =
clutter_gesture_action_get_instance_private (CLUTTER_GESTURE_ACTION (gobject));
ClutterGestureActionPrivate *priv = CLUTTER_GESTURE_ACTION (gobject)->priv;
g_array_unref (priv->points);
@ -689,7 +661,6 @@ clutter_gesture_action_class_init (ClutterGestureActionClass *klass)
gobject_class->get_property = clutter_gesture_action_get_property;
meta_class->set_actor = clutter_gesture_action_set_actor;
meta_class->set_enabled = clutter_gesture_action_set_enabled;
klass->gesture_begin = default_event_handler;
klass->gesture_progress = default_event_handler;
@ -863,14 +834,13 @@ clutter_gesture_action_class_init (ClutterGestureActionClass *klass)
static void
clutter_gesture_action_init (ClutterGestureAction *self)
{
ClutterGestureActionPrivate *priv =
clutter_gesture_action_get_instance_private (self);
self->priv = clutter_gesture_action_get_instance_private (self);
priv->points = g_array_sized_new (FALSE, TRUE, sizeof (GesturePoint), 3);
g_array_set_clear_func (priv->points, (GDestroyNotify) gesture_point_unset);
self->priv->points = g_array_sized_new (FALSE, TRUE, sizeof (GesturePoint), 3);
g_array_set_clear_func (self->priv->points, (GDestroyNotify) gesture_point_unset);
priv->requested_nb_points = 1;
priv->edge = CLUTTER_GESTURE_TRIGGER_EDGE_NONE;
self->priv->requested_nb_points = 1;
self->priv->edge = CLUTTER_GESTURE_TRIGGER_EDGE_NONE;
}
/**
@ -909,21 +879,16 @@ clutter_gesture_action_get_press_coords (ClutterGestureAction *action,
gfloat *press_x,
gfloat *press_y)
{
ClutterGestureActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
priv = clutter_gesture_action_get_instance_private (action);
g_return_if_fail (priv->points->len > point);
g_return_if_fail (action->priv->points->len > point);
if (press_x)
*press_x = g_array_index (priv->points,
*press_x = g_array_index (action->priv->points,
GesturePoint,
point).press_x;
if (press_y)
*press_y = g_array_index (priv->points,
*press_y = g_array_index (action->priv->points,
GesturePoint,
point).press_y;
}
@ -949,21 +914,16 @@ clutter_gesture_action_get_motion_coords (ClutterGestureAction *action,
gfloat *motion_x,
gfloat *motion_y)
{
ClutterGestureActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
priv = clutter_gesture_action_get_instance_private (action);
g_return_if_fail (priv->points->len > point);
g_return_if_fail (action->priv->points->len > point);
if (motion_x)
*motion_x = g_array_index (priv->points,
*motion_x = g_array_index (action->priv->points,
GesturePoint,
point).last_motion_x;
if (motion_y)
*motion_y = g_array_index (priv->points,
*motion_y = g_array_index (action->priv->points,
GesturePoint,
point).last_motion_y;
}
@ -991,19 +951,15 @@ clutter_gesture_action_get_motion_delta (ClutterGestureAction *action,
gfloat *delta_x,
gfloat *delta_y)
{
ClutterGestureActionPrivate *priv;
gfloat d_x, d_y;
g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0);
g_return_val_if_fail (action->priv->points->len > point, 0);
priv = clutter_gesture_action_get_instance_private (action);
g_return_val_if_fail (priv->points->len > point, 0);
d_x = g_array_index (priv->points,
d_x = g_array_index (action->priv->points,
GesturePoint,
point).last_delta_x;
d_y = g_array_index (priv->points,
d_y = g_array_index (action->priv->points,
GesturePoint,
point).last_delta_y;
@ -1037,21 +993,16 @@ clutter_gesture_action_get_release_coords (ClutterGestureAction *action,
gfloat *release_x,
gfloat *release_y)
{
ClutterGestureActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
priv = clutter_gesture_action_get_instance_private (action);
g_return_if_fail (priv->points->len > point);
g_return_if_fail (action->priv->points->len > point);
if (release_x)
*release_x = g_array_index (priv->points,
*release_x = g_array_index (action->priv->points,
GesturePoint,
point).release_x;
if (release_y)
*release_y = g_array_index (priv->points,
*release_y = g_array_index (action->priv->points,
GesturePoint,
point).release_y;
}
@ -1077,20 +1028,16 @@ clutter_gesture_action_get_velocity (ClutterGestureAction *action,
gfloat *velocity_x,
gfloat *velocity_y)
{
ClutterGestureActionPrivate *priv;
gfloat d_x, d_y, distance, velocity;
gint64 d_t;
g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0);
priv = clutter_gesture_action_get_instance_private (action);
g_return_val_if_fail (priv->points->len > point, 0);
g_return_val_if_fail (action->priv->points->len > point, 0);
distance = clutter_gesture_action_get_motion_delta (action, point,
&d_x, &d_y);
d_t = g_array_index (priv->points,
d_t = g_array_index (action->priv->points,
GesturePoint,
point).last_delta_time;
@ -1117,13 +1064,9 @@ clutter_gesture_action_get_velocity (ClutterGestureAction *action,
gint
clutter_gesture_action_get_n_touch_points (ClutterGestureAction *action)
{
ClutterGestureActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0);
priv = clutter_gesture_action_get_instance_private (action);
return priv->requested_nb_points;
return action->priv->requested_nb_points;
}
/**
@ -1144,7 +1087,7 @@ clutter_gesture_action_set_n_touch_points (ClutterGestureAction *action,
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
g_return_if_fail (nb_points >= 1);
priv = clutter_gesture_action_get_instance_private (action);
priv = action->priv;
if (priv->requested_nb_points == nb_points)
return;
@ -1198,13 +1141,9 @@ clutter_gesture_action_set_n_touch_points (ClutterGestureAction *action,
guint
clutter_gesture_action_get_n_current_points (ClutterGestureAction *action)
{
ClutterGestureActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0);
priv = clutter_gesture_action_get_instance_private (action);
return priv->points->len;
return action->priv->points->len;
}
/**
@ -1222,15 +1161,10 @@ ClutterEventSequence *
clutter_gesture_action_get_sequence (ClutterGestureAction *action,
guint point)
{
ClutterGestureActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), NULL);
g_return_val_if_fail (action->priv->points->len > point, NULL);
priv = clutter_gesture_action_get_instance_private (action);
g_return_val_if_fail (priv->points->len > point, NULL);
return g_array_index (priv->points, GesturePoint, point).sequence;
return g_array_index (action->priv->points, GesturePoint, point).sequence;
}
/**
@ -1249,15 +1183,10 @@ ClutterInputDevice *
clutter_gesture_action_get_device (ClutterGestureAction *action,
guint point)
{
ClutterGestureActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), NULL);
g_return_val_if_fail (action->priv->points->len > point, NULL);
priv = clutter_gesture_action_get_instance_private (action);
g_return_val_if_fail (priv->points->len > point, NULL);
return g_array_index (priv->points, GesturePoint, point).device;
return g_array_index (action->priv->points, GesturePoint, point).device;
}
/**
@ -1277,15 +1206,11 @@ clutter_gesture_action_get_last_event (ClutterGestureAction *action,
guint point)
{
GesturePoint *gesture_point;
ClutterGestureActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), NULL);
g_return_val_if_fail (action->priv->points->len > point, NULL);
priv = clutter_gesture_action_get_instance_private (action);
g_return_val_if_fail (priv->points->len > point, NULL);
gesture_point = &g_array_index (priv->points, GesturePoint, point);
gesture_point = &g_array_index (action->priv->points, GesturePoint, point);
return gesture_point->last_event;
}
@ -1322,16 +1247,12 @@ void
clutter_gesture_action_set_threshold_trigger_edge (ClutterGestureAction *action,
ClutterGestureTriggerEdge edge)
{
ClutterGestureActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
priv = clutter_gesture_action_get_instance_private (action);
if (priv->edge == edge)
if (action->priv->edge == edge)
return;
priv->edge = edge;
action->priv->edge = edge;
g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_EDGE]);
}
@ -1350,14 +1271,10 @@ clutter_gesture_action_set_threshold_trigger_edge (ClutterGestureAction *ac
ClutterGestureTriggerEdge
clutter_gesture_action_get_threshold_trigger_edge (ClutterGestureAction *action)
{
ClutterGestureActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action),
CLUTTER_GESTURE_TRIGGER_EDGE_NONE);
priv = clutter_gesture_action_get_instance_private (action);
return priv->edge;
return action->priv->edge;
}
/**
@ -1397,21 +1314,17 @@ clutter_gesture_action_set_threshold_trigger_distance (ClutterGestureAction
float x,
float y)
{
ClutterGestureActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
priv = clutter_gesture_action_get_instance_private (action);
if (fabsf (x - priv->distance_x) > FLOAT_EPSILON)
if (fabsf (x - action->priv->distance_x) > FLOAT_EPSILON)
{
priv->distance_x = x;
action->priv->distance_x = x;
g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_X]);
}
if (fabsf (y - priv->distance_y) > FLOAT_EPSILON)
if (fabsf (y - action->priv->distance_y) > FLOAT_EPSILON)
{
priv->distance_y = y;
action->priv->distance_y = y;
g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_Y]);
}
}
@ -1432,23 +1345,19 @@ clutter_gesture_action_get_threshold_trigger_distance (ClutterGestureAction *act
float *x,
float *y)
{
ClutterGestureActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
priv = clutter_gesture_action_get_instance_private (action);
if (x != NULL)
{
if (priv->distance_x > 0.0)
*x = priv->distance_x;
if (action->priv->distance_x > 0.0)
*x = action->priv->distance_x;
else
*x = gesture_get_default_threshold ();
}
if (y != NULL)
{
if (priv->distance_y > 0.0)
*y = priv->distance_y;
if (action->priv->distance_y > 0.0)
*y = action->priv->distance_y;
else
*y = gesture_get_default_threshold ();
}

View File

@ -34,13 +34,32 @@
G_BEGIN_DECLS
#define CLUTTER_TYPE_GESTURE_ACTION (clutter_gesture_action_get_type ())
#define CLUTTER_TYPE_GESTURE_ACTION (clutter_gesture_action_get_type ())
#define CLUTTER_GESTURE_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_GESTURE_ACTION, ClutterGestureAction))
#define CLUTTER_IS_GESTURE_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_GESTURE_ACTION))
#define CLUTTER_GESTURE_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_GESTURE_ACTION, ClutterGestureActionClass))
#define CLUTTER_IS_GESTURE_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_GESTURE_ACTION))
#define CLUTTER_GESTURE_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_GESTURE_ACTION, ClutterGestureActionClass))
CLUTTER_EXPORT
G_DECLARE_DERIVABLE_TYPE (ClutterGestureAction, clutter_gesture_action,
CLUTTER, GESTURE_ACTION, ClutterAction);
typedef struct _ClutterGestureAction ClutterGestureAction;
typedef struct _ClutterGestureActionPrivate ClutterGestureActionPrivate;
typedef struct _ClutterGestureActionClass ClutterGestureActionClass;
typedef struct _ClutterGestureActionPrivate ClutterGestureActionPrivate;
/**
* ClutterGestureAction:
*
* The #ClutterGestureAction structure contains
* only private data and should be accessed using the provided API
*
* Since: 1.8
*/
struct _ClutterGestureAction
{
/*< private >*/
ClutterAction parent_instance;
ClutterGestureActionPrivate *priv;
};
/**
* ClutterGestureActionClass:
@ -82,6 +101,9 @@ struct _ClutterGestureActionClass
void (* _clutter_gesture_action6) (void);
};
CLUTTER_EXPORT
GType clutter_gesture_action_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterAction * clutter_gesture_action_new (void);

View File

@ -1,130 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
*
* Copyright (C) 2019 Endless, Inc
* Copyright (C) 2009, 2010 Intel Corp
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "clutter-build-config.h"
#include "clutter-graphene.h"
#include "clutter-private.h"
#include "clutter-types.h"
static gboolean
graphene_matrix_progress (const GValue *a,
const GValue *b,
double progress,
GValue *retval)
{
const graphene_matrix_t *am = g_value_get_boxed (a);
const graphene_matrix_t *bm = g_value_get_boxed (b);
graphene_matrix_t res;
graphene_matrix_interpolate (am, bm, progress, &res);
g_value_set_boxed (retval, &res);
return TRUE;
}
static gboolean
graphene_point_progress (const GValue *a,
const GValue *b,
double progress,
GValue *retval)
{
const graphene_point_t *ap = g_value_get_boxed (a);
const graphene_point_t *bp = g_value_get_boxed (b);
graphene_point_t res;
graphene_point_interpolate (ap, bp, progress, &res);
g_value_set_boxed (retval, &res);
return TRUE;
}
static gboolean
graphene_point3d_progress (const GValue *a,
const GValue *b,
double progress,
GValue *retval)
{
const graphene_point3d_t *av = g_value_get_boxed (a);
const graphene_point3d_t *bv = g_value_get_boxed (b);
graphene_point3d_t res;
graphene_point3d_interpolate (av, bv, progress, &res);
g_value_set_boxed (retval, &res);
return TRUE;
}
static gboolean
graphene_rect_progress (const GValue *a,
const GValue *b,
double progress,
GValue *retval)
{
const graphene_rect_t *rect_a = g_value_get_boxed (a);
const graphene_rect_t *rect_b = g_value_get_boxed (b);
graphene_rect_t res;
graphene_rect_interpolate (rect_a, rect_b, progress, &res);
g_value_set_boxed (retval, &res);
return TRUE;
}
static gboolean
graphene_size_progress (const GValue *a,
const GValue *b,
double progress,
GValue *retval)
{
const graphene_size_t *as = g_value_get_boxed (a);
const graphene_size_t *bs = g_value_get_boxed (b);
graphene_size_t res;
graphene_size_interpolate (as, bs, progress, &res);
g_value_set_boxed (retval, &res);
return TRUE;
}
void
clutter_graphene_init (void)
{
clutter_interval_register_progress_func (GRAPHENE_TYPE_MATRIX,
graphene_matrix_progress);
clutter_interval_register_progress_func (GRAPHENE_TYPE_POINT,
graphene_point_progress);
clutter_interval_register_progress_func (GRAPHENE_TYPE_POINT3D,
graphene_point3d_progress);
clutter_interval_register_progress_func (GRAPHENE_TYPE_RECT,
graphene_rect_progress);
clutter_interval_register_progress_func (GRAPHENE_TYPE_SIZE,
graphene_size_progress);
}

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